summaryrefslogtreecommitdiff
path: root/rules.js
diff options
context:
space:
mode:
authorTor Andersson <tor@ccxvii.net>2024-04-15 18:37:32 +0200
committerTor Andersson <tor@ccxvii.net>2024-04-15 20:46:06 +0200
commite55b80ca7b4d9ddb7bfa96e75570dd88354e9e77 (patch)
treef55c344504ea45fbcfe62bc2997e10c131254cd3 /rules.js
parent6332b7063a83fdd496170c0ad1a2b2fcc2cb600e (diff)
downloadplantagenet-e55b80ca7b4d9ddb7bfa96e75570dd88354e9e77.tar.gz
Reorder code to follow rulebook numbering.
Diffstat (limited to 'rules.js')
-rw-r--r--rules.js12927
1 files changed, 6467 insertions, 6460 deletions
diff --git a/rules.js b/rules.js
index 33414e0..49ee55a 100644
--- a/rules.js
+++ b/rules.js
@@ -1,15 +1,87 @@
"use strict"
+// TODO: "approach" pause when about to move into intercept range?
+// TODO: log end victory conditions at scenario start
+// Check all push/clear_undo
+// TODO : Check BUG done visible in Death of Disband despite being false
+// TODO: check flank attack
+
+let game = null
+let view = null
+let states = {}
+
+// === CONSTANTS ===
+
const data = require("./data.js")
+function find_card(name) {
+ let ix = data.cards.findIndex(x => x.name === name)
+ if (ix < 0)
+ throw "CANNOT FIND CARD: " + name
+ return ix
+}
+
+function find_lord(name) {
+ let ix = data.lords.findIndex(x => x.name === name)
+ if (ix < 0)
+ throw "CANNOT FIND LORD: " + name
+ return ix
+}
+
+function find_locale(name) {
+ let ix = data.locales.findIndex(x => x.name === name)
+ if (ix < 0)
+ throw "CANNOT FIND LOCALE: " + name
+ return ix
+}
+
+function find_vassal(name) {
+ let ix = data.vassals.findIndex(x => x.name === name)
+ if (ix < 0)
+ throw "CANNOT FIND VASSAL: " + name
+ return ix
+}
+
const BOTH = "Both"
const LANCASTER = "Lancaster"
const YORK = "York"
-// TODO: "approach" pause when about to move into intercept range?
+exports.roles = [ LANCASTER, YORK ]
-var P1 = null
-var P2 = null
+const NOBODY = -1
+const NOWHERE = -1
+const NOTHING = -1
+
+const CALENDAR = 100
+
+const VASSAL_READY = 29
+const VASSAL_CALENDAR = 30
+const VASSAL_OUT_OF_PLAY = 31
+
+const SUMMER = 0
+const SPRING = 1
+const WINTER = 2
+const AUTUMN = 3
+
+const SEASONS = [
+ null,
+ WINTER,
+ SPRING,
+ SUMMER,
+ AUTUMN,
+ WINTER,
+ WINTER,
+ SPRING,
+ SUMMER,
+ AUTUMN,
+ WINTER,
+ WINTER,
+ SPRING,
+ SUMMER,
+ AUTUMN,
+ WINTER,
+ null,
+]
const INFLUENCE_TURNS = [ 1, 4, 6, 9, 11, 14 ]
const GROW_TURNS = [ 4, 9, 14 ]
@@ -18,42 +90,6 @@ const WASTE_TURNS = [ 5, 10 ]
const HIT = [ "0", "\u2776", "\u2777", "\u2778", "\u2779", "\u277A", "\u277B" ]
const MISS = [ "0", "\u2460", "\u2461", "\u2462", "\u2463", "\u2464", "\u2465" ]
-function range(x) {
- switch (x) {
- case 0: return "0"
- case 1: return "1"
- case 2: return "1-2"
- case 3: return "1-3"
- case 4: return "1-4"
- case 5: return "1-5"
- case 6: return "Automatic success"
- }
-}
-
-let game = null
-let view = null
-let states = {}
-
-exports.roles = [ LANCASTER, YORK ]
-
-exports.scenarios = [
- "Ia. Henry VI",
- "Ib. Towton",
- "Ic. Somerset's Return",
- "II. Warwicks' Rebellion",
- "III. My Kingdom for a Horse",
-// TODO "I-III. Wars of the Roses",
-]
-
-const scenario_last_turn = {
- "Ia. Henry VI": 15,
- "Ib. Towton": 2,
- "Ic. Somerset's Return": 8,
- "II. Warwicks' Rebellion": 15,
- "III. My Kingdom for a Horse": 15,
- "I-III. Wars of the Roses": 15,
-}
-
// unit types
const RETINUE = 0
const VASSAL = 1
@@ -84,34 +120,6 @@ const D1 = 3 // defenders
const D2 = 4
const D3 = 5
-function find_card(name) {
- let ix = data.cards.findIndex(x => x.name === name)
- if (ix < 0)
- throw "CANNOT FIND CARD: " + name
- return ix
-}
-
-function find_lord(name) {
- let ix = data.lords.findIndex(x => x.name === name)
- if (ix < 0)
- throw "CANNOT FIND LORD: " + name
- return ix
-}
-
-function find_locale(name) {
- let ix = data.locales.findIndex(x => x.name === name)
- if (ix < 0)
- throw "CANNOT FIND LOCALE: " + name
- return ix
-}
-
-function find_vassal(name) {
- let ix = data.vassals.findIndex(x => x.name === name)
- if (ix < 0)
- throw "CANNOT FIND VASSAL: " + name
- return ix
-}
-
const lord_name = data.lords.map(lord => lord.name)
const lord_count = data.lords.length
@@ -131,6 +139,150 @@ const last_york_card = 36
const first_lancaster_card = 37
const last_lancaster_card = 73
+function is_york_card(c) {
+ return c >= first_york_card && c <= last_york_card
+}
+
+function is_lancaster_card(c) {
+ return c >= first_lancaster_card && c <= last_lancaster_card
+}
+
+const first_york_lord = 0
+const last_york_lord = 13
+const first_lancaster_lord = 14
+const last_lancaster_lord = 27
+
+const YORK_LORD_MASK = 0x1fff
+const LANCASTER_LORD_MASK = YORK_LORD_MASK << 14
+
+function is_york_lord(lord) {
+ return lord >= first_york_lord && lord <= last_york_lord
+}
+
+function is_lancaster_lord(lord) {
+ return lord >= first_lancaster_lord && lord <= last_lancaster_lord
+}
+
+function is_marshal(lord) {
+ switch (lord) {
+ case LORD_MARGARET:
+ return true
+ case LORD_HENRY_VI:
+ return true
+ case LORD_HENRY_TUDOR:
+ return true
+ case LORD_EDWARD_IV:
+ return true
+ case LORD_GLOUCESTER_2:
+ return true
+ case LORD_RICHARD_III:
+ return true
+ case LORD_YORK:
+ return true
+ default:
+ return false
+ }
+}
+
+function is_lieutenant(lord) {
+ switch (lord) {
+ case LORD_WARWICK_L:
+ return true
+ case LORD_SOMERSET_1:
+ return true
+ case LORD_GLOUCESTER_1:
+ return true
+ case LORD_WARWICK_Y:
+ return true
+ default:
+ return false
+ }
+}
+
+function is_seaport(loc) {
+ return set_has(data.seaports, loc)
+}
+
+function is_stronghold(loc) {
+ return data.locales[loc].type !== "exile"
+}
+
+function is_exile(loc) {
+ return data.locales[loc].type === "exile"
+}
+
+function is_city(loc) {
+ return data.locales[loc].type === "city"
+}
+
+function is_town(loc) {
+ return data.locales[loc].type === "town"
+}
+
+function is_wales(loc) {
+ return data.locales[loc].region === "Wales"
+}
+
+function is_south(loc) {
+ return data.locales[loc].region === "South"
+}
+
+function is_north(loc) {
+ return data.locales[loc].region === "North"
+}
+
+function is_fortress(loc) {
+ return data.locales[loc].type === "fortress"
+}
+
+function is_sea(loc) {
+ return data.locales[loc].type === "sea"
+}
+
+function find_ports(here) {
+ if ((lord_has_capability(game.group, AOW_YORK_GREAT_SHIPS) || lord_has_capability(game.group, AOW_LANCASTER_GREAT_SHIPS)))
+ return data.all_ports
+ if (here === data.sea_1) return data.port_1
+ if (here === data.sea_2) return data.port_2
+ if (here === data.sea_3) return data.port_3
+ if (here === data.exile_1) return data.port_1
+ if (here === data.exile_2) return data.port_2
+ if (here === data.exile_3) return data.port_3
+ if (here === data.exile_4) return data.port_1
+ if (set_has(data.port_1, here)) return data.port_1
+ if (set_has(data.port_2, here)) return data.port_2
+ if (set_has(data.port_3, here)) return data.port_3
+ return null
+}
+
+function find_sail_locales(here) {
+ if (here === data.sea_1) return data.way_sea_1
+ if (here === data.sea_2) return data.way_sea_2
+ if (here === data.sea_3) return data.way_sea_3
+ if (here === data.exile_1) return data.way_exile_1
+ if (here === data.exile_2) return data.way_exile_2
+ if (here === data.exile_3) return data.way_exile_3
+ if (set_has(data.port_1, here)) return data.way_port_1
+ if (set_has(data.port_2, here)) return data.way_port_2
+ if (set_has(data.port_3, here)) return data.way_port_3
+ return null
+}
+
+function make_locale_list(pred) {
+ let list = []
+ for (let loc = first_locale; loc <= last_locale; ++loc)
+ if (pred(loc))
+ list.push(loc)
+ return list
+}
+
+const all_north_locales = make_locale_list(is_north)
+const all_south_locales = make_locale_list(is_south)
+const all_wales_locales = make_locale_list(is_wales)
+const all_city_locales = make_locale_list(is_city)
+const all_town_locales = make_locale_list(is_town)
+const all_fortress_locales = make_locale_list(is_fortress)
+
const Y1 = find_card("Y1")
const Y2 = find_card("Y2")
const Y3 = find_card("Y3")
@@ -320,16 +472,11 @@ const VASSAL_MONTAGU = find_vassal("Montagu")
const VASSAL_THOMAS_STANLEY = find_vassal("Thomas Stanley")
const VASSAL_TROLLOPE = find_vassal("Trollope")
-// === === === === FROM NEVSKY === === === ===
-
-// TODO: log end victory conditions at scenario start
-
const AOW_LANCASTER_CULVERINS_AND_FALCONETS = [L1 , L2]
const AOW_LANCASTER_MUSTERD_MY_SOLDIERS = L3
const AOW_LANCASTER_HERALDS = L4
const AOW_LANCASTER_CHURCH_BLESSINGS = L5
-const AOW_LANCASTER_GREAT_SHIPS = L6 // TODO Resolve bug about not correctly
-// targeting ports on other seats and further
+const AOW_LANCASTER_GREAT_SHIPS = L6 // TODO Resolve bug about not correctly targeting ports on other seats and further
const AOW_LANCASTER_HARBINGERS = L7
const AOW_LANCASTER_HAY_WAINS = L8
const AOW_LANCASTER_QUARTERMASTERS = L9
@@ -375,7 +522,7 @@ const AOW_YORK_YORKISTS_NEVER_WAIT = Y11
const AOW_YORK_SOLDIERS_OF_FORTUNE = Y12
const AOW_YORK_SCOURERS = Y13
const AOW_YORK_BURGUNDIANS = [ Y14, Y23 ]
-const AOW_YORK_NAVAL_BLOCKADE = Y15 // TODO DEBUG pop_state() going into parley and not after province selection
+const AOW_YORK_NAVAL_BLOCKADE = Y15 // TODO DEBUG pop_state() going into parley and not after province selection
const AOW_YORK_BELOVED_WARWICK = Y16
const AOW_YORK_ALICE_MONTAGU = Y17
const AOW_YORK_IRISHMEN = Y18
@@ -478,107 +625,95 @@ const EVENT_YORK_PRIVY_COUNCIL = Y35
const EVENT_YORK_SWIFT_MANEUVER = Y36
const EVENT_YORK_PATRICK_DE_LA_MOTE = Y37
-// Check all push/clear_undo
-// TODO : Check BUG done visible in Death of Disband despite being false
+// === STATE: ACTIVE PLAYER ===
-const NOBODY = -1
-const NOWHERE = -1
-const NOTHING = -1
+var P1 = null
+var P2 = null
-const CALENDAR = 100
+var first_friendly_lord = 0
+var last_friendly_lord = 13
+var first_enemy_lord = 14
+var last_enemy_lord = 27
-const VASSAL_READY = 29
-const VASSAL_CALENDAR = 30
-const VASSAL_OUT_OF_PLAY = 31
+function update_aliases() {
+ if (game.active === YORK) {
+ first_friendly_lord = 0
+ last_friendly_lord = 13
+ first_enemy_lord = 14
+ last_enemy_lord = 27
+ } else if (game.active === LANCASTER) {
+ first_friendly_lord = 14
+ last_friendly_lord = 27
+ first_enemy_lord = 0
+ last_enemy_lord = 13
+ } else {
+ first_friendly_lord = -1
+ last_friendly_lord = -1
+ first_enemy_lord = -1
+ last_enemy_lord = -1
+ }
+ if (game.rebel === YORK) {
+ P1 = YORK
+ P2 = LANCASTER
+ } else {
+ P1 = LANCASTER
+ P2 = YORK
+ }
+}
-const SUMMER = 0
-const SPRING = 1
-const WINTER = 2
-const AUTUMN = 3
+function load_state(state) {
+ if (game !== state) {
+ game = state
+ update_aliases()
+ }
+}
-const SEASONS = [
- null,
- WINTER,
- SPRING,
- SUMMER,
- AUTUMN,
- WINTER,
- WINTER,
- SPRING,
- SUMMER,
- AUTUMN,
- WINTER,
- WINTER,
- SPRING,
- SUMMER,
- AUTUMN,
- WINTER,
- null,
-]
+function set_active(new_active) {
+ if (game.active !== new_active) {
+ clear_undo()
+ game.active = new_active
+ update_aliases()
+ }
+}
-const TURN_NAME = [
- null,
- "1 - January/February/March",
- "2 - April/May",
- "3 - June/July",
- "4 - August/September/October",
- "5 - November/December",
- "6 - January/February/March",
- "7 - April/May",
- "8 - June/July",
- "9 - August/September/October",
- "10 - November/December",
- "11 - January/February/March",
- "12 - April/May",
- "13 - June/July",
- "14 - August/September/October",
- "15 - November/December",
- null,
-]
+function set_active_enemy() {
+ if (game.active === YORK)
+ set_active(LANCASTER)
+ else
+ set_active(YORK)
+}
-function find_ports(here) {
- if ((lord_has_capability(game.group, AOW_YORK_GREAT_SHIPS) || lord_has_capability(game.group, AOW_LANCASTER_GREAT_SHIPS)))
- return data.all_ports
- if (here === data.sea_1) return data.port_1
- if (here === data.sea_2) return data.port_2
- if (here === data.sea_3) return data.port_3
- if (here === data.exile_1) return data.port_1
- if (here === data.exile_2) return data.port_2
- if (here === data.exile_3) return data.port_3
- if (here === data.exile_4) return data.port_1
- if (set_has(data.port_1, here)) return data.port_1
- if (set_has(data.port_2, here)) return data.port_2
- if (set_has(data.port_3, here)) return data.port_3
- return null
+function set_active_command() {
+ if (is_york_lord(game.command))
+ set_active(YORK)
+ else
+ set_active(LANCASTER)
}
-function find_sail_locales(here) {
- if (here === data.sea_1) return data.way_sea_1
- if (here === data.sea_2) return data.way_sea_2
- if (here === data.sea_3) return data.way_sea_3
- if (here === data.exile_1) return data.way_exile_1
- if (here === data.exile_2) return data.way_exile_2
- if (here === data.exile_3) return data.way_exile_3
- if (set_has(data.port_1, here)) return data.way_port_1
- if (set_has(data.port_2, here)) return data.way_port_2
- if (set_has(data.port_3, here)) return data.way_port_3
- return null
+function reduce_influence(amt) {
+ if (game.active === YORK)
+ reduce_york_influence(amt)
+ else
+ reduce_lancaster_influence(amt)
}
-function make_locale_list(pred) {
- let list = []
- for (let loc = first_locale; loc <= last_locale; ++loc)
- if (pred(loc))
- list.push(loc)
- return list
+function reduce_york_influence(amt) {
+ game.influence += amt
}
-const all_north_locales = make_locale_list(is_north)
-const all_south_locales = make_locale_list(is_south)
-const all_wales_locales = make_locale_list(is_wales)
-const all_city_locales = make_locale_list(is_city)
-const all_town_locales = make_locale_list(is_town)
-const all_fortress_locales = make_locale_list(is_fortress)
+function increase_york_influence(amt) {
+ game.influence -= amt
+}
+
+function reduce_lancaster_influence(amt) {
+ game.influence -= amt
+}
+
+function increase_lancaster_influence(amt) {
+ game.influence += amt
+}
+
+// === STATE: TURN ===
function current_turn() {
return game.turn >> 1
@@ -588,114 +723,154 @@ function current_season() {
return SEASONS[game.turn >> 1]
}
+function is_campaign_phase() {
+ return (game.turn & 1) === 1
+}
+
+function is_levy_phase() {
+ return (game.turn & 1) === 0
+}
+
function current_turn_name() {
return String(game.turn >> 1)
}
+function max_plan_length() {
+ switch (current_season()) {
+ case SUMMER:
+ return 7
+ case SPRING:
+ return 6
+ case WINTER:
+ return 4
+ case AUTUMN:
+ return 6
+ }
+}
+
+// === STATE: CARDS ===
+
function current_hand() {
if (game.active === YORK)
return game.hand_y
return game.hand_l
}
-function is_campaign_phase() {
- return (game.turn & 1) === 1
+function is_friendly_card(c) {
+ if (game.active === YORK)
+ return is_york_card(c)
+ return is_lancaster_card(c)
}
-function is_levy_phase() {
- return (game.turn & 1) === 0
+function has_card_in_hand(c) {
+ if (game.active === YORK)
+ return set_has(game.hand_y, c)
+ return set_has(game.hand_l, c)
}
-// === GAME STATE ===
-
-const first_york_lord = 0
-const last_york_lord = 13
-const first_lancaster_lord = 14
-const last_lancaster_lord = 27
+function could_play_card(c) {
+ if (!game.hidden) {
+ // TODO: check capabilities on lords revealed in battle if hidden
+ if (map_has_value(game.pieces.capabilities, c))
+ return false
+ }
+ if (set_has(game.events, c))
+ return false
+ if (is_york_card(c))
+ return game.hand_y.length > 0
+ if (is_lancaster_card(c))
+ return game.hand_l.length > 0
+ return true
+}
-let first_friendly_lord = 0
-let last_friendly_lord = 13
-let first_enemy_lord = 14
-let last_enemy_lord = 27
+function count_cards_in_plan(plan, lord) {
+ let n = 0
+ for (let c of plan)
+ if (c === lord)
+ ++n
+ return n
+}
-function update_aliases() {
- if (game.active === YORK) {
- first_friendly_lord = 0
- last_friendly_lord = 13
- first_enemy_lord = 14
- last_enemy_lord = 27
- } else if (game.active === LANCASTER) {
- first_friendly_lord = 14
- last_friendly_lord = 27
- first_enemy_lord = 0
- last_enemy_lord = 13
- } else {
- first_friendly_lord = -1
- last_friendly_lord = -1
- first_enemy_lord = -1
- last_enemy_lord = -1
- }
- if (game.rebel === YORK) {
- P1 = YORK
- P2 = LANCASTER
- } else {
- P1 = LANCASTER
- P2 = YORK
- }
+function is_card_in_use(c) {
+ if (set_has(game.hand_y, c))
+ return true
+ if (set_has(game.hand_l, c))
+ return true
+ if (set_has(game.events, c))
+ return true
+ if (map_has_value(game.pieces.capabilities, c))
+ return true
+ return false
}
-function load_state(state) {
- if (game !== state) {
- game = state
- update_aliases()
- }
+function list_deck() {
+ let deck = []
+ let first_card = game.active === YORK ? first_york_card : first_lancaster_card
+ let last_card = game.active === YORK ? last_york_card : last_lancaster_card
+ for (let c = first_card; c <= last_card; ++c)
+ if (!is_card_in_use(c) && is_card_in_scenario(c))
+ deck.push(c)
+ return deck
}
-function push_state(next) {
- if (!states[next])
- throw Error("No such state: " + next)
- game.stack.push([ game.state, game.who, game.count ])
- game.state = next
+function draw_card(deck) {
+ clear_undo()
+ let i = random(deck.length)
+ let c = deck[i]
+ set_delete(deck, c)
+ return c
}
-function pop_state() {
- [ game.state, game.who, game.count ] = game.stack.pop()
+function draw_two_cards() {
+ let deck = list_deck()
+ return [ draw_card(deck), draw_card(deck) ]
}
-function set_active(new_active) {
- if (game.active !== new_active) {
- clear_undo()
- game.active = new_active
- update_aliases()
+function discard_events(when) {
+ for (let i = 0; i < game.events.length; ) {
+ let c = game.events[i]
+ if (data.cards[c].when === when)
+ array_remove(game.events, i)
+ else
+ ++i
}
}
-function set_active_enemy() {
- set_active(enemy_player())
+function discard_extra_levy_events() {
+ for (let i = 0; i < game.events.length; ) {
+ let c = game.events[i]
+ if (c === Y20)
+ array_remove(game.events, i)
+ else
+ ++i
+ }
}
-function enemy_player() {
- if (game.active === YORK)
- return LANCASTER
- if (game.active === LANCASTER)
- return YORK
- return null
+function discard_friendly_events(when) {
+ for (let i = 0; i < game.events.length; ) {
+ let c = game.events[i]
+ if (is_friendly_card(c) && data.cards[c].when === when)
+ array_remove(game.events, i)
+ else
+ ++i
+ }
}
-function has_any_spoils() {
- return game.spoils && game.spoils[PROV] + game.spoils[COIN] + game.spoils[CART] + game.spoils[SHIP] > 0
+function is_event_in_play(c) {
+ return set_has(game.events, c)
}
-function get_spoils(type) {
- if (game.spoils)
- return game.spoils[type]
- return 0
+// === STATE: LORD ===
+
+function get_lord_locale(lord) {
+ return map_get(game.pieces.locale, lord, NOWHERE)
}
-function add_spoils(type, n) {
- if (!game.spoils)
- game.spoils = [ 0, 0, 0, 0, 0, 0, 0 ]
- game.spoils[type] += n
+function set_lord_locale(lord, locale) {
+ if (locale === NOWHERE)
+ map_delete(game.pieces.locale, lord)
+ else
+ map_set(game.pieces.locale, lord, locale)
}
function get_lord_calendar(lord) {
@@ -712,10 +887,6 @@ function set_lord_calendar(lord, turn) {
set_lord_locale(lord, CALENDAR + turn)
}
-function get_lord_locale(lord) {
- return map_get(game.pieces.locale, lord, NOWHERE)
-}
-
function get_lord_capability(lord, n) {
return map2_get(game.pieces.capabilities, lord, n, NOTHING)
}
@@ -731,46 +902,6 @@ function get_lord_assets(lord, n) {
return map_get_pack4(game.pieces.assets, lord, n)
}
-function get_lord_forces(lord, n) {
- return map_get_pack4(game.pieces.forces, lord, n)
-}
-
-function get_lord_routed_forces(lord, n) {
- return map_get_pack4(game.pieces.routed, lord, n)
-}
-
-function lord_has_unrouted_units(lord) {
- for (let x = 0; x < FORCE_TYPE_COUNT; ++x)
- if (get_lord_forces(lord, x) > 0)
- return true
- let result = false
- for_each_vassal_with_lord(lord, v => {
- if (!set_has(game.battle.routed_vassals, v))
- result = true
- })
- return result
-}
-
-function rout_vassal(_lord, vassal) {
- set_add(game.battle.routed_vassals, vassal)
-}
-
-function set_lord_locale(lord, locale) {
- if (locale === NOWHERE)
- map_delete(game.pieces.locale, lord)
- else
- map_set(game.pieces.locale, lord, locale)
-}
-
-function get_force_name(lord, n, x) {
- if (n === RETINUE) {
- return `${lord_name[lord]}'s Retinue`
- } else if (n === VASSAL) {
- return `Vassal ${data.vassals[x].name}`
- }
- return FORCE_TYPE_NAME[n]
-}
-
function set_lord_assets(lord, n, x) {
if (x < 0)
x = 0
@@ -783,6 +914,18 @@ function add_lord_assets(lord, n, x) {
set_lord_assets(lord, n, get_lord_assets(lord, n) + x)
}
+function drop_prov(lord) {
+ add_lord_assets(lord, PROV, -1)
+}
+
+function drop_cart(lord) {
+ add_lord_assets(lord, CART, -1)
+}
+
+function get_lord_forces(lord, n) {
+ return map_get_pack4(game.pieces.forces, lord, n)
+}
+
function set_lord_forces(lord, n, x) {
if (x < 0)
x = 0
@@ -795,6 +938,10 @@ function add_lord_forces(lord, n, x) {
set_lord_forces(lord, n, get_lord_forces(lord, n) + x)
}
+function get_lord_routed_forces(lord, n) {
+ return map_get_pack4(game.pieces.routed, lord, n)
+}
+
function set_lord_routed_forces(lord, n, x) {
if (x < 0)
x = 0
@@ -807,10 +954,6 @@ function add_lord_routed_forces(lord, n, x) {
set_lord_routed_forces(lord, n, get_lord_routed_forces(lord, n) + x)
}
-function clear_lords_moved() {
- map_clear(game.pieces.moved)
-}
-
function get_lord_moved(lord) {
return map_get(game.pieces.moved, lord, 0)
}
@@ -819,6 +962,10 @@ function set_lord_moved(lord, x) {
map_set(game.pieces.moved, lord, x)
}
+function clear_lords_moved() {
+ map_clear(game.pieces.moved)
+}
+
function set_lord_fought(lord) {
set_lord_moved(lord, 1)
// TODO: is this needed?
@@ -849,36 +996,31 @@ function pay_lord(lord) {
set_lord_moved(lord, n)
}
-function get_lord_array_position(lord) {
- for (let p = 0; p < 12; ++p)
- if (game.battle.array[p] === lord)
- return p
- return -1
+function is_lord_on_map(lord) {
+ let loc = get_lord_locale(lord)
+ return loc !== NOWHERE && loc < CALENDAR
}
-// === GAME STATE HELPERS ===
+function is_lord_in_play(lord) {
+ return get_lord_locale(lord) !== NOWHERE
+}
-function roll_die() {
- clear_undo()
- return random(6) + 1
+function is_lord_on_calendar(lord) {
+ let loc = get_lord_locale(lord)
+ return loc >= CALENDAR
}
-function get_shared_assets(loc, what) {
- let m = 0
- let n = 0
- for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord) {
- if (get_lord_locale(lord) === loc)
- n += get_lord_assets(lord, what)
- if (game.state === "supply_source" && lord_has_capability(lord, AOW_LANCASTER_HAY_WAINS) && what === CART) {
- m = get_lord_assets(lord, CART)
- n += m
- }
- if (game.state === "supply_source" && (lord_has_capability(lord, AOW_YORK_GREAT_SHIPS) || lord_has_capability(lord, AOW_YORK_GREAT_SHIPS)) && what === SHIP) {
- m = get_lord_assets(lord, SHIP)
- n += m
- }
- }
- return n
+function is_lord_ready(lord) {
+ let loc = get_lord_locale(lord)
+ return loc >= CALENDAR && loc <= CALENDAR + (game.turn >> 1)
+}
+
+function is_friendly_lord(lord) {
+ return lord >= first_friendly_lord && lord <= last_friendly_lord
+}
+
+function is_enemy_lord(lord) {
+ return lord >= first_enemy_lord && lord <= last_enemy_lord
}
function count_lord_all_forces(lord) {
@@ -892,16 +1034,56 @@ function count_lord_all_forces(lord) {
}
function count_lord_ships(lord) {
- let ships = get_lord_assets(lord, SHIP)
- return ships
+ return get_lord_assets(lord, SHIP)
}
-function count_group_ships() {
+function count_lord_transport(lord) {
+ return get_lord_assets(lord, CART)
+}
+
+function lord_has_unrouted_units(lord) {
+ for (let x = 0; x < FORCE_TYPE_COUNT; ++x)
+ if (get_lord_forces(lord, x) > 0)
+ return true
+ let result = false
+ for_each_vassal_with_lord(lord, v => {
+ if (!set_has(game.battle.routed_vassals, v))
+ result = true
+ })
+ return result
+}
+
+function find_lord_with_capability_card(c) {
+ for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord)
+ if (lord_has_capability_card(lord, c))
+ return lord
+ return NOBODY
+}
+
+function get_force_name(lord, n, x) {
+ if (n === RETINUE)
+ return `${lord_name[lord]}'s Retinue`
+ if (n === VASSAL)
+ return `Vassal ${data.vassals[x].name}`
+ return FORCE_TYPE_NAME[n]
+}
+
+// === STATE: LORD (SHARED) ===
+
+function get_shared_assets(loc, what) {
+ let m = 0
let n = 0
- for (let lord of game.group) {
- n += count_lord_ships(lord)
- if (lord_has_capability(lord, AOW_YORK_GREAT_SHIPS) || lord_has_capability(lord, AOW_LANCASTER_GREAT_SHIPS))
- n += count_lord_ships(lord)
+ for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord) {
+ if (get_lord_locale(lord) === loc)
+ n += get_lord_assets(lord, what)
+ if (game.state === "supply_source" && lord_has_capability(lord, AOW_LANCASTER_HAY_WAINS) && what === CART) {
+ m = get_lord_assets(lord, CART)
+ n += m
+ }
+ if (game.state === "supply_source" && (lord_has_capability(lord, AOW_YORK_GREAT_SHIPS) || lord_has_capability(lord, AOW_YORK_GREAT_SHIPS)) && what === SHIP) {
+ m = get_lord_assets(lord, SHIP)
+ n += m
+ }
}
return n
}
@@ -919,8 +1101,14 @@ function count_group_assets(type, group = game.group) {
return n
}
-function count_lord_transport(lord) {
- return get_lord_assets(lord, CART)
+function count_group_ships() {
+ let n = 0
+ for (let lord of game.group) {
+ n += count_lord_ships(lord)
+ if (lord_has_capability(lord, AOW_YORK_GREAT_SHIPS) || lord_has_capability(lord, AOW_LANCASTER_GREAT_SHIPS))
+ n += count_lord_ships(lord)
+ }
+ return n
}
function count_group_transport(group = game.group) {
@@ -934,138 +1122,7 @@ function count_group_lords() {
return game.group.length
}
-function max_plan_length() {
- switch (current_season()) {
- case SUMMER:
- return 7
- case SPRING:
- return 6
- case WINTER:
- return 4
- case AUTUMN:
- return 6
- }
-}
-
-function count_cards_in_plan(plan, lord) {
- let n = 0
- for (let c of plan)
- if (c === lord)
- ++n
- return n
-}
-
-function is_marshal(lord) {
- switch (lord) {
- case LORD_MARGARET:
- return true
- case LORD_HENRY_VI:
- return true
- case LORD_HENRY_TUDOR:
- return true
- case LORD_EDWARD_IV:
- return true
- case LORD_GLOUCESTER_2:
- return true
- case LORD_RICHARD_III:
- return true
- case LORD_YORK:
- return true
- default:
- return false
- }
-}
-
-function is_lieutenant(lord) {
- switch (lord) {
- case LORD_WARWICK_L:
- return true
- case LORD_SOMERSET_1:
- return true
- case LORD_GLOUCESTER_1:
- return true
- case LORD_WARWICK_Y:
- return true
- default:
- return false
- }
-}
-
-function is_york_card(c) {
- return c >= first_york_card && c <= last_york_card
-}
-
-function is_lancaster_card(c) {
- return c >= first_lancaster_card && c <= last_lancaster_card
-}
-
-function is_card_in_use(c) {
- if (set_has(game.hand_y, c))
- return true
- if (set_has(game.hand_l, c))
- return true
- if (set_has(game.events, c))
- return true
- if (map_has_value(game.pieces.capabilities, c))
- return true
- return false
-}
-
-function is_card_in_scenario(_c) {
- // TODO: Cards setup
- return true
-}
-
-function list_deck() {
- let deck = []
- let first_card = game.active === YORK ? first_york_card : first_lancaster_card
- let last_card = game.active === YORK ? last_york_card : last_lancaster_card
- for (let c = first_card; c <= last_card; ++c)
- if (!is_card_in_use(c) && is_card_in_scenario(c))
- deck.push(c)
- return deck
-}
-
-function is_friendly_card(c) {
- if (game.active === YORK)
- return is_york_card(c)
- return is_lancaster_card(c)
-}
-
-function has_card_in_hand(c) {
- if (game.active === YORK)
- return set_has(game.hand_y, c)
- return set_has(game.hand_l, c)
-}
-
-// Used in CULVERINS AND FALCONETS
-function find_lord_with_capability_card(c) {
- for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord)
- if (lord_has_capability_card(lord, c))
- return lord
- return NOBODY
-}
-
-function is_lord_on_map(lord) {
- let loc = get_lord_locale(lord)
- return loc !== NOWHERE && loc < CALENDAR
-}
-
-function is_lord_in_play(lord) {
- return get_lord_locale(lord) !== NOWHERE
-}
-
-function is_lord_on_calendar(lord) {
- let loc = get_lord_locale(lord)
- return loc >= CALENDAR
-}
-
-function is_lord_ready(lord) {
- let loc = get_lord_locale(lord)
- return loc >= CALENDAR && loc <= CALENDAR + (game.turn >> 1)
-}
-
-// === VASSAL STATE ===
+// === STATE: VASSAL ===
function set_vassal_lord_and_service(vassal, lord, service) {
game.pieces.vassals[vassal] = lord + (service << 5)
@@ -1145,120 +1202,11 @@ function pay_vassal(vassal) {
set_vassal_lord_and_service(vassal, get_vassal_lord(vassal), current_turn() + 1)
}
-function is_york_lord(lord) {
- return lord >= first_york_lord && lord <= last_york_lord
-}
-
-function is_lancaster_lord(lord) {
- return lord >= first_lancaster_lord && lord <= last_lancaster_lord
-}
-
-function is_friendly_lord(lord) {
- return lord >= first_friendly_lord && lord <= last_friendly_lord
-}
-
-function is_enemy_lord(lord) {
- return lord >= first_enemy_lord && lord <= last_enemy_lord
-}
-
-function is_lord_at_friendly_locale(lord) {
- let loc = get_lord_locale(lord)
- return is_friendly_locale(loc)
-}
-
-function has_locale_to_muster(lord) {
- // Can muster at own seat without enemy lord.
- if (!has_enemy_lord(data.lords[lord].seat))
- return true
-
- // Else, can muster at any friendly seat (of a friendly lord who is also in play)
- for (let other = first_friendly_lord; other <= last_friendly_lord; other++)
- if (is_lord_in_play(other) && is_friendly_locale(data.lords[other].seat))
- return true
-
- // Tough luck!
- return false
-}
-
-function has_friendly_lord(loc) {
- for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord)
- if (get_lord_locale(lord) === loc)
- return true
- return false
-}
-
-function is_adjacent_friendly_port_english_channel(loc) {
- for (let next of data.locales[loc].adjacent) {
- if (is_friendly_locale(next) && data.port_2.includes(next))
- return true
- }
-}
-
-function has_enemy_lord(loc) {
- for (let lord = first_enemy_lord; lord <= last_enemy_lord; ++lord)
- if (get_lord_locale(lord) === loc)
- return true
- return false
-}
-
-function has_unbesieged_enemy_lord(loc) {
- for (let lord = first_enemy_lord; lord <= last_enemy_lord; ++lord)
- if (get_lord_locale(lord) === loc)
- return true
- return false
-}
-
-function is_seaport(loc) {
- return set_has(data.seaports, loc)
-}
-
-function is_stronghold(loc) {
- return data.locales[loc].type !== "exile"
-}
-
-function is_exile(loc) {
- return data.locales[loc].type === "exile"
-}
-
-function is_city(loc) {
- return data.locales[loc].type === "city"
-}
-
-function is_town(loc) {
- return data.locales[loc].type === "town"
-}
-
-function is_wales(loc) {
- return data.locales[loc].region === "Wales"
-}
-
-function is_south(loc) {
- return data.locales[loc].region === "South"
-}
-
-function is_north(loc) {
- return data.locales[loc].region === "North"
-}
-
-function is_lord_in_wales(lord) {
- return is_wales(get_lord_locale(lord))
-}
-
-function is_lord_in_south(lord) {
- return is_south(get_lord_locale(lord))
-}
-
-function is_lord_in_north(lord) {
- return is_north(get_lord_locale(lord))
-}
-
-function is_fortress(loc) {
- return data.locales[loc].type === "fortress"
+function rout_vassal(_lord, vassal) {
+ set_add(game.battle.routed_vassals, vassal)
}
-function is_sea(loc) {
- return data.locales[loc].type === "sea"
-}
+// === STATE: LOCALE ===
function is_favour_friendly(loc) {
if (game.active === YORK)
@@ -1298,6 +1246,44 @@ function remove_favoury_marker(loc) {
set_delete(game.pieces.favoury, loc)
}
+function shift_favour_away(loc) {
+ if (game.active === YORK)
+ shift_favour_toward_lancaster(loc)
+ else
+ shift_favour_toward_york(loc)
+}
+
+function shift_favour_toward(loc) {
+ if (game.active === YORK)
+ shift_favour_toward_york(loc)
+ else
+ shift_favour_toward_lancaster(loc)
+}
+
+function shift_favour_toward_york(loc) {
+ if (has_favourl_marker(loc))
+ remove_favourl_marker(loc)
+ else
+ add_favoury_marker(loc)
+}
+
+function shift_favour_toward_lancaster(loc) {
+ if (has_favoury_marker(loc))
+ remove_favoury_marker(loc)
+ else
+ add_favourl_marker(loc)
+}
+
+function set_favour_enemy(loc) {
+ if (game.active === YORK) {
+ remove_favoury_marker(loc)
+ add_favourl_marker(loc)
+ } else {
+ remove_favourl_marker(loc)
+ add_favoury_marker(loc)
+ }
+}
+
function has_exhausted_marker(loc) {
return set_has(game.pieces.exhausted, loc)
}
@@ -1341,1201 +1327,303 @@ function deplete_locale(loc) {
}
}
+function is_neutral_locale(loc) {
+ return !has_favourl_marker(loc) && !has_favoury_marker(loc)
+}
+
+function has_favour_in_locale(side, loc) {
+ if (side === YORK)
+ return has_favoury_marker(loc)
+ else
+ return has_favourl_marker(loc)
+}
+
function is_friendly_locale(loc) {
if (loc !== NOWHERE && loc < CALENDAR) {
if (has_enemy_lord(loc))
return false
- if (is_favour_friendly(loc)) {
+ if (is_favour_friendly(loc))
return true
- }
}
return false
}
-function can_add_troops(_lordwho, locale) {
- if (!has_exhausted_marker(locale) && !is_exile(locale))
- return true
- return false
-}
-
-function can_add_troops_coa(lordwho, locale) {
- for (let next of data.locales[locale].adjacent) {
- if (is_friendly_locale(next) && lord_has_capability(lordwho, AOW_LANCASTER_COMMISION_OF_ARRAY) && (!has_exhausted_marker(locale) && !is_exile(locale)))
+function is_adjacent_friendly_port_english_channel(loc) {
+ for (let next of data.locales[loc].adjacent) {
+ if (is_friendly_locale(next) && data.port_2.includes(next))
return true
}
- return false
}
-function can_add_troops_beloved_warwick(lordwho, locale) {
- return (
- lord_has_capability(lordwho, AOW_YORK_BELOVED_WARWICK) &&
- !has_exhausted_marker(locale) &&
- !is_exile(locale)
- )
-}
+// === STATE: LORD & LOCALE ===
-function can_add_troops_irishmen(lordwho, locale) {
- return (
- lord_has_capability(lordwho, AOW_YORK_IRISHMEN) &&
- !has_exhausted_marker(locale) &&
- (locale === LOC_IRELAND || data.port_3.includes(locale))
- )
-}
-
-function can_add_troops_sof(lordwho, locale) {
- if (
- lord_has_capability(lordwho, AOW_YORK_SOLDIERS_OF_FORTUNE) &&
- !has_exhausted_marker(locale) &&
- !is_exile(locale) &&
- get_shared_assets(locale, COIN) > 0
- ) {
- let number = 6
- for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord)
- number -= get_lord_forces(lord, MERCENARIES)
- if (number >= 1)
- return true
- }
- return false
+function is_lord_at_friendly_locale(lord) {
+ return is_friendly_locale(get_lord_locale(lord))
}
-function can_add_transport(who, what) {
- return get_lord_assets(who, what) < 100
+function is_lord_in_wales(lord) {
+ return is_wales(get_lord_locale(lord))
}
-function reduce_influence(amt) {
- if (game.active === YORK)
- reduce_york_influence(amt)
- else
- reduce_lancaster_influence(amt)
+function is_lord_in_south(lord) {
+ return is_south(get_lord_locale(lord))
}
-function reduce_york_influence(amt) {
- game.influence += amt
+function is_lord_in_north(lord) {
+ return is_north(get_lord_locale(lord))
}
-function increase_york_influence(amt) {
- game.influence -= amt
+function has_friendly_lord(loc) {
+ for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord)
+ if (get_lord_locale(lord) === loc)
+ return true
+ return false
}
-function reduce_lancaster_influence(amt) {
- game.influence -= amt
+function has_enemy_lord(loc) {
+ for (let lord = first_enemy_lord; lord <= last_enemy_lord; ++lord)
+ if (get_lord_locale(lord) === loc)
+ return true
+ return false
}
-function increase_lancaster_influence(amt) {
- game.influence += amt
+function has_unbesieged_enemy_lord(loc) {
+ for (let lord = first_enemy_lord; lord <= last_enemy_lord; ++lord)
+ if (get_lord_locale(lord) === loc)
+ return true
+ return false
}
-function shift_favour_away(loc) {
- if (game.active === YORK)
- shift_favour_toward_lancaster(loc)
- else
- shift_favour_toward_york(loc)
+function is_lord_in_or_adjacent_to_north(lord) {
+ let here = get_lord_locale(lord)
+ if (is_north(here))
+ return true
+ for (let loc of data.locales[here].adjacent)
+ if (is_north(loc))
+ return true
+ return false
}
-function shift_favour_toward(loc) {
- if (game.active === YORK)
- shift_favour_toward_york(loc)
- else
- shift_favour_toward_lancaster(loc)
+function is_lord_in_or_adjacent_to_south(lord) {
+ let here = get_lord_locale(lord)
+ if (is_south(here))
+ return true
+ for (let loc of data.locales[here].adjacent)
+ if (is_south(loc))
+ return true
+ return false
}
-function shift_favour_toward_york(loc) {
- if (has_favourl_marker(loc))
- remove_favourl_marker(loc)
- else
- add_favoury_marker(loc)
+function is_lord_in_or_adjacent_to_wales(lord) {
+ let here = get_lord_locale(lord)
+ if (is_wales(here))
+ return true
+ for (let loc of data.locales[here].adjacent)
+ if (is_wales(loc))
+ return true
+ return false
}
-function shift_favour_toward_lancaster(loc) {
- if (has_favoury_marker(loc))
- remove_favoury_marker(loc)
+// Captain capability (lieutenant/marshall only if no other)
+function other_marshal_or_lieutenant(loc) {
+ let here = loc
+ let n = 0
+ for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord)
+ if (lord !== game.command) {
+ if (get_lord_locale(lord) === here && (is_marshal(lord) || is_lieutenant(lord)))
+ n += 1
+ }
+ if (n === 0)
+ return false
else
- add_favourl_marker(loc)
+ return true
}
-function set_favour_enemy(loc) {
- if (game.active === YORK) {
- remove_favoury_marker(loc)
- add_favourl_marker(loc)
- } else {
- remove_favourl_marker(loc)
- add_favoury_marker(loc)
- }
+function has_adjacent_enemy(loc) {
+ for (let next of data.locales[loc].adjacent)
+ if (has_unbesieged_enemy_lord(next))
+ return true
+ return false
}
-// === SETUP ===
-
-function muster_lord_forces(lord) {
- let info = data.lords[lord]
- set_lord_forces(lord, RETINUE, info.forces.retinue | 0)
- set_lord_forces(lord, MEN_AT_ARMS, info.forces.men_at_arms | 0)
- set_lord_forces(lord, LONGBOWMEN, info.forces.longbowmen | 0)
- set_lord_forces(lord, MILITIA, info.forces.militia | 0)
+function has_adjacent_friendly(loc) {
+ for (let next of data.locales[loc].adjacent)
+ if (has_friendly_lord(next))
+ return true
+ return false
}
-function muster_lord(lord, locale) {
- let info = data.lords[lord]
-
- set_lord_locale(lord, locale)
-
- set_lord_assets(lord, PROV, info.assets.prov | 0)
- set_lord_assets(lord, COIN, info.assets.coin | 0)
+// === 1.4 INFLUENCE ===
- set_lord_assets(lord, CART, info.assets.cart | 0)
- set_lord_assets(lord, SHIP, info.ships | 0)
+// Bonus score but still maxed at 5
+function influence_capabilities(lord, score) {
+ let here = get_lord_locale(game.group)
+ if (game.active === YORK && is_event_in_play(EVENT_YORK_YORKIST_PARADE))
+ score += 2
+ if (game.active === YORK && is_event_in_play(EVENT_YORK_PRIVY_COUNCIL))
+ score += 1
+ if (game.state === "parley" && ((is_event_in_play(EVENT_YORK_RICHARD_OF_YORK) && game.active === YORK) || lord_has_capability(game.group, AOW_LANCASTER_IN_THE_NAME_OF_THE_KING)))
+ score += 1
+ if (get_lord_locale(LORD_MARGARET) === here && lord_has_capability(game.group, AOW_LANCASTER_LOYAL_SOMERSET))
+ score += 1
+ if (lord_has_capability(lord, AOW_YORK_YORKS_FAVOURED_SON))
+ score += 1
+ if (
+ get_lord_locale(LORD_WARWICK_L) === here &&
+ lord_has_capability(game.group, AOW_LANCASTER_MARRIED_TO_A_NEVILLE) &&
+ is_friendly_locale(here)
+ )
+ score += 2
+ if (has_favoury_marker(here) && lord_has_capability(lord, AOW_YORK_FAIR_ARBITER))
+ score += 1
+ if (lord_has_capability(lord, AOW_YORK_FALLEN_BROTHER) && !is_lord_in_play(LORD_CLARENCE))
+ score += 2
- muster_lord_forces(lord)
+ return score
}
-function draw_card(deck) {
- clear_undo()
- let i = random(deck.length)
- let c = deck[i]
- set_delete(deck, c)
- return c
-}
+// Cards that allows automatic success
+function automatic_success(lord, score) {
-function discard_events(when) {
- for (let i = 0; i < game.events.length; ) {
- let c = game.events[i]
- if (data.cards[c].when === when)
- array_remove(game.events, i)
- else
- ++i
- }
-}
+ if (lord_has_capability(lord, AOW_LANCASTER_TWO_ROSES))
+ score = 6
+ if (game.active === LANCASTER
+ && is_event_in_play(EVENT_LANCASTER_THE_EARL_OF_RICHMOND)
+ && game.state === "levy_muster_vassal")
+ score = 6
+ if (game.active === LANCASTER
+ && game.flags.parliament_votes === 1
+ && game.state === "parley")
+ score = 6
+ if (game.active === YORK
+ && game.flags.jack_cade > 0
+ && game.state === "parley")
+ score = 6
+ if (game.active === YORK
+ && game.flags.succession === 1
+ && game.state === "parley")
+ score = 6
+ if (is_campaign_phase()
+ && game.command === LORD_DEVON
+ && get_lord_locale(LORD_DEVON) === LOC_EXETER
+ && is_event_in_play(EVENT_YORK_DORSET)
+ && game.state === "parley")
+ score = 6
-function discard_extra_levy_events() {
- for (let i = 0; i < game.events.length; ) {
- let c = game.events[i]
- if (c === Y20)
- array_remove(game.events, i)
- else
- ++i
- }
+ return score
}
-function discard_friendly_events(when) {
- for (let i = 0; i < game.events.length; ) {
- let c = game.events[i]
- if (is_friendly_card(c) && data.cards[c].when === when)
- array_remove(game.events, i)
- else
- ++i
+// Initiate influence check with cards influencing the cost overriding all others
+// (even automatic at no cost)
+function init_influence_check(lord) {
+ game.check = []
+ game.check.push({ cost: 1, modifier: 0, source: "base" })
+ game.check.push({ cost: 0, modifier: data.lords[lord].influence, source: "lord" })
+ if (game.active === LANCASTER
+ && is_event_in_play(EVENT_YORK_AN_HONEST_TALE_SPEEDS_BEST)
+ && game.state === "parley"){
+ game.check.push({ cost: 1, modifier: 0, source:"An Honest tale speeds best"})
}
-}
-
-exports.setup = function (seed, scenario, options) {
- game = {
- seed,
- scenario,
- hidden: options.hidden ? 1 : 0,
-
- log: [],
- undo: [],
-
- active: null,
- rebel: null,
- state: "setup_lords",
- stack: [],
- victory_check: 0,
- influence: 0,
-
- hand_y: [],
- hand_l: [],
- plan_y: [],
- plan_l: [],
-
- turn: 0,
- events: [], // this levy/this campaign cards
-
- pieces: {
- // per lord data
- locale: [],
- assets: [],
- forces: [],
- routed: [],
- capabilities: [], // TODO map card -> lord instead of lord+slot -> card
- moved: [],
- in_exile: 0,
-
- // per vassal data
- vassals: Array(vassal_count).fill(VASSAL_OUT_OF_PLAY),
-
- // per locale data
- depleted: [],
- exhausted: [],
- favourl: [],
- favoury: [],
- propaganda: [],
- },
-
- flags: {
- first_action: 0,
- first_march_highway: 0,
- free_levy: 0,
- free_parley_henry:0,
- free_parley_gloucester:0,
- burgundians:0,
- charity:0,
- bloody:0,
- london_for_york:0,
- surprise_landing:0,
- parliament_votes:0,
- succession:0,
- jack_cade:0,
- commons_militia:0,
- swap_battle_attacker:0,
- supply_depot:0,
- loyalty_and_trust:0,
- warden_of_the_marches:0,
- naval_blockade:0
- },
-
- command: NOBODY,
- actions: 0,
- group: 0,
- intercept_group: 0,
- who: NOBODY,
- where: NOWHERE,
- what: NOTHING,
- which: NOTHING,
- count: 0,
-
- supply: 0,
- march: 0,
- battle: 0,
- spoils: 0,
- parley: 0,
+ if (game.active === LANCASTER
+ && is_event_in_play(EVENT_LANCASTER_PARLIAMENT_VOTES)
+ && game.flags.parliament_votes === 1
+ && game.state === "parley") {
+ game.check.push({ cost: -1, modifier: 0, source:"Parliament Votes"})
}
-
- log_h1(scenario)
-
- switch (scenario) {
- default:
- case "Ia. Henry VI":
- setup_Ia()
- break
- case "Ib. Towton":
- setup_Ib()
- break
- case "Ic. Somerset's Return":
- setup_Ic()
- break
- case "II. Warwicks' Rebellion":
- setup_II()
- break
- case "III. My Kingdom for a Horse":
- setup_III()
- break
- case "I-III. Wars of the Roses":
- setup_ItoIII()
- break
+ if (game.active === YORK
+ && is_event_in_play(EVENT_YORK_SUCCESSION)
+ && game.flags.succession === 1
+ && game.state === "parley") {
+ game.check.push({ cost: -1, modifier: 0, source:"Succession"})
}
-
- update_aliases()
-
- goto_setup_lords()
-
- return game
-}
-
-function setup_Ia() {
- game.turn = 1 << 1
-
- game.rebel = YORK
- game.active = YORK
- game.victory_check = 40
- game.influence = 0
- muster_lord(LORD_YORK, LOC_ELY)
- muster_lord(LORD_MARCH, LOC_LUDLOW)
- muster_lord(LORD_HENRY_VI, LOC_LONDON)
- muster_lord(LORD_SOMERSET_1, LOC_LONDON)
-
- set_lord_calendar(LORD_NORTHUMBERLAND_L, 2)
- set_lord_calendar(LORD_EXETER_1, 3)
- set_lord_calendar(LORD_BUCKINGHAM, 5)
- set_lord_calendar(LORD_SALISBURY, 2)
- set_lord_calendar(LORD_WARWICK_Y, 3)
- set_lord_calendar(LORD_RUTLAND, 5)
-
- add_favourl_marker(LOC_LONDON)
- add_favourl_marker(LOC_WELLS)
- add_favourl_marker(LOC_SCOTLAND)
- add_favourl_marker(LOC_FRANCE)
-
- add_favoury_marker(LOC_ELY)
- add_favoury_marker(LOC_LUDLOW)
- add_favoury_marker(LOC_BURGUNDY)
- add_favoury_marker(LOC_IRELAND)
-
- setup_vassals()
-}
-
-function setup_Ib() {
- game.turn = 1 << 1
-
- game.rebel = YORK
- game.active = YORK
- game.victory_check = 45
- game.influence = 0
- muster_lord(LORD_NORFOLK, LOC_LONDON)
- muster_lord(LORD_WARWICK_Y, LOC_LONDON)
- muster_lord(LORD_MARCH, LOC_LUDLOW)
- muster_lord(LORD_EXETER_1, LOC_NEWCASTLE)
- muster_lord(LORD_SOMERSET_1, LOC_NEWCASTLE)
- muster_lord(LORD_NORTHUMBERLAND_L, LOC_CARLISLE)
-
- add_favourl_marker(LOC_ST_ALBANS)
- add_favourl_marker(LOC_SCARBOROUGH)
- add_favourl_marker(LOC_NEWCASTLE)
- add_favourl_marker(LOC_BAMBURGH)
- add_favourl_marker(LOC_HEXHAM)
- add_favourl_marker(LOC_APPLEBY)
- add_favourl_marker(LOC_CARLISLE)
- add_favourl_marker(LOC_SCOTLAND)
- add_favourl_marker(LOC_FRANCE)
-
- add_favoury_marker(LOC_LONDON)
- add_favoury_marker(LOC_CALAIS)
- add_favoury_marker(LOC_GLOUCESTER)
- add_favoury_marker(LOC_HEREFORD)
- add_favoury_marker(LOC_OXFORD)
- add_favoury_marker(LOC_SALISBURY)
- add_favoury_marker(LOC_WINCHESTER)
- add_favoury_marker(LOC_GUILDFORD)
- add_favoury_marker(LOC_ARUNDEL)
- add_favoury_marker(LOC_HASTINGS)
- add_favoury_marker(LOC_DOVER)
- add_favoury_marker(LOC_ROCHESTER)
- add_favoury_marker(LOC_CANTERBURY)
- add_favoury_marker(LOC_SOUTHAMPTON)
- add_favoury_marker(LOC_BURGUNDY)
- add_favoury_marker(LOC_IRELAND)
-
- setup_vassals([ VASSAL_FAUCONBERG, VASSAL_NORFOLK ])
- muster_vassal(VASSAL_FAUCONBERG, LORD_MARCH)
-}
-
-function setup_Ic() {
- game.turn = 5 << 1
-
- game.rebel = YORK
- game.active = YORK
- game.victory_check = 40
- game.influence = 6
- muster_lord(LORD_WARWICK_Y, LOC_LONDON)
- muster_lord(LORD_MARCH, LOC_LONDON)
- muster_lord(LORD_SOMERSET_1, LOC_BAMBURGH)
-
- set_lord_calendar(LORD_HENRY_VI, 5)
-
- add_favourl_marker(LOC_SCARBOROUGH)
- add_favourl_marker(LOC_NEWCASTLE)
- add_favourl_marker(LOC_BAMBURGH)
- add_favourl_marker(LOC_HEXHAM)
- add_favourl_marker(LOC_APPLEBY)
- add_favourl_marker(LOC_CARLISLE)
- add_favourl_marker(LOC_HARLECH)
- add_favourl_marker(LOC_PEMBROKE)
- add_favourl_marker(LOC_CARDIFF)
- add_favourl_marker(LOC_CHESTER)
- add_favourl_marker(LOC_LANCASTER)
- add_favourl_marker(LOC_SCOTLAND)
- add_favourl_marker(LOC_FRANCE)
-
- add_favoury_marker(LOC_LONDON)
- add_favoury_marker(LOC_CALAIS)
- add_favoury_marker(LOC_LUDLOW)
- add_favoury_marker(LOC_HEREFORD)
- add_favoury_marker(LOC_SALISBURY)
- add_favoury_marker(LOC_WINCHESTER)
- add_favoury_marker(LOC_GUILDFORD)
- add_favoury_marker(LOC_ARUNDEL)
- add_favoury_marker(LOC_HASTINGS)
- add_favoury_marker(LOC_DOVER)
- add_favoury_marker(LOC_ROCHESTER)
- add_favoury_marker(LOC_CANTERBURY)
- add_favoury_marker(LOC_SOUTHAMPTON)
- add_favoury_marker(LOC_BURGUNDY)
- add_favoury_marker(LOC_IRELAND)
-
- setup_vassals()
-}
-
-function setup_II() {
- game.turn = 1 << 1
-
- game.rebel = LANCASTER
- game.active = LANCASTER
- game.victory_check = 40
- game.influence = 0
- muster_lord(LORD_EDWARD_IV, LOC_LONDON)
- muster_lord(LORD_PEMBROKE, LOC_PEMBROKE)
- muster_lord(LORD_WARWICK_L, LOC_CALAIS)
- muster_lord(LORD_CLARENCE, LOC_YORK)
- muster_lord(LORD_JASPER_TUDOR_1, LOC_HARLECH)
-
- set_lord_calendar(LORD_DEVON, 1)
- set_lord_calendar(LORD_GLOUCESTER_1, 9)
- set_lord_calendar(LORD_NORTHUMBERLAND_Y1, 9)
- set_lord_calendar(LORD_MARGARET, 9)
- set_lord_in_exile(LORD_MARGARET)
- set_lord_calendar(LORD_SOMERSET_2, 9)
- set_lord_in_exile(LORD_SOMERSET_2)
- set_lord_calendar(LORD_OXFORD, 9)
- set_lord_in_exile(LORD_OXFORD)
- set_lord_calendar(LORD_EXETER_2, 9)
- set_lord_in_exile(LORD_EXETER_2)
-
- add_favourl_marker(LOC_CALAIS)
- add_favourl_marker(LOC_YORK)
- add_favourl_marker(LOC_HARLECH)
- add_favourl_marker(LOC_COVENTRY)
- add_favourl_marker(LOC_WELLS)
- add_favourl_marker(LOC_FRANCE)
-
- add_favoury_marker(LOC_LONDON)
- add_favoury_marker(LOC_ELY)
- add_favoury_marker(LOC_LUDLOW)
- add_favoury_marker(LOC_CARLISLE)
- add_favoury_marker(LOC_PEMBROKE)
- add_favoury_marker(LOC_EXETER)
- add_favoury_marker(LOC_BURGUNDY)
-
- setup_vassals([ VASSAL_DEVON, VASSAL_OXFORD ])
-
- // TODO: Add Foreign Haven rule
- // TODO: Add Skaky Allies rules
}
-function setup_III() {
- game.turn = 1 << 1
-
- game.rebel = LANCASTER
- game.active = LANCASTER
- game.victory_check = 40
- game.influence = 0
- muster_lord(LORD_RICHARD_III, LOC_LONDON)
- muster_lord(LORD_NORTHUMBERLAND_Y2, LOC_CARLISLE)
- muster_lord(LORD_NORFOLK, LOC_ARUNDEL)
- muster_lord(LORD_HENRY_TUDOR, LOC_FRANCE)
- muster_lord(LORD_JASPER_TUDOR_2, LOC_FRANCE)
- muster_lord(LORD_OXFORD, LOC_FRANCE)
-
- add_favourl_marker(LOC_FRANCE)
- add_favourl_marker(LOC_OXFORD)
- add_favourl_marker(LOC_HARLECH)
- add_favourl_marker(LOC_PEMBROKE)
-
- add_favoury_marker(LOC_BURGUNDY)
- add_favoury_marker(LOC_LONDON)
- add_favoury_marker(LOC_CALAIS)
- add_favoury_marker(LOC_CARLISLE)
- add_favoury_marker(LOC_ARUNDEL)
- add_favoury_marker(LOC_YORK)
- add_favoury_marker(LOC_GLOUCESTER)
-
- setup_vassals([ VASSAL_OXFORD, VASSAL_NORFOLK ])
-}
-
-function setup_ItoIII() {
- game.turn = 1 << 1
-
- game.rebel = YORK
- game.active = YORK
- game.victory_check = 45
- game.influence = 0
- muster_lord(LORD_YORK, LOC_ELY)
- muster_lord(LORD_MARCH, LOC_LUDLOW)
- muster_lord(LORD_HENRY_VI, LOC_LONDON)
- muster_lord(LORD_SOMERSET_1, LOC_WELLS)
-
- set_lord_calendar(LORD_NORTHUMBERLAND_L, 1)
- set_lord_calendar(LORD_EXETER_1, 3)
- set_lord_calendar(LORD_BUCKINGHAM, 5)
- set_lord_calendar(LORD_SALISBURY, 2)
- set_lord_calendar(LORD_WARWICK_Y, 3)
- set_lord_calendar(LORD_RUTLAND, 5)
-
- add_favourl_marker(LOC_LONDON)
- add_favourl_marker(LOC_WELLS)
- add_favourl_marker(LOC_SCOTLAND)
- add_favourl_marker(LOC_FRANCE)
-
- add_favoury_marker(LOC_ELY)
- add_favoury_marker(LOC_LUDLOW)
- add_favoury_marker(LOC_BURGUNDY)
- add_favoury_marker(LOC_IRELAND)
-
- setup_vassals()
+function end_influence_check() {
+ game.check = 0
}
-// === CAMPAIGN GAME -- NOT IMPLEMENTED YET ===
-/*
+function count_influence_score() {
+ let score = game.check.reduce((p, c) => p + c.modifier, 0)
+ let lord = 0
+ if (is_levy_phase())
+ lord = game.who
+ if (is_campaign_phase())
+ lord = game.command
-function should_remove_Y28_event_card() {
- return game.scenario !== "I-III. Wars of the Roses"
-}
+ // Space for whose lord has been selected for SUSPICION EVENT
-function has_Y28_happened() {
- //TODO: Scenario IIY and IIL when Y28 happens.
- return false
-}
+ score = (lord, score)
-function add_card_scenario(c) {
- // TODO: Add card in scenario
-}
+ if (score > 5)
+ score = 5
+ if (score < 1)
+ score = 1
-function remove_card_scenario(c) {
- //TODO: Remove card in scenario
+ score = automatic_success(lord, score)
+ return score
}
-function setup_II_Y() {
- game.turn = 1 << 1
- game.scenario = "IIY. The Kingmaker"
- game.rebel = LANCASTER
- game.active = LANCASTER
- game.victory_check = 45
- game.influence = 0
-
- for (let lord = first_lord; lord <= last_lord; lord++) {
- if (is_lord_in_play(lord)) {
- disband_lord(lord, false)
+function count_influence_cost() {
+ if (game.state === "parley") {
+ if (is_campaign_phase()) {
+ if (game.command === LORD_DEVON && get_lord_locale(LORD_DEVON) === LOC_EXETER && is_event_in_play(EVENT_YORK_DORSET))
+ return 0
}
- }
- for (let loc = first_locale; loc <= last_locale; loc++) {
- remove_exhausted_marker(loc)
- remove_depleted_marker(loc)
- remove_favourl_marker(loc)
- remove_favoury_marker(loc)
- }
- discard_events("this_levy")
- discard_events("hold")
- discard_events("this_campaign")
-
- // Setup
- // Yorkist setup
- // TODO: Add cards Y1-Y13, Y25, Y26, Y27, Y29, Y30
-
- if (is_lord_in_play(LORD_RUTLAND) && main_york_heir !== LORD_RUTLAND) {
- muster_lord(LORD_RUTLAND, LOC_CANTERBURY)
- add_favoury_marker(LOC_CANTERBURY)
- }
-
- set_lord_calendar(LORD_DEVON, 1)
- set_lord_calendar(LORD_GLOUCESTER_1, 9)
- set_lord_calendar(LORD_NORTHUMBERLAND_Y1, 9)
-
- if (main_york_heir === LORD_YORK) {
- muster_lord(LORD_YORK, LOC_CANTERBURY)
- add_favoury_marker(LOC_LONDON)
- if (is_lord_in_play(LORD_MARCH)) {
- muster_lord(LORD_MARCH, LOC_LUDLOW)
+ if (is_levy_phase()) {
+ if (game.flags.jack_cade > 0)
+ return 0
}
- // TODO: Add cards Y14, Y18, Y19, Y20
- }
-
- if (main_york_heir === LORD_MARCH) {
- muster_lord(LORD_EDWARD_IV, LOC_LONDON)
- // Removed because he can't appear in scenario III
- disband_lord(LORD_MARCH, true)
- // TODO: Add cards Y23, Y24, Y28, Y31
- }
-
- if (main_york_heir === LORD_RUTLAND) {
- muster_lord(LORD_RUTLAND, LOC_LONDON)
- // TODO: Add cards Y20, Y21, Y28, Y35
- }
-
- // If < 2 heirs, muster Pembroke
- if ((main_york_heir === LORD_RUTLAND || main_york_heir === LORD_GLOUCESTER_1)
- || (main_york_heir === LORD_EDWARD_IV && !is_lord_in_play(LORD_RUTLAND))) {
- muster_lord(LORD_PEMBROKE, LOC_PEMBROKE)
- }
-
- // Lancaster setup
- // TODO: Add cards L1-L3, L5-L13, L23, L24, L25, L29, L30, L36
-
- if (main_lancaster_heir === LORD_HENRY_VI) {
- set_lord_calendar(LORD_HENRY_VI, 9)
- set_lord_in_exile(LORD_HENRY_VI)
- // TODO: Add L17, L18, L20, L21
- }
- if (main_lancaster_heir === LORD_MARGARET) {
- set_lord_calendar(LORD_MARGARET, 9)
- set_lord_in_exile(LORD_MARGARET)
-
- // TODO: Add L27, L28, L31 + L26 Special rule
- }
- if (main_lancaster_heir === LORD_SOMERSET_1 || main_lancaster_heir === LORD_SOMERSET_2) {
- // TODO: Add cards L20, L21, L27
- }
-
- if (is_lord_in_play(LORD_SOMERSET_1)) {
- set_lord_calendar(LORD_SOMERSET_1, 9)
- set_lord_in_exile(LORD_SOMERSET_1)
}
- else if (is_lord_in_play(LORD_SOMERSET_2)) {
- set_lord_calendar(LORD_SOMERSET_2, 9)
- set_lord_in_exile(LORD_SOMERSET_2)
- }
-
- muster_lord(LORD_WARWICK_L, LOC_CALAIS)
- muster_lord(LORD_CLARENCE, LOC_YORK)
- muster_lord(LORD_JASPER_TUDOR_1, LOC_HARLECH)
- set_lord_calendar(LORD_OXFORD, 9)
- set_lord_in_exile(LORD_OXFORD)
- set_lord_calendar(LORD_EXETER_2, 9)
- set_lord_in_exile(LORD_EXETER_2)
-
- add_favourl_marker(LOC_CALAIS)
- add_favourl_marker(LOC_YORK)
- add_favourl_marker(LOC_HARLECH)
- add_favourl_marker(LOC_COVENTRY)
- add_favourl_marker(LOC_WELLS)
-
- add_favoury_marker(LOC_LONDON)
- add_favoury_marker(LOC_ELY)
- add_favoury_marker(LOC_LUDLOW)
- add_favoury_marker(LOC_CARLISLE)
- add_favoury_marker(LOC_PEMBROKE)
- add_favoury_marker(LOC_EXETER)
-
- // Exile box setup
- add_favourl_marker(LOC_FRANCE)
- add_favoury_marker(LOC_BURGUNDY)
-
- setup_vassals([ VASSAL_DEVON, VASSAL_OXFORD ])
-
- // TODO: Add Foreign Haven rule
- // TODO: Add Skaky Allies rules
- // TODO: Natural causes rule
-
+ return game.check.reduce((p, c) => p + c.cost, 0)
}
-function setup_II_L() {
- game.turn = 1 << 1
- game.scenario = "IIL. Lancastrian Legitimacy Fades"
- game.rebel = YORK
- game.active = YORK
- game.victory_check = 40
- game.influence = 0
-
- for (let lord = first_lord; lord <= last_lord; lord++) {
- if (is_lord_in_play(lord)) {
- disband_lord(lord, false)
- }
- }
- for (let loc = first_locale; loc <= last_locale; loc++) {
- remove_exhausted_marker(loc)
- remove_depleted_marker(loc)
- remove_favourl_marker(loc)
- remove_favoury_marker(loc)
- }
- discard_events("this_levy")
- discard_events("hold")
- discard_events("this_campaign")
-
- // Setup
- // Lancaster setup
- // TODO: Add cards L1-L3, L5-L13, L18, L19, L20, L21, L25, L29, L34
-
- if (main_lancaster_heir === LORD_HENRY_VI) {
- muster_lord(LORD_HENRY_VI, LOC_LONDON)
- // TODO: Add L15, L17
- if (is_lord_in_play(LORD_SOMERSET_1)) {
- muster_lord(LORD_SOMERSET_1, LOC_WELLS)
- }
- if (is_lord_in_play(LORD_SOMERSET_2)) {
- muster_lord(LORD_SOMERSET_2, LOC_WELLS)
- }
- }
-
- if (main_lancaster_heir === LORD_MARGARET) {
- set_lord_calendar(LORD_MARGARET, 1)
- // TODO: Add L27, L31 + L26 Special rule
- if (is_lord_in_play(LORD_SOMERSET_1)) {
- muster_lord(LORD_SOMERSET_1, LOC_WELLS)
- }
- if (is_lord_in_play(LORD_SOMERSET_2)) {
- muster_lord(LORD_SOMERSET_2, LOC_WELLS)
- }
- }
- if (main_lancaster_heir === LORD_SOMERSET_1 || main_lancaster_heir === LORD_SOMERSET_2) {
- // TODO: Add cards L16, L27
- muster_lord(LORD_SOMERSET_1, LOC_LONDON)
- if (main_lancaster_heir === LORD_SOMERSET_2) {
- // Somerset 2 cylinder replaced by Somerset 1 cylinder
- disband_lord(LORD_SOMERSET_2, true)
- }
- }
-
- // Yorkist setup
- // TODO: Add cards Y1-Y13, Y15, Y16, Y17, Y22, Y28, Y29, Y31, Y34
-
- if (main_york_heir === LORD_YORK) {
- set_lord_calendar(LORD_YORK, 7)
- set_lord_in_exile(LORD_YORK)
- // TODO: Add cards Y14, Y20
- }
-
- if (main_york_heir === LORD_MARCH) {
- set_lord_calendar(LORD_MARCH, 7)
- set_lord_in_exile(LORD_MARCH)
- // TODO: Add cards Y20, 21
- }
-
- if (main_york_heir === LORD_RUTLAND) {
- set_lord_calendar(LORD_MARCH, 7)
- // TODO: Add cards Y20, Y21
- }
-
- if (main_york_heir === LORD_GLOUCESTER_1) {
- // TODO: Add cards Y25, Y30
- }
-
- if (is_lord_in_play(LORD_MARCH) && main_york_heir !== LORD_MARCH) {
- set_lord_calendar(LORD_MARCH, 7)
- set_lord_in_exile(LORD_MARCH)
- }
-
- if (is_lord_in_play(LORD_RUTLAND) && main_york_heir !== LORD_RUTLAND) {
- set_lord_calendar(LORD_RUTLAND, 7)
- set_lord_in_exile(LORD_RUTLAND)
- }
- if (is_lord_in_play(LORD_GLOUCESTER_1) && main_york_heir !== LORD_GLOUCESTER_1) {
- set_lord_calendar(LORD_GLOUCESTER_1, 7)
- set_lord_in_exile(LORD_GLOUCESTER_1)
- }
-
- muster_lord(LORD_WARWICK_Y, LOC_CALAIS)
- muster_lord(LORD_SALISBURY, LOC_YORK)
- muster_lord(LORD_PEMBROKE, LOC_PEMBROKE)
- muster_lord(LORD_JASPER_TUDOR_1, LOC_HARLECH)
- set_lord_calendar(LORD_DEVON, 1)
- set_lord_calendar(LORD_OXFORD, 2)
- set_lord_calendar(LORD_EXETER_2, 2)
- set_lord_calendar(LORD_NORTHUMBERLAND_L, 8)
-
- add_favourl_marker(LOC_LONDON)
- add_favourl_marker(LOC_HARLECH)
- add_favourl_marker(LOC_OXFORD)
- add_favourl_marker(LOC_WELLS)
- add_favourl_marker(LOC_EXETER)
- add_favourl_marker(LOC_CARLISLE)
-
- add_favoury_marker(LOC_CALAIS)
- add_favoury_marker(LOC_YORK)
- add_favoury_marker(LOC_ELY)
- add_favoury_marker(LOC_LUDLOW)
- add_favoury_marker(LOC_PEMBROKE)
-
- // Exile box setup
- add_favourl_marker(LOC_FRANCE)
- add_favoury_marker(LOC_BURGUNDY)
-
- setup_vassals([ VASSAL_DEVON, VASSAL_OXFORD ])
+function do_influence_check() {
+ reduce_influence(count_influence_cost())
+ let rating = count_influence_score()
+ let roll = roll_die()
+ let success
- // TODO: Add Foreign Haven rule
- // TODO: Add Shaky Allies rules
- // TODO: Natural causes rule
+ if (roll === 1 || rating === 6)
+ success = true
+ else if (roll === 6)
+ success = false
+ else
+ success = roll <= rating
+ // TODO: print log message here instead of returning object
+ return { success: success, rating: rating, roll: roll }
}
-function setup_III_Y() {
- game.turn = 1 << 1
- game.scenario = "IIIY. New Rivals"
- game.rebel = LANCASTER
- game.active = LANCASTER
- game.victory_check = 45
- game.influence = 0
-
- if (!is_lord_in_play(LORD_YORK)) {
- game.influence += 8
- }
- if (!is_lord_in_play(LORD_MARCH) && !is_lord_in_play(LORD_EDWARD_IV)) {
- game.influence += 8
- }
- if (!is_lord_in_play(LORD_RUTLAND)) {
- game.influence += 8
- }
- if (!is_lord_in_play(LORD_GLOUCESTER_1) && !is_lord_in_play(LORD_GLOUCESTER_2) && !is_lord_in_play(LORD_RICHARD_III)) {
- game.influence += 8
- }
- if (!is_lord_in_play(LORD_HENRY_VI)) {
- game.influence -= 8
- }
- if (!is_lord_in_play(LORD_HENRY_VI) && !is_lord_in_play(LORD_MARGARET)) {
- game.influence -= 8
- }
- if (!is_lord_in_play(LORD_SOMERSET_1)) {
- game.influence -= 8
- }
- if (!is_lord_in_play(LORD_SOMERSET_1) && !is_lord_in_play(LORD_SOMERSET_2)) {
- game.influence -= 8
- }
-
- for (let lord = first_lord; lord <= last_lord; lord++) {
- if (is_lord_in_play(lord)) {
- disband_lord(lord, false)
- }
- }
- for (let loc = first_locale; loc <= last_locale; loc++) {
- remove_exhausted_marker(loc)
- remove_depleted_marker(loc)
- remove_favourl_marker(loc)
- remove_favoury_marker(loc)
- }
- discard_events("this_levy")
- discard_events("hold")
- discard_events("this_campaign")
-
- // Yorkist Setup
- // TODO: Add Y1-Y13, Y36
-
- if (has_Y28_happened()) {
- if (is_lord_in_play(LORD_RUTLAND) && (is_lord_in_play(LORD_GLOUCESTER_1) || is_lord_in_play(LORD_GLOUCESTER_2) || is_lord_in_play(LORD_RICHARD_III))) {
- // If Gloucester (any) and Rutland, Rutland dies
- disband_lord(LORD_RUTLAND, true)
- }
- }
-
- if (main_york_heir === LORD_RUTLAND && (!is_lord_in_play(LORD_GLOUCESTER_1) && !is_lord_in_play(LORD_GLOUCESTER_2))) {
- // If Rutland is lone heir, Rutland dies
- disband_lord(LORD_RUTLAND, true)
- //Warwick becomes king
- muster_lord(LORD_WARWICK_Y, LOC_LONDON)
- add_favoury_marker(LOC_LONDON)
- muster_lord(LORD_SALISBURY, LOC_YORK)
- add_favoury_marker(LOC_YORK)
-
- // TODO: Add Y16, Y17, Y22
- }
-
- // If only 1 is alive
- if (main_york_heir === LORD_YORK && !is_lord_in_play(LORD_MARCH) && !is_lord_in_play(LORD_RUTLAND) && !is_lord_in_play(LORD_GLOUCESTER_1)) {
- muster_lord(LORD_NORTHUMBERLAND_Y2, LOC_CARLISLE)
- add_favoury_marker(LOC_CARLISLE)
-
- // TODO: Add Y37
- }
- if ((main_york_heir === LORD_MARCH || main_york_heir === LORD_EDWARD_IV) && !is_lord_in_play(LORD_RUTLAND) && !is_lord_in_play(LORD_GLOUCESTER_1)) {
- muster_lord(LORD_NORTHUMBERLAND_Y2, LOC_CARLISLE)
- add_favoury_marker(LOC_CARLISLE)
- // TODO: Add Y37
- }
- if (main_york_heir === LORD_GLOUCESTER_1 || main_york_heir === LORD_RICHARD_III) {
- muster_lord(LORD_NORTHUMBERLAND_Y2, LOC_CARLISLE)
- add_favoury_marker(LOC_CARLISLE)
- // TODO: Add Y37
- }
- muster_lord(LORD_NORFOLK, LOC_ARUNDEL)
- add_favoury_marker(LOC_ARUNDEL)
-
- if (main_york_heir === LORD_YORK) {
- // TODO: Add Y14, Y21
- if (is_lord_in_play(LORD_MARCH)) {
- muster_lord(LORD_MARCH, LOC_LUDLOW)
- add_favoury_marker(LOC_LUDLOW)
- // Add Y20
- // Only 2 heirs can stay
- disband_lord(LORD_RUTLAND, true)
- disband_lord(LORD_GLOUCESTER_1, true)
- }
- if (!is_lord_in_play(LORD_MARCH) && is_lord_in_play(LORD_RUTLAND)) {
- muster_lord(LORD_RUTLAND, LOC_CANTERBURY)
- add_favoury_marker(LOC_CANTERBURY)
- // TODO: Add Y20
- }
- if (is_lord_in_play(LORD_GLOUCESTER_1)) {
- muster_lord(LORD_GLOUCESTER_1, LOC_GLOUCESTER)
- add_favoury_marker(LOC_GLOUCESTER)
- // TODO: Y34
- }
- }
- if (main_york_heir === LORD_MARCH || main_york_heir === LORD_EDWARD_IV) {
- muster_lord(LORD_EDWARD_IV, LOC_LONDON)
- add_favoury_marker(LOC_LONDON)
-
- // If Edward IV is on the map, remove March
- disband_lord(LORD_MARCH, true)
- // TODO: Add Y23, Y24
- if (is_lord_in_play(LORD_RUTLAND)) {
- muster_lord(LORD_RUTLAND, LOC_CANTERBURY)
- add_favoury_marker(LOC_CANTERBURY)
- // TODO: Add Y31
- }
- if (is_lord_in_play(LORD_GLOUCESTER_1)) {
- muster_lord(LORD_GLOUCESTER_1, LOC_GLOUCESTER)
- add_favoury_marker(LOC_GLOUCESTER)
- // TODO: Add Y28, Y34
- }
-
- }
- if (main_york_heir === LORD_RUTLAND) {
- muster_lord(LORD_RUTLAND, LOC_LONDON)
- add_favoury_marker(LOC_LONDON)
- // TODO: Add Y20, Y21
- if (is_lord_in_play(LORD_GLOUCESTER_1)) {
- muster_lord(LORD_GLOUCESTER_2, LOC_LONDON)
- // If Rutland is King, golden gloucester 2 arrives and gloucester 1 is gone
- disband_lord(LORD_GLOUCESTER_1, true)
- // TODO: Add Y34
- }
- }
- if (main_york_heir === LORD_GLOUCESTER_1) {
- muster_lord(LORD_RICHARD_III, LOC_LONDON)
- add_favoury_marker(LOC_LONDON)
- // if Richard III is here, both gloucester are gone
- disband_lord(LORD_GLOUCESTER_1, true)
- disband_lord(LORD_GLOUCESTER_2, true)
- // TODO: Add Y32, Y33
- }
-
- // Lancaster setup
- // TODO: Add L1-L13, L34, L35, L36, L37
-
- if (main_lancaster_heir === LORD_HENRY_VI || main_lancaster_heir === LORD_MARGARET) {
- muster_lord(LORD_MARGARET, LOC_FRANCE)
- // TODO: Add L27, L31 + L26 Edward
- // Only one heir
- disband_lord(LORD_HENRY_VI, true)
- disband_lord(LORD_SOMERSET_1, true)
- disband_lord(LORD_SOMERSET_2, true)
- }
- // If Margaret not here and Edward IV not king
- if (!is_lord_on_map(LORD_MARGARET) && main_york_heir !== LORD_EDWARD_IV) {
- muster_lord(LORD_HENRY_TUDOR, LOC_FRANCE)
- // TODO: Add L32, L35
- disband_lord(LORD_SOMERSET_1, true)
- disband_lord(LORD_SOMERSET_2, true)
- }
- if (!is_lord_on_map(LORD_MARGARET) && !is_lord_on_map(LORD_HENRY_TUDOR)) {
- muster_lord(LORD_WARWICK_L, LOC_CALAIS)
- add_favourl_marker(LOC_CALAIS)
- // TODO: Add L23, L30
- }
-
- if (is_lord_on_map(LORD_MARGARET) || is_lord_on_map(LORD_HENRY_TUDOR)) {
- muster_lord(LORD_OXFORD, LOC_FRANCE)
- add_favourl_marker(LOC_OXFORD)
- muster_lord(LORD_JASPER_TUDOR_2, LOC_FRANCE)
- add_favoury_marker(LOC_PEMBROKE)
- }
- else if (is_lord_on_map(LORD_WARWICK_L)) {
- muster_lord(LORD_OXFORD, LOC_CALAIS)
- add_favourl_marker(LOC_OXFORD)
- muster_lord(LORD_JASPER_TUDOR_2, LOC_CALAIS)
- add_favoury_marker(LOC_PEMBROKE)
- }
- else {
- throw Error("Error Lancastrian setup III.Y")
- }
-
- // Exile box setup
- add_favourl_marker(LOC_FRANCE)
- add_favoury_marker(LOC_BURGUNDY)
-
- setup_vassals([ VASSAL_OXFORD, VASSAL_NORFOLK ])
+function add_influence_check_modifier_1() {
+ game.check.push({ cost: 1, modifier: 1, source: "add" })
}
-function setup_III_L() {
- game.turn = 1 << 1
- game.scenario = "IIIL. Yorkists Last Stand"
- game.rebel = YORK
- game.active = YORK
- game.victory_check = 45
- game.influence = 0
-
- if (!is_lord_in_play(LORD_YORK)) {
- game.influence += 8
- }
- if (!is_lord_in_play(LORD_MARCH) && !is_lord_in_play(LORD_EDWARD_IV)) {
- game.influence += 8
- }
- if (!is_lord_in_play(LORD_RUTLAND)) {
- game.influence += 8
- }
- if (!is_lord_in_play(LORD_GLOUCESTER_1) && !is_lord_in_play(LORD_GLOUCESTER_2) && !is_lord_in_play(LORD_RICHARD_III)) {
- game.influence += 8
- }
- if (!is_lord_in_play(LORD_HENRY_VI)) {
- game.influence -= 8
- }
- if (!is_lord_in_play(LORD_HENRY_VI) && !is_lord_in_play(LORD_MARGARET)) {
- game.influence -= 8
- }
- if (!is_lord_in_play(LORD_SOMERSET_1)) {
- game.influence -= 8
- }
- if (!is_lord_in_play(LORD_SOMERSET_1) && !is_lord_in_play(LORD_SOMERSET_2)) {
- game.influence -= 8
- }
-
- for (let lord = first_lord; lord <= last_lord; lord++) {
- if (is_lord_in_play(lord)) {
- disband_lord(lord, false)
- }
- }
- for (let loc = first_locale; loc <= last_locale; loc++) {
- remove_exhausted_marker(loc)
- remove_depleted_marker(loc)
- remove_favourl_marker(loc)
- remove_favoury_marker(loc)
- }
- discard_events("this_levy")
- discard_events("hold")
- discard_events("this_campaign")
-
- // Lancaster Setup
- // TODO: Add L1-L13, L25, L34, L36
-
- if (main_lancaster_heir === LORD_HENRY_VI) {
- muster_lord(LORD_HENRY_VI, LOC_LONDON)
- // TOOD: Add L15, L17
- }
- if (main_lancaster_heir === LORD_MARGARET) {
- muster_lord(LORD_MARGARET, LOC_LONDON)
- // TODO: Add L27, L31
- }
- if (main_lancaster_heir === LORD_SOMERSET_1) {
- muster_lord(LORD_SOMERSET_1, LOC_LONDON)
- add_favourl_marker(LOC_WELLS)
- // TODO: Add L18, L20, L27
- }
- // Should never happen but as a failsafe
- if (main_lancaster_heir === LORD_SOMERSET_2) {
- muster_lord(LORD_SOMERSET_1, LOC_LONDON)
- add_favourl_marker(LOC_WELLS)
- disband_lord(LORD_SOMERSET_2, true)
- // TODO: Add L18, L20, L27
- }
- muster_lord(LORD_OXFORD, LOC_OXFORD)
- muster_lord(LORD_JASPER_TUDOR_2, LOC_PEMBROKE)
- add_favourl_marker(LOC_OXFORD)
- add_favourl_marker(LOC_PEMBROKE)
- add_favourl_marker(LOC_LONDON)
-
- // York Setup
- // TOOD: Add Y1-Y13, Y36
-
- if (has_Y28_happened()) {
- if (is_lord_in_play(LORD_GLOUCESTER_1) || is_lord_in_play(LORD_GLOUCESTER_2) || is_lord_in_play(LORD_RICHARD_III)) {
- // If Gloucester (any), all other yorkist heir dies
- disband_lord(LORD_YORK, true)
- disband_lord(LORD_RUTLAND, true)
- disband_lord(LORD_MARCH, true)
- disband_lord(LORD_EDWARD_IV, true)
- disband_lord(LORD_GLOUCESTER_1, true)
- disband_lord(LORD_RICHARD_III, true)
- muster_lord(LORD_GLOUCESTER_2, LOC_BURGUNDY)
- // TODO: Add Y35
- }
- }
-
- if (main_york_heir === LORD_YORK) {
- muster_lord(LORD_YORK, LOC_BURGUNDY)
- add_favoury_marker(LOC_ELY)
- // TODO: Add Y14, Y18
- if (is_lord_in_play(LORD_MARCH)) {
- // Only next highest heir alive
- disband_lord(LORD_RUTLAND, true)
- disband_lord(LORD_GLOUCESTER_1, true)
- disband_lord(LORD_GLOUCESTER_2, true)
- muster_lord(LORD_MARCH, LOC_BURGUNDY)
- add_favoury_marker(LOC_LUDLOW)
- //TODO: Add Y20
- }
- else if (!is_lord_in_play(LORD_MARCH) && is_lord_in_play(LORD_RUTLAND)) {
- // Only next highest heir alive
- disband_lord(LORD_GLOUCESTER_1, true)
- disband_lord(LORD_GLOUCESTER_2, true)
- muster_lord(LORD_RUTLAND, LOC_BURGUNDY)
- add_favoury_marker(LOC_CANTERBURY)
- //TODO: Add Y20
- }
- else if (!is_lord_in_play(LORD_MARCH) && !is_lord_in_play(LORD_RUTLAND) && (is_lord_in_play(LORD_GLOUCESTER_1) || is_lord_in_play(LORD_GLOUCESTER_2))) {
- // Final Scenario, and no succession rule
- disband_lord(LORD_GLOUCESTER_2, true)
- muster_lord(LORD_GLOUCESTER_1, LOC_BURGUNDY)
- add_favoury_marker(LOC_GLOUCESTER)
- // TODO: Add Y4
- }
- else {
- // If York alone
- muster_lord(LORD_SALISBURY, LOC_BURGUNDY)
- add_favoury_marker(LOC_YORK)
- //TODO: Add Y17, Y22
- }
- }
- if (main_york_heir === LORD_MARCH || main_york_heir === LORD_RUTLAND) {
- // If March or Rutland is highest heir, Warwick takes the lead
- disband_lord(LORD_MARCH, true)
- disband_lord(LORD_RUTLAND, true)
- muster_lord(LORD_WARWICK_Y, LOC_CALAIS)
- add_favoury_marker(LOC_CALAIS)
- //TODO: Add Y16
- }
-
- if (main_york_heir === LORD_WARWICK_Y) {
- muster_lord(LORD_NORFOLK, LOC_CALAIS)
- muster_lord(LORD_SALISBURY, LOC_CALAIS)
- add_favoury_marker(LOC_CALAIS)
- //TODO: Add Y17, Y22
- }
- else (
- muster_lord(LORD_NORFOLK, LOC_BURGUNDY)
- )
-
- if (main_york_heir === LORD_GLOUCESTER_1) {
- disband_lord(LORD_GLOUCESTER_1, true)
- muster_lord(LORD_GLOUCESTER_2, LOC_BURGUNDY)
- muster_lord(LORD_SALISBURY, LOC_BURGUNDY)
- //TODO: Add Y17, Y22
- }
+function add_influence_check_modifier_2() {
+ game.check.push({ cost: 3, modifier: 2, source: "add" })
+}
- add_favoury_marker(LOC_ARUNDEL)
+function add_influence_check_distance(distance) {
+ let idx = game.check.findIndex(i => i.source === "distance")
- // Exile box setup
- add_favourl_marker(LOC_FRANCE)
- add_favoury_marker(LOC_BURGUNDY)
+ if (idx !== NOTHING)
+ game.check.splice(idx, 1)
- setup_vassals([ VASSAL_OXFORD, VASSAL_NORFOLK ])
+ game.check.push({ cost: distance, modifier: 0, source: "distance" })
}
-// FULL SCENARIO HEIR
-function get_main_york_heir() {
- if (is_lord_in_play(LORD_YORK))
- return LORD_YORK
- if (!is_lord_in_play(LORD_YORK) && is_lord_in_play(LORD_MARCH))
- return LORD_MARCH
- if (!is_lord_in_play(LORD_YORK) && !is_lord_in_play(LORD_MARCH) && is_lord_in_play(LORD_EDWARD_IV))
- return LORD_EDWARD_IV
- if (!is_lord_in_play(LORD_YORK) && !is_lord_in_play(LORD_MARCH) && !is_lord_in_play(LORD_EDWARD_IV) && is_lord_in_play(LORD_RUTLAND))
- return LORD_RUTLAND
- if (!is_lord_in_play(LORD_YORK) && !is_lord_in_play(LORD_MARCH) && !is_lord_in_play(LORD_EDWARD_IV) && !is_lord_in_play(LORD_RUTLAND) && (is_lord_in_play(LORD_GLOUCESTER_1) || is_lord_in_play(LORD_GLOUCESTER_2) || is_lord_in_play(LORD_RICHARD_III)))
- return LORD_GLOUCESTER_1
- if (!is_lord_in_play(LORD_YORK) && !is_lord_in_play(LORD_MARCH) && !is_lord_in_play(LORD_EDWARD_IV) && !is_lord_in_play(LORD_RUTLAND) && !is_lord_in_play(LORD_GLOUCESTER_1) && !is_lord_in_play(LORD_GLOUCESTER_2) && !is_lord_in_play(LORD_RICHARD_III))
- return LORD_WARWICK_Y
-}
+function prompt_influence_check() {
+ if (!game.check.some(c => c.source === "add")) {
+ view.actions.spend1 = 1
+ view.actions.spend3 = 1
+ }
+ if (game.where !== NOWHERE)
+ gen_action_locale(game.where)
+ view.actions.check = 1
-function get_main_lancaster_heir() {
- if (is_lord_in_play(LORD_HENRY_VI))
- return LORD_HENRY_VI
- if (!is_lord_in_play(LORD_HENRY_VI) && is_lord_in_play(LORD_MARGARET))
- return LORD_MARGARET
- if (!is_lord_in_play(LORD_HENRY_VI) && !is_lord_in_play(LORD_MARGARET) && is_lord_in_play(LORD_SOMERSET_1))
- return LORD_SOMERSET_1
- if (!is_lord_in_play(LORD_HENRY_VI) && !is_lord_in_play(LORD_MARGARET) && !is_lord_in_play(LORD_SOMERSET_1) && is_lord_in_play(LORD_SOMERSET_2))
- return LORD_SOMERSET_2
- if (!is_lord_in_play(LORD_HENRY_VI) && !is_lord_in_play(LORD_MARGARET) && !is_lord_in_play(LORD_SOMERSET_1) && !is_lord_in_play(LORD_SOMERSET_2) && is_lord_in_play(LORD_HENRY_TUDOR))
- return LORD_HENRY_TUDOR
- if (!is_lord_in_play(LORD_HENRY_VI) && !is_lord_in_play(LORD_MARGARET) && !is_lord_in_play(LORD_SOMERSET_1) && !is_lord_in_play(LORD_SOMERSET_2) && !is_lord_in_play(LORD_HENRY_TUDOR) && is_lord_in_play(LORD_WARWICK_L))
- return LORD_WARWICK_L
+ view.prompt += `Cost: ${count_influence_cost()} - Range (${range(count_influence_score())})`
}
-*/
+// === 2.0 SETUP ===
function goto_setup_lords() {
// setup will be used in some scenarios
@@ -2566,1969 +1654,689 @@ function end_setup_lords() {
}
}
-// === EVENTS ===
-
-function is_event_in_play(c) {
- return set_has(game.events, c)
-}
-
-function is_leeward_battle_line_in_play(lord) {
- if (is_archery_step()) {
- if (is_event_in_play(EVENT_LANCASTER_LEEWARD_BATTLE_LINE)
- && !is_event_in_play(EVENT_YORK_LEEWARD_BATTLE_LINE)
- && is_york_lord(lord)) {
- logevent(EVENT_LANCASTER_LEEWARD_BATTLE_LINE)
- return true
-
- }
- if (is_event_in_play(EVENT_YORK_LEEWARD_BATTLE_LINE)
- && !is_event_in_play(EVENT_LANCASTER_LEEWARD_BATTLE_LINE)
- && is_lancaster_lord(lord)) {
- logevent(EVENT_YORK_LEEWARD_BATTLE_LINE)
- return true
- }
+// === 3.1 LEVY: ARTS OF WAR (FIRST TURN) ===
- }
- return false
+function discard_card_capability(c) {
+ log(`${game.active} discarded C${c}.`)
}
-function is_caltrops_in_play() {
- if (game.active === YORK)
- return is_event_in_play(EVENT_YORK_CALTROPS)
+function discard_card_event(c) {
+ log(`${game.active} discarded E${c}.`)
}
-function is_regroup_in_play() {
+function goto_levy_arts_of_war_first() {
if (game.active === YORK)
- return is_event_in_play(EVENT_YORK_REGROUP)
-}
-
-function is_swift_maneuver_in_play() {
- return is_event_in_play(EVENT_YORK_SWIFT_MANEUVER)
-}
-
-function is_york_dominating_north() {
- let dom = 0
- for (let loc of all_north_locales) {
- if (has_favoury_marker(loc)) {
- dom++
- }
- }
- if (dom > 5)
- return true
-
- return false
-}
-
-function is_york_dominating_south() {
- let dom = 0
- for (let loc of all_south_locales) {
- if (has_favoury_marker(loc)) {
- dom++
- }
- }
- if (dom > 9)
- return true
- if (dom > 4
- && (lord_has_capability(LORD_MARCH, AOW_YORK_SOUTHERNERS)
- || lord_has_capability(LORD_RUTLAND, AOW_YORK_SOUTHERNERS)
- || lord_has_capability(LORD_YORK, AOW_YORK_SOUTHERNERS)))
- return true
-
- return false
-}
-
-function is_york_dominating_wales() {
- let dom = 0
- for (let loc of all_wales_locales) {
- if (has_favoury_marker(loc)) {
- dom++
- }
- }
- if (dom > 5)
- return true
- if (dom > 2
- && (lord_has_capability(LORD_MARCH, AOW_YORK_WELSHMEN)
- || lord_has_capability(LORD_YORK, AOW_YORK_WELSHMEN)))
- return true
-
- return false
-}
-
-function is_lord_in_or_adjacent_to_north(lord) {
- let here = get_lord_locale(lord)
- if (is_north(here))
- return true
- for (let loc of data.locales[here].adjacent)
- if (is_north(loc))
- return true
- return false
-}
-
-function is_lord_in_or_adjacent_to_south(lord) {
- let here = get_lord_locale(lord)
- if (is_south(here))
- return true
- for (let loc of data.locales[here].adjacent)
- if (is_south(loc))
- return true
- return false
-}
-
-function is_lord_in_or_adjacent_to_wales(lord) {
- let here = get_lord_locale(lord)
- if (is_wales(here))
- return true
- for (let loc of data.locales[here].adjacent)
- if (is_wales(loc))
- return true
- return false
-}
-
-function is_jack_cade_eligible(lord) {
- if (!is_event_in_play(EVENT_YORK_JACK_CADE))
- return false
- if (is_lord_in_or_adjacent_to_south(lord) && is_york_dominating_south())
- return true
- if (is_lord_in_or_adjacent_to_north(lord) && is_york_dominating_north())
- return true
- if (is_lord_in_or_adjacent_to_wales(lord) && is_york_dominating_wales())
- return true
- return false
-}
-
-function goto_immediate_event(c) {
- switch (c) {
- // This Levy / Campaign
- case EVENT_LANCASTER_BE_SENT_FOR:
- set_add(game.events, c)
- return end_immediate_event()
- case EVENT_LANCASTER_SEAMANSHIP:
- set_add(game.events, c)
- return end_immediate_event()
- case EVENT_LANCASTER_FORCED_MARCHES:
- set_add(game.events, c)
- return end_immediate_event()
- case EVENT_LANCASTER_RISING_WAGES:
- set_add(game.events, c)
- return end_immediate_event()
- case EVENT_LANCASTER_NEW_ACT_OF_PARLIAMENT:
- set_add(game.events, c)
- return end_immediate_event()
- case EVENT_LANCASTER_MY_CROWN_IS_IN_MY_HEART:
- set_add(game.events, c)
- return end_immediate_event()
- case EVENT_LANCASTER_PARLIAMENT_VOTES:
- set_add(game.events, c)
- return end_immediate_event()
- case EVENT_LANCASTER_FRENCH_FLEET:
- set_add(game.events, c)
- return end_immediate_event()
- case EVENT_LANCASTER_BUCKINGHAMS_PLOT:
- set_add(game.events, c)
- return end_immediate_event()
- case EVENT_LANCASTER_MARGARET_BEAUFORT:
- set_add(game.events, c)
- return end_immediate_event()
- case EVENT_LANCASTER_THE_EARL_OF_RICHMOND:
- set_add(game.events, c)
- return end_immediate_event()
-
- case EVENT_YORK_JACK_CADE:
- set_add(game.events, c)
- return end_immediate_event()
- case EVENT_YORK_SEAMANSHIP:
- set_add(game.events, c)
- return end_immediate_event()
- case EVENT_YORK_YORKISTS_BLOCK_PARLIAMENT:
- set_add(game.events, c)
- return end_immediate_event()
- case EVENT_YORK_EXILE_PACT:
- set_add(game.events, c)
- return end_immediate_event()
- case EVENT_YORK_RICHARD_OF_YORK:
- set_add(game.events, c)
- return end_immediate_event()
- case EVENT_YORK_THE_COMMONS:
- set_add(game.events, c)
- return end_immediate_event()
- case EVENT_YORK_SUCCESSION:
- set_add(game.events, c)
- return end_immediate_event()
- case EVENT_YORK_LOYALTY_AND_TRUST:
- set_add(game.events, c)
- return end_immediate_event()
- case EVENT_YORK_OWAIN_GLYNDWR:
- set_add(game.events, c)
- return end_immediate_event()
- case EVENT_YORK_GLOUCESTER_AS_HEIR:
- set_add(game.events, c)
- return end_immediate_event()
- case EVENT_YORK_DORSET:
- set_add(game.events, c)
- return end_immediate_event()
- case EVENT_YORK_THE_KINGS_NAME:
- set_add(game.events, c)
- return end_immediate_event()
- case EVENT_YORK_EDWARD_V:
- set_add(game.events, c)
- return end_immediate_event()
- case EVENT_YORK_AN_HONEST_TALE_SPEEDS_BEST:
- set_add(game.events, c)
- return end_immediate_event()
- case EVENT_YORK_PRIVY_COUNCIL:
- set_add(game.events, c)
- return end_immediate_event()
-
- // Immediate effect
- // Discard - Immediate Events
- case EVENT_LANCASTER_SCOTS:
- return goto_lancaster_event_scots()
- case EVENT_LANCASTER_HENRY_PRESSURES_PARLIAMENT:
- return goto_lancaster_event_henry_pressures_parliament()
- case EVENT_LANCASTER_HENRYS_PROCLAMATION:
- return goto_lancaster_event_henrys_proclamation()
- case EVENT_LANCASTER_FRENCH_TROOPS:
- return goto_lancaster_event_french_troops()
- case EVENT_LANCASTER_WARWICKS_PROPAGANDA:
- return goto_warwicks_propaganda()
- case EVENT_LANCASTER_WARWICKS_PROPAGANDA2:
- return goto_warwicks_propaganda()
- case EVENT_LANCASTER_WELSH_REBELLION:
- return goto_lancaster_event_welsh_rebellion()
- case EVENT_LANCASTER_HENRY_RELEASED:
- return goto_lancaster_event_henry_released()
- case EVENT_LANCASTER_LUNIVERSELLE_ARAGNE:
- return goto_lancaster_event_luniverselle_aragne()
- case EVENT_LANCASTER_TO_WILFUL_DISOBEDIANCE:
- return goto_lancaster_event_to_wilful_disobediance()
- case EVENT_LANCASTER_FRENCH_WAR_LOANS:
- return goto_lancaster_event_french_war_loans()
- case EVENT_LANCASTER_ROBINS_REBELLION:
- return goto_lancaster_event_robins_rebellion()
- case EVENT_LANCASTER_TUDOR_BANNERS:
- return goto_lancaster_event_tudor_banners()
- case EVENT_YORK_TAX_COLLECTORS:
- return goto_york_event_tax_collectors()
- case EVENT_YORK_LONDON_FOR_YORK:
- return goto_york_event_london_for_york()
- case EVENT_YORK_SHEWOLF_OF_FRANCE:
- return goto_york_event_shewolf_of_france()
- case EVENT_YORK_SIR_RICHARD_LEIGH:
- return goto_york_event_sir_richard_leigh()
- case EVENT_YORK_CHARLES_THE_BOLD:
- return goto_york_event_charles_the_bold()
- case EVENT_YORK_DUBIOUS_CLARENCE:
- return goto_dubious_clarence()
- case EVENT_YORK_YORKIST_NORTH:
- return goto_york_event_yorkist_north()
- case EVENT_YORK_EARL_RIVERS:
- return goto_york_event_earl_rivers()
- default:
- log("NOT IMPLEMENTED")
- return end_immediate_event()
- }
-}
-
-function end_immediate_event() {
- resume_levy_arts_of_war()
-}
-
-// === EVENTS: UNIQUE IMMEDIATE EVENTS ===
-
-// === EVENTS: LANCASTER SCOTS EVENT ===
-
-function goto_lancaster_event_scots() {
- game.state = "scots"
- game.count = []
- game.who = NOBODY
+ log_h2("York Arts of War")
+ else
+ log_h2("Lancaster Arts of War")
+ game.state = "levy_arts_of_war_first"
+ game.what = draw_two_cards()
}
-function end_lancaster_event_scots() {
- game.count = 0
- game.who = NOBODY
- end_immediate_event()
+function resume_levy_arts_of_war_first() {
+ if (game.what.length === 0)
+ end_levy_arts_of_war_first()
}
-states.scots = {
- inactive: "Scots",
+states.levy_arts_of_war_first = {
+ inactive: "Arts of War",
prompt() {
- view.prompt = "Scots: You may add 1 Men-at-Arms and 1 Militia to each Lord."
- for (let lord = first_lancaster_lord; lord <= last_lancaster_lord; lord++) {
- if (is_lord_on_map(lord) && map_get(game.count, lord, 0) < 3) {
+ let c = game.what[0]
+ view.arts_of_war = game.what
+ view.what = c
+ let discard = true
+ for (let lord of data.cards[c].lords) {
+ if (is_lord_on_map(lord) && !lord_already_has_capability(lord, c)) {
gen_action_lord(lord)
+ discard = false
}
}
-
- if (game.who !== NOBODY) {
- let troops = map_get(game.count, game.who, 0)
- if ((troops & 1) === 0)
- view.actions.add_militia = 1
- if ((troops & 2) === 0)
- view.actions.add_men_at_arms = 1
+ if (discard) {
+ view.prompt = `Arts of War: Discard ${data.cards[c].capability}.`
+ view.actions.discard = 1
+ } else {
+ view.prompt = `Arts of War: Assign ${data.cards[c].capability} to a Lord.`
}
- view.actions.done = 1
- },
- done() {
- end_lancaster_event_scots()
- },
- add_militia() {
- add_lord_forces(game.who, MILITIA, 1)
- let troops = map_get(game.count, game.who, 0)
- map_set(game.count, game.who, troops + 1)
- if (troops !== 0)
- game.who = NOBODY
- },
- add_men_at_arms() {
- add_lord_forces(game.who, MEN_AT_ARMS, 1)
- let troops = map_get(game.count, game.who, 0)
- map_set(game.count, game.who, troops + 2)
- if (troops !== 0)
- game.who = NOBODY
},
lord(lord) {
push_undo()
- game.who = lord
+ let c = game.what.shift()
+ log(`${game.active} deployed Capability.`)
+ add_lord_capability(lord, c)
+ capability_muster_effects(lord, c)
+ resume_levy_arts_of_war_first()
+ },
+ discard() {
+ push_undo()
+ let c = game.what.shift()
+ discard_card_capability(c)
+ resume_levy_arts_of_war_first()
},
}
-// === EVENTS: LANCASTER HENRY PRESSURES PARLIAMENT EVENT ===
-
-function goto_lancaster_event_henry_pressures_parliament() {
- let count = 0
- for (let vassal = first_vassal; vassal <= last_vassal; vassal++) {
- if (is_vassal_mustered_with_york_lord(vassal)) {
- count++
- }
- }
-
- if (count > 0) {
- logi(`Removed ${count} York influence.`)
- reduce_york_influence(count)
- }
-
- end_immediate_event()
-}
-
-// === EVENTS: LANCASTER HENRY'S PROCLAMATION EVENT ===
-
-function goto_lancaster_event_henrys_proclamation() {
- for (let vassal = first_vassal; vassal <= last_vassal; vassal++) {
- if (is_vassal_mustered_with_york_lord(vassal)) {
- set_vassal_lord_and_service(vassal, get_vassal_lord(vassal), current_turn())
- logi(`Vassal ${data.vassals[vassal].name} moved to current turn`)
-
- }
- }
- end_immediate_event()
+function end_levy_arts_of_war_first() {
+ game.what = NOTHING
+ set_active_enemy()
+ if (game.active === P2)
+ goto_levy_arts_of_war_first()
+ else
+ goto_levy_muster()
}
-// === EVENTS: LANCASTER FRENCH TROOPS EVENT ===
+// === 3.1 LEVY: ARTS OF WAR ===
-function goto_lancaster_event_french_troops() {
- let can_play = false
- for (let lord = first_friendly_lord; lord <= last_friendly_lord; lord++) {
- if (is_lord_on_map(lord) && data.seaports.includes(get_lord_locale(lord))) {
- can_play = true
- }
- }
- if (can_play) {
- game.state = "french_troops"
- game.who = NOBODY
- game.count = 0
- } else {
- end_immediate_event()
- }
+function goto_levy_arts_of_war() {
+ if (game.active === YORK)
+ log_h2("York Arts of War")
+ else
+ log_h2("Lancaster Arts of War")
+ game.what = draw_two_cards()
+ resume_levy_arts_of_war()
}
-function end_lancaster_event_french_troops() {
- game.who = NOBODY
- game.count = 0
- end_immediate_event()
+function resume_levy_arts_of_war() {
+ game.state = "levy_arts_of_war"
+ if (game.what.length === 0)
+ end_levy_arts_of_war()
}
-states.french_troops = {
- inactive: "French Troops",
+states.levy_arts_of_war = {
+ inactive: "Arts of War",
prompt() {
-
- view.prompt = `Add 2 Men at Arms and 2 Militia to a Lord at a port.`
- if (game.who === NOBODY) {
- for (let lord = first_friendly_lord; lord <= last_friendly_lord; lord++) {
- if (is_lord_on_map(lord) && is_seaport(get_lord_locale(lord))) {
- gen_action_lord(lord)
- }
- }
- } else {
- view.prompt = `Add ${2-pack2_get(game.count, 0)} Men at Arms and ${2-pack2_get(game.count, 1)} Militia to ${lord_name[game.who]}.`
- if (pack2_get(game.count, 0) < 2)
- view.actions.add_men_at_arms = 1
- if (pack2_get(game.count, 1) < 2)
- view.actions.add_militia = 1
+ let c = game.what[0]
+ view.arts_of_war = [ c ]
+ view.what = c
+ switch (data.cards[c].when) {
+ case "this_levy":
+ case "this_campaign":
+ case "now":
+ view.prompt = `Arts of War: Play ${data.cards[c].event}.`
+ view.actions.play = 1
+ break
+ case "hold":
+ view.prompt = `Arts of War: Hold ${data.cards[c].event}.`
+ view.actions.hold = 1
+ break
+ case "never":
+ view.prompt = `Arts of War: Discard ${data.cards[c].event}.`
+ view.actions.discard = 1
+ break
}
-
- view.actions.done = 1
},
- add_men_at_arms() {
- push_undo()
- add_lord_forces(game.who, MEN_AT_ARMS, 1)
- let c = pack2_get(game.count, 0)
- game.count = pack2_set(game.count, 0, c+1)
+ play() {
+ let c = game.what.shift()
+ log(`${game.active} played E${c}.`)
+ goto_immediate_event(c)
},
- add_militia() {
- push_undo()
- add_lord_forces(game.who, MILITIA, 1)
- let c = pack2_get(game.count, 1)
- game.count = pack2_set(game.count, 1, c+1)
+ hold() {
+ let c = game.what.shift()
+ log(`${game.active} Held Event.`)
+ if (game.active === YORK)
+ set_add(game.hand_y, c)
+ else
+ set_add(game.hand_l, c)
+ resume_levy_arts_of_war()
},
- lord(lord) {
- push_undo()
- game.who = lord
+ discard() {
+ let c = game.what.shift()
+ discard_card_event(c)
+ resume_levy_arts_of_war()
},
- done() {
- end_lancaster_event_french_troops()
- }
-}
-
-// === EVENTS: WARWICKS PROPAGANDA ===
-
-function add_propaganda_target(loc) {
- set_add(game.pieces.propaganda, loc)
}
-function remove_propaganda_target(loc) {
- set_delete(game.pieces.propaganda, loc)
+function end_levy_arts_of_war() {
+ game.what = NOTHING
+ set_active_enemy()
+ if (game.active === P2)
+ goto_levy_arts_of_war()
+ else
+ goto_pay()
}
-function is_propaganda_target(loc) {
- return set_has(game.pieces.propaganda, loc)
-}
+// === 3.2 LEVY: PAY ===
-function goto_warwicks_propaganda() {
- let can_play = false
- for (let loc = first_locale; loc <= last_locale; ++loc) {
- if (has_favoury_marker(loc)) {
- can_play = true
+function reset_unpaid_lords() {
+ for (let lord = first_friendly_lord; lord <= last_friendly_lord; lord++) {
+ if (is_lord_unfed(lord)) {
+ set_lord_unfed(lord, Math.ceil(count_lord_all_forces(lord) / 6))
}
}
-
- if (can_play) {
- game.state = "warwicks_propaganda"
- game.who = NOBODY
- game.count = 0
- } else {
- end_immediate_event()
- }
}
-states.warwicks_propaganda = {
- inactive: "Warwick's Propaganda",
- prompt() {
- view.prompt = `Select up to ${3-game.count} Yorkists Locales.`
- for (let loc = first_locale; loc <= last_locale; loc++) {
- if (game.count < 3 && has_favoury_marker(loc) && !is_exile(loc) && !is_propaganda_target(loc)) {
- gen_action_locale(loc)
- }
+function goto_pay() {
+ log_br()
+ let n = 0
+ for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord) {
+ let here = get_lord_locale(lord)
+ if (is_lord_on_map(lord) &&
+ !is_lord_on_calendar(lord) &&
+ lord_has_capability(lord, AOW_LANCASTER_MADAME_LA_GRANDE) &&
+ (((is_friendly_locale(here)) && data.port_2.includes(here)) ||
+ is_adjacent_friendly_port_english_channel(here))) {
+ add_lord_assets(lord, COIN, 1)
+ }
+ if (
+ game.active === LANCASTER &&
+ is_lord_on_map(lord) &&
+ lord_has_capability(LORD_NORTHUMBERLAND_L, AOW_LANCASTER_PERCYS_POWER) &&
+ is_lord_in_north(LORD_NORTHUMBERLAND_L) &&
+ is_lord_in_north(lord)
+ ) {
+ set_lord_unfed(lord, 0)
+ } else {
+ n = Math.ceil(count_lord_all_forces(lord) / 6)
+ set_lord_unfed(lord, n)
}
- view.actions.done = 1
- },
- locale(loc) {
- push_undo()
- add_propaganda_target(loc)
- game.count++
- },
- done() {
- goto_yorkist_choice()
}
+ game.state = "pay"
}
-function goto_yorkist_choice() {
- game.who = NOBODY
- set_active_enemy()
- game.state = "warwicks_propaganda_yorkist_choice"
-}
-
-states.warwicks_propaganda_yorkist_choice = {
- inactive: "Yorkists to choose to Pay or Remove favour",
+states.pay = {
+ inactive: "Pay",
prompt() {
- view.prompt = `For each Stronghold, Pay 2 influence or Remove favour.`
+ view.prompt = "Pay: You must Pay your Lord's Troops"
let done = true
- if (game.who === NOBODY) {
- for (let loc = first_locale; loc <= last_locale; loc++) {
- if (is_propaganda_target(loc)) {
- gen_action_locale(loc)
- done = false
+
+ // Pay from own mat
+ if (done) {
+ for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord) {
+ if (is_lord_unfed(lord)) {
+ if (get_lord_assets(lord, COIN) > 0) {
+ gen_action_coin(lord)
+ done = false
+ }
}
}
- if (done) {
- view.actions.done = 1
- }
- } else {
- view.actions.remove_favour = 1
- view.actions.pay = 1
}
- },
- locale(loc) {
- game.who = loc
- },
- remove_favour() {
- push_undo()
- remove_favoury_marker(game.who)
- remove_propaganda_target(game.who)
- logi(`Removed favour in ${game.who}`)
- game.who = NOBODY
- },
- pay() {
- push_undo()
- reduce_influence(2)
- logi(`Paid 2 to keep ${game.who}`)
- remove_propaganda_target(game.who)
- game.who = NOBODY
- },
- done() {
- end_warwicks_propaganda()
- },
-}
-
-function end_warwicks_propaganda() {
- game.who = NOBODY
- game.count = 0
- set_active_enemy()
- end_immediate_event()
-}
-
-// === EVENTS: WELSH REBELLION ===
-
-function goto_lancaster_event_welsh_rebellion() {
- let can_play_remove_troops = false
- let can_play_remove_favour = false
- for (let lord = first_york_lord; lord <= last_york_lord; ++lord) {
- if (is_lord_on_map(lord) && is_lord_in_wales(lord)) {
- set_lord_moved(lord, 1)
- can_play_remove_troops = true
- }
- }
- for (let loc = first_locale; loc <= last_locale; loc++) {
- if (is_wales(loc) && has_favoury_marker(loc))
- can_play_remove_favour = true
- }
-
- if (can_play_remove_troops) {
- push_state("welsh_rebellion_remove_troops")
- game.who = NOBODY
- game.count = 0
- }
- else if (can_play_remove_favour) {
- push_state("welsh_rebellion_remove_favour")
- game.who = NOBODY
- game.count = 0
- }
- else {
- end_immediate_event()
- }
-}
-states.welsh_rebellion_remove_troops = {
- inactive: "Welsh Rebellion \u2014 Remove troops",
- prompt() {
- view.prompt = `Remove 2 Troops from each enemy Lord in Wales.`
- let done = true
- if (game.who === NOBODY) {
- for (let lord = first_enemy_lord; lord <= last_enemy_lord; lord++) {
- if (is_lord_on_map(lord) && is_lord_in_wales(lord) && get_lord_moved(lord)) {
+ // Sharing
+ if (done) {
+ view.prompt = "Pay: You must Pay Lords with Shared Coin."
+ for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord) {
+ if (is_lord_unfed(lord) && can_pay_from_shared(lord)) {
gen_action_lord(lord)
done = false
}
}
- if (done) {
- view.actions.done = 1
- }
}
- else if (game.who !== NOBODY) {
- if (game.count >= 0) {
- view.prompt = `Remove ${game.count} Troops from ${data.lords[game.who].name}.`
- if (game.count === 0) {
- set_lord_moved(game.who, 0)
- view.actions.done = 1
- }
- else {
- if (get_lord_forces(game.who, BURGUNDIANS) > 0)
- gen_action_burgundians(game.who)
- if (get_lord_forces(game.who, MERCENARIES) > 0)
- gen_action_mercenaries(game.who)
- if (get_lord_forces(game.who, LONGBOWMEN) > 0)
- gen_action_longbowmen(game.who)
- if (get_lord_forces(game.who, MEN_AT_ARMS) > 0)
- gen_action_men_at_arms(game.who)
- if (get_lord_forces(game.who, MILITIA) > 0)
- gen_action_militia(game.who)
+
+ if (done) {
+ view.prompt = "Pay: You must Pillage and/or Disband."
+ for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord) {
+ if (is_lord_unfed(lord)) {
+ view.actions.pillage = 1
+ done = false
}
}
}
+
+ // All done!
+ if (done) {
+ view.prompt = "Pay: All done."
+ view.actions.end_pay = 1
+ }
+ },
+ coin(lord) {
+ push_undo()
+ add_lord_assets(lord, COIN, -1)
+ pay_lord(lord)
},
lord(lord) {
push_undo()
game.who = lord
- game.count = 2
- },
- burgundians(lord) {
- add_lord_forces(lord, BURGUNDIANS, -1)
- game.count--
- },
- mercenaries(lord) {
- add_lord_forces(lord, MERCENARIES, -1)
- game.count--
- },
- longbowmen(lord) {
- add_lord_forces(lord, LONGBOWMEN, -1)
- game.count--
- },
- men_at_arms(lord) {
- add_lord_forces(lord, MEN_AT_ARMS, -1)
- game.count--
+ game.state = "pay_lord_shared"
},
- militia(lord) {
- add_lord_forces(lord, MILITIA, -1)
- game.count--
+ pillage() {
+ push_undo()
+ reset_unpaid_lords()
+ goto_pillage_coin()
},
- done() {
- end_welsh_rebellion()
+ end_pay() {
+ end_pay()
},
+ card: action_held_event,
}
-states.welsh_rebellion_remove_favour = {
- inactive: "Welsh Rebellion \u2014 Remove Favour",
+states.pay_lord_shared = {
+ inactive: "Pay",
prompt() {
- view.prompt = `Select up to ${2-game.count} Locales in Wales.`
- for (let loc = first_locale; loc <= last_locale; loc++) {
- if (game.count < 2 && is_wales(loc) && has_favoury_marker(loc)) {
- gen_action_locale(loc)
+ view.prompt = `Pay: You must Feed ${lord_name[game.who]} with Shared Coin.`
+ let loc = get_lord_locale(game.who)
+ for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord) {
+ if (get_lord_locale(lord) === loc) {
+ if (get_lord_assets(lord, COIN) > 0)
+ gen_action_coin(lord)
}
}
- view.actions.done = 1
},
- locale(loc) {
+ coin(lord) {
push_undo()
- remove_favoury_marker(loc)
- logi(`Removed favour at ${data.locales[loc].name}`)
- game.count++
- },
- done() {
- end_immediate_event()
+ add_lord_assets(lord, COIN, -1)
+ pay_lord(game.who)
+ resume_pay_lord_shared()
},
}
-function end_welsh_rebellion() {
- for (let lord = first_york_lord; lord <= last_york_lord; ++lord) {
- if (is_lord_on_map(lord) && is_lord_in_wales(lord) && !lord_has_unrouted_units(lord))
- disband_lord(lord, false)
- }
- game.count = 0
- game.who = NOBODY
- end_immediate_event()
-}
-
-// === EVENTS: HENRY RELEASED ===
-function goto_lancaster_event_henry_released() {
- if (has_favourl_marker(LOC_LONDON)) {
- logi(`Henry Released : 5 Influence for Lancaster`)
- increase_lancaster_influence(5)
- }
- end_immediate_event()
-}
-
-// === EVENTS : L'UNIVERSELLE ARAGNE ===
-
-function goto_lancaster_event_luniverselle_aragne() {
- let can_play = false
- for (let vassal = first_vassal; vassal <= last_vassal; vassal++) {
- if (is_vassal_mustered_with_york_lord(vassal)) {
- can_play = true
- }
- }
- if (can_play) {
- game.state = "aragne"
+function resume_pay_lord_shared() {
+ if (!is_lord_unfed(game.who) || !can_pay_from_shared(game.who)) {
game.who = NOBODY
- game.count = 0
- } else {
- logi("No Effect")
- end_immediate_event()
+ game.state = "pay"
}
}
-states.aragne = {
- inactive: "L'universelle Aragne",
- prompt() {
- view.prompt = "Select up to 2 Vassals"
- if (game.who === NOBODY && game.count < 2) {
- for (let v = first_vassal; v <= last_vassal; v++) {
- if (!get_vassal_moved(v) && is_vassal_mustered_with_york_lord(v)) {
- gen_action_vassal(v)
- }
- }
- }
- view.actions.done = 1
- },
- vassal(v) {
- push_undo()
- game.who = v
- game.count++
- set_vassal_moved(v, 1)
- logi(`Vassal ${data.vassals[v].name} selected`)
- game.who = NOBODY
- },
- done() {
- goto_yorkist_aragne()
- },
-}
-
-function goto_yorkist_aragne() {
+function end_pay() {
game.who = NOBODY
set_active_enemy()
- game.state = "yorkist_aragne"
+ if (game.active === P2) {
+ goto_pay()
+ } else
+ goto_pay_lords()
}
-states.yorkist_aragne = {
- inactive: "Influence checks",
- prompt() {
- view.prompt = `For Each vassal, influence check : failure disbands it`
- let done = true
- if (game.who === NOBODY) {
- for (let v = first_vassal; v <= last_vassal; v++) {
- if (get_vassal_moved(v) && is_vassal_mustered_with_friendly_lord(v)) {
- gen_action_vassal(v)
- done = false
- }
- }
- if (done) {
- view.actions.done = 1
- }
- }
- },
- vassal(other) {
- push_undo()
- goto_aragne_save(other)
- },
- done() {
- end_universelle_aragne()
- },
-}
+// === 3.2.1 PAY TROOPS (PILLAGE) ===
-function goto_aragne_save(other) {
- game.who = other
- game.where = NOWHERE
- get_vassal_lord(other)
- init_influence_check(get_vassal_lord(other))
- game.check.push({
- cost: 0,
- modifier: data.vassals[other].influence * (game.active === LANCASTER ? -1 : 1),
- source: "vassal",
- })
- push_state("aragne_save")
+function goto_pillage_food() {
+ push_state("pillage")
+ game.what = PROV
}
-states.aragne_save = {
- inactive: `Influence check`,
- prompt() {
- view.prompt = `Influence check : Failure disbands ${data.vassals[game.who].name}`
- prompt_influence_check()
- },
- spend1: add_influence_check_modifier_1,
- spend3: add_influence_check_modifier_2,
- check() {
- let results = do_influence_check()
- logi(`Attempt to save ${data.vassals[game.who].name} ${results.success ? "Successful" : "Failed"}: (${range(results.rating)}) ${results.success ? HIT[results.roll] : MISS[results.roll]}`)
-
- if (results.success) {
- set_vassal_moved(game.who, 0)
- game.who = NOBODY
- end_influence_check()
- push_state("yorkist_aragne")
- } else {
- set_vassal_moved(game.who, 0)
- disband_vassal(game.who)
- if (game.who === VASSAL_HASTINGS) {
- discard_card_capability(AOW_YORK_HASTINGS)
- logi(`Hastings Discarded`)
- }
- game.who = NOBODY
- end_influence_check()
- push_state("yorkist_aragne")
- }
- },
+function goto_pillage_coin() {
+ push_state("pillage")
+ game.what = COIN
}
-function end_universelle_aragne() {
- game.who = NOBODY
- game.count = 0
- end_immediate_event()
+function end_pillage() {
+ pop_state()
}
-// === EVENTS : TO WILFUL DISOBEDIANCE ===
-
-function goto_lancaster_event_to_wilful_disobediance() {
- let can_play = false
- for (let loc = first_locale; loc <= last_locale; loc++){
- if (has_favoury_marker(loc) && !has_enemy_lord(loc) && !has_adjacent_enemy(loc) && (has_friendly_lord(loc) || has_adjacent_friendly(loc))) {
- can_play = true
- }
- }
- if (can_play) {
- game.state = "wilful_disobediance"
- game.who = NOBODY
- game.count = 0
- } else {
- end_immediate_event()
- logi(`No Effect`)
- }
-
-}
-states.wilful_disobediance = {
- inactive: "to wilful disobediance",
- prompt() {
- view.prompt = `Select up to ${2-game.count} Yorkists Locales.`
- for (let loc = first_locale; loc <= last_locale; loc++) {
- if (
- game.count < 2 &&
- has_favoury_marker(loc) &&
- !has_enemy_lord(loc) &&
- !has_adjacent_enemy(loc) &&
- (has_friendly_lord(loc) || has_adjacent_friendly(loc))
- ) {
- gen_action_locale(loc)
- }
- }
- view.actions.done = 1
- },
- locale(loc) {
- push_undo()
- remove_favoury_marker(loc)
- game.count++
- logi(`Favour removed at ${loc}`)
- },
- done() {
- logi(`No Effect`)
- end_immediate_event()
- }
+function can_pillage(loc) {
+ return !is_exile(loc) && !has_exhausted_marker(loc)
}
-// === EVENTS : FRENCH WAR LOANS ===
+states.pillage = {
+ inactive: "Pillage",
+ prompt() {
+ view.prompt = `Pillage: Pillage the locales where your ${game.what === PROV ? "unfed" : "unpaid"} lords are.`
-function goto_lancaster_event_french_war_loans() {
- for (let lord = first_lancaster_lord; lord <= last_lancaster_lord; ++lord) {
- if (is_lord_on_map(lord) && !is_lord_on_calendar(lord)) {
- add_lord_assets(lord, PROV, 1)
- add_lord_assets(lord, COIN, 1)
- logi(`1 Coin and 1 Provender added to ${data.lords[lord].name}`)
+ let done = true
+ for (let x = first_friendly_lord; x <= last_friendly_lord; x++) {
+ if (is_lord_on_map(x) && is_lord_unfed(x) && can_pillage(get_lord_locale(x))) {
+ gen_action_locale(get_lord_locale(x))
+ done = false
+ }
}
- }
- end_immediate_event()
-}
-
-// === EVENTS : ROBINS REBELLION ===
-function goto_lancaster_event_robins_rebellion() {
- let can_play = false
- for (let loc = first_locale; loc <= last_locale; loc++) {
- if (is_north(loc) && !has_favourl_marker(loc)) {
- can_play = true
+ if (done) {
+ view.prompt = `Pillage: Unable to Pillage, you must disband your ${game.what === PROV ? "unfed" : "unpaid"} lords.`
+ for (let x = first_friendly_lord; x <= last_friendly_lord; x++) {
+ if (is_lord_on_map(x) && is_lord_unfed(x)) {
+ gen_action_lord(x)
+ done = false
+ }
+ }
}
- }
- if (can_play) {
- game.state = "robins_rebellion"
- game.who = NOBODY
- game.count = 0
- } else {
- logi(`No Effect`)
- end_immediate_event()
- }
-}
-states.robins_rebellion = {
- inactive: "Robin's Rebellion",
- prompt() {
- view.prompt = `Select up to ${3-game.count} Locales in North.`
- for (let loc = first_locale; loc <= last_locale; loc++) {
- if (game.count < 3 && is_north(loc) && !has_favourl_marker(loc)) {
- gen_action_locale(loc)
- }
+ if (done) {
+ view.prompt = `Pillage: Done.`
+ view.actions.done = 1
}
- view.actions.done = 1
},
locale(loc) {
- push_undo()
- shift_favour_toward(loc)
- logi(`Placed/Removed favour at ${data.locales[loc].name}`)
- game.count++
+ // pillage the Locale
+ game.where = loc
+ goto_pillage_locale()
+ },
+ lord(lord) {
+ disband_influence_penalty(lord)
+ disband_lord(lord)
},
done() {
- end_immediate_event()
- }
+ end_pillage()
+ },
}
-// === EVENTS: TUDOR BANNERS ===
-
-function tudor_banner_eligible() {
- if (is_lord_on_map(LORD_HENRY_TUDOR) && !is_lord_on_calendar(LORD_HENRY_TUDOR)) {
- for (let next of data.locales[get_lord_locale(LORD_HENRY_TUDOR)].adjacent) {
- if (can_parley_at(next))
- return true
- }
- }
- else
- return false
+function goto_pillage_locale() {
+ push_state("pillage_locale")
}
-function goto_lancaster_event_tudor_banners() {
- let can_play = false
- if (tudor_banner_eligible()) {
- can_play = true
- }
- if (can_play) {
- game.state = "tudor_banners"
- game.who = NOBODY
- } else {
- logi(`No Effect`)
- end_immediate_event()
- }
+function end_pillage_locale() {
+ pop_state()
+ game.where = NOWHERE
+ end_pillage()
}
-states.tudor_banners = {
- inactive: "Tudor banners",
+states.pillage_locale = {
+ inactive: "Pillage",
prompt() {
- view.prompt = `Select locales adjacent to Henry to make them Lancastrian`
- for (let next of data.locales[get_lord_locale(LORD_HENRY_TUDOR)].adjacent) {
- if (!has_enemy_lord(next) && !has_favourl_marker(next)) {
- gen_action_locale(next)
- } else {
- view.actions.done = 1
+ view.prompt = `Pillage: Choose Lord to Pillage ${data.locales[game.where].name}.`
+
+ for (let x = first_friendly_lord; x <= last_friendly_lord; x++) {
+ if (get_lord_locale(x) === game.where && is_lord_unfed(x)) {
+ gen_action_lord(x)
}
}
},
- locale(loc) {
- push_undo()
- remove_favoury_marker(loc)
- add_favourl_marker(loc)
- logi(`Placed Lancastrian favour at ${data.locales[loc].name}`)
- },
- done() {
- end_immediate_event()
- }
-}
-// === EVENTS: TAX COLLECTORS ===
+ lord(lord) {
+ // Pillage
+ // Same values as Taxing.
+ let num = get_tax_amount(game.where)
+ add_lord_assets(lord, COIN, num)
+ add_lord_assets(lord, PROV, num)
+ reduce_influence(4 * num)
-function goto_york_event_tax_collectors() {
- game.who = NOBODY
- game.count = 0
- for (let lord = first_york_lord; lord <= last_york_lord; ++lord) {
- if (is_lord_on_map(lord) && !is_lord_on_calendar(lord)) {
- set_lord_moved(lord, 1)
- }
- }
- push_state("tax_collectors")
-}
+ add_exhausted_marker(game.where)
+ set_favour_enemy(game.where)
+ for (let next of data.locales[game.where].adjacent)
+ shift_favour_away(next)
-function can_action_tax_collectors(lord) {
- let here = get_lord_locale(lord)
- if (can_tax_collectors_at(here, lord))
- return true
- return search_tax_collectors(false, here, lord)
+ end_pillage_locale()
+ },
}
-function can_tax_collectors_at(here, lord) {
- if (is_friendly_locale(here) && !has_exhausted_marker(here)) {
- // London, Calais, and Harlech
- if (here === LOC_LONDON || here === LOC_CALAIS || here === LOC_HARLECH)
- return true
+// === 3.2.2 PAY LORDS ===
- // Own seat
- if (here === data.lords[lord].seat)
+function has_friendly_lord_who_must_pay_troops() {
+ for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord)
+ if (is_lord_unfed(lord))
return true
-
- // vassal seats
- for (let vassal = first_vassal; vassal <= last_vassal; ++vassal)
- if (is_vassal_mustered_with(vassal, lord))
- if (here === data.vassals[vassal].seat)
- return true
- }
return false
}
-function search_tax_collectors(result, start, lord) {
- let ships = get_shared_assets(start, SHIP)
-
- search_seen.fill(0)
- search_seen[start] = 1
-
- let queue = [ start ]
- while (queue.length > 0) {
- let here = queue.shift()
-
- if (is_lord_on_map(lord) && !is_lord_on_calendar(lord)) {
- if (can_tax_collectors_at(here, lord)) {
- if (result)
- set_add(result, here)
- else
- return true
- }
- }
+function goto_pay_lords() {
+ for (let lord = first_friendly_lord; lord <= last_friendly_lord; lord++) {
+ if (is_lord_on_map(lord))
+ set_lord_unfed(lord, 1)
+ }
- if (is_friendly_locale(here)) {
- for (let next of data.locales[here].adjacent) {
- if (!search_seen[next]) {
- search_seen[next] = 1
- queue.push(next)
- }
- }
- if (ships > 0 && is_seaport(here)) {
- for (let next of find_ports(here)) {
- if (!search_seen[next]) {
- search_seen[next] = 1
- queue.push(next)
- }
- }
- }
- }
+ if (has_friendly_lord_who_must_pay_troops()) {
+ game.who = NOBODY
+ game.state = "pay_lords"
+ } else {
+ end_pay_lords()
}
+}
- if (result)
- return result
+function end_pay_lords() {
+ set_active_enemy()
+
+ if (game.active === P2)
+ goto_pay_lords()
else
- return false
+ goto_pay_vassals()
}
-states.tax_collectors = {
- inactive: "Tax Collectors",
+states.pay_lords = {
+ inactive: "Pay Lords",
prompt() {
- view.prompt = "Tax Collectors : You may tax for Double coin with each lord"
- for (let lord = first_york_lord; lord <= last_york_lord; ++lord) {
- if (can_action_tax_collectors(lord) && get_lord_moved(lord)) {
- gen_action_lord(lord)
+ view.prompt = "Pay Lords in Influence or Disband them."
+ prompt_held_event()
+ let done = true
+ game.count = 0
+ if (game.who === NOBODY) {
+ for (let lord = first_friendly_lord; lord <= last_friendly_lord; lord++) {
+ if (is_lord_on_map(lord) && is_lord_unfed(lord)) {
+ gen_action_lord(lord)
+ done = false
+ }
}
- }
- view.actions.done = 1
- },
+ if (done) {
+ view.actions.done = 1
+ }
+ if (!done)
+ view.actions.pay_all = 1
+ } else {
+ view.actions.disband = 1
+ view.actions.pay = 1
+ } },
lord(lord) {
push_undo()
- game.where = NOWHERE
game.who = lord
- push_state("double_tax_collectors")
- init_influence_check(lord)
},
- done() {
- end_tax_collectors()
- },
-}
-
-states.double_tax_collectors = {
- inactive: "Tax Collectors",
- prompt() {
- view.prompt = "Tax: Select the location to tax for double."
- if (game.where === NOWHERE) {
- for (let loc of search_tax_collectors([], get_lord_locale(game.who), game.who))
- gen_action_locale(loc)
- } else {
- view.prompt = `Tax: Attempting to tax ${data.locales[game.where].name}. `
- prompt_influence_check()
- }
- },
- locale(loc) {
- game.where = loc
- if (loc === data.lords[game.who].seat) {
- // Auto succeed without influence check at Lords seat.
- deplete_locale(game.where)
-
- log(`Taxed %${game.where}.`)
- add_lord_assets(game.who, COIN, get_tax_amount(game.where)*2)
- set_lord_moved(game.who, 0)
- end_tax_lord()
- }
+ disband() {
+ push_undo()
+ disband_lord(game.who)
+ game.who = NOBODY
},
- spend1: add_influence_check_modifier_1,
- spend3: add_influence_check_modifier_2,
- check() {
- let results = do_influence_check()
- logi(`Tax : ${results.success ? "Successful" : "Failed"}: (${range(results.rating)}) ${results.success ? HIT[results.roll] : MISS[results.roll]}`)
-
- if (lord_has_capability(game.who, AOW_YORK_SO_WISE_SO_YOUNG)) {
- log(`C${AOW_YORK_SO_WISE_SO_YOUNG}.`)
- add_lord_assets(game.who, COIN, 1)
- }
-
- if (results.success) {
- deplete_locale(game.where)
- log(`Taxed %${game.where}.`)
- add_lord_assets(game.who, COIN, get_tax_amount(game.where)*2)
-
- if (
- game.command === LORD_DEVON &&
- (game.where === LOC_EXETER ||
- game.where === LOC_LAUNCESTON ||
- game.where === LOC_PLYMOUTH ||
- game.where === LOC_WELLS ||
- game.where === LOC_DORCHESTER)
- )
- add_lord_assets(game.command, COIN, 4)
- } else {
- log(`Tax of %${game.where} failed.`)
-
- }
+ pay() {
+ push_undo()
+ reduce_influence(is_exile(get_lord_locale(game.who)) ? 2 : 1)
set_lord_moved(game.who, 0)
game.who = NOBODY
- push_state("tax_collectors")
},
-}
-
-function end_tax_lord() {
- game.where = NOWHERE
- game.who = NOBODY
- pop_state()
-}
-
-function end_tax_collectors() {
- game.where = NOWHERE
- game.who = NOBODY
- game.count = 0
- end_immediate_event()
-}
-
-// === EVENTS: LONDON FOR YORK ===
-
-function goto_york_event_london_for_york() {
- let can_play = false
- if (has_favoury_marker(LOC_LONDON)) {
- can_play = true
- }
- if (can_play) {
+ pay_all() {
+ push_undo()
+ for (let lord = first_friendly_lord; lord <= last_friendly_lord; lord++) {
+ if (is_lord_on_map(lord) && is_lord_unfed(lord)) {
+ ++game.count
+ set_lord_moved(lord, 0)
+ if (is_exile(get_lord_locale(lord))) {
+ ++game.count
+ }
+ reduce_influence(game.count)
+ game.count = 0
+ }
+ }
game.who = NOBODY
- game.state = "london_for_york"
- } else {
- logi(`No Effect`)
- end_immediate_event()
- }
-}
-states.london_for_york = {
- inactive: "London For York",
- prompt() {
- view.prompt = `Select London to add a second favour marker`
- gen_action_locale(LOC_LONDON)
},
- locale(loc) {
- push_undo()
- game.flags.london_for_york = 1
- logi(`Second marker placed at ${data.locales[loc].name}`)
- logi(`Immune to Lancastrian parley unless aided by event`)
- end_immediate_event()
+ card: action_held_event,
+ done() {
+ end_pay_lords()
},
}
-function check_london_protected() {
-// TODO IF HENRY/MARGARET ARE MUSTERED IT DOES NOT CHANGE FAVOUR
-// ONLY L17/L18 and Pillage will cancel that event
-//(it is annuled when london go to neutral
- if (game.state === "pillage") {
- return false
- }
- if (game.flags.london_for_york === 1 && game.where === LOC_LONDON) {
- return true
- }
- else {
- return false
- }
-}
+// === 3.2.3 PAY VASSALS ===
-// === EVENTS: SHE-WOLF OF FRANCE ===
+function goto_pay_vassals() {
+ let vassal_to_pay = false
-function goto_york_event_shewolf_of_france() {
- let can_play = false
for (let v = first_vassal; v <= last_vassal; v++) {
- if (is_vassal_mustered_with_friendly_lord(v)) {
- set_vassal_moved(v, 1)
- can_play = true
+ if (
+ is_vassal_mustered_with_friendly_lord(v) &&
+ get_vassal_service(v) === current_turn()
+ ) {
+ vassal_to_pay = true
}
}
- if (can_play) {
- game.state = "she_wolf"
- game.who = NOBODY
+ if (vassal_to_pay) {
+ game.state = "pay_vassals"
+ game.what = NOBODY
} else {
- logi(`No Effect`)
- end_immediate_event()
+ end_pay_vassals()
}
}
-// TO TRACK VASSALS DURING EVENTS
-function get_vassal_moved(v) {
- return map_get(game.pieces.moved, v, 0)
-}
-
-function set_vassal_moved(v, x) {
- map_set(game.pieces.moved, v, x)
-}
+function end_pay_vassals() {
+ set_active_enemy()
-function pay_vassal_shewolf(vassal) {
- if (current_turn() < 16)
- set_vassal_lord_and_service(vassal, get_vassal_lord(vassal),get_vassal_service(vassal) + 1)
+ if (game.active === P1) {
+ goto_muster_exiles()
+ } else {
+ goto_pay_vassals()
+ }
}
-states.she_wolf = {
- inactive: "She-Wolf of France",
+states.pay_vassals = {
+ inactive: "Pay Vassals",
prompt() {
let done = true
- view.prompt = "You may shift your vassals one calendar box."
- if (game.who === NOBODY) {
+ view.prompt = "You may pay or disband vassals in the next calendar box."
+ if (game.what === NOBODY) {
for (let v = first_vassal; v <= last_vassal; v++) {
- if (get_vassal_moved(v) && is_vassal_mustered_with_friendly_lord(v)) {
+ if (
+ is_vassal_mustered_with_friendly_lord(v) &&
+ get_vassal_service(v) === current_turn()
+ ) {
gen_action_vassal(v)
done = false
}
}
+
if (done) {
view.actions.done = 1
}
+ if (!done)
+ view.actions.pay_all = 1
+ } else {
+ view.actions.pay = 1
+ view.actions.disband = 1
}
},
vassal(v) {
push_undo()
- game.who = v
- pay_vassal_shewolf(game.who)
- set_vassal_moved(v, 0)
- logi(`Vassal ${data.vassals[v].name} shifted one calendar box`)
- game.who = NOBODY
- },
- done() {
- end_immediate_event()
- },
-}
-
-// === EVENTS : RICHARD LEIGH ===
-function goto_york_event_sir_richard_leigh() {
- let can_play = false
- if (!has_favoury_marker(LOC_LONDON)) {
- can_play = true
- }
- if (can_play) {
- game.state = "richard_leigh"
- game.who = LOC_LONDON
- game.count = 0
- } else {
- logi(`No Effect`)
- end_immediate_event()
- }
-}
-
-states.richard_leigh = {
- inactive: "Richard Leigh",
- prompt() {
- view.prompt = `Select London, shift it once in your favour`
- if (game.who === LOC_LONDON && !has_favoury_marker(LOC_LONDON)) {
- gen_action_locale(LOC_LONDON)
- } else {
- view.actions.done = 1
- }
+ game.what = v
},
- locale(loc) {
+ pay() {
push_undo()
- shift_favour_toward(loc)
- logi(`London shifted once in your favour`)
- game.who = NOBODY
- },
- done() {
- end_immediate_event()
- }
-}
-
-// === EVENTS: CHARLES THE BOLD ===
-
-function goto_york_event_charles_the_bold() {
- for (let lord = first_york_lord; lord <= last_york_lord; ++lord) {
- if (is_lord_on_map(lord) && !is_lord_on_calendar(lord)) {
- add_lord_assets(lord, PROV, 1)
- add_lord_assets(lord, COIN, 1)
- logi(`1 Coin and 1 Provender added to ${data.lords[lord].name}`)
- }
- }
- end_immediate_event()
-}
-
-// === EVENTS: DUBIOUS CLARENCE ===
-
-function goto_dubious_clarence() {
- let can_play = false
- if ((is_lord_on_map(LORD_EDWARD_IV) && !is_lord_on_calendar(LORD_EDWARD_IV))
- && is_lord_on_map(LORD_CLARENCE) && !is_lord_on_calendar(LORD_CLARENCE))
- can_play = true
-
- if (can_play) {
- game.state = "dubious_clarence"
- game.who = LORD_EDWARD_IV
- init_influence_check(LORD_EDWARD_IV)
- } else {
- logi(`No Effect`)
- end_immediate_event()
- }
-}
-
-states.dubious_clarence = {
- inactive: "Dubious Clarence",
- prompt() {
- view.prompt = `You may Influence check with Edward to disband Clarence `
- prompt_influence_check()
- },
- spend1: add_influence_check_modifier_1,
- spend3: add_influence_check_modifier_2,
- check() {
- let results = do_influence_check()
- log(`Attempt to disband Clarence ${results.success ? "Successful" : "Failed"}: (${range(results.rating)}) ${results.success ? HIT[results.roll] : MISS[results.roll]}`)
-
- if (results.success) {
- disband_lord(LORD_CLARENCE, false)
- end_immediate_event()
- } else {
- end_immediate_event()
- }
+ pay_vassal(game.what)
+ reduce_influence(1)
+ game.what = NOBODY
},
-}
-
-// === EVENTS: YORKIST NORTH ===
-
-function goto_york_event_yorkist_north() {
- let influence_gained = 0
- for (let lord = first_york_lord; lord <= last_york_lord; ++lord) {
- if (is_lord_on_map(lord) && !is_lord_on_calendar(lord) && is_lord_in_north(lord))
- influence_gained++
- }
- for (let loc = first_locale; loc <= last_locale; loc++) {
- if (loc !== NOWHERE && loc < CALENDAR && has_favoury_marker(loc) && is_north(loc)) {
- influence_gained++
- }
- }
- logi(`Yorkist North : ${influence_gained} Influence for Yorkists`)
- increase_york_influence(influence_gained)
- end_immediate_event()
-}
-
-// === EARL RIVERS ===
-
-function goto_york_event_earl_rivers() {
- game.state = "earl_rivers"
- game.count = []
- game.who = NOBODY
-}
-
-function end_york_event_earl_rivers() {
- game.count = 0
- game.who = NOBODY
- end_immediate_event()
-}
-
-states.earl_rivers = {
- inactive: "Earl Rivers",
- prompt() {
- view.prompt = "Earl Rivers: Add up to 2 Militia to each lord"
- view.actions.done = 1
- for (let lord = first_york_lord; lord <= last_york_lord; lord++) {
- if (is_lord_on_map(lord) && map_get(game.count, lord, 0) < 3) {
- gen_action_lord(lord)
+ pay_all() {
+ push_undo()
+ for (let v = first_vassal; v <= last_vassal; v++) {
+ if (is_vassal_mustered_with_friendly_lord(v)
+ && get_vassal_service(v) === current_turn()) {
+ pay_vassal(v)
+ reduce_influence(1)
+ game.what = NOBODY
}
}
-
- if (game.who !== NOBODY) {
- let troops = map_get(game.count, game.who, 0)
- if ((troops & 1) === 0)
- view.actions.add_militia = 1
- }
- if (game.who !== NOBODY) {
- let troops = map_get(game.count, game.who, 0)
- if ((troops & 1) === 0)
- view.actions.add_militia2 = 1
- }
- },
- done() {
- end_york_event_earl_rivers()
},
- add_militia() {
+ disband() {
push_undo()
- add_lord_forces(game.who, MILITIA, 1)
- let troops = map_get(game.count, game.who, 0)
- map_set(game.count, game.who, troops + 1)
- if (troops > 1)
- game.who = NOBODY
+ disband_vassal(game.what)
+ game.what = NOBODY
},
- add_militia2() {
- push_undo()
- add_lord_forces(game.who, MILITIA, 2)
- let troops = map_get(game.count, game.who, 0)
- map_set(game.count, game.who, troops + 1)
- if (troops > 1)
- game.who = NOBODY
+ done() {
+ end_pay_vassals()
},
- lord(lord) {
- push_undo()
- game.who = lord
- }
}
-// === EVENTS: SHIFT LORD OR SERVICE (IMMEDIATE) ===
-/*
-function prompt_shift_lord_on_calendar(boxes) {
- if (game.who !== NOBODY) {
- // Shift in direction beneficial to active player.
- if (is_friendly_lord(game.who)) {
- if (is_lord_on_calendar(game.who))
- gen_action_calendar(get_lord_calendar(game.who) - boxes)
- else
- gen_action_calendar(get_lord_calendar(game.who) + boxes)
- } else {
- if (is_lord_on_calendar(game.who))
- gen_action_calendar(get_lord_calendar(game.who) + boxes)
- else
- gen_action_calendar(get_lord_calendar(game.who) - boxes)
- }
- }
-}
-*/
-// === EVENTS: HOLD ===
+// === 3.2.4 DISBAND ===
-function play_held_event(c) {
- log(`Played E${c}.`)
- if (c >= first_york_card && c <= last_york_card)
- set_delete(game.hand_y, c)
- else
- set_delete(game.hand_l, c)
+function disband_lord(lord, permanently = false) {
+ let turn = current_turn()
+ let extra = 6
- /* Hold events with This Levy/Campaign */
- if (
- c === EVENT_YORK_YORKIST_PARADE ||
- c === EVENT_YORK_PARLIAMENTS_TRUCE ||
- c === EVENT_LANCASTER_PARLIAMENTS_TRUCE
- ) {
- set_add(game.events, c)
+ if (permanently) {
+ log(`Removed L${lord}.`)
+ set_lord_locale(lord, NOWHERE)
+ } else if (lord_has_capability(lord, AOW_YORK_ENGLAND_IS_MY_HOME)) {
+ set_lord_calendar(lord, turn + (extra - data.lords[lord].influence))
+ log(`Disbanded L${lord} to turn ${current_turn() + 1}.`)
}
-}
-
-// TODO: use or remove this function
-function end_held_event() {
- pop_state()
- game.what = NOTHING
-}
-
-function prompt_held_event() {
- for (let c of current_hand())
- if (can_play_held_event(c))
- gen_action_card(c)
-}
-
-function prompt_held_event_intercept() {
- for (let c of current_hand())
- if (can_play_held_event_intercept(c))
- gen_action_card(c)
-}
-
-function can_play_held_event(c) {
- switch (c) {
- case EVENT_LANCASTER_ASPIELLES:
- return can_play_l_aspielles()
- case EVENT_LANCASTER_REBEL_SUPPLY_DEPOT:
- return can_play_rebel_supply_depot()
- case EVENT_LANCASTER_SURPRISE_LANDING:
- return can_play_surprise_landing()
- case EVENT_LANCASTER_PARLIAMENTS_TRUCE:
- return can_play_parliaments_truce()
- case EVENT_YORK_PARLIAMENTS_TRUCE:
- return can_play_parliaments_truce()
- case EVENT_YORK_ASPIELLES:
- return can_play_y_aspielles()
- case EVENT_YORK_YORKIST_PARADE:
- return can_play_yorkist_parade()
- case EVENT_YORK_SUN_IN_SPLENDOUR:
- return can_play_sun_in_splendour()
+ else {
+ set_lord_calendar(lord, turn + (extra - data.lords[lord].influence))
+ log(`Disbanded L${lord} to turn ${get_lord_calendar(lord)}.`)
}
- return false
-}
-function can_play_held_event_intercept(c) {
- switch (c) {
- case EVENT_LANCASTER_FLANK_ATTACK:
- return can_play_flank_attack()
- case EVENT_YORK_FLANK_ATTACK:
- return can_play_flank_attack()
- }
- return false
-}
+ discard_lord_capability_n(lord, 0)
+ discard_lord_capability_n(lord, 1)
-function action_held_event(c) {
- push_undo()
- play_held_event(c)
- game.what = c
- goto_held_event(c)
-}
+ for (let x = 0; x < ASSET_TYPE_COUNT; ++x)
+ set_lord_assets(lord, x, 0)
-function goto_held_event(c) {
- switch (c) {
- case EVENT_YORK_ESCAPE_SHIP:
- goto_play_escape_ship()
- break
- case EVENT_YORK_ASPIELLES:
- goto_play_aspielles()
- break
- case EVENT_LANCASTER_ESCAPE_SHIP:
- // TODO?
- break
- case EVENT_LANCASTER_TALBOT_TO_THE_RESCUE:
- // TODO?
- break
- case EVENT_LANCASTER_WARDEN_OF_THE_MARCHES:
- goto_play_warden_of_the_marches()
- break
- case EVENT_LANCASTER_REBEL_SUPPLY_DEPOT:
- goto_rebel_supply_depot()
- break
- case EVENT_LANCASTER_SURPRISE_LANDING:
- goto_play_surprise_landing()
- break
- case EVENT_LANCASTER_ASPIELLES:
- goto_play_aspielles()
- break
- case EVENT_YORK_SUN_IN_SPLENDOUR:
- goto_play_sun_in_splendour()
- break
+ for (let x = 0; x < FORCE_TYPE_COUNT; ++x) {
+ set_lord_forces(lord, x, 0)
+ if (get_lord_routed_forces(lord, x) > 0) {
+ set_lord_routed_forces(lord, x, 0)
+ }
}
-}
-
-// === EVENTS: HOLD - UNIQUE ===
-function can_play_l_aspielles() {
- if (game.hand_y.length > 0 || game.hidden) {
- return true
- }
- return false
-}
+ set_lord_moved(lord, 0)
-function can_play_y_aspielles() {
- if (game.hand_l.length > 0 || game.hidden) {
- return true
- }
- return false
+ for_each_vassal_with_lord(lord, v => {
+ disband_vassal(v)
+ })
}
-function can_play_parliaments_truce() {
- return game.state === "campaign"
-}
+// === 3.3.1 MUSTER EXILES ===
-function can_play_rebel_supply_depot() {
- if (game.active === YORK)
- return false
- if (game.group) {
- for (let lord of game.group) {
- if (get_lord_moved(lord) && is_seaport(get_lord_locale(game.command))) {
- return true
- }
+function goto_muster_exiles() {
+ for (let x = first_friendly_lord; x <= last_friendly_lord; x++) {
+ if ((get_lord_locale(x) === current_turn() + CALENDAR && get_lord_in_exile(x))
+ || (is_lancaster_lord(x) && is_lord_on_calendar((get_lord_locale(x)) && get_lord_in_exile(x) && is_event_in_play(EVENT_LANCASTER_BE_SENT_FOR)))) {
+ game.state = "muster_exiles"
+ return
}
}
- return false
-}
-
-function can_play_surprise_landing() {
- let here = get_lord_locale(game.command)
- if (game.flags.surprise_landing === 0 || !is_seaport(here) || here === LOC_CALAIS || here === LOC_PEMBROKE || here === LOC_HARLECH || here === LANCASTER || is_sea(here))
- return false
- return true
+ end_muster_exiles()
}
-function can_play_yorkist_parade() {
- if (game.active === YORK && is_favour_friendly(LOC_LONDON) && (get_lord_locale(LORD_WARWICK_Y) === LOC_LONDON || get_lord_locale(LORD_YORK) === LOC_LONDON)) {
- return true
- }
- return false
-}
+function end_muster_exiles() {
+ set_active_enemy()
-function can_play_sun_in_splendour() {
- if (is_levy_phase() && is_lord_on_calendar(LORD_EDWARD_IV)) {
- return true
+ if (game.active === P1) {
+ if (!check_disband_victory()) {
+ goto_ready_vassals()
+ }
+ } else {
+ goto_muster_exiles()
}
- return false
-}
-
-function can_play_flank_attack() {
- return game.state === "intercept" && game.who !== NOBODY && !is_truce_in_effect()
-}
-
-// === EVENTS : HOLD - SUN IN SPLENDOUR
-
-function goto_play_sun_in_splendour() {
- push_state("sun_in_splendour")
}
-states.sun_in_splendour = {
- inactive: "Sun in splendour",
+states.muster_exiles = {
+ inactive: "Muster Exiles",
prompt() {
+ view.prompt = "Muster Exiled Lords."
let done = true
- view.prompt = "Sun in Splendour: Muster Edward IV in any friendly locale with no enemy lord"
- if (is_lord_on_calendar(LORD_EDWARD_IV)) {
- for (let loc = first_locale; loc <= last_locale; loc++) {
- if (is_friendly_locale(loc)) {
+
+ if (game.who === NOBODY) {
+ for (let x = first_friendly_lord; x <= last_friendly_lord; x++) {
+ if ((get_lord_locale(x) === current_turn() + CALENDAR && get_lord_in_exile(x))
+ || (is_lancaster_lord(x) && is_lord_on_calendar((get_lord_locale(x)) && get_lord_in_exile(x) && is_event_in_play(EVENT_LANCASTER_BE_SENT_FOR)))) {
+ gen_action_lord(x)
done = false
- gen_action_locale(loc)
}
}
- }
- if (done) {
- view.actions.done = 1
- }
- },
- locale(loc) {
- push_undo()
- muster_lord(LORD_EDWARD_IV, loc)
- logi(`Mustered Edward IV at ${data.locales[loc].name}`)
- },
- done() {
- end_sun_in_splendour()
- },
-}
-
-function end_sun_in_splendour() {
- game.who = NOBODY
- pop_state()
-}
-
-// === EVENTS : HOLD - REBEL SUPPLY DEPOT ===
-
-function goto_rebel_supply_depot() {
- game.flags.supply_depot = 1
- add_spoils(PROV, 4)
- push_state("rebel_supply_depot")
-}
-
-states.rebel_supply_depot = {
- inactive: "Rebel Supply depot",
- prompt() {
- if (has_any_spoils()) {
- view.prompt = "Divide " + list_spoils() + "."
- let here = get_lord_locale(game.command)
- for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord) {
- if (get_lord_locale(lord) === here)
- prompt_select_lord(lord)
- if (game.who !== NOBODY)
- prompt_spoils()
- }
} else {
- view.prompt = "Rebel Supply Depot: All done."
- view.actions.end_spoils = 1
+ for (let loc of data.exile_boxes)
+ if (has_favour_in_locale(game.active, loc))
+ gen_action_locale(loc)
}
- },
- lord: action_select_lord,
- take_prov() {
- push_undo_without_who()
- take_spoils(PROV)
- },
- end_spoils() {
- end_rebel_supply_depot()
- },
-}
-
-function end_rebel_supply_depot() {
- game.who = NOBODY
- game.spoils = 0
- resume_command()
-}
-// === EVENTS: HOLD - ASPIELLES ===
-
-function goto_play_aspielles() {
- push_state("aspielles")
- game.who = NOBODY
-}
-
-states.aspielles = {
- inactive: "Aspielles",
- prompt() {
- view.prompt = "Aspielles: You may see enemy held cards"
- if (game.hidden) {
- view.prompt += " and an enemy lord to see his mat"
- }
- prompt_held_event()
- if (game.hidden) {
- for (let lord = first_enemy_lord; lord <= last_enemy_lord; ++lord)
- gen_action_lord(lord)
- }
- if (game.active === YORK) {
- view.hand = game.hand_l
- log("Lancaster hand shown to the York player")
- }
- if (game.active === LANCASTER) {
- view.hand = game.hand_y
- log("York hand shown to the Lancaster player")
+ if (done) {
+ view.actions.done = true
}
- view.actions.done = 1
-
},
lord(lord) {
- log(`${lord_name[lord]} Spied`)
- view.reveal |= (1 << lord)
+ game.who = lord
+ },
+ locale(loc) {
+ muster_lord_in_exile(game.who, loc)
+ game.who = NOBODY
},
- card: action_held_event,
done() {
- if (is_campaign_phase()) {
- resume_command()
- } else {
- pop_state()
- }
+ end_muster_exiles()
},
}
-// === EVENTS: HOLD - SURPRISE LANDING ===
-
-function goto_play_surprise_landing() {
- push_state("surprise_landing")
- game.flags.surprise_landing = 2
- game.who = NOBODY
-}
-
-states.surprise_landing = {
- inactive: "Surprise Landing",
- prompt() {
- view.prompt = "Surprise Landing : You may march once (no path)."
- prompt_held_event()
-
- view.group = game.group
- let here = get_lord_locale(game.command)
- // 4.3.2 Marshals MAY take other lords
- if (
- is_marshal(game.command) ||
- (lord_has_capability(game.command, AOW_YORK_CAPTAIN) && !other_marshal_or_lieutenant(here))
- ) {
- for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord)
- 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 = first_friendly_lord; lord <= last_friendly_lord; ++lord)
- if (lord !== game.command)
- if (get_lord_locale(lord) === here && !is_marshal(lord)) {
- gen_action_lord(lord)
- }
- }
-
- prompt_march()
- },
- lord(lord) {
- set_toggle(game.group, lord)
- },
- locale: goto_march,
- card: action_held_event,
+function muster_lord_in_exile(lord, exile_box) {
+ remove_lord_from_exile(lord)
+ muster_lord(lord, exile_box)
}
-// === CAPABILITIES ===
-
-// When a lord levy a capability, its + Lordship
-// effects and muster vassal applies instantly
-function capability_muster_effects(lord, c) {
- if (c === AOW_LANCASTER_MONTAGU)
- muster_vassal(VASSAL_MONTAGU, lord)
-
- if (c === AOW_LANCASTER_MY_FATHERS_BLOOD)
- muster_vassal(VASSAL_CLIFFORD, lord)
-
- if (c === AOW_LANCASTER_ANDREW_TROLLOPE)
- muster_vassal(VASSAL_TROLLOPE, lord)
+// === 3.3.2 READY VASSALS ===
- if (c === AOW_LANCASTER_EDWARD)
- muster_vassal(VASSAL_EDWARD, lord)
-
- if (c === AOW_LANCASTER_THOMAS_STANLEY) {
- muster_vassal(VASSAL_THOMAS_STANLEY, lord)
- game.flags.free_levy = 1
- }
-
- if (c === AOW_YORK_HASTINGS) {
- add_lord_forces(lord, MEN_AT_ARMS, 2)
- muster_vassal(VASSAL_HASTINGS, lord)
- }
- if (c === AOW_YORK_FAIR_ARBITER && is_friendly_locale(get_lord_locale(LORD_SALISBURY))) {
- game.count += 1
- }
- if (c === AOW_YORK_FALLEN_BROTHER && !is_lord_in_play(LORD_CLARENCE)) {
- game.count += 1
- }
-
- if (c === AOW_YORK_BURGUNDIANS) {
- if (is_seaport(get_lord_locale(lord) && !is_exile(get_lord_locale(lord)))) {
- add_lord_forces(lord, BURGUNDIANS, 2)
- logi(AOW_YORK_BURGUNDIANS)
- game.flags.burgundians = 1
- }
- else {
- game.flags.burgundians = 0
+function goto_ready_vassals() {
+ for (let vassal = first_vassal; vassal <= last_vassal; vassal++) {
+ if (get_vassal_service(vassal) === current_turn()) {
+ set_vassal_lord_and_service(vassal, VASSAL_READY, 0)
}
}
-}
-
-function lordship_effects(lord) {
- if (is_friendly_locale(get_lord_locale(lord)) && lord_has_capability(lord, AOW_YORK_FAIR_ARBITER))
- game.count += 1
- if (lord_has_capability(lord, AOW_YORK_FALLEN_BROTHER) && !is_lord_in_play(LORD_CLARENCE))
- game.count += 1
- if (is_event_in_play(EVENT_YORK_EDWARD_V) && (lord === LORD_GLOUCESTER_1 || lord === LORD_GLOUCESTER_2))
- game.count += 3
- if (is_lancaster_lord(lord) && is_event_in_play(EVENT_LANCASTER_PARLIAMENT_VOTES)) {
- game.flags.parliament_votes = 1
- }
- if (is_york_lord(lord) && is_jack_cade_eligible(lord)) {
- game.flags.jack_cade = 2
- }
- if (is_york_lord(lord) && is_event_in_play(EVENT_YORK_SUCCESSION)) {
- game.flags.succession = 1
- }
-}
-
-// === LEVY: ARTS OF WAR (FIRST TURN) ===
-
-function draw_two_cards() {
- let deck = list_deck()
- return [ draw_card(deck), draw_card(deck) ]
-}
-
-function discard_card_capability(c) {
- log(`${game.active} discarded C${c}.`)
-}
-
-function discard_card_event(c) {
- log(`${game.active} discarded E${c}.`)
-}
-
-function goto_levy_arts_of_war_first() {
- if (game.active === YORK)
- log_h2("York Arts of War")
- else
- log_h2("Lancaster Arts of War")
- game.state = "levy_arts_of_war_first"
- game.what = draw_two_cards()
-}
-
-function resume_levy_arts_of_war_first() {
- if (game.what.length === 0)
- end_levy_arts_of_war_first()
-}
-
-states.levy_arts_of_war_first = {
- inactive: "Arts of War",
- prompt() {
- let c = game.what[0]
- view.arts_of_war = game.what
- view.what = c
- let discard = true
- for (let lord of data.cards[c].lords) {
- if (is_lord_on_map(lord) && !lord_already_has_capability(lord, c)) {
- gen_action_lord(lord)
- discard = false
- }
- }
- if (discard) {
- view.prompt = `Arts of War: Discard ${data.cards[c].capability}.`
- view.actions.discard = 1
- } else {
- view.prompt = `Arts of War: Assign ${data.cards[c].capability} to a Lord.`
- }
- },
- lord(lord) {
- push_undo()
- let c = game.what.shift()
- log(`${game.active} deployed Capability.`)
- add_lord_capability(lord, c)
- capability_muster_effects(lord, c)
- resume_levy_arts_of_war_first()
- },
- discard() {
- push_undo()
- let c = game.what.shift()
- discard_card_capability(c)
- resume_levy_arts_of_war_first()
- },
-}
-
-function end_levy_arts_of_war_first() {
- game.what = NOTHING
- set_active_enemy()
- if (game.active === P2)
- goto_levy_arts_of_war_first()
- else
- goto_levy_muster()
-}
-// === LEVY: ARTS OF WAR ===
-
-function goto_levy_arts_of_war() {
- if (game.active === YORK)
- log_h2("York Arts of War")
- else
- log_h2("Lancaster Arts of War")
- game.what = draw_two_cards()
- resume_levy_arts_of_war()
-}
-
-function resume_levy_arts_of_war() {
- game.state = "levy_arts_of_war"
- if (game.what.length === 0)
- end_levy_arts_of_war()
+ goto_levy_muster()
}
-states.levy_arts_of_war = {
- inactive: "Arts of War",
- prompt() {
- let c = game.what[0]
- view.arts_of_war = [ c ]
- view.what = c
- switch (data.cards[c].when) {
- case "this_levy":
- case "this_campaign":
- case "now":
- view.prompt = `Arts of War: Play ${data.cards[c].event}.`
- view.actions.play = 1
- break
- case "hold":
- view.prompt = `Arts of War: Hold ${data.cards[c].event}.`
- view.actions.hold = 1
- break
- case "never":
- view.prompt = `Arts of War: Discard ${data.cards[c].event}.`
- view.actions.discard = 1
- break
- }
- },
- play() {
- let c = game.what.shift()
- log(`${game.active} played E${c}.`)
- goto_immediate_event(c)
- },
- hold() {
- let c = game.what.shift()
- log(`${game.active} Held Event.`)
- if (game.active === YORK)
- set_add(game.hand_y, c)
- else
- set_add(game.hand_l, c)
- resume_levy_arts_of_war()
- },
- discard() {
- let c = game.what.shift()
- discard_card_event(c)
- resume_levy_arts_of_war()
- },
-}
+// === 3.4 MUSTER ===
-function end_levy_arts_of_war() {
- game.what = NOTHING
- set_active_enemy()
- if (game.active === P2)
- goto_levy_arts_of_war()
- else
- goto_pay()
+function reset_flags() {
+ // to avoid some flags affecting campaign
+ game.flags.jack_cade = 0
+ game.flags.parliament_votes = 0
}
-// === LEVY: MUSTER ===
-
function goto_levy_muster() {
for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord) {
clear_lords_moved()
@@ -4560,12 +2368,6 @@ function end_levy_muster() {
goto_levy_discard_events()
}
-function reset_flags() {
- // to avoid some flags affecting campaign
- game.flags.jack_cade = 0
- game.flags.parliament_votes = 0
-}
-
function can_lord_muster(lord) {
// already mustered (except free levy)! TODO : re-check parley henry if ships are levied and at exile
if (get_lord_moved(lord)
@@ -4586,6 +2388,20 @@ function can_lord_muster(lord) {
return false
}
+function has_locale_to_muster(lord) {
+ // Can muster at own seat without enemy lord.
+ if (!has_enemy_lord(data.lords[lord].seat))
+ return true
+
+ // Else, can muster at any friendly seat (of a friendly lord who is also in play)
+ for (let other = first_friendly_lord; other <= last_friendly_lord; other++)
+ if (is_lord_in_play(other) && is_friendly_locale(data.lords[other].seat))
+ return true
+
+ // Tough luck!
+ return false
+}
+
states.levy_muster = {
inactive: "Muster",
prompt() {
@@ -4843,357 +2659,7 @@ states.levy_muster_lord = {
},
}
-// === EVENT : THE KINGS NAME ===
-
-function eligible_kings_name() {
- if (
- (!is_lord_on_calendar(LORD_GLOUCESTER_1) && is_lord_on_map(LORD_GLOUCESTER_1)) ||
- (!is_lord_on_calendar(LORD_GLOUCESTER_2) && is_lord_on_map(LORD_GLOUCESTER_2))
- ) {
- if (is_event_in_play(EVENT_YORK_THE_KINGS_NAME) && game.active === LANCASTER)
- return true
- }
- return false
-}
-
-function goto_kings_name(action) {
- game.what = action
- set_active_enemy()
- push_state("kings_name")
-}
-
-states.kings_name = {
- inactive: `King's name`,
- prompt() {
- view.prompt = `King's Name: You pay may 1 Influence to cancel last ${game.what} action`
- view.actions.pass = 1
- view.actions.pay = 1
- },
- pay() {
- push_undo()
- reduce_influence(1)
- goto_kings_name_cancel()
- },
- pass() {
- set_active_enemy()
- pop_state()
- if (game.state === "levy_muster_lord_attempt") {
- push_state("muster_lord_at_seat")
- }
- if (game.state === "levy_muster_vassal") {
- muster_vassal(game.which, game.who)
- pop_state()
- }
- if (game.state === "muster_capability") {
- add_lord_capability(game.who, game.which)
- capability_muster_effects(game.who, game.which)
- pop_state()
- }
- if (game.state === "parley") {
- game.what = NOTHING
- game.where = NOWHERE
- pop_state()
- }
- resume_levy_muster_lord()
- }
-}
-
-function goto_kings_name_cancel() {
- switch(game.what) {
- case "Levy Lord":
- pop_state()
- end_levy_muster_lord_attempt()
- break
- case "Levy Cart":
- add_lord_assets(game.who, CART, -2)
- pop_state()
- resume_levy_muster_lord()
- break
- case "Levy Ship":
- add_lord_assets(game.who, SHIP, -1)
- pop_state()
- resume_levy_muster_lord()
- break
- case "Levy Vassal":
- game.which = NOTHING
- end_levy_muster_vassal()
- break
- case "Levy Troops":
- kings_name_reset_troops()
- pop_state()
- resume_levy_muster_lord()
- break
- case "Parley":
- shift_favour_toward_york(game.where)
- pop_state()
- game.where = NOWHERE
- end_parley()
- break
- case "Capability":
- game.which = NOTHING
- pop_state()
- pop_state()
- resume_levy_muster_lord()
- break
- case "Levy Beloved Warwick":
- add_lord_forces(game.who, MILITIA, -5)
- pop_state()
- resume_levy_muster_lord()
- break
- default:
- throw Error("No King's name cancel state found")
- }
- log(`${game.what} action cancelled`)
- logevent(`${EVENT_YORK_THE_KINGS_NAME}`)
- set_active_enemy()
-}
-
-function kings_name_reset_troops() {
- if (!lord_has_capability(game.who, AOW_LANCASTER_QUARTERMASTERS)) {
- remove_depleted_marker(get_lord_locale(game.who))
- remove_exhausted_marker(get_lord_locale(game.who))
- }
-
- let here = get_lord_locale(game.who)
- let here_type = data.locales[here].type
- switch (here_type) {
- case "calais":
- add_lord_forces(game.who, MEN_AT_ARMS, -2)
- add_lord_forces(game.who, LONGBOWMEN, -1)
- break
- case "london":
- add_lord_forces(game.who, MEN_AT_ARMS, -1)
- add_lord_forces(game.who, LONGBOWMEN, -1)
- add_lord_forces(game.who, MILITIA, -1)
- break
- case "harlech":
- add_lord_forces(game.who, MEN_AT_ARMS, -1)
- add_lord_forces(game.who, LONGBOWMEN, -2)
- break
- case "city":
- add_lord_forces(game.who, LONGBOWMEN, -1)
- add_lord_forces(game.who, MILITIA, -1)
- break
- case "town":
- add_lord_forces(game.who, MILITIA, -2)
- break
- case "fortress":
- add_lord_forces(game.who, MEN_AT_ARMS, -1)
- add_lord_forces(game.who, MILITIA, -1)
- break
- }
-}
-
-// === EVENT : RISING WAGES ===
-
-states.rising_wages = {
- inactive: "Rising Wages",
- prompt() {
- let here = get_lord_locale(game.who)
- view.prompt = "Rising Wages: Pay 1 extra coin to levy troops"
- for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord) {
- let loc = get_lord_locale(lord)
- if (here === loc && (get_lord_assets(lord, COIN) > 0)) {
- gen_action_coin(lord)
- }
- }
- },
- coin(lord) {
- push_undo()
- add_lord_assets(lord, COIN, -1)
- logi(`${EVENT_LANCASTER_RISING_WAGES}`)
- log("York paid 1 Coin to Levy troops")
- pop_state()
- },
-}
-
-// Check if the levy troops is at vassal seat
-
-function chamberlains_eligible_levy(locale) {
- for (let vassal = first_vassal; vassal <= last_vassal; ++vassal)
- if (is_vassal_mustered_with(vassal, game.who) && lord_has_capability(game.who, AOW_LANCASTER_CHAMBERLAINS)) {
- if (locale === data.vassals[vassal].seat)
- return true
- }
-}
-
-// === EVENT: THE COMMONS ===
-
-states.the_commons = {
- inactive: "The Commons",
- prompt() {
- view.prompt = `Add up to ${game.flags.commons_militia} Militias.`
- if (game.flags.commons_militia > 0) {
- view.actions.add_militia = 1
- }
- view.actions.done = 1
- },
- add_militia() {
- push_undo()
- add_lord_forces(game.who, MILITIA, 1)
- --game.flags.commons_militia
- },
- done() {
- push_undo()
- end_the_commons()
-
- }
-}
-
-function end_the_commons() {
- game.flags.commons_militia = 0
- pop_state()
- resume_levy_muster_lord()
-}
-
-// === CAPABILITY: SOLDIERS OF FORTUNE
-
-states.soldier_of_fortune = {
- inactive: "Levy Troops",
- prompt() {
- view.prompt = `Pay 1 Coin for Mercenaries ${lord_name[game.who]}.`
- let done = true
- if (done) {
- for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord) {
- if (is_lord_unfed(lord) && can_pay_from_shared(lord)) {
- if (get_lord_assets(lord, COIN) > 0) {
- gen_action_coin(lord)
- done = false
- }
- }
- }
- }
- // Done
- if (done) {
- view.prompt = "Soldiers of fortune: Done."
- view.actions.end_sof = 1
- }
- },
- coin(lord) {
- push_undo()
- let here = get_lord_locale(game.who)
- let here_type = data.locales[here].type
- let number = get_lord_forces(game.who, MERCENARIES)
- let merc = 0
- if (!lord_has_capability(game.who, AOW_YORK_WOODWILLES))
- deplete_locale(here)
-
- switch (here_type) {
- case "calais":
- add_lord_forces(game.who, MEN_AT_ARMS, 2)
- add_lord_forces(game.who, LONGBOWMEN, 1)
- break
- case "london":
- add_lord_forces(game.who, MEN_AT_ARMS, 1)
- add_lord_forces(game.who, LONGBOWMEN, 1)
- add_lord_forces(game.who, MILITIA, 1)
- break
- case "harlech":
- add_lord_forces(game.who, MEN_AT_ARMS, 1)
- add_lord_forces(game.who, LONGBOWMEN, 2)
- break
- case "city":
- add_lord_forces(game.who, LONGBOWMEN, 1)
- add_lord_forces(game.who, MILITIA, 1)
- break
- case "town":
- add_lord_forces(game.who, MILITIA, 2)
- break
- case "fortress":
- add_lord_forces(game.who, MEN_AT_ARMS, 1)
- add_lord_forces(game.who, MILITIA, 1)
- break
- }
- if (game.flags.free_levy === 1) {
- ++game.count
- game.flags.free_levy = 0
- }
- if (number === 5)
- merc = 1
- else
- merc = 2
- add_lord_assets(lord, COIN, -1)
- add_lord_forces(game.who, MERCENARIES, merc)
- set_lord_unfed(game.who, 0)
- },
- end_sof() {
- end_soldiers_of_fortune()
- },
- card: action_held_event,
-}
-
-function end_soldiers_of_fortune() {
- pop_state()
- resume_levy_muster_lord()
-}
-
-
-// === CAPABILITY: COMMISSION OF ARRAY
-
-states.commission_of_array = {
- inactive: "Levy Troops",
- prompt() {
- view.prompt = `Lord troops adjacent to ${lord_name[game.who]}.`
- let done = true
- let here = get_lord_locale(game.who)
- if (done) {
- for (let next of data.locales[here].adjacent) {
- if (is_friendly_locale(next) && lord_has_capability(game.who, AOW_LANCASTER_COMMISION_OF_ARRAY) && (!has_exhausted_marker(next) && !is_exile(next))) {
- done = false
- gen_action_locale(next)
- }
- }
- }
- // Done
- if (done) {
- view.prompt = "Commission of Array: Done."
- view.actions.end_coa = 1
- }
- },
- locale(loc) {
- push_undo()
- let loc_type = data.locales[loc].type
- deplete_locale(loc)
-
- switch (loc_type) {
- case "calais":
- add_lord_forces(game.who, MEN_AT_ARMS, 2)
- add_lord_forces(game.who, LONGBOWMEN, 1)
- break
- case "london":
- add_lord_forces(game.who, MEN_AT_ARMS, 1)
- add_lord_forces(game.who, LONGBOWMEN, 1)
- add_lord_forces(game.who, MILITIA, 1)
- break
- case "harlech":
- add_lord_forces(game.who, MEN_AT_ARMS, 1)
- add_lord_forces(game.who, LONGBOWMEN, 2)
- break
- case "city":
- add_lord_forces(game.who, LONGBOWMEN, 1)
- add_lord_forces(game.who, MILITIA, 1)
- break
- case "town":
- add_lord_forces(game.who, MILITIA, 2)
- break
- case "fortress":
- add_lord_forces(game.who, MEN_AT_ARMS, 1)
- add_lord_forces(game.who, MILITIA, 1)
- break
- }
- if (game.flags.free_levy === 1) {
- ++game.count
- game.flags.free_levy = 0
- }
- end_commission_of_array()
- },
- card: action_held_event,
-}
-
-function end_commission_of_array() {
- pop_state()
- resume_levy_muster_lord()
-}
+// === 3.4.2 LEVY LORD ===
states.muster_lord_at_seat = {
inactive: "Muster",
@@ -5274,6 +2740,143 @@ function end_muster_lord_at_seat() {
end_levy_muster_lord_attempt()
}
+// === 3.4.3 LEVY VASSAL ===
+
+function eligible_vassal(vassal) {
+ if (!is_vassal_ready(vassal)) {
+ return false
+ }
+ if (
+ !is_favour_friendly(data.vassals[vassal].seat) &&
+ (game.who !== LORD_HENRY_TUDOR || !is_event_in_play(EVENT_LANCASTER_MARGARET_BEAUFORT))
+ ) {
+ return false
+ }
+ if (!is_favour_friendly(data.vassals[vassal].seat))
+ return false
+ if (
+ game.active === LANCASTER &&
+ is_event_in_play(EVENT_YORK_YORKISTS_BLOCK_PARLIAMENT) &&
+ !(is_event_in_play(EVENT_LANCASTER_MARGARET_BEAUFORT) && !is_event_in_play(EVENT_LANCASTER_THE_EARL_OF_RICHMOND))
+ ) {
+ return false
+ }
+ return true
+}
+
+function goto_levy_muster_vassal(vassal) {
+ game.where = NOWHERE
+ let influence_cost = 0
+ if (game.active === YORK && is_event_in_play(EVENT_LANCASTER_BUCKINGHAMS_PLOT))
+ influence_cost += 2
+
+ push_state("levy_muster_vassal")
+ init_influence_check(game.who)
+ game.check.push({
+ cost: influence_cost,
+ modifier: data.vassals[vassal].influence * (game.active === LANCASTER ? -1 : 1),
+ source: "vassal",
+ })
+}
+
+function end_levy_muster_vassal() {
+ pop_state()
+ end_influence_check()
+ resume_levy_muster_lord()
+}
+
+states.levy_muster_vassal = {
+ inactive: "Levy Vassal",
+ prompt() {
+ view.prompt = `Levy Vassal ${data.vassals[game.which].name}. `
+ prompt_influence_check()
+ },
+ spend1: add_influence_check_modifier_1,
+ spend3: add_influence_check_modifier_2,
+ check() {
+ let results = do_influence_check()
+
+ if (lord_has_capability(game.who, AOW_LANCASTER_TWO_ROSES)) {
+ log(`Automatic Success. C${AOW_LANCASTER_TWO_ROSES}.`)
+ }
+ else if (game.active === LANCASTER && is_event_in_play(EVENT_LANCASTER_THE_EARL_OF_RICHMOND) && game.state === "levy_muster_vassal") {
+ log(`Automatic Success. C${EVENT_LANCASTER_THE_EARL_OF_RICHMOND}.`)
+ }
+ else {
+ log(`Attempt to levy V${game.which} ${results.success ? "Successful" : "Failed"}: (${range(results.rating)}) ${results.success ? HIT[results.roll] : MISS[results.roll]}`)
+ }
+
+ if (results.success) {
+ if (eligible_kings_name()) {
+ goto_kings_name("Levy Vassal")
+ }
+ else {
+ muster_vassal(game.which, game.who)
+ end_levy_muster_vassal()
+ }
+ }
+ else {
+ end_levy_muster_vassal()
+ }
+ },
+}
+
+// === 3.4.4 LEVY TROOPS ===
+
+function can_add_troops(_lordwho, locale) {
+ if (!has_exhausted_marker(locale) && !is_exile(locale))
+ return true
+ return false
+}
+
+function can_add_troops_coa(lordwho, locale) {
+ for (let next of data.locales[locale].adjacent) {
+ if (is_friendly_locale(next) && lord_has_capability(lordwho, AOW_LANCASTER_COMMISION_OF_ARRAY) && (!has_exhausted_marker(locale) && !is_exile(locale)))
+ return true
+ }
+ return false
+}
+
+function can_add_troops_beloved_warwick(lordwho, locale) {
+ return (
+ lord_has_capability(lordwho, AOW_YORK_BELOVED_WARWICK) &&
+ !has_exhausted_marker(locale) &&
+ !is_exile(locale)
+ )
+}
+
+function can_add_troops_irishmen(lordwho, locale) {
+ return (
+ lord_has_capability(lordwho, AOW_YORK_IRISHMEN) &&
+ !has_exhausted_marker(locale) &&
+ (locale === LOC_IRELAND || data.port_3.includes(locale))
+ )
+}
+
+function can_add_troops_sof(lordwho, locale) {
+ if (
+ lord_has_capability(lordwho, AOW_YORK_SOLDIERS_OF_FORTUNE) &&
+ !has_exhausted_marker(locale) &&
+ !is_exile(locale) &&
+ get_shared_assets(locale, COIN) > 0
+ ) {
+ let number = 6
+ for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord)
+ number -= get_lord_forces(lord, MERCENARIES)
+ if (number >= 1)
+ return true
+ }
+ return false
+}
+
+// === 3.4.5 LEVY TRANSPORT
+
+function can_add_transport(who, what) {
+ return get_lord_assets(who, what) < 100
+}
+
+// === 3.4.6 LEVY CAPABILITY ===
+
function lord_has_capability_card(lord, c) {
if (get_lord_capability(lord, 0) === c)
return true
@@ -5379,7 +2982,7 @@ states.muster_capability = {
},
}
-// === LEVY: DISCARD EVENTS ===
+// === 3.4 MUSTER - DISCARD EVENTS ===
function goto_levy_discard_events() {
// Discard "This Levy" events from play.
@@ -5388,7 +2991,7 @@ function goto_levy_discard_events() {
goto_campaign_plan()
}
-// === CAMPAIGN: PLAN ===
+// === 4.1 CAMPAIGN: PLAN ===
function goto_campaign_plan() {
game.turn++
@@ -5464,7 +3067,21 @@ function end_campaign_plan() {
goto_command_activation()
}
-// === CAMPAIGN: COMMAND ACTIVATION ===
+// === 4.2 CAMPAIGN: COMMAND ===
+
+// First action vs actions that take full command card
+function is_first_action() {
+ return game.flags.first_action
+}
+
+// If march on a highway, set the flag so the lord can go through
+// a second highway at no cost
+function is_first_march_highway() {
+ if (game.flags.first_march_highway === 1)
+ return true
+ else
+ return false
+}
function goto_command_activation() {
if (game.plan_y.length === 0 && game.plan_l.length === 0) {
@@ -5502,29 +3119,6 @@ function goto_command_activation() {
}
}
-// === CAMPAIGN: ACTIONS ===
-
-function set_active_command() {
- if (game.command >= first_york_lord && game.command <= last_york_lord)
- set_active(YORK)
- else
- set_active(LANCASTER)
-}
-
-// First action vs actions that take full command card
-function is_first_action() {
- return game.flags.first_action
-}
-
-// If march on a highway, set the flag so the lord can go through
-// a second highway at no cost
-function is_first_march_highway() {
- if (game.flags.first_march_highway === 1)
- return true
- else
- return false
-}
-
function goto_command() {
game.actions = data.lords[game.command].command
if (lord_has_capability(game.command, AOW_YORK_THOMAS_BOURCHIER) && is_city(get_lord_locale(game.command)))
@@ -5582,21 +3176,6 @@ function end_command() {
goto_feed()
}
-// Captain capability (lieutenant/marshall only if no other)
-function other_marshal_or_lieutenant(loc) {
- let here = loc
- let n = 0
- for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord)
- if (lord !== game.command) {
- if (get_lord_locale(lord) === here && (is_marshal(lord) || is_lieutenant(lord)))
- n += 1
- }
- if (n === 0)
- return false
- else
- return true
-}
-
states.command = {
inactive: "Command",
prompt() {
@@ -5694,177 +3273,637 @@ states.command = {
},
}
-// === INFLUENCE CHECKS ===
+// === 4.5 ACTION: SUPPLY (SEARCH) ===
-// Bonus score but still maxed at 5
-function influence_capabilities(lord, score) {
- let here = get_lord_locale(game.group)
- if (game.active === YORK && is_event_in_play(EVENT_YORK_YORKIST_PARADE))
- score += 2
- if (game.active === YORK && is_event_in_play(EVENT_YORK_PRIVY_COUNCIL))
- score += 1
- if (game.state === "parley" && ((is_event_in_play(EVENT_YORK_RICHARD_OF_YORK) && game.active === YORK) || lord_has_capability(game.group, AOW_LANCASTER_IN_THE_NAME_OF_THE_KING)))
- score += 1
- if (get_lord_locale(LORD_MARGARET) === here && lord_has_capability(game.group, AOW_LANCASTER_LOYAL_SOMERSET))
- score += 1
- if (lord_has_capability(lord, AOW_YORK_YORKS_FAVOURED_SON))
- score += 1
- if (
- get_lord_locale(LORD_WARWICK_L) === here &&
- lord_has_capability(game.group, AOW_LANCASTER_MARRIED_TO_A_NEVILLE) &&
- is_friendly_locale(here)
+function can_supply_at(loc, ships) {
+ // if theoretically possible to supply (does not check carts or ships)
+ if (is_stronghold(loc) && is_friendly_locale(loc)) {
+ if (ships > 0 && is_seaport(loc))
+ return true
+ if (!has_exhausted_marker(loc))
+ return true
+ }
+ return false
+}
+
+function search_supply_by_way(result, start, carts, ships) {
+ search_dist.fill(0)
+ search_seen.fill(0)
+ search_seen[start] = 1
+
+ let queue = [ start ]
+ while (queue.length > 0) {
+ let here = queue.shift()
+ let dist = search_dist[here]
+
+ if (can_supply_at(here, ships)) {
+ if (result)
+ map_set(result, here, dist)
+ else
+ return true
+ }
+
+ if (is_friendly_locale(here)) {
+ let next_dist = dist + 1
+ if (next_dist <= carts) {
+ for (let next of data.locales[here].adjacent) {
+ if (!search_seen[next]) {
+ search_seen[next] = 1
+ search_dist[next] = next_dist
+ queue.push(next)
+ }
+ }
+ }
+ }
+ }
+
+ if (result)
+ return result
+ return false
+}
+
+function search_supply_by_sea(result, here) {
+ // Search via sea from Exile box.
+ if (is_friendly_locale(here)) {
+ for (let next of find_ports(here)) {
+ if (can_supply_at(next, 1)) {
+ if (result)
+ map_set(result, next, 0)
+ else
+ return true
+ }
+ }
+ }
+ if (result)
+ return result
+ return false
+}
+
+function search_supply(result) {
+ let here = get_lord_locale(game.command)
+ let carts = get_shared_assets(here, CART)
+ let ships = get_shared_assets(here, SHIP)
+ if (ships > 0 && is_exile(here))
+ result = search_supply_by_sea(result, here)
+ result = search_supply_by_way(result, here, carts, ships)
+ return result
+}
+
+// === 4.5 ACTION: SUPPLY ===
+
+function command_has_harbingers() {
+ return (
+ lord_has_capability(game.command, AOW_LANCASTER_HARBINGERS) ||
+ lord_has_capability(game.command, AOW_YORK_HARBINGERS)
)
- score += 2
- if (has_favoury_marker(here) && lord_has_capability(lord, AOW_YORK_FAIR_ARBITER))
- score += 1
- if (lord_has_capability(lord, AOW_YORK_FALLEN_BROTHER) && !is_lord_in_play(LORD_CLARENCE))
- score += 2
+}
- return score
+function chamberlains_eligible_supply(source) {
+ for (let vassal = first_vassal; vassal <= last_vassal; ++vassal)
+ if (
+ is_vassal_mustered_with(vassal, game.command) &&
+ lord_has_capability(game.command, AOW_LANCASTER_CHAMBERLAINS)
+ ) {
+ if (source === data.vassals[vassal].seat)
+ return true
+ }
}
-// Cards that allows automatic success
-function automatic_success(lord, score) {
+function command_has_stafford_branch(loc) {
+ if (lord_has_capability(game.command, AOW_YORK_STAFFORD_BRANCH)) {
+ return (
+ loc === LOC_EXETER ||
+ loc === LOC_LAUNCESTON ||
+ loc === LOC_PLYMOUTH ||
+ loc === LOC_WELLS ||
+ loc === LOC_DORCHESTER
+ )
+ }
+ return false
+}
- if (lord_has_capability(lord, AOW_LANCASTER_TWO_ROSES))
- score = 6
- if (game.active === LANCASTER
- && is_event_in_play(EVENT_LANCASTER_THE_EARL_OF_RICHMOND)
- && game.state === "levy_muster_vassal")
- score = 6
- if (game.active === LANCASTER
- && game.flags.parliament_votes === 1
- && game.state === "parley")
- score = 6
- if (game.active === YORK
- && game.flags.jack_cade > 0
- && game.state === "parley")
- score = 6
- if (game.active === YORK
- && game.flags.succession === 1
- && game.state === "parley")
- score = 6
- if (is_campaign_phase()
- && game.command === LORD_DEVON
- && get_lord_locale(LORD_DEVON) === LOC_EXETER
- && is_event_in_play(EVENT_YORK_DORSET)
- && game.state === "parley")
- score = 6
+function init_supply() {
+ game.supply = search_supply([])
+}
- return score
+function can_action_supply() {
+ if (game.actions < 1)
+ return false
+ return search_supply(false)
}
-// Initiate influence check with cards influencing the cost overriding all others
-// (even automatic at no cost)
-function init_influence_check(lord) {
- game.check = []
- game.check.push({ cost: 1, modifier: 0, source: "base" })
- game.check.push({ cost: 0, modifier: data.lords[lord].influence, source: "lord" })
- if (game.active === LANCASTER
- && is_event_in_play(EVENT_YORK_AN_HONEST_TALE_SPEEDS_BEST)
- && game.state === "parley"){
- game.check.push({ cost: 1, modifier: 0, source:"An Honest tale speeds best"})
+function goto_supply() {
+ push_undo()
+ log(`Supplied`)
+ game.state = "supply_source"
+ init_supply()
+}
+
+function modify_supply(loc, supply) {
+ let here = get_lord_locale(game.command)
+ let carts = get_shared_assets(here, CART)
+
+ // Must carry supply over land with one cart per provender per way
+ let distance = map_get(game.supply, loc, 0)
+ if (distance > 0)
+ supply = Math.min(supply, Math.floor(carts / distance))
+
+ // Harbingers event doubles supply received
+ if (command_has_harbingers())
+ supply = supply * 2
+
+ return supply
+}
+
+function get_port_supply_amount(loc) {
+ if (is_seaport(loc)) {
+ let here = get_lord_locale(game.command)
+ let ships = get_shared_assets(here, SHIP)
+ return modify_supply(loc, ships)
}
- if (game.active === LANCASTER
- && is_event_in_play(EVENT_LANCASTER_PARLIAMENT_VOTES)
- && game.flags.parliament_votes === 1
- && game.state === "parley") {
- game.check.push({ cost: -1, modifier: 0, source:"Parliament Votes"})
+ return 0
+}
+
+function get_stronghold_supply_amount(loc) {
+ if (!has_exhausted_marker(loc)) {
+ let supply
+
+ if (loc === LOC_LONDON || loc === LOC_CALAIS)
+ supply = 3
+ else if (is_city(loc))
+ supply = 2
+ else
+ supply = 1
+
+ if (command_has_stafford_branch(loc))
+ supply += 1
+
+ return modify_supply(loc, supply)
}
- if (game.active === YORK
- && is_event_in_play(EVENT_YORK_SUCCESSION)
- && game.flags.succession === 1
- && game.state === "parley") {
- game.check.push({ cost: -1, modifier: 0, source:"Succession"})
+ return 0
+}
+
+states.supply_source = {
+ inactive: "Supply",
+ prompt() {
+ view.prompt = "Supply: Select Supply Source."
+
+ let here = get_lord_locale(game.command)
+ let carts = get_shared_assets(here, CART)
+ let ships = get_shared_assets(here, SHIP)
+
+ if (carts > 0)
+ view.prompt += ` ${carts} Cart.`
+ if (ships > 0)
+ view.prompt += ` ${ships} Ship.`
+
+ for (let i = 0; i < game.supply.length; i += 2)
+ gen_action_locale(game.supply[i])
+ },
+ locale(loc) {
+ push_undo()
+
+ let port_supply = get_port_supply_amount(loc)
+ let stronghold_supply = get_stronghold_supply_amount(loc)
+
+ if (stronghold_supply > 0 && port_supply === 0) {
+ use_stronghold_supply(loc, stronghold_supply)
+ return
+ }
+
+ if (port_supply > 0 && stronghold_supply === 0) {
+ use_port_supply(loc, port_supply)
+ return
+ }
+
+ game.where = loc
+ game.state = "select_supply_type"
+ },
+}
+
+function quartermasters_eligible_supply(source) {
+ for (let vassal = first_vassal; vassal <= last_vassal; ++vassal)
+ if (
+ is_vassal_mustered_with(vassal, game.command) &&
+ lord_has_capability(game.command, AOW_LANCASTER_CHAMBERLAINS)
+ ) {
+ if (source === data.vassals[vassal].seat)
+ return true
+ }
+}
+
+function use_stronghold_supply(source, amount) {
+ logi(`${amount} from Stronghold at %${source}`)
+ add_lord_assets(game.command, PROV, amount)
+ if (chamberlains_eligible_supply(source)) {
+ end_supply()
+ }
+ else {
+ deplete_locale(source)
+ end_supply()
}
}
-function end_influence_check() {
- game.check = 0
+function use_port_supply(source, amount) {
+ logi(`${amount} from Port at %${source}`)
+ add_lord_assets(game.command, PROV, amount)
+ end_supply()
}
-function count_influence_score() {
- let score = game.check.reduce((p, c) => p + c.modifier, 0)
- let lord = 0
- if (is_levy_phase())
- lord = game.who
- if (is_campaign_phase())
- lord = game.command
+function end_supply() {
+ spend_action(1)
+ resume_command()
+ game.supply = 0
+ game.where = NOWHERE
+}
- // Space for whose lord has been selected for SUSPICION EVENT
+states.select_supply_type = {
+ inactive: "Supply",
+ prompt() {
+ let port = get_port_supply_amount(game.where)
+ let stronghold = get_stronghold_supply_amount(game.where)
- score = (lord, score)
+ view.prompt = `Supply: ${stronghold} from Stronghold or ${port} from Port?`
+ view.actions.stronghold = 1
+ view.actions.port = 1
+ },
+ stronghold() {
+ use_stronghold_supply(game.where, get_stronghold_supply_amount(game.where))
+ },
+ port() {
+ if (check_naval_blockade("supply", game.where)) {
+ roll_naval_blockade()
+ }
+ else {
+ use_port_supply(game.where, get_port_supply_amount(game.where))
+ }
+ },
+}
- if (score > 5)
- score = 5
- if (score < 1)
- score = 1
+// === 4.6.1 ACTION: SAIL ===
- score = automatic_success(lord, score)
- return score
+function has_enough_available_ships_for_army() {
+ let ships = count_group_ships()
+ let army = count_lord_all_forces(game.group)
+ let needed_ships = army / 6
+ return needed_ships <= ships
}
-function count_influence_cost() {
- if (game.state === "parley") {
- if (is_campaign_phase()) {
- if (game.command === LORD_DEVON && get_lord_locale(LORD_DEVON) === LOC_EXETER && is_event_in_play(EVENT_YORK_DORSET))
- return 0
+function is_seamanship_in_play() {
+ if (game.active === LANCASTER && is_event_in_play(EVENT_LANCASTER_SEAMANSHIP))
+ return true
+ if (game.active === YORK && is_event_in_play(EVENT_YORK_SEAMANSHIP))
+ return true
+ return false
+}
+
+function can_sail_to(to) {
+ if (is_wales_forbidden(to))
+ return false
+ if (has_enemy_lord(to)) {
+ if (is_truce_in_effect())
+ return false
+ if (!lord_has_capability(game.command, AOW_LANCASTER_HIGH_ADMIRAL))
+ return false
+ }
+ return true
+}
+
+function can_action_sail() {
+ // Must use whole action except if seamanship in play
+
+ if (is_lancaster_lord(game.command)) {
+ if (!is_first_action() && !is_event_in_play(EVENT_LANCASTER_SEAMANSHIP))
+ return false
+ }
+
+ if (is_york_lord(game.command)) {
+ if ((is_event_in_play(EVENT_LANCASTER_FRENCH_FLEET) || !is_first_action() && !is_event_in_play(EVENT_YORK_SEAMANSHIP)))
+ return false
+ }
+
+ if (game.actions === 0)
+ return false
+
+ // at a seaport
+ let here = get_lord_locale(game.command)
+ if (!is_seaport(here))
+ return false
+
+ // with enough ships to carry all the army
+ if (!has_enough_available_ships_for_army())
+ return false
+
+ // and a valid destination
+ for (let to of find_sail_locales(here)) {
+ if (to === here)
+ continue
+ if (can_sail_to(to))
+ return true
+ }
+
+ return false
+}
+
+function goto_sail() {
+ push_undo()
+ game.state = "sail"
+}
+
+states.sail = {
+ inactive: "Sail",
+ prompt() {
+ view.group = game.group
+
+ let here = get_lord_locale(game.command)
+ let ships = count_group_ships()
+ let prov = count_group_assets(PROV)
+ let cart = count_group_assets(CART)
+
+ let overflow_prov = (prov / 2 - ships) * 2
+ let overflow_cart = (cart / 2 - ships) * 2
+
+ if (overflow_prov <= 0 && overflow_cart <= 0) {
+ view.prompt = `Sail: Select a destination Port.`
+ for (let to of find_sail_locales(here)) {
+ if (to === here)
+ continue
+ if (can_sail_to(to))
+ gen_action_locale(to)
+ }
+ } else if (overflow_cart > 0) {
+ view.prompt = `Sailing with ${ships} Ships. Please discard ${overflow_cart} Cart`
+ if (cart > 0) {
+ for (let lord of game.group) {
+ if (get_lord_assets(lord, CART) > 0)
+ gen_action_cart(lord)
+ }
+ }
+ } else if (overflow_prov > 0) {
+ view.prompt = `Sailing with ${ships} Ships. Please discard ${overflow_prov} Provender`
+ if (prov > 0) {
+ for (let lord of game.group) {
+ if (get_lord_assets(lord, PROV) > 0)
+ gen_action_prov(lord)
+ }
+ }
+ } else {
+ view.prompt = "ERROR"
}
- if (is_levy_phase()) {
- if (game.flags.jack_cade > 0)
- return 0
+ },
+ prov: drop_prov,
+ cart: drop_cart,
+ locale(to) {
+ if (check_naval_blockade("sail", get_lord_locale(game.command)) || check_naval_blockade("sail", to)) {
+ roll_naval_blockade()
+ game.where = to
+ }
+ else {
+ log(`Sailed to %${to}${format_group_move()}.`)
+
+ for (let lord of game.group) {
+ set_lord_locale(lord, to)
+ set_lord_moved(lord, 1)
+ levy_burgundians(lord)
+ }
+
+ if (is_seamanship_in_play())
+ spend_action(1)
+ else
+ spend_all_actions()
+
+ // you can go to unbesieged enemy lord with norfolk capability
+ if (has_unbesieged_enemy_lord(to))
+ goto_confirm_approach_sail()
+ else {
+ game.flags.surprise_landing = 1
+ resume_command()
+ }
}
+ },
+}
+
+function goto_confirm_approach_sail() {
+ game.state = "confirm_approach_sail"
+}
+
+states.confirm_approach_sail = {
+ inactive: "Sail",
+ prompt() {
+ view.prompt = `Sail: Confirm Approach to enemy Lord.`
+ view.group = game.group
+ view.actions.approach = 1
+ },
+ approach() {
+ push_undo()
+ goto_battle()
+ },
+}
+
+// === 4.6.2 ACTION: FORAGE ===
+
+function can_action_forage() {
+ if (game.actions < 1)
+ return false
+ let here = get_lord_locale(game.command)
+ if (has_exhausted_marker(here) || is_sea(here))
+ return false
+ return true
+}
+
+function goto_forage() {
+ push_undo()
+ let here = get_lord_locale(game.command)
+ if (!has_adjacent_enemy(here) && is_neutral_locale(here)) {
+ let die = roll_die()
+ if (die <= 4) {
+ add_lord_assets(game.command, PROV, 1)
+ log(`${HIT[die]}, Foraged at %${here}`)
+ deplete_locale(here)
+ } else {
+ log(`${MISS[die]}, Forage Failure`)
+ }
+ } else if (has_adjacent_enemy(here) || is_favour_enemy(here, game.active)) {
+ let die = roll_die()
+ if (die <= 3) {
+ add_lord_assets(game.command, PROV, 1)
+ log(`${HIT[die]}, Foraged at %${here}`)
+ deplete_locale(here)
+ } else {
+ log(`${MISS[die]}, Forage Failure`)
+ }
+ } else {
+ add_lord_assets(game.command, PROV, 1)
+ log(`Foraged at %${here}`)
+ deplete_locale(here)
}
- return game.check.reduce((p, c) => p + c.cost, 0)
+ if (lord_has_capability(game.command, AOW_YORK_SCOURERS)) {
+ add_lord_assets(game.command, PROV, 1)
+ log(`1 Extra Provender (Scourers)`)
+ }
+
+ spend_action(1)
+ resume_command()
}
-function do_influence_check() {
- reduce_influence(count_influence_cost())
- let rating = count_influence_score()
- let roll = roll_die()
- let success
+// === 4.6.3 ACTION: TAX ===
- if (roll === 1 || rating === 6)
- success = true
- else if (roll === 6)
- success = false
+function can_tax_at(here) {
+ if (is_friendly_locale(here) && !has_exhausted_marker(here)) {
+ // London, Calais, and Harlech
+ if (here === LOC_LONDON || here === LOC_CALAIS || here === LOC_HARLECH)
+ return true
+
+ // Own seat
+ if (here === data.lords[game.command].seat)
+ return true
+
+ // vassal seats
+ for (let vassal = first_vassal; vassal <= last_vassal; ++vassal)
+ if (is_vassal_mustered_with(vassal, game.command))
+ if (here === data.vassals[vassal].seat)
+ return true
+ }
+ return false
+}
+
+// adjacent friendly locales to an eligible stronghold (can_tax_at)
+function search_tax(result, start) {
+ let ships = get_shared_assets(start, SHIP)
+
+ search_seen.fill(0)
+ search_seen[start] = 1
+
+ let queue = [ start ]
+ while (queue.length > 0) {
+ let here = queue.shift()
+
+ if (can_tax_at(here)) {
+ if (result)
+ set_add(result, here)
+ else
+ return true
+ }
+
+ if (is_friendly_locale(here)) {
+ for (let next of data.locales[here].adjacent) {
+ if (!search_seen[next]) {
+ search_seen[next] = 1
+ queue.push(next)
+ }
+ }
+ if (ships > 0 && is_seaport(here)) {
+ for (let next of find_ports(here)) {
+ if (!search_seen[next]) {
+ search_seen[next] = 1
+ queue.push(next)
+ }
+ }
+ }
+ }
+ }
+ if (result)
+ return result
else
- success = roll <= rating
+ return false
+}
- // TODO: print log message here instead of returning object
- return { success: success, rating: rating, roll: roll }
+function can_action_tax() {
+ if (game.actions < 1)
+ return false
+ let here = get_lord_locale(game.command)
+ if (can_tax_at(here))
+ return true
+ return search_tax(false, here)
}
-function add_influence_check_modifier_1() {
- game.check.push({ cost: 1, modifier: 1, source: "add" })
+function goto_tax() {
+ push_undo()
+ push_state("tax")
+ init_influence_check(game.command)
+ game.where = NOWHERE
}
-function add_influence_check_modifier_2() {
- game.check.push({ cost: 3, modifier: 2, source: "add" })
+function end_tax() {
+ pop_state()
+ game.where = NOWHERE
+ spend_action(1)
+ resume_command()
}
-function add_influence_check_distance(distance) {
- let idx = game.check.findIndex(i => i.source === "distance")
+function get_tax_amount(loc) {
+ let tax
- if (idx !== NOTHING)
- game.check.splice(idx, 1)
+ if (loc === LOC_LONDON || loc === LOC_CALAIS)
+ tax = 3
+ else if (is_city(loc))
+ tax = 2
+ else
+ tax = 1
- game.check.push({ cost: distance, modifier: 0, source: "distance" })
+ if (command_has_stafford_branch(loc))
+ tax += 1
+
+ return tax
}
-function prompt_influence_check() {
- if (!game.check.some(c => c.source === "add")) {
- view.actions.spend1 = 1
- view.actions.spend3 = 1
- }
- if (game.where !== NOWHERE)
- gen_action_locale(game.where)
- view.actions.check = 1
+states.tax = {
+ inactive: "Tax",
+ prompt() {
+ view.prompt = "Tax: Select the location to tax."
+ if (game.where === NOWHERE) {
+ for (let loc of search_tax([], get_lord_locale(game.command)))
+ gen_action_locale(loc)
+ } else {
+ view.prompt = `Tax: Attempting to tax ${data.locales[game.where].name}. `
+ prompt_influence_check()
+ }
+ },
+ locale(loc) {
+ game.where = loc
+ if (loc === data.lords[game.command].seat) {
+ // Auto succeed without influence check at Lords seat.
+ deplete_locale(game.where)
- view.prompt += `Cost: ${count_influence_cost()} - Range (${range(count_influence_score())})`
+ log(`Taxed automatically successful at %${game.where}.`)
+ add_lord_assets(game.command, COIN, get_tax_amount(game.where))
+ end_tax()
+ }
+ },
+ spend1: add_influence_check_modifier_1,
+ spend3: add_influence_check_modifier_2,
+ check() {
+ let results = do_influence_check()
+ logi(`Tax : ${results.success ? "Successful" : "Failed"}: (${range(results.rating)}) ${results.success ? HIT[results.roll] : MISS[results.roll]}`)
+
+ if (lord_has_capability(game.command, AOW_YORK_SO_WISE_SO_YOUNG)) {
+ log(`C${AOW_YORK_SO_WISE_SO_YOUNG}.`)
+ add_lord_assets(game.command, COIN, 1)
+ }
+
+ if (results.success) {
+ deplete_locale(game.where)
+
+ log(`Taxed %${game.where}.`)
+ add_lord_assets(game.command, COIN, get_tax_amount(game.where))
+
+ if (
+ game.command === LORD_DEVON &&
+ (game.where === LOC_EXETER ||
+ game.where === LOC_LAUNCESTON ||
+ game.where === LOC_PLYMOUTH ||
+ game.where === LOC_WELLS ||
+ game.where === LOC_DORCHESTER)
+ )
+ add_lord_assets(game.command, COIN, 1)
+ } else {
+ log(`Tax of %${game.where} failed.`)
+ }
+ end_tax()
+ },
}
-// === ACTION: PARLEY ===
+// === 4.6.4 ACTION: PARLEY ===
// TODO : FIX Parley through strongholds overseas
function can_parley_at(loc) {
@@ -6110,88 +4149,7 @@ states.parley = {
}
}
-// === ACTION: LEVY VASSAL ===
-
-function eligible_vassal(vassal) {
- if (!is_vassal_ready(vassal)) {
- return false
- }
- if (
- !is_favour_friendly(data.vassals[vassal].seat) &&
- (game.who !== LORD_HENRY_TUDOR || !is_event_in_play(EVENT_LANCASTER_MARGARET_BEAUFORT))
- ) {
- return false
- }
- if (!is_favour_friendly(data.vassals[vassal].seat))
- return false
- if (
- game.active === LANCASTER &&
- is_event_in_play(EVENT_YORK_YORKISTS_BLOCK_PARLIAMENT) &&
- !(is_event_in_play(EVENT_LANCASTER_MARGARET_BEAUFORT) && !is_event_in_play(EVENT_LANCASTER_THE_EARL_OF_RICHMOND))
- ) {
- return false
- }
- return true
-}
-
-function goto_levy_muster_vassal(vassal) {
- game.where = NOWHERE
- let influence_cost = 0
- if (game.active === YORK && is_event_in_play(EVENT_LANCASTER_BUCKINGHAMS_PLOT))
- influence_cost += 2
-
- push_state("levy_muster_vassal")
- init_influence_check(game.who)
- game.check.push({
- cost: influence_cost,
- modifier: data.vassals[vassal].influence * (game.active === LANCASTER ? -1 : 1),
- source: "vassal",
- })
-}
-
-function end_levy_muster_vassal() {
- pop_state()
- end_influence_check()
- resume_levy_muster_lord()
-}
-
-states.levy_muster_vassal = {
- inactive: "Levy Vassal",
- prompt() {
- view.prompt = `Levy Vassal ${data.vassals[game.which].name}. `
- prompt_influence_check()
- },
- spend1: add_influence_check_modifier_1,
- spend3: add_influence_check_modifier_2,
- check() {
- let results = do_influence_check()
-
- if (lord_has_capability(game.who, AOW_LANCASTER_TWO_ROSES)) {
- log(`Automatic Success. C${AOW_LANCASTER_TWO_ROSES}.`)
- }
- else if (game.active === LANCASTER && is_event_in_play(EVENT_LANCASTER_THE_EARL_OF_RICHMOND) && game.state === "levy_muster_vassal") {
- log(`Automatic Success. C${EVENT_LANCASTER_THE_EARL_OF_RICHMOND}.`)
- }
- else {
- log(`Attempt to levy V${game.which} ${results.success ? "Successful" : "Failed"}: (${range(results.rating)}) ${results.success ? HIT[results.roll] : MISS[results.roll]}`)
- }
-
- if (results.success) {
- if (eligible_kings_name()) {
- goto_kings_name("Levy Vassal")
- }
- else {
- muster_vassal(game.which, game.who)
- end_levy_muster_vassal()
- }
- }
- else {
- end_levy_muster_vassal()
- }
- },
-}
-
-// === ACTION: MARCH ===
+// === 4.3 ACTION: MARCH ===
function get_way_type(from, to) {
return map_get(data.ways[from], to, undefined)
@@ -6371,7 +4329,7 @@ function end_march() {
resume_command()
}
-// === Interception ===
+// === 4.3.4 INTERCEPT ===
function can_intercept_to(to) {
// TODO: forbid lancaster intercept into york moving to york, and vice versa
@@ -6404,6 +4362,22 @@ function end_intercept() {
goto_kings_parley()
}
+function can_play_held_event_intercept(c) {
+ switch (c) {
+ case EVENT_LANCASTER_FLANK_ATTACK:
+ return can_play_flank_attack()
+ case EVENT_YORK_FLANK_ATTACK:
+ return can_play_flank_attack()
+ }
+ return false
+}
+
+function prompt_held_event_intercept() {
+ for (let c of current_hand())
+ if (can_play_held_event_intercept(c))
+ gen_action_card(c)
+}
+
states.intercept = {
inactive: "Intercept",
prompt() {
@@ -6527,7 +4501,13 @@ function for_each_friendly_lord_in_locale(loc, f) {
f(lord)
}
-// === King's Parley / Parliament's Truce -- cancel Approach ===
+// === MARCH EVENT: FLANK ATTACK ===
+
+function can_play_flank_attack() {
+ return game.state === "intercept" && game.who !== NOBODY && !is_truce_in_effect()
+}
+
+// === MARCH EVENT: KING'S PARLEY ===
// TODO: merge states into one question
@@ -6575,6 +4555,12 @@ function end_kings_parley() {
goto_parliaments_truce()
}
+// === MARCH EVENT: PARLIAMENT'S TRUCE ===
+
+function can_play_parliaments_truce() {
+ return game.state === "campaign"
+}
+
function is_truce_in_effect() {
return (
is_event_in_play(EVENT_YORK_PARLIAMENTS_TRUCE) ||
@@ -6640,6 +4626,8 @@ function end_parliaments_truce() {
goto_blocked_ford()
}
+// === MARCH EVENT: BLOCKED FORD ===
+
function goto_blocked_ford() {
let here = get_lord_locale(game.command)
@@ -6679,7 +4667,7 @@ states.blocked_ford = {
},
}
-// === Exile ===
+// === 4.3.5 APPROACH - EXILE ===
function goto_exiles() {
let here = get_lord_locale(game.command)
@@ -6746,7 +4734,23 @@ function remove_lord_from_exile(lord) {
game.pieces.in_exile = pack1_set(game.pieces.in_exile, lord, 0)
}
-// === ACTION: MARCH - DIVIDE SPOILS AFTER AVOID BATTLE ===
+// === 4.3.5 APPROACH - EXILE (SPOILS) ===
+
+function has_any_spoils() {
+ return game.spoils && game.spoils[PROV] + game.spoils[COIN] + game.spoils[CART] + game.spoils[SHIP] > 0
+}
+
+function get_spoils(type) {
+ if (game.spoils)
+ return game.spoils[type]
+ return 0
+}
+
+function add_spoils(type, n) {
+ if (!game.spoils)
+ game.spoils = [ 0, 0, 0, 0, 0, 0, 0 ]
+ game.spoils[type] += n
+}
function list_spoils() {
let list = []
@@ -6774,1176 +4778,138 @@ function take_spoils(type) {
game.who = NOBODY
}
-// === ACTION: SUPPLY (SEARCHING) ===
+// === 4.4 BATTLE ===
-function can_supply_at(loc, ships) {
- // if theoretically possible to supply (does not check carts or ships)
- if (is_stronghold(loc) && is_friendly_locale(loc)) {
- if (ships > 0 && is_seaport(loc))
- return true
- if (!has_exhausted_marker(loc))
- return true
- }
- return false
-}
-
-function search_supply_by_way(result, start, carts, ships) {
- search_dist.fill(0)
- search_seen.fill(0)
- search_seen[start] = 1
-
- let queue = [ start ]
- while (queue.length > 0) {
- let here = queue.shift()
- let dist = search_dist[here]
-
- if (can_supply_at(here, ships)) {
- if (result)
- map_set(result, here, dist)
- else
- return true
- }
-
- if (is_friendly_locale(here)) {
- let next_dist = dist + 1
- if (next_dist <= carts) {
- for (let next of data.locales[here].adjacent) {
- if (!search_seen[next]) {
- search_seen[next] = 1
- search_dist[next] = next_dist
- queue.push(next)
- }
- }
- }
- }
- }
-
- if (result)
- return result
- return false
-}
-
-function search_supply_by_sea(result, here) {
- // Search via sea from Exile box.
- if (is_friendly_locale(here)) {
- for (let next of find_ports(here)) {
- if (can_supply_at(next, 1)) {
- if (result)
- map_set(result, next, 0)
- else
- return true
- }
- }
- }
- if (result)
- return result
- return false
-}
-
-function search_supply(result) {
- let here = get_lord_locale(game.command)
- let carts = get_shared_assets(here, CART)
- let ships = get_shared_assets(here, SHIP)
- if (ships > 0 && is_exile(here))
- result = search_supply_by_sea(result, here)
- result = search_supply_by_way(result, here, carts, ships)
- return result
-}
-
-// === ACTION: SUPPLY ===
-
-function command_has_harbingers() {
- return (
- lord_has_capability(game.command, AOW_LANCASTER_HARBINGERS) ||
- lord_has_capability(game.command, AOW_YORK_HARBINGERS)
- )
-}
-
-function chamberlains_eligible_supply(source) {
- for (let vassal = first_vassal; vassal <= last_vassal; ++vassal)
- if (
- is_vassal_mustered_with(vassal, game.command) &&
- lord_has_capability(game.command, AOW_LANCASTER_CHAMBERLAINS)
- ) {
- if (source === data.vassals[vassal].seat)
- return true
- }
-}
-
-function command_has_stafford_branch(loc) {
- if (lord_has_capability(game.command, AOW_YORK_STAFFORD_BRANCH)) {
- return (
- loc === LOC_EXETER ||
- loc === LOC_LAUNCESTON ||
- loc === LOC_PLYMOUTH ||
- loc === LOC_WELLS ||
- loc === LOC_DORCHESTER
- )
- }
- return false
-}
-
-function init_supply() {
- game.supply = search_supply([])
-}
-
-function can_action_supply() {
- if (game.actions < 1)
- return false
- return search_supply(false)
-}
-
-function goto_supply() {
- push_undo()
- log(`Supplied`)
- game.state = "supply_source"
- init_supply()
-}
-
-function modify_supply(loc, supply) {
- let here = get_lord_locale(game.command)
- let carts = get_shared_assets(here, CART)
-
- // Must carry supply over land with one cart per provender per way
- let distance = map_get(game.supply, loc, 0)
- if (distance > 0)
- supply = Math.min(supply, Math.floor(carts / distance))
-
- // Harbingers event doubles supply received
- if (command_has_harbingers())
- supply = supply * 2
-
- return supply
-}
-
-function get_port_supply_amount(loc) {
- if (is_seaport(loc)) {
- let here = get_lord_locale(game.command)
- let ships = get_shared_assets(here, SHIP)
- return modify_supply(loc, ships)
- }
- return 0
-}
-
-function get_stronghold_supply_amount(loc) {
- if (!has_exhausted_marker(loc)) {
- let supply
-
- if (loc === LOC_LONDON || loc === LOC_CALAIS)
- supply = 3
- else if (is_city(loc))
- supply = 2
- else
- supply = 1
-
- if (command_has_stafford_branch(loc))
- supply += 1
-
- return modify_supply(loc, supply)
- }
- return 0
-}
-
-states.supply_source = {
- inactive: "Supply",
- prompt() {
- view.prompt = "Supply: Select Supply Source."
-
- let here = get_lord_locale(game.command)
- let carts = get_shared_assets(here, CART)
- let ships = get_shared_assets(here, SHIP)
-
- if (carts > 0)
- view.prompt += ` ${carts} Cart.`
- if (ships > 0)
- view.prompt += ` ${ships} Ship.`
-
- for (let i = 0; i < game.supply.length; i += 2)
- gen_action_locale(game.supply[i])
- },
- locale(loc) {
- push_undo()
-
- let port_supply = get_port_supply_amount(loc)
- let stronghold_supply = get_stronghold_supply_amount(loc)
-
- if (stronghold_supply > 0 && port_supply === 0) {
- use_stronghold_supply(loc, stronghold_supply)
- return
- }
-
- if (port_supply > 0 && stronghold_supply === 0) {
- use_port_supply(loc, port_supply)
- return
- }
-
- game.where = loc
- game.state = "select_supply_type"
- },
-}
-
-function quartermasters_eligible_supply(source) {
- for (let vassal = first_vassal; vassal <= last_vassal; ++vassal)
- if (
- is_vassal_mustered_with(vassal, game.command) &&
- lord_has_capability(game.command, AOW_LANCASTER_CHAMBERLAINS)
- ) {
- if (source === data.vassals[vassal].seat)
- return true
- }
-}
-
-function use_stronghold_supply(source, amount) {
- logi(`${amount} from Stronghold at %${source}`)
- add_lord_assets(game.command, PROV, amount)
- if (chamberlains_eligible_supply(source)) {
- end_supply()
- }
- else {
- deplete_locale(source)
- end_supply()
- }
-}
-
-function use_port_supply(source, amount) {
- logi(`${amount} from Port at %${source}`)
- add_lord_assets(game.command, PROV, amount)
- end_supply()
-}
-
-function end_supply() {
- spend_action(1)
- resume_command()
- game.supply = 0
- game.where = NOWHERE
-}
-
-states.select_supply_type = {
- inactive: "Supply",
- prompt() {
- let port = get_port_supply_amount(game.where)
- let stronghold = get_stronghold_supply_amount(game.where)
-
- view.prompt = `Supply: ${stronghold} from Stronghold or ${port} from Port?`
- view.actions.stronghold = 1
- view.actions.port = 1
- },
- stronghold() {
- use_stronghold_supply(game.where, get_stronghold_supply_amount(game.where))
- },
- port() {
- if (check_naval_blockade("supply", game.where)) {
- roll_naval_blockade()
- }
- else {
- use_port_supply(game.where, get_port_supply_amount(game.where))
- }
- },
-}
-
-// === ACTION: FORAGE ===
-
-function can_action_forage() {
- if (game.actions < 1)
- return false
- let here = get_lord_locale(game.command)
- if (has_exhausted_marker(here) || is_sea(here))
- return false
- return true
-}
-
-function has_adjacent_enemy(loc) {
- for (let next of data.locales[loc].adjacent)
- if (has_unbesieged_enemy_lord(next))
- return true
- return false
-}
-
-function has_adjacent_friendly(loc) {
- for (let next of data.locales[loc].adjacent)
- if (has_friendly_lord(next))
- return true
- return false
-}
-
-function goto_forage() {
- push_undo()
- let here = get_lord_locale(game.command)
- if (!has_adjacent_enemy(here) && is_neutral_locale(here)) {
- let die = roll_die()
- if (die <= 4) {
- add_lord_assets(game.command, PROV, 1)
- log(`${HIT[die]}, Foraged at %${here}`)
- deplete_locale(here)
- } else {
- log(`${MISS[die]}, Forage Failure`)
- }
- } else if (has_adjacent_enemy(here) || is_favour_enemy(here, game.active)) {
- let die = roll_die()
- if (die <= 3) {
- add_lord_assets(game.command, PROV, 1)
- log(`${HIT[die]}, Foraged at %${here}`)
- deplete_locale(here)
- } else {
- log(`${MISS[die]}, Forage Failure`)
- }
- } else {
- add_lord_assets(game.command, PROV, 1)
- log(`Foraged at %${here}`)
- deplete_locale(here)
- }
- if (lord_has_capability(game.command, AOW_YORK_SCOURERS)) {
- add_lord_assets(game.command, PROV, 1)
- log(`1 Extra Provender (Scourers)`)
- }
-
- spend_action(1)
- resume_command()
+function get_lord_array_position(lord) {
+ for (let p = 0; p < 12; ++p)
+ if (game.battle.array[p] === lord)
+ return p
+ return -1
}
-// === ACTION: TAX ===
-
-function can_tax_at(here) {
- if (is_friendly_locale(here) && !has_exhausted_marker(here)) {
- // London, Calais, and Harlech
- if (here === LOC_LONDON || here === LOC_CALAIS || here === LOC_HARLECH)
- return true
-
- // Own seat
- if (here === data.lords[game.command].seat)
- return true
-
- // vassal seats
- for (let vassal = first_vassal; vassal <= last_vassal; ++vassal)
- if (is_vassal_mustered_with(vassal, game.command))
- if (here === data.vassals[vassal].seat)
- return true
- }
- return false
+function set_active_attacker() {
+ set_active(game.battle.attacker)
}
-// adjacent friendly locales to an eligible stronghold (can_tax_at)
-function search_tax(result, start) {
- let ships = get_shared_assets(start, SHIP)
-
- search_seen.fill(0)
- search_seen[start] = 1
-
- let queue = [ start ]
- while (queue.length > 0) {
- let here = queue.shift()
-
- if (can_tax_at(here)) {
- if (result)
- set_add(result, here)
- else
- return true
- }
-
- if (is_friendly_locale(here)) {
- for (let next of data.locales[here].adjacent) {
- if (!search_seen[next]) {
- search_seen[next] = 1
- queue.push(next)
- }
- }
- if (ships > 0 && is_seaport(here)) {
- for (let next of find_ports(here)) {
- if (!search_seen[next]) {
- search_seen[next] = 1
- queue.push(next)
- }
- }
- }
- }
- }
- if (result)
- return result
+function set_active_defender() {
+ if (game.battle.attacker === P1)
+ set_active(P2)
else
- return false
+ set_active(P1)
}
-function can_action_tax() {
- if (game.actions < 1)
- return false
- let here = get_lord_locale(game.command)
- if (can_tax_at(here))
+function ravine_check(lord,pos) {
+ // TODO: if no lord in pos and no ravine? -- if (lord !== NOBODY)
+ if (game.battle.array[pos] === lord)
return true
- return search_tax(false, here)
-}
-
-function goto_tax() {
- push_undo()
- push_state("tax")
- init_influence_check(game.command)
- game.where = NOWHERE
-}
-
-function end_tax() {
- pop_state()
- game.where = NOWHERE
- spend_action(1)
- resume_command()
-}
-
-function get_tax_amount(loc) {
- let tax
-
- if (loc === LOC_LONDON || loc === LOC_CALAIS)
- tax = 3
- else if (is_city(loc))
- tax = 2
- else
- tax = 1
-
- if (command_has_stafford_branch(loc))
- tax += 1
-
- return tax
-}
-
-states.tax = {
- inactive: "Tax",
- prompt() {
- view.prompt = "Tax: Select the location to tax."
- if (game.where === NOWHERE) {
- for (let loc of search_tax([], get_lord_locale(game.command)))
- gen_action_locale(loc)
- } else {
- view.prompt = `Tax: Attempting to tax ${data.locales[game.where].name}. `
- prompt_influence_check()
- }
- },
- locale(loc) {
- game.where = loc
- if (loc === data.lords[game.command].seat) {
- // Auto succeed without influence check at Lords seat.
- deplete_locale(game.where)
-
- log(`Taxed automatically successful at %${game.where}.`)
- add_lord_assets(game.command, COIN, get_tax_amount(game.where))
- end_tax()
- }
- },
- spend1: add_influence_check_modifier_1,
- spend3: add_influence_check_modifier_2,
- check() {
- let results = do_influence_check()
- logi(`Tax : ${results.success ? "Successful" : "Failed"}: (${range(results.rating)}) ${results.success ? HIT[results.roll] : MISS[results.roll]}`)
-
- if (lord_has_capability(game.command, AOW_YORK_SO_WISE_SO_YOUNG)) {
- log(`C${AOW_YORK_SO_WISE_SO_YOUNG}.`)
- add_lord_assets(game.command, COIN, 1)
- }
-
- if (results.success) {
- deplete_locale(game.where)
-
- log(`Taxed %${game.where}.`)
- add_lord_assets(game.command, COIN, get_tax_amount(game.where))
-
- if (
- game.command === LORD_DEVON &&
- (game.where === LOC_EXETER ||
- game.where === LOC_LAUNCESTON ||
- game.where === LOC_PLYMOUTH ||
- game.where === LOC_WELLS ||
- game.where === LOC_DORCHESTER)
- )
- add_lord_assets(game.command, COIN, 1)
- } else {
- log(`Tax of %${game.where} failed.`)
- }
- end_tax()
- },
-}
-
-// === ACTION: SAIL ===
-
-function drop_prov(lord) {
- add_lord_assets(lord, PROV, -1)
-}
-
-function drop_cart(lord) {
- add_lord_assets(lord, CART, -1)
-}
-
-function has_enough_available_ships_for_army() {
- let ships = count_group_ships()
- let army = count_lord_all_forces(game.group)
- let needed_ships = army / 6
- return needed_ships <= ships
-}
-
-function can_sail_to(to) {
- if (is_wales_forbidden(to))
- return false
- if (has_enemy_lord(to)) {
- if (is_truce_in_effect())
- return false
- if (!lord_has_capability(game.command, AOW_LANCASTER_HIGH_ADMIRAL))
- return false
- }
- return true
-}
-
-function can_action_sail() {
- // Must use whole action except if seamanship in play
-
- if (is_lancaster_lord(game.command)) {
- if (!is_first_action() && !is_event_in_play(EVENT_LANCASTER_SEAMANSHIP))
- return false
- }
-
- if (is_york_lord(game.command)) {
- if ((is_event_in_play(EVENT_LANCASTER_FRENCH_FLEET) || !is_first_action() && !is_event_in_play(EVENT_YORK_SEAMANSHIP)))
- return false
- }
-
- if (game.actions === 0)
- return false
-
- // at a seaport
- let here = get_lord_locale(game.command)
- if (!is_seaport(here))
- return false
-
- // with enough ships to carry all the army
- if (!has_enough_available_ships_for_army())
- return false
-
- // and a valid destination
- for (let to of find_sail_locales(here)) {
- if (to === here)
- continue
- if (can_sail_to(to))
- return true
- }
-
return false
}
-function is_seamanship_in_play() {
- if (game.active === LANCASTER && is_event_in_play(EVENT_LANCASTER_SEAMANSHIP))
- return true
- if (game.active === YORK && is_event_in_play(EVENT_YORK_SEAMANSHIP))
+function filled(pos) {
+ if (game.battle.array[pos] !== NOBODY && !ravine_check(game.battle.ravine, pos)) {
return true
- return false
-}
-
-function goto_sail() {
- push_undo()
- game.state = "sail"
-}
-
-states.sail = {
- inactive: "Sail",
- prompt() {
- view.group = game.group
-
- let here = get_lord_locale(game.command)
- let ships = count_group_ships()
- let prov = count_group_assets(PROV)
- let cart = count_group_assets(CART)
-
- let overflow_prov = (prov / 2 - ships) * 2
- let overflow_cart = (cart / 2 - ships) * 2
-
- if (overflow_prov <= 0 && overflow_cart <= 0) {
- view.prompt = `Sail: Select a destination Port.`
- for (let to of find_sail_locales(here)) {
- if (to === here)
- continue
- if (can_sail_to(to))
- gen_action_locale(to)
- }
- } else if (overflow_cart > 0) {
- view.prompt = `Sailing with ${ships} Ships. Please discard ${overflow_cart} Cart`
- if (cart > 0) {
- for (let lord of game.group) {
- if (get_lord_assets(lord, CART) > 0)
- gen_action_cart(lord)
- }
- }
- } else if (overflow_prov > 0) {
- view.prompt = `Sailing with ${ships} Ships. Please discard ${overflow_prov} Provender`
- if (prov > 0) {
- for (let lord of game.group) {
- if (get_lord_assets(lord, PROV) > 0)
- gen_action_prov(lord)
- }
- }
- } else {
- view.prompt = "ERROR"
- }
- },
- prov: drop_prov,
- cart: drop_cart,
- locale(to) {
- if (check_naval_blockade("sail", get_lord_locale(game.command)) || check_naval_blockade("sail", to)) {
- roll_naval_blockade()
- game.where = to
- }
- else {
- log(`Sailed to %${to}${format_group_move()}.`)
-
- for (let lord of game.group) {
- set_lord_locale(lord, to)
- set_lord_moved(lord, 1)
- levy_burgundians(lord)
- }
-
- if (is_seamanship_in_play())
- spend_action(1)
- else
- spend_all_actions()
-
- // you can go to unbesieged enemy lord with norfolk capability
- if (has_unbesieged_enemy_lord(to))
- goto_confirm_approach_sail()
- else {
- game.flags.surprise_landing = 1
- resume_command()
- }
- }
- },
-}
-
-function goto_confirm_approach_sail() {
- game.state = "confirm_approach_sail"
-}
-
-states.confirm_approach_sail = {
- inactive: "Sail",
- prompt() {
- view.prompt = `Sail: Confirm Approach to enemy Lord.`
- view.group = game.group
- view.actions.approach = 1
- },
- approach() {
- push_undo()
- goto_battle()
- },
-}
-
-// === CAPABILITY : WE DONE DEEDS OF CHARITY ===
-
-function tow_extra_ip() {
- for (let lord = first_york_lord; lord <= last_york_lord; ++lord) {
- if (lord_has_capability(lord, AOW_YORK_WE_DONE_DEEDS_OF_CHARITY) && (get_lord_assets(lord, PROV) > 0 || get_shared_assets(lord, PROV) > 0))
- return true
}
return false
}
-states.tow_extra_ip = {
- inactive: "We done needs of charity",
- prompt() {
- let loc = 0
- view.prompt = "We done deeds of charity: spend up to two Provender to add influence points."
- for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord) {
- if (lord_has_capability(lord, AOW_YORK_WE_DONE_DEEDS_OF_CHARITY)) {
- loc = get_lord_locale(lord)
- }
- }
- for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord) {
- if (game.flags.charity < 2 && get_lord_locale(lord) === loc && (get_lord_assets(lord, PROV) > 0)) {
- gen_action_prov(lord)
- }
- }
- view.actions.done = 1
- },
- prov(lord) {
- push_undo()
- add_lord_assets(lord, PROV, -1)
- game.flags.charity += 1
- },
- done() {
- increase_york_influence(game.flags.charity)
- logi(`${AOW_YORK_WE_DONE_DEEDS_OF_CHARITY}`)
- log("York paid " + game.flags.charity + " provender to add " + game.flags.charity + " Influence Points")
- game.flags.charity = 0
- goto_disembark()
- },
-}
-
-// === CAPABILITY : MERCHANTS ===
-
-function can_action_merchants() {
- let loc = get_lord_locale(game.command)
- if (game.actions <= 0)
- return false
-
- if (lord_has_capability(game.command, AOW_LANCASTER_MERCHANTS) && count_deplete(loc) > 0)
- return true
- else
- return false
-}
-
-function goto_merchants() {
- game.count = count_deplete(get_lord_locale(game.command))
- game.state = "merchants"
- init_influence_check(game.command)
-}
-
-states.merchants = {
- inactive: "Merchants",
- prompt() {
- view.prompt = "Merchants: Succeed an influence check to remove Depleted markers"
- prompt_influence_check()
- },
- spend1: add_influence_check_modifier_1,
- spend3: add_influence_check_modifier_2,
- check() {
- let results = do_influence_check()
- log(`Attempt to C${AOW_LANCASTER_MERCHANTS} with %${game.command} ${results.success ? "Successful" : "Failed"}: (${range(results.rating)}) ${results.success ? HIT[results.roll] : MISS[results.roll]}`)
- if (results.success) {
- merchants_success()
- } else {
- end_merchants_attempt()
- }
- }
-}
-function merchants_success() {
- game.state = "merchants_success"
-}
-
-states.merchants_success = {
- inactive: "Merchants Success",
- prompt() {
- view.prompt = `Remove Depleted/Exhausted markers`
- deplete_merchants()
- if (game.count === 0) {
- view.actions.done = 1
- }
- },
- locale(loc) {
- push_undo()
- remove_depleted_marker(loc)
- remove_exhausted_marker(loc)
- --game.count
- if (game.count === 0) {
- end_merchants_attempt()
- }
- },
- done(){
- end_merchants_attempt()
- }
-}
+const battle_strike_positions = [ D1, D2, D3, A1, A2, A3 ]
-function end_merchants_attempt() {
- spend_action(1)
- game.count = 0
- push_undo()
- end_influence_check()
- resume_command()
-}
+const battle_steps = [
+ { name: "Archery", hits: count_archery_hits },
+ { name: "Melee", hits: count_melee_hits },
+]
-function deplete_merchants() {
- let here = get_lord_locale(game.command)
- for (let next of data.locales[here].adjacent) {
- if (has_exhausted_marker(next) || has_depleted_marker(next))
- gen_action_locale(next)
- }
- if (has_exhausted_marker(here) || has_depleted_marker(here))
- gen_action_locale(here)
-}
+function count_archery_hits(lord) {
+ let hits = 0
+ hits += get_lord_forces(lord, LONGBOWMEN) << 2
+ hits += get_lord_forces(lord, BURGUNDIANS) << 2
+ hits += get_lord_forces(lord, MILITIA)
+ hits += get_lord_forces(lord, MERCENARIES)
-function count_deplete(loc) {
- game.count = 0
- for (let next of data.locales[loc].adjacent) {
- if (has_exhausted_marker(next) || has_depleted_marker(next)) {
- ++game.count
- }
- }
- if (has_exhausted_marker(loc) || has_depleted_marker(loc)) {
- ++game.count
+ if (is_leeward_battle_line_in_play(lord)) {
+ // TODO: rounding?
+ return hits/2
}
- if (game.count > 1)
- return game.count = 2
- else
- return game.count
-}
-
-// === CAPABILITY : BURGUNDIANS ===
-function levy_burgundians(lord) {
- if (is_seaport(get_lord_locale(lord)) && !is_exile(get_lord_locale(lord)) && lord_has_capability(lord, AOW_YORK_BURGUNDIANS) && game.flags.burgundians === 0) {
- add_lord_forces(lord, BURGUNDIANS, 2)
- logi(AOW_YORK_BURGUNDIANS)
- game.flags.burgundians = 1
- }
+ return hits
}
-// === EVENT ACTION : EXILE PACT ===
-
-function can_action_exile_pact() {
- if (game.actions <= 0 || !is_event_in_play(EVENT_YORK_EXILE_PACT))
- return false
+function count_melee_hits(lord) {
+ let hits = 0
+ hits += /*retinue*/ 3 << 1
+ //hits += count_vassals_with_lord(lord) << 2
+ if (lord_has_capability(lord, AOW_LANCASTER_CHEVALIERS))
+ hits += get_lord_forces(lord, MEN_AT_ARMS) << 2
else
- return true
-}
-
-function goto_exile_pact() {
- push_undo()
- game.state = "exile_pact"
-}
-
-states.exile_pact = {
- inactive: "Exile pact",
- prompt() {
- view.prompt = "Exile Pact : place your cylinder in one of your Exile boxes"
- for (let loc of data.exile_boxes) {
- if (has_favour_in_locale(game.active, loc))
- gen_action_locale(loc)
- }
- },
- locale(loc) {
- push_undo()
- set_lord_locale(game.command, loc)
- end_exile_pact()
- }
-}
-
-function end_exile_pact() {
- spend_action(1)
- push_undo()
- resume_command()
-}
-
-// === CAPABILITY : NAVAL BLOCKADE
-
-function parley_through_sea(start, locale) {
- // Only entered in levy
- let ships = get_shared_assets(start, SHIP)
-
- if (ships === 0) {
- game.flags.naval_blockade = -1
- }
-
- search_dist.fill(0)
- search_seen.fill(0)
- search_seen[start] = 1
-
- let queue = [ start ]
- while (queue.length > 0) {
- let here = queue.shift()
- let dist = search_dist[here]
- let next_dist = dist + 1
-
- if (is_friendly_locale(here)) {
- for (let next of data.locales[here].adjacent) {
- if (!search_seen[next]) {
- search_seen[next] = 1
- search_dist[next] = next_dist
- queue.push(next)
- if (next === locale) {
- game.flags.naval_blockade = -1
- }
- }
- }
- }
- }
- queue = [ start ]
- while (queue.length > 0) {
- let here = queue.shift()
- let dist = search_dist[here]
- let next_dist = dist + 1
-
- if (is_friendly_locale(here)) {
- if (ships > 0 && is_seaport(here)) {
- for (let next of find_ports(here)) {
- if (!search_seen[next]) {
- search_seen[next] = 1
- search_dist[next] = next_dist
- queue.push(next)
- if (next === locale && game.flags.naval_blockade !== -1) {
- game.flags.naval_blockade = 1
- }
- }
- }
- }
- }
- }
-}
-
-function check_naval_blockade(action, locale) {
- let ports = [data.port_1, data.port_2, data.port_3]
- game.what = action
-
- if (!lord_has_capability(LORD_WARWICK_Y, AOW_YORK_NAVAL_BLOCKADE) || !is_seaport(get_lord_locale(LORD_WARWICK_Y)) || is_exile(get_lord_locale(LORD_WARWICK_Y))) {
- return false
- }
-
- if (action === "levy parley") {
- parley_through_sea(get_lord_locale(game.who), locale)
- if (game.flags.naval_blockade !== 1) {
- return false
- }
- }
+ hits += get_lord_forces(lord, MEN_AT_ARMS) << 1
+ hits += get_lord_forces(lord, MILITIA)
+ hits += get_lord_forces(lord, MERCENARIES)
+ hits += get_lord_forces(lord, BURGUNDIANS) << 1
- if (action === "campaign parley" && data.locales[locale].adjacent.includes(get_lord_locale(game.command))) {
- return false
- }
-
- for (let port of ports) {
- if (set_has(port, get_lord_locale(LORD_WARWICK_Y)) && set_has(port, locale)) {
- return true
- }
+ if (lord === game.battle.caltrops) {
+ hits += 2
}
-}
-
-function roll_naval_blockade() {
- push_state("naval_blockade")
-}
-
-// Parley, and Tax
-states.naval_blockade = {
- inactive: "Naval Blockade",
- prompt() {
- view.prompt = `Naval Blockade : Warwick block this action except on a 1-2`
- view.actions.roll = 1
- },
- roll() {
- let threshold = 2
- let roll = roll_die()
- let success = threshold >= roll
- log(`Attempt to counter Naval Blockade ${success ? "Failed" : "Successful"}: (1-2) ${success ? HIT[roll] : MISS[roll]}`)
- if (success) {
- logi(`Successfully overran C${AOW_YORK_NAVAL_BLOCKADE}`)
- if (game.what === "levy parley") {
- game.flags.naval_blockade = -1
- }
- if (game.what === "campaign parley") {
- game.flags.naval_blockade = -1
- }
- if (game.what === "levy ship") {
- add_lord_assets(game.who, SHIP, 1)
- }
- if (game.what === "supply") {
- use_port_supply(game.where, get_port_supply_amount(game.where))
- }
- if (game.what === "sail") {
- log(`Sailed to %${game.where}${format_group_move()}.`)
- for (let lord of game.group) {
- set_lord_locale(lord, game.where)
- set_lord_moved(lord, 1)
- }
- if (is_seamanship_in_play())
- spend_action(1)
- else
- spend_all_actions()
- game.flags.surprise_landing = 1
- resume_command()
- }
- }
- else {
- logi(`Failed C${AOW_YORK_NAVAL_BLOCKADE}`)
- if (game.what === "levy parley") {
- pop_state()
- }
- if (game.what === "campaign parley") {
- pop_state()
- }
- }
- if (game.what === "levy parley") {
- pop_state()
- resume_levy_muster_lord()
- }
- if (game.what === "campaign parley") {
- pop_state()
- --game.count
- resume_command()
- }
- if (game.what === "levy ship") {
- pop_state()
- resume_levy_muster_lord()
- }
- if (game.what === "supply" && !success) {
- end_supply()
- }
- if (game.what === "sail" && !success) {
- resume_command()
- }
- game.what = NOTHING
- },
-}
-
-// === CAPABILITY : AGITATORS ===
-
-function can_action_agitators() {
- let here = get_lord_locale(game.command)
- if (game.actions <= 0)
- return false
- if (lord_has_capability(game.command, AOW_YORK_AGITATORS)) {
- for (let next of data.locales[here].adjacent) {
- if (!has_exhausted_marker(next) && !is_friendly_locale(next))
- return true
- }
- }
- else
- return false
+ return hits
}
-function goto_agitators() {
- game.count = count_deplete(get_lord_locale(game.command))
- game.state = "agitators"
+function count_lord_hits(lord) {
+ return battle_steps[game.battle.step].hits(lord)
}
-states.agitators = {
- inactive: "Agitators",
- prompt() {
- view.prompt = "Agitators: Add a depleted marker or flip to exhausted adjacent"
- deplete_agitators()
- },
- locale(loc) {
- push_undo()
- if (has_depleted_marker(loc)) {
- add_exhausted_marker(loc)
- }
- else {
- add_depleted_marker(loc)
- }
- end_agitators()
- },
+function format_strike_step() {
+ return battle_steps[game.battle.step].name
}
-function deplete_agitators() {
- let here = get_lord_locale(game.command)
- for (let next of data.locales[here].adjacent) {
- if (!has_exhausted_marker(next) && !is_friendly_locale(next))
- gen_action_locale(next)
+function format_hits() {
+ if (game.battle.ahits > 0) {
+ return `${game.battle.ahits} Hit${game.battle.ahits > 1 ? "s" : ""}`
+ } else if (game.battle.dhits > 0) {
+ return `${game.battle.dhits} Hit${game.battle.dhits > 1 ? "s" : ""}`
}
}
-function end_agitators() {
- spend_action(1)
- push_undo()
- resume_command()
-}
-
-// === CAPABILITY : HERALDS ===
-
-function can_action_heralds() {
- if (game.actions <= 0)
- return false
-
- if (!is_first_action())
- return false
- // at a seaport
- let here = get_lord_locale(game.command)
- if (!is_seaport(here))
- return false
-
- if (!lord_has_capability(game.command, AOW_LANCASTER_HERALDS))
- return false
-
- for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord) {
- if (is_lord_on_calendar(lord))
- return true
- }
+function is_battle_over() {
+ set_active_attacker()
+ if (has_no_unrouted_forces())
+ return true
+ set_active_defender()
+ if (has_no_unrouted_forces())
+ return true
return false
}
-function goto_heralds() {
- game.state = "heralds"
-}
-
-states.heralds = {
- inactive: "Heralds",
- prompt() {
- view.prompt = "Heralds: Choose a Lord on calendar to shift him to next turn box"
- for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord) {
- if (is_lord_on_calendar(lord))
- gen_action_lord(lord)
- }
- },
- lord(other) {
- goto_heralds_attempt(other)
- },
-}
-
-function goto_heralds_attempt(lord) {
- game.what = lord
- push_state("heralds_attempt")
- init_influence_check(game.command)
+function has_no_unrouted_forces() {
+ // All unrouted lords are either in battle array or in reserves
+ for (let p = 0; p < 6; ++p)
+ if (is_friendly_lord(game.battle.array[p]))
+ return false
+ for (let lord of game.battle.reserves)
+ if (is_friendly_lord(lord))
+ return false
+ return true
}
-states.heralds_attempt = {
- inactive: "Heralds Attempt",
- prompt() {
- view.prompt = `Attempt to shift ${lord_name[game.what]} to next Turn Box. `
- prompt_influence_check()
- },
- spend1: add_influence_check_modifier_1,
- spend3: add_influence_check_modifier_2,
- check() {
- let results = do_influence_check()
- log(`Attempt to shift L${game.what} ${results.success ? "Successful" : "Failed"}: (${range(results.rating)}) ${results.success ? HIT[results.roll] : MISS[results.roll]}`)
-
- if (results.success) {
- game.who = game.what
- set_lord_calendar(game.who, current_turn() + 1)
- end_heralds_attempt()
- } else {
- end_heralds_attempt()
- }
- },
+function is_attacker() {
+ return game.active === game.battle.attacker
}
-function end_heralds_attempt() {
- spend_all_actions()
- pop_state()
- end_influence_check()
- resume_command()
+function is_defender() {
+ return game.active !== game.battle.attacker
}
-// === BATTLE ===
-
-function set_active_attacker() {
- set_active(game.battle.attacker)
+function is_archery_step() {
+ return game.battle.step === 0
}
-function set_active_defender() {
- if (game.battle.attacker === P1)
- set_active(P2)
- else
- set_active(P1)
+function is_melee_step() {
+ return game.battle.step === 1
}
-function goto_battle() {
- start_battle()
+function has_strike(pos) {
+ return game.battle.ah[pos] > 0
}
-function init_battle(here) {
- game.battle = {
- where: here,
- round: 1,
- step: 0,
- relief: 0,
- attacker: game.active,
- ambush: 0,
- loser: 0,
- fought: 0, // flag all lords who participated
- array: [
- -1, -1, -1,
- -1, -1, -1,
- ],
- valour: Array(lord_count).fill(0),
- routed_vassals: [],
- engagements: [],
- reserves: [],
- retreated: 0,
- fled: [],
- routed: [],
- target: NOBODY,
- strikers: 0,
- a_hits: 0,
- d_hits: 0,
- fc: -1,
- }
-}
// Capabilities adding troops at start of the battle
function add_battle_capability_troops() {
@@ -8022,12 +4988,37 @@ function remove_battle_capability_troops() {
}
}
-function start_battle() {
+function goto_battle() {
let here = get_lord_locale(game.command)
log_h3(`Battle at %${here}`)
- init_battle(game.where)
+ game.battle = {
+ where: game.where,
+ round: 1,
+ step: 0,
+ relief: 0,
+ attacker: game.active,
+ ambush: 0,
+ loser: 0,
+ fought: 0, // flag all lords who participated
+ array: [
+ -1, -1, -1,
+ -1, -1, -1,
+ ],
+ valour: Array(lord_count).fill(0),
+ routed_vassals: [],
+ engagements: [],
+ reserves: [],
+ retreated: 0,
+ fled: [],
+ routed: [],
+ target: NOBODY,
+ strikers: 0,
+ a_hits: 0,
+ d_hits: 0,
+ fc: -1,
+ }
// Troops by capability
@@ -8084,7 +5075,7 @@ function start_battle() {
goto_array_defender()
}
-// === BATTLE: BATTLE ARRAY ===
+// === 4.4.1 BATTLE ARRAY ===
// 0) Defender decides to stand for Battle, not Exile
// 1) Defender decides how he wants to array his lords
@@ -8232,32 +5223,32 @@ states.array_defender = {
end_array: end_array_defender,
}
-// === BATTLE: EVENTS ===
+// === 4.4.1 BATTLE ARRAY: EVENTS ===
-function goto_attacker_events() {
- set_active_attacker()
+function goto_defender_events() {
+ set_active_defender()
log_br()
if (can_play_battle_events())
- game.state = "attacker_events"
+ game.state = "defender_events"
else
- end_attacker_events()
+ end_defender_events()
}
-function end_attacker_events() {
- goto_battle_rounds()
+function end_defender_events() {
+ goto_attacker_events()
}
-function goto_defender_events() {
- set_active_defender()
+function goto_attacker_events() {
+ set_active_attacker()
log_br()
if (can_play_battle_events())
- game.state = "defender_events"
+ game.state = "attacker_events"
else
- end_defender_events()
+ end_attacker_events()
}
-function end_defender_events() {
- goto_attacker_events()
+function end_attacker_events() {
+ goto_battle_rounds()
}
function resume_battle_events() {
@@ -8268,19 +5259,30 @@ function resume_battle_events() {
goto_defender_events()
}
-function could_play_card(c) {
- if (!game.hidden) {
- // TODO: check capabilities on lords revealed in battle if hidden
- if (map_has_value(game.pieces.capabilities, c))
- return false
- }
- if (set_has(game.events, c))
- return false
- if (is_york_card(c))
- return game.hand_y.length > 0
- if (is_lancaster_card(c))
- return game.hand_l.length > 0
- return true
+states.defender_events = {
+ inactive: "Defender Events",
+ prompt() {
+ view.prompt = "Defender may play Events."
+ prompt_battle_events()
+
+ // defender only events
+ },
+ card: action_battle_events,
+ done() {
+ end_defender_events()
+ },
+}
+
+states.attacker_events = {
+ inactive: "Attacker Events",
+ prompt() {
+ view.prompt = "Attacker may play Events."
+ prompt_battle_events()
+ },
+ card: action_battle_events,
+ done() {
+ end_attacker_events()
+ },
}
function can_play_battle_events() {
@@ -8315,7 +5317,7 @@ function prompt_battle_events() {
// both attacker and defender events
if (game.active === LANCASTER) {
gen_action_card_if_held(EVENT_LANCASTER_LEEWARD_BATTLE_LINE)
- if (can_play_suspicion())
+ if (can_play_suspicion())
gen_action_card_if_held(EVENT_LANCASTER_SUSPICION)
if (can_play_for_trust_not_him())
gen_action_card_if_held(EVENT_LANCASTER_FOR_TRUST_NOT_HIM)
@@ -8333,204 +5335,6 @@ function prompt_battle_events() {
view.actions.done = 1
}
-function prompt_battle_events_death() {
- // both attacker and defender events
- if (game.active === LANCASTER) {
- if (can_play_escape_ship())
- gen_action_card_if_held(EVENT_LANCASTER_ESCAPE_SHIP)
- if (can_play_warden_of_the_marches())
- gen_action_card_if_held(EVENT_LANCASTER_WARDEN_OF_THE_MARCHES)
- if (can_play_talbot_to_the_rescue())
- gen_action_card_if_held(EVENT_LANCASTER_TALBOT_TO_THE_RESCUE)
- }
- if (game.active === YORK) {
- if (can_play_escape_ship())
- gen_action_card_if_held(EVENT_YORK_ESCAPE_SHIP)
- }
- view.actions.done = 1
-}
-
-// === EVENT : WARDEN OF THE MARCHES ===
-
-function can_play_warden_of_the_marches() {
- // TOOD : Maybe a bug with blocked ford/exile ?
- let can_play = false
- for (let loc = first_locale; loc <= last_locale; loc++) {
- if (is_friendly_locale(loc) && is_north(loc) && loc !== game.battle.where) {
- can_play = true
- }
- }
- if (!can_play) {
- return false
- }
- // if blocked ford then flee
- if (is_north(game.where))
- return true
- // if battle
- if (is_north(game.battle.where))
- return true
- return false
-}
-
-function goto_play_warden_of_the_marches() {
- push_undo()
- push_state("warden_of_the_marches")
-}
-
-states.warden_of_the_marches = {
- inactive: "Warden of the Marches",
- prompt() {
- let done = true
- view.prompt = "Warden of the Marches: Select a friendly locale in the North to move routed lords there"
- for (let loc = first_locale; loc <= last_locale; loc++) {
- if (is_friendly_locale(loc) && is_north(loc) && loc !== game.battle.where) {
- done = false
- gen_action_locale(loc)
- }
- }
- if (done) {
- view.actions.done = 1
- }
- },
- locale(loc) {
- push_undo()
- for (let lord = first_lancaster_lord; lord <= last_lancaster_lord; lord++) {
- if (get_lord_locale(lord) === game.battle.where) {
- set_lord_locale(lord, loc)
- if (!lord_has_unrouted_troops(lord)) {
- disband_lord(lord, false)
- }
- else {
- set_lord_forces(lord, RETINUE, 1)
- }
- for (let x = 0; x < FORCE_TYPE_COUNT; ++x) {
- set_lord_forces(lord, x, 0)
- if (get_lord_routed_forces(lord, x) > 0) {
- set_lord_routed_forces(lord, x, 0)
- }
- }
- for_each_vassal_with_lord(lord, v => {
- if (set_has(game.battle.routed_vassals, v)) {
- array_remove(game.battle.routed_vassals, v)
- disband_vassal(v)
- }
- })
- }
- }
- logi(`Moved to ${data.locales[loc].name}`)
- end_warden_of_the_marches()
- },
- done() {
- end_warden_of_the_marches()
- },
-}
-
-function end_warden_of_the_marches() {
- game.flags.warden_of_the_marches = 1
- game.who = NOBODY
- pop_state()
-}
-
-// === EVENT : ESCAPE SHIP ===
-
-function can_play_escape_ship() {
- return can_escape_at(game.battle.where)
-}
-
-function can_escape_at(here) {
- if (game.active === YORK && has_favoury_marker(here) && is_seaport(here))
- return true
- if (game.active === LANCASTER && has_favourl_marker(here) && is_seaport(here))
- return true
- if (search_escape_route(here))
- return true
- return false
-}
-
-function search_escape_route(start) {
- search_seen.fill(0)
- search_seen[start] = 1
- let queue = [start]
-
- while (queue.length > 0) {
- let here = queue.shift()
-
- // Check if the current locale is a seaport
- if (is_seaport(here)) {
- return true
- }
-
- if (is_friendly_locale(here)) {
- for (let next of data.locales[here].adjacent) {
- if (!search_seen[next]) {
- search_seen[next] = 1
- queue.push(next)
- }
- }
- }
- }
- return false
-}
-
-function goto_play_escape_ship() {
- push_state("escape_ship")
- game.who = NOBODY
-}
-
-states.escape_ship = {
- inactive: `Escape ship`,
- prompt() {
- view.prompt = "Escape Ship: Your lords go to Exile."
- view.actions.escape_ship = 1
- },
- escape_ship() {
- push_undo()
- for (let lord of game.battle.fled) {
- log(`${lord_name[lord]} went to exile.`)
- exile_lord(lord)
- set_delete(game.battle.fled, lord)
- }
- for (let lord of game.battle.routed) {
- log(`${lord_name[lord]} went to exile.`)
- exile_lord(lord)
- set_delete(game.battle.routed, lord)
- }
- goto_battle_aftermath()
- },
-}
-
-// === EVENT : TALBOT TO THE RESCUE ===
-
-function can_play_talbot_to_the_rescue() {
- return true
-}
-
-states.attacker_events = {
- inactive: "Attacker Events",
- prompt() {
- view.prompt = "Attacker may play Events."
- prompt_battle_events()
- },
- card: action_battle_events,
- done() {
- end_attacker_events()
- },
-}
-
-states.defender_events = {
- inactive: "Defender Events",
- prompt() {
- view.prompt = "Defender may play Events."
- prompt_battle_events()
-
- // defender only events
- },
- card: action_battle_events,
- done() {
- end_defender_events()
- },
-}
-
function action_battle_events(c) {
game.what = c
set_delete(current_hand(), c)
@@ -8562,7 +5366,7 @@ function action_battle_events(c) {
}
}
-// === EVENT : RAVINE ===
+// === BATTLE EVENT: RAVINE ===
states.ravine = {
inactive: "Ravine",
@@ -8588,7 +5392,22 @@ states.ravine = {
},
}
-// === EVENT : CALTROPS ===
+// === BATTLE EVENT: REGROUP ===
+
+function is_regroup_in_play() {
+ if (game.active === YORK)
+ return is_event_in_play(EVENT_YORK_REGROUP)
+ return false
+}
+
+// TODO
+
+// === BATTLE EVENT: CALTROPS ===
+
+function is_caltrops_in_play() {
+ if (game.active === YORK)
+ return is_event_in_play(EVENT_YORK_CALTROPS)
+}
states.caltrops = {
inactive: "Caltrops",
@@ -8609,7 +5428,7 @@ states.caltrops = {
},
}
-// === EVENT : SUSPICION ===
+// === BATTLE EVENT: SUSPICION ===
function can_play_suspicion() {
if (highest_friendly_influence() >= lowest_enemy_influence()) {
@@ -8724,7 +5543,7 @@ states.influence_check_suspicion = {
},
}
-// === EVENT : FOR TRUST NOT HIM ===
+// === BATTLE EVENT: FOR TRUST NOT HIM ===
function can_play_for_trust_not_him() {
for (let vassal = first_vassal; vassal <= last_vassal; vassal++) {
@@ -8824,7 +5643,126 @@ function end_for_trust_not_him() {
resume_battle_events()
}
-// === BATTLE: FLEE ===
+// === BATTLE EVENT: LEEWARD BATTLE LINE ===
+
+function is_leeward_battle_line_in_play(lord) {
+ if (is_archery_step()) {
+ if (is_event_in_play(EVENT_LANCASTER_LEEWARD_BATTLE_LINE)
+ && !is_event_in_play(EVENT_YORK_LEEWARD_BATTLE_LINE)
+ && is_york_lord(lord)) {
+ logevent(EVENT_LANCASTER_LEEWARD_BATTLE_LINE)
+ return true
+ }
+ if (is_event_in_play(EVENT_YORK_LEEWARD_BATTLE_LINE)
+ && !is_event_in_play(EVENT_LANCASTER_LEEWARD_BATTLE_LINE)
+ && is_lancaster_lord(lord)) {
+ logevent(EVENT_YORK_LEEWARD_BATTLE_LINE)
+ return true
+ }
+ }
+ return false
+}
+
+// === BATTLE EVENT: CULVERINS AND FALCONETS ===
+
+function goto_culverins() {
+ let can_play = false
+ for (let lord of game.battle.array) {
+ if (is_lancaster_lord(lord) && lord_has_capability(lord, AOW_LANCASTER_CULVERINS_AND_FALCONETS))
+ can_play = true
+ if (is_york_lord(lord) && lord_has_capability(lord, AOW_YORK_CULVERINS_AND_FALCONETS))
+ can_play = true
+ }
+ if (can_play) {
+ set_active_defender()
+ game.state = "culverins_and_falconets"
+ game.who = NOBODY
+ }
+ else {
+ goto_engagement_total_hits()
+ }
+}
+
+function artillery_hits(ahits) {
+ if (is_attacker()) {
+ game.battle.attacker_artillery = ahits*2
+ }
+ if (is_defender()) {
+ game.battle.defender_artillery = ahits*2
+ }
+}
+
+states.culverins_and_falconets = {
+ inactive: "Culverins and Falconets",
+ prompt() {
+ let done = true
+ view.prompt = `Use Culverin and Falconets ?`
+ for (let lord of game.battle.array) {
+ if (lord !== NOBODY) {
+ if (is_friendly_lord(lord) && (lord_has_capability(lord, AOW_YORK_CULVERINS_AND_FALCONETS))) {
+ gen_action_card(AOW_YORK_CULVERINS_AND_FALCONETS)
+ done = false
+ }
+ if (is_friendly_lord(lord) && (lord_has_capability(lord, AOW_LANCASTER_CULVERINS_AND_FALCONETS))) {
+ gen_action_card(AOW_LANCASTER_CULVERINS_AND_FALCONETS)
+ done = false
+ }
+ }
+ }
+ if (done) {
+ view.prompt = "Culverins and Falconets : Done"
+ }
+ view.actions.done = 1
+ },
+ card(c) {
+ let die = roll_die()
+ let lord = find_lord_with_capability_card(c)
+ if (is_event_in_play(EVENT_YORK_PATRICK_DE_LA_MOTE) && game.active === YORK) {
+ let die2 = roll_die()
+ die += die2
+ }
+ logi(`${data.lords[lord].name} Artillery does ${die} hits`)
+ artillery_hits(die)
+ discard_lord_capability(lord, c)
+ },
+ done() {
+ if (is_defender()) {
+ set_active_enemy()
+ }
+ else {
+ goto_engagement_total_hits()
+ }
+ }
+}
+
+// === BATTLE EVENT: SWIFT MANEUVER ===
+
+function is_swift_maneuver_in_play() {
+ return is_event_in_play(EVENT_YORK_SWIFT_MANEUVER)
+}
+
+states.swift_maneuver = {
+ inactive: "Swift Maneuver",
+ prompt() {
+ view.prompt = "Swift Maneuver: You may end the round now"
+ view.actions.end_battle_round = 1
+ view.actions.pass = 1
+ },
+ end_battle_round() {
+ logevent(`${EVENT_YORK_SWIFT_MANEUVER}`)
+ log("Ended Action Round.")
+ set_active_enemy()
+ goto_end_battle_round()
+ },
+ pass() {
+ logevent(`${EVENT_YORK_SWIFT_MANEUVER}`)
+ log("Passed.")
+ set_active_enemy()
+ pop_state()
+ },
+}
+
+// === 4.4.2 BATTLE ROUNDS ===
function goto_battle_rounds() {
set_active_defender()
@@ -8832,6 +5770,8 @@ function goto_battle_rounds() {
goto_flee()
}
+// === 4.4.2 BATTLE ROUNDS: FLEE ===
+
function goto_flee() {
game.state = "flee_battle"
}
@@ -8881,7 +5821,7 @@ states.flee_battle = {
},
}
-// === BATTLE: REPOSITION ===
+// === 4.4.2 BATTLE ROUNDS: REPOSITION ===
function slide_array(from, to) {
game.battle.array[to] = game.battle.array[from]
@@ -9043,107 +5983,8 @@ states.reposition_center = {
},
}
-// === BATTLE: STRIKE ===
-
-function filled(pos) {
- if (game.battle.array[pos] !== NOBODY && !ravine_check(game.battle.ravine, pos)) {
- return true
- }
- return false
-}
-const battle_strike_positions = [ D1, D2, D3, A1, A2, A3 ]
-
-const battle_steps = [
- { name: "Archery", hits: count_archery_hits },
- { name: "Melee", hits: count_melee_hits },
-]
-
-function count_archery_hits(lord) {
- let hits = 0
- hits += get_lord_forces(lord, LONGBOWMEN) << 2
- hits += get_lord_forces(lord, BURGUNDIANS) << 2
- hits += get_lord_forces(lord, MILITIA)
- hits += get_lord_forces(lord, MERCENARIES)
-
- if (is_leeward_battle_line_in_play(lord)) {
- return hits/2
- }
-
- return hits
-}
-
-function count_melee_hits(lord) {
- let hits = 0
- hits += /*retinue*/ 3 << 1
- //hits += count_vassals_with_lord(lord) << 2
- if (lord_has_capability(lord, AOW_LANCASTER_CHEVALIERS))
- hits += get_lord_forces(lord, MEN_AT_ARMS) << 2
- else
- hits += get_lord_forces(lord, MEN_AT_ARMS) << 1
- hits += get_lord_forces(lord, MILITIA)
- hits += get_lord_forces(lord, MERCENARIES)
- hits += get_lord_forces(lord, BURGUNDIANS) << 1
-
- if (lord === game.battle.caltrops) {
- hits += 2
- }
-
- return hits
-}
-
-function count_lord_hits(lord) {
- return battle_steps[game.battle.step].hits(lord)
-}
-
-function is_battle_over() {
- set_active_attacker()
- if (has_no_unrouted_forces())
- return true
- set_active_defender()
- if (has_no_unrouted_forces())
- return true
- return false
-}
-
-function has_no_unrouted_forces() {
- // All unrouted lords are either in battle array or in reserves
- for (let p = 0; p < 6; ++p)
- if (is_friendly_lord(game.battle.array[p]))
- return false
- for (let lord of game.battle.reserves)
- if (is_friendly_lord(lord))
- return false
- return true
-}
-
-function is_attacker() {
- return game.active === game.battle.attacker
-}
-
-function is_defender() {
- return game.active !== game.battle.attacker
-}
-
-function is_archery_step() {
- return game.battle.step === 0
-}
-
-function is_melee_step() {
- return game.battle.step === 1
-}
-
-function has_strike(pos) {
- return game.battle.ah[pos] > 0
-}
-
-// === BATTLE: ENGAGEMENTS
-
-function ravine_check(lord,pos) {
- if (game.battle.array[pos] === lord)
- return true
- return false
-}
+// === 4.4.2 BATTLE ROUNDS: ENGAGE / STRIKE ===
function determine_engagements() {
let center = [ A2, D2 ]
@@ -9167,33 +6008,6 @@ function determine_engagements() {
return results
}
-// === BATTLE: STRIKE ===
-
-// for each battle step:
-// generate strikes for each lord
-// while strikes remain:
-// create list of strike groups (choose left/right both rows)
-// select strike group
-// create target group (choose if sally)
-// total strikes and roll for walls
-// while hits remain:
-// assign hit to unit in target group
-// if lord routs:
-// forget choice of left/right strike group in current row
-// create new target group (choose if left/right/sally)
-
-function format_strike_step() {
- return battle_steps[game.battle.step].name
-}
-
-function format_hits() {
- if (game.battle.ahits > 0) {
- return `${game.battle.ahits} Hit${game.battle.ahits > 1 ? "s" : ""}`
- } else if (game.battle.dhits > 0) {
- return `${game.battle.dhits} Hit${game.battle.dhits > 1 ? "s" : ""}`
- }
-}
-
function goto_first_engagement() {
game.battle.step = 0
game.battle.engagements = determine_engagements()
@@ -9289,79 +6103,20 @@ function resume_engagement() {
}
}
-// === BATTLE: CULVERINS AND FALCONETS ===
-
-function goto_culverins() {
- let can_play = false
- for (let lord of game.battle.array) {
- if (is_lancaster_lord(lord) && lord_has_capability(lord, AOW_LANCASTER_CULVERINS_AND_FALCONETS))
- can_play = true
- if (is_york_lord(lord) && lord_has_capability(lord, AOW_YORK_CULVERINS_AND_FALCONETS))
- can_play = true
- }
- if (can_play) {
- set_active_defender()
- game.state = "culverins_and_falconets"
- game.who = NOBODY
- }
- else {
- goto_engagement_total_hits()
- }
-}
-
-states.culverins_and_falconets = {
- inactive: "Culverins and Falconets",
- prompt() {
- let done = true
- view.prompt = `Use Culverin and Falconets ?`
- for (let lord of game.battle.array) {
- if (lord !== NOBODY) {
- if (is_friendly_lord(lord) && (lord_has_capability(lord, AOW_YORK_CULVERINS_AND_FALCONETS))) {
- gen_action_card(AOW_YORK_CULVERINS_AND_FALCONETS)
- done = false
- }
- if (is_friendly_lord(lord) && (lord_has_capability(lord, AOW_LANCASTER_CULVERINS_AND_FALCONETS))) {
- gen_action_card(AOW_LANCASTER_CULVERINS_AND_FALCONETS)
- done = false
- }
- }
- }
- if (done) {
- view.prompt = "Culverins and Falconets : Done"
- }
- view.actions.done = 1
- },
- card(c) {
- let die = roll_die()
- let lord = find_lord_with_capability_card(c)
- if (is_event_in_play(EVENT_YORK_PATRICK_DE_LA_MOTE) && game.active === YORK) {
- let die2 = roll_die()
- die += die2
- }
- logi(`${data.lords[lord].name} Artillery does ${die} hits`)
- artillery_hits(die)
- discard_lord_capability(lord, c)
- },
- done() {
- if (is_defender()) {
- set_active_enemy()
- }
- else {
- goto_engagement_total_hits()
- }
- }
-}
-
-function artillery_hits(ahits) {
- if (is_attacker()) {
- game.battle.attacker_artillery = ahits*2
- }
- if (is_defender()) {
- game.battle.defender_artillery = ahits*2
- }
-}
+// === 4.4.2 BATTLE ROUNDS: TOTAL HITS (ROUND UP) ===
-// === BATTLE: TOTAL HITS (ROUND UP) ===
+// for each battle step:
+// generate strikes for each lord
+// while strikes remain:
+// create list of strike groups (choose left/right both rows)
+// select strike group
+// create target group (choose if sally)
+// total strikes and roll for walls
+// while hits remain:
+// assign hit to unit in target group
+// if lord routs:
+// forget choice of left/right strike group in current row
+// create new target group (choose if left/right/sally)
function goto_engagement_total_hits() {
let ahits = 0
@@ -9420,7 +6175,7 @@ function log_hits(total, name) {
logi(`No ${name}s`)
}
-// === BATTLE: ASSIGN HITS TO UNITS / ROLL BY HIT / ROUT ===
+// === 4.4.2 BATTLE ROUNDS: APPLY HITS / PROTECTION / ROLL BY HIT / ROUT ===
function goto_defender_assign_hits() {
set_active_defender()
@@ -9675,10 +6430,11 @@ function action_assign_hits(lord, type, special) {
game.where = special
} else {
rout_unit(lord, type, special)
- // Switf Maneuver event
+ // Swift Maneuver event
if (is_swift_maneuver_in_play() && type === RETINUE) {
set_active_enemy()
push_state("swift_maneuver")
+ // TODO: add return here?
}
finish_action_assign_hits(lord)
}
@@ -9728,33 +6484,12 @@ states.spend_valour = {
},
}
-states.swift_maneuver = {
- inactive: "Swift Maneuver",
- prompt() {
- view.prompt = "Swift Maneuver: You may end the round now"
- view.actions.end_battle_round = 1
- view.actions.pass = 1
- },
- end_battle_round() {
- logevent(`${EVENT_YORK_SWIFT_MANEUVER}`)
- log("Ended Action Round.")
- set_active_enemy()
- goto_end_battle_round()
- },
- pass() {
- logevent(`${EVENT_YORK_SWIFT_MANEUVER}`)
- log("Passed.")
- set_active_enemy()
- pop_state()
- },
-}
+// === BATTLE: NEW ROUND ===
function goto_end_battle_round() {
end_battle_round()
}
-// === BATTLE: NEW ROUND ===
-
function end_battle_round() {
game.battle.ravine = NOBODY
let attacker_loser = null
@@ -9785,11 +6520,12 @@ function end_battle_round() {
game.battle.ambush = 0
+ // TODO: goto_battle_rounds() instead?
set_active_defender()
goto_flee()
}
-// === ENDING THE BATTLE ===
+// === 4.4.3 ENDING THE BATTLE ===
// Ending the Battle - optimized from rules as written
// Loser retreat / withdraw / remove
@@ -9803,10 +6539,10 @@ function set_active_loser() {
}
function set_active_victor() {
- if (game.battle.loser === P1)
- set_active(P2)
+ if (game.battle.loser === YORK)
+ set_active(LANCASTER)
else
- set_active(P1)
+ set_active(YORK)
}
function end_battle() {
@@ -9830,6 +6566,8 @@ function has_defeated_lords() {
return false
}
+// === 4.4.3 ENDING THE BATTLE: INFLUENCE ===
+
function goto_battle_influence() {
if (game.battle.loser !== BOTH) {
set_active_loser()
@@ -9849,7 +6587,7 @@ function goto_battle_influence() {
}
}
-// === ENDING THE BATTLE: LOSSES ===
+// === 4.4.3 ENDING THE BATTLE: LOSSES ===
function has_battle_losses() {
for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord)
@@ -9937,7 +6675,7 @@ states.battle_losses = {
},
}
-// === ENDING THE BATTLE: SPOILS (VICTOR) ===
+// === 4.4.3 ENDING THE BATTLE: SPOILS ===
function log_spoils() {
if (game.spoils[PROV] > 0)
@@ -9946,17 +6684,6 @@ function log_spoils() {
logi(game.spoils[CART] + " Cart")
}
-function is_neutral_locale(loc) {
- return !has_favourl_marker(loc) && !has_favoury_marker(loc)
-}
-
-function has_favour_in_locale(side, loc) {
- if (side === YORK)
- return has_favoury_marker(loc)
- else
- return has_favourl_marker(loc)
-}
-
function calculate_spoils() {
let n_prov = 0
let n_cart = 0
@@ -10054,6 +6781,8 @@ states.battle_spoils = {
},
}
+// === 4.4.3 ENDING THE BATTLE: DEATH CHECK AND DISBAND ===
+
function goto_death_or_disband() {
remove_battle_capability_troops()
if (has_defeated_lords()) {
@@ -10077,6 +6806,23 @@ function end_death_or_disband() {
}
}
+function prompt_battle_events_death() {
+ // both attacker and defender events
+ if (game.active === LANCASTER) {
+ if (can_play_escape_ship())
+ gen_action_card_if_held(EVENT_LANCASTER_ESCAPE_SHIP)
+ if (can_play_warden_of_the_marches())
+ gen_action_card_if_held(EVENT_LANCASTER_WARDEN_OF_THE_MARCHES)
+ if (can_play_talbot_to_the_rescue())
+ gen_action_card_if_held(EVENT_LANCASTER_TALBOT_TO_THE_RESCUE)
+ }
+ if (game.active === YORK) {
+ if (can_play_escape_ship())
+ gen_action_card_if_held(EVENT_YORK_ESCAPE_SHIP)
+ }
+ view.actions.done = 1
+}
+
states.death_or_disband = {
inactive: "Death or Disband",
prompt() {
@@ -10110,7 +6856,7 @@ states.death_or_disband = {
let threshold = 2
let modifier = 0
- // === CAPABILITY : BLOODY THOU ART, BLOODY WILL BE THE END === //
+ // CAPABILITY: BLOODY THOU ART, BLOODY WILL BE THE END
if (is_lancaster_lord(lord) && game.flags.bloody === 1) {
logcap(AOW_YORK_BLOODY_THOU_ART)
disband_lord(lord, true)
@@ -10135,7 +6881,166 @@ states.death_or_disband = {
card: action_held_event,
}
-// === ENDING THE BATTLE: VASSAL DISBAND ===
+// === DEATH CHECK EVENT: ESCAPE SHIP ===
+
+function can_play_escape_ship() {
+ return can_escape_at(game.battle.where)
+}
+
+function can_escape_at(here) {
+ if (game.active === YORK && has_favoury_marker(here) && is_seaport(here))
+ return true
+ if (game.active === LANCASTER && has_favourl_marker(here) && is_seaport(here))
+ return true
+ if (search_escape_route(here))
+ return true
+ return false
+}
+
+function search_escape_route(start) {
+ search_seen.fill(0)
+ search_seen[start] = 1
+ let queue = [start]
+
+ while (queue.length > 0) {
+ let here = queue.shift()
+
+ // Check if the current locale is a seaport
+ if (is_seaport(here)) {
+ return true
+ }
+
+ if (is_friendly_locale(here)) {
+ for (let next of data.locales[here].adjacent) {
+ if (!search_seen[next]) {
+ search_seen[next] = 1
+ queue.push(next)
+ }
+ }
+ }
+ }
+ return false
+}
+
+function goto_play_escape_ship() {
+ push_state("escape_ship")
+ game.who = NOBODY
+}
+
+states.escape_ship = {
+ inactive: `Escape ship`,
+ prompt() {
+ view.prompt = "Escape Ship: Your lords go to Exile."
+ view.actions.escape_ship = 1
+ },
+ escape_ship() {
+ push_undo()
+ for (let lord of game.battle.fled) {
+ log(`${lord_name[lord]} went to exile.`)
+ exile_lord(lord)
+ set_delete(game.battle.fled, lord)
+ }
+ for (let lord of game.battle.routed) {
+ log(`${lord_name[lord]} went to exile.`)
+ exile_lord(lord)
+ set_delete(game.battle.routed, lord)
+ }
+ goto_battle_aftermath()
+ },
+}
+
+// === DEATH CHECK EVENT: TALBOT TO THE RESCUE ===
+
+function can_play_talbot_to_the_rescue() {
+ return true
+}
+
+function goto_play_talbot_to_the_rescue() {
+ throw "TODO"
+}
+
+// === DEATH CHECK EVENT: WARDEN OF THE MARCHES ===
+
+function can_play_warden_of_the_marches() {
+ // TOOD : Maybe a bug with blocked ford/exile ?
+ let can_play = false
+ for (let loc = first_locale; loc <= last_locale; loc++) {
+ if (is_friendly_locale(loc) && is_north(loc) && loc !== game.battle.where) {
+ can_play = true
+ }
+ }
+ if (!can_play) {
+ return false
+ }
+ // if blocked ford then flee
+ if (is_north(game.where))
+ return true
+ // if battle
+ if (is_north(game.battle.where))
+ return true
+ return false
+}
+
+function goto_play_warden_of_the_marches() {
+ push_undo()
+ push_state("warden_of_the_marches")
+}
+
+states.warden_of_the_marches = {
+ inactive: "Warden of the Marches",
+ prompt() {
+ let done = true
+ view.prompt = "Warden of the Marches: Select a friendly locale in the North to move routed lords there"
+ for (let loc = first_locale; loc <= last_locale; loc++) {
+ if (is_friendly_locale(loc) && is_north(loc) && loc !== game.battle.where) {
+ done = false
+ gen_action_locale(loc)
+ }
+ }
+ if (done) {
+ view.actions.done = 1
+ }
+ },
+ locale(loc) {
+ push_undo()
+ for (let lord = first_lancaster_lord; lord <= last_lancaster_lord; lord++) {
+ if (get_lord_locale(lord) === game.battle.where) {
+ set_lord_locale(lord, loc)
+ if (!lord_has_unrouted_troops(lord)) {
+ disband_lord(lord, false)
+ }
+ else {
+ set_lord_forces(lord, RETINUE, 1)
+ }
+ for (let x = 0; x < FORCE_TYPE_COUNT; ++x) {
+ set_lord_forces(lord, x, 0)
+ if (get_lord_routed_forces(lord, x) > 0) {
+ set_lord_routed_forces(lord, x, 0)
+ }
+ }
+ for_each_vassal_with_lord(lord, v => {
+ if (set_has(game.battle.routed_vassals, v)) {
+ array_remove(game.battle.routed_vassals, v)
+ disband_vassal(v)
+ }
+ })
+ }
+ }
+ logi(`Moved to ${data.locales[loc].name}`)
+ end_warden_of_the_marches()
+ },
+ done() {
+ end_warden_of_the_marches()
+ },
+}
+
+function end_warden_of_the_marches() {
+ game.flags.warden_of_the_marches = 1
+ game.who = NOBODY
+ pop_state()
+}
+
+// === 4.4.4 ENDING THE BATTLE: AFTERMATH ===
function goto_battle_aftermath() {
set_active(game.battle.attacker)
@@ -10164,12 +7069,13 @@ function goto_battle_aftermath() {
end_march()
}
-// === CAMPAIGN: FEED ===
+// === 4.7 FEED ===
function can_feed_from_shared(lord) {
let loc = get_lord_locale(lord)
return get_shared_assets(loc, PROV) > 0
}
+
function can_pay_from_shared(lord) {
let loc = get_lord_locale(lord)
return get_shared_assets(loc, COIN) > 0
@@ -10312,739 +7218,22 @@ function end_feed() {
goto_remove_markers()
}
-// === LEVY & CAMPAIGN: PAY ===
-
-function reset_unpaid_lords() {
- for (let lord = first_friendly_lord; lord <= last_friendly_lord; lord++) {
- if (is_lord_unfed(lord)) {
- set_lord_unfed(lord, Math.ceil(count_lord_all_forces(lord) / 6))
- }
- }
-}
-
-function goto_pay() {
- log_br()
- let n = 0
- for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord) {
- let here = get_lord_locale(lord)
- if (is_lord_on_map(lord) &&
- !is_lord_on_calendar(lord) &&
- lord_has_capability(lord, AOW_LANCASTER_MADAME_LA_GRANDE) &&
- (((is_friendly_locale(here)) && data.port_2.includes(here)) ||
- is_adjacent_friendly_port_english_channel(here))) {
- add_lord_assets(lord, COIN, 1)
- }
- if (
- game.active === LANCASTER &&
- is_lord_on_map(lord) &&
- lord_has_capability(LORD_NORTHUMBERLAND_L, AOW_LANCASTER_PERCYS_POWER) &&
- is_lord_in_north(LORD_NORTHUMBERLAND_L) &&
- is_lord_in_north(lord)
- ) {
- set_lord_unfed(lord, 0)
- } else {
- n = Math.ceil(count_lord_all_forces(lord) / 6)
- set_lord_unfed(lord, n)
- }
- }
- game.state = "pay"
-}
-
-states.pay = {
- inactive: "Pay",
- prompt() {
- view.prompt = "Pay: You must Pay your Lord's Troops"
- let done = true
-
- // Pay from own mat
- if (done) {
- for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord) {
- if (is_lord_unfed(lord)) {
- if (get_lord_assets(lord, COIN) > 0) {
- gen_action_coin(lord)
- done = false
- }
- }
- }
- }
-
- // Sharing
- if (done) {
- view.prompt = "Pay: You must Pay Lords with Shared Coin."
- for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord) {
- if (is_lord_unfed(lord) && can_pay_from_shared(lord)) {
- gen_action_lord(lord)
- done = false
- }
- }
- }
-
- if (done) {
- view.prompt = "Pay: You must Pillage and/or Disband."
- for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord) {
- if (is_lord_unfed(lord)) {
- view.actions.pillage = 1
- done = false
- }
- }
- }
-
- // All done!
- if (done) {
- view.prompt = "Pay: All done."
- view.actions.end_pay = 1
- }
- },
- coin(lord) {
- push_undo()
- add_lord_assets(lord, COIN, -1)
- pay_lord(lord)
- },
- lord(lord) {
- push_undo()
- game.who = lord
- game.state = "pay_lord_shared"
- },
- pillage() {
- push_undo()
- reset_unpaid_lords()
- goto_pillage_coin()
- },
- end_pay() {
- end_pay()
- },
- card: action_held_event,
-}
-
-states.pay_lord_shared = {
- inactive: "Pay",
- prompt() {
- view.prompt = `Pay: You must Feed ${lord_name[game.who]} with Shared Coin.`
- let loc = get_lord_locale(game.who)
- for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord) {
- if (get_lord_locale(lord) === loc) {
- if (get_lord_assets(lord, COIN) > 0)
- gen_action_coin(lord)
- }
- }
- },
- coin(lord) {
- push_undo()
- add_lord_assets(lord, COIN, -1)
- pay_lord(game.who)
- resume_pay_lord_shared()
- },
-}
-
-function resume_pay_lord_shared() {
- if (!is_lord_unfed(game.who) || !can_pay_from_shared(game.who)) {
- game.who = NOBODY
- game.state = "pay"
- }
-}
-
-function end_pay() {
- game.who = NOBODY
- set_active_enemy()
- if (game.active === P2) {
- goto_pay()
- } else
- goto_pay_lords()
-}
-
-function has_friendly_lord_who_must_pay_troops() {
- for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord)
- if (is_lord_unfed(lord))
- return true
- return false
-}
-
-function goto_pay_lords() {
- for (let lord = first_friendly_lord; lord <= last_friendly_lord; lord++) {
- if (is_lord_on_map(lord))
- set_lord_unfed(lord, 1)
- }
-
- if (has_friendly_lord_who_must_pay_troops()) {
- game.who = NOBODY
- game.state = "pay_lords"
- } else {
- end_pay_lords()
- }
-}
-
-function end_pay_lords() {
- set_active_enemy()
-
- if (game.active === P2)
- goto_pay_lords()
- else
- goto_pay_vassals()
-}
-
-states.pay_lords = {
- inactive: "Pay Lords",
- prompt() {
- view.prompt = "Pay Lords in Influence or Disband them."
- prompt_held_event()
- let done = true
- game.count = 0
- if (game.who === NOBODY) {
- for (let lord = first_friendly_lord; lord <= last_friendly_lord; lord++) {
- if (is_lord_on_map(lord) && is_lord_unfed(lord)) {
- gen_action_lord(lord)
- done = false
- }
- }
- if (done) {
- view.actions.done = 1
- }
- if (!done)
- view.actions.pay_all = 1
- } else {
- view.actions.disband = 1
- view.actions.pay = 1
- } },
- lord(lord) {
- push_undo()
- game.who = lord
- },
- disband() {
- push_undo()
- disband_lord(game.who)
- game.who = NOBODY
- },
- pay() {
- push_undo()
- reduce_influence(is_exile(get_lord_locale(game.who)) ? 2 : 1)
- set_lord_moved(game.who, 0)
- game.who = NOBODY
- },
- pay_all() {
- push_undo()
- for (let lord = first_friendly_lord; lord <= last_friendly_lord; lord++) {
- if (is_lord_on_map(lord) && is_lord_unfed(lord)) {
- ++game.count
- set_lord_moved(lord, 0)
- if (is_exile(get_lord_locale(lord))) {
- ++game.count
- }
- reduce_influence(game.count)
- game.count = 0
- }
- }
- game.who = NOBODY
-
- },
- card: action_held_event,
- done() {
- end_pay_lords()
- },
-}
-
-function goto_pay_vassals() {
- let vassal_to_pay = false
-
- for (let v = first_vassal; v <= last_vassal; v++) {
- if (
- is_vassal_mustered_with_friendly_lord(v) &&
- get_vassal_service(v) === current_turn()
- ) {
- vassal_to_pay = true
- }
- }
- if (vassal_to_pay) {
- game.state = "pay_vassals"
- game.what = NOBODY
- } else {
- end_pay_vassals()
- }
-}
-
-function end_pay_vassals() {
- set_active_enemy()
-
- if (game.active === P1) {
- goto_muster_exiles()
- } else {
- goto_pay_vassals()
- }
-}
-
-states.pay_vassals = {
- inactive: "Pay Vassals",
- prompt() {
- let done = true
- view.prompt = "You may pay or disband vassals in the next calendar box."
- if (game.what === NOBODY) {
- for (let v = first_vassal; v <= last_vassal; v++) {
- if (
- is_vassal_mustered_with_friendly_lord(v) &&
- get_vassal_service(v) === current_turn()
- ) {
- gen_action_vassal(v)
- done = false
- }
- }
-
- if (done) {
- view.actions.done = 1
- }
- if (!done)
- view.actions.pay_all = 1
- } else {
- view.actions.pay = 1
- view.actions.disband = 1
- }
- },
- vassal(v) {
- push_undo()
- game.what = v
- },
- pay() {
- push_undo()
- pay_vassal(game.what)
- reduce_influence(1)
- game.what = NOBODY
- },
- pay_all() {
- push_undo()
- for (let v = first_vassal; v <= last_vassal; v++) {
- if (is_vassal_mustered_with_friendly_lord(v)
- && get_vassal_service(v) === current_turn()) {
- pay_vassal(v)
- reduce_influence(1)
- game.what = NOBODY
- }
- }
- },
- disband() {
- push_undo()
- disband_vassal(game.what)
- game.what = NOBODY
- },
- done() {
- end_pay_vassals()
- },
-}
-
-function goto_ready_vassals() {
- for (let vassal = first_vassal; vassal <= last_vassal; vassal++) {
- if (get_vassal_service(vassal) === current_turn()) {
- set_vassal_lord_and_service(vassal, VASSAL_READY, 0)
- }
- }
-
- goto_levy_muster()
-}
-
-function goto_muster_exiles() {
- for (let x = first_friendly_lord; x <= last_friendly_lord; x++) {
- if ((get_lord_locale(x) === current_turn() + CALENDAR && get_lord_in_exile(x))
- || (is_lancaster_lord(x) && is_lord_on_calendar((get_lord_locale(x)) && get_lord_in_exile(x) && is_event_in_play(EVENT_LANCASTER_BE_SENT_FOR)))) {
- game.state = "muster_exiles"
- return
- }
- }
- end_muster_exiles()
-}
-
-function end_muster_exiles() {
- set_active_enemy()
-
- if (game.active === P1) {
- if (!check_disband_victory()) {
- goto_ready_vassals()
- }
- } else {
- goto_muster_exiles()
- }
-}
-
-states.muster_exiles = {
- inactive: "Muster Exiles",
- prompt() {
- view.prompt = "Muster Exiled Lords."
- let done = true
-
- if (game.who === NOBODY) {
- for (let x = first_friendly_lord; x <= last_friendly_lord; x++) {
- if ((get_lord_locale(x) === current_turn() + CALENDAR && get_lord_in_exile(x))
- || (is_lancaster_lord(x) && is_lord_on_calendar((get_lord_locale(x)) && get_lord_in_exile(x) && is_event_in_play(EVENT_LANCASTER_BE_SENT_FOR)))) {
- gen_action_lord(x)
- done = false
- }
- }
- } else {
- for (let loc of data.exile_boxes)
- if (has_favour_in_locale(game.active, loc))
- gen_action_locale(loc)
- }
-
- if (done) {
- view.actions.done = true
- }
- },
- lord(lord) {
- game.who = lord
- },
- locale(loc) {
- muster_lord_in_exile(game.who, loc)
- game.who = NOBODY
- },
- done() {
- end_muster_exiles()
- },
-}
-
-function muster_lord_in_exile(lord, exile_box) {
- remove_lord_from_exile(lord)
- muster_lord(lord, exile_box)
-}
-
-// === PILLAGE ===
-
-function goto_pillage_food() {
- push_state("pillage")
- game.what = PROV
-}
-
-function goto_pillage_coin() {
- push_state("pillage")
- game.what = COIN
-}
-
-function end_pillage() {
- pop_state()
-}
-
-function can_pillage(loc) {
- return !is_exile(loc) && !has_exhausted_marker(loc)
-}
-
-states.pillage = {
- inactive: "Pillage",
- prompt() {
- view.prompt = `Pillage: Pillage the locales where your ${game.what === PROV ? "unfed" : "unpaid"} lords are.`
-
- let done = true
- for (let x = first_friendly_lord; x <= last_friendly_lord; x++) {
- if (is_lord_on_map(x) && is_lord_unfed(x) && can_pillage(get_lord_locale(x))) {
- gen_action_locale(get_lord_locale(x))
- done = false
- }
- }
-
- if (done) {
- view.prompt = `Pillage: Unable to Pillage, you must disband your ${game.what === PROV ? "unfed" : "unpaid"} lords.`
- for (let x = first_friendly_lord; x <= last_friendly_lord; x++) {
- if (is_lord_on_map(x) && is_lord_unfed(x)) {
- gen_action_lord(x)
- done = false
- }
- }
- }
-
- if (done) {
- view.prompt = `Pillage: Done.`
- view.actions.done = 1
- }
- },
- locale(loc) {
- // pillage the Locale
- game.where = loc
- goto_pillage_locale()
- },
- lord(lord) {
- disband_influence_penalty(lord)
- disband_lord(lord)
- },
- done() {
- end_pillage()
- },
-}
-
-function goto_pillage_locale() {
- push_state("pillage_locale")
-}
-
-function end_pillage_locale() {
- pop_state()
- game.where = NOWHERE
- end_pillage()
-}
-
-states.pillage_locale = {
- inactive: "Pillage",
- prompt() {
- view.prompt = `Pillage: Choose Lord to Pillage ${data.locales[game.where].name}.`
-
- for (let x = first_friendly_lord; x <= last_friendly_lord; x++) {
- if (get_lord_locale(x) === game.where && is_lord_unfed(x)) {
- gen_action_lord(x)
- }
- }
- },
- lord(lord) {
- // Pillage
- // Same values as Taxing.
- let num = get_tax_amount(game.where)
- add_lord_assets(lord, COIN, num)
- add_lord_assets(lord, PROV, num)
- reduce_influence(4 * num)
-
- add_exhausted_marker(game.where)
- set_favour_enemy(game.where)
- for (let next of data.locales[game.where].adjacent)
- shift_favour_away(next)
-
- end_pillage_locale()
- },
-}
-
-// === LEVY & CAMPAIGN: DISBAND ===
-
-function disband_lord(lord, permanently = false) {
- let turn = current_turn()
- let extra = 6
-
- if (permanently) {
- log(`Removed L${lord}.`)
- set_lord_locale(lord, NOWHERE)
- } else if (lord_has_capability(lord, AOW_YORK_ENGLAND_IS_MY_HOME)) {
- set_lord_calendar(lord, turn + (extra - data.lords[lord].influence))
- log(`Disbanded L${lord} to turn ${current_turn() + 1}.`)
- }
- else {
- set_lord_calendar(lord, turn + (extra - data.lords[lord].influence))
- log(`Disbanded L${lord} to turn ${get_lord_calendar(lord)}.`)
- }
-
- discard_lord_capability_n(lord, 0)
- discard_lord_capability_n(lord, 1)
-
- for (let x = 0; x < ASSET_TYPE_COUNT; ++x)
- set_lord_assets(lord, x, 0)
-
- for (let x = 0; x < FORCE_TYPE_COUNT; ++x) {
- set_lord_forces(lord, x, 0)
- if (get_lord_routed_forces(lord, x) > 0) {
- set_lord_routed_forces(lord, x, 0)
- }
- }
-
- set_lord_moved(lord, 0)
-
- for_each_vassal_with_lord(lord, v => {
- disband_vassal(v)
- })
-}
-
-// === CAMPAIGN: REMOVE MARKERS ===
+// === 4.7 FEED: REMOVE MARKERS ===
function goto_remove_markers() {
clear_lords_moved()
goto_command_activation()
}
-// === END CAMPAIGN: GAME END ===
-
-function check_campaign_victory_york(inc_exiles = false) {
- for (let lord = first_lancaster_lord; lord <= last_lancaster_lord; ++lord)
- if (
- is_lord_on_map(lord) ||
- (inc_exiles && get_lord_locale(lord) === CALENDAR + current_turn() + 1 && get_lord_in_exile(lord))
- )
- return false
- return true
-}
-
-function check_campaign_victory_lancaster(inc_exiles = false) {
- for (let lord = first_york_lord; lord <= last_york_lord; ++lord)
- if (
- is_lord_on_map(lord) ||
- (inc_exiles && get_lord_locale(lord) === CALENDAR + current_turn() + 1 && get_lord_in_exile(lord))
- )
- return false
- return true
-}
-
-function check_campaign_victory() {
- let york_v = check_campaign_victory_york(true)
- let lancaster_v = check_campaign_victory_lancaster(true)
-
- if (york_v && lancaster_v) {
- goto_game_over("Draw", "The game ended in a draw.")
- return true
- } else if (york_v) {
- goto_game_over(YORK, `${YORK} won a Campaign Victory!`)
- return true
- } else if (lancaster_v) {
- goto_game_over(LANCASTER, `${LANCASTER} won a Campaign Victory!`)
- return true
- }
-
- return false
-}
-
-function check_disband_victory() {
- let york_v = check_campaign_victory_york()
- let lancaster_v = check_campaign_victory_lancaster()
-
- if (york_v && lancaster_v) {
- goto_game_over("Draw", "The game ended in a draw.")
- return true
- } else if (york_v) {
- goto_game_over(YORK, `${YORK} won a Campaign Victory!`)
- return true
- } else if (lancaster_v) {
- goto_game_over(LANCASTER, `${LANCASTER} won a Campaign Victory!`)
- return true
- }
-
- return false
-}
-
-function check_scenario_end_victory() {
- if (current_turn() === scenario_last_turn[game.scenario]) {
- // Scenario End Victory
-
- if (game.ip === 0)
- goto_game_over("Draw", "The game ended in a draw.")
- else if (game.ip > 0)
- goto_game_over(LANCASTER, `${LANCASTER} won with ${game.ip} Influence.`)
- else
- goto_game_over(YORK, `${YORK} won with ${Math.abs(game.ip)} Influence.`)
-
- return true
- }
- return false
-}
-
-function check_threshold_victory() {
- // This needs to change to account for graduated victory thresholds in some scenarios.
-
- if (Math.abs(game.ip) > game.victory_check) {
- if (game.ip > 0)
- goto_game_over(LANCASTER, `${LANCASTER} won with ${game.ip} Influence.`)
- else
- goto_game_over(YORK, `${YORK} won with ${Math.abs(game.ip)} Influence.`)
-
- return true
- }
-
- return false
-}
+// === 4.8 END CAMPAIGN ===
function goto_end_campaign() {
log_h1("End Campaign")
set_active(P1)
- tides_of_war()
-}
-
-function goto_game_end() {
- // GAME END
-
- if (!(check_scenario_end_victory() || check_campaign_victory() || check_threshold_victory())) {
- if (set_has(GROW_TURNS, current_turn())) {
- do_grow()
- } else if (set_has(WASTE_TURNS, current_turn())) {
- do_waste()
- } else {
- goto_reset()
- }
- }
-}
-
-function do_grow() {
- log("Grow:")
- logi("Changing all Depleted locales to Normal.")
- logi("Changing all Exhausted locales to Depleted.")
-
- for (let x = first_locale; x <= last_locale; x++) {
- refresh_locale(x)
- }
- goto_reset()
-}
-
-function do_waste() {
- log("Waste:")
- logi("Removing half of all lords provinder, carts, and ships.")
- logi("Resetting Lords Coin and Troops to initial values.")
- for (let x = first_lord; x <= last_lord; x++) {
- if (is_lord_on_map(x)) {
- do_lord_waste(x)
- }
- }
-
- goto_reset()
-}
-
-function do_lord_waste(lord) {
- remove_half(lord, PROV)
- remove_half(lord, CART)
- remove_half(lord, SHIP)
- set_lord_assets(lord, COIN, data.lords[lord].assets.coin)
- muster_lord_forces(lord)
-}
-
-function remove_half(lord, type) {
- set_lord_assets(lord, type, Math.ceil(get_lord_assets(lord, type) / 2))
-}
-
-// === END CAMPAIGN: RESET (DISCARD ARTS OF WAR) ===
-
-function goto_reset() {
- game.state = "reset"
-
- // Discard "This Campaign" events from play.
- discard_friendly_events("this_campaign")
-}
-
-states.reset = {
- inactive: "Reset",
- prompt() {
- view.prompt = "Reset: You may discard any held Arts of War cards desired."
- if (game.active === YORK) {
- for (let c = first_york_card; c <= last_york_card; ++c) {
- if (set_has(game.hand_y, c)) {
- gen_action_card(c)
- }
- }
- }
- if (game.active === LANCASTER) {
- for (let c = first_lancaster_card; c <= last_lancaster_card; ++c) {
- if (set_has(game.hand_l, c)) {
- gen_action_card(c)
- }
- }
- }
- view.actions.end_discard = 1
- },
- card(c) {
- push_undo()
- if (set_has(game.hand_y, c)) {
- log("Discarded Held card.")
- set_delete(game.hand_y, c)
- } else if (set_has(game.hand_l, c)) {
- log("Discarded Held card.")
- set_delete(game.hand_l, c)
- }
- },
- end_discard() {
- end_reset()
- },
-}
-
-function end_reset() {
- set_active_enemy()
- if (game.active === P2)
- goto_reset()
- else
- goto_advance_campaign()
+ goto_tides_of_war()
}
-// === END CAMPAIGN: TIDES OF WAR ===
+// === 4.8.1 END CAMPAIGN: TIDES OF WAR ===
function tides_calc() {
log_h3(`Tides of War`)
@@ -11322,7 +7511,7 @@ function tides_calc() {
game.influence -= domy
}
-function tides_of_war() {
+function goto_tides_of_war() {
if (lord_has_capability(LORD_BUCKINGHAM, AOW_LANCASTER_STAFFORD_ESTATES)) {
add_lord_assets(LORD_BUCKINGHAM, COIN, 1)
add_lord_assets(LORD_BUCKINGHAM, PROV, 1)
@@ -11336,7 +7525,7 @@ function tides_of_war() {
goto_disembark()
}
-// === END CAMPAIGN: DISEMBARK ===
+// === 4.8.2 END CAMPAIGN: DISEMBARK ===
function has_lords_at_sea() {
for (let x = first_friendly_lord; x <= last_friendly_lord; x++) {
@@ -11369,7 +7558,7 @@ function end_disembark() {
}
else {
set_active(P1)
- goto_game_end()
+ goto_victory_check()
}
}
@@ -11469,193 +7658,3867 @@ function goto_advance_campaign() {
goto_levy_arts_of_war()
}
-// === GAME OVER ===
+// === 4.8.3 END CAMPAIGN: VICTORY CHECK ===
-function goto_game_over(result, victory) {
- game.state = "game_over"
- game.active = "None"
- game.result = result
- game.victory = victory
- log_h1("Game Over")
- log(game.victory)
+function goto_victory_check() {
+ if (!(check_scenario_end_victory() || check_campaign_victory() || check_threshold_victory())) {
+ if (set_has(GROW_TURNS, current_turn())) {
+ do_grow()
+ } else if (set_has(WASTE_TURNS, current_turn())) {
+ do_waste()
+ } else {
+ goto_reset()
+ }
+ }
+}
+
+// === 4.8.4 END CAMPAIGN: GROW ===
+
+function do_grow() {
+ log("Grow:")
+ logi("Changing all Depleted locales to Normal.")
+ logi("Changing all Exhausted locales to Depleted.")
+
+ for (let x = first_locale; x <= last_locale; x++) {
+ refresh_locale(x)
+ }
+ goto_reset()
+}
+
+// === 4.8.5 END CAMPAIGN: WASTE ===
+
+function do_waste() {
+ log("Waste:")
+ logi("Removing half of all lords provinder, carts, and ships.")
+ logi("Resetting Lords Coin and Troops to initial values.")
+ for (let x = first_lord; x <= last_lord; x++) {
+ if (is_lord_on_map(x)) {
+ do_lord_waste(x)
+ }
+ }
+
+ goto_reset()
+}
+
+function do_lord_waste(lord) {
+ remove_half(lord, PROV)
+ remove_half(lord, CART)
+ remove_half(lord, SHIP)
+ set_lord_assets(lord, COIN, data.lords[lord].assets.coin)
+ muster_lord_forces(lord)
+}
+
+function remove_half(lord, type) {
+ set_lord_assets(lord, type, Math.ceil(get_lord_assets(lord, type) / 2))
+}
+
+// === 4.8.6 END CAMPAIGN: RESET (DISCARD ARTS OF WAR) ===
+
+function goto_reset() {
+ game.state = "reset"
+
+ // Discard "This Campaign" events from play.
+ discard_friendly_events("this_campaign")
+}
+
+states.reset = {
+ inactive: "Reset",
+ prompt() {
+ view.prompt = "Reset: You may discard any held Arts of War cards desired."
+ if (game.active === YORK) {
+ for (let c = first_york_card; c <= last_york_card; ++c) {
+ if (set_has(game.hand_y, c)) {
+ gen_action_card(c)
+ }
+ }
+ }
+ if (game.active === LANCASTER) {
+ for (let c = first_lancaster_card; c <= last_lancaster_card; ++c) {
+ if (set_has(game.hand_l, c)) {
+ gen_action_card(c)
+ }
+ }
+ }
+ view.actions.end_discard = 1
+ },
+ card(c) {
+ push_undo()
+ if (set_has(game.hand_y, c)) {
+ log("Discarded Held card.")
+ set_delete(game.hand_y, c)
+ } else if (set_has(game.hand_l, c)) {
+ log("Discarded Held card.")
+ set_delete(game.hand_l, c)
+ }
+ },
+ end_discard() {
+ end_reset()
+ },
+}
+
+function end_reset() {
+ set_active_enemy()
+ if (game.active === P2)
+ goto_reset()
+ else
+ goto_advance_campaign()
+}
+
+// === 5.1 CAMPAIGN VICTORY ===
+
+function check_campaign_victory_york(inc_exiles = false) {
+ for (let lord = first_lancaster_lord; lord <= last_lancaster_lord; ++lord)
+ if (
+ is_lord_on_map(lord) ||
+ (inc_exiles && get_lord_locale(lord) === CALENDAR + current_turn() + 1 && get_lord_in_exile(lord))
+ )
+ return false
return true
}
-states.game_over = {
- get inactive() {
- return game.victory
+function check_campaign_victory_lancaster(inc_exiles = false) {
+ for (let lord = first_york_lord; lord <= last_york_lord; ++lord)
+ if (
+ is_lord_on_map(lord) ||
+ (inc_exiles && get_lord_locale(lord) === CALENDAR + current_turn() + 1 && get_lord_in_exile(lord))
+ )
+ return false
+ return true
+}
+
+function check_campaign_victory() {
+ let york_v = check_campaign_victory_york(true)
+ let lancaster_v = check_campaign_victory_lancaster(true)
+
+ if (york_v && lancaster_v) {
+ goto_game_over("Draw", "The game ended in a draw.")
+ return true
+ } else if (york_v) {
+ goto_game_over(YORK, `${YORK} won a Campaign Victory!`)
+ return true
+ } else if (lancaster_v) {
+ goto_game_over(LANCASTER, `${LANCASTER} won a Campaign Victory!`)
+ return true
+ }
+
+ return false
+}
+
+function check_disband_victory() {
+ let york_v = check_campaign_victory_york()
+ let lancaster_v = check_campaign_victory_lancaster()
+
+ if (york_v && lancaster_v) {
+ goto_game_over("Draw", "The game ended in a draw.")
+ return true
+ } else if (york_v) {
+ goto_game_over(YORK, `${YORK} won a Campaign Victory!`)
+ return true
+ } else if (lancaster_v) {
+ goto_game_over(LANCASTER, `${LANCASTER} won a Campaign Victory!`)
+ return true
+ }
+
+ return false
+}
+
+// === 5.2 THRESHOLD VICTORY ===
+
+function check_threshold_victory() {
+ // This needs to change to account for graduated victory thresholds in some scenarios.
+
+ if (Math.abs(game.ip) > game.victory_check) {
+ if (game.ip > 0)
+ goto_game_over(LANCASTER, `${LANCASTER} won with ${game.ip} Influence.`)
+ else
+ goto_game_over(YORK, `${YORK} won with ${Math.abs(game.ip)} Influence.`)
+
+ return true
+ }
+
+ return false
+}
+
+// === 5.3 SCENARIO END VICTORY ===
+
+function check_scenario_end_victory() {
+ if (current_turn() === scenario_last_turn[game.scenario]) {
+ // Scenario End Victory
+
+ if (game.ip === 0)
+ goto_game_over("Draw", "The game ended in a draw.")
+ else if (game.ip > 0)
+ goto_game_over(LANCASTER, `${LANCASTER} won with ${game.ip} Influence.`)
+ else
+ goto_game_over(YORK, `${YORK} won with ${Math.abs(game.ip)} Influence.`)
+
+ return true
+ }
+ return false
+}
+
+// === 6.0 SCENARIOS ===
+
+exports.scenarios = [
+ "Ia. Henry VI",
+ "Ib. Towton",
+ "Ic. Somerset's Return",
+ "II. Warwicks' Rebellion",
+ "III. My Kingdom for a Horse",
+// TODO "I-III. Wars of the Roses",
+]
+
+const scenario_last_turn = {
+ "Ia. Henry VI": 15,
+ "Ib. Towton": 2,
+ "Ic. Somerset's Return": 8,
+ "II. Warwicks' Rebellion": 15,
+ "III. My Kingdom for a Horse": 15,
+ "I-III. Wars of the Roses": 15,
+}
+
+function is_card_in_scenario(_c) {
+ // TODO: Cards setup
+ return true
+}
+
+function muster_lord_forces(lord) {
+ let info = data.lords[lord]
+ set_lord_forces(lord, RETINUE, info.forces.retinue | 0)
+ set_lord_forces(lord, MEN_AT_ARMS, info.forces.men_at_arms | 0)
+ set_lord_forces(lord, LONGBOWMEN, info.forces.longbowmen | 0)
+ set_lord_forces(lord, MILITIA, info.forces.militia | 0)
+}
+
+function muster_lord(lord, locale) {
+ let info = data.lords[lord]
+
+ set_lord_locale(lord, locale)
+
+ set_lord_assets(lord, PROV, info.assets.prov | 0)
+ set_lord_assets(lord, COIN, info.assets.coin | 0)
+
+ set_lord_assets(lord, CART, info.assets.cart | 0)
+ set_lord_assets(lord, SHIP, info.ships | 0)
+
+ muster_lord_forces(lord)
+}
+
+exports.setup = function (seed, scenario, options) {
+ game = {
+ seed,
+ scenario,
+ hidden: options.hidden ? 1 : 0,
+
+ log: [],
+ undo: [],
+
+ active: null,
+ rebel: null,
+ state: "setup_lords",
+ stack: [],
+ victory_check: 0,
+ influence: 0,
+
+ hand_y: [],
+ hand_l: [],
+ plan_y: [],
+ plan_l: [],
+
+ turn: 0,
+ events: [], // this levy/this campaign cards
+
+ pieces: {
+ // per lord data
+ locale: [],
+ assets: [],
+ forces: [],
+ routed: [],
+ capabilities: [], // TODO map card -> lord instead of lord+slot -> card
+ moved: [],
+ in_exile: 0,
+
+ // per vassal data
+ vassals: Array(vassal_count).fill(VASSAL_OUT_OF_PLAY),
+
+ // per locale data
+ depleted: [],
+ exhausted: [],
+ favourl: [],
+ favoury: [],
+ propaganda: [],
+ },
+
+ flags: {
+ first_action: 0,
+ first_march_highway: 0,
+ free_levy: 0,
+ free_parley_henry:0,
+ free_parley_gloucester:0,
+ burgundians:0,
+ charity:0,
+ bloody:0,
+ london_for_york:0,
+ surprise_landing:0,
+ parliament_votes:0,
+ succession:0,
+ jack_cade:0,
+ commons_militia:0,
+ swap_battle_attacker:0,
+ supply_depot:0,
+ loyalty_and_trust:0,
+ warden_of_the_marches:0,
+ naval_blockade:0
+ },
+
+ command: NOBODY,
+ actions: 0,
+ group: 0,
+ intercept_group: 0,
+ who: NOBODY,
+ where: NOWHERE,
+ what: NOTHING,
+ which: NOTHING,
+ count: 0,
+
+ supply: 0,
+ march: 0,
+ battle: 0,
+ spoils: 0,
+ parley: 0,
+ }
+
+ log_h1(scenario)
+
+ switch (scenario) {
+ default:
+ case "Ia. Henry VI":
+ setup_Ia()
+ break
+ case "Ib. Towton":
+ setup_Ib()
+ break
+ case "Ic. Somerset's Return":
+ setup_Ic()
+ break
+ case "II. Warwicks' Rebellion":
+ setup_II()
+ break
+ case "III. My Kingdom for a Horse":
+ setup_III()
+ break
+ case "I-III. Wars of the Roses":
+ setup_ItoIII()
+ break
+ }
+
+ update_aliases()
+
+ goto_setup_lords()
+
+ return game
+}
+
+function setup_Ia() {
+ game.turn = 1 << 1
+
+ game.rebel = YORK
+ game.active = YORK
+ game.victory_check = 40
+ game.influence = 0
+ muster_lord(LORD_YORK, LOC_ELY)
+ muster_lord(LORD_MARCH, LOC_LUDLOW)
+ muster_lord(LORD_HENRY_VI, LOC_LONDON)
+ muster_lord(LORD_SOMERSET_1, LOC_LONDON)
+
+ set_lord_calendar(LORD_NORTHUMBERLAND_L, 2)
+ set_lord_calendar(LORD_EXETER_1, 3)
+ set_lord_calendar(LORD_BUCKINGHAM, 5)
+ set_lord_calendar(LORD_SALISBURY, 2)
+ set_lord_calendar(LORD_WARWICK_Y, 3)
+ set_lord_calendar(LORD_RUTLAND, 5)
+
+ add_favourl_marker(LOC_LONDON)
+ add_favourl_marker(LOC_WELLS)
+ add_favourl_marker(LOC_SCOTLAND)
+ add_favourl_marker(LOC_FRANCE)
+
+ add_favoury_marker(LOC_ELY)
+ add_favoury_marker(LOC_LUDLOW)
+ add_favoury_marker(LOC_BURGUNDY)
+ add_favoury_marker(LOC_IRELAND)
+
+ setup_vassals()
+}
+
+function setup_Ib() {
+ game.turn = 1 << 1
+
+ game.rebel = YORK
+ game.active = YORK
+ game.victory_check = 45
+ game.influence = 0
+ muster_lord(LORD_NORFOLK, LOC_LONDON)
+ muster_lord(LORD_WARWICK_Y, LOC_LONDON)
+ muster_lord(LORD_MARCH, LOC_LUDLOW)
+ muster_lord(LORD_EXETER_1, LOC_NEWCASTLE)
+ muster_lord(LORD_SOMERSET_1, LOC_NEWCASTLE)
+ muster_lord(LORD_NORTHUMBERLAND_L, LOC_CARLISLE)
+
+ add_favourl_marker(LOC_ST_ALBANS)
+ add_favourl_marker(LOC_SCARBOROUGH)
+ add_favourl_marker(LOC_NEWCASTLE)
+ add_favourl_marker(LOC_BAMBURGH)
+ add_favourl_marker(LOC_HEXHAM)
+ add_favourl_marker(LOC_APPLEBY)
+ add_favourl_marker(LOC_CARLISLE)
+ add_favourl_marker(LOC_SCOTLAND)
+ add_favourl_marker(LOC_FRANCE)
+
+ add_favoury_marker(LOC_LONDON)
+ add_favoury_marker(LOC_CALAIS)
+ add_favoury_marker(LOC_GLOUCESTER)
+ add_favoury_marker(LOC_HEREFORD)
+ add_favoury_marker(LOC_OXFORD)
+ add_favoury_marker(LOC_SALISBURY)
+ add_favoury_marker(LOC_WINCHESTER)
+ add_favoury_marker(LOC_GUILDFORD)
+ add_favoury_marker(LOC_ARUNDEL)
+ add_favoury_marker(LOC_HASTINGS)
+ add_favoury_marker(LOC_DOVER)
+ add_favoury_marker(LOC_ROCHESTER)
+ add_favoury_marker(LOC_CANTERBURY)
+ add_favoury_marker(LOC_SOUTHAMPTON)
+ add_favoury_marker(LOC_BURGUNDY)
+ add_favoury_marker(LOC_IRELAND)
+
+ setup_vassals([ VASSAL_FAUCONBERG, VASSAL_NORFOLK ])
+ muster_vassal(VASSAL_FAUCONBERG, LORD_MARCH)
+}
+
+function setup_Ic() {
+ game.turn = 5 << 1
+
+ game.rebel = YORK
+ game.active = YORK
+ game.victory_check = 40
+ game.influence = 6
+ muster_lord(LORD_WARWICK_Y, LOC_LONDON)
+ muster_lord(LORD_MARCH, LOC_LONDON)
+ muster_lord(LORD_SOMERSET_1, LOC_BAMBURGH)
+
+ set_lord_calendar(LORD_HENRY_VI, 5)
+
+ add_favourl_marker(LOC_SCARBOROUGH)
+ add_favourl_marker(LOC_NEWCASTLE)
+ add_favourl_marker(LOC_BAMBURGH)
+ add_favourl_marker(LOC_HEXHAM)
+ add_favourl_marker(LOC_APPLEBY)
+ add_favourl_marker(LOC_CARLISLE)
+ add_favourl_marker(LOC_HARLECH)
+ add_favourl_marker(LOC_PEMBROKE)
+ add_favourl_marker(LOC_CARDIFF)
+ add_favourl_marker(LOC_CHESTER)
+ add_favourl_marker(LOC_LANCASTER)
+ add_favourl_marker(LOC_SCOTLAND)
+ add_favourl_marker(LOC_FRANCE)
+
+ add_favoury_marker(LOC_LONDON)
+ add_favoury_marker(LOC_CALAIS)
+ add_favoury_marker(LOC_LUDLOW)
+ add_favoury_marker(LOC_HEREFORD)
+ add_favoury_marker(LOC_SALISBURY)
+ add_favoury_marker(LOC_WINCHESTER)
+ add_favoury_marker(LOC_GUILDFORD)
+ add_favoury_marker(LOC_ARUNDEL)
+ add_favoury_marker(LOC_HASTINGS)
+ add_favoury_marker(LOC_DOVER)
+ add_favoury_marker(LOC_ROCHESTER)
+ add_favoury_marker(LOC_CANTERBURY)
+ add_favoury_marker(LOC_SOUTHAMPTON)
+ add_favoury_marker(LOC_BURGUNDY)
+ add_favoury_marker(LOC_IRELAND)
+
+ setup_vassals()
+}
+
+function setup_II() {
+ game.turn = 1 << 1
+
+ game.rebel = LANCASTER
+ game.active = LANCASTER
+ game.victory_check = 40
+ game.influence = 0
+ muster_lord(LORD_EDWARD_IV, LOC_LONDON)
+ muster_lord(LORD_PEMBROKE, LOC_PEMBROKE)
+ muster_lord(LORD_WARWICK_L, LOC_CALAIS)
+ muster_lord(LORD_CLARENCE, LOC_YORK)
+ muster_lord(LORD_JASPER_TUDOR_1, LOC_HARLECH)
+
+ set_lord_calendar(LORD_DEVON, 1)
+ set_lord_calendar(LORD_GLOUCESTER_1, 9)
+ set_lord_calendar(LORD_NORTHUMBERLAND_Y1, 9)
+ set_lord_calendar(LORD_MARGARET, 9)
+ set_lord_in_exile(LORD_MARGARET)
+ set_lord_calendar(LORD_SOMERSET_2, 9)
+ set_lord_in_exile(LORD_SOMERSET_2)
+ set_lord_calendar(LORD_OXFORD, 9)
+ set_lord_in_exile(LORD_OXFORD)
+ set_lord_calendar(LORD_EXETER_2, 9)
+ set_lord_in_exile(LORD_EXETER_2)
+
+ add_favourl_marker(LOC_CALAIS)
+ add_favourl_marker(LOC_YORK)
+ add_favourl_marker(LOC_HARLECH)
+ add_favourl_marker(LOC_COVENTRY)
+ add_favourl_marker(LOC_WELLS)
+ add_favourl_marker(LOC_FRANCE)
+
+ add_favoury_marker(LOC_LONDON)
+ add_favoury_marker(LOC_ELY)
+ add_favoury_marker(LOC_LUDLOW)
+ add_favoury_marker(LOC_CARLISLE)
+ add_favoury_marker(LOC_PEMBROKE)
+ add_favoury_marker(LOC_EXETER)
+ add_favoury_marker(LOC_BURGUNDY)
+
+ setup_vassals([ VASSAL_DEVON, VASSAL_OXFORD ])
+
+ // TODO: Add Foreign Haven rule
+ // TODO: Add Skaky Allies rules
+}
+
+function setup_III() {
+ game.turn = 1 << 1
+
+ game.rebel = LANCASTER
+ game.active = LANCASTER
+ game.victory_check = 40
+ game.influence = 0
+ muster_lord(LORD_RICHARD_III, LOC_LONDON)
+ muster_lord(LORD_NORTHUMBERLAND_Y2, LOC_CARLISLE)
+ muster_lord(LORD_NORFOLK, LOC_ARUNDEL)
+ muster_lord(LORD_HENRY_TUDOR, LOC_FRANCE)
+ muster_lord(LORD_JASPER_TUDOR_2, LOC_FRANCE)
+ muster_lord(LORD_OXFORD, LOC_FRANCE)
+
+ add_favourl_marker(LOC_FRANCE)
+ add_favourl_marker(LOC_OXFORD)
+ add_favourl_marker(LOC_HARLECH)
+ add_favourl_marker(LOC_PEMBROKE)
+
+ add_favoury_marker(LOC_BURGUNDY)
+ add_favoury_marker(LOC_LONDON)
+ add_favoury_marker(LOC_CALAIS)
+ add_favoury_marker(LOC_CARLISLE)
+ add_favoury_marker(LOC_ARUNDEL)
+ add_favoury_marker(LOC_YORK)
+ add_favoury_marker(LOC_GLOUCESTER)
+
+ setup_vassals([ VASSAL_OXFORD, VASSAL_NORFOLK ])
+}
+
+function setup_ItoIII() {
+ game.turn = 1 << 1
+
+ game.rebel = YORK
+ game.active = YORK
+ game.victory_check = 45
+ game.influence = 0
+ muster_lord(LORD_YORK, LOC_ELY)
+ muster_lord(LORD_MARCH, LOC_LUDLOW)
+ muster_lord(LORD_HENRY_VI, LOC_LONDON)
+ muster_lord(LORD_SOMERSET_1, LOC_WELLS)
+
+ set_lord_calendar(LORD_NORTHUMBERLAND_L, 1)
+ set_lord_calendar(LORD_EXETER_1, 3)
+ set_lord_calendar(LORD_BUCKINGHAM, 5)
+ set_lord_calendar(LORD_SALISBURY, 2)
+ set_lord_calendar(LORD_WARWICK_Y, 3)
+ set_lord_calendar(LORD_RUTLAND, 5)
+
+ add_favourl_marker(LOC_LONDON)
+ add_favourl_marker(LOC_WELLS)
+ add_favourl_marker(LOC_SCOTLAND)
+ add_favourl_marker(LOC_FRANCE)
+
+ add_favoury_marker(LOC_ELY)
+ add_favoury_marker(LOC_LUDLOW)
+ add_favoury_marker(LOC_BURGUNDY)
+ add_favoury_marker(LOC_IRELAND)
+
+ setup_vassals()
+}
+
+// === 6.0 CAMPAIGN ===
+/*
+
+function should_remove_Y28_event_card() {
+ return game.scenario !== "I-III. Wars of the Roses"
+}
+
+function has_Y28_happened() {
+ //TODO: Scenario IIY and IIL when Y28 happens.
+ return false
+}
+
+function add_card_scenario(c) {
+ // TODO: Add card in scenario
+}
+
+function remove_card_scenario(c) {
+ //TODO: Remove card in scenario
+}
+
+function setup_II_Y() {
+ game.turn = 1 << 1
+ game.scenario = "IIY. The Kingmaker"
+ game.rebel = LANCASTER
+ game.active = LANCASTER
+ game.victory_check = 45
+ game.influence = 0
+
+ for (let lord = first_lord; lord <= last_lord; lord++) {
+ if (is_lord_in_play(lord)) {
+ disband_lord(lord, false)
+ }
+ }
+ for (let loc = first_locale; loc <= last_locale; loc++) {
+ remove_exhausted_marker(loc)
+ remove_depleted_marker(loc)
+ remove_favourl_marker(loc)
+ remove_favoury_marker(loc)
+ }
+ discard_events("this_levy")
+ discard_events("hold")
+ discard_events("this_campaign")
+
+ // Setup
+ // Yorkist setup
+ // TODO: Add cards Y1-Y13, Y25, Y26, Y27, Y29, Y30
+
+ if (is_lord_in_play(LORD_RUTLAND) && main_york_heir !== LORD_RUTLAND) {
+ muster_lord(LORD_RUTLAND, LOC_CANTERBURY)
+ add_favoury_marker(LOC_CANTERBURY)
+ }
+
+ set_lord_calendar(LORD_DEVON, 1)
+ set_lord_calendar(LORD_GLOUCESTER_1, 9)
+ set_lord_calendar(LORD_NORTHUMBERLAND_Y1, 9)
+
+ if (main_york_heir === LORD_YORK) {
+ muster_lord(LORD_YORK, LOC_CANTERBURY)
+ add_favoury_marker(LOC_LONDON)
+ if (is_lord_in_play(LORD_MARCH)) {
+ muster_lord(LORD_MARCH, LOC_LUDLOW)
+ }
+ // TODO: Add cards Y14, Y18, Y19, Y20
+ }
+
+ if (main_york_heir === LORD_MARCH) {
+ muster_lord(LORD_EDWARD_IV, LOC_LONDON)
+ // Removed because he can't appear in scenario III
+ disband_lord(LORD_MARCH, true)
+ // TODO: Add cards Y23, Y24, Y28, Y31
+ }
+
+ if (main_york_heir === LORD_RUTLAND) {
+ muster_lord(LORD_RUTLAND, LOC_LONDON)
+ // TODO: Add cards Y20, Y21, Y28, Y35
+ }
+
+ // If < 2 heirs, muster Pembroke
+ if ((main_york_heir === LORD_RUTLAND || main_york_heir === LORD_GLOUCESTER_1)
+ || (main_york_heir === LORD_EDWARD_IV && !is_lord_in_play(LORD_RUTLAND))) {
+ muster_lord(LORD_PEMBROKE, LOC_PEMBROKE)
+ }
+
+ // Lancaster setup
+ // TODO: Add cards L1-L3, L5-L13, L23, L24, L25, L29, L30, L36
+
+ if (main_lancaster_heir === LORD_HENRY_VI) {
+ set_lord_calendar(LORD_HENRY_VI, 9)
+ set_lord_in_exile(LORD_HENRY_VI)
+ // TODO: Add L17, L18, L20, L21
+ }
+ if (main_lancaster_heir === LORD_MARGARET) {
+ set_lord_calendar(LORD_MARGARET, 9)
+ set_lord_in_exile(LORD_MARGARET)
+
+ // TODO: Add L27, L28, L31 + L26 Special rule
+ }
+ if (main_lancaster_heir === LORD_SOMERSET_1 || main_lancaster_heir === LORD_SOMERSET_2) {
+ // TODO: Add cards L20, L21, L27
+ }
+
+ if (is_lord_in_play(LORD_SOMERSET_1)) {
+ set_lord_calendar(LORD_SOMERSET_1, 9)
+ set_lord_in_exile(LORD_SOMERSET_1)
+ }
+ else if (is_lord_in_play(LORD_SOMERSET_2)) {
+ set_lord_calendar(LORD_SOMERSET_2, 9)
+ set_lord_in_exile(LORD_SOMERSET_2)
+ }
+
+ muster_lord(LORD_WARWICK_L, LOC_CALAIS)
+ muster_lord(LORD_CLARENCE, LOC_YORK)
+ muster_lord(LORD_JASPER_TUDOR_1, LOC_HARLECH)
+ set_lord_calendar(LORD_OXFORD, 9)
+ set_lord_in_exile(LORD_OXFORD)
+ set_lord_calendar(LORD_EXETER_2, 9)
+ set_lord_in_exile(LORD_EXETER_2)
+
+ add_favourl_marker(LOC_CALAIS)
+ add_favourl_marker(LOC_YORK)
+ add_favourl_marker(LOC_HARLECH)
+ add_favourl_marker(LOC_COVENTRY)
+ add_favourl_marker(LOC_WELLS)
+
+ add_favoury_marker(LOC_LONDON)
+ add_favoury_marker(LOC_ELY)
+ add_favoury_marker(LOC_LUDLOW)
+ add_favoury_marker(LOC_CARLISLE)
+ add_favoury_marker(LOC_PEMBROKE)
+ add_favoury_marker(LOC_EXETER)
+
+ // Exile box setup
+ add_favourl_marker(LOC_FRANCE)
+ add_favoury_marker(LOC_BURGUNDY)
+
+ setup_vassals([ VASSAL_DEVON, VASSAL_OXFORD ])
+
+ // TODO: Add Foreign Haven rule
+ // TODO: Add Skaky Allies rules
+ // TODO: Natural causes rule
+
+}
+
+function setup_II_L() {
+ game.turn = 1 << 1
+ game.scenario = "IIL. Lancastrian Legitimacy Fades"
+ game.rebel = YORK
+ game.active = YORK
+ game.victory_check = 40
+ game.influence = 0
+
+ for (let lord = first_lord; lord <= last_lord; lord++) {
+ if (is_lord_in_play(lord)) {
+ disband_lord(lord, false)
+ }
+ }
+ for (let loc = first_locale; loc <= last_locale; loc++) {
+ remove_exhausted_marker(loc)
+ remove_depleted_marker(loc)
+ remove_favourl_marker(loc)
+ remove_favoury_marker(loc)
+ }
+ discard_events("this_levy")
+ discard_events("hold")
+ discard_events("this_campaign")
+
+ // Setup
+ // Lancaster setup
+ // TODO: Add cards L1-L3, L5-L13, L18, L19, L20, L21, L25, L29, L34
+
+ if (main_lancaster_heir === LORD_HENRY_VI) {
+ muster_lord(LORD_HENRY_VI, LOC_LONDON)
+ // TODO: Add L15, L17
+ if (is_lord_in_play(LORD_SOMERSET_1)) {
+ muster_lord(LORD_SOMERSET_1, LOC_WELLS)
+ }
+ if (is_lord_in_play(LORD_SOMERSET_2)) {
+ muster_lord(LORD_SOMERSET_2, LOC_WELLS)
+ }
+ }
+
+ if (main_lancaster_heir === LORD_MARGARET) {
+ set_lord_calendar(LORD_MARGARET, 1)
+ // TODO: Add L27, L31 + L26 Special rule
+ if (is_lord_in_play(LORD_SOMERSET_1)) {
+ muster_lord(LORD_SOMERSET_1, LOC_WELLS)
+ }
+ if (is_lord_in_play(LORD_SOMERSET_2)) {
+ muster_lord(LORD_SOMERSET_2, LOC_WELLS)
+ }
+ }
+ if (main_lancaster_heir === LORD_SOMERSET_1 || main_lancaster_heir === LORD_SOMERSET_2) {
+ // TODO: Add cards L16, L27
+ muster_lord(LORD_SOMERSET_1, LOC_LONDON)
+ if (main_lancaster_heir === LORD_SOMERSET_2) {
+ // Somerset 2 cylinder replaced by Somerset 1 cylinder
+ disband_lord(LORD_SOMERSET_2, true)
+ }
+ }
+
+ // Yorkist setup
+ // TODO: Add cards Y1-Y13, Y15, Y16, Y17, Y22, Y28, Y29, Y31, Y34
+
+ if (main_york_heir === LORD_YORK) {
+ set_lord_calendar(LORD_YORK, 7)
+ set_lord_in_exile(LORD_YORK)
+ // TODO: Add cards Y14, Y20
+ }
+
+ if (main_york_heir === LORD_MARCH) {
+ set_lord_calendar(LORD_MARCH, 7)
+ set_lord_in_exile(LORD_MARCH)
+ // TODO: Add cards Y20, 21
+ }
+
+ if (main_york_heir === LORD_RUTLAND) {
+ set_lord_calendar(LORD_MARCH, 7)
+ // TODO: Add cards Y20, Y21
+ }
+
+ if (main_york_heir === LORD_GLOUCESTER_1) {
+ // TODO: Add cards Y25, Y30
+ }
+
+ if (is_lord_in_play(LORD_MARCH) && main_york_heir !== LORD_MARCH) {
+ set_lord_calendar(LORD_MARCH, 7)
+ set_lord_in_exile(LORD_MARCH)
+ }
+
+ if (is_lord_in_play(LORD_RUTLAND) && main_york_heir !== LORD_RUTLAND) {
+ set_lord_calendar(LORD_RUTLAND, 7)
+ set_lord_in_exile(LORD_RUTLAND)
+ }
+ if (is_lord_in_play(LORD_GLOUCESTER_1) && main_york_heir !== LORD_GLOUCESTER_1) {
+ set_lord_calendar(LORD_GLOUCESTER_1, 7)
+ set_lord_in_exile(LORD_GLOUCESTER_1)
+ }
+
+ muster_lord(LORD_WARWICK_Y, LOC_CALAIS)
+ muster_lord(LORD_SALISBURY, LOC_YORK)
+ muster_lord(LORD_PEMBROKE, LOC_PEMBROKE)
+ muster_lord(LORD_JASPER_TUDOR_1, LOC_HARLECH)
+ set_lord_calendar(LORD_DEVON, 1)
+ set_lord_calendar(LORD_OXFORD, 2)
+ set_lord_calendar(LORD_EXETER_2, 2)
+ set_lord_calendar(LORD_NORTHUMBERLAND_L, 8)
+
+ add_favourl_marker(LOC_LONDON)
+ add_favourl_marker(LOC_HARLECH)
+ add_favourl_marker(LOC_OXFORD)
+ add_favourl_marker(LOC_WELLS)
+ add_favourl_marker(LOC_EXETER)
+ add_favourl_marker(LOC_CARLISLE)
+
+ add_favoury_marker(LOC_CALAIS)
+ add_favoury_marker(LOC_YORK)
+ add_favoury_marker(LOC_ELY)
+ add_favoury_marker(LOC_LUDLOW)
+ add_favoury_marker(LOC_PEMBROKE)
+
+ // Exile box setup
+ add_favourl_marker(LOC_FRANCE)
+ add_favoury_marker(LOC_BURGUNDY)
+
+ setup_vassals([ VASSAL_DEVON, VASSAL_OXFORD ])
+
+ // TODO: Add Foreign Haven rule
+ // TODO: Add Shaky Allies rules
+ // TODO: Natural causes rule
+
+}
+
+function setup_III_Y() {
+ game.turn = 1 << 1
+ game.scenario = "IIIY. New Rivals"
+ game.rebel = LANCASTER
+ game.active = LANCASTER
+ game.victory_check = 45
+ game.influence = 0
+
+ if (!is_lord_in_play(LORD_YORK)) {
+ game.influence += 8
+ }
+ if (!is_lord_in_play(LORD_MARCH) && !is_lord_in_play(LORD_EDWARD_IV)) {
+ game.influence += 8
+ }
+ if (!is_lord_in_play(LORD_RUTLAND)) {
+ game.influence += 8
+ }
+ if (!is_lord_in_play(LORD_GLOUCESTER_1) && !is_lord_in_play(LORD_GLOUCESTER_2) && !is_lord_in_play(LORD_RICHARD_III)) {
+ game.influence += 8
+ }
+ if (!is_lord_in_play(LORD_HENRY_VI)) {
+ game.influence -= 8
+ }
+ if (!is_lord_in_play(LORD_HENRY_VI) && !is_lord_in_play(LORD_MARGARET)) {
+ game.influence -= 8
+ }
+ if (!is_lord_in_play(LORD_SOMERSET_1)) {
+ game.influence -= 8
+ }
+ if (!is_lord_in_play(LORD_SOMERSET_1) && !is_lord_in_play(LORD_SOMERSET_2)) {
+ game.influence -= 8
+ }
+
+ for (let lord = first_lord; lord <= last_lord; lord++) {
+ if (is_lord_in_play(lord)) {
+ disband_lord(lord, false)
+ }
+ }
+ for (let loc = first_locale; loc <= last_locale; loc++) {
+ remove_exhausted_marker(loc)
+ remove_depleted_marker(loc)
+ remove_favourl_marker(loc)
+ remove_favoury_marker(loc)
+ }
+ discard_events("this_levy")
+ discard_events("hold")
+ discard_events("this_campaign")
+
+ // Yorkist Setup
+ // TODO: Add Y1-Y13, Y36
+
+ if (has_Y28_happened()) {
+ if (is_lord_in_play(LORD_RUTLAND) && (is_lord_in_play(LORD_GLOUCESTER_1) || is_lord_in_play(LORD_GLOUCESTER_2) || is_lord_in_play(LORD_RICHARD_III))) {
+ // If Gloucester (any) and Rutland, Rutland dies
+ disband_lord(LORD_RUTLAND, true)
+ }
+ }
+
+ if (main_york_heir === LORD_RUTLAND && (!is_lord_in_play(LORD_GLOUCESTER_1) && !is_lord_in_play(LORD_GLOUCESTER_2))) {
+ // If Rutland is lone heir, Rutland dies
+ disband_lord(LORD_RUTLAND, true)
+ //Warwick becomes king
+ muster_lord(LORD_WARWICK_Y, LOC_LONDON)
+ add_favoury_marker(LOC_LONDON)
+ muster_lord(LORD_SALISBURY, LOC_YORK)
+ add_favoury_marker(LOC_YORK)
+
+ // TODO: Add Y16, Y17, Y22
+ }
+
+ // If only 1 is alive
+ if (main_york_heir === LORD_YORK && !is_lord_in_play(LORD_MARCH) && !is_lord_in_play(LORD_RUTLAND) && !is_lord_in_play(LORD_GLOUCESTER_1)) {
+ muster_lord(LORD_NORTHUMBERLAND_Y2, LOC_CARLISLE)
+ add_favoury_marker(LOC_CARLISLE)
+
+ // TODO: Add Y37
+ }
+ if ((main_york_heir === LORD_MARCH || main_york_heir === LORD_EDWARD_IV) && !is_lord_in_play(LORD_RUTLAND) && !is_lord_in_play(LORD_GLOUCESTER_1)) {
+ muster_lord(LORD_NORTHUMBERLAND_Y2, LOC_CARLISLE)
+ add_favoury_marker(LOC_CARLISLE)
+ // TODO: Add Y37
+ }
+ if (main_york_heir === LORD_GLOUCESTER_1 || main_york_heir === LORD_RICHARD_III) {
+ muster_lord(LORD_NORTHUMBERLAND_Y2, LOC_CARLISLE)
+ add_favoury_marker(LOC_CARLISLE)
+ // TODO: Add Y37
+ }
+ muster_lord(LORD_NORFOLK, LOC_ARUNDEL)
+ add_favoury_marker(LOC_ARUNDEL)
+
+ if (main_york_heir === LORD_YORK) {
+ // TODO: Add Y14, Y21
+ if (is_lord_in_play(LORD_MARCH)) {
+ muster_lord(LORD_MARCH, LOC_LUDLOW)
+ add_favoury_marker(LOC_LUDLOW)
+ // Add Y20
+ // Only 2 heirs can stay
+ disband_lord(LORD_RUTLAND, true)
+ disband_lord(LORD_GLOUCESTER_1, true)
+ }
+ if (!is_lord_in_play(LORD_MARCH) && is_lord_in_play(LORD_RUTLAND)) {
+ muster_lord(LORD_RUTLAND, LOC_CANTERBURY)
+ add_favoury_marker(LOC_CANTERBURY)
+ // TODO: Add Y20
+ }
+ if (is_lord_in_play(LORD_GLOUCESTER_1)) {
+ muster_lord(LORD_GLOUCESTER_1, LOC_GLOUCESTER)
+ add_favoury_marker(LOC_GLOUCESTER)
+ // TODO: Y34
+ }
+ }
+ if (main_york_heir === LORD_MARCH || main_york_heir === LORD_EDWARD_IV) {
+ muster_lord(LORD_EDWARD_IV, LOC_LONDON)
+ add_favoury_marker(LOC_LONDON)
+
+ // If Edward IV is on the map, remove March
+ disband_lord(LORD_MARCH, true)
+ // TODO: Add Y23, Y24
+ if (is_lord_in_play(LORD_RUTLAND)) {
+ muster_lord(LORD_RUTLAND, LOC_CANTERBURY)
+ add_favoury_marker(LOC_CANTERBURY)
+ // TODO: Add Y31
+ }
+ if (is_lord_in_play(LORD_GLOUCESTER_1)) {
+ muster_lord(LORD_GLOUCESTER_1, LOC_GLOUCESTER)
+ add_favoury_marker(LOC_GLOUCESTER)
+ // TODO: Add Y28, Y34
+ }
+
+ }
+ if (main_york_heir === LORD_RUTLAND) {
+ muster_lord(LORD_RUTLAND, LOC_LONDON)
+ add_favoury_marker(LOC_LONDON)
+ // TODO: Add Y20, Y21
+ if (is_lord_in_play(LORD_GLOUCESTER_1)) {
+ muster_lord(LORD_GLOUCESTER_2, LOC_LONDON)
+ // If Rutland is King, golden gloucester 2 arrives and gloucester 1 is gone
+ disband_lord(LORD_GLOUCESTER_1, true)
+ // TODO: Add Y34
+ }
+ }
+ if (main_york_heir === LORD_GLOUCESTER_1) {
+ muster_lord(LORD_RICHARD_III, LOC_LONDON)
+ add_favoury_marker(LOC_LONDON)
+ // if Richard III is here, both gloucester are gone
+ disband_lord(LORD_GLOUCESTER_1, true)
+ disband_lord(LORD_GLOUCESTER_2, true)
+ // TODO: Add Y32, Y33
+ }
+
+ // Lancaster setup
+ // TODO: Add L1-L13, L34, L35, L36, L37
+
+ if (main_lancaster_heir === LORD_HENRY_VI || main_lancaster_heir === LORD_MARGARET) {
+ muster_lord(LORD_MARGARET, LOC_FRANCE)
+ // TODO: Add L27, L31 + L26 Edward
+ // Only one heir
+ disband_lord(LORD_HENRY_VI, true)
+ disband_lord(LORD_SOMERSET_1, true)
+ disband_lord(LORD_SOMERSET_2, true)
+ }
+ // If Margaret not here and Edward IV not king
+ if (!is_lord_on_map(LORD_MARGARET) && main_york_heir !== LORD_EDWARD_IV) {
+ muster_lord(LORD_HENRY_TUDOR, LOC_FRANCE)
+ // TODO: Add L32, L35
+ disband_lord(LORD_SOMERSET_1, true)
+ disband_lord(LORD_SOMERSET_2, true)
+ }
+ if (!is_lord_on_map(LORD_MARGARET) && !is_lord_on_map(LORD_HENRY_TUDOR)) {
+ muster_lord(LORD_WARWICK_L, LOC_CALAIS)
+ add_favourl_marker(LOC_CALAIS)
+ // TODO: Add L23, L30
+ }
+
+ if (is_lord_on_map(LORD_MARGARET) || is_lord_on_map(LORD_HENRY_TUDOR)) {
+ muster_lord(LORD_OXFORD, LOC_FRANCE)
+ add_favourl_marker(LOC_OXFORD)
+ muster_lord(LORD_JASPER_TUDOR_2, LOC_FRANCE)
+ add_favoury_marker(LOC_PEMBROKE)
+ }
+ else if (is_lord_on_map(LORD_WARWICK_L)) {
+ muster_lord(LORD_OXFORD, LOC_CALAIS)
+ add_favourl_marker(LOC_OXFORD)
+ muster_lord(LORD_JASPER_TUDOR_2, LOC_CALAIS)
+ add_favoury_marker(LOC_PEMBROKE)
+ }
+ else {
+ throw Error("Error Lancastrian setup III.Y")
+ }
+
+ // Exile box setup
+ add_favourl_marker(LOC_FRANCE)
+ add_favoury_marker(LOC_BURGUNDY)
+
+ setup_vassals([ VASSAL_OXFORD, VASSAL_NORFOLK ])
+}
+
+function setup_III_L() {
+ game.turn = 1 << 1
+ game.scenario = "IIIL. Yorkists Last Stand"
+ game.rebel = YORK
+ game.active = YORK
+ game.victory_check = 45
+ game.influence = 0
+
+ if (!is_lord_in_play(LORD_YORK)) {
+ game.influence += 8
+ }
+ if (!is_lord_in_play(LORD_MARCH) && !is_lord_in_play(LORD_EDWARD_IV)) {
+ game.influence += 8
+ }
+ if (!is_lord_in_play(LORD_RUTLAND)) {
+ game.influence += 8
+ }
+ if (!is_lord_in_play(LORD_GLOUCESTER_1) && !is_lord_in_play(LORD_GLOUCESTER_2) && !is_lord_in_play(LORD_RICHARD_III)) {
+ game.influence += 8
+ }
+ if (!is_lord_in_play(LORD_HENRY_VI)) {
+ game.influence -= 8
+ }
+ if (!is_lord_in_play(LORD_HENRY_VI) && !is_lord_in_play(LORD_MARGARET)) {
+ game.influence -= 8
+ }
+ if (!is_lord_in_play(LORD_SOMERSET_1)) {
+ game.influence -= 8
+ }
+ if (!is_lord_in_play(LORD_SOMERSET_1) && !is_lord_in_play(LORD_SOMERSET_2)) {
+ game.influence -= 8
+ }
+
+ for (let lord = first_lord; lord <= last_lord; lord++) {
+ if (is_lord_in_play(lord)) {
+ disband_lord(lord, false)
+ }
+ }
+ for (let loc = first_locale; loc <= last_locale; loc++) {
+ remove_exhausted_marker(loc)
+ remove_depleted_marker(loc)
+ remove_favourl_marker(loc)
+ remove_favoury_marker(loc)
+ }
+ discard_events("this_levy")
+ discard_events("hold")
+ discard_events("this_campaign")
+
+ // Lancaster Setup
+ // TODO: Add L1-L13, L25, L34, L36
+
+ if (main_lancaster_heir === LORD_HENRY_VI) {
+ muster_lord(LORD_HENRY_VI, LOC_LONDON)
+ // TOOD: Add L15, L17
+ }
+ if (main_lancaster_heir === LORD_MARGARET) {
+ muster_lord(LORD_MARGARET, LOC_LONDON)
+ // TODO: Add L27, L31
+ }
+ if (main_lancaster_heir === LORD_SOMERSET_1) {
+ muster_lord(LORD_SOMERSET_1, LOC_LONDON)
+ add_favourl_marker(LOC_WELLS)
+ // TODO: Add L18, L20, L27
+ }
+ // Should never happen but as a failsafe
+ if (main_lancaster_heir === LORD_SOMERSET_2) {
+ muster_lord(LORD_SOMERSET_1, LOC_LONDON)
+ add_favourl_marker(LOC_WELLS)
+ disband_lord(LORD_SOMERSET_2, true)
+ // TODO: Add L18, L20, L27
+ }
+ muster_lord(LORD_OXFORD, LOC_OXFORD)
+ muster_lord(LORD_JASPER_TUDOR_2, LOC_PEMBROKE)
+ add_favourl_marker(LOC_OXFORD)
+ add_favourl_marker(LOC_PEMBROKE)
+ add_favourl_marker(LOC_LONDON)
+
+ // York Setup
+ // TOOD: Add Y1-Y13, Y36
+
+ if (has_Y28_happened()) {
+ if (is_lord_in_play(LORD_GLOUCESTER_1) || is_lord_in_play(LORD_GLOUCESTER_2) || is_lord_in_play(LORD_RICHARD_III)) {
+ // If Gloucester (any), all other yorkist heir dies
+ disband_lord(LORD_YORK, true)
+ disband_lord(LORD_RUTLAND, true)
+ disband_lord(LORD_MARCH, true)
+ disband_lord(LORD_EDWARD_IV, true)
+ disband_lord(LORD_GLOUCESTER_1, true)
+ disband_lord(LORD_RICHARD_III, true)
+ muster_lord(LORD_GLOUCESTER_2, LOC_BURGUNDY)
+ // TODO: Add Y35
+ }
+ }
+
+ if (main_york_heir === LORD_YORK) {
+ muster_lord(LORD_YORK, LOC_BURGUNDY)
+ add_favoury_marker(LOC_ELY)
+ // TODO: Add Y14, Y18
+ if (is_lord_in_play(LORD_MARCH)) {
+ // Only next highest heir alive
+ disband_lord(LORD_RUTLAND, true)
+ disband_lord(LORD_GLOUCESTER_1, true)
+ disband_lord(LORD_GLOUCESTER_2, true)
+ muster_lord(LORD_MARCH, LOC_BURGUNDY)
+ add_favoury_marker(LOC_LUDLOW)
+ //TODO: Add Y20
+ }
+ else if (!is_lord_in_play(LORD_MARCH) && is_lord_in_play(LORD_RUTLAND)) {
+ // Only next highest heir alive
+ disband_lord(LORD_GLOUCESTER_1, true)
+ disband_lord(LORD_GLOUCESTER_2, true)
+ muster_lord(LORD_RUTLAND, LOC_BURGUNDY)
+ add_favoury_marker(LOC_CANTERBURY)
+ //TODO: Add Y20
+ }
+ else if (!is_lord_in_play(LORD_MARCH) && !is_lord_in_play(LORD_RUTLAND) && (is_lord_in_play(LORD_GLOUCESTER_1) || is_lord_in_play(LORD_GLOUCESTER_2))) {
+ // Final Scenario, and no succession rule
+ disband_lord(LORD_GLOUCESTER_2, true)
+ muster_lord(LORD_GLOUCESTER_1, LOC_BURGUNDY)
+ add_favoury_marker(LOC_GLOUCESTER)
+ // TODO: Add Y4
+ }
+ else {
+ // If York alone
+ muster_lord(LORD_SALISBURY, LOC_BURGUNDY)
+ add_favoury_marker(LOC_YORK)
+ //TODO: Add Y17, Y22
+ }
+ }
+ if (main_york_heir === LORD_MARCH || main_york_heir === LORD_RUTLAND) {
+ // If March or Rutland is highest heir, Warwick takes the lead
+ disband_lord(LORD_MARCH, true)
+ disband_lord(LORD_RUTLAND, true)
+ muster_lord(LORD_WARWICK_Y, LOC_CALAIS)
+ add_favoury_marker(LOC_CALAIS)
+ //TODO: Add Y16
+ }
+
+ if (main_york_heir === LORD_WARWICK_Y) {
+ muster_lord(LORD_NORFOLK, LOC_CALAIS)
+ muster_lord(LORD_SALISBURY, LOC_CALAIS)
+ add_favoury_marker(LOC_CALAIS)
+ //TODO: Add Y17, Y22
+ }
+ else (
+ muster_lord(LORD_NORFOLK, LOC_BURGUNDY)
+ )
+
+ if (main_york_heir === LORD_GLOUCESTER_1) {
+ disband_lord(LORD_GLOUCESTER_1, true)
+ muster_lord(LORD_GLOUCESTER_2, LOC_BURGUNDY)
+ muster_lord(LORD_SALISBURY, LOC_BURGUNDY)
+ //TODO: Add Y17, Y22
+ }
+
+ add_favoury_marker(LOC_ARUNDEL)
+
+ // Exile box setup
+ add_favourl_marker(LOC_FRANCE)
+ add_favoury_marker(LOC_BURGUNDY)
+
+ setup_vassals([ VASSAL_OXFORD, VASSAL_NORFOLK ])
+}
+
+// FULL SCENARIO HEIR
+function get_main_york_heir() {
+ if (is_lord_in_play(LORD_YORK))
+ return LORD_YORK
+ if (!is_lord_in_play(LORD_YORK) && is_lord_in_play(LORD_MARCH))
+ return LORD_MARCH
+ if (!is_lord_in_play(LORD_YORK) && !is_lord_in_play(LORD_MARCH) && is_lord_in_play(LORD_EDWARD_IV))
+ return LORD_EDWARD_IV
+ if (!is_lord_in_play(LORD_YORK) && !is_lord_in_play(LORD_MARCH) && !is_lord_in_play(LORD_EDWARD_IV) && is_lord_in_play(LORD_RUTLAND))
+ return LORD_RUTLAND
+ if (!is_lord_in_play(LORD_YORK) && !is_lord_in_play(LORD_MARCH) && !is_lord_in_play(LORD_EDWARD_IV) && !is_lord_in_play(LORD_RUTLAND) && (is_lord_in_play(LORD_GLOUCESTER_1) || is_lord_in_play(LORD_GLOUCESTER_2) || is_lord_in_play(LORD_RICHARD_III)))
+ return LORD_GLOUCESTER_1
+ if (!is_lord_in_play(LORD_YORK) && !is_lord_in_play(LORD_MARCH) && !is_lord_in_play(LORD_EDWARD_IV) && !is_lord_in_play(LORD_RUTLAND) && !is_lord_in_play(LORD_GLOUCESTER_1) && !is_lord_in_play(LORD_GLOUCESTER_2) && !is_lord_in_play(LORD_RICHARD_III))
+ return LORD_WARWICK_Y
+}
+
+function get_main_lancaster_heir() {
+ if (is_lord_in_play(LORD_HENRY_VI))
+ return LORD_HENRY_VI
+ if (!is_lord_in_play(LORD_HENRY_VI) && is_lord_in_play(LORD_MARGARET))
+ return LORD_MARGARET
+ if (!is_lord_in_play(LORD_HENRY_VI) && !is_lord_in_play(LORD_MARGARET) && is_lord_in_play(LORD_SOMERSET_1))
+ return LORD_SOMERSET_1
+ if (!is_lord_in_play(LORD_HENRY_VI) && !is_lord_in_play(LORD_MARGARET) && !is_lord_in_play(LORD_SOMERSET_1) && is_lord_in_play(LORD_SOMERSET_2))
+ return LORD_SOMERSET_2
+ if (!is_lord_in_play(LORD_HENRY_VI) && !is_lord_in_play(LORD_MARGARET) && !is_lord_in_play(LORD_SOMERSET_1) && !is_lord_in_play(LORD_SOMERSET_2) && is_lord_in_play(LORD_HENRY_TUDOR))
+ return LORD_HENRY_TUDOR
+ if (!is_lord_in_play(LORD_HENRY_VI) && !is_lord_in_play(LORD_MARGARET) && !is_lord_in_play(LORD_SOMERSET_1) && !is_lord_in_play(LORD_SOMERSET_2) && !is_lord_in_play(LORD_HENRY_TUDOR) && is_lord_in_play(LORD_WARWICK_L))
+ return LORD_WARWICK_L
+}
+
+*/
+
+// === CAPABILITY: MUSTER EFFECTS ===
+
+// When a lord levies a capability, its muster vassal applies instantly.
+function capability_muster_effects(lord, c) {
+ if (c === AOW_LANCASTER_MONTAGU)
+ muster_vassal(VASSAL_MONTAGU, lord)
+
+ if (c === AOW_LANCASTER_MY_FATHERS_BLOOD)
+ muster_vassal(VASSAL_CLIFFORD, lord)
+
+ if (c === AOW_LANCASTER_ANDREW_TROLLOPE)
+ muster_vassal(VASSAL_TROLLOPE, lord)
+
+ if (c === AOW_LANCASTER_EDWARD)
+ muster_vassal(VASSAL_EDWARD, lord)
+
+ if (c === AOW_LANCASTER_THOMAS_STANLEY) {
+ muster_vassal(VASSAL_THOMAS_STANLEY, lord)
+ game.flags.free_levy = 1
+ }
+
+ if (c === AOW_YORK_HASTINGS) {
+ add_lord_forces(lord, MEN_AT_ARMS, 2)
+ muster_vassal(VASSAL_HASTINGS, lord)
+ }
+ if (c === AOW_YORK_FAIR_ARBITER && is_friendly_locale(get_lord_locale(LORD_SALISBURY))) {
+ game.count += 1
+ }
+ if (c === AOW_YORK_FALLEN_BROTHER && !is_lord_in_play(LORD_CLARENCE)) {
+ game.count += 1
+ }
+
+ if (c === AOW_YORK_BURGUNDIANS) {
+ if (is_seaport(get_lord_locale(lord) && !is_exile(get_lord_locale(lord)))) {
+ add_lord_forces(lord, BURGUNDIANS, 2)
+ logi(AOW_YORK_BURGUNDIANS)
+ game.flags.burgundians = 1
+ }
+ else {
+ game.flags.burgundians = 0
+ }
+ }
+}
+
+// === CAPABILITY: LORDSHIP EFFECTS ===
+
+// When a lord levies a capability, its +Lordship effects apply instantly.
+function lordship_effects(lord) {
+ if (is_friendly_locale(get_lord_locale(lord)) && lord_has_capability(lord, AOW_YORK_FAIR_ARBITER))
+ game.count += 1
+ if (lord_has_capability(lord, AOW_YORK_FALLEN_BROTHER) && !is_lord_in_play(LORD_CLARENCE))
+ game.count += 1
+ if (is_event_in_play(EVENT_YORK_EDWARD_V) && (lord === LORD_GLOUCESTER_1 || lord === LORD_GLOUCESTER_2))
+ game.count += 3
+ if (is_lancaster_lord(lord) && is_event_in_play(EVENT_LANCASTER_PARLIAMENT_VOTES)) {
+ game.flags.parliament_votes = 1
+ }
+ if (is_york_lord(lord) && is_jack_cade_eligible(lord)) {
+ game.flags.jack_cade = 2
+ }
+ if (is_york_lord(lord) && is_event_in_play(EVENT_YORK_SUCCESSION)) {
+ game.flags.succession = 1
+ }
+}
+
+// === CAPABILITY: SOLDIERS OF FORTUNE ===
+
+states.soldier_of_fortune = {
+ inactive: "Levy Troops",
+ prompt() {
+ view.prompt = `Pay 1 Coin for Mercenaries ${lord_name[game.who]}.`
+ let done = true
+ if (done) {
+ for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord) {
+ if (is_lord_unfed(lord) && can_pay_from_shared(lord)) {
+ if (get_lord_assets(lord, COIN) > 0) {
+ gen_action_coin(lord)
+ done = false
+ }
+ }
+ }
+ }
+ // Done
+ if (done) {
+ view.prompt = "Soldiers of fortune: Done."
+ view.actions.end_sof = 1
+ }
},
+ coin(lord) {
+ push_undo()
+ let here = get_lord_locale(game.who)
+ let here_type = data.locales[here].type
+ let number = get_lord_forces(game.who, MERCENARIES)
+ let merc = 0
+ if (!lord_has_capability(game.who, AOW_YORK_WOODWILLES))
+ deplete_locale(here)
+
+ switch (here_type) {
+ case "calais":
+ add_lord_forces(game.who, MEN_AT_ARMS, 2)
+ add_lord_forces(game.who, LONGBOWMEN, 1)
+ break
+ case "london":
+ add_lord_forces(game.who, MEN_AT_ARMS, 1)
+ add_lord_forces(game.who, LONGBOWMEN, 1)
+ add_lord_forces(game.who, MILITIA, 1)
+ break
+ case "harlech":
+ add_lord_forces(game.who, MEN_AT_ARMS, 1)
+ add_lord_forces(game.who, LONGBOWMEN, 2)
+ break
+ case "city":
+ add_lord_forces(game.who, LONGBOWMEN, 1)
+ add_lord_forces(game.who, MILITIA, 1)
+ break
+ case "town":
+ add_lord_forces(game.who, MILITIA, 2)
+ break
+ case "fortress":
+ add_lord_forces(game.who, MEN_AT_ARMS, 1)
+ add_lord_forces(game.who, MILITIA, 1)
+ break
+ }
+ if (game.flags.free_levy === 1) {
+ ++game.count
+ game.flags.free_levy = 0
+ }
+ if (number === 5)
+ merc = 1
+ else
+ merc = 2
+ add_lord_assets(lord, COIN, -1)
+ add_lord_forces(game.who, MERCENARIES, merc)
+ set_lord_unfed(game.who, 0)
+ },
+ end_sof() {
+ end_soldiers_of_fortune()
+ },
+ card: action_held_event,
+}
+
+function end_soldiers_of_fortune() {
+ pop_state()
+ resume_levy_muster_lord()
+}
+
+// === CAPABILITY: COMMISSION OF ARRAY ===
+
+states.commission_of_array = {
+ inactive: "Levy Troops",
prompt() {
- view.prompt = game.victory
+ view.prompt = `Lord troops adjacent to ${lord_name[game.who]}.`
+ let done = true
+ let here = get_lord_locale(game.who)
+ if (done) {
+ for (let next of data.locales[here].adjacent) {
+ if (is_friendly_locale(next) && lord_has_capability(game.who, AOW_LANCASTER_COMMISION_OF_ARRAY) && (!has_exhausted_marker(next) && !is_exile(next))) {
+ done = false
+ gen_action_locale(next)
+ }
+ }
+ }
+ // Done
+ if (done) {
+ view.prompt = "Commission of Array: Done."
+ view.actions.end_coa = 1
+ }
},
+ locale(loc) {
+ push_undo()
+ let loc_type = data.locales[loc].type
+ deplete_locale(loc)
+
+ switch (loc_type) {
+ case "calais":
+ add_lord_forces(game.who, MEN_AT_ARMS, 2)
+ add_lord_forces(game.who, LONGBOWMEN, 1)
+ break
+ case "london":
+ add_lord_forces(game.who, MEN_AT_ARMS, 1)
+ add_lord_forces(game.who, LONGBOWMEN, 1)
+ add_lord_forces(game.who, MILITIA, 1)
+ break
+ case "harlech":
+ add_lord_forces(game.who, MEN_AT_ARMS, 1)
+ add_lord_forces(game.who, LONGBOWMEN, 2)
+ break
+ case "city":
+ add_lord_forces(game.who, LONGBOWMEN, 1)
+ add_lord_forces(game.who, MILITIA, 1)
+ break
+ case "town":
+ add_lord_forces(game.who, MILITIA, 2)
+ break
+ case "fortress":
+ add_lord_forces(game.who, MEN_AT_ARMS, 1)
+ add_lord_forces(game.who, MILITIA, 1)
+ break
+ }
+ if (game.flags.free_levy === 1) {
+ ++game.count
+ game.flags.free_levy = 0
+ }
+ end_commission_of_array()
+ },
+ card: action_held_event,
}
-// === UNCOMMON TEMPLATE ===
+function end_commission_of_array() {
+ pop_state()
+ resume_levy_muster_lord()
+}
-function log_br() {
- if (game.log.length > 0 && game.log[game.log.length - 1] !== "")
- game.log.push("")
+// === CAPABILITY: WE DONE DEEDS OF CHARITY ===
+
+function tow_extra_ip() {
+ for (let lord = first_york_lord; lord <= last_york_lord; ++lord) {
+ if (lord_has_capability(lord, AOW_YORK_WE_DONE_DEEDS_OF_CHARITY) && (get_lord_assets(lord, PROV) > 0 || get_shared_assets(lord, PROV) > 0))
+ return true
+ }
+ return false
}
-function log(msg) {
- game.log.push(msg)
+states.tow_extra_ip = {
+ inactive: "We done needs of charity",
+ prompt() {
+ let loc = 0
+ view.prompt = "We done deeds of charity: spend up to two Provender to add influence points."
+ for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord) {
+ if (lord_has_capability(lord, AOW_YORK_WE_DONE_DEEDS_OF_CHARITY)) {
+ loc = get_lord_locale(lord)
+ }
+ }
+ for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord) {
+ if (game.flags.charity < 2 && get_lord_locale(lord) === loc && (get_lord_assets(lord, PROV) > 0)) {
+ gen_action_prov(lord)
+ }
+ }
+ view.actions.done = 1
+ },
+ prov(lord) {
+ push_undo()
+ add_lord_assets(lord, PROV, -1)
+ game.flags.charity += 1
+ },
+ done() {
+ increase_york_influence(game.flags.charity)
+ logi(`${AOW_YORK_WE_DONE_DEEDS_OF_CHARITY}`)
+ log("York paid " + game.flags.charity + " provender to add " + game.flags.charity + " Influence Points")
+ game.flags.charity = 0
+ goto_disembark()
+ },
}
-function logevent(cap) {
- game.log.push(`E${cap}.`)
+// === CAPABILITY: MERCHANTS ===
+
+function can_action_merchants() {
+ let loc = get_lord_locale(game.command)
+ if (game.actions <= 0)
+ return false
+
+ if (lord_has_capability(game.command, AOW_LANCASTER_MERCHANTS) && count_deplete(loc) > 0)
+ return true
+ else
+ return false
}
-function logcap(cap) {
- game.log.push(`C${cap}.`)
+function goto_merchants() {
+ game.count = count_deplete(get_lord_locale(game.command))
+ game.state = "merchants"
+ init_influence_check(game.command)
}
-function logi(msg) {
- game.log.push(">" + msg)
+states.merchants = {
+ inactive: "Merchants",
+ prompt() {
+ view.prompt = "Merchants: Succeed an influence check to remove Depleted markers"
+ prompt_influence_check()
+ },
+ spend1: add_influence_check_modifier_1,
+ spend3: add_influence_check_modifier_2,
+ check() {
+ let results = do_influence_check()
+ log(`Attempt to C${AOW_LANCASTER_MERCHANTS} with %${game.command} ${results.success ? "Successful" : "Failed"}: (${range(results.rating)}) ${results.success ? HIT[results.roll] : MISS[results.roll]}`)
+ if (results.success) {
+ merchants_success()
+ } else {
+ end_merchants_attempt()
+ }
+ }
+}
+function merchants_success() {
+ game.state = "merchants_success"
}
-function log_h1(msg) {
- log_br()
- log(".h1 " + msg)
- log_br()
+states.merchants_success = {
+ inactive: "Merchants Success",
+ prompt() {
+ view.prompt = `Remove Depleted/Exhausted markers`
+ deplete_merchants()
+ if (game.count === 0) {
+ view.actions.done = 1
+ }
+ },
+ locale(loc) {
+ push_undo()
+ remove_depleted_marker(loc)
+ remove_exhausted_marker(loc)
+ --game.count
+ if (game.count === 0) {
+ end_merchants_attempt()
+ }
+ },
+ done(){
+ end_merchants_attempt()
+ }
}
-function log_h2(msg) {
- log_br()
- if (game.active === YORK)
- log(".h2t " + msg)
+function end_merchants_attempt() {
+ spend_action(1)
+ game.count = 0
+ push_undo()
+ end_influence_check()
+ resume_command()
+}
+
+function deplete_merchants() {
+ let here = get_lord_locale(game.command)
+ for (let next of data.locales[here].adjacent) {
+ if (has_exhausted_marker(next) || has_depleted_marker(next))
+ gen_action_locale(next)
+ }
+ if (has_exhausted_marker(here) || has_depleted_marker(here))
+ gen_action_locale(here)
+}
+
+function count_deplete(loc) {
+ game.count = 0
+ for (let next of data.locales[loc].adjacent) {
+ if (has_exhausted_marker(next) || has_depleted_marker(next)) {
+ ++game.count
+ }
+ }
+ if (has_exhausted_marker(loc) || has_depleted_marker(loc)) {
+ ++game.count
+ }
+ if (game.count > 1)
+ return game.count = 2
else
- log(".h2r " + msg)
- log_br()
+ return game.count
}
-function log_h3(msg) {
- log_br()
- if (game.active === YORK)
- log(".h3t " + msg)
+// === CAPABILITY: BURGUNDIANS ===
+
+function levy_burgundians(lord) {
+ if (is_seaport(get_lord_locale(lord)) && !is_exile(get_lord_locale(lord)) && lord_has_capability(lord, AOW_YORK_BURGUNDIANS) && game.flags.burgundians === 0) {
+ add_lord_forces(lord, BURGUNDIANS, 2)
+ logi(AOW_YORK_BURGUNDIANS)
+ game.flags.burgundians = 1
+ }
+}
+
+// === CAPABILITY: NAVAL BLOCKADE ===
+
+function parley_through_sea(start, locale) {
+ // Only entered in levy
+ let ships = get_shared_assets(start, SHIP)
+
+ if (ships === 0) {
+ game.flags.naval_blockade = -1
+ }
+
+ search_dist.fill(0)
+ search_seen.fill(0)
+ search_seen[start] = 1
+
+ let queue = [ start ]
+ while (queue.length > 0) {
+ let here = queue.shift()
+ let dist = search_dist[here]
+ let next_dist = dist + 1
+
+ if (is_friendly_locale(here)) {
+ for (let next of data.locales[here].adjacent) {
+ if (!search_seen[next]) {
+ search_seen[next] = 1
+ search_dist[next] = next_dist
+ queue.push(next)
+ if (next === locale) {
+ game.flags.naval_blockade = -1
+ }
+ }
+ }
+ }
+ }
+ queue = [ start ]
+ while (queue.length > 0) {
+ let here = queue.shift()
+ let dist = search_dist[here]
+ let next_dist = dist + 1
+
+ if (is_friendly_locale(here)) {
+ if (ships > 0 && is_seaport(here)) {
+ for (let next of find_ports(here)) {
+ if (!search_seen[next]) {
+ search_seen[next] = 1
+ search_dist[next] = next_dist
+ queue.push(next)
+ if (next === locale && game.flags.naval_blockade !== -1) {
+ game.flags.naval_blockade = 1
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+function check_naval_blockade(action, locale) {
+ let ports = [data.port_1, data.port_2, data.port_3]
+ game.what = action
+
+ if (!lord_has_capability(LORD_WARWICK_Y, AOW_YORK_NAVAL_BLOCKADE) || !is_seaport(get_lord_locale(LORD_WARWICK_Y)) || is_exile(get_lord_locale(LORD_WARWICK_Y))) {
+ return false
+ }
+
+ if (action === "levy parley") {
+ parley_through_sea(get_lord_locale(game.who), locale)
+ if (game.flags.naval_blockade !== 1) {
+ return false
+ }
+ }
+
+ if (action === "campaign parley" && data.locales[locale].adjacent.includes(get_lord_locale(game.command))) {
+ return false
+ }
+
+ for (let port of ports) {
+ if (set_has(port, get_lord_locale(LORD_WARWICK_Y)) && set_has(port, locale)) {
+ return true
+ }
+ }
+}
+
+function roll_naval_blockade() {
+ push_state("naval_blockade")
+}
+
+// Parley, and Tax
+states.naval_blockade = {
+ inactive: "Naval Blockade",
+ prompt() {
+ view.prompt = `Naval Blockade : Warwick block this action except on a 1-2`
+ view.actions.roll = 1
+ },
+ roll() {
+ let threshold = 2
+ let roll = roll_die()
+ let success = threshold >= roll
+ log(`Attempt to counter Naval Blockade ${success ? "Failed" : "Successful"}: (1-2) ${success ? HIT[roll] : MISS[roll]}`)
+ if (success) {
+ logi(`Successfully overran C${AOW_YORK_NAVAL_BLOCKADE}`)
+ if (game.what === "levy parley") {
+ game.flags.naval_blockade = -1
+ }
+ if (game.what === "campaign parley") {
+ game.flags.naval_blockade = -1
+ }
+ if (game.what === "levy ship") {
+ add_lord_assets(game.who, SHIP, 1)
+ }
+ if (game.what === "supply") {
+ use_port_supply(game.where, get_port_supply_amount(game.where))
+ }
+ if (game.what === "sail") {
+ log(`Sailed to %${game.where}${format_group_move()}.`)
+ for (let lord of game.group) {
+ set_lord_locale(lord, game.where)
+ set_lord_moved(lord, 1)
+ }
+ if (is_seamanship_in_play())
+ spend_action(1)
+ else
+ spend_all_actions()
+
+ game.flags.surprise_landing = 1
+ resume_command()
+ }
+ }
+ else {
+ logi(`Failed C${AOW_YORK_NAVAL_BLOCKADE}`)
+ if (game.what === "levy parley") {
+ pop_state()
+ }
+ if (game.what === "campaign parley") {
+ pop_state()
+ }
+ }
+ if (game.what === "levy parley") {
+ pop_state()
+ resume_levy_muster_lord()
+ }
+ if (game.what === "campaign parley") {
+ pop_state()
+ --game.count
+ resume_command()
+ }
+ if (game.what === "levy ship") {
+ pop_state()
+ resume_levy_muster_lord()
+ }
+ if (game.what === "supply" && !success) {
+ end_supply()
+ }
+ if (game.what === "sail" && !success) {
+ resume_command()
+ }
+ game.what = NOTHING
+ },
+}
+
+// === CAPABILITY: AGITATORS ===
+
+function can_action_agitators() {
+ let here = get_lord_locale(game.command)
+ if (game.actions <= 0)
+ return false
+ if (lord_has_capability(game.command, AOW_YORK_AGITATORS)) {
+ for (let next of data.locales[here].adjacent) {
+ if (!has_exhausted_marker(next) && !is_friendly_locale(next))
+ return true
+ }
+ }
else
- log(".h3r " + msg)
- log_br()
+ return false
}
-function log_h4(msg) {
- log_br()
- log(".h4 " + msg)
+function goto_agitators() {
+ game.count = count_deplete(get_lord_locale(game.command))
+ game.state = "agitators"
}
-function log_h5(msg) {
- log_br()
- log(".h5 " + msg)
+states.agitators = {
+ inactive: "Agitators",
+ prompt() {
+ view.prompt = "Agitators: Add a depleted marker or flip to exhausted adjacent"
+ deplete_agitators()
+ },
+ locale(loc) {
+ push_undo()
+ if (has_depleted_marker(loc)) {
+ add_exhausted_marker(loc)
+ }
+ else {
+ add_depleted_marker(loc)
+ }
+ end_agitators()
+ },
}
-function gen_action(action, argument) {
- if (!(action in view.actions))
- view.actions[action] = []
- set_add(view.actions[action], argument)
+function deplete_agitators() {
+ let here = get_lord_locale(game.command)
+ for (let next of data.locales[here].adjacent) {
+ if (!has_exhausted_marker(next) && !is_friendly_locale(next))
+ gen_action_locale(next)
+ }
}
-function gen_action_card_if_held(c) {
- if (has_card_in_hand(c))
- gen_action_card(c)
+function end_agitators() {
+ spend_action(1)
+ push_undo()
+ resume_command()
}
-function prompt_select_lord(lord) {
- if (lord !== game.who)
- gen_action_lord(lord)
+// === CAPABILITY: HERALDS ===
+
+function can_action_heralds() {
+ if (game.actions <= 0)
+ return false
+
+ if (!is_first_action())
+ return false
+ // at a seaport
+ let here = get_lord_locale(game.command)
+ if (!is_seaport(here))
+ return false
+
+ if (!lord_has_capability(game.command, AOW_LANCASTER_HERALDS))
+ return false
+
+ for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord) {
+ if (is_lord_on_calendar(lord))
+ return true
+ }
+ return false
}
-function action_select_lord(lord) {
- if (game.who === lord)
+function goto_heralds() {
+ game.state = "heralds"
+}
+
+states.heralds = {
+ inactive: "Heralds",
+ prompt() {
+ view.prompt = "Heralds: Choose a Lord on calendar to shift him to next turn box"
+ for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord) {
+ if (is_lord_on_calendar(lord))
+ gen_action_lord(lord)
+ }
+ },
+ lord(other) {
+ goto_heralds_attempt(other)
+ },
+}
+
+function goto_heralds_attempt(lord) {
+ game.what = lord
+ push_state("heralds_attempt")
+ init_influence_check(game.command)
+}
+
+states.heralds_attempt = {
+ inactive: "Heralds Attempt",
+ prompt() {
+ view.prompt = `Attempt to shift ${lord_name[game.what]} to next Turn Box. `
+ prompt_influence_check()
+ },
+ spend1: add_influence_check_modifier_1,
+ spend3: add_influence_check_modifier_2,
+ check() {
+ let results = do_influence_check()
+ log(`Attempt to shift L${game.what} ${results.success ? "Successful" : "Failed"}: (${range(results.rating)}) ${results.success ? HIT[results.roll] : MISS[results.roll]}`)
+
+ if (results.success) {
+ game.who = game.what
+ set_lord_calendar(game.who, current_turn() + 1)
+ end_heralds_attempt()
+ } else {
+ end_heralds_attempt()
+ }
+ },
+}
+
+function end_heralds_attempt() {
+ spend_all_actions()
+ pop_state()
+ end_influence_check()
+ resume_command()
+}
+
+// === EVENTS: IMMEDIATE ===
+
+function goto_immediate_event(c) {
+ switch (c) {
+ // This Levy / Campaign
+ case EVENT_LANCASTER_BE_SENT_FOR:
+ set_add(game.events, c)
+ return end_immediate_event()
+ case EVENT_LANCASTER_SEAMANSHIP:
+ set_add(game.events, c)
+ return end_immediate_event()
+ case EVENT_LANCASTER_FORCED_MARCHES:
+ set_add(game.events, c)
+ return end_immediate_event()
+ case EVENT_LANCASTER_RISING_WAGES:
+ set_add(game.events, c)
+ return end_immediate_event()
+ case EVENT_LANCASTER_NEW_ACT_OF_PARLIAMENT:
+ set_add(game.events, c)
+ return end_immediate_event()
+ case EVENT_LANCASTER_MY_CROWN_IS_IN_MY_HEART:
+ set_add(game.events, c)
+ return end_immediate_event()
+ case EVENT_LANCASTER_PARLIAMENT_VOTES:
+ set_add(game.events, c)
+ return end_immediate_event()
+ case EVENT_LANCASTER_FRENCH_FLEET:
+ set_add(game.events, c)
+ return end_immediate_event()
+ case EVENT_LANCASTER_BUCKINGHAMS_PLOT:
+ set_add(game.events, c)
+ return end_immediate_event()
+ case EVENT_LANCASTER_MARGARET_BEAUFORT:
+ set_add(game.events, c)
+ return end_immediate_event()
+ case EVENT_LANCASTER_THE_EARL_OF_RICHMOND:
+ set_add(game.events, c)
+ return end_immediate_event()
+
+ case EVENT_YORK_JACK_CADE:
+ set_add(game.events, c)
+ return end_immediate_event()
+ case EVENT_YORK_SEAMANSHIP:
+ set_add(game.events, c)
+ return end_immediate_event()
+ case EVENT_YORK_YORKISTS_BLOCK_PARLIAMENT:
+ set_add(game.events, c)
+ return end_immediate_event()
+ case EVENT_YORK_EXILE_PACT:
+ set_add(game.events, c)
+ return end_immediate_event()
+ case EVENT_YORK_RICHARD_OF_YORK:
+ set_add(game.events, c)
+ return end_immediate_event()
+ case EVENT_YORK_THE_COMMONS:
+ set_add(game.events, c)
+ return end_immediate_event()
+ case EVENT_YORK_SUCCESSION:
+ set_add(game.events, c)
+ return end_immediate_event()
+ case EVENT_YORK_LOYALTY_AND_TRUST:
+ set_add(game.events, c)
+ return end_immediate_event()
+ case EVENT_YORK_OWAIN_GLYNDWR:
+ set_add(game.events, c)
+ return end_immediate_event()
+ case EVENT_YORK_GLOUCESTER_AS_HEIR:
+ set_add(game.events, c)
+ return end_immediate_event()
+ case EVENT_YORK_DORSET:
+ set_add(game.events, c)
+ return end_immediate_event()
+ case EVENT_YORK_THE_KINGS_NAME:
+ set_add(game.events, c)
+ return end_immediate_event()
+ case EVENT_YORK_EDWARD_V:
+ set_add(game.events, c)
+ return end_immediate_event()
+ case EVENT_YORK_AN_HONEST_TALE_SPEEDS_BEST:
+ set_add(game.events, c)
+ return end_immediate_event()
+ case EVENT_YORK_PRIVY_COUNCIL:
+ set_add(game.events, c)
+ return end_immediate_event()
+
+ // Immediate effect
+ // Discard - Immediate Events
+ case EVENT_LANCASTER_SCOTS:
+ return goto_lancaster_event_scots()
+ case EVENT_LANCASTER_HENRY_PRESSURES_PARLIAMENT:
+ return goto_lancaster_event_henry_pressures_parliament()
+ case EVENT_LANCASTER_HENRYS_PROCLAMATION:
+ return goto_lancaster_event_henrys_proclamation()
+ case EVENT_LANCASTER_FRENCH_TROOPS:
+ return goto_lancaster_event_french_troops()
+ case EVENT_LANCASTER_WARWICKS_PROPAGANDA:
+ return goto_warwicks_propaganda()
+ case EVENT_LANCASTER_WARWICKS_PROPAGANDA2:
+ return goto_warwicks_propaganda()
+ case EVENT_LANCASTER_WELSH_REBELLION:
+ return goto_lancaster_event_welsh_rebellion()
+ case EVENT_LANCASTER_HENRY_RELEASED:
+ return goto_lancaster_event_henry_released()
+ case EVENT_LANCASTER_LUNIVERSELLE_ARAGNE:
+ return goto_lancaster_event_luniverselle_aragne()
+ case EVENT_LANCASTER_TO_WILFUL_DISOBEDIANCE:
+ return goto_lancaster_event_to_wilful_disobediance()
+ case EVENT_LANCASTER_FRENCH_WAR_LOANS:
+ return goto_lancaster_event_french_war_loans()
+ case EVENT_LANCASTER_ROBINS_REBELLION:
+ return goto_lancaster_event_robins_rebellion()
+ case EVENT_LANCASTER_TUDOR_BANNERS:
+ return goto_lancaster_event_tudor_banners()
+ case EVENT_YORK_TAX_COLLECTORS:
+ return goto_york_event_tax_collectors()
+ case EVENT_YORK_LONDON_FOR_YORK:
+ return goto_york_event_london_for_york()
+ case EVENT_YORK_SHEWOLF_OF_FRANCE:
+ return goto_york_event_shewolf_of_france()
+ case EVENT_YORK_SIR_RICHARD_LEIGH:
+ return goto_york_event_sir_richard_leigh()
+ case EVENT_YORK_CHARLES_THE_BOLD:
+ return goto_york_event_charles_the_bold()
+ case EVENT_YORK_DUBIOUS_CLARENCE:
+ return goto_dubious_clarence()
+ case EVENT_YORK_YORKIST_NORTH:
+ return goto_york_event_yorkist_north()
+ case EVENT_YORK_EARL_RIVERS:
+ return goto_york_event_earl_rivers()
+ default:
+ log("NOT IMPLEMENTED")
+ return end_immediate_event()
+ }
+}
+
+function end_immediate_event() {
+ resume_levy_arts_of_war()
+}
+
+// === EVENT: JACK CADE ===
+
+function is_york_dominating_north() {
+ let dom = 0
+ for (let loc of all_north_locales) {
+ if (has_favoury_marker(loc)) {
+ dom++
+ }
+ }
+ if (dom > 5)
+ return true
+ return false
+}
+
+function is_york_dominating_south() {
+ let dom = 0
+ for (let loc of all_south_locales) {
+ if (has_favoury_marker(loc)) {
+ dom++
+ }
+ }
+ if (dom > 9)
+ return true
+ if (dom > 4
+ && (lord_has_capability(LORD_MARCH, AOW_YORK_SOUTHERNERS)
+ || lord_has_capability(LORD_RUTLAND, AOW_YORK_SOUTHERNERS)
+ || lord_has_capability(LORD_YORK, AOW_YORK_SOUTHERNERS)))
+ return true
+ return false
+}
+
+function is_york_dominating_wales() {
+ let dom = 0
+ for (let loc of all_wales_locales) {
+ if (has_favoury_marker(loc)) {
+ dom++
+ }
+ }
+ if (dom > 5)
+ return true
+ if (dom > 2
+ && (lord_has_capability(LORD_MARCH, AOW_YORK_WELSHMEN)
+ || lord_has_capability(LORD_YORK, AOW_YORK_WELSHMEN)))
+ return true
+ return false
+}
+
+function is_jack_cade_eligible(lord) {
+ if (!is_event_in_play(EVENT_YORK_JACK_CADE))
+ return false
+ if (is_lord_in_or_adjacent_to_south(lord) && is_york_dominating_south())
+ return true
+ if (is_lord_in_or_adjacent_to_north(lord) && is_york_dominating_north())
+ return true
+ if (is_lord_in_or_adjacent_to_wales(lord) && is_york_dominating_wales())
+ return true
+ return false
+}
+
+// === EVENT: LANCASTER SCOTS ===
+
+function goto_lancaster_event_scots() {
+ game.state = "scots"
+ game.count = []
+ game.who = NOBODY
+}
+
+function end_lancaster_event_scots() {
+ game.count = 0
+ game.who = NOBODY
+ end_immediate_event()
+}
+
+states.scots = {
+ inactive: "Scots",
+ prompt() {
+ view.prompt = "Scots: You may add 1 Men-at-Arms and 1 Militia to each Lord."
+ for (let lord = first_lancaster_lord; lord <= last_lancaster_lord; lord++) {
+ if (is_lord_on_map(lord) && map_get(game.count, lord, 0) < 3) {
+ gen_action_lord(lord)
+ }
+ }
+
+ if (game.who !== NOBODY) {
+ let troops = map_get(game.count, game.who, 0)
+ if ((troops & 1) === 0)
+ view.actions.add_militia = 1
+ if ((troops & 2) === 0)
+ view.actions.add_men_at_arms = 1
+ }
+ view.actions.done = 1
+ },
+ done() {
+ end_lancaster_event_scots()
+ },
+ add_militia() {
+ add_lord_forces(game.who, MILITIA, 1)
+ let troops = map_get(game.count, game.who, 0)
+ map_set(game.count, game.who, troops + 1)
+ if (troops !== 0)
+ game.who = NOBODY
+ },
+ add_men_at_arms() {
+ add_lord_forces(game.who, MEN_AT_ARMS, 1)
+ let troops = map_get(game.count, game.who, 0)
+ map_set(game.count, game.who, troops + 2)
+ if (troops !== 0)
+ game.who = NOBODY
+ },
+ lord(lord) {
+ push_undo()
+ game.who = lord
+ },
+}
+
+// === EVENT: LANCASTER HENRY PRESSURES PARLIAMENT ===
+
+function goto_lancaster_event_henry_pressures_parliament() {
+ let count = 0
+ for (let vassal = first_vassal; vassal <= last_vassal; vassal++) {
+ if (is_vassal_mustered_with_york_lord(vassal)) {
+ count++
+ }
+ }
+
+ if (count > 0) {
+ logi(`Removed ${count} York influence.`)
+ reduce_york_influence(count)
+ }
+
+ end_immediate_event()
+}
+
+// === EVENT: LANCASTER HENRY'S PROCLAMATION ===
+
+function goto_lancaster_event_henrys_proclamation() {
+ for (let vassal = first_vassal; vassal <= last_vassal; vassal++) {
+ if (is_vassal_mustered_with_york_lord(vassal)) {
+ set_vassal_lord_and_service(vassal, get_vassal_lord(vassal), current_turn())
+ logi(`Vassal ${data.vassals[vassal].name} moved to current turn`)
+
+ }
+ }
+ end_immediate_event()
+}
+
+// === EVENT: LANCASTER FRENCH TROOPS ===
+
+function goto_lancaster_event_french_troops() {
+ let can_play = false
+ for (let lord = first_friendly_lord; lord <= last_friendly_lord; lord++) {
+ if (is_lord_on_map(lord) && data.seaports.includes(get_lord_locale(lord))) {
+ can_play = true
+ }
+ }
+ if (can_play) {
+ game.state = "french_troops"
game.who = NOBODY
+ game.count = 0
+ } else {
+ end_immediate_event()
+ }
+}
+
+function end_lancaster_event_french_troops() {
+ game.who = NOBODY
+ game.count = 0
+ end_immediate_event()
+}
+
+states.french_troops = {
+ inactive: "French Troops",
+ prompt() {
+
+ view.prompt = `Add 2 Men at Arms and 2 Militia to a Lord at a port.`
+ if (game.who === NOBODY) {
+ for (let lord = first_friendly_lord; lord <= last_friendly_lord; lord++) {
+ if (is_lord_on_map(lord) && is_seaport(get_lord_locale(lord))) {
+ gen_action_lord(lord)
+ }
+ }
+ } else {
+ view.prompt = `Add ${2-pack2_get(game.count, 0)} Men at Arms and ${2-pack2_get(game.count, 1)} Militia to ${lord_name[game.who]}.`
+ if (pack2_get(game.count, 0) < 2)
+ view.actions.add_men_at_arms = 1
+ if (pack2_get(game.count, 1) < 2)
+ view.actions.add_militia = 1
+ }
+
+ view.actions.done = 1
+ },
+ add_men_at_arms() {
+ push_undo()
+ add_lord_forces(game.who, MEN_AT_ARMS, 1)
+ let c = pack2_get(game.count, 0)
+ game.count = pack2_set(game.count, 0, c+1)
+ },
+ add_militia() {
+ push_undo()
+ add_lord_forces(game.who, MILITIA, 1)
+ let c = pack2_get(game.count, 1)
+ game.count = pack2_set(game.count, 1, c+1)
+ },
+ lord(lord) {
+ push_undo()
+ game.who = lord
+ },
+ done() {
+ end_lancaster_event_french_troops()
+ }
+}
+
+// === EVENT: WARWICKS PROPAGANDA ===
+
+function add_propaganda_target(loc) {
+ set_add(game.pieces.propaganda, loc)
+}
+
+function remove_propaganda_target(loc) {
+ set_delete(game.pieces.propaganda, loc)
+}
+
+function is_propaganda_target(loc) {
+ return set_has(game.pieces.propaganda, loc)
+}
+
+function goto_warwicks_propaganda() {
+ let can_play = false
+ for (let loc = first_locale; loc <= last_locale; ++loc) {
+ if (has_favoury_marker(loc)) {
+ can_play = true
+ }
+ }
+
+ if (can_play) {
+ game.state = "warwicks_propaganda"
+ game.who = NOBODY
+ game.count = 0
+ } else {
+ end_immediate_event()
+ }
+}
+
+states.warwicks_propaganda = {
+ inactive: "Warwick's Propaganda",
+ prompt() {
+ view.prompt = `Select up to ${3-game.count} Yorkists Locales.`
+ for (let loc = first_locale; loc <= last_locale; loc++) {
+ if (game.count < 3 && has_favoury_marker(loc) && !is_exile(loc) && !is_propaganda_target(loc)) {
+ gen_action_locale(loc)
+ }
+ }
+ view.actions.done = 1
+ },
+ locale(loc) {
+ push_undo()
+ add_propaganda_target(loc)
+ game.count++
+ },
+ done() {
+ goto_yorkist_choice()
+ }
+}
+
+function goto_yorkist_choice() {
+ game.who = NOBODY
+ set_active_enemy()
+ game.state = "warwicks_propaganda_yorkist_choice"
+}
+
+states.warwicks_propaganda_yorkist_choice = {
+ inactive: "Yorkists to choose to Pay or Remove favour",
+ prompt() {
+ view.prompt = `For each Stronghold, Pay 2 influence or Remove favour.`
+ let done = true
+ if (game.who === NOBODY) {
+ for (let loc = first_locale; loc <= last_locale; loc++) {
+ if (is_propaganda_target(loc)) {
+ gen_action_locale(loc)
+ done = false
+ }
+ }
+ if (done) {
+ view.actions.done = 1
+ }
+ } else {
+ view.actions.remove_favour = 1
+ view.actions.pay = 1
+ }
+ },
+ locale(loc) {
+ game.who = loc
+ },
+ remove_favour() {
+ push_undo()
+ remove_favoury_marker(game.who)
+ remove_propaganda_target(game.who)
+ logi(`Removed favour in ${game.who}`)
+ game.who = NOBODY
+ },
+ pay() {
+ push_undo()
+ reduce_influence(2)
+ logi(`Paid 2 to keep ${game.who}`)
+ remove_propaganda_target(game.who)
+ game.who = NOBODY
+ },
+ done() {
+ end_warwicks_propaganda()
+ },
+}
+
+function end_warwicks_propaganda() {
+ game.who = NOBODY
+ game.count = 0
+ set_active_enemy()
+ end_immediate_event()
+}
+
+// === EVENT: WELSH REBELLION ===
+
+function goto_lancaster_event_welsh_rebellion() {
+ let can_play_remove_troops = false
+ let can_play_remove_favour = false
+ for (let lord = first_york_lord; lord <= last_york_lord; ++lord) {
+ if (is_lord_on_map(lord) && is_lord_in_wales(lord)) {
+ set_lord_moved(lord, 1)
+ can_play_remove_troops = true
+ }
+ }
+ for (let loc = first_locale; loc <= last_locale; loc++) {
+ if (is_wales(loc) && has_favoury_marker(loc))
+ can_play_remove_favour = true
+ }
+
+ if (can_play_remove_troops) {
+ push_state("welsh_rebellion_remove_troops")
+ game.who = NOBODY
+ game.count = 0
+ }
+ else if (can_play_remove_favour) {
+ push_state("welsh_rebellion_remove_favour")
+ game.who = NOBODY
+ game.count = 0
+ }
+ else {
+ end_immediate_event()
+ }
+}
+
+states.welsh_rebellion_remove_troops = {
+ inactive: "Welsh Rebellion \u2014 Remove troops",
+ prompt() {
+ view.prompt = `Remove 2 Troops from each enemy Lord in Wales.`
+ let done = true
+ if (game.who === NOBODY) {
+ for (let lord = first_enemy_lord; lord <= last_enemy_lord; lord++) {
+ if (is_lord_on_map(lord) && is_lord_in_wales(lord) && get_lord_moved(lord)) {
+ gen_action_lord(lord)
+ done = false
+ }
+ }
+ if (done) {
+ view.actions.done = 1
+ }
+ }
+ else if (game.who !== NOBODY) {
+ if (game.count >= 0) {
+ view.prompt = `Remove ${game.count} Troops from ${data.lords[game.who].name}.`
+ if (game.count === 0) {
+ set_lord_moved(game.who, 0)
+ view.actions.done = 1
+ }
+ else {
+ if (get_lord_forces(game.who, BURGUNDIANS) > 0)
+ gen_action_burgundians(game.who)
+ if (get_lord_forces(game.who, MERCENARIES) > 0)
+ gen_action_mercenaries(game.who)
+ if (get_lord_forces(game.who, LONGBOWMEN) > 0)
+ gen_action_longbowmen(game.who)
+ if (get_lord_forces(game.who, MEN_AT_ARMS) > 0)
+ gen_action_men_at_arms(game.who)
+ if (get_lord_forces(game.who, MILITIA) > 0)
+ gen_action_militia(game.who)
+ }
+ }
+ }
+ },
+ lord(lord) {
+ push_undo()
+ game.who = lord
+ game.count = 2
+ },
+ burgundians(lord) {
+ add_lord_forces(lord, BURGUNDIANS, -1)
+ game.count--
+ },
+ mercenaries(lord) {
+ add_lord_forces(lord, MERCENARIES, -1)
+ game.count--
+ },
+ longbowmen(lord) {
+ add_lord_forces(lord, LONGBOWMEN, -1)
+ game.count--
+ },
+ men_at_arms(lord) {
+ add_lord_forces(lord, MEN_AT_ARMS, -1)
+ game.count--
+ },
+ militia(lord) {
+ add_lord_forces(lord, MILITIA, -1)
+ game.count--
+ },
+ done() {
+ end_welsh_rebellion()
+ },
+}
+
+states.welsh_rebellion_remove_favour = {
+ inactive: "Welsh Rebellion \u2014 Remove Favour",
+ prompt() {
+ view.prompt = `Select up to ${2-game.count} Locales in Wales.`
+ for (let loc = first_locale; loc <= last_locale; loc++) {
+ if (game.count < 2 && is_wales(loc) && has_favoury_marker(loc)) {
+ gen_action_locale(loc)
+ }
+ }
+ view.actions.done = 1
+ },
+ locale(loc) {
+ push_undo()
+ remove_favoury_marker(loc)
+ logi(`Removed favour at ${data.locales[loc].name}`)
+ game.count++
+ },
+ done() {
+ end_immediate_event()
+ },
+}
+
+function end_welsh_rebellion() {
+ for (let lord = first_york_lord; lord <= last_york_lord; ++lord) {
+ if (is_lord_on_map(lord) && is_lord_in_wales(lord) && !lord_has_unrouted_units(lord))
+ disband_lord(lord, false)
+ }
+ game.count = 0
+ game.who = NOBODY
+ end_immediate_event()
+}
+
+// === EVENT: HENRY RELEASED ===
+function goto_lancaster_event_henry_released() {
+ if (has_favourl_marker(LOC_LONDON)) {
+ logi(`Henry Released : 5 Influence for Lancaster`)
+ increase_lancaster_influence(5)
+ }
+ end_immediate_event()
+}
+
+// === EVENT: L'UNIVERSELLE ARAGNE ===
+
+function goto_lancaster_event_luniverselle_aragne() {
+ let can_play = false
+ for (let vassal = first_vassal; vassal <= last_vassal; vassal++) {
+ if (is_vassal_mustered_with_york_lord(vassal)) {
+ can_play = true
+ }
+ }
+ if (can_play) {
+ game.state = "aragne"
+ game.who = NOBODY
+ game.count = 0
+ } else {
+ logi("No Effect")
+ end_immediate_event()
+ }
+}
+
+states.aragne = {
+ inactive: "L'universelle Aragne",
+ prompt() {
+ view.prompt = "Select up to 2 Vassals"
+ if (game.who === NOBODY && game.count < 2) {
+ for (let v = first_vassal; v <= last_vassal; v++) {
+ if (!get_vassal_moved(v) && is_vassal_mustered_with_york_lord(v)) {
+ gen_action_vassal(v)
+ }
+ }
+ }
+ view.actions.done = 1
+ },
+ vassal(v) {
+ push_undo()
+ game.who = v
+ game.count++
+ set_vassal_moved(v, 1)
+ logi(`Vassal ${data.vassals[v].name} selected`)
+ game.who = NOBODY
+ },
+ done() {
+ goto_yorkist_aragne()
+ },
+}
+
+function goto_yorkist_aragne() {
+ game.who = NOBODY
+ set_active_enemy()
+ game.state = "yorkist_aragne"
+}
+
+states.yorkist_aragne = {
+ inactive: "Influence checks",
+ prompt() {
+ view.prompt = `For Each vassal, influence check : failure disbands it`
+ let done = true
+ if (game.who === NOBODY) {
+ for (let v = first_vassal; v <= last_vassal; v++) {
+ if (get_vassal_moved(v) && is_vassal_mustered_with_friendly_lord(v)) {
+ gen_action_vassal(v)
+ done = false
+ }
+ }
+ if (done) {
+ view.actions.done = 1
+ }
+ }
+ },
+ vassal(other) {
+ push_undo()
+ goto_aragne_save(other)
+ },
+ done() {
+ end_universelle_aragne()
+ },
+}
+
+function goto_aragne_save(other) {
+ game.who = other
+ game.where = NOWHERE
+ get_vassal_lord(other)
+ init_influence_check(get_vassal_lord(other))
+ game.check.push({
+ cost: 0,
+ modifier: data.vassals[other].influence * (game.active === LANCASTER ? -1 : 1),
+ source: "vassal",
+ })
+ push_state("aragne_save")
+}
+
+states.aragne_save = {
+ inactive: `Influence check`,
+ prompt() {
+ view.prompt = `Influence check : Failure disbands ${data.vassals[game.who].name}`
+ prompt_influence_check()
+ },
+ spend1: add_influence_check_modifier_1,
+ spend3: add_influence_check_modifier_2,
+ check() {
+ let results = do_influence_check()
+ logi(`Attempt to save ${data.vassals[game.who].name} ${results.success ? "Successful" : "Failed"}: (${range(results.rating)}) ${results.success ? HIT[results.roll] : MISS[results.roll]}`)
+
+ if (results.success) {
+ set_vassal_moved(game.who, 0)
+ game.who = NOBODY
+ end_influence_check()
+ push_state("yorkist_aragne")
+ } else {
+ set_vassal_moved(game.who, 0)
+ disband_vassal(game.who)
+ if (game.who === VASSAL_HASTINGS) {
+ discard_card_capability(AOW_YORK_HASTINGS)
+ logi(`Hastings Discarded`)
+ }
+ game.who = NOBODY
+ end_influence_check()
+ push_state("yorkist_aragne")
+ }
+ },
+}
+
+function end_universelle_aragne() {
+ game.who = NOBODY
+ game.count = 0
+ end_immediate_event()
+}
+
+// === EVENT: TO WILFUL DISOBEDIANCE ===
+
+function goto_lancaster_event_to_wilful_disobediance() {
+ let can_play = false
+ for (let loc = first_locale; loc <= last_locale; loc++){
+ if (has_favoury_marker(loc) && !has_enemy_lord(loc) && !has_adjacent_enemy(loc) && (has_friendly_lord(loc) || has_adjacent_friendly(loc))) {
+ can_play = true
+ }
+ }
+ if (can_play) {
+ game.state = "wilful_disobediance"
+ game.who = NOBODY
+ game.count = 0
+ } else {
+ end_immediate_event()
+ logi(`No Effect`)
+ }
+
+}
+states.wilful_disobediance = {
+ inactive: "to wilful disobediance",
+ prompt() {
+ view.prompt = `Select up to ${2-game.count} Yorkists Locales.`
+ for (let loc = first_locale; loc <= last_locale; loc++) {
+ if (
+ game.count < 2 &&
+ has_favoury_marker(loc) &&
+ !has_enemy_lord(loc) &&
+ !has_adjacent_enemy(loc) &&
+ (has_friendly_lord(loc) || has_adjacent_friendly(loc))
+ ) {
+ gen_action_locale(loc)
+ }
+ }
+ view.actions.done = 1
+ },
+ locale(loc) {
+ push_undo()
+ remove_favoury_marker(loc)
+ game.count++
+ logi(`Favour removed at ${loc}`)
+ },
+ done() {
+ logi(`No Effect`)
+ end_immediate_event()
+ }
+}
+
+// === EVENT: FRENCH WAR LOANS ===
+
+function goto_lancaster_event_french_war_loans() {
+ for (let lord = first_lancaster_lord; lord <= last_lancaster_lord; ++lord) {
+ if (is_lord_on_map(lord) && !is_lord_on_calendar(lord)) {
+ add_lord_assets(lord, PROV, 1)
+ add_lord_assets(lord, COIN, 1)
+ logi(`1 Coin and 1 Provender added to ${data.lords[lord].name}`)
+ }
+ }
+ end_immediate_event()
+}
+
+// === EVENT: ROBINS REBELLION ===
+
+function goto_lancaster_event_robins_rebellion() {
+ let can_play = false
+ for (let loc = first_locale; loc <= last_locale; loc++) {
+ if (is_north(loc) && !has_favourl_marker(loc)) {
+ can_play = true
+ }
+ }
+ if (can_play) {
+ game.state = "robins_rebellion"
+ game.who = NOBODY
+ game.count = 0
+ } else {
+ logi(`No Effect`)
+ end_immediate_event()
+ }
+}
+
+states.robins_rebellion = {
+ inactive: "Robin's Rebellion",
+ prompt() {
+ view.prompt = `Select up to ${3-game.count} Locales in North.`
+ for (let loc = first_locale; loc <= last_locale; loc++) {
+ if (game.count < 3 && is_north(loc) && !has_favourl_marker(loc)) {
+ gen_action_locale(loc)
+ }
+ }
+ view.actions.done = 1
+ },
+ locale(loc) {
+ push_undo()
+ shift_favour_toward(loc)
+ logi(`Placed/Removed favour at ${data.locales[loc].name}`)
+ game.count++
+ },
+ done() {
+ end_immediate_event()
+ }
+}
+
+// === EVENT: TUDOR BANNERS ===
+
+function tudor_banner_eligible() {
+ if (is_lord_on_map(LORD_HENRY_TUDOR) && !is_lord_on_calendar(LORD_HENRY_TUDOR)) {
+ for (let next of data.locales[get_lord_locale(LORD_HENRY_TUDOR)].adjacent) {
+ if (can_parley_at(next))
+ return true
+ }
+ }
else
+ return false
+}
+
+function goto_lancaster_event_tudor_banners() {
+ let can_play = false
+ if (tudor_banner_eligible()) {
+ can_play = true
+ }
+ if (can_play) {
+ game.state = "tudor_banners"
+ game.who = NOBODY
+ } else {
+ logi(`No Effect`)
+ end_immediate_event()
+ }
+}
+
+states.tudor_banners = {
+ inactive: "Tudor banners",
+ prompt() {
+ view.prompt = `Select locales adjacent to Henry to make them Lancastrian`
+ for (let next of data.locales[get_lord_locale(LORD_HENRY_TUDOR)].adjacent) {
+ if (!has_enemy_lord(next) && !has_favourl_marker(next)) {
+ gen_action_locale(next)
+ } else {
+ view.actions.done = 1
+ }
+ }
+ },
+ locale(loc) {
+ push_undo()
+ remove_favoury_marker(loc)
+ add_favourl_marker(loc)
+ logi(`Placed Lancastrian favour at ${data.locales[loc].name}`)
+ },
+ done() {
+ end_immediate_event()
+ }
+}
+
+// === EVENT: TAX COLLECTORS ===
+
+function goto_york_event_tax_collectors() {
+ game.who = NOBODY
+ game.count = 0
+ for (let lord = first_york_lord; lord <= last_york_lord; ++lord) {
+ if (is_lord_on_map(lord) && !is_lord_on_calendar(lord)) {
+ set_lord_moved(lord, 1)
+ }
+ }
+ push_state("tax_collectors")
+}
+
+function can_action_tax_collectors(lord) {
+ let here = get_lord_locale(lord)
+ if (can_tax_collectors_at(here, lord))
+ return true
+ return search_tax_collectors(false, here, lord)
+}
+
+function can_tax_collectors_at(here, lord) {
+ if (is_friendly_locale(here) && !has_exhausted_marker(here)) {
+ // London, Calais, and Harlech
+ if (here === LOC_LONDON || here === LOC_CALAIS || here === LOC_HARLECH)
+ return true
+
+ // Own seat
+ if (here === data.lords[lord].seat)
+ return true
+
+ // vassal seats
+ for (let vassal = first_vassal; vassal <= last_vassal; ++vassal)
+ if (is_vassal_mustered_with(vassal, lord))
+ if (here === data.vassals[vassal].seat)
+ return true
+ }
+ return false
+}
+
+function search_tax_collectors(result, start, lord) {
+ let ships = get_shared_assets(start, SHIP)
+
+ search_seen.fill(0)
+ search_seen[start] = 1
+
+ let queue = [ start ]
+ while (queue.length > 0) {
+ let here = queue.shift()
+
+ if (is_lord_on_map(lord) && !is_lord_on_calendar(lord)) {
+ if (can_tax_collectors_at(here, lord)) {
+ if (result)
+ set_add(result, here)
+ else
+ return true
+ }
+ }
+
+ if (is_friendly_locale(here)) {
+ for (let next of data.locales[here].adjacent) {
+ if (!search_seen[next]) {
+ search_seen[next] = 1
+ queue.push(next)
+ }
+ }
+ if (ships > 0 && is_seaport(here)) {
+ for (let next of find_ports(here)) {
+ if (!search_seen[next]) {
+ search_seen[next] = 1
+ queue.push(next)
+ }
+ }
+ }
+ }
+ }
+
+ if (result)
+ return result
+ else
+ return false
+}
+
+states.tax_collectors = {
+ inactive: "Tax Collectors",
+ prompt() {
+ view.prompt = "Tax Collectors : You may tax for Double coin with each lord"
+ for (let lord = first_york_lord; lord <= last_york_lord; ++lord) {
+ if (can_action_tax_collectors(lord) && get_lord_moved(lord)) {
+ gen_action_lord(lord)
+ }
+ }
+ view.actions.done = 1
+ },
+ lord(lord) {
+ push_undo()
+ game.where = NOWHERE
game.who = lord
+ push_state("double_tax_collectors")
+ init_influence_check(lord)
+ },
+ done() {
+ end_tax_collectors()
+ },
}
-function gen_action_locale(locale) {
- gen_action("locale", locale)
+states.double_tax_collectors = {
+ inactive: "Tax Collectors",
+ prompt() {
+ view.prompt = "Tax: Select the location to tax for double."
+ if (game.where === NOWHERE) {
+ for (let loc of search_tax_collectors([], get_lord_locale(game.who), game.who))
+ gen_action_locale(loc)
+ } else {
+ view.prompt = `Tax: Attempting to tax ${data.locales[game.where].name}. `
+ prompt_influence_check()
+ }
+ },
+ locale(loc) {
+ game.where = loc
+ if (loc === data.lords[game.who].seat) {
+ // Auto succeed without influence check at Lords seat.
+ deplete_locale(game.where)
+
+ log(`Taxed %${game.where}.`)
+ add_lord_assets(game.who, COIN, get_tax_amount(game.where)*2)
+ set_lord_moved(game.who, 0)
+ end_tax_lord()
+ }
+ },
+ spend1: add_influence_check_modifier_1,
+ spend3: add_influence_check_modifier_2,
+ check() {
+ let results = do_influence_check()
+ logi(`Tax : ${results.success ? "Successful" : "Failed"}: (${range(results.rating)}) ${results.success ? HIT[results.roll] : MISS[results.roll]}`)
+
+ if (lord_has_capability(game.who, AOW_YORK_SO_WISE_SO_YOUNG)) {
+ log(`C${AOW_YORK_SO_WISE_SO_YOUNG}.`)
+ add_lord_assets(game.who, COIN, 1)
+ }
+
+ if (results.success) {
+ deplete_locale(game.where)
+ log(`Taxed %${game.where}.`)
+ add_lord_assets(game.who, COIN, get_tax_amount(game.where)*2)
+
+ if (
+ game.command === LORD_DEVON &&
+ (game.where === LOC_EXETER ||
+ game.where === LOC_LAUNCESTON ||
+ game.where === LOC_PLYMOUTH ||
+ game.where === LOC_WELLS ||
+ game.where === LOC_DORCHESTER)
+ )
+ add_lord_assets(game.command, COIN, 4)
+ } else {
+ log(`Tax of %${game.where} failed.`)
+
+ }
+ set_lord_moved(game.who, 0)
+ game.who = NOBODY
+ push_state("tax_collectors")
+ },
}
-function gen_action_lord(lord) {
- gen_action("lord", lord)
+function end_tax_lord() {
+ game.where = NOWHERE
+ game.who = NOBODY
+ pop_state()
}
-function gen_action_array(pos) {
- gen_action("array", pos)
+function end_tax_collectors() {
+ game.where = NOWHERE
+ game.who = NOBODY
+ game.count = 0
+ end_immediate_event()
}
-function gen_action_vassal(vassal) {
- gen_action("vassal", vassal)
+// === EVENT: LONDON FOR YORK ===
+
+function goto_york_event_london_for_york() {
+ let can_play = false
+ if (has_favoury_marker(LOC_LONDON)) {
+ can_play = true
+ }
+ if (can_play) {
+ game.who = NOBODY
+ game.state = "london_for_york"
+ } else {
+ logi(`No Effect`)
+ end_immediate_event()
+ }
}
-function gen_action_card(card_or_list) {
- if (Array.isArray(card_or_list))
- for (let c of card_or_list)
- gen_action("card", c)
+states.london_for_york = {
+ inactive: "London For York",
+ prompt() {
+ view.prompt = `Select London to add a second favour marker`
+ gen_action_locale(LOC_LONDON)
+ },
+ locale(loc) {
+ push_undo()
+ game.flags.london_for_york = 1
+ logi(`Second marker placed at ${data.locales[loc].name}`)
+ logi(`Immune to Lancastrian parley unless aided by event`)
+ end_immediate_event()
+ },
+}
+
+function check_london_protected() {
+// TODO IF HENRY/MARGARET ARE MUSTERED IT DOES NOT CHANGE FAVOUR
+// ONLY L17/L18 and Pillage will cancel that event
+//(it is annuled when london go to neutral
+ if (game.state === "pillage") {
+ return false
+ }
+ if (game.flags.london_for_york === 1 && game.where === LOC_LONDON) {
+ return true
+ }
+ else {
+ return false
+ }
+}
+
+// === EVENT: SHE-WOLF OF FRANCE ===
+
+function goto_york_event_shewolf_of_france() {
+ let can_play = false
+ for (let v = first_vassal; v <= last_vassal; v++) {
+ if (is_vassal_mustered_with_friendly_lord(v)) {
+ set_vassal_moved(v, 1)
+ can_play = true
+ }
+ }
+ if (can_play) {
+ game.state = "she_wolf"
+ game.who = NOBODY
+ } else {
+ logi(`No Effect`)
+ end_immediate_event()
+ }
+}
+
+// TO TRACK VASSALS DURING EVENTS
+
+function get_vassal_moved(v) {
+ return map_get(game.pieces.moved, v, 0)
+}
+
+function set_vassal_moved(v, x) {
+ map_set(game.pieces.moved, v, x)
+}
+
+function pay_vassal_shewolf(vassal) {
+ if (current_turn() < 16)
+ set_vassal_lord_and_service(vassal, get_vassal_lord(vassal),get_vassal_service(vassal) + 1)
+}
+
+states.she_wolf = {
+ inactive: "She-Wolf of France",
+ prompt() {
+ let done = true
+ view.prompt = "You may shift your vassals one calendar box."
+ if (game.who === NOBODY) {
+ for (let v = first_vassal; v <= last_vassal; v++) {
+ if (get_vassal_moved(v) && is_vassal_mustered_with_friendly_lord(v)) {
+ gen_action_vassal(v)
+ done = false
+ }
+ }
+ if (done) {
+ view.actions.done = 1
+ }
+ }
+ },
+ vassal(v) {
+ push_undo()
+ game.who = v
+ pay_vassal_shewolf(game.who)
+ set_vassal_moved(v, 0)
+ logi(`Vassal ${data.vassals[v].name} shifted one calendar box`)
+ game.who = NOBODY
+ },
+ done() {
+ end_immediate_event()
+ },
+}
+
+// === EVENT: RICHARD LEIGH ===
+
+function goto_york_event_sir_richard_leigh() {
+ let can_play = false
+ if (!has_favoury_marker(LOC_LONDON)) {
+ can_play = true
+ }
+ if (can_play) {
+ game.state = "richard_leigh"
+ game.who = LOC_LONDON
+ game.count = 0
+ } else {
+ logi(`No Effect`)
+ end_immediate_event()
+ }
+}
+
+states.richard_leigh = {
+ inactive: "Richard Leigh",
+ prompt() {
+ view.prompt = `Select London, shift it once in your favour`
+ if (game.who === LOC_LONDON && !has_favoury_marker(LOC_LONDON)) {
+ gen_action_locale(LOC_LONDON)
+ } else {
+ view.actions.done = 1
+ }
+ },
+ locale(loc) {
+ push_undo()
+ shift_favour_toward(loc)
+ logi(`London shifted once in your favour`)
+ game.who = NOBODY
+ },
+ done() {
+ end_immediate_event()
+ }
+}
+
+// === EVENT: CHARLES THE BOLD ===
+
+function goto_york_event_charles_the_bold() {
+ for (let lord = first_york_lord; lord <= last_york_lord; ++lord) {
+ if (is_lord_on_map(lord) && !is_lord_on_calendar(lord)) {
+ add_lord_assets(lord, PROV, 1)
+ add_lord_assets(lord, COIN, 1)
+ logi(`1 Coin and 1 Provender added to ${data.lords[lord].name}`)
+ }
+ }
+ end_immediate_event()
+}
+
+// === EVENT: DUBIOUS CLARENCE ===
+
+function goto_dubious_clarence() {
+ let can_play = false
+ if ((is_lord_on_map(LORD_EDWARD_IV) && !is_lord_on_calendar(LORD_EDWARD_IV))
+ && is_lord_on_map(LORD_CLARENCE) && !is_lord_on_calendar(LORD_CLARENCE))
+ can_play = true
+
+ if (can_play) {
+ game.state = "dubious_clarence"
+ game.who = LORD_EDWARD_IV
+ init_influence_check(LORD_EDWARD_IV)
+ } else {
+ logi(`No Effect`)
+ end_immediate_event()
+ }
+}
+
+states.dubious_clarence = {
+ inactive: "Dubious Clarence",
+ prompt() {
+ view.prompt = `You may Influence check with Edward to disband Clarence `
+ prompt_influence_check()
+ },
+ spend1: add_influence_check_modifier_1,
+ spend3: add_influence_check_modifier_2,
+ check() {
+ let results = do_influence_check()
+ log(`Attempt to disband Clarence ${results.success ? "Successful" : "Failed"}: (${range(results.rating)}) ${results.success ? HIT[results.roll] : MISS[results.roll]}`)
+
+ if (results.success) {
+ disband_lord(LORD_CLARENCE, false)
+ end_immediate_event()
+ } else {
+ end_immediate_event()
+ }
+ },
+}
+
+// === EVENT: YORKIST NORTH ===
+
+function goto_york_event_yorkist_north() {
+ let influence_gained = 0
+ for (let lord = first_york_lord; lord <= last_york_lord; ++lord) {
+ if (is_lord_on_map(lord) && !is_lord_on_calendar(lord) && is_lord_in_north(lord))
+ influence_gained++
+ }
+ for (let loc = first_locale; loc <= last_locale; loc++) {
+ if (loc !== NOWHERE && loc < CALENDAR && has_favoury_marker(loc) && is_north(loc)) {
+ influence_gained++
+ }
+ }
+ logi(`Yorkist North : ${influence_gained} Influence for Yorkists`)
+ increase_york_influence(influence_gained)
+ end_immediate_event()
+}
+
+// === EVENT: EARL RIVERS ===
+
+function goto_york_event_earl_rivers() {
+ game.state = "earl_rivers"
+ game.count = []
+ game.who = NOBODY
+}
+
+function end_york_event_earl_rivers() {
+ game.count = 0
+ game.who = NOBODY
+ end_immediate_event()
+}
+
+states.earl_rivers = {
+ inactive: "Earl Rivers",
+ prompt() {
+ view.prompt = "Earl Rivers: Add up to 2 Militia to each lord"
+ view.actions.done = 1
+ for (let lord = first_york_lord; lord <= last_york_lord; lord++) {
+ if (is_lord_on_map(lord) && map_get(game.count, lord, 0) < 3) {
+ gen_action_lord(lord)
+ }
+ }
+
+ if (game.who !== NOBODY) {
+ let troops = map_get(game.count, game.who, 0)
+ if ((troops & 1) === 0)
+ view.actions.add_militia = 1
+ }
+ if (game.who !== NOBODY) {
+ let troops = map_get(game.count, game.who, 0)
+ if ((troops & 1) === 0)
+ view.actions.add_militia2 = 1
+ }
+ },
+ done() {
+ end_york_event_earl_rivers()
+ },
+ add_militia() {
+ push_undo()
+ add_lord_forces(game.who, MILITIA, 1)
+ let troops = map_get(game.count, game.who, 0)
+ map_set(game.count, game.who, troops + 1)
+ if (troops > 1)
+ game.who = NOBODY
+ },
+ add_militia2() {
+ push_undo()
+ add_lord_forces(game.who, MILITIA, 2)
+ let troops = map_get(game.count, game.who, 0)
+ map_set(game.count, game.who, troops + 1)
+ if (troops > 1)
+ game.who = NOBODY
+ },
+ lord(lord) {
+ push_undo()
+ game.who = lord
+ }
+}
+
+// === EVENT: THE KINGS NAME ===
+
+function eligible_kings_name() {
+ if (
+ (!is_lord_on_calendar(LORD_GLOUCESTER_1) && is_lord_on_map(LORD_GLOUCESTER_1)) ||
+ (!is_lord_on_calendar(LORD_GLOUCESTER_2) && is_lord_on_map(LORD_GLOUCESTER_2))
+ ) {
+ if (is_event_in_play(EVENT_YORK_THE_KINGS_NAME) && game.active === LANCASTER)
+ return true
+ }
+ return false
+}
+
+function goto_kings_name(action) {
+ game.what = action
+ set_active_enemy()
+ push_state("kings_name")
+}
+
+states.kings_name = {
+ inactive: `King's name`,
+ prompt() {
+ view.prompt = `King's Name: You pay may 1 Influence to cancel last ${game.what} action`
+ view.actions.pass = 1
+ view.actions.pay = 1
+ },
+ pay() {
+ push_undo()
+ reduce_influence(1)
+ goto_kings_name_cancel()
+ },
+ pass() {
+ set_active_enemy()
+ pop_state()
+ if (game.state === "levy_muster_lord_attempt") {
+ push_state("muster_lord_at_seat")
+ }
+ if (game.state === "levy_muster_vassal") {
+ muster_vassal(game.which, game.who)
+ pop_state()
+ }
+ if (game.state === "muster_capability") {
+ add_lord_capability(game.who, game.which)
+ capability_muster_effects(game.who, game.which)
+ pop_state()
+ }
+ if (game.state === "parley") {
+ game.what = NOTHING
+ game.where = NOWHERE
+ pop_state()
+ }
+ resume_levy_muster_lord()
+ }
+}
+
+function goto_kings_name_cancel() {
+ switch(game.what) {
+ case "Levy Lord":
+ pop_state()
+ end_levy_muster_lord_attempt()
+ break
+ case "Levy Cart":
+ add_lord_assets(game.who, CART, -2)
+ pop_state()
+ resume_levy_muster_lord()
+ break
+ case "Levy Ship":
+ add_lord_assets(game.who, SHIP, -1)
+ pop_state()
+ resume_levy_muster_lord()
+ break
+ case "Levy Vassal":
+ game.which = NOTHING
+ end_levy_muster_vassal()
+ break
+ case "Levy Troops":
+ kings_name_reset_troops()
+ pop_state()
+ resume_levy_muster_lord()
+ break
+ case "Parley":
+ shift_favour_toward_york(game.where)
+ pop_state()
+ game.where = NOWHERE
+ end_parley()
+ break
+ case "Capability":
+ game.which = NOTHING
+ pop_state()
+ pop_state()
+ resume_levy_muster_lord()
+ break
+ case "Levy Beloved Warwick":
+ add_lord_forces(game.who, MILITIA, -5)
+ pop_state()
+ resume_levy_muster_lord()
+ break
+ default:
+ throw Error("No King's name cancel state found")
+ }
+ log(`${game.what} action cancelled`)
+ logevent(`${EVENT_YORK_THE_KINGS_NAME}`)
+ set_active_enemy()
+}
+
+function kings_name_reset_troops() {
+ if (!lord_has_capability(game.who, AOW_LANCASTER_QUARTERMASTERS)) {
+ remove_depleted_marker(get_lord_locale(game.who))
+ remove_exhausted_marker(get_lord_locale(game.who))
+ }
+
+ let here = get_lord_locale(game.who)
+ let here_type = data.locales[here].type
+ switch (here_type) {
+ case "calais":
+ add_lord_forces(game.who, MEN_AT_ARMS, -2)
+ add_lord_forces(game.who, LONGBOWMEN, -1)
+ break
+ case "london":
+ add_lord_forces(game.who, MEN_AT_ARMS, -1)
+ add_lord_forces(game.who, LONGBOWMEN, -1)
+ add_lord_forces(game.who, MILITIA, -1)
+ break
+ case "harlech":
+ add_lord_forces(game.who, MEN_AT_ARMS, -1)
+ add_lord_forces(game.who, LONGBOWMEN, -2)
+ break
+ case "city":
+ add_lord_forces(game.who, LONGBOWMEN, -1)
+ add_lord_forces(game.who, MILITIA, -1)
+ break
+ case "town":
+ add_lord_forces(game.who, MILITIA, -2)
+ break
+ case "fortress":
+ add_lord_forces(game.who, MEN_AT_ARMS, -1)
+ add_lord_forces(game.who, MILITIA, -1)
+ break
+ }
+}
+
+// === EVENT: RISING WAGES ===
+
+states.rising_wages = {
+ inactive: "Rising Wages",
+ prompt() {
+ let here = get_lord_locale(game.who)
+ view.prompt = "Rising Wages: Pay 1 extra coin to levy troops"
+ for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord) {
+ let loc = get_lord_locale(lord)
+ if (here === loc && (get_lord_assets(lord, COIN) > 0)) {
+ gen_action_coin(lord)
+ }
+ }
+ },
+ coin(lord) {
+ push_undo()
+ add_lord_assets(lord, COIN, -1)
+ logi(`${EVENT_LANCASTER_RISING_WAGES}`)
+ log("York paid 1 Coin to Levy troops")
+ pop_state()
+ },
+}
+
+// Check if the levy troops is at vassal seat
+
+function chamberlains_eligible_levy(locale) {
+ for (let vassal = first_vassal; vassal <= last_vassal; ++vassal)
+ if (is_vassal_mustered_with(vassal, game.who) && lord_has_capability(game.who, AOW_LANCASTER_CHAMBERLAINS)) {
+ if (locale === data.vassals[vassal].seat)
+ return true
+ }
+}
+
+// === EVENT: THE COMMONS ===
+
+states.the_commons = {
+ inactive: "The Commons",
+ prompt() {
+ view.prompt = `Add up to ${game.flags.commons_militia} Militias.`
+ if (game.flags.commons_militia > 0) {
+ view.actions.add_militia = 1
+ }
+ view.actions.done = 1
+ },
+ add_militia() {
+ push_undo()
+ add_lord_forces(game.who, MILITIA, 1)
+ --game.flags.commons_militia
+ },
+ done() {
+ push_undo()
+ end_the_commons()
+
+ }
+}
+
+function end_the_commons() {
+ game.flags.commons_militia = 0
+ pop_state()
+ resume_levy_muster_lord()
+}
+
+// === EVENT (AS ACTION): EXILE PACT ===
+
+function can_action_exile_pact() {
+ if (game.actions <= 0 || !is_event_in_play(EVENT_YORK_EXILE_PACT))
+ return false
else
- gen_action("card", card_or_list)
+ return true
}
-function gen_action_plan(lord) {
- gen_action("plan", lord)
+function goto_exile_pact() {
+ push_undo()
+ game.state = "exile_pact"
}
-function gen_action_prov(lord) {
- gen_action("prov", lord)
+states.exile_pact = {
+ inactive: "Exile pact",
+ prompt() {
+ view.prompt = "Exile Pact : place your cylinder in one of your Exile boxes"
+ for (let loc of data.exile_boxes) {
+ if (has_favour_in_locale(game.active, loc))
+ gen_action_locale(loc)
+ }
+ },
+ locale(loc) {
+ push_undo()
+ set_lord_locale(game.command, loc)
+ end_exile_pact()
+ }
}
-function gen_action_coin(lord) {
- gen_action("coin", lord)
+function end_exile_pact() {
+ spend_action(1)
+ push_undo()
+ resume_command()
}
-function gen_action_cart(lord) {
- gen_action("cart", lord)
+// === EVENTS: HELD ===
+
+function play_held_event(c) {
+ log(`Played E${c}.`)
+ if (c >= first_york_card && c <= last_york_card)
+ set_delete(game.hand_y, c)
+ else
+ set_delete(game.hand_l, c)
+
+ /* Hold events with This Levy/Campaign */
+ if (
+ c === EVENT_YORK_YORKIST_PARADE ||
+ c === EVENT_YORK_PARLIAMENTS_TRUCE ||
+ c === EVENT_LANCASTER_PARLIAMENTS_TRUCE
+ ) {
+ set_add(game.events, c)
+ }
}
-function gen_action_mercenaries(lord) {
- gen_action("mercenaries", lord)
+// TODO: use or remove this function
+function end_held_event() {
+ pop_state()
+ game.what = NOTHING
}
-function gen_action_burgundians(lord) {
- gen_action("burgundians", lord)
+function prompt_held_event() {
+ for (let c of current_hand())
+ if (can_play_held_event(c))
+ gen_action_card(c)
}
-function gen_action_longbowmen(lord) {
- gen_action("longbowmen", lord)
+function can_play_held_event(c) {
+ switch (c) {
+ case EVENT_LANCASTER_ASPIELLES:
+ return can_play_l_aspielles()
+ case EVENT_LANCASTER_REBEL_SUPPLY_DEPOT:
+ return can_play_rebel_supply_depot()
+ case EVENT_LANCASTER_SURPRISE_LANDING:
+ return can_play_surprise_landing()
+ case EVENT_LANCASTER_PARLIAMENTS_TRUCE:
+ return can_play_parliaments_truce()
+ case EVENT_YORK_PARLIAMENTS_TRUCE:
+ return can_play_parliaments_truce()
+ case EVENT_YORK_ASPIELLES:
+ return can_play_y_aspielles()
+ case EVENT_YORK_YORKIST_PARADE:
+ return can_play_yorkist_parade()
+ case EVENT_YORK_SUN_IN_SPLENDOUR:
+ return can_play_sun_in_splendour()
+ }
+ return false
}
-function gen_action_retinue(lord) {
- gen_action("retinue", lord)
+function action_held_event(c) {
+ push_undo()
+ play_held_event(c)
+ game.what = c
+ goto_held_event(c)
}
-function gen_action_men_at_arms(lord) {
- gen_action("men_at_arms", lord)
+function goto_held_event(c) {
+ switch (c) {
+ case EVENT_YORK_ESCAPE_SHIP:
+ goto_play_escape_ship()
+ break
+ case EVENT_YORK_ASPIELLES:
+ goto_play_aspielles()
+ break
+ case EVENT_LANCASTER_ESCAPE_SHIP:
+ goto_play_escape_ship()
+ break
+ case EVENT_LANCASTER_TALBOT_TO_THE_RESCUE:
+ goto_play_talbot_to_the_rescue()
+ break
+ case EVENT_LANCASTER_WARDEN_OF_THE_MARCHES:
+ goto_play_warden_of_the_marches()
+ break
+ case EVENT_LANCASTER_REBEL_SUPPLY_DEPOT:
+ goto_play_rebel_supply_depot()
+ break
+ case EVENT_LANCASTER_SURPRISE_LANDING:
+ goto_play_surprise_landing()
+ break
+ case EVENT_LANCASTER_ASPIELLES:
+ goto_play_aspielles()
+ break
+ case EVENT_YORK_SUN_IN_SPLENDOUR:
+ goto_play_sun_in_splendour()
+ break
+ }
}
-function gen_action_militia(lord) {
- gen_action("militia", lord)
+// === HELD EVENT (LEVY): YORKIST PARADE ===
+
+function can_play_yorkist_parade() {
+ // TODO: only during levy?
+ if (game.active === YORK && is_favour_friendly(LOC_LONDON) && (get_lord_locale(LORD_WARWICK_Y) === LOC_LONDON || get_lord_locale(LORD_YORK) === LOC_LONDON)) {
+ return true
+ }
+ return false
}
-function gen_action_routed_mercenaries(lord) {
- gen_action("routed_mercenaries", lord)
+// === HELD EVENT (LEVY): SUN IN SPLENDOUR ===
+
+function can_play_sun_in_splendour() {
+ if (is_levy_phase() && is_lord_on_calendar(LORD_EDWARD_IV)) {
+ return true
+ }
+ return false
}
-function gen_action_routed_longbowmen(lord) {
- gen_action("routed_longbowmen", lord)
+function goto_play_sun_in_splendour() {
+ push_state("sun_in_splendour")
}
-function gen_action_routed_burgundians(lord) {
- gen_action("routed_burgundians", lord)
+states.sun_in_splendour = {
+ inactive: "Sun in splendour",
+ prompt() {
+ let done = true
+ view.prompt = "Sun in Splendour: Muster Edward IV in any friendly locale with no enemy lord"
+ if (is_lord_on_calendar(LORD_EDWARD_IV)) {
+ for (let loc = first_locale; loc <= last_locale; loc++) {
+ if (is_friendly_locale(loc)) {
+ done = false
+ gen_action_locale(loc)
+ }
+ }
+ }
+ if (done) {
+ view.actions.done = 1
+ }
+ },
+ locale(loc) {
+ push_undo()
+ muster_lord(LORD_EDWARD_IV, loc)
+ logi(`Mustered Edward IV at ${data.locales[loc].name}`)
+ },
+ done() {
+ end_sun_in_splendour()
+ },
}
-function gen_action_routed_men_at_arms(lord) {
- gen_action("routed_men_at_arms", lord)
+function end_sun_in_splendour() {
+ game.who = NOBODY
+ pop_state()
}
-function gen_action_routed_militia(lord) {
- gen_action("routed_militia", lord)
+// === HELD EVENT: ASPIELLES ===
+
+function can_play_l_aspielles() {
+ if (game.hand_y.length > 0 || game.hidden) {
+ return true
+ }
+ return false
}
-const YORK_LORD_MASK = 0x1fff
-const LANCASTER_LORD_MASK = YORK_LORD_MASK << 14
+function can_play_y_aspielles() {
+ if (game.hand_l.length > 0 || game.hidden) {
+ return true
+ }
+ return false
+}
+
+function goto_play_aspielles() {
+ push_state("aspielles")
+ game.who = NOBODY
+}
+
+states.aspielles = {
+ inactive: "Aspielles",
+ prompt() {
+ view.prompt = "Aspielles: You may see enemy held cards"
+ if (game.hidden) {
+ view.prompt += " and an enemy lord to see his mat"
+ }
+ prompt_held_event()
+ if (game.hidden) {
+ for (let lord = first_enemy_lord; lord <= last_enemy_lord; ++lord)
+ gen_action_lord(lord)
+ }
+ if (game.active === YORK) {
+ view.hand = game.hand_l
+ log("Lancaster hand shown to the York player")
+ }
+ if (game.active === LANCASTER) {
+ view.hand = game.hand_y
+ log("York hand shown to the Lancaster player")
+ }
+ view.actions.done = 1
+
+ },
+ lord(lord) {
+ log(`${lord_name[lord]} Spied`)
+ view.reveal |= (1 << lord)
+ },
+ card: action_held_event,
+ done() {
+ if (is_campaign_phase()) {
+ resume_command()
+ } else {
+ pop_state()
+ }
+ },
+}
+
+// === HELD EVENT: REBEL SUPPLY DEPOT ===
+
+function can_play_rebel_supply_depot() {
+ if (game.active === YORK)
+ return false
+ if (game.group) {
+ for (let lord of game.group) {
+ if (get_lord_moved(lord) && is_seaport(get_lord_locale(game.command))) {
+ return true
+ }
+ }
+ }
+ return false
+}
+
+function goto_play_rebel_supply_depot() {
+ game.flags.supply_depot = 1
+ add_spoils(PROV, 4)
+ push_state("rebel_supply_depot")
+}
+
+states.rebel_supply_depot = {
+ inactive: "Rebel Supply depot",
+ prompt() {
+ if (has_any_spoils()) {
+ view.prompt = "Divide " + list_spoils() + "."
+ let here = get_lord_locale(game.command)
+ for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord) {
+ if (get_lord_locale(lord) === here)
+ prompt_select_lord(lord)
+ if (game.who !== NOBODY)
+ prompt_spoils()
+ }
+ } else {
+ view.prompt = "Rebel Supply Depot: All done."
+ view.actions.end_spoils = 1
+ }
+ },
+ lord: action_select_lord,
+ take_prov() {
+ push_undo_without_who()
+ take_spoils(PROV)
+ },
+ end_spoils() {
+ end_rebel_supply_depot()
+ },
+}
+
+function end_rebel_supply_depot() {
+ game.who = NOBODY
+ game.spoils = 0
+ resume_command()
+}
+
+// === HELD EVENT: SURPRISE LANDING ===
+
+function can_play_surprise_landing() {
+ let here = get_lord_locale(game.command)
+ if (game.flags.surprise_landing === 0 || !is_seaport(here) || here === LOC_CALAIS || here === LOC_PEMBROKE || here === LOC_HARLECH || here === LANCASTER || is_sea(here))
+ return false
+ return true
+}
+
+function goto_play_surprise_landing() {
+ push_state("surprise_landing")
+ game.flags.surprise_landing = 2
+ game.who = NOBODY
+}
+
+states.surprise_landing = {
+ inactive: "Surprise Landing",
+ prompt() {
+ view.prompt = "Surprise Landing : You may march once (no path)."
+ prompt_held_event()
+
+ view.group = game.group
+ let here = get_lord_locale(game.command)
+ // 4.3.2 Marshals MAY take other lords
+ if (
+ is_marshal(game.command) ||
+ (lord_has_capability(game.command, AOW_YORK_CAPTAIN) && !other_marshal_or_lieutenant(here))
+ ) {
+ for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord)
+ 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 = first_friendly_lord; lord <= last_friendly_lord; ++lord)
+ if (lord !== game.command)
+ if (get_lord_locale(lord) === here && !is_marshal(lord)) {
+ gen_action_lord(lord)
+ }
+ }
+
+ prompt_march()
+ },
+ lord(lord) {
+ set_toggle(game.group, lord)
+ },
+ locale: goto_march,
+ card: action_held_event,
+}
+
+// === LOGGING ===
+
+function range(x) {
+ switch (x) {
+ case 0: return "0"
+ case 1: return "1"
+ case 2: return "1-2"
+ case 3: return "1-3"
+ case 4: return "1-4"
+ case 5: return "1-5"
+ case 6: return "Automatic success"
+ }
+}
+
+function log_br() {
+ if (game.log.length > 0 && game.log[game.log.length - 1] !== "")
+ game.log.push("")
+}
+
+function log(msg) {
+ game.log.push(msg)
+}
+
+function logevent(cap) {
+ game.log.push(`E${cap}.`)
+}
+
+function logcap(cap) {
+ game.log.push(`C${cap}.`)
+}
+
+function logi(msg) {
+ game.log.push(">" + msg)
+}
+
+function log_h1(msg) {
+ log_br()
+ log(".h1 " + msg)
+ log_br()
+}
+
+function log_h2(msg) {
+ log_br()
+ if (game.active === YORK)
+ log(".h2t " + msg)
+ else
+ log(".h2r " + msg)
+ log_br()
+}
+
+function log_h3(msg) {
+ log_br()
+ if (game.active === YORK)
+ log(".h3t " + msg)
+ else
+ log(".h3r " + msg)
+ log_br()
+}
+
+function log_h4(msg) {
+ log_br()
+ log(".h4 " + msg)
+}
+
+function log_h5(msg) {
+ log_br()
+ log(".h5 " + msg)
+}
+
+// === VIEW & ACTION ===
exports.view = function (state, current) {
load_state(state)
@@ -11746,39 +11609,146 @@ exports.action = function (state, current, action, arg) {
return game
}
-// === COMMON TEMPLATE ===
+function gen_action(action, argument) {
+ if (!(action in view.actions))
+ view.actions[action] = []
+ set_add(view.actions[action], argument)
+}
-// Packed array of small numbers in one word
+function gen_action_card_if_held(c) {
+ if (has_card_in_hand(c))
+ gen_action_card(c)
+}
-function pack1_get(word, n) {
- return (word >>> n) & 1
+function prompt_select_lord(lord) {
+ if (lord !== game.who)
+ gen_action_lord(lord)
}
-function pack2_get(word, n) {
- n = n << 1
- return (word >>> n) & 3
+function action_select_lord(lord) {
+ if (game.who === lord)
+ game.who = NOBODY
+ else
+ game.who = lord
}
-function pack4_get(word, n) {
- n = n << 2
- return (word >>> n) & 15
+function gen_action_locale(locale) {
+ gen_action("locale", locale)
}
-function pack1_set(word, n, x) {
- return (word & ~(1 << n)) | (x << n)
+function gen_action_lord(lord) {
+ gen_action("lord", lord)
}
-function pack2_set(word, n, x) {
- n = n << 1
- return (word & ~(3 << n)) | (x << n)
+function gen_action_array(pos) {
+ gen_action("array", pos)
}
-function pack4_set(word, n, x) {
- n = n << 2
- return (word & ~(15 << n)) | (x << n)
+function gen_action_vassal(vassal) {
+ gen_action("vassal", vassal)
+}
+
+function gen_action_card(card_or_list) {
+ if (Array.isArray(card_or_list))
+ for (let c of card_or_list)
+ gen_action("card", c)
+ else
+ gen_action("card", card_or_list)
+}
+
+function gen_action_plan(lord) {
+ gen_action("plan", lord)
+}
+
+function gen_action_prov(lord) {
+ gen_action("prov", lord)
+}
+
+function gen_action_coin(lord) {
+ gen_action("coin", lord)
+}
+
+function gen_action_cart(lord) {
+ gen_action("cart", lord)
+}
+
+function gen_action_mercenaries(lord) {
+ gen_action("mercenaries", lord)
+}
+
+function gen_action_burgundians(lord) {
+ gen_action("burgundians", lord)
+}
+
+function gen_action_longbowmen(lord) {
+ gen_action("longbowmen", lord)
+}
+
+function gen_action_retinue(lord) {
+ gen_action("retinue", lord)
+}
+
+function gen_action_men_at_arms(lord) {
+ gen_action("men_at_arms", lord)
+}
+
+function gen_action_militia(lord) {
+ gen_action("militia", lord)
+}
+
+function gen_action_routed_mercenaries(lord) {
+ gen_action("routed_mercenaries", lord)
+}
+
+function gen_action_routed_longbowmen(lord) {
+ gen_action("routed_longbowmen", lord)
+}
+
+function gen_action_routed_burgundians(lord) {
+ gen_action("routed_burgundians", lord)
+}
+
+function gen_action_routed_men_at_arms(lord) {
+ gen_action("routed_men_at_arms", lord)
+}
+
+function gen_action_routed_militia(lord) {
+ gen_action("routed_militia", lord)
+}
+
+// === GAME OVER ===
+
+function goto_game_over(result, victory) {
+ game.state = "game_over"
+ game.active = "None"
+ game.result = result
+ game.victory = victory
+ log_h1("Game Over")
+ log(game.victory)
+ return true
+}
+
+states.game_over = {
+ get inactive() {
+ return game.victory
+ },
+ prompt() {
+ view.prompt = game.victory
+ },
}
-// === COMMON LIBRARY ===
+// === UTILITY FUNCTIONS ===
+
+function push_state(next) {
+ if (!states[next])
+ throw Error("No such state: " + next)
+ game.stack.push([ game.state, game.who, game.count ])
+ game.state = next
+}
+
+function pop_state() {
+ [ game.state, game.who, game.count ] = game.stack.pop()
+}
function clear_undo() {
if (game.undo.length > 0)
@@ -11816,6 +11786,11 @@ function pop_undo() {
game.undo = save_undo
}
+function roll_die() {
+ clear_undo()
+ return random(6) + 1
+}
+
function random(range) {
// An MLCG using integer arithmetic with doubles.
// https://www.ams.org/journals/mcom/1999-68-225/S0025-5718-99-00996-5/S0025-5718-99-00996-5.pdf
@@ -11849,6 +11824,36 @@ function object_copy(original) {
}
}
+// Packed array of small numbers in one word
+
+function pack1_get(word, n) {
+ return (word >>> n) & 1
+}
+
+function pack2_get(word, n) {
+ n = n << 1
+ return (word >>> n) & 3
+}
+
+function pack4_get(word, n) {
+ n = n << 2
+ return (word >>> n) & 15
+}
+
+function pack1_set(word, n, x) {
+ return (word & ~(1 << n)) | (x << n)
+}
+
+function pack2_set(word, n, x) {
+ n = n << 1
+ return (word & ~(3 << n)) | (x << n)
+}
+
+function pack4_set(word, n, x) {
+ n = n << 2
+ return (word & ~(15 << n)) | (x << n)
+}
+
// Array remove and insert (faster than splice)
function array_remove_item(array, item) {
@@ -12060,6 +12065,8 @@ function map_delete(map, item) {
}
}
+// === FUZZING ASSERTS ===
+
const mutually_exclusive_lords = [
[LORD_EXETER_1, LORD_EXETER_2],
[LORD_SOMERSET_1, LORD_SOMERSET_2],