agents.manual_agent
1import asyncio 2from typing import List, Optional, Tuple, Union 3 4from agents.base_agent import BaseUTTTAgent 5 6 7class ManualUTTTAgent(BaseUTTTAgent): 8 """ 9 An agent that allows manual control via the CLI. 10 """ 11 12 async def deliberate( 13 self, 14 board: List[List[int]], 15 macro_board: List[List[int]], 16 active_macro: Optional[List[int]], 17 valid_actions: List[List[int]], 18 ) -> Optional[Union[List[int], Tuple[int, int]]]: 19 """ 20 Prompts the user to enter a move via the command line. 21 22 Args: 23 board (List[List[int]]): The current 9x9 board state. 24 macro_board (List[List[int]]): The current 3x3 macro board state. 25 active_macro (Optional[List[int]]): The active macro board coordinates [my, mx]. 26 valid_actions (List[List[int]]): A list of valid moves [x, y]. 27 28 Returns: 29 Optional[Union[List[int], Tuple[int, int]]]: The chosen move [x, y] or None. 30 """ 31 print(f"\n--- YOUR TURN (Player {self.player_id}) ---") 32 33 # If no active macro, we default to showing the whole board, 34 # but for a 'Free Move', relative coordinates are harder to define. 35 # We will allow the user to pick the macro-board first. 36 if active_macro is None: 37 print(">>> FREE MOVE! Pick any macro-board.") 38 while True: 39 m_input = await asyncio.to_thread( 40 input, "Select Macro-Board [mx,my] (0-2): " 41 ) 42 try: 43 parts = m_input.strip().split(",") 44 if len(parts) != 2: 45 raise ValueError 46 mx, my = [int(i) for i in parts] 47 if 0 <= mx <= 2 and 0 <= my <= 2 and macro_board[my][mx] == 0: 48 active_macro = [my, mx] 49 break 50 print("That macro-board is already finished or invalid.") 51 except ValueError: 52 print("Use format 'mx,my' (e.g., 1,1 for center).") 53 54 my, mx = active_macro 55 print(f">>> Playing in Macro-Board [{mx}, {my}]") 56 57 while True: 58 user_input = await asyncio.to_thread( 59 input, "Enter local move 'x,y' (0-2): " 60 ) 61 62 try: 63 parts = user_input.strip().split(",") 64 if len(parts) != 2: 65 raise ValueError 66 lx, ly = [int(i) for i in parts] 67 # Convert Relative (0-2) to Global (0-8) 68 gx = mx * 3 + lx 69 gy = my * 3 + ly 70 71 if [gx, gy] in valid_actions: 72 return [gx, gy] 73 else: 74 print( 75 f"Invalid local move. Cell ({lx},{ly}) is either taken or out of bounds." 76 ) 77 except (ValueError, IndexError): 78 print("Invalid format. Use 'x,y' where x and y are 0, 1, or 2.") 79 80 81if __name__ == "__main__": 82 agent = ManualUTTTAgent() 83 print("Starting Relative-Coordinate Manual Agent...") 84 asyncio.run(agent.run())
8class ManualUTTTAgent(BaseUTTTAgent): 9 """ 10 An agent that allows manual control via the CLI. 11 """ 12 13 async def deliberate( 14 self, 15 board: List[List[int]], 16 macro_board: List[List[int]], 17 active_macro: Optional[List[int]], 18 valid_actions: List[List[int]], 19 ) -> Optional[Union[List[int], Tuple[int, int]]]: 20 """ 21 Prompts the user to enter a move via the command line. 22 23 Args: 24 board (List[List[int]]): The current 9x9 board state. 25 macro_board (List[List[int]]): The current 3x3 macro board state. 26 active_macro (Optional[List[int]]): The active macro board coordinates [my, mx]. 27 valid_actions (List[List[int]]): A list of valid moves [x, y]. 28 29 Returns: 30 Optional[Union[List[int], Tuple[int, int]]]: The chosen move [x, y] or None. 31 """ 32 print(f"\n--- YOUR TURN (Player {self.player_id}) ---") 33 34 # If no active macro, we default to showing the whole board, 35 # but for a 'Free Move', relative coordinates are harder to define. 36 # We will allow the user to pick the macro-board first. 37 if active_macro is None: 38 print(">>> FREE MOVE! Pick any macro-board.") 39 while True: 40 m_input = await asyncio.to_thread( 41 input, "Select Macro-Board [mx,my] (0-2): " 42 ) 43 try: 44 parts = m_input.strip().split(",") 45 if len(parts) != 2: 46 raise ValueError 47 mx, my = [int(i) for i in parts] 48 if 0 <= mx <= 2 and 0 <= my <= 2 and macro_board[my][mx] == 0: 49 active_macro = [my, mx] 50 break 51 print("That macro-board is already finished or invalid.") 52 except ValueError: 53 print("Use format 'mx,my' (e.g., 1,1 for center).") 54 55 my, mx = active_macro 56 print(f">>> Playing in Macro-Board [{mx}, {my}]") 57 58 while True: 59 user_input = await asyncio.to_thread( 60 input, "Enter local move 'x,y' (0-2): " 61 ) 62 63 try: 64 parts = user_input.strip().split(",") 65 if len(parts) != 2: 66 raise ValueError 67 lx, ly = [int(i) for i in parts] 68 # Convert Relative (0-2) to Global (0-8) 69 gx = mx * 3 + lx 70 gy = my * 3 + ly 71 72 if [gx, gy] in valid_actions: 73 return [gx, gy] 74 else: 75 print( 76 f"Invalid local move. Cell ({lx},{ly}) is either taken or out of bounds." 77 ) 78 except (ValueError, IndexError): 79 print("Invalid format. Use 'x,y' where x and y are 0, 1, or 2.")
An agent that allows manual control via the CLI.
async def
deliberate( self, board: List[List[int]], macro_board: List[List[int]], active_macro: Optional[List[int]], valid_actions: List[List[int]]) -> Union[List[int], Tuple[int, int], NoneType]:
13 async def deliberate( 14 self, 15 board: List[List[int]], 16 macro_board: List[List[int]], 17 active_macro: Optional[List[int]], 18 valid_actions: List[List[int]], 19 ) -> Optional[Union[List[int], Tuple[int, int]]]: 20 """ 21 Prompts the user to enter a move via the command line. 22 23 Args: 24 board (List[List[int]]): The current 9x9 board state. 25 macro_board (List[List[int]]): The current 3x3 macro board state. 26 active_macro (Optional[List[int]]): The active macro board coordinates [my, mx]. 27 valid_actions (List[List[int]]): A list of valid moves [x, y]. 28 29 Returns: 30 Optional[Union[List[int], Tuple[int, int]]]: The chosen move [x, y] or None. 31 """ 32 print(f"\n--- YOUR TURN (Player {self.player_id}) ---") 33 34 # If no active macro, we default to showing the whole board, 35 # but for a 'Free Move', relative coordinates are harder to define. 36 # We will allow the user to pick the macro-board first. 37 if active_macro is None: 38 print(">>> FREE MOVE! Pick any macro-board.") 39 while True: 40 m_input = await asyncio.to_thread( 41 input, "Select Macro-Board [mx,my] (0-2): " 42 ) 43 try: 44 parts = m_input.strip().split(",") 45 if len(parts) != 2: 46 raise ValueError 47 mx, my = [int(i) for i in parts] 48 if 0 <= mx <= 2 and 0 <= my <= 2 and macro_board[my][mx] == 0: 49 active_macro = [my, mx] 50 break 51 print("That macro-board is already finished or invalid.") 52 except ValueError: 53 print("Use format 'mx,my' (e.g., 1,1 for center).") 54 55 my, mx = active_macro 56 print(f">>> Playing in Macro-Board [{mx}, {my}]") 57 58 while True: 59 user_input = await asyncio.to_thread( 60 input, "Enter local move 'x,y' (0-2): " 61 ) 62 63 try: 64 parts = user_input.strip().split(",") 65 if len(parts) != 2: 66 raise ValueError 67 lx, ly = [int(i) for i in parts] 68 # Convert Relative (0-2) to Global (0-8) 69 gx = mx * 3 + lx 70 gy = my * 3 + ly 71 72 if [gx, gy] in valid_actions: 73 return [gx, gy] 74 else: 75 print( 76 f"Invalid local move. Cell ({lx},{ly}) is either taken or out of bounds." 77 ) 78 except (ValueError, IndexError): 79 print("Invalid format. Use 'x,y' where x and y are 0, 1, or 2.")
Prompts the user to enter a move via the command line.
Args: board (List[List[int]]): The current 9x9 board state. macro_board (List[List[int]]): The current 3x3 macro board state. active_macro (Optional[List[int]]): The active macro board coordinates [my, mx]. valid_actions (List[List[int]]): A list of valid moves [x, y].
Returns: Optional[Union[List[int], Tuple[int, int]]]: The chosen move [x, y] or None.