"use strict" // TODO: layout cubes in spaces in two groups (max 4 each space) // TODO: layout cubes on tracks/pools as one space let layout = [] let space_layout_cube = [] let space_layout_disc = [] let ui = { cards: [ null ], cubes: [], discs: [], spaces: [], red_momentum: document.getElementById("red_momentum"), blue_momentum: document.getElementById("blue_momentum"), political_vp: document.getElementById("political_vp"), military_vp: document.getElementById("military_vp"), round_marker: document.getElementById("round_marker"), } const card_names = [ "Initiative", "Jules Ducatel", "The Murder of Vincenzini", "Brassardiers", "Jules Ferry", "Le Figaro", "Général Louis Valentin", "Général Espivent", "Les Amis de l'Ordre", "Socialist Newspaper Ban", "Fortification of Mont-Valérien", "Adolphe Thiers", "Otto von Bismarck", "Général Ernest de Cissey", "Colonel de Lochner", "Jules Favre", "Hostage Decree", "Maréchal Macmahon", "Paule Minck", "Walery Wroblewski", "Banque de France", "Le Réveil", "Execution of Generals", "Les Cantinières", "Eugène Protot", "Paul Cluseret", "Gaston Crémieux", "Luise Michel", "Jaroslav Dombrowski", "Raoul Rigault", "Karl Marx", "Blanquists", "Général Lullier", "Jules Vallès", "Charles Delescluze", "Conciliation", "Georges Clemenceau", "Archbishop Georges Darboy", "Victor Hugo", "Léon Gambetta", "Elihu Washburne", "Freemason Parade", "Paris Cannons", "Aux Barricades!", "Commune's Stronghold", "Fighting in Issy Village", "Battle of Mont-Valérien", "Raid on Château de Vincennes", "Revolution in the Press", "Pius IX", "Socialist International", "Royalists Dissension", "Rise of Republicanism", "Legitimacy", ] const space_names = [ "National Assembly", "Royalists", "Republicans", "Press", "Catholic Church", "Social Movements", "Mont-Valérien", "Fort D'Issy", "Château de Vincennes", "Butte Montmartre", "Butte-Aux-Cailles", "Père Lachaise", "Prussian Occupied Territory", "Versailles HQ", "Red Cube Pool 1", "Red Cube Pool 2", "Red Cube Pool 3", "Red Crisis Track Start", "Red Crisis Track Escalation", "Red Crisis Track Tension", "Red Crisis Track Final Crisis", "Red Bonus Cubes 1", "Red Bonus Cubes 2", "Red Bonus Cubes 3", "Blue Cube Pool", "Blue Crisis Track Start", "Blue Crisis Track Escalation", "Blue Crisis Track Tension", "Blue Crisis Track Final Crisis", "Blue Bonus Cubes 1", "Blue Bonus Cubes 2", "Blue Bonus Cubes 3", "Prussian Collaboration 1", "Prussian Collaboration 2", "Prussian Collaboration 3", ] const space_count = space_names.length // :r !python3 tools/genboxes.py const boxes = { "Royalists": [80,428,126,126], "Republicans": [490,428,126,126], "Catholic Church": [80,786,126,126], "Social Movements": [490,786,126,126], "Fort D'Issy": [844,793,126,126], "Butte-Aux-Cailles": [1038,660,126,126], "Père Lachaise": [1206,591,126,126], "Château de Vincennes": [1342,650,126,127], "Press": [294,727,112,112], "National Assembly": [292,496,112,112], "Butte Montmartre": [1052,460,112,111], "Mont-Valérien": [717,507,112,112], "Versailles HQ": [662,850,101,95], "Prussian Occupied Territory": [1298,353,180,86], "Red Crisis Track Start": [982,61,90,112], "Red Crisis Track Escalation": [1072,61,84,112], "Red Crisis Track Tension": [1156,61,83,112], "Red Crisis Track Final Crisis": [1239,61,83,112], "Blue Crisis Track Start": [432,61,88,112], "Blue Crisis Track Escalation": [348,61,84,112], "Blue Crisis Track Tension": [265,61,83,112], "Blue Crisis Track Final Crisis": [182,61,83,112], "Blue Objective Card": [120,996,272,54], "Red Objective Card": [1114,996,272,54], "Blue Cube Pool": [180,198,198,55], "Red Bonus Cubes 1": [1072,22,84,39], "Red Bonus Cubes 2": [1156,22,83,39], "Red Bonus Cubes 3": [1239,22,83,39], "Blue Bonus Cubes 1": [348,22,84,39], "Blue Bonus Cubes 2": [265,22,83,39], "Blue Bonus Cubes 3": [182,22,83,39], "Red Cube Pool 1": [787,330,115,39], "Red Cube Pool 2": [902,330,136,39], "Red Cube Pool 3": [1038,330,157,40], "Prussian Collaboration 1": [600,330,115,39], "Prussian Collaboration 2": [463,330,136,39], "Prussian Collaboration 3": [306,330,157,39], } function is_card_action(action, card) { if (view.actions && view.actions[action] && view.actions[action].includes(card)) 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 } function on_blur(evt) { document.getElementById("status").textContent = "" } function on_focus_space(evt) { document.getElementById("status").textContent = evt.target.my_name } function on_click_space(evt) { if (evt.button === 0) { if (send_action('space', evt.target.my_space)) evt.stopPropagation() } } function on_click_cube(evt) { if (evt.button === 0) { if (send_action('piece', evt.target.my_cube)) evt.stopPropagation() } } function on_click_disc(evt) { if (evt.button === 0) { if (send_action('piece', evt.target.my_disc)) evt.stopPropagation() } } function build_user_interface() { let elt for (let c = 1; c <= 41 + 12; ++c) { elt = ui.cards[c] = document.createElement("div") elt.className = `card card_${c}` elt.my_card = c elt.addEventListener("click", on_click_card) } for (let i = 0; i < 36; ++i) { elt = ui.cubes[i] = document.createElement("div") if (i < 18) elt.className = "piece cube red" else elt.className = "piece cube blue" elt.my_cube = i elt.addEventListener("mousedown", on_click_cube) document.getElementById("pieces").appendChild(elt) } for (let i = 0; i < 4; ++i) { elt = ui.discs[i] = document.createElement("div") if (i < 2) elt.className = "piece disc red" else elt.className = "piece disc blue" elt.my_disc = i + 36 elt.addEventListener("mousedown", on_click_disc) document.getElementById("pieces").appendChild(elt) } for (let i = 0; i < space_count; ++i) { let name = space_names[i] let [x, y, w, h] = boxes[name] elt = ui.spaces[i] = document.createElement("div") elt.className = "space" elt.my_space = i elt.my_name = name elt.addEventListener("mousedown", on_click_space) elt.addEventListener("mouseenter", on_focus_space) elt.addEventListener("mouseleave", on_blur) let bw = 8 elt.style.top = y + "px" elt.style.left = x + "px" elt.style.width = (w - bw * 2) + "px" elt.style.height = (h - bw * 2) + "px" space_layout_cube[i] = { x: x + Math.round(w/2), y: y + Math.round(h*1/2) } space_layout_disc[i] = { x: x + w, y: y + h } document.getElementById("spaces").appendChild(elt) } } function layout_cubes(list, xorig, yorig) { const dx = 20 const dy = 11 if (list.length > 0) { let ncol = Math.round(Math.sqrt(list.length)) let nrow = Math.ceil(list.length / ncol) function place_cube(row, col, e, z) { let x = xorig - (row * dx - col * dx) - 18 + (nrow-ncol) * 6 let y = yorig - (row * dy + col * dy) - 28 + (nrow-1) * 8 e.style.left = x + "px" e.style.top = y + "px" e.style.zIndex = z } let z = 50 let i = 0 for (let row = 0; row < nrow; ++row) for (let col = 0; col < ncol && i < list.length; ++col) place_cube(row, col, list[list.length-(++i)], z--) } } function layout_disc(s, disc) { if (s > 0) { disc.classList.remove("hide") disc.style.left = (space_layout_disc[s].x - 50 - 12) + "px" disc.style.top = (space_layout_disc[s].y - 20 - 8) + "px" disc.style.zIndex = 51; } else disc.classList.add("hide") } function on_focus_card_tip(card_number) { document.getElementById("tooltip").className = "card card_" + card_number } function on_blur_card_tip() { document.getElementById("tooltip").classList = "card hide" } function sub_card_name(match, p1, offset, string) { let c = p1 | 0 let n = card_names[c] return `${n}` } 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(/^\.h1/)) { text = text.substring(4) p.className = 'h1' } if (text.match(/^\.h2/)) { text = text.substring(4) if (text === 'Commune') p.className = 'h2 commune' else if (text === 'Versailles') p.className = 'h2 versailles' else p.className = 'h2' } p.innerHTML = text return p } function on_update() { if (view.discard) document.getElementById("discarded_card").className = `card card_${view.discard}` else document.getElementById("discarded_card").className = `card card_strategy_back` if (view.initiative === "Commune") document.getElementById("commune_info").textContent = "\u2756" else document.getElementById("commune_info").textContent = "" if (view.initiative === "Versailles") document.getElementById("versailles_info").textContent = "\u2756" else document.getElementById("versailles_info").textContent = "" ui.round_marker.className = `piece pawn round${view.round}` ui.red_momentum.className = `piece cylinder red m${view.red_momentum}` ui.blue_momentum.className = `piece cylinder blue m${view.blue_momentum}` ui.military_vp.className = `piece cylinder purple vp${5+view.military_vp}` ui.political_vp.className = `piece cylinder orange vp${5+view.political_vp}` document.getElementById("hand").replaceChildren() if (view.objective) document.getElementById("hand").appendChild(ui.cards[view.objective]) if (view.hand) for (let c of view.hand) document.getElementById("hand").appendChild(ui.cards[c]) for (let i = 0; i < space_names.length; ++i) layout[i] = [] for (let i = 0; i < 36; ++i) { if (view.pieces[i] >= 0) { layout[view.pieces[i]].push(ui.cubes[i]) ui.cubes[i].classList.remove("hide"); ui.cubes[i].classList.toggle("action", is_piece_action(i)) } else { ui.cubes[i].classList.add("hide"); } } for (let i = 0; i < space_count; ++i) { layout_cubes(layout[i], space_layout_cube[i].x, space_layout_cube[i].y) ui.spaces[i].classList.toggle("action", is_space_action(i)) } for (let i = 0; i < 4; ++i) { layout_disc(view.pieces[36+i], ui.discs[i]) ui.discs[i].classList.toggle("action", is_piece_action(36+i)) } for (let i = 1; i < ui.cards.length; ++i) { ui.cards[i].classList.toggle("action", is_card_action('card', i)) } action_button("commune", "Commune"); action_button("versailles", "Versailles"); action_button("spend", "Spend"); action_button("draw", "Draw"); action_button("end_remove", "End Remove"); action_button("end_turn", "End Turn"); action_button("done", "Done"); action_button("undo", "Undo"); } /* CARD ACTION MENU */ 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") } 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 on_card_event() { if (send_action('card_event', current_popup_card)) hide_popup_menu() } function on_card_ops() { if (send_action('card_ops', current_popup_card)) hide_popup_menu() } function on_card_ops_political() { if (send_action('card_ops_political', current_popup_card)) hide_popup_menu() } function on_card_ops_military() { if (send_action('card_ops_military', current_popup_card)) hide_popup_menu() } function on_card_use_discarded() { if (send_action('card_use_discarded', current_popup_card)) hide_popup_menu() } function on_card_advance_momentum() { if (send_action('card_advance_momentum', current_popup_card)) hide_popup_menu() } function on_click_card(evt) { if (evt.button === 0) { if (view.actions) { let card = evt.target.my_card if (is_card_action('card', card)) { send_action('card', card) } else { let menu = [] if (is_card_action('card_event', card)) menu.push('card_event') if (is_card_action('card_ops_political', card)) menu.push('card_ops_political') if (is_card_action('card_ops_military', card)) menu.push('card_ops_military') if (is_card_action('card_use_discarded', card)) menu.push('card_use_discarded') if (is_card_action('card_advance_momentum', card)) menu.push('card_advance_momentum') if (menu.length > 0) { current_popup_card = card show_popup_menu(evt, menu) } } } } } build_user_interface() scroll_with_middle_mouse("main")