summaryrefslogtreecommitdiff
path: root/rules.js
diff options
context:
space:
mode:
authorTor Andersson <tor@ccxvii.net>2025-03-02 12:03:00 +0100
committerTor Andersson <tor@ccxvii.net>2025-03-02 12:16:01 +0100
commita4c2b8458d1059c373c4a714bce0b5f68a3ce20f (patch)
tree352d0f51bea9ea86033745d9bd9579385dbaacf0 /rules.js
parent905cef05c773df8df8ee33d844dda449df9aeca1 (diff)
downloadland-and-freedom-a4c2b8458d1059c373c4a714bce0b5f68a3ce20f.tar.gz
Some rules.ts changes for new client.
Remove unused properties from view object. Use separate fascist_cards and trash view properties. Remove common selectable_cards property. Use game.fascist when resolving fascist event and test. - prevent saving undo states (no choices here) - color header brown for active player (not their own faction) Use abbreviated player order in view.player_order.
Diffstat (limited to 'rules.js')
-rw-r--r--rules.js80
1 files changed, 38 insertions, 42 deletions
diff --git a/rules.js b/rules.js
index f8eb5d9..46a9176 100644
--- a/rules.js
+++ b/rules.js
@@ -80,7 +80,7 @@ function gen_spend_hero_points() {
}
function action(state, player, action, arg) {
game = state;
- if (action !== 'undo' && game.state !== 'choose_card') {
+ if (action !== 'undo' && game.state !== 'choose_card' && !game.fascist) {
push_undo();
}
let S = states[game.state];
@@ -134,11 +134,13 @@ function setup_bag_of_glory() {
next();
}
function setup_choose_card() {
+ game.fascist = 0;
game.engine = [create_state_node('choose_card', 'all')];
game.engine.push(create_function_node('setup_player_turn'));
next();
}
function setup_final_bid() {
+ game.fascist = 0;
log_h1('Final Bid');
const player_order = get_player_order();
game.engine = player_order.map((faction_id) => create_state_node('choose_final_bid', faction_id));
@@ -148,6 +150,7 @@ function setup_final_bid() {
next();
}
function setup_player_turn() {
+ game.fascist = 0;
const next_faction = game.first_player === null
? get_player_order()[0]
: get_next_faction_in_player_order(get_active_faction());
@@ -344,38 +347,28 @@ function game_view(state, current) {
game = state;
const faction = current === OBSERVER ? null : player_faction_map[current];
view = {
- active: game.active,
- 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,
played_card: game.played_card,
- player_order: current === OBSERVER
- ? game.player_order
- : get_player_order_in_game(faction).map((id) => faction_player_map[id]),
- selectable_cards: game.selectable_cards,
+ player_order: current === OBSERVER ? get_player_order() : get_player_order_in_game(faction),
selected_cards: current === OBSERVER ? [] : game.selected_cards[faction],
tableaus: game.tableaus,
tracks: game.tracks,
triggered_track_effects: game.triggered_track_effects,
used_medallions: game.used_medallions,
year: game.year,
+ fascist: game.fascist,
};
if (game.state === 'game_over') {
view.prompt = game.victory;
@@ -404,7 +397,6 @@ function setup(seed, _scenario, _options) {
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: {
@@ -459,7 +451,6 @@ function setup(seed, _scenario, _options) {
},
played_card: null,
player_order: [data_1.MODERATE],
- selectable_cards: [],
selected_cards: {
a: [],
c: [],
@@ -484,6 +475,7 @@ function setup(seed, _scenario, _options) {
turn: 0,
year: 0,
glory_current_year: null,
+ fascist: 0,
};
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);
@@ -531,6 +523,7 @@ function start_turn() {
const card = cards[cardId];
log_h2('Fascist Event', 'fascist');
log(card.title);
+ game.fascist = 1;
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'));
@@ -1403,7 +1396,8 @@ states.peek_fascist_cards = {
prompt() {
gen_spend_hero_points();
view.prompt = 'Choose one card to return to the top of the deck';
- for (const c of game.selectable_cards) {
+ view.fascist_cards = game.fascist_cards;
+ for (const c of game.fascist_cards) {
gen_action_card(c);
}
},
@@ -1412,12 +1406,12 @@ states.peek_fascist_cards = {
},
card(c) {
game.top_of_events_deck = c;
- for (const ec of game.selectable_cards) {
+ for (const ec of game.fascist_cards) {
if (ec !== c) {
game.discard.f.push(ec);
}
}
- game.selectable_cards = [];
+ delete game.fascist_cards;
resolve_active_and_proceed();
},
};
@@ -1636,16 +1630,22 @@ states.remove_attack_from_fronts = {
},
};
states.return_card = {
- inactive: 'return a card to their hand',
+ inactive: "return a card to their hand",
prompt() {
+ const faction = get_active_faction();
gen_spend_hero_points();
- view.prompt = 'Choose a card to return to your hand';
- if (game.selectable_cards.length === 0) {
- view.prompt = 'No card in trash to return. You must skip';
- gen_action('skip');
+ view.prompt = "Choose a card to return to your hand";
+ view.trash = game.trash[faction];
+ let possible = false;
+ for (let c of game.trash[faction]) {
+ if (c !== game.played_card) {
+ gen_action_card(c);
+ possible = true;
+ }
}
- for (const c of game.selectable_cards) {
- gen_action_card(c);
+ if (!possible) {
+ view.prompt = "No card in trash to return. You must skip";
+ gen_action("skip");
}
},
spend_hp() {
@@ -1656,11 +1656,9 @@ states.return_card = {
array_remove(game.trash[faction], game.trash[faction].indexOf(c));
game.hands[faction].push(c);
logi(`${faction_player_map[faction]} returns a card to their hand`);
- game.selectable_cards = [];
resolve_active_and_proceed();
},
skip() {
- game.selectable_cards = [];
resolve_active_and_proceed();
},
};
@@ -2029,8 +2027,9 @@ function card45_event2() {
resolve_active_and_proceed();
}
function card46_event3() {
+ game.fascist_cards = [];
for (let i = 0; i < 3; ++i) {
- game.selectable_cards.push(draw_fascist_card());
+ game.fascist_cards.push(draw_fascist_card());
}
resolve_active_and_proceed();
}
@@ -2050,8 +2049,6 @@ function card54_event1() {
resolve_active_and_proceed();
}
function setup_return_card_from_trash() {
- const faction = get_active_faction();
- game.selectable_cards = game.trash[faction].filter((c) => c !== game.played_card);
resolve_active_and_proceed();
}
function add_glory(faction, amount, indent = false) {
@@ -2254,6 +2251,7 @@ function play_card(faction, type) {
return card;
}
function resolve_fascist_test() {
+ game.fascist = 1;
log_h2('Fascist Test', 'fascist');
const test = get_current_event().test;
const status = game.fronts[test.front].status;
@@ -2684,7 +2682,7 @@ function log_h1(msg) {
}
function log_h2(msg, player) {
log_br();
- log(`.h2${player ? `.${player}` : ''} ${msg}`);
+ log(`#${player[0].toLowerCase()} ${msg}`);
log_br();
}
function log_h3(msg) {
@@ -2810,18 +2808,16 @@ function list_deck(id) {
const deck = [];
const card_list = id === data_1.FASCIST_ID ? fascist_decks[game.year] : faction_cards[id];
card_list.forEach((card) => {
- if (game.discard[id].includes(card) ||
- game.selectable_cards.includes(card)) {
- return;
- }
- if (id === data_1.FASCIST_ID && game.current_events.includes(card)) {
- return;
+ if (id === data_1.FASCIST_ID) {
+ if (game.current_events.includes(card))
+ return;
+ if (game.discard[id].includes(card))
+ return;
}
- else if (id !== data_1.FASCIST_ID &&
- (game.hands[id].includes(card) ||
- game.discard[id].includes(card) ||
- game.tableaus[id].includes(card) ||
- game.trash[id].includes(card))) {
+ else if (game.hands[id].includes(card) ||
+ game.discard[id].includes(card) ||
+ game.tableaus[id].includes(card) ||
+ game.trash[id].includes(card)) {
return;
}
deck.push(card);