예제 #1
0
    def next(self):
        '''Apply player moves and update game state.

        Return a new StateMachine representing the new turn.
        '''
        if self.players != self.moves:
            players = ', '.join(self.players - self.moves)
            raise GameError(GameError.NO_MOVES % players)

        # calculate the new 'true' facts by querying for 'next'
        state = ASTNode.new('?state')
        next_query = ASTNode.new('next')
        next_query.children = [state]
        next_facts = [d[state.term] for d in self.db.query(next_query)]

        # delete the 'does', 'true', and derived facts
        self.db.facts.pop(('does', 2))
        self.moves = set()
        new_db = self.db.copy()
        new_db.derived_facts = {}
        new_db.facts.pop(('true', 1))

        # replace 'true' facts with 'next' facts
        for fact in next_facts:
            new_db.define_fact('true', 1, [fact])

        next = StateMachine(new_db)
        next.players = self.players
        return next
예제 #2
0
    def next(self):
        '''Apply player moves and update game state.

        Return a new StateMachine representing the new turn.
        '''
        if self.players != self.moves:
            players = ', '.join(self.players - self.moves)
            raise GameError(GameError.NO_MOVES % players)

        # calculate the new 'true' facts by querying for 'next'
        state = ASTNode.new('?state')
        next_query = ASTNode.new('next')
        next_query.children = [state]
        next_facts = [d[state.term] for d in self.db.query(next_query)]

        # delete the 'does', 'true', and derived facts
        self.db.facts.pop(('does', 2))
        self.moves = set()
        new_db = self.db.copy()
        new_db.derived_facts = {}
        new_db.facts.pop(('true', 1))

        # replace 'true' facts with 'next' facts
        for fact in next_facts:
            new_db.define_fact('true', 1, [fact])

        next = StateMachine(new_db)
        next.players = self.players
        return next
예제 #3
0
파일: test_ast.py 프로젝트: jazzyb/pygdl
 def _new_tree(self):
     pred = ASTNode(MockToken(None, None, None, None, '<='))
     legal = ASTNode(MockToken(None, None, None, None, 'legal'))
     legal.create_child(MockToken(None, None, None, None, '?player'))
     legal.create_child(MockToken(None, None, None, None, '?move'))
     true = ASTNode(MockToken(None, None, None, None, 'true'))
     pred.children = [legal, true]
     return pred
예제 #4
0
 def test_move_player(self):
     fsm = StateMachine()
     data = '''
     (role x)
     (init 1)
     (<= (legal x ?x) (true ?x))
     '''
     fsm.store(data=data)
     fsm.move('x', '1')
     query = ASTNode.new('does')
     query.children = [ASTNode.new(x) for x in ('x', '1')]
     self.assertTrue(fsm.db.query(query))
예제 #5
0
 def test_move_player_complex(self):
     fsm = StateMachine()
     data = '''
     (role x)
     (init (cell 1 1 b))
     (<= (legal x ?x) (true ?x))
     '''
     fsm.store(data=data)
     fsm.move('x', '(cell 1 1 b)')
     cell = ASTNode.new('cell')
     cell.children = [ASTNode.new(x) for x in ('1', '1', 'b')]
     query = ASTNode.new('does')
     query.children = [ASTNode.new('x'), cell]
     self.assertTrue(fsm.db.query(query))
예제 #6
0
 def test_store_init(self):
     fsm = StateMachine()
     data = '''
     (role x)
     (role o)
     (init (cell a))
     (init (cell b))
     (init (cell c))
     (init (cell d))
     '''
     fsm.store(data=data)
     query = ASTNode.new('true')
     query.children = [ASTNode.new('?state')]
     results = [{k: str(d[k]) for k in d} for d in fsm.db.query(query)]
     for i in ('a', 'b', 'c', 'd'):
         self.assertIn({'?state': '(cell %s)' % i}, results)
예제 #7
0
파일: test_ast.py 프로젝트: jazzyb/pygdl
 def _new_tree(self):
     pred = ASTNode(MockToken(None, None, None, None, '<='))
     legal = ASTNode(MockToken(None, None, None, None, 'legal'))
     legal.create_child(MockToken(None, None, None, None, '?player'))
     legal.create_child(MockToken(None, None, None, None, '?move'))
     true = ASTNode(MockToken(None, None, None, None, 'true'))
     pred.children = [legal, true]
     return pred
