Search code examples
javascriptnode.jsrandomgambling

random numbers with weights in an array


I want to be able to create an array of random numbers similar to the results of a slot machine. I know how to pull random numbers but i want to weight the entire result.

So for example in the below code, i would want to only allow row2 to return [6,6,6] 1 in 10000 times.

The problem I am having is I can create a function that wont display 6 except for once in 10000 but thats not what i want. I want to display it in the rows but just dont want that specific result except once in 10000 spins.

I would want to set different odds for all the winning sets. Any advice?

here is my code so far:

var row1 = [0, 0, 0];
var row2 = [0, 0, 0];
var row3 = [0, 0, 0];

var bar1 = 1;
var bar2 = 2;
var bar3 = 3;
var cherry = 4;
var seven = 5;
var diamond = 6;

var balance = 100;
function loadBalance(buyIn) {
  return (balance += buyIn);
}

var reelArray = [1, 2, 3, 4, 5, 6];

function randomChoice(arr) {
  const randIndex = Math.floor(Math.random() * arr.length);
  return arr[randIndex];
}



function spin() {
  for (j = 0; j <= 2; j++) {
    row1[j] = randomChoice(reelArray);
    row2[j] = randomChoice(reelArray);
    row3[j] = randomChoice(reelArray);
  }

  console.log(`${row1}\n${row2}\n${row3}`);
}

function play() {
  spin();
  checkWinner();
}

function checkWinner() {
  if (row2[0] != row2[1]) {
    console.log("you lost");
    balance = balance - 1;
    console.log(`bal: `, balance);
    return balance;
  } else if (row2[1] != row2[2]) {
    console.log("you lost");
    balance = balance - 1;
    console.log(`bal: `, balance);
    return balance;
  } else {
    console.log("you won!");
    switch (row2[0]) {
      case 1:
        balance = balance + 20;
        console.log(`bal: `, balance);
        break;
      case 2:
        balance = balance + 40;
        console.log(`bal: `, balance);
        break;
      case 3:
        balance = balance + 80;
        console.log(`bal: `, balance);
        break;
      case 4:
        balance = balance + 20;
        console.log(`bal: `, balance);
        break;
      case 5:
        balance = balance + 200;
        console.log(`bal: `, balance);
        break;
      case 6:
        balance = balance + 1000;
        console.log(`bal: `, balance);
        break;
      default:
        break;
    }
  }
  return;
}

function runIt() {
  for (i = 0; i <= 100; i++) {
    play();
  }
}

runIt();


Solution

  • To change the odds for specific results?

    You could check for those specific scores, and then do an extra randomized check.

    Below is a snippet that simulates and counts such method.

    It doesn't garantee that the rigged results gets picked every 1 out of N times exactly.
    But they'll get lower odds to occur.

    An alternative could be to store an object with counters for the rigged results. And then only recurse when the counter of such rigged result is still below it's limit. And reset it's counter when it was allowed to pass. But a gambler that knows that this method is used could just wait for other gamblers to waste their gambles & rage quit. Then take over just before it's near that limit. Thus increasing his odds to win.

    const reelWords = ['bar1', 'bar2', 'bar3', 'cherry', 'seven', 'diamond'];
    const riggedOdds = { 111: 100, 222: 200, 333: 300, 444: 400, 555: 500, 666: 10000 };
    const winningcombos = [111, 222, 333, 444, 555, 666];
    
    function getRandomReel(elementLimit) {     
      let N = (elementLimit < 2) ? 2 : elementLimit;
      if(N > reelWords.length) N = reelWords.length;
    
      let arrNums = [];
      let arrWords = [];
    
      while(arrNums.length < 3){
        let idx = Math.floor(Math.random() * N); // random 0 to N-1
        arrNums.push(idx+1);
        arrWords.push(reelWords[idx]);
      }
    
      let arrCombo = Number(arrNums.join(''));
      if(arrCombo in riggedOdds){
          let riggedOdd = riggedOdds[arrCombo];
          let newOdd = Math.floor(riggedOdd/(N*N*N));
          let n = Math.floor(Math.random()*(newOdd+1));
          //console.log('combo:'+ arrCombo +', rigged:'+ riggedOdd +', new odd:'+ newOdd +', n:'+ n);
          if(n > 0) {
              return getRandomReel(N); // recurse
          }
      }
      return {"combo": arrCombo, "words": arrWords };
    }
    
    function printDictAsTable(dict){
       let htmlstr = "<table border=1><tr><th>Number</th><th>Count</th></tr>";
       
       let sortedKeys = Object.keys(dict).sort(function(a,b){return b-a});
    
       for (let i=0; i<sortedKeys.length; i++) {
         let key = sortedKeys[i];
         htmlstr += "<tr><td>"+ key +" </td><td>" + dict[key] + " </td></tr>";
       }
       htmlstr += "</table>";
       document.getElementById("resultContainer").innerHTML = htmlstr;
    }
    
    function loopRiggedOneArmedBanditSimulationAndPrint(){
        let elementLimit = Number(document.getElementById("elementLimit").value);
        let loopTotal = Number(document.getElementById("loopLimit").value);
        let dict = {};
        
        for(let i = 0; i < loopTotal; i++){
            let reel = getRandomReel(elementLimit);
            let combo = reel.combo;
            dict[combo] = dict[combo] ? dict[combo] + 1 : 1;
        }
        
        printDictAsTable(dict);
    }
    
    function GambleAndPrint() {
       let elementLimit = reelWords.length;
       document.getElementById("rangeInput").value = elementLimit ;
       document.getElementById("elementLimit").value = elementLimit;
       let htmlstr = "<table border=1>";
       for(let i = 0; i < 3; i++){
          let reel = getRandomReel(elementLimit);
          let arr = reel.words;
          let winorlose = (winningcombos.indexOf(reel.combo) > -1) ? 'won' : '...';
          htmlstr += "<tr><td>"+arr[0]+"</td><td>"+arr[1]+"</td><td>"+arr[2]+"</td><td>"+ winorlose +"</td></tr>";
       }
       htmlstr += "</table>";
       document.getElementById("resultContainer").innerHTML = htmlstr;
    }
    
    loopRiggedOneArmedBanditSimulationAndPrint();
    <div id="topContainer">
    <div id="inputAndButton" style="float: left;">
    <p>Elements : 
      <input type="number" id="elementLimit" value=2 readonly><br/>
      <input type="range" id="rangeInput" min=2 max=6 value=2 onchange="document.getElementById('elementLimit').value=this.value;">
     </p>
    <p>Loops: <input type="number" id="loopLimit" value=10000></p>
    <p><button type="button" onclick="loopRiggedOneArmedBanditSimulationAndPrint()">
        Loop and Count Simulation
    </button>
    <button type="button" onclick="GambleAndPrint()">
        Gamble
    </button>
    </p>
    </div>
    <div id="resultContainer" style="float: right;"></div>
    </div>