diff options
Diffstat (limited to 'rules.ts')
-rw-r--r-- | rules.ts | 495 |
1 files changed, 401 insertions, 94 deletions
@@ -39,6 +39,7 @@ import data, { CLOSEST_TO_VICTORY, COLLECTIVIZATION, GOVERNMENT, + INITIATIVE_PLAYER, SOVIET_SUPPORT, FOREIGN_AID, ON, @@ -54,6 +55,13 @@ import data, { create_effect, AWAY_FROM_CENTER, TOWARDS_CENTER, + ARCHIVES_MEDALLION_ID, + INTELLIGENCE_MEDALLION_ID, + // VOLUNTEERS_MEDALLION_ID, + ORGANIZATION_MEDALLION_ID, + STRATEGY_MEDALLION_ID, + PROPAGANDA_MEDALLION_ID, + VOLUNTEERS_MEDALLION_ID, // StaticData, // PLAYER_WITH_MOST_HERO_POINTS, } from './data'; @@ -98,6 +106,7 @@ const bonus_names: string[] = ['Morale Bonus', 'Teamwork Bonus']; const { cards, + medallions, // fronts, tracks, } = data; @@ -110,10 +119,6 @@ const faction_cards = { [MODERATES_ID]: make_list(1, 18) as CardId[], }; -const medaillons = make_list(0, 8) as number[]; - -console.log('medaillons', medaillons); - const fascist_decks = { 1: make_list(55, 72), 2: make_list(73, 90), @@ -133,6 +138,10 @@ function gen_action(action: string, argument?: number | string) { } } +function gen_action_blank_marker(marker_id: number) { + gen_action('blank_marker', marker_id); +} + function gen_action_bonus(bonus_id: number) { gen_action('bonus', bonus_id); } @@ -145,6 +154,10 @@ function gen_action_front(front_id: string) { gen_action('front', front_id); } +function gen_action_medallion(medallion_id: number) { + gen_action('medallion', medallion_id); +} + function gen_action_standee(track_id: number) { gen_action('standee', track_id); } @@ -256,8 +269,6 @@ function setup_player_turn() { function start_of_player_turn() { const args = get_active_node_args(); - console.log('args', args); - console.log('args'); const player = faction_player_map[args.f]; log_h2(player, player); resolve_active_and_proceed(); @@ -319,7 +330,6 @@ function insert_before_or_after_active_node( return; } const i = a.parent.indexOf(a.node); - console.log('insert_before_active_node', i); if (i >= 0) { array_insert(a.parent, i + (position == 'after' ? 1 : 0), node); } @@ -356,7 +366,6 @@ function next() { function resolve_active_node() { const next_node = get_active_node(game.engine); - console.log('resolve_active_node', next_node); if (next_node !== null) { next_node.r = resolved; } @@ -393,11 +402,12 @@ function game_view(state: Game, player: Player) { hand: game.hands[faction_id], hero_points: game.hero_points, initiative: game.initiative, - medaillons: game.medaillons, + medallions: game.medallions, selected_card: game.chosen_cards[faction_id], tableaus: game.tableaus, tracks: game.tracks, triggered_track_effects: game.triggered_track_effects, + used_medallions: game.used_medallions, year: game.year, }; @@ -482,13 +492,12 @@ export function setup(seed: number, _scenario: string, _options: unknown) { [MODERATES_ID]: null, }, initiative: MODERATES_ID, - medaillons: [ - draw_item(medaillons), - draw_item(medaillons), - draw_item(medaillons), - draw_item(medaillons), - draw_item(medaillons), - ], + medallions: { + [ANARCHISTS_ID]: [], + [COMMUNISTS_ID]: [], + [MODERATES_ID]: [], + pool: [], + }, tableaus: { [ANARCHISTS_ID]: [], [COMMUNISTS_ID]: [], @@ -500,14 +509,17 @@ export function setup(seed: number, _scenario: string, _options: unknown) { [COMMUNISTS_ID]: [], [MODERATES_ID]: [], }, - triggered_track_effects: [[], [], [], [], []], + triggered_track_effects: [], log: [], undo: [], + used_medallions: [], turn: 0, year: 0, state_data: null, }; + draw_medallions(); + start_year(); return game; } @@ -515,6 +527,11 @@ export function setup(seed: number, _scenario: string, _options: unknown) { function draw_hand_cards(faction_id: FactionId, count: number) { const deck = list_deck(faction_id); + if (game.medallions[faction_id].includes(INTELLIGENCE_MEDALLION_ID)) { + count++; + } + const drawn_cards = count; + // Draw all remaining cards if (deck.length < count) { count = count - deck.length; @@ -522,13 +539,12 @@ function draw_hand_cards(faction_id: FactionId, count: number) { game.discard[faction_id] = []; } - console.log('draw_hand_cards', count); const log = - count === 1 + drawn_cards === 1 ? `${get_player(faction_id)} draws 1 card` - : `${get_player(faction_id)} draws ${count} cards`; + : `${get_player(faction_id)} draws ${drawn_cards} cards`; logi(log); - console.log('deck', list_deck(faction_id)); + for (let i = 0; i < count; i++) { const deck = list_deck(faction_id); game.hands[faction_id].push(draw_card(deck)); @@ -557,9 +573,7 @@ function start_turn() { log_h2('Fascist Event', 'fascist'); log(card.title); - game.engine = card.effects.map((effect) => - resolve_effect(effect, game.initiative) - ); + game.engine = card.effects.map((effect) => resolve_effect(effect)); if (game.year === 3 && game.turn === 1) { game.engine.push(create_function_node('setup_final_bid')); } else { @@ -594,33 +608,57 @@ states.activate_icon = { resolve_active_and_proceed(); }, collectivization() { - move_track(COLLECTIVIZATION, get_icon_count_in_tableau('collectivization')); + const count = get_icon_count_in_tableau('collectivization'); + if (can_use_medallion(ORGANIZATION_MEDALLION_ID)) { + insert_use_organization_medallion_node(COLLECTIVIZATION, count); + } else { + move_track(COLLECTIVIZATION, count); + } resolve_active_and_proceed(); }, d_collectivization() { - move_track( - COLLECTIVIZATION, - -1 * get_icon_count_in_tableau('d_collectivization') - ); + const count = -1 * get_icon_count_in_tableau('d_collectivization'); + if (can_use_medallion(ORGANIZATION_MEDALLION_ID)) { + insert_use_organization_medallion_node(COLLECTIVIZATION, count); + } else { + move_track(COLLECTIVIZATION, count); + } resolve_active_and_proceed(); }, d_foreign_aid() { - move_track(FOREIGN_AID, -1 * get_icon_count_in_tableau('d_foreign_aid')); + const count = -1 * get_icon_count_in_tableau('d_foreign_aid'); + if (can_use_medallion(ORGANIZATION_MEDALLION_ID)) { + insert_use_organization_medallion_node(FOREIGN_AID, count); + } else { + move_track(FOREIGN_AID, count); + } resolve_active_and_proceed(); }, d_government() { - move_track(GOVERNMENT, -1 * get_icon_count_in_tableau('d_government')); + const count = -1 * get_icon_count_in_tableau('d_government'); + if (can_use_medallion(ORGANIZATION_MEDALLION_ID)) { + insert_use_organization_medallion_node(GOVERNMENT, count); + } else { + move_track(GOVERNMENT, count); + } resolve_active_and_proceed(); }, d_liberty() { - move_track(LIBERTY, -1 * get_icon_count_in_tableau('d_liberty')); + const count = -1 * get_icon_count_in_tableau('d_liberty'); + if (can_use_medallion(ORGANIZATION_MEDALLION_ID)) { + insert_use_organization_medallion_node(LIBERTY, count); + } else { + move_track(LIBERTY, count); + } resolve_active_and_proceed(); }, d_soviet_support() { - move_track( - SOVIET_SUPPORT, - -1 * get_icon_count_in_tableau('d_soviet_support') - ); + const count = -1 * get_icon_count_in_tableau('d_soviet_support'); + if (can_use_medallion(ORGANIZATION_MEDALLION_ID)) { + insert_use_organization_medallion_node(SOVIET_SUPPORT, count); + } else { + move_track(SOVIET_SUPPORT, count); + } resolve_active_and_proceed(); }, draw_card() { @@ -631,12 +669,22 @@ states.activate_icon = { resolve_active_and_proceed(); }, foreign_aid() { - move_track(FOREIGN_AID, get_icon_count_in_tableau('foreign_aid')); + const count = get_icon_count_in_tableau('foreign_aid'); + if (can_use_medallion(ORGANIZATION_MEDALLION_ID)) { + insert_use_organization_medallion_node(FOREIGN_AID, count); + } else { + move_track(FOREIGN_AID, count); + } resolve_active_and_proceed(); }, government() { const direction = game.active === COMMUNIST ? -1 : 1; - move_track(GOVERNMENT, direction * get_icon_count_in_tableau('government')); + const count = direction * get_icon_count_in_tableau('government'); + if (can_use_medallion(ORGANIZATION_MEDALLION_ID)) { + insert_use_organization_medallion_node(GOVERNMENT, count); + } else { + move_track(GOVERNMENT, count); + } resolve_active_and_proceed(); }, government_to_center() { @@ -648,11 +696,21 @@ states.activate_icon = { resolve_active_and_proceed(); }, liberty() { - move_track(LIBERTY, get_icon_count_in_tableau('liberty')); + const count = get_icon_count_in_tableau('liberty'); + if (can_use_medallion(ORGANIZATION_MEDALLION_ID)) { + insert_use_organization_medallion_node(LIBERTY, count); + } else { + move_track(LIBERTY, count); + } resolve_active_and_proceed(); }, soviet_support() { - move_track(SOVIET_SUPPORT, get_icon_count_in_tableau('soviet_support')); + const count = get_icon_count_in_tableau('soviet_support'); + if (can_use_medallion(ORGANIZATION_MEDALLION_ID)) { + insert_use_organization_medallion_node(SOVIET_SUPPORT, count); + } else { + move_track(SOVIET_SUPPORT, count); + } resolve_active_and_proceed(); }, teamwork_on() { @@ -668,17 +726,11 @@ states.add_glory = { gen_action('add_glory'); }, add_glory() { - console.log('add_glory'); let number = 1; if (game.turn === 4) { number++; } - game.bag_of_glory.push(get_active_faction()); - if (number === 1) { - log_h3(`${game.active} adds 1 token to the Bag of Glory`); - } else { - log_h3(`${game.active} adds ${number} tokens to the Bag of Glory`); - } + add_glory(get_active_faction(), number); resolve_active_and_proceed(); }, }; @@ -898,13 +950,54 @@ states.choose_final_bid = { }, }; +states.choose_medallion = { + inactive: 'choose a medallion', + prompt() { + view.prompt = 'Choose a medallion'; + for (let m of game.medallions.pool) { + gen_action_medallion(m); + } + if (!game.medallions.pool.some((m) => m !== null)) { + gen_action('skip'); + } + }, + medallion(m: number) { + const faction = get_active_faction(); + const medallion = medallions[m]; + + logi(`${faction_player_map[faction]} earns ${medallion.name}`); + + const index = game.medallions.pool.indexOf(m); + + game.medallions.pool[index] = null; + + switch (m) { + case 0: + add_glory(faction, 1, true); + break; + case 1: + gain_hero_points(faction, 7); + break; + case 2: + // insert play another card action + break; + default: + game.medallions[faction].push(m); + } + resolve_active_and_proceed(); + }, + skip() { + resolve_active_and_proceed(); + }, +}; + states.end_of_year_discard = { inactive: 'discard cards from hand and tableau', prompt() { view.prompt = 'Discard a card'; const faction_id = get_active_faction(); const hand = game.hands[faction_id]; - if (hand.length > game.year) { + if (hand.length > get_hand_limit(faction_id)) { for (let c of hand) gen_action_card(c); } const tableau = game.tableaus[faction_id]; @@ -914,7 +1007,6 @@ states.end_of_year_discard = { }, card(c: CardId) { const faction_id = get_active_faction(); - console.log('list deck', list_deck(faction_id)); if (game.hands[faction_id].includes(c)) { game.hands[faction_id] = game.hands[faction_id].filter((id) => id !== c); } else if (game.tableaus[faction_id].includes(c)) { @@ -924,7 +1016,7 @@ states.end_of_year_discard = { } game.discard[faction_id].push(c); if ( - game.hands[faction_id].length > game.year || + game.hands[faction_id].length > get_hand_limit(faction_id) || game.tableaus[faction_id].length > game.year ) { // More cards to discard so resolve same state again @@ -966,7 +1058,6 @@ states.lose_hero_points = { view.prompt = 'Choose player to lose Hero Points'; if (args.t === PLAYER_WITH_MOST_HERO_POINTS) { const factions = get_factions_with_most_hero_poins(); - console.log('faction', factions); for (let faction_id of factions) { gen_action(faction_player_map[faction_id]); } @@ -1014,7 +1105,9 @@ states.move_track = { s === GOVERNMENT && (value === TOWARDS_CENTER || value === AWAY_FROM_CENTER) ) { - value = get_government_track_direction(value); + const direction = get_government_track_direction(value); + // Value equals direction because away / towards always moves 1 step + value = direction; } move_track(s, value); @@ -1095,9 +1188,9 @@ states.player_turn = { game.trash[faction_id].push(card); log_h3(`${game.active} plays ${cards[card].title} for the Event`); - insert_after_active_node(create_effects_node(cards[card].effects)); + insert_before_active_node(create_effects_node(cards[card].effects)); - resolve_active_and_proceed(); + next(); }, spend_hp() { // insert spend hero points node before current node @@ -1111,18 +1204,55 @@ states.player_turn = { }, }; +states.remove_blank_marker = { + inactive: 'remove a Blank marker', + prompt() { + view.prompt = 'Remove a Blank marker'; + + for (const b of game.triggered_track_effects) { + gen_action_blank_marker(b); + } + }, + blank_marker(b: number) { + const faction = get_active_faction(); + pay_hero_points(faction, 1); + + const track_id = Math.floor(b / 11); + const space_id = b % 11; + + logi( + `${ + faction_player_map[faction] + } removes a Blank marker from space ${space_id} of ${get_track_name( + track_id + )}` + ); + game.triggered_track_effects = game.triggered_track_effects.filter( + (id) => id !== b + ); + game.used_medallions.push(ARCHIVES_MEDALLION_ID); + resolve_active_and_proceed(); + }, +}; + states.spend_hero_points = { inactive: 'spend Hero points', prompt() { view.prompt = 'Spend your Hero points'; gen_action('done'); + const faction = get_active_faction(); const hero_points = game.hero_points[get_active_faction()]; if (hero_points === 0) { return; } gen_action('draw_card'); - + if (can_use_medallion(ARCHIVES_MEDALLION_ID, faction)) { + gen_action('remove_blank_marker'); + } + if (can_use_medallion(VOLUNTEERS_MEDALLION_ID, faction)) { + gen_action('add_to_front'); + } if (hero_points < 2) { return; } @@ -1145,6 +1275,20 @@ states.spend_hero_points = { } gen_action_standee(GOVERNMENT); }, + add_to_front() { + const faction = get_active_faction(); + pay_hero_points(faction, 1); + insert_after_active_node( + create_seq_node([ + create_leaf_node('add_to_front', faction, { + t: ANY, + v: 1, + }), + create_leaf_node('spend_hero_points', faction), + ]) + ); + resolve_active_and_proceed(); + }, done() { resolve_active_and_proceed(); }, @@ -1157,6 +1301,21 @@ states.spend_hero_points = { pay_hero_points(faction, 1); draw_hand_cards(faction, 1); }, + remove_blank_marker() { + const faction = get_active_faction(); + if (game.used_medallions) { + game.used_medallions.push(ARCHIVES_MEDALLION_ID); + } else { + game.used_medallions = [ARCHIVES_MEDALLION_ID]; + } + insert_after_active_node( + create_seq_node([ + create_leaf_node('remove_blank_marker', faction), + create_leaf_node('spend_hero_points', faction), + ]) + ); + resolve_active_and_proceed(); + }, standee(track_id: number) { let amount = 2; if (track_id === LIBERTY || track_id === COLLECTIVIZATION) { @@ -1179,21 +1338,59 @@ states.spend_hero_points = { }, }; -// states.move_to = { -// inactive: 'move', -// prompt() { -// view.prompt = 'Move the piece to a space.'; -// for (let s = 0; s < 64; ++s) gen_action_space(s); -// }, -// // space(to) { -// // game.location[game.selected] = to -// // game.state = "move" -// // if (game.active === PLAYER1) -// // game.active = PLAYER2 -// // else -// // game.active = PLAYER1 -// // }, -// }; +states.use_organization_medallion = { + inactive: 'use Organization Medallion', + prompt() { + view.prompt = 'Use Organization Medallion?'; + + gen_action('yes'); + gen_action('no'); + }, + yes() { + const faction = get_active_faction(); + pay_hero_points(faction, 1); + game.used_medallions.push(ORGANIZATION_MEDALLION_ID); + + let { t, v } = get_active_node_args(); + + if (v > 0) { + v++; + } else { + v--; + } + + move_track(t, v); + resolve_active_and_proceed(); + }, + no() { + const { t, v } = get_active_node_args(); + + move_track(t, v); + resolve_active_and_proceed(); + }, +}; + +states.use_strategy_medallion = { + inactive: 'use Strategy Medallion', + prompt() { + view.prompt = 'Use Strategy Medallion?'; + + gen_action('yes'); + gen_action('no'); + }, + yes() { + game.used_medallions.push(STRATEGY_MEDALLION_ID); + const { f } = get_active_node_args(); + const faction = get_active_faction(); + + update_front(f, 1, faction); + + resolve_active_and_proceed(); + }, + no() { + resolve_active_and_proceed(); + }, +}; // #endrregion @@ -1208,6 +1405,27 @@ function pop_undo() { // #region GAME FUNCTIONS +function add_glory( + faction: FactionId, + amount: number, + indent: boolean = false +) { + for (let i = 0; i < amount; ++i) { + game.bag_of_glory.push(get_active_faction()); + } + + let text = + amount === 1 + ? `${faction_player_map[faction]} adds 1 token to the Bag of Glory` + : `${faction_player_map[faction]} adds ${amount} tokens to the Bag of Glory`; + + if (indent) { + logi(text); + } else { + log_h3(text); + } +} + // Check if Morale bonus is on so player can activate icon function check_activate_icon() { if (game.bonuses[MORALE_BONUS] === ON) { @@ -1281,6 +1499,7 @@ function end_of_turn() { Object.keys(game.fronts).forEach((front_id) => { game.fronts[front_id].contributions = []; }); + game.used_medallions = []; if (game.turn === 4) { end_of_year(); } else { @@ -1365,6 +1584,14 @@ function game_over(result: Player | 'None', victory: string) { log(game.victory); } +function get_hand_limit(faction: FactionId) { + let hand_limit = game.year; + if (game.medallions[faction].includes(INTELLIGENCE_MEDALLION_ID)) { + hand_limit++; + } + return hand_limit; +} + function resolve_fascist_test() { log_h2('Fascist Test', 'fascist'); @@ -1375,9 +1602,23 @@ function resolve_fascist_test() { (status !== DEFEAT && game.fronts[test.front].value >= test.value); if (test_passed) { log('The Test is passed'); + for (const faction of get_player_order()) { + let hero_points_gain = game.fronts[test.front].contributions.includes( + faction + ) + ? 2 + : 0; + if (can_use_medallion(PROPAGANDA_MEDALLION_ID, faction)) { + hero_points_gain += 2; + } + if (hero_points_gain > 0) { + gain_hero_points(faction, hero_points_gain); + } + } } else { log('The Test is failed'); } + const effect = test_passed ? test.pass : test.fail; const node = resolve_effect(effect); @@ -1421,7 +1662,6 @@ function resolve_final_bid() { // TODO: check for defeated / won fronts function get_fronts_to_add_to(target: string): FrontId[] { - console.log('get_fronts_to_add_to', target); if (target === CLOSEST_TO_DEFEAT || target === CLOSEST_TO_VICTORY) { return get_fronts_closest_to(target); } else if (target === ANY) { @@ -1434,9 +1674,11 @@ function get_fronts_to_add_to(target: string): FrontId[] { function get_max_value_for_track(track_id: number) { switch (track_id) { case LIBERTY: - return game.tracks[COLLECTIVIZATION] >= 8 ? 10 : 7; + const max_lib = game.tracks[COLLECTIVIZATION] >= 8 ? 10 : 7; + return Math.max(max_lib, game.tracks[LIBERTY]); case GOVERNMENT: - return game.tracks[FOREIGN_AID] >= 8 ? 10 : 7; + const max_gov = game.tracks[FOREIGN_AID] >= 8 ? 10 : 7; + return Math.max(max_gov, game.tracks[GOVERNMENT]); case COLLECTIVIZATION: case SOVIET_SUPPORT: case FOREIGN_AID: @@ -1448,7 +1690,8 @@ function get_max_value_for_track(track_id: number) { function get_min_value_for_track(track_id: number) { switch (track_id) { case GOVERNMENT: - return game.tracks[SOVIET_SUPPORT] >= 8 ? 4 : 1; + const min_gov = game.tracks[SOVIET_SUPPORT] >= 8 ? 4 : 1; + return Math.min(min_gov, game.tracks[GOVERNMENT]); case LIBERTY: case COLLECTIVIZATION: case SOVIET_SUPPORT: @@ -1476,8 +1719,8 @@ function move_track(track_id: number, change: number) { const current_value = game.tracks[track_id]; let new_value = current_value + change; new_value = Math.max(new_value, get_min_value_for_track(track_id)); - new_value = Math.min(new_value, get_max_value_for_track(track_id)); + game.tracks[track_id] = new_value; logi(`${get_track_name(track_id)} to ${new_value}`); @@ -1492,10 +1735,14 @@ function move_track(track_id: number, change: number) { const trigger = tracks[track_id].triggers[space_id]; if ( trigger !== null && - !game.triggered_track_effects[track_id].includes(space_id) + !game.triggered_track_effects.includes( + get_blank_marker_id(track_id, space_id) + ) ) { if (space_id !== 0) { - game.triggered_track_effects[track_id].push(space_id); + game.triggered_track_effects.push( + get_blank_marker_id(track_id, space_id) + ); } const node = resolve_effect(trigger); if (node !== null) { @@ -1510,6 +1757,33 @@ function pay_hero_points(faction: FactionId, amount: number) { game.hero_points.pool += amount; } +function can_use_medallion(medallion_id: number, faction?: FactionId) { + faction = faction === undefined ? get_active_faction() : faction; + const can_use = + game.medallions[faction].includes(medallion_id) && + !game.used_medallions.includes(medallion_id); + + if (medallion_id === ORGANIZATION_MEDALLION_ID) { + return can_use && game.hero_points[faction] > 0; + } else { + return can_use; + } +} + +function insert_use_organization_medallion_node( + track_id: number, + value: number +) { + const faction = get_active_faction(); + + insert_after_active_node( + create_leaf_node('use_organization_medallion', faction, { + t: track_id, + v: value, + }) + ); +} + function update_bonus(bonus_id: number, status: number) { if (game.bonuses[bonus_id] === status) { return; @@ -1557,6 +1831,19 @@ function update_front( game.fronts[front_id].contributions.push(faction_id); } + if ( + change > 0 && + faction_id !== undefined && + game.fronts[front_id].value < 10 && + can_use_medallion(STRATEGY_MEDALLION_ID) + ) { + insert_after_active_node( + create_leaf_node('use_strategy_medallion', get_active_faction(), { + f: front_id, + }) + ); + } + // Check victory / defeat on a front if (game.fronts[front_id].value >= 10) { victory_on_a_front(front_id); @@ -1597,33 +1884,45 @@ function create_effects_node(effects: Effect[]): EngineNode { } return accrued; }, []); - return { - t: seq_node, - c: nodes, - }; + return create_seq_node(nodes); +} + +function get_faction_to_resolve_effect(effect: Effect): FactionId { + if (!effect.faction) { + return get_active_faction(); + } + if (effect.faction === INITIATIVE_PLAYER) { + return game.initiative; + } + return effect.faction; } const effect_type_state_map: Record<string, string> = { attack: 'attack_front', bonus: 'change_bonus', front: 'add_to_front', + medallion: 'choose_medallion', track: 'move_track', }; function resolve_effect( - effect: Effect, - faction: FactionId = get_active_faction() + effect: Effect + // faction: FactionId = get_active_faction() // ): EngineNode | null { const args = { t: effect.target, v: effect.value, }; - let state = effect_type_state_map[effect.type]; + const faction = get_faction_to_resolve_effect(effect); + + // Default cases where effect type is mapped to a state + let state = effect_type_state_map[effect.type]; if (state !== undefined) { return create_leaf_node(state, faction, args); } + // Specific mapping based on target if ( effect.type === 'hero_points' && effect.target === PLAYER_WITH_MOST_HERO_POINTS @@ -1666,13 +1965,6 @@ function draw_card(deck: CardId[]): CardId { return c; } -function draw_item(ids: number[]): number { - let i = random(ids.length); - let r = ids[i] as CardId; - set_delete(ids, r); - return r; -} - function lose_hero_point(faction: FactionId, value: number) { const points_lost = Math.min(game.hero_points[faction], Math.abs(value)); game.hero_points.pool += points_lost; @@ -1749,8 +2041,6 @@ function log_h2(msg: string, player?: Player | 'fascist') { log_br(); } -log; - // function log_h2_active(msg: string) { // log_br(); // log('.h2 ' + msg); @@ -1790,6 +2080,10 @@ function get_active_faction_id(): FactionId { return player_faction_map[game.active]; } +function get_blank_marker_id(track_id: number, space_id: number) { + return track_id * 11 + space_id; +} + function get_faction_id(player: Player): FactionId { return player_faction_map[player]; } @@ -1918,7 +2212,10 @@ function list_deck(id: FactionId | 'fascist') { const card_list = id === 'fascist' ? fascist_decks[game.year] : faction_cards[id]; card_list.forEach((card) => { - if (id === 'fascist' && game.discard.f.includes(card)) { + if ( + id === 'fascist' && + (game.discard.f.includes(card) || game.current_events.includes(card)) + ) { return; } else if ( id !== 'fascist' && @@ -1933,6 +2230,16 @@ function list_deck(id: FactionId | 'fascist') { return deck; } +function draw_medallions() { + const medallion_ids = make_list(0, 8) as number[]; + for (let m = 0; m < 5; ++m) { + let i = random(medallion_ids.length); + let r = medallion_ids[i] as CardId; + set_delete(medallion_ids, r); + game.medallions.pool.push(r); + } +} + // #endregion // #region ARRAY |