diff options
-rw-r--r-- | data.js | 4 | ||||
-rw-r--r-- | data.ts | 4 | ||||
-rw-r--r-- | play.js | 5 | ||||
-rw-r--r-- | play.ts | 6 | ||||
-rw-r--r-- | rules.js | 110 | ||||
-rw-r--r-- | rules.ts | 152 |
6 files changed, 170 insertions, 111 deletions
@@ -1144,7 +1144,7 @@ const data = { pass: create_effect('hero_points', PLAYER_WITH_MOST_HERO_POINTS, 1), fail: create_effect('track', FOREIGN_AID, -2), }, - title: 'NAZI MINING', + title: 'NAZI MINING CONTRACT', type: 'ec', year: 2, }, @@ -1627,7 +1627,7 @@ const data = { test: { front: MADRID, value: 0, - pass: create_effect('play_card', INITIATIVE_PLAYER, 1), + pass: create_effect('play_card', INITIATIVE_PLAYER, 1, INITIATIVE_PLAYER), fail: create_effect('track', FOREIGN_AID, -3), }, title: 'NATIONAL DEFENCE COUNCIL', @@ -1181,7 +1181,7 @@ const data: StaticData = { pass: create_effect('hero_points', PLAYER_WITH_MOST_HERO_POINTS, 1), fail: create_effect('track', FOREIGN_AID, -2), }, - title: 'NAZI MINING', + title: 'NAZI MINING CONTRACT', type: 'ec', year: 2, }, @@ -1689,7 +1689,7 @@ const data: StaticData = { test: { front: MADRID, value: 0, - pass: create_effect('play_card', INITIATIVE_PLAYER, 1), + pass: create_effect('play_card', INITIATIVE_PLAYER, 1, INITIATIVE_PLAYER), fail: create_effect('track', FOREIGN_AID, -3), }, title: 'NATIONAL DEFENCE COUNCIL', @@ -330,6 +330,7 @@ function on_update() { ui.turn_info.style.display = 'none'; } else { + ui.turn_info.style.display = ''; ui.turn_info_card.setAttribute('data-card-id', view.played_card + ''); } for (let g = 0; g < view.glory.length; ++g) { @@ -346,8 +347,6 @@ function on_update() { action_button('d_foreign_aid', 'Decrease Foreign Aid'); action_button('d_government', 'Decrease Government'); action_button('d_soviet_support', 'Decrease Soviet Support'); - action_button('draw_card', 'Draw a card'); - action_button('draw_cards', 'Draw cards'); action_button('foreign_aid', 'Foreign Aid'); action_button('government', 'Government'); action_button('liberty', 'Liberty'); @@ -357,6 +356,8 @@ function on_update() { action_button('Communist', 'Communist'); action_button('Moderate', 'Moderate'); action_button('gain_hp', 'Gain Hero Points'); + action_button('draw_card', 'Draw a card'); + action_button('draw_cards', 'Draw cards'); action_button('play_for_ap', 'Play card for Action Points'); action_button('play_for_event', 'Play card for Event'); action_button('spend_hp', 'Spend Hero Points'); @@ -432,6 +432,7 @@ function on_update() { if (view.played_card === null) { ui.turn_info.style.display = 'none'; } else { + ui.turn_info.style.display = ''; ui.turn_info_card.setAttribute('data-card-id', view.played_card + ''); } @@ -454,8 +455,7 @@ function on_update() { action_button('d_government', 'Decrease Government'); action_button('d_soviet_support', 'Decrease Soviet Support'); - action_button('draw_card', 'Draw a card'); - action_button('draw_cards', 'Draw cards'); + action_button('foreign_aid', 'Foreign Aid'); action_button('government', 'Government'); action_button('liberty', 'Liberty'); @@ -466,6 +466,8 @@ function on_update() { action_button('Communist', 'Communist'); action_button('Moderate', 'Moderate'); action_button('gain_hp', 'Gain Hero Points'); + action_button('draw_card', 'Draw a card'); + action_button('draw_cards', 'Draw cards'); // action_button('draw_card', 'Draw card'); action_button('play_for_ap', 'Play card for Action Points'); action_button('play_for_event', 'Play card for Event'); @@ -433,7 +433,7 @@ states.activate_icon = { inactive: 'activate an icon', prompt() { view.prompt = 'Choose an icon to activate'; - const c = cards[game.selected_cards[get_active_faction_id()][0]]; + const c = cards[game.played_card]; for (const i of c.icons) { gen_action(i); } @@ -764,12 +764,17 @@ states.choose_card = { inactive: 'choose a card', prompt() { view.prompt = 'Choose a card to play this turn'; - const hand = game.hands[player_faction_map[game.active]]; - for (let c of hand) - gen_action_card(c); + const faction = get_active_faction(); + const hand = game.hands[faction]; + for (let c of hand) { + if (!game.selected_cards[faction].includes(c)) { + gen_action_card(c); + } + } }, card(c) { - game.selected_cards[player_faction_map[game.active]].push(c); + const faction = get_active_faction(); + game.selected_cards[faction].push(c); resolve_active_and_proceed(); }, }; @@ -824,6 +829,7 @@ states.choose_medallion = { gain_hero_points(faction, 7); break; case 2: + insert_after_active_node(create_leaf_node('choose_card', faction)); break; default: game.medallions[faction].push(m); @@ -928,32 +934,34 @@ states.game_over = { view.prompt = game.victory; }, }; -states.lose_hero_points = { +function resolve_player_with_most_hero_points(faction) { + const value = get_active_node_args().v; + if (value < 0) { + lose_hero_point(faction, value); + } + else { + gain_hero_points(faction, value); + } + resolve_active_and_proceed(); +} +states.select_player_with_most_hero_points = { inactive: 'choose a Player', prompt() { - const args = get_active_node_args(); - view.prompt = 'Choose player to lose Hero Points'; - if (args.t === data_1.PLAYER_WITH_MOST_HERO_POINTS) { - const factions = get_factions_with_most_hero_poins(); - for (let faction_id of factions) { - gen_action(faction_player_map[faction_id]); - } + const { v } = get_active_node_args(); + view.prompt = v < 0 ? 'Choose player to lose Hero Points' : 'Choose player to gain Hero Points'; + const factions = get_factions_with_most_hero_poins(); + for (let faction_id of factions) { + gen_action(faction_player_map[faction_id]); } }, Anarchist() { - const value = get_active_node_args().v; - lose_hero_point(data_1.ANARCHISTS_ID, value); - resolve_active_and_proceed(); + resolve_player_with_most_hero_points(data_1.ANARCHISTS_ID); }, Communist() { - const value = get_active_node_args().v; - lose_hero_point(data_1.COMMUNISTS_ID, value); - resolve_active_and_proceed(); + resolve_player_with_most_hero_points(data_1.COMMUNISTS_ID); }, Moderate() { - const value = get_active_node_args().v; - lose_hero_point(data_1.MODERATES_ID, value); - resolve_active_and_proceed(); + resolve_player_with_most_hero_points(data_1.MODERATES_ID); }, }; states.move_attacks = { @@ -1027,8 +1035,8 @@ states.player_turn = { inactive: 'play their turn', prompt() { const faction_id = get_faction_id(game.active); - const can_spend_hp = game.hero_points[faction_id] > 0; - const can_play_card = game.hands[faction_id].includes(game.selected_cards[faction_id][0]); + 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; view.prompt = 'Play a card or spend Hero points'; if (!(can_play_card || can_spend_hp)) { view.prompt = 'End turn'; @@ -1036,6 +1044,9 @@ states.player_turn = { else if (!can_play_card && can_spend_hp) { view.prompt = 'Spend Hero Points or end turn'; } + else if (can_play_card && !can_spend_hp) { + view.prompt = 'Play a card'; + } if (can_play_card) { gen_action('play_for_ap'); gen_action('play_for_event'); @@ -1053,28 +1064,20 @@ states.player_turn = { resolve_active_and_proceed(true); }, play_for_ap() { - const faction_id = get_faction_id(game.active); - const card = game.selected_cards[faction_id][0]; - game.played_card = card; - log_h3(`${game.active} plays ${cards[card].title} for the Action Points`); - array_remove(game.hands[faction_id], game.hands[faction_id].indexOf(card)); - game.tableaus[faction_id].push(card); + const faction = get_active_faction(); + const { strength } = play_card(faction, 'play_for_ap'); insert_before_active_node(create_seq_node([ - create_leaf_node('choose_area_ap', faction_id, { - strength: cards[card].strength, + create_leaf_node('choose_area_ap', faction, { + strength, }), create_function_node('check_activate_icon'), ])); next(); }, play_for_event() { - const faction_id = get_faction_id(game.active); - const card = game.selected_cards[faction_id][0]; - game.played_card = card; - array_remove(game.hands[faction_id], game.hands[faction_id].indexOf(card)); - game.trash[faction_id].push(card); - log_h3(`${game.active} plays ${cards[card].title} for the Event`); - insert_before_active_node(create_effects_node(cards[card].effects)); + const faction = get_active_faction(); + const { effects } = play_card(faction, 'play_for_ap'); + insert_before_active_node(create_effects_node(effects)); next(); }, spend_hp() { @@ -1513,6 +1516,22 @@ function get_hand_limit(faction) { } return hand_limit; } +function play_card(faction, type) { + const index = game.selected_cards[faction].length - 1; + const card_id = game.selected_cards[faction][index]; + const card = cards[card_id]; + game.played_card = card_id; + log_h3(`${game.active} plays ${card.title} for the ${type === 'play_for_event' ? 'Event' : 'Action Points'}`); + array_remove(game.hands[faction], game.hands[faction].indexOf(card_id)); + array_remove(game.selected_cards[faction], index); + if (type === 'play_for_event') { + game.trash[faction].push(card_id); + } + else { + game.tableaus[faction].push(card_id); + } + return card; +} function resolve_fascist_test() { log_h2('Fascist Test', 'fascist'); const test = get_current_event().test; @@ -1784,7 +1803,7 @@ function resolve_effect(effect) { condition: effect.type === 'hero_points' && effect.target === data_1.PLAYER_WITH_MOST_HERO_POINTS, resolve: () => { - return create_leaf_node('lose_hero_points', faction, args); + return create_leaf_node('select_player_with_most_hero_points', faction, args); }, }, { @@ -1811,7 +1830,7 @@ function resolve_effect(effect) { { condition: effect.type === 'hero_points' && effect.target === data_1.INITIATIVE_PLAYER, resolve: () => { - return create_leaf_node('gain_hero_points', game.initiative); + return create_leaf_node('gain_hero_points', game.initiative, args); }, }, { @@ -1851,6 +1870,15 @@ function resolve_effect(effect) { return create_seq_node(leaf_nodes); }, }, + { + condition: effect.type === 'play_card', + resolve: () => { + return create_seq_node([ + create_leaf_node('choose_card', faction), + create_leaf_node('player_turn', faction), + ]); + }, + }, ]; const strategy = strategies.find((strategy) => strategy.condition); if (strategy) { @@ -634,7 +634,7 @@ states.activate_icon = { inactive: 'activate an icon', prompt() { view.prompt = 'Choose an icon to activate'; - const c = cards[game.selected_cards[get_active_faction_id()][0]] as PlayerCard; + const c = cards[game.played_card] as PlayerCard; for (const i of c.icons) { gen_action(i); } @@ -978,11 +978,17 @@ states.choose_card = { inactive: 'choose a card', prompt() { view.prompt = 'Choose a card to play this turn'; - const hand = game.hands[player_faction_map[game.active]]; - for (let c of hand) gen_action_card(c); + const faction = get_active_faction(); + const hand = game.hands[faction]; + for (let c of hand) { + if (!game.selected_cards[faction].includes(c)) { + gen_action_card(c); + } + } }, card(c: CardId) { - game.selected_cards[player_faction_map[game.active]].push(c); + const faction = get_active_faction(); + game.selected_cards[faction].push(c); resolve_active_and_proceed(); }, }; @@ -1042,7 +1048,7 @@ states.choose_medallion = { gain_hero_points(faction, 7); break; case 2: - // insert play another card action + insert_after_active_node(create_leaf_node('choose_card', faction)); break; default: game.medallions[faction].push(m); @@ -1153,32 +1159,36 @@ states.game_over = { }, }; -states.lose_hero_points = { +function resolve_player_with_most_hero_points(faction: FactionId) { + const value = get_active_node_args().v; + if (value < 0) { + lose_hero_point(faction, value); + } else { + gain_hero_points(faction, value) + } + resolve_active_and_proceed(); +} + + +states.select_player_with_most_hero_points = { inactive: 'choose a Player', prompt() { - const args = get_active_node_args(); - view.prompt = 'Choose player to lose Hero Points'; - if (args.t === PLAYER_WITH_MOST_HERO_POINTS) { - const factions = get_factions_with_most_hero_poins(); - for (let faction_id of factions) { - gen_action(faction_player_map[faction_id]); - } + const { v } = get_active_node_args(); + view.prompt = v < 0 ? 'Choose player to lose Hero Points' : 'Choose player to gain Hero Points'; + + const factions = get_factions_with_most_hero_poins(); + for (let faction_id of factions) { + gen_action(faction_player_map[faction_id]); } }, Anarchist() { - const value = get_active_node_args().v; - lose_hero_point(ANARCHISTS_ID, value); - resolve_active_and_proceed(); + resolve_player_with_most_hero_points(ANARCHISTS_ID); }, Communist() { - const value = get_active_node_args().v; - lose_hero_point(COMMUNISTS_ID, value); - resolve_active_and_proceed(); + resolve_player_with_most_hero_points(COMMUNISTS_ID); }, Moderate() { - const value = get_active_node_args().v; - lose_hero_point(MODERATES_ID, value); - resolve_active_and_proceed(); + resolve_player_with_most_hero_points(MODERATES_ID); }, }; @@ -1266,16 +1276,19 @@ states.player_turn = { inactive: 'play their turn', prompt() { const faction_id = get_faction_id(game.active as Player); - const can_spend_hp = game.hero_points[faction_id] > 0; - // TODO: refactor to check selected_cards.length - const can_play_card = game.hands[faction_id].includes( - game.selected_cards[faction_id][0] - ); + + 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; + view.prompt = 'Play a card or spend Hero points'; if (!(can_play_card || can_spend_hp)) { view.prompt = 'End turn'; } else if (!can_play_card && can_spend_hp) { view.prompt = 'Spend Hero Points or end turn'; + } else if (can_play_card && !can_spend_hp) { + view.prompt = 'Play a card'; } // const card = game.cards_in_play[faction_id]; @@ -1296,16 +1309,13 @@ states.player_turn = { resolve_active_and_proceed(true); }, play_for_ap() { - const faction_id = get_faction_id(game.active as Player); - const card = game.selected_cards[faction_id][0]; - game.played_card = card; - log_h3(`${game.active} plays ${cards[card].title} for the Action Points`); - array_remove(game.hands[faction_id], game.hands[faction_id].indexOf(card)); - game.tableaus[faction_id].push(card); + const faction = get_active_faction(); + const { strength } = play_card(faction, 'play_for_ap'); + insert_before_active_node( create_seq_node([ - create_leaf_node('choose_area_ap', faction_id, { - strength: (cards[card] as PlayerCard).strength, + create_leaf_node('choose_area_ap', faction, { + strength, }), create_function_node('check_activate_icon'), ]) @@ -1313,14 +1323,10 @@ states.player_turn = { next(); }, play_for_event() { - const faction_id = get_faction_id(game.active as Player); - const card = game.selected_cards[faction_id][0]; - game.played_card = card; - array_remove(game.hands[faction_id], game.hands[faction_id].indexOf(card)); - game.trash[faction_id].push(card); - log_h3(`${game.active} plays ${cards[card].title} for the Event`); + const faction = get_active_faction(); + const { effects } = play_card(faction, 'play_for_ap'); - insert_before_active_node(create_effects_node(cards[card].effects)); + insert_before_active_node(create_effects_node(effects)); next(); }, @@ -1497,7 +1503,7 @@ states.swap_card_tableau_hand = { gen_action_card(c); } }, - // card(c: CardId) {}, + // card(c: CardId) {}, }; // TODO: implement, card 12 + card 32 + card 44 @@ -1887,6 +1893,29 @@ function get_hand_limit(faction: FactionId) { return hand_limit; } +function play_card( + faction: FactionId, + type: 'play_for_event' | 'play_for_ap' +): PlayerCard { + const index = game.selected_cards[faction].length - 1; + const card_id = game.selected_cards[faction][index]; + const card = cards[card_id]; + game.played_card = card_id; + log_h3( + `${game.active} plays ${card.title} for the ${ + type === 'play_for_event' ? 'Event' : 'Action Points' + }` + ); + array_remove(game.hands[faction], game.hands[faction].indexOf(card_id)); + array_remove(game.selected_cards[faction], index); + if (type === 'play_for_event') { + game.trash[faction].push(card_id); + } else { + game.tableaus[faction].push(card_id); + } + return card as PlayerCard; +} + function resolve_fascist_test() { log_h2('Fascist Test', 'fascist'); @@ -1939,7 +1968,9 @@ function resolve_final_bid() { highest_bid = player_bid; winners = [f]; } - game.hands[f] = game.hands[f].filter((c) => !game.selected_cards[f].includes(c)); + game.hands[f] = game.hands[f].filter( + (c) => !game.selected_cards[f].includes(c) + ); game.discard[f].concat(game.selected_cards[f]); game.selected_cards[f] = []; } @@ -2237,7 +2268,11 @@ function resolve_effect( effect.type === 'hero_points' && effect.target === PLAYER_WITH_MOST_HERO_POINTS, resolve: () => { - return create_leaf_node('lose_hero_points', faction, args); + return create_leaf_node( + 'select_player_with_most_hero_points', + faction, + args + ); }, }, { @@ -2274,7 +2309,7 @@ function resolve_effect( condition: effect.type === 'hero_points' && effect.target === INITIATIVE_PLAYER, resolve: () => { - return create_leaf_node('gain_hero_points', game.initiative); + return create_leaf_node('gain_hero_points', game.initiative, args); }, }, { @@ -2323,6 +2358,15 @@ function resolve_effect( return create_seq_node(leaf_nodes); }, }, + { + condition: effect.type === 'play_card', + resolve: () => { + return create_seq_node([ + create_leaf_node('choose_card', faction), + create_leaf_node('player_turn', faction), + ]); + }, + }, ]; const strategy = strategies.find((strategy) => strategy.condition); @@ -2333,22 +2377,6 @@ function resolve_effect( console.log('----UNRESOLVED EFFECT----', effect); throw new Error('Unresolved effect'); } - // if ( - // // TODO: determine state based on value? - // effect.type === 'hero_points' && - // effect.target === PLAYER_WITH_MOST_HERO_POINTS - // ) { - // state = 'lose_hero_points'; - // } else if (effect.type === 'hero_points' && effect.target === SELF) { - // state = 'gain_hero_points'; - // } else if (effect.type === 'draw_card' && effect.target === SELF) { - // state = 'draw_card'; - // } - // if (state === undefined) { - // console.log('----UNRESOLVED EFFECT----', effect); - // return null; - // } - // return create_leaf_node(state, faction, args); } function win_final_bid(faction_id: FactionId) { |