diff options
Diffstat (limited to 'rules.js')
-rw-r--r-- | rules.js | 199 |
1 files changed, 163 insertions, 36 deletions
@@ -1471,11 +1471,6 @@ function stop_move(who) { game.state = 'move_who' } -// === PURSUIT FIRE === - -function goto_pursuit_fire() { -} - // === REFUSE BATTLE === function gen_withdraw_group_move(who, from) { @@ -1485,6 +1480,7 @@ function gen_withdraw_group_move(who, from) { } function goto_refuse_battle() { + clear_undo() if (game.active_battles.length > 0) { set_passive_player() game.state = 'refuse_battle' @@ -1504,13 +1500,10 @@ states.refuse_battle = { hex(x) { push_undo() set_delete(game.active_battles, x) - game.battle = x - game.from1 = x + game.pursuit = x goto_pursuit_fire(x) - } + }, next() { - clear_undo() - set_active_player() goto_combat_phase() } } @@ -1561,6 +1554,8 @@ states.refuse_battle_to = { // ==== COMBAT PHASE === function goto_combat_phase() { + clear_undo() + set_active_player() game.state = 'select_active_battles' } @@ -1667,7 +1662,7 @@ const xxx_fire = { }, } -function count_normal_steps() { +function count_normal_steps_in_battle() { let steps = [ 0, 0, 0, 0 ] for (let u = 0; u < units.length; ++u) if (is_enemy_unit(u) && unit_hex(u) === game.battle) @@ -1675,7 +1670,7 @@ function count_normal_steps() { return steps } -function count_elite_steps() { +function count_elite_steps_in_battle() { let steps = [ 0, 0, 0, 0 ] for (let u = 0; u < units.length; ++u) if (is_enemy_unit(u) && unit_hex(u) === game.battle) @@ -1683,7 +1678,7 @@ function count_elite_steps() { return steps } -function count_hp() { +function count_hp_in_battle() { let hp = [ 0, 0, 0, 0 ] for (let u = 0; u < units.length; ++u) if (is_enemy_unit(u) && unit_hex(u) === game.battle) @@ -1691,11 +1686,35 @@ function count_hp() { return hp } +function count_normal_steps_in_pursuit() { + let steps = 0 + for (let u = 0; u < units.length; ++u) + if (is_enemy_unit(u) && unit_hex(u) === game.pursuit) + steps += unit_steps(u) + return steps +} + +function count_elite_steps_in_pursuit() { + let steps = 0 + for (let u = 0; u < units.length; ++u) + if (is_enemy_unit(u) && unit_hex(u) === game.pursuit) + steps += unit_steps(u) + return steps +} + +function count_hp_in_pursuit() { + let hp = 0 + for (let u = 0; u < units.length; ++u) + if (is_enemy_unit(u) && unit_hex(u) === game.pursuit) + hp += unit_hp(u) + return hp +} + const xxx_fire_target = { prompt() { view.prompt = `Select a target class.` - let hp = count_hp() + let hp = count_hp_in_battle() for (let i = 0; i < 4; ++i) hp[i] -= game.hits[i] @@ -1760,32 +1779,30 @@ const xxx_fire_hits = { prompt() { view.prompt = `Apply hits.` - let normal_steps = count_normal_steps() - let elite_steps = count_elite_steps() + let normal_steps = count_normal_steps_in_battle() + let elite_steps = count_elite_steps_in_battle() let done = true - for (let u = 0; u < units.length; ++u) { - if (is_friendly_unit(u) && unit_hex(u) === game.battle) { - let c = unit_class(u) - if (is_unit_elite(u)) { - if (game.hits[c] >= 2) { + for_each_friendly_unit_in_hex(game.battle, u => { + let c = unit_class(u) + if (is_unit_elite(u)) { + if (game.hits[c] >= 2) { + gen_action_unit(u) + done = false + } + } else { + if (game.hits[c] >= 1) { + // If mixed elite and non-elite: must assign ALL damage. + if (elite_steps[c] > 0 && normal_steps[c] === 1 && (game.hits[c] & 1) === 0) { + // Eliminating the last non-elite must not leave an odd + // number of hits remaining. + } else { gen_action_unit(u) done = false } - } else { - if (game.hits[c] >= 1) { - // If mixed elite and non-elite: must assign ALL damage. - if (elite_steps[c] > 0 && normal_steps[c] === 1 && (game.hits[c] & 1) === 0) { - // Eliminating the last non-elite must not leave an odd - // number of hits remaining. - } else { - gen_action_unit(u) - done = false - } - } } } - } + }) if (done) gen_action_next() }, @@ -1875,6 +1892,113 @@ function end_combat_phase() { end_player_turn() } +// === PURSUIT FIRE === + +function goto_pursuit_fire() { + clear_undo() + set_active_player() + game.state = 'pursuit_fire' + game.hits = 0 +} + +function slowest_enemy_unit_speed(where) { + let r = 4 + for (let u = 0; u < units.length; ++u) { + if (is_enemy_unit(u) && unit_hex(u) === where) { + let s = unit_speed(u) + if (s < r) + r = s + } + } + return r +} + +function roll_pursuit_fire(n) { + for (let i = 0; i < n; ++i) { + let roll = random(6) + 1 + log(`Pursuit fire ${roll}.`) + if (roll >= 4) + game.hits++ + } +} + +states.pursuit_fire = { + inactive: "pursuit fire (fire)", + prompt() { + view.prompt = `Pursuit Fire.` + let slowest = slowest_enemy_unit_speed(game.pursuit) + for_each_friendly_unit_in_hex(game.pursuit, u => { + if (unit_speed(u) >= slowest && !is_unit_fired(u)) + gen_action_unit(u) + }) + gen_action('next') + }, + unit(who) { + let slowest = slowest_enemy_unit_speed(game.pursuit) + if (unit_speed(who) > slowest) + roll_pursuit_fire(2) + else + roll_pursuit_fire(1) + set_unit_fired(who) + }, + next() { + goto_pursuit_hits() + } +} + +function goto_pursuit_hits() { + if (game.hits > 0) { + set_passive_player() + let hp = count_hp_in_pursuit() + if (game.hits > hp) + game.hits = hp + game.state = 'pursuit_hits' + } else { + end_pursuit_fire() + } +} + +states.pursuit_hits = { + inactive: "pursuit fire (hits)", + prompt() { + view.prompt = `Pursuit Fire: Apply ${game.hits} hits.` + + let normal_steps = count_normal_steps_in_pursuit() + let elite_steps = count_elite_steps_in_pursuit() + + let done = true + for_each_friendly_unit_in_hex(game.pursuit, u => { + if (is_unit_elite(u)) { + if (game.hits >= 2) { + gen_action_unit(u) + done = false + } + } else { + if (game.hits >= 1) { + // If mixed elite and non-elite: must assign ALL damage. + if (elite_steps > 0 && normal_steps === 1 && (game.hits & 1) === 0) { + // Eliminating the last non-elite must not leave an odd + // number of hits remaining. + } else { + gen_action_unit(u) + done = false + } + } + } + }) + if (done) + gen_action('next') + }, + unit(who) { + push_undo() + game.hits -= reduce_unit(who) + }, + next() { + clear_undo() + end_pursuit_fire() + }, +} + // === DEPLOYMENT === states.free_deployment = { @@ -2454,8 +2578,10 @@ exports.setup = function (seed, scenario, options) { move_road: 4, // combat + partial_retreats: [], // remember partial retreats to forbid initiating combat active_battles: [], assault_battles: [], + pursuit: 0, battle: 0, fired: [], hits: null, @@ -2492,10 +2618,11 @@ exports.view = function(state, current) { if (game.to1) view.to1 = game.to1 if (game.to2) view.to2 = game.to2 + if (game.pursuit) view.pursuit = game.pursuit if (game.battle) view.battle = game.battle - if (game.fired) view.fired = game.fired - if (game.hits) view.hits = game.hits - if (game.flash) view.flash = game.flash + if (game.fired !== undefined) view.fired = game.fired + if (game.hits !== undefined) view.hits = game.hits + if (game.flash !== undefined) view.flash = game.flash return common_view(current) } |