diff options
Diffstat (limited to 'rules.js')
-rw-r--r-- | rules.js | 141 |
1 files changed, 114 insertions, 27 deletions
@@ -1,6 +1,6 @@ "use strict" -// TODO: legal pass withdrawal moves (reduce supply net, withdraw from fortress attack) +// TODO: valid pass withdrawal moves (reduce supply net, withdraw from fortress attack) // TODO: fortress combat in pass turns (must withdraw) // TODO: log summaries (deploy, rebuild, move, etc) @@ -1455,6 +1455,17 @@ function unit_supply_line(who) { return allied_supply_line() } +function unit_supply_network(who) { + switch (unit_supply(who)) { + case SS_BARDIA: return bardia_supply_network() + case SS_BENGHAZI: return benghazi_supply_network() + case SS_TOBRUK: return tobruk_supply_network() + } + if (is_axis_unit(who)) + return axis_supply_network() + return allied_supply_network() +} + function unit_supply_distance(who) { switch (unit_supply(who)) { case SS_BARDIA: return distance_to[BARDIA] @@ -1466,6 +1477,17 @@ function unit_supply_distance(who) { return distance_to[ALEXANDRIA] } +function unit_supply_source(who) { + switch (unit_supply(who)) { + case SS_BARDIA: return BARDIA + case SS_BENGHAZI: return BENGHAZI + case SS_TOBRUK: return TOBRUK + } + if (is_axis_unit(who)) + return EL_AGHEILA + return ALEXANDRIA +} + function friendly_supply_base() { if (is_axis_player()) return EL_AGHEILA @@ -1478,8 +1500,7 @@ function friendly_supply_network() { return allied_supply_network() } -function query_friendly_supply_network(x, y) { - // TODO: fortress supply +function query_friendly_supply_network(src, x, y) { let save_x let save_y if (is_axis_player()) { @@ -1488,7 +1509,7 @@ function query_friendly_supply_network(x, y) { if (y) save_y = presence_axis[y] if (x) presence_axis[x] = 0 if (y) presence_axis[y] = 1 - trace_supply_network(EL_AGHEILA) + trace_supply_network(src) if (x) presence_axis[x] = save_x if (y) presence_axis[y] = save_y } else { @@ -1497,7 +1518,7 @@ function query_friendly_supply_network(x, y) { if (y) save_y = presence_allied[y] if (x) presence_allied[x] = 0 if (y) presence_allied[y] = 1 - trace_supply_network(ALEXANDRIA) + trace_supply_network(src) if (x) presence_allied[x] = save_x if (y) presence_allied[y] = save_y } @@ -1795,26 +1816,33 @@ function is_network_reduced(reference, candidate) { return false } -function is_legal_withdrawal_from(x) { +function is_valid_withdrawal_from(x) { if (is_battle_hex(x)) { // can retreat, will always reduce supply network return can_all_units_disengage_and_withdraw(x); } else { // non-retreat withdrawal, check if network is reduced after we leave this hex - let ref_net = friendly_supply_network() - let new_net = query_friendly_supply_network(x, 0) - if (is_network_reduced(ref_net, new_net)) - return true + // TODO: mixed supply source in hex (supplied and unsupplied) + if (can_all_units_withdraw(x)) { + let who = fastest_undisrupted_friendly_unit(x) + if (is_unit_supplied(who)) { + let ref_net = unit_supply_network(who) + let new_net = query_friendly_supply_network(unit_supply_source(who), x, 0) + if (is_network_reduced(ref_net, new_net)) + return true + } + } } return false } -function is_legal_withdrawal_to(from, to) { +function is_valid_withdrawal_group_move(who, from, to) { + // TODO: pass actual source instead of sample unit if (is_battle_hex(from)) { return true } else { - let ref_net = friendly_supply_network() - let new_net = query_friendly_supply_network(from, to) + let ref_net = unit_supply_network(who) + let new_net = query_friendly_supply_network(unit_supply_source(who), from, to) if (is_network_reduced(ref_net, new_net)) return true } @@ -2476,7 +2504,7 @@ states.group_move_from = { } if (!mandatory) { for (let x of all_hexes) - if (has_undisrupted_friendly_unit(x) && is_legal_withdrawal_from(x)) + if (has_undisrupted_friendly_unit(x) && is_valid_withdrawal_from(x)) gen_action_hex(x) } } @@ -2506,6 +2534,16 @@ states.group_move_from = { game.state = 'select_moves' else goto_move() + + if (game.turn_option === 'pass') { + // Precalculate valid withdrawal move destinations here + let rommel1 = (game.rommel === 1) ? 1 : 0 + let who = fastest_undisrupted_friendly_unit(game.from1) + console.log("CALC WITHDRAWAL DESTINATIONS") + search_withdraw(who, 1 + rommel1) + game.withdraw = list_valid_withdrawal_group_moves(who, game.from1, unit_speed[who] + 1 + rommel1) + console.log("DONE") + } }, } @@ -2749,6 +2787,8 @@ states.move = { push_undo() // XXX clear_undo() log_br() + if (game.turn_option === 'pass') + delete game.withdraw end_movement() } } @@ -2816,6 +2856,15 @@ function gen_move() { } } +function list_valid_withdrawal_group_moves(who, from, speed) { + let result = [] + for (let to of all_hexes) + if (to != from) + if (can_move_to(to, speed) && is_valid_withdrawal_group_move(who, game.from1, to)) + result.push(to) + return result +} + function gen_withdraw() { let rommel1 = (game.rommel === 1) ? 1 : 0 let speed = unit_speed[game.selected] @@ -2824,9 +2873,9 @@ function gen_withdraw() { if (!game.to1 && game.from1 === from) { for (let to of all_hexes) { if (to != from) { - if (can_move_to(to, speed + rommel1) && is_legal_withdrawal_to(game.from1, to)) + if (can_move_to(to, speed + rommel1) && set_has(game.withdraw, to)) gen_action_hex(to) - else if (can_move_to(to, speed + 1 + rommel1) && is_legal_withdrawal_to(game.from1, to)) + else if (can_move_to(to, speed + 1 + rommel1) && set_has(game.withdraw, to)) gen_action_forced_march(to) } } @@ -3263,16 +3312,18 @@ function is_enemy_hexside(side) { } function can_unit_disengage_and_withdraw(who) { - let sline = unit_supply_line(who) - let sdist = unit_supply_distance(who) - let from = unit_hex(who) let result = false - for_each_adjacent_hex(from, to => { - let side = to_side_id(from, to) - if (is_friendly_hexside(side) && !has_enemy_unit(to)) - if (sline[side] && sdist[to] <= sdist[from]) - result = true - }) + if (is_unit_supplied(who)) { + let sline = unit_supply_line(who) + let sdist = unit_supply_distance(who) + let from = unit_hex(who) + for_each_adjacent_hex(from, to => { + let side = to_side_id(from, to) + if (is_friendly_hexside(side) && !has_enemy_unit(to)) + if (sline[side] && sdist[to] <= sdist[from]) + result = true + }) + } return result } @@ -3288,8 +3339,11 @@ function can_unit_disengage_and_move(who) { } function can_unit_disengage_and_withdraw_to(who, to, extra) { - search_withdraw_retreat(who, extra) - return can_move_to(to, unit_speed[who] + extra) + if (is_unit_supplied(who)) { + search_withdraw_retreat(who, extra) + return can_move_to(to, unit_speed[who] + extra) + } + return false } function can_unit_disengage_and_move_to(who, to, extra) { @@ -3567,6 +3621,16 @@ function can_all_units_disengage_and_withdraw(from) { return result } +function can_all_units_withdraw(from) { + let result = true + for_each_undisrupted_friendly_unit_in_hex(from, u => { + // No supply line to withdraw along! + if (!is_unit_supplied(u)) + result = false + }) + return result +} + states.refuse_battle = { inactive: "refuse battle", prompt() { @@ -4379,6 +4443,29 @@ function slowest_undisrupted_enemy_unit_speed(where) { return r } +function slowest_undisrupted_friendly_unit_speed(where) { + let r = 4 + for_each_undisrupted_friendly_unit_in_hex(where, u => { + let s = unit_speed[u] + if (s < r) + r = s + }) + return r +} + +function fastest_undisrupted_friendly_unit(where) { + let who = -1 + let r = 0 + for_each_undisrupted_friendly_unit_in_hex(where, u => { + let s = unit_speed[u] + if (s > r) { + who = u + r = s + } + }) + return who +} + function goto_rout_fire(where) { set_enemy_player() game.hits = 0 |