83 lines
2.4 KiB
Python
83 lines
2.4 KiB
Python
"""Public client entry points."""
|
|
|
|
from typing import List, Optional
|
|
|
|
import requests
|
|
|
|
from .poll import ServerAgent
|
|
|
|
|
|
class PyClient:
|
|
"""Host games between discovered server agents."""
|
|
|
|
def __init__(self, hosts: List[str], debug : bool = False) -> None:
|
|
"""
|
|
Create a PyClient.
|
|
|
|
:param hosts: URLs of servers that can participate.
|
|
:type hosts: List[str]
|
|
:raises ValueError: If no reachable servers are provided.
|
|
"""
|
|
self.agents: List[ServerAgent] = []
|
|
self.debug = debug
|
|
self.hosts: List[str] = []
|
|
|
|
for host in hosts:
|
|
agent = self.__discover_host(host)
|
|
if agent is not None:
|
|
self.agents.append(agent)
|
|
self.hosts.append(agent.url)
|
|
|
|
if len(self.hosts) <= 0:
|
|
raise ValueError(
|
|
"No valid hosts found! Check your internet connection or verify the URLs are correct."
|
|
)
|
|
|
|
def __discover_host(self, url: str) -> Optional[ServerAgent]:
|
|
try:
|
|
return ServerAgent.from_url(url, debug=self.debug)
|
|
except (requests.exceptions.RequestException, ValueError):
|
|
return None
|
|
|
|
def play_game(self, name : str, game, timeout : float = 1.0):
|
|
"""
|
|
Play a given game. Ask the registered agents to participate.
|
|
"""
|
|
agents = [ agent for agent in self.agents if name in agent.games ]
|
|
states = []
|
|
|
|
current_state = game.empty()
|
|
|
|
while current_state.winner() is None:
|
|
player : int = current_state.player_to_move()
|
|
|
|
if len(agents) < player:
|
|
raise KeyError(
|
|
f"{player} players for game {name}, found only {len(agents)}"
|
|
)
|
|
|
|
# Ask for move
|
|
agent = agents[player-1]
|
|
payload = agent.poll(
|
|
game=current_state.action_name(),
|
|
payload=current_state.as_seen_by(player),
|
|
timeout=timeout,
|
|
)
|
|
|
|
# Calculate move
|
|
current_state = current_state.move(payload)
|
|
|
|
# Save the results
|
|
states.append((player, payload, current_state))
|
|
|
|
return states
|
|
|
|
def verify_host(self, url: str) -> bool:
|
|
"""
|
|
Verify whether the URL seems to contain a link to a playable server.
|
|
"""
|
|
return self.__discover_host(url) is not None
|
|
|
|
|
|
__all__ = ["PyClient", "ServerAgent"]
|