Esempio n. 1
0
def create_base_infos(game_model):
    from ggplib.util.symbols import SymbolFactory
    symbol_factory = SymbolFactory()
    return [
        BaseInfo(idx, symbol_factory.symbolize(s))
        for idx, s in enumerate(game_model.bases)
    ]
Esempio n. 2
0
    def __init__(self, game_info, verbose=False, fast_reset=False):
        self.game_info = game_info
        self.verbose = verbose
        self.fast_reset = fast_reset

        # used to convert to base state
        self.symbol_factory = SymbolFactory()

        self.sm = self.game_info.get_sm()
        self.game = self.game_info.game
        self.match_id = None

        # store a joint move / basestate internally
        self.joint_move = self.sm.get_joint_move()
        self.next_basestate = self.sm.new_base_state()

        # XXX we really shouldn't need to do this... why not just use model??? XXX
        def get_base_tuple(i):
            return tuple(
                self.symbol_factory.to_symbols(game_info.model.bases[i]))[0]

        self.bases = [
            get_base_tuple(i) for i in range(self.next_basestate.len())
        ]

        self.players = []
        self.players_map = {}

        # updated after game is finished
        self.scores = {}

        if verbose:
            log.info("GAMEMASTER: create a gamemaster for game %s" % self.game)

        self.matches = None
Esempio n. 3
0
    def __init__(self, gdl_str, verbose=False, fast_reset=False):
        self.verbose = verbose
        self.fast_reset = fast_reset

        # used to convert to base state
        self.symbol_factory = SymbolFactory()

        self.gdl_str = gdl_str
        _, info = lookup.by_gdl(gdl_str)
        self.sm = info.get_sm()
        self.game = info.game
        self.match_id = None

        # store a joint move / basestate internally
        self.joint_move = self.sm.get_joint_move()
        self.next_basestate = self.sm.new_base_state()

        def get_base_tuple(i):
            return tuple(self.symbol_factory.to_symbols(self.sm.get_gdl(i)))[0]

        self.bases = [get_base_tuple(i) for i in range(self.next_basestate.len())]

        self.players = []
        self.players_map = {}

        # updated after game is finished
        self.scores = {}

        if verbose:
            log.info("GAMEMASTER: create a gamemaster for game %s" % self.game)
        self.matches = None
Esempio n. 4
0
    def print_board(self, sm):
        from ggplib.util.symbols import SymbolFactory

        as_str = self.game_info.model.basestate_to_str(sm.get_current_state())

        sf = SymbolFactory()
        states = sf.to_symbols(as_str)

        control = None
        board_map = {}

        for s in list(states):
            base = s[1]
            if base[0] == "control":
                control = base[1]
            elif base[0] == "cell":
                key = "abcdefghijklmnop".index(base[1]) + 1, int(base[2]),
                board_map[key] = base[3]

        board_size = self.size
        lines = []
        line_len = board_size * 2 + 1

        def indent(y):
            return y * ' '

        lines.append("    %s +" % indent(0) + "-" * line_len + "+")
        for i in range(board_size):
            y = i + 1
            ll = [" %2d %s \\" % (y, indent(y))]

            for j in range(board_size):
                x = j + 1
                key = x, y
                if key in board_map:
                    if board_map[key] == "black":
                        ll.append(" %s" % u"\u26C0")
                    else:
                        assert board_map[key] == "white"
                        ll.append(" %s" % u"\u26C2")
                else:
                    ll.append(" .")

            lines.append("".join(ll) + " \\")

        lines.append("   %s  +" % indent(board_size + 1) + "-" * line_len +
                     "+")
        lines.append("   %s   " % indent(board_size + 1) +
                     ' '.join('%s' % c
                              for c in 'abcdefghijklmnopqrs'[:board_size]))

        print
        print
        print "\n".join(lines)
        print "Control:", control
