summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTroy Nordine <tdnordine@gmail.com>2023-09-28 21:13:36 -0500
committerTor Andersson <tor@ccxvii.net>2023-12-10 18:16:55 +0100
commit9fa42674c2be8e2c2e737755cdcdaf0278af81f2 (patch)
tree162bfd226b493ab333476dc44db167b1a55f328c
parentfab5a0ec52ffeea2dd03e1bc9a1ef9ab2dfa40fa (diff)
downloadplantagenet-9fa42674c2be8e2c2e737755cdcdaf0278af81f2.tar.gz
Added initial Disembark, Grow, Waste.
-rw-r--r--rules.js564
1 files changed, 384 insertions, 180 deletions
diff --git a/rules.js b/rules.js
index 6cf3113..f074db6 100644
--- a/rules.js
+++ b/rules.js
@@ -9,6 +9,10 @@ const YORK = "York"
var P1 = LANCASTER
var P2 = YORK
+const INFLUENCE_TURNS = [1, 4, 6, 9, 11, 14]
+const GROW_TURNS = [4, 9, 14]
+const WASTE_TURNS = [5, 10]
+
const HIT = [ "0", '\u2776', '\u2777', '\u2778', '\u2779', '\u277A', '\u277B' ]
const MISS = [ "0", '\u2460', '\u2461', '\u2462', '\u2463', '\u2464', '\u2465' ]
@@ -353,6 +357,13 @@ const VASSAL_MONTAGU = find_vassal('Montagu')
const VASSAL_THOMAS_STANLEY = find_vassal('Thomas Stanley')
const VASSAL_TROLLOPE = find_vassal('Trollope')
+const SEAS = [LOC_NORTH_SEA, LOC_IRISH_SEA, LOC_ENGLISH_CHANNEL]
+
+// === === === === FROM NEVSKY === === === ===
+
+// TODO: log end victory conditions at scenario start
+
+
const AOW_LANCASTER_CULVERINS_AND_FALCONETS = [ L1, L2 ] // TODO
const AOW_LANCASTER_MUSTERD_MY_SOLDIERS = L3 // TODO
const AOW_LANCASTER_HERALDS = L4 // TODO
@@ -1446,6 +1457,18 @@ function remove_depleted_marker(loc) {
function remove_exhausted_marker(loc) {
set_delete(game.pieces.exhausted, loc)
}
+
+function refresh_locale(locale) {
+ if (has_depleted_marker(locale)) {
+ remove_depleted_marker(locale)
+ }
+
+ if (is_locale_exhausted(locale)) {
+ remove_exhausted_marker(locale)
+ add_depleted_marker(locale)
+ }
+}
+
function deplete_locale(loc) {
if (has_depleted_marker(loc)) {
remove_depleted_marker(loc),
@@ -6587,88 +6610,37 @@ function goto_remove_markers() {
goto_command_activation()
}
-// === END CAMPAIGN: GROWTH ===
-// TODO : PLANTAGENET GROW
-function count_enemy_ravaged() {
- let n = 0
- for (let loc of game.pieces.ravaged)
- if (is_friendly_territory(loc))
- ++n
- return n
-}
-
-function goto_grow() {
- game.count = count_enemy_ravaged() >> 1
- log_br()
- if (game.active === TEUTONS)
- log("Teutonic Growth")
- else
- log("Russian Growth")
- if (game.count === 0) {
- logi("Nothing")
- end_growth()
- } else {
- game.state = "growth"
- }
-}
-
-function end_growth() {
- set_active_enemy()
- if (game.active === P2)
- goto_grow()
- else
- goto_game_end()
-}
-
-states.growth = {
- inactive: "Grow",
- prompt() {
- view.prompt = `Grow: Remove ${game.count} enemy Ravaged markers.`
- if (game.count > 0) {
- for (let loc of game.pieces.ravaged)
- if (is_friendly_territory(loc))
- gen_action_locale(loc)
- } else {
- view.actions.end_growth = 1
- }
- },
- locale(loc) {
- push_undo()
- logi(`%${loc}`)
- remove_ravaged_marker(loc)
- game.count--
- },
- end_growth() {
- clear_undo()
- end_growth()
- },
-}
-
// === END CAMPAIGN: GAME END ===
-function check_campaign_victory_york() {
+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))
+ 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() {
+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))
+ 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() {
- if (check_campaign_victory_york()) {
- goto_game_over(P1, `${P1} won a 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
- }
- if (check_campaign_victory_lancaster()) {
- goto_game_over(P2, `${P2} won a Campaign Victory!`)
+ } else if (york_v) {
+ goto_game_over(P1, `${YORK} won a Campaign Victory!`)
+ return true
+ } else if (lancaster_v) {
+ goto_game_over(P2, `${LANCASTER} won a Campaign Victory!`)
return true
}
+
return false
}
@@ -6691,156 +6663,238 @@ function check_disband_victory() {
}
-function goto_end_campaign() {
- log_h1("End Campaign")
+function check_scenario_end_victory() {
+ if (current_turn() === scenario_last_turn[game.scenario]) { // Scenario End Victory
- set_active(P1)
+ 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
- if (current_turn() === 8 || current_turn() === 16) {
- goto_grow()
- } else {
- goto_game_end()
- }
}
-function goto_game_end() {
- // GAME END
- if (current_turn() === scenario_last_turn[game.scenario]) {
- goto_game_over("Draw", "The game ended in a draw.")
- } else {
- goto_plow_and_reap()
+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
}
-// === END CAMPAIGN: PLOW AND REAP ===
-function goto_plow_and_reap() {
- let turn = current_turn()
- end_plow_and_reap()
-}
+function goto_end_campaign() {
+ log_h1("End Campaign")
-function end_plow_and_reap() {
- goto_wastage()
+ set_active(P1)
+ tides_of_war()
}
-// === END CAMPAIGN: WASTAGE ===
-// TODO : WASTE
-function goto_wastage() {
- if (game.turn === 5 || game.turn === 10) {
- clear_lords_moved()
- let done = true
- for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord) {
- if (check_lord_wastage(lord)) {
- set_lord_moved(lord, 3)
- done = false
+function goto_game_end() {
+ // GAME END
+
+ if (!(check_scenario_end_victory() || check_campaign_victory() || check_threshold_victory())) {
+
+ if (GROW_TURNS.includes(current_turn())) {
+ do_grow()
+ } else if (WASTE_TURNS.includes(current_turn())) {
+ do_waste()
+ } else {
+ goto_reset()
}
}
- if (done)
- end_wastage()
- else
- game.state = "wastage"
-}
- else {
- push_undo()
- goto_reset()
- }
}
-function check_lord_wastage(lord) {
- if (get_lord_assets(lord, PROV) > 1)
- return true
- if (get_lord_assets(lord, COIN) > 1)
- return true
- if (get_lord_assets(lord, CART) > 1)
- return true
- if (get_lord_assets(lord, SHIP) > 1)
- return true
- return false
+function do_grow() {
+ for (let x = first_locale; x <= last_locale; x++) {
+ refresh_locale(x)
+ }
+ goto_reset()
}
-function prompt_wastage(lord) {
- if (get_lord_assets(lord, PROV) > 0)
- gen_action_prov(lord)
- if (get_lord_assets(lord, COIN) > 0)
- gen_action_coin(lord)
- if (get_lord_assets(lord, CART) > 0)
- gen_action_cart(lord)
- if (get_lord_assets(lord, SHIP) > 0)
- gen_action_ship(lord)
- for (let i = 0; i < 2; ++i) {
- let c = get_lord_capability(lord, i)
- if (c !== NOTHING)
- gen_action_card(c)
+function do_waste() {
+ for (let x = first_lord; x <= last_lord; x++) {
+ if (is_lord_on_map(x)){
+ do_lord_waste(x)
+ }
}
-}
-function action_wastage(lord, type) {
- push_undo()
- set_lord_moved(lord, 0)
- add_lord_assets(lord, type, -1)
+ goto_reset()
}
-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 do_lord_waste(lord) {
+ [PROV, CART, SHIP].forEach(a => remove_half(lord, a))
+ set_lord_assets(lord, COIN, data.lords[lord].coin)
+ muster_lord_forces(lord)
}
-states.wastage = {
- inactive: "Wastage",
- prompt() {
- let done = true
- for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord) {
- if (get_lord_moved(lord)) {
- prompt_wastage(lord)
- done = false
- }
- }
- if (done) {
- view.prompt = "Wastage: All done."
- view.actions.end_wastage = 1
- } else {
- view.prompt = "Wastage: Discard one Asset or Capability from each affected Lord."
- }
- },
- card(c) {
- push_undo()
- let lord = find_lord_with_capability_card(c)
- set_lord_moved(lord, 0)
- discard_lord_capability(lord, c)
- },
- prov(lord) { action_wastage(lord, PROV) },
- coin(lord) { action_wastage(lord, COIN) },
- cart(lord) { action_wastage(lord, CART) },
- ship(lord) { action_wastage(lord, SHIP) },
- end_wastage() {
- end_wastage()
- },
+function remove_half(lord, type) {
+ set_lord_assets(lord, type, Math.ceil(get_lord_assets(lord, type)/2))
}
-function end_wastage() {
- push_undo()
- set_active_enemy()
- goto_reset()
-}
+
+// === END CAMPAIGN: WASTAGE ===
+// TODO : WASTE
+// function goto_wastage() {
+// if (game.turn === 5 || game.turn === 10) {
+// clear_lords_moved()
+// let done = true
+// for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord) {
+// if (check_lord_wastage(lord)) {
+// set_lord_moved(lord, 3)
+// done = false
+// }
+// }
+// if (done)
+// end_wastage()
+// else
+// game.state = "wastage"
+// }
+// else {
+// push_undo()
+// goto_reset()
+// }
+// }
+
+// function check_lord_wastage(lord) {
+// if (get_lord_assets(lord, PROV) > 1)
+// return true
+// if (get_lord_assets(lord, COIN) > 1)
+// return true
+// if (get_lord_assets(lord, CART) > 1)
+// return true
+// if (get_lord_assets(lord, SHIP) > 1)
+// return true
+// return false
+// }
+
+// function prompt_wastage(lord) {
+// if (get_lord_assets(lord, PROV) > 0)
+// gen_action_prov(lord)
+// if (get_lord_assets(lord, COIN) > 0)
+// gen_action_coin(lord)
+// if (get_lord_assets(lord, CART) > 0)
+// gen_action_cart(lord)
+// if (get_lord_assets(lord, SHIP) > 0)
+// gen_action_ship(lord)
+// for (let i = 0; i < 2; ++i) {
+// let c = get_lord_capability(lord, i)
+// if (c !== NOTHING)
+// gen_action_card(c)
+// }
+// }
+
+// function action_wastage(lord, type) {
+// push_undo()
+// set_lord_moved(lord, 0)
+// add_lord_assets(lord, type, -1)
+// }
+
+// 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
+// }
+
+// states.wastage = {
+// inactive: "Wastage",
+// prompt() {
+// let done = true
+// for (let lord = first_friendly_lord; lord <= last_friendly_lord; ++lord) {
+// if (get_lord_moved(lord)) {
+// prompt_wastage(lord)
+// done = false
+// }
+// }
+// if (done) {
+// view.prompt = "Wastage: All done."
+// view.actions.end_wastage = 1
+// } else {
+// view.prompt = "Wastage: Discard one Asset or Capability from each affected Lord."
+// }
+// },
+// card(c) {
+// push_undo()
+// let lord = find_lord_with_capability_card(c)
+// set_lord_moved(lord, 0)
+// discard_lord_capability(lord, c)
+// },
+// prov(lord) { action_wastage(lord, PROV) },
+// coin(lord) { action_wastage(lord, COIN) },
+// cart(lord) { action_wastage(lord, CART) },
+// ship(lord) { action_wastage(lord, SHIP) },
+// end_wastage() {
+// end_wastage()
+// },
+// }
+
+// function end_wastage() {
+// push_undo()
+// set_active_enemy()
+// goto_reset()
+// }
// === END CAMPAIGN: RESET (DISCARD ARTS OF WAR) ===
function goto_reset() {
+ game.state = "reset"
// Discard "This Campaign" events from play.
discard_friendly_events("this_campaign")
- end_reset()
+
+}
+
+states.reset = {
+ inactive: "Reset",
+ prompt() {
+ view.prompt = "Reset: You may discard any held Arts of War cards desired."
+ if (game.active === P1) {
+ for (let c = first_p1_card; c <= last_p1_card; ++c)
+ if (can_discard_card(c))
+ gen_action_card(c)
+ }
+ if (game.active === P2) {
+ for (let c = first_p2_card; c <= last_p2_card; ++c)
+ if (can_discard_card(c))
+ gen_action_card(c)
+ }
+ view.actions.end_discard = 1
+ },
+ card(c) {
+ push_undo()
+ if (set_has(game.hand1, c)) {
+ log("Discarded Held card.")
+ set_delete(game.hand1, c)
+ } else if (set_has(game.hand2, c)) {
+ log("Discarded Held card.")
+ set_delete(game.hand2, c)
+ }
+ },
+ end_discard() {
+ end_reset()
+ },
}
function end_reset() {
clear_undo()
set_active_enemy()
if (game.active === P2)
- goto_plow_and_reap()
+ goto_reset()
else
- tides_of_war()
+ goto_advance_campaign()
}
// === END CAMPAIGN: TIDES OF WAR ===
@@ -7050,8 +7104,26 @@ function tides_calc(){
domy += 1
}
- log(`Total ` + domy + ` Influence for York`)
- log(`Total ` + doml + ` Influence for Lancaster`)
+ if (INFLUENCE_TURNS.includes(current_turn())) {
+ for (let y = first_york_lord; y <= last_york_lord; y++) {
+ if (is_lord_on_map(y)) {
+ domy += data.lords[y].influence
+ }
+ }
+
+ for (let l = first_lancaster_lord; y <= last_lancaster_lord; y++) {
+ if (is_lord_on_map(l)) {
+ domy += data.lords[l].influence
+ }
+ }
+
+ }
+
+ log(`Total ` + domy + ` Influence for York`)
+ log(`Total ` + doml + ` Influence for Lancaster`)
+
+ game.influence += doml
+ game.influence -= domy
}
@@ -7065,9 +7137,141 @@ function tides_of_war() {
}
tides_calc()
- goto_advance_campaign()
+ goto_disembark()
+}
+
+// === END CAMPAIGN: DISEMBARK ===
+
+function has_lords_at_sea() {
+ for (let x = first_friendly_lord; x <= last_friendly_lord; x++) {
+ if (is_lord_at_sea(x))
+ return true
+ }
+ return false
+}
+
+function get_lords_at_sea() {
+ let results = []
+ for (let x = first_friendly_lord; x <= last_friendly_lord; x++) {
+ if (is_lord_at_sea(x)) {
+ results.push(x)
+ }
+ }
+ return results;
+}
+
+function is_lord_at_sea(lord) {
+ return SEAS.includes(get_lord_locale(lord))
+}
+
+function goto_disembark() {
+ if (has_lords_at_sea()) {
+ game.state = "disembark"
+ } else {
+ end_disembark()
+ }
+}
+
+function end_disembark() {
+ clear_undo()
+ game.who = NOBODY
+ set_active_enemy()
+ if (game.active === P2)
+ goto_disembark()
+ else
+ goto_game_end()
+}
+
+function do_disembark() {
+ let roll = roll_die()
+ let success = roll >= 5
+
+ return success
+}
+
+function get_safe_ports(sea) {
+ let ports
+ if (data.sea_1.contains(sea)) ports = data.port_1
+ if (data.sea_2.contains(sea)) ports = data.port_2
+ if (data.sea_3.contains(sea)) ports = data.port_3
+
+ return ports
+ .filter(p => !has_enemy_lord(p))
+}
+
+function has_safe_ports(sea) {
+ return get_safe_ports(sea).length > 0
+}
+
+states.disembark = {
+ inactive: "Disembark",
+ prompt() {
+ view.prompt = "Disembark your lords at sea."
+ let done = true
+ if (game.who === NOBODY) {
+ get_lords_at_sea()
+ .forEach(l => {gen_action_lord(l);done=false})
+ } else {
+ let sea = get_lord_locale(game.who)
+ get_safe_ports(sea)
+ .forEach(gen_action_locale)
+ }
+
+ if (done) {
+ view.actions.done = 1
+ }
+ },
+ lord(lord) {
+ if (do_disembark(lord)) {
+ if (has_safe_ports(get_lord_locale(lord))) {
+ game.who = lord
+ } else {
+ no_safe_disembark(lord)
+ }
+ } else {
+ shipwreck(lord)
+ }
+
+ },
+ locale(loc) {
+ successful_disembark(game.who, loc)
+ },
+ done() {
+ end_disembark()
+ }
+}
+
+function successful_disembark(lord, loc) {
+ set_lord_locale(lord, loc)
+ set_lord_moved(lord, 1)
+
+ goto_feed()
}
+function shipwreck(lord) {
+ let influence = data.lords[lord].influence
+
+ for (let v = first_vassal; v <= last_vassal; v++) {
+ if (get_vassal_locale(v) === lord) {
+ influence += 1
+ }
+ }
+
+ disband_lord(lord, true)
+
+ if (game.active === LANCASTRIANS)
+ game.ip -= influence
+ else
+ game.ip += influence
+}
+
+function no_safe_disembark(lord) {
+ disband_lord(lord)
+}
+
+
+
+
function goto_advance_campaign() {
game.turn++