Samplebot

From WarfishWiki

Jump to: navigation, search

[edit] Introduction

The first thing you may want to do is to invite "samplebot@warfish.net" to a game of Warfish to get a feel for what the working bot looks like. Samplebot turns out to be kinda handy when testing game board designs as well.

This page describes how to make a bot using the XML/JSON Apis and provides the complete listing (implemented as a mod_python script) for a working bot that demonstrates the various apis. SampleBot is pretty a dumb player, but he finishes his turns and is relatively quick.

The basic idea is that you create a cgi script that can retrieve information from Warfish using the XML/JSON apis. Then you provide the url for your cgi script to Warfish (i.e. called the "notification url") so that your cgi script can be invoked each time it is your bot's turn. Then anyone can invite your bot to play a game and it will be notified via http and can make its moves.

[edit] Code

Here is the entire code listing for the samplebot.py

#!/usr/bin/python
# SampleBot
#
# This is an sample bot designed to provide you with a starting point
# for creating your own bots.  You are free to use this code freely in your own
# Warfish bots.
#
# copyright Warfish.net 2006
import urllib # standard python library
import urllib2 # standard python library
import random # standard python library

import simplejson # simple library with no external dependencies
# this is a third party library available here:
# http://cheeseshop.python.org/pypi/simplejson/1.5


# You can get this value from typing javascript:document.write(document.cookie)
# into browser when viewing a page on Warfish
#
# Cut and paste the value that is printed into your browser window it
authcookie = " LAST=samplebot@warfish.net; PHPSESSID=1231231231230844f21f462"

# Another cookie used in testing
alternatecookie = "LAST=samplebot@warfish.net; PHPSESSID=123123e4859e4124bf7cd4d18d35"

# three basic ways to invoke this code
# [1] from the command line (see main())
# [2] from the web (see index())
# [3] as a library (i.e. import samplebot, then instantiate wfGameTable or call sampleBot)

def main(argv):

   "quot;quot;command-line based access"quot;quot;
   def usage():
       print "usage:"
       print " -g game table id (required)"
       print " -d debug level (1 or 2)"
       print " -d cookie id (0 or 1, defaults to 0)"
       print " -h (help)"
   try: opts, args = getopt.getopt(argv, "hg:d:c:")
   except getopt.GetoptError: usage(); sys.exit(2)
   gid = None
   debug = 0
   ca = 0
   for opt, arg in opts:
       if opt == "-h": usage(); sys.exit()
       elif opt == "-g": gid = int(arg)
       elif opt == "-d": debug = int(arg)
       elif opt == "-c": ca = int(arg)
   if gid == None or debug < 0 or debug > 2 or ca < 0 or ca > 1:
       usage()
       sys.exit(2)
   sampleBot(gid, ca, debug = 1)

def index(req, gid, ca = None):
   "quot;quot;web/url based access"quot;quot;
   # alternete cookie for testing?
   if ca != None and int(ca) == 1: ca = 1
   else: ca = 0
   
   # execute twice in case we have back to back actions (such as join to unitplace)
   sampleBot(gid, ca)
   sampleBot(gid, ca)    
   return "SUCCESS"
def fetchData(cgiArgsDict, acookie, debug = 0):
   "quot;quot;simple wrapper for data retrieval and parsing"quot;quot;
   url = "http://warfish.net/war/services/rest"
   cgiArgsDict['_format'] = 'json'
   req = urllib2.Request(url,urllib.urlencode(cgiArgsDict),{'Cookie':acookie})
   res = urllib2.urlopen(req)
   restext = res.read()
   if debug == 2: print "%s" % restext
   retData = simplejson.loads(restext)
   res.close()
   return retData

