aboutsummaryrefslogtreecommitdiff
path: root/diplomacy/engine/power.py
diff options
context:
space:
mode:
Diffstat (limited to 'diplomacy/engine/power.py')
-rw-r--r--diplomacy/engine/power.py99
1 files changed, 55 insertions, 44 deletions
diff --git a/diplomacy/engine/power.py b/diplomacy/engine/power.py
index 1fe282b..c3826e6 100644
--- a/diplomacy/engine/power.py
+++ b/diplomacy/engine/power.py
@@ -15,6 +15,7 @@
# with this program. If not, see <https://www.gnu.org/licenses/>.
# ==============================================================================
""" Power
+
- Contains the power object representing a power in the game
"""
from copy import deepcopy
@@ -28,33 +29,36 @@ from diplomacy.utils.constants import OrderSettings
class Power(Jsonable):
""" Power Class
- Properties:
- - abbrev - Contains the abbrev of the power (usually the first letter of the power name) (e.g. 'F' for FRANCE)
- - adjust - List of pending adjustment orders
- (e.g. ['A PAR B', 'A PAR R MAR', 'A MAR D', 'WAIVE'])
- - centers - Contains the list of supply centers currently controlled by the power ['MOS', 'SEV', 'STP', 'WAR']
- - civil_disorder - Boolean flag to indicate that the power has been put in CIVIL_DISORDER (e.g. True or False)
- - controller - Sorted dictionary mapping timestamp to controller (either dummy or a user ID) who takes
- control of power at this timestamp.
- - game - Contains a reference to the game object
- - goner - Boolean to indicate that this power doesn't control any SCs any more (e.g. True or False)
- - homes - Contains a list of homes supply centers (where you can build)
- e.g. ['PAR', 'MAR', ... ] or None if empty
- - influence - Contains a list of locations influenced by this power
- Note: To influence a location, the power must have visited it last.
- e.g ['PAR', 'MAR', ... ]
- - name - Contains the name of the power
- - orders - Contains a dictionary of units and their orders.
- For NO_CHECK games, unit is 'ORDER 1', 'ORDER 2', ...
- - e.g. {'A PAR': '- MAR' } or {'ORDER 1': 'A PAR - MAR', 'ORDER 2': '...', ... }
- - Can also be {'REORDER 1': 'A PAR - MAR', 'INVALID 1': 'A PAR - MAR', ... } after validation
- - retreats - Contains the list of units that need to retreat with their possible retreat locations
- (e.g. {'A PAR': ['MAR', 'BER']})
- - role - Power type (observer, omniscient, player or server power).
- Either the power name (for a player power) or a value in diplomacy.utils.strings.ALL_ROLE_TYPES
- - tokens - Only for server power: set of tokens of current power controlled (if not None).
- - units - Contains the list of units (e.g. ['A PAR', 'A MAR', ...]
- - vote - Only for omniscient, player and server power: power vote ('yes', 'no' or 'neutral').
+ Properties:
+
+ - **abbrev** - Contains the abbrev of the power (i.e. the first letter of the power name) (e.g. 'F' for FRANCE)
+ - **adjust** - List of pending adjustment orders
+ (e.g. ['A PAR B', 'A PAR R MAR', 'A MAR D', 'WAIVE'])
+ - **centers** - Contains the list of supply centers currently controlled by the power ['MOS', 'SEV', 'STP']
+ - **civil_disorder** - Bool flag to indicate that the power has been put in CIVIL_DISORDER (e.g. True or False)
+ - **controller** - Sorted dictionary mapping timestamp to controller (either dummy or a user ID) who takes
+ control of power at this timestamp.
+ - **game** - Contains a reference to the game object
+ - **goner** - Boolean to indicate that this power doesn't control any SCs any more (e.g. True or False)
+ - **homes** - Contains a list of homes supply centers (where you can build)
+ e.g. ['PAR', 'MAR', ... ] or None if empty
+ - **influence** - Contains a list of locations influenced by this power
+ Note: To influence a location, the power must have visited it last.
+ e.g ['PAR', 'MAR', ... ]
+ - **name** - Contains the name of the power (e.g. 'FRANCE')
+ - **orders** - Contains a dictionary of units and their orders.
+ For NO_CHECK games, unit is 'ORDER 1', 'ORDER 2', ...
+
+ - e.g. {'A PAR': '- MAR' } or {'ORDER 1': 'A PAR - MAR', 'ORDER 2': '...', ... }
+ - Can also be {'REORDER 1': 'A PAR - MAR', 'INVALID 1': 'A PAR - MAR', ... } after validation
+
+ - **retreats** - Contains the list of units that need to retreat with their possible retreat locations
+ (e.g. {'A PAR': ['MAR', 'BER']})
+ - **role** - Power type (observer, omniscient, player or server power).
+ Either the power name (for a player power) or a value in diplomacy.utils.strings.ALL_ROLE_TYPES
+ - **tokens** - Only for server power: set of tokens of current power controlled (if not None).
+ - **units** - Contains the list of units (e.g. ['A PAR', 'A MAR', ...]
+ - **vote** - Only for omniscient, player and server power: power vote ('yes', 'no' or 'neutral').
"""
__slots__ = ['game', 'name', 'abbrev', 'adjust', 'centers', 'units', 'influence', 'homes',
'retreats', 'goner', 'civil_disorder', 'orders', 'role', 'controller', 'vote',
@@ -128,9 +132,7 @@ class Power(Jsonable):
return text
def __deepcopy__(self, memo):
- """ Fast deep copy implementation
- - (Not setting the game object)
- """
+ """ Fast deep copy implementation (**not setting the game object**) """
cls = self.__class__
result = cls.__new__(cls)
@@ -145,6 +147,7 @@ class Power(Jsonable):
def reinit(self, include_flags=6):
""" Performs a reinitialization of some of the parameters
+
:param include_flags: Bit mask to indicate which params to reset
(bit 1 = orders, 2 = persistent, 4 = transient)
:return: None
@@ -187,6 +190,7 @@ class Power(Jsonable):
@staticmethod
def compare(power_1, power_2):
""" Comparator object - Compares two Power objects
+
:param power_1: The first Power object to compare
:param power_2: The second Power object to compare
:return: 1 if self is greater, -1 if other is greater, 0 if they are equal
@@ -199,6 +203,7 @@ class Power(Jsonable):
def initialize(self, game):
""" Initializes a game and resets home, centers and units
+
:param game: The game to use for initialization
:type game: diplomacy.Game
"""
@@ -233,6 +238,7 @@ class Power(Jsonable):
def merge(self, other_power):
""" Transfer all units, centers, and homes of the other_power to this power
+
:param other_power: The other power (will be empty after the merge)
"""
# Regular units
@@ -291,12 +297,14 @@ class Power(Jsonable):
def is_dummy(self):
""" Indicates if the power is a dummy
+
:return: Boolean flag to indicate if the power is a dummy
"""
return self.controller.last_value() == strings.DUMMY
def is_eliminated(self):
""" Returns a flag to show if player is eliminated
+
:return: If the current power is eliminated
"""
# Not eliminated if has units left
@@ -310,6 +318,7 @@ class Power(Jsonable):
def moves_submitted(self):
""" Returns a boolean to indicate if moves has been submitted
+
:return: 1 if not in Movement phase, or orders submitted, or no more units lefts
"""
if self.game.phase_type != 'M':
@@ -321,35 +330,37 @@ class Power(Jsonable):
# ==============================================================
def is_observer_power(self):
- """ Return True if this power is an observer power. """
+ """ (Network Method) Return True if this power is an observer power. """
return self.role == strings.OBSERVER_TYPE
def is_omniscient_power(self):
- """ Return True if this power is an omniscient power. """
+ """ (Network Method) Return True if this power is an omniscient power. """
return self.role == strings.OMNISCIENT_TYPE
def is_player_power(self):
- """ Return True if this power is a player power. """
+ """ (Network Method) Return True if this power is a player power. """
return self.role == self.name
def is_server_power(self):
- """ Return True if this power is a server power. """
+ """ (Network Method) Return True if this power is a server power. """
return self.role == strings.SERVER_TYPE
def is_controlled(self):
- """ Return True if this power is controlled. """
+ """ (Network Method) Return True if this power is controlled. """
return self.controller.last_value() != strings.DUMMY
def does_not_wait(self):
- """ Return True if this power does not wait (ie. if we could already process orders of this power). """
+ """ (Network Method) Return True if this power does not wait
+ (ie. if we could already process orders of this power).
+ """
return self.order_is_set and not self.wait
def update_controller(self, username, timestamp):
- """ Update controller with given username and timestamp. """
+ """ (Network Method) Update controller with given username and timestamp. """
self.controller.put(timestamp, username)
def set_controlled(self, username):
- """ Control power with given username. Username may be None (meaning no controller). """
+ """ (Network Method) Control power with given username. Username may be None (meaning no controller). """
if username is None or username == strings.DUMMY:
if self.controller.last_value() != strings.DUMMY:
self.controller.put(common.timestamp_microseconds(), strings.DUMMY)
@@ -363,15 +374,15 @@ class Power(Jsonable):
raise DiplomacyException('Power already controlled by someone else. Kick previous controller before.')
def get_controller(self):
- """ Return current power controller name ('dummy' if power is not controlled). """
+ """ (Network Method) Return current power controller name ('dummy' if power is not controlled). """
return self.controller.last_value()
def get_controller_timestamp(self):
- """ Return timestamp when current controller took control of this power. """
+ """ (Network Method) Return timestamp when current controller took control of this power. """
return self.controller.last_key()
def is_controlled_by(self, username):
- """ Return True if this power is controlled by given username. """
+ """ (Network Method) Return True if this power is controlled by given username. """
if username == constants.PRIVATE_BOT_USERNAME:
# Bot is connected if power is dummy and has some associated tokens.
return self.is_dummy() and bool(self.tokens)
@@ -380,16 +391,16 @@ class Power(Jsonable):
# Server-only methods.
def has_token(self, token):
- """ Return True if this power has given token. """
+ """ (Server Method) Return True if this power has given token. """
assert self.is_server_power()
return token in self.tokens
def add_token(self, token):
- """ Add given token to this power. """
+ """ (Server Method) Add given token to this power. """
assert self.is_server_power()
self.tokens.add(token)
def remove_tokens(self, tokens):
- """ Remove sequence of tokens from this power. """
+ """ (Server Method) Remove sequence of tokens from this power. """
assert self.is_server_power()
self.tokens.difference_update(tokens)