summaryrefslogtreecommitdiff
path: root/rules.js
diff options
context:
space:
mode:
Diffstat (limited to 'rules.js')
-rw-r--r--rules.js183
1 files changed, 127 insertions, 56 deletions
diff --git a/rules.js b/rules.js
index f822600..5f25ae0 100644
--- a/rules.js
+++ b/rules.js
@@ -2828,7 +2828,7 @@ states.levy_muster_lord = {
parley() {
push_undo()
- goto_parley(game.who, "levy")
+ goto_parley()
},
done() {
@@ -3312,11 +3312,12 @@ states.command = {
parley() {
push_undo()
- goto_parley(game.command, "command")
+ goto_parley()
},
}
// === INFLUENCE CHECKS ===
+
function influence_capabilities(lord, score) {
let here = get_lord_locale(game.group)
if (game.state === "parley" && lord_has_capability(game.group, AOW_LANCASTER_IN_THE_NAME_OF_THE_KING))
@@ -3434,49 +3435,111 @@ function prompt_influence_check() {
// INFLUENCE CHECK = 8) and 9) and 10) Will happen a lot in the game, so a own function is best that will be modified depending on exceptions
-function command_parley_accept(loc) {
- return !is_exile(loc.locale) && !is_friendly_locale(loc.locale) && !has_enemy_lord(loc.locale) && loc.distance <= 1
+function can_parley_at(loc) {
+ return !is_exile(loc) && !is_friendly_locale(loc) && !has_enemy_lord(loc)
+}
+
+var search_seen = new Array(last_locale + 1)
+var search_dist = new Array(last_locale + 1)
+
+function search_parley_during_levy(result, start) {
+ let ships = get_shared_assets(start, SHIP)
+
+ 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 (can_parley_at(here)) {
+ if (result)
+ map_set(result, here, dist)
+ else
+ return true
+ }
+
+ 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 (ships > 0 && is_seaport(next)) {
+ for (let next of find_ports_from_port(here)) {
+ if (!search_seen[next]) {
+ search_seen[next] = 1
+ search_dist[next] = next_dist
+ queue.push(next)
+ }
+ }
+ }
+ }
+ }
+
+ if (result)
+ return result
+ else
+ return false
}
function can_action_parley_command() {
if (game.actions <= 0)
return false
- let targets = map_search(game.command, command_parley_accept, parley_adjacent)
- let res = targets.next()
- return res.done !== true
-}
+ let here = get_lord_locale(game.command)
-function levy_parley_accept(loc) {
- return !is_exile(loc.locale) && !is_friendly_locale(loc.locale) && !has_enemy_lord(loc.locale)
-}
+ if (can_parley_at(here))
+ return true
-function can_action_parley_levy() {
- if (game.count <= 0)
- return false
+ for (let next of data.locales[here].adjacent)
+ if (can_parley_at(next))
+ return true
- let targets = map_search(game.who, levy_parley_accept, parley_adjacent)
+ if (is_seaport(here) && get_shared_assets(here, SHIP) > 0)
+ for (let next of find_ports_from_port(here))
+ if (can_parley_at(next))
+ return true
- return targets.next().done !== true
+ return false
}
-function parley_adjacent(here, _) {
- let seaports = []
+function list_parley_command() {
+ let result = []
- // TODO: precompute these?
+ let here = get_lord_locale(game.command)
+ if (can_parley_at(here))
+ set_add(result, here)
- if (is_exile(here) && get_shared_assets(here, SHIP) > 0) {
- return find_ports_from_exile(here)
- } else if (is_seaport(here) && get_shared_assets(here, SHIP) > 0) {
- if (set_has(data.port_1, here))
- seaports = data.port_1
- if (set_has(data.port_2, here))
- seaports = data.port_2
- if (set_has(data.port_3, here))
- seaports = data.port_3
- }
+ for (let next of data.locales[here].adjacent)
+ if (can_parley_at(next))
+ set_add(result, here)
- return data.locales[here].adjacent.concat(seaports)
+ if (is_seaport(here) && get_shared_assets(here, SHIP) > 0)
+ for (let next of find_ports_from_port(here))
+ if (can_parley_at(next))
+ set_add(result, here)
+
+ return result
+}
+
+function can_action_parley_levy() {
+ if (game.count <= 0)
+ return false
+ let here = get_lord_locale(game.who)
+ if (can_parley_at(here))
+ return true
+ return search_parley_during_levy(false, here)
+}
+
+function list_parley_levy() {
+ let here = get_lord_locale(game.who)
+ return search_parley_during_levy([], here)
}
function find_ports_from_exile(here) {
@@ -3497,6 +3560,16 @@ function find_ports_from_sea(here) {
return null
}
+function find_ports_from_port(here) {
+ 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_destinations_from_port(here) {
switch (true) {
case here === data.exile_1: return data.way_exile_1
@@ -3512,13 +3585,6 @@ function find_destinations_from_port(here) {
return null
}
-function find_parley_targets(lord, acceptfn, adjacentfn) {
- let results = []
- for (let loc of map_search(lord, acceptfn, adjacentfn))
- results.push(loc)
- return results
-}
-
function* map_search(lord, acceptfn, adjacentfn, prune = true) {
let start = get_lord_locale(lord)
let queue = [ { locale: start, distance: 0 } ]
@@ -3545,22 +3611,27 @@ function* map_search(lord, acceptfn, adjacentfn, prune = true) {
}
}
-function goto_parley(lord, from) {
+function goto_parley() {
push_state("parley")
- init_influence_check(lord)
- if (from === "levy")
- game.what = find_parley_targets(lord, levy_parley_accept, parley_adjacent)
- else
- game.what = find_parley_targets(lord, command_parley_accept, parley_adjacent)
+ if (is_levy_phase()) {
+ init_influence_check(game.who)
+ game.what = list_parley_levy()
+ } else {
+ init_influence_check(game.command)
+ game.what = list_parley_command()
- if (game.what.length === 1 && is_campaign_phase() && get_lord_locale(lord) === game.what[0].locale) {
// Campaign phase, and current location is no cost (except some events), and always successful.
- shift_favour_toward(game.what[0].locale)
- end_parley()
- } else if (game.what.length === 1) {
- game.where = game.what[0].locale
- add_influence_check_distance(game.what[0].distance)
+ if (game.what.length === 2 && get_lord_locale(game.command) === game.what[0]) {
+ shift_favour_toward(game.what[0].locale)
+ end_parley()
+ return
+ }
+ }
+
+ if (game.what.length === 2) {
+ game.where = game.what[0]
+ add_influence_check_distance(game.what[1])
} else {
game.where = NOWHERE
}
@@ -3572,7 +3643,7 @@ function end_parley() {
game.where = NOWHERE
game.what = NOTHING
end_influence_check()
- if (game.state === "command") {
+ if (is_campaign_phase()) {
spend_action(1)
resume_command()
} else {
@@ -3585,23 +3656,23 @@ states.parley = {
prompt() {
view.prompt = "Parley: Choose a Locale to Parley."
if (game.where === NOTHING) {
- for (let loc of game.what)
- gen_action_locale(loc.locale)
+ for (let i = 0; i < game.what.length; i += 2)
+ gen_action_locale(game.what[i])
} else {
view.prompt = "Parley: "
prompt_influence_check()
}
},
locale(loc) {
+ push_undo()
game.where = loc
- for (let loc of game.what) {
- if (loc.locale === game.where)
- add_influence_check_distance(loc.distance)
- }
+ add_influence_check_distance(map_get(game.what, loc))
},
spend1: add_influence_check_modifier_1,
spend3: add_influence_check_modifier_2,
check() {
+ clear_undo()
+
let results = do_influence_check()
log(`Attempt to Parley with %${game.where} ${results.success ? "Successful" : "Failed"}: (${range(results.rating)}) ${results.success ? HIT[results.roll] : MISS[results.roll]}`)