pacai.core.isolation.none
1import logging 2import random 3import typing 4 5import edq.util.time 6 7import pacai.core.action 8import pacai.core.agent 9import pacai.core.agentaction 10import pacai.core.agentinfo 11import pacai.core.gamestate 12import pacai.core.isolation.isolator 13 14class NoneIsolator(pacai.core.isolation.isolator.AgentIsolator): 15 """ 16 An isolator that does not do any isolation between the engine and agents. 17 All agents will be run in the same thread (and therefore processes space). 18 This is the simplest and fastest of all isolators, but offers the least control and protection. 19 Agents cannot be timed out (since they run on the same thread). 20 Agents can also access any memory, disk, or permissions that the core engine has access to. 21 """ 22 23 def __init__(self) -> None: 24 self._agents: dict[int, pacai.core.agent.Agent] = {} 25 """ 26 The agents that this isolator manages. 27 These agents are held and ran in this thread's memory space. 28 """ 29 30 def init_agents(self, agent_infos: dict[int, pacai.core.agentinfo.AgentInfo]) -> None: 31 self._agents = {} 32 for (agent_index, agent_info) in agent_infos.items(): 33 self._agents[agent_index] = pacai.core.agent.load(agent_info) 34 35 def game_start(self, 36 rng: random.Random, 37 initial_state: pacai.core.gamestate.GameState, 38 timeout: float, 39 ) -> dict[int, pacai.core.agentaction.AgentActionRecord]: 40 results = {} 41 for (agent_index, agent) in self._agents.items(): 42 data = { 43 'agent_index': agent_index, 44 'suggested_seed': rng.randint(0, 2**64), 45 'initial_state': initial_state, 46 } 47 48 results[agent_index] = _call_agent_method(agent_index, agent.game_start_full, data) 49 50 return results 51 52 def game_complete(self, 53 final_state: pacai.core.gamestate.GameState, 54 timeout: float, 55 ) -> dict[int, pacai.core.agentaction.AgentActionRecord]: 56 results = {} 57 for (agent_index, agent) in self._agents.items(): 58 data = { 59 'final_state': final_state, 60 } 61 62 results[agent_index] = _call_agent_method(agent_index, agent.game_complete_full, data) 63 64 return results 65 66 def get_action(self, 67 state: pacai.core.gamestate.GameState, 68 user_inputs: list[pacai.core.action.Action], 69 timeout: float, 70 ) -> pacai.core.agentaction.AgentActionRecord: 71 agent = self._agents[state.agent_index] 72 data = { 73 'state': state, 74 'user_inputs': user_inputs, 75 } 76 77 return _call_agent_method(state.agent_index, agent.get_action_full, data) 78 79 def close(self) -> None: 80 self._agents.clear() 81 82def _call_agent_method( 83 agent_index: int, 84 agent_method: typing.Callable[..., pacai.core.agentaction.AgentAction], 85 agent_method_kwargs: dict[str, typing.Any], 86 ) -> pacai.core.agentaction.AgentActionRecord: 87 """ Call a method on the agent and do all the proper bookkeeping. """ 88 89 crashed = False 90 agent_action: pacai.core.agentaction.AgentAction | None = None 91 92 start_time = edq.util.time.Timestamp.now() 93 94 try: 95 agent_action = agent_method(**agent_method_kwargs) 96 except Exception as ex: 97 crashed = True 98 logging.warning("Agent %d crashed.", agent_index, exc_info = ex) 99 100 end_time = edq.util.time.Timestamp.now() 101 102 return pacai.core.agentaction.AgentActionRecord( 103 agent_index = agent_index, 104 agent_action = agent_action, 105 duration = end_time.sub(start_time), 106 crashed = crashed)
15class NoneIsolator(pacai.core.isolation.isolator.AgentIsolator): 16 """ 17 An isolator that does not do any isolation between the engine and agents. 18 All agents will be run in the same thread (and therefore processes space). 19 This is the simplest and fastest of all isolators, but offers the least control and protection. 20 Agents cannot be timed out (since they run on the same thread). 21 Agents can also access any memory, disk, or permissions that the core engine has access to. 22 """ 23 24 def __init__(self) -> None: 25 self._agents: dict[int, pacai.core.agent.Agent] = {} 26 """ 27 The agents that this isolator manages. 28 These agents are held and ran in this thread's memory space. 29 """ 30 31 def init_agents(self, agent_infos: dict[int, pacai.core.agentinfo.AgentInfo]) -> None: 32 self._agents = {} 33 for (agent_index, agent_info) in agent_infos.items(): 34 self._agents[agent_index] = pacai.core.agent.load(agent_info) 35 36 def game_start(self, 37 rng: random.Random, 38 initial_state: pacai.core.gamestate.GameState, 39 timeout: float, 40 ) -> dict[int, pacai.core.agentaction.AgentActionRecord]: 41 results = {} 42 for (agent_index, agent) in self._agents.items(): 43 data = { 44 'agent_index': agent_index, 45 'suggested_seed': rng.randint(0, 2**64), 46 'initial_state': initial_state, 47 } 48 49 results[agent_index] = _call_agent_method(agent_index, agent.game_start_full, data) 50 51 return results 52 53 def game_complete(self, 54 final_state: pacai.core.gamestate.GameState, 55 timeout: float, 56 ) -> dict[int, pacai.core.agentaction.AgentActionRecord]: 57 results = {} 58 for (agent_index, agent) in self._agents.items(): 59 data = { 60 'final_state': final_state, 61 } 62 63 results[agent_index] = _call_agent_method(agent_index, agent.game_complete_full, data) 64 65 return results 66 67 def get_action(self, 68 state: pacai.core.gamestate.GameState, 69 user_inputs: list[pacai.core.action.Action], 70 timeout: float, 71 ) -> pacai.core.agentaction.AgentActionRecord: 72 agent = self._agents[state.agent_index] 73 data = { 74 'state': state, 75 'user_inputs': user_inputs, 76 } 77 78 return _call_agent_method(state.agent_index, agent.get_action_full, data) 79 80 def close(self) -> None: 81 self._agents.clear()
An isolator that does not do any isolation between the engine and agents. All agents will be run in the same thread (and therefore processes space). This is the simplest and fastest of all isolators, but offers the least control and protection. Agents cannot be timed out (since they run on the same thread). Agents can also access any memory, disk, or permissions that the core engine has access to.
31 def init_agents(self, agent_infos: dict[int, pacai.core.agentinfo.AgentInfo]) -> None: 32 self._agents = {} 33 for (agent_index, agent_info) in agent_infos.items(): 34 self._agents[agent_index] = pacai.core.agent.load(agent_info)
Initialize the agents this isolator will be responsible for.
def
game_start( self, rng: random.Random, initial_state: pacai.core.gamestate.GameState, timeout: float) -> dict[int, pacai.core.agentaction.AgentActionRecord]:
36 def game_start(self, 37 rng: random.Random, 38 initial_state: pacai.core.gamestate.GameState, 39 timeout: float, 40 ) -> dict[int, pacai.core.agentaction.AgentActionRecord]: 41 results = {} 42 for (agent_index, agent) in self._agents.items(): 43 data = { 44 'agent_index': agent_index, 45 'suggested_seed': rng.randint(0, 2**64), 46 'initial_state': initial_state, 47 } 48 49 results[agent_index] = _call_agent_method(agent_index, agent.game_start_full, data) 50 51 return results
Pass along the initial game state to each agent and all them the allotted time to start.
def
game_complete( self, final_state: pacai.core.gamestate.GameState, timeout: float) -> dict[int, pacai.core.agentaction.AgentActionRecord]:
53 def game_complete(self, 54 final_state: pacai.core.gamestate.GameState, 55 timeout: float, 56 ) -> dict[int, pacai.core.agentaction.AgentActionRecord]: 57 results = {} 58 for (agent_index, agent) in self._agents.items(): 59 data = { 60 'final_state': final_state, 61 } 62 63 results[agent_index] = _call_agent_method(agent_index, agent.game_complete_full, data) 64 65 return results
Notify all agents that the game is over.
def
get_action( self, state: pacai.core.gamestate.GameState, user_inputs: list[pacai.core.action.Action], timeout: float) -> pacai.core.agentaction.AgentActionRecord:
67 def get_action(self, 68 state: pacai.core.gamestate.GameState, 69 user_inputs: list[pacai.core.action.Action], 70 timeout: float, 71 ) -> pacai.core.agentaction.AgentActionRecord: 72 agent = self._agents[state.agent_index] 73 data = { 74 'state': state, 75 'user_inputs': user_inputs, 76 } 77 78 return _call_agent_method(state.agent_index, agent.get_action_full, data)
Get the current agent's next action. User inputs may be provided by the UI if available.