summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor@ccxvii.net>2024-09-19 00:50:03 +0200
committerTor Andersson <tor@ccxvii.net>2024-09-20 15:05:33 +0200
commitdd623349cefe4a629c9355703711e800295634c8 (patch)
tree79bb4fb6df7e3be2dac76f59a38b73109b5ecf7f
parent9ba7ea8a1661961eadbfadc538416f71c9e996b1 (diff)
downloadwilderness-war-dd623349cefe4a629c9355703711e800295634c8.tar.gz
Update common code library.
-rw-r--r--rules.js270
1 files changed, 237 insertions, 33 deletions
diff --git a/rules.js b/rules.js
index 7f61f45..0d3b55e 100644
--- a/rules.js
+++ b/rules.js
@@ -173,6 +173,8 @@ const NORTHERN_COLONIAL_MILITIAS = 142
const SOUTHERN_COLONIAL_MILITIAS = 143
const ST_LAWRENCE_CANADIAN_MILITIAS = 144
+// MISC DATA
+
// Patch up leader/box associations.
const box_from_leader = []
const leader_from_box = []
@@ -196,6 +198,8 @@ for (let s = first_space; s <= last_space; ++s) {
// Make non-breaking names.
spaces.forEach(ss => ss.nb_name = ss.name.replace(/ /g, '\xa0'))
+
+// GLOBALS
pieces.forEach(pp => {
if (pp.desc) pp.nb_desc = pp.desc.replace(/ /g, '\xa0')
if (pp.rdesc) pp.nb_rdesc = pp.rdesc.replace(/ /g, '\xa0')
@@ -224,14 +228,14 @@ let last_friendly_leader
let last_friendly_piece
let last_friendly_unit
+// UTILITY FUNCTIONS
+
function abs(x) {
return x < 0 ? -x : x
}
function random(n) {
clear_undo()
- if (game.rng === 1)
- return ((game.seed = game.seed * 69621 % 0x7fffffff) / 0x7fffffff) * n | 0
return (game.seed = game.seed * 200105 % 34359738337) % n
}
@@ -351,6 +355,8 @@ function flush_go_home_summary() {
}
}
+// CURRENT PLAYER ALIASES
+
function enemy() {
return game.active === FRANCE ? BRITAIN : FRANCE
}
@@ -9797,11 +9803,6 @@ exports.setup = function (seed, scenario, options) {
// ACTION HANDLERS
-function clear_undo() {
- if (game.undo && game.undo.length > 0)
- game.undo.length = 0
-}
-
function push_undo() {
if (game.undo) {
let copy = {}
@@ -10006,21 +10007,80 @@ exports.view = function(state, current) {
// COMMON LIBRARY
-// remove item at index (faster than splice)
+function clear_undo() {
+ if (game.undo) {
+ game.undo.length = 0
+ }
+}
+
+// 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
+ }
+}
+
+// Array remove and insert (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_remove_item(array, item) {
+ let n = array.length
+ for (let i = 0; i < n; ++i)
+ if (array[i] === item)
+ return array_remove(array, i)
+}
+
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 array_remove_pair(array, index) {
+ let n = array.length
+ for (let i = index + 2; i < n; ++i)
+ array[i - 2] = array[i]
+ array.length = n - 2
+}
+
+function array_insert_pair(array, index, key, value) {
+ for (let i = array.length; i > index; i -= 2) {
+ array[i] = array[i-2]
+ array[i+1] = array[i-1]
+ }
+ array[index] = key
+ array[index+1] = value
+}
+
+// Set as plain sorted array
+
+function set_clear(set) {
+ set.length = 0
}
function set_has(set, item) {
@@ -10050,9 +10110,9 @@ function set_add(set, item) {
else if (item > x)
a = m + 1
else
- return set
+ return
}
- return array_insert(set, a, item)
+ array_insert(set, a, item)
}
function set_delete(set, item) {
@@ -10065,36 +10125,180 @@ function set_delete(set, item) {
b = m - 1
else if (item > x)
a = m + 1
+ else {
+ array_remove(set, m)
+ return
+ }
+ }
+}
+
+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 {
+ array_remove(set, m)
+ return
+ }
+ }
+ array_insert(set, a, item)
+}
+
+// Map as plain sorted array of key/value pairs
+
+function map_clear(map) {
+ map.length = 0
+}
+
+function map_has(map, key) {
+ let a = 0
+ let b = (map.length >> 1) - 1
+ while (a <= b) {
+ let m = (a + b) >> 1
+ let x = map[m<<1]
+ if (key < x)
+ b = m - 1
+ else if (key > x)
+ a = m + 1
else
- return array_remove(set, m)
+ return true
}
- return set
+ return false
}
-// 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)
+function map_get(map, key, missing) {
+ let a = 0
+ let b = (map.length >> 1) - 1
+ while (a <= b) {
+ let m = (a + b) >> 1
+ let x = map[m<<1]
+ if (key < x)
+ b = m - 1
+ else if (key > x)
+ a = m + 1
+ else
+ return map[(m<<1)+1]
+ }
+ return missing
+}
+
+function map_set(map, key, value) {
+ let a = 0
+ let b = (map.length >> 1) - 1
+ while (a <= b) {
+ let m = (a + b) >> 1
+ let x = map[m<<1]
+ if (key < x)
+ b = m - 1
+ else if (key > x)
+ a = m + 1
+ else {
+ map[(m<<1)+1] = value
+ return
+ }
+ }
+ array_insert_pair(map, a<<1, key, value)
+}
+
+function map_delete(map, key) {
+ let a = 0
+ let b = (map.length >> 1) - 1
+ while (a <= b) {
+ let m = (a + b) >> 1
+ let x = map[m<<1]
+ if (key < x)
+ b = m - 1
+ else if (key > x)
+ a = m + 1
+ else {
+ array_remove_pair(map, m<<1)
+ return
+ }
+ }
+}
+
+function map_for_each(map, f) {
+ for (let i = 0; i < map.length; i += 2)
+ f(map[i], map[i+1])
+}
+
+function object_diff(a, b) {
+ if (a === b)
+ return false
+ if (a !== null && b !== null && typeof a === "object" && typeof b === "object") {
+ if (Array.isArray(a)) {
+ if (!Array.isArray(b))
+ return true
+ let a_length = a.length
+ if (b.length !== a_length)
+ return true
+ for (let i = 0; i < a_length; ++i)
+ if (object_diff(a[i], b[i]))
+ return true
+ return false
+ }
+ for (let key in a)
+ if (object_diff(a[key], b[key]))
+ return true
+ for (let key in b)
+ if (!(key in a))
+ return true
+ return false
+ }
+ return true
+}
+
+// same as Object.groupBy
+function object_group_by(items, callback) {
+ let groups = {}
+ if (typeof callback === "function") {
+ for (let item of items) {
+ let key = callback(item)
+ if (key in groups)
+ groups[key].push(item)
else
- copy[i] = v
+ groups[key] = [ item ]
}
- 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)
+ for (let item of items) {
+ let key = item[callback]
+ if (key in groups)
+ groups[key].push(item)
else
- copy[i] = v
+ groups[key] = [ item ]
+ }
+ }
+ return groups
+}
+
+function map_group_by(items, callback) {
+ let groups = []
+ if (typeof callback === "function") {
+ for (let item of items) {
+ let key = callback(item)
+ let arr = map_get(groups, key)
+ if (arr)
+ arr.push(item)
+ else
+ map_set(groups, key, [ item ])
+ }
+ } else {
+ for (let item of items) {
+ let key = item[callback]
+ let arr = map_get(groups, key)
+ if (arr)
+ arr.push(item)
+ else
+ map_set(groups, key, [ item ])
}
- return copy
}
+ return groups
}
/* ASSERTS */