summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrans Bongers <fransbongers@franss-mbp.home>2024-12-27 19:45:21 +0100
committerFrans Bongers <fransbongers@franss-mbp.home>2024-12-27 19:45:21 +0100
commit9d0630a33e0358f943e68008823f355bceb71be1 (patch)
treebbb5b0cd5e1b8381d767ee1694f928f24f8a5ac9
parent5dc1ee327e16431b6700f3977469943f002a0c7c (diff)
downloadland-and-freedom-9d0630a33e0358f943e68008823f355bceb71be1.tar.gz
setup for event effects
-rw-r--r--data.js49
-rw-r--r--data.ts79
-rw-r--r--rules.js354
-rw-r--r--rules.ts480
-rw-r--r--types.d.ts21
5 files changed, 835 insertions, 148 deletions
diff --git a/data.js b/data.js
index 20a6486..7b86c73 100644
--- a/data.js
+++ b/data.js
@@ -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,
diff --git a/data.ts b/data.ts
index 2f51434..8121115 100644
--- a/data.ts
+++ b/data.ts
@@ -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,
diff --git a/rules.js b/rules.js
index f68af28..711573c 100644
--- a/rules.js
+++ b/rules.js
@@ -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();
diff --git a/rules.ts b/rules.ts
index 6831f5e..98a6806 100644
--- a/rules.ts
+++ b/rules.ts
@@ -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];
}
diff --git a/types.d.ts b/types.d.ts
index 06f4125..33e8456 100644
--- a/types.d.ts
+++ b/types.d.ts
@@ -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';
}