summaryrefslogtreecommitdiff
path: root/rules.js
diff options
context:
space:
mode:
Diffstat (limited to 'rules.js')
-rw-r--r--rules.js618
1 files changed, 263 insertions, 355 deletions
diff --git a/rules.js b/rules.js
index 6bc4a8d..e5d7c33 100644
--- a/rules.js
+++ b/rules.js
@@ -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 ]