summaryrefslogtreecommitdiff
path: root/rules.js
diff options
context:
space:
mode:
authorTor Andersson <tor@ccxvii.net>2022-07-26 18:08:01 +0200
committerTor Andersson <tor@ccxvii.net>2022-11-17 13:11:26 +0100
commit0ec21335f4a5b7c77c1c61c1944f3567cbdfa66c (patch)
tree2fe2f8b1ac9ccc5180449b5ee7ab4efd78e54108 /rules.js
parentca6ff126e74dd6bde8af32f6a3f945394e5d3c26 (diff)
downloadrommel-in-the-desert-0ec21335f4a5b7c77c1c61c1944f3567cbdfa66c.tar.gz
first/last enemy unit
Diffstat (limited to 'rules.js')
-rw-r--r--rules.js189
1 files changed, 77 insertions, 112 deletions
diff --git a/rules.js b/rules.js
index 30001e3..274ca4f 100644
--- a/rules.js
+++ b/rules.js
@@ -1,16 +1,17 @@
"use strict"
-// TODO: BLITZ TURN
-
// TODO: fortress supply
// TODO: fortress battles mandatory combat!
+// TODO: legal pass withdrawal moves
+// TODO: raiders
+// TODO: MINEFIELDS
// TODO: FORCED MARCHES
-// TODO: SUPPLY CARDS (playing and revealing and choosing turn option)
+// TODO: SUPPLY COMMITMENT
// TODO: BUILDUP
+// TODO: setup scenario specials
-// TODO: first_friendly_unit / for_each_friendly_unit
-
+// TODO: clean up "can retreat" checks
// TODO: when is "fired" status cleared?
// TODO: cache_valid, cache_axis, cache_allied (presence and disruption per hex)
@@ -24,51 +25,6 @@
// RULES: disrupted units routed again in second enemy turn, will they still recover?
// assume yes, easy to change (remove from game.recover set if routed)
-// TODO: check that full retreat of all units is possible for pass regroup moves!
-// TODO: pass withdrawal moves must reduce supply net
-
-// TODO: forced marches (force march at first move, remember where to for later, or separate step)
-// TODO: raider
-
-// unit state: location (8 bits), supply source (3 bits), steps (2 bits), disrupted (1 bit)
-
-// SEQUENCE
-// --------
-// Supply check
-// Turn option
-// Movement
-// declare moves
-// normal moves
-// rout
-// retreats
-// declare full/partial retreats
-// probe combat
-// pursuit fire
-// withdraw
-// rout
-// pursuit fire
-// withdraw
-// forced marches
-// refuse battle
-// pursuit fire
-// withdraw
-// rout
-// pursuit fire
-// withdraw
-// Combat
-// declare active
-// declare assault
-// resolve
-// defensive fire
-// rout
-// offensive fire
-// rout
-// Blitz Movement
-// Blitz Combat
-// Final supply check
-// rout
-// Reveal supply cards -> next player
-
const max = Math.max
const min = Math.min
const abs = Math.abs
@@ -78,13 +34,35 @@ var after_rout = {}
var game = null
var view = null
-let { all_hexes, hex_exists, hex_road, side_road, side_limit, hex_name, units, regions } = require("./data")
+const { all_hexes, hex_exists, hex_road, side_road, side_limit, hex_name, units, regions } = require("./data")
const first_axis_unit = 0
const first_allied_unit = units.findIndex(item => item.nationality === 'allied')
const last_axis_unit = first_allied_unit - 1
const last_allied_unit = units.length - 1
+var first_friendly_unit, last_friendly_unit
+var first_enemy_unit, last_friendly_unit
+
+function update_aliases() {
+ if (game.active === AXIS) {
+ first_friendly_unit = first_axis_unit
+ last_friendly_unit = last_axis_unit
+ first_enemy_unit = first_allied_unit
+ last_enemy_unit = last_allied_unit
+ } else {
+ first_friendly_unit = first_allied_unit
+ last_friendly_unit = last_allied_unit
+ first_enemy_unit = first_axis_unit
+ last_enemy_unit = last_axis_unit
+ }
+}
+
+function load_state(state) {
+ game = state
+ update_aliases()
+}
+
function debug_hexes3(n, list) {
console.log("--", n, "--")
list = list.map((x,i) => hex_exists[i] ? x : "")
@@ -246,6 +224,8 @@ function is_hex_or_adjacent_to(x, where) {
// === UNIT STATE ===
+// location (8 bits), supply source (3 bits), steps lost (2 bits), disrupted (1 bit)
+
function apply_select(u) {
if (game.selected === u)
game.selected = -1
@@ -411,18 +391,6 @@ function unit_hp(u) {
return unit_steps(u) * unit_hp_per_step(u)
}
-function is_friendly_unit(u) {
- if (game.active === AXIS)
- return is_axis_unit(u)
- return is_allied_unit(u)
-}
-
-function is_enemy_unit(u) {
- if (game.active === ALLIED)
- return is_axis_unit(u)
- return is_allied_unit(u)
-}
-
function is_friendly_hex(x) {
if (game.active === AXIS)
return is_axis_hex(x)
@@ -571,6 +539,12 @@ function has_unshielded_disrupted_enemy_unit(x) {
return has_unshielded_disrupted_allied_unit(x)
}
+function has_unshielded_disrupted_friendly_unit(x) {
+ if (game.active === ALLIED)
+ return has_unshielded_disrupted_allied_unit(x)
+ return has_unshielded_disrupted_axis_unit(x)
+}
+
function is_overrun_hex(x) {
return has_undisrupted_friendly_unit(x) && has_unshielded_disrupted_enemy_unit(x)
}
@@ -685,66 +659,55 @@ function for_each_allied_unit(fn) {
}
function for_each_friendly_unit(fn) {
- // TODO: first/last_enemy_unit
- for (let u = 0; u < units.length; ++u)
- if (is_friendly_unit(u))
- fn(u)
+ for (let u = first_friendly_unit; u <= last_friendly_unit; ++u)
+ fn(u)
}
function for_each_enemy_unit(fn) {
- // TODO: first/last_enemy_unit
- for (let u = 0; u < units.length; ++u)
- if (is_enemy_unit(u))
- fn(u)
+ for (let u = first_enemy_unit; u <= last_enemy_unit; ++u)
+ fn(u)
}
function for_each_friendly_unit_in_hex(x, fn) {
- // TODO: first/last_enemy_unit
- for (let u = 0; u < units.length; ++u)
- if (is_friendly_unit(u) && unit_hex(u) === x)
+ for (let u = first_friendly_unit; u <= last_friendly_unit; ++u)
+ if (unit_hex(u) === x)
fn(u)
}
function for_each_undisrupted_friendly_unit_in_hex(x, fn) {
- // TODO: first/last_enemy_unit
- for (let u = 0; u < units.length; ++u)
- if (is_friendly_unit(u) && !is_unit_disrupted(u) && unit_hex(u) === x)
+ for (let u = first_friendly_unit; u <= last_friendly_unit; ++u)
+ if (!is_unit_disrupted(u) && unit_hex(u) === x)
fn(u)
}
function for_each_undisrupted_and_unmoved_friendly_unit_in_hex(x, fn) {
- // TODO: first/last_enemy_unit
- for (let u = 0; u < units.length; ++u)
- if (is_friendly_unit(u) && !is_unit_disrupted(u) && unit_hex(u) === x && !is_unit_moved(u))
+ for (let u = first_friendly_unit; u <= last_friendly_unit; ++u)
+ if (!is_unit_disrupted(u) && unit_hex(u) === x && !is_unit_moved(u))
fn(u)
}
function has_undisrupted_and_moved_friendly_unit_in_hex(x) {
- // TODO: first/last_enemy_unit
- for (let u = 0; u < units.length; ++u)
- if (is_friendly_unit(u) && !is_unit_disrupted(u) && unit_hex(u) === x && is_unit_moved(u))
+ for (let u = first_friendly_unit; u <= last_friendly_unit; ++u)
+ if (!is_unit_disrupted(u) && unit_hex(u) === x && is_unit_moved(u))
return true
}
function for_each_undisrupted_friendly_unit_in_hex_or_adjacent(x, fn) {
- // TODO: first/last_enemy_unit
- for (let u = 0; u < units.length; ++u)
- if (is_friendly_unit(u) && !is_unit_disrupted(u) && is_hex_or_adjacent_to(unit_hex(u), x))
+ for (let u = first_friendly_unit; u <= last_friendly_unit; ++u)
+ if (!is_unit_disrupted(u) && is_hex_or_adjacent_to(unit_hex(u), x))
fn(u)
}
function for_each_enemy_unit_in_hex(x, fn) {
- // TODO: first/last_enemy_unit
- for (let u = 0; u < units.length; ++u)
- if (is_enemy_unit(u) && unit_hex(u) === x)
+ for (let u = first_enemy_unit; u <= last_enemy_unit; ++u)
+ if (unit_hex(u) === x)
fn(u)
}
function for_each_undisrupted_enemy_unit_in_hex(x, fn) {
- // TODO: first/last_enemy_unit
- for (let u = 0; u < units.length; ++u)
- if (is_enemy_unit(u) && !is_unit_disrupted(u) && unit_hex(u) === x)
+ for (let u = first_enemy_unit; u <= last_enemy_unit; ++u)
+ if (!is_unit_disrupted(u) && unit_hex(u) === x)
fn(u)
}
@@ -1361,6 +1324,22 @@ function find_valid_regroup_destinations(from, rommel) {
function set_active_player() {
game.active = game.phasing
+ update_aliases()
+}
+
+function set_passive_player() {
+ if (game.phasing === AXIS)
+ game.active = ALLIED
+ else
+ game.active = AXIS
+ update_aliases()
+}
+
+function set_enemy_player() {
+ if (is_active_player())
+ set_passive_player()
+ else
+ set_active_player()
}
function is_active_player() {
@@ -1379,20 +1358,6 @@ function is_allied_player() {
return game.active === ALLIED
}
-function set_passive_player() {
- if (game.phasing === AXIS)
- game.active = ALLIED
- else
- game.active = AXIS
-}
-
-function set_enemy_player() {
- if (game.active === AXIS)
- game.active = ALLIED
- else
- game.active = AXIS
-}
-
function end_player_turn() {
set_clear(game.partial_retreats)
@@ -1740,7 +1705,6 @@ states.regroup_move_destination = {
function end_move_phase() {
game.side_limit = {}
- game.rommel = 0
game.from1 = game.from2 = game.to1 = game.to2 = 0
// TODO: forced marches
goto_refuse_battle()
@@ -3716,7 +3680,8 @@ function setup(name) {
game.tobruk = setup_fortress(scenario, TOBRUK)
log_h2("Axis Deployment")
- game.active = 'Axis'
+ game.phasing = AXIS
+ set_active_player()
game.state = 'free_deployment'
game.selected = -1
}
@@ -3807,7 +3772,7 @@ exports.setup = function (seed, scenario, options) {
}
exports.view = function(state, current) {
- game = state
+ load_state(state)
view = {
month: game.month,
@@ -3841,7 +3806,7 @@ exports.view = function(state, current) {
exports.query = function (state, current, q) {
if (q === 'supply') {
- game = state
+ load_state(state)
update_supply_networks()
return {
axis_supply: game.axis_supply,
@@ -4051,7 +4016,7 @@ states.game_over = {
}
exports.resign = function (state, current) {
- game = state
+ load_state(state)
if (game.state !== 'game_over') {
for (let opponent of exports.roles) {
if (opponent !== current) {
@@ -4064,7 +4029,7 @@ exports.resign = function (state, current) {
}
exports.action = function (state, current, action, arg) {
- game = state
+ load_state(state)
// Object.seal(game) // XXX: don't allow adding properties
let S = states[game.state]
if (S && action in S) {