summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor@ccxvii.net>2024-05-27 00:28:00 +0200
committerTor Andersson <tor@ccxvii.net>2024-05-30 21:59:25 +0200
commitcd5a083ea9ade6a7f6ef7e16e336fff9f30343aa (patch)
tree1bbd415bfc886610942786772ac541cb1ad5df09
parent38f9e31f86205664139dcd4d1980d4299c117a2d (diff)
downloadfriedrich-cd5a083ea9ade6a7f6ef7e16e336fff9f30343aa.tar.gz
chevert unstack. stay in attack position. no move search.
-rw-r--r--play.css20
-rw-r--r--play.html1
-rw-r--r--play.js216
-rw-r--r--rules.js335
4 files changed, 69 insertions, 503 deletions
diff --git a/play.css b/play.css
index b69659f..658b1e1 100644
--- a/play.css
+++ b/play.css
@@ -205,6 +205,15 @@ TWOD.piece.cylinder {
border: 1px solid black;
}
+#combat {
+ position: absolute;
+ width: 52px;
+ height: 52px;
+ border: 4px solid #c00;
+ background-color: #c008;
+ border-radius: 50%;
+}
+
.panel {
background-color: #444;
width: clamp(824px, calc(100% - 30px), 1636px);
@@ -279,17 +288,6 @@ TWOD.piece.cylinder {
.space.objective.action.imperial { background-color: #fbe30080; }
.space.objective.action.france { background-color: #ed1c2380; }
-@media (pointer: fine) {
-
-.move line { stroke: white; }
-.battle line { stroke: #c00; }
-.retreat line { stroke: #800; opacity: 33%; }
-line { stroke-linecap: round; }
-line.road { stroke-width: 6px; }
-line.major_road { stroke-width: 8px; }
-
-}
-
.marker.conquest.austria { background-image: url(images/conquest_austria.2x.png) }
.marker.conquest.france { background-image: url(images/conquest_france.2x.png) }
.marker.conquest.imperial { background-image: url(images/conquest_imperial.2x.png) }
diff --git a/play.html b/play.html
index 3dc4d9a..f384dac 100644
--- a/play.html
+++ b/play.html
@@ -38,7 +38,6 @@
<div id="mapwrap">
<div id="map">
- <svg id="roads" class="move" viewBox="0 0 2485 1654"></svg>
<div id="spaces"></div>
<div id="markers"></div>
<div id="pieces"></div>
diff --git a/play.js b/play.js
index cc3eb25..5803c11 100644
--- a/play.js
+++ b/play.js
@@ -1,14 +1,14 @@
"use strict"
// vim: set nowrap:
+/* globals data, view, action_button, action_button_with_argument, confirm_action_button, send_action
+*/
// TODO: sort selected generals above deselected generals when detaching?
// TODO: show battle icon overlay (instead of roads)
// TODO: remove roads and path highlighting code
// TODO: tooltips
-const svgNS = "http://www.w3.org/2000/svg"
-
function toggle_pieces() {
document.getElementById("pieces").classList.toggle("hide")
}
@@ -47,7 +47,6 @@ set_add_all(all_objectives, data.type.objective_russia)
const objective1 = [ [], [], [], [], [], [], [] ]
const objective2 = [ [], [], [], [], [], [], [] ]
-const protect = [ [], [], [], [], [], [], [] ]
for (let s of data.type.objective_prussia) set_add(objective1[P_PRUSSIA], s)
for (let s of data.type.objective_russia) set_add(objective1[P_RUSSIA], s)
@@ -63,7 +62,6 @@ const power_class = [ "prussia", "hanover", "russia", "sweden", "austria", "impe
const power_name = [ "Prussia", "Hanover", "Russia", "Sweden", "Austria", "Imperial Army", "France" ]
const GENERAL_POWER = [ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 2, 2, 3, 4, 4, 4, 4, 4, 5, 6, 6, 6 ]
-const TRAIN_POWER = [ 0, 0, 1, 2, 2, 3, 4, 4, 5, 6, 6 ]
const all_powers = [ 0, 1, 2, 3, 4, 5, 6 ]
@@ -90,6 +88,10 @@ const all_power_trains = [
const RESERVE = 4
let suit_class = [ "S", "C", "H", "D", "R" ]
+function to_deck(c) {
+ return c >> 7
+}
+
function to_suit(c) {
return (c >> 4) & 7
}
@@ -304,12 +306,9 @@ function register_action(target, action, id) {
}
function on_click_action(evt, target) {
- if (evt.button === 0) {
- if (send_action(target.my_action, target.my_id)) {
- hide_move_path()
+ if (evt.button === 0)
+ if (send_action(target.my_action, target.my_id))
evt.stopPropagation()
- }
- }
}
function process_actions() {
@@ -323,33 +322,6 @@ function is_action(action, arg) {
return !!(view.actions && view.actions[action] && set_has(view.actions[action], arg))
}
-function make_road(c1, c2, type) {
- let e = document.createElementNS(svgNS, "line")
- e.setAttribute("class", type)
- let x1 = data.cities.x[c1]
- let y1 = data.cities.y[c1]
- let x2 = data.cities.x[c2]
- let y2 = data.cities.y[c2]
-
- let v = Math.hypot(x2 - x1, y2 - y1)
- let dx = (x2 - x1) / v
- let dy = (y2 - y1) / v
- let r = 18
- x1 += r * dx
- y1 += r * dy
- x2 -= r * dx
- y2 -= r * dy
-
- e.setAttribute("x1", x1)
- e.setAttribute("y1", y1)
- e.setAttribute("x2", x2)
- e.setAttribute("y2", y2)
- e.setAttribute("visibility", "hidden")
- ui.roads[c1][c2] = e
- ui.roads[c2][c1] = e
- ui.roads_element.appendChild(e)
-}
-
function create_piece(action, id, style) {
let e = document.createElement("div")
e.className = style
@@ -365,10 +337,6 @@ function create_marker(style) {
return e
}
-function make_tc_id(n, suit, value) {
- return (n << 7) | (suit << 4) | value
-}
-
function make_tc_deck(n) {
for (let suit = 0; suit <= 3; ++suit) {
for (let value = 2; value <= 13; ++value) {
@@ -493,6 +461,9 @@ function on_init() {
make_tc_deck_back("deck_5"),
]
+ ui.combat = document.createElement("div")
+ ui.combat.id = "combat"
+
ui.tcbreak = document.createElement("div")
ui.tcbreak.className = "draw-break"
@@ -500,23 +471,6 @@ function on_init() {
for (let fc = 0; fc <= 18; ++fc)
ui.fate[fc] = make_fate_card(fc)
- if (1) {
- for (let a = 0; a <= last_city; ++a)
- ui.roads[a] = []
- for (let a = 0; a <= last_city; ++a) {
- for (let b of cities.major_roads[a]) {
- if (a < b) {
- make_road(a, b, "major_road")
- }
- }
- for (let b of cities.roads[a]) {
- if (a < b) {
- make_road(a, b, "road")
- }
- }
- }
- }
-
for (let a = 0; a <= last_city; ++a) {
let e = ui.cities[a] = document.createElement("div")
let x = cities.x[a]
@@ -569,117 +523,18 @@ function on_init() {
on_init()
-/* SHOW PATH FOR MOVES */
+/* TOOLTIPS */
function on_focus_city(evt) {
- document.getElementById("status").textContent = evt.target.my_name
- if (view) {
- if (view.move_minor)
- show_move_path(evt.target.my_id)
- if (view.retreat)
- show_retreat_path(evt.target.my_id)
- }
}
function on_blur_city() {
- document.getElementById("status").textContent = ""
- hide_move_path()
}
function on_focus_piece(evt) {
- document.getElementById("status").textContent = evt.target.my_name
- if (view && view.move_minor)
- show_move_path(view.pos[evt.target.my_id])
}
function on_blur_piece() {
- document.getElementById("status").textContent = ""
- hide_move_path()
-}
-
-var _move_path = []
-var _battle_road = null
-
-function hide_move_path() {
- if (_move_path) {
- for (let i = 1; i < _move_path.length; ++i) {
- let x = _move_path[i-1]
- let y = _move_path[i]
- ui.roads[x][y].setAttribute("visibility", "hidden")
- }
- _move_path = null
- }
-}
-
-function show_move_path(x) {
- hide_move_path()
-
- if (map_get(view.move_major, x, -1) >= 0) {
- _move_path = []
- while (x >= 0) {
- _move_path.push(x)
- x = map_get(view.move_major, x, -1)
- }
- }
-
- else
-
- if (map_get(view.move_minor, x, -1) >= 0) {
- _move_path = []
- while (x >= 0) {
- _move_path.push(x)
- x = map_get(view.move_minor, x, -1)
- }
- }
-
- if (_move_path) {
- for (let i = 1; i < _move_path.length; ++i) {
- let x = _move_path[i-1]
- let y = _move_path[i]
- ui.roads[x][y].setAttribute("visibility", "visible")
- }
- }
-}
-
-function show_retreat_path(x) {
- hide_move_path()
- _move_path = map_get(view.retreat, x, null)
- if (_move_path) {
- _move_path = _move_path.slice()
- _move_path.push(x)
- for (let i = 1; i < _move_path.length; ++i) {
- let x = _move_path[i-1]
- let y = _move_path[i]
- ui.roads[x][y].setAttribute("visibility", "visible")
- }
- }
-}
-
-function show_battle_path() {
- _battle_road = ui.roads[view.attacker][view.defender]
- _battle_road.setAttribute("visibility", "visible")
-}
-
-function hide_battle_path() {
- if (_battle_road) {
- _battle_road.setAttribute("visibility", "hidden")
- _battle_road = null
- }
-}
-
-function update_path() {
- hide_move_path()
- hide_battle_path()
- if (view.move_major) {
- ui.roads_element.setAttribute("class", "move")
- } else if (view.retreat) {
- ui.roads_element.setAttribute("class", "retreat")
- } else if (view.attacker !== undefined) {
- ui.roads_element.setAttribute("class", "battle")
- show_battle_path()
- } else {
- ui.roads_element.setAttribute("class", null)
- }
}
/* UPDATE UI */
@@ -796,6 +651,14 @@ function layout_train(id, s) {
e.classList.toggle("selected", set_has(view.selected, id))
}
+function layout_combat_marker() {
+ let x = (data.cities.x[view.attacker] + data.cities.x[view.defender]) >> 1
+ let y = (data.cities.y[view.attacker] + data.cities.y[view.defender]) >> 1
+ ui.combat.style.left = x - 30 + "px"
+ ui.combat.style.top = y - 30 + "px"
+ ui.combat.style.zIndex = y
+}
+
function create_conquest(style, s) {
let x = data.cities.x[s]
let y = data.cities.y[s]
@@ -807,18 +670,6 @@ function create_conquest(style, s) {
return e
}
-function to_deck(c) {
- return c >> 7
-}
-
-function to_suit(c) {
- return (c >> 4) & 7
-}
-
-function to_value(c) {
- return c & 15
-}
-
function update_favicon() {
let favicon = document.querySelector('link[rel="icon"]')
switch (params.role) {
@@ -859,7 +710,9 @@ function colorize(text) {
}
function on_update() {
- ui.prompt.innerHTML = colorize(view.prompt)
+ let text = colorize(view.prompt)
+ if (text !== view.prompt)
+ ui.prompt.innerHTML = text
ui.header.classList.toggle("prussia", view.power === P_PRUSSIA)
ui.header.classList.toggle("hanover", view.power === P_HANOVER)
@@ -876,8 +729,6 @@ function on_update() {
for (let t = 24; t <= 34; ++t)
layout_train(t, view.pos[t])
- update_path()
-
let back = [ 0, 0, 0, 0, 0 ]
for (let i = 0; i < 5; ++i)
@@ -916,6 +767,11 @@ function on_update() {
for (let s of view.retro)
ui.markers_element.appendChild(ui.retro[s])
+ if (view.attacker !== undefined && view.defender !== undefined) {
+ ui.markers_element.appendChild(ui.combat)
+ layout_combat_marker()
+ }
+
/* troops 1-8, reserve 1-10 with modifiers +1 and +5 */
for (let v = 16; v >= 0; --v)
action_button_with_argument("value", v, v)
@@ -1066,19 +922,3 @@ function set_add_all(set, other) {
for (let item of other)
set_add(set, item)
}
-
-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
-}
diff --git a/rules.js b/rules.js
index 37520d4..713e234 100644
--- a/rules.js
+++ b/rules.js
@@ -1,5 +1,8 @@
"use strict"
+// TODO: prussian offensive (no capture when not offensive)
+// TODO: final score summary at game end (FWC rules)
+
const R_FREDERICK = "Frederick"
const R_ELISABETH = "Elisabeth"
const R_MARIA_THERESA = "Maria Theresa"
@@ -364,13 +367,6 @@ function clear_fate_effect() {
game.fx = 0
}
-function may_unstack() {
- // TODO: 3-piece stack?
- if (game.fx === NEXT_TURN_CHEVERT_MAY_NOT_UNSTACK)
- return !set_has(game.selected, GEN_CHEVERT)
- return true
-}
-
function forbid_play_value_10_or_more() {
if (game.fx === NEXT_TURN_IF_PRUSSIA_AND_FRANCE_FIGHT_EACH_OTHER_THEY_MAY_NOT_USE_TCS_WITH_VALUES_OF_10_OR_MORE) {
let a = get_stack_power(game.attacker)
@@ -1463,9 +1459,9 @@ states.movement = {
game.major = 0
if (is_supply_train(p))
- resume_move_supply_train()
+ game.state = "move_supply_train"
else
- resume_move_general()
+ game.state = "move_general"
},
confirm_end_movement() {
this.end_movement()
@@ -1483,7 +1479,6 @@ function format_move(max) {
return ` up to ${n} cities.`
}
-// TODO: also force moving if in such a position and can move away
function forbid_stopping_at(from) {
switch (game.fx) {
case NEXT_TURN_SOUBISE_AND_HILDBURGHAUSEN_MAY_NOT_ATTACK_WITH_THE_SAME_TC_SYMBOL:
@@ -1500,22 +1495,6 @@ function forbid_stopping_at(from) {
return false
}
-function forbid_attack(from, to) {
- switch (game.fx) {
- case NEXT_TURN_SOUBISE_AND_HILDBURGHAUSEN_MAY_NOT_ATTACK_WITH_THE_SAME_TC_SYMBOL:
- return game.pos[GEN_SOUBISE] === from && game.ia_attack === get_space_suit(from)
- case NEXT_TURN_NO_GENERAL_MAY_BE_ATTACKED_IN_THE_CITY_OF_HALLE:
- return to === HALLE
- case NEXT_TURN_CUMBERLAND_MAY_NOT_MOVE_INTO_ATTACK_POSITION:
- return game.pos[GEN_CUMBERLAND] === from
- case NEXT_TURN_SOUBISE_MAY_NOT_MOVE_INTO_ATTACK_POSITION:
- return game.pos[GEN_SOUBISE] === from
- case NEXT_TURN_FRIEDRICH_MAY_NOT_MOVE_INTO_ATTACK_POSITION:
- return game.pos[GEN_FRIEDRICH] === from
- }
- return false
-}
-
function forbid_capture(s) {
switch (game.fx) {
case NEXT_TURN_CUMBERLAND_MAY_NOT_MOVE_INTO_ATTACK_POSITION:
@@ -1548,10 +1527,6 @@ function can_move_train_to(to) {
return !has_any_piece(to)
}
-function can_continue_train_from(_) {
- return true
-}
-
function can_move_general_in_theory(p, to) {
if (has_friendly_supply_train(to))
return false
@@ -1595,65 +1570,6 @@ function can_continue_general_from(from) {
return true
}
-function search_move(from, range, road_type, can_move_to, can_continue_from) {
- let seen = [ from, -1 ]
- let queue = [ from << 4 ]
- while (queue.length > 0) {
- let item = queue.shift()
- let here = item >> 4
- let dist = (item & 15) + 1
- for (let next of data.cities[road_type][here]) {
- if (map_has(seen, next))
- continue
- if (!can_move_to(next))
- continue
- if (dist <= range) {
- map_set(seen, next, here)
- if (can_continue_from(next))
- queue.push((next << 4) | dist)
- }
- }
- }
- return seen
-}
-
-function resume_move_supply_train() {
- if (game.count === 2 + game.major) {
- end_move_piece()
- } else {
- let here = game.pos[game.selected[0]]
- game.state = "move_supply_train"
- if (game.major && game.count < 3)
- game.move_major = search_move(here, 3 - game.count, "major_roads", can_move_train_to, can_continue_train_from)
- else
- game.move_major = []
- if (game.count < 2)
- game.move_minor = search_move(here, 2 - game.count, "adjacent", can_move_train_to, can_continue_train_from)
- else
- game.move_minor = []
- }
-}
-
-function resume_move_general() {
- let range = movement_range()
- if (game.count === range + game.major) {
- end_move_piece()
- } else {
- game.state = "move_general"
- /* NEW
- let here = game.pos[game.selected[0]]
- if (game.major && game.count < range+1)
- game.move_major = search_move(here, range+1 - game.count, "major_roads", can_move_general_to, can_continue_general_from)
- else
- game.move_major = []
- if (game.count < range)
- game.move_minor = search_move(here, range - game.count, "adjacent", can_move_general_to, can_continue_general_from)
- else
- game.move_minor = []
- */
- }
-}
-
function move_general_to(to) {
let pow = game.power
let who = game.selected[0]
@@ -1738,77 +1654,7 @@ function move_general_immediately(to) {
}
}
-states.move_supply_train_NEW = {
- inactive: "move",
- prompt() {
- prompt("Move supply train" + format_move(2))
- view.selected = game.selected
-
- let who = game.selected[0]
- let here = game.pos[who]
-
- if (game.move_major)
- map_for_each_key(game.move_major, s => { if (s !== here) gen_action_space(s) })
- if (game.move_minor)
- map_for_each_key(game.move_minor, s => { if (s !== here) gen_action_space(s) })
-
- view.move_major = game.move_major
- view.move_minor = game.move_minor
-
- /*
- if (game.count < 2 + game.major)
- for (let next of data.cities.major_roads[here])
- if (!has_any_piece(next))
- gen_action_space(next)
- if (game.count < 2)
- for (let next of data.cities.roads[here])
- if (!has_any_piece(next))
- gen_action_space(next)
- */
-
- if (game.count > 0) {
- gen_action_piece(who)
- view.actions.stop = 1
- }
- },
- piece(_) {
- this.stop()
- },
- stop() {
- end_move_piece()
- },
- space(to) {
- let who = game.selected[0]
-
- set_add(game.moved, who)
- game.pos[who] = to
-
- log("P" + who + " to S" + to)
-
- let m = map_get(game.move_major, to, 0)
- if (m > 0) {
- while (m > 0) {
- // TODO: reverse
- log(">S" + m)
- m = map_get(game.move_major, m)
- ++ game.count
- }
- } else {
- m = map_get(game.move_minor, to, 0)
- while (m > 0) {
- // TODO: reverse
- log(">S" + m)
- m = map_get(game.move_minor, m)
- ++ game.count
- }
- game.major = 0
- }
-
- resume_move_supply_train()
- },
-}
-
-states.move_supply_train_OLD = {
+states.move_supply_train = {
inactive: "move",
prompt() {
prompt("Move supply train" + format_move(2))
@@ -1854,7 +1700,7 @@ states.move_supply_train_OLD = {
},
}
-states.move_general_NEW = {
+states.move_general = {
inactive: "move",
prompt() {
prompt("Move " + format_selected() + format_move(movement_range()))
@@ -1864,110 +1710,20 @@ states.move_general_NEW = {
let here = game.pos[who]
if (game.count === 0) {
- if (may_unstack()) {
- if (game.selected.length > 1)
- view.actions.detach = 1
- else
- view.actions.detach = 0
- }
-
- let s_take = count_stacked_take()
- let s_give = count_stacked_give()
- let u_take = count_unstacked_take()
- let u_give = count_unstacked_give()
- if (s_take > 0 && u_give > 0)
- view.actions.take = 1
- if (s_give > 0 && u_take > 0)
- view.actions.give = 1
- } else {
- if (forbid_stopping_at(here)) {
- view.actions.stop = 0
+ if (game.fx === NEXT_TURN_CHEVERT_MAY_NOT_UNSTACK && game.pos[GEN_CHEVERT] === here) {
+ view.prompt += " Chevert may not unstack."
+ if (count_generals(here) === 3) {
+ // two options: leave alone, or leave with chevert
+ // to leave with chevert, detach non-chevert
+ // to leave alone, detach non-chevert, then detach chevert
+ if (game.selected.length === 3)
+ for (let p of game.selected)
+ if (p !== GEN_CHEVERT)
+ gen_action_piece(p)
+ if (game.selected.length === 2)
+ gen_action_piece(GEN_CHEVERT)
+ }
} else {
- gen_action_piece(who)
- view.actions.stop = 1
- }
- }
-
- view.move_major = game.move_major
- view.move_minor = game.move_minor
-
- if (game.move_major)
- map_for_each_key(game.move_major, s => { if (s !== here) gen_action_space_or_piece(s) })
- if (game.move_minor)
- map_for_each_key(game.move_minor, s => { if (s !== here) gen_action_space_or_piece(s) })
- },
- take() {
- game.state = "move_take"
- },
- give() {
- game.state = "move_give"
- },
- detach() {
- game.state = "move_detach"
- },
- piece(p) {
- if (p === game.selected[0])
- this.stop()
- else
- this.space(game.pos[p])
- },
- stop() {
- for (let p of game.selected)
- set_add(game.moved, p)
- end_move_piece()
- },
- space(to) {
- let who = game.selected[0]
- let path = [ to ]
-
- let m = map_get(game.move_major, to, -1)
- if (m >= 0) {
- while (m >= 0) {
- path.unshift(m)
- m = map_get(game.move_major, m, -1)
- ++game.count
- }
- } else {
- m = map_get(game.move_minor, to, -1)
- while (m >= 0) {
- path.unshift(m)
- m = map_get(game.move_minor, m, -1)
- ++game.count
- }
- game.major = 0
- }
-
- log("P" + who + " " + path.map(s => "S" + s).join(" > "))
-
- let stop = false
- path.shift() // skip start space
- for (let s of path)
- stop ||= move_general_to(s)
-
- if (stop)
- this.stop()
- else
- resume_move_general()
- },
-}
-
-states.move_general_OLD = {
- inactive: "move",
- prompt() {
- prompt("Move " + format_selected() + format_move(movement_range()))
- view.selected = game.selected
-
- let who = game.selected[0]
- let here = game.pos[who]
-
- if (game.count === 0) {
- if (may_unstack()) {
- /*
- if (game.selected.length > 1)
- view.actions.detach = 1
- else
- view.actions.detach = 0
- */
if (game.selected.length > 1)
for (let p of game.selected)
gen_action_piece(p)
@@ -2007,9 +1763,6 @@ states.move_general_OLD = {
give() {
game.state = "move_give"
},
- detach() {
- game.state = "move_detach"
- },
piece(p) {
if (game.count === 0) {
if (set_has(game.selected, p))
@@ -2042,24 +1795,6 @@ states.move_general_OLD = {
},
}
-states.move_general = states.move_general_OLD
-states.move_supply_train = states.move_supply_train_OLD
-//states.move_general = states.move_general_NEW
-//states.move_supply_train = states.move_supply_train_NEW
-
-states.move_detach = {
- inactive: "move",
- prompt() {
- prompt("Move " + format_selected() + ". Detach general from stack.")
- for (let p of game.selected)
- gen_action_piece(p)
- },
- piece(p) {
- set_delete(game.selected, p)
- game.state = "move_general"
- },
-}
-
states.move_take = {
inactive: "move",
prompt() {
@@ -2332,11 +2067,11 @@ function prompt_combat(value, extra = null) {
}
function inactive_attack() {
- return "attack " + format_combat(game.count)
+ return "combat " + format_combat(game.count)
}
function inactive_defend() {
- return "defend " + format_combat(-game.count)
+ return "combat " + format_combat(-game.count)
}
function goto_combat() {
@@ -2357,10 +2092,8 @@ function goto_combat() {
for (let a of from) {
for (let b of to) {
if (set_has(data.cities.adjacent[a], b)) {
- if (!forbid_attack(a, b)) {
- game.combat.push(a)
- game.combat.push(b)
- }
+ game.combat.push(a)
+ game.combat.push(b)
}
}
}
@@ -2897,7 +2630,7 @@ function search_retreat_possible_dfs(result, seen, here, range) {
if (has_any_piece(next))
continue
if (range === 1) {
- map_set(result, next, seen.slice())
+ set_add(result, next)
} else {
seen.push(next)
search_retreat_possible_dfs(result, seen, next, range - 1)
@@ -2924,12 +2657,9 @@ function search_retreat(loser, winner, range) {
}
let result = []
- map_for_each(possible, (s, path) => {
- if (map_get(distance, s, -1) === max) {
+ for (let s of possible)
+ if (map_get(distance, s, -1) === max)
result.push(s)
- result.push(path)
- }
- })
return result
}
@@ -2938,15 +2668,14 @@ states.retreat = {
prompt() {
prompt("Retreat " + format_selected() + " " + Math.abs(game.count) + " cities.")
view.selected = game.selected
- view.retreat = game.retreat
- map_for_each_key(game.retreat, gen_action_space)
+ for (let s of game.retreat)
+ gen_action_space(s)
},
space(to) {
push_undo()
log("Retreated to S" + to + ".")
- for (let p of game.selected) {
+ for (let p of game.selected)
game.pos[p] = to
- }
delete game.retreat
game.state = "retreat_done"
},
@@ -3578,7 +3307,7 @@ function goto_flip_5_or_6_from_nearest_train(power, list) {
}
states.flip_5_or_6_from_nearest_train = {
- inactive: "flip general out of supply",
+ inactive: "flip generals out of supply",
prompt() {
prompt("Flip " + format_selected() + " out of supply.")
for (let p of game.selected)
@@ -3592,7 +3321,7 @@ states.flip_5_or_6_from_nearest_train = {
}
states.flip_any_one_prussian_general_or_stack_in_austria_or_saxony = {
- inactive: "flip general out of supply",
+ inactive: "flip any one Prussian general/stack in Austria or Saxony out of supply",
prompt() {
prompt("Flip any one Prussian general/stack in Austria or Saxony out of supply.")
for (let p of game.selected)