summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--play.css3
-rw-r--r--play.html3
-rw-r--r--play.js73
-rw-r--r--rules.js426
4 files changed, 360 insertions, 145 deletions
diff --git a/play.css b/play.css
index 45e1c09..f21cb33 100644
--- a/play.css
+++ b/play.css
@@ -392,6 +392,9 @@ body.p2 #Galatia_NPG { display: block }
#ardashir { background-image: url(images/ardashir.png) }
#cniva { background-image: url(images/cniva.png) }
#shapur { background-image: url(images/shapur.png) }
+#ardashir.inactive { background-image: url(images/ardashir_back.png) }
+#cniva.inactive { background-image: url(images/cniva_back.png) }
+#shapur.inactive { background-image: url(images/shapur_back.png) }
#postumus { background-image: url(images/rival_postumus.png) }
#priest_king { background-image: url(images/rival_priest_king.png) }
#zenobia { background-image: url(images/rival_zenobia.png) }
diff --git a/play.html b/play.html
index 5038688..2a68045 100644
--- a/play.html
+++ b/play.html
@@ -51,7 +51,6 @@
<div id="mapwrap">
<div id="map">
<div id="crisis_table"></div>
-<div id="active_event"></div>
<svg id="mapsvg" width="2550" height="1650" viewBox="0 0 2550 1650">
<g class="region" id="region_aegyptus"><path d="M1499 1309c-1 0-3 2-6 4-4 3-12 6-18 6-4 0-21 10-29 17-7 7-15 17-17 24-4 11-2 25 7 39 3 6 4 14 2 21-3 9-14 26-19 30-8 6-16 12-19 13-5 1-6 2-3 18 6 33 6 45 3 64-3 15-6 55-4 60l1 2h662v-4c-1-3-2-5-4-7-2-3-8-11-11-19-1-3-2-6-2-11v-7l-6-5c-4-3-10-10-13-15s-8-11-9-12c-2-1-4-4-4-7-1-2-4-6-5-9-6-7-7-10-6-15 1-6-2-13-9-20-5-6-5-6-5-11 0-3 1-7 2-9 0-1 2-6 3-11 0-5 2-10 3-12l15-15c8-6 14-12 16-15 5-8 8-19 5-19-1 0-3 0-5 1s-3 1-5 0-4-1-10 1c-9 3-15 2-20-2-3-2-5-3-7 0-1 1-4 2-6 3-4 1-5 1-7 0-1-1-2-2-2-3s-1-2-3-3c-6-2-10-7-10-10s0-3-5-3c-3 0-7-1-11-3-3-1-7-2-7-2-1 0-3 2-6 3-5 5-17 8-23 6-2-1-4-1-5 0-1 0-2 2-4 5-2 6-5 7-8 6-5-2-6-1-14 7-20 19-33 23-46 15-8-5-16-8-22-8-6 1-19-1-22-3-1-2-3-2-6-2-6 1-14-2-18-5-3-3-5-4-14-6-7-1-16-3-22-3-6-1-13-3-16-3-9-3-15-2-26 1-5 2-10 4-12 4-5 0-10-4-12-8 0-2-3-7-5-11-4-8-7-9-19-7-4 1-11 1-15 1-7-1-9-1-14-5-6-3-7-3-17-4-12-1-16-2-21-7-4-4-4-4-4-9 1-7 0-9-8-12-3-1-8-2-10-3-3 0-6-1-8-2-3-1-7-3-9-3-5-1-24-2-26-1z"/></g>
@@ -77,6 +76,8 @@
<g class="sea" id="region_pontus_euxinus"><path d="M378 306c-1 1-1 1 0 1s2 0 3-1c0-1-1-1-3 0zM1885 468c-4 1-10 2-13 3-4 3-5 3-5 6 0 4-9 21-15 28-3 3-6 6-7 8-2 3-4 4-8 6-6 1-11 5-11 8 0 1-4 4-7 4-1 0-2 0-2 1s2 5 5 7c2 4 2 7 0 21-1 4-2 9-2 12 0 7-5 11-18 12-6 0-9 1-10 2 0 1-2 1-4 1-4 0-4 0-3 12 0 1-1 4-3 8l-4 6v12c0 7 0 15-1 18 0 4-1 7 0 11 1 6 0 11-4 14-2 2-3 2-7 2-7 0-9 1-12 6-1 2-3 5-4 7-1 3-1 6-1 16s-1 12-2 14c-2 2-2 3 2 3 2 0 5 1 8 2 6 3 7 6 7 27 0 12 0 21-1 23-1 5-1 5 1 8s9 7 23 13c10 4 13 4 22 5 7 1 16 2 22 2 14 2 16 2 23-1 5-2 5-2 9-1 13 5 28 6 36 3 4-1 5-2 6-6 2-6 2-6 10-11 16-10 20-13 25-18 6-5 21-13 27-14 3-1 9-3 14-6l10-5h21c11 1 26 1 33 0h12l5-4c6-6 10-4 14 6 2 7 6 11 11 13 6 3 9 2 17-1l7-3 4 2c5 2 8 7 8 12 0 3 1 4 5 8 3 3 6 5 7 5 0 0 2-1 4-3 3-3 4-3 9-3 7 0 13 3 16 7 1 3 3 4 6 5 2 0 6 1 9 2 5 2 5 2 8 1 4-3 7-2 11 1 3 3 5 3 13 4 12 2 17 2 25-1 11-5 18-7 24-8 3-1 7-1 9-2 2 0 4 0 7 2s6 3 20 5c7 1 7 1 12-2 3-1 7-3 9-4s6-3 8-5c3-2 7-5 9-5 6-2 21-13 23-17 2-2 4-6 7-10 6-9 6-13 2-23-3-8-6-16-9-28-3-9-5-12-10-13-8-2-9-3-11-7-1-2-3-4-4-4-1-1-3-2-5-4s-5-2-10-3c-9-1-16-4-19-9-2-2-4-4-8-6-5-2-15-10-32-26-11-11-16-15-24-21-3-2-7-4-8-5s-7-3-11-4c-11-1-14-3-17-7-1-2-4-4-6-6-4-3-5-3-13-3-7-1-8-1-12-4-2-1-5-5-6-7-2-3-4-6-5-7-3-3-14-7-20-8-3 0-6-1-7-3-4-2-4-3 0-7l2-3-2 1c-3 1-4 2-4 7 0 2 0 5-1 6-2 3-7 5-14 6-4 1-9 1-11 2-2 0-4 0-8-3-2-2-5-3-6-3-2 0-4 2-7 4-2 3-6 7-9 10-5 5-6 5-12 5-10 1-19 5-21 10-4 6-15 16-20 17-9 3-18 1-28-7-4-3-4-5 0-9 1-2 2-4 2-6s1-6 2-8c1-3 1-4 0-7-2-6-5-8-11-8-4 0-6-1-12-5-7-4-7-4-18-2-3 0-4 0-7-2-5-5-2-12 6-16 1-1 4-3 7-5 2-2 8-6 12-8s9-4 10-5c1 0 5-2 8-4 3-1 5-2 5-3 0-3-1-4-5-4-2 0-5-1-8-2-4-2-5-2-14-1-6 1-13 2-17 3-7 1-13 1-18-3-5-3-11-6-16-7-5-2-6-2-6-4s1-3 2-4c2-2 2-2 1-3s-3-1-5 0c-4 0-7-2-7-6-1-3-3-3-14-2zM1007 1292c0 1 0 1 1 1s1 0 1-1 0-1-1-1-1 0-1 1z"/></g>
</svg>
+<div id="active_event"></div>
+
<div id="pieces">
<div id="crisis_die_1" class="hide" style="right:175px;top:530px"></div>
diff --git a/play.js b/play.js
index 8a5cf42..da4efe3 100644
--- a/play.js
+++ b/play.js
@@ -1,10 +1,13 @@
"use strict"
// TODO: battle dialog popup for rolling and assigning hits!
-// TODO: move barbarian dice to current homeland
+// TODO: show killed leaders taken for bonus purchase
// === SYNC with rules.js ===
+const LEGION_COUNT = 33
+const BARBARIAN_COUNT = 53
+
const CARD_M1 = [ 0, 11 ]
const CARD_S1 = [ 12, 23 ]
const CARD_P1 = [ 24, 35 ]
@@ -77,6 +80,12 @@ const BRITANNIA = 9
const GALATIA = 10
const SYRIA = 11
+const ALAMANNI = 0
+const FRANKS = 1
+const GOTHS = 2
+const NOMADS = 3
+const SASSANIDS = 4
+
const ALAMANNI_HOMELAND = 12
const FRANKS_HOMELAND = 13
const GOTHS_HOMELAND = 14
@@ -93,13 +102,15 @@ const UNAVAILABLE = 22
const ARMY = 23
-const TRIBE_COUNT = [ 0, 5, 3, 4, 5 ]
-const BARBARIAN_COUNT = [ 0, 50, 30, 40, 50 ]
-const first_barbarian = [ 0, 10, 20, 30, 40 ]
-const last_barbarian = [ 9, 19, 29, 39, 49 ]
+const first_barbarian = [ 0, 10, 20, 31, 41 ]
+const last_barbarian = [ 9, 19, 30, 40, 52 ]
const first_governor = [ 0, 6, 12, 18 ]
const first_general = [ 0, 6, 12, 18 ]
+const CNIVA = first_barbarian[GOTHS] + 0
+const ARDASHIR = first_barbarian[SASSANIDS] + 0
+const SHAPUR = first_barbarian[SASSANIDS] + 1
+
const REGION_NAME = [
"Italia",
"Asia",
@@ -740,7 +751,7 @@ function on_init() {
ui.event_cards[e] = create("div", { className: "card event event_" + e })
}
- for (let i = 0; i < 33; ++i)
+ for (let i = 0; i < LEGION_COUNT; ++i)
ui.legions[i] = create_piece(i, "legion", "legion", "legion_" + i)
for (let p = 0; p < 4; ++p) {
@@ -754,10 +765,6 @@ function on_init() {
}
}
- 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")
-
ui.rival_emperors[0] = create_piece(0, "rival_emperor", "rival_emperor", "postumus")
ui.rival_emperors[1] = create_piece(1, "rival_emperor", "rival_emperor", "priest_king")
ui.rival_emperors[2] = create_piece(2, "rival_emperor", "rival_emperor", "zenobia")
@@ -766,6 +773,10 @@ function on_init() {
for (let id = first_barbarian[tribe]; id <= last_barbarian[tribe]; ++id)
ui.barbarians[id] = create_piece(id, "barbarian", BARBARIAN_CLASS[tribe])
+ ui.barbarians[CNIVA].id = "cniva"
+ ui.barbarians[SHAPUR].id = "shapur"
+ ui.barbarians[ARDASHIR].id = "ardashir"
+
for (let p = 0; p < 4; ++p) {
for (let g = 0; g < 6; ++g) {
ui.castra[p][g] = create_thing({ className: "castra hide" })
@@ -1013,7 +1024,7 @@ function on_update() {
hide(ui.militia[region])
}
- for (let i = 0; i < 33; ++i) {
+ for (let i = 0; i < LEGION_COUNT; ++i) {
if (is_legion_unused(i))
hide(ui.legions[i])
else
@@ -1024,28 +1035,27 @@ function on_update() {
ui.legions[i].classList.toggle("reduced", false)
}
- // TODO: Cniva, Ardashir, and Shapur
- // TODO: Zenobia, Postumus, Priest King
-
- for (let id = 0; id < BARBARIAN_COUNT[player_count]; ++id) {
- show(ui.barbarians[id])
+ for (let id = 0; id < BARBARIAN_COUNT; ++id) {
+ let loc = get_barbarian_location(id)
+ if (loc === UNAVAILABLE)
+ hide(ui.barbarians[id])
+ else
+ show(ui.barbarians[id])
if (is_barbarian_inactive(id))
ui.barbarians[id].classList.toggle("inactive", true)
else
ui.barbarians[id].classList.toggle("inactive", false)
}
- for (let id = BARBARIAN_COUNT[player_count]; id < ui.barbarians.length; ++id)
- hide(ui.barbarians[id])
-
stack_count.fill(0)
for (let region = 0; region < 12 + 5; ++region) {
- for (let tribe = 0; tribe < TRIBE_COUNT[player_count]; ++tribe) {
+ for (let tribe = 0; tribe < 5; ++tribe) {
let active_barbarians = []
let inactive_barbarians = []
- // TODO: Cniva, Ardashir, and Shapur
for (let id = first_barbarian[tribe]; id <= last_barbarian[tribe]; ++id) {
+ if (id === CNIVA || id === ARDASHIR || id === SHAPUR)
+ continue
let loc = get_barbarian_location(id)
let inactive = is_barbarian_inactive(id)
if (loc === region) {
@@ -1065,13 +1075,19 @@ function on_update() {
}
}
- for (let re = 0; re < 3; ++re) {
- let loc = get_rival_emperor_location(re)
+ for (let id of [ CNIVA, ARDASHIR, SHAPUR ]) {
+ let loc = get_barbarian_location(id)
+ if (loc !== UNAVAILABLE)
+ layout_stack(-1, [ ui.barbarians[id] ], loc, false, 8, 8)
+ }
+
+ for (let id = 0; id < 3; ++id) {
+ let loc = get_rival_emperor_location(id)
if (loc === UNAVAILABLE)
- hide(ui.rival_emperors[re])
+ hide(ui.rival_emperors[id])
else {
- show(ui.rival_emperors[re])
- layout_stack(-1, [ ui.rival_emperors[re] ], loc, false, 8, 8)
+ show(ui.rival_emperors[id])
+ layout_stack(-1, [ ui.rival_emperors[id] ], loc, false, 8, 8)
}
}
@@ -1144,13 +1160,13 @@ function on_update() {
stack.push(e)
- for (let i = 0; i < 33; ++i) {
+ for (let i = 0; i < LEGION_COUNT; ++i) {
let loc = get_legion_location(i)
if (loc === army)
stack.push(ui.legions[i])
}
- for (let tribe = 0; tribe < TRIBE_COUNT[player_count]; ++tribe) {
+ for (let tribe = 0; tribe < 5; ++tribe) {
for (let id = first_barbarian[tribe]; id <= last_barbarian[tribe]; ++id) {
let loc = get_barbarian_location(id)
if (loc === army)
@@ -1287,6 +1303,7 @@ function on_update() {
action_button("end_actions", "End Actions")
+ action_button("save", "Save")
action_button("pass", "Pass")
action_button("done", "Done")
action_button("undo", "Undo")
diff --git a/rules.js b/rules.js
index 9b51295..2c866d6 100644
--- a/rules.js
+++ b/rules.js
@@ -1,28 +1,14 @@
"use strict"
-// TODO: barbarian leaders -> barbarian list
/*
TODO
----
+[ ] cut holes for capital in region svg
[ ] crisis pax deorum
[ ] combat battle screen - splay stack / dialog for watching contents and taking hits
-
-[ ] rival emperors
- [ ] emperor turns
- [ ] combat
- [ ] support check
- [ ] combat bonus
- [ ] buy/trash bonus
-
-[ ] barbarian leaders
- [ ] invasion
- [ ] combat bonus
- [ ] combat effect
- [ ] buy/trash bonus
-
-[ ] other events
+[ ] killed leader stash for buy/trash phase
*/
@@ -65,6 +51,7 @@ const SENATE = 1
const POPULACE = 2
const LEGION_COUNT = 33
+const BARBARIAN_COUNT = 53
// REGIONS
@@ -175,9 +162,20 @@ const GOTHS = 2
const NOMADS = 3
const SASSANIDS = 4
-const BARBARIAN_COUNT = [ 0, 50, 30, 40, 50 ]
-const first_barbarian = [ 0, 10, 20, 30, 40 ]
-const last_barbarian = [ 9, 19, 29, 39, 49 ]
+const first_barbarian = [ 0, 10, 20, 31, 41 ]
+const last_barbarian = [ 9, 19, 30, 40, 52 ]
+
+const CNIVA = first_barbarian[GOTHS] + 0
+const ARDASHIR = first_barbarian[SASSANIDS] + 0
+const SHAPUR = first_barbarian[SASSANIDS] + 1
+
+const POSTUMUS = 0
+const PRIEST_KING = 1
+const ZENOBIA = 2
+
+const CNIVA_BONUS = 1 << 3
+const ARDASHIR_BONUS = 1 << 4
+const SHAPUR_BONUS = 1 << 5
const GENERAL_NAME = [
"Red 0", "Red 1", "Red 2", "Red 3", "Red 4", "Red 5",
@@ -202,14 +200,6 @@ const BARBARIAN_HOMELAND = [
SASSANIDS_HOMELAND,
]
-const CNIVA = 0
-const ARDASHIR = 1
-const SHAPUR = 2
-
-const POSTUMUS = 0
-const PRIEST_KING = 1
-const ZENOBIA = 2
-
const BARBARIAN_INVASION = [
// Alamanni
[
@@ -456,6 +446,10 @@ function get_barbarian_tribe(id) {
return -1
}
+function is_barbarian_leader(id) {
+ return id === CNIVA || id === ARDASHIR || id === SHAPUR
+}
+
// === BOARD STATE ===
function is_no_place_governor(where) {
@@ -725,8 +719,6 @@ function is_neutral_province(where) {
}
function has_active_barbarians(where) {
- if (has_barbarian_leader(where))
- return true
return some_barbarian((id, loc, active) => loc === where && active)
}
@@ -748,6 +740,13 @@ function find_active_barbarian_of_tribe(where, tribe) {
return -1
}
+function find_active_non_leader_barbarian_of_tribe(where, tribe) {
+ for (let id = first_barbarian[tribe]; id <= last_barbarian[tribe]; ++id)
+ if (!is_barbarian_leader(id) && get_barbarian_location(id) === where && is_barbarian_active(id))
+ return id
+ return -1
+}
+
function find_inactive_barbarian_of_tribe(where, tribe) {
for (let id = first_barbarian[tribe]; id <= last_barbarian[tribe]; ++id)
if (get_barbarian_location(id) === where && is_barbarian_inactive(id))
@@ -755,11 +754,11 @@ function find_inactive_barbarian_of_tribe(where, tribe) {
return -1
}
-function has_barbarian_leader(where) {
- for (let i = 0; i < 3; ++i)
- if (game.barbarian_leaders[i] === where)
- return true
- return false
+function find_inactive_non_leader_barbarian_of_tribe(where, tribe) {
+ for (let id = first_barbarian[tribe]; id <= last_barbarian[tribe]; ++id)
+ if (!is_barbarian_leader(id) && get_barbarian_location(id) === where && is_barbarian_inactive(id))
+ return id
+ return -1
}
function has_rival_emperor(where) {
@@ -1015,8 +1014,30 @@ function roll_dice_no_reroll(count, target) {
function eliminate_barbarian(id) {
let tribe = get_barbarian_tribe(id)
- set_barbarian_location(id, BARBARIAN_HOMELAND[tribe])
- set_barbarian_inactive(id)
+ if (is_barbarian_leader(id) && game.battle) {
+ if (id === CNIVA) {
+ log("Cniva killed!")
+ game.battle.killed |= CNIVA_BONUS
+ }
+ if (id === ARDASHIR) {
+ log("Ardashir killed!")
+ game.battle.killed |= ARDASHIR_BONUS
+ }
+ if (id === SHAPUR) {
+ log("Shapur killed!")
+ game.battle.killed |= SHAPUR_BONUS
+ }
+ set_barbarian_location(id, UNAVAILABLE)
+ } else {
+ set_barbarian_location(id, BARBARIAN_HOMELAND[tribe])
+ set_barbarian_inactive(id)
+ }
+}
+
+function eliminate_rival_emperor(id) {
+ if (game.battle)
+ game.battle.killed |= (1 << id)
+ set_rival_emperor_location(id, UNAVAILABLE)
}
function eliminate_militia(where) {
@@ -1035,6 +1056,7 @@ function assign_hit_to_legion(id) {
if (is_legion_reduced(id)) {
set_legion_location(id, AVAILABLE)
if (count_legions_in_army(army) === 0) {
+ log(GENERAL_NAME[army] + " killed!")
set_general_location(army, AVAILABLE)
clear_general_battled(army)
}
@@ -1140,6 +1162,7 @@ states.setup_hand = {
function goto_start_turn() {
log_h2(PLAYER_NAMES[game.current])
+ game.killed = 0
game.battled = 0
game.mbattled = 0
game.placed = 0
@@ -1273,6 +1296,11 @@ function roll_barbarian_crisis() {
let black = game.dice[2] = roll_die()
let white = game.dice[3] = roll_die()
+ if (game.active_event === EVENT_RAIDING_PARTIES)
+ black = Math.max(1, black - 2)
+ if (game.active_event === EVENT_PREPARING_FOR_WAR)
+ black = Math.min(6, black + 2)
+
logi(`B${black} W${white}`)
if (black <= count_active_barbarians_at_home(tribe))
@@ -1284,6 +1312,13 @@ function roll_barbarian_crisis() {
function goto_barbarian_invasion(tribe, black, white) {
logi("Invasion!")
game.count = game.dice[2]
+
+ // Ardashir: ALL active Sassanids invade!
+ if (tribe === SASSANIDS) {
+ if (get_barbarian_location(ARDASHIR) === SASSANIDS_HOMELAND)
+ game.count = count_active_barbarians_at_home(tribe)
+ }
+
game.state = "barbarian_invasion"
}
@@ -1351,6 +1386,28 @@ function goto_crisis_event() {
goto_take_actions()
}
+function get_improvement_cost() {
+ if (game.active_event === EVENT_INFLATION)
+ return 4
+ return 3
+}
+
+function get_roman_drm() {
+ if (game.active_event === EVENT_BAD_AUGURIES)
+ return 1
+ if (game.active_event === EVENT_GOOD_AUGURIES)
+ return -1
+ return 0
+}
+
+function get_plague_hits() {
+ if (game.active_event === EVENT_PLAGUE_OF_CYPRIAN) {
+ log("Plague B0")
+ return 1
+ }
+ return 0
+}
+
// CRISIS: BARBARIAN LEADER
function goto_crisis_barbarian_leader(id, where) {
@@ -1365,14 +1422,11 @@ states.crisis_barbarian_leader = {
gen_action_region(game.where)
},
region(where) {
- set_barbarian_leader_location(game.count, game.where)
+ set_barbarian_location(game.count, game.where)
goto_take_actions()
},
}
-function set_barbarian_leader_location(id, where) {
-}
-
// CRISIS: RIVAL EMPEROR
function goto_crisis_rival_emperor(id, where) {
@@ -1387,7 +1441,6 @@ states.crisis_rival_emperor = {
gen_action_region(game.where)
},
region(where) {
- console.log("RE", game.count, game.where)
set_rival_emperor_location(game.count, game.where)
goto_take_actions()
},
@@ -1415,23 +1468,33 @@ function resume_palmyra_allies() {
states.palmyra_allies = {
prompt() {
prompt("Palmyra Allies: Remove " + game.count + " active Sassanids.")
- let id
+ let id, where
+
+ where = get_barbarian_location(SHAPUR)
+ if (where === GALATIA || where === SYRIA || where === SASSANIDS_HOMELAND)
+ gen_action_barbarian(SHAPUR)
+
+ where = get_barbarian_location(ARDASHIR)
+ if (where === GALATIA || where === SYRIA || where === SASSANIDS_HOMELAND)
+ gen_action_barbarian(ARDASHIR)
- // TODO: barbarian leaders
- id = find_active_barbarian_of_tribe(SASSANIDS, GALATIA)
+ id = find_active_non_leader_barbarian_of_tribe(SASSANIDS, GALATIA)
if (id >= 0)
gen_action_barbarian(id)
- id = find_active_barbarian_of_tribe(SASSANIDS, SYRIA)
+ id = find_active_non_leader_barbarian_of_tribe(SASSANIDS, SYRIA)
if (id >= 0)
gen_action_barbarian(id)
- id = find_active_barbarian_of_tribe(SASSANIDS, SASSANIDS_HOMELAND)
+ id = find_active_non_leader_barbarian_of_tribe(SASSANIDS, SASSANIDS_HOMELAND)
if (id >= 0)
gen_action_barbarian(id)
},
barbarian(id) {
push_undo()
eliminate_barbarian(id)
- resume_palmyra_allies()
+ if (--game.count === 0)
+ goto_take_actions()
+ else
+ resume_palmyra_allies()
},
}
@@ -1619,7 +1682,7 @@ states.take_actions = {
// Build an Improvement
if (can_build_improvement(where)) {
- if (pip >= 3) {
+ if (pip >= get_improvement_cost()) {
if (!has_amphitheater(where))
view.actions.amphitheater = 1
if (!has_basilica(where))
@@ -1764,13 +1827,13 @@ states.take_actions = {
push_undo()
let where = get_governor_location(game.selected_governor)
log("Held Games in S" + where + ".")
- spend_ip(POPULACE, 3)
+ spend_ip(POPULACE, 2)
remove_one_mob(where)
},
amphitheater() {
push_undo()
- spend_ip(POPULACE, 3)
+ spend_ip(POPULACE, get_improvement_cost())
let where = get_governor_location(game.selected_governor)
add_amphitheater(where)
log("Built Amphitheater in S" + where + ".")
@@ -1778,7 +1841,7 @@ states.take_actions = {
basilica() {
push_undo()
- spend_ip(POPULACE, 3)
+ spend_ip(POPULACE, get_improvement_cost())
let where = get_governor_location(game.selected_governor)
add_basilica(where)
log("Built Basilica in S" + where + ".")
@@ -1786,7 +1849,7 @@ states.take_actions = {
limes() {
push_undo()
- spend_ip(POPULACE, 3)
+ spend_ip(POPULACE, get_improvement_cost())
let where = get_governor_location(game.selected_governor)
add_limes(where)
log("Built Limes in S" + where + ".")
@@ -1880,11 +1943,17 @@ function enter_capital() {
if (is_pretender_province(where) && is_enemy_province(where)) {
game.count = get_province_governor(where) / 6 | 0
game.where = where
- if (is_seat_of_power(where))
+ if (is_seat_of_power(where)) {
game.state = "occupy_seat_of_power_1"
- else
+ return
+ } else {
game.state = "occupy_breakaway"
+ return
+ }
}
+
+ if (game.battle)
+ end_battle()
}
function resume_occupy_seat_of_power() {
@@ -2408,8 +2477,11 @@ states.tribute = {
function can_foederati_from_region(where) {
let tribe_count = get_tribe_count()
for (let tribe = 0; tribe < tribe_count; ++tribe) {
- if (find_barbarian_of_tribe(where, tribe) >= 0)
+ if (find_active_non_leader_barbarian_of_tribe(where, tribe) >= 0)
return true
+ if (is_province(where))
+ if (find_inactive_non_leader_barbarian_of_tribe(where, tribe) >= 0)
+ return true
}
return false
}
@@ -2417,11 +2489,11 @@ function can_foederati_from_region(where) {
function gen_foederati(where) {
let tribe_count = get_tribe_count()
for (let tribe = 0; tribe < tribe_count; ++tribe) {
- let id = find_active_barbarian_of_tribe(where, tribe)
+ let id = find_active_non_leader_barbarian_of_tribe(where, tribe)
if (id >= 0)
gen_action_barbarian(id)
if (is_province(where)) {
- id = find_inactive_barbarian_of_tribe(where, tribe)
+ id = find_inactive_non_leader_barbarian_of_tribe(where, tribe)
if (id >= 0)
gen_action_barbarian(id)
}
@@ -2609,7 +2681,7 @@ function goto_battle_vs_militia(where, attacker) {
function goto_battle(type, where, attacker, target) {
spend_ip(MILITARY, 1)
game.where = where
- game.battle = { type, attacker, target, flanking: 0 }
+ game.battle = { type, attacker, target, flanking: 0, killed: 0 }
game.state = "battle"
if (attacker >= 0) {
if (is_general_inside_capital(attacker))
@@ -2628,7 +2700,7 @@ function gen_initiate_battle(where) {
if (loc === where && is_enemy_general(id))
gen_action_general(id)
})
- let tribe_count = get_tribe_count()
+ let tribe_count = 5
for (let tribe = 0; tribe < tribe_count; ++tribe) {
let id = find_active_barbarian_of_tribe(where, tribe)
if (id >= 0)
@@ -2643,6 +2715,9 @@ function gen_initiate_battle(where) {
if (has_lone_militia(where))
gen_action_militia(where)
}
+ for (let id = 0; id < 3; ++id)
+ if (get_rival_emperor_location(id) === where)
+ gen_action_rival_emperor(id)
}
}
@@ -2688,44 +2763,40 @@ states.flanking_maneuver = {
}
function roll_combat_dice() {
- game.battle.dhits = roll_attacker_dice()
game.battle.dtaken = 0
+ game.battle.ataken = 0
- if (game.battle.type === "militia" && has_militia_castra(game.where)) {
- log("Castra reduces 1 hit")
- if (game.battle.dhits > 0)
- game.battle.dhits -= 1
- }
- if (game.battle.type === "general" && has_general_castra(game.battle.target)) {
- log("Castra reduces 1 hit")
- if (game.battle.dhits > 0)
- game.battle.dhits -= 1
- }
+ game.battle.dhits = roll_attacker_dice()
+ log("Total " + game.battle.dhits + " hits!")
game.battle.ahits = roll_defender_dice()
- game.battle.ataken = 0
+ log("Total " + game.battle.ahits + " hits!")
+ log_br()
}
function roll_flanking_maneuver_dice() {
log("Flanking Maneuver Reroll")
- game.battle.ahits = roll_defender_dice()
- game.battle.ataken = 0
+ game.battle.dhits = roll_defender_dice()
+ log("Total " + game.battle.dhits + " hits!")
+ log_br()
}
function roll_general_dice(general) {
let army = ARMY + general
let n = 0
+ let drm = get_roman_drm()
+
log(GENERAL_NAME[general])
if (is_general_inside_capital(general) && has_militia(game.where)) {
log("Militia")
- n += roll_dice(1, 5)
+ n += roll_dice(1, 5 + drm)
}
let full_strength = 0
let reduced = 0
- for (let id = 0; id < 33; ++id) {
+ for (let id = 0; id < LEGION_COUNT; ++id) {
if (get_legion_location(id) === army) {
if (is_legion_reduced(id))
reduced += 1
@@ -2735,11 +2806,11 @@ function roll_general_dice(general) {
}
if (full_strength > 0) {
log("Legions")
- n += roll_dice(full_strength, 3)
+ n += roll_dice(full_strength, 3 + drm)
}
if (reduced > 0) {
log("Reduced Legions")
- n += roll_dice(reduced, 5)
+ n += roll_dice(reduced, 5 + drm)
}
let barbarians = 0
@@ -2748,7 +2819,7 @@ function roll_general_dice(general) {
barbarians += 1
if (barbarians > 0) {
log("Barbarians")
- n += roll_dice(barbarians, 4)
+ n += roll_dice(barbarians, 4 + drm)
}
return n
@@ -2756,7 +2827,7 @@ function roll_general_dice(general) {
function roll_militia_dice() {
log("Militia")
- return roll_dice(1, 5)
+ return roll_dice(1, 5 + get_roman_drm())
}
function roll_rival_emperor_dice(rival_emperor) {
@@ -2771,35 +2842,68 @@ function roll_barbarian_dice(tribe) {
for (let id = first_barbarian[tribe]; id <= last_barbarian[tribe]; ++id)
if (get_barbarian_location(id) === game.where)
if (prov || is_barbarian_active(id))
- n += 1
+ n += is_barbarian_leader(id) ? 2 : 1
return roll_dice(n, 4)
}
function roll_attacker_dice() {
log_h3("ATTACKER")
+
+ let n = get_plague_hits()
if (game.battle.attacker < 0)
- return roll_militia_dice()
+ n = roll_militia_dice()
else
- return roll_general_dice(game.battle.attacker)
+ n = roll_general_dice(game.battle.attacker)
+
+ if (game.battle.type === "militia" && has_militia_castra(game.where)) {
+ log("Castra reduces 1 hit")
+ n -= 1
+ }
+ if (game.battle.type === "general" && has_general_castra(game.battle.target)) {
+ log("Castra reduces 1 hit")
+ n -= 1
+ }
+
+ if (game.battle.type === "barbarians" && get_barbarian_location(SHAPUR) === game.where) {
+ log("Shapur I reduced 1 hit")
+ n -= 1
+ }
+
+ return Math.max(0, n)
}
function roll_defender_dice() {
log_h3("DEFENDER")
+
+ let n = get_plague_hits()
switch (game.battle.type) {
case "militia":
- return roll_militia_dice()
+ n = roll_militia_dice()
+ break
case "rival_emperor":
- return roll_rival_emperor_dice(game.battle.target)
+ n = roll_rival_emperor_dice(game.battle.target)
+ break
case "barbarians":
- return roll_barbarian_dice(game.battle.target)
+ n = roll_barbarian_dice(game.battle.target)
+ break
case "general":
- return roll_general_dice(game.battle.target)
+ n = roll_general_dice(game.battle.target)
+ break
}
- return 0
+
+ return Math.max(0, n)
}
// COMBAT: ASSIGN HITS
+function has_hits_rival_emperor(id) {
+ return get_rival_emperor_location(id) !== UNAVAILABLE
+}
+
+function gen_hits_rival_emperor(id) {
+ gen_action_rival_emperor(id)
+}
+
function has_hits_militia() {
return has_militia(game.where)
}
@@ -2833,7 +2937,7 @@ function has_hits_general(general) {
for (let id = 0; id < game.barbarians.length; ++id)
if (get_barbarian_location(id) === army)
return true
- for (let id = 0; id < 33; ++id)
+ for (let id = 0; id < LEGION_COUNT; ++id)
if (get_legion_location(id) === army)
return true
return false
@@ -2860,7 +2964,7 @@ function gen_hits_general(general) {
// NOTE: reduce all legions before eliminating any
if (!done) {
- for (let id = 0; id < 33; ++id) {
+ for (let id = 0; id < LEGION_COUNT; ++id) {
if (get_legion_location(id) === army && !is_legion_reduced(id)) {
gen_action_legion(id)
done = true
@@ -2869,7 +2973,7 @@ function gen_hits_general(general) {
}
if (!done) {
- for (let id = 0; id < 33; ++id) {
+ for (let id = 0; id < LEGION_COUNT; ++id) {
if (get_legion_location(id) === army && is_legion_reduced(id)) {
gen_action_legion(id)
done = true
@@ -2984,6 +3088,11 @@ states.assign_hits_on_defender = {
eliminate_barbarian(id)
goto_assign_hits_on_defender()
},
+ rival_emperor(id) {
+ game.battle.dtaken += 1
+ eliminate_rival_emperor(id)
+ goto_assign_hits_on_defender()
+ }
}
function is_attacker_eliminated() {
@@ -3013,7 +3122,6 @@ function is_defender_eliminated() {
function goto_combat_victory() {
let de = is_defender_eliminated()
let ae = is_attacker_eliminated()
- console.log("goto_combat_victory", de, ae)
if (de && ae)
end_battle()
else if (de || game.battle.dtaken > game.battle.ataken)
@@ -3031,15 +3139,15 @@ function award_legacy(p, reason, n) {
}
function goto_combat_victory_defender() {
+ game.battle.killed = 0
if (game.battle.type === "general")
award_legacy(game.battle.target / 6 | 0, "Victory", 2)
if (game.battle.type === "militia")
- award_legacy(get_province_governor(game.where) / 6 | 0, "Victory", 2)
+ award_legacy(get_province_player(game.where), "Victory", 2)
end_battle()
}
function goto_combat_victory_attacker() {
-
if (game.battle.type === "barbarians") {
award_legacy(game.current, "Victory", 2 + game.battle.dtaken)
@@ -3058,8 +3166,6 @@ function goto_combat_victory_attacker() {
remove_general_castra(game.battle.target)
}
- // TODO: barbarian leader / rival emperor bonus
-
if (can_enter_capital(game.where))
game.state = "advance_after_combat"
else
@@ -3074,7 +3180,6 @@ states.advance_after_combat = {
},
capital(where) {
push_undo()
- end_battle()
enter_capital()
},
pass() {
@@ -3084,10 +3189,43 @@ states.advance_after_combat = {
}
function end_battle() {
+ // Deselect eliminated general...
+ if (game.selected_general >= 0 && get_general_location(game.selected_general) === AVAILABLE)
+ game.selected_general = -1
+ if (game.battle.killed && can_free_increase_support_level(game.where)) {
+ game.state = "free_increase_support_level"
+ return
+ }
game.battle = null
game.state = "take_actions"
}
+function can_free_increase_support_level(where) {
+ return where !== ITALIA && get_support(where) < 4 && is_own_province(where)
+}
+
+states.free_increase_support_level = {
+ prompt() {
+ prompt("Combat: Increase Support Level or use Leader to buy cheaper card?")
+ view.color = POPULACE
+ gen_action_region(game.where)
+ view.actions.save = 1
+ },
+ region(where) {
+ push_undo()
+ increase_support(game.where)
+ game.battle = null
+ game.state = "take_actions"
+ },
+ save() {
+ push_undo()
+ log("Saved for cost reduction.")
+ game.killed |= game.battle.killed
+ game.battle = null
+ game.state = "take_actions"
+ },
+}
+
// === SUPPORT CHECK ===
function goto_support_check() {
@@ -3097,7 +3235,7 @@ function goto_support_check() {
function is_any_rival_emperor_or_pretender() {
for (let i = 0; i < 3; ++i)
- if (get_rival_emperor_location(i) === UNAVAILABLE)
+ if (get_rival_emperor_location(i) !== UNAVAILABLE)
return true
for (let where = 0; where < 12; ++where)
if (is_seat_of_power(where) && is_enemy_province(where))
@@ -3329,9 +3467,47 @@ function find_market_with_card(c) {
return null
}
+function has_military_card_bonus() {
+ let military_bonus = 0
+ if (game.killed & CNIVA_BONUS)
+ military_bonus += 2
+ if (game.killed & ARDASHIR_BONUS)
+ military_bonus += 2
+ if (game.killed & SHAPUR_BONUS)
+ military_bonus += 2
+ return military_bonus
+}
+
+function has_senate_card_bonus() {
+ let senate_bonus = 0
+ if (game.killed & (1 << POSTUMUS))
+ senate_bonus += 2
+ if (game.killed & (1 << PRIEST_KING))
+ senate_bonus += 2
+ if (game.killed & (1 << ZENOBIA))
+ senate_bonus += 2
+ return senate_bonus
+}
+
+function spend_military_card_bonus() {
+ game.killed &= ~(CNIVA_BONUS | ARDASHIR_BONUS | SHAPUR_BONUS)
+}
+
+function spend_senate_card_bonus() {
+ game.killed &= ~((1 << POSTUMUS) | (1 << PRIEST_KING) | (1 << ZENOBIA))
+}
+
states.buy_trash = {
prompt() {
+ let military_bonus = has_military_card_bonus()
+ let senate_bonus = has_senate_card_bonus()
+
prompt("Buy/Trash cards: " + game.pp + "PP left.")
+ if (military_bonus)
+ view.prompt += " First Military card is 2 cheaper."
+ if (senate_bonus)
+ view.prompt += " First Senate card is 2 cheaper."
+
let nprov = count_own_provinces()
if (game.pp >= 3) {
for (let c of current_discard())
@@ -3344,6 +3520,10 @@ states.buy_trash = {
if (cost > nprov)
cost *= 2
cost += game.count
+ if (military_bonus && card_influence(c) === MILITARY)
+ cost -= 2
+ if (senate_bonus && card_influence(c) === SENATE)
+ cost -= 2
if (game.pp >= cost)
gen_action_card(c)
}
@@ -3357,13 +3537,27 @@ states.buy_trash = {
set_delete(current_discard(), c)
game.pp -= 3
} else {
+ let military_bonus = has_military_card_bonus()
+ let senate_bonus = has_senate_card_bonus()
+
log("Bought " + card_name(c))
set_add(current_discard(), c)
set_delete(find_market_with_card(c), c)
+
let cost = card_value(c)
if (cost > count_own_provinces())
cost *= 2
cost += game.count
+
+ if (military_bonus && card_influence(c) === MILITARY) {
+ spend_military_card_bonus()
+ cost -= 2
+ }
+ if (senate_bonus && card_influence(c) === SENATE) {
+ spend_senate_card_bonus()
+ cost -= 2
+ }
+
game.pp -= cost
game.count += 1
}
@@ -3588,8 +3782,12 @@ function setup_market_pile(cards) {
function setup_barbarians(tribe, home) {
for (let id = first_barbarian[tribe]; id <= last_barbarian[tribe]; ++id) {
- set_barbarian_location(id, home)
- set_barbarian_inactive(id)
+ if (is_barbarian_leader(id)) {
+ set_barbarian_location(id, UNAVAILABLE)
+ } else {
+ set_barbarian_location(id, home)
+ set_barbarian_inactive(id)
+ }
}
}
@@ -3616,6 +3814,7 @@ exports.setup = function (seed, scenario, options) {
selected_general: -1,
played: [],
used: [],
+ killed: 0,
placed: 0,
battled: 0,
count: 0,
@@ -3637,9 +3836,8 @@ exports.setup = function (seed, scenario, options) {
governors: new Array(6 * player_count).fill(UNAVAILABLE),
generals: new Array(6 * player_count).fill(UNAVAILABLE),
legions: new Array(LEGION_COUNT).fill(AVAILABLE),
- barbarians: new Array(BARBARIAN_COUNT[player_count]).fill(AVAILABLE),
+ barbarians: new Array(BARBARIAN_COUNT).fill(AVAILABLE),
rival_emperors: [ UNAVAILABLE, UNAVAILABLE, UNAVAILABLE ],
- barbarian_leaders: [ UNAVAILABLE, UNAVAILABLE, UNAVAILABLE ],
dice: [ 0, 0, 0, 0 ], // first two are crisis table dice, second two are barbarian homeland dice
market: null,
@@ -3657,7 +3855,6 @@ exports.setup = function (seed, scenario, options) {
game.events = setup_events()
- /*
game.market = [
setup_market_pile(CARD_M2),
setup_market_pile(CARD_S2),
@@ -3669,32 +3866,26 @@ exports.setup = function (seed, scenario, options) {
setup_market_pile(CARD_S4),
setup_market_pile(CARD_P4),
]
- */
- game.market = [
- setup_market_pile(CARD_M2),
- setup_market_pile(CARD_M3),
- setup_market_pile(CARD_M4),
- setup_market_pile(CARD_S2),
- setup_market_pile(CARD_S3),
- setup_market_pile(CARD_S4),
- setup_market_pile(CARD_P2),
- setup_market_pile(CARD_P3),
- setup_market_pile(CARD_P4),
- ]
setup_barbarians(ALAMANNI, ALAMANNI_HOMELAND)
setup_barbarians(FRANKS, FRANKS_HOMELAND)
setup_barbarians(GOTHS, GOTHS_HOMELAND)
+
if (player_count >= 3)
setup_barbarians(NOMADS, NOMADS_HOMELAND)
+ else
+ setup_barbarians(NOMADS, UNAVAILABLE)
+
if (player_count >= 4)
setup_barbarians(SASSANIDS, SASSANIDS_HOMELAND)
+ else
+ setup_barbarians(SASSANIDS, UNAVAILABLE)
for (let player = 0; player < player_count; ++player) {
game.hand[player] = []
game.draw[player] = setup_player_deck(player)
game.discard[player] = []
- for (let i = 0; i < 9; ++i) set_add(game.draw[player], game.market[i].pop())
+ // for (let i = 0; i < 9; ++i) set_add(game.draw[player], game.market[i].pop())
}
update_neutral_italia()
@@ -3768,7 +3959,6 @@ exports.view = function (state, player_name) {
legions: game.legions,
barbarians: game.barbarians,
rival_emperors: game.rival_emperors,
- barbarian_leaders: game.barbarian_leaders,
dice: game.dice,
event: game.active_event,
@@ -3872,6 +4062,10 @@ function gen_action_barbarian(id) {
gen_action("barbarian", id)
}
+function gen_action_rival_emperor(id) {
+ gen_action("rival_emperor", id)
+}
+
function gen_action_militia(where) {
gen_action("militia", where)
}