diff options
author | Tor Andersson <tor@ccxvii.net> | 2024-10-23 12:08:47 +0200 |
---|---|---|
committer | Tor Andersson <tor@ccxvii.net> | 2024-10-23 12:13:09 +0200 |
commit | 456d08d10840405e34f20af321e1802bcf156c53 (patch) | |
tree | efbd31c898626597b246f11c665a6b068a98a350 /rules.js | |
parent | 7dc86dde42c3bf9cd38bc40da477dbd03f5b5ba3 (diff) | |
download | maria-456d08d10840405e34f20af321e1802bcf156c53.tar.gz |
25 optional political rule
Diffstat (limited to 'rules.js')
-rw-r--r-- | rules.js | 139 |
1 files changed, 90 insertions, 49 deletions
@@ -4,8 +4,6 @@ /* TODO -TODO: face-up / face-down TCs in display - use "placed" and "saved" arrays or implicit with "game.trump"? - show who controls which power in player list set-aside victory marker areas @@ -301,6 +299,9 @@ const MUNCHEN = find_city("München") const DRESDEN = find_city("Dresden") const ENGLAND = find_city("England") +const EAST_PRUSSIA = find_city("East Prussia") +const AUSTRIAN_ITALY_BOX = data.sectors.ItalyA[0] +const FRENCH_ITALY_BOX = data.sectors.ItalyF[0] const all_pieces = [ ...all_power_generals.flat(), ...all_power_trains.flat() ] const all_trains = [ ...all_power_trains.flat() ] @@ -584,6 +585,10 @@ function format_card(c) { return (to_deck(c)+1) + "^" + format_card_prompt(c) } +function format_card_list(list) { + return list.map(format_card).join(", ") +} + function format_reserve(c, v) { return (to_deck(c)+1) + "^" + v + "R" } @@ -875,6 +880,13 @@ function count_used_troops() { return current } +function has_general_of_power(to, power) { + for (let p of all_power_generals[power]) + if (game.pos[p] === to) + return true + return false +} + function has_any_piece(to) { for (let p = 0; p <= last_piece; ++p) if (game.pos[p] === to) @@ -1151,9 +1163,11 @@ function count_used_cards() { held[to_deck(c)]++ } - // count cards in saved political display + // count cards in political display for (let pow of all_major_powers) { - for (let c of game.saved[pow]) + for (let c of game.face_up[pow]) + held[to_deck(c)]++ + for (let c of game.face_down[pow]) held[to_deck(c)]++ } @@ -3337,20 +3351,19 @@ const INFLUENCE_ORDER = [ function goto_politics() { game.political = [] - game.placed = [ 0, 0, 0, 0 ] game.stage = 0 game.save_saxony = game.saxony - // 25.1 Return face-down TCs to the players + // 25.1 Return face-down (previously placed) TCs to the players for (let pow of all_major_powers) { - for (let c of game.saved[pow]) + for (let c of game.face_down[pow]) set_add(game.hand[pow], c) - game.saved[pow] = [] + game.face_down[pow] = [] } // 25.2 Reveal 2 Political Cards - log("Reveal") + log("Political Cards") while (game.political.length < 2) { let pc = game.pol_deck.pop() log(">C" + pc) @@ -3412,7 +3425,7 @@ states.place_tc_on_display = { push_undo() log(power_name[game.power] + " placed a TC.") set_delete(game.hand[game.power], c) - game.placed[game.power] = c + set_add(game.face_down[game.power], c) game.state = "place_tc_on_display_done" }, pass() { @@ -3447,18 +3460,22 @@ function goto_determine_order_of_influence() { log_br() log("Influence") - // Turn cards face-up and turn bluff cards face down again + // Turn cards face-up (and turn bluff cards face down again) for (let pow of POWER_FROM_POLITICAL_STAGE) { - let c = game.placed[pow] - if (c > 0) { - if (is_trump_card(c)) - log(">" + format_card(c) + " " + power_name[pow]) - else - log(">" + format_card(c) + " " + power_name[pow] + " (bluff)") - set_add(game.saved[pow], c) + for (let i = 0; i < game.face_down[pow].length;) { + let c = game.face_down[pow][i] + if (is_trump_card(c)) { + array_remove(game.face_down[pow], i) + set_add(game.face_up[pow], c) + } else { + ++i + } } + if (game.face_down[pow].length > 0) + log(">" + power_name[pow] + " " + format_card_list(game.face_down[pow]) + " (bluff)") + if (game.face_up[pow].length > 0) + log(">" + power_name[pow] + " " + format_card_list(game.face_up[pow])) } - delete game.placed log_br() game.stage = 0 @@ -3467,10 +3484,10 @@ function goto_determine_order_of_influence() { function count_influence(pow) { let n = 0 - for (let c of game.saved[pow]) + for (let c of game.face_up[pow]) if (is_reserve(c)) n += 16 - else if (to_suit(c) === game.trump) + else n += to_value(c) return n } @@ -3521,7 +3538,7 @@ states.select_political_card = { log(power_name[game.power] + " chose C" + pc + ".") // face-up TCs to discard - game.saved[game.power] = game.saved[game.power].filter(c => !is_trump_card(c)) + game.face_up[game.power] = [] game.pc = pc game.pcx = -1 @@ -3555,9 +3572,17 @@ states.political_card_discard_or_execute = { function end_politics() { delete game.political - // flip TCs on display face down game.trump = -1 + // did not take a political turn; flip all cards face-down + for (let pow of all_major_powers) { + if (!(game.stage & (1 << pow))) { + for (let c of game.face_up[pow]) + set_add(game.face_down[pow], c) + game.face_up[pow] = [] + } + } + goto_adjust_political_tracks() } @@ -3802,7 +3827,7 @@ function is_saxony_austrian_ally() { states.saxony_shift = { inactive: "shift Saxony marker", prompt() { - prompt("Shift Saxony marker ${game.count} to the right.") + prompt(`Shift Saxony marker ${game.count} to the right.`) view.actions.shift = [ 1 ] view.actions.pass = 1 }, @@ -3840,8 +3865,34 @@ function goto_adjust_political_tracks() { if (game.italy >= 8) game.flags |= F_ITALY_AUSTRIA // Expeditionary corps - // TODO + goto_expeditionary_corps() +} + +function check_expeditionary_corps(power, space, active) { + if (active && !has_general_of_power(space, power)) { + set_active_to_power(power) + game.state = "send_expeditionary_corps_off_map" + return 1 + } + if (!active && has_general_of_power(space, power)) { + set_active_to_power(power) + game.state = "bring_expeditionary_corps_on_map" + return 1 + } + return 0 +} +function goto_expeditionary_corps() { + if (check_expeditionary_corps(P_PRUSSIA, EAST_PRUSSIA, game.russia >= 5)) + return + if (check_expeditionary_corps(P_FRANCE, FRENCH_ITALY_BOX, game.italy <= 2)) + return + if (check_expeditionary_corps(P_AUSTRIA, AUSTRIAN_ITALY_BOX, game.italy >= 8)) + return + goto_saxony_defection() +} + +function goto_saxony_defection() { // Saxony defection let save_saxony = game.save_saxony delete game.save_saxony @@ -3991,9 +4042,12 @@ function make_tactics_discard(n) { for (let pow of all_powers) if (set_has(game.hand[pow], c)) return false - for (let pow of all_major_powers) - if (set_has(game.saved[pow], c)) + for (let pow of all_major_powers) { + if (set_has(game.face_up[pow], c)) + return false + if (set_has(game.face_down[pow], c)) return false + } return true }) } @@ -4025,7 +4079,11 @@ exports.setup = function (seed, _scenario, _options) { pol_deck: null, deck: null, hand: [ [], [], [], [], [], [] ], - saved: [ [], [], [], [] ], + + // face-up (saved) TCs + face_up: [ [], [], [], [] ], + // face-down (placed) TCs + face_down: [ [], [], [], [] ], pos: setup_piece_position.slice(), oos: 0, @@ -4203,30 +4261,14 @@ function mask_hand(player) { return view_hand } -function mask_placed(player) { - let view_placed = [] - for (let pow of all_major_powers) { - if (game.placed[pow] === 0) - view_placed[pow] = -1 - else if (player_from_power(pow) === player) - view_placed[pow] = game.placed[pow] - else - view_placed[pow] = game.placed[pow] & ~127 - } - return view_placed +function mask_face_down() { + return game.face_down.map(list => list.map(c => c & ~127)) } function is_trump_card(c) { return (game.trump >= 0) && (is_reserve(c) || to_suit(c) === game.trump) } -function mask_saved(player) { - let view_saved = [] - for (let pow of all_major_powers) - view_saved[pow] = game.saved[pow].map(c => is_trump_card(c) ? c : c & ~127) - return view_saved -} - function total_troops_list() { let list = [] for (let pow of all_powers) { @@ -4263,7 +4305,8 @@ exports.view = function (state, player) { discard: total_discard_list(), pol_deck: mask_pol_deck(), - saved: mask_saved(), + face_up: game.face_up, + face_down: mask_face_down(), power: game.power, retro: game.retro, @@ -4276,8 +4319,6 @@ exports.view = function (state, player) { if (game.political) view.political = game.political - if (game.placed) - view.placed = mask_placed(player) if (game.state === "game_over") { view.prompt = game.victory |