From 719d61982953caf61c0df7776347e13105a2e8b2 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Sat, 22 Oct 2022 12:53:57 +0200 Subject: Add asset rendering scripts. --- tools/gendata.js | 705 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 705 insertions(+) create mode 100644 tools/gendata.js (limited to 'tools/gendata.js') diff --git a/tools/gendata.js b/tools/gendata.js new file mode 100644 index 0000000..2968023 --- /dev/null +++ b/tools/gendata.js @@ -0,0 +1,705 @@ +// Run this script inside the "tools" directory to generate data.js and build_counters3.sh + +"use strict" + +const fs = require('fs') + +// :r !python3 genboxes.py +const boxes = { +"Wesenberg": [1448,3625,304,60], +"Fellin": [1013,4583,184,61], +"Odenpäh": [1378,5103,250,61], +"Adsel": [1504,5612,185,60], +"Wenden": [909,5759,232,60], +"Luga": [2667,3295,148,62], +"Kaibolovo": [2904,3522,285,62], +"Koporye": [3133,3160,241,62], +"Neva": [3924,2934,148,62], +"Volkhov": [4591,3783,231,63], +"Lovat": [4243,5581,187,63], +"Porkhov": [3515,5467,241,63], +"Izborsk": [2240,5431,241,62], +"Velikiye Luki": [3706,6347,351,61], +"Tesovo": [3936,4102,121,32], +"Zheltsy": [3501,4176,128,30], +"Sablia": [3788,4541,104,31], +"Gdov": [2427,4149,88,30], +"Dubrovno": [3153,5214,161,31], +"Ostrov": [2746,5717,115,30], +"Rositten": [2046,6307,146,30], +"Kirrumpäh": [1877,5389,175,30], +"Pernau": [517,4580,118,30], +"Narwia": [2371,3549,123,31], +"Wierland": [1999,3680,200,100], +"Warbola": [292,3797,142,31], +"Waiga": [1535,4113,200,100], +"Jerwen": [1064,3946,200,100], +"Harrien": [567,3983,200,100], +"Sackala": [617,4769,200,100], +"Metsepole": [509,5226,200,100], +"Lettgallia": [2048,5777,200,100], +"Tolowa": [1541,5933,200,100], +"Ugaunia": [1957,4940,200,100], +"Revala": [1030,3410,200,100], +"Velikaya River": [3029,6090,200,100], +"Sorot River": [3299,5781,200,100], +"Shelon River": [3654,4864,200,100], +"Zhelcha River": [2782,4586,200,100], +"Plyussa River": [2829,4234,200,100], +"Ingria": [3820,3639,200,100], +"Vod": [3488,3345,200,100], +"Izhora": [4074,3323,200,100], +"Karelia": [3833,2408,200,100], +"Ladoga": [4619,2817,238,90], +"Novgorod": [4318,4315,333,112], +"Rusa": [4329,5166,205,92], +"Riga": [273,6231,205,91], +"Pskov": [2680,5263,205,91], +"Dorpat": [1625,4589,253,91], +"Leal": [108,4266,205,91], +"Reval": [601,3564,206,91], +"box1": [40,168,592,917], +"box2": [650,168,591,913], +"box3": [1313,167,591,916], +"box4": [1922,167,590,916], +"box5": [2587,167,592,918], +"box6": [3196,167,588,916], +"box7": [3859,167,594,916], +"box8": [4469,166,591,918], +"box9": [39,1119,594,915], +"Victory": [172,183,217,215], +"Turn": [399,184,216,214], +"Novgorod Veche": [4193,5847,844,628], +"Uzmen": [2112,4692,200,100], +"way-crossroads": [1500,4717,462,149], +"way-wirz": [1295,4526,175,350], +"way-peipus-east": [2232,4197,220,465], +"way-peipus-north": [2065,3836,361,228], +"way-peipus-west": [1988,4141,218,520], +} + +let data = [] +function print(str) { + data.push(str) +} + +var locmap = {} + +// 0=offmap, 1-N=map locales, 100-M=calendar boxes +var locales = [null] +var ways = [] +var waterways = [] +var trackways = [] + +const scale = 1 + +function defloc(region, stronghold, type, name) { + let [x, y, w, h] = boxes[name] + x = Math.round(x * scale) + y = Math.round(y * scale) + w = Math.round(w * scale) + h = Math.round(h * scale) + locmap[name] = locales.length + locales.push({ name, type, stronghold, region, ways: [], box: { x, y, w, h } }) +} + +function defway(type, list) { + let ix = ways.length + list = list.map(name=>locmap[name]).sort((a,b)=>a-b) + ways.push({type, locales: list}) + for (let from of list) { + for (let to of list) { + if (from !== to) { + let old = locales[from].ways.find(w => w[0] === to) + if (old) + old.push(ix) + else + locales[from].ways.push([to, ix]) + } + } + } + return ways[ix] +} + +function waterway(locs) { return defway('waterway', locs.split(", ")) } +function trackway(locs) { return defway('trackway', locs.split(", ")) } + +defloc("Danish Estonia", 3, "bishopric", "Reval") +defloc("Danish Estonia", 2, "castle", "Wesenberg") +defloc("Danish Estonia", 0, "town", "Narwia") +defloc("Danish Estonia", 0, "town", "Warbola") +defloc("Danish Estonia", 0, "region", "Harrien") +defloc("Danish Estonia", 0, "region", "Revala") +defloc("Danish Estonia", 0, "region", "Wierland") + +defloc("Crusader Livonia", 3, "bishopric", "Dorpat") +defloc("Crusader Livonia", 3, "bishopric", "Leal") +defloc("Crusader Livonia", 3, "bishopric", "Riga") +defloc("Crusader Livonia", 2, "castle", "Adsel") +defloc("Crusader Livonia", 2, "castle", "Fellin") +defloc("Crusader Livonia", 2, "castle", "Odenpäh") +defloc("Crusader Livonia", 2, "castle", "Wenden") +defloc("Crusader Livonia", 0, "town", "Kirrumpäh") +defloc("Crusader Livonia", 0, "town", "Pernau") +defloc("Crusader Livonia", 0, "town", "Rositten") +defloc("Crusader Livonia", 0, "region", "Jerwen") +defloc("Crusader Livonia", 0, "region", "Lettgallia") +defloc("Crusader Livonia", 0, "region", "Metsepole") +defloc("Crusader Livonia", 0, "region", "Sackala") +defloc("Crusader Livonia", 0, "region", "Tolowa") +defloc("Crusader Livonia", 0, "region", "Ugaunia") +defloc("Crusader Livonia", 0, "region", "Waiga") + +defloc("Novgorodan Rus", 3, "archbishopric", "Novgorod") +defloc("Novgorodan Rus", 3, "city", "Ladoga") +defloc("Novgorodan Rus", 3, "city", "Pskov") +defloc("Novgorodan Rus", 3, "city", "Rusa") +defloc("Novgorodan Rus", 0, "traderoute", "Lovat") +defloc("Novgorodan Rus", 0, "traderoute", "Luga") +defloc("Novgorodan Rus", 0, "traderoute", "Neva") +defloc("Novgorodan Rus", 0, "traderoute", "Volkhov") +defloc("Novgorodan Rus", 1, "fort", "Izborsk") +defloc("Novgorodan Rus", 1, "fort", "Kaibolovo") +defloc("Novgorodan Rus", 1, "fort", "Koporye") +defloc("Novgorodan Rus", 1, "fort", "Porkhov") +defloc("Novgorodan Rus", 1, "fort", "Velikiye Luki") +defloc("Novgorodan Rus", 0, "town", "Dubrovno") +defloc("Novgorodan Rus", 0, "town", "Gdov") +defloc("Novgorodan Rus", 0, "town", "Ostrov") +defloc("Novgorodan Rus", 0, "town", "Sablia") +defloc("Novgorodan Rus", 0, "town", "Tesovo") +defloc("Novgorodan Rus", 0, "town", "Zheltsy") +defloc("Novgorodan Rus", 0, "region", "Ingria") +defloc("Novgorodan Rus", 0, "region", "Izhora") +defloc("Novgorodan Rus", 0, "region", "Karelia") +defloc("Novgorodan Rus", 0, "region", "Plyussa River") +defloc("Novgorodan Rus", 0, "region", "Shelon River") +defloc("Novgorodan Rus", 0, "region", "Sorot River") +defloc("Novgorodan Rus", 0, "region", "Uzmen") +defloc("Novgorodan Rus", 0, "region", "Velikaya River") +defloc("Novgorodan Rus", 0, "region", "Vod") +defloc("Novgorodan Rus", 0, "region", "Zhelcha River") + +waterway("Dorpat, Narwia, Gdov, Uzmen").name = "Pleipat W" +waterway("Gdov, Uzmen").name = "Pleipat E" +waterway("Fellin, Dorpat, Odenpäh").name = "Wirz" +trackway("Dorpat, Odenpäh, Ugaunia").name = "Crossroads" + +waterway("Uzmen, Pskov") +waterway("Uzmen, Zhelcha River") +waterway("Novgorod, Shelon River, Rusa") +waterway("Pernau, Fellin, Jerwen") +waterway("Riga, Wenden") +waterway("Wenden, Adsel") +waterway("Pskov, Ostrov") +waterway("Ostrov, Velikaya River") +waterway("Sorot River, Velikaya River") +waterway("Rusa, Lovat") +waterway("Lovat, Velikiye Luki") +waterway("Shelon River, Dubrovno") +waterway("Shelon River, Porkhov") +waterway("Narwia, Plyussa River") +waterway("Luga, Kaibolovo") +waterway("Kaibolovo, Zheltsy") +waterway("Zheltsy, Sablia") +waterway("Zheltsy, Tesovo") +waterway("Ladoga, Volkhov") +waterway("Volkhov, Novgorod") +waterway("Neva, Ladoga") + +trackway("Reval, Revala") +trackway("Revala, Wesenberg") +trackway("Wierland, Narwia") +trackway("Narwia, Kaibolovo") +trackway("Wierland, Waiga") +trackway("Wesenberg, Jerwen") +trackway("Reval, Warbola") +trackway("Warbola, Harrien") +trackway("Harrien, Jerwen") +trackway("Warbola, Leal") + +trackway("Waiga, Dorpat") +trackway("Leal, Pernau") +trackway("Fellin, Sackala") +trackway("Sackala, Metsepole") +trackway("Metsepole, Wenden") +trackway("Wenden, Tolowa") +trackway("Tolowa, Rositten") +trackway("Lettgallia, Rositten") +trackway("Adsel, Tolowa, Lettgallia") +trackway("Adsel, Kirrumpäh") +trackway("Odenpäh, Kirrumpäh") +trackway("Kirrumpäh, Izborsk") +trackway("Ugaunia, Uzmen") +trackway("Ugaunia, Izborsk") +trackway("Lettgallia, Ostrov") +trackway("Lettgallia, Izborsk") + +trackway("Izborsk, Pskov") +trackway("Kaibolovo, Koporye") +trackway("Koporye, Vod") +trackway("Vod, Neva") +trackway("Vod, Ingria") +trackway("Karelia, Neva") +trackway("Neva, Izhora") +trackway("Izhora, Ladoga") +trackway("Izhora, Ingria") +trackway("Ingria, Tesovo") +trackway("Tesovo, Novgorod") +trackway("Novgorod, Sablia") +trackway("Sablia, Shelon River") + +trackway("Gdov, Plyussa River") +trackway("Plyussa River, Zheltsy") +trackway("Plyussa River, Zhelcha River") +trackway("Zhelcha River, Pskov") +trackway("Pskov, Dubrovno") +trackway("Dubrovno, Porkhov") +trackway("Porkhov, Sorot River") +trackway("Velikaya River, Velikiye Luki") + +let seaports = [ + "Riga", "Pernau", "Leal", "Reval", "Narwia", "Luga", "Koporye", "Neva" +].map(name => locmap[name]).sort((a,b)=>a-b) + +function dumplist(name, list) { + print(name + ":[") + for (let item of list) + print(JSON.stringify(item) + ",") + print("],") +} + +function seats(list) { + return list.split(", ").map(name => locmap[name]).sort((a,b)=>a-b) +} + +let lords = [ + + { + side: "Teutonic", + name: "Andreas", + full_name: "Andreas von Felben", + title: "Landmeister in Livonia", + seats: seats("Riga, Wenden"), + marshal: 2, + fealty: 2, + service: 4, + lordship: 3, + command: 3, + forces: { + knights: 1, + sergeants: 2, + light_horse: 0, + men_at_arms: 1, + militia: 0, + }, + assets: { + transport: 2, + prov: 2, + }, + ships: 1, + }, + + { + side: "Teutonic", + name: "Heinrich", + full_name: "Heinrich", + title: "Bishop of Ösel-Wiek", + seats: seats("Leal"), + marshal: 0, + fealty: 3, + service: 4, + lordship: 2, + command: 1, + forces: { + knights: 1, + sergeants: 1, + light_horse: 0, + men_at_arms: 1, + militia: 0, + }, + assets: { + ship: 1, + coin: 2, + prov: 1, + }, + ships: 1, + }, + + { + side: "Teutonic", + name: "Hermann", + full_name: "Hermann", + title: "Bishop of Dorpat", + seats: seats("Dorpat, Odenpäh"), + marshal: 1, + fealty: 4, + service: 4, + lordship: 3, + command: 3, + forces: { + knights: 1, + sergeants: 1, + light_horse: 0, + men_at_arms: 2, + militia: 0, + }, + assets: { + transport: 1, + coin: 1, + prov: 1, + }, + ships: 0, + }, + + { + side: "Teutonic", + name: "Knud & Abel", + full_name: "Knud & Abel", + title: "Princes of Denmark", + seats: seats("Reval, Wesenburg"), + marshal: 0, + fealty: 2, + service: 3, + lordship: 3, + command: 2, + forces: { + knights: 1, + sergeants: 1, + light_horse: 3, + men_at_arms: 0, + militia: 0, + }, + assets: { + ship: 2, + prov: 2, + }, + ships: 1, + }, + + { + side: "Teutonic", + name: "Rudolf", + full_name: "Rudolf von Kassel", + title: "Castellan of Wenden", + seats: seats("Wenden"), + marshal: 0, + fealty: 5, + service: 2, + lordship: 1, + command: 3, + forces: { + knights: 1, + sergeants: 1, + light_horse: 0, + men_at_arms: 1, + militia: 0, + }, + assets: { + transport: 1, + prov: 1, + }, + ships: 0, + }, + + { + side: "Teutonic", + name: "Yaroslav", + full_name: "Yaroslav", + title: "Exile of Pskov", + seats: seats("Odenpäh, Pskov"), + marshal: 0, + fealty: 4, + service: 2, + lordship: 1, + command: 2, + forces: { + knights: 1, + sergeants: 0, + light_horse: 1, + men_at_arms: 1, + militia: 0, + }, + assets: { + transport: 1, + prov: 1, + }, + ships: 0, + }, + + { + side: "Russian", + name: "Aleksandr", + full_name: "Aleksandr", + title: "Prince of Novgorod", + seats: seats("Novgorod, Rusa"), + marshal: 2, + fealty: 0, + service: 6, + lordship: 4, + command: 3, + forces: { + knights: 3, + sergeants: 0, + light_horse: 0, + men_at_arms: 2, + militia: 0, + }, + assets: { + transport: 2, + }, + ships: 1, + }, + + { + side: "Russian", + name: "Andrey", + full_name: "Andrey", + title: "Prince of Suzdal", + seats: seats("Novgorod, Rusa"), + marshal: 1, + fealty: 4, + service: 5, + lordship: 3, + command: 2, + forces: { + knights: 3, + sergeants: 0, + light_horse: 0, + men_at_arms: 2, + militia: 0, + }, + assets: { + transport: 2, + }, + ships: 1, + }, + + { + side: "Russian", + name: "Domash", + full_name: "Domash", + title: "Tysyatskiy of Novgorod", + seats: seats("Novgorod"), + marshal: 0, + fealty: 4, + service: 4, + lordship: 2, + command: 2, + forces: { + knights: 0, + sergeants: 1, + light_horse: 1, + men_at_arms: 2, + militia: 1, + }, + assets: { + transport: 4, + prov: 4, + }, + ships: 1, + }, + + { + side: "Russian", + name: "Gavrilo", + full_name: "Gavrilo", + title: "Voyevoda of Pskov", + seats: seats("Pskov"), + marshal: 0, + fealty: 3, + service: 4, + lordship: 3, + command: 2, + forces: { + knights: 1, + sergeants: 0, + light_horse: 1, + men_at_arms: 1, + militia: 1, + }, + assets: { + transport: 2, + coin: 1, + prov: 2, + }, + ships: 1, + }, + + { + side: "Russian", + name: "Karelians", + full_name: "Karelians", + title: "Tributaries of Novgorod", + seats: seats("Ladoga"), + marshal: 0, + fealty: 4, + service: 2, + lordship: 1, + command: 2, + forces: { + knights: 0, + sergeants: 0, + light_horse: 1, + men_at_arms: 0, + militia: 4, + }, + assets: { + transport: 1, + }, + ships: 1, + }, + + { + side: "Russian", + name: "Vladislav", + full_name: "Vladislav", + title: "Bailiff of Ladoga", + seats: seats("Ladoga"), + marshal: 0, + fealty: 5, + service: 3, + lordship: 2, + command: 3, + forces: { + knights: 0, + sergeants: 1, + light_horse: 1, + men_at_arms: 2, + militia: 0, + }, + assets: { + transport: 1, + prov: 1, + }, + ships: 1, + }, + +] + +let vassals = [] +for (let lord of lords) + lord.vassals = [] + +function vassal(lord, service, name, forces, capability) { + let lord_id = lords.findIndex(x => x.name === lord) + if (lord_id < 0) throw Error("no such lord", lord) + lords[lord_id].vassals.push(vassals.length) + vassals.push({ lord: lord_id, name, service, forces, capability }) +} + +vassal("Andreas", 1, "Lettgallian Auxiliaries", { light_horse: 1, militia: 1 }) +vassal("Andreas", 2, "Summer Crusaders", { knights: 3 }, "Crusade") +vassal("Andreas", 3, "Teutonic Vassals", { knights: 1, men_at_arms: 2 }) + +vassal("Heinrich", 2, "Heinrich von Lode", { knights: 1, men_at_arms: 1 }) +vassal("Heinrich", 2, "Odward von Lode", { knights: 1, men_at_arms: 1 }) + +vassal("Hermann", 2, "Helmond von Lüneburg", { knights: 1, men_at_arms: 1 }) +vassal("Hermann", 2, "Johannes von Dolen", { knights: 1, men_at_arms: 1 }) +vassal("Hermann", 1, "Ugaunian Auxiliaries", { light_horse: 1, militia: 1 }) + +vassal("Knud & Abel", 2, "Dietrich von Kivel", { knights: 1, men_at_arms: 1 }) +vassal("Knud & Abel", 1, "Estonian Auxiliaries", { light_horse: 1, militia: 1 }) +vassal("Knud & Abel", 2, "Otto von Lüneburg", { knights: 1, men_at_arms: 1 }) + +vassal("Rudolf", 2, "Ex-Sword Brethren", { knights: 1, sergeants: 1 }) +vassal("Rudolf", 2, "Jerwen Teutonic Vassals", { knights: 1, men_at_arms: 1 }) +vassal("Rudolf", 2, "Summer Crusaders", { knights: 2 }, "Crusade") + +vassal("Yaroslav", 1, "Mstislavich Partisans", { militia: 2 }) + +vassal("Aleksandr", 3, "Mongols", { asiatic_horse: 2 }, "Steppe Warriors") +vassal("Aleksandr", 3, "Mongols", { asiatic_horse: 2 }, "Steppe Warriors") +vassal("Aleksandr", 4, "Pereyaslavl", { men_at_arms: 1 }) +vassal("Aleksandr", 3, "Rostov", { men_at_arms: 1 }) +vassal("Aleksandr", 3, "Yaroslavl", { men_at_arms: 1 }) + +vassal("Andrey", 3, "Kipchaqs", { asiatic_horse: 3 }, "Steppe Warriors") +vassal("Andrey", 3, "Kipchaqs", { asiatic_horse: 3 }, "Steppe Warriors") +vassal("Andrey", 4, "Suzdal", { men_at_arms: 1 }) +vassal("Andrey", 4, "Vladimir", { men_at_arms: 1 }) + +vassal("Domash", 2, "Novgorod", { militia: 2 }) +vassal("Domash", 2, "Novgorod", { militia: 2 }) +vassal("Domash", 2, "Novgorod", { militia: 2 }) + +vassal("Gavrilo", 1, "Borderland Russians", { light_horse: 1, militia: 1 }) +vassal("Gavrilo", 2, "Pskov Militia", { militia: 2 }) +vassal("Gavrilo", 4, "Pskov", { men_at_arms: 1 }) + +vassal("Vladislav", 1, "Izhoran Auxiliaries", { militia: 1 }) +vassal("Vladislav", 1, "Ingrian Auxiliaries", { militia: 1 }) +vassal("Vladislav", 1, "Vepsian Auxiliaries", { militia: 1 }) +vassal("Vladislav", 1, "Vodian Auxiliaries", { militia: 1 }) + +function to_path(name) { + return name + .toLowerCase() + .replace(/&/g, 'and') + .replace(/[ -]/g, '_') + .replace(/ü/g, 'u') + .replace(/ö/g, 'o') + .replace(/ä/g, 'a') +} + +let lord_service = {Russian:[],Teutonic:[]} +let vassal_service = {Russian:[],Teutonic:[]} + +let last_path, last_side, last_ix + +last_path = null +last_side = null +lords.forEach((lord,id) => { + let side = lord.side + let path = "counters300/lord_" + side.toLowerCase() + "_" + to_path(lord.name) + if (side !== last_side) { + last_ix = 0 + last_side = side + } + lord.image = last_ix + if (path !== last_path) { + last_ix++ + last_path = path + lord_service[side].push(path + ".a.png") + lord_service[side].push(path + ".b.png") + } +}) + +last_path = null +last_side = null +vassals.forEach((vassal,id) => { + let lord = lords[vassal.lord] + let side = lord.side + let path = "counters300/vassal_" + side.toLowerCase() + "_" + to_path(lord.name) + "_" + to_path(vassal.name) + if (side !== last_side) { + last_ix = 0 + last_side = side + } + vassal.image = last_ix + if (path !== last_path) { + last_ix++ + last_path = path + vassal_service[side].push(path + ".a.png") + vassal_service[side].push(path + ".b.png") + } +}) + +let script = [] +script.push("mkdir -p service300") +script.push("montage -mode concatenate -tile 2x " + lord_service.Teutonic.join(" ") + " service300/service_lords_teutonic.png") +script.push("montage -mode concatenate -tile 2x " + vassal_service.Teutonic.join(" ") + " service300/service_vassals_teutonic.png") +script.push("montage -mode concatenate -tile 2x " + lord_service.Russian.join(" ") + " service300/service_lords_russian.png") +script.push("montage -mode concatenate -tile 2x " + vassal_service.Russian.join(" ") + " service300/service_vassals_russian.png") + +print("const data = {") +print("seaports:" + JSON.stringify(seaports) + ",") +dumplist("locales", locales) +dumplist("ways", ways) +dumplist("lords", lords) +dumplist("vassals", vassals) +print("}") +print("if (typeof module !== 'undefined') module.exports = data") + +fs.writeFileSync("build_counters3.sh", script.join("\n") + "\n") +fs.writeFileSync("../data.js", data.join("\n") + "\n") -- cgit v1.2.3