summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor@ccxvii.net>2024-06-21 17:51:05 +0200
committerTor Andersson <tor@ccxvii.net>2024-08-21 00:28:20 +0200
commit7d7bf01a9f9919dd094b7e22ee747ec54a3858a2 (patch)
tree809f14ab78bede500e7e0d7f3adf6858fbd8793b
parent2f454e5f5554ce2350f4ccf2edca04819c8e1e83 (diff)
downloadwashingtons-war-7d7bf01a9f9919dd094b7e22ee747ec54a3858a2.tar.gz
cleanups and reorg
-rw-r--r--rules.js384
1 files changed, 206 insertions, 178 deletions
diff --git a/rules.js b/rules.js
index 2fd69a5..416790f 100644
--- a/rules.js
+++ b/rules.js
@@ -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)