diff options
-rw-r--r-- | images/blue_cube.svg (renamed from pieces/blue_cube.svg) | 0 | ||||
-rw-r--r-- | images/blue_cylinder.svg (renamed from pieces/blue_cylinder.svg) | 0 | ||||
-rw-r--r-- | images/blue_disc.svg (renamed from pieces/blue_disc.svg) | 0 | ||||
-rw-r--r-- | images/icon_forts.svg (renamed from space_forts.svg) | 0 | ||||
-rw-r--r-- | images/icon_institutional.svg (renamed from space_institutional.svg) | 0 | ||||
-rw-r--r-- | images/icon_paris.svg (renamed from space_paris.svg) | 0 | ||||
-rw-r--r-- | images/icon_public_opinion.svg (renamed from space_public_opinion.svg) | 0 | ||||
-rw-r--r-- | images/orange_cylinder.svg (renamed from pieces/orange_cylinder.svg) | 0 | ||||
-rw-r--r-- | images/pawn.svg (renamed from pieces/pawn.svg) | 0 | ||||
-rw-r--r-- | images/pivotal_forts.svg | 4 | ||||
-rw-r--r-- | images/pivotal_institutional.svg | 4 | ||||
-rw-r--r-- | images/pivotal_paris.svg | 4 | ||||
-rw-r--r-- | images/pivotal_public_opinion.svg | 4 | ||||
-rw-r--r-- | images/pivotal_selected.svg | 4 | ||||
-rw-r--r-- | images/purple_cylinder.svg (renamed from pieces/purple_cylinder.svg) | 0 | ||||
-rw-r--r-- | images/red_cube.svg (renamed from pieces/red_cube.svg) | 0 | ||||
-rw-r--r-- | images/red_cylinder.svg (renamed from pieces/red_cylinder.svg) | 0 | ||||
-rw-r--r-- | images/red_disc.svg (renamed from pieces/red_disc.svg) | 0 | ||||
-rw-r--r-- | play.css | 85 | ||||
-rw-r--r-- | play.js | 144 | ||||
-rw-r--r-- | rules.js | 41 |
21 files changed, 215 insertions, 75 deletions
diff --git a/pieces/blue_cube.svg b/images/blue_cube.svg index 44a7753..44a7753 100644 --- a/pieces/blue_cube.svg +++ b/images/blue_cube.svg diff --git a/pieces/blue_cylinder.svg b/images/blue_cylinder.svg index 9442877..9442877 100644 --- a/pieces/blue_cylinder.svg +++ b/images/blue_cylinder.svg diff --git a/pieces/blue_disc.svg b/images/blue_disc.svg index 5a2dae5..5a2dae5 100644 --- a/pieces/blue_disc.svg +++ b/images/blue_disc.svg diff --git a/space_forts.svg b/images/icon_forts.svg index 11f32e8..11f32e8 100644 --- a/space_forts.svg +++ b/images/icon_forts.svg diff --git a/space_institutional.svg b/images/icon_institutional.svg index 3255365..3255365 100644 --- a/space_institutional.svg +++ b/images/icon_institutional.svg diff --git a/space_paris.svg b/images/icon_paris.svg index a881efd..a881efd 100644 --- a/space_paris.svg +++ b/images/icon_paris.svg diff --git a/space_public_opinion.svg b/images/icon_public_opinion.svg index a3d6cca..a3d6cca 100644 --- a/space_public_opinion.svg +++ b/images/icon_public_opinion.svg diff --git a/pieces/orange_cylinder.svg b/images/orange_cylinder.svg index fe1e9e9..fe1e9e9 100644 --- a/pieces/orange_cylinder.svg +++ b/images/orange_cylinder.svg diff --git a/pieces/pawn.svg b/images/pawn.svg index b722211..b722211 100644 --- a/pieces/pawn.svg +++ b/images/pawn.svg diff --git a/images/pivotal_forts.svg b/images/pivotal_forts.svg new file mode 100644 index 0000000..9b2e08b --- /dev/null +++ b/images/pivotal_forts.svg @@ -0,0 +1,4 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="158" height="158"> +<path fill-opacity="0.5" fill="hsl(175,32%,85%)" stroke="hsl(175,32%,85%)" stroke-width="4" + d="m 79 9 21 21 29 0 0 29 21 21 -21 21 0 29 -29 0 -21 21 -21 -21 -29 0 0 -29 -21 -21 21 -21 0 -29 29 0 z" /> +</svg> diff --git a/images/pivotal_institutional.svg b/images/pivotal_institutional.svg new file mode 100644 index 0000000..df73c9d --- /dev/null +++ b/images/pivotal_institutional.svg @@ -0,0 +1,4 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="158" height="158"> +<path fill-opacity="0.5" fill="hsl(78,64%,85%)" stroke="hsl(78,64%,85%)" stroke-width="4" + d="m 79 9 21 21 29 0 0 29 21 21 -21 21 0 29 -29 0 -21 21 -21 -21 -29 0 0 -29 -21 -21 21 -21 0 -29 29 0 z" /> +</svg> diff --git a/images/pivotal_paris.svg b/images/pivotal_paris.svg new file mode 100644 index 0000000..92d1b04 --- /dev/null +++ b/images/pivotal_paris.svg @@ -0,0 +1,4 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="158" height="158"> +<path fill-opacity="0.5" fill="hsl(275,40%,85%)" stroke="hsl(275,40%,85%)" stroke-width="4" + d="m 79 9 21 21 29 0 0 29 21 21 -21 21 0 29 -29 0 -21 21 -21 -21 -29 0 0 -29 -21 -21 21 -21 0 -29 29 0 z" /> +</svg> diff --git a/images/pivotal_public_opinion.svg b/images/pivotal_public_opinion.svg new file mode 100644 index 0000000..60df1e7 --- /dev/null +++ b/images/pivotal_public_opinion.svg @@ -0,0 +1,4 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="158" height="158"> +<path fill-opacity="0.5" fill="hsl(34,80%,85%)" stroke="hsl(34,80%,85%)" stroke-width="4" + d="m 79 9 21 21 29 0 0 29 21 21 -21 21 0 29 -29 0 -21 21 -21 -21 -29 0 0 -29 -21 -21 21 -21 0 -29 29 0 z" /> +</svg> diff --git a/images/pivotal_selected.svg b/images/pivotal_selected.svg new file mode 100644 index 0000000..0b54c9c --- /dev/null +++ b/images/pivotal_selected.svg @@ -0,0 +1,4 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="158" height="158"> +<path fill="none" stroke="yellow" stroke-width="4" stroke-dasharray="8 8" + d="m 79 9 21 21 29 0 0 29 21 21 -21 21 0 29 -29 0 -21 21 -21 -21 -29 0 0 -29 -21 -21 21 -21 0 -29 29 0 z" /> +</svg> diff --git a/pieces/purple_cylinder.svg b/images/purple_cylinder.svg index 7e2dc0d..7e2dc0d 100644 --- a/pieces/purple_cylinder.svg +++ b/images/purple_cylinder.svg diff --git a/pieces/red_cube.svg b/images/red_cube.svg index 9ca9807..9ca9807 100644 --- a/pieces/red_cube.svg +++ b/images/red_cube.svg diff --git a/pieces/red_cylinder.svg b/images/red_cylinder.svg index 929dad8..929dad8 100644 --- a/pieces/red_cylinder.svg +++ b/images/red_cylinder.svg diff --git a/pieces/red_disc.svg b/images/red_disc.svg index aa4d319..aa4d319 100644 --- a/pieces/red_disc.svg +++ b/images/red_disc.svg @@ -136,12 +136,47 @@ body.censorship #hand_panel { width: clamp(290px, 1370px, 100%) } background-color: #fff8; } +.space.institutional.action { + border: 4px solid hsl(78, 64%, 85%); + background-color: hsl(78, 64%, 85%, 0.5); +} + +.space.public_opinion.action { + border: 4px solid hsl(34, 80%, 85%); + background-color: hsl(34, 80%, 85%, 0.5); +} + +.space.forts.action { + border: 4px solid hsl(175, 32%, 85%); + background-color: hsl(175, 32%, 85%, 0.5); +} + +.space.paris.action { + border: 4px solid hsl(275, 40%, 85%); + background-color: hsl(275, 40%, 85%, 0.5); +} + +.space.pivotal.action { + border: none; + border-radius: 50%; + background-color: transparent; +} + +.space.pivotal.action.institutional { background-image: url(images/pivotal_institutional.svg) } +.space.pivotal.action.public_opinion { background-image: url(images/pivotal_public_opinion.svg) } +.space.pivotal.action.forts { background-image: url(images/pivotal_forts.svg) } +.space.pivotal.action.paris { background-image: url(images/pivotal_paris.svg) } + .space.selected { border: 4px dashed yellow; } +.space.pivotal.selected { + border: none; + background-image: url(images/pivotal_selected.svg); +} + .piece { - pointer-events: none; position: absolute; background-size: cover; background-repeat: no-repeat; @@ -151,6 +186,10 @@ body.censorship #hand_panel { width: clamp(290px, 1370px, 100%) } transition-timing-function: ease; } +.piece.cube { + pointer-events: none; +} + .piece.action { pointer-events: auto; filter: @@ -160,7 +199,7 @@ body.censorship #hand_panel { width: clamp(290px, 1370px, 100%) } drop-shadow(2px 0 0 white) } -.piece.selected { +.piece.red.action { filter: drop-shadow(0 -2px 0 yellow) drop-shadow(0 2px 0 yellow) @@ -168,6 +207,30 @@ body.censorship #hand_panel { width: clamp(290px, 1370px, 100%) } drop-shadow(2px 0 0 yellow) } +.piece.blue.action { + filter: + drop-shadow(0 -2px 0 cyan) + drop-shadow(0 2px 0 cyan) + drop-shadow(-2px 0 0 cyan) + drop-shadow(2px 0 0 cyan) +} + +.piece.red.selected { + filter: + drop-shadow(0 -2px 0 gold) + drop-shadow(0 2px 0 gold) + drop-shadow(-2px 0 0 gold) + drop-shadow(2px 0 0 gold) +} + +.piece.blue.selected { + filter: + drop-shadow(0 -2px 0 mediumturquoise) + drop-shadow(0 2px 0 mediumturquoise) + drop-shadow(-2px 0 0 mediumturquoise) + drop-shadow(2px 0 0 mediumturquoise) +} + .card.action { box-shadow: 0 0 0 3px white; } @@ -181,15 +244,15 @@ body.censorship #hand_panel { width: clamp(290px, 1370px, 100%) } .piece.cylinder { width: 50px; height: 50px; } .piece.pawn { width: 35px; height: 60px; } -.piece.cube.red { background-image:url(pieces/red_cube.svg) } -.piece.cube.blue { background-image:url(pieces/blue_cube.svg) } -.piece.disc.red { background-image:url(pieces/red_disc.svg) } -.piece.disc.blue { background-image:url(pieces/blue_disc.svg) } -.piece.cylinder.red { background-image:url(pieces/red_cylinder.svg) } -.piece.cylinder.blue { background-image:url(pieces/blue_cylinder.svg) } -.piece.cylinder.orange { background-image:url(pieces/orange_cylinder.svg) } -.piece.cylinder.purple { background-image:url(pieces/purple_cylinder.svg) } -.piece.pawn { background-image:url(pieces/pawn.svg) } +.piece.cube.red { background-image:url(images/red_cube.svg) } +.piece.cube.blue { background-image:url(images/blue_cube.svg) } +.piece.disc.red { background-image:url(images/red_disc.svg) } +.piece.disc.blue { background-image:url(images/blue_disc.svg) } +.piece.cylinder.red { background-image:url(images/red_cylinder.svg) } +.piece.cylinder.blue { background-image:url(images/blue_cylinder.svg) } +.piece.cylinder.orange { background-image:url(images/orange_cylinder.svg) } +.piece.cylinder.purple { background-image:url(images/purple_cylinder.svg) } +.piece.pawn { background-image:url(images/pawn.svg) } #round_marker { top: 965px; } #round_marker.round1 { left: 623px; } @@ -119,10 +119,10 @@ const space_count = space_names.length const boxes = { "Royalists": [80,428,126,126], "Republicans": [490,428,126,126], - "Catholic Church": [80,786,126,126], - "Social Movements": [490,786,126,126], + "Catholic Church": [80,787,126,126], + "Social Movements": [490,787,126,126], "Fort d'Issy": [844,793,126,126], - "Butte-Aux-Cailles": [1038,660,126,126], + "Butte-Aux-Cailles": [1038,661,126,126], "Père Lachaise": [1206,591,126,126], "Château de Vincennes": [1342,650,126,127], "Press": [294,727,112,112], @@ -131,29 +131,34 @@ const boxes = { "Mont-Valérien": [717,507,112,112], "Versailles HQ": [662,850,101,95], "Prussian Occupied Territory": [1298,353,180,86], - "Red Crisis Track Start": [982,61,90,112], - "Red Crisis Track Escalation": [1072,61,84,112], - "Red Crisis Track Tension": [1156,61,83,112], - "Red Crisis Track Final Crisis": [1239,61,83,112], - "Blue Crisis Track Start": [432,61,88,112], - "Blue Crisis Track Escalation": [348,61,84,112], - "Blue Crisis Track Tension": [265,61,83,112], - "Blue Crisis Track Final Crisis": [182,61,83,112], + "Blue Objective Card": [120,996,272,54], "Red Objective Card": [1114,996,272,54], + "Blue Cube Pool": [180,198,198,55], - "Red Bonus Cubes 1": [1072,22,84,39], - "Red Bonus Cubes 2": [1156,22,83,39], - "Red Bonus Cubes 3": [1239,22,83,39], - "Blue Bonus Cubes 1": [348,22,84,39], - "Blue Bonus Cubes 2": [265,22,83,39], - "Blue Bonus Cubes 3": [182,22,83,39], - "Red Cube Pool 1": [787,330,115,39], - "Red Cube Pool 2": [902,330,136,39], - "Red Cube Pool 3": [1038,330,157,40], - "Prussian Collaboration 1": [600,330,115,39], - "Prussian Collaboration 2": [463,330,136,39], - "Prussian Collaboration 3": [306,330,157,39], + + "Red Crisis Track Start": [982,70,90,112], + "Red Crisis Track Escalation": [1072,70,84,112], + "Red Crisis Track Tension": [1156,70,84,112], + "Red Crisis Track Final Crisis": [1239,70,84,112], + "Blue Crisis Track Start": [432,70,88,112], + "Blue Crisis Track Escalation": [348,70,84,112], + "Blue Crisis Track Tension": [265,70,84,112], + "Blue Crisis Track Final Crisis": [182,70,84,112], + + "Red Bonus Cubes 1": [1072,20,84,40], + "Red Bonus Cubes 2": [1156,20,84,40], + "Red Bonus Cubes 3": [1239,20,84,40], + "Blue Bonus Cubes 1": [348,23,84,40], + "Blue Bonus Cubes 2": [265,23,84,40], + "Blue Bonus Cubes 3": [182,20,84,40], + + "Red Cube Pool 1": [787,340,115,40], + "Red Cube Pool 2": [902,340,100,40], + "Red Cube Pool 3": [1038,340,157,40], + "Prussian Collaboration 1": [600,340,115,40], + "Prussian Collaboration 2": [463,340,100,40], + "Prussian Collaboration 3": [306,340,140,40], } function is_action(action) { @@ -188,6 +193,11 @@ function on_focus_space(evt) { document.getElementById("status").textContent = evt.target.my_name } +function on_focus_piece(evt) { + if (evt.target.my_name) + document.getElementById("status").textContent = evt.target.my_name +} + function on_click_red_momentum(evt) { if (evt.button === 0) { if (send_action('red_momentum')) @@ -237,11 +247,34 @@ function create(t, p, ...c) { return e } +const DIMENSION_CLASS = [ + "institutional", "institutional", "institutional", + "public_opinion", "public_opinion", "public_opinion", + "forts", "forts", "forts", + "paris", "paris", "paris", +] + + function build_user_interface() { let elt - document.getElementById("red_momentum").addEventListener("mousedown", on_click_red_momentum) - document.getElementById("blue_momentum").addEventListener("mousedown", on_click_blue_momentum) + ui.red_momentum.my_name = "Revolutionary Momentum" + ui.red_momentum.onmousedown = on_click_red_momentum + ui.red_momentum.onmouseenter = on_focus_piece + ui.red_momentum.onmouseleave = on_blur + + ui.blue_momentum.my_name = "Prussian Collaboration" + ui.blue_momentum.onmousedown = on_click_blue_momentum + ui.blue_momentum.onmouseenter = on_focus_piece + ui.blue_momentum.onmouseleave = on_blur + + ui.political_vp.my_name = "Political VP" + ui.political_vp.onmouseenter = on_focus_piece + ui.political_vp.onmouseleave = on_blur + + ui.military_vp.my_name = "Military VP" + ui.military_vp.onmouseenter = on_focus_piece + ui.military_vp.onmouseleave = on_blur ui.objective_back = [ create("div", { className: "card card_objective_back" }), @@ -276,20 +309,35 @@ function build_user_interface() { document.getElementById("pieces").appendChild(elt) } - for (let i = 0; i < space_count; ++i) { - let name = space_names[i] + for (let s = 0; s < space_count; ++s) { + let name = space_names[s] let [x, y, w, h] = boxes[name] - elt = ui.spaces[i] = create("div", { - className: "space", - my_space: i, + let cn = "space" + if (s < 12) + cn += " " + DIMENSION_CLASS[s] + if (s === 0 || s === 3 || s === 6 || s === 9) { + cn += " pivotal" + x -= 22 + y -= 23 + w += 46 + h += 46 + } else { + x += 5 + y += 5 + w -= 10 + h -= 10 + } + elt = ui.spaces[s] = create("div", { + className: cn, + my_space: s, my_name: name, onmousedown: on_click_space, onmouseenter: on_focus_space, onmouseleave: on_blur, style: `top: ${y-1}px;left:${x-1}px;width:${w+2}px;height:${h+2}px` }) - space_layout_cube[i] = { x: x + Math.round(w/2), y: y + Math.round(h*1/2) } - space_layout_disc[i] = { x: x + w, y: y + h } + space_layout_cube[s] = { x: x + Math.round(w/2), y: y + Math.round(h*1/2) } + space_layout_disc[s] = { x: x + w, y: y + h } document.getElementById("spaces").appendChild(elt) } } @@ -355,35 +403,35 @@ function sub_space_name(match, p1, offset, string) { } if (true) { if (c <= 2) - return '<img class="s" src="space_institutional.svg">' + n + return '<img class="s" src="images/icon_institutional.svg">' + n if (c <= 5) - return '<img class="s" src="space_public_opinion.svg">' + n + return '<img class="s" src="images/icon_public_opinion.svg">' + n if (c <= 8) - return '<img class="s" src="space_forts.svg">' + n + return '<img class="s" src="images/icon_forts.svg">' + n if (c <= 11) - return '<img class="s" src="space_paris.svg">' + n + return '<img class="s" src="images/icon_paris.svg">' + n } if (true) { if (c <= 2) - return '<span class="institutional"><img class="s" src="space_institutional.svg">' + n + "</span>" + return '<span class="institutional"><img class="s" src="images/icon_institutional.svg">' + n + "</span>" if (c <= 5) - return '<span class="public_opinion"><img class="s" src="space_public_opinion.svg">' + n + "</span>" + return '<span class="public_opinion"><img class="s" src="images/icon_public_opinion.svg">' + n + "</span>" if (c <= 8) - return '<span class="forts"><img class="s" src="space_forts.svg">' + n + "</span>" + return '<span class="forts"><img class="s" src="images/icon_forts.svg">' + n + "</span>" if (c <= 11) - return '<span class="paris"><img class="s" src="space_paris.svg">' + n + "</span>" + return '<span class="paris"><img class="s" src="images/icon_paris.svg">' + n + "</span>" } 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">' -const IMG_MV = '<img class="m" src="pieces/purple_cylinder.svg">' -const IMG_PV = '<img class="m" src="pieces/orange_cylinder.svg">' +const IMG_RC = '<img class="c" src="images/red_cube.svg">' +const IMG_BC = '<img class="c" src="images/blue_cube.svg">' +const IMG_RD = '<img class="d" src="images/red_disc.svg">' +const IMG_BD = '<img class="d" src="images/blue_disc.svg">' +const IMG_RM = '<img class="m" src="images/red_cylinder.svg">' +const IMG_BM = '<img class="m" src="images/blue_cylinder.svg">' +const IMG_MV = '<img class="m" src="images/purple_cylinder.svg">' +const IMG_PV = '<img class="m" src="images/orange_cylinder.svg">' function on_log(text) { let p = document.createElement("div") @@ -1502,52 +1502,61 @@ function end_versailles_crisis_breach() { } states.commune_crisis_breach = { - inactive: "add cubes to Pool", + inactive: "move bonus cubes", prompt() { - view.prompt = "Crisis Breach: Add cubes to Pool." + view.prompt = "Crisis Breach: Move bonus cubes to Pool." if (count_commune_cubes(RED_CRISIS_TRACK[1]) < 2) for_each_commune_cube(RED_BONUS_CUBES[0], gen_action_piece) if (count_commune_cubes(RED_CRISIS_TRACK[2]) < 2) for_each_commune_cube(RED_BONUS_CUBES[1], gen_action_piece) - if (count_commune_cubes(RED_CRISIS_TRACK[3]) < 2) - for_each_commune_cube(RED_BONUS_CUBES[2], gen_action_piece) + if (count_commune_cubes(RED_CRISIS_TRACK[3]) < 2) { + if (count_versailles_cubes(BLUE_BONUS_CUBES[2]) > 0) { + view.prompt = "Crisis Breach: Remove bonus cubes." + for_each_versailles_cube(BLUE_BONUS_CUBES[2], gen_action_piece) + } else + for_each_commune_cube(RED_BONUS_CUBES[2], gen_action_piece) + } }, piece(p) { - if (p === RED_BONUS_CUBES[2] && !is_commune_first_to_breach_final()) { + if (is_versailles_cube(p)) { remove_piece_from_play(p) - log("Removed RC from bonus.") + log("Removed BC from bonus.") } else { remove_piece(p) if (game.pieces[p] < 0) log("Removed RC from bonus.") else log("Added RC to Pool.") + goto_commune_crisis_breach() } - goto_commune_crisis_breach() }, } states.versailles_crisis_breach = { - inactive: "add cubes to Pool", + inactive: "move bonus cubes", prompt() { - view.prompt = "Crisis Breach: Add cubes to Pool." + view.prompt = "Crisis Breach: Move bonus cubes to Pool." if (count_versailles_cubes(BLUE_CRISIS_TRACK[1]) < 2) for_each_versailles_cube(BLUE_BONUS_CUBES[0], gen_action_piece) if (count_versailles_cubes(BLUE_CRISIS_TRACK[2]) < 1) for_each_versailles_cube(BLUE_BONUS_CUBES[1], gen_action_piece) - if (count_versailles_cubes(BLUE_CRISIS_TRACK[3]) < 2) - for_each_versailles_cube(BLUE_BONUS_CUBES[2], gen_action_piece) + if (count_versailles_cubes(BLUE_CRISIS_TRACK[3]) < 2) { + if (count_commune_cubes(RED_BONUS_CUBES[2]) > 0) { + view.prompt = "Crisis Breach: Remove opponent's bonus cubes." + for_each_commune_cube(RED_BONUS_CUBES[2], gen_action_piece) + } else + for_each_versailles_cube(BLUE_BONUS_CUBES[2], gen_action_piece) + } }, piece(p) { - let s = game.pieces[p] - if (s === BLUE_BONUS_CUBES[2] && !is_versailles_first_to_breach_final()) { + if (is_commune_cube(p)) { remove_piece_from_play(p) - log("Removed BC from bonus.") + log("Removed RC from bonus.") } else { remove_piece(p) log("Added BC to Pool.") + goto_versailles_crisis_breach() } - goto_versailles_crisis_breach() }, } @@ -3216,7 +3225,7 @@ exports.setup = function (seed, scenario, options) { strategy_deck: [], objective_deck: [], - discard: 0, + discard: [], red_final: 34, red_hand: [], |