Esempio n. 5
0
def pretty_board(board_size, sm):
    ' pretty print board current state of match '

    from ggplib.util.symbols import SymbolFactory
    as_str = get_game_info(board_size).model.basestate_to_str(
        sm.get_current_state())
    sf = SymbolFactory()
    states = sf.to_symbols(as_str)
    mapping = {}
    control = None
    for s in list(states):
        if s[1][0] == "control":
            control = s[1][1]
        else:
            if board_size != 6:
                assert s[1][0] == "cellHolds"
            else:
                assert s[1][0] == "cell"

            key = int(s[1][1]), int(s[1][2])
            mapping[key] = s[1][3]

    lines = []
    line_len = board_size * 4 + 1
    lines.append("    +" + "-" * (line_len - 2) + "+")
    for i in reversed(range(1, board_size + 1)):
        ll = [" %s  |" % i]
        for j in reversed(range(1, board_size + 1)):
            key = j, i
            if key in mapping:
                if mapping[key] == "black":
                    ll.append(" %s |" % u"\u2659")
                else:
                    assert mapping[key] == "white"
                    ll.append(" %s |" % u"\u265F")
            else:
                ll.append("   |")

        lines.append("".join(ll))
        if i > 1:
            lines.append("    " + "-" * line_len)

    lines.append("    +" + "-" * (line_len - 2) + "+")
    if board_size == 8:
        lines.append("     " + ' '.join(' %s ' % c for c in 'abcdefgh'))
    else:
        lines.append("     " + ' '.join(' %s ' % c for c in 'abcdef'))

    print
    print
    print "\n".join(lines)
    print "Control:", control
Esempio n. 6
0
def symbolize(txt, pos):
    global symbol_factory
    if symbol_factory is None:
        symbol_factory = SymbolFactory()

    symbols = symbol_factory.symbolize(txt)
    symbols = symbols[pos]

    # convert terms to lists - make things simpler knowing it is a list of size 1+
    if isinstance(symbols, Term):
        return ListTerm((symbols, ))

    return symbols
Esempio n. 7
0
def pretty_board(board_size, sm):
    assert board_size == 8 or board_size == 10
    game_info = lookup.by_name(
        "reversi") if board_size == 8 else lookup.by_name("reversi_10x10")

    from ggplib.util.symbols import SymbolFactory
    as_str = game_info.model.basestate_to_str(sm.get_current_state())
    sf = SymbolFactory()
    print list(sf.to_symbols(as_str))

    mapping = {}
    control = None
    for s in sf.to_symbols(as_str):
        if s[1][0] == "control":
            control = s[1][1]
        else:
            assert s[1][0] == "cell"

            key = int(s[1][1]), int(s[1][2])
            mapping[key] = s[1][3]

    lines = []
    line_len = board_size * 4 + 1
    lines.append("     +" + "-" * (line_len - 2) + "+")
    for i in reversed(range(1, board_size + 1)):
        ll = [" %2s  |" % i]
        for j in reversed(range(1, board_size + 1)):
            key = j, i
            if key in mapping:
                if mapping[key] == "black":
                    ll.append(" %s |" % u"\u2659")
                else:
                    assert mapping[key] in ("red", "white")
                    ll.append(" %s |" % u"\u265F")
            else:
                ll.append("   |")

        lines.append("".join(ll))
        if i > 1:
            lines.append("     " + "-" * line_len)

    lines.append("     +" + "-" * (line_len - 2) + "+")
    if board_size == 8:
        lines.append("      " + ' '.join(' %s ' % c for c in 'abcdefgh'))
    else:
        lines.append("      " + ' '.join(' %s ' % c for c in 'abcdef'))

    print
    print
    print "\n".join(lines)
    print "Control:", control
