summaryrefslogtreecommitdiff
path: root/rules.ts
diff options
context:
space:
mode:
Diffstat (limited to 'rules.ts')
-rw-r--r--rules.ts106
1 files changed, 70 insertions, 36 deletions
diff --git a/rules.ts b/rules.ts
index 1469ece..be48715 100644
--- a/rules.ts
+++ b/rules.ts
@@ -21,6 +21,7 @@ import {
FascistId,
ClosestToDefeat,
ClosestToVictory,
+ EndOfYearDiscardArgs,
} from './types';
import data, {
@@ -167,6 +168,8 @@ function gen_spend_hero_points() {
}
}
+const multiactive_states = ['choose_card', 'end_of_year_discard'];
+
export function action(
state: Game,
player: Player,
@@ -175,7 +178,7 @@ export function action(
) {
game = state;
- if (action !== 'undo' && game.state !== 'choose_card') {
+ if (action !== 'undo' && !multiactive_states.includes(game.state)) {
push_undo();
}
@@ -298,20 +301,6 @@ function setup_player_turn(faction_id: FactionId) {
}
}
-// 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();
-
- if (
- game.hands[faction].length > get_hand_limit(faction) ||
- game.tableaus[faction].length > game.year
- ) {
- insert_after_active_node(create_state_node('end_of_year_discard', faction));
- }
-
- resolve_active_and_proceed();
-}
-
function end_of_player_turn() {
const { f: faction } = get_active_node_args();
const next_faction = get_next_faction_in_player_order(faction);
@@ -336,7 +325,6 @@ function start_of_player_turn() {
}
const engine_functions: Record<string, Function> = {
- check_end_of_year_discard,
checkpoint,
end_of_player_turn,
end_of_turn,
@@ -846,20 +834,23 @@ states.activate_icon = {
if (game.bonuses[TEAMWORK_BONUS] === OFF) {
gen_action_bonus(TEAMWORK_BONUS);
can_activate_icon = true;
- } else {
- can_activate_icon = false;
}
break;
+ case 'draw_card':
+ gen_action('draw_card');
+ can_activate_icon = true;
+ break;
default:
gen_action(i);
}
-
+
if (!player_can_resolve_icon(i)) {
view.actions[i] = 0;
}
- if (!can_activate_icon) {
- gen_action('skip');
- }
+ }
+
+ if (!can_activate_icon) {
+ gen_action('skip');
}
},
spend_hp() {
@@ -1538,10 +1529,14 @@ states.draw_glory = {
},
};
+// Multiactive end of year discard state
states.end_of_year_discard = {
inactive: 'discard cards from hand and tableau',
- prompt() {
- const faction_id = get_active_faction();
+ prompt(player: Player) {
+ const faction_id = player_faction_map[player];
+
+ const {d: discarded} = get_active_node_args<EndOfYearDiscardArgs>();
+
const hand = game.hands[faction_id];
const hand_limit = get_hand_limit(faction_id);
const needs_to_discard_from_hand = hand.length > hand_limit;
@@ -1556,30 +1551,57 @@ states.end_of_year_discard = {
if (needs_to_discard_from_hand && needs_to_discard_from_tableau) {
view.prompt = 'Discard a card from your hand or tableau';
- } else {
+ } else if (needs_to_discard_from_hand || needs_to_discard_from_tableau) {
view.prompt = `Discard a card from your ${
needs_to_discard_from_hand ? 'hand' : 'tableau'
}`;
+ } else {
+ view.prompt = 'Confirm discard';
+ view.actions.confirm = 1;
+ }
+ if (discarded[faction_id].h.length > 0 || discarded[faction_id].t.length > 0) {
+ view.actions.undo = 1;
}
},
- card(c: CardId) {
- const faction_id = get_active_faction();
+ card(c: CardId, player: Player) {
+ const faction_id = player_faction_map[player];
+
+ // Need to keep track of where cards are discarded from for undo
+ const {d: discarded} = get_active_node_args<EndOfYearDiscardArgs>();
+
if (game.hands[faction_id].includes(c)) {
game.hands[faction_id] = game.hands[faction_id].filter((id) => id !== c);
+ discarded[faction_id].h.push(c);
} else if (game.tableaus[faction_id].includes(c)) {
game.tableaus[faction_id] = game.tableaus[faction_id].filter(
(id) => id !== c
);
+ discarded[faction_id].t.push(c);
}
+
game.discard[faction_id].push(c);
if (
- game.hands[faction_id].length > get_hand_limit(faction_id) ||
- game.tableaus[faction_id].length > game.year
+ game.hands[faction_id].length <= get_hand_limit(faction_id) &&
+ game.tableaus[faction_id].length <= game.year
) {
- // More cards to discard so resolve same state again
- next();
+ log(`${player} discarded cards.`);
+ }
+ },
+ undo(_, player: Player) {
+ const faction_id = player_faction_map[player];
+ const last_discarded = game.discard[faction_id].pop();
+ const {d: discarded} = get_active_node_args<EndOfYearDiscardArgs>();
+ if (discarded[faction_id].h.includes(last_discarded)) {
+ game.hands[faction_id].push(last_discarded);
+ discarded[faction_id].h.pop()
} else {
- log(`${game.active} discarded cards.`);
+ game.tableaus[faction_id].push(last_discarded);
+ discarded[faction_id].t.pop()
+ }
+ },
+ confirm(_, player: Player) {
+ set_delete(game.active as Player[], player);
+ if (game.active.length === 0) {
resolve_active_and_proceed();
}
},
@@ -2780,11 +2802,23 @@ function end_of_year_cleanup() {
);
gain_hero_points_in_player_order(players_to_gain_hero_points, game.year);
+ game.engine = [];
// Setup card discarding
- game.engine = get_player_order().map((f) =>
- create_function_node('check_end_of_year_discard', { f })
- );
- game.engine.push(create_function_node('checkpoint'));
+ const factions_that_must_discard: FactionId[] = [];
+ role_ids.forEach((factionId) => {
+ if (
+ game.hands[factionId].length > get_hand_limit(factionId) ||
+ game.tableaus[factionId].length > game.year
+ ) {
+ factions_that_must_discard.push(factionId);
+ }
+ })
+ if (factions_that_must_discard.length > 0) {
+ game.engine.push(create_state_node('end_of_year_discard', factions_that_must_discard, {d: [{h:[], t: []}, {h:[], t: []}, {h:[], t: []}]}))
+
+ }
+
+ game.engine.push(create_function_node('checkpoint')); // Can be removed as preceding state is now multi active?
game.engine.push(create_function_node('start_year'));
// New deck is used for next year so clear top card