summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrans Bongers <fransbongers@franss-mbp.home>2024-12-02 21:46:43 +0100
committerFrans Bongers <fransbongers@franss-mbp.home>2024-12-02 21:46:43 +0100
commit48726dd19ad8dde11a6172f30b5071987b7d09b5 (patch)
tree8b36ebc15d609d1a316ef6f98870d232ab09db6e
parente32cc3efe1c1ef5378cef422555e8c8289449938 (diff)
downloadland-and-freedom-48726dd19ad8dde11a6172f30b5071987b7d09b5.tar.gz
add tableaus and icon data
-rw-r--r--data.js92
-rw-r--r--data.ts92
-rw-r--r--land-and-freedom.css53
-rw-r--r--land-and-freedom.scss65
-rw-r--r--play.html19
-rw-r--r--play.js37
-rw-r--r--play.ts56
-rw-r--r--rules.js464
-rw-r--r--rules.ts609
-rw-r--r--types.d.ts37
10 files changed, 1064 insertions, 460 deletions
diff --git a/data.js b/data.js
index c41aee7..edf0e36 100644
--- a/data.js
+++ b/data.js
@@ -1,6 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-exports.PLAYER_WITH_MOST_HERO_POINTS = exports.ON = exports.OFF = exports.TEAMWORK_BONUS = exports.MORALE_BONUS = exports.FOREIGN_AID = exports.SOVIET_SUPPORT = exports.GOVERNMENT = exports.COLLECTIVIZATION = exports.LIBERTY = void 0;
+exports.TRASH = exports.TOWARDS_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.GOVERNMENT = exports.COLLECTIVIZATION = exports.CLOSEST_TO_VICTORY = exports.CLOSEST_TO_DEFEAT = exports.LIBERTY = exports.ANY = void 0;
const LIBERTY = 0;
exports.LIBERTY = LIBERTY;
const COLLECTIVIZATION = 1;
@@ -26,13 +26,20 @@ const MADRID = 'm';
const NORTHERN = 'n';
const SOUTHERN = 's';
const CLOSEST_TO_DEFEAT = 'd';
+exports.CLOSEST_TO_DEFEAT = CLOSEST_TO_DEFEAT;
const CLOSEST_TO_VICTORY = 'v';
+exports.CLOSEST_TO_VICTORY = CLOSEST_TO_VICTORY;
const TOWARDS_CENTER = 10;
+exports.TOWARDS_CENTER = TOWARDS_CENTER;
const AWAY_FROM_CENTER = 11;
const ANY = 'any';
+exports.ANY = ANY;
const SELF = 'self';
+exports.SELF = SELF;
const OTHER_PLAYERS = 'other';
+exports.OTHER_PLAYERS = OTHER_PLAYERS;
const TRASH = 'trash';
+exports.TRASH = TRASH;
function create_effect(type, target, value) {
return {
type,
@@ -49,6 +56,7 @@ const data = {
create_effect('track', FOREIGN_AID, 2),
create_effect('track', SOVIET_SUPPORT, -1),
],
+ icons: ['foreign_aid', 'add_to_front', 'd_soviet_support'],
strength: 1,
title: 'CLANDESTINE FRENCH ARMS',
type: 'pc',
@@ -60,6 +68,7 @@ const data = {
create_effect('front', ANY, 3),
create_effect('track', LIBERTY, -2),
],
+ icons: ['foreign_aid', 'add_to_front', 'd_liberty'],
strength: 2,
title: 'POPULAR ARMY OF THE REPUBLIC',
type: 'pc',
@@ -70,6 +79,7 @@ const data = {
create_effect('front', CLOSEST_TO_DEFEAT, 3),
create_effect('draw_card', SELF, 1),
],
+ icons: ['add_to_front', 'government', 'draw_card'],
strength: 2,
title: 'MEXICAN GUNS',
type: 'pc',
@@ -81,6 +91,7 @@ const data = {
create_effect('track', FOREIGN_AID, 1),
create_effect('swap_card_tableau_hand', ANY, 1),
],
+ icons: ['add_to_front', 'foreign_aid'],
strength: 1,
title: 'BATTLE OF GUADALAJARA',
type: 'pc',
@@ -93,6 +104,7 @@ const data = {
create_effect('draw_card', SELF, 3),
create_effect('draw_card', OTHER_PLAYERS, 1),
],
+ icons: ['teamwork_on', 'add_to_front', 'draw_card'],
strength: 1,
title: '"SI ME OUIERES ESCRIBIR"',
type: 'pc',
@@ -104,6 +116,7 @@ const data = {
create_effect('track', GOVERNMENT, 1),
create_effect('draw_card', SELF, 1),
],
+ icons: ['teamwork_on', 'add_to_front', 'government', 'draw_card'],
strength: 2,
title: 'XYZ LINE',
type: 'pc',
@@ -117,6 +130,12 @@ const data = {
create_effect('track', GOVERNMENT, 2),
create_effect('hero_points', SELF, 1),
],
+ icons: [
+ 'add_to_front',
+ 'foreign_aid',
+ 'd_collectivization',
+ 'government',
+ ],
strength: 3,
title: 'INDALECIO PRIETO',
type: 'pc',
@@ -127,6 +146,7 @@ const data = {
create_effect('bonus', ANY, ON),
create_effect('front', ANY, 3),
],
+ icons: ['teamwork_on', 'add_to_front'],
strength: 1,
title: "PEOPLE'S OLYMPIAD",
type: 'pc',
@@ -139,6 +159,12 @@ const data = {
create_effect('track', SOVIET_SUPPORT, -2),
create_effect('draw_card', SELF, 3),
],
+ icons: [
+ 'd_liberty',
+ 'd_collectivization',
+ 'd_soviet_support',
+ 'draw_card',
+ ],
strength: 1,
title: 'FOUR ANARCHIST MINISTERS',
type: 'pc',
@@ -149,6 +175,7 @@ const data = {
create_effect('track', FOREIGN_AID, 4),
create_effect('add_to_tableau', SELF, 1),
],
+ icons: ['foreign_aid', 'draw_card'],
strength: 1,
title: 'GUERNICA',
type: 'pc',
@@ -160,6 +187,7 @@ const data = {
create_effect('remove_blank_marker', ANY, 1),
create_effect('track', FOREIGN_AID, 2),
],
+ icons: ['add_to_front', 'foreign_aid'],
strength: 1,
title: 'ERNEST HEMINGWAY',
type: 'pc',
@@ -170,6 +198,7 @@ const data = {
create_effect('track', SOVIET_SUPPORT, -3),
create_effect('track', COLLECTIVIZATION, -3),
],
+ icons: ['add_to_front', 'd_soviet_support', 'd_collectivization'],
strength: 1,
title: 'HUESCA OFFENSIVE',
type: 'pc',
@@ -182,6 +211,7 @@ const data = {
create_effect('track', GOVERNMENT, 2),
create_effect('hero_points', SELF, 1),
],
+ icons: ['foreign_aid', 'd_soviet_support', 'government'],
strength: 1,
title: 'PABLO NERUDA',
type: 'pc',
@@ -193,6 +223,7 @@ const data = {
create_effect('track', COLLECTIVIZATION, -1),
create_effect('track', GOVERNMENT, 1),
],
+ icons: ['add_to_front', 'd_collectivization', 'government'],
strength: 1,
title: 'EUSKO GUDAROSTEA',
type: 'pc',
@@ -203,6 +234,7 @@ const data = {
create_effect('track', FOREIGN_AID, 2),
create_effect('return_card', TRASH, 1),
],
+ icons: ['d_liberty', 'd_collectivization', 'foreign_aid', 'draw_card'],
strength: 2,
title: 'JUAN NEGRÍN',
type: 'pc',
@@ -210,6 +242,7 @@ const data = {
{
id: 16,
effects: [],
+ icons: ['add_to_front', 'foreign_aid'],
strength: 1,
title: 'PUBLICIZE FASCIST WAR CRIMES',
type: 'pc',
@@ -220,6 +253,7 @@ const data = {
create_effect('track', FOREIGN_AID, 1),
create_effect('track', GOVERNMENT, 1),
],
+ icons: ['foreign_aid', 'government', 'd_collectivization'],
strength: 1,
title: 'AGRARIAN REFORM',
type: 'pc',
@@ -231,6 +265,7 @@ const data = {
create_effect('track', GOVERNMENT, 2),
create_effect('draw_card', SELF, 2),
],
+ icons: ['d_collectivization', 'government', 'draw_card'],
strength: 1,
title: 'IMPOSE FACTORY MANAGERS',
type: 'pc',
@@ -242,6 +277,7 @@ const data = {
create_effect('track', GOVERNMENT, -1),
create_effect('return_card', TRASH, 1),
],
+ icons: ['add_to_front', 'government', 'draw_card'],
strength: 2,
title: '¡NO PASARÁN!',
type: 'pc',
@@ -252,6 +288,7 @@ const data = {
create_effect('bonus', ANY, ON),
create_effect('track', SOVIET_SUPPORT, 2),
],
+ icons: ['teamwork_on', 'soviet_support', 'add_to_front'],
strength: 2,
title: 'RUSSIAN FIGHTERS',
type: 'pc',
@@ -264,6 +301,7 @@ const data = {
create_effect('track', COLLECTIVIZATION, -2),
create_effect('hero_points', SELF, 1),
],
+ icons: ['add_to_front', 'd_liberty', 'd_collectivization'],
strength: 1,
title: 'ENRIQUE LÍSTER',
type: 'pc',
@@ -274,6 +312,7 @@ const data = {
create_effect('track', LIBERTY, -2),
create_effect('track', SOVIET_SUPPORT, 1),
],
+ icons: ['d_liberty', 'soviet_support', 'government'],
strength: 2,
title: 'LARGO CABALLERO',
type: 'pc',
@@ -284,6 +323,7 @@ const data = {
create_effect('track', FOREIGN_AID, -2),
create_effect('draw_card', SELF, 2),
],
+ icons: ['add_to_front', 'd_foreign_aid', 'draw_card'],
strength: 2,
title: 'SOVIET TANKS',
type: 'pc',
@@ -297,6 +337,7 @@ const data = {
create_effect('track', GOVERNMENT, -2),
create_effect('hero_points', SELF, 1),
],
+ icons: ['add_to_front', 'soviet_support', 'd_liberty', 'government'],
strength: 3,
title: 'DOLORES IBÁRRURI',
type: 'pc',
@@ -309,6 +350,7 @@ const data = {
create_effect('draw_card', SELF, 3),
create_effect('draw_card', OTHER_PLAYERS, 1),
],
+ icons: ['teamwork_on', 'add_to_front', 'draw_card'],
strength: 1,
title: 'PAUL ROBESON',
type: 'pc',
@@ -319,6 +361,7 @@ const data = {
create_effect('track', LIBERTY, -2),
create_effect('track', GOVERNMENT, -1),
],
+ icons: ['add_to_front', 'd_liberty', 'government'],
strength: 1,
title: 'MADRID DEFENSE COUNCIL',
type: 'pc',
@@ -331,6 +374,7 @@ const data = {
create_effect('track', FOREIGN_AID, -1),
create_effect('draw_card', SELF, 1),
],
+ icons: ['soviet_support', 'd_foreign_aid', 'draw_card'],
strength: 1,
title: "STALIN GETS THE REPUBLIC'S GOLD",
type: 'pc',
@@ -343,6 +387,7 @@ const data = {
create_effect('track', FOREIGN_AID, -1),
create_effect('draw_card', SELF, 1),
],
+ icons: ['teamwork_on', 'add_to_front', 'd_foreign_aid', 'draw_card'],
strength: 1,
title: 'INTERNATIONAL BRIGADES',
type: 'pc',
@@ -352,6 +397,7 @@ const data = {
effects: [
create_effect('track', GOVERNMENT, -2),
],
+ icons: ['government', 'd_liberty'],
strength: 1,
title: 'BAN WOMEN FROM THE FRONT',
type: 'pc',
@@ -363,6 +409,7 @@ const data = {
create_effect('track', SOVIET_SUPPORT, 2),
create_effect('track', FOREIGN_AID, -3),
],
+ icons: ['add_to_front', 'soviet_support', 'd_foreign_aid'],
strength: 1,
title: 'ABRAHAM LINCOLN BRIGADE',
type: 'pc',
@@ -374,6 +421,7 @@ const data = {
create_effect('track', SOVIET_SUPPORT, 3),
create_effect('track', GOVERNMENT, -2),
],
+ icons: ['soviet_support', 'government'],
strength: 2,
title: 'OUTLAW THE POUM',
type: 'pc',
@@ -384,6 +432,12 @@ const data = {
create_effect('front', ANY, 1),
create_effect('track', SOVIET_SUPPORT, 1),
],
+ icons: [
+ 'add_to_front',
+ 'soviet_support',
+ 'd_liberty',
+ 'd_collectivization',
+ ],
strength: 1,
title: 'DISBAND THE CONTROL PATROLS',
type: 'pc',
@@ -396,6 +450,7 @@ const data = {
create_effect('track', LIBERTY, -4),
create_effect('swap_card_tableau_hand', ANY, 1),
],
+ icons: ['soviet_support', 'd_liberty'],
strength: 1,
title: 'MAY DAYS',
type: 'pc',
@@ -407,6 +462,7 @@ const data = {
create_effect('track', GOVERNMENT, -1),
create_effect('draw_card', SELF, 1),
],
+ icons: ['add_to_front', 'government', 'draw_card'],
strength: 1,
title: 'FIFTH REGIMENT',
type: 'pc',
@@ -417,6 +473,7 @@ const data = {
create_effect('front', ANY, 2),
create_effect('draw_card', SELF, 2),
],
+ icons: ['add_to_front', 'soviet_support', 'draw_card'],
strength: 1,
title: 'THÄLMANN BATTALION',
type: 'pc',
@@ -429,6 +486,7 @@ const data = {
create_effect('draw_card', SELF, 2),
create_effect('add_to_tableau', ANY, 1),
],
+ icons: ['soviet_support', 'd_collectivization', 'draw_card'],
strength: 1,
title: 'DE-COLLECTIVIZE AGRICULTURE',
type: 'pc',
@@ -442,6 +500,12 @@ const data = {
create_effect('track', GOVERNMENT, TOWARDS_CENTER),
create_effect('hero_points', SELF, 1),
],
+ icons: [
+ 'add_to_front',
+ 'collectivization',
+ 'liberty',
+ 'government_to_center',
+ ],
strength: 3,
title: 'BUENAVENTURA DURRUTI',
type: 'pc',
@@ -454,6 +518,7 @@ const data = {
create_effect('draw_card', SELF, 1),
create_effect('swap_card_tableau_hand', ANY, 1),
],
+ icons: ['liberty', 'd_soviet_support', 'draw_card'],
strength: 2,
title: 'MUJERES LIBRES',
type: 'pc',
@@ -464,6 +529,7 @@ const data = {
create_effect('track', COLLECTIVIZATION, 1),
create_effect('draw_card', SELF, 2),
],
+ icons: ['add_to_front', 'collectivization', 'draw_card'],
strength: 1,
title: 'IRON COLUMN',
type: 'pc',
@@ -475,6 +541,7 @@ const data = {
create_effect('track', COLLECTIVIZATION, 2),
create_effect('draw_card', SELF, 1),
],
+ icons: ['add_to_front', 'collectivization', 'draw_card'],
strength: 2,
title: 'ASTURIAN MINERS',
type: 'pc',
@@ -486,6 +553,7 @@ const data = {
create_effect('track', COLLECTIVIZATION, 3),
create_effect('return_card', TRASH, 1),
],
+ icons: ['teamwork_on', 'collectivization', 'draw_card'],
strength: 2,
title: 'CNT-FAI',
type: 'pc',
@@ -497,6 +565,7 @@ const data = {
create_effect('front', ARAGON, 2),
create_effect('front', MADRID, 1),
],
+ icons: ['liberty', 'add_to_front'],
strength: 2,
title: 'DURRUTI COLUMN',
type: 'pc',
@@ -510,6 +579,7 @@ const data = {
create_effect('draw_card', SELF, 3),
create_effect('draw_card', OTHER_PLAYERS, 1),
],
+ icons: ['teamwork_on', 'add_to_front', 'd_soviet_support', 'draw_card'],
strength: 1,
title: 'GEORGE ORWELL',
type: 'pc',
@@ -521,6 +591,7 @@ const data = {
create_effect('track', LIBERTY, 1),
create_effect('track', FOREIGN_AID, -1),
],
+ icons: ['add_to_front', 'liberty', 'd_foreign_aid'],
strength: 1,
title: 'F.I.J.L.',
type: 'pc',
@@ -529,8 +600,9 @@ const data = {
id: 45,
effects: [
create_effect('front', ANY, 2),
- create_effect('track', FOREIGN_AID, -3)
+ create_effect('track', FOREIGN_AID, -3),
],
+ icons: ['add_to_front', 'collectivization', 'd_foreign_aid'],
strength: 1,
title: 'ARM THE UNIONS',
type: 'pc',
@@ -541,6 +613,7 @@ const data = {
create_effect('bonus', ANY, ON),
create_effect('track', LIBERTY, 2),
],
+ icons: ['teamwork_on', 'liberty', 'add_to_front'],
strength: 1,
title: 'GUERRILLAS',
type: 'pc',
@@ -553,6 +626,7 @@ const data = {
create_effect('track', GOVERNMENT, TOWARDS_CENTER),
create_effect('draw_card', SELF, 1),
],
+ icons: ['liberty', 'government_to_center', 'draw_card'],
strength: 1,
title: 'RADICAL EDUCATION',
type: 'pc',
@@ -564,6 +638,7 @@ const data = {
create_effect('track', SOVIET_SUPPORT, -2),
create_effect('draw_card', SELF, 3),
],
+ icons: ['add_to_front', 'd_soviet_support', 'draw_card'],
strength: 1,
title: 'MATTEOTTI BATTALION',
type: 'pc',
@@ -574,6 +649,7 @@ const data = {
create_effect('track', COLLECTIVIZATION, 4),
create_effect('draw_card', SELF, 1),
],
+ icons: ['collectivization', 'draw_card'],
strength: 1,
title: 'COLLECTIVIZE AGRICULTURE',
type: 'pc',
@@ -584,6 +660,7 @@ const data = {
create_effect('track', COLLECTIVIZATION, 1),
create_effect('track', FOREIGN_AID, -1),
],
+ icons: ['collectivization', 'add_to_front', 'd_foreign_aid'],
strength: 1,
title: 'ARMORED VEHICLES',
type: 'pc',
@@ -595,6 +672,7 @@ const data = {
create_effect('track', FOREIGN_AID, -2),
create_effect('track', GOVERNMENT, TOWARDS_CENTER),
],
+ icons: ['collectivization', 'd_foreign_aid', 'government_to_center'],
strength: 1,
title: 'INDUSTRIAL DEMOCRACY',
type: 'pc',
@@ -605,6 +683,12 @@ const data = {
create_effect('front', ANY, 1),
create_effect('track', GOVERNMENT, TOWARDS_CENTER),
],
+ icons: [
+ 'add_to_front',
+ 'liberty',
+ 'collectivization',
+ 'government_to_center',
+ ],
strength: 2,
title: 'AFFINITY GROUPS',
type: 'pc',
@@ -615,6 +699,7 @@ const data = {
create_effect('track', LIBERTY, 1),
create_effect('hero_points', SELF, 1),
],
+ icons: ['liberty', 'add_to_front'],
strength: 1,
title: 'GENDER-INCLUSIVE MILITIA',
type: 'pc',
@@ -625,6 +710,7 @@ const data = {
create_effect('track', SOVIET_SUPPORT, -1),
create_effect('add_to_tableau', ANY, 1),
],
+ icons: ['liberty', 'd_soviet_support', 'draw_card'],
strength: 1,
title: 'FEDERICA MONTSENY',
type: 'pc',
@@ -711,7 +797,7 @@ const data = {
effects: [
create_effect('attack', SOUTHERN, -5),
create_effect('bonus', MORALE_BONUS, OFF),
- create_effect('hero_points', PLAYER_WITH_MOST_HERO_POINTS, -1),
+ create_effect('track', LIBERTY, -1),
],
title: 'AIRLIFT OF THE ARMY OF AFRICA',
type: 'ec',
diff --git a/data.ts b/data.ts
index d2d2172..6facc50 100644
--- a/data.ts
+++ b/data.ts
@@ -30,7 +30,10 @@ const OTHER_PLAYERS = 'other';
const TRASH = 'trash';
export {
+ ANY,
LIBERTY,
+ CLOSEST_TO_DEFEAT,
+ CLOSEST_TO_VICTORY,
COLLECTIVIZATION,
GOVERNMENT,
SOVIET_SUPPORT,
@@ -39,7 +42,11 @@ export {
TEAMWORK_BONUS,
OFF,
ON,
+ OTHER_PLAYERS,
PLAYER_WITH_MOST_HERO_POINTS,
+ SELF,
+ TOWARDS_CENTER,
+ TRASH,
};
function create_effect(
@@ -64,6 +71,7 @@ const data: StaticData = {
// create_effect('track', FOREIGN_AID, 2), // Conditional support
create_effect('track', SOVIET_SUPPORT, -1),
],
+ icons: ['foreign_aid', 'add_to_front', 'd_soviet_support'],
strength: 1,
title: 'CLANDESTINE FRENCH ARMS',
type: 'pc',
@@ -75,6 +83,7 @@ const data: StaticData = {
create_effect('front', ANY, 3),
create_effect('track', LIBERTY, -2),
],
+ icons: ['foreign_aid', 'add_to_front', 'd_liberty'],
strength: 2,
title: 'POPULAR ARMY OF THE REPUBLIC',
type: 'pc',
@@ -86,6 +95,7 @@ const data: StaticData = {
// create_effect('track', FOREIGN_AID, 2), // conditional effect
create_effect('draw_card', SELF, 1),
],
+ icons: ['add_to_front', 'government', 'draw_card'],
strength: 2,
title: 'MEXICAN GUNS',
type: 'pc',
@@ -97,6 +107,7 @@ const data: StaticData = {
create_effect('track', FOREIGN_AID, 1),
create_effect('swap_card_tableau_hand', ANY, 1),
],
+ icons: ['add_to_front', 'foreign_aid'],
strength: 1,
title: 'BATTLE OF GUADALAJARA',
type: 'pc',
@@ -109,6 +120,7 @@ const data: StaticData = {
create_effect('draw_card', SELF, 3),
create_effect('draw_card', OTHER_PLAYERS, 1),
],
+ icons: ['teamwork_on', 'add_to_front', 'draw_card'],
strength: 1,
title: '"SI ME OUIERES ESCRIBIR"',
type: 'pc',
@@ -121,6 +133,7 @@ const data: StaticData = {
create_effect('track', GOVERNMENT, 1),
create_effect('draw_card', SELF, 1),
],
+ icons: ['teamwork_on', 'add_to_front', 'government', 'draw_card'],
strength: 2,
title: 'XYZ LINE',
type: 'pc',
@@ -134,6 +147,12 @@ const data: StaticData = {
create_effect('track', GOVERNMENT, 2),
create_effect('hero_points', SELF, 1),
],
+ icons: [
+ 'add_to_front',
+ 'foreign_aid',
+ 'd_collectivization',
+ 'government',
+ ],
strength: 3,
title: 'INDALECIO PRIETO',
type: 'pc',
@@ -144,6 +163,7 @@ const data: StaticData = {
create_effect('bonus', ANY, ON),
create_effect('front', ANY, 3),
],
+ icons: ['teamwork_on', 'add_to_front'],
strength: 1,
title: "PEOPLE'S OLYMPIAD",
type: 'pc',
@@ -156,6 +176,12 @@ const data: StaticData = {
create_effect('track', SOVIET_SUPPORT, -2),
create_effect('draw_card', SELF, 3),
],
+ icons: [
+ 'd_liberty',
+ 'd_collectivization',
+ 'd_soviet_support',
+ 'draw_card',
+ ],
strength: 1,
title: 'FOUR ANARCHIST MINISTERS',
type: 'pc',
@@ -167,6 +193,7 @@ const data: StaticData = {
// create_effect('track', FOREIGN_AID, 3) // conditional draw cards
create_effect('add_to_tableau', SELF, 1),
],
+ icons: ['foreign_aid', 'draw_card'],
strength: 1,
title: 'GUERNICA',
type: 'pc',
@@ -178,6 +205,7 @@ const data: StaticData = {
create_effect('remove_blank_marker', ANY, 1),
create_effect('track', FOREIGN_AID, 2),
],
+ icons: ['add_to_front', 'foreign_aid'],
strength: 1,
title: 'ERNEST HEMINGWAY',
type: 'pc',
@@ -189,6 +217,7 @@ const data: StaticData = {
create_effect('track', SOVIET_SUPPORT, -3),
create_effect('track', COLLECTIVIZATION, -3),
],
+ icons: ['add_to_front', 'd_soviet_support', 'd_collectivization'],
strength: 1,
title: 'HUESCA OFFENSIVE',
type: 'pc',
@@ -201,6 +230,7 @@ const data: StaticData = {
create_effect('track', GOVERNMENT, 2),
create_effect('hero_points', SELF, 1),
],
+ icons: ['foreign_aid', 'd_soviet_support', 'government'],
strength: 1,
title: 'PABLO NERUDA',
type: 'pc',
@@ -212,6 +242,7 @@ const data: StaticData = {
create_effect('track', COLLECTIVIZATION, -1),
create_effect('track', GOVERNMENT, 1),
],
+ icons: ['add_to_front', 'd_collectivization', 'government'],
strength: 1,
title: 'EUSKO GUDAROSTEA',
type: 'pc',
@@ -223,6 +254,7 @@ const data: StaticData = {
create_effect('track', FOREIGN_AID, 2),
create_effect('return_card', TRASH, 1),
],
+ icons: ['d_liberty', 'd_collectivization', 'foreign_aid', 'draw_card'],
strength: 2,
title: 'JUAN NEGRÍN',
type: 'pc',
@@ -233,6 +265,7 @@ const data: StaticData = {
// create_effect('front', ANY, -2) // move attacks
// create_effect('track', FOREIGN_AID, 4) // conditional
],
+ icons: ['add_to_front', 'foreign_aid'],
strength: 1,
title: 'PUBLICIZE FASCIST WAR CRIMES',
type: 'pc',
@@ -244,6 +277,7 @@ const data: StaticData = {
create_effect('track', GOVERNMENT, 1),
// create_effect('track', COLLECTIVIZATION,-4) // conditional
],
+ icons: ['foreign_aid', 'government', 'd_collectivization'],
strength: 1,
title: 'AGRARIAN REFORM',
type: 'pc',
@@ -255,6 +289,7 @@ const data: StaticData = {
create_effect('track', GOVERNMENT, 2),
create_effect('draw_card', SELF, 2),
],
+ icons: ['d_collectivization', 'government', 'draw_card'],
strength: 1,
title: 'IMPOSE FACTORY MANAGERS',
type: 'pc',
@@ -266,6 +301,7 @@ const data: StaticData = {
create_effect('track', GOVERNMENT, -1),
create_effect('return_card', TRASH, 1),
],
+ icons: ['add_to_front', 'government', 'draw_card'],
strength: 2,
title: '¡NO PASARÁN!',
type: 'pc',
@@ -277,6 +313,7 @@ const data: StaticData = {
create_effect('track', SOVIET_SUPPORT, 2),
// create_effect('front') // conditional on track
],
+ icons: ['teamwork_on', 'soviet_support', 'add_to_front'],
strength: 2,
title: 'RUSSIAN FIGHTERS',
type: 'pc',
@@ -289,6 +326,7 @@ const data: StaticData = {
create_effect('track', COLLECTIVIZATION, -2),
create_effect('hero_points', SELF, 1),
],
+ icons: ['add_to_front', 'd_liberty', 'd_collectivization'],
strength: 1,
title: 'ENRIQUE LÍSTER',
type: 'pc',
@@ -300,6 +338,7 @@ const data: StaticData = {
create_effect('track', SOVIET_SUPPORT, 1),
// create_effect('track', GOVERNMENT, -2) // conditional
],
+ icons: ['d_liberty', 'soviet_support', 'government'],
strength: 2,
title: 'LARGO CABALLERO',
type: 'pc',
@@ -311,6 +350,7 @@ const data: StaticData = {
create_effect('track', FOREIGN_AID, -2),
create_effect('draw_card', SELF, 2),
],
+ icons: ['add_to_front', 'd_foreign_aid', 'draw_card'],
strength: 2,
title: 'SOVIET TANKS',
type: 'pc',
@@ -324,6 +364,7 @@ const data: StaticData = {
create_effect('track', GOVERNMENT, -2),
create_effect('hero_points', SELF, 1),
],
+ icons: ['add_to_front', 'soviet_support', 'd_liberty', 'government'],
strength: 3,
title: 'DOLORES IBÁRRURI',
type: 'pc',
@@ -336,6 +377,7 @@ const data: StaticData = {
create_effect('draw_card', SELF, 3),
create_effect('draw_card', OTHER_PLAYERS, 1),
],
+ icons: ['teamwork_on', 'add_to_front', 'draw_card'],
strength: 1,
title: 'PAUL ROBESON',
type: 'pc',
@@ -347,6 +389,7 @@ const data: StaticData = {
create_effect('track', LIBERTY, -2),
create_effect('track', GOVERNMENT, -1),
],
+ icons: ['add_to_front', 'd_liberty', 'government'],
strength: 1,
title: 'MADRID DEFENSE COUNCIL',
type: 'pc',
@@ -359,6 +402,7 @@ const data: StaticData = {
create_effect('track', FOREIGN_AID, -1),
create_effect('draw_card', SELF, 1),
],
+ icons: ['soviet_support', 'd_foreign_aid', 'draw_card'],
strength: 1,
title: "STALIN GETS THE REPUBLIC'S GOLD",
type: 'pc',
@@ -371,6 +415,7 @@ const data: StaticData = {
create_effect('track', FOREIGN_AID, -1),
create_effect('draw_card', SELF, 1),
],
+ icons: ['teamwork_on', 'add_to_front', 'd_foreign_aid', 'draw_card'],
strength: 1,
title: 'INTERNATIONAL BRIGADES',
type: 'pc',
@@ -381,6 +426,7 @@ const data: StaticData = {
create_effect('track', GOVERNMENT, -2),
// create_effect('track', LIBERTY, -3) // conditional
],
+ icons: ['government', 'd_liberty'],
strength: 1,
title: 'BAN WOMEN FROM THE FRONT',
type: 'pc',
@@ -392,6 +438,7 @@ const data: StaticData = {
create_effect('track', SOVIET_SUPPORT, 2),
create_effect('track', FOREIGN_AID, -3),
],
+ icons: ['add_to_front', 'soviet_support', 'd_foreign_aid'],
strength: 1,
title: 'ABRAHAM LINCOLN BRIGADE',
type: 'pc',
@@ -403,6 +450,7 @@ const data: StaticData = {
create_effect('track', SOVIET_SUPPORT, 3),
create_effect('track', GOVERNMENT, -2),
],
+ icons: ['soviet_support', 'government'],
strength: 2,
title: 'OUTLAW THE POUM',
type: 'pc',
@@ -415,6 +463,12 @@ const data: StaticData = {
create_effect('track', SOVIET_SUPPORT, 1),
// create_effect('track') // choose one of two tracks
],
+ icons: [
+ 'add_to_front',
+ 'soviet_support',
+ 'd_liberty',
+ 'd_collectivization',
+ ],
strength: 1,
title: 'DISBAND THE CONTROL PATROLS',
type: 'pc',
@@ -427,6 +481,7 @@ const data: StaticData = {
create_effect('track', LIBERTY, -4),
create_effect('swap_card_tableau_hand', ANY, 1),
],
+ icons: ['soviet_support', 'd_liberty'],
strength: 1,
title: 'MAY DAYS',
type: 'pc',
@@ -438,6 +493,7 @@ const data: StaticData = {
create_effect('track', GOVERNMENT, -1),
create_effect('draw_card', SELF, 1),
],
+ icons: ['add_to_front', 'government', 'draw_card'],
strength: 1,
title: 'FIFTH REGIMENT',
type: 'pc',
@@ -449,6 +505,7 @@ const data: StaticData = {
// create_effect('track', SOVIET_SUPPORT,2) // conditional
create_effect('draw_card', SELF, 2),
],
+ icons: ['add_to_front', 'soviet_support', 'draw_card'],
strength: 1,
title: 'THÄLMANN BATTALION',
type: 'pc',
@@ -461,6 +518,7 @@ const data: StaticData = {
create_effect('draw_card', SELF, 2),
create_effect('add_to_tableau', ANY, 1),
],
+ icons: ['soviet_support', 'd_collectivization', 'draw_card'],
strength: 1,
title: 'DE-COLLECTIVIZE AGRICULTURE',
type: 'pc',
@@ -469,11 +527,17 @@ const data: StaticData = {
id: 37,
effects: [
create_effect('front', ANY, 1),
- create_effect('track', COLLECTIVIZATION,2),
+ create_effect('track', COLLECTIVIZATION, 2),
create_effect('track', LIBERTY, 2),
create_effect('track', GOVERNMENT, TOWARDS_CENTER),
create_effect('hero_points', SELF, 1),
],
+ icons: [
+ 'add_to_front',
+ 'collectivization',
+ 'liberty',
+ 'government_to_center',
+ ],
strength: 3,
title: 'BUENAVENTURA DURRUTI',
type: 'pc',
@@ -486,6 +550,7 @@ const data: StaticData = {
create_effect('draw_card', SELF, 1),
create_effect('swap_card_tableau_hand', ANY, 1),
],
+ icons: ['liberty', 'd_soviet_support', 'draw_card'],
strength: 2,
title: 'MUJERES LIBRES',
type: 'pc',
@@ -497,6 +562,7 @@ const data: StaticData = {
create_effect('track', COLLECTIVIZATION, 1),
create_effect('draw_card', SELF, 2),
],
+ icons: ['add_to_front', 'collectivization', 'draw_card'],
strength: 1,
title: 'IRON COLUMN',
type: 'pc',
@@ -508,6 +574,7 @@ const data: StaticData = {
create_effect('track', COLLECTIVIZATION, 2),
create_effect('draw_card', SELF, 1),
],
+ icons: ['add_to_front', 'collectivization', 'draw_card'],
strength: 2,
title: 'ASTURIAN MINERS',
type: 'pc',
@@ -519,6 +586,7 @@ const data: StaticData = {
create_effect('track', COLLECTIVIZATION, 3),
create_effect('return_card', TRASH, 1),
],
+ icons: ['teamwork_on', 'collectivization', 'draw_card'],
strength: 2,
title: 'CNT-FAI',
type: 'pc',
@@ -531,6 +599,7 @@ const data: StaticData = {
create_effect('front', MADRID, 1),
// create_effect('ability') // activate ability
],
+ icons: ['liberty', 'add_to_front'],
strength: 2,
title: 'DURRUTI COLUMN',
type: 'pc',
@@ -544,6 +613,7 @@ const data: StaticData = {
create_effect('draw_card', SELF, 3),
create_effect('draw_card', OTHER_PLAYERS, 1),
],
+ icons: ['teamwork_on', 'add_to_front', 'd_soviet_support', 'draw_card'],
strength: 1,
title: 'GEORGE ORWELL',
type: 'pc',
@@ -556,6 +626,7 @@ const data: StaticData = {
create_effect('track', LIBERTY, 1),
create_effect('track', FOREIGN_AID, -1),
],
+ icons: ['add_to_front', 'liberty', 'd_foreign_aid'],
strength: 1,
title: 'F.I.J.L.',
type: 'pc',
@@ -565,8 +636,9 @@ const data: StaticData = {
effects: [
create_effect('front', ANY, 2),
// create_effect('track', COLLECTIVIZATION, 1) // conditional
- create_effect('track', FOREIGN_AID, -3)
+ create_effect('track', FOREIGN_AID, -3),
],
+ icons: ['add_to_front', 'collectivization', 'd_foreign_aid'],
strength: 1,
title: 'ARM THE UNIONS',
type: 'pc',
@@ -578,6 +650,7 @@ const data: StaticData = {
create_effect('track', LIBERTY, 2),
// create_effect('special') // Peek at Fascist cards
],
+ icons: ['teamwork_on', 'liberty', 'add_to_front'],
strength: 1,
title: 'GUERRILLAS',
type: 'pc',
@@ -590,6 +663,7 @@ const data: StaticData = {
create_effect('track', GOVERNMENT, TOWARDS_CENTER),
create_effect('draw_card', SELF, 1),
],
+ icons: ['liberty', 'government_to_center', 'draw_card'],
strength: 1,
title: 'RADICAL EDUCATION',
type: 'pc',
@@ -601,6 +675,7 @@ const data: StaticData = {
create_effect('track', SOVIET_SUPPORT, -2),
create_effect('draw_card', SELF, 3),
],
+ icons: ['add_to_front', 'd_soviet_support', 'draw_card'],
strength: 1,
title: 'MATTEOTTI BATTALION',
type: 'pc',
@@ -611,6 +686,7 @@ const data: StaticData = {
create_effect('track', COLLECTIVIZATION, 4),
create_effect('draw_card', SELF, 1),
],
+ icons: ['collectivization', 'draw_card'],
strength: 1,
title: 'COLLECTIVIZE AGRICULTURE',
type: 'pc',
@@ -622,6 +698,7 @@ const data: StaticData = {
// create_effect('front', ARAGON, 3) // conditional
create_effect('track', FOREIGN_AID, -1),
],
+ icons: ['collectivization', 'add_to_front', 'd_foreign_aid'],
strength: 1,
title: 'ARMORED VEHICLES',
type: 'pc',
@@ -633,6 +710,7 @@ const data: StaticData = {
create_effect('track', FOREIGN_AID, -2),
create_effect('track', GOVERNMENT, TOWARDS_CENTER),
],
+ icons: ['collectivization', 'd_foreign_aid', 'government_to_center'],
strength: 1,
title: 'INDUSTRIAL DEMOCRACY',
type: 'pc',
@@ -644,6 +722,12 @@ const data: StaticData = {
// create_effect('track') // choose
create_effect('track', GOVERNMENT, TOWARDS_CENTER),
],
+ icons: [
+ 'add_to_front',
+ 'liberty',
+ 'collectivization',
+ 'government_to_center',
+ ],
strength: 2,
title: 'AFFINITY GROUPS',
type: 'pc',
@@ -655,6 +739,7 @@ const data: StaticData = {
// create_effect('front', ANY, 3) // conditional
create_effect('hero_points', SELF, 1),
],
+ icons: ['liberty', 'add_to_front'],
strength: 1,
title: 'GENDER-INCLUSIVE MILITIA',
type: 'pc',
@@ -666,6 +751,7 @@ const data: StaticData = {
create_effect('track', SOVIET_SUPPORT, -1),
create_effect('add_to_tableau', ANY, 1),
],
+ icons: ['liberty', 'd_soviet_support', 'draw_card'],
strength: 1,
title: 'FEDERICA MONTSENY',
type: 'pc',
@@ -752,7 +838,7 @@ const data: StaticData = {
effects: [
create_effect('attack', SOUTHERN, -5),
create_effect('bonus', MORALE_BONUS, OFF),
- create_effect('hero_points', PLAYER_WITH_MOST_HERO_POINTS, -1),
+ create_effect('track', LIBERTY, -1),
],
title: 'AIRLIFT OF THE ARMY OF AFRICA',
type: 'ec',
diff --git a/land-and-freedom.css b/land-and-freedom.css
index 00fbfd0..9452199 100644
--- a/land-and-freedom.css
+++ b/land-and-freedom.css
@@ -1,5 +1,5 @@
main {
- background-color: darkolivegreen;
+ background-color: #7B904B;
}
/* MAP */
@@ -26,13 +26,39 @@ main {
background-image: url(images/map100.png);
}
}
-#hand {
+.panel {
+ min-width: 1271px;
+ max-width: 1271px;
+ background-color: #58641D;
+ margin: 12px auto;
+ box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.2666666667);
+ border: 2px solid #333;
+}
+
+.panel_body {
display: flex;
- flex-direction: row;
- gap: 8px;
- margin-top: 16px;
- padding: 16px;
justify-content: center;
+ flex-wrap: wrap;
+ padding: 12px;
+ gap: 12px;
+ min-height: 260px;
+}
+
+.panel_header {
+ color: white;
+ user-select: none;
+ font-weight: bold;
+ text-align: center;
+ border-bottom: 2px solid #333;
+ background-color: red;
+}
+
+#hand_header {
+ background-color: #273B09;
+}
+
+.panel_header[data-faction-id=a] {
+ background: linear-gradient(45deg, black 50%, red 0);
}
.front {
@@ -321,6 +347,17 @@ main {
height: 180px;
}
+.blank_marker {
+ box-sizing: border-box;
+ position: absolute;
+ background-color: red;
+ width: 29px;
+ height: 29px;
+ border-radius: 50%;
+ box-shadow: 0 0 0 1px #333;
+ margin-top: 1px;
+}
+
.standee {
box-sizing: border-box;
position: absolute;
@@ -333,14 +370,17 @@ main {
transition-property: top, left;
transition-duration: 700ms;
transition-timing-function: ease;
+ z-index: 1;
}
+.bonus.action,
.card.action,
.front.action,
.standee.action {
box-shadow: 0 0 0 3px white;
}
+.bonus.action:hover,
.card.action:hover,
.card.selected,
.front.action:hover,
@@ -375,6 +415,7 @@ main {
height: 54px;
background-size: cover;
background-repeat: no-repeat;
+ border-radius: 50%;
}
.bonus[data-bonus-id="0"][data-bonus-on="0"] {
diff --git a/land-and-freedom.scss b/land-and-freedom.scss
index 5dd9325..3602c26 100644
--- a/land-and-freedom.scss
+++ b/land-and-freedom.scss
@@ -6,7 +6,8 @@ $selected-color: yellow; //blue;
main {
// background-color: rgb(213, 196, 131);
- background-color: darkolivegreen;
+ // background-color: darkolivegreen;
+ background-color: #7B904B;;
}
/* MAP */
@@ -43,15 +44,52 @@ main {
}
}
-#hand {
+.panel {
+ min-width: 1271px;
+ max-width: 1271px;
+ // background-color: hsl(34, 10%, 35%);
+ background-color: #58641D;
+ margin: 12px auto;
+ box-shadow: 1px 2px 4px #0004;
+ border: 2px solid #333;
+}
+
+.panel_body {
display: flex;
- flex-direction: row;
- gap: 8px;
- margin-top: 16px;
- padding: 16px;
justify-content: center;
+ flex-wrap: wrap;
+ padding: 12px;
+ gap: 12px;
+ min-height: 260px;
+}
+
+.panel_header {
+ color: white;
+ user-select: none;
+ font-weight: bold;
+ text-align: center;
+ border-bottom: 2px solid #333;
+ background-color: red;
}
+#hand_header {
+ background-color: #273B09;
+}
+
+.panel_header[data-faction-id="a"] {
+ background: linear-gradient(45deg, black 50%, red 0);
+}
+
+// #hand,
+// .tableau {
+// display: flex;
+// flex-direction: row;
+// gap: 8px;
+// margin-top: 16px;
+// padding: 16px;
+// justify-content: center;
+// }
+
.front {
position: absolute;
box-sizing: border-box;
@@ -102,6 +140,17 @@ main {
height: 180px;
}
+.blank_marker {
+ box-sizing: border-box;
+ position: absolute;
+ background-color: red;
+ width: 29px;
+ height: 29px;
+ border-radius: 50%;
+ box-shadow: 0 0 0 1px #333;
+ margin-top: 1px;
+}
+
.standee {
box-sizing: border-box;
position: absolute;
@@ -114,15 +163,18 @@ main {
transition-property: top, left;
transition-duration: 700ms;
transition-timing-function: ease;
+ z-index: 1;
// opacity: 0.6;
}
+.bonus.action,
.card.action,
.front.action,
.standee.action {
box-shadow: 0 0 0 3px $selectable-color;
}
+.bonus.action:hover,
.card.action:hover,
.card.selected,
.front.action:hover,
@@ -147,6 +199,7 @@ main {
height: 54px;
background-size: cover;
background-repeat: no-repeat;
+ border-radius: 50%;
}
@for $i from 0 through 1 {
diff --git a/play.html b/play.html
index 0dfdfe0..04e8168 100644
--- a/play.html
+++ b/play.html
@@ -43,11 +43,28 @@
<div id="spaces">
</div>
<div id="pieces"></div>
+ <div id="markers"></div>
<div id="tracks"></div>
<div id="current_events"></div>
</div>
</div>
- <div id="hand"></div>
+
+ <div class="panel">
+ <div id="hand_header" class="panel_header">Hand</div>
+ <div id="hand" class="panel_body"></div>
+ </div>
+ <div class="panel">
+ <div class="panel_header" data-faction-id="a">Anarchist</div>
+ <div id="tableau_a" class="panel_body"></div>
+ </div>
+ <div class="panel">
+ <div class="panel_header" data-faction-id="c">Communist</div>
+ <div id="tableau_c" class="panel_body"></div>
+ </div>
+ <div class="panel">
+ <div class="panel_header" data-faction-id="m">Moderate</div>
+ <div id="tableau_m" class="panel_body"></div>
+ </div>
</main>
<footer id="status"></footer>
diff --git a/play.js b/play.js
index c654730..7607bc4 100644
--- a/play.js
+++ b/play.js
@@ -1,14 +1,24 @@
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
const BONUSES_COUNT = 2;
-const CARD_COUNT = 62;
+const CARD_COUNT = 63;
const MEDAILLONS_COUNT = 5;
const STANDEES_COUNT = 5;
+const TRACK_COUNT = 5;
+const TRACK_LENGTH = 11;
+const FACTIONS = ['a', 'c', 'm'];
let ui = {
map: document.getElementById('map'),
+ markers: document.getElementById('markers'),
hand: document.getElementById('hand'),
current_events: document.getElementById('current_events'),
+ tableaus: {
+ a: document.getElementById('tableau_a'),
+ c: document.getElementById('tableau_c'),
+ m: document.getElementById('tableau_m'),
+ },
tracks: document.getElementById('tracks'),
+ blank_markers: [[], [], [], [], []],
bonuses: [],
fronts: {},
frontValues: {},
@@ -147,6 +157,13 @@ function on_init() {
on_init_once = true;
console.log('ui', ui);
console.log('document', document);
+ for (let t = 0; t < 5; ++t) {
+ for (let bm = 0; bm < TRACK_LENGTH; ++bm) {
+ let e = (ui.blank_markers[t][bm] = document.createElement('div'));
+ e.className = 'blank_marker';
+ register_action(e, 'blank_marker', bm);
+ }
+ }
for (let b = 0; b < BONUSES_COUNT; ++b) {
let e = (ui.bonuses[b] = document.createElement('div'));
e.className = 'bonus';
@@ -191,6 +208,14 @@ function on_update() {
ui.cards[cardId].style.left = LAYOUT_CURRENT_EVENTS[i][0] + 'px';
ui.cards[cardId].style.top = LAYOUT_CURRENT_EVENTS[i][1] + 'px';
}
+ ui.markers.replaceChildren();
+ for (let t = 0; t < TRACK_COUNT; ++t) {
+ for (let bm of view.triggered_track_effects[t]) {
+ ui.markers.appendChild(ui.blank_markers[t][bm]);
+ ui.blank_markers[t][bm].style.left = LAYOUT_TRACKS[t][bm][0] + 'px';
+ ui.blank_markers[t][bm].style.top = LAYOUT_TRACKS[t][bm][1] + 'px';
+ }
+ }
for (let bonus_id of Object.keys(view.bonuses)) {
ui.bonuses[bonus_id].setAttribute('data-bonus-on', view.bonuses[bonus_id] + 0);
}
@@ -202,7 +227,6 @@ function on_update() {
ui.cards[c].classList.add('selected');
}
}
- ;
for (let i = 0; i < view.tracks.length; ++i) {
ui.standees[i].style.left = LAYOUT_TRACKS[i][view.tracks[i]][0] + 'px';
ui.standees[i].style.top = LAYOUT_TRACKS[i][view.tracks[i]][1] + 'px';
@@ -216,11 +240,19 @@ function on_update() {
ui.medaillons[i].style.top = LAYOUT_MEDAILLONS[i][1] + 'px';
}
}
+ for (let faction_id of FACTIONS) {
+ ui.tableaus[faction_id].replaceChildren();
+ for (let c of view.tableaus[faction_id]) {
+ ui.cards[c].classList.remove('selected');
+ ui.tableaus[faction_id].appendChild(ui.cards[c]);
+ }
+ }
for (let e of action_register)
e.classList.toggle('action', is_action(e.my_action, e.my_id));
action_button('Anarchist', 'Anarchist');
action_button('Communist', 'Communist');
action_button('Moderate', 'Moderate');
+ action_button('gain_hp', 'Gain Hero Points');
action_button('draw_card', 'Draw card');
action_button('play_for_ap', 'Play card for Action Points');
action_button('play_for_event', 'Play card for Event');
@@ -229,6 +261,7 @@ function on_update() {
action_button('up', 'Up');
action_button('down', 'Down');
action_button('next', 'Next');
+ action_button('skip', 'Skip');
action_button('done', 'Done');
action_button('undo', 'Undo');
}
diff --git a/play.ts b/play.ts
index 644ec89..36d64e5 100644
--- a/play.ts
+++ b/play.ts
@@ -12,15 +12,25 @@ declare const view: View;
const BONUSES_COUNT = 2;
// const PIECE_COUNT = 32;
-const CARD_COUNT = 62;
+const CARD_COUNT = 63;
const MEDAILLONS_COUNT = 5;
const STANDEES_COUNT = 5;
+const TRACK_COUNT = 5;
+const TRACK_LENGTH = 11;
+const FACTIONS = ['a', 'c', 'm'];
let ui = {
map: document.getElementById('map'),
+ markers: document.getElementById('markers'),
hand: document.getElementById('hand'),
current_events: document.getElementById('current_events'),
+ tableaus: {
+ a: document.getElementById('tableau_a'),
+ c: document.getElementById('tableau_c'),
+ m: document.getElementById('tableau_m'),
+ },
tracks: document.getElementById('tracks'),
+ blank_markers: [[], [], [], [], []],
bonuses: [],
fronts: {},
frontValues: {},
@@ -179,20 +189,14 @@ function on_init() {
console.log('document', document);
- // create space elements
- // for (let s = 0; s < SPACE_COUNT; ++s) {
- // let e = ui.spaces[s].document.createElement('div');
- // e.className = 'space';
- // register_action(e, 'space', s);
- // ui.map.appendChild(e);
- // }
-
- // // create piece elements
- // for (let p = 0; p < PIECE_COUNT; ++p) {
- // let e = (ui.pieces[p] = document.createElement('div'));
- // e.className = 'piece';
- // register_action(e, 'piece', p);
- // }
+ // Create blank_markers
+ for (let t = 0; t < 5; ++t) {
+ for (let bm = 0; bm < TRACK_LENGTH; ++bm) {
+ let e = (ui.blank_markers[t][bm] = document.createElement('div'));
+ e.className = 'blank_marker';
+ register_action(e, 'blank_marker', bm);
+ }
+ }
// create bonus markers
for (let b = 0; b < BONUSES_COUNT; ++b) {
@@ -257,6 +261,16 @@ function on_update() {
ui.cards[cardId].style.top = LAYOUT_CURRENT_EVENTS[i][1] + 'px';
}
+
+ ui.markers.replaceChildren();
+ for (let t = 0; t < TRACK_COUNT; ++t) {
+ for (let bm of view.triggered_track_effects[t]) {
+ ui.markers.appendChild(ui.blank_markers[t][bm]);
+ ui.blank_markers[t][bm].style.left = LAYOUT_TRACKS[t][bm][0] + 'px';
+ ui.blank_markers[t][bm].style.top = LAYOUT_TRACKS[t][bm][1] + 'px';
+ }
+ }
+
for (let bonus_id of Object.keys(view.bonuses)) {
ui.bonuses[bonus_id].setAttribute(
'data-bonus-on',
@@ -271,7 +285,7 @@ function on_update() {
if (c === view.selected_card) {
ui.cards[c].classList.add('selected');
}
- };
+ }
for (let i = 0; i < view.tracks.length; ++i) {
// ui.tracks.appendChild(ui.standees[i]);
@@ -290,12 +304,21 @@ function on_update() {
}
}
+ for (let faction_id of FACTIONS) {
+ ui.tableaus[faction_id].replaceChildren();
+ for (let c of view.tableaus[faction_id]) {
+ ui.cards[c].classList.remove('selected');
+ ui.tableaus[faction_id].appendChild(ui.cards[c]);
+ }
+ }
+
for (let e of action_register)
e.classList.toggle('action', is_action(e.my_action, e.my_id));
action_button('Anarchist', 'Anarchist');
action_button('Communist', 'Communist');
action_button('Moderate', 'Moderate');
+ action_button('gain_hp', 'Gain Hero Points');
action_button('draw_card', 'Draw card');
action_button('play_for_ap', 'Play card for Action Points');
action_button('play_for_event', 'Play card for Event');
@@ -304,6 +327,7 @@ function on_update() {
action_button('up', 'Up');
action_button('down', 'Down');
action_button('next', 'Next');
+ action_button('skip', 'Skip');
action_button('done', 'Done');
action_button('undo', 'Undo');
}
diff --git a/rules.js b/rules.js
index 62592e5..8dc2b2e 100644
--- a/rules.js
+++ b/rules.js
@@ -26,14 +26,16 @@ const player_faction_map = {
[exports.MODERATE]: MODERATES_ID,
};
const front_names = {
- a: 'the Aragon Front',
- m: 'the Madrid Front',
- n: 'the Nothern Front',
- s: 'the Southern Front',
+ a: 'Aragon Front',
+ m: 'Madrid Front',
+ n: 'Nothern Front',
+ s: 'Southern Front',
d: 'the Front closest to Defeat',
v: 'the Front closest to Victory',
};
+const bonus_names = ['Morale Bonus', 'Teamwork Bonus'];
const { cards, tracks, } = data_1.default;
+const bonuses = [data_1.MORALE_BONUS, data_1.TEAMWORK_BONUS];
const faction_cards = {
[ANARCHISTS_ID]: make_list(37, 54),
[COMMUNISTS_ID]: make_list(19, 36),
@@ -56,9 +58,15 @@ function gen_action(action, argument) {
view.actions[action].push(argument);
}
}
+function gen_action_bonus(bonus_id) {
+ gen_action('bonus', bonus_id);
+}
function gen_action_card(card_id) {
gen_action('card', card_id);
}
+function gen_action_front(front_id) {
+ gen_action('front', front_id);
+}
function gen_action_standee(track_id) {
gen_action('standee', track_id);
}
@@ -78,59 +86,53 @@ const leaf_node = 'l';
const seq_node = 's';
const function_node = 'f';
const resolved = 1;
+function create_leaf_node(state, faction, args) {
+ return {
+ t: leaf_node,
+ s: state,
+ p: faction,
+ a: args,
+ r: 0,
+ };
+}
+function create_function_node(func_name, args) {
+ return {
+ t: function_node,
+ f: func_name,
+ a: args,
+ r: 0,
+ };
+}
+function create_seq_node(children) {
+ return {
+ t: seq_node,
+ c: children,
+ };
+}
function setup_bag_of_glory() {
- console.log('setup_bag_of_glory');
game.engine = [
- {
- t: leaf_node,
- p: game.initiative,
- s: 'add_glory',
- },
- {
- t: function_node,
- f: 'end_of_turn',
- },
+ create_leaf_node('add_glory', game.initiative),
+ create_function_node('end_of_turn'),
];
next();
}
function setup_choose_card() {
console.log('setup_choose_card');
const player_order = get_player_order();
- game.engine = player_order.map((faction_id) => ({
- t: leaf_node,
- p: faction_id,
- s: 'choose_card',
- }));
- game.engine.push({
- t: function_node,
- f: 'setup_player_turn',
- });
+ game.engine = player_order.map((faction_id) => create_leaf_node('choose_card', faction_id));
+ game.engine.push(create_function_node('setup_player_turn'));
next();
}
function setup_player_turn() {
console.log('setup_player_turn');
const player_order = get_player_order();
- game.engine = player_order.map((faction_id) => ({
- t: seq_node,
- c: [
- {
- t: leaf_node,
- s: 'player_turn',
- p: faction_id,
- },
- ],
- }));
- game.engine.push({
- t: function_node,
- f: 'resolve_fascist_test',
- });
- game.engine.push({
- t: function_node,
- f: 'setup_bag_of_glory',
- });
+ game.engine = player_order.map((faction_id) => create_seq_node([create_leaf_node('player_turn', faction_id)]));
+ game.engine.push(create_function_node('resolve_fascist_test'));
+ game.engine.push(create_function_node('setup_bag_of_glory'));
next();
}
const engine_functions = {
+ check_activate_icon,
end_of_turn,
end_of_year,
setup_bag_of_glory,
@@ -224,8 +226,10 @@ function game_view(state, player) {
fronts: game.fronts,
hand: game.hands[faction_id],
medaillons: game.medaillons,
- selected_card: game.cards_in_play[faction_id],
+ selected_card: game.chosen_cards[faction_id],
+ tableaus: game.tableaus,
tracks: game.tracks,
+ triggered_track_effects: game.triggered_track_effects,
};
if (player !== game.active) {
let inactive = states[game.state].inactive || game.state;
@@ -278,7 +282,7 @@ function setup(seed, _scenario, _options) {
[MODERATES_ID]: 0,
pool: 14,
},
- cards_in_play: {
+ chosen_cards: {
[ANARCHISTS_ID]: null,
[COMMUNISTS_ID]: null,
[MODERATES_ID]: null,
@@ -297,6 +301,11 @@ function setup(seed, _scenario, _options) {
[MODERATES_ID]: [],
},
tracks: [5, 5, 6, 3, 3],
+ trash: {
+ [ANARCHISTS_ID]: [],
+ [COMMUNISTS_ID]: [],
+ [MODERATES_ID]: [],
+ },
triggered_track_effects: [[], [], [], [], []],
log: [],
undo: [],
@@ -335,6 +344,12 @@ function start_turn() {
});
next();
}
+states.activate_icon = {
+ inactive: 'activate an icon',
+ prompt() {
+ view.prompt = 'Choose an icon to activate';
+ }
+};
states.add_glory = {
inactive: 'add tokens to the Bag of Glory',
prompt() {
@@ -357,25 +372,43 @@ states.add_glory = {
resolve_active_and_proceed();
},
};
+states.add_to_front = {
+ inactive: 'add strength to a Front',
+ prompt() {
+ const args = get_active_node_args();
+ const possible_fronts = get_fronts_to_add_to(args.t);
+ view.prompt =
+ possible_fronts.length === 1
+ ? `Add strength to ${front_names[possible_fronts[0]]}`
+ : 'Add strength to a Front';
+ for (let f of possible_fronts) {
+ gen_action_front(f);
+ }
+ },
+ front(f) {
+ const value = get_active_node_args().v;
+ update_front(f, value);
+ resolve_active_and_proceed();
+ },
+};
states.attack_front = {
inactive: 'attack a Front',
prompt() {
const node = get_active_node();
- const front = node.a.f;
+ const front = node.a.t;
view.prompt = 'Attack ' + front_names[front];
if (front === 'd' || front === 'v') {
const fronts = get_fronts_closest_to(front);
fronts.forEach((id) => gen_action('front', id));
}
else {
- gen_action('front', front);
+ gen_action_front(front);
}
},
front(f) {
const node = get_active_node();
const value = node.a.v;
- game.fronts[f] += value;
- log_h3(`${Math.abs(value)} attacks added to ${front_names[f]}`);
+ update_front(f, value);
resolve_active_and_proceed();
},
};
@@ -383,9 +416,18 @@ states.choose_area_ap = {
inactive: 'choose area to use Action Points',
prompt() {
view.prompt = 'Choose area of the board to affect';
- for (let track of tracks) {
+ for (const track of tracks) {
gen_action_standee(track.id);
}
+ const fronts = get_fronts_to_add_to(data_1.ANY);
+ for (const front of fronts) {
+ gen_action_front(front);
+ }
+ },
+ front(f) {
+ const s = get_active_node_args().strength;
+ update_front(f, s);
+ resolve_active_and_proceed();
},
standee(track_id) {
console.log('standee', track_id);
@@ -401,22 +443,36 @@ states.choose_area_ap = {
resolve_active_and_proceed();
},
};
-states.move_track_up_or_down = {
- inactive: 'move a track',
+states.change_bonus = {
+ inactive: 'gain select Bonus',
prompt() {
- const node = get_active_node();
- view.prompt = `Move ${get_track_name(node.a.track_id)} up or down`;
- gen_action('up');
- gen_action('down');
+ const args = get_active_node_args();
+ if ((args.v === data_1.ON &&
+ game.bonuses[data_1.TEAMWORK_BONUS] === data_1.ON &&
+ game.bonuses[data_1.MORALE_BONUS] === data_1.ON) ||
+ (args.v === data_1.OFF && game.bonuses[args.t] === data_1.OFF)) {
+ gen_action('skip');
+ }
+ if (args.t === data_1.ANY && args.v === data_1.ON) {
+ view.prompt = 'Turn on a Bonus';
+ for (const bonus of bonuses) {
+ if (game.bonuses[bonus] === data_1.OFF) {
+ gen_action_bonus(bonus);
+ }
+ }
+ }
+ else if (args.v === data_1.OFF) {
+ view.prompt = `Turn off ${bonus_names[args.t]}`;
+ gen_action_bonus(args.t);
+ }
},
- down() {
- const node = get_active_node();
- move_track(node.a.track_id, -1 * node.a.strength);
+ bonus(b) {
+ const value = get_active_node_args().v;
+ game.bonuses[b] = value;
+ log(`${bonus_names[b]} ${value === data_1.ON ? 'on' : 'off'}`);
resolve_active_and_proceed();
},
- up() {
- const node = get_active_node();
- move_track(node.a.track_id, node.a.strength);
+ skip() {
resolve_active_and_proceed();
},
};
@@ -429,18 +485,53 @@ states.choose_card = {
gen_action_card(c);
},
card(c) {
- log_h3(`${game.active} chooses a card`);
- if (!game.cards_in_play) {
- game.cards_in_play = {};
+ game.chosen_cards[player_faction_map[game.active]] = c;
+ resolve_active_and_proceed();
+ },
+};
+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');
+ },
+ gain_hp() {
+ const value = get_active_node_args().v;
+ if (game.hero_points.pool > value) {
+ game.hero_points.pool -= value;
+ game.hero_points[get_active_faction()] += value;
}
- game.cards_in_play[player_faction_map[game.active]] = c;
resolve_active_and_proceed();
},
};
states.lose_hero_points = {
inactive: 'choose a Player',
prompt() {
- view.prompt = 'Lose Hero Points';
+ const args = get_active_node_args();
+ view.prompt = 'Choose player to lose Hero Points';
+ if (args.t === data_1.PLAYER_WITH_MOST_HERO_POINTS) {
+ const factions = get_factions_with_most_hero_poins();
+ console.log('faction', factions);
+ for (let faction_id of factions) {
+ gen_action(faction_player_map[faction_id]);
+ }
+ }
+ },
+ Anarchist() {
+ const value = get_active_node_args().v;
+ lose_hero_point(ANARCHISTS_ID, value);
+ resolve_active_and_proceed();
+ },
+ Communist() {
+ const value = get_active_node_args().v;
+ lose_hero_point(ANARCHISTS_ID, value);
+ resolve_active_and_proceed();
+ },
+ Moderate() {
+ const value = get_active_node_args().v;
+ lose_hero_point(ANARCHISTS_ID, value);
+ resolve_active_and_proceed();
},
};
states.move_track = {
@@ -459,23 +550,46 @@ states.move_track = {
resolve_active_and_proceed();
},
};
+states.move_track_up_or_down = {
+ inactive: 'move a track',
+ prompt() {
+ const node = get_active_node();
+ view.prompt = `Move ${get_track_name(node.a.track_id)} up or down`;
+ gen_action('up');
+ gen_action('down');
+ },
+ down() {
+ const node = get_active_node();
+ move_track(node.a.track_id, -1 * node.a.strength);
+ resolve_active_and_proceed();
+ },
+ up() {
+ const node = get_active_node();
+ move_track(node.a.track_id, node.a.strength);
+ resolve_active_and_proceed();
+ },
+};
states.player_turn = {
inactive: 'play their turn',
prompt() {
const faction_id = get_faction_id(game.active);
- const hero_points = game.hero_points[faction_id];
- view.prompt =
- hero_points === 0
- ? 'Play your card'
- : 'Play your card or spend Hero points';
- if (game.cards_in_play[faction_id] !== null) {
+ const can_spend_hp = game.hero_points[faction_id] > 0;
+ const can_play_card = game.hands[faction_id].includes(game.chosen_cards[faction_id]);
+ view.prompt = 'Play a card or spend Hero points';
+ if (!(can_play_card || can_spend_hp)) {
+ view.prompt = 'End turn';
+ }
+ else if (!can_play_card && can_spend_hp) {
+ view.prompt = 'Spend Hero Points or end turn';
+ }
+ if (can_play_card) {
gen_action('play_for_ap');
gen_action('play_for_event');
}
else {
gen_action('done');
}
- if (hero_points > 0) {
+ if (can_spend_hp) {
gen_action('spend_hp');
}
},
@@ -484,34 +598,25 @@ states.player_turn = {
},
play_for_ap() {
const faction_id = get_faction_id(game.active);
- const card = game.cards_in_play[faction_id];
+ const card = game.chosen_cards[faction_id];
log_h3(`${game.active} plays ${cards[card].title} for the Action Points`);
- if (!game.discard) {
- game.discard = {
- [ANARCHISTS_ID]: [],
- [COMMUNISTS_ID]: [],
- [MODERATES_ID]: [],
- f: [],
- };
- }
array_remove(game.hands[faction_id], game.hands[faction_id].indexOf(card));
- game.discard[faction_id].push(card);
- insert_before_active_node({
- t: leaf_node,
- p: faction_id,
- s: 'choose_area_ap',
- a: {
+ game.tableaus[faction_id].push(card);
+ insert_before_active_node(create_seq_node([
+ create_leaf_node('choose_area_ap', faction_id, {
strength: cards[card].strength,
- },
- });
+ }),
+ create_function_node('check_activate_icon'),
+ ]));
next();
},
play_for_event() {
const faction_id = get_faction_id(game.active);
- const card = game.cards_in_play[faction_id];
+ const card = game.chosen_cards[faction_id];
+ array_remove(game.hands[faction_id], game.hands[faction_id].indexOf(card));
+ game.trash[faction_id].push(card);
log_h3(`${game.active} plays ${cards[card].title} for the Event`);
- game.cards_in_play[faction_id] = null;
- game.tableaus[faction_id].push(card);
+ insert_after_active_node(create_effects_node(cards[card].effects));
resolve_active_and_proceed();
},
spend_hp() {
@@ -522,52 +627,6 @@ states.player_turn = {
});
next();
},
- card(c) {
- const faction = get_active_faction();
- log_h3(`${game.active} plays ${cards[c].title} to their tableau`);
- if (!game.tableaus) {
- game.tableaus = {
- [ANARCHISTS_ID]: [],
- [COMMUNISTS_ID]: [],
- [MODERATES_ID]: [],
- };
- }
- game.cards_in_play[faction] = null;
- game.tableaus[faction].push(c);
- array_remove(game.hands[faction], game.hands[faction].indexOf(c));
- resolve_active_and_proceed();
- },
-};
-states.resolve_event = {
- inactive: 'resolve Fascist Event',
- prompt() {
- const card = get_current_event();
- const node = get_active_node(game.engine);
- const effect = card.effects[node.a];
- view.prompt = get_event_prompt(effect);
- if (effect.type === 'track') {
- gen_action('standee', effect.target);
- }
- else if (effect.type === 'hero_points' &&
- effect.target === data_1.PLAYER_WITH_MOST_HERO_POINTS) {
- const factions = get_factions_with_most_hero_poins();
- for (let faction_id of factions) {
- gen_action(get_player(faction_id));
- }
- }
- },
- Anarchist() {
- lose_hero_point(ANARCHISTS_ID, 1);
- resolve_active_and_proceed();
- },
- Communist() {
- lose_hero_point(ANARCHISTS_ID, 1);
- resolve_active_and_proceed();
- },
- Moderate() {
- lose_hero_point(ANARCHISTS_ID, 1);
- resolve_active_and_proceed();
- },
};
states.spend_hero_points = {
inactive: 'spend Hero points',
@@ -595,6 +654,12 @@ function pop_undo() {
game.log = save_log;
game.undo = save_undo;
}
+function check_activate_icon() {
+ if (game.bonuses[data_1.MORALE_BONUS] === data_1.ON) {
+ insert_after_active_node(create_leaf_node('activate_icon', get_active_faction_id()));
+ }
+ resolve_active_and_proceed();
+}
function end_of_turn() {
log_h2('End of turn');
if (game.turn === 4) {
@@ -611,13 +676,25 @@ function resolve_fascist_test() {
log_h2('Fascist test is resolved');
next();
}
+function get_fronts_to_add_to(target) {
+ console.log('get_fronts_to_add_to', target);
+ if (target === data_1.CLOSEST_TO_DEFEAT || target === data_1.CLOSEST_TO_VICTORY) {
+ return get_fronts_closest_to(target);
+ }
+ else if (target === data_1.ANY) {
+ return ['a', 'm', 'n', 's'];
+ }
+ else {
+ return [target];
+ }
+}
function move_track(track_id, change) {
const current_value = game.tracks[track_id];
let new_value = current_value + change;
new_value = Math.max(new_value, track_id === data_1.GOVERNMENT ? 1 : 0);
new_value = Math.min(new_value, 10);
game.tracks[track_id] = new_value;
- log(`${game.active} moves ${get_track_name(track_id)} to ${new_value}`);
+ log(`${get_track_name(track_id)} to ${new_value}`);
const triggered_spaces = change > 0
? make_list(current_value + 1, new_value).reverse()
: make_list(new_value, current_value - 1);
@@ -635,42 +712,46 @@ function move_track(track_id, change) {
}
});
}
+function update_front(f, change) {
+ game.fronts[f] += change;
+ log(`${front_names[f]}: ${change > 0 ? '+' : ''}${change}`);
+}
+function create_effects_node(effects) {
+ const nodes = effects.reduce((accrued, current) => {
+ const node = resolve_effect(current);
+ if (node !== null) {
+ accrued.push(node);
+ }
+ return accrued;
+ }, []);
+ return {
+ t: seq_node,
+ c: nodes,
+ };
+}
+const effect_type_state_map = {
+ attack: 'attack_front',
+ bonus: 'change_bonus',
+ front: 'add_to_front',
+ track: 'move_track',
+};
function resolve_effect(effect, faction = get_active_faction()) {
- if (effect.type === 'attack') {
- return {
- t: leaf_node,
- p: faction,
- s: 'attack_front',
- a: {
- f: effect.target,
- v: effect.value,
- },
- };
- }
- if (effect.type === 'track') {
- return {
- t: leaf_node,
- p: faction,
- s: 'move_track',
- a: {
- t: effect.target,
- v: effect.value,
- },
- };
+ const args = {
+ t: effect.target,
+ 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) {
- return {
- t: leaf_node,
- p: faction,
- s: 'lose_hero_points',
- a: {
- p: effect.target,
- v: effect.value,
- },
- };
+ state = 'lose_hero_points';
}
- return null;
+ if (effect.type === 'hero_points' && effect.target === data_1.SELF) {
+ state = 'gain_hero_points';
+ }
+ return state === undefined ? null : create_leaf_node(state, faction, args);
}
function draw_card(deck) {
clear_undo();
@@ -686,33 +767,19 @@ function draw_item(ids) {
return r;
}
function lose_hero_point(faction, value) {
- const points_lost = Math.min(game.hero_points[faction], value);
+ const points_lost = Math.min(game.hero_points[faction], Math.abs(value));
game.hero_points.pool += points_lost;
game.hero_points[faction] -= points_lost;
+ if (points_lost === 0) {
+ return;
+ }
if (points_lost === 1) {
- log(`${get_player(faction)} loses 1 Hero Point`);
+ log(`${get_player(faction)}: -1 Hero Point`);
}
else {
- log(`${get_player(faction)} loses ${points_lost} Hero Points`);
+ log(`${get_player(faction)}: -${points_lost} Hero Points`);
}
}
-function get_current_event() {
- return cards[game.current_events[game.current_events.length - 1]];
-}
-function get_event_prompt(effect) {
- let prompt = '';
- switch (effect.type) {
- case 'attack':
- return 'Attack ' + front_names[effect.target];
- case 'bonus':
- break;
- case 'hero_points':
- return 'Select player with most Hero points';
- case 'track':
- return 'Decrease ' + tracks[effect.target].name;
- }
- return prompt;
-}
function get_fronts_closest_to(target) {
const values = Object.values(game.fronts);
const targetValue = target === 'd' ? Math.min(...values) : Math.max(...values);
@@ -783,11 +850,18 @@ function get_next_faction(faction_id) {
return role_ids[index + 1];
}
function get_factions_with_most_hero_poins() {
- const most_hero_points = Math.max(...Object.values(game.hero_points));
- const faction_ids = [];
- Object.entries(game.hero_points).forEach(([faction, hero_points]) => {
- if (hero_points === most_hero_points) {
- faction_ids.push(faction);
+ let most_hero_points = null;
+ let faction_ids = [];
+ Object.entries(game.hero_points).forEach(([id, value]) => {
+ if (id === 'pool') {
+ return;
+ }
+ if (most_hero_points === null || value > most_hero_points) {
+ most_hero_points = value;
+ faction_ids = [id];
+ }
+ else if (most_hero_points === value) {
+ faction_ids.push(id);
}
});
return faction_ids;
diff --git a/rules.ts b/rules.ts
index 0b4901f..e5206bd 100644
--- a/rules.ts
+++ b/rules.ts
@@ -11,6 +11,7 @@ import {
LeafNode,
Player,
PlayerCard,
+ SeqNode,
States,
View,
} from './types';
@@ -24,13 +25,20 @@ import data, {
// MORALE_BONUS,
// TEAMWORK_BONUS,
// OFF,
- ON,
LIBERTY,
+ CLOSEST_TO_DEFEAT,
+ CLOSEST_TO_VICTORY,
COLLECTIVIZATION,
GOVERNMENT,
SOVIET_SUPPORT,
FOREIGN_AID,
+ ON,
PLAYER_WITH_MOST_HERO_POINTS,
+ SELF,
+ ANY,
+ TEAMWORK_BONUS,
+ MORALE_BONUS,
+ OFF,
// StaticData,
// PLAYER_WITH_MOST_HERO_POINTS,
} from './data';
@@ -67,20 +75,24 @@ const player_faction_map: Record<Player, FactionId> = {
};
const front_names: Record<string, string> = {
- a: 'the Aragon Front',
- m: 'the Madrid Front',
- n: 'the Nothern Front',
- s: 'the Southern Front',
+ a: 'Aragon Front',
+ m: 'Madrid Front',
+ n: 'Nothern Front',
+ s: 'Southern Front',
d: 'the Front closest to Defeat',
v: 'the Front closest to Victory',
};
+const bonus_names: string[] = ['Morale Bonus', 'Teamwork Bonus'];
+
const {
cards,
// fronts,
tracks,
} = data;
+const bonuses = [MORALE_BONUS, TEAMWORK_BONUS];
+
const faction_cards = {
[ANARCHISTS_ID]: make_list(37, 54) as CardId[],
[COMMUNISTS_ID]: make_list(19, 36) as CardId[],
@@ -108,10 +120,18 @@ function gen_action(action: string, argument?: number | string) {
}
}
+function gen_action_bonus(bonus_id: number) {
+ gen_action('bonus', bonus_id);
+}
+
function gen_action_card(card_id: CardId) {
gen_action('card', card_id);
}
+function gen_action_front(front_id: string) {
+ gen_action('front', front_id);
+}
+
function gen_action_standee(track_id: number) {
gen_action('standee', track_id);
}
@@ -150,18 +170,40 @@ const seq_node = 's';
const function_node = 'f';
const resolved = 1;
+function create_leaf_node(
+ state: string,
+ faction: FactionId,
+ args?: any
+): LeafNode {
+ return {
+ t: leaf_node,
+ s: state,
+ p: faction,
+ a: args,
+ r: 0,
+ };
+}
+
+function create_function_node(func_name: string, args?: any): FunctionNode {
+ return {
+ t: function_node,
+ f: func_name,
+ a: args,
+ r: 0,
+ };
+}
+
+function create_seq_node(children: EngineNode[]): SeqNode {
+ return {
+ t: seq_node,
+ c: children,
+ };
+}
+
function setup_bag_of_glory() {
- console.log('setup_bag_of_glory');
game.engine = [
- {
- t: leaf_node,
- p: game.initiative,
- s: 'add_glory',
- },
- {
- t: function_node,
- f: 'end_of_turn',
- },
+ create_leaf_node('add_glory', game.initiative),
+ create_function_node('end_of_turn'),
];
next();
}
@@ -169,43 +211,26 @@ function setup_bag_of_glory() {
function setup_choose_card() {
console.log('setup_choose_card');
const player_order = get_player_order();
- game.engine = player_order.map((faction_id) => ({
- t: leaf_node,
- p: faction_id,
- s: 'choose_card',
- }));
- game.engine.push({
- t: function_node,
- f: 'setup_player_turn',
- });
+ game.engine = player_order.map((faction_id) =>
+ create_leaf_node('choose_card', faction_id)
+ );
+ game.engine.push(create_function_node('setup_player_turn'));
next();
}
function setup_player_turn() {
console.log('setup_player_turn');
const player_order = get_player_order();
- game.engine = player_order.map((faction_id) => ({
- t: seq_node,
- c: [
- {
- t: leaf_node,
- s: 'player_turn',
- p: faction_id,
- },
- ],
- }));
- game.engine.push({
- t: function_node,
- f: 'resolve_fascist_test',
- });
- game.engine.push({
- t: function_node,
- f: 'setup_bag_of_glory',
- });
+ game.engine = player_order.map((faction_id) =>
+ create_seq_node([create_leaf_node('player_turn', faction_id)])
+ );
+ game.engine.push(create_function_node('resolve_fascist_test'));
+ game.engine.push(create_function_node('setup_bag_of_glory'));
next();
}
const engine_functions: Record<string, Function> = {
+ check_activate_icon,
end_of_turn,
end_of_year,
setup_bag_of_glory,
@@ -360,8 +385,10 @@ function game_view(state: Game, player: Player) {
fronts: game.fronts,
hand: game.hands[faction_id],
medaillons: game.medaillons,
- selected_card: game.cards_in_play[faction_id],
+ selected_card: game.chosen_cards[faction_id],
+ tableaus: game.tableaus,
tracks: game.tracks,
+ triggered_track_effects: game.triggered_track_effects,
};
if (player !== game.active) {
@@ -419,7 +446,7 @@ export function setup(seed: number, _scenario: string, _options: unknown) {
[MODERATES_ID]: 0,
pool: 14,
},
- cards_in_play: {
+ chosen_cards: {
[ANARCHISTS_ID]: null,
[COMMUNISTS_ID]: null,
[MODERATES_ID]: null,
@@ -438,6 +465,11 @@ export function setup(seed: number, _scenario: string, _options: unknown) {
[MODERATES_ID]: [],
},
tracks: [5, 5, 6, 3, 3],
+ trash: {
+ [ANARCHISTS_ID]: [],
+ [COMMUNISTS_ID]: [],
+ [MODERATES_ID]: [],
+ },
triggered_track_effects: [[], [], [], [], []],
log: [],
undo: [],
@@ -495,6 +527,13 @@ function start_turn() {
// region STATES
+states.activate_icon = {
+ inactive: 'activate an icon',
+ prompt() {
+ view.prompt = 'Choose an icon to activate'
+ }
+}
+
states.add_glory = {
inactive: 'add tokens to the Bag of Glory',
prompt() {
@@ -517,24 +556,43 @@ states.add_glory = {
},
};
+states.add_to_front = {
+ inactive: 'add strength to a Front',
+ prompt() {
+ const args = get_active_node_args();
+ const possible_fronts = get_fronts_to_add_to(args.t);
+ view.prompt =
+ possible_fronts.length === 1
+ ? `Add strength to ${front_names[possible_fronts[0]]}`
+ : 'Add strength to a Front';
+ for (let f of possible_fronts) {
+ gen_action_front(f);
+ }
+ },
+ front(f: string) {
+ const value = get_active_node_args().v;
+ update_front(f, value);
+ resolve_active_and_proceed();
+ },
+};
+
states.attack_front = {
inactive: 'attack a Front',
prompt() {
const node = get_active_node();
- const front = node.a.f;
+ const front = node.a.t;
view.prompt = 'Attack ' + front_names[front];
if (front === 'd' || front === 'v') {
const fronts = get_fronts_closest_to(front);
fronts.forEach((id) => gen_action('front', id));
} else {
- gen_action('front', front);
+ gen_action_front(front);
}
},
front(f: string) {
const node = get_active_node();
const value = node.a.v;
- game.fronts[f] += value;
- log_h3(`${Math.abs(value)} attacks added to ${front_names[f]}`);
+ update_front(f, value);
resolve_active_and_proceed();
},
};
@@ -543,9 +601,18 @@ states.choose_area_ap = {
inactive: 'choose area to use Action Points',
prompt() {
view.prompt = 'Choose area of the board to affect';
- for (let track of tracks) {
+ for (const track of tracks) {
gen_action_standee(track.id);
}
+ const fronts = get_fronts_to_add_to(ANY);
+ for (const front of fronts) {
+ gen_action_front(front);
+ }
+ },
+ front(f: string) {
+ const s = get_active_node_args().strength;
+ update_front(f, s);
+ resolve_active_and_proceed();
},
standee(track_id: number) {
console.log('standee', track_id);
@@ -562,22 +629,37 @@ states.choose_area_ap = {
},
};
-states.move_track_up_or_down = {
- inactive: 'move a track',
+states.change_bonus = {
+ inactive: 'gain select Bonus',
prompt() {
- const node = get_active_node();
- view.prompt = `Move ${get_track_name(node.a.track_id)} up or down`;
- gen_action('up');
- gen_action('down');
+ const args = get_active_node_args();
+ if (
+ (args.v === ON &&
+ game.bonuses[TEAMWORK_BONUS] === ON &&
+ game.bonuses[MORALE_BONUS] === ON) ||
+ (args.v === OFF && game.bonuses[args.t] === OFF)
+ ) {
+ gen_action('skip');
+ }
+ if (args.t === ANY && args.v === ON) {
+ view.prompt = 'Turn on a Bonus';
+ for (const bonus of bonuses) {
+ if (game.bonuses[bonus] === OFF) {
+ gen_action_bonus(bonus);
+ }
+ }
+ } else if (args.v === OFF) {
+ view.prompt = `Turn off ${bonus_names[args.t]}`;
+ gen_action_bonus(args.t);
+ }
},
- down() {
- const node = get_active_node();
- move_track(node.a.track_id, -1 * node.a.strength);
+ bonus(b: number) {
+ const value = get_active_node_args().v;
+ game.bonuses[b] = value;
+ log(`${bonus_names[b]} ${value === ON ? 'on' : 'off'}`);
resolve_active_and_proceed();
},
- up() {
- const node = get_active_node();
- move_track(node.a.track_id, node.a.strength);
+ skip() {
resolve_active_and_proceed();
},
};
@@ -590,11 +672,24 @@ states.choose_card = {
for (let c of hand) gen_action_card(c);
},
card(c: CardId) {
- log_h3(`${game.active} chooses a card`);
- if (!game.cards_in_play) {
- game.cards_in_play = {};
+ game.chosen_cards[player_faction_map[game.active]] = c;
+ resolve_active_and_proceed();
+ },
+};
+
+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');
+ },
+ gain_hp() {
+ const value = get_active_node_args().v;
+ if (game.hero_points.pool > value) {
+ game.hero_points.pool -= value;
+ game.hero_points[get_active_faction()] += value;
}
- game.cards_in_play[player_faction_map[game.active]] = c;
resolve_active_and_proceed();
},
};
@@ -602,7 +697,30 @@ states.choose_card = {
states.lose_hero_points = {
inactive: 'choose a Player',
prompt() {
- view.prompt = 'Lose Hero Points';
+ const args = get_active_node_args();
+ view.prompt = 'Choose player to lose Hero Points';
+ if (args.t === PLAYER_WITH_MOST_HERO_POINTS) {
+ const factions = get_factions_with_most_hero_poins();
+ console.log('faction', factions);
+ for (let faction_id of factions) {
+ gen_action(faction_player_map[faction_id]);
+ }
+ }
+ },
+ Anarchist() {
+ const value = get_active_node_args().v;
+ lose_hero_point(ANARCHISTS_ID, value);
+ resolve_active_and_proceed();
+ },
+ Communist() {
+ const value = get_active_node_args().v;
+ lose_hero_point(ANARCHISTS_ID, value);
+ resolve_active_and_proceed();
+ },
+ Moderate() {
+ const value = get_active_node_args().v;
+ lose_hero_point(ANARCHISTS_ID, value);
+ resolve_active_and_proceed();
},
};
@@ -614,12 +732,32 @@ states.move_track = {
const value = node.a.v;
view.prompt = `Move ${tracks[track].name} ${value > 0 ? 'up' : 'down'}`;
// return 'Decrease ' + tracks[effect.target].name;
- gen_action_standee(track)
+ gen_action_standee(track);
},
standee(s: number) {
const node = get_active_node();
const value = node.a.v;
- move_track(s, value)
+ move_track(s, value);
+ resolve_active_and_proceed();
+ },
+};
+
+states.move_track_up_or_down = {
+ inactive: 'move a track',
+ prompt() {
+ const node = get_active_node();
+ view.prompt = `Move ${get_track_name(node.a.track_id)} up or down`;
+ gen_action('up');
+ gen_action('down');
+ },
+ down() {
+ const node = get_active_node();
+ move_track(node.a.track_id, -1 * node.a.strength);
+ resolve_active_and_proceed();
+ },
+ up() {
+ const node = get_active_node();
+ move_track(node.a.track_id, node.a.strength);
resolve_active_and_proceed();
},
};
@@ -628,21 +766,26 @@ states.player_turn = {
inactive: 'play their turn',
prompt() {
const faction_id = get_faction_id(game.active);
- const hero_points = game.hero_points[faction_id];
- view.prompt =
- hero_points === 0
- ? 'Play your card'
- : 'Play your card or spend Hero points';
+ const can_spend_hp = game.hero_points[faction_id] > 0;
+ const can_play_card = game.hands[faction_id].includes(
+ game.chosen_cards[faction_id]
+ );
+ view.prompt = 'Play a card or spend Hero points';
+ if (!(can_play_card || can_spend_hp)) {
+ view.prompt = 'End turn';
+ } else if (!can_play_card && can_spend_hp) {
+ view.prompt = 'Spend Hero Points or end turn';
+ }
// const card = game.cards_in_play[faction_id];
- if (game.cards_in_play[faction_id] !== null) {
+ if (can_play_card) {
// gen_action_card();
gen_action('play_for_ap');
gen_action('play_for_event');
} else {
gen_action('done');
}
- if (hero_points > 0) {
+ if (can_spend_hp) {
gen_action('spend_hp');
}
},
@@ -651,34 +794,29 @@ states.player_turn = {
},
play_for_ap() {
const faction_id = get_faction_id(game.active);
- const card = game.cards_in_play[faction_id];
+ const card = game.chosen_cards[faction_id];
log_h3(`${game.active} plays ${cards[card].title} for the Action Points`);
- if (!game.discard) {
- game.discard = {
- [ANARCHISTS_ID]: [],
- [COMMUNISTS_ID]: [],
- [MODERATES_ID]: [],
- f: [],
- };
- }
array_remove(game.hands[faction_id], game.hands[faction_id].indexOf(card));
- game.discard[faction_id].push(card);
- insert_before_active_node({
- t: leaf_node,
- p: faction_id,
- s: 'choose_area_ap',
- a: {
- strength: (cards[card] as PlayerCard).strength,
- },
- });
+ game.tableaus[faction_id].push(card);
+ insert_before_active_node(
+ create_seq_node([
+ create_leaf_node('choose_area_ap', faction_id, {
+ strength: (cards[card] as PlayerCard).strength,
+ }),
+ create_function_node('check_activate_icon'),
+ ])
+ );
next();
},
play_for_event() {
const faction_id = get_faction_id(game.active);
- const card = game.cards_in_play[faction_id];
+ const card = game.chosen_cards[faction_id];
+ array_remove(game.hands[faction_id], game.hands[faction_id].indexOf(card));
+ game.trash[faction_id].push(card);
log_h3(`${game.active} plays ${cards[card].title} for the Event`);
- game.cards_in_play[faction_id] = null;
- game.tableaus[faction_id].push(card);
+
+ insert_after_active_node(create_effects_node(cards[card].effects));
+
resolve_active_and_proceed();
},
spend_hp() {
@@ -690,58 +828,58 @@ states.player_turn = {
// insert spend hero points node before current node
next();
},
- card(c: CardId) {
- const faction = get_active_faction();
- log_h3(`${game.active} plays ${cards[c].title} to their tableau`);
- if (!game.tableaus) {
- game.tableaus = {
- [ANARCHISTS_ID]: [],
- [COMMUNISTS_ID]: [],
- [MODERATES_ID]: [],
- };
- }
- game.cards_in_play[faction] = null;
- game.tableaus[faction].push(c);
- array_remove(game.hands[faction], game.hands[faction].indexOf(c));
- resolve_active_and_proceed();
- },
+ // card(c: CardId) {
+ // const faction = get_active_faction();
+ // log_h3(`${game.active} plays ${cards[c].title} to their tableau`);
+ // if (!game.tableaus) {
+ // game.tableaus = {
+ // [ANARCHISTS_ID]: [],
+ // [COMMUNISTS_ID]: [],
+ // [MODERATES_ID]: [],
+ // };
+ // }
+ // game.chosen_cards[faction] = null;
+ // game.tableaus[faction].push(c);
+ // array_remove(game.hands[faction], game.hands[faction].indexOf(c));
+ // resolve_active_and_proceed();
+ // },
};
-states.resolve_event = {
- inactive: 'resolve Fascist Event',
- prompt() {
- const card = get_current_event();
- const node = get_active_node(game.engine) as LeafNode;
- const effect: Effect = card.effects[node.a];
- view.prompt = get_event_prompt(effect);
-
-if (effect.type === 'track') {
- gen_action('standee', effect.target);
- } else if (
- effect.type === 'hero_points' &&
- effect.target === PLAYER_WITH_MOST_HERO_POINTS
- ) {
- const factions = get_factions_with_most_hero_poins();
- for (let faction_id of factions) {
- gen_action(get_player(faction_id));
- }
- }
- // for (let p = 0; p < 5; ++p) gen_action('standee', p);
- },
+// states.resolve_event = {
+// inactive: 'resolve Fascist Event',
+// prompt() {
+// const card = get_current_event();
+// const node = get_active_node(game.engine) as LeafNode;
+// const effect: Effect = card.effects[node.a];
+// view.prompt = get_event_prompt(effect);
+
+// if (effect.type === 'track') {
+// gen_action('standee', effect.target);
+// } else if (
+// effect.type === 'hero_points' &&
+// effect.target === PLAYER_WITH_MOST_HERO_POINTS
+// ) {
+// const factions = get_factions_with_most_hero_poins();
+// for (let faction_id of factions) {
+// gen_action(get_player(faction_id));
+// }
+// }
+// // for (let p = 0; p < 5; ++p) gen_action('standee', p);
+// },
- Anarchist() {
- lose_hero_point(ANARCHISTS_ID, 1);
- resolve_active_and_proceed();
- },
- Communist() {
- lose_hero_point(ANARCHISTS_ID, 1);
- resolve_active_and_proceed();
- },
- Moderate() {
- lose_hero_point(ANARCHISTS_ID, 1);
- resolve_active_and_proceed();
- },
-};
+// Anarchist() {
+// lose_hero_point(ANARCHISTS_ID, 1);
+// resolve_active_and_proceed();
+// },
+// Communist() {
+// lose_hero_point(ANARCHISTS_ID, 1);
+// resolve_active_and_proceed();
+// },
+// Moderate() {
+// lose_hero_point(ANARCHISTS_ID, 1);
+// resolve_active_and_proceed();
+// },
+// };
states.spend_hero_points = {
inactive: 'spend Hero points',
@@ -793,6 +931,16 @@ function pop_undo() {
// #region GAME FUNCTIONS
+// Check if Morale bonus is on so player can activate icon
+function check_activate_icon() {
+ if (game.bonuses[MORALE_BONUS] === ON) {
+ insert_after_active_node(
+ create_leaf_node('activate_icon', get_active_faction_id())
+ );
+ }
+ resolve_active_and_proceed();
+}
+
function end_of_turn() {
// REMOVE playre tplems from the Fronts;
log_h2('End of turn');
@@ -812,6 +960,18 @@ function resolve_fascist_test() {
next();
}
+// TODO: check for defeated / won fronts
+function get_fronts_to_add_to(target: string): string[] {
+ console.log('get_fronts_to_add_to', target);
+ if (target === CLOSEST_TO_DEFEAT || target === CLOSEST_TO_VICTORY) {
+ return get_fronts_closest_to(target);
+ } else if (target === ANY) {
+ return ['a', 'm', 'n', 's'];
+ } else {
+ return [target];
+ }
+}
+
function move_track(track_id: number, change: number) {
// Check if track can be moved
// Updata values
@@ -822,7 +982,7 @@ function move_track(track_id: number, change: number) {
new_value = Math.max(new_value, track_id === GOVERNMENT ? 1 : 0);
new_value = Math.min(new_value, 10);
game.tracks[track_id] = new_value;
- log(`${game.active} moves ${get_track_name(track_id)} to ${new_value}`);
+ log(`${get_track_name(track_id)} to ${new_value}`);
const triggered_spaces =
change > 0
? make_list(current_value + 1, new_value).reverse()
@@ -845,67 +1005,57 @@ function move_track(track_id: number, change: number) {
});
}
+// TODO: acccount for victory / defeat of front
+function update_front(f: string, change: number) {
+ game.fronts[f] += change;
+ log(`${front_names[f]}: ${change > 0 ? '+' : ''}${change}`);
+}
+
+function create_effects_node(effects: Effect[]): EngineNode {
+ const nodes = effects.reduce((accrued: EngineNode[], current: Effect) => {
+ const node = resolve_effect(current);
+ if (node !== null) {
+ accrued.push(node);
+ }
+ return accrued;
+ }, []);
+ return {
+ t: seq_node,
+ c: nodes,
+ };
+}
+
+const effect_type_state_map: Record<string, string> = {
+ attack: 'attack_front',
+ bonus: 'change_bonus',
+ front: 'add_to_front',
+ track: 'move_track',
+};
+
function resolve_effect(
effect: Effect,
faction: FactionId = get_active_faction()
): EngineNode | null {
- if (effect.type === 'attack') {
- return {
- t: leaf_node,
- p: faction,
- s: 'attack_front',
- a: {
- f: effect.target,
- v: effect.value,
- },
- };
- }
- if (effect.type === 'track') {
- return {
- t: leaf_node,
- p: faction,
- s: 'move_track',
- a: {
- t: effect.target,
- v: effect.value,
- },
- };
+ const args = {
+ t: effect.target,
+ 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 === PLAYER_WITH_MOST_HERO_POINTS
) {
- return {
- t: leaf_node,
- p: faction,
- s: 'lose_hero_points',
- a: {
- p: effect.target,
- v: effect.value,
- },
- };
+ state = 'lose_hero_points';
}
- return null;
-
- // if (
- // effect.type === 'attack' &&
- // (effect.target === 'd' || effect.target === 'v')
- // ) {
- // const fronts = get_fronts_closest_to(effect.target);
- // fronts.forEach((id) => gen_action('front', id));
- // } else if (effect.type === 'attack') {
- // gen_action('front', effect.target);
- // } else if (effect.type === 'track') {
- // gen_action('standee', effect.target);
- // } else if (
- // effect.type === 'hero_points' &&
- // effect.target === PLAYER_WITH_MOST_HERO_POINTS
- // ) {
- // const factions = get_factions_with_most_hero_poins();
- // for (let faction_id of factions) {
- // gen_action(get_player(faction_id));
- // }
- // }
+ if (effect.type === 'hero_points' && effect.target === SELF) {
+ state = 'gain_hero_points';
+ }
+ return state === undefined ? null : create_leaf_node(state, faction, args);
}
// #endregion
@@ -936,13 +1086,16 @@ function draw_item(ids: number[]): number {
}
function lose_hero_point(faction: FactionId, value: number) {
- const points_lost = Math.min(game.hero_points[faction], value);
+ const points_lost = Math.min(game.hero_points[faction], Math.abs(value));
game.hero_points.pool += points_lost;
game.hero_points[faction] -= points_lost;
+ if (points_lost === 0) {
+ return;
+ }
if (points_lost === 1) {
- log(`${get_player(faction)} loses 1 Hero Point`);
+ log(`${get_player(faction)}: -1 Hero Point`);
} else {
- log(`${get_player(faction)} loses ${points_lost} Hero Points`);
+ log(`${get_player(faction)}: -${points_lost} Hero Points`);
}
}
@@ -950,11 +1103,11 @@ function lose_hero_point(faction: FactionId, value: number) {
// #region EVENTS
-function get_current_event(): EventCard {
- return cards[
- game.current_events[game.current_events.length - 1]
- ] as EventCard;
-}
+// function get_current_event(): EventCard {
+// return cards[
+// game.current_events[game.current_events.length - 1]
+// ] as EventCard;
+// }
// function get_front_name(frontId: string) {
// switch (frontId) {
@@ -975,20 +1128,20 @@ function get_current_event(): EventCard {
// }
// }
-function get_event_prompt(effect: Effect) {
- let prompt = '';
- switch (effect.type) {
- case 'attack':
- return 'Attack ' + front_names[effect.target as string];
- case 'bonus':
- break;
- case 'hero_points':
- return 'Select player with most Hero points';
- case 'track':
- return 'Decrease ' + tracks[effect.target].name;
- }
- return prompt;
-}
+// function get_event_prompt(effect: Effect) {
+// let prompt = '';
+// switch (effect.type) {
+// case 'attack':
+// return 'Attack ' + front_names[effect.target as string];
+// case 'bonus':
+// break;
+// case 'hero_points':
+// return 'Select player with most Hero points';
+// case 'track':
+// return 'Decrease ' + tracks[effect.target].name;
+// }
+// return prompt;
+// }
// function resolve_event_attack(target: string | number, value: number) {
// switch (target) {
@@ -1156,12 +1309,18 @@ function get_next_faction(faction_id: FactionId): FactionId {
return role_ids[index + 1];
}
-function get_factions_with_most_hero_poins() {
- const most_hero_points = Math.max(...Object.values(game.hero_points));
- const faction_ids = [];
- Object.entries(game.hero_points).forEach(([faction, hero_points]) => {
- if (hero_points === most_hero_points) {
- faction_ids.push(faction);
+function get_factions_with_most_hero_poins(): FactionId[] {
+ let most_hero_points = null;
+ let faction_ids = [];
+ Object.entries(game.hero_points).forEach(([id, value]) => {
+ if (id === 'pool') {
+ return;
+ }
+ if (most_hero_points === null || value > most_hero_points) {
+ most_hero_points = value;
+ faction_ids = [id];
+ } else if (most_hero_points === value) {
+ faction_ids.push(id);
}
});
return faction_ids;
diff --git a/types.d.ts b/types.d.ts
index b470acc..318d935 100644
--- a/types.d.ts
+++ b/types.d.ts
@@ -21,7 +21,7 @@ export interface Game {
bag_of_glory: Record<FactionId, number>;
blank_markers: number[][];
bonuses: number[];
- cards_in_play: Record<FactionId, CardId>;
+ chosen_cards: Record<FactionId, CardId>;
current_events: CardId[];
discard: Record<FactionId | 'f', number[]>;
engine: EngineNode[];
@@ -37,6 +37,7 @@ export interface Game {
medaillons: Array<number | null>;
tableaus: Record<FactionId, CardId[]>;
tracks: number[];
+ trash: Record<FactionId, number[]>;
triggered_track_effects: number[][];
result?: string;
victory?: string;
@@ -66,7 +67,9 @@ export interface View {
fronts: Game['fronts'];
hand: CardId[];
medaillons: Game['medaillons'];
+ tableaus: Game['tableaus'];
tracks: number[];
+ triggered_track_effects: Game['triggered_track_effects'];
}
export type States = {
@@ -108,14 +111,42 @@ export interface EventCard extends CardBase {
effects: Effect[];
}
+export type Icon =
+ | 'add_to_front'
+ | 'collectivization'
+ | 'd_collectivization'
+ | 'd_foreign_aid'
+ | 'd_government'
+ | 'd_liberty'
+ | 'd_soviet_support'
+ | 'draw_card'
+ | 'foreign_aid'
+ | 'government'
+ | 'government_to_center'
+ | 'liberty'
+ | 'soviet_support'
+ | 'teamwork_on';
+
export interface PlayerCard extends CardBase {
type: 'pc';
strength: number;
effects: Effect[];
+ icons: Icon[];
}
export interface Effect {
- type: 'attack' | 'track' | 'bonus' | 'hero_points' | 'front' | 'medaillon' | 'draw_card' | 'swap_card_tableau_hand' | 'add_to_tableau' | 'remove_blank_marker' | 'return_card';
+ type:
+ | 'attack'
+ | 'track'
+ | 'bonus'
+ | 'hero_points'
+ | 'front'
+ | 'medaillon'
+ | 'draw_card'
+ | 'swap_card_tableau_hand'
+ | 'add_to_tableau'
+ | 'remove_blank_marker'
+ | 'return_card';
target: string | number;
value: number;
}
@@ -137,4 +168,4 @@ export interface StaticData {
name: string;
triggers: Array<null | Effect>;
}>;
-} \ No newline at end of file
+}