diff options
112 files changed, 821 insertions, 815 deletions
diff --git a/data/help/craps.yaml b/data/help/craps.yaml index f5ce844..3537a80 100644 --- a/data/help/craps.yaml +++ b/data/help/craps.yaml @@ -4,11 +4,12 @@ category: Interaction related: [casino, roulette] description: | Craps — multiplayer house editions at the Domita Fortuna casino. - From single-zero roulette, west reaches Bank Craps. Head north along - the gallery for Simplified, High Point, Crapless, New York, Die Rich, - then Diceless. Join with play craps in each room; table rules gives - that edition's exact targets and payouts. The examples below are BANK - rules, not a promise that every edition accepts every bet. + From single-zero roulette, east reaches Bank Craps. North of the pit + waits Simplified, High Point, then Crapless; south waits New York, + Die Rich, then Diceless. Join with play craps in each room; table + rules gives that edition's exact targets and payouts. The examples + below are BANK rules, not a promise that every edition accepts every + bet. play craps Join the tail of the shooting queue watch craps Watch without betting diff --git a/data/help/roulette.yaml b/data/help/roulette.yaml index fae288c..a6f4c23 100644 --- a/data/help/roulette.yaml +++ b/data/help/roulette.yaml @@ -3,9 +3,9 @@ category: Interaction related: [racetrack, casino, blackjack, baccarat, slots] description: | Play roulette in the Domita Fortuna casino. - From the vestibule: north, up, north reaches single zero; - east from single zero reaches the racetrack; - another north reaches double zero. + Take the stairs up in the vestibule, then east past blackjack and + baccarat to single zero; north reaches double zero, south the + racetrack, and east the craps pit. play roulette Join the table table Show layout, phase, and last result diff --git a/data/mobs/vesta/casino_host.yaml b/data/mobs/vesta/casino_host.yaml index 92a887d..f41360a 100644 --- a/data/mobs/vesta/casino_host.yaml +++ b/data/mobs/vesta/casino_host.yaml @@ -9,8 +9,10 @@ talk: nodes: start: messages: - - Welcome to Domita Fortuna. Every game has its own room and posted rules. The upper floors - are open to visitors but their gaming halls are not operating yet. No membership or wager is needed - to explore. + - 'Welcome to Domita Fortuna. Take the stairs up to the gaming street: + blackjack, baccarat, roulette, craps, then slots, one salon each going + east. Step north or south inside each salon for its house editions. + The bank booth down by the door stores your valuables, and no + membership or wager is needed to explore.' options: - text: Thank you. diff --git a/data/objects/casino_test_portal.yaml b/data/objects/casino_test_portal.yaml index 0132d32..468589c 100644 --- a/data/objects/casino_test_portal.yaml +++ b/data/objects/casino_test_portal.yaml @@ -11,4 +11,4 @@ on_use: weight: 1 - teleport: 6100 messages: - - 'Testing shortcut: welcome to the Domita casino! Head north to explore the gaming floors.' + - 'Testing shortcut: welcome to the Domita casino! Take the stairs up to the gaming street.' diff --git a/data/rooms/casino/6100.yaml b/data/rooms/casino/6100.yaml index e822eda..6e77bc6 100644 --- a/data/rooms/casino/6100.yaml +++ b/data/rooms/casino/6100.yaml @@ -1,17 +1,19 @@ name: Vestibule -description: A ceiling of tiny brass suns hangs over polished stone. Icarus Leisure’s emblem repeats on - every column. Stairs and galleries are open to all visitors. +description: A ceiling of tiny brass suns hangs over polished stone. Icarus Leisure's emblem repeats on + every column. Grand stairs rise to the ground gaming floor. exits: south: room: 5111 - north: + up: room: 6101 mobs: - id: casino_host +- id: casino_cashier objects: - name: wayboard - description: 'Grand stair: ground gaming floor above the entrance podium. West: five blackjack salons, - three baccarat salons. East: five slot rooms. Three upper galleries reserve fifteen future game halls. - Roulette salons: north, up, north for single zero; east for the racetrack; continue north for double zero. - All floors are open without a wager.' + description: 'Domita Fortuna in one line: take the stairs up to the gaming street — blackjack, + baccarat, roulette, craps, slots, one salon each, going east. Each salon keeps its own house + editions in the galleries north and south. The bank booth by the door stores your valuables; + no wager is needed to explore.' inroom_description: A wayboard stands where travelers can read it. +- id: bank_booth diff --git a/data/rooms/casino/6101.yaml b/data/rooms/casino/6101.yaml index 7df2c07..fb2838a 100644 --- a/data/rooms/casino/6101.yaml +++ b/data/rooms/casino/6101.yaml @@ -1,8 +1,39 @@ -name: Grand Atrium -description: A ceiling of tiny brass suns hangs over polished stone. Icarus Leisure’s emblem repeats on - every column. Stairs and galleries are open to all visitors. +name: Classic Blackjack +description: The first salon on the gaming street above the entrance podium. A six-deck + blackjack table sits under shaded lamps; the house editions wait in the galleries + north and south. Look at the table for its rules. exits: - south: + down: room: 6100 - up: + east: + room: 6127 + north: room: 6102 + south: + room: 6106 +casino_tables: +- id: classic + game: blackjack + max_players: 6 + betting_ticks: 30 + min_bet: 10 + max_bet: 1000 + blackjack: + decks: 6 + shuffle_at: 0.25 + blackjack_payout: 1.5 + dealer_hit_soft_17: false + max_split_hands: 4 + resplit_aces: false + double_after_split: true + double_split_blackjack: false + insurance_payout: 2 + surrender: false + action_ticks: 25 + split_unlike_ten_values: false +objects: +- name: rules plaque + description: Play blackjack; bet min, bet max or bet <amount>. Blackjack pays 3:2; insurance 2:1. 6 + deck(s). Dealer stands on soft 17. No surrender. Double after split allowed. Split 21 pays 1:1; split + identical ranks only. + inroom_description: A rules plaque stands where travelers can read it. diff --git a/data/rooms/casino/6102.yaml b/data/rooms/casino/6102.yaml index 26f80d4..ae39910 100644 --- a/data/rooms/casino/6102.yaml +++ b/data/rooms/casino/6102.yaml @@ -1,17 +1,34 @@ -name: Ground Gaming Floor Landing -description: The entrance stair rises onto a broad podium, the casino’s ground gaming floor. A directory - divides the floor into card salons west and machine galleries east. Higher stairs lead to future gaming - floors. +name: Copper Blackjack +description: A modest six-deck table for small purses; limits are 1–100 credits. The next house edition + waits north. No wager is required to watch or pass through. exits: - north: - room: 6182 - down: - room: 6101 south: - room: 6106 - west: - room: 6115 - east: - room: 6125 - up: - room: 6149 + room: 6101 + north: + room: 6104 +casino_tables: +- id: copper + game: blackjack + max_players: 6 + betting_ticks: 30 + min_bet: 1 + max_bet: 100 + blackjack: + decks: 6 + shuffle_at: 0.25 + blackjack_payout: 1.5 + dealer_hit_soft_17: false + max_split_hands: 4 + resplit_aces: false + double_after_split: true + double_split_blackjack: false + insurance_payout: 2 + surrender: false + action_ticks: 40 + split_unlike_ten_values: false +objects: +- name: rules plaque + description: Play blackjack; bet min, bet max or bet <amount>. Blackjack pays 3:2; insurance 2:1. 6 + deck(s). Dealer stands on soft 17. No surrender. Double after split allowed. Split 21 pays 1:1; split + identical ranks only. + inroom_description: A rules plaque stands where travelers can read it. diff --git a/data/rooms/casino/6103.yaml b/data/rooms/casino/6103.yaml deleted file mode 100644 index 2632e65..0000000 --- a/data/rooms/casino/6103.yaml +++ /dev/null @@ -1,10 +0,0 @@ -name: South Gaming Rotunda -description: Deep carpet quiets footsteps between individual gaming salons. Each doorway displays its - own rules and wager limits. -exits: - north: - room: 6104 - west: - room: 6107 - east: - room: 6117 diff --git a/data/rooms/casino/6104.yaml b/data/rooms/casino/6104.yaml index 38ad8c5..2ec6993 100644 --- a/data/rooms/casino/6104.yaml +++ b/data/rooms/casino/6104.yaml @@ -1,12 +1,32 @@ -name: Amber Concourse -description: Deep carpet quiets footsteps between individual gaming salons. Each doorway displays its - own rules and wager limits. +name: Single Deck Salon +description: One deck, 6:5 naturals, and a dealer who hits soft 17 — the sharpest game in the house. + Limits are 25–2500 credits. No wager is required to watch or pass through. exits: south: - room: 6103 - north: - room: 6105 - west: - room: 6109 - east: - room: 6119 + room: 6102 +casino_tables: +- id: single + game: blackjack + max_players: 6 + betting_ticks: 30 + min_bet: 25 + max_bet: 2500 + blackjack: + decks: 1 + shuffle_at: 0.25 + blackjack_payout: 1.2 + dealer_hit_soft_17: true + max_split_hands: 2 + resplit_aces: false + double_after_split: false + double_split_blackjack: false + insurance_payout: 2 + surrender: false + action_ticks: 25 + split_unlike_ten_values: false +objects: +- name: rules plaque + description: Play blackjack; bet min, bet max or bet <amount>. Blackjack pays 6:5; insurance 2:1. 1 + deck(s). Dealer hits soft 17. No surrender. No double after split. Split 21 pays 1:1; split identical + ranks only. + inroom_description: A rules plaque stands where travelers can read it. diff --git a/data/rooms/casino/6105.yaml b/data/rooms/casino/6105.yaml deleted file mode 100644 index 0ebe609..0000000 --- a/data/rooms/casino/6105.yaml +++ /dev/null @@ -1,12 +0,0 @@ -name: Central Gaming Concourse -description: Deep carpet quiets footsteps between individual gaming salons. Each doorway displays its - own rules and wager limits. -exits: - south: - room: 6104 - north: - room: 6106 - west: - room: 6111 - east: - room: 6121 diff --git a/data/rooms/casino/6106.yaml b/data/rooms/casino/6106.yaml index 2ba4faf..6cf1345 100644 --- a/data/rooms/casino/6106.yaml +++ b/data/rooms/casino/6106.yaml @@ -1,12 +1,34 @@ -name: Marble Concourse -description: Deep carpet quiets footsteps between individual gaming salons. Each doorway displays its - own rules and wager limits. +name: Mercy Blackjack +description: A forgiving table — late surrender and re-splitting aces are offered here. Limits are + 2–500 credits. The high-limit salon waits south. No wager is required to watch or pass through. exits: - south: - room: 6105 north: - room: 6102 - west: - room: 6113 - east: - room: 6123 + room: 6101 + south: + room: 6108 +casino_tables: +- id: mercy + game: blackjack + max_players: 6 + betting_ticks: 30 + min_bet: 2 + max_bet: 500 + blackjack: + decks: 6 + shuffle_at: 0.25 + blackjack_payout: 1.5 + dealer_hit_soft_17: false + max_split_hands: 4 + resplit_aces: true + double_after_split: true + double_split_blackjack: false + insurance_payout: 2 + surrender: true + action_ticks: 25 + split_unlike_ten_values: false +objects: +- name: rules plaque + description: Play blackjack; bet min, bet max or bet <amount>. Blackjack pays 3:2; insurance 2:1. 6 + deck(s). Dealer stands on soft 17. Late surrender and re-splitting aces offered. Double after split allowed. Split 21 pays 1:1; split + identical ranks only. + inroom_description: A rules plaque stands where travelers can read it. diff --git a/data/rooms/casino/6107.yaml b/data/rooms/casino/6107.yaml deleted file mode 100644 index 85fc600..0000000 --- a/data/rooms/casino/6107.yaml +++ /dev/null @@ -1,8 +0,0 @@ -name: Copper Blackjack Anteroom -description: A quiet seating bay separates the concourse from Copper Blackjack. A brass plaque states - the rules before anyone joins a game. -exits: - east: - room: 6103 - west: - room: 6108 diff --git a/data/rooms/casino/6108.yaml b/data/rooms/casino/6108.yaml index 877e219..db7beaa 100644 --- a/data/rooms/casino/6108.yaml +++ b/data/rooms/casino/6108.yaml @@ -1,34 +1,34 @@ -name: Copper Blackjack -description: An individual blackjack salon opens beyond the anteroom. Limits are 1–100 credits. No wager - is required to watch or pass through. +name: Midnight Blackjack +description: Eight decks and a dealer who hits soft 17, under midnight-blue felt. Limits are + 100–10000 credits. A prosperous local watches the high-limit action from the rail. exits: - east: - room: 6107 - west: - room: 6127 + north: + room: 6106 casino_tables: -- id: copper +- id: midnight game: blackjack max_players: 6 betting_ticks: 30 - min_bet: 1 - max_bet: 100 + min_bet: 100 + max_bet: 10000 blackjack: - decks: 6 + decks: 8 shuffle_at: 0.25 blackjack_payout: 1.5 - dealer_hit_soft_17: false + dealer_hit_soft_17: true max_split_hands: 4 resplit_aces: false double_after_split: true double_split_blackjack: false insurance_payout: 2 surrender: false - action_ticks: 40 + action_ticks: 25 split_unlike_ten_values: false +mobs: +- id: casino_patron objects: - name: rules plaque - description: Play blackjack; bet min, bet max or bet <amount>. Blackjack pays 3:2; insurance 2:1. 6 - deck(s). Dealer stands on soft 17. No surrender. Double after split allowed. Split 21 pays 1:1; split - identical ranks only. + description: Play blackjack; bet min, bet max or bet <amount>. Blackjack pays 3:2; insurance 2:1. 8 + deck(s). Dealer hits soft 17. No surrender. Double after split allowed. Split 21 pays 1:1; split identical + ranks only. inroom_description: A rules plaque stands where travelers can read it. diff --git a/data/rooms/casino/6109.yaml b/data/rooms/casino/6109.yaml deleted file mode 100644 index 4e2786c..0000000 --- a/data/rooms/casino/6109.yaml +++ /dev/null @@ -1,8 +0,0 @@ -name: Classic Blackjack Anteroom -description: A quiet seating bay separates the concourse from Classic Blackjack. A brass plaque states - the rules before anyone joins a game. -exits: - east: - room: 6104 - west: - room: 6110 diff --git a/data/rooms/casino/6110.yaml b/data/rooms/casino/6110.yaml deleted file mode 100644 index 5f77c60..0000000 --- a/data/rooms/casino/6110.yaml +++ /dev/null @@ -1,34 +0,0 @@ -name: Classic Blackjack -description: An individual blackjack salon opens beyond the anteroom. Limits are 10–1000 credits. No wager - is required to watch or pass through. -exits: - east: - room: 6109 - west: - room: 6130 -casino_tables: -- id: classic - game: blackjack - max_players: 6 - betting_ticks: 30 - min_bet: 10 - max_bet: 1000 - blackjack: - decks: 6 - shuffle_at: 0.25 - blackjack_payout: 1.5 - dealer_hit_soft_17: false - max_split_hands: 4 - resplit_aces: false - double_after_split: true - double_split_blackjack: false - insurance_payout: 2 - surrender: false - action_ticks: 25 - split_unlike_ten_values: false -objects: -- name: rules plaque - description: Play blackjack; bet min, bet max or bet <amount>. Blackjack pays 3:2; insurance 2:1. 6 - deck(s). Dealer stands on soft 17. No surrender. Double after split allowed. Split 21 pays 1:1; split - identical ranks only. - inroom_description: A rules plaque stands where travelers can read it. diff --git a/data/rooms/casino/6111.yaml b/data/rooms/casino/6111.yaml deleted file mode 100644 index 5f33706..0000000 --- a/data/rooms/casino/6111.yaml +++ /dev/null @@ -1,8 +0,0 @@ -name: Mercy Blackjack Anteroom -description: A quiet seating bay separates the concourse from Mercy Blackjack. A brass plaque states the - rules before anyone joins a game. -exits: - east: - room: 6105 - west: - room: 6112 diff --git a/data/rooms/casino/6112.yaml b/data/rooms/casino/6112.yaml deleted file mode 100644 index a77775d..0000000 --- a/data/rooms/casino/6112.yaml +++ /dev/null @@ -1,34 +0,0 @@ -name: Mercy Blackjack -description: An individual blackjack salon opens beyond the anteroom. Limits are 2–500 credits. No wager - is required to watch or pass through. -exits: - east: - room: 6111 - west: - room: 6128 -casino_tables: -- id: mercy - game: blackjack - max_players: 6 - betting_ticks: 30 - min_bet: 2 - max_bet: 500 - blackjack: - decks: 6 - shuffle_at: 0.25 - blackjack_payout: 1.5 - dealer_hit_soft_17: false - max_split_hands: 4 - resplit_aces: true - double_after_split: true - double_split_blackjack: false - insurance_payout: 2 - surrender: true - action_ticks: 25 - split_unlike_ten_values: false -objects: -- name: rules plaque - description: Play blackjack; bet min, bet max or bet <amount>. Blackjack pays 3:2; insurance 2:1. 6 - deck(s). Dealer stands on soft 17. Late surrender and re-splitting aces offered. Double after split allowed. Split 21 pays - 1:1; split identical ranks only. - inroom_description: A rules plaque stands where travelers can read it. diff --git a/data/rooms/casino/6113.yaml b/data/rooms/casino/6113.yaml deleted file mode 100644 index e1fb79d..0000000 --- a/data/rooms/casino/6113.yaml +++ /dev/null @@ -1,8 +0,0 @@ -name: Single Deck Salon Anteroom -description: A quiet seating bay separates the concourse from Single Deck Salon. A brass plaque states - the rules before anyone joins a game. -exits: - east: - room: 6106 - west: - room: 6114 diff --git a/data/rooms/casino/6114.yaml b/data/rooms/casino/6114.yaml deleted file mode 100644 index 0689249..0000000 --- a/data/rooms/casino/6114.yaml +++ /dev/null @@ -1,34 +0,0 @@ -name: Single Deck Salon -description: An individual blackjack salon opens beyond the anteroom. Limits are 25–2500 credits. No wager - is required to watch or pass through. -exits: - east: - room: 6113 - west: - room: 6131 -casino_tables: -- id: single - game: blackjack - max_players: 6 - betting_ticks: 30 - min_bet: 25 - max_bet: 2500 - blackjack: - decks: 1 - shuffle_at: 0.25 - blackjack_payout: 1.2 - dealer_hit_soft_17: true - max_split_hands: 2 - resplit_aces: false - double_after_split: false - double_split_blackjack: false - insurance_payout: 2 - surrender: false - action_ticks: 25 - split_unlike_ten_values: false -objects: -- name: rules plaque - description: Play blackjack; bet min, bet max or bet <amount>. Blackjack pays 6:5; insurance 2:1. 1 - deck(s). Dealer hits soft 17. No surrender. No double after split. Split 21 pays 1:1; split identical - ranks only. - inroom_description: A rules plaque stands where travelers can read it. diff --git a/data/rooms/casino/6115.yaml b/data/rooms/casino/6115.yaml deleted file mode 100644 index b58fde3..0000000 --- a/data/rooms/casino/6115.yaml +++ /dev/null @@ -1,8 +0,0 @@ -name: Midnight Blackjack Anteroom -description: A quiet seating bay separates the concourse from Midnight Blackjack. A brass plaque states - the rules before anyone joins a game. -exits: - east: - room: 6102 - west: - room: 6116 diff --git a/data/rooms/casino/6116.yaml b/data/rooms/casino/6116.yaml deleted file mode 100644 index 044b106..0000000 --- a/data/rooms/casino/6116.yaml +++ /dev/null @@ -1,34 +0,0 @@ -name: Midnight Blackjack -description: An individual blackjack salon opens beyond the anteroom. Limits are 100–10000 credits. No - wager is required to watch or pass through. -exits: - east: - room: 6115 - west: - room: 6129 -casino_tables: -- id: midnight - game: blackjack - max_players: 6 - betting_ticks: 30 - min_bet: 100 - max_bet: 10000 - blackjack: - decks: 8 - shuffle_at: 0.25 - blackjack_payout: 1.5 - dealer_hit_soft_17: true - max_split_hands: 4 - resplit_aces: false - double_after_split: true - double_split_blackjack: false - insurance_payout: 2 - surrender: false - action_ticks: 25 - split_unlike_ten_values: false -objects: -- name: rules plaque - description: Play blackjack; bet min, bet max or bet <amount>. Blackjack pays 3:2; insurance 2:1. 8 - deck(s). Dealer hits soft 17. No surrender. Double after split allowed. Split 21 pays 1:1; split identical - ranks only. - inroom_description: A rules plaque stands where travelers can read it. diff --git a/data/rooms/casino/6117.yaml b/data/rooms/casino/6117.yaml deleted file mode 100644 index ac51ab5..0000000 --- a/data/rooms/casino/6117.yaml +++ /dev/null @@ -1,8 +0,0 @@ -name: Penny Reels Anteroom -description: A quiet seating bay separates the concourse from Penny Reels. A brass plaque states the rules - before anyone joins a game. -exits: - west: - room: 6103 - east: - room: 6118 diff --git a/data/rooms/casino/6118.yaml b/data/rooms/casino/6118.yaml index 98e6d9d..5ec251b 100644 --- a/data/rooms/casino/6118.yaml +++ b/data/rooms/casino/6118.yaml @@ -1,11 +1,13 @@ name: Penny Reels -description: An individual slots salon opens beyond the anteroom. Limits are 1–25 credits. No wager is - required to watch or pass through. +description: A wall of chiming reels opens the machine gallery; limits are 1–25 credits. Higher-stakes + machines wait north and south. No wager is required to watch or pass through. exits: west: - room: 6117 - east: - room: 6132 + room: 6185 + north: + room: 6120 + south: + room: 6122 casino_machines: - id: penny_reels game: slots diff --git a/data/rooms/casino/6119.yaml b/data/rooms/casino/6119.yaml deleted file mode 100644 index cdf73e8..0000000 --- a/data/rooms/casino/6119.yaml +++ /dev/null @@ -1,8 +0,0 @@ -name: Silver Reels Anteroom -description: A quiet seating bay separates the concourse from Silver Reels. A brass plaque states the - rules before anyone joins a game. -exits: - west: - room: 6104 - east: - room: 6120 diff --git a/data/rooms/casino/6120.yaml b/data/rooms/casino/6120.yaml index 63b12d3..ed25f49 100644 --- a/data/rooms/casino/6120.yaml +++ b/data/rooms/casino/6120.yaml @@ -1,11 +1,10 @@ name: Silver Reels -description: An individual slots salon opens beyond the anteroom. Limits are 10–500 credits. No wager - is required to watch or pass through. +description: Mid-limit reels; wagers 10-500 credits. The high-limit salon waits north. exits: - west: - room: 6119 - east: - room: 6133 + south: + room: 6118 + north: + room: 6126 casino_machines: - id: silver_reels game: slots diff --git a/data/rooms/casino/6121.yaml b/data/rooms/casino/6121.yaml deleted file mode 100644 index 511ceb8..0000000 --- a/data/rooms/casino/6121.yaml +++ /dev/null @@ -1,8 +0,0 @@ -name: Timber Reels Anteroom -description: A quiet seating bay separates the concourse from Timber Reels. A brass plaque states the - rules before anyone joins a game. -exits: - west: - room: 6105 - east: - room: 6122 diff --git a/data/rooms/casino/6122.yaml b/data/rooms/casino/6122.yaml index 486256b..9d8027c 100644 --- a/data/rooms/casino/6122.yaml +++ b/data/rooms/casino/6122.yaml @@ -1,11 +1,10 @@ name: Timber Reels -description: An individual slots salon opens beyond the anteroom. Limits are 1–100 credits. No wager is - required to watch or pass through. +description: Huff-and-even-more-puff reels; wagers 1-100 credits. Another huff cabinet waits south. exits: - west: - room: 6121 - east: - room: 6134 + north: + room: 6118 + south: + room: 6124 casino_machines: - id: timber_reels game: slots diff --git a/data/rooms/casino/6123.yaml b/data/rooms/casino/6123.yaml deleted file mode 100644 index dc3bd2c..0000000 --- a/data/rooms/casino/6123.yaml +++ /dev/null @@ -1,8 +0,0 @@ -name: Golden Timber Reels Anteroom -description: A quiet seating bay separates the concourse from Golden Timber Reels. A brass plaque states - the rules before anyone joins a game. -exits: - west: - room: 6106 - east: - room: 6124 diff --git a/data/rooms/casino/6124.yaml b/data/rooms/casino/6124.yaml index ac0319d..2ef7d00 100644 --- a/data/rooms/casino/6124.yaml +++ b/data/rooms/casino/6124.yaml @@ -1,11 +1,8 @@ name: Golden Timber Reels -description: An individual slots salon opens beyond the anteroom. Limits are 25–2500 credits. No wager - is required to watch or pass through. +description: The golden huff cabinet takes larger wagers, 25-2500 credits. exits: - west: - room: 6123 - east: - room: 6135 + north: + room: 6122 casino_machines: - id: golden_timber_reels game: slots diff --git a/data/rooms/casino/6125.yaml b/data/rooms/casino/6125.yaml deleted file mode 100644 index 6641421..0000000 --- a/data/rooms/casino/6125.yaml +++ /dev/null @@ -1,8 +0,0 @@ -name: Platinum Reels Anteroom -description: A quiet seating bay separates the concourse from Platinum Reels. A brass plaque states the - rules before anyone joins a game. -exits: - west: - room: 6102 - east: - room: 6126 diff --git a/data/rooms/casino/6126.yaml b/data/rooms/casino/6126.yaml index 272b5ff..4b99a7a 100644 --- a/data/rooms/casino/6126.yaml +++ b/data/rooms/casino/6126.yaml @@ -1,11 +1,8 @@ name: Platinum Reels -description: An individual slots salon opens beyond the anteroom. Limits are 100–10000 credits. No wager - is required to watch or pass through. +description: The high-limit reels; wagers 100-10000 credits. exits: - west: - room: 6125 - east: - room: 6136 + south: + room: 6120 casino_machines: - id: platinum_reels game: slots diff --git a/data/rooms/casino/6127.yaml b/data/rooms/casino/6127.yaml index b0390b5..4ce355e 100644 --- a/data/rooms/casino/6127.yaml +++ b/data/rooms/casino/6127.yaml @@ -1,9 +1,14 @@ name: Harbor Baccarat -description: Green baize and shaded lamps distinguish this quiet baccarat salon from the neighboring blackjack - room. A traditional commission baccarat table offers pair bets; look at the table for its rules. +description: Green baize and shaded lamps. A traditional commission baccarat table offers pair bets; its no-commission editions wait north and south. Look at the table for its rules. exits: + west: + room: 6101 east: - room: 6108 + room: 6182 + north: + room: 6128 + south: + room: 6129 casino_tables: - id: harbor_baccarat game: baccarat diff --git a/data/rooms/casino/6128.yaml b/data/rooms/casino/6128.yaml index 35226a2..c7f329f 100644 --- a/data/rooms/casino/6128.yaml +++ b/data/rooms/casino/6128.yaml @@ -1,9 +1,8 @@ name: Charter Baccarat -description: Green baize and shaded lamps distinguish this quiet baccarat salon from the neighboring blackjack - room. A Super 6 no-commission baccarat table waits here; look at the table for its rules. +description: A Super 6 no-commission baccarat table; winning Banker sixes pay half, and the separate super_6 wager pays 12:1. exits: - east: - room: 6112 + south: + room: 6127 casino_tables: - id: charter_baccarat game: baccarat diff --git a/data/rooms/casino/6129.yaml b/data/rooms/casino/6129.yaml index 50c40e4..0aa7fcd 100644 --- a/data/rooms/casino/6129.yaml +++ b/data/rooms/casino/6129.yaml @@ -1,9 +1,8 @@ name: Crown Baccarat -description: Green baize and shaded lamps distinguish this quiet baccarat salon from the neighboring blackjack - room. An EZ Baccarat no-commission table offers Dragon 7 and Panda 8; look at the table for its rules. +description: An EZ Baccarat no-commission table; a winning three-card Banker seven pushes Banker bets, and Dragon 7 and Panda 8 are offered. exits: - east: - room: 6116 + north: + room: 6127 casino_tables: - id: crown_baccarat game: baccarat diff --git a/data/rooms/casino/6130.yaml b/data/rooms/casino/6130.yaml deleted file mode 100644 index 2a3008f..0000000 --- a/data/rooms/casino/6130.yaml +++ /dev/null @@ -1,9 +0,0 @@ -name: Cashier Gallery -description: A long brass grille protects the counting desk; the public bank booth remains outside it. -exits: - east: - room: 6110 -objects: -- id: bank_booth -mobs: -- id: casino_cashier diff --git a/data/rooms/casino/6131.yaml b/data/rooms/casino/6131.yaml deleted file mode 100644 index 645c9fb..0000000 --- a/data/rooms/casino/6131.yaml +++ /dev/null @@ -1,6 +0,0 @@ -name: Responsible Play Lounge -description: Quiet chairs face a clock with unusually large numerals. A sign reminds visitors that the - next hand does not owe them a win. -exits: - east: - room: 6114 diff --git a/data/rooms/casino/6132.yaml b/data/rooms/casino/6132.yaml deleted file mode 100644 index 34f8756..0000000 --- a/data/rooms/casino/6132.yaml +++ /dev/null @@ -1,7 +0,0 @@ -name: South Buffet -description: A public range lets travelers cook their own food alongside the dining tables. -exits: - west: - room: 6118 -objects: -- id: cooking_range diff --git a/data/rooms/casino/6133.yaml b/data/rooms/casino/6133.yaml deleted file mode 100644 index 9e00c74..0000000 --- a/data/rooms/casino/6133.yaml +++ /dev/null @@ -1,5 +0,0 @@ -name: Cloakroom -description: Numbered hooks and clean benches serve visitors who only came to see the building. -exits: - west: - room: 6120 diff --git a/data/rooms/casino/6134.yaml b/data/rooms/casino/6134.yaml deleted file mode 100644 index 6bd9f53..0000000 --- a/data/rooms/casino/6134.yaml +++ /dev/null @@ -1,7 +0,0 @@ -name: Guest Services -description: A charger sits beneath a directory of every floor. -exits: - west: - room: 6122 -objects: -- id: charging_station diff --git a/data/rooms/casino/6135.yaml b/data/rooms/casino/6135.yaml deleted file mode 100644 index d1e9745..0000000 --- a/data/rooms/casino/6135.yaml +++ /dev/null @@ -1,5 +0,0 @@ -name: Musicians’ Alcove -description: A mechanical piano waits between performances. -exits: - west: - room: 6124 diff --git a/data/rooms/casino/6136.yaml b/data/rooms/casino/6136.yaml deleted file mode 100644 index ea7e05b..0000000 --- a/data/rooms/casino/6136.yaml +++ /dev/null @@ -1,5 +0,0 @@ -name: Observation Lounge -description: Tall windows show Domita’s slate roofs far below the illuminated signs. -exits: - west: - room: 6126 diff --git a/data/rooms/casino/6137.yaml b/data/rooms/casino/6137.yaml deleted file mode 100644 index e8809f7..0000000 --- a/data/rooms/casino/6137.yaml +++ /dev/null @@ -1,10 +0,0 @@ -name: First Gallery South Rotunda -description: The first gallery is freely open for exploration. Completed corridors face unfurnished gaming - rooms; signs explicitly say that no games operate on this floor yet. -exits: - west: - room: 6138 - east: - room: 6139 - north: - room: 6140 diff --git a/data/rooms/casino/6138.yaml b/data/rooms/casino/6138.yaml deleted file mode 100644 index 2ccb2a8..0000000 --- a/data/rooms/casino/6138.yaml +++ /dev/null @@ -1,6 +0,0 @@ -name: First Gallery Future Tournament Hall -description: Power sockets, table anchor points and service passages are installed, but there is no playable - game here yet. This hall is reserved for a future casino expansion. -exits: - east: - room: 6137 diff --git a/data/rooms/casino/6139.yaml b/data/rooms/casino/6139.yaml deleted file mode 100644 index fb45596..0000000 --- a/data/rooms/casino/6139.yaml +++ /dev/null @@ -1,5 +0,0 @@ -name: First Gallery Balcony Lounge -description: A sheltered balcony overlooks the city without requiring a ticket. -exits: - west: - room: 6137 diff --git a/data/rooms/casino/6140.yaml b/data/rooms/casino/6140.yaml deleted file mode 100644 index 04bf1af..0000000 --- a/data/rooms/casino/6140.yaml +++ /dev/null @@ -1,12 +0,0 @@ -name: First Gallery Promenade -description: The first gallery is freely open for exploration. Completed corridors face unfurnished gaming - rooms; signs explicitly say that no games operate on this floor yet. -exits: - south: - room: 6137 - west: - room: 6141 - east: - room: 6142 - north: - room: 6143 diff --git a/data/rooms/casino/6141.yaml b/data/rooms/casino/6141.yaml deleted file mode 100644 index 7195e2c..0000000 --- a/data/rooms/casino/6141.yaml +++ /dev/null @@ -1,6 +0,0 @@ -name: First Gallery Future Card Salon -description: Power sockets, table anchor points and service passages are installed, but there is no playable - game here yet. This hall is reserved for a future casino expansion. -exits: - east: - room: 6140 diff --git a/data/rooms/casino/6142.yaml b/data/rooms/casino/6142.yaml deleted file mode 100644 index f49b1b5..0000000 --- a/data/rooms/casino/6142.yaml +++ /dev/null @@ -1,5 +0,0 @@ -name: First Gallery Refreshment Room -description: Empty serving counters stand ready for the next expansion. -exits: - west: - room: 6140 diff --git a/data/rooms/casino/6143.yaml b/data/rooms/casino/6143.yaml deleted file mode 100644 index 37f3a73..0000000 --- a/data/rooms/casino/6143.yaml +++ /dev/null @@ -1,12 +0,0 @@ -name: First Gallery Central Landing -description: The first gallery is freely open for exploration. Completed corridors face unfurnished gaming - rooms; signs explicitly say that no games operate on this floor yet. -exits: - south: - room: 6140 - west: - room: 6144 - east: - room: 6145 - north: - room: 6146 diff --git a/data/rooms/casino/6144.yaml b/data/rooms/casino/6144.yaml deleted file mode 100644 index cc30669..0000000 --- a/data/rooms/casino/6144.yaml +++ /dev/null @@ -1,6 +0,0 @@ -name: First Gallery Future Wheel Gallery -description: Power sockets, table anchor points and service passages are installed, but there is no playable - game here yet. This hall is reserved for a future casino expansion. -exits: - east: - room: 6143 diff --git a/data/rooms/casino/6145.yaml b/data/rooms/casino/6145.yaml deleted file mode 100644 index 60f1e0f..0000000 --- a/data/rooms/casino/6145.yaml +++ /dev/null @@ -1,5 +0,0 @@ -name: First Gallery Exhibition Room -description: Building models show the corporation’s increasingly extravagant plans. -exits: - west: - room: 6143 diff --git a/data/rooms/casino/6146.yaml b/data/rooms/casino/6146.yaml deleted file mode 100644 index 04a9521..0000000 --- a/data/rooms/casino/6146.yaml +++ /dev/null @@ -1,12 +0,0 @@ -name: First Gallery North Promenade -description: The first gallery is freely open for exploration. Completed corridors face unfurnished gaming - rooms; signs explicitly say that no games operate on this floor yet. -exits: - south: - room: 6143 - west: - room: 6147 - east: - room: 6148 - north: - room: 6149 diff --git a/data/rooms/casino/6147.yaml b/data/rooms/casino/6147.yaml deleted file mode 100644 index 2b85741..0000000 --- a/data/rooms/casino/6147.yaml +++ /dev/null @@ -1,6 +0,0 @@ -name: First Gallery Future Dice Salon -description: Power sockets, table anchor points and service passages are installed, but there is no playable - game here yet. This hall is reserved for a future casino expansion. -exits: - east: - room: 6146 diff --git a/data/rooms/casino/6148.yaml b/data/rooms/casino/6148.yaml deleted file mode 100644 index c9982b5..0000000 --- a/data/rooms/casino/6148.yaml +++ /dev/null @@ -1,7 +0,0 @@ -name: First Gallery Staff History Gallery -description: Photographs remember workers whose names do not appear on the marble dedication. -exits: - west: - room: 6146 -mobs: -- id: casino_patron diff --git a/data/rooms/casino/6149.yaml b/data/rooms/casino/6149.yaml deleted file mode 100644 index e40a521..0000000 --- a/data/rooms/casino/6149.yaml +++ /dev/null @@ -1,14 +0,0 @@ -name: First Gallery Grand Stair -description: The first gallery is freely open for exploration. Completed corridors face unfurnished gaming - rooms; signs explicitly say that no games operate on this floor yet. -exits: - south: - room: 6146 - down: - room: 6102 - west: - room: 6150 - east: - room: 6151 - up: - room: 6164 diff --git a/data/rooms/casino/6150.yaml b/data/rooms/casino/6150.yaml deleted file mode 100644 index 8e627fd..0000000 --- a/data/rooms/casino/6150.yaml +++ /dev/null @@ -1,6 +0,0 @@ -name: First Gallery Future Private Table Hall -description: Power sockets, table anchor points and service passages are installed, but there is no playable - game here yet. This hall is reserved for a future casino expansion. -exits: - east: - room: 6149 diff --git a/data/rooms/casino/6151.yaml b/data/rooms/casino/6151.yaml deleted file mode 100644 index f0d2e9f..0000000 --- a/data/rooms/casino/6151.yaml +++ /dev/null @@ -1,5 +0,0 @@ -name: First Gallery Viewing Terrace -description: A long window gives a clear view of the roads that belong to everyone. -exits: - west: - room: 6149 diff --git a/data/rooms/casino/6152.yaml b/data/rooms/casino/6152.yaml deleted file mode 100644 index 9433ce8..0000000 --- a/data/rooms/casino/6152.yaml +++ /dev/null @@ -1,10 +0,0 @@ -name: Second Gallery South Rotunda -description: The second gallery is freely open for exploration. Completed corridors face unfurnished gaming - rooms; signs explicitly say that no games operate on this floor yet. -exits: - west: - room: 6153 - east: - room: 6154 - north: - room: 6155 diff --git a/data/rooms/casino/6153.yaml b/data/rooms/casino/6153.yaml deleted file mode 100644 index 34b51b4..0000000 --- a/data/rooms/casino/6153.yaml +++ /dev/null @@ -1,6 +0,0 @@ -name: Second Gallery Future Tournament Hall -description: Power sockets, table anchor points and service passages are installed, but there is no playable - game here yet. This hall is reserved for a future casino expansion. -exits: - east: - room: 6152 diff --git a/data/rooms/casino/6154.yaml b/data/rooms/casino/6154.yaml deleted file mode 100644 index a05fd8a..0000000 --- a/data/rooms/casino/6154.yaml +++ /dev/null @@ -1,5 +0,0 @@ -name: Second Gallery Balcony Lounge -description: A sheltered balcony overlooks the city without requiring a ticket. -exits: - west: - room: 6152 diff --git a/data/rooms/casino/6155.yaml b/data/rooms/casino/6155.yaml deleted file mode 100644 index b0ddb4d..0000000 --- a/data/rooms/casino/6155.yaml +++ /dev/null @@ -1,12 +0,0 @@ -name: Second Gallery Promenade -description: The second gallery is freely open for exploration. Completed corridors face unfurnished gaming - rooms; signs explicitly say that no games operate on this floor yet. -exits: - south: - room: 6152 - west: - room: 6156 - east: - room: 6157 - north: - room: 6158 diff --git a/data/rooms/casino/6156.yaml b/data/rooms/casino/6156.yaml deleted file mode 100644 index a879c4b..0000000 --- a/data/rooms/casino/6156.yaml +++ /dev/null @@ -1,6 +0,0 @@ -name: Second Gallery Future Card Salon -description: Power sockets, table anchor points and service passages are installed, but there is no playable - game here yet. This hall is reserved for a future casino expansion. -exits: - east: - room: 6155 diff --git a/data/rooms/casino/6157.yaml b/data/rooms/casino/6157.yaml deleted file mode 100644 index 83add4d..0000000 --- a/data/rooms/casino/6157.yaml +++ /dev/null @@ -1,5 +0,0 @@ -name: Second Gallery Refreshment Room -description: Empty serving counters stand ready for the next expansion. -exits: - west: - room: 6155 diff --git a/data/rooms/casino/6158.yaml b/data/rooms/casino/6158.yaml deleted file mode 100644 index fb598e4..0000000 --- a/data/rooms/casino/6158.yaml +++ /dev/null @@ -1,12 +0,0 @@ -name: Second Gallery Central Landing -description: The second gallery is freely open for exploration. Completed corridors face unfurnished gaming - rooms; signs explicitly say that no games operate on this floor yet. -exits: - south: - room: 6155 - west: - room: 6159 - east: - room: 6160 - north: - room: 6161 diff --git a/data/rooms/casino/6159.yaml b/data/rooms/casino/6159.yaml deleted file mode 100644 index fff90ea..0000000 --- a/data/rooms/casino/6159.yaml +++ /dev/null @@ -1,6 +0,0 @@ -name: Second Gallery Future Wheel Gallery -description: Power sockets, table anchor points and service passages are installed, but there is no playable - game here yet. This hall is reserved for a future casino expansion. -exits: - east: - room: 6158 diff --git a/data/rooms/casino/6160.yaml b/data/rooms/casino/6160.yaml deleted file mode 100644 index 4c71e15..0000000 --- a/data/rooms/casino/6160.yaml +++ /dev/null @@ -1,5 +0,0 @@ -name: Second Gallery Exhibition Room -description: Building models show the corporation’s increasingly extravagant plans. -exits: - west: - room: 6158 diff --git a/data/rooms/casino/6161.yaml b/data/rooms/casino/6161.yaml deleted file mode 100644 index 750c8ea..0000000 --- a/data/rooms/casino/6161.yaml +++ /dev/null @@ -1,12 +0,0 @@ -name: Second Gallery North Promenade -description: The second gallery is freely open for exploration. Completed corridors face unfurnished gaming - rooms; signs explicitly say that no games operate on this floor yet. -exits: - south: - room: 6158 - west: - room: 6162 - east: - room: 6163 - north: - room: 6164 diff --git a/data/rooms/casino/6162.yaml b/data/rooms/casino/6162.yaml deleted file mode 100644 index c083708..0000000 --- a/data/rooms/casino/6162.yaml +++ /dev/null @@ -1,6 +0,0 @@ -name: Second Gallery Future Dice Salon -description: Power sockets, table anchor points and service passages are installed, but there is no playable - game here yet. This hall is reserved for a future casino expansion. -exits: - east: - room: 6161 diff --git a/data/rooms/casino/6163.yaml b/data/rooms/casino/6163.yaml deleted file mode 100644 index 58983a0..0000000 --- a/data/rooms/casino/6163.yaml +++ /dev/null @@ -1,5 +0,0 @@ -name: Second Gallery Staff History Gallery -description: Photographs remember workers whose names do not appear on the marble dedication. -exits: - west: - room: 6161 diff --git a/data/rooms/casino/6164.yaml b/data/rooms/casino/6164.yaml deleted file mode 100644 index 2cf8ee1..0000000 --- a/data/rooms/casino/6164.yaml +++ /dev/null @@ -1,14 +0,0 @@ -name: Second Gallery Grand Stair -description: The second gallery is freely open for exploration. Completed corridors face unfurnished gaming - rooms; signs explicitly say that no games operate on this floor yet. -exits: - south: - room: 6161 - down: - room: 6149 - west: - room: 6165 - east: - room: 6166 - up: - room: 6179 diff --git a/data/rooms/casino/6165.yaml b/data/rooms/casino/6165.yaml deleted file mode 100644 index f588711..0000000 --- a/data/rooms/casino/6165.yaml +++ /dev/null @@ -1,6 +0,0 @@ -name: Second Gallery Future Private Table Hall -description: Power sockets, table anchor points and service passages are installed, but there is no playable - game here yet. This hall is reserved for a future casino expansion. -exits: - east: - room: 6164 diff --git a/data/rooms/casino/6166.yaml b/data/rooms/casino/6166.yaml deleted file mode 100644 index ce4c421..0000000 --- a/data/rooms/casino/6166.yaml +++ /dev/null @@ -1,5 +0,0 @@ -name: Second Gallery Viewing Terrace -description: A long window gives a clear view of the roads that belong to everyone. -exits: - west: - room: 6164 diff --git a/data/rooms/casino/6167.yaml b/data/rooms/casino/6167.yaml deleted file mode 100644 index 35dc3aa..0000000 --- a/data/rooms/casino/6167.yaml +++ /dev/null @@ -1,10 +0,0 @@ -name: Crown Floor South Rotunda -description: The crown floor is freely open for exploration. Completed corridors face unfurnished gaming - rooms; signs explicitly say that no games operate on this floor yet. -exits: - west: - room: 6168 - east: - room: 6169 - north: - room: 6170 diff --git a/data/rooms/casino/6168.yaml b/data/rooms/casino/6168.yaml deleted file mode 100644 index 5b5822e..0000000 --- a/data/rooms/casino/6168.yaml +++ /dev/null @@ -1,6 +0,0 @@ -name: Crown Floor Future Tournament Hall -description: Power sockets, table anchor points and service passages are installed, but there is no playable - game here yet. This hall is reserved for a future casino expansion. -exits: - east: - room: 6167 diff --git a/data/rooms/casino/6169.yaml b/data/rooms/casino/6169.yaml deleted file mode 100644 index ae54bca..0000000 --- a/data/rooms/casino/6169.yaml +++ /dev/null @@ -1,5 +0,0 @@ -name: Crown Floor Balcony Lounge -description: A sheltered balcony overlooks the city without requiring a ticket. -exits: - west: - room: 6167 diff --git a/data/rooms/casino/6170.yaml b/data/rooms/casino/6170.yaml deleted file mode 100644 index d275920..0000000 --- a/data/rooms/casino/6170.yaml +++ /dev/null @@ -1,12 +0,0 @@ -name: Crown Floor Promenade -description: The crown floor is freely open for exploration. Completed corridors face unfurnished gaming - rooms; signs explicitly say that no games operate on this floor yet. -exits: - south: - room: 6167 - west: - room: 6171 - east: - room: 6172 - north: - room: 6173 diff --git a/data/rooms/casino/6171.yaml b/data/rooms/casino/6171.yaml deleted file mode 100644 index 41fbe05..0000000 --- a/data/rooms/casino/6171.yaml +++ /dev/null @@ -1,6 +0,0 @@ -name: Crown Floor Future Card Salon -description: Power sockets, table anchor points and service passages are installed, but there is no playable - game here yet. This hall is reserved for a future casino expansion. -exits: - east: - room: 6170 diff --git a/data/rooms/casino/6172.yaml b/data/rooms/casino/6172.yaml deleted file mode 100644 index 44e9161..0000000 --- a/data/rooms/casino/6172.yaml +++ /dev/null @@ -1,5 +0,0 @@ -name: Crown Floor Refreshment Room -description: Empty serving counters stand ready for the next expansion. -exits: - west: - room: 6170 diff --git a/data/rooms/casino/6173.yaml b/data/rooms/casino/6173.yaml deleted file mode 100644 index 1fd3e12..0000000 --- a/data/rooms/casino/6173.yaml +++ /dev/null @@ -1,12 +0,0 @@ -name: Crown Floor Central Landing -description: The crown floor is freely open for exploration. Completed corridors face unfurnished gaming - rooms; signs explicitly say that no games operate on this floor yet. -exits: - south: - room: 6170 - west: - room: 6174 - east: - room: 6175 - north: - room: 6176 diff --git a/data/rooms/casino/6174.yaml b/data/rooms/casino/6174.yaml deleted file mode 100644 index dd31f28..0000000 --- a/data/rooms/casino/6174.yaml +++ /dev/null @@ -1,6 +0,0 @@ -name: Crown Floor Future Wheel Gallery -description: Power sockets, table anchor points and service passages are installed, but there is no playable - game here yet. This hall is reserved for a future casino expansion. -exits: - east: - room: 6173 diff --git a/data/rooms/casino/6175.yaml b/data/rooms/casino/6175.yaml deleted file mode 100644 index ec79025..0000000 --- a/data/rooms/casino/6175.yaml +++ /dev/null @@ -1,5 +0,0 @@ -name: Crown Floor Exhibition Room -description: Building models show the corporation’s increasingly extravagant plans. -exits: - west: - room: 6173 diff --git a/data/rooms/casino/6176.yaml b/data/rooms/casino/6176.yaml deleted file mode 100644 index d1a0ba6..0000000 --- a/data/rooms/casino/6176.yaml +++ /dev/null @@ -1,12 +0,0 @@ -name: Crown Floor North Promenade -description: The crown floor is freely open for exploration. Completed corridors face unfurnished gaming - rooms; signs explicitly say that no games operate on this floor yet. -exits: - south: - room: 6173 - west: - room: 6177 - east: - room: 6178 - north: - room: 6179 diff --git a/data/rooms/casino/6177.yaml b/data/rooms/casino/6177.yaml deleted file mode 100644 index be5d0e9..0000000 --- a/data/rooms/casino/6177.yaml +++ /dev/null @@ -1,6 +0,0 @@ -name: Crown Floor Future Dice Salon -description: Power sockets, table anchor points and service passages are installed, but there is no playable - game here yet. This hall is reserved for a future casino expansion. -exits: - east: - room: 6176 diff --git a/data/rooms/casino/6178.yaml b/data/rooms/casino/6178.yaml deleted file mode 100644 index 4929fec..0000000 --- a/data/rooms/casino/6178.yaml +++ /dev/null @@ -1,5 +0,0 @@ -name: Crown Floor Staff History Gallery -description: Photographs remember workers whose names do not appear on the marble dedication. -exits: - west: - room: 6176 diff --git a/data/rooms/casino/6179.yaml b/data/rooms/casino/6179.yaml deleted file mode 100644 index 7a9e652..0000000 --- a/data/rooms/casino/6179.yaml +++ /dev/null @@ -1,12 +0,0 @@ -name: Crown Floor Grand Stair -description: The crown floor is freely open for exploration. Completed corridors face unfurnished gaming - rooms; signs explicitly say that no games operate on this floor yet. -exits: - south: - room: 6176 - down: - room: 6164 - west: - room: 6180 - east: - room: 6181 diff --git a/data/rooms/casino/6180.yaml b/data/rooms/casino/6180.yaml deleted file mode 100644 index 2a83860..0000000 --- a/data/rooms/casino/6180.yaml +++ /dev/null @@ -1,6 +0,0 @@ -name: Crown Floor Future Private Table Hall -description: Power sockets, table anchor points and service passages are installed, but there is no playable - game here yet. This hall is reserved for a future casino expansion. -exits: - east: - room: 6179 diff --git a/data/rooms/casino/6181.yaml b/data/rooms/casino/6181.yaml deleted file mode 100644 index 78927b6..0000000 --- a/data/rooms/casino/6181.yaml +++ /dev/null @@ -1,5 +0,0 @@ -name: Crown Floor Viewing Terrace -description: A long window gives a clear view of the roads that belong to everyone. -exits: - west: - room: 6179 diff --git a/data/rooms/casino/6182.yaml b/data/rooms/casino/6182.yaml index c298be1..9ee541a 100644 --- a/data/rooms/casino/6182.yaml +++ b/data/rooms/casino/6182.yaml @@ -1,14 +1,14 @@ name: Single Zero Roulette Salon -description: A polished European wheel turns beside green felt marked with a single zero. The dealer invites visitors to play roulette. +description: A polished European wheel turns beside green felt marked with a single zero. The double-zero wheel waits north, the racetrack south, and the craps pit east. exits: - south: - room: 6102 + west: + room: 6127 + east: + room: 6185 north: room: 6183 - east: + south: room: 6184 - west: - room: 6185 casino_tables: - id: roulette_single game: roulette diff --git a/data/rooms/casino/6183.yaml b/data/rooms/casino/6183.yaml index 68f12bc..ac98df9 100644 --- a/data/rooms/casino/6183.yaml +++ b/data/rooms/casino/6183.yaml @@ -1,5 +1,5 @@ name: Double Zero Roulette Salon -description: An American roulette wheel gleams under brass lamps. Its green zero and double-zero pockets face a neatly marked betting layout. +description: An American roulette wheel gleams under brass lamps; its green zero and double-zero pockets face a neatly marked betting layout. exits: south: room: 6182 diff --git a/data/rooms/casino/6184.yaml b/data/rooms/casino/6184.yaml index 76c9cf1..745a333 100644 --- a/data/rooms/casino/6184.yaml +++ b/data/rooms/casino/6184.yaml @@ -1,7 +1,7 @@ name: Racetrack Roulette Salon -description: A single-zero wheel turns above a long oval racetrack painted on green felt. Brass plaques name the French call bets for players who prefer the wheel's own neighbours. +description: A single-zero wheel turns above a long oval racetrack painted on green felt. Brass plaques name the French call bets. exits: - west: + north: room: 6182 casino_tables: - id: roulette_racetrack diff --git a/data/rooms/casino/6185.yaml b/data/rooms/casino/6185.yaml index 05e6bcf..11e7805 100644 --- a/data/rooms/casino/6185.yaml +++ b/data/rooms/casino/6185.yaml @@ -1,10 +1,14 @@ name: Bank Craps Pit -description: A sweeping green felt table curves beneath warm brass lamps. Ivory dice rest beside a polished stick, while a bright puck marks the point above the numbered boxes. Inlaid plaques advertise Fire and All Tall Small bets. A northern gallery leads to six house-edition craps tables, each with its own posted rules. +description: A sweeping green felt table curves beneath warm brass lamps. Ivory dice rest beside a polished stick, and a bright puck marks the point. House editions wait north and south; slots lie east. exits: + west: + room: 6182 + east: + room: 6118 north: room: 6186 - east: - room: 6182 + south: + room: 6189 casino_tables: - id: bank_craps game: craps diff --git a/data/rooms/casino/6186.yaml b/data/rooms/casino/6186.yaml index ff21553..efece43 100644 --- a/data/rooms/casino/6186.yaml +++ b/data/rooms/casino/6186.yaml @@ -1,5 +1,5 @@ name: Simplified Craps Gallery -description: A small felt table offers a brisk single-roll game. Its brass plaque reads 'Simplified — house edition; pass only.' The bank pit lies south, with more variations continuing north. +description: A brisk single-roll game — pass only; the dice roll on their own three seconds after a bet. exits: south: room: 6185 diff --git a/data/rooms/casino/6187.yaml b/data/rooms/casino/6187.yaml index 84cf6fb..169ad81 100644 --- a/data/rooms/casino/6187.yaml +++ b/data/rooms/casino/6187.yaml @@ -1,5 +1,5 @@ name: High Point Craps Gallery -description: Ascending brass numerals surround a compact felt. A plaque explains that this house edition requires the next total to exceed the point. Simplified craps lies south; crapless craps is north. +description: Ascending brass numerals surround a compact felt; the next total must exceed the point. exits: south: room: 6186 diff --git a/data/rooms/casino/6188.yaml b/data/rooms/casino/6188.yaml index bb248f8..92caf26 100644 --- a/data/rooms/casino/6188.yaml +++ b/data/rooms/casino/6188.yaml @@ -1,10 +1,8 @@ name: Crapless Craps Gallery -description: Extra boxes for two, three, eleven and twelve stretch across the felt. A warning makes clear that these totals become points rather than instant losses or wins. High Point lies south; New York craps is north. +description: Every total can be the point here — only the seven wins on the come-out. exits: south: room: 6187 - north: - room: 6189 casino_tables: - id: crapless_craps game: craps diff --git a/data/rooms/casino/6189.yaml b/data/rooms/casino/6189.yaml index 89c78d6..b42eaba 100644 --- a/data/rooms/casino/6189.yaml +++ b/data/rooms/casino/6189.yaml @@ -1,9 +1,9 @@ name: New York Craps Gallery -description: A restrained layout displays pass, don't pass, buy and lay wagers. The house-edition plaque promises win-only commissions and no proposition bets. Crapless lies south; Die Rich is north. +description: Banker pass, don’t pass, buy and lay bets only, with a 5% win-only commission. exits: - south: - room: 6188 north: + room: 6185 + south: room: 6190 casino_tables: - id: new_york_craps diff --git a/data/rooms/casino/6190.yaml b/data/rooms/casino/6190.yaml index de23373..3577103 100644 --- a/data/rooms/casino/6190.yaml +++ b/data/rooms/casino/6190.yaml @@ -1,9 +1,9 @@ name: Die Rich Craps Gallery -description: A single ivory die rests in a shallow tray. The house-edition plaque reads 'Six wins coming out; one loses; repeat any other point before one.' New York lies south; the card-driven Diceless table is north. +description: A single die in play — come-out 6 wins, 1 loses, and 2-5 become the point. exits: - south: - room: 6189 north: + room: 6189 + south: room: 6191 casino_tables: - id: die_rich_craps diff --git a/data/rooms/casino/6191.yaml b/data/rooms/casino/6191.yaml index 81ebcc0..05313fc 100644 --- a/data/rooms/casino/6191.yaml +++ b/data/rooms/casino/6191.yaml @@ -1,7 +1,7 @@ name: Diceless Craps Salon -description: Two six-card packs labelled A and B replace the dice on a full bank-craps layout. The dealer replaces and reshuffles both packs after every draw. The variations gallery returns south through Die Rich. +description: Two packs of cards numbered 1-6 replace the dice; every draw is reshuffled. exits: - south: + north: room: 6190 casino_tables: - id: diceless_craps diff --git a/internal/casino/baccarat.go b/internal/casino/baccarat.go index 0890d59..50ac111 100644 --- a/internal/casino/baccarat.go +++ b/internal/casino/baccarat.go @@ -72,7 +72,11 @@ func (t *baccaratTable) join(name string) []Event { return []Event{t.private(name, "That baccarat table is full.")} } events := []Event{t.addSeatLocked(name, &baccaratPlayer{Participant: Participant{Name: name, Connected: true}})} - events = append(events, t.private(name, t.Config.BaccaratRulesText()), t.menuEvent(name)) + // The rules board is a rendered felt (presentation layer); the engine + // only ships the configuration. + rules := t.private(name, "") + rules.Snapshot = &BaccaratRulesView{Config: t.Config} + events = append(events, rules, t.menuEvent(name)) return events } diff --git a/internal/casino/baccarat_variants_test.go b/internal/casino/baccarat_variants_test.go index 4f88227..094412e 100644 --- a/internal/casino/baccarat_variants_test.go +++ b/internal/casino/baccarat_variants_test.go @@ -89,8 +89,17 @@ func TestBaccaratEZLiveSettlementAndOptionalMenus(t *testing.T) { cfg := TableConfig{ID: "ez", Game: GameBaccarat, Baccarat: BaccaratConfig{Variant: BaccaratEZ, Dragon7: true}} table := newBaccaratTestTable(cfg) events := table.join("alice") - if !hasMessage(events, "Variant: EZ Baccarat") || !hasMessage(events, "dragon_7") { - t.Fatal("join missing rules/optional wager") + rulesView := false + for _, e := range events { + if view, ok := e.Snapshot.(*BaccaratRulesView); ok { + rulesView = true + if !view.Config.Baccarat.Dragon7 { + t.Fatal("rules felt missing the enabled Dragon 7 wager") + } + } + } + if !rulesView { + t.Fatal("join missing rules felt") } table.join("bob") forceShoe(table, baccaratCards("A A A A 2 5")...) diff --git a/internal/casino/blackjack.go b/internal/casino/blackjack.go index 53bee6c..bd5b86b 100644 --- a/internal/casino/blackjack.go +++ b/internal/casino/blackjack.go @@ -139,7 +139,11 @@ func (t *blackjackTable) join(name string) []Event { return []Event{t.private(name, "That blackjack table is full.")} } events := []Event{t.addSeatLocked(name, &blackjackPlayer{Participant: Participant{Name: name, Connected: true}})} - events = append(events, t.private(name, t.Config.BlackjackRulesText()), t.menuEvent(name)) + // The rules board is a rendered felt (presentation layer); the engine + // only ships the configuration. + rules := t.private(name, "") + rules.Snapshot = &BlackjackRulesView{Config: t.Config} + events = append(events, rules, t.menuEvent(name)) return events } diff --git a/internal/casino/blackjack_rules_test.go b/internal/casino/blackjack_rules_test.go index 62f4d0a..b0c9459 100644 --- a/internal/casino/blackjack_rules_test.go +++ b/internal/casino/blackjack_rules_test.go @@ -27,7 +27,7 @@ func TestBlackjackRuleCardDefaultsAndOverrides(t *testing.T) { events := table.join("alice") found := false for _, e := range events { - if e.Message == text { + if view, ok := e.Snapshot.(*BlackjackRulesView); ok && view.Config.Blackjack == table.Config.Blackjack { found = true if e.Public { t.Error("rules broadcast to bystanders") @@ -35,7 +35,7 @@ func TestBlackjackRuleCardDefaultsAndOverrides(t *testing.T) { } } if !found { - t.Fatal("joining did not display effective rules") + t.Fatal("joining did not ship the rules view") } } } diff --git a/internal/casino/types.go b/internal/casino/types.go index 62a8f34..ecded85 100644 --- a/internal/casino/types.go +++ b/internal/casino/types.go @@ -323,6 +323,14 @@ type BlackjackSnapshot struct { func (*BlackjackSnapshot) snapshot() {} +// BlackjackRulesView ships a table's configuration so the presentation layer +// can draw the house-rule felt instead of a raw rules dump. +type BlackjackRulesView struct { + Config TableConfig +} + +func (*BlackjackRulesView) snapshot() {} + // BaccaratBetView lists one participant's wager on a baccarat outcome. type BaccaratBetView struct { Name string @@ -340,6 +348,14 @@ type BaccaratSnapshot struct { func (*BaccaratSnapshot) snapshot() {} +// BaccaratRulesView ships a table's configuration so the presentation layer +// can draw the house-rule felt instead of a raw rules dump. +type BaccaratRulesView struct { + Config TableConfig +} + +func (*BaccaratRulesView) snapshot() {} + type Participant struct { Name string Connected bool diff --git a/internal/game/baccarat_rules_test.go b/internal/game/baccarat_rules_test.go index 14328c1..63e2dc2 100644 --- a/internal/game/baccarat_rules_test.go +++ b/internal/game/baccarat_rules_test.go @@ -28,9 +28,10 @@ func TestLookBaccaratFixtureWithoutScenery(t *testing.T) { for _, target := range []string{"baccarat", "baccarat table", "table", "test", "test table"} { conn.data = nil g.doLookTarget(sess, target) - for _, want := range []string{"Variant: EZ Baccarat", "Number of decks: 6", "Dragon 7 (dragon_7): Enabled; 40:1", "Panda 8 (panda_8): Not offered"} { - if !strings.Contains(string(conn.data), want) { - t.Fatalf("look %s missing %q: %s", target, want, conn.data) + text := plainRoulette(string(conn.data)) + for _, want := range []string{"EZ BACCARAT — NO COMMISSION", "DECKS", "6", "DRAGON 7", "40:1", "PANDA 8", "NOT OFFERED"} { + if !strings.Contains(text, want) { + t.Fatalf("look %s missing %q: %s", target, want, text) } } } @@ -67,12 +68,16 @@ func TestCasinoFloorBaccaratProfiles(t *testing.T) { events := g.Casino.Join(tc.room, cfg, "alice") found := false for _, e := range events { - if e.Message == cfg.BaccaratRulesText() { + if view, ok := e.Snapshot.(*casino.BaccaratRulesView); ok { found = true + art := renderBaccaratRulesFelt(view.Config, "none", true) + if !strings.Contains(art, "DRAWING — AUTOMATIC PUNTO BANCO") { + t.Fatalf("room %d: rules felt incomplete", tc.room) + } } } if !found { - t.Fatalf("room %d: join missing rule card", tc.room) + t.Fatalf("room %d: join missing rules felt", tc.room) } if !strings.Contains(cfg.BaccaratRulesText(), tc.spot+"): Enabled") { t.Fatalf("room %d: missing optional bet", tc.room) diff --git a/internal/game/blackjack_rules_test.go b/internal/game/blackjack_rules_test.go index 33598c3..47d057c 100644 --- a/internal/game/blackjack_rules_test.go +++ b/internal/game/blackjack_rules_test.go @@ -29,9 +29,10 @@ func TestLookBlackjackFixtureWithoutScenery(t *testing.T) { if !g.lookBlackjackTable(sess, target) { t.Fatalf("did not match %q", target) } - for _, want := range []string{"Number of decks: 1", "Blackjack pays 6:5", "Double after split: Yes"} { - if !strings.Contains(string(conn.data), want) { - t.Fatalf("look %s missing %q: %s", target, want, conn.data) + text := plainRoulette(string(conn.data)) + for _, want := range []string{"DECKS", "1", "BLACKJACK PAYS 6 TO 5", "AFTER SPLIT" + strings.Repeat(" ", 21) + "YES"} { + if !strings.Contains(text, want) { + t.Fatalf("look %s missing %q: %s", target, want, text) } } } diff --git a/internal/game/casino.go b/internal/game/casino.go index 744eac6..f29efd6 100644 --- a/internal/game/casino.go +++ b/internal/game/casino.go @@ -719,6 +719,10 @@ func (g *Game) renderCasinoSnapshot(sess *net.Session, snapshot casino.Snapshot) return renderSlotSnapshot(s, mode, unicode) case *casino.BlackjackSnapshot: return renderBlackjackSnapshotFor(s, mode, unicode, size, sess.Player.OptionString("card_style"), g.CardArt, sess.Player.Name) + case *casino.BlackjackRulesView: + return renderBlackjackRulesFelt(s.Config, mode, unicode) + case *casino.BaccaratRulesView: + return renderBaccaratRulesFelt(s.Config, mode, unicode) case *casino.BaccaratSnapshot: return renderBaccaratSnapshot(s, mode, unicode, size, sess.Player.OptionString("card_style"), g.CardArt) } diff --git a/internal/game/casino_ux_test.go b/internal/game/casino_ux_test.go index 0d5ad63..aa98c87 100644 --- a/internal/game/casino_ux_test.go +++ b/internal/game/casino_ux_test.go @@ -96,7 +96,7 @@ func TestTableStatusShowsStateAndRules(t *testing.T) { } conn.data = nil g.executeTableStatus(sess, []string{"rules"}, "table rules") - if !strings.Contains(stripANSI(string(conn.data)), "payout") { + if !strings.Contains(stripANSI(string(conn.data)), "BLACKJACK PAYS") { t.Fatalf("table rules missing: %q", stripANSI(string(conn.data))) } } diff --git a/internal/game/craps_variants_test.go b/internal/game/craps_variants_test.go index 76d1424..42f3529 100644 --- a/internal/game/craps_variants_test.go +++ b/internal/game/craps_variants_test.go @@ -64,40 +64,57 @@ func TestCrapsVariantRendering(t *testing.T) { func TestShippedCrapsGallery(t *testing.T) { w := world.New(filepath.Join("..", "..", "data")) - variants := []string{"bank", "simplified", "high_point", "crapless", "new_york", "die_rich", "diceless"} - for i, v := range variants { - id := 6185 + i - room, err := w.LoadRoom(id) - if err != nil { - t.Fatal(err) - } - if len(room.CasinoTables) != 1 { - t.Fatal(id, "missing table") + northVariants := []string{"simplified", "high_point", "crapless"} + southVariants := []string{"new_york", "die_rich", "diceless"} + for i, v := range northVariants { + id := 6186 + i + room := loadCrapsRoom(t, w, id, v) + if i > 0 && room.Exits["south"].Room != id-1 { + t.Fatal(id, "missing return exit") } - cfg := room.CasinoTables[0] - if cfg.Game != casino.GameCraps || cfg.Craps.Variant != v { - t.Fatal(id, cfg) + if i < len(northVariants)-1 && room.Exits["north"].Room != id+1 { + t.Fatal(id, "unreachable next table") } - if err := cfg.Validate(); err != nil { - t.Fatal(id, err) + } + for i, v := range southVariants { + id := 6189 + i + room := loadCrapsRoom(t, w, id, v) + if i == 0 && room.Exits["north"].Room != 6185 { + t.Fatal(id, "south gallery unreachable from the bank pit") } - if i > 0 && room.Exits["south"].Room != id-1 { + if i > 0 && room.Exits["north"].Room != id-1 { t.Fatal(id, "missing return exit") } - if i < len(variants)-1 && room.Exits["north"].Room != id+1 { + if i < len(southVariants)-1 && room.Exits["south"].Room != id+1 { t.Fatal(id, "unreachable next table") } - m := casino.NewManager(1) - m.Join(id, cfg, "a") - if m.Table(id, cfg.ID) == nil { - t.Fatal(id, "table registration") - } } - room, err := w.LoadRoom(6182) + room := loadCrapsRoom(t, w, 6185, "bank") + if room.Exits["west"].Room != 6182 || room.Exits["east"].Room != 6118 { + t.Fatal("pit exits missing", room.Exits) + } +} + +func loadCrapsRoom(t *testing.T, w *world.World, id int, variant string) *world.Room { + t.Helper() + room, err := w.LoadRoom(id) if err != nil { t.Fatal(err) } - if room.Exits["west"].Room != 6185 { - t.Fatal("gallery unreachable from roulette") + if len(room.CasinoTables) != 1 { + t.Fatal(id, "missing table") + } + cfg := room.CasinoTables[0] + if cfg.Game != casino.GameCraps || cfg.Craps.Variant != variant { + t.Fatal(id, cfg) + } + if err := cfg.Validate(); err != nil { + t.Fatal(id, err) + } + m := casino.NewManager(1) + m.Join(id, cfg, "a") + if m.Table(id, cfg.ID) == nil { + t.Fatal(id, "table registration") } + return room } diff --git a/internal/game/render_baccarat_felt.go b/internal/game/render_baccarat_felt.go new file mode 100644 index 0000000..84f91e3 --- /dev/null +++ b/internal/game/render_baccarat_felt.go @@ -0,0 +1,111 @@ +package game + +import ( + "fmt" + "strings" + + "thehouseoficarus/internal/casino" +) + +// A baccarat felt: the three main wagers as betting boxes, the optional side +// bets and house settings in labelled boxes, and the punto banco drawing +// table across the bottom. Reuses the shared felt canvas and palette. +func renderBaccaratRulesFelt(cfg casino.TableConfig, mode string, unicode bool) string { + b := cfg.Baccarat.Normalize() + c := newCrapsCanvas(22) + // Title block: variant, scoring, naturals. + c.box(0, 0, 76, 4) + c.center(1, 75, 1, baccaratVariantTitle(b), crapsGold) + c.center(1, 75, 2, "ACE 1 | 2-9 FACE | 10/J/Q/K 0 — HIGHEST LAST DIGIT WINS", crapsInk) + c.center(1, 75, 3, "AN INITIAL 8 OR 9 ON EITHER HAND STOPS ALL DRAWING", crapsMuted) + // Three betting boxes: PLAYER | TIE | BANKER. + spots := [3][2]int{{0, 25}, {25, 50}, {50, 76}} + for _, x := range spots { + c.box(x[0], 4, x[1], 8) + } + c.center(1, 24, 5, "PLAYER", crapsGold) + c.center(26, 49, 5, "TIE", crapsGold) + c.center(51, 75, 5, "BANKER", crapsGold) + c.center(1, 24, 6, "PAYS 1:1", crapsInk) + c.center(26, 49, 6, "PAYS "+ratioText(b.TiePayout), crapsInk) + c.center(51, 75, 6, bankerPayoutText(b), crapsInk) + c.center(1, 24, 7, "", crapsMuted) + c.center(26, 49, 7, "PLAYER & BANKER PUSH", crapsMuted) + c.center(51, 75, 7, bankerNoteText(b), crapsMuted) + // Side bets and house settings. + boxY := [2][2]int{{8, 15}, {8, 15}} + xs := [2][2]int{{0, 38}, {38, 76}} + for i := range boxY { + c.box(xs[i][0], boxY[i][0], xs[i][1], boxY[i][1]) + } + c.center(1, 37, 9, "SIDE BETS", crapsGold) + c.center(39, 75, 9, "HOUSE", crapsGold) + side := [][2]string{ + {"PLAYER PAIR", optionalText(b.PairBets, "11:1")}, + {"BANKER PAIR", optionalText(b.PairBets, "11:1")}, + {"DRAGON 7", optionalText(b.Dragon7, "40:1")}, + {"PANDA 8", optionalText(b.Panda8, "25:1")}, + {"SUPER 6", optionalText(b.Super6Bet, "12:1")}, + } + house := [][2]string{ + {"DECKS", fmt.Sprintf("%d", b.Decks)}, + {"SHUFFLE AT", fmt.Sprintf("%g%% REMAINING", b.ShuffleAt*100)}, + {"BET LIMITS", betLimitsText(cfg.MinBet, cfg.MaxBet)}, + {"SEATS", fmt.Sprintf("%d", cfg.MaxPlayers)}, + {"BETTING WINDOW", fmt.Sprintf("%d TICKS", cfg.BettingTicks)}, + } + for j, row := range side { + c.bjRule(0, 38, 10+j, row[0], row[1]) + } + for j, row := range house { + c.bjRule(38, 76, 10+j, row[0], row[1]) + } + // Drawing table across the bottom. + c.box(0, 15, 76, 21) + c.center(1, 75, 16, "DRAWING — AUTOMATIC PUNTO BANCO", crapsGold) + draw := []string{ + "PLAYER: DRAWS 0-5; STANDS 6-7. BANKER VS A STANDING PLAYER: DRAWS 0-5.", + "BANKER VS A DRAWING PLAYER: 0-2 ALWAYS DRAWS; 3 DRAWS UNLESS VS 8;", + "4 DRAWS VS 2-7; 5 DRAWS VS 4-7; 6 DRAWS VS 6-7; 7 STANDS.", + "ONE WAGER PER PLAYER PER ROUND; SIDE BETS SETTLE INDEPENDENTLY.", + } + for i, line := range draw { + c.text(3, 17+i, line, crapsInk) + } + return c.render(mode, unicode) +} + +func baccaratVariantTitle(b casino.BaccaratConfig) string { + switch b.Variant { + case casino.BaccaratSuper6: + return "SUPER 6 BACCARAT — NO COMMISSION" + case casino.BaccaratEZ: + return "EZ BACCARAT — NO COMMISSION" + default: + return "PUNTO BANCO — COMMISSION" + } +} +func bankerPayoutText(b casino.BaccaratConfig) string { + switch b.Variant { + case casino.BaccaratSuper6, casino.BaccaratEZ, casino.BaccaratCommission: + return "PAYS 1:1" + default: + return "PAYS " + ratioText(b.BankerPayout) + } +} +func bankerNoteText(b casino.BaccaratConfig) string { + switch b.Variant { + case casino.BaccaratSuper6: + return "WINNING 6 PAYS 1:2" + case casino.BaccaratEZ: + return "3-CARD 7 PUSHES" + default: + return fmt.Sprintf("%s%% COMMISSION", strings.TrimRight(strings.TrimRight(fmt.Sprintf("%.6g", (1-b.BankerPayout)*100), "0"), ".")) + } +} +func optionalText(enabled bool, payout string) string { + if enabled { + return payout + } + return "NOT OFFERED" +} diff --git a/internal/game/render_baccarat_felt_test.go b/internal/game/render_baccarat_felt_test.go new file mode 100644 index 0000000..dabaa36 --- /dev/null +++ b/internal/game/render_baccarat_felt_test.go @@ -0,0 +1,92 @@ +package game + +import ( + "strings" + "testing" + + "thehouseoficarus/internal/casino" + "thehouseoficarus/internal/color" +) + +func TestBaccaratRulesFeltGeometryAndPhrases(t *testing.T) { + cfg := casino.TableConfig{ID: "harbor", Game: casino.GameBaccarat, MinBet: 1, MaxBet: 100, MaxPlayers: 8, BettingTicks: 35, + Baccarat: casino.BaccaratConfig{Variant: casino.BaccaratCommission, PairBets: true, Decks: 8, ShuffleAt: 0.25, TiePayout: 8, BankerPayout: 0.95}} + for _, unicode := range []bool{false, true} { + art := renderBaccaratRulesFelt(cfg, "none", unicode) + rows := strings.Split(strings.TrimSuffix(art, "\n"), "\n") + if len(rows) != 22 { + t.Fatalf("felt height %d", len(rows)) + } + for _, row := range rows { + if color.VisibleLen(row) != 77 { + t.Fatalf("misaligned (%d): %s", color.VisibleLen(row), row) + } + } + for _, want := range []string{ + "PUNTO BANCO — COMMISSION", "HIGHEST LAST DIGIT WINS", "STOPS ALL DRAWING", + "PLAYER", "TIE", "BANKER", "PAYS 1:1", "PAYS 8 TO 1", "5% COMMISSION", + "PLAYER & BANKER PUSH", + "SIDE BETS", "HOUSE", "PLAYER PAIR", "BANKER PAIR", "11:1", + "DRAGON 7", "PANDA 8", "SUPER 6", "NOT OFFERED", + "DECKS", "SHUFFLE AT", "BET LIMITS", "1-100 CREDITS", "35 TICKS", + "DRAWING — AUTOMATIC PUNTO BANCO", "DRAWS 0-5", "6 DRAWS VS 6-7", + "ONE WAGER PER PLAYER PER ROUND", + } { + if !strings.Contains(art, want) { + t.Fatalf("missing %q in unicode=%v felt", want, unicode) + } + } + // The raw dump's phrases must not leak onto the felt. + for _, stale := range []string{"Number of decks", "Drawing: Automatic", "Fractional credits:"} { + if strings.Contains(art, stale) { + t.Fatalf("stale prose %q on felt", stale) + } + } + } +} + +func TestBaccaratRulesFeltFollowsConfig(t *testing.T) { + cfg := casino.TableConfig{ID: "crown", Game: casino.GameBaccarat, MinBet: 100, MaxBet: 10000, BettingTicks: 35, + Baccarat: casino.BaccaratConfig{Variant: casino.BaccaratEZ, Dragon7: true, Panda8: true, Decks: 6, TiePayout: 9, BankerPayout: 1, ShuffleAt: 0.5}} + art := renderBaccaratRulesFelt(cfg, "none", true) + for _, want := range []string{"EZ BACCARAT — NO COMMISSION", "PAYS 9 TO 1", "3-CARD 7 PUSHES", + "DRAGON 7" + strings.Repeat(" ", 23) + "40:1", "PANDA 8" + strings.Repeat(" ", 24) + "25:1", + "100-10000 CREDITS", "50% REMAINING"} { + if !strings.Contains(art, want) { + t.Fatalf("missing %q: %s", want, art) + } + } + cfg2 := casino.TableConfig{ID: "charter", Game: casino.GameBaccarat, + Baccarat: casino.BaccaratConfig{Variant: casino.BaccaratSuper6, Super6Bet: true, TiePayout: 9}} + art2 := renderBaccaratRulesFelt(cfg2, "none", true) + for _, want := range []string{"SUPER 6 BACCARAT — NO COMMISSION", "WINNING 6 PAYS 1:2", "SUPER 6" + strings.Repeat(" ", 24) + "12:1", "PAYS 9 TO 1"} { + if !strings.Contains(art2, want) { + t.Fatalf("missing %q: %s", want, art2) + } + } +} + +func TestBaccaratJoinPrintsFeltNotProse(t *testing.T) { + g := &Game{Casino: casino.NewManager(1)} + g.Casino.Join(1, casino.TableConfig{ID: "bac", Game: casino.GameBaccarat}, "alice") + events := g.Casino.Join(1, casino.TableConfig{ID: "bac", Game: casino.GameBaccarat}, "bob") + found := false + for _, e := range events { + if view, ok := e.Snapshot.(*casino.BaccaratRulesView); ok { + found = true + art := renderBaccaratRulesFelt(view.Config, "none", true) + if !strings.Contains(art, "PUNTO BANCO — COMMISSION") || !strings.Contains(art, "DECKS") { + t.Fatal("rules felt missing phrases", art) + } + if e.Message != "" { + t.Fatal("rules event carries prose", e.Message) + } + } + if strings.Contains(e.Message+e.PrivateMessage, "Number of decks") { + t.Fatal("raw rules prose leaked onto join", e) + } + } + if !found { + t.Fatal("join did not attach the rules felt") + } +} diff --git a/internal/game/render_blackjack_felt.go b/internal/game/render_blackjack_felt.go new file mode 100644 index 0000000..41a5382 --- /dev/null +++ b/internal/game/render_blackjack_felt.go @@ -0,0 +1,137 @@ +package game + +import ( + "fmt" + "strconv" + + "thehouseoficarus/internal/casino" +) + +// A blackjack felt: the classic centre-display phrases a real table prints +// (blackjack payout, dealer draw rule, insurance), then the remaining +// configurable rules arranged in labelled boxes. It reuses the craps felt +// canvas and palette: fixed 77-column art, dark green baize, gold headings. +// Fixed engine behaviour (peek timing, rounding) is left off the felt. +func renderBlackjackRulesFelt(cfg casino.TableConfig, mode string, unicode bool) string { + b := cfg.Blackjack.Normalize() + c := newCrapsCanvas(21) + // Centre display: the phrases printed on every real blackjack table. + c.box(0, 0, 76, 5) + c.center(1, 75, 2, "BLACKJACK PAYS "+ratioText(b.BlackjackPayout), crapsGold) + dealer := "DEALER MUST STAND ON 17 AND DRAW TO 16" + if b.DealerHitsSoft17() { + dealer = "DEALER HITS SOFT 17" + } + c.center(1, 75, 3, dealer, crapsInk) + c.center(1, 75, 4, "INSURANCE PAYS "+ratioText(b.InsurancePayout), crapsGold) + // Four labelled rule boxes share edges with the centre display above. + boxY := [4][2]int{{5, 12}, {5, 12}, {12, 20}, {12, 20}} + xs := [4][2]int{{0, 38}, {38, 76}, {0, 38}, {38, 76}} + for i := range boxY { + c.box(xs[i][0], boxY[i][0], xs[i][1], boxY[i][1]) + } + titles := [4]string{"THE SHOE", "PAYS", "DOUBLE & SPLIT", "HOUSE"} + for i, title := range titles { + c.center(xs[i][0]+1, xs[i][1]-1, boxY[i][0]+1, title, crapsGold) + } + rows := [4][][2]string{ + { + {"DECKS", fmt.Sprintf("%d", b.Decks)}, + {"SHUFFLE AT", fmt.Sprintf("%g%% REMAINING", b.ShuffleAt*100)}, + {"SHOE LOW", "RESHUFFLE MID-ROUND"}, + {"HOLE CARD", "YES (PEEK)"}, + {"", ""}, + }, + { + {"ORDINARY WIN", "1:1"}, + {"TIE", "PUSH"}, + {"BJ VS BJ", "PUSH"}, + {"SPLIT-HAND 21", "1:1"}, + {"SPLIT+DOUBLE 21", splitDouble21Text(b)}, + {"", ""}, + }, + { + {"DOUBLE", "ANY TWO, ONE CARD"}, + {"AFTER SPLIT", yesNoText(b.AllowsDoubleAfterSplit())}, + {"MAX HANDS", fmt.Sprintf("%d (RESPLIT %s)", b.MaxSplitHands, yesNoText(b.MaxSplitHands > 2))}, + {"RESPLIT ACES", yesNoText(b.AllowsResplitAces())}, + {"PAIRS", pairsText(b)}, + {"SPLIT ACES", "ONE CARD, NO HITS"}, + }, + { + {"SURRENDER", surrenderText(b)}, + {"INSURANCE COST", "HALF THE BET"}, + {"BET LIMITS", betLimitsText(cfg.MinBet, cfg.MaxBet)}, + {"SEATS", fmt.Sprintf("%d", cfg.MaxPlayers)}, + {"BETTING WINDOW", fmt.Sprintf("%d TICKS", cfg.BettingTicks)}, + {"ACTION WINDOW", fmt.Sprintf("%d TICKS", b.ActionTicks)}, + }, + } + for i, box := range rows { + for j, row := range box { + if row[0] == "" && row[1] == "" { + continue + } + c.bjRule(xs[i][0], xs[i][1], boxY[i][0]+2+j, row[0], row[1]) + } + } + return c.render(mode, unicode) +} + +// bjRule paints one "LABEL ..... VALUE" row inside a box: the label muted at +// the left margin, the value right-aligned to the box's inner right edge. +func (c *crapsCanvas) bjRule(x1, x2, y int, label, value string) { + c.text(x1+2, y, label, crapsMuted) + vx := x2 - 1 - len([]rune(value)) + if vx < x1+2+len([]rune(label))+1 { + vx = x1 + 2 + len([]rune(label)) + 1 + } + c.text(vx, y, value, crapsInk) +} + +// betLimitsText renders the wager range compactly so it fits inside a box. +func betLimitsText(minBet, maxBet int) string { + if maxBet == int(^uint(0)>>1) { + return fmt.Sprintf("%d+ CREDITS", minBet) + } + return fmt.Sprintf("%d-%d CREDITS", minBet, maxBet) +} + +func ratioText(p float64) string { + switch p { + case 1.5: + return "3 TO 2" + case 1.2: + return "6 TO 5" + case 2: + return "2 TO 1" + case 1: + return "1 TO 1" + default: + return strconv.FormatFloat(p, 'g', -1, 64) + " TO 1" + } +} +func splitDouble21Text(b casino.BlackjackConfig) string { + if b.CountsDoubleSplitBlackjack() { + return "BLACKJACK " + ratioText(b.BlackjackPayout) + } + return "1:1" +} +func yesNoText(v bool) string { + if v { + return "YES" + } + return "NO" +} +func pairsText(b casino.BlackjackConfig) string { + if b.AllowsUnlikeTenSplit() { + return "RANKS OR TENS" + } + return "IDENTICAL RANKS" +} +func surrenderText(b casino.BlackjackConfig) string { + if b.AllowsSurrender() { + return "LATE, TWO CARDS" + } + return "NOT OFFERED" +} diff --git a/internal/game/render_blackjack_felt_test.go b/internal/game/render_blackjack_felt_test.go new file mode 100644 index 0000000..a67251a --- /dev/null +++ b/internal/game/render_blackjack_felt_test.go @@ -0,0 +1,84 @@ +package game + +import ( + "strings" + "testing" + + "thehouseoficarus/internal/casino" + "thehouseoficarus/internal/color" +) + +func TestBlackjackRulesFeltGeometryAndPhrases(t *testing.T) { + cfg := casino.TableConfig{ID: "midnight", Game: casino.GameBlackjack, MinBet: 100, MaxBet: 10000, MaxPlayers: 6, BettingTicks: 18, + Blackjack: casino.BlackjackConfig{ActionTicks: 15, DoubleSplitBlackjack: &[]bool{false}[0]}} + for _, unicode := range []bool{false, true} { + art := renderBlackjackRulesFelt(cfg, "none", unicode) + rows := strings.Split(strings.TrimSuffix(art, "\n"), "\n") + if len(rows) != 21 { + t.Fatalf("felt height %d", len(rows)) + } + for _, row := range rows { + if color.VisibleLen(row) != 77 { + t.Fatalf("misaligned (%d): %s", color.VisibleLen(row), row) + } + } + for _, want := range []string{ + "BLACKJACK PAYS 3 TO 2", "DEALER MUST STAND ON 17 AND DRAW TO 16", "INSURANCE PAYS 2 TO 1", + "THE SHOE", "PAYS", "DOUBLE & SPLIT", "HOUSE", + "DECKS", "SHUFFLE AT", "25% REMAINING", "RESHUFFLE MID-ROUND", "HOLE CARD", + "ORDINARY WIN", "SPLIT+DOUBLE 21", "DOUBLE", "ANY TWO, ONE CARD", "MAX HANDS", "ONE CARD, NO HITS", + "SURRENDER", "NOT OFFERED", "100-10000 CREDITS", "18 TICKS", "15 TICKS", + } { + if !strings.Contains(art, want) { + t.Fatalf("missing %q in unicode=%v felt", want, unicode) + } + } + // The raw dump's phrases and fixed engine rules must not leak onto the felt. + for _, stale := range []string{"Number of decks", "Dealer hole card / peek:", "FRACTIONS", "BJ CHECK", "HOUSE BLACKJACK"} { + if strings.Contains(art, stale) { + t.Fatalf("stale prose %q on felt", stale) + } + } + } +} + +func TestBlackjackRulesFeltFollowsConfig(t *testing.T) { + yes, no := true, false + cfg := casino.TableConfig{ID: "high", Game: casino.GameBlackjack, MinBet: 5, MaxBet: 500, + Blackjack: casino.BlackjackConfig{Decks: 1, BlackjackPayout: 1.2, DealerHitSoft17: &yes, Surrender: &yes, + ShuffleAt: 0.5, MaxSplitHands: 2, DoubleAfterSplit: &no, ResplitAces: &yes, SplitUnlikeTenValues: &no, + DoubleSplitBlackjack: &no, InsurancePayout: 2}} + art := renderBlackjackRulesFelt(cfg, "none", true) + for _, want := range []string{"BLACKJACK PAYS 6 TO 5", "DEALER HITS SOFT 17", "LATE, TWO CARDS", "50% REMAINING", + "AFTER SPLIT NO", "RESPLIT ACES YES", "PAIRS IDENTICAL RANKS", + "SPLIT+DOUBLE 21 1:1", "5-500 CREDITS"} { + if !strings.Contains(art, want) { + t.Fatalf("missing %q: %s", want, art) + } + } +} + +func TestBlackjackJoinPrintsFeltNotProse(t *testing.T) { + g := &Game{Casino: casino.NewManager(1)} + g.Casino.Join(1, casino.TableConfig{ID: "bj", Game: casino.GameBlackjack, BettingTicks: 2}, "alice") + events := g.Casino.Join(1, casino.TableConfig{ID: "bj", Game: casino.GameBlackjack, BettingTicks: 2}, "bob") + found := false + for _, e := range events { + if view, ok := e.Snapshot.(*casino.BlackjackRulesView); ok { + found = true + art := renderBlackjackRulesFelt(view.Config, "none", true) + if !strings.Contains(art, "BLACKJACK PAYS 3 TO 2") || !strings.Contains(art, "DECKS") { + t.Fatal("rules felt missing phrases", art) + } + if e.Message != "" { + t.Fatal("rules event carries prose", e.Message) + } + } + if strings.Contains(e.Message+e.PrivateMessage, "Number of decks") { + t.Fatal("raw rules prose leaked onto join", e) + } + } + if !found { + t.Fatal("join did not attach the rules felt") + } +} diff --git a/internal/game/render_roulette.go b/internal/game/render_roulette.go index 1e7f971..0e4b1a3 100644 --- a/internal/game/render_roulette.go +++ b/internal/game/render_roulette.go @@ -597,6 +597,13 @@ func renderRouletteResult(pockets [5]string, mode string, unicode bool, size int } func (g *Game) renderCasinoRules(sess *net.Session, cfg casino.TableConfig) string { + if cfg.Game == casino.GameBlackjack { + // The whole rule card is a rendered felt. + return g.renderCasinoSnapshot(sess, &casino.BlackjackRulesView{Config: cfg}) + } + if cfg.Game == casino.GameBaccarat { + return g.renderCasinoSnapshot(sess, &casino.BaccaratRulesView{Config: cfg}) + } rules := g.colorize(sess, "casino_action", cfg.RulesText()) if cfg.Game == casino.GameCraps { snap := &casino.CrapsSnapshot{Phase: "waiting"} diff --git a/internal/game/vesta_world_test.go b/internal/game/vesta_world_test.go index 50e799c..1a26bf6 100644 --- a/internal/game/vesta_world_test.go +++ b/internal/game/vesta_world_test.go @@ -269,12 +269,11 @@ func TestVestaEarlySkillsAndSeparateServices(t *testing.T) { func TestVestaCasinoFloorsAndVariants(t *testing.T) { _, rooms, zones := loadVesta(t) - grid := world.BuildGrid(6102, func(id int) (*world.Room, bool) { + grid := world.BuildGrid(6101, func(id int) (*world.Room, bool) { r, ok := rooms[id] return r, ok }, nil, nil, nil) games := map[string]int{} - floors := map[int]int{} future := 0 soft17, surrender, singleDeck, huff, classic := false, false, false, false, false for id, r := range rooms { @@ -284,14 +283,17 @@ func TestVestaCasinoFloorsAndVariants(t *testing.T) { } continue } - floor := grid.Coord[id][2] - floors[floor]++ + // The vestibule stays at street level (below the gaming floor); + // every gaming room shares 6101's floor. + if id != 6100 && grid.Coord[id][2] != grid.Coord[6101][2] { + t.Errorf("casino room %d drifted off the gaming floor", id) + } if strings.Contains(r.Name, "Future ") { future++ } count := len(r.CasinoTables) + len(r.CasinoMachines) - if count > 1 || count > 0 && floor != 0 { - t.Errorf("room %d: games must have individual ground-floor salons", id) + if count > 1 { + t.Errorf("room %d: games must have individual salons", id) } for _, table := range r.CasinoTables { games[string(table.Game)]++ @@ -307,11 +309,57 @@ func TestVestaCasinoFloorsAndVariants(t *testing.T) { classic = classic || machine.Variant == "" } } - if games["blackjack"] < 5 || games["baccarat"] < 3 || games["slots"] < 5 || !soft17 || !surrender || !singleDeck || !huff || !classic { + if games["blackjack"] != 5 || games["baccarat"] != 3 || games["roulette"] != 3 || games["craps"] != 7 || games["slots"] != 5 || !soft17 || !surrender || !singleDeck || !huff || !classic { t.Errorf("casino variant coverage lost: %v", games) } - if future < 15 || floors[0] < 30 || floors[1] < 15 || floors[2] < 15 || floors[3] < 15 { - t.Errorf("casino needs a large ground floor and substantial expansion floors: floors=%v future=%d", floors, future) + if future != 0 { + t.Errorf("placeholder galleries remain: %d", future) + } + // One salon per game sits on the gaming street; each keeps its editions + // within a couple of steps north or south, so no variant is ever far away. + street := map[int]string{6101: "blackjack", 6127: "baccarat", 6182: "roulette", 6185: "craps", 6118: "slots"} + for id, game := range street { + r := rooms[id] + found := false + for _, table := range r.CasinoTables { + found = found || string(table.Game) == game + } + for _, machine := range r.CasinoMachines { + found = found || string(machine.Game) == game + } + if !found { + t.Errorf("street room %d lost its %s salon", id, game) + } + } + // Street links: the blackjack salon joins the vestibule by stairs and + // the street eastward; the middle salons connect west and east; the + // slots salon ends the street. + for id, want := range map[int][]world.ExitDir{ + 6101: {world.Down, world.East}, + 6127: {world.West, world.East}, + 6182: {world.West, world.East}, + 6185: {world.West, world.East}, + 6118: {world.West}, + } { + r := rooms[id] + for _, dir := range want { + exit, ok := r.Exits[dir] + if !ok || rooms[exit.Room] == nil { + t.Errorf("street room %d lost its %s link", id, dir) + } + } + } + if rooms[6100].Exits[world.Up].Room != 6101 || rooms[5111].Exits[world.North].Room != 6100 { + t.Fatal("vestibule disconnected") + } + foundBank := false + for _, ref := range rooms[6100].Objects { + if ref.ID == "bank_booth" { + foundBank = true + } + } + if !foundBank { + t.Fatal("casino lost its bank booth") } } |