class wfGameTable:
   "quot;quot;wfGameTable is a wrapper for the XML/JSON api that provides some additional 
   accessor functions to manipulate game data"quot;quot;
   def __init__(self, gameid, acookie):
       self._gid = gameid
       self._details = None
       self._state = None
       self._lastattack = None
       self._lastattackcapture = False
       self._acookie = acookie

   def cardlist(self):
       return ['A','B','C','W']

   # The following three functions, loadDetails, loadState and doMove
   # are responsible for all the communication between samplebot and warfish.net
   def loadDetails(self, debug = 0):
       gamedetails_data = fetchData({'_method':'warfish.tables.getDetails','gid':self._gid}, self._acookie, debug)
       if gamedetails_data['stat'] != 'ok': return False
       self._details = gamedetails_data['_content']
       return True        

   def loadState(self, debug = 0):
       gamestate_data = fetchData({'_method':'warfish.tables.getState','gid':self._gid}, self._acookie, debug)
       if gamestate_data['stat'] != 'ok': return False
       self._state = gamestate_data['_content']
       return True

   def doMove(self, params, debug = 0):
       params['_method'] = 'warfish.tables.doMove'
       params['gid'] = self._gid
       data = fetchData(params, self._acookie, debug)
       if data['stat'] == 'ok' and data['_content']['return']['code'] == '1': return (True,data)
       return (False,data)
   def doMove_join(self, colorid, name):
       return self.doMove({'action':'join','colorid':colorid,'name':name})[0]
   def doMove_selectSingle(self, cid):
       return self.doMove({'action':'selectsingle','cid':cid})[0]
   def doMove_selectTerritories(self, tlist, debug = 0):
       if debug == 2: print "clist=%s" % ",".join(["%s" % i for i in tlist])
       return self.doMove({'action':'selectterritories','clist':",".join(["%s" % i for i in tlist])}, debug)[0]
   def doMove_placeSingle(self, cid):
       return self.doMove({'action':'placesingle','cid':cid})[0]
   def doMove_placeUnits(self, clist, ulist, debug = 0):
       (retval, data) = self.doMove({'action':'placeunits','clist':",".join(["%s" % i for i in clist]),'ulist':",".join(["%s" % j for j in ulist])}, debug)
       if retval: self.updateLocalData_placeUnits(clist, ulist)
       return retval
   def doMove_useCards(self, numA, numB, numC, numW):
       (retval, data) = self.doMove({'action':'usecards','numA':numA,'numB':numB,'numC':numC,'numW':numW})
       if retval: self.updateLocalData_useCards(data)
       return retval
   def doMove_attack(self, fromcid, tocid, numunits, continuous):
       (retval, data) = self.doMove({'action':'attack', 'fromcid':fromcid,'tocid':tocid,'numunits':numunits,'continuous':continuous})
       if retval: self.updateLocalData_attack(fromcid, tocid, numunits, continuous, data)
       return retval
   def doMove_freeTransfer(self, numunits, debug = 0):
       (retval, data) = self.doMove({'action':'freetransfer', 'numunits':numunits}, debug)
       if retval: self.updateLocalData_transfer(self.getLastAttack()[0],self.getLastAttack()[0],numunits)
       return retval
   def doMove_transfer(self, fromcid, tocid, numunits, debug = 0):
       (retval, data) = self.doMove({'action':'transfer','fromcid':fromcid,'tocid':tocid,'numunits':numunits}, debug)
       if retval: self.updateLocalData_transfer(fromcid, tocid, numunits)
       return retval
   def doMove_endTurn(self, debug = 0):
       (retval, data) = self.doMove({'action':'endturn'}, debug)
       return retval
   def doMove_issueOrders(self, olist, alist, debug = 0):
       if debug == 2: print "olist=%s" % ",".join(["%s" % i for i in olist])
       if debug == 2: print "alist=%s" % ",".join(["%s" % ":".join(["%s" % k for k in j]) for j in alist])
       (retval, data) = self.doMove({'action':'issueorders','olist':",".join(["%s" % i for i in olist]),'alist':",".join(["%s" % ":".join(["%s" % k for k in j]) for j in alist])}, debug)
       if debug == 2: print "%s" % data
       return retval
   
   def updateLocalData_placeUnits(self, clist, ulist):
       for ix, i in enumerate(clist):
           tinfo = self.getTerritoryInfo(i)
           tinfo['units'] = "%s" % int(int(tinfo['units']) + ulist[ix])
           self._state['players']['_content']['player'][self.getSeatId()]['units'] = "%s" % int(self.getNumUnits() - ulist[ix])            
   def updateLocalData_useCards(self, data):
       # update local data
       bonus = int(data['_content']['return']['_content']['bonus']['units'])
       numunits = self.getNumUnits() + bonus
       self._state['players']['_content']['player'][self.getSeatId()]['units'] = "%s" % numunits
   def getLastAttack(self):
       return self._lastattack
   def getLastAttackWasCapture(self):
       return self._lastattackcapture
   def updateLocalData_attack(self, fromcid, tocid, numunits, continuous, data):
       # update local data            
       attackerloss = int(data['_content']['return']['_content']['results']['totalattackerlosses'])
       defenderloss = int(data['_content']['return']['_content']['results']['totaldefenderlosses'])
       self._lastattack = (fromcid,tocid,numunits,continuous)            
       self._lastattackcapture = False
       if defenderloss != int(self.getTerritoryInfo(tocid)['units']):
           self.getTerritoryInfo(fromcid)['units'] = "%s" % int(int(self.getTerritoryInfo(fromcid)['units']) - attackerloss)
           if self.getTerritoryInfo(tocid)['units'] != "?":
               self.getTerritoryInfo(tocid)['units'] = "%s" % int(int(self.getTerritoryInfo(tocid)['units']) - defenderloss)
       else:
           # territory captured logic
           self._lastattackcapture = True
           attacklist = data['_content']['return']['_content']['attack']
           lastattack = attacklist[-1]
           num_attackers_in_tocid = len(lastattack['attackdice'].split(',')) - int(lastattack['attackerlosses'])
           frominfo = self.getTerritoryInfo(fromcid)
           toinfo = self.getTerritoryInfo(tocid)
           frominfo['units'] = "%s" % int(int(frominfo['units']) - attackerloss - num_attackers_in_tocid)
           toinfo['units'] = "%s" % num_attackers_in_tocid
           toinfo['playerid'] = frominfo['playerid']
           if data['_content']['return']['_content']['results']['eliminate'] == "1":
               if int(data['_content']['return']['_content']['elimdata']['numcardscaptured']) > 0:
                   # add capturecardids
                   capturedcardids = [int(i) for i in data['_content']['return']['_content']['elimdata']['capturedcardids'].split(',')]
                   for ix,i in self.cardlist():
                       self.getCard()['num%s' % i] = "%s" % int(int(self.getCards()['num%s' % i]) + capturedcardids.count(ix))
               # unit capture
               if int(data['_content']['return']['_content']['elimdata']['unitsadded']) > 0:
                   self._state['players']['_content']['player'][self.getSeatId()]['units'] = self.getNumUnits() + int(data['_content']['return']['_content']['elimdata']['unitsadded'])
   def updateLocalData_transfer(self, fromcid, tocid, numunits):
       self.getTerritoryInfo(fromcid)['units'] = "%s" % int(int(self.getTerritoryInfo(fromcid)['units']) - numunits)
       self.getTerritoryInfo(tocid)['units'] = "%s" % int(int(self.getTerritoryInfo(tocid)['units']) - numunits)
   def getPossibleActions(self):
       "quot;quot;inspect the getState data to return any possible actions, empty if not your turn"quot;quot;
       if self._state['possibleactions'].has_key('_content') and self._state['possibleactions']['_content'].has_key('action'):
           return [i['id'] for i in self._state['possibleactions']['_content']['action']]
       else:
           return []
   def getTerritories(self):
       return self._state['board']['_content']['area']
   def getAdjacentTerritories(self, cid):
       alist = []
       for i in self._details['board']['_content']['border']:
           if int(i['a']) == cid: alist.append(self.getTerritoryInfo(int(i['b'])))
       return alist
   def friendlyTerritory(self, cinfo):
       if cinfo['playerid'] and cinfo['playerid'] != "?" and int(cinfo['playerid']) == self.getSeatId(): return True
       else: return False
   def getTerritoryInfo(self, cid):
       for k in self._state['board']['_content']['area']:
           if cid == int(k['id']): return k
       return None
   def getFriendlyTerritories(self):
       ftlist = []
       for i in self.getTerritories():
           if self.friendlyTerritory(i):
               ftlist.append(i)
       return ftlist
   def getPossibleTransfers(self):
       ptlist = []
       for i in self.getFriendlyTerritories():
           if int(i['units']) > 1:
               for j in self.getAdjacentTerritories(int(i['id'])):
                   if self.friendlyTerritory(j):
                       tomove = int(i['units']) - 1
                       maxtomove = self.getNumPerCountry() - int(j['units'])
                       if tomove > maxtomove: tomove = maxtomove
                       if tomove > 0:
                           ptlist.append( (int(i['id']), int(j['id']), int(i['units']) - 1) )
       return ptlist
   def getPossibleAttacks(self):        
       ptlist = []
       for i in self.getFriendlyTerritories():
           if int(i['units']) > 1: 
               for j in self.getAdjacentTerritories(int(i['id'])):
                   if not self.friendlyTerritory(j):
                       ptlist.append( (int(i['id']), int(j['id']), int(i['units']) - 1) )
       return ptlist
   def getUnoccupiedTerritories(self):
       tlist = []
       for i in self.getTerritories():
           if not i['playerid'] or i['playerid'] == "":
               tlist.append(int(i['id']))
       return tlist
   def getNumCards(self):
       cardlist = self.cardlist()
       numcards = 0
       for i in cardlist: numcards += int(self.getCards()['num%s' % i])
       return numcards
   def getCards(self):
       return self._state['cards']['_content']['self']
   def getCardIds(self):
       cardids = []
       cardlist = self.cardlist()        
       for ix,i in enumerate(cardlist): cardids.extend([ix for j in range(int(self.getCards()['num%s' % i]))])
       return cardids
   def mustCard(self, duringattack = False):
       if duringattack: maxcards = 5
       else: maxcards = 4
       
       if self.getNumCards() > maxcards: return True
       return False
   def captureMoreUnitsToMove(self):
       if self.getLastAttack() == None: return False
       
       # if last attack was a capture and there are more units in fromcid
       if self.getLastAttackWasCapture() and int(self.getTerritoryInfo(self.getLastAttack()[0])['units']) > 1:
           return True
       else:
           return False
   def getNumReserves(self):
       return int(self._details['rules']['numreserves'])
   def getNumPerCountry(self):
       return int(self._details['rules']['numpercountry'])
   def getNumTransfers(self):
       return int(self._details['rules']['numtransfers'])
   def getCardsWorth(self):
       return int(self._state['cards']['worth'])
   def getSeatId(self):
       return int(self._state['players']['_content']['self']['playerid'])
   def getNumUnits(self):
       return int(self._state['players']['_content']['player'][self.getSeatId()]['units'])
   def getPlayers(self):
       return self._state['players']['_content']['player']
   def mustPlaceUnits(self):
       if self.getNumUnits() > self.getNumReserves(): return True
       else: return False
   G_NOTYOURTURN = 0
   G_JOIN = 1
   G_SETUP_TURNBASED_SELECT = 2
   G_SETUP_BLIND_SELECT = 3
   G_SETUP_TURNBASED_PLACE = 4
   G_SETUP_BLIND_PLACE = 5
   G_PLAY_TURNBASED = 6
   G_PLAY_BLIND = 7
   def getStage(self):
       pa = self.getPossibleActions()
       if len(pa) == 0:
           return self.G_NOTYOURTURN
       elif len(pa) == 1:
           if pa[0] == 'join': return self.G_JOIN
           elif pa[0] == 'selectsingle': return self.G_SETUP_TURNBASED_SELECT
           elif pa[0] == 'selectterritories': return self.G_SETUP_BLIND_SELECT
           elif pa[0] == 'placesingle': return self.G_SETUP_TURNBASED_PLACE
           elif pa[0] == 'placeunits': return self.G_SETUP_BLIND_PLACE
           elif pa[0] == 'issueorders': return self.G_PLAY_BLIND
           elif pa[0] == 'freetransfer': return self.G_PLAY_TURNBASED # shouldn't reach this line
       else:
           return self.G_PLAY_TURNBASED
