From 005a221f87a6b1a24ee9ea38c2e57798401146fe Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Sat, 9 Dec 2023 17:28:44 +0100 Subject: Inkerman & The Fog. --- rules.js | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 81 insertions(+), 21 deletions(-) (limited to 'rules.js') diff --git a/rules.js b/rules.js index 3e77533..7316a03 100644 --- a/rules.js +++ b/rules.js @@ -29,7 +29,7 @@ TODO: extra input steps */ -// TODO: allow placing dice on full special formations? +// TODO: morale cube limit (cannot place on special if maxed) // TODO: fizzle when action says to take cards from other dice? const data = require("./data.js") @@ -196,6 +196,14 @@ const S8_CLINTON = find_card(8, "Clinton") const S8_GRANT = find_card(8, "Grant") const S8_HESSIANS = find_card(8, "Hessians") +const S37_INKERMAN = find_scenario(37) +const S37_PAULOFFS_LEFT = find_card(37, "Pauloff's Left") +const S37_PAULOFFS_RIGHT = find_card(37, "Pauloff's Right") +const S37_BRITISH_TROOPS = find_card(37, "British Troops") +const S37_FRENCH_TROOPS = find_card(37, "French Troops") +const S37_SOIMONOFF = find_card(37, "Soimonoff") +const S37_THE_FOG = find_card(37, "The Fog") + // === SETUP === exports.setup = function (seed, scenario, options) { @@ -271,6 +279,10 @@ exports.setup = function (seed, scenario, options) { log(".h2 " + info.date) log("") + if (game.scenario === S37_INKERMAN) { + map_set(game.cubes, S37_THE_FOG, 3) + } + goto_action_phase() return game @@ -319,7 +331,7 @@ function add_cubes(c, n) { function remove_cubes(c, n) { let old = map_get(game.cubes, c, 0) - map_set(game.cubes, c, Math.min(0, old - n)) + map_set(game.cubes, c, Math.max(0, old - n)) } function add_sticks(c, n) { @@ -423,9 +435,6 @@ function check_impossible_to_attack_victory() { for (let c of game.front[p]) if (is_card_attack_with_target_in_play(c)) return false - for (let c of game.reserve[p]) - if (is_card_attack_with_target_in_play(c)) - return false return true } @@ -1119,10 +1128,15 @@ function is_mandatory_reaction(c, a) { } function can_take_action(c, a) { - if (a.type === "Attack" && find_target_of_attack(a) < 0) - return false - if (a.type === "Command" && find_first_target_of_command(a) < 0) - return false + if (a.type === "Attack") { + if (find_target_of_attack(a) < 0) + return false + } + + if (a.type === "Command") { + if (find_first_target_of_command(c, a) < 0) + return false + } if (game.scenario === S8_BROOKLYN_HEIGHTS) { if (c === S8_CLINTON) { @@ -1259,7 +1273,7 @@ function goto_take_action(c, ix) { game.state = "bombard" break case "Command": - game.state = "command" + goto_command() break } } @@ -1278,12 +1292,18 @@ function find_target_of_attack(a) { return -1 } -function find_first_target_of_command(a) { - for (let c of a.target_list) { - if (set_has(game.reserve[0], c)) - return c - if (set_has(game.reserve[1], c)) - return c +function find_first_target_of_command(c, a) { + + if (game.scenario === S37_INKERMAN) { + if (c === S37_THE_FOG) + return S37_THE_FOG + } + + for (let t of a.target_list) { + if (set_has(game.reserve[0], t)) + return t + if (set_has(game.reserve[1], t)) + return t } return -1 } @@ -1332,6 +1352,13 @@ function goto_attack() { } } + if (game.scenario === S37_INKERMAN) { + // Until the first Fog Cube is lifted. + if (map_get(game.cubes, S37_THE_FOG, 0) === 3) { + game.hits -= 1 + } + } + if (card_has_rule(game.target, "suffer_1_less_1_max")) game.hits = Math.max(0, Math.min(1, game.hits - 1)) if (card_has_rule(game.target, "suffer_1_less")) @@ -1366,6 +1393,22 @@ function resume_attack() { end_action_phase() } +// === COMMAND === + +function goto_command() { + + if (game.scenario === S37_INKERMAN && game.selected === S37_THE_FOG) { + log("The Fog Lifts...") + remove_cubes(S37_THE_FOG, 1) + remove_dice(game.selected) + end_action_phase() + return + } + + game.state = "command" +} + + states.command = { prompt() { let list = find_all_targets_of_command(current_action()) @@ -1388,7 +1431,14 @@ states.command = { } } - if (find_first_target_of_command(current_action())) { + if (game.scenario === S37_INKERMAN) { + if (c === S37_PAULOFFS_LEFT) { + log("Morale Cube added to Russian side.") + game.morale[0] += 1 + } + } + + if (find_first_target_of_command(game.selected, current_action()) < 0) { pay_for_action(game.selected) end_action_phase() } @@ -1672,6 +1722,7 @@ function get_attack_hits(c, a) { return 1 case "1 hit per die.": case "1 hit per die. 1 self per action.": + case "1 hit per die. Ignore first target until it comes out of Reserve.": return count_dice_on_card(c) case "1 hit per pair.": case "1 hit per pair. 1 self per action.": @@ -1687,6 +1738,7 @@ function get_attack_self(c, a) { throw new Error("invalid attack effect: " + a.effect) case "1 hit.": case "1 hit per die.": + case "1 hit per die. Ignore first target until it comes out of Reserve.": case "1 hit per pair.": return 0 case "1 hit. 1 self per action.": @@ -1877,10 +1929,18 @@ states.pursuit = { // === RESERVE === -function should_enter_reserve(rc) { - let reserve = data.cards[rc].reserve - for (let c of reserve) - if (!set_has(game.front[0], c) && !set_has(game.front[1], c)) +function should_enter_reserve(c) { + let reserve = data.cards[c].reserve + + if (game.scenario === S37_INKERMAN) { + if (c === S37_BRITISH_TROOPS) + return map_get(game.cubes, S37_THE_FOG, 0) === 1 + if (c === S37_FRENCH_TROOPS) + return map_get(game.cubes, S37_THE_FOG, 0) === 0 + } + + for (let t of reserve) + if (!set_has(game.front[0], t) && !set_has(game.front[1], t)) return true return false } -- cgit v1.2.3