summaryrefslogtreecommitdiff
path: root/rules.ts
diff options
context:
space:
mode:
Diffstat (limited to 'rules.ts')
-rw-r--r--rules.ts134
1 files changed, 112 insertions, 22 deletions
diff --git a/rules.ts b/rules.ts
index 2cee300..db25c1b 100644
--- a/rules.ts
+++ b/rules.ts
@@ -276,6 +276,9 @@ function setup_choose_card() {
game.engine = player_order.map((faction_id) =>
create_leaf_node('choose_card', faction_id)
);
+ // Add extra confirm, otherwise first players card will be revealed
+ // before confirm
+ game.engine.push(create_leaf_node('confirm_turn', player_order[2]));
game.engine.push(create_function_node('setup_player_turn'));
next();
}
@@ -329,6 +332,7 @@ function end_of_player_turn() {
const { f: faction } = get_active_node_args();
if (get_next_faction_in_player_order(faction) === game.first_player) {
game.engine = [
+ create_leaf_node('change_active_player', game.initiative),
create_function_node('resolve_fascist_test'),
create_function_node('setup_bag_of_glory'),
];
@@ -352,6 +356,7 @@ const engine_functions: Record<string, Function> = {
checkpoint,
end_of_player_turn,
end_of_turn,
+ end_of_year_cleanup,
end_resolving_event_effects,
setup_bag_of_glory,
setup_choose_card,
@@ -469,7 +474,10 @@ function insert_before_active_node(
insert_before_or_after_active_node(node, 'before', engine);
}
-function next() {
+function next(checkpoint = false) {
+ if (checkpoint) {
+ clear_undo();
+ }
const node = get_active_node(game.engine);
if (node.t === function_node && engine_functions[node.f]) {
const args = node.a;
@@ -499,19 +507,16 @@ function next() {
}
}
-function resolve_active_node(checkpoint = false) {
+function resolve_active_node() {
const next_node = get_active_node(game.engine);
if (next_node !== null) {
next_node.r = resolved;
}
- if (checkpoint) {
- clear_undo();
- }
}
function resolve_active_and_proceed(checkpoint = false) {
- resolve_active_node(checkpoint);
- next();
+ resolve_active_node();
+ next(checkpoint);
}
// #endregion
@@ -667,6 +672,7 @@ export function setup(seed: number, _scenario: string, _options: unknown) {
top_of_events_deck: null,
turn: 0,
year: 0,
+ glory_current_year: null,
};
// Randomly choose second player
@@ -749,6 +755,13 @@ function start_turn() {
// region STATES
+function player_can_resolve_icon(icon: Icon): boolean {
+ if (icon === 'teamwork_on' && game.bonuses[TEAMWORK_BONUS] === ON) {
+ return false;
+ }
+ return true;
+}
+
states.activate_icon = {
inactive: 'activate an icon',
prompt() {
@@ -757,6 +770,9 @@ states.activate_icon = {
const c = cards[game.played_card] as PlayerCard;
for (const i of c.icons) {
gen_action(i);
+ if (!player_can_resolve_icon(i)) {
+ view.actions[i] = 0;
+ }
}
},
spend_hp() {
@@ -1059,6 +1075,21 @@ states.break_tie_winner = {
},
};
+/**
+ * Change does not do anything, but it will change
+ * active player and trigger a confirm for the previous
+ * state
+ */
+states.change_active_player = {
+ inactive: '',
+ auto_resolve() {
+ return true;
+ },
+ prompt() {
+ view.prompt = '';
+ }
+}
+
states.choose_area_ap = {
inactive: 'choose area to use Action Points',
prompt() {
@@ -1340,6 +1371,37 @@ states.draw_card = {
},
};
+states.draw_glory = {
+ inactive: 'draw from the Bag of Glory',
+ prompt() {
+ gen_spend_hero_points();
+ view.prompt = 'Draw from the Bag of Glory';
+ gen_action('draw_glory');
+ },
+ draw_glory() {
+ const index = random(game.bag_of_glory.length);
+ const faction = game.bag_of_glory[index];
+
+ game.glory.push(faction);
+
+ // TODO: remove if statement, just here atm to not break
+ // running games
+ if (!game.glory_current_year) {
+ game.glory_current_year = game.glory_current_year = {
+ a: false,
+ c: false,
+ m: false,
+ };
+ }
+ game.glory_current_year[faction] = true;
+
+ array_remove(game.bag_of_glory, index);
+
+ log(`${get_player(get_active_faction())} draws <ft${faction}> from the Bag of Glory`)
+ resolve_active_and_proceed(true);
+ },
+};
+
states.end_of_year_discard = {
inactive: 'discard cards from hand and tableau',
prompt() {
@@ -1578,6 +1640,20 @@ function can_move_track_down(track_id): boolean {
states.move_track_up_or_down = {
inactive: 'move a track',
+ auto_resolve() {
+ const { track_id, strength } = get_active_node_args();
+ const can_move_up = can_move_track_up(track_id);
+ const can_move_down = can_move_track_down(track_id);
+ if (can_move_up && can_move_down) {
+ return false;
+ }
+ if (can_move_up) {
+ move_track(track_id, strength);
+ } else if (can_move_down) {
+ move_track(track_id, -1 * strength);
+ }
+ return true;
+ },
prompt() {
gen_spend_hero_points();
const { track_id } = get_active_node_args();
@@ -2541,26 +2617,27 @@ function end_of_year() {
}
const glory_to_draw = [0, 1, 2, 5];
- const glory_this_year: Record<FactionId, boolean> = {
+
+ game.glory_current_year = {
a: false,
c: false,
m: false,
};
- const drawn_glory = [];
+
+ const player_order = get_player_order();
+
+ const engine = [];
+
for (let i = 0; i < glory_to_draw[game.year]; ++i) {
- const index = random(game.bag_of_glory.length);
- const faction = game.bag_of_glory[index];
- game.glory.push(faction);
- drawn_glory.push(faction);
- glory_this_year[faction] = true;
- array_remove(game.bag_of_glory, index);
+ engine.push(create_leaf_node('draw_glory', player_order[i % 3]));
}
- log(
- `Tokens pulled from the Bag of Glory: ${drawn_glory
- .map((faction_id: string) => `<ft${faction_id}>`)
- .join('')}`
- );
+ engine.push(create_function_node('end_of_year_cleanup'));
+ game.engine = engine;
+ next(true);
+}
+
+function end_of_year_cleanup() {
if (game.year === 3) {
// end of game
determine_winner();
@@ -2568,7 +2645,7 @@ function end_of_year() {
}
const players_to_gain_hero_points = role_ids.filter(
- (f) => !glory_this_year[f]
+ (f) => !game.glory_current_year?.[f]
);
gain_hero_points_in_player_order(players_to_gain_hero_points, game.year);
@@ -2582,6 +2659,7 @@ function end_of_year() {
// New deck is used for next year so clear top card
// if it was set
game.top_of_events_deck = null;
+ game.glory_current_year = null;
next();
}
@@ -2693,6 +2771,9 @@ function resolve_fascist_test() {
const test_passed =
status === VICTORY ||
(status !== DEFEAT && game.fronts[test.front].value >= test.value);
+
+ const hero_point_actions: EngineNode[] = [];
+
if (test_passed) {
log('The Test is passed');
for (const faction of get_player_order()) {
@@ -2705,9 +2786,16 @@ function resolve_fascist_test() {
hero_points_gain += 2;
}
if (hero_points_gain > 0) {
- gain_hero_points(faction, hero_points_gain);
+ const node = resolve_effect(
+ create_effect('hero_points', faction, hero_points_gain)
+ );
+ hero_point_actions.push(node);
}
}
+
+ if (hero_point_actions.length > 0) {
+ insert_after_active_node(create_seq_node(hero_point_actions));
+ }
} else {
log('The Test is failed');
}
@@ -2764,6 +2852,8 @@ function get_fronts_to_add_to(target: string, not: FrontId[] = []): FrontId[] {
);
} else if (game.fronts[target].status === DEFEAT) {
return get_fronts_closest_to(CLOSEST_TO_DEFEAT);
+ } else if (game.fronts[target].status === VICTORY) {
+ return get_fronts_to_add_to(ANY);
} else {
return [target as FrontId];
}