Add docstrings and doctests to pbot.py + Python cleanups.
[poker.git] / pbot.py
diff --git a/pbot.py b/pbot.py
new file mode 100755 (executable)
index 0000000..af7a3fb
--- /dev/null
+++ b/pbot.py
@@ -0,0 +1,73 @@
+#!/usr/bin/python
+
+"""Run a poker championship.
+"""
+
+from table import Player, Blinds, Table
+from deck import DECK
+
+
+def run(players, blinds, start_stack, hand_limit, tournaments, verbose=False):
+    for n in xrange(tournaments):
+        for player in players:
+            player.cash = start_stack
+        table = Table(deck=DECK, players=players, blinds=blinds,
+                      verbose=verbose)
+        while len(table.players) > 1 and table.hand_count < hand_limit:
+            table.play_round()
+            # keep bots up to date, so they can think in parallel
+            for player in players:
+                if player.brain:
+                    player.log_flush(table.log)
+        if len(table.players) == 1:
+            print "INFO WINNER: Player %s" % table.players[0]
+        else:
+            assert table.hand_count >= hand_limit
+            print "INFO Time expired"
+            for player in table.players:
+                print "INFO Tie: Player %s" % player
+
+
+if __name__ == '__main__':
+    from optparse import OptionParser
+
+    usage = '%prog [options] PLAYER PLAYER ...'
+    epilog = ('`PLAYER`s should be name,brain tuples, e.g. (`a,p1.py`).  '
+              'Give just the name for a human playing from the command line.')
+    p = OptionParser(usage=usage, epilog=epilog)
+    p.add_option('-s', '--start-stack', dest='stack', default=1000,
+                 type='int', help='start stack (%default)')
+    p.add_option('-b', '--blinds', dest='blinds',
+                 default='1,2,4,8,16,25,37,50',
+                 help='blind schedule (%default)')
+    p.add_option('-c', '--hand-clock', dest='clock', default=20, type='int',
+                 help='hands between blind increments (%default)')
+    p.add_option('-l', '--hand-limit', dest='limit', default=5000, type='int',
+                 help='hand limit (-1 for unlimited play, %default')
+    p.add_option('-t', '--tournaments', dest='tournaments', default=1,
+                 type='int', help='number of tournaments (%default)')
+    p.add_option('-v', '--verbose', dest='verbose', action='store_true',
+                 help='print the log as it is written')
+
+    options,args = p.parse_args()
+
+    blinds = Blinds(blinds=[int(x) for x in options.blinds.split(',')],
+                    hand_clock=options.clock)
+
+    players = []
+    for arg in args:
+        fields = [x.strip() for x in arg.rsplit(',', 1)]
+        name = fields[0]
+        if len(fields) == 1:
+            brain = None
+        else:
+            brain = fields[1]
+        players.append(Player(name=name, brain=brain))
+
+    try:
+        run(players=players, blinds=blinds, start_stack=options.stack,
+            hand_limit=options.limit, tournaments=options.tournaments,
+            verbose=options.verbose)
+    finally:  # kill the bots
+        for p in players:
+            p.kill()