Esempio n. 8
0
def pretty_board(sm):
    ' pretty print board current state of match '
    from ggplib.util.symbols import SymbolFactory

    lines = []
    for i, value in enumerate(sm.get_current_state().to_list()):
        if value:
            lines.append(sm.get_gdl(i))

    sf = SymbolFactory()
    states = sf.to_symbols("\n".join(lines))
    mapping = {}
    control = None
    for s in list(states):
        if s[1][0] == "control":
            control = s[1][1]
        else:
            assert s[1][0] == "cell"
            key = int(s[1][1]), int(s[1][2])
            mapping[key] = s[1][3]

    board_size = 6

    lines = []
    line_len = board_size * 4 + 1
    lines.append("    +" + "-" * (line_len - 2) + "+")
    for i in reversed(range(1, board_size + 1)):
        ll = [" %s  |" % i]
        for j in reversed(range(1, board_size + 1)):
            key = j, i
            if key in mapping:
                if mapping[key] == "black":
                    ll.append(" %s |" % u"\u2659")
                else:
                    assert mapping[key] == "white"
                    ll.append(" %s |" % u"\u265F")
            else:
                ll.append("   |")

        lines.append("".join(ll))
        if i > 1:
            lines.append("    " + "-" * line_len)

    lines.append("    +" + "-" * (line_len - 2) + "+")
    lines.append("     " + ' '.join(' %s ' % c for c in 'abcdef'))

    print
    print
    print "\n".join(lines)
    print "Control:", control
Esempio n. 9
0
    def print_board(self, sm):
        from ggplib.util.symbols import SymbolFactory

        as_str = self.game_info.model.basestate_to_str(sm.get_current_state())

        sf = SymbolFactory()
        states = sf.to_symbols(as_str)

        control = None
        board_map = {}

        for s in list(states):
            base = s[1]
            if base[0] == "control":
                control = base[1]
            elif base[0] == "cell":
                key = int(base[1]), int(base[2])
                board_map[key] = base[3]

        board_size = 19
        lines = []
        line_len = board_size * 2 + 1
        lines.append("     +" + "-" * line_len + "+")

        for y in range(board_size, 0, -1):
            ll = [" %2d  |" % y]
            for j in range(board_size):
                x = j + 1
                key = x, y
                if key in board_map:
                    if board_map[key] == "black":
                        ll.append(" %s" % u"\u26C0")
                    else:
                        assert board_map[key] == "white"
                        ll.append(" %s" % u"\u26C2")
                else:
                    ll.append(" .")

            lines.append("".join(ll) + " |")

        lines.append("     +" + "-" * line_len + "+")
        lines.append("       " + ' '.join('%s' % c
                                          for c in 'abcdefghijklmnopqrs'))

        print
        print
        print "\n".join(lines)
        print "Control:", control
Esempio n. 10
0
    def print_board(self, sm):
        as_str = self.game_info.model.basestate_to_str(sm.get_current_state())
        print as_str

        sf = SymbolFactory()
        states = sf.to_symbols(as_str)

        control = None
        board_map = {}

        for s in list(states):
            base = s[1]
            if base[0] == "control":
                control = base[1]
            elif base[0] == "cell":
                key = int(base[1]), int(base[2])
                board_map[key] = base[3]

        def row(i):
            yield ' '
            for j in range(10, 0, -1):
                key = j, i
                if key in board_map:
                    if board_map[key] == "arrow":
                        yield " %s " % u"\u25C8"

                    elif board_map[key] == "black":
                        yield " B "

                    else:
                        assert board_map[key] == "white"
                        yield " W "

                else:
                    yield ' . '

        def lines():
            for i in range(10, 0, -1):
                yield "".join(row(i))

        print
        print
        print "\n".join(lines())
        print "Control:", control
Esempio n. 11
0
def determine_legals(game):
    factory = SymbolFactory()

    def grouper(action, group_by):
        if isinstance(action, Term):
            base, ary = (str(action), 0)
        else:
            base, ary = (str(action[0]), len(action) - 1)

        key = (base, ary)
        if key not in group_by:
            domains = group_by[key] = []
            for i in range(ary):
                domains.append(set())
        else:
            domains = group_by[key]

        for i in range(ary):
            domains[i].add(action[i+1])

        return base, ary, domains

    game_model = lookup.by_name(game).model
    for ri, role in enumerate(game_model.roles):

        group_by_role = {}
        print "doing role", role

        for a in game_model.actions[ri]:
            action = factory.symbolize(a)
            assert action[0] == "does"
            assert action[1] == role, "%s != %s" % (action[1], role)
            action = action[2]

            grouper(action, group_by_role)

        print group_by_role
