summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rules.js393
1 files changed, 391 insertions, 2 deletions
diff --git a/rules.js b/rules.js
index bad1211..51218c6 100644
--- a/rules.js
+++ b/rules.js
@@ -9,6 +9,55 @@ var game, view
// space list:
// objective/fortress have control (0 or power)
+const data = require("./data")
+let objectives = {}
+let anti_objectives = { Austria: [], "Pragmatic Army": [], France: [], Prussia: [] }
+let prot_objectives = { Austria: [], "Pragmatic Army": [], France: [], Prussia: [] }
+
+let whose_objective = {
+ Austria: [ "France", "Prussia" ],
+ Bavaria: [ "Austria" ],
+ France: [ "Austria", "Pragmatic Army" ],
+ Netherlands: [ "France" ],
+ Prussia: [ "Austria" ],
+ Saxony: [ "Austria" ],
+ Silesia: [ "Austria", "Prussia" ],
+ HRE: [ "Austria", "Pragmatic Army", "France" ],
+}
+
+let protect_objective = {
+ Austria: [ "Austria" ],
+ Bavaria: [ "France" ],
+ France: [ "France" ],
+ Netherlands: [ "Pragmatic Army" ],
+ Prussia: [ "Prussia" ],
+ Saxony: [ "Prussia" ],
+ Silesia: [ "Austria", "Prussia" ],
+ HRE: [ "Austria", "Pragmatic Army", "France" ],
+}
+
+for (let type of [ "major_fortress", "minor_fortress" ]) {
+ let group = object_group_by(data.type[type], s => data.cities.country[s])
+ for (let region in group) {
+ if (objectives[region] === undefined)
+ objectives[region] = []
+ for (let s of group[region]) {
+ set_add(objectives[region], s)
+ console.log(region)
+ for (let list of whose_objective[region])
+ set_add(anti_objectives[list], s)
+ for (let list of protect_objective[region])
+ set_add(prot_objectives[list], s)
+ }
+
+ }
+}
+for (let x in anti_objectives)
+ console.log(x, anti_objectives[x].length)
+console.log(objectives)
+console.log("TAKE", anti_objectives)
+console.log("PROT", prot_objectives)
+
exports.roles = [ "Maria Theresa", "Frederick", "Louis XV" ]
exports.scenarios = [ "Standard", "Introductory" ]
@@ -50,6 +99,7 @@ exports.setup = function (seed, scenario, options) {
state: "setup",
turn: 1,
+ step: 0,
ctl: [],
loc: [],
str: [],
@@ -106,8 +156,8 @@ exports.setup = function (seed, scenario, options) {
exports.view = function (state) {
game = state
view = {
- log: game.log
- power: game.power
+ log: game.log,
+ power: game.power,
turn: game.turn,
ctl: game.ctl,
loc: game.loc,
@@ -115,3 +165,342 @@ exports.view = function (state) {
}
return view
}
+
+
+
+// === COMMON LIBRARY ===
+
+function clear_undo() {
+ if (game.undo) {
+ game.undo.length = 0
+ }
+}
+
+function push_undo() {
+ if (game.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() {
+ if (game.undo) {
+ let save_log = game.log
+ let save_undo = game.undo
+ game = save_undo.pop()
+ save_log.length = game.log
+ game.log = save_log
+ game.undo = save_undo
+ }
+}
+
+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
+}
+
+function random_bigint(range) {
+ // Largest MLCG that will fit its state in a double.
+ // Uses BigInt for arithmetic, so is an order of magnitude slower.
+ // https://www.ams.org/journals/mcom/1999-68-225/S0025-5718-99-00996-5/S0025-5718-99-00996-5.pdf
+ // m = 2**53 - 111
+ return (game.seed = Number(BigInt(game.seed) * 5667072534355537n % 9007199254740881n)) % range
+}
+
+function shuffle(list) {
+ // Fisher-Yates shuffle
+ for (let i = list.length - 1; i > 0; --i) {
+ let j = random(i + 1)
+ let tmp = list[j]
+ list[j] = list[i]
+ list[i] = tmp
+ }
+}
+
+function shuffle_bigint(list) {
+ // Fisher-Yates shuffle
+ for (let i = list.length - 1; i > 0; --i) {
+ let j = random_bigint(i + 1)
+ let tmp = list[j]
+ list[j] = list[i]
+ list[i] = tmp
+ }
+}
+
+// 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
+}
+
+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
+}
+
+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) {
+ 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
+ }
+ 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 {
+ 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)
+}
+
+function set_union(a, b) {
+ let out = a.slice()
+ for (let item of b)
+ set_add(out, item)
+ return out
+}
+
+// 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 true
+ }
+ return false
+}
+
+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 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
+ groups[key] = [ item ]
+ }
+ } else {
+ for (let item of items) {
+ let key = item[callback]
+ if (key in groups)
+ groups[key].push(item)
+ else
+ groups[key] = [ item ]
+ }
+ }
+ return groups
+}