diff --git a/server/documents/shared/monopoly_rules/_metadata.json b/server/documents/shared/monopoly_rules/_metadata.json new file mode 100644 index 00000000..0b421dc0 --- /dev/null +++ b/server/documents/shared/monopoly_rules/_metadata.json @@ -0,0 +1,14 @@ +{ + "categories": [], + "source_locale": "en", + "titles": { + "en": "Monopoly Rules" + }, + "locales": { + "en": { + "created": "2026-06-20T00:00:00.000000+00:00", + "modified_contents": "2026-06-20T00:00:00.000000+00:00", + "public": true + } + } +} diff --git a/server/documents/shared/monopoly_rules/en.md b/server/documents/shared/monopoly_rules/en.md new file mode 100644 index 00000000..d1c22c35 --- /dev/null +++ b/server/documents/shared/monopoly_rules/en.md @@ -0,0 +1,114 @@ +# Monopoly Rules +PlayPalace team, 2026. + +This guide describes PlayPalace's Classic Monopoly implementation. It is based on the server rules in this game and informed by Hasbro's official Monopoly Classic Game instructions: https://instructions.hasbro.com/en-my/instruction/monopoly-classic-game + +## TL;DR +Monopoly is a property trading game for 2 to 8 players. Move around the board, buy unowned properties, collect rent from opponents, build houses and hotels on complete color sets, and try to stay solvent while everyone else goes bankrupt. The last non-bankrupt player wins. + +The default PlayPalace settings follow the classic rules: each player starts with $1500, passing GO pays $200, Free Parking does nothing, and the bank has 32 houses and 12 hotels. The host can enable optional house rules before the game starts. + +## Object +Become the wealthiest surviving player by buying, renting, trading, mortgaging, and improving properties. A player who cannot pay a debt after raising money must declare bankruptcy. When only one solvent player remains, that player wins. + +## Setup +Each player begins on GO with the configured starting cash. The classic board has 40 spaces, including: + +* 22 street properties in color groups. +* 4 railroads. +* 2 utilities. +* 3 Chance spaces. +* 3 Community Chest spaces. +* GO, Jail / Just Visiting, Free Parking, Go to Jail, Income Tax, and Luxury Tax. + +The Chance and Community Chest decks are shuffled at the start. Get Out of Jail Free cards stay with the player who drew them until used or traded; other cards return to their deck after they resolve. + +## Turn Flow +On your turn, roll two dice and move clockwise that many spaces. If you roll doubles, you usually get another roll after the landing is resolved. If you roll doubles three times on the same turn, you go directly to Jail. + +After you land, the server resolves the space: + +* If you land on an unowned property, choose whether to buy it or send it to auction. +* If you land on an opponent's unmortgaged property, pay rent. +* If you land on Chance or Community Chest, draw and resolve the card. +* If you land on a tax space, pay the bank. +* If you land on Go to Jail, move directly to Jail. + +Most turns advance automatically after all required choices and payments are complete. + +## Buying And Auctions +When you land on an unowned property, you may buy it for its printed price. If you do not buy it, an auction starts. Every solvent player may bid or pass. Bids must meet the minimum bid and increase by at least $10. The highest remaining bidder pays the winning bid and receives the property. If everyone passes without bidding, the property remains unowned. + +## Rent +Rent is due when you land on another player's unmortgaged property. + +* Streets charge the rent shown for their current building level. +* An unimproved street in a complete color set charges double base rent. +* Railroads charge more rent as their owner holds more railroads. +* Utilities charge 4 times the dice roll if the owner has one utility, or 10 times the dice roll if the owner has both utilities. +* Chance cards that send you to a railroad or utility may apply their special rent multiplier. + +Mortgaged properties do not collect rent. + +## Houses And Hotels +You may build only on a complete, unmortgaged color set. Buildings must be kept even across the set: build on the lowest properties first, and sell from the highest properties first. + +Each street can hold up to 4 houses. The next build replaces those 4 houses with a hotel. Houses and hotels are limited by the bank supply. Selling a building returns half its purchase price. + +## Mortgages +You may mortgage an unimproved property to receive its mortgage value. Streets cannot be mortgaged while any property in their color group has houses or a hotel. + +To unmortgage a property, pay the mortgage value plus 10% interest. If a mortgaged property changes hands through a trade or bankruptcy transfer, the new owner pays the mortgage transfer interest. + +## Trading +Players may trade cash, properties, and Get Out of Jail Free cards. A trade can include multiple properties from either side. Properties with buildings, or properties in a color group that currently has buildings, cannot be traded until the buildings are sold. + +The proposing player builds an offer, sends it, and the target player accepts or declines. Trades are validated again when accepted, so an offer can become invalid if cash, ownership, debt, or buildings change before acceptance. + +## Jail +You can enter Jail by landing on Go to Jail, drawing a Go to Jail card, or rolling doubles three times in one turn. + +While in Jail, you may: + +* Pay $50 bail before rolling. +* Use a Get Out of Jail Free card. +* Roll for doubles. + +If you roll doubles, you leave Jail and move by that roll. If you fail to roll doubles three times, you must pay $50 and then move by the third roll. If you cannot pay, the amount becomes a debt. + +## Chance And Community Chest +Cards may move you, award or charge cash, send you to Jail, give a Get Out of Jail Free card, charge repair fees based on your buildings, or transfer money between players. + +When a card moves you past GO, you collect $200 unless the card or destination says otherwise. Get Out of Jail Free cards can be used later or traded. + +## Debt And Bankruptcy +If you owe more cash than you have, the debt stays pending while you raise money by mortgaging properties, selling buildings, or accepting valid trades. Once you have enough cash, pay the debt. + +If you still cannot or do not pay, declare bankruptcy. If you owe another player, your remaining cash, properties, and Get Out of Jail Free cards transfer to that player. If you owe the bank, your properties return to the bank. + +## Free Parking +By default, Free Parking is only a resting space and pays nothing. + +The host may enable the Free Parking jackpot house rule before the game. With that option on, bank payments such as taxes, fees, and bail go into a pot. Landing on Free Parking collects the pot, then resets it to the configured seed amount. + +## Options +The host can configure these settings before play: + +* **Starting cash:** Cash each player receives at setup. Default: $1500. +* **Free Parking jackpot:** Optional house rule. Default: off. +* **Free Parking starting pot:** The pot amount at game start and after each payout when the jackpot rule is enabled. Default: $0. + +## Controls +Common Monopoly actions: + +* **Roll dice:** Roll on your turn. +* **Buy property / Auction property:** Resolve an unowned property you landed on. +* **Mortgage / Unmortgage property:** Raise cash or restore a property. +* **Build house or hotel / Sell house or hotel:** Improve or liquidate a complete color set. +* **Pay bail / Use Get Out of Jail Free card:** Jail options available before rolling. +* **Pay debt / Declare bankruptcy:** Resolve a pending debt. +* **Offer trade:** Build a trade offer with another player. +* **Check assets:** Review your cash, location, net worth, cards, and properties. +* **Check board:** Review bank supply, unowned property count, player positions, and pending table state. + +Keyboard shortcuts include R or Space to roll, B to buy, A to auction, E to end a visible manual turn phase, Ctrl+T to offer a trade, C to check assets, Shift+C to check the board, F1 to show rules, and Escape to open the action menu. diff --git a/server/game_utils/action_execution_mixin.py b/server/game_utils/action_execution_mixin.py index 342d63fa..feba9d88 100644 --- a/server/game_utils/action_execution_mixin.py +++ b/server/game_utils/action_execution_mixin.py @@ -180,6 +180,11 @@ def _request_action_input(self, action: Action, player: "Player") -> None: for opt in options: if menu_option_meta: display_text = menu_option_meta.get_localized_choice(opt, user.locale) + elif getattr(self, "_menu_options_encode_ids", False) and "|" in opt: + # Opt-in convention: options are encoded "value|label" so a + # stable id can be carried as the selection value without + # being shown. Display only the human-readable label half. + display_text = opt.split("|", 1)[1] else: display_text = opt items.append(MenuItem(text=display_text, id=opt)) diff --git a/server/games/__init__.py b/server/games/__init__.py index 9f7aad68..937f5b89 100644 --- a/server/games/__init__.py +++ b/server/games/__init__.py @@ -24,6 +24,7 @@ from .holdem.game import HoldemGame from .crazyeights.game import CrazyEightsGame +from .monopoly.game import MonopolyGame from .snakesandladders.game import SnakesAndLaddersGame from .rollingballs.game import RollingBallsGame from .sorry.game import SorryGame @@ -67,6 +68,7 @@ "FiveCardDrawGame", "HoldemGame", "CrazyEightsGame", + "MonopolyGame", "SnakesAndLaddersGame", "RollingBallsGame", "SorryGame", diff --git a/server/games/monopoly/__init__.py b/server/games/monopoly/__init__.py new file mode 100644 index 00000000..e334d231 --- /dev/null +++ b/server/games/monopoly/__init__.py @@ -0,0 +1,5 @@ +"""Monopoly game package.""" + +from .game import MonopolyGame, MonopolyPlayer + +__all__ = ["MonopolyGame", "MonopolyPlayer"] diff --git a/server/games/monopoly/board.py b/server/games/monopoly/board.py new file mode 100644 index 00000000..36050829 --- /dev/null +++ b/server/games/monopoly/board.py @@ -0,0 +1,400 @@ +"""Board definitions for Monopoly. + +The gameplay engine is written against :class:`BoardDefinition` so themed +boards can be added later without changing the turn loop. +""" + +from __future__ import annotations + +from dataclasses import dataclass + + +DEFAULT_BOARD_ID = "classic" +BOARD_SIZE = 40 +STARTING_CASH = 1500 +PASS_GO_CASH = 200 +TOTAL_HOUSES = 32 +TOTAL_HOTELS = 12 + +PURCHASABLE_KINDS = {"street", "railroad", "utility"} + + +@dataclass(frozen=True) +class MonopolySpace: + """A space on a Monopoly board.""" + + index: int + space_id: str + name: str + kind: str + price: int = 0 + rents: tuple[int, ...] = () + color_group: str = "" + house_cost: int = 0 + mortgage_value: int = 0 + tax_amount: int = 0 + + @property + def is_purchasable(self) -> bool: + return self.kind in PURCHASABLE_KINDS + + +@dataclass(frozen=True) +class BoardDefinition: + """Static data for one playable Monopoly board.""" + + board_id: str + name: str + spaces: tuple[MonopolySpace, ...] + starting_cash: int = STARTING_CASH + pass_go_cash: int = PASS_GO_CASH + total_houses: int = TOTAL_HOUSES + total_hotels: int = TOTAL_HOTELS + + @property + def space_by_id(self) -> dict[str, MonopolySpace]: + return {space.space_id: space for space in self.spaces} + + @property + def purchasable_spaces(self) -> tuple[MonopolySpace, ...]: + return tuple(space for space in self.spaces if space.is_purchasable) + + @property + def color_group_space_ids(self) -> dict[str, tuple[str, ...]]: + groups: dict[str, list[str]] = {} + for space in self.spaces: + if space.color_group: + groups.setdefault(space.color_group, []).append(space.space_id) + return {group: tuple(ids) for group, ids in groups.items()} + + def get_space(self, space_id: str) -> MonopolySpace: + return self.space_by_id[space_id] + + def get_space_at(self, index: int) -> MonopolySpace: + return self.spaces[index % len(self.spaces)] + + +def _street( + index: int, + space_id: str, + name: str, + price: int, + rents: tuple[int, int, int, int, int, int], + color_group: str, + house_cost: int, +) -> MonopolySpace: + return MonopolySpace( + index=index, + space_id=space_id, + name=name, + kind="street", + price=price, + rents=rents, + color_group=color_group, + house_cost=house_cost, + mortgage_value=price // 2, + ) + + +def _railroad(index: int, space_id: str, name: str) -> MonopolySpace: + return MonopolySpace( + index=index, + space_id=space_id, + name=name, + kind="railroad", + price=200, + rents=(25, 50, 100, 200), + mortgage_value=100, + ) + + +def _utility(index: int, space_id: str, name: str) -> MonopolySpace: + return MonopolySpace( + index=index, + space_id=space_id, + name=name, + kind="utility", + price=150, + mortgage_value=75, + ) + + +CLASSIC_SPACES: tuple[MonopolySpace, ...] = ( + MonopolySpace(0, "go", "GO", "go"), + _street( + 1, + "mediterranean_avenue", + "Mediterranean Avenue", + 60, + (2, 10, 30, 90, 160, 250), + "brown", + 50, + ), + MonopolySpace(2, "community_chest_1", "Community Chest", "community_chest"), + _street(3, "baltic_avenue", "Baltic Avenue", 60, (4, 20, 60, 180, 320, 450), "brown", 50), + MonopolySpace(4, "income_tax", "Income Tax", "tax", tax_amount=200), + _railroad(5, "reading_railroad", "Reading Railroad"), + _street( + 6, + "oriental_avenue", + "Oriental Avenue", + 100, + (6, 30, 90, 270, 400, 550), + "light_blue", + 50, + ), + MonopolySpace(7, "chance_1", "Chance", "chance"), + _street( + 8, + "vermont_avenue", + "Vermont Avenue", + 100, + (6, 30, 90, 270, 400, 550), + "light_blue", + 50, + ), + _street( + 9, + "connecticut_avenue", + "Connecticut Avenue", + 120, + (8, 40, 100, 300, 450, 600), + "light_blue", + 50, + ), + MonopolySpace(10, "jail", "Jail / Just Visiting", "jail"), + _street( + 11, + "st_charles_place", + "St. Charles Place", + 140, + (10, 50, 150, 450, 625, 750), + "pink", + 100, + ), + _utility(12, "electric_company", "Electric Company"), + _street(13, "states_avenue", "States Avenue", 140, (10, 50, 150, 450, 625, 750), "pink", 100), + _street( + 14, + "virginia_avenue", + "Virginia Avenue", + 160, + (12, 60, 180, 500, 700, 900), + "pink", + 100, + ), + _railroad(15, "pennsylvania_railroad", "Pennsylvania Railroad"), + _street( + 16, + "st_james_place", + "St. James Place", + 180, + (14, 70, 200, 550, 750, 950), + "orange", + 100, + ), + MonopolySpace(17, "community_chest_2", "Community Chest", "community_chest"), + _street( + 18, + "tennessee_avenue", + "Tennessee Avenue", + 180, + (14, 70, 200, 550, 750, 950), + "orange", + 100, + ), + _street( + 19, + "new_york_avenue", + "New York Avenue", + 200, + (16, 80, 220, 600, 800, 1000), + "orange", + 100, + ), + MonopolySpace(20, "free_parking", "Free Parking", "free_parking"), + _street( + 21, + "kentucky_avenue", + "Kentucky Avenue", + 220, + (18, 90, 250, 700, 875, 1050), + "red", + 150, + ), + MonopolySpace(22, "chance_2", "Chance", "chance"), + _street( + 23, + "indiana_avenue", + "Indiana Avenue", + 220, + (18, 90, 250, 700, 875, 1050), + "red", + 150, + ), + _street( + 24, + "illinois_avenue", + "Illinois Avenue", + 240, + (20, 100, 300, 750, 925, 1100), + "red", + 150, + ), + _railroad(25, "bo_railroad", "B. & O. Railroad"), + _street( + 26, + "atlantic_avenue", + "Atlantic Avenue", + 260, + (22, 110, 330, 800, 975, 1150), + "yellow", + 150, + ), + _street( + 27, + "ventnor_avenue", + "Ventnor Avenue", + 260, + (22, 110, 330, 800, 975, 1150), + "yellow", + 150, + ), + _utility(28, "water_works", "Water Works"), + _street( + 29, + "marvin_gardens", + "Marvin Gardens", + 280, + (24, 120, 360, 850, 1025, 1200), + "yellow", + 150, + ), + MonopolySpace(30, "go_to_jail", "Go to Jail", "go_to_jail"), + _street( + 31, + "pacific_avenue", + "Pacific Avenue", + 300, + (26, 130, 390, 900, 1100, 1275), + "green", + 200, + ), + _street( + 32, + "north_carolina_avenue", + "North Carolina Avenue", + 300, + (26, 130, 390, 900, 1100, 1275), + "green", + 200, + ), + MonopolySpace(33, "community_chest_3", "Community Chest", "community_chest"), + _street( + 34, + "pennsylvania_avenue", + "Pennsylvania Avenue", + 320, + (28, 150, 450, 1000, 1200, 1400), + "green", + 200, + ), + _railroad(35, "short_line", "Short Line"), + MonopolySpace(36, "chance_3", "Chance", "chance"), + _street( + 37, + "park_place", + "Park Place", + 350, + (35, 175, 500, 1100, 1300, 1500), + "dark_blue", + 200, + ), + MonopolySpace(38, "luxury_tax", "Luxury Tax", "tax", tax_amount=100), + _street(39, "boardwalk", "Boardwalk", 400, (50, 200, 600, 1400, 1700, 2000), "dark_blue", 200), +) + +CLASSIC_BOARD = BoardDefinition( + board_id=DEFAULT_BOARD_ID, + name="Classic Monopoly", + spaces=CLASSIC_SPACES, +) + +BOARDS: dict[str, BoardDefinition] = {CLASSIC_BOARD.board_id: CLASSIC_BOARD} + +CHANCE_CARD_IDS: tuple[str, ...] = ( + "advance_to_go", + "advance_to_illinois_avenue", + "advance_to_st_charles_place", + "advance_to_nearest_utility", + "advance_to_nearest_railroad", + "bank_dividend_50", + "get_out_of_jail_free_chance", + "go_back_three", + "go_to_jail", + "general_repairs", + "speeding_fine_15", + "take_trip_to_reading_railroad", + "take_walk_on_boardwalk", + "chairman_pay_50_each", + "building_loan_matures_150", + "crossword_competition_100", +) + +COMMUNITY_CHEST_CARD_IDS: tuple[str, ...] = ( + "advance_to_go", + "bank_error_collect_200", + "doctor_fee_pay_50", + "sale_of_stock_collect_50", + "get_out_of_jail_free_community_chest", + "go_to_jail", + "holiday_fund_matures_100", + "income_tax_refund_20", + "birthday_collect_10_each", + "life_insurance_matures_100", + "hospital_fees_pay_100", + "school_fees_pay_50", + "consultancy_fee_collect_25", + "street_repairs", + "beauty_contest_collect_10", + "inherit_100", +) + +CARD_TEXT: dict[str, str] = { + "advance_to_go": "Advance to GO. Collect $200.", + "advance_to_illinois_avenue": "Advance to Illinois Avenue. If you pass GO, collect $200.", + "advance_to_st_charles_place": "Advance to St. Charles Place. If you pass GO, collect $200.", + "advance_to_nearest_utility": "Advance to the nearest Utility.", + "advance_to_nearest_railroad": "Advance to the nearest Railroad.", + "bank_dividend_50": "Bank pays you dividend of $50.", + "get_out_of_jail_free_chance": "Get Out of Jail Free.", + "go_back_three": "Go back 3 spaces.", + "go_to_jail": "Go to Jail.", + "general_repairs": "Make general repairs on all your property.", + "speeding_fine_15": "Speeding fine. Pay $15.", + "take_trip_to_reading_railroad": "Take a trip to Reading Railroad.", + "take_walk_on_boardwalk": "Take a walk on Boardwalk.", + "chairman_pay_50_each": "You have been elected Chairman of the Board. Pay each player $50.", + "building_loan_matures_150": "Your building loan matures. Collect $150.", + "crossword_competition_100": "You have won a crossword competition. Collect $100.", + "bank_error_collect_200": "Bank error in your favor. Collect $200.", + "doctor_fee_pay_50": "Doctor's fee. Pay $50.", + "sale_of_stock_collect_50": "From sale of stock you get $50.", + "get_out_of_jail_free_community_chest": "Get Out of Jail Free.", + "holiday_fund_matures_100": "Holiday fund matures. Receive $100.", + "income_tax_refund_20": "Income tax refund. Collect $20.", + "birthday_collect_10_each": "It is your birthday. Collect $10 from each player.", + "life_insurance_matures_100": "Life insurance matures. Collect $100.", + "hospital_fees_pay_100": "Pay hospital fees of $100.", + "school_fees_pay_50": "Pay school fees of $50.", + "consultancy_fee_collect_25": "Receive $25 consultancy fee.", + "street_repairs": "You are assessed for street repairs.", + "beauty_contest_collect_10": "You have won second prize in a beauty contest. Collect $10.", + "inherit_100": "You inherit $100.", +} + + +def get_board(board_id: str = DEFAULT_BOARD_ID) -> BoardDefinition: + """Return a board definition, falling back to the classic board.""" + + return BOARDS.get(board_id, CLASSIC_BOARD) diff --git a/server/games/monopoly/game.py b/server/games/monopoly/game.py new file mode 100644 index 00000000..0ad95d86 --- /dev/null +++ b/server/games/monopoly/game.py @@ -0,0 +1,2629 @@ +"""Classic Monopoly game implementation.""" + +from __future__ import annotations + +from dataclasses import dataclass, field +from datetime import datetime +import random + +from server.core.ui.keybinds import KeybindState + +from ...game_utils.actions import Action, ActionSet, EditboxInput, MenuInput, Visibility +from ...game_utils.bot_helper import BotHelper +from ...game_utils.game_result import GameResult, PlayerResult +from ...game_utils.game_status import GameStatus +from ...game_utils.options import BoolOption, GameOptions, IntOption, option_field +from ...messages.localization import Localization +from ..base import Game, Player +from ..registry import register_game +from .board import ( + CARD_TEXT, + CHANCE_CARD_IDS, + COMMUNITY_CHEST_CARD_IDS, + DEFAULT_BOARD_ID, + PASS_GO_CASH, + STARTING_CASH, + BoardDefinition, + MonopolySpace, + get_board, +) + + +BAIL_AMOUNT = 50 +MIN_AUCTION_INCREMENT = 10 +HOTEL_LEVEL = 5 +JAIL_POSITION = 10 +GO_POSITION = 0 +JAIL_CARD_TRADE_VALUE = 50 + + +@dataclass +class MonopolyPlayer(Player): + """Player state for Monopoly.""" + + position: int = GO_POSITION + cash: int = STARTING_CASH + bankrupt: bool = False + in_jail: bool = False + jail_turns: int = 0 + jail_free_cards: list[str] = field(default_factory=list) + last_roll: list[int] = field(default_factory=list) + + +@dataclass +class MonopolyPropertyState: + """Mutable state for a purchasable board space.""" + + owner_id: str = "" + mortgaged: bool = False + houses: int = 0 + + +@dataclass +class MonopolyDebt: + """Debt waiting for the debtor to raise funds or declare bankruptcy.""" + + debtor_id: str + amount: int + creditor_id: str = "" + reason: str = "" + feeds_pot: bool = False + + +@dataclass +class MonopolyAuction: + """English auction state for an unowned property.""" + + property_id: str + highest_bidder_id: str = "" + highest_bid: int = 0 + passed_player_ids: list[str] = field(default_factory=list) + + +@dataclass +class MonopolyTradeOffer: + """A pending or in-progress trade between two players. + + Each side may bundle any number of properties, a cash amount, and a Get + Out of Jail Free card. While a player composes an offer it lives in + ``trade_draft_offers``; once sent it becomes the game's ``pending_trade``. + """ + + proposer_id: str = "" + target_id: str = "" + give_cash: int = 0 + receive_cash: int = 0 + give_property_ids: list[str] = field(default_factory=list) + receive_property_ids: list[str] = field(default_factory=list) + give_jail_card: bool = False + receive_jail_card: bool = False + summary: str = "" + + +@dataclass +class MonopolyOptions(GameOptions): + """Configurable house rules for Monopoly. + + Every default reproduces the official Hasbro ruleset (Free Parking does + nothing, $1500 starting cash). Turning an option on enables a popular + house rule without affecting the faithful default experience. + """ + + starting_cash: int = option_field( + IntOption( + default=STARTING_CASH, + min_val=500, + max_val=10000, + value_key="cash", + label="monopoly-option-starting-cash", + prompt="monopoly-option-enter-starting-cash", + change_msg="monopoly-option-changed-starting-cash", + description="monopoly-option-desc-starting-cash", + ) + ) + free_parking_jackpot: bool = option_field( + BoolOption( + default=False, + value_key="enabled", + label="monopoly-option-free-parking-jackpot", + change_msg="monopoly-option-changed-free-parking-jackpot", + description="monopoly-option-desc-free-parking-jackpot", + ) + ) + free_parking_seed: int = option_field( + IntOption( + default=0, + min_val=0, + max_val=2000, + value_key="cash", + label="monopoly-option-free-parking-seed", + prompt="monopoly-option-enter-free-parking-seed", + change_msg="monopoly-option-changed-free-parking-seed", + description="monopoly-option-desc-free-parking-seed", + ), + visible_when=("free_parking_jackpot", lambda value: bool(value)), + ) + + +@dataclass +@register_game +class MonopolyGame(Game): + """Classic Monopoly with a data-driven board profile.""" + + # Menu options are encoded as "value|label" (see _encode_property_option and + # the trade pickers); this opts into showing only the label half. + _menu_options_encode_ids = True + + players: list[MonopolyPlayer] = field(default_factory=list) + options: MonopolyOptions = field(default_factory=MonopolyOptions) + + board_id: str = DEFAULT_BOARD_ID + property_states: dict[str, MonopolyPropertyState] = field(default_factory=dict) + chance_deck: list[str] = field(default_factory=list) + community_chest_deck: list[str] = field(default_factory=list) + bank_houses: int = 32 + bank_hotels: int = 12 + free_parking_pot: int = 0 + + phase: str = "await_roll" + pending_purchase_property_id: str = "" + pending_debt: MonopolyDebt | None = None + auction: MonopolyAuction | None = None + pending_trade: MonopolyTradeOffer | None = None + trade_draft_offers: dict[str, MonopolyTradeOffer] = field(default_factory=dict) + extra_roll_pending: bool = False + doubles_count: int = 0 + winner_id: str = "" + + @classmethod + def get_name(cls) -> str: + return "Monopoly" + + @classmethod + def get_type(cls) -> str: + return "monopoly" + + @classmethod + def get_category(cls) -> str: + return "category-board-games" + + @classmethod + def get_min_players(cls) -> int: + return 2 + + @classmethod + def get_max_players(cls) -> int: + return 8 + + @property + def board(self) -> BoardDefinition: + return get_board(self.board_id) + + def create_player(self, player_id: str, name: str, is_bot: bool = False) -> MonopolyPlayer: + return MonopolyPlayer(id=player_id, name=name, is_bot=is_bot) + + def rebuild_runtime_state(self) -> None: + self._ensure_property_states() + + def on_start(self) -> None: + """Start a classic Monopoly game.""" + + self.status = GameStatus.PLAYING + self.game_active = True + self.phase = "await_roll" + self.pending_purchase_property_id = "" + self.pending_debt = None + self.auction = None + self.pending_trade = None + self.trade_draft_offers.clear() + self.extra_roll_pending = False + self.doubles_count = 0 + self.winner_id = "" + + board = self.board + self.property_states = { + space.space_id: MonopolyPropertyState() for space in board.purchasable_spaces + } + self.chance_deck = list(CHANCE_CARD_IDS) + self.community_chest_deck = list(COMMUNITY_CHEST_CARD_IDS) + random.shuffle(self.chance_deck) + random.shuffle(self.community_chest_deck) + self.bank_houses = board.total_houses + self.bank_hotels = board.total_hotels + self.free_parking_pot = ( + self.options.free_parking_seed if self.options.free_parking_jackpot else 0 + ) + + starting_cash = self.options.starting_cash + for player in self.get_active_players(): + mp: MonopolyPlayer = player # type: ignore[assignment] + mp.position = GO_POSITION + mp.cash = starting_cash + mp.bankrupt = False + mp.in_jail = False + mp.jail_turns = 0 + mp.jail_free_cards.clear() + mp.last_roll.clear() + + self.set_turn_players(self.get_active_players()) + self.broadcast_l("monopoly-started", board=board.name, cash=self._money(starting_cash)) + self._start_turn(rebuild_all=True) + + def create_turn_action_set(self, player: MonopolyPlayer) -> ActionSet: + user = self.get_user(player) + locale = user.locale if user else "en" + + action_set = ActionSet(name="turn") + action_set.add( + Action( + id="roll", + label=Localization.get(locale, "monopoly-roll-dice"), + handler="_action_roll", + is_enabled="_is_roll_enabled", + is_hidden="_is_roll_hidden", + ) + ) + action_set.add( + Action( + id="buy_property", + label=Localization.get(locale, "monopoly-buy-property"), + handler="_action_buy_property", + is_enabled="_is_buy_property_enabled", + is_hidden="_is_buy_property_hidden", + ) + ) + action_set.add( + Action( + id="auction_property", + label=Localization.get(locale, "monopoly-auction-property"), + handler="_action_auction_property", + is_enabled="_is_auction_property_enabled", + is_hidden="_is_buy_property_hidden", + ) + ) + action_set.add( + Action( + id="pay_debt", + label=Localization.get(locale, "monopoly-pay-debt"), + handler="_action_pay_debt", + is_enabled="_is_pay_debt_enabled", + is_hidden="_is_pay_debt_hidden", + ) + ) + action_set.add( + Action( + id="declare_bankruptcy", + label=Localization.get(locale, "monopoly-declare-bankruptcy"), + handler="_action_declare_bankruptcy", + is_enabled="_is_declare_bankruptcy_enabled", + is_hidden="_is_declare_bankruptcy_hidden", + ) + ) + action_set.add( + Action( + id="offer_trade", + label=Localization.get(locale, "monopoly-offer-trade"), + handler="_action_offer_trade", + is_enabled="_is_offer_trade_enabled", + is_hidden="_is_offer_trade_hidden", + input_request=MenuInput( + prompt="monopoly-select-trade-partner", + options="_trade_partner_options", + bot_select="_bot_select_first_option", + ), + ) + ) + # Interactive trade builder — these are only visible while the player + # is composing an offer (see _is_trade_builder_hidden). + action_set.add( + Action( + id="trade_give", + label=Localization.get(locale, "monopoly-trade-give"), + handler="_action_trade_toggle_give", + is_enabled="_is_trade_builder_enabled", + is_hidden="_is_trade_builder_hidden", + input_request=MenuInput( + prompt="monopoly-select-trade-give", + options="_trade_give_options", + bot_select="_bot_select_first_option", + ), + ) + ) + action_set.add( + Action( + id="trade_request", + label=Localization.get(locale, "monopoly-trade-request"), + handler="_action_trade_toggle_request", + is_enabled="_is_trade_builder_enabled", + is_hidden="_is_trade_builder_hidden", + input_request=MenuInput( + prompt="monopoly-select-trade-request", + options="_trade_request_options", + bot_select="_bot_select_first_option", + ), + ) + ) + action_set.add( + Action( + id="trade_cash", + label=Localization.get(locale, "monopoly-trade-cash"), + handler="_action_trade_set_cash", + is_enabled="_is_trade_builder_enabled", + is_hidden="_is_trade_builder_hidden", + input_request=EditboxInput(prompt="monopoly-enter-trade-cash", default="0"), + ) + ) + action_set.add( + Action( + id="trade_jail", + label=Localization.get(locale, "monopoly-trade-jail"), + handler="_action_trade_toggle_jail", + is_enabled="_is_trade_builder_enabled", + is_hidden="_is_trade_jail_hidden", + input_request=MenuInput( + prompt="monopoly-select-trade-jail", + options="_trade_jail_options", + bot_select="_bot_select_first_option", + ), + ) + ) + action_set.add( + Action( + id="trade_review", + label=Localization.get(locale, "monopoly-trade-review"), + handler="_action_trade_review", + is_enabled="_is_trade_builder_enabled", + is_hidden="_is_trade_builder_hidden", + ) + ) + action_set.add( + Action( + id="trade_send", + label=Localization.get(locale, "monopoly-trade-send"), + handler="_action_trade_send", + is_enabled="_is_trade_builder_enabled", + is_hidden="_is_trade_builder_hidden", + ) + ) + action_set.add( + Action( + id="trade_cancel", + label=Localization.get(locale, "monopoly-trade-cancel"), + handler="_action_trade_cancel", + is_enabled="_is_trade_builder_enabled", + is_hidden="_is_trade_builder_hidden", + ) + ) + action_set.add( + Action( + id="accept_trade", + label=Localization.get(locale, "monopoly-accept-trade"), + handler="_action_accept_trade", + is_enabled="_is_accept_trade_enabled", + is_hidden="_is_pending_trade_hidden", + ) + ) + action_set.add( + Action( + id="decline_trade", + label=Localization.get(locale, "monopoly-decline-trade"), + handler="_action_decline_trade", + is_enabled="_is_decline_trade_enabled", + is_hidden="_is_pending_trade_hidden", + ) + ) + action_set.add( + Action( + id="auction_bid", + label=Localization.get(locale, "monopoly-auction-bid"), + handler="_action_auction_bid", + is_enabled="_is_auction_bid_enabled", + is_hidden="_is_auction_action_hidden", + input_request=EditboxInput( + prompt="monopoly-enter-auction-bid", + default="", + bot_input="_bot_input_auction_bid", + ), + ) + ) + action_set.add( + Action( + id="auction_pass", + label=Localization.get(locale, "monopoly-auction-pass"), + handler="_action_auction_pass", + is_enabled="_is_auction_pass_enabled", + is_hidden="_is_auction_action_hidden", + ) + ) + action_set.add( + Action( + id="pay_bail", + label=Localization.get(locale, "monopoly-pay-bail"), + handler="_action_pay_bail", + is_enabled="_is_pay_bail_enabled", + is_hidden="_is_pay_bail_hidden", + ) + ) + action_set.add( + Action( + id="use_jail_card", + label=Localization.get(locale, "monopoly-use-jail-card"), + handler="_action_use_jail_card", + is_enabled="_is_use_jail_card_enabled", + is_hidden="_is_pay_bail_hidden", + ) + ) + action_set.add( + Action( + id="mortgage_property", + label=Localization.get(locale, "monopoly-mortgage-property"), + handler="_action_mortgage_property", + is_enabled="_is_mortgage_property_enabled", + is_hidden="_is_mortgage_property_hidden", + input_request=MenuInput( + prompt="monopoly-select-property-mortgage", + options="_mortgage_property_options", + bot_select="_bot_select_first_option", + ), + ) + ) + action_set.add( + Action( + id="unmortgage_property", + label=Localization.get(locale, "monopoly-unmortgage-property"), + handler="_action_unmortgage_property", + is_enabled="_is_unmortgage_property_enabled", + is_hidden="_is_unmortgage_property_hidden", + input_request=MenuInput( + prompt="monopoly-select-property-unmortgage", + options="_unmortgage_property_options", + bot_select="_bot_select_first_option", + ), + ) + ) + action_set.add( + Action( + id="build_house", + label=Localization.get(locale, "monopoly-build-house"), + handler="_action_build_house", + is_enabled="_is_build_house_enabled", + is_hidden="_is_build_house_hidden", + input_request=MenuInput( + prompt="monopoly-select-property-build", + options="_build_property_options", + bot_select="_bot_select_first_option", + ), + ) + ) + action_set.add( + Action( + id="sell_house", + label=Localization.get(locale, "monopoly-sell-house"), + handler="_action_sell_house", + is_enabled="_is_sell_house_enabled", + is_hidden="_is_sell_house_hidden", + input_request=MenuInput( + prompt="monopoly-select-property-sell", + options="_sell_building_options", + bot_select="_bot_select_first_option", + ), + ) + ) + action_set.add( + Action( + id="end_turn", + label=Localization.get(locale, "monopoly-end-turn"), + handler="_action_end_turn", + is_enabled="_is_end_turn_enabled", + is_hidden="_is_end_turn_hidden", + ) + ) + return action_set + + def create_standard_action_set(self, player: Player) -> ActionSet: + action_set = super().create_standard_action_set(player) + user = self.get_user(player) + locale = user.locale if user else "en" + + action_set.add( + Action( + id="check_assets", + label=Localization.get(locale, "monopoly-check-assets"), + handler="_action_check_assets", + is_enabled="_is_check_assets_enabled", + is_hidden="_is_check_assets_hidden", + ) + ) + action_set.add( + Action( + id="check_board", + label=Localization.get(locale, "monopoly-check-board"), + handler="_action_check_board", + is_enabled="_is_check_assets_enabled", + is_hidden="_is_check_assets_hidden", + ) + ) + for action_id in ("check_board", "check_assets"): + if action_id in action_set._order: + action_set._order.remove(action_id) + action_set._order.insert(0, action_id) + return action_set + + def setup_keybinds(self) -> None: + super().setup_keybinds() + self.define_keybind("r", "Roll dice", ["roll"], state=KeybindState.ACTIVE) + self.define_keybind("space", "Roll dice", ["roll"], state=KeybindState.ACTIVE) + self.define_keybind("b", "Buy property", ["buy_property"], state=KeybindState.ACTIVE) + self.define_keybind("a", "Auction property", ["auction_property"], state=KeybindState.ACTIVE) + self.define_keybind("e", "End turn", ["end_turn"], state=KeybindState.ACTIVE) + self.define_keybind("ctrl+t", "Offer trade", ["offer_trade"], state=KeybindState.ACTIVE) + self.define_keybind("c", "Check assets", ["check_assets"], state=KeybindState.ACTIVE) + self.define_keybind("shift+c", "Check board", ["check_board"], state=KeybindState.ACTIVE) + + # ------------------------------------------------------------------ + # Action visibility and guards + # ------------------------------------------------------------------ + + def get_all_visible_actions(self, player: Player): + """Focus the menu on the trade builder while an offer is being composed. + + When the player has an open trade draft, only the ``trade_*`` builder + actions are shown; otherwise those builder actions stay hidden. + """ + if self._should_hide_idle_turn_menu(player): + return [] + visible = super().get_all_visible_actions(player) + building = self._active_player(player).id in self.trade_draft_offers + if building: + return [rv for rv in visible if rv.action.id.startswith("trade_")] + return [rv for rv in visible if not rv.action.id.startswith("trade_")] + + def rebuild_player_menu(self, player: Player, *, position: int | None = None) -> None: + """Show no passive turn menu to idle players waiting for someone else.""" + if self._should_hide_idle_turn_menu(player): + user = self.get_user(player) + if user: + user.remove_menu("turn_menu") + return + super().rebuild_player_menu(player, position=position) + + def _active_player(self, player: Player) -> MonopolyPlayer: + return player # type: ignore[return-value] + + def _is_playing(self) -> bool: + return self.status == GameStatus.PLAYING and self.game_active + + def _should_hide_idle_turn_menu(self, player: Player) -> bool: + if not self._is_playing() or player.is_spectator or player.is_bot: + return False + if self._is_current_turn_player(player): + return False + if self.pending_debt and self.pending_debt.debtor_id == player.id: + return False + if self.pending_trade and self.pending_trade.target_id == player.id: + return False + if self.auction and not self._is_bankrupt(player) and player.id in {p.id for p in self._auction_players()}: + return False + if self._active_player(player).id in self.trade_draft_offers: + return False + return True + + def _is_bankrupt(self, player: Player) -> bool: + return bool(getattr(player, "bankrupt", False)) + + def _is_action_menu_only_hidden(self, player: Player) -> Visibility: + return Visibility.HIDDEN + + def _is_current_turn_player(self, player: Player) -> bool: + return self.current_player == player and not self._is_bankrupt(player) + + def _can_manage_assets(self, player: Player) -> str | None: + if not self._is_playing(): + return "action-not-playing" + if player.is_spectator: + return "action-not-available" + if self._is_bankrupt(player): + return "monopoly-player-bankrupt-disabled" + if self.auction: + return "monopoly-auction-active" + if self.pending_trade: + return "monopoly-trade-pending" + if self.pending_purchase_property_id and player == self.current_player: + return "monopoly-resolve-property-first" + if self.pending_debt and self.pending_debt.debtor_id != player.id: + return "monopoly-debt-pending" + return None + + def _is_roll_enabled(self, player: Player) -> str | None: + if not self._is_playing(): + return "action-not-playing" + if self.phase != "await_roll": + return "monopoly-roll-not-available" + if not self._is_current_turn_player(player): + return "action-not-your-turn" + return None + + def _is_roll_hidden(self, player: Player) -> Visibility: + if self._is_playing() and self.phase == "await_roll" and self._is_current_turn_player(player): + return Visibility.VISIBLE + return Visibility.HIDDEN + + def _is_buy_property_enabled(self, player: Player) -> str | None: + if not self._is_playing(): + return "action-not-playing" + if not self._is_current_turn_player(player): + return "action-not-your-turn" + if self.phase != "await_purchase" or not self.pending_purchase_property_id: + return "monopoly-no-property-to-buy" + space = self._space(self.pending_purchase_property_id) + if self._active_player(player).cash < space.price: + return "monopoly-not-enough-cash" + return None + + def _is_auction_property_enabled(self, player: Player) -> str | None: + if not self._is_playing(): + return "action-not-playing" + if not self._is_current_turn_player(player): + return "action-not-your-turn" + if self.phase != "await_purchase" or not self.pending_purchase_property_id: + return "monopoly-no-property-to-auction" + return None + + def _is_buy_property_hidden(self, player: Player) -> Visibility: + if self.phase == "await_purchase" and self._is_current_turn_player(player): + return Visibility.VISIBLE + return Visibility.HIDDEN + + def _is_pay_debt_enabled(self, player: Player) -> str | None: + if not self.pending_debt or self.pending_debt.debtor_id != player.id: + return "monopoly-no-debt" + if self._active_player(player).cash < self.pending_debt.amount: + return "monopoly-not-enough-cash" + return None + + def _is_pay_debt_hidden(self, player: Player) -> Visibility: + if self.pending_debt and self.pending_debt.debtor_id == player.id: + return Visibility.VISIBLE + return Visibility.HIDDEN + + def _is_declare_bankruptcy_enabled(self, player: Player) -> str | None: + if not self.pending_debt or self.pending_debt.debtor_id != player.id: + return "monopoly-no-debt" + return None + + def _is_declare_bankruptcy_hidden(self, player: Player) -> Visibility: + return self._is_pay_debt_hidden(player) + + def _is_auction_bid_enabled(self, player: Player) -> str | None: + if not self.auction: + return "monopoly-no-auction-active" + if self._is_bankrupt(player) or player.id not in {p.id for p in self._auction_players()}: + return "action-not-available" + if player.id in self.auction.passed_player_ids: + return "monopoly-auction-already-passed" + if self._active_player(player).cash < self._minimum_auction_bid(): + return "monopoly-not-enough-cash" + return None + + def _is_auction_pass_enabled(self, player: Player) -> str | None: + if not self.auction: + return "monopoly-no-auction-active" + if self._is_bankrupt(player) or player.id not in {p.id for p in self._auction_players()}: + return "action-not-available" + if player.id in self.auction.passed_player_ids: + return "monopoly-auction-already-passed" + return None + + def _is_auction_action_hidden(self, player: Player) -> Visibility: + if self.auction and not self._is_bankrupt(player) and not player.is_spectator: + return Visibility.VISIBLE + return Visibility.HIDDEN + + def _is_pay_bail_enabled(self, player: Player) -> str | None: + if not self._is_current_turn_player(player): + return "action-not-your-turn" + mp = self._active_player(player) + if not mp.in_jail: + return "monopoly-not-in-jail" + if mp.cash < BAIL_AMOUNT: + return "monopoly-not-enough-cash" + return None + + def _is_pay_bail_hidden(self, player: Player) -> Visibility: + mp = self._active_player(player) + if self.phase == "await_roll" and self._is_current_turn_player(player) and mp.in_jail: + return Visibility.VISIBLE + return Visibility.HIDDEN + + def _is_use_jail_card_enabled(self, player: Player) -> str | None: + if not self._is_current_turn_player(player): + return "action-not-your-turn" + mp = self._active_player(player) + if not mp.in_jail: + return "monopoly-not-in-jail" + if not mp.jail_free_cards: + return "monopoly-no-jail-card" + return None + + def _is_mortgage_property_enabled(self, player: Player) -> str | None: + error = self._can_manage_assets(player) + if error: + return error + if not self._mortgage_property_options(player): + return "monopoly-no-mortgage-options" + return None + + def _is_mortgage_property_hidden(self, player: Player) -> Visibility: + return Visibility.VISIBLE if self._is_mortgage_property_enabled(player) is None else Visibility.HIDDEN + + def _is_unmortgage_property_enabled(self, player: Player) -> str | None: + error = self._can_manage_assets(player) + if error: + return error + if not self._unmortgage_property_options(player): + return "monopoly-no-unmortgage-options" + return None + + def _is_unmortgage_property_hidden(self, player: Player) -> Visibility: + return Visibility.VISIBLE if self._is_unmortgage_property_enabled(player) is None else Visibility.HIDDEN + + def _is_build_house_enabled(self, player: Player) -> str | None: + error = self._can_manage_assets(player) + if error: + return error + if self.pending_debt: + return "monopoly-debt-pending" + if not self._build_property_options(player): + return "monopoly-no-build-options" + return None + + def _is_build_house_hidden(self, player: Player) -> Visibility: + return Visibility.VISIBLE if self._is_build_house_enabled(player) is None else Visibility.HIDDEN + + def _is_sell_house_enabled(self, player: Player) -> str | None: + error = self._can_manage_assets(player) + if error: + return error + if not self._sell_building_options(player): + return "monopoly-no-sell-options" + return None + + def _is_sell_house_hidden(self, player: Player) -> Visibility: + return Visibility.VISIBLE if self._is_sell_house_enabled(player) is None else Visibility.HIDDEN + + def _is_offer_trade_enabled(self, player: Player) -> str | None: + error = self._can_manage_assets(player) + if error: + return error + if self._active_player(player).id in self.trade_draft_offers: + return "monopoly-trade-pending" + if not self._trade_partner_options(player): + return "monopoly-no-trade-options" + return None + + def _is_offer_trade_hidden(self, player: Player) -> Visibility: + return Visibility.VISIBLE if self._is_offer_trade_enabled(player) is None else Visibility.HIDDEN + + def _is_trade_builder_enabled(self, player: Player) -> str | None: + if self._active_player(player).id not in self.trade_draft_offers: + return "monopoly-no-trade-pending" + return None + + def _is_trade_builder_hidden(self, player: Player) -> Visibility: + building = self._active_player(player).id in self.trade_draft_offers + return Visibility.VISIBLE if building else Visibility.HIDDEN + + def _is_trade_jail_hidden(self, player: Player) -> Visibility: + mp = self._active_player(player) + draft = self.trade_draft_offers.get(mp.id) + if not draft: + return Visibility.HIDDEN + target = self._player_by_id(draft.target_id) + if mp.jail_free_cards or (target and target.jail_free_cards): + return Visibility.VISIBLE + return Visibility.HIDDEN + + def _is_accept_trade_enabled(self, player: Player) -> str | None: + if not self.pending_trade or self.pending_trade.target_id != player.id: + return "monopoly-no-trade-pending" + return self._validate_trade_offer(self.pending_trade) + + def _is_decline_trade_enabled(self, player: Player) -> str | None: + if not self.pending_trade or self.pending_trade.target_id != player.id: + return "monopoly-no-trade-pending" + if self._is_bankrupt(player): + return "monopoly-player-bankrupt-disabled" + return None + + def _is_pending_trade_hidden(self, player: Player) -> Visibility: + if self.pending_trade and self.pending_trade.target_id == player.id: + return Visibility.VISIBLE + return Visibility.HIDDEN + + def _is_end_turn_enabled(self, player: Player) -> str | None: + if not self._is_playing(): + return "action-not-playing" + if not self._is_current_turn_player(player): + return "action-not-your-turn" + if self.phase != "post_roll": + return "monopoly-roll-first" + return None + + def _is_end_turn_hidden(self, player: Player) -> Visibility: + if self.phase == "post_roll" and self._is_current_turn_player(player): + return Visibility.VISIBLE + return Visibility.HIDDEN + + def _is_check_assets_enabled(self, player: Player) -> str | None: + if not self._is_playing() and self.status != GameStatus.FINISHED: + return "action-not-playing" + return None + + def _is_check_assets_hidden(self, player: Player) -> Visibility: + if self._is_check_assets_enabled(player) is None: + return Visibility.VISIBLE + return Visibility.HIDDEN + + # ------------------------------------------------------------------ + # Turn flow + # ------------------------------------------------------------------ + + def _start_turn(self, *, rebuild_all: bool = False, previous_player: Player | None = None) -> None: + player = self.current_player + if not player: + return + mp = self._active_player(player) + if mp.bankrupt: + self.advance_turn(announce=False) + self._start_turn(rebuild_all=True) + return + + self.phase = "await_roll" + self.pending_purchase_property_id = "" + self.pending_debt = None + self.auction = None + self.extra_roll_pending = False + self.broadcast_l("monopoly-turn", player=mp.name) + if mp.in_jail: + self.broadcast_l("monopoly-in-jail-turn", player=mp.name, turns=mp.jail_turns) + + BotHelper.jolt_bot(mp, ticks=random.randint(8, 18)) + if rebuild_all: + self.rebuild_all_menus() + elif previous_player and previous_player != mp: + self.rebuild_player_menu(previous_player) + # Always snap the active player's cursor to their primary action (Roll) + # at the start of their turn so it never sticks on an always-visible + # item such as "Check assets". + self.rebuild_player_menu(mp, position=1) + + def _focus_active_player(self, player: MonopolyPlayer) -> None: + """Snap a still-active player's cursor to their primary (first) action. + + After a rebuild the client keeps the cursor on the previously selected + item by id, which makes it stick on an always-visible entry such as + "Check assets". When this player still holds the turn, move their cursor + back to the first action (Roll, Buy, Pay debt, ... for the phase). + """ + if self.current_player == player and not self._active_player(player).bankrupt: + self.rebuild_player_menu(self._active_player(player), position=1) + + def _action_roll(self, player: MonopolyPlayer, action_id: str) -> None: + if player.in_jail: + self._roll_from_jail(player) + return + + die1, die2 = random.randint(1, 6), random.randint(1, 6) + total = die1 + die2 + player.last_roll = [die1, die2] + is_double = die1 == die2 + self.extra_roll_pending = is_double + if is_double: + self.doubles_count += 1 + else: + self.doubles_count = 0 + + self.broadcast_l( + "monopoly-roll-result", + player=player.name, + die1=die1, + die2=die2, + total=total, + ) + + if self.doubles_count >= 3: + self.broadcast_l("monopoly-three-doubles-jail", player=player.name) + self._send_to_jail(player) + self.extra_roll_pending = False + self._complete_roll_resolution(player) + self.rebuild_all_menus() + return + + self._move_steps(player, total) + if self._resolve_landing(player, roll_total=total): + self._complete_roll_resolution(player) + self.rebuild_all_menus() + self._focus_active_player(player) + + def _roll_from_jail(self, player: MonopolyPlayer) -> None: + die1, die2 = random.randint(1, 6), random.randint(1, 6) + total = die1 + die2 + player.last_roll = [die1, die2] + self.extra_roll_pending = False + + if die1 == die2: + player.in_jail = False + player.jail_turns = 0 + self.broadcast_l( + "monopoly-jail-roll-doubles", + player=player.name, + die1=die1, + die2=die2, + ) + self._move_steps(player, total) + if self._resolve_landing(player, roll_total=total): + self._complete_roll_resolution(player) + self.rebuild_all_menus() + self._focus_active_player(player) + return + + player.jail_turns += 1 + self.broadcast_l( + "monopoly-jail-roll-failed", + player=player.name, + die1=die1, + die2=die2, + attempts=player.jail_turns, + ) + if player.jail_turns >= 3: + if player.cash >= BAIL_AMOUNT: + self._pay_bank(player, BAIL_AMOUNT, "bail") + player.in_jail = False + player.jail_turns = 0 + self._move_steps(player, total) + if self._resolve_landing(player, roll_total=total): + self._complete_roll_resolution(player) + else: + self._set_debt(player, BAIL_AMOUNT, None, "bail") + else: + self._complete_roll_resolution(player) + self.rebuild_all_menus() + self._focus_active_player(player) + + def _action_end_turn(self, player: MonopolyPlayer, action_id: str) -> None: + self.doubles_count = 0 + self.extra_roll_pending = False + previous = player + self.advance_turn(announce=False) + self._start_turn(previous_player=previous) + + def _complete_roll_resolution(self, player: MonopolyPlayer) -> None: + if not self._is_playing() or player.bankrupt: + return + if self.pending_purchase_property_id or self.pending_debt or self.auction: + return + if self.extra_roll_pending and not player.in_jail: + self.phase = "await_roll" + self.broadcast_l("monopoly-roll-again", player=player.name) + BotHelper.jolt_bot(player, ticks=random.randint(8, 18)) + else: + self._advance_after_turn_completion(player) + + def _advance_after_turn_completion(self, player: MonopolyPlayer) -> None: + if not self._is_playing() or player.bankrupt or self.current_player != player: + return + self.doubles_count = 0 + self.extra_roll_pending = False + previous = player + self.advance_turn(announce=False) + self._start_turn(rebuild_all=True, previous_player=previous) + + # ------------------------------------------------------------------ + # Space resolution and cards + # ------------------------------------------------------------------ + + def _resolve_landing( + self, + player: MonopolyPlayer, + *, + roll_total: int, + railroad_rent_multiplier: int = 1, + utility_rent_multiplier: int | None = None, + ) -> bool: + space = self._space_at(player.position) + self.broadcast_l("monopoly-landed", player=player.name, space=space.name) + + if space.kind == "go": + return True + if space.kind == "free_parking": + if self.options.free_parking_jackpot: + payout = self.free_parking_pot + self.free_parking_pot = self.options.free_parking_seed + if payout > 0: + player.cash += payout + self.broadcast_l( + "monopoly-free-parking-jackpot", + player=player.name, + amount=self._money(payout), + ) + return True + self.broadcast_l("monopoly-free-parking", player=player.name) + return True + if space.kind == "jail": + self.broadcast_l("monopoly-just-visiting", player=player.name) + return True + if space.kind == "go_to_jail": + self._send_to_jail(player) + self.extra_roll_pending = False + return True + if space.kind == "tax": + return self._pay_bank(player, space.tax_amount, space.name) + if space.kind == "chance": + return self._draw_card(player, "chance", roll_total=roll_total) + if space.kind == "community_chest": + return self._draw_card(player, "community_chest", roll_total=roll_total) + if space.is_purchasable: + return self._resolve_property_landing( + player, + space, + roll_total=roll_total, + railroad_rent_multiplier=railroad_rent_multiplier, + utility_rent_multiplier=utility_rent_multiplier, + ) + return True + + def _resolve_property_landing( + self, + player: MonopolyPlayer, + space: MonopolySpace, + *, + roll_total: int, + railroad_rent_multiplier: int = 1, + utility_rent_multiplier: int | None = None, + ) -> bool: + state = self.property_states[space.space_id] + if not state.owner_id: + self.pending_purchase_property_id = space.space_id + self.phase = "await_purchase" + self.broadcast_l( + "monopoly-property-available", + property=space.name, + price=self._money(space.price), + ) + return False + + if state.owner_id == player.id: + self.broadcast_l("monopoly-landed-own-property", player=player.name, property=space.name) + return True + if state.mortgaged: + self.broadcast_l("monopoly-mortgaged-no-rent", player=player.name, property=space.name) + return True + + owner = self._player_by_id(state.owner_id) + if not owner or owner.bankrupt: + return True + + rent = self._calculate_rent( + space, + roll_total=roll_total, + railroad_multiplier=railroad_rent_multiplier, + utility_multiplier=utility_rent_multiplier, + ) + return self._pay_player(player, owner, rent, f"rent for {space.name}") + + def _draw_card(self, player: MonopolyPlayer, deck_name: str, *, roll_total: int) -> bool: + deck = self.chance_deck if deck_name == "chance" else self.community_chest_deck + if not deck: + deck.extend(CHANCE_CARD_IDS if deck_name == "chance" else COMMUNITY_CHEST_CARD_IDS) + random.shuffle(deck) + card_id = deck.pop(0) + text = CARD_TEXT.get(card_id, card_id.replace("_", " ")) + self.broadcast_l("monopoly-card-drawn", player=player.name, deck=deck_name, text=text) + + keep_card = card_id.startswith("get_out_of_jail_free") + if keep_card: + player.jail_free_cards.append(card_id) + return True + + deck.append(card_id) + return self._apply_card(player, card_id, roll_total=roll_total) + + def _apply_card(self, player: MonopolyPlayer, card_id: str, *, roll_total: int) -> bool: + if card_id == "advance_to_go": + self._move_to(player, GO_POSITION, collect_go=True) + return True + if card_id == "advance_to_illinois_avenue": + self._move_to(player, 24, collect_go=True) + return self._resolve_landing(player, roll_total=roll_total) + if card_id == "advance_to_st_charles_place": + self._move_to(player, 11, collect_go=True) + return self._resolve_landing(player, roll_total=roll_total) + if card_id == "advance_to_nearest_utility": + self._move_to_nearest(player, "utility") + card_roll = random.randint(1, 6) + random.randint(1, 6) + return self._resolve_landing( + player, + roll_total=card_roll, + utility_rent_multiplier=10, + ) + if card_id == "advance_to_nearest_railroad": + self._move_to_nearest(player, "railroad") + return self._resolve_landing( + player, + roll_total=roll_total, + railroad_rent_multiplier=2, + ) + if card_id == "go_back_three": + player.position = (player.position - 3) % len(self.board.spaces) + self.broadcast_l("monopoly-moved-to", player=player.name, space=self._space_at(player.position).name) + return self._resolve_landing(player, roll_total=roll_total) + if card_id == "go_to_jail": + self._send_to_jail(player) + self.extra_roll_pending = False + return True + if card_id == "take_trip_to_reading_railroad": + self._move_to(player, 5, collect_go=True) + return self._resolve_landing(player, roll_total=roll_total) + if card_id == "take_walk_on_boardwalk": + self._move_to(player, 39, collect_go=True) + return self._resolve_landing(player, roll_total=roll_total) + if card_id in { + "bank_dividend_50", + "sale_of_stock_collect_50", + "holiday_fund_matures_100", + "income_tax_refund_20", + "life_insurance_matures_100", + "consultancy_fee_collect_25", + "beauty_contest_collect_10", + "inherit_100", + "building_loan_matures_150", + "crossword_competition_100", + "bank_error_collect_200", + }: + card_payouts = { + "bank_dividend_50": 50, + "sale_of_stock_collect_50": 50, + "holiday_fund_matures_100": 100, + "income_tax_refund_20": 20, + "life_insurance_matures_100": 100, + "consultancy_fee_collect_25": 25, + "beauty_contest_collect_10": 10, + "inherit_100": 100, + "building_loan_matures_150": 150, + "crossword_competition_100": 100, + "bank_error_collect_200": 200, + } + card_reasons = { + "bank_dividend_50": "bank dividend", + "sale_of_stock_collect_50": "sale of stock", + "holiday_fund_matures_100": "holiday fund", + "income_tax_refund_20": "income tax refund", + "life_insurance_matures_100": "life insurance", + "consultancy_fee_collect_25": "consultancy fee", + "beauty_contest_collect_10": "beauty contest prize", + "inherit_100": "inheritance", + "building_loan_matures_150": "building loan", + "crossword_competition_100": "crossword competition", + "bank_error_collect_200": "bank error", + } + self._credit(player, card_payouts[card_id], card_reasons[card_id]) + return True + if card_id in { + "doctor_fee_pay_50", + "hospital_fees_pay_100", + "school_fees_pay_50", + "speeding_fine_15", + }: + card_fees = { + "doctor_fee_pay_50": 50, + "hospital_fees_pay_100": 100, + "school_fees_pay_50": 50, + "speeding_fine_15": 15, + } + card_reasons = { + "doctor_fee_pay_50": "doctor's fee", + "hospital_fees_pay_100": "hospital fees", + "school_fees_pay_50": "school fees", + "speeding_fine_15": "speeding fine", + } + return self._pay_bank(player, card_fees[card_id], card_reasons[card_id]) + if card_id == "general_repairs": + amount = self._building_count(player, houses=True) * 25 + self._building_count(player, hotels=True) * 100 + return self._pay_bank(player, amount, "repairs") + if card_id == "street_repairs": + amount = self._building_count(player, houses=True) * 40 + self._building_count(player, hotels=True) * 115 + return self._pay_bank(player, amount, "street repairs") + if card_id == "birthday_collect_10_each": + for other in self._solvent_players(): + if other.id != player.id: + self._pay_player(other, player, 10, "birthday") + return self.pending_debt is None + if card_id == "chairman_pay_50_each": + total = 50 * (len([p for p in self._solvent_players() if p.id != player.id])) + if not self._pay_bank(player, total, "chairman payment", feeds_pot=False): + return False + for other in self._solvent_players(): + if other.id != player.id: + self._credit(other, 50, "chairman payment") + return True + return True + + # ------------------------------------------------------------------ + # Purchases and auctions + # ------------------------------------------------------------------ + + def _action_buy_property(self, player: MonopolyPlayer, action_id: str) -> None: + space = self._space(self.pending_purchase_property_id) + if player.cash < space.price: + return + player.cash -= space.price + self.property_states[space.space_id].owner_id = player.id + self.pending_purchase_property_id = "" + self.broadcast_l( + "monopoly-property-bought", + player=player.name, + property=space.name, + price=self._money(space.price), + ) + self._announce_completed_set(player, space) + self._complete_roll_resolution(player) + self.rebuild_all_menus() + self._focus_active_player(player) + + def _action_auction_property(self, player: MonopolyPlayer, action_id: str) -> None: + property_id = self.pending_purchase_property_id + if not property_id: + return + self.pending_purchase_property_id = "" + # Every solvent player bids in an auction, so drop any open trade + # drafts to return their menus from the builder to normal play. + self.trade_draft_offers.clear() + self.auction = MonopolyAuction(property_id=property_id) + self.phase = "auction" + space = self._space(property_id) + self.broadcast_l( + "monopoly-auction-started", + property=space.name, + amount=self._money(self._minimum_auction_bid()), + ) + BotHelper.jolt_bots(self, ticks=6, players=self._auction_players()) + self.rebuild_all_menus() + + def _action_auction_bid(self, player: MonopolyPlayer, amount_text: str, action_id: str) -> None: + if not self.auction: + return + try: + amount = int(amount_text.strip().replace("$", "")) + except ValueError: + user = self.get_user(player) + if user: + user.speak_l("monopoly-invalid-bid") + return + minimum = self._minimum_auction_bid() + if amount < minimum or amount > player.cash: + user = self.get_user(player) + if user: + user.speak_l( + "monopoly-bid-out-of-range", + minimum=self._money(minimum), + cash=self._money(player.cash), + ) + return + + self.auction.highest_bidder_id = player.id + self.auction.highest_bid = amount + if player.id in self.auction.passed_player_ids: + self.auction.passed_player_ids.remove(player.id) + space = self._space(self.auction.property_id) + self.broadcast_l( + "monopoly-auction-bid-placed", + player=player.name, + amount=self._money(amount), + property=space.name, + ) + self._finalize_auction_if_ready() + self.rebuild_all_menus() + + def _action_auction_pass(self, player: MonopolyPlayer, action_id: str) -> None: + if not self.auction: + return + if player.id not in self.auction.passed_player_ids: + self.auction.passed_player_ids.append(player.id) + space = self._space(self.auction.property_id) + self.broadcast_l("monopoly-auction-pass-event", player=player.name, property=space.name) + self._finalize_auction_if_ready() + self.rebuild_all_menus() + + def _finalize_auction_if_ready(self) -> None: + if not self.auction: + return + players = self._auction_players() + if not players: + self.auction = None + self._resume_after_auction() + return + if not self.auction.highest_bidder_id: + if len(self.auction.passed_player_ids) >= len(players): + space = self._space(self.auction.property_id) + self.broadcast_l("monopoly-auction-no-bids", property=space.name) + self.auction = None + self._resume_after_auction() + return + + remaining = [ + player + for player in players + if player.id != self.auction.highest_bidder_id + and player.id not in self.auction.passed_player_ids + ] + if remaining: + return + + winner = self._player_by_id(self.auction.highest_bidder_id) + space = self._space(self.auction.property_id) + amount = self.auction.highest_bid + self.auction = None + if winner and winner.cash >= amount: + winner.cash -= amount + self.property_states[space.space_id].owner_id = winner.id + self.broadcast_l( + "monopoly-auction-won", + player=winner.name, + property=space.name, + amount=self._money(amount), + ) + self._announce_completed_set(winner, space) + self._resume_after_auction() + + def _resume_after_auction(self) -> None: + current = self.current_player + if current and not self._is_bankrupt(current): + self._complete_roll_resolution(self._active_player(current)) + else: + self.phase = "await_roll" + + # ------------------------------------------------------------------ + # Asset actions + # ------------------------------------------------------------------ + + def _action_mortgage_property( + self, player: MonopolyPlayer, property_id: str, action_id: str + ) -> None: + property_id = self._decode_property_option(property_id) + if property_id not in self.property_states: + return + space = self._space(property_id) + state = self.property_states[property_id] + if state.owner_id != player.id or state.mortgaged or not self._can_mortgage(space): + return + state.mortgaged = True + player.cash += space.mortgage_value + self.broadcast_l( + "monopoly-property-mortgaged", + player=player.name, + property=space.name, + amount=self._money(space.mortgage_value), + ) + self._after_asset_change(player) + + def _action_unmortgage_property( + self, player: MonopolyPlayer, property_id: str, action_id: str + ) -> None: + property_id = self._decode_property_option(property_id) + if property_id not in self.property_states: + return + space = self._space(property_id) + state = self.property_states[property_id] + cost = self._unmortgage_cost(space) + if state.owner_id != player.id or not state.mortgaged or player.cash < cost: + return + player.cash -= cost + state.mortgaged = False + self.broadcast_l( + "monopoly-property-unmortgaged", + player=player.name, + property=space.name, + amount=self._money(cost), + ) + self._after_asset_change(player) + + def _action_build_house(self, player: MonopolyPlayer, property_id: str, action_id: str) -> None: + property_id = self._decode_property_option(property_id) + space = self._space(property_id) + state = self.property_states[property_id] + if not self._can_build_on(player, space): + return + if player.cash < space.house_cost: + return + if state.houses == 4: + if self.bank_hotels <= 0: + return + self.bank_hotels -= 1 + self.bank_houses += 4 + label = "hotel" + else: + if self.bank_houses <= 0: + return + self.bank_houses -= 1 + label = "house" + state.houses += 1 + player.cash -= space.house_cost + self.broadcast_l( + "monopoly-building-built", + player=player.name, + building=label, + property=space.name, + amount=self._money(space.house_cost), + level=self._building_label(state.houses), + ) + self._after_asset_change(player) + + def _action_sell_house(self, player: MonopolyPlayer, property_id: str, action_id: str) -> None: + property_id = self._decode_property_option(property_id) + space = self._space(property_id) + state = self.property_states[property_id] + if state.owner_id != player.id or state.houses <= 0 or not self._can_sell_from(space): + return + amount = space.house_cost // 2 + if state.houses == HOTEL_LEVEL: + if self.bank_houses < 4: + return + self.bank_hotels += 1 + self.bank_houses -= 4 + else: + self.bank_houses += 1 + state.houses -= 1 + player.cash += amount + self.broadcast_l( + "monopoly-building-sold", + player=player.name, + property=space.name, + amount=self._money(amount), + level=self._building_label(state.houses), + ) + self._after_asset_change(player) + + def _after_asset_change(self, player: MonopolyPlayer) -> None: + if self.pending_debt and self.pending_debt.debtor_id == player.id and player.cash >= self.pending_debt.amount: + self.broadcast_l("monopoly-debt-can-pay", player=player.name) + self.rebuild_all_menus() + + def _action_pay_debt(self, player: MonopolyPlayer, action_id: str) -> None: + if not self.pending_debt or self.pending_debt.debtor_id != player.id: + return + debt = self.pending_debt + if player.cash < debt.amount: + return + player.cash -= debt.amount + creditor = self._player_by_id(debt.creditor_id) if debt.creditor_id else None + if creditor: + creditor.cash += debt.amount + self.broadcast_l( + "monopoly-paid-player", + player=player.name, + target=creditor.name, + amount=self._money(debt.amount), + reason=debt.reason, + ) + else: + if debt.feeds_pot: + self._bank_income(debt.amount) + self.broadcast_l( + "monopoly-paid-bank", + player=player.name, + amount=self._money(debt.amount), + reason=debt.reason, + ) + self.pending_debt = None + current = self._active_player(self.current_player) if self.current_player else player + self._complete_roll_resolution(current) + self.rebuild_all_menus() + + def _action_declare_bankruptcy(self, player: MonopolyPlayer, action_id: str) -> None: + if not self.pending_debt or self.pending_debt.debtor_id != player.id: + return + creditor = self._player_by_id(self.pending_debt.creditor_id) if self.pending_debt.creditor_id else None + self._bankrupt_player(player, creditor) + if self.game_active and self.current_player and self.current_player != player: + self._complete_roll_resolution(self._active_player(self.current_player)) + self.rebuild_all_menus() + + def _action_pay_bail(self, player: MonopolyPlayer, action_id: str) -> None: + if player.cash < BAIL_AMOUNT or not player.in_jail: + return + self._pay_bank(player, BAIL_AMOUNT, "bail") + player.in_jail = False + player.jail_turns = 0 + self.broadcast_l("monopoly-bail-paid", player=player.name, amount=self._money(BAIL_AMOUNT)) + self.rebuild_all_menus() + + def _action_use_jail_card(self, player: MonopolyPlayer, action_id: str) -> None: + if not player.in_jail or not player.jail_free_cards: + return + card_id = player.jail_free_cards.pop(0) + if card_id.endswith("chance"): + self.chance_deck.append(card_id) + else: + self.community_chest_deck.append(card_id) + player.in_jail = False + player.jail_turns = 0 + self.broadcast_l("monopoly-jail-card-used", player=player.name) + self.rebuild_all_menus() + + # ------------------------------------------------------------------ + # Trades + # ------------------------------------------------------------------ + + def _action_offer_trade( + self, player: MonopolyPlayer, selected_partner: str, action_id: str + ) -> None: + """Begin composing a trade by choosing a partner; opens the builder.""" + mp = self._active_player(player) + if self.pending_trade or mp.id in self.trade_draft_offers: + return + target = self._trade_partner_from_option(mp, selected_partner) + if not target: + user = self.get_user(player) + if user: + user.speak_l("monopoly-trade-no-longer-valid") + return + self.trade_draft_offers[mp.id] = MonopolyTradeOffer( + proposer_id=mp.id, target_id=target.id + ) + user = self.get_user(player) + if user: + user.speak_l("monopoly-trade-building", target=target.name) + self.rebuild_all_menus() + + def _action_trade_toggle_give( + self, player: MonopolyPlayer, property_id: str, action_id: str + ) -> None: + self._toggle_trade_property(player, property_id, side="give") + + def _action_trade_toggle_request( + self, player: MonopolyPlayer, property_id: str, action_id: str + ) -> None: + self._toggle_trade_property(player, property_id, side="receive") + + def _toggle_trade_property( + self, player: MonopolyPlayer, property_id: str, *, side: str + ) -> None: + mp = self._active_player(player) + draft = self.trade_draft_offers.get(mp.id) + if not draft: + return + property_id = self._decode_property_option(property_id) + if property_id not in self.property_states: + return + ids = draft.give_property_ids if side == "give" else draft.receive_property_ids + if property_id in ids: + ids.remove(property_id) + else: + owner_id = mp.id if side == "give" else draft.target_id + space = self._space(property_id) + state = self.property_states[property_id] + if state.owner_id != owner_id or not self._can_trade_property(space): + user = self.get_user(player) + if user: + user.speak_l("monopoly-trade-no-longer-valid") + return + ids.append(property_id) + self.rebuild_all_menus() + + def _action_trade_set_cash( + self, player: MonopolyPlayer, amount_text: str, action_id: str + ) -> None: + mp = self._active_player(player) + draft = self.trade_draft_offers.get(mp.id) + if not draft: + return + amount = self._parse_trade_amount(amount_text) + if amount is None: + user = self.get_user(player) + if user: + user.speak_l("monopoly-invalid-trade-amount") + return + # Positive: the proposer pays the partner. Negative: the partner pays. + if amount >= 0: + draft.give_cash = amount + draft.receive_cash = 0 + else: + draft.give_cash = 0 + draft.receive_cash = abs(amount) + self.rebuild_all_menus() + + def _action_trade_toggle_jail( + self, player: MonopolyPlayer, selected: str, action_id: str + ) -> None: + mp = self._active_player(player) + draft = self.trade_draft_offers.get(mp.id) + if not draft: + return + side = selected.split("|", 1)[0] + if side == "give": + draft.give_jail_card = not draft.give_jail_card + elif side == "receive": + draft.receive_jail_card = not draft.receive_jail_card + self.rebuild_all_menus() + + def _action_trade_review(self, player: MonopolyPlayer, action_id: str) -> None: + mp = self._active_player(player) + draft = self.trade_draft_offers.get(mp.id) + if not draft: + return + user = self.get_user(player) + if not user: + return + lines = [self._trade_summary(draft)] + for label, ids in ( + ("You give", draft.give_property_ids), + ("You receive", draft.receive_property_ids), + ): + for property_id in ids: + lines.append(f"{label}: {self._property_detail_line(property_id)}") + self.status_box(player, lines) + + def _action_trade_send(self, player: MonopolyPlayer, action_id: str) -> None: + mp = self._active_player(player) + draft = self.trade_draft_offers.get(mp.id) + if not draft: + return + draft.summary = self._trade_summary(draft) + error = self._validate_trade_offer(draft) + if error: + user = self.get_user(player) + if user: + user.speak_l(error) + return + self.trade_draft_offers.pop(mp.id, None) + self._offer_trade(mp, draft) + + def _action_trade_cancel(self, player: MonopolyPlayer, action_id: str) -> None: + mp = self._active_player(player) + if self.trade_draft_offers.pop(mp.id, None) is not None: + user = self.get_user(player) + if user: + user.speak_l("monopoly-trade-cancelled") + self.rebuild_all_menus() + + def _offer_trade(self, player: MonopolyPlayer, offer: MonopolyTradeOffer) -> None: + error = self._validate_trade_offer(offer) + if error: + user = self.get_user(player) + if user: + user.speak_l(error) + return + + self.pending_trade = offer + target = self._player_by_id(offer.target_id) + self.broadcast_l( + "monopoly-trade-offered", + player=player.name, + target=target.name if target else "Unknown", + summary=offer.summary, + ) + if target: + BotHelper.jolt_bot(target, ticks=random.randint(4, 9)) + self.rebuild_all_menus() + + def _action_accept_trade(self, player: MonopolyPlayer, action_id: str) -> None: + offer = self.pending_trade + if not offer or offer.target_id != player.id: + return + error = self._validate_trade_offer(offer) + if error: + self.pending_trade = None + user = self.get_user(player) + if user: + user.speak_l("monopoly-trade-no-longer-valid") + self.rebuild_all_menus() + return + + proposer = self._player_by_id(offer.proposer_id) + target = self._player_by_id(offer.target_id) + if not proposer or not target: + self.pending_trade = None + self.rebuild_all_menus() + return + + proposer.cash = proposer.cash - offer.give_cash + offer.receive_cash + target.cash = target.cash - offer.receive_cash + offer.give_cash + + transferred_spaces: list[tuple[MonopolyPlayer, MonopolySpace]] = [] + for property_id in offer.give_property_ids: + space = self._space(property_id) + self.property_states[space.space_id].owner_id = target.id + transferred_spaces.append((target, space)) + for property_id in offer.receive_property_ids: + space = self._space(property_id) + self.property_states[space.space_id].owner_id = proposer.id + transferred_spaces.append((proposer, space)) + + if offer.give_jail_card and proposer.jail_free_cards: + target.jail_free_cards.append(proposer.jail_free_cards.pop(0)) + if offer.receive_jail_card and target.jail_free_cards: + proposer.jail_free_cards.append(target.jail_free_cards.pop(0)) + + for property_id in offer.receive_property_ids: + self._charge_trade_mortgage_interest(proposer, property_id) + for property_id in offer.give_property_ids: + self._charge_trade_mortgage_interest(target, property_id) + + self.pending_trade = None + self.broadcast_l( + "monopoly-trade-accepted", + player=proposer.name, + target=target.name, + summary=offer.summary, + ) + for owner, space in transferred_spaces: + self._announce_completed_set(owner, space) + self._announce_payable_pending_debt(proposer) + self._announce_payable_pending_debt(target) + self.rebuild_all_menus() + + def _action_decline_trade(self, player: MonopolyPlayer, action_id: str) -> None: + offer = self.pending_trade + if not offer or offer.target_id != player.id: + return + proposer = self._player_by_id(offer.proposer_id) + self.pending_trade = None + self.broadcast_l( + "monopoly-trade-declined", + player=proposer.name if proposer else "Unknown", + target=player.name, + summary=offer.summary, + ) + self.rebuild_all_menus() + + # ------------------------------------------------------------------ + # Menu option helpers + # ------------------------------------------------------------------ + + def _mortgage_property_options(self, player: Player) -> list[str]: + mp = self._active_player(player) + options = [] + for space in self._owned_spaces(mp): + state = self.property_states[space.space_id] + if not state.mortgaged and self._can_mortgage(space): + options.append(self._encode_property_option(space, space.mortgage_value)) + return options + + def _unmortgage_property_options(self, player: Player) -> list[str]: + mp = self._active_player(player) + options = [] + for space in self._owned_spaces(mp): + state = self.property_states[space.space_id] + cost = self._unmortgage_cost(space) + if state.mortgaged and mp.cash >= cost: + options.append(self._encode_property_option(space, cost)) + return options + + def _build_property_options(self, player: Player) -> list[str]: + mp = self._active_player(player) + return [ + self._encode_property_option(space, space.house_cost) + for space in self._owned_spaces(mp) + if self._can_build_on(mp, space) + ] + + def _sell_building_options(self, player: Player) -> list[str]: + mp = self._active_player(player) + return [ + self._encode_property_option(space, space.house_cost // 2) + for space in self._owned_spaces(mp) + if self.property_states[space.space_id].houses > 0 and self._can_sell_from(space) + ] + + def _can_offer_trade(self, proposer: MonopolyPlayer) -> bool: + """Whether a player may start composing a trade right now.""" + if proposer.bankrupt or proposer.is_spectator or self.pending_trade: + return False + if self.auction or self.pending_purchase_property_id: + return False + if self.pending_debt and self.pending_debt.debtor_id != proposer.id: + return False + return True + + def _trade_partner_options(self, player: Player) -> list[str]: + mp = self._active_player(player) + if not self._can_offer_trade(mp): + return [] + return [ + f"{target.id}|{target.name}" + for target in self._solvent_players() + if target.id != mp.id and not target.is_spectator + ] + + def _trade_partner_from_option( + self, player: MonopolyPlayer, selected_partner: str + ) -> MonopolyPlayer | None: + target_id = selected_partner.split("|", 1)[0] + target = self._player_by_id(target_id) + if not target or target.id == player.id or target.bankrupt or target.is_spectator: + return None + return target + + def _trade_property_options(self, player: Player, *, side: str) -> list[str]: + """Checklist options for one side of the trade draft (give/request).""" + mp = self._active_player(player) + draft = self.trade_draft_offers.get(mp.id) + if not draft: + return [] + if side == "give": + owner_id, selected = mp.id, draft.give_property_ids + else: + owner_id, selected = draft.target_id, draft.receive_property_ids + owner = self._player_by_id(owner_id) + if not owner: + return [] + options = [] + for space in self._owned_spaces(owner): + if not self._can_trade_property(space): + continue + mark = "* " if space.space_id in selected else "" + options.append(f"{space.space_id}|{mark}{space.name}") + return options + + def _trade_give_options(self, player: Player) -> list[str]: + return self._trade_property_options(player, side="give") + + def _trade_request_options(self, player: Player) -> list[str]: + return self._trade_property_options(player, side="receive") + + def _trade_jail_options(self, player: Player) -> list[str]: + mp = self._active_player(player) + draft = self.trade_draft_offers.get(mp.id) + if not draft: + return [] + target = self._player_by_id(draft.target_id) + options = [] + if mp.jail_free_cards: + mark = "* " if draft.give_jail_card else "" + options.append(f"give|{mark}Include your Get Out of Jail Free card") + if target and target.jail_free_cards: + mark = "* " if draft.receive_jail_card else "" + options.append(f"receive|{mark}Request {target.name}'s Get Out of Jail Free card") + return options + + def _bot_select_first_option(self, player: Player, options: list[str]) -> str | None: + return options[0] if options else None + + def _bot_input_auction_bid(self, player: MonopolyPlayer) -> str | None: + if not self.auction: + return None + space = self._space(self.auction.property_id) + minimum = self._minimum_auction_bid() + max_bid = min(player.cash, max(space.price, space.mortgage_value * 2)) + if self._owns_group_candidate(player, space): + max_bid = min(player.cash, space.price + 100) + if minimum <= max_bid and player.cash - minimum >= 100: + return str(minimum) + return None + + # ------------------------------------------------------------------ + # Core economic helpers + # ------------------------------------------------------------------ + + def _ensure_property_states(self) -> None: + for space in self.board.purchasable_spaces: + self.property_states.setdefault(space.space_id, MonopolyPropertyState()) + + def _money(self, amount: int) -> str: + return f"${amount}" + + def _space(self, space_id: str) -> MonopolySpace: + return self.board.get_space(space_id) + + def _space_at(self, index: int) -> MonopolySpace: + return self.board.get_space_at(index) + + def _player_by_id(self, player_id: str) -> MonopolyPlayer | None: + player = self.get_player_by_id(player_id) + return player if player is None else self._active_player(player) + + def _solvent_players(self) -> list[MonopolyPlayer]: + return [ + self._active_player(player) + for player in self.get_active_players() + if not self._active_player(player).bankrupt + ] + + def _bank_income(self, amount: int) -> None: + """Route money paid to the bank into the Free Parking pot when enabled. + + Implements the optional Free Parking jackpot house rule: taxes, fees, + and bail collected by the bank accumulate in a pot that a player wins + by landing on Free Parking. No-op under the official ruleset. + """ + if amount > 0 and self.options.free_parking_jackpot: + self.free_parking_pot += amount + + def _credit(self, player: MonopolyPlayer, amount: int, reason: str) -> None: + if amount <= 0: + return + player.cash += amount + self.broadcast_l( + "monopoly-collected", + player=player.name, + amount=self._money(amount), + reason=reason, + ) + + def _pay_bank( + self, player: MonopolyPlayer, amount: int, reason: str, *, feeds_pot: bool = True + ) -> bool: + if amount <= 0: + return True + if player.cash >= amount: + player.cash -= amount + if feeds_pot: + self._bank_income(amount) + self.broadcast_l( + "monopoly-paid-bank", + player=player.name, + amount=self._money(amount), + reason=reason, + ) + return True + self._set_debt(player, amount, None, reason, feeds_pot=feeds_pot) + return False + + def _pay_player( + self, debtor: MonopolyPlayer, creditor: MonopolyPlayer, amount: int, reason: str + ) -> bool: + if amount <= 0 or debtor.id == creditor.id: + return True + if debtor.cash >= amount: + debtor.cash -= amount + creditor.cash += amount + self.broadcast_l( + "monopoly-paid-player", + player=debtor.name, + target=creditor.name, + amount=self._money(amount), + reason=reason, + ) + return True + self._set_debt(debtor, amount, creditor, reason) + return False + + def _set_debt( + self, + debtor: MonopolyPlayer, + amount: int, + creditor: MonopolyPlayer | None, + reason: str, + *, + feeds_pot: bool = False, + ) -> None: + self.pending_debt = MonopolyDebt( + debtor_id=debtor.id, + creditor_id=creditor.id if creditor else "", + amount=amount, + reason=reason, + feeds_pot=feeds_pot and creditor is None, + ) + self.phase = "await_debt" + target = creditor.name if creditor else "the bank" + self.broadcast_l( + "monopoly-debt-created", + player=debtor.name, + amount=self._money(amount), + target=target, + reason=reason, + ) + + def _move_steps(self, player: MonopolyPlayer, steps: int) -> None: + self._move_to(player, player.position + steps, collect_go=True) + + def _move_to(self, player: MonopolyPlayer, target_position: int, *, collect_go: bool) -> None: + old_position = player.position + board_size = len(self.board.spaces) + wrapped_target = target_position % board_size + if collect_go and target_position >= board_size and old_position != wrapped_target: + self._credit(player, self.board.pass_go_cash, "passing GO") + self.broadcast_l( + "monopoly-pass-go", + player=player.name, + amount=self._money(self.board.pass_go_cash), + ) + elif collect_go and wrapped_target < old_position and target_position != old_position: + self._credit(player, self.board.pass_go_cash, "passing GO") + self.broadcast_l( + "monopoly-pass-go", + player=player.name, + amount=self._money(self.board.pass_go_cash), + ) + player.position = wrapped_target + self.broadcast_l("monopoly-moved-to", player=player.name, space=self._space_at(player.position).name) + + def _move_to_nearest(self, player: MonopolyPlayer, kind: str) -> None: + board_size = len(self.board.spaces) + for distance in range(1, board_size + 1): + target = (player.position + distance) % board_size + if self._space_at(target).kind == kind: + self._move_to(player, player.position + distance, collect_go=True) + return + + def _send_to_jail(self, player: MonopolyPlayer) -> None: + player.position = JAIL_POSITION + player.in_jail = True + player.jail_turns = 0 + self.broadcast_l("monopoly-go-to-jail", player=player.name) + + def _calculate_rent( + self, + space: MonopolySpace, + *, + roll_total: int, + railroad_multiplier: int = 1, + utility_multiplier: int | None = None, + ) -> int: + state = self.property_states[space.space_id] + owner_id = state.owner_id + if space.kind == "street": + rent = space.rents[state.houses] + if state.houses == 0 and self._owns_complete_group(owner_id, space.color_group): + rent *= 2 + return rent + if space.kind == "railroad": + owned_count = len( + [ + owned_space + for owned_space in self._owned_spaces_by_id(owner_id) + if owned_space.kind == "railroad" + ] + ) + index = max(0, min(owned_count, len(space.rents)) - 1) + return space.rents[index] * railroad_multiplier + if space.kind == "utility": + multiplier = utility_multiplier + if multiplier is None: + owned_count = len( + [ + owned_space + for owned_space in self._owned_spaces_by_id(owner_id) + if owned_space.kind == "utility" + ] + ) + multiplier = 10 if owned_count >= 2 else 4 + return roll_total * multiplier + return 0 + + def _owns_complete_group(self, owner_id: str, color_group: str) -> bool: + if not owner_id or not color_group: + return False + group_ids = self.board.color_group_space_ids.get(color_group, ()) + return all(self.property_states[space_id].owner_id == owner_id for space_id in group_ids) + + def _owns_group_candidate(self, player: MonopolyPlayer, space: MonopolySpace) -> bool: + if not space.color_group: + return False + group_ids = self.board.color_group_space_ids.get(space.color_group, ()) + return all( + space_id == space.space_id or self.property_states[space_id].owner_id == player.id + for space_id in group_ids + ) + + def _owned_spaces(self, player: MonopolyPlayer) -> list[MonopolySpace]: + return self._owned_spaces_by_id(player.id) + + def _owned_spaces_by_id(self, owner_id: str) -> list[MonopolySpace]: + return [ + self._space(space_id) + for space_id, state in self.property_states.items() + if state.owner_id == owner_id + ] + + def _building_count( + self, player: MonopolyPlayer, *, houses: bool = False, hotels: bool = False + ) -> int: + count = 0 + for space in self._owned_spaces(player): + level = self.property_states[space.space_id].houses + if houses and 0 < level < HOTEL_LEVEL: + count += level + if hotels and level == HOTEL_LEVEL: + count += 1 + return count + + def _can_mortgage(self, space: MonopolySpace) -> bool: + if space.kind != "street": + return True + group_ids = self.board.color_group_space_ids.get(space.color_group, ()) + return all(self.property_states[space_id].houses == 0 for space_id in group_ids) + + def _unmortgage_cost(self, space: MonopolySpace) -> int: + return space.mortgage_value + max(1, space.mortgage_value // 10) + + def _can_build_on(self, player: MonopolyPlayer, space: MonopolySpace) -> bool: + if space.kind != "street" or space.house_cost <= 0 or player.cash < space.house_cost: + return False + state = self.property_states[space.space_id] + if state.owner_id != player.id or state.mortgaged or state.houses >= HOTEL_LEVEL: + return False + group_ids = self.board.color_group_space_ids.get(space.color_group, ()) + if not group_ids or not all(self.property_states[space_id].owner_id == player.id for space_id in group_ids): + return False + if any(self.property_states[space_id].mortgaged for space_id in group_ids): + return False + levels = [self.property_states[space_id].houses for space_id in group_ids] + if state.houses > min(levels): + return False + if state.houses == 4: + return self.bank_hotels > 0 + return self.bank_houses > 0 + + def _can_sell_from(self, space: MonopolySpace) -> bool: + if space.kind != "street": + return False + state = self.property_states[space.space_id] + group_ids = self.board.color_group_space_ids.get(space.color_group, ()) + levels = [self.property_states[space_id].houses for space_id in group_ids] + if state.houses < max(levels): + return False + if state.houses == HOTEL_LEVEL: + return self.bank_houses >= 4 + return True + + def _can_trade_property(self, space: MonopolySpace) -> bool: + state = self.property_states[space.space_id] + if state.houses > 0: + return False + if space.kind != "street": + return True + group_ids = self.board.color_group_space_ids.get(space.color_group, ()) + return all(self.property_states[space_id].houses == 0 for space_id in group_ids) + + def _trade_summary(self, offer: MonopolyTradeOffer) -> str: + proposer = self._player_by_id(offer.proposer_id) + target = self._player_by_id(offer.target_id) + give = self._trade_side_label( + cash=offer.give_cash, + property_ids=offer.give_property_ids, + jail_card=offer.give_jail_card, + ) + receive = self._trade_side_label( + cash=offer.receive_cash, + property_ids=offer.receive_property_ids, + jail_card=offer.receive_jail_card, + ) + target_name = target.name if target else "Unknown" + proposer_name = proposer.name if proposer else "Unknown" + return f"{proposer_name} gives {give} to {target_name} for {receive}" + + def _trade_side_label( + self, *, cash: int, property_ids: list[str], jail_card: bool + ) -> str: + parts: list[str] = [] + if cash: + parts.append(self._money(cash)) + for property_id in property_ids: + parts.append(self._space(property_id).name) + if jail_card: + parts.append("Get Out of Jail Free card") + return " and ".join(parts) if parts else "nothing" + + def _property_detail_line(self, property_id: str) -> str: + """A one-line summary of a property for the trade review screen.""" + space = self._space(property_id) + state = self.property_states[property_id] + bits = [space.name] + if space.color_group: + bits.append(space.color_group.replace("_", " ")) + if space.rents: + bits.append(f"rent {self._money(min(space.rents))}-{self._money(max(space.rents))}") + bits.append(f"mortgage {self._money(space.mortgage_value)}") + if state.mortgaged: + bits.append("currently mortgaged") + if state.houses: + bits.append(self._building_label(state.houses)) + return ", ".join(bits) + "." + + def _parse_trade_amount(self, amount_text: str) -> int | None: + cleaned = amount_text.strip().replace("$", "").replace(",", "") + if not cleaned: + return None + try: + return int(cleaned) + except ValueError: + return None + + def _validate_trade_offer(self, offer: MonopolyTradeOffer) -> str | None: + if not self._is_playing(): + return "action-not-playing" + proposer = self._player_by_id(offer.proposer_id) + target = self._player_by_id(offer.target_id) + if not proposer or not target or proposer.id == target.id: + return "action-not-available" + if proposer.bankrupt or target.bankrupt or proposer.is_spectator or target.is_spectator: + return "monopoly-player-bankrupt-disabled" + if self.auction: + return "monopoly-auction-active" + if self.pending_purchase_property_id: + return "monopoly-resolve-property-first" + if self.pending_debt and self.pending_debt.debtor_id not in {proposer.id, target.id}: + return "monopoly-debt-pending" + if offer.give_cash < 0 or offer.receive_cash < 0: + return "monopoly-trade-no-longer-valid" + if not any( + [ + offer.give_cash, + offer.receive_cash, + offer.give_property_ids, + offer.receive_property_ids, + offer.give_jail_card, + offer.receive_jail_card, + ] + ): + return "monopoly-trade-no-longer-valid" + + for property_id in offer.give_property_ids: + if property_id not in self.property_states: + return "monopoly-trade-no-longer-valid" + space = self._space(property_id) + state = self.property_states[property_id] + if state.owner_id != proposer.id or not self._can_trade_property(space): + return "monopoly-trade-no-longer-valid" + for property_id in offer.receive_property_ids: + if property_id not in self.property_states: + return "monopoly-trade-no-longer-valid" + space = self._space(property_id) + state = self.property_states[property_id] + if state.owner_id != target.id or not self._can_trade_property(space): + return "monopoly-trade-no-longer-valid" + if offer.give_jail_card and not proposer.jail_free_cards: + return "monopoly-no-jail-card" + if offer.receive_jail_card and not target.jail_free_cards: + return "monopoly-no-jail-card" + + proposer_cash_after = proposer.cash - offer.give_cash + offer.receive_cash + target_cash_after = target.cash - offer.receive_cash + offer.give_cash + if proposer_cash_after < 0 or target_cash_after < 0: + return "monopoly-not-enough-cash" + proposer_interest = sum( + self._trade_mortgage_interest(property_id) + for property_id in offer.receive_property_ids + ) + target_interest = sum( + self._trade_mortgage_interest(property_id) + for property_id in offer.give_property_ids + ) + if proposer_cash_after < proposer_interest or target_cash_after < target_interest: + return "monopoly-not-enough-cash" + return None + + def _trade_mortgage_interest(self, property_id: str) -> int: + if not property_id: + return 0 + state = self.property_states[property_id] + if not state.mortgaged: + return 0 + return max(1, self._space(property_id).mortgage_value // 10) + + def _charge_trade_mortgage_interest( + self, player: MonopolyPlayer, property_id: str + ) -> None: + interest = self._trade_mortgage_interest(property_id) + if interest <= 0: + return + player.cash -= interest + self.broadcast_l( + "monopoly-mortgage-transfer-interest-paid", + player=player.name, + amount=self._money(interest), + ) + + def _announce_payable_pending_debt(self, player: MonopolyPlayer) -> None: + if self.pending_debt and self.pending_debt.debtor_id == player.id and player.cash >= self.pending_debt.amount: + self.broadcast_l("monopoly-debt-can-pay", player=player.name) + + def _building_label(self, houses: int) -> str: + if houses == 0: + return "no buildings" + if houses == HOTEL_LEVEL: + return "hotel" + return f"{houses} house" if houses == 1 else f"{houses} houses" + + def _encode_property_option(self, space: MonopolySpace, amount: int) -> str: + return f"{space.space_id}|{space.name} ({self._money(amount)})" + + def _decode_property_option(self, option: str) -> str: + return option.split("|", 1)[0] + + def _auction_players(self) -> list[MonopolyPlayer]: + return [player for player in self._solvent_players() if not player.is_spectator] + + def _minimum_auction_bid(self) -> int: + if not self.auction or self.auction.highest_bid <= 0: + return MIN_AUCTION_INCREMENT + return self.auction.highest_bid + MIN_AUCTION_INCREMENT + + def _announce_completed_set(self, player: MonopolyPlayer, space: MonopolySpace) -> None: + if space.kind == "street" and self._owns_complete_group(player.id, space.color_group): + self.broadcast_l( + "monopoly-completed-set", + player=player.name, + group=space.color_group.replace("_", " "), + ) + elif space.kind in {"railroad", "utility"}: + owned_count = len([owned for owned in self._owned_spaces(player) if owned.kind == space.kind]) + target = 4 if space.kind == "railroad" else 2 + if owned_count == target: + self.broadcast_l("monopoly-completed-set", player=player.name, group=f"{space.kind}s") + + def _bankrupt_player( + self, player: MonopolyPlayer, creditor: MonopolyPlayer | None + ) -> None: + self._liquidate_all_buildings(player) + if creditor: + creditor.cash += player.cash + for space in self._owned_spaces(player): + self.property_states[space.space_id].owner_id = creditor.id + creditor.jail_free_cards.extend(player.jail_free_cards) + else: + for space in self._owned_spaces(player): + self.property_states[space.space_id] = MonopolyPropertyState() + + player.cash = 0 + player.jail_free_cards.clear() + player.bankrupt = True + player.in_jail = False + self.pending_debt = None + self.pending_purchase_property_id = "" + if self.pending_trade and player.id in { + self.pending_trade.proposer_id, + self.pending_trade.target_id, + }: + self.pending_trade = None + if self.auction and player.id in {p.id for p in self._auction_players()}: + self.auction.passed_player_ids.append(player.id) + self.turn_player_ids = [player_id for player_id in self.turn_player_ids if player_id != player.id] + creditor_name = creditor.name if creditor else "the bank" + self.broadcast_l("monopoly-player-bankrupt", player=player.name, creditor=creditor_name) + self._check_for_winner() + + def _liquidate_all_buildings(self, player: MonopolyPlayer) -> None: + for space in self._owned_spaces(player): + state = self.property_states[space.space_id] + if state.houses == 0: + continue + if state.houses == HOTEL_LEVEL: + self.bank_hotels += 1 + player.cash += (space.house_cost // 2) * 5 + else: + self.bank_houses += state.houses + player.cash += (space.house_cost // 2) * state.houses + state.houses = 0 + + def _check_for_winner(self) -> None: + solvent = self._solvent_players() + if len(solvent) == 1: + winner = solvent[0] + self.winner_id = winner.id + self.broadcast_l( + "monopoly-winner", + player=winner.name, + value=self._money(self._net_worth(winner)), + ) + self.finish_game() + + def _net_worth(self, player: MonopolyPlayer) -> int: + total = player.cash + for space in self._owned_spaces(player): + state = self.property_states[space.space_id] + total += space.mortgage_value if state.mortgaged else space.price + if space.kind == "street": + if state.houses == HOTEL_LEVEL: + total += space.house_cost * 5 + else: + total += space.house_cost * state.houses + return total + + # ------------------------------------------------------------------ + # Status actions, bots, and results + # ------------------------------------------------------------------ + + def _action_check_assets(self, player: MonopolyPlayer, action_id: str) -> None: + user = self.get_user(player) + if not user: + return + lines = [ + f"{player.name}: {self._money(player.cash)} cash, " + f"net worth {self._money(self._net_worth(player))}, " + f"at {self._space_at(player.position).name}." + ] + if player.in_jail: + lines.append(f"In jail, attempt {player.jail_turns + 1} of 3.") + if player.jail_free_cards: + lines.append(f"Get Out of Jail Free cards: {len(player.jail_free_cards)}.") + owned = self._owned_spaces(player) + if owned: + for space in owned: + state = self.property_states[space.space_id] + markers = [] + if state.mortgaged: + markers.append("mortgaged") + if state.houses: + markers.append(self._building_label(state.houses)) + suffix = f" ({', '.join(markers)})" if markers else "" + lines.append(f"{space.name}{suffix}.") + else: + lines.append("No properties owned.") + self.status_box(player, lines) + + def _action_check_board(self, player: MonopolyPlayer, action_id: str) -> None: + user = self.get_user(player) + if not user: + return + unowned = [space for space in self.board.purchasable_spaces if not self.property_states[space.space_id].owner_id] + lines = [ + f"Bank supply: {self.bank_houses} houses, {self.bank_hotels} hotels.", + f"Unowned properties: {len(unowned)}.", + ] + if self.options.free_parking_jackpot: + lines.append(f"Free Parking pot: {self._money(self.free_parking_pot)}.") + for other in self._solvent_players(): + lines.append( + f"{other.name}: {self._space_at(other.position).name}, " + f"{self._money(other.cash)} cash, net worth {self._money(self._net_worth(other))}." + ) + if self.pending_debt: + debtor = self._player_by_id(self.pending_debt.debtor_id) + target = self._player_by_id(self.pending_debt.creditor_id) + lines.append( + f"Pending debt: {debtor.name if debtor else 'Unknown'} owes " + f"{self._money(self.pending_debt.amount)} to " + f"{target.name if target else 'the bank'}." + ) + if self.auction: + space = self._space(self.auction.property_id) + bidder = self._player_by_id(self.auction.highest_bidder_id) + high = self._money(self.auction.highest_bid) if self.auction.highest_bid else "no bid" + lines.append(f"Auction: {space.name}, high bid {high} by {bidder.name if bidder else 'nobody'}.") + if self.pending_trade: + lines.append(f"Pending trade: {self.pending_trade.summary}.") + self.status_box(player, lines) + + def on_tick(self) -> None: + super().on_tick() + if self.status != GameStatus.PLAYING or not self.game_active: + return + if self.pending_trade: + self._process_trade_bot() + if self.auction: + self._process_auction_bots() + else: + BotHelper.on_tick(self) + + def _process_trade_bot(self) -> None: + if not self.pending_trade: + return + target = self._player_by_id(self.pending_trade.target_id) + if not target or not target.is_bot: + return + BotHelper.process_bot_action( + bot=target, + think_fn=lambda target=target: self.bot_think(target), + execute_fn=lambda action_id, target=target: self.execute_action(target, action_id), + ) + + def _process_auction_bots(self) -> None: + for bot in self._auction_players(): + if not bot.is_bot or bot.id in (self.auction.passed_player_ids if self.auction else []): + continue + BotHelper.process_bot_action( + bot=bot, + think_fn=lambda bot=bot: self.bot_think(bot), + execute_fn=lambda action_id, bot=bot: self.execute_action(bot, action_id), + ) + + def bot_think(self, player: MonopolyPlayer) -> str | None: + if player.bankrupt: + return None + if self.pending_trade and self.pending_trade.target_id == player.id: + if self._validate_trade_offer(self.pending_trade): + return "decline_trade" + return "accept_trade" if self._bot_should_accept_trade(player, self.pending_trade) else "decline_trade" + if self.auction: + if player.id == self.auction.highest_bidder_id: + return None + return "auction_bid" if self._bot_input_auction_bid(player) else "auction_pass" + if self.pending_debt and self.pending_debt.debtor_id == player.id: + if player.cash >= self.pending_debt.amount: + return "pay_debt" + if self._sell_building_options(player): + return "sell_house" + if self._mortgage_property_options(player): + return "mortgage_property" + return "declare_bankruptcy" + if self.current_player != player: + return None + if self.phase == "await_roll": + if player.in_jail: + if player.jail_free_cards: + return "use_jail_card" + if player.cash > 350: + return "pay_bail" + return "roll" + if self.phase == "await_purchase": + if not self.pending_purchase_property_id: + return None + space = self._space(self.pending_purchase_property_id) + if player.cash - space.price >= 200 or self._owns_group_candidate(player, space): + return "buy_property" + return "auction_property" + if self.phase == "post_roll": + if player.cash > 500 and self._build_property_options(player): + return "build_house" + return "end_turn" + return None + + def _bot_should_accept_trade( + self, target: MonopolyPlayer, offer: MonopolyTradeOffer + ) -> bool: + incoming = self._trade_side_value( + owner=target, + cash=offer.give_cash, + property_ids=offer.give_property_ids, + jail_card=offer.give_jail_card, + ) + outgoing = self._trade_side_value( + owner=target, + cash=offer.receive_cash, + property_ids=offer.receive_property_ids, + jail_card=offer.receive_jail_card, + ) + return incoming >= outgoing + + def _trade_side_value( + self, + *, + owner: MonopolyPlayer, + cash: int, + property_ids: list[str], + jail_card: bool, + ) -> int: + value = cash + for property_id in property_ids: + space = self._space(property_id) + state = self.property_states[property_id] + value += space.mortgage_value if state.mortgaged else space.price + if self._owns_group_candidate(owner, space): + value += 100 + if jail_card: + value += JAIL_CARD_TRADE_VALUE + return value + + def build_game_result(self) -> GameResult: + sorted_players = sorted( + self.get_active_players(), + key=lambda player: ( + not self._active_player(player).bankrupt, + self._net_worth(self._active_player(player)), + ), + reverse=True, + ) + winner = self._player_by_id(self.winner_id) if self.winner_id else None + return GameResult( + game_type=self.get_type(), + timestamp=datetime.now().isoformat(), + duration_ticks=self.sound_scheduler_tick, + player_results=[ + PlayerResult(player_id=p.id, player_name=p.name, is_bot=p.is_bot) + for p in sorted_players + ], + custom_data={ + "winner_name": winner.name if winner else None, + "net_worth": {p.name: self._net_worth(self._active_player(p)) for p in self.players}, + }, + ) + + def format_end_screen(self, result: GameResult, locale: str) -> list[str]: + lines = [Localization.get(locale, "game-final-scores")] + net_worth = result.custom_data.get("net_worth", {}) + for index, player_result in enumerate(result.player_results, 1): + amount = net_worth.get(player_result.player_name, 0) + lines.append(f"{index}. {player_result.player_name}: {self._money(amount)}") + return lines diff --git a/server/locales/ar/monopoly.ftl b/server/locales/ar/monopoly.ftl new file mode 100644 index 00000000..330c8df1 --- /dev/null +++ b/server/locales/ar/monopoly.ftl @@ -0,0 +1,116 @@ +# Monopoly game messages + +game-name-monopoly = Monopoly + +monopoly-started = Monopoly started on { $board }. Each player begins with { $cash }. +monopoly-turn = { $player }'s turn. +monopoly-in-jail-turn = { $player } is in jail. Failed roll attempts: { $turns }. + +# Actions +monopoly-roll-dice = Roll dice +monopoly-buy-property = Buy property +monopoly-auction-property = Auction property +monopoly-end-turn = End turn +monopoly-auction-bid = Place auction bid +monopoly-auction-pass = Pass in auction +monopoly-mortgage-property = Mortgage property +monopoly-unmortgage-property = Unmortgage property +monopoly-build-house = Build house or hotel +monopoly-sell-house = Sell house or hotel +monopoly-pay-bail = Pay bail +monopoly-use-jail-card = Use Get Out of Jail Free card +monopoly-pay-debt = Pay debt +monopoly-declare-bankruptcy = Declare bankruptcy +monopoly-offer-trade = Offer trade +monopoly-submit-trade-amount = Set trade amount +monopoly-accept-trade = Accept trade +monopoly-decline-trade = Decline trade +monopoly-check-assets = Check assets +monopoly-check-board = Check board + +# Prompts +monopoly-enter-auction-bid = Enter auction bid amount +monopoly-select-property-mortgage = Select a property to mortgage +monopoly-select-property-unmortgage = Select a property to unmortgage +monopoly-select-property-build = Select a property to build on +monopoly-select-property-sell = Select a property to sell from +monopoly-select-trade-offer = Select a trade offer +monopoly-enter-trade-cash = Enter the cash amount for this trade. For property swaps, use a positive amount if you pay the other player, a negative amount if they pay you, or 0. + +# Validation +monopoly-player-bankrupt-disabled = You are bankrupt. +monopoly-auction-active = Resolve the active auction first. +monopoly-resolve-property-first = Resolve the pending property decision first. +monopoly-debt-pending = Resolve the pending debt first. +monopoly-roll-not-available = Rolling is not available right now. +monopoly-roll-first = Roll first. +monopoly-no-property-to-buy = There is no property to buy right now. +monopoly-no-property-to-auction = There is no property to auction right now. +monopoly-no-debt = There is no debt to pay. +monopoly-no-auction-active = There is no auction in progress. +monopoly-auction-already-passed = You have already passed in this auction. +monopoly-not-enough-cash = You do not have enough cash. +monopoly-not-in-jail = You are not in jail. +monopoly-no-jail-card = You do not have a Get Out of Jail Free card. +monopoly-no-mortgage-options = You do not have any properties available to mortgage. +monopoly-no-unmortgage-options = You do not have any properties available to unmortgage. +monopoly-no-build-options = You do not have any properties available to build on. +monopoly-no-sell-options = You do not have any buildings available to sell. +monopoly-no-trade-options = You do not have any valid trades to offer. +monopoly-trade-pending = Resolve the pending trade first. +monopoly-no-trade-pending = There is no trade pending for you. +monopoly-trade-no-longer-valid = That trade is no longer valid. +monopoly-invalid-trade-amount = That trade amount is not a valid number. +monopoly-invalid-bid = That bid is not a valid number. +monopoly-bid-out-of-range = Bid at least { $minimum } and no more than your cash ({ $cash }). + +# Board events +monopoly-roll-result = { $player } rolled { $die1 } + { $die2 } = { $total }. +monopoly-landed = { $player } landed on { $space }. +monopoly-moved-to = { $player } moved to { $space }. +monopoly-pass-go = { $player } passed GO and collected { $amount }. +monopoly-collected = { $player } collected { $amount } for { $reason }. +monopoly-paid-bank = { $player } paid { $amount } to the bank for { $reason }. +monopoly-paid-player = { $player } paid { $amount } to { $target } for { $reason }. +monopoly-free-parking = { $player } is resting on Free Parking. +monopoly-just-visiting = { $player } is just visiting jail. +monopoly-go-to-jail = { $player } goes directly to jail. +monopoly-landed-own-property = { $player } landed on their own { $property }. + +# Properties and rent +monopoly-property-available = { $property } is unowned and costs { $price }. +monopoly-property-bought = { $player } bought { $property } for { $price }. +monopoly-completed-set = { $player } completed the { $group } set. +monopoly-mortgaged-no-rent = { $player } landed on mortgaged { $property }; no rent is due. +monopoly-property-mortgaged = { $player } mortgaged { $property } for { $amount }. +monopoly-property-unmortgaged = { $player } unmortgaged { $property } for { $amount }. +monopoly-building-built = { $player } built a { $building } on { $property } for { $amount }. Level: { $level }. +monopoly-building-sold = { $player } sold a building on { $property } for { $amount }. Level: { $level }. + +# Trades +monopoly-trade-offered = { $player } offered { $target } a trade: { $summary }. +monopoly-trade-accepted = { $target } accepted { $player }'s trade: { $summary }. +monopoly-trade-declined = { $target } declined { $player }'s trade: { $summary }. +monopoly-mortgage-transfer-interest-paid = { $player } paid { $amount } mortgage transfer interest. + +# Auctions +monopoly-auction-started = Auction started for { $property }. Minimum bid: { $amount }. +monopoly-auction-bid-placed = { $player } bid { $amount } for { $property }. +monopoly-auction-pass-event = { $player } passed on { $property }. +monopoly-auction-no-bids = No bids for { $property }. It remains unsold. +monopoly-auction-won = { $player } won { $property } for { $amount }. + +# Jail and doubles +monopoly-roll-again = { $player } rolled doubles and gets another roll. +monopoly-three-doubles-jail = { $player } rolled doubles three times and is sent to jail. +monopoly-jail-roll-doubles = { $player } rolled doubles ({ $die1 } and { $die2 }) and leaves jail. +monopoly-jail-roll-failed = { $player } rolled { $die1 } and { $die2 } in jail. Attempt { $attempts }. +monopoly-bail-paid = { $player } paid { $amount } bail. +monopoly-jail-card-used = { $player } used a Get Out of Jail Free card. + +# Cards and debt +monopoly-card-drawn = { $player } drew { $deck }: { $text } +monopoly-debt-created = { $player } owes { $amount } to { $target } for { $reason }. +monopoly-debt-can-pay = { $player } has enough cash to pay the pending debt. +monopoly-player-bankrupt = { $player } is bankrupt. Creditor: { $creditor }. +monopoly-winner = { $player } wins Monopoly with net worth { $value }. diff --git a/server/locales/cs/monopoly.ftl b/server/locales/cs/monopoly.ftl new file mode 100644 index 00000000..330c8df1 --- /dev/null +++ b/server/locales/cs/monopoly.ftl @@ -0,0 +1,116 @@ +# Monopoly game messages + +game-name-monopoly = Monopoly + +monopoly-started = Monopoly started on { $board }. Each player begins with { $cash }. +monopoly-turn = { $player }'s turn. +monopoly-in-jail-turn = { $player } is in jail. Failed roll attempts: { $turns }. + +# Actions +monopoly-roll-dice = Roll dice +monopoly-buy-property = Buy property +monopoly-auction-property = Auction property +monopoly-end-turn = End turn +monopoly-auction-bid = Place auction bid +monopoly-auction-pass = Pass in auction +monopoly-mortgage-property = Mortgage property +monopoly-unmortgage-property = Unmortgage property +monopoly-build-house = Build house or hotel +monopoly-sell-house = Sell house or hotel +monopoly-pay-bail = Pay bail +monopoly-use-jail-card = Use Get Out of Jail Free card +monopoly-pay-debt = Pay debt +monopoly-declare-bankruptcy = Declare bankruptcy +monopoly-offer-trade = Offer trade +monopoly-submit-trade-amount = Set trade amount +monopoly-accept-trade = Accept trade +monopoly-decline-trade = Decline trade +monopoly-check-assets = Check assets +monopoly-check-board = Check board + +# Prompts +monopoly-enter-auction-bid = Enter auction bid amount +monopoly-select-property-mortgage = Select a property to mortgage +monopoly-select-property-unmortgage = Select a property to unmortgage +monopoly-select-property-build = Select a property to build on +monopoly-select-property-sell = Select a property to sell from +monopoly-select-trade-offer = Select a trade offer +monopoly-enter-trade-cash = Enter the cash amount for this trade. For property swaps, use a positive amount if you pay the other player, a negative amount if they pay you, or 0. + +# Validation +monopoly-player-bankrupt-disabled = You are bankrupt. +monopoly-auction-active = Resolve the active auction first. +monopoly-resolve-property-first = Resolve the pending property decision first. +monopoly-debt-pending = Resolve the pending debt first. +monopoly-roll-not-available = Rolling is not available right now. +monopoly-roll-first = Roll first. +monopoly-no-property-to-buy = There is no property to buy right now. +monopoly-no-property-to-auction = There is no property to auction right now. +monopoly-no-debt = There is no debt to pay. +monopoly-no-auction-active = There is no auction in progress. +monopoly-auction-already-passed = You have already passed in this auction. +monopoly-not-enough-cash = You do not have enough cash. +monopoly-not-in-jail = You are not in jail. +monopoly-no-jail-card = You do not have a Get Out of Jail Free card. +monopoly-no-mortgage-options = You do not have any properties available to mortgage. +monopoly-no-unmortgage-options = You do not have any properties available to unmortgage. +monopoly-no-build-options = You do not have any properties available to build on. +monopoly-no-sell-options = You do not have any buildings available to sell. +monopoly-no-trade-options = You do not have any valid trades to offer. +monopoly-trade-pending = Resolve the pending trade first. +monopoly-no-trade-pending = There is no trade pending for you. +monopoly-trade-no-longer-valid = That trade is no longer valid. +monopoly-invalid-trade-amount = That trade amount is not a valid number. +monopoly-invalid-bid = That bid is not a valid number. +monopoly-bid-out-of-range = Bid at least { $minimum } and no more than your cash ({ $cash }). + +# Board events +monopoly-roll-result = { $player } rolled { $die1 } + { $die2 } = { $total }. +monopoly-landed = { $player } landed on { $space }. +monopoly-moved-to = { $player } moved to { $space }. +monopoly-pass-go = { $player } passed GO and collected { $amount }. +monopoly-collected = { $player } collected { $amount } for { $reason }. +monopoly-paid-bank = { $player } paid { $amount } to the bank for { $reason }. +monopoly-paid-player = { $player } paid { $amount } to { $target } for { $reason }. +monopoly-free-parking = { $player } is resting on Free Parking. +monopoly-just-visiting = { $player } is just visiting jail. +monopoly-go-to-jail = { $player } goes directly to jail. +monopoly-landed-own-property = { $player } landed on their own { $property }. + +# Properties and rent +monopoly-property-available = { $property } is unowned and costs { $price }. +monopoly-property-bought = { $player } bought { $property } for { $price }. +monopoly-completed-set = { $player } completed the { $group } set. +monopoly-mortgaged-no-rent = { $player } landed on mortgaged { $property }; no rent is due. +monopoly-property-mortgaged = { $player } mortgaged { $property } for { $amount }. +monopoly-property-unmortgaged = { $player } unmortgaged { $property } for { $amount }. +monopoly-building-built = { $player } built a { $building } on { $property } for { $amount }. Level: { $level }. +monopoly-building-sold = { $player } sold a building on { $property } for { $amount }. Level: { $level }. + +# Trades +monopoly-trade-offered = { $player } offered { $target } a trade: { $summary }. +monopoly-trade-accepted = { $target } accepted { $player }'s trade: { $summary }. +monopoly-trade-declined = { $target } declined { $player }'s trade: { $summary }. +monopoly-mortgage-transfer-interest-paid = { $player } paid { $amount } mortgage transfer interest. + +# Auctions +monopoly-auction-started = Auction started for { $property }. Minimum bid: { $amount }. +monopoly-auction-bid-placed = { $player } bid { $amount } for { $property }. +monopoly-auction-pass-event = { $player } passed on { $property }. +monopoly-auction-no-bids = No bids for { $property }. It remains unsold. +monopoly-auction-won = { $player } won { $property } for { $amount }. + +# Jail and doubles +monopoly-roll-again = { $player } rolled doubles and gets another roll. +monopoly-three-doubles-jail = { $player } rolled doubles three times and is sent to jail. +monopoly-jail-roll-doubles = { $player } rolled doubles ({ $die1 } and { $die2 }) and leaves jail. +monopoly-jail-roll-failed = { $player } rolled { $die1 } and { $die2 } in jail. Attempt { $attempts }. +monopoly-bail-paid = { $player } paid { $amount } bail. +monopoly-jail-card-used = { $player } used a Get Out of Jail Free card. + +# Cards and debt +monopoly-card-drawn = { $player } drew { $deck }: { $text } +monopoly-debt-created = { $player } owes { $amount } to { $target } for { $reason }. +monopoly-debt-can-pay = { $player } has enough cash to pay the pending debt. +monopoly-player-bankrupt = { $player } is bankrupt. Creditor: { $creditor }. +monopoly-winner = { $player } wins Monopoly with net worth { $value }. diff --git a/server/locales/de/monopoly.ftl b/server/locales/de/monopoly.ftl new file mode 100644 index 00000000..330c8df1 --- /dev/null +++ b/server/locales/de/monopoly.ftl @@ -0,0 +1,116 @@ +# Monopoly game messages + +game-name-monopoly = Monopoly + +monopoly-started = Monopoly started on { $board }. Each player begins with { $cash }. +monopoly-turn = { $player }'s turn. +monopoly-in-jail-turn = { $player } is in jail. Failed roll attempts: { $turns }. + +# Actions +monopoly-roll-dice = Roll dice +monopoly-buy-property = Buy property +monopoly-auction-property = Auction property +monopoly-end-turn = End turn +monopoly-auction-bid = Place auction bid +monopoly-auction-pass = Pass in auction +monopoly-mortgage-property = Mortgage property +monopoly-unmortgage-property = Unmortgage property +monopoly-build-house = Build house or hotel +monopoly-sell-house = Sell house or hotel +monopoly-pay-bail = Pay bail +monopoly-use-jail-card = Use Get Out of Jail Free card +monopoly-pay-debt = Pay debt +monopoly-declare-bankruptcy = Declare bankruptcy +monopoly-offer-trade = Offer trade +monopoly-submit-trade-amount = Set trade amount +monopoly-accept-trade = Accept trade +monopoly-decline-trade = Decline trade +monopoly-check-assets = Check assets +monopoly-check-board = Check board + +# Prompts +monopoly-enter-auction-bid = Enter auction bid amount +monopoly-select-property-mortgage = Select a property to mortgage +monopoly-select-property-unmortgage = Select a property to unmortgage +monopoly-select-property-build = Select a property to build on +monopoly-select-property-sell = Select a property to sell from +monopoly-select-trade-offer = Select a trade offer +monopoly-enter-trade-cash = Enter the cash amount for this trade. For property swaps, use a positive amount if you pay the other player, a negative amount if they pay you, or 0. + +# Validation +monopoly-player-bankrupt-disabled = You are bankrupt. +monopoly-auction-active = Resolve the active auction first. +monopoly-resolve-property-first = Resolve the pending property decision first. +monopoly-debt-pending = Resolve the pending debt first. +monopoly-roll-not-available = Rolling is not available right now. +monopoly-roll-first = Roll first. +monopoly-no-property-to-buy = There is no property to buy right now. +monopoly-no-property-to-auction = There is no property to auction right now. +monopoly-no-debt = There is no debt to pay. +monopoly-no-auction-active = There is no auction in progress. +monopoly-auction-already-passed = You have already passed in this auction. +monopoly-not-enough-cash = You do not have enough cash. +monopoly-not-in-jail = You are not in jail. +monopoly-no-jail-card = You do not have a Get Out of Jail Free card. +monopoly-no-mortgage-options = You do not have any properties available to mortgage. +monopoly-no-unmortgage-options = You do not have any properties available to unmortgage. +monopoly-no-build-options = You do not have any properties available to build on. +monopoly-no-sell-options = You do not have any buildings available to sell. +monopoly-no-trade-options = You do not have any valid trades to offer. +monopoly-trade-pending = Resolve the pending trade first. +monopoly-no-trade-pending = There is no trade pending for you. +monopoly-trade-no-longer-valid = That trade is no longer valid. +monopoly-invalid-trade-amount = That trade amount is not a valid number. +monopoly-invalid-bid = That bid is not a valid number. +monopoly-bid-out-of-range = Bid at least { $minimum } and no more than your cash ({ $cash }). + +# Board events +monopoly-roll-result = { $player } rolled { $die1 } + { $die2 } = { $total }. +monopoly-landed = { $player } landed on { $space }. +monopoly-moved-to = { $player } moved to { $space }. +monopoly-pass-go = { $player } passed GO and collected { $amount }. +monopoly-collected = { $player } collected { $amount } for { $reason }. +monopoly-paid-bank = { $player } paid { $amount } to the bank for { $reason }. +monopoly-paid-player = { $player } paid { $amount } to { $target } for { $reason }. +monopoly-free-parking = { $player } is resting on Free Parking. +monopoly-just-visiting = { $player } is just visiting jail. +monopoly-go-to-jail = { $player } goes directly to jail. +monopoly-landed-own-property = { $player } landed on their own { $property }. + +# Properties and rent +monopoly-property-available = { $property } is unowned and costs { $price }. +monopoly-property-bought = { $player } bought { $property } for { $price }. +monopoly-completed-set = { $player } completed the { $group } set. +monopoly-mortgaged-no-rent = { $player } landed on mortgaged { $property }; no rent is due. +monopoly-property-mortgaged = { $player } mortgaged { $property } for { $amount }. +monopoly-property-unmortgaged = { $player } unmortgaged { $property } for { $amount }. +monopoly-building-built = { $player } built a { $building } on { $property } for { $amount }. Level: { $level }. +monopoly-building-sold = { $player } sold a building on { $property } for { $amount }. Level: { $level }. + +# Trades +monopoly-trade-offered = { $player } offered { $target } a trade: { $summary }. +monopoly-trade-accepted = { $target } accepted { $player }'s trade: { $summary }. +monopoly-trade-declined = { $target } declined { $player }'s trade: { $summary }. +monopoly-mortgage-transfer-interest-paid = { $player } paid { $amount } mortgage transfer interest. + +# Auctions +monopoly-auction-started = Auction started for { $property }. Minimum bid: { $amount }. +monopoly-auction-bid-placed = { $player } bid { $amount } for { $property }. +monopoly-auction-pass-event = { $player } passed on { $property }. +monopoly-auction-no-bids = No bids for { $property }. It remains unsold. +monopoly-auction-won = { $player } won { $property } for { $amount }. + +# Jail and doubles +monopoly-roll-again = { $player } rolled doubles and gets another roll. +monopoly-three-doubles-jail = { $player } rolled doubles three times and is sent to jail. +monopoly-jail-roll-doubles = { $player } rolled doubles ({ $die1 } and { $die2 }) and leaves jail. +monopoly-jail-roll-failed = { $player } rolled { $die1 } and { $die2 } in jail. Attempt { $attempts }. +monopoly-bail-paid = { $player } paid { $amount } bail. +monopoly-jail-card-used = { $player } used a Get Out of Jail Free card. + +# Cards and debt +monopoly-card-drawn = { $player } drew { $deck }: { $text } +monopoly-debt-created = { $player } owes { $amount } to { $target } for { $reason }. +monopoly-debt-can-pay = { $player } has enough cash to pay the pending debt. +monopoly-player-bankrupt = { $player } is bankrupt. Creditor: { $creditor }. +monopoly-winner = { $player } wins Monopoly with net worth { $value }. diff --git a/server/locales/en/games.ftl b/server/locales/en/games.ftl index e23fc09f..c06b5918 100644 --- a/server/locales/en/games.ftl +++ b/server/locales/en/games.ftl @@ -42,6 +42,9 @@ game-team-mode-x-teams-of-y = { $num_teams } teams of { $team_size } option-on = on option-off = off +# In-game read-only options viewer +check-game-options = Check game options + # Option navigation option-back = Back option-min-selected = At least { $count } { $count -> diff --git a/server/locales/en/monopoly.ftl b/server/locales/en/monopoly.ftl new file mode 100644 index 00000000..16479620 --- /dev/null +++ b/server/locales/en/monopoly.ftl @@ -0,0 +1,141 @@ +# Monopoly game messages + +game-name-monopoly = Monopoly + +monopoly-started = Monopoly started on { $board }. Each player begins with { $cash }. +monopoly-turn = { $player }'s turn. +monopoly-in-jail-turn = { $player } is in jail. Failed roll attempts: { $turns }. + +# Actions +monopoly-roll-dice = Roll dice +monopoly-buy-property = Buy property +monopoly-auction-property = Auction property +monopoly-end-turn = End turn +monopoly-auction-bid = Place auction bid +monopoly-auction-pass = Pass in auction +monopoly-mortgage-property = Mortgage property +monopoly-unmortgage-property = Unmortgage property +monopoly-build-house = Build house or hotel +monopoly-sell-house = Sell house or hotel +monopoly-pay-bail = Pay bail +monopoly-use-jail-card = Use Get Out of Jail Free card +monopoly-pay-debt = Pay debt +monopoly-declare-bankruptcy = Declare bankruptcy +monopoly-offer-trade = Offer trade +monopoly-trade-give = Choose properties to give +monopoly-trade-request = Choose properties to request +monopoly-trade-cash = Set cash in this trade +monopoly-trade-jail = Include a Get Out of Jail Free card +monopoly-trade-review = Review this trade +monopoly-trade-send = Send trade offer +monopoly-trade-cancel = Cancel trade +monopoly-accept-trade = Accept trade +monopoly-decline-trade = Decline trade +monopoly-check-assets = Check assets +monopoly-check-board = Check board + +# Prompts +monopoly-enter-auction-bid = Enter auction bid amount +monopoly-select-property-mortgage = Select a property to mortgage +monopoly-select-property-unmortgage = Select a property to unmortgage +monopoly-select-property-build = Select a property to build on +monopoly-select-property-sell = Select a property to sell from +monopoly-select-trade-partner = Select a player to trade with +monopoly-select-trade-give = Choose one of your properties to add to or remove from the offer +monopoly-select-trade-request = Choose one of their properties to add to or remove from the offer +monopoly-select-trade-jail = Choose a Get Out of Jail Free card to include or remove +monopoly-enter-trade-cash = Enter the cash for this trade: a positive amount if you pay the other player, a negative amount if they pay you, or 0. + +# Validation +monopoly-player-bankrupt-disabled = You are bankrupt. +monopoly-auction-active = Resolve the active auction first. +monopoly-resolve-property-first = Resolve the pending property decision first. +monopoly-debt-pending = Resolve the pending debt first. +monopoly-roll-not-available = Rolling is not available right now. +monopoly-roll-first = Roll first. +monopoly-no-property-to-buy = There is no property to buy right now. +monopoly-no-property-to-auction = There is no property to auction right now. +monopoly-no-debt = There is no debt to pay. +monopoly-no-auction-active = There is no auction in progress. +monopoly-auction-already-passed = You have already passed in this auction. +monopoly-not-enough-cash = You do not have enough cash. +monopoly-not-in-jail = You are not in jail. +monopoly-no-jail-card = You do not have a Get Out of Jail Free card. +monopoly-no-mortgage-options = You do not have any properties available to mortgage. +monopoly-no-unmortgage-options = You do not have any properties available to unmortgage. +monopoly-no-build-options = You do not have any properties available to build on. +monopoly-no-sell-options = You do not have any buildings available to sell. +monopoly-no-trade-options = You do not have any valid trades to offer. +monopoly-trade-pending = Resolve the pending trade first. +monopoly-no-trade-pending = There is no trade pending for you. +monopoly-trade-no-longer-valid = That trade is no longer valid. +monopoly-invalid-trade-amount = That trade amount is not a valid number. +monopoly-invalid-bid = That bid is not a valid number. +monopoly-bid-out-of-range = Bid at least { $minimum } and no more than your cash ({ $cash }). + +# Board events +monopoly-roll-result = { $player } rolled { $die1 } + { $die2 } = { $total }. +monopoly-landed = { $player } landed on { $space }. +monopoly-moved-to = { $player } moved to { $space }. +monopoly-pass-go = { $player } passed GO and collected { $amount }. +monopoly-collected = { $player } collected { $amount } for { $reason }. +monopoly-paid-bank = { $player } paid { $amount } to the bank for { $reason }. +monopoly-paid-player = { $player } paid { $amount } to { $target } for { $reason }. +monopoly-free-parking = { $player } is resting on Free Parking. +monopoly-free-parking-jackpot = { $player } landed on Free Parking and scooped the { $amount } jackpot! +monopoly-just-visiting = { $player } is just visiting jail. +monopoly-go-to-jail = { $player } goes directly to jail. +monopoly-landed-own-property = { $player } landed on their own { $property }. + +# Properties and rent +monopoly-property-available = { $property } is unowned and costs { $price }. +monopoly-property-bought = { $player } bought { $property } for { $price }. +monopoly-completed-set = { $player } completed the { $group } set. +monopoly-mortgaged-no-rent = { $player } landed on mortgaged { $property }; no rent is due. +monopoly-property-mortgaged = { $player } mortgaged { $property } for { $amount }. +monopoly-property-unmortgaged = { $player } unmortgaged { $property } for { $amount }. +monopoly-building-built = { $player } built a { $building } on { $property } for { $amount }. Level: { $level }. +monopoly-building-sold = { $player } sold a building on { $property } for { $amount }. Level: { $level }. + +# Trades +monopoly-trade-building = Building a trade with { $target }. Add properties, cash, and cards, then send the offer. +monopoly-trade-cancelled = Trade offer cancelled. +monopoly-trade-offered = { $player } offered { $target } a trade: { $summary }. +monopoly-trade-accepted = { $target } accepted { $player }'s trade: { $summary }. +monopoly-trade-declined = { $target } declined { $player }'s trade: { $summary }. +monopoly-mortgage-transfer-interest-paid = { $player } paid { $amount } mortgage transfer interest. + +# Auctions +monopoly-auction-started = Auction started for { $property }. Minimum bid: { $amount }. +monopoly-auction-bid-placed = { $player } bid { $amount } for { $property }. +monopoly-auction-pass-event = { $player } passed on { $property }. +monopoly-auction-no-bids = No bids for { $property }. It remains unsold. +monopoly-auction-won = { $player } won { $property } for { $amount }. + +# Jail and doubles +monopoly-roll-again = { $player } rolled doubles and gets another roll. +monopoly-three-doubles-jail = { $player } rolled doubles three times and is sent to jail. +monopoly-jail-roll-doubles = { $player } rolled doubles ({ $die1 } and { $die2 }) and leaves jail. +monopoly-jail-roll-failed = { $player } rolled { $die1 } and { $die2 } in jail. Attempt { $attempts }. +monopoly-bail-paid = { $player } paid { $amount } bail. +monopoly-jail-card-used = { $player } used a Get Out of Jail Free card. + +# Cards and debt +monopoly-card-drawn = { $player } drew { $deck }: { $text } +monopoly-debt-created = { $player } owes { $amount } to { $target } for { $reason }. +monopoly-debt-can-pay = { $player } has enough cash to pay the pending debt. +monopoly-player-bankrupt = { $player } is bankrupt. Creditor: { $creditor }. +monopoly-winner = { $player } wins Monopoly with net worth { $value }. + +# House-rule options (lobby settings; defaults reproduce the official ruleset) +monopoly-option-starting-cash = Starting cash: ${ $cash } +monopoly-option-enter-starting-cash = Enter the starting cash each player receives +monopoly-option-changed-starting-cash = Starting cash set to ${ $cash }. +monopoly-option-desc-starting-cash = How much money each player begins with. The official rule is 1500. +monopoly-option-free-parking-jackpot = Free Parking jackpot: { $enabled } +monopoly-option-changed-free-parking-jackpot = Free Parking jackpot turned { $enabled }. +monopoly-option-desc-free-parking-jackpot = House rule: taxes, fees, and bail paid to the bank pile into a pot that a player wins by landing on Free Parking. Off by default for official rules. +monopoly-option-free-parking-seed = Free Parking starting pot: ${ $cash } +monopoly-option-enter-free-parking-seed = Enter the amount the Free Parking pot starts and resets to +monopoly-option-changed-free-parking-seed = Free Parking starting pot set to ${ $cash }. +monopoly-option-desc-free-parking-seed = The amount the pot holds at the start and resets to after a player collects it. Default 0. diff --git a/server/locales/es/monopoly.ftl b/server/locales/es/monopoly.ftl new file mode 100644 index 00000000..330c8df1 --- /dev/null +++ b/server/locales/es/monopoly.ftl @@ -0,0 +1,116 @@ +# Monopoly game messages + +game-name-monopoly = Monopoly + +monopoly-started = Monopoly started on { $board }. Each player begins with { $cash }. +monopoly-turn = { $player }'s turn. +monopoly-in-jail-turn = { $player } is in jail. Failed roll attempts: { $turns }. + +# Actions +monopoly-roll-dice = Roll dice +monopoly-buy-property = Buy property +monopoly-auction-property = Auction property +monopoly-end-turn = End turn +monopoly-auction-bid = Place auction bid +monopoly-auction-pass = Pass in auction +monopoly-mortgage-property = Mortgage property +monopoly-unmortgage-property = Unmortgage property +monopoly-build-house = Build house or hotel +monopoly-sell-house = Sell house or hotel +monopoly-pay-bail = Pay bail +monopoly-use-jail-card = Use Get Out of Jail Free card +monopoly-pay-debt = Pay debt +monopoly-declare-bankruptcy = Declare bankruptcy +monopoly-offer-trade = Offer trade +monopoly-submit-trade-amount = Set trade amount +monopoly-accept-trade = Accept trade +monopoly-decline-trade = Decline trade +monopoly-check-assets = Check assets +monopoly-check-board = Check board + +# Prompts +monopoly-enter-auction-bid = Enter auction bid amount +monopoly-select-property-mortgage = Select a property to mortgage +monopoly-select-property-unmortgage = Select a property to unmortgage +monopoly-select-property-build = Select a property to build on +monopoly-select-property-sell = Select a property to sell from +monopoly-select-trade-offer = Select a trade offer +monopoly-enter-trade-cash = Enter the cash amount for this trade. For property swaps, use a positive amount if you pay the other player, a negative amount if they pay you, or 0. + +# Validation +monopoly-player-bankrupt-disabled = You are bankrupt. +monopoly-auction-active = Resolve the active auction first. +monopoly-resolve-property-first = Resolve the pending property decision first. +monopoly-debt-pending = Resolve the pending debt first. +monopoly-roll-not-available = Rolling is not available right now. +monopoly-roll-first = Roll first. +monopoly-no-property-to-buy = There is no property to buy right now. +monopoly-no-property-to-auction = There is no property to auction right now. +monopoly-no-debt = There is no debt to pay. +monopoly-no-auction-active = There is no auction in progress. +monopoly-auction-already-passed = You have already passed in this auction. +monopoly-not-enough-cash = You do not have enough cash. +monopoly-not-in-jail = You are not in jail. +monopoly-no-jail-card = You do not have a Get Out of Jail Free card. +monopoly-no-mortgage-options = You do not have any properties available to mortgage. +monopoly-no-unmortgage-options = You do not have any properties available to unmortgage. +monopoly-no-build-options = You do not have any properties available to build on. +monopoly-no-sell-options = You do not have any buildings available to sell. +monopoly-no-trade-options = You do not have any valid trades to offer. +monopoly-trade-pending = Resolve the pending trade first. +monopoly-no-trade-pending = There is no trade pending for you. +monopoly-trade-no-longer-valid = That trade is no longer valid. +monopoly-invalid-trade-amount = That trade amount is not a valid number. +monopoly-invalid-bid = That bid is not a valid number. +monopoly-bid-out-of-range = Bid at least { $minimum } and no more than your cash ({ $cash }). + +# Board events +monopoly-roll-result = { $player } rolled { $die1 } + { $die2 } = { $total }. +monopoly-landed = { $player } landed on { $space }. +monopoly-moved-to = { $player } moved to { $space }. +monopoly-pass-go = { $player } passed GO and collected { $amount }. +monopoly-collected = { $player } collected { $amount } for { $reason }. +monopoly-paid-bank = { $player } paid { $amount } to the bank for { $reason }. +monopoly-paid-player = { $player } paid { $amount } to { $target } for { $reason }. +monopoly-free-parking = { $player } is resting on Free Parking. +monopoly-just-visiting = { $player } is just visiting jail. +monopoly-go-to-jail = { $player } goes directly to jail. +monopoly-landed-own-property = { $player } landed on their own { $property }. + +# Properties and rent +monopoly-property-available = { $property } is unowned and costs { $price }. +monopoly-property-bought = { $player } bought { $property } for { $price }. +monopoly-completed-set = { $player } completed the { $group } set. +monopoly-mortgaged-no-rent = { $player } landed on mortgaged { $property }; no rent is due. +monopoly-property-mortgaged = { $player } mortgaged { $property } for { $amount }. +monopoly-property-unmortgaged = { $player } unmortgaged { $property } for { $amount }. +monopoly-building-built = { $player } built a { $building } on { $property } for { $amount }. Level: { $level }. +monopoly-building-sold = { $player } sold a building on { $property } for { $amount }. Level: { $level }. + +# Trades +monopoly-trade-offered = { $player } offered { $target } a trade: { $summary }. +monopoly-trade-accepted = { $target } accepted { $player }'s trade: { $summary }. +monopoly-trade-declined = { $target } declined { $player }'s trade: { $summary }. +monopoly-mortgage-transfer-interest-paid = { $player } paid { $amount } mortgage transfer interest. + +# Auctions +monopoly-auction-started = Auction started for { $property }. Minimum bid: { $amount }. +monopoly-auction-bid-placed = { $player } bid { $amount } for { $property }. +monopoly-auction-pass-event = { $player } passed on { $property }. +monopoly-auction-no-bids = No bids for { $property }. It remains unsold. +monopoly-auction-won = { $player } won { $property } for { $amount }. + +# Jail and doubles +monopoly-roll-again = { $player } rolled doubles and gets another roll. +monopoly-three-doubles-jail = { $player } rolled doubles three times and is sent to jail. +monopoly-jail-roll-doubles = { $player } rolled doubles ({ $die1 } and { $die2 }) and leaves jail. +monopoly-jail-roll-failed = { $player } rolled { $die1 } and { $die2 } in jail. Attempt { $attempts }. +monopoly-bail-paid = { $player } paid { $amount } bail. +monopoly-jail-card-used = { $player } used a Get Out of Jail Free card. + +# Cards and debt +monopoly-card-drawn = { $player } drew { $deck }: { $text } +monopoly-debt-created = { $player } owes { $amount } to { $target } for { $reason }. +monopoly-debt-can-pay = { $player } has enough cash to pay the pending debt. +monopoly-player-bankrupt = { $player } is bankrupt. Creditor: { $creditor }. +monopoly-winner = { $player } wins Monopoly with net worth { $value }. diff --git a/server/locales/fa/monopoly.ftl b/server/locales/fa/monopoly.ftl new file mode 100644 index 00000000..330c8df1 --- /dev/null +++ b/server/locales/fa/monopoly.ftl @@ -0,0 +1,116 @@ +# Monopoly game messages + +game-name-monopoly = Monopoly + +monopoly-started = Monopoly started on { $board }. Each player begins with { $cash }. +monopoly-turn = { $player }'s turn. +monopoly-in-jail-turn = { $player } is in jail. Failed roll attempts: { $turns }. + +# Actions +monopoly-roll-dice = Roll dice +monopoly-buy-property = Buy property +monopoly-auction-property = Auction property +monopoly-end-turn = End turn +monopoly-auction-bid = Place auction bid +monopoly-auction-pass = Pass in auction +monopoly-mortgage-property = Mortgage property +monopoly-unmortgage-property = Unmortgage property +monopoly-build-house = Build house or hotel +monopoly-sell-house = Sell house or hotel +monopoly-pay-bail = Pay bail +monopoly-use-jail-card = Use Get Out of Jail Free card +monopoly-pay-debt = Pay debt +monopoly-declare-bankruptcy = Declare bankruptcy +monopoly-offer-trade = Offer trade +monopoly-submit-trade-amount = Set trade amount +monopoly-accept-trade = Accept trade +monopoly-decline-trade = Decline trade +monopoly-check-assets = Check assets +monopoly-check-board = Check board + +# Prompts +monopoly-enter-auction-bid = Enter auction bid amount +monopoly-select-property-mortgage = Select a property to mortgage +monopoly-select-property-unmortgage = Select a property to unmortgage +monopoly-select-property-build = Select a property to build on +monopoly-select-property-sell = Select a property to sell from +monopoly-select-trade-offer = Select a trade offer +monopoly-enter-trade-cash = Enter the cash amount for this trade. For property swaps, use a positive amount if you pay the other player, a negative amount if they pay you, or 0. + +# Validation +monopoly-player-bankrupt-disabled = You are bankrupt. +monopoly-auction-active = Resolve the active auction first. +monopoly-resolve-property-first = Resolve the pending property decision first. +monopoly-debt-pending = Resolve the pending debt first. +monopoly-roll-not-available = Rolling is not available right now. +monopoly-roll-first = Roll first. +monopoly-no-property-to-buy = There is no property to buy right now. +monopoly-no-property-to-auction = There is no property to auction right now. +monopoly-no-debt = There is no debt to pay. +monopoly-no-auction-active = There is no auction in progress. +monopoly-auction-already-passed = You have already passed in this auction. +monopoly-not-enough-cash = You do not have enough cash. +monopoly-not-in-jail = You are not in jail. +monopoly-no-jail-card = You do not have a Get Out of Jail Free card. +monopoly-no-mortgage-options = You do not have any properties available to mortgage. +monopoly-no-unmortgage-options = You do not have any properties available to unmortgage. +monopoly-no-build-options = You do not have any properties available to build on. +monopoly-no-sell-options = You do not have any buildings available to sell. +monopoly-no-trade-options = You do not have any valid trades to offer. +monopoly-trade-pending = Resolve the pending trade first. +monopoly-no-trade-pending = There is no trade pending for you. +monopoly-trade-no-longer-valid = That trade is no longer valid. +monopoly-invalid-trade-amount = That trade amount is not a valid number. +monopoly-invalid-bid = That bid is not a valid number. +monopoly-bid-out-of-range = Bid at least { $minimum } and no more than your cash ({ $cash }). + +# Board events +monopoly-roll-result = { $player } rolled { $die1 } + { $die2 } = { $total }. +monopoly-landed = { $player } landed on { $space }. +monopoly-moved-to = { $player } moved to { $space }. +monopoly-pass-go = { $player } passed GO and collected { $amount }. +monopoly-collected = { $player } collected { $amount } for { $reason }. +monopoly-paid-bank = { $player } paid { $amount } to the bank for { $reason }. +monopoly-paid-player = { $player } paid { $amount } to { $target } for { $reason }. +monopoly-free-parking = { $player } is resting on Free Parking. +monopoly-just-visiting = { $player } is just visiting jail. +monopoly-go-to-jail = { $player } goes directly to jail. +monopoly-landed-own-property = { $player } landed on their own { $property }. + +# Properties and rent +monopoly-property-available = { $property } is unowned and costs { $price }. +monopoly-property-bought = { $player } bought { $property } for { $price }. +monopoly-completed-set = { $player } completed the { $group } set. +monopoly-mortgaged-no-rent = { $player } landed on mortgaged { $property }; no rent is due. +monopoly-property-mortgaged = { $player } mortgaged { $property } for { $amount }. +monopoly-property-unmortgaged = { $player } unmortgaged { $property } for { $amount }. +monopoly-building-built = { $player } built a { $building } on { $property } for { $amount }. Level: { $level }. +monopoly-building-sold = { $player } sold a building on { $property } for { $amount }. Level: { $level }. + +# Trades +monopoly-trade-offered = { $player } offered { $target } a trade: { $summary }. +monopoly-trade-accepted = { $target } accepted { $player }'s trade: { $summary }. +monopoly-trade-declined = { $target } declined { $player }'s trade: { $summary }. +monopoly-mortgage-transfer-interest-paid = { $player } paid { $amount } mortgage transfer interest. + +# Auctions +monopoly-auction-started = Auction started for { $property }. Minimum bid: { $amount }. +monopoly-auction-bid-placed = { $player } bid { $amount } for { $property }. +monopoly-auction-pass-event = { $player } passed on { $property }. +monopoly-auction-no-bids = No bids for { $property }. It remains unsold. +monopoly-auction-won = { $player } won { $property } for { $amount }. + +# Jail and doubles +monopoly-roll-again = { $player } rolled doubles and gets another roll. +monopoly-three-doubles-jail = { $player } rolled doubles three times and is sent to jail. +monopoly-jail-roll-doubles = { $player } rolled doubles ({ $die1 } and { $die2 }) and leaves jail. +monopoly-jail-roll-failed = { $player } rolled { $die1 } and { $die2 } in jail. Attempt { $attempts }. +monopoly-bail-paid = { $player } paid { $amount } bail. +monopoly-jail-card-used = { $player } used a Get Out of Jail Free card. + +# Cards and debt +monopoly-card-drawn = { $player } drew { $deck }: { $text } +monopoly-debt-created = { $player } owes { $amount } to { $target } for { $reason }. +monopoly-debt-can-pay = { $player } has enough cash to pay the pending debt. +monopoly-player-bankrupt = { $player } is bankrupt. Creditor: { $creditor }. +monopoly-winner = { $player } wins Monopoly with net worth { $value }. diff --git a/server/locales/fr/monopoly.ftl b/server/locales/fr/monopoly.ftl new file mode 100644 index 00000000..330c8df1 --- /dev/null +++ b/server/locales/fr/monopoly.ftl @@ -0,0 +1,116 @@ +# Monopoly game messages + +game-name-monopoly = Monopoly + +monopoly-started = Monopoly started on { $board }. Each player begins with { $cash }. +monopoly-turn = { $player }'s turn. +monopoly-in-jail-turn = { $player } is in jail. Failed roll attempts: { $turns }. + +# Actions +monopoly-roll-dice = Roll dice +monopoly-buy-property = Buy property +monopoly-auction-property = Auction property +monopoly-end-turn = End turn +monopoly-auction-bid = Place auction bid +monopoly-auction-pass = Pass in auction +monopoly-mortgage-property = Mortgage property +monopoly-unmortgage-property = Unmortgage property +monopoly-build-house = Build house or hotel +monopoly-sell-house = Sell house or hotel +monopoly-pay-bail = Pay bail +monopoly-use-jail-card = Use Get Out of Jail Free card +monopoly-pay-debt = Pay debt +monopoly-declare-bankruptcy = Declare bankruptcy +monopoly-offer-trade = Offer trade +monopoly-submit-trade-amount = Set trade amount +monopoly-accept-trade = Accept trade +monopoly-decline-trade = Decline trade +monopoly-check-assets = Check assets +monopoly-check-board = Check board + +# Prompts +monopoly-enter-auction-bid = Enter auction bid amount +monopoly-select-property-mortgage = Select a property to mortgage +monopoly-select-property-unmortgage = Select a property to unmortgage +monopoly-select-property-build = Select a property to build on +monopoly-select-property-sell = Select a property to sell from +monopoly-select-trade-offer = Select a trade offer +monopoly-enter-trade-cash = Enter the cash amount for this trade. For property swaps, use a positive amount if you pay the other player, a negative amount if they pay you, or 0. + +# Validation +monopoly-player-bankrupt-disabled = You are bankrupt. +monopoly-auction-active = Resolve the active auction first. +monopoly-resolve-property-first = Resolve the pending property decision first. +monopoly-debt-pending = Resolve the pending debt first. +monopoly-roll-not-available = Rolling is not available right now. +monopoly-roll-first = Roll first. +monopoly-no-property-to-buy = There is no property to buy right now. +monopoly-no-property-to-auction = There is no property to auction right now. +monopoly-no-debt = There is no debt to pay. +monopoly-no-auction-active = There is no auction in progress. +monopoly-auction-already-passed = You have already passed in this auction. +monopoly-not-enough-cash = You do not have enough cash. +monopoly-not-in-jail = You are not in jail. +monopoly-no-jail-card = You do not have a Get Out of Jail Free card. +monopoly-no-mortgage-options = You do not have any properties available to mortgage. +monopoly-no-unmortgage-options = You do not have any properties available to unmortgage. +monopoly-no-build-options = You do not have any properties available to build on. +monopoly-no-sell-options = You do not have any buildings available to sell. +monopoly-no-trade-options = You do not have any valid trades to offer. +monopoly-trade-pending = Resolve the pending trade first. +monopoly-no-trade-pending = There is no trade pending for you. +monopoly-trade-no-longer-valid = That trade is no longer valid. +monopoly-invalid-trade-amount = That trade amount is not a valid number. +monopoly-invalid-bid = That bid is not a valid number. +monopoly-bid-out-of-range = Bid at least { $minimum } and no more than your cash ({ $cash }). + +# Board events +monopoly-roll-result = { $player } rolled { $die1 } + { $die2 } = { $total }. +monopoly-landed = { $player } landed on { $space }. +monopoly-moved-to = { $player } moved to { $space }. +monopoly-pass-go = { $player } passed GO and collected { $amount }. +monopoly-collected = { $player } collected { $amount } for { $reason }. +monopoly-paid-bank = { $player } paid { $amount } to the bank for { $reason }. +monopoly-paid-player = { $player } paid { $amount } to { $target } for { $reason }. +monopoly-free-parking = { $player } is resting on Free Parking. +monopoly-just-visiting = { $player } is just visiting jail. +monopoly-go-to-jail = { $player } goes directly to jail. +monopoly-landed-own-property = { $player } landed on their own { $property }. + +# Properties and rent +monopoly-property-available = { $property } is unowned and costs { $price }. +monopoly-property-bought = { $player } bought { $property } for { $price }. +monopoly-completed-set = { $player } completed the { $group } set. +monopoly-mortgaged-no-rent = { $player } landed on mortgaged { $property }; no rent is due. +monopoly-property-mortgaged = { $player } mortgaged { $property } for { $amount }. +monopoly-property-unmortgaged = { $player } unmortgaged { $property } for { $amount }. +monopoly-building-built = { $player } built a { $building } on { $property } for { $amount }. Level: { $level }. +monopoly-building-sold = { $player } sold a building on { $property } for { $amount }. Level: { $level }. + +# Trades +monopoly-trade-offered = { $player } offered { $target } a trade: { $summary }. +monopoly-trade-accepted = { $target } accepted { $player }'s trade: { $summary }. +monopoly-trade-declined = { $target } declined { $player }'s trade: { $summary }. +monopoly-mortgage-transfer-interest-paid = { $player } paid { $amount } mortgage transfer interest. + +# Auctions +monopoly-auction-started = Auction started for { $property }. Minimum bid: { $amount }. +monopoly-auction-bid-placed = { $player } bid { $amount } for { $property }. +monopoly-auction-pass-event = { $player } passed on { $property }. +monopoly-auction-no-bids = No bids for { $property }. It remains unsold. +monopoly-auction-won = { $player } won { $property } for { $amount }. + +# Jail and doubles +monopoly-roll-again = { $player } rolled doubles and gets another roll. +monopoly-three-doubles-jail = { $player } rolled doubles three times and is sent to jail. +monopoly-jail-roll-doubles = { $player } rolled doubles ({ $die1 } and { $die2 }) and leaves jail. +monopoly-jail-roll-failed = { $player } rolled { $die1 } and { $die2 } in jail. Attempt { $attempts }. +monopoly-bail-paid = { $player } paid { $amount } bail. +monopoly-jail-card-used = { $player } used a Get Out of Jail Free card. + +# Cards and debt +monopoly-card-drawn = { $player } drew { $deck }: { $text } +monopoly-debt-created = { $player } owes { $amount } to { $target } for { $reason }. +monopoly-debt-can-pay = { $player } has enough cash to pay the pending debt. +monopoly-player-bankrupt = { $player } is bankrupt. Creditor: { $creditor }. +monopoly-winner = { $player } wins Monopoly with net worth { $value }. diff --git a/server/locales/hi/monopoly.ftl b/server/locales/hi/monopoly.ftl new file mode 100644 index 00000000..330c8df1 --- /dev/null +++ b/server/locales/hi/monopoly.ftl @@ -0,0 +1,116 @@ +# Monopoly game messages + +game-name-monopoly = Monopoly + +monopoly-started = Monopoly started on { $board }. Each player begins with { $cash }. +monopoly-turn = { $player }'s turn. +monopoly-in-jail-turn = { $player } is in jail. Failed roll attempts: { $turns }. + +# Actions +monopoly-roll-dice = Roll dice +monopoly-buy-property = Buy property +monopoly-auction-property = Auction property +monopoly-end-turn = End turn +monopoly-auction-bid = Place auction bid +monopoly-auction-pass = Pass in auction +monopoly-mortgage-property = Mortgage property +monopoly-unmortgage-property = Unmortgage property +monopoly-build-house = Build house or hotel +monopoly-sell-house = Sell house or hotel +monopoly-pay-bail = Pay bail +monopoly-use-jail-card = Use Get Out of Jail Free card +monopoly-pay-debt = Pay debt +monopoly-declare-bankruptcy = Declare bankruptcy +monopoly-offer-trade = Offer trade +monopoly-submit-trade-amount = Set trade amount +monopoly-accept-trade = Accept trade +monopoly-decline-trade = Decline trade +monopoly-check-assets = Check assets +monopoly-check-board = Check board + +# Prompts +monopoly-enter-auction-bid = Enter auction bid amount +monopoly-select-property-mortgage = Select a property to mortgage +monopoly-select-property-unmortgage = Select a property to unmortgage +monopoly-select-property-build = Select a property to build on +monopoly-select-property-sell = Select a property to sell from +monopoly-select-trade-offer = Select a trade offer +monopoly-enter-trade-cash = Enter the cash amount for this trade. For property swaps, use a positive amount if you pay the other player, a negative amount if they pay you, or 0. + +# Validation +monopoly-player-bankrupt-disabled = You are bankrupt. +monopoly-auction-active = Resolve the active auction first. +monopoly-resolve-property-first = Resolve the pending property decision first. +monopoly-debt-pending = Resolve the pending debt first. +monopoly-roll-not-available = Rolling is not available right now. +monopoly-roll-first = Roll first. +monopoly-no-property-to-buy = There is no property to buy right now. +monopoly-no-property-to-auction = There is no property to auction right now. +monopoly-no-debt = There is no debt to pay. +monopoly-no-auction-active = There is no auction in progress. +monopoly-auction-already-passed = You have already passed in this auction. +monopoly-not-enough-cash = You do not have enough cash. +monopoly-not-in-jail = You are not in jail. +monopoly-no-jail-card = You do not have a Get Out of Jail Free card. +monopoly-no-mortgage-options = You do not have any properties available to mortgage. +monopoly-no-unmortgage-options = You do not have any properties available to unmortgage. +monopoly-no-build-options = You do not have any properties available to build on. +monopoly-no-sell-options = You do not have any buildings available to sell. +monopoly-no-trade-options = You do not have any valid trades to offer. +monopoly-trade-pending = Resolve the pending trade first. +monopoly-no-trade-pending = There is no trade pending for you. +monopoly-trade-no-longer-valid = That trade is no longer valid. +monopoly-invalid-trade-amount = That trade amount is not a valid number. +monopoly-invalid-bid = That bid is not a valid number. +monopoly-bid-out-of-range = Bid at least { $minimum } and no more than your cash ({ $cash }). + +# Board events +monopoly-roll-result = { $player } rolled { $die1 } + { $die2 } = { $total }. +monopoly-landed = { $player } landed on { $space }. +monopoly-moved-to = { $player } moved to { $space }. +monopoly-pass-go = { $player } passed GO and collected { $amount }. +monopoly-collected = { $player } collected { $amount } for { $reason }. +monopoly-paid-bank = { $player } paid { $amount } to the bank for { $reason }. +monopoly-paid-player = { $player } paid { $amount } to { $target } for { $reason }. +monopoly-free-parking = { $player } is resting on Free Parking. +monopoly-just-visiting = { $player } is just visiting jail. +monopoly-go-to-jail = { $player } goes directly to jail. +monopoly-landed-own-property = { $player } landed on their own { $property }. + +# Properties and rent +monopoly-property-available = { $property } is unowned and costs { $price }. +monopoly-property-bought = { $player } bought { $property } for { $price }. +monopoly-completed-set = { $player } completed the { $group } set. +monopoly-mortgaged-no-rent = { $player } landed on mortgaged { $property }; no rent is due. +monopoly-property-mortgaged = { $player } mortgaged { $property } for { $amount }. +monopoly-property-unmortgaged = { $player } unmortgaged { $property } for { $amount }. +monopoly-building-built = { $player } built a { $building } on { $property } for { $amount }. Level: { $level }. +monopoly-building-sold = { $player } sold a building on { $property } for { $amount }. Level: { $level }. + +# Trades +monopoly-trade-offered = { $player } offered { $target } a trade: { $summary }. +monopoly-trade-accepted = { $target } accepted { $player }'s trade: { $summary }. +monopoly-trade-declined = { $target } declined { $player }'s trade: { $summary }. +monopoly-mortgage-transfer-interest-paid = { $player } paid { $amount } mortgage transfer interest. + +# Auctions +monopoly-auction-started = Auction started for { $property }. Minimum bid: { $amount }. +monopoly-auction-bid-placed = { $player } bid { $amount } for { $property }. +monopoly-auction-pass-event = { $player } passed on { $property }. +monopoly-auction-no-bids = No bids for { $property }. It remains unsold. +monopoly-auction-won = { $player } won { $property } for { $amount }. + +# Jail and doubles +monopoly-roll-again = { $player } rolled doubles and gets another roll. +monopoly-three-doubles-jail = { $player } rolled doubles three times and is sent to jail. +monopoly-jail-roll-doubles = { $player } rolled doubles ({ $die1 } and { $die2 }) and leaves jail. +monopoly-jail-roll-failed = { $player } rolled { $die1 } and { $die2 } in jail. Attempt { $attempts }. +monopoly-bail-paid = { $player } paid { $amount } bail. +monopoly-jail-card-used = { $player } used a Get Out of Jail Free card. + +# Cards and debt +monopoly-card-drawn = { $player } drew { $deck }: { $text } +monopoly-debt-created = { $player } owes { $amount } to { $target } for { $reason }. +monopoly-debt-can-pay = { $player } has enough cash to pay the pending debt. +monopoly-player-bankrupt = { $player } is bankrupt. Creditor: { $creditor }. +monopoly-winner = { $player } wins Monopoly with net worth { $value }. diff --git a/server/locales/hr/monopoly.ftl b/server/locales/hr/monopoly.ftl new file mode 100644 index 00000000..330c8df1 --- /dev/null +++ b/server/locales/hr/monopoly.ftl @@ -0,0 +1,116 @@ +# Monopoly game messages + +game-name-monopoly = Monopoly + +monopoly-started = Monopoly started on { $board }. Each player begins with { $cash }. +monopoly-turn = { $player }'s turn. +monopoly-in-jail-turn = { $player } is in jail. Failed roll attempts: { $turns }. + +# Actions +monopoly-roll-dice = Roll dice +monopoly-buy-property = Buy property +monopoly-auction-property = Auction property +monopoly-end-turn = End turn +monopoly-auction-bid = Place auction bid +monopoly-auction-pass = Pass in auction +monopoly-mortgage-property = Mortgage property +monopoly-unmortgage-property = Unmortgage property +monopoly-build-house = Build house or hotel +monopoly-sell-house = Sell house or hotel +monopoly-pay-bail = Pay bail +monopoly-use-jail-card = Use Get Out of Jail Free card +monopoly-pay-debt = Pay debt +monopoly-declare-bankruptcy = Declare bankruptcy +monopoly-offer-trade = Offer trade +monopoly-submit-trade-amount = Set trade amount +monopoly-accept-trade = Accept trade +monopoly-decline-trade = Decline trade +monopoly-check-assets = Check assets +monopoly-check-board = Check board + +# Prompts +monopoly-enter-auction-bid = Enter auction bid amount +monopoly-select-property-mortgage = Select a property to mortgage +monopoly-select-property-unmortgage = Select a property to unmortgage +monopoly-select-property-build = Select a property to build on +monopoly-select-property-sell = Select a property to sell from +monopoly-select-trade-offer = Select a trade offer +monopoly-enter-trade-cash = Enter the cash amount for this trade. For property swaps, use a positive amount if you pay the other player, a negative amount if they pay you, or 0. + +# Validation +monopoly-player-bankrupt-disabled = You are bankrupt. +monopoly-auction-active = Resolve the active auction first. +monopoly-resolve-property-first = Resolve the pending property decision first. +monopoly-debt-pending = Resolve the pending debt first. +monopoly-roll-not-available = Rolling is not available right now. +monopoly-roll-first = Roll first. +monopoly-no-property-to-buy = There is no property to buy right now. +monopoly-no-property-to-auction = There is no property to auction right now. +monopoly-no-debt = There is no debt to pay. +monopoly-no-auction-active = There is no auction in progress. +monopoly-auction-already-passed = You have already passed in this auction. +monopoly-not-enough-cash = You do not have enough cash. +monopoly-not-in-jail = You are not in jail. +monopoly-no-jail-card = You do not have a Get Out of Jail Free card. +monopoly-no-mortgage-options = You do not have any properties available to mortgage. +monopoly-no-unmortgage-options = You do not have any properties available to unmortgage. +monopoly-no-build-options = You do not have any properties available to build on. +monopoly-no-sell-options = You do not have any buildings available to sell. +monopoly-no-trade-options = You do not have any valid trades to offer. +monopoly-trade-pending = Resolve the pending trade first. +monopoly-no-trade-pending = There is no trade pending for you. +monopoly-trade-no-longer-valid = That trade is no longer valid. +monopoly-invalid-trade-amount = That trade amount is not a valid number. +monopoly-invalid-bid = That bid is not a valid number. +monopoly-bid-out-of-range = Bid at least { $minimum } and no more than your cash ({ $cash }). + +# Board events +monopoly-roll-result = { $player } rolled { $die1 } + { $die2 } = { $total }. +monopoly-landed = { $player } landed on { $space }. +monopoly-moved-to = { $player } moved to { $space }. +monopoly-pass-go = { $player } passed GO and collected { $amount }. +monopoly-collected = { $player } collected { $amount } for { $reason }. +monopoly-paid-bank = { $player } paid { $amount } to the bank for { $reason }. +monopoly-paid-player = { $player } paid { $amount } to { $target } for { $reason }. +monopoly-free-parking = { $player } is resting on Free Parking. +monopoly-just-visiting = { $player } is just visiting jail. +monopoly-go-to-jail = { $player } goes directly to jail. +monopoly-landed-own-property = { $player } landed on their own { $property }. + +# Properties and rent +monopoly-property-available = { $property } is unowned and costs { $price }. +monopoly-property-bought = { $player } bought { $property } for { $price }. +monopoly-completed-set = { $player } completed the { $group } set. +monopoly-mortgaged-no-rent = { $player } landed on mortgaged { $property }; no rent is due. +monopoly-property-mortgaged = { $player } mortgaged { $property } for { $amount }. +monopoly-property-unmortgaged = { $player } unmortgaged { $property } for { $amount }. +monopoly-building-built = { $player } built a { $building } on { $property } for { $amount }. Level: { $level }. +monopoly-building-sold = { $player } sold a building on { $property } for { $amount }. Level: { $level }. + +# Trades +monopoly-trade-offered = { $player } offered { $target } a trade: { $summary }. +monopoly-trade-accepted = { $target } accepted { $player }'s trade: { $summary }. +monopoly-trade-declined = { $target } declined { $player }'s trade: { $summary }. +monopoly-mortgage-transfer-interest-paid = { $player } paid { $amount } mortgage transfer interest. + +# Auctions +monopoly-auction-started = Auction started for { $property }. Minimum bid: { $amount }. +monopoly-auction-bid-placed = { $player } bid { $amount } for { $property }. +monopoly-auction-pass-event = { $player } passed on { $property }. +monopoly-auction-no-bids = No bids for { $property }. It remains unsold. +monopoly-auction-won = { $player } won { $property } for { $amount }. + +# Jail and doubles +monopoly-roll-again = { $player } rolled doubles and gets another roll. +monopoly-three-doubles-jail = { $player } rolled doubles three times and is sent to jail. +monopoly-jail-roll-doubles = { $player } rolled doubles ({ $die1 } and { $die2 }) and leaves jail. +monopoly-jail-roll-failed = { $player } rolled { $die1 } and { $die2 } in jail. Attempt { $attempts }. +monopoly-bail-paid = { $player } paid { $amount } bail. +monopoly-jail-card-used = { $player } used a Get Out of Jail Free card. + +# Cards and debt +monopoly-card-drawn = { $player } drew { $deck }: { $text } +monopoly-debt-created = { $player } owes { $amount } to { $target } for { $reason }. +monopoly-debt-can-pay = { $player } has enough cash to pay the pending debt. +monopoly-player-bankrupt = { $player } is bankrupt. Creditor: { $creditor }. +monopoly-winner = { $player } wins Monopoly with net worth { $value }. diff --git a/server/locales/hu/monopoly.ftl b/server/locales/hu/monopoly.ftl new file mode 100644 index 00000000..330c8df1 --- /dev/null +++ b/server/locales/hu/monopoly.ftl @@ -0,0 +1,116 @@ +# Monopoly game messages + +game-name-monopoly = Monopoly + +monopoly-started = Monopoly started on { $board }. Each player begins with { $cash }. +monopoly-turn = { $player }'s turn. +monopoly-in-jail-turn = { $player } is in jail. Failed roll attempts: { $turns }. + +# Actions +monopoly-roll-dice = Roll dice +monopoly-buy-property = Buy property +monopoly-auction-property = Auction property +monopoly-end-turn = End turn +monopoly-auction-bid = Place auction bid +monopoly-auction-pass = Pass in auction +monopoly-mortgage-property = Mortgage property +monopoly-unmortgage-property = Unmortgage property +monopoly-build-house = Build house or hotel +monopoly-sell-house = Sell house or hotel +monopoly-pay-bail = Pay bail +monopoly-use-jail-card = Use Get Out of Jail Free card +monopoly-pay-debt = Pay debt +monopoly-declare-bankruptcy = Declare bankruptcy +monopoly-offer-trade = Offer trade +monopoly-submit-trade-amount = Set trade amount +monopoly-accept-trade = Accept trade +monopoly-decline-trade = Decline trade +monopoly-check-assets = Check assets +monopoly-check-board = Check board + +# Prompts +monopoly-enter-auction-bid = Enter auction bid amount +monopoly-select-property-mortgage = Select a property to mortgage +monopoly-select-property-unmortgage = Select a property to unmortgage +monopoly-select-property-build = Select a property to build on +monopoly-select-property-sell = Select a property to sell from +monopoly-select-trade-offer = Select a trade offer +monopoly-enter-trade-cash = Enter the cash amount for this trade. For property swaps, use a positive amount if you pay the other player, a negative amount if they pay you, or 0. + +# Validation +monopoly-player-bankrupt-disabled = You are bankrupt. +monopoly-auction-active = Resolve the active auction first. +monopoly-resolve-property-first = Resolve the pending property decision first. +monopoly-debt-pending = Resolve the pending debt first. +monopoly-roll-not-available = Rolling is not available right now. +monopoly-roll-first = Roll first. +monopoly-no-property-to-buy = There is no property to buy right now. +monopoly-no-property-to-auction = There is no property to auction right now. +monopoly-no-debt = There is no debt to pay. +monopoly-no-auction-active = There is no auction in progress. +monopoly-auction-already-passed = You have already passed in this auction. +monopoly-not-enough-cash = You do not have enough cash. +monopoly-not-in-jail = You are not in jail. +monopoly-no-jail-card = You do not have a Get Out of Jail Free card. +monopoly-no-mortgage-options = You do not have any properties available to mortgage. +monopoly-no-unmortgage-options = You do not have any properties available to unmortgage. +monopoly-no-build-options = You do not have any properties available to build on. +monopoly-no-sell-options = You do not have any buildings available to sell. +monopoly-no-trade-options = You do not have any valid trades to offer. +monopoly-trade-pending = Resolve the pending trade first. +monopoly-no-trade-pending = There is no trade pending for you. +monopoly-trade-no-longer-valid = That trade is no longer valid. +monopoly-invalid-trade-amount = That trade amount is not a valid number. +monopoly-invalid-bid = That bid is not a valid number. +monopoly-bid-out-of-range = Bid at least { $minimum } and no more than your cash ({ $cash }). + +# Board events +monopoly-roll-result = { $player } rolled { $die1 } + { $die2 } = { $total }. +monopoly-landed = { $player } landed on { $space }. +monopoly-moved-to = { $player } moved to { $space }. +monopoly-pass-go = { $player } passed GO and collected { $amount }. +monopoly-collected = { $player } collected { $amount } for { $reason }. +monopoly-paid-bank = { $player } paid { $amount } to the bank for { $reason }. +monopoly-paid-player = { $player } paid { $amount } to { $target } for { $reason }. +monopoly-free-parking = { $player } is resting on Free Parking. +monopoly-just-visiting = { $player } is just visiting jail. +monopoly-go-to-jail = { $player } goes directly to jail. +monopoly-landed-own-property = { $player } landed on their own { $property }. + +# Properties and rent +monopoly-property-available = { $property } is unowned and costs { $price }. +monopoly-property-bought = { $player } bought { $property } for { $price }. +monopoly-completed-set = { $player } completed the { $group } set. +monopoly-mortgaged-no-rent = { $player } landed on mortgaged { $property }; no rent is due. +monopoly-property-mortgaged = { $player } mortgaged { $property } for { $amount }. +monopoly-property-unmortgaged = { $player } unmortgaged { $property } for { $amount }. +monopoly-building-built = { $player } built a { $building } on { $property } for { $amount }. Level: { $level }. +monopoly-building-sold = { $player } sold a building on { $property } for { $amount }. Level: { $level }. + +# Trades +monopoly-trade-offered = { $player } offered { $target } a trade: { $summary }. +monopoly-trade-accepted = { $target } accepted { $player }'s trade: { $summary }. +monopoly-trade-declined = { $target } declined { $player }'s trade: { $summary }. +monopoly-mortgage-transfer-interest-paid = { $player } paid { $amount } mortgage transfer interest. + +# Auctions +monopoly-auction-started = Auction started for { $property }. Minimum bid: { $amount }. +monopoly-auction-bid-placed = { $player } bid { $amount } for { $property }. +monopoly-auction-pass-event = { $player } passed on { $property }. +monopoly-auction-no-bids = No bids for { $property }. It remains unsold. +monopoly-auction-won = { $player } won { $property } for { $amount }. + +# Jail and doubles +monopoly-roll-again = { $player } rolled doubles and gets another roll. +monopoly-three-doubles-jail = { $player } rolled doubles three times and is sent to jail. +monopoly-jail-roll-doubles = { $player } rolled doubles ({ $die1 } and { $die2 }) and leaves jail. +monopoly-jail-roll-failed = { $player } rolled { $die1 } and { $die2 } in jail. Attempt { $attempts }. +monopoly-bail-paid = { $player } paid { $amount } bail. +monopoly-jail-card-used = { $player } used a Get Out of Jail Free card. + +# Cards and debt +monopoly-card-drawn = { $player } drew { $deck }: { $text } +monopoly-debt-created = { $player } owes { $amount } to { $target } for { $reason }. +monopoly-debt-can-pay = { $player } has enough cash to pay the pending debt. +monopoly-player-bankrupt = { $player } is bankrupt. Creditor: { $creditor }. +monopoly-winner = { $player } wins Monopoly with net worth { $value }. diff --git a/server/locales/id/monopoly.ftl b/server/locales/id/monopoly.ftl new file mode 100644 index 00000000..330c8df1 --- /dev/null +++ b/server/locales/id/monopoly.ftl @@ -0,0 +1,116 @@ +# Monopoly game messages + +game-name-monopoly = Monopoly + +monopoly-started = Monopoly started on { $board }. Each player begins with { $cash }. +monopoly-turn = { $player }'s turn. +monopoly-in-jail-turn = { $player } is in jail. Failed roll attempts: { $turns }. + +# Actions +monopoly-roll-dice = Roll dice +monopoly-buy-property = Buy property +monopoly-auction-property = Auction property +monopoly-end-turn = End turn +monopoly-auction-bid = Place auction bid +monopoly-auction-pass = Pass in auction +monopoly-mortgage-property = Mortgage property +monopoly-unmortgage-property = Unmortgage property +monopoly-build-house = Build house or hotel +monopoly-sell-house = Sell house or hotel +monopoly-pay-bail = Pay bail +monopoly-use-jail-card = Use Get Out of Jail Free card +monopoly-pay-debt = Pay debt +monopoly-declare-bankruptcy = Declare bankruptcy +monopoly-offer-trade = Offer trade +monopoly-submit-trade-amount = Set trade amount +monopoly-accept-trade = Accept trade +monopoly-decline-trade = Decline trade +monopoly-check-assets = Check assets +monopoly-check-board = Check board + +# Prompts +monopoly-enter-auction-bid = Enter auction bid amount +monopoly-select-property-mortgage = Select a property to mortgage +monopoly-select-property-unmortgage = Select a property to unmortgage +monopoly-select-property-build = Select a property to build on +monopoly-select-property-sell = Select a property to sell from +monopoly-select-trade-offer = Select a trade offer +monopoly-enter-trade-cash = Enter the cash amount for this trade. For property swaps, use a positive amount if you pay the other player, a negative amount if they pay you, or 0. + +# Validation +monopoly-player-bankrupt-disabled = You are bankrupt. +monopoly-auction-active = Resolve the active auction first. +monopoly-resolve-property-first = Resolve the pending property decision first. +monopoly-debt-pending = Resolve the pending debt first. +monopoly-roll-not-available = Rolling is not available right now. +monopoly-roll-first = Roll first. +monopoly-no-property-to-buy = There is no property to buy right now. +monopoly-no-property-to-auction = There is no property to auction right now. +monopoly-no-debt = There is no debt to pay. +monopoly-no-auction-active = There is no auction in progress. +monopoly-auction-already-passed = You have already passed in this auction. +monopoly-not-enough-cash = You do not have enough cash. +monopoly-not-in-jail = You are not in jail. +monopoly-no-jail-card = You do not have a Get Out of Jail Free card. +monopoly-no-mortgage-options = You do not have any properties available to mortgage. +monopoly-no-unmortgage-options = You do not have any properties available to unmortgage. +monopoly-no-build-options = You do not have any properties available to build on. +monopoly-no-sell-options = You do not have any buildings available to sell. +monopoly-no-trade-options = You do not have any valid trades to offer. +monopoly-trade-pending = Resolve the pending trade first. +monopoly-no-trade-pending = There is no trade pending for you. +monopoly-trade-no-longer-valid = That trade is no longer valid. +monopoly-invalid-trade-amount = That trade amount is not a valid number. +monopoly-invalid-bid = That bid is not a valid number. +monopoly-bid-out-of-range = Bid at least { $minimum } and no more than your cash ({ $cash }). + +# Board events +monopoly-roll-result = { $player } rolled { $die1 } + { $die2 } = { $total }. +monopoly-landed = { $player } landed on { $space }. +monopoly-moved-to = { $player } moved to { $space }. +monopoly-pass-go = { $player } passed GO and collected { $amount }. +monopoly-collected = { $player } collected { $amount } for { $reason }. +monopoly-paid-bank = { $player } paid { $amount } to the bank for { $reason }. +monopoly-paid-player = { $player } paid { $amount } to { $target } for { $reason }. +monopoly-free-parking = { $player } is resting on Free Parking. +monopoly-just-visiting = { $player } is just visiting jail. +monopoly-go-to-jail = { $player } goes directly to jail. +monopoly-landed-own-property = { $player } landed on their own { $property }. + +# Properties and rent +monopoly-property-available = { $property } is unowned and costs { $price }. +monopoly-property-bought = { $player } bought { $property } for { $price }. +monopoly-completed-set = { $player } completed the { $group } set. +monopoly-mortgaged-no-rent = { $player } landed on mortgaged { $property }; no rent is due. +monopoly-property-mortgaged = { $player } mortgaged { $property } for { $amount }. +monopoly-property-unmortgaged = { $player } unmortgaged { $property } for { $amount }. +monopoly-building-built = { $player } built a { $building } on { $property } for { $amount }. Level: { $level }. +monopoly-building-sold = { $player } sold a building on { $property } for { $amount }. Level: { $level }. + +# Trades +monopoly-trade-offered = { $player } offered { $target } a trade: { $summary }. +monopoly-trade-accepted = { $target } accepted { $player }'s trade: { $summary }. +monopoly-trade-declined = { $target } declined { $player }'s trade: { $summary }. +monopoly-mortgage-transfer-interest-paid = { $player } paid { $amount } mortgage transfer interest. + +# Auctions +monopoly-auction-started = Auction started for { $property }. Minimum bid: { $amount }. +monopoly-auction-bid-placed = { $player } bid { $amount } for { $property }. +monopoly-auction-pass-event = { $player } passed on { $property }. +monopoly-auction-no-bids = No bids for { $property }. It remains unsold. +monopoly-auction-won = { $player } won { $property } for { $amount }. + +# Jail and doubles +monopoly-roll-again = { $player } rolled doubles and gets another roll. +monopoly-three-doubles-jail = { $player } rolled doubles three times and is sent to jail. +monopoly-jail-roll-doubles = { $player } rolled doubles ({ $die1 } and { $die2 }) and leaves jail. +monopoly-jail-roll-failed = { $player } rolled { $die1 } and { $die2 } in jail. Attempt { $attempts }. +monopoly-bail-paid = { $player } paid { $amount } bail. +monopoly-jail-card-used = { $player } used a Get Out of Jail Free card. + +# Cards and debt +monopoly-card-drawn = { $player } drew { $deck }: { $text } +monopoly-debt-created = { $player } owes { $amount } to { $target } for { $reason }. +monopoly-debt-can-pay = { $player } has enough cash to pay the pending debt. +monopoly-player-bankrupt = { $player } is bankrupt. Creditor: { $creditor }. +monopoly-winner = { $player } wins Monopoly with net worth { $value }. diff --git a/server/locales/it/monopoly.ftl b/server/locales/it/monopoly.ftl new file mode 100644 index 00000000..330c8df1 --- /dev/null +++ b/server/locales/it/monopoly.ftl @@ -0,0 +1,116 @@ +# Monopoly game messages + +game-name-monopoly = Monopoly + +monopoly-started = Monopoly started on { $board }. Each player begins with { $cash }. +monopoly-turn = { $player }'s turn. +monopoly-in-jail-turn = { $player } is in jail. Failed roll attempts: { $turns }. + +# Actions +monopoly-roll-dice = Roll dice +monopoly-buy-property = Buy property +monopoly-auction-property = Auction property +monopoly-end-turn = End turn +monopoly-auction-bid = Place auction bid +monopoly-auction-pass = Pass in auction +monopoly-mortgage-property = Mortgage property +monopoly-unmortgage-property = Unmortgage property +monopoly-build-house = Build house or hotel +monopoly-sell-house = Sell house or hotel +monopoly-pay-bail = Pay bail +monopoly-use-jail-card = Use Get Out of Jail Free card +monopoly-pay-debt = Pay debt +monopoly-declare-bankruptcy = Declare bankruptcy +monopoly-offer-trade = Offer trade +monopoly-submit-trade-amount = Set trade amount +monopoly-accept-trade = Accept trade +monopoly-decline-trade = Decline trade +monopoly-check-assets = Check assets +monopoly-check-board = Check board + +# Prompts +monopoly-enter-auction-bid = Enter auction bid amount +monopoly-select-property-mortgage = Select a property to mortgage +monopoly-select-property-unmortgage = Select a property to unmortgage +monopoly-select-property-build = Select a property to build on +monopoly-select-property-sell = Select a property to sell from +monopoly-select-trade-offer = Select a trade offer +monopoly-enter-trade-cash = Enter the cash amount for this trade. For property swaps, use a positive amount if you pay the other player, a negative amount if they pay you, or 0. + +# Validation +monopoly-player-bankrupt-disabled = You are bankrupt. +monopoly-auction-active = Resolve the active auction first. +monopoly-resolve-property-first = Resolve the pending property decision first. +monopoly-debt-pending = Resolve the pending debt first. +monopoly-roll-not-available = Rolling is not available right now. +monopoly-roll-first = Roll first. +monopoly-no-property-to-buy = There is no property to buy right now. +monopoly-no-property-to-auction = There is no property to auction right now. +monopoly-no-debt = There is no debt to pay. +monopoly-no-auction-active = There is no auction in progress. +monopoly-auction-already-passed = You have already passed in this auction. +monopoly-not-enough-cash = You do not have enough cash. +monopoly-not-in-jail = You are not in jail. +monopoly-no-jail-card = You do not have a Get Out of Jail Free card. +monopoly-no-mortgage-options = You do not have any properties available to mortgage. +monopoly-no-unmortgage-options = You do not have any properties available to unmortgage. +monopoly-no-build-options = You do not have any properties available to build on. +monopoly-no-sell-options = You do not have any buildings available to sell. +monopoly-no-trade-options = You do not have any valid trades to offer. +monopoly-trade-pending = Resolve the pending trade first. +monopoly-no-trade-pending = There is no trade pending for you. +monopoly-trade-no-longer-valid = That trade is no longer valid. +monopoly-invalid-trade-amount = That trade amount is not a valid number. +monopoly-invalid-bid = That bid is not a valid number. +monopoly-bid-out-of-range = Bid at least { $minimum } and no more than your cash ({ $cash }). + +# Board events +monopoly-roll-result = { $player } rolled { $die1 } + { $die2 } = { $total }. +monopoly-landed = { $player } landed on { $space }. +monopoly-moved-to = { $player } moved to { $space }. +monopoly-pass-go = { $player } passed GO and collected { $amount }. +monopoly-collected = { $player } collected { $amount } for { $reason }. +monopoly-paid-bank = { $player } paid { $amount } to the bank for { $reason }. +monopoly-paid-player = { $player } paid { $amount } to { $target } for { $reason }. +monopoly-free-parking = { $player } is resting on Free Parking. +monopoly-just-visiting = { $player } is just visiting jail. +monopoly-go-to-jail = { $player } goes directly to jail. +monopoly-landed-own-property = { $player } landed on their own { $property }. + +# Properties and rent +monopoly-property-available = { $property } is unowned and costs { $price }. +monopoly-property-bought = { $player } bought { $property } for { $price }. +monopoly-completed-set = { $player } completed the { $group } set. +monopoly-mortgaged-no-rent = { $player } landed on mortgaged { $property }; no rent is due. +monopoly-property-mortgaged = { $player } mortgaged { $property } for { $amount }. +monopoly-property-unmortgaged = { $player } unmortgaged { $property } for { $amount }. +monopoly-building-built = { $player } built a { $building } on { $property } for { $amount }. Level: { $level }. +monopoly-building-sold = { $player } sold a building on { $property } for { $amount }. Level: { $level }. + +# Trades +monopoly-trade-offered = { $player } offered { $target } a trade: { $summary }. +monopoly-trade-accepted = { $target } accepted { $player }'s trade: { $summary }. +monopoly-trade-declined = { $target } declined { $player }'s trade: { $summary }. +monopoly-mortgage-transfer-interest-paid = { $player } paid { $amount } mortgage transfer interest. + +# Auctions +monopoly-auction-started = Auction started for { $property }. Minimum bid: { $amount }. +monopoly-auction-bid-placed = { $player } bid { $amount } for { $property }. +monopoly-auction-pass-event = { $player } passed on { $property }. +monopoly-auction-no-bids = No bids for { $property }. It remains unsold. +monopoly-auction-won = { $player } won { $property } for { $amount }. + +# Jail and doubles +monopoly-roll-again = { $player } rolled doubles and gets another roll. +monopoly-three-doubles-jail = { $player } rolled doubles three times and is sent to jail. +monopoly-jail-roll-doubles = { $player } rolled doubles ({ $die1 } and { $die2 }) and leaves jail. +monopoly-jail-roll-failed = { $player } rolled { $die1 } and { $die2 } in jail. Attempt { $attempts }. +monopoly-bail-paid = { $player } paid { $amount } bail. +monopoly-jail-card-used = { $player } used a Get Out of Jail Free card. + +# Cards and debt +monopoly-card-drawn = { $player } drew { $deck }: { $text } +monopoly-debt-created = { $player } owes { $amount } to { $target } for { $reason }. +monopoly-debt-can-pay = { $player } has enough cash to pay the pending debt. +monopoly-player-bankrupt = { $player } is bankrupt. Creditor: { $creditor }. +monopoly-winner = { $player } wins Monopoly with net worth { $value }. diff --git a/server/locales/ja/monopoly.ftl b/server/locales/ja/monopoly.ftl new file mode 100644 index 00000000..330c8df1 --- /dev/null +++ b/server/locales/ja/monopoly.ftl @@ -0,0 +1,116 @@ +# Monopoly game messages + +game-name-monopoly = Monopoly + +monopoly-started = Monopoly started on { $board }. Each player begins with { $cash }. +monopoly-turn = { $player }'s turn. +monopoly-in-jail-turn = { $player } is in jail. Failed roll attempts: { $turns }. + +# Actions +monopoly-roll-dice = Roll dice +monopoly-buy-property = Buy property +monopoly-auction-property = Auction property +monopoly-end-turn = End turn +monopoly-auction-bid = Place auction bid +monopoly-auction-pass = Pass in auction +monopoly-mortgage-property = Mortgage property +monopoly-unmortgage-property = Unmortgage property +monopoly-build-house = Build house or hotel +monopoly-sell-house = Sell house or hotel +monopoly-pay-bail = Pay bail +monopoly-use-jail-card = Use Get Out of Jail Free card +monopoly-pay-debt = Pay debt +monopoly-declare-bankruptcy = Declare bankruptcy +monopoly-offer-trade = Offer trade +monopoly-submit-trade-amount = Set trade amount +monopoly-accept-trade = Accept trade +monopoly-decline-trade = Decline trade +monopoly-check-assets = Check assets +monopoly-check-board = Check board + +# Prompts +monopoly-enter-auction-bid = Enter auction bid amount +monopoly-select-property-mortgage = Select a property to mortgage +monopoly-select-property-unmortgage = Select a property to unmortgage +monopoly-select-property-build = Select a property to build on +monopoly-select-property-sell = Select a property to sell from +monopoly-select-trade-offer = Select a trade offer +monopoly-enter-trade-cash = Enter the cash amount for this trade. For property swaps, use a positive amount if you pay the other player, a negative amount if they pay you, or 0. + +# Validation +monopoly-player-bankrupt-disabled = You are bankrupt. +monopoly-auction-active = Resolve the active auction first. +monopoly-resolve-property-first = Resolve the pending property decision first. +monopoly-debt-pending = Resolve the pending debt first. +monopoly-roll-not-available = Rolling is not available right now. +monopoly-roll-first = Roll first. +monopoly-no-property-to-buy = There is no property to buy right now. +monopoly-no-property-to-auction = There is no property to auction right now. +monopoly-no-debt = There is no debt to pay. +monopoly-no-auction-active = There is no auction in progress. +monopoly-auction-already-passed = You have already passed in this auction. +monopoly-not-enough-cash = You do not have enough cash. +monopoly-not-in-jail = You are not in jail. +monopoly-no-jail-card = You do not have a Get Out of Jail Free card. +monopoly-no-mortgage-options = You do not have any properties available to mortgage. +monopoly-no-unmortgage-options = You do not have any properties available to unmortgage. +monopoly-no-build-options = You do not have any properties available to build on. +monopoly-no-sell-options = You do not have any buildings available to sell. +monopoly-no-trade-options = You do not have any valid trades to offer. +monopoly-trade-pending = Resolve the pending trade first. +monopoly-no-trade-pending = There is no trade pending for you. +monopoly-trade-no-longer-valid = That trade is no longer valid. +monopoly-invalid-trade-amount = That trade amount is not a valid number. +monopoly-invalid-bid = That bid is not a valid number. +monopoly-bid-out-of-range = Bid at least { $minimum } and no more than your cash ({ $cash }). + +# Board events +monopoly-roll-result = { $player } rolled { $die1 } + { $die2 } = { $total }. +monopoly-landed = { $player } landed on { $space }. +monopoly-moved-to = { $player } moved to { $space }. +monopoly-pass-go = { $player } passed GO and collected { $amount }. +monopoly-collected = { $player } collected { $amount } for { $reason }. +monopoly-paid-bank = { $player } paid { $amount } to the bank for { $reason }. +monopoly-paid-player = { $player } paid { $amount } to { $target } for { $reason }. +monopoly-free-parking = { $player } is resting on Free Parking. +monopoly-just-visiting = { $player } is just visiting jail. +monopoly-go-to-jail = { $player } goes directly to jail. +monopoly-landed-own-property = { $player } landed on their own { $property }. + +# Properties and rent +monopoly-property-available = { $property } is unowned and costs { $price }. +monopoly-property-bought = { $player } bought { $property } for { $price }. +monopoly-completed-set = { $player } completed the { $group } set. +monopoly-mortgaged-no-rent = { $player } landed on mortgaged { $property }; no rent is due. +monopoly-property-mortgaged = { $player } mortgaged { $property } for { $amount }. +monopoly-property-unmortgaged = { $player } unmortgaged { $property } for { $amount }. +monopoly-building-built = { $player } built a { $building } on { $property } for { $amount }. Level: { $level }. +monopoly-building-sold = { $player } sold a building on { $property } for { $amount }. Level: { $level }. + +# Trades +monopoly-trade-offered = { $player } offered { $target } a trade: { $summary }. +monopoly-trade-accepted = { $target } accepted { $player }'s trade: { $summary }. +monopoly-trade-declined = { $target } declined { $player }'s trade: { $summary }. +monopoly-mortgage-transfer-interest-paid = { $player } paid { $amount } mortgage transfer interest. + +# Auctions +monopoly-auction-started = Auction started for { $property }. Minimum bid: { $amount }. +monopoly-auction-bid-placed = { $player } bid { $amount } for { $property }. +monopoly-auction-pass-event = { $player } passed on { $property }. +monopoly-auction-no-bids = No bids for { $property }. It remains unsold. +monopoly-auction-won = { $player } won { $property } for { $amount }. + +# Jail and doubles +monopoly-roll-again = { $player } rolled doubles and gets another roll. +monopoly-three-doubles-jail = { $player } rolled doubles three times and is sent to jail. +monopoly-jail-roll-doubles = { $player } rolled doubles ({ $die1 } and { $die2 }) and leaves jail. +monopoly-jail-roll-failed = { $player } rolled { $die1 } and { $die2 } in jail. Attempt { $attempts }. +monopoly-bail-paid = { $player } paid { $amount } bail. +monopoly-jail-card-used = { $player } used a Get Out of Jail Free card. + +# Cards and debt +monopoly-card-drawn = { $player } drew { $deck }: { $text } +monopoly-debt-created = { $player } owes { $amount } to { $target } for { $reason }. +monopoly-debt-can-pay = { $player } has enough cash to pay the pending debt. +monopoly-player-bankrupt = { $player } is bankrupt. Creditor: { $creditor }. +monopoly-winner = { $player } wins Monopoly with net worth { $value }. diff --git a/server/locales/ko/monopoly.ftl b/server/locales/ko/monopoly.ftl new file mode 100644 index 00000000..330c8df1 --- /dev/null +++ b/server/locales/ko/monopoly.ftl @@ -0,0 +1,116 @@ +# Monopoly game messages + +game-name-monopoly = Monopoly + +monopoly-started = Monopoly started on { $board }. Each player begins with { $cash }. +monopoly-turn = { $player }'s turn. +monopoly-in-jail-turn = { $player } is in jail. Failed roll attempts: { $turns }. + +# Actions +monopoly-roll-dice = Roll dice +monopoly-buy-property = Buy property +monopoly-auction-property = Auction property +monopoly-end-turn = End turn +monopoly-auction-bid = Place auction bid +monopoly-auction-pass = Pass in auction +monopoly-mortgage-property = Mortgage property +monopoly-unmortgage-property = Unmortgage property +monopoly-build-house = Build house or hotel +monopoly-sell-house = Sell house or hotel +monopoly-pay-bail = Pay bail +monopoly-use-jail-card = Use Get Out of Jail Free card +monopoly-pay-debt = Pay debt +monopoly-declare-bankruptcy = Declare bankruptcy +monopoly-offer-trade = Offer trade +monopoly-submit-trade-amount = Set trade amount +monopoly-accept-trade = Accept trade +monopoly-decline-trade = Decline trade +monopoly-check-assets = Check assets +monopoly-check-board = Check board + +# Prompts +monopoly-enter-auction-bid = Enter auction bid amount +monopoly-select-property-mortgage = Select a property to mortgage +monopoly-select-property-unmortgage = Select a property to unmortgage +monopoly-select-property-build = Select a property to build on +monopoly-select-property-sell = Select a property to sell from +monopoly-select-trade-offer = Select a trade offer +monopoly-enter-trade-cash = Enter the cash amount for this trade. For property swaps, use a positive amount if you pay the other player, a negative amount if they pay you, or 0. + +# Validation +monopoly-player-bankrupt-disabled = You are bankrupt. +monopoly-auction-active = Resolve the active auction first. +monopoly-resolve-property-first = Resolve the pending property decision first. +monopoly-debt-pending = Resolve the pending debt first. +monopoly-roll-not-available = Rolling is not available right now. +monopoly-roll-first = Roll first. +monopoly-no-property-to-buy = There is no property to buy right now. +monopoly-no-property-to-auction = There is no property to auction right now. +monopoly-no-debt = There is no debt to pay. +monopoly-no-auction-active = There is no auction in progress. +monopoly-auction-already-passed = You have already passed in this auction. +monopoly-not-enough-cash = You do not have enough cash. +monopoly-not-in-jail = You are not in jail. +monopoly-no-jail-card = You do not have a Get Out of Jail Free card. +monopoly-no-mortgage-options = You do not have any properties available to mortgage. +monopoly-no-unmortgage-options = You do not have any properties available to unmortgage. +monopoly-no-build-options = You do not have any properties available to build on. +monopoly-no-sell-options = You do not have any buildings available to sell. +monopoly-no-trade-options = You do not have any valid trades to offer. +monopoly-trade-pending = Resolve the pending trade first. +monopoly-no-trade-pending = There is no trade pending for you. +monopoly-trade-no-longer-valid = That trade is no longer valid. +monopoly-invalid-trade-amount = That trade amount is not a valid number. +monopoly-invalid-bid = That bid is not a valid number. +monopoly-bid-out-of-range = Bid at least { $minimum } and no more than your cash ({ $cash }). + +# Board events +monopoly-roll-result = { $player } rolled { $die1 } + { $die2 } = { $total }. +monopoly-landed = { $player } landed on { $space }. +monopoly-moved-to = { $player } moved to { $space }. +monopoly-pass-go = { $player } passed GO and collected { $amount }. +monopoly-collected = { $player } collected { $amount } for { $reason }. +monopoly-paid-bank = { $player } paid { $amount } to the bank for { $reason }. +monopoly-paid-player = { $player } paid { $amount } to { $target } for { $reason }. +monopoly-free-parking = { $player } is resting on Free Parking. +monopoly-just-visiting = { $player } is just visiting jail. +monopoly-go-to-jail = { $player } goes directly to jail. +monopoly-landed-own-property = { $player } landed on their own { $property }. + +# Properties and rent +monopoly-property-available = { $property } is unowned and costs { $price }. +monopoly-property-bought = { $player } bought { $property } for { $price }. +monopoly-completed-set = { $player } completed the { $group } set. +monopoly-mortgaged-no-rent = { $player } landed on mortgaged { $property }; no rent is due. +monopoly-property-mortgaged = { $player } mortgaged { $property } for { $amount }. +monopoly-property-unmortgaged = { $player } unmortgaged { $property } for { $amount }. +monopoly-building-built = { $player } built a { $building } on { $property } for { $amount }. Level: { $level }. +monopoly-building-sold = { $player } sold a building on { $property } for { $amount }. Level: { $level }. + +# Trades +monopoly-trade-offered = { $player } offered { $target } a trade: { $summary }. +monopoly-trade-accepted = { $target } accepted { $player }'s trade: { $summary }. +monopoly-trade-declined = { $target } declined { $player }'s trade: { $summary }. +monopoly-mortgage-transfer-interest-paid = { $player } paid { $amount } mortgage transfer interest. + +# Auctions +monopoly-auction-started = Auction started for { $property }. Minimum bid: { $amount }. +monopoly-auction-bid-placed = { $player } bid { $amount } for { $property }. +monopoly-auction-pass-event = { $player } passed on { $property }. +monopoly-auction-no-bids = No bids for { $property }. It remains unsold. +monopoly-auction-won = { $player } won { $property } for { $amount }. + +# Jail and doubles +monopoly-roll-again = { $player } rolled doubles and gets another roll. +monopoly-three-doubles-jail = { $player } rolled doubles three times and is sent to jail. +monopoly-jail-roll-doubles = { $player } rolled doubles ({ $die1 } and { $die2 }) and leaves jail. +monopoly-jail-roll-failed = { $player } rolled { $die1 } and { $die2 } in jail. Attempt { $attempts }. +monopoly-bail-paid = { $player } paid { $amount } bail. +monopoly-jail-card-used = { $player } used a Get Out of Jail Free card. + +# Cards and debt +monopoly-card-drawn = { $player } drew { $deck }: { $text } +monopoly-debt-created = { $player } owes { $amount } to { $target } for { $reason }. +monopoly-debt-can-pay = { $player } has enough cash to pay the pending debt. +monopoly-player-bankrupt = { $player } is bankrupt. Creditor: { $creditor }. +monopoly-winner = { $player } wins Monopoly with net worth { $value }. diff --git a/server/locales/mn/monopoly.ftl b/server/locales/mn/monopoly.ftl new file mode 100644 index 00000000..330c8df1 --- /dev/null +++ b/server/locales/mn/monopoly.ftl @@ -0,0 +1,116 @@ +# Monopoly game messages + +game-name-monopoly = Monopoly + +monopoly-started = Monopoly started on { $board }. Each player begins with { $cash }. +monopoly-turn = { $player }'s turn. +monopoly-in-jail-turn = { $player } is in jail. Failed roll attempts: { $turns }. + +# Actions +monopoly-roll-dice = Roll dice +monopoly-buy-property = Buy property +monopoly-auction-property = Auction property +monopoly-end-turn = End turn +monopoly-auction-bid = Place auction bid +monopoly-auction-pass = Pass in auction +monopoly-mortgage-property = Mortgage property +monopoly-unmortgage-property = Unmortgage property +monopoly-build-house = Build house or hotel +monopoly-sell-house = Sell house or hotel +monopoly-pay-bail = Pay bail +monopoly-use-jail-card = Use Get Out of Jail Free card +monopoly-pay-debt = Pay debt +monopoly-declare-bankruptcy = Declare bankruptcy +monopoly-offer-trade = Offer trade +monopoly-submit-trade-amount = Set trade amount +monopoly-accept-trade = Accept trade +monopoly-decline-trade = Decline trade +monopoly-check-assets = Check assets +monopoly-check-board = Check board + +# Prompts +monopoly-enter-auction-bid = Enter auction bid amount +monopoly-select-property-mortgage = Select a property to mortgage +monopoly-select-property-unmortgage = Select a property to unmortgage +monopoly-select-property-build = Select a property to build on +monopoly-select-property-sell = Select a property to sell from +monopoly-select-trade-offer = Select a trade offer +monopoly-enter-trade-cash = Enter the cash amount for this trade. For property swaps, use a positive amount if you pay the other player, a negative amount if they pay you, or 0. + +# Validation +monopoly-player-bankrupt-disabled = You are bankrupt. +monopoly-auction-active = Resolve the active auction first. +monopoly-resolve-property-first = Resolve the pending property decision first. +monopoly-debt-pending = Resolve the pending debt first. +monopoly-roll-not-available = Rolling is not available right now. +monopoly-roll-first = Roll first. +monopoly-no-property-to-buy = There is no property to buy right now. +monopoly-no-property-to-auction = There is no property to auction right now. +monopoly-no-debt = There is no debt to pay. +monopoly-no-auction-active = There is no auction in progress. +monopoly-auction-already-passed = You have already passed in this auction. +monopoly-not-enough-cash = You do not have enough cash. +monopoly-not-in-jail = You are not in jail. +monopoly-no-jail-card = You do not have a Get Out of Jail Free card. +monopoly-no-mortgage-options = You do not have any properties available to mortgage. +monopoly-no-unmortgage-options = You do not have any properties available to unmortgage. +monopoly-no-build-options = You do not have any properties available to build on. +monopoly-no-sell-options = You do not have any buildings available to sell. +monopoly-no-trade-options = You do not have any valid trades to offer. +monopoly-trade-pending = Resolve the pending trade first. +monopoly-no-trade-pending = There is no trade pending for you. +monopoly-trade-no-longer-valid = That trade is no longer valid. +monopoly-invalid-trade-amount = That trade amount is not a valid number. +monopoly-invalid-bid = That bid is not a valid number. +monopoly-bid-out-of-range = Bid at least { $minimum } and no more than your cash ({ $cash }). + +# Board events +monopoly-roll-result = { $player } rolled { $die1 } + { $die2 } = { $total }. +monopoly-landed = { $player } landed on { $space }. +monopoly-moved-to = { $player } moved to { $space }. +monopoly-pass-go = { $player } passed GO and collected { $amount }. +monopoly-collected = { $player } collected { $amount } for { $reason }. +monopoly-paid-bank = { $player } paid { $amount } to the bank for { $reason }. +monopoly-paid-player = { $player } paid { $amount } to { $target } for { $reason }. +monopoly-free-parking = { $player } is resting on Free Parking. +monopoly-just-visiting = { $player } is just visiting jail. +monopoly-go-to-jail = { $player } goes directly to jail. +monopoly-landed-own-property = { $player } landed on their own { $property }. + +# Properties and rent +monopoly-property-available = { $property } is unowned and costs { $price }. +monopoly-property-bought = { $player } bought { $property } for { $price }. +monopoly-completed-set = { $player } completed the { $group } set. +monopoly-mortgaged-no-rent = { $player } landed on mortgaged { $property }; no rent is due. +monopoly-property-mortgaged = { $player } mortgaged { $property } for { $amount }. +monopoly-property-unmortgaged = { $player } unmortgaged { $property } for { $amount }. +monopoly-building-built = { $player } built a { $building } on { $property } for { $amount }. Level: { $level }. +monopoly-building-sold = { $player } sold a building on { $property } for { $amount }. Level: { $level }. + +# Trades +monopoly-trade-offered = { $player } offered { $target } a trade: { $summary }. +monopoly-trade-accepted = { $target } accepted { $player }'s trade: { $summary }. +monopoly-trade-declined = { $target } declined { $player }'s trade: { $summary }. +monopoly-mortgage-transfer-interest-paid = { $player } paid { $amount } mortgage transfer interest. + +# Auctions +monopoly-auction-started = Auction started for { $property }. Minimum bid: { $amount }. +monopoly-auction-bid-placed = { $player } bid { $amount } for { $property }. +monopoly-auction-pass-event = { $player } passed on { $property }. +monopoly-auction-no-bids = No bids for { $property }. It remains unsold. +monopoly-auction-won = { $player } won { $property } for { $amount }. + +# Jail and doubles +monopoly-roll-again = { $player } rolled doubles and gets another roll. +monopoly-three-doubles-jail = { $player } rolled doubles three times and is sent to jail. +monopoly-jail-roll-doubles = { $player } rolled doubles ({ $die1 } and { $die2 }) and leaves jail. +monopoly-jail-roll-failed = { $player } rolled { $die1 } and { $die2 } in jail. Attempt { $attempts }. +monopoly-bail-paid = { $player } paid { $amount } bail. +monopoly-jail-card-used = { $player } used a Get Out of Jail Free card. + +# Cards and debt +monopoly-card-drawn = { $player } drew { $deck }: { $text } +monopoly-debt-created = { $player } owes { $amount } to { $target } for { $reason }. +monopoly-debt-can-pay = { $player } has enough cash to pay the pending debt. +monopoly-player-bankrupt = { $player } is bankrupt. Creditor: { $creditor }. +monopoly-winner = { $player } wins Monopoly with net worth { $value }. diff --git a/server/locales/nl/monopoly.ftl b/server/locales/nl/monopoly.ftl new file mode 100644 index 00000000..330c8df1 --- /dev/null +++ b/server/locales/nl/monopoly.ftl @@ -0,0 +1,116 @@ +# Monopoly game messages + +game-name-monopoly = Monopoly + +monopoly-started = Monopoly started on { $board }. Each player begins with { $cash }. +monopoly-turn = { $player }'s turn. +monopoly-in-jail-turn = { $player } is in jail. Failed roll attempts: { $turns }. + +# Actions +monopoly-roll-dice = Roll dice +monopoly-buy-property = Buy property +monopoly-auction-property = Auction property +monopoly-end-turn = End turn +monopoly-auction-bid = Place auction bid +monopoly-auction-pass = Pass in auction +monopoly-mortgage-property = Mortgage property +monopoly-unmortgage-property = Unmortgage property +monopoly-build-house = Build house or hotel +monopoly-sell-house = Sell house or hotel +monopoly-pay-bail = Pay bail +monopoly-use-jail-card = Use Get Out of Jail Free card +monopoly-pay-debt = Pay debt +monopoly-declare-bankruptcy = Declare bankruptcy +monopoly-offer-trade = Offer trade +monopoly-submit-trade-amount = Set trade amount +monopoly-accept-trade = Accept trade +monopoly-decline-trade = Decline trade +monopoly-check-assets = Check assets +monopoly-check-board = Check board + +# Prompts +monopoly-enter-auction-bid = Enter auction bid amount +monopoly-select-property-mortgage = Select a property to mortgage +monopoly-select-property-unmortgage = Select a property to unmortgage +monopoly-select-property-build = Select a property to build on +monopoly-select-property-sell = Select a property to sell from +monopoly-select-trade-offer = Select a trade offer +monopoly-enter-trade-cash = Enter the cash amount for this trade. For property swaps, use a positive amount if you pay the other player, a negative amount if they pay you, or 0. + +# Validation +monopoly-player-bankrupt-disabled = You are bankrupt. +monopoly-auction-active = Resolve the active auction first. +monopoly-resolve-property-first = Resolve the pending property decision first. +monopoly-debt-pending = Resolve the pending debt first. +monopoly-roll-not-available = Rolling is not available right now. +monopoly-roll-first = Roll first. +monopoly-no-property-to-buy = There is no property to buy right now. +monopoly-no-property-to-auction = There is no property to auction right now. +monopoly-no-debt = There is no debt to pay. +monopoly-no-auction-active = There is no auction in progress. +monopoly-auction-already-passed = You have already passed in this auction. +monopoly-not-enough-cash = You do not have enough cash. +monopoly-not-in-jail = You are not in jail. +monopoly-no-jail-card = You do not have a Get Out of Jail Free card. +monopoly-no-mortgage-options = You do not have any properties available to mortgage. +monopoly-no-unmortgage-options = You do not have any properties available to unmortgage. +monopoly-no-build-options = You do not have any properties available to build on. +monopoly-no-sell-options = You do not have any buildings available to sell. +monopoly-no-trade-options = You do not have any valid trades to offer. +monopoly-trade-pending = Resolve the pending trade first. +monopoly-no-trade-pending = There is no trade pending for you. +monopoly-trade-no-longer-valid = That trade is no longer valid. +monopoly-invalid-trade-amount = That trade amount is not a valid number. +monopoly-invalid-bid = That bid is not a valid number. +monopoly-bid-out-of-range = Bid at least { $minimum } and no more than your cash ({ $cash }). + +# Board events +monopoly-roll-result = { $player } rolled { $die1 } + { $die2 } = { $total }. +monopoly-landed = { $player } landed on { $space }. +monopoly-moved-to = { $player } moved to { $space }. +monopoly-pass-go = { $player } passed GO and collected { $amount }. +monopoly-collected = { $player } collected { $amount } for { $reason }. +monopoly-paid-bank = { $player } paid { $amount } to the bank for { $reason }. +monopoly-paid-player = { $player } paid { $amount } to { $target } for { $reason }. +monopoly-free-parking = { $player } is resting on Free Parking. +monopoly-just-visiting = { $player } is just visiting jail. +monopoly-go-to-jail = { $player } goes directly to jail. +monopoly-landed-own-property = { $player } landed on their own { $property }. + +# Properties and rent +monopoly-property-available = { $property } is unowned and costs { $price }. +monopoly-property-bought = { $player } bought { $property } for { $price }. +monopoly-completed-set = { $player } completed the { $group } set. +monopoly-mortgaged-no-rent = { $player } landed on mortgaged { $property }; no rent is due. +monopoly-property-mortgaged = { $player } mortgaged { $property } for { $amount }. +monopoly-property-unmortgaged = { $player } unmortgaged { $property } for { $amount }. +monopoly-building-built = { $player } built a { $building } on { $property } for { $amount }. Level: { $level }. +monopoly-building-sold = { $player } sold a building on { $property } for { $amount }. Level: { $level }. + +# Trades +monopoly-trade-offered = { $player } offered { $target } a trade: { $summary }. +monopoly-trade-accepted = { $target } accepted { $player }'s trade: { $summary }. +monopoly-trade-declined = { $target } declined { $player }'s trade: { $summary }. +monopoly-mortgage-transfer-interest-paid = { $player } paid { $amount } mortgage transfer interest. + +# Auctions +monopoly-auction-started = Auction started for { $property }. Minimum bid: { $amount }. +monopoly-auction-bid-placed = { $player } bid { $amount } for { $property }. +monopoly-auction-pass-event = { $player } passed on { $property }. +monopoly-auction-no-bids = No bids for { $property }. It remains unsold. +monopoly-auction-won = { $player } won { $property } for { $amount }. + +# Jail and doubles +monopoly-roll-again = { $player } rolled doubles and gets another roll. +monopoly-three-doubles-jail = { $player } rolled doubles three times and is sent to jail. +monopoly-jail-roll-doubles = { $player } rolled doubles ({ $die1 } and { $die2 }) and leaves jail. +monopoly-jail-roll-failed = { $player } rolled { $die1 } and { $die2 } in jail. Attempt { $attempts }. +monopoly-bail-paid = { $player } paid { $amount } bail. +monopoly-jail-card-used = { $player } used a Get Out of Jail Free card. + +# Cards and debt +monopoly-card-drawn = { $player } drew { $deck }: { $text } +monopoly-debt-created = { $player } owes { $amount } to { $target } for { $reason }. +monopoly-debt-can-pay = { $player } has enough cash to pay the pending debt. +monopoly-player-bankrupt = { $player } is bankrupt. Creditor: { $creditor }. +monopoly-winner = { $player } wins Monopoly with net worth { $value }. diff --git a/server/locales/pl/monopoly.ftl b/server/locales/pl/monopoly.ftl new file mode 100644 index 00000000..330c8df1 --- /dev/null +++ b/server/locales/pl/monopoly.ftl @@ -0,0 +1,116 @@ +# Monopoly game messages + +game-name-monopoly = Monopoly + +monopoly-started = Monopoly started on { $board }. Each player begins with { $cash }. +monopoly-turn = { $player }'s turn. +monopoly-in-jail-turn = { $player } is in jail. Failed roll attempts: { $turns }. + +# Actions +monopoly-roll-dice = Roll dice +monopoly-buy-property = Buy property +monopoly-auction-property = Auction property +monopoly-end-turn = End turn +monopoly-auction-bid = Place auction bid +monopoly-auction-pass = Pass in auction +monopoly-mortgage-property = Mortgage property +monopoly-unmortgage-property = Unmortgage property +monopoly-build-house = Build house or hotel +monopoly-sell-house = Sell house or hotel +monopoly-pay-bail = Pay bail +monopoly-use-jail-card = Use Get Out of Jail Free card +monopoly-pay-debt = Pay debt +monopoly-declare-bankruptcy = Declare bankruptcy +monopoly-offer-trade = Offer trade +monopoly-submit-trade-amount = Set trade amount +monopoly-accept-trade = Accept trade +monopoly-decline-trade = Decline trade +monopoly-check-assets = Check assets +monopoly-check-board = Check board + +# Prompts +monopoly-enter-auction-bid = Enter auction bid amount +monopoly-select-property-mortgage = Select a property to mortgage +monopoly-select-property-unmortgage = Select a property to unmortgage +monopoly-select-property-build = Select a property to build on +monopoly-select-property-sell = Select a property to sell from +monopoly-select-trade-offer = Select a trade offer +monopoly-enter-trade-cash = Enter the cash amount for this trade. For property swaps, use a positive amount if you pay the other player, a negative amount if they pay you, or 0. + +# Validation +monopoly-player-bankrupt-disabled = You are bankrupt. +monopoly-auction-active = Resolve the active auction first. +monopoly-resolve-property-first = Resolve the pending property decision first. +monopoly-debt-pending = Resolve the pending debt first. +monopoly-roll-not-available = Rolling is not available right now. +monopoly-roll-first = Roll first. +monopoly-no-property-to-buy = There is no property to buy right now. +monopoly-no-property-to-auction = There is no property to auction right now. +monopoly-no-debt = There is no debt to pay. +monopoly-no-auction-active = There is no auction in progress. +monopoly-auction-already-passed = You have already passed in this auction. +monopoly-not-enough-cash = You do not have enough cash. +monopoly-not-in-jail = You are not in jail. +monopoly-no-jail-card = You do not have a Get Out of Jail Free card. +monopoly-no-mortgage-options = You do not have any properties available to mortgage. +monopoly-no-unmortgage-options = You do not have any properties available to unmortgage. +monopoly-no-build-options = You do not have any properties available to build on. +monopoly-no-sell-options = You do not have any buildings available to sell. +monopoly-no-trade-options = You do not have any valid trades to offer. +monopoly-trade-pending = Resolve the pending trade first. +monopoly-no-trade-pending = There is no trade pending for you. +monopoly-trade-no-longer-valid = That trade is no longer valid. +monopoly-invalid-trade-amount = That trade amount is not a valid number. +monopoly-invalid-bid = That bid is not a valid number. +monopoly-bid-out-of-range = Bid at least { $minimum } and no more than your cash ({ $cash }). + +# Board events +monopoly-roll-result = { $player } rolled { $die1 } + { $die2 } = { $total }. +monopoly-landed = { $player } landed on { $space }. +monopoly-moved-to = { $player } moved to { $space }. +monopoly-pass-go = { $player } passed GO and collected { $amount }. +monopoly-collected = { $player } collected { $amount } for { $reason }. +monopoly-paid-bank = { $player } paid { $amount } to the bank for { $reason }. +monopoly-paid-player = { $player } paid { $amount } to { $target } for { $reason }. +monopoly-free-parking = { $player } is resting on Free Parking. +monopoly-just-visiting = { $player } is just visiting jail. +monopoly-go-to-jail = { $player } goes directly to jail. +monopoly-landed-own-property = { $player } landed on their own { $property }. + +# Properties and rent +monopoly-property-available = { $property } is unowned and costs { $price }. +monopoly-property-bought = { $player } bought { $property } for { $price }. +monopoly-completed-set = { $player } completed the { $group } set. +monopoly-mortgaged-no-rent = { $player } landed on mortgaged { $property }; no rent is due. +monopoly-property-mortgaged = { $player } mortgaged { $property } for { $amount }. +monopoly-property-unmortgaged = { $player } unmortgaged { $property } for { $amount }. +monopoly-building-built = { $player } built a { $building } on { $property } for { $amount }. Level: { $level }. +monopoly-building-sold = { $player } sold a building on { $property } for { $amount }. Level: { $level }. + +# Trades +monopoly-trade-offered = { $player } offered { $target } a trade: { $summary }. +monopoly-trade-accepted = { $target } accepted { $player }'s trade: { $summary }. +monopoly-trade-declined = { $target } declined { $player }'s trade: { $summary }. +monopoly-mortgage-transfer-interest-paid = { $player } paid { $amount } mortgage transfer interest. + +# Auctions +monopoly-auction-started = Auction started for { $property }. Minimum bid: { $amount }. +monopoly-auction-bid-placed = { $player } bid { $amount } for { $property }. +monopoly-auction-pass-event = { $player } passed on { $property }. +monopoly-auction-no-bids = No bids for { $property }. It remains unsold. +monopoly-auction-won = { $player } won { $property } for { $amount }. + +# Jail and doubles +monopoly-roll-again = { $player } rolled doubles and gets another roll. +monopoly-three-doubles-jail = { $player } rolled doubles three times and is sent to jail. +monopoly-jail-roll-doubles = { $player } rolled doubles ({ $die1 } and { $die2 }) and leaves jail. +monopoly-jail-roll-failed = { $player } rolled { $die1 } and { $die2 } in jail. Attempt { $attempts }. +monopoly-bail-paid = { $player } paid { $amount } bail. +monopoly-jail-card-used = { $player } used a Get Out of Jail Free card. + +# Cards and debt +monopoly-card-drawn = { $player } drew { $deck }: { $text } +monopoly-debt-created = { $player } owes { $amount } to { $target } for { $reason }. +monopoly-debt-can-pay = { $player } has enough cash to pay the pending debt. +monopoly-player-bankrupt = { $player } is bankrupt. Creditor: { $creditor }. +monopoly-winner = { $player } wins Monopoly with net worth { $value }. diff --git a/server/locales/pt/monopoly.ftl b/server/locales/pt/monopoly.ftl new file mode 100644 index 00000000..330c8df1 --- /dev/null +++ b/server/locales/pt/monopoly.ftl @@ -0,0 +1,116 @@ +# Monopoly game messages + +game-name-monopoly = Monopoly + +monopoly-started = Monopoly started on { $board }. Each player begins with { $cash }. +monopoly-turn = { $player }'s turn. +monopoly-in-jail-turn = { $player } is in jail. Failed roll attempts: { $turns }. + +# Actions +monopoly-roll-dice = Roll dice +monopoly-buy-property = Buy property +monopoly-auction-property = Auction property +monopoly-end-turn = End turn +monopoly-auction-bid = Place auction bid +monopoly-auction-pass = Pass in auction +monopoly-mortgage-property = Mortgage property +monopoly-unmortgage-property = Unmortgage property +monopoly-build-house = Build house or hotel +monopoly-sell-house = Sell house or hotel +monopoly-pay-bail = Pay bail +monopoly-use-jail-card = Use Get Out of Jail Free card +monopoly-pay-debt = Pay debt +monopoly-declare-bankruptcy = Declare bankruptcy +monopoly-offer-trade = Offer trade +monopoly-submit-trade-amount = Set trade amount +monopoly-accept-trade = Accept trade +monopoly-decline-trade = Decline trade +monopoly-check-assets = Check assets +monopoly-check-board = Check board + +# Prompts +monopoly-enter-auction-bid = Enter auction bid amount +monopoly-select-property-mortgage = Select a property to mortgage +monopoly-select-property-unmortgage = Select a property to unmortgage +monopoly-select-property-build = Select a property to build on +monopoly-select-property-sell = Select a property to sell from +monopoly-select-trade-offer = Select a trade offer +monopoly-enter-trade-cash = Enter the cash amount for this trade. For property swaps, use a positive amount if you pay the other player, a negative amount if they pay you, or 0. + +# Validation +monopoly-player-bankrupt-disabled = You are bankrupt. +monopoly-auction-active = Resolve the active auction first. +monopoly-resolve-property-first = Resolve the pending property decision first. +monopoly-debt-pending = Resolve the pending debt first. +monopoly-roll-not-available = Rolling is not available right now. +monopoly-roll-first = Roll first. +monopoly-no-property-to-buy = There is no property to buy right now. +monopoly-no-property-to-auction = There is no property to auction right now. +monopoly-no-debt = There is no debt to pay. +monopoly-no-auction-active = There is no auction in progress. +monopoly-auction-already-passed = You have already passed in this auction. +monopoly-not-enough-cash = You do not have enough cash. +monopoly-not-in-jail = You are not in jail. +monopoly-no-jail-card = You do not have a Get Out of Jail Free card. +monopoly-no-mortgage-options = You do not have any properties available to mortgage. +monopoly-no-unmortgage-options = You do not have any properties available to unmortgage. +monopoly-no-build-options = You do not have any properties available to build on. +monopoly-no-sell-options = You do not have any buildings available to sell. +monopoly-no-trade-options = You do not have any valid trades to offer. +monopoly-trade-pending = Resolve the pending trade first. +monopoly-no-trade-pending = There is no trade pending for you. +monopoly-trade-no-longer-valid = That trade is no longer valid. +monopoly-invalid-trade-amount = That trade amount is not a valid number. +monopoly-invalid-bid = That bid is not a valid number. +monopoly-bid-out-of-range = Bid at least { $minimum } and no more than your cash ({ $cash }). + +# Board events +monopoly-roll-result = { $player } rolled { $die1 } + { $die2 } = { $total }. +monopoly-landed = { $player } landed on { $space }. +monopoly-moved-to = { $player } moved to { $space }. +monopoly-pass-go = { $player } passed GO and collected { $amount }. +monopoly-collected = { $player } collected { $amount } for { $reason }. +monopoly-paid-bank = { $player } paid { $amount } to the bank for { $reason }. +monopoly-paid-player = { $player } paid { $amount } to { $target } for { $reason }. +monopoly-free-parking = { $player } is resting on Free Parking. +monopoly-just-visiting = { $player } is just visiting jail. +monopoly-go-to-jail = { $player } goes directly to jail. +monopoly-landed-own-property = { $player } landed on their own { $property }. + +# Properties and rent +monopoly-property-available = { $property } is unowned and costs { $price }. +monopoly-property-bought = { $player } bought { $property } for { $price }. +monopoly-completed-set = { $player } completed the { $group } set. +monopoly-mortgaged-no-rent = { $player } landed on mortgaged { $property }; no rent is due. +monopoly-property-mortgaged = { $player } mortgaged { $property } for { $amount }. +monopoly-property-unmortgaged = { $player } unmortgaged { $property } for { $amount }. +monopoly-building-built = { $player } built a { $building } on { $property } for { $amount }. Level: { $level }. +monopoly-building-sold = { $player } sold a building on { $property } for { $amount }. Level: { $level }. + +# Trades +monopoly-trade-offered = { $player } offered { $target } a trade: { $summary }. +monopoly-trade-accepted = { $target } accepted { $player }'s trade: { $summary }. +monopoly-trade-declined = { $target } declined { $player }'s trade: { $summary }. +monopoly-mortgage-transfer-interest-paid = { $player } paid { $amount } mortgage transfer interest. + +# Auctions +monopoly-auction-started = Auction started for { $property }. Minimum bid: { $amount }. +monopoly-auction-bid-placed = { $player } bid { $amount } for { $property }. +monopoly-auction-pass-event = { $player } passed on { $property }. +monopoly-auction-no-bids = No bids for { $property }. It remains unsold. +monopoly-auction-won = { $player } won { $property } for { $amount }. + +# Jail and doubles +monopoly-roll-again = { $player } rolled doubles and gets another roll. +monopoly-three-doubles-jail = { $player } rolled doubles three times and is sent to jail. +monopoly-jail-roll-doubles = { $player } rolled doubles ({ $die1 } and { $die2 }) and leaves jail. +monopoly-jail-roll-failed = { $player } rolled { $die1 } and { $die2 } in jail. Attempt { $attempts }. +monopoly-bail-paid = { $player } paid { $amount } bail. +monopoly-jail-card-used = { $player } used a Get Out of Jail Free card. + +# Cards and debt +monopoly-card-drawn = { $player } drew { $deck }: { $text } +monopoly-debt-created = { $player } owes { $amount } to { $target } for { $reason }. +monopoly-debt-can-pay = { $player } has enough cash to pay the pending debt. +monopoly-player-bankrupt = { $player } is bankrupt. Creditor: { $creditor }. +monopoly-winner = { $player } wins Monopoly with net worth { $value }. diff --git a/server/locales/ro/monopoly.ftl b/server/locales/ro/monopoly.ftl new file mode 100644 index 00000000..330c8df1 --- /dev/null +++ b/server/locales/ro/monopoly.ftl @@ -0,0 +1,116 @@ +# Monopoly game messages + +game-name-monopoly = Monopoly + +monopoly-started = Monopoly started on { $board }. Each player begins with { $cash }. +monopoly-turn = { $player }'s turn. +monopoly-in-jail-turn = { $player } is in jail. Failed roll attempts: { $turns }. + +# Actions +monopoly-roll-dice = Roll dice +monopoly-buy-property = Buy property +monopoly-auction-property = Auction property +monopoly-end-turn = End turn +monopoly-auction-bid = Place auction bid +monopoly-auction-pass = Pass in auction +monopoly-mortgage-property = Mortgage property +monopoly-unmortgage-property = Unmortgage property +monopoly-build-house = Build house or hotel +monopoly-sell-house = Sell house or hotel +monopoly-pay-bail = Pay bail +monopoly-use-jail-card = Use Get Out of Jail Free card +monopoly-pay-debt = Pay debt +monopoly-declare-bankruptcy = Declare bankruptcy +monopoly-offer-trade = Offer trade +monopoly-submit-trade-amount = Set trade amount +monopoly-accept-trade = Accept trade +monopoly-decline-trade = Decline trade +monopoly-check-assets = Check assets +monopoly-check-board = Check board + +# Prompts +monopoly-enter-auction-bid = Enter auction bid amount +monopoly-select-property-mortgage = Select a property to mortgage +monopoly-select-property-unmortgage = Select a property to unmortgage +monopoly-select-property-build = Select a property to build on +monopoly-select-property-sell = Select a property to sell from +monopoly-select-trade-offer = Select a trade offer +monopoly-enter-trade-cash = Enter the cash amount for this trade. For property swaps, use a positive amount if you pay the other player, a negative amount if they pay you, or 0. + +# Validation +monopoly-player-bankrupt-disabled = You are bankrupt. +monopoly-auction-active = Resolve the active auction first. +monopoly-resolve-property-first = Resolve the pending property decision first. +monopoly-debt-pending = Resolve the pending debt first. +monopoly-roll-not-available = Rolling is not available right now. +monopoly-roll-first = Roll first. +monopoly-no-property-to-buy = There is no property to buy right now. +monopoly-no-property-to-auction = There is no property to auction right now. +monopoly-no-debt = There is no debt to pay. +monopoly-no-auction-active = There is no auction in progress. +monopoly-auction-already-passed = You have already passed in this auction. +monopoly-not-enough-cash = You do not have enough cash. +monopoly-not-in-jail = You are not in jail. +monopoly-no-jail-card = You do not have a Get Out of Jail Free card. +monopoly-no-mortgage-options = You do not have any properties available to mortgage. +monopoly-no-unmortgage-options = You do not have any properties available to unmortgage. +monopoly-no-build-options = You do not have any properties available to build on. +monopoly-no-sell-options = You do not have any buildings available to sell. +monopoly-no-trade-options = You do not have any valid trades to offer. +monopoly-trade-pending = Resolve the pending trade first. +monopoly-no-trade-pending = There is no trade pending for you. +monopoly-trade-no-longer-valid = That trade is no longer valid. +monopoly-invalid-trade-amount = That trade amount is not a valid number. +monopoly-invalid-bid = That bid is not a valid number. +monopoly-bid-out-of-range = Bid at least { $minimum } and no more than your cash ({ $cash }). + +# Board events +monopoly-roll-result = { $player } rolled { $die1 } + { $die2 } = { $total }. +monopoly-landed = { $player } landed on { $space }. +monopoly-moved-to = { $player } moved to { $space }. +monopoly-pass-go = { $player } passed GO and collected { $amount }. +monopoly-collected = { $player } collected { $amount } for { $reason }. +monopoly-paid-bank = { $player } paid { $amount } to the bank for { $reason }. +monopoly-paid-player = { $player } paid { $amount } to { $target } for { $reason }. +monopoly-free-parking = { $player } is resting on Free Parking. +monopoly-just-visiting = { $player } is just visiting jail. +monopoly-go-to-jail = { $player } goes directly to jail. +monopoly-landed-own-property = { $player } landed on their own { $property }. + +# Properties and rent +monopoly-property-available = { $property } is unowned and costs { $price }. +monopoly-property-bought = { $player } bought { $property } for { $price }. +monopoly-completed-set = { $player } completed the { $group } set. +monopoly-mortgaged-no-rent = { $player } landed on mortgaged { $property }; no rent is due. +monopoly-property-mortgaged = { $player } mortgaged { $property } for { $amount }. +monopoly-property-unmortgaged = { $player } unmortgaged { $property } for { $amount }. +monopoly-building-built = { $player } built a { $building } on { $property } for { $amount }. Level: { $level }. +monopoly-building-sold = { $player } sold a building on { $property } for { $amount }. Level: { $level }. + +# Trades +monopoly-trade-offered = { $player } offered { $target } a trade: { $summary }. +monopoly-trade-accepted = { $target } accepted { $player }'s trade: { $summary }. +monopoly-trade-declined = { $target } declined { $player }'s trade: { $summary }. +monopoly-mortgage-transfer-interest-paid = { $player } paid { $amount } mortgage transfer interest. + +# Auctions +monopoly-auction-started = Auction started for { $property }. Minimum bid: { $amount }. +monopoly-auction-bid-placed = { $player } bid { $amount } for { $property }. +monopoly-auction-pass-event = { $player } passed on { $property }. +monopoly-auction-no-bids = No bids for { $property }. It remains unsold. +monopoly-auction-won = { $player } won { $property } for { $amount }. + +# Jail and doubles +monopoly-roll-again = { $player } rolled doubles and gets another roll. +monopoly-three-doubles-jail = { $player } rolled doubles three times and is sent to jail. +monopoly-jail-roll-doubles = { $player } rolled doubles ({ $die1 } and { $die2 }) and leaves jail. +monopoly-jail-roll-failed = { $player } rolled { $die1 } and { $die2 } in jail. Attempt { $attempts }. +monopoly-bail-paid = { $player } paid { $amount } bail. +monopoly-jail-card-used = { $player } used a Get Out of Jail Free card. + +# Cards and debt +monopoly-card-drawn = { $player } drew { $deck }: { $text } +monopoly-debt-created = { $player } owes { $amount } to { $target } for { $reason }. +monopoly-debt-can-pay = { $player } has enough cash to pay the pending debt. +monopoly-player-bankrupt = { $player } is bankrupt. Creditor: { $creditor }. +monopoly-winner = { $player } wins Monopoly with net worth { $value }. diff --git a/server/locales/ru/monopoly.ftl b/server/locales/ru/monopoly.ftl new file mode 100644 index 00000000..330c8df1 --- /dev/null +++ b/server/locales/ru/monopoly.ftl @@ -0,0 +1,116 @@ +# Monopoly game messages + +game-name-monopoly = Monopoly + +monopoly-started = Monopoly started on { $board }. Each player begins with { $cash }. +monopoly-turn = { $player }'s turn. +monopoly-in-jail-turn = { $player } is in jail. Failed roll attempts: { $turns }. + +# Actions +monopoly-roll-dice = Roll dice +monopoly-buy-property = Buy property +monopoly-auction-property = Auction property +monopoly-end-turn = End turn +monopoly-auction-bid = Place auction bid +monopoly-auction-pass = Pass in auction +monopoly-mortgage-property = Mortgage property +monopoly-unmortgage-property = Unmortgage property +monopoly-build-house = Build house or hotel +monopoly-sell-house = Sell house or hotel +monopoly-pay-bail = Pay bail +monopoly-use-jail-card = Use Get Out of Jail Free card +monopoly-pay-debt = Pay debt +monopoly-declare-bankruptcy = Declare bankruptcy +monopoly-offer-trade = Offer trade +monopoly-submit-trade-amount = Set trade amount +monopoly-accept-trade = Accept trade +monopoly-decline-trade = Decline trade +monopoly-check-assets = Check assets +monopoly-check-board = Check board + +# Prompts +monopoly-enter-auction-bid = Enter auction bid amount +monopoly-select-property-mortgage = Select a property to mortgage +monopoly-select-property-unmortgage = Select a property to unmortgage +monopoly-select-property-build = Select a property to build on +monopoly-select-property-sell = Select a property to sell from +monopoly-select-trade-offer = Select a trade offer +monopoly-enter-trade-cash = Enter the cash amount for this trade. For property swaps, use a positive amount if you pay the other player, a negative amount if they pay you, or 0. + +# Validation +monopoly-player-bankrupt-disabled = You are bankrupt. +monopoly-auction-active = Resolve the active auction first. +monopoly-resolve-property-first = Resolve the pending property decision first. +monopoly-debt-pending = Resolve the pending debt first. +monopoly-roll-not-available = Rolling is not available right now. +monopoly-roll-first = Roll first. +monopoly-no-property-to-buy = There is no property to buy right now. +monopoly-no-property-to-auction = There is no property to auction right now. +monopoly-no-debt = There is no debt to pay. +monopoly-no-auction-active = There is no auction in progress. +monopoly-auction-already-passed = You have already passed in this auction. +monopoly-not-enough-cash = You do not have enough cash. +monopoly-not-in-jail = You are not in jail. +monopoly-no-jail-card = You do not have a Get Out of Jail Free card. +monopoly-no-mortgage-options = You do not have any properties available to mortgage. +monopoly-no-unmortgage-options = You do not have any properties available to unmortgage. +monopoly-no-build-options = You do not have any properties available to build on. +monopoly-no-sell-options = You do not have any buildings available to sell. +monopoly-no-trade-options = You do not have any valid trades to offer. +monopoly-trade-pending = Resolve the pending trade first. +monopoly-no-trade-pending = There is no trade pending for you. +monopoly-trade-no-longer-valid = That trade is no longer valid. +monopoly-invalid-trade-amount = That trade amount is not a valid number. +monopoly-invalid-bid = That bid is not a valid number. +monopoly-bid-out-of-range = Bid at least { $minimum } and no more than your cash ({ $cash }). + +# Board events +monopoly-roll-result = { $player } rolled { $die1 } + { $die2 } = { $total }. +monopoly-landed = { $player } landed on { $space }. +monopoly-moved-to = { $player } moved to { $space }. +monopoly-pass-go = { $player } passed GO and collected { $amount }. +monopoly-collected = { $player } collected { $amount } for { $reason }. +monopoly-paid-bank = { $player } paid { $amount } to the bank for { $reason }. +monopoly-paid-player = { $player } paid { $amount } to { $target } for { $reason }. +monopoly-free-parking = { $player } is resting on Free Parking. +monopoly-just-visiting = { $player } is just visiting jail. +monopoly-go-to-jail = { $player } goes directly to jail. +monopoly-landed-own-property = { $player } landed on their own { $property }. + +# Properties and rent +monopoly-property-available = { $property } is unowned and costs { $price }. +monopoly-property-bought = { $player } bought { $property } for { $price }. +monopoly-completed-set = { $player } completed the { $group } set. +monopoly-mortgaged-no-rent = { $player } landed on mortgaged { $property }; no rent is due. +monopoly-property-mortgaged = { $player } mortgaged { $property } for { $amount }. +monopoly-property-unmortgaged = { $player } unmortgaged { $property } for { $amount }. +monopoly-building-built = { $player } built a { $building } on { $property } for { $amount }. Level: { $level }. +monopoly-building-sold = { $player } sold a building on { $property } for { $amount }. Level: { $level }. + +# Trades +monopoly-trade-offered = { $player } offered { $target } a trade: { $summary }. +monopoly-trade-accepted = { $target } accepted { $player }'s trade: { $summary }. +monopoly-trade-declined = { $target } declined { $player }'s trade: { $summary }. +monopoly-mortgage-transfer-interest-paid = { $player } paid { $amount } mortgage transfer interest. + +# Auctions +monopoly-auction-started = Auction started for { $property }. Minimum bid: { $amount }. +monopoly-auction-bid-placed = { $player } bid { $amount } for { $property }. +monopoly-auction-pass-event = { $player } passed on { $property }. +monopoly-auction-no-bids = No bids for { $property }. It remains unsold. +monopoly-auction-won = { $player } won { $property } for { $amount }. + +# Jail and doubles +monopoly-roll-again = { $player } rolled doubles and gets another roll. +monopoly-three-doubles-jail = { $player } rolled doubles three times and is sent to jail. +monopoly-jail-roll-doubles = { $player } rolled doubles ({ $die1 } and { $die2 }) and leaves jail. +monopoly-jail-roll-failed = { $player } rolled { $die1 } and { $die2 } in jail. Attempt { $attempts }. +monopoly-bail-paid = { $player } paid { $amount } bail. +monopoly-jail-card-used = { $player } used a Get Out of Jail Free card. + +# Cards and debt +monopoly-card-drawn = { $player } drew { $deck }: { $text } +monopoly-debt-created = { $player } owes { $amount } to { $target } for { $reason }. +monopoly-debt-can-pay = { $player } has enough cash to pay the pending debt. +monopoly-player-bankrupt = { $player } is bankrupt. Creditor: { $creditor }. +monopoly-winner = { $player } wins Monopoly with net worth { $value }. diff --git a/server/locales/sk/monopoly.ftl b/server/locales/sk/monopoly.ftl new file mode 100644 index 00000000..330c8df1 --- /dev/null +++ b/server/locales/sk/monopoly.ftl @@ -0,0 +1,116 @@ +# Monopoly game messages + +game-name-monopoly = Monopoly + +monopoly-started = Monopoly started on { $board }. Each player begins with { $cash }. +monopoly-turn = { $player }'s turn. +monopoly-in-jail-turn = { $player } is in jail. Failed roll attempts: { $turns }. + +# Actions +monopoly-roll-dice = Roll dice +monopoly-buy-property = Buy property +monopoly-auction-property = Auction property +monopoly-end-turn = End turn +monopoly-auction-bid = Place auction bid +monopoly-auction-pass = Pass in auction +monopoly-mortgage-property = Mortgage property +monopoly-unmortgage-property = Unmortgage property +monopoly-build-house = Build house or hotel +monopoly-sell-house = Sell house or hotel +monopoly-pay-bail = Pay bail +monopoly-use-jail-card = Use Get Out of Jail Free card +monopoly-pay-debt = Pay debt +monopoly-declare-bankruptcy = Declare bankruptcy +monopoly-offer-trade = Offer trade +monopoly-submit-trade-amount = Set trade amount +monopoly-accept-trade = Accept trade +monopoly-decline-trade = Decline trade +monopoly-check-assets = Check assets +monopoly-check-board = Check board + +# Prompts +monopoly-enter-auction-bid = Enter auction bid amount +monopoly-select-property-mortgage = Select a property to mortgage +monopoly-select-property-unmortgage = Select a property to unmortgage +monopoly-select-property-build = Select a property to build on +monopoly-select-property-sell = Select a property to sell from +monopoly-select-trade-offer = Select a trade offer +monopoly-enter-trade-cash = Enter the cash amount for this trade. For property swaps, use a positive amount if you pay the other player, a negative amount if they pay you, or 0. + +# Validation +monopoly-player-bankrupt-disabled = You are bankrupt. +monopoly-auction-active = Resolve the active auction first. +monopoly-resolve-property-first = Resolve the pending property decision first. +monopoly-debt-pending = Resolve the pending debt first. +monopoly-roll-not-available = Rolling is not available right now. +monopoly-roll-first = Roll first. +monopoly-no-property-to-buy = There is no property to buy right now. +monopoly-no-property-to-auction = There is no property to auction right now. +monopoly-no-debt = There is no debt to pay. +monopoly-no-auction-active = There is no auction in progress. +monopoly-auction-already-passed = You have already passed in this auction. +monopoly-not-enough-cash = You do not have enough cash. +monopoly-not-in-jail = You are not in jail. +monopoly-no-jail-card = You do not have a Get Out of Jail Free card. +monopoly-no-mortgage-options = You do not have any properties available to mortgage. +monopoly-no-unmortgage-options = You do not have any properties available to unmortgage. +monopoly-no-build-options = You do not have any properties available to build on. +monopoly-no-sell-options = You do not have any buildings available to sell. +monopoly-no-trade-options = You do not have any valid trades to offer. +monopoly-trade-pending = Resolve the pending trade first. +monopoly-no-trade-pending = There is no trade pending for you. +monopoly-trade-no-longer-valid = That trade is no longer valid. +monopoly-invalid-trade-amount = That trade amount is not a valid number. +monopoly-invalid-bid = That bid is not a valid number. +monopoly-bid-out-of-range = Bid at least { $minimum } and no more than your cash ({ $cash }). + +# Board events +monopoly-roll-result = { $player } rolled { $die1 } + { $die2 } = { $total }. +monopoly-landed = { $player } landed on { $space }. +monopoly-moved-to = { $player } moved to { $space }. +monopoly-pass-go = { $player } passed GO and collected { $amount }. +monopoly-collected = { $player } collected { $amount } for { $reason }. +monopoly-paid-bank = { $player } paid { $amount } to the bank for { $reason }. +monopoly-paid-player = { $player } paid { $amount } to { $target } for { $reason }. +monopoly-free-parking = { $player } is resting on Free Parking. +monopoly-just-visiting = { $player } is just visiting jail. +monopoly-go-to-jail = { $player } goes directly to jail. +monopoly-landed-own-property = { $player } landed on their own { $property }. + +# Properties and rent +monopoly-property-available = { $property } is unowned and costs { $price }. +monopoly-property-bought = { $player } bought { $property } for { $price }. +monopoly-completed-set = { $player } completed the { $group } set. +monopoly-mortgaged-no-rent = { $player } landed on mortgaged { $property }; no rent is due. +monopoly-property-mortgaged = { $player } mortgaged { $property } for { $amount }. +monopoly-property-unmortgaged = { $player } unmortgaged { $property } for { $amount }. +monopoly-building-built = { $player } built a { $building } on { $property } for { $amount }. Level: { $level }. +monopoly-building-sold = { $player } sold a building on { $property } for { $amount }. Level: { $level }. + +# Trades +monopoly-trade-offered = { $player } offered { $target } a trade: { $summary }. +monopoly-trade-accepted = { $target } accepted { $player }'s trade: { $summary }. +monopoly-trade-declined = { $target } declined { $player }'s trade: { $summary }. +monopoly-mortgage-transfer-interest-paid = { $player } paid { $amount } mortgage transfer interest. + +# Auctions +monopoly-auction-started = Auction started for { $property }. Minimum bid: { $amount }. +monopoly-auction-bid-placed = { $player } bid { $amount } for { $property }. +monopoly-auction-pass-event = { $player } passed on { $property }. +monopoly-auction-no-bids = No bids for { $property }. It remains unsold. +monopoly-auction-won = { $player } won { $property } for { $amount }. + +# Jail and doubles +monopoly-roll-again = { $player } rolled doubles and gets another roll. +monopoly-three-doubles-jail = { $player } rolled doubles three times and is sent to jail. +monopoly-jail-roll-doubles = { $player } rolled doubles ({ $die1 } and { $die2 }) and leaves jail. +monopoly-jail-roll-failed = { $player } rolled { $die1 } and { $die2 } in jail. Attempt { $attempts }. +monopoly-bail-paid = { $player } paid { $amount } bail. +monopoly-jail-card-used = { $player } used a Get Out of Jail Free card. + +# Cards and debt +monopoly-card-drawn = { $player } drew { $deck }: { $text } +monopoly-debt-created = { $player } owes { $amount } to { $target } for { $reason }. +monopoly-debt-can-pay = { $player } has enough cash to pay the pending debt. +monopoly-player-bankrupt = { $player } is bankrupt. Creditor: { $creditor }. +monopoly-winner = { $player } wins Monopoly with net worth { $value }. diff --git a/server/locales/sl/monopoly.ftl b/server/locales/sl/monopoly.ftl new file mode 100644 index 00000000..330c8df1 --- /dev/null +++ b/server/locales/sl/monopoly.ftl @@ -0,0 +1,116 @@ +# Monopoly game messages + +game-name-monopoly = Monopoly + +monopoly-started = Monopoly started on { $board }. Each player begins with { $cash }. +monopoly-turn = { $player }'s turn. +monopoly-in-jail-turn = { $player } is in jail. Failed roll attempts: { $turns }. + +# Actions +monopoly-roll-dice = Roll dice +monopoly-buy-property = Buy property +monopoly-auction-property = Auction property +monopoly-end-turn = End turn +monopoly-auction-bid = Place auction bid +monopoly-auction-pass = Pass in auction +monopoly-mortgage-property = Mortgage property +monopoly-unmortgage-property = Unmortgage property +monopoly-build-house = Build house or hotel +monopoly-sell-house = Sell house or hotel +monopoly-pay-bail = Pay bail +monopoly-use-jail-card = Use Get Out of Jail Free card +monopoly-pay-debt = Pay debt +monopoly-declare-bankruptcy = Declare bankruptcy +monopoly-offer-trade = Offer trade +monopoly-submit-trade-amount = Set trade amount +monopoly-accept-trade = Accept trade +monopoly-decline-trade = Decline trade +monopoly-check-assets = Check assets +monopoly-check-board = Check board + +# Prompts +monopoly-enter-auction-bid = Enter auction bid amount +monopoly-select-property-mortgage = Select a property to mortgage +monopoly-select-property-unmortgage = Select a property to unmortgage +monopoly-select-property-build = Select a property to build on +monopoly-select-property-sell = Select a property to sell from +monopoly-select-trade-offer = Select a trade offer +monopoly-enter-trade-cash = Enter the cash amount for this trade. For property swaps, use a positive amount if you pay the other player, a negative amount if they pay you, or 0. + +# Validation +monopoly-player-bankrupt-disabled = You are bankrupt. +monopoly-auction-active = Resolve the active auction first. +monopoly-resolve-property-first = Resolve the pending property decision first. +monopoly-debt-pending = Resolve the pending debt first. +monopoly-roll-not-available = Rolling is not available right now. +monopoly-roll-first = Roll first. +monopoly-no-property-to-buy = There is no property to buy right now. +monopoly-no-property-to-auction = There is no property to auction right now. +monopoly-no-debt = There is no debt to pay. +monopoly-no-auction-active = There is no auction in progress. +monopoly-auction-already-passed = You have already passed in this auction. +monopoly-not-enough-cash = You do not have enough cash. +monopoly-not-in-jail = You are not in jail. +monopoly-no-jail-card = You do not have a Get Out of Jail Free card. +monopoly-no-mortgage-options = You do not have any properties available to mortgage. +monopoly-no-unmortgage-options = You do not have any properties available to unmortgage. +monopoly-no-build-options = You do not have any properties available to build on. +monopoly-no-sell-options = You do not have any buildings available to sell. +monopoly-no-trade-options = You do not have any valid trades to offer. +monopoly-trade-pending = Resolve the pending trade first. +monopoly-no-trade-pending = There is no trade pending for you. +monopoly-trade-no-longer-valid = That trade is no longer valid. +monopoly-invalid-trade-amount = That trade amount is not a valid number. +monopoly-invalid-bid = That bid is not a valid number. +monopoly-bid-out-of-range = Bid at least { $minimum } and no more than your cash ({ $cash }). + +# Board events +monopoly-roll-result = { $player } rolled { $die1 } + { $die2 } = { $total }. +monopoly-landed = { $player } landed on { $space }. +monopoly-moved-to = { $player } moved to { $space }. +monopoly-pass-go = { $player } passed GO and collected { $amount }. +monopoly-collected = { $player } collected { $amount } for { $reason }. +monopoly-paid-bank = { $player } paid { $amount } to the bank for { $reason }. +monopoly-paid-player = { $player } paid { $amount } to { $target } for { $reason }. +monopoly-free-parking = { $player } is resting on Free Parking. +monopoly-just-visiting = { $player } is just visiting jail. +monopoly-go-to-jail = { $player } goes directly to jail. +monopoly-landed-own-property = { $player } landed on their own { $property }. + +# Properties and rent +monopoly-property-available = { $property } is unowned and costs { $price }. +monopoly-property-bought = { $player } bought { $property } for { $price }. +monopoly-completed-set = { $player } completed the { $group } set. +monopoly-mortgaged-no-rent = { $player } landed on mortgaged { $property }; no rent is due. +monopoly-property-mortgaged = { $player } mortgaged { $property } for { $amount }. +monopoly-property-unmortgaged = { $player } unmortgaged { $property } for { $amount }. +monopoly-building-built = { $player } built a { $building } on { $property } for { $amount }. Level: { $level }. +monopoly-building-sold = { $player } sold a building on { $property } for { $amount }. Level: { $level }. + +# Trades +monopoly-trade-offered = { $player } offered { $target } a trade: { $summary }. +monopoly-trade-accepted = { $target } accepted { $player }'s trade: { $summary }. +monopoly-trade-declined = { $target } declined { $player }'s trade: { $summary }. +monopoly-mortgage-transfer-interest-paid = { $player } paid { $amount } mortgage transfer interest. + +# Auctions +monopoly-auction-started = Auction started for { $property }. Minimum bid: { $amount }. +monopoly-auction-bid-placed = { $player } bid { $amount } for { $property }. +monopoly-auction-pass-event = { $player } passed on { $property }. +monopoly-auction-no-bids = No bids for { $property }. It remains unsold. +monopoly-auction-won = { $player } won { $property } for { $amount }. + +# Jail and doubles +monopoly-roll-again = { $player } rolled doubles and gets another roll. +monopoly-three-doubles-jail = { $player } rolled doubles three times and is sent to jail. +monopoly-jail-roll-doubles = { $player } rolled doubles ({ $die1 } and { $die2 }) and leaves jail. +monopoly-jail-roll-failed = { $player } rolled { $die1 } and { $die2 } in jail. Attempt { $attempts }. +monopoly-bail-paid = { $player } paid { $amount } bail. +monopoly-jail-card-used = { $player } used a Get Out of Jail Free card. + +# Cards and debt +monopoly-card-drawn = { $player } drew { $deck }: { $text } +monopoly-debt-created = { $player } owes { $amount } to { $target } for { $reason }. +monopoly-debt-can-pay = { $player } has enough cash to pay the pending debt. +monopoly-player-bankrupt = { $player } is bankrupt. Creditor: { $creditor }. +monopoly-winner = { $player } wins Monopoly with net worth { $value }. diff --git a/server/locales/sr/monopoly.ftl b/server/locales/sr/monopoly.ftl new file mode 100644 index 00000000..330c8df1 --- /dev/null +++ b/server/locales/sr/monopoly.ftl @@ -0,0 +1,116 @@ +# Monopoly game messages + +game-name-monopoly = Monopoly + +monopoly-started = Monopoly started on { $board }. Each player begins with { $cash }. +monopoly-turn = { $player }'s turn. +monopoly-in-jail-turn = { $player } is in jail. Failed roll attempts: { $turns }. + +# Actions +monopoly-roll-dice = Roll dice +monopoly-buy-property = Buy property +monopoly-auction-property = Auction property +monopoly-end-turn = End turn +monopoly-auction-bid = Place auction bid +monopoly-auction-pass = Pass in auction +monopoly-mortgage-property = Mortgage property +monopoly-unmortgage-property = Unmortgage property +monopoly-build-house = Build house or hotel +monopoly-sell-house = Sell house or hotel +monopoly-pay-bail = Pay bail +monopoly-use-jail-card = Use Get Out of Jail Free card +monopoly-pay-debt = Pay debt +monopoly-declare-bankruptcy = Declare bankruptcy +monopoly-offer-trade = Offer trade +monopoly-submit-trade-amount = Set trade amount +monopoly-accept-trade = Accept trade +monopoly-decline-trade = Decline trade +monopoly-check-assets = Check assets +monopoly-check-board = Check board + +# Prompts +monopoly-enter-auction-bid = Enter auction bid amount +monopoly-select-property-mortgage = Select a property to mortgage +monopoly-select-property-unmortgage = Select a property to unmortgage +monopoly-select-property-build = Select a property to build on +monopoly-select-property-sell = Select a property to sell from +monopoly-select-trade-offer = Select a trade offer +monopoly-enter-trade-cash = Enter the cash amount for this trade. For property swaps, use a positive amount if you pay the other player, a negative amount if they pay you, or 0. + +# Validation +monopoly-player-bankrupt-disabled = You are bankrupt. +monopoly-auction-active = Resolve the active auction first. +monopoly-resolve-property-first = Resolve the pending property decision first. +monopoly-debt-pending = Resolve the pending debt first. +monopoly-roll-not-available = Rolling is not available right now. +monopoly-roll-first = Roll first. +monopoly-no-property-to-buy = There is no property to buy right now. +monopoly-no-property-to-auction = There is no property to auction right now. +monopoly-no-debt = There is no debt to pay. +monopoly-no-auction-active = There is no auction in progress. +monopoly-auction-already-passed = You have already passed in this auction. +monopoly-not-enough-cash = You do not have enough cash. +monopoly-not-in-jail = You are not in jail. +monopoly-no-jail-card = You do not have a Get Out of Jail Free card. +monopoly-no-mortgage-options = You do not have any properties available to mortgage. +monopoly-no-unmortgage-options = You do not have any properties available to unmortgage. +monopoly-no-build-options = You do not have any properties available to build on. +monopoly-no-sell-options = You do not have any buildings available to sell. +monopoly-no-trade-options = You do not have any valid trades to offer. +monopoly-trade-pending = Resolve the pending trade first. +monopoly-no-trade-pending = There is no trade pending for you. +monopoly-trade-no-longer-valid = That trade is no longer valid. +monopoly-invalid-trade-amount = That trade amount is not a valid number. +monopoly-invalid-bid = That bid is not a valid number. +monopoly-bid-out-of-range = Bid at least { $minimum } and no more than your cash ({ $cash }). + +# Board events +monopoly-roll-result = { $player } rolled { $die1 } + { $die2 } = { $total }. +monopoly-landed = { $player } landed on { $space }. +monopoly-moved-to = { $player } moved to { $space }. +monopoly-pass-go = { $player } passed GO and collected { $amount }. +monopoly-collected = { $player } collected { $amount } for { $reason }. +monopoly-paid-bank = { $player } paid { $amount } to the bank for { $reason }. +monopoly-paid-player = { $player } paid { $amount } to { $target } for { $reason }. +monopoly-free-parking = { $player } is resting on Free Parking. +monopoly-just-visiting = { $player } is just visiting jail. +monopoly-go-to-jail = { $player } goes directly to jail. +monopoly-landed-own-property = { $player } landed on their own { $property }. + +# Properties and rent +monopoly-property-available = { $property } is unowned and costs { $price }. +monopoly-property-bought = { $player } bought { $property } for { $price }. +monopoly-completed-set = { $player } completed the { $group } set. +monopoly-mortgaged-no-rent = { $player } landed on mortgaged { $property }; no rent is due. +monopoly-property-mortgaged = { $player } mortgaged { $property } for { $amount }. +monopoly-property-unmortgaged = { $player } unmortgaged { $property } for { $amount }. +monopoly-building-built = { $player } built a { $building } on { $property } for { $amount }. Level: { $level }. +monopoly-building-sold = { $player } sold a building on { $property } for { $amount }. Level: { $level }. + +# Trades +monopoly-trade-offered = { $player } offered { $target } a trade: { $summary }. +monopoly-trade-accepted = { $target } accepted { $player }'s trade: { $summary }. +monopoly-trade-declined = { $target } declined { $player }'s trade: { $summary }. +monopoly-mortgage-transfer-interest-paid = { $player } paid { $amount } mortgage transfer interest. + +# Auctions +monopoly-auction-started = Auction started for { $property }. Minimum bid: { $amount }. +monopoly-auction-bid-placed = { $player } bid { $amount } for { $property }. +monopoly-auction-pass-event = { $player } passed on { $property }. +monopoly-auction-no-bids = No bids for { $property }. It remains unsold. +monopoly-auction-won = { $player } won { $property } for { $amount }. + +# Jail and doubles +monopoly-roll-again = { $player } rolled doubles and gets another roll. +monopoly-three-doubles-jail = { $player } rolled doubles three times and is sent to jail. +monopoly-jail-roll-doubles = { $player } rolled doubles ({ $die1 } and { $die2 }) and leaves jail. +monopoly-jail-roll-failed = { $player } rolled { $die1 } and { $die2 } in jail. Attempt { $attempts }. +monopoly-bail-paid = { $player } paid { $amount } bail. +monopoly-jail-card-used = { $player } used a Get Out of Jail Free card. + +# Cards and debt +monopoly-card-drawn = { $player } drew { $deck }: { $text } +monopoly-debt-created = { $player } owes { $amount } to { $target } for { $reason }. +monopoly-debt-can-pay = { $player } has enough cash to pay the pending debt. +monopoly-player-bankrupt = { $player } is bankrupt. Creditor: { $creditor }. +monopoly-winner = { $player } wins Monopoly with net worth { $value }. diff --git a/server/locales/sv/monopoly.ftl b/server/locales/sv/monopoly.ftl new file mode 100644 index 00000000..330c8df1 --- /dev/null +++ b/server/locales/sv/monopoly.ftl @@ -0,0 +1,116 @@ +# Monopoly game messages + +game-name-monopoly = Monopoly + +monopoly-started = Monopoly started on { $board }. Each player begins with { $cash }. +monopoly-turn = { $player }'s turn. +monopoly-in-jail-turn = { $player } is in jail. Failed roll attempts: { $turns }. + +# Actions +monopoly-roll-dice = Roll dice +monopoly-buy-property = Buy property +monopoly-auction-property = Auction property +monopoly-end-turn = End turn +monopoly-auction-bid = Place auction bid +monopoly-auction-pass = Pass in auction +monopoly-mortgage-property = Mortgage property +monopoly-unmortgage-property = Unmortgage property +monopoly-build-house = Build house or hotel +monopoly-sell-house = Sell house or hotel +monopoly-pay-bail = Pay bail +monopoly-use-jail-card = Use Get Out of Jail Free card +monopoly-pay-debt = Pay debt +monopoly-declare-bankruptcy = Declare bankruptcy +monopoly-offer-trade = Offer trade +monopoly-submit-trade-amount = Set trade amount +monopoly-accept-trade = Accept trade +monopoly-decline-trade = Decline trade +monopoly-check-assets = Check assets +monopoly-check-board = Check board + +# Prompts +monopoly-enter-auction-bid = Enter auction bid amount +monopoly-select-property-mortgage = Select a property to mortgage +monopoly-select-property-unmortgage = Select a property to unmortgage +monopoly-select-property-build = Select a property to build on +monopoly-select-property-sell = Select a property to sell from +monopoly-select-trade-offer = Select a trade offer +monopoly-enter-trade-cash = Enter the cash amount for this trade. For property swaps, use a positive amount if you pay the other player, a negative amount if they pay you, or 0. + +# Validation +monopoly-player-bankrupt-disabled = You are bankrupt. +monopoly-auction-active = Resolve the active auction first. +monopoly-resolve-property-first = Resolve the pending property decision first. +monopoly-debt-pending = Resolve the pending debt first. +monopoly-roll-not-available = Rolling is not available right now. +monopoly-roll-first = Roll first. +monopoly-no-property-to-buy = There is no property to buy right now. +monopoly-no-property-to-auction = There is no property to auction right now. +monopoly-no-debt = There is no debt to pay. +monopoly-no-auction-active = There is no auction in progress. +monopoly-auction-already-passed = You have already passed in this auction. +monopoly-not-enough-cash = You do not have enough cash. +monopoly-not-in-jail = You are not in jail. +monopoly-no-jail-card = You do not have a Get Out of Jail Free card. +monopoly-no-mortgage-options = You do not have any properties available to mortgage. +monopoly-no-unmortgage-options = You do not have any properties available to unmortgage. +monopoly-no-build-options = You do not have any properties available to build on. +monopoly-no-sell-options = You do not have any buildings available to sell. +monopoly-no-trade-options = You do not have any valid trades to offer. +monopoly-trade-pending = Resolve the pending trade first. +monopoly-no-trade-pending = There is no trade pending for you. +monopoly-trade-no-longer-valid = That trade is no longer valid. +monopoly-invalid-trade-amount = That trade amount is not a valid number. +monopoly-invalid-bid = That bid is not a valid number. +monopoly-bid-out-of-range = Bid at least { $minimum } and no more than your cash ({ $cash }). + +# Board events +monopoly-roll-result = { $player } rolled { $die1 } + { $die2 } = { $total }. +monopoly-landed = { $player } landed on { $space }. +monopoly-moved-to = { $player } moved to { $space }. +monopoly-pass-go = { $player } passed GO and collected { $amount }. +monopoly-collected = { $player } collected { $amount } for { $reason }. +monopoly-paid-bank = { $player } paid { $amount } to the bank for { $reason }. +monopoly-paid-player = { $player } paid { $amount } to { $target } for { $reason }. +monopoly-free-parking = { $player } is resting on Free Parking. +monopoly-just-visiting = { $player } is just visiting jail. +monopoly-go-to-jail = { $player } goes directly to jail. +monopoly-landed-own-property = { $player } landed on their own { $property }. + +# Properties and rent +monopoly-property-available = { $property } is unowned and costs { $price }. +monopoly-property-bought = { $player } bought { $property } for { $price }. +monopoly-completed-set = { $player } completed the { $group } set. +monopoly-mortgaged-no-rent = { $player } landed on mortgaged { $property }; no rent is due. +monopoly-property-mortgaged = { $player } mortgaged { $property } for { $amount }. +monopoly-property-unmortgaged = { $player } unmortgaged { $property } for { $amount }. +monopoly-building-built = { $player } built a { $building } on { $property } for { $amount }. Level: { $level }. +monopoly-building-sold = { $player } sold a building on { $property } for { $amount }. Level: { $level }. + +# Trades +monopoly-trade-offered = { $player } offered { $target } a trade: { $summary }. +monopoly-trade-accepted = { $target } accepted { $player }'s trade: { $summary }. +monopoly-trade-declined = { $target } declined { $player }'s trade: { $summary }. +monopoly-mortgage-transfer-interest-paid = { $player } paid { $amount } mortgage transfer interest. + +# Auctions +monopoly-auction-started = Auction started for { $property }. Minimum bid: { $amount }. +monopoly-auction-bid-placed = { $player } bid { $amount } for { $property }. +monopoly-auction-pass-event = { $player } passed on { $property }. +monopoly-auction-no-bids = No bids for { $property }. It remains unsold. +monopoly-auction-won = { $player } won { $property } for { $amount }. + +# Jail and doubles +monopoly-roll-again = { $player } rolled doubles and gets another roll. +monopoly-three-doubles-jail = { $player } rolled doubles three times and is sent to jail. +monopoly-jail-roll-doubles = { $player } rolled doubles ({ $die1 } and { $die2 }) and leaves jail. +monopoly-jail-roll-failed = { $player } rolled { $die1 } and { $die2 } in jail. Attempt { $attempts }. +monopoly-bail-paid = { $player } paid { $amount } bail. +monopoly-jail-card-used = { $player } used a Get Out of Jail Free card. + +# Cards and debt +monopoly-card-drawn = { $player } drew { $deck }: { $text } +monopoly-debt-created = { $player } owes { $amount } to { $target } for { $reason }. +monopoly-debt-can-pay = { $player } has enough cash to pay the pending debt. +monopoly-player-bankrupt = { $player } is bankrupt. Creditor: { $creditor }. +monopoly-winner = { $player } wins Monopoly with net worth { $value }. diff --git a/server/locales/th/monopoly.ftl b/server/locales/th/monopoly.ftl new file mode 100644 index 00000000..330c8df1 --- /dev/null +++ b/server/locales/th/monopoly.ftl @@ -0,0 +1,116 @@ +# Monopoly game messages + +game-name-monopoly = Monopoly + +monopoly-started = Monopoly started on { $board }. Each player begins with { $cash }. +monopoly-turn = { $player }'s turn. +monopoly-in-jail-turn = { $player } is in jail. Failed roll attempts: { $turns }. + +# Actions +monopoly-roll-dice = Roll dice +monopoly-buy-property = Buy property +monopoly-auction-property = Auction property +monopoly-end-turn = End turn +monopoly-auction-bid = Place auction bid +monopoly-auction-pass = Pass in auction +monopoly-mortgage-property = Mortgage property +monopoly-unmortgage-property = Unmortgage property +monopoly-build-house = Build house or hotel +monopoly-sell-house = Sell house or hotel +monopoly-pay-bail = Pay bail +monopoly-use-jail-card = Use Get Out of Jail Free card +monopoly-pay-debt = Pay debt +monopoly-declare-bankruptcy = Declare bankruptcy +monopoly-offer-trade = Offer trade +monopoly-submit-trade-amount = Set trade amount +monopoly-accept-trade = Accept trade +monopoly-decline-trade = Decline trade +monopoly-check-assets = Check assets +monopoly-check-board = Check board + +# Prompts +monopoly-enter-auction-bid = Enter auction bid amount +monopoly-select-property-mortgage = Select a property to mortgage +monopoly-select-property-unmortgage = Select a property to unmortgage +monopoly-select-property-build = Select a property to build on +monopoly-select-property-sell = Select a property to sell from +monopoly-select-trade-offer = Select a trade offer +monopoly-enter-trade-cash = Enter the cash amount for this trade. For property swaps, use a positive amount if you pay the other player, a negative amount if they pay you, or 0. + +# Validation +monopoly-player-bankrupt-disabled = You are bankrupt. +monopoly-auction-active = Resolve the active auction first. +monopoly-resolve-property-first = Resolve the pending property decision first. +monopoly-debt-pending = Resolve the pending debt first. +monopoly-roll-not-available = Rolling is not available right now. +monopoly-roll-first = Roll first. +monopoly-no-property-to-buy = There is no property to buy right now. +monopoly-no-property-to-auction = There is no property to auction right now. +monopoly-no-debt = There is no debt to pay. +monopoly-no-auction-active = There is no auction in progress. +monopoly-auction-already-passed = You have already passed in this auction. +monopoly-not-enough-cash = You do not have enough cash. +monopoly-not-in-jail = You are not in jail. +monopoly-no-jail-card = You do not have a Get Out of Jail Free card. +monopoly-no-mortgage-options = You do not have any properties available to mortgage. +monopoly-no-unmortgage-options = You do not have any properties available to unmortgage. +monopoly-no-build-options = You do not have any properties available to build on. +monopoly-no-sell-options = You do not have any buildings available to sell. +monopoly-no-trade-options = You do not have any valid trades to offer. +monopoly-trade-pending = Resolve the pending trade first. +monopoly-no-trade-pending = There is no trade pending for you. +monopoly-trade-no-longer-valid = That trade is no longer valid. +monopoly-invalid-trade-amount = That trade amount is not a valid number. +monopoly-invalid-bid = That bid is not a valid number. +monopoly-bid-out-of-range = Bid at least { $minimum } and no more than your cash ({ $cash }). + +# Board events +monopoly-roll-result = { $player } rolled { $die1 } + { $die2 } = { $total }. +monopoly-landed = { $player } landed on { $space }. +monopoly-moved-to = { $player } moved to { $space }. +monopoly-pass-go = { $player } passed GO and collected { $amount }. +monopoly-collected = { $player } collected { $amount } for { $reason }. +monopoly-paid-bank = { $player } paid { $amount } to the bank for { $reason }. +monopoly-paid-player = { $player } paid { $amount } to { $target } for { $reason }. +monopoly-free-parking = { $player } is resting on Free Parking. +monopoly-just-visiting = { $player } is just visiting jail. +monopoly-go-to-jail = { $player } goes directly to jail. +monopoly-landed-own-property = { $player } landed on their own { $property }. + +# Properties and rent +monopoly-property-available = { $property } is unowned and costs { $price }. +monopoly-property-bought = { $player } bought { $property } for { $price }. +monopoly-completed-set = { $player } completed the { $group } set. +monopoly-mortgaged-no-rent = { $player } landed on mortgaged { $property }; no rent is due. +monopoly-property-mortgaged = { $player } mortgaged { $property } for { $amount }. +monopoly-property-unmortgaged = { $player } unmortgaged { $property } for { $amount }. +monopoly-building-built = { $player } built a { $building } on { $property } for { $amount }. Level: { $level }. +monopoly-building-sold = { $player } sold a building on { $property } for { $amount }. Level: { $level }. + +# Trades +monopoly-trade-offered = { $player } offered { $target } a trade: { $summary }. +monopoly-trade-accepted = { $target } accepted { $player }'s trade: { $summary }. +monopoly-trade-declined = { $target } declined { $player }'s trade: { $summary }. +monopoly-mortgage-transfer-interest-paid = { $player } paid { $amount } mortgage transfer interest. + +# Auctions +monopoly-auction-started = Auction started for { $property }. Minimum bid: { $amount }. +monopoly-auction-bid-placed = { $player } bid { $amount } for { $property }. +monopoly-auction-pass-event = { $player } passed on { $property }. +monopoly-auction-no-bids = No bids for { $property }. It remains unsold. +monopoly-auction-won = { $player } won { $property } for { $amount }. + +# Jail and doubles +monopoly-roll-again = { $player } rolled doubles and gets another roll. +monopoly-three-doubles-jail = { $player } rolled doubles three times and is sent to jail. +monopoly-jail-roll-doubles = { $player } rolled doubles ({ $die1 } and { $die2 }) and leaves jail. +monopoly-jail-roll-failed = { $player } rolled { $die1 } and { $die2 } in jail. Attempt { $attempts }. +monopoly-bail-paid = { $player } paid { $amount } bail. +monopoly-jail-card-used = { $player } used a Get Out of Jail Free card. + +# Cards and debt +monopoly-card-drawn = { $player } drew { $deck }: { $text } +monopoly-debt-created = { $player } owes { $amount } to { $target } for { $reason }. +monopoly-debt-can-pay = { $player } has enough cash to pay the pending debt. +monopoly-player-bankrupt = { $player } is bankrupt. Creditor: { $creditor }. +monopoly-winner = { $player } wins Monopoly with net worth { $value }. diff --git a/server/locales/tr/monopoly.ftl b/server/locales/tr/monopoly.ftl new file mode 100644 index 00000000..330c8df1 --- /dev/null +++ b/server/locales/tr/monopoly.ftl @@ -0,0 +1,116 @@ +# Monopoly game messages + +game-name-monopoly = Monopoly + +monopoly-started = Monopoly started on { $board }. Each player begins with { $cash }. +monopoly-turn = { $player }'s turn. +monopoly-in-jail-turn = { $player } is in jail. Failed roll attempts: { $turns }. + +# Actions +monopoly-roll-dice = Roll dice +monopoly-buy-property = Buy property +monopoly-auction-property = Auction property +monopoly-end-turn = End turn +monopoly-auction-bid = Place auction bid +monopoly-auction-pass = Pass in auction +monopoly-mortgage-property = Mortgage property +monopoly-unmortgage-property = Unmortgage property +monopoly-build-house = Build house or hotel +monopoly-sell-house = Sell house or hotel +monopoly-pay-bail = Pay bail +monopoly-use-jail-card = Use Get Out of Jail Free card +monopoly-pay-debt = Pay debt +monopoly-declare-bankruptcy = Declare bankruptcy +monopoly-offer-trade = Offer trade +monopoly-submit-trade-amount = Set trade amount +monopoly-accept-trade = Accept trade +monopoly-decline-trade = Decline trade +monopoly-check-assets = Check assets +monopoly-check-board = Check board + +# Prompts +monopoly-enter-auction-bid = Enter auction bid amount +monopoly-select-property-mortgage = Select a property to mortgage +monopoly-select-property-unmortgage = Select a property to unmortgage +monopoly-select-property-build = Select a property to build on +monopoly-select-property-sell = Select a property to sell from +monopoly-select-trade-offer = Select a trade offer +monopoly-enter-trade-cash = Enter the cash amount for this trade. For property swaps, use a positive amount if you pay the other player, a negative amount if they pay you, or 0. + +# Validation +monopoly-player-bankrupt-disabled = You are bankrupt. +monopoly-auction-active = Resolve the active auction first. +monopoly-resolve-property-first = Resolve the pending property decision first. +monopoly-debt-pending = Resolve the pending debt first. +monopoly-roll-not-available = Rolling is not available right now. +monopoly-roll-first = Roll first. +monopoly-no-property-to-buy = There is no property to buy right now. +monopoly-no-property-to-auction = There is no property to auction right now. +monopoly-no-debt = There is no debt to pay. +monopoly-no-auction-active = There is no auction in progress. +monopoly-auction-already-passed = You have already passed in this auction. +monopoly-not-enough-cash = You do not have enough cash. +monopoly-not-in-jail = You are not in jail. +monopoly-no-jail-card = You do not have a Get Out of Jail Free card. +monopoly-no-mortgage-options = You do not have any properties available to mortgage. +monopoly-no-unmortgage-options = You do not have any properties available to unmortgage. +monopoly-no-build-options = You do not have any properties available to build on. +monopoly-no-sell-options = You do not have any buildings available to sell. +monopoly-no-trade-options = You do not have any valid trades to offer. +monopoly-trade-pending = Resolve the pending trade first. +monopoly-no-trade-pending = There is no trade pending for you. +monopoly-trade-no-longer-valid = That trade is no longer valid. +monopoly-invalid-trade-amount = That trade amount is not a valid number. +monopoly-invalid-bid = That bid is not a valid number. +monopoly-bid-out-of-range = Bid at least { $minimum } and no more than your cash ({ $cash }). + +# Board events +monopoly-roll-result = { $player } rolled { $die1 } + { $die2 } = { $total }. +monopoly-landed = { $player } landed on { $space }. +monopoly-moved-to = { $player } moved to { $space }. +monopoly-pass-go = { $player } passed GO and collected { $amount }. +monopoly-collected = { $player } collected { $amount } for { $reason }. +monopoly-paid-bank = { $player } paid { $amount } to the bank for { $reason }. +monopoly-paid-player = { $player } paid { $amount } to { $target } for { $reason }. +monopoly-free-parking = { $player } is resting on Free Parking. +monopoly-just-visiting = { $player } is just visiting jail. +monopoly-go-to-jail = { $player } goes directly to jail. +monopoly-landed-own-property = { $player } landed on their own { $property }. + +# Properties and rent +monopoly-property-available = { $property } is unowned and costs { $price }. +monopoly-property-bought = { $player } bought { $property } for { $price }. +monopoly-completed-set = { $player } completed the { $group } set. +monopoly-mortgaged-no-rent = { $player } landed on mortgaged { $property }; no rent is due. +monopoly-property-mortgaged = { $player } mortgaged { $property } for { $amount }. +monopoly-property-unmortgaged = { $player } unmortgaged { $property } for { $amount }. +monopoly-building-built = { $player } built a { $building } on { $property } for { $amount }. Level: { $level }. +monopoly-building-sold = { $player } sold a building on { $property } for { $amount }. Level: { $level }. + +# Trades +monopoly-trade-offered = { $player } offered { $target } a trade: { $summary }. +monopoly-trade-accepted = { $target } accepted { $player }'s trade: { $summary }. +monopoly-trade-declined = { $target } declined { $player }'s trade: { $summary }. +monopoly-mortgage-transfer-interest-paid = { $player } paid { $amount } mortgage transfer interest. + +# Auctions +monopoly-auction-started = Auction started for { $property }. Minimum bid: { $amount }. +monopoly-auction-bid-placed = { $player } bid { $amount } for { $property }. +monopoly-auction-pass-event = { $player } passed on { $property }. +monopoly-auction-no-bids = No bids for { $property }. It remains unsold. +monopoly-auction-won = { $player } won { $property } for { $amount }. + +# Jail and doubles +monopoly-roll-again = { $player } rolled doubles and gets another roll. +monopoly-three-doubles-jail = { $player } rolled doubles three times and is sent to jail. +monopoly-jail-roll-doubles = { $player } rolled doubles ({ $die1 } and { $die2 }) and leaves jail. +monopoly-jail-roll-failed = { $player } rolled { $die1 } and { $die2 } in jail. Attempt { $attempts }. +monopoly-bail-paid = { $player } paid { $amount } bail. +monopoly-jail-card-used = { $player } used a Get Out of Jail Free card. + +# Cards and debt +monopoly-card-drawn = { $player } drew { $deck }: { $text } +monopoly-debt-created = { $player } owes { $amount } to { $target } for { $reason }. +monopoly-debt-can-pay = { $player } has enough cash to pay the pending debt. +monopoly-player-bankrupt = { $player } is bankrupt. Creditor: { $creditor }. +monopoly-winner = { $player } wins Monopoly with net worth { $value }. diff --git a/server/locales/uk/monopoly.ftl b/server/locales/uk/monopoly.ftl new file mode 100644 index 00000000..330c8df1 --- /dev/null +++ b/server/locales/uk/monopoly.ftl @@ -0,0 +1,116 @@ +# Monopoly game messages + +game-name-monopoly = Monopoly + +monopoly-started = Monopoly started on { $board }. Each player begins with { $cash }. +monopoly-turn = { $player }'s turn. +monopoly-in-jail-turn = { $player } is in jail. Failed roll attempts: { $turns }. + +# Actions +monopoly-roll-dice = Roll dice +monopoly-buy-property = Buy property +monopoly-auction-property = Auction property +monopoly-end-turn = End turn +monopoly-auction-bid = Place auction bid +monopoly-auction-pass = Pass in auction +monopoly-mortgage-property = Mortgage property +monopoly-unmortgage-property = Unmortgage property +monopoly-build-house = Build house or hotel +monopoly-sell-house = Sell house or hotel +monopoly-pay-bail = Pay bail +monopoly-use-jail-card = Use Get Out of Jail Free card +monopoly-pay-debt = Pay debt +monopoly-declare-bankruptcy = Declare bankruptcy +monopoly-offer-trade = Offer trade +monopoly-submit-trade-amount = Set trade amount +monopoly-accept-trade = Accept trade +monopoly-decline-trade = Decline trade +monopoly-check-assets = Check assets +monopoly-check-board = Check board + +# Prompts +monopoly-enter-auction-bid = Enter auction bid amount +monopoly-select-property-mortgage = Select a property to mortgage +monopoly-select-property-unmortgage = Select a property to unmortgage +monopoly-select-property-build = Select a property to build on +monopoly-select-property-sell = Select a property to sell from +monopoly-select-trade-offer = Select a trade offer +monopoly-enter-trade-cash = Enter the cash amount for this trade. For property swaps, use a positive amount if you pay the other player, a negative amount if they pay you, or 0. + +# Validation +monopoly-player-bankrupt-disabled = You are bankrupt. +monopoly-auction-active = Resolve the active auction first. +monopoly-resolve-property-first = Resolve the pending property decision first. +monopoly-debt-pending = Resolve the pending debt first. +monopoly-roll-not-available = Rolling is not available right now. +monopoly-roll-first = Roll first. +monopoly-no-property-to-buy = There is no property to buy right now. +monopoly-no-property-to-auction = There is no property to auction right now. +monopoly-no-debt = There is no debt to pay. +monopoly-no-auction-active = There is no auction in progress. +monopoly-auction-already-passed = You have already passed in this auction. +monopoly-not-enough-cash = You do not have enough cash. +monopoly-not-in-jail = You are not in jail. +monopoly-no-jail-card = You do not have a Get Out of Jail Free card. +monopoly-no-mortgage-options = You do not have any properties available to mortgage. +monopoly-no-unmortgage-options = You do not have any properties available to unmortgage. +monopoly-no-build-options = You do not have any properties available to build on. +monopoly-no-sell-options = You do not have any buildings available to sell. +monopoly-no-trade-options = You do not have any valid trades to offer. +monopoly-trade-pending = Resolve the pending trade first. +monopoly-no-trade-pending = There is no trade pending for you. +monopoly-trade-no-longer-valid = That trade is no longer valid. +monopoly-invalid-trade-amount = That trade amount is not a valid number. +monopoly-invalid-bid = That bid is not a valid number. +monopoly-bid-out-of-range = Bid at least { $minimum } and no more than your cash ({ $cash }). + +# Board events +monopoly-roll-result = { $player } rolled { $die1 } + { $die2 } = { $total }. +monopoly-landed = { $player } landed on { $space }. +monopoly-moved-to = { $player } moved to { $space }. +monopoly-pass-go = { $player } passed GO and collected { $amount }. +monopoly-collected = { $player } collected { $amount } for { $reason }. +monopoly-paid-bank = { $player } paid { $amount } to the bank for { $reason }. +monopoly-paid-player = { $player } paid { $amount } to { $target } for { $reason }. +monopoly-free-parking = { $player } is resting on Free Parking. +monopoly-just-visiting = { $player } is just visiting jail. +monopoly-go-to-jail = { $player } goes directly to jail. +monopoly-landed-own-property = { $player } landed on their own { $property }. + +# Properties and rent +monopoly-property-available = { $property } is unowned and costs { $price }. +monopoly-property-bought = { $player } bought { $property } for { $price }. +monopoly-completed-set = { $player } completed the { $group } set. +monopoly-mortgaged-no-rent = { $player } landed on mortgaged { $property }; no rent is due. +monopoly-property-mortgaged = { $player } mortgaged { $property } for { $amount }. +monopoly-property-unmortgaged = { $player } unmortgaged { $property } for { $amount }. +monopoly-building-built = { $player } built a { $building } on { $property } for { $amount }. Level: { $level }. +monopoly-building-sold = { $player } sold a building on { $property } for { $amount }. Level: { $level }. + +# Trades +monopoly-trade-offered = { $player } offered { $target } a trade: { $summary }. +monopoly-trade-accepted = { $target } accepted { $player }'s trade: { $summary }. +monopoly-trade-declined = { $target } declined { $player }'s trade: { $summary }. +monopoly-mortgage-transfer-interest-paid = { $player } paid { $amount } mortgage transfer interest. + +# Auctions +monopoly-auction-started = Auction started for { $property }. Minimum bid: { $amount }. +monopoly-auction-bid-placed = { $player } bid { $amount } for { $property }. +monopoly-auction-pass-event = { $player } passed on { $property }. +monopoly-auction-no-bids = No bids for { $property }. It remains unsold. +monopoly-auction-won = { $player } won { $property } for { $amount }. + +# Jail and doubles +monopoly-roll-again = { $player } rolled doubles and gets another roll. +monopoly-three-doubles-jail = { $player } rolled doubles three times and is sent to jail. +monopoly-jail-roll-doubles = { $player } rolled doubles ({ $die1 } and { $die2 }) and leaves jail. +monopoly-jail-roll-failed = { $player } rolled { $die1 } and { $die2 } in jail. Attempt { $attempts }. +monopoly-bail-paid = { $player } paid { $amount } bail. +monopoly-jail-card-used = { $player } used a Get Out of Jail Free card. + +# Cards and debt +monopoly-card-drawn = { $player } drew { $deck }: { $text } +monopoly-debt-created = { $player } owes { $amount } to { $target } for { $reason }. +monopoly-debt-can-pay = { $player } has enough cash to pay the pending debt. +monopoly-player-bankrupt = { $player } is bankrupt. Creditor: { $creditor }. +monopoly-winner = { $player } wins Monopoly with net worth { $value }. diff --git a/server/locales/vi/monopoly.ftl b/server/locales/vi/monopoly.ftl new file mode 100644 index 00000000..330c8df1 --- /dev/null +++ b/server/locales/vi/monopoly.ftl @@ -0,0 +1,116 @@ +# Monopoly game messages + +game-name-monopoly = Monopoly + +monopoly-started = Monopoly started on { $board }. Each player begins with { $cash }. +monopoly-turn = { $player }'s turn. +monopoly-in-jail-turn = { $player } is in jail. Failed roll attempts: { $turns }. + +# Actions +monopoly-roll-dice = Roll dice +monopoly-buy-property = Buy property +monopoly-auction-property = Auction property +monopoly-end-turn = End turn +monopoly-auction-bid = Place auction bid +monopoly-auction-pass = Pass in auction +monopoly-mortgage-property = Mortgage property +monopoly-unmortgage-property = Unmortgage property +monopoly-build-house = Build house or hotel +monopoly-sell-house = Sell house or hotel +monopoly-pay-bail = Pay bail +monopoly-use-jail-card = Use Get Out of Jail Free card +monopoly-pay-debt = Pay debt +monopoly-declare-bankruptcy = Declare bankruptcy +monopoly-offer-trade = Offer trade +monopoly-submit-trade-amount = Set trade amount +monopoly-accept-trade = Accept trade +monopoly-decline-trade = Decline trade +monopoly-check-assets = Check assets +monopoly-check-board = Check board + +# Prompts +monopoly-enter-auction-bid = Enter auction bid amount +monopoly-select-property-mortgage = Select a property to mortgage +monopoly-select-property-unmortgage = Select a property to unmortgage +monopoly-select-property-build = Select a property to build on +monopoly-select-property-sell = Select a property to sell from +monopoly-select-trade-offer = Select a trade offer +monopoly-enter-trade-cash = Enter the cash amount for this trade. For property swaps, use a positive amount if you pay the other player, a negative amount if they pay you, or 0. + +# Validation +monopoly-player-bankrupt-disabled = You are bankrupt. +monopoly-auction-active = Resolve the active auction first. +monopoly-resolve-property-first = Resolve the pending property decision first. +monopoly-debt-pending = Resolve the pending debt first. +monopoly-roll-not-available = Rolling is not available right now. +monopoly-roll-first = Roll first. +monopoly-no-property-to-buy = There is no property to buy right now. +monopoly-no-property-to-auction = There is no property to auction right now. +monopoly-no-debt = There is no debt to pay. +monopoly-no-auction-active = There is no auction in progress. +monopoly-auction-already-passed = You have already passed in this auction. +monopoly-not-enough-cash = You do not have enough cash. +monopoly-not-in-jail = You are not in jail. +monopoly-no-jail-card = You do not have a Get Out of Jail Free card. +monopoly-no-mortgage-options = You do not have any properties available to mortgage. +monopoly-no-unmortgage-options = You do not have any properties available to unmortgage. +monopoly-no-build-options = You do not have any properties available to build on. +monopoly-no-sell-options = You do not have any buildings available to sell. +monopoly-no-trade-options = You do not have any valid trades to offer. +monopoly-trade-pending = Resolve the pending trade first. +monopoly-no-trade-pending = There is no trade pending for you. +monopoly-trade-no-longer-valid = That trade is no longer valid. +monopoly-invalid-trade-amount = That trade amount is not a valid number. +monopoly-invalid-bid = That bid is not a valid number. +monopoly-bid-out-of-range = Bid at least { $minimum } and no more than your cash ({ $cash }). + +# Board events +monopoly-roll-result = { $player } rolled { $die1 } + { $die2 } = { $total }. +monopoly-landed = { $player } landed on { $space }. +monopoly-moved-to = { $player } moved to { $space }. +monopoly-pass-go = { $player } passed GO and collected { $amount }. +monopoly-collected = { $player } collected { $amount } for { $reason }. +monopoly-paid-bank = { $player } paid { $amount } to the bank for { $reason }. +monopoly-paid-player = { $player } paid { $amount } to { $target } for { $reason }. +monopoly-free-parking = { $player } is resting on Free Parking. +monopoly-just-visiting = { $player } is just visiting jail. +monopoly-go-to-jail = { $player } goes directly to jail. +monopoly-landed-own-property = { $player } landed on their own { $property }. + +# Properties and rent +monopoly-property-available = { $property } is unowned and costs { $price }. +monopoly-property-bought = { $player } bought { $property } for { $price }. +monopoly-completed-set = { $player } completed the { $group } set. +monopoly-mortgaged-no-rent = { $player } landed on mortgaged { $property }; no rent is due. +monopoly-property-mortgaged = { $player } mortgaged { $property } for { $amount }. +monopoly-property-unmortgaged = { $player } unmortgaged { $property } for { $amount }. +monopoly-building-built = { $player } built a { $building } on { $property } for { $amount }. Level: { $level }. +monopoly-building-sold = { $player } sold a building on { $property } for { $amount }. Level: { $level }. + +# Trades +monopoly-trade-offered = { $player } offered { $target } a trade: { $summary }. +monopoly-trade-accepted = { $target } accepted { $player }'s trade: { $summary }. +monopoly-trade-declined = { $target } declined { $player }'s trade: { $summary }. +monopoly-mortgage-transfer-interest-paid = { $player } paid { $amount } mortgage transfer interest. + +# Auctions +monopoly-auction-started = Auction started for { $property }. Minimum bid: { $amount }. +monopoly-auction-bid-placed = { $player } bid { $amount } for { $property }. +monopoly-auction-pass-event = { $player } passed on { $property }. +monopoly-auction-no-bids = No bids for { $property }. It remains unsold. +monopoly-auction-won = { $player } won { $property } for { $amount }. + +# Jail and doubles +monopoly-roll-again = { $player } rolled doubles and gets another roll. +monopoly-three-doubles-jail = { $player } rolled doubles three times and is sent to jail. +monopoly-jail-roll-doubles = { $player } rolled doubles ({ $die1 } and { $die2 }) and leaves jail. +monopoly-jail-roll-failed = { $player } rolled { $die1 } and { $die2 } in jail. Attempt { $attempts }. +monopoly-bail-paid = { $player } paid { $amount } bail. +monopoly-jail-card-used = { $player } used a Get Out of Jail Free card. + +# Cards and debt +monopoly-card-drawn = { $player } drew { $deck }: { $text } +monopoly-debt-created = { $player } owes { $amount } to { $target } for { $reason }. +monopoly-debt-can-pay = { $player } has enough cash to pay the pending debt. +monopoly-player-bankrupt = { $player } is bankrupt. Creditor: { $creditor }. +monopoly-winner = { $player } wins Monopoly with net worth { $value }. diff --git a/server/locales/zh/monopoly.ftl b/server/locales/zh/monopoly.ftl new file mode 100644 index 00000000..330c8df1 --- /dev/null +++ b/server/locales/zh/monopoly.ftl @@ -0,0 +1,116 @@ +# Monopoly game messages + +game-name-monopoly = Monopoly + +monopoly-started = Monopoly started on { $board }. Each player begins with { $cash }. +monopoly-turn = { $player }'s turn. +monopoly-in-jail-turn = { $player } is in jail. Failed roll attempts: { $turns }. + +# Actions +monopoly-roll-dice = Roll dice +monopoly-buy-property = Buy property +monopoly-auction-property = Auction property +monopoly-end-turn = End turn +monopoly-auction-bid = Place auction bid +monopoly-auction-pass = Pass in auction +monopoly-mortgage-property = Mortgage property +monopoly-unmortgage-property = Unmortgage property +monopoly-build-house = Build house or hotel +monopoly-sell-house = Sell house or hotel +monopoly-pay-bail = Pay bail +monopoly-use-jail-card = Use Get Out of Jail Free card +monopoly-pay-debt = Pay debt +monopoly-declare-bankruptcy = Declare bankruptcy +monopoly-offer-trade = Offer trade +monopoly-submit-trade-amount = Set trade amount +monopoly-accept-trade = Accept trade +monopoly-decline-trade = Decline trade +monopoly-check-assets = Check assets +monopoly-check-board = Check board + +# Prompts +monopoly-enter-auction-bid = Enter auction bid amount +monopoly-select-property-mortgage = Select a property to mortgage +monopoly-select-property-unmortgage = Select a property to unmortgage +monopoly-select-property-build = Select a property to build on +monopoly-select-property-sell = Select a property to sell from +monopoly-select-trade-offer = Select a trade offer +monopoly-enter-trade-cash = Enter the cash amount for this trade. For property swaps, use a positive amount if you pay the other player, a negative amount if they pay you, or 0. + +# Validation +monopoly-player-bankrupt-disabled = You are bankrupt. +monopoly-auction-active = Resolve the active auction first. +monopoly-resolve-property-first = Resolve the pending property decision first. +monopoly-debt-pending = Resolve the pending debt first. +monopoly-roll-not-available = Rolling is not available right now. +monopoly-roll-first = Roll first. +monopoly-no-property-to-buy = There is no property to buy right now. +monopoly-no-property-to-auction = There is no property to auction right now. +monopoly-no-debt = There is no debt to pay. +monopoly-no-auction-active = There is no auction in progress. +monopoly-auction-already-passed = You have already passed in this auction. +monopoly-not-enough-cash = You do not have enough cash. +monopoly-not-in-jail = You are not in jail. +monopoly-no-jail-card = You do not have a Get Out of Jail Free card. +monopoly-no-mortgage-options = You do not have any properties available to mortgage. +monopoly-no-unmortgage-options = You do not have any properties available to unmortgage. +monopoly-no-build-options = You do not have any properties available to build on. +monopoly-no-sell-options = You do not have any buildings available to sell. +monopoly-no-trade-options = You do not have any valid trades to offer. +monopoly-trade-pending = Resolve the pending trade first. +monopoly-no-trade-pending = There is no trade pending for you. +monopoly-trade-no-longer-valid = That trade is no longer valid. +monopoly-invalid-trade-amount = That trade amount is not a valid number. +monopoly-invalid-bid = That bid is not a valid number. +monopoly-bid-out-of-range = Bid at least { $minimum } and no more than your cash ({ $cash }). + +# Board events +monopoly-roll-result = { $player } rolled { $die1 } + { $die2 } = { $total }. +monopoly-landed = { $player } landed on { $space }. +monopoly-moved-to = { $player } moved to { $space }. +monopoly-pass-go = { $player } passed GO and collected { $amount }. +monopoly-collected = { $player } collected { $amount } for { $reason }. +monopoly-paid-bank = { $player } paid { $amount } to the bank for { $reason }. +monopoly-paid-player = { $player } paid { $amount } to { $target } for { $reason }. +monopoly-free-parking = { $player } is resting on Free Parking. +monopoly-just-visiting = { $player } is just visiting jail. +monopoly-go-to-jail = { $player } goes directly to jail. +monopoly-landed-own-property = { $player } landed on their own { $property }. + +# Properties and rent +monopoly-property-available = { $property } is unowned and costs { $price }. +monopoly-property-bought = { $player } bought { $property } for { $price }. +monopoly-completed-set = { $player } completed the { $group } set. +monopoly-mortgaged-no-rent = { $player } landed on mortgaged { $property }; no rent is due. +monopoly-property-mortgaged = { $player } mortgaged { $property } for { $amount }. +monopoly-property-unmortgaged = { $player } unmortgaged { $property } for { $amount }. +monopoly-building-built = { $player } built a { $building } on { $property } for { $amount }. Level: { $level }. +monopoly-building-sold = { $player } sold a building on { $property } for { $amount }. Level: { $level }. + +# Trades +monopoly-trade-offered = { $player } offered { $target } a trade: { $summary }. +monopoly-trade-accepted = { $target } accepted { $player }'s trade: { $summary }. +monopoly-trade-declined = { $target } declined { $player }'s trade: { $summary }. +monopoly-mortgage-transfer-interest-paid = { $player } paid { $amount } mortgage transfer interest. + +# Auctions +monopoly-auction-started = Auction started for { $property }. Minimum bid: { $amount }. +monopoly-auction-bid-placed = { $player } bid { $amount } for { $property }. +monopoly-auction-pass-event = { $player } passed on { $property }. +monopoly-auction-no-bids = No bids for { $property }. It remains unsold. +monopoly-auction-won = { $player } won { $property } for { $amount }. + +# Jail and doubles +monopoly-roll-again = { $player } rolled doubles and gets another roll. +monopoly-three-doubles-jail = { $player } rolled doubles three times and is sent to jail. +monopoly-jail-roll-doubles = { $player } rolled doubles ({ $die1 } and { $die2 }) and leaves jail. +monopoly-jail-roll-failed = { $player } rolled { $die1 } and { $die2 } in jail. Attempt { $attempts }. +monopoly-bail-paid = { $player } paid { $amount } bail. +monopoly-jail-card-used = { $player } used a Get Out of Jail Free card. + +# Cards and debt +monopoly-card-drawn = { $player } drew { $deck }: { $text } +monopoly-debt-created = { $player } owes { $amount } to { $target } for { $reason }. +monopoly-debt-can-pay = { $player } has enough cash to pay the pending debt. +monopoly-player-bankrupt = { $player } is bankrupt. Creditor: { $creditor }. +monopoly-winner = { $player } wins Monopoly with net worth { $value }. diff --git a/server/locales/zu/monopoly.ftl b/server/locales/zu/monopoly.ftl new file mode 100644 index 00000000..330c8df1 --- /dev/null +++ b/server/locales/zu/monopoly.ftl @@ -0,0 +1,116 @@ +# Monopoly game messages + +game-name-monopoly = Monopoly + +monopoly-started = Monopoly started on { $board }. Each player begins with { $cash }. +monopoly-turn = { $player }'s turn. +monopoly-in-jail-turn = { $player } is in jail. Failed roll attempts: { $turns }. + +# Actions +monopoly-roll-dice = Roll dice +monopoly-buy-property = Buy property +monopoly-auction-property = Auction property +monopoly-end-turn = End turn +monopoly-auction-bid = Place auction bid +monopoly-auction-pass = Pass in auction +monopoly-mortgage-property = Mortgage property +monopoly-unmortgage-property = Unmortgage property +monopoly-build-house = Build house or hotel +monopoly-sell-house = Sell house or hotel +monopoly-pay-bail = Pay bail +monopoly-use-jail-card = Use Get Out of Jail Free card +monopoly-pay-debt = Pay debt +monopoly-declare-bankruptcy = Declare bankruptcy +monopoly-offer-trade = Offer trade +monopoly-submit-trade-amount = Set trade amount +monopoly-accept-trade = Accept trade +monopoly-decline-trade = Decline trade +monopoly-check-assets = Check assets +monopoly-check-board = Check board + +# Prompts +monopoly-enter-auction-bid = Enter auction bid amount +monopoly-select-property-mortgage = Select a property to mortgage +monopoly-select-property-unmortgage = Select a property to unmortgage +monopoly-select-property-build = Select a property to build on +monopoly-select-property-sell = Select a property to sell from +monopoly-select-trade-offer = Select a trade offer +monopoly-enter-trade-cash = Enter the cash amount for this trade. For property swaps, use a positive amount if you pay the other player, a negative amount if they pay you, or 0. + +# Validation +monopoly-player-bankrupt-disabled = You are bankrupt. +monopoly-auction-active = Resolve the active auction first. +monopoly-resolve-property-first = Resolve the pending property decision first. +monopoly-debt-pending = Resolve the pending debt first. +monopoly-roll-not-available = Rolling is not available right now. +monopoly-roll-first = Roll first. +monopoly-no-property-to-buy = There is no property to buy right now. +monopoly-no-property-to-auction = There is no property to auction right now. +monopoly-no-debt = There is no debt to pay. +monopoly-no-auction-active = There is no auction in progress. +monopoly-auction-already-passed = You have already passed in this auction. +monopoly-not-enough-cash = You do not have enough cash. +monopoly-not-in-jail = You are not in jail. +monopoly-no-jail-card = You do not have a Get Out of Jail Free card. +monopoly-no-mortgage-options = You do not have any properties available to mortgage. +monopoly-no-unmortgage-options = You do not have any properties available to unmortgage. +monopoly-no-build-options = You do not have any properties available to build on. +monopoly-no-sell-options = You do not have any buildings available to sell. +monopoly-no-trade-options = You do not have any valid trades to offer. +monopoly-trade-pending = Resolve the pending trade first. +monopoly-no-trade-pending = There is no trade pending for you. +monopoly-trade-no-longer-valid = That trade is no longer valid. +monopoly-invalid-trade-amount = That trade amount is not a valid number. +monopoly-invalid-bid = That bid is not a valid number. +monopoly-bid-out-of-range = Bid at least { $minimum } and no more than your cash ({ $cash }). + +# Board events +monopoly-roll-result = { $player } rolled { $die1 } + { $die2 } = { $total }. +monopoly-landed = { $player } landed on { $space }. +monopoly-moved-to = { $player } moved to { $space }. +monopoly-pass-go = { $player } passed GO and collected { $amount }. +monopoly-collected = { $player } collected { $amount } for { $reason }. +monopoly-paid-bank = { $player } paid { $amount } to the bank for { $reason }. +monopoly-paid-player = { $player } paid { $amount } to { $target } for { $reason }. +monopoly-free-parking = { $player } is resting on Free Parking. +monopoly-just-visiting = { $player } is just visiting jail. +monopoly-go-to-jail = { $player } goes directly to jail. +monopoly-landed-own-property = { $player } landed on their own { $property }. + +# Properties and rent +monopoly-property-available = { $property } is unowned and costs { $price }. +monopoly-property-bought = { $player } bought { $property } for { $price }. +monopoly-completed-set = { $player } completed the { $group } set. +monopoly-mortgaged-no-rent = { $player } landed on mortgaged { $property }; no rent is due. +monopoly-property-mortgaged = { $player } mortgaged { $property } for { $amount }. +monopoly-property-unmortgaged = { $player } unmortgaged { $property } for { $amount }. +monopoly-building-built = { $player } built a { $building } on { $property } for { $amount }. Level: { $level }. +monopoly-building-sold = { $player } sold a building on { $property } for { $amount }. Level: { $level }. + +# Trades +monopoly-trade-offered = { $player } offered { $target } a trade: { $summary }. +monopoly-trade-accepted = { $target } accepted { $player }'s trade: { $summary }. +monopoly-trade-declined = { $target } declined { $player }'s trade: { $summary }. +monopoly-mortgage-transfer-interest-paid = { $player } paid { $amount } mortgage transfer interest. + +# Auctions +monopoly-auction-started = Auction started for { $property }. Minimum bid: { $amount }. +monopoly-auction-bid-placed = { $player } bid { $amount } for { $property }. +monopoly-auction-pass-event = { $player } passed on { $property }. +monopoly-auction-no-bids = No bids for { $property }. It remains unsold. +monopoly-auction-won = { $player } won { $property } for { $amount }. + +# Jail and doubles +monopoly-roll-again = { $player } rolled doubles and gets another roll. +monopoly-three-doubles-jail = { $player } rolled doubles three times and is sent to jail. +monopoly-jail-roll-doubles = { $player } rolled doubles ({ $die1 } and { $die2 }) and leaves jail. +monopoly-jail-roll-failed = { $player } rolled { $die1 } and { $die2 } in jail. Attempt { $attempts }. +monopoly-bail-paid = { $player } paid { $amount } bail. +monopoly-jail-card-used = { $player } used a Get Out of Jail Free card. + +# Cards and debt +monopoly-card-drawn = { $player } drew { $deck }: { $text } +monopoly-debt-created = { $player } owes { $amount } to { $target } for { $reason }. +monopoly-debt-can-pay = { $player } has enough cash to pay the pending debt. +monopoly-player-bankrupt = { $player } is bankrupt. Creditor: { $creditor }. +monopoly-winner = { $player } wins Monopoly with net worth { $value }. diff --git a/server/tests/test_monopoly.py b/server/tests/test_monopoly.py new file mode 100644 index 00000000..54885f39 --- /dev/null +++ b/server/tests/test_monopoly.py @@ -0,0 +1,518 @@ +"""Tests for the classic Monopoly implementation.""" + +from server.core.users.bot import Bot +from server.core.users.test_user import MockUser +from server.games.registry import GameRegistry +from server.games.monopoly.board import CHANCE_CARD_IDS, COMMUNITY_CHEST_CARD_IDS, get_board +from server.games.monopoly.game import MonopolyGame, MonopolyPlayer + + +def make_game() -> tuple[MonopolyGame, MonopolyPlayer, MonopolyPlayer]: + game = MonopolyGame() + alice = game.add_player("Alice", MockUser("Alice")) + bob = game.add_player("Bob", MockUser("Bob")) + game.on_start() + game.reset_turn_order() + return game, alice, bob # type: ignore[return-value] + + +def test_classic_board_definition_has_expected_shape(): + board = get_board() + + assert board.name == "Classic Monopoly" + assert len(board.spaces) == 40 + assert len(board.purchasable_spaces) == 28 + assert len(CHANCE_CARD_IDS) == 16 + assert len(COMMUNITY_CHEST_CARD_IDS) == 16 + assert board.get_space("boardwalk").price == 400 + assert board.get_space("boardwalk").rents == (50, 200, 600, 1400, 1700, 2000) + + +def test_start_initializes_players_and_property_bank(): + game, alice, bob = make_game() + + assert game.get_name() == "Monopoly" + assert game.get_type() == "monopoly" + assert game.get_max_players() == 8 + assert alice.cash == 1500 + assert bob.cash == 1500 + assert len(game.property_states) == 28 + assert game.bank_houses == 32 + assert game.bank_hotels == 12 + + +def test_monopoly_is_registered_in_board_games_category(): + board_games = GameRegistry.get_by_category()["category-board-games"] + + assert any(game_class.get_type() == "monopoly" for game_class in board_games) + + +def test_buy_property_assigns_deed_and_charges_cash(): + game, alice, _bob = make_game() + game.pending_purchase_property_id = "mediterranean_avenue" + game.phase = "await_purchase" + + game.execute_action(alice, "buy_property") + + assert game.property_states["mediterranean_avenue"].owner_id == alice.id + assert alice.cash == 1440 + assert game.pending_purchase_property_id == "" + assert game.current_player == _bob + assert game.phase == "await_roll" + + +def test_unimproved_complete_color_set_doubles_rent(): + game, alice, bob = make_game() + game.property_states["mediterranean_avenue"].owner_id = alice.id + game.property_states["baltic_avenue"].owner_id = alice.id + bob.position = 1 + + complete = game._resolve_landing(bob, roll_total=7) + + assert complete is True + assert bob.cash == 1496 + assert alice.cash == 1504 + + +def test_building_uses_even_build_rule_and_increases_rent(): + game, alice, bob = make_game() + game.property_states["mediterranean_avenue"].owner_id = alice.id + game.property_states["baltic_avenue"].owner_id = alice.id + + game.execute_action(alice, "build_house", "mediterranean_avenue|Mediterranean Avenue") + + assert game.property_states["mediterranean_avenue"].houses == 1 + assert game.bank_houses == 31 + assert alice.cash == 1450 + + bob.position = 1 + assert game._resolve_landing(bob, roll_total=5) is True + assert bob.cash == 1490 + assert alice.cash == 1460 + + +def test_auction_awards_property_to_high_bidder_after_others_pass(): + game, alice, bob = make_game() + game.pending_purchase_property_id = "baltic_avenue" + game.phase = "await_purchase" + + game.execute_action(alice, "auction_property") + game.execute_action(bob, "auction_bid", "70") + game.execute_action(alice, "auction_pass") + + assert game.auction is None + assert game.property_states["baltic_avenue"].owner_id == bob.id + assert bob.cash == 1430 + + +def test_debt_can_be_resolved_by_mortgaging_property(): + game, alice, bob = make_game() + game.property_states["boardwalk"].owner_id = alice.id + bob.cash = 25 + bob.position = 39 + + assert game._resolve_landing(bob, roll_total=8) is False + assert game.pending_debt is not None + assert game.pending_debt.amount == 50 + + game.property_states["reading_railroad"].owner_id = bob.id + game.execute_action(bob, "mortgage_property", "reading_railroad|Reading Railroad") + game.execute_action(bob, "pay_debt") + + assert game.pending_debt is None + assert bob.cash == 75 + assert alice.cash == 1550 + + +def test_non_current_debt_payment_completes_current_turn(): + game, alice, bob = make_game() + game._set_debt(bob, 10, alice, "birthday") + + game.execute_action(bob, "pay_debt") + + assert game.pending_debt is None + assert alice.cash == 1510 + assert bob.cash == 1490 + assert game.current_player == bob + assert game.phase == "await_roll" + + +def test_trade_sells_property_for_cash(): + game, alice, bob = make_game() + game.property_states["mediterranean_avenue"].owner_id = alice.id + + game.execute_action(alice, "offer_trade", f"{bob.id}|Bob") + game.execute_action(alice, "trade_give", "mediterranean_avenue|Mediterranean Avenue") + game.execute_action(alice, "trade_cash", "-73") # Bob pays Alice $73 + game.execute_action(alice, "trade_send") + game.execute_action(bob, "accept_trade") + + assert game.pending_trade is None + assert game.property_states["mediterranean_avenue"].owner_id == bob.id + assert alice.cash == 1573 + assert bob.cash == 1427 + + +def test_asset_actions_are_visible_on_main_turn_menu_when_available(): + game, alice, _bob = make_game() + game.property_states["mediterranean_avenue"].owner_id = alice.id + + visible_ids = [resolved.action.id for resolved in game.get_all_visible_actions(alice)] + + assert "check_assets" in visible_ids + assert "check_board" in visible_ids + assert "mortgage_property" in visible_ids + assert "offer_trade" in visible_ids + + +def test_trade_rejects_improved_color_group_properties(): + game, alice, bob = make_game() + game.property_states["mediterranean_avenue"].owner_id = alice.id + game.property_states["baltic_avenue"].owner_id = alice.id + game.property_states["mediterranean_avenue"].houses = 1 + + game.execute_action(alice, "offer_trade", f"{bob.id}|Bob") + options = game._trade_give_options(alice) + + assert not any("Mediterranean Avenue" in option for option in options) + assert not any("Baltic Avenue" in option for option in options) + + +def test_trade_mortgaged_property_charges_transfer_interest(): + game, alice, bob = make_game() + game.property_states["reading_railroad"].owner_id = alice.id + game.property_states["reading_railroad"].mortgaged = True + + game.execute_action(alice, "offer_trade", f"{bob.id}|Bob") + game.execute_action(alice, "trade_give", "reading_railroad|Reading Railroad") + game.execute_action(alice, "trade_cash", "-100") # Bob pays Alice $100 + game.execute_action(alice, "trade_send") + game.execute_action(bob, "accept_trade") + + assert game.property_states["reading_railroad"].owner_id == bob.id + assert game.property_states["reading_railroad"].mortgaged is True + assert alice.cash == 1600 + assert bob.cash == 1390 + + +def test_trade_get_out_of_jail_card_for_cash(): + game, alice, bob = make_game() + alice.jail_free_cards.append("get_out_of_jail_free_chance") + + game.execute_action(alice, "offer_trade", f"{bob.id}|Bob") + game.execute_action(alice, "trade_jail", "give|Include your Get Out of Jail Free card") + game.execute_action(alice, "trade_cash", "-50") # Bob pays Alice $50 + game.execute_action(alice, "trade_send") + game.execute_action(bob, "accept_trade") + + assert alice.jail_free_cards == [] + assert bob.jail_free_cards == ["get_out_of_jail_free_chance"] + assert alice.cash == 1550 + assert bob.cash == 1450 + + +def test_completed_non_double_turn_advances_automatically(): + game, alice, bob = make_game() + + game._complete_roll_resolution(alice) + + assert game.current_player == bob + assert game.phase == "await_roll" + + +def test_doubles_keep_turn_for_extra_roll(): + game, alice, _bob = make_game() + game.extra_roll_pending = True + + game._complete_roll_resolution(alice) + + assert game.current_player == alice + assert game.phase == "await_roll" + + +def test_bankruptcy_transfers_assets_to_creditor_and_finishes_game(): + game, alice, bob = make_game() + game.property_states["boardwalk"].owner_id = bob.id + bob.cash = 0 + game._set_debt(bob, 100, alice, "rent") + + game.execute_action(bob, "declare_bankruptcy") + + assert bob.bankrupt is True + assert game.property_states["boardwalk"].owner_id == alice.id + assert game.game_active is False + assert game.winner_id == alice.id + + +def test_serialization_preserves_monopoly_state(): + game, alice, _bob = make_game() + game.property_states["park_place"].owner_id = alice.id + game.property_states["park_place"].mortgaged = True + alice.cash = 1234 + + loaded = MonopolyGame.from_json(game.to_json()) + + assert loaded.players[0].cash == 1234 + assert loaded.property_states["park_place"].owner_id == alice.id + assert loaded.property_states["park_place"].mortgaged is True + + +def test_bot_game_progresses_without_crashing(): + game = MonopolyGame() + bot1 = Bot("Bot1") + bot2 = Bot("Bot2") + game.add_player("Bot1", bot1) + game.add_player("Bot2", bot2) + game.on_start() + + for _ in range(400): + game.on_tick() + if not game.game_active: + break + + assert game.status in {"playing", "finished"} + + +def test_starting_cash_option_sets_player_balances(): + game = MonopolyGame() + game.options.starting_cash = 2500 + alice = game.add_player("Alice", MockUser("Alice")) + bob = game.add_player("Bob", MockUser("Bob")) + game.on_start() + + assert alice.cash == 2500 + assert bob.cash == 2500 + + +def test_free_parking_does_nothing_by_default(): + game, alice, _bob = make_game() + alice.position = 20 # Free Parking + + assert game._resolve_landing(alice, roll_total=6) is True + assert alice.cash == 1500 + assert game.free_parking_pot == 0 + + +def test_free_parking_jackpot_accumulates_taxes_and_pays_out(): + game = MonopolyGame() + game.options.free_parking_jackpot = True + alice = game.add_player("Alice", MockUser("Alice")) + bob = game.add_player("Bob", MockUser("Bob")) + game.on_start() + game.reset_turn_order() + + # Income Tax ($200) is paid to the bank and routed into the pot. + alice.position = 4 + assert game._resolve_landing(alice, roll_total=4) is True + assert alice.cash == 1300 + assert game.free_parking_pot == 200 + + # Landing on Free Parking wins the pot, which then resets to the seed (0). + bob.position = 20 + assert game._resolve_landing(bob, roll_total=6) is True + assert bob.cash == 1700 + assert game.free_parking_pot == 0 + + +def test_free_parking_pot_seeds_and_resets_to_seed(): + game = MonopolyGame() + game.options.free_parking_jackpot = True + game.options.free_parking_seed = 100 + alice = game.add_player("Alice", MockUser("Alice")) + bob = game.add_player("Bob", MockUser("Bob")) + game.on_start() + game.reset_turn_order() + + # The pot starts at the seed amount. + assert game.free_parking_pot == 100 + + # Luxury Tax ($100) accumulates on top of the seed. + alice.position = 38 + assert game._resolve_landing(alice, roll_total=2) is True + assert game.free_parking_pot == 200 + + bob.position = 20 + assert game._resolve_landing(bob, roll_total=6) is True + assert bob.cash == 1700 + assert game.free_parking_pot == 100 # reset to seed, not zero + + +def test_card_cash_message_uses_card_reason_not_literal_card(): + game, alice, _bob = make_game() + user = game.get_user(alice) + user.clear_messages() + + game.community_chest_deck = ["beauty_contest_collect_10"] + + assert game._draw_card(alice, "community_chest", roll_total=7) is True + + spoken = user.get_spoken_messages() + assert any("collected $10 for beauty contest prize" in message for message in spoken) + assert not any("for card" in message for message in spoken) + + +def test_non_current_player_has_no_turn_menu_but_escape_actions_still_work(): + game, alice, bob = make_game() + other = bob if game.current_player == alice else alice + other_user = game.get_user(other) + + game.rebuild_all_menus() + + assert "turn_menu" not in other_user.menus + + game.execute_action(other, "show_actions") + + action_menu = other_user.menus["actions_menu"] + action_ids = [item.id for item in action_menu["items"]] + assert "leave_game" in action_ids + + +def test_jackpot_deferred_bank_debt_feeds_pot_when_paid(): + game = MonopolyGame() + game.options.free_parking_jackpot = True + alice = game.add_player("Alice", MockUser("Alice")) + _bob = game.add_player("Bob", MockUser("Bob")) + game.on_start() + game.reset_turn_order() + + # Alice cannot afford the $200 Income Tax up front, so it becomes a debt. + alice.cash = 50 + alice.position = 4 + assert game._resolve_landing(alice, roll_total=4) is False + assert game.pending_debt is not None + assert game.free_parking_pot == 0 # not collected yet + + # Once she raises funds and pays, the bank income still feeds the pot. + alice.cash = 200 + game.execute_action(alice, "pay_debt") + assert game.pending_debt is None + assert game.free_parking_pot == 200 + + +def test_trade_builder_bundles_multiple_properties_and_cash(): + game, alice, bob = make_game() + game.property_states["boardwalk"].owner_id = alice.id + game.property_states["park_place"].owner_id = alice.id + game.property_states["baltic_avenue"].owner_id = bob.id + + game.execute_action(alice, "offer_trade", f"{bob.id}|Bob") + game.execute_action(alice, "trade_give", "boardwalk|Boardwalk") + game.execute_action(alice, "trade_give", "park_place|Park Place") + game.execute_action(alice, "trade_request", "baltic_avenue|Baltic Avenue") + game.execute_action(alice, "trade_cash", "200") # Alice pays Bob $200 + game.execute_action(alice, "trade_send") + + assert game.pending_trade is not None + assert set(game.pending_trade.give_property_ids) == {"boardwalk", "park_place"} + assert game.pending_trade.receive_property_ids == ["baltic_avenue"] + + game.execute_action(bob, "accept_trade") + + assert game.property_states["boardwalk"].owner_id == bob.id + assert game.property_states["park_place"].owner_id == bob.id + assert game.property_states["baltic_avenue"].owner_id == alice.id + assert alice.cash == 1300 + assert bob.cash == 1700 + + +def test_trade_partner_menu_hides_encoded_ids(): + game, alice, bob = make_game() + current = game._active_player(game.current_player) + user = game.get_user(current) + + # No input value -> the framework presents the partner picker menu. + game.execute_action(current, "offer_trade") + + menu = user.menus["action_input_menu"] + texts = [item.text for item in menu["items"]] + ids = [item.id for item in menu["items"]] + + # The shown label is the plain player name; the selection value still + # carries the "playerid|name" encoding so resolution stays unambiguous. + assert "Bob" in texts + assert all("|" not in text for text in texts) + assert any("|" in option_id for option_id in ids) + + +def test_property_menu_hides_encoded_ids(): + game, alice, _bob = make_game() + game.property_states["reading_railroad"].owner_id = alice.id + + game.execute_action(alice, "mortgage_property") + + menu = game.get_user(alice).menus["action_input_menu"] + texts = [item.text for item in menu["items"]] + assert any(text.startswith("Reading Railroad") for text in texts) + assert all("|" not in text for text in texts) + + +def test_trade_builder_toggle_removes_property(): + game, alice, bob = make_game() + game.property_states["boardwalk"].owner_id = alice.id + + game.execute_action(alice, "offer_trade", f"{bob.id}|Bob") + game.execute_action(alice, "trade_give", "boardwalk|Boardwalk") + assert game.trade_draft_offers[alice.id].give_property_ids == ["boardwalk"] + + game.execute_action(alice, "trade_give", "boardwalk|Boardwalk") # toggle off + assert game.trade_draft_offers[alice.id].give_property_ids == [] + + +def test_trade_builder_cancel_discards_draft(): + game, alice, bob = make_game() + + game.execute_action(alice, "offer_trade", f"{bob.id}|Bob") + assert alice.id in game.trade_draft_offers + + game.execute_action(alice, "trade_cancel") + assert alice.id not in game.trade_draft_offers + + +def test_turn_start_focuses_roll_not_check_assets(): + game, alice, bob = make_game() + current = game._active_player(game.current_player) + user = game.get_user(current) + + game._start_turn(rebuild_all=True) + + menu = user.menus["turn_menu"] + assert menu["position"] == 1 + assert menu["items"][0].id == "roll" + + +def test_landing_on_unowned_property_focuses_buy(monkeypatch): + game, alice, bob = make_game() + current = game._active_player(game.current_player) + user = game.get_user(current) + + dice = iter([1, 2]) # total 3 from GO -> Baltic Avenue (unowned), not a double + + def fake_randint(low, high): + if (low, high) == (1, 6): + return next(dice) + return high + + monkeypatch.setattr("server.games.monopoly.game.random.randint", fake_randint) + + game.execute_action(current, "roll") + + assert game.pending_purchase_property_id == "baltic_avenue" + menu = user.menus["turn_menu"] + assert menu["position"] == 1 + assert menu["items"][0].id == "buy_property" + + +def test_trade_builder_focuses_menu_on_builder_actions(): + game, alice, bob = make_game() + + ids_before = {rv.action.id for rv in game.get_all_visible_actions(alice)} + assert "offer_trade" in ids_before + assert not any(action_id.startswith("trade_") for action_id in ids_before) + + game.execute_action(alice, "offer_trade", f"{bob.id}|Bob") + + ids_building = {rv.action.id for rv in game.get_all_visible_actions(alice)} + assert ids_building + assert all(action_id.startswith("trade_") for action_id in ids_building) + assert {"trade_give", "trade_request", "trade_send", "trade_cancel"} <= ids_building + assert "roll" not in ids_building