summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor@ccxvii.net>2022-07-25 11:38:55 +0200
committerTor Andersson <tor@ccxvii.net>2022-11-17 13:11:26 +0100
commitf3e39d636cb1281e1fbc55abae28b1f2317b743a (patch)
tree94fbfea3a21b805da64fc919de07510819855eb8
parent76b763521928ff2a11c04f022d4b2d1a67357ed5 (diff)
downloadrommel-in-the-desert-f3e39d636cb1281e1fbc55abae28b1f2317b743a.tar.gz
regroup move forward search
-rw-r--r--rules.js227
1 files changed, 120 insertions, 107 deletions
diff --git a/rules.js b/rules.js
index 0726a42..312faaa 100644
--- a/rules.js
+++ b/rules.js
@@ -605,6 +605,14 @@ function for_each_undisrupted_friendly_unit_in_hex(x, fn) {
fn(u)
}
+function for_each_undisrupted_and_unmoved_friendly_unit_in_hex(x, fn) {
+ // TODO: first/last_enemy_unit
+ for (let u = 0; u < units.length; ++u)
+ if (is_friendly_unit(u) && !is_unit_disrupted(u) && unit_hex(u) === x && !is_unit_moved(u))
+ fn(u)
+}
+
+
function for_each_undisrupted_friendly_unit_in_hex_or_adjacent(x, fn) {
// TODO: first/last_enemy_unit
for (let u = 0; u < units.length; ++u)
@@ -1172,9 +1180,9 @@ function adjacent_hex_has_undisrupted_friendly_unit(here) {
return false
}
-function max_speed_of_undisrupted_friendly_unit_in_hex(from) {
+function max_speed_of_undisrupted_and_unmoved_friendly_unit_in_hex(from) {
let max_speed = 0
- for_each_undisrupted_friendly_unit_in_hex(from, u => {
+ for_each_undisrupted_and_unmoved_friendly_unit_in_hex(from, u => {
let s = unit_speed(u)
if (s > max_speed)
max_speed = s
@@ -1184,7 +1192,7 @@ function max_speed_of_undisrupted_friendly_unit_in_hex(from) {
function find_valid_regroup_destinations(from, rommel) {
// TODO: forced march
- let speed = max_speed_of_undisrupted_friendly_unit_in_hex(from)
+ let speed = max_speed_of_undisrupted_and_unmoved_friendly_unit_in_hex(from)
if (speed > 0) {
search_move(from, speed + rommel)
for (let x of all_hexes)
@@ -1490,9 +1498,117 @@ function goto_move() {
log(`Group move from #${game.from2}.`)
}
log_br()
- game.state = 'move_who'
+ game.state = 'move'
}
+states.move = {
+ inactive: "move",
+ prompt() {
+ view.prompt = `Move: Select unit to move.`
+
+ let rommel1 = (game.rommel === 1) ? 1 : 0
+ let rommel2 = (game.rommel === 2) ? 1 : 0
+
+ if (game.selected < 0) {
+
+ // Select Group Move 1
+ if (!game.to1 && game.from1) {
+ if (!is_battle_hex(game.from1)) {
+ for_each_undisrupted_and_unmoved_friendly_unit_in_hex(game.from1, u => {
+ gen_action_unit(u)
+ })
+ }
+ }
+
+ // Select Group Move 2
+ if (!game.to2 && game.from2) {
+ if (!is_battle_hex(game.from2)) {
+ for_each_undisrupted_and_unmoved_friendly_unit_in_hex(game.from2, u => {
+ gen_action_unit(u)
+ })
+ }
+ }
+
+ // Select Regroup Move 1
+ if (game.to1) {
+ for_each_hex_and_adjacent_hex(game.from1, from => {
+ let speed = max_speed_of_undisrupted_and_unmoved_friendly_unit_in_hex(from)
+ if (speed > 0 && !has_enemy_unit(from)) {
+ search_move(from, speed + rommel1)
+ for_each_undisrupted_and_unmoved_friendly_unit_in_hex(from, u => {
+ if (can_move_to(game.to1, unit_speed(u) + rommel1))
+ gen_action_unit(u)
+ })
+ }
+ })
+ }
+
+ // Select Regroup Move 2
+ if (game.to1) {
+ for_each_hex_and_adjacent_hex(game.from2, from => {
+ let speed = max_speed_of_undisrupted_and_unmoved_friendly_unit_in_hex(from)
+ if (speed > 0 && !has_enemy_unit(from)) {
+ search_move(from, speed + rommel2)
+ for_each_undisrupted_and_unmoved_friendly_unit_in_hex(from, u => {
+ if (can_move_to(game.to2, unit_speed(u) + rommel2))
+ gen_action_unit(u)
+ })
+ }
+ })
+ }
+
+ // Retreat
+ let has_retreat_hex = false
+ if (!game.to1 && game.from1 && is_battle_hex(game.from1) && !set_has(game.partial_retreats, game.from1))
+ has_retreat_hex = true
+ if (!game.to2 && game.from2 && is_battle_hex(game.from2) && !set_has(game.partial_retreats, game.from2))
+ has_retreat_hex = true
+ if (game.to1 && !has_enemy_unit(game.to1)) {
+ for_each_hex_and_adjacent_hex(game.from1, x => {
+ if (has_undisrupted_friendly_unit(x) && is_battle_hex(x) && !set_has(game.partial_retreats, x))
+ has_retreat_hex = true
+ })
+ }
+ if (game.to2 && !has_enemy_unit(game.to2)) {
+ for_each_hex_and_adjacent_hex(game.from2, x => {
+ if (has_undisrupted_friendly_unit(x) && is_battle_hex(x) && !set_has(game.partial_retreats, x))
+ has_retreat_hex = true
+ })
+ }
+ if (has_retreat_hex)
+ gen_action('retreat')
+
+ gen_action('end_move')
+ } else {
+
+ // Deselect
+ gen_action_unit(game.selected)
+
+ // Move
+ if (game.turn_option === 'pass')
+ gen_move(search_withdraw)
+ else
+ gen_move(search_move)
+
+ }
+ },
+ unit(who) {
+ apply_select(who)
+ },
+ hex(to) {
+ apply_move(to)
+ },
+ retreat() {
+ push_undo()
+ log_br()
+ game.state = 'retreat_from'
+ },
+ end_move() {
+ clear_undo()
+ log_br()
+ end_move_phase()
+ }
+}
function gen_move(search_fn) {
let rommel1 = (game.rommel === 1) ? 1 : 0
@@ -1602,109 +1718,6 @@ function move_unit(who, to, speed) {
}
}
-states.move_who = {
- inactive: "move",
- prompt() {
- view.prompt = `Move: Select unit to move.`
-
- let rommel1 = (game.rommel === 1) ? 1 : 0
- let rommel2 = (game.rommel === 2) ? 1 : 0
-
- if (game.selected < 0) {
-
- // Select Group Move 1
- if (!game.to1 && game.from1) {
- if (!is_battle_hex(game.from1)) {
- for_each_undisrupted_friendly_unit_in_hex(game.from1, u => {
- if (!is_unit_moved(u))
- gen_action_unit(u)
- })
- }
- }
-
- // Select Group Move 2
- if (!game.to2 && game.from2) {
- if (!is_battle_hex(game.from2)) {
- for_each_undisrupted_friendly_unit_in_hex(game.from2, u => {
- if (!is_unit_moved(u))
- gen_action_unit(u)
- })
- }
- }
-
- // Select Regroup Move 1
- if (game.to1) {
- search_move(game.to1, 4 + rommel1)
- for_each_undisrupted_friendly_unit_in_hex_or_adjacent(game.from1, u => {
- if (!is_unit_moved(u) && can_move_to(game.to1, unit_speed(u) + rommel1))
- if (!is_battle_hex(unit_hex(u)))
- gen_action_unit(u)
- })
- }
-
- // Select Regroup Move 2
- if (game.to1) {
- search_move(game.to2, 4 + rommel1)
- for_each_undisrupted_friendly_unit_in_hex_or_adjacent(game.from2, u => {
- if (!is_unit_moved(u) && can_move_to(game.to2, unit_speed(u) + rommel2))
- if (!is_battle_hex(unit_hex(u)))
- gen_action_unit(u)
- })
- }
-
- // Retreat
- let has_retreat_hex = false
- if (!game.to1 && game.from1 && is_battle_hex(game.from1) && !set_has(game.partial_retreats, game.from1))
- has_retreat_hex = true
- if (!game.to2 && game.from2 && is_battle_hex(game.from2) && !set_has(game.partial_retreats, game.from2))
- has_retreat_hex = true
- if (game.to1 && !has_enemy_unit(game.to1)) {
- for_each_hex_and_adjacent_hex(game.from1, x => {
- if (has_undisrupted_friendly_unit(x) && is_battle_hex(x) && !set_has(game.partial_retreats, x))
- has_retreat_hex = true
- })
- }
- if (game.to2 && !has_enemy_unit(game.to2)) {
- for_each_hex_and_adjacent_hex(game.from2, x => {
- if (has_undisrupted_friendly_unit(x) && is_battle_hex(x) && !set_has(game.partial_retreats, x))
- has_retreat_hex = true
- })
- }
- if (has_retreat_hex)
- gen_action('retreat')
-
- gen_action('end_move')
- } else {
-
- // Deselect
- gen_action_unit(game.selected)
-
- // Move
- if (game.turn_option === 'pass')
- gen_move(search_withdraw)
- else
- gen_move(search_move)
-
- }
- },
- unit(who) {
- apply_select(who)
- },
- hex(to) {
- apply_move(to)
- },
- retreat() {
- push_undo()
- log_br()
- game.state = 'retreat_from'
- },
- end_move() {
- clear_undo()
- log_br()
- end_move_phase()
- }
-}
-
// === RETREAT ===
function can_select_retreat_hex() {