Skip to content

Instantly share code, notes, and snippets.

@Restuta
Last active June 17, 2017 11:43
Show Gist options
  • Save Restuta/4c4ddb525898a6534db7d913e535460b to your computer and use it in GitHub Desktop.
Save Restuta/4c4ddb525898a6534db7d913e535460b to your computer and use it in GitHub Desktop.
Gamblers Fallacy
/*
Models flip-a-coin game with variative chance of "heads" and "tails". Chance depends on betWinPayoutRatio.
For 2 it's 50% like you wold expect and for 10 it's 1/10th
Once you copy paste this code to Chrome's console, run
main({
gamesToPlay: 100,
timesToPlayEachGame: 1000000,
chainLenghtToWaitFor: 5,
betWinPayoutRatio: 10,
})
and tweak self-explanatory parametrs
The most interesting one is "chainLenghtToWaitFor" which represents how long a player should wait for a give number of tails in a row
before placing a bet to heads. For 5 a player would wait for 5 tails in a row and only then place a bet on heads.
starting money for each player is 1000
each bet is equal to 1
I CHALLANGE YOU to find parameters where avgMoneyLeft doubles =)
*/
function main({
gamesToPlay = 10,
timesToPlayEachGame = 10,
chainLenghtToWaitFor = 5,
betWinPayoutRatio = 2
}) {
console.clear()
const log = console.log
log(...arguments)
function rnd(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
// const flipCoin = () => (Math.random() >= 0.5 ? 'heads' : 'tails')
const flipCoin = () => (rnd(1, betWinPayoutRatio) === 1 ? 'tails' : 'heads')
const winningBet = coinSide => (coinSide === 'tails')
class Player {
constructor({startingMoney, winGoal}) {
this.money = startingMoney
this.betsPlaced = 0
this.betPlaced = false
this.betAmount = 0
this.winGoalAchived = false
}
placeBet(betAmount) {
const remainingMoney = this.money - betAmount
this.betPlaced = true
this.betsPlaced++
this.betAmount = betAmount
this.money -= betAmount
}
collectWinnings({payoutRatio}) {
this.money += (this.betAmount * payoutRatio)
this.betPlaced = false
this.betAmount = 0
if (this.money >= this.winGoal) {
this.winGoalAchieved = true
log(`Win goal achieved, player's balance: ${this.money}`)
}
}
feelDisappointed() {
this.betPlaced = false
this.betAmount = 0
}
}
function playAGame({sameSideChainLength = 5, timesToPlay = 1000}) {
let headsInARow = 0
let previousFlipWasHeads = false
const player = new Player({startingMoney: 1000, winGoal: 2000})
for(let i = 0; i < timesToPlay; i++) {
let coinSide = flipCoin()
if (player.betPlaced) {
if (winningBet(coinSide)) {
player.collectWinnings({payoutRatio: betWinPayoutRatio})
// log('collected winnings')
} else {
player.feelDisappointed()
}
}
if (coinSide === 'heads') {
if (previousFlipWasHeads) {
headsInARow++
} else {
headsInARow = 1
}
previousFlipWasHeads = true
} else {
previousFlipWasHeads = false
headsInARow = 0
}
if (headsInARow === sameSideChainLength) {
player.placeBet(1)
}
}
// log(player.money)
// log(`Bets placed: ${player.betsPlaced}`)
return {
moneyLeft: player.money,
betsPlaced: player.betsPlaced
}
}
const game = () => playAGame({sameSideChainLength: chainLenghtToWaitFor, timesToPlay: timesToPlayEachGame})
const playGameNTimes = (game, times) => {
let results = []
for (let i = 0; i < times; i++) {
results.push(game())
}
return results
}
const gamesResults = playGameNTimes(game, gamesToPlay)
const stats = gamesResults
.reduce((a, b) => {
a.moneyLeft += b.moneyLeft
a.betsPlaced += b.betsPlaced
return a
}, {moneyLeft: 0, betsPlaced: 0})
log('--- last N games results ---')
gamesResults.slice(gamesToPlay - 10).map(x => {
log(x)
return x
})
log('Total bankrupt players: ')
log(gamesResults.filter(x => x.moneyLeft < 0).length)
console.info({
avgMoneyLeft: stats.moneyLeft / gamesToPlay,
avgBetsPlaced: stats.betsPlaced / gamesToPlay
})
//1234
}
main({
gamesToPlay: 100,
timesToPlayEachGame: 1000000,
chainLenghtToWaitFor: 5,
betWinPayoutRatio: 10,
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment