def build_road(player, vertex1, vertex2): if vertex2 < vertex1: (vertex1, vertex2) = (vertex2, vertex1) if ( #the player has the resources player.hasResourcesFor(BuildTypes.ROAD) and #both vertices are valid v.isvalid(v.decompress(vertex1)) and v.isvalid(v.decompress(vertex2)) and #no other roads overlap Road.overlaps_q(player, vertex1, vertex2).count() == 0 and #the player has a road at one of the vertices already player.road_meets_q(vertex1, vertex2).count() != 0 ) : player.takeResourcesFor(BuildTypes.ROAD) r = Road(player.UserID, vertex1, vertex2) player.game.roads.append(r) player.game.log(Log.road_built(player, r)) # TODO: check if we now have longest road. # It is a longest path problem. Check the rules before implementing db_session.commit() return "success" else: return "failure"
def build_settlement(player, p): #TODO: make sure decompress checks validity vertex = v.decompress(p) if ( players_turn(player) and #there are no settlements within the distance rule Settlement.distance_rule(player.GameID, vertex) and #and the player has a road to the vertex player.roads_q().count() > 0 and #FIXME #and the player has the requisite resources player.hasResourcesFor(BuildTypes.TOWN) ) : player.takeResourcesFor(BuildTypes.TOWN) #Actually, I think it would be better to just have add_settlement written here inline s = player.add_settlement(p) player.Score += 1 player.game.log(Log.settlement_built(player, s)) player.checkVictory() db_session.commit() return "success" else: return "failure"
def move_robber(player, to, stealfrom): game = player.game if not ( #We're supposed to be moving the robber game.State == Game.States.MOVE_ROBBER and #this player is supposed to be moving the robber player.UserID == game.CurrentPlayerID and #the robber isn't being moved nowhere game.RobberHex != to and #the place where the robber is being moved is valid to in h.valid_hexes ) : return "failure" v1 = v.decompress(to) adjacent_vertices = map(v.compress, h.adjacent(v1)) vulnerable_players = db_session.query(Settlement.UserID). \ filter_by(GameID=game.GameID). \ filter(Settlement.Vertex.in_(adjacent_vertices)). \ filter(Settlement.UserID != player.UserID). \ all() if (len(vulnerable_players) == 0 and stealfrom is None) or (stealfrom,) in vulnerable_players: game.RobberHex = to game.State = Game.States.NORMAL_PLAY if stealfrom is not None: pass #TODO game.log(Log.robber_moved(player.UserID, to)) game.log(Log.req_turn(player.UserID)) db_session.commit() return "success" else: return "failure"
def setup(player, settlement_vertex, road_to): game = player.game settlement_v = v.decompress(settlement_vertex) road_v = v.decompress(road_to) if ( #we're setting up game.State in [Game.States.SETUP_FORWARD, Game.States.SETUP_BACKWARD] and #it's the player's turn player.UserID == game.CurrentPlayerID and #the settlement vertex is valid v.isvalid(settlement_v) and #the new settlement conforms to the distance rule Settlement.distance_rule(player.GameID, settlement_v) and #the road vertex is adjacent to the settlement (and valid) road_v in v.adjacent(settlement_v) #we don't have to check for existing roads, #because there can't be any, by the distance rule ): s = player.add_settlement(settlement_vertex) r = player.add_road(settlement_vertex, road_to) player.Score += 1 game.log(Log.setup(player, settlement_vertex, road_to)) if game.State == Game.States.SETUP_FORWARD: if game.CurrentIndex + 1 == len(game.players): #time to go backwards game.State = Game.States.SETUP_BACKWARD else: game.CurrentIndex += 1 elif game.State == Game.States.SETUP_BACKWARD: #TODO: A naming schema for compressed/uncompressed vertices (Hungarian Notation FTW!) adjacent = map(v.compress, v.adjacent_hexes(settlement_v)) cards = db_session.query(Hex.Type, func.count()). \ filter_by(GameID=game.GameID). \ filter(Hex.Vertex.in_(adjacent)). \ filter(Hex.Type != Terrain.DESERT). \ group_by(Hex.Type). \ all() player.add_cards([(j, i) for (i, j) in cards]) if game.CurrentIndex == 0: #setup is over, welcome to the real world, Neo game.State = Game.States.NORMAL_PLAY else: game.CurrentIndex -= 1 game.CurrentPlayerID = game.players[game.CurrentIndex].UserID log_state_change(game) db_session.commit() return "success" else: return "failure"
def give_cards(rolled): #gets hexes that have just yielded stuff rolled_hexes = db_session.query(Hex.Vertex, Hex.Type). \ filter_by(GameID=self.GameID). \ filter(Hex.Chit == rolled). \ filter(Hex.Vertex != self.RobberHex). \ all() """ Creates a dict of the form: (type -> (vertex -> count) where: type is the type of hex vertex is a vertex number adjacent to the hex count is the number of times that vertex would receive cards of type *type* It may be better to do sort | uniq here """ types = {} for (hex, type) in rolled_hexes: if not type in types: types[type] = {} adjacent = map(v.compress, h.adjacent(v.decompress(hex))) for i in adjacent: if not i in types[type]: types[type][i] = 0 types[type][i] += 1 """ Creates a dict of the form: (userid -> (type -> count)) where: userid is self explanatory type if the type of resource (equivalent to the type of hex) count is the number of cards of that resource type """ users = {} for t in types: #get all settlements that are adjacent to hexes #of type *type* settlements = Settlement.query. \ filter_by(GameID=self.GameID). \ filter(Settlement.Vertex.in_(types[t].keys())). \ all() for s in settlements: if not s.UserID in users: users[s.UserID] = {} if not t in users[s.UserID]: users[s.UserID][t] = 0 #give double for cities users[s.UserID][t] += \ (2 if s.Type == Settlement.CITY else 1) * \ types[t][s.Vertex] for u in users: allocated = list(map(lambda type: (users[u][type], type), users[u].keys())) GamePlayer.query. \ filter_by(GameID=self.GameID). \ filter_by(UserID=u).one(). \ add_cards(allocated)