Esempio n. 12
0
class GGPServer(Resource):
    ''' a server deal withs the ggp web service like protocol.  It has only one player, which is
      passed into each new match. '''

    symbol_factory = SymbolFactory()
    current_match = None
    player = None
    last_info_time = 0
    info_counts = 0

    timeout_deferred = None

    def set_player(self, player):
        self.player = player

    def getChild(self, *args):
        return self

    def render_GET(self, request):
        log.debug("Got GET request from: %s" % request.getClientIP())
        return self.handle(request)

    def render_POST(self, request):
        # log.debug("Got POST request from: %s" % request.getClientIP())
        # log.debug("HEADERS : %s" % pprint.pformat(request.getAllHeaders()))

        res = self.handle(request)
        res = res.replace('(', ' ( ').replace(')', ' ) ')

        # 'CORS' - stuff I don't understand.  Was needed to run standford 'player checker'.
        request.setHeader('Access-Control-Allow-Origin', '*')
        request.setHeader('Access-Control-Allow-Methods', 'GET')
        request.setHeader('Access-Control-Allow-Headers',
                          'x-prototype-version,x-requested-with')
        request.setHeader('Access-Control-Max-Age', 2520)
        request.setHeader('Content-type', 'application/json')

        return res

    def handle(self, request):
        content = request.content.getvalue()

        # Tiltyard seems to ping with empty content...
        if content == "":
            return self.handle_info()

        try:
            symbols = list(self.symbol_factory.symbolize(content))

            # get head
            if len(symbols) == 0:
                log.warning('Empty symbols')
                return self.handle_info()

            head = symbols[0]
            if head.lower() == "info":
                res = self.handle_info()

            elif head.lower() == "start":
                log.debug("HEADERS : %s" % pprint.pformat(request.getAllHeaders()))
                log.debug(str(symbols))
                res = self.handle_start(symbols)

            elif head.lower() == "play":
                log.debug(str(symbols))
                res = self.handle_play(symbols)

            elif head.lower() == "stop":
                log.debug(str(symbols))
                res = self.handle_stop(symbols)

            elif head.lower() == "abort":
                log.debug(str(symbols))
                res = self.handle_abort(symbols)

            else:
                log.error("UNHANDLED REQUEST %s" % symbols)

        except Exception as exc:
            log.error("ERROR - aborting: %s" % exc)
            log.error(traceback.format_exc())

            if self.current_match:
                self.abort()

            res = "aborted"

        return res

    def handle_info(self):
        cur_time = time.time()

        # do info_counts or we get reports of "0 infos in the last minute"
        self.info_counts += 1
        if cur_time - self.last_info_time > 60:
            log.debug("Got %s infos in last minute" % self.info_counts)
            self.info_counts = 0
            self.last_info_time = cur_time

        if self.current_match is None:
            return "((name %s) (status available))" % self.player.get_name()
        else:
            return "((name %s) (status busy))" % self.player.get_name()

    def handle_start(self, symbols):
        assert len(symbols) == 6
        match_id = symbols[1]
        role = symbols[2]
        gdl = symbols[3]
        meta_time = int(symbols[4])
        move_time = int(symbols[5])

        if self.current_match is not None:
            log.debug("GOT A START message for %s while already playing match" % match_id)
            return "busy"
        else:
            log.info("Starting new match %s" % match_id)
            self.current_match = match.Match(match_id, role, meta_time, move_time, self.player, gdl, cushion_time=CUSHION_TIME)
            try:
                # start gameserver timeout
                self.update_gameserver_timeout(self.current_match.meta_time)

                self.current_match.do_start()
                return "ready"

            except match.BadGame:
                return "busy"

    def handle_play(self, symbols):
        assert len(symbols) == 3
        match_id = symbols[1]
        if self.current_match is None:
            log.warning("rx'd play for non-current match %s" % match_id)
            return "busy"
        if self.current_match.match_id != match_id:
            log.error("rx'd play different from current match (%s != %s)" % (match_id, self.current_match.match_id))
            return "busy"

        move = symbols[2]

        if isinstance(move, ListTerm):
            move = list(move)
        else:
            assert move.lower() == 'nil', "Move is %s" % move
            move = None

        # update gameserver timeout
        self.update_gameserver_timeout(self.current_match.move_time)
        return self.current_match.do_play(move)

    def handle_stop(self, symbols):
        assert len(symbols) == 3
        match_id = symbols[1]
        if self.current_match is None:
            log.warning("rx'd 'stop' for non-current match %s" % match_id)
            return "busy"
        if self.current_match.match_id != match_id:
            log.error("rx'd 'stop' different from current match (%s != %s)" % (match_id, self.current_match.match_id))
            return "busy"

        move = symbols[2]

        # XXX bug with standford 'player checker'??? XXX need to find out what is going on here?
        if isinstance(move, str) and move.lower != "nil":
            move = self.symbol_factory.symbolize("( %s )" % move)

        res = self.current_match.do_play(move)
        if res != "done":
            log.error("Game was NOT done %s" % self.current_match.match_id)

        else:
            # cancel any timeout callbacks
            self.update_gameserver_timeout(None)
            self.current_match.do_stop()

        self.current_match = None
        return "done"

    def handle_abort(self, symbols):
        assert len(symbols) == 2
        match_id = symbols[1]

        if self.current_match is None:
            log.warning("rx'd 'abort' for non-current match %s" % match_id)
            return "busy"

        if self.current_match.match_id != match_id:
            log.error("rx'd 'abort' different from current match (%s != %s)" % (match_id, self.current_match.match_id))
            return "busy"

        # cancel any timeout callbacks
        self.abort()
        return "aborted"

    def abort(self):
        assert self.current_match is not None

        try:
            res = self.current_match.do_abort()
        except Exception as exc:
            log.critical("CRITICAL ERROR - during abort: %s" % exc)
            log.critical(traceback.format_exc())

        # always set it none
        self.current_match = None

        # and cancel any timeouts
        self.update_gameserver_timeout(None)

    def update_gameserver_timeout(self, wait_time):
        # cancel the current timeout
        if self.timeout_deferred is not None:
            self.timeout_deferred.cancel()
            self.timeout_deferred = None

        if wait_time is not None:
            when_time = wait_time + GAMESERVER_TIMEOUT
            self.timeout_deferred = task.deferLater(reactor, when_time, self.gameserver_timeout)

    def gameserver_timeout(self):
        log.critical("Timeout from server - forcing aborting")

        if self.current_match:
            self.current_match.do_abort()
            self.current_match = None

        self.timeout_deferred = None
