summaryrefslogtreecommitdiff
path: root/rules.js
diff options
context:
space:
mode:
authorTor Andersson <tor@ccxvii.net>2022-02-23 18:37:20 +0100
committerTor Andersson <tor@ccxvii.net>2023-02-18 11:54:52 +0100
commitb9fc238867b9828e8f93305a55d2a15f668a640c (patch)
tree3c621ff9ee99f091aa910b63289fe6ef40f7d5cd /rules.js
parent5a6ea19ceccb88065f5c5dd0ad10195071333c74 (diff)
downloadwilderness-war-b9fc238867b9828e8f93305a55d2a15f668a640c.tar.gz
Use ranges for tests.
Diffstat (limited to 'rules.js')
-rw-r--r--rules.js1669
1 files changed, 824 insertions, 845 deletions
diff --git a/rules.js b/rules.js
index e6c38ce..9179c98 100644
--- a/rules.js
+++ b/rules.js
@@ -8,20 +8,16 @@
// TODO: remove old 7 command leader(s) immediately as they're drawn, before placing reinforcements
// CLEANUPS
-// TODO: replace piece[p].type lookups with index range checks
// TODO: make 'inside' negative location instead of separate array
-// TODO: abbreviate per-player (game.British.xxx) property name (game.b.xxx)
// TODO: move core of is_friendly/enemy to is_british/french and branch in is_friendly/enemy
-// TODO: for_each_exit -> flat list of all exits
// TODO: use is_enemy_occupied(s) instead of has_unbesieged_enemy_units || has_unbesieged_enemy_fortifications
-// TODO: use game.french.fortresses for victory checks
// TODO: use leader box location for 'pool'
// UI: show discard/removed card list in UI
// UI: show pool leaders in their own box
// UI: show dead leaders as grayed out in own box
// UI: siege marker on top of besieged stack in fortresses
-// TODO: list possible battle response cards
+// TODO: summary of step losses in log (brief/verbose)
// MAJOR
// TODO: find closest path to non-infiltration space for allowing infiltration
@@ -41,52 +37,189 @@ const { spaces, pieces, cards } = require("./data");
const BRITAIN = 'Britain';
const FRANCE = 'France';
-// Order of pieces: br.leaders/br.units/fr.leaders/fr.units
-const last_piece = pieces.length - 1;
-
-let first_british_piece = -1;
-let last_british_leader = -1;
-let last_british_piece = -1;
-let first_french_piece = -1;
-let last_french_leader = -1;
-let last_french_piece = -1;
-
-let british_militia_units = [];
-let french_militia_units = [];
-
-// Figure out piece indices.
-for (let p = 1; p <= last_piece; ++p) {
- if (pieces[p].faction === 'british') {
- if (pieces[p].type === 'militia')
- british_militia_units.push(p);
- if (first_british_piece < 0)
- first_british_piece = p;
- if (pieces[p].type === 'leader')
- last_british_leader = p;
- last_british_piece = p;
- } else {
- if (pieces[p].type === 'militia')
- french_militia_units.push(p);
- if (first_french_piece < 0)
- first_french_piece = p;
- if (pieces[p].type === 'leader')
- last_french_leader = p;
- last_french_piece = p;
- }
-}
+// CARDS
+const first_amphib_card = 17;
+const last_amphib_card = 20;
+const SURRENDER = 6;
+const MASSACRE = 7;
+const COEHORNS = 8;
+const FIELDWORKS_1 = 9;
+const FIELDWORKS_2 = 10;
+const AMBUSH_1 = 11;
+const AMBUSH_2 = 12;
+const BLOCKHOUSES = 13;
+const FOUL_WEATHER = 14;
+const LAKE_SCHOONER = 15;
+const GEORGE_CROGHAN = 16;
+const LOUISBOURG_SQUADRONS = 21;
+const ACADIANS_EXPELLED = 66;
-let first_british_unit = last_british_leader;
-let last_british_unit = last_british_piece;
-let first_french_unit = last_french_leader;
-let last_french_unit = last_french_piece;
+// PIECE RANGES
+const first_piece = 1;
+const last_piece = 151;
+const first_british_piece = 1;
+const last_british_piece = 86;
+const first_british_leader = 1;
+const last_british_leader = 13;
+const first_british_unit = 14;
+const last_british_unit = 86;
+const first_french_piece = 87;
+const last_french_piece = 151;
+const first_french_leader = 87;
+const last_french_leader = 96;
+const first_french_unit = 97;
+const last_french_unit = 151;
+const first_british_militia = 83;
+const last_british_militia = 86;
+const first_french_militia = 148;
+const last_french_militia = 151;
+const first_french_regular = 134;
+const last_french_regular = 147;
+const first_coureurs = 119;
+const last_coureurs = 126;
+const first_british_regular = 56;
+const last_british_regular = 72;
+const first_highland = 77;
+const last_highland = 82;
+const first_royal_american = 73;
+const last_royal_american = 76;
+const first_light_infantry = 26;
+const last_light_infantry = 31;
+const first_southern_provincial = 50;
+const last_southern_provincial = 55;
+const first_northern_provincial = 32;
+const last_northern_provincial = 49;
+const first_ranger = 23;
+const last_ranger = 25;
+const first_cherokee = 14;
+const last_cherokee = 15;
+const first_mohawk = 21;
+const last_mohawk = 22;
+function is_leader(p) { return (p >= 1 && p <= 13) || (p >= 87 && p <= 96); }
+function is_unit(p) { return (p >= 14 && p <= 86) || (p >= 97 && p <= 151); }
+function is_auxiliary(p) { return (p >= 14 && p <= 25) || (p >= 97 && p <= 126); }
+function is_drilled_troops(p) { return (p >= 26 && p <= 82) || (p >= 127 && p <= 147); }
+function is_militia(p) { return (p >= 83 && p <= 86) || (p >= 148 && p <= 151); }
+function is_regular(p) { return (p >= 56 && p <= 82) || (p >= 127 && p <= 147); }
+function is_light_infantry(p) { return (p >= 26 && p <= 31); }
+function is_provincial(p) { return (p >= 32 && p <= 55); }
+function is_southern_provincial(p) { return (p >= 50 && p <= 55); }
+function is_northern_provincial(p) { return (p >= 32 && p <= 49); }
+function is_coureurs(p) { return (p >= 119 && p <= 126); }
+function is_ranger(p) { return (p >= 23 && p <= 25); }
+function is_indian(p) { return (p >= 14 && p <= 22) || (p >= 97 && p <= 118); }
+function is_french_indian(p) { return (p >= 97 && p <= 118); }
+function is_british_indian(p) { return (p >= 14 && p <= 22); }
+function is_blue_indian(p) { return (p >= 101 && p <= 107); }
+function is_orange_indian(p) { return (p >= 113 && p <= 118); }
+function is_blue_orange_indian(p) { return (p >= 97 && p <= 100); }
+function is_gray_indian(p) { return (p >= 16 && p <= 20) || (p >= 108 && p <= 112); }
+function is_cherokee(p) { return (p >= 14 && p <= 15); }
+function is_mohawk(p) { return (p >= 21 && p <= 22); }
+function is_british_iroquois_or_mohawk(p) { return (p >= 16 && p <= 22); }
+const AMHERST = 1;
+const BRADDOCK = 2;
+const ABERCROMBY = 3;
+const LOUDOUN = 4;
+const WOLFE = 5;
+const FORBES = 6;
+const SHIRLEY = 7;
+const MURRAY = 8;
+const MONCKTON = 9;
+const WEBB = 10;
+const BRADSTREET = 11;
+const DUNBAR = 12;
+const JOHNSON = 13;
+const MONTCALM = 87;
+const DIESKAU = 88;
+const LEVIS = 89;
+const VAUDREUIL = 90;
+const DRUCOUR = 91;
+const RIGAUD = 92;
+const VILLIERS = 93;
+const BOUGAINVILLE = 94;
+const BEAUJEU = 95;
+const DUMAS = 96;
+
+// SPACE RANGES
+const first_space = 1;
+const last_space = 141;
+const first_leader_box = 145;
+const last_leader_box = 167;
+const first_northern_department = 1;
+const last_northern_department = 21;
+const first_southern_department = 22;
+const last_southern_department = 40;
+const first_st_lawrence_department = 41;
+const last_st_lawrence_department = 52;
+function is_leader_box(s) { return (s >= 145 && s <= 167); }
+function is_fortress(s) { return (s >= 1 && s <= 4) || (s >= 22 && s <= 24) || (s >= 41 && s <= 42) || (s >= 139 && s <= 140); }
+function is_port(s) { return (s >= 1 && s <= 3) || (s >= 22 && s <= 24) || (s === 41) || (s >= 139 && s <= 140); }
+function is_st_lawrence_department(s) { return (s >= 41 && s <= 52); }
+function is_southern_department(s) { return (s >= 22 && s <= 40); }
+function is_northern_department(s) { return (s >= 1 && s <= 21); }
+function is_originally_french(s) { return (s >= 41 && s <= 52) || (s === 140); }
+function is_originally_british(s) { return (s >= 1 && s <= 40) || (s === 139); }
+function is_wilderness_or_mountain(s) { return (s >= 53 && s <= 138); }
+function is_wilderness(s) { return (s >= 53 && s <= 119); }
+function is_mountain(s) { return (s >= 120 && s <= 138); }
+function is_cultivated(s) { return (s >= 1 && s <= 52); }
+const ALBANY = 4;
+const ALEXANDRIA = 22;
+const BAIE_ST_PAUL = 43;
+const BALTIMORE = 23;
+const BOSTON = 1;
+const CANAJOHARIE = 56;
+const CAYUGA = 60;
+const HALIFAX = 139;
+const KAHNAWAKE = 45;
+const KARAGHIYADIRHA = 76;
+const KITTANING = 77;
+const LAC_DES_DEUX_MONTAGNES = 46;
+const LOGSTOWN = 81;
+const LOUISBOURG = 140;
+const MINGO_TOWN = 83;
+const MISSISSAUGA = 84;
+const MONTREAL = 42;
+const NEW_HAVEN = 2;
+const NEW_YORK = 3;
+const NIAGARA = 86;
+const OHIO_FORKS = 88;
+const ONEIDA_CARRY_EAST = 89;
+const ONEIDA_CARRY_WEST = 90;
+const ONEIDA_CASTLE = 91;
+const ONONDAGA = 92;
+const OSWEGO = 96;
+const PAYS_D_EN_HAUT = 141;
+const PHILADELPHIA = 24;
+const QUEBEC = 41;
+const RIVIERE_OUELLE = 47;
+const SHAWIANGTO = 102;
+const ST_FRANCOIS = 49;
+const ILE_D_ORLEANS = 52;
+const NORTHERN_COLONIAL_MILITIAS = 142;
+const SOUTHERN_COLONIAL_MILITIAS = 143;
+const ST_LAWRENCE_CANADIAN_MILITIAS = 144;
// Patch up leader/box associations.
-for (let s = 1; s < spaces.length; ++s) {
- if (spaces[s].type === 'leader-box') {
- let p = find_leader(spaces[s].name);
- spaces[s].leader = p;
- pieces[p].box = s;
- }
+const box_from_leader = [];
+const leader_from_box = [];
+for (let p = 0; p <= last_french_leader; ++p)
+ box_from_leader[p] = 0;
+for (let s = first_leader_box; s <= last_leader_box; ++s) {
+ let p = pieces.findIndex(piece => piece.name === spaces[s].name);
+ box_from_leader[p] = s;
+ leader_from_box[s-first_leader_box] = p;
+}
+
+// Patch up space exits.
+for (let s = first_space; s <= last_space; ++s) {
+ let ss = spaces[s];
+ ss.exits = ss.land.concat(ss.river).concat(ss.lakeshore);
+ ss.exits_with_type = [];
+ ss.land.forEach(n => ss.exits_with_type.push([n,'land']));
+ ss.river.forEach(n => ss.exits_with_type.push([n,'river']));
+ ss.lakeshore.forEach(n => ss.exits_with_type.push([n,'lakeshore']));
}
let game;
@@ -102,12 +235,12 @@ let supply_cache; // cleared when setting active player and loading game state
let first_enemy_leader;
let first_enemy_piece;
let first_enemy_unit;
-let first_friendly_leader;
-let first_friendly_piece;
-let first_friendly_unit;
let last_enemy_leader;
let last_enemy_piece;
let last_enemy_unit;
+let first_friendly_leader;
+let first_friendly_piece;
+let first_friendly_unit;
let last_friendly_leader;
let last_friendly_piece;
let last_friendly_unit;
@@ -145,7 +278,6 @@ function remove_from_array(array, item) {
function log(...args) {
let s = Array.from(args).join(" ");
- console.log("LOG", s);
game.log.push(s);
}
@@ -168,28 +300,39 @@ function update_active_aliases() {
if (game.active === BRITAIN) {
player = game.british;
enemy_player = game.french;
- first_enemy_piece = first_french_piece;
- last_enemy_leader = last_french_leader;
- last_enemy_piece = last_french_piece;
+
first_friendly_piece = first_british_piece;
- last_friendly_leader = last_british_leader;
last_friendly_piece = last_british_piece;
+ first_friendly_leader = first_british_leader;
+ last_friendly_leader = last_british_leader;
+ first_friendly_unit = first_british_unit;
+ last_friendly_unit = last_british_unit;
+
+ first_enemy_piece = first_french_piece;
+ last_enemy_piece = last_french_piece;
+ first_enemy_leader = first_french_leader;
+ last_enemy_leader = last_french_leader;
+ first_enemy_unit = first_french_unit;
+ last_enemy_unit = last_french_unit;
+
} else {
player = game.french;
enemy_player = game.british;
- first_enemy_piece = first_british_piece;
- last_enemy_leader = last_british_leader;
- last_enemy_piece = last_british_piece;
+
first_friendly_piece = first_french_piece;
- last_friendly_leader = last_french_leader;
last_friendly_piece = last_french_piece;
+ first_friendly_leader = first_french_leader;
+ last_friendly_leader = last_french_leader;
+ first_friendly_unit = first_french_unit;
+ last_friendly_unit = last_french_unit;
+
+ first_enemy_piece = first_british_piece;
+ last_enemy_piece = last_british_piece;
+ first_enemy_leader = first_british_leader;
+ last_enemy_leader = last_british_leader;
+ first_enemy_unit = first_british_unit;
+ last_enemy_unit = last_british_unit;
}
- first_enemy_leader = first_enemy_piece;
- first_friendly_leader = first_friendly_piece;
- first_enemy_unit = last_enemy_leader + 1;
- first_friendly_unit = last_friendly_leader + 1;
- last_enemy_unit = last_enemy_piece;
- last_friendly_unit = last_friendly_piece;
}
// LISTS
@@ -210,244 +353,204 @@ function find_space(name) {
return ix;
}
-function find_leader(name) {
- let ix = pieces.findIndex(piece => piece.name === name);
- if (ix < 0)
- throw new Error("cannot find leader " + name);
- return ix;
-}
-
-function find_unused_unit(name) {
+function find_unused_piece(name) {
for (let i = 0; i <= last_piece; ++i)
if (pieces[i].name === name && game.location[i] === 0)
return i;
throw new Error("cannot find unit " + name);
}
+function find_unused_provincial(dept) {
+ if (dept === 'northern') {
+ for (let p = first_northern_provincial; p <= last_northern_provincial; ++p)
+ if (is_piece_unused(p))
+ return p;
+ } else {
+ for (let p = first_southern_provincial; p <= last_southern_provincial; ++p)
+ if (is_piece_unused(p))
+ return p;
+ }
+ return 0;
+}
+
+function find_unused_friendly_militia() {
+ if (game.active === FRANCE) {
+ for (let p = first_french_militia; p <= last_french_militia; ++p)
+ if (is_piece_unused(p))
+ return p;
+ } else {
+ for (let p = first_british_militia; p <= last_british_militia; ++p)
+ if (is_piece_unused(p))
+ return p;
+ }
+ return 0;
+}
+
+function find_unused_coureurs() {
+ for (let p = first_french_unit; p <= last_french_unit; ++p)
+ if (is_coureurs(p) && is_piece_unused(p))
+ return p;
+ return 0;
+}
+
+function find_unused_ranger() {
+ for (let p = first_friendly_unit; p <= last_friendly_unit; ++p)
+ if (is_ranger(p) && is_piece_unused(p))
+ return p;
+ return 0;
+}
+
+function find_unused_british_regular() {
+ for (let p = first_british_regular; p <= last_british_regular; ++p)
+ if (is_piece_unused(p))
+ return p;
+ return 0;
+}
+
+function find_unused_french_regular() {
+ for (let p = first_french_regular; p <= last_french_regular; ++p)
+ if (is_piece_unused(p))
+ return p;
+ return 0;
+}
+
+function find_unused_highland() {
+ for (let p = first_highland; p <= last_highland; ++p)
+ if (is_piece_unused(p))
+ return p;
+ return 0;
+}
+
+function find_unused_royal_american() {
+ for (let p = first_royal_american; p <= last_royal_american; ++p)
+ if (is_piece_unused(p))
+ return p;
+ return 0;
+}
+
+function find_unused_light_infantry() {
+ for (let p = first_light_infantry; p <= last_light_infantry; ++p)
+ if (is_piece_unused(p))
+ return p;
+ return 0;
+}
+
const ports = [
- "Alexandria",
- "Baltimore",
- "Boston",
- "Halifax",
- "Louisbourg",
- "New Haven",
- "New York",
- "Philadelphia",
- "Québec",
-].map(name => spaces.findIndex(space => space.name === name));
-
-const all_fortresses = [
- "Albany",
- "Alexandria",
- "Baltimore",
- "Boston",
- "Halifax",
- "Louisbourg",
- "Montréal",
- "New Haven",
- "New York",
- "Philadelphia",
- "Québec",
-].map(name => spaces.findIndex(space => space.name === name));
+ ALEXANDRIA,
+ BALTIMORE,
+ BOSTON,
+ HALIFAX,
+ LOUISBOURG,
+ NEW_HAVEN,
+ NEW_YORK,
+ PHILADELPHIA,
+ QUEBEC,
+]
+
+const fortresses = [
+ ALBANY,
+ ALEXANDRIA,
+ BALTIMORE,
+ BOSTON,
+ HALIFAX,
+ LOUISBOURG,
+ MONTREAL,
+ NEW_HAVEN,
+ NEW_YORK,
+ PHILADELPHIA,
+ QUEBEC,
+]
const originally_french_fortresses = [
- "Louisbourg",
- "Montréal",
- "Québec",
-].map(name => spaces.findIndex(space => space.name === name));
+ LOUISBOURG,
+ MONTREAL,
+ QUEBEC,
+];
const originally_british_fortresses = [
- "Albany",
- "Alexandria",
- "Baltimore",
- "Boston",
- "Halifax",
- "New Haven",
- "New York",
- "Philadelphia",
-].map(name => spaces.findIndex(space => space.name === name));
+ ALBANY,
+ ALEXANDRIA,
+ BALTIMORE,
+ BOSTON,
+ HALIFAX,
+ NEW_HAVEN,
+ NEW_YORK,
+ PHILADELPHIA,
+];
const originally_british_fortresses_and_all_ports = [
- "Albany",
- "Alexandria",
- "Baltimore",
- "Boston",
- "Halifax",
- "Louisbourg",
- "New Haven",
- "New York",
- "Philadelphia",
- "Québec",
-].map(name => spaces.findIndex(space => space.name === name));
-
-
-const departments = {
- st_lawrence: [
- "Baie-St-Paul",
- "Bécancour",
- "Kahnawake",
- "Lac des Deux Montagnes",
- "Montréal",
- "Québec",
- "Rivière-Ouelle",
- "Sorel",
- "St-François",
- "St-Jean",
- "Trois-Rivières",
- "Île d'Orléans",
- ].map(name => spaces.findIndex(space => space.name === name)),
- northern: [
- "Albany",
- "Boston",
- "Burlington",
- "Charlestown",
- "Concord",
- "Deerfield",
- "Gloucester",
- "Hartford",
- "Hoosic",
- "Kinderhook",
- "Manchester",
- "New Haven",
- "New York",
- "Northampton",
- "Peekskill",
- "Portsmouth",
- "Poughkeepsie",
- "Providence",
- "Schenectady",
- "Trenton",
- "Worcester",
- ].map(name => spaces.findIndex(space => space.name === name)),
- southern: [
- "Alexandria",
- "Ashby's Gap",
- "Augusta",
- "Baltimore",
- "Carlisle",
- "Culpeper",
- "Easton",
- "Frederick",
- "Harris's Ferry",
- "Head of Elk",
- "Lancaster",
- "New Castle",
- "Philadelphia",
- "Reading",
- "Shepherd's Ferry",
- "Winchester",
- "Woodstock",
- "Wright's Ferry",
- "York",
- ].map(name => spaces.findIndex(space => space.name === name)),
+ ALBANY,
+ ALEXANDRIA,
+ BALTIMORE,
+ BOSTON,
+ HALIFAX,
+ LOUISBOURG,
+ NEW_HAVEN,
+ NEW_YORK,
+ PHILADELPHIA,
+ QUEBEC,
+];
+
+function is_friendly_indian(p) {
+ if (game.active === FRANCE)
+ return is_french_indian(p);
+ return is_british_indian(p);
}
-const indian_spaces = {
- "blue-orange": [
- find_space("Pays d'en Haut")
- ],
- blue: [
- "Kahnawake",
- "Lac des Deux Montagnes",
- "Mississauga",
- "St-François",
- ].map(name => spaces.findIndex(space => space.name === name)),
- orange: [
- "Kittaning",
- "Logstown",
- "Mingo Town",
- ].map(name => spaces.findIndex(space => space.name === name)),
- mohawks: [
- "Canajoharie",
- ].map(name => spaces.findIndex(space => space.name === name)),
- gray: [
- "Cayuga",
- "Karaghiyadirha",
- "Oneida Castle",
- "Onondaga",
- "Shawiangto",
- ].map(name => spaces.findIndex(space => space.name === name)),
-}
-
-const indian_tribe = {};
-
-function define_indian_settlement(space_name, tribe) {
- let space = find_space(space_name);
- if (space_name !== "Pays d'en Haut")
- indian_tribe[space] = tribe;
- for (let p = 1; p <= last_piece; ++p)
- if (pieces[p].name === tribe)
- pieces[p].settlement = space;
-}
-
-define_indian_settlement("Kahnawake", "Caughnawaga");
-define_indian_settlement("Lac des Deux Montagnes", "Algonquin");
-define_indian_settlement("Mississauga", "Mississauga");
-define_indian_settlement("St-François", "Abenaki");
-
-define_indian_settlement("Mingo Town", "Mingo");
-define_indian_settlement("Logstown", "Shawnee");
-define_indian_settlement("Kittaning", "Delaware");
-
-define_indian_settlement("Canajoharie", "Mohawk");
-
-define_indian_settlement("Cayuga", "Cayuga");
-define_indian_settlement("Karaghiyadirha", "Seneca");
-define_indian_settlement("Oneida Castle", "Oneida");
-define_indian_settlement("Onondaga", "Onondaga");
-define_indian_settlement("Shawiangto", "Tuscarora");
-
-define_indian_settlement("Pays d'en Haut", "Ojibwa");
-define_indian_settlement("Pays d'en Haut", "Ottawa");
-define_indian_settlement("Pays d'en Haut", "Potawatomi");
-define_indian_settlement("Pays d'en Haut", "Huron");
-
-const JOHNSON = find_leader("Johnson");
-const ABERCROMBY = find_leader("Abercromby");
-const AMHERST = find_leader("Amherst");
-const FORBES = find_leader("Forbes");
-const WOLFE = find_leader("Wolfe");
-const BRADDOCK = find_leader("Braddock");
-const LOUDOUN = find_leader("Loudoun");
-const MONTCALM = find_leader("Montcalm");
-const LEVIS = find_leader("Lévis");
-const BOUGAINVILLE = find_leader("Bougainville");
-const SHIRLEY = find_leader("Shirley");
-
-const HALIFAX = find_space("Halifax");
-const LOUISBOURG = find_space("Louisbourg");
-const BAIE_ST_PAUL = find_space("Baie-St-Paul");
-const RIVIERE_OUELLE = find_space("Rivière-Ouelle");
-const ILE_D_ORLEANS = find_space("Île d'Orléans");
-const QUEBEC = find_space("Québec");
-const MONTREAL = find_space("Montréal");
-const OHIO_FORKS = find_space("Ohio Forks");
-const CANAJOHARIE = find_space("Canajoharie");
-const NIAGARA = find_space("Niagara");
-const OSWEGO = find_space("Oswego");
-const ONEIDA_CARRY_WEST = find_space("Oneida Carry West");
-const ONEIDA_CARRY_EAST = find_space("Oneida Carry East");
-const PAYS_D_EN_HAUT = find_space("Pays d'en Haut");
-
-const ST_LAWRENCE_CANADIAN_MILITIAS = find_space("St. Lawrence Canadian Militias");
-const NORTHERN_COLONIAL_MILITIAS = find_space("Northern Colonial Militias");
-const SOUTHERN_COLONIAL_MILITIAS = find_space("Southern Colonial Militias");
+const indians = {
+ spaces_from_color: {},
+ pieces_from_color: {},
+ pieces_from_space: {},
+ space_from_piece: {},
+ tribe_from_space: {},
+};
-const SURRENDER = 6;
-const MASSACRE = 7;
-const COEHORNS = 8;
-const FIELDWORKS_1 = 9;
-const FIELDWORKS_2 = 10;
-const AMBUSH_1 = 11;
-const AMBUSH_2 = 12;
-const BLOCKHOUSES = 13;
-const FOUL_WEATHER = 14;
-const LAKE_SCHOONER = 15;
-const GEORGE_CROGHAN = 16;
-const first_amphib_card = 17;
-const last_amphib_card = 20;
-const LOUISBOURG_SQUADRONS = 21;
-const ACADIANS_EXPELLED = 66;
+function define_indian(color, space, tribe) {
+ if (!indians.pieces_from_color[color])
+ indians.pieces_from_color[color] = [];
+ if (!indians.spaces_from_color[color])
+ indians.spaces_from_color[color] = [];
+ if (space) {
+ if (!indians.spaces_from_color[color].includes(space))
+ indians.spaces_from_color[color].push(space);
+ }
+ if (!indians.pieces_from_space[space])
+ indians.pieces_from_space[space] = [];
+ if (space === PAYS_D_EN_HAUT)
+ indians.tribe_from_space[space] = "Pays d'en Haut";
+ else
+ indians.tribe_from_space[space] = tribe;
+ for (let p = 1; p <= last_piece; ++p) {
+ if (is_indian(p) && pieces[p].name === tribe) {
+ indians.pieces_from_color[color].push(p);
+ indians.pieces_from_space[space].push(p);
+ indians.space_from_piece[p] = space;
+ }
+ }
+}
+
+define_indian("cherokee", 0, "Cherokee");
+define_indian("mohawk", CANAJOHARIE, "Mohawk");
+
+define_indian("blue", ST_FRANCOIS, "Abenaki");
+define_indian("blue", LAC_DES_DEUX_MONTAGNES, "Algonquin");
+define_indian("blue", KAHNAWAKE, "Caughnawaga");
+define_indian("blue", MISSISSAUGA, "Mississauga");
+
+define_indian("orange", KITTANING, "Delaware");
+define_indian("orange", MINGO_TOWN, "Mingo");
+define_indian("orange", LOGSTOWN, "Shawnee");
+
+define_indian("blue-orange", PAYS_D_EN_HAUT, "Huron");
+define_indian("blue-orange", PAYS_D_EN_HAUT, "Ojibwa");
+define_indian("blue-orange", PAYS_D_EN_HAUT, "Ottawa");
+define_indian("blue-orange", PAYS_D_EN_HAUT, "Potawatomi");
+
+define_indian("gray", CAYUGA, "Cayuga");
+define_indian("gray", ONEIDA_CASTLE, "Oneida");
+define_indian("gray", ONONDAGA, "Onondaga");
+define_indian("gray", KARAGHIYADIRHA, "Seneca");
+define_indian("gray", SHAWIANGTO, "Tuscarora");
const within_two_of_canajoharie = [ CANAJOHARIE ];
for_each_exit(CANAJOHARIE, one => {
@@ -462,10 +565,10 @@ for_each_exit(CANAJOHARIE, one => {
});
const within_two_of_gray_settlement = [];
-indian_spaces.gray.forEach(zero => {
+indians.spaces_from_color.gray.forEach(zero => {
within_two_of_gray_settlement.push(zero);
});
-indian_spaces.gray.forEach(zero => {
+indians.spaces_from_color.gray.forEach(zero => {
for_each_exit(zero, one => {
if (!within_two_of_gray_settlement.includes(one)) {
within_two_of_gray_settlement.push(one);
@@ -483,28 +586,6 @@ for_each_exit(OHIO_FORKS, one => {
in_or_adjacent_to_ohio_forks.push(one);
});
-function has_amphibious_arrow(s) {
- return s === HALIFAX || s === LOUISBOURG;
-}
-
-// Map spaces except militia boxes and leader boxes.
-const first_space = 1;
-const last_space = NORTHERN_COLONIAL_MILITIAS-1;
-
-const british_iroquois_or_mohawk_names = [
- "Seneca", "Cayuga", "Onondaga", "Tuscarora", "Oneida", "Mohawk"
-];
-
-const british_iroquois_or_mohawk_units = [];
-for (let i = 1; i <= last_piece; ++i) {
- let piece = pieces[i];
- if (piece.faction === 'british' && piece.type === 'indian' && british_iroquois_or_mohawk_names.includes(piece.name))
- british_iroquois_or_mohawk_units.push(i);
-}
-
-const originally_friendly_french_spaces = departments.st_lawrence.concat([LOUISBOURG]);
-const originally_friendly_british_spaces = departments.northern.concat(departments.southern).concat([HALIFAX]);
-
// CARD DECK
function reshuffle_deck() {
@@ -570,7 +651,6 @@ function draw_leader_from_pool() {
}
game.british.pool.splice(i, 1);
- move_piece_to(p, leader_box(p)); // TODO: yes/no show drawn leader here?
return p;
}
return 0;
@@ -588,12 +668,18 @@ function is_friendly_card_available(c) {
return player.hand.length > 0 && is_card_available(c);
}
+function get_player_hand(role) {
+ if (role === FRANCE)
+ return game.french.hand;
+ return game.british.hand;
+}
+
function is_card_available_for_attacker(c) {
- return game[game.battle.attacker].hand.length > 0 && is_card_available(c);
+ return get_player_hand(game.battle.attacker).length > 0 && is_card_available(c);
}
function is_card_available_for_defender(c) {
- return game[game.battle.defender].hand.length > 0 && is_card_available(c);
+ return get_player_hand(game.battle.defender).length > 0 && is_card_available(c);
}
// ITERATORS
@@ -603,14 +689,14 @@ function for_each_siege(fn) {
fn(sid|0, game.sieges[sid]);
}
+function for_each_exit_with_type(s, fn) {
+ for (let [n, t] of spaces[s].exits_with_type)
+ fn(n, t);
+}
+
function for_each_exit(s, fn) {
- let { land, river, lakeshore } = spaces[s];
- for (let i = 0; i < land.length; ++i)
- fn(land[i], 'land');
- for (let i = 0; i < river.length; ++i)
- fn(river[i], 'river');
- for (let i = 0; i < lakeshore.length; ++i)
- fn(lakeshore[i], 'lakeshore');
+ for (let n of spaces[s].exits)
+ fn(n);
}
function for_each_friendly_piece_in_node(node, fn) {
@@ -696,7 +782,7 @@ function for_each_british_controlled_port_and_amphib(fn) {
function list_auxiliary_units_in_force(force) {
let list = [];
for_each_unit_in_force(force, p => {
- if (is_auxiliary_unit(p))
+ if (is_auxiliary(p))
list.push(p);
});
return list;
@@ -705,11 +791,11 @@ function list_auxiliary_units_in_force(force) {
// STATIC PROPERTIES
function department_militia(s) {
- if (departments.st_lawrence.includes(s))
+ if (is_st_lawrence_department(s))
return ST_LAWRENCE_CANADIAN_MILITIAS;
- if (departments.northern.includes(s))
+ if (is_northern_department(s))
return NORTHERN_COLONIAL_MILITIAS;
- if (departments.southern.includes(s))
+ if (is_southern_department(s))
return SOUTHERN_COLONIAL_MILITIAS;
return 0;
}
@@ -726,148 +812,20 @@ function is_lake_connection(from, to) {
return false;
}
-function is_wilderness_or_mountain(s) {
- let type = spaces[s].type;
- return type === 'wilderness' || type === 'mountain';
-}
-
-function is_wilderness(s) {
- return spaces[s].type === 'wilderness';
-}
-
-function is_mountain(s) {
- return spaces[s].type === 'mountain';
-}
-
-function is_cultivated(s) {
- return spaces[s].type === 'cultivated';
-}
-
-function is_militia_box(s) {
- return spaces[s].type === 'militia-box';
-}
-
-function is_leader_box(s) {
- return spaces[s].type === 'leader-box';
+function has_amphibious_arrow(s) {
+ return s === HALIFAX || s === LOUISBOURG;
}
function is_originally_friendly(s) {
if (game.active === FRANCE)
- return originally_friendly_french_spaces.includes(s);
- return originally_friendly_british_spaces.includes(s);
+ return is_originally_french(s);
+ return is_originally_british(s);
}
function is_originally_enemy(s) {
if (game.active === BRITAIN)
- return originally_friendly_french_spaces.includes(s);
- return originally_friendly_british_spaces.includes(s);
-}
-
-function is_fortress(s) {
- return all_fortresses.includes(s);
-}
-
-function is_leader(p) {
- return pieces[p].type === 'leader';
-}
-
-function is_unit(p) {
- return pieces[p].type !== 'leader';
-}
-
-function is_british_iroquois_or_mohawk(p) {
- return british_iroquois_or_mohawk_units.includes(p);
-}
-
-function is_provincial_unit(p) {
- switch (pieces[p].type) {
- case 'northern provincial': return true;
- case 'southern provincial': return true;
- }
- return false;
-}
-
-function is_provincial_unit_from(p, type) {
- switch (pieces[p].type) {
- case 'northern provincial': return type === 'northern';
- case 'southern provincial': return type === 'southern';
- }
- return false;
-}
-
-function is_drilled_troops(p) {
- switch (pieces[p].type) {
- case 'regular': return true;
- case 'marine detachment': return true;
- case 'royal': return true;
- case 'highland': return true;
- case 'light infantry': return true;
- case 'northern provincial': return true;
- case 'southern provincial': return true;
- }
- return false;
-}
-
-function is_militia_unit(p) {
- return pieces[p].type === 'militia';
-}
-
-function is_light_infantry_unit(p) {
- return pieces[p].type === 'light infantry';
-}
-
-function is_indian_unit(p) {
- return pieces[p].type === 'indian';
-}
-
-function is_indian_tribe(p, tribe) {
- return pieces[p].type === 'indian' && pieces[p].name === tribe;
-}
-
-function indian_home_settlement(p) {
- return pieces[p].settlement || 0;
-}
-
-function is_regular_unit(p) {
- let type = pieces[p].type;
- return type === 'regular' || type === 'marine detachment' || type === 'highland' || type === 'royal';
-}
-
-function is_highland_unit(p) {
- return pieces[p].type === 'highland';
-}
-
-function is_royal_american_unit(p) {
- return pieces[p].type === 'royal';
-}
-
-function is_34_regular_unit(p) {
- return pieces[p].type === 'regular';
-}
-
-function is_western_indian_unit(p) {
- return pieces[p].type === 'indian' && pieces[p].subtype === 'orange';
-}
-
-function is_pays_d_en_haut_indian_unit(p) {
- return pieces[p].type === 'indian' && pieces[p].subtype === 'blue-orange';
-}
-
-function is_ranger_unit(p) {
- return pieces[p].type === 'ranger';
-}
-
-function is_coureurs_unit(p) {
- return pieces[p].type === 'coureurs';
-}
-
-function is_auxiliary_unit(p) {
- switch (pieces[p].type) {
- case 'indian': return true;
- case 'coureurs': return true;
- case 'ranger': return true;
- }
- return false;
+ return is_originally_french(s);
+ return is_originally_british(s);
}
function piece_name(p) {
@@ -884,12 +842,8 @@ function piece_movement(p) {
return pieces[p].movement;
}
-function leader_box_leader(s) {
- return spaces[s].leader;
-}
-
function leader_box(p) {
- return pieces[p].box;
+ return box_from_leader[p];
}
function leader_initiative(p) {
@@ -919,9 +873,9 @@ function piece_node(p) {
}
function piece_space(p) {
- let where = piece_node(p);
+ let where = game.location[p];
if (is_leader_box(where))
- return piece_node(leader_box_leader(where));
+ return game.location[leader_from_box[where-first_leader_box]];
return where;
}
@@ -1017,11 +971,11 @@ function set_piece_outside(p) {
}
function is_piece_on_map(p) {
- return piece_node(p) !== 0;
+ return game.location[p] !== 0;
}
function is_piece_unused(p) {
- return piece_node(p) === 0;
+ return game.location[p] === 0;
}
function is_piece_in_node(p, node) {
@@ -1049,13 +1003,13 @@ function has_fieldworks(s) {
}
function place_fieldworks(s) {
- log(`Fieldworks placed at ${space_name(s)}.`);
+ log(`Placed fieldworks at ${space_name(s)}.`);
game.fieldworks.push(s);
}
function remove_fieldworks(s) {
if (game.fieldworks.includes(s)) {
- log(`Fieldworks removed at ${space_name(s)}.`);
+ log(`Removed fieldworks at ${space_name(s)}.`);
remove_from_array(game.fieldworks, s);
}
}
@@ -1314,7 +1268,7 @@ function has_friendly_drilled_troops(s) {
function has_friendly_regulars(s) {
for (let p = first_friendly_unit; p <= last_friendly_unit; ++p)
- if (is_regular_unit(p) && is_piece_in_space(p, s))
+ if (is_regular(p) && is_piece_in_space(p, s))
return true;
return false;
}
@@ -1322,21 +1276,21 @@ function has_friendly_regulars(s) {
function has_friendly_rangers(s) {
if (game.active === BRITAIN)
for (let p = first_british_unit; p <= last_british_unit; ++p)
- if (is_ranger_unit(p) && is_piece_in_space(p, s))
+ if (is_ranger(p) && is_piece_in_space(p, s))
return true;
return false;
}
function has_friendly_indians(s) {
for (let p = first_friendly_unit; p <= last_friendly_unit; ++p)
- if (is_indian_unit(p) && is_piece_in_space(p, s))
+ if (is_indian(p) && is_piece_in_space(p, s))
return true;
return false;
}
function has_unbesieged_enemy_auxiliary(s) {
for (let p = first_enemy_unit; p <= last_enemy_unit; ++p)
- if (is_auxiliary_unit(p) && is_piece_in_space(p, s) && !is_piece_inside(p))
+ if (is_auxiliary(p) && is_piece_in_space(p, s) && !is_piece_inside(p))
return true;
return false;
}
@@ -1379,10 +1333,17 @@ function has_besieged_friendly_units(s) {
}
function count_militia_in_department(box) {
- let list = (box === ST_LAWRENCE_CANADIAN_MILITIAS ? french_militia_units : british_militia_units);
- for (let i = 0; i < list.length; ++i)
- if (piece_node(list[i]) === box)
- return true;
+ if (box === ST_LAWRENCE_CANADIAN_MILITIAS) {
+ for (let p = first_french_militia; p <= last_french_militia; ++p) {
+ if (piece_node(p) === box)
+ return true;
+ }
+ } else {
+ for (let p = first_british_militia; p <= last_british_militia; ++p) {
+ if (piece_node(p) === box)
+ return true;
+ }
+ }
return false;
}
@@ -1408,14 +1369,14 @@ function is_lone_auxiliary(who) {
let only_ax = true;
let ax_count = 0;
for_each_unit_in_force(who, p => {
- if (is_auxiliary_unit(p))
+ if (is_auxiliary(p))
++ax_count;
else
only_ax = false;
});
return only_ax && ax_count === 1;
}
- return is_auxiliary_unit(who);
+ return is_auxiliary(who);
}
function force_has_drilled_troops(who) {
@@ -1436,28 +1397,28 @@ function force_has_supplied_drilled_troops(who) {
return false;
}
-function force_has_auxiliary_unit(who) {
+function force_has_auxiliary(who) {
if (is_leader(who)) {
let has_ax = false;
for_each_unit_in_force(who, p => {
- if (is_auxiliary_unit(p))
+ if (is_auxiliary(p))
has_ax = true;
});
return has_ax;
}
- return is_auxiliary_unit(who);
+ return is_auxiliary(who);
}
function force_has_only_auxiliary_units(who) {
if (is_leader(who)) {
let only_ax = true;
for_each_unit_in_force(who, p => {
- if (!is_auxiliary_unit(p))
+ if (!is_auxiliary(p))
only_ax = false;
});
return only_ax;
}
- return is_auxiliary_unit(who);
+ return is_auxiliary(who);
}
function is_raid_space(s) {
@@ -1607,31 +1568,33 @@ function restore_unit(p) {
set_unit_reduced(p, 0);
}
-function reduce_unit(p) {
+function reduce_unit(p, verbose=true) {
if (is_unit_reduced(p)) {
- eliminate_piece(p);
+ eliminate_piece(p, verbose);
return true;
}
set_unit_reduced(p, 1);
- log(`Reduced ${piece_name_and_place(p)}.`);
+ if (verbose)
+ log(`Reduced ${piece_name_and_place(p)}.`);
+ else
+ log(`Reduced ${piece_name(p)}.`);
return false;
}
-function eliminate_piece(p) {
- log(`Eliminated ${piece_name_and_place(p)}.`);
+function eliminate_piece(p, verbose=true) {
+ if (verbose)
+ log(`Eliminated ${piece_name_and_place(p)}.`);
+ else
+ log(`Eliminated ${piece_name(p)}.`);
unstack_force(p);
set_unit_reduced(p, 0);
game.location[p] = 0;
- if (is_indian_unit(p)) {
- let home = indian_home_settlement(p);
+ if (is_indian(p)) {
+ let home = indians.space_from_piece[p];
if (home) {
- let tribe = indian_tribe[home];
if (is_indian_tribe_eliminated(home)) {
- if (home === PAYS_D_EN_HAUT)
- log(`Removed Pays d'en Haut allied marker.`);
- else
- log(`Removed ${tribe} allied marker.`);
- if (pieces[p].faction === 'british')
+ log(`Removed ${indians.tribe_from_space[home]} allied marker.`);
+ if (is_british_indian(p))
remove_from_array(game.british.allied, home);
else
remove_from_array(game.french.allied, home);
@@ -1640,27 +1603,16 @@ function eliminate_piece(p) {
}
}
-function eliminate_indian_tribe(tribe) {
- // OPTIMIZE: indian unit piece ranges
- for (let p = 1; p <= last_piece; ++p)
- if (is_indian_tribe(p, tribe) && is_piece_unbesieged(p))
+function eliminate_indian_tribe(s) {
+ for (let p of indians.pieces_from_space[s])
+ if (is_piece_unbesieged(p))
eliminate_piece(p);
}
-function is_indian_tribe_eliminated(home) {
- // OPTIMIZE: indian unit piece ranges
- if (home === PAYS_D_EN_HAUT) {
- for (let p = 1; p <= last_piece; ++p)
- if (is_pays_d_en_haut_indian_unit(p))
- if (is_piece_on_map(p))
- return false;
- } else {
- let tribe = indian_tribe[home];
- for (let p = 1; p <= last_piece; ++p)
- if (is_indian_tribe(p, tribe))
- if (is_piece_on_map(p))
- return false;
- }
+function is_indian_tribe_eliminated(s) {
+ for (let p of indians.pieces_from_space[s])
+ if (is_piece_on_map(p))
+ return false;
return true;
}
@@ -1687,18 +1639,17 @@ function place_piece(who, to) {
}
}
- if (is_indian_unit(who)) {
- let home = indian_home_settlement(who);
+ if (is_indian(who)) {
+ let home = indians.space_from_piece[who];
if (home) {
- let tribe = indian_tribe[home];
- if (pieces[who].faction === 'british') {
+ if (is_british_indian(who)) {
if (!game.british.allied.includes(home)) {
- log(`Placed ${tribe} allied marker.`);
+ log(`Placed ${indians.tribe_from_space[home]} allied marker.`);
game.british.allied.push(home);
}
} else {
if (!game.french.allied.includes(home)) {
- log(`Placed ${tribe} allied marker.`);
+ log(`Placed ${indians.tribe_from_space[home]} allied marker.`);
game.french.allied.push(home);
}
}
@@ -1837,7 +1788,7 @@ function search_supply_spaces_imp(queue) {
// If we must have come here by water way:
let cultivated = is_cultivated(current) || has_friendly_fortifications(current) || has_friendly_amphib(current);
// console.log("SUPPLY", space_name(current), cultivated);
- for_each_exit(current, (next, type) => {
+ for_each_exit_with_type(current, (next, type) => {
if (reached.includes(next))
return; // continue
if (has_unbesieged_enemy_units(next) || has_unbesieged_enemy_fortifications(next))
@@ -1931,7 +1882,7 @@ function find_closest_friendly_unbesieged_fortification(start) {
result.push(here);
}
if (dist < stop) {
- for_each_exit(here, (next) => {
+ for_each_exit(here, next => {
if (!(next in seen))
queue.push([next, dist+1]);
seen[next] = 1;
@@ -2194,13 +2145,13 @@ states.activate_individually = {
for (let p = first_friendly_unit; p <= last_friendly_unit; ++p) {
if (is_piece_on_map(p)) {
if (game.count >= 0.5) {
- if (is_indian_unit(p))
+ if (is_indian(p))
gen_action_piece(p);
}
if (game.count >= 1) {
- if (is_ranger_unit(p))
+ if (is_ranger(p))
gen_action_piece(p);
- if (is_coureurs_unit(p))
+ if (is_coureurs(p))
gen_action_piece(p);
if (is_drilled_troops(p))
if (game.activation.length === 0)
@@ -2215,7 +2166,7 @@ states.activate_individually = {
game.activation.push(p);
if (is_drilled_troops(p))
game.count = 0;
- else if (is_indian_unit(p))
+ else if (is_indian(p))
game.count -= 0.5;
else
game.count -= 1.0;
@@ -2244,6 +2195,7 @@ states.activate_force = {
}
states.select_campaign_1 = {
+ inactive: "campaign",
prompt() {
view.prompt = "Campaign \u2014 select the first leader.";
for (let p = first_friendly_leader; p <= last_friendly_leader; ++p) {
@@ -2263,6 +2215,7 @@ states.select_campaign_1 = {
}
states.select_campaign_2 = {
+ inactive: "campaign",
prompt() {
view.prompt = "Campaign \u2014 select the second leader.";
for (let p = first_friendly_leader; p <= last_friendly_leader; ++p) {
@@ -2344,7 +2297,18 @@ function can_drop_off_leader(commander, subordinate) {
return count_non_british_iroquois_and_mohawk_units_in_force(commander) <= force_command(commander) - leader_command(subordinate);
}
+const define_force_reason_prompt = {
+ 'campaign_1': "for first campaign",
+ 'campaign_2': "for second campaign",
+ 'move': "to move",
+ 'intercept': "to intercept",
+ 'avoid': "to avoid battle",
+}
+
states.define_force = {
+ get inactive() {
+ return "define force " + define_force_reason_prompt[game.force.reason];
+ },
prompt() {
let commander = game.force.commander;
let where = piece_space(commander);
@@ -2353,7 +2317,7 @@ states.define_force = {
let cmd_use = count_non_british_iroquois_and_mohawk_units_in_force(commander);
let cmd_cap = force_command(commander);
- view.prompt = `Define the force to ${game.force.reason} with ${piece_name(commander)} from ${space_name(where)} (${cmd_use}/${cmd_cap}).`;
+ view.prompt = `Define force ${define_force_reason_prompt[game.force.reason]} with ${piece_name(commander)} from ${space_name(where)} (${cmd_use}/${cmd_cap}).`;
view.who = commander;
let can_pick_up = false;
@@ -2475,6 +2439,7 @@ states.define_force = {
// TODO: merge with define_force using reason=intercept_lone_ax
states.define_force_lone_ax = {
+ inactive: "define lone auxiliary force to intercept",
prompt() {
let commander = game.force.commander;
let where = piece_space(commander);
@@ -2492,7 +2457,7 @@ states.define_force_lone_ax = {
// pick up units (max 1 auxiliary)
if (n === 0) {
for_each_friendly_unit_in_node(where, p => {
- if (is_auxiliary_unit(p)) {
+ if (is_auxiliary(p)) {
if (is_british_iroquois_or_mohawk(p)) {
// 5.534 Only Johnson can command British Iroquois and Mohawk (and for free)
if (is_piece_in_force(JOHNSON, commander))
@@ -2646,7 +2611,7 @@ function piece_can_naval_move_from(who, from) {
if (game.active === BRITAIN) {
if (has_amphib(from))
return true;
- if (ports.includes(from))
+ if (is_port(from))
return is_friendly_controlled_space(from);
return false;
}
@@ -2804,7 +2769,7 @@ function apply_move(to) {
const from_ff = has_friendly_fortifications_or_cultivated(from);
const to_ff = has_friendly_fortifications_or_cultivated(to);
const has_dt = force_has_drilled_troops(who);
- const has_ax = force_has_auxiliary_unit(who);
+ const has_ax = force_has_auxiliary(who);
// Must stop on mountains.
if (is_mountain(to) && !to_ff)
@@ -3233,7 +3198,7 @@ function gen_intercept() {
let has_br_indians = false;
for_each_friendly_unit_in_space(from, p => {
if (is_piece_unbesieged(p)) {
- if (is_auxiliary_unit(p)) {
+ if (is_auxiliary(p)) {
gen_action_piece(p);
if (is_british_iroquois_or_mohawk(p))
has_br_indians = true;
@@ -3341,7 +3306,7 @@ function attempt_intercept() {
if (is_leader(who))
die = modify(die, leader_tactics(who), "leader tactics");
if (die >= 4) {
- log(`Intercepted by ${describe_force(who)}!`);
+ log(`Intercepted by ${describe_force(who)}.`);
end_intercept_success();
} else {
log(`${piece_name_and_place(who)} failed interception.`);
@@ -3407,6 +3372,7 @@ states.declare_inside = {
set_piece_inside(p);
},
next() {
+ clear_undo();
set_active_enemy();
goto_avoid_battle();
},
@@ -3525,7 +3491,7 @@ states.avoid_to = {
});
}
}
- log(`Avoided battle with ${describe_force(moving_piece())}!`);
+ log(`Avoided battle with ${describe_force(moving_piece())}.`);
},
space(to) {
end_avoid_battle_success(to);
@@ -3641,16 +3607,16 @@ function combat_result(die, str, shift) {
let k = clamp(i + shift, 0, COMBAT_RESULT_TABLE.length-1);
let r = COMBAT_RESULT_TABLE[k][1][die];
if (k === 0)
- log(`Lookup ${die} on column 0: ${r}.`);
+ log(`Lookup ${die} on column 0.`);
else if (k === COMBAT_RESULT_TABLE.length - 1)
- log(`Lookup ${die} on column >= 28: ${r}.`);
+ log(`Lookup ${die} on column >= 28.`);
else {
let a = COMBAT_RESULT_TABLE[k-1][0] + 1;
let b = COMBAT_RESULT_TABLE[k][0];
if (a === b)
- log(`Lookup ${die} on column ${b}: ${r}.`);
+ log(`Lookup ${die} on column ${b}.`);
else
- log(`Lookup ${die} on column ${a}-${b}: ${r}.`);
+ log(`Lookup ${die} on column ${a}-${b}.`);
}
return r;
}
@@ -3676,6 +3642,7 @@ function goto_battle(where, is_assault) {
// Make a list of attacking pieces (for sorties and so we can unstack from the leader box)
if (game.battle.assault) {
+ console.log("START ASSAULT");
game.battle.atk_commander = find_friendly_commanding_leader_in_space(game.battle.where);
let where = game.battle.where;
if (game.battle.attacker === BRITAIN) {
@@ -3687,12 +3654,14 @@ function goto_battle(where, is_assault) {
if (is_piece_in_space(p, where))
game.battle.atk_pcs.push(p);
}
- } else if (game.raid) {
+ } else if (game.raid.where === where) {
+ console.log("START RAID BATTLE");
game.battle.atk_commander = find_friendly_commanding_leader_in_space(game.battle.where);
for_each_friendly_piece_in_space(game.battle.where, p => {
game.battle.atk_pcs.push(p);
});
} else {
+ console.log("START BATTLE");
game.battle.atk_commander = game.move.moving;
for_each_piece_in_force(game.move.moving, p => {
game.battle.atk_pcs.push(p);
@@ -3715,7 +3684,7 @@ function goto_battle(where, is_assault) {
for_each_attacking_piece(p => {
if (is_unit(p))
++n_atk;
- if (is_regular_unit(p))
+ if (is_regular(p))
game.battle.atk_worth_vp = 1;
});
if (n_atk > 4)
@@ -3725,7 +3694,7 @@ function goto_battle(where, is_assault) {
for_each_defending_piece(p => {
if (is_unit(p))
++n_def;
- if (is_regular_unit(p))
+ if (is_regular(p))
game.battle.def_worth_vp = 1;
});
if (n_def > 4)
@@ -3746,24 +3715,27 @@ function goto_battle_militia() {
let box = department_militia(game.battle.where);
if (box && count_militia_in_department(box) > 0) {
console.log("MILITIA", space_name(game.battle.where), space_name(box));
- let dept = null;
+ let first = 0, last = 0;
switch (box) {
case ST_LAWRENCE_CANADIAN_MILITIAS:
set_active(FRANCE);
- dept = departments.st_lawrence;
+ first = first_st_lawrence_department;
+ last = last_st_lawrence_department;
break;
case NORTHERN_COLONIAL_MILITIAS:
set_active(BRITAIN);
- dept = departments.northern;
+ first = first_northern_department;
+ last = last_northern_department;
break;
case SOUTHERN_COLONIAL_MILITIAS:
set_active(BRITAIN);
- dept = departments.southern;
+ first = first_southern_department;
+ last = last_southern_department;
break;
}
// 7.3 exception: No Militia if there are enemy raided markers.
- for (let i = 0; i < dept.length; ++i)
- if (has_enemy_raided_marker(dept[i]))
+ for (let s = first; s <= last; ++s)
+ if (has_enemy_raided_marker(s))
return goto_battle_sortie();
game.state = 'militia_in_battle';
} else {
@@ -3776,9 +3748,15 @@ states.militia_in_battle = {
view.prompt = "Determine which Militia units will participate.";
let box = department_militia(game.battle.where);
view.where = game.battle.where;
- for (let p = first_friendly_unit; p <= last_friendly_unit; ++p)
- if (piece_node(p) === box)
- gen_action_piece(p);
+ if (game.active === FRANCE) {
+ for (let p = first_french_militia; p <= last_french_militia; ++p)
+ if (piece_node(p) === box)
+ gen_action_piece(p);
+ } else {
+ for (let p = first_british_militia; p <= last_british_militia; ++p)
+ if (piece_node(p) === box)
+ gen_action_piece(p);
+ }
gen_action_next();
},
piece(p) {
@@ -3830,7 +3808,7 @@ states.sortie = {
function count_auxiliary_units_in_attack() {
let n = 0;
for_each_attacking_piece(p => {
- if (is_auxiliary_unit(p))
+ if (is_auxiliary(p))
++n;
});
return n;
@@ -3839,7 +3817,7 @@ function count_auxiliary_units_in_attack() {
function count_auxiliary_units_in_defense() {
let n = 0;
for_each_defending_piece(p => {
- if (is_auxiliary_unit(p))
+ if (is_auxiliary(p))
++n;
});
return n;
@@ -3848,7 +3826,7 @@ function count_auxiliary_units_in_defense() {
function has_light_infantry_in_attack() {
let n = 0;
for_each_attacking_piece(p => {
- if (is_light_infantry_unit(p))
+ if (is_light_infantry(p))
++n;
});
return n > 0;
@@ -3857,7 +3835,7 @@ function has_light_infantry_in_attack() {
function has_light_infantry_in_defense() {
let n = 0;
for_each_defending_piece(p => {
- if (is_light_infantry_unit(p))
+ if (is_light_infantry(p))
++n;
});
return n > 0;
@@ -3984,7 +3962,8 @@ states.attacker_events = {
else
dont_have.push('"Fieldworks"');
}
- view.prompt = "Attacker events.";
+ view.prompt = "Attacker at ${game.battle.where}.";
+ view.where = game.battle.where;
if (have.length > 0)
view.prompt += " You may play " + have.join(" or ") + ".";
if (dont_have.length > 0)
@@ -4051,6 +4030,7 @@ states.defender_events = {
dont_have.push('"Fieldworks"');
}
view.prompt = `Defender at ${space_name(game.battle.where)}.`;
+ view.where = game.battle.where;
if (have.length > 0)
view.prompt += " You may play " + have.join(" or ") + ".";
if (dont_have.length > 0)
@@ -4178,14 +4158,14 @@ function goto_atk_fire() {
shift -= 1;
} else {
if (is_wilderness_or_mountain(game.battle.where)) {
- let atk_has_ax = some_attacking_piece(p => is_auxiliary_unit(p) || is_light_infantry_unit(p));
- let def_has_ax = some_defending_piece(p => is_auxiliary_unit(p) || is_light_infantry_unit(p));
+ let atk_has_ax = some_attacking_piece(p => is_auxiliary(p) || is_light_infantry(p));
+ let def_has_ax = some_defending_piece(p => is_auxiliary(p) || is_light_infantry(p));
if (!atk_has_ax && def_has_ax)
die = modify(die, -1, "vs auxiliaries in wilderness");
}
if (is_cultivated(game.battle.where)) {
- let atk_has_reg = some_attacking_piece(p => is_regular_unit(p));
- let def_has_reg = some_defending_piece(p => is_regular_unit(p));
+ let atk_has_reg = some_attacking_piece(p => is_regular(p));
+ let def_has_reg = some_defending_piece(p => is_regular(p));
if (!atk_has_reg && def_has_reg)
die = modify(die, -1, "vs regulars in cultivated");
}
@@ -4231,14 +4211,14 @@ function goto_def_fire() {
if (!game.battle.assault) {
if (is_wilderness_or_mountain(game.battle.where)) {
- let atk_has_ax = some_attacking_piece(p => is_auxiliary_unit(p) || is_light_infantry_unit(p));
- let def_has_ax = some_defending_piece(p => is_auxiliary_unit(p) || is_light_infantry_unit(p));
+ let atk_has_ax = some_attacking_piece(p => is_auxiliary(p) || is_light_infantry(p));
+ let def_has_ax = some_defending_piece(p => is_auxiliary(p) || is_light_infantry(p));
if (atk_has_ax && !def_has_ax)
die = modify(die, -1, "vs auxiliaries in wilderness");
}
if (is_cultivated(game.battle.where)) {
- let atk_has_reg = some_attacking_piece(p => is_regular_unit(p));
- let def_has_reg = some_defending_piece(p => is_regular_unit(p));
+ let atk_has_reg = some_attacking_piece(p => is_regular(p));
+ let def_has_reg = some_defending_piece(p => is_regular(p));
if (atk_has_reg && !def_has_reg)
die = modify(die, -1, "vs regulars in cultivated");
}
@@ -4269,6 +4249,8 @@ function goto_atk_step_losses() {
if (is_unit(p))
game.battle.units.push(p);
});
+ log("");
+ log("ATTACKER LOSSES");
} else {
end_step_losses();
}
@@ -4292,6 +4274,10 @@ function goto_def_step_losses() {
// None to take!
if (game.battle.units.length === 0)
end_step_losses();
+ else {
+ log("");
+ log("DEFENDER LOSSES");
+ }
} else {
end_step_losses();
}
@@ -4345,7 +4331,7 @@ states.step_losses = {
--game.battle.step_loss;
if (game.battle.dt_loss > 0 && is_drilled_troops(p))
--game.battle.dt_loss;
- if (reduce_unit(p)) {
+ if (reduce_unit(p, false)) {
remove_from_array(game.battle.atk_pcs, p);
remove_from_array(game.battle.units, p);
}
@@ -4398,7 +4384,7 @@ states.raid_step_losses = {
piece(p) {
push_undo();
--game.raid.step_loss;
- if (reduce_unit(p))
+ if (reduce_unit(p, false))
remove_from_array(game.raid.units, p);
},
next() {
@@ -4413,32 +4399,32 @@ function goto_atk_leader_check() {
set_active(game.battle.attacker);
game.battle.leader_check = [];
if ((game.battle.def_result > 0) && (game.battle.def_die === 1 || game.battle.def_die === 6)) {
- log(`${game.battle.attacker} leader loss check`);
for_each_attacking_piece(p => {
if (is_leader(p))
game.battle.leader_check.push(p);
});
}
- if (game.battle.leader_check.length > 0)
+ if (game.battle.leader_check.length > 0) {
game.state = 'leader_check';
- else
+ } else {
end_leader_check();
+ }
}
function goto_def_leader_check() {
set_active(game.battle.defender);
game.battle.leader_check = [];
if ((game.battle.atk_result > 0) && (game.battle.atk_die === 1 || game.battle.atk_die === 6)) {
- log(`${game.battle.defender} leader loss check`);
for_each_defending_piece(p => {
if (is_leader(p))
game.battle.leader_check.push(p);
});
}
- if (game.battle.leader_check.length > 0)
+ if (game.battle.leader_check.length > 0) {
game.state = 'leader_check';
- else
+ } else {
end_leader_check();
+ }
}
states.leader_check = {
@@ -4448,7 +4434,7 @@ states.leader_check = {
gen_action_piece(game.battle.leader_check[i]);
},
piece(p) {
- let die = roll_die("for " + piece_name(p) + " leader check");
+ let die = roll_die("for " + piece_name(p));
if (die === 1) {
if (game.battle)
remove_from_array(game.battle.atk_pcs, p);
@@ -4485,7 +4471,7 @@ states.raid_leader_check = {
gen_action_piece(game.raid.leader_check[i]);
},
piece(p) {
- let die = roll_die("for " + piece_name(p) + " leader check");
+ let die = roll_die("for " + piece_name(p));
if (die === 1)
eliminate_piece(p);
remove_from_array(game.raid.leader_check, p);
@@ -4504,7 +4490,7 @@ function return_militia(where) {
if (box) {
let n = 0;
for (let p = 1; p <= last_piece; ++p) {
- if (is_militia_unit(p) && is_piece_in_space(p, where)) {
+ if (is_militia(p) && is_piece_in_space(p, where)) {
move_piece_to(p, box);
++n;
}
@@ -4533,10 +4519,10 @@ function determine_winner_battle() {
let atk_eliminated = count_attacking_units() === 0;
let def_eliminated = count_unbesieged_enemy_units_in_space(where) === 0;
- log("RESULT", "atk_eliminated", game.battle.atk_eliminated);
+ log("RESULT", "atk_eliminated", atk_eliminated);
log("RESULT", "atk_result", game.battle.atk_result);
log("RESULT", "atk_caused", game.battle.atk_caused);
- log("RESULT", "def_eliminated", game.battle.def_eliminated);
+ log("RESULT", "def_eliminated", def_eliminated);
log("RESULT", "def_result", game.battle.def_result);
log("RESULT", "def_caused", game.battle.def_caused);
@@ -4856,10 +4842,10 @@ states.retreat_defender_to = {
let from = game.battle.where;
let who = game.battle.who;
if (from === to) {
- log("retreats inside fortification");
+ log(`${piece_name(who)} retreats inside fortification.`);
set_piece_inside(who);
} else {
- log("retreats to " + space_name(to));
+ log(`${piece_name(who)} retreats to ${space_name(to)}.`);
move_piece_to(who, to);
}
game.state = 'retreat_defender';
@@ -5236,9 +5222,15 @@ states.militia_against_raid = {
view.where = game.raid.where;
if (game.count > 0) {
let box = department_militia(game.raid.where);
- for (let p = first_friendly_unit; p <= last_friendly_unit; ++p)
- if (piece_node(p) === box)
- gen_action_piece(p);
+ if (game.active === FRANCE) {
+ for (let p = first_french_militia; p <= last_french_militia; ++p)
+ if (piece_node(p) === box)
+ gen_action_piece(p);
+ } else {
+ for (let p = first_british_militia; p <= last_british_militia; ++p)
+ if (piece_node(p) === box)
+ gen_action_piece(p);
+ }
}
gen_action_next();
},
@@ -5330,7 +5322,7 @@ function resolve_raid() {
if (x_stockade)
destroy_enemy_stockade_in_raid(where);
if (x_allied)
- eliminate_indian_tribe(indian_tribe[where]);
+ eliminate_indian_tribe(where);
} else {
log(`Result ${die} vs ${column}:\nFailure with ${losses} losses.`);
}
@@ -5359,7 +5351,7 @@ function can_follow_indians_home(from) {
return true;
}
for (let p = first_friendly_unit; p <= last_friendly_unit; ++p) {
- if (is_coureurs_unit(p) && is_piece_in_space(p, from) && !is_piece_inside(p))
+ if (is_coureurs(p) && is_piece_in_space(p, from) && !is_piece_inside(p))
return true;
}
return false;
@@ -5416,14 +5408,14 @@ states.raiders_go_home = {
if (true) {
// INDIANS FIRST
for_each_friendly_unit_in_space(from, p => {
- if (is_indian_unit(p)) {
+ if (is_indian(p)) {
done = false;
gen_action_piece(p);
}
});
if (done) {
for_each_friendly_piece_in_space(from, p => {
- if (!is_indian_unit(p)) {
+ if (!is_indian(p)) {
done = false;
gen_action_piece(p);
}
@@ -5464,8 +5456,8 @@ states.indians_and_leaders_go_home = {
if (s && !is_piece_inside(p) && !has_friendly_fortifications(s)) {
// Indians not at their settlement
- if (is_indian_unit(p)) {
- if (s !== indian_home_settlement(p)) {
+ if (is_indian(p)) {
+ if (s !== indians.space_from_piece[p]) {
done = false;
gen_action_piece(p);
}
@@ -5511,8 +5503,8 @@ states.go_home_to = {
let can_go_home = false;
- if (is_indian_unit(who)) {
- let home = indian_home_settlement(who);
+ if (is_indian(who)) {
+ let home = indians.space_from_piece[who];
// 10.412: Cherokee have no home settlement
if (home && has_friendly_allied_settlement(home) && !has_enemy_units(home)) {
can_go_home = true;
@@ -5545,8 +5537,8 @@ states.go_home_to = {
let from = game.go_home.from;
log(`${piece_name(who)} went home to ${space_name(to)}.`);
move_piece_to(who, to);
- if (is_indian_unit(who)) {
- let home = indian_home_settlement(who);
+ if (is_indian(who)) {
+ let home = indians.space_from_piece[who];
console.log("go_home", space_name(from), space_name(to), space_name(home));
game.count = 0;
if (to !== home) {
@@ -5608,7 +5600,7 @@ states.go_home_with_indians = {
gen_action_piece(p);
}
for (let p = first_friendly_unit; p <= last_friendly_unit; ++p) {
- if (is_coureurs_unit(p) && is_piece_in_space(p, from) && !is_piece_inside(p))
+ if (is_coureurs(p) && is_piece_in_space(p, from) && !is_piece_inside(p))
gen_action_piece(p);
}
@@ -5750,7 +5742,7 @@ states.winter_attrition = {
push_undo();
if (is_unit_reduced(p))
stack.n--;
- reduce_unit(p);
+ reduce_unit(p, true);
remove_from_array(stack.dt, p);
},
next() {
@@ -5855,7 +5847,7 @@ function goto_game_over(result, victory) {
states.game_over = {
inactive() {
- return view.prompt = game.victory;
+ view.prompt = game.victory;
}
}
@@ -5916,10 +5908,10 @@ states.demolish_fort = {
},
space(s) {
if (has_friendly_fort_uc(s)) {
- log(`Demolishes fort U/C at ${space_name(s)}.`);
+ log(`Demolished fort U/C at ${space_name(s)}.`);
remove_friendly_fort_uc(s);
} else if (has_friendly_fort(s)) {
- log(`Demolishes fort at ${space_name(s)}.`);
+ log(`Demolished fort at ${space_name(s)}.`);
award_vp(-1);
remove_friendly_fort(s);
}
@@ -5934,7 +5926,7 @@ states.demolish_stockade = {
gen_action_space(s);
},
space(s) {
- log(`Demolishes stockade at ${space_name(s)}.`);
+ log(`Demolished stockade at ${space_name(s)}.`);
remove_friendly_stockade(s);
end_demolish();
}
@@ -6124,7 +6116,7 @@ function massacre_play(c) {
play_card(c);
let s = moving_piece_space();
for (let p = 1; p <= last_piece; ++p)
- if (is_indian_unit(p) && is_piece_in_space(p, s))
+ if (is_indian(p) && is_piece_in_space(p, s))
eliminate_piece(p);
award_vp(1);
set_active_enemy();
@@ -6140,7 +6132,7 @@ function can_place_in_space(s) {
function can_restore_unit(p) {
if (is_piece_on_map(p) && is_piece_unbesieged(p) && is_unit_reduced(p)) {
- if (is_militia_unit(p))
+ if (is_militia(p))
return true; // always in militia box
if (is_drilled_troops(p))
return is_in_supply(piece_space(p));
@@ -6149,11 +6141,19 @@ function can_restore_unit(p) {
return false;
}
-function count_french_raids_in_dept(dept) {
+function count_french_raids_in_southern_department() {
+ let n = 0;
+ for (let i = 0; i < game.french.raids.length; ++i) {
+ if (is_southern_department(game.french.raids[i]))
+ ++n;
+ }
+ return n;
+}
+
+function count_french_raids_in_northern_department() {
let n = 0;
for (let i = 0; i < game.french.raids.length; ++i) {
- let s = game.french.raids[i];
- if (departments[dept].includes(s))
+ if (is_northern_department(game.french.raids[i]))
++n;
}
return n;
@@ -6161,15 +6161,15 @@ function count_french_raids_in_dept(dept) {
events.provincial_regiments_dispersed_for_frontier_duty = {
can_play() {
- let s = Math.min(count_french_raids_in_dept('southern'), count_provincial_units_from('southern'));
- let n = Math.min(count_french_raids_in_dept('northern'), count_provincial_units_from('northern'));
+ let s = Math.min(count_french_raids_in_southern_department(), count_southern_provincials());
+ let n = Math.min(count_french_raids_in_northern_department(), count_northern_provincials());
return (s + n) > 0;
},
play() {
game.state = 'provincial_regiments_dispersed_for_frontier_duty';
game.frontier_duty = {
- southern: Math.min(count_french_raids_in_dept('southern'), count_provincial_units_from('southern')),
- northern: Math.min(count_french_raids_in_dept('northern'), count_provincial_units_from('northern')),
+ southern: Math.min(count_french_raids_in_southern_department(), count_southern_provincials()),
+ northern: Math.min(count_french_raids_in_northern_department(), count_northern_provincials()),
};
}
}
@@ -6179,20 +6179,24 @@ states.provincial_regiments_dispersed_for_frontier_duty = {
view.prompt = `Eliminate ${game.frontier_duty.southern} southern and ${game.frontier_duty.northern} northern provincials.`;
let can_eliminate = false;
for (let p = first_british_unit; p <= last_british_unit; ++p) {
- if ((game.frontier_duty.northern > 0 && is_provincial_unit_from(p, 'northern')) ||
- (game.frontier_duty.southern > 0 && is_provincial_unit_from(p, 'southern'))) {
+ if ((game.frontier_duty.northern > 0 && is_northern_provincial(p)) ||
+ (game.frontier_duty.southern > 0 && is_southern_provincial(p))) {
can_eliminate = true;
gen_action_piece(p);
}
}
- if (!can_eliminate)
+ if (can_eliminate) {
+ view.prompt = `Eliminate ${game.frontier_duty.southern} southern and ${game.frontier_duty.northern} northern provincials.`;
+ } else {
+ view.prompt = `Eliminate southern and northern provincials \u2014 done.`;
gen_action_next();
+ }
},
piece(p) {
push_undo();
- if (is_provincial_unit_from(p, 'southern'))
+ if (is_southern_provincial(p))
game.frontier_duty.southern --;
- if (is_provincial_unit_from(p, 'northern'))
+ if (is_northern_provincial(p))
game.frontier_duty.northern --;
eliminate_piece(p);
},
@@ -6266,35 +6270,22 @@ events.iroquois_alliance = {
},
}
-function find_friendly_unused_indian(home) {
- if (home === PAYS_D_EN_HAUT) {
- for (let p = first_friendly_unit; p <= last_friendly_unit; ++p)
- if (is_pays_d_en_haut_indian_unit(p) && is_piece_unused(p))
- return p;
- } else {
- let tribe = indian_tribe[home];
- for (let p = first_friendly_unit; p <= last_friendly_unit; ++p)
- if (pieces[p].name === tribe && is_piece_unused(p))
- return p;
- }
+function find_friendly_unused_indian(s) {
+ for (let p of indians.pieces_from_space[s])
+ if (is_friendly_indian(p) && is_piece_unused(p))
+ return p;
return 0;
}
-function is_indian_alliance(p, alliance) {
- if (is_indian_unit(p))
- return pieces[p].subtype === alliance;
- return false;
-}
-
states.indian_alliance = {
prompt() {
let can_place = false;
for (let a of game.alliance) {
if (game.count >= 1) {
- for (let s of indian_spaces[a]) {
- if (!has_enemy_allied_settlement(s)) {
- let p = find_friendly_unused_indian(s);
- if (p && can_place_in_space(s)) {
+ for (let p of indians.pieces_from_color[a]) {
+ if (is_friendly_indian(p) && is_piece_unused(p)) {
+ let s = indians.space_from_piece[p];
+ if (!has_enemy_allied_settlement(s) && can_place_in_space(s)) {
can_place = true;
gen_action_space(s);
}
@@ -6302,12 +6293,10 @@ states.indian_alliance = {
}
}
if (game.count >= 0.5) {
- for (let p = first_friendly_unit; p <= last_friendly_unit; ++p) {
- if (is_indian_alliance(p, a)) {
- if (can_restore_unit(p)) {
- can_place = true;
- gen_action_piece(p);
- }
+ for (let p of indians.pieces_from_color[a]) {
+ if (is_friendly_indian(p) && can_restore_unit(p)) {
+ can_place = true;
+ gen_action_piece(p);
}
}
}
@@ -6341,27 +6330,20 @@ states.indian_alliance = {
}
// Used by Mohawks and Cherokees events.
-function place_british_indian_tribe(s, tribe) {
+function place_british_indian_tribe(s, first, last) {
push_undo();
-
- // OPTIMIZE: use mohawks piece list
- for (let p = first_british_unit; p <= last_british_unit; ++p) {
- if (is_indian_tribe(p, tribe)) {
- if (is_piece_unused(p))
- place_piece(p, s);
- }
+ for (let p = first; p <= last; ++p) {
+ if (is_piece_unused(p))
+ place_piece(p, s);
}
-
game.count = 0;
}
-function restore_british_indian_tribe(tribe) {
+function restore_british_indian_tribe(first, last) {
// TODO: restore_mohawks/cherokee state for manual restoring?
- for (let p = first_british_unit; p <= last_british_unit; ++p) {
- if (is_indian_tribe(p, tribe)) {
- if (can_restore_unit(p))
- restore_unit(p);
- }
+ for (let p = first; p <= last; ++p) {
+ if (can_restore_unit(p))
+ restore_unit(p);
}
}
@@ -6376,7 +6358,7 @@ events.mohawks = {
play() {
game.state = 'mohawks';
game.count = 1;
- restore_british_indian_tribe('Mohawk');
+ restore_british_indian_tribe(first_mohawk, last_mohawk);
},
}
@@ -6398,7 +6380,7 @@ states.mohawks = {
}
},
space(s) {
- place_british_indian_tribe(s, 'Mohawk');
+ place_british_indian_tribe(s, first_mohawk, last_mohawk);
},
next() {
end_action_phase();
@@ -6415,7 +6397,7 @@ events.cherokees = {
game.events.cherokees = 1;
game.state = 'cherokees';
game.count = 1;
- restore_british_indian_tribe(s, 'Cherokee');
+ restore_british_indian_tribe(first_cherokee, last_cherokee);
},
}
@@ -6423,8 +6405,7 @@ states.cherokees = {
prompt() {
let can_place = false;
if (game.count > 0) {
- for (let i = 0; i < departments.southern.length; ++i) {
- let s = departments.southern[i];
+ for (let s = first_southern_department; s <= last_southern_department; ++s) {
if (has_unbesieged_friendly_fortifications(s)) {
can_place = true;
gen_action_space(s);
@@ -6439,7 +6420,7 @@ states.cherokees = {
}
},
space(s) {
- place_british_indian_tribe(s, 'Cherokee');
+ place_british_indian_tribe(s, first_cherokee, last_cherokee);
},
next() {
end_action_phase();
@@ -6467,16 +6448,16 @@ events.cherokee_uprising = {
states.cherokee_uprising = {
prompt() {
- view.prompt = `Eliminate ${game.uprising.regular} regular, ${game.uprising.southern} southern provincial, and all Cherokee.`;
+ view.prompt = `Eliminate ${game.uprising.regular} regulars, ${game.uprising.southern} southern provincials, and all Cherokee.`;
let can_eliminate = false;
for (let p = first_british_unit; p <= last_british_unit; ++p) {
if (is_piece_on_map(p) && is_piece_unbesieged(p)) {
let x = false;
- if (game.uprising.regular > 0 && is_regular_unit(p))
+ if (game.uprising.regular > 0 && is_regular(p))
x = true;
- if (game.uprising.southern > 0 && is_provincial_unit_from(p, 'southern'))
+ if (game.uprising.southern > 0 && is_southern_provincial(p))
x = true;
- if (is_indian_tribe(p, 'Cherokee'))
+ if (is_cherokee(p))
x = true;
if (x) {
can_eliminate = true;
@@ -6489,9 +6470,9 @@ states.cherokee_uprising = {
},
piece(p) {
push_undo();
- if (is_regular_unit(p))
+ if (is_regular(p))
game.uprising.regular --;
- if (is_provincial_unit_from(p, 'southern'))
+ if (is_southern_provincial(p))
game.uprising.southern --;
eliminate_piece(p);
},
@@ -6512,8 +6493,8 @@ events.treaty_of_easton = {
play() {
// TODO: treaty_of_easton state for manual elimination?
for (let p = first_french_unit; p <= last_french_unit; ++p) {
- if (is_indian_unit(p) && is_piece_on_map(p) && is_piece_unbesieged(p)) {
- if (is_western_indian_unit(p)) {
+ if (is_indian(p) && is_piece_on_map(p) && is_piece_unbesieged(p)) {
+ if (is_orange_indian(p)) {
eliminate_piece(p);
}
}
@@ -6535,7 +6516,7 @@ states.indians_desert = {
let can_desert = false;
if (game.count > 0) {
for (let p = first_enemy_unit; p <= last_enemy_unit; ++p) {
- if (is_indian_unit(p) && is_piece_on_map(p) && is_piece_unbesieged(p)) {
+ if (is_indian(p) && is_piece_on_map(p) && is_piece_unbesieged(p)) {
if (!game.indians_desert || is_piece_in_space(p, game.indians_desert)) {
can_desert = true;
gen_action_piece(p);
@@ -6691,12 +6672,12 @@ states.reduce_from_small_pox = {
piece(p) {
push_undo();
game.count --;
- reduce_unit(p);
+ reduce_unit(p, false);
},
next() {
for_each_friendly_unit_in_space(game.small_pox, p => {
- if (is_indian_unit(p))
- eliminate_piece(p);
+ if (is_indian(p))
+ eliminate_piece(p, false);
});
delete game.small_pox;
set_active_enemy();
@@ -6788,30 +6769,50 @@ states.british_ministerial_crisis = {
}
}
-function count_reduced_unbesieged_provincial_units_from(dept) {
+function count_southern_provincials() {
let n = 0;
- for (let p = first_british_unit; p <= last_british_unit; ++p)
- if (is_provincial_unit_from(p, dept) && is_piece_on_map(p))
- if (is_piece_unbesieged(p) && is_unit_reduced(p))
- ++n;
+ for (let p = first_southern_provincial; p <= last_southern_provincial; ++p)
+ if (is_piece_on_map(p))
+ ++n;
return n;
}
-function count_unbesieged_provincial_units_from(dept) {
+function count_northern_provincials() {
let n = 0;
- // OPTIMIZE: use provincial unit numbers
- for (let p = first_british_unit; p <= last_british_unit; ++p)
- if (is_provincial_unit_from(p, dept) && is_piece_on_map(p))
- if (is_piece_unbesieged(p))
- ++n;
+ for (let p = first_northern_provincial; p <= last_northern_provincial; ++p)
+ if (is_piece_on_map(p))
+ ++n;
return n;
}
-function count_provincial_units_from(dept) {
+function count_unbesieged_southern_provincials() {
let n = 0;
- // OPTIMIZE: use provincial unit numbers
- for (let p = first_british_unit; p <= last_british_unit; ++p)
- if (is_provincial_unit_from(p, dept) && is_piece_on_map(p))
+ for (let p = first_southern_provincial; p <= last_southern_provincial; ++p)
+ if (is_piece_on_map(p) && is_piece_unbesieged(p))
+ ++n;
+ return n;
+}
+
+function count_unbesieged_northern_provincials() {
+ let n = 0;
+ for (let p = first_northern_provincial; p <= last_northern_provincial; ++p)
+ if (is_piece_on_map(p) && is_piece_unbesieged(p))
+ ++n;
+ return n;
+}
+
+function count_reduced_unbesieged_southern_provincials() {
+ let n = 0;
+ for (let p = first_southern_provincial; p <= last_southern_provincial; ++p)
+ if (is_piece_on_map(p) && is_piece_unbesieged(p) && is_unit_reduced(p))
+ ++n;
+ return n;
+}
+
+function count_reduced_unbesieged_northern_provincials() {
+ let n = 0;
+ for (let p = first_northern_provincial; p <= last_northern_provincial; ++p)
+ if (is_piece_on_map(p) && is_piece_unbesieged(p) && is_unit_reduced(p))
++n;
return n;
}
@@ -6820,13 +6821,13 @@ events.stingy_provincial_assembly = {
can_play() {
if (game.pa === ENTHUSIASTIC)
return false;
- let num_n = count_unbesieged_provincial_units_from('northern');
- let num_s = count_unbesieged_provincial_units_from('southern');
+ let num_n = count_unbesieged_northern_provincials();
+ let num_s = count_unbesieged_southern_provincials();
return (num_n + num_s) > 0;
},
play() {
- let num_n = count_unbesieged_provincial_units_from('northern');
- let num_s = count_unbesieged_provincial_units_from('southern');
+ let num_n = count_unbesieged_northern_provincials();
+ let num_s = count_unbesieged_southern_provincials();
if (num_n > 0 && num_s === 0) {
goto_stingy_provincial_assembly('northern');
} else if (num_n === 0 && num_s > 0) {
@@ -6864,10 +6865,15 @@ states.stingy_provincial_assembly = {
prompt() {
if (game.count > 0) {
view.prompt = `Stingy Provincial Assembly \u2014 remove a ${game.department} provincial unit.`;
- // OPTIMIZE: use provincial unit numbers
- for (let p = first_british_unit; p <= last_british_unit; ++p)
- if (is_provincial_unit_from(p, game.department) && is_piece_unbesieged(p))
- gen_action_piece(p);
+ if (game.department === 'northern') {
+ for (let p = first_northern_provincial; p <= last_northern_provincial; ++p)
+ if (is_piece_unbesieged(p))
+ gen_action_piece(p);
+ } else {
+ for (let p = first_southern_provincial; p <= last_southern_provincial; ++p)
+ if (is_piece_unbesieged(p))
+ gen_action_piece(p);
+ }
} else {
view.prompt = `Stingy Provincial Assembly \u2014 done.`;
gen_action_next();
@@ -6911,22 +6917,15 @@ function pa_name() {
}
}
-const provincial_limit_southern = [ 2, 4, 6 ];
-const provincial_limit_northern = [ 6, 10, 18 ];
-
-function provincial_limit(dept) {
- if (dept === 'northern')
- return provincial_limit_northern[game.pa];
- else
- return provincial_limit_southern[game.pa];
-}
+const southern_provincial_limit = [ 2, 4, 6 ];
+const northern_provincial_limit = [ 6, 10, 18 ];
function goto_enforce_provincial_limits() {
if (game.pa < ENTHUSIASTIC) {
- let num_s = count_provincial_units_from('southern');
- let num_n = count_provincial_units_from('northern');
- let max_n = provincial_limit('northern');
- let max_s = provincial_limit('southern');
+ let num_s = count_southern_provincials();
+ let num_n = count_northern_provincials();
+ let max_n = northern_provincial_limit[game.pa];
+ let max_s = southern_provincial_limit[game.pa];
if (num_s > max_s || num_n > max_n) {
clear_undo();
set_active_enemy();
@@ -6939,19 +6938,23 @@ function goto_enforce_provincial_limits() {
states.enforce_provincial_limits = {
prompt() {
- let num_s = count_provincial_units_from('southern');
- let num_n = count_provincial_units_from('northern');
- let max_n = provincial_limit('northern');
- let max_s = provincial_limit('southern');
+ let num_s = count_southern_provincials();
+ let num_n = count_northern_provincials();
+ let max_n = northern_provincial_limit[game.pa];
+ let max_s = southern_provincial_limit[game.pa];
console.log("British Colonial Politics", num_s, max_s, num_n, max_n);
let can_remove = false;
- if (num_s > max_s || num_n > max_n) {
- // OPTIMIZE: use provincial unit numbers
- for (let p = first_british_unit; p <= last_british_unit; ++p) {
- if (num_s > max_s && is_provincial_unit_from(p, 'southern') && is_piece_unbesieged(p)) {
+ if (num_s > max_s) {
+ for (let p = first_southern_provincial; p <= last_southern_provincial; ++p) {
+ if (is_piece_unbesieged(p)) {
gen_action_piece(p);
can_remove = true;
- } else if (num_n > max_n && is_provincial_unit_from(p, 'northern') && is_piece_unbesieged(p)) {
+ }
+ }
+ }
+ if (num_n > max_n) {
+ for (let p = first_northern_provincial; p <= last_northern_provincial; ++p) {
+ if (is_piece_unbesieged(p)) {
gen_action_piece(p);
can_remove = true;
}
@@ -6974,23 +6977,33 @@ states.enforce_provincial_limits = {
},
}
-function can_raise_provincial_regiments(dept) {
- let num = count_provincial_units_from(dept);
- let max = provincial_limit(dept);
+function can_raise_southern_provincial_regiments() {
+ let num = count_southern_provincials();
+ let max = southern_provincial_limit[game.pa];
+ return num < max;
+}
+
+function can_raise_northern_provincial_regiments() {
+ let num = count_northern_provincials();
+ let max = northern_provincial_limit[game.pa];
return num < max;
}
-function can_restore_provincial_regiments(dept) {
- return count_reduced_unbesieged_provincial_units_from(dept) > 0;
+function can_restore_southern_provincial_regiments() {
+ return count_reduced_unbesieged_southern_provincials() > 0;
+}
+
+function can_restore_northern_provincial_regiments() {
+ return count_reduced_unbesieged_northern_provincials() > 0;
}
events.raise_provincial_regiments = {
can_play() {
if (game.pa === RELUCTANT)
return false;
- if (can_raise_provincial_regiments('northern') || can_restore_provincial_regiments('northern'))
+ if (can_raise_northern_provincial_regiments() || can_restore_northern_provincial_regiments())
return true;
- if (can_raise_provincial_regiments('southern') || can_restore_provincial_regiments('southern'))
+ if (can_raise_southern_provincial_regiments() || can_restore_southern_provincial_regiments())
return true;
return false;
},
@@ -7002,23 +7015,23 @@ events.raise_provincial_regiments = {
states.raise_provincial_regiments_where = {
prompt() {
view.prompt = "Raise Provincial regiments in which department?";
- if (can_raise_provincial_regiments('northern') || can_restore_provincial_regiments('northern'))
+ if (can_raise_northern_provincial_regiments() || can_restore_northern_provincial_regiments())
gen_action('northern');
- if (can_raise_provincial_regiments('southern') || can_restore_provincial_regiments('southern'))
+ if (can_raise_southern_provincial_regiments() || can_restore_southern_provincial_regiments())
gen_action('southern');
},
northern() {
push_undo();
- let num = count_provincial_units_from('northern');
- let max = provincial_limit('northern');
+ let num = count_northern_provincials();
+ let max = northern_provincial_limit[game.pa];
game.state = 'raise_provincial_regiments';
game.count = clamp(max - num, 0, 4);
game.department = 'northern';
},
southern() {
push_undo();
- let num = count_provincial_units_from('southern');
- let max = provincial_limit('southern');
+ let num = count_southern_provincials();
+ let max = southern_provincial_limit[game.pa];
game.state = 'raise_provincial_regiments';
game.count = clamp(max - num, 0, 2);
game.department = 'southern';
@@ -7026,29 +7039,34 @@ states.raise_provincial_regiments_where = {
},
}
-function find_unused_provincial(dept) {
- for (let p = first_friendly_unit; p <= last_friendly_unit; ++p)
- if (is_provincial_unit_from(p, dept) && is_piece_unused(p))
- return p;
- return 0;
-}
-
states.raise_provincial_regiments = {
prompt() {
let can_raise = false;
if (!game.did_raise) {
- if (can_restore_provincial_regiments(game.department)) {
+ if (game.department === 'northern' && can_restore_northern_provincial_regiments()) {
+ can_raise = true;
+ gen_action('restore');
+ }
+ if (game.department === 'southern' && can_restore_southern_provincial_regiments()) {
can_raise = true;
gen_action('restore');
}
}
if (game.count > 0) {
- let list = departments[game.department];
- for (let i = 0; i < list.length; ++i) {
- let s = list[i];
- if (has_unbesieged_friendly_fortifications(s)) {
- can_raise = true;
- gen_action_space(s);
+ if (game.department === 'northern') {
+ for (let s = first_northern_department; s <= last_northern_department; ++s) {
+ if (has_unbesieged_friendly_fortifications(s)) {
+ can_raise = true;
+ gen_action_space(s);
+ }
+ }
+ }
+ if (game.department === 'southern') {
+ for (let s = first_southern_department; s <= last_southern_department; ++s) {
+ if (has_unbesieged_friendly_fortifications(s)) {
+ can_raise = true;
+ gen_action_space(s);
+ }
}
}
}
@@ -7065,8 +7083,12 @@ states.raise_provincial_regiments = {
restore() {
// TODO: restore_provincial_regiments state for manual restoring?
push_undo();
- for (let p = first_friendly_unit; p <= last_friendly_unit; ++p) {
- if (is_provincial_unit_from(p, game.department))
+ if (game.department === 'northern') {
+ for (let p = first_northern_provincial; p <= last_northern_provincial; ++p)
+ if (can_restore_unit(p))
+ restore_unit(p);
+ } else {
+ for (let p = first_southern_provincial; p <= last_southern_provincial; ++p)
if (can_restore_unit(p))
restore_unit(p);
}
@@ -7156,7 +7178,7 @@ states.bastions_repaired = {
}
function is_colonial_recruit(p) {
- return is_coureurs_unit(p) || is_ranger_unit(p) || is_light_infantry_unit(p) || is_provincial_unit(p);
+ return is_coureurs(p) || is_ranger(p) || is_light_infantry(p) || is_provincial(p);
}
events.colonial_recruits = {
@@ -7207,7 +7229,7 @@ states.colonial_recruits = {
function has_unbesieged_reduced_regular_or_light_infantry_units() {
for (let p = first_friendly_unit; p <= last_friendly_unit; ++p)
- if (is_regular_unit(p) || is_light_infantry_unit(p))
+ if (is_regular(p) || is_light_infantry(p))
if (is_piece_unbesieged(p) && is_unit_reduced(p))
return true;
return false;
@@ -7255,7 +7277,7 @@ states.restore_regular_or_light_infantry_units = {
let can_restore = false;
if (game.count > 0) {
for (let p = first_friendly_unit; p <= last_friendly_unit; ++p) {
- if (is_regular_unit(p) || is_light_infantry_unit(p)) {
+ if (is_regular(p) || is_light_infantry(p)) {
if (can_restore_unit(p)) {
can_restore = true;
gen_action_piece(p);
@@ -7280,13 +7302,6 @@ states.restore_regular_or_light_infantry_units = {
},
}
-function find_unused_friendly_militia() {
- for (let p = first_friendly_unit; p <= last_friendly_unit; ++p)
- if (is_militia_unit(p) && is_piece_unused(p))
- return p;
- return 0;
-}
-
events.call_out_militias = {
play() {
game.state = 'call_out_militias';
@@ -7313,10 +7328,19 @@ states.call_out_militias = {
}
}
if (game.count > 0) {
- for (let p = first_friendly_unit; p <= last_friendly_unit; ++p) {
- if (is_militia_unit(p) && is_unit_reduced(p) && is_militia_box(piece_space(p))) {
- can_place = true;
- gen_action_piece(p);
+ if (game.active === BRITAIN) {
+ for (let p = first_british_militia; p <= last_british_militia; ++p) {
+ if (is_piece_on_map(p) && is_unit_reduced(p)) {
+ can_place = true;
+ gen_action_piece(p);
+ }
+ }
+ } else {
+ for (let p = first_french_militia; p <= last_french_militia; ++p) {
+ if (is_piece_on_map(p) && is_unit_reduced(p)) {
+ can_place = true;
+ gen_action_piece(p);
+ }
}
}
}
@@ -7339,13 +7363,6 @@ states.call_out_militias = {
},
}
-function find_unused_ranger_unit() {
- for (let p = first_friendly_unit; p <= last_friendly_unit; ++p)
- if (is_ranger_unit(p) && is_piece_unused(p))
- return p;
- return 0;
-}
-
events.rangers = {
play() {
game.state = 'rangers';
@@ -7358,7 +7375,7 @@ states.rangers = {
view.prompt = `Place a Rangers unit at a fortification, or restore 2 to full strength.`;
let can_place = false;
if (game.count === 2) {
- if (find_unused_ranger_unit()) {
+ if (find_unused_ranger()) {
for (let s = first_space; s <= last_space; ++s) {
if (has_unbesieged_friendly_fortifications(s)) {
can_place = true;
@@ -7370,7 +7387,7 @@ states.rangers = {
}
if (game.count > 0) {
for (let p = first_friendly_unit; p <= last_friendly_unit; ++p) {
- if (is_ranger_unit(p)) {
+ if (is_ranger(p)) {
if (can_restore_unit(p)) {
can_place = true;
gen_action_piece(p);
@@ -7383,7 +7400,7 @@ states.rangers = {
},
space(s) {
push_undo();
- let p = find_unused_ranger_unit();
+ let p = find_unused_ranger();
place_piece(p, s);
game.count -= 2;
},
@@ -7397,13 +7414,6 @@ states.rangers = {
},
}
-function find_unused_french_regular_unit() {
- for (let p = first_french_unit; p <= last_french_unit; ++p)
- if (is_34_regular_unit(p) && is_piece_unused(p))
- return p;
- return 0;
-}
-
events.french_regulars = {
can_play() {
if (game.events.french_regulars)
@@ -7461,7 +7471,7 @@ states.french_regulars = {
let p = game.leader.shift();
place_piece(p, s);
} else {
- let p = find_unused_french_regular_unit();
+ let p = find_unused_french_regular();
if (p) {
place_piece(p, s);
game.count --;
@@ -7477,13 +7487,6 @@ states.french_regulars = {
},
}
-function find_unused_light_infantry_unit() {
- for (let p = first_british_unit; p <= last_british_unit; ++p)
- if (is_light_infantry_unit(p) && is_piece_unused(p))
- return p;
- return 0;
-}
-
events.light_infantry = {
play() {
clear_undo(); // drawing leader from pool
@@ -7520,7 +7523,7 @@ states.light_infantry = {
place_piece(game.leader, s);
game.leader = 0;
} else {
- let p = find_unused_light_infantry_unit();
+ let p = find_unused_light_infantry();
if (p) {
place_piece(p, s);
game.count --;
@@ -7535,13 +7538,6 @@ states.light_infantry = {
},
}
-function find_unused_british_regular_unit() {
- for (let p = first_british_unit; p <= last_british_unit; ++p)
- if (is_34_regular_unit(p) && is_piece_unused(p))
- return p;
- return 0;
-}
-
events.british_regulars = {
can_play() {
// TODO: check available ports
@@ -7585,7 +7581,7 @@ states.british_regulars = {
place_piece(game.leader, s);
game.leader = 0;
} else {
- let p = find_unused_british_regular_unit();
+ let p = find_unused_british_regular();
if (p) {
place_piece(p, s);
game.count --;
@@ -7600,13 +7596,6 @@ states.british_regulars = {
},
}
-function find_unused_highland_unit() {
- for (let p = first_british_unit; p <= last_british_unit; ++p)
- if (is_highland_unit(p) && is_piece_unused(p))
- return p;
- return 0;
-}
-
events.highlanders = {
can_play() {
// TODO: check available ports
@@ -7661,7 +7650,7 @@ states.highlanders = {
let p = game.leader.shift();
place_piece(p, s);
} else {
- let p = find_unused_highland_unit();
+ let p = find_unused_highland();
if (p) {
place_piece(p, s);
game.count --;
@@ -7675,13 +7664,6 @@ states.highlanders = {
},
}
-function find_unused_royal_american_unit() {
- for (let p = first_british_unit; p <= last_british_unit; ++p)
- if (is_royal_american_unit(p) && is_piece_unused(p))
- return p;
- return 0;
-}
-
events.royal_americans = {
can_play() {
// TODO: check available fortresses in northern or southern depts
@@ -7708,15 +7690,12 @@ states.royal_americans = {
view.prompt = `Place Royal American units at any fortress in the departments \u2014 done.`;
}
if (game.count > 0) {
- // OPTIMIZE: use a list of fortresses in the departments
- departments.northern.forEach(s => {
+ for (let s = first_northern_department; s <= last_northern_department; ++s)
if (has_unbesieged_friendly_fortress(s))
gen_action_space(s);
- });
- departments.southern.forEach(s => {
+ for (let s = first_southern_department; s <= last_southern_department; ++s)
if (has_unbesieged_friendly_fortress(s))
gen_action_space(s);
- });
} else {
gen_action_next();
}
@@ -7727,7 +7706,7 @@ states.royal_americans = {
place_piece(game.leader, s);
game.leader = 0;
} else {
- let p = find_unused_royal_american_unit();
+ let p = find_unused_royal_american();
if (p) {
place_piece(p, s);
game.count --;
@@ -7741,13 +7720,6 @@ states.royal_americans = {
},
}
-function find_unused_coureurs_unit() {
- for (let p = first_french_unit; p <= last_french_unit; ++p)
- if (is_coureurs_unit(p) && is_piece_unused(p))
- return p;
- return 0;
-}
-
events.acadians_expelled = {
can_play() {
if (game.options.acadians)
@@ -7757,13 +7729,13 @@ events.acadians_expelled = {
play() {
// TODO: acadians_expelled_halifax state for manual placing?
for (let i = 0; i < 2; ++i) {
- let p = find_unused_british_regular_unit();
+ let p = find_unused_british_regular();
place_piece(p, HALIFAX);
}
// TODO: restore_acadians_expelled state for manual restoring?
for (let p = first_french_unit; p <= last_french_unit; ++p) {
- if (is_militia_unit(p) || is_coureurs_unit(p))
+ if (is_militia(p) || is_coureurs(p))
if (can_restore_unit(p))
restore_unit(p);
}
@@ -7789,7 +7761,7 @@ states.acadians_expelled = {
},
space(s) {
push_undo();
- let p = find_unused_coureurs_unit();
+ let p = find_unused_coureurs();
if (p)
place_piece(p, s);
game.count = 0;
@@ -7928,11 +7900,15 @@ function setup_markers(m, list) {
}
function setup_leader(where, who) {
- game.location[find_leader(who)] = find_space(where);
+ who = find_unused_piece(who);
+ where = find_space(where);
+ game.location[who] = where;
}
function setup_unit(where, who) {
- game.location[find_unused_unit(who)] = find_space(where);
+ who = find_unused_piece(who);
+ where = find_space(where);
+ game.location[who] = where;
}
function setup_1757(end_year) {
@@ -8091,11 +8067,11 @@ function setup_1757(end_year) {
setup_unit("Southern Colonial Militias", "Colonial Militia");
- game.british.pool.push(find_leader("Amherst"));
- game.british.pool.push(find_leader("Bradstreet"));
- game.british.pool.push(find_leader("Forbes"));
- game.british.pool.push(find_leader("Murray"));
- game.british.pool.push(find_leader("Wolfe"));
+ game.british.pool.push(find_unused_piece("Amherst"));
+ game.british.pool.push(find_unused_piece("Bradstreet"));
+ game.british.pool.push(find_unused_piece("Forbes"));
+ game.british.pool.push(find_unused_piece("Murray"));
+ game.british.pool.push(find_unused_piece("Wolfe"));
setup_leader("eliminated", "Braddock");
setup_leader("eliminated", "Shirley");
@@ -8218,11 +8194,11 @@ function setup_1755() {
setup_unit("Will's Creek", "Virginia");
setup_unit("Will's Creek", "Maryland");
- game.british.pool.push(find_leader("Abercromby"));
- game.british.pool.push(find_leader("Bradstreet"));
- game.british.pool.push(find_leader("Loudoun"));
- game.british.pool.push(find_leader("Murray"));
- game.british.pool.push(find_leader("Webb"));
+ game.british.pool.push(find_unused_piece("Abercromby"));
+ game.british.pool.push(find_unused_piece("Bradstreet"));
+ game.british.pool.push(find_unused_piece("Loudoun"));
+ game.british.pool.push(find_unused_piece("Murray"));
+ game.british.pool.push(find_unused_piece("Webb"));
game.events.once_french_regulars = 1;
}
@@ -8456,17 +8432,21 @@ exports.view = function(state, current) {
// discard: game.discard,
// removed: game.removed,
french: {
+ hand: game.french.hand.length,
allied: game.french.allied,
stockades: game.french.stockades,
forts_uc: game.french.forts_uc,
forts: game.french.forts,
+ fortresses: game.french.fortresses,
raids: game.french.raids,
},
british: {
+ hand: game.british.hand.length,
allied: game.british.allied,
stockades: game.british.stockades,
forts_uc: game.british.forts_uc,
forts: game.british.forts,
+ fortresses: game.british.fortresses,
raids: game.british.raids,
pool: game.british.pool,
},
@@ -8478,14 +8458,10 @@ exports.view = function(state, current) {
if (game.activation)
view.activation = game.activation;
- if (game.move)
- view.move = game.move;
- if (game.force)
- view.force = game.force;
if (game.british.held)
- view.british_held = 1;
+ view.british.held = 1;
if (game.french.held)
- view.french_held = 1;
+ view.french.held = 1;
if (current === FRANCE)
view.hand = game.french.hand;
@@ -8500,8 +8476,11 @@ exports.view = function(state, current) {
}
if (current === 'Observer' || game.active !== current) {
- if (states[game.state].inactive)
+ let inactive = states[game.state].inactive;
+ if (typeof inactive === 'function')
states[game.state].inactive();
+ else if (typeof inactive === 'string')
+ view.prompt = `Waiting for ${game.active} \u2014 ${inactive}...`;
else
view.prompt = `Waiting for ${game.active} \u2014 ${game.state.replace(/_/g, " ")}...`;
} else {