summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--play.css214
-rw-r--r--play.html25
-rw-r--r--play.js132
-rw-r--r--rules.js221
4 files changed, 316 insertions, 276 deletions
diff --git a/play.css b/play.css
index 95fe951..76fc72e 100644
--- a/play.css
+++ b/play.css
@@ -11,6 +11,7 @@
#prompt {
font-family: "Suit Symbols", var(--font-widget);
font-variant-numeric: tabular-nums;
+ white-space: wrap;
}
body {
@@ -39,13 +40,12 @@ body {
#political_display {
position: relative;
- margin: 0 auto;
width: 877px;
height: 620px;
background-size: cover;
background-image: url(Maria.Political.Display.075.jpg);
background-color: #ece1a9;
- box-shadow: 2px 2px 4px #0006;
+ Xbox-shadow: 2px 2px 4px #0006;
border: 1px solid #0008;
}
@@ -77,34 +77,29 @@ svg .main_road {
--color-light-bavaria: hsl(36, 70%, 80%);
--color-light-prussia: hsl(210, 80%, 75%);
--color-light-saxony: hsl(140, 50%, 70%);
- --color-light-pragmatic: hsl(0, 0%, 75%);
+ --color-light-pragmatic: hsl(264, 10%, 75%);
--color-light-austria: hsl(0, 0%, 97%);
--color-light-political: hsl(50, 73%, 78%);
+ --color-light-discard: hsl(52, 37%, 80%);
--color-medium-france: hsl(0, 35%, 70%);
--color-medium-bavaria: hsl(36, 65%, 70%);
--color-medium-prussia: hsl(210, 30%, 60%);
--color-medium-saxony: hsl(140, 20%, 55%);
- --color-medium-pragmatic: hsl(0, 0%, 65%);
+ --color-medium-pragmatic: hsl(264, 10%, 65%);
--color-medium-austria: hsl(0, 0%, 90%);
--color-medium-political: hsl(50, 35%, 60%);
-
- --color-dark-france: hsl(358, 85%, 52%);
- --color-dark-bavaria: hsl(36, 65%, 52%);
- --color-dark-prussia: hsl(198, 100%, 24%);
- --color-dark-saxony: hsl(139, 72%, 28%);
- --color-dark-pragmatic: hsl(0, 0%, 87%);
- --color-dark-austria: hsl(0, 0%, 97%);
+ --color-medium-discard: hsl(52, 25%, 70%);
--color-role-louis: hsl(0, 70%, 80%);
--color-role-frederick: hsl(210, 80%, 75%);
--color-role-maria: hsl(0, 0%, 97%);
- --color-clubs: #007c49;
- --color-diamonds: #c2263e;
- --color-hearts: #ed1c24;
- --color-spades: #274085;
- --color-reserve: #0094c9;
+ --color-clubs: #0079a1;
+ --color-diamonds: #9d403f;
+ --color-hearts: #ed1c23;
+ --color-spades: #00507c;
+ --color-reserve: #59594c;
}
/* PANELS */
@@ -130,8 +125,7 @@ svg .main_road {
justify-content: start;
flex-wrap: wrap;
padding: 18px;
- gap: 18px;
- min-height: 256px;
+ min-height: calc(257px + 4px);
}
#hand_france_header { background-color: var(--color-light-france) }
@@ -151,6 +145,8 @@ svg .main_road {
#political_header { background-color: var(--color-light-political) }
#political_panel { background-color: var(--color-medium-political) }
+#discard_pile_header { background-color: var(--color-light-discard); }
+#discard_pile_panel { background-color: var(--color-medium-discard); }
/* LOG */
@@ -195,6 +191,8 @@ svg .main_road {
#log span.suit { font-size: 11px; }
+span.value { padding: 0 1px }
+
span.suit.reserve { padding: 0 1px; }
span.suit.spades { color: var(--color-spades) }
@@ -412,6 +410,19 @@ span.suit.reserve { color: var(--color-reserve); font-weight: bold; font-family:
.number.n7 { background-position: -84px 0px; }
.number.n8 { background-position: -98px 0px; }
+/* CARD COUNTING AIDS */
+
+@media (hover: hover) {
+ #shift_button {
+ display: none;
+ }
+}
+
+body.shift span.value.deck_1 { background-color: #9513 }
+body.shift span.value.deck_2 { background-color: #04f2 }
+body.shift span.value.deck_3 { background-color: #0f03 }
+body.shift span.value.deck_4 { background-color: #f002 }
+
/* CARDS */
.card {
@@ -444,9 +455,26 @@ span.suit.reserve { color: var(--color-reserve); font-weight: bold; font-family:
.card.polcard { cursor: zoom-in }
.card.polcard.zoom { cursor: zoom-out }
-.draw-break { margin-left: 145px; }
-.card.tc { margin-right: -145px; }
-.panel_body { padding-right: calc(18px + 145px); }
+.draw-break { margin-left: 167px; }
+.card.tc { margin-right: calc(-167px + 40px); }
+.card.tc.reverse { margin-right: calc(-167px + 20px); }
+.card.tc.pile { margin-right: calc(-167px + 6px); }
+.card.tc.hand { margin-right: calc(-167px + 10px); }
+.card.polcard.pile { margin-right: calc(-167px + 6px); }
+
+.panel_body { padding-right: calc(18px + 167px); }
+.panel_body { gap: 18px 0; }
+#discard_pile_body { padding: 18px; gap: 18px; }
+
+#political_body { padding: 4px 0; display: body; }
+#political_panel { width: 879px }
+#discard_pile_panel { max-width: calc(230px * 4 + 18px * 5) }
+
+.card_pile {
+ display: flex;
+ flex-wrap: wrap;
+ width: 230px;
+}
.card.tc.H10 { background-image: url(cards/Maria.TC.01.075.jpg) }
.card.tc.H9 { background-image: url(cards/Maria.TC.02.075.jpg) }
@@ -491,15 +519,15 @@ span.suit.reserve { color: var(--color-reserve); font-weight: bold; font-family:
.card.tc.reverse.deck_3 { background-image: url(cards/Maria.TC.reverse.deck_3.075.jpg) }
.card.tc.reverse.deck_4 { background-image: url(cards/Maria.TC.reverse.deck_4.075.jpg) }
-.card.polcard.c01 { background-image: url(cards/Maria.PolCard.01.075.jpg) }
-.card.polcard.c02 { background-image: url(cards/Maria.PolCard.02.075.jpg) }
-.card.polcard.c03 { background-image: url(cards/Maria.PolCard.03.075.jpg) }
-.card.polcard.c04 { background-image: url(cards/Maria.PolCard.04.075.jpg) }
-.card.polcard.c05 { background-image: url(cards/Maria.PolCard.05.075.jpg) }
-.card.polcard.c06 { background-image: url(cards/Maria.PolCard.06.075.jpg) }
-.card.polcard.c07 { background-image: url(cards/Maria.PolCard.07.075.jpg) }
-.card.polcard.c08 { background-image: url(cards/Maria.PolCard.08.075.jpg) }
-.card.polcard.c09 { background-image: url(cards/Maria.PolCard.09.075.jpg) }
+.card.polcard.c1 { background-image: url(cards/Maria.PolCard.01.075.jpg) }
+.card.polcard.c2 { background-image: url(cards/Maria.PolCard.02.075.jpg) }
+.card.polcard.c3 { background-image: url(cards/Maria.PolCard.03.075.jpg) }
+.card.polcard.c4 { background-image: url(cards/Maria.PolCard.04.075.jpg) }
+.card.polcard.c5 { background-image: url(cards/Maria.PolCard.05.075.jpg) }
+.card.polcard.c6 { background-image: url(cards/Maria.PolCard.06.075.jpg) }
+.card.polcard.c7 { background-image: url(cards/Maria.PolCard.07.075.jpg) }
+.card.polcard.c8 { background-image: url(cards/Maria.PolCard.08.075.jpg) }
+.card.polcard.c9 { background-image: url(cards/Maria.PolCard.09.075.jpg) }
.card.polcard.c10 { background-image: url(cards/Maria.PolCard.10.075.jpg) }
.card.polcard.c11 { background-image: url(cards/Maria.PolCard.11.075.jpg) }
.card.polcard.c12 { background-image: url(cards/Maria.PolCard.12.075.jpg) }
@@ -515,70 +543,97 @@ span.suit.reserve { color: var(--color-reserve); font-weight: bold; font-family:
.card.polcard.c22 { background-image: url(cards/Maria.PolCard.22.075.jpg) }
.card.polcard.c23 { background-image: url(cards/Maria.PolCard.23.075.jpg) }
.card.polcard.c24 { background-image: url(cards/Maria.PolCard.24.075.jpg) }
-.card.polcard.impelection { background-image: url(cards/Maria.PolCard.ImpElection.075.jpg) }
+.card.polcard.c25 { background-image: url(cards/Maria.PolCard.ImpElection.075.jpg) }
+
.card.polcard.reverse.deck_1 { background-image: url(cards/Maria.PolCard.reverse.deck_1.075.jpg) }
.card.polcard.reverse.deck_2 { background-image: url(cards/Maria.PolCard.reverse.deck_2.075.jpg) }
.card.polcard.reverse.deck_3 { background-image: url(cards/Maria.PolCard.reverse.deck_3.075.jpg) }
.card.polcard.reverse.deck_4 { background-image: url(cards/Maria.PolCard.reverse.deck_4.075.jpg) }
+.card.polcard.c1.zoom { background-image: url(cards/Maria.PolCard.01.150.jpg) }
+.card.polcard.c2.zoom { background-image: url(cards/Maria.PolCard.02.150.jpg) }
+.card.polcard.c3.zoom { background-image: url(cards/Maria.PolCard.03.150.jpg) }
+.card.polcard.c4.zoom { background-image: url(cards/Maria.PolCard.04.150.jpg) }
+.card.polcard.c5.zoom { background-image: url(cards/Maria.PolCard.05.150.jpg) }
+.card.polcard.c6.zoom { background-image: url(cards/Maria.PolCard.06.150.jpg) }
+.card.polcard.c7.zoom { background-image: url(cards/Maria.PolCard.07.150.jpg) }
+.card.polcard.c8.zoom { background-image: url(cards/Maria.PolCard.08.150.jpg) }
+.card.polcard.c9.zoom { background-image: url(cards/Maria.PolCard.09.150.jpg) }
+.card.polcard.c10.zoom { background-image: url(cards/Maria.PolCard.10.150.jpg) }
+.card.polcard.c11.zoom { background-image: url(cards/Maria.PolCard.11.150.jpg) }
+.card.polcard.c12.zoom { background-image: url(cards/Maria.PolCard.12.150.jpg) }
+.card.polcard.c13.zoom { background-image: url(cards/Maria.PolCard.13.150.jpg) }
+.card.polcard.c14.zoom { background-image: url(cards/Maria.PolCard.14.150.jpg) }
+.card.polcard.c15.zoom { background-image: url(cards/Maria.PolCard.15.150.jpg) }
+.card.polcard.c16.zoom { background-image: url(cards/Maria.PolCard.16.150.jpg) }
+.card.polcard.c17.zoom { background-image: url(cards/Maria.PolCard.17.150.jpg) }
+.card.polcard.c18.zoom { background-image: url(cards/Maria.PolCard.18.150.jpg) }
+.card.polcard.c19.zoom { background-image: url(cards/Maria.PolCard.19.150.jpg) }
+.card.polcard.c20.zoom { background-image: url(cards/Maria.PolCard.20.150.jpg) }
+.card.polcard.c21.zoom { background-image: url(cards/Maria.PolCard.21.150.jpg) }
+.card.polcard.c22.zoom { background-image: url(cards/Maria.PolCard.22.150.jpg) }
+.card.polcard.c23.zoom { background-image: url(cards/Maria.PolCard.23.150.jpg) }
+.card.polcard.c24.zoom { background-image: url(cards/Maria.PolCard.24.150.jpg) }
+.card.polcard.c25.zoom { background-image: url(cards/Maria.PolCard.ImpElection.150.jpg) }
+
/* @2x */
@media (min-resolution: 97dpi) {
#map { background-image: url(Maria.Gameboard.150.jpg) }
#political_display { background-image: url(Maria.Political.Display.150.jpg) }
- .card.tc.c01 { background-image: url(cards/Maria.TC.01.150.jpg) }
- .card.tc.c02 { background-image: url(cards/Maria.TC.02.150.jpg) }
- .card.tc.c03 { background-image: url(cards/Maria.TC.03.150.jpg) }
- .card.tc.c04 { background-image: url(cards/Maria.TC.04.150.jpg) }
- .card.tc.c05 { background-image: url(cards/Maria.TC.05.150.jpg) }
- .card.tc.c06 { background-image: url(cards/Maria.TC.06.150.jpg) }
- .card.tc.c07 { background-image: url(cards/Maria.TC.07.150.jpg) }
- .card.tc.c08 { background-image: url(cards/Maria.TC.08.150.jpg) }
- .card.tc.c09 { background-image: url(cards/Maria.TC.09.150.jpg) }
- .card.tc.c10 { background-image: url(cards/Maria.TC.10.150.jpg) }
- .card.tc.c11 { background-image: url(cards/Maria.TC.11.150.jpg) }
- .card.tc.c12 { background-image: url(cards/Maria.TC.12.150.jpg) }
- .card.tc.c13 { background-image: url(cards/Maria.TC.13.150.jpg) }
- .card.tc.c14 { background-image: url(cards/Maria.TC.14.150.jpg) }
- .card.tc.c15 { background-image: url(cards/Maria.TC.15.150.jpg) }
- .card.tc.c16 { background-image: url(cards/Maria.TC.16.150.jpg) }
- .card.tc.c17 { background-image: url(cards/Maria.TC.17.150.jpg) }
- .card.tc.c18 { background-image: url(cards/Maria.TC.18.150.jpg) }
- .card.tc.c19 { background-image: url(cards/Maria.TC.19.150.jpg) }
- .card.tc.c20 { background-image: url(cards/Maria.TC.20.150.jpg) }
- .card.tc.c21 { background-image: url(cards/Maria.TC.21.150.jpg) }
- .card.tc.c22 { background-image: url(cards/Maria.TC.22.150.jpg) }
- .card.tc.c23 { background-image: url(cards/Maria.TC.23.150.jpg) }
- .card.tc.c24 { background-image: url(cards/Maria.TC.24.150.jpg) }
- .card.tc.c25 { background-image: url(cards/Maria.TC.25.150.jpg) }
- .card.tc.c26 { background-image: url(cards/Maria.TC.26.150.jpg) }
- .card.tc.c27 { background-image: url(cards/Maria.TC.27.150.jpg) }
- .card.tc.c28 { background-image: url(cards/Maria.TC.28.150.jpg) }
- .card.tc.c29 { background-image: url(cards/Maria.TC.29.150.jpg) }
- .card.tc.c30 { background-image: url(cards/Maria.TC.30.150.jpg) }
- .card.tc.c31 { background-image: url(cards/Maria.TC.31.150.jpg) }
- .card.tc.c32 { background-image: url(cards/Maria.TC.32.150.jpg) }
- .card.tc.c33 { background-image: url(cards/Maria.TC.33.150.jpg) }
- .card.tc.c34 { background-image: url(cards/Maria.TC.34.150.jpg) }
- .card.tc.c35 { background-image: url(cards/Maria.TC.35.150.jpg) }
- .card.tc.c36 { background-image: url(cards/Maria.TC.36.150.jpg) }
- .card.tc.c37 { background-image: url(cards/Maria.TC.37.150.jpg) }
- .card.tc.c38 { background-image: url(cards/Maria.TC.38.150.jpg) }
+ .card.tc.H10 { background-image: url(cards/Maria.TC.01.150.jpg) }
+ .card.tc.H9 { background-image: url(cards/Maria.TC.02.150.jpg) }
+ .card.tc.H8 { background-image: url(cards/Maria.TC.03.150.jpg) }
+ .card.tc.H7 { background-image: url(cards/Maria.TC.04.150.jpg) }
+ .card.tc.H6 { background-image: url(cards/Maria.TC.05.150.jpg) }
+ .card.tc.H5 { background-image: url(cards/Maria.TC.06.150.jpg) }
+ .card.tc.H4 { background-image: url(cards/Maria.TC.07.150.jpg) }
+ .card.tc.H3 { background-image: url(cards/Maria.TC.08.150.jpg) }
+ .card.tc.H2 { background-image: url(cards/Maria.TC.09.150.jpg) }
+ .card.tc.R { background-image: url(cards/Maria.TC.10.150.jpg) }
+ .card.tc.S10 { background-image: url(cards/Maria.TC.11.150.jpg) }
+ .card.tc.S9 { background-image: url(cards/Maria.TC.12.150.jpg) }
+ .card.tc.S8 { background-image: url(cards/Maria.TC.13.150.jpg) }
+ .card.tc.S7 { background-image: url(cards/Maria.TC.14.150.jpg) }
+ .card.tc.S6 { background-image: url(cards/Maria.TC.15.150.jpg) }
+ .card.tc.S5 { background-image: url(cards/Maria.TC.16.150.jpg) }
+ .card.tc.S4 { background-image: url(cards/Maria.TC.17.150.jpg) }
+ .card.tc.S3 { background-image: url(cards/Maria.TC.18.150.jpg) }
+ .card.tc.S2 { background-image: url(cards/Maria.TC.19.150.jpg) }
+ .card.tc.D10 { background-image: url(cards/Maria.TC.21.150.jpg) }
+ .card.tc.D9 { background-image: url(cards/Maria.TC.22.150.jpg) }
+ .card.tc.D8 { background-image: url(cards/Maria.TC.23.150.jpg) }
+ .card.tc.D7 { background-image: url(cards/Maria.TC.24.150.jpg) }
+ .card.tc.D6 { background-image: url(cards/Maria.TC.25.150.jpg) }
+ .card.tc.D5 { background-image: url(cards/Maria.TC.26.150.jpg) }
+ .card.tc.D4 { background-image: url(cards/Maria.TC.27.150.jpg) }
+ .card.tc.D3 { background-image: url(cards/Maria.TC.28.150.jpg) }
+ .card.tc.D2 { background-image: url(cards/Maria.TC.29.150.jpg) }
+ .card.tc.C10 { background-image: url(cards/Maria.TC.30.150.jpg) }
+ .card.tc.C9 { background-image: url(cards/Maria.TC.31.150.jpg) }
+ .card.tc.C8 { background-image: url(cards/Maria.TC.32.150.jpg) }
+ .card.tc.C7 { background-image: url(cards/Maria.TC.33.150.jpg) }
+ .card.tc.C6 { background-image: url(cards/Maria.TC.34.150.jpg) }
+ .card.tc.C5 { background-image: url(cards/Maria.TC.35.150.jpg) }
+ .card.tc.C4 { background-image: url(cards/Maria.TC.36.150.jpg) }
+ .card.tc.C3 { background-image: url(cards/Maria.TC.37.150.jpg) }
+ .card.tc.C2 { background-image: url(cards/Maria.TC.38.150.jpg) }
+
.card.tc.reverse.deck_1 { background-image: url(cards/Maria.TC.reverse.deck_1.150.jpg) }
.card.tc.reverse.deck_2 { background-image: url(cards/Maria.TC.reverse.deck_2.150.jpg) }
.card.tc.reverse.deck_3 { background-image: url(cards/Maria.TC.reverse.deck_3.150.jpg) }
.card.tc.reverse.deck_4 { background-image: url(cards/Maria.TC.reverse.deck_4.150.jpg) }
- .card.polcard.c01 { background-image: url(cards/Maria.PolCard.01.150.jpg) }
- .card.polcard.c02 { background-image: url(cards/Maria.PolCard.02.150.jpg) }
- .card.polcard.c03 { background-image: url(cards/Maria.PolCard.03.150.jpg) }
- .card.polcard.c04 { background-image: url(cards/Maria.PolCard.04.150.jpg) }
- .card.polcard.c05 { background-image: url(cards/Maria.PolCard.05.150.jpg) }
- .card.polcard.c06 { background-image: url(cards/Maria.PolCard.06.150.jpg) }
- .card.polcard.c07 { background-image: url(cards/Maria.PolCard.07.150.jpg) }
- .card.polcard.c08 { background-image: url(cards/Maria.PolCard.08.150.jpg) }
- .card.polcard.c09 { background-image: url(cards/Maria.PolCard.09.150.jpg) }
+ .card.polcard.c1 { background-image: url(cards/Maria.PolCard.01.150.jpg) }
+ .card.polcard.c2 { background-image: url(cards/Maria.PolCard.02.150.jpg) }
+ .card.polcard.c3 { background-image: url(cards/Maria.PolCard.03.150.jpg) }
+ .card.polcard.c4 { background-image: url(cards/Maria.PolCard.04.150.jpg) }
+ .card.polcard.c5 { background-image: url(cards/Maria.PolCard.05.150.jpg) }
+ .card.polcard.c6 { background-image: url(cards/Maria.PolCard.06.150.jpg) }
+ .card.polcard.c7 { background-image: url(cards/Maria.PolCard.07.150.jpg) }
+ .card.polcard.c8 { background-image: url(cards/Maria.PolCard.08.150.jpg) }
+ .card.polcard.c9 { background-image: url(cards/Maria.PolCard.09.150.jpg) }
.card.polcard.c10 { background-image: url(cards/Maria.PolCard.10.150.jpg) }
.card.polcard.c11 { background-image: url(cards/Maria.PolCard.11.150.jpg) }
.card.polcard.c12 { background-image: url(cards/Maria.PolCard.12.150.jpg) }
@@ -594,7 +649,8 @@ span.suit.reserve { color: var(--color-reserve); font-weight: bold; font-family:
.card.polcard.c22 { background-image: url(cards/Maria.PolCard.22.150.jpg) }
.card.polcard.c23 { background-image: url(cards/Maria.PolCard.23.150.jpg) }
.card.polcard.c24 { background-image: url(cards/Maria.PolCard.24.150.jpg) }
- .card.polcard.impelection { background-image: url(cards/Maria.PolCard.ImpElection.150.jpg) }
+ .card.polcard.c25 { background-image: url(cards/Maria.PolCard.ImpElection.150.jpg) }
+
.card.polcard.reverse.deck_1 { background-image: url(cards/Maria.PolCard.reverse.deck_1.150.jpg) }
.card.polcard.reverse.deck_2 { background-image: url(cards/Maria.PolCard.reverse.deck_2.150.jpg) }
.card.polcard.reverse.deck_3 { background-image: url(cards/Maria.PolCard.reverse.deck_3.150.jpg) }
diff --git a/play.html b/play.html
index 2cc2490..4f7e2b5 100644
--- a/play.html
+++ b/play.html
@@ -94,9 +94,9 @@
<!-- Political Display -->
- <div id="political_panel" class="panel" style="width:905px">
+ <div id="political_panel" class="panel">
<div id="political_header" class="panel_header">Political Display</div>
- <div class="panel_body" style="padding:12px">
+ <div id="political_body">
<div id="political_display">
<div id="display_track_saxony"></div>
<div id="display_track_russia"></div>
@@ -106,12 +106,31 @@
<div id="display_pragmatic_army"></div>
<div id="display_austria"></div>
</div>
+ <div style="display:flex;flex-wrap:wrap;gap:18px;margin:18px;">
+ <div class="card_pile">
+ <div id="pcp4" class="card polcard pile reverse deck_4"></div>
+ <div id="pcp3" class="card polcard pile reverse deck_3"></div>
+ <div id="pcp2" class="card polcard pile reverse deck_2"></div>
+ <div id="pcp1" class="card polcard pile reverse deck_1"></div>
+ <div id="pcp_imp" class="card polcard c25"></div>
+ </div>
+ <div class="card polcard c1"></div>
+ <div class="card polcard c2"></div>
+ </div>
</div>
</div>
</div>
-<br>
+<div id="discard_pile_panel" class="panel">
+<div id="discard_pile_header" class="panel_header">Decks &amp; Discard Piles</div>
+<div id="discard_pile_body" class="panel_body">
+ <div class="card_pile" id="discard_1"></div>
+ <div class="card_pile" id="discard_2"></div>
+ <div class="card_pile" id="discard_3"></div>
+ <div class="card_pile" id="discard_4"></div>
+</div>
+</div>
</main>
diff --git a/play.js b/play.js
index daf430c..3d8235d 100644
--- a/play.js
+++ b/play.js
@@ -18,6 +18,10 @@ function toggle_pieces() {
}
}
+function toggle_shift() {
+ document.body.classList.toggle("shift")
+}
+
/* DATA */
const P_FRANCE = 0
@@ -108,12 +112,12 @@ const piece_name = [
"BatthyƔny",
"Neipperg",
"Arenberg",
- "supply train", "supply train",
- "supply train",
- "supply train", "supply train",
- "supply train",
- "supply train",
- "supply train", "supply train", "supply train",
+ "French ST", "French ST",
+ "Bavarian ST",
+ "Prussian ST", "Prussian ST",
+ "Saxon ST",
+ "Pragmatic Army ST",
+ "Austrian ST", "Austrian ST", "Austrian ST",
"hussars", "hussars",
]
@@ -160,7 +164,6 @@ function make_road(c1, c2, type) {
document.getElementById("roads").appendChild(e)
}
-
/* PANEL ORDER */
const panel_order = [ P_FRANCE, P_BAVARIA, P_PRUSSIA, P_SAXONY, P_PRAGMATIC, P_AUSTRIA, P_AUSTRIA+1 ]
@@ -234,6 +237,12 @@ const ui = {
pieces_element: document.getElementById("pieces"),
markers_element: document.getElementById("markers"),
political_display: document.getElementById("political_display"),
+ discard: [
+ document.getElementById("discard_1"),
+ document.getElementById("discard_2"),
+ document.getElementById("discard_3"),
+ document.getElementById("discard_4"),
+ ],
power_panel_list: document.getElementById("power_panel_list"),
power_header: [
document.getElementById("hand_france_header"),
@@ -334,6 +343,16 @@ function make_tc_deck_back(n) {
return list
}
+function make_tc_deck_discard(n) {
+ let list = []
+ for (let i = 0; i < 10; ++i) {
+ let e = document.createElement("div")
+ e.className = "card tc pile reverse " + n
+ list.push(e)
+ }
+ return list
+}
+
function make_political_card(fc) {
let e = document.createElement("div")
if (fc === 0)
@@ -427,6 +446,13 @@ function on_init() {
make_tc_deck_back("deck_4"),
]
+ ui.tc_discard = [
+ make_tc_deck_discard("deck_1"),
+ make_tc_deck_discard("deck_2"),
+ make_tc_deck_discard("deck_3"),
+ make_tc_deck_discard("deck_4"),
+ ]
+
ui.combat = document.createElement("div")
ui.combat.id = "combat"
ui.combat.style.zIndex = 2000
@@ -552,7 +578,11 @@ function on_blur_city() {
}
function on_focus_piece(evt) {
- ui.status.textContent = piece_name[evt.target.my_id]
+ let p = evt.target.my_id
+ if (p < 20 && view.troops[p] > 0)
+ ui.status.textContent = piece_name[evt.target.my_id] + " (" + view.troops[p] + " troops)"
+ else
+ ui.status.textContent = piece_name[evt.target.my_id]
}
function on_blur_piece() {
@@ -609,16 +639,15 @@ function get_cylinder_power(id) {
}
function layout_general(id, s) {
- let e = ui.pieces[id]
let x, y, n
if (s === REMOVED) {
- if (e.parentElement === ui.pieces_element)
+ if (ui.pieces[id].parentElement === ui.pieces_element)
+ e.remove()
+ if (ui.troops[id].parentElement === ui.pieces_element)
e.remove()
return
}
- if (e.parentElement !== ui.pieces_element)
- ui.pieces_element.appendChild(e)
if (s === ELIMINATED) {
n = layout_general_offset_elim(id)
@@ -632,6 +661,9 @@ function layout_general(id, s) {
let selected = set_has(view.selected, id)
+ let e = ui.pieces[id]
+ if (e.parentElement !== ui.pieces_element)
+ ui.pieces_element.appendChild(e)
e.style.left = (x - 21) + "px"
e.style.top = (y - 29 - 15 * n) + "px"
e.style.zIndex = y + n
@@ -639,10 +671,9 @@ function layout_general(id, s) {
e.classList.toggle("oos", (view.oos & (1 <<id)) !== 0)
e = ui.troops[id]
- // e.style.left = (x + 21 + 1) + "px"
- // e.style.top = (y - 7 - 14 * n) + "px"
+ if (e.parentElement !== ui.pieces_element)
+ ui.pieces_element.appendChild(e)
e.style.left = (x - 7) + "px"
- // e.style.top = (y + 7 - 15 * n) + "px"
e.style.top = (y + 2 - 15 * n) + "px"
e.style.zIndex = y + n + 1
e.className = power_class[piece_power[id]] + " piece number n" + view.troops[id]
@@ -717,9 +748,10 @@ function create_conquest(style, s) {
function update_favicon() {
let favicon = document.querySelector('link[rel="icon"]')
switch (params.role) {
+ case "Louis XV": favicon.href = "favicon/louis.png"; break
case "Frederick": favicon.href = "favicon/fritz.png"; break
+ default:
case "Maria Theresa": favicon.href = "favicon/maria.png"; break
- case "Louis XV": favicon.href = "favicon/louis.png"; break
}
}
@@ -735,28 +767,29 @@ const colorize_H = '<span class="suit hearts">\u2665</span>'
const colorize_D = '<span class="suit diamonds">\u2666</span>'
const colorize_R = '$1<span class="suit reserve">R</span>'
-const suit_text = [
- '<span class="suit spades">\u2660</span>',
- '<span class="suit clubs">\u2663</span>',
- '<span class="suit hearts">\u2665</span>',
- '<span class="suit diamonds">\u2666</span>',
- '<span class="suit reserve">R</span>'
-]
+const colorize_1 = '<span class="value deck_1">$1</span>'
+const colorize_2 = '<span class="value deck_2">$1</span>'
+const colorize_3 = '<span class="value deck_3">$1</span>'
+const colorize_4 = '<span class="value deck_4">$1</span>'
function colorize(text) {
+ text = text.replace(/1\^(\d+)/g, colorize_1)
+ text = text.replace(/2\^(\d+)/g, colorize_2)
+ text = text.replace(/3\^(\d+)/g, colorize_3)
+ text = text.replace(/4\^(\d+)/g, colorize_4)
+ text = text.replace(/(\d+)R/g, colorize_R)
text = text.replaceAll("\u2660", colorize_S)
text = text.replaceAll("\u2663", colorize_C)
text = text.replaceAll("\u2665", colorize_H)
text = text.replaceAll("\u2666", colorize_D)
- text = text.replace(/(\d+)R/g, colorize_R)
return text
}
-function on_update() {
-// let text = colorize(view.prompt)
-// if (text !== view.prompt)
-// ui.prompt.innerHTML = text
+function on_prompt(text) {
+ return colorize(view.prompt)
+}
+function on_update() {
ui.header.classList.toggle("france", view.power === P_FRANCE)
ui.header.classList.toggle("bavaria", view.power === P_BAVARIA)
ui.header.classList.toggle("prussia", view.power === P_PRUSSIA)
@@ -791,6 +824,7 @@ function on_update() {
ui.hand[pow].replaceChildren()
view.hand[pow].sort(cmp_tc)
for (let c of view.hand[pow]) {
+ console.log("C", c, c&15)
if ((c & 15) === 0)
ui.hand[pow].appendChild(ui.tc_back[c>>7][back[c>>7]++])
else
@@ -816,6 +850,12 @@ function on_update() {
ui.political_display.appendChild(ui.fate[c])
*/
+ for (let deck = 0; deck < 4; ++deck) {
+ ui.discard[deck].replaceChildren()
+ for (let i = 0; i < view.discard[deck]; ++i)
+ ui.discard[deck].appendChild(ui.tc_discard[deck][i])
+ }
+
ui.markers_element.replaceChildren()
/*
for (let s of view.conquest)
@@ -833,7 +873,7 @@ function on_update() {
action_button_with_argument("value", v, v)
for (let p = 0; p < 20; ++p) {
- action_button_with_argument("detach", p, "Detach " + piece_abbr[p])
+ action_button_with_argument("unstack", p, "Unstack " + piece_abbr[p])
action_button_with_argument("promote", p, "Promote " + piece_abbr[p])
action_button_with_argument("demote", p, "Demote " + piece_abbr[p])
}
@@ -879,8 +919,13 @@ function sub_space(match, p1) {
return `<span class="city_tip" onclick="on_click_city_tip(${x})" onmouseenter="on_focus_city_tip(${x})" onmouseleave="on_blur_city_tip(${x})">${n}</span>`
}
-function sub_tc(match, p1) {
- return value + suit_text[suit]
+function sub_path(pieces_and_spaces) {
+ let ps = pieces_and_spaces[0].split(",")
+ let ss = pieces_and_spaces[1].split(",")
+ let x = ss[ss.length-1]
+ let ps_name = ps.map(p => piece_name[p]).join(" and ")
+ let ss_name = data.cities.name[x]
+ return `<span onclick="on_click_city_tip(${x})" onmouseenter="on_focus_path_tip([${ps.join(",")}],[${ss.join(",")}])" onmouseleave="on_blur_path_tip()">${ps_name} to ${ss_name}.</span>`
}
function on_log(text) {
@@ -905,29 +950,24 @@ function on_log(text) {
text = text.replace(/</g, "&lt;")
text = text.replace(/>/g, "&gt;")
+ text = text.replaceAll(" 1 troops", " 1 troop")
+
+ text = colorize(text)
text = text.replace(/S(\d+)/g, sub_space)
text = text.replace(/P(\d+)/g, sub_piece)
- text = colorize(text)
- if (text.match(/^\$(\d+)/)) {
- let fx = parseInt(text.substring(1))
- if (fx < 48 + 6)
- text = `<div class="q">${fate_flavor_text[fx]}</div><div></div><div>${fate_effect_text[fx]}</div><div></div>`
- else
- text = `<div class="q">${fate_flavor_text[fx]}</div><div></div>`
- }
- else if (text.match(/^# /)) {
- p.className = "h fate"
+ if (text.startsWith("#")) {
+ p.className = "h turn"
text = text.substring(2)
}
- else if (text.match(/^\.s1/))
- text = the_war_in_the_west_text
- else if (text.match(/^\.s2/))
- text = the_austrian_theater_text
- else if (text.match(/^=\d/)) {
+ else if (text.startsWith("=")) {
p.className = "h " + power_class[text[1]]
text = power_name[text[1]]
}
+ else if (text.startsWith("@")) {
+ p.className = "move_tip"
+ text = sub_path(text.substring(1).split(";"))
+ }
p.innerHTML = text
return p
diff --git a/rules.js b/rules.js
index bdb4a00..e1659f2 100644
--- a/rules.js
+++ b/rules.js
@@ -1,117 +1,5 @@
"use strict"
-/*
-var game, view
-
-// piece list:
-// generals, trains, and hussars - have location (loc)
-// generals - have strength (str)
-
-// space list:
-// objective/fortress have control (0 or power)
-
-const data = require("./data")
-let objectives = {}
-let anti_objectives = { Austria: [], "Pragmatic Army": [], France: [], Prussia: [] }
-let prot_objectives = { Austria: [], "Pragmatic Army": [], France: [], Prussia: [] }
-
-let whose_objective = {
- Austria: [ "France", "Prussia" ],
- Bavaria: [ "Austria" ],
- France: [ "Austria", "Pragmatic Army" ],
- Netherlands: [ "France" ],
- Prussia: [ "Austria" ],
- Saxony: [ "Austria" ],
- Silesia: [ "Austria", "Prussia" ],
- HRE: [ "Austria", "Pragmatic Army", "France" ],
-}
-
-let protect_objective = {
- Austria: [ "Austria" ],
- Bavaria: [ "France" ],
- France: [ "France" ],
- Netherlands: [ "Pragmatic Army" ],
- Prussia: [ "Prussia" ],
- Saxony: [ "Prussia" ],
- Silesia: [ "Austria", "Prussia" ],
- HRE: [ "Austria", "Pragmatic Army", "France" ],
-}
-
-for (let type of [ "major_fortress", "minor_fortress" ]) {
- let group = object_group_by(data.type[type], s => data.cities.country[s])
- for (let region in group) {
- if (objectives[region] === undefined)
- objectives[region] = []
- for (let s of group[region]) {
- set_add(objectives[region], s)
- console.log(region)
- for (let list of whose_objective[region])
- set_add(anti_objectives[list], s)
- for (let list of protect_objective[region])
- set_add(prot_objectives[list], s)
- }
-
- }
-}
-for (let x in anti_objectives)
- console.log(x, anti_objectives[x].length)
-console.log(objectives)
-console.log("TAKE", anti_objectives)
-console.log("PROT", prot_objectives)
-
-exports.roles = [
- "Louis XV",
- "Frederick",
- "Maria Theresa",
-]
-
-exports.scenarios = [ "Standard", "Introductory" ]
-
-const P_AUSTRIA = 0
-const P_PRUSSIA = 1
-const P_SAXONY = 2
-const P_PRAGMATIC = 3
-const P_FRANCE = 4
-const P_BAVARIA = 5
-
-const PLAYERS = {
- "Maria Theresa": [ P_AUSTRIA ],
- "Frederick": [ P_PRUSSIA, P_SAXONY, P_PRAGMATIC ],
- "Louis XV": [ P_FRANCE, P_BAVARIA ],
-}
-
-const MAJOR_POWERS = [ P_AUSTRIA, P_PRUSSIA, P_FRANCE, P_PRAGMATIC ]
-
-const MINOR_POWERS = [ P_BAVARIA, P_SAXONY ]
-
-const ALLIED = [
- [ P_FRANCE, P_BAVARIA, P_PRUSSIA, P_SAXONY ],
- [ P_AUSTRIA, P_PRAGMATIC ],
-]
-
-const COOPERATE = [
- [ P_FRANCE, P_BAVARIA ],
- [ P_PRUSSIA, P_SAXONY ],
- [ P_AUSTRIA, P_PRAGMATIC ],
-]
-
-*/
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-"use strict"
-
const R_LOUIS_XV = "Louis XV"
const R_FREDERICK = "Frederick"
const R_MARIA_THERESA = "Maria Theresa"
@@ -314,22 +202,36 @@ function to_value(c) {
return c & 15
}
-function format_card(c) {
+function format_card_prompt(c) {
if (is_reserve(c))
return "8R"
return to_value(c) + suit_name[to_suit(c)]
}
+function format_card(c) {
+ return (to_deck(c)+1) + "^" + format_card_prompt(c)
+}
+
+function format_reserve(c, v) {
+ return (to_deck(c)+1) + "^" + v + "R"
+}
+
function is_reserve(c) {
return to_suit(c) === RESERVE
}
-function format_cards(list) {
+function format_card_list(list) {
if (list.length > 0)
return list.map(format_card).join(", ")
return "nothing"
}
+function format_card_list_prompt(list) {
+ if (list.length > 0)
+ return list.map(format_card_prompt).join(", ")
+ return "nothing"
+}
+
function format_selected() {
if (game.selected.length === 0)
return "nobody"
@@ -682,19 +584,29 @@ function find_largest_discard(u) {
throw "OUT OF CARDS"
}
-function next_tactics_deck() {
- let held = [ 0, 0, 0, 0, 0 ]
+function count_used_cards() {
+ let held = [ 0, 0, 0, 0 ]
// count cards in hands
for (let pow of all_powers) {
for (let c of game.hand[pow])
held[to_deck(c)]++
}
+
+ // count cards currently being held
if (game.draw)
for (let c of game.draw)
held[to_deck(c)]++
- if (game.oo > 0)
- held[to_deck(game.oo)]++
+
+ // count cards remaining in deck
+ for (let c of game.deck)
+ held[to_deck(c)]++
+
+ return held
+}
+
+function next_tactics_deck() {
+ let held = count_used_cards()
// find next unused deck
for (let i = 1; i < 5; ++i) {
@@ -726,6 +638,13 @@ function next_tactics_deck() {
shuffle_bigint(game.deck)
}
+function total_discard_list() {
+ let discard = count_used_cards()
+ for (let i = 0; i < 4; ++i)
+ discard[i] = Math.ceil((38 - discard[i]) / 5)
+ return discard
+}
+
function draw_tc(n) {
game.draw = []
@@ -763,7 +682,7 @@ states.tactical_cards_show = {
inactive: "draw tactical cards",
prompt() {
view.draw = game.draw
- prompt("Draw " + format_cards(game.draw) + ".")
+ prompt("Draw " + format_card_list_prompt(game.draw) + ".")
view.actions.end_cards = 1
},
end_cards() {
@@ -942,10 +861,10 @@ states.movement = {
game.count = 0
- if (data.cities.major_roads[here].length > 0)
- game.major = 1
+ if (data.cities.main_roads[here].length > 0)
+ game.main = 1
else
- game.major = 0
+ game.main = 0
if (is_supply_train(p))
game.state = "move_supply_train"
@@ -973,7 +892,7 @@ states.movement = {
function format_move(max) {
let n = max - game.count
- if (game.major)
+ if (game.main)
return ` up to ${n} cities (${n+1} on main roads).`
return ` up to ${n} cities.`
}
@@ -1075,8 +994,8 @@ states.move_supply_train = {
let who = game.selected[0]
let here = game.pos[who]
- if (game.count < 2 + game.major)
- for (let next of data.cities.major_roads[here])
+ if (game.count < 2 + game.main)
+ for (let next of data.cities.main_roads[here])
if (!has_any_piece(next))
gen_action_space(next)
if (game.count < 2)
@@ -1107,13 +1026,13 @@ states.move_supply_train = {
log(">to S" + to)
- if (!set_has(data.cities.major_roads[from], to))
- game.major = 0
+ if (!set_has(data.cities.main_roads[from], to))
+ game.main = 0
set_add(game.moved, who)
game.pos[who] = to
- if (++game.count === 2 + game.major)
+ if (++game.count === 2 + game.main)
end_move_piece()
},
}
@@ -1131,7 +1050,7 @@ states.move_general = {
if (game.selected.length > 1) {
for (let p of game.selected) {
gen_action_piece(p)
- gen_action_detach(p)
+ gen_action_unstack(p)
}
}
@@ -1151,8 +1070,8 @@ states.move_general = {
view.actions.stop = 1
}
- if (game.count < movement_range() + game.major)
- for (let next of data.cities.major_roads[here])
+ if (game.count < movement_range() + game.main)
+ for (let next of data.cities.main_roads[here])
if (can_move_general_to(next))
gen_action_space_or_piece(next)
@@ -1167,7 +1086,7 @@ states.move_general = {
give() {
game.state = "move_give"
},
- detach(p) {
+ unstack(p) {
set_delete(game.selected, p)
},
piece(p) {
@@ -1199,10 +1118,10 @@ states.move_general = {
log(">to S" + to)
- if (!set_has(data.cities.major_roads[from], to))
- game.major = 0
+ if (!set_has(data.cities.main_roads[from], to))
+ game.main = 0
- if (move_general_to(to) || ++game.count === movement_range() + game.major)
+ if (move_general_to(to) || ++game.count === movement_range() + game.main)
end_move_piece()
},
}
@@ -1698,22 +1617,22 @@ function format_combat(value) {
let d = format_combat_stack(game.defender)
let s = signed_number(value)
let p = POWER_NAME[game.power]
- return `${a} vs ${d}. ${p} is at ${s}`
+ return `${a} vs ${d}. ${p} is at ${s}.`
}
function inactive_attack() {
- return "combat " + format_combat(game.count)
+ return "Waiting for " + format_combat(game.count)
}
function inactive_defend() {
- return "combat " + format_combat(-game.count)
+ return "Waiting for " + format_combat(-game.count)
}
function prompt_combat(value, extra = null) {
- let text = "Combat " + format_combat(value) + "."
+ let text = format_combat(value)
if (extra)
text += " " + extra
- prompt(text)
+ view.prompt = text
}
function set_active_attacker() {
@@ -1764,6 +1683,7 @@ function gen_play_card(suit) {
}
function gen_play_reserve() {
+ view.draw = [ game.reserve ]
view.actions.value = [ 1, 2, 3, 4, 5, 6, 7, 8 ]
}
@@ -1778,13 +1698,15 @@ function play_card(c, sign) {
}
function play_reserve(v, sign) {
+ let c = game.reserve
+ delete game.reserve
let prefix = (sign < 0 ? ">>" : ">") + POWER_NAME[game.power]
if (sign < 0)
game.count -= v
else
game.count += v
let score = signed_number(sign * game.count)
- log(`${prefix} ${v}R = ${score}`)
+ log(`${prefix} ${format_reserve(c, v)} = ${score}`)
}
function play_combat_card(c, sign, resume, next_state) {
@@ -1792,6 +1714,7 @@ function play_combat_card(c, sign, resume, next_state) {
array_remove_item(game.hand[game.power], c)
if (is_reserve(c)) {
game.state = next_state
+ game.reserve = c
} else {
play_card(c, sign)
resume()
@@ -2486,8 +2409,6 @@ function make_tactics_deck(n) {
function make_tactics_discard(n) {
return make_tactics_deck(n).filter(c => {
- if (c === game.oo)
- return false
if (game.draw && set_has(game.draw, c))
return false
for (let pow of all_powers)
@@ -2693,6 +2614,7 @@ exports.view = function (state, player) {
troops: mask_troops(player),
hand: mask_hand(player),
pt: total_troops_list(),
+ discard: total_discard_list(),
power: game.power,
retro: game.retro,
@@ -2705,11 +2627,14 @@ exports.view = function (state, player) {
if (game.state === "game_over") {
view.prompt = game.victory
+ view.troops = game.troops
+ view.hand = game.hand
} else if (game.active !== player) {
let inactive = states[game.state].inactive || game.state
if (typeof inactive === "function")
- inactive = inactive()
- view.prompt = `Waiting for ${POWER_NAME[game.power]} to ${inactive}.`
+ view.prompt = inactive()
+ else
+ view.prompt = `Waiting for ${POWER_NAME[game.power]} to ${inactive}.`
} else {
view.actions = {}
if (states[game.state])
@@ -2730,11 +2655,11 @@ exports.view = function (state, player) {
/* COMMON FRAMEWORK */
function goto_game_over(result, victory) {
+ log("# The End")
game.active = "None"
game.state = "game_over"
game.result = result
game.victory = victory
- log("# Game Over")
log(game.victory)
return true
}
@@ -2790,8 +2715,8 @@ function gen_action_card(c) {
gen_action("card", c)
}
-function gen_action_detach(p) {
- gen_action("detach", p)
+function gen_action_unstack(p) {
+ gen_action("unstack", p)
}
function log(msg) {