def doSampleJoin(game, debug = 0):
   # pick first available color
   selectedcolorid = 0
   for i in range(1, 16 + 1):
       colortaken = False
       for j in game.getPlayers():
           if int(j['colorid']) == i:
               colortaken = True
               break
       if not colortaken:
           selectedcolorid = i
           break
   if game.doMove_join(selectedcolorid, "Sample Bot"):
       if debug: print "Joined game"
   else:
       if debug: print "ERROR joining game"
def doSampleSelectSingle(game, debug = 0):
   tlist = game.getUnoccupiedTerritories()
   if len(tlist) > 0:
       random.shuffle(tlist)
       if game.doMove_selectSingle(tlist[0]):
           if debug: print "Selected country"
       else:
           if debug: print "ERROR selecting country"
   else:
       if debug: print "ERROR selecting country (no unoccupied territories)"
def doSampleSelectTerritories(game, debug = 0):
   tlist = game.getUnoccupiedTerritories()
   if len(tlist) > 0:
       random.shuffle(tlist)
       if game.doMove_selectTerritories(tlist, debug):
           if debug: print "Selected territories"
       else:
           if debug: print "ERROR selecting territories"
   else:
       if debug: print "ERROR selecting territories (no unoccupied territories)"
def doSamplePlaceSingle(game, debug = 0):
   ftlist = game.getFriendlyTerritories()
   if len(ftlist) > 0:
       random.shuffle(ftlist)
       acceptablecid = None
       for i in ftlist:
           if int(i['units']) < game.getNumPerCountry():
               acceptablecid = int(i['id'])
               break
       if game.doMove_placeSingle(acceptablecid):
           if debug: print "Placed single unit"
       else:
           if debug: print "ERROR placing single unit"
   else:
       if debug: print "ERROR placing single unit (no friendly territories)"        
