summaryrefslogtreecommitdiff
path: root/rules.js
diff options
context:
space:
mode:
Diffstat (limited to 'rules.js')
-rw-r--r--rules.js567
1 files changed, 362 insertions, 205 deletions
diff --git a/rules.js b/rules.js
index 02d9a69..40853de 100644
--- a/rules.js
+++ b/rules.js
@@ -1,5 +1,7 @@
"use strict"
+// TODO: no card menu
+
const COMMUNE = "Commune";
const VERSAILLES = "Versailles";
@@ -134,118 +136,118 @@ const BLUE_CRISIS_TRACK = [25, 26, 27, 28]
const BLUE_BONUS_CUBES = [29, 30, 31]
const PRUSSIAN_COLLABORATION = [32, 33, 34]
-const S_NATIONAL_ASSEMBLY = 0
-const S_ROYALISTS = 1
-const S_REPUBLICANS = 2
+const NATIONAL_ASSEMBLY = 0
+const ROYALISTS = 1
+const REPUBLICANS = 2
-const S_PRESS = 3
-const S_CATHOLIC_CHURCH = 4
-const S_SOCIAL_MOVEMENTS = 5
+const PRESS = 3
+const CATHOLIC_CHURCH = 4
+const SOCIAL_MOVEMENTS = 5
-const S_MONT_VALERIEN = 6
-const S_FORT_D_ISSY = 7
-const S_CHATEAU_DE_VINCENNES = 8
+const MONT_VALERIEN = 6
+const FORT_D_ISSY = 7
+const CHATEAU_DE_VINCENNES = 8
-const S_BUTTE_MONTMARTRE = 9
-const S_BUTTE_AUX_CAILLES = 10
-const S_PERE_LACHAISE = 11
+const BUTTE_MONTMARTRE = 9
+const BUTTE_AUX_CAILLES = 10
+const PERE_LACHAISE = 11
-const S_PRUSSIAN_OCCUPIED_TERRITORY = 12
-const S_VERSAILLES_HQ = 13
+const PRUSSIAN_OCCUPIED_TERRITORY = 12
+const VERSAILLES_HQ = 13
-const first_space = S_NATIONAL_ASSEMBLY
-const last_space = S_PERE_LACHAISE
+const first_space = NATIONAL_ASSEMBLY
+const last_space = PERE_LACHAISE
const space_count = last_space + 1
const POLITICAL = [
- S_NATIONAL_ASSEMBLY,
- S_ROYALISTS,
- S_REPUBLICANS,
- S_PRESS,
- S_CATHOLIC_CHURCH,
- S_SOCIAL_MOVEMENTS,
+ NATIONAL_ASSEMBLY,
+ ROYALISTS,
+ REPUBLICANS,
+ PRESS,
+ CATHOLIC_CHURCH,
+ SOCIAL_MOVEMENTS,
]
const MILITARY = [
- S_MONT_VALERIEN,
- S_FORT_D_ISSY,
- S_CHATEAU_DE_VINCENNES,
- S_BUTTE_MONTMARTRE,
- S_BUTTE_AUX_CAILLES,
- S_PERE_LACHAISE,
+ MONT_VALERIEN,
+ FORT_D_ISSY,
+ CHATEAU_DE_VINCENNES,
+ BUTTE_MONTMARTRE,
+ BUTTE_AUX_CAILLES,
+ PERE_LACHAISE,
]
function is_political_space(s) {
return (
- s === S_NATIONAL_ASSEMBLY ||
- s === S_ROYALISTS ||
- s === S_REPUBLICANS ||
- s === S_PRESS ||
- s === S_CATHOLIC_CHURCH ||
- s === S_SOCIAL_MOVEMENTS
+ s === NATIONAL_ASSEMBLY ||
+ s === ROYALISTS ||
+ s === REPUBLICANS ||
+ s === PRESS ||
+ s === CATHOLIC_CHURCH ||
+ s === SOCIAL_MOVEMENTS
)
}
function is_military_space(s) {
return (
- s === S_MONT_VALERIEN ||
- s === S_FORT_D_ISSY ||
- s === S_CHATEAU_DE_VINCENNES ||
- s === S_BUTTE_MONTMARTRE ||
- s === S_BUTTE_AUX_CAILLES ||
- s === S_PERE_LACHAISE
+ s === MONT_VALERIEN ||
+ s === FORT_D_ISSY ||
+ s === CHATEAU_DE_VINCENNES ||
+ s === BUTTE_MONTMARTRE ||
+ s === BUTTE_AUX_CAILLES ||
+ s === PERE_LACHAISE
)
}
-const DIM_INSTITUTIONAL = [ S_NATIONAL_ASSEMBLY, S_ROYALISTS, S_REPUBLICANS ]
-const DIM_PUBLIC_OPINION = [ S_PRESS, S_CATHOLIC_CHURCH, S_SOCIAL_MOVEMENTS ]
+const INSTITUTIONAL = [ NATIONAL_ASSEMBLY, ROYALISTS, REPUBLICANS ]
+const PUBLIC_OPINION = [ PRESS, CATHOLIC_CHURCH, SOCIAL_MOVEMENTS ]
-const DIM_FORTS = [ S_MONT_VALERIEN, S_FORT_D_ISSY, S_CHATEAU_DE_VINCENNES ]
-const DIM_PARIS = [ S_BUTTE_MONTMARTRE, S_BUTTE_AUX_CAILLES, S_PERE_LACHAISE ]
+const FORTS = [ MONT_VALERIEN, FORT_D_ISSY, CHATEAU_DE_VINCENNES ]
+const PARIS = [ BUTTE_MONTMARTRE, BUTTE_AUX_CAILLES, PERE_LACHAISE ]
const ADJACENT_TO = [
- [ S_ROYALISTS, S_REPUBLICANS ],
- [ S_PRESS, S_CATHOLIC_CHURCH ],
- [ S_PRESS, S_SOCIAL_MOVEMENTS ],
- [ S_ROYALISTS, S_REPUBLICANS, S_CATHOLIC_CHURCH, S_SOCIAL_MOVEMENTS ],
- [ S_ROYALISTS, S_PRESS ],
- [ S_REPUBLICANS, S_PRESS ],
- [ S_BUTTE_MONTMARTRE, S_VERSAILLES_HQ ],
- [ S_CHATEAU_DE_VINCENNES, S_BUTTE_AUX_CAILLES, S_VERSAILLES_HQ ],
- [ S_FORT_D_ISSY, S_PERE_LACHAISE, S_PRUSSIAN_OCCUPIED_TERRITORY ],
- [ S_MONT_VALERIEN, S_BUTTE_AUX_CAILLES, S_PERE_LACHAISE ],
- [ S_FORT_D_ISSY, S_BUTTE_MONTMARTRE, S_PERE_LACHAISE ],
- [ S_CHATEAU_DE_VINCENNES, S_BUTTE_MONTMARTRE, S_BUTTE_AUX_CAILLES, S_PRUSSIAN_OCCUPIED_TERRITORY ],
- [ S_CHATEAU_DE_VINCENNES, S_PERE_LACHAISE ],
- [ S_MONT_VALERIEN, S_FORT_D_ISSY ],
+ [ ROYALISTS, REPUBLICANS ],
+ [ PRESS, CATHOLIC_CHURCH ],
+ [ PRESS, SOCIAL_MOVEMENTS ],
+ [ ROYALISTS, REPUBLICANS, CATHOLIC_CHURCH, SOCIAL_MOVEMENTS ],
+ [ ROYALISTS, PRESS ],
+ [ REPUBLICANS, PRESS ],
+ [ BUTTE_MONTMARTRE, VERSAILLES_HQ ],
+ [ CHATEAU_DE_VINCENNES, BUTTE_AUX_CAILLES, VERSAILLES_HQ ],
+ [ FORT_D_ISSY, PERE_LACHAISE, PRUSSIAN_OCCUPIED_TERRITORY ],
+ [ MONT_VALERIEN, BUTTE_AUX_CAILLES, PERE_LACHAISE ],
+ [ FORT_D_ISSY, BUTTE_MONTMARTRE, PERE_LACHAISE ],
+ [ CHATEAU_DE_VINCENNES, BUTTE_MONTMARTRE, BUTTE_AUX_CAILLES, PRUSSIAN_OCCUPIED_TERRITORY ],
+ [ CHATEAU_DE_VINCENNES, PERE_LACHAISE ],
+ [ MONT_VALERIEN, FORT_D_ISSY ],
]
const ADJACENT_FROM = [
[ ],
- [ S_NATIONAL_ASSEMBLY, S_PRESS, S_CATHOLIC_CHURCH ],
- [ S_NATIONAL_ASSEMBLY, S_PRESS, S_SOCIAL_MOVEMENTS ],
- [ S_ROYALISTS, S_REPUBLICANS, S_CATHOLIC_CHURCH, S_SOCIAL_MOVEMENTS ],
- [ S_ROYALISTS, S_PRESS ],
- [ S_REPUBLICANS, S_PRESS ],
- [ S_BUTTE_MONTMARTRE, S_VERSAILLES_HQ ],
- [ S_CHATEAU_DE_VINCENNES, S_BUTTE_AUX_CAILLES, S_VERSAILLES_HQ ],
- [ S_FORT_D_ISSY, S_PERE_LACHAISE, S_PRUSSIAN_OCCUPIED_TERRITORY ],
- [ S_MONT_VALERIEN, S_BUTTE_AUX_CAILLES, S_PERE_LACHAISE ],
- [ S_FORT_D_ISSY, S_BUTTE_MONTMARTRE, S_PERE_LACHAISE ],
- [ S_CHATEAU_DE_VINCENNES, S_BUTTE_MONTMARTRE, S_BUTTE_AUX_CAILLES, S_PRUSSIAN_OCCUPIED_TERRITORY ],
- [ S_CHATEAU_DE_VINCENNES, S_PERE_LACHAISE ],
- [ S_MONT_VALERIEN, S_FORT_D_ISSY ],
+ [ NATIONAL_ASSEMBLY, PRESS, CATHOLIC_CHURCH ],
+ [ NATIONAL_ASSEMBLY, PRESS, SOCIAL_MOVEMENTS ],
+ [ ROYALISTS, REPUBLICANS, CATHOLIC_CHURCH, SOCIAL_MOVEMENTS ],
+ [ ROYALISTS, PRESS ],
+ [ REPUBLICANS, PRESS ],
+ [ BUTTE_MONTMARTRE, VERSAILLES_HQ ],
+ [ CHATEAU_DE_VINCENNES, BUTTE_AUX_CAILLES, VERSAILLES_HQ ],
+ [ FORT_D_ISSY, PERE_LACHAISE, PRUSSIAN_OCCUPIED_TERRITORY ],
+ [ MONT_VALERIEN, BUTTE_AUX_CAILLES, PERE_LACHAISE ],
+ [ FORT_D_ISSY, BUTTE_MONTMARTRE, PERE_LACHAISE ],
+ [ CHATEAU_DE_VINCENNES, BUTTE_MONTMARTRE, BUTTE_AUX_CAILLES, PRUSSIAN_OCCUPIED_TERRITORY ],
+ [ CHATEAU_DE_VINCENNES, PERE_LACHAISE ],
+ [ MONT_VALERIEN, FORT_D_ISSY ],
]
// === GAME STATE ===
function discard_card(c) {
- array_remove_item(player_hand(game.active), c)
+ array_remove_item(player_hand(), c)
game.discard = c
}
function recycle_card(c) {
- array_remove_item(player_hand(game.active), c)
+ array_remove_item(player_hand(), c)
game.strategy_deck.unshift(c)
}
@@ -253,10 +255,6 @@ function is_objective_card(c) {
return c >= 42 && c <= 53
}
-function is_strategy_card(c) {
- return !is_objective_card(c) && c !== 17 && c !== 34
-}
-
function is_commune_card(c) {
return c >= 18 && c <= 34
}
@@ -275,12 +273,18 @@ function enemy_player() {
return COMMUNE
}
-function player_hand(current) {
- if (current === COMMUNE)
+function player_hand() {
+ if (game.active === COMMUNE)
return game.red_hand
return game.blue_hand
}
+function player_set_aside(current) {
+ if (game.active === COMMUNE)
+ return game.red_set_aside
+ return game.blue_set_aside
+}
+
function is_space(s) {
return s >= first_space && s <= last_space
}
@@ -332,13 +336,13 @@ function update_presence_and_control() {
game.control = 0
// Permanent Presence
- game.presence |= (1 << (S_PERE_LACHAISE))
- game.presence |= (1 << (S_SOCIAL_MOVEMENTS))
- game.presence |= (1 << (S_ROYALISTS + space_count))
+ game.presence |= 1 << PERE_LACHAISE
+ game.presence |= 1 << SOCIAL_MOVEMENTS
+ game.presence |= 1 << (ROYALISTS + space_count)
for (let s = first_space; s <= last_space; ++s) {
- let c_bit = (1 << (s))
- let v_bit = (1 << (s + space_count))
+ let c_bit = 1 << s
+ let v_bit = 1 << (s + space_count)
if (c_count[s] > 0)
game.presence |= c_bit
if (v_count[s] > 0)
@@ -348,47 +352,46 @@ function update_presence_and_control() {
if (v_count[s] > c_count[s])
game.control |= v_bit
}
-
}
-function is_present(side, s) {
- if (side === COMMUNE)
+function is_present(s) {
+ if (game.active === COMMUNE)
return game.presence & (1 << (s))
return game.presence & (1 << (s + space_count))
}
function is_commune_control(s) {
- if (s === S_VERSAILLES_HQ)
+ if (s === VERSAILLES_HQ)
return false
- if (s === S_PRUSSIAN_OCCUPIED_TERRITORY)
+ if (s === PRUSSIAN_OCCUPIED_TERRITORY)
return false
return game.control & (1 << (s))
}
function is_versailles_control(s) {
- if (s === S_VERSAILLES_HQ)
+ if (s === VERSAILLES_HQ)
return true
- if (s === S_PRUSSIAN_OCCUPIED_TERRITORY)
+ if (s === PRUSSIAN_OCCUPIED_TERRITORY)
return game.blue_momentum === 3
return game.control & (1 << (s + space_count))
}
-function is_control(side, s) {
- if (side === COMMUNE)
+function is_control(s) {
+ if (game.active === COMMUNE)
return is_commune_control(s)
return is_versailles_control(s)
}
-function is_adjacent_to_control(side, here) {
+function is_adjacent_to_control(here) {
for (let s of ADJACENT_TO[here])
- if (is_control(side, s))
+ if (is_control(s))
return true
return false
}
-function is_control_dimension(side, dim) {
+function is_control_dimension(dim) {
for (let s of dim)
- if (!is_control(side, s))
+ if (!is_control(s))
return false
return true
}
@@ -433,6 +436,12 @@ function count_versailles_pieces(s) {
return count_versailles_cubes(s) + count_versailles_discs(s)
}
+function count_friendly_cubes(s) {
+ if (game.active === COMMUNE)
+ return count_commune_cubes(s)
+ return count_versailles_cubes(s)
+}
+
function count_enemy_pieces(s) {
if (game.active === COMMUNE)
return count_versailles_pieces(s)
@@ -517,7 +526,14 @@ function is_disc(p) {
function remove_piece(p) {
if (is_commune_cube(p)) {
- game.pieces[p] = RED_CUBE_POOL[0] // TODO...
+ if (game.red_momentum >= 1 && count_commune_cubes(RED_CUBE_POOL[0]) < 2)
+ game.pieces[p] = RED_CUBE_POOL[0]
+ else if (game.red_momentum >= 2 && count_commune_cubes(RED_CUBE_POOL[1]) < 1)
+ game.pieces[p] = RED_CUBE_POOL[1]
+ else if (game.red_momentum >= 3 && count_commune_cubes(RED_CUBE_POOL[2]) < 1)
+ game.pieces[p] = RED_CUBE_POOL[2]
+ else
+ game.pieces[p] = -1
} else if (is_versailles_cube(p)) {
game.pieces[p] = BLUE_CUBE_POOL
} else {
@@ -525,6 +541,10 @@ function remove_piece(p) {
}
}
+function remove_piece_from_play(p) {
+ game.pieces[p] = -1
+}
+
function place_piece(p, s) {
game.pieces[p] = s
}
@@ -552,6 +572,7 @@ function find_available_cube() {
return p
}
}
+ return -1
}
function for_each_enemy_cube(s, f) {
@@ -619,24 +640,24 @@ function versailles_political_vp() {
states.choose_objective_card = {
inactive: "choose an objective card",
prompt(current) {
- view.prompt = "Choose an Objective card."
- for (let c of player_hand(current))
- if (is_objective_card(c))
+ view.prompt = "Choose an Objective card to keep."
+ if (current === COMMUNE)
+ for (let c of game.red_objective)
+ gen_action_card(c)
+ else
+ for (let c of game.blue_objective)
gen_action_card(c)
},
card(c, current) {
- if (current === COMMUNE) {
- game.red_objective = c
- game.red_hand = game.red_hand.filter(c => !is_objective_card(c))
- } else {
- game.blue_objective = c
- game.blue_hand = game.blue_hand.filter(c => !is_objective_card(c))
- }
- if (game.red_objective > 0 && game.blue_objective > 0)
+ if (current === COMMUNE)
+ game.red_objective = [ c ]
+ else
+ game.blue_objective = [ c ]
+ if (game.red_objective.length === 1 && game.blue_objective.length === 1)
end_choose_objective_card()
- else if (game.red_objective > 0)
+ else if (game.red_objective.length === 1)
game.active = VERSAILLES
- else if (game.blue_objective > 0)
+ else if (game.blue_objective.length === 1)
game.active = COMMUNE
else
game.active = "Both"
@@ -660,9 +681,9 @@ function goto_initiative_phase() {
}
states.initiative_phase = {
- inactive: "decide player order",
+ inactive: "decide initiative",
prompt() {
- view.prompt = "Decide player order."
+ view.prompt = "Decide who will have the initiative."
view.actions.commune = 1
view.actions.versailles = 1
},
@@ -696,9 +717,8 @@ states.censorship_phase = {
inactive: "censorship phase",
prompt() {
view.prompt = "Discard a card from your hand."
- for (let c of player_hand(game.active))
- if (is_strategy_card(c))
- gen_action("card", c)
+ for (let c of player_hand())
+ gen_action("card", c)
},
card(c) {
log(`Discarded #${c}.`)
@@ -719,83 +739,195 @@ function goto_strategy_phase() {
}
function resume_strategy_phase() {
- game.active = enemy_player()
- goto_strategy_phase()
+ if (game.red_hand.length === 1 && game.blue_hand.length === 1) {
+ goto_set_aside_cards()
+ } else {
+ game.active = enemy_player()
+ goto_strategy_phase()
+ }
+}
+
+function has_final_crisis_card() {
+ if (game.active === COMMUNE)
+ return game.red_final
+ return game.blue_final
}
states.strategy_phase = {
inactive: "play a card",
prompt() {
view.prompt = "Play a card."
- let hand = player_hand(game.active)
- let n_strategy = 0
- for (let c of hand)
- if (is_strategy_card(c))
- n_strategy += 1
- for (let c of hand) {
- if (is_strategy_card(c)) {
- if (can_play_event(c))
- gen_action("card_event", c)
- gen_action("card_ops_political", c)
- gen_action("card_ops_military", c)
- if (game.discard > 0 && can_play_event(game.discard))
- gen_action("card_use_discarded", c)
- if (can_advance_momentum())
- gen_action("card_advance_momentum", c)
- }
- if (c === 17 || c === 34) {
- if (n_strategy > 0) {
- gen_action("card_ops_political", c)
- gen_action("card_ops_military", c)
- }
- }
- }
+ for (let c of player_hand())
+ gen_action_card(c)
},
- card_event(c) {
+ card(c) {
push_undo()
- log(`Played #${c} for event.`)
- discard_card(c)
- goto_play_event()
+ log(`Played #${c}.`)
+ game.what = c
+ game.state = "play_card"
},
- card_ops_political(c) {
- push_undo()
- if (c === 17 || c === 34)
- return goto_final_crisis_discard(c, POLITICAL)
- log(`Played #${c} for ${card_ops[c]} Political ops.`)
- discard_card(c)
- goto_operations(card_ops[c], POLITICAL)
+}
+
+states.play_card = {
+ prompt() {
+ let c = game.what
+
+ view.selected_card = game.what
+
+ view.actions.political = 1
+ view.actions.military = 1
+
+ if (can_play_event(c))
+ view.actions.event = 1
+ else
+ view.actions.event = 0
+
+ if (can_advance_momentum()) {
+ view.actions.momentum = 1
+ if (game.active === COMMUNE)
+ view.actions.red_momentum = 1
+ else
+ view.actions.blue_momentum = 1
+ }
+
+ if (game.discard > 0 && can_play_event(game.discard))
+ gen_action_card(game.discard)
+
+ let final = has_final_crisis_card()
+ if (final > 0)
+ gen_action_card(final)
},
- card_ops_military(c) {
- push_undo()
- if (c === 17 || c === 34)
- return goto_final_crisis_discard(c, MILITARY)
- log(`Played #${c} for ${card_ops[c]} Military ops.`)
- discard_card(c)
- goto_operations(card_ops[c], MILITARY)
+ event() {
+ log("Event.")
+ discard_card(game.what)
+ goto_play_event(game.what)
},
- card_advance_momentum(c) {
- push_undo()
- log(`Played #${c} to advance momentum.`)
+ political() {
+ log("Ops.")
+ discard_card(game.what)
+ goto_operations(card_ops[game.what], POLITICAL)
+ },
+ military() {
+ log("Ops.")
+ discard_card(game.what)
+ goto_operations(card_ops[game.what], MILITARY)
+ },
+ momentum() {
+ log(`Momentum.`)
if (game.scenario === "Censorship")
- recycle_card(c)
+ recycle_card(game.what)
else
- discard_card(c)
+ discard_card(game.what)
if (game.active === COMMUNE)
- game.red_momentum += 1
+ advance_revolutionary_momentum(1)
else
- game.blue_momentum += 1
- // TODO: momentum trigger
- resume_strategy_phase()
+ advance_prussian_collaboration(1)
},
- card_use_discarded(c) {
- push_undo()
- log(`Discarded #${c} to play #${game.discard}.`)
- let old_c = game.discard
- discard_card(c)
- goto_play_event(old_c)
+ red_momentum() {
+ this.momentum()
+ },
+ blue_momentum() {
+ this.momentum()
+ },
+ card(c) {
+ log(`Discarded for #${c}.`)
+ if (c === game.discard) {
+ discard_card(game.what)
+ game.what = c
+ goto_play_event(c)
+ } else {
+ discard_card(game.what)
+ game.what = c
+ game.state = "play_final"
+ }
+ },
+}
+
+states.play_final = {
+ prompt() {
+ view.prompt = card_names[game.what] + ": Use up to 4 Operations Points."
+ view.selected_card = game.what
+ view.actions.political = 1
+ view.actions.military = 1
+ },
+ political() {
+ discard_final()
+ goto_operations(4, POLITICAL)
+ },
+ military() {
+ discard_final()
+ goto_operations(4, MILITARY)
+ },
+}
+
+function discard_final() {
+ if (game.active === COMMUNE)
+ game.red_final = 0
+ else
+ game.blue_final = 0
+}
+
+// === PLAYER MOMENTUM TRACKS ===
+
+function advance_revolutionary_momentum(x) {
+ game.red_momentum += x
+ for (let i = game.red_momentum; i < 3; ++i)
+ for_each_commune_cube(RED_CUBE_POOL[i], p => game.pieces[p] = -1)
+ game.active = VERSAILLES
+ if (x > 0 && game.red_momentum >= 2)
+ game.state = "revolutionary_momentum_trigger"
+ else
+ end_momentum_trigger()
+}
+
+function advance_prussian_collaboration(x) {
+ game.blue_momentum += x
+ for (let i = 0; i < game.blue_momentum; ++i)
+ for_each_versailles_cube(PRUSSIAN_COLLABORATION[i], p => game.pieces[p] = BLUE_CUBE_POOL)
+ game.active = COMMUNE
+ if (x > 0 && game.blue_momentum >= 2)
+ game.state = "prussian_collaboration_trigger"
+ else
+ end_momentum_trigger()
+}
+
+states.revolutionary_momentum_trigger = {
+ prompt() {
+ view.prompt = "Revolutionary Momentum: Place a cube in an Institutional space."
+ for (let s of INSTITUTIONAL)
+ gen_action_space(s)
+ view.actions.skip = 1
+ },
+ space(s) {
+ place_piece(find_available_cube(), s)
+ end_momentum_trigger()
+ },
+ skip() {
+ end_momentum_trigger()
+ },
+}
+
+states.prussian_collaboration_trigger = {
+ prompt() {
+ view.prompt = "Prussian Collaboration: Place a cube in a Public Opinion space."
+ for (let s of PUBLIC_OPINION)
+ gen_action_space(s)
+ view.actions.skip = 1
+ },
+ space(s) {
+ place_piece(find_available_cube(), s)
+ end_momentum_trigger()
+ },
+ skip() {
+ end_momentum_trigger()
},
}
+function end_momentum_trigger() {
+ game.active = enemy_player()
+ resume_strategy_phase()
+}
+
// === OPERATIONS ===
function goto_operations(count, spaces) {
@@ -805,25 +937,24 @@ function goto_operations(count, spaces) {
}
function goto_final_crisis_discard(c, spaces) {
+ log("Played #" + c + ".")
game.state = "discard_final_crisis"
game.count = 4
game.spaces = spaces
- array_remove_item(player_hand(game.active), c)
}
states.discard_final_crisis = {
inactive: "discard a card to play final crisis",
prompt() {
view.prompt = "Discard a card to play Final Crisis card for ops."
- let hand = player_hand(game.active)
+ let hand = player_hand()
for (let c of hand)
- if (is_strategy_card(c))
- gen_action("card", c)
+ gen_action("card", c)
},
card(c) {
push_undo()
log(`Discarded #${c} to play Final Crisis card for ops.`)
- array_remove_item(player_hand(game.active), c)
+ array_remove_item(player_hand(), c)
game.discard = c
goto_operations_remove()
},
@@ -847,7 +978,7 @@ function can_operations_remove() {
}
function can_operations_remove_space(s) {
- if (is_present(game.active, s) || is_adjacent_to_control(game.active, s)) {
+ if (is_present(s) || is_adjacent_to_control(s)) {
let c = has_enemy_cube(s)
let d = has_enemy_disc(s)
if (c || d) {
@@ -864,11 +995,11 @@ function can_operations_remove_space(s) {
function military_strength(s) {
let str = 0
for (let next of ADJACENT_FROM[s])
- if (is_control(game.active, next))
+ if (is_control(next))
str += 1
- if (is_present(game.active, s))
+ if (is_present(s))
str += 1
- if (is_control(game.active, s))
+ if (is_control(s))
str += 1
return str
}
@@ -989,7 +1120,9 @@ function can_operations_place() {
}
function can_operations_place_space(s) {
- if (is_present(game.active, s) || is_adjacent_to_control(game.active, s)) {
+ if (is_present(s) || is_adjacent_to_control(s)) {
+ if (count_friendly_cubes(s) >= 4)
+ return false
let d = has_enemy_disc(s)
if (!d || game.count >= 2)
return true
@@ -999,7 +1132,7 @@ function can_operations_place_space(s) {
states.operations_place = {
prompt() {
- view.prompt = "Operations: Place cubes into Political spaces."
+ view.prompt = "Operations: Place cubes."
for (let s of game.spaces)
if (can_operations_place_space(s))
gen_action_space(s)
@@ -1045,6 +1178,25 @@ function end_operations() {
resume_strategy_phase()
}
+// === SET ASIDE CARDS ===
+
+function goto_set_aside_cards() {
+ for (let c of game.red_hand)
+ game.red_set_aside.push(c)
+ game.red_hand = []
+
+ for (let c of game.blue_hand)
+ game.blue_set_aside.push(c)
+ game.blue_hand = []
+
+ goto_pivotal_space_bonus_actions()
+}
+
+function goto_pivotal_space_bonus_actions() {
+ game.state = "pivotal_space_bonus_actions"
+ game.active = game.initiative
+}
+
// === EVENTS ===
function goto_play_event(c) {
@@ -1077,13 +1229,15 @@ exports.setup = function (seed, scenario, options) {
objective_deck: [],
discard: 0,
- red_hand: [ 34 ],
- red_final: [],
- red_objective: 0,
+ red_final: 34,
+ red_hand: [],
+ red_set_aside: [],
+ red_objective: [],
- blue_hand: [ 17 ],
- blue_final: [],
- blue_objective: 0,
+ blue_final: 17,
+ blue_hand: [],
+ blue_set_aside: [],
+ blue_objective: [],
presence: 0,
control: 0,
@@ -1105,9 +1259,9 @@ exports.setup = function (seed, scenario, options) {
RED_BONUS_CUBES[1],
RED_BONUS_CUBES[2],
RED_BONUS_CUBES[2],
- S_PRESS,
- S_SOCIAL_MOVEMENTS,
- S_PERE_LACHAISE,
+ PRESS,
+ SOCIAL_MOVEMENTS,
+ PERE_LACHAISE,
// Versailles cubes
BLUE_CRISIS_TRACK[0],
BLUE_CRISIS_TRACK[1],
@@ -1119,14 +1273,14 @@ exports.setup = function (seed, scenario, options) {
BLUE_BONUS_CUBES[1],
BLUE_BONUS_CUBES[2],
BLUE_BONUS_CUBES[2],
- BLUE_CUBE_POOL,
- BLUE_CUBE_POOL,
- BLUE_CUBE_POOL,
- BLUE_CUBE_POOL,
- BLUE_CUBE_POOL,
- BLUE_CUBE_POOL,
- S_ROYALISTS,
- S_PRESS,
+ PRUSSIAN_COLLABORATION[0],
+ PRUSSIAN_COLLABORATION[1],
+ PRUSSIAN_COLLABORATION[1],
+ PRUSSIAN_COLLABORATION[2],
+ PRUSSIAN_COLLABORATION[2],
+ PRUSSIAN_COLLABORATION[2],
+ ROYALISTS,
+ PRESS,
// Commune discs
-1, -1,
// Versailles discs
@@ -1155,14 +1309,14 @@ exports.setup = function (seed, scenario, options) {
if (game.scenario === "Censorship")
n = 5
- for (let i = 0; i < 5; ++i) {
+ for (let i = 0; i < n; ++i) {
game.red_hand.push(game.strategy_deck.pop())
game.blue_hand.push(game.strategy_deck.pop())
}
for (let i = 0; i < 2; ++i) {
- game.red_hand.push(game.objective_deck.pop())
- game.blue_hand.push(game.objective_deck.pop())
+ game.red_objective.push(game.objective_deck.pop())
+ game.blue_objective.push(game.objective_deck.pop())
}
return game
@@ -1197,17 +1351,20 @@ exports.view = function(state, player) {
discard: game.discard,
hand: 0,
final: 0,
+ set_aside: 0,
objective: 0
}
if (player === COMMUNE) {
view.hand = game.red_hand
view.final = game.red_final
+ view.set_aside = game.red_set_aside
view.objective = game.red_objective
}
if (player === VERSAILLES) {
view.hand = game.blue_hand
view.final = game.blue_final
+ view.set_aside = game.blue_set_aside
view.objective = game.blue_objective
}