From e8cf1f4cc0b953dadcc06ccfd0ee4e6ce29be2ad Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Mon, 6 Jun 2022 21:42:43 +0200 Subject: Zap semicolons. --- play.js | 832 ++++++++++---------- rules.js | 2624 +++++++++++++++++++++++++++++++------------------------------- 2 files changed, 1728 insertions(+), 1728 deletions(-) diff --git a/play.js b/play.js index 485d318..6720f11 100644 --- a/play.js +++ b/play.js @@ -1,31 +1,31 @@ -"use strict"; +"use strict" // CONSTANTS -const player_names = [ "Gray", "Blue", "Tan", "Red", "Black", "None" ]; -const player_index = Object.fromEntries(Object.entries(player_names).map(([k,v])=>[v,k|0])); - -const Persia = 201; -const Transcaspia = 202; -const Herat = 203; -const Kabul = 204; -const Kandahar = 205; -const Punjab = 206; - -const Persia_Transcaspia = 301; -const Persia_Herat = 302; -const Transcaspia_Herat = 303; -const Transcaspia_Kabul = 304; -const Herat_Kabul = 305; -const Herat_Kandahar = 306; -const Kabul_Kandahar = 307; -const Kabul_Punjab = 308; -const Kandahar_Punjab = 309; - -const Gift2 = 400; -const Gift4 = 401; -const Gift6 = 402; -const Safe_House = 500; +const player_names = [ "Gray", "Blue", "Tan", "Red", "Black", "None" ] +const player_index = Object.fromEntries(Object.entries(player_names).map(([k,v])=>[v,k|0])) + +const Persia = 201 +const Transcaspia = 202 +const Herat = 203 +const Kabul = 204 +const Kandahar = 205 +const Punjab = 206 + +const Persia_Transcaspia = 301 +const Persia_Herat = 302 +const Transcaspia_Herat = 303 +const Transcaspia_Kabul = 304 +const Herat_Kabul = 305 +const Herat_Kandahar = 306 +const Kabul_Kandahar = 307 +const Kabul_Punjab = 308 +const Kandahar_Punjab = 309 + +const Gift2 = 400 +const Gift4 = 401 +const Gift6 = 402 +const Safe_House = 500 const region_index = { "Persia": Persia, @@ -34,7 +34,7 @@ const region_index = { "Kabul": Kabul, "Kandahar": Kandahar, "Punjab": Punjab, -}; +} const space_names = { [Persia]: "Persia", @@ -56,11 +56,11 @@ const space_names = { cards.forEach(card => { if (card) { - card.region = region_index[card.region]; + card.region = region_index[card.region] if (card.name === 'EVENT') - card.name = card.if_discarded + " / " + card.if_purchased; + card.name = card.if_discarded + " / " + card.if_purchased } -}); +}) const event_cards = { new_tactics: 105, @@ -73,7 +73,7 @@ const event_cards = { pashtunwali_values: 115, embarrassment_of_riches: 106, disregard_for_customs: 107, -}; +} const VP_OFFSET = [ [-16, -16], @@ -81,7 +81,7 @@ const VP_OFFSET = [ [0, 0], [-16, 16], [16, 16], -]; +] const VP_TRACK = [ [ 91, 43 ], @@ -108,128 +108,128 @@ const VP_TRACK = [ [ 635, 563 ], [ 545, 563 ], [ 454, 563 ], -]; +] // GAME STATE function player_cylinders(p) { - return 36 + p * 10; + return 36 + p * 10 } function ruler_of_region(r) { - let ruler = -1; + let ruler = -1 - let n_afghan = 0; - let n_british = 0; - let n_russian = 0; + let n_afghan = 0 + let n_british = 0 + let n_russian = 0 for (let i = 0; i < 12; ++i) { if (view.pieces[i] === r) - n_afghan ++; + n_afghan ++ if (view.pieces[i+12] === r) - n_british ++; + n_british ++ if (view.pieces[i+24] === r) - n_russian ++; + n_russian ++ } - let max_ruling = Math.max(n_afghan, n_british, n_russian); + let max_ruling = Math.max(n_afghan, n_british, n_russian) for (let p = 0; p < view.players.length; ++p) { - let n_tribes = 0; - let x = 36 + p * 10; + let n_tribes = 0 + let x = 36 + p * 10 for (let i = x; i < x + 10; ++i) if (view.pieces[i] === r) - n_tribes++; + n_tribes++ - let n_ruling = n_tribes; + let n_ruling = n_tribes if (view.players[p].loyalty === 'Afghan') - n_ruling += n_afghan; + n_ruling += n_afghan if (view.players[p].loyalty === 'British') - n_ruling += n_british; + n_ruling += n_british if (view.players[p].loyalty === 'Russian') - n_ruling += n_russian; + n_ruling += n_russian if (n_ruling === max_ruling) { - ruler = -1; + ruler = -1 } else if (n_ruling > max_ruling) { - max_ruling = n_ruling; + max_ruling = n_ruling if (n_tribes > 0) - ruler = p; + ruler = p else - ruler = -1; + ruler = -1 } } - return ruler; + return ruler } function count_influence_points(p) { - let n = 1 + view.players[p].prizes; - let x = player_cylinders(p); + let n = 1 + view.players[p].prizes + let x = player_cylinders(p) if (!view.events.embarrassment_of_riches) { - let gv = view.players[p].events.koh_i_noor ? 2 : 1; + let gv = view.players[p].events.koh_i_noor ? 2 : 1 for (let i = x; i < x + 10; ++i) { - let s = view.pieces[i]; + let s = view.pieces[i] if (s === Gift2 || s === Gift4 || s === Gift6) - n += gv; + n += gv } } if (!view.players[p].events.rumor) { - let court = view.players[p].court; + let court = view.players[p].court for (let i = 0; i < court.length; ++i) if (cards[court[i]].patriot) - ++n; + ++n } - return n; + return n } function count_cylinders_in_play(p) { - let n = 0; - let x = player_cylinders(p); + let n = 0 + let x = player_cylinders(p) for (let i = x; i < x + 10; ++i) if (view.pieces[i] > 0) - ++n; - return n; + ++n + return n } function is_piece_army(i) { - return (view.pieces[i] >= 201 && view.pieces[i] <= 206); + return (view.pieces[i] >= 201 && view.pieces[i] <= 206) } function is_piece_road(i) { - return (view.pieces[i] >= 301 && view.pieces[i] <= 309); + return (view.pieces[i] >= 301 && view.pieces[i] <= 309) } function is_card_action(action, card) { if (view.actions && view.actions[action] && view.actions[action].includes(card)) - return true; - return false; + return true + return false } function is_place_gift_action(i) { if (view.actions && view.actions.place_gift && view.actions.place_gift.includes(i)) - return true; - return false; + return true + return false } function is_suit_action(suit) { if (view.actions && view.actions.suit && view.actions.suit.includes(suit)) - return true; - return false; + return true + return false } function is_piece_action(i) { if (view.actions && view.actions.piece && view.actions.piece.includes(i)) - return true; - return false; + return true + return false } function is_space_action(i) { if (view.actions && view.actions.space && view.actions.space.includes(i)) - return true; - return false; + return true + return false } // UI ELEMENTS @@ -247,67 +247,67 @@ let ui = { } function scroll_to_map() { - ui.board.scrollIntoView({behavior:'smooth'}); + ui.board.scrollIntoView({behavior:'smooth'}) } function scroll_to_market() { - ui.market.scrollIntoView({behavior:'smooth'}); + ui.market.scrollIntoView({behavior:'smooth'}) } function scroll_to_player(p) { - ui.player[p].area.scrollIntoView({behavior:'smooth'}); + ui.player[p].area.scrollIntoView({behavior:'smooth'}) } -let open_toggle = true; +let open_toggle = true function toggle_open_hands() { - open_toggle = !open_toggle; + open_toggle = !open_toggle for (let p = 0; p < view.players.length; ++p) if (p !== player_index[player]) - ui.player[p].hand.classList.toggle("hide", open_toggle); + ui.player[p].hand.classList.toggle("hide", open_toggle) } function on_blur() { - ui.status.textContent = ""; - ui.tooltip.classList = "hide"; + ui.status.textContent = "" + ui.tooltip.classList = "hide" } function on_focus_card_tip(c) { - ui.tooltip.classList = "card card_" + c; + ui.tooltip.classList = "card card_" + c } function on_click_card_tip(c) { - ui.cards[c].scrollIntoView({behavior:'smooth'}); + ui.cards[c].scrollIntoView({behavior:'smooth'}) } function on_focus_card(evt) { - let c = evt.target.card; + let c = evt.target.card if (!evt.target.classList.contains("card_back")) { - ui.status.textContent = `${evt.target.card} - ${cards[c].name}`; - ui.tooltip.classList = "focus card card_" + c; + ui.status.textContent = `${evt.target.card} - ${cards[c].name}` + ui.tooltip.classList = "focus card card_" + c } } function on_focus_space(evt) { - ui.status.textContent = space_names[evt.target.space]; + ui.status.textContent = space_names[evt.target.space] } function on_click_space(evt) { - send_action('space', evt.target.space); - evt.stopPropagation(); + send_action('space', evt.target.space) + evt.stopPropagation() } function on_click_block(evt) { - send_action('piece', evt.target.piece); - evt.stopPropagation(); + send_action('piece', evt.target.piece) + evt.stopPropagation() } function on_click_cylinder(evt) { - send_action('piece', evt.target.piece); - evt.stopPropagation(); + send_action('piece', evt.target.piece) + evt.stopPropagation() } function toggle_hand(p) { - ui.player[p].hand.classList.toggle("hide"); + ui.player[p].hand.classList.toggle("hide") } // CARD MENU @@ -315,47 +315,47 @@ function toggle_hand(p) { const card_action_menu = [ 'play_left', 'play_right', -]; +] -let current_popup_card = 0; +let current_popup_card = 0 function show_popup_menu(evt, list) { - document.querySelectorAll("#popup div").forEach(e => e.classList.remove('enabled')); + document.querySelectorAll("#popup div").forEach(e => e.classList.remove('enabled')) for (let item of list) { - let e = document.getElementById("menu_" + item); - e.classList.add('enabled'); + let e = document.getElementById("menu_" + item) + e.classList.add('enabled') } - let popup = document.getElementById("popup"); - popup.style.display = 'block'; - popup.style.left = (evt.clientX-50) + "px"; - popup.style.top = (evt.clientY-12) + "px"; - ui.cards[current_popup_card].classList.add("selected"); - ui.popup_label.textContent = cards[current_popup_card].name; + let popup = document.getElementById("popup") + popup.style.display = 'block' + popup.style.left = (evt.clientX-50) + "px" + popup.style.top = (evt.clientY-12) + "px" + ui.cards[current_popup_card].classList.add("selected") + ui.popup_label.textContent = cards[current_popup_card].name } function hide_popup_menu() { - let popup = document.getElementById("popup"); - popup.style.display = 'none'; + let popup = document.getElementById("popup") + popup.style.display = 'none' if (current_popup_card) { - ui.cards[current_popup_card].classList.remove("selected"); - current_popup_card = 0; + ui.cards[current_popup_card].classList.remove("selected") + current_popup_card = 0 } } function popup_action(action) { - send_action(action, current_popup_card); - hide_popup_menu(); + send_action(action, current_popup_card) + hide_popup_menu() } function on_click_card(evt) { - let c = evt.target.card; + let c = evt.target.card if (is_card_action('card', c)) { - send_action('card', c); + send_action('card', c) } else { - let menu = card_action_menu.filter(a => is_card_action(a, c)); + let menu = card_action_menu.filter(a => is_card_action(a, c)) if (menu.length > 0) { - current_popup_card = c; - show_popup_menu(evt, menu); + current_popup_card = c + show_popup_menu(evt, menu) } } } @@ -363,141 +363,141 @@ function on_click_card(evt) { // LOG function sub_card_name(match, p1) { - let c = p1 | 0; - let name = cards[c].name; - return `${name}`; + let c = p1 | 0 + let name = cards[c].name + return `${name}` } function on_log(text) { - let p = document.createElement("div"); + let p = document.createElement("div") if (text.match(/^>/)) { - text = text.substring(1); - p.className = 'i'; + text = text.substring(1) + p.className = 'i' } - text = text.replace(/&/g, "&"); - text = text.replace(//g, ">"); - text = text.replace(/#(\d+)/g, sub_card_name); + text = text.replace(/&/g, "&") + text = text.replace(//g, ">") + text = text.replace(/#(\d+)/g, sub_card_name) if (text.match(/^.turn/)) { - text = text.substring(6); - p.className = 'turn ' + text; + text = text.substring(6) + p.className = 'turn ' + text } - let m; + let m if ((m = text.match(/^.dc.(\w+) (.*)/))) { - text = m[2]; - p.className = 'dc ' + m[1]; + text = m[2] + p.className = 'dc ' + m[1] } - p.innerHTML = text; - return p; + p.innerHTML = text + return p } // LAYOUT function layout_block_pool() { function place_block_pool(i, x, y) { - ui.pieces[i].style = `top:${27+y*48}px;left:${1070+26+x*(26+35)}px`; + ui.pieces[i].style = `top:${27+y*48}px;left:${1070+26+x*(26+35)}px` } for (let k = 0, i = 0; i < 12; ++i) { if (view.pieces[i] === 0) { - place_block_pool(i, 0, k); - ++k; + place_block_pool(i, 0, k) + ++k } } for (let k = 0, i = 12; i < 24; ++i) { if (view.pieces[i] === 0) { - place_block_pool(i, 1, k); - ++k; + place_block_pool(i, 1, k) + ++k } } for (let k = 0, i = 24; i < 36; ++i) { if (view.pieces[i] === 0) { - place_block_pool(i, 2, k); - ++k; + place_block_pool(i, 2, k) + ++k } } } function layout_armies(list, xc, yc, maxcol) { function place_army(y, x, i) { - ui.pieces[i].style = `top:${yc+y*16+x*1}px;left:${xc+x*26-y*16}px`; + ui.pieces[i].style = `top:${yc+y*16+x*1}px;left:${xc+x*26-y*16}px` } - let ncol = Math.min(maxcol, list.length); - let nrow = Math.ceil(list.length / ncol); - let i = 0; + let ncol = Math.min(maxcol, list.length) + let nrow = Math.ceil(list.length / ncol) + let i = 0 for (let row = 0; row < nrow; ++row) for (let col = 0; col < ncol && i < list.length; ++col) - place_army(row, col - (ncol/2) - ((nrow-1)/4), list[i++]); + place_army(row, col - (ncol/2) - ((nrow-1)/4), list[i++]) } function layout_tribes_radial(list, xc, yc, maxcol) { function place_tribe(x, y, i) { - ui.pieces[i].style = `top:${Math.round(y)}px;left:${Math.round(x)}px`; + ui.pieces[i].style = `top:${Math.round(y)}px;left:${Math.round(x)}px` } - let angle = 2 * Math.PI / Math.max(list.length, 7); - let phase = (list.length <= 3) ? Math.PI * 2 / 7 : (list.length - 1) * angle / 2; + let angle = 2 * Math.PI / Math.max(list.length, 7) + let phase = (list.length <= 3) ? Math.PI * 2 / 7 : (list.length - 1) * angle / 2 for (let i = 0; i < list.length; ++i) { - let x = xc + Math.sin(i * angle - phase) * 46 - 14; - let y = yc - Math.cos(i * angle - phase) * 44 - 14; - place_tribe(x, y, list[i]); + let x = xc + Math.sin(i * angle - phase) * 46 - 14 + let y = yc - Math.cos(i * angle - phase) * 44 - 14 + place_tribe(x, y, list[i]) } } function layout_region_armies(r, xc, yc, maxcol) { - let list = []; + let list = [] for (let i = 0; i < 36; ++i) if (view.pieces[i] === r) - list.push(i); - layout_armies(list, xc - 4, yc, maxcol); + list.push(i) + layout_armies(list, xc - 4, yc, maxcol) } function layout_region_tribes(r, xc, yc, maxcol) { - let list = []; + let list = [] for (let i = 36; i < view.pieces.length; ++i) if (view.pieces[i] === r) - list.push(i); + list.push(i) if (list.length > 0) - layout_tribes_radial(list, xc, yc, maxcol); + layout_tribes_radial(list, xc, yc, maxcol) } function layout_border(r, xc, yc, line) { - xc -= 24; - yc -= 12; + xc -= 24 + yc -= 12 function place_piece_border(i, k) { - let x, y; + let x, y switch (line) { - case 0: x = k * 18; y = k * 7; break; - case 1: x = k * 4; y = k * 16; break; - case 2: x = k * -4; y = k * 16; break; - case 3: x = k * -12; y = k * 14; break; + case 0: x = k * 18; y = k * 7; break + case 1: x = k * 4; y = k * 16; break + case 2: x = k * -4; y = k * 16; break + case 3: x = k * -12; y = k * 14; break } - ui.pieces[i].style = `top:${yc+y}px;left:${xc+x}px`; + ui.pieces[i].style = `top:${yc+y}px;left:${xc+x}px` } - let n = 0; + let n = 0 for (let i = 0; i < view.pieces.length; ++i) { if (view.pieces[i] === r) - ++n; + ++n } for (let k = (-(n-1)/2), i = 0; i < view.pieces.length; ++i) { if (view.pieces[i] === r) { - place_piece_border(i, k); - ++k; + place_piece_border(i, k) + ++k } } } // UPDATE UI -let once = true; +let once = true function on_update() { if (once) { - build_ui(); - once = false; + build_ui() + once = false } function update_event_cards(node, events) { for (let evt in events) - node.appendChild(ui.cards[event_cards[evt]]); + node.appendChild(ui.cards[event_cards[evt]]) } let ruler = [ @@ -507,220 +507,220 @@ function on_update() { ruler_of_region(Kabul), ruler_of_region(Kandahar), ruler_of_region(Punjab) - ]; + ] - ui.prompt.innerHTML = view.prompt.replace(/#(\d+)/g, sub_card_name); + ui.prompt.innerHTML = view.prompt.replace(/#(\d+)/g, sub_card_name) - ui.deck_info.textContent = `${view.cards[0]}x Draw Deck, ${view.cards[1]}x Dominance Check`; + ui.deck_info.textContent = `${view.cards[0]}x Draw Deck, ${view.cards[1]}x Dominance Check` - action_button("loyalty_afghan", "Afghan"); - action_button("loyalty_british", "British"); - action_button("loyalty_russian", "Russian"); + action_button("loyalty_afghan", "Afghan") + action_button("loyalty_british", "British") + action_button("loyalty_russian", "Russian") - action_button("courtly_manners", "Courtly Manners"); - action_button("beg", "Beg"); - action_button("pay", "Pay"); - action_button("waive", "Waive"); - action_button("accept", "Accept"); + action_button("courtly_manners", "Courtly Manners") + action_button("beg", "Beg") + action_button("pay", "Pay") + action_button("waive", "Waive") + action_button("accept", "Accept") for (let i = 0; i < 10; ++i) - action_button("offer_" + i, i); + action_button("offer_" + i, i) - action_button("refuse", "Refuse"); + action_button("refuse", "Refuse") - action_button("player_0", "Gray"); - action_button("player_1", "Blue"); - action_button("player_2", "Tan"); - action_button("player_3", "Red"); - action_button("player_4", "Black"); + action_button("player_0", "Gray") + action_button("player_1", "Blue") + action_button("player_2", "Tan") + action_button("player_3", "Red") + action_button("player_4", "Black") - action_button("pass", "Pass"); - action_button("next", "Next"); - action_button("end_game", "End game"); + action_button("pass", "Pass") + action_button("next", "Next") + action_button("end_game", "End game") confirm_action_button("end_turn_pass", "End turn", - "Are you sure you want to END TURN while you still have actions?"); - action_button("end_turn", "End turn"); - action_button("undo", "Undo"); + "Are you sure you want to END TURN while you still have actions?") + action_button("end_turn", "End turn") + action_button("undo", "Undo") - ui.favored1.className = view.favored; - ui.favored2.className = view.favored + " icon"; + ui.favored1.className = view.favored + ui.favored2.className = view.favored + " icon" for (let row = 0; row < 2; ++row) { for (let col = 0; col < 6; ++col) { - let ce = ui.cards[view.market_cards[row][col]]; + let ce = ui.cards[view.market_cards[row][col]] if (ce) - ce.classList.remove("card_back"); - let me = ui.market_card[row][col]; + ce.classList.remove("card_back") + let me = ui.market_card[row][col] if (me.firstChild !== ce) { if (me.firstChild) - me.removeChild(me.firstChild); + me.removeChild(me.firstChild) if (ce) - me.appendChild(ce); + me.appendChild(ce) } - let coins = view.market_coins[row][col]; + let coins = view.market_coins[row][col] if (coins > 0) { - ui.market_coin[row][col].textContent = coins; - ui.market_coin[row][col].className = "coin"; + ui.market_coin[row][col].textContent = coins + ui.market_coin[row][col].className = "coin" } else { - ui.market_coin[row][col].textContent = ""; - ui.market_coin[row][col].className = "coin hide"; + ui.market_coin[row][col].textContent = "" + ui.market_coin[row][col].className = "coin hide" } } } for (let i = 1; i < cards.length; ++i) { - ui.cards[i].classList.toggle('action', is_card_action('card', i)); + ui.cards[i].classList.toggle('action', is_card_action('card', i)) } for (let i = 201; i <= 206; ++i) { - ui.spaces[i].classList.toggle('action', is_space_action(i)); - ui.spaces[i].classList.toggle('selected', view.where === i); + ui.spaces[i].classList.toggle('action', is_space_action(i)) + ui.spaces[i].classList.toggle('selected', view.where === i) } for (let i = 301; i <= 309; ++i) - ui.spaces[i].classList.toggle('action', is_space_action(i)); + ui.spaces[i].classList.toggle('action', is_space_action(i)) for (let i = 0; i < 36; ++i) { - ui.pieces[i].classList.toggle('action', is_piece_action(i)); - ui.pieces[i].classList.toggle('selected', view.selected === i); - ui.pieces[i].classList.toggle('road', is_piece_road(i)); - ui.pieces[i].classList.toggle('army', is_piece_army(i)); + ui.pieces[i].classList.toggle('action', is_piece_action(i)) + ui.pieces[i].classList.toggle('selected', view.selected === i) + ui.pieces[i].classList.toggle('road', is_piece_road(i)) + ui.pieces[i].classList.toggle('army', is_piece_army(i)) } for (let p = 0; p < view.players.length; ++p) { - let pp = view.players[p]; - let me = ui.player[p].court; + let pp = view.players[p] + let me = ui.player[p].court while (me.firstChild) - me.removeChild(me.firstChild); - me.appendChild(ui.player[p].pool); - update_event_cards(me, view.players[p].events); + me.removeChild(me.firstChild) + me.appendChild(ui.player[p].pool) + update_event_cards(me, view.players[p].events) for (let i = 0; i < pp.court.length; ++i) { - let ce = ui.cards[pp.court[i]]; - me.appendChild(ce); - ce.classList.remove("card_back"); + let ce = ui.cards[pp.court[i]] + me.appendChild(ce) + ce.classList.remove("card_back") } if (p === player_index[player]) { - ui.player[p].gift_2.classList.toggle('action', is_place_gift_action(2)); - ui.player[p].gift_4.classList.toggle('action', is_place_gift_action(4)); - ui.player[p].gift_6.classList.toggle('action', is_place_gift_action(6)); + ui.player[p].gift_2.classList.toggle('action', is_place_gift_action(2)) + ui.player[p].gift_4.classList.toggle('action', is_place_gift_action(4)) + ui.player[p].gift_6.classList.toggle('action', is_place_gift_action(6)) } - me = ui.global_events; + me = ui.global_events while (me.firstChild) - me.removeChild(me.firstChild); - update_event_cards(me, view.events); + me.removeChild(me.firstChild) + update_event_cards(me, view.events) - me = ui.player[p].hand; + me = ui.player[p].hand while (me.firstChild) - me.removeChild(me.firstChild); + me.removeChild(me.firstChild) if (p === player_index[player]) - me.classList.remove("hide"); + me.classList.remove("hide") for (let i = 0; i < pp.hand.length; ++i) { - let ce = ui.cards[pp.hand[i]]; + let ce = ui.cards[pp.hand[i]] if (p !== player_index[player] && !view.open) - ce.classList.add("card_back"); + ce.classList.add("card_back") else - ce.classList.remove("card_back"); - me.appendChild(ce); + ce.classList.remove("card_back") + me.appendChild(ce) } if (view.players[p].coins === 0) { - ui.player[p].coin.classList.add("hide"); + ui.player[p].coin.classList.add("hide") } else { - ui.player[p].coin.classList.remove("hide"); - ui.player[p].coin.textContent = view.players[p].coins; + ui.player[p].coin.classList.remove("hide") + ui.player[p].coin.textContent = view.players[p].coins } if (view.players[p].prizes === 0) { - ui.player[p].prize.classList.add("hide"); + ui.player[p].prize.classList.add("hide") } else { - ui.player[p].prize.classList.remove("hide"); + ui.player[p].prize.classList.remove("hide") if (view.players[p].prizes === 1) - ui.player[p].prize.textContent = view.players[p].prizes + " prize"; + ui.player[p].prize.textContent = view.players[p].prizes + " prize" else - ui.player[p].prize.textContent = view.players[p].prizes + " prizes"; + ui.player[p].prize.textContent = view.players[p].prizes + " prizes" } ui.player[p].role.classList.toggle("active", p === player_index[view.active]) - ui.player[p].dial.className = "player_dial " + view.players[p].loyalty + " p" + p; + ui.player[p].dial.className = "player_dial " + view.players[p].loyalty + " p" + p - ui.player[p].role_loy_icon.className = "role_loyalty_icon " + view.players[p].loyalty; - ui.player[p].role_loy_text.textContent = count_influence_points(p); - ui.player[p].role_cyl_text.textContent = count_cylinders_in_play(p); - ui.player[p].role_rup_text.textContent = view.players[p].coins; + ui.player[p].role_loy_icon.className = "role_loyalty_icon " + view.players[p].loyalty + ui.player[p].role_loy_text.textContent = count_influence_points(p) + ui.player[p].role_cyl_text.textContent = count_cylinders_in_play(p) + ui.player[p].role_rup_text.textContent = view.players[p].coins - ui.player[p].hand_size.textContent = view.players[p].hand.length; + ui.player[p].hand_size.textContent = view.players[p].hand.length - ui.player[p].score.style.left = (VP_OFFSET[p][0] + VP_TRACK[view.players[p].vp][0]) + "px"; - ui.player[p].score.style.top = (VP_OFFSET[p][1] + VP_TRACK[view.players[p].vp][1]) + "px"; + ui.player[p].score.style.left = (VP_OFFSET[p][0] + VP_TRACK[view.players[p].vp][0]) + "px" + ui.player[p].score.style.top = (VP_OFFSET[p][1] + VP_TRACK[view.players[p].vp][1]) + "px" for (let i = 0; i < 10; ++i) { - let x = 36 + p * 10 + i; - let s = view.pieces[x]; + let x = 36 + p * 10 + i + let s = view.pieces[x] if (s === 0 || s === Safe_House) - ui.player[p].pool.appendChild(ui.pieces[x]); + ui.player[p].pool.appendChild(ui.pieces[x]) else if (s === Gift2) - ui.player[p].gift_2.appendChild(ui.pieces[x]); + ui.player[p].gift_2.appendChild(ui.pieces[x]) else if (s === Gift4) - ui.player[p].gift_4.appendChild(ui.pieces[x]); + ui.player[p].gift_4.appendChild(ui.pieces[x]) else if (s === Gift6) - ui.player[p].gift_6.appendChild(ui.pieces[x]); + ui.player[p].gift_6.appendChild(ui.pieces[x]) else if (s <= 100) - ui.spyrows[s].appendChild(ui.pieces[x]); + ui.spyrows[s].appendChild(ui.pieces[x]) else { if (ui.pieces[x].parentElement !== ui.board) - ui.board.appendChild(ui.pieces[x]); + ui.board.appendChild(ui.pieces[x]) } - ui.pieces[x].classList.toggle('action', is_piece_action(x)); - ui.pieces[x].classList.toggle('selected', view.selected === x); - ui.pieces[x].style = ""; + ui.pieces[x].classList.toggle('action', is_piece_action(x)) + ui.pieces[x].classList.toggle('selected', view.selected === x) + ui.pieces[x].style = "" } } for (let i = 0; i < 6; ++i) if (ruler[i] === -1) - ui.rule[i].classList = `rule ${space_names[i+Persia]} hide`; + ui.rule[i].classList = `rule ${space_names[i+Persia]} hide` else - ui.rule[i].classList = `rule ${space_names[i+Persia]} ${player_names[ruler[i]]}`; - - ui.suit_political.classList.toggle('action', is_suit_action('Political')); - ui.suit_intelligence.classList.toggle('action', is_suit_action('Intelligence')); - ui.suit_economic.classList.toggle('action', is_suit_action('Economic')); - ui.suit_military.classList.toggle('action', is_suit_action('Military')); - - layout_block_pool(); - - layout_region_armies(Persia, 204, 466, 5); - layout_region_armies(Transcaspia, 252, 227, 6); - layout_region_armies(Herat, 454, 458, 6); - layout_region_armies(Kabul, 671, 238, 8); - layout_region_armies(Kandahar, 730, 477, 5); - layout_region_armies(Punjab, 928+10, 381, 4); - - layout_region_tribes(Persia, 204, 426, 5); - layout_region_tribes(Transcaspia, 252, 152+5, 10); - layout_region_tribes(Herat, 454, 383, 6); - layout_region_tribes(Kabul, 671, 163, 12); - layout_region_tribes(Kandahar, 730, 437, 6); - layout_region_tribes(Punjab, 928, 306, 3); - - layout_border(Persia_Transcaspia, 188, 320, 0); - layout_border(Persia_Herat, 313, 441, 1); - layout_border(Transcaspia_Herat, 371, 297, 3); - layout_border(Transcaspia_Kabul, 477, 164, 1); - layout_border(Herat_Kabul, 527, 297, 0); - layout_border(Herat_Kandahar, 598, 441, 2); - layout_border(Kabul_Kandahar, 699, 338, 0); - layout_border(Kabul_Punjab, 859, 211, 2); - layout_border(Kandahar_Punjab, 836, 438, 1); + ui.rule[i].classList = `rule ${space_names[i+Persia]} ${player_names[ruler[i]]}` + + ui.suit_political.classList.toggle('action', is_suit_action('Political')) + ui.suit_intelligence.classList.toggle('action', is_suit_action('Intelligence')) + ui.suit_economic.classList.toggle('action', is_suit_action('Economic')) + ui.suit_military.classList.toggle('action', is_suit_action('Military')) + + layout_block_pool() + + layout_region_armies(Persia, 204, 466, 5) + layout_region_armies(Transcaspia, 252, 227, 6) + layout_region_armies(Herat, 454, 458, 6) + layout_region_armies(Kabul, 671, 238, 8) + layout_region_armies(Kandahar, 730, 477, 5) + layout_region_armies(Punjab, 928+10, 381, 4) + + layout_region_tribes(Persia, 204, 426, 5) + layout_region_tribes(Transcaspia, 252, 152+5, 10) + layout_region_tribes(Herat, 454, 383, 6) + layout_region_tribes(Kabul, 671, 163, 12) + layout_region_tribes(Kandahar, 730, 437, 6) + layout_region_tribes(Punjab, 928, 306, 3) + + layout_border(Persia_Transcaspia, 188, 320, 0) + layout_border(Persia_Herat, 313, 441, 1) + layout_border(Transcaspia_Herat, 371, 297, 3) + layout_border(Transcaspia_Kabul, 477, 164, 1) + layout_border(Herat_Kabul, 527, 297, 0) + layout_border(Herat_Kandahar, 598, 441, 2) + layout_border(Kabul_Kandahar, 699, 338, 0) + layout_border(Kabul_Punjab, 859, 211, 2) + layout_border(Kandahar_Punjab, 836, 438, 1) for (let action in ui.card_action_index) { for (let i = 0; i < ui.card_action_index[action].length; ++i) { - let c = ui.card_action_index[action][i]; - let e = ui.card_action_element[action][i]; - e.classList.toggle("action", is_card_action(action, c)); + let c = ui.card_action_index[action][i] + let e = ui.card_action_element[action][i] + e.classList.toggle("action", is_card_action(action, c)) } } } @@ -728,7 +728,7 @@ function on_update() { // BUILD UI function build_ui() { - let passive_cards = [1,3,5,15,17,21,24,41,42,43,51,54,56,66,68,70,72,78,83,91,97,99]; + let passive_cards = [1,3,5,15,17,21,24,41,42,43,51,54,56,66,68,70,72,78,83,91,97,99] function build_player_ui(p) { return { @@ -753,77 +753,77 @@ function build_ui() { } function build_card_action(card, action, i, x) { - let e = document.createElement("div"); - e.className = `card_action ${action} n${x}`; - e.addEventListener("click", () => send_action(action, i)); - ui.card_action_index[action].push(i); - ui.card_action_element[action].push(e); - card.appendChild(e); + let e = document.createElement("div") + e.className = `card_action ${action} n${x}` + e.addEventListener("click", () => send_action(action, i)) + ui.card_action_index[action].push(i) + ui.card_action_element[action].push(e) + card.appendChild(e) } function build_space(i, n) { - ui.spaces[i] = document.getElementById("svgmap").getElementById(n); - ui.spaces[i].space = i; - ui.spaces[i].addEventListener("click", on_click_space); - ui.spaces[i].addEventListener("mouseenter", on_focus_space); - ui.spaces[i].addEventListener("mouseleave", on_blur); + ui.spaces[i] = document.getElementById("svgmap").getElementById(n) + ui.spaces[i].space = i + ui.spaces[i].addEventListener("click", on_click_space) + ui.spaces[i].addEventListener("mouseenter", on_focus_space) + ui.spaces[i].addEventListener("mouseleave", on_blur) } for (let c = 1; c < cards.length; ++c) { - let e = document.createElement("div"); - e.card = c; + let e = document.createElement("div") + e.card = c if (c <= 100) { - let info = cards[c]; - e.className = "card card_" + c + " " + info.suit; - let n = 0; - if (info.gift) ++n, build_card_action(e, 'gift', c, info.gift); - if (info.move) ++n, build_card_action(e, 'move', c, info.move); - if (info.betray) ++n, build_card_action(e, 'betray', c, info.betray); - if (info.battle) ++n, build_card_action(e, 'battle', c, info.battle); - if (info.build) ++n, build_card_action(e, 'build', c, info.build); - if (info.tax) ++n, build_card_action(e, 'tax', c, info.tax); + let info = cards[c] + e.className = "card card_" + c + " " + info.suit + let n = 0 + if (info.gift) ++n, build_card_action(e, 'gift', c, info.gift) + if (info.move) ++n, build_card_action(e, 'move', c, info.move) + if (info.betray) ++n, build_card_action(e, 'betray', c, info.betray) + if (info.battle) ++n, build_card_action(e, 'battle', c, info.battle) + if (info.build) ++n, build_card_action(e, 'build', c, info.build) + if (info.tax) ++n, build_card_action(e, 'tax', c, info.tax) if (passive_cards.includes(c)) - e.classList.add("passive"); + e.classList.add("passive") if (n === 3) - e.classList.add("three"); + e.classList.add("three") } else { - e.className = "event card card_" + c; + e.className = "event card card_" + c } - e.addEventListener("click", on_click_card); - e.addEventListener("mouseenter", on_focus_card); - e.addEventListener("mouseleave", on_blur); - ui.cards[c] = e; - let ee = document.createElement("div"); - ee.className = "spyrow"; - e.appendChild(ee); - ui.spyrows[c] = ee; + e.addEventListener("click", on_click_card) + e.addEventListener("mouseenter", on_focus_card) + e.addEventListener("mouseleave", on_blur) + ui.cards[c] = e + let ee = document.createElement("div") + ee.className = "spyrow" + e.appendChild(ee) + ui.spyrows[c] = ee } for (let row = 0; row < 2; ++row) { for (let col = 0; col < 6; ++col) { - ui.market_card[row][col] = document.getElementById("market_card_" + row + "_" + col); - ui.market_coin[row][col] = document.getElementById("market_coin_" + row + "_" + col); + ui.market_card[row][col] = document.getElementById("market_card_" + row + "_" + col) + ui.market_coin[row][col] = document.getElementById("market_coin_" + row + "_" + col) } } for (let p = 0; p < 5; ++p) { - ui.player[p] = build_player_ui(p); + ui.player[p] = build_player_ui(p) ui.player[p].hand_size.addEventListener("click", - () => toggle_hand(p)); + () => toggle_hand(p)) for (let i = 0; i < 10; ++i) { - let x = 36 + p * 10 + i; - ui.pieces[x] = document.createElement("div"); - ui.pieces[x].piece = x; - ui.pieces[x].className = "cylinder p" + p; - ui.pieces[x].addEventListener("click", on_click_cylinder); - ui.player[p].pool.appendChild(ui.pieces[x]); + let x = 36 + p * 10 + i + ui.pieces[x] = document.createElement("div") + ui.pieces[x].piece = x + ui.pieces[x].className = "cylinder p" + p + ui.pieces[x].addEventListener("click", on_click_cylinder) + ui.player[p].pool.appendChild(ui.pieces[x]) } - ui.player[p].gift_2.addEventListener("click", () => send_action('place_gift', 2)); - ui.player[p].gift_4.addEventListener("click", () => send_action('place_gift', 4)); - ui.player[p].gift_6.addEventListener("click", () => send_action('place_gift', 6)); + ui.player[p].gift_2.addEventListener("click", () => send_action('place_gift', 2)) + ui.player[p].gift_4.addEventListener("click", () => send_action('place_gift', 4)) + ui.player[p].gift_6.addEventListener("click", () => send_action('place_gift', 6)) } ui.rule = [ @@ -833,85 +833,85 @@ function build_ui() { document.querySelector(`#board .rule.Kabul`), document.querySelector(`#board .rule.Kandahar`), document.querySelector(`#board .rule.Punjab`), - ]; - - ui.prompt = document.getElementById("prompt"); - ui.deck_info = document.getElementById("deck_info"); - ui.board = document.getElementById("board"); - ui.market = document.getElementById("market"); - ui.status = document.getElementById("status"); - ui.tooltip = document.getElementById("tooltip"); - ui.favored1 = document.getElementById("favored_suit_marker"); - ui.favored2 = document.getElementById("favored_suit_banner"); - ui.popup_label = document.getElementById("popup_label"); - ui.global_events = document.getElementById("global_events"); - - ui.suit_political = document.getElementById("suit_political"); - ui.suit_intelligence = document.getElementById("suit_intelligence"); - ui.suit_economic = document.getElementById("suit_economic"); - ui.suit_military = document.getElementById("suit_military"); - - ui.suit_political.addEventListener("click", () => send_action('suit', 'Political')); - ui.suit_intelligence.addEventListener("click", () => send_action('suit', 'Intelligence')); - ui.suit_economic.addEventListener("click", () => send_action('suit', 'Economic')); - ui.suit_military.addEventListener("click", () => send_action('suit', 'Military')); - - build_space(Transcaspia, "Transcaspia"); - build_space(Kabul, "Kabul"); - build_space(Punjab, "Punjab"); - build_space(Persia, "Persia"); - build_space(Herat, "Herat"); - build_space(Kandahar, "Kandahar"); - build_space(Persia_Transcaspia, "Persia/Transcaspia"); - build_space(Persia_Herat, "Persia/Herat"); - build_space(Transcaspia_Herat, "Transcaspia/Herat"); - build_space(Transcaspia_Kabul, "Transcaspia/Kabul"); - build_space(Herat_Kabul, "Herat/Kabul"); - build_space(Herat_Kandahar, "Herat/Kandahar"); - build_space(Kabul_Kandahar, "Kabul/Kandahar"); - build_space(Kabul_Punjab, "Kabul/Punjab"); - build_space(Kandahar_Punjab, "Kandahar/Punjab"); + ] + + ui.prompt = document.getElementById("prompt") + ui.deck_info = document.getElementById("deck_info") + ui.board = document.getElementById("board") + ui.market = document.getElementById("market") + ui.status = document.getElementById("status") + ui.tooltip = document.getElementById("tooltip") + ui.favored1 = document.getElementById("favored_suit_marker") + ui.favored2 = document.getElementById("favored_suit_banner") + ui.popup_label = document.getElementById("popup_label") + ui.global_events = document.getElementById("global_events") + + ui.suit_political = document.getElementById("suit_political") + ui.suit_intelligence = document.getElementById("suit_intelligence") + ui.suit_economic = document.getElementById("suit_economic") + ui.suit_military = document.getElementById("suit_military") + + ui.suit_political.addEventListener("click", () => send_action('suit', 'Political')) + ui.suit_intelligence.addEventListener("click", () => send_action('suit', 'Intelligence')) + ui.suit_economic.addEventListener("click", () => send_action('suit', 'Economic')) + ui.suit_military.addEventListener("click", () => send_action('suit', 'Military')) + + build_space(Transcaspia, "Transcaspia") + build_space(Kabul, "Kabul") + build_space(Punjab, "Punjab") + build_space(Persia, "Persia") + build_space(Herat, "Herat") + build_space(Kandahar, "Kandahar") + build_space(Persia_Transcaspia, "Persia/Transcaspia") + build_space(Persia_Herat, "Persia/Herat") + build_space(Transcaspia_Herat, "Transcaspia/Herat") + build_space(Transcaspia_Kabul, "Transcaspia/Kabul") + build_space(Herat_Kabul, "Herat/Kabul") + build_space(Herat_Kandahar, "Herat/Kandahar") + build_space(Kabul_Kandahar, "Kabul/Kandahar") + build_space(Kabul_Punjab, "Kabul/Punjab") + build_space(Kandahar_Punjab, "Kandahar/Punjab") function make_block(p, faction) { - let div = document.createElement("div"); - div.className = faction + " block"; - div.piece = p; - div.addEventListener("click", on_click_block); - ui.board.appendChild(div); - return div; + let div = document.createElement("div") + div.className = faction + " block" + div.piece = p + div.addEventListener("click", on_click_block) + ui.board.appendChild(div) + return div } - for (let i = 0; i < 12; ++i) ui.pieces[i] = make_block(i, "Afghan"); - for (let i = 12; i < 24; ++i) ui.pieces[i] = make_block(i, "British"); - for (let i = 24; i < 36; ++i) ui.pieces[i] = make_block(i, "Russian"); + for (let i = 0; i < 12; ++i) ui.pieces[i] = make_block(i, "Afghan") + for (let i = 12; i < 24; ++i) ui.pieces[i] = make_block(i, "British") + for (let i = 24; i < 36; ++i) ui.pieces[i] = make_block(i, "Russian") // Sort player roles so active player is on top! - let top = player === 'Observer' ? 0 : player_index[player]; - let alist = document.getElementById("player_area_list"); - let rlist = document.getElementById("roles"); + let top = player === 'Observer' ? 0 : player_index[player] + let alist = document.getElementById("player_area_list") + let rlist = document.getElementById("roles") for (let p = top; p < view.players.length; ++p) { - alist.appendChild(ui.player[p].area); - rlist.appendChild(ui.player[p].role); - ui.player[p].area.classList.remove("hide"); - ui.player[p].role.classList.remove("hide"); - ui.player[p].score.classList.remove("hide"); + alist.appendChild(ui.player[p].area) + rlist.appendChild(ui.player[p].role) + ui.player[p].area.classList.remove("hide") + ui.player[p].role.classList.remove("hide") + ui.player[p].score.classList.remove("hide") } for (let p = 0; p < top; ++p) { - alist.appendChild(ui.player[p].area); - rlist.appendChild(ui.player[p].role); - ui.player[p].area.classList.remove("hide"); - ui.player[p].role.classList.remove("hide"); - ui.player[p].score.classList.remove("hide"); + alist.appendChild(ui.player[p].area) + rlist.appendChild(ui.player[p].role) + ui.player[p].area.classList.remove("hide") + ui.player[p].role.classList.remove("hide") + ui.player[p].score.classList.remove("hide") } if (player !== 'Observer') - ui.player[top].hand_size.classList.add("hide"); + ui.player[top].hand_size.classList.add("hide") } function debug() { - function rr(k,v) { return k === 'log' || k === 'players' || k === 'actions' ? undefined: v; } - console.log("VIEW", JSON.stringify(view, rr, 0)); - console.log("ACTIONS", JSON.stringify(view.actions, rr, 0)); + function rr(k,v) { return k === 'log' || k === 'players' || k === 'actions' ? undefined : v } + console.log("VIEW", JSON.stringify(view, rr, 0)) + console.log("ACTIONS", JSON.stringify(view.actions, rr, 0)) for (let i = 0; i < view.players.length; ++i) - console.log("PLAYER", i, JSON.stringify(view.players[i], rr, 0)); + console.log("PLAYER", i, JSON.stringify(view.players[i], rr, 0)) } diff --git a/rules.js b/rules.js index 71f2b8f..ac6fda0 100644 --- a/rules.js +++ b/rules.js @@ -1,44 +1,44 @@ -"use strict"; - -let cards = require("./cards.js"); - -const Afghan = 'Afghan'; -const British = 'British'; -const Russian = 'Russian'; - -const Political = 'Political'; -const Intelligence = 'Intelligence'; -const Economic = 'Economic'; -const Military = 'Military'; - -const Persia = 201; -const Transcaspia = 202; -const Herat = 203; -const Kabul = 204; -const Kandahar = 205; -const Punjab = 206; - -const Persia_Transcaspia = 301; -const Persia_Herat = 302; -const Transcaspia_Herat = 303; -const Transcaspia_Kabul = 304; -const Herat_Kabul = 305; -const Herat_Kandahar = 306; -const Kabul_Kandahar = 307; -const Kabul_Punjab = 308; -const Kandahar_Punjab = 309; - -const Gift2 = 400; -const Gift4 = 401; -const Gift6 = 402; -const Safe_House = 500; - -const first_region = 201; -const last_region = 206; - -const PUBLIC_WITHDRAWAL = 111; -const SAFE_HOUSE_1 = 41; -const SAFE_HOUSE_2 = 72; +"use strict" + +let cards = require("./cards.js") + +const Afghan = 'Afghan' +const British = 'British' +const Russian = 'Russian' + +const Political = 'Political' +const Intelligence = 'Intelligence' +const Economic = 'Economic' +const Military = 'Military' + +const Persia = 201 +const Transcaspia = 202 +const Herat = 203 +const Kabul = 204 +const Kandahar = 205 +const Punjab = 206 + +const Persia_Transcaspia = 301 +const Persia_Herat = 302 +const Transcaspia_Herat = 303 +const Transcaspia_Kabul = 304 +const Herat_Kabul = 305 +const Herat_Kandahar = 306 +const Kabul_Kandahar = 307 +const Kabul_Punjab = 308 +const Kandahar_Punjab = 309 + +const Gift2 = 400 +const Gift4 = 401 +const Gift6 = 402 +const Safe_House = 500 + +const first_region = 201 +const last_region = 206 + +const PUBLIC_WITHDRAWAL = 111 +const SAFE_HOUSE_1 = 41 +const SAFE_HOUSE_2 = 72 const player_names = [ "Gray", @@ -47,9 +47,9 @@ const player_names = [ "Red", "Black", "None" -]; +] -const player_index = Object.fromEntries(Object.entries(player_names).map(([k,v])=>[v,k|0])); +const player_index = Object.fromEntries(Object.entries(player_names).map(([k,v])=>[v,k|0])) const region_names = { [Persia]: "Persia", @@ -58,7 +58,7 @@ const region_names = { [Kabul]: "Kabul", [Kandahar]: "Kandahar", [Punjab]: "Punjab", -}; +} const region_index = { "Persia": Persia, @@ -67,15 +67,15 @@ const region_index = { "Kabul": Kabul, "Kandahar": Kandahar, "Punjab": Punjab, -}; +} cards.forEach(card => { if (card) { - card.region = region_index[card.region]; + card.region = region_index[card.region] if (card.name === 'EVENT') - card.name = card.if_discarded + " / " + card.if_purchased; + card.name = card.if_discarded + " / " + card.if_purchased } -}); +}) const border_names = { [Persia_Transcaspia]: "Persia/Transcaspia", @@ -108,519 +108,519 @@ const roads = { } function is_dominance_check(c) { - return c >= 101 && c <= 104; + return c >= 101 && c <= 104 } function is_event_card(c) { - return c > 100; + return c > 100 } -let game = null; -let player = null; -let view = null; +let game = null +let player = null +let view = null -let states = {}; +let states = {} const scenario_player_count = { "2P": 2, "3P": 3, "4P": 4, "5P": 5 } -exports.scenarios = [ "3P", "4P", "5P", "2P" ]; +exports.scenarios = [ "3P", "4P", "5P", "2P" ] exports.roles = function (scenario) { switch (scenario) { - case "2P": return player_names.slice(0, 2); - case "3P": return player_names.slice(0, 3); - case "4P": return player_names.slice(0, 4); - case "5P": return player_names.slice(0, 5); + case "2P": return player_names.slice(0, 2) + case "3P": return player_names.slice(0, 3) + case "4P": return player_names.slice(0, 4) + case "5P": return player_names.slice(0, 5) } } exports.ready = function (scenario, options, players) { switch (scenario) { - case "2P": return players.length === 2; - case "3P": return players.length === 3; - case "4P": return players.length === 4; - case "5P": return players.length === 5; + case "2P": return players.length === 2 + case "3P": return players.length === 3 + case "4P": return players.length === 4 + case "5P": return players.length === 5 } } function random(n) { - return ((game.seed = game.seed * 69621 % 0x7fffffff) / 0x7fffffff) * n | 0; + return ((game.seed = game.seed * 69621 % 0x7fffffff) / 0x7fffffff) * n | 0 } function shuffle(deck) { for (let i = deck.length - 1; i > 0; --i) { - let j = random(i + 1); - let tmp = deck[j]; - deck[j] = deck[i]; - deck[i] = tmp; + let j = random(i + 1) + let tmp = deck[j] + deck[j] = deck[i] + deck[i] = tmp } } function remove_from_array(array, item) { - let i = array.indexOf(item); + let i = array.indexOf(item) if (i >= 0) - array.splice(i, 1); + array.splice(i, 1) } function set_active(new_active) { if (game.active !== new_active) - clear_undo(); - game.active = new_active; - update_aliases(); + clear_undo() + game.active = new_active + update_aliases() } function update_aliases() { - player = game.players[game.active]; + player = game.players[game.active] } function find_card_in_market(c) { for (let row = 0; row < 2; ++row) for (let col = 0; col < 6; ++col) if (c === game.market_cards[row][col]) - return [row, col]; - return null; + return [row, col] + return null } function find_card_in_court(c) { for (let p = 0; p < game.players.length; ++p) { - let court = game.players[p].court; + let court = game.players[p].court for (let i = 0; i < court.length; ++i) if (court[i] === c) - return p; + return p } - return -1; + return -1 } function next_player(current) { - return (current + 1) % game.players.length; + return (current + 1) % game.players.length } function a_coalition(s) { switch (s) { - case Afghan: return "an Afghan"; - case British: return "a British"; - case Russian: return "a Russian"; + case Afghan: return "an Afghan" + case British: return "a British" + case Russian: return "a Russian" } } function logbr() { if (game.log.length > 0 && game.log[game.log.length-1] !== "") - game.log.push(""); + game.log.push("") } function log(msg) { - game.log.push(msg); + game.log.push(msg) } function logi(msg) { - game.log.push(">" + msg); + game.log.push(">" + msg) } function clear_undo() { - game.undo = []; + game.undo = [] } function push_undo() { game.undo.push(JSON.stringify(game, (k,v) => { - if (k === 'undo') return 0; - if (k === 'log') return v.length; - return v; - })); + if (k === 'undo') return 0 + if (k === 'log') return v.length + return v + })) } function pop_undo() { - let save_undo = game.undo; - let save_log = game.log; - game = JSON.parse(save_undo.pop()); - game.undo = save_undo; - save_log.length = game.log; - game.log = save_log; + let save_undo = game.undo + let save_log = game.log + game = JSON.parse(save_undo.pop()) + game.undo = save_undo + save_log.length = game.log + game.log = save_log } function gen_action(action, argument=undefined) { if (argument !== undefined) { if (!(action in view.actions)) { - view.actions[action] = [ argument ]; + view.actions[action] = [ argument ] } else { if (!view.actions[action].includes(argument)) - view.actions[action].push(argument); + view.actions[action].push(argument) } } else { - view.actions[action] = 1; + view.actions[action] = 1 } } // STATE QUERIES function active_has_court_card(c) { - let court = player.court; + let court = player.court for (let i = 0; i < court.length; ++i) if (court[i] === c) - return true; - return false; + return true + return false } function player_has_court_card(p, c) { - let court = game.players[p].court; + let court = game.players[p].court for (let i = 0; i < court.length; ++i) if (court[i] === c) - return true; - return false; + return true + return false } function which_player_has_court_card(c) { for (let p = 0; p < game.players.length; ++p) { - let court = game.players[p].court; + let court = game.players[p].court for (let i = 0; i < court.length; ++i) if (court[i] === c) - return p; + return p } - return -1; + return -1 } -function active_has_russian_influence() { return active_has_court_card(70); } -function active_has_persian_influence() { return active_has_court_card(68); } -function active_has_herat_influence() { return active_has_court_card(66); } -function active_has_claim_of_ancient_lineage() { return active_has_court_card(5); } -function active_has_indian_supplies() { return active_has_court_card(51); } -function active_has_well_connected() { return active_has_court_card(56); } -function active_has_strange_bedfellows() { return active_has_court_card(21); } -function active_has_infrastructure() { return active_has_court_card(78); } -function active_has_civil_service_reforms() { return active_has_court_card(24); } -function active_has_charismatic_courtiers() { return active_has_court_card(42); } -function active_has_blackmail_kandahar() { return active_has_court_card(43); } -function active_has_blackmail_herat() { return active_has_court_card(54); } +function active_has_russian_influence() { return active_has_court_card(70) } +function active_has_persian_influence() { return active_has_court_card(68) } +function active_has_herat_influence() { return active_has_court_card(66) } +function active_has_claim_of_ancient_lineage() { return active_has_court_card(5) } +function active_has_indian_supplies() { return active_has_court_card(51) } +function active_has_well_connected() { return active_has_court_card(56) } +function active_has_strange_bedfellows() { return active_has_court_card(21) } +function active_has_infrastructure() { return active_has_court_card(78) } +function active_has_civil_service_reforms() { return active_has_court_card(24) } +function active_has_charismatic_courtiers() { return active_has_court_card(42) } +function active_has_blackmail_kandahar() { return active_has_court_card(43) } +function active_has_blackmail_herat() { return active_has_court_card(54) } -function player_has_bodyguards(p) { return player_has_court_card(p, 15) || player_has_court_card(p, 83); } -function player_has_indispensable_advisors(p) { return player_has_court_card(p, 1); } -function player_has_citadel_in_kabul(p) { return player_has_court_card(p, 17); } -function player_has_citadel_in_transcaspia(p) { return player_has_court_card(p, 97); } -function player_has_safe_house(p) { return player_has_court_card(p, 41) || player_has_court_card(p, 72); } +function player_has_bodyguards(p) { return player_has_court_card(p, 15) || player_has_court_card(p, 83) } +function player_has_indispensable_advisors(p) { return player_has_court_card(p, 1) } +function player_has_citadel_in_kabul(p) { return player_has_court_card(p, 17) } +function player_has_citadel_in_transcaspia(p) { return player_has_court_card(p, 97) } +function player_has_safe_house(p) { return player_has_court_card(p, 41) || player_has_court_card(p, 72) } -function which_player_has_insurrection() { return which_player_has_court_card(3); } +function which_player_has_insurrection() { return which_player_has_court_card(3) } function player_has_citadel(p, r) { - if (r === Kabul) return player_has_citadel_in_kabul(p); - if (r === Transcaspia) return player_has_citadel_in_transcaspia(p); - return false; + if (r === Kabul) return player_has_citadel_in_kabul(p) + if (r === Transcaspia) return player_has_citadel_in_transcaspia(p) + return false } function player_coalition_blocks(p) { switch (game.players[p].loyalty) { - case Afghan: return 0; - case British: return 12; - case Russian: return 24; + case Afghan: return 0 + case British: return 12 + case Russian: return 24 } } function active_coalition_blocks() { switch (player.loyalty) { - case Afghan: return 0; - case British: return 12; - case Russian: return 24; + case Afghan: return 0 + case British: return 12 + case Russian: return 24 } } function player_cylinders(p) { - return 36 + p * 10; + return 36 + p * 10 } function active_cylinders() { - return 36 + game.active * 10; + return 36 + game.active * 10 } function min_gift_cost() { - let x = active_cylinders(); - let avail_2 = true, avail_4 = true, avail_6 = true; + let x = active_cylinders() + let avail_2 = true, avail_4 = true, avail_6 = true for (let i = x; i < x + 10; ++i) { - let s = game.pieces[i]; - if (s === Gift2) avail_2 = false; - else if (s === Gift4) avail_4 = false; - else if (s === Gift6) avail_6 = false; + let s = game.pieces[i] + if (s === Gift2) avail_2 = false + else if (s === Gift4) avail_4 = false + else if (s === Gift6) avail_6 = false } - if (avail_2) return 2; - if (avail_4) return 4; - if (avail_6) return 6; - return 1000; + if (avail_2) return 2 + if (avail_4) return 4 + if (avail_6) return 6 + return 1000 } function gen_place_gift() { - let x = active_cylinders(); - let avail_2 = true, avail_4 = true, avail_6 = true; + let x = active_cylinders() + let avail_2 = true, avail_4 = true, avail_6 = true for (let i = x; i < x + 10; ++i) { - let s = game.pieces[i]; - if (s === Gift2) avail_2 = false; - else if (s === Gift4) avail_4 = false; - else if (s === Gift6) avail_6 = false; + let s = game.pieces[i] + if (s === Gift2) avail_2 = false + else if (s === Gift4) avail_4 = false + else if (s === Gift6) avail_6 = false } - if (avail_2 && player.coins >= 2) gen_action('place_gift', 2); - if (avail_4 && player.coins >= 4) gen_action('place_gift', 4); - if (avail_6 && player.coins >= 6) gen_action('place_gift', 6); + if (avail_2 && player.coins >= 2) gen_action('place_gift', 2) + if (avail_4 && player.coins >= 4) gen_action('place_gift', 4) + if (avail_6 && player.coins >= 6) gen_action('place_gift', 6) } function ruler_of_region(r) { - let ruler = -1; + let ruler = -1 - let n_afghan = 0; - let n_british = 0; - let n_russian = 0; + let n_afghan = 0 + let n_british = 0 + let n_russian = 0 for (let i = 0; i < 12; ++i) { if (game.pieces[i] === r) - n_afghan ++; + n_afghan ++ if (game.pieces[i+12] === r) - n_british ++; + n_british ++ if (game.pieces[i+24] === r) - n_russian ++; + n_russian ++ } - let max_ruling = Math.max(n_afghan, n_british, n_russian); + let max_ruling = Math.max(n_afghan, n_british, n_russian) for (let p = 0; p < game.players.length; ++p) { - let n_tribes = 0; - let x = player_cylinders(p); + let n_tribes = 0 + let x = player_cylinders(p) for (let i = x; i < x + 10; ++i) if (game.pieces[i] === r) - n_tribes++; + n_tribes++ - let n_ruling = n_tribes; + let n_ruling = n_tribes if (game.players[p].loyalty === Afghan) - n_ruling += n_afghan; + n_ruling += n_afghan if (game.players[p].loyalty === British) - n_ruling += n_british; + n_ruling += n_british if (game.players[p].loyalty === Russian) - n_ruling += n_russian; + n_ruling += n_russian if (n_ruling === max_ruling) { - ruler = -1; + ruler = -1 } else if (n_ruling > max_ruling) { - max_ruling = n_ruling; + max_ruling = n_ruling if (n_tribes > 0) - ruler = p; + ruler = p else - ruler = -1; + ruler = -1 } } - return ruler; + return ruler } function player_rules_region(p, r) { - return ruler_of_region(r) === p; + return ruler_of_region(r) === p } function active_rules_region(r) { - return player_rules_region(game.active, r); + return player_rules_region(game.active, r) } function player_rules_any_region(p) { for (let r = first_region; r <= last_region; ++r) if (player_rules_region(p, r)) - return true; - return false; + return true + return false } function active_rules_any_region() { - return player_rules_any_region(game.active); + return player_rules_any_region(game.active) } function active_can_betray() { - let x = active_cylinders(); + let x = active_cylinders() for (let i = x; i < x + 10; ++i) { if (game.pieces[i] >= 1 && game.pieces[i] <= 100) { - let c = game.pieces[i]; + let c = game.pieces[i] if (cards[c].suit !== Political) - return true; - let p = find_card_in_court(c); + return true + let p = find_card_in_court(c) if (!player_has_bodyguards(p)) - return true; + return true } } - return false; + return false } function card_has_no_spies(c) { for (let p = 0; p < game.players.length; ++p) { - let x = player_cylinders(p); + let x = player_cylinders(p) for (let i = x; i < x + 10; ++i) if (game.pieces[i] === c) - return false; + return false } - return true; + return true } function market_cost(col, c) { if (col === 0) - return 0; + return 0 if (cards[c].patriot === Russian && active_has_russian_influence()) - return 0; + return 0 if (cards[c].region === Persia && active_has_persian_influence()) - return 0; + return 0 if (cards[c].region === Herat && active_has_herat_influence()) - return 0; + return 0 if (game.favored === Military) - return 2 * col; - return col; + return 2 * col + return col } function is_favored_suit(c) { if (cards[c].suit === game.favored) - return true; + return true if (player.events.new_tactics && cards[c].suit === Military) - return true; - if (c === 91) return true; // Savvy Operator - if (c === 99) return true; // Irregulars - return false; + return true + if (c === 91) return true // Savvy Operator + if (c === 99) return true // Irregulars + return false } function rightmost_card(row, i) { while (i >= 0 && game.market_cards[row][i] === 0) - --i; - return i; + --i + return i } function pay_action_cost(cost, offset) { - player.coins -= cost; - let ra = rightmost_card(0, 5); - let rb = rightmost_card(1, 5); + player.coins -= cost + let ra = rightmost_card(0, 5) + let rb = rightmost_card(1, 5) for (let i = 0; i < offset; ++i) { - ra = rightmost_card(0, ra-1); - rb = rightmost_card(1, rb-1); + ra = rightmost_card(0, ra-1) + rb = rightmost_card(1, rb-1) } for (let i = 0; i < cost; i += 2) { - if (ra >= 0) game.market_coins[0][ra] ++; - if (rb >= 0) game.market_coins[1][rb] ++; - ra = rightmost_card(0, ra-1); - rb = rightmost_card(1, rb-1); + if (ra >= 0) game.market_coins[0][ra] ++ + if (rb >= 0) game.market_coins[1][rb] ++ + ra = rightmost_card(0, ra-1) + rb = rightmost_card(1, rb-1) } - check_public_withdrawal(); + check_public_withdrawal() } function remove_all_tribes_and_armies(where) { - logi(`Removed all tribes and armies in ${region_names[where]}.`); + logi(`Removed all tribes and armies in ${region_names[where]}.`) for (let i = 0; i < 36; ++i) if (game.pieces[i] === where) - game.pieces[i] = 0; + game.pieces[i] = 0 for (let p = 0; p < game.players.length; ++p) { - let x = player_cylinders(p); - let maybe_overthrow = false; + let x = player_cylinders(p) + let maybe_overthrow = false for (let i = x; i < x + 10; ++i) { if (game.pieces[i] === where) { - game.pieces[i] = 0; - maybe_overthrow = true; + game.pieces[i] = 0 + maybe_overthrow = true } } if (maybe_overthrow) - check_region_overthrow(p, where); + check_region_overthrow(p, where) } } function player_with_most_spies(c) { - let who = -1; - let max_spies = 0; + let who = -1 + let max_spies = 0 for (let p = 0; p < game.players.length; ++p) { - let n_spies = count_player_cylinders(p, c); + let n_spies = count_player_cylinders(p, c) if (n_spies === max_spies) { - who = -1; + who = -1 } else if (n_spies > max_spies) { - max_spies = n_spies; - who = p; + max_spies = n_spies + who = p } } - return who; + return who } function select_available_cylinder() { - let x = active_cylinders(); + let x = active_cylinders() for (let i = x; i < x + 10; ++i) if (game.pieces[i] === 0) - return i; - return -1; + return i + return -1 } function gen_select_cylinder() { - let x = active_cylinders(); + let x = active_cylinders() for (let i = x; i < x + 10; ++i) if (!game.used_pieces.includes(i)) - gen_action('piece', i); + gen_action('piece', i) } function gen_select_spy_to_move() { - let x = active_cylinders(); + let x = active_cylinders() for (let i = x; i < x + 10; ++i) if (game.pieces[i] > 0 && game.pieces[i] <= 100) - gen_action('piece', i); + gen_action('piece', i) } function gen_select_tribe_to_move() { - let x = active_cylinders(); + let x = active_cylinders() for (let i = x; i < x + 10; ++i) if (game.pieces[i] >= first_region && game.pieces[i] <= last_region) - gen_action('piece', i); + gen_action('piece', i) } function select_available_block() { - let b = active_coalition_blocks(); + let b = active_coalition_blocks() for (let i = b + 11; i >= b; --i) if (game.pieces[i] === 0) - return i; - return -1; + return i + return -1 } function select_afghan_block() { for (let i = 0; i < 12; ++i) if (game.pieces[i] === 0) - return i; - return -1; + return i + return -1 } function gen_select_block() { - let b = active_coalition_blocks(); + let b = active_coalition_blocks() for (let i = b; i < b + 12; ++i) if (!game.used_pieces.includes(i)) - gen_action('piece', i); + gen_action('piece', i) } function gen_select_army_to_move() { - let b = active_coalition_blocks(); + let b = active_coalition_blocks() for (let i = b; i < b + 12; ++i) { - let r = game.pieces[i]; + let r = game.pieces[i] if (r >= first_region && r <= last_region) if (active_can_move_from_region(r)) - gen_action('piece', i); + gen_action('piece', i) } } // DISCARD COURT CARD function discard_court_card(c) { - let pidx = -1; + let pidx = -1 // Remove card from court for (let p = 0; p < game.players.length; ++p) { - let i = game.players[p].court.indexOf(c); + let i = game.players[p].court.indexOf(c) if (i >= 0) { - game.players[p].court.splice(i, 1); - pidx = p; - break; + game.players[p].court.splice(i, 1) + pidx = p + break } } if (pidx !== game.phasing) - log(`Discarded #${c} from ${player_names[pidx]} court.`); + log(`Discarded #${c} from ${player_names[pidx]} court.`) else - log(`Discarded #${c} from court.`); + log(`Discarded #${c} from court.`) // Return all spies on card for (let p = 0; p < game.players.length; ++p) { - let x = player_cylinders(p); + let x = player_cylinders(p) for (let i = x; i < x + 10; ++i) { if (game.pieces[i] === c) { - log(`Returned ${player_names[p]} spy.`); - game.pieces[i] = 0; + log(`Returned ${player_names[p]} spy.`) + game.pieces[i] = 0 } } } @@ -628,155 +628,155 @@ function discard_court_card(c) { // Return rupees for leverage if (cards[c].leveraged) { if (pidx !== game.phasing) - log(`${player_names[pidx]} paid back leverage.`); + log(`${player_names[pidx]} paid back leverage.`) else - log(`Paid back leverage.`); + log(`Paid back leverage.`) - game.players[pidx].coins -= 2; + game.players[pidx].coins -= 2 } if (cards[c].suit === Political) - check_court_overthrow(pidx, cards[c].region); + check_court_overthrow(pidx, cards[c].region) } // CHANGE LOYALTY function change_loyalty(new_loyalty) { - player.loyalty = new_loyalty; + player.loyalty = new_loyalty - log(`Loyalty to ${player.loyalty}.`); + log(`Loyalty to ${player.loyalty}.`) for (let i = 0; i < player.court.length;) { - let c = player.court[i]; - let card = cards[c]; + let c = player.court[i] + let card = cards[c] if (card.patriot && card.patriot !== new_loyalty) { - discard_court_card(c); + discard_court_card(c) } else { - ++i; + ++i } } - let x = active_cylinders(); + let x = active_cylinders() for (let i = x; i < x + 10; ++i) { - let s = game.pieces[i]; + let s = game.pieces[i] if (s === Gift2 || s === Gift4 || s === Gift6) - game.pieces[i] = 0; + game.pieces[i] = 0 } - player.prizes = 0; + player.prizes = 0 } // RETURN LEVERAGE function check_leverage() { - let first = game.phasing; + let first = game.phasing for (let p = first; p < game.players.length; ++p) if (check_player_leverage(p)) - return; + return for (let p = 0; p < first; ++p) if (check_player_leverage(p)) - return; - check_safe_house(); + return + check_safe_house() } function check_player_leverage(p) { if (game.players[p].coins < 0) { if (game.players[p].hand.length + game.players[p].court.length === 0) { - game.players[p].coins = 0; + game.players[p].coins = 0 } else { - logbr(); - set_active(p); - game.state = 'leverage'; - return true; + logbr() + set_active(p) + game.state = 'leverage' + return true } } - return false; + return false } states.leverage = { prompt() { if (player.coins < 0) { - view.prompt = `Discard cards from your hand or court to pay back leverage.`; + view.prompt = `Discard cards from your hand or court to pay back leverage.` for (let i = 0; i < player.hand.length; ++i) - gen_action('card', player.hand[i]); + gen_action('card', player.hand[i]) for (let i = 0; i < player.court.length; ++i) - gen_action('card', player.court[i]); + gen_action('card', player.court[i]) } else { - view.prompt = `Discard cards from your hand or court to pay back leverage \u2014 done.`; - gen_action('next'); + view.prompt = `Discard cards from your hand or court to pay back leverage \u2014 done.` + gen_action('next') } }, card(c) { - push_undo(); - player.coins ++; + push_undo() + player.coins ++ if (player.hand.includes(c)) { - log(`Discarded #${c} from hand.`); - remove_from_array(player.hand, c); + log(`Discarded #${c} from hand.`) + remove_from_array(player.hand, c) } else { - discard_court_card(c); + discard_court_card(c) } if (player.hand.length + player.court.length === 0) - player.coins = 0; + player.coins = 0 }, next() { - push_undo(); - check_leverage(); + push_undo() + check_leverage() } } // OVERTHROW function check_court_overthrow(p, r) { - let court = game.players[p].court; - let x = player_cylinders(p); + let court = game.players[p].court + let x = player_cylinders(p) - let nc = 0; + let nc = 0 for (let i = 0; i < court.length; ++i) { - let info = cards[court[i]]; + let info = cards[court[i]] if (info.suit === Political && info.region === r) - ++nc; + ++nc } - let nt = 0; + let nt = 0 for (let i = x; i < x + 10; ++i) if (game.pieces[i] === r) - ++nt; + ++nt if (nc === 0 && nt > 0) { - log(`${player_names[p]} overthrown in ${region_names[r]}.`); + log(`${player_names[p]} overthrown in ${region_names[r]}.`) for (let i = x; i < x + 10; ++i) { if (game.pieces[i] === r) { - // log(`Removed ${player_names[p]} tribe.`); - game.pieces[i] = 0; + // log(`Removed ${player_names[p]} tribe.`) + game.pieces[i] = 0 } } } } function check_region_overthrow(p, r) { - let court = game.players[p].court; - let x = player_cylinders(p); + let court = game.players[p].court + let x = player_cylinders(p) - let nc = 0; + let nc = 0 for (let i = 0; i < court.length; ++i) { - let info = cards[court[i]]; + let info = cards[court[i]] if (info.suit === Political && info.region === r) - ++nc; + ++nc } - let nt = 0; + let nt = 0 for (let i = x; i < x + 10; ++i) if (game.pieces[i] === r) - ++nt; + ++nt if (nt === 0 && nc > 0) { - log(`${player_names[p]} overthrown in ${region_names[r]}.`); + log(`${player_names[p]} overthrown in ${region_names[r]}.`) for (let i = 0; i < court.length;) { - let info = cards[court[i]]; + let info = cards[court[i]] if (info.suit === Political && info.region === r) - discard_court_card(court[i]); + discard_court_card(court[i]) else - ++i; + ++i } } } @@ -785,174 +785,174 @@ function check_region_overthrow(p, r) { states.bribe = { prompt() { - let p = game.bribe; - view.prompt = `Must pay ${game.count} rupee bribe to ${player_names[p]}.`; + let p = game.bribe + view.prompt = `Must pay ${game.count} rupee bribe to ${player_names[p]}.` if (player.coins - game.reserve >= game.count) - gen_action('pay'); - gen_action('beg'); + gen_action('pay') + gen_action('beg') if (player.events.courtly_manners) - gen_action('courtly_manners'); + gen_action('courtly_manners') if (game.undo.length === 0) - gen_action('refuse'); + gen_action('refuse') }, courtly_manners() { - log(`Did not pay bribe.`); - end_bribe(); + log(`Did not pay bribe.`) + end_bribe() }, pay() { - let p = game.bribe; - log(`Paid ${game.count} to ${player_names[p]}.`); - game.players[p].coins += game.count; - game.players[game.active].coins -= game.count; - end_bribe(); + let p = game.bribe + log(`Paid ${game.count} to ${player_names[p]}.`) + game.players[p].coins += game.count + game.players[game.active].coins -= game.count + end_bribe() }, beg() { - let p = game.bribe; - log(`Asked ${player_names[p]} to waive the bribe for #${game.card}.`); - game.state = 'waive'; - set_active(p); + let p = game.bribe + log(`Asked ${player_names[p]} to waive the bribe for #${game.card}.`) + game.state = 'waive' + set_active(p) }, refuse() { - game.card = 0; - game.where = 0; - resume_actions(); + game.card = 0 + game.where = 0 + resume_actions() }, } states.waive = { prompt() { if (typeof game.where === 'string') - view.prompt = `${player_names[game.phasing]} asks you to waive the bribe to use #${game.card} to ${game.where}.`; + view.prompt = `${player_names[game.phasing]} asks you to waive the bribe to use #${game.card} to ${game.where}.` else - view.prompt = `${player_names[game.phasing]} asks you to waive the bribe to play #${game.card}.`; - let max_cost = Math.min(game.players[game.phasing].coins - game.reserve, game.count); - gen_action('waive'); + view.prompt = `${player_names[game.phasing]} asks you to waive the bribe to play #${game.card}.` + let max_cost = Math.min(game.players[game.phasing].coins - game.reserve, game.count) + gen_action('waive') for (let i = 1; i < max_cost; ++i) - gen_action('offer_' + i); - gen_action('refuse'); + gen_action('offer_' + i) + gen_action('refuse') }, waive() { - log(`${player_names[game.active]} waived the bribe.`); - set_active(game.phasing); - end_bribe(); - }, - offer_1() { do_offer(1); }, - offer_2() { do_offer(2); }, - offer_3() { do_offer(3); }, - offer_4() { do_offer(4); }, - offer_5() { do_offer(5); }, - offer_6() { do_offer(6); }, - offer_7() { do_offer(7); }, - offer_8() { do_offer(8); }, - offer_9() { do_offer(9); }, + log(`${player_names[game.active]} waived the bribe.`) + set_active(game.phasing) + end_bribe() + }, + offer_1() { do_offer(1) }, + offer_2() { do_offer(2) }, + offer_3() { do_offer(3) }, + offer_4() { do_offer(4) }, + offer_5() { do_offer(5) }, + offer_6() { do_offer(6) }, + offer_7() { do_offer(7) }, + offer_8() { do_offer(8) }, + offer_9() { do_offer(9) }, refuse() { - log(`${player_names[game.active]} refused to waive the bribe.`); - game.state = 'bribe'; - set_active(game.phasing); + log(`${player_names[game.active]} refused to waive the bribe.`) + game.state = 'bribe' + set_active(game.phasing) }, } function do_offer(n) { - log(`${player_names[game.active]} reduced the bribe to ${n}.`); - game.count = 1; - game.state = 'bribe'; - set_active(game.phasing); + log(`${player_names[game.active]} reduced the bribe to ${n}.`) + game.count = 1 + game.state = 'bribe' + set_active(game.phasing) } function end_bribe() { if (typeof game.where === 'string') - do_card_action_2(); + do_card_action_2() else - do_play_2(); + do_play_2() } // STARTING LOYALTY states.loyalty = { prompt() { - view.prompt = `Choose your loyalty \u2014 Afghan, British, or Russian.`; - gen_action('loyalty_afghan'); - gen_action('loyalty_british'); - gen_action('loyalty_russian'); + view.prompt = `Choose your loyalty \u2014 Afghan, British, or Russian.` + gen_action('loyalty_afghan') + gen_action('loyalty_british') + gen_action('loyalty_russian') }, loyalty_afghan() { - set_starting_loyalty(Afghan); + set_starting_loyalty(Afghan) }, loyalty_british() { - set_starting_loyalty(British); + set_starting_loyalty(British) }, loyalty_russian() { - set_starting_loyalty(Russian); + set_starting_loyalty(Russian) }, } function set_starting_loyalty(loyalty) { - log(`${player_names[game.active]} loyalty to ${loyalty}.`); - player.loyalty = loyalty; - let next = next_player(game.active); + log(`${player_names[game.active]} loyalty to ${loyalty}.`) + player.loyalty = loyalty + let next = next_player(game.active) if (game.players[next].loyalty) - goto_actions(); + goto_actions() else - set_active(next); + set_active(next) } // ACTION PHASE function goto_actions() { - game.phasing = game.active; - game.actions = 2; - game.used_cards = []; // track cards that have been used - game.used_pieces = []; - game.selected = -1; - game.where = 0; - logbr(); - log(`.turn ${player_names[game.phasing]}`); - logbr(); - - let bmh = active_can_blackmail(Herat); - let bmk = active_can_blackmail(Kandahar); + game.phasing = game.active + game.actions = 2 + game.used_cards = [] // track cards that have been used + game.used_pieces = [] + game.selected = -1 + game.where = 0 + logbr() + log(`.turn ${player_names[game.phasing]}`) + logbr() + + let bmh = active_can_blackmail(Herat) + let bmk = active_can_blackmail(Kandahar) if (bmh || bmk) { - game.state = 'blackmail'; - game.where = (bmh && bmk) ? -1 : (bmh ? Herat : Kandahar); - game.selected = select_available_cylinder(); + game.state = 'blackmail' + game.where = (bmh && bmk) ? -1 : (bmh ? Herat : Kandahar) + game.selected = select_available_cylinder() } else { - resume_actions(); + resume_actions() } } function end_action() { - check_leverage(); + check_leverage() } function resume_actions() { - set_active(game.phasing); - game.selected = -1; - game.where = 0; - game.state = 'actions'; + set_active(game.phasing) + game.selected = -1 + game.where = 0 + game.state = 'actions' } function goto_next_player() { - game.phasing = next_player(game.phasing); - set_active(game.phasing); - goto_actions(); + game.phasing = next_player(game.phasing) + set_active(game.phasing) + goto_actions() } states.actions = { prompt() { // Pass / End turn if (game.actions > 0) { - gen_action('end_turn_pass'); + gen_action('end_turn_pass') } else { - gen_action('end_turn'); + gen_action('end_turn') } // Purchase if (game.actions > 0) { for (let row = 0; row < 2; ++row) { for (let col = 0; col < 6; ++col) { - let c = game.market_cards[row][col]; + let c = game.market_cards[row][col] if (c && market_cost(col, c) <= player.coins && !game.used_cards.includes(c) && c !== PUBLIC_WITHDRAWAL) - gen_action('card', c); + gen_action('card', c) } } } @@ -960,190 +960,190 @@ states.actions = { // Play if (game.actions > 0) { for (let i = 0; i < player.hand.length; ++i) { - let c = player.hand[i]; - gen_action('play_left', c); - gen_action('play_right', c); + let c = player.hand[i] + gen_action('play_left', c) + gen_action('play_right', c) } } // Card-based actions - let bonus = false; + let bonus = false for (let i = 0; i < player.court.length; ++i) { - let c = player.court[i]; - let card = cards[c]; + let c = player.court[i] + let card = cards[c] if (game.used_cards.includes(c)) - continue; + continue - let favored = is_favored_suit(c); + let favored = is_favored_suit(c) if (favored || game.actions > 0) { - let usable = false; + let usable = false if (card.tax && active_can_tax()) { - gen_action('tax', c); - usable = true; + gen_action('tax', c) + usable = true } if (card.gift && player.coins >= min_gift_cost()) { - gen_action('gift', c); - usable = true; + gen_action('gift', c) + usable = true } if (card.build && player.coins >= 2 && active_rules_any_region()) { - gen_action('build', c); - usable = true; + gen_action('build', c) + usable = true } if (card.move && active_can_move()) { - gen_action('move', c); - usable = true; + gen_action('move', c) + usable = true } if (card.betray && player.coins >= 2 && active_can_betray()) { - gen_action('betray', c); - usable = true; + gen_action('betray', c) + usable = true } if (card.battle && active_can_battle()) { - gen_action('battle', c); - usable = true; + gen_action('battle', c) + usable = true } if (usable && favored) - bonus = true; + bonus = true } } if (game.actions === 2) - view.prompt = `You may take two actions.`; + view.prompt = `You may take two actions.` else if (game.actions === 1) - view.prompt = `You may take one more action.`; + view.prompt = `You may take one more action.` else - view.prompt = `You have no more actions.`; + view.prompt = `You have no more actions.` if (bonus) - view.prompt += ` You may take bonus actions.`; + view.prompt += ` You may take bonus actions.` }, // Purchase card from market card(c) { - push_undo(); - logbr(); + push_undo() + logbr() - let [row, col] = find_card_in_market(c); - game.actions --; + let [row, col] = find_card_in_market(c) + game.actions -- - let cost = market_cost(col, c); - let cost_per_card = cost / col; + let cost = market_cost(col, c) + let cost_per_card = cost / col for (let i = 0; i < col; ++i) { if (game.market_cards[row][i] > 0) { - game.market_coins[row][i] += cost_per_card; - game.used_cards.push(game.market_cards[row][i]); + game.market_coins[row][i] += cost_per_card + game.used_cards.push(game.market_cards[row][i]) } else { - game.market_coins[1-row][i] += cost_per_card; - game.used_cards.push(game.market_cards[1-row][i]); + game.market_coins[1-row][i] += cost_per_card + game.used_cards.push(game.market_cards[1-row][i]) } } - check_public_withdrawal(); + check_public_withdrawal() - logbr(); + logbr() if (cost > 0) - player.coins -= cost; + player.coins -= cost - let took = game.market_coins[row][col]; + let took = game.market_coins[row][col] if (took > 0) - player.coins += took; + player.coins += took - game.market_coins[row][col] = 0; - game.market_cards[row][col] = 0; + game.market_coins[row][col] = 0 + game.market_cards[row][col] = 0 - log(`Purchased #${c}.`); + log(`Purchased #${c}.`) if (cost > 0 && took > 0) - logi(`Paid ${cost} and took ${took}.`); + logi(`Paid ${cost} and took ${took}.`) else if (cost > 0) - logi(`Paid ${cost}.`); + logi(`Paid ${cost}.`) else if (took > 0) - logi(`Took ${took}.`); + logi(`Took ${took}.`) if (is_dominance_check(c)) { - do_dominance_check('purchase'); + do_dominance_check('purchase') } else if (is_event_card(c)) { - events_if_purchased[cards[c].if_purchased](); + events_if_purchased[cards[c].if_purchased]() } else { - player.hand.push(c); - resume_actions(); + player.hand.push(c) + resume_actions() } }, // Play card to court - play_left(c) { do_play_1(c, 0); }, - play_right(c) { do_play_1(c, 1); }, + play_left(c) { do_play_1(c, 0) }, + play_right(c) { do_play_1(c, 1) }, // Use card based ability - tax(c) { do_card_action_1(c, "Tax", 0); }, - gift(c) { do_card_action_1(c, "Gift", min_gift_cost()); }, - build(c) { do_card_action_1(c, "Build", 2); }, - move(c) { do_card_action_1(c, "Move", 0); }, - betray(c) { do_card_action_1(c, "Betray", 2); }, - battle(c) { do_card_action_1(c, "Battle", 0); }, + tax(c) { do_card_action_1(c, "Tax", 0) }, + gift(c) { do_card_action_1(c, "Gift", min_gift_cost()) }, + build(c) { do_card_action_1(c, "Build", 2) }, + move(c) { do_card_action_1(c, "Move", 0) }, + betray(c) { do_card_action_1(c, "Betray", 2) }, + battle(c) { do_card_action_1(c, "Battle", 0) }, end_turn_pass() { - logbr(); - log(`Passed.`); - goto_cleanup_court(); + logbr() + log(`Passed.`) + goto_cleanup_court() }, end_turn() { - goto_cleanup_court(); + goto_cleanup_court() }, } // PLAY CARD function do_play_1(c, side) { - push_undo(); - game.card = c; - game.where = side; + push_undo() + game.card = c + game.where = side if (!active_has_charismatic_courtiers() && !game.events.disregard_for_customs) { - let ruler = ruler_of_region(cards[c].region); + let ruler = ruler_of_region(cards[c].region) if (ruler >= 0 && ruler !== game.active) { - logbr(); - game.state = 'bribe'; - game.count = count_player_cylinders(ruler, cards[c].region); - game.reserve = 0; - game.bribe = ruler; - return; + logbr() + game.state = 'bribe' + game.count = count_player_cylinders(ruler, cards[c].region) + game.reserve = 0 + game.bribe = ruler + return } } - do_play_2(); + do_play_2() } function do_play_2() { - let c = game.card; - let side = game.where; - game.actions --; - logbr(); - log(`Played #${c}.`); - let idx = player.hand.indexOf(c); - player.hand.splice(idx, 1); + let c = game.card + let side = game.where + game.actions -- + logbr() + log(`Played #${c}.`) + let idx = player.hand.indexOf(c) + player.hand.splice(idx, 1) if (side) - player.court.push(c); + player.court.push(c) else - player.court.unshift(c); - goto_play_patriot(); + player.court.unshift(c) + goto_play_patriot() } function goto_play_patriot() { - let card = cards[game.card]; + let card = cards[game.card] if (card.patriot && card.patriot !== player.loyalty) - change_loyalty(card.patriot); - goto_play_tribes(); + change_loyalty(card.patriot) + goto_play_tribes() } function goto_play_tribes() { - let card = cards[game.card]; + let card = cards[game.card] if (card.tribes) { - game.count = card.tribes; - game.state = 'place_tribe'; - game.where = card.region; - game.selected = select_available_cylinder(); + game.count = card.tribes + game.state = 'place_tribe' + game.where = card.region + game.selected = select_available_cylinder() } else { - goto_play_roads(); + goto_play_roads() } } @@ -1151,39 +1151,39 @@ states.place_tribe = { inactive: "place tribe", prompt() { if (game.selected < 0) { - view.prompt = `Place tribe in ${region_names[game.where]} \u2014 select a cylinder.`; - gen_select_cylinder(); + view.prompt = `Place tribe in ${region_names[game.where]} \u2014 select a cylinder.` + gen_select_cylinder() } else { - view.prompt = `Place tribe in ${region_names[game.where]}.`; - gen_action('space', game.where); + view.prompt = `Place tribe in ${region_names[game.where]}.` + gen_action('space', game.where) } }, piece(x) { - push_undo(); - game.selected = x; + push_undo() + game.selected = x }, space(s) { - push_undo(); - logi(`Tribe to ${region_names[s]}.`); - game.pieces[game.selected] = s; - game.used_pieces.push(game.selected); - game.selected = -1; + push_undo() + logi(`Tribe to ${region_names[s]}.`) + game.pieces[game.selected] = s + game.used_pieces.push(game.selected) + game.selected = -1 if (--game.count === 0) - goto_play_roads(); + goto_play_roads() else - game.selected = select_available_cylinder(); + game.selected = select_available_cylinder() }, } function goto_play_roads() { - let card = cards[game.card]; + let card = cards[game.card] if (card.roads) { - game.count = card.roads; - game.state = 'place_road'; - game.where = card.region; - game.selected = select_available_block(); + game.count = card.roads + game.state = 'place_road' + game.where = card.region + game.selected = select_available_block() } else { - goto_play_armies(); + goto_play_armies() } } @@ -1191,40 +1191,40 @@ states.place_road = { inactive: "place road", prompt() { if (game.selected < 0) { - view.prompt = `Place ${player.loyalty} road in ${region_names[game.where]} \u2014 select a block to move.`; - gen_select_block(); + view.prompt = `Place ${player.loyalty} road in ${region_names[game.where]} \u2014 select a block to move.` + gen_select_block() } else { - view.prompt = `Place ${player.loyalty} road in ${region_names[game.where]}.`; + view.prompt = `Place ${player.loyalty} road in ${region_names[game.where]}.` for (let s of borders[game.where]) - gen_action('space', s); + gen_action('space', s) } }, piece(x) { - push_undo(); - game.selected = x; + push_undo() + game.selected = x }, space(s) { - push_undo(); - logi(`${player.loyalty} road to ${border_names[s]}.`); - game.pieces[game.selected] = s; - game.used_pieces.push(game.selected); - game.selected = -1; + push_undo() + logi(`${player.loyalty} road to ${border_names[s]}.`) + game.pieces[game.selected] = s + game.used_pieces.push(game.selected) + game.selected = -1 if (--game.count === 0) - goto_play_armies(); + goto_play_armies() else - game.selected = select_available_block(); + game.selected = select_available_block() }, } function goto_play_armies() { - let card = cards[game.card]; + let card = cards[game.card] if (card.armies) { - game.count = card.armies; - game.state = 'place_army'; - game.where = card.region; - game.selected = select_available_block(); + game.count = card.armies + game.state = 'place_army' + game.where = card.region + game.selected = select_available_block() } else { - goto_play_spies(); + goto_play_spies() } } @@ -1232,39 +1232,39 @@ states.place_army = { inactive: "place army", prompt() { if (game.selected < 0) { - view.prompt = `Place ${player.loyalty} army in ${region_names[game.where]} \u2014 select a block to move.`; - gen_select_block(); + view.prompt = `Place ${player.loyalty} army in ${region_names[game.where]} \u2014 select a block to move.` + gen_select_block() } else { - view.prompt = `Place ${player.loyalty} army in ${region_names[game.where]}.`; - gen_action('space', game.where); + view.prompt = `Place ${player.loyalty} army in ${region_names[game.where]}.` + gen_action('space', game.where) } }, piece(x) { - push_undo(); - game.selected = x; + push_undo() + game.selected = x }, space(s) { - push_undo(); - logi(`${player.loyalty} army to ${region_names[s]}.`); - game.pieces[game.selected] = s; - game.used_pieces.push(game.selected); - game.selected = -1; + push_undo() + logi(`${player.loyalty} army to ${region_names[s]}.`) + game.pieces[game.selected] = s + game.used_pieces.push(game.selected) + game.selected = -1 if (--game.count === 0) - goto_play_spies(); + goto_play_spies() else - game.selected = select_available_block(); + game.selected = select_available_block() }, } function goto_play_spies() { - let card = cards[game.card]; + let card = cards[game.card] if (card.spies) { - game.count = card.spies; - game.state = 'place_spy'; - game.where = card.region; - game.selected = select_available_cylinder(); + game.count = card.spies + game.state = 'place_spy' + game.where = card.region + game.selected = select_available_cylinder() } else { - goto_play_leveraged(); + goto_play_leveraged() } } @@ -1272,68 +1272,68 @@ states.place_spy = { inactive: "place spy", prompt() { if (game.selected < 0) { - view.prompt = `Place spy on a court card in ${region_names[game.where]} \u2014 select a cylinder.`; - gen_select_cylinder(); + view.prompt = `Place spy on a court card in ${region_names[game.where]} \u2014 select a cylinder.` + gen_select_cylinder() } else { - view.prompt = `Place spy on a court card in ${region_names[game.where]}.`; + view.prompt = `Place spy on a court card in ${region_names[game.where]}.` for (let p = 0; p < game.players.length; ++p) { - let court = game.players[p].court; + let court = game.players[p].court for (let i = 0; i < court.length; ++i) { - let card = cards[court[i]]; + let card = cards[court[i]] if (card.region === game.where) { - gen_action('card', court[i]); + gen_action('card', court[i]) } } } } }, piece(x) { - push_undo(); - game.selected = x; + push_undo() + game.selected = x }, card(c) { - push_undo(); - logi(`Spy to #${c}.`); - game.pieces[game.selected] = c; - game.used_pieces.push(game.selected); - game.selected = -1; + push_undo() + logi(`Spy to #${c}.`) + game.pieces[game.selected] = c + game.used_pieces.push(game.selected) + game.selected = -1 if (--game.count === 0) - goto_play_leveraged(); + goto_play_leveraged() else - game.selected = select_available_cylinder(); + game.selected = select_available_cylinder() }, } function goto_play_leveraged() { - let card = cards[game.card]; + let card = cards[game.card] if (card.leveraged) { - logi(`Leveraged.`); - player.coins += 2; + logi(`Leveraged.`) + player.coins += 2 } - goto_play_favored_suit_impact(); + goto_play_favored_suit_impact() } function goto_play_favored_suit_impact() { - let card = cards[game.card]; + let card = cards[game.card] if (card.climate && !game.events.pashtunwali_values) { - game.state = 'favored_suit_impact'; - game.where = card.climate; + game.state = 'favored_suit_impact' + game.where = card.climate } else { - end_action(); + end_action() } } states.favored_suit_impact = { inactive: "favored suit", prompt() { - view.prompt = `Change the favored suit to ${game.where}.`; - gen_action('suit', game.where); + view.prompt = `Change the favored suit to ${game.where}.` + gen_action('suit', game.where) }, suit(suit) { - push_undo(); - logi(`Favored suit to ${suit}.`); - game.favored = suit; - end_action(); + push_undo() + logi(`Favored suit to ${suit}.`) + game.favored = suit + end_action() }, } @@ -1341,55 +1341,55 @@ states.favored_suit_impact = { const card_action_table = { Tax() { - game.state = 'tax'; + game.state = 'tax' }, Gift() { - game.selected = select_available_cylinder(); - game.state = 'gift'; + game.selected = select_available_cylinder() + game.state = 'gift' }, Build() { - game.count = Math.min(3, Math.floor(player.coins / 2)); + game.count = Math.min(3, Math.floor(player.coins / 2)) if (player.events.nation_building) - game.count *= 2; - game.selected = select_available_block(); - game.reserve = 0; - game.state = 'build'; + game.count *= 2 + game.selected = select_available_block() + game.reserve = 0 + game.state = 'build' }, Move() { - game.selected = -1; - game.state = 'move'; + game.selected = -1 + game.state = 'move' }, Betray() { - pay_action_cost(2, 0); - game.state = 'betray'; + pay_action_cost(2, 0) + game.state = 'betray' }, Battle() { - game.state = 'battle'; - game.where = 0; + game.state = 'battle' + game.where = 0 }, } function do_card_action_1(c, what, reserve) { - push_undo(); - game.card = c; - game.where = what; + push_undo() + game.card = c + game.where = what if (!active_has_civil_service_reforms() && !game.events.disregard_for_customs) { - let who = player_with_most_spies(c); + let who = player_with_most_spies(c) if (who >= 0 && who !== game.active) { - logbr(); - game.state = 'bribe'; - game.count = count_player_cylinders(who, c); - game.reserve = reserve; - game.bribe = who; - return; + logbr() + game.state = 'bribe' + game.count = count_player_cylinders(who, c) + game.reserve = reserve + game.bribe = who + return } } - do_card_action_2(); + do_card_action_2() } const past_what = { @@ -1402,95 +1402,95 @@ const past_what = { } function do_card_action_2() { - let c = game.card; - let what = game.where; - game.used_cards.push(c); + let c = game.card + let what = game.where + game.used_cards.push(c) if (!is_favored_suit(c)) - game.actions --; - game.count = cards[c].rank; - logbr(); - log(`${past_what[what]} with #${c}.`); - card_action_table[what](); + game.actions -- + game.count = cards[c].rank + logbr() + log(`${past_what[what]} with #${c}.`) + card_action_table[what]() } // CARD-BASED ACTION: TAX function can_tax_player(active, p, claim) { - let okay = claim; - let shelter = 0; - let court = game.players[p].court; + let okay = claim + let shelter = 0 + let court = game.players[p].court for (let i = 0; i < court.length; ++i) { - let c = court[i]; + let c = court[i] if (!okay && player_rules_region(active, cards[c].region)) - okay = true; + okay = true if (cards[c].suit === Economic) - shelter += cards[c].rank; + shelter += cards[c].rank } - return okay && game.players[p].coins > shelter; + return okay && game.players[p].coins > shelter } function do_tax_player(p) { - push_undo(); - logi(`Taxed ${player_names[p]} player.`); - game.players[p].coins --; - player.coins ++; + push_undo() + logi(`Taxed ${player_names[p]} player.`) + game.players[p].coins -- + player.coins ++ if (--game.count === 0) - end_action(); + end_action() } function active_can_tax() { for (let row = 0; row < 2; ++row) for (let col = 0; col < 6; ++col) if (game.market_coins[row][col] > 0) - return true; - let claim = active_has_claim_of_ancient_lineage(); + return true + let claim = active_has_claim_of_ancient_lineage() for (let p = 0; p < game.players.length; ++p) if (p !== game.active && can_tax_player(game.active, p, claim)) - return true; - return false; + return true + return false } states.tax = { prompt() { if (game.count === 1) - view.prompt = `Tax \u2014 take up to ${game.count} rupee from market cards or players.`; + view.prompt = `Tax \u2014 take up to ${game.count} rupee from market cards or players.` else - view.prompt = `Tax \u2014 take up to ${game.count} rupees from market cards or players.`; + view.prompt = `Tax \u2014 take up to ${game.count} rupees from market cards or players.` for (let row = 0; row < 2; ++row) { for (let col = 0; col < 6; ++col) { if (game.market_coins[row][col] > 0) - gen_action('card', game.market_cards[row][col]); + gen_action('card', game.market_cards[row][col]) } } - let claim = active_has_claim_of_ancient_lineage(); + let claim = active_has_claim_of_ancient_lineage() for (let p = 0; p < game.players.length; ++p) { if (p !== game.active && can_tax_player(game.active, p, claim)) { - gen_action('player_' + p); + gen_action('player_' + p) } } - gen_action('pass'); + gen_action('pass') }, pass() { - push_undo(); - end_action(); + push_undo() + end_action() }, card(c) { - push_undo(); - let [row, col] = find_card_in_market(c); - logi(`Taxed market.`); - game.market_coins[row][col] --; - player.coins ++; + push_undo() + let [row, col] = find_card_in_market(c) + logi(`Taxed market.`) + game.market_coins[row][col] -- + player.coins ++ if (--game.count === 0) - end_action(); + end_action() }, - player_0() { do_tax_player(0); }, - player_1() { do_tax_player(1); }, - player_2() { do_tax_player(2); }, - player_3() { do_tax_player(3); }, - player_4() { do_tax_player(4); }, + player_0() { do_tax_player(0) }, + player_1() { do_tax_player(1) }, + player_2() { do_tax_player(2) }, + player_3() { do_tax_player(3) }, + player_4() { do_tax_player(4) }, } // CARD-BASED ACTION: GIFT @@ -1498,30 +1498,30 @@ states.tax = { states.gift = { prompt() { if (game.selected < 0) { - view.prompt = `Select cylinder to place as Gift.`; - gen_select_cylinder(); + view.prompt = `Select cylinder to place as Gift.` + gen_select_cylinder() } else { - view.prompt = `Place cylinder as Gift.`; - gen_place_gift(); + view.prompt = `Place cylinder as Gift.` + gen_place_gift() } }, piece(x) { - push_undo(); - game.selected = x; + push_undo() + game.selected = x }, place_gift(cost) { - push_undo(); - logi(`Paid ${cost}.`); - pay_action_cost(cost, 0); + push_undo() + logi(`Paid ${cost}.`) + pay_action_cost(cost, 0) if (cost === 2) - game.pieces[game.selected] = Gift2; + game.pieces[game.selected] = Gift2 else if (cost === 4) - game.pieces[game.selected] = Gift4; + game.pieces[game.selected] = Gift4 else if (cost === 6) - game.pieces[game.selected] = Gift6; - game.used_pieces.push(game.selected); - game.selected = -1; - end_action(); + game.pieces[game.selected] = Gift6 + game.used_pieces.push(game.selected) + game.selected = -1 + end_action() } } @@ -1529,222 +1529,222 @@ states.gift = { states.build = { prompt() { - view.prompt = `Build up to ${game.count} armies and/or roads.`; - gen_action('next'); - let must_pay = !player.events.nation_building || (game.count & 1) === 0; + view.prompt = `Build up to ${game.count} armies and/or roads.` + gen_action('next') + let must_pay = !player.events.nation_building || (game.count & 1) === 0 if (!must_pay || player.coins >= 2) { if (game.selected < 0) { - gen_select_block(); + gen_select_block() } else { for (let r = first_region; r <= last_region; ++r) { if (active_rules_region(r)) { - gen_action('space', r); + gen_action('space', r) for (let s of borders[r]) - gen_action('space', s); + gen_action('space', s) } } } } }, piece(x) { - push_undo(); - game.selected = x; + push_undo() + game.selected = x }, space(s) { - push_undo(); + push_undo() - let must_pay = !player.events.nation_building || (game.count & 1) === 0; + let must_pay = !player.events.nation_building || (game.count & 1) === 0 if (must_pay) - pay_action_cost(2, game.reserve++); + pay_action_cost(2, game.reserve++) if (s <= last_region) - logi(`${player.loyalty} army to ${region_names[s]}.`); + logi(`${player.loyalty} army to ${region_names[s]}.`) else - logi(`${player.loyalty} road to ${border_names[s]}.`); - game.pieces[game.selected] = s; - game.used_pieces.push(game.selected); - game.selected = -1; - --game.count; + logi(`${player.loyalty} road to ${border_names[s]}.`) + game.pieces[game.selected] = s + game.used_pieces.push(game.selected) + game.selected = -1 + --game.count - must_pay = !player.events.nation_building || (game.count & 1) === 0; + must_pay = !player.events.nation_building || (game.count & 1) === 0 if (game.count === 0 || (must_pay && player.coins < 2)) - end_build_action(); + end_build_action() else - game.selected = select_available_block(); + game.selected = select_available_block() }, next() { - push_undo(); - end_build_action(); + push_undo() + end_build_action() }, } states.infrastructure = { prompt() { - view.prompt = `Place an additional block.`; + view.prompt = `Place an additional block.` if (game.selected < 0) { - gen_select_block(); + gen_select_block() } else { for (let r = first_region; r <= last_region; ++r) { if (active_rules_region(r)) { - gen_action('space', r); + gen_action('space', r) for (let s of borders[r]) - gen_action('space', s); + gen_action('space', s) } } } }, piece(x) { - push_undo(); - game.selected = x; + push_undo() + game.selected = x }, space(s) { - push_undo(); + push_undo() if (s <= last_region) - logi(`${player.loyalty} army to ${region_names[s]}.`); + logi(`${player.loyalty} army to ${region_names[s]}.`) else - logi(`${player.loyalty} road to ${border_names[s]}.`); - game.pieces[game.selected] = s; - game.used_pieces.push(game.selected); - game.selected = -1; - end_action(); + logi(`${player.loyalty} road to ${border_names[s]}.`) + game.pieces[game.selected] = s + game.used_pieces.push(game.selected) + game.selected = -1 + end_action() }, } function end_build_action() { if (active_has_infrastructure()) { - game.state = 'infrastructure'; - game.selected = select_available_block(); + game.state = 'infrastructure' + game.selected = select_available_block() } else { - end_action(); + end_action() } } // CARD-BASED ACTION: MOVE function last_court_position() { - let n = 0; + let n = 0 for (let p = 0; p < game.players.length; ++p) - n += game.players[p].court.length; - return n - 1; + n += game.players[p].court.length + return n - 1 } function court_card_from_position(y) { - let x = 0; + let x = 0 for (let p = 0; p < game.players.length; ++p) { - let court = game.players[p].court; + let court = game.players[p].court if (y < x + court.length) - return court[y - x]; - x += court.length; + return court[y - x] + x += court.length } - return 0; + return 0 } function court_position_from_card(c) { - let x = 0; + let x = 0 for (let p = 0; p < game.players.length; ++p) { - let court = game.players[p].court; + let court = game.players[p].court for (let i = 0; i < court.length; ++i) { if (c === court[i]) - return x + i; + return x + i } - x += court.length; + x += court.length } - return -1; + return -1 } function find_border(a, b) { if (a > b) { - let c = a; a = b; b = c; + let c = a; a = b; b = c } - if (a === Persia && b === Transcaspia) return Persia_Transcaspia; - if (a === Persia && b === Herat) return Persia_Herat; - if (a === Transcaspia && b === Herat) return Transcaspia_Herat; - if (a === Transcaspia && b === Kabul) return Transcaspia_Kabul; - if (a === Herat && b === Kabul) return Herat_Kabul; - if (a === Herat && b === Kandahar) return Herat_Kandahar; - if (a === Kabul && b === Kandahar) return Kabul_Kandahar; - if (a === Kabul && b === Punjab) return Kabul_Punjab; - if (a === Kandahar && b === Punjab) return Kandahar_Punjab; - throw new Error(`bad border ${a} ${b}`); + if (a === Persia && b === Transcaspia) return Persia_Transcaspia + if (a === Persia && b === Herat) return Persia_Herat + if (a === Transcaspia && b === Herat) return Transcaspia_Herat + if (a === Transcaspia && b === Kabul) return Transcaspia_Kabul + if (a === Herat && b === Kabul) return Herat_Kabul + if (a === Herat && b === Kandahar) return Herat_Kandahar + if (a === Kabul && b === Kandahar) return Kabul_Kandahar + if (a === Kabul && b === Punjab) return Kabul_Punjab + if (a === Kandahar && b === Punjab) return Kandahar_Punjab + throw new Error(`bad border ${a} ${b}`) } function can_army_move_across_border(here, next) { - let border = find_border(here, next); - let b = active_coalition_blocks(); + let border = find_border(here, next) + let b = active_coalition_blocks() for (let i = b; i < b + 12; ++i) if (game.pieces[i] === border) - return true; - return false; + return true + return false } function active_can_move_from_region(here) { - let supplies = active_has_indian_supplies(); + let supplies = active_has_indian_supplies() for (let next of roads[here]) if (supplies || can_army_move_across_border(here, next)) - return true; - return false; + return true + return false } function active_can_move() { - let b = active_coalition_blocks(); - let x = active_cylinders(); + let b = active_coalition_blocks() + let x = active_cylinders() for (let i = b; i < b + 12; ++i) { - let r = game.pieces[i]; + let r = game.pieces[i] if (r >= first_region && r <= last_region) if (active_can_move_from_region(r)) - return true; + return true } for (let i = x; i < x + 10; ++i) { - let r = game.pieces[i]; + let r = game.pieces[i] if (r > 0 && r <= 100) - return true; + return true } if (player.events.nationalism) { for (let i = x; i < x + 10; ++i) { - let r = game.pieces[i]; + let r = game.pieces[i] if (r >= first_region && r <= last_region) if (active_can_move_from_region(r)) - return true; + return true } } - return false; + return false } states.move = { prompt() { if (game.selected >= 0) { - let here = game.pieces[game.selected]; + let here = game.pieces[game.selected] // Spy on a court card if (here <= 100) { - let c = here; - here = court_position_from_card(here); - view.prompt = `Move spy from #${c}.`; + let c = here + here = court_position_from_card(here) + view.prompt = `Move spy from #${c}.` - let last = last_court_position(); - let prev = here > 0 ? here - 1 : last; - let next = here < last ? here + 1 : 0; - gen_action('card', court_card_from_position(prev)); - gen_action('card', court_card_from_position(next)); + let last = last_court_position() + let prev = here > 0 ? here - 1 : last + let next = here < last ? here + 1 : 0 + gen_action('card', court_card_from_position(prev)) + gen_action('card', court_card_from_position(next)) if (active_has_well_connected()) { - let pprev = prev > 0 ? prev - 1 : last; - let nnext = next < last ? next + 1 : 0; - gen_action('card', court_card_from_position(pprev)); - gen_action('card', court_card_from_position(nnext)); + let pprev = prev > 0 ? prev - 1 : last + let nnext = next < last ? next + 1 : 0 + gen_action('card', court_card_from_position(pprev)) + gen_action('card', court_card_from_position(nnext)) } if (active_has_strange_bedfellows()) { - let r = cards[c].region; + let r = cards[c].region for (let p = 0; p < game.players.length; ++p) { - let court = game.players[p].court; + let court = game.players[p].court for (let i = 0; i < court.length; ++i) if (cards[court[i]].region === r) - gen_action('card', court[i]); + gen_action('card', court[i]) } } } @@ -1752,63 +1752,63 @@ states.move = { // Army or tribe in a region else { if (game.selected < 36) - view.prompt = `Move ${player.loyalty} army from ${region_names[here]}.`; + view.prompt = `Move ${player.loyalty} army from ${region_names[here]}.` else - view.prompt = `Move ${player_names[game.active]} tribe from ${region_names[here]}.`; - let supplies = active_has_indian_supplies(); + view.prompt = `Move ${player_names[game.active]} tribe from ${region_names[here]}.` + let supplies = active_has_indian_supplies() for (let next of roads[here]) if (supplies || can_army_move_across_border(here, next)) - gen_action('space', next); + gen_action('space', next) } } else { if (player.events.nationalism) { if (game.count === 1) - view.prompt = `Move up to ${game.count} spy, army, or tribe \u2014 select a spy, army, or tribe to move.`; + view.prompt = `Move up to ${game.count} spy, army, or tribe \u2014 select a spy, army, or tribe to move.` else - view.prompt = `Move up to ${game.count} spies, armies, and/or tribes \u2014 select a spy, army, or tribe to move.`; + view.prompt = `Move up to ${game.count} spies, armies, and/or tribes \u2014 select a spy, army, or tribe to move.` } else { if (game.count === 1) - view.prompt = `Move up to ${game.count} spy or army \u2014 select a spy or army to move.`; + view.prompt = `Move up to ${game.count} spy or army \u2014 select a spy or army to move.` else - view.prompt = `Move up to ${game.count} spies and/or armies \u2014 select a spy or army to move.`; + view.prompt = `Move up to ${game.count} spies and/or armies \u2014 select a spy or army to move.` } - gen_action('next'); - gen_select_army_to_move(); - gen_select_spy_to_move(); + gen_action('next') + gen_select_army_to_move() + gen_select_spy_to_move() if (player.events.nationalism) - gen_select_tribe_to_move(); + gen_select_tribe_to_move() } }, piece(x) { - push_undo(); - game.selected = x; + push_undo() + game.selected = x }, card(c) { - push_undo(); - let old = game.pieces[game.selected]; - logi(`Spy from #${old} to #${c}.`); - game.pieces[game.selected] = c; - game.selected = -1; + push_undo() + let old = game.pieces[game.selected] + logi(`Spy from #${old} to #${c}.`) + game.pieces[game.selected] = c + game.selected = -1 if (--game.count === 0) - end_action(); + end_action() }, space(s) { - push_undo(); - let old = game.pieces[game.selected]; - game.pieces[game.selected] = s; + push_undo() + let old = game.pieces[game.selected] + game.pieces[game.selected] = s if (game.selected < 36) { - logi(`${player.loyalty} army from ${region_names[old]} to ${region_names[s]}.`); + logi(`${player.loyalty} army from ${region_names[old]} to ${region_names[s]}.`) } else { - logi(`Tribe from ${region_names[old]} to ${region_names[s]}.`); - check_region_overthrow(game.active, old); + logi(`Tribe from ${region_names[old]} to ${region_names[s]}.`) + check_region_overthrow(game.active, old) } - game.selected = -1; + game.selected = -1 if (--game.count === 0) - end_action(); + end_action() }, next() { - push_undo(); - end_action(); + push_undo() + end_action() }, } @@ -1816,29 +1816,29 @@ states.move = { states.betray = { prompt() { - view.prompt = `Discard one court card where you have a spy.`; - let x = active_cylinders(); + view.prompt = `Discard one court card where you have a spy.` + let x = active_cylinders() for (let i = x; i < x + 10; ++i) { if (game.pieces[i] > 0 && game.pieces[i] <= 100) { - let c = game.pieces[i]; + let c = game.pieces[i] if (cards[c].suit !== Political) { - gen_action('card', c); + gen_action('card', c) } else { - let p = find_card_in_court(c); + let p = find_card_in_court(c) if (!player_has_bodyguards(p)) - gen_action('card', c); + gen_action('card', c) } } } }, card(c) { - push_undo(); - discard_court_card(c); + push_undo() + discard_court_card(c) if (cards[c].prize) { - game.card = c; - game.state = 'accept_prize'; + game.card = c + game.state = 'accept_prize' } else { - end_action(); + end_action() } }, } @@ -1846,19 +1846,19 @@ states.betray = { states.accept_prize = { inactive: "accept prize", prompt() { - view.prompt = `You may accept #${game.card} as ${a_coalition(cards[game.card].prize)} prize.`; - gen_action('accept'); - gen_action('refuse'); + view.prompt = `You may accept #${game.card} as ${a_coalition(cards[game.card].prize)} prize.` + gen_action('accept') + gen_action('refuse') }, accept() { - log(`Accepted ${cards[game.card].prize} prize.`); + log(`Accepted ${cards[game.card].prize} prize.`) if (cards[game.card].prize !== player.loyalty) - change_loyalty(cards[game.card].prize); - player.prizes ++; - end_action(); + change_loyalty(cards[game.card].prize) + player.prizes ++ + end_action() }, refuse() { - end_action(); + end_action() }, } @@ -1868,229 +1868,229 @@ function gen_battle_blocks(where) { if (player.loyalty !== Afghan) for (let i = 0; i < 12; ++i) if (game.pieces[i] === where) - gen_action('piece', i); + gen_action('piece', i) if (player.loyalty !== British) for (let i = 12; i < 24; ++i) if (game.pieces[i] === where) - gen_action('piece', i); + gen_action('piece', i) if (player.loyalty !== Russian) for (let i = 24; i < 36; ++i) if (game.pieces[i] === where) - gen_action('piece', i); + gen_action('piece', i) } function count_active_spies_on_card(where) { - let n = 0; - let x = active_cylinders(); + let n = 0 + let x = active_cylinders() for (let i = x; i < x + 10; ++i) if (game.pieces[i] === where) - ++n; - return n; + ++n + return n } function count_enemy_spies_on_card(where) { - let n = 0; + let n = 0 for (let p = 0; p < game.players.length; ++p) { if (p === game.active) - continue; + continue if (player_has_indispensable_advisors(p)) - continue; - let x = player_cylinders(p); + continue + let x = player_cylinders(p) for (let i = x; i < x + 10; ++i) { if (game.pieces[i] === where) - ++n; + ++n } } - return n; + return n } function count_player_armies_in_region(p, where) { - let n = 0; - let b = player_coalition_blocks(p); + let n = 0 + let b = player_coalition_blocks(p) for (let i = b; i < b + 12; ++i) if (game.pieces[i] === where) - ++n; - return n; + ++n + return n } function count_player_cylinders(p, r) { - let x = player_cylinders(p); - let n = 0; + let x = player_cylinders(p) + let n = 0 for (let i = x; i < x + 10; ++i) if (game.pieces[i] === r) - ++n; - return n; + ++n + return n } function count_active_armies_in_region(where) { - let n = count_player_armies_in_region(game.active, where); + let n = count_player_armies_in_region(game.active, where) if (player.events.nationalism) - n += count_player_cylinders(game.active, where); - return n; + n += count_player_cylinders(game.active, where) + return n } function count_enemy_blocks_on_border(where) { - let n = 0; + let n = 0 if (player.loyalty !== Afghan) for (let i = 0; i < 12; ++i) if (game.pieces[i] === where) - ++n; + ++n if (player.loyalty !== British) for (let i = 12; i < 24; ++i) if (game.pieces[i] === where) - ++n; + ++n if (player.loyalty !== Russian) for (let i = 24; i < 36; ++i) if (game.pieces[i] === where) - ++n; - return n; + ++n + return n } function count_enemy_tribes_and_blocks_in_region(where) { - let n = 0; + let n = 0 for (let p = 0; p < game.players.length; ++p) { if (game.players[p].loyalty === player.loyalty) - continue; + continue if (player_has_citadel(p, where)) - continue; - let x = player_cylinders(p); + continue + let x = player_cylinders(p) for (let i = x; i < x + 10; ++i) if (game.pieces[i] === where) - ++n; + ++n } if (player.loyalty !== Afghan) for (let i = 0; i < 12; ++i) if (game.pieces[i] === where) - ++n; + ++n if (player.loyalty !== British) for (let i = 12; i < 24; ++i) if (game.pieces[i] === where) - ++n; + ++n if (player.loyalty !== Russian) for (let i = 24; i < 36; ++i) if (game.pieces[i] === where) - ++n; + ++n for (let b of borders[where]) - n += count_enemy_blocks_on_border(b); - return n; + n += count_enemy_blocks_on_border(b) + return n } function is_battle_card(where) { - return count_active_spies_on_card(where) > 0 && count_enemy_spies_on_card(where) > 0; + return count_active_spies_on_card(where) > 0 && count_enemy_spies_on_card(where) > 0 } function is_battle_region(where) { - return count_active_armies_in_region(where) > 0 && count_enemy_tribes_and_blocks_in_region(where) > 0; + return count_active_armies_in_region(where) > 0 && count_enemy_tribes_and_blocks_in_region(where) > 0 } function piece_owner(x) { - if (x < 12) return "Afghan"; - if (x < 24) return "British"; - if (x < 36) return "Russian"; - if (x < 36+10) return player_names[0]; - if (x < 36+20) return player_names[1]; - if (x < 36+30) return player_names[2]; - if (x < 36+40) return player_names[3]; - if (x < 36+50) return player_names[4]; - return "undefined"; + if (x < 12) return "Afghan" + if (x < 24) return "British" + if (x < 36) return "Russian" + if (x < 36+10) return player_names[0] + if (x < 36+20) return player_names[1] + if (x < 36+30) return player_names[2] + if (x < 36+40) return player_names[3] + if (x < 36+50) return player_names[4] + return "undefined" } function active_can_battle() { for (let r = first_region; r <= last_region; ++r) { if (is_battle_region(r)) - return true; + return true } for (let p = 0; p < game.players.length; ++p) { - let court = game.players[p].court; + let court = game.players[p].court for (let i = 0; i < court.length; ++i) if (is_battle_card(court[i])) - return true; + return true } - return false; + return false } states.battle = { prompt() { if (game.where <= 0) { - view.prompt = `Start a battle in a single region or on a court card.`; + view.prompt = `Start a battle in a single region or on a court card.` for (let p = 0; p < game.players.length; ++p) { - let court = game.players[p].court; + let court = game.players[p].court for (let i = 0; i < court.length; ++i) { if (is_battle_card(court[i])) - gen_action('card', court[i]); + gen_action('card', court[i]) } } for (let r = first_region; r <= last_region; ++r) { if (is_battle_region(r)) - gen_action('space', r); + gen_action('space', r) } } else { - let where = game.where; + let where = game.where if (where >= first_region && where <= last_region) { - view.prompt = `Remove up to ${game.count} tribes, roads, or armies from ${region_names[where]}.`; - gen_battle_blocks(where); + view.prompt = `Remove up to ${game.count} tribes, roads, or armies from ${region_names[where]}.` + gen_battle_blocks(where) for (let border of borders[where]) - gen_battle_blocks(border); + gen_battle_blocks(border) for (let p = 0; p < game.players.length; ++p) { if (p !== game.active && game.players[p].loyalty !== player.loyalty && !player_has_citadel(p, where)) { - let x = player_cylinders(p); + let x = player_cylinders(p) for (let i = x; i < x + 10; ++i) if (game.pieces[i] === where) - gen_action('piece', i); + gen_action('piece', i) } } } else { - view.prompt = `Remove up to ${game.count} spies on #${where}.`; + view.prompt = `Remove up to ${game.count} spies on #${where}.` for (let p = 0; p < game.players.length; ++p) { if (p !== game.active && !player_has_indispensable_advisors(p)) { - let x = player_cylinders(p); + let x = player_cylinders(p) for (let i = x; i < x + 10; ++i) if (game.pieces[i] === where) - gen_action('piece', i); + gen_action('piece', i) } } } - gen_action('next'); + gen_action('next') } }, card(where) { - push_undo(); - //logi(`Battle on #${where}.`); - game.where = where; - game.count = Math.min(game.count, count_active_spies_on_card(where)); + push_undo() + //logi(`Battle on #${where}.`) + game.where = where + game.count = Math.min(game.count, count_active_spies_on_card(where)) }, space(s) { - push_undo(); - //logi(`Battle in ${region_names[s]}.`); - game.where = s; - game.count = Math.min(game.count, count_active_armies_in_region(s)); + push_undo() + //logi(`Battle in ${region_names[s]}.`) + game.where = s + game.count = Math.min(game.count, count_active_armies_in_region(s)) }, piece(x) { - push_undo(); - let where = game.pieces[x]; - game.pieces[x] = 0; + push_undo() + let where = game.pieces[x] + game.pieces[x] = 0 if (x < 36) { if (where >= first_region && where <= last_region) - logi(`Removed ${piece_owner(x)} army from ${region_names[where]}.`); + logi(`Removed ${piece_owner(x)} army from ${region_names[where]}.`) else - logi(`Removed ${piece_owner(x)} road from ${border_names[where]}.`); + logi(`Removed ${piece_owner(x)} road from ${border_names[where]}.`) } else { - let p = Math.floor((x - 36) / 10); + let p = Math.floor((x - 36) / 10) if (where <= 100) { - logi(`Removed ${piece_owner(x)} spy from #${where}.`); + logi(`Removed ${piece_owner(x)} spy from #${where}.`) if (player_has_safe_house(p)) - game.pieces[x] = Safe_House; + game.pieces[x] = Safe_House } else { - logi(`Removed ${piece_owner(x)} tribe from ${region_names[where]}.`); - check_region_overthrow(p, where); + logi(`Removed ${piece_owner(x)} tribe from ${region_names[where]}.`) + check_region_overthrow(p, where) } } if (--game.count === 0) - end_action(); + end_action() }, next() { - push_undo(); - end_action(); + push_undo() + end_action() } } @@ -2099,142 +2099,142 @@ states.battle = { function active_can_blackmail(r) { if ((r === Herat && active_has_blackmail_herat()) || (r === Kandahar && active_has_blackmail_kandahar())) { for (let p = 0; p < game.players.length; ++p) { - let court = game.players[p].court; + let court = game.players[p].court for (let i = 0; i < court.length; ++i) { - let c = court[i]; + let c = court[i] if (cards[c].region === r && card_has_no_spies(c)) - return true; + return true } } } - return false; + return false } states.blackmail = { prompt() { - let bmh = game.where !== Kandahar && active_can_blackmail(Herat); - let bmk = game.where !== Herat && active_can_blackmail(Kandahar); - let msg = ""; + let bmh = game.where !== Kandahar && active_can_blackmail(Herat) + let bmk = game.where !== Herat && active_can_blackmail(Kandahar) + let msg = "" if (bmh && bmk) - msg = "any Herat and/or Kandahar court card without a spy"; + msg = "any Herat and/or Kandahar court card without a spy" else if (bmh) - msg = "any Herat court card without a spy"; + msg = "any Herat court card without a spy" else - msg = "any Kandahar court card without a spy"; + msg = "any Kandahar court card without a spy" if (game.selected < 0) { - view.prompt = `Blackmail \u2014 select a spy to place on ${msg}.`; - gen_select_cylinder(); + view.prompt = `Blackmail \u2014 select a spy to place on ${msg}.` + gen_select_cylinder() } else { - let bmh = game.where !== Kandahar && active_can_blackmail(Herat); - let bmk = game.where !== Herat && active_can_blackmail(Kandahar); - view.prompt = `Blackmail \u2014 place a spy on ${msg}.`; + let bmh = game.where !== Kandahar && active_can_blackmail(Herat) + let bmk = game.where !== Herat && active_can_blackmail(Kandahar) + view.prompt = `Blackmail \u2014 place a spy on ${msg}.` for (let p = 0; p < game.players.length; ++p) { - let court = game.players[p].court; + let court = game.players[p].court for (let i = 0; i < court.length; ++i) { - let c = court[i]; + let c = court[i] if (bmh && cards[c].region === Herat && card_has_no_spies(c)) - gen_action('card', c); + gen_action('card', c) if (bmk && cards[c].region === Kandahar && card_has_no_spies(c)) - gen_action('card', c); + gen_action('card', c) } } } - gen_action('pass'); + gen_action('pass') }, piece(x) { - push_undo(); - game.selected = x; + push_undo() + game.selected = x }, card(c) { - push_undo(); - log(`Blackmail spy to #${c}.`); - game.pieces[game.selected] = c; - game.used_pieces.push(game.selected); + push_undo() + log(`Blackmail spy to #${c}.`) + game.pieces[game.selected] = c + game.used_pieces.push(game.selected) if (game.where < 0) { - game.where = (cards[c].region === Herat) ? Kandahar : Herat; - game.selected = select_available_cylinder(); + game.where = (cards[c].region === Herat) ? Kandahar : Herat + game.selected = select_available_cylinder() } else { - resume_actions(); + resume_actions() } }, pass() { - push_undo(); - resume_actions(); + push_undo() + resume_actions() }, } // PASSIVE: SAFEHOUSE function check_safe_house() { - let first = game.phasing; + let first = game.phasing for (let p = first; p < game.players.length; ++p) if (check_player_safe_house(p)) - return; + return for (let p = 0; p < first; ++p) if (check_player_safe_house(p)) - return; + return if (game.actions >= 0) - resume_actions(); + resume_actions() else - goto_cleanup_hand(); + goto_cleanup_hand() } function check_player_safe_house(p) { - let x = player_cylinders(p); + let x = player_cylinders(p) for (let i = x; i < x + 10; ++i) { if (game.pieces[i] === Safe_House) { if (player_has_safe_house(p)) { - set_active(p); - logbr(); - game.state = 'safe_house'; - game.selected = i; - return true; + set_active(p) + logbr() + game.state = 'safe_house' + game.selected = i + return true } else { - game.pieces[i] = 0; + game.pieces[i] = 0 } } } - return false; + return false } states.safe_house = { inactive: "safe house", prompt() { - view.prompt = `Safe House \u2014 you may place your killed spy on a Safe House.`; + view.prompt = `Safe House \u2014 you may place your killed spy on a Safe House.` if (player.court.indexOf(SAFE_HOUSE_1) >= 0) - gen_action('card', SAFE_HOUSE_1); + gen_action('card', SAFE_HOUSE_1) if (player.court.indexOf(SAFE_HOUSE_2) >= 0) - gen_action('card', SAFE_HOUSE_2); - gen_action('pass'); + gen_action('card', SAFE_HOUSE_2) + gen_action('pass') }, card(c) { - push_undo(); - log(`${player_names[game.active]} spy to #${c}.`); - game.pieces[game.selected] = c; - game.selected = -1; - check_safe_house(); + push_undo() + log(`${player_names[game.active]} spy to #${c}.`) + game.pieces[game.selected] = c + game.selected = -1 + check_safe_house() }, pass() { - push_undo(); - game.pieces[game.selected] = 0; - game.selected = -1; - check_safe_house(); + push_undo() + game.pieces[game.selected] = 0 + game.selected = -1 + check_safe_house() }, } // PASSIVE: INSURRECTION function check_insurrection() { - let prince = which_player_has_insurrection(); + let prince = which_player_has_insurrection() if (prince >= 0) { - logbr(); - log(`Prince Akbar Khan`); - game.count = 2; - game.selected = select_afghan_block(); - set_active(prince); - game.state = 'insurrection'; + logbr() + log(`Prince Akbar Khan`) + game.count = 2 + game.selected = select_afghan_block() + set_active(prince) + game.state = 'insurrection' } else { - end_dominance_check(); + end_dominance_check() } } @@ -2242,165 +2242,165 @@ states.insurrection = { prompt() { if (game.count > 0) { if (game.selected < 0) { - view.prompt = `Insurrection \u2014 select an Afghan block to move.`; - gen_select_block(); + view.prompt = `Insurrection \u2014 select an Afghan block to move.` + gen_select_block() } else { - view.prompt = `Insurrection \u2014 place Afghan army in Kabul.`; - gen_action('space', Kabul); + view.prompt = `Insurrection \u2014 place Afghan army in Kabul.` + gen_action('space', Kabul) } } else { - view.prompt = `Insurrection \u2014 done.`; - gen_action('next'); + view.prompt = `Insurrection \u2014 done.` + gen_action('next') } }, piece(x) { - push_undo(); - game.selected = x; + push_undo() + game.selected = x }, space() { - push_undo(); - logi(`Afghan army to Kabul.`); - game.pieces[game.selected] = Kabul; - game.selected = -1; + push_undo() + logi(`Afghan army to Kabul.`) + game.pieces[game.selected] = Kabul + game.selected = -1 if (--game.count > 0) - game.selected = select_available_block(); + game.selected = select_available_block() }, next() { - push_undo(); - end_dominance_check(); + push_undo() + end_dominance_check() } } // CLEANUP function player_court_size() { - let stars = 3; + let stars = 3 for (let i = 0; i < player.court.length; ++i) { - let c = player.court[i]; + let c = player.court[i] if (cards[c].suit === Political) - stars += cards[c].rank; + stars += cards[c].rank } - return stars; + return stars } function player_hand_size() { - let stars = 2; + let stars = 2 for (let i = 0; i < player.court.length; ++i) { - let c = player.court[i]; + let c = player.court[i] if (cards[c].suit === Intelligence) - stars += cards[c].rank; + stars += cards[c].rank } - return stars; + return stars } function goto_cleanup_court() { - game.actions = -1; - logbr(); + game.actions = -1 + logbr() if (player.court.length > player_court_size()) { - game.state = 'cleanup_court'; + game.state = 'cleanup_court' } else { - goto_cleanup_hand(); + goto_cleanup_hand() } } states.cleanup_court = { inactive: "cleanup court", prompt() { - let size = player_court_size(); + let size = player_court_size() if (player.court.length <= size) { - view.prompt = `Discard cards in your court until you are within your limit \u2014 done.`; - gen_action('next'); + view.prompt = `Discard cards in your court until you are within your limit \u2014 done.` + gen_action('next') } else { - view.prompt = `Discard cards in your court until you are within your limit (${size}).`; + view.prompt = `Discard cards in your court until you are within your limit (${size}).` for (let i = 0; i < player.court.length; ++i) - gen_action('card', player.court[i]); + gen_action('card', player.court[i]) } }, card(c) { - push_undo(); - discard_court_card(c); + push_undo() + discard_court_card(c) }, next() { - push_undo(); - check_leverage(); + push_undo() + check_leverage() } } function goto_cleanup_hand() { if (player.hand.length > player_hand_size()) { - game.state = 'cleanup_hand'; + game.state = 'cleanup_hand' } else { - goto_discard_events(); + goto_discard_events() } } states.cleanup_hand = { inactive: "cleanup hand", prompt() { - let size = player_hand_size(); + let size = player_hand_size() if (player.hand.length <= size) { - view.prompt = `Discard cards in your hand until you are within your limit \u2014 done.`; - gen_action('next'); + view.prompt = `Discard cards in your hand until you are within your limit \u2014 done.` + gen_action('next') } else { - view.prompt = `Discard cards in your hand until you are within your limit (${size}).`; + view.prompt = `Discard cards in your hand until you are within your limit (${size}).` for (let i = 0; i < player.hand.length; ++i) - gen_action('card', player.hand[i]); + gen_action('card', player.hand[i]) } }, card(c) { - push_undo(); - log(`Discarded #${c} from hand.`); - remove_from_array(player.hand, c); + push_undo() + log(`Discarded #${c} from hand.`) + remove_from_array(player.hand, c) }, next() { - push_undo(); - goto_discard_events(); + push_undo() + goto_discard_events() } } function goto_discard_events() { if (is_event_card(game.market_cards[0][0]) || is_event_card(game.market_cards[1][0])) { - game.state = 'discard_events'; + game.state = 'discard_events' } else { - goto_refill_market(); + goto_refill_market() } } function do_discard_event(row, c) { - game.market_cards[row][0] = 0; - logbr(); - log(`Discarded #${c}.`); + game.market_cards[row][0] = 0 + logbr() + log(`Discarded #${c}.`) if (is_dominance_check(c)) { - do_dominance_check('discard'); + do_dominance_check('discard') } else { - events_if_discarded[cards[c].if_discarded](row); + events_if_discarded[cards[c].if_discarded](row) } } states.discard_events = { inactive: "discard event cards", prompt() { - view.prompt = `Discard any event cards in the leftmost column of the market.`; + view.prompt = `Discard any event cards in the leftmost column of the market.` if (is_event_card(game.market_cards[0][0])) - gen_action('card', game.market_cards[0][0]); + gen_action('card', game.market_cards[0][0]) else if (is_event_card(game.market_cards[1][0])) - gen_action('card', game.market_cards[1][0]); + gen_action('card', game.market_cards[1][0]) }, card(c) { - push_undo(); + push_undo() if (c === game.market_cards[0][0]) - do_discard_event(0, c); + do_discard_event(0, c) else - do_discard_event(1, c); + do_discard_event(1, c) }, } function discard_instability_cards() { for (let row = 0; row < 2; ++row) { for (let col = 0; col < 6; ++col) { - let c = game.market_cards[row][col]; + let c = game.market_cards[row][col] if (is_dominance_check(c)) - game.market_cards[row][col] = 0; + game.market_cards[row][col] = 0 } } } @@ -2408,17 +2408,17 @@ function discard_instability_cards() { function goto_refill_market() { // Move all cards (and their rupees) to the left. for (let row = 0; row < 2; ++row) { - let row_cards = game.market_cards[row]; - let row_coins = game.market_coins[row]; + let row_cards = game.market_cards[row] + let row_coins = game.market_coins[row] for (let to = 0; to < 6; ++to) { if (row_cards[to] === 0) { for (let from = to + 1; from < 6; ++from) { if (row_cards[from] > 0) { - row_cards[to] = row_cards[from]; - row_cards[from] = 0; - row_coins[to] += row_coins[from]; - row_coins[from] = 0; - break; + row_cards[to] = row_cards[from] + row_cards[from] = 0 + row_coins[to] += row_coins[from] + row_coins[from] = 0 + break } } } @@ -2426,52 +2426,52 @@ function goto_refill_market() { } // Instability ... - let instability = 0; + let instability = 0 for (let row = 0; row < 2; ++row) { for (let col = 0; col < 6; ++col) { - let c = game.market_cards[row][col]; + let c = game.market_cards[row][col] if (is_dominance_check(c)) - ++instability; + ++instability } } - clear_undo(); + clear_undo() // Fill with new cards from left (top row in each column first) for (let col = 0; col < 6; ++col) { for (let row = 0; row < 2; ++row) { if (game.deck.length > 0) { if (game.market_cards[row][col] === 0) { - let c = game.deck.pop(); - game.market_cards[row][col] = c; + let c = game.deck.pop() + game.market_cards[row][col] = c if (instability > 0 && is_dominance_check(c)) { - game.state = 'instability'; - return; + game.state = 'instability' + return } } } } } - goto_next_player(); + goto_next_player() } states.instability = { prompt() { - view.prompt = "Instability \u2014 perform a Dominance Check immediately."; + view.prompt = "Instability \u2014 perform a Dominance Check immediately." for (let row = 0; row < 2; ++row) { for (let col = 0; col < 6; ++col) { - let c = game.market_cards[row][col]; + let c = game.market_cards[row][col] if (is_dominance_check(c)) - gen_action('card', c); + gen_action('card', c) } } }, - card(c) { - logbr(); - log(`Instability!`); - discard_instability_cards(); - do_dominance_check('instability'); + card() { + logbr() + log(`Instability!`) + discard_instability_cards() + do_dominance_check('instability') } } @@ -2480,121 +2480,121 @@ states.instability = { const events_if_discarded = { "Military" () { - goto_favored_suit_event(Military); + goto_favored_suit_event(Military) }, "Embarrassment of Riches" () { - game.events.embarrassment_of_riches = 1; - goto_discard_events(); + game.events.embarrassment_of_riches = 1 + goto_discard_events() }, "Disregard for Customs" () { - game.events.disregard_for_customs = 1; - goto_discard_events(); + game.events.disregard_for_customs = 1 + goto_discard_events() }, "Failure to Impress" () { - logi("Discarded all loyalty prizes."); + logi("Discarded all loyalty prizes.") for (let p = 0; p < game.players.length; ++p) - game.players[p].prizes = 0; - goto_discard_events(); + game.players[p].prizes = 0 + goto_discard_events() }, "Riots in Punjab" () { - goto_riots(Punjab); + goto_riots(Punjab) }, "Riots in Herat" () { - goto_riots(Herat); + goto_riots(Herat) }, "No effect" () { - logi("No effect."); - goto_discard_events(); + logi("No effect.") + goto_discard_events() }, "Riots in Kabul" () { - goto_riots(Kabul); + goto_riots(Kabul) }, "Riots in Persia" () { - goto_riots(Persia); + goto_riots(Persia) }, "Confidence Failure" () { - game.state = 'confidence_failure'; + game.state = 'confidence_failure' if (player.hand.length === 0) - next_confidence_failure(); + next_confidence_failure() }, "Intelligence" () { - goto_favored_suit_event(Intelligence); + goto_favored_suit_event(Intelligence) }, "Political" () { - goto_favored_suit_event(Political); + goto_favored_suit_event(Political) }, } function goto_favored_suit_event(suit) { - game.state = 'favored_suit'; - game.where = suit; + game.state = 'favored_suit' + game.where = suit } states.favored_suit = { inactive: "favored suit", prompt() { - view.prompt = `Change the favored suit to ${game.where}.`; - gen_action('suit', game.where); + view.prompt = `Change the favored suit to ${game.where}.` + gen_action('suit', game.where) }, suit(suit) { - logi(`Favored suit to ${suit}.`); - game.favored = suit; - goto_discard_events(); + logi(`Favored suit to ${suit}.`) + game.favored = suit + goto_discard_events() }, } function goto_riots(where) { - game.state = 'riots'; - game.where = where; + game.state = 'riots' + game.where = where } states.riots = { prompt() { - view.prompt = `Riot in ${region_names[game.where]}.`; - gen_action('space', game.where); + view.prompt = `Riot in ${region_names[game.where]}.` + gen_action('space', game.where) }, space(s) { - remove_all_tribes_and_armies(s); - goto_discard_events(); + remove_all_tribes_and_armies(s) + goto_discard_events() }, } states.confidence_failure = { inactive: "confidence failure", prompt() { - view.prompt = "Confidence Failure \u2014 discard a card from your hand."; + view.prompt = "Confidence Failure \u2014 discard a card from your hand." for (let i = 0; i < player.hand.length; ++i) - gen_action('card', player.hand[i]); + gen_action('card', player.hand[i]) }, card(c) { - log(`${player_names[game.active]} discarded #${c} from hand.`); - remove_from_array(player.hand, c); - next_confidence_failure(); + log(`${player_names[game.active]} discarded #${c} from hand.`) + remove_from_array(player.hand, c) + next_confidence_failure() }, } function next_confidence_failure() { - let next = game.active; + let next = game.active for (let i = 0; i < 10; ++i) { - next = next_player(next); + next = next_player(next) if (next === game.phasing) - return goto_discard_events(); + return goto_discard_events() if (game.players[next].hand.length > 0) - return set_active(next); + return set_active(next) } - throw new Error("FAIL"); + throw new Error("FAIL") } // EVENTS: IF PURCHASED @@ -2602,58 +2602,58 @@ function next_confidence_failure() { const events_if_purchased = { "New Tactics" () { - player.events.new_tactics = 1; - end_action(); + player.events.new_tactics = 1 + end_action() }, "Koh-i-noor Recovered" () { - player.events.koh_i_noor = 1; - end_action(); + player.events.koh_i_noor = 1 + end_action() }, "Courtly Manners" () { - player.events.courtly_manners = 1; - end_action(); + player.events.courtly_manners = 1 + end_action() }, "Rumor" () { - game.state = 'rumor'; + game.state = 'rumor' }, "Conflict Fatigue" () { - game.events.conflict_fatigue = 1; - end_action(); + game.events.conflict_fatigue = 1 + end_action() }, "Nationalism" () { - player.events.nationalism = 1; - end_action(); + player.events.nationalism = 1 + end_action() }, "Public Withdrawal" () { - throw new Error("cannot purchase"); + throw new Error("cannot purchase") }, "Nation Building" () { - player.events.nation_building = 1; - end_action(); + player.events.nation_building = 1 + end_action() }, "Backing of Persian Aristocracy" () { - player.coins += 3; - end_action(); + player.coins += 3 + end_action() }, "Other Persuasive Methods" () { - game.state = 'other_persuasive_methods'; + game.state = 'other_persuasive_methods' }, "Pashtunwali Values" () { - game.state = 'pashtunwali_values'; + game.state = 'pashtunwali_values' }, "Rebuke" () { - game.state = 'rebuke'; + game.state = 'rebuke' }, } @@ -2667,375 +2667,375 @@ function check_public_withdrawal() { for (let row = 0; row < 2; ++row) for (let col = 0; col < 6; ++col) if (game.market_cards[row][col] === PUBLIC_WITHDRAWAL) - game.market_coins[row][col] = 0; + game.market_coins[row][col] = 0 } states.rumor = { prompt() { - view.prompt = `Rumor \u2014 choose a player.`; + view.prompt = `Rumor \u2014 choose a player.` for (let p = 0; p < game.players.length; ++p) if (p !== game.active) - gen_action('player_' + p); + gen_action('player_' + p) }, - player_0() { do_rumor(0); }, - player_1() { do_rumor(1); }, - player_2() { do_rumor(2); }, - player_3() { do_rumor(3); }, - player_4() { do_rumor(4); }, + player_0() { do_rumor(0) }, + player_1() { do_rumor(1) }, + player_2() { do_rumor(2) }, + player_3() { do_rumor(3) }, + player_4() { do_rumor(4) }, } function do_rumor(p) { - push_undo(); - log(`${player_names[game.active]} chose ${player_names[p]} for Rumor.`); - game.players[p].events.rumor = 1; - end_action(); + push_undo() + log(`${player_names[game.active]} chose ${player_names[p]} for Rumor.`) + game.players[p].events.rumor = 1 + end_action() } states.other_persuasive_methods = { inactive: "other persuasive methods", prompt() { - view.prompt = `Other Persuasive Methods \u2014 exchange your hand with another player.`; + view.prompt = `Other Persuasive Methods \u2014 exchange your hand with another player.` for (let p = 0; p < game.players.length; ++p) if (p !== game.active) - gen_action('player_' + p); + gen_action('player_' + p) }, - player_0() { do_other_persuasive_methods(0); }, - player_1() { do_other_persuasive_methods(1); }, - player_2() { do_other_persuasive_methods(2); }, - player_3() { do_other_persuasive_methods(3); }, - player_4() { do_other_persuasive_methods(4); }, + player_0() { do_other_persuasive_methods(0) }, + player_1() { do_other_persuasive_methods(1) }, + player_2() { do_other_persuasive_methods(2) }, + player_3() { do_other_persuasive_methods(3) }, + player_4() { do_other_persuasive_methods(4) }, } function do_other_persuasive_methods(p) { if (game.open) - push_undo(); + push_undo() else - clear_undo(); // No undo if closed hands. - log(`${player_names[game.active]} exchanged hands with ${player_names[p]}.`); - let swap = game.players[game.active].hand; - game.players[game.active].hand = game.players[p].hand; - game.players[p].hand = swap; - end_action(); + clear_undo() // No undo if closed hands. + log(`${player_names[game.active]} exchanged hands with ${player_names[p]}.`) + let swap = game.players[game.active].hand + game.players[game.active].hand = game.players[p].hand + game.players[p].hand = swap + end_action() } states.pashtunwali_values = { inactive: "Pastunwali values", prompt() { - view.prompt = `Pashtunwali Values \u2014 choose a suit to favor.`; - gen_action('suit', Political); - gen_action('suit', Intelligence); - gen_action('suit', Economic); - gen_action('suit', Military); + view.prompt = `Pashtunwali Values \u2014 choose a suit to favor.` + gen_action('suit', Political) + gen_action('suit', Intelligence) + gen_action('suit', Economic) + gen_action('suit', Military) }, suit(suit) { - log(`Favored suit to ${suit}.`); - game.favored = suit; - game.events.pashtunwali_values = 1; - end_action(); + log(`Favored suit to ${suit}.`) + game.favored = suit + game.events.pashtunwali_values = 1 + end_action() }, } states.rebuke = { prompt() { - view.prompt = `Rebuke \u2014 remove all tribes and armies in a single region.`; + view.prompt = `Rebuke \u2014 remove all tribes and armies in a single region.` for (let s = first_region; s <= last_region; ++s) // TODO: can pick empty region? - gen_action('space', s); + gen_action('space', s) }, space(s) { - push_undo(); - remove_all_tribes_and_armies(s); - end_action(); + push_undo() + remove_all_tribes_and_armies(s) + end_action() }, } // DOMINANCE CHECK function count_cylinders_in_play(p) { - let n = 0; - let x = player_cylinders(p); + let n = 0 + let x = player_cylinders(p) for (let i = x; i < x + 10; ++i) if (game.pieces[i] > 0) - ++n; - return n; + ++n + return n } function count_influence_points(p) { - let n = 1 + game.players[p].prizes; - let x = player_cylinders(p); + let n = 1 + game.players[p].prizes + let x = player_cylinders(p) if (!game.events.embarrassment_of_riches) { - let gv = game.players[p].events.koh_i_noor ? 2 : 1; + let gv = game.players[p].events.koh_i_noor ? 2 : 1 for (let i = x; i < x + 10; ++i) { - let s = game.pieces[i]; + let s = game.pieces[i] if (s === Gift2 || s === Gift4 || s === Gift6) - n += gv; + n += gv } } if (!game.players[p].events.rumor) { - let court = game.players[p].court; + let court = game.players[p].court for (let i = 0; i < court.length; ++i) if (cards[court[i]].patriot) - ++n; + ++n } - return n; + return n } function assign_vp(points, score, sorted) { - const PLACE = [ "1st", "2nd", "3rd" ]; - let place = 0; - sorted.sort((a,b) => b-a); + const PLACE = [ "1st", "2nd", "3rd" ] + let place = 0 + sorted.sort((a,b) => b-a) while (points.length > 0 && sorted.length > 0) { - let n = 0; + let n = 0 for (let p = 0; p < game.players.length; ++p) if (score[p] === sorted[0]) - ++n; - let v = 0; + ++n + let v = 0 for (let i = 0; i < n; ++i) - v += points[i] | 0; - v = Math.floor(v / n); - let msg = `${PLACE[place]} place:`; + v += points[i] | 0 + v = Math.floor(v / n) + let msg = `${PLACE[place]} place:` for (let p = 0; p < game.players.length; ++p) { if (score[p] === sorted[0]) { - msg += "\n" + player_names[p] + " scored " + v + " vp."; - game.players[p].vp += v; + msg += "\n" + player_names[p] + " scored " + v + " vp." + game.players[p].vp += v } } - log(msg); - points = points.slice(n); - sorted = sorted.slice(n); - place += n; + log(msg) + points = points.slice(n) + sorted = sorted.slice(n) + place += n } } function count_dominance_cards() { - let n = 0; + let n = 0 for (let row = 0; row < 2; ++row) for (let col = 0; col < 6; ++col) if (is_dominance_check(game.market_cards[row][col])) - ++n; + ++n for (let i = 0; i < game.deck.length; ++i) if (is_dominance_check(game.deck[i])) - ++n; - return n; + ++n + return n } function is_final_dominance_check() { for (let row = 0; row < 2; ++row) for (let col = 0; col < 6; ++col) if (is_dominance_check(game.market_cards[row][col])) - return false; + return false for (let i = 0; i < game.deck.length; ++i) if (is_dominance_check(game.deck[i])) - return false; - return true; + return false + return true } function rank_score(a, b) { - return parseInt(b) - parseInt(a); + return parseInt(b) - parseInt(a) } function do_dominance_check(reason) { - let n_afghan = 0; - let n_british = 0; - let n_russian = 0; - let success = null; + let n_afghan = 0 + let n_british = 0 + let n_russian = 0 + let success = null for (let i = 0; i < 12; ++i) { if (game.pieces[i] > 0) - n_afghan ++; + n_afghan ++ if (game.pieces[i+12] > 0) - n_british ++; + n_british ++ if (game.pieces[i+24] > 0) - n_russian ++; + n_russian ++ } logi(n_afghan + " Afghan block" + (n_afghan !== 1 ? "s," : ",")) logi(n_british + " British block" + (n_british !== 1 ? "s," : ",")) logi(n_russian + " Russian block" + (n_russian !== 1 ? "s." : ".")) - let limit = game.events.conflict_fatigue ? 2 : 4; + let limit = game.events.conflict_fatigue ? 2 : 4 if (n_afghan >= n_british+limit && n_afghan >= n_russian+limit) - success = Afghan; + success = Afghan else if (n_british >= n_afghan+limit && n_british >= n_russian+limit) - success = British; + success = British else if (n_russian >= n_british+limit && n_russian >= n_afghan+limit) - success = Russian; + success = Russian - let final = is_final_dominance_check(); + let final = is_final_dominance_check() - let score = new Array(game.players.length).fill(0); + let score = new Array(game.players.length).fill(0) if (success) { - logbr(); - log(`.dc.${success} Dominant ${success} Coalition`); - logbr(); + logbr() + log(`.dc.${success} Dominant ${success} Coalition`) + logbr() if (final) - log(`Final Dominance Check.`); - let list = []; + log(`Final Dominance Check.`) + let list = [] for (let p = 0; p < game.players.length; ++p) { if (game.players[p].loyalty === success) { - score[p] = count_influence_points(p); - list.push(`${score[p]} ${player_names[p]} influence`); + score[p] = count_influence_points(p) + list.push(`${score[p]} ${player_names[p]} influence`) } } - list.sort(rank_score); - log("Ranking:\n" + list.join(",\n") + "."); + list.sort(rank_score) + log("Ranking:\n" + list.join(",\n") + ".") if (final) - assign_vp([10, 6, 2], score, score.filter(x=>x>0)); + assign_vp([10, 6, 2], score, score.filter(x=>x>0)) else - assign_vp([5, 3, 1], score, score.filter(x=>x>0)); + assign_vp([5, 3, 1], score, score.filter(x=>x>0)) } else { - logbr(); - log(`.dc.unsuccessful Unsuccessful Check`); - logbr(); + logbr() + log(`.dc.unsuccessful Unsuccessful Check`) + logbr() if (final) - log(`Final Dominance Check.`); - let list = []; + log(`Final Dominance Check.`) + let list = [] for (let p = 0; p < game.players.length; ++p) { - score[p] = count_cylinders_in_play(p); + score[p] = count_cylinders_in_play(p) if (score[p] !== 1) - list.push(`${score[p]} ${player_names[p]} cylinders`); + list.push(`${score[p]} ${player_names[p]} cylinders`) else - list.push(`${score[p]} ${player_names[p]} cylinder`); + list.push(`${score[p]} ${player_names[p]} cylinder`) } - list.sort(rank_score); - log("Ranking:\n" + list.join(",\n") + "."); + list.sort(rank_score) + log("Ranking:\n" + list.join(",\n") + ".") if (final) - assign_vp([6, 2], score, score.slice()); + assign_vp([6, 2], score, score.slice()) else - assign_vp([3, 1], score, score.slice()); + assign_vp([3, 1], score, score.slice()) } // Clear the board. if (success) { for (let i = 0; i < 36; ++i) - game.pieces[i] = 0; + game.pieces[i] = 0 } // Check instant victory - let vps = game.players.map(pp => pp.vp).sort((a,b)=>b-a); + let vps = game.players.map(pp => pp.vp).sort((a,b)=>b-a) if (vps[0] >= vps[1] + 4) - return goto_pause_game_over(); + return goto_pause_game_over() if (final) - return goto_pause_game_over(); + return goto_pause_game_over() - game.events = {}; + game.events = {} for (let p = 0; p < game.players.length; ++p) - game.players[p].events = {}; + game.players[p].events = {} - game.where = reason; + game.where = reason - check_insurrection(); + check_insurrection() } function end_dominance_check() { - set_active(game.phasing); + set_active(game.phasing) if (game.state === 'game_over') - return; + return switch (game.where) { case 'discard': - return goto_discard_events(); + return goto_discard_events() case 'purchase': - return resume_actions(); + return resume_actions() case 'instability': - return goto_refill_market(); + return goto_refill_market() } } function vp_tie(pp) { - let court = pp.court; - let stars = 0; + let court = pp.court + let stars = 0 for (let i = 0; i < court.length; ++i) { - let c = court[i]; + let c = court[i] if (cards[c].suit === Military) - stars += cards[c].rank; + stars += cards[c].rank } - return pp.vp * 10000 + stars * 100 + pp.coins; + return pp.vp * 10000 + stars * 100 + pp.coins } function compute_victory() { - let vps = game.players.map((pp,i) => [vp_tie(pp),i]).sort((a,b)=>b[0]-a[0]); - let result = []; + let vps = game.players.map((pp,i) => [vp_tie(pp),i]).sort((a,b)=>b[0]-a[0]) + let result = [] for (let i = 0; i < vps.length; ++i) if (vps[i][0] === vps[0][0]) result.push(player_names[vps[i][1]]) - game.result = result.join(", "); - game.victory = result.join(" and ") + " won!"; - logbr(); - log(game.victory); + game.result = result.join(", ") + game.victory = result.join(" and ") + " won!" + logbr() + log(game.victory) } function goto_pause_game_over() { - compute_victory(); + compute_victory() if (game.undo && game.undo.length > 0) - game.state = 'pause_game_over'; + game.state = 'pause_game_over' else - game.state = 'game_over'; + game.state = 'game_over' } function goto_game_over() { - compute_victory(); - game.state = 'game_over'; - game.active = 5; + compute_victory() + game.state = 'game_over' + game.active = 5 } states.pause_game_over = { inactive: "game over", prompt() { - view.prompt = game.victory; - gen_action('end_game'); + view.prompt = game.victory + gen_action('end_game') }, end_game() { - game.state = 'game_over'; - game.active = 5; + game.state = 'game_over' + game.active = 5 } } // SETUP function prepare_deck() { - let court_cards = []; + let court_cards = [] for (let i = 1; i <= 100; ++i) - court_cards.push(i); + court_cards.push(i) - let event_cards = []; + let event_cards = [] for (let i = 105; i <= 116; ++i) - event_cards.push(i); + event_cards.push(i) - let piles = [ [], [], [], [], [], [] ]; + let piles = [ [], [], [], [], [], [] ] - shuffle(court_cards); + shuffle(court_cards) for (let i = 0; i < 6; ++i) for (let k = 0; k < 5 + game.players.length; ++k) - piles[i].push(court_cards.pop()); + piles[i].push(court_cards.pop()) // Leftmost pile is 5, rightmost pile is 0 - piles[3].push(101); - piles[2].push(102); - piles[1].push(103); - piles[0].push(104); + piles[3].push(101) + piles[2].push(102) + piles[1].push(103) + piles[0].push(104) - shuffle(event_cards); + shuffle(event_cards) - piles[4].push(event_cards.pop()); - piles[4].push(event_cards.pop()); - piles[3].push(event_cards.pop()); - piles[2].push(event_cards.pop()); - piles[1].push(event_cards.pop()); - piles[0].push(event_cards.pop()); + piles[4].push(event_cards.pop()) + piles[4].push(event_cards.pop()) + piles[3].push(event_cards.pop()) + piles[2].push(event_cards.pop()) + piles[1].push(event_cards.pop()) + piles[0].push(event_cards.pop()) for (let i = 0; i < 6; ++i) - shuffle(piles[i]); + shuffle(piles[i]) - game.deck = piles.flat(); + game.deck = piles.flat() } exports.setup = function (seed, scenario, options) { - let player_count = scenario_player_count[scenario]; + let player_count = scenario_player_count[scenario] game = { seed: seed, @@ -3071,7 +3071,7 @@ exports.setup = function (seed, scenario, options) { log: [], undo: [], - }; + } for (let i = 0; i < player_count; ++i) { game.players[i] = { @@ -3085,58 +3085,58 @@ exports.setup = function (seed, scenario, options) { } } - prepare_deck(); + prepare_deck() for (let col = 0; col < 6; ++col) for (let row = 0; row < 2; ++row) - game.market_cards[row][col] = game.deck.pop(); + game.market_cards[row][col] = game.deck.pop() // Starting loyalty, starting with a random player. - game.state = 'loyalty'; - game.active = random(player_count); + game.state = 'loyalty' + game.active = random(player_count) - return save_game(); + return save_game() } function load_game(state) { - game = state; - game.active = player_index[game.active]; - update_aliases(); + game = state + game.active = player_index[game.active] + update_aliases() } function save_game() { - game.active = player_names[game.active]; - return game; + game.active = player_names[game.active] + return game } exports.action = function (state, current, action, arg) { - load_game(state); - let S = states[game.state]; + load_game(state) + let S = states[game.state] if (action in S) { - S[action](arg, current); + S[action](arg, current) } else { if (action === 'undo' && game.undo && game.undo.length > 0) - pop_undo(); + pop_undo() else - throw new Error("Invalid action: " + action); + throw new Error("Invalid action: " + action) } - return save_game(); + return save_game() } exports.resign = function (state, current) { - load_game(state); - logbr(); - log(`${current} resigned.`); - goto_game_over(); - game.victory = `${current} resigned.`; - return save_game(); + load_game(state) + logbr() + log(`${current} resigned.`) + goto_game_over() + game.victory = `${current} resigned.` + return save_game() } -exports.is_checkpoint = (a, b) => a.phasing !== b.phasing; +exports.is_checkpoint = (a, b) => a.phasing !== b.phasing -exports.view = function(state, current) { - current = player_index[current]; - load_game(state); +exports.view = function (state, current) { + current = player_index[current] + load_game(state) view = { log: game.log, @@ -3151,23 +3151,23 @@ exports.view = function(state, current) { selected: game.selected, cards: [ game.deck.length, count_dominance_cards() ], open: game.open, - }; + } if (game.state === 'game_over') { - view.prompt = game.victory; + view.prompt = game.victory } else if (current === 'Observer' || game.active !== current) { - let inactive = states[game.state].inactive || game.state; - view.prompt = `Waiting for ${player_names[game.active]} \u2014 ${inactive}...`; + let inactive = states[game.state].inactive || game.state + view.prompt = `Waiting for ${player_names[game.active]} \u2014 ${inactive}...` } else { view.actions = {} - states[game.state].prompt(); - view.prompt = player_names[game.active] + ": " + view.prompt; + states[game.state].prompt() + view.prompt = player_names[game.active] + ": " + view.prompt if (game.undo && game.undo.length > 0) - view.actions.undo = 1; + view.actions.undo = 1 else - view.actions.undo = 0; + view.actions.undo = 0 } - save_game(); - return view; + save_game() + return view } -- cgit v1.2.3