diff options
-rw-r--r-- | data.js | 1467 | ||||
-rw-r--r-- | play.html | 14 | ||||
-rw-r--r-- | play.js | 359 | ||||
-rw-r--r-- | rules.js | 587 | ||||
-rw-r--r-- | tools/gendata.js | 67 |
5 files changed, 595 insertions, 1899 deletions
@@ -1,1467 +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 - ], - "cards": [ - null, - { - "number": 1, - "name": "1st Division", - "order": [ - "Government", - "FARC", - "AUC", - "Cartels" - ] - }, - { - "number": 2, - "name": "Ospina & Mora", - "order": [ - "Government", - "FARC", - "AUC", - "Cartels" - ] - }, - { - "number": 3, - "name": "Tapias", - "order": [ - "Government", - "FARC", - "AUC", - "Cartels" - ] - }, - { - "number": 4, - "name": "Caño Limón - Coveñas", - "order": [ - "Government", - "FARC", - "Cartels", - "AUC" - ] - }, - { - "number": 5, - "name": "Occidental & Ecopetrol", - "order": [ - "Government", - "FARC", - "Cartels", - "AUC" - ] - }, - { - "number": 6, - "name": "Oil Spill", - "order": [ - "Government", - "FARC", - "Cartels", - "AUC" - ] - }, - { - "number": 7, - "name": "7th Special Forces", - "order": [ - "Government", - "AUC", - "FARC", - "Cartels" - ] - }, - { - "number": 8, - "name": "Fuerza Aérea Colombiana", - "order": [ - "Government", - "AUC", - "FARC", - "Cartels" - ] - }, - { - "number": 9, - "name": "High Mountain Battalions", - "order": [ - "Government", - "AUC", - "FARC", - "Cartels" - ] - }, - { - "number": 10, - "name": "Blackhawks", - "order": [ - "Government", - "AUC", - "Cartels", - "FARC" - ] - }, - { - "number": 11, - "name": "National Defense & Security Council", - "order": [ - "Government", - "AUC", - "Cartels", - "FARC" - ] - }, - { - "number": 12, - "name": "Plan Colombia", - "order": [ - "Government", - "AUC", - "Cartels", - "FARC" - ] - }, - { - "number": 13, - "name": "Plan Meteoro", - "order": [ - "Government", - "Cartels", - "FARC", - "AUC" - ] - }, - { - "number": 14, - "name": "Tres Esquinas", - "order": [ - "Government", - "Cartels", - "FARC", - "AUC" - ] - }, - { - "number": 15, - "name": "War Tax", - "order": [ - "Government", - "Cartels", - "FARC", - "AUC" - ] - }, - { - "number": 16, - "name": "Coffee Prices", - "order": [ - "Government", - "Cartels", - "AUC", - "FARC" - ] - }, - { - "number": 17, - "name": "Madrid Donors", - "order": [ - "Government", - "Cartels", - "AUC", - "FARC" - ] - }, - { - "number": 18, - "name": "NSPD-18", - "order": [ - "Government", - "Cartels", - "AUC", - "FARC" - ] - }, - { - "number": 19, - "name": "General Offensive", - "order": [ - "FARC", - "Government", - "AUC", - "Cartels" - ] - }, - { - "number": 20, - "name": "Mono Jojoy", - "order": [ - "FARC", - "Government", - "AUC", - "Cartels" - ] - }, - { - "number": 21, - "name": "Raúl Reyes", - "order": [ - "FARC", - "Government", - "AUC", - "Cartels" - ] - }, - { - "number": 22, - "name": "Alfonso Cano", - "order": [ - "FARC", - "Government", - "Cartels", - "AUC" - ] - }, - { - "number": 23, - "name": "DoD Contractors", - "order": [ - "FARC", - "Government", - "Cartels", - "AUC" - ] - }, - { - "number": 24, - "name": "Operación Jaque", - "order": [ - "FARC", - "Government", - "Cartels", - "AUC" - ] - }, - { - "number": 25, - "name": "Ejército de Liberación Nacional", - "order": [ - "FARC", - "AUC", - "Government", - "Cartels" - ] - }, - { - "number": 26, - "name": "Gramaje", - "order": [ - "FARC", - "AUC", - "Government", - "Cartels" - ] - }, - { - "number": 27, - "name": "Misil Antiaéreo", - "order": [ - "FARC", - "AUC", - "Government", - "Cartels" - ] - }, - { - "number": 28, - "name": "Hugo Chávez", - "order": [ - "FARC", - "AUC", - "Cartels", - "Government" - ] - }, - { - "number": 29, - "name": "Kill Zone", - "order": [ - "FARC", - "AUC", - "Cartels", - "Government" - ] - }, - { - "number": 30, - "name": "Peace Commission", - "order": [ - "FARC", - "AUC", - "Cartels", - "Government" - ] - }, - { - "number": 31, - "name": "Betancourt", - "order": [ - "FARC", - "Cartels", - "Government", - "AUC" - ] - }, - { - "number": 32, - "name": "Secuestrados", - "order": [ - "FARC", - "Cartels", - "Government", - "AUC" - ] - }, - { - "number": 33, - "name": "Sucumbíos", - "order": [ - "FARC", - "Cartels", - "Government", - "AUC" - ] - }, - { - "number": 34, - "name": "Airdropped AKs", - "order": [ - "FARC", - "Cartels", - "AUC", - "Government" - ] - }, - { - "number": 35, - "name": "Crop Substitution", - "order": [ - "FARC", - "Cartels", - "AUC", - "Government" - ] - }, - { - "number": 36, - "name": "Zona de Convivencia", - "order": [ - "FARC", - "Cartels", - "AUC", - "Government" - ] - }, - { - "number": 37, - "name": "Former Military", - "order": [ - "AUC", - "Government", - "FARC", - "Cartels" - ] - }, - { - "number": 38, - "name": "National Coordination Center", - "order": [ - "AUC", - "Government", - "FARC", - "Cartels" - ] - }, - { - "number": 39, - "name": "Soldados Campesinos", - "order": [ - "AUC", - "Government", - "FARC", - "Cartels" - ] - }, - { - "number": 40, - "name": "Demobilization", - "order": [ - "AUC", - "Government", - "Cartels", - "FARC" - ] - }, - { - "number": 41, - "name": "Mancuso", - "order": [ - "AUC", - "Government", - "Cartels", - "FARC" - ] - }, - { - "number": 42, - "name": "Senado & Cámara", - "order": [ - "AUC", - "Government", - "Cartels", - "FARC" - ] - }, - { - "number": 43, - "name": "Calima Front", - "order": [ - "AUC", - "FARC", - "Government", - "Cartels" - ] - }, - { - "number": 44, - "name": "Colombia Nueva", - "order": [ - "AUC", - "FARC", - "Government", - "Cartels" - ] - }, - { - "number": 45, - "name": "Los Derechos Humanos", - "order": [ - "AUC", - "FARC", - "Government", - "Cartels" - ] - }, - { - "number": 46, - "name": "Limpieza", - "order": [ - "AUC", - "FARC", - "Cartels", - "Government" - ] - }, - { - "number": 47, - "name": "Pinto & del Rosario", - "order": [ - "AUC", - "FARC", - "Cartels", - "Government" - ] - }, - { - "number": 48, - "name": "Unión Sindical Obrera", - "order": [ - "AUC", - "FARC", - "Cartels", - "Government" - ] - }, - { - "number": 49, - "name": "Bloques", - "order": [ - "AUC", - "Cartels", - "Government", - "FARC" - ] - }, - { - "number": 50, - "name": "Carabineros", - "order": [ - "AUC", - "Cartels", - "Government", - "FARC" - ] - }, - { - "number": 51, - "name": "Pipeline Repairs", - "order": [ - "AUC", - "Cartels", - "Government", - "FARC" - ] - }, - { - "number": 52, - "name": "Castaño", - "order": [ - "AUC", - "Cartels", - "FARC", - "Government" - ] - }, - { - "number": 53, - "name": "Criminal Air Force", - "order": [ - "AUC", - "Cartels", - "FARC", - "Government" - ] - }, - { - "number": 54, - "name": "Deserters & Defectors", - "order": [ - "AUC", - "Cartels", - "FARC", - "Government" - ] - }, - { - "number": 55, - "name": "DEA Agents", - "order": [ - "Cartels", - "Government", - "FARC", - "AUC" - ] - }, - { - "number": 56, - "name": "Drogas La Rebaja", - "order": [ - "Cartels", - "Government", - "FARC", - "AUC" - ] - }, - { - "number": 57, - "name": "Op Millennium", - "order": [ - "Cartels", - "Government", - "FARC", - "AUC" - ] - }, - { - "number": 58, - "name": "General Serrano", - "order": [ - "Cartels", - "Government", - "AUC", - "FARC" - ] - }, - { - "number": 59, - "name": "Salcedo", - "order": [ - "Cartels", - "Government", - "AUC", - "FARC" - ] - }, - { - "number": 60, - "name": "The Chess Player", - "order": [ - "Cartels", - "Government", - "AUC", - "FARC" - ] - }, - { - "number": 61, - "name": "Air Bridge", - "order": [ - "Cartels", - "FARC", - "Government", - "AUC" - ] - }, - { - "number": 62, - "name": "Amazonía", - "order": [ - "Cartels", - "FARC", - "Government", - "AUC" - ] - }, - { - "number": 63, - "name": "Narco-War", - "order": [ - "Cartels", - "FARC", - "Government", - "AUC" - ] - }, - { - "number": 64, - "name": "Cocaine Labs", - "order": [ - "Cartels", - "FARC", - "AUC", - "Government" - ] - }, - { - "number": 65, - "name": "Poppies", - "order": [ - "Cartels", - "FARC", - "AUC", - "Government" - ] - }, - { - "number": 66, - "name": "Tingo María", - "order": [ - "Cartels", - "FARC", - "AUC", - "Government" - ] - }, - { - "number": 67, - "name": "Mexican Traffickers", - "order": [ - "Cartels", - "AUC", - "Government", - "FARC" - ] - }, - { - "number": 68, - "name": "Narco-Subs", - "order": [ - "Cartels", - "AUC", - "Government", - "FARC" - ] - }, - { - "number": 69, - "name": "Riverines & Fast Boats", - "order": [ - "Cartels", - "AUC", - "Government", - "FARC" - ] - }, - { - "number": 70, - "name": "Ayahuasca Tourism", - "order": [ - "Cartels", - "AUC", - "FARC", - "Government" - ] - }, - { - "number": 71, - "name": "Darién", - "order": [ - "Cartels", - "AUC", - "FARC", - "Government" - ] - }, - { - "number": 72, - "name": "Sicarios", - "order": [ - "Cartels", - "AUC", - "FARC", - "Government" - ] - }, - { - "number": 73, - "name": "Propaganda!", - "order": null - }, - { - "number": 74, - "name": "Propaganda!", - "order": null - }, - { - "number": 75, - "name": "Propaganda!", - "order": null - }, - { - "number": 76, - "name": "Propaganda!", - "order": null - } - ], - "spaces": [ - { - "type": "city", - "id": "Bogota", - "name": "Bogotá", - "pop": 8, - "adjacent": [ - 35, - 42, - 43, - 45, - 19, - 22, - 14, - 20 - ] - }, - { - "type": "city", - "id": "Cali", - "name": "Cali", - "pop": 3, - "adjacent": [ - 12, - 13, - 20, - 33, - 37, - 41 - ] - }, - { - "type": "city", - "id": "Medellin", - "name": "Medellín", - "pop": 3, - "adjacent": [ - 12, - 18, - 39, - 40 - ] - }, - { - "type": "city", - "id": "Bucaramanga", - "name": "Bucaramanga", - "pop": 2, - "adjacent": [ - 18, - 19, - 42, - 47 - ] - }, - { - "type": "city", - "id": "Ibague", - "name": "Ibagué", - "pop": 2, - "adjacent": [ - 12, - 18, - 20, - 40, - 41, - 42 - ] - }, - { - "type": "city", - "id": "Santa Marta", - "name": "Santa Marta", - "pop": 2, - "adjacent": [ - 11, - 17, - 32, - 46 - ] - }, - { - "type": "city", - "id": "Cartagena", - "name": "Cartagena", - "pop": 1, - "adjacent": [ - 11, - 32, - 38 - ] - }, - { - "type": "city", - "id": "Cucuta", - "name": "Cúcuta", - "pop": 1, - "adjacent": [ - 19, - 31, - 44, - 49 - ] - }, - { - "type": "city", - "id": "Neiva", - "name": "Neiva", - "pop": 1, - "adjacent": [ - 14, - 16, - 20, - 34, - 43 - ] - }, - { - "type": "city", - "id": "Pasto", - "name": "Pasto", - "pop": 1, - "adjacent": [ - 13, - 16, - 20, - 28, - 33, - 34, - 36 - ] - }, - { - "type": "city", - "id": "Sincelejo", - "name": "Sincelejo", - "pop": 1, - "adjacent": [ - 11, - 12, - 18, - 38, - 39, - 48 - ] - }, - { - "type": "forest", - "id": "Atlantico", - "name": "Atlántico", - "pop": 1, - "adjacent": [ - 5, - 6, - 10, - 17, - 18, - 19, - 32, - 38, - 46, - 47, - 48, - 49 - ] - }, - { - "type": "forest", - "id": "Choco", - "name": "Chocó", - "pop": 1, - "adjacent": [ - 1, - 2, - 4, - 10, - 13, - 18, - 20, - 29, - 37, - 39, - 40, - 41 - ] - }, - { - "type": "forest", - "id": "Narino", - "name": "Nariño", - "pop": 1, - "adjacent": [ - 1, - 9, - 12, - 20, - 28, - 33, - 36, - 37 - ] - }, - { - "type": "forest", - "id": "Meta West", - "name": "Meta West", - "pop": 1, - "adjacent": [ - 0, - 8, - 15, - 16, - 20, - 22, - 35, - 43 - ] - }, - { - "type": "forest", - "id": "Guaviare", - "name": "Guaviare", - "pop": 1, - "adjacent": [ - 14, - 16, - 22, - 23, - 24, - 25, - 35 - ] - }, - { - "type": "forest", - "id": "Putumayo", - "name": "Putumayo", - "pop": 1, - "adjacent": [ - 8, - 9, - 14, - 15, - 20, - 25, - 26, - 28, - 30, - 34 - ] - }, - { - "type": "mountain", - "id": "Cesar", - "name": "Cesar", - "pop": 1, - "adjacent": [ - 5, - 11, - 18, - 19, - 31, - 46, - 47, - 48, - 49 - ] - }, - { - "type": "mountain", - "id": "Antioquia", - "name": "Antioquia", - "pop": 2, - "adjacent": [ - 2, - 3, - 4, - 10, - 11, - 12, - 17, - 19, - 20, - 39, - 40, - 42, - 46, - 47, - 48, - 49 - ] - }, - { - "type": "mountain", - "id": "Santander", - "name": "Santander", - "pop": 2, - "adjacent": [ - 0, - 3, - 7, - 11, - 17, - 18, - 20, - 21, - 22, - 31, - 45, - 46, - 47, - 48, - 49 - ] - }, - { - "type": "mountain", - "id": "Huila", - "name": "Huila", - "pop": 2, - "adjacent": [ - 0, - 1, - 4, - 8, - 9, - 12, - 13, - 14, - 16, - 18, - 19, - 33, - 34, - 41, - 42, - 43 - ] - }, - { - "type": "grassland", - "id": "Arauca", - "name": "Arauca", - "pop": 1, - "adjacent": [ - 19, - 22, - 23, - 31, - 44, - 45 - ] - }, - { - "type": "grassland", - "id": "Meta East", - "name": "Meta East", - "pop": 1, - "adjacent": [ - 0, - 14, - 15, - 19, - 21, - 23, - 35, - 45 - ] - }, - { - "type": "grassland", - "id": "Vichada", - "name": "Vichada", - "pop": 0, - "adjacent": [ - 15, - 21, - 22, - 24, - 31 - ] - }, - { - "type": "forest", - "id": "Guainia", - "name": "Guainía", - "pop": 0, - "adjacent": [ - 15, - 23, - 25, - 27, - 31 - ] - }, - { - "type": "forest", - "id": "Vaupes", - "name": "Vaupés", - "pop": 0, - "adjacent": [ - 15, - 16, - 24, - 26, - 27 - ] - }, - { - "type": "forest", - "id": "Amazonas", - "name": "Amazonas", - "pop": 0, - "adjacent": [ - 16, - 25, - 27, - 30 - ] - }, - { - "type": "foreign", - "id": "Brasil", - "name": "Brasil", - "pop": 0, - "adjacent": [ - 24, - 25, - 26 - ] - }, - { - "type": "foreign", - "id": "Ecuador", - "name": "Ecuador", - "pop": 0, - "adjacent": [ - 9, - 13, - 16, - 36 - ] - }, - { - "type": "foreign", - "id": "Panama", - "name": "Panamá", - "pop": 0, - "adjacent": [ - 12 - ] - }, - { - "type": "foreign", - "id": "Peru", - "name": "Perú", - "pop": 0, - "adjacent": [ - 16, - 26 - ] - }, - { - "type": "foreign", - "id": "Venezuela", - "name": "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 - ] - } - ] -} +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]]} if (typeof module !== 'undefined') module.exports = data @@ -49,6 +49,11 @@ <div class="role_user">-</div> </div> </div> + <div class="role" id="role_FARC"> + <div class="role_name"><span>FARC</span> + <div class="role_user">-</div> + </div> + </div> <div class="role" id="role_AUC"> <div class="role_name"><span>AUC</span> <div class="role_user">-</div> @@ -59,11 +64,6 @@ <div class="role_user">-</div> </div> </div> - <div class="role" id="role_FARC"> - <div class="role_name"><span>FARC</span> - <div class="role_user">-</div> - </div> - </div> </div> <div id="log"></div> </aside> @@ -147,13 +147,13 @@ <div id="pieces"> <div id="govt_cylinder" class="piece govt cylinder"></div> +<div id="farc_cylinder" class="piece farc cylinder"></div> <div id="auc_cylinder" class="piece auc cylinder"></div> <div id="cartels_cylinder" class="piece cartels cylinder"></div> -<div id="farc_cylinder" class="piece farc cylinder"></div> <div id="govt_resources" class="piece govt cylinder"></div> +<div id="farc_resources" class="piece farc cylinder"></div> <div id="auc_resources" class="piece auc cylinder"></div> <div id="cartels_resources" class="piece cartels cylinder"></div> -<div id="farc_resources" class="piece farc cylinder"></div> </div> </div> @@ -1,6 +1,32 @@ // TODO: FARC zone // TODO: terror markers +// Factions +const GOVT = 0 +const FARC = 1 +const AUC = 2 +const CARTELS = 3 + +// Pieces +const BASE = 0 +const GUERRILLA = 1 +const TROOPS = 2 +const POLICE = 3 + +const first_piece = data.first_piece +const last_piece = data.last_piece + +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 + // Spaces const AVAILABLE = -1 @@ -18,16 +44,17 @@ const INELIGIBLE = 8 let ui = { favicon: document.getElementById("favicon"), header: document.querySelector("header"), - player: { - govt: document.getElementById("role_Government"), - auc: document.getElementById("role_AUC"), - cartels: document.getElementById("role_Cartels"), - farc: document.getElementById("role_FARC"), - }, + player: [ + document.getElementById("role_Government"), + document.getElementById("role_FARC"), + document.getElementById("role_AUC"), + document.getElementById("role_Cartels"), + ], spaces: [], control: [], support: [], sabotage: [], + terror: [], next_card: document.getElementById("next_card"), this_card: document.getElementById("this_card"), deck_size: document.getElementById("deck_size"), @@ -41,39 +68,26 @@ let ui = { document.getElementById("SOP_C2"), document.getElementById("SOP_PASS"), ], - misc: { + tokens: { aid: document.getElementById("token_aid"), total_support: document.getElementById("token_total_support"), oppose_plus_bases: document.getElementById("token_oppose_plus_bases"), president: document.getElementById("token_el_presidente"), propaganda: document.getElementById("token_prop_card"), - shipments: [], - }, - govt: { - resources: document.getElementById("govt_resources"), - cylinder: document.getElementById("govt_cylinder"), - police: [], - troops: [], - bases: [], - }, - auc: { - resources: document.getElementById("auc_resources"), - cylinder: document.getElementById("auc_cylinder"), - guerrillas: [], - bases: [], - }, - cartels: { - resources: document.getElementById("cartels_resources"), - cylinder: document.getElementById("cartels_cylinder"), - guerrillas: [], - bases: [], - }, - farc: { - resources: document.getElementById("farc_resources"), - cylinder: document.getElementById("farc_cylinder"), - guerrillas: [], - bases: [], }, + pieces: [], + resources: [ + document.getElementById("govt_resources"), + document.getElementById("farc_resources"), + document.getElementById("auc_resources"), + document.getElementById("cartels_resources"), + ], + cylinder: [ + document.getElementById("govt_cylinder"), + document.getElementById("farc_cylinder"), + document.getElementById("auc_cylinder"), + document.getElementById("cartels_cylinder"), + ], } function create(t, p, ...c) { @@ -104,17 +118,6 @@ function on_click_action(evt) { send_action(evt.target.my_action, evt.target.my_id) } -const first_pop = 1 -const first_city = 0 -const last_city = 10 -const first_dept = 11 -const last_pop = 22 -const last_dept = 26 -const first_foreign = 27 -const last_foreign = 31 -const first_loc = 32 -const last_loc = 49 - const center_xy = { "Santa Marta": [682,436], "Cartagena": [500,512], @@ -305,25 +308,38 @@ function init_ui() { return e } - function create_piece_list(list, c, action, n, x, y) { - for (let i = 0; i < n; ++i) - list[i] = create_piece(c, action, i, x, y) + function create_piece_list(faction, type, c, x, y) { + for (let p = first_piece[faction][type]; p <= last_piece[faction][type]; ++p) + ui.pieces[p] = create_piece(c, "piece", p, x, y) } - create_piece_list(ui.misc.shipments, "token shipment", "shipment", 4, 0, 0) + ui.farc_zones = [ + document.getElementById("tokens").appendChild(create("div", { className: "hide" })), + document.getElementById("tokens").appendChild(create("div", { className: "hide" })), + document.getElementById("tokens").appendChild(create("div", { className: "hide" })), + ] - create_piece_list(ui.govt.police, "piece govt police", "govt_police", 30, 0, 4) - create_piece_list(ui.govt.troops, "piece govt troops", "govt_troops", 30, 0, 4) - create_piece_list(ui.govt.bases, "piece govt base", "govt_base", 3, -4, 10) + ui.shipments = [ + create_piece("token shipment", "shipment", 0, 0, 0), + create_piece("token shipment", "shipment", 1, 0, 0), + create_piece("token shipment", "shipment", 2, 0, 0), + create_piece("token shipment", "shipment", 3, 0, 0), + ] - create_piece_list(ui.auc.guerrillas, "piece auc guerrilla", "auc_guerrilla", 18, 2, 0) - create_piece_list(ui.auc.bases, "piece auc base", "auc_base", 6, -4, 10) + ui.pieces = [] - create_piece_list(ui.cartels.guerrillas, "piece cartels guerrilla", "cartels_guerrilla", 12, 2, 0) - create_piece_list(ui.cartels.bases, "piece cartels base", "cartels_base", 15, -4, 10) + create_piece_list(GOVT, BASE, "piece govt base", -4, 10) + create_piece_list(GOVT, POLICE, "piece govt police", 0, 4) + create_piece_list(GOVT, TROOPS, "piece govt troops", 0, 4) - create_piece_list(ui.farc.guerrillas, "piece farc guerrilla", "farc_guerrilla", 30, 2, 0) - create_piece_list(ui.farc.bases, "piece farc base", "farc_base", 9, -4, 10) + create_piece_list(FARC, BASE, "piece farc base", -4, 10) + create_piece_list(FARC, GUERRILLA, "piece farc guerrilla", 2, 0) + + create_piece_list(AUC, BASE, "piece auc base", -4, 10) + create_piece_list(AUC, GUERRILLA, "piece auc guerrilla", 2, 0) + + create_piece_list(CARTELS, GUERRILLA, "piece cartels guerrilla", 2, 0) + create_piece_list(CARTELS, BASE, "piece cartels base", -4, 10) register_action(ui.sop[1], "sop", 1) register_action(ui.sop[2], "sop", 2) @@ -334,21 +350,15 @@ function init_ui() { register_action(ui.sop[7], "sop", 7) } -function filter_piece_list(list, slist, elist, space) { - for (let i = 0; i < slist.length; ++i) - if (slist[i] === space) - list.push(elist[i]) +function filter_piece_list(list, space, faction, type) { + for (let i = first_piece[faction][type]; i <= last_piece[faction][type]; ++i) + if (view.pieces[i] === space) + list.push(ui.pieces[i]) } -function layout_cubes_available(slist, elist, space, xorig, yorig) { +function layout_available(faction, type, xorig, yorig) { let list = [] - filter_piece_list(list, slist, elist, space) - layout_pieces(list, xorig, yorig) -} - -function layout_guerrillas_available(slist, elist, space, xorig, yorig) { - let list = [] - filter_piece_list(list, slist, elist, space) + filter_piece_list(list, AVAILABLE, faction, type) layout_pieces(list, xorig, yorig) } @@ -424,14 +434,6 @@ const sop_xy = [ [SOP_C2, 1374-22, 632-24], ] -const SHORT_LIST = [ "govt", "auc", "cartels", "farc" ] -const SHORT = { - "Government": "govt", - "AUC": "auc", - "Cartels": "cartels", - "FARC": "farc", -} - function layout_sop() { let x, y, z @@ -439,13 +441,10 @@ function layout_sop() { x = 1164 - 22 y = 480 z = 1 - let order = data.cards[view.deck[0]].order - if (!order) - order = [ "Government", "AUC", "Cartels", "FARC" ] + let order = data.card_order[view.deck[0]] for (let faction of order) { - faction = SHORT[faction] - if (view[faction].cylinder === ELIGIBLE) { - place_piece(ui[faction].cylinder, x, y, z) + if (view.cylinder[faction] === ELIGIBLE) { + place_piece(ui.cylinder[faction], x, y, z) y += 40 z += 1 } @@ -455,9 +454,9 @@ function layout_sop() { x = 1510 - 22 y = 480 z = 1 - for (let faction of SHORT_LIST) { - if (view[faction].cylinder === INELIGIBLE) { - place_piece(ui[faction].cylinder, x, y, z) + for (let faction = 0; faction < 4; ++faction) { + if (view.cylinder[faction] === INELIGIBLE) { + place_piece(ui.cylinder[faction], x, y, z) y += 40 z += 1 } @@ -468,9 +467,9 @@ function layout_sop() { y = 688 - 28 z = 1 i = 0 - for (let faction of SHORT_LIST) { - if (view[faction].cylinder === SOP_PASS) { - place_piece(ui[faction].cylinder, x, y, z) + for (let faction = 0; faction < 4; ++faction) { + if (view.cylinder[faction] === SOP_PASS) { + place_piece(ui.cylinder[faction], x, y, z) x += 48 z += 1 if (++i === 2) { x -= 72; y += 28 } @@ -478,10 +477,9 @@ function layout_sop() { } for (let [i, x, y] of sop_xy) { - if (view.govt.cylinder === i) place_piece(ui.govt.cylinder, x, y) - if (view.auc.cylinder === i) place_piece(ui.auc.cylinder, x, y) - if (view.cartels.cylinder === i) place_piece(ui.cartels.cylinder, x, y) - if (view.farc.cylinder === i) place_piece(ui.farc.cylinder, x, y) + for (let faction = 0; faction < 4; ++faction) + if (view.cylinder[faction] === i) + place_piece(ui.cylinder[faction], x, y) } for (let i = 1; i <= 7; ++i) { @@ -495,10 +493,10 @@ function layout_sop() { function calc_oppose_bases() { let total = 0 for (let s = 0; s <= last_pop; ++s) { - if (view.misc.support[s] < 0) - total -= data.spaces[s].pop * view.misc.support[s] + if (view.support[s] < 0) + total -= data.spaces[s].pop * view.support[s] } - for (let b of view.farc.bases) + for (let b = first_piece[FARC][BASE]; b <= last_piece[FARC][BASE]; ++b) if (b !== AVAILABLE) total += 1 return total @@ -507,8 +505,8 @@ function calc_oppose_bases() { function calc_support() { let total = 0 for (let s = 0; s <= last_pop; ++s) { - if (view.misc.support[s] > 0) - total += data.spaces[s].pop * view.misc.support[s] + if (view.support[s] > 0) + total += data.spaces[s].pop * view.support[s] } return total } @@ -540,14 +538,12 @@ function layout_score() { let total_support = calc_support() let oppose_plus_bases = calc_oppose_bases() - if (total_support === i) list.push(ui.misc.total_support) - if (oppose_plus_bases === i) list.push(ui.misc.oppose_plus_bases) - if (view.misc.aid === i) list.push(ui.misc.aid) + if (total_support === i) list.push(ui.tokens.total_support) + if (oppose_plus_bases === i) list.push(ui.tokens.oppose_plus_bases) + if (view.aid === i) list.push(ui.tokens.aid) - if (view.govt.resources === i) list.push(ui.govt.resources) - if (view.auc.resources === i) list.push(ui.auc.resources) - if (view.cartels.resources === i) list.push(ui.cartels.resources) - if (view.farc.resources === i) list.push(ui.farc.resources) + for (let faction = 0; faction < 4; ++faction) + if (view.resources[faction] === i) list.push(ui.resources[faction]) if (i <= 30) y = 16 else if (i >= 77) y = 2486 @@ -572,21 +568,42 @@ function layout_score() { } } -function update_guerrillas_active(elts, guerrillas, active) { - for (let i = 0; i < guerrillas.length; ++i) { - if (active & (1 << i)) - elts[i].classList.add("active") +function update_guerrillas_underground(faction, type, underground) { + let p0 = first_piece[faction][type] + let p1 = last_piece[faction][type] + for (let i = 0, p = p0; p <= p1; ++i, ++p) { + if (underground & (1 << i)) + ui.pieces[p].classList.remove("active") else - elts[i].classList.remove("active") + ui.pieces[p].classList.add("active") } } -function on_update() { - ui.header.classList.toggle("govt", view.active === "Government") - ui.header.classList.toggle("auc", view.active === "AUC") - ui.header.classList.toggle("cartels", view.active === "Cartels") - ui.header.classList.toggle("farc", view.active === "FARC") +function action_piece_list(list, action) { + if (view.actions && view.actions[action]) { + for (let i = 0; i < list.length; ++i) { + if (set_has(view.actions[action], i)) { + list[i].classList.add("action") + } else { + list[i].classList.remove("action") + } + } + } +} +function layout_farc_zone(s, elt) { + let [x, y] = get_center_xy(s) + if (s <= last_pop) { + y -= 65 + } else { + x += 55 + } + elt.className = "token farc_zone" + elt.style.top = (y - 25) + "px" + elt.style.left = (x - 25) + "px" +} + +function on_update() { switch (player) { case "Government": favicon.href = "images/icon_govt.png"; break case "AUC": favicon.href = "images/icon_auc.png"; break @@ -594,19 +611,24 @@ function on_update() { case "FARC": favicon.href = "images/icon_farc.png"; break } - ui.misc.president.style.left = [ 0, "254px", "337px", "420px" ][view.misc.president] + ui.header.classList.toggle("govt", view.current === GOVT) + ui.header.classList.toggle("auc", view.current === AUC) + ui.header.classList.toggle("cartels", view.current === CARTELS) + ui.header.classList.toggle("farc", view.current === FARC) - ui.player.govt.classList.toggle("active", view.active === "Government") - ui.player.auc.classList.toggle("active", view.active === "AUC") - ui.player.cartels.classList.toggle("active", view.active === "Cartels") - ui.player.farc.classList.toggle("active", view.active === "FARC") + ui.player[GOVT].classList.toggle("active", view.current === GOVT) + ui.player[AUC].classList.toggle("active", view.current === AUC) + ui.player[CARTELS].classList.toggle("active", view.current === CARTELS) + ui.player[FARC].classList.toggle("active", view.current === FARC) + + ui.tokens.president.style.left = [ 0, "254px", "337px", "420px" ][view.president] if (view.propaganda > 0) { - ui.misc.propaganda.style.top = "744px" - ui.misc.propaganda.style.left = (1124 + 75 * (view.propaganda - 1)) + "px" + ui.tokens.propaganda.style.top = "744px" + ui.tokens.propaganda.style.left = (1124 + 75 * (view.propaganda - 1)) + "px" } else { - ui.misc.propaganda.style.top = "666px" - ui.misc.propaganda.style.left = "1029px" + ui.tokens.propaganda.style.top = "666px" + ui.tokens.propaganda.style.left = "1029px" } ui.this_card.className = "card card_" + view.deck[0] @@ -616,16 +638,19 @@ function on_update() { layout_sop() layout_score() - layout_cubes_available(view.govt.troops, ui.govt.troops, AVAILABLE, 114, 248) - layout_cubes_available(view.govt.police, ui.govt.police, AVAILABLE, 114, 448) - layout_guerrillas_available(view.auc.guerrillas, ui.auc.guerrillas, AVAILABLE, 196, 2370) - layout_guerrillas_available(view.cartels.guerrillas, ui.cartels.guerrillas, AVAILABLE, 1465, 1970) - layout_guerrillas_available(view.farc.guerrillas, ui.farc.guerrillas, AVAILABLE, 1396, 234) + layout_available(GOVT, TROOPS, 114, 248) + layout_available(GOVT, POLICE, 114, 448) + layout_available(FARC, GUERRILLA, 1396, 234) + layout_available(AUC, GUERRILLA, 196, 2370) + layout_available(CARTELS, GUERRILLA, 1465, 1970) + + for (let i = view.farc_zones.length; i < ui.farc_zones.length; ++i) + ui.farc_zones[i].className = "hide" let list = [] for (let s = 0; s < data.spaces.length; ++s) { if (s <= last_pop) { - switch (view.misc.support[s]) { + switch (view.support[s]) { case -2: ui.support[s].className = "token active_opposition"; break case -1: ui.support[s].className = "token passive_opposition"; break case 0: ui.support[s].className = "hide"; break @@ -635,75 +660,85 @@ function on_update() { } if (s >= first_loc && s <= last_loc) { - if (set_has(view.misc.sabotage, s)) + if (set_has(view.sabotage, s)) ui.sabotage[s].className = "token sabotage" else ui.sabotage[s].className = "hide" } if (s <= last_dept) { - if (set_has(view.misc.farc_zones, s)) - ui.control[s].className = "token farc_zone" - else switch (view.misc.control[s]) { - case 0: ui.control[s].className = "hide"; break - case 1: ui.control[s].className = "token govt_control"; break - case 2: ui.control[s].className = "token farc_control"; break - } + for (let i = 0; i < view.farc_zones.length; ++i) + if (view.farc_zones[i] === s) + layout_farc_zone(s, ui.farc_zones[i]) + if (view.govt_control & (1<<s)) + ui.control[s].className = "token govt_control" + else if (view.farc_control & (1<<s)) + ui.control[s].className = "token farc_control" + else + ui.control[s].className = "hide" } - update_guerrillas_active(ui.auc.guerrillas, view.auc.guerrillas, view.auc.active) - update_guerrillas_active(ui.cartels.guerrillas, view.cartels.guerrillas, view.cartels.active) - update_guerrillas_active(ui.farc.guerrillas, view.farc.guerrillas, view.farc.active) + update_guerrillas_underground(FARC, GUERRILLA, view.underground[FARC]) + update_guerrillas_underground(AUC, GUERRILLA, view.underground[AUC]) + update_guerrillas_underground(CARTELS, GUERRILLA, view.underground[CARTELS]) list.length = 0 - filter_piece_list(list, view.auc.guerrillas, ui.auc.guerrillas, s) - filter_piece_list(list, view.cartels.guerrillas, ui.cartels.guerrillas, s) - filter_piece_list(list, view.farc.guerrillas, ui.farc.guerrillas, s) - filter_piece_list(list, view.govt.troops, ui.govt.troops, s) - filter_piece_list(list, view.govt.police, ui.govt.police, s) + filter_piece_list(list, s, FARC, GUERRILLA) + filter_piece_list(list, s, AUC, GUERRILLA) + filter_piece_list(list, s, CARTELS, GUERRILLA) + filter_piece_list(list, s, GOVT, TROOPS) + filter_piece_list(list, s, GOVT, POLICE) - // TODO: associate shipments with other piece, not space - filter_piece_list(list, view.misc.shipments, ui.misc.shipments, s) + // TODO: shipments with other faction/piece, not space let xy = get_layout_xy(s) if (xy) layout_pieces(list, xy[0], xy[1]) list.length = 0 - filter_piece_list(list, view.govt.bases, ui.govt.bases, s) - filter_piece_list(list, view.auc.bases, ui.auc.bases, s) - filter_piece_list(list, view.farc.bases, ui.farc.bases, s) - filter_piece_list(list, view.cartels.bases, ui.cartels.bases, s) + filter_piece_list(list, s, GOVT, BASE) + filter_piece_list(list, s, FARC, BASE) + filter_piece_list(list, s, AUC, BASE) + filter_piece_list(list, s, CARTELS, BASE) xy = get_center_xy(s) if (xy) layout_space_bases(list, xy[0], xy[1], s <= last_city ? get_layout_radius(s) : 0) else - console.log("NO SPACE", s, data.spaces[s].name) + console.log("NO SPACE", s, data.space_name[s]) ui.spaces[s].classList.toggle("action", is_action("space", s)) } list.length = 0 - filter_piece_list(list, view.misc.shipments, ui.misc.shipments, AVAILABLE) + for (let i = 0; i < 4; ++i) + if (view.shipments[i] === AVAILABLE) + list.push(ui.shipments[i]) layout_available_bases(list, 1532, 1722, 2, 2, 89, 69) list.length = 0 - filter_piece_list(list, view.govt.bases, ui.govt.bases, AVAILABLE) + filter_piece_list(list, AVAILABLE, GOVT, BASE) layout_available_bases(list, 287 + 177, 371, 3, 1, 61, 0) list.length = 0 - filter_piece_list(list, view.auc.bases, ui.auc.bases, AVAILABLE) - layout_available_bases(list, 446 + 360, 2386, 6, 1, 61, 0) + filter_piece_list(list, AVAILABLE, FARC, BASE) + layout_available_bases(list, 446 + 543, 2295, 9, 1, 61, 0) list.length = 0 - filter_piece_list(list, view.farc.bases, ui.farc.bases, AVAILABLE) - layout_available_bases(list, 446 + 543, 2295, 9, 1, 61, 0) + filter_piece_list(list, AVAILABLE, AUC, BASE) + layout_available_bases(list, 446 + 360, 2386, 6, 1, 61, 0) list.length = 0 - filter_piece_list(list, view.cartels.bases, ui.cartels.bases, AVAILABLE) + filter_piece_list(list, AVAILABLE, CARTELS, BASE) layout_available_bases(list, 1373 + 183, 2117, 3, 5, 63, 63) + if (view.actions && view.actions.piece) + for (let i = 0; i < ui.pieces.length; ++i) + ui.pieces[i].classList.toggle("action", set_has(view.actions.piece, i)) + else + for (let i = 0; i < ui.pieces.length; ++i) + ui.pieces[i].classList.remove("action") + action_button("train", "Train") action_button("patrol", "Patrol") action_button("sweep", "Sweep") @@ -744,13 +779,13 @@ function on_blur_card_tip(c) { function sub_card(match, p1) { let x = p1 | 0 - let n = data.cards[x].name + let n = data.card_name[x] return `<span class="tip" onmouseenter="on_focus_card_tip(${x})" onmouseleave="on_blur_card_tip(${x})" onclick="on_click_card_tip(${x})">${n}</span>` } function sub_space(match, p1) { let x = p1 | 0 - let n = data.spaces[x].name + let n = data.space_name[x] return `<span class="tip" onmouseenter="on_focus_space_tip(${x})" onmouseleave="on_blur_space_tip(${x})" onclick="on_click_space_tip(${x})">${n}</span>` } @@ -6,15 +6,44 @@ let view = null const data = require("./data.js") -const GOVT = "Government" -const AUC = "AUC" -const CARTELS = "Cartels" -const FARC = "FARC" - -// For 3 and 2 player games -const AUC_CARTELS = "AUC + Cartels" -const GOVT_AUC = "Government + AUC" -const FARC_CARTELS = "FARC + Cartels" +// Role names +const NAME_GOVT = "Government" +const NAME_FARC = "FARC" +const NAME_AUC = "AUC" +const NAME_CARTELS = "Cartels" +const NAME_GOVT_AUC = "Government + AUC" +const NAME_FARC_CARTELS = "FARC + Cartels" +const NAME_AUC_CARTELS = "AUC + Cartels" + +const faction_name = [ NAME_GOVT, NAME_FARC, NAME_AUC, NAME_CARTELS ] + +// Factions +const GOVT = 0 +const FARC = 1 +const AUC = 2 +const CARTELS = 3 + +// Pieces +const BASE = 0 +const GUERRILLA = 1 +const TROOPS = 2 +const POLICE = 3 + +const space_name = data.space_name + +const first_piece = data.first_piece +const last_piece = data.last_piece + +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 // Sequence of Play options const ELIGIBLE = 0 @@ -34,28 +63,15 @@ const NEUTRAL = 0 const PASSIVE_OPPOSITION = -1 const ACTIVE_OPPOSITION = -2 -// Control ? -const UNCONTROLLED = 0 -const CTL_GOVERNMENT = 1 -const CTL_AUC = 2 -const CTL_CARTELS = 3 -const CTL_FARC = 4 +// Control +const CTL_NEUTRAL = 0 +const CTL_GOVT = 1 +const CTL_FARC = 2 const SAMPER = 1 const PASTRANA = 2 const URIBE = 3 -const first_pop = 1 -const first_city = 0 -const last_city = 10 -const first_dept = 11 -const last_pop = 22 -const last_dept = 26 -const first_foreign = 27 -const last_foreign = 31 -const first_loc = 32 -const last_loc = 49 - const AVAILABLE = -1 // Cities @@ -102,10 +118,10 @@ const COASTAL_SPACES = [ ATLANTICO, CHOCO, NARINO, CESAR ] exports.roles = function (scenario) { if (scenario.startsWith("2P")) - return [ GOVT_AUC, FARC_CARTELS ] + return [ NAME_GOVT_AUC, NAME_FARC_CARTELS ] if (scenario.startsWith("3P")) - return [ GOVT, FARC, AUC_CARTELS ] - return [ GOVT, AUC, CARTELS, FARC ] + return [ NAME_GOVT, NAME_FARC, NAME_AUC_CARTELS ] + return [ NAME_GOVT, NAME_FARC, NAME_AUC, NAME_CARTELS ] } exports.scenarios = [ @@ -122,22 +138,32 @@ exports.scenarios = [ function load_game(state) { game = state - if (game.scenario !== 4) - game.active = game.save_active } function save_game() { + if (game.scenario === 4) { + if (game.current === GOVT) + game.active = NAME_GOVT + if (game.current === FARC) + game.active = NAME_FARC + if (game.current === AUC) + game.active = NAME_AUC + if (game.current === CARTELS) + game.active = NAME_CARTELS + } if (game.scenario === 3) { - game.save_active = game.active - if (game.active === AUC || game.active === CARTELS) - game.active = AUC_CARTELS + if (game.current === GOVT) + game.active = NAME_GOVT + if (game.current === FARC) + game.active = NAME_FARC + if (game.current === AUC || game.current === CARTELS) + game.active = NAME_AUC_CARTELS } if (game.scenario === 2) { - game.save_active = game.active - if (game.active === GOVT || game.active === AUC) - game.active = GOVT_AUC - if (game.active === FARC || game.active === CARTELS) - game.active = FARC_CARTELS + if (game.current === GOVT || game.current === AUC) + game.active = NAME_GOVT_AUC + if (game.current === FARC || game.current === CARTELS) + game.active = NAME_FARC_CARTELS } return game } @@ -147,53 +173,29 @@ exports.setup = function (seed, scenario, options) { seed, log: [], undo: [], + active: null, scenario: 4, - active: null, + current: 0, state: null, op_spaces: null, sa_spaces: null, deck: [], - misc: { - aid: 0, - president: 0, - shipments: [ AVAILABLE, AVAILABLE, AVAILABLE, AVAILABLE ], - control: Array(27).fill(0), - support: Array(23).fill(NEUTRAL), - farc_zones: [], - terror: [], - sabotage: [], - }, - govt: { - cylinder: ELIGIBLE, - resources: 0, - troops: Array(30).fill(AVAILABLE), - police: Array(30).fill(AVAILABLE), - bases: Array(3).fill(AVAILABLE), - }, - auc: { - cylinder: ELIGIBLE, - resources: 0, - guerrillas: Array(18).fill(AVAILABLE), - bases: Array(6).fill(AVAILABLE), - active: 0, - }, - cartels: { - cylinder: ELIGIBLE, - resources: 0, - guerrillas: Array(12).fill(AVAILABLE), - bases: Array(15).fill(AVAILABLE), - active: 0, - }, - farc: { - cylinder: ELIGIBLE, - resources: 0, - guerrillas: Array(30).fill(AVAILABLE), - bases: Array(9).fill(AVAILABLE), - active: 0, - }, + president: 0, + aid: 0, + cylinder: [ ELIGIBLE, ELIGIBLE, ELIGIBLE, ELIGIBLE ], + resources: [ 0, 0, 0, 0 ], + shipments: [ AVAILABLE, AVAILABLE, AVAILABLE, AVAILABLE ], + pieces: Array(153).fill(AVAILABLE), + underground: [ 0, 0, -1, -1 ], + farc_control: 0, + govt_control: 0, + support: Array(23).fill(NEUTRAL), + farc_zones: [], + terror: [], + sabotage: [], } if (scenario.startsWith("3P")) @@ -229,12 +231,12 @@ exports.setup = function (seed, scenario, options) { } function setup_standard() { - game.misc.aid = 9 - game.misc.president = SAMPER - game.govt.resources = 40 - game.auc.resources = 10 - game.cartels.resources = 10 - game.farc.resources = 10 + game.aid = 9 + game.president = SAMPER + game.resources[GOVT] = 40 + game.resources[AUC] = 10 + game.resources[CARTELS] = 10 + game.resources[FARC] = 10 set_support(ATLANTICO, ACTIVE_SUPPORT) set_support(SANTANDER, ACTIVE_SUPPORT) @@ -250,81 +252,81 @@ function setup_standard() { set_support(PUTUMAYO, ACTIVE_OPPOSITION) set_support(NARINO, ACTIVE_OPPOSITION) - place_piece(game.govt.troops, 3, BOGOTA) - place_piece(game.govt.troops, 3, MEDELLIN) - place_piece(game.govt.troops, 3, CALI) - place_piece(game.govt.troops, 3, SANTANDER) - place_piece(game.govt.police, 2, BOGOTA) + place_piece(GOVT, TROOPS, 3, BOGOTA) + place_piece(GOVT, TROOPS, 3, MEDELLIN) + place_piece(GOVT, TROOPS, 3, CALI) + place_piece(GOVT, TROOPS, 3, SANTANDER) + place_piece(GOVT, POLICE, 2, BOGOTA) for (let s = first_city; s <= last_city; ++s) if (s !== BOGOTA) - place_piece(game.govt.police, 1, s) - place_piece(game.govt.bases, 1, SANTANDER) - - place_piece(game.farc.guerrillas, 1, NARINO) - place_piece(game.farc.guerrillas, 1, CHOCO) - place_piece(game.farc.guerrillas, 1, SANTANDER) - place_piece(game.farc.guerrillas, 1, HUILA) - place_piece(game.farc.guerrillas, 1, ARAUCA) - place_piece(game.farc.guerrillas, 1, META_EAST) - place_piece(game.farc.guerrillas, 2, META_WEST) - place_piece(game.farc.guerrillas, 2, GUAVIARE) - place_piece(game.farc.guerrillas, 2, PUTUMAYO) - place_piece(game.farc.bases, 1, CHOCO) - place_piece(game.farc.bases, 1, HUILA) - place_piece(game.farc.bases, 1, ARAUCA) - place_piece(game.farc.bases, 1, META_EAST) - place_piece(game.farc.bases, 1, META_WEST) - place_piece(game.farc.bases, 1, GUAVIARE) - - place_piece(game.auc.guerrillas, 1, ATLANTICO) - place_piece(game.auc.guerrillas, 1, ANTIOQUIA) - place_piece(game.auc.guerrillas, 1, SANTANDER) - place_piece(game.auc.guerrillas, 1, ARAUCA) - place_piece(game.auc.guerrillas, 1, GUAVIARE) - place_piece(game.auc.guerrillas, 1, PUTUMAYO) - place_piece(game.auc.bases, 1, ANTIOQUIA) - - place_piece(game.cartels.guerrillas, 1, CALI) - place_piece(game.cartels.guerrillas, 1, PUTUMAYO) - place_piece(game.cartels.bases, 1, CALI) - place_piece(game.cartels.bases, 1, META_EAST) - place_piece(game.cartels.bases, 1, META_WEST) - place_piece(game.cartels.bases, 1, GUAVIARE) - place_piece(game.cartels.bases, 2, PUTUMAYO) + place_piece(GOVT, POLICE, 1, s) + place_piece(GOVT, BASE, 1, SANTANDER) + + place_piece(FARC, GUERRILLA, 1, NARINO) + place_piece(FARC, GUERRILLA, 1, CHOCO) + place_piece(FARC, GUERRILLA, 1, SANTANDER) + place_piece(FARC, GUERRILLA, 1, HUILA) + place_piece(FARC, GUERRILLA, 1, ARAUCA) + place_piece(FARC, GUERRILLA, 1, META_EAST) + place_piece(FARC, GUERRILLA, 2, META_WEST) + place_piece(FARC, GUERRILLA, 2, GUAVIARE) + place_piece(FARC, GUERRILLA, 2, PUTUMAYO) + place_piece(FARC, BASE, 1, CHOCO) + place_piece(FARC, BASE, 1, HUILA) + place_piece(FARC, BASE, 1, ARAUCA) + place_piece(FARC, BASE, 1, META_EAST) + place_piece(FARC, BASE, 1, META_WEST) + place_piece(FARC, BASE, 1, GUAVIARE) + + place_piece(AUC, GUERRILLA, 1, ATLANTICO) + place_piece(AUC, GUERRILLA, 1, ANTIOQUIA) + place_piece(AUC, GUERRILLA, 1, SANTANDER) + place_piece(AUC, GUERRILLA, 1, ARAUCA) + place_piece(AUC, GUERRILLA, 1, GUAVIARE) + place_piece(AUC, GUERRILLA, 1, PUTUMAYO) + place_piece(AUC, BASE, 1, ANTIOQUIA) + + place_piece(CARTELS, GUERRILLA, 1, CALI) + place_piece(CARTELS, GUERRILLA, 1, PUTUMAYO) + place_piece(CARTELS, BASE, 1, CALI) + place_piece(CARTELS, BASE, 1, META_EAST) + place_piece(CARTELS, BASE, 1, META_WEST) + place_piece(CARTELS, BASE, 1, GUAVIARE) + place_piece(CARTELS, BASE, 2, PUTUMAYO) } function setup_quick() { - place_piece(game.cartels.guerrillas, 4, MEDELLIN) - place_piece(game.cartels.bases, 1, MEDELLIN) + place_piece(CARTELS, GUERRILLA, 4, MEDELLIN) + place_piece(CARTELS, BASE, 1, MEDELLIN) set_support(CALI, ACTIVE_SUPPORT) - place_piece(game.govt.police, 4, CALI) - remove_piece(game.cartels.guerrillas, 1, CALI) - remove_piece(game.cartels.bases, 1, CALI) + place_piece(GOVT, POLICE, 4, CALI) + remove_piece(CARTELS, GUERRILLA, 1, CALI) + remove_piece(CARTELS, BASE, 1, CALI) - place_piece(game.govt.troops, 6, BOGOTA) + place_piece(GOVT, TROOPS, 6, BOGOTA) - place_piece(game.auc.bases, 1, SANTANDER) + place_piece(AUC, BASE, 1, SANTANDER) set_support(ARAUCA, NEUTRAL) - place_piece(game.auc.guerrillas, 1, ARAUCA) + place_piece(AUC, GUERRILLA, 1, ARAUCA) - set_add(game.misc.farc_zones, META_WEST) - place_piece(game.farc.guerrillas, 4, META_WEST) + set_add(game.farc_zones, META_WEST) + place_piece(FARC, GUERRILLA, 4, META_WEST) set_support(HUILA, ACTIVE_OPPOSITION) - place_piece(game.farc.guerrillas, 3, HUILA) - place_piece(game.auc.guerrillas, 2, HUILA) - place_piece(game.cartels.bases, 1, HUILA) + place_piece(FARC, GUERRILLA, 3, HUILA) + place_piece(AUC, GUERRILLA, 2, HUILA) + place_piece(CARTELS, BASE, 1, HUILA) - place_piece(game.farc.guerrillas, 2, VAUPES) + place_piece(FARC, GUERRILLA, 2, VAUPES) - game.auc.resources = 5 - game.farc.resources = 10 - game.cartels.resources = 20 - game.govt.resources = 30 + game.resources[AUC] = 5 + game.resources[FARC] = 10 + game.resources[CARTELS] = 20 + game.resources[GOVT] = 30 - game.misc.president = PASTRANA + game.president = PASTRANA } function shuffle_all_cards() { @@ -359,60 +361,93 @@ function setup_deck(count, a, b) { } function set_support(place, amount) { - game.misc.support[place] = amount + game.support[place] = amount } function get_support(place, amount) { - return game.misc.support[place] + return game.support[place] } -function place_piece(list, count, where) { - for (let i = 0; i < list.length && count > 0; ++i) { - if (list[i] < 0) { - list[i] = where +function place_piece(faction, type, count, where) { + for (let p = first_piece[faction][type]; count > 0; ++p) { + if (game.pieces[p] < 0) { + game.pieces[p] = where --count } } - if (count !== 0) - throw Error("bad piece count") } -function remove_piece(list, count, where) { - for (let i = 0; i < list.length && count > 0; ++i) { - if (list[i] === where) { - list[i] = AVAILABLE +function remove_piece(faction, type, count, where) { + for (let p = first_piece[faction][type]; count > 0; ++p) { + if (game.pieces[p] === where) { + game.pieces[p] = AVAILABLE --count } } - if (count !== 0) - throw Error("bad piece count") } -function count_pieces_imp(s, list) { +function count_pieces_imp(s, faction, type) { + let first = first_piece[faction][type] + let last = last_piece[faction][type] let n = 0 - for (let i = 0; i < list.length; ++i) - if (list[i] === s) + for (let p = first; p <= last; ++p) + if (game.pieces[p] === s) ++n return n } 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, game.govt.troops) + - count_pieces_imp(s, game.govt.police) + - count_pieces_imp(s, game.govt.bases) - let a = count_pieces_imp(s, game.auc.guerrillas) + - count_pieces_imp(s, game.auc.bases) - let c = count_pieces_imp(s, game.cartels.guerrillas) + - count_pieces_imp(s, game.cartels.bases) - let f = count_pieces_imp(s, game.farc.guerrillas) + - count_pieces_imp(s, game.farc.bases) + 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) if (g > a + c + f) - game.misc.control[s] = 1 + game.govt_control |= (1 << s) else if (f > g + a + c) - game.misc.control[s] = 2 - else - game.misc.control[s] = 0 + game.farc_control |= (1 << s) + } +} + +function is_city(s) { + return s <= last_city +} + +function has_govt_base(s) { + return set_has(game.govt.bases, s) +} + +function is_underground(p) { + for (let faction = 1; faction < 4; ++faction) { + let p0 = first_piece[faction][GUERRILLA] + let p1 = last_piece[faction][GUERRILLA] + if (p >= p0 && p <= p1) + return game.underground[faction] & (1 << (p - p0)) + } +} + +function set_underground(p) { + for (let faction = 1; faction < 4; ++faction) { + let p0 = first_piece[faction][GUERRILLA] + let p1 = last_piece[faction][GUERRILLA] + if (p >= p0 && p <= p1) + game.underground[faction] |= (1 << (p - p0)) + } +} + +function set_active(p) { + for (let faction = 1; faction < 4; ++faction) { + let p0 = first_piece[faction][GUERRILLA] + let p1 = last_piece[faction][GUERRILLA] + if (p >= p0 && p <= p1) + game.underground[faction] &= ~(1 << (p - p0)) } } @@ -430,44 +465,29 @@ function goto_card() { } function adjust_eligibility(faction) { - if (faction.cylinder === INELIGIBLE || faction.cylinder === SOP_PASS) - faction.cylinder = ELIGIBLE - else if (faction.cylinder !== ELIGIBLE) - faction.cylinder = INELIGIBLE + if (game.cylinder[faction] === INELIGIBLE || game.cylinder[faction] === SOP_PASS) + game.cylinder[faction] = ELIGIBLE + else if (game.cylinder[faction] !== ELIGIBLE) + game.cylinder[faction] = INELIGIBLE } function end_card() { - adjust_eligibility(game.govt) - adjust_eligibility(game.auc) - adjust_eligibility(game.cartels) - adjust_eligibility(game.farc) + adjust_eligibility(GOVT) + adjust_eligibility(FARC) + adjust_eligibility(AUC) + adjust_eligibility(CARTELS) clear_undo() array_remove(game.deck, 0) goto_card() } -function current_faction() { - switch (game.active) { - case GOVT: return game.govt - case AUC: return game.auc - case CARTELS: return game.cartels - case FARC: return game.farc - } -} - function is_eligible(faction) { - switch (faction) { - case GOVT: return game.govt.cylinder === ELIGIBLE - case AUC: return game.auc.cylinder === ELIGIBLE - case CARTELS: return game.cartels.cylinder === ELIGIBLE - case FARC: return game.farc.cylinder === ELIGIBLE - } - return false + return game.cylinder[faction] === ELIGIBLE } function next_eligible_faction() { - let order = data.cards[this_card()].order + let order = data.card_order[this_card()] for (let faction of order) if (is_eligible(faction)) return faction @@ -476,10 +496,10 @@ function next_eligible_faction() { function did_option(e) { return ( - game.govt.cylinder === e || - game.auc.cylinder === e || - game.cartels.cylinder === e || - game.farc.cylinder === e + game.cylinder[GOVT] === e || + game.cylinder[FARC] === e || + game.cylinder[AUC] === e || + game.cylinder[CARTELS] === e ) } @@ -503,16 +523,16 @@ function resume_event_card() { } function goto_eligible1() { - game.active = next_eligible_faction() - if (game.active === null) + game.current = next_eligible_faction() + if (game.current === null) end_card() else game.state = "eligible1" } function goto_eligible2() { - game.active = next_eligible_faction() - if (game.active === null) + game.current = next_eligible_faction() + if (game.current === null) end_card() else game.state = "eligible2" @@ -527,11 +547,10 @@ states.eligible1 = { gen_action("sop", SOP_1ST_EVENT) gen_action("sop", SOP_PASS) }, - sop(e) { + sop(option) { push_undo() - let faction = current_faction() - faction.cylinder = e - switch (e) { + game.cylinder[game.current] = option + switch (option) { case SOP_PASS: goto_pass() break @@ -560,11 +579,10 @@ states.eligible2 = { gen_action("sop", SOP_2ND_OP_AND_SA) gen_action("sop", SOP_PASS) }, - sop(e) { + sop(option) { push_undo() - let faction = current_faction() - faction.cylinder = e - switch (e) { + game.cylinder[game.current] = option + switch (option) { case SOP_PASS: goto_pass() break @@ -582,12 +600,11 @@ states.eligible2 = { } function goto_pass() { - log_h2(game.active + " - Pass") - let faction = current_faction() - if (game.active === GOVT) - faction.resources += 3 + log_h2(faction_name[game.current] + " - Pass") + if (game.current === GOVT) + game.resources[game.current] += 3 else - faction.resources += 1 + game.resources[game.current] += 1 resume_event_card() } @@ -611,27 +628,27 @@ states.limop_or_event = { } function goto_event() { - log_h2(game.active + " - Event") + log_h2(faction_name[game.current] + " - Event") log("TODO: Event") resume_event_card() } function goto_op_only() { - log_h2(game.active + " - Op only") + log_h2(faction_name[game.current] + " - Op Only") game.state = "op" game.op_spaces = [] game.sa_spaces = null } function goto_op_and_sa() { - log_h2(game.active + " - Op + Special") + log_h2(faction_name[game.current] + " - Op + Special") game.state = "op" game.op_spaces = [] game.sa_spaces = [] } function goto_limop() { - log_h2(game.active + " - LimOp") + log_h2(faction_name[game.current] + " - LimOp") game.state = "op" game.op_spaces = [] game.sa_spaces = null @@ -647,7 +664,7 @@ function can_use_special_activity() { states.op = { prompt() { view.prompt = "Choose an Operation." - if (game.active === GOVT) { + if (game.current === GOVT) { view.actions.train = 1 view.actions.patrol = 1 view.actions.sweep = 1 @@ -658,6 +675,7 @@ states.op = { view.actions.attack = 1 view.actions.terror = 1 } + view.actions.remove = 1 }, train() { @@ -701,6 +719,35 @@ states.op = { log_h3("Terror") game.state = "terror" }, + + remove() { + push_undo() + game.save_state = game.state + game.state = "remove" + }, +} + +function for_each_own_piece(f) { + f(p) +} + +states.remove = { + 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 + }, + piece(p) { + push_undo() + game.pieces[p] = AVAILABLE + }, + done() { + game.state = game.save_state + game.save_state = 0 + } } states.train = { @@ -736,6 +783,36 @@ states.train = { 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 + } else { + game.state = "train_base_or_civic" + } + }, +} + +function gen_select_available(action, list) { + for (let i = list.length; i-- > 0; ) { + if (list[i] === AVAILABLE) { + gen_action(action, i) + return + } + } + for (let i = 0; i < list.length; ++i) + gen_action(action, i) +} + +states.train_place_cubes = { + prompt() { + view.prompt = `Train in ${space_name[game.where]}: Place up to ${game.count} cubes.` + + if (game.selected < 0) { + gen_select_available("govt_police", game.govt.police) + gen_select_available("govt_troops", game.govt.troops) + } }, } @@ -744,6 +821,7 @@ states.train = { function goto_game_over(result, victory) { game = { ...game } // make a copy so we can add properties! game.state = "game_over" + game.current = -1 game.active = "None" game.result = result game.victory = victory @@ -804,20 +882,27 @@ function gen_action(action, argument) { set_add(view.actions[action], argument) } -function is_current_active(current) { - switch (current) { - case GOVT_AUC: - return game.active === GOVT || game.active === AUC - case FARC_CARTELS: - return game.active === FARC || game.active === CARTELS - case AUC_CARTELS: - return game.active === AUC || game.active === CARTELS - default: - return game.active === current +function is_current_role(role) { + switch (role) { + case NAME_GOVT_AUC: + return game.current === GOVT || game.current === AUC + case NAME_FARC_CARTELS: + return game.current === FARC || game.current === CARTELS + case NAME_AUC_CARTELS: + return game.current === AUC || game.current === CARTELS + case NAME_GOVT: + return game.current === GOVT + case NAME_FARC: + return game.current === FARC + case NAME_AUC: + return game.current === AUC + case NAME_CARTELS: + return game.current === CARTELS } + return false } -exports.view = function (state, current) { +exports.view = function (state, role) { load_game(state) let this_card = game.deck[0] @@ -825,31 +910,37 @@ exports.view = function (state, current) { let deck_size = Math.max(0, game.deck.length - 2) view = { - active: game.active, prompt: null, actions: null, log: game.log, + current: game.current, deck: [ this_card, next_card, deck_size ], - op_spaces: game.op_spaces, - sa_spaces: game.sa_spaces, - misc: game.misc, - govt: game.govt, - auc: game.auc, - cartels: game.cartels, - farc: game.farc, + president: game.president, + aid: game.aid, + cylinder: game.cylinder, + resources: game.resources, + shipments: game.shipments, + pieces: game.pieces, + underground: game.underground, + govt_control: game.govt_control, + farc_control: game.farc_control, + support: game.support, + farc_zones: game.farc_zones, + terror: game.terror, + sabotage: game.sabotage, } if (game.state === "game_over") { view.prompt = game.victory - } else if (current === "Observer" || !is_current_active(current)) { + } else if (!is_current_role(role)) { let inactive = states[game.state].inactive || game.state - view.prompt = `Waiting for ${game.active} \u2014 ${inactive}.` + view.prompt = `Waiting for ${faction_name[game.current]} \u2014 ${inactive}.` } else { view.actions = {} view.who = game.who if (states[game.state]) - states[game.state].prompt(current) + states[game.state].prompt() else view.prompt = "Unknown state: " + game.state if (view.actions.undo === undefined) { @@ -864,12 +955,12 @@ exports.view = function (state, current) { return view } -exports.action = function (state, current, action, arg) { +exports.action = function (state, role, action, arg) { load_game(state) - Object.seal(game) // 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, current) + S[action](arg) } else { if (action === "undo" && game.undo && game.undo.length > 0) pop_undo() diff --git a/tools/gendata.js b/tools/gendata.js index 5d59674..e7f5df6 100644 --- a/tools/gendata.js +++ b/tools/gendata.js @@ -2,18 +2,30 @@ let fs = require("fs") let data = {} +const GOVT = 0 +const FARC = 1 +const AUC = 2 +const CARTELS = 3 + +const BASE = 0 +const GUERRILLA = 1 +const TROOPS = 2 +const POLICE = 3 + function to_ascii(s) { return s.normalize("NFD").replace(/[\u0300-\u036f]/g, "") } -const IMAP = { G: "Government", F: "FARC", A: "AUC", C: "Cartels" } +const IMAP = { G: GOVT, F: FARC, A: AUC, C: CARTELS } let order = null -let cards = [ null ] +let card_name = [ null ] +let card_order = [ null ] function def_order(s) { order = [ IMAP[s[0]], IMAP[s[1]], IMAP[s[2]], IMAP[s[3]] ] } function def_card(number, name) { - cards[number] = { number, name, order } + card_name[number] = name + card_order[number] = order } def_order("GFAC") def_card(1, "1st Division") @@ -111,14 +123,15 @@ def_order("CAFG") def_card(70, "Ayahuasca Tourism") def_card(71, "Darién") def_card(72, "Sicarios") -order = null + +def_order("GFAC") def_card(73, "Propaganda!") def_card(74, "Propaganda!") def_card(75, "Propaganda!") def_card(76, "Propaganda!") let spaces = [ ] -let space_names = [ ] +let space_name = [ ] function add(list, item) { if (!list.includes(item)) @@ -126,31 +139,31 @@ function add(list, item) { } function def_space(type, pop, name) { - spaces.push({ type, id: to_ascii(name), name, pop, adjacent: [] }) - space_names.push(name) + spaces.push({ type, id: to_ascii(name), pop, adjacent: [] }) + space_name.push(name) } function def_town(name) { - spaces.push({ type: "town", id: to_ascii(name), name, adjacent: [] }) - space_names.push(name) + spaces.push({ type: "town", id: to_ascii(name), adjacent: [] }) + space_name.push(name) } function def_loc(type, econ, cities, depts) { let name = cities.join(" / ") let loc_names = cities.concat(depts) - let loc_spaces = loc_names.map(n => space_names.indexOf(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) }) for (let loc of loc_spaces) if (loc >= 0) add(spaces[loc].adjacent, ix) - space_names.push(name) + space_name.push(name) return ix } function adjacent(an, bn) { - ax = space_names.indexOf(an) - bx = space_names.indexOf(bn) + ax = space_name.indexOf(an) + bx = space_name.indexOf(bn) add(spaces[ax].adjacent, bx) add(spaces[bx].adjacent, ax) } @@ -379,12 +392,34 @@ adjacent("Vaupés", "Guaviare") adjacent("Amazonas", "Vaupés") adjacent("Amazonas", "Putumayo") -data.coastal_spaces = [ "Cesar", "Atlántico", "Chocó", "Nariño" ].map(n=>space_names.indexOf(n)).sort((a,b)=>a-b) +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) spaces[i].adjacent.sort((a,b)=>a-b) -data.cards = cards + +data.card_name = card_name +data.card_order = card_order +data.space_name = space_name data.spaces = spaces -fs.writeFileSync("data.js", "const data = " + JSON.stringify(data, 0, "\t") + "\nif (typeof module !== 'undefined') module.exports = data\n") +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 ] ] +function def_piece(faction, type, count) { + pc_first[faction][type] = pc_index + pc_last[faction][type] = pc_index + count - 1 + pc_index += count +} +def_piece(GOVT, BASE, 3) +def_piece(GOVT, GUERRILLA, 0) +def_piece(GOVT, TROOPS, 30) +def_piece(GOVT, POLICE, 30) +def_piece(FARC, BASE, 9) +def_piece(FARC, GUERRILLA, 30) +def_piece(AUC, BASE, 6) +def_piece(AUC, GUERRILLA, 18) +def_piece(CARTELS, BASE, 15) +def_piece(CARTELS, GUERRILLA, 12) + +fs.writeFileSync("data.js", "const data = " + JSON.stringify(data, 0, 0) + "\nif (typeof module !== 'undefined') module.exports = data\n") |