summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor@ccxvii.net>2023-10-10 16:39:49 +0200
committerTor Andersson <tor@ccxvii.net>2023-12-10 18:16:55 +0100
commitb167b49550b6460a29662fe7fb512f21be7dd7f7 (patch)
tree61301db6f6a838beeddbfd15c97a2df0602a8290
parentf15c978b76f57cd27303f2860d4329a86e407d93 (diff)
downloadplantagenet-b167b49550b6460a29662fe7fb512f21be7dd7f7.tar.gz
Tweak vassal state handling.
-rw-r--r--play.js74
-rw-r--r--rules.js171
2 files changed, 122 insertions, 123 deletions
diff --git a/play.js b/play.js
index 490eeca..0bce29a 100644
--- a/play.js
+++ b/play.js
@@ -212,11 +212,13 @@ const asset_type_count = 4
const asset_action_name = [ "prov", "coin", "cart", "ship" ]
const asset_type_x34 = [ 1, 1, 1, 0 ]
-const VASSAL_UNAVAILABLE = 201
-const VASSAL_READY = 200
const NOWHERE = -1
const CALENDAR = 100
+const VASSAL_READY = 29
+const VASSAL_CALENDAR = 30
+const VASSAL_OUT_OF_PLAY = 31
+
const TOWN = "town"
const CITY = "city"
const FORTRESS = "fortress"
@@ -419,21 +421,17 @@ function count_favour(type) {
return n
}
-function is_vassal_ready(vassal) {
- return pack8_get(view.pieces.vassals[vassal], 0) === VASSAL_READY
-}
-
-function is_vassal_unavailable(vassal) {
- return pack8_get(view.pieces.vassals[vassal], 0) === VASSAL_UNAVAILABLE
+function get_vassal_lord(vassal) {
+ return view.pieces.vassals[vassal] & 31
}
-function get_vassal_locale(vassal) {
- return pack8_get(view.pieces.vassals[vassal], 1)
+function get_vassal_service(vassal) {
+ return view.pieces.vassals[vassal] >> 5
}
function for_each_vassal_with_lord(lord, f) {
for (let x = first_vassal; x < last_vassal; x++)
- if (pack8_get(view.pieces.vassals[x], 0) === lord)
+ if (get_vassal_lord(x) === lord)
f(x)
}
@@ -594,7 +592,8 @@ const ui = {
lord_mat: [],
lord_exile: [],
lord_buttons: [],
- map_vassals: [],
+ vassal_cal: [], // token on calendar
+ vassal_map: [], // token on map
forces: [],
routed: [],
assets: [],
@@ -609,7 +608,6 @@ const ui = {
calendar: [],
track: [],
seat: [],
- vassalbox: [],
plan_panel: document.getElementById("plan_panel"),
plan: document.getElementById("plan"),
@@ -828,7 +826,7 @@ function build_map() {
})
data.vassalbox.forEach((vassal, ix) => {
- let e = ui.vassalbox[ix] = document.createElement("div")
+ let e = ui.vassal_map[ix] = document.createElement("div")
let { x, y, w, h } = vassal.box
let xc = Math.round(x + w / 2)
let yc = Math.round(y + h / 2)
@@ -841,13 +839,13 @@ function build_map() {
e.style.height = 46 + "px"
e.style.backgroundSize = small + "px"
register_action(e, "vassal", ix)
- register_tooltip(e, data.vassalbox[ix].name)
+ register_tooltip(e, data.vassals[ix].name)
document.getElementById("pieces").appendChild(e)
})
data.vassals.forEach((vassal, ix) => {
- let e = ui.map_vassals[ix] = document.createElement("div")
- e.className = "hide marker square vassal vassal_" + clean_name(vassal.name)
+ let e = ui.vassal_cal[ix] = document.createElement("div")
+ e.className = "hide marker square back vassal vassal_" + clean_name(vassal.name)
e.style.position = "absolute"
e.style.width = 46 + "px"
e.style.height = 46 + "px"
@@ -1467,20 +1465,34 @@ function update_court() {
function update_vassals() {
for (let v = first_vassal; v < last_vassal; v++) {
- let info = data.vassals[v]
- if (!is_vassal_ready(v) && get_vassal_locale(v) !== 0) {
- let e = ui.map_vassals[v]
- e.classList.add("hide")
- calendar_layout_vassal[get_vassal_locale(v) - CALENDAR].push(e)
- e.classList.remove("hide")
- e.classList.toggle("action", is_action("vassal", v))
- e.classList.toggle("back", is_vassal_unavailable(v))
- ui.vassalbox[v].classList.add("hide")
- } else if (is_vassal_ready(v)) {
- let e = ui.vassalbox[v]
- e.classList.remove("hide")
- e.classList.toggle("action", is_action("vassal", v))
- e.classList.add("vassal" + clean_name(info.name))
+ let loc = get_vassal_lord(v)
+ let srv = get_vassal_service(v)
+ if (loc === VASSAL_OUT_OF_PLAY) {
+ // not present
+ ui.vassal_cal[v].classList.add("hide")
+ if (ui.vassal_map[v]) {
+ ui.vassal_map[v].classList.add("hide")
+ }
+ } else if (loc === VASSAL_READY) {
+ // on map
+ ui.vassal_cal[v].classList.add("hide")
+ if (ui.vassal_map[v]) {
+ ui.vassal_map[v].classList.remove("hide")
+ ui.vassal_map[v].classList.toggle("action", is_action("vassal", v))
+ }
+ } else {
+ // on calendar (+ maybe on lord mat)
+ if (data.vassals[v].service > 0) {
+ ui.vassal_cal[v].classList.remove("hide")
+ ui.vassal_cal[v].classList.toggle("action", is_action("vassal", v))
+ calendar_layout_vassal[srv].push(ui.vassal_cal[v])
+ } else {
+ // special vassal not on calendar
+ ui.vassal_cal[v].classList.add("hide")
+ }
+ if (ui.vassal_map[v]) {
+ ui.vassal_map[v].classList.add("hide")
+ }
}
}
}
diff --git a/rules.js b/rules.js
index 52aca03..8a30687 100644
--- a/rules.js
+++ b/rules.js
@@ -6,6 +6,8 @@ const BOTH = "Both"
const LANCASTER = "Lancaster"
const YORK = "York"
+// TODO: "approach" pause when about to move into intercept range?
+
var P1 = null
var P2 = null
@@ -651,16 +653,16 @@ const EVENT_YORK_PATRICK_DE_LA_MOTE = Y37 // TODO
// Check all push/clear_undo
-const VASSAL_UNAVAILABLE = 201
-const VASSAL_READY = 200
-//const VASSAL_MUSTERED = -3
-
const NOBODY = -1
const NOWHERE = -1
const NOTHING = -1
const NEVER = -1
+
const CALENDAR = 100
-const TRACK = 100
+
+const VASSAL_READY = 29
+const VASSAL_CALENDAR = 30
+const VASSAL_OUT_OF_PLAY = 31
const SUMMER = 0
const SPRING = 1
@@ -964,8 +966,8 @@ function shift_lord_cylinder(lord, dir) {
function set_lord_assets(lord, n, x) {
if (x < 0)
x = 0
- if (x > 40)
- x = 40
+ if (x > 15)
+ x = 15
map_set_pack4(game.pieces.assets, lord, n, x)
}
@@ -1282,89 +1284,88 @@ function is_lord_ready(lord) {
return loc >= CALENDAR && loc <= CALENDAR + (game.turn >> 1)
}
+// === VASSAL STATE ===
+
+function set_vassal_lord_and_service(vassal, lord, service) {
+ game.pieces.vassals[vassal] = lord + (service << 5)
+}
+
+function get_vassal_lord(vassal) {
+ return game.pieces.vassals[vassal] & 31
+}
+
+function get_vassal_service(vassal) {
+ return game.pieces.vassals[vassal] >> 5
+}
+
function setup_vassals(excludes = []) {
for (let x = first_vassal; x < last_vassal; x++) {
if (!excludes.includes(x) && data.vassals[x].capability === undefined) {
- set_vassal_ready(x)
- set_vassal_on_map(x, data.vassals[x].seat)
+ set_vassal_lord_and_service(x, VASSAL_READY, 0)
}
}
}
-function set_vassal_on_map(vassal, loc) {
- game.pieces.vassals[vassal] = pack8_set(game.pieces.vassals[vassal], 1, loc)
-}
-
-function get_vassal_locale(vassal) {
- return pack8_get(game.pieces.vassals[vassal], 1)
-}
-
-function for_each_vassal_with_lord(lord, f) {
- for (let x = first_vassal; x < last_vassal; x++)
- if (pack8_get(game.pieces.vassals[x], 0) === lord)
- f(x)
+function is_vassal_ready(x) {
+ return get_vassal_lord(x) === VASSAL_READY
}
-function count_vassals_with_lord(lord) {
- let n = 0
- for_each_vassal_with_lord(lord, _ => {
- ++n
- })
- return n
+function is_vassal_mustered(x) {
+ return get_vassal_lord(x) < VASSAL_READY
}
-function get_lord_with_vassal(vassal) {
- return pack8_get(game.pieces.vassals[vassal], 0)
+function is_vassal_mustered_with(x, lord) {
+ return get_vassal_lord(x) === lord
}
-function set_vassal_ready(vassal) {
- game.pieces.vassals[vassal] = pack8_set(game.pieces.vassals[vassal], 0, VASSAL_READY)
+function is_vassal_mustered_with_friendly_lord(x) {
+ return is_friendly_lord(get_vassal_lord(x))
}
-function set_vassal_on_calendar(vassal, turn) {
- if (data.vassals[vassal].service === 0)
- return
- game.pieces.vassals[vassal] = pack8_set(game.pieces.vassals[vassal], 1, turn + CALENDAR)
+function is_vassal_mustered_with_york_lord(x) {
+ return is_york_lord(get_vassal_lord(x))
}
-function set_vassal_with_lord(vassal, lord) {
- game.pieces.vassals[vassal] = pack8_set(game.pieces.vassals[vassal], 0, lord)
+function for_each_vassal_with_lord(lord, f) {
+ for (let x = first_vassal; x < last_vassal; x++)
+ if (is_vassal_mustered_with(x, lord))
+ f(x)
}
-function set_vassal_unavailable(vassal) {
- game.pieces.vassals[vassal] = pack8_set(game.pieces.vassals[vassal], 0, VASSAL_UNAVAILABLE)
+function count_vassals_with_lord(lord) {
+ let n = 0
+ for (let x = first_vassal; x < last_vassal; x++)
+ if (is_vassal_mustered_with(x, lord))
+ ++n
+ return n
}
function muster_vassal(vassal, lord) {
- set_vassal_with_lord(vassal, lord)
- if (data.vassals[vassal].service !== 0 && lord_has_capability(lord, AOW_YORK_ALICE_MONTAGU))
- set_vassal_on_calendar(vassal, current_turn() + (1 + data.vassals[vassal].service))
- else if (data.vassals[vassal].service !== 0)
- set_vassal_on_calendar(vassal, current_turn() + data.vassals[vassal].service)
+ if (data.vassals[vassal].service !== 0) {
+ let service = current_turn() + data.vassals[vassal].service
+ if (lord_has_capability(lord, AOW_YORK_ALICE_MONTAGU))
+ service += 1
+ set_vassal_lord_and_service(vassal, lord, service)
+ } else {
+ set_vassal_lord_and_service(vassal, lord, 0)
+ }
}
function disband_vassal(vassal) {
- let new_turn = current_turn() + (6 - data.vassals[vassal].service)
- set_vassal_unavailable(vassal)
- set_vassal_on_calendar(vassal, new_turn)
- log(`Disbanded V${vassal} to turn ${current_turn() + (6 - data.vassals[vassal].service)}.`)
+ if (data.vassals[vassa].service > 0) {
+ let new_turn = current_turn() + (6 - data.vassals[vassal].service)
+ set_vassal_lord_and_service(vassal, VASSAL_CALENDAR, new_turn)
+ log(`Disbanded V${vassal} to turn ${current_turn() + (6 - data.vassals[vassal].service)}.`)
+ } else {
+ // TODO: special vassals with no service marker!?
+ set_vassal_lord_and_service(vassal, VASSAL_OUT_OF_PLAY, 0)
+ log(`Disbanded V${vassal}.`)
+ }
}
function pay_vassal(vassal) {
if (current_turn() < 15)
- set_vassal_on_calendar(vassal, current_turn() + 1)
-}
-
-function is_vassal_unavailable(vassal) {
- return pack8_get(game.pieces.vassals[vassal], 0) === VASSAL_UNAVAILABLE
-}
-
-function is_vassal_ready(vassal) {
- return pack8_get(game.pieces.vassals[vassal], 0) === VASSAL_READY
-}
-
-function is_vassal_mustered(vassal) {
- return pack8_get(game.pieces.vassals[vassal]) < VASSAL_READY
+ set_vassal_lord_and_service(vassal, get_vassal_lord(vassal), current_turn() + 1)
}
function is_york_lord(lord) {
@@ -1869,7 +1870,7 @@ exports.setup = function (seed, scenario, options) {
in_exile: 0,
// per vassal data
- vassals: Array(vassal_count).fill(VASSAL_UNAVAILABLE),
+ vassals: Array(vassal_count).fill(VASSAL_OUT_OF_PLAY),
// per locale data
depleted: [],
@@ -2395,7 +2396,7 @@ states.scots = {
function goto_lancaster_event_henry_pressures_parliament() {
let count = 0
for (let vassal = first_vassal; vassal <= last_vassal; vassal++) {
- if (is_vassal_mustered(vassal) && is_york_lord(get_lord_with_vassal(vassal))) {
+ if (is_vassal_mustered_with_york_lord(vassal)) {
count++
}
}
@@ -2412,8 +2413,8 @@ function goto_lancaster_event_henry_pressures_parliament() {
function goto_lancaster_event_henrys_proclamation() {
for (let vassal = first_vassal; vassal <= last_vassal; vassal++) {
- if (is_vassal_mustered(vassal) && is_york_lord(get_lord_with_vassal(vassal))) {
- set_vassal_on_calendar(vassal, current_turn())
+ if (is_vassal_mustered_with_york_lord(vassal)) {
+ set_vassal_lord_and_service(vassal, get_vassal_lord(vassal), current_turn())
}
}
}
@@ -2928,11 +2929,9 @@ states.levy_muster_lord = {
}
// Muster Ready Vassal Forces
- if (is_friendly_locale(here)) {
- for (let vassal = first_vassal; vassal <= last_vassal; vassal++)
- if (is_vassal_ready(vassal) && is_favour_friendly(data.vassals[vassal].seat))
- gen_action_vassal(vassal)
- }
+ for (let vassal = first_vassal; vassal <= last_vassal; vassal++)
+ if (is_vassal_ready(vassal) && is_favour_friendly(data.vassals[vassal].seat))
+ gen_action_vassal(vassal)
// Add Transport
if (is_seaport(here) && get_lord_assets(game.who, SHIP) < 2)
@@ -4615,7 +4614,7 @@ function can_tax_at(here) {
// vassal seats
for (let vassal = first_vassal; vassal < last_vassal; ++vassal)
- if (get_lord_with_vassal(vassal) === game.command)
+ if (is_vassal_mustered_with(vassal, game.command))
if (here === data.vassals[vassal].seat)
return true
}
@@ -5880,7 +5879,8 @@ states.assign_hits = {
action_assign_hits(lord, MILITIA)
},
vassal(vassal) {
- action_assign_hits(get_lord_with_vassal(vassal), VASSAL, vassal)
+ let lord = get_vassal_lord(vassal)
+ action_assign_hits(lord, VASSAL, vassal)
},
}
@@ -6770,9 +6770,8 @@ function goto_pay_vassals() {
for (let v = first_vassal; v < last_vassal; v++) {
if (
- is_vassal_mustered(v) &&
- is_friendly_lord(get_lord_with_vassal(v)) &&
- get_vassal_locale(v) === CALENDAR + current_turn()
+ is_vassal_mustered_with_friendly_lord(v) &&
+ get_vassal_service(v) === current_turn()
) {
vassal_to_pay = true
}
@@ -6803,9 +6802,8 @@ states.pay_vassals = {
if (game.what === NOBODY) {
for (let v = first_vassal; v < last_vassal; v++) {
if (
- is_vassal_mustered(v) &&
- is_friendly_lord(get_lord_with_vassal(v)) &&
- get_vassal_locale(v) === CALENDAR + current_turn()
+ is_vassal_mustered_with_friendly_lord(v) &&
+ get_vassal_service(v) === current_turn()
) {
gen_action_vassal(v)
done = false
@@ -6841,9 +6839,8 @@ states.pay_vassals = {
function goto_ready_vassals() {
for (let vassal = first_vassal; vassal <= last_vassal; vassal++) {
- if (is_vassal_unavailable(vassal) && get_vassal_locale(vassal) === CALENDAR + current_turn()) {
- set_vassal_ready(vassal)
- set_vassal_on_map(vassal, data.vassals[vassal].seat)
+ if (get_vassal_service(vassal) === current_turn()) {
+ set_vassal_lord_and_service(vassal, VASSAL_READY, 0)
}
}
@@ -7696,7 +7693,7 @@ function disband_influence_penalty(lord) {
let influence = data.lords[lord].influence
for (let v = first_vassal; v <= last_vassal; v++) {
- if (get_vassal_locale(v) === lord) {
+ if (is_vassal_mustered_with(v, lord)) {
influence += 1
}
}
@@ -8052,11 +8049,6 @@ function pack4_get(word, n) {
return (word >>> n) & 15
}
-function pack8_get(word, n) {
- n = n << 3
- return (word >>> n) & 255
-}
-
function pack1_set(word, n, x) {
return (word & ~(1 << n)) | (x << n)
}
@@ -8071,11 +8063,6 @@ function pack4_set(word, n, x) {
return (word & ~(15 << n)) | (x << n)
}
-function pack8_set(word, n, x) {
- n = n << 3
- return (word & ~(255 << n)) | (x << n)
-}
-
// === COMMON LIBRARY ===
function clear_undo() {