summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data.js6
-rw-r--r--data.ts6
-rw-r--r--play.js1
-rw-r--r--play.ts1
-rw-r--r--rules.js92
-rw-r--r--rules.ts110
-rw-r--r--types.d.ts1
7 files changed, 140 insertions, 77 deletions
diff --git a/data.js b/data.js
index 3ade53d..8c86144 100644
--- a/data.js
+++ b/data.js
@@ -818,7 +818,7 @@ const data = {
effects: [
create_effect('attack', SOUTHERN, -3, INITIATIVE_PLAYER),
create_effect('attack', CLOSEST_TO_VICTORY, -2, INITIATIVE_PLAYER),
- create_effect('bonus', MORALE_BONUS, OFF, INITIATIVE_PLAYER),
+ create_effect('bonus', TEAMWORK_BONUS, OFF, INITIATIVE_PLAYER),
],
test: {
front: SOUTHERN,
@@ -1285,7 +1285,7 @@ const data = {
test: {
front: ARAGON,
value: -1,
- pass: create_effect('track', GOVERNMENT, TOWARDS_CENTER),
+ pass: create_effect('track', GOVERNMENT, AWAY_FROM_CENTER),
fail: create_effect('track', COLLECTIVIZATION, -1),
},
title: 'BATTLE OF TERUEL',
@@ -1872,7 +1872,7 @@ const data = {
null,
null,
null,
- create_effect('track', LIBERTY, -1),
+ create_effect('track', COLLECTIVIZATION, -1),
null,
create_effect('front', ANY, 1, MODERATES_ID),
create_effect('track', GOVERNMENT, 1),
diff --git a/data.ts b/data.ts
index d38ea68..b82dea0 100644
--- a/data.ts
+++ b/data.ts
@@ -840,7 +840,7 @@ const data: StaticData = {
effects: [
create_effect('attack', SOUTHERN, -3, INITIATIVE_PLAYER),
create_effect('attack', CLOSEST_TO_VICTORY, -2, INITIATIVE_PLAYER),
- create_effect('bonus', MORALE_BONUS, OFF, INITIATIVE_PLAYER),
+ create_effect('bonus', TEAMWORK_BONUS, OFF, INITIATIVE_PLAYER),
],
test: {
front: SOUTHERN,
@@ -1322,7 +1322,7 @@ const data: StaticData = {
test: {
front: ARAGON,
value: -1,
- pass: create_effect('track', GOVERNMENT, TOWARDS_CENTER),
+ pass: create_effect('track', GOVERNMENT, AWAY_FROM_CENTER),
fail: create_effect('track', COLLECTIVIZATION, -1),
},
title: 'BATTLE OF TERUEL',
@@ -1944,7 +1944,7 @@ const data: StaticData = {
null,
null,
null,
- create_effect('track', LIBERTY, -1),
+ create_effect('track', COLLECTIVIZATION, -1),
null,
create_effect('front', ANY, 1, MODERATES_ID),
create_effect('track', GOVERNMENT, 1),
diff --git a/play.js b/play.js
index b55c6be..5b002e8 100644
--- a/play.js
+++ b/play.js
@@ -427,6 +427,7 @@ function on_update() {
action_button('move_track', 'Move a Track');
action_button('turn_on_bonus', 'Turn on a Bonus');
action_button('add_glory', 'Add to Bag of Glory');
+ action_button('draw_glory', 'Draw from Bag of Glory');
action_button('up', 'Up');
action_button('down', 'Down');
action_button('next', 'Next');
diff --git a/play.ts b/play.ts
index adf9f9d..0e1eea6 100644
--- a/play.ts
+++ b/play.ts
@@ -544,6 +544,7 @@ function on_update() {
action_button('turn_on_bonus', 'Turn on a Bonus');
action_button('add_glory', 'Add to Bag of Glory');
+ action_button('draw_glory', 'Draw from Bag of Glory');
action_button('up', 'Up');
action_button('down', 'Down');
action_button('next', 'Next');
diff --git a/rules.js b/rules.js
index 8d0bd80..abff1d8 100644
--- a/rules.js
+++ b/rules.js
@@ -175,6 +175,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'),
];
@@ -197,6 +198,7 @@ const engine_functions = {
checkpoint,
end_of_player_turn,
end_of_turn,
+ end_of_year_cleanup,
end_resolving_event_effects,
setup_bag_of_glory,
setup_choose_card,
@@ -287,7 +289,10 @@ function insert_after_active_node(node, engine = game.engine) {
function insert_before_active_node(node, engine = game.engine) {
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;
@@ -313,18 +318,15 @@ 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);
}
function game_view(state, current) {
game = state;
@@ -465,6 +467,7 @@ function setup(seed, _scenario, _options) {
top_of_events_deck: null,
turn: 0,
year: 0,
+ glory_current_year: null,
};
game.player_order.push(exports.roles[random(2)]);
game.player_order.push(game.player_order[1] === data_1.ANARCHIST ? data_1.COMMUNIST : data_1.ANARCHIST);
@@ -830,6 +833,15 @@ states.break_tie_winner = {
resolve_active_and_proceed();
},
};
+states.change_active_player = {
+ inactive: '',
+ auto_resolve() {
+ return true;
+ },
+ prompt() {
+ view.prompt = '';
+ }
+};
states.choose_area_ap = {
inactive: 'choose area to use Action Points',
prompt() {
@@ -1050,11 +1062,6 @@ states.confirm_turn = {
};
states.draw_card = {
inactive: 'draw a card',
- auto_resolve() {
- const { v } = get_active_node_args();
- draw_hand_cards(get_active_faction(), v);
- return true;
- },
prompt() {
gen_spend_hero_points();
const { v } = get_active_node_args();
@@ -1075,6 +1082,30 @@ states.draw_card = {
resolve_active_and_proceed();
},
};
+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);
+ 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() {
@@ -1120,17 +1151,6 @@ states.end_of_year_discard = {
};
states.hero_points = {
inactive: 'gain Hero Points',
- auto_resolve() {
- const { v } = get_active_node_args();
- const faction = get_active_faction();
- if (v < 0) {
- lose_hero_points(faction, v);
- }
- else if (v > 0 && game.hero_points.pool > 0) {
- gain_hero_points(faction, v);
- }
- return true;
- },
prompt() {
gen_spend_hero_points();
const value = get_active_node_args().v;
@@ -2103,33 +2123,32 @@ function end_of_year() {
log_h1('End of year');
}
const glory_to_draw = [0, 1, 2, 5];
- const glory_this_year = {
+ 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) => `<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) {
determine_winner();
return;
}
- const players_to_gain_hero_points = role_ids.filter((f) => !glory_this_year[f]);
+ const players_to_gain_hero_points = role_ids.filter((f) => !game.glory_current_year?.[f]);
gain_hero_points_in_player_order(players_to_gain_hero_points, game.year);
game.engine = get_player_order().map((f) => create_function_node('check_end_of_year_discard', { f }));
game.engine.push(create_function_node('checkpoint'));
game.engine.push(create_function_node('start_year'));
game.top_of_events_deck = null;
+ game.glory_current_year = null;
next();
}
function end_resolving_event_effects() {
@@ -2273,6 +2292,9 @@ function get_fronts_to_add_to(target, not = []) {
else if (game.fronts[target].status === data_1.DEFEAT) {
return get_fronts_closest_to(data_1.CLOSEST_TO_DEFEAT);
}
+ else if (game.fronts[target].status === data_1.VICTORY) {
+ return get_fronts_to_add_to(data_1.ANY);
+ }
else {
return [target];
}
diff --git a/rules.ts b/rules.ts
index 6ba2470..db25c1b 100644
--- a/rules.ts
+++ b/rules.ts
@@ -332,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'),
];
@@ -355,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,
@@ -472,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;
@@ -502,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
@@ -670,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
@@ -1072,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() {
@@ -1332,11 +1350,6 @@ states.confirm_turn = {
states.draw_card = {
inactive: 'draw a card',
- auto_resolve() {
- const { v } = get_active_node_args();
- draw_hand_cards(get_active_faction(), v);
- return true;
- },
prompt() {
gen_spend_hero_points();
const { v } = get_active_node_args();
@@ -1358,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() {
@@ -1407,16 +1451,6 @@ states.end_of_year_discard = {
states.hero_points = {
inactive: 'gain Hero Points',
- auto_resolve() {
- const { v } = get_active_node_args();
- const faction = get_active_faction();
- if (v < 0) {
- lose_hero_points(faction, v);
- } else if (v > 0 && game.hero_points.pool > 0) {
- gain_hero_points(faction, v);
- }
- return true;
- },
prompt() {
gen_spend_hero_points();
const value = get_active_node_args().v;
@@ -2583,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();
@@ -2610,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);
@@ -2624,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();
}
@@ -2816,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];
}
diff --git a/types.d.ts b/types.d.ts
index d55f03e..b4ef5f0 100644
--- a/types.d.ts
+++ b/types.d.ts
@@ -72,6 +72,7 @@ export interface Game {
trash: Record<FactionId, CardId[]>;
triggered_track_effects: number[];
used_medallions: number[];
+ glory_current_year?: Record<FactionId, boolean> | null;
}
export interface View {