diff options
-rw-r--r-- | play.js | 10 | ||||
-rw-r--r-- | rules.js | 450 |
2 files changed, 203 insertions, 257 deletions
@@ -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) @@ -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 -} |