summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--play.html12
-rw-r--r--play.js26
-rw-r--r--rules.js231
3 files changed, 170 insertions, 99 deletions
diff --git a/play.html b/play.html
index b60fa69..d2975c9 100644
--- a/play.html
+++ b/play.html
@@ -30,6 +30,18 @@ body.Versailles header.your_turn { background-color: skyblue; }
#log .tip { font-style: italic }
#log .tip:hover { cursor: pointer; text-decoration: underline; }
+#log img.c { height: 15px; vertical-align: -3px }
+#log img.d { height: 15px; vertical-align: -3px }
+#log img.m { height: 18px; vertical-align: -5px }
+
+#log .hr {
+ background-color: hsl(40, 50%, 40%);
+ margin: 9px 0;
+ padding: 0;
+ height: 1px;
+ min-height: 0;
+}
+
.role_extra {
float: right;
}
diff --git a/play.js b/play.js
index 62566fc..2e61505 100644
--- a/play.js
+++ b/play.js
@@ -346,6 +346,13 @@ function sub_space_name(match, p1, offset, string) {
return n
}
+const IMG_RC = '<img class="c" src="pieces/red_cube.svg">'
+const IMG_BC = '<img class="c" src="pieces/blue_cube.svg">'
+const IMG_RD = '<img class="d" src="pieces/red_disc.svg">'
+const IMG_BD = '<img class="d" src="pieces/blue_disc.svg">'
+const IMG_RM = '<img class="m" src="pieces/red_cylinder.svg">'
+const IMG_BM = '<img class="m" src="pieces/blue_cylinder.svg">'
+
function on_log(text) {
let p = document.createElement("div")
@@ -360,6 +367,13 @@ function on_log(text) {
text = text.replace(/C(\d+)/g, sub_card_name)
text = text.replace(/S(\d+)/g, sub_space_name)
+ text = text.replace(/\bRC\b/g, IMG_RC)
+ text = text.replace(/\bBC\b/g, IMG_BC)
+ text = text.replace(/\bRD\b/g, IMG_RD)
+ text = text.replace(/\bBD\b/g, IMG_BD)
+ text = text.replace(/\bRM\b/g, IMG_RM)
+ text = text.replace(/\bBM\b/g, IMG_BM)
+
if (text.match(/^\.h1/)) {
text = text.substring(4)
p.className = 'h1'
@@ -377,7 +391,17 @@ function on_log(text) {
if (text.match(/^\.h3/)) {
text = text.substring(4)
- p.className = 'h3'
+ p.className = 'h3'
+ }
+
+ if (text.match(/^\.h4/)) {
+ text = text.substring(4)
+ p.className = 'h4'
+ }
+
+ if (text.match(/^.hr$/)) {
+ p.className = "hr";
+ text = "";
}
p.innerHTML = text
diff --git a/rules.js b/rules.js
index 68c47a4..fa55b52 100644
--- a/rules.js
+++ b/rules.js
@@ -195,7 +195,7 @@ const PARIS = [ BUTTE_MONTMARTRE, BUTTE_AUX_CAILLES, PERE_LACHAISE ]
const PIVOTAL = [ NATIONAL_ASSEMBLY, PRESS, MONT_VALERIEN, BUTTE_MONTMARTRE ]
function is_same_list(a, b) {
- if (a !== b)
+ if (a === b)
return true
if (a.length !== b.length)
return false
@@ -224,7 +224,7 @@ function space_list_name(list) {
return "Paris"
if (is_same_list(list, PIVOTAL))
return "Pivotal"
- return "???"
+ return list.map(s=>space_names[s]).join(", ")
}
const DIMENSION_SPACES = [
@@ -707,6 +707,14 @@ function is_versailles_cube(p) {
return p >= first_versailles_cube && p <= last_versailles_cube
}
+function is_commune_disc(p) {
+ return p >= first_commune_disc && p <= last_commune_disc
+}
+
+function is_versailles_disc(p) {
+ return p >= first_versailles_disc && p <= last_versailles_disc
+}
+
function is_disc(p) {
return p >= 36
}
@@ -963,6 +971,7 @@ function end_choose_objective_card() {
// === INITIATIVE PHASE ===
function goto_initiative_phase() {
+ log_h2("Initiative Phase")
let c_level = commune_political_vp() - game.red_momentum
let v_level = versailles_political_vp() - game.blue_momentum
if (c_level >= v_level)
@@ -1015,7 +1024,7 @@ states.censorship_phase = {
gen_action("card", c)
},
card(c) {
- log(`Discarded C${c}.`)
+ log(game.active + " discarded C" + c + ".")
discard_card(c)
if (game.active === game.initiative)
game.active = enemy_player()
@@ -1028,7 +1037,7 @@ states.censorship_phase = {
function goto_strategy_phase() {
clear_undo()
- log_h2(game.active)
+ log_h2("Strategy Phase")
game.state = "strategy_phase"
}
@@ -1036,8 +1045,10 @@ function resume_strategy_phase() {
if (game.red_hand.length === 1 && game.blue_hand.length === 1) {
goto_set_aside_cards()
} else {
+ log_sep()
+ clear_undo()
game.active = enemy_player()
- goto_strategy_phase()
+ game.state = "strategy_phase"
}
}
@@ -1095,72 +1106,63 @@ states.play_card = {
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 (can_advance_momentum())
+ view.actions.momentum = 1
},
event() {
push_undo()
- log(`Played C${game.what} for Event.`)
+ log_h4(game.active + " - Event")
+ logi("C" + game.what)
discard_card(game.what)
goto_play_event(game.what)
},
political() {
push_undo()
- log(`Played C${game.what} for ${card_ops[game.what]} OP.`)
+ log_h4(game.active + " - Operations")
+ logi("C" + game.what)
discard_card(game.what)
goto_operations(card_ops[game.what], POLITICAL)
},
military() {
push_undo()
- log(`Played C${game.what} for ${card_ops[game.what]} OP.`)
+ log_h4(game.active + " - Operations")
+ logi("C" + game.what)
discard_card(game.what)
goto_operations(card_ops[game.what], MILITARY)
},
momentum() {
push_undo()
+ log_h4(game.active + " - Momentum")
+ logi("C" + game.what)
if (game.censorship)
recycle_card(game.what)
else
discard_card(game.what)
- if (game.active === COMMUNE) {
- log(`Played C${game.what} for Revolutionary Momentum.`)
- advance_revolutionary_momentum1(1)
- game.state = "advance_revolutionary_momentum_done"
- } else {
- log(`Played C${game.what} for Prussian Collaboration.`)
- advance_prussian_collaboration1(1)
- game.state = "advance_prussian_collaboration_done"
- }
- },
- red_momentum() {
- this.momentum()
- },
- blue_momentum() {
- this.momentum()
+ if (game.active === COMMUNE)
+ game.state = "advance_revolutionary_momentum"
+ else
+ game.state = "advance_prussian_collaboration"
},
}
-states.advance_revolutionary_momentum_done = {
+states.advance_revolutionary_momentum = {
prompt() {
- view.prompt = card_names[game.what] + ": All done."
- view.actions.done = 1
+ view.prompt = "Advance Revolutionary Momentum."
+ view.actions.red_momentum = 1
},
- done() {
+ red_momentum() {
+ advance_revolutionary_momentum1(1)
advance_revolutionary_momentum2(1)
},
}
-states.advance_prussian_collaboration_done = {
+states.advance_prussian_collaboration = {
prompt() {
- view.prompt = card_names[game.what] + ": All done."
- view.actions.done = 1
+ view.prompt = "Advance Prussian Collaboration"
+ view.actions.blue_momentum = 1
},
- done() {
+ blue_momentum() {
+ advance_prussian_collaboration1(1)
advance_prussian_collaboration2(1)
},
}
@@ -1174,7 +1176,9 @@ states.play_discard = {
},
card(c) {
push_undo()
- log("Discarded C" + c + " to play C" + game.what + ".")
+ log_h4(game.active + " - Discarded Event")
+ logi("C" + c)
+ logi("C" + game.what)
discard_card(c)
goto_play_event(game.what)
},
@@ -1189,7 +1193,9 @@ states.play_final_discard = {
},
card(c) {
push_undo()
- log("Discarded C" + c + " to play C" + game.what + ".")
+ log_h4(game.active + " - Final Crisis")
+ logi("C" + c)
+ logi("C" + game.what)
discard_final()
discard_card(c)
game.state = "play_final_ops"
@@ -1231,6 +1237,10 @@ function advance_revolutionary_momentum(x) {
function advance_revolutionary_momentum1(x) {
game.red_momentum += x
+ if (x > 0)
+ log("Increased RM to " + game.red_momentum + ".")
+ else
+ log("Decreased RM to " + game.red_momentum + ".")
for (let i = game.red_momentum; i < 3; ++i)
for_each_commune_cube(RED_CUBE_POOL[i], remove_piece_from_play)
}
@@ -1238,10 +1248,12 @@ function advance_revolutionary_momentum1(x) {
function advance_revolutionary_momentum2(x) {
game.momentum_active = game.active
game.active = VERSAILLES
- if (x > 0 && game.red_momentum >= 2 && can_place_cube_in_any(INSTITUTIONAL))
+ if (x > 0 && game.red_momentum >= 2 && can_place_cube_in_any(INSTITUTIONAL)) {
+ clear_undo()
game.state = "revolutionary_momentum_trigger"
- else
+ } else {
end_momentum_trigger()
+ }
}
function advance_prussian_collaboration(x) {
@@ -1251,6 +1263,10 @@ function advance_prussian_collaboration(x) {
function advance_prussian_collaboration1(x) {
game.blue_momentum += x
+ if (x > 0)
+ log("Increased BM to " + game.blue_momentum + ".")
+ else
+ log("Decreased BM to " + game.blue_momentum + ".")
for (let i = 0; i < game.blue_momentum; ++i)
for_each_versailles_cube(PRUSSIAN_COLLABORATION[i], remove_piece)
}
@@ -1258,10 +1274,12 @@ function advance_prussian_collaboration1(x) {
function advance_prussian_collaboration2(x) {
game.momentum_active = game.active
game.active = COMMUNE
- if (x > 0 && game.blue_momentum >= 2 && can_place_cube_in_any(PUBLIC_OPINION))
+ if (x > 0 && game.blue_momentum >= 2 && can_place_cube_in_any(PUBLIC_OPINION)) {
+ clear_undo()
game.state = "prussian_collaboration_trigger"
- else
+ } else {
end_momentum_trigger()
+ }
}
states.revolutionary_momentum_trigger = {
@@ -1273,7 +1291,7 @@ states.revolutionary_momentum_trigger = {
view.actions.pass = 1
},
space(s) {
- log("Placed red cube in S" + s + ".")
+ log("Placed RC in S" + s + ".")
place_cube(s)
end_momentum_trigger()
},
@@ -1291,7 +1309,7 @@ states.prussian_collaboration_trigger = {
view.actions.pass = 1
},
space(s) {
- log("Placed blue cube in S" + s + ".")
+ log("Placed BC in S" + s + ".")
place_cube(s)
end_momentum_trigger()
},
@@ -1332,7 +1350,8 @@ function assess_crisis_breach_all() {
function assess_crisis_breach(side, i, crisis_track, bonus_cubes, start_count, enemy_final_crisis) {
let count = count_cubes(crisis_track)
if (count < start_count && count_cubes(bonus_cubes) > 0) {
- log(side + " Breached " + crisis_names[i] + "!")
+ log_br()
+ log(side + " breached " + crisis_names[i] + "!")
if (enemy_final_crisis) {
if (count_cubes(enemy_final_crisis) === 2) {
for_each_cube(bonus_cubes, remove_piece)
@@ -1396,10 +1415,16 @@ function military_strength(s) {
return str
}
+function piece_abbr(p) {
+ if (is_commune_cube(p)) return "RC"
+ if (is_versailles_cube(p)) return "BC"
+ if (is_commune_disc(p)) return "RD"
+ if (is_versailles_disc(p)) return "BD"
+}
+
states.operations_remove = {
prompt() {
let prompt = "Use " + game.count + " OP in " + space_list_name(game.spaces) + " to remove."
- //let prompt = "Use " + game.count + " OP to remove in " + space_list_name(game.spaces) + "."
if (game.vm)
event_prompt(prompt)
else
@@ -1417,6 +1442,7 @@ states.operations_remove = {
piece(p) {
push_undo()
let s = game.pieces[p]
+ let pn = piece_abbr(p)
if (has_enemy_disc(s))
game.count -= 2
@@ -1426,16 +1452,16 @@ states.operations_remove = {
if (is_military_space(s)) {
let str = military_strength(s)
if (str >= 3) {
- logi("Remove from S" + s + ".")
+ logi("Remove " + pn + " from S" + s + ".")
remove_piece(p)
resume_operations_remove()
} else {
- log("Remove from S" + s + ":")
+ log("Remove " + pn + " from S" + s + ".")
game.who = p
game.state = "operations_remove_spend"
}
} else {
- log("Removed from S" + s + ".")
+ log("Removed " + pn + " from S" + s + ".")
remove_piece(p)
resume_operations_remove()
}
@@ -1537,7 +1563,6 @@ function can_operations_place_space(s) {
states.operations_place = {
prompt() {
- //let prompt = "Use " + game.count + " OP to place in " + space_list_name(game.spaces) + "."
let prompt = "Use " + game.count + " OP in " + space_list_name(game.spaces) + " to place."
if (game.vm)
event_prompt(prompt)
@@ -1554,7 +1579,10 @@ states.operations_place = {
game.count -= 2
else
game.count -= 1
- log("Placed in S" + s + ".")
+ if (game.active === COMMUNE)
+ log("Placed RC in S" + s + ".")
+ else
+ log("Placed BC in S" + s + ".")
place_cube(s)
resume_operations_place()
},
@@ -1569,15 +1597,15 @@ function resume_operations_place() {
}
function goto_operations_done() {
- game.state = "operations_done"
+ if (game.vm)
+ end_operations()
+ else
+ game.state = "operations_done"
}
states.operations_done = {
prompt() {
- if (game.vm)
- event_prompt("Finished Operations in " + space_list_name(game.spaces) + ".")
- else
- view.prompt = "Operations: All done."
+ view.prompt = "Operations: All done."
view.actions.done = 1
},
done() {
@@ -1586,14 +1614,10 @@ states.operations_done = {
}
function end_operations() {
- if (game.vm) {
+ if (game.vm)
vm_next()
- // Fast-forward past "All done" if Ops was the last thing in an event.
- if (game.state === "vm_return")
- end_event()
- } else {
+ else
end_card_play()
- }
}
// === SET ASIDE CARDS ===
@@ -1666,23 +1690,23 @@ states.bonus_action = {
},
de_escalate() {
push_undo()
- log("De-escalated")
+ log_h4(game.active + " - De-escalated")
game.state = "de_escalate_1"
},
spread_influence() {
push_undo()
- log("Spread Influence")
+ log_h4(game.active + " - Spread Influence")
game.who = -1
game.count = 2
game.state = "spread_influence"
},
turncoat() {
push_undo()
- log("Turncoat")
+ log_h4(game.active + " - Turncoat")
game.state = "turncoat"
},
pass() {
- log("Passed")
+ log_h4(game.active + " - Passed")
resume_pivotal_space_bonus_actions()
},
}
@@ -1697,10 +1721,7 @@ states.de_escalate_1 = {
piece(p) {
push_undo()
let s = game.pieces[p]
- if (is_commune_cube(p))
- logi("Commune S" + s)
- else
- logi("Versailles S" + s)
+ log("Removed " + piece_abbr(p) + " from S" + s + ".")
remove_piece(p)
game.state = "de_escalate_2"
},
@@ -1718,10 +1739,7 @@ states.de_escalate_2 = {
piece(p) {
push_undo()
let s = game.pieces[p]
- if (is_commune_cube(p))
- logi("Commune S" + s)
- else
- logi("Versailles S" + s)
+ log("Removed " + piece_abbr(p) + " from S" + s + ".")
remove_piece(p)
resume_pivotal_space_bonus_actions()
},
@@ -1749,7 +1767,7 @@ states.spread_influence = {
},
space(s) {
let from = game.pieces[game.who]
- logi("S" + from + " to S" + s)
+ log("Moved " + piece_abbr(game.who) + " from S" + from + " to S" + s + ".")
move_piece(game.who, s)
game.who = -1
if (--game.count === 0)
@@ -1770,7 +1788,7 @@ states.turncoat = {
piece(p) {
let s = game.pieces[p]
push_undo()
- logi("Replaced in S" + s)
+ log("Replaced " + piece_abbr(p) + " in S" + s + ".")
replace_cube(p)
resume_pivotal_space_bonus_actions()
},
@@ -1890,6 +1908,7 @@ function resume_objective_card_events() {
let c = commune_objective_card()
let v = versailles_objective_card()
if (c || v) {
+ game.active = game.initiative
game.state = "objective_card_events"
} else {
delete game.reveal_objectives
@@ -1914,16 +1933,18 @@ states.objective_card_events = {
game.red_objective = 0
game.red_fulfilled += 1
game.active = COMMUNE
- log_br()
- log("Commune played C" + c + ".")
+ log_sep()
+ log("Commune - Objective")
+ logi("C" + c)
goto_play_event(c)
}
if (c === versailles_objective_card()) {
game.blue_objective = 0
game.blue_fulfilled += 1
game.active = VERSAILLES
- log_br()
- log("Versailles played C" + c + ".")
+ log_sep()
+ log("Versailles - Objective")
+ logi("C" + c)
goto_play_event(c)
}
},
@@ -2438,7 +2459,6 @@ states.vm_increase_revolutionary_momentum = {
},
red_momentum() {
push_undo()
- log("Revolutionary Momentum.")
advance_revolutionary_momentum(1)
},
}
@@ -2450,7 +2470,6 @@ states.vm_increase_prussian_collaboration = {
},
blue_momentum() {
push_undo()
- log("Prussian Collaboration.")
advance_prussian_collaboration(1)
},
}
@@ -2462,7 +2481,6 @@ states.vm_decrease_revolutionary_momentum = {
},
red_momentum() {
push_undo()
- log("Decreased Revolutionary Momentum.")
advance_revolutionary_momentum(-1)
},
}
@@ -2474,7 +2492,6 @@ states.vm_decrease_prussian_collaboration = {
},
blue_momentum() {
push_undo()
- log("Decreased Prussian Collaboration.")
advance_prussian_collaboration(-1)
},
}
@@ -2505,7 +2522,10 @@ states.vm_place = {
space(s) {
push_undo()
place_cube(s, game.vm.removed)
- log("Placed in S" + s + ".")
+ if (game.active === COMMUNE)
+ log("Placed RC in S" + s + ".")
+ else
+ log("Placed BC in S" + s + ".")
if (--game.vm.count === 0 || !can_vm_place(game.vm.removed))
vm_next()
},
@@ -2548,9 +2568,9 @@ states.vm_move_disc = {
piece(p) {
push_undo()
if (game.current === COMMUNE)
- log("Moved Barricade from S" + s + ".")
+ log("Moved RD from S" + s + ".")
else
- log("Moved Fortification from S" + s + ".")
+ log("Moved BD from S" + s + ".")
remove_piece(p)
game.state = "vm_place_disc"
},
@@ -2572,9 +2592,9 @@ states.vm_place_disc = {
space(s) {
push_undo()
if (game.current === COMMUNE)
- log("Placed Barricade in S" + s + ".")
+ log("Placed RD in S" + s + ".")
else
- log("Placed Fortification in S" + s + ".")
+ log("Placed BD in S" + s + ".")
place_disc(s)
vm_next()
},
@@ -2611,7 +2631,7 @@ states.vm_replace = {
push_undo()
let s = game.pieces[p]
replace_cube(p)
- log("Replaced in S" + s + ".")
+ log("Replaced " + piece_abbr(p) + " in S" + s + ".")
if (--game.vm.count === 0 || !can_vm_replace())
vm_next()
},
@@ -2647,7 +2667,10 @@ states.vm_remove = {
piece(p) {
push_undo()
let s = game.pieces[p]
- log("Removed from S" + s + ".")
+ if (game.active === COMMUNE)
+ log("Removed BC from S" + s + ".")
+ else
+ log("Removed RC from S" + s + ".")
remove_piece(p)
if (--game.vm.count === 0 || !can_vm_remove())
vm_next()
@@ -2667,7 +2690,10 @@ states.vm_remove_own = {
piece(p) {
push_undo()
let s = game.pieces[p]
- log("Removed own from S" + s + ".")
+ if (game.active === COMMUNE)
+ log("Removed RC from S" + s + ".")
+ else
+ log("Removed BC from S" + s + ".")
remove_piece(p)
vm_next()
},
@@ -2713,9 +2739,9 @@ states.vm_move = {
game.who = p
},
space(s) {
- let old_s = game.pieces[game.who]
+ let from = game.pieces[game.who]
move_piece(game.who, s)
- log("Moved from S" + old_s + " to S" + s + ".")
+ log("Moved " + piece_abbr(game.who) + " from S" + from + " to S" + s + ".")
game.who = -1
if (--game.vm.count === 0 || !can_vm_move())
vm_next()
@@ -2762,7 +2788,7 @@ states.general_louis_valentin = {
push_undo()
let s = game.pieces[p]
array_remove_item(game.vm.spaces, s)
- log("Removed from S" + s + ".")
+ log("Removed RC from S" + s + ".")
remove_piece(p)
if (--game.vm.count === 0 || !can_vm_remove())
vm_next()
@@ -2784,7 +2810,7 @@ states.pius_ix = {
let s = game.pieces[p]
array_remove_item(game.vm.spaces, s)
replace_cube(p)
- log("Replaced in S" + s + ".")
+ log("Replaced " + piece_abbr(p) + " in S" + s + ".")
if (--game.vm.count === 0 || !can_vm_replace())
vm_next()
},
@@ -3182,6 +3208,15 @@ function log_h3(msg) {
log_br()
}
+function log_h4(msg) {
+ log_br()
+ log(".h4 " + msg)
+}
+
+function log_sep() {
+ log(".hr")
+}
+
// === COMMON LIBRARY ===
function clear_undo() {