summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rules.js117
-rw-r--r--rules.ts190
-rw-r--r--types.d.ts4
3 files changed, 127 insertions, 184 deletions
diff --git a/rules.js b/rules.js
index dc31da9..ced9de7 100644
--- a/rules.js
+++ b/rules.js
@@ -92,13 +92,13 @@ function action(state, player, action, arg) {
throw new Error('Invalid action: ' + action);
return game;
}
-const leaf_node = 'l';
+const state_node = 'l';
const seq_node = 's';
const function_node = 'f';
const resolved = 1;
-function create_leaf_node(state, faction, args) {
+function create_state_node(state, faction, args) {
return {
- t: leaf_node,
+ t: state_node,
s: state,
p: faction,
a: args,
@@ -121,27 +121,27 @@ function create_seq_node(children) {
}
function checkpoint() {
if (game.undo.length > 0) {
- insert_after_active_node(create_leaf_node('confirm_turn', get_active_faction()));
+ insert_after_active_node(create_state_node('confirm_turn', get_active_faction()));
}
resolve_active_and_proceed();
}
function setup_bag_of_glory() {
log_h1('Bag of Glory');
game.engine = [
- create_leaf_node('add_glory', game.initiative),
+ create_state_node('add_glory', game.initiative),
create_function_node('end_of_turn'),
];
next();
}
function setup_choose_card() {
- game.engine = [create_leaf_node('choose_card', 'all')];
+ game.engine = [create_state_node('choose_card', 'all')];
game.engine.push(create_function_node('setup_player_turn'));
next();
}
function setup_final_bid() {
log_h1('Final Bid');
const player_order = get_player_order();
- game.engine = player_order.map((faction_id) => create_leaf_node('choose_final_bid', faction_id));
+ game.engine = player_order.map((faction_id) => create_state_node('choose_final_bid', faction_id));
game.engine.push(create_function_node('checkpoint'));
game.engine.push(create_function_node('resolve_final_bid'));
game.engine.push(create_function_node('setup_choose_card'));
@@ -156,7 +156,7 @@ function setup_player_turn() {
}
game.engine = [
create_function_node('start_of_player_turn', { f: next_faction }),
- create_leaf_node('player_turn', next_faction),
+ create_state_node('player_turn', next_faction),
create_function_node('end_of_player_turn', { f: next_faction }),
];
next();
@@ -165,7 +165,7 @@ function check_end_of_year_discard() {
const { f: faction } = get_active_node_args();
if (game.hands[faction].length > get_hand_limit(faction) ||
game.tableaus[faction].length > game.year) {
- insert_after_active_node(create_leaf_node('end_of_year_discard', faction));
+ insert_after_active_node(create_state_node('end_of_year_discard', faction));
}
resolve_active_and_proceed();
}
@@ -173,7 +173,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_state_node('change_active_player', game.initiative),
create_function_node('resolve_fascist_test'),
create_function_node('setup_bag_of_glory'),
];
@@ -227,7 +227,7 @@ const engine_functions = {
};
function get_active(engine) {
for (let i of engine) {
- if ((i.t === leaf_node || i.t === function_node) && i.r !== resolved) {
+ if ((i.t === state_node || i.t === function_node) && i.r !== resolved) {
return { parent: engine, node: i };
}
if (i.t === seq_node) {
@@ -246,7 +246,7 @@ function get_active_node(engine = game.engine) {
function get_nodes_for_state(state, engine = game.engine) {
let nodes = [];
for (let i of engine) {
- if (i.t === leaf_node && i.s === state) {
+ if (i.t === state_node && i.s === state) {
nodes.push(i);
}
if (i.t === seq_node) {
@@ -257,14 +257,14 @@ function get_nodes_for_state(state, engine = game.engine) {
}
function get_active_node_args() {
const node = get_active_node(game.engine);
- if (node.t === leaf_node || node.t === function_node) {
+ if (node.t === state_node || node.t === function_node) {
return node.a ?? {};
}
return null;
}
function update_active_node_args(args) {
const node = get_active_node(game.engine);
- if (node.t === leaf_node || node.t === function_node) {
+ if (node.t === state_node || node.t === function_node) {
node.a = {
...node.a,
...args,
@@ -320,7 +320,7 @@ function next(checkpoint = false) {
const current_active = game.active;
const next_active = get_next_active(node.p);
if (next_active !== current_active && game.undo.length > 0) {
- insert_before_active_node(create_leaf_node('confirm_turn', get_active_faction()));
+ insert_before_active_node(create_state_node('confirm_turn', get_active_faction()));
game.state = 'confirm_turn';
return;
}
@@ -383,7 +383,9 @@ function game_view(state, current) {
else if (current !== game.active &&
!game.active.includes(current)) {
let inactive = states[game.state].inactive || game.state;
- view.prompt = Array.isArray(game.active) ? `Waiting for other players to ${inactive}.` : `Waiting for ${game.active} to ${inactive}.`;
+ view.prompt = Array.isArray(game.active)
+ ? `Waiting for other players to ${inactive}.`
+ : `Waiting for ${game.active} to ${inactive}.`;
}
else {
view.actions = {};
@@ -561,7 +563,7 @@ states.activate_icon = {
resolve_spend_hp();
},
add_to_front() {
- insert_after_active_node(create_leaf_node('add_to_front', get_active_faction(), {
+ insert_after_active_node(create_state_node('add_to_front', get_active_faction(), {
t: data_1.ANY,
v: get_icon_count_in_tableau('add_to_front'),
}));
@@ -891,15 +893,10 @@ states.choose_area_ap = {
resolve_active_and_proceed();
},
standee(track_id) {
- insert_after_active_node({
- t: leaf_node,
- p: get_active_faction(),
- s: 'move_track_up_or_down',
- a: {
- track_id,
- strength: get_active_node()?.a.strength,
- },
- });
+ insert_after_active_node(create_state_node('move_track_up_or_down', get_active_faction(), {
+ track_id,
+ strength: get_active_node()?.a.strength,
+ }));
resolve_active_and_proceed();
},
};
@@ -1049,7 +1046,7 @@ function setup_momentum() {
};
}
else {
- insert_after_active_node(create_leaf_node('play_card', faction, {
+ insert_after_active_node(create_state_node('play_card', faction, {
src: 'momentum',
}));
}
@@ -1425,7 +1422,7 @@ states.peek_fascist_cards = {
},
};
function resolve_spend_hp() {
- insert_before_active_node(create_leaf_node('spend_hero_points', get_active_faction()));
+ insert_before_active_node(create_state_node('spend_hero_points', get_active_faction()));
log('Spends Hero Points');
next();
}
@@ -1534,7 +1531,7 @@ states.player_turn = {
update_active_node_args({
use_ap: false,
});
- insert_before_active_node(create_leaf_node('choose_area_ap', faction, {
+ insert_before_active_node(create_state_node('choose_area_ap', faction, {
strength,
}));
next();
@@ -1551,7 +1548,7 @@ states.player_turn = {
update_active_node_args({
use_morale_bonus: false,
});
- insert_before_active_node(create_leaf_node('activate_icon', get_active_faction()));
+ insert_before_active_node(create_state_node('activate_icon', get_active_faction()));
next();
},
};
@@ -1618,7 +1615,7 @@ states.remove_attack_from_fronts = {
resolve_active_and_proceed();
}
else if (card_id === 39 || card_id === 16) {
- insert_after_active_node(create_leaf_node('attack_front', get_active_faction(), {
+ insert_after_active_node(create_state_node('attack_front', get_active_faction(), {
t: data_1.ANY,
v: card_id === 39 ? -2 : -1 * removed_value,
n: card_id === 16 ? id : undefined,
@@ -1630,7 +1627,7 @@ states.remove_attack_from_fronts = {
const { f, v: card_id } = get_active_node_args();
const values = Object.values(f ?? {});
if (card_id === 39 && values.length > 0) {
- insert_after_active_node(create_leaf_node('attack_front', get_active_faction(), {
+ insert_after_active_node(create_state_node('attack_front', get_active_faction(), {
t: data_1.ANY,
v: -2,
}));
@@ -1737,11 +1734,11 @@ states.spend_hero_points = {
const faction = get_active_faction();
pay_hero_points(faction, 1);
insert_after_active_node(create_seq_node([
- create_leaf_node('add_to_front', faction, {
+ create_state_node('add_to_front', faction, {
t: data_1.ANY,
v: 1,
}),
- create_leaf_node('spend_hero_points', faction),
+ create_state_node('spend_hero_points', faction),
]));
resolve_active_and_proceed();
},
@@ -1777,8 +1774,8 @@ states.spend_hero_points = {
game.used_medallions = [data_1.ARCHIVES_MEDALLION_ID];
}
insert_after_active_node(create_seq_node([
- create_leaf_node('remove_blank_marker', faction),
- create_leaf_node('spend_hero_points', faction),
+ create_state_node('remove_blank_marker', faction),
+ create_state_node('spend_hero_points', faction),
]));
resolve_active_and_proceed();
},
@@ -1796,11 +1793,11 @@ states.spend_hero_points = {
const faction = get_active_faction();
pay_hero_points(faction, amount);
insert_after_active_node(create_seq_node([
- create_leaf_node('move_track_up_or_down', faction, {
+ create_state_node('move_track_up_or_down', faction, {
track_id,
strength: 1,
}),
- create_leaf_node('spend_hero_points', faction),
+ create_state_node('spend_hero_points', faction),
]));
resolve_active_and_proceed();
},
@@ -2121,7 +2118,7 @@ function determine_winner() {
win_game(faction_player_map[winners[0]], highest_glory);
}
else {
- insert_after_active_node(create_leaf_node('break_tie_winner', game.initiative, {
+ insert_after_active_node(create_state_node('break_tie_winner', game.initiative, {
winners,
glory: highest_glory,
}));
@@ -2168,7 +2165,7 @@ function end_of_year() {
const player_order = get_player_order();
const engine = [];
for (let i = 0; i < glory_to_draw[game.year]; ++i) {
- engine.push(create_leaf_node('draw_glory', player_order[i % 3]));
+ engine.push(create_state_node('draw_glory', player_order[i % 3]));
}
engine.push(create_function_node('end_of_year_cleanup'));
game.engine = engine;
@@ -2225,7 +2222,7 @@ function gain_hero_points(faction_id, value, skip_abilities = false) {
logi(`${get_player(faction_id)} +${gain} ${gain === 1 ? 'Hero Point' : 'Hero Points'}`);
}
function game_over(result, victory) {
- insert_after_active_node(create_leaf_node('game_over', 'None'));
+ insert_after_active_node(create_state_node('game_over', 'None'));
game.result = result;
game.victory = victory;
game.undo = [];
@@ -2315,7 +2312,7 @@ function resolve_final_bid() {
win_final_bid(winners[0]);
}
else {
- insert_after_active_node(create_leaf_node('break_tie_final_bid', game.initiative, { winners }));
+ insert_after_active_node(create_state_node('break_tie_final_bid', game.initiative, { winners }));
}
resolve_active_and_proceed();
}
@@ -2416,7 +2413,7 @@ function can_use_medallion(medallion_id, faction) {
}
function insert_use_organization_medallion_node(track_id, value) {
const faction = get_active_faction();
- insert_after_active_node(create_leaf_node('use_organization_medallion', faction, {
+ insert_after_active_node(create_state_node('use_organization_medallion', faction, {
t: track_id,
v: value,
}));
@@ -2454,7 +2451,7 @@ function update_front(front_id, change, faction_id = null) {
faction_id !== undefined &&
game.fronts[front_id].value < 10 &&
can_use_medallion(data_1.STRATEGY_MEDALLION_ID)) {
- insert_after_active_node(create_leaf_node('use_strategy_medallion', get_active_faction(), {
+ insert_after_active_node(create_state_node('use_strategy_medallion', get_active_faction(), {
f: front_id,
}));
}
@@ -2526,87 +2523,87 @@ function resolve_effect(effect, source) {
return create_function_node(effect.target);
}
if (effect.type === 'state') {
- return create_leaf_node(effect.target, faction, {
+ return create_state_node(effect.target, faction, {
v: effect.value,
src: source,
});
}
let state = effect_type_state_map[effect.type];
if (state !== undefined) {
- return create_leaf_node(state, faction, args);
+ return create_state_node(state, faction, args);
}
const strategies = [
{
condition: effect.type === 'hero_points' &&
effect.target === data_1.PLAYER_WITH_MOST_HERO_POINTS,
resolve: () => {
- return create_leaf_node('select_player_with_most_hero_points', faction, args);
+ return create_state_node('select_player_with_most_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('hero_points', faction, args)));
+ return create_seq_node(get_player_order().map((faction) => create_state_node('hero_points', faction, args)));
},
},
{
condition: effect.type === 'hero_points' && effect.target === data_1.SELF,
resolve: () => {
- return create_leaf_node('hero_points', faction, args);
+ return create_state_node('hero_points', faction, args);
},
},
{
condition: effect.type === 'hero_points' &&
role_ids.includes(effect.target),
resolve: () => {
- return create_leaf_node('hero_points', effect.target, args);
+ return create_state_node('hero_points', effect.target, args);
},
},
{
condition: effect.type === 'hero_points' && effect.target === data_1.INITIATIVE_PLAYER,
resolve: () => {
- return create_leaf_node('hero_points', game.initiative, args);
+ return create_state_node('hero_points', game.initiative, args);
},
},
{
condition: effect.type === 'draw_card' && effect.target === data_1.SELF,
resolve: () => {
- return create_leaf_node('draw_card', faction, args);
+ return create_state_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);
+ return create_state_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);
+ return create_state_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, args)));
+ return create_seq_node(get_player_order(get_active_faction()).map((faction) => create_state_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, args));
- array_remove(leaf_nodes, 0);
- return create_seq_node(leaf_nodes);
+ const state_nodes = get_player_order(get_active_faction()).map((faction) => create_state_node('draw_card', faction, args));
+ array_remove(state_nodes, 0);
+ return create_seq_node(state_nodes);
},
},
{
condition: effect.type === 'play_card',
resolve: () => {
return create_seq_node([
- create_leaf_node('play_card', faction, { src: source }),
- create_leaf_node('player_turn', faction, { src: source }),
+ create_state_node('play_card', faction, { src: source }),
+ create_state_node('player_turn', faction, { src: source }),
]);
},
},
diff --git a/rules.ts b/rules.ts
index 929b4ca..98b10b9 100644
--- a/rules.ts
+++ b/rules.ts
@@ -12,7 +12,7 @@ import {
FunctionNode,
Game,
Icon,
- LeafNode,
+ StateNode,
PlayCardArgs,
Player,
PlayerCard,
@@ -29,14 +29,6 @@ import data, {
ANARCHISTS_ID,
COMMUNISTS_ID,
MODERATES_ID,
- // LIBERTY,
- // COLLECTIVIZATION,
- // GOVERNMENT,
- // SOVIET_SUPPORT,
- // FOREIGN_AID,
- // MORALE_BONUS,
- // TEAMWORK_BONUS,
- // OFF,
LIBERTY,
CLOSEST_TO_DEFEAT,
CLOSEST_TO_VICTORY,
@@ -60,7 +52,6 @@ import data, {
TOWARDS_CENTER,
ARCHIVES_MEDALLION_ID,
INTELLIGENCE_MEDALLION_ID,
- // VOLUNTEERS_MEDALLION_ID,
ORGANIZATION_MEDALLION_ID,
STRATEGY_MEDALLION_ID,
PROPAGANDA_MEDALLION_ID,
@@ -75,24 +66,14 @@ import data, {
ARAGON,
FASCIST_ID,
NORTHERN,
- // StaticData,
- // PLAYER_WITH_MOST_HERO_POINTS,
} from './data';
-// interface State {
-// inactive: string;
-// prompt: () => void;
-// }
const OBSERVER = 'Observer';
const states = {} as States;
let game = {} as Game; // = null
var view = {} as View; // = null
-// export const ANARCHIST = 'Anarchist' as Player;
-// export const COMMUNIST = 'Communist' as Player;
-// export const MODERATE = 'Moderate' as Player;
-
const role_ids: FactionId[] = [ANARCHISTS_ID, COMMUNISTS_ID, MODERATES_ID];
const faction_player_map: Record<FactionId, Player> = {
@@ -185,18 +166,6 @@ function gen_spend_hero_points() {
}
}
-// function gen_action_space(space) {
-// gen_action('space', space);
-// }
-
-// function gen_action_piece(piece) {
-// gen_action('piece', piece);
-// }
-
-// function gen_action_card(card) {
-// gen_action('card', card);
-// }
-
export function action(
state: Game,
player: Player,
@@ -217,18 +186,18 @@ export function action(
// #region ENGINE
-const leaf_node = 'l';
+const state_node = 'l';
const seq_node = 's';
const function_node = 'f';
const resolved = 1;
-function create_leaf_node<T = any>(
+function create_state_node<T = any>(
state: string,
faction: FactionId | 'None' | 'all' | FactionId[],
args?: T
-): LeafNode {
+): StateNode {
return {
- t: leaf_node,
+ t: state_node,
s: state,
p: faction,
a: args,
@@ -256,7 +225,7 @@ function create_seq_node(children: EngineNode[]): SeqNode {
function checkpoint() {
if (game.undo.length > 0) {
insert_after_active_node(
- create_leaf_node('confirm_turn', get_active_faction())
+ create_state_node('confirm_turn', get_active_faction())
);
}
resolve_active_and_proceed();
@@ -265,22 +234,15 @@ function checkpoint() {
function setup_bag_of_glory() {
log_h1('Bag of Glory');
game.engine = [
- create_leaf_node('add_glory', game.initiative),
+ create_state_node('add_glory', game.initiative),
create_function_node('end_of_turn'),
];
next();
}
function setup_choose_card() {
- game.engine = [create_leaf_node('choose_card', 'all')];
-
- // const player_order = get_player_order();
- // 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 = [create_state_node('choose_card', 'all')];
+
game.engine.push(create_function_node('setup_player_turn'));
next();
}
@@ -289,7 +251,7 @@ function setup_final_bid() {
log_h1('Final Bid');
const player_order = get_player_order();
game.engine = player_order.map((faction_id) =>
- create_leaf_node('choose_final_bid', faction_id)
+ create_state_node('choose_final_bid', faction_id)
);
game.engine.push(create_function_node('checkpoint'));
game.engine.push(create_function_node('resolve_final_bid'));
@@ -309,14 +271,14 @@ function setup_player_turn() {
game.engine = [
create_function_node('start_of_player_turn', { f: next_faction }),
- create_leaf_node('player_turn', next_faction),
+ create_state_node('player_turn', next_faction),
create_function_node('end_of_player_turn', { f: next_faction }),
];
next();
}
-// Check if player needs to discard cards. If so inserts leaf node
+// Check if player needs to discard cards. If so inserts state node
function check_end_of_year_discard() {
const { f: faction } = get_active_node_args();
@@ -324,7 +286,7 @@ function check_end_of_year_discard() {
game.hands[faction].length > get_hand_limit(faction) ||
game.tableaus[faction].length > game.year
) {
- insert_after_active_node(create_leaf_node('end_of_year_discard', faction));
+ insert_after_active_node(create_state_node('end_of_year_discard', faction));
}
resolve_active_and_proceed();
@@ -334,7 +296,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_state_node('change_active_player', game.initiative),
create_function_node('resolve_fascist_test'),
create_function_node('setup_bag_of_glory'),
];
@@ -391,9 +353,9 @@ const engine_functions: Record<string, Function> = {
function get_active(
engine: EngineNode[]
-): { parent: EngineNode[]; node: FunctionNode | LeafNode } | null {
+): { parent: EngineNode[]; node: FunctionNode | StateNode } | null {
for (let i of engine) {
- if ((i.t === leaf_node || i.t === function_node) && i.r !== resolved) {
+ if ((i.t === state_node || i.t === function_node) && i.r !== resolved) {
return { parent: engine, node: i };
}
if (i.t === seq_node) {
@@ -408,7 +370,7 @@ function get_active(
function get_active_node(
engine: EngineNode[] = game.engine
-): FunctionNode | LeafNode | null {
+): FunctionNode | StateNode | null {
const a = get_active(engine);
return a === null ? null : a.node;
}
@@ -416,10 +378,10 @@ function get_active_node(
function get_nodes_for_state(
state: string,
engine: EngineNode[] = game.engine
-): LeafNode[] {
+): StateNode[] {
let nodes = [];
for (let i of engine) {
- if (i.t === leaf_node && i.s === state) {
+ if (i.t === state_node && i.s === state) {
nodes.push(i);
}
if (i.t === seq_node) {
@@ -431,7 +393,7 @@ function get_nodes_for_state(
function get_active_node_args<T = any>(): T {
const node = get_active_node(game.engine);
- if (node.t === leaf_node || node.t === function_node) {
+ if (node.t === state_node || node.t === function_node) {
return node.a ?? {};
}
return null;
@@ -439,7 +401,7 @@ function get_active_node_args<T = any>(): T {
function update_active_node_args<T = any>(args: Partial<T>) {
const node = get_active_node(game.engine);
- if (node.t === leaf_node || node.t === function_node) {
+ if (node.t === state_node || node.t === function_node) {
node.a = {
...node.a,
...args,
@@ -476,7 +438,7 @@ function insert_before_active_node(
insert_before_or_after_active_node(node, 'before', engine);
}
-function get_next_active(p: LeafNode['p']): Player | Player[] | 'None' {
+function get_next_active(p: StateNode['p']): Player | Player[] | 'None' {
if (Array.isArray(p)) {
return p.map((faction) => faction_player_map[faction]);
}
@@ -513,7 +475,7 @@ function next(checkpoint = false) {
if (next_active !== current_active && game.undo.length > 0) {
insert_before_active_node(
- create_leaf_node('confirm_turn', get_active_faction())
+ create_state_node('confirm_turn', get_active_faction())
);
game.state = 'confirm_turn';
return;
@@ -592,7 +554,9 @@ function game_view(state: Game, current: Player | 'Observer') {
!game.active.includes(current as Player)
) {
let inactive = states[game.state].inactive || game.state;
- view.prompt = Array.isArray(game.active) ? `Waiting for other players to ${inactive}.` : `Waiting for ${game.active} to ${inactive}.`;
+ view.prompt = Array.isArray(game.active)
+ ? `Waiting for other players to ${inactive}.`
+ : `Waiting for ${game.active} to ${inactive}.`;
} else {
view.actions = {};
if (game.undo && game.undo.length > 0) view.actions.undo = 1;
@@ -771,11 +735,6 @@ function start_turn() {
game.engine.push(create_function_node('setup_choose_card'));
}
next();
- // game.state = 'resolve_event';
- // game.active = faction_player_map[game.initiative];
- // game.state_data = {
- // current_effect: 0,
- // };
}
// region STATES
@@ -805,7 +764,7 @@ states.activate_icon = {
},
add_to_front() {
insert_after_active_node(
- create_leaf_node('add_to_front', get_active_faction(), {
+ create_state_node('add_to_front', get_active_faction(), {
t: ANY,
v: get_icon_count_in_tableau('add_to_front'),
})
@@ -1155,15 +1114,12 @@ states.choose_area_ap = {
resolve_active_and_proceed();
},
standee(track_id: number) {
- insert_after_active_node({
- t: leaf_node,
- p: get_active_faction(),
- s: 'move_track_up_or_down',
- a: {
+ insert_after_active_node(
+ create_state_node('move_track_up_or_down', get_active_faction(), {
track_id,
strength: get_active_node()?.a.strength,
- },
- });
+ })
+ );
resolve_active_and_proceed();
},
};
@@ -1328,7 +1284,7 @@ function setup_momentum() {
// right away or not. Depends on whether card for this turn has been fully resolved or not
// Get player turn node
- const node: LeafNode<PlayerTurnArgs> = get_nodes_for_state('player_turn')[0];
+ const node: StateNode<PlayerTurnArgs> = get_nodes_for_state('player_turn')[0];
const player_needs_to_play_card = game.selected_cards[faction].length > 0;
const { use_ap, use_morale_bonus, resolving_event } =
@@ -1348,7 +1304,7 @@ function setup_momentum() {
} else {
// Player can resolve choosing a new card
insert_after_active_node(
- create_leaf_node<PlayCardArgs>('play_card', faction, {
+ create_state_node<PlayCardArgs>('play_card', faction, {
src: 'momentum',
})
);
@@ -1785,7 +1741,7 @@ function resolve_spend_hp() {
// insert spend hero points node before current node
// so it will return to current node after resolving
insert_before_active_node(
- create_leaf_node('spend_hero_points', get_active_faction())
+ create_state_node('spend_hero_points', get_active_faction())
);
log('Spends Hero Points');
@@ -1911,7 +1867,7 @@ states.player_turn = {
use_ap: false,
});
insert_before_active_node(
- create_leaf_node('choose_area_ap', faction, {
+ create_state_node('choose_area_ap', faction, {
strength,
})
);
@@ -1935,7 +1891,7 @@ states.player_turn = {
use_morale_bonus: false,
});
insert_before_active_node(
- create_leaf_node('activate_icon', get_active_faction())
+ create_state_node('activate_icon', get_active_faction())
);
next();
},
@@ -2029,7 +1985,7 @@ states.remove_attack_from_fronts = {
resolve_active_and_proceed();
} else if (card_id === 39 || card_id === 16) {
insert_after_active_node(
- create_leaf_node('attack_front', get_active_faction(), {
+ create_state_node('attack_front', get_active_faction(), {
t: ANY,
v: card_id === 39 ? -2 : -1 * removed_value,
n: card_id === 16 ? id : undefined,
@@ -2043,7 +1999,7 @@ states.remove_attack_from_fronts = {
const values: number[] = Object.values(f ?? {});
if (card_id === 39 && values.length > 0) {
insert_after_active_node(
- create_leaf_node('attack_front', get_active_faction(), {
+ create_state_node('attack_front', get_active_faction(), {
t: ANY,
v: -2,
})
@@ -2161,11 +2117,11 @@ states.spend_hero_points = {
pay_hero_points(faction, 1);
insert_after_active_node(
create_seq_node([
- create_leaf_node('add_to_front', faction, {
+ create_state_node('add_to_front', faction, {
t: ANY,
v: 1,
}),
- create_leaf_node('spend_hero_points', faction),
+ create_state_node('spend_hero_points', faction),
])
);
resolve_active_and_proceed();
@@ -2202,8 +2158,8 @@ states.spend_hero_points = {
}
insert_after_active_node(
create_seq_node([
- create_leaf_node('remove_blank_marker', faction),
- create_leaf_node('spend_hero_points', faction),
+ create_state_node('remove_blank_marker', faction),
+ create_state_node('spend_hero_points', faction),
])
);
resolve_active_and_proceed();
@@ -2222,11 +2178,11 @@ states.spend_hero_points = {
pay_hero_points(faction, amount);
insert_after_active_node(
create_seq_node([
- create_leaf_node('move_track_up_or_down', faction, {
+ create_state_node('move_track_up_or_down', faction, {
track_id,
strength: 1,
}),
- create_leaf_node('spend_hero_points', faction),
+ create_state_node('spend_hero_points', faction),
])
);
resolve_active_and_proceed();
@@ -2637,7 +2593,7 @@ function determine_winner() {
win_game(faction_player_map[winners[0]], highest_glory);
} else {
insert_after_active_node(
- create_leaf_node('break_tie_winner', game.initiative, {
+ create_state_node('break_tie_winner', game.initiative, {
winners,
glory: highest_glory,
})
@@ -2689,7 +2645,7 @@ function end_of_year() {
const engine = [];
for (let i = 0; i < glory_to_draw[game.year]; ++i) {
- engine.push(create_leaf_node('draw_glory', player_order[i % 3]));
+ engine.push(create_state_node('draw_glory', player_order[i % 3]));
}
engine.push(create_function_node('end_of_year_cleanup'));
@@ -2726,7 +2682,7 @@ function end_of_year_cleanup() {
function end_resolving_event_effects() {
// Get player turn node
- const node: LeafNode<PlayerTurnArgs> = get_nodes_for_state('player_turn')[0];
+ const node: StateNode<PlayerTurnArgs> = get_nodes_for_state('player_turn')[0];
// Update args
node.a = {
@@ -2784,9 +2740,7 @@ function gain_hero_points(
}
function game_over(result: Player | 'None', victory: string) {
- insert_after_active_node(create_leaf_node('game_over', 'None'));
- // game.state = 'game_over';
- // game.active = 'None';
+ insert_after_active_node(create_state_node('game_over', 'None'));
game.result = result;
game.victory = victory;
game.undo = [];
@@ -2896,7 +2850,7 @@ function resolve_final_bid() {
win_final_bid(winners[0]);
} else {
insert_after_active_node(
- create_leaf_node('break_tie_final_bid', game.initiative, { winners })
+ create_state_node('break_tie_final_bid', game.initiative, { winners })
);
}
@@ -3025,7 +2979,7 @@ function insert_use_organization_medallion_node(
const faction = get_active_faction();
insert_after_active_node(
- create_leaf_node('use_organization_medallion', faction, {
+ create_state_node('use_organization_medallion', faction, {
t: track_id,
v: value,
})
@@ -3085,7 +3039,7 @@ function update_front(
can_use_medallion(STRATEGY_MEDALLION_ID)
) {
insert_after_active_node(
- create_leaf_node('use_strategy_medallion', get_active_faction(), {
+ create_state_node('use_strategy_medallion', get_active_faction(), {
f: front_id,
})
);
@@ -3170,7 +3124,7 @@ function resolve_effect(effect: Effect, source?: EffectSource): EngineNode {
return create_function_node(effect.target as string);
}
if (effect.type === 'state') {
- return create_leaf_node(effect.target as string, faction, {
+ return create_state_node(effect.target as string, faction, {
v: effect.value,
src: source,
});
@@ -3178,7 +3132,7 @@ function resolve_effect(effect: Effect, source?: EffectSource): EngineNode {
// Default cases where effect type is mapped to a state
let state = effect_type_state_map[effect.type];
if (state !== undefined) {
- return create_leaf_node(state, faction, args);
+ return create_state_node(state, faction, args);
}
// Specific mapping based on target
@@ -3188,7 +3142,7 @@ function resolve_effect(effect: Effect, source?: EffectSource): EngineNode {
effect.type === 'hero_points' &&
effect.target === PLAYER_WITH_MOST_HERO_POINTS,
resolve: () => {
- return create_leaf_node(
+ return create_state_node(
'select_player_with_most_hero_points',
faction,
args
@@ -3200,7 +3154,7 @@ function resolve_effect(effect: Effect, source?: EffectSource): EngineNode {
resolve: () => {
return create_seq_node(
get_player_order().map((faction) =>
- create_leaf_node('hero_points', faction, args)
+ create_state_node('hero_points', faction, args)
)
);
},
@@ -3208,7 +3162,7 @@ function resolve_effect(effect: Effect, source?: EffectSource): EngineNode {
{
condition: effect.type === 'hero_points' && effect.target === SELF,
resolve: () => {
- return create_leaf_node('hero_points', faction, args);
+ return create_state_node('hero_points', faction, args);
},
},
{
@@ -3216,7 +3170,7 @@ function resolve_effect(effect: Effect, source?: EffectSource): EngineNode {
effect.type === 'hero_points' &&
role_ids.includes(effect.target as FactionId),
resolve: () => {
- return create_leaf_node(
+ return create_state_node(
'hero_points',
effect.target as FactionId,
args
@@ -3227,20 +3181,20 @@ function resolve_effect(effect: Effect, source?: EffectSource): EngineNode {
condition:
effect.type === 'hero_points' && effect.target === INITIATIVE_PLAYER,
resolve: () => {
- return create_leaf_node('hero_points', game.initiative, args);
+ return create_state_node('hero_points', game.initiative, args);
},
},
{
condition: effect.type === 'draw_card' && effect.target === SELF,
resolve: () => {
- return create_leaf_node('draw_card', faction, args);
+ return create_state_node('draw_card', faction, args);
},
},
{
condition:
effect.type === 'draw_card' && effect.target === INITIATIVE_PLAYER,
resolve: () => {
- return create_leaf_node('draw_card', game.initiative, args);
+ return create_state_node('draw_card', game.initiative, args);
},
},
{
@@ -3248,7 +3202,7 @@ function resolve_effect(effect: Effect, source?: EffectSource): EngineNode {
effect.type === 'draw_card' &&
role_ids.includes(effect.target as FactionId),
resolve: () => {
- return create_leaf_node('draw_card', effect.target as FactionId, args);
+ return create_state_node('draw_card', effect.target as FactionId, args);
},
},
{
@@ -3256,7 +3210,7 @@ function resolve_effect(effect: Effect, source?: EffectSource): EngineNode {
resolve: () => {
return create_seq_node(
get_player_order(get_active_faction()).map((faction) =>
- create_leaf_node('draw_card', faction, args)
+ create_state_node('draw_card', faction, args)
)
);
},
@@ -3264,19 +3218,19 @@ function resolve_effect(effect: Effect, source?: EffectSource): EngineNode {
{
condition: effect.type === 'draw_card' && effect.target === OTHER_PLAYERS,
resolve: () => {
- const leaf_nodes = get_player_order(get_active_faction()).map(
- (faction) => create_leaf_node('draw_card', faction, args)
+ const state_nodes = get_player_order(get_active_faction()).map(
+ (faction) => create_state_node('draw_card', faction, args)
);
- array_remove(leaf_nodes, 0); // Remove current player
- return create_seq_node(leaf_nodes);
+ array_remove(state_nodes, 0); // Remove current player
+ return create_seq_node(state_nodes);
},
},
{
condition: effect.type === 'play_card',
resolve: () => {
return create_seq_node([
- create_leaf_node('play_card', faction, { src: source }),
- create_leaf_node('player_turn', faction, { src: source }),
+ create_state_node('play_card', faction, { src: source }),
+ create_state_node('player_turn', faction, { src: source }),
]);
},
},
@@ -3305,14 +3259,6 @@ function win_game(player: Player, glory: number) {
// #endregion
// #region CARDS
-// function draw_faction_card(faction: Player): CardId {
-// return draw_faction_cards(faction, 1)[0];
-// }
-
-// function draw_faction_cards(faction: Player, count: number = 1): CardId[] {
-// const drawnCards = [];
-
-// }
function draw_card(deck: CardId[]): CardId {
clear_undo();
diff --git a/types.d.ts b/types.d.ts
index cab4b5d..4594775 100644
--- a/types.d.ts
+++ b/types.d.ts
@@ -114,7 +114,7 @@ export type States = {
[key: string]: any;
};
-export type EngineNode = FunctionNode | LeafNode | SeqNode;
+export type EngineNode = FunctionNode | StateNode | SeqNode;
export interface FunctionNode {
t: 'f';
@@ -128,7 +128,7 @@ export interface SeqNode {
c: EngineNode[];
}
-export interface LeafNode<T = any> {
+export interface StateNode<T = any> {
t: 'l';
s: string; // State
p: FactionId | 'None' | 'all' | FactionId[]; // Player