summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--play.css33
-rw-r--r--play.html13
-rw-r--r--play.js137
-rw-r--r--rules.js283
-rw-r--r--tools/gencards.js52
5 files changed, 376 insertions, 142 deletions
diff --git a/play.css b/play.css
index 00c9cfe..fd8c0d6 100644
--- a/play.css
+++ b/play.css
@@ -182,7 +182,6 @@ body.military svg .sea.action {
.capital.action {
display: block;
border: 5px solid white;
- background-color: #fff8;
box-shadow: 0 0 6px white, inset 0 0 6px black;
z-index: 2;
}
@@ -435,6 +434,7 @@ body.p2 #Galatia_NPG { display: block }
transform: translate(0px, 0px);
}
+#played .influence_m1, #played .influence_s1, #played .influence_p1,
.card.used {
filter: brightness(75%)
}
@@ -480,6 +480,16 @@ body.p2 #Galatia_NPG { display: block }
.card.influence_s2{background-image:url(cards.1x/influence_s2.jpg)}
.card.influence_s3{background-image:url(cards.1x/influence_s3.jpg)}
.card.influence_s4{background-image:url(cards.1x/influence_s4.jpg)}
+.card.influence_s4b{background-image:url(cards.1x/influence_s4b.jpg)}
+.card.influence_m2x{background-image:url(cards.1x/influence_m2x.jpg)}
+.card.influence_m3x{background-image:url(cards.1x/influence_m3x.jpg)}
+.card.influence_m4x{background-image:url(cards.1x/influence_m4x.jpg)}
+.card.influence_p2x{background-image:url(cards.1x/influence_p2x.jpg)}
+.card.influence_p3x{background-image:url(cards.1x/influence_p3x.jpg)}
+.card.influence_p4x{background-image:url(cards.1x/influence_p4x.jpg)}
+.card.influence_s2x{background-image:url(cards.1x/influence_s2x.jpg)}
+.card.influence_s3x{background-image:url(cards.1x/influence_s3x.jpg)}
+.card.influence_s4x{background-image:url(cards.1x/influence_s4x.jpg)}
@media (min-resolution:97dpi) {
.card.event_back{background-image:url(cards.2x/event_back.jpg)}
@@ -511,22 +521,21 @@ body.p2 #Galatia_NPG { display: block }
.card.influence_s2{background-image:url(cards.2x/influence_s2.jpg)}
.card.influence_s3{background-image:url(cards.2x/influence_s3.jpg)}
.card.influence_s4{background-image:url(cards.2x/influence_s4.jpg)}
+.card.influence_s4b{background-image:url(cards.2x/influence_s4b.jpg)}
+.card.influence_m2x{background-image:url(cards.2x/influence_m2x.jpg)}
+.card.influence_m3x{background-image:url(cards.2x/influence_m3x.jpg)}
+.card.influence_m4x{background-image:url(cards.2x/influence_m4x.jpg)}
+.card.influence_p2x{background-image:url(cards.2x/influence_p2x.jpg)}
+.card.influence_p3x{background-image:url(cards.2x/influence_p3x.jpg)}
+.card.influence_p4x{background-image:url(cards.2x/influence_p4x.jpg)}
+.card.influence_s2x{background-image:url(cards.2x/influence_s2x.jpg)}
+.card.influence_s3x{background-image:url(cards.2x/influence_s3x.jpg)}
+.card.influence_s4x{background-image:url(cards.2x/influence_s4x.jpg)}
}
.influence_m1 + .influence_m1 { margin-left: -180px; }
.influence_p1 + .influence_p1 { margin-left: -180px; }
.influence_s1 + .influence_s1 { margin-left: -180px; }
-/*
-.influence_m2 + .influence_m2 { margin-left: -180px; }
-.influence_p2 + .influence_p2 { margin-left: -180px; }
-.influence_s2 + .influence_s2 { margin-left: -180px; }
-.influence_m3 + .influence_m3 { margin-left: -180px; }
-.influence_p3 + .influence_p3 { margin-left: -180px; }
-.influence_s3 + .influence_s3 { margin-left: -180px; }
-.influence_m4 + .influence_m4 { margin-left: -180px; }
-.influence_p4 + .influence_p4 { margin-left: -180px; }
-.influence_s4 + .influence_s4 { margin-left: -180px; }
-*/
#played .influence_m1 + .influence_p1 { margin-left: -180px }
#played .influence_m1 + .influence_s1 { margin-left: -180px }
diff --git a/play.html b/play.html
index ee69553..7a1005a 100644
--- a/play.html
+++ b/play.html
@@ -106,19 +106,6 @@
<div id="Syria_Capital" class="capital" style="left:2173px;top:1192px"></div>
<div id="Thracia_Capital" class="capital" style="left:1593px;top:630px"></div>
-<div id="Italia_Quaestor" class="quaestor hide" style="left:971px;top:829px"></div>
-<div id="Aegyptus_Quaestor" class="quaestor hide" style="left:1643px;top:1462px"></div>
-<div id="Africa_Quaestor" class="quaestor hide" style="left:590px;top:1284px"></div>
-<div id="Asia_Quaestor" class="quaestor hide" style="left:1622px;top:994px"></div>
-<div id="Britannia_Quaestor" class="quaestor hide" style="left:174px;top:254px"></div>
-<div id="Galatia_Quaestor" class="quaestor hide" style="left:1897px;top:925px"></div>
-<div id="Gallia_Quaestor" class="quaestor hide" style="left:403px;top:501px"></div>
-<div id="Hispania_Quaestor" class="quaestor hide" style="left:97px;top:974px"></div>
-<div id="Macedonia_Quaestor" class="quaestor hide" style="left:1327px;top:930px"></div>
-<div id="Pannonia_Quaestor" class="quaestor hide" style="left:1097px;top:620px"></div>
-<div id="Syria_Quaestor" class="quaestor hide" style="left:1977px;top:1274px"></div>
-<div id="Thracia_Quaestor" class="quaestor hide" style="left:1445px;top:714px"></div>
-
<div id="Aegyptus_NPG" class="no_place_governor" style="left:1793px;top:1380px"></div>
<div id="Africa_NPG" class="no_place_governor" style="left:741px;top:1204px"></div>
<div id="Britannia_NPG" class="no_place_governor" style="left:325px;top:177px"></div>
diff --git a/play.js b/play.js
index 7db4efb..1aefd9b 100644
--- a/play.js
+++ b/play.js
@@ -5,6 +5,63 @@
// === SYNC with rules.js ===
+const CARD_M1 = [ 0, 11 ]
+const CARD_S1 = [ 12, 23 ]
+const CARD_P1 = [ 24, 35 ]
+const CARD_M2 = [ 36, 44 ]
+const CARD_S2 = [ 45, 53 ]
+const CARD_P2 = [ 54, 62 ]
+const CARD_M2X = [ 63, 71 ]
+const CARD_S2X = [ 72, 80 ]
+const CARD_P2X = [ 81, 89 ]
+const CARD_M3 = [ 90, 97 ]
+const CARD_S3 = [ 98, 105 ]
+const CARD_P3 = [ 106, 113 ]
+const CARD_M3X = [ 114, 121 ]
+const CARD_S3X = [ 122, 129 ]
+const CARD_P3X = [ 130, 137 ]
+const CARD_M4 = [ 138, 143 ]
+const CARD_S4 = [ 144, 149 ]
+const CARD_S4B = [ 150, 155 ]
+const CARD_P4 = [ 156, 161 ]
+const CARD_M4X = [ 162, 167 ]
+const CARD_S4X = [ 168, 173 ]
+const CARD_P4X = [ 174, 179 ]
+
+const CARD_INDEX = [
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11,
+ 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15,
+ 15, 15, 15, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 20, 20,
+ 20, 20, 20, 20, 21, 21, 21, 21, 21, 21,
+]
+
+const CARD_INFO = [
+ { name: "M1", type: 0, cost: 1, event: "None" },
+ { name: "S1", type: 1, cost: 1, event: "None" },
+ { name: "P1", type: 2, cost: 1, event: "None" },
+ { name: "M2", type: 0, cost: 2, event: "Castra" },
+ { name: "S2", type: 1, cost: 2, event: "Tribute" },
+ { name: "P2", type: 2, cost: 2, event: "Quaestor" },
+ { name: "M2X", type: 0, cost: 2, event: "Cavalry" },
+ { name: "S2X", type: 1, cost: 2, event: "Princeps Senatus" },
+ { name: "P2X", type: 2, cost: 2, event: "Ambitus" },
+ { name: "M3", type: 0, cost: 3, event: "Flanking Maneuver" },
+ { name: "S3", type: 1, cost: 3, event: "Foederati" },
+ { name: "P3", type: 2, cost: 3, event: "Mob" },
+ { name: "M3X", type: 0, cost: 3, event: "Force March" },
+ { name: "S3X", type: 1, cost: 3, event: "Frumentarii" },
+ { name: "P3X", type: 2, cost: 3, event: "Mobile Vulgus" },
+ { name: "M4", type: 0, cost: 4, event: "Praetorian Guard" },
+ { name: "S4", type: 1, cost: 4, event: "Damnatio Memoriae" },
+ { name: "S4B", type: 1, cost: 4, event: "Damnatio Memoriae (exp)" },
+ { name: "P4", type: 2, cost: 4, event: "Pretender" },
+ { name: "M4X", type: 0, cost: 4, event: "Spiculum" },
+ { name: "S4X", type: 1, cost: 4, event: "Triumph" },
+ { name: "P4X", type: 2, cost: 4, event: "Demagogue" },
+]
+
const ITALIA = 0
const ASIA = 1
const GALLIA = 2
@@ -129,6 +186,16 @@ function is_breakaway(province) {
function is_seat_of_power(province) {
return view.seat_of_power & (1 << province)
}
+function find_governor(f) {
+ let n = view.legacy.length * 6
+ for (let id = 0; id < n; ++id)
+ if (f(id, get_governor_location(id)))
+ return id
+ return -1
+}
+function get_province_governor(where) {
+ return find_governor((id, loc) => loc === where)
+}
// === END SYNC ===
@@ -227,6 +294,21 @@ const LAYOUT_SUPPORT = [
BOXES["Syria Support"],
]
+const LAYOUT_QUAESTOR = [
+ [ 971, 829 ],
+ [ 1622, 994 ],
+ [ 403, 501 ],
+ [ 1327, 930 ],
+ [ 1097, 620 ],
+ [ 1445, 714 ],
+ [ 1643, 1462 ],
+ [ 590, 1284 ],
+ [ 97, 974 ],
+ [ 174, 254 ],
+ [ 1897, 925 ],
+ [ 1977, 1274 ],
+]
+
const LAYOUT_SEA = [ [ 0, 0 ] ]
const LAYOUT_HOMELAND = [
@@ -529,6 +611,8 @@ let ui = {
neutral_governors: [],
barbarian_leaders: [],
rival_emperors: [],
+ seat_of_power: [],
+ breakaway: [],
legions: [],
barbarians: [ [], [], [], [], [] ],
generals: [ [], [], [], [] ],
@@ -629,29 +713,25 @@ function is_action(action, arg) {
}
function on_init() {
- let c = 1
- function init_cards(n, className) {
- for (let i = 0; i < n; ++i)
- ui.cards[c + i] = create("div", { className, my_action: "card", my_id: c + i })
- c += n
+ for (let c = 0; c < CARD_INDEX.length; ++c) {
+ let name = CARD_INFO[CARD_INDEX[c]].name
+ ui.cards[c] = create("div", { className: "card influence_" + name.toLowerCase(), my_action: "card", my_id: c })
}
- init_cards(12, "card influence_m1")
- init_cards(12, "card influence_s1")
- init_cards(12, "card influence_p1")
- init_cards(9, "card influence_m2")
- init_cards(9, "card influence_s2")
- init_cards(9, "card influence_p2")
- init_cards(8, "card influence_m3")
- init_cards(8, "card influence_s3")
- init_cards(8, "card influence_p3")
- init_cards(6, "card influence_m4")
- init_cards(6, "card influence_s4")
- init_cards(6, "card influence_p4")
-
for (let i = 0; i < 33; ++i)
ui.legions[i] = create_piece(i, "legion", "legion", "legion_" + i)
+ for (let p = 0; p < 4; ++p) {
+ for (let i = 0; i < 12; ++i) {
+ ui.seat_of_power[p * 12 + i] = create_thing({ className: PLAYER_CLASS[p] + " seat_of_power hide" })
+ ui.seat_of_power[p * 12 + i].style.left = LAYOUT_QUAESTOR[i][0] + "px"
+ ui.seat_of_power[p * 12 + i].style.top = LAYOUT_QUAESTOR[i][1] + "px"
+ ui.breakaway[p * 12 + i] = create_thing({ className: PLAYER_CLASS[p] + " breakaway hide" })
+ ui.breakaway[p * 12 + i].style.left = LAYOUT_QUAESTOR[i][0] + "px"
+ ui.breakaway[p * 12 + i].style.top = LAYOUT_QUAESTOR[i][1] + "px"
+ }
+ }
+
ui.barbarian_leaders[0] = create_piece(0, "barbarian_leader", "goths", "cniva")
ui.barbarian_leaders[1] = create_piece(1, "barbarian_leader", "sassanids", "ardashir")
ui.barbarian_leaders[2] = create_piece(2, "barbarian_leader", "sassanids", "shapur")
@@ -676,7 +756,9 @@ function on_init() {
ui.mcastra[region] = create_thing({ className: "castra hide" })
ui.militia[region] = create_thing({ className: "militia hide", my_action: "militia", my_id: region })
ui.capital[region] = document.getElementById(REGION_NAME[region] + "_Capital")
- ui.quaestor[region] = document.getElementById(REGION_NAME[region] + "_Quaestor")
+ ui.quaestor[region] = create_thing({ className: "quaestor hide" })
+ ui.quaestor[region].style.left = LAYOUT_QUAESTOR[region][0] + "px"
+ ui.quaestor[region].style.top = LAYOUT_QUAESTOR[region][1] + "px"
// at most 3 mobs per province
ui.mobs[region * 3 + 0] = create_piece(region, "mob", "mob")
@@ -851,6 +933,23 @@ function on_update() {
}
for (let region = 0; region < 12; ++region) {
+ for (let p = 0; p < 4; ++p) {
+ let gov = get_province_governor(region)
+ if (gov > 0 && (gov/6|0) === p) {
+ if (is_seat_of_power(region))
+ show(ui.seat_of_power[region + p * 12])
+ else
+ hide(ui.seat_of_power[region + p * 12])
+ if (is_breakaway(region))
+ show(ui.breakaway[region + p * 12])
+ else
+ hide(ui.breakaway[region + p * 12])
+ } else {
+ hide(ui.seat_of_power[region + p * 12])
+ hide(ui.breakaway[region + p * 12])
+ }
+ }
+
if (has_quaestor(region))
show(ui.quaestor[region])
else
diff --git a/rules.js b/rules.js
index bdac983..8c7b846 100644
--- a/rules.js
+++ b/rules.js
@@ -316,115 +316,118 @@ const EVENT_INFLATION = 13
const EVENT_GOOD_AUGURIES = 14
const EVENT_DIOCLETIAN = 15
-// 12x
-const CARD_M1 = [ 1, 12 ]
-const CARD_S1 = [ 13, 24 ]
-const CARD_P1 = [ 25, 36 ]
-
-// 9x
-const CARD_M2 = [ 37, 45 ]
-const CARD_S2 = [ 46, 54 ]
-const CARD_P2 = [ 55, 63 ]
-
-// 8x
-const CARD_M3 = [ 64, 71 ]
-const CARD_S3 = [ 72, 79 ]
-const CARD_P3 = [ 80, 87 ]
-
-// 6x
-const CARD_M4 = [ 88, 93 ]
-const CARD_S4 = [ 94, 99 ]
-const CARD_P4 = [ 100, 105 ]
+const CARD_M1 = [ 0, 11 ]
+const CARD_S1 = [ 12, 23 ]
+const CARD_P1 = [ 24, 35 ]
+const CARD_M2 = [ 36, 44 ]
+const CARD_S2 = [ 45, 53 ]
+const CARD_P2 = [ 54, 62 ]
+const CARD_M2X = [ 63, 71 ]
+const CARD_S2X = [ 72, 80 ]
+const CARD_P2X = [ 81, 89 ]
+const CARD_M3 = [ 90, 97 ]
+const CARD_S3 = [ 98, 105 ]
+const CARD_P3 = [ 106, 113 ]
+const CARD_M3X = [ 114, 121 ]
+const CARD_S3X = [ 122, 129 ]
+const CARD_P3X = [ 130, 137 ]
+const CARD_M4 = [ 138, 143 ]
+const CARD_S4 = [ 144, 149 ]
+const CARD_S4B = [ 150, 155 ]
+const CARD_P4 = [ 156, 161 ]
+const CARD_M4X = [ 162, 167 ]
+const CARD_S4X = [ 168, 173 ]
+const CARD_P4X = [ 174, 179 ]
+
+const CARD_INDEX = [
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11,
+ 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15,
+ 15, 15, 15, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 20, 20,
+ 20, 20, 20, 20, 21, 21, 21, 21, 21, 21,
+]
+
+const CARD_INFO = [
+ { name: "M1", type: 0, cost: 1, event: "None" },
+ { name: "S1", type: 1, cost: 1, event: "None" },
+ { name: "P1", type: 2, cost: 1, event: "None" },
+ { name: "M2", type: 0, cost: 2, event: "Castra" },
+ { name: "S2", type: 1, cost: 2, event: "Tribute" },
+ { name: "P2", type: 2, cost: 2, event: "Quaestor" },
+ { name: "M2X", type: 0, cost: 2, event: "Cavalry" },
+ { name: "S2X", type: 1, cost: 2, event: "Princeps Senatus" },
+ { name: "P2X", type: 2, cost: 2, event: "Ambitus" },
+ { name: "M3", type: 0, cost: 3, event: "Flanking Maneuver" },
+ { name: "S3", type: 1, cost: 3, event: "Foederati" },
+ { name: "P3", type: 2, cost: 3, event: "Mob" },
+ { name: "M3X", type: 0, cost: 3, event: "Force March" },
+ { name: "S3X", type: 1, cost: 3, event: "Frumentarii" },
+ { name: "P3X", type: 2, cost: 3, event: "Mobile Vulgus" },
+ { name: "M4", type: 0, cost: 4, event: "Praetorian Guard" },
+ { name: "S4", type: 1, cost: 4, event: "Damnatio Memoriae" },
+ { name: "S4B", type: 1, cost: 4, event: "Damnatio Memoriae (exp)" },
+ { name: "P4", type: 2, cost: 4, event: "Pretender" },
+ { name: "M4X", type: 0, cost: 4, event: "Spiculum" },
+ { name: "S4X", type: 1, cost: 4, event: "Triumph" },
+ { name: "P4X", type: 2, cost: 4, event: "Demagogue" },
+]
function card_name(c) {
- if (c >= CARD_M1[0] && c <= CARD_M1[1]) return "M1"
- if (c >= CARD_M2[0] && c <= CARD_M2[1]) return "M2"
- if (c >= CARD_M3[0] && c <= CARD_M3[1]) return "M3"
- if (c >= CARD_M4[0] && c <= CARD_M4[1]) return "M4"
- if (c >= CARD_S1[0] && c <= CARD_S1[1]) return "S1"
- if (c >= CARD_S2[0] && c <= CARD_S2[1]) return "S2"
- if (c >= CARD_S3[0] && c <= CARD_S3[1]) return "S3"
- if (c >= CARD_S4[0] && c <= CARD_S4[1]) return "S4"
- if (c >= CARD_P1[0] && c <= CARD_P1[1]) return "P1"
- if (c >= CARD_P2[0] && c <= CARD_P2[1]) return "P2"
- if (c >= CARD_P3[0] && c <= CARD_P3[1]) return "P3"
- if (c >= CARD_P4[0] && c <= CARD_P4[1]) return "P4"
- return "??"
+ return CARD_INFO[CARD_INDEX[c]].name
}
function card_cost(c) {
- if (c >= CARD_M1[0] && c <= CARD_M1[1]) return 1
- if (c >= CARD_M2[0] && c <= CARD_M2[1]) return 2
- if (c >= CARD_M3[0] && c <= CARD_M3[1]) return 3
- if (c >= CARD_M4[0] && c <= CARD_M4[1]) return 4
- if (c >= CARD_S1[0] && c <= CARD_S1[1]) return 1
- if (c >= CARD_S2[0] && c <= CARD_S2[1]) return 2
- if (c >= CARD_S3[0] && c <= CARD_S3[1]) return 3
- if (c >= CARD_S4[0] && c <= CARD_S4[1]) return 4
- if (c >= CARD_P1[0] && c <= CARD_P1[1]) return 1
- if (c >= CARD_P2[0] && c <= CARD_P2[1]) return 2
- if (c >= CARD_P3[0] && c <= CARD_P3[1]) return 3
- if (c >= CARD_P4[0] && c <= CARD_P4[1]) return 4
- return "??"
+ return CARD_INFO[CARD_INDEX[c]].cost
+}
+
+function card_influence(c) {
+ return CARD_INFO[CARD_INDEX[c]].type
}
function card_event_name(c) {
- if (c >= CARD_M1[0] && c <= CARD_M1[1]) return "None"
- if (c >= CARD_M2[0] && c <= CARD_M2[1]) return "Castra"
- if (c >= CARD_M3[0] && c <= CARD_M3[1]) return "Flanking Maneuver"
- if (c >= CARD_M4[0] && c <= CARD_M4[1]) return "Praetorian Guard"
- if (c >= CARD_S1[0] && c <= CARD_S1[1]) return "None"
- if (c >= CARD_S2[0] && c <= CARD_S2[1]) return "Tribute"
- if (c >= CARD_S3[0] && c <= CARD_S3[1]) return "Foederati"
- if (c >= CARD_S4[0] && c <= CARD_S4[1]) return "Damnatio Memoriae"
- if (c >= CARD_P1[0] && c <= CARD_P1[1]) return "None"
- if (c >= CARD_P2[0] && c <= CARD_P2[1]) return "Quaestor"
- if (c >= CARD_P3[0] && c <= CARD_P3[1]) return "Mob"
- if (c >= CARD_P4[0] && c <= CARD_P4[1]) return "Pretender"
- return "None"
+ return CARD_INFO[CARD_INDEX[c]].event
+}
+
+const PLAY_CARD_EVENT = {
+ "Castra": play_castra,
+ // "Flanking Maneuver": play_flanking_maneuver,
+ "Praetorian Guard": play_praetorian_guard,
+ "Tribute": play_tribute,
+ "Foederati": play_foederati,
+ // "Damnatio Memoriae": play_damnatio_memoriae,
+ // "Damnatio Memoriae (exp)": play_damnatio_memoriae_exp,
+ "Quaestor": play_quaestor,
+ "Mob": play_mob,
+ "Pretender": play_pretender,
+}
+
+const CAN_PLAY_CARD_EVENT = {
+ "Castra": can_play_castra,
+ // "Flanking Maneuver": can_play_flanking_maneuver,
+ "Praetorian Guard": can_play_praetorian_guard,
+ "Tribute": can_play_tribute,
+ "Foederati": can_play_foederati,
+ // "Damnatio Memoriae": can_play_damnatio_memoriae,
+ // "Damnatio Memoriae (exp)": can_play_damnatio_memoriae_exp,
+ "Quaestor": can_play_quaestor,
+ "Mob": can_play_mob,
+ "Pretender": can_play_pretender,
}
function can_play_card_event(c) {
- if (c >= CARD_M1[0] && c <= CARD_M1[1]) return false
- if (c >= CARD_M2[0] && c <= CARD_M2[1]) return can_play_castra()
- if (c >= CARD_M3[0] && c <= CARD_M3[1]) return false // "Flanking Maneuver"
- if (c >= CARD_M4[0] && c <= CARD_M4[1]) return can_play_praetorian_guard()
- if (c >= CARD_S1[0] && c <= CARD_S1[1]) return false
- if (c >= CARD_S2[0] && c <= CARD_S2[1]) return can_play_tribute()
- if (c >= CARD_S3[0] && c <= CARD_S3[1]) return can_play_foederati()
- if (c >= CARD_S4[0] && c <= CARD_S4[1]) return false // "Damnatio Memoriae"
- if (c >= CARD_P1[0] && c <= CARD_P1[1]) return false
- if (c >= CARD_P2[0] && c <= CARD_P2[1]) return can_play_quaestor()
- if (c >= CARD_P3[0] && c <= CARD_P3[1]) return can_play_mob()
- if (c >= CARD_P4[0] && c <= CARD_P4[1]) return false // "Pretender"
- return false
+ let f = CAN_PLAY_CARD_EVENT[card_event_name(c)]
+ return f ? f() : false
}
function play_card_event(c) {
- if (c >= CARD_M2[0] && c <= CARD_M2[1]) play_castra()
- if (c >= CARD_M3[0] && c <= CARD_M3[1]) play_flanking_maneuver()
- if (c >= CARD_M4[0] && c <= CARD_M4[1]) play_praetorian_guard()
- if (c >= CARD_S2[0] && c <= CARD_S2[1]) play_tribute()
- if (c >= CARD_S3[0] && c <= CARD_S3[1]) play_foederati()
- if (c >= CARD_S4[0] && c <= CARD_S4[1]) play_damnatio_memoriae()
- if (c >= CARD_P2[0] && c <= CARD_P2[1]) play_quaestor()
- if (c >= CARD_P3[0] && c <= CARD_P3[1]) play_mob()
- if (c >= CARD_P4[0] && c <= CARD_P4[1]) play_pretender()
+ PLAY_CARD_EVENT[card_event_name(c)]()
}
function add_card_ip(c) {
- if (c >= CARD_M1[0] && c <= CARD_M1[1]) return game.ip[MILITARY] += 1
- if (c >= CARD_M2[0] && c <= CARD_M2[1]) return game.ip[MILITARY] += 2
- if (c >= CARD_M3[0] && c <= CARD_M3[1]) return game.ip[MILITARY] += 3
- if (c >= CARD_M4[0] && c <= CARD_M4[1]) return game.ip[MILITARY] += 4
- if (c >= CARD_S1[0] && c <= CARD_S1[1]) return game.ip[SENATE] += 1
- if (c >= CARD_S2[0] && c <= CARD_S2[1]) return game.ip[SENATE] += 2
- if (c >= CARD_S3[0] && c <= CARD_S3[1]) return game.ip[SENATE] += 3
- if (c >= CARD_S4[0] && c <= CARD_S4[1]) return game.ip[SENATE] += 4
- if (c >= CARD_P1[0] && c <= CARD_P1[1]) return game.ip[POPULACE] += 1
- if (c >= CARD_P2[0] && c <= CARD_P2[1]) return game.ip[POPULACE] += 2
- if (c >= CARD_P3[0] && c <= CARD_P3[1]) return game.ip[POPULACE] += 3
- if (c >= CARD_P4[0] && c <= CARD_P4[1]) return game.ip[POPULACE] += 4
+ let cost = CARD_INFO[CARD_INDEX[c]].cost
+ let type = CARD_INFO[CARD_INDEX[c]].type
+ game.ip[type] += cost
}
function is_region(where) {
@@ -1955,7 +1958,7 @@ function play_castra() {
function can_play_quaestor() {
let where = get_selected_region()
if (game.selected_governor >= 0 && is_province(where))
- return !has_quaestor(where)
+ return !has_quaestor(where) && !is_breakaway(where) && !is_seat_of_power(where)
return false
}
@@ -2100,6 +2103,85 @@ states.mob = {
},
}
+// CARD: PRETENDER
+
+function find_seat_of_power() {
+ for (let where = 1; where < 12; ++where)
+ if (is_seat_of_power(where) && is_own_province(where))
+ return where
+ return -1
+}
+
+function is_possible_seat_of_power(from) {
+ if (is_own_province(from) && get_support(from) >= 3)
+ for (let to of ADJACENT[from])
+ if (is_own_province(to) && get_support(to) >= 3)
+ return true
+ return false
+}
+
+function can_play_pretender() {
+ if (is_emperor_player())
+ return false
+ if (is_pretender_player())
+ return false
+ for (let where = 1; where < 12; ++where)
+ if (is_possible_seat_of_power(where))
+ return true
+ return false
+}
+
+function play_pretender() {
+ game.state = "pretender_seat_of_power"
+}
+
+states.pretender_seat_of_power = {
+ prompt() {
+ prompt("Pretender: Place a Seat of Power.")
+ view.color = POPULACE
+ for (let where = 0; where < 12; ++where)
+ for (let where = 1; where < 12; ++where)
+ if (is_possible_seat_of_power(where))
+ gen_action_region(where)
+ },
+ region(where) {
+ push_undo()
+ log("Seat of Power in S" + where)
+ add_seat_of_power(where)
+ remove_quaestor(where) // no effect anymore
+ goto_pretender_breakaway()
+ },
+}
+
+function goto_pretender_breakaway() {
+ let seat = find_seat_of_power()
+ for (let where of ADJACENT[seat]) {
+ if (get_support(where) >= 3 && !is_breakaway(where) && is_own_province(where)) {
+ game.state = "pretender_breakaway"
+ return
+ }
+ }
+ game.state = "take_actions"
+}
+
+states.pretender_breakaway = {
+ prompt() {
+ prompt("Pretender: Place Breakaway markers.")
+ view.color = POPULACE
+ let seat = find_seat_of_power()
+ for (let where of ADJACENT[seat])
+ if (get_support(where) >= 3 && !is_breakaway(where) && is_own_province(where))
+ gen_action_region(where)
+ },
+ region(where) {
+ push_undo()
+ log("Breakaway in S" + where)
+ add_breakaway(where)
+ remove_quaestor(where) // no effect anymore
+ goto_pretender_breakaway()
+ },
+}
+
// === COMBAT ===
function goto_battle_vs_general(where, attacker, target) {
@@ -2505,7 +2587,10 @@ function goto_combat_victory() {
}
function award_legacy(p, reason, n) {
- log(PLAYER_NAMES[p] + " gained " + n + " Legacy for " + reason + ".")
+ if (n > 0)
+ log(PLAYER_NAMES[p] + " gained " + n + " Legacy for " + reason + ".")
+ if (n < 0)
+ log(PLAYER_NAMES[p] + " lost " + n + " Legacy for " + reason + ".")
game.legacy[p] += n
}
@@ -2680,7 +2765,7 @@ function goto_expand_pretender_empire() {
function goto_gain_legacy() {
log_h3("Gain Legacy")
- if (is_only_pretender())
+ if (is_only_pretender_player())
award_legacy(game.current, "Pretender", count_own_breakaway_provinces())
if (is_emperor_player())
@@ -2699,8 +2784,8 @@ function goto_legitimize_claim() {
states.legitimize_claim = {
prompt() {
prompt("Gain Legacy: Remove Seat of Power and Breakaway markers in your provinces.")
- for (let where = 1; where < 12; ++where) {
- if (is_own_province(where) && is_seat_of_power(where) || is_breakaway(where)) {
+ for (let where = 1; where < 12; ++where)
+ if (is_own_province(where) && is_seat_of_power(where) || is_breakaway(where))
gen_action_region(where)
},
region(where) {
@@ -3151,7 +3236,7 @@ exports.setup = function (seed, scenario, options) {
game.hand[player] = []
game.draw[player] = setup_player_deck(player)
game.discard[player] = []
- game.draw[player].push(game.market[2].pop())
+ for (let i = 0; i < 9; ++i) set_add(game.draw[player], game.market[i].pop())
}
update_neutral_italia()
@@ -3216,6 +3301,8 @@ exports.view = function (state, player_name) {
amphitheater: game.amphitheater,
basilica: game.basilica,
limes: game.limes,
+ seat_of_power: game.seat_of_power,
+ breakaway: game.breakaway,
governors: game.governors,
generals: game.generals,
diff --git a/tools/gencards.js b/tools/gencards.js
new file mode 100644
index 0000000..ee88c70
--- /dev/null
+++ b/tools/gencards.js
@@ -0,0 +1,52 @@
+var ix = 0
+var xx = 0
+
+const M = 0
+const S = 1
+const P = 2
+
+const CARD_INDEX = []
+const CARD_INFO = []
+
+function mk(n, type, cost, name, event) {
+ CARD_INFO[xx] = { name, type, cost, event }
+ var a = ix
+ var b = ix + n - 1
+ for (let i = 0; i < n; ++i)
+ CARD_INDEX[a + i] = xx
+ console.log("const CARD_" + name + " = [ " + a + ", " + b + " ]")
+ ix = b + 1
+ xx += 1
+}
+
+mk(12, M, 1, "M1", "None")
+mk(12, S, 1, "S1", "None")
+mk(12, P, 1, "P1", "None")
+
+mk(9, M, 2, "M2", "Castra")
+mk(9, S, 2, "S2", "Tribute")
+mk(9, P, 2, "P2", "Quaestor")
+
+mk(9, M, 2, "M2X", "Cavalry")
+mk(9, S, 2, "S2X", "Princeps Senatus")
+mk(9, P, 2, "P2X", "Ambitus")
+
+mk(8, M, 3, "M3", "Flanking Maneuver")
+mk(8, S, 3, "S3", "Foederati")
+mk(8, P, 3, "P3", "Mob")
+
+mk(8, M, 3, "M3X", "Force March")
+mk(8, S, 3, "S3X", "Frumentarii")
+mk(8, P, 3, "P3X", "Mobile Vulgus")
+
+mk(6, M, 4, "M4", "Praetorian Guard")
+mk(6, S, 4, "S4", "Damnatio Memoriae")
+mk(6, S, 4, "S4B", "Damnatio Memoriae (exp)")
+mk(6, P, 4, "P4", "Pretender")
+
+mk(6, M, 4, "M4X", "Spiculum")
+mk(6, S, 4, "S4X", "Triumph")
+mk(6, P, 4, "P4X", "Demagogue")
+
+console.log("const CARD_INDEX = " + JSON.stringify(CARD_INDEX))
+console.log("const CARD_INFO = " + JSON.stringify(CARD_INFO))