Skip to content

Instantly share code, notes, and snippets.

@mickelsonm
Created November 14, 2015 04:44
Show Gist options
  • Save mickelsonm/5c9eee61cfc7137c3bcb to your computer and use it in GitHub Desktop.
Save mickelsonm/5c9eee61cfc7137c3bcb to your computer and use it in GitHub Desktop.
Roulette Simulator
<?php
class Table {
protected $bets = [];
protected $numbers = [
0 => ['color' => 'green'],
1 => ['color' => 'red'],
2 => ['color' => 'black'],
3 => ['color' => 'red'],
4 => ['color' => 'black'],
5 => ['color' => 'red'],
6 => ['color' => 'black'],
7 => ['color' => 'red'],
8 => ['color' => 'black'],
9 => ['color' => 'red'],
10 => ['color' => 'black'],
11 => ['color' => 'black'],
12 => ['color' => 'red'],
13 => ['color' => 'black'],
14 => ['color' => 'red'],
15 => ['color' => 'black'],
16 => ['color' => 'red'],
17 => ['color' => 'black'],
18 => ['color' => 'red'],
19 => ['color' => 'red'],
20 => ['color' => 'black'],
21 => ['color' => 'red'],
22 => ['color' => 'black'],
23 => ['color' => 'red'],
24 => ['color' => 'black'],
25 => ['color' => 'red'],
26 => ['color' => 'black'],
27 => ['color' => 'red'],
28 => ['color' => 'black'],
29 => ['color' => 'black'],
30 => ['color' => 'red'],
31 => ['color' => 'black'],
32 => ['color' => 'red'],
33 => ['color' => 'black'],
34 => ['color' => 'red'],
35 => ['color' => 'black'],
36 => ['color' => 'red'],
];
protected $lastNumber = -1;
public function spin() {
$this->lastNumber = mt_rand(0, 36);
return $this->lastNumber;
}
public function addBet(Bet $bet) {
$this->bets[] = $bet;
}
public function getBets() {
return $this->bets;
}
public function removeBets() {
$this->bets = [];
}
public function getNumberAttributes($number) {
return $this->numbers[$number];
}
public function getLastNumber() {
return $this->lastNumber;
}
}
class Bet {
const BET_NUMBER = 'number',
BET_COLOR = 'color';
protected $player;
protected $type;
protected $params;
protected $amount;
public function __construct(Player $player, $type, $params, $amount) {
$this->player = $player;
$this->type = $type;
$this->params = $params;
$this->amount = $amount;
}
public function getType() {
return $this->type;
}
public function getAmount() {
return $this->amount;
}
public function getParams() {
return $this->params;
}
public function getPlayer() {
return $this->player;
}
}
abstract class Player {
protected $name;
protected $cash = 0;
protected $lastBet;
protected $lastBetWon;
protected static $baseCash = 100;
public function __construct($name, $cash) {
$this->name = $name;
$this->addCash($cash);
}
public function resetCash() {
$this->cash = self::$baseCash;
}
public function getCash() {
return $this->cash;
}
public function addCash($amount) {
$this->cash += $amount;
}
public function bet(Table $table) {
$bet = $this->getBet($table);
if ($bet->getAmount() > $this->cash) {
return false;
}
$this->cash -= $bet->getAmount();
$this->lastBet = $bet;
$table->addBet($bet);
}
public function setLastBetWon($win) {
$this->lastBetWon = $win;
}
/**
*
* @param Table $table
* @return Bet
*/
public abstract function getBet(Table $table);
public function getName() {
return $this->name;
}
public function __toString() {
return 'Player [' . $this->name . "]: " . '$' . $this->cash . '';
}
}
class Croupier {
public function handleRound(Table $table) {
$bets = $table->getBets();
$number = $table->spin();
foreach ($bets as $bet) {
/* @var $bet Bet */
if ($this->betWins($table, $bet, $number)) {
$bet->getPlayer()->setLastBetWon(true);
$bet->getPlayer()->addCash($this->getReturn($bet));
}
}
$table->removeBets();
}
public function getReturn(Bet $bet) {
switch ($bet->getType()) {
case Bet::BET_COLOR:
return $bet->getAmount() * 2;
break;
case Bet::BET_NUMBER:
return $bet->getAmount() * 36;
break;
default:
return 0;
}
}
public function betWins(Table $table, Bet $bet, $number) {
$params = $bet->getParams();
$attr = $table->getNumberAttributes($number);
switch ($bet->getType()) {
case Bet::BET_NUMBER:
return $number === $params['number'];
case Bet::BET_COLOR:
return $params['color'] === $attr['color'];
default:
return false;
}
}
}
class Simulator {
protected $players = [];
protected $croupier;
protected $table;
protected $playerOutcomes = [];
public function __construct(Croupier $croupier, Table $table) {
$this->croupier = $croupier;
$this->table = $table;
}
public function addPlayer(Player $player) {
$this->players[] = $player;
$this->playerOutcomes[$player->getName()] = 0;
}
public function runSimulation($games = 100000, $rounds = 20) {
for ($game = 0; $game < $games; $game++) {
foreach ($this->players as $player) {
/* @var $player Player */
$player->resetCash();
$startCash = $player->getCash();
for ($round = 0; $round < $rounds; $round++) {
$player->bet($this->table);
$this->croupier->handleRound($this->table);
}
$win = $player->getCash() - $startCash;
$this->playerOutcomes[$player->getName()] += $win;
}
}
foreach ($this->playerOutcomes as $player => $outcome) {
echo 'Player [' . $player . ']: ' . $outcome / $games . "\r\n";
}
}
}
class ColorPlayer extends Player {
public function getBet(Table $table) {
$nextColor = 'red';
$nextAmount = 2;
if ($this->lastBetWon === false) {
$nextAmount *= 2;
$lastNumber = $table->getLastNumber();
$attr = $table->getNumberAttributes($lastNumber);
if ($attr['color'] === 'red') {
$nextColor = 'black';
}
}
return new Bet($this, Bet::BET_COLOR, ['color' => $nextColor], $nextAmount);
}
}
class LastNumberPlayer extends Player {
public function getBet(Table $table) {
$nextNumber = $table->getLastNumber() > -1 ? $table->getLastNumber() : 1;
return new Bet($this, Bet::BET_NUMBER, ['number' => $nextNumber], 2);
}
}
class RandomNumberPlayer extends Player {
public function getBet(Table $table) {
return new Bet($this, Bet::BET_NUMBER, ['number' => mt_rand(0, 36)], 2);
}
}
class RandomColorPlayer extends Player {
protected $colors = ['red', 'black'];
public function getBet(Table $table) {
return new Bet($this, Bet::BET_COLOR, ['color' => $this->colors[mt_rand(0, 1)]], 2);
}
}
class SingleNumberPlayer extends Player {
protected $number = 1;
public function setNumber($number) {
$this->number = $number;
}
public function getBet(Table $table) {
return new Bet($this, Bet::BET_NUMBER, ['number' => $this->number], 2);
}
}
$sim = new Simulator(new Croupier(), new Table());
$sim->addPlayer(new ColorPlayer('Color', 50));
$sim->addPlayer(new LastNumberPlayer('Number', 50));
$singleNumber = new SingleNumberPlayer('SingleNumber', 50);
$singleNumber->setNumber(0);
$sim->addPlayer($singleNumber);
$sim->addPlayer(new RandomColorPlayer('RandomColor', 50));
$sim->addPlayer(new RandomNumberPlayer('RandomNumber', 50));
$sim->runSimulation();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment