"use strict"; // CONSTANTS const player_names = [ "Gray", "Blue", "Tan", "Red", "Black" ]; 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, "Transcaspia": Transcaspia, "Herat": Herat, "Kabul": Kabul, "Kandahar": Kandahar, "Punjab": Punjab, }; const region_names = { [Persia]: "Persia", [Transcaspia]: "Transcaspia", [Herat]: "Herat", [Kabul]: "Kabul", [Kandahar]: "Kandahar", [Punjab]: "Punjab", }; cards.forEach(card => { if (card) { card.region = region_index[card.region]; if (card.name === 'EVENT') card.name = card.if_discarded + " / " + card.if_purchased; } }); const event_cards = { new_tactics: 105, koh_i_noor: 106, courtly_manners: 107, rumor: 108, conflict_fatigue: 109, nationalism: 110, nation_building: 112, pashtunwali_values: 115, embarrassment_of_riches: 106, disregard_for_customs: 107, }; const VP_OFFSET = [ [-16, -16], [-32, 0], [0, 0], [-16, 16], [16, 16], ]; const VP_TRACK = [ [ 91, 43 ], [ 183, 43 ], [ 273, 43 ], [ 363, 43 ], [ 454, 43 ], [ 545, 43 ], [ 635, 43 ], [ 726, 43 ], [ 816, 43 ], [ 906, 43 ], [ 996, 43 ], [ 1035, 78 ], [ 1035, 169 ], [ 1035, 259 ], [ 1035, 350 ], [ 1035, 441 ], [ 1035, 531 ], [ 996, 563 ], [ 906, 563 ], [ 816, 563 ], [ 726, 563 ], [ 635, 563 ], [ 545, 563 ], [ 454, 563 ], ]; // GAME STATE function player_cylinders(p) { return 36 + p * 10; } function ruler_of_region(r) { let ruler = -1; 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 ++; if (view.pieces[i+12] === r) n_british ++; if (view.pieces[i+24] === r) 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; for (let i = x; i < x + 10; ++i) if (view.pieces[i] === r) n_tribes++; let n_ruling = n_tribes; if (view.players[p].loyalty === 'Afghan') n_ruling += n_afghan; if (view.players[p].loyalty === 'British') n_ruling += n_british; if (view.players[p].loyalty === 'Russian') n_ruling += n_russian; if (n_ruling === max_ruling) { ruler = -1; } else if (n_ruling > max_ruling) { max_ruling = n_ruling; if (n_tribes > 0) ruler = p; else ruler = -1; } } return ruler; } function count_influence_points(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; for (let i = x; i < x + 10; ++i) { let s = view.pieces[i]; if (s === Gift2 || s === Gift4 || s === Gift6) n += gv; } } if (!view.players[p].events.rumor) { let court = view.players[p].court; for (let i = 0; i < court.length; ++i) if (cards[court[i]].patriot) ++n; } return n; } function count_cylinders_in_play(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; } function is_piece_army(i) { return (view.pieces[i] >= 201 && view.pieces[i] <= 206); } function is_piece_road(i) { 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; } function is_place_gift_action(i) { if (view.actions && view.actions.place_gift && view.actions.place_gift.includes(i)) return true; return false; } function is_suit_action(suit) { if (view.actions && view.actions.suit && view.actions.suit.includes(suit)) return true; return false; } function is_piece_action(i) { if (view.actions && view.actions.piece && view.actions.piece.includes(i)) return true; return false; } function is_space_action(i) { if (view.actions && view.actions.space && view.actions.space.includes(i)) return true; return false; } // UI ELEMENTS let ui = { pieces: [], spaces: [], cards: [], spyrows: [], market_card: [[],[]], market_coin: [[],[]], card_action_index: { battle: [], betray: [], build: [], gift: [], move: [], tax: [] }, card_action_element: { battle: [], betray: [], build: [], gift: [], move: [], tax: [] }, player: [], } function scroll_to_map() { ui.board.scrollIntoView({behavior:'smooth'}); } function scroll_to_market() { ui.market.scrollIntoView({behavior:'smooth'}); } function scroll_to_player(p) { ui.player[p].area.scrollIntoView({behavior:'smooth'}); } let open_toggle = true; function toggle_open_hands() { 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); } function on_blur() { ui.status.textContent = ""; ui.tooltip.classList = "hide"; } function on_focus_card_tip(c) { ui.tooltip.classList = "card card_" + c; } function on_click_card_tip(c) { ui.cards[c].scrollIntoView({behavior:'smooth'}); } function on_focus_card(evt) { 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; } } function on_click_space(evt) { send_action('space', evt.target.space); evt.stopPropagation(); } function on_click_block(evt) { send_action('piece', evt.target.piece); evt.stopPropagation(); } function on_click_cylinder(evt) { send_action('piece', evt.target.piece); evt.stopPropagation(); } function toggle_hand(p) { ui.player[p].hand.classList.toggle("hide"); } // CARD MENU const card_action_menu = [ 'play_left', 'play_right', ]; let current_popup_card = 0; function show_popup_menu(evt, list) { 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 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'; if (current_popup_card) { 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(); } function on_click_card(evt) { let c = evt.target.card; if (is_card_action('card', c)) { send_action('card', c); } else { 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); } } } // LOG function sub_card_name(match, p1) { let c = p1 | 0; let name = cards[c].name; return `${name}`; } function on_log(text) { let p = document.createElement("div"); if (text.match(/^>/)) { text = text.substring(1); p.className = 'i'; } 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; } let m; if ((m = text.match(/^.dc.(\w+) (.*)/))) { text = m[2]; p.className = 'dc ' + m[1]; } 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`; } for (let k = 0, i = 0; i < 12; ++i) { if (view.pieces[i] === 0) { 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; } } for (let k = 0, i = 24; i < 36; ++i) { if (view.pieces[i] === 0) { 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`; } 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-nrow+1, col - (ncol/2) - ((nrow-1)/4), list[i++]); } function layout_tribes(list, xc, yc, maxcol) { function place_tribe(y, x, i) { ui.pieces[i].style = `top:${yc+y*16+x*4}px;left:${xc+x*32-y*20}px`; } let ncol = Math.min(maxcol, Math.ceil(Math.sqrt(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_tribe(row, col - (ncol/2) + ((nrow-1)/4), list[i++]); } function layout_region(r, xc, yc, maxcol) { let list = []; for (let i = 0; i < 36; ++i) if (view.pieces[i] === r) list.push(i); layout_armies(list, xc - 2, yc - 50, maxcol); list = []; for (let i = 36; i < view.pieces.length; ++i) if (view.pieces[i] === r) list.push(i); layout_tribes(list, xc, yc + 20, maxcol); } function layout_border(r, xc, yc, line) { xc -= 24; yc -= 12; function place_piece_border(i, k) { 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; } ui.pieces[i].style = `top:${yc+y}px;left:${xc+x}px`; } let n = 0; for (let i = 0; i < view.pieces.length; ++i) { if (view.pieces[i] === r) ++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; } } } // UPDATE UI let once = true; function on_update() { if (once) { build_ui(); once = false; } function update_event_cards(node, events) { for (let evt in events) node.appendChild(ui.cards[event_cards[evt]]); } let ruler = [ ruler_of_region(Persia), ruler_of_region(Transcaspia), ruler_of_region(Herat), ruler_of_region(Kabul), ruler_of_region(Kandahar), ruler_of_region(Punjab) ]; 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`; 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"); for (let i = 0; i < 10; ++i) action_button("offer_" + i, i); 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("pass", "Pass"); action_button("next", "Next"); 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"); 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]]; if (ce) ce.classList.remove("card_back"); let me = ui.market_card[row][col]; if (me.firstChild !== ce) { if (me.firstChild) me.removeChild(me.firstChild); if (ce) me.appendChild(ce); } let coins = view.market_coins[row][col]; if (coins > 0) { 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"; } } } for (let i = 1; i < cards.length; ++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); } for (let i = 301; i <= 309; ++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)); } for (let p = 0; p < view.players.length; ++p) { 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); for (let i = 0; i < pp.court.length; ++i) { 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)); } me = ui.global_events; while (me.firstChild) me.removeChild(me.firstChild); update_event_cards(me, view.events); me = ui.player[p].hand; while (me.firstChild) me.removeChild(me.firstChild); if (p === player_index[player]) me.classList.remove("hide"); for (let i = 0; i < pp.hand.length; ++i) { let ce = ui.cards[pp.hand[i]]; if (p !== player_index[player] && !view.open) ce.classList.add("card_back"); else ce.classList.remove("card_back"); me.appendChild(ce); } if (view.players[p].coins == 0) { ui.player[p].coin.classList.add("hide"); } else { 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"); } else { ui.player[p].prize.classList.remove("hide"); if (view.players[p].prizes === 1) ui.player[p].prize.textContent = view.players[p].prizes + " prize"; else ui.player[p].prize.textContent = view.players[p].prizes + " prizes"; } 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].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"; for (let i = 0; i < 10; ++i) { 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]); else if (s === Gift2) ui.player[p].gift_2.appendChild(ui.pieces[x]); else if (s === Gift4) ui.player[p].gift_4.appendChild(ui.pieces[x]); else if (s === Gift6) ui.player[p].gift_6.appendChild(ui.pieces[x]); else if (s <= 100) ui.spyrows[s].appendChild(ui.pieces[x]); else 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 = ""; } } for (let i = 0; i < 6; ++i) if (ruler[i] === -1) ui.rule[i].classList = "hide"; else ui.rule[i].classList = `rule ${region_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(Persia, 206-16, 426, 5); layout_region(Transcaspia, 254, 152, 10); layout_region(Herat, 456, 383, 6); layout_region(Kabul, 673, 163, 12); layout_region(Kandahar, 732-23, 437, 6); layout_region(Punjab, 929, 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, 332, 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)); } } } // 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]; function build_player_ui(p) { return { role: document.getElementById("role_" + player_names[p]), role_rup_text: document.getElementById("rupees_" + p + "_text"), role_cyl_text: document.getElementById("cylinders_" + p + "_text"), role_loy_text: document.getElementById("loyalty_" + p + "_text"), role_loy_icon: document.getElementById("loyalty_" + p + "_icon"), score: document.getElementById("player_score_" + p), area: document.getElementById("player_area_" + p), hand_size: document.getElementById("player_hand_size_" + p), hand: document.getElementById("player_hand_" + p), court: document.getElementById("player_court_" + p), pool: document.getElementById("player_pool_" + p), dial: document.getElementById("player_dial_" + p), coin: document.getElementById("player_coin_" + p), prize: document.getElementById("player_prize_" + p), gift_2: document.getElementById("player_gift_" + p + "_2"), gift_4: document.getElementById("player_gift_" + p + "_4"), gift_6: document.getElementById("player_gift_" + p + "_6"), } } 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); } 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); } for (let c = 1; c < cards.length; ++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); if (passive_cards.includes(c)) e.classList.add("passive"); if (n === 3) e.classList.add("three"); } else { 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; } 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); } } for (let p = 0; p < 5; ++p) { ui.player[p] = build_player_ui(p); ui.player[p].hand_size.addEventListener("click", () => 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]); } 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 = [ document.querySelector(`#board .rule.Persia`), document.querySelector(`#board .rule.Transcaspia`), document.querySelector(`#board .rule.Herat`), 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"); 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; } 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"); 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"); } 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"); } if (player !== 'Observer') 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)); for (let i = 0; i < view.players.length; ++i) console.log("PLAYER", i, JSON.stringify(view.players[i], rr, 0)); }