def doSamplePlaceUnits(game, debug = 0):
   ftlist = game.getFriendlyTerritories()
   clist = []
   ulist = []
   numleft = game.getNumUnits()
   if len(ftlist) > 0:
       random.shuffle(ftlist)
       for i in ftlist:
           maxplaceable = game.getNumPerCountry() - int(i['units'])
           if maxplaceable > numleft: numtoplace = numleft
           else: numtoplace = maxplaceable
           clist.append(int(i['id']))
           ulist.append(numtoplace)
           numleft -= numtoplace
           if numleft <= game.getNumReserves(): break
       if game.doMove_placeUnits(clist, ulist, debug):
           if debug: print "Placed units"
       else:
           if debug: print "ERROR placing units"
   else:
       if debug: print "ERROR placing units (no friendly territories)"
def helperGetUsableCombo(clist, game):
   def findNum(clist, num):
       for ix, i in enumerate(game.cardlist()):
           if ix != 3 and clist.count(ix) >= num: return i
       return None
   if len(clist) < 5: return None
   ucards = None
   c = findNum(clist, 3)
   if c != None:
       ucards = {'numA':0,'numB':0,'numC':0,'numW':0}        
       ucards['num%s' % c] = 3
   else:
       if clist.count(0) > 0 and clist.count(1) > 1 and clist.count(2):
           ucards = {'numA':1,'numB':1,'numC':1,'numW':0}
   if ucards == None:
       if clist.count(3) == 1:
           c = findNum(clist, 2)
           if c != None:
               ucards = {'numA':0,'numB':0,'numC':0,'numW':0}                    
               ucards['num%s' % c] = 2
               ucards['numW'] = 1
           else:
               if clist.count(0) > 0 and clist.count(1) > 1:
                   ucards = {'numA':1,'numB':1,'numC':0,'numW':1}
               elif clist.count(1) > 0 and clist.count(2) > 1:
                   ucards = {'numA':0,'numB':1,'numC':1,'numW':1}
               elif clist.count(0) > 0 and clist.count(2) > 1:
                   ucards = {'numA':1,'numB':0,'numC':1,'numW':1}
       elif clist.count(3) == 2:
           c = findNum(clist, 1)
           if c != None:
               ucards = {'numA':0,'numB':0,'numC':0,'numW':0}                    
               ucards['num%s' % c] = 1
               ucards['numW'] = 2
   return ucards
