From 47833d20bdd7dbfdd3f13e820f595fbd5b5c387b Mon Sep 17 00:00:00 2001 From: Joël Simoneau Date: Sun, 27 Oct 2024 19:04:25 -0400 Subject: Rebel and Control. --- rules.js | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) (limited to 'rules.js') diff --git a/rules.js b/rules.js index f0449c4..f91e303 100644 --- a/rules.js +++ b/rules.js @@ -43,6 +43,7 @@ const first_piece = data.first_piece const last_piece = data.last_piece const first_space = S_ANDHRA const last_space = S_PUNJAB +const last_province = S_TAMILAKAM const faction_name = [ "Delhi Sultanate", "Bahmani Kingdom", "Vijayanagara Empire", "Mongol Invaders" ] @@ -99,6 +100,7 @@ exports.view = function (state, role) { cylinder: game.cylinder, pieces: game.pieces, tributary: game.tributary, + control: game.control, } if (game.result) { @@ -186,6 +188,7 @@ exports.setup = function (seed, scenario, _options) { bk_inf: 0, ve_inf: 0, tributary: 8191, // all 13 provinces + control: [0, 0, 0], rebel: 0, // amir/raja rebel status pieces: Array(104).fill(AVAILABLE), // piece locations cavalry: [0, 0, 0], @@ -415,6 +418,11 @@ function goto_conscript() { game.state = "rally" } +function goto_rebel() { + init_command("Rebel") + game.state = "rebel" +} + /* STATES */ states.eligible = { @@ -467,6 +475,7 @@ states.command_decree = { build: goto_build, conscript: goto_conscript, rally: goto_rally, + rebel: goto_rebel, } states.event_command = { @@ -477,6 +486,7 @@ states.event_command = { }, conscript: goto_conscript, rally: goto_rally, + rebel: goto_rebel, } states.lim_command = { @@ -487,6 +497,7 @@ states.lim_command = { }, conscript: goto_conscript, rally: goto_rally, + rebel: goto_rebel, } states.build = { @@ -600,6 +611,29 @@ states.rally_space = { } } +states.rebel = { + prompt() { + view.prompt = "Rebel: Select a Province where you are in majority." + + if (can_select_cmd_space(1)) { + for (let s = first_space; s <= last_space; ++s) { + if (!is_selected_cmd_space(s) && can_rebel_in_space(s)) + gen_action_space(s) + } + } + + view.actions.end_rebel = prompt_end_cmd(1) + }, + space(s) { + push_undo() + select_cmd_space(s, 1) + remove_tributary(s) + log_space(s, "Rebel") + }, + end_rebel: end_command, + +} + /* COMMANDS */ function init_command(type) { @@ -616,6 +650,7 @@ function gen_any_command() { view.actions.conscript = can_conscript() ? 1 : 0 } else if (game.current === BK || game.current === VE) { view.actions.rally = can_rally() ? 1 : 0 + view.actions.rebel = can_rebel() ? 1 : 0 } } @@ -676,6 +711,21 @@ function rally_count() { return count } +function can_rebel() { + // todo: implement dynasty logic + for (let s = first_space; s <= last_space; ++s) { + if (can_rebel_in_space(s)) + return true + } + return false +} + +function can_rebel_in_space(s) { + if (is_tributary(s) && has_majority(s) === game.current) + return true + return false +} + function prompt_end_cmd(cost) { if (!view.actions.space) { if (game.op.limited && game.op.spaces && game.op.spaces.length > 0) @@ -716,6 +766,7 @@ function can_build_in_space(s) { function add_tributary(s) { game.tributary |= (1 << s) + update_control() } function is_tributary(s) { @@ -724,10 +775,52 @@ function is_tributary(s) { function remove_tributary(s) { game.tributary &= ~(1 << s) + update_control() } /* MISC SPACE + PIECE QUERIES */ +function count_pieces(s, faction, type) { + let first = first_piece[faction][type] + let last = last_piece[faction][type] + let n = 0 + for (let p = first; p <= last; ++p) + if (piece_space(p) === s) + ++n + return n +} + +function count_faction_pieces(s, faction) { + switch (faction) { + case DS: + return count_pieces(s, DS, TROOPS) + count_pieces(s, DS, ELITE) + count_pieces(s, DS, DISC) + case BK: + return count_pieces(s, BK, ELITE) + count_pieces(s, BK, DISC) + case VE: + return count_pieces(s, VE, ELITE) + count_pieces(s, VE, DISC) + case MI: + return count_pieces(s, MI, TROOPS) + } +} + +function has_majority(s) { + let d = count_faction_pieces(s, DS) + let b = count_faction_pieces(s, BK) + let v = count_faction_pieces(s, VE) + let m = count_faction_pieces(s, MI) + + if (d > b + v + m) + return DS + else if (b > d + v + m) + return BK + else if (v > b + d + m) + return VE + else if (m > b + d+ v) + return MI + else + return -1 +} + function has_piece(s, faction, type) { let first = first_piece[faction][type] let last = last_piece[faction][type] @@ -770,6 +863,7 @@ function place_piece(p, s) { p = find_piece(AVAILABLE, piece_faction(p), piece_type(p)) set_piece_space(p, s) + update_control() } function piece_faction(p) { @@ -822,6 +916,16 @@ function add_resources(faction, n) { game.resources[faction] = Math.max(0, Math.min(24, game.resources[faction] + n)) } +function update_control() { + game.control = [0, 0, 0] + for (let s = first_space; s <= last_province; ++s) { + if (is_tributary(s)) continue + + let c = has_majority(s) + if (c <= VE) + game.control[c] |= (1 << s) + } +} /* ACTIONS */ -- cgit v1.2.3