diff options
author | Satya Ortiz-Gagne <satya.ortiz-gagne@mila.quebec> | 2019-06-06 12:28:35 -0400 |
---|---|---|
committer | Philip Paquette <pcpaquette@gmail.com> | 2019-06-07 20:02:12 -0400 |
commit | 5b9cdac02446dc1f74e4a06ab129aa9ad1c13e88 (patch) | |
tree | 789324fd84b14dcc04e611149cb37001c2b46272 | |
parent | 3acc6a82b843af55acb672a292a171ff9a7df328 (diff) |
DAIDE - Implemented all the DAIDE requests
- NME = NameRequest
- OBS = ObserverRequest
- IAM = IAmRequest
- HLO = HelloRequest
- MAP = MapRequest
- MDF = MapDefinitionRequest
- SCO = SupplyCentreOwnershipRequest
- NOW = CurrentPositionRequest
- HST = HistoryRequest
- SUB = SubmitOrdersRequest
- MIS = MissingOrdersRequest
- GOF = GoFlagRequest
- TME = TimeToDeadlineRequest
- DRW = DrawRequest
- SND = SendMessageRequest
- NOT = NotRequest
- YES = AcceptRequest
- REJ = RejectRequest
- PRN = ParenthesisErrorRequest
- HUH = SyntaxErrorRequest
- ADM = AdminMessageRequest
-rw-r--r-- | diplomacy/daide/requests.py | 779 | ||||
-rw-r--r-- | diplomacy/daide/tests/test_requests.py | 886 | ||||
-rw-r--r-- | diplomacy/utils/strings.py | 8 |
3 files changed, 1673 insertions, 0 deletions
diff --git a/diplomacy/daide/requests.py b/diplomacy/daide/requests.py new file mode 100644 index 0000000..0a47a52 --- /dev/null +++ b/diplomacy/daide/requests.py @@ -0,0 +1,779 @@ +# ============================================================================== +# Copyright (C) 2019 - Philip Paquette +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Affero General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +# details. +# +# You should have received a copy of the GNU Affero General Public License along +# with this program. If not, see <https://www.gnu.org/licenses/>. +# ============================================================================== +""" Daide Requests - Contains a list of requests sent by client to server """ +from diplomacy.communication.requests import _AbstractGameRequest +from diplomacy.daide.clauses import String, Number, Power, Order, Turn, SingleToken, strip_parentheses, \ + break_next_group, parse_bytes +from diplomacy.daide import tokens +from diplomacy.daide.tokens import Token, is_ascii_token +from diplomacy.utils import parsing, strings + +class RequestBuilder(): + """ Builds DaideRequest from bytes or tokens """ + @staticmethod + def from_bytes(daide_bytes, **kwargs): + """ Builds a request from DAIDE bytes + :param daide_bytes: The bytes representation of a request + :return: The DaideRequest built from the bytes + """ + if len(daide_bytes) < 2: + return None + initial_bytes = daide_bytes[:2] + if initial_bytes not in __REQUEST_CONSTRUCTORS__: + raise ValueError('Unable to find a constructor for %s' % str(Token(from_bytes=initial_bytes))) + request = __REQUEST_CONSTRUCTORS__[initial_bytes](**kwargs) # type: DaideRequest + request.parse_bytes(daide_bytes) + return request + +class DaideRequest(_AbstractGameRequest): + """ Represents a DAIDE request. """ + def __init__(self, **kwargs): + """ Constructor """ + self._bytes = b'' + self._str = '' + super(DaideRequest, self).__init__(token='', + game_id='', + game_role='', + phase='', + **kwargs) + + def __bytes__(self): + """ Returning the bytes representation of the request """ + return self._bytes + + def __str__(self): + """ Returning the string representation of the request """ + return self._str + + def parse_bytes(self, daide_bytes): + """ Builds the request from DAIDE bytes """ + assert len(daide_bytes) % 2 == 0, 'Expected request to have an even number of bytes. Got %d' % len(daide_bytes) + self._bytes = daide_bytes + + # Building str representation + while daide_bytes: + token = Token(from_bytes=(daide_bytes[0], daide_bytes[1])) + new_str = str(token) + daide_bytes = daide_bytes[2:] + pad = '' if (not self._str + or self._str[-1] == '(' + or new_str == ')' + or (is_ascii_token(token) and new_str != '(')) else ' ' + self._str = self._str + pad + new_str + + +# ==================== +# Connection requests +# ==================== + +class NameRequest(DaideRequest): + """ Represents a NME DAIDE request. Can be sent by the client as soon as it connects to the server. + Syntax: + NME ('name') ('version') + """ + __slots__ = ['client_name', 'client_version'] + params = { + strings.CLIENT_NAME: str, + strings.CLIENT_VERSION: str + } + + def __init__(self, **kwargs): + """ Constructor """ + self.client_name = '' + self.client_version = '' + super(NameRequest, self).__init__(client_name='', client_version='', **kwargs) + + def parse_bytes(self, daide_bytes): + """ Builds the request from DAIDE bytes """ + super(NameRequest, self).parse_bytes(daide_bytes) + + # Parsing + lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes) + client_name, daide_bytes = parse_bytes(String, daide_bytes) + client_version, daide_bytes = parse_bytes(String, daide_bytes) + assert str(lead_token) == 'NME', 'Expected NME request' + assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes) + + # Setting properties + self.client_name = str(client_name) + self.client_version = str(client_version) + +class ObserverRequest(DaideRequest): + """ Represents a NME DAIDE request. Can be sent by the client as soon as it connects to the server. + Syntax: + OBS + """ + __slots__ = [] + params = {} + + def parse_bytes(self, daide_bytes): + """ Builds the request from DAIDE bytes """ + super(ObserverRequest, self).parse_bytes(daide_bytes) + + # Parsing + lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes) + assert str(lead_token) == 'OBS', 'Expected OBS request' + assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes) + +class IAmRequest(DaideRequest): + """ Represents a IAM DAIDE request. Can be sent by the client at anytime to rejoin the game. + Syntax: + IAM (power) (passcode) + """ + __slots__ = ['power_name', 'passcode'] + params = { + strings.POWER_NAME: str, + strings.PASSCODE: parsing.OptionalValueType(int) + } + + def __init__(self, **kwargs): + """ Constructor """ + self.power_name = '' + self.passcode = 0 + super(IAmRequest, self).__init__(power_name='', passcode=0, **kwargs) + + def parse_bytes(self, daide_bytes): + """ Builds the request from DAIDE bytes """ + super(IAmRequest, self).parse_bytes(daide_bytes) + + # Parsing + lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes) + assert str(lead_token) == 'IAM', 'Expected IAM request' + + # Power + power_group_bytes, daide_bytes = break_next_group(daide_bytes) + power_group_bytes = strip_parentheses(power_group_bytes) + power, power_group_bytes = parse_bytes(Power, power_group_bytes) + assert not power_group_bytes, '%s bytes remaining in power group. Request is malformed' % len(power_group_bytes) + + # Passcode + passcode_group_bytes, daide_bytes = break_next_group(daide_bytes) + passcode_group_bytes = strip_parentheses(passcode_group_bytes) + passcode, passcode_group_bytes = parse_bytes(SingleToken, passcode_group_bytes) + assert not passcode_group_bytes, '%s bytes remaining in passcode group. Req. error' % len(passcode_group_bytes) + assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes) + + # Setting properties + self.power_name = str(power) + self.passcode = str(passcode) + +class HelloRequest(DaideRequest): + """ Represents a HLO DAIDE request. Sent by the client to request a copy of the HLO message. + Syntax: + HLO + """ + __slots__ = [] + params = {} + + def parse_bytes(self, daide_bytes): + """ Builds the request from DAIDE bytes """ + super(HelloRequest, self).parse_bytes(daide_bytes) + + # Parsing + lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes) + assert str(lead_token) == 'HLO', 'Expected HLO request' + assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes) + +class MapRequest(DaideRequest): + """ Represents a MAP DAIDE request. Sent by the client to request a copy of the MAP message. + Syntax: + MAP + """ + __slots__ = [] + params = {} + + def parse_bytes(self, daide_bytes): + """ Builds the request from DAIDE bytes """ + super(MapRequest, self).parse_bytes(daide_bytes) + + # Parsing + lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes) + assert str(lead_token) == 'MAP', 'Expected MAP request' + assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes) + +class MapDefinitionRequest(DaideRequest): + """ Represents a MDF DAIDE request. Sent by the client to request the map definition of the game. + Syntax: + MDF + """ + __slots__ = [] + params = {} + + def parse_bytes(self, daide_bytes): + """ Builds the request from DAIDE bytes """ + super(MapDefinitionRequest, self).parse_bytes(daide_bytes) + + # Parsing + lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes) + assert str(lead_token) == 'MDF', 'Expected MDF request' + assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes) + + +# ==================== +# Game updates +# ==================== + +class SupplyCentreOwnershipRequest(DaideRequest): + """ Represents a SCO DAIDE request. Sent by the client to request a copy of the last SCO message. + Syntax: + SCO + """ + __slots__ = [] + params = {} + + def parse_bytes(self, daide_bytes): + """ Builds the request from DAIDE bytes """ + super(SupplyCentreOwnershipRequest, self).parse_bytes(daide_bytes) + + # Parsing + lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes) + assert str(lead_token) == 'SCO', 'Expected SCO request' + assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes) + +class CurrentPositionRequest(DaideRequest): + """ Represents a NOW DAIDE request. Sent by the client to request a copy of the last NOW message. + Syntax: + NOW + """ + __slots__ = [] + params = {} + + def parse_bytes(self, daide_bytes): + """ Builds the request from DAIDE bytes """ + super(CurrentPositionRequest, self).parse_bytes(daide_bytes) + + # Parsing + lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes) + assert str(lead_token) == 'NOW', 'Expected NOW request' + assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes) + +class HistoryRequest(DaideRequest): + """ Represents a HST DAIDE request. Sent by the client to request a copy of a previous ORD, SCO and NOW messages. + Syntax: + HST (turn) + """ + def __init__(self, **kwargs): + """ Constructor """ + self.phase = '' + super(HistoryRequest, self).__init__(**kwargs) + + def parse_bytes(self, daide_bytes): + """ Builds the request from DAIDE bytes """ + super(HistoryRequest, self).parse_bytes(daide_bytes) + + # Parsing + lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes) + assert str(lead_token) == 'HST', 'Expected HST request' + + # Turn + turn, daide_bytes = parse_bytes(Turn, daide_bytes) + assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes) + + # Setting properties + self.phase = str(turn) + + +# ==================== +# Orders +# ==================== + +class SubmitOrdersRequest(DaideRequest): + """ Represents a SUB DAIDE request. Sent by the client to submit orders. + Syntax: + SUB (order) (order) ... + SUB (turn) (order) (order) ... + order syntax: + (unit) HLD # Hold + (unit) MTO province # Move to + (unit) SUP (unit) # Support + (unit) SUP (unit) MTO (prov_no_coast) # Support to move + (unit) CVY (unit) CTO province # Convoy + (unit) CTO province VIA (sea_prov sea_prov ...) # Convoy to via provinces + (unit) RTO province # Retreat to + (unit) DSB # Disband (R phase) + (unit) BLD # Build + (unit) REM # Remove (A phase) + (unit) WVE # Waive + """ + __slots__ = ['power_name', 'orders'] + params = { + strings.POWER_NAME: parsing.OptionalValueType(str), + strings.ORDERS: parsing.SequenceType(str) + } + + def __init__(self, **kwargs): + """ Constructor """ + self.power_name = None + self.phase = '' + self.orders = [] + super(SubmitOrdersRequest, self).__init__(power_name='', orders=[], **kwargs) + + def parse_bytes(self, daide_bytes): + """ Builds the request from DAIDE bytes """ + super(SubmitOrdersRequest, self).parse_bytes(daide_bytes) + orders = [] + + # Parsing + lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes) + turn, daide_bytes = parse_bytes(Turn, daide_bytes, on_error='ignore') + while daide_bytes: + order, daide_bytes = parse_bytes(Order, daide_bytes) + orders += [order] + assert str(lead_token) == 'SUB', 'Expected SUB request' + assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes) + + # Setting properties + self.phase = '' if not turn else str(turn) + self.power_name = None if not orders or not orders[0].power_name else str(orders[0].power_name) + self.orders = [str(order) for order in orders] + +class MissingOrdersRequest(DaideRequest): + """ Represents a MIS DAIDE request. Sent by the client to request a copy of the current MIS message. + Syntax: + MIS + """ + __slots__ = [] + params = {} + + def parse_bytes(self, daide_bytes): + """ Builds the request from DAIDE bytes """ + super(MissingOrdersRequest, self).parse_bytes(daide_bytes) + + # Parsing + lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes) + assert str(lead_token) == 'MIS', 'Expected MIS request' + assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes) + +class GoFlagRequest(DaideRequest): + """ Represents a GOF DAIDE request. Sent by the client to notify that the client is ready to process the turn. + Syntax: + GOF + """ + __slots__ = [] + params = {} + + def parse_bytes(self, daide_bytes): + """ Builds the request from DAIDE bytes """ + super(GoFlagRequest, self).parse_bytes(daide_bytes) + + # Parsing + lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes) + assert str(lead_token) == 'GOF', 'Expected GOF request' + assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes) + + +# ==================== +# Deadline +# ==================== + +class TimeToDeadlineRequest(DaideRequest): + """ Represents a TME DAIDE request. Sent by the client to request a TME message or to request it at a later time. + Syntax: + TME + TME (seconds) + """ + __slots__ = ['seconds'] + params = { + strings.SECONDS: parsing.OptionalValueType(int) + } + + def __init__(self, **kwargs): + """ Constructor """ + self.seconds = None + super(TimeToDeadlineRequest, self).__init__(seconds=0, **kwargs) + + def parse_bytes(self, daide_bytes): + """ Builds the request from DAIDE bytes """ + super(TimeToDeadlineRequest, self).parse_bytes(daide_bytes) + + # Parsing + lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes) + seconds_group_bytes, daide_bytes = break_next_group(daide_bytes) + assert str(lead_token) == 'TME', 'Expected TME request' + + # Seconds + if seconds_group_bytes: + seconds_group_bytes = strip_parentheses(seconds_group_bytes) + seconds, daide_bytes = parse_bytes(Number, seconds_group_bytes) + assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes) + + # Setting properties + self.seconds = None if not seconds_group_bytes else int(seconds) + + +# ==================== +# End of the game +# ==================== + +class DrawRequest(DaideRequest): + """ Represents a DRW DAIDE request. Sent by the client to notify that the client would accept a draw. + Syntax: + DRW + LVL 10: + DRW (power power ...) + """ + __slots__ = ['powers'] + params = { + strings.POWERS: parsing.SequenceType(str) + } + + def __init__(self, **kwargs): + """ Constructor """ + self.powers = [] + super(DrawRequest, self).__init__(powers=[], **kwargs) + + def parse_bytes(self, daide_bytes): + """ Builds the request from DAIDE bytes """ + super(DrawRequest, self).parse_bytes(daide_bytes) + powers = [] + + # Parsing + lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes) + assert str(lead_token) == 'DRW', 'Expected DRW request' + + # Powers + powers_group_bytes, daide_bytes = break_next_group(daide_bytes) + if powers_group_bytes: + powers_group_bytes = strip_parentheses(powers_group_bytes) + while powers_group_bytes: + power, powers_group_bytes = parse_bytes(Power, powers_group_bytes) + powers += [power] + + assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes) + + # Setting properties + self.powers = [str(power) for power in powers] + + +# ==================== +# Messaging +# ==================== + +class SendMessageRequest(DaideRequest): + """ Represents a SND DAIDE request + Syntax: + SND (power ...) (press_message) + SND (power ...) (reply) + SND (turn) (power ...) (press_message) + SND (turn) (power ...) (reply) + Press message syntax: + PRP (arrangement) + CCL (press_message) + FCT (arrangement) + TRY (tokens) + Reply syntax: + YES (press_message) + REJ (press_message) + BWX (press_message) + HUH (press_message) + """ + __slots__ = ['powers', 'message_bytes'] + params = { + strings.POWERS: parsing.SequenceType(str), + strings.MESSAGE_BYTES: parsing.OptionalValueType(str), + } + + def __init__(self, **kwargs): + """ Constructor """ + self.phase = '' + self.powers = [] + self.message_bytes = None + super(SendMessageRequest, self).__init__(powers=[], press_message='', reply='', **kwargs) + + def parse_bytes(self, daide_bytes): + """ Builds the request from DAIDE bytes """ + super(SendMessageRequest, self).parse_bytes(daide_bytes) + + # Parsing + lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes) + assert str(lead_token) == 'SND', 'Expected SND request' + + # Turn + turn, daide_bytes = parse_bytes(Turn, daide_bytes, on_error='ignore') + + # Powers + powers = [] + powers_group_bytes, daide_bytes = break_next_group(daide_bytes) + powers_group_bytes = strip_parentheses(powers_group_bytes) + while powers_group_bytes: + power, powers_group_bytes = parse_bytes(Power, powers_group_bytes) + powers += [power] + assert powers, 'Expected a group of `power`. Request is malformed' + + # Press message or reply + message_group_bytes, daide_bytes = break_next_group(daide_bytes) + message_group_bytes = strip_parentheses(message_group_bytes) + assert message_group_bytes, 'Expected a `press_message` or a `reply`. Request is malformed' + assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes) + + # Setting properties + self.phase = '' if not turn else str(turn) + self.powers = [str(power) for power in powers] + self.message_bytes = message_group_bytes + +# ==================== +# Cancel Request +# ==================== + +class NotRequest(DaideRequest): + """ Represents a NOT DAIDE request. Sent by the client to cancel a previous request. + Syntax: + NOT (SUB) # Cancel all submitted orders + NOT (SUB (order)) # Cancel specific submitted order + NOT (GOF) # Do not process orders until the deadline + NOT (TME) # Cancel all requested time messages + NOT (TME (seconds)) # Cancel specific requested time message + NOT (DRW) # Cancel all draw requests + """ + __slots__ = ['request'] + params = { + strings.REQUEST: parsing.JsonableClassType(DaideRequest) + } + + def __init__(self, **kwargs): + """ Constructor """ + self.request = None # type: DaideRequest + super(NotRequest, self).__init__(request=DaideRequest(), **kwargs) + + def parse_bytes(self, daide_bytes): + """ Builds the request from DAIDE bytes """ + super(NotRequest, self).parse_bytes(daide_bytes) + + # Parsing + lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes) + request_group_bytes, daide_bytes = break_next_group(daide_bytes) + assert str(lead_token) == 'NOT', 'Expected NOT request' + + # Request + request_group_bytes = strip_parentheses(request_group_bytes) + request = RequestBuilder.from_bytes(request_group_bytes) + assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes) + + # Setting properties + self.request = request + +# ======================== +# Accept / Reject Response +# ======================== + +class AcceptRequest(DaideRequest): + """ Represents a YES DAIDE request. + Syntax: + YES (MAP ('name')) + YES (SVE ('gamename')) + """ + __slots__ = ['response_bytes'] + params = { + strings.RESPONSE_BYTES: bytes + } + + def __init__(self, **kwargs): + """ Constructor """ + self.response_bytes = b'' + super(AcceptRequest, self).__init__(response_bytes=b'', **kwargs) + + def parse_bytes(self, daide_bytes): + """ Builds the request from DAIDE bytes """ + super(AcceptRequest, self).parse_bytes(daide_bytes) + + # Parsing + lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes) + response_bytes, daide_bytes = break_next_group(daide_bytes) + response_bytes = strip_parentheses(response_bytes) + assert str(lead_token) == 'YES', 'Expected YES request' + assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes) + + # Setting properties + self.response_bytes = response_bytes + +class RejectRequest(DaideRequest): + """ Represents a REJ DAIDE request. + Syntax: + REJ (SVE ('gamename')) + """ + __slots__ = ['response_bytes'] + params = { + strings.RESPONSE_BYTES: bytes + } + + def __init__(self, **kwargs): + """ Constructor """ + self.response_bytes = b'' + super(RejectRequest, self).__init__(response_bytes=b'', **kwargs) + + def parse_bytes(self, daide_bytes): + """ Builds the request from DAIDE bytes """ + super(RejectRequest, self).parse_bytes(daide_bytes) + + # Parsing + lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes) + response_bytes, daide_bytes = break_next_group(daide_bytes) + response_bytes = strip_parentheses(response_bytes) + assert str(lead_token) == 'REJ', 'Expected REJ request' + assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes) + + # Setting properties + self.response_bytes = response_bytes + +# ==================== +# Errors +# ==================== + +class ParenthesisErrorRequest(DaideRequest): + """ Represents a PRN DAIDE request. Sent by the client to specify an error in the set of parenthesis. + Syntax: + PRN (message) + """ + __slots__ = ['message_bytes'] + params = { + strings.MESSAGE_BYTES: bytes + } + + def __init__(self, **kwargs): + """ Constructor """ + self.message_bytes = b'' + super(ParenthesisErrorRequest, self).__init__(message_bytes=b'', **kwargs) + + def parse_bytes(self, daide_bytes): + """ Builds the request from DAIDE bytes """ + super(ParenthesisErrorRequest, self).parse_bytes(daide_bytes) + + # Parsing + lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes) + message_bytes, daide_bytes = break_next_group(daide_bytes) + if message_bytes: + message_bytes = strip_parentheses(message_bytes) + else: + message_bytes = strip_parentheses(daide_bytes) + daide_bytes = b'' + assert str(lead_token) == 'PRN', 'Expected PRN request' + assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes) + + # Setting properties + self.message_bytes = message_bytes + +class SyntaxErrorRequest(DaideRequest): + """ Represents a HUH DAIDE request. Sent by the client to specify an error in a message. + Syntax: + HUH (message) + """ + __slots__ = ['message_bytes'] + params = { + strings.MESSAGE_BYTES: bytes + } + + def __init__(self, **kwargs): + """ Constructor """ + self.message_bytes = b'' + super(SyntaxErrorRequest, self).__init__(message_bytes=b'', **kwargs) + + def parse_bytes(self, daide_bytes): + """ Builds the request from DAIDE bytes """ + super(SyntaxErrorRequest, self).parse_bytes(daide_bytes) + + # Parsing + lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes) + message_bytes, daide_bytes = break_next_group(daide_bytes) + message_bytes = strip_parentheses(message_bytes) + assert str(lead_token) == 'HUH', 'Expected HUH request' + assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes) + + # Setting properties + self.message_bytes = message_bytes + + +# ==================== +# Admin Messages +# ==================== + +class AdminMessageRequest(DaideRequest): + """ Represents a ADM DAIDE request. Can be sent by the client to send a message to all clients. + Should not be used for negotiation. + + Syntax: + ADM ('message') + """ + __slots__ = ['adm_message'] + params = { + strings.ADM_MESSAGE: str + } + + def __init__(self, **kwargs): + """ Constructor """ + self.adm_message = '' + super(AdminMessageRequest, self).__init__(adm_message='', **kwargs) + + def parse_bytes(self, daide_bytes): + """ Builds the request from DAIDE bytes """ + super(AdminMessageRequest, self).parse_bytes(daide_bytes) + + # Parsing + lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes) + adm_message, daide_bytes = parse_bytes(String, daide_bytes) + assert str(lead_token) == 'ADM', 'Expected ADM request' + assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes) + + # Setting properties + self.adm_message = str(adm_message) + +# ===================== +# Constants and aliases +# ===================== +NME = NameRequest +OBS = ObserverRequest +IAM = IAmRequest +HLO = HelloRequest +MAP = MapRequest +MDF = MapDefinitionRequest +SCO = SupplyCentreOwnershipRequest +NOW = CurrentPositionRequest +HST = HistoryRequest +SUB = SubmitOrdersRequest +MIS = MissingOrdersRequest +GOF = GoFlagRequest +TME = TimeToDeadlineRequest +DRW = DrawRequest +SND = SendMessageRequest +NOT = NotRequest +YES = AcceptRequest +REJ = RejectRequest +PRN = ParenthesisErrorRequest +HUH = SyntaxErrorRequest +ADM = AdminMessageRequest + +# Constants +__REQUEST_CONSTRUCTORS__ = {bytes(tokens.NME): NME, + bytes(tokens.OBS): OBS, + bytes(tokens.IAM): IAM, + bytes(tokens.HLO): HLO, + bytes(tokens.MAP): MAP, + bytes(tokens.MDF): MDF, + bytes(tokens.SCO): SCO, + bytes(tokens.NOW): NOW, + bytes(tokens.HST): HST, + bytes(tokens.SUB): SUB, + bytes(tokens.MIS): MIS, + bytes(tokens.GOF): GOF, + bytes(tokens.TME): TME, + bytes(tokens.DRW): DRW, + bytes(tokens.SND): SND, + bytes(tokens.NOT): NOT, + bytes(tokens.YES): YES, + bytes(tokens.REJ): REJ, + bytes(tokens.PRN): PRN, + bytes(tokens.HUH): HUH, + bytes(tokens.ADM): ADM} diff --git a/diplomacy/daide/tests/test_requests.py b/diplomacy/daide/tests/test_requests.py new file mode 100644 index 0000000..96e50e6 --- /dev/null +++ b/diplomacy/daide/tests/test_requests.py @@ -0,0 +1,886 @@ +# ============================================================================== +# Copyright (C) 2019 - Philip Paquette +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Affero General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +# details. +# +# You should have received a copy of the GNU Affero General Public License along +# with this program. If not, see <https://www.gnu.org/licenses/>. +# ============================================================================== +""" Tests for request objects """ +from diplomacy.daide import requests, tokens +from diplomacy.daide.requests import RequestBuilder +from diplomacy.daide.utils import str_to_bytes + +def test_nme_001(): + """ Tests the NME request """ + daide_str = 'NME ( A l b e r t ) ( v 6 . 0 . 1 )' + expected_str = 'NME (Albert) (v6.0.1)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.NME), 'Expected a NME request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.client_name == 'Albert' + assert request.client_version == 'v6.0.1' + +def test_nme_002(): + """ Tests the NME request """ + daide_str = 'NME ( J o h n D o e ) ( v 1 . 2 )' + expected_str = 'NME (JohnDoe) (v1.2)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.NME), 'Expected a NME request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.client_name == 'JohnDoe' + assert request.client_version == 'v1.2' + +def test_obs(): + """ Test the OBS request """ + daide_str = 'OBS' + expected_str = 'OBS' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.OBS), 'Expected a OBS request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + +def test_iam(): + """ Test the IAM request """ + daide_str = 'IAM ( FRA ) ( #1234 )' + expected_str = 'IAM (FRA) (1234)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.IAM), 'Expected a IAM request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.power_name == 'FRANCE' + assert request.passcode == '1234' + +def test_hlo(): + """ Test the HLO request """ + daide_str = 'HLO' + expected_str = 'HLO' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.HLO), 'Expected a HLO request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + +def test_map(): + """ Test the MAP request """ + daide_str = 'MAP' + expected_str = 'MAP' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.MAP), 'Expected a MAP request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + +def test_mdf(): + """ Test the MDF request """ + daide_str = 'MDF' + expected_str = 'MDF' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.MDF), 'Expected a MDF request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + +def test_sco(): + """ Test the SCO request """ + daide_str = 'SCO' + expected_str = 'SCO' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SCO), 'Expected a SCO request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + +def test_now(): + """ Test the NOW request """ + daide_str = 'NOW' + expected_str = 'NOW' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.NOW), 'Expected a NOW request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + +def test_hst_spr(): + """ Tests the HST request """ + daide_str = 'HST ( SPR #1901 )' + expected_str = 'HST (SPR 1901)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.HST), 'Expected a HST request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == 'S1901M' + +def test_sub_spr_hold(): + """ Tests the SUB request """ + daide_str = 'SUB ( SPR #1901 ) ( ( ENG AMY LVP ) HLD )' + expected_str = 'SUB (SPR 1901) ((ENG AMY LVP) HLD)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == 'S1901M' + assert request.power_name == 'ENGLAND' + assert request.orders == ['A LVP H'] + +def test_sub_sum_hold(): + """ Tests the SUB request """ + daide_str = 'SUB ( SUM #1902 ) ( ( ENG AMY LVP ) HLD )' + expected_str = 'SUB (SUM 1902) ((ENG AMY LVP) HLD)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == 'S1902R' + assert request.power_name == 'ENGLAND' + assert request.orders == ['A LVP H'] + +def test_sub_fal_hold(): + """ Tests the SUB request """ + daide_str = 'SUB ( FAL #1903 ) ( ( ENG AMY LVP ) HLD )' + expected_str = 'SUB (FAL 1903) ((ENG AMY LVP) HLD)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == 'F1903M' + assert request.power_name == 'ENGLAND' + assert request.orders == ['A LVP H'] + +def test_sub_aut_hold(): + """ Tests the SUB request """ + daide_str = 'SUB ( AUT #1904 ) ( ( ENG AMY LVP ) HLD )' + expected_str = 'SUB (AUT 1904) ((ENG AMY LVP) HLD)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == 'F1904R' + assert request.power_name == 'ENGLAND' + assert request.orders == ['A LVP H'] + +def test_sub_win_hold(): + """ Tests the SUB request """ + daide_str = 'SUB ( WIN #1905 ) ( ( ENG AMY LVP ) HLD )' + expected_str = 'SUB (WIN 1905) ((ENG AMY LVP) HLD)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == 'W1905A' + assert request.power_name == 'ENGLAND' + assert request.orders == ['A LVP H'] + +def test_sub_austria_hold(): + """ Tests the SUB request """ + daide_str = 'SUB ( ( AUS AMY LVP ) HLD )' + expected_str = 'SUB ((AUS AMY LVP) HLD)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.power_name == 'AUSTRIA' + assert request.orders == ['A LVP H'] + +def test_sub_english_hold(): + """ Tests the SUB request """ + daide_str = 'SUB ( ( ENG AMY LVP ) HLD )' + expected_str = 'SUB ((ENG AMY LVP) HLD)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.power_name == 'ENGLAND' + assert request.orders == ['A LVP H'] + +def test_sub_france_hold(): + """ Tests the SUB request """ + daide_str = 'SUB ( ( FRA AMY LVP ) HLD )' + expected_str = 'SUB ((FRA AMY LVP) HLD)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.power_name == 'FRANCE' + assert request.orders == ['A LVP H'] + +def test_sub_germany_hold(): + """ Tests the SUB request """ + daide_str = 'SUB ( ( GER AMY LVP ) HLD )' + expected_str = 'SUB ((GER AMY LVP) HLD)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.power_name == 'GERMANY' + assert request.orders == ['A LVP H'] + +def test_sub_italy_hold(): + """ Tests the SUB request """ + daide_str = 'SUB ( ( ITA AMY LVP ) HLD )' + expected_str = 'SUB ((ITA AMY LVP) HLD)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.power_name == 'ITALY' + assert request.orders == ['A LVP H'] + +def test_sub_russia_hold(): + """ Tests the SUB request """ + daide_str = 'SUB ( ( RUS AMY LVP ) HLD )' + expected_str = 'SUB ((RUS AMY LVP) HLD)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.power_name == 'RUSSIA' + assert request.orders == ['A LVP H'] + +def test_sub_turkey_hold(): + """ Tests the SUB request """ + daide_str = 'SUB ( ( TUR AMY LVP ) HLD )' + expected_str = 'SUB ((TUR AMY LVP) HLD)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.power_name == 'TURKEY' + assert request.orders == ['A LVP H'] + +def test_sub_fleet_hold(): + """ Tests the SUB request """ + daide_str = 'SUB ( ( ENG FLT LVP ) HLD )' + expected_str = 'SUB ((ENG FLT LVP) HLD)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.power_name == 'ENGLAND' + assert request.orders == ['F LVP H'] + +def test_sub_eng_ech_hold(): + """ Tests the SUB request """ + daide_str = 'SUB ( ( FRA FLT ECH ) HLD )' + expected_str = 'SUB ((FRA FLT ECH) HLD)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.power_name == 'FRANCE' + assert request.orders == ['F ENG H'] + +def test_sub_gob_bot_hold(): + """ Tests the SUB request """ + daide_str = 'SUB ( ( FRA FLT GOB ) HLD )' + expected_str = 'SUB ((FRA FLT GOB) HLD)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.power_name == 'FRANCE' + assert request.orders == ['F BOT H'] + +def test_sub_gol_lyo_hold(): + """ Tests the SUB request """ + daide_str = 'SUB ( ( FRA FLT GOL ) HLD )' + expected_str = 'SUB ((FRA FLT GOL) HLD)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.power_name == 'FRANCE' + assert request.orders == ['F LYO H'] + +def test_sub_move(): + """ Tests the SUB request """ + daide_str = 'SUB ( ( ENG FLT LON ) MTO NTH )' + expected_str = 'SUB ((ENG FLT LON) MTO NTH)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.power_name == 'ENGLAND' + assert request.orders == ['F LON - NTH'] + +def test_sub_move_coast(): + """ Tests the SUB request """ + daide_str = 'SUB ( ( ENG FLT BAR ) MTO ( STP NCS ) )' + expected_str = 'SUB ((ENG FLT BAR) MTO (STP NCS))' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.power_name == 'ENGLAND' + assert request.orders == ['F BAR - STP/NC'] + +def test_sub_support_hold_001(): + """ Tests the SUB request """ + daide_str = 'SUB ( ( ENG FLT EDI ) SUP ( ENG FLT LON ) )' + expected_str = 'SUB ((ENG FLT EDI) SUP (ENG FLT LON))' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.power_name == 'ENGLAND' + assert request.orders == ['F EDI S F LON'] + +def test_sub_support_hold_002(): + """ Tests the SUB request """ + daide_str = 'SUB ( ( ENG FLT NWY ) SUP ( ENG FLT BAR ) )' + expected_str = 'SUB ((ENG FLT NWY) SUP (ENG FLT BAR))' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.power_name == 'ENGLAND' + assert request.orders == ['F NWY S F BAR'] + +def test_sub_support_hold_003(): + """ Tests the SUB request """ + daide_str = 'SUB ( ( ENG FLT NWG ) SUP ( ENG AMY YOR ) )' + expected_str = 'SUB ((ENG FLT NWG) SUP (ENG AMY YOR))' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.power_name == 'ENGLAND' + assert request.orders == ['F NWG S A YOR'] + +def test_sub_support_move_001(): + """ Tests the SUB request """ + daide_str = 'SUB ( ( ENG FLT EDI ) SUP ( ENG FLT LON ) MTO NTH )' + expected_str = 'SUB ((ENG FLT EDI) SUP (ENG FLT LON) MTO NTH)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.power_name == 'ENGLAND' + assert request.orders == ['F EDI S F LON - NTH'] + +def test_sub_support_move_002(): + """ Tests the SUB request """ + daide_str = 'SUB ( ( ENG FLT NWY ) SUP ( ENG FLT BAR ) MTO STP )' + expected_str = 'SUB ((ENG FLT NWY) SUP (ENG FLT BAR) MTO STP)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.power_name == 'ENGLAND' + assert request.orders == ['F NWY S F BAR - STP'] + +def test_sub_support_move_003(): + """ Tests the SUB request """ + daide_str = 'SUB ( ( ENG FLT NWG ) SUP ( ENG AMY YOR ) MTO NWY )' + expected_str = 'SUB ((ENG FLT NWG) SUP (ENG AMY YOR) MTO NWY)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.power_name == 'ENGLAND' + assert request.orders == ['F NWG S A YOR - NWY'] + +def test_sub_move_via_001(): + """ Tests the SUB request """ + daide_str = 'SUB ( ( ITA AMY TUN ) CTO SYR VIA ( ION EAS ) )' + expected_str = 'SUB ((ITA AMY TUN) CTO SYR VIA (ION EAS))' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.power_name == 'ITALY' + assert request.orders == ['A TUN - SYR VIA'] + +def test_sub_move_via_002(): + """ Tests the SUB request """ + daide_str = 'SUB ( ( ENG AMY YOR ) CTO NWY VIA ( NTH ) )' + expected_str = 'SUB ((ENG AMY YOR) CTO NWY VIA (NTH))' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.power_name == 'ENGLAND' + assert request.orders == ['A YOR - NWY VIA'] + +def test_sub_convoy_001(): + """ Tests the SUB request """ + daide_str = 'SUB ( ( ITA FLT ION ) CVY ( ITA AMY TUN ) CTO SYR )' + expected_str = 'SUB ((ITA FLT ION) CVY (ITA AMY TUN) CTO SYR)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.power_name == 'ITALY' + assert request.orders == ['F ION C A TUN - SYR'] + +def test_sub_convoy_002(): + """ Tests the SUB request """ + daide_str = 'SUB ( ( ITA FLT EAS ) CVY ( ITA AMY TUN ) CTO SYR )' + expected_str = 'SUB ((ITA FLT EAS) CVY (ITA AMY TUN) CTO SYR)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.power_name == 'ITALY' + assert request.orders == ['F EAS C A TUN - SYR'] + +def test_sub_convoy_003(): + """ Tests the SUB request """ + daide_str = 'SUB ( ( ENG FLT NTH ) CVY ( ENG AMY YOR ) CTO STP )' + expected_str = 'SUB ((ENG FLT NTH) CVY (ENG AMY YOR) CTO STP)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.power_name == 'ENGLAND' + assert request.orders == ['F NTH C A YOR - STP'] + +def test_sub_retreat(): + """ Tests the SUB request """ + daide_str = 'SUB ( ( ENG FLT LON ) RTO NTH )' + expected_str = 'SUB ((ENG FLT LON) RTO NTH)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.power_name == 'ENGLAND' + assert request.orders == ['F LON R NTH'] + +def test_sub_retreat_coast(): + """ Tests the SUB request """ + daide_str = 'SUB ( ( ENG FLT LON ) RTO ( STP NCS ) )' + expected_str = 'SUB ((ENG FLT LON) RTO (STP NCS))' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.power_name == 'ENGLAND' + assert request.orders == ['F LON R STP/NC'] + +def test_sub_disband(): + """ Tests the SUB request """ + daide_str = 'SUB ( ( RUS FLT GOB ) DSB )' + expected_str = 'SUB ((RUS FLT GOB) DSB)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.power_name == 'RUSSIA' + assert request.orders == ['F BOT D'] + +def test_sub_build(): + """ Tests the SUB request """ + daide_str = 'SUB ( ( ITA FLT NAP ) BLD )' + expected_str = 'SUB ((ITA FLT NAP) BLD)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.power_name == 'ITALY' + assert request.orders == ['F NAP B'] + +def test_sub_remove(): + """ Tests the SUB request """ + daide_str = 'SUB ( ( RUS FLT GOB ) REM )' + expected_str = 'SUB ((RUS FLT GOB) REM)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.power_name == 'RUSSIA' + assert request.orders == ['F BOT D'] + +def test_sub_waive(): + """ Tests the SUB request """ + daide_str = 'SUB ( ENG WVE )' + expected_str = 'SUB (ENG WVE)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.power_name == 'ENGLAND' + assert request.orders == ['WAIVE'] + +def test_sub_multi_001(): + """ Tests the SUB request """ + daide_str = 'SUB ( ( ENG AMY LVP ) HLD ) ' \ + '( ( ENG FLT LON ) MTO NTH ) ' \ + '( ( ENG FLT EDI ) SUP ( ENG FLT LON ) MTO NTH )' + expected_str = 'SUB ((ENG AMY LVP) HLD) ' \ + '((ENG FLT LON) MTO NTH) ' \ + '((ENG FLT EDI) SUP (ENG FLT LON) MTO NTH)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.power_name == 'ENGLAND' + assert request.orders == ['A LVP H', 'F LON - NTH', 'F EDI S F LON - NTH'] + +def test_sub_multi_002(): + """ Tests the SUB request """ + daide_str = 'SUB ( ( ENG FLT BAR ) MTO ( STP NCS ) ) ' \ + '( ( ITA FLT NWY ) SUP ( ENG FLT BAR ) MTO STP )' + expected_str = 'SUB ((ENG FLT BAR) MTO (STP NCS)) ' \ + '((ITA FLT NWY) SUP (ENG FLT BAR) MTO STP)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.power_name == 'ENGLAND' + assert request.orders == ['F BAR - STP/NC', 'F NWY S F BAR - STP'] + +def test_sub_multi_003(): + """ Tests the SUB request """ + daide_str = 'SUB ( ( ITA AMY TUN ) CTO SYR VIA ( ION EAS ) ) ' \ + '( ( ITA FLT ION ) CVY ( ITA AMY TUN ) CTO SYR ) ' \ + '( ( ITA FLT EAS ) CVY ( ITA AMY TUN ) CTO SYR )' + expected_str = 'SUB ((ITA AMY TUN) CTO SYR VIA (ION EAS)) ' \ + '((ITA FLT ION) CVY (ITA AMY TUN) CTO SYR) ' \ + '((ITA FLT EAS) CVY (ITA AMY TUN) CTO SYR)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.power_name == 'ITALY' + assert request.orders == ['A TUN - SYR VIA', 'F ION C A TUN - SYR', 'F EAS C A TUN - SYR'] + +def test_sub_multi_004(): + """ Tests the SUB request """ + daide_str = 'SUB ( ( ENG AMY YOR ) CTO NWY VIA ( NTH ) ) ' \ + '( ( ENG FLT NTH ) CVY ( ENG AMY YOR ) CTO NWY ) ' \ + '( ( ENG FLT NWG ) SUP ( ENG AMY YOR ) MTO NWY )' + expected_str = 'SUB ((ENG AMY YOR) CTO NWY VIA (NTH)) ' \ + '((ENG FLT NTH) CVY (ENG AMY YOR) CTO NWY) ' \ + '((ENG FLT NWG) SUP (ENG AMY YOR) MTO NWY)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SUB), 'Expected a SUB request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.power_name == 'ENGLAND' + assert request.orders == ['A YOR - NWY VIA', 'F NTH C A YOR - NWY', 'F NWG S A YOR - NWY'] + +def test_mis(): + """ Test the MIS request """ + daide_str = 'MIS' + expected_str = 'MIS' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.MIS), 'Expected a MIS request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + +def test_gof(): + """ Test the GOF request """ + daide_str = 'GOF' + expected_str = 'GOF' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.GOF), 'Expected a GOF request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + +def test_tme(): + """ Tests the TME request """ + daide_str = 'TME' + expected_str = 'TME' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.TME), 'Expected a TME request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.seconds is None + +def test_tme_sec(): + """ Tests the TME request """ + daide_str = 'TME ( #60 )' + expected_str = 'TME (60)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.TME), 'Expected a TME request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.seconds == 60 + +def test_drw_001(): + """ Test the DRW request """ + daide_str = 'DRW' + expected_str = 'DRW' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.DRW), 'Expected a DRW request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.powers == [] + +def test_drw_002(): + """ Test the DRW request """ + daide_str = 'DRW ( FRA ENG ITA )' + expected_str = 'DRW (FRA ENG ITA)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.DRW), 'Expected a DRW request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.powers == ['FRANCE', 'ENGLAND', 'ITALY'] + +def test_snd_001(): + """ Tests the SND request """ + daide_str = 'SND ( FRA ENG ) ( PRP ( PCE ( FRA ENG GER ) ) )' + expected_str = 'SND (FRA ENG) (PRP (PCE (FRA ENG GER)))' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SND), 'Expected a SND request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.powers == ['FRANCE', 'ENGLAND'] + assert request.message_bytes == str_to_bytes('PRP ( PCE ( FRA ENG GER ) )') + +def test_snd_002(): + """ Tests the SND request """ + daide_str = 'SND ( SPR #1901 ) ( FRA ENG ) ( PRP ( PCE ( FRA ENG GER ) ) )' + expected_str = 'SND (SPR 1901) (FRA ENG) (PRP (PCE (FRA ENG GER)))' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SND), 'Expected a SND request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == 'S1901M' + assert request.powers == ['FRANCE', 'ENGLAND'] + assert request.message_bytes == str_to_bytes('PRP ( PCE ( FRA ENG GER ) )') + +def test_snd_003(): + """ Tests the SND request """ + daide_str = 'SND ( FRA ENG ) ( CCL ( PRP ( PCE ( FRA ENG GER ) ) ) )' + expected_str = 'SND (FRA ENG) (CCL (PRP (PCE (FRA ENG GER))))' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SND), 'Expected a SND request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.powers == ['FRANCE', 'ENGLAND'] + assert request.message_bytes == str_to_bytes('CCL ( PRP ( PCE ( FRA ENG GER ) ) )') + +def test_snd_004(): + """ Tests the SND request """ + daide_str = 'SND ( FRA ENG ) ( FCT ( PCE ( FRA ENG GER ) ) )' + expected_str = 'SND (FRA ENG) (FCT (PCE (FRA ENG GER)))' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SND), 'Expected a SND request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.powers == ['FRANCE', 'ENGLAND'] + assert request.message_bytes == str_to_bytes('FCT ( PCE ( FRA ENG GER ) )') + +def test_snd_005(): + """ Tests the SND request """ + daide_str = 'SND ( FRA ENG ) ( TRY ( PRP PCE ALY VSS DRW SLO NOT YES REJ BWX ) )' + expected_str = 'SND (FRA ENG) (TRY (PRP PCE ALY VSS DRW SLO NOT YES REJ BWX))' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SND), 'Expected a SND request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.powers == ['FRANCE', 'ENGLAND'] + assert request.message_bytes == str_to_bytes('TRY ( PRP PCE ALY VSS DRW SLO NOT YES REJ BWX )') + +def test_snd_006(): + """ Tests the SND request """ + daide_str = 'SND ( FRA GER ) ( YES ( PRP ( ALY ( FRA ENG GER ) VSS ( ITA ) ) ) )' + expected_str = 'SND (FRA GER) (YES (PRP (ALY (FRA ENG GER) VSS (ITA))))' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SND), 'Expected a SND request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.powers == ['FRANCE', 'GERMANY'] + assert request.message_bytes == str_to_bytes('YES ( PRP ( ALY ( FRA ENG GER ) VSS ( ITA ) ) )') + +def test_snd_007(): + """ Tests the SND request """ + daide_str = 'SND ( FRA GER ) ( REJ ( PRP ( ALY ( FRA ENG GER ) VSS ( ITA ) ) ) )' + expected_str = 'SND (FRA GER) (REJ (PRP (ALY (FRA ENG GER) VSS (ITA))))' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SND), 'Expected a SND request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.powers == ['FRANCE', 'GERMANY'] + assert request.message_bytes == str_to_bytes('REJ ( PRP ( ALY ( FRA ENG GER ) VSS ( ITA ) ) )') + +def test_snd_008(): + """ Tests the SND request """ + daide_str = 'SND ( FRA GER ) ( BWX ( PRP ( ALY ( FRA ENG GER ) VSS ( ITA ) ) ) )' + expected_str = 'SND (FRA GER) (BWX (PRP (ALY (FRA ENG GER) VSS (ITA))))' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SND), 'Expected a SND request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.powers == ['FRANCE', 'GERMANY'] + assert request.message_bytes == str_to_bytes('BWX ( PRP ( ALY ( FRA ENG GER ) VSS ( ITA ) ) )') + +def test_snd_009(): + """ Tests the SND request """ + daide_str = 'SND ( FRA GER ) ( HUH ( ERR PRP ( ALY ( FRA ENG GER ) VSS ( ITA ) ) ) )' + expected_str = 'SND (FRA GER) (HUH (ERR PRP (ALY (FRA ENG GER) VSS (ITA))))' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.SND), 'Expected a SND request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.phase == '' + assert request.powers == ['FRANCE', 'GERMANY'] + assert request.message_bytes == str_to_bytes('HUH ( ERR PRP ( ALY ( FRA ENG GER ) VSS ( ITA ) ) )') + +def test_not_sub(): + """ Tests the NOT request """ + daide_str = 'NOT ( SUB )' + expected_str = 'NOT (SUB)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.NOT), 'Expected a NOT request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert isinstance(request.request, requests.SUB), 'Expected a SUB not request' + +def test_not_sub_orders(): + """ Tests the NOT request """ + daide_str = 'NOT ( SUB ( ( ENG AMY YOR ) CTO NWY VIA ( NTH ) ) ' \ + '( ( ENG FLT NTH ) CVY ( ENG AMY YOR ) CTO NWY ) ' \ + '( ( ENG FLT NWG ) SUP ( ENG AMY YOR ) MTO NWY ) )' + expected_str = 'NOT (SUB ((ENG AMY YOR) CTO NWY VIA (NTH)) ' \ + '((ENG FLT NTH) CVY (ENG AMY YOR) CTO NWY) ' \ + '((ENG FLT NWG) SUP (ENG AMY YOR) MTO NWY))' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.NOT), 'Expected a NOT request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert isinstance(request.request, requests.SUB), 'Expected a SUB not request' + +def test_not_gof(): + """ Tests the NOT request """ + daide_str = 'NOT ( GOF )' + expected_str = 'NOT (GOF)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.NOT), 'Expected a NOT request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert isinstance(request.request, requests.GOF), 'Expected a GOF not request' + +def test_not_tme(): + """ Tests the NOT request """ + daide_str = 'NOT ( TME )' + expected_str = 'NOT (TME)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.NOT), 'Expected a NOT request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert isinstance(request.request, requests.TME), 'Expected a TME not request' + +def test_not_tme_sec(): + """ Tests the NOT request """ + daide_str = 'NOT ( TME ( #60 ) )' + expected_str = 'NOT (TME (60))' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.NOT), 'Expected a NOT request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert isinstance(request.request, requests.TME), 'Expected a TME not request' + +def test_not_drw(): + """ Tests the NOT request """ + daide_str = 'NOT ( DRW )' + expected_str = 'NOT (DRW)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.NOT), 'Expected a NOT request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert isinstance(request.request, requests.DRW), 'Expected a DRW not request' + +def test_yes(): + """ Tests the YES request """ + daide_str = 'YES ( MAP ( s t a n d a r d ) )' + expected_str = 'YES (MAP (standard))' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.YES), 'Expected a YES request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert tokens.Token(from_bytes=request.response_bytes[:2]) == tokens.MAP + +def test_rej(): + """ Tests the REJ request """ + daide_str = 'REJ ( SVE ( g a m e n a m e ) )' + expected_str = 'REJ (SVE (gamename))' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.REJ), 'Expected a REJ request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert tokens.Token(from_bytes=request.response_bytes[:2]) == tokens.SVE + +def test_prn_sub(): + """ Tests the PRN request """ + daide_str = 'PRN ( SUB ( ( ENG AMY LVP ) HLD ) ' \ + '( ( ENG FLT LON ) MTO NTH ) ' \ + '( ( ENG FLT EDI ) SUP ( ENG FLT LON ) MTO NTH )' + request_message_daide_str = 'SUB ( ( ENG AMY LVP ) HLD ) ' \ + '( ( ENG FLT LON ) MTO NTH ) ' \ + '( ( ENG FLT EDI ) SUP ( ENG FLT LON ) MTO NTH' + expected_str = 'PRN (SUB ((ENG AMY LVP) HLD) ' \ + '((ENG FLT LON) MTO NTH) ' \ + '((ENG FLT EDI) SUP (ENG FLT LON) MTO NTH)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.PRN), 'Expected a PRN request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.message_bytes == str_to_bytes(request_message_daide_str) + +def test_huh_sub(): + """ Tests the HUH request """ + daide_str = 'HUH ( )' + expected_str = 'HUH ()' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.HUH), 'Expected a HUH request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.message_bytes == b'' + +def test_adm(): + """ Tests the ADM request """ + daide_str = 'ADM ( I \' m h a v i n g c o n n e c t i o n p r o b l e m s )' + expected_str = 'ADM (I\'m having connection problems)' + request = RequestBuilder.from_bytes(str_to_bytes(daide_str)) + assert isinstance(request, requests.ADM), 'Expected a ADM request' + assert bytes(request) == str_to_bytes(daide_str) + assert str(request) == expected_str + assert request.adm_message == 'I\'m having connection problems' diff --git a/diplomacy/utils/strings.py b/diplomacy/utils/strings.py index 2a74a03..19823a8 100644 --- a/diplomacy/utils/strings.py +++ b/diplomacy/utils/strings.py @@ -19,6 +19,7 @@ ABBREV = 'abbrev' ACTIVE = 'active' ADJUST = 'adjust' +ADM_MESSAGE = 'adm_message' ADMIN = 'admin' ADMINISTRATORS = 'administrators' ALL_POSSIBLE_ORDERS = 'all_possible_orders' @@ -39,6 +40,8 @@ CENTERS = 'centers' CHANNEL = 'channel' CIVIL_DISORDER = 'civil_disorder' CLEAR_INVALID_STATE_HISTORY = 'clear_invalid_state_history' +CLIENT_NAME = 'client_name' +CLIENT_VERSION = 'client_version' COMPLETED = 'completed' CONTENT = 'content' CONTROLLED_POWERS = 'controlled_powers' @@ -90,6 +93,7 @@ MAPS_MTIME = 'maps_mtime' MASTER_TYPE = 'master_type' MAX_GAMES = 'max_games' MESSAGE = 'message' +MESSAGE_BYTES = 'message_bytes' MESSAGE_HISTORY = 'message_history' MESSAGES = 'messages' META_RULES = 'meta_rules' @@ -125,6 +129,7 @@ ORDERS_STATUSES = 'orders_statuses' OTHER_PLAYERS = 'other_players' OUTCOME = 'outcome' PARAMETERS = 'parameters' +PASSCODE = 'passcode' PASSWORD = 'password' PASSWORD_HASH = 'password_hash' PAUSED = 'paused' @@ -160,13 +165,16 @@ REGISTER = 'register' REGISTRATION_PASSWORD = 'registration_password' REMOVE_CANCELED_GAMES = 'remove_canceled_games' REMOVE_ENDED_GAMES = 'remove_ended_games' +REQUEST = 'request' REQUEST_ID = 'request_id' +RESPONSE_BYTES = 'response_bytes' RESULT = 'result' RESULT_HISTORY = 'result_history' RESULTS = 'results' RETREATS = 'retreats' ROLE = 'role' RULES = 'rules' +SECONDS = 'seconds' SENDER = 'sender' SERVER_TYPE = 'server_type' SET_ORDER = 'set_order' |