"use strict" // TODO: battle dialog popup for rolling and assigning hits! // === SYNC with rules.js === const ITALIA = 0 const ASIA = 1 const GALLIA = 2 const MACEDONIA = 3 const PANNONIA = 4 const THRACIA = 5 const AEGYPTUS = 6 const AFRICA = 7 const HISPANIA = 8 const BRITANNIA = 9 const GALATIA = 10 const SYRIA = 11 const ALAMANNI_HOMELAND = 12 const FRANKS_HOMELAND = 13 const GOTHS_HOMELAND = 14 const NOMADS_HOMELAND = 15 const SASSANIDS_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 = 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_governor = [ 0, 6, 12, 18 ] const first_general = [ 0, 6, 12, 18 ] const REGION_NAME = [ "Italia", "Asia", "Gallia", "Macedonia", "Pannonia", "Thracia", "Aegyptus", "Africa", "Hispania", "Britannia", "Galatia", "Syria", "Alamanni Homeland", "Franks Homeland", "Goths Homeland", "Nomads Homeland", "Sassanids Homeland", "Mare Occidentale", "Mare Orientale", "Oceanus Atlanticus", "Pontus Euxinus", "Available", "Unavailable", ] function is_no_place_governor(province) { return province >= view.support.length } function get_support(province) { return view.support[province] } 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.castra & (1 << id) } function has_militia_castra(province) { return view.mcastra & (1 << province) } function has_quaestor(province) { return view.quaestor & (1 << province) } function has_militia(province) { return view.militia & (1 << province) } function get_mobs(province) { return view.mobs[province] } function has_amphitheater(province) { return view.amphitheater & (1 << province) } function has_basilica(province) { return view.basilica & (1 << province) } function has_limes(province) { return view.limes & (1 << province) } function is_breakaway(province) { return view.breakaway & (1 << province) } function is_seat_of_power(province) { return view.seat_of_power & (1 << province) } // === 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 BARBARIAN_CLASS = [ "alamanni", "franks", "goths", "nomads", "sassanids" ] 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, 1480, 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 ], } const LAYOUT_XY = [ BOXES["Italia Capital"], BOXES["Asia Capital"], BOXES["Gallia Capital"], BOXES["Macedonia Capital"], BOXES["Pannonia Capital"], BOXES["Thracia Capital"], BOXES["Aegyptus Capital"], BOXES["Africa Capital"], BOXES["Hispania Capital"], BOXES["Britannia Capital"], BOXES["Galatia Capital"], BOXES["Syria Capital"], BOXES["Alamanni XY"], BOXES["Franks XY"], BOXES["Goths XY"], BOXES["Nomads XY"], BOXES["Sassanids XY"], BOXES["Mare Occidentale XY"], BOXES["Mare Orientale XY"], BOXES["Oceanus Atlanticus XY"], BOXES["Pontus Euxinus XY"], ] const LAYOUT_SUPPORT = [ BOXES["Italia Support 1"], BOXES["Asia Support"], BOXES["Gallia Support"], BOXES["Macedonia Support"], BOXES["Pannonia Support"], BOXES["Thracia Support"], BOXES["Aegyptus Support"], BOXES["Africa Support"], BOXES["Hispania Support"], BOXES["Britannia Support"], BOXES["Galatia Support"], BOXES["Syria Support"], ] 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_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_NOMADS = [ [ 0, 0 ], [ 1, 0 ], [ 2, 0 ], [ 3, 0 ], [ 4, 0 ], [ 5, 0 ], [ 0, 1 ], ] const LAYOUT_ITALIA = [ [ -3, -2 ], [ -2, -2 ], [ -1, -2 ], [ 0, -2 ], [ -2, -1 ], [ -1, -1 ], [ 0, -1 ], [ -1, 0 ], [ 1, 0 ], [ 2, 0 ], [ 0, 3 ], ] const LAYOUT_ASIA = [ [ -1, 0 ], [ 1, 0 ], [ 0, -1 ], [ -1, -1 ], [ 1, -1 ], [ 1, -2 ], [ 0, -2 ], [ 1, -3 ], [ -1, 3 ], ] const LAYOUT_GALLIA = [ [ -1, 0 ], [ 1, 0 ], [ 0, -1 ], [ -1, -1 ], [ 1, -1 ], [ -2, 0 ], [ 2, 0 ], [ 2, -1 ], [ 0, -2 ], [ 1, -2 ], [ -1, 3 ], ] const LAYOUT_MACEDONIA = [ [ -1, 0 ], [ -2, 0 ], [ 1, 0 ], [ 0, -1 ], [ -1, -1 ], [ -2, -1 ], [ -1, 3 ], ] const LAYOUT_PANNONIA = [ [ 0, -1 ], [ -1, -1 ], [ -2, -1 ], [ -3, -1 ], [ -4, -1 ], [ 1, -1 ], [ -1, -2 ], [ -2, -2 ], [ -3, -2 ], [ -4, -2 ], [ -5, -2 ], [ -1, 0 ], [ 1, 0 ], ] const LAYOUT_THRACIA = [ [ -1, 0 ], [ 1, 0 ], [ 0, -1 ], [ -1, -1 ], [ 1, -1 ], [ -2, -1 ], [ -2, -2 ], [ -3, -2 ], [ -2, -3 ], [ -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 ], [ 0, -1 ], [ -1, -1 ], [ 1, -1 ], [ -2, 0 ], [ 2, 0 ], [ -2, -1 ], [ 2, -1 ], [ 0, -2 ], [ -1, -2 ], [ 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 ], [ 0, -1 ], [ -1, -1 ], [ 1, -1 ], [ 1, -2 ], [ 0, -2 ], [ -1, -2 ], [ -1, -3 ], ] const LAYOUT_SYRIA = [ [ -1, 0 ], [ 1, 0 ], [ 0, -1 ], [ -1, -1 ], [ 1, -1 ], [ -2, 0 ], [ 2, 0 ], [ -2, -1 ], [ 2, -1 ], [ 0, -2 ], [ -1, -2 ], [ 1, -2 ], ] const LAYOUT_PATTERN = [ LAYOUT_ITALIA, LAYOUT_ASIA, LAYOUT_GALLIA, LAYOUT_MACEDONIA, LAYOUT_PANNONIA, LAYOUT_THRACIA, LAYOUT_AEGYPTUS, LAYOUT_AFRICA, LAYOUT_HISPANIA, LAYOUT_BRITANNIA, LAYOUT_GALATIA, LAYOUT_SYRIA, LAYOUT_HOMELAND, LAYOUT_HOMELAND, LAYOUT_HOMELAND, LAYOUT_NOMADS, LAYOUT_SASSANIDS, LAYOUT_SEA, LAYOUT_SEA, LAYOUT_SEA, LAYOUT_SEA, ] let ui = { cards: [], militia: [], body: document.querySelector("body"), header: document.querySelector("header"), hand: document.getElementById("hand"), draw: document.getElementById("draw"), discard: document.getElementById("discard"), 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_aegyptus"), document.getElementById("mapsvg").getElementById("region_africa"), document.getElementById("mapsvg").getElementById("region_hispania"), document.getElementById("mapsvg").getElementById("region_britannia"), document.getElementById("mapsvg").getElementById("region_galatia"), document.getElementById("mapsvg").getElementById("region_syria"), document.getElementById("mapsvg").getElementById("region_alamanni"), document.getElementById("mapsvg").getElementById("region_franks"), document.getElementById("mapsvg").getElementById("region_goths"), document.getElementById("mapsvg").getElementById("region_nomads"), document.getElementById("mapsvg").getElementById("region_sassanids"), 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: [], quaestor: [], amphitheater: [], basilica: [], limes: [], 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: [], legions: [], barbarians: [ [], [], [], [], [] ], generals: [ [], [], [], [] ], governors: [ [], [], [], [] ], castra: [ [], [], [], [] ], mcastra: [], } 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(elt) { elt.classList.remove("hide") } function hide(elt) { elt.classList.add("hide") } function toggle_pieces() { ui.pieces.classList.toggle("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 (typeof target.my_stack === "number") { evt.stopPropagation() if (focus_stack(target.my_stack)) if (!send_action(target.my_action, target.my_id)) blur_stack() } else { */ if (send_action(target.my_action, target.my_id)) evt.stopPropagation() //} } } document.getElementById("map").addEventListener("mousedown", function (evt) { if (evt.button === 0) blur_stack() }) function create_building(region, className, xoff, yoff) { let [ x, y, w, h ] = LAYOUT_SUPPORT[region] let e = create_thing({ className }) e.style.left = x + (w >> 1) + xoff - 46 + "px" e.style.top = y + h + yoff + "px" return e } 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() { let c = 1 function init_cards(n, className) { for (let i = 0; i < n; ++i) ui.cards[c + i] = create("div", { className, my_action: "card", my_id: c + i }) c += n } init_cards(12, "card influence_m1") init_cards(12, "card influence_s1") init_cards(12, "card influence_p1") init_cards(9, "card influence_m2") init_cards(9, "card influence_s2") init_cards(9, "card influence_p2") init_cards(8, "card influence_m3") init_cards(8, "card influence_s3") init_cards(8, "card influence_p3") init_cards(6, "card influence_m4") init_cards(6, "card influence_s4") init_cards(6, "card influence_p4") for (let i = 0; i < 33; ++i) ui.legions[i] = create_piece(i, "legion", "legion", "legion_" + i) 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") 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]) 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.capital[region] = document.getElementById(REGION_NAME[region] + "_Capital") ui.quaestor[region] = document.getElementById(REGION_NAME[region] + "_Quaestor") if (true) { ui.amphitheater[region] = create_building(region, "amphitheater hide", -48 - 3, 6) ui.basilica[region] = create_building(region, "basilica hide", 48 + 3, 6) ui.limes[region] = create_building(region, "limes hide", 0, 6 + 25) } else { ui.amphitheater[region] = create_building(region, "amphitheater hide", -96 - 5, 6) ui.basilica[region] = create_building(region, "basilica hide", 0, 6) ui.limes[region] = create_building(region, "limes hide", 96 + 5, 6) } register_action(ui.capital[region], "capital", region) register_action(ui.regions[region], "region", 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) } } let stack_count = new Array(21).fill(0) let stack_focus = -1 let stack_cache = [] function focus_stack(id) { if (stack_focus !== id) { // if (view.selected_general === undefined) send_action("general", id) stack_focus = id on_update() let stack = stack_cache[id] return stack && stack.length <= 1 } return true } function blur_stack() { if (stack_focus >= 0) { stack_focus = -1 on_update() } } function layout_stack(id, list, region, in_capital) { let [ x, y, w, h ] = LAYOUT_XY[region] let dx = 6 let dy = 6 let z = 1 if (id >= 0) stack_cache[id] = list x += w >> 1 y += h >> 1 x -= 30 y -= 30 if (!in_capital) { let sc = stack_count[region] if (sc >= LAYOUT_PATTERN[region].length) sc = LAYOUT_PATTERN[region].length - 1 let xo = LAYOUT_PATTERN[region][sc][0] * 80 let yo = LAYOUT_PATTERN[region][sc][1] * 80 if (stack_count[region] > sc) xo += (stack_count[region] - sc) * 80 x += xo y += yo stack_count[region] += 1 } if (list.length > 6) { dx = 4 dy = 4 } if (id >= 0) { dx = 16 dy = 16 } for (let item of list) { item.style.left = x + "px" item.style.top = y + "px" item.style.zIndex = z item.my_stack = id x -= dx y -= dy z += 1 } } function layout_available(list, dx, x0, y0) { let y = 1650 + 45 - y0 let x = 25 + x0 for (let item of list) { item.style.left = x + "px" item.style.top = y + "px" item.style.zIndex = 1 item.my_stack = 0 x += dx } } 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 on_update() { let player_count = view.legacy.length for (let i = 0; i < 24; ++i) stack_cache[i] = null ui.body.classList.toggle("p2", player_count === 2) ui.body.classList.toggle("p3", player_count === 3) ui.body.classList.toggle("p4", player_count === 4) ui.header.classList.toggle("player_red", view.current === 0) ui.header.classList.toggle("player_blue", view.current === 1) ui.header.classList.toggle("player_yellow", view.current === 2) ui.header.classList.toggle("player_green", view.current === 3) if (player_count < 4) hide(document.getElementById("role_Green")) else show(document.getElementById("role_Green")) if (player_count < 3) hide(document.getElementById("role_Yellow")) else show(document.getElementById("role_Yellow")) ui.hand.replaceChildren() ui.draw.replaceChildren() ui.discard.replaceChildren() ui.market.replaceChildren() for (let pi = 0; pi < player_count; ++pi) { let legacy = view.legacy[pi] let turns = view.emperor_turns[pi] if (legacy > 40) { legacy -= 40 ui.legacy[pi].classList.toggle("legacy_40", true) } else { ui.legacy[pi].classList.toggle("legacy_40", false) } let y = 30 for (let k = 0; k < pi; ++k) { let k_legacy = view.legacy[k] 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" y = 30 for (let k = 0; k < pi; ++k) { let k_turns = view.emperor_turns[k] if (turns === k_turns) 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) { if (has_quaestor(region)) show(ui.quaestor[region]) else hide(ui.quaestor[region]) if (has_amphitheater(region)) show(ui.amphitheater[region]) else hide(ui.amphitheater[region]) if (has_basilica(region)) show(ui.basilica[region]) else hide(ui.basilica[region]) if (has_limes(region)) show(ui.limes[region]) else hide(ui.limes[region]) if (has_militia(region)) show(ui.militia[region]) else hide(ui.militia[region]) } for (let i = 0; i < 33; ++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) } // TODO: Cniva, Ardashir, and Shapur // TODO: Zenobia, Postumus, Priest King for (let id = 0; id < BARBARIAN_COUNT[player_count]; ++id) { 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) { let active_barbarians = [] let inactive_barbarians = [] // TODO: Cniva, Ardashir, and Shapur 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) { if (inactive) inactive_barbarians.push(ui.barbarians[id]) else active_barbarians.push(ui.barbarians[id]) } } if (active_barbarians.length > 0) layout_stack(-1, active_barbarians, region, false) if (inactive_barbarians.length > 0) layout_stack(-1, inactive_barbarians, region, false) } } 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(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 } } if (lone_militia) { let mcastra = has_militia_castra(region) if (mcastra) { show(ui.mcastra[region]) layout_stack(-1, [ ui.militia[region], ui.mcastra[region] ], region, true) } else { hide(ui.mcastra[region]) layout_stack(-1, [ ui.militia[region] ], region, true) } } } 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]) } } } 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 (has_militia(region) && inside) stack.push(ui.militia[region]) for (let tribe = 0; tribe < TRIBE_COUNT[player_count]; ++tribe) { for (let id = first_barbarian[tribe]; id <= last_barbarian[tribe]; ++id) { let loc = get_barbarian_location(id) if (loc === army) stack.push(ui.barbarians[id]) } } for (let i = 0; i < 33; ++i) { let loc = get_legion_location(i) if (loc === army) stack.push(ui.legions[i]) } stack.push(e) if (castra) { show(ui.castra[pi][ai]) stack.push(ui.castra[pi][ai]) } else { hide(ui.castra[pi][ai]) } if (inside) layout_stack(pi * 6 + ai, stack, region, true) else layout_stack(pi * 6 + ai, stack, region, false) } else { avail_stack.push(e) } e.classList.toggle("unavailable", region === UNAVAILABLE) e.classList.toggle("selected", view.selected_general === pi * 6 + ai) } layout_available(avail_stack, 63, 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) } layout_available(avail_stack, 58, pi * 625 + 325, 27) } ui.dice[0].className = "dice black d" + view.dice[0] ui.dice[1].className = "dice white d" + view.dice[1] ui.dice[2].className = "dice black d" + view.dice[2] ui.dice[3].className = "dice white d" + view.dice[3] if (view.events) { for (let c of view.events) ui.played.appendChild(ui.cards[c]) } ui.played.replaceChildren() if (view.played) { for (let c of view.played) ui.played.appendChild(ui.cards[c]) } ui.hand.replaceChildren() if (view.hand) { for (let c of view.hand) ui.hand.appendChild(ui.cards[c]) } ui.draw.replaceChildren() if (view.draw) { for (let c of view.draw) ui.draw.appendChild(ui.cards[c]) } ui.discard.replaceChildren() if (view.discard) { for (let c of view.discard) ui.discard.appendChild(ui.cards[c]) } ui.market.replaceChildren() for (let c of view.market) { if (c > 0) ui.market.appendChild(ui.cards[c]) } for (let e of action_register) e.classList.toggle("action", is_action(e.my_action, e.my_id)) action_button("enter", "Enter Capital") action_button("leave", "Leave Capital") action_button("spend", "Spend") action_button("roll", "Roll") action_button("place_militia", "Place Militia") action_button("support", "Increase Support Level") action_button("hold_games", "Hold Games") action_button("build_improvement", "Build an Improvement") action_button("disperse_mob", "Disperse Mob") action_button("train_legions", "Train Legions") action_button("add_legion_to_army", "Add Legion to Army") action_button("move_army", "Move Army") action_button("initiate_battle", "Initiate Battle") action_button("amphitheater", "Amphitheater") action_button("basilica", "Basilica") action_button("limes", "Limes") action_button("recall", "Recall") action_button("recruit", "Recruit") action_button("place", "Place") action_button("create_army", "Create Army") action_button("end_actions", "End Actions") action_button("done", "Done") action_button("undo", "Undo") } on_init() scroll_with_middle_mouse("main")