From db39b3dc70a5128a51e041cbf3127b7341167f14 Mon Sep 17 00:00:00 2001 From: Frans Bongers Date: Sun, 16 Feb 2025 20:54:52 +0100 Subject: multiactive choose card state --- rules.js | 77 +++++++++++++++++++++++++++++++++++------------------ rules.ts | 90 +++++++++++++++++++++++++++++++++++++++++++------------------- types.d.ts | 2 +- 3 files changed, 114 insertions(+), 55 deletions(-) diff --git a/rules.js b/rules.js index 455475f..eeb99f8 100644 --- a/rules.js +++ b/rules.js @@ -79,7 +79,7 @@ function gen_spend_hero_points() { } } function action(state, player, action, arg) { - if (action !== 'undo') { + if (action !== 'undo' && state.state !== 'choose_card') { state.undo = push_undo(); } game = state; @@ -380,17 +380,18 @@ function game_view(state, current) { if (game.state === 'game_over') { view.prompt = game.victory; } - else if (current !== game.active) { + else if (current !== game.active && + !game.active.includes(current)) { let inactive = states[game.state].inactive || game.state; - view.prompt = `Waiting for ${game.active} to ${inactive}.`; + view.prompt = Array.isArray(game.active) ? `Waiting for other players to ${inactive}.` : `Waiting for ${game.active} to ${inactive}.`; } else { view.actions = {}; - states[game.state].prompt(); if (game.undo && game.undo.length > 0) view.actions.undo = 1; else view.actions.undo = 0; + states[game.state].prompt(current); } return view; } @@ -938,17 +939,12 @@ states.change_bonus = { resolve_active_and_proceed(); }, }; -states.choose_card = { +states.play_card = { inactive: 'choose a card', - prompt(player) { - console.log('player', player); + prompt() { gen_spend_hero_points(); - const { src } = get_active_node_args(); - view.prompt = 'Choose a card to play this turn'; - if (src === 'momentum') { - view.prompt = 'Choose a card to play'; - } - const faction = player_faction_map[player]; + view.prompt = 'Choose a card to play'; + const faction = get_active_faction(); const hand = game.hands[faction]; for (let c of hand) { if (!game.selected_cards[faction].includes(c)) { @@ -959,12 +955,49 @@ states.choose_card = { spend_hp() { resolve_spend_hp(); }, + card(c) { + const faction = get_active_faction(); + game.selected_cards[faction].push(c); + game.played_card = game.selected_cards[faction][0]; + resolve_active_and_proceed(); + }, +}; +states.choose_card = { + inactive: 'choose a card', + prompt(player) { + gen_spend_hero_points(); + view.prompt = 'Choose a card to play this turn'; + const faction = player_faction_map[player]; + if (game.selected_cards[faction].length === 0) { + view.actions.undo = 0; + const hand = game.hands[faction]; + for (let c of hand) { + if (!game.selected_cards[faction].includes(c)) { + gen_action_card(c); + } + } + } + else { + view.actions.undo = 1; + view.actions.confirm = 1; + view.prompt = 'Confirm your actions or undo'; + } + }, + spend_hp() { + resolve_spend_hp(); + }, card(c, player) { const faction = player_faction_map[player]; game.selected_cards[faction].push(c); - const { src } = get_active_node_args(); - if (src === 'momentum') { - game.played_card = game.selected_cards[faction][0]; + }, + undo(_, player) { + const faction = player_faction_map[player]; + game.selected_cards[faction] = []; + }, + confirm(_, player) { + set_delete(game.active, player); + if (game.active.length === 0) { + resolve_active_and_proceed(); } }, }; @@ -1004,7 +1037,6 @@ function setup_momentum() { return; } const node = get_nodes_for_state('player_turn')[0]; - console.log('node', node); const player_needs_to_play_card = game.selected_cards[faction].length > 0; const { use_ap, use_morale_bonus, resolving_event } = node.a ?? {}; if (player_needs_to_play_card || @@ -1017,7 +1049,7 @@ function setup_momentum() { }; } else { - insert_before_active_node(create_leaf_node('choose_card', faction, { + insert_before_active_node(create_leaf_node('play_card', faction, { src: 'momentum', })); } @@ -1398,12 +1430,6 @@ function resolve_spend_hp() { next(); } function set_player_turn_prompt({ can_play_card, can_spend_hp, use_ap, use_momentum, use_morale_bonus, }) { - console.log('set_player_turn_prompt', { - can_play_card, - use_ap, - use_morale_bonus, - use_momentum, - }); if (can_play_card && can_spend_hp) { view.prompt = 'Play a card or spend Hero points'; } @@ -1446,7 +1472,6 @@ states.player_turn = { use_morale_bonus = use_morale_bonus && game.bonuses[data_1.MORALE_BONUS] === data_1.ON; const can_spend_hp = game.faction_turn === faction_id && game.hero_points[faction_id] > 0; const can_play_card = game.selected_cards[faction_id].length > 0; - console.log('can_play_card', can_play_card); if (use_momentum) { gen_action('use_momentum'); if (use_ap || use_morale_bonus || can_play_card) { @@ -2580,7 +2605,7 @@ function resolve_effect(effect, source) { condition: effect.type === 'play_card', resolve: () => { return create_seq_node([ - create_leaf_node('choose_card', faction, { src: source }), + create_leaf_node('play_card', faction, { src: source }), create_leaf_node('player_turn', faction, { src: source }), ]); }, diff --git a/rules.ts b/rules.ts index e47abe9..1900784 100644 --- a/rules.ts +++ b/rules.ts @@ -2,7 +2,6 @@ import { CardId, - ChooseCardArgs, Effect, EffectSource, EngineNode, @@ -14,6 +13,7 @@ import { Game, Icon, LeafNode, + PlayCardArgs, Player, PlayerCard, PlayerTurnArgs, @@ -203,7 +203,7 @@ export function action( action: string, arg: unknown ) { - if (action !== 'undo') { + if (action !== 'undo' && state.state !== 'choose_card') { state.undo = push_undo(); } @@ -587,14 +587,17 @@ function game_view(state: Game, current: Player | 'Observer') { if (game.state === 'game_over') { view.prompt = game.victory; - } else if (current !== game.active) { + } else if ( + current !== game.active && + !game.active.includes(current as Player) + ) { let inactive = states[game.state].inactive || game.state; - view.prompt = `Waiting for ${game.active} to ${inactive}.`; + view.prompt = Array.isArray(game.active) ? `Waiting for other players to ${inactive}.` : `Waiting for ${game.active} to ${inactive}.`; } else { view.actions = {}; - states[game.state].prompt(); if (game.undo && game.undo.length > 0) view.actions.undo = 1; else view.actions.undo = 0; + states[game.state].prompt(current); } return view; @@ -1205,18 +1208,16 @@ states.change_bonus = { }, }; -states.choose_card = { +// Used for effects that allow play of an extra card +states.play_card = { inactive: 'choose a card', - prompt(player: Player) { - console.log('player', player); + prompt() { gen_spend_hero_points(); - const { src } = get_active_node_args(); - view.prompt = 'Choose a card to play this turn'; - if (src === 'momentum') { - view.prompt = 'Choose a card to play'; - } - const faction = player_faction_map[player]; + view.prompt = 'Choose a card to play'; + + const faction = get_active_faction(); + const hand = game.hands[faction]; for (let c of hand) { if (!game.selected_cards[faction].includes(c)) { @@ -1227,14 +1228,55 @@ states.choose_card = { spend_hp() { resolve_spend_hp(); }, + card(c: CardId) { + const faction = get_active_faction(); + game.selected_cards[faction].push(c); + + game.played_card = game.selected_cards[faction][0]; + + resolve_active_and_proceed(); + }, +}; + +// Multiactive choose card state +states.choose_card = { + inactive: 'choose a card', + prompt(player: Player) { + gen_spend_hero_points(); + view.prompt = 'Choose a card to play this turn'; + + const faction = player_faction_map[player]; + + if (game.selected_cards[faction].length === 0) { + view.actions.undo = 0; + const hand = game.hands[faction]; + for (let c of hand) { + if (!game.selected_cards[faction].includes(c)) { + gen_action_card(c); + } + } + } else { + view.actions.undo = 1; + view.actions.confirm = 1; + view.prompt = 'Confirm your actions or undo'; + } + }, + spend_hp() { + resolve_spend_hp(); + }, card(c: CardId, player: Player) { const faction = player_faction_map[player]; game.selected_cards[faction].push(c); - const { src } = get_active_node_args(); - if (src === 'momentum') { - game.played_card = game.selected_cards[faction][0]; + }, + undo(_, player: Player) { + const faction = player_faction_map[player]; + game.selected_cards[faction] = []; + }, + confirm(_, player: Player) { + set_delete(game.active as Player[], player); + if (game.active.length === 0) { + resolve_active_and_proceed(); } - // resolve_active_and_proceed(); }, }; @@ -1287,7 +1329,6 @@ function setup_momentum() { // Get player turn node const node: LeafNode = get_nodes_for_state('player_turn')[0]; - console.log('node', node); const player_needs_to_play_card = game.selected_cards[faction].length > 0; const { use_ap, use_morale_bonus, resolving_event } = @@ -1307,7 +1348,7 @@ function setup_momentum() { } else { // Player can resolve choosing a new card insert_before_active_node( - create_leaf_node('choose_card', faction, { + create_leaf_node('play_card', faction, { src: 'momentum', }) ); @@ -1758,12 +1799,6 @@ function set_player_turn_prompt({ use_momentum, use_morale_bonus, }: PlayerTurnArgs & { can_spend_hp: boolean; can_play_card: boolean }) { - console.log('set_player_turn_prompt', { - can_play_card, - use_ap, - use_morale_bonus, - use_momentum, - }); if (can_play_card && can_spend_hp) { view.prompt = 'Play a card or spend Hero points'; } else if (can_play_card && !can_spend_hp) { @@ -1809,7 +1844,6 @@ states.player_turn = { game.faction_turn === faction_id && game.hero_points[faction_id] > 0; const can_play_card = game.selected_cards[faction_id].length > 0; - console.log('can_play_card', can_play_card); if (use_momentum) { gen_action('use_momentum'); if (use_ap || use_morale_bonus || can_play_card) { @@ -3241,7 +3275,7 @@ function resolve_effect(effect: Effect, source?: EffectSource): EngineNode { condition: effect.type === 'play_card', resolve: () => { return create_seq_node([ - create_leaf_node('choose_card', faction, { src: source }), + create_leaf_node('play_card', faction, { src: source }), create_leaf_node('player_turn', faction, { src: source }), ]); }, diff --git a/types.d.ts b/types.d.ts index 6d0a31a..cab4b5d 100644 --- a/types.d.ts +++ b/types.d.ts @@ -231,7 +231,7 @@ export interface EngineNodeArgsBase { src?: EffectSource; } -export interface ChooseCardArgs extends EngineNodeArgsBase { +export interface PlayCardArgs extends EngineNodeArgsBase { } export interface PlayerTurnArgs extends EngineNodeArgsBase { -- cgit v1.2.3