diff options
-rw-r--r-- | data.js | 2 | ||||
-rw-r--r-- | events.txt | 12 | ||||
-rw-r--r-- | rules.js | 618 | ||||
-rw-r--r-- | tools/gendata.js | 6 |
4 files changed, 273 insertions, 365 deletions
@@ -1,2 +1,2 @@ -const data = {"first_space":0,"first_pop":0,"first_city":0,"last_city":10,"first_dept":11,"last_pop":22,"last_dept":26,"first_foreign":27,"last_foreign":28,"first_loc":29,"last_loc":46,"last_space":46,"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]],"card_title":[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_flavor":[null,"Jointness","COIN experts take charge","CO tightens civil-military bonds","Profitable pipeline","Oil company security","Rebels blamed","Infrastructure protection training","COIN strike aircraft","Elites guard high-altitude corridors","US helos delivered","Military-police jointness","US \"War on Drugs\"","Transport protection units","Forward base","Defense budget shot in the arm","They're up","Aid conference generous","US \"War on Terror\" takes on FARC",null,"KIA puts FARC in disarray","FARC Deputy killed","FARC leader killed in military strike","US provides aircrew","Dramatic hostage rescue","ELN and FARC jockey","FARC protection rejected","FARC MANPADs deemed a myth","Caracas controls border","Army sniffs out FARC trap","FARC accused in Commissioner's killing","Sympathy for famous hostage","Fed up with hostage-taking","Ecuadoran buffer zone","Insurgents scammed by Russian criminals","Government initiative","ELN gets its DMZ","Ties that bind","New command fights paramilitaries","Local forces platoons","Negotiated reintegration","AUC No.2 extradited","Unity behind Presidential war policy","Suspect leftists massacred","Anti-corruption campaign","Officers disciplined","Ruthless elimination","Human rights investigators","AUC targets oil labor organizers","Militias defy Castaño","National police field forces","Speedy patching","AUC leader's memoir a best seller","Insurgent access to small aircraft",null,"Law enforcement assistance","Cali cartel's drugstore chain seized","Colombian-US strike at Bernal syndicate","National Police hammer cartels","Cartel informant","Kingpin strategy scores","Peruvian coca supply controlled","Brasília's Op Cobra blocks border","Rival syndicates go for the throat","FARC taps suppliers","Growers and Government eradication focus on heroin source","Coca crop fails","Major shipment busted en route","Submersibles seized",null,"Eco-tourism helps trade balance","Arms traffic interdicted","Hired drug guns unreliable"],"card_flavor_shaded":[null,"Service parochialism","COIN strategy eludes Army","Civil-military rivalries fester","Pipeline draws attacks","Industry thought exploitative","Multinationals make mess","US training ineffective","Budget diverted to expensive jets","Equipment not delivered","Delivery of US helos delayed","Military-police rivalry","US aid focuses on drug war","Transport security deemphasized","Base overrun","Middle class resents cost of war","They're down","EU aid focuses on reconstruction","US focused on Mid-East and South Asia",null,"Military strategist","FARC Deputy channels foreign support","Ideologue","Plane down - hostage search and evasion","Hostage rescue goes awry","ELN and FARC coordinate ops","Schedule of fees","MANPADs feared","Caracas aids rebels","Tactics lure enemy in","Peace bid","Hostage negotiations forum for FARC","Ransoming highly profitable","Cross-border war","Covert weapons delivery","FARC proposals lauded",null,"Ex-officers advise paramilitaries","Sympathizers alert AUC","Local forces augment autodefensas","Talks a ruse, fighters recycled","AUC drug lord","Insurgent sympathies","Brutality blamed on Army","Political campaign divisive","International human rights cartel",null,"Prosecutors killed","Labor backs FARC","Independent militias join AUC","National police corruption","Security concerns hinder maintenance","Charismatic AUC political leader",null,null,"Más Yanquis","Retail empire","Investigation penetrated","Officials on cartel payroll","Cali cartel security chief","Cali's Gilberto Rodríguez Orejuela expands empire","Colombian coca growers fill Peruvian void","Jungle landing strips",null,"Well-oiled industry",null,"Hearty coca variety","New routes to US market","Littoral stealth",null,"Eco-tourists taken","Border sanctuary","Unemployed ready to work for syndicates"],"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","Ecuador","Panamá","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,32,39,40,42]},{"type":"city","id":"Cali","pop":3,"adjacent":[12,13,20,30,34,38]},{"type":"city","id":"Medellin","pop":3,"adjacent":[12,18,36,37]},{"type":"city","id":"Bucaramanga","pop":2,"adjacent":[18,19,39,44]},{"type":"city","id":"Ibague","pop":2,"adjacent":[12,18,20,37,38,39]},{"type":"city","id":"Santa Marta","pop":2,"adjacent":[11,17,29,43]},{"type":"city","id":"Cartagena","pop":1,"adjacent":[11,29,35]},{"type":"city","id":"Cucuta","pop":1,"adjacent":[19,41,46]},{"type":"city","id":"Neiva","pop":1,"adjacent":[14,16,20,31,40]},{"type":"city","id":"Pasto","pop":1,"adjacent":[13,16,20,27,30,31,33]},{"type":"city","id":"Sincelejo","pop":1,"adjacent":[11,12,18,35,36,45]},{"type":"forest","id":"Atlantico","pop":1,"adjacent":[5,6,10,17,18,19,29,35,43,44,45,46]},{"type":"forest","id":"Choco","pop":1,"adjacent":[1,2,4,10,13,18,20,28,34,36,37,38]},{"type":"forest","id":"Narino","pop":1,"adjacent":[1,9,12,20,27,30,33,34]},{"type":"forest","id":"Meta West","pop":1,"adjacent":[0,8,15,16,20,22,32,40]},{"type":"forest","id":"Guaviare","pop":1,"adjacent":[14,16,22,23,24,25,32]},{"type":"forest","id":"Putumayo","pop":1,"adjacent":[8,9,14,15,20,25,26,27,31]},{"type":"mountain","id":"Cesar","pop":1,"adjacent":[5,11,18,19,43,44,45,46]},{"type":"mountain","id":"Antioquia","pop":2,"adjacent":[2,3,4,10,11,12,17,19,20,36,37,39,43,44,45,46]},{"type":"mountain","id":"Santander","pop":2,"adjacent":[0,3,7,11,17,18,20,21,22,39,41,42,43,44,45,46]},{"type":"mountain","id":"Huila","pop":2,"adjacent":[0,1,4,8,9,12,13,14,16,18,19,30,31,38,39,40]},{"type":"grassland","id":"Arauca","pop":1,"adjacent":[19,22,23,41,42]},{"type":"grassland","id":"Meta East","pop":1,"adjacent":[0,14,15,19,21,23,32,42]},{"type":"grassland","id":"Vichada","pop":0,"adjacent":[15,21,22,24]},{"type":"forest","id":"Guainia","pop":0,"adjacent":[15,23,25]},{"type":"forest","id":"Vaupes","pop":0,"adjacent":[15,16,24,26]},{"type":"forest","id":"Amazonas","pop":0,"adjacent":[16,25]},{"type":"foreign","id":"Ecuador","pop":0,"adjacent":[9,13,16,33]},{"type":"foreign","id":"Panama","pop":0,"adjacent":[12]},{"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":[0,14,15,22]},{"type":"road","id":"Pasto / Tumaco","econ":1,"adjacent":[9,13,27]},{"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":[0,3,4,18,19,20]},{"type":"pipeline","id":"Bogota / Neiva","econ":2,"adjacent":[0,8,14,20]},{"type":"pipeline","id":"Cucuta / Arauca","econ":3,"adjacent":[7,19,21,21]},{"type":"pipeline","id":"Bogota / Yopal","econ":2,"adjacent":[0,19,21,22]},{"type":"pipeline","id":"Santa Marta / Ayacucho","econ":2,"adjacent":[5,11,17,18,19,44,45,46]},{"type":"pipeline","id":"Bucaramanga / Ayacucho","econ":2,"adjacent":[3,11,17,18,19,43,45,46]},{"type":"pipeline","id":"Sincelejo / Ayacucho","econ":3,"adjacent":[10,11,17,18,19,43,44,46]},{"type":"pipeline","id":"Cucuta / Ayacucho","econ":3,"adjacent":[7,11,17,18,19,43,44,45]}],"adjacent_patrol":[[32,39,40,42],[30,34,38],[36,37],[39,44],[37,38,39],[29,43],[29,35],[41,46],[31,40],[30,31,33],[35,36,45],[5,6,10,29,35,43,44,45,46],[1,2,4,10,34,36,37,38],[1,9,30,33,34],[0,8,32,40],[32],[8,9,31],[5,43,44,45,46],[2,3,4,10,36,37,39,43,44,45,46],[0,3,7,39,41,42,43,44,45,46],[0,1,4,8,9,30,31,38,39,40],[41,42],[0,32,42],[],[],[],[],[9,33],[],[5,6],[1,9],[8,9],[0],[9],[1],[6,10],[2,10],[2,4],[1,4],[0,3,4],[0,8],[7],[0],[5,44,45,46],[3,43,45,46],[10,43,44,46],[7,43,44,45]],"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]]} +const data = {"first_space":0,"first_pop":0,"first_city":0,"last_city":10,"first_dept":11,"last_pop":22,"last_dept":28,"first_loc":29,"last_loc":46,"last_space":46,"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]],"card_title":[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_flavor":[null,"Jointness","COIN experts take charge","CO tightens civil-military bonds","Profitable pipeline","Oil company security","Rebels blamed","Infrastructure protection training","COIN strike aircraft","Elites guard high-altitude corridors","US helos delivered","Military-police jointness","US \"War on Drugs\"","Transport protection units","Forward base","Defense budget shot in the arm","They're up","Aid conference generous","US \"War on Terror\" takes on FARC",null,"KIA puts FARC in disarray","FARC Deputy killed","FARC leader killed in military strike","US provides aircrew","Dramatic hostage rescue","ELN and FARC jockey","FARC protection rejected","FARC MANPADs deemed a myth","Caracas controls border","Army sniffs out FARC trap","FARC accused in Commissioner's killing","Sympathy for famous hostage","Fed up with hostage-taking","Ecuadoran buffer zone","Insurgents scammed by Russian criminals","Government initiative","ELN gets its DMZ","Ties that bind","New command fights paramilitaries","Local forces platoons","Negotiated reintegration","AUC No.2 extradited","Unity behind Presidential war policy","Suspect leftists massacred","Anti-corruption campaign","Officers disciplined","Ruthless elimination","Human rights investigators","AUC targets oil labor organizers","Militias defy Castaño","National police field forces","Speedy patching","AUC leader's memoir a best seller","Insurgent access to small aircraft",null,"Law enforcement assistance","Cali cartel's drugstore chain seized","Colombian-US strike at Bernal syndicate","National Police hammer cartels","Cartel informant","Kingpin strategy scores","Peruvian coca supply controlled","Brasília's Op Cobra blocks border","Rival syndicates go for the throat","FARC taps suppliers","Growers and Government eradication focus on heroin source","Coca crop fails","Major shipment busted en route","Submersibles seized",null,"Eco-tourism helps trade balance","Arms traffic interdicted","Hired drug guns unreliable"],"card_flavor_shaded":[null,"Service parochialism","COIN strategy eludes Army","Civil-military rivalries fester","Pipeline draws attacks","Industry thought exploitative","Multinationals make mess","US training ineffective","Budget diverted to expensive jets","Equipment not delivered","Delivery of US helos delayed","Military-police rivalry","US aid focuses on drug war","Transport security deemphasized","Base overrun","Middle class resents cost of war","They're down","EU aid focuses on reconstruction","US focused on Mid-East and South Asia",null,"Military strategist","FARC Deputy channels foreign support","Ideologue","Plane down - hostage search and evasion","Hostage rescue goes awry","ELN and FARC coordinate ops","Schedule of fees","MANPADs feared","Caracas aids rebels","Tactics lure enemy in","Peace bid","Hostage negotiations forum for FARC","Ransoming highly profitable","Cross-border war","Covert weapons delivery","FARC proposals lauded",null,"Ex-officers advise paramilitaries","Sympathizers alert AUC","Local forces augment autodefensas","Talks a ruse, fighters recycled","AUC drug lord","Insurgent sympathies","Brutality blamed on Army","Political campaign divisive","International human rights cartel",null,"Prosecutors killed","Labor backs FARC","Independent militias join AUC","National police corruption","Security concerns hinder maintenance","Charismatic AUC political leader",null,null,"Más Yanquis","Retail empire","Investigation penetrated","Officials on cartel payroll","Cali cartel security chief","Cali's Gilberto Rodríguez Orejuela expands empire","Colombian coca growers fill Peruvian void","Jungle landing strips",null,"Well-oiled industry",null,"Hearty coca variety","New routes to US market","Littoral stealth",null,"Eco-tourists taken","Border sanctuary","Unemployed ready to work for syndicates"],"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","Ecuador","Panamá","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,32,39,40,42]},{"type":"city","id":"Cali","pop":3,"adjacent":[12,13,20,30,34,38]},{"type":"city","id":"Medellin","pop":3,"adjacent":[12,18,36,37]},{"type":"city","id":"Bucaramanga","pop":2,"adjacent":[18,19,39,44]},{"type":"city","id":"Ibague","pop":2,"adjacent":[12,18,20,37,38,39]},{"type":"city","id":"Santa Marta","pop":2,"adjacent":[11,17,29,43]},{"type":"city","id":"Cartagena","pop":1,"adjacent":[11,29,35]},{"type":"city","id":"Cucuta","pop":1,"adjacent":[19,41,46]},{"type":"city","id":"Neiva","pop":1,"adjacent":[14,16,20,31,40]},{"type":"city","id":"Pasto","pop":1,"adjacent":[13,16,20,27,30,31,33]},{"type":"city","id":"Sincelejo","pop":1,"adjacent":[11,12,18,35,36,45]},{"type":"forest","id":"Atlantico","pop":1,"adjacent":[5,6,10,17,18,19,29,35,43,44,45,46]},{"type":"forest","id":"Choco","pop":1,"adjacent":[1,2,4,10,13,18,20,28,34,36,37,38]},{"type":"forest","id":"Narino","pop":1,"adjacent":[1,9,12,20,27,30,33,34]},{"type":"forest","id":"Meta West","pop":1,"adjacent":[0,8,15,16,20,22,32,40]},{"type":"forest","id":"Guaviare","pop":1,"adjacent":[14,16,22,23,24,25,32]},{"type":"forest","id":"Putumayo","pop":1,"adjacent":[8,9,14,15,20,25,26,27,31]},{"type":"mountain","id":"Cesar","pop":1,"adjacent":[5,11,18,19,43,44,45,46]},{"type":"mountain","id":"Antioquia","pop":2,"adjacent":[2,3,4,10,11,12,17,19,20,36,37,39,43,44,45,46]},{"type":"mountain","id":"Santander","pop":2,"adjacent":[0,3,7,11,17,18,20,21,22,39,41,42,43,44,45,46]},{"type":"mountain","id":"Huila","pop":2,"adjacent":[0,1,4,8,9,12,13,14,16,18,19,30,31,38,39,40]},{"type":"grassland","id":"Arauca","pop":1,"adjacent":[19,22,23,41,42]},{"type":"grassland","id":"Meta East","pop":1,"adjacent":[0,14,15,19,21,23,32,42]},{"type":"grassland","id":"Vichada","pop":0,"adjacent":[15,21,22,24]},{"type":"forest","id":"Guainia","pop":0,"adjacent":[15,23,25]},{"type":"forest","id":"Vaupes","pop":0,"adjacent":[15,16,24,26]},{"type":"forest","id":"Amazonas","pop":0,"adjacent":[16,25]},{"type":"foreign","id":"Ecuador","pop":0,"adjacent":[9,13,16,33]},{"type":"foreign","id":"Panama","pop":0,"adjacent":[12]},{"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":[0,14,15,22]},{"type":"road","id":"Pasto / Tumaco","econ":1,"adjacent":[9,13,27]},{"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":[0,3,4,18,19,20]},{"type":"pipeline","id":"Bogota / Neiva","econ":2,"adjacent":[0,8,14,20]},{"type":"pipeline","id":"Cucuta / Arauca","econ":3,"adjacent":[7,19,21,21]},{"type":"pipeline","id":"Bogota / Yopal","econ":2,"adjacent":[0,19,21,22]},{"type":"pipeline","id":"Santa Marta / Ayacucho","econ":2,"adjacent":[5,11,17,18,19,44,45,46]},{"type":"pipeline","id":"Bucaramanga / Ayacucho","econ":2,"adjacent":[3,11,17,18,19,43,45,46]},{"type":"pipeline","id":"Sincelejo / Ayacucho","econ":3,"adjacent":[10,11,17,18,19,43,44,46]},{"type":"pipeline","id":"Cucuta / Ayacucho","econ":3,"adjacent":[7,11,17,18,19,43,44,45]}],"adjacent_patrol":[[32,39,40,42],[30,34,38],[36,37],[39,44],[37,38,39],[29,43],[29,35],[41,46],[31,40],[30,31,33],[35,36,45],[5,6,10,29,35,43,44,45,46],[1,2,4,10,34,36,37,38],[1,9,30,33,34],[0,8,32,40],[32],[8,9,31],[5,43,44,45,46],[2,3,4,10,36,37,39,43,44,45,46],[0,3,7,39,41,42,43,44,45,46],[0,1,4,8,9,30,31,38,39,40],[41,42],[0,32,42],[],[],[],[],[9,33],[],[5,6],[1,9],[8,9],[0],[9],[1],[6,10],[2,10],[2,4],[1,4],[0,3,4],[0,8],[7],[0],[5,44,45,46],[3,43,45,46],[10,43,44,46],[7,43,44,45]],"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 @@ -1,3 +1,5 @@ +# remove piece - transfer or remove shipments + EVENT 1 log 1 Civic Action space each Support Phase requires Govt Control and any cube. capability @@ -342,7 +344,7 @@ EVENT 29 SHADED 29 current [FARC,AUC] - piece 2 is_piece(p, game.current, GUERRILLA) && has_enemy_piece(s) + piece 2 is_faction_guerrilla(p, game.current) && has_enemy_piece(s) free_ambush underground endpiece @@ -625,7 +627,7 @@ EVENT 46 current [FARC,AUC,CARTELS] prompt Execute free Terror with any Guerrilla. space 1 has_piece(s, game.current, GUERRILLA) - piece 1 is_piece_in_event_space(p) && is_piece(p, game.current, GUERRILLA) + piece 1 is_piece_in_event_space(p) && is_faction_guerrilla(p, game.current) free_terror terror terror_aid_cut @@ -766,13 +768,15 @@ EVENT 54 EVENT 55 remove_shipment remove_shipment + prompt Remove N Cartels Guerrillas. piece 5 is_cartels_guerrilla(p) remove endpiece aid 3 SHADED 55 - space 3 has_cartel_piece(s) + prompt Shift N spaces with Cartels pieces 1 level toward Active Opposition. + space 3 has_cartels_piece(s) && !is_active_opposition(s) shift_opposition endspace @@ -942,7 +946,7 @@ EVENT 70 SHADED 70 current [FARC,AUC,CARTELS] space 0 is_forest(s) && has_piece(s, game.current, GUERRILLA) - piece 1 is_piece_in_event_space(p) && is_piece(p, game.current, GUERRILLA) + piece 1 is_piece_in_event_space(p) && is_faction_guerrilla(p, game.current) free_terror resources (game.current) 3 endpiece @@ -2,7 +2,6 @@ // TODO: Automatic "All done" message. (limited / no more resources / no more available options). // TODO: auto-next at end of Special Activity / operation space ? -// rough undo granularity (save only at start of op/activity in space) // TODO: resume_...activity - end automatically when no more possible // TODO: for (s = ... last_space) to for_each_space (including/excluding foreign countries depending on events) @@ -88,8 +87,6 @@ const last_pop = data.last_pop const last_dept = data.last_dept const first_loc = data.first_loc const last_loc = data.last_loc -const first_foreign = data.first_foreign -const last_foreign = data.last_foreign const path_seen = new Array(last_space+1).fill(0) @@ -111,11 +108,6 @@ const NEUTRAL = 0 const PASSIVE_OPPOSITION = -1 const ACTIVE_OPPOSITION = -2 -// Control -const CTL_NEUTRAL = 0 -const CTL_GOVT = 1 -const CTL_FARC = 2 - const SAMPER = 1 const PASTRANA = 2 const URIBE = 3 @@ -156,6 +148,10 @@ const GUAINIA = 24 const VAUPES = 25 const AMAZONAS = 26 +// Foreign Countries +const ECUADOR = 27 +const PANAMA = 28 + // LoCs const CUCUTA_AYACUCHO = data.space_name.indexOf("Cúcuta / Ayacucho") const CUCUTA_ARAUCA = data.space_name.indexOf("Cúcuta / Arauca") @@ -164,14 +160,6 @@ const CALI_BUENAVENTURA = data.space_name.indexOf("Cali / Buenaventura") const CARTAGENA_SINCELEJO = data.space_name.indexOf("Cartagena / Sincelejo") const SANTA_MARTA_CARTAGENA = data.space_name.indexOf("Santa Marta / Cartagena") -// Foreign Countries -const ECUADOR = 27 -const PANAMA = 28 - -const next_to_venezuela = [ CESAR, SANTANDER, ARAUCA, VICHADA, GUAINIA ] - -const COASTAL_SPACES = [ ATLANTICO, CHOCO, NARINO, CESAR ] - exports.roles = function (scenario) { if (scenario.startsWith("2P")) return [ NAME_GOVT_AUC, NAME_FARC_CARTELS ] @@ -285,7 +273,7 @@ exports.setup = function (seed, scenario, options) { setup_deck(4, 0, 15) } - game.deck[0] = 49 + game.deck[0] = 55 log("DECK " + game.deck.join(", ")) update_control() @@ -580,11 +568,6 @@ function piece_faction(p) { return 0 } -function has_targeted_faction(faction) { - let bit = 1 << faction - return game.op.targeted & bit -} - function did_maximum_damage(targeted) { if (view.actions.piece) for (let p of view.actions.piece) @@ -674,22 +657,6 @@ function has_any_guerrilla(s) { ) } -function has_any_active_guerrilla(s) { - return ( - has_active_guerrilla(s, FARC) || - has_active_guerrilla(s, AUC) || - has_active_guerrilla(s, CARTELS) - ) -} - -function has_any_underground_guerrilla(s) { - return ( - has_underground_guerrilla(s, FARC) || - has_underground_guerrilla(s, AUC) || - has_underground_guerrilla(s, CARTELS) - ) -} - function count_bases(s) { return ( count_pieces(s, GOVT, BASE) + @@ -699,15 +666,42 @@ function count_bases(s) { ) } -function can_place_base(s) { +// TODO: faction for ECUADOR check +function can_stack_base(s) { return count_bases(s) < 2 } -function can_place_piece(s) { - // TODO: check stacking limit in Ecuador +function can_stack_piece(faction, type, s) { + if (faction === GOVT) + if (is_farc_zone(s)) + return false + if (type === BASE) + if (!can_stack_base(s)) + return false + if (s === PANAMA) + return set_has(game.capabilities, EVT_DARIEN) + if (s === ECUADOR) { + if (set_has(game.capabilities, EVT_SUCUMBIOS)) + return count_faction_pieces(s, faction) < 2 + else + return false + } return true } +function count_faction_pieces(s, faction) { + switch (faction) { + case GOVT: + return count_pieces(s, GOVT, BASE) + count_pieces(s, GOVT, TROOPS) + count_pieces(s, GOVT, POLICE) + case FARC: + return count_pieces(s, FARC, BASE) + count_pieces(s, FARC, GUERRILLA) + case AUC: + return count_pieces(s, AUC, BASE) + count_pieces(s, AUC, GUERRILLA) + case CARTELS: + return count_pieces(s, CARTELS, BASE) + count_pieces(s, CARTELS, GUERRILLA) + } +} + function count_cubes(s) { return ( count_pieces(s, GOVT, TROOPS) + @@ -715,14 +709,6 @@ function count_cubes(s) { ) } -function count_any_guerrillas(s) { - return ( - count_pieces(s, FARC, GUERRILLA) + - count_pieces(s, AUC, GUERRILLA) + - count_pieces(s, CARTELS, GUERRILLA) - ) -} - function count_any_underground_guerrillas(s) { return ( count_underground_guerrillas(s, FARC) + @@ -735,15 +721,10 @@ function update_control() { game.govt_control = 0 game.farc_control = 0 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) + let g = count_faction_pieces(s, GOVT) + let f = count_faction_pieces(s, FARC) + let a = count_faction_pieces(s, AUC) + let c = count_faction_pieces(s, CARTELS) if (g > a + c + f) game.govt_control |= (1 << s) else if (f > g + a + c) @@ -753,15 +734,10 @@ function update_control() { function has_auc_control(s) { // AUC outnumber all other forces - 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) + let g = count_faction_pieces(s, GOVT) + let f = count_faction_pieces(s, FARC) + let a = count_faction_pieces(s, AUC) + let c = count_faction_pieces(s, CARTELS) return a > g + f + c } @@ -785,10 +761,6 @@ function is_dept(s) { return s >= first_dept && s <= last_dept } -function is_city_or_dept(s) { - return is_city(s) || is_dept(s) -} - function is_loc(s) { return s >= first_loc && s <= last_loc } @@ -817,10 +789,6 @@ function is_adjacent(a, b) { return set_has(data.spaces[a].adjacent, b) } -function is_active(p) { - return !is_underground(p) -} - function is_farc_zone(s) { return set_has(game.farc_zones, s) } @@ -835,15 +803,10 @@ function is_empty(s) { } function faction_with_most_pieces(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) + let g = count_faction_pieces(s, GOVT) + let f = count_faction_pieces(s, FARC) + let a = count_faction_pieces(s, AUC) + let c = count_faction_pieces(s, CARTELS) if (g >= f && g >= a && g >= c) return GOVT if (f > g && f > a && f > c) @@ -869,6 +832,10 @@ function is_insurgent_piece(p) { return is_farc_piece(p) || is_auc_piece(p) || is_cartels_piece(p) } +function is_active(p) { + return !is_underground(p) +} + function is_underground(p) { for (let faction = 1; faction < 4; ++faction) { let p0 = first_piece[faction][GUERRILLA] @@ -913,140 +880,6 @@ function move_piece(p, s) { game.pieces[p] = s } -function place_shipment(sh, p) { - game.shipments[sh] = p << 2 -} - -function remove_shipment(sh) { - game.shipments[sh] = 0 -} - -function drop_shipment(sh) { - let p = game.shipments[sh] >> 2 - let s = game.pieces[p] - let f = piece_faction(p) - game.shipments[sh] = (s << 2) | f -} - -function is_shipment_available(sh) { - return game.shipments[sh] === 0 -} - -function is_shipment_held(sh) { - return game.shipments[sh] !== 0 && (game.shipments[sh] & 3) === 0 -} - -function get_held_shipment_faction(sh) { - return piece_faction(game.shipments[sh] >> 2) -} - -function get_held_shipment_piece(sh) { - return (game.shipments[sh] >> 2) -} - -function is_shipment_dropped(sh) { - return (game.shipments[sh] & 3) !== 0 -} - -function get_dropped_shipment_faction(sh) { - return (game.shipments[sh] & 3) -} - -function get_dropped_shipment_space(sh) { - return (game.shipments[sh] >> 2) -} - -function is_shipment_held_by_piece(sh, p) { - return is_shipment_held(sh) && get_held_shipment_piece(sh) === p -} - -function is_shipment_held_by_faction(sh, f) { - return is_shipment_held(sh) && get_held_shipment_faction(sh) === f -} - -function is_any_shipment_held_by_faction(faction) { - for (let sh = 0; sh < 4; ++sh) - if (is_shipment_held_by_faction(sh, faction)) - return true - return false -} - -function is_any_shipment_held() { - for (let sh = 0; sh < 4; ++sh) - if (is_shipment_held(sh)) - return true - return false -} - -function remove_dropped_shipments() { - for (let sh = 0; sh < 4; ++sh) - if (is_shipment_dropped(sh)) - remove_shipment(sh) -} - -function drop_held_shipments(p) { - for (let sh = 0; sh < 4; ++sh) - if (is_shipment_held_by_piece(sh, p)) - drop_shipment(sh) -} - -function has_dropped_shipments() { - for (let sh = 0; sh < 4; ++sh) - if (is_shipment_dropped(sh)) - return true - return false -} - -function can_transfer_dropped_shipments() { - for (let sh = 0; sh < 4; ++sh) - if (is_shipment_dropped(sh)) - if (has_any_guerrilla(get_dropped_shipment_space(sh))) - return true - return false -} - -function auto_transfer_dropped_shipments(s) { - for (let sh = 0; sh < 4; ++sh) - if (is_shipment_dropped(sh)) - auto_transfer_dropped_shipments(sh) -} - -function auto_transfer_dropped_shipments(sh) { - let f = get_dropped_shipment_faction(sh) - let s = get_dropped_shipment_space(sh) - let a, b, p - - p = find_guerrilla(s, f) - if (p >= 0) { - place_shipment(sh, p) - return - } - - if (f === FARC) { - a = find_guerrilla(s, AUC) - b = find_guerrilla(s, CARTELS) - } - if (f === AUC) { - a = find_guerrilla(s, FARC) - b = find_guerrilla(s, CARTELS) - } - if (f === CARTELS) { - a = find_guerrilla(s, FARC) - b = find_guerrilla(s, AUC) - } - - if (a >= 0 && b < 0) { - place_shipment(sh, a) - return - } - if (a < 0 && b >= 0) { - place_shipment(sh, b) - return - } - - // nobody to pick it up... -} - function count_terror_and_sabotage() { let n = (game.sabotage.length >> 1) for (let i = 1; i < game.terror.length; i += 2) @@ -1168,7 +1001,7 @@ function is_next_to_venezuela(s) { s === ARAUCA || s === VICHADA || s === GUAINIA || - s === AYACUCHO_CUCUTA || + s === CUCUTA_AYACUCHO || s === CUCUTA_ARAUCA ) } @@ -1183,7 +1016,7 @@ function is_next_to_ecuador(s) { ) } -function is_coastal(s) { +function is_coastal_space(s) { return ( s === CESAR || s === SANTA_MARTA || @@ -1209,10 +1042,6 @@ function is_zero_pop_forest(s) { return !is_pop(s) && is_forest(s) } -function add_aid(n) { - game.aid = Math.max(0, game.aid + n) -} - function can_govt_civic_action(s) { if (game.support[s] < 2 && has_govt_control(s)) { if (has_shaded_capability(CAP_1ST_DIV)) @@ -1309,7 +1138,7 @@ function gen_piece_in_space(space, faction, type) { function gen_place_piece(space, faction, type) { let p0 = first_piece[faction][type] let p1 = last_piece[faction][type] - if (type === BASE && !can_place_base(space)) + if (type === BASE && !can_stack_base(space)) return true let can_place = false for (let p = p0; p <= p1; ++p) { @@ -1357,6 +1186,143 @@ function gen_attack_piece(s, faction) { } } + +// === SHIPMENTS === + +function place_shipment(sh, p) { + game.shipments[sh] = p << 2 +} + +function remove_shipment(sh) { + game.shipments[sh] = 0 +} + +function drop_shipment(sh) { + let p = game.shipments[sh] >> 2 + let s = game.pieces[p] + let f = piece_faction(p) + game.shipments[sh] = (s << 2) | f +} + +function is_shipment_available(sh) { + return game.shipments[sh] === 0 +} + +function is_shipment_held(sh) { + return game.shipments[sh] !== 0 && (game.shipments[sh] & 3) === 0 +} + +function get_held_shipment_faction(sh) { + return piece_faction(game.shipments[sh] >> 2) +} + +function get_held_shipment_piece(sh) { + return (game.shipments[sh] >> 2) +} + +function is_shipment_dropped(sh) { + return (game.shipments[sh] & 3) !== 0 +} + +function get_dropped_shipment_faction(sh) { + return (game.shipments[sh] & 3) +} + +function get_dropped_shipment_space(sh) { + return (game.shipments[sh] >> 2) +} + +function is_shipment_held_by_piece(sh, p) { + return is_shipment_held(sh) && get_held_shipment_piece(sh) === p +} + +function is_shipment_held_by_faction(sh, f) { + return is_shipment_held(sh) && get_held_shipment_faction(sh) === f +} + +function is_any_shipment_held_by_faction(faction) { + for (let sh = 0; sh < 4; ++sh) + if (is_shipment_held_by_faction(sh, faction)) + return true + return false +} + +function is_any_shipment_held() { + for (let sh = 0; sh < 4; ++sh) + if (is_shipment_held(sh)) + return true + return false +} + +function remove_dropped_shipments() { + for (let sh = 0; sh < 4; ++sh) + if (is_shipment_dropped(sh)) + remove_shipment(sh) +} + +function drop_held_shipments(p) { + for (let sh = 0; sh < 4; ++sh) + if (is_shipment_held_by_piece(sh, p)) + drop_shipment(sh) +} + +function has_dropped_shipments() { + for (let sh = 0; sh < 4; ++sh) + if (is_shipment_dropped(sh)) + return true + return false +} + +function can_transfer_dropped_shipments() { + for (let sh = 0; sh < 4; ++sh) + if (is_shipment_dropped(sh)) + if (has_any_guerrilla(get_dropped_shipment_space(sh))) + return true + return false +} + +function auto_transfer_dropped_shipments(s) { + for (let sh = 0; sh < 4; ++sh) + if (is_shipment_dropped(sh)) + auto_transfer_dropped_shipment_imp(sh) +} + +function auto_transfer_dropped_shipment_imp(sh) { + let f = get_dropped_shipment_faction(sh) + let s = get_dropped_shipment_space(sh) + let a, b, p + + p = find_guerrilla(s, f) + if (p >= 0) { + place_shipment(sh, p) + return + } + + if (f === FARC) { + a = find_guerrilla(s, AUC) + b = find_guerrilla(s, CARTELS) + } + if (f === AUC) { + a = find_guerrilla(s, FARC) + b = find_guerrilla(s, CARTELS) + } + if (f === CARTELS) { + a = find_guerrilla(s, FARC) + b = find_guerrilla(s, AUC) + } + + if (a >= 0 && b < 0) { + place_shipment(sh, a) + return + } + if (a < 0 && b >= 0) { + place_shipment(sh, b) + return + } + + // nobody to pick it up... +} + // === SEQUENCE OF PLAY === function this_card() { @@ -1521,7 +1487,6 @@ function goto_pass() { } function goto_limop_or_event() { - push_undo() game.state = "limop_or_event" } @@ -1587,7 +1552,7 @@ function init_free_operation(state) { } function can_ship() { - return game.op.ship && is_any_shipment_held(game.current) + return game.op.ship && is_any_shipment_held() } function end_operation() { @@ -2309,7 +2274,6 @@ states.train_base = { } }, space(s) { - push_undo() game.op.where = s game.op.count = 3 }, @@ -2349,7 +2313,6 @@ states.train_civic = { } }, space(s) { - push_undo() game.op.where = s game.resources[game.current] -= 3 game.support[game.op.where] += 1 @@ -2449,7 +2412,6 @@ states.patrol_limop_move = { view.actions.next = 1 }, piece(p) { - push_undo() move_piece(p, game.op.where) update_control() }, @@ -2561,7 +2523,6 @@ states.patrol_activate = { view.actions.next = 0 }, piece(p) { - push_undo() let s = game.pieces[p] game.op.targeted |= target_faction(p) set_active(p) @@ -2657,7 +2618,6 @@ states.patrol_assault_space = { view.actions.next = 0 }, piece(p) { - push_undo() game.op.targeted |= target_faction(p) remove_piece(p) update_control() @@ -2668,6 +2628,7 @@ states.patrol_assault_space = { } }, next() { + push_undo() end_patrol_assault_space() transfer_or_drug_bust_shipments() }, @@ -2863,7 +2824,6 @@ states.sweep_activate = { view.actions.next = 0 }, piece(p) { - push_undo() game.op.targeted |= target_faction(p) set_active(p) if (--game.op.count === 0 || !can_sweep_activate(game.op.where)) @@ -3057,7 +3017,6 @@ states.assault_space = { view.actions.next = 0 }, piece(p) { - push_undo() game.op.targeted |= target_faction(p) remove_piece(p) update_control() @@ -3163,7 +3122,6 @@ states.rally_space = { gen_place_piece(game.op.where, game.current, GUERRILLA) }, piece(p) { - push_undo() place_piece(p, game.op.where) if (--game.op.count === 0) game.state = "rally" @@ -3198,7 +3156,6 @@ states.rally_base = { } }, piece(p) { - push_undo() if (game.op.count > 0) { remove_piece(p) --game.op.count @@ -3225,7 +3182,6 @@ states.rally_move = { view.actions.flip = 1 }, piece(p) { - push_undo() move_piece(p, game.op.where) game.op.count++ update_control() @@ -3358,8 +3314,6 @@ states.march_move = { view.actions.next = 1 }, piece(p) { - push_undo() - let from = game.pieces[p] let group = map_get(game.op.march, from, null) if (!group) @@ -3395,13 +3349,6 @@ function has_any_piece(s, faction) { return has_piece(s, faction, BASE) || has_piece(s, faction, GUERRILLA) } -function has_exposed_piece(s, faction) { - if (has_piece(s, faction, GUERRILLA)) - return has_active_guerrilla(s, faction) - else - return has_piece(s, faction, BASE) -} - function has_enemy_piece(s) { if (game.current !== GOVT && has_any_piece(s, GOVT)) return true @@ -3507,7 +3454,6 @@ states.attack_place = { gen_place_piece(game.op.where, game.current, GUERRILLA) }, piece(p) { - push_undo() place_piece(p, game.op.where) update_control() game.state = "attack_remove" @@ -3534,7 +3480,6 @@ states.attack_remove = { view.actions.next = 0 }, piece(p) { - push_undo() game.op.targeted |= target_faction(p) remove_piece(p) update_control() @@ -3816,7 +3761,6 @@ states.air_lift_move = { view.actions.end_activity = 1 }, piece(p) { - push_undo() move_piece(p, game.sa.to) update_control() if (--game.sa.count === 0 || count_cubes(game.sa.from) === 0) @@ -3854,7 +3798,6 @@ states.air_strike = { } }, piece(p) { - //push_undo() let s = game.pieces[p] log(`Air Strike in S${s}.`) remove_piece(p) @@ -3966,12 +3909,10 @@ states.eradicate_shift = { } }, space(s) { - push_undo() game.support[s] -- end_special_activity() }, piece(p) { - push_undo() place_piece(p, game.sa.where) update_control() end_special_activity() @@ -4016,7 +3957,7 @@ function goto_extort() { game.sa = { save: game.state, spaces: [], - where: -1, // for extort2 + where: -1, } game.state = "extort2" } @@ -4170,9 +4111,9 @@ function transfer_resources(from, to, n) { } function can_place_auc_piece(s) { - if (can_place_base(s) && has_piece(AVAILABLE, AUC, BASE)) + if (can_stack_base(s) && has_piece(AVAILABLE, AUC, BASE)) return true - if (can_place_piece(s) && has_piece(AVAILABLE, AUC, GUERRILLA)) + if (can_stack_piece(AUC, GUERRILLA, s) && has_piece(AVAILABLE, AUC, GUERRILLA)) return true return false } @@ -4222,9 +4163,9 @@ states.kidnap_space = { states.kidnap_place = { prompt() { view.prompt = `Kidnap in ${space_name[game.sa.where]}: Place an AUC piece.` - if (can_place_base(game.sa.where)) + if (can_stack_base(game.sa.where)) gen_piece_in_space(AVAILABLE, AUC, BASE) - if (can_place_piece(game.sa.where)) + if (can_stack_piece(AUC, GUERRILLA, game.sa.where)) gen_piece_in_space(AVAILABLE, AUC, GUERRILLA) }, piece(p) { @@ -4244,7 +4185,6 @@ function resume_kidnap_1() { } function resume_kidnap_2() { - // TODO: manually end if (game.sa.spaces.length === 3) end_special_activity() else @@ -4370,7 +4310,6 @@ states.cultivate_place = { gen_place_piece(game.sa.where, CARTELS, BASE) }, piece(p) { - push_undo() place_piece(p, game.sa.where) update_control() end_special_activity() @@ -4387,7 +4326,6 @@ states.cultivate_move = { }) }, piece(p) { - push_undo() move_piece(p, game.sa.where) update_control() end_special_activity() @@ -4580,7 +4518,6 @@ states.bribe_space = { view.actions.next = 0 }, piece(p) { - //push_undo() remove_piece(p) update_control() if (game.sa.targeted || is_base(p)) { @@ -4594,7 +4531,6 @@ states.bribe_space = { transfer_or_remove_shipments() }, flip() { - //push_undo() game.state = "bribe_flip" game.sa.count = 2 game.sa.piece = -1 @@ -4618,7 +4554,7 @@ states.bribe_flip = { set_delete(view.actions.piece, game.sa.piece) // No need to do maximum damage... - view.actions.next = 1 + view.actions.next = 1 // TODO skip? }, piece(p) { if (is_underground(p)) @@ -4633,7 +4569,6 @@ states.bribe_flip = { resume_bribe() }, next() { - //push_undo() resume_bribe() }, } @@ -4659,9 +4594,11 @@ states.event = { view.actions.shaded = 1 }, unshaded() { + push_undo() execute_event(0) }, shaded() { + push_undo() execute_event(1) }, } @@ -4710,7 +4647,14 @@ function goto_vm(start) { vm_exec() } -function event_prompt(str) { +function event_prompt(str, n) { + if (n !== undefined) { + str = str.replace(/\bN\b/, n) + if (n === 1) + str = str.replace("(s)", "") + else + str = str.replace("(s)", "s") + } view.prompt = data.card_title[this_card()] + ": " + str } @@ -4810,14 +4754,6 @@ function vm_mark_space() { vm_next() } -function vm_mark_piece() { - if (game.vm.m) - set_add(game.vm.m, game.vm.p) - else - game.vm.m = [ game.vm.p ] - vm_next() -} - function vm_save_space() { game.vm._ss = game.vm.ss game.vm._s = game.vm.s @@ -4834,22 +4770,6 @@ function vm_restore_space() { vm_next() } -function vm_save_piece() { - game.vm._pp = game.vm.pp - game.vm._p = game.vm.p - game.vm.pp = [] - game.vm.p = -1 - vm_next() -} - -function vm_restore_piece() { - game.vm.pp = game.vm._pp - game.vm.p = game.vm._p - delete game.vm._pp - delete game.vm._p - vm_next() -} - function vm_if() { if (vm_operand(1)) vm_next() @@ -4912,13 +4832,9 @@ states.vm_space = { let n = CODE[game.vm.pc][1] let f = CODE[game.vm.pc][2] if (game.vm.prompt) - event_prompt(CODE[game.vm.prompt][1]) - else if (n === 0) - event_prompt("Select each space.") - else if (n === 1) - event_prompt("Select one space.") + event_prompt(CODE[game.vm.prompt][1], n) else - event_prompt(`Select ${n} spaces.`) + event_prompt("Select N space(s).", n) for (let s = first_space; s <= last_space; ++s) if (!set_has(game.vm.ss, s) && f(s)) gen_action_space(s) @@ -4926,7 +4842,6 @@ states.vm_space = { view.actions.end_event = 1 }, space(s) { - push_undo() set_add(game.vm.ss, s) game.vm.s = s vm_next() @@ -4971,16 +4886,12 @@ function can_vm_piece() { states.vm_piece = { prompt() { - let n = CODE[game.vm.pc][1] + let n = CODE[game.vm.pc][1] - game.vm.pp.length let f = CODE[game.vm.pc][2] if (game.vm.prompt) - event_prompt(CODE[game.vm.prompt][1]) - else if (n === 0) - event_prompt("Select each piece.") - else if (n === 1) - event_prompt("Select one piece.") + event_prompt(CODE[game.vm.prompt][1], n) else - event_prompt(`Select ${n} pieces.`) + event_prompt("Select N piece(s).", n) for (let p = all_first_piece; p <= all_last_piece; ++p) if (game.pieces[p] >= 0 && !set_has(game.vm.pp, p) && f(p, game.pieces[p])) gen_action_piece(p) @@ -4988,7 +4899,6 @@ states.vm_piece = { view.actions.end_event = 1 }, piece(p) { - push_undo() set_add(game.vm.pp, p) game.vm.p = p vm_next() @@ -5005,7 +4915,7 @@ states.vm_transfer = { let from = vm_operand(1) let to = vm_operand(2) let n = vm_operand(3) - event_prompt(`Transfer ${n} resources from ${faction_name[from]} to ${faction_name[to]}.`) + event_prompt(`Transfer ${n} Resources from ${faction_name[from]} to ${faction_name[to]}.`) gen_action_resources(from) }, resources(_) { @@ -5065,11 +4975,10 @@ states.vm_aid = { if (n >= 0) event_prompt(`Aid +${n}.`) else - event_prompt(`Aid -${n}.`) + event_prompt(`Aid ${n}.`) view.actions.aid = 1 }, aid() { - push_undo() let n = vm_operand(1) add_aid(n) vm_next() @@ -5114,22 +5023,6 @@ states.vm_current = { }, } -states.vm_current_farc_or_auc = { - prompt() { - event_prompt("Select FARC or AUC.") - view.actions.farc = 1 - view.actions.auc = 1 - }, - farc() { - game.current = FARC - vm_next() - }, - auc() { - game.current = AUC - vm_next() - }, -} - function vm_place_opt() { game.vm.opt = 1 if (can_vm_place()) @@ -5147,7 +5040,7 @@ function vm_place() { } function can_vm_place_imp(faction, type) { - if (type === BASE && !can_place_base(game.vm.s)) + if (type === BASE && !can_stack_base(game.vm.s)) return false if (game.current === faction) return true @@ -5185,20 +5078,20 @@ states.vm_place = { view.where = game.vm.s let skip = game.vm.opt if (typeof faction === "object" && typeof type === "object") { - event_prompt(`Place piece in ${space_name[game.vm.s]}.`) + event_prompt(`Place piece in ${where}.`) for (let f of faction) for (let t of type) skip |= gen_place_piece(game.vm.s, f, t) } else if (typeof faction === "object") { - event_prompt(`Place ${piece_type_name[type]} in ${space_name[game.vm.s]}.`) + event_prompt(`Place ${piece_type_name[type]} in ${where}.`) for (let f of faction) skip |= gen_place_piece(game.vm.s, f, type) } else if (typeof type === "object") { - event_prompt(`Place ${faction_name[faction]} piece in ${space_name[game.vm.s]}.`) + event_prompt(`Place ${faction_name[faction]} piece in ${where}.`) for (let t of type) skip |= gen_place_piece(game.vm.s, faction, t) } else { - event_prompt(`Place ${piece_name[faction][type]} in ${space_name[game.vm.s]}.`) + event_prompt(`Place ${piece_name[faction][type]} in ${where}.`) skip |= gen_place_piece(game.vm.s, faction, type) } if (skip) @@ -5250,12 +5143,12 @@ function can_vm_place_any() { return true if (faction === GOVT) return ( - (has_piece(AVAILABLE, GOVT, BASE) && can_place_base(game.vm.s)) || + (has_piece(AVAILABLE, GOVT, BASE) && can_stack_base(game.vm.s)) || has_piece(AVAILABLE, GOVT, TROOPS) || has_piece(AVAILABLE, GOVT, POLICE) ) return ( - (has_piece(AVAILABLE, faction, BASE) && can_place_base(game.vm.s)) || + (has_piece(AVAILABLE, faction, BASE) && can_stack_base(game.vm.s)) || has_piece(AVAILABLE, faction, GUERRILLA) ) } @@ -5264,7 +5157,8 @@ states.vm_place_any = { prompt() { let faction = vm_operand(1) event_prompt(`Place any piece in ${space_name[game.vm.s]}.`) - if (can_place_base(game.vm.s)) + view.where = game.vm.s + if (can_stack_base(game.vm.s)) gen_place_piece(game.vm.s, faction, BASE) if (faction === GOVT) { gen_place_piece(game.vm.s, faction, TROOPS) @@ -5280,6 +5174,26 @@ states.vm_place_any = { }, } +function vm_remove_shipment() { + if (is_any_shipment_held()) + game.state = "vm_remove_shipment" + else + vm_next() +} + +states.vm_remove_shipment = { + prompt() { + event_prompt("Remove Shipment.") + for (let sh = 0; sh < 4; ++sh) + if (is_shipment_held(sh)) + gen_action_shipment(sh) + }, + shipment(sh) { + remove_shipment(sh) + vm_next() + }, +} + function vm_remove() { remove_piece(game.vm.p) update_control() @@ -5319,10 +5233,6 @@ function vm_underground() { vm_next() } -function vm_remove_or_end() { - game.state = "vm_remove_or_end" -} - function vm_set_passive_support_or_passive_opposition() { game.state = "vm_set_passive_support_or_passive_opposition" } @@ -5330,6 +5240,7 @@ function vm_set_passive_support_or_passive_opposition() { states.vm_set_passive_support_or_passive_opposition = { prompt() { event_prompt(`Set ${space_name[game.vm.s]} to Passive Support or Opposition.`) + view.where = game.vm.s view.actions.support = 1 view.actions.opposition = 1 }, @@ -5418,12 +5329,6 @@ function vm_place_shipment() { vm_next() } -function vm_remove_shipment() { - game.state = "vm_remove_shipment" -} - -// VM: FREE OPERATIONS - function vm_free_sweep_or_assault() { game.state = "vm_free_sweep_or_assault" } @@ -5431,6 +5336,7 @@ function vm_free_sweep_or_assault() { states.vm_free_sweep_or_assault = { prompt() { event_prompt(`Free Sweep or Assault in ${space_name[game.vm.s]}.`) + view.where = game.vm.s view.actions.sweep = 1 view.actions.assault = 1 }, @@ -5445,6 +5351,7 @@ function vm_free_sweep_or_assault_farc() { states.vm_free_sweep_or_assault_farc = { prompt() { event_prompt(`Free Sweep or Assault FARC in ${space_name[game.vm.s]}.`) + view.where = game.vm.s view.actions.sweep = 1 if (can_assault(game.vm.s, FARC)) view.actions.assault = 1 @@ -5462,6 +5369,7 @@ function vm_free_attack_or_terror() { states.vm_free_attack_or_terror = { prompt() { event_prompt(`Free Attack or Terror in ${space_name[game.vm.s]}.`) + view.where = game.vm.s if (has_enemy_piece(game.vm.s)) view.actions.attack = 1 else @@ -5472,8 +5380,6 @@ states.vm_free_attack_or_terror = { terror: vm_free_terror_space, } -// VM: FREE ACTIVITIES - function vm_free_govt_activity() { game.state = "vm_free_govt_activity" } @@ -6193,7 +6099,7 @@ const CODE = [ [ vm_return ], // SHADED 21 [ vm_resources, FARC, 6 ], - [ vm_space, 1, (s)=>(is_city(s) || is_dept(s)) && can_place_base(s) ], + [ vm_space, 1, (s)=>(is_city(s) || is_dept(s)) && can_stack_base(s) ], [ vm_place, FARC, BASE ], [ vm_endspace ], [ vm_return ], @@ -6284,7 +6190,7 @@ const CODE = [ [ vm_endspace ], [ vm_return ], // SHADED 28 - [ vm_space, 1, (s)=>is_dept(s) && is_next_to_venezuela(s) && can_place_base(s) ], + [ vm_space, 1, (s)=>is_dept(s) && is_next_to_venezuela(s) && can_stack_base(s) ], [ vm_place, FARC, BASE ], [ vm_endspace ], [ vm_space, 0, (s)=>is_loc(s) && is_adjacent(CUCUTA, s) && is_empty(s) ], @@ -6302,7 +6208,7 @@ const CODE = [ [ vm_return ], // SHADED 29 [ vm_current, [FARC,AUC] ], - [ vm_piece, 2, (p,s)=>is_piece(p, game.current, GUERRILLA) && has_enemy_piece(s) ], + [ vm_piece, 2, (p,s)=>is_faction_guerrilla(p, game.current) && has_enemy_piece(s) ], [ vm_free_ambush ], [ vm_underground ], [ vm_endpiece ], @@ -6583,7 +6489,7 @@ const CODE = [ [ vm_current, [FARC,AUC,CARTELS] ], [ vm_prompt, "Execute free Terror with any Guerrilla." ], [ vm_space, 1, (s)=>has_piece(s, game.current, GUERRILLA) ], - [ vm_piece, 1, (p,s)=>is_piece_in_event_space(p) && is_piece(p, game.current, GUERRILLA) ], + [ vm_piece, 1, (p,s)=>is_piece_in_event_space(p) && is_faction_guerrilla(p, game.current) ], [ vm_free_terror ], [ vm_terror ], [ vm_terror_aid_cut ], @@ -6681,7 +6587,7 @@ const CODE = [ [ vm_endspace ], [ vm_return ], // SHADED 52 - [ vm_space, 1, (s)=>has_auc_piece(s) && can_place_base(s) ], + [ vm_space, 1, (s)=>has_auc_piece(s) && can_stack_base(s) ], [ vm_place, AUC, BASE ], [ vm_endspace ], [ vm_piece, 0, (p,s)=>is_auc_base(p) ], @@ -6728,13 +6634,15 @@ const CODE = [ // EVENT 55 [ vm_remove_shipment ], [ vm_remove_shipment ], + [ vm_prompt, "Remove N Cartels Guerrillas." ], [ vm_piece, 5, (p,s)=>is_cartels_guerrilla(p) ], [ vm_remove ], [ vm_endpiece ], [ vm_aid, 3 ], [ vm_return ], // SHADED 55 - [ vm_space, 3, (s)=>has_cartel_piece(s) ], + [ vm_prompt, "Shift N spaces with Cartels pieces 1 level toward Active Opposition." ], + [ vm_space, 3, (s)=>has_cartels_piece(s) && !is_active_opposition(s) ], [ vm_shift_opposition ], [ vm_endspace ], [ vm_return ], @@ -6745,7 +6653,7 @@ const CODE = [ [ vm_piece, 0, (p,s)=>is_cartels_piece(p) && is_city(s) ], [ vm_resources, CARTELS, 2 ], [ vm_endpiece ], - [ vm_space, 2, (s)=>is_city(s) && can_place_base(s) ], + [ vm_space, 2, (s)=>is_city(s) && can_stack_base(s) ], [ vm_place, CARTELS, BASE ], [ vm_endspace ], [ vm_return ], @@ -6813,7 +6721,7 @@ const CODE = [ [ vm_return ], // SHADED 60 [ vm_current, CARTELS ], - [ vm_space, 2, (s)=>is_city(s) && can_place_base(s) ], + [ vm_space, 2, (s)=>is_city(s) && can_stack_base(s) ], [ vm_place, CARTELS, BASE ], [ vm_endspace ], [ vm_space, 1, (s)=>is_space(s) ], @@ -6829,7 +6737,7 @@ const CODE = [ [ vm_resources, CARTELS, -6 ], [ vm_return ], // SHADED 61 - [ vm_space, 3, (s)=>!has_cartels_piece(s) && can_place_base(s) ], + [ vm_space, 3, (s)=>!has_cartels_piece(s) && can_stack_base(s) ], [ vm_place, CARTELS, BASE ], [ vm_endspace ], [ vm_return ], @@ -6884,7 +6792,7 @@ const CODE = [ [ vm_endpiece ], [ vm_return ], // SHADED 66 - [ vm_space, 0, (s)=>is_forest(s) && has_cartels_base(s) && can_place_base(s) ], + [ vm_space, 0, (s)=>is_forest(s) && has_cartels_base(s) && can_stack_base(s) ], [ vm_place, CARTELS, BASE ], [ vm_endspace ], [ vm_return ], @@ -6916,7 +6824,7 @@ const CODE = [ // SHADED 70 [ vm_current, [FARC,AUC,CARTELS] ], [ vm_space, 0, (s)=>is_forest(s) && has_piece(s, game.current, GUERRILLA) ], - [ vm_piece, 1, (p,s)=>is_piece_in_event_space(p) && is_piece(p, game.current, GUERRILLA) ], + [ vm_piece, 1, (p,s)=>is_piece_in_event_space(p) && is_faction_guerrilla(p, game.current) ], [ vm_free_terror ], [ vm_resources, ()=>(game.current), 3 ], [ vm_endpiece ], @@ -6954,4 +6862,4 @@ const CODE = [ [ vm_endwhile ], [ vm_return ], ] -const CODE_INDEX = [ 0, 3, 6, 9, 12, 15, 18, 23, 28, 58, 64, 69, 78, 81, 84, 89, 91, 94, 97, 100, 103, 106, 109, 112, 115, 118, 121, 129, 138, 141, 145, 150, 152, 155, 158, 161, 165, -1, 176, 182, 188, 193, 198, 202, 205, 214, 221, 226, 235, 241, 247, 252, 257, 262, 265, 271, 278, 286, 292, 299, 332, 339, 343, 347, 349, 355, 361, 363, 370, 378, 383, -1, 416, 421, 429, 435, 441, 445, 453, 460, 475, 482, 487, 492, 496, 504, 510, 515, 520, 524, 531, -1, 548, 555, -1, 569, 573, 577, 582, 593, 599, 608, 613, 617, 624, -1, 641, -1, 655, 662, 666, 668, 675, 682, 690, 695, 703, 711, 723, 730, 738, 745, 749, 753, 757, -1, 769, 774, -1, -1, 783, 787, 791, 793, -1, 796, -1, -1, 801, 806, 815, 821, 827, 834 ] +const CODE_INDEX = [ 0, 3, 6, 9, 12, 15, 18, 23, 28, 58, 64, 69, 78, 81, 84, 89, 91, 94, 97, 100, 103, 106, 109, 112, 115, 118, 121, 129, 138, 141, 145, 150, 152, 155, 158, 161, 165, -1, 176, 182, 188, 193, 198, 202, 205, 214, 221, 226, 235, 241, 247, 252, 257, 262, 265, 271, 278, 286, 292, 299, 332, 339, 343, 347, 349, 355, 361, 363, 370, 378, 383, -1, 416, 421, 429, 435, 441, 445, 453, 460, 475, 482, 487, 492, 496, 504, 510, 515, 520, 524, 531, -1, 548, 555, -1, 569, 573, 577, 582, 593, 599, 608, 613, 617, 624, -1, 641, -1, 655, 663, 668, 670, 677, 684, 692, 697, 705, 713, 725, 732, 740, 747, 751, 755, 759, -1, 771, 776, -1, -1, 785, 789, 793, 795, -1, 798, -1, -1, 803, 808, 817, 823, 829, 836 ] diff --git a/tools/gendata.js b/tools/gendata.js index f417f12..5e30f35 100644 --- a/tools/gendata.js +++ b/tools/gendata.js @@ -304,16 +304,12 @@ def_space("forest", 0, "Guainía") def_space("forest", 0, "Vaupés") def_space("forest", 0, "Amazonas") -data.last_dept = spaces.length-1 - // Foreign Countries -data.first_foreign = spaces.length - def_space("foreign", 0, "Ecuador") def_space("foreign", 0, "Panamá") -data.last_foreign = spaces.length-1 +data.last_dept = spaces.length-1 // LoC |