From ccb8a6fb356f02db0b066221d4dc18a6fcc831a8 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Mon, 8 May 2023 01:09:08 +0200 Subject: Complicated events. --- events.txt | 25 ++++--- rules.js | 242 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 229 insertions(+), 38 deletions(-) diff --git a/events.txt b/events.txt index 7215377..b601ad2 100644 --- a/events.txt +++ b/events.txt @@ -3,11 +3,11 @@ # Versailles Cards CARD 1 - Jules Ducatel - # TODO - if (game.round === 4) - goto "reveal_commune_hand" - else + asm clear_undo() + if (game.round < 4) goto "reveal_commune_objective" + else + goto "reveal_commune_hand" endif ops 1 MILITARY @@ -44,8 +44,11 @@ CARD 5 - Le Figaro CARD 6 - Général Louis Valentin # remove_different_up_to 2 (where_present(PARIS)) - # TODO - goto "general_louis_valentin" + asm game.count = 2 + asm game.spaces = where_present(PARIS) + if (can_vm_remove()) + goto "general_louis_valentin" + endif CARD 7 - Général Espivent prompt "Remove up to 2 from Social Movements." @@ -79,7 +82,6 @@ CARD 11 - Adolphe Thiers CARD 12 - Otto von Bismarck # must remove own cube from National Assembly - # TODO prompt "Remove 1 blue cube from National Assembly." remove_own NATIONAL_ASSEMBLY increase_prussian_collaboration @@ -90,7 +92,7 @@ CARD 13 - Général Ernest de Cissey CARD 14 - Colonel de Lochner if (is_versailles_control(MONT_VALERIEN)) - prompt "Use 3 Operation Points in Mont-Valérien or Butte Montmartre." + prompt "Use up to 3 Operations Points in Mont-Valérien or Butte Montmartre." switch ["mont_valerien","butte_montmartre"] case "mont_valerien" ops 3 MONT_VALERIEN @@ -173,8 +175,8 @@ CARD 29 - Raoul Rigault move_up_to 2 CATHOLIC_CHURCH PARIS CARD 30 - Karl Marx - # TODO - goto "karl_marx" + asm init_karl_marx() + goto "karl_marx_discard" CARD 31 - Blanquists increase_revolutionary_momentum @@ -245,6 +247,9 @@ CARD 40 - Elihu Washburne CARD 41 - Freemason Parade # must have initiative goto "freemason_parade" + prompt "Remove a cube from both factions." + remove_own (game.vm.freemason_parade) + remove 1 (game.vm.freemason_parade) prompt "Place up to 2 or replace 1 in Institutional." switch ["place","replace"] case "place" diff --git a/rules.js b/rules.js index 21387a1..a4a7442 100644 --- a/rules.js +++ b/rules.js @@ -879,8 +879,8 @@ function start_round() { n = 5 for (let i = 0; i < n; ++i) { - game.red_hand.push(game.strategy_deck.pop()) - game.blue_hand.push(game.strategy_deck.pop()) + game.red_hand.push(draw_strategy_card()) + game.blue_hand.push(draw_strategy_card()) } for (let i = 0; i < 2; ++i) { @@ -1078,27 +1078,29 @@ states.play_card = { }, political() { push_undo() - log(card_ops[game.what] + " Ops.") + log(card_ops[game.what] + " Operations Points.") discard_card(game.what) goto_operations(card_ops[game.what], POLITICAL) }, military() { push_undo() - log(card_ops[game.what] + " Ops.") + log(card_ops[game.what] + " Operations Points.") discard_card(game.what) goto_operations(card_ops[game.what], MILITARY) }, momentum() { push_undo() - log(`Momentum.`) if (game.scenario === "Censorship") recycle_card(game.what) else discard_card(game.what) - if (game.active === COMMUNE) + if (game.active === COMMUNE) { + log("Advanced Revolutionary Momentum.") advance_revolutionary_momentum(1) - else + } else { + log("Advanced Prussian Momentum.") advance_prussian_collaboration(1) + } }, red_momentum() { this.momentum() @@ -1148,13 +1150,13 @@ states.play_final_ops = { political() { push_undo() discard_final() - log("4 Ops.") + log("4 Operations Points.") goto_operations(4, POLITICAL) }, military() { push_undo() discard_final() - log("4 Ops.") + log("4 Operations Points.") goto_operations(4, MILITARY) }, } @@ -1201,6 +1203,7 @@ states.revolutionary_momentum_trigger = { view.actions.skip = 1 }, space(s) { + log("Placed red cube in S" + s + ".") place_cube(s) end_momentum_trigger() }, @@ -1218,6 +1221,7 @@ states.prussian_collaboration_trigger = { view.actions.skip = 1 }, space(s) { + log("Placed blue cube in S" + s + ".") place_cube(s) end_momentum_trigger() }, @@ -1351,15 +1355,17 @@ states.operations_remove = { remove_piece(p) resume_operations_remove() } else if (game.count >= 1) { - log("Military strength " + str + ".") game.who = p game.state = "operations_remove_spend" } else { - log("Military strength " + str + ".") game.who = p game.state = "operations_remove_draw" } } else { + if (game.current === COMMUNE) + log("Removed blue cube from S" + s + ".") + else + log("Removed red cube from S" + s + ".") remove_piece(p) resume_operations_remove() } @@ -1372,12 +1378,15 @@ states.operations_remove = { states.operations_remove_spend = { prompt() { - view.prompt = "Operations: Spend extra Operations Point before drawing?" + let p = game.who + let s = game.pieces[p] + let str = military_strength(s) + view.prompt = "Operations: Military strength " + str + " - spend extra Operations Point?" view.actions.spend = 1 view.actions.draw = 1 }, spend() { - log("Spent 1 ops.") + log("Spent 1 extra Operations Point.") game.count -= 1 attempt_remove_piece(1) }, @@ -1400,13 +1409,21 @@ function attempt_remove_piece(extra) { clear_undo() let p = game.who let s = game.pieces[p] - let c = game.strategy_deck.pop() + let c = draw_strategy_card() let str = military_strength(s) + extra let ops = card_ops[c] log("Military strength " + str + ".") - log("Removed card C" + c + " for " + ops + " strength.") - if (str >= ops) + log("Removed card C" + c + " with " + ops + " Operations Points.") + remove_card(c) + if (str >= ops) { + if (game.current === COMMUNE) + log("Removed blue cube from S" + s + ".") + else + log("Removed red cube from S" + s + ".") remove_piece(p) + } else { + log("Failed.") + } game.who = -1 resume_operations_remove() } @@ -2313,6 +2330,7 @@ states.vm_increase_revolutionary_momentum = { }, red_momentum() { push_undo() + log("Advanced Revolutionary Momentum.") advance_revolutionary_momentum(1) }, } @@ -2324,6 +2342,7 @@ states.vm_increase_prussian_collaboration = { }, blue_momentum() { push_undo() + log("Advanced Prussian Collaboration.") advance_prussian_collaboration(1) }, } @@ -2335,6 +2354,7 @@ states.vm_decrease_revolutionary_momentum = { }, red_momentum() { push_undo() + log("Decreased Revolutionary Momentum.") advance_revolutionary_momentum(-1) }, } @@ -2346,6 +2366,7 @@ states.vm_decrease_prussian_collaboration = { }, blue_momentum() { push_undo() + log("Decreased Prussian Collaboration.") advance_prussian_collaboration(-1) }, } @@ -2376,6 +2397,10 @@ states.vm_place = { space(s) { push_undo() place_cube(s, game.vm.removed) + if (game.current === COMMUNE) + log("Placed red cube in S" + s + ".") + else + log("Placed blue cube in S" + s + ".") if (--game.vm.count === 0 || !can_vm_place(game.vm.removed)) vm_next() }, @@ -2417,6 +2442,10 @@ states.vm_move_disc = { }, piece(p) { push_undo() + if (game.current === COMMUNE) + log("Moved Barricade from S" + s + ".") + else + log("Moved Fortification from S" + s + ".") remove_piece(p) game.state = "vm_place_disc" }, @@ -2437,6 +2466,10 @@ states.vm_place_disc = { }, space(s) { push_undo() + if (game.current === COMMUNE) + log("Placed Barricade in S" + s + ".") + else + log("Placed Fortification in S" + s + ".") place_disc(s) vm_next() }, @@ -2472,6 +2505,10 @@ states.vm_replace = { piece(p) { push_undo() replace_cube(p) + if (game.current === COMMUNE) + log("Replaced blue cube in S" + s + ".") + else + log("Replaced red cube in S" + s + ".") if (--game.vm.count === 0 || !can_vm_replace()) vm_next() }, @@ -2506,6 +2543,11 @@ states.vm_remove = { }, piece(p) { push_undo() + let s = game.pieces[p] + if (game.current === COMMUNE) + log("Removed blue cube from S" + s + ".") + else + log("Removed red cube from S" + s + ".") remove_piece(p) if (--game.vm.count === 0 || !can_vm_remove()) vm_next() @@ -2519,19 +2561,17 @@ states.vm_remove = { states.vm_remove_own = { prompt() { event_prompt() - if (game.vm.upto) - view.actions.skip = 1 for (let s of game.vm.spaces) for_each_friendly_cube(s, gen_action_piece) }, piece(p) { push_undo() + let s = game.pieces[p] + if (game.current === COMMUNE) + log("Removed red cube from S" + s + ".") + else + log("Removed blue cube from S" + s + ".") remove_piece(p) - if (--game.vm.count === 0) - vm_next() - }, - skip() { - push_undo() vm_next() }, } @@ -2576,7 +2616,12 @@ states.vm_move = { game.who = p }, space(s) { + let old_s = game.pieces[game.who] move_piece(game.who, s) + if (game.current === COMMUNE) + log("Moved red cube from S" + old_s + " to S" + s + ".") + else + log("Moved blue cube from S" + old_s + " to S" + s + ".") game.who = -1 if (--game.vm.count === 0 || !can_vm_move()) vm_next() @@ -2589,6 +2634,107 @@ states.vm_move = { // === COMPLICATED EVENT STATES === +states.reveal_commune_objective = { + prompt() { + view.prompt = "Revealing Commune player's Objective Card." + view.objective = game.red_objective + view.actions.done = 1 + }, + done() { + vm_next() + }, +} + +states.reveal_commune_hand = { + prompt() { + view.prompt = "Revealing Commune player's hand." + view.objective = game.red_hand + view.actions.done = 1 + }, + done() { + vm_next() + }, +} + +states.general_louis_valentin = { + prompt() { + event_prompt("Remove a red cube from up to 2 different Paris spaces where you are present.") + view.actions.skip = 1 + for (let s of game.spaces) + if (can_remove_cube(s)) + for_each_enemy_cube(s, gen_action_piece) + }, + piece(p) { + push_undo() + let s = game.pieces[p] + array_remove_item(game.spaces, s) + if (game.current === COMMUNE) + log("Removed blue cube from S" + s + ".") + else + log("Removed red cube from S" + s + ".") + remove_piece(p) + if (--game.count === 0 || !can_vm_remove()) + vm_next() + }, + skip() { + vm_next() + }, +} + +function init_karl_marx() { + // clear_undo() + game.red_hand.push(draw_strategy_card()) + game.red_hand.push(draw_strategy_card()) + game.red_hand.push(draw_strategy_card()) + game.vm.cards = [ + game.red_hand.pop(), + game.red_hand.pop(), + game.red_hand.pop(), + ] +} + +states.karl_marx_discard = { + prompt() { + event_prompt("Discard 2 cards, then play or discard the last card.") + view.hand = game.vm.cards + for (let c of game.vm.cards) + gen_action_card(c) + }, + card(c) { + push_undo() + log("Discarded C" + c + ".") + array_remove_item(game.vm.cards, c) + game.discard = c + if (game.vm.cards.length === 1) + game.state = "karl_marx_play" + }, +} + +states.karl_marx_play = { + prompt() { + event_prompt("Play or discard the last card.") + view.hand = game.vm.cards + if (can_play_event(game.vm.cards[0])) + view.actions.event = 1 + else + view.actions.event = 0 + gen_action_card(game.vm.cards[0]) + }, + event() { + let c = game.vm.cards[0] + push_undo() + log("Played C" + c + ".") + game.discard = c + goto_play_event(c) + }, + card(c) { + push_undo() + log("Discarded C" + c + ".") + game.discard = c + vm_next() + }, +} + function can_play_freemason_parade() { for (let s of MILITARY) if (has_commune_cube(s) && has_versailles_cube(s)) @@ -2596,6 +2742,19 @@ function can_play_freemason_parade() { return false } +states.freemason_parade = { + prompt() { + event_prompt("Remove a cube from both factions in a single Military space.") + for (let s of MILITARY) + if (has_commune_cube(s) && has_versailles_cube(s)) + gen_action_space(s) + }, + space(s) { + game.vm.freemason_parade = s + vm_next() + }, +} + // === SETUP === exports.setup = function (seed, scenario, options) { @@ -2702,6 +2861,24 @@ exports.setup = function (seed, scenario, options) { return game } +function reshuffle_strategy_deck() { + game.discard = 0 + game.strategy_deck = [] + for (let c = 1; c <= 41; ++c) + if (c !== 17 && c !== 34) + if (!game.red_hand.includes(c) && !game.blue_hand.includes(c)) + game.strategy_deck.push(c) + shuffle(game.strategy_deck) +} + +function draw_strategy_card() { + if (game.strategy_deck.length === 0) { + log("Reshuffled.") + reshuffle_strategy_deck() + } + return game.strategy_deck.pop() +} + // === VIEW === exports.is_checkpoint = function (a, b) { @@ -2960,10 +3137,11 @@ function array_remove(array, index) { const CODE = [] CODE[1] = [ // Jules Ducatel - [ vm_if, ()=>(game.round === 4) ], - [ vm_goto, "reveal_commune_hand" ], - [ vm_else ], + [ vm_asm, ()=>clear_undo() ], + [ vm_if, ()=>(game.round < 4) ], [ vm_goto, "reveal_commune_objective" ], + [ vm_else ], + [ vm_goto, "reveal_commune_hand" ], [ vm_endif ], [ vm_ops, 1, MILITARY ], [ vm_return ], @@ -3009,7 +3187,11 @@ CODE[5] = [ // Le Figaro ] CODE[6] = [ // Général Louis Valentin + [ vm_asm, ()=>game.count = 2 ], + [ vm_asm, ()=>game.spaces = where_present(PARIS) ], + [ vm_if, ()=>(can_vm_remove()) ], [ vm_goto, "general_louis_valentin" ], + [ vm_endif ], [ vm_return ], ] @@ -3065,7 +3247,7 @@ CODE[13] = [ // Général Ernest de Cissey CODE[14] = [ // Colonel de Lochner [ vm_if, ()=>(is_versailles_control(MONT_VALERIEN)) ], - [ vm_prompt, "Use 3 Operation Points in Mont-Valérien or Butte Montmartre." ], + [ vm_prompt, "Use up to 3 Operations Points in Mont-Valérien or Butte Montmartre." ], [ vm_switch, ["mont_valerien","butte_montmartre"] ], [ vm_case, "mont_valerien" ], [ vm_ops, 3, MONT_VALERIEN ], @@ -3177,7 +3359,8 @@ CODE[29] = [ // Raoul Rigault ] CODE[30] = [ // Karl Marx - [ vm_goto, "karl_marx" ], + [ vm_asm, ()=>init_karl_marx() ], + [ vm_goto, "karl_marx_discard" ], [ vm_return ], ] @@ -3263,6 +3446,9 @@ CODE[40] = [ // Elihu Washburne CODE[41] = [ // Freemason Parade [ vm_goto, "freemason_parade" ], + [ vm_prompt, "Remove a cube from both factions." ], + [ vm_remove_own, ()=>(game.vm.freemason_parade) ], + [ vm_remove, 1, ()=>(game.vm.freemason_parade) ], [ vm_prompt, "Place up to 2 or replace 1 in Institutional." ], [ vm_switch, ["place","replace"] ], [ vm_case, "place" ], -- cgit v1.2.3