summaryrefslogtreecommitdiff
path: root/rules.js
diff options
context:
space:
mode:
Diffstat (limited to 'rules.js')
-rw-r--r--rules.js240
1 files changed, 134 insertions, 106 deletions
diff --git a/rules.js b/rules.js
index 4e33e65..5a7658c 100644
--- a/rules.js
+++ b/rules.js
@@ -4,8 +4,6 @@ const max = Math.max
const min = Math.min
const abs = Math.abs
-const AUTOSELECT = false
-
var states = {}
var game = null
var view = null
@@ -2274,13 +2272,13 @@ states.turn_option = {
inactive: "turn option",
prompt() {
if (game.commit[0] === 0 && game.commit[1] === 0)
- view.prompt = `Turn Option: committed zero supply.`
+ view.prompt = `Turn Option: Committed zero supply.`
else if (game.commit[1] === 0)
- view.prompt = `Turn Option: committed ${game.commit[0]} real supply.`
+ view.prompt = `Turn Option: Committed ${game.commit[0]} real supply.`
else if (game.commit[0] === 0)
- view.prompt = `Turn Option: committed ${game.commit[1]} dummy supply.`
+ view.prompt = `Turn Option: Committed ${game.commit[1]} dummy supply.`
else
- view.prompt = `Turn Option: committed ${game.commit[0]} real and ${game.commit[1]} dummy supply.`
+ view.prompt = `Turn Option: Committed ${game.commit[0]} real and ${game.commit[1]} dummy supply.`
let hand = player_hand()
if (game.commit[0] + game.commit[1] < 3) {
@@ -2726,19 +2724,14 @@ function goto_initial_supply_check_recover() {
}
function goto_initial_supply_check_rout() {
- let n = 0, where = 0
- for (let x of all_hexes) {
- if (is_friendly_rout_hex(x)) {
- where = x
- n++
- }
- }
- if (n === 0)
- goto_turn_option()
- else if (AUTOSELECT && n === 1)
- goto_rout(where, false, goto_initial_supply_check_rout)
- else
+ let rout = false
+ for (let x of all_hexes)
+ if (is_friendly_rout_hex(x))
+ rout = true
+ if (rout)
game.state = 'initial_supply_check_rout'
+ else
+ goto_turn_option()
}
states.initial_supply_check_rout = {
@@ -2812,19 +2805,14 @@ function goto_final_supply_check_disrupt() {
}
function goto_final_supply_check_rout() {
- let n = 0, where = 0
- for (let x of all_hexes) {
- if (is_friendly_rout_hex(x)) {
- where = x
- n++
- }
- }
- if (n === 0)
- end_player_turn()
- else if (AUTOSELECT && n === 1)
- goto_rout(where, false, goto_final_supply_check_rout)
- else
+ let rout = false
+ for (let x of all_hexes)
+ if (is_friendly_rout_hex(x))
+ rout = true
+ if (rout)
game.state = 'final_supply_check_rout'
+ else
+ end_player_turn()
}
states.final_supply_check_rout = {
@@ -2971,18 +2959,18 @@ function has_valid_regroup_move_left() {
}
states.select_moves = {
- inactive: "move phase",
+ inactive: "movement",
prompt() {
show_move_commands()
if (game.turn_option === 'offensive') {
if (game.from1)
- view.prompt = `Designate second offensive move.`
+ view.prompt = `Movement: Designate second offensive move.`
else
- view.prompt = `Designate first offensive move.`
+ view.prompt = `Movement: Designate first offensive move.`
} else if (game.turn_option === 'blitz') {
- view.prompt = `Designate first blitz move.`
+ view.prompt = `Movement: Designate first blitz move.`
} else {
- view.prompt = `Designate ${game.turn_option} move.`
+ view.prompt = `Movement: Designate ${game.turn_option} move.`
}
let can_group_move = has_valid_group_move_left()
@@ -3089,10 +3077,10 @@ function list_valid_regroup_moves() {
}
states.group_move_from = {
- inactive: "move phase",
+ inactive: "movement",
prompt() {
show_move_commands()
- view.prompt = `Group Move: Select hex to move from.`
+ view.prompt = `Group Move: Select group to move.`
for (let x of game.group)
if (x !== game.from1 || game.to1)
@@ -3148,10 +3136,10 @@ states.group_move_from = {
}
states.regroup_move_command_point = {
- inactive: "move phase",
+ inactive: "movement",
prompt() {
show_move_commands()
- view.prompt = `Regroup Move: Designate the command point hex.`
+ view.prompt = `Regroup Move: Select the command point hex.`
if (game.turn_option !== 'pass') {
for (let x of game.regroup)
gen_action_hex(x)
@@ -3173,10 +3161,10 @@ states.regroup_move_command_point = {
}
states.regroup_move_destination = {
- inactive: "move phase",
+ inactive: "movement",
prompt() {
show_move_commands()
- view.prompt = `Regroup Move: Select destination hex.`
+ view.prompt = `Regroup Move: Select the destination hex.`
let cp, rommel
if (game.from2 === 0)
cp = game.from1, rommel = (game.rommel === 1 ? 1 : 0)
@@ -3313,19 +3301,20 @@ function can_end_move() {
}
states.move = {
- inactive: "move phase",
+ inactive: "movement",
prompt() {
let rommel1 = (game.rommel === 1) ? 1 : 0
let rommel2 = (game.rommel === 2) ? 1 : 0
if (game.selected < 0) {
- view.prompt = `Move: Select unit to move.`
+ let can_move = false
// 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)
+ can_move = true
})
}
}
@@ -3335,6 +3324,7 @@ states.move = {
if (!is_battle_hex(game.from2)) {
for_each_undisrupted_and_unmoved_friendly_unit_in_hex(game.from2, u => {
gen_action_unit(u)
+ can_move = true
})
}
}
@@ -3347,8 +3337,10 @@ states.move = {
if (fastest >= 0) {
search_current_move(fastest, false)
for_each_undisrupted_and_unmoved_friendly_unit_in_hex(from, u => {
- if (can_move_to(game.to1, unit_speed[u] + 1 + rommel1))
+ if (can_move_to(game.to1, unit_speed[u] + 1 + rommel1)) {
gen_action_unit(u)
+ can_move = true
+ }
})
}
}
@@ -3363,18 +3355,16 @@ states.move = {
if (fastest >= 0) {
search_current_move(fastest, false)
for_each_undisrupted_and_unmoved_friendly_unit_in_hex(from, u => {
- if (can_move_to(game.to2, unit_speed[u] + 1 + rommel2))
+ if (can_move_to(game.to2, unit_speed[u] + 1 + rommel2)) {
gen_action_unit(u)
+ can_move = true
+ }
})
}
}
})
}
- // Retreat
- if (can_select_retreat_hex())
- gen_action('retreat')
-
// Overrun
let has_overrun_hex = false
for (let x of all_hexes) {
@@ -3383,15 +3373,33 @@ states.move = {
break
}
}
-
if (has_overrun_hex) {
+ if (can_move)
+ view.prompt = `Movement: Select unit to move, or hex to overrun.`
+ else
+ view.prompt = `Movement: Select hex to overrun.`
gen_action('overrun')
} else {
- if (can_end_move())
- gen_action('end_move')
+ if (can_select_retreat_hex()) {
+ if (can_move)
+ view.prompt = `Movement: Select unit to move, or retreat after all other movement.`
+ else
+ view.prompt = `Movement: You may retreat.`
+ gen_action('retreat')
+ if (can_end_move())
+ gen_action('end_move')
+ } else {
+ if (can_end_move()) {
+ if (can_move)
+ view.prompt = `Movement: Select unit to move.`
+ else
+ view.prompt = `Movement: Done.`
+ gen_action('end_move')
+ }
+ }
}
} else {
- view.prompt = `Move: Select destination hex.`
+ view.prompt = `Movement: Select destination.`
// Deselect
gen_action_unit(game.selected)
@@ -3417,7 +3425,8 @@ states.move = {
},
retreat() {
push_undo()
- goto_retreat()
+ log_br()
+ game.state = 'retreat_from'
},
overrun() {
push_undo()
@@ -3443,9 +3452,9 @@ states.move = {
}
states.overrun = {
- inactive: "move phase",
+ inactive: "movement",
prompt() {
- view.prompt = `Overrun!`
+ view.prompt = `Movement: Select hex to overrun.`
for (let x of all_hexes)
if (is_enemy_rout_hex(x))
gen_action_hex(x)
@@ -3674,9 +3683,9 @@ function move_unit(who, to, speed, move) {
}
states.forced_march_via = {
- inactive: "move phase",
+ inactive: "movement",
prompt() {
- view.prompt = `Move: Select which path to take.`
+ view.prompt = `Movement: Select which path to take.`
view.selected = game.hexside.who
view.selected_hexes = game.hexside.to
@@ -3705,9 +3714,9 @@ states.forced_march_via = {
}
states.engage_via = {
- inactive: "move phase",
+ inactive: "movement",
prompt() {
- view.prompt = `Move: Select which hex side to cross.`
+ view.prompt = `Movement: Select which hex side to cross.`
view.selected = game.hexside.who
view.selected_hexes = game.hexside.to
@@ -3876,26 +3885,17 @@ function end_forced_marches() {
}
function goto_forced_marches_rout() {
- let friend_count = 0, friend_where = 0
- let enemy_count = 0, enemy_where = 0
+ let rout = false
for (let x of all_hexes) {
- if (is_friendly_rout_hex(x)) {
- friend_where = x
- friend_count++
- }
- if (is_enemy_rout_hex(x)) {
- enemy_where = x
- enemy_count++
- }
+ if (is_friendly_rout_hex(x))
+ rout = true
+ if (is_enemy_rout_hex(x))
+ rout = true
}
- if (friend_count + enemy_count === 0)
- goto_refuse_battle()
- else if (friend_count === 1 && enemy_count === 0)
- goto_rout(friend_where, false, goto_forced_marches_rout)
- else if (friend_count === 0 && enemy_count === 1)
- goto_rout(enemy_where, true, goto_forced_marches_rout)
- else
+ if (rout)
game.state = 'forced_marches_rout'
+ else
+ goto_refuse_battle()
}
states.forced_marches_rout = {
@@ -4011,15 +4011,6 @@ function can_select_retreat_hex() {
return false
}
-function goto_retreat() {
- log_br()
- game.state = 'retreat_from'
-
- // only one valid retreat hex
- if (!game.to1 && !game.from2 && is_valid_retreat_hex(game.from1))
- goto_retreat_who(game.from1)
-}
-
states.retreat_from = {
inactive: "retreat",
prompt() {
@@ -4064,14 +4055,16 @@ states.retreat_from = {
function goto_retreat_who(from) {
game.retreat = from
- game.state = 'retreat_who'
- game.retreat_units = []
if (game.turn_option === 'pass') {
+ game.state = 'retreat_full'
+ game.retreat_units = []
for_each_undisrupted_and_unmoved_friendly_unit_in_hex(game.retreat, u => {
if (can_unit_retreat(u))
game.retreat_units.push(u)
})
- apply_retreat()
+ } else {
+ game.state = 'retreat_who'
+ game.retreat_units = []
}
}
@@ -4113,6 +4106,18 @@ states.retreat_who = {
},
}
+states.retreat_full = {
+ inactive: "retreat",
+ prompt() {
+ view.prompt = `Retreat: All units must retreat.`
+ view.selected = game.retreat_units
+ gen_action('retreat')
+ },
+ retreat() {
+ apply_retreat()
+ },
+}
+
function apply_retreat() {
let full_retreat = true
for (let u of game.retreat_units)
@@ -4189,7 +4194,6 @@ function goto_retreat_move() {
states.retreat_move = {
inactive: "retreat",
prompt() {
- view.prompt = `Retreat!`
if (game.selected < 0) {
let done = true
for (let u of game.retreat_units) {
@@ -4198,9 +4202,14 @@ states.retreat_move = {
done = false
}
}
- if (done)
+ if (done) {
+ view.prompt = `Retreat: Done.`
gen_action('end_retreat')
+ } else {
+ view.prompt = `Retreat: Select unit to withdraw.`
+ }
} else {
+ view.prompt = `Retreat: Select destination.`
let rommel1 = (game.rommel === 1) ? 1 : 0
let rommel2 = (game.rommel === 2) ? 1 : 0
gen_action_unit(game.selected)
@@ -4283,17 +4292,26 @@ function goto_refuse_battle() {
states.refuse_battle = {
inactive: "refuse battle",
prompt() {
- view.prompt = `You may Refuse Battle from hexes just attacked.`
+ view.prompt = `Refuse Battle: You may retreat from hexes just attacked.`
+ view.selected_hexes = game.selected
for (let x of game.new_battles)
if (can_all_undisrupted_units_disengage_and_withdraw(x))
gen_action_hex(x)
+ if (game.selected >= 0)
+ gen_action('refuse')
gen_action('pass')
},
hex(x) {
- log_h4(`Refused battle at #${x}`)
- game.refuse = x
- set_delete(game.new_battles, x)
- goto_pursuit_fire_during_refuse_battle(x)
+ if (x === game.selected)
+ game.selected = -1
+ else
+ game.selected = x
+ },
+ refuse() {
+ game.refuse = pop_selected()
+ log_h4(`Refused battle at #${game.refuse}`)
+ set_delete(game.new_battles, game.refuse)
+ goto_pursuit_fire_during_refuse_battle(game.refuse)
},
pass() {
goto_combat_phase()
@@ -4313,16 +4331,20 @@ function goto_refuse_battle_move() {
states.refuse_battle_move = {
inactive: "refuse battle",
prompt() {
- view.prompt = `Refuse Battle: Withdraw units.`
if (game.selected < 0) {
let done = true
for_each_undisrupted_friendly_unit_in_hex(game.refuse, u => {
gen_action_unit(u)
done = false
})
- if (done)
+ if (done) {
+ view.prompt = `Refuse Battle: Done.`
gen_action('end_retreat')
+ } else {
+ view.prompt = `Refuse Battle: Select unit to withdraw.`
+ }
} else {
+ view.prompt = `Refuse Battle: Select destination.`
let speed = unit_speed[game.selected]
gen_action_unit(game.selected)
search_withdraw_retreat(game.selected, 0)
@@ -4450,16 +4472,20 @@ function goto_rout_move() {
states.rout_move = {
inactive: "rout",
prompt() {
- view.prompt = `Rout: Withdraw units.`
if (game.selected < 0) {
let done = true
for_each_friendly_unit_in_hex(game.rout.from, u => {
gen_action_unit(u)
done = false
})
- if (done)
+ if (done) {
+ view.prompt = `Rout: Done.`
gen_action('end_rout')
+ } else {
+ view.prompt = `Rout: Select unit to withdraw.`
+ }
} else {
+ view.prompt = `Rout: Select destination.`
let speed = unit_speed[game.selected]
let eliminate = true
search_withdraw_retreat(game.selected, 0)
@@ -4572,7 +4598,7 @@ function goto_combat_phase() {
states.select_active_battles = {
inactive: "combat phase",
prompt() {
- view.prompt = `Select active battles.`
+ view.prompt = `Combat: Select active battles.`
view.selected_hexes = game.active_battles
for (let x of all_hexes) {
if (!set_has(game.active_battles, x) && is_battle_hex(x))
@@ -4611,7 +4637,7 @@ states.select_active_battles = {
states.select_assault_battles = {
inactive: "combat phase",
prompt() {
- view.prompt = `Select assault battles.`
+ view.prompt = `Combat: Select assault battles.`
view.selected_hexes = game.assault_battles
for (let x of game.active_battles)
gen_action_hex(x)
@@ -4665,7 +4691,7 @@ function goto_select_battle() {
states.select_battle = {
inactive: "combat phase",
prompt() {
- view.prompt = `Select next battle to resolve.`
+ view.prompt = `Combat: Select next battle.`
view.active_battles = game.active_battles
view.assault_battles = game.assault_battles
for (let x of game.active_battles)
@@ -5306,7 +5332,7 @@ states.pursuit_fire = {
inactive: "pursuit fire",
show_pursuit: true,
prompt() {
- view.prompt = `Pursuit Fire.`
+ view.prompt = `Pursuit Fire: Fire or withhold.`
if (game.hits < count_hp_in_pursuit()) {
let slowest = slowest_undisrupted_enemy_unit_speed(game.pursuit)
for_each_undisrupted_friendly_unit_in_hex(game.pursuit, u => {
@@ -5331,7 +5357,7 @@ states.rout_fire = {
inactive: "rout fire",
show_pursuit: true,
prompt() {
- view.prompt = `Pursuit Fire (Rout).`
+ view.prompt = `Pursuit Fire: Fire or withhold.`
if (game.hits < count_hp_in_rout()) {
let slowest = slowest_enemy_unit_speed(game.pursuit)
for_each_undisrupted_friendly_unit_in_hex(game.pursuit, u => {
@@ -7042,8 +7068,10 @@ exports.view = function(state, current) {
if (current === game.active)
view.selected = game.selected
- if (states[game.state].show_battle)
+ if (states[game.state].show_battle) {
view.battle = game.battle
+ view.retreat = game.retreat_units
+ }
if (states[game.state].show_pursuit)
view.pursuit = game.pursuit
if (view.battle || view.pursuit) {