diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/gencss.js | 7 | ||||
-rw-r--r-- | tools/gendata.js | 576 | ||||
-rw-r--r-- | tools/gentextures.sh | 36 | ||||
-rw-r--r-- | tools/genunits.js | 227 | ||||
-rw-r--r-- | tools/rock_overlay.png | bin | 0 -> 44367 bytes | |||
-rw-r--r-- | tools/rock_overlay@2x.png | bin | 0 -> 160515 bytes | |||
-rw-r--r-- | tools/scree_overlay.png | bin | 0 -> 21813 bytes | |||
-rw-r--r-- | tools/scree_overlay@2x.png | bin | 0 -> 72197 bytes | |||
-rw-r--r-- | tools/wetland.pbm | bin | 0 -> 8203 bytes |
9 files changed, 846 insertions, 0 deletions
diff --git a/tools/gencss.js b/tools/gencss.js new file mode 100644 index 0000000..4981d7c --- /dev/null +++ b/tools/gencss.js @@ -0,0 +1,7 @@ +// let n = 51, u = 'px'; +let n = 100 / 9, u = '%'; +for (let i = 0; i < 94; ++i) { + let x = (i % 10) | 0; + let y = (i / 10) | 0; + console.log(`.unit.u${i}{background-position:${x*n}${u} ${y*n}${u}}`); +} diff --git a/tools/gendata.js b/tools/gendata.js new file mode 100644 index 0000000..fb0348c --- /dev/null +++ b/tools/gendata.js @@ -0,0 +1,576 @@ +// https://www.redblobgames.com/grids/hexagons/ + +// Clear +const CLEAR = 2; + +// Constricted +const GAP = 1; + +// Rough (impassable) +const OFFMAP = 0; +const RIDGE = 0; +const MARSH = 0; +const MOUNTAIN = 0; + +// Road +const TRAIL = 1; +const TRACK = 2; +const HIGHWAY = 4; + +const map_w = 25; +const map_h = 9; + +let next = [ 1, map_w, map_w-1, -1, -map_w, -(map_w-1) ]; + +let nextdir = [ -1, 1, map_w, map_w-1, -map_w, -(map_w-1) ] +let nextname = [ "E", "W", "NW", "NE", "SE", "SW" ]; + +let hex_exists = new Array(map_w*map_h).fill(1); +let side_limit = new Array(map_w*map_h*3).fill(CLEAR); +let side_road = new Array(map_w*map_h*3).fill(0); +let hex_road = new Array(map_w*map_h).fill(0); + +function add_side(s, t) { + if (side_limit[s]) + side_limit[s] += "/" + t; + else + side_limit[s] = t; +} + +function to_side_id(a, b) { + if (a > b) { + let c = b; b = a; a = c; + } + if (a + next[0] === b) + return a * 3 + 0; + else if (a + next[1] === b) + return a * 3 + 1; + else if (a + next[2] === b) + return a * 3 + 2; + throw new Error("not a hexside " + a + " to " + b); +} + +function def_side(t,a,b) { + side_limit[to_side_id(a,b)] = t; +} + +function def_road(t, list) { + for (let i = 0; i < list.length; ++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; + if (side_limit[s] === MOUNTAIN) + side_limit[s] = GAP; + } +} + +def_side(MARSH, 176, 152); +def_side(MARSH, 179, 203); + +def_side(RIDGE, 144, 145); +def_side(RIDGE, 120, 145); +def_side(RIDGE, 121, 145); +def_side(RIDGE, 121, 146); +def_side(RIDGE, 122, 146); +def_side(RIDGE, 144, 169); +def_side(RIDGE, 144, 168); +def_side(RIDGE, 143, 168); +def_side(RIDGE, 167, 168); +def_side(RIDGE, 167, 192); +def_side(RIDGE, 191, 192); +def_side(RIDGE, 191, 216); +def_side(RIDGE, 215, 216); +def_side(RIDGE, 217, 218); +def_side(RIDGE, 217, 193); +def_side(RIDGE, 192, 193); +def_side(RIDGE, 168, 193); +def_side(RIDGE, 168, 169); +def_side(RIDGE, 69, 94); +def_side(RIDGE, 67, 92); +def_side(RIDGE, 68, 92); +def_side(RIDGE, 68, 93); +def_side(RIDGE, 65, 40); +def_side(RIDGE, 65, 64); +def_side(RIDGE, 65, 89); +def_side(RIDGE, 65, 90); +def_side(RIDGE, 66, 90); +def_side(RIDGE, 66, 91); +def_side(RIDGE, 39, 63); +def_side(RIDGE, 37, 38); +def_side(RIDGE, 36, 37); +def_side(RIDGE, 36, 61); +def_side(RIDGE, 36, 60); +def_side(RIDGE, 109, 133); +def_side(RIDGE, 108, 133); +def_side(RIDGE, 204, 179); +def_side(RIDGE, 204, 180); +def_side(RIDGE, 205, 180); +def_side(RIDGE, 31, 30); +def_side(RIDGE, 31, 55); +def_side(RIDGE, 55, 54); +def_side(RIDGE, 78, 79); +def_side(RIDGE, 30, 55); +def_side(RIDGE, 54, 79); +def_side(RIDGE, 103, 79); +def_side(RIDGE, 176, 200); +def_side(RIDGE, 176, 201); +def_side(RIDGE, 177, 152); +def_side(RIDGE, 177, 153); +def_side(RIDGE, 178, 153); +def_side(RIDGE, 153, 154); +def_side(RIDGE, 129, 154); + +def_side(MOUNTAIN, 7, 8); +def_side(MOUNTAIN, 7, 31); +def_side(MOUNTAIN, 7, 32); +def_side(MOUNTAIN, 8, 9); +def_side(MOUNTAIN, 8, 32); +def_side(MOUNTAIN, 8, 33); +def_side(MOUNTAIN, 9, 33); +def_side(MOUNTAIN, 9, 34); +def_side(MOUNTAIN, 9, 10); +def_side(MOUNTAIN, 32, 31); +def_side(MOUNTAIN, 32, 33); +def_side(MOUNTAIN, 32, 56); +def_side(MOUNTAIN, 32, 57); +def_side(MOUNTAIN, 33, 34); +def_side(MOUNTAIN, 33, 57); +def_side(MOUNTAIN, 33, 58); +def_side(MOUNTAIN, 34, 10); +def_side(MOUNTAIN, 34, 35); +def_side(MOUNTAIN, 34, 58); +def_side(MOUNTAIN, 34, 59); +def_side(MOUNTAIN, 55, 80); +def_side(MOUNTAIN, 56, 80); +def_side(MOUNTAIN, 56, 55); +def_side(MOUNTAIN, 56, 31); +def_side(MOUNTAIN, 56, 81); +def_side(MOUNTAIN, 56, 57); +def_side(MOUNTAIN, 57, 58); + +def_side(GAP, 176, 152); +def_side(GAP, 65, 40); +def_side(GAP, 65, 64); +def_side(GAP, 65, 89); +def_side(GAP, 37, 38); +def_side(GAP, 36, 37); +def_side(GAP, 36, 61); +def_side(GAP, 109, 133); +def_side(GAP, 31, 30); +def_side(GAP, 31, 55); +def_side(GAP, 55, 54); +def_side(GAP, 78, 79); +def_side(GAP, 177, 153); +def_side(GAP, 178, 153); +def_side(GAP, 129, 154); + +def_road(HIGHWAY, [151,152,128,103,78,54,30,31,7,8,9,10,35,36,37,38,39,40,64,65,66,67,68,69,70,71,72,73,74]); +def_road(HIGHWAY, [54,55,31]); +def_road(HIGHWAY, [31,32,33,9]); +def_road(HIGHWAY, [36,61,62,38]); + +def_road(TRACK, [78,79,80,81,82,58,59,35]); +def_road(TRACK, [128,104,80]); +def_road(TRACK, [83,59,60,61,86,87,88,89]); +def_road(TRACK, [37,62,87]); +def_road(TRACK, [64,89,113]); +def_road(TRACK, [62,63,64]); +def_road(TRACK, [213,189,165,141,117,93,69]); +def_road(TRACK, [72,97,121]); + +def_road(TRAIL, [152,153,178,203,204,205,181,182,183,184,185,186,187]); +def_road(TRAIL, [153,128,129,104,103]); +def_road(TRAIL, [79,55]); +def_road(TRAIL, [55,56,57,58,34,10]); +def_road(TRAIL, [58,83,107,106,130,129]); +def_road(TRAIL, [35,60,85,61]); +def_road(TRAIL, [85,86]); +def_road(TRAIL, [85,109,133,157,181]); +def_road(TRAIL, [64,88]); +def_road(TRAIL, [88,113,138,162,187]); +def_road(TRAIL, [87,112,137,162]); +def_road(TRAIL, [65,89,114,139,163,188,213]); +def_road(TRAIL, [67,91,115,140,164,189]); + +function def_offmap(a, b) { + for (let hex_id = 0; hex_id < map_w * map_h; ++hex_id) { + if (hex_id >= a && hex_id <= b) { + hex_exists[hex_id] = 0; + side_limit[hex_id * 3 + 0] = OFFMAP; + side_limit[hex_id * 3 + 1] = OFFMAP; + side_limit[hex_id * 3 + 2] = OFFMAP; + } + for (let s = 0; s < 3; ++s) { + let next_id = hex_id + next[s]; + if (next_id >= a && next_id <= b) + side_limit[hex_id * 3 + s] = OFFMAP; + } + } +} + +def_offmap(0,6); +def_offmap(11,29); +def_offmap(41,53); +def_offmap(75,77); +def_offmap(99,102); +def_offmap(124,127); +def_offmap(148,150); +def_offmap(173,175); +def_offmap(197,199); +def_offmap(222,224); + +// show spines +def_offmap(175,175, 1); +def_offmap(99,99, 1); +def_offmap(148,148, 1); +def_offmap(197,197, 1); + +// depression +def_offmap(168,168); +def_offmap(168,168); +def_offmap(192,192); +def_offmap(193,193); +def_offmap(216,217); + +// Hexes not in 2004 edition: +// def_offmap(200,202); +// def_offmap(206,212); +// def_offmap(214,221); + +// Terrain chart hexes +// def_offmap(145,146); +// def_offmap(168,172); +// def_offmap(192,196); +// def_offmap(216,221); + +// Qattara Depression and east of it +def_offmap(145,148); +def_offmap(168,172); +def_offmap(192,196); +def_offmap(216,221); + +let regions = {}; +function def_region(name, a, b) { + if (!(name in regions)) + regions[name] = []; + for (let i = a; i <= b; ++i) + regions[name].push(i); +} + +def_region("Libya", 7, 10); +def_region("Libya", 30, 40); +def_region("Libya", 54, 64); +def_region("Libya", 78, 88); +def_region("Libya", 103, 113); +def_region("Libya", 128, 138); +def_region("Libya", 151, 162); +def_region("Libya", 176, 187); +def_region("Libya", 200, 211); + +def_region("Egypt", 65, 74); +def_region("Egypt", 89, 98); +def_region("Egypt", 114, 123); +def_region("Egypt", 139, 144); +def_region("Egypt", 163, 167); +def_region("Egypt", 188, 191); +def_region("Egypt", 212, 215); + +def_region("Sidi Omar", 89, 89); +def_region("Tobruk", 37, 37); +def_region("Sollum", 65, 65); +def_region("El Agheila", 151, 151); +def_region("Mersa Brega", 152, 152); + +def_region("East Line", 36, 40); +def_region("East Line", 60, 74); +def_region("East Line", 85, 98); +def_region("East Line", 112, 123); +def_region("East Line", 137, 144); +def_region("East Line", 162, 167); +def_region("East Line", 187, 191); + +def_region("West Line", 7, 10); +def_region("West Line", 30, 35); +def_region("West Line", 54, 59); +def_region("West Line", 78, 83); +def_region("West Line", 103, 107); +def_region("West Line", 128, 130); + +def_region("Jebel el Akhdar", 7, 9); +def_region("Jebel el Akhdar", 32, 34); +def_region("Jebel el Akhdar", 56, 57); + +def_region("Sebkha el Segira", 152, 152); +def_region("Sebkha el Segira", 176, 176); +def_region("Sebket el Jeneinen", 179, 179); +def_region("Sebket el Jeneinen", 203, 203); + +def_region("Qattara Depression", 144, 146); +def_region("Qattara Depression", 168, 169); +def_region("Qattara Depression", 192, 193); +def_region("Qattara Depression", 216, 217); + +hex_name = { + 7: "El Garib", + 8: "Cyrene", + 9: "El Gubba", + 10: "Derna", + + 30: "Tocra", + 31: "Barce", + 32: "Marawa", + 33: "Wadi Cuff", + 35: "Gazala", + 36: "Acroma", + 37: "Tobruk", + 38: "Belhamed", + 39: "Gambut", + 40: "Bardia", + + 54: "Benghazi", + 55: "Er Regima", + 56: "Charruba", + 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", + 69: "Mersa Matruh", + 70: "Fuka", + 71: "El Daba", + 72: "El Alamein", + 73: "El Hamam", + 74: "Alexandria", + + 78: "Ghemines", + 79: "Skeleidima", + 80: "Msus", + 83: "Tengeder", + 85: "Bir Hacheim", + 86: "Retma", + 87: "Bir Gubi", + 88: "Gabr Saleh", + 89: "Sidi Omar", + 90: "Bir Habata", + 91: "Sofafi", + 93: "Bir el Kenayis", + 94: "Bir Khalda", + 97: "Alam Halfa", + + 103: "Beda Fomm", + 104: "Antelat", + 106: "Ben Gania", + 113: "Ft. Maddalena", + 115: "Bir Khamsa", + 116: "Bir el Qatrani", + 121: "El Himeimat", + + 128: "Agedabia", + 129: "Jebel el Matar", + 130: "Haraga", + 141: "Bir Fuad", + + 151: "El Agheila", + 152: "Mersa Brega", + 153: "El Haseiat", + + 176: "Maaten Giofer", + 178: "Sahaba", + 187: "Jarabub Oasis", + + 204: "Jalo Oasis", + 213: "Siwa Oasis", +} + + +function expand_names() { + let hex_name2 = { } + for (let hex_id = 0; hex_id < map_w * map_h; ++hex_id) { + if (hex_exists[hex_id] && !hex_name[hex_id]) { + for (let s = 0; s < 6; ++s) { + let next_id = hex_id + nextdir[s]; + if (hex_name[next_id]) { + hex_name2[hex_id] = hex_name[next_id] + " " + nextname[s]; + break; + } + } + } + } + for (let hex_id in hex_name2) + hex_name[hex_id] = hex_name2[hex_id]; +} + +expand_names(); + +let units = []; + +const class_from_type = { + "recon": "armor", + "armor": "armor", + "i-tank": "armor", + "infantry": "infantry", + "mech. inf.": "infantry", + "mot. inf.": "infantry", + "para": "infantry", + "mob. a/t": "antitank", + "mot. a/t": "antitank", + "self prop. arty": "artillery", + "artillery": "artillery", +} + +const speed_from_type = { + "recon": 4, + "armor": 3, + "i-tank": 3, // optional rule: allied i-tanks set this to 2 + "mech. inf.": 3, + "mob. a/t": 3, + "self prop. arty": 3, + "mot. inf.": 2, + "mot. a/t": 2, + "infantry": 1, + "para": 1, + "artillery": 1, +} + +let unit_map = {}; + +function def_block(nationality, type, appearance, steps, elite, label, name) { + let type_class = class_from_type[type]; + let speed = speed_from_type[type]; + if (name in unit_map) + throw new Error("duplicate block name:", name); + unit_map[name] = units.length; + units.push({nationality, type, class: type_class, speed, appearance, steps, elite, label, name}); +} + +let S = "S"; +let M = "M"; +let T = "T"; + +//def_block("italian", battle block 1); +def_block("italian", "infantry", S, 4, 0, 12, "Tre"); +def_block("italian", "infantry", S, 4, 0, 13, "Pav"); +def_block("italian", "infantry", S, 4, 0, 14, "Bre"); +def_block("italian", "infantry", S, 3, 0, 15, "Bol"); +def_block("italian", "infantry", S, 3, 0, 16, "Sav"); + +def_block("italian", "mech. inf.", 7, 4, 0, 21, "Tri"); +def_block("italian", "infantry", 7, 2, 0, 22, "Sab"); +def_block("italian", "armor", 11, 3, 0, 23, "Lit"); +def_block("italian", "mot. inf.", 17, 3, 0, 24, "Fas"); +def_block("italian", "mot. inf.", 19, 3, 0, 25, "Cen"); +def_block("italian", "infantry", 19, 2, 0, 26, "Pis"); +def_block("italian", "para", M, 4, 0, 27, "Fol"); +def_block("italian", "artillery", S, 2, 0, 28, "Ita"); +def_block("italian", "armor", S, 4, 0, 29, "Ari"); + +//def_block("german", battle block 1); +//def_block("german", battle block 2); +//def_block("german", battle block 3); +def_block("german", "armor", S, 3, 1, 14, "21/5"); +def_block("german", "recon", S, 1, 1, 15, "21/3"); +def_block("german", "mech. inf.", S, 3, 1, 16, "21/104"); +def_block("german", "recon", 3, 1, 1, 17, "15/33"); +def_block("german", "mob. a/t", 3, 2, 1, 18, "88mm/A"); +def_block("german", "mech. inf.", 3, 3, 1, 19, "15/115"); + +def_block("german", "armor", 5, 3, 1, 21, "15/8"); +def_block("german", "recon", 5, 1, 1, 22, "90/580"); +def_block("german", "mot. inf.", 5, 2, 1, 23, "90/361"); +def_block("german", "mot. a/t", 5, 2, 1, 24, "50mm"); +def_block("german", "artillery", 7, 2, 1, 25, "/104"); +def_block("german", "mot. inf.", 7, 2, 1, 26, "90/200"); +def_block("german", "mob. a/t", 11, 2, 1, 27, "88mm/B"); +def_block("german", "mech. inf.", 11, 2, 1, 28, "90/sv288"); +def_block("german", "mech. inf.", 11, 2, 1, 29, "90/346"); + +def_block("german", "para", M, 3, 1, 31, "Ram"); +def_block("german", "infantry", M, 3, 1, 32, "164/382+433"); +def_block("german", "infantry", M, 2, 1, 33, "164/125"); +def_block("german", "mech. inf.", 3, 3, 1, 34, "90/155"); +def_block("german", "mot. a/t", 17, 2, 1, 35, "76mm"); + +// def_block("allied", bb 1 +// def_block("allied", bb 2 +// def_block("allied", bb 3 +def_block("allied", "armor", S, 2, 0, 14, "2/3"); +def_block("allied", "mech. inf.", S, 2, 0, 15, "2/SG"); +def_block("allied", "mech. inf.", S, 2, 0, 16, "4IN/3m"); +def_block("allied", "mot. inf.", S, 4, 0, 17, "9AU/20"); +def_block("allied", "mot. inf.", S, 4, 0, 18, "70/14+16"); +def_block("allied", "mot. inf.", S, 3, 0, 19, "70/23"); + +def_block("allied", "armor", T, 1, 1, 21, "Matilda/A"); +def_block("allied", "mech. inf.", T, 3, 0, 22, "7/SG"); +def_block("allied", "mech. inf.", T, 3, 0, 23, "7/22G"); +def_block("allied", "mot. inf.", T, 3, 0, 24, "/Pol"); +def_block("allied", "mot. inf.", T, 3, 0, 25, "7AU/18"); +def_block("allied", "artillery", T, 2, 0, 26, "/Tob"); +def_block("allied", "mot. inf.", 18, 4, 0, 27, "51H/152"); +def_block("allied", "self prop. arty", 18, 2, 0, 28, "Priest"); +def_block("allied", "artillery", 18, 4, 0, 29, "/C"); + +def_block("allied", "armor", 2, 4, 0, 31, "7/7"); +def_block("allied", "mech. inf.", 2, 3, 0, 32, "4IN/7m"); +def_block("allied", "mot. inf.", 2, 3, 0, 33, "4IN/5"); +def_block("allied", "mot. inf.", 2, 3, 0, 34, "4IN/11"); +def_block("allied", "armor", 4, 1, 1, 35, "Matilda/B"); +def_block("allied", "i-tank", 4, 4, 0, 36, "/1AT"); +def_block("allied", "armor", 4, 3, 0, 37, "7/4"); +def_block("allied", "recon", 4, 2, 0, 38, "7"); +def_block("allied", "artillery", 20, 3, 0, 39, "/D"); + +def_block("allied", "mot. a/t", 6, 3, 0, 41, "2#"); +def_block("allied", "mech. inf.", 6, 4, 0, 42, "2NZ/4"); +def_block("allied", "mech. inf.", 6, 4, 0, 43, "2NZ/5"); +def_block("allied", "mech. inf.", 6, 4, 0, 44, "2NZ/6"); +def_block("allied", "mot. inf.", 6, 4, 0, 45, "1SA/2+5"); +def_block("allied", "mot. inf.", 6, 3, 0, 46, "1SA/1"); +def_block("allied", "recon", 8, 2, 0, 47, "1SA"); +def_block("allied", "mot. inf.", 8, 3, 0, 48, "1SA/3"); +def_block("allied", "mot. inf.", 8, 3, 0, 49, "2SA/4+6"); + +def_block("allied", "armor", 8, 4, 0, 51, "1/22"); +def_block("allied", "i-tank", 8, 3, 0, 52, "/32AT"); +def_block("allied", "artillery", 8, 2, 0, 53, "/A"); +def_block("allied", "armor", 10, 4, 0, 54, "1/2"); +def_block("allied", "mech. inf.", 10, 3, 0, 55, "1/201G"); +def_block("allied", "mech. inf.", 10, 2, 0, 56, "1/SG"); +def_block("allied", "mot. inf.", 10, 3, 0, 57, "5IN/29"); +def_block("allied", "armor", 12, 2, 1, 58, "Grant"); +def_block("allied", "mot. a/t", 12, 3, 0, 59, "6#/A"); + +def_block("allied", "mech. inf.", 14, 2, 0, 61, "10IN/161m"); +def_block("allied", "mot. inf.", 14, 4, 0, 62, "5IN/9+10"); +def_block("allied", "mot. inf.", 14, 4, 0, 63, "10IN/21+25"); +def_block("allied", "mot. inf.", 14, 2, 0, 64, "8IN/18"); +def_block("allied", "mot. inf.", 14, 4, 0, 65, "FF/2"); +def_block("allied", "artillery", 14, 4, 0, 66, "/B"); +def_block("allied", "armor", 20, 3, 1, 67, "Sher/B"); +def_block("allied", "armor", 20, 3, 0, 68, "8/9"); +def_block("allied", "armor", 20, 3, 0, 69, "8/24"); + +def_block("allied", "armor", 16, 4, 0, 71, "10/8"); +def_block("allied", "armor", 16, 3, 0, 72, "10/23"); +def_block("allied", "mot. inf.", 16, 4, 0, 73, "9AU/26"); +def_block("allied", "mot. inf.", 16, 4, 0, 74, "9AU/24"); +def_block("allied", "mot. inf.", 16, 4, 0, 75, "44/131+133"); +def_block("allied", "mot. inf.", 16, 2, 0, 76, "44/132"); +def_block("allied", "armor", 18, 3, 1, 77, "Sher/A"); +def_block("allied", "mot. a/t", 18, 4, 0, 78, "6#/B"); +def_block("allied", "mot. inf.", 18, 4, 0, 79, "51H/154"); + +console.log("const hex_exists = " + JSON.stringify(hex_exists)); +console.log("const hex_road = " + JSON.stringify(hex_road)); +console.log("const side_road = " + JSON.stringify(side_road)); +console.log("const side_limit = " + JSON.stringify(side_limit)); +console.log("const hex_name = " + JSON.stringify(hex_name)); +console.log("const regions = " + JSON.stringify(regions)); +console.log("const units = " + JSON.stringify(units)); +console.log("if (typeof module !== 'undefined') module.exports = { hex_name, hex_road, side_road, side_limit, regions, units }"); diff --git a/tools/gentextures.sh b/tools/gentextures.sh new file mode 100644 index 0000000..cacd968 --- /dev/null +++ b/tools/gentextures.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +# 2022 +# depression: c4ab8b b39e83 +# depression (old): c4bd9c +# marsh: 939874 747e5c +# mountain: b3b37d 9a9a6e +# desert: ccbda4 d6c5aa + +cat tools/wetland.pbm | pgmtoppm "#747e5c-#939874" | ppmquant 2 | pnmtopng > texture_marsh.png +#pngtopnm tools/scree_overlay@2x.png | pgmtoppm "black-#c4ab8b" | ppmquant 2 | pnmtopng > texture_scree.png +pngtopnm tools/scree_overlay@2x.png | pgmtoppm "black-#c4bd9c" | ppmquant 2 | pnmtopng > texture_scree.png +#pngtopnm tools/rock_overlay@2x.png | pnmnorm | pgmtoppm "#aaa26f-#bab079" | ppmquant 2 | pnmtopng > texture_mountain.png +pngtopnm tools/rock_overlay@2x.png | pnmnorm | pgmtoppm "#9d9d6a-#aaaa77" | ppmquant 2 | pnmtopng > texture_mountain.png +pngtopnm tools/rock_overlay@2x.png | pnmnorm | pgmtoppm "#ccbda4-#d6c5aa" | ppmquant 2 | pnmtopng > texture_clear.png +pngtopnm tools/rock_overlay@2x.png | pnmnorm | pgmtoppm "#bba487-#c4ab8b" | ppmquant 2 | pnmtopng > texture_depression.png + +for PNG in texture_*.png +do + zopflipng -y $PNG $PNG +done + +exit 0 + +OUT=textures.svg +rm -f $OUT +for PNG in texture_*.png +do +SIZE=$(file $PNG | sed 's/[^0-9]*//;s/ .*//') +echo '<pattern id="'${PNG/.png/}'" width="'$SIZE'" height="'$SIZE'" patternUnits="userSpaceOnUse">' >> $OUT +echo '<image width="'$SIZE'" height="'$SIZE'" xlink:href="data:image/png;base64,' >> $OUT +base64 $PNG >> $OUT +echo '"/>' >> $OUT +echo '"</pattern>' >> $OUT +echo >> $OUT +done diff --git a/tools/genunits.js b/tools/genunits.js new file mode 100644 index 0000000..4e0f30e --- /dev/null +++ b/tools/genunits.js @@ -0,0 +1,227 @@ +const { units } = require("../data.js"); +const print = console.log; + +print(`<svg xmlns="http://www.w3.org/2000/svg" width="510" height="510" version="1.2" viewBox="0 0 510 510"> +<defs> + +<symbol id="font_1" overflow="visible"> +<path transform="scale(1,-1) translate(-.3333333 0)" d="M .49169923 .7285156 L .49169923 0 L .29052735 0 L .29052735 .47642518 C .25797526 .45183818 .22648113 .4319407 .19604492 .4167328 C .16560872 .40152488 .1274414 .3869629 .08154297 .37304688 L .08154297 .53515627 C .1492513 .5571289 .20182292 .5835317 .23925781 .6143646 C .27669273 .6451976 .3059896 .68324789 .32714845 .7285156 L .49169923 .7285156 Z "/> +</symbol> + +<symbol id="font_2" overflow="visible"> +<path transform="scale(1,-1) translate(-.3333333 0)" d="M .6230469 0 L .026367188 0 C .033203126 .05891927 .053955079 .114339198 .08862305 .16625977 C .123291019 .21818035 .1883138 .27945964 .2836914 .35009767 C .34195964 .39339195 .37923179 .42626954 .3955078 .44873048 C .41178385 .4711914 .41992188 .49251304 .41992188 .5126953 C .41992188 .5345052 .41186524 .5531413 .39575196 .5686035 C .37963868 .58406576 .359375 .5917969 .33496095 .5917969 C .3095703 .5917969 .28881837 .5838928 .27270509 .5680847 C .2565918 .5522766 .24576824 .52437338 .24023438 .484375 L .041015626 .5003357 C .048828126 .5562439 .06315104 .59987899 .083984378 .63124087 C .10481771 .6626129 .13419597 .68666586 .17211914 .70339968 C .21004232 .7201436 .26253257 .7285156 .32958985 .7285156 C .3995768 .7285156 .45402018 .7205302 .49291993 .7045593 C .53181967 .68858847 .56241866 .6640625 .5847168 .63098147 C .60701498 .5979004 .61816409 .5608266 .61816409 .51976016 C .61816409 .47608949 .6053874 .43437196 .579834 .39460755 C .5542806 .35484315 .5078125 .3111979 .4404297 .26367188 C .40039063 .23600261 .37361656 .21663411 .36010743 .2055664 C .3465983 .1944987 .33072917 .18001302 .3125 .16210938 L .6230469 .16210938 L .6230469 0 Z "/> +</symbol> + +<symbol id="font_3" overflow="visible"> +<path transform="scale(1,-1) translate(-.3333333 0)" d="M .23388672 .5097656 L .045898439 .5431061 C .061523439 .60296127 .091552738 .64882406 .13598633 .6806946 C .18041992 .71257528 .24332683 .7285156 .32470704 .7285156 C .4181315 .7285156 .4856771 .7110494 .52734377 .67611697 C .56901046 .6411845 .58984377 .5972748 .58984377 .5443878 C .58984377 .51337179 .5813802 .48529054 .5644531 .46014405 C .54752609 .43500773 .52197268 .41297404 .48779298 .39404298 C .5154622 .38720704 .5366211 .37923179 .55126956 .3701172 C .57503256 .35546876 .59350588 .33618165 .60668948 .31225587 C .61987307 .28833009 .62646487 .25976563 .62646487 .2265625 C .62646487 .18489583 .6155599 .14493816 .59375 .10668945 C .5719401 .06844076 .54052737 .03898112 .49951173 .018310547 C .4584961 -.0023600262 .4046224 -.0126953129 .33789063 -.0126953129 C .27278648 -.0126953129 .22143555 -.0050455729 .18383789 .010253906 C .14624024 .025553385 .11531576 .04793294 .09106445 .07739258 C .06681315 .10685221 .048177083 .1438802 .03515625 .18847656 L .23388672 .21484375 C .24169922 .17480469 .25382487 .14705403 .27026368 .1315918 C .28670249 .116129558 .3076172 .10839844 .3330078 .10839844 C .35970054 .10839844 .38191734 .11816406 .3996582 .13769531 C .41739909 .15722656 .42626954 .18326824 .42626954 .21582031 C .42626954 .24902344 .4177246 .2747396 .40063478 .29296876 C .38354493 .3111979 .36035157 .3203125 .3310547 .3203125 C .3154297 .3203125 .2939453 .31640626 .26660157 .30859376 L .27685548 .45069886 C .2879232 .44906108 .29654948 .4482422 .30273438 .4482422 C .32877604 .4482422 .35050456 .4565684 .36791993 .47322084 C .3853353 .48987327 .39404298 .5096283 .39404298 .53248599 C .39404298 .55436709 .38753257 .5718384 .37451173 .5848999 C .36149089 .5979614 .34358726 .6044922 .32080079 .6044922 C .29736329 .6044922 .2783203 .59748336 .26367188 .5834656 C .24902344 .5694478 .23909505 .54488119 .23388672 .5097656 Z "/> +</symbol> + +<symbol id="font_4" overflow="visible"> +<path transform="scale(1,-1) translate(-.3333333 0)" d="M .3828125 .13378906 L .020507813 .13378906 L .020507813 .2975006 L .3828125 .7285156 L .55615237 .7285156 L .55615237 .28808595 L .6459961 .28808595 L .6459961 .13378906 L .55615237 .13378906 L .55615237 0 L .3828125 0 L .3828125 .13378906 M .3828125 .28808595 L .3828125 .5143585 L .19140625 .28808595 L .3828125 .28808595 Z "/> +</symbol> + +<symbol id="font_6" overflow="visible"> +<path transform="scale(1,-1) translate(-.3333333 0)" d="M .6166992 .5548401 L .4189453 .53027346 C .41373698 .5581258 .4050293 .57778427 .39282228 .58924868 C .38061524 .6007131 .3655599 .6064453 .34765626 .6064453 C .3154297 .6064453 .2903646 .5901286 .27246095 .5574951 C .2594401 .5340068 .24983724 .4837545 .24365235 .40673829 C .26741538 .4308268 .29182945 .44864909 .31689454 .46020509 C .34195964 .47176109 .370931 .47753907 .4038086 .47753907 C .4676107 .47753907 .52156576 .45472718 .5656738 .4091034 C .6097819 .36348979 .63183596 .3056539 .63183596 .2355957 C .63183596 .18835449 .6206868 .1451823 .5983887 .1060791 C .5760905 .066975917 .545166 .037404378 .50561526 .017364502 C .46606446 -.0026753743 .4165039 -.0126953129 .3569336 -.0126953129 C .285319 -.0126953129 .22786458 -.00047302247 .18457031 .023971558 C .14127605 .048416139 .10668945 .08744812 .08081055 .1410675 C .05493164 .19468689 .041992189 .26566569 .041992189 .3540039 C .041992189 .48339845 .06917318 .5781657 .123535159 .63830569 C .17789714 .6984456 .25325523 .7285156 .34960938 .7285156 C .40657554 .7285156 .45157878 .72190859 .48461915 .70869448 C .5176595 .69549056 .54508468 .6761678 .56689456 .6507263 C .5887044 .62528488 .60530599 .59332278 .6166992 .5548401 M .25048829 .2355957 C .25048829 .19678752 .2602539 .16637166 .27978517 .14434815 C .2993164 .1223348 .3232422 .111328128 .3515625 .111328128 C .37760417 .111328128 .39941407 .121276859 .4169922 .14117432 C .4345703 .16107178 .44335938 .1907552 .44335938 .23022461 C .44335938 .27067057 .43424479 .30149333 .41601563 .32269288 C .39778648 .34389244 .37516276 .3544922 .34814454 .3544922 C .32047526 .3544922 .2972819 .34421794 .27856446 .32366944 C .25984703 .30312095 .25048829 .27376304 .25048829 .2355957 Z "/> +</symbol> + +<symbol id="cv4"> +<use href="#font_4" transform="translate(25.5,11) rotate(0) scale(12)"/> +<use href="#font_3" transform="translate(40,25.5) rotate(90) scale(12)"/> +<use href="#font_2" transform="translate(25.5,40) rotate(180) scale(12)"/> +<use href="#font_1" transform="translate(11,25.5) rotate(-90) scale(12)"/> +</symbol> + +<symbol id="cv3"> +<use href="#font_3" transform="translate(25.5,11) rotate(0) scale(12)"/> +<use href="#font_2" transform="translate(40,25.5) rotate(90) scale(12)"/> +<use href="#font_1" transform="translate(25.5,40) rotate(180) scale(12)"/> +</symbol> + +<symbol id="cv2"> +<use href="#font_2" transform="translate(25.5,11) rotate(0) scale(12)"/> +<use href="#font_1" transform="translate(40,25.5) rotate(90) scale(12)"/> +</symbol> + +<symbol id="cv1"> +<use href="#font_1" transform="translate(25.5,11) rotate(0) scale(12)"/> +</symbol> + +<symbol id="cv3e"> +<use href="#font_6" transform="translate(25.5,11) rotate(0) scale(12)"/> +<use href="#font_4" transform="translate(40,25.5) rotate(90) scale(12)"/> +<use href="#font_2" transform="translate(25.5,40) rotate(180) scale(12)"/> +</symbol> + +<symbol id="cv2e"> +<use href="#font_4" transform="translate(25.5,11) rotate(0) scale(12)"/> +<use href="#font_2" transform="translate(40,25.5) rotate(90) scale(12)"/> +</symbol> + +<symbol id="cv1e"> +<use href="#font_2" transform="translate(25.5,11) rotate(0) scale(12)"/> +</symbol> + +</defs> +<g font-family="Arial,Helvetica,sans-serif" font-weight="bold">`); + +SYMBOLS = { + +"armor": ` +<path fill="#ccc" stroke="#111" stroke-linejoin="round" stroke-width="1.5" d="M38.3 38.3H12.8V12.9h25.5zm0 0"/> +<path fill="none" stroke="#111" stroke-width="1.5" d="M33.8 25.4c0 2.7-2.4 5-5.4 5h-5.7c-3 0-5.5-2.3-5.5-5s2.5-4.9 5.5-4.9h5.7c3 0 5.4 2.2 5.4 5zm0 0"/> +`, + +"armor_elite": ` +<path fill="#ccc" stroke="#111" stroke-linejoin="round" stroke-width="1.5" d="M38.3 38.3H12.8V12.9h25.5zm0 0"/> +<path fill="#a08672" stroke="#111" stroke-width="1.5" d="M33.8 25.4c0 2.7-2.4 5-5.4 5h-5.7c-3 0-5.5-2.3-5.5-5s2.5-4.9 5.5-4.9h5.7c3 0 5.4 2.2 5.4 5zm0 0"/> +`, + +"armor_itank": ` +<path fill="#ccc" stroke="#111" stroke-linejoin="round" stroke-width="1.5" d="M38.3 38.3H12.8V12.9h25.5zm0 0"/> +<path fill="none" stroke="#111" stroke-width="1.5" d="M34.1 25.4c0 2.7-2.4 4.9-5.4 4.9H23c-3 0-5.5-2.2-5.5-5 0-2.6 2.4-4.8 5.5-4.8h5.7c3 0 5.4 2.2 5.4 4.9zm0 0"/> +<path fill="#111" d="M27.3 28.3h-3.4v-1h1v-3.8h-1v-1h3.4v1h-1v3.7h1zm0 0"/> +`, + +"artillery": ` +<path fill="#ccc" stroke="#111" stroke-linejoin="round" stroke-width="1.5" d="M38.3 38.3H12.8V12.9h25.5zm0 0"/> +<path fill="#111" d="M29.8 25.6c0 2.3-2 4.2-4.3 4.2a4.2 4.2 0 0 1-4.2-4.2 4.2 4.2 0 0 1 4.2-4.2c2.4 0 4.3 1.8 4.3 4.2"/> +`, + +"infantry": ` +<path fill="#ccc" stroke="#111" stroke-linejoin="round" stroke-width="1.5" d="M38.3 38.3H12.8V12.9h25.5zm0 0"/> +<path fill="none" stroke="#111" stroke-width="1.5" d="M12.8 12.8 38.3 38M38.2 13l-25.4 25"/> +`, + +"mechanized_infantry": ` +<path fill="#ccc" stroke="#111" stroke-linejoin="round" stroke-width="1.5" d="M38.3 38.3H12.8V12.9h25.5zm0 0"/> +<path fill="none" stroke="#111" stroke-width="1.5" d="M12.8 12.8 38.3 38M38.2 13l-25.4 25m21-12.5c0 2.7-2.4 5-5.4 5h-5.7c-3 0-5.5-2.3-5.5-5s2.5-4.9 5.5-4.9h5.7c3 0 5.4 2.2 5.4 5zm0 0"/> +`, + +"mobile_antitank": ` +<path fill="#ccc" stroke="#111" stroke-linejoin="round" stroke-width="1.5" d="M38.3 38.3H12.8V12.9h25.5zm0 0"/> +<path fill="none" stroke="#111" stroke-width="1.5" d="M33.8 25.4c0 2.7-2.4 5-5.4 5h-5.7c-3 0-5.5-2.3-5.5-5s2.5-4.9 5.5-4.9h5.7c3 0 5.4 2.2 5.4 5zm0 0"/> +<path fill="#fff" stroke="#111" stroke-width="1.5" d="m25.9 13-9.6 24.9m9.3-25.1 9.1 25.4"/> +`, + +"motorized_antitank_new": ` +<path fill="#ccc" stroke="#111" stroke-linejoin="round" stroke-width="1.5" d="M38.3 38.3H12.8V12.9h25.5zm0 0"/> +<path fill="#fff" stroke="#111" stroke-width="1.5" d="m25.9 13-9.6 24.9m9.3-25.1 9.1 25.4"/> +<path fill="#111" d="M23.8 34.8c0 1.3-1 2.3-2.4 2.3-1.3 0-2.4-1-2.4-2.3s1-2.3 2.4-2.3c1.3 0 2.4 1 2.4 2.3m8.2 0c0 1.3-1 2.3-2.4 2.3-1.3 0-2.4-1-2.4-2.3s1-2.3 2.4-2.3c1.3 0 2.4 1 2.4 2.3"/> +`, + +"motorized_antitank_old": ` +<path fill="#ccc" stroke="#111" stroke-linejoin="round" stroke-width="1.5" d="M38.3 38.3H12.8V12.9h25.5zm0 0"/> +<path fill="#fff" stroke="#111" stroke-width="1.5" d="m25.9 13-9.6 24.9m9.3-25.1 9.1 25.4"/> +`, + +"motorized_infantry": ` +<path fill="#ccc" stroke="#111" stroke-linejoin="round" stroke-width="1.5" d="M38.3 38.3H12.8V12.9h25.5zm0 0"/> +<path fill="none" stroke="#111" stroke-width="1.5" d="M12.8 12.8 38.3 38M38.2 13l-25.4 25"/> +<path fill="#111" d="M23.7 34.7c0 1.3-1 2.4-2.4 2.4-1.3 0-2.4-1-2.4-2.4s1-2.3 2.4-2.3c1.3 0 2.4 1 2.4 2.3m8.2 0c0 1.3-1 2.4-2.4 2.4a2.3 2.3 0 1 1 0-4.7c1.4 0 2.4 1 2.4 2.3"/> +`, + +"paratroopers": ` +<path fill="#ccc" stroke="#111" stroke-linejoin="round" stroke-width="1.5" d="M38.3 38.3H12.8V12.9h25.5zm0 0"/> +<path fill="none" stroke="#111" stroke-width="1.5" d="M12.8 12.8 38.3 38M38.2 13l-25.4 25m12.6-1.5v-2c0-1 1-1.8 2.2-1.8 1.2 0 2.2.9 2.2 1.9v1.9m-8.8 0v-2c0-1 1-1.8 2.2-1.8 1.2 0 2.2.9 2.2 1.9v1.9"/> +`, + +"recon": ` +<path fill="#ccc" stroke="#111" stroke-linejoin="round" stroke-width="1.5" d="M38.3 38.3H12.8V12.9h25.5zm0 0"/> +<path fill="none" stroke="#111" stroke-width="1.5" d="M33.8 25.4c0 2.7-2.4 5-5.4 5h-5.7c-3 0-5.5-2.3-5.5-5s2.5-4.9 5.5-4.9h5.7c3 0 5.4 2.2 5.4 5zM38.2 13l-25.4 25"/> +`, + +"self_propelled_artillery": ` +<path fill="#ccc" stroke="#111" stroke-linejoin="round" stroke-width="1.5" d="M38.3 38.3H12.8V12.8h25.5zm0 0"/> +<path fill="none" stroke="#111" stroke-width="1.5" d="M33.8 25.5c0 2.7-2.4 5-5.4 5h-5.7c-3 0-5.5-2.3-5.5-5s2.4-4.9 5.5-4.9h5.7c3 0 5.4 2.2 5.4 5zm0 0"/> +<path fill="#111" d="M29 25.5a3.4 3.4 0 0 1-3.5 3.4 3.4 3.4 0 0 1-3.4-3.4 3.4 3.4 0 0 1 3.4-3.4 3.4 3.4 0 0 1 3.4 3.4"/> +`, + +} + +const TYPEMAP = { + "armor": "armor", + "artillery": "artillery", + "i-tank": "armor_itank", + "infantry": "infantry", + "mech. inf.": "mechanized_infantry", + "mob. a/t": "mobile_antitank", + "mot. a/t": "motorized_antitank_new", + "mot. inf.": "motorized_infantry", + "para": "paratroopers", + "recon": "recon", + "self prop. arty": "self_propelled_artillery", +}; + +// 94 units + +let smcp = /(IN|AU|NZ|SA|AT|H|G)$/; +smcp = /NEVER/; + +const COLORMAP = { + "italian": "#b0c5d4", + "german": "#f9e3b3", + "allied": "#cead78", + "Pol": "#ffffff", + "FF": "#8197cd", + "NZ": "#95c3d6", + "AU": "#f48480", + "SA": "#f9a64a", + "IN": "#84c88b", +} + +const BLACK = { + italian: "#221f1f", + german: "#004e2f", + allied: "#5c3a1e" +} + +let x = 0, y = 0; +for (let u of units) { + let type = TYPEMAP[u.type]; + let black = BLACK[u.nationality]; + let fill = COLORMAP[u.nationality]; + + let [a, b] = u.name.split('/'); + if (b) + b = b.split('+'); + + for (let n in COLORMAP) + if (a.endsWith(n) || (b && b[0] === n)) + fill = COLORMAP[n]; + + print(`<g transform="translate(${x},${y})">`); + + if (type === 'armor' && u.elite && u.nationality === 'allied') + type = 'armor_elite'; + + let symbol = SYMBOLS[type]; + print(symbol.replace(/#ccc/g, fill).replace(/#111/g, black).trim()); + + if (u.elite) + print(`<use href="#cv${u.steps}e" fill="${black}"/>`); + else + print(`<use href="#cv${u.steps}" fill="${black}"/>`); + + print(`<g fill="${black}">`); + print(`<text text-anchor="start" font-size="7" x="2" y="8">${u.appearance}</text>`); + print(`<text text-anchor="start" font-size="7" x="2" y="48">${a}</text>`); + + if (b) { + if (b.length > 1) { + print(`<text text-anchor="end" font-size="7" x="49" y="43">${b[0]}</text>`); + print(`<text text-anchor="end" font-size="7" x="49" y="49">${b[1]}</text>`); + } else { + print(`<text text-anchor="end" font-size="7" x="48" y="48">${b[0]}</text>`); + } + } + + print(`</g>`); + print(`</g>`); + x += 51; + if (x >= 510) { + y += 51; + x = 0; + } +} +print(`</g>`); +print(`</svg>`); diff --git a/tools/rock_overlay.png b/tools/rock_overlay.png Binary files differnew file mode 100644 index 0000000..d2c6976 --- /dev/null +++ b/tools/rock_overlay.png diff --git a/tools/rock_overlay@2x.png b/tools/rock_overlay@2x.png Binary files differnew file mode 100644 index 0000000..8710ab6 --- /dev/null +++ b/tools/rock_overlay@2x.png diff --git a/tools/scree_overlay.png b/tools/scree_overlay.png Binary files differnew file mode 100644 index 0000000..cab6b5c --- /dev/null +++ b/tools/scree_overlay.png diff --git a/tools/scree_overlay@2x.png b/tools/scree_overlay@2x.png Binary files differnew file mode 100644 index 0000000..5680582 --- /dev/null +++ b/tools/scree_overlay@2x.png diff --git a/tools/wetland.pbm b/tools/wetland.pbm Binary files differnew file mode 100644 index 0000000..aa9151c --- /dev/null +++ b/tools/wetland.pbm |