From 41064aa4d7b938e1887cdc571bb47fa82090a6b4 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Tue, 28 Feb 2023 00:39:19 +0100 Subject: Rally, March. --- data.js | 2 +- images/back-forth.svg | 1 + images/shaking-hands.svg | 1 + play.css | 30 +- play.html | 10 + play.js | 11 + rules.js | 790 ++++++++++++++++++++++++++++++++++++++++------- tools/gendata.js | 33 +- 8 files changed, 739 insertions(+), 139 deletions(-) create mode 100644 images/back-forth.svg create mode 100644 images/shaking-hands.svg diff --git a/data.js b/data.js index cf3eef4..0feac9c 100644 --- a/data.js +++ b/data.js @@ -1,2 +1,2 @@ -const data = {"first_pop":1,"first_city":0,"last_city":10,"first_dept":11,"last_pop":22,"last_dept":26,"first_foreign":27,"last_foreign":31,"first_loc":32,"last_loc":49,"coastal_spaces":[11,12,13,17],"card_name":[null,"1st Division","Ospina & Mora","Tapias","Caño Limón - Coveñas","Occidental & Ecopetrol","Oil Spill","7th Special Forces","Fuerza Aérea Colombiana","High Mountain Battalions","Blackhawks","National Defense & Security Council","Plan Colombia","Plan Meteoro","Tres Esquinas","War Tax","Coffee Prices","Madrid Donors","NSPD-18","General Offensive","Mono Jojoy","Raúl Reyes","Alfonso Cano","DoD Contractors","Operación Jaque","Ejército de Liberación Nacional","Gramaje","Misil Antiaéreo","Hugo Chávez","Kill Zone","Peace Commission","Betancourt","Secuestrados","Sucumbíos","Airdropped AKs","Crop Substitution","Zona de Convivencia","Former Military","National Coordination Center","Soldados Campesinos","Demobilization","Mancuso","Senado & Cámara","Calima Front","Colombia Nueva","Los Derechos Humanos","Limpieza","Pinto & del Rosario","Unión Sindical Obrera","Bloques","Carabineros","Pipeline Repairs","Castaño","Criminal Air Force","Deserters & Defectors","DEA Agents","Drogas La Rebaja","Op Millennium","General Serrano","Salcedo","The Chess Player","Air Bridge","Amazonía","Narco-War","Cocaine Labs","Poppies","Tingo María","Mexican Traffickers","Narco-Subs","Riverines & Fast Boats","Ayahuasca Tourism","Darién","Sicarios","Propaganda!","Propaganda!","Propaganda!","Propaganda!"],"card_order":[null,[0,1,2,3],[0,1,2,3],[0,1,2,3],[0,1,3,2],[0,1,3,2],[0,1,3,2],[0,2,1,3],[0,2,1,3],[0,2,1,3],[0,2,3,1],[0,2,3,1],[0,2,3,1],[0,3,1,2],[0,3,1,2],[0,3,1,2],[0,3,2,1],[0,3,2,1],[0,3,2,1],[1,0,2,3],[1,0,2,3],[1,0,2,3],[1,0,3,2],[1,0,3,2],[1,0,3,2],[1,2,0,3],[1,2,0,3],[1,2,0,3],[1,2,3,0],[1,2,3,0],[1,2,3,0],[1,3,0,2],[1,3,0,2],[1,3,0,2],[1,3,2,0],[1,3,2,0],[1,3,2,0],[2,0,1,3],[2,0,1,3],[2,0,1,3],[2,0,3,1],[2,0,3,1],[2,0,3,1],[2,1,0,3],[2,1,0,3],[2,1,0,3],[2,1,3,0],[2,1,3,0],[2,1,3,0],[2,3,0,1],[2,3,0,1],[2,3,0,1],[2,3,1,0],[2,3,1,0],[2,3,1,0],[3,0,1,2],[3,0,1,2],[3,0,1,2],[3,0,2,1],[3,0,2,1],[3,0,2,1],[3,1,0,2],[3,1,0,2],[3,1,0,2],[3,1,2,0],[3,1,2,0],[3,1,2,0],[3,2,0,1],[3,2,0,1],[3,2,0,1],[3,2,1,0],[3,2,1,0],[3,2,1,0],null,null,null,null],"space_name":["Bogotá","Cali","Medellín","Bucaramanga","Ibagué","Santa Marta","Cartagena","Cúcuta","Neiva","Pasto","Sincelejo","Atlántico","Chocó","Nariño","Meta West","Guaviare","Putumayo","Cesar","Antioquia","Santander","Huila","Arauca","Meta East","Vichada","Guainía","Vaupés","Amazonas","Brasil","Ecuador","Panamá","Perú","Venezuela","Santa Marta / Cartagena","Cali / Pasto","Neiva / Pasto","Bogotá / San José","Pasto / Tumaco","Cali / Buenaventura","Cartagena / Sincelejo","Sincelejo / Medellín","Medellín / Ibagué","Ibagué / Cali","Bucaramanga / Ibagué / Bogotá","Bogotá / Neiva","Cúcuta / Arauca","Bogotá / Yopal","Santa Marta / Ayacucho","Bucaramanga / Ayacucho","Sincelejo / Ayacucho","Cúcuta / Ayacucho"],"spaces":[{"type":"city","id":"Bogota","pop":8,"adjacent":[35,42,43,45,19,22,14,20]},{"type":"city","id":"Cali","pop":3,"adjacent":[12,13,20,33,37,41]},{"type":"city","id":"Medellin","pop":3,"adjacent":[12,18,39,40]},{"type":"city","id":"Bucaramanga","pop":2,"adjacent":[18,19,42,47]},{"type":"city","id":"Ibague","pop":2,"adjacent":[12,18,20,40,41,42]},{"type":"city","id":"Santa Marta","pop":2,"adjacent":[11,17,32,46]},{"type":"city","id":"Cartagena","pop":1,"adjacent":[11,32,38]},{"type":"city","id":"Cucuta","pop":1,"adjacent":[19,31,44,49]},{"type":"city","id":"Neiva","pop":1,"adjacent":[14,16,20,34,43]},{"type":"city","id":"Pasto","pop":1,"adjacent":[13,16,20,28,33,34,36]},{"type":"city","id":"Sincelejo","pop":1,"adjacent":[11,12,18,38,39,48]},{"type":"forest","id":"Atlantico","pop":1,"adjacent":[5,6,10,17,18,19,32,38,46,47,48,49]},{"type":"forest","id":"Choco","pop":1,"adjacent":[1,2,4,10,13,18,20,29,37,39,40,41]},{"type":"forest","id":"Narino","pop":1,"adjacent":[1,9,12,20,28,33,36,37]},{"type":"forest","id":"Meta West","pop":1,"adjacent":[0,8,15,16,20,22,35,43]},{"type":"forest","id":"Guaviare","pop":1,"adjacent":[14,16,22,23,24,25,35]},{"type":"forest","id":"Putumayo","pop":1,"adjacent":[8,9,14,15,20,25,26,28,30,34]},{"type":"mountain","id":"Cesar","pop":1,"adjacent":[5,11,18,19,31,46,47,48,49]},{"type":"mountain","id":"Antioquia","pop":2,"adjacent":[2,3,4,10,11,12,17,19,20,39,40,42,46,47,48,49]},{"type":"mountain","id":"Santander","pop":2,"adjacent":[0,3,7,11,17,18,20,21,22,31,45,46,47,48,49]},{"type":"mountain","id":"Huila","pop":2,"adjacent":[0,1,4,8,9,12,13,14,16,18,19,33,34,41,42,43]},{"type":"grassland","id":"Arauca","pop":1,"adjacent":[19,22,23,31,44,45]},{"type":"grassland","id":"Meta East","pop":1,"adjacent":[0,14,15,19,21,23,35,45]},{"type":"grassland","id":"Vichada","pop":0,"adjacent":[15,21,22,24,31]},{"type":"forest","id":"Guainia","pop":0,"adjacent":[15,23,25,27,31]},{"type":"forest","id":"Vaupes","pop":0,"adjacent":[15,16,24,26,27]},{"type":"forest","id":"Amazonas","pop":0,"adjacent":[16,25,27,30]},{"type":"foreign","id":"Brasil","pop":0,"adjacent":[24,25,26]},{"type":"foreign","id":"Ecuador","pop":0,"adjacent":[9,13,16,36]},{"type":"foreign","id":"Panama","pop":0,"adjacent":[12]},{"type":"foreign","id":"Peru","pop":0,"adjacent":[16,26]},{"type":"foreign","id":"Venezuela","pop":0,"adjacent":[7,17,19,21,23,24,44,49]},{"type":"road","name":"Santa Marta / Cartagena","id":"Santa Marta / Cartagena","econ":1,"adjacent":[5,6,11]},{"type":"road","name":"Cali / Pasto","id":"Cali / Pasto","econ":1,"adjacent":[1,9,13,20]},{"type":"road","name":"Neiva / Pasto","id":"Neiva / Pasto","econ":1,"adjacent":[8,9,16,20]},{"type":"road","name":"Bogotá / San José","id":"Bogota / San Jose","econ":1,"adjacent":[14,15,22]},{"type":"road","name":"Pasto / Tumaco","id":"Pasto / Tumaco","econ":1,"adjacent":[9,13,28]},{"type":"pipeline","name":"Cali / Buenaventura","id":"Cali / Buenaventura","econ":1,"adjacent":[1,12,13]},{"type":"pipeline","name":"Cartagena / Sincelejo","id":"Cartagena / Sincelejo","econ":1,"adjacent":[6,10,11]},{"type":"pipeline","name":"Sincelejo / Medellín","id":"Sincelejo / Medellin","econ":2,"adjacent":[2,10,12,18]},{"type":"pipeline","name":"Medellín / Ibagué","id":"Medellin / Ibague","econ":1,"adjacent":[2,4,12,18]},{"type":"pipeline","name":"Ibagué / Cali","id":"Ibague / Cali","econ":1,"adjacent":[1,4,12,20]},{"type":"pipeline","name":"Bucaramanga / Ibagué / Bogotá","id":"Bucaramanga / Ibague / Bogota","econ":2,"adjacent":[3,4,18,20]},{"type":"pipeline","name":"Bogotá / Neiva","id":"Bogota / Neiva","econ":2,"adjacent":[8,14,20]},{"type":"pipeline","name":"Cúcuta / Arauca","id":"Cucuta / Arauca","econ":3,"adjacent":[7,21,21,31]},{"type":"pipeline","name":"Bogotá / Yopal","id":"Bogota / Yopal","econ":2,"adjacent":[19,21,22]},{"type":"pipeline","name":"Santa Marta / Ayacucho","id":"Santa Marta / Ayacucho","econ":2,"adjacent":[5,11,17,18,19,47,48,49]},{"type":"pipeline","name":"Bucaramanga / Ayacucho","id":"Bucaramanga / Ayacucho","econ":2,"adjacent":[3,11,17,18,19,46,48,49]},{"type":"pipeline","name":"Sincelejo / Ayacucho","id":"Sincelejo / Ayacucho","econ":3,"adjacent":[10,11,17,18,19,46,47,49]},{"type":"pipeline","name":"Cúcuta / Ayacucho","id":"Cucuta / Ayacucho","econ":3,"adjacent":[7,11,17,18,19,31,46,47,48]}],"first_piece":[[0,3,3,33],[63,72],[102,108],[126,141]],"last_piece":[[2,2,32,62],[71,101],[107,125],[140,152]]} +const data = {"first_space":0,"first_pop":1,"first_city":0,"last_city":10,"first_dept":11,"last_pop":22,"last_dept":26,"first_foreign":27,"last_foreign":31,"first_loc":32,"last_loc":49,"last_space":49,"coastal_spaces":[11,12,13,17],"card_name":[null,"1st Division","Ospina & Mora","Tapias","Caño Limón - Coveñas","Occidental & Ecopetrol","Oil Spill","7th Special Forces","Fuerza Aérea Colombiana","High Mountain Battalions","Blackhawks","National Defense & Security Council","Plan Colombia","Plan Meteoro","Tres Esquinas","War Tax","Coffee Prices","Madrid Donors","NSPD-18","General Offensive","Mono Jojoy","Raúl Reyes","Alfonso Cano","DoD Contractors","Operación Jaque","Ejército de Liberación Nacional","Gramaje","Misil Antiaéreo","Hugo Chávez","Kill Zone","Peace Commission","Betancourt","Secuestrados","Sucumbíos","Airdropped AKs","Crop Substitution","Zona de Convivencia","Former Military","National Coordination Center","Soldados Campesinos","Demobilization","Mancuso","Senado & Cámara","Calima Front","Colombia Nueva","Los Derechos Humanos","Limpieza","Pinto & del Rosario","Unión Sindical Obrera","Bloques","Carabineros","Pipeline Repairs","Castaño","Criminal Air Force","Deserters & Defectors","DEA Agents","Drogas La Rebaja","Op Millennium","General Serrano","Salcedo","The Chess Player","Air Bridge","Amazonía","Narco-War","Cocaine Labs","Poppies","Tingo María","Mexican Traffickers","Narco-Subs","Riverines & Fast Boats","Ayahuasca Tourism","Darién","Sicarios","Propaganda!","Propaganda!","Propaganda!","Propaganda!"],"card_order":[null,[0,1,2,3],[0,1,2,3],[0,1,2,3],[0,1,3,2],[0,1,3,2],[0,1,3,2],[0,2,1,3],[0,2,1,3],[0,2,1,3],[0,2,3,1],[0,2,3,1],[0,2,3,1],[0,3,1,2],[0,3,1,2],[0,3,1,2],[0,3,2,1],[0,3,2,1],[0,3,2,1],[1,0,2,3],[1,0,2,3],[1,0,2,3],[1,0,3,2],[1,0,3,2],[1,0,3,2],[1,2,0,3],[1,2,0,3],[1,2,0,3],[1,2,3,0],[1,2,3,0],[1,2,3,0],[1,3,0,2],[1,3,0,2],[1,3,0,2],[1,3,2,0],[1,3,2,0],[1,3,2,0],[2,0,1,3],[2,0,1,3],[2,0,1,3],[2,0,3,1],[2,0,3,1],[2,0,3,1],[2,1,0,3],[2,1,0,3],[2,1,0,3],[2,1,3,0],[2,1,3,0],[2,1,3,0],[2,3,0,1],[2,3,0,1],[2,3,0,1],[2,3,1,0],[2,3,1,0],[2,3,1,0],[3,0,1,2],[3,0,1,2],[3,0,1,2],[3,0,2,1],[3,0,2,1],[3,0,2,1],[3,1,0,2],[3,1,0,2],[3,1,0,2],[3,1,2,0],[3,1,2,0],[3,1,2,0],[3,2,0,1],[3,2,0,1],[3,2,0,1],[3,2,1,0],[3,2,1,0],[3,2,1,0],[0,1,2,3],[0,1,2,3],[0,1,2,3],[0,1,2,3]],"space_name":["Bogotá","Cali","Medellín","Bucaramanga","Ibagué","Santa Marta","Cartagena","Cúcuta","Neiva","Pasto","Sincelejo","Atlántico","Chocó","Nariño","Meta West","Guaviare","Putumayo","Cesar","Antioquia","Santander","Huila","Arauca","Meta East","Vichada","Guainía","Vaupés","Amazonas","Panamá","Ecuador","Brasil","Perú","Venezuela","Santa Marta / Cartagena","Cali / Pasto","Neiva / Pasto","Bogotá / San José","Pasto / Tumaco","Cali / Buenaventura","Cartagena / Sincelejo","Sincelejo / Medellín","Medellín / Ibagué","Ibagué / Cali","Bucaramanga / Ibagué / Bogotá","Bogotá / Neiva","Cúcuta / Arauca","Bogotá / Yopal","Santa Marta / Ayacucho","Bucaramanga / Ayacucho","Sincelejo / Ayacucho","Cúcuta / Ayacucho"],"spaces":[{"type":"city","id":"Bogota","pop":8,"adjacent":[14,19,20,22,35,42,43,45]},{"type":"city","id":"Cali","pop":3,"adjacent":[12,13,20,33,37,41]},{"type":"city","id":"Medellin","pop":3,"adjacent":[12,18,39,40]},{"type":"city","id":"Bucaramanga","pop":2,"adjacent":[18,19,42,47]},{"type":"city","id":"Ibague","pop":2,"adjacent":[12,18,20,40,41,42]},{"type":"city","id":"Santa Marta","pop":2,"adjacent":[11,17,32,46]},{"type":"city","id":"Cartagena","pop":1,"adjacent":[11,32,38]},{"type":"city","id":"Cucuta","pop":1,"adjacent":[19,31,44,49]},{"type":"city","id":"Neiva","pop":1,"adjacent":[14,16,20,34,43]},{"type":"city","id":"Pasto","pop":1,"adjacent":[13,16,20,28,33,34,36]},{"type":"city","id":"Sincelejo","pop":1,"adjacent":[11,12,18,38,39,48]},{"type":"forest","id":"Atlantico","pop":1,"adjacent":[5,6,10,17,18,19,32,38,46,47,48,49]},{"type":"forest","id":"Choco","pop":1,"adjacent":[1,2,4,10,13,18,20,27,37,39,40,41]},{"type":"forest","id":"Narino","pop":1,"adjacent":[1,9,12,20,28,33,36,37]},{"type":"forest","id":"Meta West","pop":1,"adjacent":[0,8,15,16,20,22,35,43]},{"type":"forest","id":"Guaviare","pop":1,"adjacent":[14,16,22,23,24,25,35]},{"type":"forest","id":"Putumayo","pop":1,"adjacent":[8,9,14,15,20,25,26,28,30,34]},{"type":"mountain","id":"Cesar","pop":1,"adjacent":[5,11,18,19,31,46,47,48,49]},{"type":"mountain","id":"Antioquia","pop":2,"adjacent":[2,3,4,10,11,12,17,19,20,39,40,42,46,47,48,49]},{"type":"mountain","id":"Santander","pop":2,"adjacent":[0,3,7,11,17,18,20,21,22,31,42,44,45,46,47,48,49]},{"type":"mountain","id":"Huila","pop":2,"adjacent":[0,1,4,8,9,12,13,14,16,18,19,33,34,41,42,43]},{"type":"grassland","id":"Arauca","pop":1,"adjacent":[19,22,23,31,44,45]},{"type":"grassland","id":"Meta East","pop":1,"adjacent":[0,14,15,19,21,23,35,45]},{"type":"grassland","id":"Vichada","pop":0,"adjacent":[15,21,22,24,31]},{"type":"forest","id":"Guainia","pop":0,"adjacent":[15,23,25,29,31]},{"type":"forest","id":"Vaupes","pop":0,"adjacent":[15,16,24,26,29]},{"type":"forest","id":"Amazonas","pop":0,"adjacent":[16,25,29,30]},{"type":"foreign","id":"Panama","pop":0,"adjacent":[12]},{"type":"foreign","id":"Ecuador","pop":0,"adjacent":[9,13,16,36]},{"type":"foreign","id":"Brasil","pop":0,"adjacent":[24,25,26]},{"type":"foreign","id":"Peru","pop":0,"adjacent":[16,26]},{"type":"foreign","id":"Venezuela","pop":0,"adjacent":[7,17,19,21,23,24,44,49]},{"type":"road","id":"Santa Marta / Cartagena","econ":1,"adjacent":[5,6,11]},{"type":"road","id":"Cali / Pasto","econ":1,"adjacent":[1,9,13,20]},{"type":"road","id":"Neiva / Pasto","econ":1,"adjacent":[8,9,16,20]},{"type":"road","id":"Bogota / San Jose","econ":1,"adjacent":[14,15,22]},{"type":"road","id":"Pasto / Tumaco","econ":1,"adjacent":[9,13,28]},{"type":"pipeline","id":"Cali / Buenaventura","econ":1,"adjacent":[1,12,13]},{"type":"pipeline","id":"Cartagena / Sincelejo","econ":1,"adjacent":[6,10,11]},{"type":"pipeline","id":"Sincelejo / Medellin","econ":2,"adjacent":[2,10,12,18]},{"type":"pipeline","id":"Medellin / Ibague","econ":1,"adjacent":[2,4,12,18]},{"type":"pipeline","id":"Ibague / Cali","econ":1,"adjacent":[1,4,12,20]},{"type":"pipeline","id":"Bucaramanga / Ibague / Bogota","econ":2,"adjacent":[3,4,18,19,20]},{"type":"pipeline","id":"Bogota / Neiva","econ":2,"adjacent":[8,14,20]},{"type":"pipeline","id":"Cucuta / Arauca","econ":3,"adjacent":[7,19,21,21,31]},{"type":"pipeline","id":"Bogota / Yopal","econ":2,"adjacent":[19,21,22]},{"type":"pipeline","id":"Santa Marta / Ayacucho","econ":2,"adjacent":[5,11,17,18,19,47,48,49]},{"type":"pipeline","id":"Bucaramanga / Ayacucho","econ":2,"adjacent":[3,11,17,18,19,46,48,49]},{"type":"pipeline","id":"Sincelejo / Ayacucho","econ":3,"adjacent":[10,11,17,18,19,46,47,49]},{"type":"pipeline","id":"Cucuta / Ayacucho","econ":3,"adjacent":[7,11,17,18,19,31,46,47,48]}],"first_piece":[[0,3,3,33,0],[63,72],[102,108],[126,141]],"last_piece":[[2,2,32,62,-1],[71,101],[107,125],[140,152]]} if (typeof module !== 'undefined') module.exports = data diff --git a/images/back-forth.svg b/images/back-forth.svg new file mode 100644 index 0000000..e76e9b1 --- /dev/null +++ b/images/back-forth.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/shaking-hands.svg b/images/shaking-hands.svg new file mode 100644 index 0000000..f3b76cd --- /dev/null +++ b/images/shaking-hands.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/play.css b/play.css index 5958485..2cf2615 100644 --- a/play.css +++ b/play.css @@ -57,31 +57,36 @@ main { background-color: #777; } #cities { position: absolute; } #boxes { position: absolute; } -path { fill: transparent; } -path.action { fill: white; fill-opacity: 0.3; stroke: white; stroke-width: 4; } +path { fill: transparent; stroke-width: 4; } +path.action { fill: white; fill-opacity: 0.3; stroke: white; } path.action.foreign { fill: gold; stroke: lemonchiffon; } path.action.forest { fill: limegreen; stroke: limegreen; } path.action.grassland { fill: greenyellow; stroke: greenyellow; } path.action.mountain { fill: chocolate; stroke: chocolate; } +path.selected { stroke: yellow; } -.box{position:absolute;box-sizing:border-box;} -.box.action{z-index:100; border:4px solid lemonchiffon;} +.box{position:absolute;box-sizing:border-box;border:4px solid transparent} .box.city{border-radius:50%} -.box.city.action{background-color:#6495ed55;border:4px solid cornflowerblue;} .box.loc{border-radius:50%} -.box.loc.action{background-color:#fff5;border:4px solid white;} +.box.action{border-color:lemonchiffon;} +.box.city.action{background-color:#6495ed55;border-color:deepskyblue;} +.box.loc.action{background-color:#fff5;border-color:white;} +.box.selected{border-color:yellow;} + -.piece { position: absolute; } -.piece { background-position: center; background-repeat: no-repeat; background-size: contain; } .piece { + position: absolute; + pointer-events: none; + background-position: center; + background-repeat: no-repeat; + background-size: contain; transition-property: top, left; transition-duration: 700ms; transition-timing-function: ease; -} -.piece { filter: drop-shadow(0 1px 2px #000a); } .piece.action { + pointer-events: auto; filter: drop-shadow(0 -2px 0 white) drop-shadow(0 2px 0 white) @@ -91,6 +96,7 @@ path.action.mountain { fill: chocolate; stroke: chocolate; } } .token { + pointer-events: none; position: absolute; transition-property: top, left; transition-duration: 700ms; @@ -103,6 +109,10 @@ path.action.mountain { fill: chocolate; stroke: chocolate; } height: 45px; } +.token.action { + pointer-events: auto; +} + .token.terror, .token.sabotage, .token.active_opposition, diff --git a/play.html b/play.html index 33d1584..46a5f2d 100644 --- a/play.html +++ b/play.html @@ -37,6 +37,16 @@
+ +
diff --git a/play.js b/play.js index b13418c..c4a3733 100644 --- a/play.js +++ b/play.js @@ -726,6 +726,7 @@ function on_update() { console.log("NO SPACE", s, data.space_name[s]) ui.spaces[s].classList.toggle("action", is_action("space", s)) + ui.spaces[s].classList.toggle("selected", view.where === s) } list.length = 0 @@ -779,11 +780,21 @@ function on_update() { action_button("kidnap", "Process") action_button("kidnap", "Bribe") + // Train/Rally sub-actions + action_button("move", "Move") + action_button("flip", "Flip") + action_button("base", "Base") + action_button("civic", "Civic Action") + action_button("unshaded", "Unshaded") action_button("shaded", "Shaded") action_button("event", "Event") action_button("limop", "LimOp") + + action_button("next", "Next") + action_button("done", "Done") + action_button("remove", "Remove") action_button("undo", "Undo") } diff --git a/rules.js b/rules.js index d8e921d..831377d 100644 --- a/rules.js +++ b/rules.js @@ -28,22 +28,25 @@ const BASE = 0 const GUERRILLA = 1 const TROOPS = 2 const POLICE = 3 +const CUBE = 4 const space_name = data.space_name const first_piece = data.first_piece const last_piece = data.last_piece +const first_space = data.first_space +const last_space = data.last_space const first_pop = data.first_pop const first_city = data.first_city const last_city = data.last_city const first_dept = data.first_dept const last_pop = data.last_pop const last_dept = data.last_dept -const first_foreign = data.first_foreign -const last_foreign = data.last_foreign const first_loc = data.first_loc const last_loc = data.last_loc +const first_foreign = data.first_foreign +const last_foreign = data.last_foreign // Sequence of Play options const ELIGIBLE = 0 @@ -179,8 +182,8 @@ exports.setup = function (seed, scenario, options) { current: 0, state: null, - op_spaces: null, - sa_spaces: null, + op: null, + sa: null, deck: [], president: 0, @@ -293,6 +296,9 @@ function setup_standard() { place_piece(CARTELS, BASE, 1, META_WEST) place_piece(CARTELS, BASE, 1, GUAVIARE) place_piece(CARTELS, BASE, 2, PUTUMAYO) + + // XXX + set_support(BOGOTA, ACTIVE_OPPOSITION) } function setup_quick() { @@ -386,7 +392,7 @@ function remove_piece(faction, type, count, where) { } } -function count_pieces_imp(s, faction, type) { +function count_pieces(s, faction, type) { let first = first_piece[faction][type] let last = last_piece[faction][type] let n = 0 @@ -396,19 +402,53 @@ function count_pieces_imp(s, faction, type) { return n } +function has_piece(s, faction, type) { + let first = first_piece[faction][type] + let last = last_piece[faction][type] + for (let p = first; p <= last; ++p) + if (game.pieces[p] === s) + return true + return false +} + +function has_active_guerrilla(s, faction) { + let first = first_piece[faction][GUERRILLA] + let last = last_piece[faction][GUERRILLA] + for (let p = first; p <= last; ++p) + if (game.pieces[p] === s && !is_underground(p)) + return true + return false +} + +function count_bases(s) { + return ( + count_pieces(s, GOVT, BASE) + + count_pieces(s, FARC, BASE) + + count_pieces(s, AUC, BASE) + + count_pieces(s, CARTELS, BASE) + ) +} + +function count_cubes(s) { + return ( + count_pieces(s, GOVT, TROOPS) + + count_pieces(s, GOVT, POLICE) + ) +} + function update_control() { game.govt_control = 0 game.farc_control = 0 - for (let s = 0; s <= last_dept; ++s) { - let g = count_pieces_imp(s, GOVT, BASE) + - count_pieces_imp(s, GOVT, TROOPS) + - count_pieces_imp(s, GOVT, POLICE) - let f = count_pieces_imp(s, FARC, BASE) + - count_pieces_imp(s, FARC, GUERRILLA) - let a = count_pieces_imp(s, AUC, BASE) + - count_pieces_imp(s, AUC, GUERRILLA) - let c = count_pieces_imp(s, CARTELS, BASE) + - count_pieces_imp(s, CARTELS, GUERRILLA) + for (let s = first_space; s <= last_dept; ++s) { + let g = count_pieces(s, GOVT, BASE) + + count_pieces(s, GOVT, TROOPS) + + count_pieces(s, GOVT, POLICE) + let f = count_pieces(s, FARC, BASE) + + count_pieces(s, FARC, GUERRILLA) + let a = count_pieces(s, AUC, BASE) + + count_pieces(s, AUC, GUERRILLA) + let c = count_pieces(s, CARTELS, BASE) + + count_pieces(s, CARTELS, GUERRILLA) if (g > a + c + f) game.govt_control |= (1 << s) else if (f > g + a + c) @@ -417,11 +457,19 @@ function update_control() { } function is_city(s) { - return s <= last_city + return s >= first_city && s <= last_city } -function has_govt_base(s) { - return set_has(game.govt.bases, s) +function is_dept(s) { + return s >= first_dept && s <= last_dept +} + +function is_loc(s) { + return s >= first_loc && s <= last_loc +} + +function is_adjacent(a, b) { + return set_has(data.spaces[a].adjacent, b) } function is_underground(p) { @@ -451,12 +499,42 @@ function set_active(p) { } } +function has_govt_control(s) { + return game.govt_control & (1 << s) +} + +function has_farc_control(s) { + return game.farc_control & (1 << s) +} + +function can_govt_civic_action(s) { + return game.support[s] < 2 && has_govt_control(s) && has_piece(s, GOVT, TROOPS) && has_piece(s, GOVT, POLICE) +} + +function for_each_piece(faction, type, f) { + let p0 = first_piece[faction][type] + let p1 = last_piece[faction][type] + for (let p = p0; p <= p1; ++p) + f(p) +} + +function gen_piece_in_space(faction, type, space) { + for_each_piece(faction, type, p => { + if (game.pieces[p] === space) + gen_action("piece", p) + }) +} + // === SEQUENCE OF PLAY === function this_card() { return game.deck[0] } +function is_final_card() { + return false +} + function goto_card() { if (this_card() > 72) goto_propaganda_card() @@ -587,7 +665,7 @@ states.eligible2 = { goto_pass() break case SOP_2ND_LIMOP: - goto_op_only() + goto_limop() break case SOP_2ND_LIMOP_OR_EVENT: goto_limop_or_event() @@ -635,43 +713,100 @@ function goto_event() { function goto_op_only() { log_h2(faction_name[game.current] + " - Op Only") - game.state = "op" - game.op_spaces = [] - game.sa_spaces = null + goto_operation() } function goto_op_and_sa() { log_h2(faction_name[game.current] + " - Op + Special") - game.state = "op" - game.op_spaces = [] - game.sa_spaces = [] + goto_operation() } function goto_limop() { log_h2(faction_name[game.current] + " - LimOp") + goto_operation() +} + +function goto_operation() { game.state = "op" - game.op_spaces = [] - game.sa_spaces = null + game.op = { + spaces: [], + pieces: [], + count: 0, + } +} + +function end_operation() { + game.op = null + resume_event_card() } function can_use_special_activity() { - let faction = current_faction() - if (faction.cylinder === SOP_1ST_OP_AND_SA || faction.cylinder === SOP_2ND_OP_AND_SA) + if (game.cylinder[game.current] === SOP_1ST_OP_AND_SA || game.cylinder[game.current] === SOP_2ND_OP_AND_SA) + return true + return false +} + +function is_limop() { + if (game.cylinder[game.current] === SOP_2ND_LIMOP || game.cylinder[game.current] === SOP_2ND_LIMOP_OR_EVENT) return true return false } +function action_remove() { + push_undo() + game.save_state = game.state + game.state = "remove" +} + +states.remove = { + prompt() { + view.prompt = "Remove pieces to Available Forces." + for (let p = first_piece[game.current][BASE]; p <= last_piece[game.current][BASE]; ++p) + if (game.pieces[p] !== AVAILABLE) + gen_action("piece", p) + if (game.current === GOVT) { + for (let p = first_piece[game.current][TROOPS]; p <= last_piece[game.current][TROOPS]; ++p) + if (game.pieces[p] !== AVAILABLE) + gen_action("piece", p) + for (let p = first_piece[game.current][POLICE]; p <= last_piece[game.current][POLICE]; ++p) + if (game.pieces[p] !== AVAILABLE) + gen_action("piece", p) + } else { + for (let p = first_piece[game.current][GUERRILLA]; p <= last_piece[game.current][GUERRILLA]; ++p) + if (game.pieces[p] !== AVAILABLE) + gen_action("piece", p) + } + view.actions.done = 1 + }, + piece(p) { + game.pieces[p] = AVAILABLE + update_control() + }, + done() { + game.state = game.save_state + game.save_state = 0 + }, +} + +// === OPERATIONS === + states.op = { prompt() { view.prompt = "Choose an Operation." if (game.current === GOVT) { view.actions.train = 1 view.actions.patrol = 1 - view.actions.sweep = 1 + if (is_final_card()) + view.actions.sweep = 0 + else + view.actions.sweep = 1 view.actions.assault = 1 } else { view.actions.rally = 1 - view.actions.march = 1 + if (is_final_card()) + view.actions.march = 0 + else + view.actions.march = 1 view.actions.attack = 1 view.actions.terror = 1 } @@ -708,6 +843,7 @@ states.op = { push_undo() log_h3("March") game.state = "march" + game.op.pieces = [] }, attack() { push_undo() @@ -719,101 +855,545 @@ states.op = { log_h3("Terror") game.state = "terror" }, +} + +function gen_operation_common() { + if (game.op.spaces.length > 0) + view.actions.done = 1 + else + view.actions.done = 0 + view.actions.remove = 1 +} + +// OPERATION: TRAIN + +states.train = { + prompt() { + view.prompt = "Train: Place cubes first, then replace with Base or buy Civic Action." + + if (can_use_special_activity()) { + view.actions.air_lift = 1 + view.actions.eradicate = 1 + } + + // Any Departments or Cities + if (game.resources[game.current] >= 3) { + for (let s = first_space; s <= last_dept; ++s) { + if (is_city(s) || has_piece(s, GOVT, BASE)) + if (!set_has(game.op.spaces, s)) + gen_action("space", s) + } + } + + // place base + view.actions.base = 1 + + // buy civic action + view.actions.civic = 1 - remove() { + gen_operation_common() + }, + space(s) { + push_undo() + + logi(`S${s}.`) + + game.resources[game.current] -= 3 + set_add(game.op.spaces, s) + + game.state = "train_place" + game.op.where = s + game.op.count = 6 + }, + base() { + push_undo() + game.state = "train_base" + game.op.where = -1 + }, + civic() { push_undo() - game.save_state = game.state - game.state = "remove" + game.state = "train_civic" + game.op.where = -1 }, + done() { + end_operation() + }, + air_lift: goto_air_lift, + eradicate: goto_eradicate, } -function for_each_own_piece(f) { - f(p) +states.train_place = { + prompt() { + view.prompt = `Train in ${space_name[game.op.where]}: Place up to ${game.op.count} cubes.` + view.where = game.op.where + + if (game.op.count > 0) { + gen_piece_in_space(GOVT, POLICE, AVAILABLE) + gen_piece_in_space(GOVT, TROOPS, AVAILABLE) + } + + view.actions.next = 1 + view.actions.remove = 1 + }, + piece(p) { + push_undo() + game.pieces[p] = game.op.where + if (--game.op.count == 0) + game.state = "train" + update_control() + }, + next() { + game.op.count = 0 + game.state = "train" + }, } -states.remove = { +states.train_base = { prompt() { - view.prompt = "Remove pieces to Available Forces." - for_each_own_piece(p => { - if (game.pieces[p] !== AVAILABLE) - gen_action("piece", p) - }) - view.actions.done = 1 + if (game.op.where < 0) { + view.prompt = `Train: Replace 3 cubes with a Base.` + for (let s = first_space; s <= last_dept; ++s) { + if (set_has(game.op.spaces, s) || game.resources[game.current] >= 3) + if (count_bases(s) < 2 && count_cubes(s) >= 3) + gen_action("space", s) + } + } else { + if (game.op.count < 0) { + view.prompt = `Train: All done.` + view.actions.done = 1 + } else if (game.op.count > 0) { + view.prompt = `Train: Replace ${game.op.count} cubes with a Base.` + gen_piece_in_space(GOVT, POLICE, game.op.where) + gen_piece_in_space(GOVT, TROOPS, game.op.where) + } else { + view.prompt = `Train: Place Base.` + gen_piece_in_space(GOVT, BASE, AVAILABLE) + } + } + }, + space(s) { + push_undo() + if (!set_has(game.op.spaces, s)) { + game.resources[game.current] -= 3 + set_add(game.op.spaces, s) + } + game.op.where = s + game.op.count = 3 }, piece(p) { push_undo() - game.pieces[p] = AVAILABLE + if (game.op.count > 0) + game.pieces[p] = AVAILABLE + else + game.pieces[p] = game.op.where + --game.op.count + update_control() }, - done() { - game.state = game.save_state - game.save_state = 0 - } + done: end_operation, } -states.train = { +states.train_civic = { prompt() { - let faction = current_faction() + let res = game.resources[game.current] + if (game.op.where < 0) { + view.prompt = `Train: Buy Civic Action.` + if (res >= 3) { + for (let s = first_space; s <= last_dept; ++s) { + if (set_has(game.op.spaces, s) || res >= 6) + if (can_govt_civic_action(s)) + gen_action("space", s) + } + } + } else { + view.prompt = `Train: Buy Civic Action in ${space_name[game.op.where]}.` + view.where = game.op.where + if (res >= 3 && can_govt_civic_action(game.op.where)) + gen_action("space", game.op.where) + else + view.prompt = `Train: All done.` + view.actions.done = 1 + } + }, + space(s) { + push_undo() + if (!set_has(game.op.spaces, s)) { + game.resources[game.current] -= 3 + set_add(game.op.spaces, s) + } + game.op.where = s + game.resources[game.current] -= 3 + game.support[game.op.where] += 1 + }, + done: end_operation, +} - view.prompt = "Train: Select spaces." +// OPERATION: RALLY + +function rally_count() { + if (has_piece(game.op.where, game.current, BASE)) + return data.spaces[game.op.where].pop + count_pieces(game.op.where, game.current, BASE) + return 1 +} + +states.rally = { + prompt() { + if (game.current === FARC) + view.prompt = "Rally: Select City or Department without Support." + else if (game.current === AUC) + view.prompt = "Rally: Select City or Department without Opposition." + else + view.prompt = "Rally: Select City or Department." if (can_use_special_activity()) { - view.actions.air_lift = 1 - view.actions.eradicate = 1 + if (game.current === FARC) + view.actions.extort = 1 + if (game.current === AUC) + view.actions.extort = 1 + if (game.current === CARTELS) { + view.actions.cultivate = 1 + view.actions.process = 1 + view.actions.bribe = 1 + } } - // Any Departments or Cities - if (faction.resources >= 3) { - for (let s = 0; s <= last_dept; ++s) { - if (!set_has(game.op_spaces, s)) - gen_action("space", s) + // Departments or Cities + if (game.resources[game.current] >= 1) { + for (let s = first_space; s <= last_dept; ++s) { + if (set_has(game.op.spaces, s)) + continue + + // FARC: without Support + if (game.current === FARC) + if (game.support[s] > 0) + continue + + // AUC: without Opposition + if (game.current === AUC) + if (game.support[s] < 0) + continue + + gen_action("space", s) } } + + gen_operation_common() }, - air_lift() { + space(s) { push_undo() - game.state = "air_lift" + + logi(`S${s}.`) + game.resources[game.current] -= 1 + set_add(game.op.spaces, s) + + game.state = "rally_place" + game.op.where = s + game.op.count = rally_count() }, - eradicate() { + done: end_operation, + extort: goto_extort, + cultivate: goto_cultivate, + process: goto_process, + bribe: goto_bribe, +} + +states.rally_place = { + prompt() { + view.prompt = `Rally: Place up to ${game.op.count} Guerrillas.` + view.where = game.op.where + view.actions.remove = 1 + + if (game.op.count === rally_count()) { + view.actions.base = 0 + view.actions.flip = 0 + view.actions.move = 0 + if (count_pieces(game.op.where, game.current, GUERRILLA) >= 2) { + if (count_bases(game.op.where) < 2) + view.actions.base = 1 + } + if (has_piece(game.op.where, game.current, BASE)) { + if (has_active_guerrilla(game.op.where, game.current)) + view.actions.flip = 1 + view.actions.move = 1 + } + } + + view.actions.next = 1 + + gen_piece_in_space(game.current, GUERRILLA, AVAILABLE) + }, + piece(p) { push_undo() - game.state = "eradicate" + set_underground(p) + game.pieces[p] = game.op.where + if (--game.op.count === 0) + game.state = "rally" + update_control() }, - space(s) { + base() { push_undo() - logi(`S${s}.`) - let faction = current_faction() - faction.resources -= 3 - set_add(game.op_spaces, s) - game.where = s - if (is_city(s) || has_govt_base(s)) { - game.state = "train_place_cubes" - game.selected = -1 - game.count = 6 + logi("Base.") + game.state = "rally_base" + game.op.count = 2 + }, + flip() { + push_undo() + logi("Flipped.") + for_each_piece(game.current, GUERRILLA, p => { + if (game.pieces[p] === game.op.where) + set_underground(p) + }) + game.state = "rally" + }, + move() { + push_undo() + logi("Moved.") + game.state = "rally_move" + game.op.count = 0 + }, + next() { + push_undo() + game.state = "rally" + }, +} + +states.rally_base = { + prompt() { + view.prompt = `Rally: Replace ${game.op.count} Guerrillas with a Base.` + if (game.op.count > 0) + gen_piece_in_space(game.current, GUERRILLA, game.op.where) + else + gen_piece_in_space(game.current, BASE, AVAILABLE) + }, + piece(p) { + push_undo() + if (game.op.count > 0) { + set_underground(p) + game.pieces[p] = AVAILABLE + --game.op.count } else { - game.state = "train_base_or_civic" + game.pieces[p] = game.op.where + game.state = "rally" } + update_control() }, } -function gen_select_available(action, list) { - for (let i = list.length; i-- > 0; ) { - if (list[i] === AVAILABLE) { - gen_action(action, i) - return - } +states.rally_move = { + prompt() { + view.where = game.op.where + view.actions.remove = 1 + + view.prompt = `Rally: Move any Guerrillas to ${space_name[game.op.where]}.` + + for_each_piece(game.current, GUERRILLA, p => { + if (game.pieces[p] !== game.op.where && game.pieces[p] !== AVAILABLE) + gen_action("piece", p) + }) + + view.actions.next = 1 + }, + piece(p) { + push_undo() + game.pieces[p] = game.op.where + game.op.count++ + update_control() + }, + next() { + push_undo() + game.op.count = 0 + game.state = "rally" } - for (let i = 0; i < list.length; ++i) - gen_action(action, i) } -states.train_place_cubes = { +// OPERATION: MARCH + +function can_march_to(to) { + for (let from of data.spaces[to].adjacent) + if (has_piece(from, game.current, GUERRILLA)) + return true + return false +} + +states.march = { prompt() { - view.prompt = `Train in ${space_name[game.where]}: Place up to ${game.count} cubes.` + view.prompt = `March: Move Guerrillas to Cities/Departments/LoCs.` + + if (can_use_special_activity()) { + if (game.current === FARC) + view.actions.extort = 1 + if (game.current === AUC) + view.actions.extort = 1 + if (game.current === CARTELS) { + view.actions.cultivate = 1 + view.actions.process = 1 + view.actions.bribe = 1 + } + } + + // TODO: check if move is possible - if (game.selected < 0) { - gen_select_available("govt_police", game.govt.police) - gen_select_available("govt_troops", game.govt.troops) + if (game.resources[game.current] >= 1) { + for (let s = first_space; s <= last_dept; ++s) { + if (set_has(game.op.spaces, s)) + continue + if (can_march_to(s)) + gen_action("space", s) + } } + + for (let s = first_loc; s <= last_loc; ++s) { + if (set_has(game.op.spaces, s)) + continue + if (can_march_to(s)) + gen_action("space", s) + } + + gen_operation_common() }, + space(s) { + push_undo() + + logi(`S${s}.`) + + if (s <= last_dept) + game.resources[game.current] -= 1 + + set_add(game.op.spaces, s) + + game.state = "march_move" + game.op.where = s + game.op.march = [] + }, + done: end_operation, +} + +function may_activate_marching_guerrillas() { + if (is_loc(game.op.where)) + return true + if (game.support[game.op.where] > 0) + return true + if (game.current === AUC && game.support[game.op.where] < 0) + return true + return false +} + +function activate_marching_guerrillas(group) { + console.log("MARCH", group) + if (may_activate_marching_guerrillas()) { + let count = group.length + count += count_pieces(game.op.where, GOVT, TROOPS) + count += count_pieces(game.op.where, GOVT, POLICE) + if (game.current === AUC) + count += count_pieces(game.op.where, FARC, GUERRILLA) + if (count > 3) + for (let p of group) + set_active(p) + } +} + +states.march_move = { + prompt() { + view.prompt = `March: Move Guerrillas to ${space_name[game.op.where]}.` + view.where = game.op.where + + for_each_piece(game.current, GUERRILLA, p => { + // May not move more than once + if (set_has(game.op.pieces, p)) + return // continue + + let s = game.pieces[p] + if (is_adjacent(game.op.where, s)) + gen_action("piece", p) + }) + + if (game.op.march.length > 0) + view.actions.next = 1 + }, + piece(p) { + push_undo() + + let from = game.pieces[p] + let group = map_get(game.op.march, from, null) + if (!group) + group = [] + set_add(group, p) + map_set(game.op.march, from, group) + + activate_marching_guerrillas(group) + + set_add(game.op.pieces, p) + + game.pieces[p] = game.op.where + + update_control() + }, + next() { + push_undo() + game.op.march = 0 + game.state = "march" + }, +} + +// === SPECIAL ACTIVITIES === + +function goto_air_lift() { + push_undo() + game.save_state = game.state + game.state = "air_lift" +} + +function goto_air_strike() { + push_undo() + game.save_state = game.state + game.state = "air_strike" +} + +function goto_eradicate() { + push_undo() + game.save_state = game.state + game.state = "eradicate" +} + +function goto_extort() { + push_undo() + game.save_state = game.state + game.state = "extort" +} + +function goto_ambush() { + push_undo() + game.save_state = game.state + game.state = "ambush" +} + +function goto_kidnap() { + push_undo() + game.save_state = game.state + game.state = "kidnap" +} + +function goto_assassinate() { + push_undo() + game.save_state = game.state + game.state = "assassinate" +} + +function goto_cultivate() { + push_undo() + game.save_state = game.state + game.state = "cultivate" +} + +function goto_process() { + push_undo() + game.save_state = game.state + game.state = "process" +} + +function goto_bribe() { + push_undo() + game.save_state = game.state + game.state = "bribe" } // === GAME OVER === @@ -958,13 +1538,18 @@ exports.view = function (state, role) { exports.action = function (state, role, action, arg) { load_game(state) - // Object.seal(game) // XXX: don't allow adding properties + + // XXX - don't allow adding properties + Object.seal(game) // XXX: don't allow adding properties + let S = states[game.state] if (S && action in S) { S[action](arg) } else { if (action === "undo" && game.undo && game.undo.length > 0) pop_undo() + else if (action === "remove") + action_remove() else throw new Error("Invalid action: " + action) } @@ -977,36 +1562,6 @@ exports.is_checkpoint = function (a, b) { // === COMMON LIBRARY === -// Packed array of small numbers in one word - -function pack1_get(word, n) { - return (word >>> n) & 1 -} - -function pack2_get(word, n) { - n = n << 1 - return (word >>> n) & 3 -} - -function pack4_get(word, n) { - n = n << 2 - return (word >>> n) & 15 -} - -function pack1_set(word, n, x) { - return (word & ~(1 << n)) | (x << n) -} - -function pack2_set(word, n, x) { - n = n << 1 - return (word & ~(3 << n)) | (x << n) -} - -function pack4_set(word, n, x) { - n = n << 2 - return (word & ~(15 << n)) | (x << n) -} - function clear_undo() { if (game.undo.length > 0) game.undo = [] @@ -1254,3 +1809,4 @@ function map_delete(map, item) { } } } + diff --git a/tools/gendata.js b/tools/gendata.js index e7f5df6..4fd79a2 100644 --- a/tools/gendata.js +++ b/tools/gendata.js @@ -151,9 +151,12 @@ function def_town(name) { function def_loc(type, econ, cities, depts) { let name = cities.join(" / ") let loc_names = cities.concat(depts) + for (let n of loc_names) + if (space_name.indexOf(n) < 0) + console.log("not a space: " + n) let loc_spaces = loc_names.map(n => space_name.indexOf(n)) let ix = spaces.length - spaces.push({ type, name, id: to_ascii(name), econ, adjacent: loc_spaces.filter(x=>x>0) }) + spaces.push({ type, id: to_ascii(name), econ, adjacent: loc_spaces.filter(x=>x>0) }) for (let loc of loc_spaces) if (loc >= 0) add(spaces[loc].adjacent, ix) @@ -169,7 +172,11 @@ function adjacent(an, bn) { } // Cities + +data.first_space = 0 + data.first_pop = 1 + data.first_city = spaces.length def_space("city", 8, "Bogotá") @@ -186,9 +193,10 @@ def_space("city", 1, "Sincelejo") data.last_city = spaces.length-1 +// Departments + data.first_dept = spaces.length -// Departments def_space("forest", 1, "Atlántico") def_space("forest", 1, "Chocó") def_space("forest", 1, "Nariño") @@ -211,12 +219,13 @@ def_space("forest", 0, "Amazonas") data.last_dept = spaces.length-1 +// Foreign Countries + data.first_foreign = spaces.length -// Foreign Countries -def_space("foreign", 0, "Brasil") -def_space("foreign", 0, "Ecuador") def_space("foreign", 0, "Panamá") +def_space("foreign", 0, "Ecuador") +def_space("foreign", 0, "Brasil") def_space("foreign", 0, "Perú") def_space("foreign", 0, "Venezuela") @@ -239,9 +248,9 @@ def_loc("pipeline", 2, [ "Sincelejo", "Medellín"], [ "Chocó", "Antioquia" ]) def_loc("pipeline", 1, [ "Medellín", "Ibagué"], [ "Chocó", "Antioquia" ]) def_loc("pipeline", 1, [ "Ibagué", "Cali"], [ "Chocó", "Huila" ]) -def_loc("pipeline", 2, [ "Bucaramanga", "Ibagué", "Bogotá" ], [ "Antioquia", "Santa", "Huila" ]) +def_loc("pipeline", 2, [ "Bucaramanga", "Ibagué", "Bogotá" ], [ "Antioquia", "Santander", "Huila" ]) def_loc("pipeline", 2, [ "Bogotá", "Neiva" ], [ "Huila", "Meta West" ]) -def_loc("pipeline", 3, [ "Cúcuta", "Arauca" ], [ "Venezuela", "Arauca", "Santaner" ]) +def_loc("pipeline", 3, [ "Cúcuta", "Arauca" ], [ "Venezuela", "Arauca", "Santander" ]) def_loc("pipeline", 2, [ "Bogotá", "Yopal" ], [ "Santander", "Arauca", "Meta East"]) let ayacucho = [ @@ -259,6 +268,8 @@ for (let a of ayacucho) { data.last_loc = spaces.length-1 +data.last_space = spaces.length-1 + // City in Dept adjacent("Santa Marta", "Cesar") @@ -394,9 +405,9 @@ adjacent("Amazonas", "Putumayo") data.coastal_spaces = [ "Cesar", "Atlántico", "Chocó", "Nariño" ].map(n=>space_name.indexOf(n)).sort((a,b)=>a-b) -for (let i = 1; i < spaces.length; ++i) +for (let i = 0; i < spaces.length; ++i) { spaces[i].adjacent.sort((a,b)=>a-b) - +} data.card_name = card_name data.card_order = card_order @@ -404,8 +415,8 @@ data.space_name = space_name data.spaces = spaces let pc_index = 0 -let pc_first = data.first_piece = [ [ 0, 0, 0, 0 ], [ 0, 0 ], [ 0, 0 ], [ 0, 0 ] ] -let pc_last = data.last_piece = [ [ -1, -1, -1, -1 ], [ -1, -1 ], [ -1, -1 ], [ -1, -1 ] ] +let pc_first = data.first_piece = [ [ 0, 0, 0, 0, 0 ], [ 0, 0 ], [ 0, 0 ], [ 0, 0 ] ] +let pc_last = data.last_piece = [ [ -1, -1, -1, -1, -1 ], [ -1, -1 ], [ -1, -1 ], [ -1, -1 ] ] function def_piece(faction, type, count) { pc_first[faction][type] = pc_index pc_last[faction][type] = pc_index + count - 1 -- cgit v1.2.3