Actions
Game class
Game
Bases: Model
Represents the core state and data of a single "Magnate" game session.
Attributes:
| Name | Type | Description |
|---|---|---|
datetime |
DateTimeField
|
The timestamp of when the game was created or started. |
positions |
JSONField
|
Maps a player's user ID (str/int) to their current square's custom ID (int). |
money |
JSONField
|
Maps a player's user ID (str/int) to their current money balance (int). |
active_phase_player |
ForeignKey
|
The user who must take action in the current micro-phase (e.g., the user who needs to respond to a trade, which might differ from the active_turn_player). |
active_turn_player |
ForeignKey
|
The user whose actual turn it is on the board. |
phase |
CharField
|
The current |
players |
ManyToManyField
|
The pool of users actively participating in this game. |
ordered_players |
JSONField
|
A list of player primary keys |
streak |
IntegerField
|
Tracks consecutive identical dice rolls (e.g., rolling doubles). Usually triggers jail time if it hits 3. |
possible_destinations |
JSONField
|
Maps a target |
parking_money |
PositiveIntegerField
|
The accumulated jackpot for landing on the "Free Parking" equivalent. |
jail_remaining_turns |
JSONField
|
Maps a player's user ID (str/int) to the number of turns (int) they have left to serve in jail. |
proposal |
ForeignKey
|
A reference to an active trade proposal ( |
fantasy_event |
ForeignKey
|
A reference to an active chance/community chest style event
( |
current_auction |
ForeignKey
|
A reference to an active property auction ( |
finished |
BooleanField
|
Flag indicating if the game has concluded. |
bonus_response |
ForeignKey
|
Reference to a specific bonus or penalty modifier ( |
kick_out_task_id |
CharField
|
The ID of the scheduled Celery task responsible for kicking a player if they fail to act within the time limit. |
next_phase_task_id |
CharField
|
The ID of the scheduled Celery task responsible for auto-advancing the game to the next phase if a timeout occurs. |
current_turn |
PositiveIntegerField
|
The global counter for the number of turns that have elapsed. |
Source code in magnate/models.py
class Game(models.Model):
"""
Represents the core state and data of a single "Magnate" game session.
Attributes:
datetime (DateTimeField): The timestamp of when the game was created or started.
positions (JSONField): Maps a player's user ID (str/int) to their current square's custom ID (int).
money (JSONField): Maps a player's user ID (str/int) to their current money balance (int).
active_phase_player (ForeignKey): The user who must take action in the current micro-phase
(e.g., the user who needs to respond to a trade, which might differ from the active_turn_player).
active_turn_player (ForeignKey): The user whose actual turn it is on the board.
phase (CharField): The current `GamePhase` of the game state machine.
players (ManyToManyField): The pool of users actively participating in this game.
ordered_players (JSONField): A list of player primary keys `[pk1, pk2, pk3, ...]`
representing the strict turn order of the game.
streak (IntegerField): Tracks consecutive identical dice rolls (e.g., rolling doubles).
Usually triggers jail time if it hits 3.
possible_destinations (JSONField): Maps a target `square_id` (str) to the `dice_combination` (int)
required to get there. Used when a player has multiple routing options (e.g., taking a tram).
parking_money (PositiveIntegerField): The accumulated jackpot for landing on the "Free Parking" equivalent.
jail_remaining_turns (JSONField): Maps a player's user ID (str/int) to the number of turns (int)
they have left to serve in jail.
proposal (ForeignKey): A reference to an active trade proposal (`ActionTradeProposal`) currently
blocking the game state awaiting a response.
fantasy_event (ForeignKey): A reference to an active chance/community chest style event
(`FantasyEvent`) currently being resolved.
current_auction (ForeignKey): A reference to an active property auction (`Auction`) taking place.
finished (BooleanField): Flag indicating if the game has concluded.
bonus_response (ForeignKey): Reference to a specific bonus or penalty modifier (`ResponseBonus`)
applied to the current state.
kick_out_task_id (CharField): The ID of the scheduled Celery task responsible for kicking
a player if they fail to act within the time limit.
next_phase_task_id (CharField): The ID of the scheduled Celery task responsible for auto-advancing
the game to the next phase if a timeout occurs.
current_turn (PositiveIntegerField): The global counter for the number of turns that have elapsed.
"""
datetime = models.DateTimeField()
# Maps user_id -> square_custom_id
positions = models.JSONField(default=dict, blank=True)
# Maps user_id -> amount
money = models.JSONField(default=dict, blank=True)
active_phase_player = models.ForeignKey('CustomUser', on_delete=models.SET_NULL, null=True, related_name='phase_to_play')
active_turn_player = models.ForeignKey('CustomUser', on_delete=models.SET_NULL, null=True, related_name='turns_to_play')
class GamePhase(models.TextChoices):
"""
Enumeration of the possible states (phases) within a game's turn cycle.
Attributes:
roll_the_dices: The initial phase of a turn. The `active_turn_player`
must throw the dice to determine movement.
choose_square: Triggered when a player's movement path presents a fork
or routing option (e.g., deciding whether to take a tram/subway line).
The player must select their specific destination square.
choose_fantasy: Triggered when a player lands on a dynamic event square
The player must acknowledge and resolve the active `fantasy_event`.
management: Triggered when a player lands on an unowned property. The
player must choose to either purchase the property at its list price
or decline the purchase (which typically immediately triggers an `auction`).
business: A versatile phase usually occurring at the end of a turn
or before a roll. The player can build/demolish houses, mortgage/unmortgage
properties, or finalize their board state before passing the turn.
liquidation: An emergency phase triggered when a player owes a debt
(to the bank or another player) that exceeds their current liquid cash.
They are forced to sell assets or mortgage properties to cover the debt,
or face bankruptcy.
auction: A competitive, multi-player phase triggered when a property
is declined in the `management` phase. The standard turn loop pauses, and
players take turns placing bids until a winner is determined.
proposal_acceptance: An interruptive phase triggered when one player
sends a trade request to another. The game loop pauses, the
`active_phase_player` switches to the recipient, and they must either
accept or decline the pending `proposal`.
end_game: A terminal state indicating the match has concluded, usually
because all other players have gone bankrupt. No further actions can
be taken.
"""
roll_the_dices = 'roll_the_dices'
choose_square = 'choose_square'
choose_fantasy = 'choose_fantasy'
management = 'management'
liquidation = 'liquidation'
business = 'business'
auction = 'auction'
proposal_acceptance = 'proposal_acceptance'
end_game = 'end_game'
phase = models.CharField(choices=GamePhase, max_length=20, default='roll_the_dices')
players = models.ManyToManyField('CustomUser', related_name='active_playing')
# ordered_player = [pk1, pk2, pk3, ...]
ordered_players = models.JSONField(default=list)
streak = models.IntegerField(default=0)
#dict[string,int], key=square_id, value=dice_combination to get there
possible_destinations = models.JSONField(default=dict, blank=True)
parking_money = models.PositiveIntegerField(default=0)
# Maps user_id -> uint
jail_remaining_turns = models.JSONField(default=dict, blank=True)
proposal = models.ForeignKey('ActionTradeProposal', on_delete=models.SET_NULL, null=True, blank=True, related_name='trade_proposal')
fantasy_event = models.ForeignKey('FantasyEvent', on_delete=models.SET_NULL, null=True, blank=True, related_name='fantasy_event')
current_auction = models.ForeignKey('Auction', on_delete=models.SET_NULL, null=True, blank=True, related_name='active_game')
finished = models.BooleanField(default=False)
bonus_response = models.ForeignKey('ResponseBonus', on_delete=models.SET_NULL, null=True, blank=True, related_name='bonus_response')
kick_out_task_id = models.CharField(max_length=255, null=True, blank=True)
next_phase_task_id = models.CharField(max_length=255, null=True, blank=True)
current_turn = models.PositiveIntegerField(default=1)
GamePhase
Bases: TextChoices
Enumeration of the possible states (phases) within a game's turn cycle.
Attributes:
| Name | Type | Description |
|---|---|---|
roll_the_dices |
The initial phase of a turn. The |
|
choose_square |
Triggered when a player's movement path presents a fork or routing option (e.g., deciding whether to take a tram/subway line). The player must select their specific destination square. |
|
choose_fantasy |
Triggered when a player lands on a dynamic event square
The player must acknowledge and resolve the active |
|
management |
Triggered when a player lands on an unowned property. The
player must choose to either purchase the property at its list price
or decline the purchase (which typically immediately triggers an |
|
business |
A versatile phase usually occurring at the end of a turn or before a roll. The player can build/demolish houses, mortgage/unmortgage properties, or finalize their board state before passing the turn. |
|
liquidation |
An emergency phase triggered when a player owes a debt (to the bank or another player) that exceeds their current liquid cash. They are forced to sell assets or mortgage properties to cover the debt, or face bankruptcy. |
|
auction |
A competitive, multi-player phase triggered when a property
is declined in the |
|
proposal_acceptance |
An interruptive phase triggered when one player
sends a trade request to another. The game loop pauses, the
|
|
end_game |
A terminal state indicating the match has concluded, usually because all other players have gone bankrupt. No further actions can be taken. |
Source code in magnate/models.py
class GamePhase(models.TextChoices):
"""
Enumeration of the possible states (phases) within a game's turn cycle.
Attributes:
roll_the_dices: The initial phase of a turn. The `active_turn_player`
must throw the dice to determine movement.
choose_square: Triggered when a player's movement path presents a fork
or routing option (e.g., deciding whether to take a tram/subway line).
The player must select their specific destination square.
choose_fantasy: Triggered when a player lands on a dynamic event square
The player must acknowledge and resolve the active `fantasy_event`.
management: Triggered when a player lands on an unowned property. The
player must choose to either purchase the property at its list price
or decline the purchase (which typically immediately triggers an `auction`).
business: A versatile phase usually occurring at the end of a turn
or before a roll. The player can build/demolish houses, mortgage/unmortgage
properties, or finalize their board state before passing the turn.
liquidation: An emergency phase triggered when a player owes a debt
(to the bank or another player) that exceeds their current liquid cash.
They are forced to sell assets or mortgage properties to cover the debt,
or face bankruptcy.
auction: A competitive, multi-player phase triggered when a property
is declined in the `management` phase. The standard turn loop pauses, and
players take turns placing bids until a winner is determined.
proposal_acceptance: An interruptive phase triggered when one player
sends a trade request to another. The game loop pauses, the
`active_phase_player` switches to the recipient, and they must either
accept or decline the pending `proposal`.
end_game: A terminal state indicating the match has concluded, usually
because all other players have gone bankrupt. No further actions can
be taken.
"""
roll_the_dices = 'roll_the_dices'
choose_square = 'choose_square'
choose_fantasy = 'choose_fantasy'
management = 'management'
liquidation = 'liquidation'
business = 'business'
auction = 'auction'
proposal_acceptance = 'proposal_acceptance'
end_game = 'end_game'
GameStatusSerializer
Bases: ModelSerializer
Example
A standard serialized response during the 'roll_the_dices' phase:
{
"id": 1,
"datetime": "2026-04-06T18:30:00Z",
"positions": {"42": 0, "85": 12},
"money": {"42": 1500, "85": 1350},
"active_phase_player": 42,
"active_turn_player": 42,
"phase": "roll_the_dices",
"players": [42, 85],
"ordered_players": [42, 85],
"streak": 0,
"possible_destinations": {},
"parking_money": 200,
"jail_remaining_turns": {},
"proposal": null,
"fantasy_event": null,
"current_auction": null,
"finished": false,
"bonus_response": null,
"current_turn": 5
}
Source code in magnate/serializers.py
class GameStatusSerializer(serializers.ModelSerializer):
"""
Example:
A standard serialized response during the 'roll_the_dices' phase:
```json
{
"id": 1,
"datetime": "2026-04-06T18:30:00Z",
"positions": {"42": 0, "85": 12},
"money": {"42": 1500, "85": 1350},
"active_phase_player": 42,
"active_turn_player": 42,
"phase": "roll_the_dices",
"players": [42, 85],
"ordered_players": [42, 85],
"streak": 0,
"possible_destinations": {},
"parking_money": 200,
"jail_remaining_turns": {},
"proposal": null,
"fantasy_event": null,
"current_auction": null,
"finished": false,
"bonus_response": null,
"current_turn": 5
}
```
"""
class Meta:
model = Game
exclude = ['kick_out_task_id', 'next_phase_task_id']