summaryrefslogtreecommitdiff
path: root/play.js
diff options
context:
space:
mode:
authorTor Andersson <tor@ccxvii.net>2023-11-22 01:55:38 +0100
committerTor Andersson <tor@ccxvii.net>2024-01-08 16:36:47 +0100
commitb2c68b84481e4393fd13d78184318bbe22ff427c (patch)
tree214a3baf9e01ea171d69331355b72ab360753eda /play.js
parent95b90a9b4c21d6fd0805177d5193a8a62fa217ad (diff)
downloadtable-battles-b2c68b84481e4393fd13d78184318bbe22ff427c.tar.gz
lotsa stuff
Diffstat (limited to 'play.js')
-rw-r--r--play.js288
1 files changed, 288 insertions, 0 deletions
diff --git a/play.js b/play.js
new file mode 100644
index 0000000..176a006
--- /dev/null
+++ b/play.js
@@ -0,0 +1,288 @@
+"use strict"
+
+const wing_name = [ "red", "pink", "blue", "dkblue" ]
+const reactions = [ "Screen", "Counterattack", "Absorb" ]
+
+let ui = {
+ main: document.querySelector("main"),
+ role_row: [ document.getElementById("role_First"), document.getElementById("role_Second") ],
+ role_name: [ document.getElementById("role1"), document.getElementById("role2") ],
+ name: [ document.getElementById("name1"), document.getElementById("name2") ],
+ front: [ document.getElementById("front1"), document.getElementById("front2") ],
+ morale: [ document.getElementById("morale1"), document.getElementById("morale2") ],
+ pool: [ document.getElementById("pool1"), document.getElementById("pool2") ],
+ reserve: [ document.getElementById("reserve1"), document.getElementById("reserve2") ],
+
+ cards: {},
+ slots: {},
+ slot_sticks: {},
+ slot_cubes: {},
+ slot_dice: {},
+
+ dice: [],
+ sticks: [],
+ cubes: [],
+}
+
+let action_register = []
+
+function register_action(e, action, id, fizzle=null) {
+ e.my_id = id
+ e.my_action = action
+ e.my_fizzle = fizzle
+ e.onclick = on_click_action
+ action_register.push(e)
+ return e
+}
+
+function on_click_action(evt) {
+ if (evt.button === 0) {
+ if (send_action(evt.target.my_action, evt.target.my_id))
+ evt.stopPropagation()
+ if (evt.target.my_fizzle)
+ if (send_action(evt.target.my_fizzle, evt.target.my_id))
+ evt.stopPropagation()
+ }
+}
+
+function is_action(action, arg) {
+ if (arg === undefined)
+ return !!(view.actions && view.actions[action] === 1)
+ return !!(view.actions && view.actions[action] && view.actions[action].includes(arg))
+}
+
+function create_div(className, text) {
+ let e = document.createElement("div")
+ e.className = className
+ if (text)
+ e.innerHTML = text
+ return e
+}
+
+function append_div(parent, className, text) {
+ let e = create_div(className, text)
+ parent.appendChild(e)
+ return e
+}
+
+function create_formation_slot(id, top) {
+ let card = data.cards[id]
+
+ let e = create_div("slot " + wing_name[card.wing])
+
+ if (top) {
+ ui.slot_dice[id] = append_div(e, "slot_dice")
+ e.appendChild(ui.cards[id])
+ }
+
+ if (card.special)
+ ui.slot_cubes[id] = append_div(e, "slot_cubes")
+ else
+ ui.slot_sticks[id] = append_div(e, "slot_sticks")
+
+ if (!top) {
+ e.appendChild(ui.cards[id])
+ ui.slot_dice[id] = append_div(e, "slot_dice")
+ }
+
+ return e
+}
+
+function create_formation_card(id) {
+ let card = data.cards[id]
+ let e = create_div("card formation " + wing_name[card.wing])
+ let e_a1 = null
+ let e_a2 = null
+
+ register_action(e, "card", id)
+
+ append_div(e, "name " + wing_name[card.wing], card.name)
+
+ if (card.special === 1)
+ append_div(e, "strength", "I")
+ else if (card.special === 2)
+ append_div(e, "strength", "II")
+ else if (card.special === 3)
+ append_div(e, "strength", "III")
+ else
+ append_div(e, "strength", card.strength)
+
+ if (card.dice) {
+ if (card.star)
+ append_div(e, "dice_area", card.dice + '<div class="star">&#x2605;</div>')
+ else
+ append_div(e, "dice_area", card.dice)
+ }
+
+ function create_action(a, ix) {
+ let ee = append_div(e, "action_row")
+ let et
+ if (reactions.includes(a.type))
+ et = append_div(ee, "action_type reaction", a.type)
+ else
+ et = append_div(ee, "action_type", a.type)
+ register_action(et, "a" + ix, id, "f" + ix)
+ append_div(ee, "action_requirement", a.requirement)
+ if (Array.isArray(a.target))
+ append_div(ee, "action_target", a.target.map(t=>data.cards[t].name).join(", "))
+ else
+ append_div(ee, "action_target", a.target)
+ if (a.effect)
+ append_div(ee, "action_effect", a.effect)
+ return et
+ }
+
+ if (card.actions.length >= 1)
+ e_a1 = create_action(card.actions[0], 1)
+ if (card.actions.length >= 2)
+ e_a2 = create_action(card.actions[1], 2)
+
+ if (card.rule_text)
+ append_div(e, "rule_text", card.rule_text)
+ if (card.lore_text)
+ append_div(e, "lore_text", card.lore_text)
+
+ if (card.retire) {
+ let ee = append_div(e, "reserve", "RETIRE")
+ register_action(ee, "retire", id)
+ } else if (card.pursuit) {
+ append_div(e, "reserve", "PURSUIT")
+ } else if (card.reserve) {
+ if (card.reserve.length === 0)
+ append_div(e, "reserve", "IN RESERVE (Commanded)")
+ else
+ append_div(e, "reserve", "IN RESERVE (" + card.reserve.map(c => data.cards[c].name).join(" or ") + ")")
+ }
+
+ append_div(e, "number", card.number)
+
+ return e
+}
+
+function fill_card_row(top, parent, list) {
+ parent.replaceChildren()
+ for (let id of list) {
+ let i, n
+
+ if (!ui.cards[id])
+ ui.cards[id] = create_formation_card(id)
+ if (!ui.slots[id])
+ ui.slots[id] = create_formation_slot(id, top)
+ parent.append(ui.slots[id])
+
+ ui.cards[id].classList.toggle("selected", view.selected === id)
+
+ n = map_get(view.cubes, id, 0)
+ for (let i = 0; i < n; ++i)
+ add_cube(ui.slot_cubes[id])
+
+ n = map_get(view.sticks, id, 0)
+ for (let i = 0; i < n; ++i)
+ add_stick(ui.slot_sticks[id])
+ }
+}
+
+function add_cube(parent) {
+ for (let i = 0; i < 10; ++i) {
+ if (ui.cubes[i].parentElement === null) {
+ parent.appendChild(ui.cubes[i])
+ return
+ }
+ }
+ throw Error("OUT OF CUBES ERROR")
+}
+
+function add_stick(parent) {
+ for (let i = 0; i < 80; ++i) {
+ if (ui.sticks[i].parentElement === null) {
+ parent.appendChild(ui.sticks[i])
+ return
+ }
+ }
+ throw Error("OUT OF CUBES ERROR")
+}
+
+function on_update() {
+ let p1 = 0, p2 = 1
+ if (player === "First")
+ p1 = 1, p2 = 0
+
+ ui.main.dataset.scenario = data.scenarios[view.scenario].number
+ ui.name[p1].textContent = data.scenarios[view.scenario].players[0].name
+ ui.name[p2].textContent = data.scenarios[view.scenario].players[1].name
+
+ ui.role_name[p1].textContent = data.scenarios[view.scenario].players[0].name
+ ui.role_name[p2].textContent = data.scenarios[view.scenario].players[1].name
+
+ for (let e of ui.cubes)
+ e.remove()
+ for (let e of ui.sticks)
+ e.remove()
+
+ fill_card_row(p2, ui.reserve[p1], view.reserve[0])
+ fill_card_row(p2, ui.front[p1], view.front[0])
+ fill_card_row(p1, ui.reserve[p2], view.reserve[1])
+ fill_card_row(p1, ui.front[p2], view.front[1])
+
+ for (let i = 0; i < view.morale[0]; ++i)
+ add_cube(ui.morale[p1])
+
+ for (let i = 0; i < view.morale[1]; ++i)
+ add_cube(ui.morale[p2])
+
+ function update_die(d, p) {
+ let v = view.dice[d * 2 + 0]
+ let c = view.dice[d * 2 + 1]
+ ui.dice[d].className = "die d" + v
+ if (c < 0)
+ ui.pool[p].appendChild(ui.dice[d])
+ else
+ ui.slot_dice[c].appendChild(ui.dice[d])
+ }
+
+ for (let i = 0; i < 6; ++i) {
+ update_die(i, p1)
+ update_die(i+6, p2)
+ }
+
+ for (let e of action_register) {
+ if (e.my_fizzle) {
+ e.classList.toggle("action", is_action(e.my_action, e.my_id) || is_action(e.my_fizzle, e.my_id))
+ e.classList.toggle("fizzle", is_action(e.my_fizzle, e.my_id))
+ } else {
+ e.classList.toggle("action", is_action(e.my_action, e.my_id))
+ }
+ }
+
+ action_button("bombard", "Bombard")
+ action_button("roll", "Roll")
+ action_button("pass", "Pass")
+ action_button("done", "Done")
+ action_button("end_turn", "End turn")
+ action_button("undo", "Undo")
+}
+
+for (let i = 0; i < 10; ++i)
+ ui.cubes[i] = create_div("cube")
+
+for (let i = 0; i < 80; ++i)
+ ui.sticks[i] = create_div("stick")
+
+for (let i = 0; i < 12; ++i)
+ ui.dice[i] = register_action(create_div("die d0"), "die", i)
+
+function map_get(map, key, missing) {
+ let a = 0
+ let b = (map.length >> 1) - 1
+ while (a <= b) {
+ let m = (a + b) >> 1
+ let x = map[m<<1]
+ if (key < x)
+ b = m - 1
+ else if (key > x)
+ a = m + 1
+ else
+ return map[(m<<1)+1]
+ }
+ return missing
+}