diff options
Diffstat (limited to 'rules.js')
-rw-r--r-- | rules.js | 1501 |
1 files changed, 695 insertions, 806 deletions
@@ -4,8 +4,9 @@ // TODO: auto-next at end of Special Activity / operation 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) -// TODO: how granular undo (one at start of each space, each step, or each piece?) +// TODO: mark faction ineligible/eligible + +// TODO: check stacking of ecuador on move/place let states = {} let game = null @@ -438,160 +439,139 @@ function setup_remove_piece(faction, type, count, where) { } } -function count_pieces(s, faction, type) { - let first = first_piece[faction][type] - let last = last_piece[faction][type] - let n = 0 - for (let p = first; p <= last; ++p) - if (game.pieces[p] === s) - ++n - return n -} +// === MISC PIECE QUERIES === -function add_resources(faction, n) { - game.resources[faction] = Math.max(0, Math.min(99, game.resources[faction] + n)) +function piece_faction(p) { + if (p >= first_piece[GOVT][TROOPS] && p <= last_piece[GOVT][TROOPS]) + return GOVT + if (p >= first_piece[GOVT][POLICE] && p <= last_piece[GOVT][POLICE]) + return GOVT + if (p >= first_piece[GOVT][BASE] && p <= last_piece[GOVT][BASE]) + return GOVT + if (p >= first_piece[FARC][GUERRILLA] && p <= last_piece[FARC][GUERRILLA]) + return FARC + if (p >= first_piece[FARC][BASE] && p <= last_piece[FARC][BASE]) + return FARC + if (p >= first_piece[AUC][GUERRILLA] && p <= last_piece[AUC][GUERRILLA]) + return AUC + if (p >= first_piece[AUC][BASE] && p <= last_piece[AUC][BASE]) + return AUC + if (p >= first_piece[CARTELS][GUERRILLA] && p <= last_piece[CARTELS][GUERRILLA]) + return CARTELS + if (p >= first_piece[CARTELS][BASE] && p <= last_piece[CARTELS][BASE]) + return CARTELS + throw "IMPOSSIBLE" } -function add_aid(n) { - game.aid = Math.max(0, Math.min(29, game.aid + n)) +function target_faction(p) { + return 1 << piece_faction(p) } function is_enemy_piece(p) { return piece_faction(p) !== game.current } -function is_govt_base(p) { - return p >= first_piece[GOVT][BASE] && p <= last_piece[GOVT][BASE] -} - -function is_police(p) { - return p >= first_piece[GOVT][POLICE] && p <= last_piece[GOVT][POLICE] -} - -function is_troops(p) { - return p >= first_piece[GOVT][TROOPS] && p <= last_piece[GOVT][TROOPS] -} - -function is_faction_guerrilla(p, faction) { - return p >= first_piece[faction][GUERRILLA] && p <= last_piece[faction][GUERRILLA] +function is_piece(p, faction, type) { + return p >= first_piece[faction][type] && p <= last_piece[faction][type] } -function is_farc_base(p) { - return p >= first_piece[FARC][BASE] && p <= last_piece[FARC][BASE] -} +function is_govt_base(p) { return is_piece(p, GOVT, BASE) } +function is_troops(p) { return is_piece(p, GOVT, TROOPS) } +function is_police(p) { return is_piece(p, GOVT, POLICE) } +function is_cube(p) { return is_troops(p) || is_police(p) } +function is_govt_piece(p) { return is_govt_base(p) || is_cube(p) } -function is_farc_guerrilla(p) { - return p >= first_piece[FARC][GUERRILLA] && p <= last_piece[FARC][GUERRILLA] -} - -function is_farc_piece(p) { - return is_farc_base(p) || is_farc_guerrilla(p) -} +function is_farc_base(p) { return is_piece(p, FARC, BASE) } +function is_farc_guerrilla(p) { return is_piece(p, FARC, GUERRILLA) } +function is_farc_piece(p) { return is_farc_base(p) || is_farc_guerrilla(p) } -function is_auc_base(p) { - return p >= first_piece[AUC][BASE] && p <= last_piece[AUC][BASE] -} +function is_auc_base(p) { is_piece(p, AUC, BASE) } +function is_auc_guerrilla(p) { is_piece(p, AUC, GUERRILLA) } +function is_auc_piece(p) { return is_auc_base(p) || is_auc_guerrilla(p) } -function is_auc_guerrilla(p) { - return p >= first_piece[AUC][GUERRILLA] && p <= last_piece[AUC][GUERRILLA] -} +function is_cartels_base(p) { is_piece(p, CARTELS, BASE) } +function is_cartels_guerrilla(p) { is_piece(p, CARTELS, GUERRILLA) } +function is_cartels_piece(p) { return is_cartels_base(p) || is_cartels_guerrilla(p) } -function is_auc_piece(p) { - return is_auc_base(p) || is_auc_guerrilla(p) +function is_faction_guerrilla(p, faction) { + return is_piece(p, faction, GUERRILLA) } -function is_cartels_base(p) { - return p >= first_piece[CARTELS][BASE] && p <= last_piece[CARTELS][BASE] +function is_base(p) { + return is_govt_base(p) || is_farc_base(p) || is_auc_base(p) || is_cartels_base(p) } -function is_cartels_guerrilla(p) { - return p >= first_piece[CARTELS][GUERRILLA] && p <= last_piece[CARTELS][GUERRILLA] +function is_guerrilla(p) { + return is_farc_guerrilla(p) || is_auc_guerrilla(p) || is_cartels_guerrilla(p) } -function is_cartels_piece(p) { - return is_cartels_base(p) || is_cartels_guerrilla(p) +function is_insurgent_piece(p) { + return is_farc_piece(p) || is_auc_piece(p) || is_cartels_piece(p) } -function is_base(p) { - if (p >= first_piece[GOVT][BASE] && p <= last_piece[GOVT][BASE]) - return true - if (p >= first_piece[FARC][BASE] && p <= last_piece[FARC][BASE]) - return true - if (p >= first_piece[AUC][BASE] && p <= last_piece[AUC][BASE]) - return true - if (p >= first_piece[CARTELS][BASE] && p <= last_piece[CARTELS][BASE]) - return true - return false -} +// === MISC SPACE + PIECE QUERIES === -function target_faction(p) { - if (p >= first_piece[GOVT][TROOPS] && p <= last_piece[GOVT][TROOPS]) - return 1 << GOVT - if (p >= first_piece[GOVT][POLICE] && p <= last_piece[GOVT][POLICE]) - return 1 << GOVT - if (p >= first_piece[GOVT][BASE] && p <= last_piece[GOVT][BASE]) - return 1 << GOVT - if (p >= first_piece[FARC][GUERRILLA] && p <= last_piece[FARC][GUERRILLA]) - return 1 << FARC - if (p >= first_piece[FARC][BASE] && p <= last_piece[FARC][BASE]) - return 1 << FARC - if (p >= first_piece[AUC][GUERRILLA] && p <= last_piece[AUC][GUERRILLA]) - return 1 << AUC - if (p >= first_piece[AUC][BASE] && p <= last_piece[AUC][BASE]) - return 1 << AUC - if (p >= first_piece[CARTELS][GUERRILLA] && p <= last_piece[CARTELS][GUERRILLA]) - return 1 << CARTELS - if (p >= first_piece[CARTELS][BASE] && p <= last_piece[CARTELS][BASE]) - return 1 << CARTELS - return 0 +function count_pieces(s, faction, type) { + let first = first_piece[faction][type] + let last = last_piece[faction][type] + let n = 0 + for (let p = first; p <= last; ++p) + if (game.pieces[p] === s) + ++n + return n } -function piece_faction(p) { - if (p >= first_piece[GOVT][TROOPS] && p <= last_piece[GOVT][TROOPS]) - return GOVT - if (p >= first_piece[GOVT][POLICE] && p <= last_piece[GOVT][POLICE]) - return GOVT - if (p >= first_piece[GOVT][BASE] && p <= last_piece[GOVT][BASE]) - return GOVT - if (p >= first_piece[FARC][GUERRILLA] && p <= last_piece[FARC][GUERRILLA]) - return FARC - if (p >= first_piece[FARC][BASE] && p <= last_piece[FARC][BASE]) - return FARC - if (p >= first_piece[AUC][GUERRILLA] && p <= last_piece[AUC][GUERRILLA]) - return AUC - if (p >= first_piece[AUC][BASE] && p <= last_piece[AUC][BASE]) - return AUC - if (p >= first_piece[CARTELS][GUERRILLA] && p <= last_piece[CARTELS][GUERRILLA]) - return CARTELS - if (p >= first_piece[CARTELS][BASE] && p <= last_piece[CARTELS][BASE]) - return CARTELS - return 0 +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 did_maximum_damage(targeted) { - if (view.actions.piece) - for (let p of view.actions.piece) - if (targeted & target_faction(p)) - return false - return true +function count_bases(s) { + return ( + count_pieces(s, GOVT, BASE) + + count_pieces(s, FARC, BASE) + + count_pieces(s, AUC, BASE) + + count_pieces(s, CARTELS, BASE) + ) } -function has_momentum(c) { - return set_has(game.momentum, c) +function count_cubes(s) { + return count_pieces(s, GOVT, TROOPS) + count_pieces(s, GOVT, POLICE) } -function has_capability(c) { - return set_has(game.capabilities, c) +function count_faction_underground_guerrillas(s, faction) { + let first = first_piece[faction][GUERRILLA] + let last = last_piece[faction][GUERRILLA] + let n = 0 + for (let p = first; p <= last; ++p) + if (game.pieces[p] === s && is_underground(p)) + ++n + return n } -function has_shaded_capability(c) { - return set_has(game.capabilities, -c) +function count_any_underground_guerrillas(s) { + return ( + count_faction_underground_guerrillas(s, FARC) + + count_faction_underground_guerrillas(s, AUC) + + count_faction_underground_guerrillas(s, CARTELS) + ) } -function is_piece(p, faction, type) { +function find_piece(s, faction, type) { let first = first_piece[faction][type] let last = last_piece[faction][type] - return p >= first && p <= last + for (let p = first; p <= last; ++p) + if (game.pieces[p] === s) + return p + return -1 } function has_piece(s, faction, type) { @@ -621,34 +601,6 @@ function has_underground_guerrilla(s, faction) { return false } -function count_underground_guerrillas(s, faction) { - let first = first_piece[faction][GUERRILLA] - let last = last_piece[faction][GUERRILLA] - let n = 0 - for (let p = first; p <= last; ++p) - if (game.pieces[p] === s && is_underground(p)) - ++n - return n -} - -function find_underground_guerrilla(s, faction) { - let first = first_piece[faction][GUERRILLA] - let last = last_piece[faction][GUERRILLA] - for (let p = first; p <= last; ++p) - if (game.pieces[p] === s && is_underground(p)) - return p - return -1 -} - -function find_guerrilla(s, faction) { - let first = first_piece[faction][GUERRILLA] - let last = last_piece[faction][GUERRILLA] - for (let p = first; p <= last; ++p) - if (game.pieces[p] === s) - return p - return -1 -} - function has_any_guerrilla(s) { return ( has_piece(s, FARC, GUERRILLA) || @@ -657,92 +609,92 @@ function has_any_guerrilla(s) { ) } -function count_bases(s) { - return ( - count_pieces(s, GOVT, BASE) + - count_pieces(s, FARC, BASE) + - count_pieces(s, AUC, BASE) + - count_pieces(s, CARTELS, BASE) - ) +function has_troops(s) { return has_piece(s, GOVT, TROOPS) } +function has_police(s) { return has_piece(s, GOVT, POLICE) } +function has_cube(s) { return has_piece(s, GOVT, TROOPS) || has_piece(s, GOVT, POLICE) } +function has_govt_piece(s) { return has_piece(s, GOVT, BASE) || has_piece(s, GOVT, TROOPS) || has_piece(s, GOVT, POLICE) } + +function has_farc_guerrilla(s) { return has_piece(s, FARC, GUERRILLA) } +function has_farc_piece(s) { return has_piece(s, FARC, BASE) || has_piece(s, FARC, GUERRILLA) } + +function has_auc_piece(s) { return has_piece(s, AUC, BASE) || has_piece(s, AUC, GUERRILLA) } + +function has_cartels_base(s) { return has_piece(s, CARTELS, BASE) } +function has_cartels_guerrilla(s) { return has_piece(s, CARTELS, GUERRILLA) } +function has_cartels_piece(s) { return has_piece(s, CARTELS, BASE) || has_piece(s, CARTELS, GUERRILLA) } + +function has_faction_piece(s, faction) { + if (faction === GOVT) + return has_piece(s, GOVT, BASE) || has_piece(s, GOVT, TROOPS) || has_piece(s, GOVT, POLICE) + return has_piece(s, faction, BASE) || has_piece(s, faction, GUERRILLA) } -// TODO: faction for ECUADOR check -function can_stack_base(s) { - return count_bases(s) < 2 +function is_empty(s) { + return !( + has_faction_piece(s, GOVT) || + has_faction_piece(s, FARC) || + has_faction_piece(s, AUC) || + has_faction_piece(s, CARTELS) + ) } -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 has_enemy_piece(s) { + if (game.current !== GOVT && has_faction_piece(s, GOVT)) + return true + if (game.current !== FARC && has_faction_piece(s, FARC)) + return true + if (game.current !== AUC && has_faction_piece(s, AUC)) + return true + if (game.current !== CARTELS && has_faction_piece(s, CARTELS)) + return true + return false } -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) - } +// === MISC SPACE QUERIES === + +function is_adjacent(a, b) { + return set_has(data.spaces[a].adjacent, b) } -function count_cubes(s) { +function is_coastal_space(s) { return ( - count_pieces(s, GOVT, TROOPS) + - count_pieces(s, GOVT, POLICE) + s === CESAR || + s === SANTA_MARTA || + s === ATLANTICO || + s === CARTAGENA || + s === SINCELEJO || + s === CHOCO || + s === NARINO || + s === PANAMA || + s === ECUADOR || + s === PASTO_TUMACO || + s === CALI_BUENAVENTURA || + s === CARTAGENA_SINCELEJO || + s === SANTA_MARTA_CARTAGENA ) } -function count_any_underground_guerrillas(s) { +function is_next_to_ecuador(s) { return ( - count_underground_guerrillas(s, FARC) + - count_underground_guerrillas(s, AUC) + - count_underground_guerrillas(s, CARTELS) + s === NARINO || + s === PASTO || + s === PUTUMAYO || + s === ARAUCA || + s === PASTO_TUMACO ) } -function update_control() { - game.govt_control = 0 - game.farc_control = 0 - for (let s = first_space; s <= last_dept; ++s) { - 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) - game.farc_control |= (1 << s) - } -} - -function has_auc_control(s) { - // AUC outnumber all other forces - 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 -} - -function is_city(s) { - return s >= first_city && s <= last_city +function is_next_to_venezuela(s) { + return ( + s === CESAR || + s === CUCUTA || + s === SANTANDER || + s === ARAUCA || + s === VICHADA || + s === GUAINIA || + s === CUCUTA_AYACUCHO || + s === CUCUTA_ARAUCA + ) } function is_space(s) { @@ -761,12 +713,12 @@ function is_dept(s) { return s >= first_dept && s <= last_dept } -function is_loc(s) { - return s >= first_loc && s <= last_loc +function is_city(s) { + return s >= first_city && s <= last_city } -function is_city_or_loc(s) { - return (s >= first_city && s <= last_city) || (s >= first_loc && s <= last_loc) +function is_loc(s) { + return s >= first_loc && s <= last_loc } function is_pop(s) { @@ -785,128 +737,34 @@ function is_forest(s) { return data.spaces[s].type === "forest" } -function is_adjacent(a, b) { - return set_has(data.spaces[a].adjacent, b) -} - -function is_farc_zone(s) { - return set_has(game.farc_zones, s) -} - -function is_empty(s) { - return !( - has_any_piece(s, GOVT) || - has_any_piece(s, FARC) || - has_any_piece(s, AUC) || - has_any_piece(s, CARTELS) - ) -} - -function faction_with_most_pieces(s) { - 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) - return FARC - if (a > g && a > f && a > c) - return AUC - if (c > g && c > f && c > a) - return CARTELS - return GOVT -} - -function is_guerrilla(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 true - } - return false -} - -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] - 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)) - } -} - -function remove_piece(p) { - let s = game.pieces[p] - drop_held_shipments(p) - set_underground(p) - game.pieces[p] = AVAILABLE - // auto_transfer_dropped_shipments(s) -} - -function place_piece(p, s) { - set_underground(p) - game.pieces[p] = s +function is_city_or_loc(s) { + return is_city(s) || is_loc(s) } -function move_piece(p, s) { - game.pieces[p] = s +function is_zero_pop_dept(s) { + return !is_pop(s) && is_dept(s) } -function count_terror_and_sabotage() { - let n = (game.sabotage.length >> 1) - for (let i = 1; i < game.terror.length; i += 2) - n += game.terror[i] - return n +function is_zero_pop_forest(s) { + return !is_pop(s) && is_forest(s) } -function place_terror(s) { - if (count_terror_and_sabotage() < 40) - map_set(game.terror, s, map_get(game.terror, s, 0) + 1) -} +// === MISC DYNAMIC QUERIES === -function place_sabotage(s) { - if (count_terror_and_sabotage() < 40) - set_add(game.sabotage, s) +function has_momentum(c) { + return set_has(game.momentum, c) } -function has_sabotage(s) { - return set_has(game.sabotage, s) +function has_capability(c) { + return set_has(game.capabilities, c) } -function count_terror(s) { - return map_get(game.terror, s, 0) +function has_shaded_capability(c) { + return set_has(game.capabilities, -c) } -function has_terror(s) { - return map_get(game.terror, s, 0) > 0 +function is_farc_zone(s) { + return set_has(game.farc_zones, s) } function has_govt_control(s) { @@ -917,36 +775,13 @@ function has_farc_control(s) { return (s <= last_dept) && game.farc_control & (1 << s) } -function has_cartels_base(s) { - return has_piece(s, CARTELS, BASE) -} - -function has_farc_guerrilla(s) { - return has_piece(s, FARC, GUERRILLA) -} - -function has_cartels_guerrilla(s) { - return has_piece(s, CARTELS, GUERRILLA) -} - -function is_unsabotaged_pipeline(s) { - return is_pipeline(s) && !has_sabotage(s) -} - -function has_no_guerrilla(s) { - return !has_any_guerrilla(s) -} - -function has_auc_piece(s) { - return has_piece(s, AUC, BASE) || has_piece(s, AUC, GUERRILLA) -} - -function has_farc_piece(s) { - return has_piece(s, FARC, BASE) || has_piece(s, FARC, GUERRILLA) -} - -function has_cartels_piece(s) { - return has_piece(s, CARTELS, BASE) || has_piece(s, CARTELS, GUERRILLA) +function has_auc_control(s) { + // AUC outnumber all other forces + 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 } function is_neutral(s) { @@ -977,98 +812,72 @@ function is_opposition(s) { return is_pop(s) && game.support[s] < 0 } -function has_govt_piece(s) { - return has_piece(s, GOVT, BASE) || has_piece(s, GOVT, TROOPS) || has_piece(s, GOVT, POLICE) -} - -function has_cubes(s) { - return has_piece(s, GOVT, TROOPS) || has_piece(s, GOVT, POLICE) -} - -function has_troops(s) { - return has_piece(s, GOVT, TROOPS) -} - -function has_police(s) { - return has_piece(s, GOVT, POLICE) +function has_sabotage(s) { + return set_has(game.sabotage, s) } -function is_next_to_venezuela(s) { - return ( - s === CESAR || - s === CUCUTA || - s === SANTANDER || - s === ARAUCA || - s === VICHADA || - s === GUAINIA || - s === CUCUTA_AYACUCHO || - s === CUCUTA_ARAUCA - ) +function has_terror(s) { + return map_get(game.terror, s, 0) > 0 } -function is_next_to_ecuador(s) { - return ( - s === NARINO || - s === PASTO || - s === PUTUMAYO || - s === ARAUCA || - s === PASTO_TUMACO - ) +function count_terror(s) { + return map_get(game.terror, s, 0) } -function is_coastal_space(s) { - return ( - s === CESAR || - s === SANTA_MARTA || - s === ATLANTICO || - s === CARTAGENA || - s === SINCELEJO || - s === CHOCO || - s === NARINO || - s === PANAMA || - s === ECUADOR || - s === PASTO_TUMACO || - s === CALI_BUENAVENTURA || - s === CARTAGENA_SINCELEJO || - s === SANTA_MARTA_CARTAGENA - ) +function count_terror_and_sabotage() { + let n = (game.sabotage.length >> 1) + for (let i = 1; i < game.terror.length; i += 2) + n += game.terror[i] + return n } -function is_zero_pop_dept(s) { - return !is_pop(s) && is_dept(s) +function is_unsabotaged_pipeline(s) { + return is_pipeline(s) && !has_sabotage(s) } -function is_zero_pop_forest(s) { - return !is_pop(s) && is_forest(s) -} +// === MISC COMPOUND QUERIES == -function can_govt_civic_action(s) { - if (game.support[s] < 2 && has_govt_control(s)) { - if (has_shaded_capability(CAP_1ST_DIV)) - return count_pieces(s, GOVT, TROOPS) >= 2 && count_pieces(s, GOVT, POLICE) >= 2 - return has_piece(s, GOVT, TROOPS) && has_piece(s, GOVT, POLICE) +function is_possible_farc_zone(s) { + if (is_mountain(s) && !is_farc_zone(s)) { + let max = 0 + for (let x = first_dept; x <= last_dept; ++x) { + if (is_mountain(x) && !is_farc_zone(x)) { + let xn = count_pieces(x, FARC, BASE) + count_pieces(x, FARC, GUERRILLA) + if (xn > max) + max = xn + } + } + return count_pieces(s, FARC, BASE) + count_pieces(s, FARC, GUERRILLA) === max } return false } -function is_redeploy_troops_space(s) { - if (is_city(s) && has_govt_control(s)) - return true - if (s === BOGOTA) { - for (let x = first_city; x <= last_city; ++x) - if (has_govt_control(x)) - return false - return true +function is_highest_value_pipeline_without_cubes(s) { + let max = 0 + for (let x = first_loc; x <= last_loc; ++x) { + if (is_pipeline(x) && !has_cube(x)) { + let e = data.spaces[x].econ + if (e > max) + max = e + } } - return false + return data.spaces[s].econ === max } -function is_redeploy_police_space(s) { - if (is_loc(s)) - return true - if (has_govt_control(s)) - return true - return false +function faction_with_most_pieces(s) { + 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) + return FARC + if (a > g && a > f && a > c) + return AUC + if (c > g && c > f && c > a) + return CARTELS + return GOVT } function is_any_pipeline_sabotaged() { @@ -1078,116 +887,149 @@ function is_any_pipeline_sabotaged() { return false } -function adjacent_has_farc_guerrilla(s) { +function is_adjacent_to_3econ_loc(s) { for (let x of data.spaces[s].adjacent) - if (has_farc_guerrilla(x)) + if (is_loc(x) && data.spaces[x].econ === 3) + return true + return false +} + +function is_adjacent_to_3econ_pipeline(s) { + for (let x of data.spaces[s].adjacent) + if (is_pipeline(x) && data.spaces[x].econ === 3) return true return false } -function is_there_or_adjacent(s, list) { +function is_with_or_adjacent_to_mark(s, list) { for (let x of list) if (x === s || is_adjacent(x, s)) return true return false } -function is_adjacent_to_3econ_loc(s) { +function is_with_or_adjacent_to_farc_guerrilla(s) { + if (has_farc_guerrilla(s)) + return true for (let x of data.spaces[s].adjacent) - if (is_loc(x) && data.spaces[x].econ === 3) + if (has_farc_guerrilla(x)) return true return false } -function is_adjacent_to_3econ_pipeline(s) { +function is_adjacent_to_support(s) { for (let x of data.spaces[s].adjacent) - if (is_pipeline(x) && data.spaces[x].econ === 3) + if (is_support(x)) return true return false } -function is_possible_farc_zone(s) { - if (is_mountain(s) && !is_farc_zone(s)) { - let max = 0 - for (let x = first_dept; x <= last_dept; ++x) { - if (is_mountain(x) && !is_farc_zone(x)) { - let xn = count_pieces(x, FARC, BASE) + count_pieces(x, FARC, GUERRILLA) - if (xn > max) - max = xn - } - } - return count_pieces(s, FARC, BASE) + count_pieces(s, FARC, GUERRILLA) === max +function is_redeploy_troops_space(s) { + if (is_city(s) && has_govt_control(s)) + return true + if (s === BOGOTA) { + for (let x = first_city; x <= last_city; ++x) + if (has_govt_control(x)) + return false + return true } return false } -function for_each_piece(faction, type, f) { - let p0 = first_piece[faction][type] - let p1 = last_piece[faction][type] - for (let p = p0; p <= p1; ++p) - f(p) +function is_redeploy_police_space(s) { + if (is_loc(s)) + return true + if (has_govt_control(s)) + return true + return false } -function gen_piece_in_space(space, faction, type) { - for_each_piece(faction, type, p => { - if (game.pieces[p] === space) - gen_action_piece(p) - }) +// === MISC STATE COMMANDS == + +function update_control() { + game.govt_control = 0 + game.farc_control = 0 + for (let s = first_space; s <= last_dept; ++s) { + 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) + game.farc_control |= (1 << s) + } } -function gen_place_piece(space, faction, type) { - let p0 = first_piece[faction][type] - let p1 = last_piece[faction][type] - if (type === BASE && !can_stack_base(space)) - return true - let can_place = false - for (let p = p0; p <= p1; ++p) { - if (game.pieces[p] === AVAILABLE) { - gen_action_piece(p) - can_place = true - if (type === BASE) - break - } +function add_resources(faction, n) { + game.resources[faction] = Math.max(0, Math.min(99, game.resources[faction] + n)) +} + +function add_aid(n) { + game.aid = Math.max(0, Math.min(29, game.aid + n)) +} + +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)) } - if (!can_place && faction === game.current) { - for (let p = p0; p <= p1; ++p) - if (game.pieces[p] !== space || (type === GUERRILLA && !is_underground(p))) - gen_action_piece(p) +} + +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)) } - return !can_place } -function gen_underground_guerrillas(s, faction) { - for_each_piece(faction, GUERRILLA, p => { - if (game.pieces[p] === s) - if (is_underground(p)) - gen_action_piece(p) - }) +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)) + } } -function gen_active_guerrillas(s, faction) { - for_each_piece(faction, GUERRILLA, p => { - if (game.pieces[p] === s) - if (is_active(p)) - gen_action_piece(p) - }) +function is_active(p) { + return !is_underground(p) } -function gen_attack_piece(s, faction) { - if (faction === GOVT) { - gen_piece_in_space(s, GOVT, TROOPS) - gen_piece_in_space(s, GOVT, POLICE) - if (!has_piece(s, GOVT, TROOPS) && !has_piece(s, GOVT, POLICE)) - gen_piece_in_space(s, GOVT, BASE) - } else { - gen_piece_in_space(s, faction, GUERRILLA) - if (!has_piece(s, faction, GUERRILLA)) - gen_piece_in_space(s, faction, BASE) +function move_piece(p, s) { + game.pieces[p] = s +} + +function place_piece(p, s) { + set_underground(p) + game.pieces[p] = s +} + +function remove_piece(p) { + if (is_guerrilla(p)) { + // let s = game.pieces[p] + drop_held_shipments(p) + // TODO: auto_transfer_dropped_shipments(s) - immediate or wait? + set_underground(p) } + game.pieces[p] = AVAILABLE } +function place_terror(s) { + if (count_terror_and_sabotage() < 40) + map_set(game.terror, s, map_get(game.terror, s, 0) + 1) +} + +function place_sabotage(s) { + if (count_terror_and_sabotage() < 40) + set_add(game.sabotage, s) +} -// === SHIPMENTS === +// === SHIPMENT QUERIES AND COMMANDS === function place_shipment(sh, p) { game.shipments[sh] = p << 2 @@ -1240,13 +1082,6 @@ 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)) @@ -1292,23 +1127,23 @@ function auto_transfer_dropped_shipment_imp(sh) { let s = get_dropped_shipment_space(sh) let a, b, p - p = find_guerrilla(s, f) + p = find_piece(s, f, GUERRILLA) if (p >= 0) { place_shipment(sh, p) return } if (f === FARC) { - a = find_guerrilla(s, AUC) - b = find_guerrilla(s, CARTELS) + a = find_piece(s, AUC, GUERRILLA) + b = find_piece(s, CARTELS, GUERRILLA) } if (f === AUC) { - a = find_guerrilla(s, FARC) - b = find_guerrilla(s, CARTELS) + a = find_piece(s, FARC, GUERRILLA) + b = find_piece(s, CARTELS, GUERRILLA) } if (f === CARTELS) { - a = find_guerrilla(s, FARC) - b = find_guerrilla(s, AUC) + a = find_piece(s, FARC, GUERRILLA) + b = find_piece(s, AUC, GUERRILLA) } if (a >= 0 && b < 0) { @@ -1323,248 +1158,107 @@ function auto_transfer_dropped_shipment_imp(sh) { // nobody to pick it up... } -// === SEQUENCE OF PLAY === - -function this_card() { - return game.deck[0] -} - -function is_final_card() { - return false -} - -function goto_card() { - if (this_card() > 72) - goto_propaganda_card() - else - goto_event_card() -} - -function adjust_eligibility(faction) { - if (game.cylinder[faction] === INELIGIBLE || game.cylinder[faction] === SOP_PASS) - game.cylinder[faction] = ELIGIBLE - else if (game.cylinder[faction] !== ELIGIBLE) - game.cylinder[faction] = INELIGIBLE -} +// === ITERATORS AND ACTION GENERATORS === -function end_card() { - adjust_eligibility(GOVT) - adjust_eligibility(FARC) - adjust_eligibility(AUC) - adjust_eligibility(CARTELS) - - clear_undo() - array_remove(game.deck, 0) - goto_card() -} - -function is_eligible(faction) { - return game.cylinder[faction] === ELIGIBLE -} - -function next_eligible_faction() { - let order = data.card_order[this_card()] - for (let faction of order) - if (is_eligible(faction)) - return faction - return null -} - -function did_option(e) { - return ( - game.cylinder[GOVT] === e || - game.cylinder[FARC] === e || - game.cylinder[AUC] === e || - game.cylinder[CARTELS] === e - ) -} - -function goto_event_card() { - log_h1("C" + this_card()) - resume_event_card() +function can_stack_base(s) { + // TODO: faction for ECUADOR check + return count_bases(s) < 2 } -function resume_event_card() { - clear_undo() - let did_1st = (did_option(SOP_1ST_OP_ONLY) || did_option(SOP_1ST_OP_AND_SA) || did_option(SOP_1ST_EVENT)) - let did_2nd = (did_option(SOP_2ND_LIMOP) || did_option(SOP_2ND_LIMOP_OR_EVENT) || did_option(SOP_2ND_OP_AND_SA)) - if (did_1st) { - if (did_2nd) - end_card() +function can_stack_piece(s, faction, type) { + 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 - goto_eligible2() - } else { - goto_eligible1() + return false } + return true } -function goto_eligible1() { - game.current = next_eligible_faction() - if (game.current === null) - end_card() - else - game.state = "eligible1" -} - -function goto_eligible2() { - game.current = next_eligible_faction() - if (game.current === null) - end_card() - else - game.state = "eligible2" -} - -states.eligible1 = { - disable_negotiation: true, - inactive: "1st Eligible", - prompt() { - view.prompt = `${data.card_title[this_card()]}: Choose a Sequence of Play option.` - gen_action("sop", SOP_1ST_OP_ONLY) - gen_action("sop", SOP_1ST_OP_AND_SA) - gen_action("sop", SOP_1ST_EVENT) - gen_action("sop", SOP_PASS) - }, - sop(option) { - push_undo() - game.cylinder[game.current] = option - switch (option) { - case SOP_PASS: - goto_pass() - break - case SOP_1ST_OP_ONLY: - goto_op_only() - break - case SOP_1ST_OP_AND_SA: - goto_op_and_sa() - break - case SOP_1ST_EVENT: - goto_event() - break - } - }, +function can_place_any_available_piece(s, faction) { + if (can_stack_base(s) && has_piece(AVAILABLE, faction, BASE)) + return true + return can_stack_piece(s, faction, GUERRILLA) && has_piece(AVAILABLE, faction, GUERRILLA) } -states.eligible2 = { - disable_negotiation: true, - inactive: "2nd Eligible", - prompt() { - view.prompt = `${data.card_title[this_card()]}: Choose a Sequence of Play option.` - if (did_option(SOP_1ST_OP_ONLY)) - gen_action("sop", SOP_2ND_LIMOP) - if (did_option(SOP_1ST_OP_AND_SA)) - gen_action("sop", SOP_2ND_LIMOP_OR_EVENT) - if (did_option(SOP_1ST_EVENT)) - gen_action("sop", SOP_2ND_OP_AND_SA) - gen_action("sop", SOP_PASS) - }, - sop(option) { - push_undo() - game.cylinder[game.current] = option - switch (option) { - case SOP_PASS: - goto_pass() - break - case SOP_2ND_LIMOP: - goto_limop() - break - case SOP_2ND_LIMOP_OR_EVENT: - goto_limop_or_event() - break - case SOP_2ND_OP_AND_SA: - goto_op_and_sa() - break - } - }, +function did_maximum_damage(targeted) { + if (view.actions.piece) + for (let p of view.actions.piece) + if (targeted & target_faction(p)) + return false + return true } -function goto_pass() { - log_h2(faction_name[game.current] + " - Pass") - if (game.current === GOVT) - add_resources(game.current, 3) - else - add_resources(game.current, 1) - resume_event_card() +function for_each_piece(faction, type, f) { + let p0 = first_piece[faction][type] + let p1 = last_piece[faction][type] + for (let p = p0; p <= p1; ++p) + f(p) } -function goto_limop_or_event() { - game.state = "limop_or_event" +function gen_piece_in_space(space, faction, type) { + for_each_piece(faction, type, p => { + if (game.pieces[p] === space) + gen_action_piece(p) + }) } -states.limop_or_event = { - prompt() { - view.prompt = `${data.card_title[this_card()]}: Event or Limited Operation?` - view.actions.event = 1 - view.actions.limop = 1 - }, - event() { - goto_event() - }, - limop() { - goto_limop() +function gen_place_piece(space, faction, type) { + let p0 = first_piece[faction][type] + let p1 = last_piece[faction][type] + if (type === BASE && !can_stack_base(space)) + return true + let can_place = false + for (let p = p0; p <= p1; ++p) { + if (game.pieces[p] === AVAILABLE) { + gen_action_piece(p) + can_place = true + if (type === BASE) + break + } } -} - -function goto_event() { - log_h2(faction_name[game.current] + " - Event") - if (set_has(single_events, this_card())) - execute_event(0) - else - game.state = "event" -} - -function goto_op_only() { - log_h2(faction_name[game.current] + " - Op Only") - goto_operation(0, 0, 0, 1) -} - -function goto_op_and_sa() { - log_h2(faction_name[game.current] + " - Op + Special") - goto_operation(0, 0, 1, 0) -} - -function goto_limop() { - log_h2(faction_name[game.current] + " - LimOp") - goto_operation(0, 1, 0, 1) -} - -function goto_ship_limop() { - log_h2(faction_name[game.current] + " - Ship") - goto_operation(1, 1, 0, 0) -} - -function goto_operation(free, limited, special, ship) { - game.state = "op" - game.op = { - free, - limited, - ship, - spaces: [], - targeted: 0, - pieces: 0, - count: 0, + if (!can_place && faction === game.current) { + for (let p = p0; p <= p1; ++p) + if (game.pieces[p] !== space || (type === GUERRILLA && !is_underground(p))) + gen_action_piece(p) } - game.sa = special + return !can_place } -function init_free_operation(state) { - goto_operation(1, 0, 0, 0) - game.state = state +function gen_underground_guerrillas(s, faction) { + for_each_piece(faction, GUERRILLA, p => { + if (game.pieces[p] === s) + if (is_underground(p)) + gen_action_piece(p) + }) } -function can_ship() { - return game.op.ship && is_any_shipment_held() +function gen_active_guerrillas(s, faction) { + for_each_piece(faction, GUERRILLA, p => { + if (game.pieces[p] === s) + if (is_active(p)) + gen_action_piece(p) + }) } -function end_operation() { - if (can_ship()) { - push_undo() - game.state = "ship" +function gen_attack_piece(s, faction) { + if (faction === GOVT) { + gen_piece_in_space(s, GOVT, TROOPS) + gen_piece_in_space(s, GOVT, POLICE) + if (!has_piece(s, GOVT, TROOPS) && !has_piece(s, GOVT, POLICE)) + gen_piece_in_space(s, GOVT, BASE) } else { - game.op = null - if (game.vm) - vm_next() - else - resume_event_card() + gen_piece_in_space(s, faction, GUERRILLA) + if (!has_piece(s, faction, GUERRILLA)) + gen_piece_in_space(s, faction, BASE) } } @@ -2054,6 +1748,251 @@ states.drug_bust = { }, } +// === SEQUENCE OF PLAY === + +function this_card() { + return game.deck[0] +} + +function is_final_card() { + // TODO + return false +} + +function is_eligible(faction) { + return game.cylinder[faction] === ELIGIBLE +} + +function goto_card() { + if (this_card() > 72) + goto_propaganda_card() + else + goto_event_card() +} + +function adjust_eligibility(faction) { + 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(GOVT) + adjust_eligibility(FARC) + adjust_eligibility(AUC) + adjust_eligibility(CARTELS) + + clear_undo() + array_remove(game.deck, 0) + goto_card() +} + +function next_eligible_faction() { + let order = data.card_order[this_card()] + for (let faction of order) + if (is_eligible(faction)) + return faction + return null +} + +function did_option(e) { + return ( + game.cylinder[GOVT] === e || + game.cylinder[FARC] === e || + game.cylinder[AUC] === e || + game.cylinder[CARTELS] === e + ) +} + +function goto_event_card() { + log_h1("C" + this_card()) + resume_event_card() +} + +function resume_event_card() { + clear_undo() + let did_1st = (did_option(SOP_1ST_OP_ONLY) || did_option(SOP_1ST_OP_AND_SA) || did_option(SOP_1ST_EVENT)) + let did_2nd = (did_option(SOP_2ND_LIMOP) || did_option(SOP_2ND_LIMOP_OR_EVENT) || did_option(SOP_2ND_OP_AND_SA)) + if (did_1st) { + if (did_2nd) + end_card() + else + goto_eligible2() + } else { + goto_eligible1() + } +} + +function goto_eligible1() { + game.current = next_eligible_faction() + if (game.current === null) + end_card() + else + game.state = "eligible1" +} + +function goto_eligible2() { + game.current = next_eligible_faction() + if (game.current === null) + end_card() + else + game.state = "eligible2" +} + +states.eligible1 = { + disable_negotiation: true, + inactive: "1st Eligible", + prompt() { + view.prompt = `${data.card_title[this_card()]}: Choose a Sequence of Play option.` + gen_action("sop", SOP_1ST_OP_ONLY) + gen_action("sop", SOP_1ST_OP_AND_SA) + gen_action("sop", SOP_1ST_EVENT) + gen_action("sop", SOP_PASS) + }, + sop(option) { + push_undo() + game.cylinder[game.current] = option + switch (option) { + case SOP_PASS: + goto_pass() + break + case SOP_1ST_OP_ONLY: + goto_op_only() + break + case SOP_1ST_OP_AND_SA: + goto_op_and_sa() + break + case SOP_1ST_EVENT: + goto_event() + break + } + }, +} + +states.eligible2 = { + disable_negotiation: true, + inactive: "2nd Eligible", + prompt() { + view.prompt = `${data.card_title[this_card()]}: Choose a Sequence of Play option.` + if (did_option(SOP_1ST_OP_ONLY)) + gen_action("sop", SOP_2ND_LIMOP) + if (did_option(SOP_1ST_OP_AND_SA)) + gen_action("sop", SOP_2ND_LIMOP_OR_EVENT) + if (did_option(SOP_1ST_EVENT)) + gen_action("sop", SOP_2ND_OP_AND_SA) + gen_action("sop", SOP_PASS) + }, + sop(option) { + push_undo() + game.cylinder[game.current] = option + switch (option) { + case SOP_PASS: + goto_pass() + break + case SOP_2ND_LIMOP: + goto_limop() + break + case SOP_2ND_LIMOP_OR_EVENT: + goto_limop_or_event() + break + case SOP_2ND_OP_AND_SA: + goto_op_and_sa() + break + } + }, +} + +function goto_pass() { + log_h2(faction_name[game.current] + " - Pass") + if (game.current === GOVT) + add_resources(game.current, 3) + else + add_resources(game.current, 1) + resume_event_card() +} + +function goto_limop_or_event() { + game.state = "limop_or_event" +} + +states.limop_or_event = { + prompt() { + view.prompt = `${data.card_title[this_card()]}: Event or Limited Operation?` + view.actions.event = 1 + view.actions.limop = 1 + }, + event() { + goto_event() + }, + limop() { + goto_limop() + } +} + +function goto_event() { + log_h2(faction_name[game.current] + " - Event") + if (set_has(single_events, this_card())) + execute_event(0) + else + game.state = "event" +} + +function goto_op_only() { + log_h2(faction_name[game.current] + " - Op Only") + goto_operation(0, 0, 0, 1) +} + +function goto_op_and_sa() { + log_h2(faction_name[game.current] + " - Op + Special") + goto_operation(0, 0, 1, 0) +} + +function goto_limop() { + log_h2(faction_name[game.current] + " - LimOp") + goto_operation(0, 1, 0, 1) +} + +function goto_ship_limop() { + log_h2(faction_name[game.current] + " - Ship") + goto_operation(1, 1, 0, 0) +} + +function goto_operation(free, limited, special, ship) { + game.state = "op" + game.op = { + free, + limited, + ship, + spaces: [], + targeted: 0, + pieces: 0, + count: 0, + } + game.sa = special +} + +function init_free_operation(state) { + goto_operation(1, 0, 0, 0) + game.state = state +} + +function can_ship() { + return game.op.ship && is_any_shipment_held() +} + +function end_operation() { + if (can_ship()) { + push_undo() + game.state = "ship" + } else { + game.op = null + if (game.vm) + vm_next() + else + resume_event_card() + } +} // === OPERATIONS === @@ -2155,13 +2094,22 @@ function select_op_space(s, cost) { // OPERATION: TRAIN function can_govt_train_base(s) { - return count_bases(s) < 2 && count_cubes(s) >= 3 + return can_stack_base(s) && count_cubes(s) >= 3 } function can_govt_train_place(s) { return is_city(s) || has_piece(s, GOVT, BASE) } +function can_govt_civic_action(s) { + if (game.support[s] < 2 && has_govt_control(s)) { + if (has_shaded_capability(CAP_1ST_DIV)) + return count_pieces(s, GOVT, TROOPS) >= 2 && count_pieces(s, GOVT, POLICE) >= 2 + return has_piece(s, GOVT, TROOPS) && has_piece(s, GOVT, POLICE) + } + return false +} + states.train = { prompt() { view.prompt = "Train: Select City or Department." @@ -2768,7 +2716,6 @@ states.sweep_move = { }, } - function do_sweep_activate() { game.state = "sweep_activate" @@ -3343,24 +3290,6 @@ function vm_free_attack() { do_attack_space(game.vm.s) } -function has_any_piece(s, faction) { - if (faction === GOVT) - return has_piece(s, GOVT, BASE) || has_piece(s, GOVT, TROOPS) || has_piece(s, GOVT, POLICE) - return has_piece(s, faction, BASE) || has_piece(s, faction, GUERRILLA) -} - -function has_enemy_piece(s) { - if (game.current !== GOVT && has_any_piece(s, GOVT)) - return true - if (game.current !== FARC && has_any_piece(s, FARC)) - return true - if (game.current !== AUC && has_any_piece(s, AUC)) - return true - if (game.current !== CARTELS && has_any_piece(s, CARTELS)) - return true - return false -} - states.attack = { prompt() { view.prompt = "Attack: Select space with Guerrilla and enemy piece." @@ -3922,7 +3851,6 @@ states.eradicate_shift = { }, } - // SPECIAL ACTIVITY: AMBUSH function vm_free_ambush() { @@ -3959,41 +3887,10 @@ function goto_extort() { spaces: [], where: -1, } - game.state = "extort2" -} - -states.extort1 = { - prompt() { - view.prompt = "Extort: Activate Underground Guerrillas to gain Resources." - - for (let s = first_space; s <= last_space; ++s) { - if (set_has(game.sa.spaces, s)) - continue - if (has_underground_guerrilla(s, game.current)) { - if (game.current === FARC && has_farc_control(s)) - gen_action_space(s) - if (game.current === AUC && has_auc_control(s)) - gen_action_space(s) - } - } - - view.actions.end_activity = 1 - }, - space(s) { - push_undo() - logi(`S${s}.`) - let p = find_underground_guerrilla(s, game.current) - set_active(p) - set_add(game.sa.spaces, s) - add_resources(game.current, 1) - }, - end_activity() { - push_undo() - end_special_activity() - }, + game.state = "extort" } -states.extort2 = { +states.extort = { prompt() { if (game.sa.where < 0) { view.prompt = "Extort: Select space with Underground Guerrilla that you control." @@ -4110,14 +4007,6 @@ function transfer_resources(from, to, n) { add_resources(to, n) } -function can_place_auc_piece(s) { - if (can_stack_base(s) && has_piece(AVAILABLE, AUC, BASE)) - return true - if (can_stack_piece(AUC, GUERRILLA, s) && has_piece(AVAILABLE, AUC, GUERRILLA)) - return true - return false -} - states.kidnap_space = { prompt() { view.prompt = `Kidnap in ${space_name[game.sa.where]}.` @@ -4151,7 +4040,7 @@ states.kidnap_space = { log("Rolled " + die + ".") transfer_resources(faction, game.current, die) - if (die === 6 && can_place_auc_piece(game.sa.where)) { + if (die === 6 && can_place_any_available_piece(game.sa.where, AUC)) { game.current = AUC game.state = "kidnap_place" } else { @@ -4165,7 +4054,7 @@ states.kidnap_place = { view.prompt = `Kidnap in ${space_name[game.sa.where]}: Place an AUC piece.` if (can_stack_base(game.sa.where)) gen_piece_in_space(AVAILABLE, AUC, BASE) - if (can_stack_piece(AUC, GUERRILLA, game.sa.where)) + if (can_stack_piece(game.sa.where, AUC, GUERRILLA)) gen_piece_in_space(AVAILABLE, AUC, GUERRILLA) }, piece(p) { @@ -5925,7 +5814,7 @@ const CODE = [ [ vm_mark_space ], [ vm_endspace ], [ vm_prompt, "Flip 3 Guerrillas there or adjacent to Active." ], - [ vm_piece, 3, (p,s)=>is_guerrilla(p) && is_underground(p) && is_there_or_adjacent(s, game.vm.m) ], + [ vm_piece, 3, (p,s)=>is_guerrilla(p) && is_underground(p) && is_with_or_adjacent_to_mark(s, game.vm.m) ], [ vm_activate ], [ vm_endpiece ], [ vm_return ], @@ -6065,7 +5954,7 @@ const CODE = [ [ vm_return ], // EVENT 19 [ vm_if, ()=>game.current === GOVT ], - [ vm_space, 0, (s)=>has_cubes(s) && has_enemy_piece(s) ], + [ vm_space, 0, (s)=>has_cube(s) && has_enemy_piece(s) ], [ vm_free_sweep_or_assault ], [ vm_endspace ], [ vm_endif ], @@ -6354,7 +6243,7 @@ const CODE = [ // TODO // EVENT 37 [ vm_current, GOVT ], - [ vm_space, 0, (s)=>has_cubes(s) && has_farc_piece(s) ], + [ vm_space, 0, (s)=>has_cube(s) && has_farc_piece(s) ], [ vm_free_sweep_or_assault_farc ], [ vm_endspace ], [ vm_return ], @@ -6368,14 +6257,14 @@ const CODE = [ [ vm_endspace ], [ vm_return ], // EVENT 38 - [ vm_space, 3, (s)=>has_cubes(s) || is_support(s) ], + [ vm_space, 3, (s)=>has_cube(s) || is_support(s) ], [ vm_piece, 0, (p,s)=>is_piece_in_event_space(p) && is_auc_guerrilla(p) && is_active(p) ], [ vm_remove ], [ vm_endpiece ], [ vm_endspace ], [ vm_return ], // SHADED 38 - [ vm_space, 0, (s)=>has_cubes(s) || is_support(s) ], + [ vm_space, 0, (s)=>has_cube(s) || is_support(s) ], [ vm_piece, 0, (p,s)=>is_piece_in_event_space(p) && is_auc_guerrilla(p) && is_active(p) ], [ vm_underground ], [ vm_endpiece ], @@ -6404,7 +6293,7 @@ const CODE = [ [ vm_endpiece ], [ vm_return ], // SHADED 40 - [ vm_space, 1, (s)=>is_dept(s) && has_auc_piece(s) && has_cubes(s) ], + [ vm_space, 1, (s)=>is_dept(s) && has_auc_piece(s) && has_cube(s) ], [ vm_prompt, "Move all cubes to any Cities." ], [ vm_piece, 0, (p,s)=>is_piece_in_event_space(p) && (is_troops(p) || is_police(p)) ], [ vm_save_space ], @@ -6473,7 +6362,7 @@ const CODE = [ [ vm_resources, GOVT, -3 ], [ vm_return ], // EVENT 45 - [ vm_space, 0, (s)=>has_cubes(s) && has_terror(s) ], + [ vm_space, 0, (s)=>has_cube(s) && has_terror(s) ], [ vm_shift_support ], [ vm_endspace ], [ vm_return ], @@ -6577,7 +6466,7 @@ const CODE = [ [ vm_return ], // SHADED 51 [ vm_prompt, "Sabotage Pipelines with or adjacent to FARC Guerrillas." ], - [ vm_space, 3, (s)=>is_pipeline(s) && (has_farc_guerrilla(s) || adjacent_has_farc_guerrilla(s)) ], + [ vm_space, 3, (s)=>is_pipeline(s) && is_with_or_adjacent_to_farc_guerrilla(s) ], [ vm_sabotage ], [ vm_endspace ], [ vm_return ], |