Bot-Man-Toe/pyclient/__init__.py

81 lines
2.3 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]) -> 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.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)
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.
"""
states = []
current_state = game.empty()
while current_state.winner() is None:
player : int = current_state.player_to_move()
if len(self.agents) < player:
raise KeyError(
f"The client does not have access to {player} players"
)
# Ask for move
agent = self.agents[player]
payload = agent.poll(
game=current_state.action_name(),
payload=current_state.to_dict(),
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"]