From 7ca587623a2c3cc684eac2c7c9ce59eb4e1dc2f3 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Sat, 6 Aug 2022 16:45:43 +0200 Subject: Reveal minefields moved through. --- play.js | 28 +++++++------ rules.js | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 122 insertions(+), 40 deletions(-) diff --git a/play.js b/play.js index 866f1c6..4a56239 100644 --- a/play.js +++ b/play.js @@ -632,18 +632,22 @@ function update_map() { ui.months[i].classList.toggle("now", i === view.month) } - for (let i = ui.minefields.length; i < view.minefields.length; ++i) { - let elt = ui.minefields[i] = document.createElement("div") - elt.className = "minefield" - ui.minefields_holder.appendChild(elt) - } - for (let i = view.minefields.length; i < ui.minefields.length; ++i) { - ui.minefields[i].remove() - } - for (let i = 0; i < view.minefields.length; ++i) { - let hex = view.minefields[i] - ui.minefields[i].style.left = (ui.hex_x[hex] - 40) + "px" - ui.minefields[i].style.top = (ui.hex_y[hex] + 4) + "px" + if (view.minefields) { + for (let i = ui.minefields.length; i < view.minefields.length; ++i) { + let elt = ui.minefields[i] = document.createElement("div") + elt.className = "minefield" + ui.minefields_holder.appendChild(elt) + } + for (let i = view.minefields.length; i < ui.minefields.length; ++i) + ui.minefields[i].remove() + for (let i = 0; i < view.minefields.length; ++i) { + let hex = view.minefields[i] + ui.minefields[i].style.left = (ui.hex_x[hex] - 40) + "px" + ui.minefields[i].style.top = (ui.hex_y[hex] + 4) + "px" + } + } else { + for (let i = 0; i < ui.minefields.length; ++i) + ui.minefields[i].remove() } for (let hex = 0; hex < stack.length; ++hex) { diff --git a/rules.js b/rules.js index 0930ef5..6a8a636 100644 --- a/rules.js +++ b/rules.js @@ -171,6 +171,11 @@ const SS_BENGHAZI = 3 const SS_TOBRUK = 4 const SS_OASIS = 5 +const MF_AXIS = 0 +const MF_ALLIED = 1 +const MF_VISIBLE = 2 +const MF_REVEAL = 3 + const region_egypt = regions["Egypt"] const region_egypt_and_libya = regions["Libya"].concat(regions["Egypt"]) const region_libya_and_sidi_omar = regions["Libya"].concat(regions["Sidi Omar"]) @@ -1483,10 +1488,7 @@ function friendly_supply_network() { // === PATHING === -// NOTE: we don't actually need path_from but we can use it to show paths taken in client -// NOTE: we may need the path to reveal minefields moved through const path_from = [ new Array(hexcount), new Array(hexcount), new Array(hexcount), null, new Array(hexcount) ] - const path_cost = [ new Array(hexcount), new Array(hexcount), new Array(hexcount), null, new Array(hexcount) ] const path_valid = new Array(hexcount) @@ -1735,6 +1737,16 @@ function can_move_to(to, speed) { return false } +function move_road(to, speed) { + if (path_cost[4][to] <= speed + 4) + return 4 + if (path_cost[2][to] <= speed + 2) + return 2 + if (path_cost[1][to] <= speed + 1) + return 1 + return 0 +} + function max_speed_of_undisrupted_and_unmoved_friendly_unit_in_hex(from) { let max_speed = 0 for_each_undisrupted_and_unmoved_friendly_unit_in_hex(from, u => { @@ -1756,6 +1768,33 @@ function find_valid_regroup_destinations(from, rommel) { } } +// === MINEFIELDS === + +function visit_hex(x) { + let mf_enemy = (game.active === AXIS) ? MF_AXIS : MF_ALLIED + if (set_has(game.minefields[mf_enemy], x)) + set_add(game.minefields[MF_REVEAL], x) + console.log("VISIT", x, hex_name[x]) +} + +function visit_path(from, to, speed) { + let road = move_road(to, speed) + while (to && to !== from) { + visit_hex(to) + to = path_from[road][to] + } +} + +function reveal_visited_minefields() { + for (let x of game.minefields[MF_REVEAL]) { + log(`Minefield at #${x}.`) + set_delete(game.minefields[MF_AXIS], x) + set_delete(game.minefields[MF_ALLIED], x) + set_add(game.minefields[MF_VISIBLE], x) + } + set_clear(game.minefields[MF_REVEAL]) +} + // === SUPPLY COMMITMENT & TURN OPTION === function goto_turn_option() { @@ -2341,6 +2380,7 @@ states.select_moves = { }, end_turn() { clear_undo() + reveal_visited_minefields() goto_final_supply_check() } } @@ -2816,7 +2856,7 @@ function move_unit(who, to, speed, move) { if (game.hexside.forced[0]) forced_march_via(who, game.hexside.via[0], to, move) else - engage_via(who, game.hexside.via[0], to) + engage_via(who, game.hexside.via[0], to, move) delete game.hexside } else { game.state = 'engage_via' @@ -2825,6 +2865,7 @@ function move_unit(who, to, speed, move) { else { log(`>from #${from} to #${to}`) + visit_path(from, to, speed) set_unit_moved(who) set_unit_hex(who, to) } @@ -2838,6 +2879,14 @@ states.forced_march_via = { gen_action_hex(x) }, hex(via) { + let rommel1 = (game.rommel === 1) ? 1 : 0 + let rommel2 = (game.rommel === 2) ? 1 : 0 + let who = game.hexside.who + let from = unit_hex(who) + let speed = unit_speed[who] + + search_move(from, speed + 1 + (rommel1 | rommel2)) + forced_march_via(game.hexside.who, via, game.hexside.to, game.hexside.move) delete game.hexside game.state = 'move' @@ -2855,22 +2904,39 @@ states.engage_via = { gen_action_hex(game.hexside.via[i]) }, forced_march(via) { + let rommel1 = (game.rommel === 1) ? 1 : 0 + let rommel2 = (game.rommel === 2) ? 1 : 0 + let who = game.hexside.who + let from = unit_hex(who) + let speed = unit_speed[who] + search_move(from, speed + 1 + (rommel1 | rommel2)) + forced_march_via(game.hexside.who, via, game.hexside.to, game.hexside.move) delete game.hexside game.state = 'move' }, hex(via) { - engage_via(game.hexside.who, via, game.hexside.to) + let rommel1 = (game.rommel === 1) ? 1 : 0 + let rommel2 = (game.rommel === 2) ? 1 : 0 + let who = game.hexside.who + let from = unit_hex(who) + let speed = unit_speed[who] + search_move(from, speed + (rommel1 | rommel2)) + + engage_via(game.hexside.who, via, game.hexside.to, game.hexside.move) delete game.hexside game.state = 'move' } } function forced_march_via(who, via, to, move) { + let speed = unit_speed[who] + (game.rommel === move ? 1 : 0) let from = unit_hex(who) set_unit_moved(who) set_unit_hex(who, via) + visit_path(from, via, speed) + // remember where we should advance to / return to if ((move === 1 && game.to1) || (move === 2 && game.to2)) game.forced.push([who, to, from]) @@ -2889,12 +2955,25 @@ function forced_march_via(who, via, to, move) { log(`>forced march from #${from} via #${via} to #${to}`) } -function engage_via(who, via, to) { +function engage_via(who, via, to, move) { + let speed = unit_speed[who] + (game.rommel === move ? 1 : 0) let from = unit_hex(who) set_unit_moved(who) set_unit_hex(who, to) + visit_path(from, via, speed) + visit_hex(to) + + if (from !== via) + log(`>from #${from} via #${via} to #${to}`) + else + log(`>from #${from} to #${to}`) + + engage_via_hexside(who, via, to) +} + +function engage_via_hexside(who, via, to) { let side = to_side_id(via, to) if (game.side_limit[side]) game.side_limit[side] = 2 @@ -2913,11 +2992,6 @@ function engage_via(who, via, to) { claim_hex_control_for_defender(to) set_add(game.active_battles, to) } - - if (from !== via) - log(`>from #${from} via #${via} to #${to}`) - else - log(`>from #${from} to #${to}`) } // === FORCED MARCHES === @@ -2944,8 +3018,9 @@ states.forced_marches = { let roll = roll_die() if (roll >= 4) { log(`Forced March roll ${die_face_hit[roll]} success.`) + visit_hex(to) if (has_enemy_unit(to)) { - engage_via(who, via, to, false) + engage_via_hexside(who, via, to, false) } else { set_unit_hex(who, to) log(`>from #${via} to #${to}`) @@ -3630,6 +3705,8 @@ function is_mandatory_combat(fortress) { function goto_combat_phase() { set_active_player() + reveal_visited_minefields() + if (game.turn_option === 'pass') { if (is_mandatory_combat(BARDIA)) return goto_rout(BARDIA, false, goto_combat_phase) @@ -4673,12 +4750,12 @@ function count_secret_minefields() { let n = 0 if (is_axis_player()) { let network = game.buildup.axis_network - for (let x of game.axis_minefields) + for (let x of game.minefields[MF_AXIS]) if (network[x]) ++n } else { let network = game.buildup.allied_network - for (let x of game.allied_minefields) + for (let x of game.minefields[MF_ALLIED]) if (network[x]) ++n } @@ -5732,10 +5809,8 @@ exports.setup = function (seed, scenario, options) { raiders: [], recover: [], - axis_minefields: [], - allied_minefields: [], - reveal_minefields: [], // to be revealed at end of movement - minefields: [], // revealed to both players + // axis/allied/visible/to-be-revealed + minefields: [[],[],[],[]], // revealed to both players // fortress control fortress: 7, @@ -5810,22 +5885,25 @@ exports.view = function(state, current) { allied_sides: game.allied_sides, } + let player_minefields = null if (current === AXIS) { view.cards = game.axis_hand - if (game.axis_minefields.length > 0) - view.minefields = game.minefields.concat(game.axis_minefields) - else - view.minefields = game.minefields + if (game.minefields[MF_AXIS].length > 0) + player_minefields = game.minefields[MF_AXIS] } else if (current === ALLIED) { view.cards = game.allied_hand - if (game.allied_minefields.length > 0) - view.minefields = game.minefields.concat(game.allied_minefields) - else - view.minefields = game.minefields + if (game.minefields[MF_ALLIED].length > 0) + player_minefields = game.minefields[MF_ALLIED] } - else { - view.minefields = game.minefields + if (game.minefields[MF_VISIBLE].length > 0) { + if (player_minefields) + view.minefields = game.minefields[MF_VISIBLE].concat(player_minefields) + else + view.minefields = game.minefields[MF_VISIBLE] + } else { + if (player_minefields) + view.minefields = player_minefields } if (current === game.active) -- cgit v1.2.3