summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrans Bongers <fransbongers@franss-mbp.home>2024-12-01 15:09:24 +0100
committerFrans Bongers <fransbongers@franss-mbp.home>2024-12-01 15:09:24 +0100
commit74e1497d50a6ff81c74c593f2d0f7018d2995fd8 (patch)
tree9dd74df38232b1ab5f76b84f362c98abc6eaa7d1
parentf05a9531508822f5dfb51105334444b53fe11b3e (diff)
downloadland-and-freedom-74e1497d50a6ff81c74c593f2d0f7018d2995fd8.tar.gz
add stack data for triggers on tracks
-rw-r--r--data.js280
-rw-r--r--data.ts294
-rw-r--r--play.js2
-rw-r--r--play.ts2
-rw-r--r--rules.js177
-rw-r--r--rules.ts193
-rw-r--r--types.d.ts1
7 files changed, 780 insertions, 169 deletions
diff --git a/data.js b/data.js
index a028139..d60e7ee 100644
--- a/data.js
+++ b/data.js
@@ -21,6 +21,15 @@ const ON = 1;
exports.ON = ON;
const PLAYER_WITH_MOST_HERO_POINTS = 0;
exports.PLAYER_WITH_MOST_HERO_POINTS = PLAYER_WITH_MOST_HERO_POINTS;
+const ARAGON = 'a';
+const MADRID = 'm';
+const NORTHERN = 'n';
+const SOUTHERN = 's';
+const CLOSEST_TO_DEFEAT = 'd';
+const CLOSEST_TO_VICTORY = 'v';
+const TOWARDS_CENTER = 10;
+const AWAY_FROM_CENTER = 11;
+const ANY = 'any';
const data = {
cards: [
{},
@@ -352,12 +361,12 @@ const data = {
id: 55,
effects: [
{
- target: 's',
+ target: SOUTHERN,
type: 'attack',
value: 4,
},
{
- target: 'a',
+ target: ARAGON,
type: 'attack',
value: 1,
},
@@ -375,12 +384,12 @@ const data = {
id: 56,
effects: [
{
- target: 's',
+ target: SOUTHERN,
type: 'attack',
value: 3,
},
{
- target: 'v',
+ target: CLOSEST_TO_VICTORY,
type: 'attack',
value: 2,
},
@@ -398,9 +407,9 @@ const data = {
id: 57,
effects: [
{
- target: 'm',
+ target: MADRID,
type: 'attack',
- value: 5,
+ value: -5,
},
{
target: FOREIGN_AID,
@@ -423,12 +432,12 @@ const data = {
{
target: 'n',
type: 'attack',
- value: 5,
+ value: -5,
},
{
target: 'v',
type: 'attack',
- value: 1,
+ value: -1,
},
{
target: COLLECTIVIZATION,
@@ -444,14 +453,14 @@ const data = {
id: 59,
effects: [
{
- target: 'm',
+ target: MADRID,
type: 'attack',
- value: 4,
+ value: -4,
},
{
- target: 'v',
+ target: CLOSEST_TO_VICTORY,
type: 'attack',
- value: 2,
+ value: -2,
},
{
target: LIBERTY,
@@ -467,14 +476,14 @@ const data = {
id: 60,
effects: [
{
- target: 'n',
+ target: NORTHERN,
type: 'attack',
- value: 3,
+ value: -3,
},
{
- target: 'v',
+ target: CLOSEST_TO_VICTORY,
type: 'attack',
- value: 3,
+ value: -3,
},
{
target: LIBERTY,
@@ -490,14 +499,14 @@ const data = {
id: 61,
effects: [
{
- target: 'a',
+ target: ARAGON,
type: 'attack',
- value: 4,
+ value: -4,
},
{
- target: 'v',
+ target: CLOSEST_TO_VICTORY,
type: 'attack',
- value: 2,
+ value: -2,
},
{
target: PLAYER_WITH_MOST_HERO_POINTS,
@@ -513,9 +522,9 @@ const data = {
id: 62,
effects: [
{
- target: 's',
+ target: SOUTHERN,
type: 'attack',
- value: 5,
+ value: -5,
},
{
target: MORALE_BONUS,
@@ -535,25 +544,25 @@ const data = {
],
fronts: [
{
- id: 'n',
+ id: NORTHERN,
name: 'Northern',
left: 89,
top: 96,
},
{
- id: 'a',
+ id: ARAGON,
name: 'Aragon',
left: 340,
top: 182,
},
{
- id: 'm',
+ id: MADRID,
name: 'Madrid',
left: 115,
top: 262,
},
{
- id: 's',
+ id: SOUTHERN,
name: 'Southern',
left: 205,
top: 426,
@@ -562,40 +571,239 @@ const data = {
medaillons: [
{
id: 0,
- name: 'Subterfuge'
+ name: 'Subterfuge',
},
{
id: 1,
- name: 'Valor'
+ name: 'Valor',
},
{
id: 2,
- name: 'Momentum'
+ name: 'Momentum',
},
{
id: 3,
- name: 'Strategy'
+ name: 'Strategy',
},
{
id: 4,
- name: 'Propaganda'
+ name: 'Propaganda',
},
{
id: 5,
- name: 'Intelligence'
+ name: 'Intelligence',
},
{
id: 6,
- name: 'Volunteers'
+ name: 'Volunteers',
},
{
id: 7,
- name: 'Archives'
+ name: 'Archives',
},
{
id: 8,
- name: 'Organization'
+ name: 'Organization',
+ },
+ ],
+ tracks: [
+ {
+ id: LIBERTY,
+ name: 'Liberty',
+ triggers: [
+ {
+ type: 'bonus',
+ target: MORALE_BONUS,
+ value: OFF,
+ },
+ {
+ type: 'attack',
+ target: MADRID,
+ value: -1,
+ },
+ null,
+ {
+ type: 'track',
+ target: SOVIET_SUPPORT,
+ value: 1,
+ },
+ null,
+ null,
+ null,
+ {
+ type: 'track',
+ target: GOVERNMENT,
+ value: TOWARDS_CENTER,
+ },
+ {
+ type: 'front',
+ target: ANY,
+ value: 1,
+ },
+ null,
+ {
+ type: 'medaillon',
+ target: ANY,
+ value: 1,
+ },
+ ],
+ },
+ {
+ id: COLLECTIVIZATION,
+ name: 'Collectivization',
+ triggers: [
+ {
+ type: 'bonus',
+ target: MORALE_BONUS,
+ value: OFF,
+ },
+ {
+ type: 'attack',
+ target: ARAGON,
+ value: -1,
+ },
+ null,
+ {
+ type: 'track',
+ target: FOREIGN_AID,
+ value: 1,
+ },
+ null,
+ null,
+ null,
+ {
+ type: 'front',
+ target: ANY,
+ value: 1,
+ },
+ {
+ type: 'track',
+ target: LIBERTY,
+ value: 1,
+ },
+ null,
+ {
+ type: 'medaillon',
+ target: ANY,
+ value: 1,
+ },
+ ],
+ },
+ {
+ id: GOVERNMENT,
+ name: 'Government',
+ triggers: [
+ null,
+ {
+ type: 'medaillon',
+ target: ANY,
+ value: 1,
+ },
+ null,
+ null,
+ {
+ type: 'track',
+ target: SOVIET_SUPPORT,
+ value: 1,
+ },
+ null,
+ null,
+ {
+ type: 'track',
+ target: FOREIGN_AID,
+ value: 1,
+ },
+ null,
+ null,
+ {
+ type: 'medaillon',
+ target: ANY,
+ value: 1,
+ },
+ ],
+ },
+ {
+ id: SOVIET_SUPPORT,
+ name: 'Soviet Support',
+ triggers: [
+ {
+ type: 'bonus',
+ target: MORALE_BONUS,
+ value: OFF,
+ },
+ {
+ type: 'attack',
+ target: SOUTHERN,
+ value: -1,
+ },
+ null,
+ null,
+ null,
+ {
+ type: 'track',
+ target: LIBERTY,
+ value: -1,
+ },
+ null,
+ {
+ type: 'front',
+ target: ANY,
+ value: 1,
+ },
+ {
+ type: 'track',
+ target: GOVERNMENT,
+ value: -1,
+ },
+ null,
+ {
+ type: 'medaillon',
+ target: ANY,
+ value: 1,
+ },
+ ],
+ },
+ {
+ id: FOREIGN_AID,
+ name: 'Foreign Aid',
+ triggers: [
+ {
+ type: 'bonus',
+ target: MORALE_BONUS,
+ value: OFF,
+ },
+ {
+ type: 'attack',
+ target: NORTHERN,
+ value: -1,
+ },
+ null,
+ null,
+ null,
+ {
+ type: 'track',
+ target: LIBERTY,
+ value: -1,
+ },
+ null,
+ {
+ type: 'front',
+ target: ANY,
+ value: 1,
+ },
+ {
+ type: 'track',
+ target: GOVERNMENT,
+ value: 1,
+ },
+ null,
+ {
+ type: 'medaillon',
+ target: ANY,
+ value: 1,
+ },
+ ],
},
- ]
+ ],
};
exports.default = data;
diff --git a/data.ts b/data.ts
index c1d62b3..3b4e29d 100644
--- a/data.ts
+++ b/data.ts
@@ -33,7 +33,16 @@ export interface StaticData {
medaillons: Array<{
id: number;
name: string;
- }>
+ }>;
+ tracks: Array<{
+ id: number;
+ name: string;
+ triggers: Array<null | {
+ type: 'attack' | 'track' | 'bonus' | 'front' | 'medaillon';
+ target: string | number;
+ value: number;
+ }>;
+ }>;
}
const LIBERTY = 0;
@@ -50,6 +59,18 @@ const ON = 1;
const PLAYER_WITH_MOST_HERO_POINTS = 0;
+const ARAGON = 'a';
+const MADRID = 'm';
+const NORTHERN = 'n';
+const SOUTHERN = 's';
+const CLOSEST_TO_DEFEAT = 'd';
+const CLOSEST_TO_VICTORY = 'v';
+
+const TOWARDS_CENTER = 10;
+const AWAY_FROM_CENTER = 11;
+
+const ANY = 'any';
+
export {
LIBERTY,
COLLECTIVIZATION,
@@ -394,12 +415,12 @@ const data: StaticData = {
id: 55,
effects: [
{
- target: 's',
+ target: SOUTHERN,
type: 'attack',
value: 4,
},
{
- target: 'a',
+ target: ARAGON,
type: 'attack',
value: 1,
},
@@ -417,12 +438,12 @@ const data: StaticData = {
id: 56,
effects: [
{
- target: 's',
+ target: SOUTHERN,
type: 'attack',
value: 3,
},
{
- target: 'v',
+ target: CLOSEST_TO_VICTORY,
type: 'attack',
value: 2,
},
@@ -440,9 +461,9 @@ const data: StaticData = {
id: 57,
effects: [
{
- target: 'm',
+ target: MADRID,
type: 'attack',
- value: 5,
+ value: -5,
},
{
target: FOREIGN_AID,
@@ -465,12 +486,12 @@ const data: StaticData = {
{
target: 'n',
type: 'attack',
- value: 5,
+ value: -5,
},
{
target: 'v',
type: 'attack',
- value: 1,
+ value: -1,
},
{
target: COLLECTIVIZATION,
@@ -486,14 +507,14 @@ const data: StaticData = {
id: 59,
effects: [
{
- target: 'm',
+ target: MADRID,
type: 'attack',
- value: 4,
+ value: -4,
},
{
- target: 'v',
+ target: CLOSEST_TO_VICTORY,
type: 'attack',
- value: 2,
+ value: -2,
},
{
target: LIBERTY,
@@ -509,14 +530,14 @@ const data: StaticData = {
id: 60,
effects: [
{
- target: 'n',
+ target: NORTHERN,
type: 'attack',
- value: 3,
+ value: -3,
},
{
- target: 'v',
+ target: CLOSEST_TO_VICTORY,
type: 'attack',
- value: 3,
+ value: -3,
},
{
target: LIBERTY,
@@ -532,14 +553,14 @@ const data: StaticData = {
id: 61,
effects: [
{
- target: 'a',
+ target: ARAGON,
type: 'attack',
- value: 4,
+ value: -4,
},
{
- target: 'v',
+ target: CLOSEST_TO_VICTORY,
type: 'attack',
- value: 2,
+ value: -2,
},
{
target: PLAYER_WITH_MOST_HERO_POINTS,
@@ -555,9 +576,9 @@ const data: StaticData = {
id: 62,
effects: [
{
- target: 's',
+ target: SOUTHERN,
type: 'attack',
- value: 5,
+ value: -5,
},
{
target: MORALE_BONUS,
@@ -577,25 +598,25 @@ const data: StaticData = {
],
fronts: [
{
- id: 'n',
+ id: NORTHERN,
name: 'Northern',
left: 89,
top: 96,
},
{
- id: 'a',
+ id: ARAGON,
name: 'Aragon',
left: 340,
top: 182,
},
{
- id: 'm',
+ id: MADRID,
name: 'Madrid',
left: 115,
top: 262,
},
{
- id: 's',
+ id: SOUTHERN,
name: 'Southern',
left: 205,
top: 426,
@@ -604,40 +625,239 @@ const data: StaticData = {
medaillons: [
{
id: 0,
- name: 'Subterfuge'
+ name: 'Subterfuge',
},
{
id: 1,
- name: 'Valor'
+ name: 'Valor',
},
{
id: 2,
- name: 'Momentum'
+ name: 'Momentum',
},
{
id: 3,
- name: 'Strategy'
+ name: 'Strategy',
},
{
id: 4,
- name: 'Propaganda'
+ name: 'Propaganda',
},
{
id: 5,
- name: 'Intelligence'
+ name: 'Intelligence',
},
{
id: 6,
- name: 'Volunteers'
+ name: 'Volunteers',
},
{
id: 7,
- name: 'Archives'
+ name: 'Archives',
},
{
id: 8,
- name: 'Organization'
+ name: 'Organization',
+ },
+ ],
+ tracks: [
+ {
+ id: LIBERTY,
+ name: 'Liberty',
+ triggers: [
+ {
+ type: 'bonus',
+ target: MORALE_BONUS,
+ value: OFF,
+ },
+ {
+ type: 'attack',
+ target: MADRID,
+ value: -1,
+ },
+ null,
+ {
+ type: 'track',
+ target: SOVIET_SUPPORT,
+ value: 1,
+ },
+ null,
+ null,
+ null,
+ {
+ type: 'track',
+ target: GOVERNMENT,
+ value: TOWARDS_CENTER,
+ },
+ {
+ type: 'front',
+ target: ANY,
+ value: 1,
+ },
+ null,
+ {
+ type: 'medaillon',
+ target: ANY,
+ value: 1,
+ },
+ ],
},
- ]
+ {
+ id: COLLECTIVIZATION,
+ name: 'Collectivization',
+ triggers: [
+ {
+ type: 'bonus',
+ target: MORALE_BONUS,
+ value: OFF,
+ },
+ {
+ type: 'attack',
+ target: ARAGON,
+ value: -1,
+ },
+ null,
+ {
+ type: 'track',
+ target: FOREIGN_AID,
+ value: 1,
+ },
+ null,
+ null,
+ null,
+ {
+ type: 'front',
+ target: ANY,
+ value: 1,
+ },
+ {
+ type: 'track',
+ target: LIBERTY,
+ value: 1,
+ },
+ null,
+ {
+ type: 'medaillon',
+ target: ANY,
+ value: 1,
+ },
+ ],
+ },
+ {
+ id: GOVERNMENT,
+ name: 'Government',
+ triggers: [
+ null,
+ {
+ type: 'medaillon',
+ target: ANY,
+ value: 1,
+ },
+ null,
+ null,
+ {
+ type: 'track',
+ target: SOVIET_SUPPORT,
+ value: 1,
+ },
+ null,
+ null,
+ {
+ type: 'track',
+ target: FOREIGN_AID,
+ value: 1,
+ },
+ null,
+ null,
+ {
+ type: 'medaillon',
+ target: ANY,
+ value: 1,
+ },
+ ],
+ },
+ {
+ id: SOVIET_SUPPORT,
+ name: 'Soviet Support',
+ triggers: [
+ {
+ type: 'bonus',
+ target: MORALE_BONUS,
+ value: OFF,
+ },
+ {
+ type: 'attack',
+ target: SOUTHERN,
+ value: -1,
+ },
+ null,
+ null,
+ null,
+ {
+ type: 'track',
+ target: LIBERTY,
+ value: -1,
+ },
+ null,
+ {
+ type: 'front',
+ target: ANY,
+ value: 1,
+ },
+ {
+ type: 'track',
+ target: GOVERNMENT,
+ value: -1,
+ },
+ null,
+ {
+ type: 'medaillon',
+ target: ANY,
+ value: 1,
+ },
+ ],
+ },
+ {
+ id: FOREIGN_AID,
+ name: 'Foreign Aid',
+ triggers: [
+ {
+ type: 'bonus',
+ target: MORALE_BONUS,
+ value: OFF,
+ },
+ {
+ type: 'attack',
+ target: NORTHERN,
+ value: -1,
+ },
+ null,
+ null,
+ null,
+ {
+ type: 'track',
+ target: LIBERTY,
+ value: -1,
+ },
+ null,
+ {
+ type: 'front',
+ target: ANY,
+ value: 1,
+ },
+ {
+ type: 'track',
+ target: GOVERNMENT,
+ value: 1,
+ },
+ null,
+ {
+ type: 'medaillon',
+ target: ANY,
+ value: 1,
+ },
+ ],
+ },
+ ],
};
export default data;
diff --git a/play.js b/play.js
index c39f702..c654730 100644
--- a/play.js
+++ b/play.js
@@ -226,6 +226,8 @@ function on_update() {
action_button('play_for_event', 'Play card for Event');
action_button('spend_hp', 'Spend Hero Points');
action_button('add_glory', 'Add Glory');
+ action_button('up', 'Up');
+ action_button('down', 'Down');
action_button('next', 'Next');
action_button('done', 'Done');
action_button('undo', 'Undo');
diff --git a/play.ts b/play.ts
index e0cb69a..c0b144f 100644
--- a/play.ts
+++ b/play.ts
@@ -305,6 +305,8 @@ function on_update() {
action_button('play_for_event', 'Play card for Event');
action_button('spend_hp', 'Spend Hero Points');
action_button('add_glory', 'Add Glory');
+ action_button('up', 'Up');
+ action_button('down', 'Down');
action_button('next', 'Next');
action_button('done', 'Done');
action_button('undo', 'Undo');
diff --git a/rules.js b/rules.js
index cf1b88f..3fa056a 100644
--- a/rules.js
+++ b/rules.js
@@ -33,6 +33,13 @@ const front_names = {
d: 'the Front closest to Defeat',
v: 'the Front closest to Victory',
};
+const tracks = [
+ data_1.LIBERTY,
+ data_1.COLLECTIVIZATION,
+ data_1.GOVERNMENT,
+ data_1.SOVIET_SUPPORT,
+ data_1.FOREIGN_AID,
+];
const track_names = {
[data_1.LIBERTY]: 'Liberty',
[data_1.COLLECTIVIZATION]: 'Collectivization',
@@ -66,6 +73,9 @@ function gen_action(action, argument) {
function gen_action_card(card_id) {
gen_action('card', card_id);
}
+function gen_action_standee(track_id) {
+ gen_action('standee', track_id);
+}
function action(state, player, action, arg) {
console.log('action', state, player, action, arg);
game = state;
@@ -156,7 +166,7 @@ function get_active(engine) {
}
return null;
}
-function get_active_node(engine) {
+function get_active_node(engine = game.engine) {
const a = get_active(engine);
return a === null ? null : a.node;
}
@@ -258,6 +268,12 @@ function setup(seed, _scenario, _options) {
blank_markers: [[], [], [], [], []],
bonuses: [data_1.ON, data_1.ON],
current_events: [],
+ discard: {
+ [ANARCHISTS_ID]: [],
+ [COMMUNISTS_ID]: [],
+ [MODERATES_ID]: [],
+ f: [],
+ },
engine: [],
fronts: {
a: -2,
@@ -359,58 +375,46 @@ states.add_glory = {
resolve_active_and_proceed();
},
};
-states.resolve_event = {
- inactive: 'resolve Fascist Event',
+states.choose_area_ap = {
+ inactive: 'choose area to use Action Points',
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 === '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 === 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));
- }
+ view.prompt = 'Choose area of the board to affect';
+ for (let track_id of tracks) {
+ gen_action_standee(track_id);
}
},
- front(f) {
- const card = get_current_event();
- const value = card.effects[get_active_node_args()].value;
- game.fronts[f] -= value;
- log_h3(`${value} attacks added to ${front_names[f]}`);
+ standee(track_id) {
+ console.log('standee', track_id);
+ insert_after_active_node({
+ t: leaf_node,
+ p: get_active_faction_id(),
+ s: 'move_track_up_or_down',
+ a: {
+ track_id,
+ strength: get_active_node()?.a.strength,
+ },
+ });
resolve_active_and_proceed();
},
- standee(s) {
- const effect = get_current_event().effects[get_active_node_args()];
- const value = effect.value;
- game.tracks[s] += value;
- log_h3(`${track_names[effect.target]} decreased by ${Math.abs(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');
},
- Anarchist() {
- lose_hero_point(ANARCHISTS_ID, 1);
+ down() {
+ const node = get_active_node();
+ move_track(node.a.track_id, -1 * node.a.strength);
resolve_active_and_proceed();
},
- Communist() {
- lose_hero_point(ANARCHISTS_ID, 1);
+ up() {
+ const node = get_active_node();
+ move_track(node.a.track_id, node.a.strength);
resolve_active_and_proceed();
- },
- Moderate() {
- lose_hero_point(ANARCHISTS_ID, 1);
- resolve_active_and_proceed();
- },
+ }
};
states.choose_card = {
inactive: 'choose a card',
@@ -442,15 +446,39 @@ states.player_turn = {
gen_action('play_for_ap');
gen_action('play_for_event');
}
+ else {
+ gen_action('done');
+ }
if (hero_points > 0) {
gen_action('spend_hp');
}
},
+ done() {
+ resolve_active_and_proceed();
+ },
play_for_ap() {
const faction_id = get_faction_id(game.active);
const card = game.cards_in_play[faction_id];
log_h3(`${game.active} plays ${cards[card].title} for the Action Points`);
- resolve_active_and_proceed();
+ 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].strength,
+ },
+ });
+ next();
},
play_for_event() {
const faction_id = get_faction_id(game.active);
@@ -484,6 +512,59 @@ states.player_turn = {
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 === '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 === 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));
+ }
+ }
+ },
+ front(f) {
+ const card = get_current_event();
+ const value = card.effects[get_active_node_args()].value;
+ game.fronts[f] -= value;
+ log_h3(`${value} attacks added to ${front_names[f]}`);
+ resolve_active_and_proceed();
+ },
+ standee(s) {
+ const effect = get_current_event().effects[get_active_node_args()];
+ const value = effect.value;
+ game.tracks[s] += value;
+ log_h3(`${track_names[effect.target]} decreased by ${Math.abs(value)}`);
+ 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',
prompt() {
@@ -526,7 +607,8 @@ function resolve_fascist_test() {
log_h2('Fascist test is resolved');
next();
}
-function move_track(track, change) { }
+function move_track(track, change) {
+}
function draw_card(deck) {
clear_undo();
let i = random(deck.length);
@@ -647,6 +729,9 @@ function get_factions_with_most_hero_poins() {
});
return faction_ids;
}
+function get_track_name(track_id) {
+ return track_names[track_id];
+}
function make_list(first, last) {
let list = [];
for (let i = first; i <= last; i++)
diff --git a/rules.ts b/rules.ts
index 0348814..cbe7f5a 100644
--- a/rules.ts
+++ b/rules.ts
@@ -30,6 +30,7 @@ import data, {
SOVIET_SUPPORT,
FOREIGN_AID,
PLAYER_WITH_MOST_HERO_POINTS,
+ PlayerCard,
// StaticData,
// PLAYER_WITH_MOST_HERO_POINTS,
} from './data';
@@ -74,6 +75,14 @@ const front_names: Record<string, string> = {
v: 'the Front closest to Victory',
};
+const tracks = [
+ LIBERTY,
+ COLLECTIVIZATION,
+ GOVERNMENT,
+ SOVIET_SUPPORT,
+ FOREIGN_AID,
+];
+
const track_names: Record<number, string> = {
[LIBERTY]: 'Liberty',
[COLLECTIVIZATION]: 'Collectivization',
@@ -118,6 +127,10 @@ function gen_action_card(card_id: CardId) {
gen_action('card', card_id);
}
+function gen_action_standee(track_id: number) {
+ gen_action('standee', track_id);
+}
+
// function gen_action_space(space) {
// gen_action('space', space);
// }
@@ -248,7 +261,9 @@ function get_active(
// return null;
// }
-function get_active_node(engine: EngineNode[]): FunctionNode | LeafNode | null {
+function get_active_node(
+ engine: EngineNode[] = game.engine
+): FunctionNode | LeafNode | null {
const a = get_active(engine);
return a === null ? null : a.node;
// for (let i of engine) {
@@ -395,6 +410,12 @@ export function setup(seed: number, _scenario: string, _options: unknown) {
blank_markers: [[], [], [], [], []],
bonuses: [ON, ON],
current_events: [],
+ discard: {
+ [ANARCHISTS_ID]: [],
+ [COMMUNISTS_ID]: [],
+ [MODERATES_ID]: [],
+ f: [],
+ },
engine: [],
fronts: {
a: -2,
@@ -513,62 +534,48 @@ states.add_glory = {
},
};
-states.resolve_event = {
- inactive: 'resolve Fascist Event',
+states.choose_area_ap = {
+ inactive: 'choose area to use Action Points',
prompt() {
- const card = get_current_event();
- const node = get_active_node(game.engine) as LeafNode;
- const effect: CardEffect = card.effects[node.a];
- view.prompt = get_event_prompt(effect);
-
- 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));
- }
+ view.prompt = 'Choose area of the board to affect';
+ for (let track_id of tracks) {
+ gen_action_standee(track_id);
}
- // for (let p = 0; p < 5; ++p) gen_action('standee', p);
- },
- front(f: string) {
- const card = get_current_event();
- const value = card.effects[get_active_node_args()].value;
- game.fronts[f] -= value;
- log_h3(`${value} attacks added to ${front_names[f]}`);
- resolve_active_and_proceed();
},
- standee(s: string) {
- const effect = get_current_event().effects[get_active_node_args()];
- const value = effect.value;
- game.tracks[s] += value;
- log_h3(`${track_names[effect.target]} decreased by ${Math.abs(value)}`);
+ standee(track_id: number) {
+ console.log('standee', track_id);
+ insert_after_active_node({
+ t: leaf_node,
+ p: get_active_faction_id(),
+ s: 'move_track_up_or_down',
+ a: {
+ track_id,
+ strength: get_active_node()?.a.strength,
+ },
+ });
resolve_active_and_proceed();
},
- Anarchist() {
- lose_hero_point(ANARCHISTS_ID, 1);
- 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');
},
- Communist() {
- lose_hero_point(ANARCHISTS_ID, 1);
+ down() {
+ const node = get_active_node();
+ move_track(node.a.track_id, -1 * node.a.strength);
resolve_active_and_proceed();
},
- Moderate() {
- lose_hero_point(ANARCHISTS_ID, 1);
+ up() {
+ const node = get_active_node();
+ move_track(node.a.track_id, node.a.strength);
resolve_active_and_proceed();
- },
-};
+ }
+}
states.choose_card = {
inactive: 'choose a card',
@@ -602,16 +609,39 @@ states.player_turn = {
// gen_action_card();
gen_action('play_for_ap');
gen_action('play_for_event');
+ } else {
+ gen_action('done');
}
if (hero_points > 0) {
gen_action('spend_hp');
}
},
+ done() {
+ resolve_active_and_proceed();
+ },
play_for_ap() {
const faction_id = get_faction_id(game.active);
const card = game.cards_in_play[faction_id];
log_h3(`${game.active} plays ${cards[card].title} for the Action Points`);
- resolve_active_and_proceed();
+ 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,
+ },
+ });
+ next();
},
play_for_event() {
const faction_id = get_faction_id(game.active);
@@ -647,6 +677,63 @@ states.player_turn = {
},
};
+states.resolve_event = {
+ inactive: 'resolve Fascist Event',
+ prompt() {
+ const card = get_current_event();
+ const node = get_active_node(game.engine) as LeafNode;
+ const effect: CardEffect = card.effects[node.a];
+ view.prompt = get_event_prompt(effect);
+
+ 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));
+ }
+ }
+ // for (let p = 0; p < 5; ++p) gen_action('standee', p);
+ },
+ front(f: string) {
+ const card = get_current_event();
+ const value = card.effects[get_active_node_args()].value;
+ game.fronts[f] -= value;
+ log_h3(`${value} attacks added to ${front_names[f]}`);
+ resolve_active_and_proceed();
+ },
+ standee(s: string) {
+ const effect = get_current_event().effects[get_active_node_args()];
+ const value = effect.value;
+ game.tracks[s] += value;
+ log_h3(`${track_names[effect.target]} decreased by ${Math.abs(value)}`);
+ 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',
prompt() {
@@ -716,7 +803,9 @@ function resolve_fascist_test() {
next();
}
-function move_track(track: number, change: number) {}
+function move_track(track: number, change: number) {
+
+}
// #endregion
@@ -977,6 +1066,10 @@ function get_factions_with_most_hero_poins() {
return faction_ids;
}
+function get_track_name(track_id: number): string {
+ return track_names[track_id];
+}
+
function make_list(first: number, last: number) {
let list = [];
for (let i = first; i <= last; i++) list.push(i);
diff --git a/types.d.ts b/types.d.ts
index 4ba17f7..a79c951 100644
--- a/types.d.ts
+++ b/types.d.ts
@@ -23,6 +23,7 @@ export interface Game {
bonuses: number[];
cards_in_play: Record<FactionId, CardId>;
current_events: CardId[];
+ discard: Record<FactionId | 'f', number[]>;
engine: EngineNode[];
fronts: {
a: number;