From bf856d132261e7ca91ca6f8fbe5cecef6ba939d6 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Fri, 25 Oct 2024 12:06:40 +0200 Subject: Normalize line endings. Added .gitattributes with text=auto setting. Ran `git add --renormalize .` to update all the checked in files. --- rules.js | 19784 ++++++++++++++++++++++++++++++------------------------------- 1 file changed, 9892 insertions(+), 9892 deletions(-) (limited to 'rules.js') diff --git a/rules.js b/rules.js index 91818c9..44bbef6 100644 --- a/rules.js +++ b/rules.js @@ -1,9892 +1,9892 @@ -//"use strict" - -const { spaces, cards, power_cards } = require("./data.js") - -var game, view, states = {} - -const DEM = "Democrat" -const COM = "Communist" - -const first_strategy_card = 1 -const last_strategy_card = 110 - -const dem_tst_req = [5, 5, 6, 6, 7, 8, 9, 10] -const com_tst_req = [6, 6, 7, 7, 8, 7, 6, 5] -const scoring_cards = [22, 23, 42, 43, 55, 95] -const leader_cards = [37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48] -const leaders = [1, 4, 5, 6, 7] -const support_loss_roll = [0, 0, 1, 1, 2, 2, 3, 4] -const vp_roll = [0, 0, 1, 1, 2, 2, 3, 4] -const countries = ['Poland', 'Hungary', 'East_Germany', 'Bulgaria', 'Czechoslovakia', 'Romania'] -const elite_spaces = [12, 15, 27, 43, 51, 69] -const all_power_cards = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52 ] -const numberless_cards = [25, 26, 27, 28, 29, 30, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52] -const auto_resolve_events = [5, 8, 9, 13, 17, 25, 26, 30, 35, 50, 53, 54, 58, 59, 62, 63, 65, 70, 72, 74, 86, 99, 102, 108] -const switch_events = [6, 20, 71] - -exports.scenarios = [ "Standard" ] - -exports.roles = [ DEM, COM ] - -// --- SET UP --- - -exports.setup = function (seed, scenario, options) { - game = { - seed: seed, - log: [], - undo: [], - summary: [], - active: null, - state: "com_init", - return: '', - vm: null, - vm_event: 0, - vm_event_to_do: false, - vm_infl_to_do: false, - - played_card: 0, - table_cards: [], - available_ops: 0, - vm_available_ops: 0, - valid_spaces: [], - valid_cards: [], - - vp: 0, - turn: 0, - round: 0, - round_player: COM, - stability: 0, - dem_tst_position: 0, - com_tst_position: 0, - dem_tst_attempted: 0, - com_tst_attempted: 0, - dem_tst_attempted_this_turn: 0, - com_tst_attempted_this_turn: 0, - - demInfl: [], - comInfl: [], - - strategy_deck: [], - strategy_discard: [], - discard: false, - view_opp_hand: false, - strategy_removed: [], - persistent_events: [], - power_struggle_deck: [], - power_struggle_discard: [], - dem_hand_limit: 8, - com_hand_limit: 8, - democrat_hand: [], - communist_hand: [], - - pwr_struggle_in: [], - is_pwr_struggle: false, - dem_pwr_hand_limit: 0, - com_pwr_hand_limit: 0, - dem_pwr_hand: [], - com_pwr_hand: [], - raised_stakes_discard: 0, - raised_stakes: 0, - raised_stakes_round: 0, - phase: 0, - times_held: [0, 0, 0, 0, 0, 0], - revolutions: [false, false, false, false, false, false], - remove_opponent_infl: false, - tactics_fails: '', - } - - log_h1("1989 Dawn of Freedom") - - game.active = COM - start_game() - - return game -} - -function start_game() { - //starting influence - - // Draw cards - - //console.log('start game') - - game.strategy_deck = draw_deck(cards) - reset_power() - - //Set starting influence - spaces.forEach((space, index) => { - if (space !== null) { - game.demInfl[index] = space.demInfl - game.comInfl[index] = space.comInfl - } - }) - - //Set starting placement ops - game.starting_infl = { - com_starting_infl: 0, - dem_starting_infl: 0 - }, - - // Set variable event cards where event is playable at start of game - - game.playable_cards = [14, 15, 21, 70] - - //console.log('game.strategy_deck: ', game.strategy_deck[1]) - draw_cards(game.strategy_deck, game.democrat_hand, game.communist_hand, game.dem_hand_limit, game.com_hand_limit) - //.log('game.strategy_deck: ', game.strategy_deck[1], 'democrat_hand:', game.democrat_hand) - - game.valid_spaces = valid_spaces_setup() - game.available_ops = 2 - game.phase = 0 - log_h1("Place starting Support Points") - log_side() -} - - -exports.view = function(state, player) { - game = state - - view = { - log: game.log, - active: game.active, - prompt: null, - actions: null, - - played_card: game.played_card, - table_cards: game.table_cards, - valid_spaces: game.valid_spaces, - valid_cards: game.valid_cards, - - demInfl: game.demInfl, - comInfl: game.comInfl, - turn: game.turn, - round: game.round, - round_player: game.round_player, - vp: game.vp, - stability: game.stability, - dem_tst: game.dem_tst_position, - com_tst: game.com_tst_position, - persistent_events: game.persistent_events, - systematization: game.systematization, - the_tyrant_is_gone: game.the_tyrant_is_gone, - - strategy_deck: game.strategy_deck.length, - strategy_removed: game.strategy_removed, - discard: game.discard, - show_opp_hand: game.view_opp_hand, - - democrat_hand: game.democrat_hand.length, - communist_hand: game.communist_hand.length, - democrat_power_hand: game.dem_pwr_hand.length, - communist_power_hand: game.com_pwr_hand.length, - ceausescu_cards: game.ceausescu_cards, - is_pwr_struggle: game.is_pwr_struggle, - times_held: game.times_held, - revolutions: game.revolutions, - - hand: [], - set_aside: [], - pwr_hand: [], - - - } - - if (game.is_pwr_struggle) { - view.strategy_discard = game.power_struggle_discard - } else { - view.strategy_discard = game.strategy_discard - } - - if (player === game.active && game.vm && game.vm.draw) - view.drawn = game.vm.draw - - if (player === game.active) { - if (game.selected_space > 0 ) { - view.valid_spaces = [game.selected_space] - } else { - view.valid_spaces = game.valid_spaces - } - } else { - view.valid_spaces = [] - } - - if (player === game.active) { - view.valid_cards = game.valid_cards - } else { - view.valid_cards = [] - } - - if (player === DEM) { - view.hand = game.democrat_hand - if (game.communist_hand_red) { - view.opp_hand = game.communist_hand_red - } - view.set_aside = game.democrat_set_aside /*Is this being used? */ - view.power_hand = [...game.dem_pwr_hand].sort((a, b) => a - b) - - } else if (player === COM) { - view.hand = game.communist_hand - view.opp_hand = [...game.dem_pwr_hand].sort((a, b) => a - b) - view.power_hand = [...game.com_pwr_hand].sort((a, b) => a - b) - } - - if (player === DEM) { - view.samizdat = game.samizdat_card - } - - if (game.state === "game_over") { - view.prompt = game.victory - } else if (player === "Observer" || (game.active !== player && game.active !== "Both")) { - if (states[game.state]) { - let inactive = states[game.state].inactive - if (typeof inactive === "function") - view.prompt = `Waiting for ${game.active} ${inactive()}` - else - view.prompt = `Waiting for ${game.active} to ${inactive}` - } else { - view.prompt = "A Unknown state: " + game.state - } - } else { - view.actions = {} - - if (states[game.state]) - states[game.state].prompt(player) - else - view.prompt = "B Unknown state: " + game.state - if (view.actions.undo === undefined) { - if (game.undo && game.undo.length > 0) - view.actions.undo = 1 - else - view.actions.undo = 0 - } - } - - return view -} - - -// === ACTIONS =========== - -function gen_action(action, argument) { -//console.log('gen_action called with ', action, ' and ', argument) - if (argument === undefined) { - //console.log('argument undefined') - view.actions[action] = 1 - } else { - if (!(action in view.actions)) { - //console.log('push argument') - view.actions[action] = [] - } - view.actions[action].push(argument) - } - //console.log('view.actions: ', view.actions, 'view.actions[action]: ', view.actions[action]) -} - -function gen_action_infl(space){ - gen_action("infl", space) -} - -function gen_action_card(card){ - gen_action("card", card) -} - -function gen_action_sc(space){ - gen_action("sc", space) -} - -function gen_action_scoring(){ - gen_action("scoring") -} - -exports.action = function (state, player, action, arg) { - //console.log('exports.action called with state:' , state, 'player:', player, 'action: ', action, 'arg: ', arg) - game = state - if (states[game.state] && action in states[game.state]) { - states[game.state][action](arg, player) - } else { - if (action === "undo" && game.undo && game.undo.length > 0) - pop_undo() - else - throw new Error("Invalid action: " + action) - } - return game -} - -// ============= GAME STATES ======================= - -states.com_init = { - inactive: 'place starting SPs.', - prompt() { - //console.log('state:', game.state, 'game.valid_spaces', game.valid_spaces) - if (game.starting_infl.dem_starting_infl === 2 && game.available_ops === 0 ) { - view.prompt = 'Place starting SPs: done. Start Turn 1.'; - gen_action("start"); - } else if (game.available_ops === 0) { - view.prompt = 'Place starting SPs: done.'; - gen_action("done"); - return; - } else if (game.starting_infl.dem_starting_infl === 2) { - view.prompt = `Place your last ${pluralize(game.available_ops,'starting SP')}.` - } else { - view.prompt = `Place ${pluralize(game.available_ops,'starting SP')}.` - } - for (let space_id of game.valid_spaces) { - gen_action_infl(space_id); - } - }, - infl(space) { - add_infl(space) - - }, - done() { - if (game.summary.length > 0) { - pop_summary() - log_br() - } - - game.starting_infl.com_starting_infl++ - if (game.starting_infl.com_starting_infl == 1){ - game.available_ops = 3 - game.state = 'dem_init' - valid_spaces_setup() - next_player() - } else if (game.starting_infl.com_starting_infl == 2) { - game.available_ops = 4 - game.state = 'dem_init' - valid_spaces_setup() - next_player() - } else if (game.starting_infl.com_starting_infl == 3) { - delete game.starting_infl - game.state = 'start_game' - } - }, - start() { - new_turn() - clear_undo() - game.state = 'choose_card' - } -} - -states.dem_init = { - inactive: 'place starting SPs.', - prompt() { - //console.log('state:', game.state) - if (game.available_ops == 0) { - view.prompt = 'Place starting SPs: done.'; - gen_action("done"); - return; - } else if (game.starting_infl.com_starting_infl === 2) { - view.prompt = `Place your last ${pluralize(game.available_ops,'starting SP')}.` - } else { - view.prompt = `Place ${pluralize(game.available_ops,'starting SP')}.` - } - for (let space_id of game.valid_spaces) { - gen_action_infl(space_id); - } - }, - infl(space) { - add_infl(space) - }, - - done() { - if (game.summary.length > 0) { - pop_summary() - log_br() - } - - game.starting_infl.dem_starting_infl++ - if (game.starting_infl.dem_starting_infl == 1){ - game.available_ops = 3 - } else if (game.starting_infl.dem_starting_infl == 2) { - game.available_ops = 2 - } - game.state = 'com_init' - valid_spaces_setup() - next_player() - } -} - - -states.choose_card = { - inactive: 'choose a card.', - prompt() { - if ((game.active===DEM && game.democrat_hand.length === 0) || game.active === COM && game.communist_hand.length === 0) { - view.prompt = 'No cards remaining: you must pass.' - gen_action('pass') - } else { - view.prompt = 'Choose a card.' - let available_cards - if (game.active === DEM) { - available_cards = game.democrat_hand - } else { - available_cards = game.communist_hand - } - for (let card of available_cards) { - gen_action_card(card) - } - } - }, - card(card) { - push_undo() - - //Check if player is at risk of losing game due to held scoring card - if (!scoring_cards.includes(card)) { - let scoring_cards_count = count_scoring_cards() - - if (game.round !== 8 && scoring_cards_count >= (8-game.round)){ - game.temp = card - game.state = 'confirm_card' - return - } - } - select_card(card) - }, - pass() { - log('No cards remaining. Passed') - //end_round() - game.state = 'end_round' - } -} - -states.confirm_card = { - inactive: 'choose a card.', - prompt() { - let scoring_cards_count = count_scoring_cards() - view.prompt = `${pluralize(scoring_cards_count,'scoring card')} in hand with ${pluralize(8-game.round,'turn')} remaining. Scoring cards may not be held. Continue?` - gen_action('continue') - }, - continue() { - select_card(game.temp) - } -} - -states.play_card ={ - get inactive() { - return `play ${clean_name(cards[game.played_card].name)}.` - }, - prompt () { - /*if (game.phase >= 1) { /*Finish here when playing your own event - console.log('in play card') - view.prompt = `${clean_name(cards[game.played_card].name)}: done. End the Action Round.` - gen_action('end_round') - return - }*/ - - view.prompt = `Play ${clean_name(cards[game.played_card].name)} for:` - - if (scoring_cards.includes(game.played_card)) { - /*view.prompt = 'Play for:'*/ - gen_action('event') - return - } - - // Check for Reformer Rehabilitated - - //console.log('game.active', game.active, 'game.playable_cards[67].playable', game.playable_cards[67].playable) - - - if (game.played_card === 67 && game.playable_cards.includes(67)){ - if (game.active === DEM && (game.dem_tst_position > game.com_tst_position)) { - gen_action('event') - } - if (game.active === COM && (game.dem_tst_position < game.com_tst_position)) { - gen_action('event') - } - } - - //Check for events - //console.log('event_is_playable(game.played_card)', event_is_playable(game.played_card)) - if (event_is_playable(game.played_card)) { - //console.log('card is playable') - //Check for Tiananmen Square Track awards special abilities - //console.log('game.tst_7', game.tst_7) - if ((game.active === DEM && cards[game.played_card].side === 'C' && game.dem_tst_position >= 7 && game.com_tst_position < 7 && !game.tst_7) || (game.active === COM && cards[game.played_card].side === 'D' && game.com_tst_position >= 7 && game.dem_tst_position < 7 && !game.tst_7)){ - gen_action('tst_7') - } - - if ((game.active === DEM && cards[game.played_card].side !== 'C' && game.dem_tst_position >= 8 && game.com_tst_position < 8 && !game.tst_8) || (game.active === COM && cards[game.played_card].side !== 'D' && game.com_tst_position >= 8 && game.dem_tst_position < 8 && !game.tst_8)){ - gen_action('tst_8') - } - - //Continue with normal logic - get_events(game.played_card) - } - - gen_action('influence') - gen_action('support_check') - - if ((game.active === DEM && game.dem_tst_attempted_this_turn === 0 && game.dem_tst_position < 8 ) || (game.active === COM && game.com_tst_attempted_this_turn === 0 && game.com_tst_position < 8)) { - gen_action('tst') - } - - }, - event() { - push_undo() - //console.log('played event, game.active', game.active, 'game.view_opp_hand', game.view_opp_hand) - log_gap(`Played C${cards[game.played_card].number} for the event`) - game.vm_infl_to_do = false - if (scoring_cards.includes(game.played_card)) {game.phase = 0} - else {game.phase = 1} - game.return = game.active - if (switch_events.includes(game.played_card)) {next_player()} - game.vm_event = game.played_card - //console.log('before event, game.vm_infl_to_do', game.vm_infl_to_do) - goto_vm(game.vm_event) - }, - opp_event() { - push_undo() - log_gap(`Played C${cards[game.played_card].number} for the event`) - game.phase = 1 /*Do I still need this?*/ - game.vm_infl_to_do = true - game.return = game.active - game.vm_event = game.played_card - if (is_auto_resolve(game.played_card) || switch_events.includes(game.played_card)) { - goto_vm(game.vm_event)} - else { - next_player() - log(`C${game.vm_event}`) - goto_vm(game.vm_event) - } - }, - influence() { - push_undo() - log_gap(`Played C${cards[game.played_card].number} to place SPs`) - - - // Check if Common European Home played for influence - if (game.played_card === 21) { - if (game.active === DEM) { - game.vp -- - log('-1 VP') - if (check_vp()) { - return - } - } else { - game.vp ++ - log('+1 VP') - if (check_vp()) { - return - } - } - } - // Check if card is opponent card with event that needs to be resolved - - if (cards[game.played_card].playable || game.playable_cards.includes(game.played_card)) { - if ((game.active === DEM && cards[game.played_card].side === "C" ) || (game.active === COM && cards[game.played_card].side === "D")) { - //game.phase = 1 /*Do I need this? */ - game.vm_event_to_do = true - } - } - - // If ABHR - Set AHBR tracker to true - if (game.persistent_events.includes(58)) { - game.austria_hungary_border_reopened_tracker = true - } - game.state='add_influence' - valid_spaces_infl() - }, - tst() { - push_undo() - log_gap(`Played C${cards[game.played_card].number} to the Tiananmen Square Track`) - game.state='tiananmen_square_attempt' - }, - support_check() { - push_undo() - log_gap(`Played C${cards[game.played_card].number} for support checks`) - - // Check if card is opponent card with event that needs to be resolved - - if (cards[game.played_card].playable || game.playable_cards.includes(game.played_card)) { - if ((game.active === DEM && cards[game.played_card].side === "C" ) || (game.active === COM && cards[game.played_card].side === "D")) { - game.vm_event_to_do = true - } - } - - game.available_ops = 2 - game.state='support_check_prep' - valid_spaces_sc() - }, - tst_7() { /*Cancel opponent event */ - push_undo() - log(`Played C${game.played_card}. Event cancelled using TST Award`) - game.tst_7 = true - game.vm_infl_to_do = true - game.state = 'resolve_opponent_event' - }, - tst_8() { /*Play card for ops and event */ - push_undo() - game.vm_event_to_do = true - game.vm_infl_to_do = true - game.tst_8 = true - log(`Played C${game.played_card} for event and operations`) - game.state = 'vm_tst_8' - }, - end_round () { - end_round() - } - -} - -states.resolve_opponent_event = { - get inactive() { - return `resolve ${clean_name(cards[game.played_card].name)}.` - }, - prompt() { - //console.log('in resolve opponent event: discard', game.strategy_discard) - if (game.vm_infl_to_do) { - view.prompt = 'Event resolved. Choose to play card for:' - gen_action('influence') - gen_action('support_check') - } else if (game.vm_event_to_do) { - // Check for Tiananmen Square Track ability - play opponent card without triggering event - if ((game.active === DEM && game.dem_tst_position >= 7 && game.com_tst_position < 7 && !game.tst_7) || (game.active === COM && game.com_tst_position >= 7 && game.dem_tst_position < 7 && !game.tst_7)){ - gen_action('tst_7') - } - view.prompt = `${clean_name(cards[game.played_card].name)}: you must resolve the opponent event.` - gen_action('opp_event') - } else { - view.prompt = 'Event resolved. End the action round.' - gen_action('end_round') - } - }, - influence(){ - push_undo() - // If ABHR - Set AHBR tracker to true - if (game.persistent_events.includes(58)) { - game.austria_hungary_border_reopened_tracker = true - } - game.state = 'finish_add_infl' - valid_spaces_infl() - }, - support_check() { - push_undo() - game.available_ops = 2 - game.state = 'finish_support_check_prep' - valid_spaces_sc() - }, - opp_event() { - game.vm_event_to_do = false - game.return_state = 'resolve_opponent_event' - if (is_auto_resolve(game.played_card) || switch_events.includes(game.played_card)) { - game.return = game.active - log(`Played C${game.played_card} for the event`) - goto_vm(game.played_card)} - else { - if (game.active === DEM) { - game.return = COM - } else { - game.return = DEM - } - next_player() - log(`C${game.played_card}`) - goto_vm(game.played_card) - } - }, - tst_7() { - push_undo() - log('Event cancelled using TST Award') - game.tst_7 = true - game.vm_event_to_do = false - }, - end_round() { - push_undo() - /*if(game.round_player === COM && game.active === DEM) { - log_h3('End of Communist Action Round') - change_player() - } */ - end_round() - } -} - - -states.finish_add_infl = { - inactive: 'add SPs.', - prompt () { - if (game.available_ops === 0) { - view.prompt = 'Place SPs: done.' - gen_action("end_round") - return; - } - - view.prompt = `Add SPs: ${game.available_ops} remaining.` - - // Generate actions for valid spaces - for (let space_id of game.valid_spaces) { - gen_action_infl(space_id) - } - }, - infl(space) { - add_infl(space) - }, - end_round() { - push_undo() - if (game.summary.length > 0) { - pop_summary() - log_br() - } - - end_round() - //game.state = 'end_round' - } -} - -states.finish_support_check_prep = { - inactive: 'do support checks.', - prompt () { - if (game.available_ops === 0) { - view.prompt = 'Support checks: done.' - gen_action('end_round') - //return - } else { - view.prompt = `Select a space. ${pluralize(game.available_ops, 'support check')} remaining.` - for (let space_id of game.valid_spaces) { - gen_action_sc(space_id) - } - } - }, - sc(space) { - push_undo() - game.selected_space = space - // Check for Austria-Hungary Border Reopened - check on first support check only - //console.log('game.austria_hungary_border_reopened_checked', game.austria_hungary_border_reopened_checked) - if (game.persistent_events.includes(58)){ - if (game.active === DEM && game.available_ops > 1) { - //console.log('in ahb check, country, ', spaces[game.selected_space].country, 'ahb', 'austria_hungary_border_reopened']) - if (spaces[game.selected_space].country === 'East_Germany' && game.persistent_events.includes(58) && game.active === DEM) { - game.state = 'finish_austria_hungary_border_reopened_check' - return - } - } - } - game.state = 'finish_do_support_check' - }, - end_round () { - end_round() - //game.state = 'end_round' - } -} - -states.finish_austria_hungary_border_reopened_check = { - inactive: 'decide Austria-Hungary Border Reopened', - prompt() { - view.prompt = 'Austria-Hungary Border Reopened: will both support checks be in East Germany?' - gen_action('yes') - gen_action('no') - }, - yes() { - game.austria_hungary_border_reopened_tracker = true - game.state = 'finish_do_support_check' - }, - no() { - game.state = 'finish_do_support_check' - } -} - -states.finish_do_support_check = { - inactive: 'do support checks', - prompt () { - view.prompt = `Support check: ${spaces[game.selected_space].name_unique}. Roll a die.` - gen_action('roll') - }, - roll() { - clear_undo() - do_sc(game.selected_space) - game.available_ops-- - if (game.available_ops === 0) { - game.valid_spaces = [] - } - game.state = 'finish_support_check_prep' - return - } -} - -states.add_influence = { - inactive: 'add SPs.', - prompt () { - if (game.available_ops <= 0) { - view.prompt = 'Place SPs: done.' - if (!game.vm_event_to_do) { - gen_action("end_round") - } else { - gen_action('done') - } - } else { - - view.prompt = `Add SPs: ${game.available_ops} remaining.` - - // Generate actions for valid spaces - for (let space_id of game.valid_spaces) { - gen_action_infl(space_id); - } - } - }, - infl(space) { - add_infl(space) - }, - end_round() { - push_undo() - if (game.summary.length > 0) { - pop_summary() - log_br() - } - end_round() - }, - done() { - if (game.summary.length > 0) { - pop_summary() - log_br() - } - reset_austria_hungary_border_reopened() - game.state = 'resolve_opponent_event' - } -} - -states.tiananmen_square_attempt = { - inactive: 'do Tiananmen Square Attempt.', - prompt () { - view.prompt = 'Tiananmen Square Track attempt: Roll a die.' - gen_action('roll') - }, - roll() { - clear_undo() - do_tst_attempt () - } -} - -states.tiananmen_square_attempt_success = { - inactive: 'do Tiananmen Square Attempt.', - prompt () { - if (game.vm_event > 200) { - view.prompt = 'Tiananmen Square Track attempt successful. Go to TST Award.' - gen_action('done') - } else { - view.prompt = 'Tiananmen Square Track attempt successful.' - gen_action('end_round') - } - - }, - done () { - push_undo() - //console.log('going to tst award, game.return_state', game.return_state) - goto_vm(game.vm_event) - }, - end_round () { - push_undo() - end_round() - } -} - -states.tiananmen_square_attempt_fail = { - inactive: 'do Tiananmen Square Attempt.', - prompt () { - view.prompt = 'Tiananmen Square Track attempt failed.' - gen_action('end_round') - }, - end_round () { - push_undo() - end_round() - //game.state = 'tiananmen_square_attempt_done' - } -} - -states.tiananmen_square_attempt_done = { - inactive: 'do Tiananmen Square Attempt.', - prompt () { - view.prompt = 'Tiananmen Square Track attempt: done.' - gen_action('end_round') - }, - end_round () { - end_round() - //game.state = 'end_round' - } -} - -states.tst_goddess = { - inactive: 'choose whether to discard a card.', - prompt() { - //if (game.phase === 0) { - view.prompt = 'Tiananmen Square Track award: you may discard a non-Power Struggle Card and draw a replacement.' - for (let card of game.valid_cards) { - gen_action_card(card) - } - gen_action('pass') - /*} else { - view.prompt = 'Discard a card: done.' - gen_action('done') - }*/ - }, - card(card) { - push_undo() - discard(card) - game.valid_cards = [] - game.state = 'tst_goddess_draw' - //game.phase++ - /*if (game.active === DEM) { - draw_cards(game.strategy_deck, game.democrat_hand, game.communist_hand, game.democrat_hand.length +1, game.communist_hand.length) - } else { - draw_cards(game.strategy_deck, game.democrat_hand, game.communist_hand, game.democrat_hand.length, game.communist_hand.length +1) - }*/ - }, - pass() { - log('Did not discard') - log_h2("Action Round " + game.round) - if (game.active === DEM) { - next_player() - } else { - log_side() - } - if (game.persistent_events.includes(5)) { - game.state = 'general_strike' - } else { - game.state = 'choose_card' - } - }, - done() { - - log_h2("Action Round " + game.round) - if (game.active === DEM) { - next_player() - } else { - log_side() - } - game.phase = 0 - if (game.persistent_events.includes(5)) { - game.state = 'general_strike' - } else { - game.state = 'choose_card' - } - } -} - -states.tst_goddess_draw = { - inactive: 'choose whether to discard a card.', - prompt() { - view.prompt = 'Draw a replacement card.' - gen_action('draw') - }, - draw() { - if (game.active === DEM) { - draw_cards(game.strategy_deck, game.democrat_hand, game.communist_hand, game.democrat_hand.length +1, game.communist_hand.length) - } else { - draw_cards(game.strategy_deck, game.democrat_hand, game.communist_hand, game.democrat_hand.length, game.communist_hand.length +1) - } - log_h2("Action Round " + game.round) - if (game.active === DEM) { - next_player() - } else { - log_side() - } - game.phase = 0 - if (game.persistent_events.includes(5)) { - game.state = 'general_strike' - } else { - game.state = 'choose_card' - } - } -} - - - -states.support_check_prep = { - inactive: 'do support checks', - prompt () { - if (game.available_ops === 0) { /*Needs another check for Support Checks done during Crowd Turns against Ceausescu*/ - if (game.is_pwr_struggle) { - view.prompt = 'The Crowd Turns Against Ceausescu. Support checks: done.' - gen_action('done') - } else if (!game.vm_event_to_do) { - view.prompt = 'Support checks: done.' - gen_action('end_round') - } else { - view.prompt = 'Support checks: done.' - gen_action('done') - } - } else if (game.available_ops > 0) { - view.prompt = `Select a space. ${pluralize(game.available_ops, 'support check')} remaining.` - - for (let space_id of game.valid_spaces) { - gen_action_sc(space_id) - } - } - }, - sc(space) { - push_undo() - game.selected_space = space - - // Check for Austria-Hungary Border Reopened - check on first support check only - //console.log('game.austria_hungary_border_reopened_checked', game.austria_hungary_border_reopened_checked) - if (game.persistent_events.includes(58)) { - if (game.active === DEM && game.available_ops > 1) { - if (spaces[game.selected_space].country === 'East_Germany' && game.persistent_events.includes(58) && game.active === DEM) { - game.state = 'austria_hungary_border_reopened_check' - return - } - //game.state = 'do_support_check' - } /*else { */ - } - game.state = 'do_support_check' - //} - }, - end_round() { - push_undo() - end_round() - }, - done() { - push_undo() - if (game.is_pwr_struggle) {/*Crowd Turns Against Ceausescu should be the only time you end up here during a power struggle */ - if (game.return !== game.active) { - next_player() - } - log_h2('Raise the Stakes') - game.state = 'raise_stakes_1' - return - } - reset_austria_hungary_border_reopened() - game.state = 'resolve_opponent_event' - } -} - -states.do_support_check = { - inactive: 'do support checks.', - prompt () { - // console.log('in do_support_check') - view.prompt = `Support check: ${spaces[game.selected_space].name_unique}. Roll a die.` - gen_action('roll') - }, - roll() { - clear_undo() - do_sc(game.selected_space) - game.available_ops-- - if (game.available_ops === 0) { - game.valid_spaces = [] - } - game.state = 'support_check_prep' - return - } -} - -states.austria_hungary_border_reopened_check = { - inactive: 'decide Austria-Hungary Border Reopened.', - prompt() { - view.prompt = 'Austria-Hungary Border Reopened: will both support checks be in East Germany?' - gen_action('yes') - gen_action('no') - }, - yes() { - game.austria_hungary_border_reopened_tracker = true - game.state = 'do_support_check' - }, - no() { - game.state = 'do_support_check' - } -} - -states.end_round = { - inactive: 'finish playing a card.', - prompt() { - view.prompt = 'End the Action Round.' - gen_action('end_round') - }, - end_round() { - push_undo() - end_round() - } -} - -//======================= POWER STRUGGLE =============================== - -states.draw_power_cards = { - inactive: 'draw cards.', - prompt() { - view.prompt = `${clean_name(cards[this_card()].name)}: draw cards.` - gen_action('draw') - }, - draw() { - push_undo() - game.power_struggle_deck = [...all_power_cards] - // console.log('game.power_struggle_deck.length', game.power_struggle_deck.length) - //console.log('called draw cards, country', game.pwr_struggle_in, 'game.active', game.active, 'game.view_opp_hand', game.view_opp_hand) - //console.log('test3') - let presence = check_presence(game.pwr_struggle_in) - //console.log('test2') - if (presence.dem_spaces > 0) { - game.dem_pwr_hand_limit = 6 + 2*(presence.dem_spaces - 1) - } else { - game.dem_pwr_hand_limit = 0 - } - if (presence.com_spaces > 0 ) { - game.com_pwr_hand_limit = 6 + 2*(presence.com_spaces - 1) - } else { - game.com_pwr_hand_limit = 0 - } - // Events which affect cards drawn - if (game.persistent_events.includes(17) && game.com_pwr_hand_limit >= 2) { - log('Democrat receives 2 cards from Communist due to C17') - game.dem_pwr_hand_limit += 2 - game.com_pwr_hand_limit -= 2 - discard_from_table(17) - game.persistent_events = game.persistent_events.filter(n => n !== 17) - } - - if (game.persistent_events.includes(72)) { - let farmer_check - for (let space of spaces) { - if (space && space.country === game.pwr_struggle_in && space.socio === 3 && check_dem_control(space.space_id)) { - farmer_check = true - } - } - if (farmer_check && game.com_pwr_hand_limit > 0) { - log('Democrat receives 1 cards from Communist due to C72') - game.dem_pwr_hand_limit += 1 - game.com_pwr_hand_limit -= 1 - permanently_remove(72) - game.persistent_events = game.persistent_events.filter(n => n !== 72) - } - } - - if (game.persistent_events.includes(102) && game.dem_pwr_hand_limit >=2 && (game.pwr_struggle_in === 'Romania' || game.pwr_struggle_in === 'Bulgaria')) { - log('Communist receives 2 cards from Democrat due to C102') - game.dem_pwr_hand_limit -= 2 - game.com_pwr_hand_limit += 2 - permanently_remove(102) - game.persistent_events = game.persistent_events.filter(n => n !== 102) - } - - //Draw Power Cards - game.is_pwr_struggle = true - //console.log('game.dem_pwr_hand_limit', game.dem_pwr_hand_limit, 'game.com_pwr_hand_limit', game.com_pwr_hand_limit) - draw_cards(game.power_struggle_deck, game.dem_pwr_hand, game.com_pwr_hand, game.dem_pwr_hand_limit, game.com_pwr_hand_limit) - if (game.active === DEM) { - game.valid_cards = [...game.dem_pwr_hand] - } else { - game.valid_cards = [...game.com_pwr_hand] - } - //game.valid_cards = all_power_cards - - log(`Communist: ${game.com_pwr_hand.length} cards`) - log(`Democrat: ${game.dem_pwr_hand.length} cards`) - - //Check if The Crowd Turns Against Ceausescu occurs - if (game.table_cards.includes(54) && game.pwr_struggle_in === 'Romania') { - //console.log('draw cards: crowd subcheck, game.active', game.active) - if (game.active === COM) { - game.return = COM - next_player() - } - log_h3('C54') - game.persistent_events.push(54) - game.state = 'the_crowd_turns_against_ceausescu_prep' - } else { - log_h2('Raise the Stakes') - game.state = 'raise_stakes_1' - //console.log('game.state', game.state, 'game.active', game.active, 'game.view_opp_hand', game.view_opp_hand) - } - } -} - -states.the_crowd_turns_against_ceausescu_prep = { - get inactive() { - return `resolve ${clean_name(cards[54].name)}.` - }, - prompt() { - view.prompt = 'The Crowd Turns Against Ceausescu: draw cards.' - gen_action('draw') - }, - draw() { - game.ceausescu_cards = [] - draw_cards(game.power_struggle_deck, game.ceausescu_cards, game.com_pwr_hand, 15, game.com_pwr_hand.length) - //console.log('game.ceausescu_cards', game.ceausescu_cards) - game.temp = game.ceausescu_cards.filter(card => card && card >=25 && card <= 30).length - log(`Drew ${pluralize(game.temp, 'Rally in the Square')}.`) - game.vm_available_ops = game.temp * 3 - log(`Democrat takes a ${game.vm_available_ops} Action Round`) - game.state = 'vm_the_crowd_turns_against_ceausescu' - } -} - -states.vm_the_crowd_turns_against_ceausescu = { - get inactive() { - return `resolve ${clean_name(cards[54].name)}.` - }, - prompt() { - view.prompt = `You have ${game.vm_available_ops} operations points. Play for:` - gen_action('influence') - gen_action('support_check') - }, - influence() { - push_undo() - delete game.ceausescu_cards - valid_spaces_infl() - game.valid_spaces = game.valid_spaces.filter(n => spaces[n].country === 'Romania') - game.state = 'the_crowd_turns_against_ceausescu_infl' /* Send this to add_infl. Add check at end of add_infl similar to valid_spaces*/ - }, - support_check() { - push_undo() - delete game.ceausescu_cards - valid_spaces_sc() - game.available_ops = 2 - game.state = 'support_check_prep' - } -} - -states.the_crowd_turns_against_ceausescu_infl = { - inactive: 'add SPs.', - prompt () { - if (game.vm_available_ops === 0) - { - view.prompt = 'Place SPs: done.'; - gen_action("done"); - return; - } - - view.prompt = `Add SPs: ${game.vm_available_ops} remaining` - for (let space of game.valid_spaces) { - gen_action_infl(space) - } - }, - infl(space) { - vm_do_add_infl(space) - }, - done() { - if (game.summary.length > 0) { - pop_summary() - log_br() - } - - if (game.return !== game.active) { - next_player() - } - log_h2('Raise the Stakes') - game.state = 'raise_stakes_1' - } -} - -states.raise_stakes_1 = { - inactive: 'raise the stakes.', - - prompt () { - // console.log('raise stakes 1 - valid cards', game.valid_cards) - // console.log('raise the stakes: game.played_power_card', game.played_power_card, 'game.active', game.active, 'game.view_opp_hand', game.view_opp_hand) - if ((game.active === DEM && game.dem_pwr_hand < 3) || (game.active === COM && game.com_pwr_hand < 3)) { - view.prompt = 'Raise the stakes: you must pass.' - gen_action('pass') - } - else if (game.raised_stakes_discard === 3) { - view.prompt = 'Raise the stakes: done.' - gen_action('done') - } else { - view.prompt = `Discard ${3-game.raised_stakes_discard} cards to raise the stakes.` - if (game.raised_stakes_discard === 0) { - gen_action('pass') - } - for (let card of game.valid_cards) { - gen_action_card(card) - } - } - }, - card(card) { - push_undo() - if (numberless_cards.includes(card)) { - log(`Discarded: P${card}`) - } else { - log(`Discarded: P${card} V${power_cards[card].value}`) - } - discard(card) - - game.raised_stakes_discard ++ - if (game.raised_stakes_discard === 3) { - game.raised_stakes++ - game.valid_cards = [] - } - }, - pass(){ - log('Did not raise the stakes') - game.raised_stakes_discard = 0 - next_player() - if (game.active === DEM) { - game.valid_cards = [...game.dem_pwr_hand] - } else { - game.valid_cards = [...game.com_pwr_hand] - } - game.state = 'raise_stakes_2' - }, - done () { - log_gap('Raised the stakes') - game.raised_stakes_discard = 0 - next_player() - //console.log('game.active', game.active) - if (game.active === DEM) { - game.valid_cards = [...game.dem_pwr_hand] - } else { - game.valid_cards = [...game.com_pwr_hand] - } - // console.log('game.valid_cards', game.valid_cards) - game.state = 'raise_stakes_2' - } -} - -states.raise_stakes_2 = { - inactive: 'raise the stakes.', - - prompt () { - if ((game.active === DEM && game.dem_pwr_hand < 3) || (game.active === COM && game.com_pwr_hand < 3)) { - view.prompt = 'Raise the stakes: you must pass.' - gen_action('pass') - return - } - if (game.raised_stakes_discard === 3) { - view.prompt = 'Raise the stakes: done.' - gen_action('done') - } else { - view.prompt = `Discard ${3-game.raised_stakes_discard} cards to raise the stakes.` - if (game.raised_stakes_discard === 0) { - gen_action('pass') - } - for (let card of game.valid_cards) { - gen_action_card(card) - } - } - }, - card(card) { - push_undo() - if (numberless_cards.includes(card)) { - log(`Discarded: P${card}`) - } else { - log(`Discarded: P${card} V${power_cards[card].value}`) - } - discard(card) - - game.raised_stakes_discard ++ - if (game.raised_stakes_discard === 3) { - game.raised_stakes++ - game.valid_cards = [] - } - - }, - pass() { - log('Did not raise the stakes') - game.raised_stakes_discard = 0 - game.valid_cards = [] - log_h2('Play Cards') - next_player() - game.state = 'begin_power_struggle' - }, - done () { - log_gap('Raised the stakes') - game.raised_stakes_discard = 0 - game.valid_cards = [] - log_h2('Play Cards') - next_player() - game.state = 'begin_power_struggle' - }, -} - -states.begin_power_struggle = { - inactive: 'begin power struggle.', - prompt() { - view.prompt = 'Begin power struggle.' - gen_action('struggle') - }, - struggle () { - do_valid_cards() - game.state = 'power_struggle' - } -} - -states.power_struggle = { - inactive: 'play a card.', - prompt () { - console.log('game.vm_event', game.vm_event) - if (game.phase === 0) { - if (game.valid_cards.length > 0) { - view.prompt = "Play a card." - for (let card of game.valid_cards) { - gen_action_card(card) - } - } else if ( game.valid_cards.length === 0) { - view.prompt = 'No valid cards. You must concede.' - gen_action('concede') - } - } - if (game.phase === 1) { - if (game.valid_cards.length > 0) { - view.prompt = `${power_cards[game.played_power_card].name} played. You must match or concede.` - gen_action('concede') - for (let card of game.valid_cards) { - gen_action_card(card) - } - } else if (game.valid_cards.length === 0) { - view.prompt = `${power_cards[game.played_power_card].name} played. You must concede.` - gen_action('concede') - } - } - else if (game.phase === 2) { - view.prompt = 'You matched. Roll a die.' - gen_action('roll') - } - else if (game.phase === 3) { - view.prompt = 'Play leader as:' - if (game.tactics_fails !== "Strike") {gen_action('strike')} - if (game.tactics_fails !== "March") {gen_action('march')} - if (game.tactics_fails !== "Rally in the Square") {gen_action('rally')} - if (game.tactics_fails !== "Petition") {gen_action('petition')} - } - }, - card(card) { - push_undo() - discard(card) - game.valid_cards=[] - game.return_state = 'power_struggle' - if (card === 52) { - log_gap(`Played P52: P${power_cards[game.played_power_card].number} no longer playable`) - - } else { - if (game.phase === 0 && leader_cards.includes(card)) {} /* Log nothing. Probably a better way to do this */ - else if (numberless_cards.includes(card)) { - log_gap(`Played: P${card}`) - } else { - log_gap(`Played: P${card} V${power_cards[card].value}`) - } - } - if (game.phase === 0) { - if (card >= 37 && card <= 48) { /*When a leader is played */ - game.played_power_card = card - game.phase = 3 - } else if (card === 49){ /*Scare Tactics */ - game.return = '' - goto_vm(349) /*Can I combine these 3 into a single stage where you goto_vm(300 + card) ? */ - } else if (card === 50) { /*Support Surges */ - if (game.active === DEM) { - game.return = COM - } else { - game.return = DEM - } - goto_vm(350) - } else if (game.phase === 0 && card === 51) { /*Support Falters */ - next_player() - goto_vm(351) - } else { - game.played_power_card = card - game.phase = 1 - next_player() - do_valid_cards() - } - } else if (game.phase === 1) { - if (card === 52) { - game.tactics_fails = power_cards[game.played_power_card].name - game.phase = 0 - next_player() - do_valid_cards() - } else if (power_cards[game.played_power_card].value === 1) { - log('Takes initiative') - game.phase = 0 - do_valid_cards() - } else { - game.phase = 2 - } - } - }, - roll () { - let roll = Math.floor(Math.random() * 6) + 1 - log(`Roll: D${roll}`) - if (roll >= power_cards[game.played_power_card].value) { - log('Initiative roll successful') - game.phase = 0 - do_valid_cards() - } else { - log(`Initiative roll failed. Required ${power_cards[game.played_power_card].value} or more`) - game.phase = 0 - next_player() - do_valid_cards() - } - }, - concede () { - push_undo() - game.valid_cards = [] - log('Conceded') - log_h2('Aftermath') - log_h3('Support Loss') - //if ((game.played_power_card >= 25 && game.played_power_card <= 30) || game.played_power_card === 53) {game.rally_win = 2} - //if ((game.played_power_card >= 31 && game.played_power_card <= 36) || game.played_power_card === 54) {game.petition_win = 2} - if (game.phase === 0) { - game.played_power_card = 0 /*If conceded when held the initiative but had no playable cards, ignore the last played card */ - } - game.phase = 0 - game.state = 'support_loss' - }, - strike () { - log(`Played: P${power_cards[game.played_power_card].number} as a Strike`) - game.played_power_card = 9 - game.phase = 1 - next_player() - do_valid_cards() - }, - march () { - log(`Played: P${power_cards[game.played_power_card].number} as a March`) - game.played_power_card = 21 - game.phase = 1 - next_player() - do_valid_cards() - }, - rally () { - log(`Played: P${power_cards[game.played_power_card].number} as a Rally in the Square`) - game.played_power_card = 53 - game.phase = 1 - next_player() - do_valid_cards() - }, - petition () { - log(`Played: P${power_cards[game.played_power_card].number} as a Petition`) - game.played_power_card = 54 - game.phase = 1 - next_player() - do_valid_cards() - }, - /*draw () { - if (game.active === DEM) { - draw_cards(game.power_struggle_deck, game.dem_pwr_hand, game.com_pwr_hand, game.dem_pwr_hand.length+2, game.com_pwr_hand.length) - } else {draw_cards(game.power_struggle_deck, game.dem_pwr_hand, game.com_pwr_hand, game.dem_pwr_hand.length, game.com_pwr_hand.length+2)} - game.phase = 0 - next_player() - do_valid_cards() - },*/ - /*infl(space) { - game.remove_opponent_infl = true - remove_infl(space) - game.phase = 6 - }, - discard () { /*Is this still needed? - if (game.active === DEM) {discard_card(game.dem_pwr_hand)} - else {discard_card(game.com_pwr_hand)} - game.available_ops -- - }, */ - done () { - if (game.phase === 7) { /*Is this ever called anymore? */ - game.phase = 0 - log_msg_gap('Takes initiative') - do_valid_cards() - } else { - game.phase = 0 - next_player() - do_valid_cards() - } - } -} - -states.support_loss ={ - inactive: 'do Support Loss.', - prompt () { - if (!game.persistent_events.includes(111)) { - if (game.phase === 0) { - view.prompt = 'You lost the Power Struggle. Roll a die for Support Loss.' - gen_action('roll') - } else if (game.phase === 1 && game.available_ops > 0 && game.valid_spaces.length > 0) { - view.prompt = `Power Struggle - ${country_name(game.pwr_struggle_in)}. Support Loss: remove ${pluralize(game.available_ops,'SP')}.` - - for (let space_id of game.valid_spaces) { - gen_action_infl(space_id) - } - } else if (game.phase === 1 && game.available_ops === 0 ) { - view.prompt = `Power Struggle - ${country_name(game.pwr_struggle_in)}. Support Loss: finished.` - gen_action('done') - } else if (game.phase === 1 && game.valid_spaces.length === 0) { - view.prompt = `Power Struggle - ${country_name(game.pwr_struggle_in)}. Support Loss: no remaining SPs to remove.` - gen_action('done') - } - } else { - if (game.phase === 0) { - view.prompt = 'You lost the Power Struggle. Roll a die for Support Loss.' - gen_action('roll') - } else if (game.phase === 1 && game.available_ops > 0 && game.valid_spaces.length > 0) { - view.prompt = `New Year's Eve Party - ${country_name(game.pwr_struggle_in)}. Support Loss: remove ${pluralize(game.available_ops,'SP')}.` - - for (let space_id of game.valid_spaces) { - gen_action_infl(space_id) - } - } else if (game.phase === 1 && game.available_ops === 0 ) { - view.prompt = `New Year's Eve Party - ${country_name(game.pwr_struggle_in)}. Support Loss: finished.` - gen_action('done') - } else if (game.phase === 1 && game.valid_spaces.length === 0) { - view.prompt = `New Year's Eve Party - ${country_name(game.pwr_struggle_in)}. Support Loss: no remaining SPs to remove.` - gen_action('done') - } - } - }, - roll () { - clear_undo() - let roll = Math.floor(Math.random() * 6) + 1 - let rally_win = 0 - let petition_win = 0 - log(`Roll: D${roll}`) - if ((game.played_power_card >= 25 && game.played_power_card <= 30) || game.played_power_card === 53) { rally_win = 2} - if ((game.played_power_card >= 31 && game.played_power_card <= 36) || game.played_power_card === 54) { petition_win = 2} - let modified_roll = roll + game.raised_stakes + rally_win - petition_win - - // Roll modifiers - if (game.active === COM && game.persistent_events.includes(62)) { - log('+1 from C62') - modified_roll ++ - } - - if (modified_roll < 0) {modified_roll = 0} - else if (modified_roll > 7) {modified_roll = 7} - - - if (game.raised_stakes !== 0) { - log(`+${game.raised_stakes} from Raising the Stakes`) - } - if (rally_win !== 0) { - log('+2 from winning on a P25') - } - if (petition_win !== 0) { - log('-2 from winning on a P31') - } - if (modified_roll !== roll) { - log(`Modified roll: ${modified_roll}`) - } - game.available_ops = support_loss_roll[modified_roll] - if (game.available_ops === 0) { - log('Does not remove SPs') - } - game.phase++ - if (game.available_ops > 0) { - valid_spaces_support_loss() - } - }, - infl (space) { - game.remove_opponent_infl = false /* Don't know why this is needed... */ - remove_infl(space) - if (game.available_ops === 0 ) { - game.valid_spaces = [] - } - }, - done () { - if (game.summary.length > 0) { - pop_summary() - log_br() - } - next_player() - log_h3('Victory Point') - game.phase = 0 - game.state = 'vp_roll' - } -} - -states.vp_roll = { - inactive: 'do VP Roll.', - prompt () { - if (!game.persistent_events.includes(111)) { - if (game.phase === 0) { - view.prompt = `Power Struggle - ${country_name(game.pwr_struggle_in)}: roll a die for Victory.` - gen_action('roll') - } else if (game.phase === 1) { - view.prompt = `Power Struggle - ${country_name(game.pwr_struggle_in)}: take power.` - gen_action('take') - } else if (game.phase === 2) { - view.prompt = `Power Struggle - ${country_name(game.pwr_struggle_in)}: proceed to scoring.` - gen_action('scoring') - } - } else { - if (game.phase === 0) { - view.prompt = `New Year's Eve Party - ${country_name(game.pwr_struggle_in)}: roll a die for Victory.` - gen_action('roll') - } else if (game.phase === 1) { - view.prompt = `New Year's Eve Party - ${country_name(game.pwr_struggle_in)}: take power.` - gen_action('take') - } else if (game.phase === 2) { - view.prompt = `New Year's Eve Party - ${country_name(game.pwr_struggle_in)}: proceed to scoring.` - gen_action('scoring') - } - } - }, - roll () { - let roll = Math.floor(Math.random() * 6) + 1 - log(`Roll: D${roll}`) - let rally_win = 0 - let petition_win = 0 - if ((game.played_power_card >= 25 && game.played_power_card <= 30) || game.played_power_card === 53) {rally_win = 2} - if ((game.played_power_card >= 31 && game.played_power_card <= 36) || game.played_power_card === 54) {petition_win = 2} - let modified_roll = roll + game.raised_stakes + rally_win - petition_win - if (game.active === DEM && game.persistent_events.includes(62)) { - log('+1 from C62') - modified_roll ++ - } - if (modified_roll < 0) {modified_roll = 0} - else if (modified_roll > 7) {modified_roll = 7} - - if (game.raised_stakes !== 0) { - log(`+${game.raised_stakes} from Raising the Stakes`) - } - if (rally_win !== 0) { - log('+2 from winning on a P25') - } - if (petition_win !== 0) { - log('-2 from winning on a P31') - } - if (modified_roll !== roll) { - log(`Modified roll: ${modified_roll}`) - } - let vp_change = vp_roll[modified_roll] - if (game.active === DEM) { - log(`+${vp_change} VP`) - } else { - log(`-${vp_change} VP`) - } - if (roll >= 4) - //console.log('VP before', game.vp) - if (game.active === DEM) {game.vp += vp_change} - else {game.vp -= vp_change} - //console.log('VP after', game.vp) - if (game.active === DEM && modified_roll >= 4) { - game.phase = 1 - } else { - game.phase = 0 - if (game.active === DEM) {next_player()} - game.state = 'choose_power' - } - }, - take () { - push_undo() - //Find name of scoring card - let scoring_card = scoring_cards[countries.indexOf(game.pwr_struggle_in)] - permanently_remove(scoring_card) - take_power(game.pwr_struggle_in) - game.phase = 2 - }, - scoring () { - push_undo() - log_h2('Scoring') - score_country(game.pwr_struggle_in) - - //Check if The Tyrant is Gone occurs - if (game.table_cards.includes(97) && game.pwr_struggle_in === 'Romania' && game.persistent_events.includes(54)) { - game.return_state = 'finish_scoring' - if (game.active !== DEM) { - next_player() - } - game.state = 'the_tyrant_is_gone' - } else { - game.state = 'finish_scoring' - } - }, -} - -states.choose_power = { - inactive: 'choose whether to remain in power.', - prompt () { - if (game.phase === 0) { - view.prompt = 'Choose whether to remain in power.' - gen_action('retain') - gen_action('surrender') - } else if (game.phase === 1) { - view.prompt = 'Proceed to scoring.' - gen_action('scoring') - } - }, - retain() { - push_undo() - retain_power(game.pwr_struggle_in) - game.phase = 1 - }, - surrender () { - push_undo() - take_power(game.pwr_struggle_in) - permanently_remove(game.played_card) - game.phase = 1 - }, - scoring () { - push_undo() - score_country(game.pwr_struggle_in) - - //Check if The Tyrant is Gone occurs - if (game.table_cards.includes(97) && game.pwr_struggle_in === 'Romania' && game.persistent_events.includes(54)) { - game.return_state = 'finish_scoring' - if (game.active !== DEM) { - next_player() - } - game.state = 'the_tyrant_is_gone' - } else { - game.state = 'finish_scoring' - } - } -} -/* -states.score_country = { - inactive: `score country`, - prompt () { - view.prompt = 'Scoring: done.' - gen_action('done') - }, - done () { - reset_power() - /*if (game.return !== game.active) { - next_player()} - game.state = 'finish_scoring' - } -} -*/ - -states.the_tyrant_is_gone ={ - inactive: 'resolve The Tyrant is Gone.', - prompt() { - view.prompt = 'Play The Tyrant is Gone for the event.' - gen_action('event') - }, - event() { - if (game.active !== DEM) { - next_player() - } - if (game.round_player === DEM) { - game.return = COM - } else { - game.return = DEM - } - log_h3(`C97`) - game.vm_event = 97 - goto_vm(game.vm_event) - } -} - -states.finish_scoring ={ - inactive: 'finish scoring.', - prompt() { - view.prompt = 'End power struggle.' - gen_action('done') - } , - done() { - //console.log('game.return_state', game.return_state) - log_msg_gap('Power Struggle resolved') /*At this point log card dicarded or permanently removed? */ - if (game.persistent_events.includes(111)) { - game.state = 'new_years_eve_party' - return - } - if (check_vp()) { - return - } - reset_power() - end_round() - //game.state = 'end_round' - } -} - -// ======================================= END TURN STATES ========================================== - -states.end_turn_4_5_4 = { - inactive: 'verify held cards.', - prompt() { - view.prompt = 'End Turn: verify held cards.' - gen_action('check') - }, - check() { - log_h2('Verify held cards') - const dem_has_scoring_card = game.democrat_hand.some(card => scoring_cards.includes(card)) - const com_has_scoring_card = game.communist_hand.some(card => scoring_cards.includes(card)) - if (!dem_has_scoring_card && !com_has_scoring_card) { - log('No held scoring cards') - } - - if (dem_has_scoring_card && com_has_scoring_card) { - log('Both players have held scoring cards') - game.state = 'game_end_tie' - } - else if (dem_has_scoring_card) { - log('Democrat player has a held scoring card') - goto_game_over(COM, `${COM} won by held scoring card!`) - } - else if (com_has_scoring_card) { - log('Communist player has a held scoring card') - goto_game_over(DEM, `${DEM} won by held scoring card!`) - } - else if (game.persistent_events.includes(104)) { - log_h1(`New Year's Eve Party`) - game.vm_event = 104 - //Check if the Communist receives VP from The Tyrant is Gone - if (game.persistent_events.includes(97)) { - game.vp -= 2 - log(`Communist receives 2 VP from C97`) - } - game.persistent_events.push(111) - if (game.active !== DEM) { - next_player() - } - game.state = 'new_years_eve_party' - } - else if(game.turn === 10) { - clear_undo() - log_h2('Final Scoring') - - //Check if the Communist receives VP from The Tyrant is Gone - if (game.persistent_events.includes(97)) { - game.vp -= 2 - log(`Communist receives 2 VP from C97`) - } - game.state = 'final_scoring_held' - - } else { - game.return_state = '' - game.state = 'end_turn' - } - } -} - -states.end_turn = { - inactive: 'end the turn.', - prompt() { - view.prompt = 'End Turn: done.' - gen_action('done') - }, - done() { - new_turn() - } -} - -states.final_scoring_held = { - inactive: 'resolve final scoring.', - prompt() { - view.prompt = 'Final Scoring: Communist scores VP bonus for the number of countries they retain power.' - gen_action('bonus') - }, - bonus() { - // console.log('game.revolutions: ', game.revolutions) - const held_countries = game.revolutions.filter(value => value === false).length - let vp_gain = 4*held_countries - log(`Communist holds ${held_countries} countries: -${vp_gain} VP`) - game.vp -= 4*held_countries - game.temp = {'East_Germany': false, 'Poland': false, 'Czechoslovakia': false, 'Hungary': false, 'Romania': false, 'Bulgaria': false} - game.state = 'final_scoring' - } -} - -states.final_scoring = { - inactive: 'score countries.', - prompt() { - if (game.temp['East_Germany'] && game.temp['Poland'] && game.temp['Czechoslovakia'] && game.temp['Hungary'] && game.temp['Romania'] && game.temp['Bulgaria']) { - view.prompt = 'Final scoring: done.' - gen_action('end') - } else { - view.prompt = 'Choose a country to score:' - if (!game.temp['East_Germany']) {gen_action('east_germany')} - if (!game.temp['Poland']) {gen_action('poland')} - if (!game.temp['Czechoslovakia']) {gen_action('czechoslovakia')} - if (!game.temp['Hungary']) {gen_action('hungary')} - if (!game.temp['Romania']) {gen_action('romania')} - if (!game.temp['Bulgaria']) {gen_action('bulgaria')} - } - }, - east_germany() { - score_country('East_Germany') - game.temp['East_Germany'] = true - }, - poland() { - score_country('Poland') - game.temp['Poland'] = true - }, - czechoslovakia() { - score_country('Czechoslovakia') - game.temp['Czechoslovakia'] = true - }, - hungary() { - score_country('Hungary') - game.temp['Hungary'] = true - }, - romania() { - score_country('Romania') - game.temp['Romania'] = true - }, - bulgaria() { - score_country('Bulgaria') - game.temp['Bulgaria'] = true - }, - end() { - delete game.temp - if (game.vp > 0) { - goto_game_over(DEM, `${DEM} wins on Victory Point Track!`) - } else if (game.vp < 0) { - goto_game_over(COM, `${COM} wins on Victory Point Track!`) - } else if (game.vp === 0) { - goto_game_over('', `The game is tied!`) /*Not sure what to pass for result */ - } - } -} - -states.game_over = { - get inactive() { - return game.victory - }, - prompt() { - view.prompt = game.victory - }, -} - -// ========================== EVENT SPECIFIC STATES ================================= - -states.general_strike = { - inactive: 'discard a card.', - prompt() { - if (game.played_card === 0 ) { - view.prompt = 'General Strike: you must discard a card or play a Scoring Card.' - available_cards = game.communist_hand - for (let card of available_cards) { - gen_action_card(card) - } - } /*else if (game.phase >= 1) { - view.prompt = 'General Strike: done.' - gen_action('done') - } */ else if (game.played_card > 0 ) { - view.prompt = 'General Strike: roll a die.' - gen_action('roll') - } - }, - card (card) { - push_undo() - game.played_card = card - let find_card - find_card = game.communist_hand.indexOf(card) - game.communist_hand.splice(find_card, 1) - game.available_ops = get_card_ops(card) - if (scoring_cards.includes(card)) { - game.vm_event = card - log(`Played C${card} for the event`) - game.return_state = 'general_strike' - goto_vm(game.vm_event) - } else { - log(`Discarded C${cards[card].number}`) - } - }, - roll() { - clear_undo() - let roll = Math.floor(Math.random() * 6) + 1 - log(`Roll: D${roll}`) - - logi(`+${game.available_ops} ops`) - - let total = roll + game.available_ops - log(`Total: ${total}`) - - if (total > 5) { - log('The strike is over.') - permanently_remove(5) - game.persistent_events = game.persistent_events.filter(n => n !== 5) - } else { - log('The strike continues. Required 6 or more') - } - //game.phase = 1 - game.state = 'end_round' - }, /* - done () { - //end_round() - game.state = 'end_round' - }*/ -} - -states.honecker ={ - inactive: 'resolve Honecker.', - prompt() { - view.prompt = 'Honecker: you may take an extra action round.' - gen_action('extra') - gen_action('pass') - }, - extra() { - push_undo() - game.round++ - game.round_player = COM - game.persistent_events = game.persistent_events.filter(n => n !== 15) - game.state = 'choose_card' - }, - pass() { - log('C15: passed') - game.persistent_events = game.persistent_events.filter(n => n !== 15) - //end_round() - game.state = 'end_round' - } -} - -states.new_years_eve_party = { - get inactive() { - return `resolve ${clean_name(cards[104].name)}.` - }, - prompt() { - if (!game.is_pwr_struggle) { - view.prompt = `New Year's Eve Party: you may choose a country to have a final power struggle.` - if (!game.revolutions[0]) {gen_action('poland')} - if (!game.revolutions[1]) {gen_action('hungary')} - if (!game.revolutions[2]) {gen_action('east_germany')} - if (!game.revolutions[3]) {gen_action('bulgaria')} - if (!game.revolutions[4]) {gen_action('czechoslovakia')} - if (!game.revolutions[5]) {gen_action('romania')} - gen_action('pass') - } else { - view.prompt = `New Year's Eve Party: done.` - gen_action('end') - } - }, - east_germany() { - push_undo() - log('Chose to score East Germany') - game.vm_event = 42 - goto_vm(42) - }, - poland() { - push_undo() - log('Chose to score Poland') - game.vm_event = 22 - goto_vm(22) - }, - czechoslovakia() { - push_undo() - log('Chose to score Czechoslovakia') - game.vm_event = 55 - goto_vm(55) - }, - hungary() { - push_undo() - log('Chose to score Hungary') - game.vm_event = 23 - goto_vm(23) - }, - romania() { - push_undo() - log('Chose to score Romania') - game.vm_event = 95 - goto_vm(95) - }, - bulgaria () { - push_undo() - log('Chose to score Bulgaria') - game.vm_event = 43 - goto_vm(43) - }, - pass() { - push_undo() - log('No final power struggle') - if (game.vp > 0) { - goto_game_over(DEM, `New Year's Eve Party: ${DEM} wins on Victory Point Track!`) - } else if (game.vp < 0) { - goto_game_over(COM, `New Year's Eve Party: ${COM} wins on Victory Point Track!`) - } else if (game.vp === 0) { - goto_game_over('', `New Year's Eve Party: The game is tied!`) /*Not sure what to pass for result */ - } - }, - end() { - if (game.vp > 0) { - goto_game_over(DEM, `New Year's Eve Party: ${DEM} wins on Victory Point Track!`) - } else if (game.vp < 0) { - goto_game_over(COM, `New Year's Eve Party: ${COM} wins on Victory Point Track!`) - } else if (game.vp === 0) { - goto_game_over('', `CNew Year's Eve Party: The game is tied!`) /*Not sure what to pass for result */ - } - } -} - -states.stasi_end_round = { - inactive: 'choose next card due to Stasi.', - prompt() { - //console.log('game.stasi_card', game.stasi_card) - let available_cards = game.democrat_hand - if (available_cards.length === 0) { - view.prompt = 'Stasi: no cards remaining.' - gen_action('pass') - return - } - view.prompt = 'Stasi: you must select your next card to play.' - - for (let card of available_cards) { - gen_action_card(card) - } - }, - card(card) { - push_undo() - log_gap(`Democrat selected C${cards[card].number} as next card.`) - game.stasi_card = card - game.state = 'stasi_finish' - }, - pass() { - log('Stasi: Democrat has no remaining cards') - game.stasi_card = 0 - end_stasi_choose_card() - }, - end_round() { - push_undo() - if (game.stasi_card === 21) { - game.state = 'stasi_confirm' - } else { - end_stasi_choose_card() - } - } -} - -states.stasi_finish = { - inactive: 'choose next card due to Stasi.', - prompt() { - view.prompt = 'Stasi. Choose card: done.' - gen_action('done') - }, - done() { - push_undo() - if (game.stasi_card === 21) { - game.state = 'stasi_confirm' - } else { - end_stasi_choose_card() - } - } -} - -states.stasi_confirm = { - inactive: 'choose next card due to Stasi.', - prompt() { - if (game.stasi_card === 21 ) { - view.prompt = `If Common European Home selected, it must be played for Operations. Otherwise select the opponent's card instead.` - gen_action('done') - } - }, - done() { - game.playable_cards = game.playable_cards.filter( n => n !== 21) - end_stasi_choose_card() - } -} - -states.stasi_play_card = { - inactive: 'play a card.', - prompt () { /*Should get rid of the play card 'done' prompt for consistency with general play */ - /*if (game.played_card > 0) { - game.state = 'play_card' - view.prompt = 'Play card: done.' - gen_action("done"); - return;*/ - //} else - if (game.democrat_hand.length === 0) { - view.prompt = 'Stasi: you must pass.' - gen_action('pass') - } else { - view.prompt = `Stasi: you must play ${clean_name(cards[game.stasi_card].name)}.` - let available_cards = [game.stasi_card] - for (let card of available_cards) { - gen_action_card(card) - } - } - }, - card(card) { - push_undo() - //log_msg_gap(`Stasi: played C${card}`) - game.played_card = card - let find_card - find_card = game.democrat_hand.indexOf(card); - game.democrat_hand.splice(find_card, 1); - game.available_ops = get_card_ops(card) - - if (game.democrat_hand.includes(21) && cards[card].side === "C") { - game.state = 'stasi_resolve_common_european_home' - } else { - game.state = 'play_card' - } - - }, - pass () { - log('No cards remaining. Passed') - //end_round() - game.state = 'end_round' - }, - done () { - //game.stasi_card = 0 - if (game.democrat_hand.includes(21)) { - game.state = 'stasi_resolve_common_european_home' - } else { - game.state = 'play_card' - } - } -} - -states.stasi_resolve_common_european_home = { - inactive: 'play a card.', - prompt () { - view.prompt = `Do you wish to play ${clean_name(cards[game.played_card].name)} with Common European Home?` - gen_action('yes') - gen_action('no') - }, - yes() { - log(`Played with Common European Home`) - silent_discard(21) - game.vm_infl_to_do = true - game.vm_event_to_do = false - game.state = 'resolve_opponent_event' - }, - no() { - game.state = 'play_card' - } -} - - -// ==================== SUPPORTING STATE FUNCTIONS ============================= - - -function add_infl(space) { - push_undo() - //console.log('adding infl to', space) - //console.log('at start, event', game.persistent_events['austria_hungary_border_reopened'], 'ahbr', game.austria_hungary_border_reopened, 'tracker', game.austria_hungary_border_reopened_tracker) - //log(`Added 1 influence in %${space}`) - log_summary(`Added £ SP in %${space}`) - - //If AHBR - check AHBR conditions - if (game.persistent_events.includes(58)) { - if (spaces[space].country !== 'East_Germany'){ - game.austria_hungary_border_reopened_tracker = false - } - } - - // Check Genscher - if (game.persistent_events.includes(63) && game.active === DEM && spaces[space].country === 'East_Germany' && check_com_control(space)) { - game.available_ops-- - log_summary(`(-1 op due to C63)`) - } else if (check_opp_control(space)) { - game.available_ops -= 2 - //Check if Austria Hungary Border Reopened was used to place last SP in a controlled space in East Germany. If so, game.available_op will be negative - if (game.available_ops < 0) { - log_summary(`(Used +1 op from C58)`) - } - } else { - game.available_ops-- - } - - // Update influence values - if (game.active === COM) { - game.comInfl[space]++ - } else { - game.demInfl[space]++ - } - - // Check whether spaces are controlled - check_control_change(space) - - // Check Austria Hungary Border Reopened is true and condition has been met - if (game.available_ops === 0 && game.active === DEM && game.persistent_events.includes(58) && game.austria_hungary_border_reopened_tracker) { - game.available_ops ++ - log('+1 op from C58') - game.austria_hungary_border_reopened_tracker = false - game.valid_spaces = game.valid_spaces.filter(n => spaces[n].country === 'East_Germany') - } - - // If only 1 IP remaining, may not place in opponent controlled spaces - - // Check for Genscher & Austria Hungary Border Reopened - - if (game.available_ops === 1) { - //console.log(`in Genscher / AHBR check, game.persistent_events['genscher']`, game.persistent_events['genscher']) - if (game.active === DEM) { - if (game.persistent_events.includes(63) || (game.persistent_events.includes(58) && game.austria_hungary_border_reopened_tracker)) { - //console.log('in gensher subcheck - remove non-East German controlled ') - game.valid_spaces = game.valid_spaces.filter(n => !(check_opp_control(n) && spaces[n].country !== 'East_Germany')) - } else { - //console.log('remove all controlled spaces') - game.valid_spaces = game.valid_spaces.filter(n => !check_opp_control(n)) - } - } else { - //console.log('remove all dem controlled spaces') - game.valid_spaces = game.valid_spaces.filter(n => !check_opp_control(n)) - } - } - - //Clear valid spaces if no IP remaining. - if (game.available_ops <= 0 ) { - game.valid_spaces = [] - } -} - -function remove_infl(space) { - push_undo() - //log(`Removed 1 influence from %${space}.`) - log_summary(`Removed £ SP from %${space}.`) - - if (game.remove_opponent_infl === true) { - if (game.active === COM) { - game.demInfl[space]-- - if (game.demInfl[space] === 0) { - game.valid_spaces = game.valid_spaces.filter(id => id !== space); - } - } else { - game.comInfl[space]-- - if (game.comInfl[space] === 0) { - game.valid_spaces = game.valid_spaces.filter(id => id !== space); - } - } - check_control_change(space) - - } else { - if (game.active === COM) { - game.comInfl[space]-- - if (game.comInfl[space] === 0) { - game.valid_spaces = game.valid_spaces.filter(id => id !== space); - } - } else { - game.demInfl[space]-- - if (game.demInfl[space] === 0) { - game.valid_spaces = game.valid_spaces.filter(id => id !== space); - } - } - check_control_change(space) - } - game.available_ops-- -} - -function do_sc(space) { - clear_undo() - log_gap(`Support check: %${space}`) - - //Check Helsinki Final Act - - if (game.active === COM && game.persistent_events.includes(26) && (spaces[space].socio === 5 || spaces[space].socio === 6) ) { - log('+1 VP from C26') - game.vp ++ - if (check_vp()) { - game.state = 'game.over' - //console.log('after check_vp, game.state', game.state) - return - } - } - - // Continue with Support Check Logic - - let roll = Math.floor(Math.random() * 6) + 1 - log(`Roll: D${roll}`) - - /* - //Check if support check is being done with game.played_card or a subsequent card (e.g. Common European Home, Dash for the West, etc) - if (game.vm_event > 0) { - roll+= cards[game.vm_event].ops - log(`+${cards[game.vm_event].ops} from card ops`) - } - */ - // Check for the Crowd Turns Against Ceausescu - - //else - if (game.is_pwr_struggle) { - roll += game.vm_available_ops - logi(`+${game.vm_available_ops} from Ceausescu`) - } - - // Check if in Tiananmen Square Track Award - - else if (game.state === 'vm_tst_6_sc') { - roll += get_tst_6_ops() - roll += 2 - logi('+2 TST award') - } - else { - //let modifier = 0 - let card_ops = get_card_ops(this_card()) - - roll += card_ops - logi(`+${card_ops} from card ops`) - } - - if (game.support_check_modifier > 0) { - roll += game.support_check_modifier - logi(`+${game.support_check_modifier} from event`) - } - - // Events which modify SC rolls - //Tear Gas - if (game.active === COM && game.persistent_events.includes(30) && spaces[space].socio === 6) { - roll ++ - logi('+1 from C30') - permanently_remove(30) - game.persistent_events = game.persistent_events.filter(n => n !== 30) - } - //FRG Embassies - if (game.active === DEM && spaces[space].region === 'Eastern Europe' && game.persistent_events.includes(74)) { - roll++ - logi('+1 from C74') - } - //GrenzTruppen - if (game.active === DEM && spaces[space].country === 'East_Germany' && game.persistent_events.includes(59)) { - roll-- - logi('-1 from C59') - } - //Stand Fast - if ((game.active === COM && game.stand_fast === DEM && check_dem_control(space)) || (game.active === DEM && game.stand_fast === COM && check_com_control(space))){ - roll-- - logi('-1 from C100') - } - //Elena - if (game.active === DEM && game.persistent_events.includes(101) && spaces[space].country === 'Romania') { - roll-- - logi('-1 from C101') - } - //Austria Hungary Border Reopened - if (game.active === DEM && game.persistent_events.includes(58) && game.austria_hungary_border_reopened_tracker) { - roll++ - logi(`+1 from C58`) - } - - // Continue with logic - check for adjacency - - // Events which affect adjacency - The Wall - - const adj = count_adj(space) - //console.log('adj', adj) - if (game.active === COM && game.persistent_events.includes(9) && spaces[space].country === 'East_Germany') { - logi('No adjacency for Democrats due to C9') - logi('C9 no longer in effect') - roll += adj.com_adj - if (adj.com_adj > 0) { - logi(`+${adj.com_adj} adjacency`) - } - game.persistent_events = game.persistent_events.filter(n => n !== 9) - - // Standard adjacency - } else { - if (adj.dem_adj > 0 || adj.com_adj > 0 ){ - if (game.active === DEM) { - roll += adj.dem_adj - roll -= adj.com_adj - if (adj.dem_adj > 0) { - logi(`+${adj.dem_adj} from adjacency`) - } - if (adj.com_adj > 0) { - logi(`-${adj.com_adj} from opponent adjacency`) - } - } else { - roll += adj.com_adj - roll -= adj.dem_adj - if (adj.com_adj > 0) { - logi(`+${adj.com_adj} from adjacency`) - } - if (adj.dem_adj > 0) { - logi(`-${adj.dem_adj} from opponent adjacency`) - } - } - } - - } - - // Support check calcs - log(`Modified total: ${roll}`) - const stability = spaces[space].stability - logi(`-${stability*2} (stability * 2)`) - const change_infl = Math.max(0, roll - stability*2) - if (change_infl > 0) { - log_msg_gap(`Change influence: ${change_infl} SP`) - if(game.active === DEM) { - if (change_infl > game.comInfl[space]) { - const residual = change_infl - game.comInfl[space] - game.comInfl[space] = 0 - game.demInfl[space] += residual - } else { - game.comInfl[space] -= change_infl - } - if (game.comInfl[space] === 0) { - game.valid_spaces = game.valid_spaces.filter(id => id !== space) - } - } else { - if (change_infl > game.demInfl[space]) { - const residual = change_infl - game.demInfl[space] - game.demInfl[space] = 0 - game.comInfl[space] += residual - } else { - game.demInfl[space] -= change_infl - } - if (game.demInfl[space] === 0) { - game.valid_spaces = game.valid_spaces.filter(id => id !== space) - } - } - check_control_change(space) - - } else { - log_msg_gap('Change influence: 0 SP') - } - if (game.active === COM && game.persistent_events.includes(39) && spaces[space].space_id === 66) { - log_msg_gap('+1 VP from C39') - game.vp++ - if (check_vp()) { - return - } - } - - // If Austria-Hungary Border Reopened used, all future support checks must be in East Germany - if (game.persistent_events.includes(58)){ - if (game.austria_hungary_border_reopened_tracker) { - game.valid_spaces = game.valid_spaces.filter(n => spaces[n].country === 'East_Germany') - } - } - game.selected_space = 0 - -} - -function valid_spaces_setup() { - game.valid_spaces = [] - let valid_spaces_set = new Set(); - //console.log('in vs setup, state', game.state) - for (let i =1 ; i <= 75 ; i++) { - space = spaces[i] - - if (game.state === 'com_init') { - infl = game.demInfl[i] - - if (infl === 0) { - valid_spaces_set.add(space.space_id); - } - } else if (game.state === 'dem_init') { - infl = game.comInfl[i] - if (infl === 0) { - valid_spaces_set.add(space.space_id); - } - } - } - // Convert the set to an array before returning - game.valid_spaces = Array.from(valid_spaces_set); - return game.valid_spaces; -} - -function valid_spaces_sc() { - let valid_spaces_set = new Set(); - //console.log('valid spaces sc, persistent events', game.persistent_events) - - for (let i = 1 ; i <= 75; i++) { - space = spaces[i] - - if (game.active === DEM) { - infl = game.comInfl[i] - if (infl !== 0 ) { - valid_spaces_set.add(space.space_id); - } - } else { - infl = game.demInfl[i] - if (infl !== 0 ) { - // Check Solidarity Legalised - if (game.persistent_events.includes(2) && space.space_id === 14) {continue} - - // Check Civic Forum - if (game.persistent_events.includes(90) && space.space_id === 30) {continue} - - // Check We Are the People - if (game.persistent_events.includes(48) && space.space_id === 9) {continue} - - //Check for Foreign Currency Debt Burden - if (game.persistent_events.includes(49) && space.country === game.foreign_currency_debt_burden) {continue} { - - valid_spaces_set.add(space.space_id); - - } - } - } - } - - - // Convert the set to an array before returning - game.valid_spaces = Array.from(valid_spaces_set); - - //Check for the Crown Turns Against Ceausescu - if (game.is_pwr_struggle && game.pwr_struggle_in === 'Romania' && game.persistent_events.includes(54)) { - game.valid_spaces = game.valid_spaces.filter(n => spaces[n].country === 'Romania') - } - return game.valid_spaces; -} - -function valid_spaces_support_loss() { - let valid_spaces_set = new Set(); - for (let i = 1; i < game.demInfl.length; i++) { - //console.log('spaces.length', game.demInfl.length, 'i', i) - space = spaces[i] - if (game.active === DEM) { - infl = game.demInfl[i] - if (infl > 0 && space.country === game.pwr_struggle_in) { - valid_spaces_set.add(space.space_id); - } - } else { - infl = game.comInfl[i] - if (infl > 0 && space.country === game.pwr_struggle_in) { - valid_spaces_set.add(space.space_id); - } - } - } - - // Convert the set to an array before returning - game.valid_spaces = Array.from(valid_spaces_set); - return game.valid_spaces; -} -/* -function valid_spaces_support_falters() { - let valid_spaces_set = new Set(); - if (game.active === DEM) { - for (let piece of game.pieces) { - if (!piece) continue - let space = spaces.find(s => s && s.space_id === piece.space_id); - if (space && piece.comInfl > 0 && space.country === game.pwr_struggle_in) { - valid_spaces_set.add(space.space_id); - } - } - } else { - for (let piece of game.pieces) { - if (!piece) continue - let space = spaces.find(s => s && s.space_id === piece.space_id); - if (space && piece.demInfl > 0 && space.country === game.pwr_struggle_in) { - valid_spaces_set.add(space.space_id); - } - } - } - // Convert the set to an array before returning - game.valid_spaces = Array.from(valid_spaces_set); - return game.valid_spaces; -} - */ - -function valid_spaces_infl() { - /*if (game.state.startsWith('vm')) { - console.log('valid_spaces_infl called from VM') - } else { - console.log('valid_spaces_infl called not from VM') - }*/ - // Check if function is called from the VM or not, take relevant ops variable - let ops = game.state.startsWith('vm') ? game.vm_available_ops : game.available_ops; - - let valid_spaces_set = new Set(); - // Iterate over all spaces to find the ones with the player's influence - for (let i = 1; i < game.demInfl.length; i++) { - //piece = game.pieces[i] - space = spaces[i] - - let player_influence = game.active === COM ? game.comInfl[i] : game.demInfl[i]; - - // If the piece has the player's influence, add it and its adjacent spaces to the set - if (player_influence > 0) { - valid_spaces_set.add(space.space_id); - - // Check adjacency information - let adjacent_spaces = get_adjusted_adjacency(space.space_id) - - for (let adj_space_id of adjacent_spaces) { - //console.log('adj_space_id', adj_space_id) - if (adj_space_id) { - - const adj_piece = spaces[adj_space_id]; - //console.log('adjacent piece name', adj_piece.name_unique) - - // Check if the adjacent space is controlled by the opponent - const opponent_control = check_opp_control(adj_piece.space_id) - //console.log('controlled?', opponent_control) - - //Check for Genscher. Can always place in East Germany even with 1 op - if (game.active === DEM && adj_piece.country === 'East_Germany' && game.persistent_events.includes(63)){ - // console.log('space added with genscher') - valid_spaces_set.add(adj_piece.space_id) - } - - // Otherwise, only add the adjacent space if the available_ops >= 2 or the space is not controlled by the opponent - if (ops >= 2 || !opponent_control) { - valid_spaces_set.add(adj_piece.space_id) - } - } - } - } - } - // Convert the set to an array before returning - game.valid_spaces = Array.from(valid_spaces_set); - return game.valid_spaces; -} - -function valid_cards(player_hand, presence) { - const valid_cards_set= new Set(); - if (game.phase === 0) { - for (let c of player_hand) { - let card = power_cards.find(card => card && card.number === c); - if (card.number === 52) {continue} // Never add tactics fails - if (card.name === game.tactics_fails) {continue} //Cannot play the suit of Tactics Fails - if (card.socio === 0) { - valid_cards_set.add(card.number); - } else if (leaders.includes(card.socio) && presence[card.socio]) { - valid_cards_set.add(card.number); - } - } - } else if (game.phase === 1) { - for (let c of player_hand) { - let card = power_cards.find(card => card && card.number === c); - if (card.name === power_cards[game.played_power_card].name) { - valid_cards_set.add(card.number); - } else if (leaders.includes(card.socio) && presence[card.socio]) { - valid_cards_set.add(card.number); - } else if (card.number === 52) {valid_cards_set.add(card.number)} - } - } - game.valid_cards = Array.from(valid_cards_set); - return game.valid_cards; -} - -function do_valid_cards() { - let presence = check_presence(game.pwr_struggle_in) - if (game.active === DEM) { - valid_cards(game.dem_pwr_hand, presence.dem_leaders) - - } else { - valid_cards(game.com_pwr_hand, presence.com_leaders)} -} - -function count_adj(id) { - const space = spaces[id] - let dem_adj = 0 - let com_adj = 0 - - let adjacent_spaces = get_adjusted_adjacency(space.space_id) - - for (let adj_space_id of adjacent_spaces) { - if (adj_space_id) { - const adj_piece = spaces.find(piece => piece && piece.space_id === adj_space_id); - //console.log('adj_piece.space_id', adj_piece.space_id, 'space', space) - if (adj_piece && adj_piece.space_id !== space.space_id) { - if (check_dem_control(adj_piece.space_id)) { - //console.log('added DEM space', spaces[adj_piece.space_id].name) - dem_adj++ - } - if (check_com_control(adj_piece.space_id)) { - //console.log('added COM space', spaces[adj_piece.space_id].name) - com_adj++ - } - } - } - } - //console.log('dem_adj: ', dem_adj, 'com_adj: ', com_adj) - return {dem_adj, com_adj} -} - -/*function count_adj_worker(space_id) { - const space = spaces[space_id] - let dem_adj = 0 - let com_adj = 0 - - for (let adj_space_id of space.adjacent) { - if (adj_space_id) { - const adj_space = spaces[adj_space_id] - if (adj_space && adj_space.socio === 4) { - const adj_piece = game.pieces.find(piece => piece && piece.space_id === adj_space_id ); - if (adj_piece) { - if (adj_piece.demCtrl === 1 ) { - dem_adj++ - } - if (adj_piece.comCtrl === 1 ) { - com_adj++ - } - } - } - } - } - return {dem_adj, com_adj} -} */ - -function check_control(space_id) { - //console.log('in check control, space', spaces[space_id].name_unique) - if ( (game.comInfl[space_id] - game.demInfl[space_id]) >= spaces[space_id].stability) { - return true; - } else if ((game.demInfl[space_id] - game.comInfl[space_id]) >= spaces[space_id].stability) { - //console.log('true') - return true; - } else { - //console.log('false') - return false; - } -} - -function check_opp_control(space_id) { - if (spaces[space_id].country === 'Romania') { - //console.log('in check opp control, space', spaces[space_id].name_unique) - } - if (game.active === DEM && ((game.comInfl[space_id] - game.demInfl[space_id]) >= spaces[space_id].stability)) { - if (spaces[space_id].country === 'Romania') { - //console.log('control true') - } - return true; - } else if (game.active === COM && ((game.demInfl[space_id] - game.comInfl[space_id]) >= spaces[space_id].stability)) { - //console.log('true') - return true; - } else { - //console.log('false') - return false; - } -} - -function check_dem_control(space_id) { - if ((game.demInfl[space_id] - game.comInfl[space_id]) >= spaces[space_id].stability) { - return true; - } else { - return false; - } -} - -function check_com_control(space_id) { - if ((game.comInfl[space_id] - game.demInfl[space_id]) >= spaces[space_id].stability) { - return true; - } else { - return false; - } -} - -function do_tst_attempt() { - let roll = Math.floor(Math.random() * 6) + 1; - log(`Roll: D${roll}`); - - roll += game.available_ops - logi(`+${game.available_ops} from card ops`) - - // TIANANMEN SQUARE MODIFIERS - - if (game.active === DEM && game.dem_tst_attempted === 1 || game.active === COM && game.com_tst_attempted === 1) { - roll ++; - logi('+1 from previous TST attempts') - } - if (game.active === DEM && game.dem_tst_position >= 1 && game.com_tst_position === 0) { - roll ++ - logi('+1 from TST award') - } - if (game.active === COM && game.com_tst_position >= 1 && game.dem_tst_position === 0) { - roll ++ - logi('+1 from TST award') - } - if ((game.active === DEM && cards[game.played_card].side === 'D') || (game.active === COM && cards[game.played_card].side === 'C')) { - roll ++; - logi('+1 for playing own card'); - } - if (game.active === COM && game.persistent_events.includes(53)) { - roll ++ - logi('+1 from C53') - } - log(`Modified total: ${roll}`) - - // TIANANMEN SQUARE ATTEMPT - game.return = game.active - game.return_state = 'tiananmen_square_attempt_done' - if (game.active === DEM) { - game.dem_tst_attempted_this_turn = 1 - if (roll >= dem_tst_req[game.dem_tst_position]) { - log(`${dem_tst_req[game.dem_tst_position]} required: success`) - game.dem_tst_position++ - game.dem_tst_attempted = 0 - - //Check if they have reached box 7 or 8 first - if (game.dem_tst_position === 7 && game.com_tst_position < 7) { - game.tst_7 = false - } - if (game.dem_tst_position === 8 && game.com_tst_position < 8) { - game.tst_8 = false - } - - //Check if they have caught up to box 7 or 8 - if (game.dem_tst_position >= 7 && game.com_tst_position >= 7) { - delete game.tst_7 - } - if (game.dem_tst_position >= 8 && game.com_tst_position >= 8) { - delete game.tst_8 - } - - //Check if TST events occur - if (game.dem_tst_position === 3 && game.com_tst_position < 3) {game.vm_event = 203} - else if (game.dem_tst_position === 4 && game.com_tst_position < 4) {game.vm_event = 204} - game.state = 'tiananmen_square_attempt_success' - } else { - log(`${dem_tst_req[game.dem_tst_position]} required: fail`) - game.dem_tst_attempted = 1 - game.state = 'tiananmen_square_attempt_fail' - } - } else { - game.com_tst_attempted_this_turn = 1 - if (roll >= com_tst_req[game.com_tst_position]) { - log(`${com_tst_req[game.com_tst_position]} required: success`) - game.com_tst_position++ - game.com_tst_attempted = 0 - - //Check if they have reached box 7 or 8 first - if (game.com_tst_position === 7 && game.dem_tst_position < 7) { - game.tst_7 = false - } - if (game.com_tst_position === 8 && game.dem_tst_position < 8) { - game.tst_8 = false - } - - //Check if they have caught up to box 7 or 8 - if (game.com_tst_position >= 7 && game.dem_tst_position >= 7) { - delete game.tst_7 - } - if (game.com_tst_position >= 8 && game.dem_tst_position >= 8) { - delete game.tst_8 - } - - //Check if TST events occur - if (game.com_tst_position === 3 && game.dem_tst_position < 3) {game.vm_event = 203} - else if (game.com_tst_position === 4 && game.dem_tst_position < 4) {game.vm_event = 204} - game.state = 'tiananmen_square_attempt_success' - } else { - log(`${com_tst_req[game.com_tst_position]} required: fail`) - game.com_tst_attempted = 1 - game.state = 'tiananmen_square_attempt_fail' - } - } -} - -function check_presence(country) { - - let dem_spaces = 0; - let com_spaces = 0; - let dem_battlegrounds = 0; - let com_battlegrounds = 0; - let dem_leaders = {1: false, 4: false, 5: false, 6: false, 7: false}; - let com_leaders = {1: false, 4: false, 5: false, 6: false, 7: false}; - - - for (let i = 1; i < spaces.length; i++) { - let space = spaces[i] - if (space.country === country) { - - if (check_dem_control(i)) { - dem_spaces++; - if (space.battleground === 1) { - dem_battlegrounds++; - } - if (leaders.includes(space.socio)) { - dem_leaders[space.socio] = true; - } - } - if (check_com_control(i)) { - com_spaces++; - if (space.battleground === 1) { - com_battlegrounds++; - } - if (leaders.includes(space.socio)) { - com_leaders[space.socio] = true; - } - } - } - } - - // Determine domination - let dem_domination = dem_battlegrounds > com_battlegrounds && dem_spaces > com_spaces && dem_spaces - dem_battlegrounds > 0; - let com_domination = com_battlegrounds > dem_battlegrounds && com_spaces > dem_spaces && com_spaces - com_battlegrounds > 0; - - // Determine control - let total_battlegrounds = battlegrounds(country); - let dem_control = dem_battlegrounds === total_battlegrounds && dem_spaces > com_spaces; - let com_control = com_battlegrounds === total_battlegrounds && com_spaces > dem_spaces; - - return { - dem_spaces: dem_spaces, - com_spaces: com_spaces, - dem_battlegrounds: dem_battlegrounds, - com_battlegrounds: com_battlegrounds, - dem_domination: dem_domination, - com_domination: com_domination, - dem_control: dem_control, - com_control: com_control, - dem_leaders: dem_leaders, - com_leaders: com_leaders - }; -} - -function battlegrounds(country) { - let battlegrounds = 0; - if (country === "Hungary") { - battlegrounds = 4 - } else if (country === "Bulgaria") { - battlegrounds = 5 - } else { - battlegrounds = 6 - } - return battlegrounds; -} - -function take_power(country) { - - log(`Democrat takes power in ${game.pwr_struggle_in}`) - game.revolutions[find_country_index(country)] = true - game.times_held[find_country_index(country)] = 1 - -} - -function retain_power(country){ - game.times_held[find_country_index(country)]++ - let vp_gain = get_value(country)*game.times_held[find_country_index(country)] - log(`Chooses to retain power`) - log(`-${vp_gain} VP`) - game.vp -= vp_gain -} - -function score_country(country) { - log_h3(`Scoring: ${country}`) - -//Get scoring values - let value_presence = get_value(country) - let value_domination = value_presence*2 - let value_control - if (country !== "Hungary") { - value_control = value_presence*3 - } else { - value_control = 4 - } -//Log for scoring - - let dem_vp = 0 - let com_vp = 0 - //Check for presence - let presence = check_presence(country) -// console.log('presence: ', presence) - - //If one side has domination or control - if (presence.dem_control || presence.dem_domination) { - log(`Democrat:`) - if (presence.dem_control) { - log(`Control: +${value_control} VP`) - dem_vp += value_control - } - else { - log(`Domination: +${value_domination} VP`) - dem_vp += value_domination - } - log(`Battlegrounds: +${presence.dem_battlegrounds} VP`) - dem_vp += presence.dem_battlegrounds - log(`Total: +${dem_vp} VP`) - - log_gap('Communist:') - if (presence.com_spaces > 0) { - log(`Presence: -${value_presence} VP`) - com_vp -= value_presence - if (presence.com_battlegrounds >0) { - log(`Battlegrounds: -${presence.com_battlegrounds} VP`) - com_vp -= presence.com_battlegrounds - } - log(`Total: ${com_vp} VP`) - } else { - log('No presence: 0 VP') - } - - } - else if (presence.com_control || presence.com_domination) { - log('Communist:') - if (presence.com_control) { - log(`Control: -${value_control} VP`) - com_vp -= value_control - } - else { - log(`Domination: -${value_domination} VP`) - com_vp -= value_domination - } - log(`Battlegrounds: -${presence.com_battlegrounds} VP`) - com_vp -= presence.com_battlegrounds - log(`Total: ${com_vp} VP`) - - log_gap('Democrat:') - if (presence.dem_spaces > 0) { - log(`Presence: +${value_presence} VP`) - dem_vp += value_presence - if (presence.dem_battlegrounds > 0) { - log(`Battlegrounds: +${presence.dem_battlegrounds} VP`) - dem_vp += presence.dem_battlegrounds - } - log (`Total: +${dem_vp} VP`) - } else { - log('No presence: 0 VP') - } - - } - - //Otherwise, presence and battlegrounds - else { - log("No domination or control") - log_gap(`Communist:`) - if (presence.com_spaces > 0) { - log(`Presence: -${value_presence} VP`) - com_vp -= value_presence - if (presence.com_battlegrounds > 0) { - log(`Battlegrounds: -${presence.com_battlegrounds} VP`) - com_vp -= presence.com_battlegrounds - } else { - log('No battlegrounds') - } - log(`Total: ${com_vp} VP`) - } else { - log('No presence: 0 VP') - } - log_gap('Democrat:') - if (presence.dem_spaces > 0) { - log(`Presence: +${value_presence} VP`) - dem_vp += value_presence - if (presence.dem_battlegrounds > 0) { - log(`Battlegrounds: +${presence.dem_battlegrounds} VP`) - dem_vp += presence.dem_battlegrounds - } else { - log('No battlegrounds') - } - log(`Total: +${dem_vp} VP`) - } else { - log('No presence: 0 VP') - } - } - - -//Calculate change VP - /*let dem_vp = 0 - if (presence.dem_spaces > 0) {dem_vp += value_presence} - if (presence.dem_domination) {dem_vp += value_presence} - if (presence.dem_control && country !== "Hungary") { - dem_vp += value_control - } - else if (presence.dem_control && country === "Hungary") {dem_vp += 2} - dem_vp += presence.dem_battlegrounds - - let com_vp = 0 - if (presence.com_spaces > 0) {com_vp += value_presence} - if (presence.com_domination) {com_vp += value_presence} - if (presence.com_control && country !== "Hungary") {com_vp += value_presence} - else if (presence.com_control && country === "Hungary") {com_vp += 2} - com_vp += presence.com_battlegrounds */ - let change_vp = dem_vp + com_vp - game.vp += change_vp - if (change_vp > 0 ) { - log_gap(`Final change VP: +${change_vp} VP`) - } else { - log_gap(`Final change VP: ${change_vp} VP`) - } -} - -function get_value(country) { - let value - if (country === "East_Germany" || country === "Poland") {value = 3} - else if (country === "Czechoslovakia" || country === "Romania") {value = 2} - else value = 1 - return value -} - -function get_end_infl_prompt() { - view.prompt = `${clean_name(cards[this_card()].name)}. Add SPs: done.` - if (!game.vm_infl_to_do) { - gen_action('end_round') - } else { - gen_action('done') - } -} - -function permanently_remove(card) { - //console.log('permanently removing card:', card) - if (game.strategy_removed.includes(card)) {return} - //log_msg_gap(`C${cards[card].number} permanently removed`) - remove_from_discard(card) - - card_index = game.table_cards.indexOf(card) - if (card_index !== -1) { - //console.log('sub 2 called') - game.table_cards.splice(card_index, 1) - } - game.strategy_removed.push(card) - //console.log('game.strategy_removed', game.strategy_removed) -} - -function check_vp() { - if (game.vp >= 20) { - goto_game_over(DEM, `${DEM} won an Automatic Victory!`) - //console.log('after goto_game_over, game.state', game.state) - return true - } else if(game.vp <= -20) { - goto_game_over(COM, `${COM} won an Automatic Victory!`) - return true - } - return false -} - -function game_over() { - if (game.vp >= 20 || game.vp <= -20) { - return true - } else { return false} -} - -function goto_game_over(result, victory) { - game.state = "game_over" - game.active = "None" - game.result = result - game.victory = victory - log_h1("Game Over") - log(game.victory) - //console.log('game over, game.state', game.state) - return - -} - -function reset_austria_hungary_border_reopened() { - //game.austria_hungary_border_reopened_checked = false - game.austria_hungary_border_reopened_tracker = false -} - -function end_stasi_choose_card() { - game.round_player = COM - game.round ++ - log_h2(`Action Round ${game.round}`) - next_player() - game.valid_spaces = [] - if (game.persistent_events.includes(5)) { - log_h3('C5') - game.state = 'general_strike' - } else { - game.state = 'choose_card' - } -} - -function check_reformer() { - if (game.dem_tst_position !== game.com_tst_position) { - if (!game.playable_cards.includes(67)) { - game.playable_cards.push(67) - } - } else { - game.playable_cards = game.playable_cards.filter(n => n !== 67) - } - -} - -function count_scoring_cards() { - let scoring_check - if (game.active === DEM) { - scoring_check = game.democrat_hand.filter(card => scoring_cards.includes(card)).length - } else { - scoring_check = game.communist_hand.filter(card => scoring_cards.includes(card)).length - } - return scoring_check -} - -function select_card(card){ - game.played_card = card - game.temp = 0 - let find_card - if (game.active === COM) { - find_card = game.communist_hand.indexOf(card) - game.communist_hand.splice(find_card, 1) - } else { - find_card = game.democrat_hand.indexOf(card) - game.democrat_hand.splice(find_card, 1) - } - game.available_ops = get_card_ops(card) - - //Check Ligachev - if (game.active === DEM && game.persistent_events.includes(99) && card !== 14) { - log('-3 VP from C99') - game.vp -= 3 - if (check_vp()) { - return - } - game.persistent_events = game.persistent_events.filter(n => n !== 99) - } - game.state = 'play_card' - //console.log('game.state', game.state) -} - -function find_event(card) { - return variable_events.indexOf(card) -} - -function is_auto_resolve(card) { - - let ceausecu_events = [10, 41, 101, 107] - - if (card === 97) { - if (!game.persistent_events.includes(54)) { - return true - } - } - else if (ceausecu_events.includes(card) && game.persistent_events.includes(97)) { - return true - } - else if (card === 87 && !game.persistent_events.includes(86)) { - return true - } - else if (auto_resolve_events.includes(card)) { - return true - } else { - return false - } -} - -function get_events(card){ - if (event_is_playable(card)) { - if (cards[card].side === 'D') { - if (game.active === DEM) {gen_action('event')} - if (game.active === COM) {gen_action('opp_event')} - } - else if (cards[card].side === 'C') { - if (game.active === COM) {gen_action('event')} - if (game.active === DEM) {gen_action('opp_event')} - } - else { - gen_action('event') - } - } -} - -function event_is_playable(card) { -// console.log('game.stasi_card', game.stasi_card, 'card', card) - //Reformer never playable here - if (card === 67) { - return false - } - //Check for Common European Hmme under Stasi - else if (game.stasi_card === 21 && card === 21 && game.active === DEM) { - return false - } - //Check for The Chinese Solution - else if (game.com_tst_position === 8 && card === 96) { - return true - } - //Then check normally - else if (cards[card].playable) { - return true - } else if (game.playable_cards.includes(card)) { - return true - } else { - return false - } -} - -function get_card_ops(card) { - let ops = 0 - - if (card) { - ops = cards[card].ops - } - if (game.persistent_events.includes(25) && game.active === COM) { - if(game.state === 'choose_card' || game.state === 'stasi_play_card') { - log('+1 op from C25') - } - ops ++ - } - if (game.persistent_events.includes(50) && game.active === DEM) { - if(game.state === 'choose_card' || game.state === 'stasi_play_card' || game.state === 'vm_laszlo_tokes') { - log('+1 op from C50') - } - ops ++ - } - - if ((game.active === DEM && game.dem_tst_position >= 2 && game.com_tst_position <= 1 && cards[card].ops === 1) || (game.active === COM && game.com_tst_position >=2 && game.dem_tst_position <= 1 && cards[card].ops === 1)) { - if(game.state === 'choose_card' || game.state === 'stasi_play_card') { - log('+1 op from Tiananmen Square Track') - } - ops ++ - } - - if ((game.active === DEM && game.prudence && game.prudence.DEM !== 0)) { - if(game.state === 'choose_card' || game.state === 'stasi_play_card' || game.state === 'vm_laszlo_tokes') { - if (ops > 2) { - log(`${pluralize(game.prudence.DEM,'op')} from C8`) - } else { - if (ops > 1) { - log(`-1 op from C8`) - } - } - } - ops += game.prudence.DEM - - if (ops < 1) { - ops = 1 - } - } - - if (game.active === COM && game.prudence && game.prudence.COM < 0) { - if(game.state === 'choose_card') { - if (ops > 2) { - log(`${pluralize(game.prudence.COM,'op')} from C8`) - } else if (ops > 1) { - log(`-1 op from C8`) - } - } - ops += game.prudence.COM - if (ops < 1) { - ops = 1 - } - } return ops -} - -function get_tst_6_ops() { - let ops = 0 - - if (game.persistent_events.includes(25) && game.active === COM) { - log('+1 op from C25') - ops ++ - } - if (game.persistent_events.includes(50) && game.active === DEM) { - log('+1 op from C50') - ops ++ - } - - if ((game.active === DEM && game.prudence && game.prudence.DEM !== 0)) { - if (ops > 0) { - log(`${pluralize(game.prudence.DEM,'op')} from C8`) - } else { - log(`-1 op from C8`) - } - - ops += game.prudence.DEM - - if (ops < -1) { - ops = -1 - } - } - - if (game.active === COM && game.prudence && game.prudence.COM < 0) { - - if (ops > 0) { - log(`${pluralize(game.prudence.COM,'op')} from C8`) - } else { - log(`-1 op from C8`) - } - - ops += game.prudence.COM - if (ops < -1) { - ops = -1 - } - } - return ops -} - -function finish_the_wall() { - if (game.the_wall_must_go['dem_wins'] === 2) { - game.persistent_events.push(86) - log('+3 VP') - game.vp += 3 - if (check_vp()) { - return - } - for (let i = 1; i < spaces.length; i++) { - let space = spaces[i] - if (space.country === 'East_Germany' && game.comInfl[i] > 0){ - game.valid_spaces.push(space.space_id) - } - } - if (!game.vm_infl_to_do) { - if (game.round_player === DEM) { - game.return = COM - } else { - game.return = DEM - } - } - if (game.active === DEM) {next_player()} - vm_next () - } else { - permanently_remove(86) - delete game.the_wall_must_go - vm_return() - } -} - - -// =========== MOVING THROUGH TURNS ============ - -function end_round() { -// console.log('end round, game.persistent_events.includes(13)', game.persistent_events.includes(13)) - //Check if the game is over! - if (game.state === 'game_over') { - // console.log('in end') - return} - - //Check if the card has been removed or played to table, and if a card has been not been played. If not, discard. - if (!game.strategy_removed.includes(game.played_card) && !game.table_cards.includes(game.played_card) && game.played_card > 0) { - game.strategy_discard.push(game.played_card) - } - - //Reset - game.played_card = 0 - game.temp = 0 - game.vm_event = 0 - game.phase = 0 - game.remove_opponent_infl = false - game.is_pwr_struggle = false - game.vm_infl_to_do = false /*Can get rid of this and use game.return_state? */ - game.vm_event_to_do = false - game.vm_active_country = '' - game.return_state = '' - game.discard = false - game.return = '' - game.valid_cards = [] - game.valid_spaces = [] - check_common_european_home() - //game.playable_cards[find_event(21)] = true - reset_austria_hungary_border_reopened() /*This should be redundant! */ - - - // Check for duplicate card entries - let card_check - if (game.samizdat_card > 0) { - card_check = [...game.strategy_deck, ...game.strategy_discard, ...game.strategy_removed, ...game.table_cards, ...game.communist_hand, ... game.democrat_hand, game.samizdat_card]; - } else { - card_check = [...game.strategy_deck, ...game.strategy_discard, ...game.strategy_removed, ...game.table_cards, ...game.communist_hand, ... game.democrat_hand]; - } - - function check_duplicates(array) { - return new Set(array).size !== array.length; - } - - function find_duplicates(array) { - const duplicates = array.filter((item, index) => array.indexOf(item) !== index); - return [...new Set(duplicates)]; - } - - //console.log('game.strategy_deck', game.strategy_deck, 'game.strategy_discard', game.strategy_discard, 'game.strategy_removed', game.strategy_removed, 'game.table_cards', game.table_cards, 'game.communist_hand', game.communist_hand, 'game.democrat_hand', game.democrat_hand) - - if (check_duplicates(card_check)) { - console.log('card check', card_check) - const duplicates = find_duplicates(card_check) - console.log('game.strategy_deck', game.strategy_deck, 'game.strategy_discard', game.strategy_discard, 'game.strategy_removed', game.strategy_removed, 'game.table_cards', game.table_cards, 'game.communist_hand', game.communist_hand, 'game.democrat_hand', game.democrat_hand) - throw new Error(`Duplicate cards detected: ${duplicates.join(', ')}`) - } - //console.log('cards in game', card_check.length) - card_check = card_check.sort((a, b) => a - b) - //console.log('cards in game', card_check) - if (game.turn <= 3) { - if (card_check.length !== 40) { - throw new Error(`Wrong number of cards: ${card_check.length}`) - } - } else if (game.turn <=7) { - if (card_check.length !== 81) { - throw new Error(`Wrong number of cards: ${card_check.length}`) - } - } else if (card_check.length !== 110) { - throw new Error(`Wrong number of cards: ${card_check.length}`) - } - - - - //console.log('game.dem_tst_position ', game.dem_tst_position , 'game.com_tst_position ', game.com_tst_position ) - //Check if the Reformer is playable - check_reformer() - - // Check if last round and if so resolve end turn events - if (game.round_player === DEM && game.round === 7) { - if(game.persistent_events.includes(15)) { - if (game.active !== COM) { - next_player() - } - game.state = 'honecker' - return - } - else if (game.dem_tst_position >= 6 && game.com_tst_position <= 5) { - log_h2('Tiananmen Square Track Award') - if (game.active !== DEM) { - next_player() - } - game.return = game.active - clear_undo() - game.return_state = 'end_turn_4_5_4' - goto_vm(206) - return - } else if (game.com_tst_position >= 6 && game.dem_tst_position <= 5) { - log_h2('Tiananmen Square Track Award') - if (game.active !== COM) { - next_player() - } - game.return = game.active - clear_undo() - game.return_state = 'end_turn_4_5_4' - goto_vm(206) - return - } - else { - clear_undo() - game.state = 'end_turn_4_5_4' - return - } - } - - // Resolve end action round - //Stasi check - if(game.round_player === COM && game.persistent_events.includes(13)) { - //If in Honecker, turn ends - if (game.round === 8) { - clear_undo() - game.state = 'end_turn_4_5_4' - return - } - //Otherwise go to Stasi - game.round_player = DEM - if (game.active !== DEM) { - next_player() - } else { - log_h3('Democratic Action Round') - - } - if (game.democrat_hand.includes(game.stasi_card)) { - log_h3('C13') - game.state = 'stasi_play_card' - } else { - game.stasi_card = 0 - game.state = 'choose_card' - } - return - } - //Check if in extra Action Round - else if (game.round_player === COM && game.round === 8) { - clear_undo() - game.state = 'end_turn_4_5_4' - return - } - //Normal round end - else if (game.round_player===COM) { - game.round_player = DEM - if (game.active !== DEM) { - next_player() - } else { - log_h3('Democratic Action Round') - } - game.state = 'choose_card' - return - } - if (game.round_player === DEM) { - // console.log('checking stasi', game.persistent_events.includes(13)) - if(game.persistent_events.includes(13)) { - // console.log('stasi sub function') - if (game.active !== DEM) { - next_player() - } - log_h3('C13') - game.state = 'stasi_end_round' - return - } else if(game.round_player === DEM && game.persistent_events.includes(5)){ - game.state = 'general_strike' - game.round ++ - log_h2(`Action Round ${game.round}`) - game.round_player = COM - if (game.active !== COM) { - next_player() - } - log_h3('C5') - return - } else { - game.state = 'choose_card' - game.round_player = COM - game.round ++ - log_h2(`Action Round ${game.round}`) - if (game.active !== COM) { - next_player() - } - } - } - //game.state = 'choose_card' Does this do anything any more? -} - -/* -function end_turn(){ - /*End Turn sequence - TST support check - Verify held cards - New Year's Eve Party - Advance Turn Marker - -// CHECK FOR OPTIONAL SUPPORT CHECK - if (game.dem_tst_position >=6 && game.com_tst_position <= 5) { - if (game.active !== DEM) { - next_player_() - } - game.state = 'tst_support_check' - } - if (game.com_tst_position >=6 && game.dem_tst_position <= 5) { - if (game.active !== COM) { - next_player_() - } - game.state = 'tst_support_check' - } - - -//CHECK HELD CARDS - -} */ - -function new_turn() { - clear_undo() - game.turn ++ - game.round = 1 - game.valid_spaces=[] - game.active = COM - game.round_player = COM - game.dem_tst_attempted_this_turn = 0 - game.com_tst_attempted_this_turn = 0 - if (game.tst_7) {game.tst_7 = false} - if (game.tst_8) {game.tst_8 = false} - - //Remove events that only last one turn - game.persistent_events = game.persistent_events.filter(n => n !== 25) /*Perestroika*/ - game.persistent_events = game.persistent_events.filter(n => n !== 50) /*Sinatra Doctrine*/ - game.persistent_events = game.persistent_events.filter(n => n !== 13) /*Stasi*/ - game.persistent_events = game.persistent_events.filter(n => n !== 15) /*Honecker*/ - delete game.prudence - delete game.stasi_card - - //Austria Hungary Border Reopened - if (game.persistent_events.includes(58)) { - game.persistent_events = game.persistent_events.filter(n => n !== 58) - delete game.austria_hungary_border_reopened_tracker - log(`C58 no longer in effect`) - //permanently_remove(58) - } - //Elena - if (game.persistent_events.includes(101)) { - game.persistent_events = game.persistent_events.filter(n => n !== 101) - log(`C101 no longer in effect`) - //permanently_remove(101) - } - //GrenzTruppen - if (game.persistent_events.includes(59)) { - game.persistent_events = game.persistent_events.filter(n => n !== 59) - log(`C59 no longer in effect`) - //permanently_remove(59) - } - //Foreign Currency Debt Burden - if (game.persistent_events.includes(49)) { - game.persistent_events = game.persistent_events.filter(n => n !== 49) - delete game.foreign_currency_debt_burden - log(`C49 no longer in effect`) - //permanently_remove(49) - } - //FRG Embassies - if (game.persistent_events.includes(74)) { - game.persistent_events = game.persistent_events.filter(n => n !== 74) - log(`C74 no longer in effect`) - discard_from_table(74) - permanently_remove(74) - } - //Genscher - if (game.persistent_events.includes(63)) { - game.persistent_events = game.persistent_events.filter(n => n !== 63) - log(`C63 no longer in effect`) - discard_from_table(63) - permanently_remove(63) - } - //Stand Fast - if (game.persistent_events.includes(100)) { - game.persistent_events = game.persistent_events.filter(n => n !== 100) - delete game.stand_fast - log(`C100 no longer in effect`) - //permanently_remove(100) - } - - if (game.samizdat_card > 0 ) { - game.democrat_hand.push(game.samizdat_card) - delete game.samizdat_card - } - - log_h1("Turn " + game.turn) - - if (game.turn === 4) { - add_midyear() - } - if (game.turn === 8) { - add_lateyear() - } - if (game.turn > 1) { - if (game.persistent_events.includes(65)) { - game.com_hand_limit = 7 - log('Communist draws 7 cards due to C65') - //permanently_remove(65) - game.persistent_events = game.persistent_events.filter(n => n !== 65) - } - //console.log('deck', game.strategy_deck) - //console.log('game.com_hand_limit', game.com_hand_limit, 'communist hand before draw', game.communist_hand) - draw_cards(game.strategy_deck, game.democrat_hand, game.communist_hand, game.dem_hand_limit, game.com_hand_limit) - game.com_hand_limit = 8 - //console.log('communist hand after draw', game.communist_hand) - - } - - //Check if TST effects need to be resolved - if (game.dem_tst_position >=5 && game.com_tst_position <= 4) { - log_h2('Tiananmen Square Track award') - if(game.active !== DEM) { next_player() } - for (let card of game.democrat_hand) { - if (scoring_cards.includes(card)) continue - game.valid_cards.push(card) - } - game.state = 'tst_goddess' /* Goddess only name of Democrat bonus, not Communist*/ - return - } - else if (game.com_tst_position >=5 && game.dem_tst_position <= 4) { - log_h2('Tiananmen Square Track award') - if(game.active !== COM) { next_player() } - for (let card of game.communist_hand) { - if (scoring_cards.includes(card)) continue - game.valid_cards.push(card) - } - game.state = 'tst_goddess' - } else { - log_h2("Action Round " + game.round) - log_side() - //console.log('in start new AR call, game.active', game.active) - if (game.persistent_events.includes(5)) { - log_h3('C5') - game.state = 'general_strike' - } - else { - game.state = 'choose_card' - } - } -} - -function next_player() { - clear_undo() - //console.log('next player called') - if (game.active === DEM) - game.active = COM - else - game.active = DEM - - log_side() -} - -function change_player() { - clear_undo() - //console.log('next player called') - if (game.active === DEM) - game.active = COM - else - game.active = DEM -} - -function find_space_index(name_unique) { - return spaces.findIndex(space => space && space.name_unique === name_unique) -} - -function find_country_index(country) { - return countries.indexOf(country) -} - -function draw_deck(deck) { - return deck.filter(card => card && card.period === 1).map(card => card.number) -} - -function draw_cards(deck, democrat_hand, communist_hand, dem_hand_limit, com_hand_limit) { - //console.log('game.valid_cards at start of draw cards: ', game.valid_cards) - let turn = 'communist'; // Start with the communist player - //console.log('game.strategy_deck', game.strategy_deck) - //console.log('deck', deck, 'democrat_hand', democrat_hand, 'communist_hand', communist_hand, 'dem_hand_limit', dem_hand_limit, 'com_hand_limit', com_hand_limit) - while (democrat_hand.length < dem_hand_limit || communist_hand.length < com_hand_limit) { - //console.log('deck.length: ', deck.length) - //console.log('discard.length', game.strategy_discard ) - if (deck.length === 0) { - log_h3('--- Reshuffle ---') - - deck.push(...game.strategy_discard) - game.strategy_discard = [] - } - - else if (turn === 'communist' && communist_hand.length < com_hand_limit) { - communist_hand.push(draw_card(deck)); - //console.log('game.valid_cards after communist draw: ', JSON.stringify(game.valid_cards)); - turn = 'democrat'; - } else if(turn === 'communist' && communist_hand.length === com_hand_limit) { - turn = 'democrat'; - } - else if (turn === 'democrat' && democrat_hand.length < dem_hand_limit) { - democrat_hand.push(draw_card(deck)); - //console.log('democrat_hand: ', democrat_hand) - - //console.log('game.valid_cards after democrat draw: ', JSON.stringify(game.valid_cards)); - turn = 'communist'; - } - else if (turn === 'democrat' && democrat_hand.length === dem_hand_limit) { - turn = 'communist'; - } - } - - clear_undo() -} - -function draw_card(deck) { - //console.log('draw card called with:', deck) - //console.log('game.strategy_deck before', game.strategy_deck) - if (deck.length === 0) { - log_h3('--- Reshuffle ---') - - deck.push(...game.strategy_discard) - game.strategy_discard = [] - } - const randomIndex = Math.floor(Math.random() * deck.length) - //console.log('card chosen:', randomIndex) - //console.log('game.strategy_deck after', game.strategy_deck) - return deck.splice(randomIndex, 1)[0]; -} - -function discard(card) { - //console.log('in discard(card)') - let find_card - if (!game.is_pwr_struggle) { - - if (game.active === COM) { - find_card = game.communist_hand.indexOf(card) - game.communist_hand.splice(find_card, 1) - } else { - find_card = game.democrat_hand.indexOf(card) - game.democrat_hand.splice(find_card, 1) - } - if (!game.strategy_discard.includes(card)) { - game.strategy_discard.push(card) - log(`Discarded C${cards[card].number}`) - } - } else if (game.is_pwr_struggle) { - if (game.active === COM) { - find_card = game.com_pwr_hand.indexOf(card); - game.com_pwr_hand.splice(find_card, 1); - } else { - find_card = game.dem_pwr_hand.indexOf(card); - game.dem_pwr_hand.splice(find_card, 1); - } - - game.power_struggle_discard.push(card) - //log(`Discarded P${power_cards[card].number}`) - } -} -function silent_discard(card) { - //console.log('in discard(card)') - let find_card - if (!game.is_pwr_struggle) { - if (game.active === COM) { - find_card = game.communist_hand.indexOf(card) - game.communist_hand.splice(find_card, 1) - } else { - find_card = game.democrat_hand.indexOf(card) - game.democrat_hand.splice(find_card, 1) - } - if (!game.strategy_discard.includes(card)) { - game.strategy_discard.push(card) - } - } else if (game.is_pwr_struggle) { - if (game.active === COM) { - find_card = game.com_pwr_hand.indexOf(card); - game.com_pwr_hand.splice(find_card, 1); - } else { - find_card = game.dem_pwr_hand.indexOf(card); - game.dem_pwr_hand.splice(find_card, 1); - } - game.power_struggle_discard.push(card) - } -} - -function remove_from_discard(card) { - let card_index = game.strategy_discard.indexOf(card) - if (card_index !== -1) { - game.strategy_discard.splice(card_index, 1) - } -} - -function discard_card(hand) { - //let find_card - let card = Math.floor(Math.random()*hand.length) - let discarded_card = hand.splice(card, 1)[0] - if (game.is_pwr_struggle) { - if (numberless_cards.includes(discarded_card)) { - log_gap(`Discarded: P${discarded_card}`) - } else { - log_gap(`Discarded: P${discarded_card} V${power_cards[discarded_card].value}`) - } - } else { - log(`Discarded C${cards[discarded_card].number}`) - game.strategy_discard.push(discarded_card) - } - return discarded_card -} - -function discard_from_table(card) { - find_card = game.table_cards.indexOf(card) - game.table_cards.splice(find_card, 1) - game.strategy_discard.push(card) -} - - -function add_midyear() { - const mid_year = cards.filter(card => card && card.period === 2).map(card => card.number); - game.strategy_deck.push(...mid_year); - log_h3('Mid-year cards added to draw deck') -} - - -function add_lateyear() { - const late_year = cards.filter(card => card && card.period === 3).map(card => card.number) - game.strategy_deck.push(...late_year) - log_h3('Late-year cards added to draw deck') -} - -function reset_power() { - game.power_struggle_deck = [] - game.power_struggle_discard = [] - game.dem_pwr_hand = [] - game.com_pwr_hand = [] - game.phase = 1 - game.raised_stakes_round = 0 - game.raised_stakes = 0 - game.played_power_card = 0 - game.tactics_fails = '' - game.view_opp_hand = false - - if (game.persistent_events.includes(72)){ - permanently_remove(72) - game.table_cards = game.table_cards.filter(card => card !== 72) - game.persistent_events = game.persistent_events.filter(n => n !== 72) - } - if (game.persistent_events.includes(62)) { - permanently_remove(62) - game.table_cards = game.table_cards.filter(card => card !== 62) - game.persistent_events = game.persistent_events.filter(n => n !== 62) - } - if (game.persistent_events.includes(54) && game.pwr_struggle_in === 'Romania'){ - permanently_remove(54) - //game.table_cards = game.table_cards.filter(card => card !== 54) - - } - if (game.pwr_struggle_in === 'Romania' && game.persistent_events.includes(70)){ - //permanently_remove(70) - //game.table_cards = game.table_cards.filter(card => card !== 70) - game.persistent_events = game.persistent_events.filter(n => n !== 70) - } -} - -function check_control_change(space_id) { - - // Check if the Tyrant is Gone has been fulfilled - - if (game.the_tyrant_is_gone > 0 && check_dem_control(game.the_tyrant_is_gone)) { - log('+2 VP from C97') - game.vp += 2 - if (check_vp()) { - return - } - game.persistent_events = game.persistent_events.filter(n => n !== 97) - delete game.the_tyrant_is_gone - } -} - -function check_systematization() { - // Check for Systematization - may not use this space - if (game.systematization > 0) { - game.valid_spaces = game.valid_spaces.filter(n => n !== game.systematization) - } -} - -function check_common_european_home() { - if (!game.playable_cards.includes(21)) { - game.playable_cards.push(21) - } -} - -function this_card() { - return game.vm_event > 0 ? game.vm_event : game.played_card -} -/* -function get_ops(card) { - let ops = cards[card].ops - if (game.active === COM) { - //Check TST op bonus - if (ops === 1 && game.com_tst_position >=2 && game.dem_tst_position <=1) { - ops++ - } - //Events that influence ops - if (game.persistent_events.includes(25)) { - ops++ - } - if (game.prudence.COM && game.prudence.COM <0) { - ops += game.prudence.COM - } - - } else { - //Check TST op bonus - if (ops === 1 && game.dem_tst_position >=2 && game.com_tst_position <=1) { - ops++ - } - //Events that influence ops - if (game.persistent_events.includes(50)) { - ops++ - } - if (game.prudence.DEM && game.prudence.DEM <0) { - ops += game.prudence.DEM - } - } - //Ops can never be less than one - if (ops <1) { ops = 1 } - return ops -} - */ - -const pluralize = (count, noun, suffix = 's') => - `${count} ${noun}${Math.abs(count) !== 1 ? suffix : ''}` - -function clean_name(str) { - if (str && str.slice(-1) === '*') { - return str.slice(0, -1) - } else { - return str; - } -} - -function country_name(country) { - return country.replace(/_/g, ' ') -} - -// ======== LOG FUNCTIONS ============= - -function log(msg) { - game.log.push(msg) -} - -function log_br() { - if (game.log.length > 0 && game.log[game.log.length - 1] !== "") - game.log.push("") -} - -function logi(msg) { - game.log.push(">" + msg) -} - -function log_h1(msg) { - log_br() - log(".h1 " + msg) - log_br() -} - -function log_h2(msg) { - log_br() - log(".h2 " + msg) - log_br() -} - -function log_h3(msg) { - log_br() - log(".h3 " + msg) -} - -function log_gap(msg) { - log_br() - game.log.push(msg) -} - -function log_msg_gap(msg) { - game.log.push(msg) - log_br() -} - - -function log_side() { - log_br() - if (game.active === DEM) - log(".h2d " + game.active) - else - log(".h2c " + game.active) - log_br() -} - -function log_sep() { - log(".hr") -} - -function log_action(msg) { - log_br() - log(msg) -} - -// ============= SUMMARY FUNCTIONS ============= - -function push_summary() { - if (game.summary) - throw "TOO MANY SUMMARIES" - game.summary = [] -} - -function log_summary(msg) { - - if (msg.startsWith('Added') || msg.startsWith('Removed')) { - for (let item of game.summary) { - if (item[1] === msg) { - item[0]++ - return - } - } - } - game.summary.push([1, msg]) -} - -function pop_summary() { - if (game.summary.length > 0) { - for (let [n, msg] of game.summary) { - if (n > 1) { - log(msg.replace("£ SP", `${n} SPs`)); - } else { - log(msg.replace("£ SP", `${n} SP`)); - } - } - } - game.summary = [] -} - -function log_summary_place(p) { - let from = piece_space(p) - if (from !== AVAILABLE) - log_summary("% " + piece_name(p) + " from S" + from) - else - log_summary("% " + piece_name(p)) -} - -function log_summary_move_to_from(p, to) { - log_summary("% " + piece_name(p) + " to S" + to + " from S" + piece_space(p)) -} - -function log_summary_remove(p) { - log_summary("Removed % " + piece_name(p)) -} - -function log_summary_activated(p) { - log_summary("Activated % " + piece_faction_name(p)) -} - -// ============ UNDO FUNCTIONS ================== - -function clear_undo() { - if (game.undo.length > 0) - game.undo = [] -} - -function push_undo() { - let copy = {} - for (let k in game) { - let v = game[k] - if (k === "undo") - continue - else if (k === "log") - v = v.length - else if (typeof v === "object" && v !== null) - v = object_copy(v) - copy[k] = v - } - game.undo.push(copy) -} - -function pop_undo() { - let save_log = game.log - let save_undo = game.undo - game = save_undo.pop() - save_log.length = game.log - game.log = save_log - game.undo = save_undo -} - -// Fast deep copy for objects without cycles -function object_copy(original) { - if (Array.isArray(original)) { - let n = original.length - let copy = new Array(n) - for (let i = 0; i < n; ++i) { - let v = original[i] - if (typeof v === "object" && v !== null) - copy[i] = object_copy(v) - else - copy[i] = v - } - return copy - } else { - let copy = {} - for (let i in original) { - let v = original[i] - if (typeof v === "object" && v !== null) - copy[i] = object_copy(v) - else - copy[i] = v - } - return copy - } -} - - -/* =================== VM FUNCTIONS ========================== */ - -function goto_vm(proc) { - let old_vm = game.vm; - - game.state = "vm"; - game.vm = { - prompt: 0, - fp: proc, - ip: 0, - }; - - if (old_vm) { - game.vm.return_vm = old_vm; - } - - vm_exec(); -} - -function vm_exec() { - vm_inst(0)(); -} - -function vm_inst(a) { - //console.log('game.vm.fp', game.vm.fp, 'game.vm.ip', game.vm.ip) - return CODE[game.vm.fp][game.vm.ip][a] -} - -function vm_next() { - game.vm.ip++; - //console.log('vm_next called, game.vm.ip', game.vm.ip) - vm_exec(); -} - -function vm_operand(a) { - let x = CODE[game.vm.fp][game.vm.ip][a] - if (a > 0 && typeof x === "function") - return x() - return x -} - -function vm_assert_argcount(n) { - const argcount = CODE[game.vm.fp][game.vm.ip].length - 1 - if (argcount !== n) - throw Error(`ASSERT Invalid number of arguments on event ${game.vm.fp}: ${argcount} instead of ${n}`) -} - -function vm_log() { - log(vm_operand(1)); - vm_next(); -} - -function vm_if() { - //console.log('game.temp', game.temp) -// console.log('vm_operand(1)', vm_operand(1)) - if (!vm_operand(1)) { - let balance = 1 - while (balance > 0) { - ++game.vm.ip - switch (vm_operand(0)) { - case vm_if: - ++balance - break - case vm_endif: - --balance - break - case vm_else: - if (balance === 1) - --balance - break - } - if (game.vm.ip < 0 || game.vm.ip > CODE[game.vm.fp].length) - throw "ERROR" - } - } - vm_next() -} - -function vm_else() { - vm_goto(vm_endif, vm_if, 1, 1) -} - -function vm_endif() { - vm_next() -} - -function vm_goto_step(step) { - // console.log('vm_goto_step called, target:', step) - //console.log('game.vm.ip', game.vp.ip) - for (let i = game.vm.ip; i < CODE[game.vm.fp].length; i++) { - //console.log('i', i) - //console.log('step', CODE[game.vm.fp][i][0]) - if (CODE[game.vm.fp][i][0] === step) { - game.vm.ip = i; - vm_exec(); - return; - } - } - - console.log("ERROR: Target operation not found in the current procedure."); -} - - -function vm_goto(op, nop, dir, step) { - //console.log('vm_inst(0)', vm_inst(0), op, nop) -// console.log('vm_inst(0)', vm_inst(1), op, nop) - let balance = 1 - while (balance > 0) { - game.vm.ip += dir - if (vm_inst(0) === op) - --balance - if (vm_inst(0) === nop) - ++balance - if (game.vm.ip < 0 || game.vm.ip > CODE[game.vm.fp].length) - throw "ERROR" - } - game.vm.ip += step - vm_exec() -} - -function event_prompt(str) { - //console.log('event_prompt called with', str) - if (typeof str === "undefined") - str = CODE[game.vm.fp][game.vm.prompt][1] - if (typeof str === "function") - str = str() - //console.log('str:', str) - if (!str) { - str = "" - } - return str -} - -function vm_prompt() { - if (game.vm.prompt) - game.vm._prompt = game.vm.prompt - game.vm.prompt = game.vm.ip - vm_next() -} - -function pop_vm_prompt() { - if (game.vm._prompt) { - game.vm.prompt = game.vm._prompt - delete game.vm._prompt - } else { - game.vm.prompt = 0 - } -} - -function vm_return() { - - //console.log('in vm_return, game.vm_infl_to_do', game.vm_infl_to_do, 'return state', game.return_state) - - //Remove temporary vm variables - delete game.support_check_modifier - delete game.vm_max_infl - delete game.vm_influence_added - delete game.communist_hand_red - - game.vm_event = 0 /*Reset to 0 now that event has been completed. Hopefully this doesn't cause issues! */ - if (game.persistent_events.includes(58)) { - reset_austria_hungary_border_reopened() - } - - //Check if end event state is needed - if (game.is_pwr_struggle || game.state === 'vm_tst_6' || game.return_state === 'tiananmen_square_attempt_done') { - vm_end_event() - } - //Check if auto-resolve opponent event - else if (is_auto_resolve(game.played_card) && ((cards[game.played_card].side === 'C' && game.active === DEM) || (cards[game.played_card].side === 'D' && game.active === COM) )) { - vm_end_event() - } - else { - - game.state = 'vm_end_event' - /*if (!game.vm_infl_to_do) { - /*if ((game.active === DEM && game.round_player !==DEM) || (game.active === COM && game.round_player !== COM)) { - game.state = 'vm_end_event' - } else { - game.state = 'vm_end_event' - //end_round() - //} - } else { - console.log('vm_infl_to_do true') - vm_end_event() - }*/ - } -} - -function vm_end_event() { - //game.view_opp_hand = false -// console.log('in vm_return, game.return:', game.return, 'game.return_state:', game.return_state, 'game.vm_infl_to_do', game.vm_infl_to_do, 'game.vm_event_to_do', game.vm_event_to_do) - /*if (!game.vm_infl_to_do && !game.vm_event_to_do) { - if (game.round_player !== game.active) { - change_player() - log_h2('End of Action Round') - } - end_round() - return - } /*Go direct to end round if card fully resolved */ - if (game.return !== game.active) { - next_player()} - if (game.return_state === 'power_struggle') { - do_valid_cards() - } - if (game.return_state && game.return_state !== '') { - game.state = game.return_state - //console.log( 'game.state', game.state) - } - else if (game.vm_infl_to_do) { - game.state = 'resolve_opponent_event'} /*Can use game.return state for this? */ - //else {game.state = "play_card"} - else{ - end_round()} -} - -/* ================== VM ACTIONS =========================== */ - -function vm_opp_hand_false() { - game.view_opp_hand = false - vm_next() -} - -function vm_valid_spaces() { - let space_1 = vm_operand(1) - let space_2 = vm_operand(2) - let space_3 = vm_operand(3) - let space_4 = vm_operand(4) - let space_5 = vm_operand(5) - let space_6 = vm_operand(6) - game.valid_spaces = [space_1, space_2, space_3, space_4, space_5, space_6] - game.valid_spaces = game.valid_spaces.filter( n => n ) - - // Check for Systematization - may not use this space - check_systematization() - - vm_next() -} - -function vm_valid_spaces_opponent () { - let valid_spaces = [] - for (let i = 1; i < spaces.length; i++) { - let space = spaces[i] - - if (game.active === DEM) { - let infl = game.comInfl[i] - if (infl > 0) { - valid_spaces.push(space.space_id) - } - } else { - infl = game.demInfl[i] - if (infl > 0) { - valid_spaces.push(space.space_id) - } - } - } - game.valid_spaces = valid_spaces -// console.log('game.valid_spaces', game.valid_spaces) - vm_next() -} - -function vm_valid_spaces_socio () { - let valid_spaces = [] - for (let i = 1; i < spaces.length; i++) { - let space = spaces[i] - - if (space.socio === vm_operand(1)) { - valid_spaces.push(space.space_id) - } - } - game.valid_spaces = valid_spaces - - // Check for Systematization - may not use this space - if (game.systematization && game.systematization > 0) { - game.valid_spaces = game.valid_spaces.filter(n => n !== game.systematization) - } - vm_next() -} - -function vm_valid_spaces_opponent_socio () { - let valid_spaces = [] - for (let i = 1; i < spaces.length; i++) { - let space = spaces[i] - - if (game.active === DEM) { - let infl = game.comInfl[i] - if (infl > 0 && space.socio === vm_operand(1)) { - valid_spaces.push(space.space_id) - } - } else { - let infl = game.demInfl[i] - if (infl > 0 && space.socio === vm_operand(1)) { - valid_spaces.push(space.space_id) - } - } - } - game.valid_spaces = valid_spaces - // Check for Systematization - may not use this space - if (game.systematization && game.systematization > 0) { - game.valid_spaces = game.valid_spaces.filter(n => n !== game.systematization) - } - vm_next() -} - -function vm_valid_spaces_country () { - let country - if (vm_operand(1)) {country = vm_operand(1)} - else {country = game.vm_active_country} - for (let space of spaces) { - if (!space) continue - if (space.country === country) { - game.valid_spaces.push(space.space_id); - } - } - // Check for Systematization - may not use this space - if (game.systematization && game.systematization > 0) { - game.valid_spaces = game.valid_spaces.filter(n => n !== game.systematization) - } - vm_next() -} - -function vm_valid_spaces_sc () { - valid_spaces_sc() - vm_next() -} - -function vm_valid_spaces_country_opp () { - let country = '' - - if (vm_operand(1)) { - country = vm_operand(1) } - else { - country = game.vm_active_country - } - for (let space of spaces) { - if (!space) continue - if (game.active === DEM) { - if (space.country === country && game.comInfl[space.space_id] >0) { - game.valid_spaces.push(space.space_id); - } - } else { - if (space.country === country && game.demInfl[space.space_id]>0) { - game.valid_spaces.push(space.space_id); - } - } - } - vm_next() -} - -function vm_valid_spaces_country_sc () { - let valid_spaces = [] - let country = '' - //console.log('in vm_valid_spaces_country_sc') - if (vm_operand(1)) { - country = vm_operand(1) } - else { - country = game.vm_active_country - } - for (let space of spaces) { - if (!space) continue - if (game.active === DEM) { - if (space.country === country && game.comInfl[space.space_id] >0) { - valid_spaces.push(space.space_id); - } - } else { - if (space.country === country && game.demInfl[space.space_id] >0) { - //Check Solidarity Legalised - if (game.persistent_events.includes(2) && space.space_id === 14) {continue} - - //Check Civic Forum - if (game.persistent_events.includes(90) && space.space_id === 30) {continue} - - //Check We are the People - if (game.persistent_events.includes(48) && space.space_id === 9) {continue} - valid_spaces.push(space.space_id); - - //Check Foreign Currency Debt Burden - if (game.persistent_events.includes(49) && space.country === game.foreign_currency_debt_burden) {continue} - } - } - } - game.valid_spaces = valid_spaces - - //Check for Foreign Currency Debt Burden - /*if (game.persistent_events.includes(49) && game.active === COM) { - game.valid_spaces = game.valid_spaces.filter(n => spaces[n].country !== game.foreign_currency_debt_burden) - }*/ - vm_next() -} - -function vm_valid_spaces_country_socio_2() { - for (let space of spaces) { - if (!space) continue - if (space.space_id === game.systematization) continue - if ((space.country === vm_operand(1) && space.socio === vm_operand(2)) || (space.country === vm_operand(1) && space.socio === vm_operand(3))) { - game.valid_spaces.push(space.space_id); - } - } - vm_next() -} - -function vm_valid_spaces_region_socio() { - let valid_spaces = [] - for (let space of spaces) { - if (!space) continue - if (space.space_id === game.systematization) continue - if (space.region === vm_operand(1) && space.socio === vm_operand(2)) { - valid_spaces.push(space.space_id); - } - } - game.valid_spaces = valid_spaces - vm_next() -} - -function vm_valid_spaces_region_opp() { - let valid_spaces = [] - for (let space of spaces) { - if (!space) continue - let s = space.space_id - if ((game.active === DEM && space.region === vm_operand(1) && game.comInfl[s] > 0 ) || (game.active === COM && space.region === vm_operand(1) && game.demInfl[s] > 0 )) { - valid_spaces.push(space.space_id); - } - } - game.valid_spaces = valid_spaces - vm_next() -} - -function vm_valid_spaces_solidarity_legalised() { - let valid_spaces = [] - for (let i = 1; i < spaces.length; i++) { - let space = spaces[i] - let uncontrolled = (!check_control(i) && !check_opp_control(i)) - if ((space.country === 'Poland' && uncontrolled && space.socio === 3) || (space.country === 'Poland' && uncontrolled && space.socio === 4)) { - valid_spaces.push(space.space_id); - } - } - game.valid_spaces = valid_spaces - vm_next() -} - -function vm_active_country () { - game.valid_spaces = game.valid_spaces.filter(space_id => { - let space = spaces.find(s => s && s.space_id === space_id); - return space && space.country === game.vm_active_country; - }); - vm_next() -} - -function vm_take_control_prep() { - game.vm_available_ops = vm_operand(1) - game.state = 'vm_take_control' -} - -function vm_take_control(space) { - if (game.active === DEM) { - let current_infl = game.demInfl[space] - let opponent_infl = game.comInfl[space] - let stability = spaces[space].stability - - if ((current_infl - opponent_infl) < stability) { - game.demInfl[space] += stability - current_infl + opponent_infl - //game.pieces[space].demCtrl = 1 - //game.pieces[space].comCtrl = 0 - } - } else if (game.active === COM) { - let current_infl = game.comInfl[space] - let opponent_infl = game.demInfl[space] - let stability = spaces[space].stability - - if ((current_infl - opponent_infl) < stability) { - game.comInfl[space] += stability - current_infl + opponent_infl - //game.pieces[space].comCtrl = 1 - //game.pieces[space].demCtrl = 0 - } - } - game.valid_spaces = game.valid_spaces.filter(id => id !== space) - log(`Took control of %${space}`) -} - - -function vm_do_add_infl(space) { - push_undo() - //console.log('in vm_do_add_infl, space', space, 'ops', game.vm_available_ops, 'ahbr tracker', game.austria_hungary_border_reopened_tracker, 'ahbr in events', game.persistent_events.includes(58)) - - //log(`Added 1 influence in %${space}.`) - - log_summary(`Added £ SP in %${space}.`) - - //If AHBR - check AHBR condition - if (game.persistent_events.includes(58)) { - if (spaces[space].country !== 'East_Germany'){ - game.austria_hungary_border_reopened_tracker = false - } - } - - // Check Genscher - if (game.persistent_events.includes(63) && game.active === DEM && spaces[space].country === 'East_Germany') { - game.vm_available_ops-- - log_summary(`(-1 op due to C63)`) - } else if (check_opp_control(space)) { - game.vm_available_ops -= 2 - //Check if Austria Hungary Border Reopened was used to place last SP in a controlled space in East Germany. If so, game.vm_available_op will be negative - if (game.vm_available_ops < 0) { - log_summary(`(Used +1 op from C58)`) - } - } else { - game.vm_available_ops-- - } - - // Update influence values - if (game.active === COM) { - game.comInfl[space]++ - } else { - game.demInfl[space]++ - } - - // Check whether spaces are controlled - check_control_change(space) - - // Check Austria Hungary Border Reopened is true and condition has been met - if (game.vm_available_ops === 0 && game.active === DEM && game.persistent_events.includes(58) && game.austria_hungary_border_reopened_tracker) { - //console.log('in award extra op') - game.vm_available_ops ++ - log('+1 Op from C58') - game.austria_hungary_border_reopened_tracker = false - game.valid_spaces = game.valid_spaces.filter(n => spaces[n].country === 'East_Germany') - } - - // If only 1 IP remaining, may not place in opponent controlled spaces - - // Check for Genscher & Austria Hungary Border Reopened - - if (game.vm_available_ops === 1) { - - if (game.active === DEM) { - //Check Genscher and AHBR - if (game.persistent_events.includes(63) || (game.persistent_events.includes(58) && game.austria_hungary_border_reopened_tracker)) { - game.valid_spaces = game.valid_spaces.filter(n => !(check_com_control(n) && spaces[n].country !== 'East_Germany')) - } else { - game.valid_spaces = game.valid_spaces.filter(n => !check_com_control(n)) - } - } else { - game.valid_spaces = game.valid_spaces.filter(n => !check_dem_control(n)) - } - } - - //Clear valid spaces if no IP remaining. - if (game.vm_available_ops <= 0 ) { - game.valid_spaces = [] - } -} - -function vm_do_add_infl_free(space) { - push_undo() - //log(`Added 1 influence in %${space}.`) - - log_summary(`Added £ SP in %${space}.`) - - // Update influence values - if (game.active === COM) { - game.comInfl[space]++ - } else { - game.demInfl[space]++ - } - game.vm_available_ops-- - // Check whether spaces are controlled - check_control_change(space) - - - //console.log('game pieces:', game.pieces[space]) -} - -function vm_add_infl() { - if (vm_operand(1)) {game.vm_available_ops = vm_operand(1)} - game.state = 'vm_add_infl' -} - -function vm_add_infl_free() { - if (vm_operand(1)) {game.vm_available_ops = vm_operand(1)} - game.state = 'vm_add_infl_free' -} - -function vm_add_x_infl() { - game.vm_available_ops = vm_operand(1) - game.state = 'vm_add_x_infl' -} - -function vm_do_add_x_infl(space) { - push_undo() - log(`Added ${game.vm_available_ops} SPs in %${space}.`) - - - if (game.active === COM) { - game.comInfl[space] += game.vm_available_ops - } else { - game.demInfl[space] += game.vm_available_ops - } - check_control_change(space) - game.vm_available_ops = 0 - game.valid_spaces = [] -} - -function vm_add_limited_infl() { - game.vm_available_ops = vm_operand(1) - game.vm_max_infl = vm_operand(2) - game.state = 'vm_add_limited_infl' -} - -function vm_do_add_limited_infl(space, max_infl) { - push_undo() - //log(`Added 1 influence in %${space}.`) - - log_summary(`Added £ SP in %${space}.`) - game.vm_available_ops -- - - if (!game.vm_influence_added) { - game.vm_influence_added = {}; - } - - if (!game.vm_influence_added[space]) { - game.vm_influence_added[space] = 0; - } - - if (game.active === COM) { - game.comInfl[space] ++ - } else { - game.demInfl[space] ++ - } - - game.vm_influence_added[space] ++ - - //console.log('valid_spaces before update', game.valid_spaces) - //console.log('influence added:', game.vm_influence_added[space], 'max infl', max_infl) - if (game.vm_influence_added[space] === max_infl) { - game.valid_spaces = game.valid_spaces.filter(id => id !== space); - } - check_control_change(space) - if (game.vm_available_ops === 0) {game.valid_spaces = [] } -} - -function vm_remove_infl() { - game.vm_available_ops = vm_operand(1) - game.state = 'vm_remove_infl' -} - -function vm_remove_opp_infl() { - game.vm_available_ops = vm_operand(1) - game.remove_opponent_infl = true - if (game.is_pwr_struggle) { - game.state = 'vm_scare_tactics' - } else { - game.state = 'vm_remove_infl' - } -} - -function vm_remove_x_opp_infl() { - game.vm_available_ops = vm_operand(1) - game.remove_opponent_infl = true - game.state = 'vm_remove_x_infl' -} - -function vm_do_remove_infl(space) { - push_undo() - //log(`Removed 1 influence from %${space}.`) - log_summary(`Removed £ SP from %${space}.`) - - if (!game.vm_influence_added) { - game.vm_influence_added = {}; - } - - if (!game.vm_influence_added[space]) { - game.vm_influence_added[space] = 0; - } - if (game.remove_opponent_infl === true) { - if (game.active === COM) { - game.demInfl[space]-- - if (game.demInfl[space] === 0) { - game.valid_spaces = game.valid_spaces.filter(id => id !== space); - } - } else { - game.comInfl[space]-- - if (game.comInfl[space] === 0) { - game.valid_spaces = game.valid_spaces.filter(id => id !== space); - } - } - - - } else { - if (game.active === COM) { - game.comInfl[space]-- - if (game.comInfl[space] === 0) { - game.valid_spaces = game.valid_spaces.filter(id => id !== space); - } - } else { - game.demInfl[space]-- - if (game.demInfl[space] === 0) { - game.valid_spaces = game.valid_spaces.filter(id => id !== space); - } - } - } - check_control_change(space) - game.vm_influence_added[space]++ - game.vm_available_ops-- - if (game.vm_available_ops===0) {game.valid_spaces = []} -} - -function vm_do_remove_x_infl(space) { - push_undo() - - if (game.remove_opponent_infl) { - if (game.active === COM) { - if (game.demInfl[space] >= game.vm_available_ops) { - game.demInfl[space] -= game.vm_available_ops - } else { - game.vm_available_ops = game.demInfl[space] - game.demInfl[space] -= game.vm_available_ops - } - } else { - if (game.comInfl[space] >= game.vm_available_ops) { - game.comInfl[space] -= game.vm_available_ops - } else { - game.vm_available_ops = game.comInfl[space] - game.comInfl[space] -= game.vm_available_ops - } - } - } else { - if (game.active === COM) { - if (game.comInfl[space] >= game.vm_available_ops) { - game.comInfl[space] -= game.vm_available_ops - } else { - game.vm_available_ops = game.comInfl[space] - game.comInfl[space] -= game.vm_available_ops - } - } else { - if (game.demInfl[space] >= game.vm_available_ops) { - game.demInfl[space] -= game.vm_available_ops - } else { - game.vm_available_ops = game.demInfl[space] - game.demInfl[space] -= game.vm_available_ops - } - } - } - - log(`Removed ${game.vm_available_ops} SPs from %${space}`) - check_control_change(space) - - game.vm_available_ops = 0 - game.valid_spaces = [] -} - -function vm_remove_limited_opp_infl() { - game.vm_available_ops = vm_operand(1) - game.vm_max_infl = vm_operand(2) - game.remove_opponent_infl = true - game.state = 'vm_remove_limited_infl' -} - -function vm_do_remove_limited_infl(space, max_infl) { - push_undo() - log(`Removed SP from %${space}.`) - game.vm_available_ops -- - - - if (!game.vm_influence_added) { - game.vm_influence_added = {}; - } - - if (!game.vm_influence_added[space]) { - game.vm_influence_added[space] = 0; - } - - if (game.active === COM) { - game.demInfl[space] -- - if (game.demInfl[space] === 0) { - game.valid_spaces = game.valid_spaces.filter(id => id !== space) - } - } else { - game.comInfl[space] -- - if (game.comInfl[space] === 0) { - game.valid_spaces = game.valid_spaces.filter(id => id !== space) - } - } - - game.vm_influence_added[space] ++ - - if (game.vm_influence_added[space] === max_infl) { - game.valid_spaces = game.valid_spaces.filter(id => id !== space); - } - - check_control_change(space) - if (game.vm_available_ops === 0) {game.valid_spaces = []} -} - -function vm_remove_all_infl() { - game.vm_available_ops = vm_operand(1) - game.state = 'vm_remove_all_infl' -} - -function vm_do_remove_all_infl(space) { - push_undo() - log(`Removed all SP from %${space}.`) - - if (game.remove_opponent_infl === true) { - if (game.active === COM) { - game.demInfl[space] = 0 - } else { - game.comInfl[space] = 0 - } - check_control_change(space) - - } else { - if (game.active === COM) { - game.comInfl[space] = 0 - } else { - game.demInfl[space] = 0 - } - check_control_change(space) - } - game.vm_available_ops -- - game.valid_spaces = game.valid_spaces.filter(id => id !== space) -} - -function vm_replace_all_infl(space_id) { - if (game.active === DEM) { - game.demInfl[space_id] += game.comInfl[space_id] - game.comInfl[space_id] = 0 - } else { - game.comInfl[space_id] += game.demInfl[space_id] - game.demInfl[space_id] = 0 - } - check_control_change(space_id) -} - -function vm_1_support_check() { - game.vm_available_ops = 1 - game.state = 'vm_1_support_check_prep' -} - -function vm_support_check() { - game.vm_available_ops = vm_operand(1) - game.state = 'vm_support_check_prep' -} - -function vm_support_check_modified() { - game.vm_available_ops = vm_operand(1) - game.support_check_modifier = vm_operand(2) - game.state = 'vm_support_check_prep' -} - -function vm_switch_infl(id){ - push_undo() - - game.demInfl[id] -= game.vm_available_ops - game.comInfl[id] += game.vm_available_ops - log(`Replaced ${pluralize(game.vm_available_ops,'SP')} in %${id}`) - game.vm_available_ops = 0 - check_control_change(id) -} - -/* ===================== EVENT SPECIFIC FUNCTIONS ========== */ - -function vm_40th_anniversary_celebration() { - if (game.vp < 0 ) {game.vm_available_ops = 4} - else {game.vm_available_ops = 2} - vm_next() -} - -function vm_40th_anniversary_celebration_vp() { - game.vp -- - log('-1VP') - if (check_vp()) { - return - } - vm_next() -} - -function vm_adamec() { - game.state = 'vm_adamec' -} - -function vm_army_backs_revolution() { - game.persistent_events = game.persistent_events.filter(n => n !== 70) - game.playable_cards = game.playable_cards.filter(n => n !== 70) - /*if (game.table_cards.includes(70)) { - permanently_remove(70) - }*/ - vm_next() -} - -function vm_austria_hungary_border_reopened() { - game.persistent_events.push(58) - permanently_remove(58) - game.austria_hungary_border_reopened_tracker = false - //game.table_cards.push(58) - //remove_from_discard(58) - vm_next() -} - -function vm_betrayal() { - if (game.demInfl[58] > 0 ) { game.valid_spaces.push(58) } - if (game.demInfl[65] >0 ) { game.valid_spaces.push(65) } - game.vm_available_ops = Math.max(game.demInfl[58], game.demInfl[65]) - game.state = 'vm_switch_infl' -} - -function vm_breakaway_baltic_republics() { - log('+5 VP') - game.vp += 5 - game.stability++ - if (check_vp()) { - return - } - game.playable_cards.push(109) - game.playable_cards = game.playable_cards.filter(n => n !== 14) - if (!check_dem_control(56) && game.systematization !== 56) {game.valid_spaces.push(56)} - if (!check_dem_control(70)) {game.valid_spaces.push(70)} - vm_next() -} - -function vm_brought_in_for_questioning() { - if (game.active === COM) { - game.active = DEM - } - //game.return = game.active - game.phase = 0 - game.state = 'vm_brought_in_for_questioning' -} - -function vm_bulgarian_turks_expelled(){ - game.remove_opponent_infl = true - game.vp -= 2 - log('-2VP') - if (check_vp()) { - return - } - if (game.demInfl[70] > 0) {game.valid_spaces = [70]} - vm_next() -} - -function vm_ceausescu() { - let adj_cluj = false - if (game.demInfl[50] > 0 ) {adj_cluj = true} - if (game.demInfl[54] > 0 ) {adj_cluj = true} - if (game.demInfl[58] > 0 ) {adj_cluj = true} - if (game.demInfl[61] > 0 ) {adj_cluj = true} - - if (adj_cluj && game.comInfl[61]>0) { - game.valid_spaces = [61] - game.vm_available_ops = 1 - //next_player() - game.remove_opponent_infl = false - game.state = 'vm_remove_infl' - } - else {vm_next()} -} - -function vm_central_committee_reshuffle() { - game.state = 'vm_central_committee_reshuffle' -} - -function vm_civic_forum() { - log('+1 VP') - game.vp++ - if (check_vp()) { - return - } - game.persistent_events.push(90) - if (check_dem_control(31)) { - vm_next() - } else { - permanently_remove(90) - vm_return() - } -} - -function vm_common_european_home() { - let valid_cards = []; - for (let c of cards) { - //if (c === null) {continue} - if (game.active === DEM) { - if (c && c.side === 'C') { - valid_cards.push(c.number) - } - } else { - if (c && c.side === 'D') { - valid_cards.push(c.number) - } - } - } - game.valid_cards = valid_cards - game.state = 'vm_common_european_home_choose' -} - -function vm_dash_for_the_west() { - game.valid_cards = [] - for (let c of game.strategy_discard) { - if (cards[c].side === 'D' && cards[c].remove === 1 && (cards[c].playable || game.playable_cards.includes(c))) { - game.valid_cards.push(c) - } - } - game.state = 'vm_dash_for_the_west' -} - -function vm_deutsche_marks() { - let max_value = 1; - for (let c of game.democrat_hand) { - if (cards[c].ops > max_value) { - max_value = cards[c].ops - } - } - let valid_cards = []; - for (let c of game.democrat_hand) { - if (cards[c].ops === max_value) { - valid_cards.push(c); - } - } - game.valid_cards = valid_cards - game.state = 'vm_deutsche_marks_prep' -} - -function vm_domino_theory() { - game.discard = true - for (let card of game.strategy_discard) { - if (scoring_cards.includes(card)) {game.valid_cards.push(card) } - } - game.phase = 0 - game.state = 'vm_play_event_from_discard' -} - -function vm_eco_glasnost() { - game.persistent_events.push(39) - vm_next() -} - -function vm_elena(){ - game.persistent_events.push(101) - vm_next() -} - -function vm_eliminate(space_id) { - log(`Eliminated %${space_id}`) - const adjacent_spaces = spaces[space_id].adjacent.filter(Number.isInteger); - - //console.log('adjacency before: Iasi', game.pieces[53].adjacent, 'Ploesti:', game.pieces[59].adjacent, 'Bucharesti:', game.pieces[61].adjacent) - - // Eliminate the democrat influence and move the communist influence to Bucuresti - if (space_id === 61) { - game.demInfl[space_id] = 0 - game.comInfl[space_id] = 0 - } else { - game.demInfl[space_id] = 0 - game.comInfl[61] += game.comInfl[space_id] - if (game.comInfl[space_id] > 0 ) { - log(`${pluralize(game.comInfl[space_id],'Communist SP')} relocated to %61`) - } - game.comInfl[space_id] = 0 - } - //Update control in the eliminated space and in Bucuresti - check_control_change(space_id) - check_control_change(61) - -} - -function get_adjusted_adjacency(space_id) { - let adjacent_spaces = spaces[space_id].adjacent; - if (adjacent_spaces.includes(game.systematization)) { - //console.log('in get adjusted adjacency, systemization',game.systematization) - //console.log('adjacent_spaces', adjacent_spaces) - } - if (game.systematization !== 0) { - //console.log('in systematization check') - let eliminated_space_id = game.systematization; - - return adjacent_spaces.map(adj_space_id => { - if (adj_space_id === eliminated_space_id) { - // Replace the eliminated space with its adjacencies - //console.log('in map check, return', spaces[eliminated_space_id].adjacent) - return spaces[eliminated_space_id].adjacent; - } - //console.log('2nd check, return', adj_space_id) - return adj_space_id; - }).flat(); // Flatten in case the eliminated space has multiple adjacencies - } - //console.log('final adjacent spaces', adjacent_spaces) - return adjacent_spaces; -} - -function vm_exit_visas() { - game.state = 'vm_exit_visas' -} - -function vm_foreign_currency_debt_burden() { - log('+1VP') - game.vp++ - if (check_vp()) { - return - } - //game.table_cards.push(49) - //remove_from_discard(49) - game.persistent_events.push(49) - game.state = 'vm_foreign_currency_debt_burden' -} - -function vm_foreign_television() { - for (let i = 1 ; i < spaces.length; i++) { - if (i === 12) {continue} /*Does not apply to Dresden*/ - if (game.comInfl[i] > 0 ) { - game.valid_spaces.push(i) - } - } - vm_next() -} -function vm_frg_embassies() { - game.persistent_events.push(74) - game.table_cards.push(74) - remove_from_discard(74) - log('C74 in effect') - vm_next() -} - -function vm_general_strike() { - game.persistent_events.push(5) - game.table_cards.push(5) - remove_from_discard(5) - log('C5 in effect') - vm_next() -} - -function vm_genscher() { - game.persistent_events.push(63) - game.table_cards.push(63) - remove_from_discard(63) - log(`C63 in effect`) - vm_next() -} - -function vm_goodbye_lenin() { - game.view_opp_hand = true - game.communist_hand_red = [] - // Select Red cards to show - for (let card of game.communist_hand) { - if (cards[card].red) { - game.communist_hand_red.push(card) - } - } - //Check if these cards are playabl - for (let card of game.communist_hand_red) { - if (cards[card].playable || game.playable_cards.includes(card)) { - game.valid_cards.push(card) - } - } - game.state = 'vm_goodbye_lenin' -} - -function vm_government_resigns() { - for (let i = 1; i < spaces.length; i++) { - let space = spaces[i] - if (space.socio === 1 && game.comInfl[i] > 0 && !check_control(i)) { - game.valid_spaces.push(i) - } - } - game.remove_opponent_infl = true - vm_next() -} - -function vm_grenztruppen() { - game.persistent_events.push(59) - permanently_remove(59) - //game.table_cards.push(59) - //remove_from_discard(59) - vm_next() -} - -function vm_heal_our_bleeding_wounds() { - let change_vp = 0 - if (game.turn <= 3) {change_vp = -3 } - else if (game.turn <= 7) {change_vp = -1} - else change_vp = 3 - if (change_vp >0) { - log(`+${change_vp} VP`) - } else { - log(`-${change_vp} VP`) - } - game.vp += change_vp - if (check_vp()) { - return - } - vm_next() -} - -function vm_helsinki_final_act() { - game.persistent_events.push(26) - vm_next() -} - -function vm_honecker() { - game.persistent_events.push(15) - game.valid_cards = [] - for (let c of game.strategy_discard) { - if (scoring_cards.includes(c)) { - continue} - else { - game.valid_cards.push(c) - } - } - game.discard = true - game.state = 'vm_honecker' -} - -function vm_inflationary_currency() { - game.state = 'vm_inflationary_currency' -} - -function vm_inflationary_currency_discard() { - // This function starts with the player who is playing Inflationary Currency for the Event - // Switch player and check the hand of their opponent to see if the have cards with ops > 3 to discard - next_player() - if (game.active === COM) { - for (let card of game.communist_hand){ - if (get_card_ops(card) >= 3) { - game.valid_cards.push(card) - } - } - } else { - for (let card of game.democrat_hand){ - if (get_card_ops(card) >= 3) { - game.valid_cards.push(card) - } - } - } - game.state = 'vm_inflationary_currency_discard' -} - -function vm_kiss_of_death() { - game.state = 'vm_kiss_of_death' -} - -function vm_klaus_and_komarek() { - if (game.comInfl[29] > 0 ) {game.valid_spaces = [29]} - vm_next() -} - -function vm_kohl_proposes_reunification() { - log('+2 VP') - game.vp += 2 - if (check_vp()) { - return - } - if (game.persistent_events.includes(86)) { - game.vm_event = 87 - game.state = 'vm_common_european_home_play' - } else { - permanently_remove(87) - vm_return() - } - -} - -function vm_kremlin_coup() { - log('-3 VP') - game.vp -= 3 - game.stability ++ - if (check_vp()) { - return - } - game.support_check_modifier = 1 - //countries = ['Poland', 'Hungary', 'East_Germany', 'Bulgaria', 'Czechoslovakia', 'Romania'] - //revolutions: {'East_Germany': false, 'Poland': false, 'Czechoslovakia': false, 'Hungary': false, 'Romania': false, 'Bulgaria': false} - game.temp = [] - countries.forEach(country => { - if (!game.revolutions[find_country_index(country)]) { - game.temp.push(country) - } - }) - game.state = 'vm_kremlin_coup_choose_country' -} - -function vm_laszlo_tokes() { - game.persistent_events.push(73) - game.playable_cards.push(107) - game.state = 'vm_laszlo_tokes' -} - -function vm_legacy_of_martial_law() { - game.vm_available_ops = 1 - game.state = 'vm_switch_infl' -} - -function vm_legacy_of_1968() { - for (let i = 1; i < spaces.length; i++) { - let space = spaces[i] - if ((!check_com_control(i) && space.country === 'Czechoslovakia')) { - game.valid_spaces.push(space.space_id); - } - } - vm_next() -} - -function vm_li_peng() { - game.persistent_events.push(53) - //game.table_cards.push(53) - remove_from_discard(53) - vm_next() -} - -function vm_ligachev() { - game.persistent_events.push(99) - vm_next() -} - -function vm_malta_summit() { - game.state = 'vm_malta_summit' -} - -function vm_massacre_in_timisoara() { - game.persistent_events = game.persistent_events.filter(n => n !== 73) - vm_next() -} - -function vm_modrow() { - game.playable_cards.push(15) - game.state = 'vm_modrow' -} - -function vm_nagy_reburied(){ - if (game.comInfl[43] > 0) { - game.valid_spaces.push(43) - } - vm_next() -} - -function vm_national_salvation_front() { - game.persistent_events.push(102) - game.table_cards.push(102) - remove_from_discard(102) - vm_next() -} - -function vm_nepotism() { - game.state = 'vm_nepotism' -} - -function vm_new_years_eve_party() { - game.state = 'vm_new_years_eve_party' -} - -function vm_nomenklatura() { - game.state = 'vm_nomenklatura' -} - -function vm_normalisation() { - if (game.demInfl[27] >0) {game.valid_spaces.push(27)} - if (game.demInfl[29] > 0) {game.valid_spaces.push(29)} - game.remove_opponent_infl = true - vm_next() -} - -function vm_peasant_parties_revolt() { - game.persistent_events.push(72) - log_msg_gap('C72 in effect') - game.table_cards.push(72) - remove_from_discard(72) - vm_next() -} - -function vm_perestroika() { - game.persistent_events.push(25) - log_msg_gap('C25 in effect') - vm_next() -} - -function vm_poszgay() { - let valid_spaces = [] - for (let space of spaces) { - if (space && space.country === 'Hungary' && !check_dem_control(space.space_id)) { - valid_spaces.push(space.space_id); - } - } - game.valid_spaces = valid_spaces - vm_next() -} - -function vm_power_struggle() { - //console.log('in vm_power_struggle. game.vm_event', game.vm_event, 'game.active', game.active, 'game.view_opp_hand', game.view_opp_hand) - game.is_pwr_struggle = true - - /* TO DELETE? - //Check if Power Struggle is because of an event - */ - - if (game.vm_event > 0) { - game.pwr_struggle_in = countries[scoring_cards.indexOf(game.vm_event)] - log_h2(`C${game.vm_event}`) - } -/* - //Otherwise set Power Struggle country normally - else { - console.log('vm_power_struggle, country set normally') - game.pwr_struggle_in = countries[scoring_cards.indexOf(game.played_card)] - log_h2(`C${game.played_card}`) - }*/ - - - //Check for Securitate - if (game.pwr_struggle_in === 'Romania' && game.persistent_events.includes(70)) { - log('C70: Democrat reveals Power Struggle cards') - game.view_opp_hand = true - } - log_h2('Deal Cards') - game.state = 'draw_power_cards' -} - -function vm_presidential_visit() { - game.persistent_events.push(65) - //game.table_cards.push(65) - //remove_from_discard(65) - log_msg_gap('C65 in effect') - vm_next() -} - -function vm_prudence() { - if (!game.prudence) { - game.prudence = {DEM: 0, COM: 0} - } - if (game.active === DEM) { - game.prudence.COM -- - log(`${game.prudence.COM} to Communist ops this turn`) - } else { - game.prudence.DEM -- - log(`${game.prudence.DEM} to Democrat ops this turn`)} - vm_next() -} - -function vm_public_against_violence() { - game.valid_spaces = [] - if (game.comInfl[34] > 0 ) {game.valid_spaces.push(34)} - vm_next() -} - -function vm_reformer_rehabilitated () { - permanently_remove(67) - game.discard = true - for (let card of game.strategy_discard) { - if (!event_is_playable(card)) continue - if (card === game.played_card) continue - if (game.table_cards.includes(card)) continue - if (scoring_cards.includes(card)) continue - - game.valid_cards.push(card) - } - game.state = 'vm_play_event_from_discard' -} - -function vm_roundtable_talks() { - game.persistent_events.push(17) - game.table_cards.push(17) - remove_from_discard(17) - log_msg_gap('C17 in effect') - vm_next() -} - -function vm_sajudis_check() { - if (!check_dem_control(56)) { - game.valid_spaces.push(56) - } - if (!check_dem_control(70)) { - game.valid_spaces.push(70) - } - vm_next() -} - -function vm_sajudis() { - game.playable_cards.push(81) - game.stability++ - log('+1 VP') - game.vp++ - if (check_vp()) { - return - } - vm_next() -} - -function vm_samizdat() { - game.state = 'vm_samizdat' -} - -function vm_securitate() { - game.persistent_events.push(70) - permanently_remove(70) - //game.table_cards.push(70) - vm_next() -} - -function vm_shock_therapy() { - game.state = 'vm_shock_therapy' -} - -function vm_social_democratic_platform_adopted() { - game.state = 'vm_social_democratic_platform_adopted' -} - -function vm_solidarity_legalised() { - log_msg_gap(`C2 in effect`) - game.playable_cards.push(3) - game.persistent_events.push(2) - vm_next() -} - -function vm_st_nicholas_church () { - game.persistent_events.push(24) - game.playable_cards.push(61) - vm_next() -} - -function vm_stasi() { - log_msg_gap('C13 in effect') - game.persistent_events.push(13) - vm_next() -} - -function vm_stand_fast() { - game.persistent_events.push(100) - if (game.active === DEM) { - game.stand_fast = DEM - } else {game.stand_fast = COM} - //game.table_cards.push(100) - vm_next() -} - -function vm_systematization() { - game.state = 'vm_systematization' -} - -function vm_tank_column() { - if (game.active === DEM) { - game.dem_tst_position++ - game.dem_tst_attempted = 0 - } else { - game.com_tst_position++ - game.com_tst_attempted = 0 - } - vm_next() -} - -function vm_tear_gas () { - game.persistent_events.push(30) - game.table_cards.push(30) - remove_from_discard(30) - log_msg_gap('C30 in effect') - vm_next() -} - -function vm_the_baltic_way() { - game.playable_cards.push(84) - game.stability++ - if (!check_dem_control(56) && game.systematization !== 56) {game.valid_spaces.push(56)} - if (!check_dem_control(70) && game.systematization !== 70) {game.valid_spaces.push(70)} - log('+3 VP') - game.vp += 3 - if (check_vp()) { - return - } - vm_next() -} - -function vm_the_chinese_solution() { - game.state = 'vm_the_chinese_solution' -} - -function vm_the_crowd_turns_against_ceausescu() { - game.table_cards.push(54) - remove_from_discard(54) - game.playable_cards.push(97) - vm_next() -} - -function vm_the_monday_demonstrations() { - if (!check_dem_control(6)) {game.valid_spaces.push(6)} - if (!check_dem_control(9)) {game.valid_spaces.push(9)} - vm_next() -} - -function vm_the_sinatra_doctrine() { - game.persistent_events.push(50) - log_msg_gap('C50 in effect') - vm_next() -} - -function vm_the_third_way() { - log('-2VP') - vm_next() -} - -function vm_the_tyrant_is_gone() { - game.valid_spaces = [] - for (let i = 1; i < spaces.length; i++) { - let space = spaces[i] - if (game.demInfl[i] === 0 && space.country === 'Romania') { - if (space.space_id === game.systematization) {continue} - game.valid_spaces.push(space.space_id) - } - } - game.state = 'vm_the_tyrant_is_gone' -} - - -function vm_the_tyrant_is_gone_prep() { - game.table_cards.push(97) - remove_from_discard(97) - vm_next() -} - -function vm_tyrant_block() { - logi(`Has no effect after C97`) - vm_next() - //game.state = 'vm_tyrant_block' -} - -function vm_the_wall () { - game.persistent_events.push(9) - //game.strategy_removed.push(9) - //game.table_cards.push(9) - log_msg_gap('C9 in effect') - vm_next() -} - -function vm_the_wall_must_go() { - game.the_wall_must_go = {} - game.the_wall_must_go['dem_wins'] = 0 - game.the_wall_must_go['com_wins'] = 0 - game.the_wall_must_go['dem_roll'] = 0 - game.the_wall_must_go['com_roll'] = 0 - game.state = 'vm_the_wall_must_go' -} - -function vm_warsaw_pact_summit() { - game.warsaw_pact_summit = true /*What does this do? */ - game.state = 'vm_warsaw_pact_summit' -} - -function vm_we_are_the_people() { - if (game.demInfl[6] > 0) {game.valid_spaces = [6]} - game.persistent_events.push(48) - if (!game.vm_influence_added) { - game.vm_influence_added = {}; - } - game.vm_influence_added[6] = 0 - game.vm_available_ops = 4 - game.state = 'vm_we_are_the_people_remove' -} - -function vm_workers_revolt() { - if (game.active === DEM) { - for (let space of spaces) { - if (!space) continue - let country = space.country - if (!game.revolutions[find_country_index(country)] && game.comInfl[space.space_id] > 0 && space.socio === 4) { - game.valid_spaces.push(space.space_id); - } - } - } else { - for (let space of spaces) { - if (!space) continue - let country = space.country - if (game.revolutions[find_country_index(country)] && game.demInfl[space.space_id] > 0 && space.socio === 4) { - game.valid_spaces.push(space.space_id); - } - } - } - game.state = 'vm_workers_revolt' -} - -function vm_yakovlev_counsels_gorbachev() { - game.persistent_events.push(62) - log_msg_gap('C62 in effect') - game.table_cards.push(62) - remove_from_discard(62) - vm_next() -} - -function vm_permanently_remove () { - // Check if the event is being played as the result of another card, e.g. Dash for the West, is a card which should be removed, and which hasn't already been removed! - if (game.vm_event !== 0 && cards[game.vm_event].remove === 1 && !game.strategy_removed.includes(game.vm_event)) { - permanently_remove(game.vm_event) - } - if (cards[game.played_card].remove ===1 && !game.strategy_removed.includes(game.played_card)) { - permanently_remove(game.played_card) - } /*This means the card that called the event being played is also removed if relevant. Think this makes sense */ - vm_next() -} - -function discarded_card() { - return game.temp > 0 -} - -// =================== TIANANMEN SQUARE TRACK FUNCTIONS ==================== - -function vm_tst_3() { - log_gap('Tiananmen Square Track award') - game.state = 'vm_tst_3_prep' -} - -function vm_tst_4() { - log_gap('Tiananmen Square Track award') - game.vm_available_ops = 2 - game.remove_opponent_infl = true - game.state = 'vm_tst_4' -} -function vm_tst_6() { - log_h3('Tiananmen Square Track award') - game.vm_available_ops = 1 - game.temp = 1 //Set temp to 1, so that Card 1 is called during the support check, which has 2 ops - game.state = 'vm_tst_6' -} - -function vm_tst_8() { - game.state = 'vm_goodbye_lenin_ops' // Use this to resolve ops. -} - -// ==================== POWER STRUGGLE FUNCTIONS ====================== - -function vm_scare_tactics() { - game.vm_active_country = game.pwr_struggle_in - vm_next() -} -function vm_support_surges() { - game.state = 'vm_support_surges_1' -} - -function vm_support_falters() { - game.vm_available_ops = 2 - game.return === game.active - game.state = 'vm_support_falters' -} - -function vm_kremlin_coup_elite() { - game.valid_spaces=[] - elite_spaces.forEach(space => { - if (spaces[space].country === game.vm_active_country && !check_com_control(space)) { - game.valid_spaces.push(space); - } - }) - game.state = 'vm_kremlin_coup_take_control' -} - -/* ================== VM STATES ============================== */ - -states.vm_end_event = { - get inactive() { - return `resolve ${clean_name(cards[this_card()].name)}.` - }, - prompt () { - view.prompt = `${clean_name(cards[this_card()].name)}: done.` - if (game.vm_infl_to_do || game.return_state === 'vm_tst_8') { - gen_action('done') - } else { - gen_action('end_round') - } - }, - done() { - push_undo() - vm_end_event() - }, - end_round() { - push_undo() - game.return_state = '' - vm_end_event() - } -} - -states.vm_take_control = { - get inactive() { - return `resolve ${clean_name(cards[game.played_card].name)}.` - }, - prompt () { - if (game.vm_available_ops > 0 && game.valid_spaces.length === 0) { - view.prompt = `${clean_name(cards[this_card()].name)}: all spaces controlled. Continue.` - gen_action('done') - } else if (game.vm_available_ops > 0 ) { - view.prompt = `${clean_name(cards[this_card()].name)}: take control of ${event_prompt()}.` - for (let space_id of game.valid_spaces) { - gen_action_infl(space_id); - } - } else { - view.prompt = `${clean_name(cards[this_card()].name)}. Take control: done.` - if (game.vm_infl_to_do) { - gen_action('done') - } else { - gen_action('end_round') - } - } - }, - infl(space) { - push_undo() - vm_take_control(space) - game.vm_available_ops-- - if (game.vm_available_ops === 0) { - game.valid_spaces = [] - vm_next() - } - }, - done() { - push_undo() - vm_next() - }, - end_round() { - push_undo() - vm_next() - } -} - -states.vm_add_infl = { - inactive: 'add Support Points.', - prompt () { - if (game.vm_available_ops > 0 && game.valid_spaces.length === 0 ) { - view.prompt = `${clean_name(cards[this_card()].name)}. No available spaces remaining. Add SPs: done.` - gen_action('done') - } - else if (game.vm_available_ops > 0 ) { - view.prompt = `${clean_name(cards[this_card()].name)}: add ${pluralize(game.vm_available_ops,'SP')}${event_prompt()}.` - - for (let space_id of game.valid_spaces) { - gen_action_infl(space_id) - } - } else { - get_end_infl_prompt() - } - }, - infl(space) { - vm_do_add_infl(space) - if (game.vm_available_ops === 0) { - game.valid_spaces = [] - if (game.summary.length > 0) { - pop_summary() - log_br() - } - - game.vm_event_done = true - vm_next() - } - }, - done () { - push_undo() - if (game.summary.length > 0) { - pop_summary() - log_br() - } - - game.vm_event_done = true - vm_next() - }, - end_round() { - push_undo() - if (game.summary.length > 0) { - pop_summary() - log_br() - } - - game.vm_event_done = true - vm_next() - } -} - -states.vm_add_infl_free = { - get inactive() { - return `resolve ${clean_name(cards[this_card()].name)}: add SPs.` - }, - prompt () { - if (game.vm_available_ops > 0 && game.valid_spaces.length === 0 ) { - view.prompt = `${clean_name(cards[this_card()].name)}. No available spaces remaining. Add SPs: done.` - gen_action('done') - } else if (game.vm_available_ops > 0 ) { - view.prompt = `${clean_name(cards[this_card()].name)}: add ${game.vm_available_ops} SPs to ${event_prompt()}.` - - for (let space_id of game.valid_spaces) { - gen_action_infl(space_id); - } - } else { - get_end_infl_prompt() - } - }, - infl(space) { - vm_do_add_infl_free(space) - if (game.vm_available_ops === 0) { - game.valid_spaces = [] - if (game.summary.length > 0) { - pop_summary() - log_br() - } - - game.vm_event_done = true - vm_next() - } - }, - done () { - push_undo() - game.valid_spaces = [] - game.vm_event_done = true - if (game.summary.length > 0) { - pop_summary() - log_br() - } - vm_next() - }, - end_round () { - push_undo() - game.valid_spaces = [] - game.vm_event_done = true - if (game.summary.length > 0) { - pop_summary() - log_br() - } - vm_next() - } -} - -states.vm_add_x_infl = { - get inactive() { - return `resolve ${clean_name(cards[this_card()].name)}: add Support Points.` - }, -// inactive: `resolve ${cards[this_card()].name}: add influence.`, - prompt () { - if (game.vm_event === 101 && game.valid_spaces.length === 0) { - view.prompt = `${clean_name(cards[this_card()].name)}: the Romanian Elite space no longer exists.` - gen_action('done') - } - else if (game.vm_available_ops > 0 ) { - view.prompt = `${clean_name(cards[this_card()].name)}: Add ${game.vm_available_ops} SPs to ${event_prompt()}.` - - for (let space_id of game.valid_spaces) { - gen_action_infl(space_id) - } - } /*else { - view.prompt = `${clean_name(cards[this_card()].name)}. Add SPs: done.` - gen_action('done') - }*/ - }, - infl(space) { - push_undo() - vm_do_add_x_infl(space) - if (game.vm_available_ops === 0) { - game.vm_event_done = true - vm_next() - } - /*if (game.vm_event === (105 || 68) { - vm_next() - return - } */ - - - //game.vm_event_done = true - //vm_next() - }, - done () { - push_undo() - game.vm_event_done = true - vm_next() - } -} - -states.vm_add_limited_infl = { - get inactive() { - return `resolve ${clean_name(cards[this_card()].name)}: add Support Points.` - }, - prompt () { - if (game.vm_available_ops > 0 && game.valid_spaces.length > 0) { - if (game.vm_max_infl === 1) { - view.prompt = `${clean_name(cards[this_card()].name)}: add ${pluralize(game.vm_max_infl,'SP')} ${event_prompt()}.` - } - else { - view.prompt = `${clean_name(cards[this_card()].name)}: add ${pluralize(game.vm_available_ops,'SP')} to ${event_prompt()}.` - } - for (let space_id of game.valid_spaces) { - gen_action_infl(space_id); - } - } /*else { - view.prompt = `${clean_name(cards[this_card()].name)}. Add SPs: done.` - gen_action('done') - }*/ - }, - infl(space) { - vm_do_add_limited_infl(space, game.vm_max_infl) - if (game.vm_available_ops === 0 || game.valid_spaces.length === 0) { - game.valid_spaces = [] - if (game.summary.length > 0) { - pop_summary() - log_br() - } - game.vm_event_done = true - vm_next() - } - }, - /*done () { - push_undo() - if (game.summary.length > 0) { - pop_summary() - log_br() - } - game.vm_event_done = true - vm_next() - }*/ -} - -states.vm_remove_infl = { - inactive: 'remove Support Points.', - prompt () { - // Keep this so that there is an undo option in, e.g., Scare Tactics - if (game.valid_spaces.length === 0 && game.vm_available_ops > 0) { - view.prompt = `${clean_name(cards[this_card()].name)}: no further SPs to remove.` - gen_action('done') - return - } - if (game.vm_available_ops === 0 ) { - view.prompt = `${clean_name(cards[this_card()].name)}. Remove SPs: done.` - gen_action('done') - return - } - if (game.remove_opponent_infl) { - view.prompt = `${clean_name(cards[this_card()].name)}: remove ${pluralize(game.vm_available_ops, 'opponent SP')}${event_prompt()}.` - } - else { - view.prompt = `${clean_name(cards[this_card()].name)}: remove ${pluralize(game.vm_available_ops,'SP')}${event_prompt()}.` - } - for (let space_id of game.valid_spaces) { - gen_action_infl(space_id); - } - }, - infl(space) { - push_undo() - vm_do_remove_infl(space) - game.vm_active_country = spaces[space].country - if (game.vm_event !== 44) { - if (game.vm_available_ops === 0 ) { - if (game.summary.length > 0) { - pop_summary() - log_br() - } - vm_next() - } - } - }, - done() { - if (game.summary.length > 0) { - pop_summary() - log_br() - } - vm_next() - } -} - - -states.vm_remove_x_infl = { - get inactive() { - return `resolve ${clean_name(cards[this_card()].name)}: remove SP from ${event_prompt()}.` - }, - prompt () { - if (game.valid_spaces.length === 0 && game.vm_available_ops > 0) { - view.prompt = `${clean_name(cards[this_card()].name)}: no SPs to remove.` - gen_action('done') - } else if (game.vm_available_ops > 0) { - - view.prompt = `${clean_name(cards[this_card()].name)}: remove ${pluralize(game.vm_available_ops,'SP')} from ${event_prompt()}.` - - for (let space_id of game.valid_spaces) { - gen_action_infl(space_id); - } - } /*else { - if (game.vm_infl_to_do) { - view.prompt = `${clean_name(cards[this_card()].name)}. Remove SPs: done. Return control to phasing player.` - gen_action('done') - return - } else { - view.prompt = `${clean_name(cards[this_card()].name)}. Remove SPs: done.` - gen_action('done') - return - } - }*/ - }, - infl(space) { - vm_do_remove_x_infl(space) - /*if (game.vm_event === 68) { - vm_next() - return - }*/ - if (game.vm_available_ops === 0) { - game.vm_event_done = true - vm_next() - } - /*game.vm_event_done = true - vm_next()*/ - }, - done () { - game.vm_event_done = true - vm_next() - } -} - -states.vm_remove_limited_infl = { - inactive: 'remove SP.', - prompt () { - if (game.vm_available_ops > 0 && game.valid_spaces.length > 0) { - view.prompt = `${clean_name(cards[this_card()].name)}: remove ${pluralize(game.vm_available_ops,'SP')}${event_prompt()}, no more than ${game.vm_max_infl} per space.` - - for (let space_id of game.valid_spaces) { - gen_action_infl(space_id); - } - } else if (game.valid_spaces.length === 0 && game.vm_available_ops > 0) { - view.prompt = `${clean_name(cards[this_card()].name)}: no further SP to remove.` - gen_action('done') - } /*else { - if (game.vm_infl_to_do) { - view.prompt = `${clean_name(cards[this_card()].name)}. Remove SPs: done. Return control to phasing player.` - gen_action('done') - return - } else { - view.prompt = `${clean_name(cards[this_card()].name)}. Remove SPs: done.` - gen_action('done') - return - } - }*/ - }, - infl(space) { - vm_do_remove_limited_infl(space, game.vm_max_infl) - if (game.vm_available_ops === 0) { - game.vm_event_done = true - if (game.summary.length > 0) { - pop_summary() - log_br() - } - vm_next() - } - }, - done () { - game.vm_event_done = true - if (game.summary.length > 0) { - pop_summary() - log_br() - } - vm_next() - } -} - -states.vm_remove_all_infl = { - inactive: 'remove Support Points', - prompt () { - if (game.valid_spaces.length === 0 && game.vm_available_ops > 0) { - view.prompt = `${clean_name(cards[this_card()].name)}: no SPs to remove.` - gen_action('pass') - } else if (game.vm_available_ops > 0) { - view.prompt = `${clean_name(cards[this_card()].name)}: remove all SPs from ${event_prompt()}.` - for (let space_id of game.valid_spaces) { - gen_action_infl(space_id); - } - } /*else { - view.prompt = `${clean_name(cards[this_card()].name)}. Remove SPs: done.` - gen_action('done') - }*/ - }, - infl(space) { - vm_do_remove_all_infl(space) - game.vm_active_country = spaces[space].country - if (game.vm_available_ops === 0) { - vm_next() - } - }, - pass() { - push_undo() - vm_next() - } -} - -states.vm_support_check_prep = { - inactive: 'do support checks.', - prompt () { - /*if (game.vm_available_ops === 0) { - view.prompt = `${clean_name(cards[this_card()].name)}. Support check: done.` - gen_action('done') - } else */ - if (game.valid_spaces.length === 0) { - view.prompt = `${clean_name(cards[this_card()].name)}: no valid targets for support check.` - gen_action('done') - } else { - //if (game.vm_available_ops > 0) { - view.prompt = `${clean_name(cards[this_card()].name)}: ${event_prompt()}. ${pluralize(game.vm_available_ops, 'support check')} remaining.` - //} - for (let space_id of game.valid_spaces) { - if (!space_id) continue - gen_action_sc(space_id); - } - } - }, - sc(space) { - push_undo() - game.selected_space = space - - // Check for Austria-Hungary Border Reopened - check on first support check only - //First check for Monday Demonstrations - support checks will always be in East Germany - if (game.vm_event === 61 && game.persistent_events.includes(58)) { - game.austria_hungary_border_reopened_tracker = true - game.state = 'vm_do_support_check' - return - } - - //Then check Austria-Hungary Border Reopened normally - //console.log('game.austria_hungary_border_reopened_checked', game.austria_hungary_border_reopened_checked) - if (game.persistent_events.includes(58)) { - if (game.active === DEM && game.vm_available_ops > 1) { - if (spaces[game.selected_space].country === 'East_Germany' && game.persistent_events.includes(58) && game.active === DEM) { - game.state = 'vm_austria_hungary_border_reopened_check' - return - } - //game.state = 'do_support_check' - } /*else { */ - } - game.state = 'vm_do_support_check' - }, - done () { - push_undo() - game.vm_available_ops = 0 - vm_next () - } -} - -states.vm_ceh_support_check_prep = { - inactive: 'do support checks.', - prompt () { - /*if (game.vm_available_ops === 0) { - view.prompt = 'Support checks: done.' - gen_action('done') - return - }*/ - if (game.vm_available_ops > 0) { - view.prompt = `Select a space. ${pluralize(game.vm_available_ops, 'support check')} remaining.` - - for (let space_id of game.valid_spaces) { - gen_action_sc(space_id) - } - } - }, - sc(space) { - push_undo() - game.selected_space = space - - //Then check Austria-Hungary Border Reopened normally - //console.log('game.austria_hungary_border_reopened_checked', game.austria_hungary_border_reopened_checked) - if (game.persistent_events.includes(58)) { - if (game.active === DEM && game.vm_available_ops > 1) { - - if (spaces[game.selected_space].country === 'East_Germany' && game.persistent_events.includes(58) && game.active === DEM) { - game.state = 'vm_austria_hungary_border_reopened_check' - return - } - //game.state = 'do_support_check' - } /*else { */ - } - game.state = 'vm_ceh_do_support_check' - }, - /*done () { - vm_next () - }*/ -} - - -states.vm_ceh_do_support_check = { - inactive: 'do support checks.', - prompt () { - view.prompt = `Support check: ${spaces[game.selected_space].name_unique}. Roll a die.` - gen_action('roll') - }, - roll() { - clear_undo() - do_sc(game.selected_space) - - game.vm_available_ops-- - if (game.vm_available_ops === 0) { - game.valid_spaces = [] - vm_next() - } else { - game.state = 'vm_ceh_support_check_prep' - return - } - } -} - -states.vm_austria_hungary_border_reopened_check = { - inactive: 'decide Austria-Hungary Border Reopened', - prompt() { - view.prompt = 'Austria-Hungary Border Reopened: will all support checks be in East Germany?' - gen_action('yes') - gen_action('no') - }, - yes() { - game.austria_hungary_border_reopened_tracker = true - game.state = 'vm_do_support_check' - }, - no() { - game.state = 'vm_do_support_check' - } -} - -states.vm_1_support_check_prep = { - inactive: 'do support checks.', - prompt () { - /*if (game.vm_available_ops === 0) { - view.prompt = `${clean_name(cards[this_card()].name)}. Support check: done.` - gen_action('done') - } else */if (game.valid_spaces.length === 0) { - view.prompt = `${clean_name(cards[this_card()].name)}: no valid targets for support check.` - gen_action('done') - } else { - view.prompt = `${clean_name(cards[this_card()].name)}: ${event_prompt()}.` - - for (let space_id of game.valid_spaces) { - if (!space_id) continue - gen_action_sc(space_id); - } - } - }, - sc(space) { - push_undo() - game.selected_space = space - game.state = 'vm_do_support_check' - }, - done () { - push_undo() - game.vm_available_ops = 0 - vm_next () - } -} - -states.vm_do_support_check = { - inactive: 'do support checks.', - prompt () { - view.prompt = `Support check: ${spaces[game.selected_space].name_unique}. Roll a die.` - gen_action('roll') - }, - roll() { - clear_undo() - do_sc(game.selected_space) - game.vm_available_ops-- - if (game.vm_available_ops === 0) { - game.valid_spaces = [] - vm_next() - return - } else { - game.state = 'vm_support_check_prep' - return - } - } -} - -states.vm_tiananmen_square_attempt = { - inactive: 'do Tiananmen Square', - prompt () { - /*if (game.active === DEM && game.dem_tst_attempted_this_turn > 0 || game.active === COM && game.com_tst_attempted_this_turn > 0) { - view.prompt = 'Tiananmen Square Track attempt: done.' - gen_action('done') - return - }*/ - view.prompt = 'Tiananmen Square: roll a die' - gen_action('roll') - }, - roll() { - clear_undo() - do_tst_attempt () - }, - /*done () { - vm_next() - }*/ -} - -//================================== EVENT SPECIFIC STATES ====================================== - -states.vm_adamec = { - get inactive() { - return `resolve ${clean_name(cards[88].name)}.` - }, - prompt() { - view.prompt = 'Adamec: roll a die.' - gen_action('roll') - }, - roll() { - clear_undo() - let roll = Math.floor(Math.random() * 6) + 1 - log(`Roll: D${roll}`) - let worker_spaces = spaces.filter(space => space && space.country === 'Czechoslovakia' && space.socio === 4 && check_dem_control(space.space_id)).length - if (worker_spaces > 0) { - log(`-${worker_spaces} from Democrat controlled worker spaces`) - roll -= worker_spaces - } - log(`Modified roll: ${roll}`) - if (roll > 2) { - log('Adamec succeeds') - vm_next() - return - } - log('Adamec fails: 3 or more required') - permanently_remove(88) - vm_return() - } -} - -states.vm_brought_in_for_questioning = { - inactive: 'discard a card.', - prompt() { - /*if (game.phase === 1) { - view.prompt = 'Discard a card: done.' - gen_action('done') - } else */ - if (game.democrat_hand.length === 0) { - view.prompt = 'Brought in for Questioning. No cards to discard.' - gen_action('pass') - } else { - view.prompt = 'Brought in for Questioning: you must discard a random card.' - gen_action('discard') - } - }, - discard() { - clear_undo() - game.vm_event = discard_card(game.democrat_hand) - game.phase = 1 - if (cards[game.vm_event].side === 'C' && (cards[game.vm_event].playable || game.playable_cards.includes(game.vm_event))) { - //game.return = game.active - if (!game.vm_infl_to_do) { - if(game.round_player === DEM) { - game.return = COM - } else { - game.return = DEM - } - } - if (!is_auto_resolve(game.vm_event) && !switch_events.includes(game.vm_event)) { - next_player() - } - goto_vm(game.vm_event) - } else { - game.return = DEM - vm_return() - } - }, - pass() { - log('No cards to discard') - vm_return() - }, - /*done() { - vm_return() - }*/ -} - -states.vm_central_committee_reshuffle = { - get inactive() { - return `resolve ${clean_name(cards[57].name)}.` - }, - prompt() { - if (game.revolutions.every(n => n === true)) { - view.prompt = 'Central Committee Reshuffle: no countries to choose.' - gen_action('pass') - } else { - view.prompt = 'Central Committee Reshuffle: choose a country to add SPs.' - if (!game.revolutions[0]) {gen_action('poland')} - if (!game.revolutions[1]) {gen_action('hungary')} - if (!game.revolutions[2]) {gen_action('east_germany')} - if (!game.revolutions[3]) {gen_action('bulgaria')} - if (!game.revolutions[4]) {gen_action('czechoslovakia')} - if (!game.revolutions[5]) {gen_action('romania')} - } - }, - east_germany() { - push_undo() - game.vm_active_country = "East_Germany" - log(`Chose ${country_name(game.vm_active_country)}`) - game.valid_spaces = [1,2,3,4,5,6,7,8,9,10,11,12] - vm_next() - }, - poland() { - push_undo() - game.vm_active_country = "Poland" - log(`Chose ${country_name(game.vm_active_country)}`) - game.valid_spaces = [13,14,15,16,17,18,19,20,21,22,23,24,25,26] - vm_next() - }, - czechoslovakia() { - push_undo() - game.vm_active_country = "Czechoslovakia" - log(`Chose ${country_name(game.vm_active_country)}`) - game.valid_spaces = [27,28,29,30,31,32,33,34,35,36,37] - vm_next() - }, - hungary() { - push_undo() - game.vm_active_country = "Hungary" - log(`Chose ${country_name(game.vm_active_country)}`) - game.valid_spaces = [38,39,40,41,42,43,44,45,46,47,48,49] - vm_next() - }, - romania() { - push_undo() - game.vm_active_country = "Romania" - log(`Chose ${country_name(game.vm_active_country)}`) - game.valid_spaces = [50,51,52,53,54,55,56,57,58,59,60,61,62,63] - game.valid_spaces = game.valid_spaces.filter(space => space !== game.systematization) - vm_next() - }, - bulgaria () { - push_undo() - game.vm_active_country = "Bulgaria" - log(`Chose ${country_name(game.vm_active_country)}`) - game.valid_spaces = [64,65,66,67,68,69,70,71,72,73,74,75] - vm_next() - }, - pass() { - log('Passed') - vm_return() - } - -} - -states.vm_common_european_home_choose = { - get inactive() { - return `resolve ${clean_name(cards[game.played_card].name)}.` - }, - prompt() { - view.prompt = `Common European Home: play an opponent's card, event does not occur.` - for (let card of game.valid_cards) { - gen_action_card(card) - } - }, - card(card) { - push_undo() - //log(`Played with C${cards[card].number}`) - game.valid_cards = [] - silent_discard(card) - game.vm_event = card - game.state = 'vm_common_european_home_play' - } -} - -states.vm_common_european_home_play = { - get inactive() { - return `resolve ${clean_name(cards[this_card()].name)}.` - }, - prompt() { - view.prompt = `Play ${clean_name(cards[this_card()].name)} for:` - gen_action('influence') - gen_action('support_check') - if (game.active === DEM && game.vm_event === 87 ) { - return /*Special condition if card is actually Kohl Proposes Reunification*/ - } - /*if (game.active === DEM && game.dem_tst_attempted_this_turn === 0 || game.active === COM && game.com_tst_attempted_this_turn === 0) { - gen_action('tst') - } */ - }, - influence(){ - push_undo() - log_gap(`Played C${cards[game.vm_event].number} to place SPs`) - game.vm_available_ops = cards[game.vm_event].ops - valid_spaces_infl() - // If ABHR - Set AHBR tracker to true - if (game.persistent_events.includes(58)) { - game.austria_hungary_border_reopened_tracker = true - } - game.state = 'vm_add_infl' - }, - support_check() { - push_undo() - log_gap(`Played C${cards[game.vm_event].number} for support checks`) - game.vm_available_ops = 2 - game.state = 'vm_ceh_support_check_prep' - valid_spaces_sc() - }, - tst() { - push_undo() - log_gap(`Played C${cards[game.vm_event].number} to the Tiananmen Square Track`) - game.state = 'vm_tiananmen_square_attempt' - } -} - -states.vm_dash_for_the_west = { - get inactive() { - return `resolve ${clean_name(cards[36].name)}.` - }, - prompt() { - /* if (game.phase === 1) {*/ - view.prompt = 'Dash for the West: roll a die' - gen_action('roll') - /*} else { - view.prompt = 'Dash for the West: roll a die. Done.' - gen_action('done') - }*/ - }, - roll() { - clear_undo() - let roll = Math.floor(Math.random() * 6) + 1 - log(`Roll: D${roll}`) - let com_control = check_presence('East_Germany').com_spaces - - if (roll > com_control) { - log(`Success. More than the ${com_control} Communist controlled spaces in East Germany`) - log('+1 VP') - game.vp++ - if (check_vp()) { - return - } - game.discard = true - game.state = 'vm_play_event_from_discard' - } else { - log(`Fail: more than a ${com_control} required`) - //game.phase++ - vm_next() - } - },/* - done() { - vm_next() - }*/ -} - -states.vm_play_event_from_discard = { - get inactive() { - return `resolve ${clean_name(cards[game.played_card].name)}.` - }, - prompt() { - if (game.valid_cards.length === 0) { - view.prompt = `${clean_name(cards[this_card()].name)}: no valid cards in discard.` - gen_action('pass') - } else if (game.temp === 0) { - view.prompt = `${event_prompt()}.` - for (let card of game.valid_cards) { - gen_action('pass') - gen_action_card(card) - } - } /*else { - view.prompt = 'Choose a card: done.' - gen_action('done') - }*/ - }, - card(card) { - push_undo() - log(`Chose C${cards[card].number}`) - game.vm_event = card - game.vm_available_ops = cards[card].ops - game.discard = false - //game.return = game.active Does turning this off cause problems? - if (switch_events.includes(card)) {next_player()} - goto_vm(card) - }, - pass(){ - push_undo() - if (game.valid_cards.length === 0) { - log('No valid cards to choose') - } else{ - log('Did not choose a card') - } - vm_next() - }, -/* done(){ - push_undo() - game.discard = false - vm_next() - }*/ -} - -states.vm_deutsche_marks_prep = { - inactive: 'choose a card.', - prompt() { - if (game.valid_cards.length === 0) { - view.prompt = 'Deutsche Marks: no cards to give.' - gen_action('pass') - } else { - view.prompt = 'Deutsche Marks: choose a card to give.' - for (let card of game.valid_cards) { - gen_action_card(card) - } - } - }, - card(card) { - push_undo() - log(`Gave C${cards[card].number}`) - game.valid_cards = [] - silent_discard(card) - //next_player() - game.state = 'vm_deutsche_marks_confirm' - game.vm_event = card - }, - pass() { - push_undo() - vm_next() - } -} - -states.vm_deutsche_marks_confirm = { - inactive: 'choose a card.', - prompt() { - view.prompt = `Deutsche Marks: gave ${cards[game.vm_event].name}.` - gen_action('done') - }, - done() { - next_player() - game.state = 'vm_deutsche_marks' - } -} - -states.vm_deutsche_marks = { - get inactive() { - return `resolve ${clean_name(cards[20].name)}.` - }, - prompt() { - if(cards[game.vm_event].side === 'C' && (cards[game.vm_event].playable || game.playable_cards.includes(game.vm_event))) { - view.prompt = `Deutsche Marks: you must play ${clean_name(cards[this_card()].name)} for the event.` - gen_action('event') - } else { - view.prompt = `Deutsche Marks: play ${clean_name(cards[this_card()].name)} for:` - gen_action('influence') - gen_action('support_check') - if (game.com_tst_attempted_this_turn === 0) { - gen_action('tst') - } - } - }, - event() { - push_undo() - log(`Played C${cards[game.vm_event].number} for the event`) - if (!game.vm_infl_to_do) { - game.return = game.active - } - goto_vm(game.vm_event) - }, - influence() { - push_undo() - log(`Played C${cards[game.vm_event].number} to place SPs`) - game.vm_available_ops = get_card_ops(game.vm_event) - - /*cards[game.vm_event].ops - if (game.persistent_events.includes(25)) {game.vm_available_ops++ } - if (game.prudence.COM && game.prudence.COM < 0 ) { - game.vm_available_ops += game.prudence.COM - }*/ - valid_spaces_infl() - game.state = 'vm_add_infl' - }, - support_check() { - push_undo() - log_gap(`Played C${cards[game.vm_event].number} for support checks`) - game.vm_available_ops = 2 - game.state='vm_support_check_prep' - valid_spaces_sc() - }, - tst() { - push_undo() - log_gap(`Played C${cards[game.vm_event].number} to the Tiananmen Square Track`) - game.state='vm_tiananmen_square_attempt' - } -} - -states.vm_exit_visas = { - get inactive() { - return `resolve ${clean_name(cards[75].name)}.` - }, - prompt() { - view.prompt = 'Exit Visas: you may discard cards from your hand and draw replacements.' - for (let card of game.democrat_hand) { - gen_action_card(card) - } - if (game.temp === 0) { - gen_action('pass') - } else { - gen_action('done') - } - }, - card(card){ - push_undo() - discard(card) - game.temp++ - }, - pass() { - push_undo() - game.state = 'vm_exit_visas_finish' - }, - done() { - push_undo() - game.state = 'vm_exit_visas_finish' - } -} - -states.vm_exit_visas_finish = { - get inactive() { - return `resolve ${clean_name(cards[75].name)}.` - }, - prompt() { - if (game.temp > 0 ) { - view.prompt = 'Exit Visas: draw replacement cards.' - gen_action('draw') - } /*else { - view.prompt = 'Exit Visas. Draw cards: done.' - gen_action('done') - } */ - }, - draw() { - clear_undo() - draw_cards(game.strategy_deck, game.democrat_hand, game.communist_hand, game.democrat_hand.length + game.temp, game.communist_hand.length) - game.temp = 0 - vm_next() - }, - /*done() { - vm_next() - }*/ -} - -states.vm_foreign_currency_debt_burden = { - get inactive() { - return `resolve ${clean_name(cards[game.played_card].name)}.` - }, - prompt() { - view.prompt = 'Choose a country. The Communist may not make support checks there for the rest of the turn.' - gen_action('east_germany') - gen_action('poland') - gen_action('czechoslovakia') - gen_action('hungary') - gen_action('bulgaria') - }, - east_germany() { - push_undo() - game.foreign_currency_debt_burden = 'East_Germany' - log('Selected East Germany') - vm_next() - }, - poland() { - push_undo() - game.foreign_currency_debt_burden = 'Poland' - log('Selected Poland') - vm_next() - }, - czechoslovakia() { - push_undo() - game.foreign_currency_debt_burden = 'Czechoslovakia' - log('Selected Czechoslovakia') - vm_next() - }, - hungary() { - push_undo() - game.foreign_currency_debt_burden = 'Hungary' - log('Selected Hungary') - vm_next() - }, - bulgaria() { - push_undo() - game.foreign_currency_debt_burden = 'Bulgaria' - log('Selected Bulgaria') - vm_next() - } -} - -states.vm_goodbye_lenin = { - get inactive() { - return `resolve ${clean_name(cards[game.played_card].name)}.` - }, - prompt() { - if (game.valid_cards.length > 0 ) { - view.prompt = `Play a red event from your opponent's hand, or play Goodbye Lenin for operations.` - for (let card of game.valid_cards) { - gen_action_card(card) - gen_action('ops') - } - } else { - view.prompt = 'Communist has no red events. Play Goodbye Lenin for operations.' - gen_action('ops') - } - }, - card(card) { - push_undo() - log(`Chose to play C${card} for the event`) - let card_index = game.communist_hand.indexOf(card) - game.communist_hand.splice(card_index, 1) - game.vm_event = card - game.view_opp_hand = false - goto_vm(card) - }, - ops() { - push_undo() - if (game.valid_cards.length === 0) { - logi('No red events') - } - log('C46 played for operations') - game.view_opp_hand = false - game.state = 'vm_goodbye_lenin_ops' - } -} - -states.vm_goodbye_lenin_ops = { - get inactive() { - return `resolve ${clean_name(cards[this_card()].name)}.` - }, - prompt() { - view.prompt = `Play ${clean_name(cards[this_card()].name)} for:` - gen_action('influence') - gen_action('support_check') - if ((game.active === DEM && game.dem_tst_attempted_this_turn === 0 ) || (game.active === COM && game.com_tst_attempted_this_turn === 0 )) { - gen_action('tst') - } - }, - influence(){ - push_undo() - game.vm_available_ops = get_card_ops(this_card()) - /*if (game.persistent_events.includes(50)) { - log(`+1 from C50`) - game.vm_available_ops++ - }*/ - valid_spaces_infl() - - // If ABHR - Set AHBR tracker to true - if (game.persistent_events.includes(58)) { - game.austria_hungary_border_reopened_tracker = true - } - game.state = 'vm_add_infl' - }, - support_check() { - push_undo() - game.vm_available_ops = 2 - game.state = 'vm_support_check_prep' - valid_spaces_sc() - }, - tst() { - push_undo() - game.state = 'vm_tiananmen_square_attempt' - } -} - -states.vm_honecker = { - get inactive() { - return `resolve ${clean_name(cards[game.played_card].name)}.` - }, - prompt() { - if (game.valid_cards.length === 0 && game.temp === 0) { - view.prompt = 'Honecker: no valid cards to choose.' - gen_action('pass') - } else - if (game.temp === 0) {view.prompt = 'Honecker: choose a card to add to your hand.' - for (let card of game.valid_cards) { - gen_action_card(card) - gen_action('pass') - } - } /*else { - view.prompt = 'Honecker. Choose a card: done.' - gen_action('done') - }*/ - }, - card(card) { - push_undo() - game.valid_cards = [] - log(`Took C${cards[card].number} into hand`) - game.temp = card - let card_index = game.strategy_discard.indexOf(card) - game.strategy_discard.splice(card_index, 1) - game.communist_hand.push(card) - vm_next() - }, - pass(){ - log('Did not take a card') - game.discard = false - vm_next() - }, - /*done(){ - if (game.temp === 0) { - log('Did not take a card') - } - game.discard = false - vm_next() - } */ - -} - -states.vm_inflationary_currency = { - get inactive() { - return `resolve ${clean_name(cards[game.played_card].name)}.` - }, - prompt() { - if ((game.active === COM && game.revolutions.every(n => n === false)) || (game.active === DEM && game.revolutions.every(n => n === true))) { - view.prompt = 'Inflationary Currency: no countries to choose.' - gen_action('pass') - } else { - view.prompt = 'Inflationary Currency: choose a country where your opponent has power.' - if (game.active === DEM) { - if (!game.revolutions[0]) {gen_action('poland')} - if (!game.revolutions[1]) {gen_action('hungary')} - if (!game.revolutions[2]) {gen_action('east_germany')} - if (!game.revolutions[3]) {gen_action('bulgaria')} - if (!game.revolutions[4]) {gen_action('czechoslovakia')} - if (!game.revolutions[5]) {gen_action('romania')} - } else { - if (game.revolutions[0]) {gen_action('poland')} - if (game.revolutions[1]) {gen_action('hungary')} - if (game.revolutions[2]) {gen_action('east_germany')} - if (game.revolutions[3]) {gen_action('bulgaria')} - if (game.revolutions[4]) {gen_action('czechoslovakia')} - if (game.revolutions[5]) {gen_action('romania')} - } - } - }, - east_germany() { - push_undo() - game.vm_active_country = 'East_Germany' - log(`Chose ${country_name(game.vm_active_country)}`) - vm_next() - }, - poland() { - push_undo() - game.vm_active_country = 'Poland' - log(`Chose ${country_name(game.vm_active_country)}`) - vm_next() - }, - czechoslovakia() { - push_undo() - game.vm_active_country = 'Czechoslovakia' - log(`Chose ${country_name(game.vm_active_country)}`) - vm_next() - }, - hungary() { - push_undo() - game.vm_active_country = 'Hungary' - log(`Chose ${country_name(game.vm_active_country)}`) - vm_next() - }, - romania() { - push_undo() - game.vm_active_country = 'Romania' - log(`Chose ${country_name(game.vm_active_country)}`) - vm_next() - }, - bulgaria () { - push_undo() - game.vm_active_country = 'Bulgaria' - log(`Chose ${country_name(game.vm_active_country)}`) - vm_next() - }, - pass() { - log('Passed') - vm_return() - } -} - -states.vm_inflationary_currency_discard = { - get inactive() { - return `resolve ${clean_name(cards[game.played_card].name)}.` - }, - prompt() { - if (game.valid_cards.length === 0 ) { - view.prompt = 'Inflationary Currency: no valid cards to discard. You must pass.' - gen_action('pass') - } else if (game.temp === 0 ) { - view.prompt = 'Inflationary Currency: you may discard a 3 op or higher value card to cancel the support check.' - gen_action('pass') - for (let card of game.valid_cards) { - gen_action_card(card) - } - } /*else { - view.prompt = 'Inflationary Currency. Discard a card: done.' - gen_action('done') - } */ - }, - card(card) { - push_undo() - discard(card) - game.temp = card - if (!game.vm_infl_to_do) { - if(game.round_player === DEM) { - game.return = COM - } else { - game.return = DEM - } - } - vm_next() - }, - pass() { - push_undo() - log('Did not discard') - next_player() - game.vm_available_ops = 1 - vm_next() - //game.state = 'vm_support_check_prep' - }, - done() { - if (!game.vm_infl_to_do) { - if(game.round_player === DEM) { - game.return = COM - } else { - game.return = DEM - } - } - vm_next() - } -} - - -states.vm_kiss_of_death = { - get inactive() { - return `resolve ${clean_name(cards[game.played_card].name)}.` - }, - prompt() { - if (game.communist_hand.length === 0) { - view.prompt = 'Kiss of Death. No cards to discard.' - gen_action('pass') - } else { - view.prompt = 'Kiss of Death: you must randomly discard a card.' - gen_action('discard') - } - }, - discard() { - clear_undo() - game.vm_event = discard_card(game.communist_hand) - //Only switch player if a playable non-communist event. Common European Home is not playable here - if (cards[game.vm_event].side !== "C" && event_is_playable(game.vm_event) && game.vm_event !== 21) { - next_player() - game.state = 'vm_kiss_of_death_finish' - } else { - log('Event does not occur') - vm_next() - } - }, - pass() { - log('No card to discard') - vm_next() - } -} - -states.vm_kiss_of_death_finish = { - get inactive() { - return `resolve ${clean_name(cards[game.played_card].name)}.` - }, - prompt() { - if (game.vm_event > 0 && game.vm_event !== 21 && (cards[game.vm_event].side === 'D' || cards[game.vm_event].side === 'N')) { - view.prompt = `Play ${clean_name(cards[game.vm_event].name)} for the event.` - console.log('kiss of death before event button: game.stategy_discard', game.strategy_discard) - gen_action('event') - } else { - view.prompt = 'Event does not occur.' - gen_action('done') - } - }, - event() { - //game.return = game.active - // Remove game.vm_event from the discard - //game.strategy_discard = game.strategy_discard.filter(n => n !== game.vm_event) - - goto_vm(game.vm_event) - }, - done() { - vm_next() - } -} - -states.vm_kremlin_coup_choose_country = { - get inactive() { - return `resolve ${clean_name(cards[this_card()].name)}.` - }, - prompt() { - if (game.temp.length > 0) { - view.prompt = 'Kremlin Coup! Select a country where the Communist retains power.' - for (let country of countries) { - if (game.temp.includes(country)) { - gen_action(`${country.toLowerCase()}`) - } - } - } else { - view.prompt = 'Kremlin Coup! There are no countries where the Communist retains power.' - gen_action('done') - } - }, - east_germany() { - push_undo() - game.vm_active_country = 'East_Germany' - game.temp = game.temp.filter(country => country !== game.vm_active_country) - log(`${country_name(game.vm_active_country)}:`) - vm_kremlin_coup_elite() - }, - poland() { - push_undo() - game.vm_active_country = 'Poland' - log(`${country_name(game.vm_active_country)}:`) - game.temp = game.temp.filter(country => country !== game.vm_active_country) - vm_kremlin_coup_elite() - }, - czechoslovakia() { - push_undo() - game.vm_active_country = 'Czechoslovakia' - log(`${country_name(game.vm_active_country)}:`) - game.temp = game.temp.filter(country => country !== game.vm_active_country) - vm_kremlin_coup_elite() - }, - hungary() { - push_undo() - game.vm_active_country = 'Hungary' - log(`${country_name(game.vm_active_country)}:`) - game.temp = game.temp.filter(country => country !== game.vm_active_country) - vm_kremlin_coup_elite() - }, - romania() { - push_undo() - game.vm_active_country = 'Romania' - log(`${country_name(game.vm_active_country)}:`) - game.temp = game.temp.filter(country => country !== game.vm_active_country) - vm_kremlin_coup_elite() - }, - bulgaria () { - push_undo() - game.vm_active_country = 'Bulgaria' - log(`${country_name(game.vm_active_country)}:`) - game.temp = game.temp.filter(country => country !== game.vm_active_country) - vm_kremlin_coup_elite() - }, - done() { - game.temp = 0 - vm_next() - } -} - -states.vm_kremlin_coup_take_control = { - get inactive() { - return `resolve ${clean_name(cards[game.played_card].name)}.` - }, - prompt() { - if (game.valid_spaces.includes(game.systematization)) { - view.prompt = `Kremlin Coup! ${country_name(game.vm_active_country)}'s Elite space no longer exists.` - gen_action('done') - } - else if (game.valid_spaces.length === 0){ - view.prompt = `Kremlin Coup! ${country_name(game.vm_active_country)}'s Elite space is already controlled.` - gen_action('done') - } else { - view.prompt = `Kremlin Coup! Take control of the Elite space in ${country_name(game.vm_active_country)}.` - for (let space_id of game.valid_spaces) { - gen_action_infl(space_id); - } - } - }, - infl(space) { - push_undo() - vm_take_control(space) - if (game.vm_active_country === 'East_Germany') {game.selected_space = 3 } - if (game.vm_active_country === 'Poland') {game.selected_space = 17} - if (game.vm_active_country === 'Czechoslovakia') {game.selected_space = 29} - if (game.vm_active_country === 'Hungary') {game.selected_space = 45} - if (game.vm_active_country === 'Romania') {game.selected_space = 61} - if (game.vm_active_country === 'Bulgaria') {game.selected_space = 68} - game.state = 'vm_kremlin_coup_sc_prep' - }, - done() { - push_undo() - if (game.vm_active_country === 'East_Germany') {game.selected_space = 3 } - if (game.vm_active_country === 'Poland') {game.selected_space = 17} - if (game.vm_active_country === 'Czechoslovakia') {game.selected_space = 29} - if (game.vm_active_country === 'Hungary') {game.selected_space = 45} - if (game.vm_active_country === 'Romania') {game.selected_space = 61} - if (game.vm_active_country === 'Bulgaria') {game.selected_space = 68} - game.state = 'vm_kremlin_coup_sc_prep' - } -} - -states.vm_kremlin_coup_sc_prep = { - get inactive() { - return `resolve ${clean_name(cards[game.played_card].name)}.` - }, - prompt() { - view.prompt = `Kremlin Coup! Conduct a support check in ${country_name(game.vm_active_country)}'s Bureaucratic space.` - gen_action_sc(game.selected_space); - }, - sc(space) { - //game.selected_space = space - push_undo() - game.state = 'vm_kremlin_coup_sc' - } -} - -states.vm_kremlin_coup_sc = { - inactive: 'do support checks', - prompt () { - view.prompt = `Support check: ${spaces[game.selected_space].name_unique}. Roll a die.` - gen_action('roll') - }, - roll() { - clear_undo() - do_sc(game.selected_space) - if (game.temp.length > 0 ){ - game.state = 'vm_kremlin_coup_choose_country' - } else { - //game.state = 'vm_kremlin_coup_end' - vm_next() - } - } -} -/* -states.vm_kremlin_coup_end = { - get inactive() { - return `resolve ${clean_name(cards[this_card()].name)}.` - }, - prompt() { - view.prompt = `${clean_name(cards[this_card()].name)} Support checks: done.` - gen_action('done') - }, - done() { - vm_next() - } -} -*/ -states.vm_laszlo_tokes = { - get inactive() { - return `resolve ${clean_name(cards[game.played_card].name)}.` - }, - prompt() { - view.prompt = `Laszlo Tokes. Choose to:` - gen_action('influence') - gen_action('support_check') - }, - influence(){ - push_undo() - game.vm_available_ops = get_card_ops(73) - valid_spaces_infl() - game.valid_spaces = game.valid_spaces.filter(space_id => spaces[space_id].country === 'Romania') - game.phase = 3 - vm_next() - //game.state = 'vm_add_infl' - }, - support_check() { - push_undo() - game.vm_available_ops = 2 - //game.state = 'vm_support_check_prep' - valid_spaces_sc() - game.valid_spaces = game.valid_spaces.filter(space_id => spaces[space_id].country === 'Romania') - vm_next() - } -} - -states.vm_switch_infl = { - get inactive() { - return `resolve ${clean_name(cards[game.played_card].name)}.` - }, - prompt() { - if (game.valid_spaces.length === 0) { - view.prompt = `${clean_name(cards[this_card()].name)}: No SPs to remove.` - gen_action('pass') - } else { - /*if (game.vm_available_ops > 0 ) {*/ - view.prompt = `${clean_name(cards[game.played_card].name)}: ${event_prompt()}.` - for (let space_id of game.valid_spaces) { - gen_action_infl(space_id); - } - } /*else { - view.prompt = 'Influence replaced.' - gen_action('done') - }*/ - }, - infl(space) { - push_undo() - vm_switch_infl(space) - if (game.vm_available_ops === 0) { - game.valid_spaces = [] - } - vm_next() - }, - pass() { - vm_next() - } - /*done() { - vm_next() - }*/ -} - -states.vm_malta_summit = { - get inactive() { - return `resolve ${clean_name(cards[game.played_card].name)}.` - }, - prompt() { - /*if (game.phase === 1) {*/ - view.prompt = 'Malta Summit: roll a die.' - gen_action('roll') - /*} else { - view.prompt = 'Done.' - gen_action('done') - }*/ - }, - roll() { - clear_undo() - let roll = Math.floor(Math.random() * 6) + 1 - log(`Roll: D${roll}`) - if (game.stability > 0) { - log(`+${game.stability} from USSR Stability Track`) - log(`Modified roll: ${roll + game.stability}`) - } - if (roll + game.stability > 3) { - log('Summit successful') - game.vp += 3 - log('+3 VP') - if (check_vp()) { - return - } - if (game.comInfl[12] > 0 ) {game.valid_spaces.push(12)} - if (game.comInfl[15] > 0 ) {game.valid_spaces.push(15)} - if (game.comInfl[27] > 0 ) {game.valid_spaces.push(27)} - if (game.comInfl[43] > 0 ) {game.valid_spaces.push(43)} - if (game.comInfl[51] > 0 ) {game.valid_spaces.push(51)} - if (game.comInfl[69] > 0 ) {game.valid_spaces.push(69)} - //game.vm_available_ops = 5 - game.remove_opponent_infl = true - vm_next() - } - else { - log('Summit failed. Required 4 or more') - //game.phase++ - vm_goto_step(vm_permanently_remove) - } - }, - /*done() { - vm_next() - }*/ -} - -states.vm_modrow = { - get inactive() { - return `resolve ${clean_name(cards[game.played_card].name)}.` - }, - prompt() { - view.prompt = `Modrow: roll a die.` - gen_action('roll') - }, - roll(){ - clear_undo() - let roll = Math.floor(Math.random() * 6) + 1 - let dem_spaces = spaces.filter(space => space && space.country === 'East_Germany' && check_dem_control(space.space_id)).length - if (roll > dem_spaces) { - log(`Roll: D${roll}`) - log(`Success. More than the ${dem_spaces} Democratically controlled spaces`) - vm_next() - } else { - log(`Roll: D${roll}`) - log(`Fail. More than ${dem_spaces} required`) - permanently_remove(83) - vm_return() - } - } -} - -states.vm_nepotism = { - get inactive() { - return `resolve ${clean_name(cards[game.played_card].name)}.` - }, - prompt() { - //if (game.phase === 1 ) { - view.prompt = 'Nepotism: roll a die.' - gen_action('roll') - /*} else { - view.prompt = 'Roll a die: done.' - gen_action('done') - }*/ - }, - roll() { - clear_undo() - let roll = Math.floor(Math.random() * 6) + 1 - if (roll < 3) { - log(`Roll: D${roll} adds 4 SPs`) - game.vm_available_ops = 4} - else if (roll < 5 ) { - log(`Roll: D${roll} adds 3 SPs`) - game.vm_available_ops = 3} - else { - log(`Roll: D${roll} adds 1 SP`) - game.vm_available_ops = 1} - //game.phase = 2 - vm_next() - }, - /*done() { - vm_next() - }*/ -} - -states.vm_new_years_eve_party = { - get inactive() { - return `resolve ${clean_name(cards[104].name)}.` - }, - prompt() { - view.prompt = 'Choose whether the game ends at the end of this turn.' - gen_action('end') - gen_action('continue') - }, - end() { - push_undo() - game.persistent_events.push(104) - log('Chooses to end the game. There will be no final scoring') - let power = game.revolutions.filter(value => value === false).length - if (power > 3) { - log(`Communist holds power in ${power} countries. -3 VP`) - game.vp -= 3 - } else { - log(`Communist holds power in ${power} countries. +3 VP`) - game.vp += 3 - } - if (check_vp()) { - return - } - //game.table_cards.push(104) - permanently_remove(104) - vm_next() - }, - continue() { - push_undo() - log('Chooses to continue') - permanently_remove(104) - vm_next() - } -} - -states.vm_nomenklatura = { - get inactive() { - return `resolve ${clean_name(cards[game.played_card].name)}.` - }, - prompt() { - view.prompt = 'Nomenklatura: choose to remove all Democratic SPs from Elite spaces or add 3 SPs to any Elite space(s).' - gen_action('remove') - gen_action('add') - }, - remove() { - push_undo() - game.valid_spaces = [] - for (let i = 1; i < spaces.length; i++) { - let space = spaces[i] - - if (space.socio === 1 && game.demInfl[i] > 0) { - game.valid_spaces.push(space.space_id) - } - } - game.vm_available_ops = game.valid_spaces.length - game.remove_opponent_infl = true - game.state = 'vm_nomenklatura_remove' - }, - add() { - push_undo() - game.valid_spaces = [] - for (let space of spaces) { - if (!space) continue - if (space.socio === 1) { - game.valid_spaces.push(space.space_id) - } - } - check_systematization() - game.vm_available_ops = 3 - game.state = 'vm_nomenklatura_add' - } -} - -states.vm_nomenklatura_remove = { - get inactive() { - return `resolve ${clean_name(cards[game.played_card].name)}.` - }, - prompt() { - if (game.valid_spaces.length === 0 ) { - view.prompt = 'Nomenklatura. No SPs to remove: pass.' - gen_action('pass') - } else { - view.prompt = 'Nomenklatura: remove all Democratic SPs from Elite spaces.' - - for (let space_id of game.valid_spaces) { - gen_action_infl(space_id); - } - } - }, - infl(space) { - push_undo() - vm_do_remove_all_infl(space) - if (game.valid_spaces.length === 0) { - vm_next() - } - }, - pass() { - push_undo() - vm_next() - } -} - -states.vm_nomenklatura_add = { - get inactive() { - return `resolve ${clean_name(cards[game.played_card].name)}.` - }, - prompt() { - /*if (game.vm_available_ops === 0 || game.valid_spaces.length === 0 ) { - view.prompt = 'Nomenklatura. Add SPs: done.' - gen_action('done') - } else { */ - view.prompt = `Nomenklatura: add 3 SPs to any Elite space(s). ${pluralize(game.vm_available_ops, 'SP')} remaining.` - for (let space_id of game.valid_spaces) { - gen_action_infl(space_id); - } - //} - }, - infl(space) { - push_undo() - vm_do_add_infl_free(space) - if (game.vm_available_ops === 0 ) { - game.valid_spaces = [] - if (game.summary.length > 0) { - pop_summary() - log_br() - } - vm_next() - } - }, -/* done() { - push_undo() - if (game.summary.length > 0) { - pop_summary() - log_br() - } - vm_next() - }*/ -} - -states.vm_samizdat = { - get inactive() { - return `resolve ${clean_name(cards[game.played_card].name)}.` - }, - prompt() { - view.prompt = 'Samizdat: you may set aside a card from your hand and draw a replacement.' - for (let card of game.democrat_hand) { - gen_action_card(card) - } - gen_action('pass') - }, - card(card) { - push_undo() - game.samizdat_card = card - game.democrat_hand = game.democrat_hand.filter(c => c !== card) - log('Set aside a card') - game.state = 'vm_samizdat_finish' - }, - pass() { - push_undo() - //if (game.samizdat_card > 0) {game.state = 'vm_samizdat_finish'} - /*else { */ - log('Did not set aside a card') - vm_next() - //} - } -} - -states.vm_samizdat_finish = { - get inactive() { - return `resolve ${clean_name(cards[game.played_card].name)}.` - }, - prompt() { - /*if (game.phase ) { - view.prompt = 'Samizdat: done.' - gen_action('done') - } else {*/ - view.prompt = 'Draw a replacement card.' - gen_action('draw') - //} - }, - draw() { - clear_undo() - game.democrat_hand.push(draw_card(game.strategy_deck)) - vm_next() - //game.phase ++ - }, - /*done() { - vm_next() - }*/ -} - -states.vm_shock_therapy = { - get inactive() { - return `resolve ${clean_name(cards[game.played_card].name)}.` - }, - prompt() { - if (game.revolutions.every(n => n === false)) { - view.prompt = 'Shock Therapy: no countries to choose.' - gen_action('pass') - } else { - if (game.vm_active_country === '' ) { - view.prompt = 'Shock Therapy: choose a country where you hold Power:' - if (game.revolutions[0]) {gen_action('poland')} - if (game.revolutions[1]) {gen_action('hungary')} - if (game.revolutions[2]) {gen_action('east_germany')} - if (game.revolutions[3]) {gen_action('bulgaria')} - if (game.revolutions[4]) {gen_action('czechoslovakia')} - if (game.revolutions[5]) {gen_action('romania')} - } /*else if (game.phase === 2) { - view.prompt = 'Shock Therapy: done.' - gen_action('done') - } */ - else { - view.prompt = 'Shock Therapy: roll a die.' - gen_action('roll') - } - } - }, - east_germany() { - push_undo() - game.vm_active_country = 'East_Germany' - log(`Chose ${country_name(game.vm_active_country)}`) - }, - poland() { - push_undo() - game.vm_active_country = 'Poland' - log(`Chose ${country_name(game.vm_active_country)}`) - }, - czechoslovakia() { - push_undo() - game.vm_active_country = 'Czechoslovakia' - log(`Chose ${country_name(game.vm_active_country)}`) - }, - hungary() { - push_undo() - game.vm_active_country = 'Hungary' - log(`Chose ${country_name(game.vm_active_country)}`) - }, - romania() { - push_undo() - game.vm_active_country = 'Romania' - log(`Chose ${country_name(game.vm_active_country)}`) - }, - bulgaria () { - push_undo() - game.vm_active_country = 'Bulgaria' - log(`Chose ${country_name(game.vm_active_country)}`) - }, - roll() { - clear_undo() - let roll = Math.floor(Math.random() * 6) + 1 - let worker_farmer = 0 - for (let space of spaces) { - if (space && space.country === game.vm_active_country && check_com_control(space.space_id) && (space.socio === 3 || space.socio === 4)) { - worker_farmer++ - } - } - log(`Roll: D${roll}`) - log(`-${worker_farmer} from Communist controlled Worker and Farmer spaces`) - log(`Modified roll: ${roll - worker_farmer}`) - if ((roll - worker_farmer) > 2) { - log('C93 is successful. +3 VP') - vm_next() - } else { - log('C93 is unsuccessful. Required 3 or more') - //game.phase++ - permanently_remove(93) - vm_return() - } - }, - pass() { - log('Passed') - vm_return() - } - /*done() { - permanently_remove(93) - vm_return() - }*/ -} - -states.vm_social_democratic_platform_adopted = { - get inactive() { - return `resolve ${clean_name(cards[game.played_card].name)}.` - }, - prompt() { - if (game.revolutions.every(n => n === false)) { - view.prompt = 'Social Democratic Platform Adopted: no countries to choose.' - gen_action('pass') - } else { - view.prompt = 'Select a country where the Democrat holds Power.' - if (game.revolutions[0]) {gen_action('poland')} - if (game.revolutions[1]) {gen_action('hungary')} - if (game.revolutions[2]) {gen_action('east_germany')} - if (game.revolutions[3]) {gen_action('bulgaria')} - if (game.revolutions[4]) {gen_action('czechoslovakia')} - if (game.revolutions[5]) {gen_action('romania')} - } - }, - east_germany() { - push_undo() - game.vm_active_country = 'East_Germany' - log(`Selected ${country_name(game.vm_active_country)}`) - vm_next() - }, - poland() { - push_undo() - game.vm_active_country = 'Poland' - log(`Selected ${country_name(game.vm_active_country)}`) - vm_next()}, - czechoslovakia() { - push_undo() - game.vm_active_country = 'Czechoslovakia' - log(`Selected ${country_name(game.vm_active_country)}`) - vm_next()}, - hungary() { - push_undo() - game.vm_active_country = 'Hungary' - log(`Selected ${country_name(game.vm_active_country)}`) - vm_next() - }, - romania() { - push_undo() - game.vm_active_country = 'Romania' - log(`Selected ${country_name(game.vm_active_country)}`) - vm_next() - }, - bulgaria () { - push_undo() - game.vm_active_country = 'Bulgaria' - log(`Selected ${country_name(game.vm_active_country)}`) - vm_next() - }, - pass() { - log('Passed') - vm_return() - } -} - -states.vm_systematization = { - get inactive() { - return `resolve ${clean_name(cards[game.played_card].name)}.` - }, - prompt() { - /*if (game.systematization === 0) { */ - view.prompt = 'Systematization: eliminate a space in Romania.' - for (let space_id of game.valid_spaces) { - gen_action_infl(space_id); - } - /*} else { - view.prompt = 'Systematization: done.' - gen_action('done') - }*/ - }, - infl(space) { - push_undo() - vm_eliminate(space) - game.valid_spaces = [] - game.systematization = space - game.persistent_events.push(69) - vm_next() - }, -/* done() { - vm_next() - } */ -} - -states.vm_the_chinese_solution = { - get inactive() { - return `resolve ${clean_name(cards[game.played_card].name)}.` - }, - prompt() { - view.prompt = 'The Chinese Solution: you may give up 3 VP to conduct support checks in a country where you hold power.' - if (!game.revolutions[0]) {gen_action('poland')} - if (!game.revolutions[1]) {gen_action('hungary')} - if (!game.revolutions[2]) {gen_action('east_germany')} - if (!game.revolutions[3]) {gen_action('bulgaria')} - if (!game.revolutions[4]) {gen_action('czechoslovakia')} - if (!game.revolutions[5]) {gen_action('romania')} - gen_action('pass') - }, - east_germany() { - push_undo() - game.vm_active_country = 'East_Germany' - log(`Chose ${country_name(game.vm_active_country)}`) - log('+3 VP') - game.vp += 3 - if (check_vp()) { - return - } - vm_next() - }, - poland() { - push_undo() - game.vm_active_country = 'Poland' - log(`Chose ${country_name(game.vm_active_country)}`) - log('+3 VP') - game.vp += 3 - if (check_vp()) { - return - } - vm_next() - }, - czechoslovakia() { - push_undo() - game.vm_active_country = 'Czechoslovakia' - log(`Chose ${country_name(game.vm_active_country)}`) - log('+3 VP') - game.vp += 3 - if (check_vp()) { - return - } - vm_next() - }, - hungary() { - push_undo() - game.vm_active_country = 'Hungary' - log(`Chose ${country_name(game.vm_active_country)}`) - log('+3 VP') - game.vp += 3 - if (check_vp()) { - return - } - vm_next() - }, - romania() { - push_undo() - game.vm_active_country = 'Romania' - log(`Chose ${country_name(game.vm_active_country)}`) - log('+3 VP') - game.vp += 3 - if (check_vp()) { - return - } - vm_next() - }, - bulgaria () { - push_undo() - game.vm_active_country = 'Bulgaria' - log(`Chose ${country_name(game.vm_active_country)}`) - log('+3 VP') - game.vp += 3 - if (check_vp()) { - return - } - vm_next() - }, - pass() { - push_undo() - permanently_remove(96) - vm_return() - } -} - -states.vm_the_tyrant_is_gone = { - get inactive() { - return `resolve ${clean_name(cards[game.played_card].name)}.` - }, - prompt() { - if (!game.the_tyrant_is_gone) { - view.prompt = 'The Tyrant is Gone: Select a space in Romania for the Ceausescus to flee to.' - for (let space_id of game.valid_spaces) { - if (!space_id) continue - gen_action_infl(space_id); - } - } else { - view.prompt = 'The Tyrant is Gone: done.' - gen_action('done') - } - }, - infl(space) { - push_undo() - log(`The Ceausescus flee to %${space}`) - game.the_tyrant_is_gone = space - game.valid_spaces = [] - game.persistent_events.push(97) - - // vm_next() - }, - done () { - vm_next() - } -} -/* -states.vm_tyrant_block ={ - get inactive() { - return `resolve ${clean_name(cards[this_card()].name)}.` - }, - prompt() { - view.prompt = `${clean_name(cards[this_card()].name)} has no effect after The Tyrant Has Gone.` - gen_action('done') - }, - done() { - push_undo() - vm_next() - } -}*/ - - -states.vm_the_wall_must_go = { - get inactive() { - return `resolve ${clean_name(cards[this_card()].name)}.` - }, - prompt() { - /*if (game.the_wall_must_go['dem_wins'] === 2 || game.the_wall_must_go['com_wins'] === 2) { - view.prompt = '"The Wall Must Go!" Rolls: done.' - gen_action('done') - } else { */ - view.prompt = ('The Wall Must Go! Roll a die.') - gen_action('roll') - //} - }, - roll() { - clear_undo() - let attempt = game.the_wall_must_go['dem_wins'] + game.the_wall_must_go['com_wins'] - if (game.the_wall_must_go['dem_roll'] === 0 && game.the_wall_must_go['com_roll'] === 0) { - log_h3(`Round ${attempt+1}`) - } - - let roll = Math.floor(Math.random() * 6) + 1 - log(`Roll: D${roll}`) - if (game.active === DEM) { - let controlled_spaces = spaces.filter(space => space && space.country === 'East_Germany' && check_dem_control(space.space_id)).length - if (controlled_spaces > 0) { - log(`+${controlled_spaces} from controlled spaces in East Germany`) - log(`Modified roll: ${roll + controlled_spaces}`) - roll += controlled_spaces - } - game.the_wall_must_go['dem_roll'] = roll - } else { - let controlled_spaces = spaces.filter(space => space && space.country === 'East_Germany' && check_com_control(space.space_id)).length - if (controlled_spaces > 0) { - log(`+${controlled_spaces} from controlled spaces in East Germany`) - log(`Modified roll: ${roll + controlled_spaces}`) - roll += controlled_spaces - } - game.the_wall_must_go['com_roll'] = roll - - } - if (game.the_wall_must_go['dem_roll'] > 0 && game.the_wall_must_go['com_roll'] > 0) { - if (game.the_wall_must_go['dem_roll'] > game.the_wall_must_go['com_roll'] ) { - log('Democrat wins') - game.the_wall_must_go['dem_wins']++ - } else if (game.the_wall_must_go['dem_roll'] === game.the_wall_must_go['com_roll'] ) { - log('Tie. Re-roll') - } else { - log('Communist wins') - game.the_wall_must_go['com_wins']++ - } - - log(`Democrat: ${game.the_wall_must_go['dem_wins']}, Communist: ${game.the_wall_must_go['com_wins']}`) - } - if (game.the_wall_must_go['dem_wins'] === 2) { - log('The Democrat wins C86') - finish_the_wall() - return - } - if (game.the_wall_must_go['com_wins'] === 2) { - log('The Communist wins C86') - finish_the_wall() - return - } - if (game.the_wall_must_go['dem_roll'] === 0 || game.the_wall_must_go['com_roll'] === 0) { - next_player() - } else { - game.the_wall_must_go['dem_roll'] = 0 - game.the_wall_must_go['com_roll'] = 0 - } - }, - /*done() { - if (game.the_wall_must_go['dem_wins'] === 2) { - game.persistent_events.push(86) - log('+3 VP') - game.vp += 3 - if (check_vp()) { - return - } - for (let i = 1; i < spaces.length; i++) { - let space = spaces[i] - if (space.country === 'East_Germany' && game.comInfl[i] > 0){ - game.valid_spaces.push(space.space_id) - } - } - if (!game.vm_infl_to_do) { - if (game.round_player === DEM) { - game.return = COM - } else { - game.return = DEM - } - } - if (game.active === DEM) {next_player()} - vm_next () - } else { - permanently_remove(86) - delete game.the_wall_must_go - vm_return() - } - }*/ -} - -states.vm_warsaw_pact_summit = { - get inactive() { - return `resolve ${clean_name(cards[game.played_card].name)}.` - }, - prompt() { - view.prompt = 'Choose to play for support checks or place SPs.' - gen_action('influence') - gen_action('support_check') - }, - influence(){ - push_undo() - for (let i = 1; i < spaces.length; i++) { - let space = spaces[i] - if (game.demInfl[i] === 0) { - game.valid_spaces.push(space.space_id); - } - } - game.vm_available_ops = 4 - game.phase = 3 - //game.state = 'vm_add_infl' - vm_next() - }, - support_check(){ - push_undo() - for (let i = 1; i < spaces.length; i++) { - let space = spaces[i] - if (game.demInfl[i] > 0 && (space.socio === 5 || space.socio === 6)) { - game.valid_spaces.push(space.space_id) - } - } - game.vm_available_ops = 2 - //game.state = 'vm_support_check_prep' - vm_next() - } -} - -states.vm_we_are_the_people_remove = { - get inactive() { - return `resolve ${clean_name(cards[game.played_card].name)}.` - }, - prompt() { - if (game.demInfl[6] === 0 && game.vm_available_ops > 0) { - view.prompt = '"We are the People!": no SPs to remove.' - gen_action('done') - } else if (game.vm_available_ops > 0 ) { - view.prompt = '"We are the People!": remove up to 4 SPs from the Lutherian Church.' - gen_action('done') - for (let space_id of game.valid_spaces) { - gen_action_infl(space_id); - } - } else { - view.prompt = '"We are the People!" Remove SPs: done.' - gen_action('done') - } - }, - infl(space) { - vm_do_remove_infl(space) - }, - done() { - if (game.summary.length > 0) { - pop_summary() - log_br() - } - if (!game.vm_influence_added[6]) { - log('No SPs removed') - vm_next() - } else { - game.valid_spaces = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] - game.state = 'vm_we_are_the_people_add' - } - } -} -states.vm_we_are_the_people_add = { - get inactive() { - return `resolve ${clean_name(cards[game.played_card].name)}.` - }, - prompt() { - /* if (!game.vm_influence_added[6]) { - view.prompt = '"We are the People!" Add SPs: done.' - gen_action('done') - return - }*/ - - view.prompt = `"We are the People!": you must add the ${pluralize(game.vm_influence_added[6],'SP')} to spaces in Germany.` - for (let space_id of game.valid_spaces) { - gen_action_infl(space_id); - } - }, - infl(space) { - vm_do_add_infl_free(space) - game.vm_influence_added[6]-- - if (game.vm_influence_added[6] === 0 ) { - game.valid_spaces = [] - if (game.summary.length > 0) { - pop_summary() - log_br() - } - vm_next() - } - }, - /*done() { - push_undo() - if (game.summary.length > 0) { - pop_summary() - log_br() - } - vm_next() - }*/ -} - -states.vm_workers_revolt = { - get inactive() { - return `resolve ${clean_name(cards[game.played_card].name)}.` - }, - prompt() { - if (game.valid_spaces.length === 0 ) { - view.prompt = 'Workers Revolt: no valid spaces to select.' - gen_action('pass') - return - } - view.prompt = 'Workers Revolt: select a Worker Space in a country your opponent has power.' - for (let space_id of game.valid_spaces) { - gen_action_infl(space_id) - } - }, - pass() { - push_undo() - vm_next() - }, - infl(space) { - push_undo() - game.selected_space = space - log(`Chose %${game.selected_space}`) - game.state = 'vm_workers_revolt_finish' - } -} - - -states.vm_workers_revolt_finish = { - get inactive() { - return `resolve ${clean_name(cards[game.played_card].name)}.` - }, - prompt() { - //if (game.selected_space > 0) { - view.prompt = `Target: ${spaces[game.selected_space].name_unique}. Roll a die.` - gen_action('roll') - /* } else { - view.prompt = 'Workers Revolt: done.' - gen_action('done') - }*/ - - }, - roll() { - clear_undo() - let roll = Math.floor(Math.random() * 6) + 1 - log(`Roll: D${roll}`) - let adj = count_adj(game.selected_space) - if (game.active === DEM) { - log(`-${adj.com_adj} from opponent controlled spaces`) - roll -= adj.com_adj - } else { - log(`-${adj.dem_adj} from opponent controlled spaces`) - roll -= adj.dem_adj - } - log(`Modified roll: ${roll}`) - if (roll >= 4) { - log('Workers Revolt successful') - vm_replace_all_infl(game.temp) - } else {log('Workers Revolt fails. Required 4 or more')} - game.selected_space = 0 - vm_next() - }, - /*done() { - vm_next() - }*/ -} - -// ==================== TIANANMEN SQUARE TRACK STATES ===================== - -states.vm_tst_3_prep = { - inactive: 'resolve Tiananmen Square Track award.', - prompt() { - view.prompt = 'Tiananmen Square Track award: draw 3 cards.' - gen_action('draw') - }, - draw() { - if (game.active === DEM) { - game.temp = game.democrat_hand.length - draw_cards(game.strategy_deck, game.democrat_hand, game.communist_hand, game.democrat_hand.length + 3, game.communist_hand.length) - game.valid_cards = [game.democrat_hand[game.temp], game.democrat_hand[game.temp + 1], game.democrat_hand[game.temp + 2]] - } else { - game.temp = game.communist_hand.length - draw_cards(game.strategy_deck, game.democrat_hand, game.communist_hand, game.democrat_hand.length, game.communist_hand.length + 3) - game.valid_cards = [game.communist_hand[game.temp], game.communist_hand[game.temp + 1], game.communist_hand[game.temp + 2]] - } - game.temp = 0 - game.state = 'vm_tst_3' - } -} - -states.vm_tst_3 = { - inactive: 'resolve Tiananmen Square Track bonus.', - prompt() { - if (game.temp < 2) { - view.prompt = `Discard 2 of the drawn cards.` - for (let card of game.valid_cards) { - gen_action_card(card) - } - } /*else { - view.prompt = 'Discard cards: done.' - gen_action('done') - }*/ - }, - card(card) { - push_undo() - discard(card) - game.temp ++ - if (game.temp === 2) { - game.valid_cards = [] - vm_next() - } - }, - /*done() { - vm_next() - }*/ -} - -states.vm_tst_4 = { - inactive: 'remove SPs', - prompt () { - if (game.vm_available_ops === 0 || game.valid_spaces.length === 0) { - view.prompt = 'Tiananmen Square Track award. Remove SPs: done.' - gen_action('done') - return - } - view.prompt = `Tiananmen Square Track award: remove ${pluralize(game.vm_available_ops,'SP')}.` - - for (let space_id of game.valid_spaces) { - gen_action_infl(space_id); - } - }, - infl(space) { - vm_do_remove_infl(space) - if (game.vm_available_ops === 0) { - if (game.summary.length > 0) { - pop_summary() - log_br() - } - vm_next() - } - }, - done() { - if (game.summary.length > 0) { - pop_summary() - log_br() - } - vm_next() - } -} - -states.vm_tst_6 = { - inactive: 'make their free support check.', - prompt() { - /* if (game.vm_available_ops === 0) { - view.prompt = 'Tiananmen Square Track award support check: done.' - gen_action('done') - return - } else {*/ - view.prompt = 'Tiananmen Square Track award: you have a free 2 Ops support check.' - for (let space_id of game.valid_spaces) { - if (space_id) { - gen_action_sc(space_id); - } - } - //} - }, - sc(space) { - push_undo() - game.selected_space = space - if (game.active === DEM && game.persistent_events.includes(58) && spaces[space].country === "East_Germany") { - game.austria_hungary_border_reopened_tracker = true - } - game.state = 'vm_tst_6_sc' - }, - /*done () { - push_undo() - vm_next() - }*/ -} - -states.vm_tst_6_sc = { - inactive: 'do support check.', - prompt () { - view.prompt = `Support check: ${spaces[game.selected_space].name_unique}. Roll a die` - gen_action('roll') - }, - roll() { - clear_undo() - do_sc(game.selected_space) - game.vm_available_ops-- - game.valid_spaces = [] - game.state = 'vm_tst_6' - vm_next() - return - } -} - -states.vm_tst_8 = { - inactive: 'use Tiananmen Square Track award.', - prompt() { - if (game.vm_event_to_do && game.vm_infl_to_do) { - view.prompt = 'Choose whether to play for event or operations first.' - gen_action('event') - gen_action('ops') - } - else if (!game.vm_event_to_do && game.vm_infl_to_do) { - view.prompt = 'Event resolved. Use card for operations.' - gen_action('ops') - } - else if (game.vm_event_to_do && !game.vm_infl_to_do) { - view.prompt = 'Operations resolved. Use card for event.' - gen_action('event') - } - else if (!game.vm_event_to_do && !game.vm_infl_to_do) { - view.prompt = 'Event and operations: done.' - gen_action('end_round') - } - }, - event() { - push_undo() - log('Event') - game.vm_event_to_do = false - game.return_state = 'vm_tst_8' - game.return = game.active - game.vm_event = game.played_card - goto_vm(game.vm_event) - }, - ops() { - push_undo() - log('Operations') - game.vm_infl_to_do = false - game.return = game.active - game.return_state = 'vm_tst_8' - goto_vm(208) - }, - end_round() { - push_undo() - game.tst_8 = true - end_round() - } -} - - -states.vm_tst_8_ops = { - inactive: 'play card for operations.', - prompt() { - view.prompt = `Play ${clean_name(cards[game.played_card].name)} for:` - gen_action('influence') - gen_action('support_check') - if ((game.active === DEM && game.dem_tst_attempted_this_turn === 0 ) || (game.active === COM && game.com_tst_attempted_this_turn === 0 )) { - gen_action('tst') - } - }, - influence(){ - push_undo() - game.vm_available_ops = cards[game.played_card].ops - valid_spaces_infl() - // If ABHR - Set AHBR tracker to true - if (game.persistent_events.includes(58)) { - game.austria_hungary_border_reopened_tracker = true - } - game.state = 'vm_add_infl' - }, - support_check() { - push_undo() - game.vm_available_ops = 2 - game.state = 'vm_support_check_prep' - }, - tst() { - push_undo() - game.state = 'vm_tiananmen_square_attempt' - } -} - -// ========================= POWER STRUGGLE STATES ======================== - -states.vm_scare_tactics = { - inactive: 'remove a Support Point.', - prompt () { - if (game.valid_spaces.length === 0 && game.vm_available_ops > 0) { - view.prompt = `${clean_name(cards[this_card()].name)}: no SPs to remove.` - gen_action('done') - return - } - if (game.vm_available_ops === 0 ) { - view.prompt = `${clean_name(cards[this_card()].name)}. Remove SPs: done.` - gen_action('done') - return - } - view.prompt = `${clean_name(cards[this_card()].name)}: remove ${pluralize(game.vm_available_ops, 'opponent SP')}${event_prompt()}.` - for (let space_id of game.valid_spaces) { - gen_action_infl(space_id); - } - }, - infl(space) { - push_undo() - vm_do_remove_infl(space) - }, - done() { - if (game.summary.length > 0) { - pop_summary() - log_br() - } - vm_next() - } -} - -states.vm_support_surges_1 = { - inactive: 'draw cards.', - prompt() { - view.prompt = 'Support Surges: draw a card.' - gen_action('draw') - }, - draw() { - if (game.active === DEM) { - //console.log('hand before', game.dem_pwr_hand) - draw_cards(game.power_struggle_deck, game.dem_pwr_hand, game.com_pwr_hand, game.dem_pwr_hand.length+1, game.com_pwr_hand.length) - game.temp = game.dem_pwr_hand[game.dem_pwr_hand.length-1] - //console.log('hand after', game.dem_pwr_hand, 'game.temp', game.temp) - } else { - //console.log('hand before', game.com_pwr_hand) - draw_cards(game.power_struggle_deck, game.dem_pwr_hand, game.com_pwr_hand, game.dem_pwr_hand.length, game.com_pwr_hand.length+1) - game.temp = game.com_pwr_hand[game.com_pwr_hand.length-1] - //console.log('hand after', game.com_pwr_hand, 'game.temp', game.temp) - } - game.state = 'vm_support_surges_2' - - //game.phase = 0 - //log('Drew 2 cards') - //log('Surrenders initiative') - //vm_next() - } -} - -states.vm_support_surges_2 = { - inactive: 'draw cards.', - prompt() { - let special = [49,50,51,52] - let elite_leader = [37,38,39,40] - if (special.includes(game.temp)) { - view.prompt = `Support Surges: you drew ${power_cards[game.temp].name}. Draw a second card.` - } - else if (elite_leader.includes(game.temp)) { - view.prompt = `Support Surges: you drew an ${power_cards[game.temp].name}. Draw a second card.` - } - else if (numberless_cards.includes(game.temp)) { - view.prompt = `Support Surges: you drew a ${power_cards[game.temp].name}. Draw a second card.` - } else { - view.prompt = `Support Surges: you drew a ${power_cards[game.temp].name} ${power_cards[game.temp].value}. Draw a second card.` - } - gen_action('draw') - }, - draw() { - if (game.active === DEM) { - draw_cards(game.power_struggle_deck, game.dem_pwr_hand, game.com_pwr_hand, game.dem_pwr_hand.length+1, game.com_pwr_hand.length) - game.temp = game.dem_pwr_hand[game.dem_pwr_hand.length - 1] - } else { - draw_cards(game.power_struggle_deck, game.dem_pwr_hand, game.com_pwr_hand, game.dem_pwr_hand.length, game.com_pwr_hand.length+1) - game.temp = game.com_pwr_hand[game.com_pwr_hand.length - 1] - } - game.state = 'vm_support_surges_3' - /*game.phase = 0 - log('Drew 2 cards') - log('Surrenders initiative') - vm_next()*/ - } -} - -states.vm_support_surges_3 = { - inactive: 'draw cards.', - prompt() { - if (numberless_cards.includes(game.temp)) { - view.prompt = `Support Surges: you drew ${power_cards[game.temp].name}. Done.` - } else { - view.prompt = `Support Surges: you drew a ${power_cards[game.temp].name} ${power_cards[game.temp].value}. Done.` - } - gen_action('done') - }, - done() { - game.phase = 0 - delete game.temp - log('Drew 2 cards') - log('Surrenders initiative') - vm_next() - } -} - -states.vm_support_falters = { - inactive: 'discard cards.', - prompt() { - if ((game.active === DEM && game.dem_pwr_hand.length === 0) || (game.active === COM && game.com_pwr_hand.length === 0)) { - view.prompt = 'Support Falters: no remaining cards to discard.' - gen_action('pass') - } else if (game.vm_available_ops > 0) { - view.prompt = 'Support Falters: discard a card.' - gen_action('discard') - } else { - view.prompt = 'Support Falters: done.' - gen_action('done') - } - }, - discard() { - if (game.active === DEM) {discard_card(game.dem_pwr_hand)} - else {discard_card(game.com_pwr_hand)} - game.vm_available_ops -- - }, - pass() { - log_msg_gap('Takes initiative') - game.return = game.active - vm_next() - }, - done() { - log_gap('Takes initiative') - game.return = game.active - vm_next() - } -} - -/* =================== EVENTS ================================ */ - -// #region GENERATED EVENT CODE -const CODE = [] - -CODE[1] = [ // Legacy of Martial Law* - [ vm_permanently_remove ], - [ vm_valid_spaces_country_opp, 'Poland' ], - [ vm_prompt, 'replace 1 Democratic SP in Poland with a Communist SP' ], - [ vm_legacy_of_martial_law ], - [ vm_valid_spaces_country_sc, 'Poland' ], - [ vm_prompt, 'make a Support Check in Poland' ], - [ vm_1_support_check ], - [ vm_return ], -] - -CODE[2] = [ // Solidarity Legalised* - [ vm_permanently_remove ], - [ vm_solidarity_legalised ], - [ vm_valid_spaces_solidarity_legalised ], - [ vm_prompt, 'to every uncontrolled Worker and Farmer space in Poland' ], - [ vm_add_limited_infl, 9, 1 ], - [ vm_return ], -] - -CODE[3] = [ // Walesa - [ vm_permanently_remove ], - [ vm_valid_spaces_country, 'Poland' ], - [ vm_prompt, 'any space(s) in Poland' ], - [ vm_add_infl_free, 4 ], - [ vm_valid_spaces_country_sc, 'Poland' ], - [ vm_prompt, 'make Support Checks in Poland' ], - [ vm_support_check, 2 ], - [ vm_return ], -] - -CODE[4] = [ // Michnik - [ vm_permanently_remove ], - [ vm_valid_spaces, 26 ], - [ vm_prompt, 'the Polish Intellectuals space' ], - [ vm_add_x_infl, 3 ], - [ vm_return ], -] - -CODE[5] = [ // General strike - [ vm_general_strike ], - [ vm_return ], -] - -CODE[6] = [ // Brought in for Questioning - [ vm_brought_in_for_questioning ], - [ vm_return ], -] - -CODE[7] = [ // State Run Media* - [ vm_permanently_remove ], - [ vm_valid_spaces_opponent ], - [ vm_remove_limited_opp_infl, 4, 2 ], - [ vm_return ], -] - -CODE[8] = [ // Prudence - [ vm_prudence ], - [ vm_return ], -] - -CODE[9] = [ // The Wall* - [ vm_permanently_remove ], - [ vm_the_wall ], - [ vm_return ], -] - -CODE[10] = [ // Cult of Personality - [ vm_permanently_remove ], - [ vm_if, ()=>!game.the_tyrant_is_gone ], - [ vm_valid_spaces_country_socio_2, 'Romania', 3, 4 ], - [ vm_prompt, 'Worker or Farmer spaces in Romania, no more than 2 per space' ], - [ vm_add_limited_infl, 4, 2 ], - [ vm_else ], - [ vm_tyrant_block ], - [ vm_endif ], - [ vm_return ], -] - -CODE[11] = [ // Dissident arrested - [ vm_valid_spaces_opponent_socio, 5 ], - [ vm_prompt, 'any Intellectuals space' ], - [ vm_remove_x_opp_infl, 2 ], - [ vm_return ], -] - -CODE[12] = [ // Apparatchicks - [ vm_permanently_remove ], - [ vm_valid_spaces_socio, 2 ], - [ vm_prompt, ' to any Bureaucratic space(s)' ], - [ vm_add_infl_free, 3 ], - [ vm_return ], -] - -CODE[13] = [ // Stasi - [ vm_permanently_remove ], - [ vm_stasi ], - [ vm_return ], -] - -CODE[14] = [ // Gorbachev Charms the West - [ vm_valid_spaces_opponent ], - [ vm_remove_opp_infl, 2 ], - [ vm_valid_spaces_sc ], - [ vm_prompt, 'select a space for the Support Check' ], - [ vm_1_support_check ], - [ vm_return ], -] - -CODE[15] = [ // Honecker - [ vm_permanently_remove ], - [ vm_honecker ], - [ vm_return ], -] - -CODE[16] = [ // Nomenklatura* - [ vm_permanently_remove ], - [ vm_nomenklatura ], - [ vm_return ], -] - -CODE[17] = [ // Roundtable talks - [ vm_roundtable_talks ], - [ vm_return ], -] - -CODE[18] = [ // Poszgay Defends the Revolution - [ vm_permanently_remove ], - [ vm_poszgay ], - [ vm_prompt, 'to 4 spaces in Hungary not under Democratic control' ], - [ vm_add_limited_infl, 4, 1 ], - [ vm_return ], -] - -CODE[19] = [ // Papal vist - [ vm_permanently_remove ], - [ vm_valid_spaces, 20, 35, 38 ], - [ vm_prompt, 'any Catholic Church space' ], - [ vm_add_x_infl, 3 ], - [ vm_return ], -] - -CODE[20] = [ // Deutsche Marks* - [ vm_permanently_remove ], - [ vm_deutsche_marks ], - [ vm_return ], -] - -CODE[21] = [ // Common European Home - [ vm_common_european_home ], - [ vm_return ], -] - -CODE[22] = [ // Power Struggle - Poland - [ vm_power_struggle ], - [ vm_return ], -] - -CODE[23] = [ // Power Struggle - Hungary - [ vm_power_struggle ], - [ vm_return ], -] - -CODE[24] = [ // St Nicolas Church - [ vm_permanently_remove ], - [ vm_valid_spaces, 6 ], - [ vm_prompt, 'the Lutheran Church' ], - [ vm_take_control_prep, 1 ], - [ vm_st_nicholas_church ], - [ vm_return ], -] - -CODE[25] = [ // Perestroika - [ vm_permanently_remove ], - [ vm_perestroika ], - [ vm_return ], -] - -CODE[26] = [ // Helsinki Final Act* - [ vm_permanently_remove ], - [ vm_helsinki_final_act ], - [ vm_return ], -] - -CODE[27] = [ // Consumerism - [ vm_valid_spaces_opponent_socio, 4 ], - [ vm_prompt, ' from a Worker space' ], - [ vm_remove_opp_infl, 1 ], - [ vm_valid_spaces_opponent_socio, 4 ], - [ vm_active_country ], - [ vm_prompt, ()=>`make a support check in a Worker space in ${country_name(game.vm_active_country)}` ], - [ vm_1_support_check ], - [ vm_return ], -] - -CODE[28] = [ // Factory Party Cells - [ vm_valid_spaces_opponent_socio, 4 ], - [ vm_prompt, ' from Worker spaces' ], - [ vm_remove_limited_opp_infl, 3, 2 ], - [ vm_return ], -] - -CODE[29] = [ // Jan Palach Week* - [ vm_permanently_remove ], - [ vm_valid_spaces, 30 ], - [ vm_prompt, 'the Charles University space' ], - [ vm_add_x_infl, 6 ], - [ vm_return ], -] - -CODE[30] = [ // Tear Gas - [ vm_tear_gas ], - [ vm_return ], -] - -CODE[31] = [ // Intelligentsia - [ vm_valid_spaces, 4, 26, 31, 46, 55, 73 ], - [ vm_prompt, 'Intellectual spaces, no more than 2 per space' ], - [ vm_add_limited_infl, 4, 2 ], - [ vm_return ], -] - -CODE[32] = [ // Peasant Parties* - [ vm_permanently_remove ], - [ vm_valid_spaces_socio, 3 ], - [ vm_prompt, 'Farmer spaces, no more than 2 per space' ], - [ vm_add_limited_infl, 4, 2 ], - [ vm_return ], -] - -CODE[33] = [ // Sajudis* - [ vm_permanently_remove ], - [ vm_sajudis_check ], - [ vm_prompt, 'any Minorities space' ], - [ vm_take_control_prep, 1 ], - [ vm_sajudis ], - [ vm_return ], -] - -CODE[34] = [ // Fidesz* - [ vm_permanently_remove ], - [ vm_valid_spaces, 47 ], - [ vm_prompt, 'the Hungary students space' ], - [ vm_add_x_infl, 5 ], - [ vm_return ], -] - -CODE[35] = [ // Heal our Bleeding Wounds* - [ vm_permanently_remove ], - [ vm_heal_our_bleeding_wounds ], - [ vm_return ], -] - -CODE[36] = [ // Dash for the West* - [ vm_permanently_remove ], - [ vm_prompt, 'Dash for the West: select any Democratic event with an asterix(*) from the discard pile. Event occurs immediately' ], - [ vm_dash_for_the_west ], - [ vm_return ], -] - -CODE[37] = [ // Nagy Reburied* - [ vm_permanently_remove ], - [ vm_nagy_reburied ], - [ vm_prompt, 'the Hungary Elite space' ], - [ vm_remove_all_infl, 1 ], - [ vm_valid_spaces_country, 'Hungary' ], - [ vm_prompt, 'Hungary, no more than 2 per space' ], - [ vm_add_limited_infl, 4, 2 ], - [ vm_return ], -] - -CODE[38] = [ // July Concept - [ vm_permanently_remove ], - [ vm_valid_spaces_country, 'Bulgaria' ], - [ vm_prompt, 'Bulgaria' ], - [ vm_add_infl_free, 3 ], - [ vm_return ], -] - -CODE[39] = [ // Eco-Glasnost* - [ vm_permanently_remove ], - [ vm_valid_spaces, 66 ], - [ vm_prompt, 'Ruse' ], - [ vm_add_x_infl, 4 ], - [ vm_eco_glasnost ], - [ vm_return ], -] - -CODE[40] = [ // Hungarian Democratic Forum - [ vm_permanently_remove ], - [ vm_valid_spaces_country, 'Hungary' ], - [ vm_prompt, 'Hungary' ], - [ vm_add_infl_free, 3 ], - [ vm_valid_spaces_country_sc, 'Hungary' ], - [ vm_prompt, 'make a Support Check in Hungary' ], - [ vm_1_support_check ], - [ vm_return ], -] - -CODE[41] = [ // Ceausescu* - [ vm_permanently_remove ], - [ vm_if, ()=>!game.the_tyrant_is_gone ], - [ vm_valid_spaces_country_opp, 'Romania' ], - [ vm_prompt, ' from Romania' ], - [ vm_remove_opp_infl, 3 ], - [ vm_valid_spaces_country_sc, 'Romania' ], - [ vm_prompt, 'make a support check in Romania' ], - [ vm_1_support_check ], - [ vm_prompt, ' from Bucharesti' ], - [ vm_ceausescu ], - [ vm_else ], - [ vm_tyrant_block ], - [ vm_endif ], - [ vm_return ], -] - -CODE[42] = [ // Power Struggle - East Germany - [ vm_power_struggle ], - [ vm_return ], -] - -CODE[43] = [ // Power Struggle - Bulgaria - [ vm_power_struggle ], - [ vm_return ], -] - -CODE[44] = [ // Inflationary Currency - [ vm_permanently_remove ], - [ vm_inflationary_currency ], - [ vm_valid_spaces_country_opp ], - [ vm_prompt, ()=>` from ${country_name(game.vm_active_country)}` ], - [ vm_remove_opp_infl, 2 ], - [ vm_inflationary_currency_discard ], - [ vm_if, ()=>!discarded_card() ], - [ vm_valid_spaces_country_sc ], - [ vm_prompt, ()=>`make a Support Check in ${country_name(game.vm_active_country)}` ], - [ vm_1_support_check ], - [ vm_endif ], - [ vm_return ], -] - -CODE[45] = [ // Soviet Troop Withdrawals* - [ vm_permanently_remove ], - [ vm_valid_spaces_region_opp, 'Eastern Europe' ], - [ vm_prompt, ' from Eastern Europe' ], - [ vm_remove_limited_opp_infl, 5, 2 ], - [ vm_return ], -] - -CODE[46] = [ // Goodbye Lenin!* - [ vm_permanently_remove ], - [ vm_goodbye_lenin ], - [ vm_return ], -] - -CODE[47] = [ // Bulgarian Turks Expelled* - [ vm_permanently_remove ], - [ vm_bulgarian_turks_expelled ], - [ vm_prompt, 'Razgrad' ], - [ vm_remove_all_infl, 1 ], - [ vm_return ], -] - -CODE[48] = [ // We are the People!* - [ vm_permanently_remove ], - [ vm_we_are_the_people ], - [ vm_return ], -] - -CODE[49] = [ // Foreign Currency Debt Burden* - [ vm_permanently_remove ], - [ vm_foreign_currency_debt_burden ], - [ vm_return ], -] - -CODE[50] = [ // The Sinatra Doctrine* - [ vm_permanently_remove ], - [ vm_the_sinatra_doctrine ], - [ vm_return ], -] - -CODE[51] = [ // 40th Anniversary Celebration* - [ vm_permanently_remove ], - [ vm_40th_anniversary_celebration ], - [ vm_valid_spaces_country, 'East_Germany' ], - [ vm_prompt, 'East Germany' ], - [ vm_add_infl_free ], - [ vm_40th_anniversary_celebration_vp ], - [ vm_return ], -] - -CODE[52] = [ // Normalisation - [ vm_permanently_remove ], - [ vm_normalisation ], - [ vm_prompt, 'the Czechoslovakia Elite and Bureaucrat Spaces' ], - [ vm_remove_all_infl, 2 ], - [ vm_return ], -] - -CODE[53] = [ // Li Peng* - [ vm_permanently_remove ], - [ vm_li_peng ], - [ vm_return ], -] - -CODE[54] = [ // The Crowd Turns Against Ceausescu* - [ vm_the_crowd_turns_against_ceausescu ], - [ vm_return ], -] - -CODE[55] = [ // Power Struggle - Czechoslovakia - [ vm_power_struggle ], - [ vm_return ], -] - -CODE[56] = [ // Foreign Television - [ vm_permanently_remove ], - [ vm_foreign_television ], - [ vm_remove_limited_opp_infl, 4, 2 ], - [ vm_return ], -] - -CODE[57] = [ // Central Committee Reshuffle* - [ vm_permanently_remove ], - [ vm_central_committee_reshuffle ], - [ vm_prompt, ()=>`${country_name(game.vm_active_country)}` ], - [ vm_add_infl_free, 3 ], - [ vm_return ], -] - -CODE[58] = [ // Austria-Hungary Border Reopened* - [ vm_austria_hungary_border_reopened ], - [ vm_return ], -] - -CODE[59] = [ // GrenzTruppen* - [ vm_grenztruppen ], - [ vm_return ], -] - -CODE[60] = [ // Toxic Waste* - [ vm_permanently_remove ], - [ vm_valid_spaces_socio, 4 ], - [ vm_prompt, 'any Worker space(s)' ], - [ vm_add_infl_free, 3 ], - [ vm_return ], -] - -CODE[61] = [ // The Monday Demonstrations* - [ vm_permanently_remove ], - [ vm_the_monday_demonstrations ], - [ vm_prompt, 'the Lutheran Church Space and Leipzig' ], - [ vm_take_control_prep, 2 ], - [ vm_valid_spaces_country_sc, 'East_Germany' ], - [ vm_prompt, 'make 5 Support Checks in East Germany' ], - [ vm_support_check, 5 ], - [ vm_return ], -] - -CODE[62] = [ // Yakovlev Counsels Gorbachev* - [ vm_yakovlev_counsels_gorbachev ], - [ vm_return ], -] - -CODE[63] = [ // Genscher* - [ vm_genscher ], - [ vm_return ], -] - -CODE[64] = [ // Legacy of 1968* - [ vm_permanently_remove ], - [ vm_legacy_of_1968 ], - [ vm_prompt, 'all spaces in Czechoslovakia not controlled by the Communist Player' ], - [ vm_add_limited_infl, 11, 1 ], - [ vm_return ], -] - -CODE[65] = [ // Presidential Visit* - [ vm_permanently_remove ], - [ vm_presidential_visit ], - [ vm_return ], -] - -CODE[66] = [ // New Forum - [ vm_permanently_remove ], - [ vm_valid_spaces_country, 'East_Germany' ], - [ vm_prompt, '3 spaces in East Germany' ], - [ vm_add_limited_infl, 3, 1 ], - [ vm_return ], -] - -CODE[67] = [ // Reformer Rehabilitated* - [ vm_prompt, 'Reformer Rehabilitated: chose any non-scoring card in the discard pile. Event takes place immediately' ], - [ vm_reformer_rehabilitated ], - [ vm_return ], -] - -CODE[68] = [ // Klaus and Komarek* - [ vm_permanently_remove ], - [ vm_klaus_and_komarek ], - [ vm_prompt, 'Prague' ], - [ vm_remove_x_opp_infl, 2 ], - [ vm_valid_spaces, 29 ], - [ vm_add_x_infl, 2 ], - [ vm_return ], -] - -CODE[69] = [ // Systematization* - [ vm_permanently_remove ], - [ vm_valid_spaces_country, 'Romania' ], - [ vm_systematization ], - [ vm_return ], -] - -CODE[70] = [ // Securitate* - [ vm_securitate ], - [ vm_return ], -] - -CODE[71] = [ // Kiss of Death* - [ vm_permanently_remove ], - [ vm_kiss_of_death ], - [ vm_return ], -] - -CODE[72] = [ // Peasant Parties Revolt - [ vm_peasant_parties_revolt ], - [ vm_return ], -] - -CODE[73] = [ // Laszlo Tokes* - [ vm_permanently_remove ], - [ vm_valid_spaces, 50, 56 ], - [ vm_prompt, 'in Timisoara and Harghita/Covasna' ], - [ vm_add_limited_infl, 2, 1 ], - [ vm_laszlo_tokes ], - [ vm_if, ()=>game.phase === 3 ], - [ vm_prompt, ' in Romania' ], - [ vm_add_infl ], - [ vm_else ], - [ vm_prompt, 'make 2 Support Checks in Romania' ], - [ vm_support_check, 2 ], - [ vm_endif ], - [ vm_return ], -] - -CODE[74] = [ // FRG Embassies - [ vm_frg_embassies ], - [ vm_return ], -] - -CODE[75] = [ // Exit Visas* - [ vm_permanently_remove ], - [ vm_exit_visas ], - [ vm_return ], -] - -CODE[76] = [ // Warsaw Pact Summit - [ vm_permanently_remove ], - [ vm_warsaw_pact_summit ], - [ vm_if, ()=>game.phase === 3 ], - [ vm_prompt, ' spaces with no Democratic SPs' ], - [ vm_add_infl_free, 4 ], - [ vm_else ], - [ vm_prompt, 'Select a Student or Intellectual space' ], - [ vm_valid_spaces_country_socio_2, 3,, 4 ], - [ vm_support_check_modified, 2, 2 ], - [ vm_endif ], - [ vm_return ], -] - -CODE[77] = [ // Samizdat - [ vm_permanently_remove ], - [ vm_samizdat ], - [ vm_return ], -] - -CODE[78] = [ // Workers Revolt - [ vm_workers_revolt ], - [ vm_return ], -] - -CODE[79] = [ // The Third Way* - [ vm_permanently_remove ], - [ vm_the_third_way ], - [ vm_valid_spaces, 4 ], - [ vm_prompt, 'the East German Writers space' ], - [ vm_add_x_infl, 3 ], - [ vm_return ], -] - -CODE[80] = [ // Nepotism* - [ vm_permanently_remove ], - [ vm_nepotism ], - [ vm_valid_spaces_region_socio, 'Balkans', 4 ], - [ vm_prompt, 'Worker spaces in the Balkans' ], - [ vm_add_infl_free ], - [ vm_return ], -] - -CODE[81] = [ // The Baltic Way* - [ vm_permanently_remove ], - [ vm_the_baltic_way ], - [ vm_prompt, 'any Minorities space' ], - [ vm_take_control_prep, 1 ], - [ vm_return ], -] - -CODE[82] = [ // Spitzel* - [ vm_permanently_remove ], - [ vm_valid_spaces_country_opp, 'East_Germany' ], - [ vm_prompt, ' from East Germany' ], - [ vm_remove_opp_infl, 2 ], - [ vm_return ], -] - -CODE[83] = [ // Modrow* - [ vm_permanently_remove ], - [ vm_modrow ], - [ vm_valid_spaces_country, 'East_Germany' ], - [ vm_prompt, 'East Germany, no more than 2 per space' ], - [ vm_add_limited_infl, 4, 2 ], - [ vm_return ], -] - -CODE[84] = [ // Breakaway Baltic Republics* - [ vm_permanently_remove ], - [ vm_breakaway_baltic_republics ], - [ vm_prompt, 'any Minorities space' ], - [ vm_take_control_prep, 1 ], - [ vm_valid_spaces_sc ], - [ vm_prompt, 'select a space for the support check' ], - [ vm_1_support_check ], - [ vm_return ], -] - -CODE[85] = [ // Tank Column/Tank Man* - [ vm_permanently_remove ], - [ vm_tank_column ], - [ vm_return ], -] - -CODE[86] = [ // The Wall Must Go!* - [ vm_permanently_remove ], - [ vm_the_wall_must_go ], - [ vm_remove_infl, 3 ], - [ vm_return ], -] - -CODE[87] = [ // Kohl Proposes Reunification* - [ vm_permanently_remove ], - [ vm_kohl_proposes_reunification ], - [ vm_return ], -] - -CODE[88] = [ // Adamec* - [ vm_permanently_remove ], - [ vm_adamec ], - [ vm_valid_spaces_country, 'Czechoslovakia' ], - [ vm_prompt, 'Czechoslovakia' ], - [ vm_add_limited_infl, 4, 2 ], - [ vm_return ], -] - -CODE[89] = [ // Domino Theory* - [ vm_prompt, 'Domino Theory: choose a Power Struggle card to play from the discard pile' ], - [ vm_permanently_remove ], - [ vm_domino_theory ], - [ vm_return ], -] - -CODE[90] = [ // Civic Forum* - [ vm_permanently_remove ], - [ vm_valid_spaces_country, 'Czechoslovakia' ], - [ vm_prompt, 'Czechoslovakia' ], - [ vm_add_infl_free, 4 ], - [ vm_civic_forum ], - [ vm_valid_spaces_country_sc, 'Czechoslovakia' ], - [ vm_prompt, 'Select a space in Czechoslovakia' ], - [ vm_support_check, 2 ], - [ vm_return ], -] - -CODE[91] = [ // My First Banana* - [ vm_permanently_remove ], - [ vm_valid_spaces_country_opp, 'East_Germany' ], - [ vm_prompt, ' from East Germany' ], - [ vm_remove_opp_infl, 2 ], - [ vm_valid_spaces_country_sc, 'East_Germany' ], - [ vm_prompt, 'select a space in East Germany' ], - [ vm_support_check, 2 ], - [ vm_return ], -] - -CODE[92] = [ // Betrayal - [ vm_permanently_remove ], - [ vm_prompt, 'choose any Orthodox Church space. Replace all Democratic SPs with Communist SPs' ], - [ vm_betrayal ], - [ vm_return ], -] - -CODE[93] = [ // Shock Therapy* - [ vm_permanently_remove ], - [ vm_shock_therapy ], - [ vm_valid_spaces_country ], - [ vm_prompt, ()=>` ${country_name(game.vm_active_country)}` ], - [ vm_add_infl_free, 3 ], - [ vm_return ], -] - -CODE[94] = [ // Union of Democratic Forces* - [ vm_permanently_remove ], - [ vm_valid_spaces_country_opp, 'Bulgaria' ], - [ vm_prompt, ' from Bulgaria' ], - [ vm_remove_opp_infl, 4 ], - [ vm_valid_spaces_country_sc, 'Bulgaria' ], - [ vm_prompt, 'Make 2 Support Checks in Bulgaria' ], - [ vm_support_check, 2 ], - [ vm_return ], -] - -CODE[95] = [ // Power Struggle - Romania - [ vm_power_struggle ], - [ vm_return ], -] - -CODE[96] = [ // The Chinese Solution* - [ vm_permanently_remove ], - [ vm_the_chinese_solution ], - [ vm_valid_spaces_country_sc ], - [ vm_prompt, ()=>`make 5 Support Checks in ${country_name(game.vm_active_country)}` ], - [ vm_support_check_modified, 5, 3 ], - [ vm_return ], -] - -CODE[97] = [ // The Tyrant is Gone* - [ vm_if, ()=>game.persistent_events.includes(54) ], - [ vm_valid_spaces, 51 ], - [ vm_prompt, 'the Romanian Elite Space' ], - [ vm_remove_x_opp_infl, 4 ], - [ vm_the_tyrant_is_gone ], - [ vm_permanently_remove ], - [ vm_else ], - [ vm_the_tyrant_is_gone_prep ], - [ vm_endif ], - [ vm_return ], -] - -CODE[98] = [ // Politburo Intrigue* - [ vm_permanently_remove ], - [ vm_valid_spaces_country_opp, 'Bulgaria' ], - [ vm_prompt, ' from Bulgaria' ], - [ vm_remove_limited_opp_infl, 3, 2 ], - [ vm_valid_spaces_country_sc, 'Bulgaria' ], - [ vm_prompt, 'make a support check in Bulgaria' ], - [ vm_1_support_check ], - [ vm_return ], -] - -CODE[99] = [ // Ligachev* - [ vm_permanently_remove ], - [ vm_ligachev ], - [ vm_return ], -] - -CODE[100] = [ // Stand Fast* - [ vm_permanently_remove ], - [ vm_stand_fast ], - [ vm_return ], -] - -CODE[101] = [ // Elena* - [ vm_permanently_remove ], - [ vm_if, ()=>!game.the_tyrant_is_gone ], - [ vm_valid_spaces, 51 ], - [ vm_prompt, 'the Romania Elite Space' ], - [ vm_add_x_infl, 2 ], - [ vm_elena ], - [ vm_else ], - [ vm_tyrant_block ], - [ vm_endif ], - [ vm_return ], -] - -CODE[102] = [ // National Salvation Front* - [ vm_national_salvation_front ], - [ vm_return ], -] - -CODE[103] = [ // Government Resigns* - [ vm_government_resigns ], - [ vm_prompt, 'any uncontrolled Elite space' ], - [ vm_remove_all_infl, 1 ], - [ vm_permanently_remove ], - [ vm_return ], -] - -CODE[104] = [ // New Year's Eve Party* - [ vm_new_years_eve_party ], - [ vm_return ], -] - -CODE[105] = [ // Public Against Violence* - [ vm_permanently_remove ], - [ vm_valid_spaces, 36 ], - [ vm_prompt, 'Kosice' ], - [ vm_add_x_infl, 2 ], - [ vm_valid_spaces, 37 ], - [ vm_prompt, 'Presov' ], - [ vm_add_x_infl, 2 ], - [ vm_public_against_violence ], - [ vm_prompt, 'Make a Support Check in Bratislava' ], - [ vm_support_check_modified, 1, 2 ], - [ vm_return ], -] - -CODE[106] = [ // Social Democratic Platform Adopted* - [ vm_permanently_remove ], - [ vm_social_democratic_platform_adopted ], - [ vm_valid_spaces_country ], - [ vm_prompt, ()=>`${country_name(game.vm_active_country)}` ], - [ vm_add_infl_free, 2 ], - [ vm_valid_spaces_country_sc ], - [ vm_prompt, ()=>`make a Support Check in ${country_name(game.vm_active_country)}` ], - [ vm_1_support_check ], - [ vm_return ], -] - -CODE[107] = [ // Massacre in Timisoara* - [ vm_permanently_remove ], - [ vm_if, ()=>!game.the_tyrant_is_gone ], - [ vm_massacre_in_timisoara ], - [ vm_valid_spaces_country_sc, 'Romania' ], - [ vm_prompt, 'Make Support Checks in Romania' ], - [ vm_support_check_modified, 2, 2 ], - [ vm_else ], - [ vm_tyrant_block ], - [ vm_endif ], - [ vm_return ], -] - -CODE[108] = [ // Army Backs Revolution* - [ vm_permanently_remove ], - [ vm_army_backs_revolution ], - [ vm_return ], -] - -CODE[109] = [ // Kremlin Coup* - [ vm_permanently_remove ], - [ vm_kremlin_coup ], - [ vm_return ], -] - -CODE[110] = [ // Malta Summit* - [ vm_permanently_remove ], - [ vm_malta_summit ], - [ vm_prompt, ' from Elite spaces' ], - [ vm_remove_opp_infl, 5 ], - [ vm_return ], -] -// #endregion - - -// ============= TIANANMEN SQUARE TRACK AWARDS ==================== -CODE[203] = [//Tiananmen Square space 3 award - [vm_tst_3], - [vm_return] -] -CODE[204] = [//Tiananmen Square space 4 award - [vm_valid_spaces_opponent], - [vm_tst_4], - [vm_return] -] -CODE[206] = [//Tiananmen Square space 6 - [vm_valid_spaces_sc], - [vm_tst_6], - [vm_return] -] -CODE[208] = [//Tiananmen Square space 8 event - [vm_tst_8], - [vm_return] -] - -// ============= POWER STRUGGLE WILDCARDS ========================= - -CODE[349] = [//Scare Tactics - [vm_scare_tactics], - [vm_valid_spaces_country_opp], - [vm_prompt, ()=>` from ${country_name(game.vm_active_country)}`], - [vm_remove_opp_infl, 1], - [vm_return] -] -CODE[350] = [//Support Surges - [vm_support_surges], - [vm_return] -] -CODE[351] = [//Support Falters - [vm_support_falters], - [vm_return] -] +//"use strict" + +const { spaces, cards, power_cards } = require("./data.js") + +var game, view, states = {} + +const DEM = "Democrat" +const COM = "Communist" + +const first_strategy_card = 1 +const last_strategy_card = 110 + +const dem_tst_req = [5, 5, 6, 6, 7, 8, 9, 10] +const com_tst_req = [6, 6, 7, 7, 8, 7, 6, 5] +const scoring_cards = [22, 23, 42, 43, 55, 95] +const leader_cards = [37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48] +const leaders = [1, 4, 5, 6, 7] +const support_loss_roll = [0, 0, 1, 1, 2, 2, 3, 4] +const vp_roll = [0, 0, 1, 1, 2, 2, 3, 4] +const countries = ['Poland', 'Hungary', 'East_Germany', 'Bulgaria', 'Czechoslovakia', 'Romania'] +const elite_spaces = [12, 15, 27, 43, 51, 69] +const all_power_cards = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52 ] +const numberless_cards = [25, 26, 27, 28, 29, 30, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52] +const auto_resolve_events = [5, 8, 9, 13, 17, 25, 26, 30, 35, 50, 53, 54, 58, 59, 62, 63, 65, 70, 72, 74, 86, 99, 102, 108] +const switch_events = [6, 20, 71] + +exports.scenarios = [ "Standard" ] + +exports.roles = [ DEM, COM ] + +// --- SET UP --- + +exports.setup = function (seed, scenario, options) { + game = { + seed: seed, + log: [], + undo: [], + summary: [], + active: null, + state: "com_init", + return: '', + vm: null, + vm_event: 0, + vm_event_to_do: false, + vm_infl_to_do: false, + + played_card: 0, + table_cards: [], + available_ops: 0, + vm_available_ops: 0, + valid_spaces: [], + valid_cards: [], + + vp: 0, + turn: 0, + round: 0, + round_player: COM, + stability: 0, + dem_tst_position: 0, + com_tst_position: 0, + dem_tst_attempted: 0, + com_tst_attempted: 0, + dem_tst_attempted_this_turn: 0, + com_tst_attempted_this_turn: 0, + + demInfl: [], + comInfl: [], + + strategy_deck: [], + strategy_discard: [], + discard: false, + view_opp_hand: false, + strategy_removed: [], + persistent_events: [], + power_struggle_deck: [], + power_struggle_discard: [], + dem_hand_limit: 8, + com_hand_limit: 8, + democrat_hand: [], + communist_hand: [], + + pwr_struggle_in: [], + is_pwr_struggle: false, + dem_pwr_hand_limit: 0, + com_pwr_hand_limit: 0, + dem_pwr_hand: [], + com_pwr_hand: [], + raised_stakes_discard: 0, + raised_stakes: 0, + raised_stakes_round: 0, + phase: 0, + times_held: [0, 0, 0, 0, 0, 0], + revolutions: [false, false, false, false, false, false], + remove_opponent_infl: false, + tactics_fails: '', + } + + log_h1("1989 Dawn of Freedom") + + game.active = COM + start_game() + + return game +} + +function start_game() { + //starting influence + + // Draw cards + + //console.log('start game') + + game.strategy_deck = draw_deck(cards) + reset_power() + + //Set starting influence + spaces.forEach((space, index) => { + if (space !== null) { + game.demInfl[index] = space.demInfl + game.comInfl[index] = space.comInfl + } + }) + + //Set starting placement ops + game.starting_infl = { + com_starting_infl: 0, + dem_starting_infl: 0 + }, + + // Set variable event cards where event is playable at start of game + + game.playable_cards = [14, 15, 21, 70] + + //console.log('game.strategy_deck: ', game.strategy_deck[1]) + draw_cards(game.strategy_deck, game.democrat_hand, game.communist_hand, game.dem_hand_limit, game.com_hand_limit) + //.log('game.strategy_deck: ', game.strategy_deck[1], 'democrat_hand:', game.democrat_hand) + + game.valid_spaces = valid_spaces_setup() + game.available_ops = 2 + game.phase = 0 + log_h1("Place starting Support Points") + log_side() +} + + +exports.view = function(state, player) { + game = state + + view = { + log: game.log, + active: game.active, + prompt: null, + actions: null, + + played_card: game.played_card, + table_cards: game.table_cards, + valid_spaces: game.valid_spaces, + valid_cards: game.valid_cards, + + demInfl: game.demInfl, + comInfl: game.comInfl, + turn: game.turn, + round: game.round, + round_player: game.round_player, + vp: game.vp, + stability: game.stability, + dem_tst: game.dem_tst_position, + com_tst: game.com_tst_position, + persistent_events: game.persistent_events, + systematization: game.systematization, + the_tyrant_is_gone: game.the_tyrant_is_gone, + + strategy_deck: game.strategy_deck.length, + strategy_removed: game.strategy_removed, + discard: game.discard, + show_opp_hand: game.view_opp_hand, + + democrat_hand: game.democrat_hand.length, + communist_hand: game.communist_hand.length, + democrat_power_hand: game.dem_pwr_hand.length, + communist_power_hand: game.com_pwr_hand.length, + ceausescu_cards: game.ceausescu_cards, + is_pwr_struggle: game.is_pwr_struggle, + times_held: game.times_held, + revolutions: game.revolutions, + + hand: [], + set_aside: [], + pwr_hand: [], + + + } + + if (game.is_pwr_struggle) { + view.strategy_discard = game.power_struggle_discard + } else { + view.strategy_discard = game.strategy_discard + } + + if (player === game.active && game.vm && game.vm.draw) + view.drawn = game.vm.draw + + if (player === game.active) { + if (game.selected_space > 0 ) { + view.valid_spaces = [game.selected_space] + } else { + view.valid_spaces = game.valid_spaces + } + } else { + view.valid_spaces = [] + } + + if (player === game.active) { + view.valid_cards = game.valid_cards + } else { + view.valid_cards = [] + } + + if (player === DEM) { + view.hand = game.democrat_hand + if (game.communist_hand_red) { + view.opp_hand = game.communist_hand_red + } + view.set_aside = game.democrat_set_aside /*Is this being used? */ + view.power_hand = [...game.dem_pwr_hand].sort((a, b) => a - b) + + } else if (player === COM) { + view.hand = game.communist_hand + view.opp_hand = [...game.dem_pwr_hand].sort((a, b) => a - b) + view.power_hand = [...game.com_pwr_hand].sort((a, b) => a - b) + } + + if (player === DEM) { + view.samizdat = game.samizdat_card + } + + if (game.state === "game_over") { + view.prompt = game.victory + } else if (player === "Observer" || (game.active !== player && game.active !== "Both")) { + if (states[game.state]) { + let inactive = states[game.state].inactive + if (typeof inactive === "function") + view.prompt = `Waiting for ${game.active} ${inactive()}` + else + view.prompt = `Waiting for ${game.active} to ${inactive}` + } else { + view.prompt = "A Unknown state: " + game.state + } + } else { + view.actions = {} + + if (states[game.state]) + states[game.state].prompt(player) + else + view.prompt = "B Unknown state: " + game.state + if (view.actions.undo === undefined) { + if (game.undo && game.undo.length > 0) + view.actions.undo = 1 + else + view.actions.undo = 0 + } + } + + return view +} + + +// === ACTIONS =========== + +function gen_action(action, argument) { +//console.log('gen_action called with ', action, ' and ', argument) + if (argument === undefined) { + //console.log('argument undefined') + view.actions[action] = 1 + } else { + if (!(action in view.actions)) { + //console.log('push argument') + view.actions[action] = [] + } + view.actions[action].push(argument) + } + //console.log('view.actions: ', view.actions, 'view.actions[action]: ', view.actions[action]) +} + +function gen_action_infl(space){ + gen_action("infl", space) +} + +function gen_action_card(card){ + gen_action("card", card) +} + +function gen_action_sc(space){ + gen_action("sc", space) +} + +function gen_action_scoring(){ + gen_action("scoring") +} + +exports.action = function (state, player, action, arg) { + //console.log('exports.action called with state:' , state, 'player:', player, 'action: ', action, 'arg: ', arg) + game = state + if (states[game.state] && action in states[game.state]) { + states[game.state][action](arg, player) + } else { + if (action === "undo" && game.undo && game.undo.length > 0) + pop_undo() + else + throw new Error("Invalid action: " + action) + } + return game +} + +// ============= GAME STATES ======================= + +states.com_init = { + inactive: 'place starting SPs.', + prompt() { + //console.log('state:', game.state, 'game.valid_spaces', game.valid_spaces) + if (game.starting_infl.dem_starting_infl === 2 && game.available_ops === 0 ) { + view.prompt = 'Place starting SPs: done. Start Turn 1.'; + gen_action("start"); + } else if (game.available_ops === 0) { + view.prompt = 'Place starting SPs: done.'; + gen_action("done"); + return; + } else if (game.starting_infl.dem_starting_infl === 2) { + view.prompt = `Place your last ${pluralize(game.available_ops,'starting SP')}.` + } else { + view.prompt = `Place ${pluralize(game.available_ops,'starting SP')}.` + } + for (let space_id of game.valid_spaces) { + gen_action_infl(space_id); + } + }, + infl(space) { + add_infl(space) + + }, + done() { + if (game.summary.length > 0) { + pop_summary() + log_br() + } + + game.starting_infl.com_starting_infl++ + if (game.starting_infl.com_starting_infl == 1){ + game.available_ops = 3 + game.state = 'dem_init' + valid_spaces_setup() + next_player() + } else if (game.starting_infl.com_starting_infl == 2) { + game.available_ops = 4 + game.state = 'dem_init' + valid_spaces_setup() + next_player() + } else if (game.starting_infl.com_starting_infl == 3) { + delete game.starting_infl + game.state = 'start_game' + } + }, + start() { + new_turn() + clear_undo() + game.state = 'choose_card' + } +} + +states.dem_init = { + inactive: 'place starting SPs.', + prompt() { + //console.log('state:', game.state) + if (game.available_ops == 0) { + view.prompt = 'Place starting SPs: done.'; + gen_action("done"); + return; + } else if (game.starting_infl.com_starting_infl === 2) { + view.prompt = `Place your last ${pluralize(game.available_ops,'starting SP')}.` + } else { + view.prompt = `Place ${pluralize(game.available_ops,'starting SP')}.` + } + for (let space_id of game.valid_spaces) { + gen_action_infl(space_id); + } + }, + infl(space) { + add_infl(space) + }, + + done() { + if (game.summary.length > 0) { + pop_summary() + log_br() + } + + game.starting_infl.dem_starting_infl++ + if (game.starting_infl.dem_starting_infl == 1){ + game.available_ops = 3 + } else if (game.starting_infl.dem_starting_infl == 2) { + game.available_ops = 2 + } + game.state = 'com_init' + valid_spaces_setup() + next_player() + } +} + + +states.choose_card = { + inactive: 'choose a card.', + prompt() { + if ((game.active===DEM && game.democrat_hand.length === 0) || game.active === COM && game.communist_hand.length === 0) { + view.prompt = 'No cards remaining: you must pass.' + gen_action('pass') + } else { + view.prompt = 'Choose a card.' + let available_cards + if (game.active === DEM) { + available_cards = game.democrat_hand + } else { + available_cards = game.communist_hand + } + for (let card of available_cards) { + gen_action_card(card) + } + } + }, + card(card) { + push_undo() + + //Check if player is at risk of losing game due to held scoring card + if (!scoring_cards.includes(card)) { + let scoring_cards_count = count_scoring_cards() + + if (game.round !== 8 && scoring_cards_count >= (8-game.round)){ + game.temp = card + game.state = 'confirm_card' + return + } + } + select_card(card) + }, + pass() { + log('No cards remaining. Passed') + //end_round() + game.state = 'end_round' + } +} + +states.confirm_card = { + inactive: 'choose a card.', + prompt() { + let scoring_cards_count = count_scoring_cards() + view.prompt = `${pluralize(scoring_cards_count,'scoring card')} in hand with ${pluralize(8-game.round,'turn')} remaining. Scoring cards may not be held. Continue?` + gen_action('continue') + }, + continue() { + select_card(game.temp) + } +} + +states.play_card ={ + get inactive() { + return `play ${clean_name(cards[game.played_card].name)}.` + }, + prompt () { + /*if (game.phase >= 1) { /*Finish here when playing your own event + console.log('in play card') + view.prompt = `${clean_name(cards[game.played_card].name)}: done. End the Action Round.` + gen_action('end_round') + return + }*/ + + view.prompt = `Play ${clean_name(cards[game.played_card].name)} for:` + + if (scoring_cards.includes(game.played_card)) { + /*view.prompt = 'Play for:'*/ + gen_action('event') + return + } + + // Check for Reformer Rehabilitated + + //console.log('game.active', game.active, 'game.playable_cards[67].playable', game.playable_cards[67].playable) + + + if (game.played_card === 67 && game.playable_cards.includes(67)){ + if (game.active === DEM && (game.dem_tst_position > game.com_tst_position)) { + gen_action('event') + } + if (game.active === COM && (game.dem_tst_position < game.com_tst_position)) { + gen_action('event') + } + } + + //Check for events + //console.log('event_is_playable(game.played_card)', event_is_playable(game.played_card)) + if (event_is_playable(game.played_card)) { + //console.log('card is playable') + //Check for Tiananmen Square Track awards special abilities + //console.log('game.tst_7', game.tst_7) + if ((game.active === DEM && cards[game.played_card].side === 'C' && game.dem_tst_position >= 7 && game.com_tst_position < 7 && !game.tst_7) || (game.active === COM && cards[game.played_card].side === 'D' && game.com_tst_position >= 7 && game.dem_tst_position < 7 && !game.tst_7)){ + gen_action('tst_7') + } + + if ((game.active === DEM && cards[game.played_card].side !== 'C' && game.dem_tst_position >= 8 && game.com_tst_position < 8 && !game.tst_8) || (game.active === COM && cards[game.played_card].side !== 'D' && game.com_tst_position >= 8 && game.dem_tst_position < 8 && !game.tst_8)){ + gen_action('tst_8') + } + + //Continue with normal logic + get_events(game.played_card) + } + + gen_action('influence') + gen_action('support_check') + + if ((game.active === DEM && game.dem_tst_attempted_this_turn === 0 && game.dem_tst_position < 8 ) || (game.active === COM && game.com_tst_attempted_this_turn === 0 && game.com_tst_position < 8)) { + gen_action('tst') + } + + }, + event() { + push_undo() + //console.log('played event, game.active', game.active, 'game.view_opp_hand', game.view_opp_hand) + log_gap(`Played C${cards[game.played_card].number} for the event`) + game.vm_infl_to_do = false + if (scoring_cards.includes(game.played_card)) {game.phase = 0} + else {game.phase = 1} + game.return = game.active + if (switch_events.includes(game.played_card)) {next_player()} + game.vm_event = game.played_card + //console.log('before event, game.vm_infl_to_do', game.vm_infl_to_do) + goto_vm(game.vm_event) + }, + opp_event() { + push_undo() + log_gap(`Played C${cards[game.played_card].number} for the event`) + game.phase = 1 /*Do I still need this?*/ + game.vm_infl_to_do = true + game.return = game.active + game.vm_event = game.played_card + if (is_auto_resolve(game.played_card) || switch_events.includes(game.played_card)) { + goto_vm(game.vm_event)} + else { + next_player() + log(`C${game.vm_event}`) + goto_vm(game.vm_event) + } + }, + influence() { + push_undo() + log_gap(`Played C${cards[game.played_card].number} to place SPs`) + + + // Check if Common European Home played for influence + if (game.played_card === 21) { + if (game.active === DEM) { + game.vp -- + log('-1 VP') + if (check_vp()) { + return + } + } else { + game.vp ++ + log('+1 VP') + if (check_vp()) { + return + } + } + } + // Check if card is opponent card with event that needs to be resolved + + if (cards[game.played_card].playable || game.playable_cards.includes(game.played_card)) { + if ((game.active === DEM && cards[game.played_card].side === "C" ) || (game.active === COM && cards[game.played_card].side === "D")) { + //game.phase = 1 /*Do I need this? */ + game.vm_event_to_do = true + } + } + + // If ABHR - Set AHBR tracker to true + if (game.persistent_events.includes(58)) { + game.austria_hungary_border_reopened_tracker = true + } + game.state='add_influence' + valid_spaces_infl() + }, + tst() { + push_undo() + log_gap(`Played C${cards[game.played_card].number} to the Tiananmen Square Track`) + game.state='tiananmen_square_attempt' + }, + support_check() { + push_undo() + log_gap(`Played C${cards[game.played_card].number} for support checks`) + + // Check if card is opponent card with event that needs to be resolved + + if (cards[game.played_card].playable || game.playable_cards.includes(game.played_card)) { + if ((game.active === DEM && cards[game.played_card].side === "C" ) || (game.active === COM && cards[game.played_card].side === "D")) { + game.vm_event_to_do = true + } + } + + game.available_ops = 2 + game.state='support_check_prep' + valid_spaces_sc() + }, + tst_7() { /*Cancel opponent event */ + push_undo() + log(`Played C${game.played_card}. Event cancelled using TST Award`) + game.tst_7 = true + game.vm_infl_to_do = true + game.state = 'resolve_opponent_event' + }, + tst_8() { /*Play card for ops and event */ + push_undo() + game.vm_event_to_do = true + game.vm_infl_to_do = true + game.tst_8 = true + log(`Played C${game.played_card} for event and operations`) + game.state = 'vm_tst_8' + }, + end_round () { + end_round() + } + +} + +states.resolve_opponent_event = { + get inactive() { + return `resolve ${clean_name(cards[game.played_card].name)}.` + }, + prompt() { + //console.log('in resolve opponent event: discard', game.strategy_discard) + if (game.vm_infl_to_do) { + view.prompt = 'Event resolved. Choose to play card for:' + gen_action('influence') + gen_action('support_check') + } else if (game.vm_event_to_do) { + // Check for Tiananmen Square Track ability - play opponent card without triggering event + if ((game.active === DEM && game.dem_tst_position >= 7 && game.com_tst_position < 7 && !game.tst_7) || (game.active === COM && game.com_tst_position >= 7 && game.dem_tst_position < 7 && !game.tst_7)){ + gen_action('tst_7') + } + view.prompt = `${clean_name(cards[game.played_card].name)}: you must resolve the opponent event.` + gen_action('opp_event') + } else { + view.prompt = 'Event resolved. End the action round.' + gen_action('end_round') + } + }, + influence(){ + push_undo() + // If ABHR - Set AHBR tracker to true + if (game.persistent_events.includes(58)) { + game.austria_hungary_border_reopened_tracker = true + } + game.state = 'finish_add_infl' + valid_spaces_infl() + }, + support_check() { + push_undo() + game.available_ops = 2 + game.state = 'finish_support_check_prep' + valid_spaces_sc() + }, + opp_event() { + game.vm_event_to_do = false + game.return_state = 'resolve_opponent_event' + if (is_auto_resolve(game.played_card) || switch_events.includes(game.played_card)) { + game.return = game.active + log(`Played C${game.played_card} for the event`) + goto_vm(game.played_card)} + else { + if (game.active === DEM) { + game.return = COM + } else { + game.return = DEM + } + next_player() + log(`C${game.played_card}`) + goto_vm(game.played_card) + } + }, + tst_7() { + push_undo() + log('Event cancelled using TST Award') + game.tst_7 = true + game.vm_event_to_do = false + }, + end_round() { + push_undo() + /*if(game.round_player === COM && game.active === DEM) { + log_h3('End of Communist Action Round') + change_player() + } */ + end_round() + } +} + + +states.finish_add_infl = { + inactive: 'add SPs.', + prompt () { + if (game.available_ops === 0) { + view.prompt = 'Place SPs: done.' + gen_action("end_round") + return; + } + + view.prompt = `Add SPs: ${game.available_ops} remaining.` + + // Generate actions for valid spaces + for (let space_id of game.valid_spaces) { + gen_action_infl(space_id) + } + }, + infl(space) { + add_infl(space) + }, + end_round() { + push_undo() + if (game.summary.length > 0) { + pop_summary() + log_br() + } + + end_round() + //game.state = 'end_round' + } +} + +states.finish_support_check_prep = { + inactive: 'do support checks.', + prompt () { + if (game.available_ops === 0) { + view.prompt = 'Support checks: done.' + gen_action('end_round') + //return + } else { + view.prompt = `Select a space. ${pluralize(game.available_ops, 'support check')} remaining.` + for (let space_id of game.valid_spaces) { + gen_action_sc(space_id) + } + } + }, + sc(space) { + push_undo() + game.selected_space = space + // Check for Austria-Hungary Border Reopened - check on first support check only + //console.log('game.austria_hungary_border_reopened_checked', game.austria_hungary_border_reopened_checked) + if (game.persistent_events.includes(58)){ + if (game.active === DEM && game.available_ops > 1) { + //console.log('in ahb check, country, ', spaces[game.selected_space].country, 'ahb', 'austria_hungary_border_reopened']) + if (spaces[game.selected_space].country === 'East_Germany' && game.persistent_events.includes(58) && game.active === DEM) { + game.state = 'finish_austria_hungary_border_reopened_check' + return + } + } + } + game.state = 'finish_do_support_check' + }, + end_round () { + end_round() + //game.state = 'end_round' + } +} + +states.finish_austria_hungary_border_reopened_check = { + inactive: 'decide Austria-Hungary Border Reopened', + prompt() { + view.prompt = 'Austria-Hungary Border Reopened: will both support checks be in East Germany?' + gen_action('yes') + gen_action('no') + }, + yes() { + game.austria_hungary_border_reopened_tracker = true + game.state = 'finish_do_support_check' + }, + no() { + game.state = 'finish_do_support_check' + } +} + +states.finish_do_support_check = { + inactive: 'do support checks', + prompt () { + view.prompt = `Support check: ${spaces[game.selected_space].name_unique}. Roll a die.` + gen_action('roll') + }, + roll() { + clear_undo() + do_sc(game.selected_space) + game.available_ops-- + if (game.available_ops === 0) { + game.valid_spaces = [] + } + game.state = 'finish_support_check_prep' + return + } +} + +states.add_influence = { + inactive: 'add SPs.', + prompt () { + if (game.available_ops <= 0) { + view.prompt = 'Place SPs: done.' + if (!game.vm_event_to_do) { + gen_action("end_round") + } else { + gen_action('done') + } + } else { + + view.prompt = `Add SPs: ${game.available_ops} remaining.` + + // Generate actions for valid spaces + for (let space_id of game.valid_spaces) { + gen_action_infl(space_id); + } + } + }, + infl(space) { + add_infl(space) + }, + end_round() { + push_undo() + if (game.summary.length > 0) { + pop_summary() + log_br() + } + end_round() + }, + done() { + if (game.summary.length > 0) { + pop_summary() + log_br() + } + reset_austria_hungary_border_reopened() + game.state = 'resolve_opponent_event' + } +} + +states.tiananmen_square_attempt = { + inactive: 'do Tiananmen Square Attempt.', + prompt () { + view.prompt = 'Tiananmen Square Track attempt: Roll a die.' + gen_action('roll') + }, + roll() { + clear_undo() + do_tst_attempt () + } +} + +states.tiananmen_square_attempt_success = { + inactive: 'do Tiananmen Square Attempt.', + prompt () { + if (game.vm_event > 200) { + view.prompt = 'Tiananmen Square Track attempt successful. Go to TST Award.' + gen_action('done') + } else { + view.prompt = 'Tiananmen Square Track attempt successful.' + gen_action('end_round') + } + + }, + done () { + push_undo() + //console.log('going to tst award, game.return_state', game.return_state) + goto_vm(game.vm_event) + }, + end_round () { + push_undo() + end_round() + } +} + +states.tiananmen_square_attempt_fail = { + inactive: 'do Tiananmen Square Attempt.', + prompt () { + view.prompt = 'Tiananmen Square Track attempt failed.' + gen_action('end_round') + }, + end_round () { + push_undo() + end_round() + //game.state = 'tiananmen_square_attempt_done' + } +} + +states.tiananmen_square_attempt_done = { + inactive: 'do Tiananmen Square Attempt.', + prompt () { + view.prompt = 'Tiananmen Square Track attempt: done.' + gen_action('end_round') + }, + end_round () { + end_round() + //game.state = 'end_round' + } +} + +states.tst_goddess = { + inactive: 'choose whether to discard a card.', + prompt() { + //if (game.phase === 0) { + view.prompt = 'Tiananmen Square Track award: you may discard a non-Power Struggle Card and draw a replacement.' + for (let card of game.valid_cards) { + gen_action_card(card) + } + gen_action('pass') + /*} else { + view.prompt = 'Discard a card: done.' + gen_action('done') + }*/ + }, + card(card) { + push_undo() + discard(card) + game.valid_cards = [] + game.state = 'tst_goddess_draw' + //game.phase++ + /*if (game.active === DEM) { + draw_cards(game.strategy_deck, game.democrat_hand, game.communist_hand, game.democrat_hand.length +1, game.communist_hand.length) + } else { + draw_cards(game.strategy_deck, game.democrat_hand, game.communist_hand, game.democrat_hand.length, game.communist_hand.length +1) + }*/ + }, + pass() { + log('Did not discard') + log_h2("Action Round " + game.round) + if (game.active === DEM) { + next_player() + } else { + log_side() + } + if (game.persistent_events.includes(5)) { + game.state = 'general_strike' + } else { + game.state = 'choose_card' + } + }, + done() { + + log_h2("Action Round " + game.round) + if (game.active === DEM) { + next_player() + } else { + log_side() + } + game.phase = 0 + if (game.persistent_events.includes(5)) { + game.state = 'general_strike' + } else { + game.state = 'choose_card' + } + } +} + +states.tst_goddess_draw = { + inactive: 'choose whether to discard a card.', + prompt() { + view.prompt = 'Draw a replacement card.' + gen_action('draw') + }, + draw() { + if (game.active === DEM) { + draw_cards(game.strategy_deck, game.democrat_hand, game.communist_hand, game.democrat_hand.length +1, game.communist_hand.length) + } else { + draw_cards(game.strategy_deck, game.democrat_hand, game.communist_hand, game.democrat_hand.length, game.communist_hand.length +1) + } + log_h2("Action Round " + game.round) + if (game.active === DEM) { + next_player() + } else { + log_side() + } + game.phase = 0 + if (game.persistent_events.includes(5)) { + game.state = 'general_strike' + } else { + game.state = 'choose_card' + } + } +} + + + +states.support_check_prep = { + inactive: 'do support checks', + prompt () { + if (game.available_ops === 0) { /*Needs another check for Support Checks done during Crowd Turns against Ceausescu*/ + if (game.is_pwr_struggle) { + view.prompt = 'The Crowd Turns Against Ceausescu. Support checks: done.' + gen_action('done') + } else if (!game.vm_event_to_do) { + view.prompt = 'Support checks: done.' + gen_action('end_round') + } else { + view.prompt = 'Support checks: done.' + gen_action('done') + } + } else if (game.available_ops > 0) { + view.prompt = `Select a space. ${pluralize(game.available_ops, 'support check')} remaining.` + + for (let space_id of game.valid_spaces) { + gen_action_sc(space_id) + } + } + }, + sc(space) { + push_undo() + game.selected_space = space + + // Check for Austria-Hungary Border Reopened - check on first support check only + //console.log('game.austria_hungary_border_reopened_checked', game.austria_hungary_border_reopened_checked) + if (game.persistent_events.includes(58)) { + if (game.active === DEM && game.available_ops > 1) { + if (spaces[game.selected_space].country === 'East_Germany' && game.persistent_events.includes(58) && game.active === DEM) { + game.state = 'austria_hungary_border_reopened_check' + return + } + //game.state = 'do_support_check' + } /*else { */ + } + game.state = 'do_support_check' + //} + }, + end_round() { + push_undo() + end_round() + }, + done() { + push_undo() + if (game.is_pwr_struggle) {/*Crowd Turns Against Ceausescu should be the only time you end up here during a power struggle */ + if (game.return !== game.active) { + next_player() + } + log_h2('Raise the Stakes') + game.state = 'raise_stakes_1' + return + } + reset_austria_hungary_border_reopened() + game.state = 'resolve_opponent_event' + } +} + +states.do_support_check = { + inactive: 'do support checks.', + prompt () { + // console.log('in do_support_check') + view.prompt = `Support check: ${spaces[game.selected_space].name_unique}. Roll a die.` + gen_action('roll') + }, + roll() { + clear_undo() + do_sc(game.selected_space) + game.available_ops-- + if (game.available_ops === 0) { + game.valid_spaces = [] + } + game.state = 'support_check_prep' + return + } +} + +states.austria_hungary_border_reopened_check = { + inactive: 'decide Austria-Hungary Border Reopened.', + prompt() { + view.prompt = 'Austria-Hungary Border Reopened: will both support checks be in East Germany?' + gen_action('yes') + gen_action('no') + }, + yes() { + game.austria_hungary_border_reopened_tracker = true + game.state = 'do_support_check' + }, + no() { + game.state = 'do_support_check' + } +} + +states.end_round = { + inactive: 'finish playing a card.', + prompt() { + view.prompt = 'End the Action Round.' + gen_action('end_round') + }, + end_round() { + push_undo() + end_round() + } +} + +//======================= POWER STRUGGLE =============================== + +states.draw_power_cards = { + inactive: 'draw cards.', + prompt() { + view.prompt = `${clean_name(cards[this_card()].name)}: draw cards.` + gen_action('draw') + }, + draw() { + push_undo() + game.power_struggle_deck = [...all_power_cards] + // console.log('game.power_struggle_deck.length', game.power_struggle_deck.length) + //console.log('called draw cards, country', game.pwr_struggle_in, 'game.active', game.active, 'game.view_opp_hand', game.view_opp_hand) + //console.log('test3') + let presence = check_presence(game.pwr_struggle_in) + //console.log('test2') + if (presence.dem_spaces > 0) { + game.dem_pwr_hand_limit = 6 + 2*(presence.dem_spaces - 1) + } else { + game.dem_pwr_hand_limit = 0 + } + if (presence.com_spaces > 0 ) { + game.com_pwr_hand_limit = 6 + 2*(presence.com_spaces - 1) + } else { + game.com_pwr_hand_limit = 0 + } + // Events which affect cards drawn + if (game.persistent_events.includes(17) && game.com_pwr_hand_limit >= 2) { + log('Democrat receives 2 cards from Communist due to C17') + game.dem_pwr_hand_limit += 2 + game.com_pwr_hand_limit -= 2 + discard_from_table(17) + game.persistent_events = game.persistent_events.filter(n => n !== 17) + } + + if (game.persistent_events.includes(72)) { + let farmer_check + for (let space of spaces) { + if (space && space.country === game.pwr_struggle_in && space.socio === 3 && check_dem_control(space.space_id)) { + farmer_check = true + } + } + if (farmer_check && game.com_pwr_hand_limit > 0) { + log('Democrat receives 1 cards from Communist due to C72') + game.dem_pwr_hand_limit += 1 + game.com_pwr_hand_limit -= 1 + permanently_remove(72) + game.persistent_events = game.persistent_events.filter(n => n !== 72) + } + } + + if (game.persistent_events.includes(102) && game.dem_pwr_hand_limit >=2 && (game.pwr_struggle_in === 'Romania' || game.pwr_struggle_in === 'Bulgaria')) { + log('Communist receives 2 cards from Democrat due to C102') + game.dem_pwr_hand_limit -= 2 + game.com_pwr_hand_limit += 2 + permanently_remove(102) + game.persistent_events = game.persistent_events.filter(n => n !== 102) + } + + //Draw Power Cards + game.is_pwr_struggle = true + //console.log('game.dem_pwr_hand_limit', game.dem_pwr_hand_limit, 'game.com_pwr_hand_limit', game.com_pwr_hand_limit) + draw_cards(game.power_struggle_deck, game.dem_pwr_hand, game.com_pwr_hand, game.dem_pwr_hand_limit, game.com_pwr_hand_limit) + if (game.active === DEM) { + game.valid_cards = [...game.dem_pwr_hand] + } else { + game.valid_cards = [...game.com_pwr_hand] + } + //game.valid_cards = all_power_cards + + log(`Communist: ${game.com_pwr_hand.length} cards`) + log(`Democrat: ${game.dem_pwr_hand.length} cards`) + + //Check if The Crowd Turns Against Ceausescu occurs + if (game.table_cards.includes(54) && game.pwr_struggle_in === 'Romania') { + //console.log('draw cards: crowd subcheck, game.active', game.active) + if (game.active === COM) { + game.return = COM + next_player() + } + log_h3('C54') + game.persistent_events.push(54) + game.state = 'the_crowd_turns_against_ceausescu_prep' + } else { + log_h2('Raise the Stakes') + game.state = 'raise_stakes_1' + //console.log('game.state', game.state, 'game.active', game.active, 'game.view_opp_hand', game.view_opp_hand) + } + } +} + +states.the_crowd_turns_against_ceausescu_prep = { + get inactive() { + return `resolve ${clean_name(cards[54].name)}.` + }, + prompt() { + view.prompt = 'The Crowd Turns Against Ceausescu: draw cards.' + gen_action('draw') + }, + draw() { + game.ceausescu_cards = [] + draw_cards(game.power_struggle_deck, game.ceausescu_cards, game.com_pwr_hand, 15, game.com_pwr_hand.length) + //console.log('game.ceausescu_cards', game.ceausescu_cards) + game.temp = game.ceausescu_cards.filter(card => card && card >=25 && card <= 30).length + log(`Drew ${pluralize(game.temp, 'Rally in the Square')}.`) + game.vm_available_ops = game.temp * 3 + log(`Democrat takes a ${game.vm_available_ops} Action Round`) + game.state = 'vm_the_crowd_turns_against_ceausescu' + } +} + +states.vm_the_crowd_turns_against_ceausescu = { + get inactive() { + return `resolve ${clean_name(cards[54].name)}.` + }, + prompt() { + view.prompt = `You have ${game.vm_available_ops} operations points. Play for:` + gen_action('influence') + gen_action('support_check') + }, + influence() { + push_undo() + delete game.ceausescu_cards + valid_spaces_infl() + game.valid_spaces = game.valid_spaces.filter(n => spaces[n].country === 'Romania') + game.state = 'the_crowd_turns_against_ceausescu_infl' /* Send this to add_infl. Add check at end of add_infl similar to valid_spaces*/ + }, + support_check() { + push_undo() + delete game.ceausescu_cards + valid_spaces_sc() + game.available_ops = 2 + game.state = 'support_check_prep' + } +} + +states.the_crowd_turns_against_ceausescu_infl = { + inactive: 'add SPs.', + prompt () { + if (game.vm_available_ops === 0) + { + view.prompt = 'Place SPs: done.'; + gen_action("done"); + return; + } + + view.prompt = `Add SPs: ${game.vm_available_ops} remaining` + for (let space of game.valid_spaces) { + gen_action_infl(space) + } + }, + infl(space) { + vm_do_add_infl(space) + }, + done() { + if (game.summary.length > 0) { + pop_summary() + log_br() + } + + if (game.return !== game.active) { + next_player() + } + log_h2('Raise the Stakes') + game.state = 'raise_stakes_1' + } +} + +states.raise_stakes_1 = { + inactive: 'raise the stakes.', + + prompt () { + // console.log('raise stakes 1 - valid cards', game.valid_cards) + // console.log('raise the stakes: game.played_power_card', game.played_power_card, 'game.active', game.active, 'game.view_opp_hand', game.view_opp_hand) + if ((game.active === DEM && game.dem_pwr_hand < 3) || (game.active === COM && game.com_pwr_hand < 3)) { + view.prompt = 'Raise the stakes: you must pass.' + gen_action('pass') + } + else if (game.raised_stakes_discard === 3) { + view.prompt = 'Raise the stakes: done.' + gen_action('done') + } else { + view.prompt = `Discard ${3-game.raised_stakes_discard} cards to raise the stakes.` + if (game.raised_stakes_discard === 0) { + gen_action('pass') + } + for (let card of game.valid_cards) { + gen_action_card(card) + } + } + }, + card(card) { + push_undo() + if (numberless_cards.includes(card)) { + log(`Discarded: P${card}`) + } else { + log(`Discarded: P${card} V${power_cards[card].value}`) + } + discard(card) + + game.raised_stakes_discard ++ + if (game.raised_stakes_discard === 3) { + game.raised_stakes++ + game.valid_cards = [] + } + }, + pass(){ + log('Did not raise the stakes') + game.raised_stakes_discard = 0 + next_player() + if (game.active === DEM) { + game.valid_cards = [...game.dem_pwr_hand] + } else { + game.valid_cards = [...game.com_pwr_hand] + } + game.state = 'raise_stakes_2' + }, + done () { + log_gap('Raised the stakes') + game.raised_stakes_discard = 0 + next_player() + //console.log('game.active', game.active) + if (game.active === DEM) { + game.valid_cards = [...game.dem_pwr_hand] + } else { + game.valid_cards = [...game.com_pwr_hand] + } + // console.log('game.valid_cards', game.valid_cards) + game.state = 'raise_stakes_2' + } +} + +states.raise_stakes_2 = { + inactive: 'raise the stakes.', + + prompt () { + if ((game.active === DEM && game.dem_pwr_hand < 3) || (game.active === COM && game.com_pwr_hand < 3)) { + view.prompt = 'Raise the stakes: you must pass.' + gen_action('pass') + return + } + if (game.raised_stakes_discard === 3) { + view.prompt = 'Raise the stakes: done.' + gen_action('done') + } else { + view.prompt = `Discard ${3-game.raised_stakes_discard} cards to raise the stakes.` + if (game.raised_stakes_discard === 0) { + gen_action('pass') + } + for (let card of game.valid_cards) { + gen_action_card(card) + } + } + }, + card(card) { + push_undo() + if (numberless_cards.includes(card)) { + log(`Discarded: P${card}`) + } else { + log(`Discarded: P${card} V${power_cards[card].value}`) + } + discard(card) + + game.raised_stakes_discard ++ + if (game.raised_stakes_discard === 3) { + game.raised_stakes++ + game.valid_cards = [] + } + + }, + pass() { + log('Did not raise the stakes') + game.raised_stakes_discard = 0 + game.valid_cards = [] + log_h2('Play Cards') + next_player() + game.state = 'begin_power_struggle' + }, + done () { + log_gap('Raised the stakes') + game.raised_stakes_discard = 0 + game.valid_cards = [] + log_h2('Play Cards') + next_player() + game.state = 'begin_power_struggle' + }, +} + +states.begin_power_struggle = { + inactive: 'begin power struggle.', + prompt() { + view.prompt = 'Begin power struggle.' + gen_action('struggle') + }, + struggle () { + do_valid_cards() + game.state = 'power_struggle' + } +} + +states.power_struggle = { + inactive: 'play a card.', + prompt () { + console.log('game.vm_event', game.vm_event) + if (game.phase === 0) { + if (game.valid_cards.length > 0) { + view.prompt = "Play a card." + for (let card of game.valid_cards) { + gen_action_card(card) + } + } else if ( game.valid_cards.length === 0) { + view.prompt = 'No valid cards. You must concede.' + gen_action('concede') + } + } + if (game.phase === 1) { + if (game.valid_cards.length > 0) { + view.prompt = `${power_cards[game.played_power_card].name} played. You must match or concede.` + gen_action('concede') + for (let card of game.valid_cards) { + gen_action_card(card) + } + } else if (game.valid_cards.length === 0) { + view.prompt = `${power_cards[game.played_power_card].name} played. You must concede.` + gen_action('concede') + } + } + else if (game.phase === 2) { + view.prompt = 'You matched. Roll a die.' + gen_action('roll') + } + else if (game.phase === 3) { + view.prompt = 'Play leader as:' + if (game.tactics_fails !== "Strike") {gen_action('strike')} + if (game.tactics_fails !== "March") {gen_action('march')} + if (game.tactics_fails !== "Rally in the Square") {gen_action('rally')} + if (game.tactics_fails !== "Petition") {gen_action('petition')} + } + }, + card(card) { + push_undo() + discard(card) + game.valid_cards=[] + game.return_state = 'power_struggle' + if (card === 52) { + log_gap(`Played P52: P${power_cards[game.played_power_card].number} no longer playable`) + + } else { + if (game.phase === 0 && leader_cards.includes(card)) {} /* Log nothing. Probably a better way to do this */ + else if (numberless_cards.includes(card)) { + log_gap(`Played: P${card}`) + } else { + log_gap(`Played: P${card} V${power_cards[card].value}`) + } + } + if (game.phase === 0) { + if (card >= 37 && card <= 48) { /*When a leader is played */ + game.played_power_card = card + game.phase = 3 + } else if (card === 49){ /*Scare Tactics */ + game.return = '' + goto_vm(349) /*Can I combine these 3 into a single stage where you goto_vm(300 + card) ? */ + } else if (card === 50) { /*Support Surges */ + if (game.active === DEM) { + game.return = COM + } else { + game.return = DEM + } + goto_vm(350) + } else if (game.phase === 0 && card === 51) { /*Support Falters */ + next_player() + goto_vm(351) + } else { + game.played_power_card = card + game.phase = 1 + next_player() + do_valid_cards() + } + } else if (game.phase === 1) { + if (card === 52) { + game.tactics_fails = power_cards[game.played_power_card].name + game.phase = 0 + next_player() + do_valid_cards() + } else if (power_cards[game.played_power_card].value === 1) { + log('Takes initiative') + game.phase = 0 + do_valid_cards() + } else { + game.phase = 2 + } + } + }, + roll () { + let roll = Math.floor(Math.random() * 6) + 1 + log(`Roll: D${roll}`) + if (roll >= power_cards[game.played_power_card].value) { + log('Initiative roll successful') + game.phase = 0 + do_valid_cards() + } else { + log(`Initiative roll failed. Required ${power_cards[game.played_power_card].value} or more`) + game.phase = 0 + next_player() + do_valid_cards() + } + }, + concede () { + push_undo() + game.valid_cards = [] + log('Conceded') + log_h2('Aftermath') + log_h3('Support Loss') + //if ((game.played_power_card >= 25 && game.played_power_card <= 30) || game.played_power_card === 53) {game.rally_win = 2} + //if ((game.played_power_card >= 31 && game.played_power_card <= 36) || game.played_power_card === 54) {game.petition_win = 2} + if (game.phase === 0) { + game.played_power_card = 0 /*If conceded when held the initiative but had no playable cards, ignore the last played card */ + } + game.phase = 0 + game.state = 'support_loss' + }, + strike () { + log(`Played: P${power_cards[game.played_power_card].number} as a Strike`) + game.played_power_card = 9 + game.phase = 1 + next_player() + do_valid_cards() + }, + march () { + log(`Played: P${power_cards[game.played_power_card].number} as a March`) + game.played_power_card = 21 + game.phase = 1 + next_player() + do_valid_cards() + }, + rally () { + log(`Played: P${power_cards[game.played_power_card].number} as a Rally in the Square`) + game.played_power_card = 53 + game.phase = 1 + next_player() + do_valid_cards() + }, + petition () { + log(`Played: P${power_cards[game.played_power_card].number} as a Petition`) + game.played_power_card = 54 + game.phase = 1 + next_player() + do_valid_cards() + }, + /*draw () { + if (game.active === DEM) { + draw_cards(game.power_struggle_deck, game.dem_pwr_hand, game.com_pwr_hand, game.dem_pwr_hand.length+2, game.com_pwr_hand.length) + } else {draw_cards(game.power_struggle_deck, game.dem_pwr_hand, game.com_pwr_hand, game.dem_pwr_hand.length, game.com_pwr_hand.length+2)} + game.phase = 0 + next_player() + do_valid_cards() + },*/ + /*infl(space) { + game.remove_opponent_infl = true + remove_infl(space) + game.phase = 6 + }, + discard () { /*Is this still needed? + if (game.active === DEM) {discard_card(game.dem_pwr_hand)} + else {discard_card(game.com_pwr_hand)} + game.available_ops -- + }, */ + done () { + if (game.phase === 7) { /*Is this ever called anymore? */ + game.phase = 0 + log_msg_gap('Takes initiative') + do_valid_cards() + } else { + game.phase = 0 + next_player() + do_valid_cards() + } + } +} + +states.support_loss ={ + inactive: 'do Support Loss.', + prompt () { + if (!game.persistent_events.includes(111)) { + if (game.phase === 0) { + view.prompt = 'You lost the Power Struggle. Roll a die for Support Loss.' + gen_action('roll') + } else if (game.phase === 1 && game.available_ops > 0 && game.valid_spaces.length > 0) { + view.prompt = `Power Struggle - ${country_name(game.pwr_struggle_in)}. Support Loss: remove ${pluralize(game.available_ops,'SP')}.` + + for (let space_id of game.valid_spaces) { + gen_action_infl(space_id) + } + } else if (game.phase === 1 && game.available_ops === 0 ) { + view.prompt = `Power Struggle - ${country_name(game.pwr_struggle_in)}. Support Loss: finished.` + gen_action('done') + } else if (game.phase === 1 && game.valid_spaces.length === 0) { + view.prompt = `Power Struggle - ${country_name(game.pwr_struggle_in)}. Support Loss: no remaining SPs to remove.` + gen_action('done') + } + } else { + if (game.phase === 0) { + view.prompt = 'You lost the Power Struggle. Roll a die for Support Loss.' + gen_action('roll') + } else if (game.phase === 1 && game.available_ops > 0 && game.valid_spaces.length > 0) { + view.prompt = `New Year's Eve Party - ${country_name(game.pwr_struggle_in)}. Support Loss: remove ${pluralize(game.available_ops,'SP')}.` + + for (let space_id of game.valid_spaces) { + gen_action_infl(space_id) + } + } else if (game.phase === 1 && game.available_ops === 0 ) { + view.prompt = `New Year's Eve Party - ${country_name(game.pwr_struggle_in)}. Support Loss: finished.` + gen_action('done') + } else if (game.phase === 1 && game.valid_spaces.length === 0) { + view.prompt = `New Year's Eve Party - ${country_name(game.pwr_struggle_in)}. Support Loss: no remaining SPs to remove.` + gen_action('done') + } + } + }, + roll () { + clear_undo() + let roll = Math.floor(Math.random() * 6) + 1 + let rally_win = 0 + let petition_win = 0 + log(`Roll: D${roll}`) + if ((game.played_power_card >= 25 && game.played_power_card <= 30) || game.played_power_card === 53) { rally_win = 2} + if ((game.played_power_card >= 31 && game.played_power_card <= 36) || game.played_power_card === 54) { petition_win = 2} + let modified_roll = roll + game.raised_stakes + rally_win - petition_win + + // Roll modifiers + if (game.active === COM && game.persistent_events.includes(62)) { + log('+1 from C62') + modified_roll ++ + } + + if (modified_roll < 0) {modified_roll = 0} + else if (modified_roll > 7) {modified_roll = 7} + + + if (game.raised_stakes !== 0) { + log(`+${game.raised_stakes} from Raising the Stakes`) + } + if (rally_win !== 0) { + log('+2 from winning on a P25') + } + if (petition_win !== 0) { + log('-2 from winning on a P31') + } + if (modified_roll !== roll) { + log(`Modified roll: ${modified_roll}`) + } + game.available_ops = support_loss_roll[modified_roll] + if (game.available_ops === 0) { + log('Does not remove SPs') + } + game.phase++ + if (game.available_ops > 0) { + valid_spaces_support_loss() + } + }, + infl (space) { + game.remove_opponent_infl = false /* Don't know why this is needed... */ + remove_infl(space) + if (game.available_ops === 0 ) { + game.valid_spaces = [] + } + }, + done () { + if (game.summary.length > 0) { + pop_summary() + log_br() + } + next_player() + log_h3('Victory Point') + game.phase = 0 + game.state = 'vp_roll' + } +} + +states.vp_roll = { + inactive: 'do VP Roll.', + prompt () { + if (!game.persistent_events.includes(111)) { + if (game.phase === 0) { + view.prompt = `Power Struggle - ${country_name(game.pwr_struggle_in)}: roll a die for Victory.` + gen_action('roll') + } else if (game.phase === 1) { + view.prompt = `Power Struggle - ${country_name(game.pwr_struggle_in)}: take power.` + gen_action('take') + } else if (game.phase === 2) { + view.prompt = `Power Struggle - ${country_name(game.pwr_struggle_in)}: proceed to scoring.` + gen_action('scoring') + } + } else { + if (game.phase === 0) { + view.prompt = `New Year's Eve Party - ${country_name(game.pwr_struggle_in)}: roll a die for Victory.` + gen_action('roll') + } else if (game.phase === 1) { + view.prompt = `New Year's Eve Party - ${country_name(game.pwr_struggle_in)}: take power.` + gen_action('take') + } else if (game.phase === 2) { + view.prompt = `New Year's Eve Party - ${country_name(game.pwr_struggle_in)}: proceed to scoring.` + gen_action('scoring') + } + } + }, + roll () { + let roll = Math.floor(Math.random() * 6) + 1 + log(`Roll: D${roll}`) + let rally_win = 0 + let petition_win = 0 + if ((game.played_power_card >= 25 && game.played_power_card <= 30) || game.played_power_card === 53) {rally_win = 2} + if ((game.played_power_card >= 31 && game.played_power_card <= 36) || game.played_power_card === 54) {petition_win = 2} + let modified_roll = roll + game.raised_stakes + rally_win - petition_win + if (game.active === DEM && game.persistent_events.includes(62)) { + log('+1 from C62') + modified_roll ++ + } + if (modified_roll < 0) {modified_roll = 0} + else if (modified_roll > 7) {modified_roll = 7} + + if (game.raised_stakes !== 0) { + log(`+${game.raised_stakes} from Raising the Stakes`) + } + if (rally_win !== 0) { + log('+2 from winning on a P25') + } + if (petition_win !== 0) { + log('-2 from winning on a P31') + } + if (modified_roll !== roll) { + log(`Modified roll: ${modified_roll}`) + } + let vp_change = vp_roll[modified_roll] + if (game.active === DEM) { + log(`+${vp_change} VP`) + } else { + log(`-${vp_change} VP`) + } + if (roll >= 4) + //console.log('VP before', game.vp) + if (game.active === DEM) {game.vp += vp_change} + else {game.vp -= vp_change} + //console.log('VP after', game.vp) + if (game.active === DEM && modified_roll >= 4) { + game.phase = 1 + } else { + game.phase = 0 + if (game.active === DEM) {next_player()} + game.state = 'choose_power' + } + }, + take () { + push_undo() + //Find name of scoring card + let scoring_card = scoring_cards[countries.indexOf(game.pwr_struggle_in)] + permanently_remove(scoring_card) + take_power(game.pwr_struggle_in) + game.phase = 2 + }, + scoring () { + push_undo() + log_h2('Scoring') + score_country(game.pwr_struggle_in) + + //Check if The Tyrant is Gone occurs + if (game.table_cards.includes(97) && game.pwr_struggle_in === 'Romania' && game.persistent_events.includes(54)) { + game.return_state = 'finish_scoring' + if (game.active !== DEM) { + next_player() + } + game.state = 'the_tyrant_is_gone' + } else { + game.state = 'finish_scoring' + } + }, +} + +states.choose_power = { + inactive: 'choose whether to remain in power.', + prompt () { + if (game.phase === 0) { + view.prompt = 'Choose whether to remain in power.' + gen_action('retain') + gen_action('surrender') + } else if (game.phase === 1) { + view.prompt = 'Proceed to scoring.' + gen_action('scoring') + } + }, + retain() { + push_undo() + retain_power(game.pwr_struggle_in) + game.phase = 1 + }, + surrender () { + push_undo() + take_power(game.pwr_struggle_in) + permanently_remove(game.played_card) + game.phase = 1 + }, + scoring () { + push_undo() + score_country(game.pwr_struggle_in) + + //Check if The Tyrant is Gone occurs + if (game.table_cards.includes(97) && game.pwr_struggle_in === 'Romania' && game.persistent_events.includes(54)) { + game.return_state = 'finish_scoring' + if (game.active !== DEM) { + next_player() + } + game.state = 'the_tyrant_is_gone' + } else { + game.state = 'finish_scoring' + } + } +} +/* +states.score_country = { + inactive: `score country`, + prompt () { + view.prompt = 'Scoring: done.' + gen_action('done') + }, + done () { + reset_power() + /*if (game.return !== game.active) { + next_player()} + game.state = 'finish_scoring' + } +} +*/ + +states.the_tyrant_is_gone ={ + inactive: 'resolve The Tyrant is Gone.', + prompt() { + view.prompt = 'Play The Tyrant is Gone for the event.' + gen_action('event') + }, + event() { + if (game.active !== DEM) { + next_player() + } + if (game.round_player === DEM) { + game.return = COM + } else { + game.return = DEM + } + log_h3(`C97`) + game.vm_event = 97 + goto_vm(game.vm_event) + } +} + +states.finish_scoring ={ + inactive: 'finish scoring.', + prompt() { + view.prompt = 'End power struggle.' + gen_action('done') + } , + done() { + //console.log('game.return_state', game.return_state) + log_msg_gap('Power Struggle resolved') /*At this point log card dicarded or permanently removed? */ + if (game.persistent_events.includes(111)) { + game.state = 'new_years_eve_party' + return + } + if (check_vp()) { + return + } + reset_power() + end_round() + //game.state = 'end_round' + } +} + +// ======================================= END TURN STATES ========================================== + +states.end_turn_4_5_4 = { + inactive: 'verify held cards.', + prompt() { + view.prompt = 'End Turn: verify held cards.' + gen_action('check') + }, + check() { + log_h2('Verify held cards') + const dem_has_scoring_card = game.democrat_hand.some(card => scoring_cards.includes(card)) + const com_has_scoring_card = game.communist_hand.some(card => scoring_cards.includes(card)) + if (!dem_has_scoring_card && !com_has_scoring_card) { + log('No held scoring cards') + } + + if (dem_has_scoring_card && com_has_scoring_card) { + log('Both players have held scoring cards') + game.state = 'game_end_tie' + } + else if (dem_has_scoring_card) { + log('Democrat player has a held scoring card') + goto_game_over(COM, `${COM} won by held scoring card!`) + } + else if (com_has_scoring_card) { + log('Communist player has a held scoring card') + goto_game_over(DEM, `${DEM} won by held scoring card!`) + } + else if (game.persistent_events.includes(104)) { + log_h1(`New Year's Eve Party`) + game.vm_event = 104 + //Check if the Communist receives VP from The Tyrant is Gone + if (game.persistent_events.includes(97)) { + game.vp -= 2 + log(`Communist receives 2 VP from C97`) + } + game.persistent_events.push(111) + if (game.active !== DEM) { + next_player() + } + game.state = 'new_years_eve_party' + } + else if(game.turn === 10) { + clear_undo() + log_h2('Final Scoring') + + //Check if the Communist receives VP from The Tyrant is Gone + if (game.persistent_events.includes(97)) { + game.vp -= 2 + log(`Communist receives 2 VP from C97`) + } + game.state = 'final_scoring_held' + + } else { + game.return_state = '' + game.state = 'end_turn' + } + } +} + +states.end_turn = { + inactive: 'end the turn.', + prompt() { + view.prompt = 'End Turn: done.' + gen_action('done') + }, + done() { + new_turn() + } +} + +states.final_scoring_held = { + inactive: 'resolve final scoring.', + prompt() { + view.prompt = 'Final Scoring: Communist scores VP bonus for the number of countries they retain power.' + gen_action('bonus') + }, + bonus() { + // console.log('game.revolutions: ', game.revolutions) + const held_countries = game.revolutions.filter(value => value === false).length + let vp_gain = 4*held_countries + log(`Communist holds ${held_countries} countries: -${vp_gain} VP`) + game.vp -= 4*held_countries + game.temp = {'East_Germany': false, 'Poland': false, 'Czechoslovakia': false, 'Hungary': false, 'Romania': false, 'Bulgaria': false} + game.state = 'final_scoring' + } +} + +states.final_scoring = { + inactive: 'score countries.', + prompt() { + if (game.temp['East_Germany'] && game.temp['Poland'] && game.temp['Czechoslovakia'] && game.temp['Hungary'] && game.temp['Romania'] && game.temp['Bulgaria']) { + view.prompt = 'Final scoring: done.' + gen_action('end') + } else { + view.prompt = 'Choose a country to score:' + if (!game.temp['East_Germany']) {gen_action('east_germany')} + if (!game.temp['Poland']) {gen_action('poland')} + if (!game.temp['Czechoslovakia']) {gen_action('czechoslovakia')} + if (!game.temp['Hungary']) {gen_action('hungary')} + if (!game.temp['Romania']) {gen_action('romania')} + if (!game.temp['Bulgaria']) {gen_action('bulgaria')} + } + }, + east_germany() { + score_country('East_Germany') + game.temp['East_Germany'] = true + }, + poland() { + score_country('Poland') + game.temp['Poland'] = true + }, + czechoslovakia() { + score_country('Czechoslovakia') + game.temp['Czechoslovakia'] = true + }, + hungary() { + score_country('Hungary') + game.temp['Hungary'] = true + }, + romania() { + score_country('Romania') + game.temp['Romania'] = true + }, + bulgaria() { + score_country('Bulgaria') + game.temp['Bulgaria'] = true + }, + end() { + delete game.temp + if (game.vp > 0) { + goto_game_over(DEM, `${DEM} wins on Victory Point Track!`) + } else if (game.vp < 0) { + goto_game_over(COM, `${COM} wins on Victory Point Track!`) + } else if (game.vp === 0) { + goto_game_over('', `The game is tied!`) /*Not sure what to pass for result */ + } + } +} + +states.game_over = { + get inactive() { + return game.victory + }, + prompt() { + view.prompt = game.victory + }, +} + +// ========================== EVENT SPECIFIC STATES ================================= + +states.general_strike = { + inactive: 'discard a card.', + prompt() { + if (game.played_card === 0 ) { + view.prompt = 'General Strike: you must discard a card or play a Scoring Card.' + available_cards = game.communist_hand + for (let card of available_cards) { + gen_action_card(card) + } + } /*else if (game.phase >= 1) { + view.prompt = 'General Strike: done.' + gen_action('done') + } */ else if (game.played_card > 0 ) { + view.prompt = 'General Strike: roll a die.' + gen_action('roll') + } + }, + card (card) { + push_undo() + game.played_card = card + let find_card + find_card = game.communist_hand.indexOf(card) + game.communist_hand.splice(find_card, 1) + game.available_ops = get_card_ops(card) + if (scoring_cards.includes(card)) { + game.vm_event = card + log(`Played C${card} for the event`) + game.return_state = 'general_strike' + goto_vm(game.vm_event) + } else { + log(`Discarded C${cards[card].number}`) + } + }, + roll() { + clear_undo() + let roll = Math.floor(Math.random() * 6) + 1 + log(`Roll: D${roll}`) + + logi(`+${game.available_ops} ops`) + + let total = roll + game.available_ops + log(`Total: ${total}`) + + if (total > 5) { + log('The strike is over.') + permanently_remove(5) + game.persistent_events = game.persistent_events.filter(n => n !== 5) + } else { + log('The strike continues. Required 6 or more') + } + //game.phase = 1 + game.state = 'end_round' + }, /* + done () { + //end_round() + game.state = 'end_round' + }*/ +} + +states.honecker ={ + inactive: 'resolve Honecker.', + prompt() { + view.prompt = 'Honecker: you may take an extra action round.' + gen_action('extra') + gen_action('pass') + }, + extra() { + push_undo() + game.round++ + game.round_player = COM + game.persistent_events = game.persistent_events.filter(n => n !== 15) + game.state = 'choose_card' + }, + pass() { + log('C15: passed') + game.persistent_events = game.persistent_events.filter(n => n !== 15) + //end_round() + game.state = 'end_round' + } +} + +states.new_years_eve_party = { + get inactive() { + return `resolve ${clean_name(cards[104].name)}.` + }, + prompt() { + if (!game.is_pwr_struggle) { + view.prompt = `New Year's Eve Party: you may choose a country to have a final power struggle.` + if (!game.revolutions[0]) {gen_action('poland')} + if (!game.revolutions[1]) {gen_action('hungary')} + if (!game.revolutions[2]) {gen_action('east_germany')} + if (!game.revolutions[3]) {gen_action('bulgaria')} + if (!game.revolutions[4]) {gen_action('czechoslovakia')} + if (!game.revolutions[5]) {gen_action('romania')} + gen_action('pass') + } else { + view.prompt = `New Year's Eve Party: done.` + gen_action('end') + } + }, + east_germany() { + push_undo() + log('Chose to score East Germany') + game.vm_event = 42 + goto_vm(42) + }, + poland() { + push_undo() + log('Chose to score Poland') + game.vm_event = 22 + goto_vm(22) + }, + czechoslovakia() { + push_undo() + log('Chose to score Czechoslovakia') + game.vm_event = 55 + goto_vm(55) + }, + hungary() { + push_undo() + log('Chose to score Hungary') + game.vm_event = 23 + goto_vm(23) + }, + romania() { + push_undo() + log('Chose to score Romania') + game.vm_event = 95 + goto_vm(95) + }, + bulgaria () { + push_undo() + log('Chose to score Bulgaria') + game.vm_event = 43 + goto_vm(43) + }, + pass() { + push_undo() + log('No final power struggle') + if (game.vp > 0) { + goto_game_over(DEM, `New Year's Eve Party: ${DEM} wins on Victory Point Track!`) + } else if (game.vp < 0) { + goto_game_over(COM, `New Year's Eve Party: ${COM} wins on Victory Point Track!`) + } else if (game.vp === 0) { + goto_game_over('', `New Year's Eve Party: The game is tied!`) /*Not sure what to pass for result */ + } + }, + end() { + if (game.vp > 0) { + goto_game_over(DEM, `New Year's Eve Party: ${DEM} wins on Victory Point Track!`) + } else if (game.vp < 0) { + goto_game_over(COM, `New Year's Eve Party: ${COM} wins on Victory Point Track!`) + } else if (game.vp === 0) { + goto_game_over('', `CNew Year's Eve Party: The game is tied!`) /*Not sure what to pass for result */ + } + } +} + +states.stasi_end_round = { + inactive: 'choose next card due to Stasi.', + prompt() { + //console.log('game.stasi_card', game.stasi_card) + let available_cards = game.democrat_hand + if (available_cards.length === 0) { + view.prompt = 'Stasi: no cards remaining.' + gen_action('pass') + return + } + view.prompt = 'Stasi: you must select your next card to play.' + + for (let card of available_cards) { + gen_action_card(card) + } + }, + card(card) { + push_undo() + log_gap(`Democrat selected C${cards[card].number} as next card.`) + game.stasi_card = card + game.state = 'stasi_finish' + }, + pass() { + log('Stasi: Democrat has no remaining cards') + game.stasi_card = 0 + end_stasi_choose_card() + }, + end_round() { + push_undo() + if (game.stasi_card === 21) { + game.state = 'stasi_confirm' + } else { + end_stasi_choose_card() + } + } +} + +states.stasi_finish = { + inactive: 'choose next card due to Stasi.', + prompt() { + view.prompt = 'Stasi. Choose card: done.' + gen_action('done') + }, + done() { + push_undo() + if (game.stasi_card === 21) { + game.state = 'stasi_confirm' + } else { + end_stasi_choose_card() + } + } +} + +states.stasi_confirm = { + inactive: 'choose next card due to Stasi.', + prompt() { + if (game.stasi_card === 21 ) { + view.prompt = `If Common European Home selected, it must be played for Operations. Otherwise select the opponent's card instead.` + gen_action('done') + } + }, + done() { + game.playable_cards = game.playable_cards.filter( n => n !== 21) + end_stasi_choose_card() + } +} + +states.stasi_play_card = { + inactive: 'play a card.', + prompt () { /*Should get rid of the play card 'done' prompt for consistency with general play */ + /*if (game.played_card > 0) { + game.state = 'play_card' + view.prompt = 'Play card: done.' + gen_action("done"); + return;*/ + //} else + if (game.democrat_hand.length === 0) { + view.prompt = 'Stasi: you must pass.' + gen_action('pass') + } else { + view.prompt = `Stasi: you must play ${clean_name(cards[game.stasi_card].name)}.` + let available_cards = [game.stasi_card] + for (let card of available_cards) { + gen_action_card(card) + } + } + }, + card(card) { + push_undo() + //log_msg_gap(`Stasi: played C${card}`) + game.played_card = card + let find_card + find_card = game.democrat_hand.indexOf(card); + game.democrat_hand.splice(find_card, 1); + game.available_ops = get_card_ops(card) + + if (game.democrat_hand.includes(21) && cards[card].side === "C") { + game.state = 'stasi_resolve_common_european_home' + } else { + game.state = 'play_card' + } + + }, + pass () { + log('No cards remaining. Passed') + //end_round() + game.state = 'end_round' + }, + done () { + //game.stasi_card = 0 + if (game.democrat_hand.includes(21)) { + game.state = 'stasi_resolve_common_european_home' + } else { + game.state = 'play_card' + } + } +} + +states.stasi_resolve_common_european_home = { + inactive: 'play a card.', + prompt () { + view.prompt = `Do you wish to play ${clean_name(cards[game.played_card].name)} with Common European Home?` + gen_action('yes') + gen_action('no') + }, + yes() { + log(`Played with Common European Home`) + silent_discard(21) + game.vm_infl_to_do = true + game.vm_event_to_do = false + game.state = 'resolve_opponent_event' + }, + no() { + game.state = 'play_card' + } +} + + +// ==================== SUPPORTING STATE FUNCTIONS ============================= + + +function add_infl(space) { + push_undo() + //console.log('adding infl to', space) + //console.log('at start, event', game.persistent_events['austria_hungary_border_reopened'], 'ahbr', game.austria_hungary_border_reopened, 'tracker', game.austria_hungary_border_reopened_tracker) + //log(`Added 1 influence in %${space}`) + log_summary(`Added £ SP in %${space}`) + + //If AHBR - check AHBR conditions + if (game.persistent_events.includes(58)) { + if (spaces[space].country !== 'East_Germany'){ + game.austria_hungary_border_reopened_tracker = false + } + } + + // Check Genscher + if (game.persistent_events.includes(63) && game.active === DEM && spaces[space].country === 'East_Germany' && check_com_control(space)) { + game.available_ops-- + log_summary(`(-1 op due to C63)`) + } else if (check_opp_control(space)) { + game.available_ops -= 2 + //Check if Austria Hungary Border Reopened was used to place last SP in a controlled space in East Germany. If so, game.available_op will be negative + if (game.available_ops < 0) { + log_summary(`(Used +1 op from C58)`) + } + } else { + game.available_ops-- + } + + // Update influence values + if (game.active === COM) { + game.comInfl[space]++ + } else { + game.demInfl[space]++ + } + + // Check whether spaces are controlled + check_control_change(space) + + // Check Austria Hungary Border Reopened is true and condition has been met + if (game.available_ops === 0 && game.active === DEM && game.persistent_events.includes(58) && game.austria_hungary_border_reopened_tracker) { + game.available_ops ++ + log('+1 op from C58') + game.austria_hungary_border_reopened_tracker = false + game.valid_spaces = game.valid_spaces.filter(n => spaces[n].country === 'East_Germany') + } + + // If only 1 IP remaining, may not place in opponent controlled spaces + + // Check for Genscher & Austria Hungary Border Reopened + + if (game.available_ops === 1) { + //console.log(`in Genscher / AHBR check, game.persistent_events['genscher']`, game.persistent_events['genscher']) + if (game.active === DEM) { + if (game.persistent_events.includes(63) || (game.persistent_events.includes(58) && game.austria_hungary_border_reopened_tracker)) { + //console.log('in gensher subcheck - remove non-East German controlled ') + game.valid_spaces = game.valid_spaces.filter(n => !(check_opp_control(n) && spaces[n].country !== 'East_Germany')) + } else { + //console.log('remove all controlled spaces') + game.valid_spaces = game.valid_spaces.filter(n => !check_opp_control(n)) + } + } else { + //console.log('remove all dem controlled spaces') + game.valid_spaces = game.valid_spaces.filter(n => !check_opp_control(n)) + } + } + + //Clear valid spaces if no IP remaining. + if (game.available_ops <= 0 ) { + game.valid_spaces = [] + } +} + +function remove_infl(space) { + push_undo() + //log(`Removed 1 influence from %${space}.`) + log_summary(`Removed £ SP from %${space}.`) + + if (game.remove_opponent_infl === true) { + if (game.active === COM) { + game.demInfl[space]-- + if (game.demInfl[space] === 0) { + game.valid_spaces = game.valid_spaces.filter(id => id !== space); + } + } else { + game.comInfl[space]-- + if (game.comInfl[space] === 0) { + game.valid_spaces = game.valid_spaces.filter(id => id !== space); + } + } + check_control_change(space) + + } else { + if (game.active === COM) { + game.comInfl[space]-- + if (game.comInfl[space] === 0) { + game.valid_spaces = game.valid_spaces.filter(id => id !== space); + } + } else { + game.demInfl[space]-- + if (game.demInfl[space] === 0) { + game.valid_spaces = game.valid_spaces.filter(id => id !== space); + } + } + check_control_change(space) + } + game.available_ops-- +} + +function do_sc(space) { + clear_undo() + log_gap(`Support check: %${space}`) + + //Check Helsinki Final Act + + if (game.active === COM && game.persistent_events.includes(26) && (spaces[space].socio === 5 || spaces[space].socio === 6) ) { + log('+1 VP from C26') + game.vp ++ + if (check_vp()) { + game.state = 'game.over' + //console.log('after check_vp, game.state', game.state) + return + } + } + + // Continue with Support Check Logic + + let roll = Math.floor(Math.random() * 6) + 1 + log(`Roll: D${roll}`) + + /* + //Check if support check is being done with game.played_card or a subsequent card (e.g. Common European Home, Dash for the West, etc) + if (game.vm_event > 0) { + roll+= cards[game.vm_event].ops + log(`+${cards[game.vm_event].ops} from card ops`) + } + */ + // Check for the Crowd Turns Against Ceausescu + + //else + if (game.is_pwr_struggle) { + roll += game.vm_available_ops + logi(`+${game.vm_available_ops} from Ceausescu`) + } + + // Check if in Tiananmen Square Track Award + + else if (game.state === 'vm_tst_6_sc') { + roll += get_tst_6_ops() + roll += 2 + logi('+2 TST award') + } + else { + //let modifier = 0 + let card_ops = get_card_ops(this_card()) + + roll += card_ops + logi(`+${card_ops} from card ops`) + } + + if (game.support_check_modifier > 0) { + roll += game.support_check_modifier + logi(`+${game.support_check_modifier} from event`) + } + + // Events which modify SC rolls + //Tear Gas + if (game.active === COM && game.persistent_events.includes(30) && spaces[space].socio === 6) { + roll ++ + logi('+1 from C30') + permanently_remove(30) + game.persistent_events = game.persistent_events.filter(n => n !== 30) + } + //FRG Embassies + if (game.active === DEM && spaces[space].region === 'Eastern Europe' && game.persistent_events.includes(74)) { + roll++ + logi('+1 from C74') + } + //GrenzTruppen + if (game.active === DEM && spaces[space].country === 'East_Germany' && game.persistent_events.includes(59)) { + roll-- + logi('-1 from C59') + } + //Stand Fast + if ((game.active === COM && game.stand_fast === DEM && check_dem_control(space)) || (game.active === DEM && game.stand_fast === COM && check_com_control(space))){ + roll-- + logi('-1 from C100') + } + //Elena + if (game.active === DEM && game.persistent_events.includes(101) && spaces[space].country === 'Romania') { + roll-- + logi('-1 from C101') + } + //Austria Hungary Border Reopened + if (game.active === DEM && game.persistent_events.includes(58) && game.austria_hungary_border_reopened_tracker) { + roll++ + logi(`+1 from C58`) + } + + // Continue with logic - check for adjacency + + // Events which affect adjacency - The Wall + + const adj = count_adj(space) + //console.log('adj', adj) + if (game.active === COM && game.persistent_events.includes(9) && spaces[space].country === 'East_Germany') { + logi('No adjacency for Democrats due to C9') + logi('C9 no longer in effect') + roll += adj.com_adj + if (adj.com_adj > 0) { + logi(`+${adj.com_adj} adjacency`) + } + game.persistent_events = game.persistent_events.filter(n => n !== 9) + + // Standard adjacency + } else { + if (adj.dem_adj > 0 || adj.com_adj > 0 ){ + if (game.active === DEM) { + roll += adj.dem_adj + roll -= adj.com_adj + if (adj.dem_adj > 0) { + logi(`+${adj.dem_adj} from adjacency`) + } + if (adj.com_adj > 0) { + logi(`-${adj.com_adj} from opponent adjacency`) + } + } else { + roll += adj.com_adj + roll -= adj.dem_adj + if (adj.com_adj > 0) { + logi(`+${adj.com_adj} from adjacency`) + } + if (adj.dem_adj > 0) { + logi(`-${adj.dem_adj} from opponent adjacency`) + } + } + } + + } + + // Support check calcs + log(`Modified total: ${roll}`) + const stability = spaces[space].stability + logi(`-${stability*2} (stability * 2)`) + const change_infl = Math.max(0, roll - stability*2) + if (change_infl > 0) { + log_msg_gap(`Change influence: ${change_infl} SP`) + if(game.active === DEM) { + if (change_infl > game.comInfl[space]) { + const residual = change_infl - game.comInfl[space] + game.comInfl[space] = 0 + game.demInfl[space] += residual + } else { + game.comInfl[space] -= change_infl + } + if (game.comInfl[space] === 0) { + game.valid_spaces = game.valid_spaces.filter(id => id !== space) + } + } else { + if (change_infl > game.demInfl[space]) { + const residual = change_infl - game.demInfl[space] + game.demInfl[space] = 0 + game.comInfl[space] += residual + } else { + game.demInfl[space] -= change_infl + } + if (game.demInfl[space] === 0) { + game.valid_spaces = game.valid_spaces.filter(id => id !== space) + } + } + check_control_change(space) + + } else { + log_msg_gap('Change influence: 0 SP') + } + if (game.active === COM && game.persistent_events.includes(39) && spaces[space].space_id === 66) { + log_msg_gap('+1 VP from C39') + game.vp++ + if (check_vp()) { + return + } + } + + // If Austria-Hungary Border Reopened used, all future support checks must be in East Germany + if (game.persistent_events.includes(58)){ + if (game.austria_hungary_border_reopened_tracker) { + game.valid_spaces = game.valid_spaces.filter(n => spaces[n].country === 'East_Germany') + } + } + game.selected_space = 0 + +} + +function valid_spaces_setup() { + game.valid_spaces = [] + let valid_spaces_set = new Set(); + //console.log('in vs setup, state', game.state) + for (let i =1 ; i <= 75 ; i++) { + space = spaces[i] + + if (game.state === 'com_init') { + infl = game.demInfl[i] + + if (infl === 0) { + valid_spaces_set.add(space.space_id); + } + } else if (game.state === 'dem_init') { + infl = game.comInfl[i] + if (infl === 0) { + valid_spaces_set.add(space.space_id); + } + } + } + // Convert the set to an array before returning + game.valid_spaces = Array.from(valid_spaces_set); + return game.valid_spaces; +} + +function valid_spaces_sc() { + let valid_spaces_set = new Set(); + //console.log('valid spaces sc, persistent events', game.persistent_events) + + for (let i = 1 ; i <= 75; i++) { + space = spaces[i] + + if (game.active === DEM) { + infl = game.comInfl[i] + if (infl !== 0 ) { + valid_spaces_set.add(space.space_id); + } + } else { + infl = game.demInfl[i] + if (infl !== 0 ) { + // Check Solidarity Legalised + if (game.persistent_events.includes(2) && space.space_id === 14) {continue} + + // Check Civic Forum + if (game.persistent_events.includes(90) && space.space_id === 30) {continue} + + // Check We Are the People + if (game.persistent_events.includes(48) && space.space_id === 9) {continue} + + //Check for Foreign Currency Debt Burden + if (game.persistent_events.includes(49) && space.country === game.foreign_currency_debt_burden) {continue} { + + valid_spaces_set.add(space.space_id); + + } + } + } + } + + + // Convert the set to an array before returning + game.valid_spaces = Array.from(valid_spaces_set); + + //Check for the Crown Turns Against Ceausescu + if (game.is_pwr_struggle && game.pwr_struggle_in === 'Romania' && game.persistent_events.includes(54)) { + game.valid_spaces = game.valid_spaces.filter(n => spaces[n].country === 'Romania') + } + return game.valid_spaces; +} + +function valid_spaces_support_loss() { + let valid_spaces_set = new Set(); + for (let i = 1; i < game.demInfl.length; i++) { + //console.log('spaces.length', game.demInfl.length, 'i', i) + space = spaces[i] + if (game.active === DEM) { + infl = game.demInfl[i] + if (infl > 0 && space.country === game.pwr_struggle_in) { + valid_spaces_set.add(space.space_id); + } + } else { + infl = game.comInfl[i] + if (infl > 0 && space.country === game.pwr_struggle_in) { + valid_spaces_set.add(space.space_id); + } + } + } + + // Convert the set to an array before returning + game.valid_spaces = Array.from(valid_spaces_set); + return game.valid_spaces; +} +/* +function valid_spaces_support_falters() { + let valid_spaces_set = new Set(); + if (game.active === DEM) { + for (let piece of game.pieces) { + if (!piece) continue + let space = spaces.find(s => s && s.space_id === piece.space_id); + if (space && piece.comInfl > 0 && space.country === game.pwr_struggle_in) { + valid_spaces_set.add(space.space_id); + } + } + } else { + for (let piece of game.pieces) { + if (!piece) continue + let space = spaces.find(s => s && s.space_id === piece.space_id); + if (space && piece.demInfl > 0 && space.country === game.pwr_struggle_in) { + valid_spaces_set.add(space.space_id); + } + } + } + // Convert the set to an array before returning + game.valid_spaces = Array.from(valid_spaces_set); + return game.valid_spaces; +} + */ + +function valid_spaces_infl() { + /*if (game.state.startsWith('vm')) { + console.log('valid_spaces_infl called from VM') + } else { + console.log('valid_spaces_infl called not from VM') + }*/ + // Check if function is called from the VM or not, take relevant ops variable + let ops = game.state.startsWith('vm') ? game.vm_available_ops : game.available_ops; + + let valid_spaces_set = new Set(); + // Iterate over all spaces to find the ones with the player's influence + for (let i = 1; i < game.demInfl.length; i++) { + //piece = game.pieces[i] + space = spaces[i] + + let player_influence = game.active === COM ? game.comInfl[i] : game.demInfl[i]; + + // If the piece has the player's influence, add it and its adjacent spaces to the set + if (player_influence > 0) { + valid_spaces_set.add(space.space_id); + + // Check adjacency information + let adjacent_spaces = get_adjusted_adjacency(space.space_id) + + for (let adj_space_id of adjacent_spaces) { + //console.log('adj_space_id', adj_space_id) + if (adj_space_id) { + + const adj_piece = spaces[adj_space_id]; + //console.log('adjacent piece name', adj_piece.name_unique) + + // Check if the adjacent space is controlled by the opponent + const opponent_control = check_opp_control(adj_piece.space_id) + //console.log('controlled?', opponent_control) + + //Check for Genscher. Can always place in East Germany even with 1 op + if (game.active === DEM && adj_piece.country === 'East_Germany' && game.persistent_events.includes(63)){ + // console.log('space added with genscher') + valid_spaces_set.add(adj_piece.space_id) + } + + // Otherwise, only add the adjacent space if the available_ops >= 2 or the space is not controlled by the opponent + if (ops >= 2 || !opponent_control) { + valid_spaces_set.add(adj_piece.space_id) + } + } + } + } + } + // Convert the set to an array before returning + game.valid_spaces = Array.from(valid_spaces_set); + return game.valid_spaces; +} + +function valid_cards(player_hand, presence) { + const valid_cards_set= new Set(); + if (game.phase === 0) { + for (let c of player_hand) { + let card = power_cards.find(card => card && card.number === c); + if (card.number === 52) {continue} // Never add tactics fails + if (card.name === game.tactics_fails) {continue} //Cannot play the suit of Tactics Fails + if (card.socio === 0) { + valid_cards_set.add(card.number); + } else if (leaders.includes(card.socio) && presence[card.socio]) { + valid_cards_set.add(card.number); + } + } + } else if (game.phase === 1) { + for (let c of player_hand) { + let card = power_cards.find(card => card && card.number === c); + if (card.name === power_cards[game.played_power_card].name) { + valid_cards_set.add(card.number); + } else if (leaders.includes(card.socio) && presence[card.socio]) { + valid_cards_set.add(card.number); + } else if (card.number === 52) {valid_cards_set.add(card.number)} + } + } + game.valid_cards = Array.from(valid_cards_set); + return game.valid_cards; +} + +function do_valid_cards() { + let presence = check_presence(game.pwr_struggle_in) + if (game.active === DEM) { + valid_cards(game.dem_pwr_hand, presence.dem_leaders) + + } else { + valid_cards(game.com_pwr_hand, presence.com_leaders)} +} + +function count_adj(id) { + const space = spaces[id] + let dem_adj = 0 + let com_adj = 0 + + let adjacent_spaces = get_adjusted_adjacency(space.space_id) + + for (let adj_space_id of adjacent_spaces) { + if (adj_space_id) { + const adj_piece = spaces.find(piece => piece && piece.space_id === adj_space_id); + //console.log('adj_piece.space_id', adj_piece.space_id, 'space', space) + if (adj_piece && adj_piece.space_id !== space.space_id) { + if (check_dem_control(adj_piece.space_id)) { + //console.log('added DEM space', spaces[adj_piece.space_id].name) + dem_adj++ + } + if (check_com_control(adj_piece.space_id)) { + //console.log('added COM space', spaces[adj_piece.space_id].name) + com_adj++ + } + } + } + } + //console.log('dem_adj: ', dem_adj, 'com_adj: ', com_adj) + return {dem_adj, com_adj} +} + +/*function count_adj_worker(space_id) { + const space = spaces[space_id] + let dem_adj = 0 + let com_adj = 0 + + for (let adj_space_id of space.adjacent) { + if (adj_space_id) { + const adj_space = spaces[adj_space_id] + if (adj_space && adj_space.socio === 4) { + const adj_piece = game.pieces.find(piece => piece && piece.space_id === adj_space_id ); + if (adj_piece) { + if (adj_piece.demCtrl === 1 ) { + dem_adj++ + } + if (adj_piece.comCtrl === 1 ) { + com_adj++ + } + } + } + } + } + return {dem_adj, com_adj} +} */ + +function check_control(space_id) { + //console.log('in check control, space', spaces[space_id].name_unique) + if ( (game.comInfl[space_id] - game.demInfl[space_id]) >= spaces[space_id].stability) { + return true; + } else if ((game.demInfl[space_id] - game.comInfl[space_id]) >= spaces[space_id].stability) { + //console.log('true') + return true; + } else { + //console.log('false') + return false; + } +} + +function check_opp_control(space_id) { + if (spaces[space_id].country === 'Romania') { + //console.log('in check opp control, space', spaces[space_id].name_unique) + } + if (game.active === DEM && ((game.comInfl[space_id] - game.demInfl[space_id]) >= spaces[space_id].stability)) { + if (spaces[space_id].country === 'Romania') { + //console.log('control true') + } + return true; + } else if (game.active === COM && ((game.demInfl[space_id] - game.comInfl[space_id]) >= spaces[space_id].stability)) { + //console.log('true') + return true; + } else { + //console.log('false') + return false; + } +} + +function check_dem_control(space_id) { + if ((game.demInfl[space_id] - game.comInfl[space_id]) >= spaces[space_id].stability) { + return true; + } else { + return false; + } +} + +function check_com_control(space_id) { + if ((game.comInfl[space_id] - game.demInfl[space_id]) >= spaces[space_id].stability) { + return true; + } else { + return false; + } +} + +function do_tst_attempt() { + let roll = Math.floor(Math.random() * 6) + 1; + log(`Roll: D${roll}`); + + roll += game.available_ops + logi(`+${game.available_ops} from card ops`) + + // TIANANMEN SQUARE MODIFIERS + + if (game.active === DEM && game.dem_tst_attempted === 1 || game.active === COM && game.com_tst_attempted === 1) { + roll ++; + logi('+1 from previous TST attempts') + } + if (game.active === DEM && game.dem_tst_position >= 1 && game.com_tst_position === 0) { + roll ++ + logi('+1 from TST award') + } + if (game.active === COM && game.com_tst_position >= 1 && game.dem_tst_position === 0) { + roll ++ + logi('+1 from TST award') + } + if ((game.active === DEM && cards[game.played_card].side === 'D') || (game.active === COM && cards[game.played_card].side === 'C')) { + roll ++; + logi('+1 for playing own card'); + } + if (game.active === COM && game.persistent_events.includes(53)) { + roll ++ + logi('+1 from C53') + } + log(`Modified total: ${roll}`) + + // TIANANMEN SQUARE ATTEMPT + game.return = game.active + game.return_state = 'tiananmen_square_attempt_done' + if (game.active === DEM) { + game.dem_tst_attempted_this_turn = 1 + if (roll >= dem_tst_req[game.dem_tst_position]) { + log(`${dem_tst_req[game.dem_tst_position]} required: success`) + game.dem_tst_position++ + game.dem_tst_attempted = 0 + + //Check if they have reached box 7 or 8 first + if (game.dem_tst_position === 7 && game.com_tst_position < 7) { + game.tst_7 = false + } + if (game.dem_tst_position === 8 && game.com_tst_position < 8) { + game.tst_8 = false + } + + //Check if they have caught up to box 7 or 8 + if (game.dem_tst_position >= 7 && game.com_tst_position >= 7) { + delete game.tst_7 + } + if (game.dem_tst_position >= 8 && game.com_tst_position >= 8) { + delete game.tst_8 + } + + //Check if TST events occur + if (game.dem_tst_position === 3 && game.com_tst_position < 3) {game.vm_event = 203} + else if (game.dem_tst_position === 4 && game.com_tst_position < 4) {game.vm_event = 204} + game.state = 'tiananmen_square_attempt_success' + } else { + log(`${dem_tst_req[game.dem_tst_position]} required: fail`) + game.dem_tst_attempted = 1 + game.state = 'tiananmen_square_attempt_fail' + } + } else { + game.com_tst_attempted_this_turn = 1 + if (roll >= com_tst_req[game.com_tst_position]) { + log(`${com_tst_req[game.com_tst_position]} required: success`) + game.com_tst_position++ + game.com_tst_attempted = 0 + + //Check if they have reached box 7 or 8 first + if (game.com_tst_position === 7 && game.dem_tst_position < 7) { + game.tst_7 = false + } + if (game.com_tst_position === 8 && game.dem_tst_position < 8) { + game.tst_8 = false + } + + //Check if they have caught up to box 7 or 8 + if (game.com_tst_position >= 7 && game.dem_tst_position >= 7) { + delete game.tst_7 + } + if (game.com_tst_position >= 8 && game.dem_tst_position >= 8) { + delete game.tst_8 + } + + //Check if TST events occur + if (game.com_tst_position === 3 && game.dem_tst_position < 3) {game.vm_event = 203} + else if (game.com_tst_position === 4 && game.dem_tst_position < 4) {game.vm_event = 204} + game.state = 'tiananmen_square_attempt_success' + } else { + log(`${com_tst_req[game.com_tst_position]} required: fail`) + game.com_tst_attempted = 1 + game.state = 'tiananmen_square_attempt_fail' + } + } +} + +function check_presence(country) { + + let dem_spaces = 0; + let com_spaces = 0; + let dem_battlegrounds = 0; + let com_battlegrounds = 0; + let dem_leaders = {1: false, 4: false, 5: false, 6: false, 7: false}; + let com_leaders = {1: false, 4: false, 5: false, 6: false, 7: false}; + + + for (let i = 1; i < spaces.length; i++) { + let space = spaces[i] + if (space.country === country) { + + if (check_dem_control(i)) { + dem_spaces++; + if (space.battleground === 1) { + dem_battlegrounds++; + } + if (leaders.includes(space.socio)) { + dem_leaders[space.socio] = true; + } + } + if (check_com_control(i)) { + com_spaces++; + if (space.battleground === 1) { + com_battlegrounds++; + } + if (leaders.includes(space.socio)) { + com_leaders[space.socio] = true; + } + } + } + } + + // Determine domination + let dem_domination = dem_battlegrounds > com_battlegrounds && dem_spaces > com_spaces && dem_spaces - dem_battlegrounds > 0; + let com_domination = com_battlegrounds > dem_battlegrounds && com_spaces > dem_spaces && com_spaces - com_battlegrounds > 0; + + // Determine control + let total_battlegrounds = battlegrounds(country); + let dem_control = dem_battlegrounds === total_battlegrounds && dem_spaces > com_spaces; + let com_control = com_battlegrounds === total_battlegrounds && com_spaces > dem_spaces; + + return { + dem_spaces: dem_spaces, + com_spaces: com_spaces, + dem_battlegrounds: dem_battlegrounds, + com_battlegrounds: com_battlegrounds, + dem_domination: dem_domination, + com_domination: com_domination, + dem_control: dem_control, + com_control: com_control, + dem_leaders: dem_leaders, + com_leaders: com_leaders + }; +} + +function battlegrounds(country) { + let battlegrounds = 0; + if (country === "Hungary") { + battlegrounds = 4 + } else if (country === "Bulgaria") { + battlegrounds = 5 + } else { + battlegrounds = 6 + } + return battlegrounds; +} + +function take_power(country) { + + log(`Democrat takes power in ${game.pwr_struggle_in}`) + game.revolutions[find_country_index(country)] = true + game.times_held[find_country_index(country)] = 1 + +} + +function retain_power(country){ + game.times_held[find_country_index(country)]++ + let vp_gain = get_value(country)*game.times_held[find_country_index(country)] + log(`Chooses to retain power`) + log(`-${vp_gain} VP`) + game.vp -= vp_gain +} + +function score_country(country) { + log_h3(`Scoring: ${country}`) + +//Get scoring values + let value_presence = get_value(country) + let value_domination = value_presence*2 + let value_control + if (country !== "Hungary") { + value_control = value_presence*3 + } else { + value_control = 4 + } +//Log for scoring + + let dem_vp = 0 + let com_vp = 0 + //Check for presence + let presence = check_presence(country) +// console.log('presence: ', presence) + + //If one side has domination or control + if (presence.dem_control || presence.dem_domination) { + log(`Democrat:`) + if (presence.dem_control) { + log(`Control: +${value_control} VP`) + dem_vp += value_control + } + else { + log(`Domination: +${value_domination} VP`) + dem_vp += value_domination + } + log(`Battlegrounds: +${presence.dem_battlegrounds} VP`) + dem_vp += presence.dem_battlegrounds + log(`Total: +${dem_vp} VP`) + + log_gap('Communist:') + if (presence.com_spaces > 0) { + log(`Presence: -${value_presence} VP`) + com_vp -= value_presence + if (presence.com_battlegrounds >0) { + log(`Battlegrounds: -${presence.com_battlegrounds} VP`) + com_vp -= presence.com_battlegrounds + } + log(`Total: ${com_vp} VP`) + } else { + log('No presence: 0 VP') + } + + } + else if (presence.com_control || presence.com_domination) { + log('Communist:') + if (presence.com_control) { + log(`Control: -${value_control} VP`) + com_vp -= value_control + } + else { + log(`Domination: -${value_domination} VP`) + com_vp -= value_domination + } + log(`Battlegrounds: -${presence.com_battlegrounds} VP`) + com_vp -= presence.com_battlegrounds + log(`Total: ${com_vp} VP`) + + log_gap('Democrat:') + if (presence.dem_spaces > 0) { + log(`Presence: +${value_presence} VP`) + dem_vp += value_presence + if (presence.dem_battlegrounds > 0) { + log(`Battlegrounds: +${presence.dem_battlegrounds} VP`) + dem_vp += presence.dem_battlegrounds + } + log (`Total: +${dem_vp} VP`) + } else { + log('No presence: 0 VP') + } + + } + + //Otherwise, presence and battlegrounds + else { + log("No domination or control") + log_gap(`Communist:`) + if (presence.com_spaces > 0) { + log(`Presence: -${value_presence} VP`) + com_vp -= value_presence + if (presence.com_battlegrounds > 0) { + log(`Battlegrounds: -${presence.com_battlegrounds} VP`) + com_vp -= presence.com_battlegrounds + } else { + log('No battlegrounds') + } + log(`Total: ${com_vp} VP`) + } else { + log('No presence: 0 VP') + } + log_gap('Democrat:') + if (presence.dem_spaces > 0) { + log(`Presence: +${value_presence} VP`) + dem_vp += value_presence + if (presence.dem_battlegrounds > 0) { + log(`Battlegrounds: +${presence.dem_battlegrounds} VP`) + dem_vp += presence.dem_battlegrounds + } else { + log('No battlegrounds') + } + log(`Total: +${dem_vp} VP`) + } else { + log('No presence: 0 VP') + } + } + + +//Calculate change VP + /*let dem_vp = 0 + if (presence.dem_spaces > 0) {dem_vp += value_presence} + if (presence.dem_domination) {dem_vp += value_presence} + if (presence.dem_control && country !== "Hungary") { + dem_vp += value_control + } + else if (presence.dem_control && country === "Hungary") {dem_vp += 2} + dem_vp += presence.dem_battlegrounds + + let com_vp = 0 + if (presence.com_spaces > 0) {com_vp += value_presence} + if (presence.com_domination) {com_vp += value_presence} + if (presence.com_control && country !== "Hungary") {com_vp += value_presence} + else if (presence.com_control && country === "Hungary") {com_vp += 2} + com_vp += presence.com_battlegrounds */ + let change_vp = dem_vp + com_vp + game.vp += change_vp + if (change_vp > 0 ) { + log_gap(`Final change VP: +${change_vp} VP`) + } else { + log_gap(`Final change VP: ${change_vp} VP`) + } +} + +function get_value(country) { + let value + if (country === "East_Germany" || country === "Poland") {value = 3} + else if (country === "Czechoslovakia" || country === "Romania") {value = 2} + else value = 1 + return value +} + +function get_end_infl_prompt() { + view.prompt = `${clean_name(cards[this_card()].name)}. Add SPs: done.` + if (!game.vm_infl_to_do) { + gen_action('end_round') + } else { + gen_action('done') + } +} + +function permanently_remove(card) { + //console.log('permanently removing card:', card) + if (game.strategy_removed.includes(card)) {return} + //log_msg_gap(`C${cards[card].number} permanently removed`) + remove_from_discard(card) + + card_index = game.table_cards.indexOf(card) + if (card_index !== -1) { + //console.log('sub 2 called') + game.table_cards.splice(card_index, 1) + } + game.strategy_removed.push(card) + //console.log('game.strategy_removed', game.strategy_removed) +} + +function check_vp() { + if (game.vp >= 20) { + goto_game_over(DEM, `${DEM} won an Automatic Victory!`) + //console.log('after goto_game_over, game.state', game.state) + return true + } else if(game.vp <= -20) { + goto_game_over(COM, `${COM} won an Automatic Victory!`) + return true + } + return false +} + +function game_over() { + if (game.vp >= 20 || game.vp <= -20) { + return true + } else { return false} +} + +function goto_game_over(result, victory) { + game.state = "game_over" + game.active = "None" + game.result = result + game.victory = victory + log_h1("Game Over") + log(game.victory) + //console.log('game over, game.state', game.state) + return + +} + +function reset_austria_hungary_border_reopened() { + //game.austria_hungary_border_reopened_checked = false + game.austria_hungary_border_reopened_tracker = false +} + +function end_stasi_choose_card() { + game.round_player = COM + game.round ++ + log_h2(`Action Round ${game.round}`) + next_player() + game.valid_spaces = [] + if (game.persistent_events.includes(5)) { + log_h3('C5') + game.state = 'general_strike' + } else { + game.state = 'choose_card' + } +} + +function check_reformer() { + if (game.dem_tst_position !== game.com_tst_position) { + if (!game.playable_cards.includes(67)) { + game.playable_cards.push(67) + } + } else { + game.playable_cards = game.playable_cards.filter(n => n !== 67) + } + +} + +function count_scoring_cards() { + let scoring_check + if (game.active === DEM) { + scoring_check = game.democrat_hand.filter(card => scoring_cards.includes(card)).length + } else { + scoring_check = game.communist_hand.filter(card => scoring_cards.includes(card)).length + } + return scoring_check +} + +function select_card(card){ + game.played_card = card + game.temp = 0 + let find_card + if (game.active === COM) { + find_card = game.communist_hand.indexOf(card) + game.communist_hand.splice(find_card, 1) + } else { + find_card = game.democrat_hand.indexOf(card) + game.democrat_hand.splice(find_card, 1) + } + game.available_ops = get_card_ops(card) + + //Check Ligachev + if (game.active === DEM && game.persistent_events.includes(99) && card !== 14) { + log('-3 VP from C99') + game.vp -= 3 + if (check_vp()) { + return + } + game.persistent_events = game.persistent_events.filter(n => n !== 99) + } + game.state = 'play_card' + //console.log('game.state', game.state) +} + +function find_event(card) { + return variable_events.indexOf(card) +} + +function is_auto_resolve(card) { + + let ceausecu_events = [10, 41, 101, 107] + + if (card === 97) { + if (!game.persistent_events.includes(54)) { + return true + } + } + else if (ceausecu_events.includes(card) && game.persistent_events.includes(97)) { + return true + } + else if (card === 87 && !game.persistent_events.includes(86)) { + return true + } + else if (auto_resolve_events.includes(card)) { + return true + } else { + return false + } +} + +function get_events(card){ + if (event_is_playable(card)) { + if (cards[card].side === 'D') { + if (game.active === DEM) {gen_action('event')} + if (game.active === COM) {gen_action('opp_event')} + } + else if (cards[card].side === 'C') { + if (game.active === COM) {gen_action('event')} + if (game.active === DEM) {gen_action('opp_event')} + } + else { + gen_action('event') + } + } +} + +function event_is_playable(card) { +// console.log('game.stasi_card', game.stasi_card, 'card', card) + //Reformer never playable here + if (card === 67) { + return false + } + //Check for Common European Hmme under Stasi + else if (game.stasi_card === 21 && card === 21 && game.active === DEM) { + return false + } + //Check for The Chinese Solution + else if (game.com_tst_position === 8 && card === 96) { + return true + } + //Then check normally + else if (cards[card].playable) { + return true + } else if (game.playable_cards.includes(card)) { + return true + } else { + return false + } +} + +function get_card_ops(card) { + let ops = 0 + + if (card) { + ops = cards[card].ops + } + if (game.persistent_events.includes(25) && game.active === COM) { + if(game.state === 'choose_card' || game.state === 'stasi_play_card') { + log('+1 op from C25') + } + ops ++ + } + if (game.persistent_events.includes(50) && game.active === DEM) { + if(game.state === 'choose_card' || game.state === 'stasi_play_card' || game.state === 'vm_laszlo_tokes') { + log('+1 op from C50') + } + ops ++ + } + + if ((game.active === DEM && game.dem_tst_position >= 2 && game.com_tst_position <= 1 && cards[card].ops === 1) || (game.active === COM && game.com_tst_position >=2 && game.dem_tst_position <= 1 && cards[card].ops === 1)) { + if(game.state === 'choose_card' || game.state === 'stasi_play_card') { + log('+1 op from Tiananmen Square Track') + } + ops ++ + } + + if ((game.active === DEM && game.prudence && game.prudence.DEM !== 0)) { + if(game.state === 'choose_card' || game.state === 'stasi_play_card' || game.state === 'vm_laszlo_tokes') { + if (ops > 2) { + log(`${pluralize(game.prudence.DEM,'op')} from C8`) + } else { + if (ops > 1) { + log(`-1 op from C8`) + } + } + } + ops += game.prudence.DEM + + if (ops < 1) { + ops = 1 + } + } + + if (game.active === COM && game.prudence && game.prudence.COM < 0) { + if(game.state === 'choose_card') { + if (ops > 2) { + log(`${pluralize(game.prudence.COM,'op')} from C8`) + } else if (ops > 1) { + log(`-1 op from C8`) + } + } + ops += game.prudence.COM + if (ops < 1) { + ops = 1 + } + } return ops +} + +function get_tst_6_ops() { + let ops = 0 + + if (game.persistent_events.includes(25) && game.active === COM) { + log('+1 op from C25') + ops ++ + } + if (game.persistent_events.includes(50) && game.active === DEM) { + log('+1 op from C50') + ops ++ + } + + if ((game.active === DEM && game.prudence && game.prudence.DEM !== 0)) { + if (ops > 0) { + log(`${pluralize(game.prudence.DEM,'op')} from C8`) + } else { + log(`-1 op from C8`) + } + + ops += game.prudence.DEM + + if (ops < -1) { + ops = -1 + } + } + + if (game.active === COM && game.prudence && game.prudence.COM < 0) { + + if (ops > 0) { + log(`${pluralize(game.prudence.COM,'op')} from C8`) + } else { + log(`-1 op from C8`) + } + + ops += game.prudence.COM + if (ops < -1) { + ops = -1 + } + } + return ops +} + +function finish_the_wall() { + if (game.the_wall_must_go['dem_wins'] === 2) { + game.persistent_events.push(86) + log('+3 VP') + game.vp += 3 + if (check_vp()) { + return + } + for (let i = 1; i < spaces.length; i++) { + let space = spaces[i] + if (space.country === 'East_Germany' && game.comInfl[i] > 0){ + game.valid_spaces.push(space.space_id) + } + } + if (!game.vm_infl_to_do) { + if (game.round_player === DEM) { + game.return = COM + } else { + game.return = DEM + } + } + if (game.active === DEM) {next_player()} + vm_next () + } else { + permanently_remove(86) + delete game.the_wall_must_go + vm_return() + } +} + + +// =========== MOVING THROUGH TURNS ============ + +function end_round() { +// console.log('end round, game.persistent_events.includes(13)', game.persistent_events.includes(13)) + //Check if the game is over! + if (game.state === 'game_over') { + // console.log('in end') + return} + + //Check if the card has been removed or played to table, and if a card has been not been played. If not, discard. + if (!game.strategy_removed.includes(game.played_card) && !game.table_cards.includes(game.played_card) && game.played_card > 0) { + game.strategy_discard.push(game.played_card) + } + + //Reset + game.played_card = 0 + game.temp = 0 + game.vm_event = 0 + game.phase = 0 + game.remove_opponent_infl = false + game.is_pwr_struggle = false + game.vm_infl_to_do = false /*Can get rid of this and use game.return_state? */ + game.vm_event_to_do = false + game.vm_active_country = '' + game.return_state = '' + game.discard = false + game.return = '' + game.valid_cards = [] + game.valid_spaces = [] + check_common_european_home() + //game.playable_cards[find_event(21)] = true + reset_austria_hungary_border_reopened() /*This should be redundant! */ + + + // Check for duplicate card entries + let card_check + if (game.samizdat_card > 0) { + card_check = [...game.strategy_deck, ...game.strategy_discard, ...game.strategy_removed, ...game.table_cards, ...game.communist_hand, ... game.democrat_hand, game.samizdat_card]; + } else { + card_check = [...game.strategy_deck, ...game.strategy_discard, ...game.strategy_removed, ...game.table_cards, ...game.communist_hand, ... game.democrat_hand]; + } + + function check_duplicates(array) { + return new Set(array).size !== array.length; + } + + function find_duplicates(array) { + const duplicates = array.filter((item, index) => array.indexOf(item) !== index); + return [...new Set(duplicates)]; + } + + //console.log('game.strategy_deck', game.strategy_deck, 'game.strategy_discard', game.strategy_discard, 'game.strategy_removed', game.strategy_removed, 'game.table_cards', game.table_cards, 'game.communist_hand', game.communist_hand, 'game.democrat_hand', game.democrat_hand) + + if (check_duplicates(card_check)) { + console.log('card check', card_check) + const duplicates = find_duplicates(card_check) + console.log('game.strategy_deck', game.strategy_deck, 'game.strategy_discard', game.strategy_discard, 'game.strategy_removed', game.strategy_removed, 'game.table_cards', game.table_cards, 'game.communist_hand', game.communist_hand, 'game.democrat_hand', game.democrat_hand) + throw new Error(`Duplicate cards detected: ${duplicates.join(', ')}`) + } + //console.log('cards in game', card_check.length) + card_check = card_check.sort((a, b) => a - b) + //console.log('cards in game', card_check) + if (game.turn <= 3) { + if (card_check.length !== 40) { + throw new Error(`Wrong number of cards: ${card_check.length}`) + } + } else if (game.turn <=7) { + if (card_check.length !== 81) { + throw new Error(`Wrong number of cards: ${card_check.length}`) + } + } else if (card_check.length !== 110) { + throw new Error(`Wrong number of cards: ${card_check.length}`) + } + + + + //console.log('game.dem_tst_position ', game.dem_tst_position , 'game.com_tst_position ', game.com_tst_position ) + //Check if the Reformer is playable + check_reformer() + + // Check if last round and if so resolve end turn events + if (game.round_player === DEM && game.round === 7) { + if(game.persistent_events.includes(15)) { + if (game.active !== COM) { + next_player() + } + game.state = 'honecker' + return + } + else if (game.dem_tst_position >= 6 && game.com_tst_position <= 5) { + log_h2('Tiananmen Square Track Award') + if (game.active !== DEM) { + next_player() + } + game.return = game.active + clear_undo() + game.return_state = 'end_turn_4_5_4' + goto_vm(206) + return + } else if (game.com_tst_position >= 6 && game.dem_tst_position <= 5) { + log_h2('Tiananmen Square Track Award') + if (game.active !== COM) { + next_player() + } + game.return = game.active + clear_undo() + game.return_state = 'end_turn_4_5_4' + goto_vm(206) + return + } + else { + clear_undo() + game.state = 'end_turn_4_5_4' + return + } + } + + // Resolve end action round + //Stasi check + if(game.round_player === COM && game.persistent_events.includes(13)) { + //If in Honecker, turn ends + if (game.round === 8) { + clear_undo() + game.state = 'end_turn_4_5_4' + return + } + //Otherwise go to Stasi + game.round_player = DEM + if (game.active !== DEM) { + next_player() + } else { + log_h3('Democratic Action Round') + + } + if (game.democrat_hand.includes(game.stasi_card)) { + log_h3('C13') + game.state = 'stasi_play_card' + } else { + game.stasi_card = 0 + game.state = 'choose_card' + } + return + } + //Check if in extra Action Round + else if (game.round_player === COM && game.round === 8) { + clear_undo() + game.state = 'end_turn_4_5_4' + return + } + //Normal round end + else if (game.round_player===COM) { + game.round_player = DEM + if (game.active !== DEM) { + next_player() + } else { + log_h3('Democratic Action Round') + } + game.state = 'choose_card' + return + } + if (game.round_player === DEM) { + // console.log('checking stasi', game.persistent_events.includes(13)) + if(game.persistent_events.includes(13)) { + // console.log('stasi sub function') + if (game.active !== DEM) { + next_player() + } + log_h3('C13') + game.state = 'stasi_end_round' + return + } else if(game.round_player === DEM && game.persistent_events.includes(5)){ + game.state = 'general_strike' + game.round ++ + log_h2(`Action Round ${game.round}`) + game.round_player = COM + if (game.active !== COM) { + next_player() + } + log_h3('C5') + return + } else { + game.state = 'choose_card' + game.round_player = COM + game.round ++ + log_h2(`Action Round ${game.round}`) + if (game.active !== COM) { + next_player() + } + } + } + //game.state = 'choose_card' Does this do anything any more? +} + +/* +function end_turn(){ + /*End Turn sequence + TST support check + Verify held cards + New Year's Eve Party + Advance Turn Marker + +// CHECK FOR OPTIONAL SUPPORT CHECK + if (game.dem_tst_position >=6 && game.com_tst_position <= 5) { + if (game.active !== DEM) { + next_player_() + } + game.state = 'tst_support_check' + } + if (game.com_tst_position >=6 && game.dem_tst_position <= 5) { + if (game.active !== COM) { + next_player_() + } + game.state = 'tst_support_check' + } + + +//CHECK HELD CARDS + +} */ + +function new_turn() { + clear_undo() + game.turn ++ + game.round = 1 + game.valid_spaces=[] + game.active = COM + game.round_player = COM + game.dem_tst_attempted_this_turn = 0 + game.com_tst_attempted_this_turn = 0 + if (game.tst_7) {game.tst_7 = false} + if (game.tst_8) {game.tst_8 = false} + + //Remove events that only last one turn + game.persistent_events = game.persistent_events.filter(n => n !== 25) /*Perestroika*/ + game.persistent_events = game.persistent_events.filter(n => n !== 50) /*Sinatra Doctrine*/ + game.persistent_events = game.persistent_events.filter(n => n !== 13) /*Stasi*/ + game.persistent_events = game.persistent_events.filter(n => n !== 15) /*Honecker*/ + delete game.prudence + delete game.stasi_card + + //Austria Hungary Border Reopened + if (game.persistent_events.includes(58)) { + game.persistent_events = game.persistent_events.filter(n => n !== 58) + delete game.austria_hungary_border_reopened_tracker + log(`C58 no longer in effect`) + //permanently_remove(58) + } + //Elena + if (game.persistent_events.includes(101)) { + game.persistent_events = game.persistent_events.filter(n => n !== 101) + log(`C101 no longer in effect`) + //permanently_remove(101) + } + //GrenzTruppen + if (game.persistent_events.includes(59)) { + game.persistent_events = game.persistent_events.filter(n => n !== 59) + log(`C59 no longer in effect`) + //permanently_remove(59) + } + //Foreign Currency Debt Burden + if (game.persistent_events.includes(49)) { + game.persistent_events = game.persistent_events.filter(n => n !== 49) + delete game.foreign_currency_debt_burden + log(`C49 no longer in effect`) + //permanently_remove(49) + } + //FRG Embassies + if (game.persistent_events.includes(74)) { + game.persistent_events = game.persistent_events.filter(n => n !== 74) + log(`C74 no longer in effect`) + discard_from_table(74) + permanently_remove(74) + } + //Genscher + if (game.persistent_events.includes(63)) { + game.persistent_events = game.persistent_events.filter(n => n !== 63) + log(`C63 no longer in effect`) + discard_from_table(63) + permanently_remove(63) + } + //Stand Fast + if (game.persistent_events.includes(100)) { + game.persistent_events = game.persistent_events.filter(n => n !== 100) + delete game.stand_fast + log(`C100 no longer in effect`) + //permanently_remove(100) + } + + if (game.samizdat_card > 0 ) { + game.democrat_hand.push(game.samizdat_card) + delete game.samizdat_card + } + + log_h1("Turn " + game.turn) + + if (game.turn === 4) { + add_midyear() + } + if (game.turn === 8) { + add_lateyear() + } + if (game.turn > 1) { + if (game.persistent_events.includes(65)) { + game.com_hand_limit = 7 + log('Communist draws 7 cards due to C65') + //permanently_remove(65) + game.persistent_events = game.persistent_events.filter(n => n !== 65) + } + //console.log('deck', game.strategy_deck) + //console.log('game.com_hand_limit', game.com_hand_limit, 'communist hand before draw', game.communist_hand) + draw_cards(game.strategy_deck, game.democrat_hand, game.communist_hand, game.dem_hand_limit, game.com_hand_limit) + game.com_hand_limit = 8 + //console.log('communist hand after draw', game.communist_hand) + + } + + //Check if TST effects need to be resolved + if (game.dem_tst_position >=5 && game.com_tst_position <= 4) { + log_h2('Tiananmen Square Track award') + if(game.active !== DEM) { next_player() } + for (let card of game.democrat_hand) { + if (scoring_cards.includes(card)) continue + game.valid_cards.push(card) + } + game.state = 'tst_goddess' /* Goddess only name of Democrat bonus, not Communist*/ + return + } + else if (game.com_tst_position >=5 && game.dem_tst_position <= 4) { + log_h2('Tiananmen Square Track award') + if(game.active !== COM) { next_player() } + for (let card of game.communist_hand) { + if (scoring_cards.includes(card)) continue + game.valid_cards.push(card) + } + game.state = 'tst_goddess' + } else { + log_h2("Action Round " + game.round) + log_side() + //console.log('in start new AR call, game.active', game.active) + if (game.persistent_events.includes(5)) { + log_h3('C5') + game.state = 'general_strike' + } + else { + game.state = 'choose_card' + } + } +} + +function next_player() { + clear_undo() + //console.log('next player called') + if (game.active === DEM) + game.active = COM + else + game.active = DEM + + log_side() +} + +function change_player() { + clear_undo() + //console.log('next player called') + if (game.active === DEM) + game.active = COM + else + game.active = DEM +} + +function find_space_index(name_unique) { + return spaces.findIndex(space => space && space.name_unique === name_unique) +} + +function find_country_index(country) { + return countries.indexOf(country) +} + +function draw_deck(deck) { + return deck.filter(card => card && card.period === 1).map(card => card.number) +} + +function draw_cards(deck, democrat_hand, communist_hand, dem_hand_limit, com_hand_limit) { + //console.log('game.valid_cards at start of draw cards: ', game.valid_cards) + let turn = 'communist'; // Start with the communist player + //console.log('game.strategy_deck', game.strategy_deck) + //console.log('deck', deck, 'democrat_hand', democrat_hand, 'communist_hand', communist_hand, 'dem_hand_limit', dem_hand_limit, 'com_hand_limit', com_hand_limit) + while (democrat_hand.length < dem_hand_limit || communist_hand.length < com_hand_limit) { + //console.log('deck.length: ', deck.length) + //console.log('discard.length', game.strategy_discard ) + if (deck.length === 0) { + log_h3('--- Reshuffle ---') + + deck.push(...game.strategy_discard) + game.strategy_discard = [] + } + + else if (turn === 'communist' && communist_hand.length < com_hand_limit) { + communist_hand.push(draw_card(deck)); + //console.log('game.valid_cards after communist draw: ', JSON.stringify(game.valid_cards)); + turn = 'democrat'; + } else if(turn === 'communist' && communist_hand.length === com_hand_limit) { + turn = 'democrat'; + } + else if (turn === 'democrat' && democrat_hand.length < dem_hand_limit) { + democrat_hand.push(draw_card(deck)); + //console.log('democrat_hand: ', democrat_hand) + + //console.log('game.valid_cards after democrat draw: ', JSON.stringify(game.valid_cards)); + turn = 'communist'; + } + else if (turn === 'democrat' && democrat_hand.length === dem_hand_limit) { + turn = 'communist'; + } + } + + clear_undo() +} + +function draw_card(deck) { + //console.log('draw card called with:', deck) + //console.log('game.strategy_deck before', game.strategy_deck) + if (deck.length === 0) { + log_h3('--- Reshuffle ---') + + deck.push(...game.strategy_discard) + game.strategy_discard = [] + } + const randomIndex = Math.floor(Math.random() * deck.length) + //console.log('card chosen:', randomIndex) + //console.log('game.strategy_deck after', game.strategy_deck) + return deck.splice(randomIndex, 1)[0]; +} + +function discard(card) { + //console.log('in discard(card)') + let find_card + if (!game.is_pwr_struggle) { + + if (game.active === COM) { + find_card = game.communist_hand.indexOf(card) + game.communist_hand.splice(find_card, 1) + } else { + find_card = game.democrat_hand.indexOf(card) + game.democrat_hand.splice(find_card, 1) + } + if (!game.strategy_discard.includes(card)) { + game.strategy_discard.push(card) + log(`Discarded C${cards[card].number}`) + } + } else if (game.is_pwr_struggle) { + if (game.active === COM) { + find_card = game.com_pwr_hand.indexOf(card); + game.com_pwr_hand.splice(find_card, 1); + } else { + find_card = game.dem_pwr_hand.indexOf(card); + game.dem_pwr_hand.splice(find_card, 1); + } + + game.power_struggle_discard.push(card) + //log(`Discarded P${power_cards[card].number}`) + } +} +function silent_discard(card) { + //console.log('in discard(card)') + let find_card + if (!game.is_pwr_struggle) { + if (game.active === COM) { + find_card = game.communist_hand.indexOf(card) + game.communist_hand.splice(find_card, 1) + } else { + find_card = game.democrat_hand.indexOf(card) + game.democrat_hand.splice(find_card, 1) + } + if (!game.strategy_discard.includes(card)) { + game.strategy_discard.push(card) + } + } else if (game.is_pwr_struggle) { + if (game.active === COM) { + find_card = game.com_pwr_hand.indexOf(card); + game.com_pwr_hand.splice(find_card, 1); + } else { + find_card = game.dem_pwr_hand.indexOf(card); + game.dem_pwr_hand.splice(find_card, 1); + } + game.power_struggle_discard.push(card) + } +} + +function remove_from_discard(card) { + let card_index = game.strategy_discard.indexOf(card) + if (card_index !== -1) { + game.strategy_discard.splice(card_index, 1) + } +} + +function discard_card(hand) { + //let find_card + let card = Math.floor(Math.random()*hand.length) + let discarded_card = hand.splice(card, 1)[0] + if (game.is_pwr_struggle) { + if (numberless_cards.includes(discarded_card)) { + log_gap(`Discarded: P${discarded_card}`) + } else { + log_gap(`Discarded: P${discarded_card} V${power_cards[discarded_card].value}`) + } + } else { + log(`Discarded C${cards[discarded_card].number}`) + game.strategy_discard.push(discarded_card) + } + return discarded_card +} + +function discard_from_table(card) { + find_card = game.table_cards.indexOf(card) + game.table_cards.splice(find_card, 1) + game.strategy_discard.push(card) +} + + +function add_midyear() { + const mid_year = cards.filter(card => card && card.period === 2).map(card => card.number); + game.strategy_deck.push(...mid_year); + log_h3('Mid-year cards added to draw deck') +} + + +function add_lateyear() { + const late_year = cards.filter(card => card && card.period === 3).map(card => card.number) + game.strategy_deck.push(...late_year) + log_h3('Late-year cards added to draw deck') +} + +function reset_power() { + game.power_struggle_deck = [] + game.power_struggle_discard = [] + game.dem_pwr_hand = [] + game.com_pwr_hand = [] + game.phase = 1 + game.raised_stakes_round = 0 + game.raised_stakes = 0 + game.played_power_card = 0 + game.tactics_fails = '' + game.view_opp_hand = false + + if (game.persistent_events.includes(72)){ + permanently_remove(72) + game.table_cards = game.table_cards.filter(card => card !== 72) + game.persistent_events = game.persistent_events.filter(n => n !== 72) + } + if (game.persistent_events.includes(62)) { + permanently_remove(62) + game.table_cards = game.table_cards.filter(card => card !== 62) + game.persistent_events = game.persistent_events.filter(n => n !== 62) + } + if (game.persistent_events.includes(54) && game.pwr_struggle_in === 'Romania'){ + permanently_remove(54) + //game.table_cards = game.table_cards.filter(card => card !== 54) + + } + if (game.pwr_struggle_in === 'Romania' && game.persistent_events.includes(70)){ + //permanently_remove(70) + //game.table_cards = game.table_cards.filter(card => card !== 70) + game.persistent_events = game.persistent_events.filter(n => n !== 70) + } +} + +function check_control_change(space_id) { + + // Check if the Tyrant is Gone has been fulfilled + + if (game.the_tyrant_is_gone > 0 && check_dem_control(game.the_tyrant_is_gone)) { + log('+2 VP from C97') + game.vp += 2 + if (check_vp()) { + return + } + game.persistent_events = game.persistent_events.filter(n => n !== 97) + delete game.the_tyrant_is_gone + } +} + +function check_systematization() { + // Check for Systematization - may not use this space + if (game.systematization > 0) { + game.valid_spaces = game.valid_spaces.filter(n => n !== game.systematization) + } +} + +function check_common_european_home() { + if (!game.playable_cards.includes(21)) { + game.playable_cards.push(21) + } +} + +function this_card() { + return game.vm_event > 0 ? game.vm_event : game.played_card +} +/* +function get_ops(card) { + let ops = cards[card].ops + if (game.active === COM) { + //Check TST op bonus + if (ops === 1 && game.com_tst_position >=2 && game.dem_tst_position <=1) { + ops++ + } + //Events that influence ops + if (game.persistent_events.includes(25)) { + ops++ + } + if (game.prudence.COM && game.prudence.COM <0) { + ops += game.prudence.COM + } + + } else { + //Check TST op bonus + if (ops === 1 && game.dem_tst_position >=2 && game.com_tst_position <=1) { + ops++ + } + //Events that influence ops + if (game.persistent_events.includes(50)) { + ops++ + } + if (game.prudence.DEM && game.prudence.DEM <0) { + ops += game.prudence.DEM + } + } + //Ops can never be less than one + if (ops <1) { ops = 1 } + return ops +} + */ + +const pluralize = (count, noun, suffix = 's') => + `${count} ${noun}${Math.abs(count) !== 1 ? suffix : ''}` + +function clean_name(str) { + if (str && str.slice(-1) === '*') { + return str.slice(0, -1) + } else { + return str; + } +} + +function country_name(country) { + return country.replace(/_/g, ' ') +} + +// ======== LOG FUNCTIONS ============= + +function log(msg) { + game.log.push(msg) +} + +function log_br() { + if (game.log.length > 0 && game.log[game.log.length - 1] !== "") + game.log.push("") +} + +function logi(msg) { + game.log.push(">" + msg) +} + +function log_h1(msg) { + log_br() + log(".h1 " + msg) + log_br() +} + +function log_h2(msg) { + log_br() + log(".h2 " + msg) + log_br() +} + +function log_h3(msg) { + log_br() + log(".h3 " + msg) +} + +function log_gap(msg) { + log_br() + game.log.push(msg) +} + +function log_msg_gap(msg) { + game.log.push(msg) + log_br() +} + + +function log_side() { + log_br() + if (game.active === DEM) + log(".h2d " + game.active) + else + log(".h2c " + game.active) + log_br() +} + +function log_sep() { + log(".hr") +} + +function log_action(msg) { + log_br() + log(msg) +} + +// ============= SUMMARY FUNCTIONS ============= + +function push_summary() { + if (game.summary) + throw "TOO MANY SUMMARIES" + game.summary = [] +} + +function log_summary(msg) { + + if (msg.startsWith('Added') || msg.startsWith('Removed')) { + for (let item of game.summary) { + if (item[1] === msg) { + item[0]++ + return + } + } + } + game.summary.push([1, msg]) +} + +function pop_summary() { + if (game.summary.length > 0) { + for (let [n, msg] of game.summary) { + if (n > 1) { + log(msg.replace("£ SP", `${n} SPs`)); + } else { + log(msg.replace("£ SP", `${n} SP`)); + } + } + } + game.summary = [] +} + +function log_summary_place(p) { + let from = piece_space(p) + if (from !== AVAILABLE) + log_summary("% " + piece_name(p) + " from S" + from) + else + log_summary("% " + piece_name(p)) +} + +function log_summary_move_to_from(p, to) { + log_summary("% " + piece_name(p) + " to S" + to + " from S" + piece_space(p)) +} + +function log_summary_remove(p) { + log_summary("Removed % " + piece_name(p)) +} + +function log_summary_activated(p) { + log_summary("Activated % " + piece_faction_name(p)) +} + +// ============ UNDO FUNCTIONS ================== + +function clear_undo() { + if (game.undo.length > 0) + game.undo = [] +} + +function push_undo() { + let copy = {} + for (let k in game) { + let v = game[k] + if (k === "undo") + continue + else if (k === "log") + v = v.length + else if (typeof v === "object" && v !== null) + v = object_copy(v) + copy[k] = v + } + game.undo.push(copy) +} + +function pop_undo() { + let save_log = game.log + let save_undo = game.undo + game = save_undo.pop() + save_log.length = game.log + game.log = save_log + game.undo = save_undo +} + +// Fast deep copy for objects without cycles +function object_copy(original) { + if (Array.isArray(original)) { + let n = original.length + let copy = new Array(n) + for (let i = 0; i < n; ++i) { + let v = original[i] + if (typeof v === "object" && v !== null) + copy[i] = object_copy(v) + else + copy[i] = v + } + return copy + } else { + let copy = {} + for (let i in original) { + let v = original[i] + if (typeof v === "object" && v !== null) + copy[i] = object_copy(v) + else + copy[i] = v + } + return copy + } +} + + +/* =================== VM FUNCTIONS ========================== */ + +function goto_vm(proc) { + let old_vm = game.vm; + + game.state = "vm"; + game.vm = { + prompt: 0, + fp: proc, + ip: 0, + }; + + if (old_vm) { + game.vm.return_vm = old_vm; + } + + vm_exec(); +} + +function vm_exec() { + vm_inst(0)(); +} + +function vm_inst(a) { + //console.log('game.vm.fp', game.vm.fp, 'game.vm.ip', game.vm.ip) + return CODE[game.vm.fp][game.vm.ip][a] +} + +function vm_next() { + game.vm.ip++; + //console.log('vm_next called, game.vm.ip', game.vm.ip) + vm_exec(); +} + +function vm_operand(a) { + let x = CODE[game.vm.fp][game.vm.ip][a] + if (a > 0 && typeof x === "function") + return x() + return x +} + +function vm_assert_argcount(n) { + const argcount = CODE[game.vm.fp][game.vm.ip].length - 1 + if (argcount !== n) + throw Error(`ASSERT Invalid number of arguments on event ${game.vm.fp}: ${argcount} instead of ${n}`) +} + +function vm_log() { + log(vm_operand(1)); + vm_next(); +} + +function vm_if() { + //console.log('game.temp', game.temp) +// console.log('vm_operand(1)', vm_operand(1)) + if (!vm_operand(1)) { + let balance = 1 + while (balance > 0) { + ++game.vm.ip + switch (vm_operand(0)) { + case vm_if: + ++balance + break + case vm_endif: + --balance + break + case vm_else: + if (balance === 1) + --balance + break + } + if (game.vm.ip < 0 || game.vm.ip > CODE[game.vm.fp].length) + throw "ERROR" + } + } + vm_next() +} + +function vm_else() { + vm_goto(vm_endif, vm_if, 1, 1) +} + +function vm_endif() { + vm_next() +} + +function vm_goto_step(step) { + // console.log('vm_goto_step called, target:', step) + //console.log('game.vm.ip', game.vp.ip) + for (let i = game.vm.ip; i < CODE[game.vm.fp].length; i++) { + //console.log('i', i) + //console.log('step', CODE[game.vm.fp][i][0]) + if (CODE[game.vm.fp][i][0] === step) { + game.vm.ip = i; + vm_exec(); + return; + } + } + + console.log("ERROR: Target operation not found in the current procedure."); +} + + +function vm_goto(op, nop, dir, step) { + //console.log('vm_inst(0)', vm_inst(0), op, nop) +// console.log('vm_inst(0)', vm_inst(1), op, nop) + let balance = 1 + while (balance > 0) { + game.vm.ip += dir + if (vm_inst(0) === op) + --balance + if (vm_inst(0) === nop) + ++balance + if (game.vm.ip < 0 || game.vm.ip > CODE[game.vm.fp].length) + throw "ERROR" + } + game.vm.ip += step + vm_exec() +} + +function event_prompt(str) { + //console.log('event_prompt called with', str) + if (typeof str === "undefined") + str = CODE[game.vm.fp][game.vm.prompt][1] + if (typeof str === "function") + str = str() + //console.log('str:', str) + if (!str) { + str = "" + } + return str +} + +function vm_prompt() { + if (game.vm.prompt) + game.vm._prompt = game.vm.prompt + game.vm.prompt = game.vm.ip + vm_next() +} + +function pop_vm_prompt() { + if (game.vm._prompt) { + game.vm.prompt = game.vm._prompt + delete game.vm._prompt + } else { + game.vm.prompt = 0 + } +} + +function vm_return() { + + //console.log('in vm_return, game.vm_infl_to_do', game.vm_infl_to_do, 'return state', game.return_state) + + //Remove temporary vm variables + delete game.support_check_modifier + delete game.vm_max_infl + delete game.vm_influence_added + delete game.communist_hand_red + + game.vm_event = 0 /*Reset to 0 now that event has been completed. Hopefully this doesn't cause issues! */ + if (game.persistent_events.includes(58)) { + reset_austria_hungary_border_reopened() + } + + //Check if end event state is needed + if (game.is_pwr_struggle || game.state === 'vm_tst_6' || game.return_state === 'tiananmen_square_attempt_done') { + vm_end_event() + } + //Check if auto-resolve opponent event + else if (is_auto_resolve(game.played_card) && ((cards[game.played_card].side === 'C' && game.active === DEM) || (cards[game.played_card].side === 'D' && game.active === COM) )) { + vm_end_event() + } + else { + + game.state = 'vm_end_event' + /*if (!game.vm_infl_to_do) { + /*if ((game.active === DEM && game.round_player !==DEM) || (game.active === COM && game.round_player !== COM)) { + game.state = 'vm_end_event' + } else { + game.state = 'vm_end_event' + //end_round() + //} + } else { + console.log('vm_infl_to_do true') + vm_end_event() + }*/ + } +} + +function vm_end_event() { + //game.view_opp_hand = false +// console.log('in vm_return, game.return:', game.return, 'game.return_state:', game.return_state, 'game.vm_infl_to_do', game.vm_infl_to_do, 'game.vm_event_to_do', game.vm_event_to_do) + /*if (!game.vm_infl_to_do && !game.vm_event_to_do) { + if (game.round_player !== game.active) { + change_player() + log_h2('End of Action Round') + } + end_round() + return + } /*Go direct to end round if card fully resolved */ + if (game.return !== game.active) { + next_player()} + if (game.return_state === 'power_struggle') { + do_valid_cards() + } + if (game.return_state && game.return_state !== '') { + game.state = game.return_state + //console.log( 'game.state', game.state) + } + else if (game.vm_infl_to_do) { + game.state = 'resolve_opponent_event'} /*Can use game.return state for this? */ + //else {game.state = "play_card"} + else{ + end_round()} +} + +/* ================== VM ACTIONS =========================== */ + +function vm_opp_hand_false() { + game.view_opp_hand = false + vm_next() +} + +function vm_valid_spaces() { + let space_1 = vm_operand(1) + let space_2 = vm_operand(2) + let space_3 = vm_operand(3) + let space_4 = vm_operand(4) + let space_5 = vm_operand(5) + let space_6 = vm_operand(6) + game.valid_spaces = [space_1, space_2, space_3, space_4, space_5, space_6] + game.valid_spaces = game.valid_spaces.filter( n => n ) + + // Check for Systematization - may not use this space + check_systematization() + + vm_next() +} + +function vm_valid_spaces_opponent () { + let valid_spaces = [] + for (let i = 1; i < spaces.length; i++) { + let space = spaces[i] + + if (game.active === DEM) { + let infl = game.comInfl[i] + if (infl > 0) { + valid_spaces.push(space.space_id) + } + } else { + infl = game.demInfl[i] + if (infl > 0) { + valid_spaces.push(space.space_id) + } + } + } + game.valid_spaces = valid_spaces +// console.log('game.valid_spaces', game.valid_spaces) + vm_next() +} + +function vm_valid_spaces_socio () { + let valid_spaces = [] + for (let i = 1; i < spaces.length; i++) { + let space = spaces[i] + + if (space.socio === vm_operand(1)) { + valid_spaces.push(space.space_id) + } + } + game.valid_spaces = valid_spaces + + // Check for Systematization - may not use this space + if (game.systematization && game.systematization > 0) { + game.valid_spaces = game.valid_spaces.filter(n => n !== game.systematization) + } + vm_next() +} + +function vm_valid_spaces_opponent_socio () { + let valid_spaces = [] + for (let i = 1; i < spaces.length; i++) { + let space = spaces[i] + + if (game.active === DEM) { + let infl = game.comInfl[i] + if (infl > 0 && space.socio === vm_operand(1)) { + valid_spaces.push(space.space_id) + } + } else { + let infl = game.demInfl[i] + if (infl > 0 && space.socio === vm_operand(1)) { + valid_spaces.push(space.space_id) + } + } + } + game.valid_spaces = valid_spaces + // Check for Systematization - may not use this space + if (game.systematization && game.systematization > 0) { + game.valid_spaces = game.valid_spaces.filter(n => n !== game.systematization) + } + vm_next() +} + +function vm_valid_spaces_country () { + let country + if (vm_operand(1)) {country = vm_operand(1)} + else {country = game.vm_active_country} + for (let space of spaces) { + if (!space) continue + if (space.country === country) { + game.valid_spaces.push(space.space_id); + } + } + // Check for Systematization - may not use this space + if (game.systematization && game.systematization > 0) { + game.valid_spaces = game.valid_spaces.filter(n => n !== game.systematization) + } + vm_next() +} + +function vm_valid_spaces_sc () { + valid_spaces_sc() + vm_next() +} + +function vm_valid_spaces_country_opp () { + let country = '' + + if (vm_operand(1)) { + country = vm_operand(1) } + else { + country = game.vm_active_country + } + for (let space of spaces) { + if (!space) continue + if (game.active === DEM) { + if (space.country === country && game.comInfl[space.space_id] >0) { + game.valid_spaces.push(space.space_id); + } + } else { + if (space.country === country && game.demInfl[space.space_id]>0) { + game.valid_spaces.push(space.space_id); + } + } + } + vm_next() +} + +function vm_valid_spaces_country_sc () { + let valid_spaces = [] + let country = '' + //console.log('in vm_valid_spaces_country_sc') + if (vm_operand(1)) { + country = vm_operand(1) } + else { + country = game.vm_active_country + } + for (let space of spaces) { + if (!space) continue + if (game.active === DEM) { + if (space.country === country && game.comInfl[space.space_id] >0) { + valid_spaces.push(space.space_id); + } + } else { + if (space.country === country && game.demInfl[space.space_id] >0) { + //Check Solidarity Legalised + if (game.persistent_events.includes(2) && space.space_id === 14) {continue} + + //Check Civic Forum + if (game.persistent_events.includes(90) && space.space_id === 30) {continue} + + //Check We are the People + if (game.persistent_events.includes(48) && space.space_id === 9) {continue} + valid_spaces.push(space.space_id); + + //Check Foreign Currency Debt Burden + if (game.persistent_events.includes(49) && space.country === game.foreign_currency_debt_burden) {continue} + } + } + } + game.valid_spaces = valid_spaces + + //Check for Foreign Currency Debt Burden + /*if (game.persistent_events.includes(49) && game.active === COM) { + game.valid_spaces = game.valid_spaces.filter(n => spaces[n].country !== game.foreign_currency_debt_burden) + }*/ + vm_next() +} + +function vm_valid_spaces_country_socio_2() { + for (let space of spaces) { + if (!space) continue + if (space.space_id === game.systematization) continue + if ((space.country === vm_operand(1) && space.socio === vm_operand(2)) || (space.country === vm_operand(1) && space.socio === vm_operand(3))) { + game.valid_spaces.push(space.space_id); + } + } + vm_next() +} + +function vm_valid_spaces_region_socio() { + let valid_spaces = [] + for (let space of spaces) { + if (!space) continue + if (space.space_id === game.systematization) continue + if (space.region === vm_operand(1) && space.socio === vm_operand(2)) { + valid_spaces.push(space.space_id); + } + } + game.valid_spaces = valid_spaces + vm_next() +} + +function vm_valid_spaces_region_opp() { + let valid_spaces = [] + for (let space of spaces) { + if (!space) continue + let s = space.space_id + if ((game.active === DEM && space.region === vm_operand(1) && game.comInfl[s] > 0 ) || (game.active === COM && space.region === vm_operand(1) && game.demInfl[s] > 0 )) { + valid_spaces.push(space.space_id); + } + } + game.valid_spaces = valid_spaces + vm_next() +} + +function vm_valid_spaces_solidarity_legalised() { + let valid_spaces = [] + for (let i = 1; i < spaces.length; i++) { + let space = spaces[i] + let uncontrolled = (!check_control(i) && !check_opp_control(i)) + if ((space.country === 'Poland' && uncontrolled && space.socio === 3) || (space.country === 'Poland' && uncontrolled && space.socio === 4)) { + valid_spaces.push(space.space_id); + } + } + game.valid_spaces = valid_spaces + vm_next() +} + +function vm_active_country () { + game.valid_spaces = game.valid_spaces.filter(space_id => { + let space = spaces.find(s => s && s.space_id === space_id); + return space && space.country === game.vm_active_country; + }); + vm_next() +} + +function vm_take_control_prep() { + game.vm_available_ops = vm_operand(1) + game.state = 'vm_take_control' +} + +function vm_take_control(space) { + if (game.active === DEM) { + let current_infl = game.demInfl[space] + let opponent_infl = game.comInfl[space] + let stability = spaces[space].stability + + if ((current_infl - opponent_infl) < stability) { + game.demInfl[space] += stability - current_infl + opponent_infl + //game.pieces[space].demCtrl = 1 + //game.pieces[space].comCtrl = 0 + } + } else if (game.active === COM) { + let current_infl = game.comInfl[space] + let opponent_infl = game.demInfl[space] + let stability = spaces[space].stability + + if ((current_infl - opponent_infl) < stability) { + game.comInfl[space] += stability - current_infl + opponent_infl + //game.pieces[space].comCtrl = 1 + //game.pieces[space].demCtrl = 0 + } + } + game.valid_spaces = game.valid_spaces.filter(id => id !== space) + log(`Took control of %${space}`) +} + + +function vm_do_add_infl(space) { + push_undo() + //console.log('in vm_do_add_infl, space', space, 'ops', game.vm_available_ops, 'ahbr tracker', game.austria_hungary_border_reopened_tracker, 'ahbr in events', game.persistent_events.includes(58)) + + //log(`Added 1 influence in %${space}.`) + + log_summary(`Added £ SP in %${space}.`) + + //If AHBR - check AHBR condition + if (game.persistent_events.includes(58)) { + if (spaces[space].country !== 'East_Germany'){ + game.austria_hungary_border_reopened_tracker = false + } + } + + // Check Genscher + if (game.persistent_events.includes(63) && game.active === DEM && spaces[space].country === 'East_Germany') { + game.vm_available_ops-- + log_summary(`(-1 op due to C63)`) + } else if (check_opp_control(space)) { + game.vm_available_ops -= 2 + //Check if Austria Hungary Border Reopened was used to place last SP in a controlled space in East Germany. If so, game.vm_available_op will be negative + if (game.vm_available_ops < 0) { + log_summary(`(Used +1 op from C58)`) + } + } else { + game.vm_available_ops-- + } + + // Update influence values + if (game.active === COM) { + game.comInfl[space]++ + } else { + game.demInfl[space]++ + } + + // Check whether spaces are controlled + check_control_change(space) + + // Check Austria Hungary Border Reopened is true and condition has been met + if (game.vm_available_ops === 0 && game.active === DEM && game.persistent_events.includes(58) && game.austria_hungary_border_reopened_tracker) { + //console.log('in award extra op') + game.vm_available_ops ++ + log('+1 Op from C58') + game.austria_hungary_border_reopened_tracker = false + game.valid_spaces = game.valid_spaces.filter(n => spaces[n].country === 'East_Germany') + } + + // If only 1 IP remaining, may not place in opponent controlled spaces + + // Check for Genscher & Austria Hungary Border Reopened + + if (game.vm_available_ops === 1) { + + if (game.active === DEM) { + //Check Genscher and AHBR + if (game.persistent_events.includes(63) || (game.persistent_events.includes(58) && game.austria_hungary_border_reopened_tracker)) { + game.valid_spaces = game.valid_spaces.filter(n => !(check_com_control(n) && spaces[n].country !== 'East_Germany')) + } else { + game.valid_spaces = game.valid_spaces.filter(n => !check_com_control(n)) + } + } else { + game.valid_spaces = game.valid_spaces.filter(n => !check_dem_control(n)) + } + } + + //Clear valid spaces if no IP remaining. + if (game.vm_available_ops <= 0 ) { + game.valid_spaces = [] + } +} + +function vm_do_add_infl_free(space) { + push_undo() + //log(`Added 1 influence in %${space}.`) + + log_summary(`Added £ SP in %${space}.`) + + // Update influence values + if (game.active === COM) { + game.comInfl[space]++ + } else { + game.demInfl[space]++ + } + game.vm_available_ops-- + // Check whether spaces are controlled + check_control_change(space) + + + //console.log('game pieces:', game.pieces[space]) +} + +function vm_add_infl() { + if (vm_operand(1)) {game.vm_available_ops = vm_operand(1)} + game.state = 'vm_add_infl' +} + +function vm_add_infl_free() { + if (vm_operand(1)) {game.vm_available_ops = vm_operand(1)} + game.state = 'vm_add_infl_free' +} + +function vm_add_x_infl() { + game.vm_available_ops = vm_operand(1) + game.state = 'vm_add_x_infl' +} + +function vm_do_add_x_infl(space) { + push_undo() + log(`Added ${game.vm_available_ops} SPs in %${space}.`) + + + if (game.active === COM) { + game.comInfl[space] += game.vm_available_ops + } else { + game.demInfl[space] += game.vm_available_ops + } + check_control_change(space) + game.vm_available_ops = 0 + game.valid_spaces = [] +} + +function vm_add_limited_infl() { + game.vm_available_ops = vm_operand(1) + game.vm_max_infl = vm_operand(2) + game.state = 'vm_add_limited_infl' +} + +function vm_do_add_limited_infl(space, max_infl) { + push_undo() + //log(`Added 1 influence in %${space}.`) + + log_summary(`Added £ SP in %${space}.`) + game.vm_available_ops -- + + if (!game.vm_influence_added) { + game.vm_influence_added = {}; + } + + if (!game.vm_influence_added[space]) { + game.vm_influence_added[space] = 0; + } + + if (game.active === COM) { + game.comInfl[space] ++ + } else { + game.demInfl[space] ++ + } + + game.vm_influence_added[space] ++ + + //console.log('valid_spaces before update', game.valid_spaces) + //console.log('influence added:', game.vm_influence_added[space], 'max infl', max_infl) + if (game.vm_influence_added[space] === max_infl) { + game.valid_spaces = game.valid_spaces.filter(id => id !== space); + } + check_control_change(space) + if (game.vm_available_ops === 0) {game.valid_spaces = [] } +} + +function vm_remove_infl() { + game.vm_available_ops = vm_operand(1) + game.state = 'vm_remove_infl' +} + +function vm_remove_opp_infl() { + game.vm_available_ops = vm_operand(1) + game.remove_opponent_infl = true + if (game.is_pwr_struggle) { + game.state = 'vm_scare_tactics' + } else { + game.state = 'vm_remove_infl' + } +} + +function vm_remove_x_opp_infl() { + game.vm_available_ops = vm_operand(1) + game.remove_opponent_infl = true + game.state = 'vm_remove_x_infl' +} + +function vm_do_remove_infl(space) { + push_undo() + //log(`Removed 1 influence from %${space}.`) + log_summary(`Removed £ SP from %${space}.`) + + if (!game.vm_influence_added) { + game.vm_influence_added = {}; + } + + if (!game.vm_influence_added[space]) { + game.vm_influence_added[space] = 0; + } + if (game.remove_opponent_infl === true) { + if (game.active === COM) { + game.demInfl[space]-- + if (game.demInfl[space] === 0) { + game.valid_spaces = game.valid_spaces.filter(id => id !== space); + } + } else { + game.comInfl[space]-- + if (game.comInfl[space] === 0) { + game.valid_spaces = game.valid_spaces.filter(id => id !== space); + } + } + + + } else { + if (game.active === COM) { + game.comInfl[space]-- + if (game.comInfl[space] === 0) { + game.valid_spaces = game.valid_spaces.filter(id => id !== space); + } + } else { + game.demInfl[space]-- + if (game.demInfl[space] === 0) { + game.valid_spaces = game.valid_spaces.filter(id => id !== space); + } + } + } + check_control_change(space) + game.vm_influence_added[space]++ + game.vm_available_ops-- + if (game.vm_available_ops===0) {game.valid_spaces = []} +} + +function vm_do_remove_x_infl(space) { + push_undo() + + if (game.remove_opponent_infl) { + if (game.active === COM) { + if (game.demInfl[space] >= game.vm_available_ops) { + game.demInfl[space] -= game.vm_available_ops + } else { + game.vm_available_ops = game.demInfl[space] + game.demInfl[space] -= game.vm_available_ops + } + } else { + if (game.comInfl[space] >= game.vm_available_ops) { + game.comInfl[space] -= game.vm_available_ops + } else { + game.vm_available_ops = game.comInfl[space] + game.comInfl[space] -= game.vm_available_ops + } + } + } else { + if (game.active === COM) { + if (game.comInfl[space] >= game.vm_available_ops) { + game.comInfl[space] -= game.vm_available_ops + } else { + game.vm_available_ops = game.comInfl[space] + game.comInfl[space] -= game.vm_available_ops + } + } else { + if (game.demInfl[space] >= game.vm_available_ops) { + game.demInfl[space] -= game.vm_available_ops + } else { + game.vm_available_ops = game.demInfl[space] + game.demInfl[space] -= game.vm_available_ops + } + } + } + + log(`Removed ${game.vm_available_ops} SPs from %${space}`) + check_control_change(space) + + game.vm_available_ops = 0 + game.valid_spaces = [] +} + +function vm_remove_limited_opp_infl() { + game.vm_available_ops = vm_operand(1) + game.vm_max_infl = vm_operand(2) + game.remove_opponent_infl = true + game.state = 'vm_remove_limited_infl' +} + +function vm_do_remove_limited_infl(space, max_infl) { + push_undo() + log(`Removed SP from %${space}.`) + game.vm_available_ops -- + + + if (!game.vm_influence_added) { + game.vm_influence_added = {}; + } + + if (!game.vm_influence_added[space]) { + game.vm_influence_added[space] = 0; + } + + if (game.active === COM) { + game.demInfl[space] -- + if (game.demInfl[space] === 0) { + game.valid_spaces = game.valid_spaces.filter(id => id !== space) + } + } else { + game.comInfl[space] -- + if (game.comInfl[space] === 0) { + game.valid_spaces = game.valid_spaces.filter(id => id !== space) + } + } + + game.vm_influence_added[space] ++ + + if (game.vm_influence_added[space] === max_infl) { + game.valid_spaces = game.valid_spaces.filter(id => id !== space); + } + + check_control_change(space) + if (game.vm_available_ops === 0) {game.valid_spaces = []} +} + +function vm_remove_all_infl() { + game.vm_available_ops = vm_operand(1) + game.state = 'vm_remove_all_infl' +} + +function vm_do_remove_all_infl(space) { + push_undo() + log(`Removed all SP from %${space}.`) + + if (game.remove_opponent_infl === true) { + if (game.active === COM) { + game.demInfl[space] = 0 + } else { + game.comInfl[space] = 0 + } + check_control_change(space) + + } else { + if (game.active === COM) { + game.comInfl[space] = 0 + } else { + game.demInfl[space] = 0 + } + check_control_change(space) + } + game.vm_available_ops -- + game.valid_spaces = game.valid_spaces.filter(id => id !== space) +} + +function vm_replace_all_infl(space_id) { + if (game.active === DEM) { + game.demInfl[space_id] += game.comInfl[space_id] + game.comInfl[space_id] = 0 + } else { + game.comInfl[space_id] += game.demInfl[space_id] + game.demInfl[space_id] = 0 + } + check_control_change(space_id) +} + +function vm_1_support_check() { + game.vm_available_ops = 1 + game.state = 'vm_1_support_check_prep' +} + +function vm_support_check() { + game.vm_available_ops = vm_operand(1) + game.state = 'vm_support_check_prep' +} + +function vm_support_check_modified() { + game.vm_available_ops = vm_operand(1) + game.support_check_modifier = vm_operand(2) + game.state = 'vm_support_check_prep' +} + +function vm_switch_infl(id){ + push_undo() + + game.demInfl[id] -= game.vm_available_ops + game.comInfl[id] += game.vm_available_ops + log(`Replaced ${pluralize(game.vm_available_ops,'SP')} in %${id}`) + game.vm_available_ops = 0 + check_control_change(id) +} + +/* ===================== EVENT SPECIFIC FUNCTIONS ========== */ + +function vm_40th_anniversary_celebration() { + if (game.vp < 0 ) {game.vm_available_ops = 4} + else {game.vm_available_ops = 2} + vm_next() +} + +function vm_40th_anniversary_celebration_vp() { + game.vp -- + log('-1VP') + if (check_vp()) { + return + } + vm_next() +} + +function vm_adamec() { + game.state = 'vm_adamec' +} + +function vm_army_backs_revolution() { + game.persistent_events = game.persistent_events.filter(n => n !== 70) + game.playable_cards = game.playable_cards.filter(n => n !== 70) + /*if (game.table_cards.includes(70)) { + permanently_remove(70) + }*/ + vm_next() +} + +function vm_austria_hungary_border_reopened() { + game.persistent_events.push(58) + permanently_remove(58) + game.austria_hungary_border_reopened_tracker = false + //game.table_cards.push(58) + //remove_from_discard(58) + vm_next() +} + +function vm_betrayal() { + if (game.demInfl[58] > 0 ) { game.valid_spaces.push(58) } + if (game.demInfl[65] >0 ) { game.valid_spaces.push(65) } + game.vm_available_ops = Math.max(game.demInfl[58], game.demInfl[65]) + game.state = 'vm_switch_infl' +} + +function vm_breakaway_baltic_republics() { + log('+5 VP') + game.vp += 5 + game.stability++ + if (check_vp()) { + return + } + game.playable_cards.push(109) + game.playable_cards = game.playable_cards.filter(n => n !== 14) + if (!check_dem_control(56) && game.systematization !== 56) {game.valid_spaces.push(56)} + if (!check_dem_control(70)) {game.valid_spaces.push(70)} + vm_next() +} + +function vm_brought_in_for_questioning() { + if (game.active === COM) { + game.active = DEM + } + //game.return = game.active + game.phase = 0 + game.state = 'vm_brought_in_for_questioning' +} + +function vm_bulgarian_turks_expelled(){ + game.remove_opponent_infl = true + game.vp -= 2 + log('-2VP') + if (check_vp()) { + return + } + if (game.demInfl[70] > 0) {game.valid_spaces = [70]} + vm_next() +} + +function vm_ceausescu() { + let adj_cluj = false + if (game.demInfl[50] > 0 ) {adj_cluj = true} + if (game.demInfl[54] > 0 ) {adj_cluj = true} + if (game.demInfl[58] > 0 ) {adj_cluj = true} + if (game.demInfl[61] > 0 ) {adj_cluj = true} + + if (adj_cluj && game.comInfl[61]>0) { + game.valid_spaces = [61] + game.vm_available_ops = 1 + //next_player() + game.remove_opponent_infl = false + game.state = 'vm_remove_infl' + } + else {vm_next()} +} + +function vm_central_committee_reshuffle() { + game.state = 'vm_central_committee_reshuffle' +} + +function vm_civic_forum() { + log('+1 VP') + game.vp++ + if (check_vp()) { + return + } + game.persistent_events.push(90) + if (check_dem_control(31)) { + vm_next() + } else { + permanently_remove(90) + vm_return() + } +} + +function vm_common_european_home() { + let valid_cards = []; + for (let c of cards) { + //if (c === null) {continue} + if (game.active === DEM) { + if (c && c.side === 'C') { + valid_cards.push(c.number) + } + } else { + if (c && c.side === 'D') { + valid_cards.push(c.number) + } + } + } + game.valid_cards = valid_cards + game.state = 'vm_common_european_home_choose' +} + +function vm_dash_for_the_west() { + game.valid_cards = [] + for (let c of game.strategy_discard) { + if (cards[c].side === 'D' && cards[c].remove === 1 && (cards[c].playable || game.playable_cards.includes(c))) { + game.valid_cards.push(c) + } + } + game.state = 'vm_dash_for_the_west' +} + +function vm_deutsche_marks() { + let max_value = 1; + for (let c of game.democrat_hand) { + if (cards[c].ops > max_value) { + max_value = cards[c].ops + } + } + let valid_cards = []; + for (let c of game.democrat_hand) { + if (cards[c].ops === max_value) { + valid_cards.push(c); + } + } + game.valid_cards = valid_cards + game.state = 'vm_deutsche_marks_prep' +} + +function vm_domino_theory() { + game.discard = true + for (let card of game.strategy_discard) { + if (scoring_cards.includes(card)) {game.valid_cards.push(card) } + } + game.phase = 0 + game.state = 'vm_play_event_from_discard' +} + +function vm_eco_glasnost() { + game.persistent_events.push(39) + vm_next() +} + +function vm_elena(){ + game.persistent_events.push(101) + vm_next() +} + +function vm_eliminate(space_id) { + log(`Eliminated %${space_id}`) + const adjacent_spaces = spaces[space_id].adjacent.filter(Number.isInteger); + + //console.log('adjacency before: Iasi', game.pieces[53].adjacent, 'Ploesti:', game.pieces[59].adjacent, 'Bucharesti:', game.pieces[61].adjacent) + + // Eliminate the democrat influence and move the communist influence to Bucuresti + if (space_id === 61) { + game.demInfl[space_id] = 0 + game.comInfl[space_id] = 0 + } else { + game.demInfl[space_id] = 0 + game.comInfl[61] += game.comInfl[space_id] + if (game.comInfl[space_id] > 0 ) { + log(`${pluralize(game.comInfl[space_id],'Communist SP')} relocated to %61`) + } + game.comInfl[space_id] = 0 + } + //Update control in the eliminated space and in Bucuresti + check_control_change(space_id) + check_control_change(61) + +} + +function get_adjusted_adjacency(space_id) { + let adjacent_spaces = spaces[space_id].adjacent; + if (adjacent_spaces.includes(game.systematization)) { + //console.log('in get adjusted adjacency, systemization',game.systematization) + //console.log('adjacent_spaces', adjacent_spaces) + } + if (game.systematization !== 0) { + //console.log('in systematization check') + let eliminated_space_id = game.systematization; + + return adjacent_spaces.map(adj_space_id => { + if (adj_space_id === eliminated_space_id) { + // Replace the eliminated space with its adjacencies + //console.log('in map check, return', spaces[eliminated_space_id].adjacent) + return spaces[eliminated_space_id].adjacent; + } + //console.log('2nd check, return', adj_space_id) + return adj_space_id; + }).flat(); // Flatten in case the eliminated space has multiple adjacencies + } + //console.log('final adjacent spaces', adjacent_spaces) + return adjacent_spaces; +} + +function vm_exit_visas() { + game.state = 'vm_exit_visas' +} + +function vm_foreign_currency_debt_burden() { + log('+1VP') + game.vp++ + if (check_vp()) { + return + } + //game.table_cards.push(49) + //remove_from_discard(49) + game.persistent_events.push(49) + game.state = 'vm_foreign_currency_debt_burden' +} + +function vm_foreign_television() { + for (let i = 1 ; i < spaces.length; i++) { + if (i === 12) {continue} /*Does not apply to Dresden*/ + if (game.comInfl[i] > 0 ) { + game.valid_spaces.push(i) + } + } + vm_next() +} +function vm_frg_embassies() { + game.persistent_events.push(74) + game.table_cards.push(74) + remove_from_discard(74) + log('C74 in effect') + vm_next() +} + +function vm_general_strike() { + game.persistent_events.push(5) + game.table_cards.push(5) + remove_from_discard(5) + log('C5 in effect') + vm_next() +} + +function vm_genscher() { + game.persistent_events.push(63) + game.table_cards.push(63) + remove_from_discard(63) + log(`C63 in effect`) + vm_next() +} + +function vm_goodbye_lenin() { + game.view_opp_hand = true + game.communist_hand_red = [] + // Select Red cards to show + for (let card of game.communist_hand) { + if (cards[card].red) { + game.communist_hand_red.push(card) + } + } + //Check if these cards are playabl + for (let card of game.communist_hand_red) { + if (cards[card].playable || game.playable_cards.includes(card)) { + game.valid_cards.push(card) + } + } + game.state = 'vm_goodbye_lenin' +} + +function vm_government_resigns() { + for (let i = 1; i < spaces.length; i++) { + let space = spaces[i] + if (space.socio === 1 && game.comInfl[i] > 0 && !check_control(i)) { + game.valid_spaces.push(i) + } + } + game.remove_opponent_infl = true + vm_next() +} + +function vm_grenztruppen() { + game.persistent_events.push(59) + permanently_remove(59) + //game.table_cards.push(59) + //remove_from_discard(59) + vm_next() +} + +function vm_heal_our_bleeding_wounds() { + let change_vp = 0 + if (game.turn <= 3) {change_vp = -3 } + else if (game.turn <= 7) {change_vp = -1} + else change_vp = 3 + if (change_vp >0) { + log(`+${change_vp} VP`) + } else { + log(`-${change_vp} VP`) + } + game.vp += change_vp + if (check_vp()) { + return + } + vm_next() +} + +function vm_helsinki_final_act() { + game.persistent_events.push(26) + vm_next() +} + +function vm_honecker() { + game.persistent_events.push(15) + game.valid_cards = [] + for (let c of game.strategy_discard) { + if (scoring_cards.includes(c)) { + continue} + else { + game.valid_cards.push(c) + } + } + game.discard = true + game.state = 'vm_honecker' +} + +function vm_inflationary_currency() { + game.state = 'vm_inflationary_currency' +} + +function vm_inflationary_currency_discard() { + // This function starts with the player who is playing Inflationary Currency for the Event + // Switch player and check the hand of their opponent to see if the have cards with ops > 3 to discard + next_player() + if (game.active === COM) { + for (let card of game.communist_hand){ + if (get_card_ops(card) >= 3) { + game.valid_cards.push(card) + } + } + } else { + for (let card of game.democrat_hand){ + if (get_card_ops(card) >= 3) { + game.valid_cards.push(card) + } + } + } + game.state = 'vm_inflationary_currency_discard' +} + +function vm_kiss_of_death() { + game.state = 'vm_kiss_of_death' +} + +function vm_klaus_and_komarek() { + if (game.comInfl[29] > 0 ) {game.valid_spaces = [29]} + vm_next() +} + +function vm_kohl_proposes_reunification() { + log('+2 VP') + game.vp += 2 + if (check_vp()) { + return + } + if (game.persistent_events.includes(86)) { + game.vm_event = 87 + game.state = 'vm_common_european_home_play' + } else { + permanently_remove(87) + vm_return() + } + +} + +function vm_kremlin_coup() { + log('-3 VP') + game.vp -= 3 + game.stability ++ + if (check_vp()) { + return + } + game.support_check_modifier = 1 + //countries = ['Poland', 'Hungary', 'East_Germany', 'Bulgaria', 'Czechoslovakia', 'Romania'] + //revolutions: {'East_Germany': false, 'Poland': false, 'Czechoslovakia': false, 'Hungary': false, 'Romania': false, 'Bulgaria': false} + game.temp = [] + countries.forEach(country => { + if (!game.revolutions[find_country_index(country)]) { + game.temp.push(country) + } + }) + game.state = 'vm_kremlin_coup_choose_country' +} + +function vm_laszlo_tokes() { + game.persistent_events.push(73) + game.playable_cards.push(107) + game.state = 'vm_laszlo_tokes' +} + +function vm_legacy_of_martial_law() { + game.vm_available_ops = 1 + game.state = 'vm_switch_infl' +} + +function vm_legacy_of_1968() { + for (let i = 1; i < spaces.length; i++) { + let space = spaces[i] + if ((!check_com_control(i) && space.country === 'Czechoslovakia')) { + game.valid_spaces.push(space.space_id); + } + } + vm_next() +} + +function vm_li_peng() { + game.persistent_events.push(53) + //game.table_cards.push(53) + remove_from_discard(53) + vm_next() +} + +function vm_ligachev() { + game.persistent_events.push(99) + vm_next() +} + +function vm_malta_summit() { + game.state = 'vm_malta_summit' +} + +function vm_massacre_in_timisoara() { + game.persistent_events = game.persistent_events.filter(n => n !== 73) + vm_next() +} + +function vm_modrow() { + game.playable_cards.push(15) + game.state = 'vm_modrow' +} + +function vm_nagy_reburied(){ + if (game.comInfl[43] > 0) { + game.valid_spaces.push(43) + } + vm_next() +} + +function vm_national_salvation_front() { + game.persistent_events.push(102) + game.table_cards.push(102) + remove_from_discard(102) + vm_next() +} + +function vm_nepotism() { + game.state = 'vm_nepotism' +} + +function vm_new_years_eve_party() { + game.state = 'vm_new_years_eve_party' +} + +function vm_nomenklatura() { + game.state = 'vm_nomenklatura' +} + +function vm_normalisation() { + if (game.demInfl[27] >0) {game.valid_spaces.push(27)} + if (game.demInfl[29] > 0) {game.valid_spaces.push(29)} + game.remove_opponent_infl = true + vm_next() +} + +function vm_peasant_parties_revolt() { + game.persistent_events.push(72) + log_msg_gap('C72 in effect') + game.table_cards.push(72) + remove_from_discard(72) + vm_next() +} + +function vm_perestroika() { + game.persistent_events.push(25) + log_msg_gap('C25 in effect') + vm_next() +} + +function vm_poszgay() { + let valid_spaces = [] + for (let space of spaces) { + if (space && space.country === 'Hungary' && !check_dem_control(space.space_id)) { + valid_spaces.push(space.space_id); + } + } + game.valid_spaces = valid_spaces + vm_next() +} + +function vm_power_struggle() { + //console.log('in vm_power_struggle. game.vm_event', game.vm_event, 'game.active', game.active, 'game.view_opp_hand', game.view_opp_hand) + game.is_pwr_struggle = true + + /* TO DELETE? + //Check if Power Struggle is because of an event + */ + + if (game.vm_event > 0) { + game.pwr_struggle_in = countries[scoring_cards.indexOf(game.vm_event)] + log_h2(`C${game.vm_event}`) + } +/* + //Otherwise set Power Struggle country normally + else { + console.log('vm_power_struggle, country set normally') + game.pwr_struggle_in = countries[scoring_cards.indexOf(game.played_card)] + log_h2(`C${game.played_card}`) + }*/ + + + //Check for Securitate + if (game.pwr_struggle_in === 'Romania' && game.persistent_events.includes(70)) { + log('C70: Democrat reveals Power Struggle cards') + game.view_opp_hand = true + } + log_h2('Deal Cards') + game.state = 'draw_power_cards' +} + +function vm_presidential_visit() { + game.persistent_events.push(65) + //game.table_cards.push(65) + //remove_from_discard(65) + log_msg_gap('C65 in effect') + vm_next() +} + +function vm_prudence() { + if (!game.prudence) { + game.prudence = {DEM: 0, COM: 0} + } + if (game.active === DEM) { + game.prudence.COM -- + log(`${game.prudence.COM} to Communist ops this turn`) + } else { + game.prudence.DEM -- + log(`${game.prudence.DEM} to Democrat ops this turn`)} + vm_next() +} + +function vm_public_against_violence() { + game.valid_spaces = [] + if (game.comInfl[34] > 0 ) {game.valid_spaces.push(34)} + vm_next() +} + +function vm_reformer_rehabilitated () { + permanently_remove(67) + game.discard = true + for (let card of game.strategy_discard) { + if (!event_is_playable(card)) continue + if (card === game.played_card) continue + if (game.table_cards.includes(card)) continue + if (scoring_cards.includes(card)) continue + + game.valid_cards.push(card) + } + game.state = 'vm_play_event_from_discard' +} + +function vm_roundtable_talks() { + game.persistent_events.push(17) + game.table_cards.push(17) + remove_from_discard(17) + log_msg_gap('C17 in effect') + vm_next() +} + +function vm_sajudis_check() { + if (!check_dem_control(56)) { + game.valid_spaces.push(56) + } + if (!check_dem_control(70)) { + game.valid_spaces.push(70) + } + vm_next() +} + +function vm_sajudis() { + game.playable_cards.push(81) + game.stability++ + log('+1 VP') + game.vp++ + if (check_vp()) { + return + } + vm_next() +} + +function vm_samizdat() { + game.state = 'vm_samizdat' +} + +function vm_securitate() { + game.persistent_events.push(70) + permanently_remove(70) + //game.table_cards.push(70) + vm_next() +} + +function vm_shock_therapy() { + game.state = 'vm_shock_therapy' +} + +function vm_social_democratic_platform_adopted() { + game.state = 'vm_social_democratic_platform_adopted' +} + +function vm_solidarity_legalised() { + log_msg_gap(`C2 in effect`) + game.playable_cards.push(3) + game.persistent_events.push(2) + vm_next() +} + +function vm_st_nicholas_church () { + game.persistent_events.push(24) + game.playable_cards.push(61) + vm_next() +} + +function vm_stasi() { + log_msg_gap('C13 in effect') + game.persistent_events.push(13) + vm_next() +} + +function vm_stand_fast() { + game.persistent_events.push(100) + if (game.active === DEM) { + game.stand_fast = DEM + } else {game.stand_fast = COM} + //game.table_cards.push(100) + vm_next() +} + +function vm_systematization() { + game.state = 'vm_systematization' +} + +function vm_tank_column() { + if (game.active === DEM) { + game.dem_tst_position++ + game.dem_tst_attempted = 0 + } else { + game.com_tst_position++ + game.com_tst_attempted = 0 + } + vm_next() +} + +function vm_tear_gas () { + game.persistent_events.push(30) + game.table_cards.push(30) + remove_from_discard(30) + log_msg_gap('C30 in effect') + vm_next() +} + +function vm_the_baltic_way() { + game.playable_cards.push(84) + game.stability++ + if (!check_dem_control(56) && game.systematization !== 56) {game.valid_spaces.push(56)} + if (!check_dem_control(70) && game.systematization !== 70) {game.valid_spaces.push(70)} + log('+3 VP') + game.vp += 3 + if (check_vp()) { + return + } + vm_next() +} + +function vm_the_chinese_solution() { + game.state = 'vm_the_chinese_solution' +} + +function vm_the_crowd_turns_against_ceausescu() { + game.table_cards.push(54) + remove_from_discard(54) + game.playable_cards.push(97) + vm_next() +} + +function vm_the_monday_demonstrations() { + if (!check_dem_control(6)) {game.valid_spaces.push(6)} + if (!check_dem_control(9)) {game.valid_spaces.push(9)} + vm_next() +} + +function vm_the_sinatra_doctrine() { + game.persistent_events.push(50) + log_msg_gap('C50 in effect') + vm_next() +} + +function vm_the_third_way() { + log('-2VP') + vm_next() +} + +function vm_the_tyrant_is_gone() { + game.valid_spaces = [] + for (let i = 1; i < spaces.length; i++) { + let space = spaces[i] + if (game.demInfl[i] === 0 && space.country === 'Romania') { + if (space.space_id === game.systematization) {continue} + game.valid_spaces.push(space.space_id) + } + } + game.state = 'vm_the_tyrant_is_gone' +} + + +function vm_the_tyrant_is_gone_prep() { + game.table_cards.push(97) + remove_from_discard(97) + vm_next() +} + +function vm_tyrant_block() { + logi(`Has no effect after C97`) + vm_next() + //game.state = 'vm_tyrant_block' +} + +function vm_the_wall () { + game.persistent_events.push(9) + //game.strategy_removed.push(9) + //game.table_cards.push(9) + log_msg_gap('C9 in effect') + vm_next() +} + +function vm_the_wall_must_go() { + game.the_wall_must_go = {} + game.the_wall_must_go['dem_wins'] = 0 + game.the_wall_must_go['com_wins'] = 0 + game.the_wall_must_go['dem_roll'] = 0 + game.the_wall_must_go['com_roll'] = 0 + game.state = 'vm_the_wall_must_go' +} + +function vm_warsaw_pact_summit() { + game.warsaw_pact_summit = true /*What does this do? */ + game.state = 'vm_warsaw_pact_summit' +} + +function vm_we_are_the_people() { + if (game.demInfl[6] > 0) {game.valid_spaces = [6]} + game.persistent_events.push(48) + if (!game.vm_influence_added) { + game.vm_influence_added = {}; + } + game.vm_influence_added[6] = 0 + game.vm_available_ops = 4 + game.state = 'vm_we_are_the_people_remove' +} + +function vm_workers_revolt() { + if (game.active === DEM) { + for (let space of spaces) { + if (!space) continue + let country = space.country + if (!game.revolutions[find_country_index(country)] && game.comInfl[space.space_id] > 0 && space.socio === 4) { + game.valid_spaces.push(space.space_id); + } + } + } else { + for (let space of spaces) { + if (!space) continue + let country = space.country + if (game.revolutions[find_country_index(country)] && game.demInfl[space.space_id] > 0 && space.socio === 4) { + game.valid_spaces.push(space.space_id); + } + } + } + game.state = 'vm_workers_revolt' +} + +function vm_yakovlev_counsels_gorbachev() { + game.persistent_events.push(62) + log_msg_gap('C62 in effect') + game.table_cards.push(62) + remove_from_discard(62) + vm_next() +} + +function vm_permanently_remove () { + // Check if the event is being played as the result of another card, e.g. Dash for the West, is a card which should be removed, and which hasn't already been removed! + if (game.vm_event !== 0 && cards[game.vm_event].remove === 1 && !game.strategy_removed.includes(game.vm_event)) { + permanently_remove(game.vm_event) + } + if (cards[game.played_card].remove ===1 && !game.strategy_removed.includes(game.played_card)) { + permanently_remove(game.played_card) + } /*This means the card that called the event being played is also removed if relevant. Think this makes sense */ + vm_next() +} + +function discarded_card() { + return game.temp > 0 +} + +// =================== TIANANMEN SQUARE TRACK FUNCTIONS ==================== + +function vm_tst_3() { + log_gap('Tiananmen Square Track award') + game.state = 'vm_tst_3_prep' +} + +function vm_tst_4() { + log_gap('Tiananmen Square Track award') + game.vm_available_ops = 2 + game.remove_opponent_infl = true + game.state = 'vm_tst_4' +} +function vm_tst_6() { + log_h3('Tiananmen Square Track award') + game.vm_available_ops = 1 + game.temp = 1 //Set temp to 1, so that Card 1 is called during the support check, which has 2 ops + game.state = 'vm_tst_6' +} + +function vm_tst_8() { + game.state = 'vm_goodbye_lenin_ops' // Use this to resolve ops. +} + +// ==================== POWER STRUGGLE FUNCTIONS ====================== + +function vm_scare_tactics() { + game.vm_active_country = game.pwr_struggle_in + vm_next() +} +function vm_support_surges() { + game.state = 'vm_support_surges_1' +} + +function vm_support_falters() { + game.vm_available_ops = 2 + game.return === game.active + game.state = 'vm_support_falters' +} + +function vm_kremlin_coup_elite() { + game.valid_spaces=[] + elite_spaces.forEach(space => { + if (spaces[space].country === game.vm_active_country && !check_com_control(space)) { + game.valid_spaces.push(space); + } + }) + game.state = 'vm_kremlin_coup_take_control' +} + +/* ================== VM STATES ============================== */ + +states.vm_end_event = { + get inactive() { + return `resolve ${clean_name(cards[this_card()].name)}.` + }, + prompt () { + view.prompt = `${clean_name(cards[this_card()].name)}: done.` + if (game.vm_infl_to_do || game.return_state === 'vm_tst_8') { + gen_action('done') + } else { + gen_action('end_round') + } + }, + done() { + push_undo() + vm_end_event() + }, + end_round() { + push_undo() + game.return_state = '' + vm_end_event() + } +} + +states.vm_take_control = { + get inactive() { + return `resolve ${clean_name(cards[game.played_card].name)}.` + }, + prompt () { + if (game.vm_available_ops > 0 && game.valid_spaces.length === 0) { + view.prompt = `${clean_name(cards[this_card()].name)}: all spaces controlled. Continue.` + gen_action('done') + } else if (game.vm_available_ops > 0 ) { + view.prompt = `${clean_name(cards[this_card()].name)}: take control of ${event_prompt()}.` + for (let space_id of game.valid_spaces) { + gen_action_infl(space_id); + } + } else { + view.prompt = `${clean_name(cards[this_card()].name)}. Take control: done.` + if (game.vm_infl_to_do) { + gen_action('done') + } else { + gen_action('end_round') + } + } + }, + infl(space) { + push_undo() + vm_take_control(space) + game.vm_available_ops-- + if (game.vm_available_ops === 0) { + game.valid_spaces = [] + vm_next() + } + }, + done() { + push_undo() + vm_next() + }, + end_round() { + push_undo() + vm_next() + } +} + +states.vm_add_infl = { + inactive: 'add Support Points.', + prompt () { + if (game.vm_available_ops > 0 && game.valid_spaces.length === 0 ) { + view.prompt = `${clean_name(cards[this_card()].name)}. No available spaces remaining. Add SPs: done.` + gen_action('done') + } + else if (game.vm_available_ops > 0 ) { + view.prompt = `${clean_name(cards[this_card()].name)}: add ${pluralize(game.vm_available_ops,'SP')}${event_prompt()}.` + + for (let space_id of game.valid_spaces) { + gen_action_infl(space_id) + } + } else { + get_end_infl_prompt() + } + }, + infl(space) { + vm_do_add_infl(space) + if (game.vm_available_ops === 0) { + game.valid_spaces = [] + if (game.summary.length > 0) { + pop_summary() + log_br() + } + + game.vm_event_done = true + vm_next() + } + }, + done () { + push_undo() + if (game.summary.length > 0) { + pop_summary() + log_br() + } + + game.vm_event_done = true + vm_next() + }, + end_round() { + push_undo() + if (game.summary.length > 0) { + pop_summary() + log_br() + } + + game.vm_event_done = true + vm_next() + } +} + +states.vm_add_infl_free = { + get inactive() { + return `resolve ${clean_name(cards[this_card()].name)}: add SPs.` + }, + prompt () { + if (game.vm_available_ops > 0 && game.valid_spaces.length === 0 ) { + view.prompt = `${clean_name(cards[this_card()].name)}. No available spaces remaining. Add SPs: done.` + gen_action('done') + } else if (game.vm_available_ops > 0 ) { + view.prompt = `${clean_name(cards[this_card()].name)}: add ${game.vm_available_ops} SPs to ${event_prompt()}.` + + for (let space_id of game.valid_spaces) { + gen_action_infl(space_id); + } + } else { + get_end_infl_prompt() + } + }, + infl(space) { + vm_do_add_infl_free(space) + if (game.vm_available_ops === 0) { + game.valid_spaces = [] + if (game.summary.length > 0) { + pop_summary() + log_br() + } + + game.vm_event_done = true + vm_next() + } + }, + done () { + push_undo() + game.valid_spaces = [] + game.vm_event_done = true + if (game.summary.length > 0) { + pop_summary() + log_br() + } + vm_next() + }, + end_round () { + push_undo() + game.valid_spaces = [] + game.vm_event_done = true + if (game.summary.length > 0) { + pop_summary() + log_br() + } + vm_next() + } +} + +states.vm_add_x_infl = { + get inactive() { + return `resolve ${clean_name(cards[this_card()].name)}: add Support Points.` + }, +// inactive: `resolve ${cards[this_card()].name}: add influence.`, + prompt () { + if (game.vm_event === 101 && game.valid_spaces.length === 0) { + view.prompt = `${clean_name(cards[this_card()].name)}: the Romanian Elite space no longer exists.` + gen_action('done') + } + else if (game.vm_available_ops > 0 ) { + view.prompt = `${clean_name(cards[this_card()].name)}: Add ${game.vm_available_ops} SPs to ${event_prompt()}.` + + for (let space_id of game.valid_spaces) { + gen_action_infl(space_id) + } + } /*else { + view.prompt = `${clean_name(cards[this_card()].name)}. Add SPs: done.` + gen_action('done') + }*/ + }, + infl(space) { + push_undo() + vm_do_add_x_infl(space) + if (game.vm_available_ops === 0) { + game.vm_event_done = true + vm_next() + } + /*if (game.vm_event === (105 || 68) { + vm_next() + return + } */ + + + //game.vm_event_done = true + //vm_next() + }, + done () { + push_undo() + game.vm_event_done = true + vm_next() + } +} + +states.vm_add_limited_infl = { + get inactive() { + return `resolve ${clean_name(cards[this_card()].name)}: add Support Points.` + }, + prompt () { + if (game.vm_available_ops > 0 && game.valid_spaces.length > 0) { + if (game.vm_max_infl === 1) { + view.prompt = `${clean_name(cards[this_card()].name)}: add ${pluralize(game.vm_max_infl,'SP')} ${event_prompt()}.` + } + else { + view.prompt = `${clean_name(cards[this_card()].name)}: add ${pluralize(game.vm_available_ops,'SP')} to ${event_prompt()}.` + } + for (let space_id of game.valid_spaces) { + gen_action_infl(space_id); + } + } /*else { + view.prompt = `${clean_name(cards[this_card()].name)}. Add SPs: done.` + gen_action('done') + }*/ + }, + infl(space) { + vm_do_add_limited_infl(space, game.vm_max_infl) + if (game.vm_available_ops === 0 || game.valid_spaces.length === 0) { + game.valid_spaces = [] + if (game.summary.length > 0) { + pop_summary() + log_br() + } + game.vm_event_done = true + vm_next() + } + }, + /*done () { + push_undo() + if (game.summary.length > 0) { + pop_summary() + log_br() + } + game.vm_event_done = true + vm_next() + }*/ +} + +states.vm_remove_infl = { + inactive: 'remove Support Points.', + prompt () { + // Keep this so that there is an undo option in, e.g., Scare Tactics + if (game.valid_spaces.length === 0 && game.vm_available_ops > 0) { + view.prompt = `${clean_name(cards[this_card()].name)}: no further SPs to remove.` + gen_action('done') + return + } + if (game.vm_available_ops === 0 ) { + view.prompt = `${clean_name(cards[this_card()].name)}. Remove SPs: done.` + gen_action('done') + return + } + if (game.remove_opponent_infl) { + view.prompt = `${clean_name(cards[this_card()].name)}: remove ${pluralize(game.vm_available_ops, 'opponent SP')}${event_prompt()}.` + } + else { + view.prompt = `${clean_name(cards[this_card()].name)}: remove ${pluralize(game.vm_available_ops,'SP')}${event_prompt()}.` + } + for (let space_id of game.valid_spaces) { + gen_action_infl(space_id); + } + }, + infl(space) { + push_undo() + vm_do_remove_infl(space) + game.vm_active_country = spaces[space].country + if (game.vm_event !== 44) { + if (game.vm_available_ops === 0 ) { + if (game.summary.length > 0) { + pop_summary() + log_br() + } + vm_next() + } + } + }, + done() { + if (game.summary.length > 0) { + pop_summary() + log_br() + } + vm_next() + } +} + + +states.vm_remove_x_infl = { + get inactive() { + return `resolve ${clean_name(cards[this_card()].name)}: remove SP from ${event_prompt()}.` + }, + prompt () { + if (game.valid_spaces.length === 0 && game.vm_available_ops > 0) { + view.prompt = `${clean_name(cards[this_card()].name)}: no SPs to remove.` + gen_action('done') + } else if (game.vm_available_ops > 0) { + + view.prompt = `${clean_name(cards[this_card()].name)}: remove ${pluralize(game.vm_available_ops,'SP')} from ${event_prompt()}.` + + for (let space_id of game.valid_spaces) { + gen_action_infl(space_id); + } + } /*else { + if (game.vm_infl_to_do) { + view.prompt = `${clean_name(cards[this_card()].name)}. Remove SPs: done. Return control to phasing player.` + gen_action('done') + return + } else { + view.prompt = `${clean_name(cards[this_card()].name)}. Remove SPs: done.` + gen_action('done') + return + } + }*/ + }, + infl(space) { + vm_do_remove_x_infl(space) + /*if (game.vm_event === 68) { + vm_next() + return + }*/ + if (game.vm_available_ops === 0) { + game.vm_event_done = true + vm_next() + } + /*game.vm_event_done = true + vm_next()*/ + }, + done () { + game.vm_event_done = true + vm_next() + } +} + +states.vm_remove_limited_infl = { + inactive: 'remove SP.', + prompt () { + if (game.vm_available_ops > 0 && game.valid_spaces.length > 0) { + view.prompt = `${clean_name(cards[this_card()].name)}: remove ${pluralize(game.vm_available_ops,'SP')}${event_prompt()}, no more than ${game.vm_max_infl} per space.` + + for (let space_id of game.valid_spaces) { + gen_action_infl(space_id); + } + } else if (game.valid_spaces.length === 0 && game.vm_available_ops > 0) { + view.prompt = `${clean_name(cards[this_card()].name)}: no further SP to remove.` + gen_action('done') + } /*else { + if (game.vm_infl_to_do) { + view.prompt = `${clean_name(cards[this_card()].name)}. Remove SPs: done. Return control to phasing player.` + gen_action('done') + return + } else { + view.prompt = `${clean_name(cards[this_card()].name)}. Remove SPs: done.` + gen_action('done') + return + } + }*/ + }, + infl(space) { + vm_do_remove_limited_infl(space, game.vm_max_infl) + if (game.vm_available_ops === 0) { + game.vm_event_done = true + if (game.summary.length > 0) { + pop_summary() + log_br() + } + vm_next() + } + }, + done () { + game.vm_event_done = true + if (game.summary.length > 0) { + pop_summary() + log_br() + } + vm_next() + } +} + +states.vm_remove_all_infl = { + inactive: 'remove Support Points', + prompt () { + if (game.valid_spaces.length === 0 && game.vm_available_ops > 0) { + view.prompt = `${clean_name(cards[this_card()].name)}: no SPs to remove.` + gen_action('pass') + } else if (game.vm_available_ops > 0) { + view.prompt = `${clean_name(cards[this_card()].name)}: remove all SPs from ${event_prompt()}.` + for (let space_id of game.valid_spaces) { + gen_action_infl(space_id); + } + } /*else { + view.prompt = `${clean_name(cards[this_card()].name)}. Remove SPs: done.` + gen_action('done') + }*/ + }, + infl(space) { + vm_do_remove_all_infl(space) + game.vm_active_country = spaces[space].country + if (game.vm_available_ops === 0) { + vm_next() + } + }, + pass() { + push_undo() + vm_next() + } +} + +states.vm_support_check_prep = { + inactive: 'do support checks.', + prompt () { + /*if (game.vm_available_ops === 0) { + view.prompt = `${clean_name(cards[this_card()].name)}. Support check: done.` + gen_action('done') + } else */ + if (game.valid_spaces.length === 0) { + view.prompt = `${clean_name(cards[this_card()].name)}: no valid targets for support check.` + gen_action('done') + } else { + //if (game.vm_available_ops > 0) { + view.prompt = `${clean_name(cards[this_card()].name)}: ${event_prompt()}. ${pluralize(game.vm_available_ops, 'support check')} remaining.` + //} + for (let space_id of game.valid_spaces) { + if (!space_id) continue + gen_action_sc(space_id); + } + } + }, + sc(space) { + push_undo() + game.selected_space = space + + // Check for Austria-Hungary Border Reopened - check on first support check only + //First check for Monday Demonstrations - support checks will always be in East Germany + if (game.vm_event === 61 && game.persistent_events.includes(58)) { + game.austria_hungary_border_reopened_tracker = true + game.state = 'vm_do_support_check' + return + } + + //Then check Austria-Hungary Border Reopened normally + //console.log('game.austria_hungary_border_reopened_checked', game.austria_hungary_border_reopened_checked) + if (game.persistent_events.includes(58)) { + if (game.active === DEM && game.vm_available_ops > 1) { + if (spaces[game.selected_space].country === 'East_Germany' && game.persistent_events.includes(58) && game.active === DEM) { + game.state = 'vm_austria_hungary_border_reopened_check' + return + } + //game.state = 'do_support_check' + } /*else { */ + } + game.state = 'vm_do_support_check' + }, + done () { + push_undo() + game.vm_available_ops = 0 + vm_next () + } +} + +states.vm_ceh_support_check_prep = { + inactive: 'do support checks.', + prompt () { + /*if (game.vm_available_ops === 0) { + view.prompt = 'Support checks: done.' + gen_action('done') + return + }*/ + if (game.vm_available_ops > 0) { + view.prompt = `Select a space. ${pluralize(game.vm_available_ops, 'support check')} remaining.` + + for (let space_id of game.valid_spaces) { + gen_action_sc(space_id) + } + } + }, + sc(space) { + push_undo() + game.selected_space = space + + //Then check Austria-Hungary Border Reopened normally + //console.log('game.austria_hungary_border_reopened_checked', game.austria_hungary_border_reopened_checked) + if (game.persistent_events.includes(58)) { + if (game.active === DEM && game.vm_available_ops > 1) { + + if (spaces[game.selected_space].country === 'East_Germany' && game.persistent_events.includes(58) && game.active === DEM) { + game.state = 'vm_austria_hungary_border_reopened_check' + return + } + //game.state = 'do_support_check' + } /*else { */ + } + game.state = 'vm_ceh_do_support_check' + }, + /*done () { + vm_next () + }*/ +} + + +states.vm_ceh_do_support_check = { + inactive: 'do support checks.', + prompt () { + view.prompt = `Support check: ${spaces[game.selected_space].name_unique}. Roll a die.` + gen_action('roll') + }, + roll() { + clear_undo() + do_sc(game.selected_space) + + game.vm_available_ops-- + if (game.vm_available_ops === 0) { + game.valid_spaces = [] + vm_next() + } else { + game.state = 'vm_ceh_support_check_prep' + return + } + } +} + +states.vm_austria_hungary_border_reopened_check = { + inactive: 'decide Austria-Hungary Border Reopened', + prompt() { + view.prompt = 'Austria-Hungary Border Reopened: will all support checks be in East Germany?' + gen_action('yes') + gen_action('no') + }, + yes() { + game.austria_hungary_border_reopened_tracker = true + game.state = 'vm_do_support_check' + }, + no() { + game.state = 'vm_do_support_check' + } +} + +states.vm_1_support_check_prep = { + inactive: 'do support checks.', + prompt () { + /*if (game.vm_available_ops === 0) { + view.prompt = `${clean_name(cards[this_card()].name)}. Support check: done.` + gen_action('done') + } else */if (game.valid_spaces.length === 0) { + view.prompt = `${clean_name(cards[this_card()].name)}: no valid targets for support check.` + gen_action('done') + } else { + view.prompt = `${clean_name(cards[this_card()].name)}: ${event_prompt()}.` + + for (let space_id of game.valid_spaces) { + if (!space_id) continue + gen_action_sc(space_id); + } + } + }, + sc(space) { + push_undo() + game.selected_space = space + game.state = 'vm_do_support_check' + }, + done () { + push_undo() + game.vm_available_ops = 0 + vm_next () + } +} + +states.vm_do_support_check = { + inactive: 'do support checks.', + prompt () { + view.prompt = `Support check: ${spaces[game.selected_space].name_unique}. Roll a die.` + gen_action('roll') + }, + roll() { + clear_undo() + do_sc(game.selected_space) + game.vm_available_ops-- + if (game.vm_available_ops === 0) { + game.valid_spaces = [] + vm_next() + return + } else { + game.state = 'vm_support_check_prep' + return + } + } +} + +states.vm_tiananmen_square_attempt = { + inactive: 'do Tiananmen Square', + prompt () { + /*if (game.active === DEM && game.dem_tst_attempted_this_turn > 0 || game.active === COM && game.com_tst_attempted_this_turn > 0) { + view.prompt = 'Tiananmen Square Track attempt: done.' + gen_action('done') + return + }*/ + view.prompt = 'Tiananmen Square: roll a die' + gen_action('roll') + }, + roll() { + clear_undo() + do_tst_attempt () + }, + /*done () { + vm_next() + }*/ +} + +//================================== EVENT SPECIFIC STATES ====================================== + +states.vm_adamec = { + get inactive() { + return `resolve ${clean_name(cards[88].name)}.` + }, + prompt() { + view.prompt = 'Adamec: roll a die.' + gen_action('roll') + }, + roll() { + clear_undo() + let roll = Math.floor(Math.random() * 6) + 1 + log(`Roll: D${roll}`) + let worker_spaces = spaces.filter(space => space && space.country === 'Czechoslovakia' && space.socio === 4 && check_dem_control(space.space_id)).length + if (worker_spaces > 0) { + log(`-${worker_spaces} from Democrat controlled worker spaces`) + roll -= worker_spaces + } + log(`Modified roll: ${roll}`) + if (roll > 2) { + log('Adamec succeeds') + vm_next() + return + } + log('Adamec fails: 3 or more required') + permanently_remove(88) + vm_return() + } +} + +states.vm_brought_in_for_questioning = { + inactive: 'discard a card.', + prompt() { + /*if (game.phase === 1) { + view.prompt = 'Discard a card: done.' + gen_action('done') + } else */ + if (game.democrat_hand.length === 0) { + view.prompt = 'Brought in for Questioning. No cards to discard.' + gen_action('pass') + } else { + view.prompt = 'Brought in for Questioning: you must discard a random card.' + gen_action('discard') + } + }, + discard() { + clear_undo() + game.vm_event = discard_card(game.democrat_hand) + game.phase = 1 + if (cards[game.vm_event].side === 'C' && (cards[game.vm_event].playable || game.playable_cards.includes(game.vm_event))) { + //game.return = game.active + if (!game.vm_infl_to_do) { + if(game.round_player === DEM) { + game.return = COM + } else { + game.return = DEM + } + } + if (!is_auto_resolve(game.vm_event) && !switch_events.includes(game.vm_event)) { + next_player() + } + goto_vm(game.vm_event) + } else { + game.return = DEM + vm_return() + } + }, + pass() { + log('No cards to discard') + vm_return() + }, + /*done() { + vm_return() + }*/ +} + +states.vm_central_committee_reshuffle = { + get inactive() { + return `resolve ${clean_name(cards[57].name)}.` + }, + prompt() { + if (game.revolutions.every(n => n === true)) { + view.prompt = 'Central Committee Reshuffle: no countries to choose.' + gen_action('pass') + } else { + view.prompt = 'Central Committee Reshuffle: choose a country to add SPs.' + if (!game.revolutions[0]) {gen_action('poland')} + if (!game.revolutions[1]) {gen_action('hungary')} + if (!game.revolutions[2]) {gen_action('east_germany')} + if (!game.revolutions[3]) {gen_action('bulgaria')} + if (!game.revolutions[4]) {gen_action('czechoslovakia')} + if (!game.revolutions[5]) {gen_action('romania')} + } + }, + east_germany() { + push_undo() + game.vm_active_country = "East_Germany" + log(`Chose ${country_name(game.vm_active_country)}`) + game.valid_spaces = [1,2,3,4,5,6,7,8,9,10,11,12] + vm_next() + }, + poland() { + push_undo() + game.vm_active_country = "Poland" + log(`Chose ${country_name(game.vm_active_country)}`) + game.valid_spaces = [13,14,15,16,17,18,19,20,21,22,23,24,25,26] + vm_next() + }, + czechoslovakia() { + push_undo() + game.vm_active_country = "Czechoslovakia" + log(`Chose ${country_name(game.vm_active_country)}`) + game.valid_spaces = [27,28,29,30,31,32,33,34,35,36,37] + vm_next() + }, + hungary() { + push_undo() + game.vm_active_country = "Hungary" + log(`Chose ${country_name(game.vm_active_country)}`) + game.valid_spaces = [38,39,40,41,42,43,44,45,46,47,48,49] + vm_next() + }, + romania() { + push_undo() + game.vm_active_country = "Romania" + log(`Chose ${country_name(game.vm_active_country)}`) + game.valid_spaces = [50,51,52,53,54,55,56,57,58,59,60,61,62,63] + game.valid_spaces = game.valid_spaces.filter(space => space !== game.systematization) + vm_next() + }, + bulgaria () { + push_undo() + game.vm_active_country = "Bulgaria" + log(`Chose ${country_name(game.vm_active_country)}`) + game.valid_spaces = [64,65,66,67,68,69,70,71,72,73,74,75] + vm_next() + }, + pass() { + log('Passed') + vm_return() + } + +} + +states.vm_common_european_home_choose = { + get inactive() { + return `resolve ${clean_name(cards[game.played_card].name)}.` + }, + prompt() { + view.prompt = `Common European Home: play an opponent's card, event does not occur.` + for (let card of game.valid_cards) { + gen_action_card(card) + } + }, + card(card) { + push_undo() + //log(`Played with C${cards[card].number}`) + game.valid_cards = [] + silent_discard(card) + game.vm_event = card + game.state = 'vm_common_european_home_play' + } +} + +states.vm_common_european_home_play = { + get inactive() { + return `resolve ${clean_name(cards[this_card()].name)}.` + }, + prompt() { + view.prompt = `Play ${clean_name(cards[this_card()].name)} for:` + gen_action('influence') + gen_action('support_check') + if (game.active === DEM && game.vm_event === 87 ) { + return /*Special condition if card is actually Kohl Proposes Reunification*/ + } + /*if (game.active === DEM && game.dem_tst_attempted_this_turn === 0 || game.active === COM && game.com_tst_attempted_this_turn === 0) { + gen_action('tst') + } */ + }, + influence(){ + push_undo() + log_gap(`Played C${cards[game.vm_event].number} to place SPs`) + game.vm_available_ops = cards[game.vm_event].ops + valid_spaces_infl() + // If ABHR - Set AHBR tracker to true + if (game.persistent_events.includes(58)) { + game.austria_hungary_border_reopened_tracker = true + } + game.state = 'vm_add_infl' + }, + support_check() { + push_undo() + log_gap(`Played C${cards[game.vm_event].number} for support checks`) + game.vm_available_ops = 2 + game.state = 'vm_ceh_support_check_prep' + valid_spaces_sc() + }, + tst() { + push_undo() + log_gap(`Played C${cards[game.vm_event].number} to the Tiananmen Square Track`) + game.state = 'vm_tiananmen_square_attempt' + } +} + +states.vm_dash_for_the_west = { + get inactive() { + return `resolve ${clean_name(cards[36].name)}.` + }, + prompt() { + /* if (game.phase === 1) {*/ + view.prompt = 'Dash for the West: roll a die' + gen_action('roll') + /*} else { + view.prompt = 'Dash for the West: roll a die. Done.' + gen_action('done') + }*/ + }, + roll() { + clear_undo() + let roll = Math.floor(Math.random() * 6) + 1 + log(`Roll: D${roll}`) + let com_control = check_presence('East_Germany').com_spaces + + if (roll > com_control) { + log(`Success. More than the ${com_control} Communist controlled spaces in East Germany`) + log('+1 VP') + game.vp++ + if (check_vp()) { + return + } + game.discard = true + game.state = 'vm_play_event_from_discard' + } else { + log(`Fail: more than a ${com_control} required`) + //game.phase++ + vm_next() + } + },/* + done() { + vm_next() + }*/ +} + +states.vm_play_event_from_discard = { + get inactive() { + return `resolve ${clean_name(cards[game.played_card].name)}.` + }, + prompt() { + if (game.valid_cards.length === 0) { + view.prompt = `${clean_name(cards[this_card()].name)}: no valid cards in discard.` + gen_action('pass') + } else if (game.temp === 0) { + view.prompt = `${event_prompt()}.` + for (let card of game.valid_cards) { + gen_action('pass') + gen_action_card(card) + } + } /*else { + view.prompt = 'Choose a card: done.' + gen_action('done') + }*/ + }, + card(card) { + push_undo() + log(`Chose C${cards[card].number}`) + game.vm_event = card + game.vm_available_ops = cards[card].ops + game.discard = false + //game.return = game.active Does turning this off cause problems? + if (switch_events.includes(card)) {next_player()} + goto_vm(card) + }, + pass(){ + push_undo() + if (game.valid_cards.length === 0) { + log('No valid cards to choose') + } else{ + log('Did not choose a card') + } + vm_next() + }, +/* done(){ + push_undo() + game.discard = false + vm_next() + }*/ +} + +states.vm_deutsche_marks_prep = { + inactive: 'choose a card.', + prompt() { + if (game.valid_cards.length === 0) { + view.prompt = 'Deutsche Marks: no cards to give.' + gen_action('pass') + } else { + view.prompt = 'Deutsche Marks: choose a card to give.' + for (let card of game.valid_cards) { + gen_action_card(card) + } + } + }, + card(card) { + push_undo() + log(`Gave C${cards[card].number}`) + game.valid_cards = [] + silent_discard(card) + //next_player() + game.state = 'vm_deutsche_marks_confirm' + game.vm_event = card + }, + pass() { + push_undo() + vm_next() + } +} + +states.vm_deutsche_marks_confirm = { + inactive: 'choose a card.', + prompt() { + view.prompt = `Deutsche Marks: gave ${cards[game.vm_event].name}.` + gen_action('done') + }, + done() { + next_player() + game.state = 'vm_deutsche_marks' + } +} + +states.vm_deutsche_marks = { + get inactive() { + return `resolve ${clean_name(cards[20].name)}.` + }, + prompt() { + if(cards[game.vm_event].side === 'C' && (cards[game.vm_event].playable || game.playable_cards.includes(game.vm_event))) { + view.prompt = `Deutsche Marks: you must play ${clean_name(cards[this_card()].name)} for the event.` + gen_action('event') + } else { + view.prompt = `Deutsche Marks: play ${clean_name(cards[this_card()].name)} for:` + gen_action('influence') + gen_action('support_check') + if (game.com_tst_attempted_this_turn === 0) { + gen_action('tst') + } + } + }, + event() { + push_undo() + log(`Played C${cards[game.vm_event].number} for the event`) + if (!game.vm_infl_to_do) { + game.return = game.active + } + goto_vm(game.vm_event) + }, + influence() { + push_undo() + log(`Played C${cards[game.vm_event].number} to place SPs`) + game.vm_available_ops = get_card_ops(game.vm_event) + + /*cards[game.vm_event].ops + if (game.persistent_events.includes(25)) {game.vm_available_ops++ } + if (game.prudence.COM && game.prudence.COM < 0 ) { + game.vm_available_ops += game.prudence.COM + }*/ + valid_spaces_infl() + game.state = 'vm_add_infl' + }, + support_check() { + push_undo() + log_gap(`Played C${cards[game.vm_event].number} for support checks`) + game.vm_available_ops = 2 + game.state='vm_support_check_prep' + valid_spaces_sc() + }, + tst() { + push_undo() + log_gap(`Played C${cards[game.vm_event].number} to the Tiananmen Square Track`) + game.state='vm_tiananmen_square_attempt' + } +} + +states.vm_exit_visas = { + get inactive() { + return `resolve ${clean_name(cards[75].name)}.` + }, + prompt() { + view.prompt = 'Exit Visas: you may discard cards from your hand and draw replacements.' + for (let card of game.democrat_hand) { + gen_action_card(card) + } + if (game.temp === 0) { + gen_action('pass') + } else { + gen_action('done') + } + }, + card(card){ + push_undo() + discard(card) + game.temp++ + }, + pass() { + push_undo() + game.state = 'vm_exit_visas_finish' + }, + done() { + push_undo() + game.state = 'vm_exit_visas_finish' + } +} + +states.vm_exit_visas_finish = { + get inactive() { + return `resolve ${clean_name(cards[75].name)}.` + }, + prompt() { + if (game.temp > 0 ) { + view.prompt = 'Exit Visas: draw replacement cards.' + gen_action('draw') + } /*else { + view.prompt = 'Exit Visas. Draw cards: done.' + gen_action('done') + } */ + }, + draw() { + clear_undo() + draw_cards(game.strategy_deck, game.democrat_hand, game.communist_hand, game.democrat_hand.length + game.temp, game.communist_hand.length) + game.temp = 0 + vm_next() + }, + /*done() { + vm_next() + }*/ +} + +states.vm_foreign_currency_debt_burden = { + get inactive() { + return `resolve ${clean_name(cards[game.played_card].name)}.` + }, + prompt() { + view.prompt = 'Choose a country. The Communist may not make support checks there for the rest of the turn.' + gen_action('east_germany') + gen_action('poland') + gen_action('czechoslovakia') + gen_action('hungary') + gen_action('bulgaria') + }, + east_germany() { + push_undo() + game.foreign_currency_debt_burden = 'East_Germany' + log('Selected East Germany') + vm_next() + }, + poland() { + push_undo() + game.foreign_currency_debt_burden = 'Poland' + log('Selected Poland') + vm_next() + }, + czechoslovakia() { + push_undo() + game.foreign_currency_debt_burden = 'Czechoslovakia' + log('Selected Czechoslovakia') + vm_next() + }, + hungary() { + push_undo() + game.foreign_currency_debt_burden = 'Hungary' + log('Selected Hungary') + vm_next() + }, + bulgaria() { + push_undo() + game.foreign_currency_debt_burden = 'Bulgaria' + log('Selected Bulgaria') + vm_next() + } +} + +states.vm_goodbye_lenin = { + get inactive() { + return `resolve ${clean_name(cards[game.played_card].name)}.` + }, + prompt() { + if (game.valid_cards.length > 0 ) { + view.prompt = `Play a red event from your opponent's hand, or play Goodbye Lenin for operations.` + for (let card of game.valid_cards) { + gen_action_card(card) + gen_action('ops') + } + } else { + view.prompt = 'Communist has no red events. Play Goodbye Lenin for operations.' + gen_action('ops') + } + }, + card(card) { + push_undo() + log(`Chose to play C${card} for the event`) + let card_index = game.communist_hand.indexOf(card) + game.communist_hand.splice(card_index, 1) + game.vm_event = card + game.view_opp_hand = false + goto_vm(card) + }, + ops() { + push_undo() + if (game.valid_cards.length === 0) { + logi('No red events') + } + log('C46 played for operations') + game.view_opp_hand = false + game.state = 'vm_goodbye_lenin_ops' + } +} + +states.vm_goodbye_lenin_ops = { + get inactive() { + return `resolve ${clean_name(cards[this_card()].name)}.` + }, + prompt() { + view.prompt = `Play ${clean_name(cards[this_card()].name)} for:` + gen_action('influence') + gen_action('support_check') + if ((game.active === DEM && game.dem_tst_attempted_this_turn === 0 ) || (game.active === COM && game.com_tst_attempted_this_turn === 0 )) { + gen_action('tst') + } + }, + influence(){ + push_undo() + game.vm_available_ops = get_card_ops(this_card()) + /*if (game.persistent_events.includes(50)) { + log(`+1 from C50`) + game.vm_available_ops++ + }*/ + valid_spaces_infl() + + // If ABHR - Set AHBR tracker to true + if (game.persistent_events.includes(58)) { + game.austria_hungary_border_reopened_tracker = true + } + game.state = 'vm_add_infl' + }, + support_check() { + push_undo() + game.vm_available_ops = 2 + game.state = 'vm_support_check_prep' + valid_spaces_sc() + }, + tst() { + push_undo() + game.state = 'vm_tiananmen_square_attempt' + } +} + +states.vm_honecker = { + get inactive() { + return `resolve ${clean_name(cards[game.played_card].name)}.` + }, + prompt() { + if (game.valid_cards.length === 0 && game.temp === 0) { + view.prompt = 'Honecker: no valid cards to choose.' + gen_action('pass') + } else + if (game.temp === 0) {view.prompt = 'Honecker: choose a card to add to your hand.' + for (let card of game.valid_cards) { + gen_action_card(card) + gen_action('pass') + } + } /*else { + view.prompt = 'Honecker. Choose a card: done.' + gen_action('done') + }*/ + }, + card(card) { + push_undo() + game.valid_cards = [] + log(`Took C${cards[card].number} into hand`) + game.temp = card + let card_index = game.strategy_discard.indexOf(card) + game.strategy_discard.splice(card_index, 1) + game.communist_hand.push(card) + vm_next() + }, + pass(){ + log('Did not take a card') + game.discard = false + vm_next() + }, + /*done(){ + if (game.temp === 0) { + log('Did not take a card') + } + game.discard = false + vm_next() + } */ + +} + +states.vm_inflationary_currency = { + get inactive() { + return `resolve ${clean_name(cards[game.played_card].name)}.` + }, + prompt() { + if ((game.active === COM && game.revolutions.every(n => n === false)) || (game.active === DEM && game.revolutions.every(n => n === true))) { + view.prompt = 'Inflationary Currency: no countries to choose.' + gen_action('pass') + } else { + view.prompt = 'Inflationary Currency: choose a country where your opponent has power.' + if (game.active === DEM) { + if (!game.revolutions[0]) {gen_action('poland')} + if (!game.revolutions[1]) {gen_action('hungary')} + if (!game.revolutions[2]) {gen_action('east_germany')} + if (!game.revolutions[3]) {gen_action('bulgaria')} + if (!game.revolutions[4]) {gen_action('czechoslovakia')} + if (!game.revolutions[5]) {gen_action('romania')} + } else { + if (game.revolutions[0]) {gen_action('poland')} + if (game.revolutions[1]) {gen_action('hungary')} + if (game.revolutions[2]) {gen_action('east_germany')} + if (game.revolutions[3]) {gen_action('bulgaria')} + if (game.revolutions[4]) {gen_action('czechoslovakia')} + if (game.revolutions[5]) {gen_action('romania')} + } + } + }, + east_germany() { + push_undo() + game.vm_active_country = 'East_Germany' + log(`Chose ${country_name(game.vm_active_country)}`) + vm_next() + }, + poland() { + push_undo() + game.vm_active_country = 'Poland' + log(`Chose ${country_name(game.vm_active_country)}`) + vm_next() + }, + czechoslovakia() { + push_undo() + game.vm_active_country = 'Czechoslovakia' + log(`Chose ${country_name(game.vm_active_country)}`) + vm_next() + }, + hungary() { + push_undo() + game.vm_active_country = 'Hungary' + log(`Chose ${country_name(game.vm_active_country)}`) + vm_next() + }, + romania() { + push_undo() + game.vm_active_country = 'Romania' + log(`Chose ${country_name(game.vm_active_country)}`) + vm_next() + }, + bulgaria () { + push_undo() + game.vm_active_country = 'Bulgaria' + log(`Chose ${country_name(game.vm_active_country)}`) + vm_next() + }, + pass() { + log('Passed') + vm_return() + } +} + +states.vm_inflationary_currency_discard = { + get inactive() { + return `resolve ${clean_name(cards[game.played_card].name)}.` + }, + prompt() { + if (game.valid_cards.length === 0 ) { + view.prompt = 'Inflationary Currency: no valid cards to discard. You must pass.' + gen_action('pass') + } else if (game.temp === 0 ) { + view.prompt = 'Inflationary Currency: you may discard a 3 op or higher value card to cancel the support check.' + gen_action('pass') + for (let card of game.valid_cards) { + gen_action_card(card) + } + } /*else { + view.prompt = 'Inflationary Currency. Discard a card: done.' + gen_action('done') + } */ + }, + card(card) { + push_undo() + discard(card) + game.temp = card + if (!game.vm_infl_to_do) { + if(game.round_player === DEM) { + game.return = COM + } else { + game.return = DEM + } + } + vm_next() + }, + pass() { + push_undo() + log('Did not discard') + next_player() + game.vm_available_ops = 1 + vm_next() + //game.state = 'vm_support_check_prep' + }, + done() { + if (!game.vm_infl_to_do) { + if(game.round_player === DEM) { + game.return = COM + } else { + game.return = DEM + } + } + vm_next() + } +} + + +states.vm_kiss_of_death = { + get inactive() { + return `resolve ${clean_name(cards[game.played_card].name)}.` + }, + prompt() { + if (game.communist_hand.length === 0) { + view.prompt = 'Kiss of Death. No cards to discard.' + gen_action('pass') + } else { + view.prompt = 'Kiss of Death: you must randomly discard a card.' + gen_action('discard') + } + }, + discard() { + clear_undo() + game.vm_event = discard_card(game.communist_hand) + //Only switch player if a playable non-communist event. Common European Home is not playable here + if (cards[game.vm_event].side !== "C" && event_is_playable(game.vm_event) && game.vm_event !== 21) { + next_player() + game.state = 'vm_kiss_of_death_finish' + } else { + log('Event does not occur') + vm_next() + } + }, + pass() { + log('No card to discard') + vm_next() + } +} + +states.vm_kiss_of_death_finish = { + get inactive() { + return `resolve ${clean_name(cards[game.played_card].name)}.` + }, + prompt() { + if (game.vm_event > 0 && game.vm_event !== 21 && (cards[game.vm_event].side === 'D' || cards[game.vm_event].side === 'N')) { + view.prompt = `Play ${clean_name(cards[game.vm_event].name)} for the event.` + console.log('kiss of death before event button: game.stategy_discard', game.strategy_discard) + gen_action('event') + } else { + view.prompt = 'Event does not occur.' + gen_action('done') + } + }, + event() { + //game.return = game.active + // Remove game.vm_event from the discard + //game.strategy_discard = game.strategy_discard.filter(n => n !== game.vm_event) + + goto_vm(game.vm_event) + }, + done() { + vm_next() + } +} + +states.vm_kremlin_coup_choose_country = { + get inactive() { + return `resolve ${clean_name(cards[this_card()].name)}.` + }, + prompt() { + if (game.temp.length > 0) { + view.prompt = 'Kremlin Coup! Select a country where the Communist retains power.' + for (let country of countries) { + if (game.temp.includes(country)) { + gen_action(`${country.toLowerCase()}`) + } + } + } else { + view.prompt = 'Kremlin Coup! There are no countries where the Communist retains power.' + gen_action('done') + } + }, + east_germany() { + push_undo() + game.vm_active_country = 'East_Germany' + game.temp = game.temp.filter(country => country !== game.vm_active_country) + log(`${country_name(game.vm_active_country)}:`) + vm_kremlin_coup_elite() + }, + poland() { + push_undo() + game.vm_active_country = 'Poland' + log(`${country_name(game.vm_active_country)}:`) + game.temp = game.temp.filter(country => country !== game.vm_active_country) + vm_kremlin_coup_elite() + }, + czechoslovakia() { + push_undo() + game.vm_active_country = 'Czechoslovakia' + log(`${country_name(game.vm_active_country)}:`) + game.temp = game.temp.filter(country => country !== game.vm_active_country) + vm_kremlin_coup_elite() + }, + hungary() { + push_undo() + game.vm_active_country = 'Hungary' + log(`${country_name(game.vm_active_country)}:`) + game.temp = game.temp.filter(country => country !== game.vm_active_country) + vm_kremlin_coup_elite() + }, + romania() { + push_undo() + game.vm_active_country = 'Romania' + log(`${country_name(game.vm_active_country)}:`) + game.temp = game.temp.filter(country => country !== game.vm_active_country) + vm_kremlin_coup_elite() + }, + bulgaria () { + push_undo() + game.vm_active_country = 'Bulgaria' + log(`${country_name(game.vm_active_country)}:`) + game.temp = game.temp.filter(country => country !== game.vm_active_country) + vm_kremlin_coup_elite() + }, + done() { + game.temp = 0 + vm_next() + } +} + +states.vm_kremlin_coup_take_control = { + get inactive() { + return `resolve ${clean_name(cards[game.played_card].name)}.` + }, + prompt() { + if (game.valid_spaces.includes(game.systematization)) { + view.prompt = `Kremlin Coup! ${country_name(game.vm_active_country)}'s Elite space no longer exists.` + gen_action('done') + } + else if (game.valid_spaces.length === 0){ + view.prompt = `Kremlin Coup! ${country_name(game.vm_active_country)}'s Elite space is already controlled.` + gen_action('done') + } else { + view.prompt = `Kremlin Coup! Take control of the Elite space in ${country_name(game.vm_active_country)}.` + for (let space_id of game.valid_spaces) { + gen_action_infl(space_id); + } + } + }, + infl(space) { + push_undo() + vm_take_control(space) + if (game.vm_active_country === 'East_Germany') {game.selected_space = 3 } + if (game.vm_active_country === 'Poland') {game.selected_space = 17} + if (game.vm_active_country === 'Czechoslovakia') {game.selected_space = 29} + if (game.vm_active_country === 'Hungary') {game.selected_space = 45} + if (game.vm_active_country === 'Romania') {game.selected_space = 61} + if (game.vm_active_country === 'Bulgaria') {game.selected_space = 68} + game.state = 'vm_kremlin_coup_sc_prep' + }, + done() { + push_undo() + if (game.vm_active_country === 'East_Germany') {game.selected_space = 3 } + if (game.vm_active_country === 'Poland') {game.selected_space = 17} + if (game.vm_active_country === 'Czechoslovakia') {game.selected_space = 29} + if (game.vm_active_country === 'Hungary') {game.selected_space = 45} + if (game.vm_active_country === 'Romania') {game.selected_space = 61} + if (game.vm_active_country === 'Bulgaria') {game.selected_space = 68} + game.state = 'vm_kremlin_coup_sc_prep' + } +} + +states.vm_kremlin_coup_sc_prep = { + get inactive() { + return `resolve ${clean_name(cards[game.played_card].name)}.` + }, + prompt() { + view.prompt = `Kremlin Coup! Conduct a support check in ${country_name(game.vm_active_country)}'s Bureaucratic space.` + gen_action_sc(game.selected_space); + }, + sc(space) { + //game.selected_space = space + push_undo() + game.state = 'vm_kremlin_coup_sc' + } +} + +states.vm_kremlin_coup_sc = { + inactive: 'do support checks', + prompt () { + view.prompt = `Support check: ${spaces[game.selected_space].name_unique}. Roll a die.` + gen_action('roll') + }, + roll() { + clear_undo() + do_sc(game.selected_space) + if (game.temp.length > 0 ){ + game.state = 'vm_kremlin_coup_choose_country' + } else { + //game.state = 'vm_kremlin_coup_end' + vm_next() + } + } +} +/* +states.vm_kremlin_coup_end = { + get inactive() { + return `resolve ${clean_name(cards[this_card()].name)}.` + }, + prompt() { + view.prompt = `${clean_name(cards[this_card()].name)} Support checks: done.` + gen_action('done') + }, + done() { + vm_next() + } +} +*/ +states.vm_laszlo_tokes = { + get inactive() { + return `resolve ${clean_name(cards[game.played_card].name)}.` + }, + prompt() { + view.prompt = `Laszlo Tokes. Choose to:` + gen_action('influence') + gen_action('support_check') + }, + influence(){ + push_undo() + game.vm_available_ops = get_card_ops(73) + valid_spaces_infl() + game.valid_spaces = game.valid_spaces.filter(space_id => spaces[space_id].country === 'Romania') + game.phase = 3 + vm_next() + //game.state = 'vm_add_infl' + }, + support_check() { + push_undo() + game.vm_available_ops = 2 + //game.state = 'vm_support_check_prep' + valid_spaces_sc() + game.valid_spaces = game.valid_spaces.filter(space_id => spaces[space_id].country === 'Romania') + vm_next() + } +} + +states.vm_switch_infl = { + get inactive() { + return `resolve ${clean_name(cards[game.played_card].name)}.` + }, + prompt() { + if (game.valid_spaces.length === 0) { + view.prompt = `${clean_name(cards[this_card()].name)}: No SPs to remove.` + gen_action('pass') + } else { + /*if (game.vm_available_ops > 0 ) {*/ + view.prompt = `${clean_name(cards[game.played_card].name)}: ${event_prompt()}.` + for (let space_id of game.valid_spaces) { + gen_action_infl(space_id); + } + } /*else { + view.prompt = 'Influence replaced.' + gen_action('done') + }*/ + }, + infl(space) { + push_undo() + vm_switch_infl(space) + if (game.vm_available_ops === 0) { + game.valid_spaces = [] + } + vm_next() + }, + pass() { + vm_next() + } + /*done() { + vm_next() + }*/ +} + +states.vm_malta_summit = { + get inactive() { + return `resolve ${clean_name(cards[game.played_card].name)}.` + }, + prompt() { + /*if (game.phase === 1) {*/ + view.prompt = 'Malta Summit: roll a die.' + gen_action('roll') + /*} else { + view.prompt = 'Done.' + gen_action('done') + }*/ + }, + roll() { + clear_undo() + let roll = Math.floor(Math.random() * 6) + 1 + log(`Roll: D${roll}`) + if (game.stability > 0) { + log(`+${game.stability} from USSR Stability Track`) + log(`Modified roll: ${roll + game.stability}`) + } + if (roll + game.stability > 3) { + log('Summit successful') + game.vp += 3 + log('+3 VP') + if (check_vp()) { + return + } + if (game.comInfl[12] > 0 ) {game.valid_spaces.push(12)} + if (game.comInfl[15] > 0 ) {game.valid_spaces.push(15)} + if (game.comInfl[27] > 0 ) {game.valid_spaces.push(27)} + if (game.comInfl[43] > 0 ) {game.valid_spaces.push(43)} + if (game.comInfl[51] > 0 ) {game.valid_spaces.push(51)} + if (game.comInfl[69] > 0 ) {game.valid_spaces.push(69)} + //game.vm_available_ops = 5 + game.remove_opponent_infl = true + vm_next() + } + else { + log('Summit failed. Required 4 or more') + //game.phase++ + vm_goto_step(vm_permanently_remove) + } + }, + /*done() { + vm_next() + }*/ +} + +states.vm_modrow = { + get inactive() { + return `resolve ${clean_name(cards[game.played_card].name)}.` + }, + prompt() { + view.prompt = `Modrow: roll a die.` + gen_action('roll') + }, + roll(){ + clear_undo() + let roll = Math.floor(Math.random() * 6) + 1 + let dem_spaces = spaces.filter(space => space && space.country === 'East_Germany' && check_dem_control(space.space_id)).length + if (roll > dem_spaces) { + log(`Roll: D${roll}`) + log(`Success. More than the ${dem_spaces} Democratically controlled spaces`) + vm_next() + } else { + log(`Roll: D${roll}`) + log(`Fail. More than ${dem_spaces} required`) + permanently_remove(83) + vm_return() + } + } +} + +states.vm_nepotism = { + get inactive() { + return `resolve ${clean_name(cards[game.played_card].name)}.` + }, + prompt() { + //if (game.phase === 1 ) { + view.prompt = 'Nepotism: roll a die.' + gen_action('roll') + /*} else { + view.prompt = 'Roll a die: done.' + gen_action('done') + }*/ + }, + roll() { + clear_undo() + let roll = Math.floor(Math.random() * 6) + 1 + if (roll < 3) { + log(`Roll: D${roll} adds 4 SPs`) + game.vm_available_ops = 4} + else if (roll < 5 ) { + log(`Roll: D${roll} adds 3 SPs`) + game.vm_available_ops = 3} + else { + log(`Roll: D${roll} adds 1 SP`) + game.vm_available_ops = 1} + //game.phase = 2 + vm_next() + }, + /*done() { + vm_next() + }*/ +} + +states.vm_new_years_eve_party = { + get inactive() { + return `resolve ${clean_name(cards[104].name)}.` + }, + prompt() { + view.prompt = 'Choose whether the game ends at the end of this turn.' + gen_action('end') + gen_action('continue') + }, + end() { + push_undo() + game.persistent_events.push(104) + log('Chooses to end the game. There will be no final scoring') + let power = game.revolutions.filter(value => value === false).length + if (power > 3) { + log(`Communist holds power in ${power} countries. -3 VP`) + game.vp -= 3 + } else { + log(`Communist holds power in ${power} countries. +3 VP`) + game.vp += 3 + } + if (check_vp()) { + return + } + //game.table_cards.push(104) + permanently_remove(104) + vm_next() + }, + continue() { + push_undo() + log('Chooses to continue') + permanently_remove(104) + vm_next() + } +} + +states.vm_nomenklatura = { + get inactive() { + return `resolve ${clean_name(cards[game.played_card].name)}.` + }, + prompt() { + view.prompt = 'Nomenklatura: choose to remove all Democratic SPs from Elite spaces or add 3 SPs to any Elite space(s).' + gen_action('remove') + gen_action('add') + }, + remove() { + push_undo() + game.valid_spaces = [] + for (let i = 1; i < spaces.length; i++) { + let space = spaces[i] + + if (space.socio === 1 && game.demInfl[i] > 0) { + game.valid_spaces.push(space.space_id) + } + } + game.vm_available_ops = game.valid_spaces.length + game.remove_opponent_infl = true + game.state = 'vm_nomenklatura_remove' + }, + add() { + push_undo() + game.valid_spaces = [] + for (let space of spaces) { + if (!space) continue + if (space.socio === 1) { + game.valid_spaces.push(space.space_id) + } + } + check_systematization() + game.vm_available_ops = 3 + game.state = 'vm_nomenklatura_add' + } +} + +states.vm_nomenklatura_remove = { + get inactive() { + return `resolve ${clean_name(cards[game.played_card].name)}.` + }, + prompt() { + if (game.valid_spaces.length === 0 ) { + view.prompt = 'Nomenklatura. No SPs to remove: pass.' + gen_action('pass') + } else { + view.prompt = 'Nomenklatura: remove all Democratic SPs from Elite spaces.' + + for (let space_id of game.valid_spaces) { + gen_action_infl(space_id); + } + } + }, + infl(space) { + push_undo() + vm_do_remove_all_infl(space) + if (game.valid_spaces.length === 0) { + vm_next() + } + }, + pass() { + push_undo() + vm_next() + } +} + +states.vm_nomenklatura_add = { + get inactive() { + return `resolve ${clean_name(cards[game.played_card].name)}.` + }, + prompt() { + /*if (game.vm_available_ops === 0 || game.valid_spaces.length === 0 ) { + view.prompt = 'Nomenklatura. Add SPs: done.' + gen_action('done') + } else { */ + view.prompt = `Nomenklatura: add 3 SPs to any Elite space(s). ${pluralize(game.vm_available_ops, 'SP')} remaining.` + for (let space_id of game.valid_spaces) { + gen_action_infl(space_id); + } + //} + }, + infl(space) { + push_undo() + vm_do_add_infl_free(space) + if (game.vm_available_ops === 0 ) { + game.valid_spaces = [] + if (game.summary.length > 0) { + pop_summary() + log_br() + } + vm_next() + } + }, +/* done() { + push_undo() + if (game.summary.length > 0) { + pop_summary() + log_br() + } + vm_next() + }*/ +} + +states.vm_samizdat = { + get inactive() { + return `resolve ${clean_name(cards[game.played_card].name)}.` + }, + prompt() { + view.prompt = 'Samizdat: you may set aside a card from your hand and draw a replacement.' + for (let card of game.democrat_hand) { + gen_action_card(card) + } + gen_action('pass') + }, + card(card) { + push_undo() + game.samizdat_card = card + game.democrat_hand = game.democrat_hand.filter(c => c !== card) + log('Set aside a card') + game.state = 'vm_samizdat_finish' + }, + pass() { + push_undo() + //if (game.samizdat_card > 0) {game.state = 'vm_samizdat_finish'} + /*else { */ + log('Did not set aside a card') + vm_next() + //} + } +} + +states.vm_samizdat_finish = { + get inactive() { + return `resolve ${clean_name(cards[game.played_card].name)}.` + }, + prompt() { + /*if (game.phase ) { + view.prompt = 'Samizdat: done.' + gen_action('done') + } else {*/ + view.prompt = 'Draw a replacement card.' + gen_action('draw') + //} + }, + draw() { + clear_undo() + game.democrat_hand.push(draw_card(game.strategy_deck)) + vm_next() + //game.phase ++ + }, + /*done() { + vm_next() + }*/ +} + +states.vm_shock_therapy = { + get inactive() { + return `resolve ${clean_name(cards[game.played_card].name)}.` + }, + prompt() { + if (game.revolutions.every(n => n === false)) { + view.prompt = 'Shock Therapy: no countries to choose.' + gen_action('pass') + } else { + if (game.vm_active_country === '' ) { + view.prompt = 'Shock Therapy: choose a country where you hold Power:' + if (game.revolutions[0]) {gen_action('poland')} + if (game.revolutions[1]) {gen_action('hungary')} + if (game.revolutions[2]) {gen_action('east_germany')} + if (game.revolutions[3]) {gen_action('bulgaria')} + if (game.revolutions[4]) {gen_action('czechoslovakia')} + if (game.revolutions[5]) {gen_action('romania')} + } /*else if (game.phase === 2) { + view.prompt = 'Shock Therapy: done.' + gen_action('done') + } */ + else { + view.prompt = 'Shock Therapy: roll a die.' + gen_action('roll') + } + } + }, + east_germany() { + push_undo() + game.vm_active_country = 'East_Germany' + log(`Chose ${country_name(game.vm_active_country)}`) + }, + poland() { + push_undo() + game.vm_active_country = 'Poland' + log(`Chose ${country_name(game.vm_active_country)}`) + }, + czechoslovakia() { + push_undo() + game.vm_active_country = 'Czechoslovakia' + log(`Chose ${country_name(game.vm_active_country)}`) + }, + hungary() { + push_undo() + game.vm_active_country = 'Hungary' + log(`Chose ${country_name(game.vm_active_country)}`) + }, + romania() { + push_undo() + game.vm_active_country = 'Romania' + log(`Chose ${country_name(game.vm_active_country)}`) + }, + bulgaria () { + push_undo() + game.vm_active_country = 'Bulgaria' + log(`Chose ${country_name(game.vm_active_country)}`) + }, + roll() { + clear_undo() + let roll = Math.floor(Math.random() * 6) + 1 + let worker_farmer = 0 + for (let space of spaces) { + if (space && space.country === game.vm_active_country && check_com_control(space.space_id) && (space.socio === 3 || space.socio === 4)) { + worker_farmer++ + } + } + log(`Roll: D${roll}`) + log(`-${worker_farmer} from Communist controlled Worker and Farmer spaces`) + log(`Modified roll: ${roll - worker_farmer}`) + if ((roll - worker_farmer) > 2) { + log('C93 is successful. +3 VP') + vm_next() + } else { + log('C93 is unsuccessful. Required 3 or more') + //game.phase++ + permanently_remove(93) + vm_return() + } + }, + pass() { + log('Passed') + vm_return() + } + /*done() { + permanently_remove(93) + vm_return() + }*/ +} + +states.vm_social_democratic_platform_adopted = { + get inactive() { + return `resolve ${clean_name(cards[game.played_card].name)}.` + }, + prompt() { + if (game.revolutions.every(n => n === false)) { + view.prompt = 'Social Democratic Platform Adopted: no countries to choose.' + gen_action('pass') + } else { + view.prompt = 'Select a country where the Democrat holds Power.' + if (game.revolutions[0]) {gen_action('poland')} + if (game.revolutions[1]) {gen_action('hungary')} + if (game.revolutions[2]) {gen_action('east_germany')} + if (game.revolutions[3]) {gen_action('bulgaria')} + if (game.revolutions[4]) {gen_action('czechoslovakia')} + if (game.revolutions[5]) {gen_action('romania')} + } + }, + east_germany() { + push_undo() + game.vm_active_country = 'East_Germany' + log(`Selected ${country_name(game.vm_active_country)}`) + vm_next() + }, + poland() { + push_undo() + game.vm_active_country = 'Poland' + log(`Selected ${country_name(game.vm_active_country)}`) + vm_next()}, + czechoslovakia() { + push_undo() + game.vm_active_country = 'Czechoslovakia' + log(`Selected ${country_name(game.vm_active_country)}`) + vm_next()}, + hungary() { + push_undo() + game.vm_active_country = 'Hungary' + log(`Selected ${country_name(game.vm_active_country)}`) + vm_next() + }, + romania() { + push_undo() + game.vm_active_country = 'Romania' + log(`Selected ${country_name(game.vm_active_country)}`) + vm_next() + }, + bulgaria () { + push_undo() + game.vm_active_country = 'Bulgaria' + log(`Selected ${country_name(game.vm_active_country)}`) + vm_next() + }, + pass() { + log('Passed') + vm_return() + } +} + +states.vm_systematization = { + get inactive() { + return `resolve ${clean_name(cards[game.played_card].name)}.` + }, + prompt() { + /*if (game.systematization === 0) { */ + view.prompt = 'Systematization: eliminate a space in Romania.' + for (let space_id of game.valid_spaces) { + gen_action_infl(space_id); + } + /*} else { + view.prompt = 'Systematization: done.' + gen_action('done') + }*/ + }, + infl(space) { + push_undo() + vm_eliminate(space) + game.valid_spaces = [] + game.systematization = space + game.persistent_events.push(69) + vm_next() + }, +/* done() { + vm_next() + } */ +} + +states.vm_the_chinese_solution = { + get inactive() { + return `resolve ${clean_name(cards[game.played_card].name)}.` + }, + prompt() { + view.prompt = 'The Chinese Solution: you may give up 3 VP to conduct support checks in a country where you hold power.' + if (!game.revolutions[0]) {gen_action('poland')} + if (!game.revolutions[1]) {gen_action('hungary')} + if (!game.revolutions[2]) {gen_action('east_germany')} + if (!game.revolutions[3]) {gen_action('bulgaria')} + if (!game.revolutions[4]) {gen_action('czechoslovakia')} + if (!game.revolutions[5]) {gen_action('romania')} + gen_action('pass') + }, + east_germany() { + push_undo() + game.vm_active_country = 'East_Germany' + log(`Chose ${country_name(game.vm_active_country)}`) + log('+3 VP') + game.vp += 3 + if (check_vp()) { + return + } + vm_next() + }, + poland() { + push_undo() + game.vm_active_country = 'Poland' + log(`Chose ${country_name(game.vm_active_country)}`) + log('+3 VP') + game.vp += 3 + if (check_vp()) { + return + } + vm_next() + }, + czechoslovakia() { + push_undo() + game.vm_active_country = 'Czechoslovakia' + log(`Chose ${country_name(game.vm_active_country)}`) + log('+3 VP') + game.vp += 3 + if (check_vp()) { + return + } + vm_next() + }, + hungary() { + push_undo() + game.vm_active_country = 'Hungary' + log(`Chose ${country_name(game.vm_active_country)}`) + log('+3 VP') + game.vp += 3 + if (check_vp()) { + return + } + vm_next() + }, + romania() { + push_undo() + game.vm_active_country = 'Romania' + log(`Chose ${country_name(game.vm_active_country)}`) + log('+3 VP') + game.vp += 3 + if (check_vp()) { + return + } + vm_next() + }, + bulgaria () { + push_undo() + game.vm_active_country = 'Bulgaria' + log(`Chose ${country_name(game.vm_active_country)}`) + log('+3 VP') + game.vp += 3 + if (check_vp()) { + return + } + vm_next() + }, + pass() { + push_undo() + permanently_remove(96) + vm_return() + } +} + +states.vm_the_tyrant_is_gone = { + get inactive() { + return `resolve ${clean_name(cards[game.played_card].name)}.` + }, + prompt() { + if (!game.the_tyrant_is_gone) { + view.prompt = 'The Tyrant is Gone: Select a space in Romania for the Ceausescus to flee to.' + for (let space_id of game.valid_spaces) { + if (!space_id) continue + gen_action_infl(space_id); + } + } else { + view.prompt = 'The Tyrant is Gone: done.' + gen_action('done') + } + }, + infl(space) { + push_undo() + log(`The Ceausescus flee to %${space}`) + game.the_tyrant_is_gone = space + game.valid_spaces = [] + game.persistent_events.push(97) + + // vm_next() + }, + done () { + vm_next() + } +} +/* +states.vm_tyrant_block ={ + get inactive() { + return `resolve ${clean_name(cards[this_card()].name)}.` + }, + prompt() { + view.prompt = `${clean_name(cards[this_card()].name)} has no effect after The Tyrant Has Gone.` + gen_action('done') + }, + done() { + push_undo() + vm_next() + } +}*/ + + +states.vm_the_wall_must_go = { + get inactive() { + return `resolve ${clean_name(cards[this_card()].name)}.` + }, + prompt() { + /*if (game.the_wall_must_go['dem_wins'] === 2 || game.the_wall_must_go['com_wins'] === 2) { + view.prompt = '"The Wall Must Go!" Rolls: done.' + gen_action('done') + } else { */ + view.prompt = ('The Wall Must Go! Roll a die.') + gen_action('roll') + //} + }, + roll() { + clear_undo() + let attempt = game.the_wall_must_go['dem_wins'] + game.the_wall_must_go['com_wins'] + if (game.the_wall_must_go['dem_roll'] === 0 && game.the_wall_must_go['com_roll'] === 0) { + log_h3(`Round ${attempt+1}`) + } + + let roll = Math.floor(Math.random() * 6) + 1 + log(`Roll: D${roll}`) + if (game.active === DEM) { + let controlled_spaces = spaces.filter(space => space && space.country === 'East_Germany' && check_dem_control(space.space_id)).length + if (controlled_spaces > 0) { + log(`+${controlled_spaces} from controlled spaces in East Germany`) + log(`Modified roll: ${roll + controlled_spaces}`) + roll += controlled_spaces + } + game.the_wall_must_go['dem_roll'] = roll + } else { + let controlled_spaces = spaces.filter(space => space && space.country === 'East_Germany' && check_com_control(space.space_id)).length + if (controlled_spaces > 0) { + log(`+${controlled_spaces} from controlled spaces in East Germany`) + log(`Modified roll: ${roll + controlled_spaces}`) + roll += controlled_spaces + } + game.the_wall_must_go['com_roll'] = roll + + } + if (game.the_wall_must_go['dem_roll'] > 0 && game.the_wall_must_go['com_roll'] > 0) { + if (game.the_wall_must_go['dem_roll'] > game.the_wall_must_go['com_roll'] ) { + log('Democrat wins') + game.the_wall_must_go['dem_wins']++ + } else if (game.the_wall_must_go['dem_roll'] === game.the_wall_must_go['com_roll'] ) { + log('Tie. Re-roll') + } else { + log('Communist wins') + game.the_wall_must_go['com_wins']++ + } + + log(`Democrat: ${game.the_wall_must_go['dem_wins']}, Communist: ${game.the_wall_must_go['com_wins']}`) + } + if (game.the_wall_must_go['dem_wins'] === 2) { + log('The Democrat wins C86') + finish_the_wall() + return + } + if (game.the_wall_must_go['com_wins'] === 2) { + log('The Communist wins C86') + finish_the_wall() + return + } + if (game.the_wall_must_go['dem_roll'] === 0 || game.the_wall_must_go['com_roll'] === 0) { + next_player() + } else { + game.the_wall_must_go['dem_roll'] = 0 + game.the_wall_must_go['com_roll'] = 0 + } + }, + /*done() { + if (game.the_wall_must_go['dem_wins'] === 2) { + game.persistent_events.push(86) + log('+3 VP') + game.vp += 3 + if (check_vp()) { + return + } + for (let i = 1; i < spaces.length; i++) { + let space = spaces[i] + if (space.country === 'East_Germany' && game.comInfl[i] > 0){ + game.valid_spaces.push(space.space_id) + } + } + if (!game.vm_infl_to_do) { + if (game.round_player === DEM) { + game.return = COM + } else { + game.return = DEM + } + } + if (game.active === DEM) {next_player()} + vm_next () + } else { + permanently_remove(86) + delete game.the_wall_must_go + vm_return() + } + }*/ +} + +states.vm_warsaw_pact_summit = { + get inactive() { + return `resolve ${clean_name(cards[game.played_card].name)}.` + }, + prompt() { + view.prompt = 'Choose to play for support checks or place SPs.' + gen_action('influence') + gen_action('support_check') + }, + influence(){ + push_undo() + for (let i = 1; i < spaces.length; i++) { + let space = spaces[i] + if (game.demInfl[i] === 0) { + game.valid_spaces.push(space.space_id); + } + } + game.vm_available_ops = 4 + game.phase = 3 + //game.state = 'vm_add_infl' + vm_next() + }, + support_check(){ + push_undo() + for (let i = 1; i < spaces.length; i++) { + let space = spaces[i] + if (game.demInfl[i] > 0 && (space.socio === 5 || space.socio === 6)) { + game.valid_spaces.push(space.space_id) + } + } + game.vm_available_ops = 2 + //game.state = 'vm_support_check_prep' + vm_next() + } +} + +states.vm_we_are_the_people_remove = { + get inactive() { + return `resolve ${clean_name(cards[game.played_card].name)}.` + }, + prompt() { + if (game.demInfl[6] === 0 && game.vm_available_ops > 0) { + view.prompt = '"We are the People!": no SPs to remove.' + gen_action('done') + } else if (game.vm_available_ops > 0 ) { + view.prompt = '"We are the People!": remove up to 4 SPs from the Lutherian Church.' + gen_action('done') + for (let space_id of game.valid_spaces) { + gen_action_infl(space_id); + } + } else { + view.prompt = '"We are the People!" Remove SPs: done.' + gen_action('done') + } + }, + infl(space) { + vm_do_remove_infl(space) + }, + done() { + if (game.summary.length > 0) { + pop_summary() + log_br() + } + if (!game.vm_influence_added[6]) { + log('No SPs removed') + vm_next() + } else { + game.valid_spaces = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] + game.state = 'vm_we_are_the_people_add' + } + } +} +states.vm_we_are_the_people_add = { + get inactive() { + return `resolve ${clean_name(cards[game.played_card].name)}.` + }, + prompt() { + /* if (!game.vm_influence_added[6]) { + view.prompt = '"We are the People!" Add SPs: done.' + gen_action('done') + return + }*/ + + view.prompt = `"We are the People!": you must add the ${pluralize(game.vm_influence_added[6],'SP')} to spaces in Germany.` + for (let space_id of game.valid_spaces) { + gen_action_infl(space_id); + } + }, + infl(space) { + vm_do_add_infl_free(space) + game.vm_influence_added[6]-- + if (game.vm_influence_added[6] === 0 ) { + game.valid_spaces = [] + if (game.summary.length > 0) { + pop_summary() + log_br() + } + vm_next() + } + }, + /*done() { + push_undo() + if (game.summary.length > 0) { + pop_summary() + log_br() + } + vm_next() + }*/ +} + +states.vm_workers_revolt = { + get inactive() { + return `resolve ${clean_name(cards[game.played_card].name)}.` + }, + prompt() { + if (game.valid_spaces.length === 0 ) { + view.prompt = 'Workers Revolt: no valid spaces to select.' + gen_action('pass') + return + } + view.prompt = 'Workers Revolt: select a Worker Space in a country your opponent has power.' + for (let space_id of game.valid_spaces) { + gen_action_infl(space_id) + } + }, + pass() { + push_undo() + vm_next() + }, + infl(space) { + push_undo() + game.selected_space = space + log(`Chose %${game.selected_space}`) + game.state = 'vm_workers_revolt_finish' + } +} + + +states.vm_workers_revolt_finish = { + get inactive() { + return `resolve ${clean_name(cards[game.played_card].name)}.` + }, + prompt() { + //if (game.selected_space > 0) { + view.prompt = `Target: ${spaces[game.selected_space].name_unique}. Roll a die.` + gen_action('roll') + /* } else { + view.prompt = 'Workers Revolt: done.' + gen_action('done') + }*/ + + }, + roll() { + clear_undo() + let roll = Math.floor(Math.random() * 6) + 1 + log(`Roll: D${roll}`) + let adj = count_adj(game.selected_space) + if (game.active === DEM) { + log(`-${adj.com_adj} from opponent controlled spaces`) + roll -= adj.com_adj + } else { + log(`-${adj.dem_adj} from opponent controlled spaces`) + roll -= adj.dem_adj + } + log(`Modified roll: ${roll}`) + if (roll >= 4) { + log('Workers Revolt successful') + vm_replace_all_infl(game.temp) + } else {log('Workers Revolt fails. Required 4 or more')} + game.selected_space = 0 + vm_next() + }, + /*done() { + vm_next() + }*/ +} + +// ==================== TIANANMEN SQUARE TRACK STATES ===================== + +states.vm_tst_3_prep = { + inactive: 'resolve Tiananmen Square Track award.', + prompt() { + view.prompt = 'Tiananmen Square Track award: draw 3 cards.' + gen_action('draw') + }, + draw() { + if (game.active === DEM) { + game.temp = game.democrat_hand.length + draw_cards(game.strategy_deck, game.democrat_hand, game.communist_hand, game.democrat_hand.length + 3, game.communist_hand.length) + game.valid_cards = [game.democrat_hand[game.temp], game.democrat_hand[game.temp + 1], game.democrat_hand[game.temp + 2]] + } else { + game.temp = game.communist_hand.length + draw_cards(game.strategy_deck, game.democrat_hand, game.communist_hand, game.democrat_hand.length, game.communist_hand.length + 3) + game.valid_cards = [game.communist_hand[game.temp], game.communist_hand[game.temp + 1], game.communist_hand[game.temp + 2]] + } + game.temp = 0 + game.state = 'vm_tst_3' + } +} + +states.vm_tst_3 = { + inactive: 'resolve Tiananmen Square Track bonus.', + prompt() { + if (game.temp < 2) { + view.prompt = `Discard 2 of the drawn cards.` + for (let card of game.valid_cards) { + gen_action_card(card) + } + } /*else { + view.prompt = 'Discard cards: done.' + gen_action('done') + }*/ + }, + card(card) { + push_undo() + discard(card) + game.temp ++ + if (game.temp === 2) { + game.valid_cards = [] + vm_next() + } + }, + /*done() { + vm_next() + }*/ +} + +states.vm_tst_4 = { + inactive: 'remove SPs', + prompt () { + if (game.vm_available_ops === 0 || game.valid_spaces.length === 0) { + view.prompt = 'Tiananmen Square Track award. Remove SPs: done.' + gen_action('done') + return + } + view.prompt = `Tiananmen Square Track award: remove ${pluralize(game.vm_available_ops,'SP')}.` + + for (let space_id of game.valid_spaces) { + gen_action_infl(space_id); + } + }, + infl(space) { + vm_do_remove_infl(space) + if (game.vm_available_ops === 0) { + if (game.summary.length > 0) { + pop_summary() + log_br() + } + vm_next() + } + }, + done() { + if (game.summary.length > 0) { + pop_summary() + log_br() + } + vm_next() + } +} + +states.vm_tst_6 = { + inactive: 'make their free support check.', + prompt() { + /* if (game.vm_available_ops === 0) { + view.prompt = 'Tiananmen Square Track award support check: done.' + gen_action('done') + return + } else {*/ + view.prompt = 'Tiananmen Square Track award: you have a free 2 Ops support check.' + for (let space_id of game.valid_spaces) { + if (space_id) { + gen_action_sc(space_id); + } + } + //} + }, + sc(space) { + push_undo() + game.selected_space = space + if (game.active === DEM && game.persistent_events.includes(58) && spaces[space].country === "East_Germany") { + game.austria_hungary_border_reopened_tracker = true + } + game.state = 'vm_tst_6_sc' + }, + /*done () { + push_undo() + vm_next() + }*/ +} + +states.vm_tst_6_sc = { + inactive: 'do support check.', + prompt () { + view.prompt = `Support check: ${spaces[game.selected_space].name_unique}. Roll a die` + gen_action('roll') + }, + roll() { + clear_undo() + do_sc(game.selected_space) + game.vm_available_ops-- + game.valid_spaces = [] + game.state = 'vm_tst_6' + vm_next() + return + } +} + +states.vm_tst_8 = { + inactive: 'use Tiananmen Square Track award.', + prompt() { + if (game.vm_event_to_do && game.vm_infl_to_do) { + view.prompt = 'Choose whether to play for event or operations first.' + gen_action('event') + gen_action('ops') + } + else if (!game.vm_event_to_do && game.vm_infl_to_do) { + view.prompt = 'Event resolved. Use card for operations.' + gen_action('ops') + } + else if (game.vm_event_to_do && !game.vm_infl_to_do) { + view.prompt = 'Operations resolved. Use card for event.' + gen_action('event') + } + else if (!game.vm_event_to_do && !game.vm_infl_to_do) { + view.prompt = 'Event and operations: done.' + gen_action('end_round') + } + }, + event() { + push_undo() + log('Event') + game.vm_event_to_do = false + game.return_state = 'vm_tst_8' + game.return = game.active + game.vm_event = game.played_card + goto_vm(game.vm_event) + }, + ops() { + push_undo() + log('Operations') + game.vm_infl_to_do = false + game.return = game.active + game.return_state = 'vm_tst_8' + goto_vm(208) + }, + end_round() { + push_undo() + game.tst_8 = true + end_round() + } +} + + +states.vm_tst_8_ops = { + inactive: 'play card for operations.', + prompt() { + view.prompt = `Play ${clean_name(cards[game.played_card].name)} for:` + gen_action('influence') + gen_action('support_check') + if ((game.active === DEM && game.dem_tst_attempted_this_turn === 0 ) || (game.active === COM && game.com_tst_attempted_this_turn === 0 )) { + gen_action('tst') + } + }, + influence(){ + push_undo() + game.vm_available_ops = cards[game.played_card].ops + valid_spaces_infl() + // If ABHR - Set AHBR tracker to true + if (game.persistent_events.includes(58)) { + game.austria_hungary_border_reopened_tracker = true + } + game.state = 'vm_add_infl' + }, + support_check() { + push_undo() + game.vm_available_ops = 2 + game.state = 'vm_support_check_prep' + }, + tst() { + push_undo() + game.state = 'vm_tiananmen_square_attempt' + } +} + +// ========================= POWER STRUGGLE STATES ======================== + +states.vm_scare_tactics = { + inactive: 'remove a Support Point.', + prompt () { + if (game.valid_spaces.length === 0 && game.vm_available_ops > 0) { + view.prompt = `${clean_name(cards[this_card()].name)}: no SPs to remove.` + gen_action('done') + return + } + if (game.vm_available_ops === 0 ) { + view.prompt = `${clean_name(cards[this_card()].name)}. Remove SPs: done.` + gen_action('done') + return + } + view.prompt = `${clean_name(cards[this_card()].name)}: remove ${pluralize(game.vm_available_ops, 'opponent SP')}${event_prompt()}.` + for (let space_id of game.valid_spaces) { + gen_action_infl(space_id); + } + }, + infl(space) { + push_undo() + vm_do_remove_infl(space) + }, + done() { + if (game.summary.length > 0) { + pop_summary() + log_br() + } + vm_next() + } +} + +states.vm_support_surges_1 = { + inactive: 'draw cards.', + prompt() { + view.prompt = 'Support Surges: draw a card.' + gen_action('draw') + }, + draw() { + if (game.active === DEM) { + //console.log('hand before', game.dem_pwr_hand) + draw_cards(game.power_struggle_deck, game.dem_pwr_hand, game.com_pwr_hand, game.dem_pwr_hand.length+1, game.com_pwr_hand.length) + game.temp = game.dem_pwr_hand[game.dem_pwr_hand.length-1] + //console.log('hand after', game.dem_pwr_hand, 'game.temp', game.temp) + } else { + //console.log('hand before', game.com_pwr_hand) + draw_cards(game.power_struggle_deck, game.dem_pwr_hand, game.com_pwr_hand, game.dem_pwr_hand.length, game.com_pwr_hand.length+1) + game.temp = game.com_pwr_hand[game.com_pwr_hand.length-1] + //console.log('hand after', game.com_pwr_hand, 'game.temp', game.temp) + } + game.state = 'vm_support_surges_2' + + //game.phase = 0 + //log('Drew 2 cards') + //log('Surrenders initiative') + //vm_next() + } +} + +states.vm_support_surges_2 = { + inactive: 'draw cards.', + prompt() { + let special = [49,50,51,52] + let elite_leader = [37,38,39,40] + if (special.includes(game.temp)) { + view.prompt = `Support Surges: you drew ${power_cards[game.temp].name}. Draw a second card.` + } + else if (elite_leader.includes(game.temp)) { + view.prompt = `Support Surges: you drew an ${power_cards[game.temp].name}. Draw a second card.` + } + else if (numberless_cards.includes(game.temp)) { + view.prompt = `Support Surges: you drew a ${power_cards[game.temp].name}. Draw a second card.` + } else { + view.prompt = `Support Surges: you drew a ${power_cards[game.temp].name} ${power_cards[game.temp].value}. Draw a second card.` + } + gen_action('draw') + }, + draw() { + if (game.active === DEM) { + draw_cards(game.power_struggle_deck, game.dem_pwr_hand, game.com_pwr_hand, game.dem_pwr_hand.length+1, game.com_pwr_hand.length) + game.temp = game.dem_pwr_hand[game.dem_pwr_hand.length - 1] + } else { + draw_cards(game.power_struggle_deck, game.dem_pwr_hand, game.com_pwr_hand, game.dem_pwr_hand.length, game.com_pwr_hand.length+1) + game.temp = game.com_pwr_hand[game.com_pwr_hand.length - 1] + } + game.state = 'vm_support_surges_3' + /*game.phase = 0 + log('Drew 2 cards') + log('Surrenders initiative') + vm_next()*/ + } +} + +states.vm_support_surges_3 = { + inactive: 'draw cards.', + prompt() { + if (numberless_cards.includes(game.temp)) { + view.prompt = `Support Surges: you drew ${power_cards[game.temp].name}. Done.` + } else { + view.prompt = `Support Surges: you drew a ${power_cards[game.temp].name} ${power_cards[game.temp].value}. Done.` + } + gen_action('done') + }, + done() { + game.phase = 0 + delete game.temp + log('Drew 2 cards') + log('Surrenders initiative') + vm_next() + } +} + +states.vm_support_falters = { + inactive: 'discard cards.', + prompt() { + if ((game.active === DEM && game.dem_pwr_hand.length === 0) || (game.active === COM && game.com_pwr_hand.length === 0)) { + view.prompt = 'Support Falters: no remaining cards to discard.' + gen_action('pass') + } else if (game.vm_available_ops > 0) { + view.prompt = 'Support Falters: discard a card.' + gen_action('discard') + } else { + view.prompt = 'Support Falters: done.' + gen_action('done') + } + }, + discard() { + if (game.active === DEM) {discard_card(game.dem_pwr_hand)} + else {discard_card(game.com_pwr_hand)} + game.vm_available_ops -- + }, + pass() { + log_msg_gap('Takes initiative') + game.return = game.active + vm_next() + }, + done() { + log_gap('Takes initiative') + game.return = game.active + vm_next() + } +} + +/* =================== EVENTS ================================ */ + +// #region GENERATED EVENT CODE +const CODE = [] + +CODE[1] = [ // Legacy of Martial Law* + [ vm_permanently_remove ], + [ vm_valid_spaces_country_opp, 'Poland' ], + [ vm_prompt, 'replace 1 Democratic SP in Poland with a Communist SP' ], + [ vm_legacy_of_martial_law ], + [ vm_valid_spaces_country_sc, 'Poland' ], + [ vm_prompt, 'make a Support Check in Poland' ], + [ vm_1_support_check ], + [ vm_return ], +] + +CODE[2] = [ // Solidarity Legalised* + [ vm_permanently_remove ], + [ vm_solidarity_legalised ], + [ vm_valid_spaces_solidarity_legalised ], + [ vm_prompt, 'to every uncontrolled Worker and Farmer space in Poland' ], + [ vm_add_limited_infl, 9, 1 ], + [ vm_return ], +] + +CODE[3] = [ // Walesa + [ vm_permanently_remove ], + [ vm_valid_spaces_country, 'Poland' ], + [ vm_prompt, 'any space(s) in Poland' ], + [ vm_add_infl_free, 4 ], + [ vm_valid_spaces_country_sc, 'Poland' ], + [ vm_prompt, 'make Support Checks in Poland' ], + [ vm_support_check, 2 ], + [ vm_return ], +] + +CODE[4] = [ // Michnik + [ vm_permanently_remove ], + [ vm_valid_spaces, 26 ], + [ vm_prompt, 'the Polish Intellectuals space' ], + [ vm_add_x_infl, 3 ], + [ vm_return ], +] + +CODE[5] = [ // General strike + [ vm_general_strike ], + [ vm_return ], +] + +CODE[6] = [ // Brought in for Questioning + [ vm_brought_in_for_questioning ], + [ vm_return ], +] + +CODE[7] = [ // State Run Media* + [ vm_permanently_remove ], + [ vm_valid_spaces_opponent ], + [ vm_remove_limited_opp_infl, 4, 2 ], + [ vm_return ], +] + +CODE[8] = [ // Prudence + [ vm_prudence ], + [ vm_return ], +] + +CODE[9] = [ // The Wall* + [ vm_permanently_remove ], + [ vm_the_wall ], + [ vm_return ], +] + +CODE[10] = [ // Cult of Personality + [ vm_permanently_remove ], + [ vm_if, ()=>!game.the_tyrant_is_gone ], + [ vm_valid_spaces_country_socio_2, 'Romania', 3, 4 ], + [ vm_prompt, 'Worker or Farmer spaces in Romania, no more than 2 per space' ], + [ vm_add_limited_infl, 4, 2 ], + [ vm_else ], + [ vm_tyrant_block ], + [ vm_endif ], + [ vm_return ], +] + +CODE[11] = [ // Dissident arrested + [ vm_valid_spaces_opponent_socio, 5 ], + [ vm_prompt, 'any Intellectuals space' ], + [ vm_remove_x_opp_infl, 2 ], + [ vm_return ], +] + +CODE[12] = [ // Apparatchicks + [ vm_permanently_remove ], + [ vm_valid_spaces_socio, 2 ], + [ vm_prompt, ' to any Bureaucratic space(s)' ], + [ vm_add_infl_free, 3 ], + [ vm_return ], +] + +CODE[13] = [ // Stasi + [ vm_permanently_remove ], + [ vm_stasi ], + [ vm_return ], +] + +CODE[14] = [ // Gorbachev Charms the West + [ vm_valid_spaces_opponent ], + [ vm_remove_opp_infl, 2 ], + [ vm_valid_spaces_sc ], + [ vm_prompt, 'select a space for the Support Check' ], + [ vm_1_support_check ], + [ vm_return ], +] + +CODE[15] = [ // Honecker + [ vm_permanently_remove ], + [ vm_honecker ], + [ vm_return ], +] + +CODE[16] = [ // Nomenklatura* + [ vm_permanently_remove ], + [ vm_nomenklatura ], + [ vm_return ], +] + +CODE[17] = [ // Roundtable talks + [ vm_roundtable_talks ], + [ vm_return ], +] + +CODE[18] = [ // Poszgay Defends the Revolution + [ vm_permanently_remove ], + [ vm_poszgay ], + [ vm_prompt, 'to 4 spaces in Hungary not under Democratic control' ], + [ vm_add_limited_infl, 4, 1 ], + [ vm_return ], +] + +CODE[19] = [ // Papal vist + [ vm_permanently_remove ], + [ vm_valid_spaces, 20, 35, 38 ], + [ vm_prompt, 'any Catholic Church space' ], + [ vm_add_x_infl, 3 ], + [ vm_return ], +] + +CODE[20] = [ // Deutsche Marks* + [ vm_permanently_remove ], + [ vm_deutsche_marks ], + [ vm_return ], +] + +CODE[21] = [ // Common European Home + [ vm_common_european_home ], + [ vm_return ], +] + +CODE[22] = [ // Power Struggle - Poland + [ vm_power_struggle ], + [ vm_return ], +] + +CODE[23] = [ // Power Struggle - Hungary + [ vm_power_struggle ], + [ vm_return ], +] + +CODE[24] = [ // St Nicolas Church + [ vm_permanently_remove ], + [ vm_valid_spaces, 6 ], + [ vm_prompt, 'the Lutheran Church' ], + [ vm_take_control_prep, 1 ], + [ vm_st_nicholas_church ], + [ vm_return ], +] + +CODE[25] = [ // Perestroika + [ vm_permanently_remove ], + [ vm_perestroika ], + [ vm_return ], +] + +CODE[26] = [ // Helsinki Final Act* + [ vm_permanently_remove ], + [ vm_helsinki_final_act ], + [ vm_return ], +] + +CODE[27] = [ // Consumerism + [ vm_valid_spaces_opponent_socio, 4 ], + [ vm_prompt, ' from a Worker space' ], + [ vm_remove_opp_infl, 1 ], + [ vm_valid_spaces_opponent_socio, 4 ], + [ vm_active_country ], + [ vm_prompt, ()=>`make a support check in a Worker space in ${country_name(game.vm_active_country)}` ], + [ vm_1_support_check ], + [ vm_return ], +] + +CODE[28] = [ // Factory Party Cells + [ vm_valid_spaces_opponent_socio, 4 ], + [ vm_prompt, ' from Worker spaces' ], + [ vm_remove_limited_opp_infl, 3, 2 ], + [ vm_return ], +] + +CODE[29] = [ // Jan Palach Week* + [ vm_permanently_remove ], + [ vm_valid_spaces, 30 ], + [ vm_prompt, 'the Charles University space' ], + [ vm_add_x_infl, 6 ], + [ vm_return ], +] + +CODE[30] = [ // Tear Gas + [ vm_tear_gas ], + [ vm_return ], +] + +CODE[31] = [ // Intelligentsia + [ vm_valid_spaces, 4, 26, 31, 46, 55, 73 ], + [ vm_prompt, 'Intellectual spaces, no more than 2 per space' ], + [ vm_add_limited_infl, 4, 2 ], + [ vm_return ], +] + +CODE[32] = [ // Peasant Parties* + [ vm_permanently_remove ], + [ vm_valid_spaces_socio, 3 ], + [ vm_prompt, 'Farmer spaces, no more than 2 per space' ], + [ vm_add_limited_infl, 4, 2 ], + [ vm_return ], +] + +CODE[33] = [ // Sajudis* + [ vm_permanently_remove ], + [ vm_sajudis_check ], + [ vm_prompt, 'any Minorities space' ], + [ vm_take_control_prep, 1 ], + [ vm_sajudis ], + [ vm_return ], +] + +CODE[34] = [ // Fidesz* + [ vm_permanently_remove ], + [ vm_valid_spaces, 47 ], + [ vm_prompt, 'the Hungary students space' ], + [ vm_add_x_infl, 5 ], + [ vm_return ], +] + +CODE[35] = [ // Heal our Bleeding Wounds* + [ vm_permanently_remove ], + [ vm_heal_our_bleeding_wounds ], + [ vm_return ], +] + +CODE[36] = [ // Dash for the West* + [ vm_permanently_remove ], + [ vm_prompt, 'Dash for the West: select any Democratic event with an asterix(*) from the discard pile. Event occurs immediately' ], + [ vm_dash_for_the_west ], + [ vm_return ], +] + +CODE[37] = [ // Nagy Reburied* + [ vm_permanently_remove ], + [ vm_nagy_reburied ], + [ vm_prompt, 'the Hungary Elite space' ], + [ vm_remove_all_infl, 1 ], + [ vm_valid_spaces_country, 'Hungary' ], + [ vm_prompt, 'Hungary, no more than 2 per space' ], + [ vm_add_limited_infl, 4, 2 ], + [ vm_return ], +] + +CODE[38] = [ // July Concept + [ vm_permanently_remove ], + [ vm_valid_spaces_country, 'Bulgaria' ], + [ vm_prompt, 'Bulgaria' ], + [ vm_add_infl_free, 3 ], + [ vm_return ], +] + +CODE[39] = [ // Eco-Glasnost* + [ vm_permanently_remove ], + [ vm_valid_spaces, 66 ], + [ vm_prompt, 'Ruse' ], + [ vm_add_x_infl, 4 ], + [ vm_eco_glasnost ], + [ vm_return ], +] + +CODE[40] = [ // Hungarian Democratic Forum + [ vm_permanently_remove ], + [ vm_valid_spaces_country, 'Hungary' ], + [ vm_prompt, 'Hungary' ], + [ vm_add_infl_free, 3 ], + [ vm_valid_spaces_country_sc, 'Hungary' ], + [ vm_prompt, 'make a Support Check in Hungary' ], + [ vm_1_support_check ], + [ vm_return ], +] + +CODE[41] = [ // Ceausescu* + [ vm_permanently_remove ], + [ vm_if, ()=>!game.the_tyrant_is_gone ], + [ vm_valid_spaces_country_opp, 'Romania' ], + [ vm_prompt, ' from Romania' ], + [ vm_remove_opp_infl, 3 ], + [ vm_valid_spaces_country_sc, 'Romania' ], + [ vm_prompt, 'make a support check in Romania' ], + [ vm_1_support_check ], + [ vm_prompt, ' from Bucharesti' ], + [ vm_ceausescu ], + [ vm_else ], + [ vm_tyrant_block ], + [ vm_endif ], + [ vm_return ], +] + +CODE[42] = [ // Power Struggle - East Germany + [ vm_power_struggle ], + [ vm_return ], +] + +CODE[43] = [ // Power Struggle - Bulgaria + [ vm_power_struggle ], + [ vm_return ], +] + +CODE[44] = [ // Inflationary Currency + [ vm_permanently_remove ], + [ vm_inflationary_currency ], + [ vm_valid_spaces_country_opp ], + [ vm_prompt, ()=>` from ${country_name(game.vm_active_country)}` ], + [ vm_remove_opp_infl, 2 ], + [ vm_inflationary_currency_discard ], + [ vm_if, ()=>!discarded_card() ], + [ vm_valid_spaces_country_sc ], + [ vm_prompt, ()=>`make a Support Check in ${country_name(game.vm_active_country)}` ], + [ vm_1_support_check ], + [ vm_endif ], + [ vm_return ], +] + +CODE[45] = [ // Soviet Troop Withdrawals* + [ vm_permanently_remove ], + [ vm_valid_spaces_region_opp, 'Eastern Europe' ], + [ vm_prompt, ' from Eastern Europe' ], + [ vm_remove_limited_opp_infl, 5, 2 ], + [ vm_return ], +] + +CODE[46] = [ // Goodbye Lenin!* + [ vm_permanently_remove ], + [ vm_goodbye_lenin ], + [ vm_return ], +] + +CODE[47] = [ // Bulgarian Turks Expelled* + [ vm_permanently_remove ], + [ vm_bulgarian_turks_expelled ], + [ vm_prompt, 'Razgrad' ], + [ vm_remove_all_infl, 1 ], + [ vm_return ], +] + +CODE[48] = [ // We are the People!* + [ vm_permanently_remove ], + [ vm_we_are_the_people ], + [ vm_return ], +] + +CODE[49] = [ // Foreign Currency Debt Burden* + [ vm_permanently_remove ], + [ vm_foreign_currency_debt_burden ], + [ vm_return ], +] + +CODE[50] = [ // The Sinatra Doctrine* + [ vm_permanently_remove ], + [ vm_the_sinatra_doctrine ], + [ vm_return ], +] + +CODE[51] = [ // 40th Anniversary Celebration* + [ vm_permanently_remove ], + [ vm_40th_anniversary_celebration ], + [ vm_valid_spaces_country, 'East_Germany' ], + [ vm_prompt, 'East Germany' ], + [ vm_add_infl_free ], + [ vm_40th_anniversary_celebration_vp ], + [ vm_return ], +] + +CODE[52] = [ // Normalisation + [ vm_permanently_remove ], + [ vm_normalisation ], + [ vm_prompt, 'the Czechoslovakia Elite and Bureaucrat Spaces' ], + [ vm_remove_all_infl, 2 ], + [ vm_return ], +] + +CODE[53] = [ // Li Peng* + [ vm_permanently_remove ], + [ vm_li_peng ], + [ vm_return ], +] + +CODE[54] = [ // The Crowd Turns Against Ceausescu* + [ vm_the_crowd_turns_against_ceausescu ], + [ vm_return ], +] + +CODE[55] = [ // Power Struggle - Czechoslovakia + [ vm_power_struggle ], + [ vm_return ], +] + +CODE[56] = [ // Foreign Television + [ vm_permanently_remove ], + [ vm_foreign_television ], + [ vm_remove_limited_opp_infl, 4, 2 ], + [ vm_return ], +] + +CODE[57] = [ // Central Committee Reshuffle* + [ vm_permanently_remove ], + [ vm_central_committee_reshuffle ], + [ vm_prompt, ()=>`${country_name(game.vm_active_country)}` ], + [ vm_add_infl_free, 3 ], + [ vm_return ], +] + +CODE[58] = [ // Austria-Hungary Border Reopened* + [ vm_austria_hungary_border_reopened ], + [ vm_return ], +] + +CODE[59] = [ // GrenzTruppen* + [ vm_grenztruppen ], + [ vm_return ], +] + +CODE[60] = [ // Toxic Waste* + [ vm_permanently_remove ], + [ vm_valid_spaces_socio, 4 ], + [ vm_prompt, 'any Worker space(s)' ], + [ vm_add_infl_free, 3 ], + [ vm_return ], +] + +CODE[61] = [ // The Monday Demonstrations* + [ vm_permanently_remove ], + [ vm_the_monday_demonstrations ], + [ vm_prompt, 'the Lutheran Church Space and Leipzig' ], + [ vm_take_control_prep, 2 ], + [ vm_valid_spaces_country_sc, 'East_Germany' ], + [ vm_prompt, 'make 5 Support Checks in East Germany' ], + [ vm_support_check, 5 ], + [ vm_return ], +] + +CODE[62] = [ // Yakovlev Counsels Gorbachev* + [ vm_yakovlev_counsels_gorbachev ], + [ vm_return ], +] + +CODE[63] = [ // Genscher* + [ vm_genscher ], + [ vm_return ], +] + +CODE[64] = [ // Legacy of 1968* + [ vm_permanently_remove ], + [ vm_legacy_of_1968 ], + [ vm_prompt, 'all spaces in Czechoslovakia not controlled by the Communist Player' ], + [ vm_add_limited_infl, 11, 1 ], + [ vm_return ], +] + +CODE[65] = [ // Presidential Visit* + [ vm_permanently_remove ], + [ vm_presidential_visit ], + [ vm_return ], +] + +CODE[66] = [ // New Forum + [ vm_permanently_remove ], + [ vm_valid_spaces_country, 'East_Germany' ], + [ vm_prompt, '3 spaces in East Germany' ], + [ vm_add_limited_infl, 3, 1 ], + [ vm_return ], +] + +CODE[67] = [ // Reformer Rehabilitated* + [ vm_prompt, 'Reformer Rehabilitated: chose any non-scoring card in the discard pile. Event takes place immediately' ], + [ vm_reformer_rehabilitated ], + [ vm_return ], +] + +CODE[68] = [ // Klaus and Komarek* + [ vm_permanently_remove ], + [ vm_klaus_and_komarek ], + [ vm_prompt, 'Prague' ], + [ vm_remove_x_opp_infl, 2 ], + [ vm_valid_spaces, 29 ], + [ vm_add_x_infl, 2 ], + [ vm_return ], +] + +CODE[69] = [ // Systematization* + [ vm_permanently_remove ], + [ vm_valid_spaces_country, 'Romania' ], + [ vm_systematization ], + [ vm_return ], +] + +CODE[70] = [ // Securitate* + [ vm_securitate ], + [ vm_return ], +] + +CODE[71] = [ // Kiss of Death* + [ vm_permanently_remove ], + [ vm_kiss_of_death ], + [ vm_return ], +] + +CODE[72] = [ // Peasant Parties Revolt + [ vm_peasant_parties_revolt ], + [ vm_return ], +] + +CODE[73] = [ // Laszlo Tokes* + [ vm_permanently_remove ], + [ vm_valid_spaces, 50, 56 ], + [ vm_prompt, 'in Timisoara and Harghita/Covasna' ], + [ vm_add_limited_infl, 2, 1 ], + [ vm_laszlo_tokes ], + [ vm_if, ()=>game.phase === 3 ], + [ vm_prompt, ' in Romania' ], + [ vm_add_infl ], + [ vm_else ], + [ vm_prompt, 'make 2 Support Checks in Romania' ], + [ vm_support_check, 2 ], + [ vm_endif ], + [ vm_return ], +] + +CODE[74] = [ // FRG Embassies + [ vm_frg_embassies ], + [ vm_return ], +] + +CODE[75] = [ // Exit Visas* + [ vm_permanently_remove ], + [ vm_exit_visas ], + [ vm_return ], +] + +CODE[76] = [ // Warsaw Pact Summit + [ vm_permanently_remove ], + [ vm_warsaw_pact_summit ], + [ vm_if, ()=>game.phase === 3 ], + [ vm_prompt, ' spaces with no Democratic SPs' ], + [ vm_add_infl_free, 4 ], + [ vm_else ], + [ vm_prompt, 'Select a Student or Intellectual space' ], + [ vm_valid_spaces_country_socio_2, 3,, 4 ], + [ vm_support_check_modified, 2, 2 ], + [ vm_endif ], + [ vm_return ], +] + +CODE[77] = [ // Samizdat + [ vm_permanently_remove ], + [ vm_samizdat ], + [ vm_return ], +] + +CODE[78] = [ // Workers Revolt + [ vm_workers_revolt ], + [ vm_return ], +] + +CODE[79] = [ // The Third Way* + [ vm_permanently_remove ], + [ vm_the_third_way ], + [ vm_valid_spaces, 4 ], + [ vm_prompt, 'the East German Writers space' ], + [ vm_add_x_infl, 3 ], + [ vm_return ], +] + +CODE[80] = [ // Nepotism* + [ vm_permanently_remove ], + [ vm_nepotism ], + [ vm_valid_spaces_region_socio, 'Balkans', 4 ], + [ vm_prompt, 'Worker spaces in the Balkans' ], + [ vm_add_infl_free ], + [ vm_return ], +] + +CODE[81] = [ // The Baltic Way* + [ vm_permanently_remove ], + [ vm_the_baltic_way ], + [ vm_prompt, 'any Minorities space' ], + [ vm_take_control_prep, 1 ], + [ vm_return ], +] + +CODE[82] = [ // Spitzel* + [ vm_permanently_remove ], + [ vm_valid_spaces_country_opp, 'East_Germany' ], + [ vm_prompt, ' from East Germany' ], + [ vm_remove_opp_infl, 2 ], + [ vm_return ], +] + +CODE[83] = [ // Modrow* + [ vm_permanently_remove ], + [ vm_modrow ], + [ vm_valid_spaces_country, 'East_Germany' ], + [ vm_prompt, 'East Germany, no more than 2 per space' ], + [ vm_add_limited_infl, 4, 2 ], + [ vm_return ], +] + +CODE[84] = [ // Breakaway Baltic Republics* + [ vm_permanently_remove ], + [ vm_breakaway_baltic_republics ], + [ vm_prompt, 'any Minorities space' ], + [ vm_take_control_prep, 1 ], + [ vm_valid_spaces_sc ], + [ vm_prompt, 'select a space for the support check' ], + [ vm_1_support_check ], + [ vm_return ], +] + +CODE[85] = [ // Tank Column/Tank Man* + [ vm_permanently_remove ], + [ vm_tank_column ], + [ vm_return ], +] + +CODE[86] = [ // The Wall Must Go!* + [ vm_permanently_remove ], + [ vm_the_wall_must_go ], + [ vm_remove_infl, 3 ], + [ vm_return ], +] + +CODE[87] = [ // Kohl Proposes Reunification* + [ vm_permanently_remove ], + [ vm_kohl_proposes_reunification ], + [ vm_return ], +] + +CODE[88] = [ // Adamec* + [ vm_permanently_remove ], + [ vm_adamec ], + [ vm_valid_spaces_country, 'Czechoslovakia' ], + [ vm_prompt, 'Czechoslovakia' ], + [ vm_add_limited_infl, 4, 2 ], + [ vm_return ], +] + +CODE[89] = [ // Domino Theory* + [ vm_prompt, 'Domino Theory: choose a Power Struggle card to play from the discard pile' ], + [ vm_permanently_remove ], + [ vm_domino_theory ], + [ vm_return ], +] + +CODE[90] = [ // Civic Forum* + [ vm_permanently_remove ], + [ vm_valid_spaces_country, 'Czechoslovakia' ], + [ vm_prompt, 'Czechoslovakia' ], + [ vm_add_infl_free, 4 ], + [ vm_civic_forum ], + [ vm_valid_spaces_country_sc, 'Czechoslovakia' ], + [ vm_prompt, 'Select a space in Czechoslovakia' ], + [ vm_support_check, 2 ], + [ vm_return ], +] + +CODE[91] = [ // My First Banana* + [ vm_permanently_remove ], + [ vm_valid_spaces_country_opp, 'East_Germany' ], + [ vm_prompt, ' from East Germany' ], + [ vm_remove_opp_infl, 2 ], + [ vm_valid_spaces_country_sc, 'East_Germany' ], + [ vm_prompt, 'select a space in East Germany' ], + [ vm_support_check, 2 ], + [ vm_return ], +] + +CODE[92] = [ // Betrayal + [ vm_permanently_remove ], + [ vm_prompt, 'choose any Orthodox Church space. Replace all Democratic SPs with Communist SPs' ], + [ vm_betrayal ], + [ vm_return ], +] + +CODE[93] = [ // Shock Therapy* + [ vm_permanently_remove ], + [ vm_shock_therapy ], + [ vm_valid_spaces_country ], + [ vm_prompt, ()=>` ${country_name(game.vm_active_country)}` ], + [ vm_add_infl_free, 3 ], + [ vm_return ], +] + +CODE[94] = [ // Union of Democratic Forces* + [ vm_permanently_remove ], + [ vm_valid_spaces_country_opp, 'Bulgaria' ], + [ vm_prompt, ' from Bulgaria' ], + [ vm_remove_opp_infl, 4 ], + [ vm_valid_spaces_country_sc, 'Bulgaria' ], + [ vm_prompt, 'Make 2 Support Checks in Bulgaria' ], + [ vm_support_check, 2 ], + [ vm_return ], +] + +CODE[95] = [ // Power Struggle - Romania + [ vm_power_struggle ], + [ vm_return ], +] + +CODE[96] = [ // The Chinese Solution* + [ vm_permanently_remove ], + [ vm_the_chinese_solution ], + [ vm_valid_spaces_country_sc ], + [ vm_prompt, ()=>`make 5 Support Checks in ${country_name(game.vm_active_country)}` ], + [ vm_support_check_modified, 5, 3 ], + [ vm_return ], +] + +CODE[97] = [ // The Tyrant is Gone* + [ vm_if, ()=>game.persistent_events.includes(54) ], + [ vm_valid_spaces, 51 ], + [ vm_prompt, 'the Romanian Elite Space' ], + [ vm_remove_x_opp_infl, 4 ], + [ vm_the_tyrant_is_gone ], + [ vm_permanently_remove ], + [ vm_else ], + [ vm_the_tyrant_is_gone_prep ], + [ vm_endif ], + [ vm_return ], +] + +CODE[98] = [ // Politburo Intrigue* + [ vm_permanently_remove ], + [ vm_valid_spaces_country_opp, 'Bulgaria' ], + [ vm_prompt, ' from Bulgaria' ], + [ vm_remove_limited_opp_infl, 3, 2 ], + [ vm_valid_spaces_country_sc, 'Bulgaria' ], + [ vm_prompt, 'make a support check in Bulgaria' ], + [ vm_1_support_check ], + [ vm_return ], +] + +CODE[99] = [ // Ligachev* + [ vm_permanently_remove ], + [ vm_ligachev ], + [ vm_return ], +] + +CODE[100] = [ // Stand Fast* + [ vm_permanently_remove ], + [ vm_stand_fast ], + [ vm_return ], +] + +CODE[101] = [ // Elena* + [ vm_permanently_remove ], + [ vm_if, ()=>!game.the_tyrant_is_gone ], + [ vm_valid_spaces, 51 ], + [ vm_prompt, 'the Romania Elite Space' ], + [ vm_add_x_infl, 2 ], + [ vm_elena ], + [ vm_else ], + [ vm_tyrant_block ], + [ vm_endif ], + [ vm_return ], +] + +CODE[102] = [ // National Salvation Front* + [ vm_national_salvation_front ], + [ vm_return ], +] + +CODE[103] = [ // Government Resigns* + [ vm_government_resigns ], + [ vm_prompt, 'any uncontrolled Elite space' ], + [ vm_remove_all_infl, 1 ], + [ vm_permanently_remove ], + [ vm_return ], +] + +CODE[104] = [ // New Year's Eve Party* + [ vm_new_years_eve_party ], + [ vm_return ], +] + +CODE[105] = [ // Public Against Violence* + [ vm_permanently_remove ], + [ vm_valid_spaces, 36 ], + [ vm_prompt, 'Kosice' ], + [ vm_add_x_infl, 2 ], + [ vm_valid_spaces, 37 ], + [ vm_prompt, 'Presov' ], + [ vm_add_x_infl, 2 ], + [ vm_public_against_violence ], + [ vm_prompt, 'Make a Support Check in Bratislava' ], + [ vm_support_check_modified, 1, 2 ], + [ vm_return ], +] + +CODE[106] = [ // Social Democratic Platform Adopted* + [ vm_permanently_remove ], + [ vm_social_democratic_platform_adopted ], + [ vm_valid_spaces_country ], + [ vm_prompt, ()=>`${country_name(game.vm_active_country)}` ], + [ vm_add_infl_free, 2 ], + [ vm_valid_spaces_country_sc ], + [ vm_prompt, ()=>`make a Support Check in ${country_name(game.vm_active_country)}` ], + [ vm_1_support_check ], + [ vm_return ], +] + +CODE[107] = [ // Massacre in Timisoara* + [ vm_permanently_remove ], + [ vm_if, ()=>!game.the_tyrant_is_gone ], + [ vm_massacre_in_timisoara ], + [ vm_valid_spaces_country_sc, 'Romania' ], + [ vm_prompt, 'Make Support Checks in Romania' ], + [ vm_support_check_modified, 2, 2 ], + [ vm_else ], + [ vm_tyrant_block ], + [ vm_endif ], + [ vm_return ], +] + +CODE[108] = [ // Army Backs Revolution* + [ vm_permanently_remove ], + [ vm_army_backs_revolution ], + [ vm_return ], +] + +CODE[109] = [ // Kremlin Coup* + [ vm_permanently_remove ], + [ vm_kremlin_coup ], + [ vm_return ], +] + +CODE[110] = [ // Malta Summit* + [ vm_permanently_remove ], + [ vm_malta_summit ], + [ vm_prompt, ' from Elite spaces' ], + [ vm_remove_opp_infl, 5 ], + [ vm_return ], +] +// #endregion + + +// ============= TIANANMEN SQUARE TRACK AWARDS ==================== +CODE[203] = [//Tiananmen Square space 3 award + [vm_tst_3], + [vm_return] +] +CODE[204] = [//Tiananmen Square space 4 award + [vm_valid_spaces_opponent], + [vm_tst_4], + [vm_return] +] +CODE[206] = [//Tiananmen Square space 6 + [vm_valid_spaces_sc], + [vm_tst_6], + [vm_return] +] +CODE[208] = [//Tiananmen Square space 8 event + [vm_tst_8], + [vm_return] +] + +// ============= POWER STRUGGLE WILDCARDS ========================= + +CODE[349] = [//Scare Tactics + [vm_scare_tactics], + [vm_valid_spaces_country_opp], + [vm_prompt, ()=>` from ${country_name(game.vm_active_country)}`], + [vm_remove_opp_infl, 1], + [vm_return] +] +CODE[350] = [//Support Surges + [vm_support_surges], + [vm_return] +] +CODE[351] = [//Support Falters + [vm_support_falters], + [vm_return] +] -- cgit v1.2.3