summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor@ccxvii.net>2022-07-18 15:31:08 +0200
committerTor Andersson <tor@ccxvii.net>2022-11-17 13:11:25 +0100
commit7a924bf69ca6ec6a8396adf0e5b9d1ab8a7c1e0a (patch)
tree2a8d6142fb28ea17ddf62fab5a904f77bc248ff3
parentca8a901cb4ef47356e6e82784aea0a3e8762e7b6 (diff)
downloadrommel-in-the-desert-7a924bf69ca6ec6a8396adf0e5b9d1ab8a7c1e0a.tar.gz
Withdrawal path search.
-rw-r--r--rules.js99
1 files changed, 98 insertions, 1 deletions
diff --git a/rules.js b/rules.js
index ff66875..bf8832c 100644
--- a/rules.js
+++ b/rules.js
@@ -844,6 +844,99 @@ function search_move_bfs(from, cost, start, start_cost, road, max_cost) {
}
}
+function search_withdraw(start, is_pass_move) {
+ // recon=4, forced march=+1, rommel bonus=+1
+ let limit = is_pass_move ? 6 : 4
+
+ path_enemy.fill(0)
+ for (let u = 0; u < units.length; ++u) {
+ if (is_enemy_unit(u)) {
+ let x = unit_hex(u)
+ if (x >= first_hex && x <= last_hex)
+ path_enemy[x] = 1
+ }
+ }
+
+ let sline = game.active === AXIS ? game.axis_supply_line : game.allied_supply_line
+ let sdist = game.active === AXIS ? distance_to[EL_AGHEILA] : distance_to[ALEXANDRIA]
+
+ search_withdraw_bfs(path_from[0], path_cost[0], start, 0, limit, sline, sdist)
+ search_withdraw_bfs(path_from[1], path_cost[1], start, 1, limit + 1, sline, sdist)
+ search_withdraw_bfs(path_from[2], path_cost[2], start, 2, limit + 2, sline, sdist)
+ search_withdraw_bfs(path_from[4], path_cost[4], start, 4, limit + 4, sline, sdist)
+
+ let grid = new Array(hexcount).fill('-')
+ for (let x = first_hex; x <= last_hex; ++x) {
+ for (let speed = 4; speed >= 1; --speed) {
+ if (path_cost[0][x] <= speed)
+ grid[x] = speed
+ if (path_cost[1][x] <= speed + 1)
+ grid[x] = speed
+ if (path_cost[2][x] <= speed + 2)
+ grid[x] = speed
+ if (path_cost[4][x] <= speed + 4)
+ grid[x] = speed
+ }
+ }
+ grid[start] = '@'
+
+ debug_hexes2("reach", path_cost[0])
+}
+
+// Breadth First Search
+function search_withdraw_bfs(from, cost, start, road, max_cost, sline, sdist) {
+ let queue = [ start << 4 ]
+
+ from.fill(0)
+ cost.fill(15)
+ cost[start] = 0
+
+ while (queue.length > 0) {
+ let item = queue.shift()
+ let here = item >> 4
+ let here_cost = item & 15
+ let next_cost = here_cost + 1
+
+ for (let s = 0; s < 6; ++s) {
+ let next = here + hexnext[s]
+
+ // can't go off-map
+ if (next < first_hex || next > last_hex || !hex_exists[next])
+ continue
+
+ // already seen
+ if (cost[next] < 15)
+ continue
+
+ let side = to_side(here, next, s)
+ let max_side = side_limit[side]
+
+ // must follow supply line
+ if (sline[side] === 0)
+ continue
+
+ // may not increase distance to supply source (except Bardia/Ft. Capuzzo)
+ if (sdist[next] > sdist[here] && side !== BARDIA_FT_CAPUZZO)
+ continue
+
+ // must stay on road for current bonus
+ if (side_road[side] < road)
+ continue
+
+ // cannot enter enemy hex
+ if (path_enemy[next])
+ continue
+
+ from[next] = here
+ cost[next] = next_cost
+
+ // enough movement allowance to keep going
+ if (next_cost < max_cost)
+ queue.push(next << 4 | next_cost)
+ }
+ }
+}
+
function can_move_to(to, road, speed) {
// TODO: engagement & hexside limit
if (road >= 4 && path_cost[4][to] <= speed + 4)
@@ -1552,6 +1645,7 @@ states.refuse_battle_who = {
end_retreat() {
clear_undo()
release_hex_control(game.from1)
+ game.from1 = 0
game.state = 'refuse_battle'
}
}
@@ -1561,7 +1655,10 @@ states.refuse_battle_to = {
prompt() {
view.prompt = `Withdraw: Select destination.`
let who = game.selected[0]
- search_move(game.from1, 0, 4)
+
+ update_supply_networks()
+
+ search_withdraw(game.from1, false)
gen_withdraw_group_move(who, game.from1)
gen_action_unit(who)
},