예제 #8
0
 def move(self, player, move):
     '''Store a does/2 fact in the database representing a player's move.'''
     if player not in self.players:
         raise GameError(GameError.NO_SUCH_PLAYER % player)
     if player in self.moves:
         raise GameError(GameError.DOUBLE_MOVE % player)
     move = self._single_move_to_ast(move)
     player = ASTNode.new(player)
     if not self._legal(player, move):
         raise GameError(GameError.ILLEGAL_MOVE % (player, move))
     self.db.define_fact('does', 2, [player, move])
     self.moves.add(player.term)
예제 #9
0
 def move(self, player, move):
     '''Store a does/2 fact in the database representing a player's move.'''
     if player not in self.players:
         raise GameError(GameError.NO_SUCH_PLAYER % player)
     if player in self.moves:
         raise GameError(GameError.DOUBLE_MOVE % player)
     move = self._single_move_to_ast(move)
     player = ASTNode.new(player)
     if not self._legal(player, move):
         raise GameError(GameError.ILLEGAL_MOVE % (player, move))
     self.db.define_fact('does', 2, [player, move])
     self.moves.add(player.term)
예제 #10
0
    def score(self, player='?player'):
        '''Return the score for a player this turn.  If player is not
        provided, return a dict of all {player: score}.  If there is no goal
        defined for this player/state, then return None.

        Raise GameError if player does not exist.
        '''
        player = ASTNode.new(player)
        if not player.is_variable() and player.term not in self.players:
            raise GameError(GameError.NO_SUCH_PLAYER % player.term)
        score = ASTNode.new('?score')
        goal = ASTNode.new('goal')
        goal.children = [player, score]
        results = self.db.query(goal)
        if results is False:
            return None
        if not player.is_variable():
            return int(results[0][score.term].term)
        ret = {}
        for var_dict in results:
            ret[var_dict[player.term].term] = int(var_dict[score.term].term)
        return ret
예제 #11
0
    def score(self, player='?player'):
        '''Return the score for a player this turn.  If player is not
        provided, return a dict of all {player: score}.  If there is no goal
        defined for this player/state, then return None.

        Raise GameError if player does not exist.
        '''
        player = ASTNode.new(player)
        if not player.is_variable() and player.term not in self.players:
            raise GameError(GameError.NO_SUCH_PLAYER % player.term)
        score = ASTNode.new('?score')
        goal = ASTNode.new('goal')
        goal.children = [player, score]
        results = self.db.query(goal)
        if results is False:
            return None
        if not player.is_variable():
            return int(results[0][score.term].term)
        ret = {}
        for var_dict in results:
            ret[var_dict[player.term].term] = int(var_dict[score.term].term)
        return ret
예제 #12
0
    def legal(self, player='?player', move='?move'):
        '''If player and move are provided, return whether or not the move is
        legal this turn.

        If move is not provided, get a list of legal moves for player.

        If neither is provided, return a dict of moves for all players where
        player names are keys.
        '''
        move = self._single_move_to_ast(move)
        player = ASTNode.new(player)
        results = self._legal(player, move)
        if type(results) is bool:
            return results
        elif not player.is_variable():
            return [str(res[move.term]) for res in results]
        ret = {}
        for var_dict in results:
            move_str = str(var_dict[move.term])
            ret.setdefault(var_dict[player.term].term, []).append(move_str)
        return ret
예제 #13
0
    def legal(self, player='?player', move='?move'):
        '''If player and move are provided, return whether or not the move is
        legal this turn.

        If move is not provided, get a list of legal moves for player.

        If neither is provided, return a dict of moves for all players where
        player names are keys.
        '''
        move = self._single_move_to_ast(move)
        player = ASTNode.new(player)
        results = self._legal(player, move)
        if type(results) is bool:
            return results
        elif not player.is_variable():
            return [str(res[move.term]) for res in results]
        ret = {}
        for var_dict in results:
            move_str = str(var_dict[move.term])
            ret.setdefault(var_dict[player.term].term, []).append(move_str)
        return ret
예제 #14
0
 def is_terminal(self):
     '''Query terminal/0.'''
     return self.db.query(ASTNode.new('terminal'))
예제 #15
0
 def _legal(self, player, move):
     '''Query legal/2.  Arguments player and move are ASTNodes.'''
     legal = ASTNode.new('legal')
     legal.children = [player, move]
     return self.db.query(legal)
예제 #16
0
 def is_terminal(self):
     '''Query terminal/0.'''
     return self.db.query(ASTNode.new('terminal'))
예제 #17
0
 def _legal(self, player, move):
     '''Query legal/2.  Arguments player and move are ASTNodes.'''
     legal = ASTNode.new('legal')
     legal.children = [player, move]
     return self.db.query(legal)