diff options
author | Tor Andersson <tor@ccxvii.net> | 2024-08-23 15:14:51 +0200 |
---|---|---|
committer | Tor Andersson <tor@ccxvii.net> | 2024-08-24 01:19:42 +0200 |
commit | fb2cb74d0d97fc162e72a1c4dff8c802dd205458 (patch) | |
tree | ec7bc985b71b2b89bbb8576159d385a04dc55a28 | |
parent | faaf7a743c52fa8f02b925d8f4574c28fa2fdd4f (diff) | |
download | vijayanagara-fb2cb74d0d97fc162e72a1c4dff8c802dd205458.tar.gz |
Blank rules.
-rw-r--r-- | create.html | 0 | ||||
-rw-r--r-- | rules.js | 356 |
2 files changed, 356 insertions, 0 deletions
diff --git a/create.html b/create.html new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/create.html diff --git a/rules.js b/rules.js new file mode 100644 index 0000000..9e262dd --- /dev/null +++ b/rules.js @@ -0,0 +1,356 @@ +"use strict" + +let states = {} +let game = null +let view = null + +/* DATA */ + +const data = require("./data.js") + +// Factions +const DS = 0 +const BK = 1 +const VE = 2 + +// Faction names +const NAME_DS = "DS" +const NAME_BK = "BK" +const NAME_VE = "VE" + +const faction_name = [ "Delhi Sultanate", "Bahmani Kingdom", "Vijayanagara Empire" ] + +exports.roles = [ NAME_DS, NAME_BK, NAME_VE ] + +exports.scenarios = [ "Standard" ] + + +/* 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) +} + +// 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 +} |