def doSampleUseCards(game, debug = 0):
   ucards = helperGetUsableCombo(game.getCardIds(), game)
   if ucards != None:
       if game.doMove_useCards(ucards['numA'], ucards['numB'], ucards['numC'], ucards['numW']):
           if debug: print "Used cards"
       else:
           if debug: print "ERROR using cards"
   else:
       if debug: print "ERROR using cards (usable combo not found)"
def doSampleAttack(game, debug = 0):
   pa = game.getPossibleAttacks()
   if len(pa) > 0:
       random.shuffle(pa)
       if pa[0][2] > 2: continuous = 1
       else: continuous = 0
       if game.doMove_attack(pa[0][0], pa[0][1], pa[0][2], continuous):
           if debug: print "Attacked"
       else:
           if debug: print "ERROR attacking"
   else:
       if debug: print "ERROR attacking (no possible attacks)"
def doSampleFreeTransfer(game, debug = 0):
   info = game.getTerritoryInfo(game.getLastAttack()[0])
   if game.doMove_freeTransfer(int(info['units']) - 1, debug):
       if debug: print "Free transferred"
   else:
       if debug: print "ERROR free transferring"
def doSampleTransfer(game, debug = 0):
   pt = game.getPossibleTransfers()
   if len(pt) > 0:
       random.shuffle(pt)
       if game.doMove_transfer(pt[0][0], pt[0][1], pt[0][2], debug):
           if debug: print "Transferred"
       else:
           if debug: print "ERROR transferring"
   else:
       if debug: print "ERROR transferring (no possible transfers)"
