diff options
-rw-r--r-- | rules.js | 384 |
1 files changed, 206 insertions, 178 deletions
@@ -4,6 +4,9 @@ // TODO: campaign messed up who is who after battle // TODO: retreat with 0 CU after battle +// campaign +// event + /* DATA */ const data = require("./data.js") @@ -1055,14 +1058,16 @@ function goto_committees_of_correspondence() { } states.committees_of_correspondence = { - inactive: "Committees of Correspondence", + inactive: "to place PC markers", prompt() { - view.prompt = - "Committees of Correspondence: Place 1 PC marker in each of the 13 colonies. " + game.colonies.length + " left." - if (game.colonies.length > 0) + view.prompt = "Committees of Correspondence: Place 1 PC marker in each of the 13 colonies." + if (game.colonies.length > 0) { + view.prompt += " " + game.colonies.length + " left." gen_place_american_pc_in(game.colonies) - else + } else { + view.prompt += " Done." view.actions.next = 1 + } }, space(s) { push_undo() @@ -1088,9 +1093,9 @@ function goto_for_the_king() { } states.for_the_king = { - inactive: "For the King", + inactive: "to place PC markers", prompt() { - view.prompt = "For the King: Place 3 PC markers. " + game.count + " left." + view.prompt = "For the King: Place 3 PC markers." if (game.count > 0) gen_british_pc_ops() else @@ -1110,39 +1115,13 @@ states.for_the_king = { /* REINFORCEMENTS AND START OF STRATEGY PHASE */ -function automatic_victory() { - let n_american = 0 - let n_british = 0 - for (let space of all_spaces) { - n_american += count_french_cu(space) + count_american_cu(space) - if (SPACES[space].colony !== "CA") - n_british += count_british_cu(space) - } - if (n_american === 0) { - game.victory = "British Automatic Victory!" - game.active = "None" - game.result = P_BRITAIN - game.state = "game_over" - log(game.victory) - return true - } - if (n_british === 0) { - game.victory = "American Automatic Victory!" - game.active = "None" - game.result = P_AMERICA - game.state = "game_over" - log(game.victory) - return true - } - return false -} - function goto_start_year() { logbr() log("=t Year " + game.year) logbr() // Prisoner exchange + // TODO: manual? for (let g of BRITISH_GENERALS) if (is_general_at_location(g, CAPTURED_GENERALS)) move_general(g, BRITISH_REINFORCEMENTS) @@ -1181,13 +1160,18 @@ function goto_start_year() { } if (game.year === 1776) { + log("Added C" + DECLARATION_OF_INDEPENDENCE + ".") + log("Added C" + BARON_VON_STEUBEN + ".") + log("Shuffled deck.") game.deck.push(DECLARATION_OF_INDEPENDENCE) game.deck.push(BARON_VON_STEUBEN) shuffle(game.deck) } - if (has_flag(F_RESHUFFLE)) + if (has_flag(F_RESHUFFLE)) { + log("Re-shuffled deck.") reshuffle_deck() + } game.a_queue = 0 game.b_queue = 0 @@ -1208,7 +1192,7 @@ function goto_start_year() { states.british_declare_first = { prompt() { view.prompt = "Declare yourself as the first player by playing a campaign card?" - gen_pass() + view.actions.pass = 1 for (let c of CAMPAIGN_CARDS) { if (game.b_hand.includes(c)) { gen_action_card("card_campaign", c) @@ -1252,19 +1236,55 @@ states.choose_first_player = { function goto_strategy_phase(new_active) { game.active = new_active game.state = "strategy_phase" - logbr() if (game.active === P_AMERICA) log("=a America") else log("=b Britain") - logbr() } states.strategy_phase = { - inactive: "strategy phase", + inactive: "to play a strategy card", prompt() { view.prompt = "Play a strategy card." - gen_strategy_plays(active_hand()) + for (let c of active_hand()) { + let card = CARDS[c] + switch (card.type) { + case "mandatory-event": + gen_action_card("card_play_event", c) + break + case "campaign": + gen_action_card("card_campaign", c) + break + case "ops": + if (can_exchange_for_discard(c)) + gen_action_card("exchange_for_discard", c) + if (can_activate_general(c)) + gen_action_card("card_ops_general", c) + gen_action_card("card_ops_pc", c) + if (can_play_reinforcements()) + gen_action_card("card_ops_reinforcements", c) + if (card.count < 3) + gen_action_card("card_ops_queue", c) + break + case "british-event": + case "british-event-or-battle": + if (game.active === P_BRITAIN) + if (can_play_event(c)) + gen_action_card("card_play_event", c) + gen_action_card("card_discard_event", c) + break + case "american-event": + if (game.active === P_AMERICA) + if (can_play_event(c)) + gen_action_card("card_play_event", c) + gen_action_card("card_discard_event", c) + break + case "british-battle": + case "american-battle": + gen_action_card("card_discard_event", c) + break + } + } }, card_campaign(c) { game.did_discard_event = 0 @@ -1321,10 +1341,10 @@ states.strategy_phase = { } function end_strategy_card() { - clear_undo() - - if (automatic_victory()) + if (automatic_victory()) { + clear_undo() return + } if (game.campaign) { if (--game.campaign > 0) { @@ -1337,10 +1357,25 @@ function end_strategy_card() { } } + game.state = "end_strategy_card" +} + +states.end_strategy_card = { + prompt() { + view.prompt = "Done." + }, + next() { + clear_undo() + next_strategy_card() + }, +} + +function next_strategy_card() { if (!has_flag(F_FRENCH_ALLIANCE_TRIGGERED) && game.french_alliance === 9) { log("The French signed an alliance with the Americans!") set_flag(F_FRENCH_ALLIANCE_TRIGGERED) if (game.french_navy === -1) { + game.save = game.active game.active = P_AMERICA game.state = "place_french_navy_trigger" return @@ -1359,7 +1394,6 @@ function end_strategy_card() { if (hand.length === 0) return goto_winter_attrition_phase() } - } function clear_queue() { @@ -1369,54 +1403,12 @@ function clear_queue() { game.a_queue = 0 } -function gen_strategy_plays(hand) { - for (let c of hand) { - let card = CARDS[c] - switch (card.type) { - case "mandatory-event": - gen_action_card("card_play_event", c) - break - case "campaign": - gen_action_card("card_campaign", c) - break - case "ops": - if (can_exchange_for_discard(c)) - gen_action_card("exchange_for_discard", c) - if (can_activate_general(c)) - gen_action_card("card_ops_general", c) - gen_action_card("card_ops_pc", c) - if (can_play_reinforcements()) - gen_action_card("card_ops_reinforcements", c) - if (card.count < 3) - gen_action_card("card_ops_queue", c) - break - case "british-event": - case "british-event-or-battle": - if (game.active === P_BRITAIN) - if (can_play_event(c)) - gen_action_card("card_play_event", c) - gen_action_card("card_discard_event", c) - break - case "american-event": - if (game.active === P_AMERICA) - if (can_play_event(c)) - gen_action_card("card_play_event", c) - gen_action_card("card_discard_event", c) - break - case "british-battle": - case "american-battle": - gen_action_card("card_discard_event", c) - break - } - } -} - /* DISCARD EVENT CARD FOR PC ACTION */ states.discard_event_pc_action = { prompt() { view.prompt = "Place, flip, or remove PC marker." - gen_pass() + view.actions.pass = 1 if (game.active === P_BRITAIN) gen_british_discard_event_pc_action() else @@ -1485,7 +1477,7 @@ function goto_ops_pc(count) { states.ops_pc = { prompt() { view.prompt = "Place or flip PC markers. " + game.count + " left." - gen_pass() + view.actions.pass = 1 if (game.count > 0) { if (game.active === P_BRITAIN) gen_british_pc_ops() @@ -1577,7 +1569,7 @@ states.ops_british_reinforcements_who = { view.prompt = "Reinforcements: choose an available general or pass to bring only CU." view.prompt += " Carrying " + game.count + " British CU." view.move = { to: BRITISH_REINFORCEMENTS, who: NOBODY, carry_british: game.count } - gen_pass() + view.actions.pass = 1 gen_british_reinforcements_who() }, drop_british_cu() { @@ -1622,7 +1614,7 @@ states.ops_american_reinforcements_who = { prompt() { view.prompt = "Reinforcements: choose an available general or pass to bring only CU." view.move = { to: AMERICAN_REINFORCEMENTS, who: NOBODY, carry_american: game.count } - gen_pass() + view.actions.pass = 1 gen_american_reinforcements_who() }, general(g) { @@ -1723,7 +1715,7 @@ states.ops_general_who = { if (has_flag(F_LANDING_PARTY)) gen_landing_party() gen_activate_general() - gen_pass() + view.actions.pass = 1 }, place_british_pc(where) { clear_flag(F_LANDING_PARTY) @@ -1913,7 +1905,7 @@ states.ops_general_move = { // Cannot stop on enemy general if (!has_enemy_general(location_of_general(game.move.who))) - gen_pass() + view.actions.pass = 1 gen_carry_cu() gen_move_general() @@ -2031,7 +2023,7 @@ function goto_intercept() { states.intercept = { prompt() { view.prompt = "Intercept " + game.move.who + " in " + game.move.to + "?" - gen_pass() + view.actions.pass = 1 gen_intercept() }, general(g) { @@ -2274,7 +2266,7 @@ events.remove_british_pc_from = function (c, card) { states.remove_british_pc_from = { prompt() { view.prompt = "Remove British PC markers from " + game.where.join(", ") + ". " + game.count + " left." - gen_pass() + view.actions.pass = 1 gen_remove_british_pc_from(game.where) }, space(where) { @@ -2299,7 +2291,7 @@ events.remove_american_pc = function (c, card) { states.remove_american_pc = { prompt() { view.prompt = "Remove American PC markers. " + game.count + " left." - gen_pass() + view.actions.pass = 1 gen_remove_american_pc() }, space(where) { @@ -2323,7 +2315,7 @@ events.remove_american_pc_from = function (c, card) { states.remove_american_pc_from = { prompt() { view.prompt = "Remove American PC markers from " + game.where.join(", ") + ". " + game.count + " left." - gen_pass() + view.actions.pass = 1 gen_remove_american_pc_from(game.where) }, space(where) { @@ -2350,7 +2342,7 @@ states.remove_american_pc_from_non_port = { prompt() { view.prompt = "Remove American PC markers from non-Port space in " + game.where.join(", ") + ". " + game.count + " left." - gen_pass() + view.actions.pass = 1 gen_remove_american_pc_from_non_port(game.where) }, space(where) { @@ -2375,7 +2367,7 @@ events.remove_american_pc_within_two_spaces_of_a_british_general = function (c, states.remove_american_pc_within_two_spaces_of_a_british_general = { prompt() { view.prompt = "Remove American PC markers within two spaces of a British general. " + game.count + " left." - gen_pass() + view.actions.pass = 1 gen_remove_american_pc_within_two_spaces_of_a_british_general() }, space(where) { @@ -2400,7 +2392,7 @@ events.place_american_pc = function (c, card) { states.place_american_pc = { prompt() { view.prompt = "Place American PC markers. " + game.count + " left." - gen_pass() + view.actions.pass = 1 gen_place_american_pc() }, place_american_pc(where) { @@ -2424,7 +2416,7 @@ events.place_american_pc_in = function (c, card) { states.place_american_pc_in = { prompt() { view.prompt = "Place American PC markers in " + game.where.join(", ") + ". " + game.count + " left." - gen_pass() + view.actions.pass = 1 gen_place_american_pc_in(game.where) }, place_american_pc(where) { @@ -2450,7 +2442,7 @@ events.lord_sandwich_coastal_raids = function (c, card) { states.lord_sandwich_coastal_raids = { prompt() { view.prompt = "Remove two or flip one American PC in a port space." - gen_pass() + view.actions.pass = 1 gen_lord_sandwich_coastal_raids(game.where) }, space(where) { @@ -2487,7 +2479,7 @@ events.remove_american_cu = function (c, card) { states.remove_american_cu = { prompt() { view.prompt = "Remove one American CU from any space." - gen_pass() + view.actions.pass = 1 gen_remove_american_cu() }, remove_cu(where) { @@ -2518,7 +2510,7 @@ events.remove_british_cu = function (c, card) { states.remove_british_cu = { prompt() { view.prompt = "Remove " + game.count + " British CU from any space." - gen_pass() + view.actions.pass = 1 gen_remove_british_cu() }, remove_cu(where) { @@ -2549,7 +2541,7 @@ events.pennsylvania_and_new_jersey_line_mutinies = function (c, card) { states.pennsylvania_and_new_jersey_line_mutinies = { prompt() { view.prompt = "Remove two American CUs from the map, one each from two different spaces." - gen_pass() + view.actions.pass = 1 gen_pennsylvania_and_new_jersey_line_mutinies(game.where) }, remove_cu(where) { @@ -2602,7 +2594,7 @@ states.declaration_of_independence = { prompt() { view.prompt = "Declaration of Independence: Place 1 PC marker in each of the 13 colonies. " view.prompt += game.colonies.length + " left." - gen_pass() + view.actions.pass = 1 gen_place_american_pc_in(game.colonies) }, place_american_pc(space) { @@ -2642,7 +2634,7 @@ function goto_george_washington_captured() { states.george_washington_captured = { prompt() { view.prompt = "George Washington is captured! Remove American PC markers. " + game.count + " left." - gen_pass() + view.actions.pass = 1 gen_remove_american_pc() }, space(where) { @@ -2710,7 +2702,7 @@ function goto_retreat_before_battle() { states.retreat_before_battle = { prompt() { view.prompt = "Attempt retreat before battle?" - gen_pass() + view.actions.pass = 1 gen_defender_retreat() }, space(to) { @@ -2834,7 +2826,7 @@ function goto_play_attacker_battle_card() { states.play_attacker_battle_card = { prompt() { view.prompt = "Attack: Play or discard event for DRM." - gen_pass() + view.actions.pass = 1 gen_battle_card() }, card_battle_play(c) { @@ -2874,7 +2866,7 @@ function goto_play_defender_battle_card() { states.play_defender_battle_card = { prompt() { view.prompt = "Defend: Play or discard event for DRM." - gen_pass() + view.actions.pass = 1 gen_battle_card() }, card_battle_play(c) { @@ -3023,8 +3015,6 @@ function resolve_battle() { if (a_g !== NOBODY) a_log.push("General: " + a_g) -console.log("GENS", a_g, b_g) - if (b_g !== NOBODY) { let roll = roll_d6() if (roll <= 3) @@ -3208,7 +3198,7 @@ function end_battle() { end_strategy_card() } -/* END TURN PHASES */ +/* WINTER ATTRITION PHASE */ function apply_single_winter_attrition(owner, space) { let die = roll_d6() @@ -3281,6 +3271,8 @@ function goto_winter_attrition_phase() { goto_french_naval_phase() } +/* FRENCH NAVAL PHASE */ + function goto_french_naval_phase() { if (game.french_navy !== -1) { game.save = game.active @@ -3349,7 +3341,7 @@ states.place_rochambeau = { function end_place_rochambeau() { game.active = game.save delete game.save - end_strategy_card() + next_strategy_card() } states.place_french_navy = { @@ -3364,6 +3356,55 @@ states.place_french_navy = { }, } +/* POLITICAL CONTROL PHASE: RETURN CONGRESS */ + +function goto_political_control_phase() { + if (game.congress === CONTINENTAL_CONGRESS_DISPERSED) { + game.active = P_AMERICA + game.state = "return_continental_congress" + } else { + goto_political_control_phase_2() + } +} + +function gen_place_continental_congress() { + let n = 0 + for (let space of all_spaces) { + if (SPACES[space].colony !== "CA") { + if (has_american_pc(space) && has_no_british_playing_piece(space)) { + gen_action("place_continental_congress", space) + ++n + } + } + } + return n +} + +states.return_continental_congress = { + prompt() { + view.prompt = "Return Continental Congress to a space in the 13 colonies." + if (gen_place_continental_congress() === 0) + view.actions.pass = 1 + }, + place_continental_congress(where) { + game.congress = where + goto_political_control_phase_2() + }, + pass() { + goto_political_control_phase_2() + }, +} + +/* POLITICAL CONTROL PHASE: PLACE PC MARKERS */ + +function goto_political_control_phase_2() { + // TODO: manually place and remove + place_pc_markers_segment() + remove_isolated_american_pc_segment() + remove_isolated_british_pc_segment() + goto_end_phase() +} + function place_pc_markers_segment() { for (let space of all_spaces) { if (has_american_army(space)) { @@ -3381,6 +3422,8 @@ function place_pc_markers_segment() { } } +/* POLITICAL CONTROL PHASE: REMOVE ISOLATED PC MARKERS */ + function is_american_pc_root(space) { if (has_no_pc(space) && has_no_british_cu(space)) return true @@ -3471,55 +3514,36 @@ function remove_isolated_british_pc_segment() { remove_pc(space) } -function gen_place_continental_congress() { - let n = 0 - for (let space of all_spaces) { - if (SPACES[space].colony !== "CA") { - if (has_american_pc(space) && has_no_british_playing_piece(space)) { - gen_action("place_continental_congress", space) - ++n - } - } - } - return n -} +/* END PHASE */ -function goto_political_control_phase() { - if (game.congress === CONTINENTAL_CONGRESS_DISPERSED) { +function goto_end_phase() { + if (has_flag(F_FRENCH_ALLIANCE_TRIGGERED) && !has_flag(F_EUROPEAN_WAR)) { + set_flag(F_EUROPEAN_WAR) + game.count = 2 game.active = P_AMERICA - game.state = "return_continental_congress" - } else { - goto_political_control_phase_2() + game.state = "european_war" + set_flag(F_RESHUFFLE) + return } -} -states.return_continental_congress = { - prompt() { - view.prompt = "Return Continental Congress to a space in the 13 colonies." - if (gen_place_continental_congress() === 0) - gen_pass() - }, - place_continental_congress(where) { - game.congress = where - goto_political_control_phase_2() - }, - pass() { - goto_political_control_phase_2() - }, -} + if ((game.war_ends && game.year >= CARDS[game.war_ends].year) || game.year === 1783) { + norths_government_falls() + return + } -function goto_political_control_phase_2() { - // TODO: manually place and remove - place_pc_markers_segment() - remove_isolated_american_pc_segment() - remove_isolated_british_pc_segment() - goto_end_phase() + clear_flag(F_MUTINIES) + + game.a_queue = game.b_queue = 0 + game.year += 1 + goto_start_year() } +/* END PHASE: EUROPEAN WAR */ + states.european_war = { prompt() { view.prompt = "European War: Remove 2 British CU from any spaces. " + game.count + " left." - gen_pass() + view.actions.pass = 1 gen_remove_british_cu() }, remove_cu(where) { @@ -3532,6 +3556,35 @@ states.european_war = { }, } +/* VICTORY */ + +function automatic_victory() { + let n_american = 0 + let n_british = 0 + for (let space of all_spaces) { + n_american += count_french_cu(space) + count_american_cu(space) + if (SPACES[space].colony !== "CA") + n_british += count_british_cu(space) + } + if (n_american === 0) { + game.victory = "British Automatic Victory!" + game.active = "None" + game.result = P_BRITAIN + game.state = "game_over" + log(game.victory) + return true + } + if (n_british === 0) { + game.victory = "American Automatic Victory!" + game.active = "None" + game.result = P_AMERICA + game.state = "game_over" + log(game.victory) + return true + } + return false +} + function norths_government_falls() { let n_american = 0 for (let c = 0; c <= 13; ++c) @@ -3550,25 +3603,6 @@ function norths_government_falls() { log(game.victory) } -function goto_end_phase() { - if (has_flag(F_FRENCH_ALLIANCE_TRIGGERED) && !has_flag(F_EUROPEAN_WAR)) { - set_flag(F_EUROPEAN_WAR) - game.count = 2 - game.active = P_AMERICA - game.state = "european_war" - set_flag(F_RESHUFFLE) - return - } - - if ((game.war_ends && game.year >= CARDS[game.war_ends].year) || game.year === 1783) - return norths_government_falls() - - clear_flag(F_MUTINIES) - - game.a_queue = game.b_queue = 0 - game.year += 1 - goto_start_year() -} states.game_over = { prompt() { @@ -3600,10 +3634,6 @@ function gen_action_card(action, c) { gen_action(action, c) } -function gen_pass() { - view.actions.pass = 1 -} - exports.scenarios = [ "Standard" ] exports.roles = [ P_BRITAIN, P_AMERICA ] @@ -3678,7 +3708,7 @@ exports.view = function (state, current) { let inactive = states[game.state].inactive if (typeof inactive !== "string") inactive = game.state - view.prompt = "Waiting for " + game.active + " to " + inactive + "." + view.prompt = "Waiting for " + game.active + " " + inactive + "." } return view @@ -3977,5 +4007,3 @@ function map_delete(map, key) { } } } - -console.log(events) |