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) ]
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 __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
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
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
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
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
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
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
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
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
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
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/",
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
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