summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor@ccxvii.net>2022-11-19 22:56:08 +0100
committerTor Andersson <tor@ccxvii.net>2023-02-18 13:02:37 +0100
commit1bc80c430198d095315cd0c7643d18d12538c62b (patch)
tree6523b86a38999f3281f21b57b12c70bf4f3519e3
parent3a83d94096a32e838f3331932644f4495593e6e8 (diff)
downloadnevsky-1bc80c430198d095315cd0c7643d18d12538c62b.tar.gz
Initial capability draw. Click on lord shields.
-rw-r--r--play.html15
-rw-r--r--play.js17
-rw-r--r--rules.js154
-rw-r--r--tools/gendata.js8
4 files changed, 174 insertions, 20 deletions
diff --git a/play.html b/play.html
index 2ab1736..7285fba 100644
--- a/play.html
+++ b/play.html
@@ -232,6 +232,21 @@ body.shift .capabilities {
margin-top: -38px;
}
+.mat .shield { position: absolute; }
+.mat.teutonic .shield {
+ top: 13px; left: 11px; width: 65px; height: 75px;
+ border-radius: 4px 4px 50% 50%;
+}
+.mat.russian .shield,
+.mat.yaroslav .shield {
+ top: 10px; left: 11px; width: 55px; height: 100px;
+ border-radius: 26px 26px 50% 50%;
+}
+
+.mat .shield.action {
+ box-shadow: 0 0 6px white, inset 0 0 6px white;
+}
+
.mat .forces { top: 96px; left: 66px; width: 240px; height: 96px; }
.mat .routed { top: 200px; left: 18px; width: 236px; height: 48px; }
.mat .assets { top: 255px; left: 24px; width: 230px; height: 96px; }
diff --git a/play.js b/play.js
index 0493bb2..a1c24ec 100644
--- a/play.js
+++ b/play.js
@@ -8,6 +8,11 @@ const round = Math.round
const floor = Math.floor
const ceil = Math.ceil
+const first_p1_card = 0
+const last_p1_card = 20
+const first_p2_card = 21
+const last_p2_card = 41
+
// unit types
const KNIGHTS = 0
const SERGEANTS = 1
@@ -270,6 +275,7 @@ const ui = {
lord_cylinder: [],
lord_service: [],
lord_mat: [],
+ lord_buttons: [],
vassal_service: [],
forces: [],
routed: [],
@@ -584,6 +590,7 @@ function update_lord(ix) {
ui.lord_service[ix].classList.add("hide")
ui.lord_mat[ix].classList.add("hide")
}
+ ui.lord_buttons[ix].classList.toggle("action", is_lord_action(ix))
ui.lord_cylinder[ix].classList.toggle("action", is_lord_action(ix))
ui.lord_service[ix].classList.toggle("action", is_service_action(ix))
@@ -781,7 +788,12 @@ function on_update() {
update_veche()
- if ((view.turn & 1) === 0) {
+ if (typeof view.what === "number" && view.what >= 0) {
+ if (view.what <= first_p1_card)
+ ui.command.className = `card teutonic aow_${view.what}`
+ else
+ ui.command.className = `card russian aow_${view.what}`
+ } else if ((view.turn & 1) === 0) {
if (player === "Russians")
ui.command.className = `card russian aow_back`
else
@@ -835,6 +847,8 @@ function on_update() {
action_button("capability", "Capability")
+ action_button("discard", "Discard")
+ action_button("deploy", "Deploy")
action_button("done", "Done")
action_button("unfed", "Unfed")
action_button("end_plan", "End plan")
@@ -869,6 +883,7 @@ function build_lord_mat(lord, ix, side, name) {
ui.assets[ix] = build_div(bg, "assets")
ui.ready_vassals[ix] = build_div(bg, "ready_vassals")
ui.mustered_vassals[ix] = build_div(bg, "mustered_vassals")
+ ui.lord_buttons[ix] = build_div(bg, "shield", ix, on_click_cylinder)
ui.lord_capabilities[ix] = build_div(mat, "capabilities")
ui.lord_mat[ix] = mat
}
diff --git a/rules.js b/rules.js
index 06d386a..8510087 100644
--- a/rules.js
+++ b/rules.js
@@ -75,6 +75,11 @@ const last_p1_locale = 23
const first_p2_locale = 24
const last_p2_locale = 52
+const first_p1_card = 0
+const last_p1_card = 20
+const first_p2_card = 21
+const last_p2_card = 41
+
const LORD_ANDREAS = find_lord("Andreas")
const LORD_HEINRICH = find_lord("Heinrich")
const LORD_HERMANN = find_lord("Hermann")
@@ -807,22 +812,100 @@ function end_setup_lords() {
game.lords.moved = 0
set_active_enemy()
if (game.active === P1)
- goto_levy_arts_of_war()
+ goto_levy_arts_of_war_first()
}
-// === LEVY: ARTS OF WAR ===
+// === LEVY: ARTS OF WAR (FIRST TURN) ===
+
+function draw_two_arts_of_war_cards() {
+ // TODO: no PASS cards in some scenarios in 2nd ed
+ let deck = []
+ if (game.active === P1) {
+ for (let c = first_p1_card; c <= last_p1_card; ++c)
+ if (!is_card_in_use(c))
+ deck.push(c)
+ } else {
+ for (let c = first_p2_card; c <= last_p2_card; ++c)
+ if (!is_card_in_use(c))
+ deck.push(c)
+ }
-function goto_levy_arts_of_war() {
+ let result = []
+ let i = random(deck.length)
+ result.push(deck[i])
+ array_remove(deck, i)
+
+ i = random(deck.length)
+ result.push(deck[i])
+ array_remove(deck, i)
+ return result
+}
+
+function goto_levy_arts_of_war_first() {
log_h1("Levy " + current_turn_name())
- game.state = 'levy_arts_of_war'
- end_levy_arts_of_war()
+ game.state = 'levy_arts_of_war_first'
+ game.what = draw_two_arts_of_war_cards()
}
-states.levy_arts_of_war = {
+function resume_levy_arts_of_war_first() {
+ if (game.what.length === 0)
+ end_levy_arts_of_war_first()
+}
+
+states.levy_arts_of_war_first = {
+ prompt() {
+ let c = game.what[0]
+ view.what = c
+ if (data.cards[c].this_lord) {
+ view.prompt = `Assign ${data.cards[c].capability} to a Lord.`
+ let discard = true
+ for (let lord of data.cards[c].lords) {
+ if (is_lord_on_map(lord)) {
+ gen_action_lord(lord)
+ discard = false
+ }
+ }
+ if (discard)
+ view.actions.discard = 1
+ } else if (data.cards[c].capability) {
+ view.prompt = `Deploy ${data.cards[c].capability}.`
+ view.actions.deploy = 1
+ } else {
+ view.prompt = `No Capability.`
+ view.actions.discard = 1
+ }
+ },
+ lord(lord) {
+ let c = game.what.shift()
+ log(`${lord_name[lord]} capability #${c}`)
+ add_lord_capability(lord, c)
+ resume_levy_arts_of_war_first()
+ },
+ deploy() {
+ let c = game.what.shift()
+ log(`Global capability #${c}`)
+ set_add(game.capabilities, c)
+ resume_levy_arts_of_war_first()
+ },
+ discard() {
+ let c = game.what.shift()
+ log(`Discarded #${c}`)
+ resume_levy_arts_of_war_first()
+ },
+}
+
+function end_levy_arts_of_war_first() {
+ game.what = -1
+ set_active_enemy()
+ if (game.active === P2)
+ goto_levy_arts_of_war_first()
+ else
+ goto_pay()
}
-function end_levy_arts_of_war() {
- goto_pay()
+// === LEVY: ARTS OF WAR ===
+
+states.levy_arts_of_war = {
}
// === LEVY: MUSTER ===
@@ -1058,6 +1141,30 @@ function lord_has_capability(lord, c) {
return false
}
+function can_add_lord_capability(lord) {
+ if (get_lord_capability(lord, 0) < 0)
+ return true
+ if (get_lord_capability(lord, 1) < 0)
+ return true
+ return false
+}
+
+function add_lord_capability(lord, c) {
+ if (get_lord_capability(lord, 0) < 0)
+ return set_lord_capability(lord, 0, c)
+ if (get_lord_capability(lord, 1) < 0)
+ return set_lord_capability(lord, 1, c)
+ throw new Error("no empty capability slots!")
+}
+
+function discard_lord_capability(lord, c) {
+ if (get_lord_capability(lord, 0) === c)
+ return set_lord_capability(lord, 0, -1)
+ if (get_lord_capability(lord, 1) === c)
+ return set_lord_capability(lord, 1, -1)
+ throw new Error("capability not found")
+}
+
states.muster_capability = {
prompt() {
view.prompt = `Select a new capability for ${lord_name[game.who]}.`
@@ -1079,11 +1186,9 @@ states.muster_capability = {
push_undo()
logi(`Capability #${c}`)
if (data.cards[c].this_lord) {
- if (get_lord_capability(game.who, 0) < 0)
- set_lord_capability(game.who, 0, c)
- else if (get_lord_capability(game.who, 1) < 0)
- set_lord_capability(game.who, 1, c)
- else {
+ if (can_add_lord_capability(game.who, c)) {
+ add_lord_capability(game.who, c)
+ } else {
game.what = c
game.state = 'muster_capability_discard'
return
@@ -1105,10 +1210,8 @@ states.muster_capability_discard = {
arts_of_war(c) {
push_undo()
logi(`Discarded #${c}`)
- if (c === get_lord_capability(game.who, 0))
- set_lord_capability(game.who, 0, game.what)
- else
- set_lord_capability(game.who, 1, game.what)
+ discard_lord_capability(game.who, c)
+ add_lord_capability(game.who, game.what)
game.what = -1
pop_state()
resume_levy_muster_lord()
@@ -1639,7 +1742,22 @@ function pack4_set(word, n, x) {
return (word & ~(15 << n)) | (x << n)
}
-// Sorted array treated as Set (for JSON)
+// remove item at index (faster than splice)
+function array_remove(array, index) {
+ let n = array.length
+ for (let i = index + 1; i < n; ++i)
+ array[i - 1] = array[i]
+ array.length = n - 1
+ return array
+}
+
+// insert item at index (faster than splice)
+function array_insert(array, index, item) {
+ for (let i = array.length; i > index; --i)
+ array[i] = array[i - 1]
+ array[index] = item
+ return array
+}
function set_has(set, item) {
let a = 0
diff --git a/tools/gendata.js b/tools/gendata.js
index 3b5ece1..61980d1 100644
--- a/tools/gendata.js
+++ b/tools/gendata.js
@@ -607,7 +607,7 @@ function arts_of_war_capability(name, capability, this_lord, lord_names) {
lord_names = lords.filter(l => l.side === side).map(l => l.name)
AOW[name].lords = lord_names.map(n => lords.findIndex(l => l.name === n)).sort(cmpnum)
}
- else {
+ else if (Array.isArray(lord_names)) {
AOW[name].lords = lord_names.map(n => lords.findIndex(l => l.name === n)).sort(cmpnum)
}
}
@@ -652,6 +652,9 @@ arts_of_war_capability("T15", "Warrior Monks", false, [ "Andreas", "Rudolf" ])
arts_of_war_capability("T16", "Ransom", false, "ALL")
arts_of_war_capability("T17", "Stonemasons", true, "any")
arts_of_war_capability("T18", "Cogs", true, [ "Heinrich", "Knud & Abel", "Andreas" ])
+arts_of_war_capability("T0", "No Capability", false, null)
+arts_of_war_capability("T0", "No Capability", false, null)
+arts_of_war_capability("T0", "No Capability", false, null)
arts_of_war_event("R1", "Bridge", "hold")
arts_of_war_event("R2", "Marsh", "hold")
@@ -693,6 +696,9 @@ arts_of_war_capability("R15", "Archbishopric", false, "any")
arts_of_war_capability("R16", "Lodya", true, "any")
arts_of_war_capability("R17", "Veliky Knyaz", true, "any")
arts_of_war_capability("R18", "Stone Kremlin", true, "any")
+arts_of_war_capability("R0", "No Capability", false, null)
+arts_of_war_capability("R0", "No Capability", false, null)
+arts_of_war_capability("R0", "No Capability", false, null)
let vassals = []
for (let lord of lords)