diff options
author | Tor Andersson <tor@ccxvii.net> | 2023-08-12 23:46:58 +0200 |
---|---|---|
committer | Tor Andersson <tor@ccxvii.net> | 2023-10-01 16:11:21 +0200 |
commit | 338ff92bb17b6dab33a5e2896783615163315432 (patch) | |
tree | d04e6ac9fa23f027c30b137e3196ebc2d54d2fa0 | |
parent | e35f28bf0a8618213f79051d6cf87552ad7db226 (diff) | |
download | waterloo-campaign-1815-338ff92bb17b6dab33a5e2896783615163315432.tar.gz |
Tint moves that stop/flip.
-rw-r--r-- | data.js | 4 | ||||
-rw-r--r-- | play.js | 10 | ||||
-rw-r--r-- | rules.js | 84 |
3 files changed, 64 insertions, 34 deletions
@@ -20,8 +20,8 @@ data.map = { ], bridges: [[1117,1218],[1121,1221],[1215,1314],[1736,1737],[1737,1738],[1221,1120]], towns: [1015,1018,1021,1024,1026,1100,1117,1118,1129,1201,1204,1209,1211,1215,1217,1221,1239,1340,1401,1407,1423,1433,1516,1526,1528,1534,1601,1603,1605,1623,1631,1716,1728,1737,1800,1810,1821,1825,1830,1903,1911,1915,1916,1919,1922,1928,1932,2001,2027,2035,2119,2122,2123,2219,2222,2223,2230,2308,2315,2317,2324,2327,2333,2337,2404,2500,2521,2529,2537,2604,2609,2618,2623,2715,2721,2723,2725,2730,2733,2736,2739,2827,2829,2840,2911,2936,3002,3013,3018,3020,3031,3125,3129,3135,3138,3204,3206,3226,3231,3233,3234,3240,3313,3327,3328,3402,3408,3417,3418,3438,3441,3512,3514,3523,3528,3614,3616,3617,3631,3636,3705,3708,3715,3718,3719,3723,3803,3828,3832,3915,3919,3925,3933,4006,4038], - streams: [1124,1224,1300,1324,1501,1502,1600,2038,2138,2507,2524,2540,2624,2625,2637,2641,2718,2737,2741,2808,2817,2820,2821,2838,2905,2907,2920,2921,2938,3021,3025,3041,3118,3141,3205,3207,3219,3220,3221,3222,3223,3225,3323,3324,3325,3406,3506,3517,3518,3520,3521,3534,3536,3604,3619,3622,3623,3624,3637,3706,3707,3735,3739,3806,3820,3837,3920,3937,4007,4021,4027,4039], - all_streams: [1021,1024,1120,1124,1224,1300,1314,1324,1401,1415,1501,1502,1514,1600,1601,1603,1604,1704,1837,1937,2038,2138,2407,2507,2524,2540,2604,2608,2609,2620,2621,2624,2625,2637,2641,2704,2708,2718,2719,2721,2724,2725,2737,2740,2741,2805,2808,2817,2820,2821,2825,2838,2840,2905,2906,2907,2915,2916,2917,2920,2921,2925,2938,2940,3006,3017,3018,3019,3020,3021,3022,3025,3039,3040,3041,3106,3117,3118,3121,3122,3125,3141,3205,3207,3219,3220,3221,3222,3223,3225,3226,3305,3306,3320,3323,3324,3325,3406,3423,3502,3503,3506,3517,3518,3520,3521,3523,3534,3535,3536,3604,3605,3606,3607,3619,3622,3623,3624,3635,3637,3703,3704,3705,3706,3707,3708,3709,3710,3711,3712,3713,3714,3719,3723,3735,3736,3739,3802,3803,3806,3813,3820,3824,3825,3836,3837,3840,3906,3920,3925,3937,3938,3939,4007,4021,4026,4027,4038,4039], + only_streams: [1124,1224,1300,1324,1501,1502,1600,2038,2138,2507,2524,2540,2624,2625,2637,2641,2718,2737,2741,2808,2817,2820,2821,2838,2905,2907,2920,2921,2938,3021,3025,3041,3118,3141,3205,3207,3219,3220,3221,3222,3223,3225,3323,3324,3325,3406,3506,3517,3518,3520,3521,3534,3536,3604,3619,3622,3623,3624,3637,3706,3707,3735,3739,3806,3820,3837,3920,3937,4007,4021,4027,4039], + streams: [1021,1024,1120,1124,1224,1300,1314,1324,1401,1415,1501,1502,1514,1600,1601,1603,1604,1704,1837,1937,2038,2138,2407,2507,2524,2540,2604,2608,2609,2620,2621,2624,2625,2637,2641,2704,2708,2718,2719,2721,2724,2725,2737,2740,2741,2805,2808,2817,2820,2821,2825,2838,2840,2905,2906,2907,2915,2916,2917,2920,2921,2925,2938,2940,3006,3017,3018,3019,3020,3021,3022,3025,3039,3040,3041,3106,3117,3118,3121,3122,3125,3141,3205,3207,3219,3220,3221,3222,3223,3225,3226,3305,3306,3320,3323,3324,3325,3406,3423,3502,3503,3506,3517,3518,3520,3521,3523,3534,3535,3536,3604,3605,3606,3607,3619,3622,3623,3624,3635,3637,3703,3704,3705,3706,3707,3708,3709,3710,3711,3712,3713,3714,3719,3723,3735,3736,3739,3802,3803,3806,3813,3820,3824,3825,3836,3837,3840,3906,3920,3925,3937,3938,3939,4007,4021,4026,4027,4038,4039], names: { 1015: "Mortigny", 1018: "Couillet", @@ -97,9 +97,13 @@ function on_focus_piece(evt) { } function on_click_action(evt) { - if (evt.button === 0) + if (evt.button === 0) { if (send_action(evt.target.my_action, evt.target.my_id)) evt.stopPropagation() + if (evt.target.my_action_2) + if (send_action(evt.target.my_action_2, evt.target.my_id)) + evt.stopPropagation() + } } function toggle_pieces() { @@ -129,6 +133,7 @@ function build_hexes() { hex.onmouseenter = on_focus_hex hex.onmouseleave = on_blur hex.my_action = "hex" + hex.my_action_2 = "stop_hex" hex.my_id = hex_id if (data.map.names[hex_id]) hex.my_name = String(hex_id) + " (" + data.map.names[hex_id] + ")" @@ -190,7 +195,8 @@ function on_update() { for (let row = 0; row < data.map.rows; ++row) { for (let col = 0; col < data.map.cols; ++col) { let id = first_hex + row * 100 + col - ui.hexes[id].classList.toggle("action", is_action("hex", id)) + ui.hexes[id].classList.toggle("action", is_action("hex", id) || is_action("stop_hex", id)) + ui.hexes[id].classList.toggle("stop", is_action("stop_hex", id)) } } @@ -162,8 +162,6 @@ for (let road_id = 0; road_id < data.map.roads.length; ++road_id) { data_roads[road[k]-1000].push([road_id, k]) } -// console.log("ROAD", JSON.stringify(data_roads)) - function is_road(x) { return data_roads[x-1000].length > 0 } @@ -218,6 +216,7 @@ function update_zoc_imp(zoc, zoi, units) { } function update_zoc() { + console.log("update_zoc", zoc_valid) if (!zoc_valid) { zoc_valid = true zoc_cache.fill(0) @@ -556,7 +555,7 @@ function resume_battle_formation() { game.state = "battle_formation" update_zoc() for (let p of friendly_infantry_corps()) - if (piece_mode(p) && piece_is_in_enemy_zoc(p)) + if (!piece_mode(p) && piece_is_in_enemy_zoc(p)) return end_battle_formation() } @@ -573,8 +572,9 @@ function end_battle_formation() { states.advance_formation = { prompt() { prompt("Advance Formation.") + update_zoc() for (let p of friendly_infantry_corps()) - if (piece_mode(p) && piece_is_not_in_enemy_zoc(p)) + if (!piece_mode(p) && piece_is_not_in_enemy_zoc(p)) gen_action_piece(p) }, piece(p) { @@ -586,6 +586,7 @@ states.advance_formation = { states.battle_formation = { prompt() { prompt("Battle Formation.") + update_zoc() for (let p of friendly_infantry_corps()) if (piece_mode(p) && piece_is_in_enemy_zoc(p)) gen_action_piece(p) @@ -702,25 +703,51 @@ states.movement = { }, } +function is_stop_and_flip_move(x) { + if (!(move_seen[x-1000] & 2) && is_stream(x)) + return true + if (piece_is_infantry(game.who) && is_enemy_zoc(x)) + return true + if (piece_is_cavalry(game.who) && is_enemy_cav_zoc(x)) + return true + return false +} + states.movement_to = { prompt() { prompt("Move " + data.pieces[game.who].name + ".") update_zoc() - - gen_move(game.who) + search_move(game.who) + + for (let row = 0; row < data.map.rows; ++row) { + for (let col = 0; col < data.map.cols; ++col) { + let x = 1000 + row * 100 + col + if (move_seen[x-1000]) { + if (is_stop_and_flip_move(x)) + gen_action_stop_hex(x) + else + gen_action_hex(x) + } + } + } gen_action_piece(game.who) }, piece(p) { pop_undo() }, + stop_hex(x) { + this.hex(x) + }, hex(x) { update_zoc() + search_move(game.who) set_piece_hex(game.who, x) - if (is_stream(x)) + // off-road move into stream hex + if (!(move_seen[x-1000] & 2) && is_stream(x)) set_piece_mode(game.who, 1) if (piece_is_infantry(game.who) && is_enemy_zoc(x)) @@ -776,21 +803,18 @@ function can_move_into(here, next, hq_hex, hq_range, is_cav) { return true } -function must_stop(from, is_cav) { - // must stop in stream +function must_stop_offroad(from, is_cav) { if (is_stream(from)) return true - - // must stop in ZoC or ZoI - if (is_cav) { - if (is_enemy_zoc_or_cav_zoi(from)) - return true - } else { - if (is_enemy_zoc_or_zoi(from)) - return true - } + if (is_cav) + return is_enemy_zoc_or_cav_zoi(from) + return is_enemy_zoc_or_zoi(from) +} - return false +function must_stop_road(from, is_cav) { + if (is_cav) + return is_enemy_zoc_or_cav_zoi(from) + return is_enemy_zoc_or_zoi(from) } // OFF ROAD MOVEMENT SEARCH @@ -798,25 +822,21 @@ function must_stop(from, is_cav) { const move_seen = new Array(last_hex - 999).fill(0) const move_cost = new Array(last_hex - 999).fill(0) -function gen_move(p) { +function search_move(p) { move_seen.fill(0) let x = piece_hex(p) let m = piece_movement_allowance(p) for (let hq of data.pieces[p].hq) { let hq_hex = piece_hex(hq) if (is_map_hex(hq_hex)) { - search_move(x, m, hq_hex, piece_command_range(hq), piece_is_cavalry(p)) + search_move_offroad(x, m, hq_hex, piece_command_range(hq), piece_is_cavalry(p)) if (is_road(x)) search_move_road(x, m * 2, hq_hex, piece_command_range(hq), piece_is_cavalry(p)) } } - for (let x = 1000; x <= last_hex; ++x) - if (move_seen[x-1000]) - gen_action_hex(x) - } -function search_move(start, ma, hq_hex, hq_range, is_cav) { +function search_move_offroad(start, ma, hq_hex, hq_range, is_cav) { move_cost.fill(0) move_cost[start-1000] = ma let queue = [ start ] @@ -825,8 +845,8 @@ function search_move(start, ma, hq_hex, hq_range, is_cav) { let mp = move_cost[here-1000] - 1 for_each_adjacent(here, next => { if (can_move_into(here, next, hq_hex, hq_range, is_cav)) { - move_seen[next-1000] = 1 - if (mp > move_cost[next-1000] && !must_stop(next, is_cav)) { + move_seen[next-1000] |= 1 + if (mp > move_cost[next-1000] && !must_stop_offroad(next, is_cav)) { move_cost[next-1000] = mp queue.push(next) } @@ -861,8 +881,8 @@ function search_move_road_segment(queue, road, cur, dir, hq_hex, hq_range, is_ca let next = road[cur] if (!can_move_into(here, next, hq_hex, hq_range, is_cav)) break - move_seen[next-1000] = 1 - if (must_stop(next, is_cav)) + move_seen[next-1000] |= 2 + if (must_stop_road(next, is_cav)) return here = next cur += dir @@ -1004,6 +1024,10 @@ function gen_action_hex(hex) { gen_action("hex", hex) } +function gen_action_stop_hex(hex) { + gen_action("stop_hex", hex) +} + exports.view = function (state, player) { game = state |