//"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, 58, 59, 62, 63, 65, 70, 72, 74, 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: [], active: null, state: "com_init", return: '', vm: null, vm_event: 0, vm_event_to_do: false, vm_infl_to_do: false, vm_active_country: 0, vm_influence_added: {}, vm_max_infl: 0, played_card: 0, stasi_card: 0, samizdat_card: 0, table_cards: [], austria_hungary_border_reopened_tracker: false, temp: 0, available_ops: 0, vm_available_ops: 0, starting_infl: { com_starting_infl: 0, dem_starting_infl: 0 }, valid_spaces: [], valid_cards: [], 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, tst_success: false, tst_7: false, tst_8: false, vp: 0, pieces: [null], strategy_deck: [], strategy_discard: [], discard: false, view_opp_hand: false, strategy_removed: [], persistent_events: {austria_hungary_border_reopened: false, civic_forum: false, eco_glasnost: false, elena: false, foreign_currency_debt_burden: '', frg_embassies: false, general_strike: false, genscher: false, grenztruppen: false, helsinki_final_act: false, honecker: false, laszlo_tokes: false, li_peng: false, ligachev: false, national_salvation_front: false, perestroika: false, presidential_visit: false, prudence: '', roundtable_talks: false, securitate: false, sinatra_doctrine: false, solidarity_legalised: false, stand_fast: '', stasi: false, st_nicholas_church: false, systematization: 0, tear_gas: false, the_crowd_turns_against_ceausescu: false, the_tyrant_is_gone: 0, the_wall: false, the_wall_must_go: false, we_are_the_people: false, yakovlev: false}, power_struggle_deck: [], power_struggle_discard: [], dem_hand_limit: 8, com_hand_limit: 8, democrat_hand: [], communist_hand: [], communist_hand_red: [], pwr_struggle_in: [], is_pwr_struggle: false, dem_pwr_hand_limit: 0, com_pwr_hand_limit: 0, dem_pwr_hand: [], com_pwr_hand: [], ceausescu_cards: [], raised_stakes_discard: 0, raised_stakes: 0, raised_stakes_round: 0, rally_win: 0, petition_win: 0, phase: 0, times_held: {'East_Germany': 0, 'Poland': 0, 'Czechoslovakia': 0, 'Hungary': 0, 'Romania': 0, 'Bulgaria': 0}, revolutions: {'East_Germany': false, 'Poland': false, 'Czechoslovakia': false, 'Hungary': false, 'Romania': false, 'Bulgaria': false}, scored_countries: {'East_Germany': false, 'Poland': false, 'Czechoslovakia': false, 'Hungary': false, 'Romania': false, 'Bulgaria': false}, remove_opponent_infl: false, tactics_fails: '', warsaw_pact_summit: false, the_wall_must_go: {dem_wins: 0, com_wins: 0, dem_roll: 0, com_roll: 0}, tyrant_space: 0 } log_h1("1989 Dawn of Freedom") game.active = COM start_game() return game } function start_game() { //starting influence // Draw cards /* const card_numbers = cards.filter(card => card !== null && card !== undefined).map(card => card.number); console.log('card numbers: ', card_numbers) */ game.strategy_deck = draw_deck(cards) reset_power() game.playable_cards = cards.map(card => { if (card === null) return null return { number: card.number, playable: card.playable }}) //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) spaces.forEach((space, index) => { if(index === 0 ) return game.pieces.push({ name_unique: space.name_unique, space_id: space.space_id, demInfl: space.demInfl, comInfl: space.comInfl, demCtrl: space.demCtrl, comCtrl: space.comCtrl, stability: space.stability, adjacent: space.adjacent }); }); game.valid_spaces = valid_spaces_setup() game.available_ops = 2 game.phase = 0 log_h1("Place starting influence") 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, pieces: game.pieces, 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, strategy_deck: game.strategy_deck.length, strategy_discard: game.strategy_discard, 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 (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 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) /*Does the Communist ever see Democrat hand? */ view.power_hand = game.com_pwr_hand.sort((a, b) => a - b) } 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) { view.actions[action] = 1 } else { if (!(action in view.actions)) 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 influence', prompt() { if (game.available_ops == 0) { view.prompt = 'Place starting influence: done.'; gen_action("done"); return; } else if (game.starting_infl.dem_starting_infl === 2) { view.prompt = `Place your last ${game.available_ops} starting influence.` } else { view.prompt = `Place ${game.available_ops} starting influence.` } for (let space_id of game.valid_spaces) { if (space_id) { gen_action_infl(spaces[space_id].name_unique); } } }, infl(space) { add_infl(space) }, done() { view.prompt='Influence added.' 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) { game.state = 'start_game' } } } states.dem_init = { inactive: 'place starting influence.', prompt() { if (game.available_ops == 0) { view.prompt = 'Place starting influence: done.'; gen_action("done"); return; } else if (game.starting_infl.com_starting_infl === 2) { view.prompt = `Place your last ${game.available_ops} starting influence.` } else { view.prompt = `Place ${game.available_ops} starting influence` } for (let space_id of game.valid_spaces) { gen_action_infl(spaces[space_id].name_unique); } }, infl(space) { add_infl(space) }, done() { view.prompt='Influence added' 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.start_game = { inactive: 'start Turn 1.', prompt() { view.prompt = 'Start Turn 1.' gen_action('start') }, start() { new_turn() clear_undo() game.state = 'choose_card' } } states.choose_card = { inactive: 'choose a card.', prompt() { /*if (game.played_card > 0) { game.state = 'play_card' view.prompt = 'Choose a card: done.' gen_action("done"); return; } */ 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() game.played_card = card 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 = cards[card].ops //Check events which affect game ops if (game.persistent_events['perestroika'] && game.active === COM) { log('+1 op from C25') game.available_ops ++ } if (game.persistent_events['sinatra_doctrine'] && game.active === DEM) { log('+1 op from C50') game.available_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)) { log('+1 op from Tiananmen Square Track') game.available_ops ++ } if ((game.active === DEM && game.persistent_events['prudence'] === DEM) || (game.active === COM && game.persistent_events['prudence'] === COM)) { if (game.available_ops > 1) { log('-1 op from C8') game.available_ops -- } } //Check Ligachev if (game.active === DEM && game.persistent_events['ligachev'] && card !== 14) { log('-3 VP from C99') game.vp -= 3 check_vp() game.persistent_events['ligachev'] = false } game.state = 'play_card' console.log('game.state', game.state) }, pass() { log('No cards remaining. Passed') end_round() } /*done () { game.state = 'play_card' } */ } states.play_card ={ get inactive() { return `play ${clean_name(cards[game.played_card].name)}.` }, prompt () { if (game.phase >= 1) { view.prompt = `${clean_name(cards[game.played_card].name)}: done.` gen_action('done') 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 Tiananmen Square Track awards special abilities 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') } // Special check for Reformer Rehabilitated if ((game.active === DEM && game.playable_cards[game.played_card] === 2 && (game.dem_tst_position > game.com_tst_position)) || (game.active === COM && game.playable_cards[game.played_card].playable === 2 && (game.dem_tst_position < game.com_tst_position))) { gen_action('event') } //Continue with normal logic if ((game.active === DEM && cards[game.played_card].side === 'D' && game.playable_cards[game.played_card].playable === 1) || (game.active === COM && cards[game.played_card].side === 'C' && game.playable_cards[game.played_card].playable ===1) || (cards[game.played_card].side === 'N'&& game.playable_cards[game.played_card].playable ===1)) { gen_action('event') } else if ((game.active === DEM && (cards[game.played_card].side === 'C' && game.playable_cards[game.played_card].playable ===1)) || game.active === COM && (cards[game.played_card].side === 'D' && game.playable_cards[game.played_card].playable ===1)) { gen_action('opp_event') } gen_action('influence') if (game.active === DEM && game.dem_tst_attempted_this_turn === 0 || game.active === COM && game.com_tst_attempted_this_turn === 0) { gen_action('tst') } gen_action('support_check') }, 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`) 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()} goto_vm(game.played_card) }, opp_event() { 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 if (auto_resolve_events.includes(game.played_card) || switch_events.includes(game.played_card)) { goto_vm(game.played_card)} else { next_player() log(`C${game.played_card}`) goto_vm(game.played_card) } }, influence() { push_undo() log_gap(`Played C${cards[game.played_card].number} for influence`) // Check if Common European Home played for influence if (game.played_card === 21) { if (game.active === DEM) { game.vp -- log('-1 VP') check_vp() } else { game.vp ++ log('+1 VP') check_vp() } } // Check if card is opponent card with event that needs to be resolved if ((game.active === DEM && cards[game.played_card].side === "C" && game.playable_cards[game.played_card].playable === 1) || (game.active === COM && cards[game.played_card].side === "D" && game.playable_cards[game.played_card].playable === 1 )) { game.phase = 1 /*Do I need this? */ game.vm_event_to_do = true } // Set AHBR tracker to true 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 (game.phase === 0 && game.active === DEM && cards[game.played_card].side === "C" && game.playable_cards[game.played_card].playable === 1 || game.phase === 0 && game.active === COM && cards[game.played_card].side === "D" && game.playable_cards[game.played_card].playable === 1 ) { game.vm_event_to_do = true } game.available_ops = 2 game.state='support_check_prep' valid_spaces_sc() }, tst_8() { /*Play card for ops and event */ game.vm_event_to_do = true game.vm_infl_to_do = true game.tst_8 = true game.state = 'vm_tst_8' }, done () { 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('done') } }, influence(){ push_undo() // Set AHBR tracker to true 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 (auto_resolve_events.includes(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() game.tst_7 = true game.vm_event_to_do = false }, done() { /*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 influence.', prompt () { if (game.available_ops === 0) { view.prompt = 'Place influence: done.' gen_action("done") return; } view.prompt = `Add influence: ${game.available_ops} remaining` // Generate actions for valid spaces for (let space_id of game.valid_spaces) { /*const space = spaces.find(s => s && s.space_id === space_id); if (space) {*/ gen_action_infl(spaces[space_id].name_unique) //} } }, infl(space) { add_infl(space) }, done() { end_round() } } states.finish_support_check_prep = { inactive: 'do support checks.', prompt () { if (game.available_ops === 0) { view.prompt = 'Support checks: done.' gen_action('done') //return } else { view.prompt = `Select a space. ${pluralize(game.available_ops, 'support check')} remaining.` } for (let space_id of game.valid_spaces) { /*const space = spaces.find(s => s && s.space_id === space_id); */ if (space_id) { gen_action_sc(spaces[space_id].name_unique) } } }, sc(space) { push_undo() game.selected_space = find_space_index(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.available_ops > 1) { console.log('in ahb check, country, ', spaces[game.selected_space].country, 'ahb', game.persistent_events['austria_hungary_border_reopened']) if (spaces[game.selected_space].country === 'East_Germany' && game.persistent_events['austria_hungary_border_reopened'] && game.active === DEM) { game.state = 'finish_austria_hungary_border_reopened_check' return } } game.state = 'finish_do_support_check' }, done () { 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(spaces[game.selected_space].name_unique) game.available_ops-- if (game.available_ops === 0) { game.valid_spaces = [] } game.state = 'finish_support_check_prep' return } } states.add_influence = { inactive: 'add influence.', prompt () { if (game.available_ops <= 0) { view.prompt = 'Place influence: done.' gen_action("done") return } view.prompt = `Add influence: ${game.available_ops} remaining.` // Generate actions for valid spaces for (let space_id of game.valid_spaces) { /* const space = spaces.find(s => s && s.space_id === space_id); if (space) { */ gen_action_infl(spaces[space_id].name_unique); //} } }, infl(space) { add_infl(space) }, done() { if(game.vm_event_to_do) { reset_austria_hungary_border_reopened() game.state = 'resolve_opponent_event'} else { end_round()} } } states.tiananmen_square_attempt = { inactive: 'do Tiananmen Square Attempt.', prompt () { if ((game.active === DEM && game.dem_tst_attempted_this_turn > 0 )|| (game.active === COM && game.com_tst_attempted_this_turn > 0)) { if (game.tst_success) { view.prompt = 'Tiananmen Square Track attempt successful.' } else { view.prompt = 'Tiananmen Square Track attempt failed.' } gen_action('done') return } view.prompt = 'Tiananmen Square Track attempt: Roll a die.' gen_action('roll') }, roll() { clear_undo() do_tst_attempt () }, done () { game.tst_success = false 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.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['general_strike']) { 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['general_strike']) { game.state = 'general_strike' } else { game.state = 'choose_card' } } } states.support_check_prep = { inactive: 'do support checks', prompt () { if (game.available_ops === 0) { view.prompt = 'Support checks: done.' gen_action('done') //return } 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) { /*const space = spaces.find(s => s && s.space_id === space_id); if (space) {*/ gen_action_sc(spaces[space_id].name_unique); //} } } }, sc(space) { push_undo() game.selected_space = find_space_index(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.available_ops > 1) { console.log('in ahb check, country, ', spaces[game.selected_space].country, 'ahb', game.persistent_events['austria_hungary_border_reopened']) if (spaces[game.selected_space].country === 'East_Germany' && game.persistent_events['austria_hungary_border_reopened'] && game.active === DEM) { game.state = 'austria_hungary_border_reopened_check' return } //game.state = 'do_support_check' } /*else { */ game.state = 'do_support_check' console.log('game.state after space selected:', game.state) //} }, done () { 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() } game.state = 'raise_stakes_1' return } if (game.vm_event_to_do) { reset_austria_hungary_border_reopened() game.state = 'resolve_opponent_event' } else { end_round() } } } 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(spaces[game.selected_space].name_unique) 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' } } //======================= POWER STRUGGLE =============================== states.draw_power_cards = { inactive: 'draw cards.', prompt() { view.prompt = 'Draw cards.' gen_action('draw') }, draw() { push_undo() 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 console.log('test') if (game.persistent_events['roundtable_talks'] && 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['roundtable_talks'] = false } if (game.persistent_events['national_salvation_front'] && 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['national_salvation_front'] = false } //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) 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('The Crowd Turns Against Ceausescu') game.persistent_events['the_crowd_turns_against_ceausescu'] = true 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 ${cards[54].name}.` }, prompt() { view.prompt = 'The Crowd Turns Against Ceausescu: draw cards.' gen_action('draw') }, draw() { 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.temp = game.temp * 3 game.state = 'the_crowd_turns_against_ceausescu' } } states.the_crowd_turns_against_ceausescu = { get inactive() { return `resolve ${cards[54].name}.` }, prompt() { view.prompt = `You have ${game.temp} influence points. Play for:` gen_action('influence') gen_action('support_check') }, influence() { push_undo() game.ceausescu_cards = [] valid_spaces_infl() 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() game.ceausescu_cards = [] valid_spaces_sc() game.available_ops = 2 game.state = 'support_check_prep' } } states.the_crowd_turns_against_ceausescu_infl = { inactive: 'add influence.', prompt () { if (game.temp === 0) { view.prompt = 'Place influence: done.'; gen_action("done"); return; } view.prompt = `Add influence: ${game.temp} remaining` for (let space of game.valid_spaces) { gen_action_infl(spaces[space].name_unique) } }, infl(space) { add_infl(space) game.temp -- }, done() { 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 the stakes: game.played_power_card', game.played_power_card, 'game.active', game.active, 'game.view_opp_hand', game.view_opp_hand) 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++ } }, pass(){ log('Did not raise the stakes') game.raised_stakes_discard = 0 next_player() game.state = 'raise_stakes_2' }, done () { log_gap('Raised the stakes') game.raised_stakes_discard = 0 next_player() game.state = 'raise_stakes_2' } } states.raise_stakes_2 = { inactive: 'raise the stakes', prompt () { 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++ } }, 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.tactics_fails', game.tactics_fails) 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(`Rolled a ${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 () { 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 () { console.log('game.played_power_card', game.played_power_card) 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 = `Support Loss: remove ${game.available_ops} influence.` for (let space_id of game.valid_spaces) { /*const space = spaces.find(s => s && s.space_id === space_id); Don't think this is needed if (space) { */ gen_action_infl(spaces[space_id].name_unique); //} } } else if (game.phase === 1 && game.available_ops === 0 ) { view.prompt = 'Support Loss: finished.' gen_action('done') } else if (game.phase === 1 && game.valid_spaces.length === 0) { view.prompt = 'No remaining influence to remove.' gen_action('done') } }, roll () { let roll = Math.floor(Math.random() * 6) + 1 let rally_win = 0 let petition_win = 0 log(`Rolled a ${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['yakovlev']) { 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] game.phase++ 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 () { next_player() log_h3('Victory Point') game.phase = 0 game.state = 'vp_roll' } } states.vp_roll = { inactive: 'do VP Roll', prompt () { if (game.phase === 0) { view.prompt = 'Roll a die for Victory.' gen_action('roll') } else if (game.phase === 1) { view.prompt = 'Take power.' gen_action('take') } else if (game.phase === 2) { view.prompt = 'Proceed to scoring.' gen_action('scoring') } }, roll () { let roll = Math.floor(Math.random() * 6) + 1 log(`Rolled a ${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['yakovlev']) { log('+1 from Yakovlev Counsels Gorbachev') 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) 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['the_crowd_turns_against_ceausescu']) { game.return_state = 'finish_scoring' 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() } 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('Power Struggle resolved') /*At this point log card dicarded or permanently removed? */ if (game.persistent_events['new_years_eve_party'] === 2) { game.state = 'new_years_eve_party' return } check_vp() reset_power() 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['new_years_eve_party'] === 1) { log_h1(`New Year's Eve Party`) game.persistent_events['new_years_eve_party'] = 2 game.state = 'new_years_eve_party' } else if(game.turn === 10) { clear_undo() game.state = 'final_scoring_held' log_h2('Final Scoring') } else { game.return_state = '' 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() { const held_countries = Object.values(game.revolutions).filter(value => value === false).length let vp_gain = 4*held_countries log(`Communist holds ${held_countries} countries: gains ${vp_gain} VP`) game.vp -= 4*held_countries game.scored_countries = {'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.scored_countries['East_Germany'] && game.scored_countries['Poland'] && game.scored_countries['Czechoslovakia'] && game.scored_countries['Hungary'] && game.scored_countries['Romania'] && game.scored_countries['Bulgaria']) { view.prompt = 'Country scoring: done.' gen_action('done') } else { view.prompt = 'Choose a country to score' if (!game.scored_countries['East_Germany']) {gen_action('east_germany')} if (!game.scored_countries['Poland']) {gen_action('poland')} if (!game.scored_countries['Czechoslovakia']) {gen_action('czechoslovakia')} if (!game.scored_countries['Hungary']) {gen_action('hungary')} if (!game.scored_countries['Romania']) {gen_action('romania')} if (!game.scored_countries['Bulgaria']) {gen_action('bulgaria')} } }, east_germany() { score_country('East_Germany') game.scored_countries['East_Germany'] = true }, poland() { score_country('Poland') game.scored_countries['Poland'] = true }, czechoslovakia() { score_country('Czechoslovakia') game.scored_countries['Czechoslovakia'] = true }, hungary() { score_country('Hungary') game.scored_countries['Hungary'] = true }, romania() { score_country('Romania') game.scored_countries['Romania'] = true }, bulgaria() { score_country('Bulgaria') game.scored_countries['Bulgaria'] = true }, done() { 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.' 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 = 'Roll a die.' gen_action('roll') } }, card (card) { push_undo() log(`Discarded C${cards[card].number}`) game.played_card = card let find_card find_card = game.communist_hand.indexOf(card); game.communist_hand.splice(find_card, 1); //Check if the discarded card is a scoring card if (scoring_cards.includes(game.played_card)) { log(`Played C${card}`) game.return_state = 'general_strike' goto_vm(card) return } // Otherwise, set card ops for the roll if (game.persistent_events['perestroika'] && game.active === COM) { log('+1 op from C25') game.available_ops = cards[card].ops +1 } else {game.available_ops = cards[card].ops} }, roll() { clear_undo() let roll = Math.floor(Math.random() * 6) + 1 log(`Rolled a ${roll}`) log(`+${game.available_ops} from C${cards[game.played_card].number}.`) let total = roll + game.available_ops log(`Modified total: ${total}`) if (total > 5) { log('The strike is over.') permanently_remove(5) game.persistent_events['general_strike'] = false } else { log('The strike continues. Required 6 or more') } game.phase = 1 }, done () { 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['honecker'] = false game.state = 'choose_card' }, pass() { log('C15: passed') game.persistent_events['honecker'] = false end_round() } } states.new_years_eve_party = { get inactive() { return `resolve ${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['East_Germany']) {gen_action('east_germany')} if (!game.revolutions['Poland']) {gen_action('poland')} if (!game.revolutions['Czechoslovakia']) {gen_action('czechoslovakia')} if (!game.revolutions['Hungary']) {gen_action('hungary')} if (!game.revolutions['Romania']) {gen_action('romania')} if (!game.revolutions['Bulgaria']) {gen_action('bulgaria')} 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() 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('', `New 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() { if (game.stasi_card === 0 ) { 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) } } else { view.prompt = 'Stasi: choose card done.' gen_action('done') } }, card(card) { push_undo() log_gap(`Stasi: selected C${cards[card].number}`) game.stasi_card = card }, pass() { log('Stasi: Democrat has no remaining cards') game.stasi_card = 0 game.round_player = COM game.round ++ log_h2(`Action Round ${game.round}`) next_player() game.valid_spaces = [] if (game.persistent_events['general_strike']) { log_h3('C5') game.state = 'general_strike' } else { game.state = 'choose_card' } }, done() { game.round_player = COM game.round ++ log_h2(`Action Round ${game.round}`) next_player() game.valid_spaces = [] if (game.persistent_events['general_strike']) { log_h3('C5') game.state = 'general_strike' } else { game.state = '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.stasi_card === 0) { view.prompt = 'Stasi: you must pass.' gen_action('pass') } else { view.prompt = `Stasi: you must play ${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${cards[card].number}`) game.played_card = card let find_card find_card = game.democrat_hand.indexOf(card); const [playedCard] = game.democrat_hand.splice(find_card, 1); game.available_ops = cards[card].ops if (game.available_ops > 1 && game.persistent_events['prudence'] === DEM) { game.available_ops-- } }, pass () { log('No cards remaining. Passed') end_round() }, done () { game.state = 'play_card' game.stasi_card = 0 } } // ==================== SUPPORTING STATE FUNCTIONS ============================= function add_infl(space) { push_undo() console.log('adding infl to', space) const clicked_space = find_space_index(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 %${clicked_space}.`) if (spaces[clicked_space].country !== 'East_Germany'){ game.austria_hungary_border_reopened_tracker = false } // Check Genscher if (game.persistent_events['genscher'] && game.active === DEM && spaces[clicked_space].country === 'East_Germany') { game.available_ops-- } else if (check_control(clicked_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(`(Used +1 op from C58)`) } } else { game.available_ops-- } // Update influence values if (game.active === COM) { game.pieces[clicked_space].comInfl++ } else { game.pieces[clicked_space].demInfl++ } // Check whether spaces are controlled check_control_change(clicked_space) // Check Austria Hungary Border Reopened is true and condition has been met if (game.available_ops === 0 && game.active === DEM && game.persistent_events['austria_hungary_border_reopened'] && game.austria_hungary_border_reopened_tracker) { game.available_ops ++ log('+1 influence 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['genscher'] || (game.persistent_events['austria_hungary_border_reopened'] && game.austria_hungary_border_reopened_tracker)) { console.log('in gensher subcheck - remove non-East German controlled ') game.valid_spaces = game.valid_spaces.filter(n => !(game.pieces[n].comCtrl === 1 && spaces[n].country !== 'East_Germany')) } else { console.log('remove all controlled spaces') game.valid_spaces = game.valid_spaces.filter(n => game.pieces[n].comCtrl !== 1) } } else { game.valid_spaces = game.valid_spaces.filter(n => game.pieces[n].demCtrl !== 1) } } //Clear valid spaces if no IP remaining. if (game.available_ops <= 0 ) { game.valid_spaces = [] } } function remove_infl(space) { push_undo() const clicked_space = find_space_index(space) log(`Removed 1 influence from %${clicked_space}.`) if (game.remove_opponent_infl === true) { if (game.active === COM) { game.pieces[clicked_space].demInfl-- if (game.pieces[clicked_space].demInfl === 0) { game.valid_spaces = game.valid_spaces.filter(id => id !== clicked_space); } } else { game.pieces[clicked_space].comInfl-- if (game.pieces[clicked_space].comInfl === 0) { game.valid_spaces = game.valid_spaces.filter(id => id !== clicked_space); } } check_control_change(clicked_space) } else { if (game.active === COM) { game.pieces[clicked_space].comInfl-- if (game.pieces[clicked_space].comInfl === 0) { game.valid_spaces = game.valid_spaces.filter(id => id !== clicked_space); } } else { game.pieces[clicked_space].demInfl-- if (game.pieces[clicked_space].demInfl === 0) { game.valid_spaces = game.valid_spaces.filter(id => id !== clicked_space); } } check_control_change(clicked_space) } game.available_ops-- } function do_sc(space) { log_gap(`Support check: ${space}`) let clicked_space = find_space_index(space) //Check Helsinki Final Act if (game.active === COM && game.persistent_events['helsinki_final_act'] && (spaces[clicked_space].socio === 5 || spaces[clicked_space].socio === 6) ) { log('+1 VP from C26') game.vp ++ check_vp() } // Continue with Support Check Logic let roll = Math.floor(Math.random() * 6) + 1 log(`Rolled a ${roll}`) console.log('game.vm_event', game.vm_event) console.log('game.is_pwr_struggle', game.is_pwr_struggle) //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.temp log(`+${game.temp} from Ceausescu`) } // Check if in Tiananmen Square Track Award else if (game.state === 'vm_tst_6_sc') { roll += 2 log('+2 from Tiananmen Square Track award') } else { let card_ops = cards[game.played_card].ops // Check for Perestoika if (game.active === COM && game.persistent_events['perestroika']) { card_ops++ } // Check for Sinatra Doctrine if (game.active === DEM && game.persistent_events['sinatra_doctrine']) { card_ops++ } // Check for Prudence if ((game.active === DEM && game.persistent_events['prudence'] === DEM) || game.active === COM && game.persistent_events['prudence'] === COM) { card_ops-- } roll += card_ops log(`+${card_ops} from card ops`) } if (game.support_check_modifier > 0) { roll += game.support_check_modifier log(`+${game.support_check_modifier} from event`) } // Events which modify SC rolls if (game.active === COM && game.persistent_events['tear_gas'] && spaces[clicked_space].socio === 6) { roll ++ log('+1 from C30') permanently_remove(30) game.persistent_events['tear_gas'] = false } if (game.active === DEM && spaces[clicked_space].region === 'Eastern Europe' && game.persistent_events['frg_embassies']) { roll++ log('+1 from C74') } /*if (game.warsaw_pact_summit) { roll += 2 log('+2 from C76') }*/ if (game.active === DEM && spaces[clicked_space].country === 'East_Germany' && game.persistent_events['grenztruppen']) { roll-- log('-1 from C59') } if ((game.active === COM && game.persistent_events['stand_fast'] === DEM && game.pieces[clicked_space].demCtrl === 1) || (game.active === DEM && game.persistent_events['stand_fast'] === COM && game.pieces[clicked_space].comCtrl === 1)){ roll-- log('-1 from C100') } if (game.active === DEM && game.persistent_events['elena'] && spaces[clicked_space].country === 'Romania') { roll-- log('-1 from C101') } if (game.active === DEM && game.persistent_events['austria_hungary_border_reopened'] && game.austria_hungary_border_reopened_tracker) { roll++ log(`+1 from C58`) } // Continue with logic - check for adjacency // Events which affect adjacency - The Wall const adj = count_adj(space) if (game.active === COM && game.persistent_events['the_wall'] && spaces[clicked_space].country === 'East_Germany') { log('No adjacency for Democrats due to C9') log('C9 no longer in effect') roll += adj.com_adj if (adj.com_adj > 0) { log(`+${adj.com_adj} from adjacent control`) } game.persistent_events['the_wall'] = false // 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) { log(`+${adj.dem_adj} from adjacent control`) } if (adj.com_adj > 0) { log(`-${adj.com_adj} from adjacent opponent control`) } } else { roll += adj.com_adj roll -= adj.dem_adj if (adj.com_adj > 0) { log(`+${adj.com_adj} from adjacent control`) } if (adj.dem_adj > 0) { log(`-${adj.dem_adj} from adjacent opponent control`) } } } } // Support check calcs log(`Total support check strength: ${roll}`) const stability = spaces[find_space_index(space)].stability log(`Stability is ${stability}. Defence is ${stability*2}`) const change_infl = Math.max(0, roll - stability*2) if (change_infl > 0) { log_msg_gap(`${change_infl} point swing`) let clicked_space = find_space_index(space) if(game.active === DEM) { if (change_infl > game.pieces[clicked_space].comInfl) { const residual = change_infl - game.pieces[clicked_space].comInfl game.pieces[clicked_space].comInfl = 0 game.pieces[clicked_space].demInfl += residual } else { game.pieces[clicked_space].comInfl -= change_infl } if (game.pieces[clicked_space].comInfl === 0) { game.valid_spaces = game.valid_spaces.filter(id => id !== clicked_space) } } else { if (change_infl > game.pieces[clicked_space].demInfl) { const residual = change_infl - game.pieces[clicked_space].demInfl game.pieces[clicked_space].demInfl = 0 game.pieces[clicked_space].comInfl += residual } else { game.pieces[clicked_space].demInfl -= change_infl } if (game.pieces[clicked_space].demInfl === 0) { game.valid_spaces = game.valid_spaces.filter(id => id !== clicked_space) } } check_control_change(clicked_space) } else { log_msg_gap('No change in influence') } if (game.active === COM && game.persistent_events['eco_glasnost'] && spaces[clicked_space].space_id === 66) { log_msg_gap('+1 VP from Eco Glasnost') game.vp++ check_vp() } // If Austria-Hungary Border Reopened used, all future support checks must be in East Germany if (game.austria_hungary_border_reopened_tracker) { game.valid_spaces = game.valid_spaces.filter(n => spaces[n].country === 'East_Germany') } game.selected_space = 0 clear_undo() } function valid_spaces_setup() { game.valid_spaces = [] let valid_spaces_set = new Set(); if (game.state === 'com_init') { for (let space of game.pieces) { if (space && space.demInfl === 0) { valid_spaces_set.add(space.space_id); } } } else if (game.state === 'dem_init') { for (let space of game.pieces) { if (space && space.comInfl === 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(); if (game.active === DEM) { for (let space of game.pieces) { if (space && space.comInfl !== 0 ) { valid_spaces_set.add(space.space_id); } } } else { for (let space of game.pieces) { if (space && space.demInfl !== 0 ) { if (game.persistent_events['solidarity_legalised']) { if (space.space_id === 14) {continue} } if (game.persistent_events['civic_forum']) { if (space.space_id === 31) {continue} } if (game.persistent_events['we_are_the_people']) { if (space.space_id === 9) {continue} } valid_spaces_set.add(space.space_id); } } //Check for Foreign Currency Debt Burden if (game.persistent_events['foreign_currency_debt_burden'] !== '') { for (let n of valid_spaces_set) { if (spaces[n].country === game.persistent_events['foreign_currency_debt_burden']) { valid_spaces_set.delete(n); } } } } // 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['the_crowd_turns_against_ceausescu']) { 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(); if (game.state === 'support_loss') { 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.demInfl > 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.comInfl > 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 piece of game.pieces) { if (!piece) continue //console.log('checking piece:', piece) const player_influence = game.active === COM ? piece.comInfl : piece.demInfl; // If the piece has the player's influence, add it and its adjacent spaces to the set if (player_influence > 0) { //console.log(piece, 'added to set') valid_spaces_set.add(piece.space_id); // Check adjacency information for (let adj_space_id of piece.adjacent) { //console.log('adj_space_id', adj_space_id) if (adj_space_id) { //console.log('checking adjacent space', spaces[adj_space_id].name_unique) const adj_piece = game.pieces.find(p => p && p.space_id === adj_space_id); //console.log('adjacent piece', adj_piece) // Check if the adjacent space is controlled by the opponent const opponent_control = game.active === COM ? adj_piece.demCtrl : adj_piece.comCtrl; //console.log('controlled?', opponent_control) //console.log('genscher?', game.persistent_events['genscher']) //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['genscher']){ //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) { //console.log('space added normally') 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(name_unique) { const space = game.pieces[find_space_index(name_unique)] let dem_adj = 0 let com_adj = 0 for (let adj_space_id of space.adjacent) { if (adj_space_id) { 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++ } } } } 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) { if (game.active === COM && game.pieces[space_id].demCtrl === 1) { return true; } else if (game.active === DEM && game.pieces[space_id].comCtrl === 1) { return true; } else { return false; } } function do_tst_attempt() { let roll = Math.floor(Math.random() * 6) + 1; log(`Rolled a ${roll}`); roll += game.available_ops log(`+${game.available_ops} from the card operations value`) // TIANANMEN SQUARE MODIFIERS if (game.active === DEM && game.dem_tst_attempted === 1 || game.active === COM && game.com_tst_attempted === 1) { roll ++; log('+1 modifier from previous Tiananmen Square Track attempts') } if ((game.active === DEM && cards[game.played_card].side === 'D') || (game.active === COM && cards[game.played_card].side === 'C')) { roll ++; log('+1 for playing own card'); } if (game.active === COM && game.persistent_events['li_peng']) { roll ++ log('+1 from Li Peng') } log(`Modified die roll: ${roll}`) // TIANANMEN SQUARE ATTEMPT game.return = game.active game.return_state = 'tiananmen_square_attempt' 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.tst_success = true game.dem_tst_position++ game.dem_tst_attempted = 0 if (game.dem_tst_position === 3 && game.com_tst_position < 3) {goto_vm(203)} if (game.dem_tst_position === 4 && game.com_tst_position < 4) {goto_vm(204)} } else { log(`${dem_tst_req[game.dem_tst_position]} required: fail`) game.dem_tst_attempted = 1 } } 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.tst_success = true game.com_tst_position++ game.com_tst_attempted = 0 if (game.com_tst_position === 3 && game.dem_tst_position < 3) {goto_vm(203)} if (game.com_tst_position === 4 && game.dem_tst_position < 4) {goto_vm(204)} } else { log(`${com_tst_req[game.com_tst_position]} required: fail`) game.com_tst_attempted = 1 } } // Check whether The Reformer is playable: if ((game.dem_tst_position !== game.com_tst_position)) { game.playable_cards[67].playable = 2 } } 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 space of spaces) { if (space && space.country === country) { let piece = game.pieces.find(p => p && p.space_id === space.space_id); if (piece.demCtrl === 1) { dem_spaces++; if (space.battleground === 1) { dem_battlegrounds++; } if ([1, 4, 5, 6, 7].includes(space.socio)) { dem_leaders[space.socio] = true; } } if (piece.comCtrl === 1) { com_spaces++; if (space.battleground === 1) { com_battlegrounds++; } if ([1, 4, 5, 6, 7].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[country] = true game.times_held[country] = 1 } function retain_power(country){ game.times_held[country]++ let vp_gain = get_value(country)*game.times_held[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 } 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 } 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 permanently_remove(card) { console.log('card:', card) log_msg_gap(`C${cards[card].number} permanently removed`) let card_index = game.strategy_discard.indexOf(card) if (card_index !== -1) { console.log('sub 1 called') game.strategy_discard.splice(card_index, 1) } 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!`) } else if(game.vp <= -20) { goto_game_over(COM, `${COM} won an Automatic Victory!`) } } 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) //return true } function reset_austria_hungary_border_reopened() { //game.austria_hungary_border_reopened_checked = false game.austria_hungary_border_reopened_tracker = false } // =========== MOVING THROUGH TURNS ============ function end_round() { //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.warsaw_pact_summit = false game.vm_influence_added = {} game.return = '' game.valid_cards = [] game.valid_spaces = [] 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)) { const duplicates = find_duplicates(card_check) console.log('discard', game.strategy_discard, 'removed', game.strategy_removed, 'game.table_cards', game.table_cards, 'com hand', game.communist_hand, 'dem 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 last round and if so resolve end turn events if (game.round_player === DEM && game.round === 7) { if(game.persistent_events['honecker']) { 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 if(game.round_player === COM && game.stasi_card > 0 ) { game.round_player = DEM if (game.active !== DEM) { next_player() } game.state = 'stasi_play_card' return } else if (game.round_player === COM && game.round === 8) { clear_undo() game.state = 'end_turn_4_5_4' return } else if (game.round_player===COM) { game.round_player = DEM if (game.active !== DEM) { next_player() } game.state = 'choose_card' return } if (game.round_player === DEM) { if(game.persistent_events['stasi']) { //console.log('stasi sub function') if (game.active !== DEM) { next_player() } game.state = 'stasi_end_round' return } else if(game.round_player === DEM && game.persistent_events['general_strike']){ 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 game.tst_7 = false game.tst_8 = false game.persistent_events['perestroika'] = false game.persistent_events['prudence'] = '' game.persistent_events['sinatra_doctrine'] = false game.persistent_events['stasi'] = false game.persistent_events['honecker'] = false //Remove Events on the table which last only 1 turn console.log('in new turn') if (game.persistent_events['austria_hungary_border_reopened']) { game.persistent_events['austria_hungary_border_reopened'] = false permanently_remove(58) } if (game.persistent_events['elena']) { game.persistent_events['elena'] = false permanently_remove(101) } if (game.persistent_events['grenztruppen']) { game.persistent_events['grenztruppen'] = false permanently_remove(59) } if (game.persistent_events['foreign_currency_debt_burden'] !== '') { game.persistent_events['foreign_currency_debt_burden'] = '' permanently_remove(49) } if (game.persistent_events['frg_embassies']) { console.log('in new turn - frg embassies check') game.persistent_events['frg_embassies'] = false permanently_remove(74) } if (game.persistent_events['genscher']) { game.persistent_events['genscher'] = false permanently_remove(63) } if (game.persistent_events['stand_fast'] !== '') { game.persistent_events['stand_fast'] = '' permanently_remove(100) } if (game.samizdat_card > 0 ) { game.democrat_hand.push(game.samizdat_card) game.samizdat_card = 0 } 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['presidential_visit']) { game.com_hand_limit = 7 log('Communist draws 7 cards due to Presidential Visit') permanently_remove(65) game.persistent_events['presidential_visit'] = false } 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['general_strike']) { 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 game.pieces.findIndex(piece => piece && piece.name_unique === name_unique); } 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) const randomIndex = Math.floor(Math.random() * deck.length) //console.log('card chosen:', randomIndex) 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) } 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) } 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 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 = power_cards.filter(card => card !== null && card.number <= 52).map(card => card.number) 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.rally_win = 0 //game.petition_win = 0 game.tactics_fails = '' game.view_opp_hand = false if (game.persistent_events['peasant_parties_revolt']){ permanently_remove(72) game.table_cards = game.table_cards.filter(card => card !== 72) game.persistent_events['peasant_parties_revolt'] = false } if (game.persistent_events['yakovlev']) { permanently_remove(62) game.table_cards = game.table_cards.filter(card => card !== 62) game.persistent_events['yakovlev'] = false } if (game.persistent_events['the_crowd_turns_against_ceausescu'] && game.pwr_struggle_in === 'Romania'){ permanently_remove(54) //game.table_cards = game.table_cards.filter(card => card !== 54) game.persistent_events['the_crowd_turns_against_ceausescu'] = false } if (game.pwr_struggle_in === 'Romania' && game.persistent_events['securitate']){ permanently_remove(70) game.table_cards = game.table_cards.filter(card => card !== 70) game.persistent_events['securitate'] = false } } function check_control_change(space_id) { game.pieces[space_id].demCtrl = 0 game.pieces[space_id].comCtrl = 0 if ((game.pieces[space_id].demInfl - game.pieces[space_id].comInfl) >= game.pieces[space_id].stability) { game.pieces[space_id].demCtrl = 1 } if ((game.pieces[space_id].comInfl - game.pieces[space_id].demInfl) >= game.pieces[space_id].stability) { game.pieces[space_id].comCtrl = 1 } // Check if the Tyrant is Gone has been fulfilled if (game.persistent_events['the_tyrant_is_gone'] > 0 && game.pieces[game.persistent_events['the_tyrant_is_gone']].demCtrl === 1) { log('+2 VP from C97') game.vp += 2 game.persistent_events['the_tyrant_is_gone'] = 0 } } function check_systematisation() { // Check for Systematisation - may not use this space if (game.persistent_events['systematization'] > 0) { game.valid_spaces = game.valid_spaces.filter(n => n !== game.persistent_events['systematization']) } } function this_card() { return game.vm_event > 0 ? game.vm_event : game.played_card } const pluralize = (count, noun, suffix = 's') => `${count} ${noun}${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 COMMANDS ============= 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") } // ============ 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.vp.ip', game.vp.ip) for (let i = game.vp.ip; i < CODE[game.vm.fp].length; i++) { console.log('game.vp.ip', game.vp.ip) 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() { /* let return_vm = game.vm.return_vm; console.log('in vm_return') // Return control to the phasing player if (return_vm) { game.vm = return_vm; vm_next(); } else { // End of VM execution, return to normal game state game.state = "play_card"; } */ console.log('in vm_return, discard:', game.strategy_discard) game.support_check_modifier = 0 game.vm_event = 0 /*Reset to 0 now that event has been completed. Hopefully this doesn't cause issues! */ if (game.persistent_events['austria_hungary_border_reopened']) { reset_austria_hungary_border_reopened() } //game.view_opp_hand = false console.log('in vm_return, game.vm_return:', game.vm_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"} } /* ================== VM ACTIONS =========================== */ function vm_opp_hand_false() { game.view_opp_hand = false vm_next() } function vm_valid_spaces() { //vm_assert_argcount(6) 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 Systematisation - may not use this space check_systematisation() vm_next() } function vm_valid_spaces_opponent () { let valid_spaces = [] if (game.active === DEM) { for (let i = 1; i < game.pieces.length; i++) { let gamePiece = game.pieces[i] if (gamePiece.comInfl > 0) { valid_spaces.push(gamePiece.space_id) } } } else { for (let i = 1; i < game.pieces.length; i++) { let gamePiece = game.pieces[i] if (gamePiece.demInfl > 0) { valid_spaces.push(gamePiece.space_id) } } } game.valid_spaces = valid_spaces vm_next() } function vm_valid_spaces_socio () { let valid_spaces = [] for (let i = 1; i < game.pieces.length; i++) { let gamePiece = game.pieces[i] let space = spaces[i] if (space.socio === vm_operand(1)) { valid_spaces.push(gamePiece.space_id) } } game.valid_spaces = valid_spaces // Check for Systematisation - may not use this space if (game.persistent_events['systematization'] > 0) { game.valid_spaces = game.valid_spaces.filter(n => n !== game.persistent_events['systematization']) } vm_next() } function vm_valid_spaces_opponent_socio () { let valid_spaces = [] if (game.active === DEM) { for (let i = 1; i < game.pieces.length; i++) { let gamePiece = game.pieces[i] let space = spaces[i] if (gamePiece.comInfl > 0 && space.socio === vm_operand(1)) { valid_spaces.push(gamePiece.space_id) } } } else { for (let i = 1; i < game.pieces.length; i++) { let gamePiece = game.pieces[i] let space = spaces[i] if (gamePiece.demInfl > 0 && space.socio === vm_operand(1)) { valid_spaces.push(gamePiece.space_id) } } } game.valid_spaces = valid_spaces // Check for Systematisation - may not use this space if (game.persistent_events['systematization'] > 0) { game.valid_spaces = game.valid_spaces.filter(n => n !== game.persistent_events['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 Systematisation - may not use this space if (game.persistent_events['systematization'] > 0) { game.valid_spaces = game.valid_spaces.filter(n => n !== game.persistent_events['systematization']) } vm_next() } function vm_valid_spaces_sc () { console.log('in vm_valid_spaces_sc: game.persistent_events[we_are_the_people]', game.persistent_events['we_are_the_people']) valid_spaces_sc() /*let valid_spaces = [] for (let space of game.pieces) { if (!space) continue if (game.active === DEM) { if (space.comInfl >0) { valid_spaces.push(space.space_id); } } else { if (space.demInfl >0) { valid_spaces.push(space.space_id); } if (game.persistent_events['civic_forum']) { if (space.space_id === 31) {continue} } if (game.persistent_events['we_are_the_people']) { if (space.space_id === 9) {continue} } } } game.valid_spaces = valid_spaces if (game.persistent_events['foreign_currency_debt_burden'] !== '') { game.valid_spaces = game.valid_spaces.filter(n => spaces[n].country !== game.persistent_events['foreign_currency_debt_burden']) }*/ 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.pieces[space.space_id].comInfl >0) { game.valid_spaces.push(space.space_id); } } else { if (space.country === country && game.pieces[space.space_id].demInfl >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.pieces[space.space_id].comInfl >0) { valid_spaces.push(space.space_id); } } else { if (space.country === country && game.pieces[space.space_id].demInfl >0) { if (game.persistent_events['solidarity_legalised'] && space.space_id === 14) {continue} if (game.persistent_events['civic_forum'] && space.space_id === 31) {continue} if (game.persistent_events['we_are_the_people'] && space.space_id === 9) {continue} valid_spaces.push(space.space_id); } } } game.valid_spaces = valid_spaces if (!game.is_pwr_struggle && game.persistent_events['foreign_currency_debt_burden'] !== '') { game.valid_spaces = game.valid_spaces.filter(n => spaces[n].country !== game.persistent_events['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.persistent_events['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.persistent_events['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.pieces[s].comInfl > 0 ) || (game.active === COM && space.region === vm_operand(1) && game.pieces[s].demInfl > 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 space of spaces) { if (!space) continue let uncontrolled = game.pieces[space.space_id].demCtrl === 0 && game.pieces[space.space_id].comCtrl === 0 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) { let clicked_space = find_space_index(space) if (game.active === DEM) { let current_infl = game.pieces[clicked_space].demInfl let opponent_infl = game.pieces[clicked_space].comInfl let stability = spaces[clicked_space].stability if ((current_infl - opponent_infl) < stability) { game.pieces[clicked_space].demInfl += stability - current_infl + opponent_infl game.pieces[clicked_space].demCtrl = 1 game.pieces[clicked_space].comCtrl = 0 } } else if (game.active === COM) { let current_infl = game.pieces[clicked_space].comInfl let opponent_infl = game.pieces[clicked_space].demInfl let stability = spaces[clicked_space].stability if ((current_infl - opponent_infl) < stability) { game.pieces[clicked_space].comInfl += stability - current_infl + opponent_infl game.pieces[clicked_space].comCtrl = 1 game.pieces[clicked_space].demCtrl = 0 } } game.valid_spaces = game.valid_spaces.filter(id => id !== clicked_space) log(`Took control of %${clicked_space}`) } function vm_do_add_infl(space) { push_undo() console.log('in vm_do_add_infl, space', space) const clicked_space = find_space_index(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 %${clicked_space}.`) if (spaces[clicked_space].country !== 'East_Germany'){ game.austria_hungary_border_reopened_tracker = false } // Check Genscher if (game.persistent_events['genscher'] && game.active === DEM && spaces[clicked_space].country === 'East_Germany') { game.vm_available_ops-- } else if (check_control(clicked_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(`(Used +1 op from C58)`) } } else { game.vm_available_ops-- } // Update influence values if (game.active === COM) { game.pieces[clicked_space].comInfl++ } else { game.pieces[clicked_space].demInfl++ } // Check whether spaces are controlled check_control_change(clicked_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['austria_hungary_border_reopened'] && game.austria_hungary_border_reopened_tracker) { game.vm_available_ops ++ log('+1 influence 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) { console.log(`in Genscher / AHBR check, game.persistent_events['genscher']`, game.persistent_events['genscher']) if (game.active === DEM) { if (game.persistent_events['genscher'] || (game.persistent_events['austria_hungary_border_reopened'] && game.austria_hungary_border_reopened_tracker)) { console.log('in gensher subcheck - remove non-East German controlled ') game.valid_spaces = game.valid_spaces.filter(n => !(game.pieces[n].comCtrl === 1 && spaces[n].country !== 'East_Germany')) } else { console.log('remove all controlled spaces') game.valid_spaces = game.valid_spaces.filter(n => game.pieces[n].comCtrl !== 1) } } else { game.valid_spaces = game.valid_spaces.filter(n => game.pieces[n].demCtrl !== 1) } } //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() const clicked_space = find_space_index(space) log(`Added 1 influence in %${clicked_space}.`) // Update influence values if (game.active === COM) { game.pieces[clicked_space].comInfl++ } else { game.pieces[clicked_space].demInfl++ } game.vm_available_ops-- // Check whether spaces are controlled check_control_change(clicked_space) //console.log('game pieces:', game.pieces[clicked_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() const clicked_space = find_space_index(space) log(`Added ${game.vm_available_ops} influence in %${clicked_space}.`) if (game.active === COM) { game.pieces[clicked_space].comInfl += game.vm_available_ops } else { game.pieces[clicked_space].demInfl += game.vm_available_ops } check_control_change(clicked_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() const clicked_space = find_space_index(space) log(`Added 1 influence in %${clicked_space}.`) game.vm_available_ops -- if (!game.vm_influence_added) { game.vm_influence_added = {}; } if (!game.vm_influence_added[clicked_space]) { game.vm_influence_added[clicked_space] = 0; } if (game.active === COM) { game.pieces[clicked_space].comInfl ++ } else { game.pieces[clicked_space].demInfl ++ } game.vm_influence_added[clicked_space] ++ //console.log('valid_spaces before update', game.valid_spaces) //console.log('influence added:', game.vm_influence_added[clicked_space], 'max infl', max_infl) if (game.vm_influence_added[clicked_space] === max_infl) { game.valid_spaces = game.valid_spaces.filter(id => id !== clicked_space); } check_control_change(clicked_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 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() const clicked_space = find_space_index(space) log(`Removed 1 influence from %${clicked_space}.`) if (!game.vm_influence_added) { game.vm_influence_added = {}; } if (!game.vm_influence_added[clicked_space]) { game.vm_influence_added[clicked_space] = 0; } if (game.remove_opponent_infl === true) { if (game.active === COM) { game.pieces[clicked_space].demInfl-- if (game.pieces[clicked_space].demInfl === 0) { game.valid_spaces = game.valid_spaces.filter(id => id !== clicked_space); } } else { game.pieces[clicked_space].comInfl-- if (game.pieces[clicked_space].comInfl === 0) { game.valid_spaces = game.valid_spaces.filter(id => id !== clicked_space); } } } else { if (game.active === COM) { game.pieces[clicked_space].comInfl-- if (game.pieces[clicked_space].comInfl === 0) { game.valid_spaces = game.valid_spaces.filter(id => id !== clicked_space); } } else { game.pieces[clicked_space].demInfl-- if (game.pieces[clicked_space].demInfl === 0) { game.valid_spaces = game.valid_spaces.filter(id => id !== clicked_space); } } } check_control_change(clicked_space) game.vm_influence_added[clicked_space]++ game.vm_available_ops-- if (game.vm_available_ops===0) {game.valid_spaces = []} } function vm_do_remove_x_infl(space) { push_undo() const clicked_space = find_space_index(space) if (game.remove_opponent_infl) { if (game.active === COM) { if (game.pieces[clicked_space].demInfl >= game.vm_available_ops) { game.pieces[clicked_space].demInfl -= game.vm_available_ops } else { game.vm_available_ops = game.pieces[clicked_space].demInfl game.pieces[clicked_space].demInfl -= game.vm_available_ops } } else { if (game.pieces[clicked_space].comInfl >= game.vm_available_ops) { game.pieces[clicked_space].comInfl -= game.vm_available_ops } else { game.vm_available_ops = game.pieces[clicked_space].comInfl game.pieces[clicked_space].comInfl -= game.vm_available_ops } } } else { if (game.active === COM) { if (game.pieces[clicked_space].comInfl >= game.vm_available_ops) { game.pieces[clicked_space].comInfl -= game.vm_available_ops } else { game.vm_available_ops = game.pieces[clicked_space].comInfl game.pieces[clicked_space].comInfl -= game.vm_available_ops } } else { if (game.pieces[clicked_space].demInfl >= game.vm_available_ops) { game.pieces[clicked_space].demInfl -= game.vm_available_ops } else { game.vm_available_ops = game.pieces[clicked_space].demInfl game.pieces[clicked_space].demInfl -= game.vm_available_ops } } } log(`Removed ${game.vm_available_ops} influence from %${clicked_space}`) check_control_change(clicked_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() const clicked_space = find_space_index(space) log(`Removed influence from %${clicked_space}.`) game.vm_available_ops -- if (!game.vm_influence_added) { game.vm_influence_added = {}; } if (!game.vm_influence_added[clicked_space]) { game.vm_influence_added[clicked_space] = 0; } if (game.active === COM) { game.pieces[clicked_space].demInfl -- if (game.pieces[clicked_space].demInfl === 0) { game.valid_spaces = game.valid_spaces.filter(id => id !== clicked_space) } } else { game.pieces[clicked_space].comInfl -- if (game.pieces[clicked_space].comInfl === 0) { game.valid_spaces = game.valid_spaces.filter(id => id !== clicked_space) } } game.vm_influence_added[clicked_space] ++ if (game.vm_influence_added[clicked_space] === max_infl) { game.valid_spaces = game.valid_spaces.filter(id => id !== clicked_space); } check_control_change(clicked_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() const clicked_space = find_space_index(space) log(`Removed all influence from %${clicked_space}.`) if (game.remove_opponent_infl === true) { if (game.active === COM) { game.pieces[clicked_space].demInfl = 0 } else { game.pieces[clicked_space].comInfl = 0 } check_control_change(clicked_space) } else { if (game.active === COM) { game.pieces[clicked_space].comInfl = 0 } else { game.pieces[clicked_space].demInfl = 0 } check_control_change(clicked_space) } game.vm_available_ops -- game.valid_spaces = game.valid_spaces.filter(id => id !== clicked_space) } function vm_replace_all_infl(space_id) { if (game.active === DEM) { game.pieces[space_id].demInfl += game.pieces[space_id].comInfl game.pieces[space_id].comInfl = 0 } else { game.pieces[space_id].comInfl += game.pieces[space_id].demInfl game.pieces[space_id].demInfl = 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(space){ push_undo() let clicked_space = find_space_index(space) game.pieces[clicked_space].demInfl -= game.vm_available_ops game.pieces[clicked_space].comInfl += game.vm_available_ops log(`Replaced ${game.vm_available_ops} influence in ${spaces[clicked_space].name_unique}`) game.vm_available_ops = 0 check_control_change(clicked_space) } /* ===================== 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') check_vp() vm_next() } function vm_adamec() { game.state = 'vm_adamec' } function vm_army_backs_revolution() { game.persistent_events['securitate'] = false game.playable_cards[70].playable = 0 if (game.table_cards.includes(70)) { permanently_remove(70) } vm_next() } function vm_austria_hungary_border_reopened() { game.persistent_events['austria_hungary_border_reopened'] = true game.table_cards.push(58) vm_next() } function vm_betrayal() { if (game.pieces[58].demInfl > 0 ) { game.valid_spaces.push(58) } if (game.pieces[65].demInfl >0 ) { game.valid_spaces.push(65) } game.vm_available_ops = Math.max(game.pieces[58].demInfl, game.pieces[65].demInfl) game.state = 'vm_switch_infl' } function vm_breakaway_baltic_republics() { log('+5 VP') game.vp += 5 game.stability++ check_vp() game.playable_cards[109].playable = 1 game.playable_cards[14].playable = 0 if (game.pieces[56].demCtrl === 0 && game.persistent_events['systematization'] !== 56) {game.valid_spaces.push(56)} if (game.pieces[70].demCtrl === 0) {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') check_vp() if (game.pieces[70].demInfl > 0) {game.valid_spaces = [70]} vm_next() } function vm_ceausescu() { let adj_cluj = false if (game.pieces[50].demInfl > 0 ) {adj_cluj = true} if (game.pieces[54].demInfl > 0 ) {adj_cluj = true} if (game.pieces[58].demInfl > 0 ) {adj_cluj = true} if (game.pieces[61].demInfl > 0 ) {adj_cluj = true} if (adj_cluj && game.pieces[61].comInfl>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++ check_vp() game.persistent_events['civic_forum'] = true if (game.pieces[31].demCtrl === 1) { 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' } 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 && game.playable_cards[c].playable === 1) { 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['eco_glasnost'] = true permanently_remove(39) vm_next() } function vm_elena(){ game.persistent_events['elena'] = true game.table_cards.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) // Remove clicked_space from the adjacency lists of its adjacent spaces adjacent_spaces.forEach(s => { game.pieces[s].adjacent = spaces[s].adjacent.filter(id => id !== space_id); }); console.log('adjacency after: Iasi', game.pieces[53].adjacent, 'Ploesti:', game.pieces[59].adjacent, 'Bucharesti:', game.pieces[61].adjacent) // Connect adjacent spaces to each other for (let i = 0; i < adjacent_spaces.length; i++) { for (let j = i + 1; j < adjacent_spaces.length; j++) { console.log(' checking i,', spaces[adjacent_spaces[i]].name, 'j', spaces[adjacent_spaces[j]].name) if (!game.pieces[adjacent_spaces[i]].adjacent.includes(adjacent_spaces[j])) { game.pieces[adjacent_spaces[i]].adjacent.push(adjacent_spaces[j]); } if (!game.pieces[adjacent_spaces[j]].adjacent.includes(adjacent_spaces[i])) { game.pieces[adjacent_spaces[j]].adjacent.push(adjacent_spaces[i]); } } } console.log('adjacency after addition: Iasi', game.pieces[53].adjacent, 'Ploesti:', game.pieces[59].adjacent, 'Bucharesti:', game.pieces[61].adjacent) // Clear the adjacency list of the clicked space game.pieces[space_id].adjacent = []; // Eliminate the democrat influence and move the communist influence to Bucharesti game.pieces[space_id].demInfl = 0 game.pieces[61].comInfl += game.pieces[space_id].comInfl log(`${game.pieces[space_id].comInfl} Communist influence relocated to Bucharesti`) game.pieces[space_id].comInfl = 0 check_control_change(space_id) } function vm_exit_visas() { game.state = 'vm_exit_visas' } function vm_foreign_currency_debt_burden() { log('+1VP') game.vp++ check_vp() game.table_cards.push(49) game.state = 'vm_foreign_currency_debt_burden' } function vm_foreign_television() { for (let piece of game.pieces) { if (!piece) continue if (piece.space_id === 12) {continue} /*Does not apply to Dresden*/ if (piece.comInfl > 0 ) { game.valid_spaces.push(piece.space_id) } } vm_next() } function vm_frg_embassies() { game.persistent_events['frg_embassies'] = true game.table_cards.push(74) log('C74 in effect') vm_next() } function vm_general_strike() { game.persistent_events['general_strike'] = true game.table_cards.push(5) log('C5 in effect') vm_next() } function vm_genscher() { game.persistent_events['genscher'] = true game.table_cards.push(63) log(`C63 in effect`) vm_next() } function vm_goodbye_lenin() { game.view_opp_hand = true // Select Red cards to show for (let card of game.communist_hand) { console.log('checking card ', card, 'red', cards[card].red) if (cards[card].red) { game.communist_hand_red.push(card) } console.log('game.communist_hand_red', game.communist_hand_red) } //Check if these cards are playabl for (let card of game.communist_hand_red) { if (game.playable_cards[card].playable === 1) { game.valid_cards.push(card) } } console.log('valid_cards', game.valid_cards) game.state = 'vm_goodbye_lenin' } function vm_government_resigns() { for (let space of game.pieces) { if (space && spaces[space.space_id].socio === 1 && space.comInfl > 0 && space.comCtrl === 0 && space.demCtrl === 0) { game.valid_spaces.push(space.space_id) } } game.remove_opponent_infl = true vm_next() } function vm_grenztruppen() { console.log('in grenztruppen - player active:', game.active) game.persistent_events['grenztruppen'] = true game.table_cards.push(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 log(`${change_vp} VP`) game.vp += change_vp check_vp() vm_next() } function vm_helsinki_final_act() { game.persistent_events['helsinki_final_act'] = true vm_next() } function vm_honecker() { game.persistent_events['honecker'] = true game.discard = true game.valid_cards = [] for (let c of game.strategy_discard) { if (scoring_cards.includes(c)) { continue} else { game.valid_cards.push(c) } } game.state = 'vm_honecker' } function vm_inflationary_currency() { game.state = 'vm_inflationary_currency' } function vm_inflationary_currency_discard() { for (let card of game.communist_hand){ if (game.persistent_events['perestroika']) { if (cards[card].ops >= 2) { game.valid_cards.push(card) } } else if (game.persistent_events['prudence'] === COM ) { if (cards[card].ops >= 4) { game.valid_cards.push(card) } } else { if (cards[card].ops >= 3) { game.valid_cards.push(card) } } } next_player() game.state = 'vm_inflationary_currency_discard' } function vm_kiss_of_death() { game.state = 'vm_kiss_of_death' } function vm_klaus_and_komarek() { if (game.pieces[29].comInfl > 0 ) {game.valid_spaces = [29]} vm_next() } function vm_kohl_proposes_reunification() { log('+2 VP') game.vp += 2 check_vp() if (game.persistent_events['the_wall_must_go']) { game.vm_event = 87 game.state = 'vm_common_european_home' } else { permanently_remove(87) vm_return() } } function vm_kremlin_coup() { log('-3 VP') game.vp -= 3 check_vp() elite_spaces.forEach(space => { if (!game.revolutions[spaces[space].country]) { game.valid_spaces.push(space); } }) game.state = 'vm_kremlin_coup_take_control' } function vm_laszlo_tokes() { game.persistent_events['laszlo_tokes'] = true game.playable_cards[107].playable = 1 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 space of game.pieces) { if (space && (space.comCtrl === 0 && spaces[space.space_id].country === 'Czechoslovakia')) { game.valid_spaces.push(space.space_id); } } vm_next() } function vm_li_peng() { game.persistent_events['li_peng'] = true game.table_cards.push(53) vm_next() } function vm_ligachev() { game.persistent_events['ligachev'] = true vm_next() } function vm_malta_summit() { game.state = 'vm_malta_summit' } function vm_massacre_in_timisoara() { game.persistent_events['laszlo_tokes'] = false vm_next() } function vm_modrow() { game.playable_cards[15].playable = 0 game.state = 'vm_modrow' } function vm_national_salvation_front() { game.persistent_events['national_salvation_front'] = true game.table_cards.push(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.pieces[27].demInfl >0) {game.valid_spaces.push(27)} if (game.pieces[29].demInfl > 0) {game.valid_spaces.push(29)} game.remove_opponent_infl = true vm_next() } function vm_peasant_parties_revolt() { game.persistent_events['peasant_parties_revolt'] = true log_msg_gap('C72 in effect') game.table_cards.push(72) vm_next() } function vm_perestroika() { game.persistent_events['perestroika'] = true log_msg_gap('C25 in effect') permanently_remove(25) vm_next() } function vm_poszgay() { let valid_spaces = [] for (let space of spaces) { if (space && space.country === 'Hungary' && game.pieces[space.space_id].demCtrl === 0) { 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 //Check if Power Struggle is because of an event if (game.vm_event > 0) { console.log('vm_power_struggle, in game.vm_event check') 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['securitate']) { console.log('in Securitate subcheck') log('C70: Democrat reveals Power Struggle cards') game.view_opp_hand = true } log_h2('Deal Cards') game.state = 'draw_power_cards' console.log('game.state',game.state) } function vm_presidential_visit() { game.persistent_events['presidential_visit'] = true game.table_cards.push(65) log_msg_gap('C65 in effect') vm_next() } function vm_prudence() { if (game.active === DEM) { game.persistent_events['prudence'] = COM } else {game.persistent_events['prudence'] = DEM} log_msg_gap('C8 in effect') vm_next() } function vm_public_against_violence() { game.valid_spaces = [] if (game.pieces[34].comInfl > 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 (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['roundtable_talks'] = true game.table_cards.push(17) log_msg_gap('C17 in effect') vm_next() } function vm_sajudis() { game.playable_cards[81].playable = 1 game.stability++ log('+1 VP') game.vp++ check_vp() vm_next() } function vm_samizdat() { game.state = 'vm_samizdat' } function vm_securitate() { game.persistent_events['securitate'] = true 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[3].playable = 1 game.persistent_events['solidarity_legalised'] = true vm_next() } function vm_st_nicholas_church () { game.persistent_events['st_nicholas_church'] = true game.playable_cards[61].playable = 1 permanently_remove(24) vm_next() } function vm_stasi() { log_msg_gap('C13 in effect') game.persistent_events['stasi'] = true vm_next() } function vm_stand_fast() { if (game.active === DEM) { game.persistent_events['stand_fast'] = DEM } else {game.persistent_events['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++ } else {game.com_tst_position++} vm_next() } function vm_tear_gas () { game.persistent_events['tear_gas']= true game.table_cards.push(30) log_msg_gap('C30 in effect') vm_next() } function vm_the_baltic_way() { game.playable_cards[84].playable = 1 game.stability++ if (game.pieces[56].demCtrl === 0 && game.persistent_events['systematization'] !== 56) {game.valid_spaces.push(56)} if (game.pieces[70].demCtrl === 0 && game.persistent_events['systematization'] !== 70) {game.valid_spaces.push(70)} log('+3 VP') game.vp += 3 check_vp() vm_next() } function vm_the_chinese_solution() { game.state = 'vm_the_chinese_solution' } function vm_the_crowd_turns_against_ceausescu() { //game.persistent_events['the_crowd_turns_against_ceausescu'] = true game.table_cards.push(54) game.playable_cards[97].playable = 1 vm_next() } function vm_the_monday_demonstrations() { if (game.pieces[6].demCtrl === 0) {game.valid_spaces.push(6)} if (game.pieces[9].demCtrl === 0) {game.valid_spaces.push(9)} vm_next() } function vm_the_sinatra_doctrine() { game.persistent_events['sinatra_doctrine'] = true 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 space of game.pieces) { if (space && space.demInfl === 0 && spaces[space.space_id].country === 'Romania') { if (space.space_id === game.persistent_events['systematization']) {continue} game.valid_spaces.push(space.space_id) } } game.playable_cards[10].playable = 0 game.playable_cards[41].playable = 0 game.playable_cards[101].playable = 0 game.playable_cards[107].playable = 0 console.log('game.vm_event', game.vm_event, 'game.played_card', game.played_card) game.state = 'vm_the_tyrant_is_gone' } function vm_the_tyrant_is_gone_prep() { game.table_cards.push(97) vm_next() } function vm_the_wall () { game.persistent_events['the_wall']= true //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.pieces[6].demInfl > 0) {game.valid_spaces = [6]} game.persistent_events['we_are_the_people'] = true 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[`${country}`] && game.pieces[space.space_id].comInfl > 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[`${country}`] && game.pieces[space.space_id].demInfl > 0 && space.socio === 4) { game.valid_spaces.push(space.space_id); } } } game.state = 'vm_workers_revolt' } function vm_yakovlev_counsels_gorbachev() { game.persistent_events['yakovlev'] = true log_msg_gap('C62 in effect') game.table_cards.push(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' } function vm_support_falters() { game.vm_available_ops = 2 game.return === game.active game.state = 'vm_support_falters' } /* ================== VM STATES ============================== */ states.vm_take_control = { get inactive() { return `resolve ${clean_name(cards[game.played_card].name)}.` }, prompt () { console.log('game.vm_available_ops', game.vm_available_ops) 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) { /*const space = spaces.find(s => s && s.space_id === space_id); if (space) {*/ gen_action_infl(spaces[space_id].name_unique); //} } } else { view.prompt = `${clean_name(cards[this_card()].name)}. Take control: done.` gen_action('done') } }, infl(space) { push_undo() vm_take_control(space) game.vm_available_ops-- }, done() { vm_next() } } states.vm_add_infl = { inactive: 'add influence.', prompt () { console.log('in vm add infl') if (game.vm_available_ops > 0 && game.valid_spaces.length === 0 ) { view.prompt = 'No available spaces remaining. Add influence: done.' gen_action('done') } else if (game.vm_available_ops > 0 ) { view.prompt = `${clean_name(cards[this_card()].name)}: add ${game.vm_available_ops} influence${event_prompt()}.` for (let space_id of game.valid_spaces) { /*const space = spaces.find(s => s && s.space_id === space_id); if (space) {*/ gen_action_infl(spaces[space_id].name_unique); //} } } else { view.prompt = 'Add influence: done.' gen_action('done') } }, infl(space) { vm_do_add_infl(space) }, done () { game.vm_event_done = true vm_next() } } states.vm_add_infl_free = { get inactive() { return `resolve ${clean_name(cards[this_card()].name)}: add influence.` }, prompt () { if (game.vm_available_ops > 0 && game.valid_spaces.length === 0 ) { view.prompt = 'No available spaces remaining. Add influence: done.' gen_action('done') } else if (game.vm_available_ops > 0 ) { view.prompt = `${clean_name(cards[this_card()].name)}: add ${game.vm_available_ops} influence to ${event_prompt()}.` for (let space_id of game.valid_spaces) { /*const space = spaces.find(s => s && s.space_id === space_id); if (space) {*/ gen_action_infl(spaces[space_id].name_unique); //} } } /* else { view.prompt = 'Add influence: done.' gen_action('done') } */ }, infl(space) { vm_do_add_infl_free(space) if (game.vm_available_ops === 0 ) { game.valid_spaces = [] game.vm_event_done = true vm_next() } }, done () { game.vm_event_done = true vm_next() } } states.vm_add_x_infl = { get inactive() { return `resolve ${clean_name(cards[this_card()].name)}: add influence.` }, // inactive: `resolve ${cards[this_card()].name}: add influence.`, prompt () { if (game.vm_available_ops > 0 ) { view.prompt = `${clean_name(cards[this_card()].name)}: Add ${game.vm_available_ops} influence to ${event_prompt()}.` for (let space_id of game.valid_spaces) { /*const space = spaces.find(s => s && s.space_id === space_id); if (space) {*/ gen_action_infl(spaces[space_id].name_unique); //} } } /*else { view.prompt = 'Add influence: done.' gen_action('done') }*/ }, infl(space) { vm_do_add_x_infl(space) game.vm_event_done = true vm_next() }, /*done () { game.vm_event_done = true vm_next() }*/ } states.vm_add_limited_infl = { get inactive() { return `resolve ${clean_name(cards[this_card()].name)}: add influence.` }, 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 ${game.vm_max_infl} influence ${event_prompt()}.` } else { view.prompt = `${clean_name(cards[this_card()].name)}: add ${game.vm_available_ops} influence to ${event_prompt()}.` } for (let space_id of game.valid_spaces) { /*const space = spaces.find(s => s && s.space_id === space_id); if (space) { */ gen_action_infl(spaces[space_id].name_unique); //} } } /*else { view.prompt = `${clean_name(cards[this_card()].name)}: 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.vm_event_done = true vm_next() } }, /*done () { game.vm_event_done = true vm_next() }*/ } states.vm_remove_infl = { inactive: 'remove influence.', prompt () { // Keep this so that there is an undo option in, e.g., Scare Tactics if (game.vm_available_ops === 0 || game.valid_spaces.length === 0) { view.prompt = `${clean_name(cards[this_card()].name)}. Remove influence: 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 ${game.vm_available_ops} SP${event_prompt()}.` } for (let space_id of game.valid_spaces) { /*const space = spaces.find(s => s && s.space_id === space_id); if (space) { */ gen_action_infl(spaces[space_id].name_unique); //} } }, infl(space) { push_undo() vm_do_remove_infl(space) const clicked_space = find_space_index(space) game.vm_active_country = spaces[clicked_space].country /*if (game.vm_available_ops === 0 || game.valid_spaces.length === 0) { vm_next() }*/ }, done() { 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) { view.prompt = `${clean_name(cards[this_card()].name)}: no influence to remove.` gen_action('done') } else { view.prompt = `${clean_name(cards[this_card()].name)}: remove ${game.vm_available_ops} SP from ${event_prompt()}.` for (let space_id of game.valid_spaces) { /*const space = spaces.find(s => s && s.space_id === space_id); if (space) { */ gen_action_infl(spaces[space_id].name_unique); //} } } /*else { view.prompt = 'Remove influence: done.' gen_action('done') }*/ }, infl(space) { vm_do_remove_x_infl(space) 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 ${game.vm_available_ops} SP${event_prompt()}, no more than ${game.vm_max_infl} per space.` for (let space_id of game.valid_spaces) { /*const space = spaces.find(s => s && s.space_id === space_id); if (space) { */ gen_action_infl(spaces[space_id].name_unique); //} } } else if (game.valid_spaces.length === 0) { view.prompt = `${clean_name(cards[this_card()].name)}: no further SP to remove.` gen_action('done') } }, infl(space) { vm_do_remove_limited_infl(space, game.vm_max_infl) if (game.vm_available_ops === 0) { game.vm_event_done = true vm_next() } }, done () { game.vm_event_done = true vm_next() } } states.vm_remove_all_infl = { inactive: 'remove influence', prompt () { if (game.valid_spaces.length === 0) { view.prompt = `${clean_name(cards[this_card()].name)}: no SP to remove.` gen_action('done') return } view.prompt = `${clean_name(cards[this_card()].name)}: remove all SPs from ${event_prompt()}.` for (let space_id of game.valid_spaces) { /*const space = spaces.find(s => s && s.space_id === space_id); if (space) {*/ gen_action_infl(spaces[space_id].name_unique); // } } }, infl(space) { vm_do_remove_all_infl(space) const clicked_space = find_space_index(space) game.vm_active_country = spaces[clicked_space].country if (game.vm_available_ops === 0 || game.valid_spaces.length === 0) { vm_next() } }, done() { vm_next() } } states.vm_support_check_prep = { inactive: 'do support checks.', prompt () { console.log('in states.vm_support_check_prep, game.vm_available_ops: ', game.vm_available_ops) 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(spaces[space_id].name_unique); } } }, sc(space) { push_undo() game.selected_space = find_space_index(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.played_card === 61 || game.vm_event === 61) { 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.vm_available_ops > 1) { console.log('in ahb check, country, ', spaces[game.selected_space].country, 'ahb', game.persistent_events['austria_hungary_border_reopened']) if (spaces[game.selected_space].country === 'East_Germany' && game.persistent_events['austria_hungary_border_reopened'] && 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 () { game.vm_available_ops = 0 vm_next () } } 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(spaces[space_id].name_unique); } } }, sc(space) { push_undo() game.selected_space = find_space_index(space) game.state = 'vm_do_support_check' }, done () { 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(spaces[game.selected_space].name_unique) game.vm_available_ops-- if (game.vm_available_ops === 0) { game.valid_spaces = [] } 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 = '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 ${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(`Rolled a ${roll}`) let worker_spaces = spaces.filter(space => space && space.country === 'Czechoslovakia' && space.socio === 4 && game.pieces[space.space_id].demCtrl === 1).length if (worker_spaces > 0) { log(`-${worker_spaces} from Democrat controlled worker spaces`) roll -= worker_spaces } if (roll > 2) { log('Adamec succeeds') vm_next() return } log('Adamec fails: modified 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() { game.vm_event = discard_card(game.democrat_hand) game.phase = 1 if (cards[game.vm_event].side === 'C') { game.return = game.active if (!auto_resolve_events.includes(game.vm_event) && !switch_events.includes(game.vm_event)) { next_player() } goto_vm(game.vm_event) } }, pass() { log('No cards to discard') vm_return() }, done() { vm_return() } } states.vm_central_committee_reshuffle = { get inactive() { return `resolve ${cards[57].name}.` }, prompt() { view.prompt = 'Choose a country to add SP.' if (!game.revolutions['East_Germany']) {gen_action('east_germany')} if (!game.revolutions['Poland']) {gen_action('poland')} if (!game.revolutions['Czechoslovakia']) {gen_action('czechoslovakia')} if (!game.revolutions['Hungary']) {gen_action('hungary')} if (!game.revolutions['Romania']) {gen_action('romania')} if (!game.revolutions['Bulgaria']) {gen_action('bulgaria')} }, east_germany() { 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() { 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() { 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() { 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() { 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.persistent_events['systematization']) vm_next() }, bulgaria () { 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() }, } states.vm_common_european_home = { get inactive() { return `resolve ${cards[game.played_card].name}.` }, prompt() { if (game.vm_event === 0) { 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) } } else { view.prompt = `Play ${clean_name(cards[game.vm_event].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') } } }, card(card) { push_undo() log(`Played with C${cards[card].number}`) game.valid_cards = [] silent_discard(card) game.vm_event = card }, influence(){ push_undo() game.vm_available_ops = cards[game.vm_event].ops valid_spaces_infl() game.state = 'vm_add_infl' }, support_check() { push_undo() game.vm_available_ops = 2 game.state = 'vm_support_check_prep' valid_spaces_sc() }, tst() { game.state = 'vm_tiananmen_square_attempt' } } states.vm_dash_for_the_west = { get inactive() { return `resolve ${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(`Rolled a ${roll}`) let com_control = check_presence('East_Germany').com_spaces if (roll > com_control) { log(`More than the ${com_control} Communist controlled spaces in East Germany`) log('+1 VP') game.vp++ check_vp() game.discard = true game.state = 'vm_play_event_from_discard' } else { log(`Fail: more than a ${com_control} required`) game.phase++ } clear_undo() }, done() { vm_next() } } states.vm_play_event_from_discard = { get inactive() { return `resolve ${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('done') } else if (game.temp === 0) { view.prompt = `${event_prompt()}.` for (let card of game.valid_cards) { 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 console.log('card:', card) if (switch_events.includes(card)) {next_player()} goto_vm(card) }, done(){ 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) { log(`Gave C${cards[card].number}`) game.valid_cards = [] silent_discard(card) next_player() game.state = 'vm_deutsche_marks' game.vm_event = card }, pass() { vm_next() } } states.vm_deutsche_marks = { get inactive() { return `resolve ${cards[20].name}.` }, prompt() { if(cards[game.vm_event].side === 'C' && game.playable_cards[game.vm_event].playable === 1) { 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() { log(`Played C${cards[game.vm_event].number} for the event`) game.return === game.active goto_vm(game.vm_event) }, influence() { push_undo() log(`Played C${cards[game.vm_event].number} for influence`) game.vm_available_ops = cards[game.vm_event].ops if (game.persistent_events['perestroika']) {game.vm_available_ops++ } 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 ${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) } gen_action('done') }, card(card){ push_undo() discard(card) game.temp++ }, done() { push_undo() game.state = 'vm_exit_visas_finish' } } states.vm_exit_visas_finish = { get inactive() { return `resolve ${cards[75].name}.` }, prompt() { if (game.temp > 0 ) { view.prompt = 'Draw replacement cards.' gen_action('draw') } else { view.prompt = 'Exit Visas: 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 }, done() { vm_next() } } states.vm_foreign_currency_debt_burden = { get inactive() { return `resolve ${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.persistent_events['foreign_currency_debt_burden'] = 'East_Germany' log('Selected East Germany') vm_next() }, poland() { push_undo() game.persistent_events['foreign_currency_debt_burden'] = 'Poland' log('Selected Poland') vm_next() }, czechoslovakia() { push_undo() game.persistent_events['foreign_currency_debt_burden'] = 'Czechoslovakia' log('Selected Czechoslovakia') vm_next() }, hungary() { push_undo() game.persistent_events['foreign_currency_debt_burden'] = 'Hungary' log('Selected Hungary') vm_next() }, bulgaria() { push_undo() game.persistent_events['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() { console.log('in vm_goodbye lenin') if (game.valid_cards.length > 0 ) { view.prompt = 'Choose a card to play for the event, 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 valid cards. 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() { 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 = cards[this_card()].ops if (game.persistent_events['sinatra_doctrine']) { log(`+1 from C50`) game.vm_available_ops++ } console.log('goodbye lenin: influence selected') valid_spaces_infl() game.state = 'vm_add_infl' }, support_check() { push_undo() game.vm_available_ops = 2 game.state = 'vm_support_check_prep' valid_spaces_sc() }, tst() { game.state = 'vm_tiananmen_square_attempt' } } states.vm_honecker = { get inactive() { return `resolve ${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('done') } 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) console.log('removed after honecker', game.strategy_removed) }, pass(){ log('Did not take a card') 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() { view.prompt = 'Inflationary Currency: choose a country where your opponent has power.' if (game.active === DEM) { if (!game.revolutions['East_Germany']) {gen_action('east_germany')} if (!game.revolutions['Poland']) {gen_action('poland')} if (!game.revolutions['Czechoslovakia']) {gen_action('czechoslovakia')} if (!game.revolutions['Hungary']) {gen_action('hungary')} if (!game.revolutions['Romania']) {gen_action('romania')} if (!game.revolutions['Bulgaria']) {gen_action('bulgaria')} } else { if (game.revolutions['East_Germany']) {gen_action('east_germany')} if (game.revolutions['Poland']) {gen_action('poland')} if (game.revolutions['Czechoslovakia']) {gen_action('czechoslovakia')} if (game.revolutions['Hungary']) {gen_action('hungary')} if (game.revolutions['Romania']) {gen_action('romania')} if (game.revolutions['Bulgaria']) {gen_action('bulgaria')} } }, 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() }, } states.vm_inflationary_currency_discard = { get inactive() { return `resolve ${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 = 'Discard a card: done.' gen_action('done') } }, card(card) { push_undo() discard(card) game.temp = card }, pass() { log('Did not discard') next_player() game.vm_available_ops = 1 vm_next() //game.state = 'vm_support_check_prep' }, done() { vm_next() } } states.vm_kiss_of_death = { get inactive() { return `resolve ${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() { game.vm_event = discard_card(game.communist_hand) next_player() game.state = 'vm_kiss_of_death_finish' }, pass() { log('No card to discard') vm_next() } } states.vm_kiss_of_death_finish = { get inactive() { return `resolve ${cards[game.played_card].name}.` }, prompt() { console.log('game.vm_event', game.vm_event) if (game.vm_event > 0 && (cards[game.vm_event].side === 'D' || cards[game.vm_event].side === 'N')) { view.prompt = `Play ${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 console.log('kiss of death event section, discard', game.strategy_discard) // Remove game.vm_event from the discard game.strategy_discard = game.strategy_discard.filter(n => n !== game.vm_event) console.log('kiss of death event section 2, discard', game.strategy_discard) goto_vm(game.vm_event) }, done() { vm_next() } } states.vm_kremlin_coup_take_control = { get inactive() { return `resolve ${cards[game.played_card].name}.` }, prompt() { if (game.valid_spaces.length === 0){ view.prompt = 'No spaces remaining. Kremlin Coup: done.' gen_action('done') } else { view.prompt = `Kremlin Coup: Take control of Elite spaces in countries where the Communist retains power.` for (let space_id of game.valid_spaces) { gen_action_infl(spaces[space_id].name_unique); } } }, infl(space) { vm_take_control(space) game.vm_active_country = spaces[find_space_index(space)].country console.log('space', find_space_index(space), 'country', game.vm_active_country) if (game.vm_active_country === 'East_Germany') {game.temp = 3 } if (game.vm_active_country === 'Poland') {game.temp = 17} if (game.vm_active_country === 'Czechoslovakia') {game.temp = 29} if (game.vm_active_country === 'Hungary') {game.temp = 45} if (game.vm_active_country === 'Romania') {game.temp = 61} if (game.vm_active_country === 'Bulgaria') {game.temp = 68} game.valid_spaces.push(game.temp) game.state = 'vm_kremlin_coup_sc_prep' }, done() { vm_next() } } states.vm_kremlin_coup_sc_prep = { get inactive() { return `resolve ${cards[game.played_card].name}.` }, prompt() { view.prompt = `Conduct a support check in ${game.vm_active_country}'s Bureaucratic space.` gen_action_sc(spaces[game.temp].name_unique); }, sc(space) { game.selected_space = find_space_index(space) 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(spaces[game.selected_space].name_unique) game.state = 'vm_kremlin_coup_take_control' return } } 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() if (game.persistent_events['sinatra_doctrine']) { log(`+1 op from C50`) game.vm_available_ops = 3 } else { game.vm_available_ops = 2 } 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 ${cards[game.played_card].name}.` }, prompt() { 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) { /*const space = spaces.find(s => s && s.space_id === space_id); if (space) { */ gen_action_infl(spaces[space_id].name_unique); //} } } /*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() }, /*done() { vm_next() }*/ } states.vm_malta_summit = { get inactive() { return `resolve ${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(`Rolled a ${roll}`) if (game.stability > 0) { log(`+${game.stability} from USSR Stability Track`) } if (roll + game.stability > 3) { log('Summit successful') game.vp += 3 log('+3 VP') check_vp() if (game.pieces[12].comInfl > 0 ) {game.valid_spaces.push(12)} if (game.pieces[15].comInfl > 0 ) {game.valid_spaces.push(15)} if (game.pieces[27].comInfl > 0 ) {game.valid_spaces.push(27)} if (game.pieces[43].comInfl > 0 ) {game.valid_spaces.push(43)} if (game.pieces[51].comInfl > 0 ) {game.valid_spaces.push(51)} if (game.pieces[69].comInfl > 0 ) {game.valid_spaces.push(69)} //game.vm_available_ops = 5 game.remove_opponent_infl = true vm_next() } else { log('Summit failed') //game.phase++ vm_goto_step(vm_permanently_remove) } }, /*done() { vm_next() }*/ } states.vm_modrow = { get inactive() { return `resolve ${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' && game.pieces[space.space_id].demCtrl === 1).length if (roll > dem_spaces) { log(`Rolled a ${roll}: success`) vm_next() } else { log(`Rolled a ${roll}`) log(`Fail. More than ${dem_spaces} required`) permanently_remove(83) vm_return() } } } states.vm_nepotism = { get inactive() { return `resolve ${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(`Rolled a ${roll}: adds 4 influence`) game.vm_available_ops = 4} else if (roll < 5 ) { log(`Rolled a ${roll}: adds 3 influence`) game.vm_available_ops = 3} else { log(`Rolled a ${roll}: adds 1 influence`) game.vm_available_ops = 1} //game.phase = 2 vm_next() }, /*done() { vm_next() }*/ } states.vm_new_years_eve_party = { get inactive() { return `resolve ${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['new_years_eve_party'] = 1 log('Chooses to end the game. There will be no final scoring') let power = Object.values(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 } check_vp() game.table_cards.push(104) vm_next() }, continue() { log('Chooses to continue') permanently_remove(104) vm_next() } } states.vm_nomenklatura = { get inactive() { return `resolve ${cards[game.played_card].name}.` }, prompt() { view.prompt = 'Nomenklatura: choose to remove all Democratic influence from Elite spaces or add 3 influence to any Elite space(s).' gen_action('remove') gen_action('add') }, remove() { push_undo() game.valid_spaces = [] for (let i = 1; i < game.pieces.length; i++) { let piece = game.pieces[i] let space = spaces[i] if (space.socio === 1 && piece.demInfl > 0) { game.valid_spaces.push(piece.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) } } game.vm_available_ops = 3 game.state = 'vm_nomenklatura_add' } } states.vm_nomenklatura_remove = { get inactive() { return `resolve ${cards[game.played_card].name}.` }, prompt() { if (game.vm_available_ops === 0 || game.valid_spaces.length === 0 ) { view.prompt = 'Remove influence: done.' gen_action('done') } else { view.prompt = 'Nomenklatura: remove all Democratic influence from Elite spaces.' for (let space_id of game.valid_spaces) { /*const space = spaces.find(s => s && s.space_id === space_id); */ gen_action_infl(spaces[space_id].name_unique); } } }, infl(space) { push_undo() vm_do_remove_all_infl(space) if (game.vm_available_ops === 0) { vm_next() } }, done() { vm_next() } } states.vm_nomenklatura_add = { get inactive() { return `resolve ${cards[game.played_card].name}.` }, prompt() { if (game.vm_available_ops === 0 || game.valid_spaces.length === 0 ) { view.prompt = 'Add influence: done.' gen_action('done') } else { view.prompt = `Nomenklatura: add 3 influence to any Elite space(s). ${game.vm_available_ops} influence remaining.` for (let space_id of game.valid_spaces) { gen_action_infl(spaces[space_id].name_unique); } } }, infl(space) { push_undo() vm_do_add_infl_free(space) if (game.vm_available_ops === 0 ) {game.valid_spaces = []} }, done() { vm_next() } } states.vm_samizdat = { get inactive() { return `resolve ${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('done') }, card(card) { push_undo() game.samizdat_card = card game.democrat_hand = game.democrat_hand.filter(c => c !== card) log('Set aside a card') }, done() { if (game.samizdat_card > 0) {game.state = 'vm_samizdat_finish'} else {vm_next()} } } states.vm_samizdat_finish = { get inactive() { return `resolve ${cards[game.played_card].name}.` }, prompt() { if (game.phase === 2) { 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)) game.phase ++ }, done() { vm_next() } } states.vm_shock_therapy = { get inactive() { return `resolve ${cards[game.played_card].name}.` }, prompt() { if (game.vm_active_country === '' ) { view.prompt = 'Shock Therapy: choose a country where you hold Power:' if (game.revolutions['East_Germany']) {gen_action('east_germany')} if (game.revolutions['Poland']) {gen_action('poland')} if (game.revolutions['Czechoslovakia']) {gen_action('czechoslovakia')} if (game.revolutions['Hungary']) {gen_action('hungary')} if (game.revolutions['Romania']) {gen_action('romania')} if (game.revolutions['Bulgaria']) {gen_action('bulgaria')} } 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 for (let space of game.pieces) { if (space && spaces[space.space_id].country === game.vm_active_country && space.comCtrl === 1 && (spaces[space.space_id].socio === 3 || spaces[space.space_id].socio === 4)) { game.temp++ } } log(`Rolled a ${roll}`) log(`-${game.temp} from Communist controlled Worker and Farmer spaces`) log(`Modified roll: ${roll - game.temp}`) if ((roll - game.temp) > 2) { log('C93 is successful. +3 VP') vm_next() } else { log('C93 is unsuccessful. Required 3 or more') game.phase++ } }, done() { permanently_remove(93) vm_return() } } states.vm_social_democratic_platform_adopted = { get inactive() { return `resolve ${cards[game.played_card].name}.` }, prompt() { view.prompt = 'Select a country where the Democrat holds Power.' if (game.revolutions['East_Germany']) {gen_action('east_germany')} if (game.revolutions['Poland']) {gen_action('poland')} if (game.revolutions['Czechoslovakia']) {gen_action('czechoslovakia')} if (game.revolutions['Hungary']) {gen_action('hungary')} if (game.revolutions['Romania']) {gen_action('romania')} if (game.revolutions['Bulgaria']) {gen_action('bulgaria')} }, 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()} } states.vm_systematization = { get inactive() { return `resolve ${cards[game.played_card].name}.` }, prompt() { if (game.persistent_events['systematization'] === 0) { view.prompt = 'Systematization: eliminate a space in Romania.' for (let space_id of game.valid_spaces) { gen_action_infl(spaces[space_id].name_unique); } } else { view.prompt = 'Systematization: done.' gen_action('done') } }, infl(space) { push_undo() vm_eliminate(find_space_index(space)) game.valid_spaces = [] game.persistent_events['systematization'] = find_space_index(space) }, done() { vm_next() } } states.vm_the_chinese_solution = { get inactive() { return `resolve ${cards[game.played_card].name}.` }, prompt() { view.prompt = 'You may give up 3 VP to conduct support checks in a country where you hold power.' if (!game.revolutions['East_Germany']) {gen_action('east_germany')} if (!game.revolutions['Poland']) {gen_action('poland')} if (!game.revolutions['Czechoslovakia']) {gen_action('czechoslovakia')} if (!game.revolutions['Hungary']) {gen_action('hungary')} if (!game.revolutions['Romania']) {gen_action('romania')} if (!game.revolutions['Bulgaria']) {gen_action('bulgaria')} 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 check_vp() vm_next() }, poland() { push_undo() game.vm_active_country = 'Poland' log(`Chose ${country_name(game.vm_active_country)}`) log('+3 VP') game.vp += 3 check_vp() vm_next() }, czechoslovakia() { push_undo() game.vm_active_country = 'Czechoslovakia' log(`Chose ${country_name(game.vm_active_country)}`) log('+3 VP') game.vp += 3 check_vp() vm_next() }, hungary() { push_undo() game.vm_active_country = 'Hungary' log(`Chose ${country_name(game.vm_active_country)}`) log('+3 VP') game.vp += 3 check_vp() vm_next() }, romania() { push_undo() game.vm_active_country = 'Romania' log(`Chose ${country_name(game.vm_active_country)}`) log('+3 VP') game.vp += 3 check_vp() vm_next() }, bulgaria () { push_undo() game.vm_active_country = 'Bulgaria' log(`Chose ${country_name(game.vm_active_country)}`) log('+3 VP') game.vp += 3 check_vp() vm_next() }, pass() { permanently_remove(96) vm_return() } } states.vm_the_tyrant_is_gone = { get inactive() { return `resolve ${cards[game.played_card].name}.` }, prompt() { if (game.persistent_events['the_tyrant_is_gone']=== 0) { 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(spaces[space_id].name_unique); } } else { view.prompt = 'Select a space: done.' gen_action('done') } }, infl(space) { push_undo() log(`The Ceausescus flee to %${find_space_index(space)}`) game.persistent_events['the_tyrant_is_gone'] = find_space_index(space) }, done () { 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! 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(`Rolled a ${roll}`) if (game.active === DEM) { let controlled_spaces = spaces.filter(space => space && space.country === 'East_Germany' && game.pieces[space.space_id].demCtrl === 1).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' && game.pieces[space.space_id].comCtrl === 1).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') return } if (game.the_wall_must_go['com_wins'] === 2) { log('The Communist wins C86') 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['the_wall_must_go'] = true log('+3 VP') game.vp += 3 check_vp() for (let space of game.pieces) { if (space) {console.log('space.space_id', space.space_id)} if (space && spaces[space.space_id].country === 'East_Germany' && space.comInfl > 0){ game.valid_spaces.push(space.space_id) } } if (game.active === DEM) {next_player()} vm_next () } else { permanently_remove(86) vm_return() } } } states.vm_warsaw_pact_summit = { get inactive() { return `resolve ${cards[game.played_card].name}.` }, prompt() { view.prompt = 'Choose to play for support checks or influence.' gen_action('influence') gen_action('support_check') }, influence(){ push_undo() for (let space of game.pieces) { if (space && space.demInfl === 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 < game.pieces.length; i++) { let gamePiece = game.pieces[i] let space = spaces[i] if (gamePiece.demInfl > 0 && (space.socio === 5 || space.socio === 6)) { game.valid_spaces.push(gamePiece.space_id) } } game.vm_available_ops = 2 //game.state = 'vm_support_check_prep' console.log('game.phase',game.phase) vm_next() } } states.vm_we_are_the_people_remove = { get inactive() { return `resolve ${cards[game.played_card].name}.` }, prompt() { if (game.pieces[6].demInfl === 0) { view.prompt = '"We are the People!": no influence to remove.' gen_action('done') } else if (game.vm_available_ops > 0 ) { view.prompt = '"We are the People!": remove up to 4 influence from the Lutherian Church.' gen_action('done') for (let space_id of game.valid_spaces) { gen_action_infl(spaces[space_id].name_unique); } } else { view.prompt = 'Remove influence: done.' gen_action('done') } }, infl(space) { vm_do_remove_infl(space) }, done() { if (!game.vm_influence_added[6]) { log('No influence 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 ${cards[game.played_card].name}.` }, prompt() { if (!game.vm_influence_added[6]) { view.prompt = '"We are the People!": done.' gen_action('done') return } view.prompt = `"We are the People!": you must add the ${game.vm_influence_added[6]} influence to spaces in Germany.` gen_action('done') for (let space_id of game.valid_spaces) { /*const space = spaces.find(s => s && s.space_id === space_id);*/ gen_action_infl(spaces[space_id].name_unique); } }, infl(space) { push_undo() vm_do_add_infl_free(space) game.vm_influence_added[6]-- if (game.vm_influence_added[6] === 0 ) {game.valid_spaces = []} }, done() { vm_next() } } states.vm_workers_revolt = { get inactive() { return `resolve ${cards[game.played_card].name}.` }, prompt() { view.prompt = 'Workers Revolt: select a Worker Space in a country your opponent has power.' for (let space_id of game.valid_spaces) { /*const space = spaces.find(s => s && s.space_id === space_id); if (space) {*/ gen_action_infl(spaces[space_id].name_unique); //} } }, infl(space) { game.temp = find_space_index(space) log(`Chose %${game.temp}`) game.state = 'vm_workers_revolt_finish' } } states.vm_workers_revolt_finish = { get inactive() { return `resolve ${cards[game.played_card].name}.` }, prompt() { if (game.temp > 0) { view.prompt = `Target: ${spaces[game.temp].name}. 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(`Rolled a ${roll}`) let adj = count_adj(spaces[game.temp].name_unique) 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 } if (roll >= 4) { log('Workers Revolt successful') vm_replace_all_infl(game.temp) } else {log('Workers Revolt fails')} game.temp = 0 }, 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 = [] } }, done() { vm_next() } } states.vm_tst_4 = { inactive: 'remove influence', prompt () { if (game.vm_available_ops === 0 || game.valid_spaces.length === 0) { view.prompt = 'Remove influence: done.' gen_action('done') return } view.prompt = 'Tiananmen Square Track award: select a space to remove influence' for (let space_id of game.valid_spaces) { /*const space = spaces.find(s => s && s.space_id === space_id); if (space) {*/ gen_action_infl(spaces[space_id].name_unique); // } } }, infl(space) { vm_do_remove_infl(space) }, done() { 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(spaces[space_id].name_unique); } } } }, sc(space) { push_undo() console.log('in vm_valid_spaces_sc: game.persistent_events[we_are_the_people]', game.persistent_events['we_are_the_people']) game.selected_space = find_space_index(space) if (game.active === DEM && game.persistent_events['austria_hungary_border_reopened'] && spaces[space].country === "East_Germany") { game.austria_hungary_border_reopened_tracker = true } game.state = 'vm_tst_6_sc' }, done () { vm_next() } } /* states.vm_tst_6_prep = { 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 = `Select a space for the support check.` for (let space_id of game.valid_spaces) { if (space_id) { gen_action_sc(spaces[space_id].name_unique); } } } }, sc(space) { push_undo() game.selected_space = find_space_index(space) game.state = 'vm_tst_6_sc' }, done () { 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(spaces[game.selected_space].name_unique) game.vm_available_ops-- game.state = 'vm_tst_6' 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('done') } }, event() { game.vm_event_to_do = false game.return_state = 'vm_tst_8' game.return = game.active goto_vm(game.played_card) }, ops() { game.vm_infl_to_do = false game.return = game.active game.return_state = 'vm_tst_8' goto_vm(208) }, done() { game.tst_8 = true end_round() } } states.vm_tst_8_ops = { inactive: 'play card for operations.', prompt() { view.prompt = `Play ${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() game.state = 'vm_add_infl' }, support_check() { push_undo() game.vm_available_ops = 2 game.state = 'vm_support_check_prep' }, tst() { game.state = 'vm_tiananmen_square_attempt' } } // ========================= POWER STRUGGLE STATES ======================== states.vm_support_surges = { inactive: 'draw cards.', prompt() { view.prompt = 'Support Surges: draw 2 cards.' 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+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 log('Drew 2 cards') log('Surrenders initiative') vm_next() } } states.vm_support_falters = { inactive: 'discard cards.', prompt() { 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() { console.log('game.com_pwr_hand', game.com_pwr_hand) if (game.active === DEM) {discard_card(game.dem_pwr_hand)} else {discard_card(game.com_pwr_hand)} game.vm_available_ops -- }, done() { log_msg_gap('Takes initiative') game.return = game.active vm_next() } } /* =================== EVENTS ================================ */ // #region GENERATED EVENT CODE const CODE = [] CODE[1] = [ // Legacy of Martial Law* [ 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_permanently_remove ], [ vm_return ], ] CODE[2] = [ // Solidarity Legalised* [ 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_permanently_remove ], [ vm_return ], ] CODE[3] = [ // Walesa [ 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_permanently_remove ], [ vm_return ], ] CODE[4] = [ // Michnik [ vm_valid_spaces, 26 ], [ vm_prompt, 'the Polish Intellectuals space' ], [ vm_add_x_infl, 3 ], [ vm_permanently_remove ], [ 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_valid_spaces_opponent ], [ vm_remove_limited_opp_infl, 4, 2 ], [ vm_permanently_remove ], [ vm_return ], ] CODE[8] = [ // Prudence [ vm_prudence ], [ vm_return ], ] CODE[9] = [ // The Wall* [ vm_the_wall ], [ vm_permanently_remove ], [ vm_return ], ] CODE[10] = [ // Cult of Personality [ 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_permanently_remove ], [ 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_valid_spaces_socio, 2 ], [ vm_prompt, ' to any Bureaucratic space(s)' ], [ vm_add_infl_free, 3 ], [ vm_permanently_remove ], [ vm_return ], ] CODE[13] = [ // Stasi [ vm_stasi ], [ vm_permanently_remove ], [ 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_honecker ], [ vm_permanently_remove ], [ vm_return ], ] CODE[16] = [ // Nomenklatura* [ vm_nomenklatura ], [ vm_permanently_remove ], [ vm_return ], ] CODE[17] = [ // Roundtable talks [ vm_roundtable_talks ], [ vm_return ], ] CODE[18] = [ // Poszgay Defends the Revolution [ vm_poszgay ], [ vm_prompt, 'to 4 spaces in Hungary not under Democratic control' ], [ vm_add_limited_infl, 4, 1 ], [ vm_permanently_remove ], [ vm_return ], ] CODE[19] = [ // Papal vist [ vm_valid_spaces, 20, 35, 38 ], [ vm_prompt, 'any Catholic Church space' ], [ vm_add_x_infl, 3 ], [ vm_permanently_remove ], [ vm_return ], ] CODE[20] = [ // Deutsche Marks* [ vm_deutsche_marks ], [ vm_permanently_remove ], [ 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_valid_spaces, 6 ], [ vm_prompt, 'the Lutheran Church' ], [ vm_take_control_prep, 1 ], [ vm_st_nicholas_church ], [ vm_return ], ] CODE[25] = [ // Perestroika [ vm_perestroika ], [ vm_return ], ] CODE[26] = [ // Helsinki Final Act* [ vm_helsinki_final_act ], [ vm_permanently_remove ], [ 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_valid_spaces, 30 ], [ vm_prompt, 'the Charles University space' ], [ vm_add_x_infl, 6 ], [ vm_permanently_remove ], [ 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_valid_spaces_socio, 3 ], [ vm_prompt, 'Farmer spaces, no more than 2 per space' ], [ vm_add_limited_infl, 4, 2 ], [ vm_permanently_remove ], [ vm_return ], ] CODE[33] = [ // Sajudis* [ vm_valid_spaces, 56, 70 ], [ vm_prompt, 'any Minorities space' ], [ vm_take_control_prep, 1 ], [ vm_sajudis ], [ vm_permanently_remove ], [ vm_return ], ] CODE[34] = [ // Fidesz* [ vm_valid_spaces, 47 ], [ vm_prompt, 'the Hungary students space' ], [ vm_add_x_infl, 5 ], [ vm_permanently_remove ], [ vm_return ], ] CODE[35] = [ // Heal our Bleeding Wounds* [ vm_heal_our_bleeding_wounds ], [ vm_permanently_remove ], [ vm_return ], ] CODE[36] = [ // Dash for the West* [ vm_permanently_remove ], [ vm_dash_for_the_west ], [ vm_return ], ] CODE[37] = [ // Nagy Reburied* [ vm_valid_spaces, 43 ], [ 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_permanently_remove ], [ vm_return ], ] CODE[38] = [ // July Concept [ vm_valid_spaces_country, 'Bulgaria' ], [ vm_prompt, 'Bulgaria' ], [ vm_add_infl_free, 3 ], [ vm_permanently_remove ], [ vm_return ], ] CODE[39] = [ // Eco-Glasnost* [ vm_valid_spaces, 66 ], [ vm_prompt, 'Ruse' ], [ vm_add_x_infl, 4 ], [ vm_eco_glasnost ], [ vm_return ], ] CODE[40] = [ // Hungarian Democratic Forum [ 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_permanently_remove ], [ vm_return ], ] CODE[41] = [ // Ceausescu* [ vm_valid_spaces_country_sc, '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_permanently_remove ], [ 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_inflationary_currency ], [ vm_valid_spaces_country_sc ], [ 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_permanently_remove ], [ vm_return ], ] CODE[45] = [ // Soviet Troop Withdrawals* [ vm_valid_spaces_region_opp, 'Eastern Europe' ], [ vm_prompt, ' from Eastern Europe' ], [ vm_remove_limited_opp_infl, 5, 2 ], [ vm_permanently_remove ], [ vm_return ], ] CODE[46] = [ // Goodbye Lenin!* [ vm_goodbye_lenin ], [ vm_permanently_remove ], [ vm_return ], ] CODE[47] = [ // Bulgarian Turks Expelled* [ vm_bulgarian_turks_expelled ], [ vm_prompt, 'Razgrad' ], [ vm_remove_all_infl, 1 ], [ vm_permanently_remove ], [ vm_return ], ] CODE[48] = [ // We are the People!* [ vm_we_are_the_people ], [ vm_permanently_remove ], [ vm_return ], ] CODE[49] = [ // Foreign Currency Debt Burden* [ vm_foreign_currency_debt_burden ], [ vm_return ], ] CODE[50] = [ // The Sinatra Doctrine* [ vm_the_sinatra_doctrine ], [ vm_permanently_remove ], [ vm_return ], ] CODE[51] = [ // 40th Anniversary Celebration* [ vm_40th_anniversary_celebration ], [ vm_valid_spaces_country, 'East_Germany' ], [ vm_prompt, 'East Germany' ], [ vm_add_infl_free ], [ vm_40th_anniversary_celebration_vp ], [ vm_permanently_remove ], [ vm_return ], ] CODE[52] = [ // Normalisation [ vm_normalisation ], [ vm_prompt, 'the Czechoslovakia Elite and Bureaucrat Spaces' ], [ vm_remove_all_infl, 2 ], [ vm_permanently_remove ], [ vm_return ], ] CODE[53] = [ // Li Peng* [ 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_foreign_television ], [ vm_remove_limited_opp_infl, 4, 2 ], [ vm_permanently_remove ], [ vm_return ], ] CODE[57] = [ // Central Committee Reshuffle* [ vm_central_committee_reshuffle ], [ vm_prompt, ()=>`${country_name(game.vm_active_country)}` ], [ vm_add_infl_free, 3 ], [ vm_permanently_remove ], [ 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_valid_spaces_socio, 4 ], [ vm_prompt, 'any Worker space(s)' ], [ vm_add_infl_free, 3 ], [ vm_permanently_remove ], [ vm_return ], ] CODE[61] = [ // The Monday Demonstrations* [ 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_permanently_remove ], [ 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_legacy_of_1968 ], [ vm_prompt, 'all spaces in Czechoslovakia not controlled by the Communist Player' ], [ vm_add_limited_infl, 11, 1 ], [ vm_permanently_remove ], [ vm_return ], ] CODE[65] = [ // Presidential Visit* [ vm_presidential_visit ], [ vm_return ], ] CODE[66] = [ // New Forum [ vm_valid_spaces_country, 'East_Germany' ], [ vm_prompt, '3 spaces in East Germany' ], [ vm_add_limited_infl, 3, 1 ], [ vm_permanently_remove ], [ vm_return ], ] CODE[67] = [ // Reformer Rehabilitated* [ vm_prompt, 'Chose any non-scoring card in the discard pile. Event takes place immediately' ], [ vm_reformer_rehabilitated ], [ vm_return ], ] CODE[68] = [ // Klaus and Komarek* [ vm_klaus_and_komarek ], [ vm_prompt, 'Prague' ], [ vm_remove_x_opp_infl, 2 ], [ vm_valid_spaces, 29 ], [ vm_add_x_infl, 2 ], [ vm_permanently_remove ], [ vm_return ], ] CODE[69] = [ // Systematization* [ vm_valid_spaces_country, 'Romania' ], [ vm_systematization ], [ vm_permanently_remove ], [ 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_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_permanently_remove ], [ vm_return ], ] CODE[74] = [ // FRG Embassies [ vm_frg_embassies ], [ vm_return ], ] CODE[75] = [ // Exit Visas* [ vm_exit_visas ], [ vm_permanently_remove ], [ vm_return ], ] CODE[76] = [ // Warsaw Pact Summit [ vm_warsaw_pact_summit ], [ vm_if, ()=>game.phase === 3 ], [ vm_prompt, ' spaces with no Democratic influence' ], [ 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_permanently_remove ], [ vm_return ], ] CODE[77] = [ // Samizdat [ vm_samizdat ], [ vm_permanently_remove ], [ vm_return ], ] CODE[78] = [ // Workers Revolt [ vm_workers_revolt ], [ vm_return ], ] CODE[79] = [ // The Third Way* [ vm_the_third_way ], [ vm_valid_spaces, 4 ], [ vm_prompt, 'the East German Writers space' ], [ vm_add_x_infl, 3 ], [ vm_permanently_remove ], [ vm_return ], ] CODE[80] = [ // Nepotism* [ vm_nepotism ], [ vm_valid_spaces_region_socio, 'Balkans', 4 ], [ vm_prompt, 'Worker spaces in the Balkans' ], [ vm_add_infl_free ], [ vm_permanently_remove ], [ vm_return ], ] CODE[81] = [ // The Baltic Way* [ vm_the_baltic_way ], [ vm_prompt, 'any Minorities space' ], [ vm_take_control_prep, 1 ], [ vm_permanently_remove ], [ vm_return ], ] CODE[82] = [ // Spitzel* [ vm_valid_spaces_country_sc, 'East_Germany' ], [ vm_prompt, ' from East Germany' ], [ vm_remove_opp_infl, 2 ], [ vm_permanently_remove ], [ vm_return ], ] CODE[83] = [ // Modrow* [ vm_modrow ], [ vm_valid_spaces_country, 'East_Germany' ], [ vm_prompt, 'East Germany' ], [ vm_add_limited_infl, 4, 2 ], [ vm_permanently_remove ], [ vm_return ], ] CODE[84] = [ // Breakaway Baltic Republics* [ 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_permanently_remove ], [ vm_return ], ] CODE[85] = [ // Tank Column/Tank Man* [ vm_tank_column ], [ vm_permanently_remove ], [ vm_return ], ] CODE[86] = [ // The Wall Must Go!* [ vm_the_wall_must_go ], [ vm_remove_infl, 3 ], [ vm_permanently_remove ], [ vm_return ], ] CODE[87] = [ // Kohl Proposes Reunification* [ vm_kohl_proposes_reunification ], [ vm_permanently_remove ], [ vm_return ], ] CODE[88] = [ // Adamec* [ vm_adamec ], [ vm_valid_spaces_country, 'Czechoslovakia' ], [ vm_prompt, 'Czechoslovakia' ], [ vm_add_limited_infl, 4, 2 ], [ vm_permanently_remove ], [ vm_return ], ] CODE[89] = [ // Domino Theory* [ vm_prompt, 'Choose a Power Struggle card to play from the discard pile.' ], [ vm_domino_theory ], [ vm_permanently_remove ], [ vm_return ], ] CODE[90] = [ // Civic Forum* [ 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_permanently_remove ], [ vm_return ], ] CODE[91] = [ // My First Banana* [ 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_permanently_remove ], [ vm_return ], ] CODE[92] = [ // Betrayal [ vm_prompt, 'choose any Orthodox Church space. Replace all Democratic SPs with Communist SPs' ], [ vm_betrayal ], [ vm_permanently_remove ], [ vm_return ], ] CODE[93] = [ // Shock Therapy* [ vm_shock_therapy ], [ vm_valid_spaces_country ], [ vm_prompt, ()=>` ${country_name(game.vm_active_country)}` ], [ vm_add_infl_free, 3 ], [ vm_permanently_remove ], [ vm_return ], ] CODE[94] = [ // Union of Democratic Forces* [ vm_valid_spaces_country_sc, '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_permanently_remove ], [ vm_return ], ] CODE[95] = [ // Power Struggle - Romania [ vm_power_struggle ], [ vm_return ], ] CODE[96] = [ // The Chinese Solution* [ 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_permanently_remove ], [ vm_return ], ] CODE[97] = [ // The Tyrant is Gone* [ vm_if, ()=>game.persistent_events['the_crowd_turns_against_ceausescu'] ], [ 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_valid_spaces_country_sc, '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_permanently_remove ], [ vm_return ], ] CODE[99] = [ // Ligachev* [ vm_ligachev ], [ vm_permanently_remove ], [ vm_return ], ] CODE[100] = [ // Stand Fast* [ vm_stand_fast ], [ vm_permanently_remove ], [ vm_return ], ] CODE[101] = [ // Elena* [ vm_valid_spaces, 51 ], [ vm_prompt, 'the Romania Elite Space' ], [ vm_add_x_infl, 2 ], [ vm_elena ], [ 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_valid_spaces, 36, 37 ], [ vm_prompt, 'Kosice and Presov' ], [ vm_add_x_infl, 2 ], [ vm_valid_spaces, 36, 37 ], [ vm_add_x_infl, 2 ], [ vm_public_against_violence ], [ vm_prompt, 'Make a Support Check in Bratislava' ], [ vm_support_check_modified, 1, 2 ], [ vm_permanently_remove ], [ vm_return ], ] CODE[106] = [ // Social Democratic Platform Adopted* [ vm_social_democratic_platform_adopted ], [ vm_valid_spaces_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_permanently_remove ], [ vm_return ], ] CODE[107] = [ // Massacre in Timisoara* [ vm_valid_spaces_country_sc, 'Romania' ], [ vm_prompt, 'Make Support Checks in Romania' ], [ vm_support_check_modified, 2, 2 ], [ vm_permanently_remove ], [ vm_return ], ] CODE[108] = [ // Army Backs Revolution* [ vm_army_backs_revolution ], [ vm_permanently_remove ], [ vm_return ], ] CODE[109] = [ // Kremlin Coup* [ vm_kremlin_coup ], [ vm_prompt, 'Elite spaces in all countries where the Communist retains Power' ], [ vm_take_control_prep, 6 ], [ vm_permanently_remove ], [ vm_return ], ] CODE[110] = [ // Malta Summit* [ vm_malta_summit ], [ vm_prompt, ' from Elite spaces' ], [ vm_remove_opp_infl, 5 ], [ vm_permanently_remove ], [ 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_sc], [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] ]