summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--play.css61
-rw-r--r--play.html2
-rw-r--r--play.js171
-rw-r--r--rules.js284
4 files changed, 293 insertions, 225 deletions
diff --git a/play.css b/play.css
index 4811f80..ce727b5 100644
--- a/play.css
+++ b/play.css
@@ -23,16 +23,17 @@ body.Blue .your_turn { background-color: hsl(207,67%,83%) }
body.Yellow .your_turn { background-color: hsl(47,100%,78%) }
body.Green .your_turn { background-color: hsl(99,36%,65%) }
-#log .h1.p_red { background-color: hsl(354,85%,77%) }
-#log .h1.p_blue { background-color: hsl(207,67%,83%) }
-#log .h1.p_yellow { background-color: hsl(47,100%,78%) }
-#log .h1.p_green { background-color: hsl(99,36%,70%) }
+#log .h1.R { background-color: hsl(354,85%,77%) }
+#log .h1.B { background-color: hsl(207,67%,83%) }
+#log .h1.Y { background-color: hsl(47,100%,78%) }
+#log .h1.G { background-color: hsl(99,36%,70%) }
-#log img { height: 14px; vertical-align: -6px; }
+#log span.M { color: hsl(358, 78%, 41%) }
+#log span.S { color: hsl(206, 100%, 30%) }
+#log span.P { color: hsl(44, 100%, 32%) }
-#log span.M { color: #e31f26 }
-#log span.S { color: #0066b3 }
-#log span.P { color: hsl(44, 100%, 35%) }
+#log .tip { cursor: default }
+#log .tip:hover { text-decoration: underline; }
#log { background-color: whitesmoke; }
#log .h1 { background-color: silver; font-weight: bold; padding-top:2px; padding-bottom:2px; margin: 8px 0; text-align: center; }
@@ -54,11 +55,6 @@ body.Green .your_turn { background-color: hsl(99,36%,65%) }
background-repeat: no-repeat;
}
-#log img {
- pointer-events: none;
- vertical-align: -3px;
-}
-
#log .white {
background-image: url(images/die_black_pips.svg);
background-color: #fff;
@@ -444,22 +440,22 @@ body.p2 #npg_galatia { display: block }
.sassanids.inactive { background-image: url(images/sassanids_inactive.png) }
.neutral.governor { background-image: url(images/neutral_governor.png) }
-#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) }
-
-body.shift #ardashir { background-image: url(images/ardashir_back.png) }
-body.shift #cniva { background-image: url(images/cniva_back.png) }
-body.shift #shapur { background-image: url(images/shapur_back.png) }
-body.shift #postumus { background-image: url(images/rival_back.png) }
-body.shift #priest_king { background-image: url(images/rival_back.png) }
-body.shift #zenobia { background-image: url(images/rival_back.png) }
+.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) }
+
+body.shift .ardashir { background-image: url(images/ardashir_back.png) }
+body.shift .cniva { background-image: url(images/cniva_back.png) }
+body.shift .shapur { background-image: url(images/shapur_back.png) }
+body.shift .postumus { background-image: url(images/rival_back.png) }
+body.shift .priest_king { background-image: url(images/rival_back.png) }
+body.shift .zenobia { background-image: url(images/rival_back.png) }
.blue.governor { background-image: url(images/blue_governor.png) }
.green.governor { background-image: url(images/green_governor.png) }
@@ -500,6 +496,13 @@ body.shift #zenobia { background-image: url(images/rival_back.png) }
/* CARDS */
+#card_tip {
+ position: fixed;
+ z-index: 200;
+ right: 240px;
+ top: 60px;
+}
+
.card {
width: 250px;
height: 350px;
diff --git a/play.html b/play.html
index 9cd8e32..9182eac 100644
--- a/play.html
+++ b/play.html
@@ -14,6 +14,8 @@
</head>
<body class="p4">
+<div id="card_tip" class="hide"></div>
+
<header>
<div id="toolbar">
<div class="menu">
diff --git a/play.js b/play.js
index a0bcacf..0e6618c 100644
--- a/play.js
+++ b/play.js
@@ -57,31 +57,57 @@ const CARD_INDEX = [
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 CARD_CLASS = [
+ "influence_m1",
+ "influence_s1",
+ "influence_p1",
+ "influence_m2",
+ "influence_s2",
+ "influence_p2",
+ "influence_m2x",
+ "influence_s2x",
+ "influence_p2x",
+ "influence_m3",
+ "influence_s3",
+ "influence_p3",
+ "influence_m3x",
+ "influence_s3x",
+ "influence_p3x",
+ "influence_m4",
+ "influence_s4",
+ "influence_s4b",
+ "influence_p4",
+ "influence_m4x",
+ "influence_s4x",
+ "influence_p4x",
]
+const CARD_MAP = [
+ "M1",
+ "S1",
+ "P1",
+ "M2(Castra)",
+ "S2(Tribute)",
+ "P2(Quaestor)",
+ "M2(Cavalry)",
+ "S2(Princeps Senatus)",
+ "P2(Ambitus)",
+ "M3(Flanking Maneuver)",
+ "S3(Foederati)",
+ "P3(Mob)",
+ "M3(Force March)",
+ "S3(Frumentarii)",
+ "P3(Mobile Vulgus)",
+ "M4(Praetorian Guard)",
+ "S4(Damnatio Memoriae)",
+ "S4(Damnatio Memoriae)",
+ "P4(Pretender)",
+ "M4(Spiculum)",
+ "S4(Triumph)",
+ "P4(Demagogue)",
+]
+
+
const EVENT_NAME = [
"None",
"Plague of Cyprian",
@@ -628,6 +654,7 @@ const LAYOUT_PATTERN = [
]
let ui = {
+ card_tip: document.getElementById("card_tip"),
cards: [],
event_cards: [],
militia: [],
@@ -813,8 +840,8 @@ function is_action(action, arg) {
function on_init() {
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 influence_" + name.toLowerCase(), my_action: "card", my_id: c })
+ let name = CARD_CLASS[CARD_INDEX[c]]
+ ui.cards[c] = create("div", { className: "card influence " + name, my_action: "card", my_id: c })
}
for (let e = 0; e <= 15; ++e) {
@@ -835,17 +862,17 @@ function on_init() {
}
}
- 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")
+ ui.rival_emperors[0] = create_piece(0, "rival_emperor", "rival_emperor postumus", "postumus")
+ ui.rival_emperors[1] = create_piece(1, "rival_emperor", "rival_emperor priest_king", "priest_king")
+ ui.rival_emperors[2] = create_piece(2, "rival_emperor", "rival_emperor zenobia", "zenobia")
for (let tribe = 0; tribe < 5; ++tribe)
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"
+ ui.barbarians[CNIVA].classList.add("cniva")
+ ui.barbarians[SHAPUR].classList.add("shapur")
+ ui.barbarians[ARDASHIR].classList.add("ardashir")
for (let p = 0; p < 4; ++p) {
for (let g = 0; g < 6; ++g) {
@@ -891,7 +918,7 @@ function on_init() {
let stack_count = new Array(21).fill(0)
-let battle_width = 0
+let combat_width = 0
const BATTLE_MIN = 3
const BATTLE_H_MARGIN = 12
const BATTLE_V_MARGIN = 12
@@ -904,8 +931,8 @@ function layout_battle_stack(is_att, list, region) {
if (region < 12)
y -= 7
- if (list.length > battle_width)
- battle_width = list.length
+ if (list.length > combat_width)
+ combat_width = list.length
w = list.length * 60 + (list.length - 1) * BATTLE_H_GAP
x -= w / 2
@@ -1010,15 +1037,15 @@ function layout_barbarian_dice(black, white, tribe) {
}
function is_battle_stack(region, type, id) {
- if (view.battle_region !== region)
+ if (view.combat_region !== region)
return false
- if (type === "general" && view.battle.attacker === id)
+ if (type === "general" && view.combat.attacker === id)
return true
- if (type === "militia" && view.battle.attacker < 0)
+ if (type === "militia" && view.combat.attacker < 0)
return true
- if (type === "militia" && view.battle.type === "militia")
+ if (type === "militia" && view.combat.type === "militia")
return true
- return view.battle.type === type && view.battle.target === id
+ return view.combat.type === type && view.combat.target === id
}
function on_update() {
@@ -1050,7 +1077,7 @@ function on_update() {
ui.discard.replaceChildren()
ui.market.replaceChildren()
- battle_width = BATTLE_MIN
+ combat_width = BATTLE_MIN
for (let pi = 0; pi < player_count; ++pi) {
let legacy = view.legacy[pi]
@@ -1249,9 +1276,9 @@ function on_update() {
if (lone_militia) {
if (is_battle_stack(region, "militia", region)) {
if (has_militia_castra(region))
- layout_battle_stack(view.battle.attacker < 0, [ ui.mcastra[region], ui.militia[region] ], region)
+ layout_battle_stack(view.combat.attacker < 0, [ ui.mcastra[region], ui.militia[region] ], region)
else
- layout_battle_stack(view.battle.attacker < 0, [ ui.militia[region] ], region, true)
+ layout_battle_stack(view.combat.attacker < 0, [ ui.militia[region] ], region, true)
} else {
if (has_militia_castra(region))
layout_stack(-1, [ ui.mcastra[region], ui.militia[region] ], region, true, 16, 16)
@@ -1320,7 +1347,7 @@ function on_update() {
stack.push(ui.militia[region])
if (is_battle_stack(region, "general", pi * 6 + ai))
- layout_battle_stack(pi * 6 + ai === view.battle.attacker, stack, region)
+ layout_battle_stack(pi * 6 + ai === view.combat.attacker, stack, region)
else
layout_stack(pi * 6 + ai, stack, region, inside, 16, 16)
} else {
@@ -1362,13 +1389,13 @@ function on_update() {
layout_available(avail_stack, 64, pi * 625 + 325, 27)
}
- if (view.battle) {
- let [ x, y, w, h ] = LAYOUT_BATTLE[view.battle_region]
- if (view.battle_region < 12)
+ if (view.combat) {
+ let [ x, y, w, h ] = LAYOUT_BATTLE[view.combat_region]
+ if (view.combat_region < 12)
y -= 7
x += w >> 1
- w = battle_width * 60 + (battle_width - 1) * BATTLE_H_GAP + BATTLE_H_MARGIN * 2
+ w = combat_width * 60 + (combat_width - 1) * BATTLE_H_GAP + BATTLE_H_MARGIN * 2
x -= w / 2
h = 120 + BATTLE_V_GAP + BATTLE_V_MARGIN * 2
@@ -1486,10 +1513,13 @@ function sub_region_name(match, p1) {
return REGION_NAME[x]
}
+function sub_barbarian(match) {
+ return `<span class="tip" onmouseenter="on_focus_barbarian_tip('${match}')" onmouseleave="on_blur_tip()">${match}</span>`
+}
+
function sub_event_name(match, p1) {
let x = p1 | 0
- // TODO: tooltip?
- return EVENT_NAME[x]
+ return `<span class="tip" onmouseenter="on_focus_event_tip(${x})" onmouseleave="on_blur_tip()">${EVENT_NAME[x]}</span>`
}
function sub_icon(match) {
@@ -1497,11 +1527,13 @@ function sub_icon(match) {
}
function sub_card_1(match) {
- return match
+ let x = CARD_MAP.indexOf(match)
+ return `<span class="tip ${match[0]}" onmouseenter="on_focus_influence_tip(${x})" onmouseleave="on_blur_tip()">${match}</span>`
}
function sub_card_x(match, p1, p2) {
- return p1 + " " + p2
+ let x = CARD_MAP.indexOf(match)
+ return `<span class="tip ${match[0]}" onmouseenter="on_focus_influence_tip(${x})" onmouseleave="on_blur_tip()">${p1} ${p2}</span>`
}
function on_log(text) {
@@ -1516,9 +1548,18 @@ function on_log(text) {
text = text.replace(/</g, "&lt;")
text = text.replace(/>/g, "&gt;")
+ text = text.replace(/\bCniva\b/g, sub_barbarian)
+ text = text.replace(/\bShapur I\b/g, sub_barbarian)
+ text = text.replace(/\bArdashir\b/g, sub_barbarian)
+ text = text.replace(/\bPostumus\b/g, sub_barbarian)
+ text = text.replace(/\bZenobia\b/g, sub_barbarian)
+ text = text.replace(/\bPriest King\b/g, sub_barbarian)
+
text = text.replace(/%(\d+)/g, sub_region_name)
text = text.replace(/\bE(\d+)/g, sub_event_name)
+
text = text.replace(/\b[BW]\d\b/g, sub_icon)
+
text = text.replace(/\b[MSP][1]\b/g, sub_card_1)
text = text.replace(/\b([MSP][234])\(([^)]*)\)/g, sub_card_x)
@@ -1529,19 +1570,19 @@ function on_log(text) {
if (text.match(/^\.h1 Red/)) {
text = text.substring(4)
- p.className = "h1 p_red"
+ p.className = "h1 R"
}
else if (text.match(/^\.h1 Blue/)) {
text = text.substring(4)
- p.className = "h1 p_blue"
+ p.className = "h1 B"
}
else if (text.match(/^\.h1 Yellow/)) {
text = text.substring(4)
- p.className = "h1 p_yellow"
+ p.className = "h1 Y"
}
else if (text.match(/^\.h1 Green/)) {
text = text.substring(4)
- p.className = "h1 p_green"
+ p.className = "h1 G"
}
else if (text.match(/^\.h1/)) {
text = text.substring(4)
@@ -1560,6 +1601,26 @@ function on_log(text) {
return p
}
+function on_focus_event_tip(c) {
+ ui.card_tip.className = "card event event_" + c
+}
+
+function on_focus_influence_tip(x) {
+ ui.card_tip.className = "card influence " + CARD_CLASS[x]
+}
+
+function on_focus_barbarian_tip(x) {
+ if (x === "Ardashir") ui.card_tip.className = "card event event_2"
+ if (x === "Priest King") ui.card_tip.className = "card event event_3"
+ if (x === "Shapur I") ui.card_tip.className = "card event event_5"
+ if (x === "Postumus") ui.card_tip.className = "card event event_6"
+ if (x === "Cniva") ui.card_tip.className = "card event event_8"
+ if (x === "Zenobia") ui.card_tip.className = "card event event_9"
+}
+
+function on_blur_tip() {
+ ui.card_tip.className = "hide"
+}
on_init()
scroll_with_middle_mouse("main")
diff --git a/rules.js b/rules.js
index c529fbc..e1aba4d 100644
--- a/rules.js
+++ b/rules.js
@@ -2,15 +2,7 @@
/*
TODO
-----
-striped backgorund for "Played" when not your turn
-
-hover over event card name for popup
-
-combine flags
-
-[ ] combat battle screen - splay stack / dialog for watching contents and taking hits
[ ] killed leader stash for buy/trash phase
[ ] emperor variant (and tokens)
@@ -1029,18 +1021,18 @@ function roll_dice_no_reroll(count, target) {
function eliminate_barbarian(id) {
let tribe = get_barbarian_tribe(id)
- if (is_barbarian_leader(id) && game.battle) {
+ if (is_barbarian_leader(id) && game.combat) {
if (id === CNIVA) {
log("Cniva killed!")
- game.battle.killed |= CNIVA_BONUS
+ game.combat.killed |= CNIVA_BONUS
}
if (id === ARDASHIR) {
log("Ardashir killed!")
- game.battle.killed |= ARDASHIR_BONUS
+ game.combat.killed |= ARDASHIR_BONUS
}
if (id === SHAPUR) {
log("Shapur killed!")
- game.battle.killed |= SHAPUR_BONUS
+ game.combat.killed |= SHAPUR_BONUS
}
set_barbarian_location(id, AVAILABLE)
} else {
@@ -1051,8 +1043,8 @@ function eliminate_barbarian(id) {
function eliminate_rival_emperor(id) {
log(RIVAL_EMPEROR_NAME[id] + " killed!")
- if (game.battle)
- game.battle.killed |= (1 << id)
+ if (game.combat)
+ game.combat.killed |= (1 << id)
set_rival_emperor_location(id, AVAILABLE)
}
@@ -1137,7 +1129,7 @@ states.setup_province = {
capital(where) {
push_undo()
- log(PLAYER_NAME[game.current] + " in %" + where + ".")
+ log(PLAYER_NAME[game.current] + " selected %" + where + ".")
set_governor_location(game.current * 6 + 0, where)
@@ -1499,7 +1491,6 @@ states.crisis_barbarian_leader = {
gen_action_region(game.where)
},
region(where) {
- logi("Barbarian leader in %" + where + ".")
set_barbarian_location(game.count, where)
goto_take_actions()
},
@@ -1520,7 +1511,6 @@ states.crisis_rival_emperor = {
gen_action_region(game.where)
},
region(where) {
- logi("Rival emperor in %" + where + ".")
set_rival_emperor_location(game.count, where)
goto_take_actions()
},
@@ -1571,7 +1561,6 @@ states.palmyra_allies = {
},
barbarian(id) {
push_undo()
- logi(BARBARIAN_NAME[id] + " in %" + get_barbarian_location(id))
eliminate_barbarian(id)
if (--game.count === 0)
goto_take_actions()
@@ -1602,7 +1591,7 @@ states.ludi_saeculares = {
},
card(c) {
push_undo()
- logi("Discarded " + card_name(c))
+ logi("Discard " + card_name(c))
set_delete(current_hand(), c)
set_add(current_discard(), c)
award_legacy(game.current, "Ludi Saeculares", 2 * card_value(c))
@@ -2108,7 +2097,7 @@ function increase_support(where) {
}
function remove_governor(where) {
- log("Removed governor from %" + where + ".")
+ log("Remove governor from %" + where + ".")
eliminate_militia(where)
set_mobs(where, 0)
@@ -2453,7 +2442,9 @@ states.move_army_at_sea = {
}
function move_army_to(who, to) {
- log("Move Army to %" + to + ".")
+ let from = get_general_location(who)
+
+ log("Move Army from %" + from + " to %" + to + ".")
remove_general_castra(who)
@@ -2486,7 +2477,7 @@ function enter_capital() {
}
}
- if (game.battle)
+ if (game.combat)
end_battle()
}
@@ -2509,7 +2500,7 @@ states.occupy_seat_of_power_1 = {
},
region(where) {
push_undo()
- log("Removed Seat of Power in %" + where + ".")
+ log("Remove Seat of Power in %" + where + ".")
remove_seat_of_power(where)
remove_governor(where)
resume_occupy_seat_of_power()
@@ -2527,7 +2518,7 @@ states.occupy_seat_of_power_2 = {
},
region(where) {
push_undo()
- log("Removed Breakaway in %" + where + ".")
+ log("Remove Breakaway in %" + where + ".")
remove_breakaway(where)
resume_occupy_seat_of_power()
},
@@ -2542,7 +2533,7 @@ states.occupy_breakaway = {
},
region(where) {
push_undo()
- log("Removed Breakaway in %" + where + ".")
+ log("Remove Breakaway in %" + where + ".")
remove_breakaway(where)
remove_governor(where)
goto_replace_pretender()
@@ -2571,7 +2562,7 @@ states.replace_pretender_governor = {
},
governor(id) {
push_undo()
- log("Replaced Governor in %" + game.where + ".")
+ log("Replace Governor in %" + game.where + ".")
set_governor_location(id, game.where)
game.state = "take_actions"
},
@@ -2849,11 +2840,11 @@ states.mob = {
function auto_remove_pretender_empire(seat) {
let pretender = get_province_governor(seat) / 6 | 0
- log("Removed Seat of Power in %" + seat + ".")
+ log("Remove Seat of Power in %" + seat + ".")
remove_seat_of_power(seat)
for (let where = 1; where < 12; ++where) {
if (is_breakaway(where) && (get_province_governor(where) / 6 | 0) === pretender) {
- log("Removed Breakaway in %" + where + ".")
+ log("Remove Breakaway in %" + where + ".")
remove_breakaway(where)
}
}
@@ -2926,7 +2917,7 @@ states.pretender_breakaway = {
// === COMBAT ===
function play_flanking_maneuver() {
- game.battle.flanking = 1
+ game.combat.flanking = 1
}
function goto_battle_vs_general(where, attacker, target) {
@@ -2950,8 +2941,8 @@ function goto_battle(type, where, attacker, target) {
log_h2("Battle in %" + where)
spend_military(1)
game.where = where
- game.battle = { type, attacker, target, flanking: 0, killed: 0 }
- game.state = "battle"
+ game.combat = { type, attacker, target, flanking: 0, killed: 0 }
+ game.state = "initiate_battle"
if (attacker >= 0) {
if (is_general_inside_capital(attacker))
remove_militia_castra(where)
@@ -2991,20 +2982,20 @@ function gen_initiate_battle(where) {
}
function format_battle_target() {
- switch (game.battle.type) {
+ switch (game.combat.type) {
case "militia": return PLAYER_NAME[get_province_player(game.where)] + " militia"
- case "barbarians": return BARBARIAN_NAME[game.battle.target]
- case "general": return PLAYER_NAME[game.battle.target / 6 | 0] + " army"
- case "rival_emperor": return RIVAL_EMPEROR_NAME[game.battle.target]
+ case "barbarians": return BARBARIAN_NAME[game.combat.target]
+ case "general": return PLAYER_NAME[game.combat.target / 6 | 0] + " army"
+ case "rival_emperor": return RIVAL_EMPEROR_NAME[game.combat.target]
}
}
-states.battle = {
+states.initiate_battle = {
show_battle: true,
inactive: "Combat",
prompt() {
prompt("Initiate Battle against " + format_battle_target() + " in " + REGION_NAME[game.where] + ".")
- if (!game.battle.flanking && has_card_event(CARD_M3)) {
+ if (!game.combat.flanking && has_card_event(CARD_M3)) {
view.prompt += " You may play Flanking Maneuver."
gen_card_event(CARD_M3)
}
@@ -3019,7 +3010,7 @@ states.battle = {
roll() {
clear_undo()
roll_combat_dice()
- if (game.battle.flanking)
+ if (game.combat.flanking)
game.state = "flanking_maneuver"
else
goto_assign_hits()
@@ -3027,11 +3018,11 @@ states.battle = {
}
function format_hits() {
- let s = "Defender rolled " + game.battle.ahits + " hit"
- if (game.battle.ahits !== 1)
+ let s = "Defender rolled " + game.combat.ahits + " hit"
+ if (game.combat.ahits !== 1)
s += "s"
- s += ", attacker rolled " + game.battle.dhits + " hit"
- if (game.battle.dhits !== 1)
+ s += ", attacker rolled " + game.combat.dhits + " hit"
+ if (game.combat.dhits !== 1)
s += "s"
return s
}
@@ -3039,7 +3030,6 @@ function format_hits() {
states.flanking_maneuver = {
show_battle: true,
get inactive() { return "Flanking Maneuver. " + format_hits() },
- inactive: "Flanking Maneuver",
prompt() {
prompt("Flanking Maneuver: " + format_hits() + ".")
view.actions.pass = 1
@@ -3056,24 +3046,24 @@ states.flanking_maneuver = {
}
function roll_combat_dice() {
- game.battle.dtaken = 0
- game.battle.ataken = 0
+ game.combat.dtaken = 0
+ game.combat.ataken = 0
- log_h4("DEFENDER")
- game.battle.ahits = roll_defender_dice()
- log("Total " + game.battle.ahits + " hits!")
+ log_h3("DEFENDER")
+ game.combat.ahits = roll_defender_dice()
+ log("Total hits: " + game.combat.ahits)
log_br()
- log_h4("ATTACKER")
- game.battle.dhits = roll_attacker_dice()
- log("Total " + game.battle.dhits + " hits!")
+ log_h3("ATTACKER")
+ game.combat.dhits = roll_attacker_dice()
+ log("Total hits: " + game.combat.dhits)
log_br()
}
function roll_flanking_maneuver_dice() {
- log_h4("FLANKING MANEUVER")
- game.battle.dhits = roll_attacker_dice()
- log("Total " + game.battle.dhits + " hits!")
+ log_h3("FLANKING MANEUVER")
+ game.combat.dhits = roll_attacker_dice()
+ log("Total " + game.combat.dhits + " hits!")
log_br()
}
@@ -3083,13 +3073,6 @@ function roll_general_dice(general) {
let drm = get_roman_drm()
- log(PLAYER_NAME[general/6|0])
-
- if (is_general_inside_capital(general) && has_militia(game.where)) {
- log("Militia")
- n += roll_dice(1, 5 + drm)
- }
-
let full_strength = 0
let reduced = 0
for (let id = 0; id < LEGION_COUNT; ++id) {
@@ -3104,6 +3087,7 @@ function roll_general_dice(general) {
log("Legions")
n += roll_dice(full_strength, 3 + drm)
}
+
if (reduced > 0) {
log("Reduced Legions")
n += roll_dice(reduced, 5 + drm)
@@ -3118,6 +3102,11 @@ function roll_general_dice(general) {
n += roll_dice(barbarians, 4 + drm)
}
+ if (is_general_inside_capital(general) && has_militia(game.where)) {
+ log("Militia")
+ n += roll_dice(1, 5 + drm)
+ }
+
return n
}
@@ -3127,7 +3116,7 @@ function roll_militia_dice() {
}
function roll_rival_emperor_dice() {
- log("Rival Emperor")
+ log(RIVAL_EMPEROR_NAME[game.combat.target])
return roll_dice(3, 4)
}
@@ -3144,20 +3133,20 @@ function roll_barbarian_dice(tribe) {
function roll_attacker_dice() {
let n = get_plague_hits()
- if (game.battle.attacker < 0)
+ if (game.combat.attacker < 0)
n += roll_militia_dice()
else
- n += roll_general_dice(game.battle.attacker)
- if (game.battle.type === "militia" && has_militia_castra(game.where)) {
+ n += roll_general_dice(game.combat.attacker)
+ if (game.combat.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)) {
+ if (game.combat.type === "general" && has_general_castra(game.combat.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")
+ if (game.combat.type === "barbarians" && get_barbarian_location(SHAPUR) === game.where) {
+ log("Shapur I reduces 1 hit")
n -= 1
}
return Math.max(0, n)
@@ -3165,7 +3154,7 @@ function roll_attacker_dice() {
function roll_defender_dice() {
let n = get_plague_hits()
- switch (game.battle.type) {
+ switch (game.combat.type) {
case "militia":
n += roll_militia_dice()
break
@@ -3173,10 +3162,11 @@ function roll_defender_dice() {
n += roll_rival_emperor_dice()
break
case "barbarians":
- n += roll_barbarian_dice(game.battle.target)
+ n += roll_barbarian_dice(game.combat.target)
break
case "general":
- n += roll_general_dice(game.battle.target)
+ log(PLAYER_NAME[game.combat.target/6|0])
+ n += roll_general_dice(game.combat.target)
break
}
return Math.max(0, n)
@@ -3271,26 +3261,26 @@ function gen_hits_general(general) {
}
function has_hits_on_attacker() {
- if (game.battle.ataken < game.battle.ahits) {
- if (game.battle.attacker < 0)
+ if (game.combat.ataken < game.combat.ahits) {
+ if (game.combat.attacker < 0)
return has_hits_militia()
else
- return has_hits_general(game.battle.attacker)
+ return has_hits_general(game.combat.attacker)
}
return false
}
function has_hits_on_defender() {
- if (game.battle.dtaken < game.battle.dhits) {
- switch (game.battle.type) {
+ if (game.combat.dtaken < game.combat.dhits) {
+ switch (game.combat.type) {
case "militia":
return has_hits_militia()
case "rival_emperor":
- return has_hits_rival_emperor(game.battle.target)
+ return has_hits_rival_emperor(game.combat.target)
case "barbarians":
- return has_hits_barbarians(game.battle.target)
+ return has_hits_barbarians(game.combat.target)
case "general":
- return has_hits_general(game.battle.target)
+ return has_hits_general(game.combat.target)
}
}
return false
@@ -3319,26 +3309,26 @@ states.assign_hits_on_attacker = {
get inactive() { return "Combat. " + format_hits() },
prompt() {
prompt("Combat: " + format_hits() + ".")
- if (game.battle.attacker < 0)
+ if (game.combat.attacker < 0)
gen_hits_militia()
else
- gen_hits_general(game.battle.attacker)
+ gen_hits_general(game.combat.attacker)
},
militia(where) {
push_undo()
- game.battle.ataken += 1
+ game.combat.ataken += 1
eliminate_militia(where)
goto_assign_hits_on_attacker()
},
legion(id) {
push_undo()
- game.battle.ataken += 1
+ game.combat.ataken += 1
assign_hit_to_legion(id)
goto_assign_hits_on_attacker()
},
barbarian(id) {
push_undo()
- game.battle.ataken += 1
+ game.combat.ataken += 1
eliminate_barbarian(id)
goto_assign_hits_on_attacker()
},
@@ -3349,42 +3339,42 @@ states.assign_hits_on_defender = {
get inactive() { return "Combat. " + format_hits() },
prompt() {
prompt("Combat: " + format_hits() + ".")
- switch (game.battle.type) {
+ switch (game.combat.type) {
case "militia":
gen_hits_militia()
break
case "rival_emperor":
- gen_hits_rival_emperor(game.battle.target)
+ gen_hits_rival_emperor(game.combat.target)
break
case "barbarians":
- gen_hits_barbarians(game.battle.target)
+ gen_hits_barbarians(game.combat.target)
break
case "general":
- gen_hits_general(game.battle.target)
+ gen_hits_general(game.combat.target)
break
}
},
militia(where) {
push_undo()
- game.battle.dtaken += 1
+ game.combat.dtaken += 1
eliminate_militia(where)
goto_assign_hits_on_defender()
},
legion(id) {
push_undo()
- game.battle.dtaken += 1
+ game.combat.dtaken += 1
assign_hit_to_legion(id)
goto_assign_hits_on_defender()
},
barbarian(id) {
push_undo()
- game.battle.dtaken += 1
+ game.combat.dtaken += 1
eliminate_barbarian(id)
goto_assign_hits_on_defender()
},
rival_emperor(id) {
push_undo()
- game.battle.dtaken += 1
+ game.combat.dtaken += 1
eliminate_rival_emperor(id)
goto_assign_hits_on_defender()
}
@@ -3398,18 +3388,18 @@ function is_attacker_eliminated() {
}
function is_defender_eliminated() {
- switch (game.battle.type) {
+ switch (game.combat.type) {
case "militia":
return !has_militia(game.where)
case "rival_emperor":
- return get_rival_emperor_location(game.battle.target) === AVAILABLE
+ return get_rival_emperor_location(game.combat.target) === AVAILABLE
case "barbarians":
if (is_province(game.where))
- return find_barbarian_of_tribe(game.where, game.battle.target) < 0
+ return find_barbarian_of_tribe(game.where, game.combat.target) < 0
else
- return find_active_barbarian_of_tribe(game.where, game.battle.target) < 0
+ return find_active_barbarian_of_tribe(game.where, game.combat.target) < 0
case "general":
- return get_general_location(game.battle.target) === AVAILABLE
+ return get_general_location(game.combat.target) === AVAILABLE
}
return false
}
@@ -3422,7 +3412,7 @@ states.combat_victory = {
let ae = is_attacker_eliminated()
if (de && ae)
prompt("Combat: There is no winner.")
- else if (de || game.battle.dtaken > game.battle.ataken)
+ else if (de || game.combat.dtaken > game.combat.ataken)
prompt("Combat: You win the battle!")
else
prompt("Combat: Defenders win the battle!")
@@ -3440,7 +3430,7 @@ function goto_combat_victory() {
let ae = is_attacker_eliminated()
if (de && ae)
goto_combat_no_victory()
- else if (de || game.battle.dtaken > game.battle.ataken)
+ else if (de || game.combat.dtaken > game.combat.ataken)
goto_combat_victory_attacker()
else
goto_combat_victory_defender()
@@ -3464,40 +3454,40 @@ function award_legacy_summary(p, reason, n) {
function goto_combat_no_victory() {
log("Both sides eliminated.")
- game.battle.killed = 0
+ game.combat.killed = 0
end_battle()
}
function goto_combat_victory_defender() {
- game.battle.killed = 0
- if (game.battle.type === "general")
- award_legacy(game.battle.target / 6 | 0, "Victory", 2)
- else if (game.battle.type === "militia")
+ game.combat.killed = 0
+ if (game.combat.type === "general")
+ award_legacy(game.combat.target / 6 | 0, "Victory", 2)
+ else if (game.combat.type === "militia")
award_legacy(get_province_player(game.where), "Victory", 2)
- else if (game.battle.type === "barbarians")
- log(BARBARIAN_NAME[game.battle.target] + " won.")
- else if (game.battle.type === "rival_emperor")
- log(RIVAL_EMPEROR_NAME[game.battle.target] + " won.")
+ else if (game.combat.type === "barbarians")
+ log(BARBARIAN_NAME[game.combat.target] + " won.")
+ else if (game.combat.type === "rival_emperor")
+ log(RIVAL_EMPEROR_NAME[game.combat.target] + " won.")
end_battle()
}
function goto_combat_victory_attacker() {
- if (game.battle.type === "barbarians") {
- award_legacy(game.current, "Victory", 2 + game.battle.dtaken)
+ if (game.combat.type === "barbarians") {
+ award_legacy(game.current, "Victory", 2 + game.combat.dtaken)
// Surviving Barbarians go home (to active)
- let tribe = get_barbarian_tribe(game.battle.target)
+ let tribe = get_barbarian_tribe(game.combat.target)
for (let id = first_barbarian[tribe]; id <= last_barbarian[tribe]; ++id)
- if (get_barbarian_location(id) === game.battle)
+ if (get_barbarian_location(id) === game.combat)
set_barbarian_location(id, BARBARIAN_HOMELAND[tribe])
} else {
award_legacy(game.current, "Victory", 2)
}
// Defending Romans must retreat into province
- if (game.battle.type === "general") {
- set_general_outside_capital(game.battle.target)
- remove_general_castra(game.battle.target)
+ if (game.combat.type === "general") {
+ set_general_outside_capital(game.combat.target)
+ remove_general_castra(game.combat.target)
}
if (can_enter_capital(game.where))
@@ -3530,17 +3520,17 @@ function end_battle() {
if (game.selected_general >= 0 && get_general_location(game.selected_general) === AVAILABLE)
game.selected_general = -1
- if (game.battle.killed) {
+ if (game.combat.killed) {
if (can_free_increase_support_level(game.where)) {
game.state = "free_increase_support_level"
return
} else {
log("Kept for cost reduction.")
- game.killed |= game.battle.killed
+ game.killed |= game.combat.killed
}
}
- game.battle = null
+ game.combat = null
game.state = "take_actions"
}
@@ -3559,14 +3549,14 @@ states.free_increase_support_level = {
region(where) {
push_undo()
increase_support(where)
- game.battle = null
+ game.combat = null
game.state = "take_actions"
},
keep() {
push_undo()
log("Kept for cost reduction.")
- game.killed |= game.battle.killed
- game.battle = null
+ game.killed |= game.combat.killed
+ game.combat = null
game.state = "take_actions"
},
}
@@ -3635,7 +3625,7 @@ states.support_check = {
region(where) {
push_undo()
game.count |= (1 << where)
- log("Reduced support level in %" + where + ".")
+ log("Reduce support level in %" + where + ".")
reduce_support(where)
resume_support_check()
},
@@ -3662,7 +3652,7 @@ states.support_check_emperor = {
region(where) {
push_undo()
game.count |= (1 << where)
- log("Reduced support level in %" + where + ".")
+ log("Reduce support level in %" + where + ".")
reduce_support(where)
goto_support_check_mobs()
},
@@ -3703,7 +3693,7 @@ states.support_check_mobs = {
function goto_expand_pretender_empire() {
for (let where = 1; where < 12; ++where) {
if (is_expand_pretender_province(where)) {
- log_h4("Expand Pretender Empire")
+ log_h3("Expand Pretender Empire")
game.state = "expand_pretender_empire"
return
}
@@ -3732,7 +3722,7 @@ states.expand_pretender_empire = {
// === GAIN LEGACY ===
function goto_gain_legacy() {
- log_h4("Gain Legacy")
+ log_h3("Gain Legacy")
if (is_only_pretender_player())
award_legacy_summary(game.current, "Pretender", count_own_breakaway_provinces())
@@ -3802,10 +3792,11 @@ function count_political_points() {
}
function goto_buy_trash_cards() {
- //log_h4("Played")
- //logi(game.played.map(c=>card_name(c)).join(", "))
log_br()
- log("Played " + game.played.map(c=>card_name(c)).join(", ") + ".")
+ if (game.played.length > 0)
+ log("Played " + game.played.map(c=>card_name(c)).join(", ") + ".")
+ else
+ log("Played no cards.")
log_br()
let discard = current_discard()
@@ -3834,7 +3825,7 @@ states.buy_trash_discard = {
},
card(c) {
push_undo()
- log("Discarded " + card_name(c) + ".")
+ log("Discard " + card_name(c) + ".")
set_delete(current_hand(), c)
set_add(current_discard(), c)
},
@@ -3918,14 +3909,14 @@ states.buy_trash = {
card(c) {
push_undo()
if (set_has(current_discard(), c)) {
- log("Trashed " + card_name(c) + ".")
+ log("Trash " + card_name(c) + ".")
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) + ".")
+ log("Buy " + card_name(c) + ".")
set_add(current_discard(), c)
set_delete(find_market_with_card(c), c)
@@ -4108,7 +4099,7 @@ function vp_tie(p) {
}
function goto_game_end() {
- log_h2("Game End")
+ log_h1("Game End")
game.crisis[0] = -1
game.crisis[1] = 0
@@ -4116,11 +4107,27 @@ function goto_game_end() {
game.crisis[3] = 0
game.crisis[4] = 0
+ log_h3("Emperor Turns")
+ game.current = game.first
+ do {
+ logi(game.emperor_turns[game.current] + " " + PLAYER_NAME[game.current])
+ game.current = next_player()
+ } while (game.current !== game.first)
+
+ log_br()
+
let cutoff = award_emperor_turns(10, 1000)
cutoff = award_emperor_turns(6, cutoff)
cutoff = award_emperor_turns(3, cutoff)
award_emperor_turns(0, cutoff)
+ log_h3("Final Legacy")
+ game.current = game.first
+ do {
+ logi(game.legacy[game.current] + " " + PLAYER_NAME[game.current])
+ game.current = next_player()
+ } while (game.current !== game.first)
+
let victor = game.legacy.map((legacy,p) => [vp_tie(p),p]).sort((a,b) => b[0] - a[0])[0][1]
goto_game_over(PLAYER_NAME[victor], PLAYER_NAME[victor] + " won!")
@@ -4214,7 +4221,7 @@ exports.setup = function (seed, scenario, options) {
battled: 0,
mbattled: 0,
killed: 0,
- battle: null,
+ combat: null,
provinces: new Array(3 * player_count).fill(1),
governors: new Array(6 * player_count).fill(UNAVAILABLE),
@@ -4329,9 +4336,9 @@ exports.view = function (state, player_name) {
emperor_turns: game.emperor_turns,
}
- if (game.battle && states[game.state].show_battle) {
- view.battle = game.battle
- view.battle_region = game.where
+ if (game.combat && states[game.state].show_battle) {
+ view.combat = game.combat
+ view.combat_region = game.where
}
if (game.state === "game_over") {
@@ -4387,11 +4394,6 @@ function log_h2(msg) {
function log_h3(msg) {
log_br()
- log(".h3 " + msg)
-}
-
-function log_h4(msg) {
- log_br()
log(msg)
}