diff options
author | Tor Andersson <tor@ccxvii.net> | 2022-11-19 22:56:08 +0100 |
---|---|---|
committer | Tor Andersson <tor@ccxvii.net> | 2023-02-18 13:02:37 +0100 |
commit | 1bc80c430198d095315cd0c7643d18d12538c62b (patch) | |
tree | 6523b86a38999f3281f21b57b12c70bf4f3519e3 | |
parent | 3a83d94096a32e838f3331932644f4495593e6e8 (diff) | |
download | nevsky-1bc80c430198d095315cd0c7643d18d12538c62b.tar.gz |
Initial capability draw. Click on lord shields.
-rw-r--r-- | play.html | 15 | ||||
-rw-r--r-- | play.js | 17 | ||||
-rw-r--r-- | rules.js | 154 | ||||
-rw-r--r-- | tools/gendata.js | 8 |
4 files changed, 174 insertions, 20 deletions
@@ -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; } @@ -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 } @@ -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) |