class ValuatingTicTacToeAI(Player): def stringify(self, pos): return chr(pos[1] + 97) + chr(pos[0] + 49) def compute_move(self, game): me = game.current_player() + 1 valuation = [[0 for _ in range(3)] for _ in range(3)] for r, c in [(r, c) for r in range(3) for c in range(3)]: if game.board[r][c]: valuation[r][c] -= 100000 positions = [[((i, j), game.board[i][j]) for j in range(3)] for i in range(3)] lanes = chain(positions, zip(*positions), [[row[i] for i, row in enumerate(positions)], [list(reversed(row))[i] for i, row in enumerate(positions)]]) lanes = list(lanes) for lane in lanes: values = [x[1] for x in lane] counts = (values.count(me), values.count(me % 2 + 1), values.count(0)) points = {(2, 0, 1) : 10000, (0, 2, 1) : 1000, (1, 0, 2) : 100, (0, 0, 3) : 10, (0, 1, 2) : 1,} for pos, _ in lane: valuation[pos[0]][pos[1]] += points.get(counts, 0) best = -1 moves = [] for r, c in [(r, c) for r in range(3) for c in range(3)]: if valuation[r][c] == best: moves.append((r,c)) elif valuation[r][c] > best: moves = [(r,c)] best = valuation[r][c] if not moves: raise RuntimeError("No moves left") return self.stringify(choice(moves))