def __del__(self): if log_msg: # ccc: it is unclear to me why log_msg == None log_msg('object of type {} deleted'.format(self.__class__.__name__), 10) if class_record: # ccc: it is unclear to me why class_record == None if self.__class__ in class_record: # 671: i don't know why self.__class__ wouldn't be in class_record class_record[self.__class__] -= 1
def __new__(cls, *args, **kwargs): inst = object.__new__(cls) log_msg('created object of type {}'.format(cls.__name__), 10) # keep track of number of instances of each class class_record[cls] = class_record.get(cls, 0) + 1 return inst
def clear_log(): try: writeto = os.path.join(phantom_dir, 'utils', dbgname) with open(writeto, 'w') as f: f.write('') except Exception as e: log_msg('Exception {} in clear_log, unable to clear'.format(exception_str(e)), 1, err=True)
def __del__(self): if log_msg: # ccc: it is unclear to me why log_msg == None log_msg( 'object of type {} deleted'.format(self.__class__.__name__), 10) if class_record: # ccc: it is unclear to me why class_record == None if self.__class__ in class_record: # 671: i don't know why self.__class__ wouldn't be in class_record class_record[self.__class__] -= 1
def validate_move(self, srce, dest): piece = self.board[srce] canmove = piece.is_move_valid(dest) if self.board.cfg.do_checkmate: check = not self.board.will_checkmate(srce, dest) else: check = True log_msg('validatemove: piece={}, check={}, canmove={}'.format( piece, check, canmove), 3) return check and canmove
def validatemove(self, p1, p2): piece = self.board[p1] canmove = piece.is_move_valid(p2) if self.board.cfg.do_checkmate: check = not self.board.will_checkmate(p1, p2) else: check = True log_msg('validatemove: piece={}, check={}, canmove={}'.format( piece, check, canmove), 3) return check and canmove
def validate_move(self, srce, dest): piece = self.board[srce] canmove = piece.is_move_valid(dest) if self.board.cfg.do_checkmate: check = not self.board.will_checkmate(srce, dest) else: check = True log_msg( 'validatemove: piece={}, check={}, canmove={}'.format( piece, check, canmove), 3) return check and canmove
def main(*args): clear_log() log_msg('Phantom beginning self-test', 0, mark=True) testdir = inspect.getfile(main) testdir, dirname = os.path.split(testdir) for f in os.listdir(testdir): if f in (dirname, '__init__.py'): continue else: mn = f[:f.index('.')] m = __import__(mn) m.main(False) log_msg('Phantom self-test complete', 0, mark=True)
def main(clear=True): if clear: clear_log() log_msg('Testing Phantom.ai.pos_eval.advanced.pos_eval_advanced()', 0) for test in list_tests(): log_msg('Beginning pos eval on test {}'.format(test), 0) board = load_test(test) score = None try: score = pos_eval_advanced(board) except Exception as e: log_msg('Advanced position evaluation failed: \n{}'.format(e), 0, err=True) finally: log_msg('Pos eval test on {} complete: score={}'.format(test, score), 0) log_msg('Test complete', 0)
def _spawn_children(node, tree=None): log_msg('_spawn_children({}) starting'.format(node), 4) legal = node.board.all_legal() for piece in legal: try: for move in legal[piece]: new = node.variate(piece.coord, move) newnode = Node(node.depth + 1, (node.depth+1) > maxdepth, new, parent=node) newnode.set_parent(node) if tree: newnode.set_tree(tree) except KeyError: continue log_msg('_spawn_children({}) ending'.format(node), 4)
def _spawn_children(node, tree=None): log_msg('_spawn_children({}) starting'.format(node), 4) legal = node.board.all_legal() for piece in legal: try: for move in legal[piece]: new = node.variate(piece.coord, move) newnode = Node(node.depth + 1, (node.depth + 1) > maxdepth, new, parent=node) newnode.set_parent(node) if tree: newnode.set_tree(tree) except KeyError: continue log_msg('_spawn_children({}) ending'.format(node), 4)
def main(clear=True): if clear: clear_log() log_msg('Testing Phantom.ai.pos_eval.advanced.pos_eval_advanced()', 0) for test in list_tests(): log_msg('Beginning pos eval on test {}'.format(test), 0) board = load_test(test) score = None try: score = pos_eval_advanced(board) except Exception as e: log_msg('Advanced position evaluation failed: \n{}'.format(e), 0, err=True) finally: log_msg( 'Pos eval test on {} complete: score={}'.format(test, score), 0) log_msg('Test complete', 0)
def wrapped(*args, **kwargs): e = None try: f(*args, **kwargs) except Exception as e: #import traceback # uncomment these two lines when looking for hard to find bugs #traceback.print_exc() # prints a full stack trace if e.__class__.__name__ in self.passes: return f(*args, **kwargs) finally: if e: if e.__class__ in self.passes: raise e else: if self.log: fmt = 'exc_catch: caught an unpassed exception - {}:\n {}' log_msg(fmt.format(e.__class__.__name__, e.message), self.log, err=True) return retval
def main(clear=True): from Phantom.utils.debug import log_msg, clear_log from Phantom.core.game_class import load_game # ChessGame if clear: clear_log() log_msg('Testing Phantom.ai.pos_eval.heuristics functions', 0) g = load_game('Game 1') log_msg('Testing AI heuristics on savegame "Game 1":', 0) score = 0 for rule in all_rules: #try: log_msg(rule.__name__ + " evaluating...", 0) r = rule(g.board) log_msg(rule.__name__ + ' returned {}'.format(r), 0) score += r #except Exception as e: # log_msg('{} failed:\n{}'.format(f.__name__, e), 0, err=True) log_msg('Test complete', 0) return score
def exc_catch_wrapped(*args, **kwargs): e = None try: f(*args, **kwargs) except Exception as e: #if exc_catch_cutoff and debug > exc_catch_cutoff: if True: # if debugging, print full tracebacks import traceback traceback.print_exc() # prints a full stack trace if e.__class__.__name__ in self.passes: return f(*args, **kwargs) finally: if e: if e.__class__ in self.passes: raise e else: if self.log: fmt = 'exc_catch: caught an unpassed exception - {}:\n {}' log_msg(fmt.format(e.__class__.__name__, e.message), self.log, err=True) return retval
def main(clear=True): if clear: clear_log() log_msg('Testing Phantom.ai.pos_eval.basic pos_eval_basic() & pos_material()', 0) game = ChessGame() score = material = None try: score = pos_eval_basic(game.board) except Exception as e: log_msg('AI basic position evaluation failed: \n{}'.format(e), 0, err=True) try: material = pos_material(game.board) except Exception as e: log_msg('AI material assesment failed: \n{}'.format(e), 0, err=True) log_msg('Test complete', 0) return score, material
def log_msg(msg, level, **kwargs): err = kwargs.get('err', False) write = kwargs.get('write', True) mark = kwargs.get('mark', False) p = kwargs.get('p', '') if err and mark: mark = False if (level > debug) and (not err): return False ret = True if err: pm = '!' elif mark: pm = 'x' elif p: pm = p[0] else: pm = ' ' msg = pm + msg if len(msg) >= 88: msg = msg[:88] + '\n -' + msg[88:] writeto = os.path.join(phantom_dir, 'utils', dbgname) try: if write: with open(writeto, 'a') as f: f.write(msg + '\n') except Exception as e: log_msg("Exception {} in log_msg, couldn't write to file", level, write=False) ret = False sys.stdout.write("### {}\n".format(msg)) return ret
def _recursive_spawn(node, tree=None): log_msg('_recursive_spawn({}) starting'.format(node), 4) depth = node.depth if depth > maxdepth: log_msg('_recursive_spawn({}) reached depth cutoff'.format(node), 4) return False for child in node.children: _spawn_children(child, tree) _recursive_spawn(child, tree) log_msg('_recursive_spawn({}) ending'.format(node), 4)
def main(clear=True): if clear: clear_log() log_msg('Testing Phantom.core.board.Board.__init__() method', 0) g = None try: g = ChessGame() except Exception as e: log_msg('ChessGame instantiation test failed:\n{}'.format(e), 0, err=True) finally: log_msg('Test complete', 0) return g
def main(clear=True): if clear: clear_log() log_msg('Testing Phantom.core.board.Board.move() method', 0) b = Board() # white to move, opening layout try: b.move('e2e4') b.move('g8f6') b.move('g2g3') except Exception as e: log_msg('Phantom.core.board.Board.move() method test failed:\n{}'.format(e), 0, err=True) finally: log_msg('Test complete', 0)
def check_target(self, target): piece = self.owner.board[target] if not piece: log_msg('check_target: target is None, True', 5) ret = True elif piece.color == self.color: log_msg('check_target: target is same color, False', 5) ret = False else: log_msg('check_target: unknown, True', 5) ret = True return ret
def main(clear=True): if clear: clear_log() log_msg( 'Testing Phantom.ai.pos_eval.basic pos_eval_basic() & pos_material()', 0) game = ChessGame() score = material = None try: score = pos_eval_basic(game.board) except Exception as e: log_msg('AI basic position evaluation failed: \n{}'.format(e), 0, err=True) try: material = pos_material(game.board) except Exception as e: log_msg('AI material assesment failed: \n{}'.format(e), 0, err=True) log_msg('Test complete', 0) return score, material
def main(clear=True): if clear: clear_log() log_msg('Testing Phantom.ai.tree.generate.spawn_tree()', 0) tree = None try: g = ChessGame() tree = spawn_tree(g.board) except Exception as e: log_msg('Phanotm.ai.tree.generate.spawn_tree() test failed:\n{}'.format(e), 0, err=True) finally: log_msg('Test complete', 0) return tree
def main(clear=True): if clear: clear_log() log_msg('Testing Phantom.core.board.Board.move() method', 0) #b = Board(None) # white to move, opening layout b = ChessGame().board try: b.move('e2e4') b.move('g8f6') b.move('g2g3') except Exception as e: log_msg('Phantom.core.board.Board.move() method test failed:\n{}'.format(e), 0, err=True) finally: log_msg('Test complete', 0)
def main(clear=True): if clear: clear_log() log_msg('Testing Phantom.ai.tree.generate.spawn_tree()', 0) tree = None try: g = ChessGame() tree = spawn_tree(g.board) except Exception as e: log_msg( 'Phantom.ai.tree.generate.spawn_tree() test failed:\n{}'.format(e), 0, err=True) finally: log_msg('Test complete', 0) return tree
def main(clear=True): print('=' * 50) from Phantom.core.game_class import ChessGame from Phantom.utils.debug import log_msg, clear_log if clear: clear_log() log_msg('Testing Phantom.ai.tree.generate.spawn_tree()', 0) tree = None try: g = ChessGame() tree = spawn_tree(g.board) except ImportError: #Exception as e: log_msg('Phantom.ai.tree.generate.spawn_tree() test failed:\n{}'.format(e), 0, err=True) finally: log_msg('Test complete', 0) return tree
def main(clear=True): print('=' * 50) from Phantom.core.game_class import ChessGame from Phantom.utils.debug import log_msg, clear_log if clear: clear_log() log_msg('Testing Phantom.ai.tree.generate.spawn_tree()', 0) tree = None try: g = ChessGame() tree = spawn_tree(g.board) except ImportError: #Exception as e: log_msg( 'Phantom.ai.tree.generate.spawn_tree() test failed:\n{}'.format(e), 0, err=True) finally: log_msg('Test complete', 0) return tree
def move(self, p, p2=None): if p2 is None: p1 = Coord.from_chess(p[0:2]) p2 = Coord.from_chess(p[2:]) else: if isinstance(p, str): p1 = Coord.from_chess(p) elif isinstance(p, Coord): p1 = p if isinstance(p2, str): p2 = Coord.from_chess(p2) if self.isfrozen: raise LogicError('Board is frozen and cannot move', 'Phantom.core.board.Board.move()') if self[p1] is None: raise ChessError('No piece at {}'.format(p1), 'Phantom.core.board.Board.move()') self.premove() player = self[p1].owner is_valid = player.validatemove(p1, p2) if is_valid or self.cfg.force_moves: log_msg('move: specified move is valid, continuing', 3) piece = self[p1] # update castling rights if piece.ptype == 'rook': if piece.coord == Coord(0, 0): self.castling_rights = self.castling_rights.replace('Q', '') elif piece.coord == Coord(7, 0): self.castling_rights = self.castling_rights.replace('K', '') elif piece.coord == Coord(0, 7): self.castling_rights = self.castling_rights.replace('q', '') elif piece.coord == Coord(7, 7): self.castling_rights = self.castling_rights.replace('k', '') elif piece.ptype == 'king': if piece.color == 'white': self.castling_rights = self.castling_rights.replace('K', '') self.castling_rights = self.castling_rights.replace('Q', '') elif piece.color == 'black': self.castling_rights = self.castling_rights.replace('k', '') self.castling_rights = self.castling_rights.replace('q', '') # update en_passant rights self.en_passant_rights = '-' if piece.ptype == 'pawn': if piece.firstmove: if round_down(dist(p1, p2)) == 2: file = piece.coord.as_chess()[0] if piece.color == 'black': self.en_passant_rights = '{}6'.format(file) elif piece.color == 'white': self.en_passant_rights = '{}3'.format(file) # update halfmove & fullmove # Here we update the halfmove_clock BEFORE it is altered, to save some else # clauses later on. We simply use a few ifs to determine if it needs to be # reset. self.halfmove_clock += 1 if piece.ptype == 'pawn': self.halfmove_clock = 0 if piece.color == 'black': self.fullmove_clock += 1 target = self[p2] if self.data['move_en_passant']: if self[p1].color == 'white': target = self[p1 - Coord(0, 1)] elif self[p1].color == 'black': target = self[p1 + Coord(0, 1)] self.data['move_en_passant'] = False player.make_move(p1, p2) self.kill(target) self.lastmove = (p1, p2) self.switch_turn() self.postmove() else: self.postmove() log_msg('move: specified move is invalid', 2, err=True) raise InvalidMove('Attempted move ({} -> {}) is invalid!'.format(p1, p2), 'Phantom.core.board.Board.move()') self.unfreeze()
def main(clear=True): if clear: clear_log() log_msg('Beginning Phantom.core.boardio load functions test', 0) try: log_msg('Testing FEN load...', 0) name = listgames()[0] game = load(name) except Exception as e: log_msg('Test failed: {}'.format(e), 0, err=True) finally: log_msg('FEN load test complete.', 0) try: log_msg('Testing EPD load...', 0) name = list_tests()[0] game = load_test(name) except Exception as e: log_msg('Test failed: {}'.format(e), 0, err=True) finally: log_msg('EPD load test complete.', 0) log_msg('Phantom.core.boardio load functions test complete.', 0)
def pawn_structure(board): score = 0 from Phantom.ai.settings import (doubled_pawn, tripled_pawn, isolated_pawn, pawn_ram, eight_pawns, passed_pawn) #from Phantom.core.coord.point import Coord pawns = board.get_piece_list(ptype='pawn') white_pawns = [p for p in pawns if p.color == 'white'] black_pawns = [p for p in pawns if p.color == 'black'] log_msg('pawn_structure: counting pawns...', 5) if len(white_pawns) == 8: score += eight_pawns if len(black_pawns) == 8: score -= eight_pawns log_msg('pawn_structure: finished pawn count score={}'.format(score), 5) log_msg('pawn_structure: analyzing passed pawns...', 5) score += passed_pawn * len([pawn for pawn in white_pawns if pawn.y >= 5]) score -= passed_pawn * len([pawn for pawn in black_pawns if pawn.y <= 2]) log_msg('pawn_structure: finished passed pawns score={}'.format(score), 5) log_msg('pawn_structure: analyzing doubled pawns...', 5) for pawn in white_pawns: for p in list(pawn.north())[:1]: # a list of zero or one items if board[p] in white_pawns: score += doubled_pawn for pawn in black_pawns: for p in list(pawn.south())[:1]: # a list of zero or one items if board[p] in black_pawns: score += doubled_pawn # CCC: should this be minus instead of plus?!? log_msg('pawn_structure: finished doubled pawns score={}'.format(score), 5) log_msg('pawn_structure: analyzing isolated pawns...', 5) iso_white = iso_black = 0 #tests = [Coord(x, y) for x in [-1, 0, 1] for y in [-1, 0, 1]] #tests.remove(Coord(0, 0)) for pawn in pawns: neighbors = (list(pawn.north())[:1] + list(pawn.south())[:1] + list(pawn.east())[:1] + list(pawn.west())[:1] + list(pawn.ne())[:1] + list(pawn.nw())[:1] + list(pawn.sw())[:1] + list(pawn.sw())[:1]) if not [x for x in neighbors if board[x]]: # if no occupied neighbors if pawn.color == 'white': iso_white += 1 else: iso_black += 1 score += isolated_pawn * iso_white score -= isolated_pawn * iso_black log_msg('pawn_structure: finished isolated pawns score={}'.format(score), 5) return score
def main(clear=True): if clear: clear_log() log_msg('Beginning Phantom.core.boardio load functions test', 0) try: log_msg('Testing FEN load...', 0) name = list_games()[0] game = load(name) except Exception as e: log_msg('Test failed: {}'.format(e), 0, err=True) finally: log_msg('FEN load test complete.', 0) try: log_msg('Testing EPD load...', 0) name = list_tests()[0] game = load_test(name) except Exception as e: log_msg('Test failed: {}'.format(e), 0, err=True) finally: log_msg('EPD load test complete.', 0) log_msg('Phantom.core.boardio load functions test complete.', 0)
def wrapped(*args, **kwargs): log_msg('{} called with args ({}, {})'.format(f.__name__, args, kwargs), self.level, p='{') returned = f(*args, **kwargs) log_msg('{} returned {}'.format(f.__name__, returned), self.level, p='}') return returned
def main(clear=True): if clear: clear_log() log_msg('Testing Phantom.ai.pos_eval.heuristics functions', 0) g = ChessGame('Game 1') log_msg('Testing AI heuristics on savegame "Game 1":', 0) score = 0 for rule in all_rules: try: log_msg(rule.__name__ + " evaluating...", 0) r = rule(g.board) log_msg(rule.__name__ + ' returned {}'.format(r), 0) score += r except Exception as e: log_msg('{} failed:\n{}'.format(f.__name__, e), 0, err=True) log_msg('Test complete', 0) return score
def pawn_structure(board): score = 0 from Phantom.ai.settings import (doubled_pawn, tripled_pawn, isolated_pawn, pawn_ram, eight_pawns, passed_pawn) from Phantom.core.coord.point import Coord pawns = board.get_piece_list(ptype='pawn') white_pawns = [p for p in pawns if p.color == 'white'] black_pawns = [p for p in pawns if p.color == 'black'] log_msg('pawn_structure: counting pawns...', 5) if len(white_pawns) == 8: score += eight_pawns if len(black_pawns) == 8: score -= eight_pawns log_msg('pawn_structure: finished pawn count score={}'.format(score), 5) log_msg('pawn_structure: analyzing passed pawns...', 5) score += passed_pawn * len([pawn for pawn in white_pawns if pawn.coord.y >= 5]) score -= passed_pawn * len([pawn for pawn in black_pawns if pawn.coord.y <= 2]) log_msg('pawn_structure: finished passed pawns score={}'.format(score), 5) log_msg('pawn_structure: analyzing doubled pawns...', 5) for pawn in white_pawns: xf = files[pawn.coord.as_chess()[0]] for c in xf: p = pawn.owner.board[c] if (p and p is pawn and p.ptype == 'pawn' and p.color == 'white' and p.coord.y == (pawn.coord.y - 1)): score += doubled_pawn for pawn in black_pawns: xf = files[pawn.coord.as_chess()[0]] for c in xf: p = pawn.owner.board[c] if (p and p is not pawn and p.ptype == 'pawn' and p.color == 'black' and p.coord.y == (pawn.coord.y - 1)): score += doubled_pawn # CCC: should this be minus instead of plus?!? log_msg('pawn_structure: finished doubled pawns score={}'.format(score), 5) log_msg('pawn_structure: analyzing isolated pawns...', 5) iso_white = iso_black = [] tests = [Coord(x, y) for x in [-1, 0, 1] for y in [-1, 0, 1]] tests.remove(Coord(0, 0)) for pawn in pawns: p_c, iso = pawn.coord, True for test in tests: t_c = p_c + test if board[t_c]: iso = False break if iso: if pawn.color == 'white': iso_white.append(pawn) elif pawn.color == 'black': iso_black.append(pawn) score += isolated_pawn * len(iso_white) score -= isolated_pawn * len(iso_black) log_msg('pawn_structure: finished isolated pawns score={}'.format(score), 5) return score