Skip to content
Spencer edited this page Aug 24, 2015 · 21 revisions

Machine Poker Guide

Building your bot

Bots are written in Javascript, and simply need to export a 'play' function (CommonJS style)

Example: At it's simplest, a bot should return an integer as your bet. Bets are essentially what's getting added to the pot. You can think about it as throwing new chips into the pot.

exports.name = "Fold'em Steve";
// I just check/fold
exports.play = function(game) {
  if(game.state !== "complete") {
    return 0;
  }
};
// I just call everything!
exports.name = "Call'em Paul";
exports.play = function(game) {
  if(game.state !== "complete") {
    return game.betting.call;
  }
};

Game object

You should expect to be passed a game object which contains all the relevant information you need to make a decision, including:

  • game state ('pre-flop','flop', 'river', 'turn')
  • players and their actions
  • your own information (including your cards)
  • betting options available

Here's an example of a game object at the start of betting after the flop.

{ community: [ '2c', 'Qh', 'Jc' ],
  state: 'flop',
  hand: 1,
  betting: { call: 0, raise: 10, canRaise: true },
  self:
   { name: 'Me',
     blind: 5,
     ante: 0,
     wagered: 10,
     state: 'active',
     chips: 990,
     actions: { 'pre-flop': [ { type: 'call', bet: 5 } ] },
     cards: [ 'Qd', '8h' ],
     position: 0,
     brain: {} },
  players:
   [ { name: 'Me',
       blind: 5,
       ante: 0,
       wagered: 10,
       state: 'active',
       chips: 990,
       actions: { 'pre-flop': [ { type: 'call', bet: 5 } ] } },
     { name: 'CallBot #1',
       blind: 10,
       ante: 0,
       wagered: 10,
       state: 'active',
       chips: 990,
       actions: { 'pre-flop': [ { type: 'check' } ] } },
     { name: 'CallBot #2',
       blind: 0,
       ante: 0,
       wagered: 10,
       state: 'active',
       chips: 990,
       actions: { 'pre-flop': [ { type: 'call', bet: 10 } ] } },
     { name: 'FoldBot #1',
       blind: 0,
       ante: 0,
       wagered: 0,
       state: 'folded',
       chips: 1000,
       actions: { 'pre-flop': [ { type: 'fold' } ] } } ] }

Betting

Your play function should simply return a integer of the amount you wish to bet. This bet is in ADDITION to the amount you've already wagered.

For example, lets say you've wagered $10 so far, and are presented with the following betting state.

{ community: [ 'Kh', '7c', '2c' ],
  state: 'flop',
  hand: 1,
  betting: { call: 10, raise: 20, canRaise: true },
  self:
   { name: 'Me',
     blind: 5,
     ante: 0,
     wagered: 10,
     state: 'active',
     chips: 990,
     actions: { 'pre-flop': [ { type: 'call', bet: 5 } ] },
     cards: [ '6s', 'Qh' ],
     position: 0,
  // Concatenated for brevity
  • A bet of 0 will result in a fold, because you need to bet 10 in order to stay in the game.
  • A bet of 10 will result in a call.
  • You can also bet 20 or more in order to raise. If you've already raised and there have been no subsequent raises, you won't be able to raise again and the canRaise flag will be set to false

What happens if I return an invalid amount?

Your brain

Your program won't hold any state. Any variables you set will be lost after it's run. In order to let you save information between bets, we're giving you a brain. You brain can store up to 4k (4096) of data, and will be available to you in every call of your function.

You can find your brain under self.brain on the game object. Any property you create on the brain will automatically be saved.

Example brain usage:

exports.play = function(game) {
  if(!game.self.brain.totalBets){game.self.brain.totalBets = 0} //initialize
  if(game.state !== "complete") {
    var bet = game.betting.call;
    // This would be a total of every bet made
    // throughout all the hands played
    game.self.brain.totalBets += bet;
    return bet;
  }
};

Brain size is measured using JSON.stringify(brain).length If you exceed 4096, your brain will be reset to {} and you'll forget everything!

What happens when the game ends?

When a game finishes your play function will be called with a game object in the 'complete' state.

This allows you to evaluate your competitors actions and win data for future use (storing your learnings in your brain)

Here's and example of a completed game object

Debugging

Even though you're being run in a sandbox, I've added the ability to log data out to the terminal directly from your bot using console.log

console.log(game.self);

Limitations

Timeouts

You bot must respond in 1000ms (1 second) when the 'play' function is called. Otherwise it will be stopped and a bet of 0 will be entered.

More data about the contest hardware is forthcoming.

Size Limits

Bots are limited to a size of 16k (16384) or less. You can certainly use a javascript packer to help meet this requirement.

On unix based systems you can find your bots byte size using

wc -c bot.js

Javascript limitations

Running in the NodeJS VM means your Javascript bot will be more limited than normal. Most importantly you won't have control of the event loop. This means your bot must run to completion at each hand; you won't have access to setTimeout, setInterval to continue the program after you've made a bet.