-
-
Notifications
You must be signed in to change notification settings - Fork 107
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improved battle_against
API
#657
base: master
Are you sure you want to change the base?
Changes from 4 commits
d352908
86710a5
9c0734f
7fe4ad3
411a469
f17c415
c19a91e
1630cc5
43e524b
0d4fc51
351cdb2
9deb368
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,15 @@ | ||
"""This module defines a base class for players. | ||
""" | ||
|
||
from __future__ import annotations | ||
|
||
import asyncio | ||
import random | ||
from abc import ABC, abstractmethod | ||
from asyncio import Condition, Event, Queue, Semaphore | ||
from logging import Logger | ||
from time import perf_counter | ||
from typing import Any, Awaitable, Dict, List, Optional, Union | ||
from typing import Any, Awaitable, Dict, List, Optional, Tuple, Union | ||
|
||
import orjson | ||
|
||
|
@@ -692,7 +694,9 @@ async def _ladder(self, n_games: int): | |
perf_counter() - start_time, | ||
) | ||
|
||
async def battle_against(self, opponent: "Player", n_battles: int = 1): | ||
async def battle_against( | ||
self, *opponents: Player, n_battles: int = 1 | ||
) -> Dict[str, Tuple[float, float]]: | ||
"""Make the player play n_battles against opponent. | ||
|
||
This function is a wrapper around send_challenges and accept challenges. | ||
|
@@ -702,17 +706,30 @@ async def battle_against(self, opponent: "Player", n_battles: int = 1): | |
:param n_battles: The number of games to play. Defaults to 1. | ||
:type n_battles: int | ||
""" | ||
await handle_threaded_coroutines(self._battle_against(opponent, n_battles)) | ||
|
||
async def _battle_against(self, opponent: "Player", n_battles: int): | ||
await asyncio.gather( | ||
self.send_challenges( | ||
to_id_str(opponent.username), | ||
n_battles, | ||
to_wait=opponent.ps_client.logged_in, | ||
), | ||
opponent.accept_challenges(to_id_str(self.username), n_battles), | ||
result = await handle_threaded_coroutines( | ||
self._battle_against(*opponents, n_battles=n_battles) | ||
) | ||
return result | ||
|
||
async def _battle_against( | ||
self, *opponents: Player, n_battles: int | ||
) -> Dict[str, Tuple[float, float]]: | ||
results: Dict[str, Tuple[float, float]] = {} | ||
for opponent in opponents: | ||
await asyncio.gather( | ||
self.send_challenges( | ||
to_id_str(opponent.username), | ||
n_battles, | ||
to_wait=opponent.ps_client.logged_in, | ||
), | ||
opponent.accept_challenges( | ||
to_id_str(self.username), n_battles, opponent.next_team | ||
), | ||
) | ||
results[opponent.username] = (self.win_rate, opponent.win_rate) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should bot be part of this method - reporting results is unrelated to starting battles. Similarly, resetting the stored battles after the battles are done would be counterintuitive and make for a bad API. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point! Here you go: f17c415 |
||
self.reset_battles() | ||
opponent.reset_battles() | ||
return results | ||
|
||
async def send_challenges( | ||
self, opponent: str, n_challenges: int, to_wait: Optional[Event] = None | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you update the docstring?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this make
n_battles
a required named argument? If so i'd preferopponent
to be either a player or a list of players, and keepn_battles
from requiring to be named.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated docstring: 411a469
No need to worry, n_battles is still an optional argument - I'm pretty sure the only requirement is that all the opponents are listed before n_battles is specified, and you need to explicitly say "n_battles=..." in order to specify the integer from the Player objects.