summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data.js106
-rw-r--r--rules.js391
-rw-r--r--tools/gendata.js5
3 files changed, 322 insertions, 180 deletions
diff --git a/data.js b/data.js
index 4d8cc22..c1a60fc 100644
--- a/data.js
+++ b/data.js
@@ -3,59 +3,59 @@ seaports:[0,2,8,9,15,29,30,34],
conquerable:[0,1,7,8,9,10,11,12,13,24,25,26,27,28,29,30,31,32,33,34,35,36],
strongholds:[0,1,7,8,9,10,11,12,13,24,25,26,27,32,33,34,35,36],
locales:[
-{"name":"Reval","type":"bishopric","stronghold":3,"walls":4,"vp":2,"region":"Danish Estonia","ways":[[5,25],[3,32]],"box":{"x":601,"y":3564,"w":206,"h":91},"adjacent":[3,5],"adjacent_by_trackway":[3,5]},
-{"name":"Wesenberg","type":"castle","stronghold":2,"walls":4,"vp":1,"region":"Danish Estonia","ways":[[5,26],[17,30],[6,31]],"box":{"x":1448,"y":3625,"w":304,"h":60},"adjacent":[5,6,17],"adjacent_by_trackway":[5,6,17]},
-{"name":"Narwia","type":"town","stronghold":0,"walls":0,"vp":0,"region":"Danish Estonia","ways":[[7,2],[38,2],[49,2],[46,17],[6,27],[33,28]],"box":{"x":2371,"y":3549,"w":123,"h":31},"adjacent":[6,7,33,38,46,49],"adjacent_by_trackway":[6,33]},
-{"name":"Warbola","type":"town","stronghold":0,"walls":0,"vp":0,"region":"Danish Estonia","ways":[[0,32],[4,33],[8,35]],"box":{"x":292,"y":3797,"w":142,"h":31},"adjacent":[0,4,8],"adjacent_by_trackway":[0,4,8]},
-{"name":"Harrien","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Danish Estonia","ways":[[3,33],[17,34]],"box":{"x":567,"y":3983,"w":200,"h":100},"adjacent":[3,17],"adjacent_by_trackway":[3,17]},
-{"name":"Revala","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Danish Estonia","ways":[[0,25],[1,26]],"box":{"x":1030,"y":3410,"w":200,"h":100},"adjacent":[0,1],"adjacent_by_trackway":[0,1]},
-{"name":"Wierland","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Danish Estonia","ways":[[2,27],[23,29],[1,31]],"box":{"x":1999,"y":3680,"w":200,"h":100},"adjacent":[1,2,23],"adjacent_by_trackway":[1,2,23]},
-{"name":"Dorpat","type":"bishopric","stronghold":3,"walls":4,"vp":2,"region":"Crusader Livonia","ways":[[12,0,3],[22,0],[2,2],[38,2],[49,2],[11,3],[23,36]],"box":{"x":1625,"y":4589,"w":253,"h":91},"adjacent":[2,11,12,22,23,38,49],"adjacent_by_trackway":[12,22,23]},
-{"name":"Leal","type":"bishopric","stronghold":3,"walls":4,"vp":2,"region":"Crusader Livonia","ways":[[3,35],[15,37]],"box":{"x":108,"y":4266,"w":205,"h":91},"adjacent":[3,15],"adjacent_by_trackway":[3,15]},
-{"name":"Riga","type":"bishopric","stronghold":3,"walls":4,"vp":2,"region":"Crusader Livonia","ways":[[13,8]],"box":{"x":273,"y":6231,"w":205,"h":91},"adjacent":[13],"adjacent_by_trackway":[]},
-{"name":"Adsel","type":"castle","stronghold":2,"walls":4,"vp":1,"region":"Crusader Livonia","ways":[[13,9],[18,44],[21,44],[14,45]],"box":{"x":1504,"y":5612,"w":185,"h":60},"adjacent":[13,14,18,21],"adjacent_by_trackway":[14,18,21]},
-{"name":"Fellin","type":"castle","stronghold":2,"walls":4,"vp":1,"region":"Crusader Livonia","ways":[[7,3],[12,3],[15,7],[17,7],[20,38]],"box":{"x":1013,"y":4583,"w":184,"h":61},"adjacent":[7,12,15,17,20],"adjacent_by_trackway":[20]},
-{"name":"Odenpäh","type":"castle","stronghold":2,"walls":4,"vp":1,"region":"Crusader Livonia","ways":[[7,0,3],[22,0],[11,3],[14,46]],"box":{"x":1378,"y":5103,"w":250,"h":61},"adjacent":[7,11,14,22],"adjacent_by_trackway":[7,14,22]},
-{"name":"Wenden","type":"castle","stronghold":2,"walls":4,"vp":1,"region":"Crusader Livonia","ways":[[9,8],[10,9],[19,40],[21,41]],"box":{"x":909,"y":5759,"w":232,"h":60},"adjacent":[9,10,19,21],"adjacent_by_trackway":[19,21]},
-{"name":"Kirrumpäh","type":"town","stronghold":0,"walls":0,"vp":0,"region":"Crusader Livonia","ways":[[10,45],[12,46],[32,47]],"box":{"x":1877,"y":5389,"w":175,"h":30},"adjacent":[10,12,32],"adjacent_by_trackway":[10,12,32]},
-{"name":"Pernau","type":"town","stronghold":0,"walls":0,"vp":0,"region":"Crusader Livonia","ways":[[11,7],[17,7],[8,37]],"box":{"x":517,"y":4580,"w":118,"h":30},"adjacent":[8,11,17],"adjacent_by_trackway":[8]},
-{"name":"Rositten","type":"town","stronghold":0,"walls":0,"vp":0,"region":"Crusader Livonia","ways":[[21,42],[18,43]],"box":{"x":2046,"y":6307,"w":146,"h":30},"adjacent":[18,21],"adjacent_by_trackway":[18,21]},
-{"name":"Jerwen","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Crusader Livonia","ways":[[11,7],[15,7],[1,30],[4,34]],"box":{"x":1064,"y":3946,"w":200,"h":100},"adjacent":[1,4,11,15],"adjacent_by_trackway":[1,4]},
-{"name":"Lettgallia","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Crusader Livonia","ways":[[16,43],[10,44],[21,44],[39,50],[32,51]],"box":{"x":2048,"y":5777,"w":200,"h":100},"adjacent":[10,16,21,32,39],"adjacent_by_trackway":[10,16,21,32,39]},
-{"name":"Metsepole","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Crusader Livonia","ways":[[20,39],[13,40]],"box":{"x":509,"y":5226,"w":200,"h":100},"adjacent":[13,20],"adjacent_by_trackway":[13,20]},
-{"name":"Sackala","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Crusader Livonia","ways":[[11,38],[19,39]],"box":{"x":617,"y":4769,"w":200,"h":100},"adjacent":[11,19],"adjacent_by_trackway":[11,19]},
-{"name":"Tolowa","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Crusader Livonia","ways":[[13,41],[16,42],[10,44],[18,44]],"box":{"x":1541,"y":5933,"w":200,"h":100},"adjacent":[10,13,16,18],"adjacent_by_trackway":[10,13,16,18]},
-{"name":"Ugaunia","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Crusader Livonia","ways":[[7,0],[12,0],[49,48],[32,49]],"box":{"x":1957,"y":4940,"w":200,"h":100},"adjacent":[7,12,32,49],"adjacent_by_trackway":[7,12,32,49]},
-{"name":"Waiga","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Crusader Livonia","ways":[[6,29],[7,36]],"box":{"x":1535,"y":4113,"w":200,"h":100},"adjacent":[6,7],"adjacent_by_trackway":[6,7]},
-{"name":"Novgorod","type":"novgorod","stronghold":3,"walls":3,"vp":3,"region":"Novgorodan Rus","ways":[[27,6],[47,6],[31,23],[41,62],[40,63]],"box":{"x":4318,"y":4315,"w":333,"h":112},"adjacent":[27,31,40,41,47],"adjacent_by_trackway":[40,41]},
-{"name":"Ladoga","type":"city","stronghold":3,"walls":3,"vp":2,"region":"Novgorodan Rus","ways":[[31,22],[30,24],[44,59]],"box":{"x":4619,"y":2817,"w":238,"h":90},"adjacent":[30,31,44],"adjacent_by_trackway":[44]},
-{"name":"Pskov","type":"city","stronghold":3,"walls":3,"vp":2,"region":"Novgorodan Rus","ways":[[49,4],[39,10],[32,52],[52,68],[37,69]],"box":{"x":2680,"y":5263,"w":205,"h":91},"adjacent":[32,37,39,49,52],"adjacent_by_trackway":[32,37,52]},
-{"name":"Rusa","type":"city","stronghold":3,"walls":3,"vp":2,"region":"Novgorodan Rus","ways":[[24,6],[47,6],[28,13]],"box":{"x":4329,"y":5166,"w":205,"h":92},"adjacent":[24,28,47],"adjacent_by_trackway":[]},
-{"name":"Lovat","type":"traderoute","stronghold":0,"walls":0,"vp":1,"region":"Novgorodan Rus","ways":[[27,13],[36,14]],"box":{"x":4243,"y":5581,"w":187,"h":63},"adjacent":[27,36],"adjacent_by_trackway":[]},
-{"name":"Luga","type":"traderoute","stronghold":0,"walls":0,"vp":1,"region":"Novgorodan Rus","ways":[[33,18]],"box":{"x":2667,"y":3295,"w":148,"h":62},"adjacent":[33],"adjacent_by_trackway":[]},
-{"name":"Neva","type":"traderoute","stronghold":0,"walls":0,"vp":1,"region":"Novgorodan Rus","ways":[[25,24],[51,55],[45,57],[44,58]],"box":{"x":3924,"y":2934,"w":148,"h":62},"adjacent":[25,44,45,51],"adjacent_by_trackway":[44,45,51]},
-{"name":"Volkhov","type":"traderoute","stronghold":0,"walls":0,"vp":1,"region":"Novgorodan Rus","ways":[[25,22],[24,23]],"box":{"x":4591,"y":3783,"w":231,"h":63},"adjacent":[24,25],"adjacent_by_trackway":[]},
-{"name":"Izborsk","type":"fort","stronghold":1,"walls":3,"vp":1,"region":"Novgorodan Rus","ways":[[14,47],[22,49],[18,51],[26,52]],"box":{"x":2240,"y":5431,"w":241,"h":62},"adjacent":[14,18,22,26],"adjacent_by_trackway":[14,18,22,26]},
-{"name":"Kaibolovo","type":"fort","stronghold":1,"walls":3,"vp":1,"region":"Novgorodan Rus","ways":[[29,18],[42,19],[2,28],[34,53]],"box":{"x":2904,"y":3522,"w":285,"h":62},"adjacent":[2,29,34,42],"adjacent_by_trackway":[2,34]},
-{"name":"Koporye","type":"fort","stronghold":1,"walls":3,"vp":1,"region":"Novgorodan Rus","ways":[[33,53],[51,54]],"box":{"x":3133,"y":3160,"w":241,"h":62},"adjacent":[33,51],"adjacent_by_trackway":[33,51]},
-{"name":"Porkhov","type":"fort","stronghold":1,"walls":3,"vp":1,"region":"Novgorodan Rus","ways":[[47,16],[37,70],[48,71]],"box":{"x":3515,"y":5467,"w":241,"h":63},"adjacent":[37,47,48],"adjacent_by_trackway":[37,48]},
-{"name":"Velikiye Luki","type":"fort","stronghold":1,"walls":3,"vp":1,"region":"Novgorodan Rus","ways":[[28,14],[50,72]],"box":{"x":3706,"y":6347,"w":351,"h":61},"adjacent":[28,50],"adjacent_by_trackway":[50]},
-{"name":"Dubrovno","type":"town","stronghold":0,"walls":0,"vp":0,"region":"Novgorodan Rus","ways":[[47,15],[26,69],[35,70]],"box":{"x":3153,"y":5214,"w":161,"h":31},"adjacent":[26,35,47],"adjacent_by_trackway":[26,35]},
-{"name":"Gdov","type":"town","stronghold":0,"walls":0,"vp":0,"region":"Novgorodan Rus","ways":[[49,1,2],[2,2],[7,2],[46,65]],"box":{"x":2427,"y":4149,"w":88,"h":30},"adjacent":[2,7,46,49],"adjacent_by_trackway":[46]},
-{"name":"Ostrov","type":"town","stronghold":0,"walls":0,"vp":0,"region":"Novgorodan Rus","ways":[[26,10],[50,11],[18,50]],"box":{"x":2746,"y":5717,"w":115,"h":30},"adjacent":[18,26,50],"adjacent_by_trackway":[18]},
-{"name":"Sablia","type":"town","stronghold":0,"walls":0,"vp":0,"region":"Novgorodan Rus","ways":[[42,20],[24,63],[47,64]],"box":{"x":3788,"y":4541,"w":104,"h":31},"adjacent":[24,42,47],"adjacent_by_trackway":[24,47]},
-{"name":"Tesovo","type":"town","stronghold":0,"walls":0,"vp":0,"region":"Novgorodan Rus","ways":[[42,21],[43,61],[24,62]],"box":{"x":3936,"y":4102,"w":121,"h":32},"adjacent":[24,42,43],"adjacent_by_trackway":[24,43]},
-{"name":"Zheltsy","type":"town","stronghold":0,"walls":0,"vp":0,"region":"Novgorodan Rus","ways":[[33,19],[40,20],[41,21],[46,66]],"box":{"x":3501,"y":4176,"w":128,"h":30},"adjacent":[33,40,41,46],"adjacent_by_trackway":[46]},
-{"name":"Ingria","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Novgorodan Rus","ways":[[51,56],[44,60],[41,61]],"box":{"x":3820,"y":3639,"w":200,"h":100},"adjacent":[41,44,51],"adjacent_by_trackway":[41,44,51]},
-{"name":"Izhora","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Novgorodan Rus","ways":[[30,58],[25,59],[43,60]],"box":{"x":4074,"y":3323,"w":200,"h":100},"adjacent":[25,30,43],"adjacent_by_trackway":[25,30,43]},
-{"name":"Karelia","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Novgorodan Rus","ways":[[30,57]],"box":{"x":3833,"y":2408,"w":200,"h":100},"adjacent":[30],"adjacent_by_trackway":[30]},
-{"name":"Plyussa River","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Novgorodan Rus","ways":[[2,17],[38,65],[42,66],[52,67]],"box":{"x":2829,"y":4234,"w":200,"h":100},"adjacent":[2,38,42,52],"adjacent_by_trackway":[38,42,52]},
-{"name":"Shelon River","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Novgorodan Rus","ways":[[24,6],[27,6],[37,15],[35,16],[40,64]],"box":{"x":3654,"y":4864,"w":200,"h":100},"adjacent":[24,27,35,37,40],"adjacent_by_trackway":[40]},
-{"name":"Sorot River","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Novgorodan Rus","ways":[[50,12],[35,71]],"box":{"x":3299,"y":5781,"w":200,"h":100},"adjacent":[35,50],"adjacent_by_trackway":[35]},
-{"name":"Uzmen","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Novgorodan Rus","ways":[[38,1,2],[2,2],[7,2],[26,4],[52,5],[22,48]],"box":{"x":2112,"y":4692,"w":200,"h":100},"adjacent":[2,7,22,26,38,52],"adjacent_by_trackway":[22]},
-{"name":"Velikaya River","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Novgorodan Rus","ways":[[39,11],[48,12],[36,72]],"box":{"x":3029,"y":6090,"w":200,"h":100},"adjacent":[36,39,48],"adjacent_by_trackway":[36]},
-{"name":"Vod","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Novgorodan Rus","ways":[[34,54],[30,55],[43,56]],"box":{"x":3488,"y":3345,"w":200,"h":100},"adjacent":[30,34,43],"adjacent_by_trackway":[30,34,43]},
-{"name":"Zhelcha River","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Novgorodan Rus","ways":[[49,5],[46,67],[26,68]],"box":{"x":2782,"y":4586,"w":200,"h":100},"adjacent":[26,46,49],"adjacent_by_trackway":[26,46]},
+{"name":"Reval","type":"bishopric","stronghold":3,"walls":4,"vp":2,"region":"Danish Estonia","ways":[[5,25],[3,32]],"box":{"x":601,"y":3564,"w":206,"h":91},"adjacent":[3,5],"adjacent_by_trackway":[3,5],"adjacent_by_waterway":[]},
+{"name":"Wesenberg","type":"castle","stronghold":2,"walls":4,"vp":1,"region":"Danish Estonia","ways":[[5,26],[17,30],[6,31]],"box":{"x":1448,"y":3625,"w":304,"h":60},"adjacent":[5,6,17],"adjacent_by_trackway":[5,6,17],"adjacent_by_waterway":[]},
+{"name":"Narwia","type":"town","stronghold":0,"walls":0,"vp":0,"region":"Danish Estonia","ways":[[7,2],[38,2],[49,2],[46,17],[6,27],[33,28]],"box":{"x":2371,"y":3549,"w":123,"h":31},"adjacent":[6,7,33,38,46,49],"adjacent_by_trackway":[6,33],"adjacent_by_waterway":[7,38,46,49]},
+{"name":"Warbola","type":"town","stronghold":0,"walls":0,"vp":0,"region":"Danish Estonia","ways":[[0,32],[4,33],[8,35]],"box":{"x":292,"y":3797,"w":142,"h":31},"adjacent":[0,4,8],"adjacent_by_trackway":[0,4,8],"adjacent_by_waterway":[]},
+{"name":"Harrien","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Danish Estonia","ways":[[3,33],[17,34]],"box":{"x":567,"y":3983,"w":200,"h":100},"adjacent":[3,17],"adjacent_by_trackway":[3,17],"adjacent_by_waterway":[]},
+{"name":"Revala","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Danish Estonia","ways":[[0,25],[1,26]],"box":{"x":1030,"y":3410,"w":200,"h":100},"adjacent":[0,1],"adjacent_by_trackway":[0,1],"adjacent_by_waterway":[]},
+{"name":"Wierland","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Danish Estonia","ways":[[2,27],[23,29],[1,31]],"box":{"x":1999,"y":3680,"w":200,"h":100},"adjacent":[1,2,23],"adjacent_by_trackway":[1,2,23],"adjacent_by_waterway":[]},
+{"name":"Dorpat","type":"bishopric","stronghold":3,"walls":4,"vp":2,"region":"Crusader Livonia","ways":[[12,0,3],[22,0],[2,2],[38,2],[49,2],[11,3],[23,36]],"box":{"x":1625,"y":4589,"w":253,"h":91},"adjacent":[2,11,12,22,23,38,49],"adjacent_by_trackway":[12,22,23],"adjacent_by_waterway":[2,11,38,49]},
+{"name":"Leal","type":"bishopric","stronghold":3,"walls":4,"vp":2,"region":"Crusader Livonia","ways":[[3,35],[15,37]],"box":{"x":108,"y":4266,"w":205,"h":91},"adjacent":[3,15],"adjacent_by_trackway":[3,15],"adjacent_by_waterway":[]},
+{"name":"Riga","type":"bishopric","stronghold":3,"walls":4,"vp":2,"region":"Crusader Livonia","ways":[[13,8]],"box":{"x":273,"y":6231,"w":205,"h":91},"adjacent":[13],"adjacent_by_trackway":[],"adjacent_by_waterway":[13]},
+{"name":"Adsel","type":"castle","stronghold":2,"walls":4,"vp":1,"region":"Crusader Livonia","ways":[[13,9],[18,44],[21,44],[14,45]],"box":{"x":1504,"y":5612,"w":185,"h":60},"adjacent":[13,14,18,21],"adjacent_by_trackway":[14,18,21],"adjacent_by_waterway":[13]},
+{"name":"Fellin","type":"castle","stronghold":2,"walls":4,"vp":1,"region":"Crusader Livonia","ways":[[7,3],[12,3],[15,7],[17,7],[20,38]],"box":{"x":1013,"y":4583,"w":184,"h":61},"adjacent":[7,12,15,17,20],"adjacent_by_trackway":[20],"adjacent_by_waterway":[7,12,15,17]},
+{"name":"Odenpäh","type":"castle","stronghold":2,"walls":4,"vp":1,"region":"Crusader Livonia","ways":[[7,0,3],[22,0],[11,3],[14,46]],"box":{"x":1378,"y":5103,"w":250,"h":61},"adjacent":[7,11,14,22],"adjacent_by_trackway":[7,14,22],"adjacent_by_waterway":[11]},
+{"name":"Wenden","type":"castle","stronghold":2,"walls":4,"vp":1,"region":"Crusader Livonia","ways":[[9,8],[10,9],[19,40],[21,41]],"box":{"x":909,"y":5759,"w":232,"h":60},"adjacent":[9,10,19,21],"adjacent_by_trackway":[19,21],"adjacent_by_waterway":[9,10]},
+{"name":"Kirrumpäh","type":"town","stronghold":0,"walls":0,"vp":0,"region":"Crusader Livonia","ways":[[10,45],[12,46],[32,47]],"box":{"x":1877,"y":5389,"w":175,"h":30},"adjacent":[10,12,32],"adjacent_by_trackway":[10,12,32],"adjacent_by_waterway":[]},
+{"name":"Pernau","type":"town","stronghold":0,"walls":0,"vp":0,"region":"Crusader Livonia","ways":[[11,7],[17,7],[8,37]],"box":{"x":517,"y":4580,"w":118,"h":30},"adjacent":[8,11,17],"adjacent_by_trackway":[8],"adjacent_by_waterway":[11,17]},
+{"name":"Rositten","type":"town","stronghold":0,"walls":0,"vp":0,"region":"Crusader Livonia","ways":[[21,42],[18,43]],"box":{"x":2046,"y":6307,"w":146,"h":30},"adjacent":[18,21],"adjacent_by_trackway":[18,21],"adjacent_by_waterway":[]},
+{"name":"Jerwen","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Crusader Livonia","ways":[[11,7],[15,7],[1,30],[4,34]],"box":{"x":1064,"y":3946,"w":200,"h":100},"adjacent":[1,4,11,15],"adjacent_by_trackway":[1,4],"adjacent_by_waterway":[11,15]},
+{"name":"Lettgallia","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Crusader Livonia","ways":[[16,43],[10,44],[21,44],[39,50],[32,51]],"box":{"x":2048,"y":5777,"w":200,"h":100},"adjacent":[10,16,21,32,39],"adjacent_by_trackway":[10,16,21,32,39],"adjacent_by_waterway":[]},
+{"name":"Metsepole","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Crusader Livonia","ways":[[20,39],[13,40]],"box":{"x":509,"y":5226,"w":200,"h":100},"adjacent":[13,20],"adjacent_by_trackway":[13,20],"adjacent_by_waterway":[]},
+{"name":"Sackala","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Crusader Livonia","ways":[[11,38],[19,39]],"box":{"x":617,"y":4769,"w":200,"h":100},"adjacent":[11,19],"adjacent_by_trackway":[11,19],"adjacent_by_waterway":[]},
+{"name":"Tolowa","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Crusader Livonia","ways":[[13,41],[16,42],[10,44],[18,44]],"box":{"x":1541,"y":5933,"w":200,"h":100},"adjacent":[10,13,16,18],"adjacent_by_trackway":[10,13,16,18],"adjacent_by_waterway":[]},
+{"name":"Ugaunia","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Crusader Livonia","ways":[[7,0],[12,0],[49,48],[32,49]],"box":{"x":1957,"y":4940,"w":200,"h":100},"adjacent":[7,12,32,49],"adjacent_by_trackway":[7,12,32,49],"adjacent_by_waterway":[]},
+{"name":"Waiga","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Crusader Livonia","ways":[[6,29],[7,36]],"box":{"x":1535,"y":4113,"w":200,"h":100},"adjacent":[6,7],"adjacent_by_trackway":[6,7],"adjacent_by_waterway":[]},
+{"name":"Novgorod","type":"novgorod","stronghold":3,"walls":3,"vp":3,"region":"Novgorodan Rus","ways":[[27,6],[47,6],[31,23],[41,62],[40,63]],"box":{"x":4318,"y":4315,"w":333,"h":112},"adjacent":[27,31,40,41,47],"adjacent_by_trackway":[40,41],"adjacent_by_waterway":[27,31,47]},
+{"name":"Ladoga","type":"city","stronghold":3,"walls":3,"vp":2,"region":"Novgorodan Rus","ways":[[31,22],[30,24],[44,59]],"box":{"x":4619,"y":2817,"w":238,"h":90},"adjacent":[30,31,44],"adjacent_by_trackway":[44],"adjacent_by_waterway":[30,31]},
+{"name":"Pskov","type":"city","stronghold":3,"walls":3,"vp":2,"region":"Novgorodan Rus","ways":[[49,4],[39,10],[32,52],[52,68],[37,69]],"box":{"x":2680,"y":5263,"w":205,"h":91},"adjacent":[32,37,39,49,52],"adjacent_by_trackway":[32,37,52],"adjacent_by_waterway":[39,49]},
+{"name":"Rusa","type":"city","stronghold":3,"walls":3,"vp":2,"region":"Novgorodan Rus","ways":[[24,6],[47,6],[28,13]],"box":{"x":4329,"y":5166,"w":205,"h":92},"adjacent":[24,28,47],"adjacent_by_trackway":[],"adjacent_by_waterway":[24,28,47]},
+{"name":"Lovat","type":"traderoute","stronghold":0,"walls":0,"vp":1,"region":"Novgorodan Rus","ways":[[27,13],[36,14]],"box":{"x":4243,"y":5581,"w":187,"h":63},"adjacent":[27,36],"adjacent_by_trackway":[],"adjacent_by_waterway":[27,36]},
+{"name":"Luga","type":"traderoute","stronghold":0,"walls":0,"vp":1,"region":"Novgorodan Rus","ways":[[33,18]],"box":{"x":2667,"y":3295,"w":148,"h":62},"adjacent":[33],"adjacent_by_trackway":[],"adjacent_by_waterway":[33]},
+{"name":"Neva","type":"traderoute","stronghold":0,"walls":0,"vp":1,"region":"Novgorodan Rus","ways":[[25,24],[51,55],[45,57],[44,58]],"box":{"x":3924,"y":2934,"w":148,"h":62},"adjacent":[25,44,45,51],"adjacent_by_trackway":[44,45,51],"adjacent_by_waterway":[25]},
+{"name":"Volkhov","type":"traderoute","stronghold":0,"walls":0,"vp":1,"region":"Novgorodan Rus","ways":[[25,22],[24,23]],"box":{"x":4591,"y":3783,"w":231,"h":63},"adjacent":[24,25],"adjacent_by_trackway":[],"adjacent_by_waterway":[24,25]},
+{"name":"Izborsk","type":"fort","stronghold":1,"walls":3,"vp":1,"region":"Novgorodan Rus","ways":[[14,47],[22,49],[18,51],[26,52]],"box":{"x":2240,"y":5431,"w":241,"h":62},"adjacent":[14,18,22,26],"adjacent_by_trackway":[14,18,22,26],"adjacent_by_waterway":[]},
+{"name":"Kaibolovo","type":"fort","stronghold":1,"walls":3,"vp":1,"region":"Novgorodan Rus","ways":[[29,18],[42,19],[2,28],[34,53]],"box":{"x":2904,"y":3522,"w":285,"h":62},"adjacent":[2,29,34,42],"adjacent_by_trackway":[2,34],"adjacent_by_waterway":[29,42]},
+{"name":"Koporye","type":"fort","stronghold":1,"walls":3,"vp":1,"region":"Novgorodan Rus","ways":[[33,53],[51,54]],"box":{"x":3133,"y":3160,"w":241,"h":62},"adjacent":[33,51],"adjacent_by_trackway":[33,51],"adjacent_by_waterway":[]},
+{"name":"Porkhov","type":"fort","stronghold":1,"walls":3,"vp":1,"region":"Novgorodan Rus","ways":[[47,16],[37,70],[48,71]],"box":{"x":3515,"y":5467,"w":241,"h":63},"adjacent":[37,47,48],"adjacent_by_trackway":[37,48],"adjacent_by_waterway":[47]},
+{"name":"Velikiye Luki","type":"fort","stronghold":1,"walls":3,"vp":1,"region":"Novgorodan Rus","ways":[[28,14],[50,72]],"box":{"x":3706,"y":6347,"w":351,"h":61},"adjacent":[28,50],"adjacent_by_trackway":[50],"adjacent_by_waterway":[28]},
+{"name":"Dubrovno","type":"town","stronghold":0,"walls":0,"vp":0,"region":"Novgorodan Rus","ways":[[47,15],[26,69],[35,70]],"box":{"x":3153,"y":5214,"w":161,"h":31},"adjacent":[26,35,47],"adjacent_by_trackway":[26,35],"adjacent_by_waterway":[47]},
+{"name":"Gdov","type":"town","stronghold":0,"walls":0,"vp":0,"region":"Novgorodan Rus","ways":[[49,1,2],[2,2],[7,2],[46,65]],"box":{"x":2427,"y":4149,"w":88,"h":30},"adjacent":[2,7,46,49],"adjacent_by_trackway":[46],"adjacent_by_waterway":[2,7,49]},
+{"name":"Ostrov","type":"town","stronghold":0,"walls":0,"vp":0,"region":"Novgorodan Rus","ways":[[26,10],[50,11],[18,50]],"box":{"x":2746,"y":5717,"w":115,"h":30},"adjacent":[18,26,50],"adjacent_by_trackway":[18],"adjacent_by_waterway":[26,50]},
+{"name":"Sablia","type":"town","stronghold":0,"walls":0,"vp":0,"region":"Novgorodan Rus","ways":[[42,20],[24,63],[47,64]],"box":{"x":3788,"y":4541,"w":104,"h":31},"adjacent":[24,42,47],"adjacent_by_trackway":[24,47],"adjacent_by_waterway":[42]},
+{"name":"Tesovo","type":"town","stronghold":0,"walls":0,"vp":0,"region":"Novgorodan Rus","ways":[[42,21],[43,61],[24,62]],"box":{"x":3936,"y":4102,"w":121,"h":32},"adjacent":[24,42,43],"adjacent_by_trackway":[24,43],"adjacent_by_waterway":[42]},
+{"name":"Zheltsy","type":"town","stronghold":0,"walls":0,"vp":0,"region":"Novgorodan Rus","ways":[[33,19],[40,20],[41,21],[46,66]],"box":{"x":3501,"y":4176,"w":128,"h":30},"adjacent":[33,40,41,46],"adjacent_by_trackway":[46],"adjacent_by_waterway":[33,40,41]},
+{"name":"Ingria","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Novgorodan Rus","ways":[[51,56],[44,60],[41,61]],"box":{"x":3820,"y":3639,"w":200,"h":100},"adjacent":[41,44,51],"adjacent_by_trackway":[41,44,51],"adjacent_by_waterway":[]},
+{"name":"Izhora","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Novgorodan Rus","ways":[[30,58],[25,59],[43,60]],"box":{"x":4074,"y":3323,"w":200,"h":100},"adjacent":[25,30,43],"adjacent_by_trackway":[25,30,43],"adjacent_by_waterway":[]},
+{"name":"Karelia","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Novgorodan Rus","ways":[[30,57]],"box":{"x":3833,"y":2408,"w":200,"h":100},"adjacent":[30],"adjacent_by_trackway":[30],"adjacent_by_waterway":[]},
+{"name":"Plyussa River","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Novgorodan Rus","ways":[[2,17],[38,65],[42,66],[52,67]],"box":{"x":2829,"y":4234,"w":200,"h":100},"adjacent":[2,38,42,52],"adjacent_by_trackway":[38,42,52],"adjacent_by_waterway":[2]},
+{"name":"Shelon River","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Novgorodan Rus","ways":[[24,6],[27,6],[37,15],[35,16],[40,64]],"box":{"x":3654,"y":4864,"w":200,"h":100},"adjacent":[24,27,35,37,40],"adjacent_by_trackway":[40],"adjacent_by_waterway":[24,27,35,37]},
+{"name":"Sorot River","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Novgorodan Rus","ways":[[50,12],[35,71]],"box":{"x":3299,"y":5781,"w":200,"h":100},"adjacent":[35,50],"adjacent_by_trackway":[35],"adjacent_by_waterway":[50]},
+{"name":"Uzmen","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Novgorodan Rus","ways":[[38,1,2],[2,2],[7,2],[26,4],[52,5],[22,48]],"box":{"x":2112,"y":4692,"w":200,"h":100},"adjacent":[2,7,22,26,38,52],"adjacent_by_trackway":[22],"adjacent_by_waterway":[2,7,26,38,52]},
+{"name":"Velikaya River","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Novgorodan Rus","ways":[[39,11],[48,12],[36,72]],"box":{"x":3029,"y":6090,"w":200,"h":100},"adjacent":[36,39,48],"adjacent_by_trackway":[36],"adjacent_by_waterway":[39,48]},
+{"name":"Vod","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Novgorodan Rus","ways":[[34,54],[30,55],[43,56]],"box":{"x":3488,"y":3345,"w":200,"h":100},"adjacent":[30,34,43],"adjacent_by_trackway":[30,34,43],"adjacent_by_waterway":[]},
+{"name":"Zhelcha River","type":"region","stronghold":0,"walls":0,"vp":0,"region":"Novgorodan Rus","ways":[[49,5],[46,67],[26,68]],"box":{"x":2782,"y":4586,"w":200,"h":100},"adjacent":[26,46,49],"adjacent_by_trackway":[26,46],"adjacent_by_waterway":[49]},
],
ways:[
{"type":"trackway","locales":[7,12,22],"name":"Crossroads"},
diff --git a/rules.js b/rules.js
index e283e94..85f4745 100644
--- a/rules.js
+++ b/rules.js
@@ -1,7 +1,8 @@
"use strict"
// TODO: delay pay step if there is no feed or disband to be done
-// TODO: supply (+ lodya)
+
+// TODO: Supply (+ lodya)
// CAPABILITIES
// TODO: Ransom (T)
@@ -403,6 +404,18 @@ function enemy_player() {
return null
}
+function get_global_assets(type) {
+ return pack4_get(game.assets, type)
+}
+
+function set_global_assets(type, n) {
+ game.assets = pack4_set(game.assets, type, n)
+}
+
+function add_global_assets(type, n) {
+ game.assets = pack4_set(game.assets, type, pack4_get(game.assets) + n)
+}
+
function get_lord_locale(lord) {
return game.lords.locale[lord]
}
@@ -552,6 +565,116 @@ function count_lord_horses(lord) {
)
}
+function count_lord_boats(lord) {
+ let boats = get_lord_assets(lord, BOAT)
+
+ if (lord_has_capability(lord, AOW_RUSSIAN_LODYA)) {
+ // TODO: one option or the other (only matters for supply)
+ let ships = get_lord_assets(lord, SHIP)
+ if (ships > 2)
+ ships = 2
+ if (boats * 2 > boats + ships)
+ boats = boats * 2
+ else
+ boats = boats + ships
+ }
+
+ return boats
+}
+
+function count_shared_boats() {
+ let here = get_lord_locale(game.command)
+ let n = 0
+ for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord)
+ if (get_lord_locale(lord) === here)
+ n += count_lord_boats(lord)
+ return n
+}
+
+function count_lord_ships(lord) {
+ let ships = get_lord_assets(lord, SHIP)
+
+ if (lord_has_capability(lord, AOW_TEUTONIC_COGS)) {
+ ships *= 2
+ }
+
+ if (lord_has_capability(lord, AOW_RUSSIAN_LODYA)) {
+ // TODO: one option or the other (only matters for supply)
+ let boats = get_lord_assets(lord, BOAT)
+ if (boats > 2)
+ boats = 2
+ ships += boats
+ }
+
+ return ships
+}
+
+function count_shared_ships() {
+ let here = get_lord_locale(game.command)
+ let n = 0
+ for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord)
+ if (get_lord_locale(lord) === here)
+ n += count_lord_ships(lord)
+ return n
+}
+
+function count_shared_cogs_not_in_group() {
+ let n = 0
+ if (game.active === TEUTONS) {
+ for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord)
+ if (lord_has_capability(lord, AOW_TEUTONIC_COGS))
+ if (!set_has(game.group, lord)) // not already counted for
+ n += get_lord_assets(lord, SHIP) * 2
+ }
+ return n
+}
+
+function count_shared_cogs_not_in_locale(here) {
+ let n = 0
+ if (game.active === TEUTONS) {
+ for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord)
+ if (lord_has_capability(lord, AOW_TEUTONIC_COGS))
+ if (get_lord_locale(lord) !== here)
+ n += get_lord_assets(lord, SHIP) * 2
+ }
+ return n
+}
+
+function count_group_ships() {
+ let n = 0
+ for (let lord of game.group)
+ n += count_lord_ships(lord)
+ return n
+}
+
+function count_group_assets(asset) {
+ let n = 0
+ for (let lord of game.group)
+ n += get_lord_assets(lord, asset)
+ return n
+}
+
+function count_group_forces(type) {
+ let n = 0
+ for (let lord of game.group)
+ n += count_lord_forces(lord, type)
+ return n
+}
+
+function count_group_horses() {
+ let n = 0
+ for (let lord of game.group)
+ n += count_lord_horses(lord)
+ return n
+}
+
+function count_group_transport(type) {
+ let n = 0
+ for (let lord of game.group)
+ n += count_lord_transport(lord, type)
+ return n
+}
+
function max_plan_length() {
switch (current_season()) {
case SUMMER:
@@ -946,8 +1069,8 @@ function can_add_transport(who, what) {
return get_lord_assets(who, what) < 8
}
-function count_lord_transport(lord, way) {
- let type = data.ways[way].type
+
+function count_lord_transport(lord, type) {
let season = current_season()
let n = 0
switch (type) {
@@ -1036,11 +1159,6 @@ function is_located_with_legate(lord) {
return get_lord_locale(lord) === game.call_to_arms.legate
}
-function for_each_group_lord(fn) {
- for (let lord of game.group)
- fn(lord)
-}
-
function group_has_capability(c) {
for (let lord of game.group)
if (lord_has_capability(lord, c))
@@ -1048,41 +1166,6 @@ function group_has_capability(c) {
return false
}
-function count_group_ships() {
- let n = 0
- for (let lord of game.group)
- n += count_lord_ships(lord)
- return n
-}
-
-function count_group_assets(asset) {
- let n = 0
- for (let lord of game.group)
- n += get_lord_assets(lord, asset)
- return n
-}
-
-function count_group_forces(type) {
- let n = 0
- for (let lord of game.group)
- n += count_lord_forces(lord, type)
- return n
-}
-
-function count_group_horses() {
- let n = 0
- for (let lord of game.group)
- n += count_lord_horses(lord)
- return n
-}
-
-function count_group_transport(way) {
- let n = 0
- for (let lord of game.group)
- n += count_lord_transport(lord, way)
- return n
-}
-
// === SETUP ===
function setup_lord_on_calendar(lord, turn) {
@@ -1090,6 +1173,7 @@ function setup_lord_on_calendar(lord, turn) {
}
function muster_lord_forces(lord) {
+ let info = data.lords[lord]
set_lord_forces(lord, KNIGHTS, info.forces.knights | 0)
set_lord_forces(lord, SERGEANTS, info.forces.sergeants | 0)
set_lord_forces(lord, LIGHT_HORSE, info.forces.light_horse | 0)
@@ -1100,6 +1184,7 @@ function muster_lord_forces(lord) {
}
function muster_vassal_forces(lord, vassal) {
+ let info = data.vassals[vassal]
add_lord_forces(lord, KNIGHTS, info.forces.knights | 0)
add_lord_forces(lord, SERGEANTS, info.forces.sergeants | 0)
add_lord_forces(lord, LIGHT_HORSE, info.forces.light_horse | 0)
@@ -1138,7 +1223,6 @@ function muster_lord(lord, locale, service) {
}
function muster_vassal(lord, vassal) {
- let info = data.vassals[vassal]
game.lords.vassals[vassal] = VASSAL_MUSTERED
muster_vassal_forces(lord, vassal)
}
@@ -1206,7 +1290,7 @@ exports.setup = function (seed, scenario, options) {
approach: 0,
avoid: 0,
- spoils: 0,
+ assets: 0,
}
update_aliases()
@@ -2341,11 +2425,13 @@ states.actions = {
game.call_to_arms.legate_selected = 0
++game.extra
},
+
pass() {
push_undo()
log("Passed.")
spend_all_actions() // TODO: maybe only one action?
},
+
end_actions() {
clear_undo()
end_actions()
@@ -2353,25 +2439,24 @@ states.actions = {
forage: goto_forage,
ravage: goto_ravage,
- sail: goto_sail,
+ supply: goto_supply,
tax: goto_tax,
-
siege: goto_siege,
storm: goto_storm,
sally: goto_sally,
+ sail: goto_sail,
- lord(lord) {
- set_toggle(game.group, lord)
- if (is_upper_lord(lord))
- set_toggle(game.group, get_lower_lord(lord))
- },
+ locale: goto_march,
legate() {
toggle_legate_selected()
},
- // March!
- locale: goto_march,
+ lord(lord) {
+ set_toggle(game.group, lord)
+ if (is_upper_lord(lord))
+ set_toggle(game.group, get_lower_lord(lord))
+ },
}
// === ACTION: MARCH ===
@@ -2443,7 +2528,7 @@ states.march_way = {
function march_with_group_1() {
let way = game.approach
- let transport = count_group_transport(way)
+ let transport = count_group_transport(data.ways[way].type)
let prov = count_group_assets(PROV)
let loot = count_group_assets(LOOT)
@@ -2460,7 +2545,7 @@ states.march_laden = {
prompt() {
let to = game.where
let way = game.approach
- let transport = count_group_transport(way)
+ let transport = count_group_transport(data.ways[way].type)
let prov = count_group_assets(PROV)
let loot = count_group_assets(LOOT)
@@ -2486,7 +2571,7 @@ states.march_laden = {
}
if (loot > 0 || prov > transport) {
- for_each_group_lord(lord => {
+ for (let lord of game.group) {
if (loot > 0) {
if (get_lord_assets(lord, LOOT) > 0)
gen_action_loot(lord)
@@ -2498,7 +2583,7 @@ states.march_laden = {
if (get_lord_assets(lord, PROV) > 0)
gen_action_prov(lord)
}
- })
+ }
}
},
prov: drop_prov,
@@ -2512,7 +2597,7 @@ function march_with_group_2() {
let from = get_lord_locale(game.command)
let way = game.approach
let to = game.where
- let transport = count_group_transport(way)
+ let transport = count_group_transport(data.ways[way].type)
let prov = count_group_assets(PROV)
let loot = count_group_assets(LOOT)
let laden = loot > 0 || prov > transport
@@ -2529,10 +2614,10 @@ function march_with_group_2() {
else
log(`Marched to %${to}.`)
- for_each_group_lord(lord => {
+ for (let lord of game.group) {
set_lord_locale(lord, to)
set_lord_moved(lord, 1)
- })
+ }
if (game.call_to_arms.legate_selected)
game.call_to_arms.legate = to
@@ -2602,13 +2687,13 @@ function stronghold_capacity(loc) {
function spoil_prov(lord) {
log("Discarded Provender.")
add_lord_assets(lord, PROV, -1)
- game.spoils = pack4_set(game.spoils, PROV, pack4_get(game.spoils) + 1)
+ add_global_assets(PROV, 1)
}
function spoil_loot(lord) {
log("Discarded Loot.")
add_lord_assets(lord, LOOT, -1)
- game.spoils = pack4_set(game.spoils, LOOT, pack4_get(game.spoils) + 1)
+ add_global_assets(LOOT, 1)
}
function can_avoid_battle(to, way) {
@@ -2634,7 +2719,7 @@ function goto_avoid_battle() {
game.stack = game.group
game.who = NOBODY
game.state = "avoid_battle"
- game.spoils = 0
+ game.assets = 0
resume_avoid_battle()
}
@@ -2711,7 +2796,7 @@ states.avoid_battle_way = {
function avoid_battle_1() {
let way = game.avoid
- let transport = count_group_transport(way)
+ let transport = count_group_transport(data.ways[way].type)
let prov = count_group_assets(PROV)
let loot = count_group_assets(LOOT)
if (prov > transport || loot > 0)
@@ -2724,7 +2809,7 @@ states.avoid_battle_laden = {
prompt() {
let to = game.where
let way = game.avoid
- let transport = count_group_transport(way)
+ let transport = count_group_transport(data.ways[way].type)
let prov = count_group_assets(PROV)
let loot = count_group_assets(LOOT)
@@ -2733,16 +2818,16 @@ states.avoid_battle_laden = {
if (loot > 0) {
view.prompt += " Discard Loot."
- for_each_group_lord(lord => {
+ for (let lord of game.group) {
if (get_lord_assets(lord, LOOT) > 0)
gen_action_loot(lord)
- })
+ }
} else if (prov > transport) {
view.prompt += " Discard Provender."
- for_each_group_lord(lord => {
+ for (let lord of game.group) {
if (get_lord_assets(lord, PROV) > 0)
gen_action_prov(lord)
- })
+ }
} else {
gen_action_locale(to)
}
@@ -2768,10 +2853,10 @@ function avoid_battle_2() {
else
log(`Avoided Battle to %${to}.`)
- for_each_group_lord(lord => {
+ for (let lord of game.group) {
set_lord_locale(lord, to)
set_lord_moved(lord, 1)
- })
+ }
game.where = get_lord_locale(game.command)
game.avoid = 0
@@ -2862,7 +2947,7 @@ function end_withdraw() {
// === ACTION: MARCH - DIVIDE SPOILS AFTER AVOID BATTLE ===
function goto_divide_spoils_after_avoid_battle() {
- if (game.spoils > 0)
+ if (game.assets > 0)
game.state = "divide_spoils_after_avoid_battle"
else
march_with_group_3()
@@ -2873,7 +2958,7 @@ states.divide_spoils_after_avoid_battle = {
view.actions.end_spoils = 1
},
end_spoils() {
- game.spoils = 0
+ game.assets = 0
march_with_group_3()
},
}
@@ -3008,11 +3093,109 @@ function goto_sally() {
// === ACTION: SUPPLY ===
+function can_supply_from_sea() {
+ let season = current_season()
+ if (season === SUMMER || season === RASPUTITSA) {
+ let here = get_lord_locale(game.command)
+ let ships = count_shared_ships() + count_shared_cogs_not_in_locale(here)
+ return ships > 0
+ }
+}
+
+function list_supply_sources() {
+ let sources = []
+
+ for_each_seat(game.command, seat => {
+ set_add(sources, seat)
+ })
+
+ if (can_supply_from_sea()) {
+ if (game.active === TEUTONS)
+ for (let port of data.seaports)
+ set_add(sources, port)
+ if (game.active === RUSSIANS)
+ set_add(sources, LOC_NOVGOROD)
+ }
+
+ return sources
+}
+
+function search_supply_rec(result, seen, sources, here, boats, carts, sleds) {
+ console.log("search", "".padStart(16-(boats+carts+sleds), "-"), here)
+
+ set_add(seen, here)
+
+ if (set_has(sources, here))
+ set_add(result, here)
+
+ if (boats > 0)
+ for (let next of data.locales[here].adjacent_by_waterway)
+ search_supply_rec(result, seen, sources, next, boats - 1, carts, sleds)
+ if (carts > 0)
+ for (let next of data.locales[here].adjacent_by_trackway)
+ search_supply_rec(result, seen, sources, next, boats, carts - 1, sleds)
+ if (sleds > 0)
+ for (let next of data.locales[here].adjacent)
+ search_supply_rec(result, seen, sources, next, boats, carts, sleds - 1)
+
+ set_delete(seen, here)
+}
+
+function search_supply() {
+ let sources = list_supply_sources()
+ let start = get_lord_locale(game.command)
+
+ let result = []
+
+ let boats = get_global_assets(BOAT)
+ let carts = get_global_assets(CART)
+ let sleds = get_global_assets(SLED)
+
+ console.log("SUPPLY", sources, boats, carts, sleds)
+
+ search_supply_rec(result, [], sources, start, boats, carts, sleds)
+
+ console.log(" => ", result)
+}
+
function can_action_supply(avail) {
if (avail < 1)
return false
+ return true
+}
- return false
+function goto_supply() {
+ push_undo()
+ game.state = "supply"
+
+ // TODO: Lodya - select boat OR ship (we count both here...)
+
+ let season = current_season()
+ let here = get_lord_locale(game.command)
+ let boats = 0, carts = 0, sleds = 0, ships = 0
+ if (season === SUMMER) {
+ carts = get_shared_assets(here, CART)
+ }
+ if (season === SUMMER || season === RASPUTITSA) {
+ boats = count_shared_boats()
+ ships = count_shared_ships() + count_shared_cogs_not_in_locale(here)
+ }
+ if (season === EARLY_WINTER || season === LATE_WINTER) {
+ sleds = get_shared_assets(here, SLED)
+ }
+
+ set_global_assets(BOAT, boats)
+ set_global_assets(CART, carts)
+ set_global_assets(SLED, sleds)
+ set_global_assets(SHIP, ships)
+}
+
+states.supply = {
+ prompt() {
+ view.prompt = "Supply: Select supply sources."
+
+ search_supply()
+ },
}
// === ACTION: FORAGE ===
@@ -3205,54 +3388,8 @@ function drop_loot(lord) {
add_lord_assets(lord, LOOT, -1)
}
-function count_lord_ships(lord) {
- let ships = get_lord_assets(lord, SHIP)
-
- if (lord_has_capability(lord, AOW_TEUTONIC_COGS)) {
- ships *= 2
- }
-
- if (lord_has_capability(lord, AOW_RUSSIAN_LODYA)) {
- // TODO: one option or the other (only matters for supply)
- let boats = get_lord_assets(lord, BOAT)
- if (boats > 2)
- boats = 2
- ships += boats
- }
-
- return ships
-}
-
-function count_shared_cogs() {
- let n = 0
- if (game.active === TEUTONS) {
- for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord)
- if (lord_has_capability(lord, AOW_TEUTONIC_COGS))
- if (!set_has(game.group, lord)) // not already counted for
- n += get_lord_assets(lord, SHIP) * 2
- }
- return n
-}
-
-function count_lord_boats(lord) {
- let boats = get_lord_assets(lord, BOAT)
-
- if (lord_has_capability(lord, AOW_RUSSIAN_LODYA)) {
- // TODO: one option or the other (only matters for supply)
- let ships = get_lord_assets(lord, SHIP)
- if (ships > 2)
- ships = 2
- if (boats * 2 > boats + ships)
- boats = boats * 2
- else
- boats = boats + ships
- }
-
- return boats
-}
-
function has_enough_available_ships_for_horses() {
- let ships = count_group_ships() + count_shared_cogs()
+ let ships = count_group_ships() + count_shared_cogs_not_in_group()
let horses = count_group_horses()
let needed_ships = horses
@@ -3295,7 +3432,7 @@ states.sail = {
view.group = game.group
let here = get_lord_locale(game.command)
- let ships = count_group_ships() + count_shared_cogs()
+ let ships = count_group_ships() + count_shared_cogs_not_in_group()
let horses = count_group_horses()
let prov = count_group_assets(PROV)
let loot = count_group_assets(LOOT)
@@ -3310,14 +3447,14 @@ states.sail = {
view.prompt = `Sailing with ${ships} ships and ${horses} horses. Discard loot or provender.`
// TODO: how strict is greed?
if (loot > 0 || prov > 0) {
- for_each_group_lord(lord => {
+ for (let lord of game.group) {
if (loot > 0)
if (get_lord_assets(lord, LOOT) > 0)
gen_action_loot(lord)
if (prov > 0)
if (get_lord_assets(lord, PROV) > 0)
gen_action_prov(lord)
- })
+ }
}
} else {
view.prompt = `Sail: Choose a destination Seaport.`
@@ -3337,10 +3474,10 @@ states.sail = {
let from = get_lord_locale(game.command)
- for_each_group_lord(lord => {
+ for (let lord of game.group) {
set_lord_locale(lord, to)
set_lord_moved(lord, 1)
- })
+ }
if (game.call_to_arms.legate_selected)
game.call_to_arms.legate = to
diff --git a/tools/gendata.js b/tools/gendata.js
index ba32d49..e922246 100644
--- a/tools/gendata.js
+++ b/tools/gendata.js
@@ -306,15 +306,20 @@ function dumplist(name, list) {
locales.forEach(loc => {
loc.adjacent = []
loc.adjacent_by_trackway = []
+ loc.adjacent_by_waterway = []
for (let [to, way] of loc.ways) {
if (!loc.adjacent.includes(to))
loc.adjacent.push(to)
if (ways[way].type === "trackway")
if (!loc.adjacent_by_trackway.includes(to))
loc.adjacent_by_trackway.push(to)
+ if (ways[way].type === "waterway")
+ if (!loc.adjacent_by_waterway.includes(to))
+ loc.adjacent_by_waterway.push(to)
}
loc.adjacent.sort(cmpnum)
loc.adjacent_by_trackway.sort(cmpnum)
+ loc.adjacent_by_waterway.sort(cmpnum)
})
function seats(list) {