Esempio n. 13
0
from ggplib.player.gamemaster import GameMaster

from ggplib.db import lookup
from ggplib.db.helper import get_gdl_for_game

from ggpzero.util import attrutil

from ggpzero.defs import templates

from ggpzero.player.cpuctplayer import CppPUCTPlayer

from ggpzero.tournament.confs import TiltyardMatchSummary, TiltyardMatch, MatchSummaries


from ggplib.util.symbols import SymbolFactory
symbol_factory = SymbolFactory()


def setup():
    from ggplib.util.init import setup_once
    setup_once()

    from ggpzero.util.keras import init
    init()


games_to_url = {
    "breakthrough" : "http://games.ggp.org/base/games/breakthrough/v0/",
    "cittaceot" : "http://games.ggp.org/base/games/cittaceot/v0/",
    "checkers" : "http://games.ggp.org/base/games/checkers/v1/",
    "connectFour" : "http://games.ggp.org/base/games/connectFour/v0/",
Esempio n. 14
0
class GameMaster(object):
    def __init__(self, game_info, verbose=False, fast_reset=False):
        self.game_info = game_info
        self.verbose = verbose
        self.fast_reset = fast_reset

        # used to convert to base state
        self.symbol_factory = SymbolFactory()

        self.sm = self.game_info.get_sm()
        self.game = self.game_info.game
        self.match_id = None

        # store a joint move / basestate internally
        self.joint_move = self.sm.get_joint_move()
        self.next_basestate = self.sm.new_base_state()

        # XXX we really shouldn't need to do this... why not just use model??? XXX
        def get_base_tuple(i):
            return tuple(
                self.symbol_factory.to_symbols(game_info.model.bases[i]))[0]

        self.bases = [
            get_base_tuple(i) for i in range(self.next_basestate.len())
        ]

        self.players = []
        self.players_map = {}

        # updated after game is finished
        self.scores = {}

        if verbose:
            log.info("GAMEMASTER: create a gamemaster for game %s" % self.game)

        self.matches = None

    def create_match_id(self):
        return "a_%s_match_id_%d" % (self.game, random.randint(0, 100000))

    def add_player(self, player, role):
        self.players.append((player, role))
        self.players_map[role] = player

    def get_player(self, role_index):
        return self.players[role_index][0]

    def get_score(self, role):
        return self.scores[role]

    def get_game_depth(self):
        # ask the first match what the depth is
        if self.matches:
            return self.matches[0].game_depth
        else:
            return -1

    def convert_to_base_state(self, state_str):
        state_set = set()
        for state in self.symbol_factory.to_symbols(state_str):
            state_set.add(state)

        bs = self.sm.new_base_state()
        for i in range(bs.len()):
            # we try both with 'x' and without '(true x)'
            if self.bases[i] in state_set or self.bases[i][1] in state_set:
                bs.set(i, 1)
            else:
                bs.set(i, 0)

        return bs

    def reset(self):
        self.scores = {}
        if not self.fast_reset:
            self.matches = None

    def start(self,
              meta_time=10,
              move_time=5,
              initial_basestate=None,
              game_depth=0):
        self.match_id = self.create_match_id()

        assert self.players

        if initial_basestate is not None:
            # update the state machine
            self.sm.update_bases(initial_basestate)

            # check the game isn't finished
            assert not self.sm.is_terminal()
        else:
            # reset state machine, returns it to initial state.
            self.sm.reset()

        if self.matches is None:
            player_matches = []
            for player, role in self.players:

                match = Match(self.game_info,
                              self.match_id,
                              role,
                              meta_time,
                              move_time,
                              player,
                              verbose=self.verbose,
                              no_cleanup=True)

                player_matches.append(match)

                # call do start...
                if self.verbose:
                    log.verbose("Starting for %s / %s" %
                                (match.role, match.player))
                match.do_start(initial_basestate=initial_basestate,
                               game_depth=game_depth)

            # reorder matches to roles (and check that we have them)
            self.matches = []
            for role in self.sm.get_roles():
                for match in player_matches:
                    if role == match.role:
                        self.matches.append(match)
                        break

            assert len(self.matches) == len(self.sm.get_roles())
        else:
            for (player, role), match in zip(self.players, self.matches):
                match.fast_reset(self.match_id, player, role)
                match.do_start(initial_basestate=initial_basestate,
                               game_depth=game_depth)

    def play_single_move(self, last_move=None):
        assert not self.finished()

        actions = []
        new_last_move = []
        for role_index, (match, role) in enumerate(
                zip(self.matches, self.sm.get_roles())):

            if self.verbose:
                log.verbose(
                    "==============================================================="
                )
                log.verbose("do_play(%s) for %s / %s" %
                            (last_move, role, match.player.get_name()))
            move = match.do_play(last_move)
            new_last_move.append(move)

            # check the move is in the legals
            ls = self.sm.get_legal_state(role_index)
            choices = [ls.get_legal(ii) for ii in range(ls.get_count())]

            for choice in choices:
                choice_move = self.sm.legal_to_move(role_index, choice)

                if choice_move == move:
                    self.joint_move.set(role_index, choice)
                    actions.append(move)
                    break

        assert len(actions) == len(self.matches)
        if self.verbose:
            log.verbose("playing %s" % (actions, ))

        self.sm.next_state(self.joint_move, self.next_basestate)
        self.sm.update_bases(self.next_basestate)

        return tuple(new_last_move)

    def finished(self):
        return self.sm.is_terminal()

    def finalise_match(self, last_move):
        if self.verbose:
            log.verbose("Played to depth %d" % self.get_game_depth())
            log.verbose("Last move %s" % (last_move, ))

        for ri, role in enumerate(self.sm.get_roles()):
            score = self.sm.get_goal_value(ri)
            self.scores[role] = score
            if self.verbose:
                log.verbose("Final score for %s : %s " % (role, score))

        # Need to do the final move for player
        for match in self.matches:
            assert match.do_play(last_move) == "done"

            # and stop them
            match.do_stop()

    def play_to_end(self, last_move=None):
        while not self.finished():
            last_move = self.play_single_move(last_move)

        self.finalise_match(last_move)

    def cleanup(self, keep_sm=False):
        if self.next_basestate:
            interface.dealloc_basestate(self.next_basestate)
            self.next_basestate = None

        if self.joint_move:
            interface.dealloc_jointmove(self.joint_move)
            self.joint_move = None

        if not keep_sm and self.sm:
            interface.dealloc_statemachine(self.sm)
            self.sm = None
Esempio n. 15
0
def get_index(gdl_str, verbose=False):
    factory = SymbolFactory()
    ruleset = list(factory.to_symbols(gdl_str))

    # XXX bah, only works if rules/facts are in same order
    fact_db = OrderedDict()
    rule_db = OrderedDict()
    for lit in root_constants:
        fact_db[lit] = []
        rule_db[lit] = []

    for fact in facts(ruleset):
        assert isinstance(fact, ListTerm)
        name = fact[0]
        f = Fact(name, list(fact[1:]))
        fact_db.setdefault(name, []).append(f)

    for rule in rules(ruleset):
        assert isinstance(rule, ListTerm)
        head = rule[1]
        if isinstance(head, ListTerm):
            name = head[0]
        else:
            name = head
        r = Rule(head, factory.create(ListTerm, rule[2:]))
        rule_db.setdefault(name, []).append(r)

    if verbose:
        print "FACTS:"
        for lit in root_constants:
            print "%s:" % lit
            pprint.pprint(fact_db[lit])

        for h, b in fact_db.items():
            if h not in root_constants:
                print "%s:" % h
                pprint.pprint(fact_db[h])

        print "RULES:"
        for lit in root_constants:
            print "%s:" % lit
            pprint.pprint(rule_db[lit])

        for h, b in rule_db.items():
            if h not in root_constants:
                print "%s:" % h
                pprint.pprint(rule_db[h])

    sig = SignatureFactory()
    for lit in root_constants:
        for f in fact_db[lit]:
            sig.add_fact(f)

    for h, b in fact_db.items():
        if h not in root_constants:
            for f in fact_db[h]:
                sig.add_fact(f)

    for lit in root_constants:
        for r in rule_db[lit]:
            sig.add_rule(r)

    for h, b in rule_db.items():
        if h not in root_constants:
            for r in rule_db[h]:
                sig.add_rule(r)

    if verbose:
        print "Signature:"
        pprint.pprint(sig)

    hashed_sigs = []
    for s in sig.sigs:
        if verbose:
            print s, s.zero_sig_hash

        hashed_sigs.append(s.zero_sig_hash)
    hashed_sigs.sort()
    final_value = hash(tuple(hashed_sigs))

    # this is a reconstruct phase (testing)
    return final_value, sig