aboutsummaryrefslogtreecommitdiff
path: root/diplomacy/communication/requests.py
diff options
context:
space:
mode:
Diffstat (limited to 'diplomacy/communication/requests.py')
-rw-r--r--diplomacy/communication/requests.py506
1 files changed, 394 insertions, 112 deletions
diff --git a/diplomacy/communication/requests.py b/diplomacy/communication/requests.py
index 6f99f15..f16c33c 100644
--- a/diplomacy/communication/requests.py
+++ b/diplomacy/communication/requests.py
@@ -15,10 +15,70 @@
# with this program. If not, see <https://www.gnu.org/licenses/>.
# ==============================================================================
""" Client -> Server requests.
- Notes:
- If an error occurred on server-side while handling a request, client will receive
- a ResponseException containing message about handling error. Request exceptions
- are currently not more typed on client-side.
+
+ This module contains the definition of request (as classes)
+ that a client can send to Diplomacy server implemented in this project.
+
+ The client -> server communication follows this procedure:
+
+ - Client sends a request to server.
+ All requests have parameters that must be filled by client before being sent.
+ - Server replies with a response, which is either an error response or a valid response.
+ - Client receives and handles server response.
+
+ - If server response is an error, client converts it to a typed exception and raises it.
+ - If server response is a valid response, client return either the response data directly,
+ or make further treatments and return a derived data.
+
+ Diplomacy package actually provides 2 clients: the Python client and the web front-end.
+
+ Web front-end provides user-friendly forms to collect required request parameters,
+ makes all request calls internally, and then uses them to update graphical user interface.
+ So, when using front-end, you don't need to get familiar with underlying protocol, and documentation
+ in this module won't be really useful for you.
+
+ Python client consists of three classes (:class:`.Connection`, :class:`.Channel` and
+ :class:`.NetworkGame`) which provide appropriate methods to automatically send requests, handle
+ server response, and either raise an exception (if server returns an error) or return a client-side
+ wrapped data (if server returns a valid response) where requests were called. Thus, these methods
+ still need to receive request parameters, and you need to know what kind of data they can return.
+ So, if you use Python client, you will need the documentation in this module, which describes, for
+ each request:
+
+ - the request parameters (important)
+ - the server valid responses (less interesting)
+ - the Python client returned values (important)
+
+ All requests classes inherit from :class:`._AbstractRequest` which require parameters
+ ``name`` (from parant class :class:`.NetworkData`), ``request_id`` and ``re_sent``.
+ These parameters are automatically filled by the client.
+
+ From parent class :class:`._AbstractRequest`, we get 3 types of requests:
+
+ - public requests, which directly inherit from :class:`._AbstractRequest`.
+ - channel requests, inherited from :class:`._AbstractChannelRequest`, which requires additional
+ parameter ``token``. Token is retrieved by client when he connected to server using
+ connection request :class:`.SignIn`, and is then used to create a :class:`.Channel` object.
+ Channel object will be responsible for sending all other channel requests, automatically
+ filling token field for these requests.
+ - game requests, intherited from :class:`._AbstractGameRequest`, which itself inherit from
+ :class:`._AbstractChannelRequest`, and requires additional parameters ``game_id``, ``game_role``
+ and ``phase`` (game short phase name). Game ID, role and phase are retrieved for a specific game
+ by the client when he joined a game through one of featured :class:`.Channel` methods which return
+ a :class:`.NetworkGame` object. Network game will then be responsible for sending all other
+ game requests, automatically filling game ID, role and phase for these requests.
+
+ Then, all other requests derived directly from either abstract request class, abstract channel
+ request class, or abstract game request class, may require additional parameters, and if so, these
+ parameters will need to be filled by the user, by passing them to related client methods.
+
+ Check :class:`.Connection` for available public request methods (and associated requests).
+
+ Check :class:`.Channel` for available channel request methods (and associated requests).
+
+ Check :class:`.NetworkGame` for available game request methods (and associated requests).
+
+ Then come here to get parameters and returned values for associated requests.
"""
import inspect
import logging
@@ -34,18 +94,17 @@ LOGGER = logging.getLogger(__name__)
class _AbstractRequest(NetworkData):
""" Abstract request class.
- Field request_id is auto-filled if not defined.
+ Field **request_id** is auto-filled if not defined.
- Field name is auto-filled with snake case version of request class name.
+ Field **name** is auto-filled with snake case version of request class name.
- Field re_sent is False by default. It should be set to True if request is re-sent by client
+ Field **re_sent** is False by default. It should be set to True if request is re-sent by client
(currently done by Connection object when reconnecting).
- Timestamp field is auto-set with current local timestamp if not defined.
+ **Timestamp** field is auto-set with current local timestamp if not defined.
For game request Synchronize, timestamp should be game latest timestamp instead
(see method NetworkGame.synchronize()).
"""
-
__slots__ = ['request_id', 're_sent']
header = {
strings.REQUEST_ID: str,
@@ -57,6 +116,7 @@ class _AbstractRequest(NetworkData):
level = None
def __init__(self, **kwargs):
+ """ Constructor. """
self.request_id = None # type: str
self.re_sent = None # type: bool
super(_AbstractRequest, self).__init__(**kwargs)
@@ -70,7 +130,6 @@ class _AbstractChannelRequest(_AbstractRequest):
""" Abstract class representing a channel request.
Token field is automatically filled by a Channel object before sending request.
"""
-
__slots__ = ['token']
header = parsing.update_model(_AbstractRequest.header, {
strings.TOKEN: str
@@ -85,7 +144,6 @@ class _AbstractGameRequest(_AbstractChannelRequest):
""" Abstract class representing a game request.
Game ID, game role and phase fields are automatically filled by a NetworkGame object before sending request.
"""
-
__slots__ = ['game_id', 'game_role', 'phase']
header = parsing.extend_model(_AbstractChannelRequest.header, {
@@ -115,7 +173,17 @@ class _AbstractGameRequest(_AbstractChannelRequest):
# ====================
class GetDaidePort(_AbstractRequest):
- """ Get game DAIDE port """
+ """ Public request to get DAIDE port opened for a game.
+
+ :param game_id: ID of game for which yu want to get DAIDE port
+ :type game_id: str
+ :return:
+
+ - Server: :class:`.DataPort`
+ - Client: int - DAIDE port
+
+ :raise diplomacy.utils.exceptions.DaidePortException: if there is no DAIDE port associated to given game ID.
+ """
__slots__ = ['game_id']
params = {
strings.GAME_ID: str
@@ -126,9 +194,20 @@ class GetDaidePort(_AbstractRequest):
super(GetDaidePort, self).__init__(**kwargs)
class SignIn(_AbstractRequest):
- """ SignIn request.
- Expected response: responses.DataToken
- Expected response handler result: diplomacy.client.channel.Channel
+ """ Connection request. Log in or sign in to server.
+
+ :param username: account username
+ :param password: account password
+ :param create_user: if True, server must create user. If False, server must login user.
+ :return:
+
+ - Server: :class:`.DataToken`
+ - Client: a :class:`.Channel` object presenting user connected to the server.
+ If any sign in error occurs, raise an appropriate :class:`.ResponseException`.
+
+ :type username: str
+ :type password: str
+ :type create_user: bool
"""
__slots__ = ['username', 'password', 'create_user']
params = {
@@ -148,9 +227,47 @@ class SignIn(_AbstractRequest):
# =================
class CreateGame(_AbstractChannelRequest):
- """ CreateGame request.
- Expected response: responses.DataGame
- Expected response handler result: diplomacy.client.network_game.NetworkGame
+ """ Channel request to create a game.
+
+ :param game_id: game ID. If not provided, a game ID will be generated.
+ :param n_controls: number of controlled powers required to start the game.
+ A power becomes controlled when a player joins the game to control this power.
+ Game won't start as long it does not have this number of controlled powers.
+ Game will stop (to ``forming`` state) if the number of controlled powers decrease under
+ this number (e.g. when powers are kicked, eliminated, or when a player controlling a power
+ leaves the game). If not provided, set with the number of powers on the map (e.g. ``7``
+ on standard map).
+ :param deadline: (default ``300``) time (in seconds) for the game to wait before
+ processing a phase. ``0`` means no deadline, ie. game won't process a phase until either
+ all powers submit orders and turn off wait flag, or a game master forces game to process.
+ :param registration_password: password required to join the game.
+ If not provided, anyone can join the game.
+ :param power_name: power to control once game is created.
+
+ - If provided, the user who send this request will be joined to the game as a player
+ controlling this power.
+ - If not provided, the user who send this request will be joined to the game as an
+ omniscient observer (ie. able to see everything in the game, including user messages).
+ Plus, as game creator, user will also be a game master, ie. able to send master requests,
+ e.g. to force game processing.
+
+ :param state: game initial state (for expert users).
+ :param map_name: (default ``'standard'``) map to play on.
+ You can retrieve maps available on server by sending request :class:`GetAvailableMaps`.
+ :param rules: list of strings - game rules (for expert users).
+ :type game_id: str, optional
+ :type n_controls: int, optional
+ :type deadline: int, optional
+ :type registration_password: str, optional
+ :type power_name: str, optional
+ :type state: dict, optional
+ :type map_name: str, optional
+ :type rules: list, optional
+ :return:
+
+ - Server: :class:`.DataGame`
+ - Client: a :class:`.NetworkGame` object representing a client version of the
+ game created and joined. Either a power game (if power name given) or an omniscient game.
"""
__slots__ = ['game_id', 'power_name', 'state', 'map_name', 'rules', 'n_controls', 'deadline',
'registration_password']
@@ -177,9 +294,15 @@ class CreateGame(_AbstractChannelRequest):
super(CreateGame, self).__init__(**kwargs)
class DeleteAccount(_AbstractChannelRequest):
- """ DeleteAccount request.
- Expected response: responses.Ok
- Expected response handler result: None
+ """ Channel request to delete an account.
+
+ :param username: name of user to delete account
+
+ - if **not** given, then account to delete will be the one of user sending this request.
+ - if **provided**, then user submitting this request must have administrator privileges.
+
+ :type username: str, optional
+ :return: None
"""
__slots__ = ['username']
params = {
@@ -191,9 +314,25 @@ class DeleteAccount(_AbstractChannelRequest):
super(DeleteAccount, self).__init__(**kwargs)
class GetDummyWaitingPowers(_AbstractChannelRequest):
- """ GetDummyWaitingPowers request.
- Expected response: response.DataGamesToPowerNames
- Expected response handler result: {dict mapping game IDs to lists of dummy powers names}
+ """ Channel request to get games with dummy waiting powers.
+ A dummy waiting power is a dummy (not controlled) power:
+
+ - not yet eliminated,
+ - without orders submitted (for current game phase),
+ - but able to submit orders (for current game phase),
+ - and who is waiting for orders.
+
+ It's a non-controlled orderable free power, which is then best suited to be controlled
+ by an automated player (e.g. a bot, or a learning algorithm).
+
+ :param buffer_size: maximum number of powers to return.
+ :type buffer_size: int
+ :return:
+
+ - Server: :class:`.DataGamesToPowerNames`
+ - Client: a dictionary mapping a game ID to a list of dummy waiting power names,
+ such that the total number of power names in the entire dictionary does not exceed
+ given buffer size.
"""
__slots__ = ['buffer_size']
params = {
@@ -205,16 +344,26 @@ class GetDummyWaitingPowers(_AbstractChannelRequest):
super(GetDummyWaitingPowers, self).__init__(**kwargs)
class GetAvailableMaps(_AbstractChannelRequest):
- """ GetAvailableMaps request.
- Expected response: responses.DataMaps
- Expected response handler result: {map name => [map power names]}
+ """ Channel request to get maps available on server.
+
+ :return:
+
+ - Server: :class:`.DataMaps`
+ - Client: a dictionary associating a map name to a dictionary of information related
+ to the map. You can especially check key ``'powers'`` to get the list of map power names.
"""
__slots__ = []
class GetPlayablePowers(_AbstractChannelRequest):
- """ GetPlayablePowers request.
- Expected response: responses.DataPowerNames
- Expected response handler result: [power names]
+ """ Channel request to get the list of playable powers for a game.
+ A playable power is a dummy (uncontrolled) power not yet eliminated.
+
+ :param game_id: ID of game to get playable powers
+ :type game_id: str
+ :return:
+
+ - Server: :class:`.DataPowerNames`
+ - Client: set of playable power names for given game ID.
"""
__slots__ = ['game_id']
params = {
@@ -226,9 +375,32 @@ class GetPlayablePowers(_AbstractChannelRequest):
super(GetPlayablePowers, self).__init__(**kwargs)
class JoinGame(_AbstractChannelRequest):
- """ JoinGame request.
- Expected response: responses.DataGame
- Expected response handler result: diplomacy.client.network_game.NetworkGame
+ """ Channel request to join a game.
+
+ :param game_id: ID of game to join
+ :param power_name: if provided, name of power to control. Otherwise,
+ user wants to observe game without playing.
+ :param registration_password: password to join game. If omitted while
+ game requires a password, server will return an error.
+ :type game_id: str
+ :type power_name: str, optional
+ :type registration_password: str, optional
+ :return:
+
+ - Server: :class:`.DataGame`
+ - Client: a :class:`.NetworkGame` object representing the client game, which is either:
+
+ - a power game (if power name was given), meaning that this network game allows user
+ to play a power
+ - an observer game, if power was not given and user does not have omniscient privileges
+ for this game. Observer role allows user to watch game phases changes, orders submitted
+ and orders results for each phase, but he can not see user messages and he can not
+ send any request that requires game master privileges.
+ - an omniscient game, if power was not given and user does have game master privileges.
+ Omniscient role allows user to see everything in the game, including user messages.
+ If user does only have omniscient privileges for this game, he can't do anything more,
+ If he does have up to game master privileges, then he can also send requests that
+ require game master privileges.
"""
__slots__ = ['game_id', 'power_name', 'registration_password']
params = {
@@ -244,10 +416,22 @@ class JoinGame(_AbstractChannelRequest):
super(JoinGame, self).__init__(**kwargs)
class JoinPowers(_AbstractChannelRequest):
- """ JoinPowers request to join many powers of a game with one query.
- Useful to control many powers while still working only with 1 client game instance.
- Expected response: responses.Ok
- Expected response handler result: None
+ """ Channel request to join many powers of a game with one request.
+
+ This request is mostly identical to :class:`.JoinGame`, except that list of power names
+ is mandatory. It's useful to allow the user to control many powers while still working
+ with 1 client game instance.
+
+ :param game_id: ID of game to join
+ :param power_names: list of power names to join
+ :param registration_password: password to join the game
+ :type game_id: str
+ :type power_names: list, optional
+ :type registration_password: str, optionl
+ :return: None. If request succeeds, then the user is registered as player for all
+ given power names. The user can then simply join game to one of these powers (by sending
+ a :class:`.JoinGame` request), and he will be able to manage all the powers through
+ the client game returned by :class:`.JoinGame`.
"""
__slots__ = ['game_id', 'power_names', 'registration_password']
params = {
@@ -263,9 +447,23 @@ class JoinPowers(_AbstractChannelRequest):
super(JoinPowers, self).__init__(**kwargs)
class ListGames(_AbstractChannelRequest):
- """ ListGames request.
- Expected response: responses.DataGames
- Expected response handler result: responses.DataGames
+ """ Channel request to find games.
+
+ :param game_id: if provided, look for games with game ID either containing or contained into this game ID.
+ :param status: if provided, look for games with this status.
+ :param map_name: if provided, look for games with this map name.
+ :param include_protected: (default True) tell if we must look into games protected by a password
+ :param for_omniscience: (default False) tell if we look for games where request user can be at least omniscient.
+ :type game_id: str, optional
+ :type status: str, optional
+ :type map_name: str, optional
+ :type include_protected: bool optional
+ :type for_omniscience: bool, optional
+ :return:
+
+ - Server: :class:`.DataGames`
+ - Client: a list of :class:`.DataGameInfo` objects, each containing
+ a bunch of information about a game found. If no game found, list will be empty.
"""
__slots__ = ['game_id', 'status', 'map_name', 'include_protected', 'for_omniscience']
params = {
@@ -285,36 +483,53 @@ class ListGames(_AbstractChannelRequest):
super(ListGames, self).__init__(**kwargs)
class GetGamesInfo(_AbstractChannelRequest):
- """ Request used to get info for a given list of game IDs.
- Expected response: responses.DataGames
- Expected response handler result: responses.DataGames
+ """ Channel request to get information for a given list of game indices.
+
+ :param games: list of game ID.
+ :type games: list
+ :return:
+
+ - Server: :class:`.DataGames`
+ - Client: a list of :class:`.DataGameInfo` objects.
"""
__slots__ = ['games']
params = {
strings.GAMES: parsing.SequenceType(str)
}
+
def __init__(self, **kwargs):
self.games = []
super(GetGamesInfo, self).__init__(**kwargs)
class Logout(_AbstractChannelRequest):
- """ Logout request.
- Expected response: responses.Ok
- Expected response handler result: None
- """
+ """ Channel request to logout. Returns nothing. """
__slots__ = []
class UnknownToken(_AbstractChannelRequest):
- """ Request to tell server that a channel token is unknown.
- Expected response: Nothing - Client does not even wait for a server response.
- Expected response handler result: None
+ """ Channel request to tell server that a channel token is unknown.
+
+ .. note::
+
+ Client does not even wait for a server response when sending this request,
+ which acts more like a "client notification" sent to server.
"""
__slots__ = []
class SetGrade(_AbstractChannelRequest):
- """ SetGrade request.
- Expected response: responses.Ok
- Expected response handler result: None
+ """ Channel request to modify the grade of a user.
+ Require admin privileges to change admin grade, and at least game master privileges
+ to change omniscient or moderator grade.
+
+ :param grade: grade to update (``'omniscient'``, ``'admin'`` or ``'moderator'``)
+ :param grade_update: how to make update (``'promote'`` or ``'demote'``)
+ :param username: user for which the grade must be modified
+ :param game_id: ID of game for which the grade must be modified.
+ Required only for ``'moderator'`` and ``'omniscient'`` grade.
+ :type grade: str
+ :type grade_update: str
+ :type username: str
+ :type game_id: str, optional
+ :return: None
"""
__slots__ = ['grade', 'grade_update', 'username', 'game_id']
params = {
@@ -336,9 +551,11 @@ class SetGrade(_AbstractChannelRequest):
# ==============
class ClearCenters(_AbstractGameRequest):
- """ ClearCenters request.
- Expected response: responses.Ok
- Expected response handler result: None
+ """ Game request to clear supply centers. See method :meth:`.Game.clear_centers`.
+
+ :param power_name: if given, clear centers for this power. Otherwise, clear centers for all powers.
+ :type power_name: str, optional
+ :return: None
"""
__slots__ = ['power_name']
params = {
@@ -350,9 +567,11 @@ class ClearCenters(_AbstractGameRequest):
super(ClearCenters, self).__init__(**kwargs)
class ClearOrders(_AbstractGameRequest):
- """ ClearOrders request.
- Expected response: responses.Ok
- Expected response handler result: None
+ """ Game request to clear orders.
+
+ :param power_name: if given, clear orders for this power. Otherwise, clear orders for all powers.
+ :type power_name: str, optional
+ :return: None
"""
__slots__ = ['power_name']
params = {
@@ -364,9 +583,11 @@ class ClearOrders(_AbstractGameRequest):
super(ClearOrders, self).__init__(**kwargs)
class ClearUnits(_AbstractGameRequest):
- """ ClearUnits request.
- Expected response: responses.Ok
- Expected response handler result: None
+ """ Game request to clear units.
+
+ :param power_name: if given, clear units for this power. Otherwise, clear units for all powers.
+ :type power_name: str, optional
+ :return: None
"""
__slots__ = ['power_name']
params = {
@@ -378,25 +599,31 @@ class ClearUnits(_AbstractGameRequest):
super(ClearUnits, self).__init__(**kwargs)
class DeleteGame(_AbstractGameRequest):
- """ DeleteGame request.
- Expected response: responses.Ok
- Expected response handler result: None
- """
+ """ Game request to delete a game. Require game master privileges. Returns nothing. """
__slots__ = []
phase_dependent = False
class GetAllPossibleOrders(_AbstractGameRequest):
- """ GetAllPossibleOrders request.
- Expected response: response.DataPossibleOrders
- Expected response handler result: response.DataPossibleOrders
+ """ Game request to get all possible orders.
+ Return (server and client) a :class:`.DataPossibleOrders` object
+ containing possible orders and orderable locations.
"""
__slots__ = []
class GetPhaseHistory(_AbstractGameRequest):
- """ Get a list of game phase data from game history for given phases interval.
+ """ Game request to get a list of game phase data from game history for given phases interval.
A phase can be either None, a phase name (string) or a phase index (integer).
- Expected response: responses.DataGamePhases
- Expected response handler result: [GamePhaseData objects]
+ See :meth:`.Game.get_phase_history` about how phases are used to retrieve game phase data.
+
+ :param from_phase: phase from which to look in game history
+ :param to_phase: phase up to which to look in game history
+ :type from_phase: str | int, optional
+ :type to_phase: str | int, optional
+ :return:
+
+ - Server: DataGamePhases
+ - Client: a list of :class:`.GamePhaseData` objects corresponding to game phases
+ found between ``from_phase`` and ``to_phase`` in game history.
"""
__slots__ = ['from_phase', 'to_phase']
params = {
@@ -411,37 +638,44 @@ class GetPhaseHistory(_AbstractGameRequest):
super(GetPhaseHistory, self).__init__(**kwargs)
class LeaveGame(_AbstractGameRequest):
- """ LeaveGame request.
- Expected response: responses.Ok
- Expected response handler result: None
+ """ Game request to leave a game (logout from game). If request power name is set
+ (ie. request user was a player), then power will become uncontrolled.
+ Otherwise, user will be signed out from its observer (or omniscient) role.
+ Returns nothing.
"""
__slots__ = []
class ProcessGame(_AbstractGameRequest):
- """ ProcessGame request.
- Expected response: responses.Ok
- Expected response handler result: None
- """
+ """ Game request to force a game processing. Require master privileges. Return nothing. """
__slots__ = []
class QuerySchedule(_AbstractGameRequest):
- """ Query server for info about current scheduling for a game.
- Expected response: response.DataGameSchedule
- Expected response handler result: response.DataGameSchedule
+ """ Game request to get info about current scheduling for a game in server.
+ Returns (server and client) a :class:`.DataGameSchedule` object.
"""
__slots__ = []
class SaveGame(_AbstractGameRequest):
- """ Get game saved format in JSON.
- Expected response: response.DataSavedGame
- Expected response handler result: response.DataSavedGame
+ """ Game request to get game exported in JSON format.
+
+ :return:
+
+ - Server: :class:`.DataSavedGame`
+ - Client: dict - the JSON dictionary.
"""
__slots__ = []
class SendGameMessage(_AbstractGameRequest):
- """ SendGameMessage request.
- Expected response: responses.DataTimeStamp
- Expected response handler result: None
+ """ Game message to send a user request.
+
+ :param message: message to send. See :class:`.Message` for more info.
+ message sender must be request user role (ie. power role, in such case).
+ Message time sent must not be defined, it will be allocated by server.
+ :type message: Message
+ :return:
+
+ - Server: :class:`.DataTimeStamp`
+ - Client: nothing (returned timestamp is just used to update message locally)
"""
__slots__ = ['message']
params = {
@@ -453,9 +687,15 @@ class SendGameMessage(_AbstractGameRequest):
super(SendGameMessage, self).__init__(**kwargs)
class SetDummyPowers(_AbstractGameRequest):
- """ SetDummyPowers request.
- Expected response: responses.Ok
- Expected response handler result: None
+ """ Game request to set dummy powers. Require game master privileges.
+ If given powers are controlled, related players are kicked
+ and powers become dummy (uncontrolled).
+
+ :param power_names: list of power names to set dummy. If not provided, will be all map power names.
+ :param username: if provided, only power names controlled by this user will be set dummy.
+ :type power_names: list, optional
+ :type user_name: str, optional
+ :return: None
"""
__slots__ = ['username', 'power_names']
params = {
@@ -469,9 +709,17 @@ class SetDummyPowers(_AbstractGameRequest):
super(SetDummyPowers, self).__init__(**kwargs)
class SetGameState(_AbstractGameRequest):
- """ Request to set a game state.
- Expected response: responses.Ok
- Expected response handler result: None
+ """ Game request to set a game state (for exper users). Require game master privileges.
+
+ :param state: game state
+ :param orders: dictionary mapping a power name to a list of orders strings
+ :param results: dictionary mapping a unit to a list of order result strings
+ :param messages: dictionary mapping a timestamp to a message
+ :type state: dict
+ :type orders: dict
+ :type results: dict
+ :type messages: dict
+ :return: None
"""
__slots__ = ['state', 'orders', 'results', 'messages']
params = {
@@ -489,9 +737,18 @@ class SetGameState(_AbstractGameRequest):
super(SetGameState, self).__init__(**kwargs)
class SetGameStatus(_AbstractGameRequest):
- """ SetGameStatus request.
- Expected response: responses.Ok
- Expected response handler result: None
+ """ Game request to force game status (only if new status differs from previous one).
+ Require game master privileges.
+
+ :param status: game status to set.
+ Either ``'forming'``, ``'active'``, ``'paused'``, ``'completed'`` or ``'canceled'``.
+
+ - If new status is ``'completed'``, game will be forced to draw.
+ - If new status is ``'active'``, game will be forced to start.
+ - If new status is ``'paused'``, game will be forced to pause.
+ - If new status is ``'canceled'``, game will be canceled and become invalid.
+ :type status: str
+ :return: None
"""
__slots__ = ['status']
params = {
@@ -503,9 +760,16 @@ class SetGameStatus(_AbstractGameRequest):
super(SetGameStatus, self).__init__(**kwargs)
class SetOrders(_AbstractGameRequest):
- """ SetOrders request.
- Expected response: responses.Ok
- Expected response handler result: None
+ """ Game request to set orders for a power.
+
+ :param power_name: power name. If not given, request user must be a game player,
+ and power is inferred from request game role.
+ :param orders: list of power orders.
+ :param wait: if provided, wait flag to set for this power.
+ :type power_name: str, optional
+ :type orders: list
+ :type wait: bool, optional
+ :return: None
"""
__slots__ = ['power_name', 'orders', 'wait']
params = {
@@ -521,9 +785,14 @@ class SetOrders(_AbstractGameRequest):
super(SetOrders, self).__init__(**kwargs)
class SetWaitFlag(_AbstractGameRequest):
- """ SetWaitFlag request.
- Expected response: responses.Ok
- Expected response handler result: None
+ """ Game request to set orders for a power.
+
+ :param power_name: power name. If not given, request user must be a game player,
+ and power if inferred from request game role.
+ :param wait: wait flag to set.
+ :type power_name: str, optional
+ :type wait: bool
+ :return: None
"""
__slots__ = ['power_name', 'wait']
params = {
@@ -537,9 +806,13 @@ class SetWaitFlag(_AbstractGameRequest):
super(SetWaitFlag, self).__init__(**kwargs)
class Synchronize(_AbstractGameRequest):
- """ Synchronize request.
- Expected response: responses.DataGameInfo
- Expected response handler result: DataGameInfo
+ """ Game request to force synchronization of client game with server game.
+ If necessary, server will send appropriate notifications to client game so that it can
+ be up to date with server game state.
+
+ :param timestamp: timestamp since which client game needs to synchronize.
+ :type timestamp: int
+ :return: (server and client) a :class:`.DataGameInfo` object.
"""
__slots__ = ['timestamp']
params = {
@@ -552,11 +825,18 @@ class Synchronize(_AbstractGameRequest):
super(Synchronize, self).__init__(**kwargs)
class Vote(_AbstractGameRequest):
- """ Vote request.
- For powers only.
- Allow a power to vote about game draw for current phase.
- Expected response: responses.Ok
- Expected response handler result: None
+ """ Game request to vote for draw decision.
+ If number of pro-draw votes > number of con-draw votes for current phase,
+ then server will automatically draw the game and send appropriate notifications.
+ Votes are reset after a game processing.
+
+ :param power_name: power name who wants to vote. If not provided, request user must be a game player,
+ and power name will be inferred from request game role.
+ :param vote: vote to set. Either ``'yes'`` (power votes for draw), ``'no'`` (power votes against draw),
+ or ``'neutral'`` (power does not want to decide).
+ :type power_name: str, optional
+ :type vote: str
+ :return: None
"""
__slots__ = ['power_name', 'vote']
params = {
@@ -570,7 +850,9 @@ class Vote(_AbstractGameRequest):
super(Vote, self).__init__(**kwargs)
def parse_dict(json_request):
- """ Parse a JSON dictionary expected to represent a request. Raise an exception if parsing failed.
+ """ Parse a JSON dictionary expected to represent a request.
+ Raise an exception if parsing failed.
+
:param json_request: JSON dictionary.
:return: a request class instance.
:type json_request: dict