diff options
-rw-r--r-- | play.html | 12 | ||||
-rw-r--r-- | play.js | 26 | ||||
-rw-r--r-- | rules.js | 231 |
3 files changed, 170 insertions, 99 deletions
@@ -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; } @@ -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 @@ -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() { |