summaryrefslogtreecommitdiff
path: root/rules.js
diff options
context:
space:
mode:
Diffstat (limited to 'rules.js')
-rw-r--r--rules.js234
1 files changed, 210 insertions, 24 deletions
diff --git a/rules.js b/rules.js
index 02f77ae..a25624f 100644
--- a/rules.js
+++ b/rules.js
@@ -13,6 +13,8 @@
// TODO: show discard/removed card list in UI
// TODO: defender retreat procedure needs love
+// naming: France/Britain or "The French"/"The British"
+
// features
// TODO: track 'held'
// TODO: battle VP awards
@@ -21,7 +23,7 @@
// TODO: trace supply
// TODO: infiltration
-// check rules/implementation:
+// TODO: 10.413 leaders and coureurs may follow indians home
// TODO: leaders alone - retreat (reinforcement events that place units)
// GRAPHICS: badge for pool/dead leaders
@@ -157,10 +159,6 @@ function enemy() {
return game.active === FRANCE ? BRITAIN : FRANCE;
}
-function enemy_of(role) {
- return role === FRANCE ? BRITAIN : FRANCE;
-}
-
function set_enemy_active(new_state) {
game.state = new_state;
set_active(enemy());
@@ -1292,6 +1290,13 @@ function has_friendly_supplied_drilled_troops(space) {
return false;
}
+function has_enemy_supplied_drilled_troops(space) {
+ for (let p = first_enemy_unit; p <= last_enemy_unit; ++p)
+ if (is_drilled_troops(p) && is_piece_in_space(p, space) && is_in_enemy_supply(space))
+ return true;
+ return false;
+}
+
function has_friendly_drilled_troops(space) {
for (let p = first_friendly_unit; p <= last_friendly_unit; ++p)
if (is_drilled_troops(p) && is_piece_in_space(p, space))
@@ -1810,6 +1815,11 @@ function is_in_supply(space) {
return true;
}
+function is_in_enemy_supply(space) {
+ // TODO: trace supply
+ return true;
+}
+
function list_intercept_spaces(is_lone_ld, is_lone_ax) {
let intercept = {};
@@ -2170,9 +2180,6 @@ function start_season() {
}
function end_season() {
- log("");
- log(".h2 End Season");
- log("");
if (game.Britain.hand.length > 0)
game.Britain.held = 1;
@@ -2189,13 +2196,26 @@ function end_season() {
delete player.passed;
delete enemy_player.passed;
- game.tracks.season ++;
- start_season();
+ if (game.tracks.season === EARLY) {
+ game.tracks.season = LATE;
+ start_season();
+ } else {
+ end_late_season();
+ }
}
-function end_year() {
+function end_late_season() {
+ log("");
+ log(".h2 End Late Season");
+ log("");
delete game.events.no_amphib;
delete game.events.blockhouses;
+ set_active(FRANCE);
+ game.state = 'indians_and_leaders_go_home';
+ game.go_home = {
+ indians: {}
+ };
+ resume_indians_and_leaders_go_home();
}
function start_action_phase() {
@@ -5055,8 +5075,8 @@ function next_raider_in_space(from) {
}
function raiders_go_home() {
- // RULE: raiders go home -- can go to separate locations if many available?
// Leaders, coureurs and rangers go to nearest fortification
+ // TODO: 10.413 Leaders and coureurs may follow Indians
// Indians may follow leader
// Indians go to home settlement
@@ -5127,6 +5147,179 @@ states.raiders_go_home = {
}
}
+// LATE SEASON - INDIANS AND LEADERS GO HOME
+
+function next_indian_and_leader_to_go_home() {
+ // Indians go home first
+ for (let p = first_friendly_unit; p <= last_friendly_unit; ++p) {
+ if (is_indian_unit(p) && !is_piece_inside(p)) {
+ let s = piece_space(p);
+ if (s && s != indian_home_settlement(p) && !has_unbesieged_friendly_fortifications(s))
+ return p;
+ }
+ }
+
+ // Then leaders who are left alone in the wilderness
+ for (let p = first_friendly_leader; p <= last_friendly_leader; ++p) {
+ if (!is_piece_inside(p)) {
+ let s = piece_space(p);
+ if (s && is_wilderness_or_mountain(s) && !has_friendly_units(s) && !has_unbesieged_friendly_fortifications(s))
+ return p;
+ }
+ }
+}
+
+function resume_indians_and_leaders_go_home() {
+ let who = game.go_home.who = next_indian_and_leader_to_go_home();
+ if (who && is_leader(who))
+ game.go_home.closest = find_closest_friendly_unbesieged_fortification(piece_space(who));
+}
+
+states.indians_and_leaders_go_home = {
+ prompt() {
+ let who = game.go_home.who;
+
+ if (who)
+ view.prompt = "Indians and leaders go home \u2014 " + piece_name(who) + ".";
+ else
+ view.prompt = "Indians and leaders go home \u2014 done.";
+ view.who = who;
+
+ if (!who) {
+ gen_action('next');
+ } else if (is_indian_unit(who)) {
+ // 10.412: Cherokee have no home settlement (home=0)
+ let home = indian_home_settlement(who);
+ if (home && has_friendly_allied_settlement(home) && !has_enemy_units(home))
+ gen_action_space(home);
+ else
+ gen_action('eliminate');
+ } else {
+ let from = piece_space(who);
+ game.go_home.closest.forEach(gen_action_space);
+ if (from in game.go_home.indians)
+ game.go_home.indians[from].forEach(gen_action_space);
+ }
+ },
+ space(s) {
+ push_undo();
+ let who = game.go_home.who;
+ if (is_indian_unit(who)) {
+ let from = piece_space(who);
+ if (!(s in game.go_home.indians))
+ game.go_home.indians[from] = [];
+ game.go_home.indians[from].push(s);
+ }
+ log(`${piece_name(who)} goes home to ${space_name(s)}.`);
+ move_piece_to(who, s);
+ resume_indians_and_leaders_go_home();
+ },
+ eliminate() {
+ push_undo();
+ eliminate_piece(game.go_home.who);
+ resume_indians_and_leaders_go_home();
+ },
+ next() {
+ clear_undo();
+ if (game.active === FRANCE) {
+ set_active(BRITAIN);
+ resume_indians_and_leaders_go_home();
+ } else {
+ set_active(FRANCE);
+ delete game.go_home;
+ goto_remove_raided_markers();
+ }
+ }
+}
+
+// LATE SEASON - REMOVE RAIDED MARKERS
+
+function goto_remove_raided_markers() {
+ // TODO
+ goto_winter_attrition();
+}
+
+// LATE SEASON - WINTER ATTRITION
+
+function goto_winter_attrition() {
+ // TODO
+ goto_victory_check();
+}
+
+// LATE SEASON - VICTORY CHECK
+
+function are_all_british_controlled_spaces(list) {
+ for (let i = 0; i < list.length; ++i) {
+ let s = list[i];
+ if (!is_british_controlled_space(s))
+ return false;
+ }
+ return true;
+}
+
+function are_all_british_controlled_spaces_unless_besieged(list) {
+ for (let i = 0; i < list.length; ++i) {
+ let s = list[i];
+ // TODO: 13.12 exception -- originally-British fortresses are friendly
+ if (!is_british_controlled_space(s))
+ return false;
+ }
+ return true;
+}
+
+function count_british_controlled_spaces(list) {
+ let n = 0;
+ for (let i = 0; i < list.length; ++i) {
+ let s = list[i];
+ if (is_british_controlled_space(s))
+ ++n;
+ }
+ return n;
+}
+
+function goto_victory_check() {
+ if (are_all_british_controlled_spaces(fortresses) && are_all_british_controlled_spaces([NIAGARA, OHIO_FORKS]))
+ return goto_game_over(BRITAIN, "Sudden Death: The British control all fortresses, Niagara, and Ohio Forks.");
+ if (game.tracks.vp >= 11)
+ return goto_game_over(FRANCE, "Sudden Death: France has 11 or more VP.");
+ if (game.tracks.vp <= -11)
+ return goto_game_over(BRITAIN, "Sudden Death: Britain has 11 or more VP.");
+ if (game.tracks.year === 1760 && game.tracks.vp >= 8)
+ return goto_game_over(FRANCE, "Sudden Death: France has 8 or more VP in 1760.");
+ if (game.tracks.year === 1761 && game.tracks.vp >= 8)
+ return goto_game_over(FRANCE, "Sudden Death: France has 5 or more VP in 1761.");
+ if (game.tracks.year === game.tracks.end_year) {
+ if (game.tracks.year === 1759) {
+ if (are_all_british_controlled_spaces_unless_besieged(originally_british_fortresses) &&
+ count_british_controlled_spaces([QUEBEC, MONTREAL, NIAGARA, OHIO_FORKS]) >= 2)
+ return goto_game_over(BRITAIN, "Britain control all originally-British fortresses and two of Québec, Montréal, Niagara, and Ohio Forks.");
+ if (game.tracks.vp >= 1)
+ return goto_game_over(FRANCE, "France has at least 1 VP.");
+ if (game.tracks.vp <= -1)
+ return goto_game_over(BRITAIN, "Britain has at least 1 VP.");
+ }
+ if (game.tracks.year === 1762) {
+ if (game.tracks.vp >= 1)
+ return goto_game_over(FRANCE, "France has at least 1 VP.");
+ if (game.tracks.vp <= -5)
+ return goto_game_over(BRITAIN, "Britain has at least 5 VP.");
+ }
+ return goto_game_over(FRANCE, "Draw.");
+ } else {
+ game.tracks.year++;
+ start_year();
+ }
+}
+
+function goto_game_over(result, victory) {
+ log("");
+ log(victory);
+ game.state = 'game_over';
+ game.active = 'None';
+ game.result = result;
+ game.victory = victory;
+}
+
// DEMOLITION
function demolish(s) {
@@ -6244,7 +6437,7 @@ events.quiberon_bay = {
return true;
if (is_friendly_controlled_space(LOUISBOURG))
return true;
- if (game.year > 1759)
+ if (game.tracks.year > 1759)
return true;
return false;
},
@@ -6382,7 +6575,7 @@ events.troop_transports_and_local_enlistments = {
events.victories_in_germany_release_troops_and_finances_for_new_world = {
can_play() {
- if (game.year <= 1755)
+ if (game.tracks.year <= 1755)
return false;
if (game.active === FRANCE) {
if (game.events.quiberon)
@@ -6750,7 +6943,7 @@ function find_unused_highland_unit() {
events.highlanders = {
can_play() {
// TODO: check available ports
- if (game.events.pitt || game.year > 1758)
+ if (game.events.pitt || game.tracks.year > 1758)
return true;
return false;
},
@@ -7512,15 +7705,8 @@ function load_game_state(state) {
exports.resign = function (state, current) {
load_game_state(state);
- if (game.state !== 'game_over') {
- log("");
- log(current + " resigned.");
- game.active = current;
- game.state = 'game_over';
- game.victory = current + " resigned.";
- game.result = enemy(current);
- game.active = 'None';
- }
+ if (game.state !== 'game_over')
+ goto_game_over(enemy(), current + " resigned.");
return state;
}