Ejemplo n.º 1
0
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"
Ejemplo n.º 2
0
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"
Ejemplo n.º 3
0
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"
Ejemplo n.º 4
0
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"
Ejemplo n.º 5
0
            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)