binions
Version:
A Javascript Poker game engine
320 lines (289 loc) • 9.27 kB
JavaScript
// Generated by CoffeeScript 1.3.3
(function() {
var Deck, EventEmitter, Game, Hand, Player, utils,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
EventEmitter = require('events').EventEmitter;
Deck = require('hoyle').Deck;
Hand = require('hoyle').Hand;
Player = require('./player').Player;
utils = require('util');
Game = exports.Game = (function(_super) {
__extends(Game, _super);
Game.STATUS = {
NORMAL: 0,
PRIVILEGED: 1
};
function Game(players, betting, hand) {
var i, player, _i, _len, _ref;
this.hand = hand || 1;
this.Betting = betting;
this.players = players.filter(function(p) {
return p.chips > 0;
});
if (this.players.length < 2) {
throw "Not enough players";
}
if (this.players.length > 22) {
throw "You can't have more that 22 players. I don't have that many cards";
}
_ref = this.players;
for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
player = _ref[i];
player.position = i;
}
this.state = null;
this.reset();
}
Game.prototype.reset = function() {
var player, _i, _len, _ref;
_ref = this.players;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
player = _ref[_i];
player.reset();
}
this.deck = new Deck();
this.community = [];
this.burn = [];
return this.winners = [];
};
Game.prototype.run = function() {
var _this = this;
this.emit('roundStart');
this.deck.shuffle();
this.deck.once('shuffled', function() {
_this.deal();
return _this.takeBets();
});
return this.on('roundComplete', function() {
if (_this.deal()) {
return _this.takeBets();
} else {
return _this.settle();
}
});
};
Game.prototype.takeBets = function(betting, cb) {
var betOptions, status,
_this = this;
betting || (betting = new this.Betting(this.players, this.state));
betOptions = betting.analyze();
if (betOptions) {
status = this.status(Game.STATUS.NORMAL, betting.nextToAct, betOptions);
return betting.nextToAct.update(status, function(err, res) {
if (err) {
_this.emit("bettingError", err, betting.nextToAct);
}
betting.bet(res || 0, null, err);
return _this.takeBets(betting);
});
} else {
this.emit("roundComplete", this.state);
return typeof cb === "function" ? cb() : void 0;
}
};
Game.prototype.takeBlinds = function() {
return new this.Betting(this.players, this.state).takeBlinds();
};
Game.prototype.deal = function() {
var retval;
if (this.activePlayers().length <= 1 && this.state !== null) {
return false;
}
retval = true;
switch (this.state) {
case null:
this.preFlop();
break;
case 'pre-flop':
this.flop();
break;
case 'flop':
this.turn();
break;
case 'turn':
this.river();
break;
case 'river':
case 'final':
this.state = 'final';
retval = false;
}
this.emit('stateChange', this.state);
return retval;
};
Game.prototype.preFlop = function() {
var player, _i, _j, _len, _len1, _ref, _ref1, _results;
this.takeBlinds();
this.state = 'pre-flop';
_ref = this.players;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
player = _ref[_i];
player.cards.push(this.deck.deal());
}
_ref1 = this.players;
_results = [];
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
player = _ref1[_j];
_results.push(player.cards.push(this.deck.deal()));
}
return _results;
};
Game.prototype.flop = function() {
this.state = 'flop';
this.burn.push(this.deck.deal());
this.community.push(this.deck.deal(), this.deck.deal(), this.deck.deal());
return true;
};
Game.prototype.turn = function() {
this.state = 'turn';
this.burn.push(this.deck.deal());
return this.community.push(this.deck.deal());
};
Game.prototype.river = function() {
this.state = 'river';
this.burn.push(this.deck.deal());
return this.community.push(this.deck.deal());
};
Game.prototype.status = function(level, player, betOptions) {
var playerLevel, s, _i, _len, _ref;
s = {};
s.community = this.community.map(function(c) {
return c.toString();
});
s.state = this.state;
s.hand = this.hand;
s.betting = betOptions || null;
if (this.winners && this.winners.length > 0) {
s.winners = this.winners;
}
if (level === Game.STATUS.PRIVILEGED) {
s.deck = this.deck;
s.burn = this.burn;
}
if (player) {
s.self = player.status(Player.STATUS.PRIVILEGED);
s.self.position = this.players.indexOf(player);
}
s.players = [];
_ref = this.players;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
player = _ref[_i];
playerLevel = this.state === 'complete' ? Player.STATUS.FINAL : Player.STATUS.PUBLIC;
if (level === Game.STATUS.PRIVILEGED) {
playerLevel = Player.STATUS.PRIVILEGED;
}
s.players.push(player.status(playerLevel));
}
return s;
};
Game.prototype.distributeWinnings = function(winners) {
if (winners.length > 1) {
return this.splitPot(winners);
} else {
return this.payout(winners[0], this.take(winners[0].wagered));
}
};
Game.prototype.splitPot = function(winners) {
var each, i, leftover, lowest, total, winner, _i, _len, _results;
lowest = Math.min.apply(Math, winners.map(function(w) {
return w.wagered;
}));
total = this.take(lowest);
each = Math.floor(total / winners.length);
leftover = total - each * winners.length;
_results = [];
for (i = _i = 0, _len = winners.length; _i < _len; i = ++_i) {
winner = winners[i];
if (i === 0) {
_results.push(this.payout(winner, each + leftover));
} else {
_results.push(this.payout(winner, each));
}
}
return _results;
};
Game.prototype.take = function(amount) {
var player, total, _i, _len, _ref;
total = 0;
_ref = this.players;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
player = _ref[_i];
if (amount > player.wagered) {
total = total + player.wagered;
player.payout = player.payout - player.wagered;
player.wagered = 0;
} else {
total = total + amount;
player.payout = player.payout - amount;
player.wagered = player.wagered - amount;
}
}
return total;
};
Game.prototype.payout = function(winner, amount) {
this.winners.push({
position: winner.position,
amount: amount
});
winner.payout = winner.payout + amount;
return winner.chips = amount + winner.chips;
};
Game.prototype.pot = function() {
var player, t, _i, _len, _ref;
t = 0;
_ref = this.players;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
player = _ref[_i];
t = t + player.wagered;
}
return t;
};
Game.prototype.activePlayers = function() {
var calls;
calls = this.players.filter(function(p) {
return p.inPlay();
});
return calls;
};
Game.prototype.notifyPlayers = function(callback, index) {
var player,
_this = this;
index || (index = 0);
player = this.players[index];
if (player) {
return player.update(this.status(Game.STATUS.FINAL, player), function() {
return _this.notifyPlayers(callback, index + 1);
});
} else {
return callback();
}
};
Game.prototype.settle = function() {
var hands, inPlay, winners, winningHands,
_this = this;
this.state = 'complete';
inPlay = this.activePlayers();
while (inPlay.length >= 1) {
if (inPlay.length === 1) {
this.distributeWinnings(inPlay);
break;
} else {
hands = inPlay.map(function(p) {
return p.makeHand(_this.community);
});
winningHands = Hand.pickWinners(hands);
winners = inPlay.filter(function(p) {
return winningHands.indexOf(p.hand) >= 0;
});
this.distributeWinnings(winners);
inPlay = this.activePlayers();
}
}
return this.notifyPlayers(function() {
return _this.emit('complete');
});
};
return Game;
})(EventEmitter);
}).call(this);