summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--play.js10
-rw-r--r--rules.js450
2 files changed, 203 insertions, 257 deletions
diff --git a/play.js b/play.js
index 98646cb..dc5863e 100644
--- a/play.js
+++ b/play.js
@@ -234,6 +234,10 @@ function build_map() {
}
}
+function get_space_pc(space) {
+ return view.pc[space] & 3
+}
+
function update_units() {
const unitW = 130 / 2
const unitH = 263 / 2
@@ -273,7 +277,7 @@ function update_units() {
}
for (let space = 0; space < space_count; ++space) {
- let space_pc = view.pc[space]
+ let space_pc = get_space_pc(space)
let e = ui.pc[space]
if (space_pc === PC_BRITISH) {
e.classList.remove("american")
@@ -290,9 +294,9 @@ function update_units() {
for (let c = 0; c <= 13; ++c) {
let control = 0
for (let space of COLONIES[c]) {
- if (view.pc[space] == PC_BRITISH)
+ if (get_space_pc(space) == PC_BRITISH)
--control
- else if (view.pc[space] == PC_AMERICAN)
+ else if (get_space_pc(space) == PC_AMERICAN)
++control
}
if (control < 0)
diff --git a/rules.js b/rules.js
index f7fc222..758de2e 100644
--- a/rules.js
+++ b/rules.js
@@ -37,6 +37,24 @@ const PC_NONE = 0
const PC_BRITISH = 1
const PC_AMERICAN = 2
+// max 5 french CU in game total
+// no stacking limit on other units, but max 6 new american CU per turn * 9 turns (=54) + starting forces (2+2+5)
+// british cu = 3+8+1+8+1+5+1+1+1 (=29) reinforcements + starting forces (1+2+5)
+// 6 bits for british, 6 bits for american, 3 bits for french = 15 bits total
+// x2 for moved = 30 bits
+// moved_cu=5+5+3 bits
+// cu=5+5+3 bits
+// pc=2 bits
+
+// OR: pack space=8, owner=2, count=6, moved=6
+
+const CU_BRITISH_SHIFT = 2
+const CU_AMERICAN_SHIFT = 8
+const CU_FRENCH_SHIFT = 14
+const CU_BRITISH_MASK = 63 << CU_BRITISH_SHIFT
+const CU_AMERICAN_MASK = 63 << CU_AMERICAN_SHIFT
+const CU_FRENCH_MASK = 7 << CU_FRENCH_SHIFT
+
const AMERICAN_GENERALS = [ 0, 1, 2, 3, 4, 5, 6, 7 ]
const BRITISH_GENERALS = [ 8, 9, 10, 11, 12 ]
@@ -58,6 +76,7 @@ const HOWE = data.general_index["Howe"]
const NOWHERE = -1
const BOSTON = data.space_index["Boston"]
const CHARLESTON = data.space_index["Charleston"]
+const FALMOUTH = data.space_index["Falmouth"]
const FORT_DETROIT = data.space_index["Fort Detroit"]
const GILBERT_TOWN = data.space_index["Gilbert Town"]
const LEXINGTON_CONCORD = data.space_index["Lexington Concord"]
@@ -85,9 +104,13 @@ const BARON_VON_STEUBEN = 86
const WAR_ENDS_1779 = 71
const BENJAMIN_FRANKLIN = 101
+const general_count = data.generals.length
const space_count = 66
const all_spaces = new Array(space_count).fill(0).map((_,i)=>i)
+// 66 * 2 / 32 = 5 words for all PC data
+// cu stacks
+
const ENEMY = { American: BRITISH, British: AMERICAN }
let states = {}
@@ -113,7 +136,7 @@ function setup_game(seed) {
pc: new Array(space_count).fill(PC_NONE),
generals: new Array(general_count).fill(NOWHERE),
moved: [],
- cu: [],
+ mcu: [],
// TODO: compute on the fly
control: [],
@@ -140,7 +163,7 @@ function setup_game(seed) {
if (general !== NOBODY)
set_general_location(general, location)
if (cu > 0)
- spawn_cu(owner, location, count)
+ spawn_cu(owner, location, cu)
}
function british(place, pc, cu, ld) {
@@ -358,16 +381,20 @@ function set_space_pc(space, pc) {
game.pc[space] = pc
}
+function get_space_pc(space) {
+ return game.pc[space]
+}
+
function has_no_pc(space) {
- return game.pc[space] === PC_NONE
+ return get_space_pc(space) === PC_NONE
}
function has_british_pc(space) {
- return game.pc[space] === PC_BRITISH
+ return get_space_pc(space) === PC_BRITISH
}
function has_american_pc(space) {
- return game.pc[space] === PC_AMERICAN
+ return get_space_pc(space) === PC_AMERICAN
}
function has_enemy_pc(space) {
@@ -449,50 +476,55 @@ function update_colony_control() {
/* CU */
-function find_cu(owner, space) {
- for (let i = 0; i < game.cu.length; ++i) {
- let cu = game.cu[i]
- if (cu.location === space && cu.owner === owner)
- return cu
- }
- return null
+function reset_moved_cu() {
+ map_clear(game.mcu)
}
-function reset_moved_cu() {
- for (let cu of game.cu)
- cu.moved = 0
+function count_british_cu(s) {
+ return (game.pc[s] & CU_BRITISH_MASK) >>> CU_BRITISH_SHIFT
}
-function find_british_cu(space) {
- return find_cu(BRITISH, space)
+function count_american_cu(s) {
+ return (game.pc[s] & CU_AMERICAN_MASK) >>> CU_AMERICAN_SHIFT
}
-function find_american_cu(space) {
- return find_cu(AMERICAN, space)
+function count_french_cu(s) {
+ return (game.pc[s] & CU_FRENCH_MASK) >>> CU_FRENCH_SHIFT
}
-function find_french_cu(space) {
- return find_cu(FRENCH, space)
+function set_british_cu(s, n) {
+ game.pc[s] &= ~CU_BRITISH_MASK
+ game.pc[s] |= n << CU_BRITISH_SHIFT
+}
+
+function set_american_cu(s, n) {
+ game.pc[s] &= ~CU_AMERICAN_MASK
+ game.pc[s] |= n << CU_AMERICAN_SHIFT
+}
+
+function set_french_cu(s, n) {
+ game.pc[s] &= ~CU_FRENCH_MASK
+ game.pc[s] |= n << CU_FRENCH_SHIFT
}
function has_british_cu(space) {
- return find_british_cu(space) !== null
+ return count_british_cu(space) > 0
}
function has_no_british_cu(space) {
- return !has_british_cu(space)
+ return count_british_cu(space) === 0
}
function has_american_or_french_cu(space) {
- return find_american_cu(space) !== null || find_french_cu(space) !== null
+ return count_american_cu(space) > 0 || count_french_cu(space) > 0
}
function has_american_cu(space) {
- return find_american_cu(space) !== null
+ return count_american_cu(space) > 0
}
function has_french_cu(space) {
- return find_french_cu(space) !== null
+ return count_french_cu(space) > 0
}
function has_enemy_cu(where) {
@@ -502,44 +534,35 @@ function has_enemy_cu(where) {
return has_british_cu(where)
}
-function count_cu(owner, space) {
- let cu = find_cu(owner, space)
- return cu ? cu.count : 0
-}
-
-function count_british_cu(where) {
- let cu = find_british_cu(where)
- return cu ? cu.count : 0
+function count_unmoved_british_cu(where) {
+ return count_british_cu(where) - map_get(game.mcu, where * 3 + 0, 0)
}
-function count_american_cu(where) {
- let cu = find_american_cu(where)
- return cu ? cu.count : 0
+function count_unmoved_american_cu(where) {
+ return count_american_cu(where) - map_get(game.mcu, where * 3 + 1, 0)
}
-function count_french_cu(where) {
- let cu = find_french_cu(where)
- return cu ? cu.count : 0
+function count_unmoved_french_cu(where) {
+ return count_french_cu(where) - map_get(game.mcu, where * 3 + 2, 0)
}
-function count_unmoved_british_cu(where) {
- let cu = find_british_cu(where)
- return cu ? cu.count - cu.moved : 0
+function mark_moved_cu_imp(offset, where, moved) {
+ if (moved > 0) {
+ let old = map_get(game.mcu, where * 3 + offset, 0)
+ map_set(game.mcu, where * 3 + offset, old + moved)
+ }
}
-function count_unmoved_american_cu(where) {
- let cu = find_american_cu(where)
- return cu ? cu.count - cu.moved : 0
+function mark_moved_british_cu(space, moved) {
+ mark_moved_cu_imp(0, space, moved)
}
-function count_unmoved_french_cu(where) {
- let cu = find_french_cu(where)
- return cu ? cu.count - cu.moved : 0
+function mark_moved_american_cu(space, moved) {
+ mark_moved_cu_imp(1, space, moved)
}
-function mark_moved_cu(owner, space, moved) {
- if (moved > 0)
- find_cu(owner, space).moved += moved
+function mark_moved_french_cu(space, moved) {
+ mark_moved_cu_imp(2, space, moved)
}
function count_american_and_french_cu(where) {
@@ -557,58 +580,43 @@ function spawn_cu(owner, where, count) {
game.cu.push({ owner: owner, location: where, count: count, moved: 0 })
}
-function remove_cu(owner, where, count) {
- if (count === 0)
- return
- let cu = find_cu(owner, where)
- if (count >= cu.count) {
- let i = game.cu.indexOf(cu)
- array_remove_item(game.cu, cu)
- } else {
- cu.count -= count
- }
+function remove_british_cu(where, count) {
+ set_british_cu(where, count_british_cu(where) - count)
}
-function place_cu(owner, where, count) {
- let cu = find_cu(owner, where)
- if (!cu)
- spawn_cu(owner, where, count)
- else
- cu.count += count
+function remove_american_cu(where, count) {
+ set_american_cu(where, count_american_cu(where) - count)
+}
+
+function remove_french_cu(where, count) {
+ set_french_cu(where, count_french_cu(where) - count)
}
function place_british_cu(where, count) {
- place_cu(BRITISH, where, count)
+ set_british_cu(where, count_british_cu(where) + count)
}
function place_american_cu(where, count) {
- place_cu(AMERICAN, where, count)
+ set_american_cu(where, count_american_cu(where) + count)
}
function place_french_cu(where, count) {
- place_cu(FRENCH, where, count)
+ set_french_cu(where, count_french_cu(where) + count)
}
-function move_cu(owner, from, to, count) {
- if (count === 0)
- return
- let from_cu = find_cu(owner, from)
- if (count < from_cu.count) {
- from_cu.count -= count
- place_cu(owner, to, count)
- } else {
- let to_cu = find_cu(owner, to)
- if (to_cu) {
- remove_cu(owner, from, from_cu.count)
- to_cu.count += count
- } else {
- from_cu.location = to
- }
- }
+function move_british_cu(from, to, count) {
+ set_british_cu(from, count_british_cu(from) - count)
+ set_british_cu(to, count_british_cu(to) + count)
}
-function move_british_cu(from, to, count) {
- move_cu(BRITISH, from, to, count)
+function move_american_cu(from, to, count) {
+ set_american_cu(from, count_american_cu(from) - count)
+ set_american_cu(to, count_american_cu(to) + count)
+}
+
+function move_french_cu(from, to, count) {
+ set_french_cu(from, count_french_cu(from) - count)
+ set_french_cu(to, count_french_cu(to) + count)
}
/* GENERALS */
@@ -817,12 +825,11 @@ function place_british_reinforcements(who, count, where) {
if (has_enemy_general(where))
capture_enemy_general(where)
if (game.active === BRITISH && game.congress === where)
- disperse_continental_congress(where)
+ disperse_continental_congress()
}
}
function place_american_reinforcements(who, count, where) {
-console.log("PLACE AM", who, count, where)
let already_there = find_american_or_french_general(where)
if (who !== NOBODY && already_there !== NOBODY) {
// Never replace Washington
@@ -855,8 +862,8 @@ function place_french_reinforcements(who, where) {
move_general(who, where)
}
logp("reinforced " + where + " with the French CU")
- move_cu(FRENCH, FRENCH_REINFORCEMENTS, where, count_french_cu(FRENCH_REINFORCEMENTS))
- move_cu(FRENCH, AMERICAN_REINFORCEMENTS, where, count_french_cu(AMERICAN_REINFORCEMENTS))
+ 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(where) {
@@ -884,55 +891,57 @@ function move_army(who, from, to) {
game.count -= 1
}
if (game.carry_british > 0)
- move_cu(BRITISH, from, to, game.carry_british)
+ move_british_cu(from, to, game.carry_british)
if (game.carry_american > 0)
- move_cu(AMERICAN, from, to, game.carry_american)
+ move_american_cu(from, to, game.carry_american)
if (game.carry_french > 0)
- move_cu(FRENCH, from, to, game.carry_french)
+ move_french_cu(from, to, game.carry_french)
move_general(who, to)
}
function intercept_army(who, from, to) {
if (game.carry_british > 0)
- move_cu(BRITISH, from, to, game.carry_british)
+ move_british_cu(from, to, game.carry_british)
if (game.carry_american > 0)
- move_cu(AMERICAN, from, to, game.carry_american)
+ move_american_cu(from, to, game.carry_american)
if (game.carry_french > 0)
- move_cu(FRENCH, from, to, game.carry_french)
+ move_french_cu(from, to, game.carry_french)
move_general(who, to)
}
function overrun(where) {
logp("overran CU in " + where)
- let cu
- if (game.active === BRITISH)
- cu = find_american_cu(where) || find_french_cu(where)
- else
- cu = find_british_cu(where)
- remove_cu(cu.owner, where, 1)
+ if (game.active === BRITISH) {
+ if (count_american_cu(where) > 0)
+ remove_american_cu(where, 1)
+ else
+ remove_french_cu(where, 1)
+ } else {
+ remove_british_cu(where, 1)
+ }
}
function retreat_american_army(from, to) {
let g = find_american_or_french_general(from)
if (g)
move_general(g, to)
- move_cu(AMERICAN, from, to, count_american_cu(from))
- move_cu(FRENCH, from, to, count_french_cu(from))
+ move_american_cu(from, to, count_american_cu(from))
+ move_french_cu(from, to, count_french_cu(from))
}
function retreat_british_army(from, to) {
let g = find_british_general(from)
if (g)
move_general(g, to)
- move_cu(BRITISH, from, to, count_british_cu(from))
+ move_british_cu(from, to, count_british_cu(from))
}
function surrender_american_army(where) {
let g = find_american_or_french_general(where)
if (g)
capture_american_or_french_general(where)
- remove_cu(AMERICAN, where, count_american_cu(where))
- remove_cu(FRENCH, where, count_french_cu(where))
+ remove_american_cu(where, count_american_cu(where))
+ remove_french_cu(where, count_french_cu(where))
}
function surrender_british_army(where) {
@@ -940,10 +949,10 @@ function surrender_british_army(where) {
if (g)
capture_british_general(where)
game.british_losses += count_british_cu(where)
- remove_cu(BRITISH, where, count_british_cu(where))
+ remove_british_cu(where, count_british_cu(where))
}
-function disperse_continental_congress(where) {
+function disperse_continental_congress() {
log("Contintental Congress dispersed!")
game.congress = CONTINENTAL_CONGRESS_DISPERSED
game.congress_was_dispersed = true
@@ -1066,7 +1075,7 @@ function goto_committees_of_correspondence() {
states.committees_of_correspondence = {
inactive: "Committees of Correspondence",
- prompt(current) {
+ prompt() {
view.prompt =
"Committees of Correspondence: Place 1 PC marker in each of the 13 colonies. " + game.coc.length + " left."
if (game.coc.length > 0)
@@ -1099,7 +1108,7 @@ function goto_for_the_king() {
states.for_the_king = {
inactive: "For the King",
- prompt(current) {
+ prompt() {
view.prompt = "For the King: Place 3 PC markers. " + game.count + " left."
if (game.count > 0)
gen_british_pc_ops()
@@ -1217,7 +1226,7 @@ function goto_start_year() {
}
states.british_declare_first = {
- prompt(current) {
+ prompt() {
view.prompt = "Declare yourself as the first player by playing a campaign card?"
gen_pass()
for (let c of CAMPAIGN_CARDS) {
@@ -1243,16 +1252,16 @@ states.british_declare_first = {
}
states.choose_first_player = {
- prompt(current) {
+ prompt() {
view.prompt = "Choose who will play the first strategy card."
gen_action("american_first")
gen_action("british_first")
},
- american_first(c) {
+ american_first() {
logp("went first")
goto_strategy_phase(AMERICAN)
},
- british_first(c) {
+ british_first() {
logp("went first")
goto_strategy_phase(BRITISH)
},
@@ -1273,7 +1282,7 @@ function goto_strategy_phase(new_active) {
states.strategy_phase = {
inactive: "strategy phase",
- prompt(current) {
+ prompt() {
view.prompt = "Play a strategy card."
gen_strategy_plays(active_hand())
},
@@ -1426,7 +1435,7 @@ function gen_strategy_plays(hand) {
/* DISCARD EVENT CARD FOR PC ACTION */
states.discard_event_pc_action = {
- prompt(current) {
+ prompt() {
view.prompt = "Place, flip, or remove PC marker."
gen_pass()
if (game.active === BRITISH)
@@ -1493,7 +1502,7 @@ function goto_ops_pc(count) {
}
states.ops_pc = {
- prompt(current) {
+ prompt() {
view.prompt = "Place or flip PC markers. " + game.count + " left."
gen_pass()
if (game.count > 0) {
@@ -1548,7 +1557,7 @@ function gen_british_pc_ops() {
}
}
-function gen_british_pc_ops_end(space) {
+function gen_british_pc_ops_end() {
delete game.british_pc_space_list
}
@@ -1580,7 +1589,7 @@ function goto_ops_reinforcements(c) {
}
states.ops_british_reinforcements_who = {
- prompt(current) {
+ prompt() {
view.prompt = "Reinforcements: choose an available general or pass to bring only CU."
view.prompt += " Carrying " + game.count + " British CU."
gen_pass()
@@ -1605,7 +1614,7 @@ states.ops_british_reinforcements_who = {
}
states.ops_british_reinforcements_where = {
- prompt(current) {
+ prompt() {
view.prompt = "Reinforcements: choose a port space."
view.prompt += " Carrying " + game.count + " British CU."
gen_british_reinforcements_where()
@@ -1624,7 +1633,7 @@ states.ops_british_reinforcements_where = {
}
states.ops_american_reinforcements_who = {
- prompt(current) {
+ prompt() {
view.prompt = "Reinforcements: choose an available general or pass to bring only CU."
gen_pass()
gen_american_reinforcements_who()
@@ -1642,7 +1651,7 @@ states.ops_american_reinforcements_who = {
}
states.ops_american_reinforcements_where = {
- prompt(current) {
+ prompt() {
view.prompt = "Reinforcements: choose a space."
gen_american_reinforcements_where(game.who)
},
@@ -1716,7 +1725,7 @@ function goto_ops_general(c) {
}
states.ops_general_who = {
- prompt(current) {
+ prompt() {
if (game.campaign && game.landing_party)
view.prompt = "Campaign: Activate a general or use a landing party. " + game.campaign + " left."
else if (game.campaign)
@@ -1785,7 +1794,7 @@ function goto_remove_general(where) {
}
states.remove_general = {
- prompt(current) {
+ prompt() {
view.prompt = "Remove a general to the reinforcements box."
gen_remove_general()
},
@@ -1803,7 +1812,7 @@ function goto_remove_general_after_intercept() {
}
states.remove_general_after_intercept = {
- prompt(current) {
+ prompt() {
view.prompt = "Remove a general to the reinforcements box."
gen_remove_general()
},
@@ -1822,7 +1831,7 @@ function goto_remove_general_after_retreat(where) {
}
states.remove_general_after_retreat = {
- prompt(current) {
+ prompt() {
view.prompt = "Remove a general to the reinforcements box."
gen_remove_general()
},
@@ -1878,7 +1887,7 @@ function goto_ops_general_move(g, marblehead) {
}
states.ops_general_move = {
- prompt(current) {
+ prompt() {
view.prompt = "Move " + game.who + " with "
if (game.carry_british > 0) {
view.prompt += game.carry_british + " British CU."
@@ -1923,19 +1932,19 @@ states.ops_general_move = {
push_undo()
--game.carry_british
if (has_general_moved(game.who))
- mark_moved_cu(BRITISH, location_of_general(game.who), 1)
+ mark_moved_british_cu(location_of_general(game.who), 1)
},
drop_american_cu() {
push_undo()
--game.carry_american
if (has_general_moved(game.who))
- mark_moved_cu(AMERICAN, location_of_general(game.who), 1)
+ mark_moved_american_cu(location_of_general(game.who), 1)
},
drop_french_cu() {
push_undo()
--game.carry_french
if (has_general_moved(game.who))
- mark_moved_cu(FRENCH, location_of_general(game.who), 1)
+ mark_moved_french_cu(location_of_general(game.who), 1)
},
move(to) {
@@ -1959,7 +1968,7 @@ states.ops_general_move = {
capture_enemy_general(to)
}
if (game.active === BRITISH && game.congress === to && !has_enemy_cu(to)) {
- disperse_continental_congress(to)
+ disperse_continental_congress()
}
if (cu >= 4 && count_enemy_cu(to) === 1 && !has_enemy_general(to)) {
overrun(to)
@@ -2021,7 +2030,7 @@ function goto_intercept(from, where) {
}
states.intercept = {
- prompt(current) {
+ prompt() {
view.prompt = "Intercept " + game.save_who + " in " + game.where + "?"
gen_pass()
gen_intercept()
@@ -2071,9 +2080,9 @@ function end_intercept() {
function end_move() {
let where = location_of_general(game.who)
if (has_general_moved(game.who)) {
- mark_moved_cu(BRITISH, where, game.carry_british)
- mark_moved_cu(AMERICAN, where, game.carry_american)
- mark_moved_cu(FRENCH, where, game.carry_french)
+ mark_moved_british_cu(where, game.carry_british)
+ mark_moved_american_cu(where, game.carry_american)
+ mark_moved_french_cu(where, game.carry_french)
}
game.who = NOBODY
delete game.mobility
@@ -2267,7 +2276,7 @@ events.remove_british_pc_from = function (c, card) {
}
states.remove_british_pc_from = {
- prompt(current) {
+ prompt() {
view.prompt = "Remove British PC markers from " + game.where.join(", ") + ". " + game.count + " left."
gen_pass()
gen_remove_british_pc_from(game.where)
@@ -2292,7 +2301,7 @@ events.remove_american_pc = function (c, card) {
}
states.remove_american_pc = {
- prompt(current) {
+ prompt() {
view.prompt = "Remove American PC markers. " + game.count + " left."
gen_pass()
gen_remove_american_pc()
@@ -2316,7 +2325,7 @@ events.remove_american_pc_from = function (c, card) {
}
states.remove_american_pc_from = {
- prompt(current) {
+ prompt() {
view.prompt = "Remove American PC markers from " + game.where.join(", ") + ". " + game.count + " left."
gen_pass()
gen_remove_american_pc_from(game.where)
@@ -2342,7 +2351,7 @@ events.remove_american_pc_from_non_port = function (c, card) {
}
states.remove_american_pc_from_non_port = {
- prompt(current) {
+ prompt() {
view.prompt =
"Remove American PC markers from non-Port space in " + game.where.join(", ") + ". " + game.count + " left."
gen_pass()
@@ -2368,7 +2377,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(current) {
+ prompt() {
view.prompt = "Remove American PC markers within two spaces of a British general. " + game.count + " left."
gen_pass()
gen_remove_american_pc_within_two_spaces_of_a_british_general()
@@ -2393,7 +2402,7 @@ events.place_american_pc = function (c, card) {
}
states.place_american_pc = {
- prompt(current) {
+ prompt() {
view.prompt = "Place American PC markers. " + game.count + " left."
gen_pass()
gen_place_american_pc()
@@ -2417,7 +2426,7 @@ events.place_american_pc_in = function (c, card) {
}
states.place_american_pc_in = {
- prompt(current) {
+ prompt() {
view.prompt = "Place American PC markers in " + game.where.join(", ") + ". " + game.count + " left."
gen_pass()
gen_place_american_pc_in(game.where)
@@ -2443,7 +2452,7 @@ events.lord_sandwich_coastal_raids = function (c, card) {
}
states.lord_sandwich_coastal_raids = {
- prompt(current) {
+ prompt() {
view.prompt = "Remove two or flip one American PC in a port space."
gen_pass()
gen_lord_sandwich_coastal_raids(game.where)
@@ -2479,14 +2488,16 @@ events.remove_american_cu = function (c, card) {
}
states.remove_american_cu = {
- prompt(current) {
+ prompt() {
view.prompt = "Remove one American CU from any space."
gen_pass()
gen_remove_american_cu()
},
remove_cu(where) {
- let cu = find_american_cu(where) || find_french_cu(where)
- remove_cu(cu.owner, where, 1)
+ if (count_american_cu(where) > 0)
+ remove_american_cu(where, 1)
+ else
+ remove_french_cu(where, 1)
end_strategy_card()
},
pass() {
@@ -2508,14 +2519,13 @@ events.remove_british_cu = function (c, card) {
}
states.remove_british_cu = {
- prompt(current) {
+ prompt() {
view.prompt = "Remove " + game.count + " British CU from any space."
gen_pass()
gen_remove_british_cu()
},
remove_cu(where) {
- let cu = find_british_cu(where)
- remove_cu(cu.owner, where, 1)
+ remove_british_cu(where, 1)
if (--game.count === 0)
end_strategy_card()
},
@@ -2540,14 +2550,16 @@ events.pennsylvania_and_new_jersey_line_mutinies = function (c, card) {
}
states.pennsylvania_and_new_jersey_line_mutinies = {
- prompt(current) {
+ prompt() {
view.prompt = "Remove two American CUs from the map, one each from two different spaces."
gen_pass()
gen_pennsylvania_and_new_jersey_line_mutinies(game.where)
},
remove_cu(where) {
- let cu = find_american_cu(where) || find_french_cu(where)
- remove_cu(cu.owner, where, 1)
+ if (count_american_cu(where) > 0)
+ remove_american_cu(where, 1)
+ else
+ remove_french_cu(where, 1)
game.where = where
if (--game.count === 0)
end_strategy_card()
@@ -2572,7 +2584,7 @@ events.john_glovers_marblehead_regiment = function (c, card) {
}
states.john_glovers_marblehead_regiment_who = {
- prompt(current) {
+ prompt() {
view.prompt = "Activate an American general."
gen_activate_general()
},
@@ -2590,7 +2602,7 @@ events.declaration_of_independence = function (c, card) {
}
states.declaration_of_independence = {
- prompt(current) {
+ prompt() {
view.prompt = "Declaration of Independence: Place 1 PC marker in each of the 13 colonies. "
view.prompt += game.doi.length + " left."
gen_pass()
@@ -2627,7 +2639,7 @@ function goto_george_washington_captured() {
}
states.george_washington_captured = {
- prompt(current) {
+ prompt() {
view.prompt = "George Washington is captured! Remove American PC markers. " + game.count + " left."
gen_pass()
gen_remove_american_pc()
@@ -2694,7 +2706,7 @@ function goto_retreat_before_battle() {
}
states.retreat_before_battle = {
- prompt(current) {
+ prompt() {
view.prompt = "Attempt retreat before battle?"
gen_pass()
gen_defender_retreat()
@@ -2730,7 +2742,7 @@ function goto_remove_general_after_retreat_before_battle(to) {
}
states.remove_general_after_retreat_before_battle = {
- prompt(current) {
+ prompt() {
view.prompt = "Remove a general to the reinforcements box."
gen_remove_general()
},
@@ -2821,7 +2833,7 @@ function goto_play_attacker_battle_card() {
}
states.play_attacker_battle_card = {
- prompt(current) {
+ prompt() {
view.prompt = "Attack: Play or discard event for DRM."
gen_pass()
gen_battle_card()
@@ -2861,7 +2873,7 @@ function goto_play_defender_battle_card() {
}
states.play_defender_battle_card = {
- prompt(current) {
+ prompt() {
view.prompt = "Defend: Play or discard event for DRM."
gen_pass()
gen_battle_card()
@@ -2971,39 +2983,21 @@ function roll_winner_combat_losses(log, losing_general) {
}
function apply_british_combat_losses(max) {
- let cu = find_british_cu(game.where)
- if (cu.count > max) {
- cu.count -= max
- return max
- }
- array_remove_item(game.cu, cu)
- return cu.count
+ let n = Math.min(count_british_cu(game.where), max)
+ remove_british_cu(game.where, n)
+ return n
}
function apply_american_combat_losses(max) {
- let cu = find_american_cu(game.where)
- if (cu) {
- if (cu.count > max) {
- cu.count -= max
- return max
- }
- array_remove_item(game.cu, cu)
- return cu.count
- }
- return 0
+ let n = Math.min(count_american_cu(game.where), max)
+ remove_american_cu(game.where, n)
+ return n
}
function apply_french_combat_losses(max) {
- let cu = find_french_cu(game.where)
- if (cu) {
- if (cu.count > max) {
- cu.count -= max
- return max
- }
- array_remove_item(game.cu, cu)
- return cu.count
- }
- return 0
+ let n = Math.min(count_french_cu(game.where), max)
+ remove_french_cu(game.where, n)
+ return n
}
function apply_american_and_french_combat_losses(max) {
@@ -3159,7 +3153,7 @@ function goto_retreat_after_battle(victor) {
}
states.retreat_after_battle = {
- prompt(current) {
+ prompt() {
view.prompt = "Retreat after battle."
gen_action("surrender")
if (game.active === game.attacker)
@@ -3196,7 +3190,7 @@ function end_battle() {
game.active = game.attacker
if (game.active === BRITISH && game.congress === game.where)
- disperse_continental_congress(game.where)
+ disperse_continental_congress()
if (game.british_losses >= 3)
lose_regular_advantage()
@@ -3276,13 +3270,13 @@ function goto_winter_attrition_phase() {
// TODO: let player choose (but why would he ever choose the french?)
let lose_american = Math.min(half, n_american)
log(owner[0] + " lost " + lose_american + " American CU in " + space)
- remove_cu(AMERICAN, space, n_american)
+ remove_american_cu(space, n_american)
half -= lose_american
n_american -= lose_american
if (half > 0) {
log(owner[0] + " lost " + half + " French CU in " + space)
- remove_cu(FRENCH, space, half)
+ remove_french_cu(space, half)
}
}
}
@@ -3313,7 +3307,7 @@ function gen_place_french_navy() {
}
states.place_french_navy_trigger = {
- prompt(current) {
+ prompt() {
view.prompt = "Place the French Navy in a blockade zone."
gen_place_french_navy()
},
@@ -3327,7 +3321,7 @@ states.place_french_navy_trigger = {
}
states.place_french_navy = {
- prompt(current) {
+ prompt() {
view.prompt = "Place the French Navy in a blockade zone."
gen_place_french_navy()
},
@@ -3497,8 +3491,7 @@ states.european_war = {
gen_remove_british_cu()
},
remove_cu(where) {
- let cu = find_british_cu(where)
- remove_cu(BRITISH, where, 1)
+ remove_british_cu(where, 1)
if (--game.count === 0)
goto_end_phase()
},
@@ -3511,7 +3504,7 @@ function norths_government_falls() {
update_colony_control()
let n_american = 0
- for (let c = 0; c <= 13; ++C)
+ for (let c = 0; c <= 13; ++c)
if (game.control[c] === PC_AMERICAN)
++n_american
@@ -3579,9 +3572,7 @@ exports.action = function (state, current, action, arg) {
return game
}
-function list_actions(current) {
- view.actions = {}
- states[game.state].prompt(current)
+function list_actions() {
}
exports.view = function (state, current) {
@@ -3599,7 +3590,6 @@ exports.view = function (state, current) {
french_navy: state.french_navy,
regulars: state.regulars,
generals: state.generals,
- cu: state.cu,
pc: state.pc,
control: state.control,
a_cards: state.a_hand.length,
@@ -3622,7 +3612,8 @@ exports.view = function (state, current) {
view.hand = []
if (current === state.active) {
- list_actions(current)
+ view.actions = {}
+ states[game.state].prompt()
gen_action_undo()
} else {
let inactive = states[game.state].inactive
@@ -3645,7 +3636,7 @@ function logp(s) {
game.log.push(game.active + " " + s)
}
-function logbr(s) {
+function logbr() {
if (game.log.length > 0 && game.log[game.log.length - 1] !== "")
game.log.push("")
}
@@ -3928,52 +3919,3 @@ function map_delete(map, key) {
}
}
}
-
-function object_diff(a, b) {
- if (a === b)
- return false
- if (a !== null && b !== null && typeof a === "object" && typeof b === "object") {
- if (Array.isArray(a)) {
- if (!Array.isArray(b))
- return true
- let a_length = a.length
- if (b.length !== a_length)
- return true
- for (let i = 0; i < a_length; ++i)
- if (object_diff(a[i], b[i]))
- return true
- return false
- }
- for (let key in a)
- if (object_diff(a[key], b[key]))
- return true
- for (let key in b)
- if (!(key in a))
- return true
- return false
- }
- return true
-}
-
-// same as Object.groupBy
-function object_group_by(items, callback) {
- let groups = {}
- if (typeof callback === "function") {
- for (let item of items) {
- let key = callback(item)
- if (key in groups)
- groups[key].push(item)
- else
- groups[key] = [ item ]
- }
- } else {
- for (let item of items) {
- let key = item[callback]
- if (key in groups)
- groups[key].push(item)
- else
- groups[key] = [ item ]
- }
- }
- return groups
-}