diff options
Diffstat (limited to 'rules.ts')
-rw-r--r-- | rules.ts | 122 |
1 files changed, 50 insertions, 72 deletions
@@ -68,6 +68,7 @@ import data, { ARAGON, FASCIST_ID, NORTHERN, + MOMENTUM, } from './data'; const OBSERVER = 'Observer'; @@ -263,14 +264,14 @@ function setup_final_bid() { next(); } -function setup_player_turn() { +function setup_player_turn(faction_id: FactionId) { game.fascist = 0; game.card_played = 0; const next_faction = game.first_player === null ? get_player_order()[0] - : get_next_faction_in_player_order(get_active_faction()); + : faction_id; if (game.first_player === null) { game.first_player = next_faction; @@ -279,7 +280,6 @@ function setup_player_turn() { game.engine = [ create_function_node('start_of_player_turn', { f: next_faction }), create_state_node('player_turn', next_faction), - create_function_node('end_of_player_turn', { f: next_faction }), ]; next(); @@ -301,14 +301,15 @@ function check_end_of_year_discard() { function end_of_player_turn() { const { f: faction } = get_active_node_args(); - if (get_next_faction_in_player_order(faction) === game.first_player) { + const next_faction = get_next_faction_in_player_order(faction); + if (next_faction === game.first_player) { game.engine = [ create_state_node('change_active_player', game.initiative), create_function_node('resolve_fascist_test'), create_function_node('setup_bag_of_glory'), ]; } else { - game.engine = [create_function_node('setup_player_turn')]; + game.engine = [create_function_node('setup_player_turn', next_faction)]; } next(); } @@ -629,6 +630,7 @@ export function setup(seed: number, _scenario: string, options: Record<string,bo hero_points: [2, 2, 0, 14], initiative: MODERATES_ID, medallions: [[],[],[],[]], + momentum: null, played_card: null, player_order: [MODERATE], selected_cards: [ @@ -1228,7 +1230,7 @@ states.play_card = { }, card(c: CardId) { const faction = get_active_faction(); - game.selected_cards[faction] = [c]; + game.selected_cards[faction].push(c); game.card_played = 0; // NOTE: I don't think we are using game.played_card in the UI at the moment? @@ -1314,43 +1316,17 @@ states.choose_final_bid = { function setup_momentum() { const faction = get_active_faction(); - // Player received medallion outside of their normal turn - // and must be resolved - if (game.faction_turn !== faction) { - insert_after_active_node( - resolve_effect(create_effect('play_card', faction, 1), 'momentum') - ); - return; - } - - // Player gets medallion during their turn. Need to check if it can be player - // right away or not. Depends on whether card for this turn has been fully resolved or not - - // Get player turn node - const node: StateNode<PlayerTurnArgs> = get_nodes_for_state('player_turn')[0]; - - const player_needs_to_play_card = !game.card_played; - const { use_ap, use_morale_bonus, resolving_event } = - node.a ?? ({} as PlayerTurnArgs); + game.momentum = faction; - if ( - player_needs_to_play_card || - use_ap || - use_morale_bonus || - resolving_event - ) { - // Player hasn't fully resolved this turns card. Update args to enable button - node.a = { - ...(node.a || {}), - use_momentum: true, - }; + const momentum_nodes = resolve_effect(create_effect('play_card', faction, 1), MOMENTUM); + if (game.faction_turn !== null) { + // Player received medallion during a player turn, either their own or another players. + // Push to end of the engine so it's resolved after current turn ends + game.engine.push(momentum_nodes); + return; } else { - // Player can resolve choosing a new card - insert_after_active_node( - create_state_node<PlayCardArgs>('play_card', faction, { - src: 'momentum', - }) - ); + // Insert right after current node + insert_after_active_node(momentum_nodes) } } @@ -1863,7 +1839,7 @@ states.player_turn = { prompt() { gen_spend_hero_points(); const faction_id = get_active_faction(); - let { use_ap, use_morale_bonus, use_momentum } = + let { use_ap, use_morale_bonus, src } = get_active_node_args<PlayerTurnArgs>(); use_morale_bonus = use_morale_bonus && game.bonuses[MORALE_BONUS] === ON; @@ -1872,6 +1848,7 @@ states.player_turn = { game.faction_turn === faction_id && game.hero_points[faction_id] > 0; const can_play_card = !game.card_played; + const use_momentum = game.momentum === faction_id && src !== MOMENTUM; if (use_momentum) { gen_action('use_momentum'); if (use_ap || use_morale_bonus || can_play_card) { @@ -1905,10 +1882,16 @@ states.player_turn = { resolve_spend_hp(); }, end_turn() { - if (game.faction_turn === get_active_faction()) { + const {src} = get_active_node_args(); + const faction_id = get_active_faction(); + if (game.faction_turn === faction_id) { game.faction_turn = null; game.played_card = null; - game.selected_cards[get_active_faction()] = []; + game.engine.push(create_function_node('end_of_player_turn', { f: faction_id })); + } + game.selected_cards[faction_id].pop(); + if (src === MOMENTUM) { + game.momentum = null; } resolve_active_and_proceed(true); }, @@ -1954,23 +1937,10 @@ states.player_turn = { next(); }, use_momentum() { - log("Momentum:"); - const faction = get_active_faction(); - // We need to update since there can be a case where - // morale bonus hasn't been used yet but is still set to true - // due to bonus being turned off. - game.card_played = 0; - game.selected_cards[faction] = []; - update_active_node_args<PlayerTurnArgs>({ - use_morale_bonus: false, - use_momentum: false, - }); - insert_before_active_node( - create_state_node<PlayCardArgs>('play_card', faction, { - src: 'momentum', - }) - ) - next(); + const faction_id = get_active_faction(); + game.selected_cards[faction_id].pop(); + game.momentum = null; + resolve_active_and_proceed(); }, use_morale_bonus() { log(`Morale Bonus:`) @@ -2280,6 +2250,7 @@ states.swap_card_tableau_hand = { const selected_cards = game.selected_cards[faction]; const hand = game.hands[faction]; const tableau = game.tableaus[faction]; + const { s: selected_at_start } = get_active_node_args(); gen_action('skip'); if (tableau.length === 0) { view.prompt = 'No card in your tableau to swap.'; @@ -2290,15 +2261,15 @@ states.swap_card_tableau_hand = { view.prompt = 'No card in your hand to swap.'; return; } - if (selected_cards.length === 1) { + if (selected_cards.length === selected_at_start) { for (const c of hand) { // do not swap currently executing card! - if (selected_cards[0] !== c) { + if (!selected_cards.includes(c)) { gen_action_card(c); } } } - if (selected_cards.length === 2) { + if (selected_cards.length === selected_at_start + 1) { for (const c of tableau) { gen_action_card(c); } @@ -2311,14 +2282,15 @@ states.swap_card_tableau_hand = { const faction = get_active_faction(); const selected_cards = game.selected_cards[faction]; selected_cards.push(c); - if (selected_cards.length === 3) { + const { s: selected_at_start } = get_active_node_args(); + if (selected_cards.length === selected_at_start + 2) { const hand = game.hands[faction]; const tableau = game.tableaus[faction]; - array_remove_item(hand, selected_cards[1]); - array_remove_item(tableau, selected_cards[2]); - hand.push(selected_cards[2]); - tableau.push(selected_cards[1]); - game.selected_cards[faction].length = 1; + array_remove_item(hand, selected_cards[selected_at_start + 1]); + array_remove_item(tableau, selected_cards[selected_at_start + 2]); + hand.push(selected_cards[selected_at_start + 2]); + tableau.push(selected_cards[selected_at_start + 1]); + game.selected_cards[faction].length = selected_at_start; resolve_active_and_proceed(); } }, @@ -3223,7 +3195,7 @@ function create_effects_node( } function get_faction_to_resolve_effect(effect: Effect): FactionId { - if (!effect.faction) { + if (effect.faction === undefined || effect.faction === null) { return get_active_faction(); } if (effect.faction === INITIATIVE_PLAYER) { @@ -3263,6 +3235,12 @@ function resolve_effect(effect: Effect, source?: EffectSource): EngineNode { src: source, }); } + if (effect.type === 'swap_card_tableau_hand') { + return create_state_node('swap_card_tableau_hand', faction, { + ...args, + s: game.selected_cards[get_active_faction()].length + }); + } // Default cases where effect type is mapped to a state let state = effect_type_state_map[effect.type]; @@ -3641,7 +3619,7 @@ function get_source_name(source: EffectSource): string { case 'tr4': return tracks[4].name + ' Trigger'; case 'track_icon': return 'Track Trigger'; - case 'momentum': + case MOMENTUM: return 'Momentum'; } return source; |