def doSampleEndTurn(game, debug = 0):
   if game.doMove_endTurn(debug):
       if debug: print "Ended turn"
   else:
       if debug: print "ERROR ending turn"
O_USECARDS = 1
O_PLACEUNITS = 2
O_PRETRANSFER = 3
O_ATTACKTRANSFER = 4
def doSampleIssueOrders(game, debug = 0):
   olist = [] # orders list
   alist = [] # arguments list (must be the same length as olist)
   numcards = game.getNumCards()
   cardsunits = 0
   while numcards > 4:
       ucards = helperGetUsableCombo(game.getCardIds(), game)
       olist.append(O_USECARDS)
       cidlist = []
       for ix, i in enumerate(game.cardlist()): cidlist.extend([ix for j in range(ucards['num%s' % i])])
       alist.append(cidlist)
       cardsunits += game.getCardsWorth()
       numcards -= 3
   numleft = cardsunits + game.getNumUnits()
   addCountries = {}
   ftlist = game.getFriendlyTerritories()
   if len(ftlist) > 0:
       random.shuffle(ftlist)
       for i in ftlist:
           maxplaceable = game.getNumPerCountry() - int(i['units'])
           if maxplaceable > numleft: numtoplace = numleft
           else: numtoplace = maxplaceable
           olist.append(O_PLACEUNITS)
           alist.append((int(i['id']), numtoplace))
           addCountries[int(i['id'])] = numtoplace
           numleft -= numtoplace
           if numleft <= game.getNumReserves(): break
       random.shuffle(ftlist)
       pretransfer = False
       attacktransfer = False
       for i in ftlist:
           extra = 0
           if not addCountries.has_key(int(i['id'])): numunits = int(i['units'])
           else: numunits = int(i['units']) +  addCountries[int(i['id'])]
           if numunits > 1:
               for j in game.getAdjacentTerritories(int(i['id'])):
                   if not pretransfer and game.friendlyTerritory(j):
                       olist.append(O_PRETRANSFER)
                       alist.append( (int(i['id']), int(j['id']), numunits - 1) )
                       pretransfer = True
                       break
                   elif not attacktransfer:
                       olist.append(O_ATTACKTRANSFER)
                       alist.append( (0,int(i['id']), int(j['id']), numunits - 1,3) )
                       attacktransfer = True
                       break
           if pretransfer and attacktransfer: break
       if game.doMove_issueOrders(olist, alist, debug):
           if debug: print "Issued orders"
       else:
           if debug: print "ERROR issuing orders"
   else:
       if debug: print "ERROR issuing orders (no friendly territory)"        
def doTurnBasedPlayHelper(game, debug = 0):
   "quot;quot;helper function that combines several actions required for turn-based play"quot;quot;
   if game.mustCard(): doSampleUseCards(game, debug)
   doSamplePlaceUnits(game, debug)
   doSampleAttack(game, debug)
   if game.captureMoreUnitsToMove(): doSampleFreeTransfer(game, debug)
   while game.mustCard(duringattack = True): doSampleUseCards(game, debug)
   if game.mustPlaceUnits(): doSamplePlaceUnits(game, debug)
   doSampleTransfer(game, debug)
   if game.getNumTransfers() != 1: doSampleEndTurn(game, debug)

def sampleBot(gid, ca = 0, debug = 0):
   "quot;quot;sample bot to demonstrate each of the possible doMove actions"quot;quot;
   
   # another cookie used for testing
   if ca == 1: acookie = alternatecookie
   else: acookie = authcookie
   
   g = wfGameTable(gid, acookie)
   if not g.loadDetails(): return
   if not g.loadState(): return
   sampleActions = { g.G_JOIN: doSampleJoin,
                     g.G_SETUP_TURNBASED_SELECT: doSampleSelectSingle,
                     g.G_SETUP_BLIND_SELECT: doSampleSelectTerritories,
                     g.G_SETUP_TURNBASED_PLACE: doSamplePlaceSingle,
                     g.G_SETUP_BLIND_PLACE: doSamplePlaceUnits,
                     g.G_PLAY_TURNBASED: doTurnBasedPlayHelper,
                     g.G_PLAY_BLIND: doSampleIssueOrders }
   
   if sampleActions.has_key(g.getStage()): sampleActions[g.getStage()](g, debug)

if __name__ == "__main__":
   import sys, getopt
   main(sys.argv[1:])
Personal tools