diff options
author | Frans Bongers <fransbongers@franss-mbp.home> | 2024-12-27 19:45:21 +0100 |
---|---|---|
committer | Frans Bongers <fransbongers@franss-mbp.home> | 2024-12-27 19:45:21 +0100 |
commit | 9d0630a33e0358f943e68008823f355bceb71be1 (patch) | |
tree | bbb5b0cd5e1b8381d767ee1694f928f24f8a5ac9 | |
parent | 5dc1ee327e16431b6700f3977469943f002a0c7c (diff) | |
download | land-and-freedom-9d0630a33e0358f943e68008823f355bceb71be1.tar.gz |
setup for event effects
-rw-r--r-- | data.js | 49 | ||||
-rw-r--r-- | data.ts | 79 | ||||
-rw-r--r-- | rules.js | 354 | ||||
-rw-r--r-- | rules.ts | 480 | ||||
-rw-r--r-- | types.d.ts | 21 |
5 files changed, 835 insertions, 148 deletions
@@ -1,6 +1,6 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.ORGANIZATION_MEDALLION_ID = exports.ARCHIVES_MEDALLION_ID = exports.VOLUNTEERS_MEDALLION_ID = exports.INTELLIGENCE_MEDALLION_ID = exports.PROPAGANDA_MEDALLION_ID = exports.STRATEGY_MEDALLION_ID = exports.FRONTS = exports.DEFEAT = exports.VICTORY = exports.TRASH = exports.TOWARDS_CENTER = exports.AWAY_FROM_CENTER = exports.SELF = exports.PLAYER_WITH_MOST_HERO_POINTS = exports.OTHER_PLAYERS = exports.ON = exports.OFF = exports.TEAMWORK_BONUS = exports.MORALE_BONUS = exports.FOREIGN_AID = exports.SOVIET_SUPPORT = exports.INITIATIVE_PLAYER = exports.GOVERNMENT = exports.COLLECTIVIZATION = exports.CLOSEST_TO_VICTORY = exports.CLOSEST_TO_DEFEAT = exports.LIBERTY = exports.ANY = exports.MODERATES_ID = exports.COMMUNISTS_ID = exports.ANARCHISTS_ID = exports.MODERATE = exports.COMMUNIST = exports.ANARCHIST = void 0; +exports.LIBERTY_OR_COLLECTIVIZATION = exports.COMMUNIST_EXTRA_HERO_POINT = exports.ANARCHIST_EXTRA_HERO_POINT = exports.NORTHERN = exports.SOUTHERN = exports.ARAGON = exports.MADRID = exports.ORGANIZATION_MEDALLION_ID = exports.ARCHIVES_MEDALLION_ID = exports.VOLUNTEERS_MEDALLION_ID = exports.INTELLIGENCE_MEDALLION_ID = exports.PROPAGANDA_MEDALLION_ID = exports.STRATEGY_MEDALLION_ID = exports.FRONTS = exports.DEFEAT = exports.VICTORY = exports.TRASH = exports.TOWARDS_CENTER = exports.AWAY_FROM_CENTER = exports.SELF = exports.PLAYER_WITH_MOST_HERO_POINTS = exports.OTHER_PLAYERS = exports.ON = exports.OFF = exports.TEAMWORK_BONUS = exports.MORALE_BONUS = exports.FOREIGN_AID = exports.SOVIET_SUPPORT = exports.INITIATIVE_PLAYER = exports.GOVERNMENT = exports.COLLECTIVIZATION = exports.CLOSEST_TO_VICTORY = exports.CLOSEST_TO_DEFEAT = exports.LIBERTY = exports.ANY = exports.MODERATES_ID = exports.COMMUNISTS_ID = exports.ANARCHISTS_ID = exports.MODERATE = exports.COMMUNIST = exports.ANARCHIST = exports.ALL_PLAYERS = void 0; exports.create_effect = create_effect; const LIBERTY = 0; exports.LIBERTY = LIBERTY; @@ -12,6 +12,8 @@ const SOVIET_SUPPORT = 3; exports.SOVIET_SUPPORT = SOVIET_SUPPORT; const FOREIGN_AID = 4; exports.FOREIGN_AID = FOREIGN_AID; +const LIBERTY_OR_COLLECTIVIZATION = 5; +exports.LIBERTY_OR_COLLECTIVIZATION = LIBERTY_OR_COLLECTIVIZATION; const MORALE_BONUS = 0; exports.MORALE_BONUS = MORALE_BONUS; const TEAMWORK_BONUS = 1; @@ -25,10 +27,15 @@ exports.PLAYER_WITH_MOST_HERO_POINTS = PLAYER_WITH_MOST_HERO_POINTS; const INITIATIVE_PLAYER = 'i'; exports.INITIATIVE_PLAYER = INITIATIVE_PLAYER; const ALL_PLAYERS = 'all'; +exports.ALL_PLAYERS = ALL_PLAYERS; const ARAGON = 'a'; +exports.ARAGON = ARAGON; const MADRID = 'm'; +exports.MADRID = MADRID; const NORTHERN = 'n'; +exports.NORTHERN = NORTHERN; const SOUTHERN = 's'; +exports.SOUTHERN = SOUTHERN; const CLOSEST_TO_DEFEAT = 'd'; exports.CLOSEST_TO_DEFEAT = CLOSEST_TO_DEFEAT; const CLOSEST_TO_VICTORY = 'v'; @@ -75,6 +82,10 @@ const ARCHIVES_MEDALLION_ID = 7; exports.ARCHIVES_MEDALLION_ID = ARCHIVES_MEDALLION_ID; const ORGANIZATION_MEDALLION_ID = 8; exports.ORGANIZATION_MEDALLION_ID = ORGANIZATION_MEDALLION_ID; +const ANARCHIST_EXTRA_HERO_POINT = 0; +exports.ANARCHIST_EXTRA_HERO_POINT = ANARCHIST_EXTRA_HERO_POINT; +const COMMUNIST_EXTRA_HERO_POINT = 1; +exports.COMMUNIST_EXTRA_HERO_POINT = COMMUNIST_EXTRA_HERO_POINT; function create_effect(type, target, value, faction) { return { type, @@ -90,6 +101,7 @@ const data = { id: 1, effects: [ create_effect('track', FOREIGN_AID, 2), + create_effect('function', 'card1_event2', 0), create_effect('track', SOVIET_SUPPORT, -1), ], icons: ['foreign_aid', 'add_to_front', 'd_soviet_support'], @@ -113,6 +125,7 @@ const data = { id: 3, effects: [ create_effect('front', CLOSEST_TO_DEFEAT, 3), + create_effect('function', 'card3_event2', 0), create_effect('draw_card', SELF, 1), ], icons: ['add_to_front', 'government', 'draw_card'], @@ -149,6 +162,7 @@ const data = { id: 6, effects: [ create_effect('bonus', ANY, ON), + create_effect('state', 'remove_attack_from_fronts', 6), create_effect('track', GOVERNMENT, 1), create_effect('draw_card', SELF, 1), ], @@ -209,7 +223,8 @@ const data = { id: 10, effects: [ create_effect('track', FOREIGN_AID, 4), - create_effect('add_to_tableau', SELF, 1), + create_effect('function', 'card10_event2', 0), + create_effect('add_card_to_tableau', ANY, 1), ], icons: ['foreign_aid', 'draw_card'], strength: 1, @@ -231,6 +246,7 @@ const data = { { id: 12, effects: [ + create_effect('take_hero_points', OTHER_PLAYERS, 2), create_effect('track', SOVIET_SUPPORT, -3), create_effect('track', COLLECTIVIZATION, -3), ], @@ -267,6 +283,7 @@ const data = { { id: 15, effects: [ + create_effect('track', LIBERTY_OR_COLLECTIVIZATION, -4), create_effect('track', FOREIGN_AID, 2), create_effect('return_card', TRASH, 1), ], @@ -277,7 +294,10 @@ const data = { }, { id: 16, - effects: [], + effects: [ + create_effect('state', 'move_attacks', 2), + create_effect('function', 'card16_event2', 0), + ], icons: ['add_to_front', 'foreign_aid'], strength: 1, title: 'PUBLICIZE FASCIST WAR CRIMES', @@ -288,6 +308,7 @@ const data = { effects: [ create_effect('track', FOREIGN_AID, 1), create_effect('track', GOVERNMENT, 1), + create_effect('function', 'card17_event3', 0), ], icons: ['foreign_aid', 'government', 'd_collectivization'], strength: 1, @@ -323,6 +344,7 @@ const data = { effects: [ create_effect('bonus', ANY, ON), create_effect('track', SOVIET_SUPPORT, 2), + create_effect('function', 'card20_event3', 0), ], icons: ['teamwork_on', 'soviet_support', 'add_to_front'], strength: 2, @@ -347,6 +369,7 @@ const data = { effects: [ create_effect('track', LIBERTY, -2), create_effect('track', SOVIET_SUPPORT, 1), + create_effect('function', 'card22_event3', 0), ], icons: ['d_liberty', 'soviet_support', 'government'], strength: 2, @@ -356,6 +379,7 @@ const data = { { id: 23, effects: [ + create_effect('function', 'card23_event1', 0), create_effect('track', FOREIGN_AID, -2), create_effect('draw_card', SELF, 2), ], @@ -394,6 +418,8 @@ const data = { { id: 26, effects: [ + create_effect('function', 'card26_event1', 0), + create_effect('front', MADRID, 1), create_effect('track', LIBERTY, -2), create_effect('track', GOVERNMENT, -1), ], @@ -432,6 +458,7 @@ const data = { id: 29, effects: [ create_effect('track', GOVERNMENT, -2), + create_effect('function', 'card29_event2', 0), ], icons: ['government', 'd_liberty'], strength: 1, @@ -465,8 +492,10 @@ const data = { { id: 32, effects: [ + create_effect('take_hero_points', OTHER_PLAYERS, 1), create_effect('front', ANY, 1), create_effect('track', SOVIET_SUPPORT, 1), + create_effect('track', LIBERTY_OR_COLLECTIVIZATION, -3), ], icons: [ 'add_to_front', @@ -507,6 +536,7 @@ const data = { id: 35, effects: [ create_effect('front', ANY, 2), + create_effect('function', 'card35_event2', 0), create_effect('draw_card', SELF, 2), ], icons: ['add_to_front', 'soviet_support', 'draw_card'], @@ -520,7 +550,7 @@ const data = { create_effect('track', SOVIET_SUPPORT, 2), create_effect('track', COLLECTIVIZATION, -3), create_effect('draw_card', SELF, 2), - create_effect('add_to_tableau', ANY, 1), + create_effect('add_card_to_tableau', ANY, 1), ], icons: ['soviet_support', 'd_collectivization', 'draw_card'], strength: 1, @@ -562,6 +592,7 @@ const data = { { id: 39, effects: [ + create_effect('state', 'remove_attack_from_fronts', 39), create_effect('track', COLLECTIVIZATION, 1), create_effect('draw_card', SELF, 2), ], @@ -600,6 +631,7 @@ const data = { create_effect('track', LIBERTY, 2), create_effect('front', ARAGON, 2), create_effect('front', MADRID, 1), + create_effect('function', 'card42_event3', 0), ], icons: ['liberty', 'add_to_front'], strength: 2, @@ -623,6 +655,7 @@ const data = { { id: 44, effects: [ + create_effect('take_hero_points', OTHER_PLAYERS, 1), create_effect('front', MADRID, 2), create_effect('track', LIBERTY, 1), create_effect('track', FOREIGN_AID, -1), @@ -636,6 +669,7 @@ const data = { id: 45, effects: [ create_effect('front', ANY, 2), + create_effect('function', 'card45_event2', 0), create_effect('track', FOREIGN_AID, -3), ], icons: ['add_to_front', 'collectivization', 'd_foreign_aid'], @@ -648,6 +682,7 @@ const data = { effects: [ create_effect('bonus', ANY, ON), create_effect('track', LIBERTY, 2), + create_effect('state', 'peek_fascist_cards', 0), ], icons: ['teamwork_on', 'liberty', 'add_to_front'], strength: 1, @@ -694,6 +729,7 @@ const data = { id: 50, effects: [ create_effect('track', COLLECTIVIZATION, 1), + create_effect('function', 'card50_event2', 0), create_effect('track', FOREIGN_AID, -1), ], icons: ['collectivization', 'add_to_front', 'd_foreign_aid'], @@ -717,6 +753,7 @@ const data = { id: 52, effects: [ create_effect('front', ANY, 1), + create_effect('track', LIBERTY_OR_COLLECTIVIZATION, 3), create_effect('track', GOVERNMENT, TOWARDS_CENTER), ], icons: [ @@ -733,6 +770,7 @@ const data = { id: 53, effects: [ create_effect('track', LIBERTY, 1), + create_effect('function', 'card53_event2', 0), create_effect('hero_points', SELF, 1), ], icons: ['liberty', 'add_to_front'], @@ -743,8 +781,9 @@ const data = { { id: 54, effects: [ + create_effect('function', 'card54_event1', 0), create_effect('track', SOVIET_SUPPORT, -1), - create_effect('add_to_tableau', ANY, 1), + create_effect('add_card_to_tableau', ANY, 1), ], icons: ['liberty', 'd_soviet_support', 'draw_card'], strength: 1, @@ -5,6 +5,7 @@ const COLLECTIVIZATION = 1; const GOVERNMENT = 2; const SOVIET_SUPPORT = 3; const FOREIGN_AID = 4; +const LIBERTY_OR_COLLECTIVIZATION = 5; const MORALE_BONUS = 0; const TEAMWORK_BONUS = 1; @@ -32,9 +33,9 @@ const SELF = 'self'; const OTHER_PLAYERS = 'other'; const TRASH = 'trash'; -const ANARCHISTS_ID = 'a' as FactionId; -const COMMUNISTS_ID = 'c' as FactionId; -const MODERATES_ID = 'm' as FactionId; +const ANARCHISTS_ID: FactionId = 'a'; +const COMMUNISTS_ID: FactionId = 'c'; +const MODERATES_ID: FactionId = 'm'; const ANARCHIST = 'Anarchist' as Player; const COMMUNIST = 'Communist' as Player; @@ -43,6 +44,7 @@ const MODERATE = 'Moderate' as Player; const VICTORY = 'Victory'; const DEFEAT = 'Defeat'; +// Medallion ids const STRATEGY_MEDALLION_ID = 3; const PROPAGANDA_MEDALLION_ID = 4; const INTELLIGENCE_MEDALLION_ID = 5; @@ -50,6 +52,10 @@ const VOLUNTEERS_MEDALLION_ID = 6; const ARCHIVES_MEDALLION_ID = 7; const ORGANIZATION_MEDALLION_ID = 8; +// Abilities granted by cards +const ANARCHIST_EXTRA_HERO_POINT = 0; +const COMMUNIST_EXTRA_HERO_POINT = 1; + function create_effect( type: Effect['type'], target: Effect['target'], @@ -66,6 +72,7 @@ function create_effect( export { create_effect, + ALL_PLAYERS, ANARCHIST, COMMUNIST, MODERATE, @@ -100,6 +107,13 @@ export { VOLUNTEERS_MEDALLION_ID, ARCHIVES_MEDALLION_ID, ORGANIZATION_MEDALLION_ID, + MADRID, + ARAGON, + SOUTHERN, + NORTHERN, + ANARCHIST_EXTRA_HERO_POINT, + COMMUNIST_EXTRA_HERO_POINT, + LIBERTY_OR_COLLECTIVIZATION, }; const data: StaticData = { @@ -109,7 +123,7 @@ const data: StaticData = { id: 1, effects: [ create_effect('track', FOREIGN_AID, 2), - // create_effect('track', FOREIGN_AID, 2), // Conditional support + create_effect('function', 'card1_event2', 0), create_effect('track', SOVIET_SUPPORT, -1), ], icons: ['foreign_aid', 'add_to_front', 'd_soviet_support'], @@ -133,7 +147,7 @@ const data: StaticData = { id: 3, effects: [ create_effect('front', CLOSEST_TO_DEFEAT, 3), - // create_effect('track', FOREIGN_AID, 2), // conditional effect + create_effect('function', 'card3_event2', 0), create_effect('draw_card', SELF, 1), ], icons: ['add_to_front', 'government', 'draw_card'], @@ -170,7 +184,7 @@ const data: StaticData = { id: 6, effects: [ create_effect('bonus', ANY, ON), - // create_effect('front', ANY, ON), // REMOVE attacks from front + create_effect('state', 'remove_attack_from_fronts', 6), // REMOVE attacks from front create_effect('track', GOVERNMENT, 1), create_effect('draw_card', SELF, 1), ], @@ -231,8 +245,8 @@ const data: StaticData = { id: 10, effects: [ create_effect('track', FOREIGN_AID, 4), - // create_effect('track', FOREIGN_AID, 3) // conditional draw cards - create_effect('add_to_tableau', SELF, 1), + create_effect('function', 'card10_event2', 0), + create_effect('add_card_to_tableau', ANY, 1), ], icons: ['foreign_aid', 'draw_card'], strength: 1, @@ -254,7 +268,7 @@ const data: StaticData = { { id: 12, effects: [ - // create_effect('hero_points', OTHER_PLAYERS, -2), // take from other player + create_effect('take_hero_points', OTHER_PLAYERS, 2), create_effect('track', SOVIET_SUPPORT, -3), create_effect('track', COLLECTIVIZATION, -3), ], @@ -291,7 +305,7 @@ const data: StaticData = { { id: 15, effects: [ - // create_effect('track', ) Choose track, + create_effect('track', LIBERTY_OR_COLLECTIVIZATION, -4), create_effect('track', FOREIGN_AID, 2), create_effect('return_card', TRASH, 1), ], @@ -303,8 +317,8 @@ const data: StaticData = { { id: 16, effects: [ - // create_effect('front', ANY, -2) // move attacks - // create_effect('track', FOREIGN_AID, 4) // conditional + create_effect('state', 'move_attacks', 2), // move attacks + create_effect('function', 'card16_event2', 0), ], icons: ['add_to_front', 'foreign_aid'], strength: 1, @@ -316,7 +330,7 @@ const data: StaticData = { effects: [ create_effect('track', FOREIGN_AID, 1), create_effect('track', GOVERNMENT, 1), - // create_effect('track', COLLECTIVIZATION,-4) // conditional + create_effect('function', 'card17_event3', 0), ], icons: ['foreign_aid', 'government', 'd_collectivization'], strength: 1, @@ -352,7 +366,7 @@ const data: StaticData = { effects: [ create_effect('bonus', ANY, ON), create_effect('track', SOVIET_SUPPORT, 2), - // create_effect('front') // conditional on track + create_effect('function', 'card20_event3', 0), ], icons: ['teamwork_on', 'soviet_support', 'add_to_front'], strength: 2, @@ -377,7 +391,7 @@ const data: StaticData = { effects: [ create_effect('track', LIBERTY, -2), create_effect('track', SOVIET_SUPPORT, 1), - // create_effect('track', GOVERNMENT, -2) // conditional + create_effect('function', 'card22_event3', 0), ], icons: ['d_liberty', 'soviet_support', 'government'], strength: 2, @@ -387,7 +401,7 @@ const data: StaticData = { { id: 23, effects: [ - // create_effect('front', ANY, 4) // conditional on track + create_effect('function', 'card23_event1', 0), create_effect('track', FOREIGN_AID, -2), create_effect('draw_card', SELF, 2), ], @@ -426,7 +440,8 @@ const data: StaticData = { { id: 26, effects: [ - // create_effect('front', MADRID, 1), // ability active + create_effect('function', 'card26_event1', 0), + create_effect('front', MADRID, 1), create_effect('track', LIBERTY, -2), create_effect('track', GOVERNMENT, -1), ], @@ -465,7 +480,7 @@ const data: StaticData = { id: 29, effects: [ create_effect('track', GOVERNMENT, -2), - // create_effect('track', LIBERTY, -3) // conditional + create_effect('function', 'card29_event2', 0), ], icons: ['government', 'd_liberty'], strength: 1, @@ -499,10 +514,10 @@ const data: StaticData = { { id: 32, effects: [ - // create_effect('hero_points', OTHER_PLAYERS, 1) // take 1 from others + create_effect('take_hero_points', OTHER_PLAYERS, 1), create_effect('front', ANY, 1), create_effect('track', SOVIET_SUPPORT, 1), - // create_effect('track') // choose one of two tracks + create_effect('track', LIBERTY_OR_COLLECTIVIZATION, -3), ], icons: [ 'add_to_front', @@ -543,7 +558,7 @@ const data: StaticData = { id: 35, effects: [ create_effect('front', ANY, 2), - // create_effect('track', SOVIET_SUPPORT,2) // conditional + create_effect('function', 'card35_event2', 0), create_effect('draw_card', SELF, 2), ], icons: ['add_to_front', 'soviet_support', 'draw_card'], @@ -557,7 +572,7 @@ const data: StaticData = { create_effect('track', SOVIET_SUPPORT, 2), create_effect('track', COLLECTIVIZATION, -3), create_effect('draw_card', SELF, 2), - create_effect('add_to_tableau', ANY, 1), + create_effect('add_card_to_tableau', ANY, 1), ], icons: ['soviet_support', 'd_collectivization', 'draw_card'], strength: 1, @@ -599,7 +614,7 @@ const data: StaticData = { { id: 39, effects: [ - // create_effect('move attacks ') + create_effect('state', 'remove_attack_from_fronts', 39), // REMOVE attacks from front create_effect('track', COLLECTIVIZATION, 1), create_effect('draw_card', SELF, 2), ], @@ -638,7 +653,7 @@ const data: StaticData = { create_effect('track', LIBERTY, 2), create_effect('front', ARAGON, 2), create_effect('front', MADRID, 1), - // create_effect('ability') // activate ability + create_effect('function', 'card42_event3', 0), ], icons: ['liberty', 'add_to_front'], strength: 2, @@ -662,7 +677,7 @@ const data: StaticData = { { id: 44, effects: [ - // create_effect('hero_points', OTHER_PLAYERS, -1) // take from other player + create_effect('take_hero_points', OTHER_PLAYERS, 1), create_effect('front', MADRID, 2), create_effect('track', LIBERTY, 1), create_effect('track', FOREIGN_AID, -1), @@ -676,7 +691,7 @@ const data: StaticData = { id: 45, effects: [ create_effect('front', ANY, 2), - // create_effect('track', COLLECTIVIZATION, 1) // conditional + create_effect('function', 'card45_event2', 0), create_effect('track', FOREIGN_AID, -3), ], icons: ['add_to_front', 'collectivization', 'd_foreign_aid'], @@ -689,7 +704,7 @@ const data: StaticData = { effects: [ create_effect('bonus', ANY, ON), create_effect('track', LIBERTY, 2), - // create_effect('special') // Peek at Fascist cards + create_effect('state', 'peek_fascist_cards', 0), ], icons: ['teamwork_on', 'liberty', 'add_to_front'], strength: 1, @@ -736,7 +751,7 @@ const data: StaticData = { id: 50, effects: [ create_effect('track', COLLECTIVIZATION, 1), - // create_effect('front', ARAGON, 3) // conditional + create_effect('function', 'card50_event2', 0), create_effect('track', FOREIGN_AID, -1), ], icons: ['collectivization', 'add_to_front', 'd_foreign_aid'], @@ -760,7 +775,7 @@ const data: StaticData = { id: 52, effects: [ create_effect('front', ANY, 1), - // create_effect('track') // choose + create_effect('track', LIBERTY_OR_COLLECTIVIZATION, 3), create_effect('track', GOVERNMENT, TOWARDS_CENTER), ], icons: [ @@ -777,7 +792,7 @@ const data: StaticData = { id: 53, effects: [ create_effect('track', LIBERTY, 1), - // create_effect('front', ANY, 3) // conditional + create_effect('function', 'card53_event2', 0), create_effect('hero_points', SELF, 1), ], icons: ['liberty', 'add_to_front'], @@ -788,9 +803,9 @@ const data: StaticData = { { id: 54, effects: [ - // create_effect('track', LIBERTY, 3) // conditional + create_effect('function', 'card54_event1', 0), create_effect('track', SOVIET_SUPPORT, -1), - create_effect('add_to_tableau', ANY, 1), + create_effect('add_card_to_tableau', ANY, 1), ], icons: ['liberty', 'd_soviet_support', 'draw_card'], strength: 1, @@ -10,9 +10,9 @@ let game = {}; var view = {}; const role_ids = [data_1.ANARCHISTS_ID, data_1.COMMUNISTS_ID, data_1.MODERATES_ID]; const faction_player_map = { - [data_1.ANARCHISTS_ID]: data_1.ANARCHIST, - [data_1.COMMUNISTS_ID]: data_1.COMMUNIST, - [data_1.MODERATES_ID]: data_1.MODERATE, + a: data_1.ANARCHIST, + c: data_1.COMMUNIST, + m: data_1.MODERATE, }; const player_faction_map = { [data_1.ANARCHIST]: data_1.ANARCHISTS_ID, @@ -160,6 +160,22 @@ const engine_functions = { start_year, resolve_fascist_test, resolve_final_bid, + card1_event2, + card3_event2, + card10_event2, + card16_event2, + card17_event3, + card20_event3, + card22_event3, + card23_event1, + card26_event1, + card29_event2, + card35_event2, + card42_event3, + card45_event2, + card50_event2, + card53_event2, + card54_event1, }; function get_active(engine) { for (let i of engine) { @@ -287,21 +303,22 @@ function setup(seed, _scenario, _options) { seed: seed, state: null, active: data_1.ANARCHIST, + active_abilities: [], bag_of_glory: [data_1.ANARCHISTS_ID, data_1.COMMUNISTS_ID, data_1.MODERATES_ID], blank_markers: [[], [], [], [], []], bonuses: [data_1.ON, data_1.ON], current_events: [], discard: { - [data_1.ANARCHISTS_ID]: [], - [data_1.COMMUNISTS_ID]: [], - [data_1.MODERATES_ID]: [], + a: [], + c: [], + m: [], f: [], }, engine: [], final_bid: { - [data_1.ANARCHISTS_ID]: [], - [data_1.COMMUNISTS_ID]: [], - [data_1.MODERATES_ID]: [], + a: [], + c: [], + m: [], }, fronts: { a: { @@ -327,38 +344,38 @@ function setup(seed, _scenario, _options) { }, glory: [], hands: { - [data_1.ANARCHISTS_ID]: [], - [data_1.COMMUNISTS_ID]: [], - [data_1.MODERATES_ID]: [], + a: [], + c: [], + m: [], }, hero_points: { - [data_1.ANARCHISTS_ID]: 2, - [data_1.COMMUNISTS_ID]: 2, - [data_1.MODERATES_ID]: 0, + a: 2, + c: 2, + m: 0, pool: 14, }, chosen_cards: { - [data_1.ANARCHISTS_ID]: null, - [data_1.COMMUNISTS_ID]: null, - [data_1.MODERATES_ID]: null, + a: null, + c: null, + m: null, }, initiative: data_1.MODERATES_ID, medallions: { - [data_1.ANARCHISTS_ID]: [], - [data_1.COMMUNISTS_ID]: [], - [data_1.MODERATES_ID]: [], + a: [], + c: [], + m: [], pool: [], }, tableaus: { - [data_1.ANARCHISTS_ID]: [], - [data_1.COMMUNISTS_ID]: [], - [data_1.MODERATES_ID]: [], + a: [], + c: [], + m: [], }, tracks: [5, 5, 6, 3, 3], trash: { - [data_1.ANARCHISTS_ID]: [], - [data_1.COMMUNISTS_ID]: [], - [data_1.MODERATES_ID]: [], + a: [], + c: [], + m: [], }, triggered_track_effects: [], log: [], @@ -409,7 +426,7 @@ function start_turn() { log_h2('Fascist Event', 'fascist'); log(card.title); game.engine = card.effects.map((effect) => resolve_effect(effect)); - if (game.year === 3 && game.turn === 1) { + if (game.year === 3 && game.turn === 4) { game.engine.push(create_function_node('setup_final_bid')); } else { @@ -548,6 +565,23 @@ states.activate_icon = { resolve_active_and_proceed(); }, }; +states.add_card_to_tableau = { + inactive: 'add a card to their tableau', + prompt() { + view.prompt = 'Choose a card to add to your tableau'; + for (const c of game.hands[get_active_faction()]) { + gen_action_card(c); + } + }, + card(c) { + const faction_id = get_active_faction(); + const card = cards[c]; + array_remove(game.hands[faction_id], game.hands[faction_id].indexOf(c)); + game.tableaus[faction_id].push(c); + logi(`${faction_player_map[faction_id]} adds ${card.title} to their tableau`); + resolve_active_and_proceed(); + }, +}; states.add_glory = { inactive: 'add tokens to the Bag of Glory', prompt() { @@ -872,14 +906,24 @@ states.gain_hero_points = { inactive: 'gain Hero Points', prompt() { const value = get_active_node_args().v; - view.prompt = value > 1 ? `Gain ${value} Hero Points` : 'Gain 1 Hero Point'; - gen_action('gain_hp'); + if (game.hero_points.pool > 0) { + view.prompt = + value > 1 ? `Gain ${value} Hero Points` : 'Gain 1 Hero Point'; + gen_action('gain_hp'); + } + else { + view.prompt = 'No Hero Points available in pool. You must skip'; + gen_action('skip'); + } }, gain_hp() { const value = get_active_node_args().v; gain_hero_points(get_active_faction(), value); resolve_active_and_proceed(); }, + skip() { + resolve_active_and_proceed(); + }, }; states.game_over = { get inactive() { @@ -917,13 +961,21 @@ states.lose_hero_points = { resolve_active_and_proceed(); }, }; +states.move_attacks = { + inactive: 'move attacks', + prompt() { + view.prompt = 'Choose a Front'; + }, +}; states.move_track = { inactive: 'move a Track', prompt() { const node = get_active_node(); const track = node.a.t; const value = node.a.v; - const name = tracks[track].name; + const name = track === data_1.LIBERTY_OR_COLLECTIVIZATION + ? 'Liberty OR Collectivization' + : tracks[track].name; view.prompt = `Move ${name} ${value > 0 ? 'up' : 'down'}`; if (track === data_1.GOVERNMENT && value === data_1.TOWARDS_CENTER) { view.prompt = `Move ${name} towards center`; @@ -931,7 +983,13 @@ states.move_track = { else if (track === data_1.GOVERNMENT && value === data_1.AWAY_FROM_CENTER) { view.prompt = `Move ${name} away from center`; } - gen_action_standee(track); + if (track === data_1.LIBERTY_OR_COLLECTIVIZATION) { + gen_action_standee(data_1.LIBERTY); + gen_action_standee(data_1.COLLECTIVIZATION); + } + else { + gen_action_standee(track); + } }, standee(s) { const node = get_active_node(); @@ -964,6 +1022,12 @@ states.move_track_up_or_down = { resolve_active_and_proceed(); }, }; +states.peek_fascist_cards = { + inactive: 'peek at Fascist cards', + prompt() { + view.prompt = 'Choose one card to return to the top of the deck'; + }, +}; states.player_turn = { inactive: 'play their turn', prompt() { @@ -1039,6 +1103,18 @@ states.remove_blank_marker = { resolve_active_and_proceed(); }, }; +states.remove_attack_from_fronts = { + inactive: 'remove attacks', + prompt() { + view.prompt = 'Choose a front to remove an attack'; + }, +}; +states.return_card = { + inactive: 'return a card', + prompt() { + view.prompt = 'Choose a card to return'; + }, +}; states.spend_hero_points = { inactive: 'spend Hero points', prompt() { @@ -1134,6 +1210,23 @@ states.spend_hero_points = { resolve_active_and_proceed(); }, }; +states.swap_card_tableau_hand = { + inactive: 'swap cards', + prompt() { + view.prompt = 'Choose cards'; + const faction = get_active_faction(); + for (const c of game.hands[faction]) { + gen_action_card(c); + } + }, + card(c) { }, +}; +states.take_hero_points = { + inactive: 'take Hero Points', + prompt() { + view.prompt = 'Choose a player to take Hero Points from'; + }, +}; states.use_organization_medallion = { inactive: 'use Organization Medallion', prompt() { @@ -1179,6 +1272,87 @@ states.use_strategy_medallion = { resolve_active_and_proceed(); }, }; +function card1_event2() { + const value = game.tracks[data_1.FOREIGN_AID] >= 6 ? 3 : 2; + insert_after_active_node(resolve_effect((0, data_1.create_effect)('track', data_1.FOREIGN_AID, value))); + resolve_active_and_proceed(); +} +function card3_event2() { + const value = game.tracks[data_1.FOREIGN_AID] >= 8 ? 2 : 1; + insert_after_active_node(resolve_effect((0, data_1.create_effect)('track', data_1.GOVERNMENT, value))); + resolve_active_and_proceed(); +} +function card10_event2() { + if (game.tracks[data_1.FOREIGN_AID] >= 6) { + resolve_effect((0, data_1.create_effect)('draw_card', data_1.SELF, 2)); + } + resolve_active_and_proceed(); +} +function card16_event2() { + const value = game.tracks[data_1.GOVERNMENT] >= 6 ? 4 : 3; + insert_after_active_node(resolve_effect((0, data_1.create_effect)('track', data_1.FOREIGN_AID, value))); + resolve_active_and_proceed(); +} +function card17_event3() { + const value = game.tracks[data_1.GOVERNMENT] >= 6 ? -4 : -3; + insert_after_active_node(resolve_effect((0, data_1.create_effect)('track', data_1.COLLECTIVIZATION, value))); + resolve_active_and_proceed(); +} +function card20_event3() { + const value = game.tracks[data_1.SOVIET_SUPPORT] >= 6 ? 2 : 1; + insert_after_active_node(create_seq_node([ + resolve_effect((0, data_1.create_effect)('front', data_1.MADRID, value)), + resolve_effect((0, data_1.create_effect)('front', data_1.SOUTHERN, value)), + ])); + resolve_active_and_proceed(); +} +function card22_event3() { + const value = game.tracks[data_1.SOVIET_SUPPORT] >= 8 ? -3 : -3; + insert_after_active_node(resolve_effect((0, data_1.create_effect)('track', data_1.GOVERNMENT, value))); + resolve_active_and_proceed(); +} +function card23_event1() { + const value = game.tracks[data_1.SOVIET_SUPPORT] >= 6 ? 4 : 3; + insert_after_active_node(resolve_effect((0, data_1.create_effect)('front', data_1.ANY, value))); + resolve_active_and_proceed(); +} +function card26_event1() { + game.active_abilities.push(data_1.COMMUNIST_EXTRA_HERO_POINT); +} +function card29_event2() { + const value = game.tracks[data_1.GOVERNMENT] <= 5 ? -3 : -2; + insert_after_active_node(resolve_effect((0, data_1.create_effect)('track', data_1.LIBERTY, value))); + resolve_active_and_proceed(); +} +function card35_event2() { + const value = game.tracks[data_1.GOVERNMENT] <= 5 ? 2 : 1; + insert_after_active_node(resolve_effect((0, data_1.create_effect)('track', data_1.SOVIET_SUPPORT, value))); + resolve_active_and_proceed(); +} +function card42_event3() { + game.active_abilities.push(data_1.ANARCHIST_EXTRA_HERO_POINT); +} +function card45_event2() { + if (game.tracks[data_1.LIBERTY] >= 6) { + insert_after_active_node(resolve_effect((0, data_1.create_effect)('track', data_1.COLLECTIVIZATION, 1))); + } + resolve_active_and_proceed(); +} +function card50_event2() { + const value = game.tracks[data_1.COLLECTIVIZATION] >= 8 ? 3 : 2; + insert_after_active_node(resolve_effect((0, data_1.create_effect)('front', data_1.ARAGON, value))); + resolve_active_and_proceed(); +} +function card53_event2() { + const value = game.tracks[data_1.LIBERTY] >= 8 ? 3 : 2; + insert_after_active_node(resolve_effect((0, data_1.create_effect)('front', data_1.ANY, value))); + resolve_active_and_proceed(); +} +function card54_event1() { + const value = game.tracks[data_1.COLLECTIVIZATION] >= 8 ? 3 : 2; + insert_after_active_node(resolve_effect((0, data_1.create_effect)('track', data_1.LIBERTY, value))); + resolve_active_and_proceed(); +} function add_glory(faction, amount, indent = false) { for (let i = 0; i < amount; ++i) { game.bag_of_glory.push(get_active_faction()); @@ -1260,6 +1434,7 @@ function end_of_turn() { Object.keys(game.fronts).forEach((front_id) => { game.fronts[front_id].contributions = []; }); + game.active_abilities = []; game.used_medallions = []; if (game.turn === 4) { end_of_year(); @@ -1283,9 +1458,9 @@ function end_of_year() { } const glory_to_draw = [0, 1, 2, 5]; const glory_this_year = { - [data_1.ANARCHISTS_ID]: false, - [data_1.COMMUNISTS_ID]: false, - [data_1.MODERATES_ID]: false, + a: false, + c: false, + m: false, }; for (let i = 0; i < glory_to_draw[game.year]; ++i) { const index = random(game.bag_of_glory.length); @@ -1315,6 +1490,12 @@ function gain_hero_points(faction_id, value) { if (game.hero_points.pool === 0) { return; } + if ((faction_id === data_1.ANARCHISTS_ID && + (game.active_abilities || []).includes(data_1.ANARCHIST_EXTRA_HERO_POINT)) || + (faction_id === data_1.COMMUNISTS_ID && + (game.active_abilities || []).includes(data_1.COMMUNIST_EXTRA_HERO_POINT))) { + value++; + } const gain = Math.min(game.hero_points.pool, value); game.hero_points.pool -= gain; game.hero_points[faction_id] += gain; @@ -1571,10 +1752,15 @@ function get_faction_to_resolve_effect(effect) { return effect.faction; } const effect_type_state_map = { + add_card_to_tableau: 'add_card_to_tableau', attack: 'attack_front', bonus: 'change_bonus', front: 'add_to_front', medallion: 'choose_medallion', + remove_blank_marker: 'remove_blank_marker', + return_card: 'return_card', + swap_card_tableau_hand: 'swap_card_tableau_hand', + take_hero_points: 'take_hero_points', track: 'move_track', }; function resolve_effect(effect) { @@ -1583,25 +1769,99 @@ function resolve_effect(effect) { v: effect.value, }; const faction = get_faction_to_resolve_effect(effect); + if (effect.type === 'function') { + return create_function_node(effect.target); + } + if (effect.type === 'state') { + return create_leaf_node(effect.target, faction, { + v: effect.value, + }); + } let state = effect_type_state_map[effect.type]; if (state !== undefined) { return create_leaf_node(state, faction, args); } - if (effect.type === 'hero_points' && - effect.target === data_1.PLAYER_WITH_MOST_HERO_POINTS) { - state = 'lose_hero_points'; - } - if (effect.type === 'hero_points' && effect.target === data_1.SELF) { - state = 'gain_hero_points'; - } - if (effect.type === 'draw_card' && effect.target === data_1.SELF) { - state = 'draw_card'; + const strategies = [ + { + condition: effect.type === 'hero_points' && + effect.target === data_1.PLAYER_WITH_MOST_HERO_POINTS, + resolve: () => { + return create_leaf_node('lose_hero_points', faction, args); + }, + }, + { + condition: effect.type === 'hero_points' && effect.target === data_1.ALL_PLAYERS, + resolve: () => { + return create_seq_node(get_player_order().map((faction) => create_leaf_node('gain_hero_points', faction, { + v: effect.value, + }))); + }, + }, + { + condition: effect.type === 'hero_points' && effect.target === data_1.SELF, + resolve: () => { + return create_leaf_node('gain_hero_points', faction, args); + }, + }, + { + condition: effect.type === 'hero_points' && + role_ids.includes(effect.target), + resolve: () => { + return create_leaf_node('gain_hero_points', effect.target, args); + }, + }, + { + condition: effect.type === 'hero_points' && effect.target === data_1.INITIATIVE_PLAYER, + resolve: () => { + return create_leaf_node('gain_hero_points', game.initiative); + }, + }, + { + condition: effect.type === 'draw_card' && effect.target === data_1.SELF, + resolve: () => { + return create_leaf_node('draw_card', faction, args); + }, + }, + { + condition: effect.type === 'draw_card' && effect.target === data_1.INITIATIVE_PLAYER, + resolve: () => { + return create_leaf_node('draw_card', game.initiative, args); + }, + }, + { + condition: effect.type === 'draw_card' && + role_ids.includes(effect.target), + resolve: () => { + return create_leaf_node('draw_card', effect.target, args); + }, + }, + { + condition: effect.type === 'draw_card' && effect.target === data_1.ALL_PLAYERS, + resolve: () => { + return create_seq_node(get_player_order(get_active_faction()).map((faction) => create_leaf_node('draw_card', faction, { + v: effect.value, + }))); + }, + }, + { + condition: effect.type === 'draw_card' && effect.target === data_1.OTHER_PLAYERS, + resolve: () => { + const leaf_nodes = get_player_order(get_active_faction()).map((faction) => create_leaf_node('draw_card', faction, { + v: effect.value, + })); + array_remove(leaf_nodes, 0); + return create_seq_node(leaf_nodes); + }, + }, + ]; + const strategy = strategies.find((strategy) => strategy.condition); + if (strategy) { + return strategy.resolve(); } - if (state === undefined) { + else { console.log('----UNRESOLVED EFFECT----', effect); - return null; + throw new Error('Unresolved effect'); } - return create_leaf_node(state, faction, args); } function win_final_bid(faction_id) { log_br(); @@ -62,6 +62,14 @@ import data, { STRATEGY_MEDALLION_ID, PROPAGANDA_MEDALLION_ID, VOLUNTEERS_MEDALLION_ID, + ALL_PLAYERS, + OTHER_PLAYERS, + MADRID, + SOUTHERN, + COMMUNIST_EXTRA_HERO_POINT, + LIBERTY_OR_COLLECTIVIZATION, + ANARCHIST_EXTRA_HERO_POINT, + ARAGON, // StaticData, // PLAYER_WITH_MOST_HERO_POINTS, } from './data'; @@ -79,12 +87,12 @@ var view = {} as View; // = null // export const COMMUNIST = 'Communist' as Player; // export const MODERATE = 'Moderate' as Player; -const role_ids = [ANARCHISTS_ID, COMMUNISTS_ID, MODERATES_ID]; +const role_ids: FactionId[] = [ANARCHISTS_ID, COMMUNISTS_ID, MODERATES_ID]; const faction_player_map: Record<FactionId, Player> = { - [ANARCHISTS_ID]: ANARCHIST, - [COMMUNISTS_ID]: COMMUNIST, - [MODERATES_ID]: MODERATE, + a: ANARCHIST, + c: COMMUNIST, + m: MODERATE, }; const player_faction_map: Record<Player, FactionId> = { @@ -184,7 +192,7 @@ export function action( if (action !== 'undo') { state.undo = push_undo(); } - + game = state; let S = states[game.state]; if (action in S) S[action](arg, player); @@ -290,6 +298,23 @@ const engine_functions: Record<string, Function> = { start_year, resolve_fascist_test, resolve_final_bid, + // Unique card effects + card1_event2, + card3_event2, + card10_event2, + card16_event2, + card17_event3, + card20_event3, + card22_event3, + card23_event1, + card26_event1, + card29_event2, + card35_event2, + card42_event3, + card45_event2, + card50_event2, + card53_event2, + card54_event1, }; function get_active( @@ -456,21 +481,22 @@ export function setup(seed: number, _scenario: string, _options: unknown) { seed: seed, state: null, active: ANARCHIST, + active_abilities: [], bag_of_glory: [ANARCHISTS_ID, COMMUNISTS_ID, MODERATES_ID], blank_markers: [[], [], [], [], []], bonuses: [ON, ON], current_events: [], discard: { - [ANARCHISTS_ID]: [], - [COMMUNISTS_ID]: [], - [MODERATES_ID]: [], + a: [], + c: [], + m: [], f: [], }, engine: [], final_bid: { - [ANARCHISTS_ID]: [], - [COMMUNISTS_ID]: [], - [MODERATES_ID]: [], + a: [], + c: [], + m: [], }, fronts: { a: { @@ -496,38 +522,38 @@ export function setup(seed: number, _scenario: string, _options: unknown) { }, glory: [], hands: { - [ANARCHISTS_ID]: [], - [COMMUNISTS_ID]: [], - [MODERATES_ID]: [], + a: [], + c: [], + m: [], }, hero_points: { - [ANARCHISTS_ID]: 2, - [COMMUNISTS_ID]: 2, - [MODERATES_ID]: 0, + a: 2, + c: 2, + m: 0, pool: 14, }, chosen_cards: { - [ANARCHISTS_ID]: null, - [COMMUNISTS_ID]: null, - [MODERATES_ID]: null, + a: null, + c: null, + m: null, }, initiative: MODERATES_ID, medallions: { - [ANARCHISTS_ID]: [], - [COMMUNISTS_ID]: [], - [MODERATES_ID]: [], + a: [], + c: [], + m: [], pool: [], }, tableaus: { - [ANARCHISTS_ID]: [], - [COMMUNISTS_ID]: [], - [MODERATES_ID]: [], + a: [], + c: [], + m: [], }, tracks: [5, 5, 6, 3, 3], trash: { - [ANARCHISTS_ID]: [], - [COMMUNISTS_ID]: [], - [MODERATES_ID]: [], + a: [], + c: [], + m: [], }, triggered_track_effects: [], log: [], @@ -594,7 +620,7 @@ function start_turn() { log(card.title); game.engine = card.effects.map((effect) => resolve_effect(effect)); - if (game.year === 3 && game.turn === 1) { + if (game.year === 3 && game.turn === 4) { game.engine.push(create_function_node('setup_final_bid')); } else { game.engine.push(create_function_node('setup_choose_card')); @@ -739,6 +765,28 @@ states.activate_icon = { }, }; +// TODO: implement +// cards 10, 36, 54 +states.add_card_to_tableau = { + inactive: 'add a card to their tableau', + prompt() { + view.prompt = 'Choose a card to add to your tableau'; + for (const c of game.hands[get_active_faction()]) { + gen_action_card(c); + } + }, + card(c: CardId) { + const faction_id = get_active_faction(); + const card = cards[c]; + array_remove(game.hands[faction_id], game.hands[faction_id].indexOf(c)); + game.tableaus[faction_id].push(c); + logi( + `${faction_player_map[faction_id]} adds ${card.title} to their tableau` + ); + resolve_active_and_proceed(); + }, +}; + states.add_glory = { inactive: 'add tokens to the Bag of Glory', prompt() { @@ -1082,14 +1130,23 @@ states.gain_hero_points = { inactive: 'gain Hero Points', prompt() { const value = get_active_node_args().v; - view.prompt = value > 1 ? `Gain ${value} Hero Points` : 'Gain 1 Hero Point'; - gen_action('gain_hp'); + if (game.hero_points.pool > 0) { + view.prompt = + value > 1 ? `Gain ${value} Hero Points` : 'Gain 1 Hero Point'; + gen_action('gain_hp'); + } else { + view.prompt = 'No Hero Points available in pool. You must skip'; + gen_action('skip'); + } }, gain_hp() { const value = get_active_node_args().v; gain_hero_points(get_active_faction(), value); resolve_active_and_proceed(); }, + skip() { + resolve_active_and_proceed(); + }, }; states.game_over = { @@ -1130,13 +1187,25 @@ states.lose_hero_points = { }, }; +// TODO: implement +states.move_attacks = { + inactive: 'move attacks', + prompt() { + view.prompt = 'Choose a Front'; + }, +}; + states.move_track = { inactive: 'move a Track', prompt() { const node = get_active_node(); const track = node.a.t; const value = node.a.v; - const name = tracks[track].name; + + const name = + track === LIBERTY_OR_COLLECTIVIZATION + ? 'Liberty OR Collectivization' + : tracks[track].name; view.prompt = `Move ${name} ${value > 0 ? 'up' : 'down'}`; if (track === GOVERNMENT && value === TOWARDS_CENTER) { @@ -1144,8 +1213,13 @@ states.move_track = { } else if (track === GOVERNMENT && value === AWAY_FROM_CENTER) { view.prompt = `Move ${name} away from center`; } - // return 'Decrease ' + tracks[effect.target].name; - gen_action_standee(track); + + if (track === LIBERTY_OR_COLLECTIVIZATION) { + gen_action_standee(LIBERTY); + gen_action_standee(COLLECTIVIZATION); + } else { + gen_action_standee(track); + } }, standee(s: number) { const node = get_active_node(); @@ -1185,6 +1259,14 @@ states.move_track_up_or_down = { }, }; +// TODO: implement card 46 +states.peek_fascist_cards = { + inactive: 'peek at Fascist cards', + prompt() { + view.prompt = 'Choose one card to return to the top of the deck'; + }, +}; + states.player_turn = { inactive: 'play their turn', prompt() { @@ -1224,7 +1306,7 @@ states.player_turn = { insert_before_active_node( create_seq_node([ create_leaf_node('choose_area_ap', faction_id, { - strength: (cards[card] as PlayerCard).strength, + strength: (cards[card] as PlayerCard).strength, }), create_function_node('check_activate_icon'), ]) @@ -1285,6 +1367,23 @@ states.remove_blank_marker = { }, }; +// TOOD: implement from card 6 +states.remove_attack_from_fronts = { + inactive: 'remove attacks', + prompt() { + view.prompt = 'Choose a front to remove an attack'; + }, +}; + +// TOOD: implement from card 15 +states.return_card = { + inactive: 'return a card', + prompt() { + view.prompt = 'Choose a card to return'; + // Return from trash + }, +}; + states.spend_hero_points = { inactive: 'spend Hero points', prompt() { @@ -1388,6 +1487,28 @@ states.spend_hero_points = { }, }; +// TODO: implement, card 33 +states.swap_card_tableau_hand = { + inactive: 'swap cards', + prompt() { + view.prompt = 'Choose cards'; + const faction = get_active_faction(); + for (const c of game.hands[faction]) { + gen_action_card(c); + } + }, + card(c: CardId) {}, +}; + +// TODO: implement, card 12 + card 32 + card 44 +// Value should come from args +states.take_hero_points = { + inactive: 'take Hero Points', + prompt() { + view.prompt = 'Choose a player to take Hero Points from'; + }, +}; + states.use_organization_medallion = { inactive: 'use Organization Medallion', prompt() { @@ -1444,6 +1565,129 @@ states.use_strategy_medallion = { // #endrregion +// #region card effects + +function card1_event2() { + const value = game.tracks[FOREIGN_AID] >= 6 ? 3 : 2; + insert_after_active_node( + resolve_effect(create_effect('track', FOREIGN_AID, value)) + ); + resolve_active_and_proceed(); +} + +function card3_event2() { + const value = game.tracks[FOREIGN_AID] >= 8 ? 2 : 1; + insert_after_active_node( + resolve_effect(create_effect('track', GOVERNMENT, value)) + ); + resolve_active_and_proceed(); +} + +function card10_event2() { + if (game.tracks[FOREIGN_AID] >= 6) { + resolve_effect(create_effect('draw_card', SELF, 2)); + } + resolve_active_and_proceed(); +} + +function card16_event2() { + const value = game.tracks[GOVERNMENT] >= 6 ? 4 : 3; + + insert_after_active_node( + resolve_effect(create_effect('track', FOREIGN_AID, value)) + ); + resolve_active_and_proceed(); +} + +function card17_event3() { + const value = game.tracks[GOVERNMENT] >= 6 ? -4 : -3; + insert_after_active_node( + resolve_effect(create_effect('track', COLLECTIVIZATION, value)) + ); + resolve_active_and_proceed(); +} + +function card20_event3() { + const value = game.tracks[SOVIET_SUPPORT] >= 6 ? 2 : 1; + insert_after_active_node( + create_seq_node([ + resolve_effect(create_effect('front', MADRID, value)), + resolve_effect(create_effect('front', SOUTHERN, value)), + ]) + ); + resolve_active_and_proceed(); +} + +function card22_event3() { + const value = game.tracks[SOVIET_SUPPORT] >= 8 ? -3 : -3; + insert_after_active_node( + resolve_effect(create_effect('track', GOVERNMENT, value)) + ); + resolve_active_and_proceed(); +} + +function card23_event1() { + const value = game.tracks[SOVIET_SUPPORT] >= 6 ? 4 : 3; + insert_after_active_node(resolve_effect(create_effect('front', ANY, value))); + resolve_active_and_proceed(); +} + +function card26_event1() { + game.active_abilities.push(COMMUNIST_EXTRA_HERO_POINT); +} + +function card29_event2() { + const value = game.tracks[GOVERNMENT] <= 5 ? -3 : -2; + insert_after_active_node( + resolve_effect(create_effect('track', LIBERTY, value)) + ); + resolve_active_and_proceed(); +} + +function card35_event2() { + const value = game.tracks[GOVERNMENT] <= 5 ? 2 : 1; + insert_after_active_node( + resolve_effect(create_effect('track', SOVIET_SUPPORT, value)) + ); + resolve_active_and_proceed(); +} + +function card42_event3() { + game.active_abilities.push(ANARCHIST_EXTRA_HERO_POINT); +} + +function card45_event2() { + if (game.tracks[LIBERTY] >= 6) { + insert_after_active_node( + resolve_effect(create_effect('track', COLLECTIVIZATION, 1)) + ); + } + resolve_active_and_proceed(); +} + +function card50_event2() { + const value = game.tracks[COLLECTIVIZATION] >= 8 ? 3 : 2; + insert_after_active_node( + resolve_effect(create_effect('front', ARAGON, value)) + ); + resolve_active_and_proceed(); +} + +function card53_event2() { + const value = game.tracks[LIBERTY] >= 8 ? 3 : 2; + insert_after_active_node(resolve_effect(create_effect('front', ANY, value))); + resolve_active_and_proceed(); +} + +function card54_event1() { + const value = game.tracks[COLLECTIVIZATION] >= 8 ? 3 : 2; + insert_after_active_node( + resolve_effect(create_effect('track', LIBERTY, value)) + ); + resolve_active_and_proceed(); +} + +// #endregion // #region GAME FUNCTIONS @@ -1541,6 +1785,7 @@ function end_of_turn() { Object.keys(game.fronts).forEach((front_id) => { game.fronts[front_id].contributions = []; }); + game.active_abilities = []; game.used_medallions = []; if (game.turn === 4) { end_of_year(); @@ -1563,9 +1808,9 @@ function end_of_year() { } const glory_to_draw = [0, 1, 2, 5]; const glory_this_year: Record<FactionId, boolean> = { - [ANARCHISTS_ID]: false, - [COMMUNISTS_ID]: false, - [MODERATES_ID]: false, + a: false, + c: false, + m: false, }; for (let i = 0; i < glory_to_draw[game.year]; ++i) { const index = random(game.bag_of_glory.length); @@ -1606,6 +1851,14 @@ function gain_hero_points(faction_id: FactionId, value: number) { if (game.hero_points.pool === 0) { return; } + if ( + (faction_id === ANARCHISTS_ID && + (game.active_abilities || []).includes(ANARCHIST_EXTRA_HERO_POINT)) || + (faction_id === COMMUNISTS_ID && + (game.active_abilities || []).includes(COMMUNIST_EXTRA_HERO_POINT)) + ) { + value++; + } const gain = Math.min(game.hero_points.pool, value); game.hero_points.pool -= gain; game.hero_points[faction_id] += gain; @@ -1940,17 +2193,22 @@ function get_faction_to_resolve_effect(effect: Effect): FactionId { } const effect_type_state_map: Record<string, string> = { + add_card_to_tableau: 'add_card_to_tableau', attack: 'attack_front', bonus: 'change_bonus', front: 'add_to_front', medallion: 'choose_medallion', + remove_blank_marker: 'remove_blank_marker', + return_card: 'return_card', + swap_card_tableau_hand: 'swap_card_tableau_hand', + take_hero_points: 'take_hero_points', track: 'move_track', }; function resolve_effect( effect: Effect // faction: FactionId = get_active_faction() // -): EngineNode | null { +): EngineNode { const args = { t: effect.target, v: effect.value, @@ -1958,6 +2216,14 @@ function resolve_effect( const faction = get_faction_to_resolve_effect(effect); + if (effect.type === 'function') { + return create_function_node(effect.target as string); + } + if (effect.type === 'state') { + return create_leaf_node(effect.target as string, faction, { + v: effect.value, + }); + } // Default cases where effect type is mapped to a state let state = effect_type_state_map[effect.type]; if (state !== undefined) { @@ -1965,23 +2231,124 @@ function resolve_effect( } // Specific mapping based on target - if ( - effect.type === 'hero_points' && - effect.target === PLAYER_WITH_MOST_HERO_POINTS - ) { - state = 'lose_hero_points'; - } - if (effect.type === 'hero_points' && effect.target === SELF) { - state = 'gain_hero_points'; - } - if (effect.type === 'draw_card' && effect.target === SELF) { - state = 'draw_card'; - } - if (state === undefined) { + const strategies = [ + { + condition: + effect.type === 'hero_points' && + effect.target === PLAYER_WITH_MOST_HERO_POINTS, + resolve: () => { + return create_leaf_node('lose_hero_points', faction, args); + }, + }, + { + condition: effect.type === 'hero_points' && effect.target === ALL_PLAYERS, + resolve: () => { + return create_seq_node( + get_player_order().map((faction) => + create_leaf_node('gain_hero_points', faction, { + v: effect.value, + }) + ) + ); + }, + }, + { + condition: effect.type === 'hero_points' && effect.target === SELF, + resolve: () => { + return create_leaf_node('gain_hero_points', faction, args); + }, + }, + { + condition: + effect.type === 'hero_points' && + role_ids.includes(effect.target as FactionId), + resolve: () => { + return create_leaf_node( + 'gain_hero_points', + effect.target as FactionId, + args + ); + }, + }, + { + condition: + effect.type === 'hero_points' && effect.target === INITIATIVE_PLAYER, + resolve: () => { + return create_leaf_node('gain_hero_points', game.initiative); + }, + }, + { + condition: effect.type === 'draw_card' && effect.target === SELF, + resolve: () => { + return create_leaf_node('draw_card', faction, args); + }, + }, + { + condition: + effect.type === 'draw_card' && effect.target === INITIATIVE_PLAYER, + resolve: () => { + return create_leaf_node('draw_card', game.initiative, args); + }, + }, + { + condition: + effect.type === 'draw_card' && + role_ids.includes(effect.target as FactionId), + resolve: () => { + return create_leaf_node('draw_card', effect.target as FactionId, args); + }, + }, + { + condition: effect.type === 'draw_card' && effect.target === ALL_PLAYERS, + resolve: () => { + return create_seq_node( + get_player_order(get_active_faction()).map((faction) => + create_leaf_node('draw_card', faction, { + v: effect.value, + }) + ) + ); + }, + }, + { + condition: effect.type === 'draw_card' && effect.target === OTHER_PLAYERS, + resolve: () => { + const leaf_nodes = get_player_order(get_active_faction()).map( + (faction) => + create_leaf_node('draw_card', faction, { + v: effect.value, + }) + ); + array_remove(leaf_nodes, 0); + return create_seq_node(leaf_nodes); + }, + }, + ]; + + const strategy = strategies.find((strategy) => strategy.condition); + + if (strategy) { + return strategy.resolve(); + } else { console.log('----UNRESOLVED EFFECT----', effect); - return null; - } - return create_leaf_node(state, faction, args); + 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) { @@ -2116,7 +2483,6 @@ function log_h3(msg: string) { // #region UTILITY - function get_active_faction(): FactionId { return player_faction_map[game.active]; } @@ -7,7 +7,7 @@ export type Brand<T, TBrand extends string> = T & { export type Player = Brand<string, 'Player'>; export type CardId = Brand<number, 'CardId'>; -export type FactionId = Brand<string, 'FactionId'>; +export type FactionId = 'a' | 'c' | 'm'; export type FrontId = 'a' | 'm' | 'n' | 's'; export interface Front { @@ -17,14 +17,18 @@ export interface Front { } export interface Game { + // TODO: why is this needed? [index: number]: any; - seed: number; + // RTT + active: Player | 'None' | null; log: string[]; + seed: number; + state: string | null; undo: Game[]; + // Game specific + active_abilities: number[]; turn: number; year: number; - active: Player | 'None' | null; - state: string | null; bag_of_glory: FactionId[]; blank_markers: number[][]; bonuses: number[]; @@ -166,14 +170,17 @@ export interface Effect { | 'bonus' | 'hero_points' | 'front' + | 'function' // Use for unqique effects | 'medallion' | 'draw_card' | 'play_card' | 'swap_card_tableau_hand' - | 'add_to_tableau' + | 'state' + | 'add_card_to_tableau' | 'remove_blank_marker' - | 'return_card'; - target: string | number; + | 'return_card' + | 'take_hero_points'; + target: string | number | FactionId; value: number; faction?: FactionId | 'i'; } |