diff options
-rw-r--r-- | data.js | 2 | ||||
-rw-r--r-- | play.js | 1 | ||||
-rw-r--r-- | rules.js | 390 | ||||
-rw-r--r-- | tools/gendata.js | 3 |
4 files changed, 131 insertions, 265 deletions
@@ -1,6 +1,6 @@ const all_hexes = [7,8,9,10,30,31,32,33,34,35,36,37,38,39,40,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215] const hex_exists = [0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0] -const hex_road = [0,0,0,0,0,0,0,4,4,4,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,1,1,4,2,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,4,1,1,1,1,2,1,1,2,2,1,1,4,1,4,2,4,4,2,4,4,0,0,0,2,1,2,2,2,1,0,1,1,1,1,1,0,1,0,2,0,0,0,2,0,0,0,0,0,1,1,0,1,1,0,1,0,0,1,1,1,1,0,2,0,0,0,2,0,0,0,0,0,0,1,1,1,0,0,1,0,0,0,1,1,1,1,2,0,0,0,0,0,0,0,0,0,4,1,1,0,0,0,1,0,0,0,0,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0] +const hex_road = [0,0,0,0,0,0,0,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,1,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,1,1,2,2,2,4,4,2,4,4,4,4,4,4,4,4,4,4,4,0,0,0,4,2,2,2,2,2,0,1,2,2,2,2,0,1,0,2,0,0,0,2,0,0,0,0,0,4,2,0,1,1,0,1,0,0,1,2,1,1,0,2,0,0,0,2,0,0,0,0,0,0,4,1,1,0,0,1,0,0,0,1,1,1,1,2,0,0,0,0,0,0,0,0,0,4,4,1,0,0,0,1,0,0,0,0,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0] const side_road = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,4,4,0,0,4,0,4,0,4,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,4,4,0,4,4,0,0,0,0,0,0,0,1,4,1,2,4,4,0,4,2,0,4,0,4,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,4,1,0,1,1,0,0,1,0,0,2,1,2,2,0,2,2,1,0,4,2,1,2,2,0,2,0,0,4,2,1,4,0,1,4,0,0,4,0,1,4,0,0,4,0,2,4,0,0,4,0,0,4,2,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,4,0,2,0,0,2,0,2,2,0,0,0,0,0,0,0,1,0,0,0,1,0,1,2,0,0,2,1,0,2,1,0,0,1,2,0,0,0,0,0,1,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,4,0,0,1,2,0,0,0,1,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,4,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,1,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,1,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,1,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0,0,0,0,1,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] const side_limit = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,0,1,0,1,0,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,2,1,0,1,1,0,0,0,0,0,0,0,1,2,2,2,1,1,0,1,2,2,2,2,2,2,2,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,2,1,0,2,1,0,0,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,0,1,2,0,0,2,0,2,2,0,0,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,0,0,0,0,0,0,0,0,0,1,2,0,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,0,2,0,1,0,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,2,2,2,2,2,2,2,0,0,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] const hex_name = {"7":"El Garib","8":"Cyrene","9":"El Gubba","10":"Derna","30":"Tocra","31":"Barce","32":"Marawa","33":"Wadi Cuff","34":"Wadi Cuff E","35":"Gazala","36":"Acroma","37":"Tobruk","38":"Belhamed","39":"Gambut","40":"Bardia","54":"Benghazi","55":"Er Regima","56":"Charruba","57":"Charruba E","58":"Mechili","59":"Rotonda Segnali","60":"Sidi Mufta","61":"Bir Harmat","62":"El Adem","63":"Sidi Rezegh","64":"Ft. Capuzzo","65":"Sollum","66":"Buq Buq","67":"Sidi Barrani","68":"Sidi Barrani E","69":"Mersa Matruh","70":"Fuka","71":"El Daba","72":"El Alamein","73":"El Hamam","74":"Alexandria","78":"Ghemines","79":"Skeleidima","80":"Msus","81":"Msus E","82":"Tengeder W","83":"Tengeder","84":"Tengeder E","85":"Bir Hacheim","86":"Retma","87":"Bir Gubi","88":"Gabr Saleh","89":"Sidi Omar","90":"Bir Habata","91":"Sofafi","92":"Sofafi E","93":"Bir el Kenayis","94":"Bir Khalda","95":"Bir Khalda E","96":"Alam Halfa W","97":"Alam Halfa","98":"Alam Halfa E","103":"Beda Fomm","104":"Antelat","105":"Antelat E","106":"Ben Gania","107":"Ben Gania E","108":"Tengeder SE","109":"Bir Hacheim SW","110":"Bir Hacheim SE","111":"Retma SE","112":"Ft. Maddalena W","113":"Ft. Maddalena","114":"Ft. Maddalena E","115":"Bir Khamsa","116":"Bir el Qatrani","117":"Bir el Qatrani E","118":"Bir el Kenayis SE","119":"Bir Khalda SE","120":"El Himeimat W","121":"El Himeimat","122":"El Himeimat E","128":"Agedabia","129":"Jebel el Matar","130":"Haraga","131":"Haraga E","137":"Ft. Maddalena SW","138":"Ft. Maddalena SE","139":"Bir Khamsa SW","140":"Bir Fuad W","141":"Bir Fuad","142":"Bir Fuad E","151":"El Agheila","152":"Mersa Brega","153":"El Haseiat","154":"El Haseiat E","155":"Haraga SE","162":"Jarabub Oasis NW","163":"Jarabub Oasis NE","165":"Bir Fuad SW","166":"Bir Fuad SE","176":"Maaten Giofer","177":"Maaten Giofer E","178":"Sahaba","179":"Sahaba E","180":"Jalo Oasis NE","186":"Jarabub Oasis W","187":"Jarabub Oasis","188":"Jarabub Oasis E","189":"Siwa Oasis NE","200":"Maaten Giofer SW","201":"Maaten Giofer SE","202":"Sahaba SW","203":"Jalo Oasis W","204":"Jalo Oasis","205":"Jalo Oasis E","211":"Jarabub Oasis SW","212":"Siwa Oasis W","213":"Siwa Oasis","214":"Siwa Oasis E"} @@ -599,7 +599,6 @@ function on_update() { action_button("overrun", "Overrun") action_button("rommel", "Rommel") - action_button("stop", "Stop") action_button("retreat", "Retreat") action_button("partial_retreat", "Partial retreat") @@ -957,52 +957,63 @@ function print_path(who, from, to, road) { log(">" + p.join(" - ") + ".") } -function search_move(start, start_cost, start_road) { - // recon=4, forced march=+1, rommel bonus=+1 - let limit = 6 - +function search_init() { path_enemy.fill(0) - for (let u = 0; u < units.length; ++u) { - if (is_enemy_unit(u)) { - let x = unit_hex(u) - if (x >= first_hex && x <= last_hex) - path_enemy[x] = 1 - } - } - - search_move_bfs(path_from[0], path_cost[0], start, start_cost, 0, limit) - if (start_road >= 1) - search_move_bfs(path_from[1], path_cost[1], start, start_cost, 1, limit + 1) - if (start_road >= 2) - search_move_bfs(path_from[2], path_cost[2], start, start_cost, 2, limit + 2) - if (start_road >= 4) - search_move_bfs(path_from[4], path_cost[4], start, start_cost, 4, limit + 4) - - let grid = new Array(hexcount).fill('-') - for (let x = first_hex; x <= last_hex; ++x) { - for (let speed = 4; speed >= 1; --speed) { - if (path_cost[0][x] <= speed) - grid[x] = speed - if (path_cost[1][x] <= speed + 1) - grid[x] = speed - if (path_cost[2][x] <= speed + 2) - grid[x] = speed - if (path_cost[4][x] <= speed + 4) - grid[x] = speed - } - } - grid[start] = '@' + for_each_enemy_unit(u => { + let x = unit_hex(u) + if (x >= first_hex && x <= last_hex) + path_enemy[x] = 1 + }) +} - debug_hexes2("reach", path_cost[0]) +function search_move(start, limit) { + // Normal moves. + search_init() + search_move_bfs(path_from[0], path_cost[0], start, 0, limit) + if (hex_road[start] >= 1) + search_move_bfs(path_from[1], path_cost[1], start, 1, limit + 1) + if (hex_road[start] >= 2) + search_move_bfs(path_from[2], path_cost[2], start, 2, limit + 2) + if (hex_road[start] >= 4) + search_move_bfs(path_from[4], path_cost[4], start, 4, limit + 4) +} + +function search_retreat(start, limit) { + // (Non-withdrawal) Retreat moves may not cross enemy hex-sides, and may not engage. + search_init() + search_retreat_bfs(path_from[0], path_cost[0], start, 0, limit) + if (hex_road[start] >= 1) + search_retreat_bfs(path_from[1], path_cost[1], start, 1, limit + 1) + if (hex_road[start] >= 2) + search_retreat_bfs(path_from[2], path_cost[2], start, 2, limit + 2) + if (hex_road[start] >= 4) + search_retreat_bfs(path_from[4], path_cost[4], start, 4, limit + 4) +} + +function search_withdraw(start, limit) { + // Withdrawal moves may not cross enemy hex-sides, + // and must follow a supply line, + // and must move closer to the supply source, + // and may not engage. + let sline = game.active === AXIS ? game.axis_supply_line : game.allied_supply_line + let sdist = game.active === AXIS ? distance_to[EL_AGHEILA] : distance_to[ALEXANDRIA] + search_init() + search_withdraw_bfs(path_from[0], path_cost[0], start, 0, limit, sline, sdist) + if (hex_road[start] >= 1) + search_withdraw_bfs(path_from[1], path_cost[1], start, 1, limit + 1, sline, sdist) + if (hex_road[start] >= 2) + search_withdraw_bfs(path_from[2], path_cost[2], start, 2, limit + 2, sline, sdist) + if (hex_road[start] >= 4) + search_withdraw_bfs(path_from[4], path_cost[4], start, 4, limit + 4, sline, sdist) } // Breadth First Search -function search_move_bfs(from, cost, start, start_cost, road, max_cost) { - let queue = [ start << 4 | start_cost ] +function search_move_bfs(from, cost, start, road, max_cost) { + let queue = [ start << 4 ] from.fill(0) cost.fill(15) - cost[start] = start_cost + cost[start] = 0 while (queue.length > 0) { let item = queue.shift() @@ -1050,45 +1061,6 @@ function search_move_bfs(from, cost, start, start_cost, road, max_cost) { } } -function search_withdraw(start, is_pass_move) { - // recon=4, forced march=+1, rommel bonus=+1 - let limit = is_pass_move ? 6 : 4 - - path_enemy.fill(0) - for (let u = 0; u < units.length; ++u) { - if (is_enemy_unit(u)) { - let x = unit_hex(u) - if (x >= first_hex && x <= last_hex) - path_enemy[x] = 1 - } - } - - let sline = game.active === AXIS ? game.axis_supply_line : game.allied_supply_line - let sdist = game.active === AXIS ? distance_to[EL_AGHEILA] : distance_to[ALEXANDRIA] - - search_withdraw_bfs(path_from[0], path_cost[0], start, 0, limit, sline, sdist) - search_withdraw_bfs(path_from[1], path_cost[1], start, 1, limit + 1, sline, sdist) - search_withdraw_bfs(path_from[2], path_cost[2], start, 2, limit + 2, sline, sdist) - search_withdraw_bfs(path_from[4], path_cost[4], start, 4, limit + 4, sline, sdist) - - let grid = new Array(hexcount).fill('-') - for (let x = first_hex; x <= last_hex; ++x) { - for (let speed = 4; speed >= 1; --speed) { - if (path_cost[0][x] <= speed) - grid[x] = speed - if (path_cost[1][x] <= speed + 1) - grid[x] = speed - if (path_cost[2][x] <= speed + 2) - grid[x] = speed - if (path_cost[4][x] <= speed + 4) - grid[x] = speed - } - } - grid[start] = '@' - - debug_hexes2("reach", path_cost[0]) -} - // Breadth First Search function search_withdraw_bfs(from, cost, start, road, max_cost, sline, sdist) { let queue = [ start << 4 ] @@ -1143,39 +1115,24 @@ function search_withdraw_bfs(from, cost, start, road, max_cost, sline, sdist) { } } -// TODO: search_retreat where first hexside exit is restricted to friendly - -function can_move_to(to, road, speed) { - // TODO: engagement & hexside limit - if (road >= 4 && path_cost[4][to] <= speed + 4) +function can_move_to(to, speed) { + if (path_cost[4][to] <= speed + 4) return true - if (road >= 2 && path_cost[2][to] <= speed + 2) + if (path_cost[2][to] <= speed + 2) return true - if (road >= 1 && path_cost[1][to] <= speed + 1) + if (path_cost[1][to] <= speed + 1) return true if (path_cost[0][to] <= speed) return true return false } -function can_move_from(from, road, speed) { - // TODO: engagement & hexside limit - return can_move_to(from, road, speed) +function can_move_from(from, speed) { + return can_move_to(from, speed) } -function can_force_march_to(to, road, speed) { - if (road >= 4 && path_cost[4][to] <= speed + 5) - return true - if (road >= 2 && path_cost[2][to] <= speed + 3) - return true - if (road >= 1 && path_cost[1][to] <= speed + 2) - return true - if (path_cost[0][to] <= speed + 1) - return true - return false -} - -function pick_path(to, road, speed) { +function pick_path(to, speed) { + let road = 4 let next_cost = 15, next_road = 0 if (path_cost[0][to] <= speed) { next_cost = path_cost[0][to] @@ -1223,12 +1180,13 @@ 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) if (speed > 0) { - search_move(from, 0, 4) - for (let x = first_hex; x <= last_hex; ++x) + search_move(from, speed + rommel) + for (let x of all_hexes) if (!path_valid[x]) - if (can_move_to(x, 4, speed + rommel)) + if (can_move_to(x, speed + rommel)) path_valid[x] = 1 } } @@ -1302,7 +1260,7 @@ function goto_initial_supply_check() { } function clear_all_unit_moved() { - game.moved.length = 0 + set_clear(game.moved) } function goto_turn_option() { @@ -1464,11 +1422,12 @@ states.regroup_move_destination = { cp = game.from1, rommel = (game.rommel === 1 ? 1 : 0) else cp = game.from2, rommel = (game.rommel === 2 ? 1 : 0) + path_valid.fill(0) for_each_hex_and_adjacent_hex(cp, x => { find_valid_regroup_destinations(x, rommel) }) - for (let x = first_hex; x <= last_hex; ++x) + for (let x of all_hexes) if (path_valid[x]) gen_action_hex(x) }, @@ -1492,6 +1451,47 @@ states.regroup_move_destination = { }, } +function end_move_phase() { + game.side_limit = {} + game.rommel = 0 + game.from1 = game.from2 = game.to1 = game.to2 = 0 + // TODO: forced marches + goto_refuse_battle() +} + +// === GROUP AND REGROUP MOVEMENT === + +function unit_speed_1(who) { + return unit_speed(who) + (game.rommel === 1 ? 1 : 0) +} + +function unit_speed_2(who) { + return unit_speed(who) + (game.rommel === 2 ? 1 : 0) +} + +function gen_group_move_who(may_retreat, from) { + if (may_retreat !== is_battle_hex(from)) + return + for_each_undisrupted_friendly_unit_in_hex(from, u => { + if (!is_unit_moved(u)) + gen_action_unit(u) + }) +} + +function gen_regroup_move_who(may_retreat, command_point, destination, rommel) { + search_move(destination, 4 + rommel) + for_each_hex_and_adjacent_hex(command_point, x => { + if (x !== destination) { + if (may_retreat !== is_battle_hex(x)) + return + for_each_undisrupted_friendly_unit_in_hex(x, u => { + if (!is_unit_moved(u) && can_move_from(x, unit_speed(u) + rommel)) + gen_action_unit(u) + }) + } + }) +} + function goto_move_who() { if (game.rommel === 1) { if (game.from1 && game.to1) @@ -1516,33 +1516,9 @@ function goto_move_who() { log(`Group move from #${game.from2}.`) } log_br() - log("Moved:") game.state = 'move_who' } -function gen_group_move_who(may_retreat, from) { - if (may_retreat !== is_battle_hex(from)) - return - for_each_undisrupted_friendly_unit_in_hex(from, u => { - if (!is_unit_moved(u)) - gen_action_unit(u) - }) -} - -function gen_regroup_move_who(may_retreat, command_point, destination, rommel) { - search_move(destination, 0, 4) - for_each_hex_and_adjacent_hex(command_point, x => { - if (x !== destination) { - if (may_retreat !== is_battle_hex(x)) - return - for_each_undisrupted_friendly_unit_in_hex(x, u => { - if (!is_unit_moved(u) && can_move_from(x, 4, unit_speed(u) + rommel)) - gen_action_unit(u) - }) - } - }) -} - states.move_who = { inactive: "move (who)", prompt() { @@ -1567,8 +1543,6 @@ states.move_who = { push_undo() game.selected = [ who ] game.state = 'move_to' - game.move_used = 0 - game.move_road = 4 }, retreat() { push_undo() @@ -1582,26 +1556,15 @@ states.move_who = { } } -function end_move_phase() { - game.side_limit = {} - game.rommel = 0 - game.from1 = game.from2 = game.to1 = game.to2 = 0 - // TODO: forced marches - goto_refuse_battle() -} - function apply_move(move, who, from, to) { - let speed = unit_speed(who) + (move === game.rommel ? 1 : 0) - let road = pick_path(to, game.move_road, speed) - - print_path(who, unit_hex(who), to, road) - - game.move_road = road - game.move_used = path_cost[road][to] + let rommel = (game.rommel === move ? 1 : 0) + let road = pick_path(to, unit_speed(who) + rommel) set_unit_moved(who) set_unit_hex(who, to) + log(`>from #${from} to #${to}`) + if (is_battle_hex(to)) { let side = to_side_id(to, path_from[road][to]) @@ -1617,19 +1580,6 @@ function apply_move(move, who, from, to) { } return true } - - if (game.move_used === speed + game.move_road) - return true - - return false -} - -function unit_speed_1(who) { - return unit_speed(who) + (game.rommel === 1 ? 1 : 0) -} - -function unit_speed_2(who) { - return unit_speed(who) + (game.rommel === 2 ? 1 : 0) } function can_move_regroup_1(who, from, to) { @@ -1648,14 +1598,14 @@ function can_move_regroup_2(who, from, to) { function can_move_group_1(who, from, to) { if (from === game.from1 && !game.to1) - if (can_move_to(to, game.move_road, unit_speed_1(who))) + if (can_move_to(to, unit_speed_1(who))) return true return false } function can_move_group_2(who, from, to) { if (from === game.from2 && !game.to2) - if (can_move_to(to, game.move_road, unit_speed_2(who))) + if (can_move_to(to, unit_speed_2(who))) return true return false } @@ -1666,8 +1616,9 @@ states.move_to = { view.prompt = `Move: Select where to move.` let who = game.selected[0] let from = unit_hex(who) + let maybe_rommel = 1 - search_move(from, 0, 4) + search_move(from, unit_speed(who) + maybe_rommel) if (from === game.from1 && !game.to1) for (let to of all_hexes) @@ -1694,102 +1645,26 @@ states.move_to = { push_undo() let who = game.selected[0] let from = unit_hex(who) + let maybe_rommel = 1 - search_move(from, 0, 4) + search_move(from, unit_speed(who) + maybe_rommel) - if (can_move_group_1(who, from, to)) { - game.move_from = from - if (apply_move(1, who, from, to)) - stop_move(who) - else - game.state = 'group_move_to' - return - } - - if (can_move_group_2(who, from, to)) { - game.move_from = from - if (apply_move(2, who, from, to)) - stop_move(who) - else - game.state = 'group_move_to' - return + if (has_enemy_unit(to)) { + log("TODO: pick hex-side") } - if (can_move_regroup_1(who, from, to)) { + if (can_move_group_1(who, from, to)) apply_move(1, who, from, to) - stop_move(who) - game.state = 'move_who' - return - } - - if (can_move_regroup_2(who, from, to)) { + if (can_move_group_2(who, from, to)) + apply_move(2, who, from, to) + if (can_move_regroup_1(who, from, to)) + apply_move(1, who, from, to) + if (can_move_regroup_2(who, from, to)) apply_move(2, who, from, to) - stop_move(who) - game.state = 'move_who' - return - } - }, -} - -states.group_move_to = { - inactive: "group move (to)", - prompt() { - view.prompt = `Group Move: Select where to move.` - let who = game.selected[0] - let from = unit_hex(who) - if (game.move_used > 0) - gen_action('stop') - - search_move(from, game.move_used, game.move_road) - - if (game.move_from === game.from1 && !game.to1) - for (let to of all_hexes) - if (to != from && can_move_group_1(who, game.move_from, to)) - gen_action_hex(to) - - if (game.move_from === game.from2 && !game.to2) - for (let to of all_hexes) - if (to != from && can_move_group_2(who, game.move_from, to)) - gen_action_hex(to) - - gen_action_unit(who) - }, - unit(who) { - this.stop() - }, - hex(to) { - let who = game.selected[0] - let from = unit_hex(who) - - search_move(from, game.move_used, game.move_road) - - if (can_move_group_1(who, game.move_from, to)) { - log(`group continued ${who} to ${to}`) - if (apply_move(1, who, from, to)) - stop_move(who) - return - } - if (can_move_group_2(who, game.move_from, to)) { - log(`group continued ${who} to ${to}`) - if (apply_move(2, who, from, to)) - stop_move(who) - return - } + game.state = 'move_who' + game.selected.length = 0 }, - stop() { - let who = game.selected[0] - stop_move(who) - } -} - -function stop_move(who) { - set_unit_moved(who) - game.move_from = 0 - game.move_road = 4 - game.move_used = 0 - game.selected = [] - game.state = 'move_who' } // === RETREAT === @@ -1948,13 +1823,14 @@ states.retreat_to = { prompt() { view.prompt = `Retreat: Select destination.` let who = game.selected[0] + let from = game.retreat gen_action_unit(who) if (game.turn_option === 'pass') { - search_withdraw(game.retreat, true) + search_withdraw(from, true) } else { - search_retreat(game.retreat) + search_retreat(from) } if (from === game.from1 && !game.to1) @@ -2382,11 +2258,6 @@ function end_battle() { end_combat_phase() } -function end_probe() { - game.battle = 0 - resume_retreat() -} - // === PURSUIT FIRE === // Refuse battle @@ -3144,11 +3015,6 @@ exports.setup = function (seed, scenario, options) { from2: 0, to2: 0, - // current group move state - move_from: 0, - move_used: 0, - move_road: 4, - // retreat partial_retreats: [], // remember partial retreats to forbid initiating combat retreat: 0, diff --git a/tools/gendata.js b/tools/gendata.js index a963248..1af2356 100644 --- a/tools/gendata.js +++ b/tools/gendata.js @@ -56,7 +56,8 @@ function def_side(t,a,b) { function def_road(t, list) { for (let i = 0; i < list.length; ++i) - hex_road[list[i]] = t; + if (t > hex_road[list[i]]) + hex_road[list[i]] = t; for (let i = 1; i < list.length; ++i) { let s = to_side_id(list[i-1], list[i]); side_road[s] = t; |