summaryrefslogtreecommitdiff
path: root/rules.js
diff options
context:
space:
mode:
Diffstat (limited to 'rules.js')
-rw-r--r--rules.js368
1 files changed, 297 insertions, 71 deletions
diff --git a/rules.js b/rules.js
index 0f53324..e85112a 100644
--- a/rules.js
+++ b/rules.js
@@ -126,6 +126,7 @@ function checkpoint() {
resolve_active_and_proceed();
}
function setup_bag_of_glory() {
+ log_h1('Bag of Glory');
game.engine = [
create_leaf_node('add_glory', game.initiative),
create_function_node('end_of_turn'),
@@ -187,6 +188,7 @@ function start_of_player_turn() {
const player = faction_player_map[args.f];
log_h2(player, player);
game.faction_turn = args.f;
+ game.played_card = game.selected_cards[args.f][0];
resolve_active_and_proceed();
}
const engine_functions = {
@@ -194,6 +196,7 @@ const engine_functions = {
checkpoint,
end_of_player_turn,
end_of_turn,
+ end_resolving_event_effects,
setup_bag_of_glory,
setup_choose_card,
setup_final_bid,
@@ -239,6 +242,18 @@ function get_active_node(engine = game.engine) {
const a = get_active(engine);
return a === null ? null : a.node;
}
+function get_nodes_for_state(state, engine = game.engine) {
+ let nodes = [];
+ for (let i of engine) {
+ if (i.t === leaf_node && i.s === state) {
+ nodes.push(i);
+ }
+ if (i.t === seq_node) {
+ nodes = nodes.concat(get_nodes_for_state(state, i.c));
+ }
+ }
+ return nodes;
+}
function get_active_node_args() {
const node = get_active_node(game.engine);
if (node.t === leaf_node || node.t === function_node) {
@@ -292,6 +307,9 @@ function next() {
return;
}
game.active = next_active;
+ if (states[game.state].auto_resolve && states[game.state].auto_resolve()) {
+ resolve_active_and_proceed();
+ }
}
}
function resolve_active_node(checkpoint = false) {
@@ -314,14 +332,20 @@ function game_view(state, current) {
engine: game.engine,
log: game.log,
prompt: null,
+ state: game.state,
bag_of_glory: game.bag_of_glory,
+ bag_of_glory_count: game.bag_of_glory.length,
bonuses: game.bonuses,
current,
+ current_player_faction: faction,
current_events: game.current_events,
first_player: game.first_player,
fronts: game.fronts,
glory: game.glory,
hand: faction === null ? [] : game.hands[faction],
+ discard: faction === null ? [] : game.discard[faction],
+ trash: faction === null ? [] : game.trash[faction],
+ deck: faction === null ? [] : list_deck(faction),
hero_points: game.hero_points,
initiative: game.initiative,
medallions: game.medallions,
@@ -483,7 +507,7 @@ function start_turn() {
const card = cards[cardId];
log_h2('Fascist Event', 'fascist');
log(card.title);
- game.engine = card.effects.map((effect) => resolve_effect(effect));
+ game.engine = card.effects.map((effect) => resolve_effect(effect, 'fascist_event'));
if (game.year === 3 && game.turn === 4) {
game.engine.push(create_function_node('setup_final_bid'));
}
@@ -492,6 +516,12 @@ function start_turn() {
}
next();
}
+function player_can_resolve_icon(icon) {
+ if (icon === 'teamwork_on' && game.bonuses[data_1.TEAMWORK_BONUS] === data_1.ON) {
+ return false;
+ }
+ return true;
+}
states.activate_icon = {
inactive: 'activate an icon',
prompt() {
@@ -500,6 +530,9 @@ states.activate_icon = {
const c = cards[game.played_card];
for (const i of c.icons) {
gen_action(i);
+ if (!player_can_resolve_icon(i)) {
+ view.actions[i] = 0;
+ }
}
},
spend_hp() {
@@ -687,6 +720,9 @@ states.add_to_front = {
for (let f of possible_fronts) {
gen_action_front(f);
}
+ if (args.src) {
+ view.prompt = add_prompt_prefix(view.prompt, get_source_name(args.src));
+ }
},
spend_hp() {
resolve_spend_hp();
@@ -701,7 +737,7 @@ states.attack_front = {
inactive: 'attack a Front',
prompt() {
gen_spend_hero_points();
- const { t: target, n } = get_active_node_args();
+ const { t: target, n, src } = get_active_node_args();
let fronts = [];
if (target === data_1.ANY) {
fronts = get_fronts_to_add_to(data_1.ANY, n);
@@ -722,6 +758,18 @@ states.attack_front = {
fronts.length === 1
? `Attack ${front_names[fronts[0]]}`
: 'Attack a front';
+ let prefix = '';
+ if (src) {
+ prefix = `${get_source_name(src)}: `;
+ }
+ if (fronts.length === 1) {
+ view.prompt = prefix
+ ? `${prefix}attack ${front_names[fronts[0]]}`
+ : `Attack ${front_names[fronts[0]]}`;
+ }
+ else {
+ view.prompt = prefix ? `${prefix}attack a front` : `Attack a front`;
+ }
fronts.forEach((id) => gen_action('front', id));
},
spend_hp() {
@@ -869,7 +917,11 @@ states.choose_card = {
inactive: 'choose a card',
prompt() {
gen_spend_hero_points();
+ const { src } = get_active_node_args();
view.prompt = 'Choose a card to play this turn';
+ if (src === 'momentum') {
+ view.prompt = 'Choose a card to play';
+ }
const faction = get_active_faction();
const hand = game.hands[faction];
for (let c of hand) {
@@ -884,6 +936,10 @@ states.choose_card = {
card(c) {
const faction = get_active_faction();
game.selected_cards[faction].push(c);
+ const { src } = get_active_node_args();
+ if (src === 'momentum') {
+ game.played_card = game.selected_cards[faction][0];
+ }
resolve_active_and_proceed();
},
};
@@ -916,6 +972,31 @@ states.choose_final_bid = {
resolve_active_and_proceed(true);
},
};
+function setup_momentum() {
+ const faction = get_active_faction();
+ if (game.faction_turn !== faction) {
+ insert_after_active_node(resolve_effect((0, data_1.create_effect)('play_card', faction, 1), 'momentum'));
+ return;
+ }
+ const node = get_nodes_for_state('player_turn')[0];
+ console.log('node', node);
+ const player_needs_to_play_card = game.selected_cards[faction].length > 0;
+ const { use_ap, use_morale_bonus, resolving_event } = node.a ?? {};
+ if (player_needs_to_play_card ||
+ use_ap ||
+ use_morale_bonus ||
+ resolving_event) {
+ node.a = {
+ ...(node.a || {}),
+ use_momentum: true,
+ };
+ }
+ else {
+ insert_before_active_node(create_leaf_node('choose_card', faction, {
+ src: 'momentum',
+ }));
+ }
+}
states.choose_medallion = {
inactive: 'choose a medallion',
prompt() {
@@ -945,7 +1026,7 @@ states.choose_medallion = {
gain_hero_points(faction, 7);
break;
case 2:
- insert_after_active_node(create_leaf_node('choose_card', faction));
+ setup_momentum();
break;
default:
game.medallions[faction].push(m);
@@ -991,19 +1072,26 @@ states.draw_card = {
states.end_of_year_discard = {
inactive: 'discard cards from hand and tableau',
prompt() {
- view.prompt = 'Discard a card';
const faction_id = get_active_faction();
const hand = game.hands[faction_id];
const hand_limit = get_hand_limit(faction_id);
- if (hand.length > hand_limit) {
+ const needs_to_discard_from_hand = hand.length > hand_limit;
+ if (needs_to_discard_from_hand) {
for (let c of hand)
gen_action_card(c);
}
const tableau = game.tableaus[faction_id];
- if (tableau.length > game.year) {
+ const needs_to_discard_from_tableau = tableau.length > game.year;
+ if (needs_to_discard_from_tableau) {
for (let c of tableau)
gen_action_card(c);
}
+ if (needs_to_discard_from_hand && needs_to_discard_from_tableau) {
+ view.prompt = 'Discard a card from your hand or tableau';
+ }
+ else {
+ view.prompt = `Discard a card from your ${needs_to_discard_from_hand ? 'hand' : 'tableau'}`;
+ }
},
card(c) {
const faction_id = get_active_faction();
@@ -1126,6 +1214,9 @@ states.move_track = {
else if (track === data_1.GOVERNMENT && value === data_1.AWAY_FROM_CENTER) {
view.prompt = `Move ${name} away from center`;
}
+ if (node.a.src) {
+ view.prompt = add_prompt_prefix(view.prompt, get_source_name(node.a.src));
+ }
if (track === data_1.LIBERTY_OR_COLLECTIVIZATION) {
gen_action_standee(data_1.LIBERTY);
gen_action_standee(data_1.COLLECTIVIZATION);
@@ -1242,41 +1333,71 @@ function resolve_spend_hp() {
log('Spends Hero Points');
next();
}
+function set_player_turn_prompt({ can_play_card, can_spend_hp, use_ap, use_momentum, use_morale_bonus, }) {
+ console.log('set_player_turn_prompt', {
+ can_play_card,
+ use_ap,
+ use_morale_bonus,
+ use_momentum,
+ });
+ if (can_play_card && can_spend_hp) {
+ view.prompt = 'Play a card or spend Hero points';
+ }
+ else if (can_play_card && !can_spend_hp) {
+ view.prompt = 'Play a card';
+ }
+ else if (use_ap || use_morale_bonus || use_momentum) {
+ const text_options = [];
+ if (use_ap) {
+ text_options.push('Action Points');
+ }
+ if (use_morale_bonus) {
+ text_options.push('Morale Bonus');
+ }
+ if (can_spend_hp) {
+ text_options.push('spend Hero points');
+ }
+ if (use_momentum) {
+ view.prompt = can_spend_hp
+ ? 'Play second card or spend Hero Points'
+ : 'Play second card';
+ }
+ else {
+ view.prompt = `Use ${text_options.join(', ')} or end turn`;
+ }
+ }
+ else if (can_spend_hp) {
+ view.prompt = 'Spend Hero Points or end turn';
+ }
+ else {
+ view.prompt = 'End turn';
+ }
+}
states.player_turn = {
inactive: 'play their turn',
prompt() {
gen_spend_hero_points();
const faction_id = get_active_faction();
- const { use_ap, use_morale_bonus } = get_active_node_args();
+ let { use_ap, use_morale_bonus, use_momentum } = get_active_node_args();
+ use_morale_bonus = use_morale_bonus && game.bonuses[data_1.MORALE_BONUS] === data_1.ON;
const can_spend_hp = game.faction_turn === faction_id && game.hero_points[faction_id] > 0;
const can_play_card = game.selected_cards[faction_id].length > 0;
- if (can_play_card && can_spend_hp) {
- view.prompt = 'Play a card or spend Hero points';
- }
- else if (can_play_card && !can_spend_hp) {
- view.prompt = 'Play a card';
- }
- else if (use_ap || use_morale_bonus) {
- const text_options = [];
- if (use_ap) {
- text_options.push('Action Points');
- }
- if (use_morale_bonus) {
- text_options.push('Morale Bonus');
- }
- if (can_spend_hp) {
- text_options.push('spend Hero points');
+ console.log('can_play_card', can_play_card);
+ if (use_momentum) {
+ gen_action('use_momentum');
+ if (use_ap || use_morale_bonus || can_play_card) {
+ view.actions['use_momentum'] = 0;
}
- view.prompt = `Use ${text_options.join(', ')} or end turn`;
- }
- else if (can_spend_hp) {
- view.prompt = 'Spend Hero Points or end turn';
- }
- else {
- view.prompt = 'End turn';
}
+ set_player_turn_prompt({
+ can_play_card,
+ can_spend_hp,
+ use_ap,
+ use_momentum,
+ use_morale_bonus,
+ });
if (can_play_card) {
- gen_action('play_for_ap');
+ gen_action('play_to_tableau');
gen_action('play_for_event');
}
if (use_ap) {
@@ -1285,21 +1406,21 @@ states.player_turn = {
if (use_morale_bonus && game.bonuses[data_1.MORALE_BONUS] === data_1.ON) {
gen_action('use_morale_bonus');
}
- if (!can_play_card && !use_ap) {
- gen_action('done');
+ if (!(can_play_card || use_ap || use_morale_bonus || use_momentum)) {
+ gen_action('end_turn');
}
},
spend_hp() {
resolve_spend_hp();
},
- done() {
+ end_turn() {
game.faction_turn = null;
game.played_card = null;
resolve_active_and_proceed(true);
},
- play_for_ap() {
+ play_to_tableau() {
const faction = get_active_faction();
- const { strength } = play_card(faction, 'play_for_ap');
+ const { strength } = play_card(faction, 'play_to_tableau');
update_active_node_args({
use_morale_bonus: true,
use_ap: true,
@@ -1310,7 +1431,12 @@ states.player_turn = {
play_for_event() {
const faction = get_active_faction();
const { effects } = play_card(faction, 'play_for_event');
- insert_before_active_node(create_effects_node(effects));
+ update_active_node_args({
+ resolving_event: true,
+ });
+ const node = create_effects_node(effects);
+ node.c.push(create_function_node('end_resolving_event_effects'));
+ insert_before_active_node(node);
next();
},
use_ap() {
@@ -1324,6 +1450,14 @@ states.player_turn = {
}));
next();
},
+ use_momentum() {
+ update_active_node_args({
+ use_morale_bonus: false,
+ use_momentum: false,
+ });
+ setup_momentum();
+ next();
+ },
use_morale_bonus() {
update_active_node_args({
use_morale_bonus: false,
@@ -1387,7 +1521,7 @@ states.remove_attack_from_fronts = {
front(id) {
const { f, v: card_id } = get_active_node_args();
const removed_value = card_id === 6 ? 1 : Math.min(3, Math.abs(game.fronts[id].value));
- update_front(id, removed_value);
+ update_front(id, removed_value, get_active_faction());
const fronts = f ?? {};
fronts[id] = removed_value;
update_active_node_args({ f: fronts });
@@ -1446,31 +1580,60 @@ states.return_card = {
};
states.spend_hero_points = {
inactive: 'spend Hero points',
+ auto_resolve() {
+ const hero_points = game.hero_points[get_active_faction()];
+ if (hero_points === 0) {
+ return true;
+ }
+ return false;
+ },
prompt() {
view.prompt = 'Spend your Hero points';
- gen_action('done');
const faction = get_active_faction();
+ const { move_track, turn_on_bonus } = get_active_node_args();
+ if (move_track) {
+ view.prompt = 'Spend Hero points: move a Track';
+ }
+ else if (turn_on_bonus) {
+ view.prompt = 'Spend Hero points: turn on a Bonus';
+ }
+ if (!(move_track || turn_on_bonus)) {
+ gen_action('done');
+ }
const hero_points = game.hero_points[get_active_faction()];
if (hero_points === 0) {
return;
}
- gen_action('draw_card');
- if (can_use_medallion(data_1.ARCHIVES_MEDALLION_ID, faction)) {
- gen_action('remove_blank_marker');
- }
- if (can_use_medallion(data_1.VOLUNTEERS_MEDALLION_ID, faction)) {
- gen_action('add_to_front');
+ if (!(move_track || turn_on_bonus)) {
+ gen_action('draw_card');
+ if (can_use_medallion(data_1.ARCHIVES_MEDALLION_ID, faction)) {
+ gen_action('remove_blank_marker');
+ }
+ if (can_use_medallion(data_1.VOLUNTEERS_MEDALLION_ID, faction)) {
+ gen_action('add_to_front');
+ }
}
if (hero_points < 2) {
return;
}
- gen_action_standee(data_1.FOREIGN_AID);
- gen_action_standee(data_1.SOVIET_SUPPORT);
+ if (!(move_track || turn_on_bonus)) {
+ gen_action('move_track');
+ }
for (const bonus of bonuses) {
- if (game.bonuses[bonus] === data_1.OFF) {
+ let bonus_off = false;
+ if (!move_track && game.bonuses[bonus] === data_1.OFF) {
gen_action_bonus(bonus);
+ bonus_off = true;
}
+ if (bonus_off && !turn_on_bonus) {
+ gen_action('turn_on_bonus');
+ }
+ }
+ if (turn_on_bonus) {
+ return;
}
+ gen_action_standee(data_1.FOREIGN_AID);
+ gen_action_standee(data_1.SOVIET_SUPPORT);
if (hero_points < 3) {
return;
}
@@ -1497,13 +1660,24 @@ states.spend_hero_points = {
resolve_active_and_proceed();
},
bonus(b) {
+ update_active_node_args({
+ turn_on_bonus: false,
+ });
update_bonus(b, data_1.ON);
pay_hero_points(get_active_faction(), 2);
+ next();
},
draw_card() {
const faction = get_active_faction();
pay_hero_points(faction, 1);
draw_hand_cards(faction, 1);
+ next();
+ },
+ move_track() {
+ update_active_node_args({
+ move_track: true,
+ });
+ next();
},
remove_blank_marker() {
const faction = get_active_faction();
@@ -1520,6 +1694,9 @@ states.spend_hero_points = {
resolve_active_and_proceed();
},
standee(track_id) {
+ update_active_node_args({
+ move_track: false,
+ });
let amount = 2;
if (track_id === data_1.LIBERTY || track_id === data_1.COLLECTIVIZATION) {
amount = 3;
@@ -1538,6 +1715,12 @@ states.spend_hero_points = {
]));
resolve_active_and_proceed();
},
+ turn_on_bonus() {
+ update_active_node_args({
+ turn_on_bonus: true,
+ });
+ next();
+ },
};
states.swap_card_tableau_hand = {
inactive: 'swap cards',
@@ -1609,11 +1792,18 @@ states.take_hero_points = {
? 'Choose a player to take a Hero Point from'
: `Choose a player to take ${v} Hero Points from`;
const active_faction = get_active_faction();
+ let target_exists = false;
for (const faction of role_ids) {
- if (faction !== active_faction) {
+ if (faction !== active_faction && game.hero_points[faction] > 0) {
gen_action(faction_player_map[faction]);
+ target_exists = true;
}
}
+ if (!target_exists) {
+ view.prompt =
+ 'Not possible to take Hero Points from another player. You must skip';
+ gen_action('skip');
+ }
},
spend_hp() {
resolve_spend_hp();
@@ -1627,6 +1817,9 @@ states.take_hero_points = {
Moderate() {
resolve_take_hero_points(data_1.MODERATES_ID);
},
+ skip() {
+ resolve_active_and_proceed();
+ },
};
states.use_organization_medallion = {
inactive: 'use Organization Medallion',
@@ -1776,12 +1969,12 @@ function setup_return_card_from_trash() {
resolve_active_and_proceed();
}
function add_glory(faction, amount, indent = false) {
+ let tokens_log = '';
for (let i = 0; i < amount; ++i) {
game.bag_of_glory.push(get_active_faction());
+ tokens_log += `<ft${faction}>`;
}
- let text = amount === 1
- ? `${faction_player_map[faction]} adds 1 token to the Bag of Glory`
- : `${faction_player_map[faction]} adds ${amount} tokens to the Bag of Glory`;
+ let text = `${faction_player_map[faction]} adds ${tokens_log} to the Bag of Glory`;
if (indent) {
logi(text);
}
@@ -1874,19 +2067,27 @@ function end_of_year() {
return;
}
}
+ else {
+ log_h1('End of year');
+ }
const glory_to_draw = [0, 1, 2, 5];
const glory_this_year = {
a: false,
c: false,
m: false,
};
+ const drawn_glory = [];
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);
}
+ log(`Tokens pulled from the Bag of Glory: ${drawn_glory
+ .map((faction_id) => `<ft${faction_id}>`)
+ .join('')}`);
if (game.year === 3) {
determine_winner();
return;
@@ -1899,6 +2100,14 @@ function end_of_year() {
game.top_of_events_deck = null;
next();
}
+function end_resolving_event_effects() {
+ const node = get_nodes_for_state('player_turn')[0];
+ node.a = {
+ ...(node.a || {}),
+ resolving_event: false,
+ };
+ resolve_active_and_proceed();
+}
function gain_hero_points_in_player_order(factions, value) {
for (const f of get_player_order()) {
if (factions.includes(f)) {
@@ -1911,11 +2120,16 @@ function gain_hero_points(faction_id, value, skip_abilities = false) {
return;
}
if (!skip_abilities &&
- ((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)))) {
+ faction_id === data_1.ANARCHISTS_ID &&
+ (game.active_abilities || []).includes(data_1.ANARCHIST_EXTRA_HERO_POINT)) {
value++;
+ game.active_abilities = (game.active_abilities || []).filter((ability) => ability !== data_1.ANARCHIST_EXTRA_HERO_POINT);
+ }
+ if (!skip_abilities &&
+ faction_id === data_1.COMMUNISTS_ID &&
+ (game.active_abilities || []).includes(data_1.COMMUNIST_EXTRA_HERO_POINT)) {
+ value++;
+ game.active_abilities = (game.active_abilities || []).filter((ability) => ability !== data_1.COMMUNIST_EXTRA_HERO_POINT);
}
const gain = Math.min(game.hero_points.pool, value);
game.hero_points.pool -= gain;
@@ -1942,13 +2156,14 @@ function play_card(faction, type) {
const card_id = game.selected_cards[faction][index];
const card = cards[card_id];
game.played_card = card_id;
- log_h3(`${game.active} plays ${card.title} for the ${type === 'play_for_event' ? 'Event' : 'Action Points'}`);
array_remove(game.hands[faction], game.hands[faction].indexOf(card_id));
array_remove(game.selected_cards[faction], index);
if (type === 'play_for_event') {
+ log_h3(`${game.active} plays ${card.title} for the Event`);
game.trash[faction].push(card_id);
}
else {
+ log_h3(`${game.active} plays ${card.title} to their Tableau`);
game.tableaus[faction].push(card_id);
}
return card;
@@ -1977,7 +2192,7 @@ function resolve_fascist_test() {
log('The Test is failed');
}
const effect = test_passed ? test.pass : test.fail;
- const node = resolve_effect(effect);
+ const node = resolve_effect(effect, 'fascist_test');
if (node !== null) {
insert_after_active_node(node);
}
@@ -2081,7 +2296,7 @@ function move_track(track_id, change) {
if (space_id !== 0) {
game.triggered_track_effects.push(get_blank_marker_id(track_id, space_id));
}
- const node = resolve_effect(trigger);
+ const node = resolve_effect(trigger, 'track_icon');
if (node !== null) {
insert_after_active_node(node);
}
@@ -2204,10 +2419,11 @@ const effect_type_state_map = {
take_hero_points: 'take_hero_points',
track: 'move_track',
};
-function resolve_effect(effect) {
+function resolve_effect(effect, source) {
const args = {
t: effect.target,
v: effect.value,
+ src: source,
};
const faction = get_faction_to_resolve_effect(effect);
if (effect.type === 'function') {
@@ -2216,6 +2432,7 @@ function resolve_effect(effect) {
if (effect.type === 'state') {
return create_leaf_node(effect.target, faction, {
v: effect.value,
+ src: source,
});
}
let state = effect_type_state_map[effect.type];
@@ -2233,9 +2450,7 @@ function resolve_effect(effect) {
{
condition: effect.type === 'hero_points' && effect.target === data_1.ALL_PLAYERS,
resolve: () => {
- return create_seq_node(get_player_order().map((faction) => create_leaf_node('hero_points', faction, {
- v: effect.value,
- })));
+ return create_seq_node(get_player_order().map((faction) => create_leaf_node('hero_points', faction, args)));
},
},
{
@@ -2279,17 +2494,13 @@ function resolve_effect(effect) {
{
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,
- })));
+ return create_seq_node(get_player_order(get_active_faction()).map((faction) => create_leaf_node('draw_card', faction, args)));
},
},
{
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,
- }));
+ const leaf_nodes = get_player_order(get_active_faction()).map((faction) => create_leaf_node('draw_card', faction, args));
array_remove(leaf_nodes, 0);
return create_seq_node(leaf_nodes);
},
@@ -2298,8 +2509,8 @@ function resolve_effect(effect) {
condition: effect.type === 'play_card',
resolve: () => {
return create_seq_node([
- create_leaf_node('choose_card', faction),
- create_leaf_node('player_turn', faction),
+ create_leaf_node('choose_card', faction, { src: source }),
+ create_leaf_node('player_turn', faction, { src: source }),
]);
},
},
@@ -2384,6 +2595,12 @@ function log_h3(msg) {
log_br();
log('.h3 ' + msg);
}
+function lowerCaseFirstLetter(val) {
+ return String(val).charAt(0).toLowerCase() + String(val).slice(1);
+}
+function add_prompt_prefix(prompt, prefix) {
+ return `${prefix}: ${lowerCaseFirstLetter(prompt)}`;
+}
function get_active_faction() {
return player_faction_map[game.active];
}
@@ -2458,6 +2675,15 @@ function get_player_order_in_game(first_player = game.initiative) {
}
return order;
}
+function get_source_name(source) {
+ const prefix_map = {
+ fascist_event: 'Fascist Event',
+ fascist_test: 'Fascist Test',
+ track_icon: 'Track Trigger',
+ momentum: 'Momentum',
+ };
+ return prefix_map[source];
+}
function get_factions_with_most_hero_poins() {
let most_hero_points = null;
let faction_ids = [];