summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor@ccxvii.net>2022-09-21 14:01:19 +0200
committerTor Andersson <tor@ccxvii.net>2022-11-17 13:11:27 +0100
commitf8c759a3d71576463c3a9fa71a1e60d621a977ce (patch)
tree85923fa68d56e9cf8d8bbc1482a1f7eae376de62
parentcecaea613d4ac501128413fcf01b4261c8bc2985 (diff)
downloadrommel-in-the-desert-f8c759a3d71576463c3a9fa71a1e60d621a977ce.tar.gz
Update common functions from utility library.
-rw-r--r--rules.js284
1 files changed, 164 insertions, 120 deletions
diff --git a/rules.js b/rules.js
index 2301087..2f1d249 100644
--- a/rules.js
+++ b/rules.js
@@ -1,5 +1,11 @@
"use strict"
+// TODO: retreat withdraw co-exist with disrupted enemy - hexside control (wait for Craig)
+// TODO: buildup steps in friendly battle hex
+// TODO: rout during probe combat?
+// TODO: allow one-hex regroup moves? (failed forced march abuse)
+// TODO: rewrite regroup to group if only one hex moved (failed forced march abuse)
+
const max = Math.max
const min = Math.min
const abs = Math.abs
@@ -8,6 +14,11 @@ var states = {}
var game = null
var view = null
+const {
+ all_hexes, hex_exists, hex_road, side_road, side_limit, hex_name, regions,
+ unit_name, unit_appearance, unit_elite, unit_class, unit_speed, unit_max_steps,
+} = require("./data.js")
+
var after_rout_table = {
end_battle: end_battle,
end_refuse_battle_move_2: end_refuse_battle_move_2,
@@ -18,11 +29,6 @@ var after_rout_table = {
goto_initial_supply_check_rout: goto_initial_supply_check_rout,
}
-const {
- all_hexes, hex_exists, hex_road, side_road, side_limit, hex_name, regions,
- unit_name, unit_appearance, unit_elite, unit_class, unit_speed, unit_max_steps,
-} = require("./data")
-
function debug_hexes3(n, list) {
console.log("--", n, "--")
list = list.map((x,i) => hex_exists[i] ? x : "")
@@ -2965,8 +2971,8 @@ states.select_moves = {
view.prompt = `Movement: Designate ${game.turn_option} move.`
}
- let can_group_move = has_valid_group_move_left()
- let can_regroup_move = has_valid_regroup_move_left()
+ let can_group_move = has_valid_group_move_left() ? 1 : 0
+ let can_regroup_move = has_valid_regroup_move_left() ? 1 : 0
if (game.phasing === AXIS && game.scenario !== "1940" && game.rommel === 0) {
if (game.turn_option === 'offensive' || game.turn_option === 'blitz') {
@@ -3850,8 +3856,7 @@ states.forced_marches = {
set_unit_disrupted(who)
}
}
- game.forced.splice(ix, 1)
-
+ array_remove(game.forced, ix)
resume_forced_marches()
}
}
@@ -7152,122 +7157,11 @@ function gen_action_forced_march(x) {
// === COMMON TEMPLATE ===
-function random(range) {
- // https://www.ams.org/journals/mcom/1999-68-225/S0025-5718-99-00996-5/S0025-5718-99-00996-5.pdf
- return (game.seed = game.seed * 200105 % 34359738337) % range
-}
-
function roll_die() {
clear_undo()
return random(6) + 1
}
-// Sorted array treated as Set (for JSON)
-function set_index(set, item) {
- let a = 0
- let b = set.length - 1
- while (a <= b) {
- let m = (a + b) >> 1
- let x = set[m]
- if (item < x)
- b = m - 1
- else if (item > x)
- a = m + 1
- else
- return m
- }
- return -1
-}
-
-function set_has(set, item) {
- return set_index(set, item) >= 0
-}
-
-function set_add(set, item) {
- let a = 0
- let b = set.length - 1
- while (a <= b) {
- let m = (a + b) >> 1
- let x = set[m]
- if (item < x)
- b = m - 1
- else if (item > x)
- a = m + 1
- else
- return
- }
- set.splice(a, 0, item)
-}
-
-function set_delete(set, item) {
- let i = set_index(set, item)
- if (i >= 0)
- set.splice(i, 1)
-}
-
-function set_clear(set) {
- set.length = 0
-}
-
-function set_toggle(set, item) {
- if (set_has(set, item))
- set_delete(set, item)
- else
- set_add(set, item)
-}
-
-function deep_copy(original) {
- if (Array.isArray(original)) {
- let n = original.length
- let copy = new Array(n)
- for (let i = 0; i < n; ++i) {
- let v = original[i]
- if (typeof v === "object" && v !== null)
- copy[i] = deep_copy(v)
- else
- copy[i] = v
- }
- return copy
- } else {
- let copy = {}
- for (let i in original) {
- let v = original[i]
- if (typeof v === "object" && v !== null)
- copy[i] = deep_copy(v)
- else
- copy[i] = v
- }
- return copy
- }
-}
-
-function push_undo() {
- let copy = {}
- for (let k in game) {
- let v = game[k]
- if (k === "undo") continue
- else if (k === "log") v = v.length
- else if (typeof v === "object" && v !== null) v = deep_copy(v)
- copy[k] = v
- }
- game.undo.push(copy)
-}
-
-function pop_undo() {
- let save_log = game.log
- let save_undo = game.undo
- let state = save_undo.pop()
- save_log.length = state.log
- state.log = save_log
- state.undo = save_undo
- load_state(state)
-}
-
-function clear_undo() {
- if (game.undo.length > 0)
- game.undo = []
-}
-
function log_br() {
if (game.log.length > 0 && game.log[game.log.length-1] !== "")
game.log.push("")
@@ -7382,3 +7276,153 @@ function common_view(current) {
}
return view
}
+
+// === COMMON LIBRARY ===
+
+function random(range) {
+ // An MLCG using integer arithmetic with doubles.
+ // https://www.ams.org/journals/mcom/1999-68-225/S0025-5718-99-00996-5/S0025-5718-99-00996-5.pdf
+ // m = 2**35 − 31
+ return (game.seed = game.seed * 200105 % 34359738337) % range
+}
+
+// remove item at index (faster than splice)
+function array_remove(array, index) {
+ let n = array.length
+ for (let i = index + 1; i < n; ++i)
+ array[i - 1] = array[i]
+ array.length = n - 1
+ return array
+}
+
+// insert item at index (faster than splice)
+function array_insert(array, index, item) {
+ for (let i = array.length; i > index; --i)
+ array[i] = array[i - 1]
+ array[index] = item
+ return array
+}
+
+function set_clear(set) {
+ set.length = 0
+}
+
+function set_has(set, item) {
+ let a = 0
+ let b = set.length - 1
+ while (a <= b) {
+ let m = (a + b) >> 1
+ let x = set[m]
+ if (item < x)
+ b = m - 1
+ else if (item > x)
+ a = m + 1
+ else
+ return true
+ }
+ return false
+}
+
+function set_add(set, item) {
+ let a = 0
+ let b = set.length - 1
+ while (a <= b) {
+ let m = (a + b) >> 1
+ let x = set[m]
+ if (item < x)
+ b = m - 1
+ else if (item > x)
+ a = m + 1
+ else
+ return set
+ }
+ return array_insert(set, a, item)
+}
+
+function set_delete(set, item) {
+ let a = 0
+ let b = set.length - 1
+ while (a <= b) {
+ let m = (a + b) >> 1
+ let x = set[m]
+ if (item < x)
+ b = m - 1
+ else if (item > x)
+ a = m + 1
+ else
+ return array_remove(set, m)
+ }
+ return set
+}
+
+function set_toggle(set, item) {
+ let a = 0
+ let b = set.length - 1
+ while (a <= b) {
+ let m = (a + b) >> 1
+ let x = set[m]
+ if (item < x)
+ b = m - 1
+ else if (item > x)
+ a = m + 1
+ else
+ return array_remove(set, m)
+ }
+ return array_insert(set, a, item)
+}
+
+// Fast deep copy for objects without cycles
+function object_copy(original) {
+ if (Array.isArray(original)) {
+ let n = original.length
+ let copy = new Array(n)
+ for (let i = 0; i < n; ++i) {
+ let v = original[i]
+ if (typeof v === "object" && v !== null)
+ copy[i] = object_copy(v)
+ else
+ copy[i] = v
+ }
+ return copy
+ } else {
+ let copy = {}
+ for (let i in original) {
+ let v = original[i]
+ if (typeof v === "object" && v !== null)
+ copy[i] = object_copy(v)
+ else
+ copy[i] = v
+ }
+ return copy
+ }
+}
+
+function clear_undo() {
+ if (game.undo.length > 0)
+ game.undo = []
+}
+
+function push_undo() {
+ let copy = {}
+ for (let k in game) {
+ let v = game[k]
+ if (k === "undo")
+ continue
+ else if (k === "log")
+ v = v.length
+ else if (typeof v === "object" && v !== null)
+ v = object_copy(v)
+ copy[k] = v
+ }
+ game.undo.push(copy)
+}
+
+function pop_undo() {
+ let save_log = game.log
+ let save_undo = game.undo
+ let state = save_undo.pop()
+ save_log.length = state.log
+ state.log = save_log
+ state.undo = save_undo
+ load_state(state)
+}