summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--play.css9
-rw-r--r--play.js45
-rw-r--r--rules.js455
3 files changed, 319 insertions, 190 deletions
diff --git a/play.css b/play.css
index a8837a0..c23d8fd 100644
--- a/play.css
+++ b/play.css
@@ -15,13 +15,21 @@ body.America header.your_turn { background-color: hsl(211, 50%, 75%) }
#turn_info { background-color: hsl(35, 25%, 50%); }
#log .h { border-top: 1px solid black; border-bottom: 1px solid black; text-align: center; margin: 6px 0; }
+#log .h { background-color: hsl(35, 45%, 82%); }
#log .h.turn { background-color: hsl(35, 45%, 70%); }
#log .h.britain { background-color: hsl(15, 90%, 80%) }
#log .h.america { background-color: hsl(211, 50%, 80%) }
+#log .n { margin: 6px 0; }
+#log .m { margin-top: 6px; }
+
#log .tip { cursor: pointer; }
#log .tip:hover { text-decoration: underline; }
+#log div { padding-left: 20px; text-indent: -12px; }
+#log div.i { padding-left: 32px; text-indent: -12px; }
+#log div.ii { padding-left: 44px; text-indent: -12px; }
+
#tooltip {
display: none;
pointer-events: none;
@@ -132,6 +140,7 @@ body.America header.your_turn { background-color: hsl(211, 50%, 75%) }
background-image: url(bang.svg);
background-size: contain;
background-repeat: no-repeat;
+ opacity: 75%;
z-index: 2000;
}
diff --git a/play.js b/play.js
index c317507..70279fa 100644
--- a/play.js
+++ b/play.js
@@ -4,6 +4,8 @@
global view, data, roles, send_action, action_button
*/
+// TODO: show "reshuffle" flag next to card deck display
+
/* COMMON */
function set_has(set, item) {
@@ -294,8 +296,8 @@ function lerp(a, b, t) {
}
function show_combat_marker() {
- let x = Math.round(lerp(data.spaces[view.move.from].x, data.spaces[view.move.to].x, 0.75))
- let y = Math.round(lerp(data.spaces[view.move.from].y, data.spaces[view.move.to].y, 0.75))
+ let x = Math.round(lerp(data.spaces[view.move.from].x, data.spaces[view.move.to].x, 0.67))
+ let y = Math.round(lerp(data.spaces[view.move.from].y, data.spaces[view.move.to].y, 0.67))
ui.combat.style.left = x - 20 + "px"
ui.combat.style.top = y - 20 + "px"
ui.pieces_element.appendChild(ui.combat)
@@ -383,8 +385,8 @@ function get_army_xy_lerp(s1, s2) {
y = data.spaces[s1].y + (dy * 1/2) | 0
}
- if (Math.abs(dx) < 180 && Math.abs(dy) < 60)
- y -= 20
+ if (Math.abs(dx) < 180 && Math.abs(dy) < 60) y -= 20
+ if (Math.abs(dx) < 180 && Math.abs(dy) < 40) y -= 20
return [ x - 15, y ]
}
@@ -550,7 +552,9 @@ function on_update() {
continue
let [ x, y ] = (s < 66) ? ui.layout_static[s] : get_static_xy(s)
- if (s >= 66)
+ if (s === 68)
+ y -= 20
+ else if (s >= 66)
y -= 60
if (view.move && view.move.who === g)
@@ -797,11 +801,14 @@ function on_blur_card_tip() {
function on_log(text) {
let p = document.createElement("div")
- text = text.replace(/&/g, "&amp;")
- text = text.replace(/</g, "&lt;")
- text = text.replace(/>/g, "&gt;")
- if (text.startsWith("=t")) {
+ if (text.startsWith(">>")) {
+ p.className = "ii"
+ text = text.substring(2)
+ } else if (text.startsWith(">")) {
+ p.className = "i"
+ text = text.substring(1)
+ } else if (text.startsWith("=t")) {
p.className = "h turn"
text = text.substring(2)
} else if (text.startsWith("=a")) {
@@ -810,8 +817,28 @@ function on_log(text) {
} else if (text.startsWith("=b")) {
p.className = "h britain"
text = text.substring(3)
+ } else if (text.startsWith("=!")) {
+ p.className = "h"
+ text = text.substring(3)
}
+ if (
+ text.startsWith("Played ") ||
+ text.startsWith("Discarded ") ||
+ text.startsWith("Exchanged ") ||
+ text.startsWith("Retreated ") ||
+ text.startsWith("Surrendered ") ||
+ text === "Removed card."
+ )
+ p.className = "n"
+
+ if (text.startsWith("Moved G"))
+ p.className = "m"
+
+ text = text.replace(/&/g, "&amp;")
+ text = text.replace(/</g, "&lt;")
+ text = text.replace(/>/g, "&gt;")
+
text = text.replace(/C(\d+)/g, sub_card)
text = text.replace(/S(\d+)/g, sub_space)
text = text.replace(/G(\d+)/g, sub_general)
diff --git a/rules.js b/rules.js
index a1d9bbf..a33a73a 100644
--- a/rules.js
+++ b/rules.js
@@ -279,13 +279,10 @@ function active_hand() {
return game.active === P_AMERICA ? game.a_hand : game.b_hand
}
-function play_card(c, reason) {
- if (reason)
- log("Played C" + c + " " + reason + ".")
- else
- log("Played C" + c + " for Event.")
- if (CARDS[c].reshuffle === "if_played")
+function play_card(c) {
+ if (CARDS[c].reshuffle === "if_played") {
set_flag(F_RESHUFFLE)
+ }
set_delete(active_hand(), c)
if (CARDS[c].once) {
log("Removed card.")
@@ -299,11 +296,7 @@ function discard_card_from_hand(hand, c) {
set_flag(F_RESHUFFLE)
}
-function discard_card(c, reason) {
- if (reason)
- log("Discarded C" + c + " " + reason + ".")
- else
- log("Discarded C" + c + ".")
+function discard_card(c) {
discard_card_from_hand(active_hand(), c)
}
@@ -793,13 +786,13 @@ function capture_washington() {
function capture_british_general(where) {
let g = find_british_general(where)
- log(general_name(g) + " captured!")
+ log("Captured G" + g + ".")
move_general(g, CAPTURED_GENERALS)
}
function capture_american_or_french_general(where) {
let g = find_american_or_french_general(where)
- log(general_name(g) + " captured!")
+ log("Captured G" + g + ".")
if (g === WASHINGTON)
capture_washington()
else
@@ -843,65 +836,6 @@ function has_no_american_unit(where) {
return true
}
-function place_british_reinforcements(who, count, where) {
- let already_there = find_british_general(where)
- if (who !== NOBODY && already_there !== NOBODY) {
- move_general(already_there, BRITISH_REINFORCEMENTS)
- }
- if (who !== NOBODY) {
- log(`${count} CU and G${who} at S${where}.`)
- move_general(who, where)
- } else {
- log(`${count} CU at S${where}.`)
- }
- if (count > 0) {
- move_british_cu(BRITISH_REINFORCEMENTS, where, count)
- if (has_enemy_general(where))
- capture_enemy_general(where)
- if (game.congress === where)
- disperse_continental_congress()
- }
-}
-
-function place_american_reinforcements(who, count, where) {
- let already_there = find_american_or_french_general(where)
- if (who !== NOBODY && already_there !== NOBODY) {
- // Never replace Washington
- if (already_there === WASHINGTON)
- who = NOBODY
- else
- move_general(already_there, AMERICAN_REINFORCEMENTS)
- }
- if (who !== NOBODY) {
- log(`${count} CU and G${who} at S${where}.`)
- move_general(who, where)
- } else {
- log(`${count} CU at S${where}.`)
- }
- place_american_cu(where, count)
- if (has_enemy_general(where))
- capture_enemy_general(where)
-}
-
-function place_french_reinforcements(who, where) {
- let already_there = find_american_or_french_general(where)
- if (who !== NOBODY && already_there !== NOBODY) {
- // Never replace Washington
- if (already_there === WASHINGTON)
- who = NOBODY
- else
- move_general(already_there, AMERICAN_REINFORCEMENTS)
- }
- if (who !== NOBODY) {
- log(`${count} CU and G${who} at S${where}.`)
- move_general(who, where)
- } else {
- log(`${count} CU at S${where}.`)
- }
- move_french_cu(FRENCH_REINFORCEMENTS, where, count_french_cu(FRENCH_REINFORCEMENTS))
- move_french_cu(AMERICAN_REINFORCEMENTS, where, count_french_cu(AMERICAN_REINFORCEMENTS))
-}
-
function pickup_max_british_cu(move) {
move.carry_british = count_unmoved_british_cu(move.from)
if (move.carry_british > 5)
@@ -931,7 +865,7 @@ function move_army(army) {
}
function overrun(where) {
- logp("overran CU in " + where)
+ log("Overrun.")
if (game.active === P_BRITAIN) {
if (count_american_cu(where) > 0)
remove_american_cu(where, 1)
@@ -942,19 +876,35 @@ function overrun(where) {
}
}
+function log_retreat(g, cu, to) {
+ if (g !== NOBODY) {
+ if (cu > 0)
+ log("Retreated G" + g + " with " + cu + " CU to S" + to + ".")
+ else
+ log("Retreated G" + g + " to S" + to + ".")
+ } else {
+ log("Retreated " + cu + " CU to S" + to + ".")
+ }
+}
+
function retreat_american_army(from, to) {
let g = find_american_or_french_general(from)
if (g !== NOBODY)
move_general(g, to)
- move_american_cu(from, to, count_american_cu(from))
- move_french_cu(from, to, count_french_cu(from))
+ let a_cu = count_american_cu(from)
+ let f_cu = count_french_cu(from)
+ move_american_cu(from, to, a_cu)
+ move_french_cu(from, to, f_cu)
+ log_retreat(g, a_cu + f_cu, to)
}
function retreat_british_army(from, to) {
let g = find_british_general(from)
if (g !== NOBODY)
move_general(g, to)
- move_british_cu(from, to, count_british_cu(from))
+ let b_cu = count_british_cu(from)
+ move_british_cu(from, to, b_cu)
+ log_retreat(g, b_cu, to)
}
function surrender_american_army(where) {
@@ -974,7 +924,7 @@ function surrender_british_army(where) {
}
function disperse_continental_congress() {
- log("Contintental Congress dispersed!")
+ log("Dispersed Contintental Congress.")
game.congress = CONTINENTAL_CONGRESS_DISPERSED
set_flag(F_CONGRESS_WAS_DISPERSED)
}
@@ -988,13 +938,26 @@ function gen_place_american_pc_in_colony(list_of_colonies) {
gen_action_space(space)
}
+function filter_place_american_pc_in_colony(list_of_colonies) {
+ let result = []
+ for (let colony of list_of_colonies) {
+ for (let space of COLONIES[colony]) {
+ if (has_no_pc(space) && has_no_british_playing_piece(space)) {
+ result.push(colony)
+ break
+ }
+ }
+ }
+ return result
+}
+
/* SETUP PHASE */
function goto_committees_of_correspondence() {
log("=a Committes of Correspondence")
game.active = P_AMERICA
game.state = "committees_of_correspondence"
- game.colonies = THE_13_COLONIES.slice()
+ game.colonies = filter_place_american_pc_in_colony(THE_13_COLONIES)
}
states.committees_of_correspondence = {
@@ -1062,7 +1025,7 @@ function goto_start_year() {
log("=t Year " + game.year)
// Prisoner exchange
- // TODO: manual?
+ // TODO: manual reinforcements phase?
for (let g of BRITISH_GENERALS)
if (is_general_at_location(g, CAPTURED_GENERALS))
move_general(g, BRITISH_REINFORCEMENTS)
@@ -1180,6 +1143,15 @@ states.choose_first_player = {
function goto_strategy_phase(new_active) {
game.active = new_active
game.state = "strategy_phase"
+
+ let hand = active_hand()
+ if (hand.length === 0) {
+ game.active = ENEMY[game.active]
+ hand = active_hand()
+ if (hand.length === 0)
+ return goto_winter_attrition_phase()
+ }
+
if (game.active === P_AMERICA)
log("=a America")
else
@@ -1213,7 +1185,6 @@ states.strategy_phase = {
push_undo()
let d = game.did_discard_event
set_add(active_hand(), d)
- log("Picked up up C" + d)
game.state = "exchange"
},
}
@@ -1228,8 +1199,10 @@ states.exchange = {
gen_action_card("card", c)
},
card(c) {
+ let x = game.did_discard_event
+ set_delete(active_hand(), c)
game.did_discard_event = 0
- discard_card(c, " in exchange")
+ log("Exchanged C" + c + " for C" + x + ".")
game.state = "strategy_phase"
},
}
@@ -1240,14 +1213,22 @@ states.strategy_phase_ops = {
let c = game.card
view.selected_card = game.card
view.prompt = "Use " + card_name(c) + "."
+
if (can_activate_general(c))
view.actions.activate = 1
+ else
+ view.actions.activate = 0
+
if (can_play_reinforcements())
view.actions.reinforce = 1
+ else
+ view.actions.reinforce = 0
+
if (game.active === P_AMERICA && game.a_queue + CARDS[c].count < 3)
view.actions.queue = 1
if (game.active === P_BRITAIN && game.b_queue + CARDS[c].count < 3)
view.actions.queue = 1
+
view.actions.pc_action = 1
},
@@ -1255,24 +1236,31 @@ states.strategy_phase_ops = {
let c = game.card
game.did_discard_event = 0
clear_queue()
- play_card(c, "for PC")
+ log("Played C" + c + ".")
+ play_card(c)
goto_ops_pc(CARDS[c].count)
},
activate() {
let c = game.card
game.did_discard_event = 0
+ log("Played C" + c + ".")
+ play_card(c)
goto_ops_general(c)
},
reinforce() {
let c = game.card
game.did_discard_event = 0
clear_queue()
+ log("Played C" + c + ".")
+ play_card(c)
goto_ops_reinforcements(c)
},
queue() {
let c = game.card
game.did_discard_event = 0
- play_card(c, "to queue")
+ log("Played C" + c + ".")
+ play_card(c)
+ log("Operations Queue.")
if (game.active === P_BRITAIN)
game.b_queue += CARDS[c].count
else
@@ -1336,7 +1324,8 @@ states.strategy_phase_event = {
let c = game.card
game.did_discard_event = c
clear_queue()
- discard_card(c, "for PC action")
+ log("Discarded C" + c + ".")
+ discard_card(c)
game.state = "discard_event_pc_action"
},
}
@@ -1364,13 +1353,13 @@ function end_strategy_card() {
}
while (game.b_draw > 0) {
- log("B drew replacement card.")
+ log("British replacement card.")
set_add(game.b_hand, deal_card())
game.b_draw--
}
while (game.a_draw > 0) {
- log("A drew replacement card.")
+ log("American replacement card.")
set_add(game.a_hand, deal_card())
game.a_draw--
}
@@ -1391,6 +1380,8 @@ states.end_strategy_card = {
}
function next_strategy_card() {
+ clear_undo()
+
game.card = 0
if (!has_flag(F_FRENCH_ALLIANCE_TRIGGERED) && game.french_alliance === 9) {
@@ -1408,14 +1399,6 @@ function next_strategy_card() {
reset_moved_cu()
goto_strategy_phase(ENEMY[game.active])
-
- let hand = active_hand()
- if (hand.length === 0) {
- game.active = ENEMY[game.active]
- hand = active_hand()
- if (hand.length === 0)
- return goto_winter_attrition_phase()
- }
}
function clear_queue() {
@@ -1577,9 +1560,67 @@ function gen_american_pc_ops() {
/* PLAY OPS CARD FOR REINFORCEMENTS */
+function place_british_reinforcements(who, count, where) {
+ let already_there = find_british_general(where)
+ if (who !== NOBODY && already_there !== NOBODY) {
+ move_general(already_there, BRITISH_REINFORCEMENTS)
+ }
+ if (who !== NOBODY) {
+ log(`Reinforced ${count} CU and G${who} at S${where}.`)
+ move_general(who, where)
+ } else {
+ log(`Reinforced ${count} CU at S${where}.`)
+ }
+ if (count > 0) {
+ move_british_cu(BRITISH_REINFORCEMENTS, where, count)
+ if (has_enemy_general(where))
+ capture_enemy_general(where)
+ if (game.congress === where)
+ disperse_continental_congress()
+ }
+}
+
+function place_american_reinforcements(who, count, where) {
+ let already_there = find_american_or_french_general(where)
+ if (who !== NOBODY && already_there !== NOBODY) {
+ // Never replace Washington
+ if (already_there === WASHINGTON)
+ who = NOBODY
+ else
+ move_general(already_there, AMERICAN_REINFORCEMENTS)
+ }
+ if (who !== NOBODY) {
+ log(`Reinforced ${count} CU and G${who} at S${where}.`)
+ move_general(who, where)
+ } else {
+ log(`Reinforced ${count} CU at S${where}.`)
+ }
+ place_american_cu(where, count)
+ if (has_enemy_general(where))
+ capture_enemy_general(where)
+}
+
+function place_french_reinforcements(who, where) {
+ let already_there = find_american_or_french_general(where)
+ if (who !== NOBODY && already_there !== NOBODY) {
+ // Never replace Washington
+ if (already_there === WASHINGTON)
+ who = NOBODY
+ else
+ move_general(already_there, AMERICAN_REINFORCEMENTS)
+ }
+ if (who !== NOBODY) {
+ log(`Reinforced ${count} CU and G${who} at S${where}.`)
+ move_general(who, where)
+ } else {
+ log(`Reinforced ${count} CU at S${where}.`)
+ }
+ move_french_cu(FRENCH_REINFORCEMENTS, where, count_french_cu(FRENCH_REINFORCEMENTS))
+ move_french_cu(AMERICAN_REINFORCEMENTS, where, count_french_cu(AMERICAN_REINFORCEMENTS))
+}
+
function goto_ops_reinforcements(c) {
let count = CARDS[c].count
- play_card(c, "for reinforcements")
if (game.active === P_BRITAIN) {
game.reinforcements[0] = c
game.count = count_british_cu(BRITISH_REINFORCEMENTS)
@@ -1736,7 +1777,6 @@ function gen_american_reinforcements_where(general) {
/* PLAY OPS CARD TO MOVE A GENERAL */
function goto_ops_general(c) {
- play_card(c, "to activate a general")
if (game.active === P_BRITAIN) {
game.count = CARDS[c].count + game.b_queue
game.b_queue = 0
@@ -1951,6 +1991,14 @@ function goto_ops_general_move(g, marblehead) {
pickup_max_british_cu(game.move)
else
pickup_max_american_cu(game.move)
+
+ /*
+ let cu = game.move.carry_american + game.move.carry_french + game.move.carry_british
+ if (cu > 0)
+ log(`Moved G${g} with ${cu} CU\nfrom S${where}`)
+ else
+ */
+ log(`Moved G${g}\nfrom S${where}`)
}
function format_move_prompt() {
@@ -2006,29 +2054,40 @@ states.ops_general_move = {
drop_british_cu() {
push_undo()
--game.move.carry_british
- if (has_general_moved(game.move.who))
+ if (has_general_moved(game.move.who)) {
+ log(">>dropped CU")
mark_moved_british_cu(location_of_general(game.move.who), 1)
+ }
},
drop_american_cu() {
push_undo()
--game.move.carry_american
- if (has_general_moved(game.move.who))
+ if (has_general_moved(game.move.who)) {
+ log(">>dropped CU")
mark_moved_american_cu(location_of_general(game.move.who), 1)
+ }
},
drop_french_cu() {
push_undo()
--game.move.carry_french
- if (has_general_moved(game.move.who))
+ if (has_general_moved(game.move.who)) {
+ log(">>dropped CU")
mark_moved_french_cu(location_of_general(game.move.who), 1)
+ }
},
space(to) {
push_undo()
- set_general_moved(game.move.who)
let from = location_of_general(game.move.who)
let cu = game.move.carry_british + game.move.carry_american + game.move.carry_french
+ if (!has_general_moved(game.move.who)) {
+ log(">>with " + cu + " CU")
+ }
+
+ set_general_moved(game.move.who)
+
let may_intercept = false
if (game.active === P_BRITAIN) {
let is_sea_move = path_type(from, to) === "sea"
@@ -2045,6 +2104,8 @@ states.ops_general_move = {
game.move.count -= 1
}
+ log(">to S" + game.move.to)
+
move_army(game.move)
if (may_intercept)
@@ -2302,7 +2363,7 @@ states.intercept_roll = {
let g = game.intercept.who
let die = roll_d6()
if (die <= GENERALS[g].agility) {
- log(g + " intercepted (" + die + " <= " + GENERALS[g].agility + ")")
+ log("Intercept G" + g + "\nrolled " + die + " <= " + GENERALS[g].agility + "\nfrom S" + game.intercept.from)
game.move.did_intercept = 1
move_army(game.intercept)
@@ -2312,7 +2373,7 @@ states.intercept_roll = {
else
end_intercept()
} else {
- log(g + " failed to intercept (" + die + " > " + GENERALS[g].agility + ")")
+ log("Intercept G" + g + "\nrolled " + die + " > " + GENERALS[g].agility + "\nfailure")
delete game.intercept
if (can_intercept_to(game.move.to))
game.state = "intercept_who"
@@ -2425,7 +2486,7 @@ states.retreat_before_battle_roll = {
agility += 2
let roll = roll_d6()
if (roll <= agility) {
- logp("successfully retreated before battle: " + roll + " <= " + agility)
+ log("Retreat G" + who + "\nrolled " + roll + " <= " + agility + "\nto S" + to)
move_army(game.retreat)
if (has_enemy_general(to))
capture_enemy_general(to)
@@ -2434,7 +2495,7 @@ states.retreat_before_battle_roll = {
delete game.retreat
goto_remove_general_after_retreat_before_battle(to)
} else {
- logp("failed to retreat before battle: " + roll + " > " + agility)
+ log("Retreat G" + who + "\nrolled " + roll + " > " + agility + "\nfailure")
delete game.retreat
end_retreat_before_battle()
}
@@ -2514,6 +2575,7 @@ states.remove_benedict_arnold_defender = {
}
function goto_play_attacker_battle_card() {
+ log("=! Battle at S" + game.move.to)
game.active = game.combat.attacker
game.state = "play_attacker_battle_card"
}
@@ -2529,7 +2591,8 @@ states.play_attacker_battle_card = {
},
card_battle_play(c) {
push_undo()
- play_card(c, "for +2 DRM")
+ log(`${game.active} played C${c} for +2 DRM.`)
+ play_card(c)
if (game.active === P_BRITAIN) {
game.b_draw += 1
game.combat.b_bonus += 2
@@ -2544,7 +2607,8 @@ states.play_attacker_battle_card = {
},
card_battle_discard(c) {
push_undo()
- discard_card(c, "for +1 DRM")
+ log(`${game.active} discarded C${c} for +1 DRM.`)
+ discard_card(c)
if (game.active === P_BRITAIN) {
game.b_draw += 1
game.combat.b_bonus += 1
@@ -2579,6 +2643,8 @@ states.play_attacker_battle_card_confirm = {
function goto_play_defender_battle_card() {
game.state = "play_defender_battle_card"
game.active = ENEMY[game.combat.attacker]
+ if (active_hand().length === 0)
+ resolve_battle()
}
states.play_defender_battle_card = {
@@ -2593,7 +2659,8 @@ states.play_defender_battle_card = {
},
card_battle_play(c) {
push_undo()
- play_card(c, "for +2 DRM")
+ log(`${game.active} played C${c} for +2 DRM.`)
+ play_card(c)
if (game.active === P_BRITAIN) {
game.b_draw += 1
game.combat.b_bonus += 2
@@ -2608,7 +2675,8 @@ states.play_defender_battle_card = {
},
card_battle_discard(c) {
push_undo()
- discard_card(c, "for +1 DRM")
+ log(`${game.active} discarded C${c} for +1 DRM.`)
+ discard_card(c)
if (game.active === P_BRITAIN) {
game.b_draw += 1
game.combat.b_bonus += 1
@@ -2775,9 +2843,9 @@ function resolve_battle() {
let a_br = 0
if (b_g !== NOBODY)
- b_log.push("General: " + b_g)
+ b_log.push("General: G" + b_g)
if (a_g !== NOBODY)
- a_log.push("General: " + a_g)
+ a_log.push("General: G" + a_g)
if (b_g !== NOBODY) {
let roll = roll_d6()
@@ -2853,6 +2921,17 @@ function resolve_battle() {
a_log.push("Battle Roll: " + a_roll)
a_log.push("Battle Total: " + (a_roll + a_drm))
+ if (game.combat.attacker === P_BRITAIN) {
+ log("BRITISH ATTACK:\n" + b_log.join("\n"))
+ log("AMERICAN DEFENSE:\n" + a_log.join("\n"))
+ } else {
+ log("AMERICAN ATTACK:\n" + a_log.join("\n"))
+ log("BRITISH DEFENSE:\n" + b_log.join("\n"))
+ }
+
+ a_log = []
+ b_log = []
+
let victor
if (game.active === P_BRITAIN)
victor = b_roll + b_drm >= a_roll + a_drm ? P_BRITAIN : P_AMERICA
@@ -2876,16 +2955,23 @@ function resolve_battle() {
// Special case: winning general with no CU on enemy PC is captured
if (victor === P_BRITAIN) {
+ log("RESULT:\nBritish victory!")
if (b_g && count_british_cu(game.move.to) === 0 && has_american_pc(game.move.to))
capture_british_general(game.move.to)
} else {
+ log("RESULT:\nAmerican victory!")
if (a_g && count_american_and_french_cu(game.move.to) === 0 && has_british_pc(game.move.to))
capture_american_or_french_general(game.move.to)
}
- log("BRITISH BATTLE REPORT:\n" + b_log.join("\n"))
- log("AMERICAN BATTLE REPORT:\n" + a_log.join("\n"))
- log(victor + " victory in " + game.move.to + "!")
+
+ if (game.combat.attacker === P_BRITAIN) {
+ log("BRITISH LOSSES:\n" + b_log.join("\n"))
+ log("AMERICAN LOSSES:\n" + a_log.join("\n"))
+ } else {
+ log("AMERICAN LOSSES:\n" + a_log.join("\n"))
+ log("BRITISH LOSSES:\n" + b_log.join("\n"))
+ }
if (victor === P_AMERICA)
advance_french_alliance(1)
@@ -2996,7 +3082,7 @@ states.retreat_after_battle = {
},
space(to) {
push_undo()
- logp("retreated to " + to)
+
if (game.active === P_BRITAIN)
retreat_british_army(game.move.to, to)
else
@@ -3017,7 +3103,7 @@ states.retreat_after_battle = {
game.state = "retreat_after_battle_confirm"
},
surrender() {
- logp("surrendered")
+ log("Surrendered.")
if (game.active === P_BRITAIN)
surrender_british_army(game.move.to)
else
@@ -3056,7 +3142,6 @@ function end_battle() {
/* EVENTS */
events.campaign = function (c, card) {
- play_card(c)
game.state = "campaign"
game.campaign = card.count
if (game.active === P_BRITAIN)
@@ -3068,20 +3153,16 @@ events.campaign = function (c, card) {
}
events.the_war_ends = function (c, card) {
- log("Played C" + c)
- log("The war will end in " + card.year)
set_delete(active_hand(), c)
game.war_ends = c
end_strategy_card()
}
events.remove_random_british_card = function (c, card) {
- play_card(c)
remove_random_card(game.b_hand)
}
events.remove_random_american_card = function (c, card) {
- play_card(c)
remove_random_card(game.a_hand)
}
@@ -3090,7 +3171,7 @@ function remove_random_card(hand) {
if (hand.length > 0) {
let i = random(hand.length)
let c = hand[i]
- log("Discarded C" + c + ".")
+ log("Opponent discarded C" + c + ".")
discard_card_from_hand(hand, c)
if (CARDS[c].type === "mandatory-event")
do_event(c)
@@ -3105,7 +3186,7 @@ function advance_french_alliance(count) {
game.french_alliance += count
if (game.french_alliance > 9)
game.french_alliance = 9
- log("French alliance advanced to " + count)
+ log("French Alliance advanced to " + count + ".")
}
}
@@ -3118,7 +3199,6 @@ function lose_regular_advantage() {
}
events.baron_von_steuben_trains_the_continental_army = function (c, card) {
- play_card(c)
if (is_general_on_map(WASHINGTON))
game.state = "baron_von_steuben_trains_the_continental_army"
else
@@ -3133,7 +3213,7 @@ states.baron_von_steuben_trains_the_continental_army = {
},
general(_) {
let where = location_of_general(WASHINGTON)
- logp("placed 2 CU with Washington in " + where)
+ log("Placed 2 CU and Washington at S" + where + ".")
place_american_cu(where, 2)
lose_regular_advantage()
end_strategy_card()
@@ -3141,7 +3221,6 @@ states.baron_von_steuben_trains_the_continental_army = {
}
events.advance_french_alliance = function (c, card) {
- play_card(c)
// TODO: advance alliance manual?
// game.state = "advance_french_alliance"
advance_french_alliance(card.count)
@@ -3149,14 +3228,12 @@ events.advance_french_alliance = function (c, card) {
}
events.remove_french_navy = function (c, card) {
- play_card(c)
// TODO: remove french navy manual?
game.french_navy = game.year + 1
end_strategy_card()
}
events.remove_british_pc_from = function (c, card) {
- play_card(c)
game.count = card.count
game.where = card.where
game.state = "remove_british_pc_from"
@@ -3187,7 +3264,6 @@ states.remove_british_pc_from = {
}
events.remove_american_pc = function (c, card) {
- play_card(c)
game.count = card.count
game.state = "remove_american_pc"
}
@@ -3214,7 +3290,6 @@ states.remove_american_pc = {
}
events.remove_american_pc_from = function (c, card) {
- play_card(c)
game.count = card.count
game.where = card.where
game.state = "remove_american_pc_from"
@@ -3245,7 +3320,6 @@ states.remove_american_pc_from = {
}
events.remove_american_pc_from_non_port = function (c, card) {
- play_card(c)
game.count = card.count
game.where = card.where
game.state = "remove_american_pc_from_non_port"
@@ -3281,7 +3355,6 @@ states.remove_american_pc_from_non_port = {
}
events.remove_american_pc_within_two_spaces_of_a_british_general = function (c, card) {
- play_card(c)
game.count = card.count
game.state = "remove_american_pc_within_two_spaces_of_a_british_general"
}
@@ -3327,7 +3400,6 @@ states.remove_american_pc_within_two_spaces_of_a_british_general = {
}
events.place_american_pc = function (c, card) {
- play_card(c)
game.count = card.count
game.state = "place_american_pc"
}
@@ -3353,16 +3425,13 @@ states.place_american_pc = {
}
events.place_american_pc_in = function (c, card) {
- play_card(c)
- game.count = card.count
- game.where = card.where
+ game.where = filter_place_american_pc_in_colony(card.where)
game.state = "place_american_pc_in"
}
states.place_american_pc_in = {
prompt() {
view.prompt = "Place American PC markers in " + game.where.join(", ") + ". " + game.count + " left."
- view.actions.pass = 1
gen_place_american_pc_in_colony(game.where)
},
space(where) {
@@ -3372,14 +3441,9 @@ states.place_american_pc_in = {
end_strategy_card()
}
},
- pass() {
- delete game.where
- end_strategy_card()
- },
}
events.lord_sandwich_coastal_raids = function (c, card) {
- play_card(c)
game.state = "lord_sandwich_coastal_raids"
game.count = 2
delete game.where
@@ -3418,7 +3482,6 @@ function gen_lord_sandwich_coastal_raids(first_removed) {
}
events.remove_american_cu = function (c, card) {
- play_card(c)
game.state = "remove_american_cu"
}
@@ -3443,7 +3506,6 @@ states.remove_american_cu = {
}
events.remove_british_cu = function (c, card) {
- play_card(c)
game.state = "remove_british_cu"
game.count = card.count
}
@@ -3467,7 +3529,6 @@ states.remove_british_cu = {
}
events.pennsylvania_and_new_jersey_line_mutinies = function (c, card) {
- play_card(c)
set_flag(F_MUTINIES)
game.state = "pennsylvania_and_new_jersey_line_mutinies"
game.count = 2
@@ -3503,7 +3564,6 @@ function gen_pennsylvania_and_new_jersey_line_mutinies(first_removed) {
}
events.john_glovers_marblehead_regiment = function (c, card) {
- play_card(c)
game.state = "john_glovers_marblehead_regiment_who"
game.count = 3 // strategy rating for gen_activate_general
}
@@ -3519,18 +3579,24 @@ states.john_glovers_marblehead_regiment_who = {
}
events.declaration_of_independence = function (c, card) {
- play_card(c)
game.save = game.active
game.active = P_AMERICA
- game.colonies = THE_13_COLONIES.slice()
game.state = "declaration_of_independence"
+ game.colonies = filter_place_american_pc_in_colony(THE_13_COLONIES)
}
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."
- view.actions.pass = 1
+ if (game.colonies.length > 0) {
+ view.prompt = "Declaration of Independence: Place a PC marker in "
+ if (game.colonies.length <= 3)
+ view.prompt += game.colonies.map(colony_name).join(" and ") + "."
+ else
+ view.prompt += "each of the 13 colonies."
+ } else {
+ view.prompt = "Declaration of Independence: Done."
+ view.actions.next = 1
+ }
gen_place_american_pc_in_colony(game.colonies)
},
space(space) {
@@ -3538,24 +3604,25 @@ states.declaration_of_independence = {
let colony = SPACES[space].colony
set_delete(game.colonies, colony)
place_american_pc(space)
- if (game.colonies.length === 0)
- end_declaration_of_independence()
},
- pass() {
- push_undo()
+ next() {
+ clear_undo()
end_declaration_of_independence()
- },
+ }
}
function end_declaration_of_independence() {
game.active = game.save
delete game.save
delete game.colonies
- end_strategy_card()
+ if (end_strategy_card())
+ next_strategy_card()
}
function do_event(c) {
let card = CARDS[c]
+ log("Played C" + c + ".")
+ play_card(c)
if (card.event in events)
events[card.event](c, card)
else
@@ -3656,16 +3723,18 @@ states.george_washington_captured_during_move = {
function apply_single_winter_attrition(remove_cu, space) {
let die = roll_d6()
- log("Attrition roll " + die + " in " + space)
+ log("Roll " + die + " at S" + space)
if (die <= 3) {
- log("Lost 1 CU in " + space)
+ log(">Lost 1 CU")
remove_cu(space, 1)
+ } else {
+ log(">Lost 0 CU")
}
}
function apply_winter_attrition(remove_cu, space, n) {
let half = Math.floor(n / 2)
- log("Lost " + half + " CU in " + space)
+ log("Lost " + half + " CU at S" + space + ".")
remove_cu(space, half)
}
@@ -3701,16 +3770,17 @@ function has_american_winter_attrition(s) {
}
function goto_american_winter_attrition() {
- log("=a Winter Attrition")
game.active = P_AMERICA
game.attrition = []
for (let s of all_spaces)
if (has_american_winter_attrition(s))
game.attrition.push(s)
- if (game.attrition.length > 0)
+ if (game.attrition.length > 0) {
+ log("=a Winter Attrition")
game.state = "american_winter_attrition"
- else
+ } else {
end_american_winter_attrition()
+ }
}
function end_american_winter_attrition() {
@@ -3719,7 +3789,6 @@ function end_american_winter_attrition() {
}
function goto_british_winter_attrition() {
- log("=b Winter Attrition")
game.active = P_BRITAIN
game.attrition = []
for (let space of all_spaces) {
@@ -3728,10 +3797,12 @@ function goto_british_winter_attrition() {
if (n_british > 0 && !wq)
game.attrition.push(space)
}
- if (game.attrition.length > 0)
+ if (game.attrition.length > 0) {
+ log("=b Winter Attrition")
game.state = "british_winter_attrition"
- else
+ } else {
end_british_winter_attrition()
+ }
}
function end_british_winter_attrition() {
@@ -3787,11 +3858,11 @@ states.american_winter_attrition = {
// TODO: let player choose (but why would they ever choose French?)
let half = Math.floor(n_total / 2)
let lose_american = Math.min(half, n_american)
- log("Lost " + lose_american + " American CU in " + s)
+ log(lose_american + " American CU at " + s)
remove_american_cu(s, n_american)
half -= lose_american
if (half > 0) {
- log("Lost " + half + " French CU in " + s)
+ log(half + " French CU at " + s)
remove_french_cu(s, half)
}
}
@@ -3846,6 +3917,16 @@ function gen_place_french_navy() {
view.actions.sea = [ 0, 1, 2, 3, 4, 5, 6 ]
}
+const ZONE_NAME = [
+ "Canada",
+ "MA/RI",
+ "CT/NY",
+ "PA/DE",
+ "MD/VA",
+ "NC/SC",
+ "GA",
+]
+
states.place_french_navy_trigger = {
prompt() {
view.prompt = "Place the French Navy in a blockade zone."
@@ -3853,7 +3934,7 @@ states.place_french_navy_trigger = {
},
sea(zone) {
push_undo()
- logp("placed French Navy.")
+ log("French Navy at " + ZONE_NAME[zone] + ".")
game.french_navy = zone
goto_place_rochambeau()
},
@@ -3888,7 +3969,7 @@ states.place_rochambeau = {
},
space(to) {
push_undo()
- logp("placed Rochambeau .")
+ log("Placed 5 CU and Rochambeau at S" + to + ".")
move_general(ROCHAMBEAU, to)
move_french_cu(FRENCH_REINFORCEMENTS, to, 5)
if (count_friendly_generals(to) > 1)
@@ -3939,7 +4020,7 @@ states.place_french_navy = {
gen_place_french_navy()
},
sea(zone) {
- logp("placed French Navy.")
+ log("French Navy at " + ZONE_NAME[zone] + ".")
game.french_navy = zone
goto_political_control_phase()
},
@@ -3948,9 +4029,9 @@ states.place_french_navy = {
/* POLITICAL CONTROL PHASE: RETURN CONGRESS */
function goto_political_control_phase() {
- log("# Political Control Phase")
+ game.active = P_AMERICA
if (game.congress === CONTINENTAL_CONGRESS_DISPERSED) {
- game.active = P_AMERICA
+ log("=a Continental Congress")
game.state = "return_continental_congress"
} else {
goto_place_pc_markers_segment()
@@ -3978,11 +4059,12 @@ states.return_continental_congress = {
},
space(where) {
push_undo()
+ log("Returned Continental Congress to S" + where + ".")
game.congress = where
- goto_place_pc_markers_segment()
+ goto_place_pc_markers_segment(false)
},
pass() {
- goto_place_pc_markers_segment()
+ goto_place_pc_markers_segment(false)
},
}
@@ -4006,6 +4088,20 @@ function has_british_place_pc_markers_segment() {
function goto_place_pc_markers_segment() {
if (has_american_place_pc_markers_segment()) {
+ log("=a Place PC Markers")
+ game.active = P_AMERICA
+ game.state = "place_american_pc_markers_segment"
+ } else if (has_british_place_pc_markers_segment()) {
+ log("=b Place PC Markers")
+ game.active = P_BRITAIN
+ game.state = "place_british_pc_markers_segment"
+ } else {
+ goto_remove_isolated_pc_marker_segment()
+ }
+}
+
+function resume_place_pc_markers_segment() {
+ if (has_american_place_pc_markers_segment()) {
game.active = P_AMERICA
game.state = "place_american_pc_markers_segment"
} else if (has_british_place_pc_markers_segment()) {
@@ -4042,7 +4138,7 @@ states.place_american_pc_markers_segment = {
flip_pc(s)
},
next() {
- goto_place_pc_markers_segment()
+ resume_place_pc_markers_segment()
},
}
@@ -4072,7 +4168,7 @@ states.place_british_pc_markers_segment = {
flip_pc(s)
},
next() {
- goto_place_pc_markers_segment()
+ resume_place_pc_markers_segment()
},
}
@@ -4160,6 +4256,7 @@ function goto_remove_isolated_american_pc_segment() {
set_add(game.isolated, space)
if (game.isolated.length > 0) {
+ log("=a Remove Isolated PC Markers")
game.active = P_AMERICA
game.state = "remove_isolated_pc_segment"
} else {
@@ -4182,6 +4279,7 @@ function goto_remove_isolated_british_pc_segment() {
set_add(game.isolated, space)
if (game.isolated.length > 0) {
+ log("=b Remove Isolated PC Markers")
game.active = P_BRITAIN
game.state = "remove_isolated_pc_segment"
} else {
@@ -4201,7 +4299,6 @@ states.remove_isolated_pc_segment = {
}
},
space(s) {
- log("Removed American PC from " + s)
set_delete(game.isolated, s)
remove_pc(s)
},
@@ -4424,10 +4521,6 @@ function log(s) {
game.log.push(s)
}
-function logp(s) {
- game.log.push(game.active + " " + s)
-}
-
function log_br() {
if (game.log.length > 0 && game.log[game.log.length - 1] !== "")
game.log.push("")