summaryrefslogtreecommitdiff
path: root/rules.js
diff options
context:
space:
mode:
authorFrans Bongers <fransbongers@franss-mbp.home>2024-12-27 19:45:21 +0100
committerFrans Bongers <fransbongers@franss-mbp.home>2024-12-27 19:45:21 +0100
commit9d0630a33e0358f943e68008823f355bceb71be1 (patch)
treebbb5b0cd5e1b8381d767ee1694f928f24f8a5ac9 /rules.js
parent5dc1ee327e16431b6700f3977469943f002a0c7c (diff)
downloadland-and-freedom-9d0630a33e0358f943e68008823f355bceb71be1.tar.gz
setup for event effects
Diffstat (limited to 'rules.js')
-rw-r--r--rules.js354
1 files changed, 307 insertions, 47 deletions
diff --git a/rules.js b/rules.js
index f68af28..711573c 100644
--- a/rules.js
+++ b/rules.js
@@ -10,9 +10,9 @@ let game = {};
var view = {};
const role_ids = [data_1.ANARCHISTS_ID, data_1.COMMUNISTS_ID, data_1.MODERATES_ID];
const faction_player_map = {
- [data_1.ANARCHISTS_ID]: data_1.ANARCHIST,
- [data_1.COMMUNISTS_ID]: data_1.COMMUNIST,
- [data_1.MODERATES_ID]: data_1.MODERATE,
+ a: data_1.ANARCHIST,
+ c: data_1.COMMUNIST,
+ m: data_1.MODERATE,
};
const player_faction_map = {
[data_1.ANARCHIST]: data_1.ANARCHISTS_ID,
@@ -160,6 +160,22 @@ const engine_functions = {
start_year,
resolve_fascist_test,
resolve_final_bid,
+ card1_event2,
+ card3_event2,
+ card10_event2,
+ card16_event2,
+ card17_event3,
+ card20_event3,
+ card22_event3,
+ card23_event1,
+ card26_event1,
+ card29_event2,
+ card35_event2,
+ card42_event3,
+ card45_event2,
+ card50_event2,
+ card53_event2,
+ card54_event1,
};
function get_active(engine) {
for (let i of engine) {
@@ -287,21 +303,22 @@ function setup(seed, _scenario, _options) {
seed: seed,
state: null,
active: data_1.ANARCHIST,
+ active_abilities: [],
bag_of_glory: [data_1.ANARCHISTS_ID, data_1.COMMUNISTS_ID, data_1.MODERATES_ID],
blank_markers: [[], [], [], [], []],
bonuses: [data_1.ON, data_1.ON],
current_events: [],
discard: {
- [data_1.ANARCHISTS_ID]: [],
- [data_1.COMMUNISTS_ID]: [],
- [data_1.MODERATES_ID]: [],
+ a: [],
+ c: [],
+ m: [],
f: [],
},
engine: [],
final_bid: {
- [data_1.ANARCHISTS_ID]: [],
- [data_1.COMMUNISTS_ID]: [],
- [data_1.MODERATES_ID]: [],
+ a: [],
+ c: [],
+ m: [],
},
fronts: {
a: {
@@ -327,38 +344,38 @@ function setup(seed, _scenario, _options) {
},
glory: [],
hands: {
- [data_1.ANARCHISTS_ID]: [],
- [data_1.COMMUNISTS_ID]: [],
- [data_1.MODERATES_ID]: [],
+ a: [],
+ c: [],
+ m: [],
},
hero_points: {
- [data_1.ANARCHISTS_ID]: 2,
- [data_1.COMMUNISTS_ID]: 2,
- [data_1.MODERATES_ID]: 0,
+ a: 2,
+ c: 2,
+ m: 0,
pool: 14,
},
chosen_cards: {
- [data_1.ANARCHISTS_ID]: null,
- [data_1.COMMUNISTS_ID]: null,
- [data_1.MODERATES_ID]: null,
+ a: null,
+ c: null,
+ m: null,
},
initiative: data_1.MODERATES_ID,
medallions: {
- [data_1.ANARCHISTS_ID]: [],
- [data_1.COMMUNISTS_ID]: [],
- [data_1.MODERATES_ID]: [],
+ a: [],
+ c: [],
+ m: [],
pool: [],
},
tableaus: {
- [data_1.ANARCHISTS_ID]: [],
- [data_1.COMMUNISTS_ID]: [],
- [data_1.MODERATES_ID]: [],
+ a: [],
+ c: [],
+ m: [],
},
tracks: [5, 5, 6, 3, 3],
trash: {
- [data_1.ANARCHISTS_ID]: [],
- [data_1.COMMUNISTS_ID]: [],
- [data_1.MODERATES_ID]: [],
+ a: [],
+ c: [],
+ m: [],
},
triggered_track_effects: [],
log: [],
@@ -409,7 +426,7 @@ function start_turn() {
log_h2('Fascist Event', 'fascist');
log(card.title);
game.engine = card.effects.map((effect) => resolve_effect(effect));
- if (game.year === 3 && game.turn === 1) {
+ if (game.year === 3 && game.turn === 4) {
game.engine.push(create_function_node('setup_final_bid'));
}
else {
@@ -548,6 +565,23 @@ states.activate_icon = {
resolve_active_and_proceed();
},
};
+states.add_card_to_tableau = {
+ inactive: 'add a card to their tableau',
+ prompt() {
+ view.prompt = 'Choose a card to add to your tableau';
+ for (const c of game.hands[get_active_faction()]) {
+ gen_action_card(c);
+ }
+ },
+ card(c) {
+ const faction_id = get_active_faction();
+ const card = cards[c];
+ array_remove(game.hands[faction_id], game.hands[faction_id].indexOf(c));
+ game.tableaus[faction_id].push(c);
+ logi(`${faction_player_map[faction_id]} adds ${card.title} to their tableau`);
+ resolve_active_and_proceed();
+ },
+};
states.add_glory = {
inactive: 'add tokens to the Bag of Glory',
prompt() {
@@ -872,14 +906,24 @@ states.gain_hero_points = {
inactive: 'gain Hero Points',
prompt() {
const value = get_active_node_args().v;
- view.prompt = value > 1 ? `Gain ${value} Hero Points` : 'Gain 1 Hero Point';
- gen_action('gain_hp');
+ if (game.hero_points.pool > 0) {
+ view.prompt =
+ value > 1 ? `Gain ${value} Hero Points` : 'Gain 1 Hero Point';
+ gen_action('gain_hp');
+ }
+ else {
+ view.prompt = 'No Hero Points available in pool. You must skip';
+ gen_action('skip');
+ }
},
gain_hp() {
const value = get_active_node_args().v;
gain_hero_points(get_active_faction(), value);
resolve_active_and_proceed();
},
+ skip() {
+ resolve_active_and_proceed();
+ },
};
states.game_over = {
get inactive() {
@@ -917,13 +961,21 @@ states.lose_hero_points = {
resolve_active_and_proceed();
},
};
+states.move_attacks = {
+ inactive: 'move attacks',
+ prompt() {
+ view.prompt = 'Choose a Front';
+ },
+};
states.move_track = {
inactive: 'move a Track',
prompt() {
const node = get_active_node();
const track = node.a.t;
const value = node.a.v;
- const name = tracks[track].name;
+ const name = track === data_1.LIBERTY_OR_COLLECTIVIZATION
+ ? 'Liberty OR Collectivization'
+ : tracks[track].name;
view.prompt = `Move ${name} ${value > 0 ? 'up' : 'down'}`;
if (track === data_1.GOVERNMENT && value === data_1.TOWARDS_CENTER) {
view.prompt = `Move ${name} towards center`;
@@ -931,7 +983,13 @@ states.move_track = {
else if (track === data_1.GOVERNMENT && value === data_1.AWAY_FROM_CENTER) {
view.prompt = `Move ${name} away from center`;
}
- gen_action_standee(track);
+ if (track === data_1.LIBERTY_OR_COLLECTIVIZATION) {
+ gen_action_standee(data_1.LIBERTY);
+ gen_action_standee(data_1.COLLECTIVIZATION);
+ }
+ else {
+ gen_action_standee(track);
+ }
},
standee(s) {
const node = get_active_node();
@@ -964,6 +1022,12 @@ states.move_track_up_or_down = {
resolve_active_and_proceed();
},
};
+states.peek_fascist_cards = {
+ inactive: 'peek at Fascist cards',
+ prompt() {
+ view.prompt = 'Choose one card to return to the top of the deck';
+ },
+};
states.player_turn = {
inactive: 'play their turn',
prompt() {
@@ -1039,6 +1103,18 @@ states.remove_blank_marker = {
resolve_active_and_proceed();
},
};
+states.remove_attack_from_fronts = {
+ inactive: 'remove attacks',
+ prompt() {
+ view.prompt = 'Choose a front to remove an attack';
+ },
+};
+states.return_card = {
+ inactive: 'return a card',
+ prompt() {
+ view.prompt = 'Choose a card to return';
+ },
+};
states.spend_hero_points = {
inactive: 'spend Hero points',
prompt() {
@@ -1134,6 +1210,23 @@ states.spend_hero_points = {
resolve_active_and_proceed();
},
};
+states.swap_card_tableau_hand = {
+ inactive: 'swap cards',
+ prompt() {
+ view.prompt = 'Choose cards';
+ const faction = get_active_faction();
+ for (const c of game.hands[faction]) {
+ gen_action_card(c);
+ }
+ },
+ card(c) { },
+};
+states.take_hero_points = {
+ inactive: 'take Hero Points',
+ prompt() {
+ view.prompt = 'Choose a player to take Hero Points from';
+ },
+};
states.use_organization_medallion = {
inactive: 'use Organization Medallion',
prompt() {
@@ -1179,6 +1272,87 @@ states.use_strategy_medallion = {
resolve_active_and_proceed();
},
};
+function card1_event2() {
+ const value = game.tracks[data_1.FOREIGN_AID] >= 6 ? 3 : 2;
+ insert_after_active_node(resolve_effect((0, data_1.create_effect)('track', data_1.FOREIGN_AID, value)));
+ resolve_active_and_proceed();
+}
+function card3_event2() {
+ const value = game.tracks[data_1.FOREIGN_AID] >= 8 ? 2 : 1;
+ insert_after_active_node(resolve_effect((0, data_1.create_effect)('track', data_1.GOVERNMENT, value)));
+ resolve_active_and_proceed();
+}
+function card10_event2() {
+ if (game.tracks[data_1.FOREIGN_AID] >= 6) {
+ resolve_effect((0, data_1.create_effect)('draw_card', data_1.SELF, 2));
+ }
+ resolve_active_and_proceed();
+}
+function card16_event2() {
+ const value = game.tracks[data_1.GOVERNMENT] >= 6 ? 4 : 3;
+ insert_after_active_node(resolve_effect((0, data_1.create_effect)('track', data_1.FOREIGN_AID, value)));
+ resolve_active_and_proceed();
+}
+function card17_event3() {
+ const value = game.tracks[data_1.GOVERNMENT] >= 6 ? -4 : -3;
+ insert_after_active_node(resolve_effect((0, data_1.create_effect)('track', data_1.COLLECTIVIZATION, value)));
+ resolve_active_and_proceed();
+}
+function card20_event3() {
+ const value = game.tracks[data_1.SOVIET_SUPPORT] >= 6 ? 2 : 1;
+ insert_after_active_node(create_seq_node([
+ resolve_effect((0, data_1.create_effect)('front', data_1.MADRID, value)),
+ resolve_effect((0, data_1.create_effect)('front', data_1.SOUTHERN, value)),
+ ]));
+ resolve_active_and_proceed();
+}
+function card22_event3() {
+ const value = game.tracks[data_1.SOVIET_SUPPORT] >= 8 ? -3 : -3;
+ insert_after_active_node(resolve_effect((0, data_1.create_effect)('track', data_1.GOVERNMENT, value)));
+ resolve_active_and_proceed();
+}
+function card23_event1() {
+ const value = game.tracks[data_1.SOVIET_SUPPORT] >= 6 ? 4 : 3;
+ insert_after_active_node(resolve_effect((0, data_1.create_effect)('front', data_1.ANY, value)));
+ resolve_active_and_proceed();
+}
+function card26_event1() {
+ game.active_abilities.push(data_1.COMMUNIST_EXTRA_HERO_POINT);
+}
+function card29_event2() {
+ const value = game.tracks[data_1.GOVERNMENT] <= 5 ? -3 : -2;
+ insert_after_active_node(resolve_effect((0, data_1.create_effect)('track', data_1.LIBERTY, value)));
+ resolve_active_and_proceed();
+}
+function card35_event2() {
+ const value = game.tracks[data_1.GOVERNMENT] <= 5 ? 2 : 1;
+ insert_after_active_node(resolve_effect((0, data_1.create_effect)('track', data_1.SOVIET_SUPPORT, value)));
+ resolve_active_and_proceed();
+}
+function card42_event3() {
+ game.active_abilities.push(data_1.ANARCHIST_EXTRA_HERO_POINT);
+}
+function card45_event2() {
+ if (game.tracks[data_1.LIBERTY] >= 6) {
+ insert_after_active_node(resolve_effect((0, data_1.create_effect)('track', data_1.COLLECTIVIZATION, 1)));
+ }
+ resolve_active_and_proceed();
+}
+function card50_event2() {
+ const value = game.tracks[data_1.COLLECTIVIZATION] >= 8 ? 3 : 2;
+ insert_after_active_node(resolve_effect((0, data_1.create_effect)('front', data_1.ARAGON, value)));
+ resolve_active_and_proceed();
+}
+function card53_event2() {
+ const value = game.tracks[data_1.LIBERTY] >= 8 ? 3 : 2;
+ insert_after_active_node(resolve_effect((0, data_1.create_effect)('front', data_1.ANY, value)));
+ resolve_active_and_proceed();
+}
+function card54_event1() {
+ const value = game.tracks[data_1.COLLECTIVIZATION] >= 8 ? 3 : 2;
+ insert_after_active_node(resolve_effect((0, data_1.create_effect)('track', data_1.LIBERTY, value)));
+ resolve_active_and_proceed();
+}
function add_glory(faction, amount, indent = false) {
for (let i = 0; i < amount; ++i) {
game.bag_of_glory.push(get_active_faction());
@@ -1260,6 +1434,7 @@ function end_of_turn() {
Object.keys(game.fronts).forEach((front_id) => {
game.fronts[front_id].contributions = [];
});
+ game.active_abilities = [];
game.used_medallions = [];
if (game.turn === 4) {
end_of_year();
@@ -1283,9 +1458,9 @@ function end_of_year() {
}
const glory_to_draw = [0, 1, 2, 5];
const glory_this_year = {
- [data_1.ANARCHISTS_ID]: false,
- [data_1.COMMUNISTS_ID]: false,
- [data_1.MODERATES_ID]: false,
+ a: false,
+ c: false,
+ m: false,
};
for (let i = 0; i < glory_to_draw[game.year]; ++i) {
const index = random(game.bag_of_glory.length);
@@ -1315,6 +1490,12 @@ function gain_hero_points(faction_id, value) {
if (game.hero_points.pool === 0) {
return;
}
+ if ((faction_id === data_1.ANARCHISTS_ID &&
+ (game.active_abilities || []).includes(data_1.ANARCHIST_EXTRA_HERO_POINT)) ||
+ (faction_id === data_1.COMMUNISTS_ID &&
+ (game.active_abilities || []).includes(data_1.COMMUNIST_EXTRA_HERO_POINT))) {
+ value++;
+ }
const gain = Math.min(game.hero_points.pool, value);
game.hero_points.pool -= gain;
game.hero_points[faction_id] += gain;
@@ -1571,10 +1752,15 @@ function get_faction_to_resolve_effect(effect) {
return effect.faction;
}
const effect_type_state_map = {
+ add_card_to_tableau: 'add_card_to_tableau',
attack: 'attack_front',
bonus: 'change_bonus',
front: 'add_to_front',
medallion: 'choose_medallion',
+ remove_blank_marker: 'remove_blank_marker',
+ return_card: 'return_card',
+ swap_card_tableau_hand: 'swap_card_tableau_hand',
+ take_hero_points: 'take_hero_points',
track: 'move_track',
};
function resolve_effect(effect) {
@@ -1583,25 +1769,99 @@ function resolve_effect(effect) {
v: effect.value,
};
const faction = get_faction_to_resolve_effect(effect);
+ if (effect.type === 'function') {
+ return create_function_node(effect.target);
+ }
+ if (effect.type === 'state') {
+ return create_leaf_node(effect.target, faction, {
+ v: effect.value,
+ });
+ }
let state = effect_type_state_map[effect.type];
if (state !== undefined) {
return create_leaf_node(state, faction, args);
}
- if (effect.type === 'hero_points' &&
- effect.target === data_1.PLAYER_WITH_MOST_HERO_POINTS) {
- state = 'lose_hero_points';
- }
- if (effect.type === 'hero_points' && effect.target === data_1.SELF) {
- state = 'gain_hero_points';
- }
- if (effect.type === 'draw_card' && effect.target === data_1.SELF) {
- state = 'draw_card';
+ const strategies = [
+ {
+ condition: effect.type === 'hero_points' &&
+ effect.target === data_1.PLAYER_WITH_MOST_HERO_POINTS,
+ resolve: () => {
+ return create_leaf_node('lose_hero_points', faction, args);
+ },
+ },
+ {
+ condition: effect.type === 'hero_points' && effect.target === data_1.ALL_PLAYERS,
+ resolve: () => {
+ return create_seq_node(get_player_order().map((faction) => create_leaf_node('gain_hero_points', faction, {
+ v: effect.value,
+ })));
+ },
+ },
+ {
+ condition: effect.type === 'hero_points' && effect.target === data_1.SELF,
+ resolve: () => {
+ return create_leaf_node('gain_hero_points', faction, args);
+ },
+ },
+ {
+ condition: effect.type === 'hero_points' &&
+ role_ids.includes(effect.target),
+ resolve: () => {
+ return create_leaf_node('gain_hero_points', effect.target, args);
+ },
+ },
+ {
+ condition: effect.type === 'hero_points' && effect.target === data_1.INITIATIVE_PLAYER,
+ resolve: () => {
+ return create_leaf_node('gain_hero_points', game.initiative);
+ },
+ },
+ {
+ condition: effect.type === 'draw_card' && effect.target === data_1.SELF,
+ resolve: () => {
+ return create_leaf_node('draw_card', faction, args);
+ },
+ },
+ {
+ condition: effect.type === 'draw_card' && effect.target === data_1.INITIATIVE_PLAYER,
+ resolve: () => {
+ return create_leaf_node('draw_card', game.initiative, args);
+ },
+ },
+ {
+ condition: effect.type === 'draw_card' &&
+ role_ids.includes(effect.target),
+ resolve: () => {
+ return create_leaf_node('draw_card', effect.target, args);
+ },
+ },
+ {
+ condition: effect.type === 'draw_card' && effect.target === data_1.ALL_PLAYERS,
+ resolve: () => {
+ return create_seq_node(get_player_order(get_active_faction()).map((faction) => create_leaf_node('draw_card', faction, {
+ v: effect.value,
+ })));
+ },
+ },
+ {
+ condition: effect.type === 'draw_card' && effect.target === data_1.OTHER_PLAYERS,
+ resolve: () => {
+ const leaf_nodes = get_player_order(get_active_faction()).map((faction) => create_leaf_node('draw_card', faction, {
+ v: effect.value,
+ }));
+ array_remove(leaf_nodes, 0);
+ return create_seq_node(leaf_nodes);
+ },
+ },
+ ];
+ const strategy = strategies.find((strategy) => strategy.condition);
+ if (strategy) {
+ return strategy.resolve();
}
- if (state === undefined) {
+ else {
console.log('----UNRESOLVED EFFECT----', effect);
- return null;
+ throw new Error('Unresolved effect');
}
- return create_leaf_node(state, faction, args);
}
function win_final_bid(faction_id) {
log_br();