diff options
author | Tor Andersson <tor@ccxvii.net> | 2022-07-18 15:31:08 +0200 |
---|---|---|
committer | Tor Andersson <tor@ccxvii.net> | 2022-11-17 13:11:25 +0100 |
commit | 7a924bf69ca6ec6a8396adf0e5b9d1ab8a7c1e0a (patch) | |
tree | 2a8d6142fb28ea17ddf62fab5a904f77bc248ff3 /rules.js | |
parent | ca8a901cb4ef47356e6e82784aea0a3e8762e7b6 (diff) | |
download | rommel-in-the-desert-7a924bf69ca6ec6a8396adf0e5b9d1ab8a7c1e0a.tar.gz |
Withdrawal path search.
Diffstat (limited to 'rules.js')
-rw-r--r-- | rules.js | 99 |
1 files changed, 98 insertions, 1 deletions
@@ -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) }, |