class Game: """Represents the current state of a risk game Includes full specification of the map, rules, players and current game state. Includes the NAME ONLY of the graphical map file, along with coordinates of territories on this map.""" def __init__(self,nodeNetwork=None, players={}, bonuses=[], mapString=None, coordinates=None, mapFile=None, settingsMap={}): self.mapFile = mapFile self.coordinates = coordinates self.rules = Rules(map=nodeNetwork, players=players) self.whosTurn = self.rules.players[0] self.turnStage = 'reinforce' self.reinforcementsToPlace = {} self.lastAttack = None self.fortifies = 1 if 'fortifies' in settingsMap: self.fortifies = int(settingsMap['fortifies']) self.fortifiesLeft = self.fortifies self.bonuses=bonuses for player in self.rules.players: self.reinforcementsToPlace[player]=0 self.reinforced = False if not mapString and not (coordinates and mapFile): print "this game has no pretty visualization available" self.mapString = mapString self.settingsMap = settingsMap self.fog = False if 'fog' in self.settingsMap: self.fog = self.settingsMap['fog'] self.selectionList = [] self.showAttackResult = False self.justMadeFreeMove = False def _giveReinforcements(self): if self.reinforced == True: return False else: self.reinforced = True self.reinforcementsToPlace[self.whosTurn]=self.getDeservedReinforcements(self.whosTurn) def player_getFortifiesLeft(self,player): """Returns 0 if not the current players turn, otherwise the number of fortifying moves left in the turn""" if self.whosTurn != player: return 0 else: return self.fortifiesLeft def updateTurn(self): if self.whosTurn not in self.playersAlive and self.turnStage != 'fortify': # lose condition self.turnStage = 'fortify' self.fortifiesLeft = 0 self.updateTurn() if len(self.playersAlive) == 1 and self.playersAlive[0] == self.whosTurn: self.turnStage = 'reinforce' # win condition self.reinforcementsToPlace[self.whosTurn] = 1 elif self.turnStage == 'reinforce' and self.reinforcementsToPlace[self.whosTurn]==0: self.turnStage = 'attacks' elif (self.turnStage == 'fortify' and self.fortifiesLeft == 0) or self.whosTurn not in self.playersAlive: players = self.players # begin new turn for i in range(len(players)): if self.whosTurn == players[i]: self.whosTurn = players[(i+1)%len(players)] self.reinforcementsToPlace[self.whosTurn] = self.getDeservedReinforcements(self.whosTurn) self.fortifiesLeft = self.fortifies self.turnStage = 'reinforce' self.selectionList = [] self.lastAttack = None self.justMadeFreeMove = False self.updateTurn() break def getDeservedReinforcements(self,player): count = 0 countriesPerTroop = 3 if 'countriesPerTroop' in self.settingsMap: countriesPerTroop = int(self.settingsMap['countriesPerTroop']) countries = self.countries for country in countries: if self.isOwned(country, player): count +=1 for bonus in self.bonuses: deserveBonus = True for country in bonus[0:-1]: if not self.isOwned(country,player): deserveBonus = False if deserveBonus: count+=(countriesPerTroop*int(bonus[-1])) return max(int(count/countriesPerTroop),3) def player_reinforce(self,country,howMany,player): pass # check for correct turn, right time, have reinforcements, etc. if type(player) != type('string') and type(player) != type(u'string'): return False if self.whosTurn != player: return False if self.turnStage != 'reinforce': return False if self.reinforcementsToPlace[player]<=0: return False if type(country) != type('string') and type(country) != type(u'string'): return False if country not in self.countries: return False if not self.isOwned(country, player): return False if type(howMany) != type(1): return False if howMany>self.reinforcementsToPlace[player]: return False if howMany < 0: return False if self.rules.addUnits(country, howMany): self.reinforcementsToPlace[player]=self.reinforcementsToPlace[player]-howMany self.updateTurn() return True else: return False def player_attack(self,fromCountry,toCountry,howMany,player): if self.whosTurn != player: #raise Exception, 'player error' return False if self.turnStage != 'attacks': #raise Exception, 'its not in the attack stage' return False if type(fromCountry)!=type('string') and type(fromCountry) != type(u'string'): #raise Exception, 'from country is not a string' return False if type(toCountry)!=type('string') and type(fromCountry) != type(u'string'): #raise Exception, 'to country is not a string' return False if type(player)!=type('string') and type(player) != type(u'string'): #raise Exception, 'player is not a string' return False if type(howMany)!=type(1): #raise Exception, 'how many is not a number' return False if not fromCountry in self.countries: #raise Exception, 'from country is not a country' return False if not toCountry in self.countries: #raise Exception, 'to country is not a country' return False if not player in self.players: #raise Exception, 'player is not in this game' return False if not self.isTouching(fromCountry, toCountry): #raise Exception, 'those countries do not touch' return False if not self.isOwned(fromCountry, player): #raise Exception, 'attacker does not own from country' return False if self.isOwned(toCountry, player): #raise Exception, 'attacker owns destination country' return False if self.getTroops(fromCountry) < howMany+1: #raise Exception, 'not enough troops in fromCountry' return False if howMany < 1: #raise Exception, 'attacking with less than one troop' return False output = self.rules.attack(fromCountry,toCountry,howMany) if not output: raise Exception, 'rules.attack failed' return False else: self.lastAttack = output self.updateTurn() self.showAttackResult = True self.justMadeFreeMove = False return output def player_freeMove(self,fromCountry,toCountry,howMany,player): if type(player)!=type('string') and type(player) != type(u'string'): return False if self.whosTurn != player: return False if self.turnStage != 'attacks': return False if type(fromCountry)!=type('string') and type(fromCountry) != type(u'string'): return False if type(toCountry)!=type('string') and type(toCountry) != type(u'string'): return False if type(howMany)!=type(1): return False if not self.lastAttack['captured']: return False if fromCountry != self.lastAttack['from']: return False if toCountry != self.lastAttack['to']: return False if not player in self.players: return False if not self.isTouching(fromCountry, toCountry): return False if not self.isOwned(fromCountry, player): return False if not self.isOwned(toCountry, player): return False if self.getTroops(fromCountry) < howMany+1: return False if self.rules.moveUnits(fromCountry, toCountry, howMany): self.updateTurn() self.showAttackResult = False self.justMadeFreeMove = True return True else: raise Exception, 'rules failed' return False def player_fortify(self,fromCountry,toCountry,howMany,player): if type(player)!=type('string') and type(player) != type(u'string'): return False if self.whosTurn != player: return False if self.turnStage != 'fortify' and self.turnStage != 'attack': return False if self.fortifiesLeft <1: return False if type(fromCountry)!=type('string') and type(fromCountry) != type(u'string'): return False if type(toCountry)!=type('string') and type(toCountry) != type(u'string'): return False if type(howMany)!=type(1): return False if not self.isTouching(fromCountry, toCountry): return False if not self.isOwned(fromCountry, player): return False if not self.isOwned(toCountry, player): return False if self.getTroops(fromCountry) < howMany+1: return False if self.rules.moveUnits(fromCountry, toCountry, howMany): self.turnStage = 'fortify' self.fortifiesLeft -=1 self.updateTurn() return True else: return False def player_skip(self, player): if self.whosTurn != player: return False else: if self.turnStage == 'reinforce': if self.reinforcementsToPlace[self.whosTurn] <= 0: self.updateTurn() else: return False elif self.turnStage == 'attacks': self.turnStage = 'fortify' self.showAttackResult = False self.updateTurn() return True elif self.turnStage == 'fortify': self.fortifiesLeft = 0 self.updateTurn() return True else: return False def player_getLastAttack(self,player): if self.whosTurn != player: return False else: return self.lastAttack def getReinforcements(self,player): """Returns the number of reinforcements the player has yet to place""" return self.reinforcementsToPlace[player] def getCoordinates(self, country): return self.coordinates[country] def getAdjacentAttacks(self, country): possibleAttacks = [] player = self.getOwner(country) for adjCountry in self.getAdjacentCountries(country): if self.getOwner(adjCountry) != player: possibleAttacks.append(adjCountry) return possibleAttacks def getAdjacentCountries(self,country): return self.rules.getAdjacentCountries(country) def isTouching(self, country1, country2): return self.rules.isTouching(country1, country2) def isOwned(self, country, player): return self.rules.isOwned(country, player) def setSelection(self, list): self.selectionList = list[:] def getSelection(self): return self.selectionList[:] def clearSelection(self): self.selectionList = [] def allOwned(countryList, player): return self.rules.isOwned(country, player) def isCountry(self,country): return country in self.countries def getOwner(self, country): return self.rules.getOwner(country) def getTroops(self, country): return self.rules.getTroops(country) def getFortifies(self): return self.fortifies @property def countries(self): return self.rules.board.getCountries() @property def players(self): return self.rules.players @property def playersAlive(self): return self.rules.getPlayersAlive() @property def states(self): return self.rules.board.getCountryStates()