summaryrefslogtreecommitdiff
path: root/rules.js
diff options
context:
space:
mode:
Diffstat (limited to 'rules.js')
-rw-r--r--rules.js243
1 files changed, 219 insertions, 24 deletions
diff --git a/rules.js b/rules.js
index ba0a1d8..d3a6a3b 100644
--- a/rules.js
+++ b/rules.js
@@ -47,6 +47,7 @@ const last_space = S_PUNJAB
const last_province = S_TAMILAKAM
const faction_name = [ "Delhi Sultanate", "Bahmani Kingdom", "Vijayanagara Empire", "Mongol Invaders" ]
+const faction_acronyms = [ "ds", "bk", "ve", "mi" ]
exports.scenarios = [ "Standard", "Solo" ]
@@ -89,14 +90,14 @@ exports.view = function (state, role) {
let deck_size = Math.max(0, game.deck.length - 1)
view = {
+ state: game.state,
prompt: null,
actions: null,
log: game.log,
current: game.current,
vp: game.vp,
resources: game.resources,
- bk_inf: 0,
- ve_inf: 0,
+ inf: game.inf,
deck: [ this_card, deck_size, game.of_gods_and_kings ],
cavalry: game.cavalry,
cylinder: game.cylinder,
@@ -104,6 +105,7 @@ exports.view = function (state, role) {
tributary: game.tributary,
control: game.control,
rebel: game.rebel,
+ order: game.order,
}
if (game.result) {
@@ -189,14 +191,14 @@ exports.setup = function (seed, scenario, _options) {
resources: [ 12, 6, 7 ],
vp: [ 18, 0, 0 ],
prosperity: [ 0, 0, 0 ],
- bk_inf: 0,
- ve_inf: 0,
+ inf: [null, 1, 2],
tributary: 8191, // all 13 provinces
control: [0, 0, 0],
rebel: [null, 0, 0], // amir/raja rebel status
pieces: Array(104).fill(AVAILABLE), // piece locations
cavalry: Array(10).fill(AVAILABLE),
deck: [],
+ order: [],
cmd: {
type: null,
limited: null,
@@ -204,6 +206,7 @@ exports.setup = function (seed, scenario, _options) {
spaces: [],
pieces: [],
where: null,
+ who: null,
},
decree: 0
}
@@ -230,7 +233,7 @@ exports.setup = function (seed, scenario, _options) {
}
function setup_deck() {
- game.deck = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 ]
+ game.deck = [ 1, 37, 2, 41, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 ]
}
function setup_standard() {
@@ -285,11 +288,19 @@ function this_card() {
}
function goto_card() {
- log_h1("C" + this_card())
- if (this_card() === "todo")
- console.log("todo")
- else
+ if (this_card() >= 37 && this_card() <= 39) {
+ log_h1("Mongol Invaders C" + this_card())
+ goto_mongol_invaders(BK)
+ } else if (this_card() >= 40 && this_card() <= 42) {
+ log_h1("Mongol Invaders C" + this_card())
+ goto_mongol_invaders(VE)
+ } else {
+ log_h1("C" + this_card())
+ adjust_eligibility(DS)
+ adjust_eligibility(BK)
+ adjust_eligibility(VE)
resume_event_card()
+ }
}
function resume_event_card() {
@@ -304,10 +315,6 @@ function resume_event_card() {
function end_card() {
clear_undo()
- adjust_eligibility(DS)
- adjust_eligibility(BK)
- adjust_eligibility(VE)
-
array_remove(game.deck, 0)
goto_card()
}
@@ -341,8 +348,8 @@ function did_option(e) {
}
function next_eligible_faction() {
- let order = data.card_order[this_card()]
- for (let faction of order)
+ game.order = data.card_order[this_card()]
+ for (let faction of game.order)
if (is_eligible(faction))
return faction
return -1
@@ -373,6 +380,16 @@ function goto_pass() {
resume_event_card()
}
+function goto_advance() {
+ init_command("Advance")
+ game.state = "advance"
+}
+
+function goto_amass() {
+ init_command("Amass")
+ game.state = "amass"
+}
+
function goto_build() {
init_command("Build")
game.state = "build"
@@ -388,6 +405,13 @@ function goto_collect() {
game.state = "collect"
}
+function goto_compromising_gifts() {
+ if (game.inf[game.cmd.who] === 0)
+ end_card()
+ else
+ game.state = "compromising_gifts"
+}
+
function goto_conscript() {
init_command("Conscript")
game.state = "conscript"
@@ -462,6 +486,29 @@ function end_march_space() {
game.state = "march"
}
+function goto_mi_attack() {
+ init_command("Attack & Plunder")
+ game.state = "mi_attack"
+}
+
+function goto_mongol_invaders(faction) {
+ game.cmd = {}
+ game.current = faction
+ game.cmd.free = 2
+ goto_strategic_assistance()
+}
+
+function goto_strategic_assistance() {
+ if (game.cmd.free > 0) {
+ game.state = "strategic_assistance"
+ }
+ else {
+ game.cmd.free = 1
+ goto_compromising_gifts()
+ }
+
+}
+
function goto_rally() {
init_command("Rally")
game.state = "rally"
@@ -589,6 +636,55 @@ states.lim_command = {
rebel: goto_rebel,
}
+states.advance = {
+ prompt() {
+ view.prompt = "Advance: Select the Advance destination"
+
+ if (has_piece(S_MOUNTAIN_PASSES, MI, TROOPS))
+ gen_action_space(S_PUNJAB)
+
+ if (has_piece(S_PUNJAB, MI, TROOPS))
+ gen_action_space(S_DELHI)
+ },
+ space(s) {
+ game.cmd.where = s
+ game.state = "advance_space"
+ }
+}
+
+states.advance_space = {
+ prompt() {
+ view.prompt = "Advance: Move any number of Mongol Invaders into destination"
+
+ let origin = game.cmd.where === S_DELHI ? S_PUNJAB : S_MOUNTAIN_PASSES
+ for (let p = first_piece[MI][TROOPS]; p <= last_piece[MI][TROOPS]; ++p)
+ if (piece_space(p) === origin)
+ gen_action_piece(p)
+
+ view.actions.end_advance = true
+ },
+ piece(p) {
+ place_piece(p, game.cmd.where)
+ },
+ end_advance() {
+ game.cmd.free -= 1
+ goto_strategic_assistance()
+ }
+}
+
+states.amass = {
+ prompt() {
+ view.prompt = "Amass: Place three invaders into the Mountain Passes"
+
+ gen_action_space(S_MONGOL_INVADERS)
+ },
+ space(s) {
+ amass()
+ game.cmd.free -= 1
+ goto_strategic_assistance()
+ }
+}
+
states.build = {
prompt() {
if (game.current === BK)
@@ -619,15 +715,15 @@ states.build = {
states.cavalry = {
prompt() {
view.prompt = `Gain Cavalry: Take ${game.cmd.n_count} calvary tokens`
-
gen_take_cavalry(game.current)
+
},
token(c) {
game.cmd.n_count -= 1
set_cavalry_faction(c, game.current)
- if (!game.cmd.n_count)
- game.state = "command_decree"
-
+ if (!game.cmd.n_count) {
+ game.state = game.cmd.save
+ }
}
}
@@ -646,6 +742,32 @@ states.collect = {
}
}
+states.compromising_gifts = {
+ prompt() {
+
+ if (game.cmd.free === 1) {
+ view.prompt = "Compromising gifts: Reduce your influence by one to gain two Resources and two Cavalry tokens"
+ gen_action_influence(game.current)
+ } else {
+ view.prompt = "Compromising gifts: End gift exchange"
+ }
+
+ view.actions.end_gifts = true
+ },
+ inf() {
+ game.cmd.free = 0
+ game.inf[game.current] -= 1
+ log_h2(faction_acronyms[game.current] + "Compromising Gifts")
+ logi_resources(game.current, 2)
+ add_resources(game.current, 2)
+ game.cmd.save = "compromising_gifts"
+ goto_cavalry(2)
+ },
+ end_gifts() {
+ end_card()
+ }
+}
+
states.conscript = {
prompt() {
@@ -894,6 +1016,18 @@ states.rebel = {
end_rebel: end_command,
}
+states.strategic_assistance = {
+ prompt() {
+ let n_command = (game.cmd.free === 2) ? "two" : "one"
+ view.prompt = `Strategic Assistance: ${faction_name[game.cmd.who]} must execute ${n_command} Mongol Invaders Commands`
+
+ gen_mi_command()
+ },
+ amass: goto_amass,
+ advance: goto_advance,
+ mi_attack: goto_mi_attack,
+}
+
states.tax = {
prompt() {
view.prompt = `Tax: Collect ${tax_count()} from Controlled Prosperity and Temples`
@@ -910,7 +1044,6 @@ states.tax = {
}
states.trade = {
- // TODO : Add horses logic to trade
prompt() {
view.prompt = `Trade: Collect ${trade_count()} from Provinces with your presence`
@@ -1141,6 +1274,64 @@ function trade_count() {
return count
}
+/* MONGOL INVADERS COMMANDS */
+
+function gen_mi_command() {
+ view.actions.amass = can_amass() ? 1 : 0
+ view.actions.advance = can_advance() ? 1 : 0
+ view.actions.mi_attack = can_mi_attack() ? 1 : 0
+}
+
+function can_advance() {
+ return (has_piece(S_MOUNTAIN_PASSES, MI, TROOPS) || has_piece(S_PUNJAB, MI, TROOPS))
+}
+
+function can_amass() {
+ return has_piece(AVAILABLE, MI, TROOPS)
+}
+
+function can_mi_attack() {
+ let first = first_piece[MI][TROOPS]
+ let last = last_piece[MI][TROOPS]
+ for (let p = first; p <= last; ++p)
+ if (piece_space(p) >= 0)
+ return true
+ return false
+}
+
+function amass() {
+ let n_available = Math.min(count_faction_pieces(AVAILABLE, MI), 3)
+
+ // Add three to mountain pass
+ log_space(S_MOUNTAIN_PASSES, "Amass")
+ push_summary()
+ for (let i = 0; i < n_available; ++i) {
+ let p = find_piece(AVAILABLE, MI, TROOPS)
+ log_summary_place(p)
+ place_piece(p, S_MOUNTAIN_PASSES)
+ }
+ pop_summary()
+
+ amass_trinkle_down(S_MOUNTAIN_PASSES, S_PUNJAB)
+ amass_trinkle_down(S_PUNJAB, S_DELHI)
+
+}
+
+function amass_trinkle_down(s_source, s_dest) {
+ let n = count_faction_pieces(s_source, MI) - 4
+ if (n > 0) {
+ log_space(s_dest, "Amass")
+ push_summary()
+ for (let i = n; i > 0; --i) {
+ let p = find_piece(s_source, MI, TROOPS)
+ log_summary_place(p)
+ place_piece(p, s_dest)
+ }
+ pop_summary()
+ }
+}
+
+
/* TRIBUTARY AND REBELS */
function add_tributary(s) {
@@ -1376,8 +1567,8 @@ function set_cavalry_faction(c, f) {
}
function trade_cavalry_count() {
- if (game.bk_inf === 0) return 1;
- if (game.bk_inf <= 2) return 2;
+ if (game.inf[BK] === 0) return 1;
+ if (game.inf[BK] <= 2) return 2;
return 3;
}
@@ -1407,8 +1598,8 @@ function update_control() {
function update_vp() {
game.vp[DS] = game.prosperity[DS]
- game.vp[BK] = game.prosperity[BK] + count_pieces_on_map(BK, DISC) + game.bk_inf
- game.vp[VE] = game.prosperity[VE] + count_pieces_on_map(VE, DISC) + game.ve_inf
+ game.vp[BK] = game.prosperity[BK] + count_pieces_on_map(BK, DISC) + game.inf[BK]
+ game.vp[VE] = game.prosperity[VE] + count_pieces_on_map(VE, DISC) + game.inf[VE]
}
/* ACTIONS */
@@ -1419,6 +1610,10 @@ function gen_action(action, argument) {
set_add(view.actions[action], argument)
}
+function gen_action_influence(faction) {
+ gen_action("inf", faction)
+}
+
function gen_action_piece(p) {
gen_action("piece", p)
}