summaryrefslogtreecommitdiff
path: root/rules.js
diff options
context:
space:
mode:
Diffstat (limited to 'rules.js')
-rw-r--r--rules.js242
1 files changed, 214 insertions, 28 deletions
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" ],