diff options
author | Frans Bongers <fransbongers@franss-mbp.home> | 2024-12-01 15:09:24 +0100 |
---|---|---|
committer | Frans Bongers <fransbongers@franss-mbp.home> | 2024-12-01 15:09:24 +0100 |
commit | 74e1497d50a6ff81c74c593f2d0f7018d2995fd8 (patch) | |
tree | 9dd74df38232b1ab5f76b84f362c98abc6eaa7d1 | |
parent | f05a9531508822f5dfb51105334444b53fe11b3e (diff) | |
download | land-and-freedom-74e1497d50a6ff81c74c593f2d0f7018d2995fd8.tar.gz |
add stack data for triggers on tracks
-rw-r--r-- | data.js | 280 | ||||
-rw-r--r-- | data.ts | 294 | ||||
-rw-r--r-- | play.js | 2 | ||||
-rw-r--r-- | play.ts | 2 | ||||
-rw-r--r-- | rules.js | 177 | ||||
-rw-r--r-- | rules.ts | 193 | ||||
-rw-r--r-- | types.d.ts | 1 |
7 files changed, 780 insertions, 169 deletions
@@ -21,6 +21,15 @@ const ON = 1; exports.ON = ON; const PLAYER_WITH_MOST_HERO_POINTS = 0; exports.PLAYER_WITH_MOST_HERO_POINTS = PLAYER_WITH_MOST_HERO_POINTS; +const ARAGON = 'a'; +const MADRID = 'm'; +const NORTHERN = 'n'; +const SOUTHERN = 's'; +const CLOSEST_TO_DEFEAT = 'd'; +const CLOSEST_TO_VICTORY = 'v'; +const TOWARDS_CENTER = 10; +const AWAY_FROM_CENTER = 11; +const ANY = 'any'; const data = { cards: [ {}, @@ -352,12 +361,12 @@ const data = { id: 55, effects: [ { - target: 's', + target: SOUTHERN, type: 'attack', value: 4, }, { - target: 'a', + target: ARAGON, type: 'attack', value: 1, }, @@ -375,12 +384,12 @@ const data = { id: 56, effects: [ { - target: 's', + target: SOUTHERN, type: 'attack', value: 3, }, { - target: 'v', + target: CLOSEST_TO_VICTORY, type: 'attack', value: 2, }, @@ -398,9 +407,9 @@ const data = { id: 57, effects: [ { - target: 'm', + target: MADRID, type: 'attack', - value: 5, + value: -5, }, { target: FOREIGN_AID, @@ -423,12 +432,12 @@ const data = { { target: 'n', type: 'attack', - value: 5, + value: -5, }, { target: 'v', type: 'attack', - value: 1, + value: -1, }, { target: COLLECTIVIZATION, @@ -444,14 +453,14 @@ const data = { id: 59, effects: [ { - target: 'm', + target: MADRID, type: 'attack', - value: 4, + value: -4, }, { - target: 'v', + target: CLOSEST_TO_VICTORY, type: 'attack', - value: 2, + value: -2, }, { target: LIBERTY, @@ -467,14 +476,14 @@ const data = { id: 60, effects: [ { - target: 'n', + target: NORTHERN, type: 'attack', - value: 3, + value: -3, }, { - target: 'v', + target: CLOSEST_TO_VICTORY, type: 'attack', - value: 3, + value: -3, }, { target: LIBERTY, @@ -490,14 +499,14 @@ const data = { id: 61, effects: [ { - target: 'a', + target: ARAGON, type: 'attack', - value: 4, + value: -4, }, { - target: 'v', + target: CLOSEST_TO_VICTORY, type: 'attack', - value: 2, + value: -2, }, { target: PLAYER_WITH_MOST_HERO_POINTS, @@ -513,9 +522,9 @@ const data = { id: 62, effects: [ { - target: 's', + target: SOUTHERN, type: 'attack', - value: 5, + value: -5, }, { target: MORALE_BONUS, @@ -535,25 +544,25 @@ const data = { ], fronts: [ { - id: 'n', + id: NORTHERN, name: 'Northern', left: 89, top: 96, }, { - id: 'a', + id: ARAGON, name: 'Aragon', left: 340, top: 182, }, { - id: 'm', + id: MADRID, name: 'Madrid', left: 115, top: 262, }, { - id: 's', + id: SOUTHERN, name: 'Southern', left: 205, top: 426, @@ -562,40 +571,239 @@ const data = { medaillons: [ { id: 0, - name: 'Subterfuge' + name: 'Subterfuge', }, { id: 1, - name: 'Valor' + name: 'Valor', }, { id: 2, - name: 'Momentum' + name: 'Momentum', }, { id: 3, - name: 'Strategy' + name: 'Strategy', }, { id: 4, - name: 'Propaganda' + name: 'Propaganda', }, { id: 5, - name: 'Intelligence' + name: 'Intelligence', }, { id: 6, - name: 'Volunteers' + name: 'Volunteers', }, { id: 7, - name: 'Archives' + name: 'Archives', }, { id: 8, - name: 'Organization' + name: 'Organization', + }, + ], + tracks: [ + { + id: LIBERTY, + name: 'Liberty', + triggers: [ + { + type: 'bonus', + target: MORALE_BONUS, + value: OFF, + }, + { + type: 'attack', + target: MADRID, + value: -1, + }, + null, + { + type: 'track', + target: SOVIET_SUPPORT, + value: 1, + }, + null, + null, + null, + { + type: 'track', + target: GOVERNMENT, + value: TOWARDS_CENTER, + }, + { + type: 'front', + target: ANY, + value: 1, + }, + null, + { + type: 'medaillon', + target: ANY, + value: 1, + }, + ], + }, + { + id: COLLECTIVIZATION, + name: 'Collectivization', + triggers: [ + { + type: 'bonus', + target: MORALE_BONUS, + value: OFF, + }, + { + type: 'attack', + target: ARAGON, + value: -1, + }, + null, + { + type: 'track', + target: FOREIGN_AID, + value: 1, + }, + null, + null, + null, + { + type: 'front', + target: ANY, + value: 1, + }, + { + type: 'track', + target: LIBERTY, + value: 1, + }, + null, + { + type: 'medaillon', + target: ANY, + value: 1, + }, + ], + }, + { + id: GOVERNMENT, + name: 'Government', + triggers: [ + null, + { + type: 'medaillon', + target: ANY, + value: 1, + }, + null, + null, + { + type: 'track', + target: SOVIET_SUPPORT, + value: 1, + }, + null, + null, + { + type: 'track', + target: FOREIGN_AID, + value: 1, + }, + null, + null, + { + type: 'medaillon', + target: ANY, + value: 1, + }, + ], + }, + { + id: SOVIET_SUPPORT, + name: 'Soviet Support', + triggers: [ + { + type: 'bonus', + target: MORALE_BONUS, + value: OFF, + }, + { + type: 'attack', + target: SOUTHERN, + value: -1, + }, + null, + null, + null, + { + type: 'track', + target: LIBERTY, + value: -1, + }, + null, + { + type: 'front', + target: ANY, + value: 1, + }, + { + type: 'track', + target: GOVERNMENT, + value: -1, + }, + null, + { + type: 'medaillon', + target: ANY, + value: 1, + }, + ], + }, + { + id: FOREIGN_AID, + name: 'Foreign Aid', + triggers: [ + { + type: 'bonus', + target: MORALE_BONUS, + value: OFF, + }, + { + type: 'attack', + target: NORTHERN, + value: -1, + }, + null, + null, + null, + { + type: 'track', + target: LIBERTY, + value: -1, + }, + null, + { + type: 'front', + target: ANY, + value: 1, + }, + { + type: 'track', + target: GOVERNMENT, + value: 1, + }, + null, + { + type: 'medaillon', + target: ANY, + value: 1, + }, + ], }, - ] + ], }; exports.default = data; @@ -33,7 +33,16 @@ export interface StaticData { medaillons: Array<{ id: number; name: string; - }> + }>; + tracks: Array<{ + id: number; + name: string; + triggers: Array<null | { + type: 'attack' | 'track' | 'bonus' | 'front' | 'medaillon'; + target: string | number; + value: number; + }>; + }>; } const LIBERTY = 0; @@ -50,6 +59,18 @@ const ON = 1; const PLAYER_WITH_MOST_HERO_POINTS = 0; +const ARAGON = 'a'; +const MADRID = 'm'; +const NORTHERN = 'n'; +const SOUTHERN = 's'; +const CLOSEST_TO_DEFEAT = 'd'; +const CLOSEST_TO_VICTORY = 'v'; + +const TOWARDS_CENTER = 10; +const AWAY_FROM_CENTER = 11; + +const ANY = 'any'; + export { LIBERTY, COLLECTIVIZATION, @@ -394,12 +415,12 @@ const data: StaticData = { id: 55, effects: [ { - target: 's', + target: SOUTHERN, type: 'attack', value: 4, }, { - target: 'a', + target: ARAGON, type: 'attack', value: 1, }, @@ -417,12 +438,12 @@ const data: StaticData = { id: 56, effects: [ { - target: 's', + target: SOUTHERN, type: 'attack', value: 3, }, { - target: 'v', + target: CLOSEST_TO_VICTORY, type: 'attack', value: 2, }, @@ -440,9 +461,9 @@ const data: StaticData = { id: 57, effects: [ { - target: 'm', + target: MADRID, type: 'attack', - value: 5, + value: -5, }, { target: FOREIGN_AID, @@ -465,12 +486,12 @@ const data: StaticData = { { target: 'n', type: 'attack', - value: 5, + value: -5, }, { target: 'v', type: 'attack', - value: 1, + value: -1, }, { target: COLLECTIVIZATION, @@ -486,14 +507,14 @@ const data: StaticData = { id: 59, effects: [ { - target: 'm', + target: MADRID, type: 'attack', - value: 4, + value: -4, }, { - target: 'v', + target: CLOSEST_TO_VICTORY, type: 'attack', - value: 2, + value: -2, }, { target: LIBERTY, @@ -509,14 +530,14 @@ const data: StaticData = { id: 60, effects: [ { - target: 'n', + target: NORTHERN, type: 'attack', - value: 3, + value: -3, }, { - target: 'v', + target: CLOSEST_TO_VICTORY, type: 'attack', - value: 3, + value: -3, }, { target: LIBERTY, @@ -532,14 +553,14 @@ const data: StaticData = { id: 61, effects: [ { - target: 'a', + target: ARAGON, type: 'attack', - value: 4, + value: -4, }, { - target: 'v', + target: CLOSEST_TO_VICTORY, type: 'attack', - value: 2, + value: -2, }, { target: PLAYER_WITH_MOST_HERO_POINTS, @@ -555,9 +576,9 @@ const data: StaticData = { id: 62, effects: [ { - target: 's', + target: SOUTHERN, type: 'attack', - value: 5, + value: -5, }, { target: MORALE_BONUS, @@ -577,25 +598,25 @@ const data: StaticData = { ], fronts: [ { - id: 'n', + id: NORTHERN, name: 'Northern', left: 89, top: 96, }, { - id: 'a', + id: ARAGON, name: 'Aragon', left: 340, top: 182, }, { - id: 'm', + id: MADRID, name: 'Madrid', left: 115, top: 262, }, { - id: 's', + id: SOUTHERN, name: 'Southern', left: 205, top: 426, @@ -604,40 +625,239 @@ const data: StaticData = { medaillons: [ { id: 0, - name: 'Subterfuge' + name: 'Subterfuge', }, { id: 1, - name: 'Valor' + name: 'Valor', }, { id: 2, - name: 'Momentum' + name: 'Momentum', }, { id: 3, - name: 'Strategy' + name: 'Strategy', }, { id: 4, - name: 'Propaganda' + name: 'Propaganda', }, { id: 5, - name: 'Intelligence' + name: 'Intelligence', }, { id: 6, - name: 'Volunteers' + name: 'Volunteers', }, { id: 7, - name: 'Archives' + name: 'Archives', }, { id: 8, - name: 'Organization' + name: 'Organization', + }, + ], + tracks: [ + { + id: LIBERTY, + name: 'Liberty', + triggers: [ + { + type: 'bonus', + target: MORALE_BONUS, + value: OFF, + }, + { + type: 'attack', + target: MADRID, + value: -1, + }, + null, + { + type: 'track', + target: SOVIET_SUPPORT, + value: 1, + }, + null, + null, + null, + { + type: 'track', + target: GOVERNMENT, + value: TOWARDS_CENTER, + }, + { + type: 'front', + target: ANY, + value: 1, + }, + null, + { + type: 'medaillon', + target: ANY, + value: 1, + }, + ], }, - ] + { + id: COLLECTIVIZATION, + name: 'Collectivization', + triggers: [ + { + type: 'bonus', + target: MORALE_BONUS, + value: OFF, + }, + { + type: 'attack', + target: ARAGON, + value: -1, + }, + null, + { + type: 'track', + target: FOREIGN_AID, + value: 1, + }, + null, + null, + null, + { + type: 'front', + target: ANY, + value: 1, + }, + { + type: 'track', + target: LIBERTY, + value: 1, + }, + null, + { + type: 'medaillon', + target: ANY, + value: 1, + }, + ], + }, + { + id: GOVERNMENT, + name: 'Government', + triggers: [ + null, + { + type: 'medaillon', + target: ANY, + value: 1, + }, + null, + null, + { + type: 'track', + target: SOVIET_SUPPORT, + value: 1, + }, + null, + null, + { + type: 'track', + target: FOREIGN_AID, + value: 1, + }, + null, + null, + { + type: 'medaillon', + target: ANY, + value: 1, + }, + ], + }, + { + id: SOVIET_SUPPORT, + name: 'Soviet Support', + triggers: [ + { + type: 'bonus', + target: MORALE_BONUS, + value: OFF, + }, + { + type: 'attack', + target: SOUTHERN, + value: -1, + }, + null, + null, + null, + { + type: 'track', + target: LIBERTY, + value: -1, + }, + null, + { + type: 'front', + target: ANY, + value: 1, + }, + { + type: 'track', + target: GOVERNMENT, + value: -1, + }, + null, + { + type: 'medaillon', + target: ANY, + value: 1, + }, + ], + }, + { + id: FOREIGN_AID, + name: 'Foreign Aid', + triggers: [ + { + type: 'bonus', + target: MORALE_BONUS, + value: OFF, + }, + { + type: 'attack', + target: NORTHERN, + value: -1, + }, + null, + null, + null, + { + type: 'track', + target: LIBERTY, + value: -1, + }, + null, + { + type: 'front', + target: ANY, + value: 1, + }, + { + type: 'track', + target: GOVERNMENT, + value: 1, + }, + null, + { + type: 'medaillon', + target: ANY, + value: 1, + }, + ], + }, + ], }; export default data; @@ -226,6 +226,8 @@ function on_update() { action_button('play_for_event', 'Play card for Event'); action_button('spend_hp', 'Spend Hero Points'); action_button('add_glory', 'Add Glory'); + action_button('up', 'Up'); + action_button('down', 'Down'); action_button('next', 'Next'); action_button('done', 'Done'); action_button('undo', 'Undo'); @@ -305,6 +305,8 @@ function on_update() { action_button('play_for_event', 'Play card for Event'); action_button('spend_hp', 'Spend Hero Points'); action_button('add_glory', 'Add Glory'); + action_button('up', 'Up'); + action_button('down', 'Down'); action_button('next', 'Next'); action_button('done', 'Done'); action_button('undo', 'Undo'); @@ -33,6 +33,13 @@ const front_names = { d: 'the Front closest to Defeat', v: 'the Front closest to Victory', }; +const tracks = [ + data_1.LIBERTY, + data_1.COLLECTIVIZATION, + data_1.GOVERNMENT, + data_1.SOVIET_SUPPORT, + data_1.FOREIGN_AID, +]; const track_names = { [data_1.LIBERTY]: 'Liberty', [data_1.COLLECTIVIZATION]: 'Collectivization', @@ -66,6 +73,9 @@ function gen_action(action, argument) { function gen_action_card(card_id) { gen_action('card', card_id); } +function gen_action_standee(track_id) { + gen_action('standee', track_id); +} function action(state, player, action, arg) { console.log('action', state, player, action, arg); game = state; @@ -156,7 +166,7 @@ function get_active(engine) { } return null; } -function get_active_node(engine) { +function get_active_node(engine = game.engine) { const a = get_active(engine); return a === null ? null : a.node; } @@ -258,6 +268,12 @@ function setup(seed, _scenario, _options) { blank_markers: [[], [], [], [], []], bonuses: [data_1.ON, data_1.ON], current_events: [], + discard: { + [ANARCHISTS_ID]: [], + [COMMUNISTS_ID]: [], + [MODERATES_ID]: [], + f: [], + }, engine: [], fronts: { a: -2, @@ -359,58 +375,46 @@ states.add_glory = { resolve_active_and_proceed(); }, }; -states.resolve_event = { - inactive: 'resolve Fascist Event', +states.choose_area_ap = { + inactive: 'choose area to use Action Points', prompt() { - const card = get_current_event(); - const node = get_active_node(game.engine); - const effect = card.effects[node.a]; - view.prompt = get_event_prompt(effect); - if (effect.type === 'attack' && - (effect.target === 'd' || effect.target === 'v')) { - const fronts = get_fronts_closest_to(effect.target); - fronts.forEach((id) => gen_action('front', id)); - } - else if (effect.type === 'attack') { - gen_action('front', effect.target); - } - else if (effect.type === 'track') { - gen_action('standee', effect.target); - } - else if (effect.type === 'hero_points' && - effect.target === data_1.PLAYER_WITH_MOST_HERO_POINTS) { - const factions = get_factions_with_most_hero_poins(); - for (let faction_id of factions) { - gen_action(get_player(faction_id)); - } + view.prompt = 'Choose area of the board to affect'; + for (let track_id of tracks) { + gen_action_standee(track_id); } }, - front(f) { - const card = get_current_event(); - const value = card.effects[get_active_node_args()].value; - game.fronts[f] -= value; - log_h3(`${value} attacks added to ${front_names[f]}`); + standee(track_id) { + console.log('standee', track_id); + insert_after_active_node({ + t: leaf_node, + p: get_active_faction_id(), + s: 'move_track_up_or_down', + a: { + track_id, + strength: get_active_node()?.a.strength, + }, + }); resolve_active_and_proceed(); }, - standee(s) { - const effect = get_current_event().effects[get_active_node_args()]; - const value = effect.value; - game.tracks[s] += value; - log_h3(`${track_names[effect.target]} decreased by ${Math.abs(value)}`); - resolve_active_and_proceed(); +}; +states.move_track_up_or_down = { + inactive: 'move a track', + prompt() { + const node = get_active_node(); + view.prompt = `Move ${get_track_name(node.a.track_id)} up or down`; + gen_action('up'); + gen_action('down'); }, - Anarchist() { - lose_hero_point(ANARCHISTS_ID, 1); + down() { + const node = get_active_node(); + move_track(node.a.track_id, -1 * node.a.strength); resolve_active_and_proceed(); }, - Communist() { - lose_hero_point(ANARCHISTS_ID, 1); + up() { + const node = get_active_node(); + move_track(node.a.track_id, node.a.strength); resolve_active_and_proceed(); - }, - Moderate() { - lose_hero_point(ANARCHISTS_ID, 1); - resolve_active_and_proceed(); - }, + } }; states.choose_card = { inactive: 'choose a card', @@ -442,15 +446,39 @@ states.player_turn = { gen_action('play_for_ap'); gen_action('play_for_event'); } + else { + gen_action('done'); + } if (hero_points > 0) { gen_action('spend_hp'); } }, + done() { + resolve_active_and_proceed(); + }, play_for_ap() { const faction_id = get_faction_id(game.active); const card = game.cards_in_play[faction_id]; log_h3(`${game.active} plays ${cards[card].title} for the Action Points`); - resolve_active_and_proceed(); + if (!game.discard) { + game.discard = { + [ANARCHISTS_ID]: [], + [COMMUNISTS_ID]: [], + [MODERATES_ID]: [], + f: [], + }; + } + array_remove(game.hands[faction_id], game.hands[faction_id].indexOf(card)); + game.discard[faction_id].push(card); + insert_before_active_node({ + t: leaf_node, + p: faction_id, + s: 'choose_area_ap', + a: { + strength: cards[card].strength, + }, + }); + next(); }, play_for_event() { const faction_id = get_faction_id(game.active); @@ -484,6 +512,59 @@ states.player_turn = { resolve_active_and_proceed(); }, }; +states.resolve_event = { + inactive: 'resolve Fascist Event', + prompt() { + const card = get_current_event(); + const node = get_active_node(game.engine); + const effect = card.effects[node.a]; + view.prompt = get_event_prompt(effect); + if (effect.type === 'attack' && + (effect.target === 'd' || effect.target === 'v')) { + const fronts = get_fronts_closest_to(effect.target); + fronts.forEach((id) => gen_action('front', id)); + } + else if (effect.type === 'attack') { + gen_action('front', effect.target); + } + else if (effect.type === 'track') { + gen_action('standee', effect.target); + } + else if (effect.type === 'hero_points' && + effect.target === data_1.PLAYER_WITH_MOST_HERO_POINTS) { + const factions = get_factions_with_most_hero_poins(); + for (let faction_id of factions) { + gen_action(get_player(faction_id)); + } + } + }, + front(f) { + const card = get_current_event(); + const value = card.effects[get_active_node_args()].value; + game.fronts[f] -= value; + log_h3(`${value} attacks added to ${front_names[f]}`); + resolve_active_and_proceed(); + }, + standee(s) { + const effect = get_current_event().effects[get_active_node_args()]; + const value = effect.value; + game.tracks[s] += value; + log_h3(`${track_names[effect.target]} decreased by ${Math.abs(value)}`); + resolve_active_and_proceed(); + }, + Anarchist() { + lose_hero_point(ANARCHISTS_ID, 1); + resolve_active_and_proceed(); + }, + Communist() { + lose_hero_point(ANARCHISTS_ID, 1); + resolve_active_and_proceed(); + }, + Moderate() { + lose_hero_point(ANARCHISTS_ID, 1); + resolve_active_and_proceed(); + }, +}; states.spend_hero_points = { inactive: 'spend Hero points', prompt() { @@ -526,7 +607,8 @@ function resolve_fascist_test() { log_h2('Fascist test is resolved'); next(); } -function move_track(track, change) { } +function move_track(track, change) { +} function draw_card(deck) { clear_undo(); let i = random(deck.length); @@ -647,6 +729,9 @@ function get_factions_with_most_hero_poins() { }); return faction_ids; } +function get_track_name(track_id) { + return track_names[track_id]; +} function make_list(first, last) { let list = []; for (let i = first; i <= last; i++) @@ -30,6 +30,7 @@ import data, { SOVIET_SUPPORT, FOREIGN_AID, PLAYER_WITH_MOST_HERO_POINTS, + PlayerCard, // StaticData, // PLAYER_WITH_MOST_HERO_POINTS, } from './data'; @@ -74,6 +75,14 @@ const front_names: Record<string, string> = { v: 'the Front closest to Victory', }; +const tracks = [ + LIBERTY, + COLLECTIVIZATION, + GOVERNMENT, + SOVIET_SUPPORT, + FOREIGN_AID, +]; + const track_names: Record<number, string> = { [LIBERTY]: 'Liberty', [COLLECTIVIZATION]: 'Collectivization', @@ -118,6 +127,10 @@ function gen_action_card(card_id: CardId) { gen_action('card', card_id); } +function gen_action_standee(track_id: number) { + gen_action('standee', track_id); +} + // function gen_action_space(space) { // gen_action('space', space); // } @@ -248,7 +261,9 @@ function get_active( // return null; // } -function get_active_node(engine: EngineNode[]): FunctionNode | LeafNode | null { +function get_active_node( + engine: EngineNode[] = game.engine +): FunctionNode | LeafNode | null { const a = get_active(engine); return a === null ? null : a.node; // for (let i of engine) { @@ -395,6 +410,12 @@ export function setup(seed: number, _scenario: string, _options: unknown) { blank_markers: [[], [], [], [], []], bonuses: [ON, ON], current_events: [], + discard: { + [ANARCHISTS_ID]: [], + [COMMUNISTS_ID]: [], + [MODERATES_ID]: [], + f: [], + }, engine: [], fronts: { a: -2, @@ -513,62 +534,48 @@ states.add_glory = { }, }; -states.resolve_event = { - inactive: 'resolve Fascist Event', +states.choose_area_ap = { + inactive: 'choose area to use Action Points', prompt() { - const card = get_current_event(); - const node = get_active_node(game.engine) as LeafNode; - const effect: CardEffect = card.effects[node.a]; - view.prompt = get_event_prompt(effect); - - if ( - effect.type === 'attack' && - (effect.target === 'd' || effect.target === 'v') - ) { - const fronts = get_fronts_closest_to(effect.target); - fronts.forEach((id) => gen_action('front', id)); - } else if (effect.type === 'attack') { - gen_action('front', effect.target); - } else if (effect.type === 'track') { - gen_action('standee', effect.target); - } else if ( - effect.type === 'hero_points' && - effect.target === PLAYER_WITH_MOST_HERO_POINTS - ) { - const factions = get_factions_with_most_hero_poins(); - for (let faction_id of factions) { - gen_action(get_player(faction_id)); - } + view.prompt = 'Choose area of the board to affect'; + for (let track_id of tracks) { + gen_action_standee(track_id); } - // for (let p = 0; p < 5; ++p) gen_action('standee', p); - }, - front(f: string) { - const card = get_current_event(); - const value = card.effects[get_active_node_args()].value; - game.fronts[f] -= value; - log_h3(`${value} attacks added to ${front_names[f]}`); - resolve_active_and_proceed(); }, - standee(s: string) { - const effect = get_current_event().effects[get_active_node_args()]; - const value = effect.value; - game.tracks[s] += value; - log_h3(`${track_names[effect.target]} decreased by ${Math.abs(value)}`); + standee(track_id: number) { + console.log('standee', track_id); + insert_after_active_node({ + t: leaf_node, + p: get_active_faction_id(), + s: 'move_track_up_or_down', + a: { + track_id, + strength: get_active_node()?.a.strength, + }, + }); resolve_active_and_proceed(); }, - Anarchist() { - lose_hero_point(ANARCHISTS_ID, 1); - resolve_active_and_proceed(); +}; + +states.move_track_up_or_down = { + inactive: 'move a track', + prompt() { + const node = get_active_node(); + view.prompt = `Move ${get_track_name(node.a.track_id)} up or down` + gen_action('up'); + gen_action('down'); }, - Communist() { - lose_hero_point(ANARCHISTS_ID, 1); + down() { + const node = get_active_node(); + move_track(node.a.track_id, -1 * node.a.strength); resolve_active_and_proceed(); }, - Moderate() { - lose_hero_point(ANARCHISTS_ID, 1); + up() { + const node = get_active_node(); + move_track(node.a.track_id, node.a.strength); resolve_active_and_proceed(); - }, -}; + } +} states.choose_card = { inactive: 'choose a card', @@ -602,16 +609,39 @@ states.player_turn = { // gen_action_card(); gen_action('play_for_ap'); gen_action('play_for_event'); + } else { + gen_action('done'); } if (hero_points > 0) { gen_action('spend_hp'); } }, + done() { + resolve_active_and_proceed(); + }, play_for_ap() { const faction_id = get_faction_id(game.active); const card = game.cards_in_play[faction_id]; log_h3(`${game.active} plays ${cards[card].title} for the Action Points`); - resolve_active_and_proceed(); + if (!game.discard) { + game.discard = { + [ANARCHISTS_ID]: [], + [COMMUNISTS_ID]: [], + [MODERATES_ID]: [], + f: [], + }; + } + array_remove(game.hands[faction_id], game.hands[faction_id].indexOf(card)); + game.discard[faction_id].push(card); + insert_before_active_node({ + t: leaf_node, + p: faction_id, + s: 'choose_area_ap', + a: { + strength: (cards[card] as PlayerCard).strength, + }, + }); + next(); }, play_for_event() { const faction_id = get_faction_id(game.active); @@ -647,6 +677,63 @@ states.player_turn = { }, }; +states.resolve_event = { + inactive: 'resolve Fascist Event', + prompt() { + const card = get_current_event(); + const node = get_active_node(game.engine) as LeafNode; + const effect: CardEffect = card.effects[node.a]; + view.prompt = get_event_prompt(effect); + + if ( + effect.type === 'attack' && + (effect.target === 'd' || effect.target === 'v') + ) { + const fronts = get_fronts_closest_to(effect.target); + fronts.forEach((id) => gen_action('front', id)); + } else if (effect.type === 'attack') { + gen_action('front', effect.target); + } else if (effect.type === 'track') { + gen_action('standee', effect.target); + } else if ( + effect.type === 'hero_points' && + effect.target === PLAYER_WITH_MOST_HERO_POINTS + ) { + const factions = get_factions_with_most_hero_poins(); + for (let faction_id of factions) { + gen_action(get_player(faction_id)); + } + } + // for (let p = 0; p < 5; ++p) gen_action('standee', p); + }, + front(f: string) { + const card = get_current_event(); + const value = card.effects[get_active_node_args()].value; + game.fronts[f] -= value; + log_h3(`${value} attacks added to ${front_names[f]}`); + resolve_active_and_proceed(); + }, + standee(s: string) { + const effect = get_current_event().effects[get_active_node_args()]; + const value = effect.value; + game.tracks[s] += value; + log_h3(`${track_names[effect.target]} decreased by ${Math.abs(value)}`); + resolve_active_and_proceed(); + }, + Anarchist() { + lose_hero_point(ANARCHISTS_ID, 1); + resolve_active_and_proceed(); + }, + Communist() { + lose_hero_point(ANARCHISTS_ID, 1); + resolve_active_and_proceed(); + }, + Moderate() { + lose_hero_point(ANARCHISTS_ID, 1); + resolve_active_and_proceed(); + }, +}; + states.spend_hero_points = { inactive: 'spend Hero points', prompt() { @@ -716,7 +803,9 @@ function resolve_fascist_test() { next(); } -function move_track(track: number, change: number) {} +function move_track(track: number, change: number) { + +} // #endregion @@ -977,6 +1066,10 @@ function get_factions_with_most_hero_poins() { return faction_ids; } +function get_track_name(track_id: number): string { + return track_names[track_id]; +} + function make_list(first: number, last: number) { let list = []; for (let i = first; i <= last; i++) list.push(i); @@ -23,6 +23,7 @@ export interface Game { bonuses: number[]; cards_in_play: Record<FactionId, CardId>; current_events: CardId[]; + discard: Record<FactionId | 'f', number[]>; engine: EngineNode[]; fronts: { a: number; |