File size: 59,078 Bytes
08932e7
1
{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.14","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":86524,"databundleVersionId":9818394,"sourceType":"competition"},{"sourceId":167505,"sourceType":"modelInstanceVersion","modelInstanceId":142488,"modelId":154485}],"dockerImageVersionId":30786,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# **Active Graph Theory: A Revolutionary Approach to Contextual AI**\n\n### **Overview**\nThis notebook is an exploration of **Active Graph Theory (AGT)** and its application in solving complex, context-driven problems. While framed within the context of a chess AI challenge, the principles demonstrated here have far-reaching implications across data science, artificial intelligence, and beyond.\n\n\n\n**Active Graph Theory (AGT)** represents a shift from brute-force and static data analysis to **dynamic, contextual reasoning.** By leveraging principles like **Dynamic Relationship Expansion (DRE)** and **Active Cube Theory**, this framework enables a system to:\n- Dynamically infer relationships without pretraining on massive datasets.\n- Contextualize data in real-time, adapting to evolving environments.\n- Solve problems efficiently by mimicking natural decision-making processes.\n\nThis isn’t just about playing chess—it’s about **redefining how data interacts with logic and inference** in ways that mirror the adaptability of human thought.\n\n---\n\n### **A Unique Process**\nThis notebook may not follow the traditional structure you might expect from a polished machine learning project. Instead, it reflects my **iterative, first-principles approach**:\n- I solve problems by building frameworks from the ground up, not by starting with existing models or theories.\n- My process naturally intersects with broader principles like Einstein’s **Theory of Relativity**, graph theory, and logical structures, but these are **outcomes, not starting points.**\n\nWhile the code and structure may appear unconventional at times, it is a direct representation of my thought process—fueled by experimentation, iteration, and an unrelenting curiosity.\n\n---\n\n### **Why This Matters**\nWhat you’ll see here is not just a chess bot; it’s a demonstration of a universal framework:\n- **Dynamic Contextual Inference**: The bot prioritizes moves based on relationships and real-time game dynamics rather than brute-force simulations.\n- **Transferable Ideas**: The principles applied here can be extended to fields like fraud detection, real-time decision systems, and even physics simulations.\n- **Efficiency at Scale**: AGT does not rely on GPU-intensive training but instead uses structured logic to infer outcomes dynamically.\n\nThe chess bot is simply the beginning—a demonstration of what happens when data, relationships, and context converge in meaningful ways.\n\n---\n\n### **Acknowledgments**\nThis work represents countless hours of iteration, experimentation, and collaboration. While the ideas here are my own, I want to acknowledge the modern tools that have facilitated this journey, including **ChatGPT**, which has acted as a collaborator, bouncing ideas and helping refine this framework.\n\nThis notebook is a testament to what can be achieved when curiosity meets persistence. I hope you enjoy exploring this work as much as I’ve enjoyed creating it.\n\n---\n\n### **A Note on Structure**\nThis notebook might feel unconventional. It wasn’t designed to impress with perfect organization but to showcase the raw process of discovery and problem-solving. Every section reflects my iterative journey—an honest look at how breakthroughs are made.\n\n---\n\n### **Let’s Begin**\nWhat follows is an application of **Active Graph Theory** in the context of a chess AI. Beneath the moves, algorithms, and code is a deeper story of how data can be understood, structured, and leveraged to create systems that think dynamically. Let’s dive in.","metadata":{}},{"cell_type":"code","source":"from IPython.display import HTML\n\n# List of YouTube video URLs\nvideo_urls = [\n    \"https://www.youtube.com/embed/YwxHNlEc2hU\",  # First video\n    \"https://www.youtube.com/embed/_dqUJch3PF8\",  # Second video\n    \"https://www.youtube.com/embed/noUThX4Tnnk\",  # Third video\n    \"https://www.youtube.com/embed/AI90-uL5Hf4\"   # Fourth video\n]\n\n# Initialize an empty string to hold the HTML\nhtml_content = '<div align=\"center\">'\n\n# Loop through each video URL and create an iframe for each\nfor url in video_urls:\n    html_content += f'<iframe align=\"middle\" width=\"790\" height=\"440\" src=\"{url}\" title=\"Video\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe><br>'\n\n# Close the div tag\nhtml_content += '</div>'\n\n# Display the HTML content\nHTML(html_content)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-22T22:39:01.525720Z","iopub.execute_input":"2024-11-22T22:39:01.526094Z","iopub.status.idle":"2024-11-22T22:39:01.534187Z","shell.execute_reply.started":"2024-11-22T22:39:01.526060Z","shell.execute_reply":"2024-11-22T22:39:01.533143Z"}},"outputs":[{"execution_count":3,"output_type":"execute_result","data":{"text/plain":"<IPython.core.display.HTML object>","text/html":"<div align=\"center\"><iframe align=\"middle\" width=\"790\" height=\"440\" src=\"https://www.youtube.com/embed/YwxHNlEc2hU\" title=\"Video\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe><br><iframe align=\"middle\" width=\"790\" height=\"440\" src=\"https://www.youtube.com/embed/_dqUJch3PF8\" title=\"Video\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe><br><iframe align=\"middle\" width=\"790\" height=\"440\" src=\"https://www.youtube.com/embed/noUThX4Tnnk\" title=\"Video\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe><br><iframe align=\"middle\" width=\"790\" height=\"440\" src=\"https://www.youtube.com/embed/AI90-uL5Hf4\" title=\"Video\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe><br></div>"},"metadata":{}}],"execution_count":3},{"cell_type":"markdown","source":"# FIDE & Google Efficient Chess AI Challenge\n\nWelcome! This notebook will familiarize you with using competition's environment, creating an agent, and submitting your first chess bot!","metadata":{}},{"cell_type":"code","source":"# first let's make sure you have internet enabled\nimport requests\nrequests.get('http://www.google.com',timeout=10).ok","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T20:33:27.729299Z","iopub.execute_input":"2024-11-21T20:33:27.729570Z","iopub.status.idle":"2024-11-21T20:33:27.779742Z","shell.execute_reply.started":"2024-11-21T20:33:27.729544Z","shell.execute_reply":"2024-11-21T20:33:27.778778Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"#### If you don't have internet access (it doesn't say \"True\" above)\n1. make sure your account is Phone Verified in [account settings](https://www.kaggle.com/settings)\n2. make sure internet is turned on in Settings -> Turn on internet","metadata":{}},{"cell_type":"code","source":"%%capture\n# ensure we are on the latest version of kaggle-environments\n!pip install --upgrade kaggle-environments","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T20:33:27.782738Z","iopub.execute_input":"2024-11-21T20:33:27.783079Z","iopub.status.idle":"2024-11-21T20:33:37.419883Z","shell.execute_reply.started":"2024-11-21T20:33:27.783046Z","shell.execute_reply":"2024-11-21T20:33:37.418502Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Now let's set up the chess environment!\nfrom kaggle_environments import make\nenv = make(\"chess\", debug=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T20:33:37.421549Z","iopub.execute_input":"2024-11-21T20:33:37.421889Z","iopub.status.idle":"2024-11-21T20:33:37.467042Z","shell.execute_reply.started":"2024-11-21T20:33:37.421857Z","shell.execute_reply":"2024-11-21T20:33:37.465975Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# this should run a game in the environment between two random bots\n# NOTE: each game starts from a randomly selected opening\nresult = env.run([\"random\", \"random\"])\nenv.render(mode=\"ipython\", width=1000, height=1000) ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T20:33:37.468833Z","iopub.execute_input":"2024-11-21T20:33:37.469223Z","iopub.status.idle":"2024-11-21T20:33:44.761251Z","shell.execute_reply.started":"2024-11-21T20:33:37.469190Z","shell.execute_reply":"2024-11-21T20:33:44.760235Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Creating your first agent\nNow let's create your first agent! The environment has the [Chessnut](https://github.com/cgearhart/Chessnut) pip package installed and we'll use that to parse the board state and generate moves.","metadata":{}},{"cell_type":"code","source":"%%writefile main.py\nfrom Chessnut import Game\nimport random\n\n# Piece values for material evaluation\nPIECE_VALUES = {\n    \"p\": 1, \"n\": 3, \"b\": 3, \"r\": 5, \"q\": 9, \"k\": 0,\n    \"P\": -1, \"N\": -3, \"B\": -3, \"R\": -5, \"Q\": -9, \"K\": 0\n}\n\nCENTER_SQUARES = {\"d4\", \"d5\", \"e4\", \"e5\"}\n\ndef debug(message):\n    \"\"\"\n    Utility function for debugging.\n    \"\"\"\n    print(f\"DEBUG: {message}\")\n\ndef prioritize_moves(game, moves):\n    \"\"\"\n    Prioritize moves based on first principles.\n    \"\"\"\n    prioritized_moves = []\n\n    for move in moves:\n        piece = game.board.get_piece(Game.xy2i(move[:2]))\n        target_square = move[2:4]\n        target_piece = game.board.get_piece(Game.xy2i(target_square))\n\n        # Checkmate moves (highest priority)\n        g = Game(game.get_fen())\n        g.apply_move(move)\n        if g.status == Game.CHECKMATE:\n            debug(f\"Checkmate move found: {move}\")\n            return [move]\n\n        # Captures (next priority)\n        if target_piece != ' ':\n            debug(f\"Capture move: {move}, Captures: {target_piece}\")\n            prioritized_moves.append((move, 3 + PIECE_VALUES.get(target_piece.lower(), 0)))\n\n        # Central control (medium priority)\n        elif target_square in CENTER_SQUARES:\n            debug(f\"Central control move: {move}\")\n            prioritized_moves.append((move, 2))\n\n        # Development of knights and bishops (early-game priority)\n        elif piece.lower() in {'n', 'b'}:\n            debug(f\"Development move: {move}\")\n            prioritized_moves.append((move, 1))\n\n        # Default: Other moves (low priority)\n        else:\n            prioritized_moves.append((move, 0))\n\n    # Sort moves by priority (descending)\n    prioritized_moves.sort(key=lambda x: x[1], reverse=True)\n    return [move for move, _ in prioritized_moves]\n\ndef chess_bot(obs):\n    \"\"\"\n    Simple chess bot using first principles logic.\n    \"\"\"\n    game = Game(obs.board)\n    moves = list(game.get_moves())\n\n    if not moves:\n        return None  # No legal moves available\n\n    # Prioritize moves based on first principles\n    prioritized_moves = prioritize_moves(game, moves)\n\n    # Pick the best move (highest priority)\n    best_move = prioritized_moves[0] if prioritized_moves else random.choice(moves)\n    debug(f\"Best move selected: {best_move}\")\n    return best_move\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T20:33:44.762362Z","iopub.execute_input":"2024-11-21T20:33:44.762654Z","iopub.status.idle":"2024-11-21T20:33:44.769860Z","shell.execute_reply.started":"2024-11-21T20:33:44.762626Z","shell.execute_reply":"2024-11-21T20:33:44.768782Z"},"jupyter":{"source_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%%writefile main.py\nfrom Chessnut import Game\nimport random\n\n# Piece values for material evaluation\nPIECE_VALUES = {\n    \"p\": 1, \"n\": 3, \"b\": 3, \"r\": 5, \"q\": 9, \"k\": 0,\n    \"P\": -1, \"N\": -3, \"B\": -3, \"R\": -5, \"Q\": -9, \"K\": 0\n}\n\nCENTER_SQUARES = {\"d4\", \"d5\", \"e4\", \"e5\"}\nOPEN_FILE_BONUS = 1  # Bonus for controlling open files\nKING_SAFETY_BONUS = 2  # Bonus for moves protecting the king\nPAWN_PROMOTION_BONUS = 10  # Bonus for promoting pawns\n\n# Dynamic weights for different phases of the game\nDYNAMIC_WEIGHTS = {\n    \"early_game\": {\"center_control\": 2, \"development\": 3, \"captures\": 1},\n    \"mid_game\": {\"center_control\": 1, \"development\": 2, \"captures\": 3},\n    \"end_game\": {\"center_control\": 1, \"development\": 1, \"captures\": 5, \"king_safety\": 3},\n}\n\ndef get_game_phase(game):\n    \"\"\"\n    Determine the phase of the game based on material and move count.\n    \"\"\"\n    material_count = sum(abs(PIECE_VALUES[piece.lower()]) for piece in game.board.get_board().values() if piece != \" \")\n    if material_count > 20:\n        return \"early_game\"\n    elif material_count > 10:\n        return \"mid_game\"\n    else:\n        return \"end_game\"\n\ndef debug(message):\n    \"\"\"\n    Utility function for debugging.\n    \"\"\"\n    print(f\"DEBUG: {message}\")\n\ndef prioritize_moves(game, moves):\n    \"\"\"\n    Prioritize moves based on first principles and dynamic adjustments.\n    \"\"\"\n    prioritized_moves = []\n    game_phase = get_game_phase(game)\n    weights = DYNAMIC_WEIGHTS[game_phase]\n\n    for move in moves:\n        piece = game.board.get_piece(Game.xy2i(move[:2]))\n        target_square = move[2:4]\n        target_piece = game.board.get_piece(Game.xy2i(target_square))\n\n        score = 0\n\n        # Checkmate moves (highest priority)\n        g = Game(game.get_fen())\n        g.apply_move(move)\n        if g.status == Game.CHECKMATE:\n            debug(f\"Checkmate move found: {move}\")\n            return [move]\n\n        # Captures (weighted by phase)\n        if target_piece != ' ':\n            score += weights[\"captures\"] + PIECE_VALUES.get(target_piece.lower(), 0)\n\n        # Central control\n        if target_square in CENTER_SQUARES:\n            score += weights[\"center_control\"]\n\n        # Development of knights and bishops (early-game priority)\n        if piece.lower() in {'n', 'b'}:\n            score += weights[\"development\"]\n\n        # King safety (endgame focus)\n        if game_phase == \"end_game\" and (piece.lower() == 'k' or target_square in {\"g1\", \"g8\", \"c1\", \"c8\"}):\n            score += KING_SAFETY_BONUS\n\n        # Pawn promotion (endgame priority)\n        if piece.lower() == 'p' and target_square[1] in {\"1\", \"8\"}:  # Promotion rank\n            score += PAWN_PROMOTION_BONUS\n\n        # Default scoring for all moves\n        prioritized_moves.append((move, score))\n\n    # Sort moves by priority (descending)\n    prioritized_moves.sort(key=lambda x: x[1], reverse=True)\n    return [move for move, _ in prioritized_moves]\n\ndef predict_opponent_move(game, moves):\n    \"\"\"\n    Predict the opponent's best response to our moves by simulating each.\n    \"\"\"\n    opponent_scores = []\n    for move in moves:\n        g = Game(game.get_fen())\n        g.apply_move(move)\n        opponent_moves = list(g.get_moves())\n        if opponent_moves:\n            opponent_scores.append(min(prioritize_moves(g, opponent_moves), key=lambda x: PIECE_VALUES.get(g.board.get_piece(Game.xy2i(x[2:4])).lower(), 0)))\n    return opponent_scores\n\ndef chess_bot(obs):\n    \"\"\"\n    Chess bot using dynamic evaluation and predictions.\n    \"\"\"\n    game = Game(obs.board)\n    moves = list(game.get_moves())\n\n    if not moves:\n        return None  # No legal moves available\n\n    # Prioritize moves\n    prioritized_moves = prioritize_moves(game, moves)\n\n    # Predict opponent moves and adjust based on anticipated threats\n    if len(prioritized_moves) > 1:\n        predicted_responses = predict_opponent_move(game, prioritized_moves[:5])  # Analyze top 5 moves\n        for i, move in enumerate(prioritized_moves[:5]):\n            if predicted_responses[i]:  # Adjust priority to avoid moves leading to losses\n                prioritized_moves[i] = (move, prioritized_moves[i][1] - PIECE_VALUES.get(game.board.get_piece(Game.xy2i(predicted_responses[i][2:4])).lower(), 0))\n\n    # Sort moves after considering predictions\n    prioritized_moves.sort(key=lambda x: x[1], reverse=True)\n\n    # Pick the best move\n    best_move = prioritized_moves[0][0] if prioritized_moves else random.choice(moves)\n    debug(f\"Best move selected: {best_move}\")\n    return best_move\n\n## v2\n\nfrom Chessnut import Game\nimport random\n\n# Piece values for material evaluation\nPIECE_VALUES = {\n    \"p\": 1, \"n\": 3, \"b\": 3, \"r\": 5, \"q\": 9, \"k\": 0,\n    \"P\": -1, \"N\": -3, \"B\": -3, \"R\": -5, \"Q\": -9, \"K\": 0\n}\n\nCENTER_SQUARES = {\"d4\", \"d5\", \"e4\", \"e5\"}\n\ndef debug(message):\n    \"\"\"Utility function for debugging.\"\"\"\n    print(f\"DEBUG: {message}\")\n\ndef get_game_phase(game):\n    \"\"\"\n    Determine the game phase based on material count.\n    Early game: High material.\n    Mid game: Medium material.\n    End game: Low material.\n    \"\"\"\n    fen = game.get_fen()  # Retrieve FEN string\n    board_state = fen.split()[0]  # The first part of FEN represents the board\n    material_count = 0\n\n    for char in board_state:\n        if char.isalpha():  # If it's a piece\n            material_count += abs(PIECE_VALUES[char.lower()])\n\n    if material_count > 30:\n        return \"early\"\n    elif 15 < material_count <= 30:\n        return \"mid\"\n    else:\n        return \"end\"\n\ndef prioritize_moves(game, moves):\n    \"\"\"Prioritize moves based on first principles and game phase.\"\"\"\n    game_phase = get_game_phase(game)  # Fix applied here\n    prioritized_moves = []\n\n    for move in moves:\n        piece = game.board.get_piece(Game.xy2i(move[:2]))\n        target_square = move[2:4]\n        target_piece = game.board.get_piece(Game.xy2i(target_square))\n\n        # Checkmate moves (highest priority)\n        g = Game(game.get_fen())\n        g.apply_move(move)\n        if g.status == Game.CHECKMATE:\n            debug(f\"Checkmate move found: {move}\")\n            return [move]\n\n        # Captures (next priority)\n        if target_piece != ' ':\n            debug(f\"Capture move: {move}, Captures: {target_piece}\")\n            prioritized_moves.append((move, 3 + PIECE_VALUES.get(target_piece.lower(), 0)))\n\n        # Central control (medium priority)\n        elif target_square in CENTER_SQUARES:\n            debug(f\"Central control move: {move}\")\n            prioritized_moves.append((move, 2))\n\n        # Development of knights and bishops (early-game priority)\n        elif piece.lower() in {'n', 'b'}:\n            debug(f\"Development move: {move}\")\n            prioritized_moves.append((move, 1))\n\n        # Default: Other moves (low priority)\n        else:\n            prioritized_moves.append((move, 0))\n\n    # Sort moves by priority (descending)\n    prioritized_moves.sort(key=lambda x: x[1], reverse=True)\n    return [move for move, _ in prioritized_moves]\n\n\n\ndef prioritize_moves(game, moves):\n    \"\"\"Prioritize moves based on first principles and game phase.\"\"\"\n    game_phase = get_game_phase(game)\n    prioritized_moves = []\n\n    for move in moves:\n        piece = game.board.get_piece(Game.xy2i(move[:2]))\n        target_square = move[2:4]\n        target_piece = game.board.get_piece(Game.xy2i(target_square))\n\n        # Checkmate moves (highest priority)\n        g = Game(game.get_fen())\n        g.apply_move(move)\n        if g.status == Game.CHECKMATE:\n            debug(f\"Checkmate move found: {move}\")\n            return [move]\n\n        # Endgame: Aggressively target the king\n        if game_phase == \"end\":\n            if g.status == Game.CHECK:\n                debug(f\"Check move in endgame: {move}\")\n                prioritized_moves.append((move, 5))  # Prioritize checks\n            elif target_piece == 'K':  # Target the king\n                debug(f\"King-targeting move: {move}\")\n                prioritized_moves.append((move, 4))\n            else:\n                prioritized_moves.append((move, 0))  # Penalize irrelevant moves\n            continue\n\n        # Captures (high priority)\n        if target_piece != ' ':\n            debug(f\"Capture move: {move}, Captures: {target_piece}\")\n            prioritized_moves.append((move, 3 + PIECE_VALUES.get(target_piece.lower(), 0)))\n\n        # Central control (medium priority)\n        elif target_square in CENTER_SQUARES:\n            debug(f\"Central control move: {move}\")\n            prioritized_moves.append((move, 2))\n\n        # Development of knights and bishops (early-game priority)\n        elif piece.lower() in {'n', 'b'}:\n            debug(f\"Development move: {move}\")\n            prioritized_moves.append((move, 1))\n\n        # Default: Other moves (low priority)\n        else:\n            prioritized_moves.append((move, 0))\n\n    # Sort moves by priority (descending)\n    prioritized_moves.sort(key=lambda x: x[1], reverse=True)\n    return [move for move, _ in prioritized_moves]\n\n# Encourage king centralization and safety in the endgame\nif game_phase == \"end\" and piece.lower() == 'k':\n    if target_square in CENTER_SQUARES:\n        debug(f\"King centralization move: {move}\")\n        prioritized_moves.append((move, 2))\n    else:\n        prioritized_moves.append((move, 0))  # Avoid irrelevant king moves\n\n# Encourage pawn promotion in the endgame\nif piece.lower() == 'p':\n    rank = int(target_square[1])\n    if (rank == 8 and piece.islower()) or (rank == 1 and piece.isupper()):\n        debug(f\"Pawn promotion move: {move}\")\n        prioritized_moves.append((move, 10))  # High priority for promotion\n    elif game_phase == \"end\" and abs(rank - int(move[1])) == 1:\n        debug(f\"Pawn advancing move: {move}\")\n        prioritized_moves.append((move, 2))  # Encourage pawn advancement\n\ndef chess_bot(obs):\n    \"\"\"Simple chess bot using first principles logic.\"\"\"\n    game = Game(obs.board)\n    moves = list(game.get_moves())\n\n    if not moves:\n        return None  # No legal moves available\n\n    # Prioritize moves based on first principles\n    prioritized_moves = prioritize_moves(game, moves)\n\n    # Pick the best move (highest priority)\n    best_move = prioritized_moves[0] if prioritized_moves else random.choice(moves)\n    debug(f\"Best move selected: {best_move}\")\n    return best_move","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T20:33:44.771445Z","iopub.execute_input":"2024-11-21T20:33:44.771965Z","iopub.status.idle":"2024-11-21T20:33:44.789010Z","shell.execute_reply.started":"2024-11-21T20:33:44.771909Z","shell.execute_reply":"2024-11-21T20:33:44.787912Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%%writefile main.py\nfrom Chessnut import Game\nimport random\nimport logging\n\n# Configure Debugging and Logging\nDEBUG = True\nlogging.basicConfig(level=logging.DEBUG if DEBUG else logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')\n\ndef debug(message):\n    \"\"\"Utility function for debugging.\"\"\"\n    if DEBUG:\n        logging.debug(message)\n\n# Constants\nPIECE_VALUES = {\n    \"p\": 1, \"n\": 3, \"b\": 3, \"r\": 5, \"q\": 9, \"k\": 0,\n    \"P\": -1, \"N\": -3, \"B\": -3, \"R\": -5, \"Q\": -9, \"K\": 0\n}\nCENTER_SQUARES = {\"d4\", \"d5\", \"e4\", \"e5\"}\n\ndef load_weights():\n    \"\"\"Load weights for move prioritization.\"\"\"\n    # Optional: Extend with dynamic learning\n    return {\"central_control\": 3, \"captures\": 5, \"check\": 10, \"promotion\": 15}\n\nWEIGHTS = load_weights()\n\ndef parse_board_from_fen(fen):\n    \"\"\"\n    Parse the board from the FEN string into a dictionary representation.\n    Returns a dictionary where keys are square names (e.g., \"a1\") and values are pieces (e.g., \"P\", \"r\").\n    \"\"\"\n    rows = fen.split()[0].split(\"/\")\n    board = {}\n    for rank_idx, row in enumerate(rows):\n        file_idx = 0\n        for char in row:\n            if char.isdigit():\n                file_idx += int(char)  # Skip empty squares\n            else:\n                square = f\"{chr(file_idx + ord('a'))}{8 - rank_idx}\"\n                board[square] = char\n                file_idx += 1\n    return board\n\ndef get_game_phase(game):\n    \"\"\"\n    Determine the game phase: opening, midgame, or endgame.\n    Based on material count.\n    \"\"\"\n    fen = game.get_fen()\n    board = parse_board_from_fen(fen)\n    material_count = sum(abs(PIECE_VALUES[piece.lower()]) for piece in board.values() if piece != \" \")\n    if material_count > 30:\n        return \"opening\"\n    elif 20 < material_count <= 30:\n        return \"midgame\"\n    else:\n        return \"end\"\n\ndef prioritize_moves(game, moves):\n    \"\"\"\n    Prioritize moves based on first principles and game phase.\n    \"\"\"\n    game_phase = get_game_phase(game)\n    prioritized_moves = []\n\n    for move in moves:\n        piece = game.board.get_piece(Game.xy2i(move[:2]))\n        target_square = move[2:4]\n        target_piece = game.board.get_piece(Game.xy2i(target_square))\n\n        # Checkmate moves (highest priority)\n        g = Game(game.get_fen())\n        g.apply_move(move)\n        if g.status == Game.CHECKMATE:\n            debug(f\"Checkmate move found: {move}\")\n            return [move]\n\n        # Endgame: Aggressively target the king\n        if game_phase == \"end\":\n            if g.status == Game.CHECK:\n                debug(f\"Check move in endgame: {move}\")\n                prioritized_moves.append((move, WEIGHTS[\"check\"]))\n            elif target_piece == 'K':  # Target the king\n                debug(f\"King-targeting move: {move}\")\n                prioritized_moves.append((move, WEIGHTS[\"check\"]))\n            continue\n\n        # Captures (high priority)\n        if target_piece != ' ':\n            debug(f\"Capture move: {move}, Captures: {target_piece}\")\n            prioritized_moves.append((move, WEIGHTS[\"captures\"] + PIECE_VALUES.get(target_piece.lower(), 0)))\n\n        # Central control (medium priority)\n        elif target_square in CENTER_SQUARES:\n            debug(f\"Central control move: {move}\")\n            prioritized_moves.append((move, WEIGHTS[\"central_control\"]))\n\n        # Development of knights and bishops (early-game priority)\n        elif piece.lower() in {'n', 'b'}:\n            debug(f\"Development move: {move}\")\n            prioritized_moves.append((move, 1))\n\n        # Pawn promotion (endgame priority)\n        elif piece.lower() == 'p':\n            rank = int(target_square[1])\n            if (rank == 8 and piece.islower()) or (rank == 1 and piece.isupper()):\n                debug(f\"Pawn promotion move: {move}\")\n                prioritized_moves.append((move, WEIGHTS[\"promotion\"]))\n\n        # Default: Other moves (low priority)\n        else:\n            prioritized_moves.append((move, 0))\n\n    # Sort moves by priority (descending)\n    prioritized_moves.sort(key=lambda x: x[1], reverse=True)\n    return [move for move, _ in prioritized_moves]\n\ndef chess_bot(obs):\n    \"\"\"\n    Enhanced chess bot using prioritized move evaluation.\n    \"\"\"\n    game = Game(obs.board)\n    moves = list(game.get_moves())\n\n    if not moves:\n        return None  # No legal moves available\n\n    # Prioritize moves based on first principles\n    prioritized_moves = prioritize_moves(game, moves)\n\n    # Pick the best move (highest priority)\n    best_move = prioritized_moves[0] if prioritized_moves else random.choice(moves)\n    debug(f\"Best move selected: {best_move}\")\n    return best_move\n\n# Testing the bot\nif __name__ == \"__main__\":\n    from kaggle_environments import make\n\n    env = make(\"chess\", debug=True)\n\n    # Test bot against random agent\n    result = env.run([\"main.py\", \"random\"])\n    print(\"Agent exit status/reward/time left: \")\n    for agent in result[-1]:\n        print(\"\\t\", agent.status, \"/\", agent.reward, \"/\", agent.observation.remainingOverageTime)\n    print(\"\\n\")\n    # Render the game\n    env.render(mode=\"ipython\", width=1000, height=1000)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T20:33:44.790417Z","iopub.execute_input":"2024-11-21T20:33:44.790767Z","iopub.status.idle":"2024-11-21T20:33:44.803728Z","shell.execute_reply.started":"2024-11-21T20:33:44.790737Z","shell.execute_reply":"2024-11-21T20:33:44.802716Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%%writefile main.py\nfrom Chessnut import Game\nimport random\nimport logging\n\n# Configure Debugging and Logging\nDEBUG = True\nlogging.basicConfig(level=logging.DEBUG if DEBUG else logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')\n\ndef debug(message):\n    \"\"\"Utility function for debugging.\"\"\"\n    if DEBUG:\n        logging.debug(message)\n\n# Constants\nPIECE_VALUES = {\n    \"p\": 1, \"n\": 3, \"b\": 3, \"r\": 5, \"q\": 9, \"k\": 0,\n    \"P\": -1, \"N\": -3, \"B\": -3, \"R\": -5, \"Q\": -9, \"K\": 0\n}\nCENTER_SQUARES = {\"d4\", \"d5\", \"e4\", \"e5\"}\nCORNER_SQUARES = {\"a1\", \"h1\", \"a8\", \"h8\"}\n\ndef king_seeks_cover(board, king_square, enemy_attacks, friendly_pieces):\n    \"\"\"\n    Guides the king toward safer squares.\n    \"\"\"\n    # Generate potential king moves\n    possible_moves = []\n    file, rank = king_square[0], int(king_square[1])\n\n    for file_offset in [-1, 0, 1]:\n        for rank_offset in [-1, 0, 1]:\n            if file_offset == 0 and rank_offset == 0:\n                continue  # Skip current square\n            target_file = chr(ord(file) + file_offset)\n            target_rank = str(rank + rank_offset)\n            target_square = f\"{target_file}{target_rank}\"\n            if target_square in board:  # Ensure valid square\n                possible_moves.append(target_square)\n\n    # Filter moves for safety\n    safe_moves = [\n        move for move in possible_moves\n        if move not in enemy_attacks and move not in friendly_pieces\n    ]\n\n    # Prioritize moves near board edges or corners\n    prioritized_moves = sorted(\n        safe_moves,\n        key=lambda sq: (\n            sq in CORNER_SQUARES,  # Prefer corners\n            sq[0] in \"ah\" or sq[1] in \"18\"  # Prefer edges\n        ),\n        reverse=True,\n    )\n    return prioritized_moves\n\n\ndef load_weights():\n    \"\"\"Load weights for move prioritization.\"\"\"\n    return {\"central_control\": 3, \"captures\": 5, \"check\": 10, \"promotion\": 15, \"cornering\": 10}\n\nWEIGHTS = load_weights()\n\ndef parse_board_from_fen(fen):\n    \"\"\"Parse the board from the FEN string into a dictionary representation.\"\"\"\n    rows = fen.split()[0].split(\"/\")\n    board = {}\n    for rank_idx, row in enumerate(rows):\n        file_idx = 0\n        for char in row:\n            if char.isdigit():\n                file_idx += int(char)  # Skip empty squares\n            else:\n                square = f\"{chr(file_idx + ord('a'))}{8 - rank_idx}\"\n                board[square] = char\n                file_idx += 1\n    return board\n\ndef get_opponent_king_position(board, player):\n    \"\"\"Get the position of the opponent's king.\"\"\"\n    king = \"k\" if player == \"w\" else \"K\"\n    for square, piece in board.items():\n        if piece == king:\n            return square\n    return None\n\ndef is_adjacent(square1, square2):\n    \"\"\"Check if two squares are adjacent.\"\"\"\n    file_diff = abs(ord(square1[0]) - ord(square2[0]))\n    rank_diff = abs(int(square1[1]) - int(square2[1]))\n    return max(file_diff, rank_diff) == 1\n\ndef get_game_phase(game):\n    \"\"\"Determine the game phase: opening, midgame, or endgame.\"\"\"\n    fen = game.get_fen()\n    board = parse_board_from_fen(fen)\n    material_count = sum(abs(PIECE_VALUES[piece.lower()]) for piece in board.values() if piece != \" \")\n    if material_count > 20:\n        return \"opening\"\n    elif 10 < material_count <= 20:\n        return \"midgame\"\n    else:\n        return \"end\"\n\ndef prioritize_moves(game, moves):\n    \"\"\"Prioritize moves based on first principles and game phase.\"\"\"\n    game_phase = get_game_phase(game)\n    fen = game.get_fen()\n    board = parse_board_from_fen(fen)\n    player = \"w\" if fen.split()[1] == \"w\" else \"b\"\n    opponent_king = get_opponent_king_position(board, player)\n    prioritized_moves = []\n    score = WEIGHTS[\"central_control\"]\n    score += apply_decay(move)  # Apply decay to move score\n    prioritized_moves.append((move, score))\n\n\n    for move in moves:\n        piece = board.get(move[:2], \" \")\n        target_square = move[2:4]\n        target_piece = board.get(target_square, \" \")\n\n        # Checkmate moves (highest priority)\n        g = Game(game.get_fen())\n        g.apply_move(move)\n        if g.status == Game.CHECKMATE:\n            debug(f\"Checkmate move found: {move}\")\n            return [move]\n\n        # Endgame: Corner the opponent king\n        # Endgame: Corner the opponent king or defend friendly king\n        # Endgame: Focus on restricting the opponent king\n        if phase == \"endgame\" and opponent_king_pos:\n            if is_adjacent(end_square, opponent_king_pos):\n                debug(f\"Restricting king mobility: {move}\")\n                score = 5 + apply_decay(move)  # Boost for restricting king\n                prioritized_moves.append((move, score))\n            elif end_square in KING_ACTIVITY_SQUARES:\n                debug(f\"Controlling key square near king: {move}\")\n                score = 3 + apply_decay(move)\n                prioritized_moves.append((move, score))\n\n            # Seek cover for the friendly king\n            cover_moves = king_seeks_cover(board, friendly_king, enemy_attacks, list(board.keys()))\n            if cover_moves:\n                for move in moves:\n                    if move[2:4] in cover_moves:\n                        debug(f\"King seeking cover: {move}\")\n                        prioritized_moves.append((move, WEIGHTS[\"check\"]))\n                continue\n        \n            # Restrict opponent king\n            if opponent_king:\n                if is_adjacent(target_square, opponent_king):\n                    debug(f\"Restricting king's mobility: {move}\")\n                    prioritized_moves.append((move, WEIGHTS[\"check\"]))\n                elif target_square in CORNER_SQUARES:\n                    debug(f\"Driving king to corner: {move}\")\n                    prioritized_moves.append((move, WEIGHTS[\"cornering\"]))\n                continue\n\n        # Captures (high priority)\n        if target_piece != \" \":\n            debug(f\"Capture move: {move}, Captures: {target_piece}\")\n            prioritized_moves.append((move, WEIGHTS[\"captures\"] + PIECE_VALUES.get(target_piece.lower(), 0)))\n\n        # Central control (medium priority)\n        elif target_square in CENTER_SQUARES:\n            debug(f\"Central control move: {move}\")\n            prioritized_moves.append((move, WEIGHTS[\"central_control\"]))\n\n        # Default: Other moves (low priority)\n        else:\n            prioritized_moves.append((move, 0))\n\n    # Sort moves by priority (descending)\n    prioritized_moves.sort(key=lambda x: x[1], reverse=True)\n    return [move for move, _ in prioritized_moves]\n\n# Initialize decay counter (global or in bot state)\nMOVE_HISTORY = {}\n\ndef apply_decay(move):\n    \"\"\"Apply a decay factor to repetitive moves.\"\"\"\n    if move in MOVE_HISTORY:\n        MOVE_HISTORY[move] += 1\n    else:\n        MOVE_HISTORY[move] = 1\n    return max(0, 10 - MOVE_HISTORY[move])  # Reduce score based on repetition\n\n\ndef chess_bot(obs):\n    \"\"\"Chess bot using advanced logic with decay and dynamic phases.\"\"\"\n    fen = obs['board']\n    game = Game(fen)\n    moves = list(game.get_moves())\n\n    if not moves:\n        return None  # No legal moves available\n\n    # Convert FEN to board representation\n    board = fen_to_board(game.get_fen())\n\n    # Determine game phase\n    white_pieces, black_pieces = count_pieces(board)\n    game_phase = determine_game_phase(white_pieces, black_pieces)\n\n    # Prioritize moves dynamically\n    prioritized_moves = prioritize_moves(game, moves, game_phase, board)\n\n    # Pick the best move\n    best_move = prioritized_moves[0] if prioritized_moves else random.choice(moves)\n    debug(f\"Best move selected: {best_move}\")\n    return best_move\n\n\n# Testing the bot\nif __name__ == \"__main__\":\n    from kaggle_environments import make\n\n    env = make(\"chess\", debug=True)\n\n    # Test bot against random agent\n    result = env.run([\"main.py\", \"random\"])\n    print(\"Agent exit status/reward/time left: \")\n    for agent in result[-1]:\n        print(\"\\t\", agent.status, \"/\", agent.reward, \"/\", agent.observation.remainingOverageTime)\n    print(\"\\n\")\n    # Render the game\n    env.render(mode=\"ipython\", width=1000, height=1000)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T20:33:44.805201Z","iopub.execute_input":"2024-11-21T20:33:44.805526Z","iopub.status.idle":"2024-11-21T20:33:44.822995Z","shell.execute_reply.started":"2024-11-21T20:33:44.805490Z","shell.execute_reply":"2024-11-21T20:33:44.821843Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%%writefile main.py\nfrom Chessnut import Game\nimport random\nimport logging\n\n# Configure Debugging and Logging\nDEBUG = True\nlogging.basicConfig(level=logging.DEBUG if DEBUG else logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')\n\ndef debug(message):\n    \"\"\"Utility function for debugging.\"\"\"\n    if DEBUG:\n        logging.debug(message)\n\n# Constants\nPIECE_VALUES = {\n    \"p\": 1, \"n\": 3, \"b\": 3, \"r\": 5, \"q\": 9, \"k\": 0,\n    \"P\": -1, \"N\": -3, \"B\": -3, \"R\": -5, \"Q\": -9, \"K\": 0\n}\nCENTER_SQUARES = {\"d4\", \"d5\", \"e4\", \"e5\"}\nCORNER_SQUARES = {\"a1\", \"h1\", \"a8\", \"h8\"}\nKING_ACTIVITY_SQUARES = {\"c4\", \"c5\", \"d3\", \"d6\", \"e3\", \"e6\", \"f4\", \"f5\"}\n\n# Global decay tracking\nMOVE_HISTORY = {}\n\n# Define weights for move prioritization\nWEIGHTS = {\n    \"central_control\": 3,\n    \"captures\": 5,\n    \"check\": 10,\n    \"promotion\": 15,\n    \"cornering\": 10\n}\n\ndef apply_decay(move):\n    \"\"\"Apply a decay factor to repetitive moves.\"\"\"\n    if move in MOVE_HISTORY:\n        MOVE_HISTORY[move] += 1\n    else:\n        MOVE_HISTORY[move] = 1\n    return max(0, 10 - MOVE_HISTORY[move])  # Reduce score for repetitive moves\n\ndef fen_to_board(fen):\n    \"\"\"Convert FEN string to a board representation.\"\"\"\n    rows = fen.split()[0].split(\"/\")\n    board = {}\n    for rank_idx, row in enumerate(rows):\n        file_idx = 0\n        for char in row:\n            if char.isdigit():\n                file_idx += int(char)  # Empty squares\n            else:\n                square = f\"{chr(file_idx + ord('a'))}{8 - rank_idx}\"\n                board[square] = char\n                file_idx += 1\n    return board\n\ndef get_opponent_king_position(board, player):\n    \"\"\"Find the opponent king's position.\"\"\"\n    king = \"k\" if player == \"w\" else \"K\"\n    for square, piece in board.items():\n        if piece == king:\n            return square\n    return None\n\ndef is_adjacent(square1, square2):\n    \"\"\"Check if two squares are adjacent.\"\"\"\n    file_diff = abs(ord(square1[0]) - ord(square2[0]))\n    rank_diff = abs(int(square1[1]) - int(square2[1]))\n    return max(file_diff, rank_diff) == 1\n\ndef king_seeks_cover(board, king_square, enemy_attacks, friendly_pieces):\n    \"\"\"Direct the king to safer squares.\"\"\"\n    possible_moves = []\n    file, rank = king_square[0], int(king_square[1])\n    for file_offset in [-1, 0, 1]:\n        for rank_offset in [-1, 0, 1]:\n            if file_offset == 0 and rank_offset == 0:\n                continue\n            target_file = chr(ord(file) + file_offset)\n            target_rank = str(rank + rank_offset)\n            target_square = f\"{target_file}{target_rank}\"\n            if target_square in board:\n                possible_moves.append(target_square)\n    safe_moves = [\n        move for move in possible_moves\n        if move not in enemy_attacks and move not in friendly_pieces\n    ]\n    prioritized_moves = sorted(\n        safe_moves,\n        key=lambda sq: (\n            sq in CORNER_SQUARES,\n            sq[0] in \"ah\" or sq[1] in \"18\"\n        ),\n        reverse=True,\n    )\n    return prioritized_moves\n\ndef determine_game_phase(board):\n    \"\"\"Determine game phase based on material count.\"\"\"\n    material_count = sum(abs(PIECE_VALUES[piece.lower()]) for piece in board.values() if piece != \" \")\n    if material_count > 20:\n        return \"opening\"\n    elif 10 < material_count <= 20:\n        return \"midgame\"\n    else:\n        return \"endgame\"\n\ndef prioritize_moves(game, moves, phase, board):\n    \"\"\"Prioritize moves dynamically based on game phase.\"\"\"\n    prioritized_moves = []\n    player = \"w\" if game.get_fen().split()[1] == \"w\" else \"b\"\n    opponent_king = get_opponent_king_position(board, player)\n    \n    for move in moves:\n        start_square = move[:2]\n        end_square = move[2:4]\n        piece = board.get(start_square, \" \")\n        target_piece = board.get(end_square, \" \")\n\n        # Checkmate moves\n        g = Game(game.get_fen())\n        g.apply_move(move)\n        if g.status == Game.CHECKMATE:\n            debug(f\"Checkmate move: {move}\")\n            return [move]\n\n        # Endgame: Restrict opponent king or defend friendly king\n        if phase == \"endgame\" and opponent_king:\n            if is_adjacent(end_square, opponent_king):\n                debug(f\"Restricting opponent king: {move}\")\n                score = 5 + apply_decay(move)\n                prioritized_moves.append((move, score))\n            elif end_square in KING_ACTIVITY_SQUARES:\n                debug(f\"Targeting key square: {move}\")\n                score = 3 + apply_decay(move)\n                prioritized_moves.append((move, score))\n            continue\n\n        # Captures\n        if target_piece != \" \":\n            debug(f\"Capture: {move}, capturing {target_piece}\")\n            score = WEIGHTS[\"captures\"] + PIECE_VALUES.get(target_piece.lower(), 0)\n            prioritized_moves.append((move, score))\n            continue\n\n        # Central control\n        if end_square in CENTER_SQUARES:\n            debug(f\"Central control: {move}\")\n            score = WEIGHTS[\"central_control\"]\n            prioritized_moves.append((move, score))\n            continue\n\n        # Default moves\n        score = apply_decay(move)\n        prioritized_moves.append((move, score))\n\n    prioritized_moves.sort(key=lambda x: x[1], reverse=True)\n    return [move for move, _ in prioritized_moves]\n\ndef chess_bot(obs):\n    \"\"\"Dynamic chess bot with prioritization.\"\"\"\n    fen = obs['board']\n    game = Game(fen)\n    moves = list(game.get_moves())\n\n    if not moves:\n        return None\n\n    board = fen_to_board(fen)\n    phase = determine_game_phase(board)\n    debug(f\"Game phase: {phase}\")\n\n    prioritized_moves = prioritize_moves(game, moves, phase, board)\n    best_move = prioritized_moves[0] if prioritized_moves else random.choice(moves)\n    debug(f\"Best move: {best_move}\")\n    return best_move\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T20:33:44.824720Z","iopub.execute_input":"2024-11-21T20:33:44.825317Z","iopub.status.idle":"2024-11-21T20:33:44.841435Z","shell.execute_reply.started":"2024-11-21T20:33:44.825271Z","shell.execute_reply":"2024-11-21T20:33:44.840294Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%%writefile main.py\nfrom Chessnut import Game\nimport random\nimport logging\n\n# Configure Debugging and Logging\nDEBUG = True\nlogging.basicConfig(level=logging.DEBUG if DEBUG else logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')\n\ndef debug(message):\n    \"\"\"Utility function for debugging.\"\"\"\n    if DEBUG:\n        logging.debug(message)\n\n# Constants\nPIECE_VALUES = {\n    \"p\": 1, \"n\": 3, \"b\": 3, \"r\": 5, \"q\": 9, \"k\": 0,\n    \"P\": -1, \"N\": -3, \"B\": -3, \"R\": -5, \"Q\": -9, \"K\": 0\n}\nCENTER_SQUARES = {\"d4\", \"d5\", \"e4\", \"e5\"}\nCORNER_SQUARES = {\"a1\", \"h1\", \"a8\", \"h8\"}\nKING_ACTIVITY_SQUARES = {\"c4\", \"c5\", \"d3\", \"d6\", \"e3\", \"e6\", \"f4\", \"f5\"}\n\n# Define weights for move prioritization\nWEIGHTS = {\n    \"central_control\": 3,\n    \"captures\": 5,\n    \"check\": 10,\n    \"aggression\": 7,\n    \"cornering\": 12\n}\n\n# Move history to prevent repetitive moves\nMOVE_HISTORY = {}\n\ndef apply_decay(move):\n    \"\"\"Apply a decay factor to repetitive moves.\"\"\"\n    if move in MOVE_HISTORY:\n        MOVE_HISTORY[move] += 1\n    else:\n        MOVE_HISTORY[move] = 1\n    return max(0, 10 - MOVE_HISTORY[move])  # Penalize repetitive moves\n\ndef fen_to_board(fen):\n    \"\"\"Convert FEN string to a board representation.\"\"\"\n    rows = fen.split()[0].split(\"/\")\n    board = {}\n    for rank_idx, row in enumerate(rows):\n        file_idx = 0\n        for char in row:\n            if char.isdigit():\n                file_idx += int(char)\n            else:\n                square = f\"{chr(file_idx + ord('a'))}{8 - rank_idx}\"\n                board[square] = char\n                file_idx += 1\n    return board\n\ndef get_opponent_king_position(board, player):\n    \"\"\"Find the opponent king's position.\"\"\"\n    king = \"k\" if player == \"w\" else \"K\"\n    for square, piece in board.items():\n        if piece == king:\n            return square\n    return None\n\ndef is_adjacent(square1, square2):\n    \"\"\"Check if two squares are adjacent.\"\"\"\n    file_diff = abs(ord(square1[0]) - ord(square2[0]))\n    rank_diff = abs(int(square1[1]) - int(square2[1]))\n    return max(file_diff, rank_diff) == 1\n\ndef king_seeks_cover(board, king_square, enemy_attacks, friendly_pieces):\n    \"\"\"Direct the king to safer squares.\"\"\"\n    possible_moves = []\n    file, rank = king_square[0], int(king_square[1])\n    for file_offset in [-1, 0, 1]:\n        for rank_offset in [-1, 0, 1]:\n            if file_offset == 0 and rank_offset == 0:\n                continue\n            target_file = chr(ord(file) + file_offset)\n            target_rank = str(rank + rank_offset)\n            target_square = f\"{target_file}{target_rank}\"\n            if target_square in board:\n                possible_moves.append(target_square)\n    safe_moves = [\n        move for move in possible_moves\n        if move not in enemy_attacks and move not in friendly_pieces\n    ]\n    return safe_moves\n\ndef determine_game_phase(board):\n    \"\"\"Determine game phase based on material count.\"\"\"\n    material_count = sum(abs(PIECE_VALUES[piece.lower()]) for piece in board.values() if piece != \" \")\n    if material_count > 25:\n        return \"opening\"\n    elif 10 < material_count <= 25:\n        return \"midgame\"\n    else:\n        return \"endgame\"\n\ndef prioritize_moves(game, moves, phase, board):\n    \"\"\"Prioritize moves dynamically based on game phase.\"\"\"\n    prioritized_moves = []\n    player = \"w\" if game.get_fen().split()[1] == \"w\" else \"b\"\n    opponent_king = get_opponent_king_position(board, player)\n\n    for move in moves:\n        start_square = move[:2]\n        end_square = move[2:4]\n        piece = board.get(start_square, \" \")\n        target_piece = board.get(end_square, \" \")\n\n        # Checkmate moves\n        g = Game(game.get_fen())\n        g.apply_move(move)\n        if g.status == Game.CHECKMATE:\n            debug(f\"Checkmate move: {move}\")\n            return [move]\n\n        # Captures\n        if target_piece != \" \":\n            score = WEIGHTS[\"captures\"] + PIECE_VALUES.get(target_piece.lower(), 0)\n            prioritized_moves.append((move, score))\n            continue\n\n        # Central control\n        if end_square in CENTER_SQUARES:\n            score = WEIGHTS[\"central_control\"]\n            prioritized_moves.append((move, score))\n            continue\n\n        # Endgame strategies\n        if phase == \"endgame\":\n            if opponent_king and is_adjacent(end_square, opponent_king):\n                score = WEIGHTS[\"check\"] + apply_decay(move)\n                prioritized_moves.append((move, score))\n            elif end_square in KING_ACTIVITY_SQUARES:\n                score = WEIGHTS[\"aggression\"] + apply_decay(move)\n                prioritized_moves.append((move, score))\n            continue\n\n        # Default moves\n        score = apply_decay(move)\n        prioritized_moves.append((move, score))\n\n    prioritized_moves.sort(key=lambda x: x[1], reverse=True)\n    return [move for move, _ in prioritized_moves]\n\ndef chess_bot(obs):\n    \"\"\"Dynamic chess bot with prioritization.\"\"\"\n    fen = obs['board']\n    game = Game(fen)\n    moves = list(game.get_moves())\n\n    if not moves:\n        return None\n\n    board = fen_to_board(fen)\n    phase = determine_game_phase(board)\n    debug(f\"Game phase: {phase}\")\n\n    prioritized_moves = prioritize_moves(game, moves, phase, board)\n    best_move = prioritized_moves[0] if prioritized_moves else random.choice(moves)\n    debug(f\"Best move: {best_move}\")\n    return best_move\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T20:33:44.842978Z","iopub.execute_input":"2024-11-21T20:33:44.843318Z","iopub.status.idle":"2024-11-21T20:33:44.857239Z","shell.execute_reply.started":"2024-11-21T20:33:44.843278Z","shell.execute_reply":"2024-11-21T20:33:44.856074Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%%writefile main.py\nfrom Chessnut import Game\nimport random\nimport logging\n\n# Configure Debugging and Logging\nDEBUG = True\nlogging.basicConfig(level=logging.DEBUG if DEBUG else logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')\n\ndef debug(message):\n    \"\"\"Utility function for debugging.\"\"\"\n    if DEBUG:\n        logging.debug(message)\n\n# Constants\nPIECE_VALUES = {\n    \"p\": 1, \"n\": 3, \"b\": 3, \"r\": 5, \"q\": 9, \"k\": 0,\n    \"P\": -1, \"N\": -3, \"B\": -3, \"R\": -5, \"Q\": -9, \"K\": 0\n}\nCENTER_SQUARES = {\"d4\", \"d5\", \"e4\", \"e5\"}\nKING_ACTIVITY_SQUARES = {\"c4\", \"c5\", \"d3\", \"d6\", \"e3\", \"e6\", \"f4\", \"f5\"}\n\n# Move history to reduce repetitive moves\nMOVE_HISTORY = {}\n\n# Define weights for move prioritization\nWEIGHTS = {\n    \"central_control\": 3,\n    \"captures\": 8,\n    \"checks\": 12,\n    \"defense\": 7,\n    \"aggression\": 10,\n    \"coordination\": 15,\n}\n\ndef apply_decay(move):\n    \"\"\"Apply a decay factor to repetitive moves.\"\"\"\n    if move in MOVE_HISTORY:\n        MOVE_HISTORY[move] += 1\n    else:\n        MOVE_HISTORY[move] = 1\n    return max(0, 10 - MOVE_HISTORY[move])  # Penalize repetitive moves\n\ndef fen_to_board(fen):\n    \"\"\"Convert FEN string to a board representation.\"\"\"\n    rows = fen.split()[0].split(\"/\")\n    board = {}\n    for rank_idx, row in enumerate(rows):\n        file_idx = 0\n        for char in row:\n            if char.isdigit():\n                file_idx += int(char)\n            else:\n                square = f\"{chr(file_idx + ord('a'))}{8 - rank_idx}\"\n                board[square] = char\n                file_idx += 1\n    return board\n\ndef evaluate_opponent_moves(game, moves):\n    \"\"\"Evaluate opponent's responses to each move.\"\"\"\n    opponent_moves = []\n    for move in moves:\n        g = Game(game.get_fen())\n        g.apply_move(move)\n        opponent_moves.extend(list(g.get_moves()))\n    return set(opponent_moves)\n\n\n\ndef endgame_prioritization(board, moves, player):\n    \"\"\"Refine moves to corner the opponent king in the endgame.\"\"\"\n    prioritized_moves = []\n    king_square = [sq for sq, piece in board.items() if piece.lower() == \"k\" and piece.isupper() != (player == \"w\")]\n\n    for move in moves:\n        end_square = move[2:4]\n\n        # Target the opponent king directly\n        if end_square in king_square:\n            prioritized_moves.append((move, WEIGHTS[\"checks\"] + 20))\n            continue\n\n        # Moves that restrict the opponent king's movement\n        g = Game(board)\n        g.apply_move(move)\n        new_king_moves = list(g.get_moves())\n        restricted_squares = len(king_square) - len(new_king_moves)\n\n        score = WEIGHTS[\"coordination\"] + restricted_squares\n        prioritized_moves.append((move, score))\n\n    # Sort by priority\n    prioritized_moves.sort(key=lambda x: x[1], reverse=True)\n    return [move for move, _ in prioritized_moves]\n    \ndef prioritize_moves(game, moves, phase, board):\n    \"\"\"Prioritize moves dynamically based on game phase and opponent evaluation.\"\"\"\n    prioritized_moves = []\n    player = \"w\" if game.get_fen().split()[1] == \"w\" else \"b\"\n\n    for move in moves:\n        start_square = move[:2]\n        end_square = move[2:4]\n        piece = board.get(start_square, \" \")\n        target_piece = board.get(end_square, \" \")\n\n        # Checkmate moves\n        g = Game(game.get_fen())\n        g.apply_move(move)\n        if g.status == Game.CHECKMATE:\n            debug(f\"Checkmate move: {move}\")\n            return [move]\n\n        # Captures\n        if target_piece != \" \":\n            score = WEIGHTS[\"captures\"] + PIECE_VALUES.get(target_piece.lower(), 0)\n            prioritized_moves.append((move, score))\n            continue\n\n        # Central control\n        if end_square in CENTER_SQUARES:\n            score = WEIGHTS[\"central_control\"]\n            prioritized_moves.append((move, score))\n            continue\n\n        # Checks and Threats\n        g = Game(game.get_fen())\n        g.apply_move(move)\n        if g.status == Game.CHECK:\n            score = WEIGHTS[\"checks\"]\n            prioritized_moves.append((move, score))\n            continue\n\n        # Endgame: King Coordination\n        if phase == \"endgame\":\n            if piece.lower() in {\"q\", \"r\", \"b\"}:  # Aggressive long-range pieces\n                score = WEIGHTS[\"coordination\"] + apply_decay(move)\n                endgame_prioritization.append((move, score))\n                continue\n\n        # Default moves with decay\n        score = apply_decay(move)\n        prioritized_moves.append((move, score))\n\n    # Sort moves by priority\n    prioritized_moves.sort(key=lambda x: x[1], reverse=True)\n    return [move for move, _ in prioritized_moves]\n\ndef chess_bot(obs):\n    \"\"\"Dynamic chess bot with prioritization and strategy.\"\"\"\n    fen = obs['board']\n    game = Game(fen)\n    moves = list(game.get_moves())\n\n    if not moves:\n        return None\n\n    board = fen_to_board(fen)\n    phase = \"endgame\" if len(moves) < 20 else \"midgame\"\n    debug(f\"Game phase: {phase}\")\n\n    opponent_moves = evaluate_opponent_moves(game, moves)\n    debug(f\"Evaluating opponent moves: {len(opponent_moves)} possibilities\")\n\n    prioritized_moves = prioritize_moves(game, moves, phase, board)\n    best_move = prioritized_moves[0] if prioritized_moves else random.choice(moves)\n    debug(f\"Best move: {best_move}\")\n    return best_move\n\n# Test the bot\nif __name__ == \"__main__\":\n    from kaggle_environments import make\n\n    env = make(\"chess\", debug=True)\n\n    result = env.run([\"main.py\", \"random\"])\n    print(\"Agent exit status/reward/time left: \")\n    for agent in result[-1]:\n        print(\"\\t\", agent.status, \"/\", agent.reward, \"/\", agent.observation.remainingOverageTime)\n    env.render(mode=\"ipython\", width=1000, height=1000)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T20:33:45.495699Z","iopub.execute_input":"2024-11-21T20:33:45.496041Z","iopub.status.idle":"2024-11-21T20:33:45.504545Z","shell.execute_reply.started":"2024-11-21T20:33:45.496009Z","shell.execute_reply":"2024-11-21T20:33:45.503578Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Testing your agent\n\nNow let's see how your agent does againt the random agent!","metadata":{}},{"cell_type":"code","source":"result = env.run([\"main.py\", \"random\"])\nprint(\"Agent exit status/reward/time left: \")\n# look at the generated replay.json and print out the agent info\nfor agent in result[-1]:\n    print(\"\\t\", agent.status, \"/\", agent.reward, \"/\", agent.observation.remainingOverageTime)\nprint(\"\\n\")\n# render the game\nenv.render(mode=\"ipython\", width=1000, height=1000) ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T20:33:44.876302Z","iopub.execute_input":"2024-11-21T20:33:44.876623Z","iopub.status.idle":"2024-11-21T20:33:45.493878Z","shell.execute_reply.started":"2024-11-21T20:33:44.876587Z","shell.execute_reply":"2024-11-21T20:33:45.492871Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# To Submit:\n1. Download (or save) main.py\n2. Go to the [submissions page](https://www.kaggle.com/competitions/fide-google-efficiency-chess-ai-challenge/submissions) and click \"Submit Agent\"\n3. Upload main.py\n4. Press Submit!\n\nNow doubt you are already thinking of ways this bot could be improved! Go ahead and fork this notebook and get started! ♟️","metadata":{}},{"cell_type":"markdown","source":"# Submitting Multiple files \n### (or compressing your main.py)\n\nSet up your directory structure like this:\n```\nkaggle_submissions/\n  main.py\n  <other files as desired>\n```\n\nYou can run `tar -czf submission.tar.gz -C kaggle_submissions .` and upload `submission.tar.gz`","metadata":{}}]}