Build PyClient turn generator
parent
17e12a12ab
commit
10e808751a
|
|
@ -1,6 +1,6 @@
|
||||||
"""Public client entry points."""
|
"""Public client entry points."""
|
||||||
|
|
||||||
from typing import List, Optional
|
from typing import Any, Generator, List, Optional
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
|
|
@ -39,12 +39,28 @@ class PyClient:
|
||||||
except (requests.exceptions.RequestException, ValueError):
|
except (requests.exceptions.RequestException, ValueError):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def play_game(self, name : str, game, timeout : float = 1.0):
|
def gen_game(self, name : str, game : Any, urls : list[str], timeout : float = 1.0, move_default_if_nonexistent : bool = False) -> Generator[tuple[int, dict[str, Any], Any], None, None]:
|
||||||
"""
|
"""
|
||||||
Play a given game. Ask the registered agents to participate.
|
Play game. Return the results as they've been calculated.
|
||||||
|
|
||||||
|
:param name: Unique identifier string name for the game
|
||||||
|
:type name: str
|
||||||
|
:param game: Game to be played
|
||||||
|
:type game: Any
|
||||||
|
:param urls: List of URLs where players are located
|
||||||
|
:type urls: list[str]
|
||||||
|
:param timeout: Maximum time in seconds to wait for a player to respond
|
||||||
|
:type timeout: float
|
||||||
|
:param move_default_if_nonexistent: If a required player doesn't exist, raise an error. When this is set to true, however, the program will instead assume a player that always takes the default option.
|
||||||
|
:type move_default_if_nonexistent: bool
|
||||||
|
:return: Generator of each turn consisting of a player, what action it took and what that resulted in.
|
||||||
|
:rtype: Generator[tuple[int, dict[str, Any], Any], None, None]
|
||||||
|
:raises KeyError: The number of URLs provided is too low, the game requires more players.
|
||||||
"""
|
"""
|
||||||
agents = [ agent for agent in self.agents if name in agent.games ]
|
agents = [
|
||||||
states = []
|
ServerAgent(url=url, name="", games={}, debug=self.debug)
|
||||||
|
for url in urls
|
||||||
|
]
|
||||||
|
|
||||||
current_state = game.empty()
|
current_state = game.empty()
|
||||||
|
|
||||||
|
|
@ -52,14 +68,19 @@ class PyClient:
|
||||||
player : int = current_state.player_to_move()
|
player : int = current_state.player_to_move()
|
||||||
|
|
||||||
if len(agents) < player:
|
if len(agents) < player:
|
||||||
|
if not move_default_if_nonexistent:
|
||||||
raise KeyError(
|
raise KeyError(
|
||||||
f"{player} players for game {name}, found only {len(agents)}"
|
f"Game requires at least {player} players to exist, found only {len(agents)}"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Ask for move
|
current_state = current_state.move_default()
|
||||||
|
|
||||||
|
yield player, {}, current_state
|
||||||
|
|
||||||
|
else:
|
||||||
agent = agents[player-1]
|
agent = agents[player-1]
|
||||||
payload = agent.poll(
|
payload = agent.poll(
|
||||||
game=current_state.action_name(),
|
game=(name + "/" + current_state.action_name()).strip("/"),
|
||||||
payload=current_state.as_seen_by(player),
|
payload=current_state.as_seen_by(player),
|
||||||
timeout=timeout,
|
timeout=timeout,
|
||||||
)
|
)
|
||||||
|
|
@ -67,10 +88,18 @@ class PyClient:
|
||||||
# Calculate move
|
# Calculate move
|
||||||
current_state = current_state.move(payload)
|
current_state = current_state.move(payload)
|
||||||
|
|
||||||
# Save the results
|
yield player, payload or {}, current_state
|
||||||
states.append((player, payload, current_state))
|
|
||||||
|
|
||||||
return states
|
def play_game(self, name : str, game, timeout : float = 1.0) -> list[tuple[int, dict[str, Any], Any]]:
|
||||||
|
"""
|
||||||
|
Play a given game. Ask the registered agents to participate.
|
||||||
|
"""
|
||||||
|
urls = [ agent.url for agent in self.agents if name in agent.games ]
|
||||||
|
|
||||||
|
return list(self.gen_game(
|
||||||
|
name=name, game=game, urls=urls, timeout=timeout,
|
||||||
|
move_default_if_nonexistent=False,
|
||||||
|
))
|
||||||
|
|
||||||
def verify_host(self, url: str) -> bool:
|
def verify_host(self, url: str) -> bool:
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -169,8 +169,8 @@ class TicTacToe:
|
||||||
f"Index to write to should be 1-9, not {index}"
|
f"Index to write to should be 1-9, not {index}"
|
||||||
)
|
)
|
||||||
|
|
||||||
def action_name(self):
|
def action_name(self) -> str:
|
||||||
return "/tic-tac-toe"
|
return ""
|
||||||
|
|
||||||
def as_seen_by(self, player : int) -> Dict[str, Any]:
|
def as_seen_by(self, player : int) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue