summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor@ccxvii.net>2022-06-20 22:11:54 +0200
committerTor Andersson <tor@ccxvii.net>2022-11-16 19:08:56 +0100
commitfdbe7f2b30ed3d88be9ef0b4cbc17e66a8c07eeb (patch)
treeb0ebccd0b9b536988ac6581b99558e9479306ed7
parent3a0d6e9698a8c94f3df11a2e2869d9c740b929f2 (diff)
downloadjulius-caesar-fdbe7f2b30ed3d88be9ef0b4cbc17e66a8c07eeb.tar.gz
Optimize loops.
Use for (let x of list) instead of for (let x in object). This gives a ~100% speed-up.
-rw-r--r--rules.js110
1 files changed, 63 insertions, 47 deletions
diff --git a/rules.js b/rules.js
index 8e67ff6..a0175cc 100644
--- a/rules.js
+++ b/rules.js
@@ -13,6 +13,9 @@ exports.roles = [
const { CARDS, SPACES, EDGES, BLOCKS } = require('./data')
+const BLOCKLIST = Object.keys(BLOCKS)
+const SPACELIST = Object.keys(SPACES)
+
const APOLLO = 1
const JUPITER = 2
const MARS = 3
@@ -310,28 +313,44 @@ function enemy_player() {
function count_friendly(where) {
let count = 0
let p = game.active
- for (let b in BLOCKS) {
+ for (let b of BLOCKLIST) {
if (game.location[b] === where && block_owner(b) === p)
++count
}
return count
}
+function has_friendly(where) {
+ let p = game.active
+ for (let b of BLOCKLIST)
+ if (game.location[b] === where && block_owner(b) === p)
+ return true
+ return false
+}
+
function count_enemy(where) {
let count = 0
let p = enemy_player()
- for (let b in BLOCKS) {
+ for (let b of BLOCKLIST) {
if (game.location[b] === where && block_owner(b) === p)
++count
}
return count
}
+function has_enemy(where) {
+ let p = enemy_player()
+ for (let b of BLOCKLIST)
+ if (game.location[b] === where && block_owner(b) === p)
+ return true
+ return false
+}
+
function count_pinning(where) {
let count = 0
if (game.active === game.p2) {
let p = enemy_player()
- for (let b in BLOCKS) {
+ for (let b of BLOCKLIST) {
if (game.location[b] === where && block_owner(b) === p)
if (!game.reserves.includes(b))
++count
@@ -342,7 +361,7 @@ function count_pinning(where) {
function count_pinned(where) {
let count = 0
- for (let b in BLOCKS) {
+ for (let b of BLOCKLIST) {
if (game.location[b] === where && block_owner(b) === game.active)
if (!game.reserves.includes(b))
++count
@@ -381,10 +400,10 @@ function is_navis(b) {
return BLOCKS[b].type === 'navis'
}
-function is_friendly_space(where) { return count_friendly(where) > 0 && count_enemy(where) === 0 }
-function is_enemy_space(where) { return count_friendly(where) === 0 && count_enemy(where) > 0 }
+function is_friendly_space(where) { return has_friendly(where) && count_enemy(where) === 0 }
+function is_enemy_space(where) { return count_friendly(where) === 0 && has_enemy(where) }
function is_vacant_space(where) { return count_friendly(where) === 0 && count_enemy(where) === 0 }
-function is_contested_space(where) { return count_friendly(where) > 0 && count_enemy(where) > 0 }
+function is_contested_space(where) { return has_friendly(where) && has_enemy(where) }
function is_friendly_city(where) { return is_city(where) && is_friendly_space(where) }
function is_enemy_city(where) { return is_city(where) && is_enemy_space(where) }
@@ -395,10 +414,7 @@ function is_vacant_sea(where) { return is_sea(where) && is_vacant_space(where) }
function is_contested_sea(where) { return is_sea(where) && is_contested_space(where) }
function have_contested_spaces() {
- for (let where in SPACES)
- if (is_map_space(where) && is_contested_space(where))
- return true
- return false
+ return SPACELIST.some(where => is_map_space(where) && is_contested_space(where))
}
function supply_limit(where) {
@@ -409,7 +425,7 @@ function supply_limit(where) {
function is_over_supply_limit(where) {
let count = 0
- for (let b in BLOCKS) {
+ for (let b of BLOCKLIST) {
if (game.location[b] === where)
++count
}
@@ -422,7 +438,7 @@ function count_vp() {
game.c_vp = 0
game.p_vp = 0
game.active = CAESAR
- for (let s in SPACES) {
+ for (let s of SPACELIST) {
if (is_friendly_city(s))
game.c_vp += SPACES[s].value
if (is_enemy_city(s))
@@ -695,7 +711,7 @@ function can_levy(b) {
if (block_owner(b) !== game.active)
return false
if (location === LEVY) {
- for (let to in SPACES)
+ for (let to of SPACELIST)
if (can_levy_to(b, to))
return true
return false
@@ -712,7 +728,7 @@ let states = {}
function start_free_deployment() {
game.active = CAESAR
game.setup_limit = {}
- for (let space in SPACES) {
+ for (let space of SPACELIST) {
if (is_map_space(space)) {
let n = count_friendly(space) + count_enemy(space)
if (n > 0)
@@ -726,7 +742,7 @@ function start_free_deployment() {
function validate_free_deployment() {
game.setup_error = []
- for (let space in SPACES) {
+ for (let space of SPACELIST) {
if (is_friendly_city(space)) {
let n = count_friendly(space)
let d = n - game.setup_limit[space]
@@ -753,7 +769,7 @@ states.free_deployment = {
} else {
format_deployment_error(view)
}
- for (let b in BLOCKS)
+ for (let b of BLOCKLIST)
if (block_owner(b) === game.active && is_map_space(game.location[b]))
gen_action(view, 'block', b)
},
@@ -788,7 +804,7 @@ states.free_deployment_to = {
}
gen_action_undo(view)
gen_action(view, 'block', game.who)
- for (let space in SPACES) {
+ for (let space of SPACELIST) {
if (space in game.setup_limit && space !== game.location[game.who]) {
if (!is_enemy_city(space)) {
if (block_type(game.who) === 'navis') {
@@ -1153,7 +1169,7 @@ states.jupiter = {
if (is_inactive_player(current))
return view.prompt = "Waiting for " + game.active + "..."
view.prompt = "Jupiter: Choose one enemy army adjacent to a friendly city."
- for (let s in SPACES) {
+ for (let s of SPACELIST) {
if (is_friendly_city(s)) {
for (let to of SPACES[s].exits)
if (is_enemy_city(to) || is_contested_city(to))
@@ -1165,7 +1181,7 @@ states.jupiter = {
space: function (where) {
/* pick a random block */
let list = []
- for (let x in BLOCKS)
+ for (let x of BLOCKLIST)
if (game.location[x] === where)
list.push(x)
let i = random(list.length)
@@ -1178,7 +1194,7 @@ states.jupiter = {
jupiter_block(CLEOPATRA)
} else {
let list = []
- for (let b in BLOCKS)
+ for (let b of BLOCKLIST)
if (game.location[b] === where && BLOCKS[b].owner === owner)
list.push(b)
let i = random(list.length)
@@ -1214,14 +1230,14 @@ states.vulcan = {
if (is_inactive_player(current))
return view.prompt = "Waiting for " + game.active + "..."
view.prompt = "Vulcan: Choose an enemy city to suffer a volcanic eruption."
- for (let s in SPACES)
+ for (let s of SPACELIST)
if (is_enemy_city(s))
gen_action(view, 'space', s)
},
space: function (city) {
log("Vulcan struck " + city + "!")
if (game.automatic_disruption) {
- for (let b in BLOCKS)
+ for (let b of BLOCKLIST)
if (game.location[b] === city)
reduce_block(b)
// uh-oh! cleopatra switched sides!
@@ -1231,7 +1247,7 @@ states.vulcan = {
} else {
game.where = city
game.vulcan = []
- for (let b in BLOCKS)
+ for (let b of BLOCKLIST)
if (game.location[b] === city)
game.vulcan.push(b)
game.active = enemy(game.active)
@@ -1265,7 +1281,7 @@ states.apply_vulcan = {
function goto_mars_and_neptune() {
game.surprise_list = []
- for (let where in SPACES)
+ for (let where of SPACELIST)
if (is_map_space(where) && is_contested_space(where))
game.surprise_list.push(where)
if (game.surprise_list.length === 0) {
@@ -1343,7 +1359,7 @@ states.move_who = {
else
view.prompt = "Choose an army to group move. "+game.moves+"MP left."
if (game.moves === 0) {
- for (let b in BLOCKS) {
+ for (let b of BLOCKLIST) {
let from = game.location[b]
if (game.activated.includes(from))
if (can_block_move(b))
@@ -1351,7 +1367,7 @@ states.move_who = {
}
} else {
let have_amphibious = false
- for (let b in BLOCKS) {
+ for (let b of BLOCKLIST) {
let can_move = false
if (game.amphibious_available && can_amphibious_move(b)) {
can_move = true
@@ -1610,7 +1626,7 @@ states.levy = {
view.prompt = "Choose an army to levy. "+game.levies+"LP left."
let is_levy_possible = false
if (game.levies > 0) {
- for (let b in BLOCKS) {
+ for (let b of BLOCKLIST) {
if (can_levy(b)) {
gen_action(view, 'block', b)
is_levy_possible = true
@@ -1652,7 +1668,7 @@ states.levy_where = {
if (is_inactive_player(current))
return view.prompt = "Waiting for " + game.active + " to levy..."
view.prompt = "Choose a friendly city to levy " + block_name(game.who) + " in."
- for (let to in SPACES)
+ for (let to of SPACELIST)
if (can_levy_to(game.who, to))
gen_action(view, 'space', to)
gen_action(view, 'block', game.who); // for canceling levy
@@ -1697,7 +1713,7 @@ states.pick_battle = {
if (is_inactive_player(current))
return view.prompt = "Waiting for " + game.active + " to pick a battle..."
view.prompt = "Choose the next battle to fight!"
- for (let s in SPACES)
+ for (let s of SPACELIST)
if (is_contested_city(s) || is_contested_sea(s))
gen_action(view, 'space', s)
},
@@ -1721,7 +1737,7 @@ function is_defender(b) {
function count_attackers() {
let count = 0
- for (let b in BLOCKS) {
+ for (let b of BLOCKLIST) {
if (is_attacker(b))
++count
}
@@ -1730,7 +1746,7 @@ function count_attackers() {
function count_defenders() {
let count = 0
- for (let b in BLOCKS) {
+ for (let b of BLOCKLIST) {
if (is_defender(b))
++count
}
@@ -1755,7 +1771,7 @@ function resume_battle() {
}
function bring_on_reserves() {
- for (let b in BLOCKS) {
+ for (let b of BLOCKLIST) {
if (game.location[b] === game.where) {
remove_from_array(game.reserves, b)
}
@@ -1765,14 +1781,14 @@ function bring_on_reserves() {
function goto_disrupt_reserves() {
game.flash = "Reserves were disrupted."
if (game.automatic_disruption) {
- for (let b in BLOCKS)
+ for (let b of BLOCKLIST)
if (game.location[b] === game.where && block_owner(b) === game.attacker[game.where])
if (game.reserves.includes(b))
reduce_block(b)
end_disrupt_reserves()
} else {
game.disrupted = []
- for (let b in BLOCKS)
+ for (let b of BLOCKLIST)
if (game.location[b] === game.where && block_owner(b) === game.attacker[game.where])
if (game.reserves.includes(b))
game.disrupted.push(b)
@@ -1851,7 +1867,7 @@ function start_battle_round() {
function pump_battle_round() {
function filter_battle_blocks(ci, is_candidate) {
let output = null
- for (let b in BLOCKS) {
+ for (let b of BLOCKLIST) {
if (is_candidate(b) && !game.moved[b]) {
if (block_initiative(b) === ci) {
if (!output)
@@ -2059,11 +2075,11 @@ function goto_battle_hits() {
function list_victims(p) {
let is_candidate = (p === game.attacker[game.where]) ? is_attacker : is_defender
let max = 0
- for (let b in BLOCKS)
+ for (let b of BLOCKLIST)
if (is_candidate(b) && block_strength(b) > max)
max = block_strength(b)
let list = []
- for (let b in BLOCKS)
+ for (let b of BLOCKLIST)
if (is_candidate(b) && block_strength(b) === max)
list.push(b)
return list
@@ -2188,7 +2204,7 @@ states.regroup = {
if (is_inactive_player(current))
return view.prompt = "Waiting for " + game.active + " to regroup..."
view.prompt = "Regroup: Choose an army to move."
- for (let b in BLOCKS) {
+ for (let b of BLOCKLIST) {
if (game.location[b] === game.where) {
if (can_regroup(b))
gen_action(view, 'block', b)
@@ -2287,7 +2303,7 @@ function check_victory() {
function count_navis_to_port() {
let count = 0
- for (let b in BLOCKS) {
+ for (let b of BLOCKLIST) {
if (block_owner(b) === game.active && BLOCKS[b].type === 'navis')
if (SPACES[game.location[b]].type === 'sea')
if (can_navis_move_to_port(b))
@@ -2329,7 +2345,7 @@ states.navis_to_port = {
return view.prompt = "Waiting for " + game.active + " to move navis to port..."
view.prompt = "Move all Navis to a friendly port."
let count = 0
- for (let b in BLOCKS) {
+ for (let b of BLOCKLIST) {
if (block_owner(b) === game.active && BLOCKS[b].type === 'navis') {
if (SPACES[game.location[b]].type === 'sea') {
if (can_navis_move_to_port(b)) {
@@ -2393,7 +2409,7 @@ states.disband = {
if (is_inactive_player(current))
return view.prompt = "Waiting for " + game.active + " to disband..."
let okay_to_end = true
- for (let b in BLOCKS) {
+ for (let b of BLOCKLIST) {
if (block_owner(b) === game.active && is_map_space(game.location[b]) && b !== CLEOPATRA) {
if (is_over_supply_limit(game.location[b])) {
okay_to_end = false
@@ -2406,7 +2422,7 @@ states.disband = {
view.prompt = "Disband armies in excess of supply."
} else {
view.prompt = "You may disband armies to your levy pool."
- for (let b in BLOCKS) {
+ for (let b of BLOCKLIST) {
if (is_map_space(game.location[b]))
if (block_owner(b) === game.active && b !== CLEOPATRA)
gen_action(view, 'block', b)
@@ -2437,7 +2453,7 @@ states.disband = {
function end_year() {
game.year ++
- for (let b in BLOCKS) {
+ for (let b of BLOCKLIST) {
if (game.location[b] === DEAD && BLOCKS[b].type !== 'leader') {
disband_block(b)
}
@@ -2567,7 +2583,7 @@ exports.setup = function (seed, scenario, options) {
}
function deploy_block(owner, location, name) {
- for (let b in BLOCKS) {
+ for (let b of BLOCKLIST) {
if (BLOCKS[b].owner === owner && BLOCKS[b].name === name) {
game.steps[b] = BLOCKS[b].steps
game.location[b] = location
@@ -2577,7 +2593,7 @@ function deploy_block(owner, location, name) {
}
function setup_historical_deployment() {
- for (let b in BLOCKS) {
+ for (let b of BLOCKLIST) {
game.location[b] = LEVY
game.steps[b] = BLOCKS[b].steps
}
@@ -2660,7 +2676,7 @@ function make_battle_view() {
}
function fill_cell(name, p, fn) {
- for (let b in BLOCKS) {
+ for (let b of BLOCKLIST) {
if (game.location[b] === game.where & block_owner(b) === p && fn(b)) {
bv[name].push(b)
}