summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTroy Nordine <tdnordine@gmail.com>2023-09-15 08:36:50 -0500
committerTor Andersson <tor@ccxvii.net>2023-12-10 18:16:55 +0100
commit6e2916306b73f1f55458215e43f08dcdf6017986 (patch)
tree0199d5fbf87ad34556c483b913cd5516aafe5165
parent3d38b4e9bf51effaa02d9dc2fe83ff2e4b27ec18 (diff)
downloadplantagenet-6e2916306b73f1f55458215e43f08dcdf6017986.tar.gz
Initial Parley Changes.
-rw-r--r--rules.js227
1 files changed, 224 insertions, 3 deletions
diff --git a/rules.js b/rules.js
index ea22080..4c704a2 100644
--- a/rules.js
+++ b/rules.js
@@ -1169,11 +1169,11 @@ function is_friendly_locale(loc) {
if (loc !== NOWHERE && loc < CALENDAR) {
if (has_enemy_lord(loc))
return false
- /*if (has_favour_marker(loc)) { //to add friendly favour marker later
+ if (is_favour_friendly(loc, game.active)) { //to add friendly favour marker later
return true
- }*/
+ }
}
- return true // TESTING PURPOSES NEED TO CHANGE TO FALSE
+ return false // TESTING PURPOSES NEED TO CHANGE TO FALSE
}
function can_add_troops(lordwho, locale) {
@@ -1235,6 +1235,34 @@ function increase_lancaster_influnce(amt) {
game.influence += amt
}
+function shift_favor_away(loc) {
+ if (game.active === YORK)
+ shift_favor_toward_lancaster(loc)
+ else
+ shift_favor_toward_york(loc)
+}
+
+function shift_favor_toward(loc) {
+ if (game.active === YORK)
+ shift_favor_toward_york(loc)
+ else
+ shift_favor_toward_lancaster(loc)
+}
+
+function shift_favor_toward_york(loc) {
+ if (has_favourl_marker(loc))
+ remove_favourl_marker(loc)
+ else
+ add_favoury_marker(loc)
+}
+
+function shift_favor_toward_lancaster(loc) {
+ if (has_favoury_marker(loc))
+ remove_favoury_marker(loc)
+ else
+ add_favourl_marker(loc)
+}
+
/*
function count_unbesieged_friendly_lords(loc) {
let n = 0
@@ -1423,6 +1451,7 @@ exports.setup = function (seed, scenario, options) {
march: 0,
battle: 0,
spoils: 0,
+ parley: 0,
}
update_aliases()
@@ -2178,6 +2207,9 @@ states.levy_muster_lord = {
// Add Capability
if (can_add_lord_capability(game.who))
view.actions.capability = 1
+
+ if (can_action_parley_levy())
+ view.actions.parley = 1
}
view.actions.done = 1
@@ -2254,6 +2286,10 @@ states.levy_muster_lord = {
push_state("muster_capability")
},
+ parley() {
+ goto_parley(game.who, "levy")
+ },
+
done() {
set_lord_moved(game.who, 1)
pop_state()
@@ -2680,6 +2716,8 @@ states.command = {
view.actions.tax = 1
if (can_action_sail())
view.actions.sail = 1
+ if (can_action_parley_command())
+ view.actions.parley = 1
},
pass() {
@@ -2708,8 +2746,56 @@ states.command = {
},
card: action_held_event,
+
+ parley() {
+ goto_parley(game.command, "command")
+ },
}
+// === INFLUENCE CHECKS ===
+
+function init_influence_check(lord, base_cost) {
+ game.check = []
+
+ if (base_cost > 0) {
+ game.check.push({cost:base_cost, modifier: 0, source: "base"})
+ }
+ game.check.push({cost: 0, modifier: data.lords[lord].influence, source: "lord"})
+}
+
+function end_infllunce_check() {
+ game.check = 0
+}
+
+function do_influence_check() {
+ reduce_influence(game.check.reduce((p,c) => p+c.cost, 0))
+ let rating = game.check.reduce((p,c) => p+c.modifier, 0)
+ let roll = roll_die()
+
+ return {success: roll <= rating, rating: rating, roll: roll}
+}
+
+function add_influence_check_modifier_1() {
+ game.check.push({cost: 1, modifier: 1, source: "add"})
+}
+
+function add_influence_check_modifier_2() {
+ game.check.push({cost: 3, modifier: 2, source: "add"})
+}
+
+function add_influence_check_distance(distance) {
+ game.check.push({cost: distance, modifier: 0, source: "distance"})
+}
+
+function prompt_influence_check() {
+ if (!game.check.some(c => c.source === "add")) {
+ gen_action("spend1")
+ gen_action("spend3")
+ }
+ view.actions.check = 1
+}
+
+
// === ACTION: PARLEY ===
// 1) During Levy / game.who -- Campaign / game.command
@@ -2732,6 +2818,141 @@ states.command = {
// 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(here) && !is_friendly_locale(loc.locale) && !has_enemy_lord(loc.locale) && loc.distance <= 1
+}
+
+function can_action_parley_command() {
+ let targets = find_parley_targets(game.command, command_parley_accept, parley_adjacent)
+
+ return targets.next().done !== true
+}
+
+function levy_parley_accept(loc) {
+ return !is_exile(here) && !is_friendly_locale(loc.locale) && !has_enemy_lord(loc.locale)
+}
+
+function can_action_parley_levy() {
+ let targets = find_parley_targets(game.command, levy_parley_accept, parley_adjacent)
+
+ return targets.next().done !== true
+}
+
+function parley_adjacent(here) {
+ let seaports = []
+ if (is_seaport(here) && get_lord_assets(lord, SHIP) > 0 ) {
+ if (data.port_1.includes(here)) seaports = data.port_1
+ if (data.port_2.includes(here)) seaports = data.port_2
+ if (data.port_3.includes(here)) seaports = data.port_3
+ } else if (is_exile(here) && get_lord_assets(lord, SHIP) > 0) {
+ return find_ports_from_exile(here)
+ }
+ return data.locales[here].adjacent.concat(seaports)
+}
+
+function find_ports_from_exile(here) {
+ if (data.exile_1.includes(here)) return data.port_1
+ if (data.exile_2.includes(here)) return data.port_2
+ if (data.exile_3.includes(here)) return data.port_3
+}
+
+function find_parley_targets(lord, acceptfn, adjacentfn) {
+ let results = []
+ for (let loc in map_search(lord, acceptfn, adjacentfn))
+ results.push(loc)
+ return results
+}
+
+function* map_search(lord, acceptfn, adjacentfn) {
+ let here = get_lord_locale(lord)
+ let locales = [{locale:here, distance: 0}]
+
+ let seen = []
+
+ while (true) {
+ if (locales.length === 0)
+ return
+
+ let loc = locales.shift()
+ seen.push(loc.locale)
+
+ if (acceptfn(loc)) {
+ yield loc
+ continue
+ }
+ if (is_friendly_locale(loc.locale)) {
+ let distance = loc.distance + 1
+ locales = locales.concat(
+ adjacentfn(loc.locale)
+ .filter(l => !seen.includes(l))
+ .filter(l => !locales.some((r) => r.locale === l))
+ .map(x => {return {locale: x, distance: distance }})
+ )
+ }
+ }
+}
+
+function goto_parley(lord, from) {
+ push_undo()
+ push_state("parley")
+ 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)
+
+ game.where = NOWHERE
+ init_influence_check(lord, 0)
+}
+
+function end_parley() {
+ clear_undo()
+ pop_state()
+ game.where = NOWHERE
+ game.what = NOTHING
+ end_infllunce_check()
+ if (game.state === "command") {
+ spend_action(1)
+ resume_command()
+ } else {
+ resume_levy_muster_lord()
+ }
+}
+
+states.parley = {
+ inactive: "Parley",
+ prompt() {
+ view.prompt = "Parley: Choose a Locale to Parley."
+ if (game.where === NOTHING) {
+ for (let loc in game.what)
+ gen_action_locale(loc.locale)
+ } else {
+ prompt_influence_check()
+ }
+
+ },
+ locale(loc) {
+ game.where = loc
+ },
+ spend1:add_influence_check_modifier_1,
+ spend3:add_influence_check_modifier_2,
+ check() {
+ for (let loc in game.what) {
+ if (loc.locale === game.where)
+ add_influence_check_distance(loc.distance)
+ }
+
+ 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]}`)
+
+ if (results.success) {
+ shift_favor_toward(game.where)
+ }
+ end_parley()
+ }
+}
+
+
// === ACTION: LEVY VASSAL ===
// 1) During Levy ONLY
// 2) game.who location must be friendly and Vassal seat locale must be friendly