"use strict"
/*
global view, data, roles, send_action, action_button, confirm_action_button
*/
// TODO: show "reshuffle" flag next to card deck display
function toggle_counters() {
// Cycle between showing everything, only markers, and nothing.
if (ui.map.classList.contains("hide_markers")) {
ui.map.classList.remove("hide_markers")
ui.map.classList.remove("hide_pieces")
} else if (ui.map.classList.contains("hide_pieces")) {
ui.map.classList.add("hide_markers")
} else {
ui.map.classList.add("hide_pieces")
}
}
/* COMMON */
function lerp(a, b, t) {
return a + t * (b - a)
}
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
}
/* DATA */
const PC_NONE = 0
const PC_BRITISH = 1
const PC_AMERICAN = 2
const CU_BRITISH_SHIFT = 2
const CU_AMERICAN_SHIFT = 8
const CU_FRENCH_SHIFT = 14
const CU_BRITISH_MASK = 63 << CU_BRITISH_SHIFT
const CU_AMERICAN_MASK = 63 << CU_AMERICAN_SHIFT
const CU_FRENCH_MASK = 7 << CU_FRENCH_SHIFT
const QUEBEC = data.space_index["Quebec"]
const MONTREAL = data.space_index["Montreal"]
const CARDS = data.cards
const P_BRITAIN = "Britain"
const P_AMERICA = "America"
const F_RESHUFFLE = 1
const F_REGULARS = 2
const F_EUROPEAN_WAR = 4
const F_MUTINIES = 16
const general_count = data.generals.length
const CONTINENTAL_CONGRESS_DISPERSED = data.space_index["Continental Congress Dispersed"]
const FRENCH_REINFORCEMENTS = data.space_index["French Reinforcements"]
const NOWHERE = data.spaces.length
/* ACCESSORS */
function get_space_pc(space) {
return view.cupc[space] & 3
}
function has_british_pc(space) {
return get_space_pc(space) === PC_BRITISH
}
function has_american_pc(space) {
return get_space_pc(space) === PC_AMERICAN
}
function count_british_cu(s) {
return (view.cupc[s] & CU_BRITISH_MASK) >>> CU_BRITISH_SHIFT
}
function count_american_cu(s) {
return (view.cupc[s] & CU_AMERICAN_MASK) >>> CU_AMERICAN_SHIFT
}
function count_french_cu(s) {
return (view.cupc[s] & CU_FRENCH_MASK) >>> CU_FRENCH_SHIFT
}
/* ANIMATION */
var animation_list = []
function remember_position(e) {
if (e.parentElement) {
animation_list.push(e)
let prect = e.parentElement.getBoundingClientRect()
let rect = e.getBoundingClientRect()
e.my_visible = 1
e.my_parent = e.parentElement
e.my_px = prect.x
e.my_py = prect.y
e.my_x = rect.x
e.my_y = rect.y
} else {
e.my_visible = 0
e.my_parent = null
e.my_x = 0
e.my_y = 0
e.my_z = 0
}
}
function animate_position(e) {
if (e.parentElement && e.my_visible) {
let prect = e.parentElement.getBoundingClientRect()
let rect = e.getBoundingClientRect()
let dx, dy
if (e.parentElement === e.my_parent) {
dx = (e.my_x - e.my_px) - (rect.x - prect.x)
dy = (e.my_y - e.my_py) - (rect.y - prect.y)
} else {
dx = e.my_x - rect.x
dy = e.my_y - rect.y
}
if (dx !== 0 || dy !== 0) {
e.animate(
[
{ transform: `translate(${dx}px, ${dy}px)`, },
{ transform: "translate(0, 0)", },
],
{ duration: 333, easing: "ease" }
)
}
}
}
function animate_positions() {
for (let e of animation_list)
animate_position(e)
animation_list.length = 0
}
/* BUILD UI */
let ui = {
favicon: document.getElementById("favicon"),
header: document.querySelector("header"),
status: document.getElementById("status"),
tooltip: document.getElementById("tooltip"),
war_ends: document.getElementById("war_ends"),
played_british_reinforcements: document.getElementById("played_british_reinforcements"),
played_american_reinforcements_1: document.getElementById("played_american_reinforcements_1"),
played_american_reinforcements_2: document.getElementById("played_american_reinforcements_2"),
last_played: document.getElementById("last_played"),
reshuffle: document.getElementById("reshuffle"),
hand: document.getElementById("hand"),
map: document.getElementById("map"),
spaces_element: document.getElementById("spaces"),
markers_element: document.getElementById("markers"),
pieces_element: document.getElementById("pieces"),
cards: [],
spaces: [],
seas: [],
a_pc: [],
b_pc: [],
a_colony: [],
b_colony: [],
a_cu: [],
b_cu: [],
f_cu: [],
a_mcu: [],
b_mcu: [],
f_mcu: [],
layout_static: [],
layout_move: null,
layout_react: null,
generals: [],
}
let action_register = []
function register_action(target, action, id) {
target.my_action = action
target.my_id = id
target.onmousedown = on_click_action
action_register.push(target)
}
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_click_action(evt) {
if (evt.button === 0)
send_action(evt.target.my_action, evt.target.my_id)
}
const SPACE_W = { fortified_port: 68, winter_quarters: 78, regular: 80, box: 100 }
function build_marker(cn, x, y, w, h) {
let e = document.createElement("div")
e.className = cn
e.style.top = Math.round(y - h/2) + "px"
e.style.left = Math.round(x - w/2) + "px"
return e
}
function build_piece(cn, w, h) {
let e = document.createElement("div")
e.className = cn
e.my_dx = w >> 1
e.my_dy = h >> 1
return e
}
function on_init() {
ui.war_ends.addEventListener("mouseenter", on_focus_war_ends)
ui.war_ends.addEventListener("mouseleave", on_blur_war_ends)
ui.last_played.addEventListener("mouseenter", on_focus_last_played)
ui.last_played.addEventListener("mouseleave", on_blur_last_played)
for (let c = 0; c <= 110; ++c) {
let e = ui.cards[c] = document.createElement("div")
e.className = "card card_" + c
if (c > 0) {
e.my_id = c
register_action(e, "card", c)
}
}
for (let s = 0; s < data.spaces.length; ++s) {
let info = data.spaces[s]
let e = ui.spaces[s] = document.createElement("div")
let x = info.x
let y = info.y
let w = SPACE_W[info.type]
let h = SPACE_W[info.type]
if (info.type === "box") {
x = data.layout.box[info.name][0]
y = data.layout.box[info.name][1]
w = data.layout.box[info.name][2]
h = data.layout.box[info.name][3]
}
e.className = "space " + info.type + " " + data.colony_name[info.colony]
e.style.left = x - w/2 + "px"
e.style.top = y - h/2 + "px"
e.style.width = w - 10 + "px"
e.style.height = h - 10 + "px"
register_action(e, "space", s)
register_tooltip(e, info.name)
ui.spaces_element.appendChild(e)
ui.b_pc[s] = build_marker("marker pc british", x, y, 58, 66)
ui.a_pc[s] = build_marker("marker pc american", x, y, 58, 66)
ui.b_cu[s] = build_piece("marker cu british", 60+2, 60+2)
ui.a_cu[s] = build_piece("marker cu american", 60+2, 60+2)
ui.f_cu[s] = build_piece("marker cu french", 60+2, 60+2)
}
for (let g = 0; g < general_count; ++g) {
ui.b_mcu[g] = build_piece("marker cu british", 60+2, 60+2)
ui.a_mcu[g] = build_piece("marker cu american", 60+2, 60+2)
ui.f_mcu[g] = build_piece("marker cu french", 60+2, 60+2)
}
for (let s = 0; s < 7; ++s) {
let e = ui.seas[s] = document.createElement("div")
let [ x, y, w, h ] = data.layout.sea[s]
e.className = "space sea"
e.style.left = x + "px"
e.style.top = y + "px"
e.style.width = w - 14 + "px"
e.style.height = h - 14 + "px"
register_action(e, "sea", s)
register_tooltip(e, data.seas[s].map(x => data.spaces[x].name).join(", "))
ui.spaces_element.appendChild(e)
}
for (let g = 0; g < general_count; ++g) {
let e = ui.generals[g] = build_piece("marker general small " + data.generals[g].name, 45+2, 45+2)
register_action(e, "general", g)
let info = data.generals[g]
let tip = `${info.name} ${info.strategy}-${info.battle}-${info.agility}`
if (info.bonus)
tip += "+2R"
register_tooltip(e, tip)
}
for (let i = 0; i < 14; ++i) {
let [ x, y ] = data.layout.colony[i]
ui.a_colony[i] = build_marker("marker small control american", x, y, 45+2, 45+2)
ui.b_colony[i] = build_marker("marker small control british", x, y, 45+2, 45+2)
register_tooltip(ui.a_colony[i], data.colony_name[i])
register_tooltip(ui.b_colony[i], data.colony_name[i])
}
ui.congress = build_piece("marker large congress", 55+2, 55+2)
ui.french_navy = build_piece("marker large french_navy", 55+2, 55+2)
ui.turn_marker = build_piece("marker large turn", 55+2, 55+2)
ui.french_alliance = build_piece("marker large french_alliance", 55+2, 55+2)
ui.combat = document.createElement("div")
ui.combat.id = "combat"
}
on_init()
/* UPDATE UI */
function show_move_marker(marker, s1, s2) {
let x1 = data.spaces[s1].x
let y1 = data.spaces[s1].y
let x2 = data.spaces[s2].x
let y2 = data.spaces[s2].y
let dx = x2 - x1
let dy = y2 - y1
let n = Math.hypot(dx, dy)
let a = Math.atan2(dy, dx)
let x, y
if (n < 150) {
x = x2 - (dx/n) * 36
y = y2 - (dy/n) * 36
} else {
x = lerp(x1, x2, 3/4)
y = lerp(y1, y2, 3/4)
}
marker.style.left = (x|0) - 24 + "px"
marker.style.top = (y|0) - 24 + "px"
marker.style.transform = "rotate(" + (a + Math.PI/2) + "rad)"
ui.markers_element.appendChild(marker)
}
function toggle_marker(e, cond) {
if (cond)
show_marker(e)
}
function show_marker(e) {
ui.markers_element.appendChild(e)
}
function show_marker_at(e, x, y) {
show_marker(e)
e.style.left = x - e.my_dx + "px"
e.style.top = y - e.my_dy + "px"
}
function show_marker_at_xy(e, xy) {
show_marker_at(e, xy[0], xy[1])
}
function show_piece(e) {
ui.pieces_element.appendChild(e)
}
function show_piece_at(e, x, y) {
show_piece(e)
e.style.left = x - e.my_dx + "px"
e.style.top = y - e.my_dy + "px"
}
function show_piece_at_xy(e, xy) {
show_piece_at(e, xy[0], xy[1])
}
function show_piece_with_number_at(e, n, x, y) {
if (n > 0) {
show_piece(e)
e.textContent = n
e.style.left = x - e.my_dx + "px"
e.style.top = y - e.my_dy + "px"
}
}
function player_info(player, nc, nq) {
let info = ""
if (player == P_AMERICA) {
if ((view.flags & F_MUTINIES) || view.congress === CONTINENTAL_CONGRESS_DISPERSED)
info += "\u{1f6ab} "
}
if (nq > 0)
info += nq + "\u{231b} "
info += nc + "\u{1f3b4}"
return info
}
function general_offset(g) {
let n = 0
for (let i = 0; i < g; ++i) {
if (view.move && view.move.from !== view.move.to && view.move.who === i)
continue
if (view.react && view.react.who === i)
continue
if (view.loca[i] === view.loca[g])
++n
}
return n
}
function general_total(g) {
let n = 0
for (let i = 0; i < general_count; ++i) {
if (view.move && view.move.who === i)
continue
if (view.react && view.react.who === i)
continue
if (view.loca[i] === view.loca[g])
++n
}
return n
}
function get_army_xy_lerp(s1, s2) {
if (s1 === s2)
return get_army_xy(s2)
//return get_army_xy(s2)
let x, y
if (s1 >= 66) {
x = data.spaces[s1].x - 15
y = data.spaces[s1].y - 40
} else {
let x1 = data.spaces[s1].x
let y1 = data.spaces[s1].y
let x2 = data.spaces[s2].x
let y2 = data.spaces[s2].y
let dx = x2 - x1
let dy = y2 - y1
let n = Math.hypot(dx, dy)
x = lerp(x1, x2, 1/2)
y = lerp(y1, y2, 1/2)
if (n < 150) {
if (Math.abs(dx) * 0.75 > Math.abs(dy)) {
if (dx > 0)
x -= 10
else
x += 10
y -= 35
}
}
}
return [ (x|0) , (y|0) ]
}
function get_army_xy(s) {
let x, y
if (s >= 66) {
x = data.spaces[s].x
y = data.spaces[s].y - 120
} else {
x = data.spaces[s].x
y = data.spaces[s].y - 40
}
return [ x, y ]
}
function get_static_xy(s) {
let x, y
if (s >= 66) {
x = data.spaces[s].x
y = data.spaces[s].y + 20
} else {
x = data.spaces[s].x - 20
y = data.spaces[s].y + 10
}
return [ x, y ]
}
function get_static_acu(s) {
let cu = count_american_cu(s)
if (view.move && view.move.to === s)
cu -= view.move.carry_american
if (view.react && view.react.from === s)
cu -= view.react.carry_american
return cu
}
function get_static_fcu(s) {
let cu = count_french_cu(s)
if (view.move && view.move.to === s)
cu -= view.move.carry_french
if (view.react && view.react.from === s)
cu -= view.react.carry_french
return cu
}
function get_static_bcu(s) {
let cu = count_british_cu(s)
if (view.move && view.move.to === s)
cu -= view.move.carry_british
if (view.react && view.react.from === s)
cu -= view.react.carry_british
return cu
}
function get_colony_control(c) {
let control = 0
if (c === 0) {
if (get_space_pc(QUEBEC) === PC_BRITISH && get_space_pc(MONTREAL) === PC_BRITISH)
return PC_BRITISH
if (get_space_pc(QUEBEC) === PC_AMERICAN && get_space_pc(MONTREAL) === PC_AMERICAN)
return PC_AMERICAN
return PC_NONE
}
for (let space of data.colonies[c]) {
let pc = get_space_pc(space)
if (pc === PC_BRITISH)
--control
else if (pc === PC_AMERICAN)
++control
}
if (control < 0)
return PC_BRITISH
if (control > 0)
return PC_AMERICAN
return PC_NONE
}
function layout_all_cu(an, fn, bn, ae, fe, be, pos) {
let [ x, y ] = pos
show_piece_with_number_at(ae, an, x, y)
if (an > 0)
x += 30
show_piece_with_number_at(fe, fn, x, y)
if (fn > 0)
x += 30
show_piece_with_number_at(be, bn, x, y)
if (bn > 0)
x += 30
// if (an > 0 || fn > 0 || bn > 0) x -= 10
return [ x, y ]
}
function on_update() {
remember_position(ui.turn_marker)
remember_position(ui.french_alliance)
remember_position(ui.french_navy)
remember_position(ui.congress)
for (let g = 0; g < general_count; ++g) {
remember_position(ui.generals[g])
remember_position(ui.b_mcu[g])
remember_position(ui.a_mcu[g])
remember_position(ui.f_mcu[g])
}
roles.America.stat.textContent = player_info(P_AMERICA, view.a_cards, view.a_queue)
roles.Britain.stat.textContent = player_info(P_BRITAIN, view.b_cards, view.b_queue)
ui.last_played.className = "card shrink card_" + view.last_played
ui.markers_element.replaceChildren()
ui.pieces_element.replaceChildren()
for (let s = 0; s < data.spaces.length; ++s) {
toggle_marker(ui.b_pc[s], has_british_pc(s))
toggle_marker(ui.a_pc[s], has_american_pc(s))
}
if (view.congress === CONTINENTAL_CONGRESS_DISPERSED)
show_piece_at(ui.congress, data.spaces[view.congress].x, data.spaces[view.congress].y)
else
show_piece_at(ui.congress, data.spaces[view.congress].x+20, data.spaces[view.congress].y-10)
if (view.french_navy < 0)
show_piece_at(ui.french_navy, data.spaces[FRENCH_REINFORCEMENTS].x-65, data.spaces[FRENCH_REINFORCEMENTS].y)
else if (view.french_navy === 1784)
show_piece_at(ui.french_navy, data.layout.turn[1783][0] + 20, data.layout.turn[1783][1] - 20)
else if (view.french_navy > 1700)
show_piece_at_xy(ui.french_navy, data.layout.turn[view.french_navy])
else
show_piece_at(ui.french_navy, data.layout.sea[view.french_navy][0]-15, data.layout.sea[view.french_navy][1]+42)
if (view.move && view.move.from !== view.move.to)
show_move_marker(ui.combat, view.move.from, view.move.to)
for (let s = 0; s < data.spaces.length; ++s) {
let found = -1
for (let g = 0; g < general_count; ++g) {
if (view.move && view.move.who === g)
continue
if (view.react && view.react.who === g)
continue
if (view.loca[g] === s) {
found = g
break
}
}
if (found >= 0) {
ui.layout_static[s] = layout_all_cu(
get_static_acu(s),
get_static_fcu(s),
get_static_bcu(s),
ui.a_mcu[found],
ui.f_mcu[found],
ui.b_mcu[found],
get_static_xy(s)
)
} else {
ui.layout_static[s] = layout_all_cu(
get_static_acu(s),
get_static_fcu(s),
get_static_bcu(s),
ui.a_cu[s],
ui.f_cu[s],
ui.b_cu[s],
get_static_xy(s)
)
}
}
if (view.move) {
let xy = null
if (view.move.from === view.move.to &&
view.move.carry_american === count_american_cu(view.move.to) &&
view.move.carry_french === count_french_cu(view.move.to) &&
view.move.carry_british === count_british_cu(view.move.to)
)
xy = get_static_xy(view.move.to)
else
xy = get_army_xy_lerp(view.move.from, view.move.to)
if (view.move.who >= 0) {
ui.layout_move = layout_all_cu(
view.move.carry_american | 0,
view.move.carry_french | 0,
view.move.carry_british | 0,
ui.a_mcu[view.move.who],
ui.f_mcu[view.move.who],
ui.b_mcu[view.move.who],
xy
)
} else {
ui.layout_move = layout_all_cu(
view.move.carry_american | 0,
view.move.carry_french | 0,
view.move.carry_british | 0,
ui.a_cu[view.move.to],
ui.f_cu[view.move.to],
ui.b_cu[view.move.to],
xy
)
}
}
if (view.react) {
ui.layout_react = layout_all_cu(
view.react.carry_american | 0,
view.react.carry_french | 0,
view.react.carry_british | 0,
ui.a_mcu[view.react.who],
ui.f_mcu[view.react.who],
ui.b_mcu[view.react.who],
get_army_xy_lerp(view.react.from, view.react.to)
)
}
for (let g = 0; g < general_count; ++g) {
let s = view.loca[g]
if (s === NOWHERE)
continue
let [ x, y ] = (s < 66) ? ui.layout_static[s] : get_static_xy(s)
if (s === 68)
y -= 20
else if (s >= 66)
y -= 60
if (view.move && view.move.who === g)
[ x, y ] = ui.layout_move
if (view.react && view.react.who === g)
[ x, y ] = ui.layout_react
ui.generals[g].classList.toggle("selected", view.selected_general === g)
if (view.move && view.move.who === g) {
// already laid out
} else if (view.react && view.react.who === g) {
// already laid out
} else {
if (s < 66) {
let offset = general_offset(g)
x += offset * (45 + 9)
} else {
let wrap = (s === 66 ? 3 : 4)
let total = general_total(g)
let offset = general_offset(g)
let off_x = offset % wrap
let off_y = offset / wrap | 0
let ctr_x = total > wrap ? wrap : total
off_x -= (ctr_x - 1) / 2
x += off_x * (45 + 9)
y += off_y * (45 + 9)
y -= 15
}
}
show_piece_at(ui.generals[g], x, y)
}
for (let i = 0; i < 14; ++i) {
let control = get_colony_control(i)
toggle_marker(ui.b_colony[i], control === PC_BRITISH)
toggle_marker(ui.a_colony[i], control === PC_AMERICAN)
}
ui.reshuffle.classList.toggle("hide", !(view.flags & F_RESHUFFLE))
ui.turn_marker.classList.toggle("no_regulars", !(view.flags & F_REGULARS))
ui.french_alliance.classList.toggle("european_war", !!(view.flags & F_EUROPEAN_WAR))
show_marker_at_xy(ui.turn_marker, data.layout.turn[view.year])
show_marker_at_xy(ui.french_alliance, data.layout.french_alliance_track[view.french_alliance])
ui.hand.replaceChildren()
if (view.hand) {
for (let c of view.hand) {
ui.cards[c].classList.toggle("selected", view.selected_card === c)
ui.hand.appendChild(ui.cards[c])
}
}
if (view.war_ends)
ui.war_ends.className = "year_" + CARDS[view.war_ends].year
else
ui.war_ends.className = ""
if (view.reinforcements[0] > 0)
ui.played_british_reinforcements.className = "reinforcements ops_" + CARDS[view.reinforcements[0]].count
else
ui.played_british_reinforcements.className = ""
if (view.reinforcements[1] > 0)
ui.played_american_reinforcements_1.className = "reinforcements ops_" + CARDS[view.reinforcements[1]].count
else
ui.played_american_reinforcements_1.className = ""
if (view.reinforcements[2] > 0)
ui.played_american_reinforcements_2.className = "reinforcements ops_" + CARDS[view.reinforcements[2]].count
else
ui.played_american_reinforcements_2.className = ""
for (let e of action_register)
e.classList.toggle("action", is_action(e.my_action, e.my_id))
animate_positions()
action_button("exchange", "Exchange")
action_button("queue", "Queue")
action_button("reinforce", "Reinforce")
action_button("activate", "Activate")
action_button("pc_action", "PC Action")
action_button("event", "Event")
action_button("campaign", "Campaign")
action_button("landing_party", "Landing Party")
action_button("no_general", "No General")
action_button("pickup_french_cu", "Take French CU")
action_button("pickup_british_cu", "Take CU")
action_button("pickup_american_cu", "Take CU")
action_button("drop_french_cu", "Drop French CU")
action_button("drop_british_cu", "Drop CU")
action_button("drop_american_cu", "Drop CU")
action_button("britain_first", "Britain")
action_button("america_first", "America")
action_button("surrender", "Surrender")
action_button("stop", "Stop")
action_button("roll", "Roll")
action_button("next", "Next")
action_button("done", "Done")
action_button("pass", "Pass")
confirm_action_button("confirm_pass", "Pass", "Are you sure you want to PASS on this action?")
action_button("undo", "Undo")
}
/* TOOLTIPS */
function register_tooltip(elt, focus, blur) {
if (typeof focus === "function")
elt.onmouseenter = focus
else
elt.onmouseenter = () => on_focus(focus)
if (typeof blur === "function")
elt.onmouseleave = blur
else
elt.onmouseleave = on_blur
}
function on_focus(text) {
ui.status.textContent = text
}
function on_blur() {
ui.status.textContent = ""
}
function on_click_space_tip(s) {
ui.spaces[s].scrollIntoView({ block: "center", inline: "center", behavior: "smooth" })
}
function on_focus_space_tip(s) {
ui.spaces[s].classList.add("tip")
}
function on_blur_space_tip(s) {
ui.spaces[s].classList.remove("tip")
}
function on_click_general_tip(s) {
ui.generals[s].scrollIntoView({ block: "center", inline: "center", behavior: "smooth" })
}
function on_focus_general_tip(s) {
ui.generals[s].classList.add("tip")
}
function on_blur_general_tip(s) {
ui.generals[s].classList.remove("tip")
}
function on_focus_card_tip(c) {
ui.tooltip.className = "card card_" + c
}
function on_blur_card_tip() {
ui.tooltip.classList = "hide"
}
function on_focus_last_played() {
if (view.last_played)
ui.tooltip.className = "card card_" + view.last_played
}
function on_blur_last_played() {
ui.tooltip.classList = "hide"
}
function on_focus_war_ends() {
if (view.war_ends)
ui.tooltip.className = "card card_" + view.war_ends
}
function on_blur_war_ends() {
ui.tooltip.classList = "hide"
}
/* LOG */
function sub_space(_match, p1) {
let x = p1 | 0
let n = data.spaces[x].name
if (n === "Wilmington DE")
n = "Wilmington"
n = n.replaceAll(" ", "\xa0")
let co = data.spaces[x].colony
if (co)
n += "\xa0(" + data.colony_name[data.spaces[x].colony] + ")"
return `${n}`
}
function sub_general(_match, p1) {
let x = p1 | 0
let n = data.generals[x].name
return `${n}`
}
function sub_minus(_match, p1) {
return "\u2212" + p1
}
function sub_card(_match, p1) {
let x = p1 | 0
let n = data.cards[x].title
return `${n}`
}
const ICONS = {
D1: '',
D2: '',
D3: '',
D4: '',
D5: '',
D6: '',
A1: '1',
A2: '2',
A3: '3',
A4: '4',
A5: '5',
A6: '6',
AB1: '1',
AB2: '2',
AB3: '3',
AB4: '4',
AB5: '5',
AB6: '6',
BB1: '1',
BB2: '2',
BB3: '3',
BB4: '4',
BB5: '5',
BB6: '6',
FB1: '1',
FB2: '2',
FB3: '3',
FB4: '4',
FB5: '5',
FB6: '6',
}
function sub_icon(match) {
return ICONS[match] || match
}
function on_log(text) {
let p = document.createElement("div")
if (text.startsWith(">>")) {
p.className = "ii"
text = text.substring(2)
} else if (text.startsWith(">")) {
p.className = "i"
text = text.substring(1)
} else if (text.startsWith("=t")) {
p.className = "h turn"
text = text.substring(2)
} else if (text.startsWith("=a")) {
p.className = "h america"
text = text.substring(3)
} else if (text.startsWith("=b")) {
p.className = "h britain"
text = text.substring(3)
} else if (text.startsWith("=!")) {
p.className = "h"
text = text.substring(3)
}
if (
text.startsWith("Played ") ||
text.startsWith("Discarded ") ||
text.startsWith("Exchanged ") ||
text.startsWith("Retreated ") ||
text.startsWith("Surrendered ") ||
text === "Removed card."
)
p.className = "n"
if (text.startsWith("Moved G") || text.startsWith("Landing Party"))
p.className = "m"
text = text.replace(/&/g, "&")
text = text.replace(//g, ">")
text = text.replace(/-(\d)/g, sub_minus)
text = text.replace(/\b[D][1-6]\b/g, sub_icon)
text = text.replace(/\b[A][1-6]\b/g, sub_icon)
text = text.replace(/\bAB[1-6]\b/g, sub_icon)
text = text.replace(/\bBB[1-6]\b/g, sub_icon)
text = text.replace(/\bFB[1-6]\b/g, sub_icon)
text = text.replace(/C(\d+)/g, sub_card)
text = text.replace(/S(\d+)/g, sub_space)
text = text.replace(/G(\d+)/g, sub_general)
p.innerHTML = text
return p
}