"use strict"
// TODO: show killed leaders taken for bonus purchase
function check_menu(id, x) {
document.getElementById(id).className = x ? "menu_item checked" : "menu_item unchecked"
}
function remember_position(e) {
if (e.parentElement) {
let rect = e.getBoundingClientRect()
e.my_parent = e.parentElement
e.my_x = rect.x
e.my_y = rect.y
} else {
e.my_parent = null
e.my_x = 0
e.my_y = 0
}
}
function animate_position(e) {
if (e.parentElement) {
if (e.my_parent) {
let rect = e.getBoundingClientRect()
let dx = e.my_x - rect.x
let dy = e.my_y - rect.y
if (dx !== 0 || dy !== 0) {
e.animate(
[
{ transform: `translate(${dx}px, ${dy}px)`, },
{ transform: "translate(0, 0)", },
],
{ duration: 250, easing: "ease" }
)
}
}
}
}
const ICONS = {
B0: '',
B1: '',
B2: '',
B3: '',
B4: '',
B5: '',
B6: '',
W0: '',
W1: '',
W2: '',
W3: '',
W4: '',
W5: '',
W6: '',
}
// === SYNC with rules.js ===
const LEGION_COUNT = 33
const BARBARIAN_COUNT = [ 36, 46, 56 ]
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_S4_V2 = [ 150, 155 ] // updated damnatio
const CARD_P4 = [ 156, 161 ]
const CARD_M4X = [ 162, 167 ]
const CARD_S4X = [ 168, 173 ]
const CARD_P4X = [ 174, 179 ]
const CARD_S3_V2 = [ 180, 188 ] // updated foederati
const CARD_P4X_V2 = [ 189, 194 ] // updated demagogue
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,
22, 22, 22, 22, 22, 22, 22, 22,
23, 23, 23, 23, 23, 23,
]
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_s4_v2",
"influence_p4",
"influence_m4x",
"influence_s4x",
"influence_p4x",
"influence_s3_v2",
"influence_p4x_v2",
]
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)",
"S3(Foederati)",
"P4(Demagogue)",
]
const EVENT_NAME = [
"None",
"Plague of Cyprian",
"Ardashir",
"Priest King",
"Palmyra Allies",
"Shapur I",
"Postumus",
"Ludi Saeculares",
"Cniva",
"Zenobia",
"Bad Auguries",
"Raiding Parties",
"Preparing for War",
"Inflation",
"Good Auguries",
"Diocletian",
]
const ITALIA = 0
const ASIA = 1
const GALLIA = 2
const MACEDONIA = 3
const PANNONIA = 4
const THRACIA = 5
const BRITANNIA = 6
const GALATIA = 7
const SYRIA = 8
const AEGYPTUS = 9
const AFRICA = 10
const HISPANIA = 11
const ALAMANNI = 0
const FRANKS = 1
const GOTHS = 2
const SASSANIDS = 3
const NOMADS = 4
const ALAMANNI_HOMELAND = 12
const FRANKS_HOMELAND = 13
const GOTHS_HOMELAND = 14
const SASSANIDS_HOMELAND = 15
const NOMADS_HOMELAND = 16
const MARE_OCCIDENTALE = 17
const MARE_ORIENTALE = 18
const OCEANUS_ATLANTICUS = 19
const PONTUS_EUXINUS = 20
const AVAILABLE = 21
const UNAVAILABLE = 22
const ARMY = 24
const first_barbarian = [ 3, 13, 23, 34, 46 ]
const last_barbarian = [ 12, 22, 33, 45, 55 ]
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",
"Gallia",
"Macedonia",
"Pannonia",
"Thracia",
"Britannia",
"Galatia",
"Syria",
"Aegyptus",
"Africa",
"Hispania",
"Alamanni homeland",
"Frank homeland",
"Goth homeland",
"Sassanid homeland",
"Nomad homeland",
"Mare Occidentale",
"Mare Orientale",
"Oceanus Atlanticus",
"Pontus Euxinus",
"Available",
"Unavailable",
]
const BIT_AMPHITHEATER = 1 << 7
const BIT_BASILICA = 1 << 8
const BIT_LIMES = 1 << 9
const BIT_QUAESTOR = 1 << 10
const BIT_MILITIA = 1 << 11
const BIT_BREAKAWAY = 1 << 12
const BIT_SEAT_OF_POWER = 1 << 13
const BIT_MILITIA_CASTRA = 1 << 14
const BIT_MARKET = 1 << 15
const BIT_MONUMENT = 1 << 16
const BIT_PORT = 1 << 17
const BIT_TEMPLE = 1 << 18
function get_support(where) { return view.provinces[where] & 15 }
function get_mobs(where) { return (view.provinces[where] >> 4) & 7 }
function has_quaestor(where) { return view.provinces[where] & BIT_QUAESTOR }
function has_militia(where) { return view.provinces[where] & BIT_MILITIA }
function has_amphitheater(where) { return view.provinces[where] & BIT_AMPHITHEATER }
function has_basilica(where) { return view.provinces[where] & BIT_BASILICA }
function has_limes(where) { return view.provinces[where] & BIT_LIMES }
function has_market(where) { return view.provinces[where] & BIT_MARKET }
function has_monument(where) { return view.provinces[where] & BIT_MONUMENT }
function has_port(where) { return view.provinces[where] & BIT_PORT }
function has_temple(where) { return view.provinces[where] & BIT_TEMPLE }
function is_breakaway(where) { return view.provinces[where] & BIT_BREAKAWAY }
function is_seat_of_power(where) { return view.provinces[where] & BIT_SEAT_OF_POWER }
function has_militia_castra(where) { return view.provinces[where] & BIT_MILITIA_CASTRA }
function is_no_place_governor(where) {
return where >= view.provinces.length
}
function get_rival_emperor_location(id) {
return view.barbarians[id] & 63
}
function get_barbarian_location(id) {
return view.barbarians[id] & 63
}
function is_barbarian_inactive(id) {
return view.barbarians[id] & 64
}
function get_legion_location(ix) {
return view.legions[ix] & 63
}
function is_legion_reduced(ix) {
return view.legions[ix] & 64
}
function is_legion_unused(ix) {
return view.legions[ix] === AVAILABLE
}
function get_governor_location(id, loc) {
return view.governors[id] & 63
}
function get_general_location(id) {
return view.generals[id] & 63
}
function is_general_inside_capital(id) {
return view.generals[id] & 64
}
function has_general_castra(id) {
return view.generals[id] & 128
}
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 ===
function set_has(set, item) {
let a = 0
let b = set.length - 1
while (a <= b) {
let m = (a + b) >> 1
let x = set[m]
if (item < x)
b = m - 1
else if (item > x)
a = m + 1
else
return true
}
return false
}
const PLAYER_CLASS = [ "red", "blue", "yellow", "green" ]
const PLAYER_NAME = [ "Red", "Blue", "Yellow", "Green" ]
const BARBARIAN_CLASS = [ "alamanni", "franks", "goths", "sassanids", "nomads" ]
const BOXES = {
"Thracia Support": [ 1502, 720, 258, 52 ],
"Syria Support": [ 2034, 1280, 258, 52 ],
"Pannonia Support": [ 1154, 626, 258, 53 ],
"Macedonia Support": [ 1384, 936, 258, 53 ],
"Hispania Support": [ 154, 980, 258, 53 ],
"Gallia Support": [ 460, 507, 258, 53 ],
"Galatia Support": [ 1954, 931, 258, 53 ],
"Britannia Support": [ 231, 260, 258, 52 ],
"Asia Support": [ 1679, 1000, 258, 52 ],
"Africa Support": [ 647, 1290, 258, 53 ],
"Aegyptus Support": [ 1700, 1468, 258, 53 ],
"Italia Support 2": [ 1054, 887, 258, 52 ],
"Italia Support 1": [ 1028, 835, 258, 52 ],
"Thracia Capital": [ 1594, 631, 70, 70 ],
"Syria Capital": [ 2174, 1193, 70, 70 ],
"Pannonia Capital": [ 1214, 536, 70, 70 ],
"Macedonia Capital": [ 1477, 850, 70, 70 ],
"Italia Capital": [ 1038, 743, 70, 70 ],
"Hispania Capital": [ 249, 892, 70, 70 ],
"Gallia Capital": [ 554, 418, 70, 70 ],
"Galatia Capital": [ 2048, 842, 70, 70 ],
"Britannia Capital": [ 325, 177, 70, 70 ],
"Asia Capital": [ 1790, 908, 70, 70 ],
"Africa Capital": [ 741, 1204, 70, 70 ],
"Aegyptus Capital": [ 1793, 1380, 70, 70 ],
"Pontus Euxinus XY": [ 1880, 580, 60, 60 ],
"Mare Orientale XY": [ 1480, 1160, 60, 60 ],
"Mare Occidentale XY": [ 720, 900, 60, 60 ],
"Oceanus Atlanticus XY": [ 180, 500, 60, 60 ],
"Nomads XY": [ 520, 1440, 60, 60 ],
"Sassanids XY": [ 2440, 820, 60, 60 ],
"Goths XY": [ 2020, 360, 60, 60 ],
"Alamanni XY": [ 1540, 280, 60, 60 ],
"Franks XY": [ 1160, 300, 60, 60 ],
"Franks Dice": [ 785, 160, 100, 50 ],
"Alamanni Dice": [ 1265, 160, 100, 50 ],
"Goths Dice": [ 1730, 195, 100, 50 ],
"Sassanids Dice": [ 2380, 895, 100, 50 ],
"Nomads Dice": [ 570, 1520, 100, 50 ],
"Franks Battle": [ 750, 210, 430, 180 ],
"Alamanni Battle": [ 1240, 210, 430, 180 ],
"Goths Battle": [ 1670, 245, 430, 180 ],
"Sassanids Battle": [ 2070, 980, 430, 180 ],
"Nomads Battle": [ 670, 1400, 430, 180 ],
}
const LAYOUT_XY = [
BOXES["Italia Capital"],
BOXES["Asia Capital"],
BOXES["Gallia Capital"],
BOXES["Macedonia Capital"],
BOXES["Pannonia Capital"],
BOXES["Thracia Capital"],
BOXES["Britannia Capital"],
BOXES["Galatia Capital"],
BOXES["Syria Capital"],
BOXES["Aegyptus Capital"],
BOXES["Africa Capital"],
BOXES["Hispania Capital"],
BOXES["Alamanni XY"],
BOXES["Franks XY"],
BOXES["Goths XY"],
BOXES["Sassanids XY"],
BOXES["Nomads XY"],
BOXES["Mare Occidentale XY"],
BOXES["Mare Orientale XY"],
BOXES["Oceanus Atlanticus XY"],
BOXES["Pontus Euxinus XY"],
]
const LAYOUT_BATTLE = [
BOXES["Italia Capital"],
BOXES["Asia Capital"],
BOXES["Gallia Capital"],
BOXES["Macedonia Capital"],
BOXES["Pannonia Capital"],
BOXES["Thracia Capital"],
BOXES["Britannia Capital"],
BOXES["Galatia Capital"],
BOXES["Syria Capital"],
BOXES["Aegyptus Capital"],
BOXES["Africa Capital"],
BOXES["Hispania Capital"],
BOXES["Alamanni Battle"],
BOXES["Franks Battle"],
BOXES["Goths Battle"],
BOXES["Sassanids Battle"],
BOXES["Nomads Battle"],
]
const LAYOUT_SUPPORT = [
BOXES["Italia Support 1"],
BOXES["Asia Support"],
BOXES["Gallia Support"],
BOXES["Macedonia Support"],
BOXES["Pannonia Support"],
BOXES["Thracia Support"],
BOXES["Britannia Support"],
BOXES["Galatia Support"],
BOXES["Syria Support"],
BOXES["Aegyptus Support"],
BOXES["Africa Support"],
BOXES["Hispania Support"],
]
const LAYOUT_DICE = [
BOXES["Alamanni Dice"],
BOXES["Franks Dice"],
BOXES["Goths Dice"],
BOXES["Sassanids Dice"],
BOXES["Nomads Dice"],
]
const LAYOUT_QUAESTOR = [
[ 971, 829 ],
[ 1622, 994 ],
[ 403, 501 ],
[ 1327, 930 ],
[ 1097, 620 ],
[ 1445, 714 ],
[ 174, 254 ],
[ 1897, 925 ],
[ 1977, 1274 ],
[ 1643, 1462 ],
[ 590, 1284 ],
[ 97, 974 ],
]
const LAYOUT_SEA = [ [ 0, 0 ] ]
const LAYOUT_HOMELAND = [
[ 0, 0 ],
[ -1, 0 ],
[ -2, 0 ],
[ -3, 0 ],
[ -3, -1 ],
[ -2, -1 ],
[ -1, -1 ],
[ 0, -1 ],
]
const LAYOUT_ALAMANNI = [
[ 0, 0 ],
[ -1, 0 ],
[ -2, 0 ],
[ -2, 1 ],
[ -2, -1 ],
]
const LAYOUT_NOMADS = [
[ 0, 0 ],
[ 1, 0 ],
[ 4, 0 ],
[ 5, 0 ],
[ -1, -1 ],
[ 2, 0 ],
[ 3, 0 ],
[ -2, -1 ],
[ -3, -1 ],
[ 0, 1 ],
]
const LAYOUT_SASSANIDS = [
[ 0, 0 ],
[ -1, 0 ],
[ -2, 0 ],
[ 0, -1 ],
[ -1, -1 ],
[ -2, -1 ],
[ -2, 1 ],
[ -1, 1 ],
[ 0, 1 ],
[ -2, 2 ],
[ -1, 2 ],
[ 0, 2 ],
]
const LAYOUT_ITALIA = [
//[ 0, -2 ],
[ -1, -2 ],
[ -2, -2 ],
[ -3, -2 ],
[ -2, -1 ],
[ -1, -1 ],
[ 0, -1 ],
[ 1, 0 ],
[ 2, 0 ],
[ -1, 0 ],
[ 0, 3 ],
]
const LAYOUT_ASIA = [
[ -1, 0 ],
[ 1, 0 ],
[ -1, -1 ],
[ 0, -1 ],
[ 1, -1 ],
[ 1, -2 ],
[ 0, -2 ],
[ 1, -3 ],
[ -1, 3 ],
]
const LAYOUT_GALLIA = [
[ -1, 0 ],
[ 1, 0 ],
[ 2, 0 ],
[ 2, -1 ],
[ 2, -2 ],
[ -2, 0 ],
[ 1, -1 ],
[ 1, -2 ],
[ 0, -1 ],
[ 0, -2 ],
[ -1, 3 ],
]
const LAYOUT_MACEDONIA = [
[ -1, 0 ],
[ -2, 0 ],
[ 1, 0 ],
[ 0, -1 ],
[ -1, -1 ],
[ -2, -1 ],
[ -1, 3 ],
]
const LAYOUT_PANNONIA = [
[ -3.5, -1.4 ],
[ -2.5, -1.4 ],
[ -1.5, -1.4 ],
[ -0.5, -1.4 ],
[ +0.5, -1.4 ],
[ -4.5, -1.4 ],
[ -1, 0 ],
[ 1, 0 ],
]
const LAYOUT_THRACIA = [
[ -2, -1 ],
[ -2, -2 ],
[ -1, 0 ],
[ 1, 0 ],
[ 1, -1 ],
[ -2, -3 ],
[ 0, -1 ],
[ -1, -1 ],
[ -1, -2 ],
]
const LAYOUT_BRITANNIA = [
[ -1, 0 ],
[ 1, 0 ],
[ 2, 0 ],
[ -2, 0 ],
[ -3, 0 ],
[ -3, 1 ],
[ -3, 2 ],
[ -2, 1 ],
[ -2, 2 ],
[ -3, 3 ],
]
const LAYOUT_GALATIA = [
[ -1, 0 ],
[ 1, 0 ],
[ 1, -1 ],
[ 0, -1 ],
[ -1, -1 ],
[ 1, -2 ],
[ 0, -2 ],
[ -1, -2 ],
[ -1, -3 ],
]
const LAYOUT_SYRIA = [
[ -1, 0 ],
[ 1, 0 ],
[ 1, -1 ],
[ 0, -1 ],
[ -1, -1 ],
[ -2, 0 ],
[ 2, 0 ],
[ -2, -1 ],
[ 2, -1 ],
[ 0, -2 ],
[ -1, -2 ],
[ 1, -2 ],
]
const LAYOUT_AEGYPTUS = [
[ -1, 0 ],
[ -2, 0 ],
[ -3, 0 ],
[ -4, 0 ],
[ 1, 0 ],
[ -4, -1 ],
[ -4, 1 ],
[ -3, 1 ],
[ -4, 2 ],
[ -3, 2 ],
[ 3, 2 ],
]
const LAYOUT_AFRICA = [
[ -1, 0 ],
[ -2, 0 ],
[ -3, 0 ],
[ -4, 0 ],
[ 1, 0 ],
[ 2, 0 ],
[ 2, -1 ],
[ 1, -1 ],
[ -4, 1 ],
[ -3, 1 ],
[ 3, 2 ],
[ 4, 2 ],
[ 5, 2 ],
[ 6, 2 ],
[ 5, 3 ],
]
const LAYOUT_HISPANIA = [
[ -1, 0 ],
[ 1, 0 ],
[ 2, 0 ],
[ 3, -1 ],
[ -2, 0 ],
[ 2, -1 ],
[ 1, -1 ],
[ 0, -1 ],
[ -1, -1 ],
[ -1, -2 ],
[ 0, -2 ],
[ 1, -2 ],
[ -1, 3 ],
]
const LAYOUT_PATTERN = [
LAYOUT_ITALIA,
LAYOUT_ASIA,
LAYOUT_GALLIA,
LAYOUT_MACEDONIA,
LAYOUT_PANNONIA,
LAYOUT_THRACIA,
LAYOUT_BRITANNIA,
LAYOUT_GALATIA,
LAYOUT_SYRIA,
LAYOUT_AEGYPTUS,
LAYOUT_AFRICA,
LAYOUT_HISPANIA,
LAYOUT_ALAMANNI,
LAYOUT_HOMELAND,
LAYOUT_HOMELAND,
LAYOUT_SASSANIDS,
LAYOUT_NOMADS,
LAYOUT_SEA,
LAYOUT_SEA,
LAYOUT_SEA,
LAYOUT_SEA,
]
let ui = {
card_tip: document.getElementById("card_tip"),
cards: [],
event_cards: [],
militia: [],
body: document.querySelector("body"),
header: document.querySelector("header"),
hand: document.getElementById("hand"),
draw: document.getElementById("draw"),
active_event: document.getElementById("active_event"),
combat_mask: document.getElementById("combat_mask"),
discard: document.getElementById("discard"),
played_header: document.getElementById("played_header"),
played_panel: document.getElementById("played_panel"),
played: document.getElementById("played"),
market: document.getElementById("market"),
pieces: document.getElementById("pieces"),
legacy: [
document.getElementById("red_legacy"),
document.getElementById("blue_legacy"),
document.getElementById("yellow_legacy"),
document.getElementById("green_legacy"),
],
emperor_turns: [
document.getElementById("red_emperor_turns"),
document.getElementById("blue_emperor_turns"),
document.getElementById("yellow_emperor_turns"),
document.getElementById("green_emperor_turns"),
],
regions: [
document.getElementById("mapsvg").getElementById("region_italia"),
document.getElementById("mapsvg").getElementById("region_asia"),
document.getElementById("mapsvg").getElementById("region_gallia"),
document.getElementById("mapsvg").getElementById("region_macedonia"),
document.getElementById("mapsvg").getElementById("region_pannonia"),
document.getElementById("mapsvg").getElementById("region_thracia"),
document.getElementById("mapsvg").getElementById("region_britannia"),
document.getElementById("mapsvg").getElementById("region_galatia"),
document.getElementById("mapsvg").getElementById("region_syria"),
document.getElementById("mapsvg").getElementById("region_aegyptus"),
document.getElementById("mapsvg").getElementById("region_africa"),
document.getElementById("mapsvg").getElementById("region_hispania"),
document.getElementById("mapsvg").getElementById("region_alamanni"),
document.getElementById("mapsvg").getElementById("region_franks"),
document.getElementById("mapsvg").getElementById("region_goths"),
document.getElementById("mapsvg").getElementById("region_sassanids"),
document.getElementById("mapsvg").getElementById("region_nomads"),
document.getElementById("mapsvg").getElementById("region_mare_occidentale"),
document.getElementById("mapsvg").getElementById("region_mare_orientale"),
document.getElementById("mapsvg").getElementById("region_oceanus_atlanticus"),
document.getElementById("mapsvg").getElementById("region_pontus_euxinus"),
],
capital: [
document.getElementById("capital_italia"),
document.getElementById("capital_asia"),
document.getElementById("capital_gallia"),
document.getElementById("capital_macedonia"),
document.getElementById("capital_pannonia"),
document.getElementById("capital_thracia"),
document.getElementById("capital_britannia"),
document.getElementById("capital_galatia"),
document.getElementById("capital_syria"),
document.getElementById("capital_aegyptus"),
document.getElementById("capital_africa"),
document.getElementById("capital_hispania"),
],
quaestor: [],
imp_amphitheater: [],
imp_basilica: [],
imp_limes: [],
imp_market: [],
imp_monument: [],
imp_port: [],
imp_temple: [],
crisis: document.getElementById("crisis_highlight"),
dice: [
document.getElementById("crisis_die_1"),
document.getElementById("crisis_die_2"),
document.getElementById("barbarian_die_1"),
document.getElementById("barbarian_die_2"),
],
neutral_governors: [],
barbarian_leaders: [],
rival_emperors: [],
seat_of_power: [],
breakaway: [],
legions: [],
barbarians: [ [], [], [], [], [] ],
generals: [ [], [], [], [] ],
governors: [ [], [], [], [] ],
castra: [ [], [], [], [] ],
mcastra: [],
mobs: [],
}
function get_province_governor_player(where) {
let np = view.legacy.length
for (let p = 0; p < np; ++p)
for (let i = 0; i < 6; ++i)
if (get_governor_location(first_governor[p] + i) === where)
return p
return -1
}
function is_neutral_province(where) {
if (is_no_place_governor(where))
return false
return get_province_governor_player(where) < 0
}
function show_improvement(elt, off) {
let x = 0, y = 0
switch (off) {
case 1:
x = -48 - 3
y = 6
break
case 2:
x = 48 + 3
y = 6
break
case 3:
x = 0
y = 6 + 25
break
}
elt.style.left = elt.my_x + x + "px"
elt.style.top = elt.my_y + y + "px"
elt.classList.remove("hide")
}
function show(elt) {
elt.classList.remove("hide")
}
function hide(elt) {
elt.classList.add("hide")
}
function create(t, p, ...c) {
let e = document.createElement(t)
Object.assign(e, p)
e.append(c)
if (p.my_action)
register_action(e, p.my_action, p.my_id)
return e
}
function create_thing(p) {
let e = create("div", p)
ui.pieces.appendChild(e)
return e
}
function create_piece(id, action, css_class, dom_id) {
if (dom_id)
return create_thing({ className: css_class + " hide", id: dom_id, my_action: action, my_id: id })
return create_thing({ className: css_class + " hide", my_action: action, my_id: id })
}
let action_register = []
function register_action(target, action, id) {
target.my_action = action
target.my_id = id
target.onmousedown = (evt) => on_click_action(evt, target)
action_register.push(target)
}
function on_click_action(evt, target) {
if (evt.button === 0)
if (send_action(target.my_action, target.my_id))
evt.stopPropagation()
}
function create_building(region, className, xoff, yoff) {
let [ x, y, w, h ] = LAYOUT_SUPPORT[region]
if (region === ITALIA)
y += 52
let e = create_thing({ className })
e.my_x = x + (w >> 1) - 46
e.my_y = y + h
return e
}
function create_support_buttons(region) {
let [ x0, y0 ] = LAYOUT_SUPPORT[region]
for (let i = 0; i <= 4; ++i) {
let x = Math.floor(-1 + x0 + i * 51.6666)
let y = (-1 + y0)
let e = create_thing({ className: "support s" + i, my_action: "support", my_id: (region << 3) + i })
e.style.top = y + "px"
e.style.left = x + "px"
}
if (region === ITALIA) {
[ x0, y0 ] = BOXES["Italia Support 2"]
for (let i = 5; i <= 7; ++i) {
let x = Math.floor(-1 + x0 + (i-5) * 51.6666)
let y = (-1 + y0)
let e = create_thing({ className: "support s" + i, my_action: "support", my_id: (region << 3) + i })
e.style.top = y + "px"
e.style.left = x + "px"
}
}
}
function is_action(action, arg) {
if (arg === undefined)
return !!(view.actions && view.actions[action] === 1)
return !!(view.actions && view.actions[action] && set_has(view.actions[action], arg))
}
function on_init() {
for (let c = 0; c < CARD_INDEX.length; ++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) {
ui.event_cards[e] = create("div", { className: "card event event_" + e })
}
for (let i = 0; i < LEGION_COUNT; ++i)
ui.legions[i] = create_piece(i, "legion", "legion", "legion_" + i)
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].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) {
ui.castra[p][g] = create_thing({ className: "castra hide" })
ui.governors[p][g] = create_piece(p * 6 + g, "governor", PLAYER_CLASS[p] + " governor n" + g)
ui.generals[p][g] = create_piece(p * 6 + g, "general", PLAYER_CLASS[p] + " general n" + g)
}
}
for (let region = 0; region < 12; ++region) {
ui.mcastra[region] = create_thing({ className: "castra hide" })
ui.militia[region] = create_thing({ className: "militia hide", my_action: "militia", my_id: region })
ui.quaestor[region] = create_thing({ className: "quaestor hide" })
ui.quaestor[region].style.left = (LAYOUT_QUAESTOR[region][0] + 16) + "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")
ui.mobs[region * 3 + 1] = create_piece(region, "mob", "mob")
ui.mobs[region * 3 + 2] = create_piece(region, "mob", "mob")
ui.imp_amphitheater[region] = create_building(region, "improvement amphitheater hide")
ui.imp_basilica[region] = create_building(region, "improvement basilica hide")
ui.imp_limes[region] = create_building(region, "improvement limes hide")
ui.imp_market[region] = create_building(region, "improvement market hide")
ui.imp_monument[region] = create_building(region, "improvement monument hide")
ui.imp_port[region] = create_building(region, "improvement port hide")
ui.imp_temple[region] = create_building(region, "improvement temple hide")
register_action(ui.capital[region], "capital", region)
register_action(ui.regions[region], "region", region)
create_support_buttons(region)
ui.neutral_governors[region] = create_thing({ className: "neutral governor hide" })
}
for (let region = 12; region < 21; ++region) {
register_action(ui.regions[region], "region", region)
}
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] + 16) + "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] + 16) + "px"
ui.breakaway[p * 12 + i].style.top = (LAYOUT_QUAESTOR[i][1]) + "px"
}
}
}
let stack_count = new Array(21).fill(0)
let combat_width = 0
const BATTLE_MIN = 3
const BATTLE_H_MARGIN = 12
const BATTLE_V_MARGIN = 12
const BATTLE_H_GAP = 8
const BATTLE_V_GAP = 16
function layout_battle_stack(is_att, list, region) {
let [ x, y, w, h ] = LAYOUT_BATTLE[region]
x += w >> 1
if (region < 12)
y -= 7
if (list.length > combat_width)
combat_width = list.length
w = list.length * 60 + (list.length - 1) * BATTLE_H_GAP
x -= w / 2
y += BATTLE_V_MARGIN
if (is_att)
y += 60 + BATTLE_V_GAP
for (let item of list) {
item.style.left = x + "px"
item.style.top = y + "px"
item.style.zIndex = 101
x += 60 + BATTLE_H_GAP
}
}
function layout_stack(id, list, region, in_capital, dx, dy, z = 1) {
let [ x, y, w, h ] = LAYOUT_XY[region]
x += w >> 1
y += h >> 1
x -= 30
y -= 30
if (!in_capital) {
let step = (region < 12) ? 80 : 100
let sc = stack_count[region]
if (sc >= LAYOUT_PATTERN[region].length)
sc = LAYOUT_PATTERN[region].length - 1
let xo = LAYOUT_PATTERN[region][sc][0] * step
let yo = LAYOUT_PATTERN[region][sc][1] * step
if (stack_count[region] > sc)
xo += (stack_count[region] - sc) * step
x += xo
y += yo
stack_count[region] += 1
}
if (in_capital === 2) {
x += 36
y += 18
}
for (let i = list.length - 1; i >= 0; --i) {
let item = list[i]
item.style.left = x + "px"
item.style.top = y + "px"
item.style.zIndex = z
x -= dx
y -= dy
z += 1
}
}
function layout_available(list, dx, x0, y0) {
let y = 1650 + 45 - y0
let x = 25 + x0
let z = 7
for (let item of list) {
item.style.left = x + "px"
item.style.top = y + "px"
item.style.zIndex = z
x += dx
z -= 1
}
}
function layout_governor(e, color, region) {
e.className = color + " governor s" + get_support(region)
e.style.left = LAYOUT_SUPPORT[region][0] - 1 + "px"
e.style.top = LAYOUT_SUPPORT[region][1] - 1 + "px"
}
function layout_governor_available(e, color) {
e.className = color + " governor"
}
function layout_governor_unavailable(e, color, ix) {
e.className = color + " governor n" + ix
}
function layout_mob(region, i, e, visible, x2) {
if (visible) {
let [ x, y, w, h ] = LAYOUT_SUPPORT[region]
e.className = x2 ? "mob_x2" : "mob"
e.style.top = (y - 36) + "px"
e.style.left = (x + 26 + 26 * i) + "px"
} else {
e.className = "hide"
}
}
function layout_barbarian_dice(black, white, tribe) {
if (tribe >= 0) {
show(black)
show(white)
let [ x, y, w, h ] = LAYOUT_DICE[tribe]
black.style.top = (y + 4) + "px"
white.style.top = (y + 4) + "px"
black.style.left = (x + 0) + "px"
white.style.left = (x + 50) + "px"
} else {
hide(black)
hide(white)
}
}
function is_battle_stack(region, type, id) {
if (view.combat_region !== region)
return false
if (type === "general" && view.combat.attacker === id)
return true
if (type === "militia" && view.combat.attacker < 0)
return true
if (type === "militia" && view.combat.type === "militia")
return true
return view.combat.type === type && view.combat.target === id
}
function on_update() {
let player_count = view.legacy.length
ui.cards.forEach(remember_position)
for (let p = 0; p < player_count; ++p) {
let t = view.legacy[p] + " (" + view.emperor_turns[p] + ")"
if (p === view.first)
t = "\u2756 " + t
roles[PLAYER_NAME[p]].stat.textContent = t
}
ui.body.classList.toggle("p2", player_count === 2)
ui.body.classList.toggle("p3", player_count === 3)
ui.body.classList.toggle("p4", player_count === 4)
combat_width = BATTLE_MIN
for (let pi = 0; pi < player_count; ++pi) {
let legacy = view.legacy[pi]
let turns = view.emperor_turns[pi]
if (legacy > 80) {
legacy -= 80
ui.legacy[pi].classList.toggle("legacy_80", true)
ui.legacy[pi].classList.toggle("legacy_40", false)
} else if (legacy > 40) {
legacy -= 40
ui.legacy[pi].classList.toggle("legacy_80", false)
ui.legacy[pi].classList.toggle("legacy_40", true)
} else {
ui.legacy[pi].classList.toggle("legacy_80", false)
ui.legacy[pi].classList.toggle("legacy_40", false)
}
let n = 0
for (let k = 0; k < player_count; ++k) {
let k_legacy = view.legacy[k]
if (k_legacy > 80)
k_legacy -= 40
if (k_legacy > 40)
k_legacy -= 40
if (legacy === k_legacy)
++n
}
let y = (n === 1) ? 50 : (n === 2) ? 40 : 30
for (let k = 0; k < pi; ++k) {
let k_legacy = view.legacy[k]
if (k_legacy > 80)
k_legacy -= 40
if (k_legacy > 40)
k_legacy -= 40
if (legacy === k_legacy)
y += 20
}
show(ui.legacy[pi])
ui.legacy[pi].style.left = Math.round(43 + legacy * 60.2) + "px"
ui.legacy[pi].style.top = 2 + y + "px"
n = 0
for (let k = 0; k < player_count; ++k)
if (turns === view.emperor_turns[k])
++n
y = (n === 1) ? 50 : (n === 2) ? 40 : 30
for (let k = 0; k < pi; ++k)
if (turns === view.emperor_turns[k])
y += 20
show(ui.emperor_turns[pi])
ui.emperor_turns[pi].style.left = Math.round(41 + turns * 60.2) + "px"
ui.emperor_turns[pi].style.top = 0 + y + "px"
}
for (let pi = player_count; pi < 4; ++pi) {
hide(ui.legacy[pi])
hide(ui.emperor_turns[pi])
}
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])
if (is_seat_of_power(region) || is_breakaway(region))
ui.quaestor[region].classList.add("pretender")
} else {
hide(ui.quaestor[region])
ui.quaestor[region].classList.remove("pretender")
}
if (has_militia(region))
show(ui.militia[region])
else
hide(ui.militia[region])
ui.militia[region].classList.toggle("selected", view.selected_militia === region)
let imp_off = 0
if (has_amphitheater(region))
show_improvement(ui.imp_amphitheater[region], ++imp_off)
else
hide(ui.imp_amphitheater[region])
if (has_basilica(region))
show_improvement(ui.imp_basilica[region], ++imp_off)
else
hide(ui.imp_basilica[region])
if (has_limes(region))
show_improvement(ui.imp_limes[region], ++imp_off)
else
hide(ui.imp_limes[region])
if (has_market(region))
show_improvement(ui.imp_market[region], ++imp_off)
else
hide(ui.imp_market[region])
if (has_monument(region))
show_improvement(ui.imp_monument[region], ++imp_off)
else
hide(ui.imp_monument[region])
if (has_port(region))
show_improvement(ui.imp_port[region], ++imp_off)
else
hide(ui.imp_port[region])
if (has_temple(region))
show_improvement(ui.imp_temple[region], ++imp_off)
else
hide(ui.imp_temple[region])
}
for (let i = 0; i < LEGION_COUNT; ++i) {
if (is_legion_unused(i))
hide(ui.legions[i])
else
show(ui.legions[i])
if (is_legion_reduced(i))
ui.legions[i].classList.toggle("reduced", true)
else
ui.legions[i].classList.toggle("reduced", false)
}
for (let id = 3; id < BARBARIAN_COUNT[player_count-2]; ++id) {
let loc = get_barbarian_location(id)
if (loc === AVAILABLE)
hide(ui.barbarians[id])
else
show(ui.barbarians[id])
}
for (let id = BARBARIAN_COUNT[player_count-2]; id < 56; ++id)
hide(ui.barbarians[id])
stack_count.fill(0)
for (let region = 0; region < 12 + 5; ++region) {
for (let tribe = 0; tribe < 5; ++tribe) {
let battle = []
let active_barbarians = []
let inactive_barbarians = []
for (let id = first_barbarian[tribe]; id <= last_barbarian[tribe]; ++id) {
let loc = get_barbarian_location(id)
let inactive = is_barbarian_inactive(id)
if (loc === region) {
let bb = is_battle_stack(region, "barbarians", tribe) && (region < 12 || !inactive)
if (bb)
battle.push(ui.barbarians[id])
else if (inactive)
inactive_barbarians.push(ui.barbarians[id])
else
active_barbarians.push(ui.barbarians[id])
// always show leaders as active during battle
if (!inactive || (bb && (id === CNIVA || id == ARDASHIR || id === SHAPUR)))
ui.barbarians[id].classList.toggle("inactive", false)
else
ui.barbarians[id].classList.toggle("inactive", true)
}
}
if (inactive_barbarians.length > 0)
if (region >= 12)
layout_stack(-1, inactive_barbarians, region, false, 4, 4)
else
layout_stack(-1, inactive_barbarians, region, false, 8, 8)
if (active_barbarians.length > 0)
layout_stack(-1, active_barbarians, region, false, 8, 8)
if (battle.length > 0)
layout_battle_stack(0, battle, region)
}
}
for (let id = 0; id < 3; ++id) {
let loc = get_rival_emperor_location(id)
if (loc === AVAILABLE)
hide(ui.rival_emperors[id])
else {
show(ui.rival_emperors[id])
if (is_battle_stack(loc, "rival_emperor", id))
layout_battle_stack(0, [ ui.rival_emperors[id] ], loc)
else
layout_stack(-1, [ ui.rival_emperors[id] ], loc, false, 8, 8)
}
}
for (let region = 0; region < 21; ++region) {
ui.regions[region].classList.toggle("selected", view.selected_region === region)
}
for (let region = 0; region < 12; ++region) {
if (has_militia_castra(region))
show(ui.mcastra[region])
else
hide(ui.mcastra[region])
if (has_militia(region)) {
let lone_militia = true
for (let pi = 0; pi < player_count; ++pi) {
for (let i = 0; i < 6; ++i) {
let loc = get_general_location(first_general[pi] + i)
let inside = is_general_inside_capital(first_general[pi] + i)
if (loc === region && inside)
lone_militia = false
}
}
// militia that already battled is not part of attacker stack
if (view.combat_region === region && view.combat.attacker >= 0 && !view.combat.militia)
lone_militia = true
if (lone_militia) {
if (is_battle_stack(region, "militia", region)) {
if (has_militia_castra(region))
layout_battle_stack(view.combat.attacker < 0, [ ui.mcastra[region], ui.militia[region] ], region)
else
layout_battle_stack(view.combat.attacker < 0, [ ui.militia[region] ], region, true)
} else {
let inside = 1
if (is_action("capital", region))
inside = 2
if (has_militia_castra(region))
layout_stack(-1, [ ui.mcastra[region], ui.militia[region] ], region, inside, 16, 16)
else
layout_stack(-1, [ ui.militia[region] ], region, inside, 16, 16)
}
}
}
if (is_no_place_governor(region)) {
hide(ui.neutral_governors[region])
} else {
if (is_neutral_province(region)) {
show(ui.neutral_governors[region])
layout_governor(ui.neutral_governors[region], "neutral", region)
} else {
hide(ui.neutral_governors[region])
}
}
let n = get_mobs(region)
layout_mob(region, 0, ui.mobs[region * 3 + 0], n >= 1, n >= 2)
layout_mob(region, 1, ui.mobs[region * 3 + 1], n >= 3, n >= 4)
layout_mob(region, 2, ui.mobs[region * 3 + 2], n >= 5, n >= 6)
}
for (let pi = 0; pi < player_count; ++pi) {
let avail_stack = []
for (let ai = 0; ai < 6; ++ai) {
let army = ARMY + first_general[pi] + ai
let region = get_general_location(first_general[pi] + ai)
let inside = is_general_inside_capital(first_general[pi] + ai)
let castra = has_general_castra(first_general[pi] + ai)
let e = ui.generals[pi][ai]
show(e)
if (region < 21) {
let stack = []
if (castra) {
show(ui.castra[pi][ai])
stack.push(ui.castra[pi][ai])
} else {
hide(ui.castra[pi][ai])
}
if (has_militia_castra(region) && inside)
stack.push(ui.mcastra[region])
stack.push(e)
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 < 5; ++tribe) {
for (let id = first_barbarian[tribe]; id <= last_barbarian[tribe]; ++id) {
let loc = get_barbarian_location(id)
if (loc === army) {
ui.barbarians[id].classList.toggle("inactive", false)
stack.push(ui.barbarians[id])
}
}
}
if (has_militia(region) && inside) {
// militia that already battled is not part of attacker stack
if (view.combat_region === region && view.combat.attacker >= 0 && !view.combat.militia)
;
else
stack.push(ui.militia[region])
}
if (is_battle_stack(region, "general", pi * 6 + ai))
layout_battle_stack(pi * 6 + ai === view.combat.attacker, stack, region)
else
layout_stack(pi * 6 + ai, stack, region, inside ? 1 : 0, 16, 16)
} else {
avail_stack.push(e)
hide(ui.castra[pi][ai])
}
e.classList.toggle("unavailable", region === UNAVAILABLE)
e.classList.toggle("selected", view.selected_general === pi * 6 + ai)
e.classList.toggle("emperor", view.emperor === army)
}
if (avail_stack.length >= 6)
layout_available(avail_stack, 48, pi * 625 + 0, 30)
else if (avail_stack.length >= 5)
layout_available(avail_stack, 63, pi * 625 + 0, 30)
else
layout_available(avail_stack, 69, pi * 625 + 0, 30)
}
for (let pi = 0; pi < player_count; ++pi) {
let avail_stack = []
for (let ai = 0; ai < 6; ++ai) {
let region = get_governor_location(first_governor[pi] + ai)
let e = ui.governors[pi][ai]
if (region < 12) {
layout_governor(e, PLAYER_CLASS[pi], region)
} else {
if (region === AVAILABLE)
layout_governor_available(e, PLAYER_CLASS[pi])
else
layout_governor_unavailable(e, PLAYER_CLASS[pi], ai)
avail_stack.push(e)
}
e.classList.toggle("unavailable", region === UNAVAILABLE)
e.classList.toggle("selected", view.selected_governor === pi * 6 + ai)
e.classList.toggle("emperor", view.emperor === pi * 6 + ai)
}
if (avail_stack.length >= 6)
layout_available(avail_stack, 43, pi * 625 + 325, 27)
else if (avail_stack.length >= 5)
layout_available(avail_stack, 58, pi * 625 + 325, 27)
else
layout_available(avail_stack, 64, pi * 625 + 325, 27)
}
if (view.combat) {
let [ x, y, w, h ] = LAYOUT_BATTLE[view.combat_region]
if (view.combat_region < 12)
y -= 7
x += w >> 1
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
show(ui.combat_mask)
ui.combat_mask.style.left = x + "px"
ui.combat_mask.style.top = y + "px"
ui.combat_mask.style.width = w + "px"
ui.combat_mask.style.height = h + "px"
} else {
hide(ui.combat_mask)
}
ui.body.classList.toggle("military", view.color === 0)
ui.body.classList.toggle("senate", view.color === 1)
ui.body.classList.toggle("populace", view.color === 2)
layout_barbarian_dice(ui.dice[2], ui.dice[3], view.crisis[0])
ui.crisis.className = "p_" + PLAYER_CLASS[view.current] + " c" + (view.crisis[1] + view.crisis[2])
ui.dice[0].className = "dice black d" + view.crisis[1]
ui.dice[1].className = "dice white d" + view.crisis[2]
if (view.crisis[0] >= 0) {
ui.dice[2].className = "dice black d" + view.crisis[3]
ui.dice[3].className = "dice white d" + view.crisis[4]
} else {
ui.dice[2].className = "dice black hide"
ui.dice[3].className = "dice white hide"
}
ui.active_event.replaceChildren()
ui.active_event.appendChild(ui.event_cards[view.event])
ui.played_panel.className = "panel p_" + PLAYER_CLASS[view.current]
ui.played_header.textContent = PLAYER_NAME[view.current] + " Played"
ui.played.className = "panel_body p_" + PLAYER_CLASS[view.current]
ui.played.replaceChildren()
if (view.played) {
for (let c of view.played) {
ui.played.appendChild(ui.cards[c])
ui.cards[c].classList.toggle("used", set_has(view.used, c))
}
}
ui.hand.replaceChildren()
if (view.hand) {
for (let c of view.hand) {
ui.hand.appendChild(ui.cards[c])
ui.cards[c].classList.remove("used")
}
}
ui.draw.replaceChildren()
if (view.draw) {
for (let c of view.draw) {
ui.draw.appendChild(ui.cards[c])
ui.cards[c].classList.remove("used")
}
}
ui.discard.replaceChildren()
if (view.discard) {
for (let c of view.discard) {
ui.discard.appendChild(ui.cards[c])
ui.cards[c].classList.remove("used")
}
}
ui.market.replaceChildren()
for (let c of view.market) {
if (c > 0) {
ui.market.appendChild(ui.cards[c])
ui.cards[c].classList.remove("used")
}
}
ui.cards.forEach(animate_position)
for (let e of action_register)
e.classList.toggle("action", is_action(e.my_action, e.my_id))
action_button("play_all", "Play All")
action_button("confirm", "Confirm")
action_button("recruit_general", "Recruit General")
action_button("create_army", "Create Army")
action_button("recruit_governor", "Recruit Governor")
action_button("place_governor", "Place Governor")
action_button("enter", "Enter Capital")
action_button("leave", "Leave Capital")
action_button("automatic", "Automatic")
action_button("spend_military", "Spend Military")
action_button("spend_senate", "Spend Senate")
action_button("keep", "Keep")
action_button("reroll", "Re-roll")
action_button("roll", "Roll")
action_button("amphitheater", "Amphitheater")
action_button("basilica", "Basilica")
action_button("limes", "Limes")
action_button("market", "Market")
action_button("monument", "Monument")
action_button("port", "Port")
action_button("temple", "Temple")
action_button("disperse_mob", "Disperse Mob")
action_button("train_legions", "Train Legions")
action_button("add_legion_to_army", "Add Legion to Army")
action_button("recall_governor", "Recall Governor")
action_button("hold_games", "Hold Games")
action_button("place_militia", "Place Militia")
action_button("build_improvement", "Build Improvement")
action_button("end_actions", "End Actions")
action_button("end_turn", "End Turn")
action_button("pass", "Pass")
action_button("done", "Done")
action_button("undo", "Undo")
}
function sub_region_name(match, p1) {
let x = p1 | 0
return REGION_NAME[x]
}
function sub_barbarian(match) {
return `${match}`
}
function sub_event_name(match, p1) {
let x = p1 | 0
return `${EVENT_NAME[x]}`
}
function sub_icon(match) {
return ICONS[match]
}
function sub_card_1(match) {
let x = CARD_MAP.indexOf(match)
return `${match}`
}
function sub_card_x(match, p1, p2) {
let x = CARD_MAP.indexOf(match)
if (p2 === "Damnatio Memoriae*")
p2 = "Damnatio Memoriae"
return `${p1} ${p2}`
}
var log_combat2 = 0
var log_combat1 = 0
var log_place = 0
var log_pretender = 0
function on_log(text, ix) {
let p = document.createElement("div")
if (text.match(/^>/)) {
text = text.substring(1)
p.className = "i"
}
text = text.replace(/&/g, "&")
text = text.replace(//g, ">")
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)
if (text.match(/^.turn/)) {
text = text.substring(6)
p.className = "turn " + text
}
if (text.match(/^\.h1 Red/)) {
text = text.substring(4)
p.className = "h1 R"
} else if (text.match(/^\.h1 Blue/)) {
text = text.substring(4)
p.className = "h1 B"
} else if (text.match(/^\.h1 Yellow/)) {
text = text.substring(4)
p.className = "h1 Y"
} else if (text.match(/^\.h1 Green/)) {
text = text.substring(4)
p.className = "h1 G"
} else if (text.match(/^\.h1/)) {
text = text.substring(4)
p.className = "h1"
} else if (text.match(/^\.h2/)) {
text = text.substring(4)
p.className = "h2"
} else if (text.match(/^\.h3/)) {
text = text.substring(4)
p.className = "h3"
}
// Reset group box counters (when log is rewound)
if (ix <= log_combat2) log_combat2 = 0
if (ix <= log_combat1) log_combat1 = 0
if (ix <= log_place) log_place = 0
if (ix <= log_pretender) log_pretender = 0
// Group pretender messages
if (text.match(/^Pretender\.$/) || text.match(/^Occupied /)) {
log_pretender = ix
p.classList.add("h2")
text = text.replace(".", "")
}
if (log_pretender && text === "")
log_pretender = 0
if (log_pretender)
p.classList.add("group", "populace")
// Group combat messages
if (text.match(/^Battle in /)) {
p.classList.add("h2")
log_combat2 = ix
log_combat1 = ix
}
if (log_combat1) {
if (
text === "DEFENDER" ||
text === "ATTACKER" ||
text === "FLANKING MANEUVER" ||
text === "SPICULUM" ||
text === "RESULT"
)
p.classList.add("h3")
if (text === "RESULT")
log_combat2 = 0
}
if (log_combat1 && !log_combat2 && text === "")
log_combat1 = 0
if (log_combat1)
p.classList.add("group", "military")
// Group place governor
if (text.match(/^Place Governor in /) || text.match(/^Praetorian Guard in /)) {
log_place = ix
p.classList.add("h2")
text = text.replace(".", "")
}
if (log_place && text === "")
log_place = 0
if (log_place)
p.classList.add("group", "senate")
p.innerHTML = 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"
}
let tint = window.localStorage[params.title_id + "/tint"]
if (tint === undefined)
tint = 1
set_tint(tint)
function set_tint(x) {
window.localStorage[params.title_id + "/tint"] = tint = x
check_menu("tint", !!tint)
ui.body.classList.toggle("tint", !!tint)
}
function toggle_tint() {
set_tint(!tint)
}
on_init()