summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--play.css11
-rw-r--r--play.js4
-rw-r--r--rules.ts358
3 files changed, 166 insertions, 207 deletions
diff --git a/play.css b/play.css
index 25b7fe3..5dd1f17 100644
--- a/play.css
+++ b/play.css
@@ -22,19 +22,12 @@ body.Lancaster #event_header, body.Lancaster #hand_header, body.Lancaster #plan_
#log .h3 { text-decoration: underline; }
#log .h4 { text-decoration: underline; }
-#log .h1 { background-color: #e5ce98 }
-#log .h2 { background-color: #e6e5be }
-
-#log .h2.lancaster { background-color: #fad2d3 }
-#log .h2.york { background-color: #d1ddf1 }
-
#log .h1 { background-color: silver }
#log .h2 { background-color: gainsboro }
+#log .h2.lancaster { background-color: #fad2d3 }
+#log .h2.york { background-color: #d1ddf1 }
#log .ip { float: right; padding: 0 4px 0 0; text-indent: 0; color: dimgray }
-/*
-#log .ip::after { content: "IP" }
-*/
#log div { padding-left: 20px; text-indent: -12px; }
#log div.i { padding-left: 32px; text-indent: -12px; }
diff --git a/play.js b/play.js
index 7775f56..06c5b91 100644
--- a/play.js
+++ b/play.js
@@ -1423,7 +1423,7 @@ function on_update() {
if (view.battle) {
let { x, y, w, h } = data.locales[view.battle.where].box
- ui.battle.className = "marker circle battle"
+ ui.battle.className = "marker square battle"
ui.battle.style.left = ((x+w/2)|0) - 27 + "px"
ui.battle.style.top = y + h - 27 + "px"
} else {
@@ -1542,8 +1542,8 @@ function on_update() {
action_button("capability", "Capability")
// CAMPAIGN
- action_button("supply", "Supply")
action_button("sail", "Sail")
+ action_button("supply", "Supply")
action_button("forage", "Forage")
action_button("tax", "Tax")
diff --git a/rules.ts b/rules.ts
index 40429f8..5a979cc 100644
--- a/rules.ts
+++ b/rules.ts
@@ -1449,11 +1449,9 @@ function find_lord_with_capability_card(c: Card) {
return NOBODY
}
-function get_force_name(lord: Lord, n: Force, x: Vassal = NOVASSAL) {
- if (n === RETINUE)
- return `${lord_name[lord]}'s Retinue`
+function get_force_name(_lord: Lord, n: Force, x: Vassal = NOVASSAL) {
if (n === VASSAL)
- return `Vassal ${vassal_name[x]}`
+ return "V" + x
return FORCE_TYPE_NAME[n]
}
@@ -1505,6 +1503,14 @@ function get_modified_valour(lord: Lord, report: boolean) {
return valour
}
+function can_pick_up_lords(lord: Lord) {
+ if (is_marshal(lord) || is_lieutenant(lord))
+ return true
+ if (lord_has_capability(lord, AOW_YORK_CAPTAIN) && !has_other_marshal_or_lieutenant(lord, get_lord_locale(lord)))
+ return true
+ return false
+}
+
// === STATE: LORD (SHARED) ===
function get_york_shared_assets(loc: Locale, what: Asset) {
@@ -1901,18 +1907,11 @@ function is_lord_in_or_adjacent_to_wales(lord: Lord) {
return false
}
-// Captain capability (lieutenant/marshall only if no other)
-function other_marshal_or_lieutenant(loc: Locale) {
- let n = 0
- for (let lord of all_friendly_lords())
- if (lord !== game.command) {
- if (get_lord_locale(lord) === loc && (is_marshal(lord) || is_lieutenant(lord)))
- n += 1
- }
- if (n === 0)
- return false
- else
- return true
+function has_other_marshal_or_lieutenant(lord: Lord, here: Locale) {
+ for (let other of all_friendly_lords())
+ if (other !== lord && get_lord_locale(other) === here && (is_marshal(other) || is_lieutenant(other)))
+ return true
+ return false
}
function has_adjacent_enemy(loc: Locale) {
@@ -2836,7 +2835,7 @@ function death_lord(lord: Lord) {
if (lord === LORD_WARWICK_L && game.battle.attacker === YORK)
foreign_haven_shift_lords()
}
- log(`Death L${lord}.`)
+ log(`Removed L${lord}.`)
set_lord_locale(lord, NOWHERE)
clear_lord(lord)
}
@@ -3901,6 +3900,7 @@ function end_command() {
states.command = {
inactive: "Command",
prompt() {
+ let here = get_lord_locale(game.command)
if (game.actions === 0)
view.prompt = `Command: ${lord_name[game.command]} has no more actions.`
else if (game.actions === 1)
@@ -3910,8 +3910,6 @@ states.command = {
view.group = game.group
- let here = get_lord_locale(game.command)
-
prompt_held_event_at_campaign()
if (!is_lord_on_map(game.command)) {
@@ -3920,25 +3918,11 @@ states.command = {
return
}
- // 4.3.2 Marshals MAY take other lords
- // TODO: PICK_UP_LORDS
- if (
- is_marshal(game.command) ||
- (lord_has_capability(game.command, AOW_YORK_CAPTAIN) && !other_marshal_or_lieutenant(here))
- ) {
- for (let lord of all_friendly_lords())
- if (lord !== game.command)
- if (get_lord_locale(lord) === here)
- gen_action_lord(lord)
- }
-
- // Lieutenant may not take marshall
- if (is_lieutenant(game.command)) {
- for (let lord of all_friendly_lords())
- if (lord !== game.command)
- if (get_lord_locale(lord) === here && !is_marshal(lord)) {
- gen_action_lord(lord)
- }
+ if (can_pick_up_lords(game.command)) {
+ for_each_friendly_lord_in_locale(here, other => {
+ if (other !== game.command && !is_marshal(other))
+ gen_action_lord(other)
+ })
}
if (game.actions > 0) {
@@ -3946,7 +3930,8 @@ states.command = {
view.actions.supply = 0
view.actions.forage = 0
view.actions.tax = 0
- view.actions.sail = 0
+ if (is_seaport(here) || is_exile_box(here))
+ view.actions.sail = 0
view.actions.parley = 0
view.actions.pass = 1
} else {
@@ -4921,7 +4906,7 @@ function goto_parley_campaign() {
// Campaign phase, and current location is no cost (except some events), and always successful.
if (can_parley_at(here)) {
- log(`Parley at ${locale_name[here]}`)
+ log(`Parley at S${here}.`)
shift_favour_toward(here)
if (is_lancaster_lord(game.command) && is_event_in_play(EVENT_YORK_AN_HONEST_TALE_SPEEDS_BEST)) {
reduce_lancaster_influence(1)
@@ -5339,6 +5324,8 @@ states.intercept = {
inactive: "Intercept",
prompt() {
let to = game.march.to
+
+ view.group = game.intercept
view.where = to
if (game.who === NOBODY) {
@@ -5357,13 +5344,10 @@ states.intercept = {
gen_action_lord(game.who)
- // TODO: PICK_UP_LORDS
- // 4.3.2 Marshals MAY take other lords
- // or CAPTAIN?
- if (is_marshal(game.who) || is_lieutenant(game.who)) {
- for_each_friendly_lord_in_locale(get_lord_locale(game.who), lord => {
- if (!is_marshal(lord) && is_move_allowed(lord, to))
- gen_action_lord(lord)
+ if (can_pick_up_lords(game.who)) {
+ for_each_friendly_lord_in_locale(get_lord_locale(game.who), other => {
+ if (other !== game.who && !is_marshal(other) && is_move_allowed(other, to))
+ gen_action_lord(other)
})
}
@@ -5401,6 +5385,7 @@ states.intercept = {
intercept() {
let success = false
if (is_flank_attack_in_play()) {
+ log("Intercept with " + format_intercept() + ".")
end_passive_held_event()
success = true
}
@@ -5409,11 +5394,13 @@ states.intercept = {
let roll = roll_die()
success = roll <= valour
if (success)
- log(`Intercept with ${format_intercept()} ${range(valour)}: B${roll}`)
+ log(`Intercept ${range(valour)}: B${roll}`)
else
- log(`Intercept with ${format_intercept()} ${range(valour)}: W${roll}`)
+ log(`Intercept ${range(valour)}: W${roll}`)
+ log(">with " + format_intercept())
get_modified_valour(game.who, true)
}
+
if (success) {
goto_intercept_march()
} else {
@@ -6131,7 +6118,7 @@ function remove_battle_capability_troops(lord: Lord) {
function goto_battle() {
let here = get_lord_locale(game.command)
- log_h3(`Battle at S${here}`)
+ log_h2_common(`Battle at S${here}`)
game.battle = {
where: here,
@@ -6875,7 +6862,7 @@ function end_regroup() {
*/
function goto_battle_rounds() {
- log_h4(`Battle Round ${game.battle.round}`)
+ log_h3(`Round ${game.battle.round}`)
game.battle.step = 0
@@ -6969,9 +6956,9 @@ function use_culverins(lord: Lord) {
if (is_event_in_play(EVENT_YORK_PATRICK_DE_LA_MOTE) && game.active === YORK) {
logevent(EVENT_YORK_PATRICK_DE_LA_MOTE)
die2 = roll_die()
- logi(`${die1} + ${die2} culverins`)
+ logi(`${die1} + ${die2} Cannons`)
} else {
- logi(`${die1} culverins`)
+ logi(`${die1} Cannons`)
}
set_delete(game.battle.culverins, lord)
return (die1 + die2) << 1
@@ -7014,7 +7001,7 @@ states.flee_battle = {
},
lord(lord) {
push_undo()
- log(`${lord_name[lord]} Fled the battle of S${game.battle.where}.`)
+ log(`Flee L${lord}.`)
set_add(game.battle.routed, lord)
set_add(game.battle.fled, lord)
remove_lord_from_battle(lord)
@@ -7399,7 +7386,7 @@ function goto_total_hits() {
let lord = game.battle.array[pos]
if (lord !== NOBODY) {
let hits = count_lord_hits(lord)
- log_hits(hits / 2, lord_name[lord])
+ log_hits(hits / 2, "L" + lord)
hits += use_culverins(lord)
if (pos === A1 || pos === A2 || pos === A3)
ahits += hits
@@ -7421,9 +7408,6 @@ function goto_total_hits() {
game.battle.ahits = ahits
game.battle.dhits = dhits
- log_hits(ahits, "ATK TOTAL")
- log_hits(dhits, "DEF TOTAL")
-
game.battle.final_charge = 0
if (can_final_charge()) {
@@ -7461,7 +7445,7 @@ states.final_charge = {
},
final_charge() {
logcap(AOW_YORK_FINAL_CHARGE)
- log_hits("+3", lord_name[find_lord_with_capability_card(AOW_YORK_FINAL_CHARGE)])
+ log_hits("+3", "L" + find_lord_with_capability_card(AOW_YORK_FINAL_CHARGE))
log_hits("+1", "Final Charge")
game.battle.final_charge = 1
if (game.battle.attacker === YORK) {
@@ -7865,7 +7849,7 @@ states.swift_maneuver_2 = {
// === 4.4.2 BATTLE ROUNDS: LORD ROUT ===
function rout_lord(lord: Lord) {
- log(`L${lord} Routed.`)
+ log(">L" + lord)
let pos = get_lord_array_position(lord)
@@ -8003,13 +7987,15 @@ function set_active_victor() {
}
function end_battle() {
+ //game.battle.array = null
+ game.battle.caltrops = NOBODY
+
+ log_h3("Ending the Battle")
if (game.battle.loser === BOTH)
- log_h4(`Both Sides Lost`)
+ log("Both sides lose.")
else
- log_h4(`${game.battle.loser} Lost`)
+ log(`${game.battle.loser} lose.`)
- //game.battle.array = null
- game.battle.caltrops = NOBODY
goto_battle_influence()
}
@@ -8023,21 +8009,102 @@ function has_defeated_lords() {
// === 4.4.3 ENDING THE BATTLE: INFLUENCE ===
function goto_battle_influence() {
+ log_h4(`Influence`)
+
if (game.battle.loser !== BOTH) {
set_active_loser()
- let influence = 0
- for (let lord of game.battle.routed)
- if (is_friendly_lord(lord))
- influence += get_lord_influence(lord) + count_vassals_with_lord(lord)
+ for (let lord of game.battle.routed) {
+ if (is_friendly_lord(lord)) {
+ reduce_influence(get_lord_influence(lord) + count_vassals_with_lord(lord))
+ log(">L" + lord)
+ }
+ }
- reduce_influence(influence)
goto_battle_spoils()
} else {
end_battle_losses()
}
}
+// === 4.4.3 ENDING THE BATTLE: SPOILS ===
+
+function find_lone_friendly_lord_at(loc: Locale) {
+ let who = NOBODY
+ let n = 0
+ for (let lord of all_friendly_lords()) {
+ if (get_lord_locale(lord) === loc) {
+ who = lord
+ ++n
+ }
+ }
+ if (n === 1)
+ return who
+ return NOBODY
+}
+
+function goto_battle_spoils() {
+ set_active_loser()
+ for (let lord of all_friendly_lords())
+ if (get_lord_locale(lord) === game.battle.where)
+ give_up_spoils(lord)
+
+ set_active_victor()
+ round_spoils()
+ if (has_any_spoils() && has_friendly_lord(game.battle.where)) {
+ log_h4("Spoils")
+ log_spoils()
+ game.state = "battle_spoils"
+ game.who = find_lone_friendly_lord_at(game.battle.where)
+ } else {
+ end_battle_spoils()
+ }
+}
+
+function end_battle_spoils() {
+ game.who = NOBODY
+ delete game.spoils
+ goto_battle_losses_victor()
+}
+
+states.battle_spoils = {
+ inactive: "Spoils",
+ prompt() {
+ if (has_any_spoils()) {
+ view.prompt = "Spoils: Divide " + list_spoils() + "."
+ let here = game.battle.where
+ for (let lord of all_friendly_lords())
+ if (get_lord_locale(lord) === here)
+ prompt_select_lord(lord)
+ if (game.who !== NOBODY)
+ prompt_spoils()
+ } else {
+ view.prompt = "Spoils: All done."
+ view.actions.end_spoils = 1
+ }
+ },
+ lord: action_select_lord,
+
+ take_prov() {
+ push_undo_without_who()
+ take_spoils(PROV)
+ },
+
+ take_cart() {
+ push_undo_without_who()
+ take_spoils(CART)
+ },
+
+ take_all() {
+ push_undo_without_who()
+ take_all_spoils()
+ },
+
+ end_spoils() {
+ end_battle_spoils()
+ },
+}
+
// === 4.4.3 ENDING THE BATTLE: LOSSES ===
function has_battle_losses() {
@@ -8051,7 +8118,7 @@ function goto_battle_losses_victor() {
set_active_victor()
game.who = NOBODY
if (has_battle_losses())
- log_h4(`${game.active} Losses`)
+ log_h4(`Losses`)
resume_battle_losses()
}
@@ -8130,84 +8197,6 @@ states.battle_losses = {
},
}
-// === 4.4.3 ENDING THE BATTLE: SPOILS ===
-
-function find_lone_friendly_lord_at(loc: Locale) {
- let who = NOBODY
- let n = 0
- for (let lord of all_friendly_lords()) {
- if (get_lord_locale(lord) === loc) {
- who = lord
- ++n
- }
- }
- if (n === 1)
- return who
- return NOBODY
-}
-
-function goto_battle_spoils() {
- set_active_loser()
- for (let lord of all_friendly_lords())
- if (get_lord_locale(lord) === game.battle.where)
- give_up_spoils(lord)
-
- set_active_victor()
- round_spoils()
- if (has_any_spoils() && has_friendly_lord(game.battle.where)) {
- log_h4("Spoils")
- log_spoils()
- game.state = "battle_spoils"
- game.who = find_lone_friendly_lord_at(game.battle.where)
- } else {
- end_battle_spoils()
- }
-}
-
-function end_battle_spoils() {
- game.who = NOBODY
- delete game.spoils
- goto_battle_losses_victor()
-}
-
-states.battle_spoils = {
- inactive: "Spoils",
- prompt() {
- if (has_any_spoils()) {
- view.prompt = "Spoils: Divide " + list_spoils() + "."
- let here = game.battle.where
- for (let lord of all_friendly_lords())
- if (get_lord_locale(lord) === here)
- prompt_select_lord(lord)
- if (game.who !== NOBODY)
- prompt_spoils()
- } else {
- view.prompt = "Spoils: All done."
- view.actions.end_spoils = 1
- }
- },
- lord: action_select_lord,
-
- take_prov() {
- push_undo_without_who()
- take_spoils(PROV)
- },
-
- take_cart() {
- push_undo_without_who()
- take_spoils(CART)
- },
-
- take_all() {
- push_undo_without_who()
- take_all_spoils()
- },
-
- end_spoils() {
- end_battle_spoils()
- },
-}
-
// === 4.4.3 ENDING THE BATTLE: DEATH CHECK AND DISBAND ===
function has_any_friendly_routed_vassals() {
@@ -8346,18 +8335,18 @@ states.death_check = {
let die = roll_die()
if (set_has(game.battle.fled, game.who)) {
if (die >= 5) {
- logi("L" + game.who + " 5-6 B" + die)
+ logi("L" + game.who + " 5-6: B" + die)
death_lord(game.who)
} else {
- logi("L" + game.who + " 5-6 W" + die)
+ logi("L" + game.who + " 5-6: W" + die)
disband_lord(game.who)
}
} else {
if (die >= 3) {
- logi("L" + game.who + " 3-6 B" + die)
+ logi("L" + game.who + " 3-6: B" + die)
death_lord(game.who)
} else {
- logi("L" + game.who + " 3-6 W" + die)
+ logi("L" + game.who + " 3-6: W" + die)
disband_lord(game.who)
}
}
@@ -11022,8 +11011,7 @@ states.agitators = {
},
locale(loc) {
push_undo()
- logcap(AOW_YORK_AGITATORS)
- logi("S" + loc)
+ log("C" + AOW_YORK_AGITATORS + " at S" + loc + ".")
if (has_depleted_marker(loc))
add_exhausted_marker(loc)
else
@@ -11251,18 +11239,12 @@ states.scots = {
// === EVENT: LANCASTER HENRY PRESSURES PARLIAMENT ===
function goto_lancaster_event_henry_pressures_parliament() {
- let count = 0
- for (let vassal of all_vassals) {
- if (is_vassal_mustered_with_york_lord(vassal)) {
- count++
+ for (let v of all_vassals) {
+ if (is_vassal_mustered_with_york_lord(v)) {
+ reduce_york_influence(1)
+ log(">V" + v)
}
}
-
- if (count > 0) {
- logi(`Removed ${count} York influence.`)
- reduce_york_influence(count)
- }
-
end_immediate_event()
}
@@ -11456,13 +11438,13 @@ states.warwicks_propaganda_yorkist_choice = {
push_undo()
remove_york_favour(game.where)
remove_propaganda_target(game.where)
- logi(`Removed favour in ${game.where}`)
+ logi(`Removed York Favour at S${game.where}.`)
game.where = NOWHERE
},
influence() {
push_undo()
reduce_influence(2)
- logi(`Paid 2 to keep ${game.where}`)
+ logi(`Paid 2 to keep S${game.where}`)
remove_propaganda_target(game.where)
game.where = NOWHERE
},
@@ -11606,7 +11588,7 @@ states.welsh_rebellion_remove_favour = {
locale(loc) {
push_undo()
remove_york_favour(loc)
- logi(`Removed favour at ${locale_name[loc]}`)
+ log(`Removed York Favour at S${loc}.`)
game.count++
},
done() {
@@ -11618,8 +11600,8 @@ states.welsh_rebellion_remove_favour = {
function goto_lancaster_event_henry_released() {
if (has_lancaster_favour(LOC_LONDON)) {
- logi(`Henry Released : 5 Influence for Lancaster`)
increase_lancaster_influence(5)
+ log("London Favours Lancastrians.")
}
end_immediate_event()
}
@@ -11659,7 +11641,7 @@ states.aragne_1 = {
vassal(v) {
push_undo()
set_add(game.event_aragne, v)
- logi(`Vassal ${vassal_name[v]} selected`)
+ log(">V" + v)
},
done() {
push_undo()
@@ -11760,7 +11742,7 @@ states.wilful_disobedience = {
push_undo()
remove_york_favour(loc)
game.count++
- logi(`Favour removed at ${loc}`)
+ logi(`Yorkist Favour removed at S${loc}`)
},
done() {
logi("No effect.")
@@ -11773,9 +11755,9 @@ states.wilful_disobedience = {
function goto_lancaster_event_french_war_loans() {
for (let lord of all_lancaster_lords) {
if (is_lord_on_map(lord) && !is_lord_on_calendar(lord)) {
+ logi(">L" + lord)
add_lord_assets(lord, PROV, 1)
add_lord_assets(lord, COIN, 1)
- logi(`1 Coin and 1 Provender added to ${lord_name[lord]}`)
}
}
end_immediate_event()
@@ -11812,7 +11794,7 @@ states.robins_rebellion = {
locale(loc) {
push_undo()
shift_favour_toward(loc)
- logi(`Placed/Removed favour at ${locale_name[loc]}`)
+ log(`Placed/Removed Favour at S${loc}.`)
game.count++
},
done() {
@@ -11861,7 +11843,7 @@ states.tudor_banners = {
push_undo()
remove_york_favour(loc)
add_lancaster_favour(loc)
- logi(`Placed Lancastrian favour at ${locale_name[loc]}`)
+ log(`Placed Lancastrian Favour at S${loc}`)
},
done() {
game.who = NOBODY
@@ -12036,7 +12018,7 @@ states.she_wolf = {
if (t < 16)
set_vassal_lord_and_service(v, get_vassal_lord(v), t)
set_add(game.event_she_wolf, v)
- log(`${vassal_name[v]} to T${t}.`)
+ log(`>V${v} to T${t}`)
},
done() {
delete game.event_she_wolf
@@ -12531,7 +12513,7 @@ states.sun_in_splendour = {
muster_lord(LORD_EDWARD_IV, loc)
set_lord_moved(LORD_EDWARD_IV, 1)
- log(`L${LORD_EDWARD_IV} at ${locale_name[loc]}`)
+ log(`L${LORD_EDWARD_IV} at ${locale_name[loc]}.`)
end_held_event()
game.state = "muster"
@@ -12731,29 +12713,13 @@ states.surprise_landing = {
inactive: "Surprise Landing",
prompt() {
view.prompt = "Surprise Landing: Free march."
-
view.group = game.group
- let here = get_lord_locale(game.command)
- // 4.3.2 Marshals MAY take other lords
- // TODO: PICK_UP_LORDS
- if (
- is_marshal(game.command) ||
- (lord_has_capability(game.command, AOW_YORK_CAPTAIN) && !other_marshal_or_lieutenant(here))
- ) {
- for (let lord of all_friendly_lords())
- if (lord !== game.command)
- if (get_lord_locale(lord) === here)
- gen_action_lord(lord)
- }
-
- // Lieutenant may not take marshall
- if (is_lieutenant(game.command)) {
- for (let lord of all_friendly_lords())
- if (lord !== game.command)
- if (get_lord_locale(lord) === here && !is_marshal(lord)) {
- gen_action_lord(lord)
- }
+ if (can_pick_up_lords(game.command)) {
+ for_each_friendly_lord_in_locale(get_lord_locale(game.command), other => {
+ if (other !== game.command && !is_marshal(other))
+ gen_action_lord(other)
+ })
}
prompt_march()