diff options
author | Tor Andersson <tor@ccxvii.net> | 2024-08-20 23:46:06 +0200 |
---|---|---|
committer | Tor Andersson <tor@ccxvii.net> | 2024-08-21 00:28:20 +0200 |
commit | bd220ea527eaf640636a5a80a6c4cd654a7e25d8 (patch) | |
tree | c7b00437209547074063d8f32599536c02ed0eab | |
parent | b1c09b948305b84f31afd81cc1b4c0fadd1fd997 (diff) | |
download | washingtons-war-bd220ea527eaf640636a5a80a6c4cd654a7e25d8.tar.gz |
Keep the bit rot away.
-rw-r--r-- | about.html | 1 | ||||
-rw-r--r-- | play.css | 41 | ||||
-rw-r--r-- | play.html | 91 | ||||
-rw-r--r-- | play.js | 197 | ||||
-rw-r--r-- | rules.js | 366 | ||||
-rw-r--r-- | title.sql | 2 |
6 files changed, 349 insertions, 349 deletions
@@ -1,7 +1,6 @@ <p> Unlicensed game prototype! -<br clear=left> <ul> <li><a href="/washingtons-war/info/rulebook.html">Rulebook</a> @@ -1,10 +1,13 @@ main { background-color: slategray; } header { background-color: silver; } +aside { background-color: #f5e8d7; } body.British header.your_turn { background-color: salmon; } body.American header.your_turn { background-color: skyblue; } -aside { background-color: #f5e8d7; } -.one .role_name { background-color: skyblue; } -.two .role_name { background-color: salmon; } +#role_American .role_name { background-color: skyblue; } +#role_British .role_name { background-color: salmon; } +.role_vp { float: right; } + +#log > div { padding-left: 20px; text-indent: -12px; } #log .h1 { background-color: tan; @@ -22,7 +25,7 @@ aside { background-color: #f5e8d7; } #log .h2.american { background-color: skyblue; } #log .h2.british { background-color: salmon; } -#log .card_tip { text-decoration: dotted underline; } +#log .card_tip:hover { text-decoration: dotted underline; } aside { width: 230px; @@ -42,22 +45,20 @@ aside { margin: 5px auto; } +.hand { + margin: 15px; + display: flex; + flex-wrap: wrap; + justify-content: center; + min-height: 370px; + gap: 15px; +} + /* CARD ACTION POPUP MENU */ -#popup { - position: absolute; - user-select: none; - background-color: #ddd; - left: 10px; - top: 100px; - box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.3); - z-index: 100; - min-width: 20ex; - white-space: nowrap; -} -#popup div { padding: 3pt 8pt; display: none; } -#popup div.enabled { padding: 3pt 8pt; display: block; } -#popup div:hover { background-color: teal; color: white; } +#popup { max-width: 250px; } +#popup li.title { text-align: center } +#popup li.disabled { display: none } /* MAP WITH MARKERS, CUs, LEADERS, AND SPACES */ @@ -160,7 +161,6 @@ aside { line-height: 50px; padding-left: 6px; font-size: 30px; - user-select: none; color: white; text-shadow: 0px 0px 3px black; font-weight: bold; @@ -257,7 +257,8 @@ aside { .hand .card.enabled:hover, .hand .card.selected { Xtransform: scale(1.5) translate(0,-30px); - transform: scale(1.1); + Xtransform: scale(1.1); + transform: translate(0,-10px); z-index: 10; } @@ -1,14 +1,14 @@ <!DOCTYPE html> -<html> +<html lang="en"> <head> -<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1"> +<meta name="viewport" content="width=device-width, height=device-height, user-scalable=no, interactive-widget=resizes-content, viewport-fit=cover"> +<meta name="theme-color" content="#444"> <meta charset="utf-8"> <title>WASHINGTON'S WAR</title> <link rel="icon" href="favicon.png"> <link rel="stylesheet" href="/fonts/fonts.css"> -<link rel="stylesheet" href="/common/grid.css"> +<link rel="stylesheet" href="/common/client.css"> <link rel="stylesheet" href="play.css"> -<script defer src="/socket.io/socket.io.min.js"></script> <script defer src="/common/client.js"></script> <script defer src="data.js"></script> <script defer src="cards.js"></script> @@ -17,67 +17,38 @@ </head> <body> -<div id="popup" onmouseleave="hide_popup_menu()"> - <div id="menu_card_play_event" onclick="on_card_play_event()"> - Play Event - </div> - <div id="menu_card_discard_event" onclick="on_card_discard_event()"> - Discard for PC action - </div> - <div id="menu_card_campaign" onclick="on_card_campaign()"> - Play Campaign - </div> - <div id="menu_card_ops_general" onclick="on_card_ops_general()"> - Activate a General - </div> - <div id="menu_card_ops_pc" onclick="on_card_ops_pc()"> - Place PC markers - </div> - <div id="menu_card_ops_reinforcements" onclick="on_card_ops_reinforcements()"> - Bring on Reinforcements - </div> - <div id="menu_card_ops_queue" onclick="on_card_ops_queue()"> - Place into Operations Queue - </div> - <div id="menu_card_battle_play" onclick="on_card_battle_play()"> - Play for +2 DRM - </div> - <div id="menu_card_battle_discard" onclick="on_card_battle_discard()"> - Discard for +1 DRM - </div> - <div id="menu_exchange_for_discard" onclick="on_exchange_for_discard()"> - Exchange for Discarded Event - </div> -</div> +<menu id="popup"> + <li class="title">CARD + <li class="separator"> + <li data-action="card_play_event"> Play Event + <li data-action="card_discard_event"> Discard for PC action + <li data-action="card_campaign"> Play Campaign + <li data-action="card_ops_general"> Activate a General + <li data-action="card_ops_pc"> Place PC markers + <li data-action="card_ops_reinforcements"> Bring on Reinforcements + <li data-action="card_ops_queue"> Place into Operations Queue + <li data-action="card_battle_play"> Play for +2 DRM + <li data-action="card_battle_discard"> Discard for +1 DRM + <li data-action="exchange_for_discard"> Exchange for Discarded Event +</menu> <header> - <div class="menu"> - <div class="menu_title"><img src="/images/cog.svg"></div> - <div class="menu_popup"> - <div class="menu_item" onclick="toggle_fullscreen()">Fullscreen</div> - <div class="menu_separator"></div> - <div class="menu_item" onclick="window.open('info/playbook.html', '_blank')">Playbook</div> - <div class="menu_item" onclick="window.open('info/rulebook.html', '_blank')">Rulebook</div> - <div class="menu_item" onclick="window.open('cards.html', '_blank')">Cards</div> - <div class="menu_separator"></div> - <div class="menu_item" onclick="send_save()">🐞 Save</div> - <div class="menu_item" onclick="send_restore()">🐞 Restore</div> - <div class="menu_separator"></div> - <div class="menu_item" onclick="send_restart()">⚠ Restart</div> - </div> + <div id="toolbar"> + <details> + <summary><img src="/images/cog.svg"></summary> + <menu> + <li><a href="info/playbook.html" target="blank">Playbook</a> + <li><a href="info/rulebook.html" target="blank">Rulebook</a> + <li><a href="cards.html" target="blank">Cards</a> + </menu> + </details> + <button onclick="toggle_markers()"><img src="/images/earth-america.svg"></button> </div> - - <div class="icon_button" onclick="toggle_markers()"><img src="/images/earth-america.svg"></div> - <div class="icon_button" onclick="toggle_zoom()"><img src="/images/magnifying-glass.svg"></div> - <div class="icon_button" onclick="toggle_log()"><img src="/images/scroll-quill.svg"></div> - - <div id="prompt"></div> - <div id="actions"></div> </header> <aside> <div class="roles"> - <div class="role one"> + <div class="role" id="role_American"> <div class="role_name"> American <div class="role_vp" id="american_vp">VP</div> @@ -85,7 +56,7 @@ </div> <div class="role_info" id="american_info">$N cards in hand.</div> </div> - <div class="role two"> + <div class="role" id="role_British"> <div class="role_name"> British <div class="role_vp" id="british_vp"></div> @@ -98,7 +69,7 @@ <div id="log"></div> </aside> -<main> +<main onclick="hide_popup_menu()"> <div id="mapwrap"> <div id="map"> @@ -17,7 +17,7 @@ let ui = { cu: [], }; -create_log_entry = function (text) { +function on_log(text) { let p = document.createElement("div"); text = text.replace(/&/g, "&"); text = text.replace(/</g, "<"); @@ -193,21 +193,21 @@ function update_units() { const cuX = 20; const cuY = 10; - update_marker(ui.turn, "Game Turn " + game.year); - if (game.regulars) + update_marker(ui.turn, "Game Turn " + view.year); + if (view.regulars) ui.turn.classList.remove("no-regulars"); else ui.turn.classList.add("no-regulars"); - update_marker(ui.congress, game.congress); + update_marker(ui.congress, view.congress); - update_marker(ui.french_alliance, "French Alliance Track " + game.french_alliance); - if (game.european_war) + update_marker(ui.french_alliance, "French Alliance Track " + view.french_alliance); + if (view.european_war) ui.french_alliance.classList.add("european-war"); else ui.french_alliance.classList.remove("european-war"); - if (game.french_navy == "French Reinforcements") { + if (view.french_navy == "French Reinforcements") { let x = BOXES["French Reinforcements"].x-130/2-10; let y = BOXES["French Reinforcements"].y-32; let w = 126/2; @@ -215,11 +215,11 @@ function update_units() { ui.french_navy.style.left = ((x-w/2)|0) + "px"; ui.french_navy.style.top = ((y-h/2)|0) + "px"; } else { - update_marker(ui.french_navy, game.french_navy); + update_marker(ui.french_navy, view.french_navy); } for (let space in SPACES) { - let space_pc = game.pc[space]; + let space_pc = view.pc[space]; let e = document.getElementById(space+"-pc"); if (e) { if (space_pc === BRITISH) { @@ -238,9 +238,9 @@ function update_units() { for (let c in COLONIES) { let control = 0; for (let space of COLONIES[c]) { - if (game.pc[space] == BRITISH) + if (view.pc[space] == BRITISH) --control; - else if (game.pc[space] == AMERICAN) + else if (view.pc[space] == AMERICAN) ++control; } if (control < 0) @@ -254,7 +254,7 @@ function update_units() { let offset = {}; for (let g in GENERALS) { let e = ui.generals[g]; - let unit = game.generals[g]; + let unit = view.generals[g]; let space = SPACES[unit.location] || BOXES[unit.location]; if (space) { let o = (offset[space.name]|0); @@ -264,7 +264,7 @@ function update_units() { } else { e.classList.add("offmap"); } - if (game.who == g) + if (view.who == g) e.classList.add("selected"); else e.classList.remove("selected"); @@ -273,8 +273,8 @@ function update_units() { // TODO: reuse CU elements offset = {}; clear_group("cu"); - for (let i = 0; i < game.cu.length; ++i) { - let cu = game.cu[i]; + for (let i = 0; i < view.cu.length; ++i) { + let cu = view.cu[i]; let space = SPACES[cu.location] || BOXES[cu.location]; let o = (offset[space.name]|0); let x = space.x + o * cuX; @@ -296,9 +296,9 @@ function player_info(player, nc, nq) { if (nq > 0) info += "\n" + nq + " OPS in queue."; if (player == AMERICAN) { - if (game.pennsylvania_and_new_jersey_line_mutinies) + if (view.pennsylvania_and_new_jersey_line_mutinies) info += "\nPennsylvania and New Jersey Line Mutinies!"; - if (game.congress == CONTINENTAL_CONGRESS_DISPERSED) + if (view.congress == CONTINENTAL_CONGRESS_DISPERSED) info += "\nContinental Congress Dispersed!"; } return info; @@ -307,13 +307,13 @@ function player_info(player, nc, nq) { function on_update() { let e; - document.getElementById("british_info").textContent = player_info(BRITISH, game.b_cards, game.b_queue); - document.getElementById("american_info").textContent = player_info(AMERICAN, game.a_cards, game.a_queue); + document.getElementById("british_info").textContent = player_info(BRITISH, view.b_cards, view.b_queue); + document.getElementById("american_info").textContent = player_info(AMERICAN, view.a_cards, view.a_queue); - if (!game.last_played) + if (!view.last_played) document.getElementById("last_played").className = "card show card_back"; else - document.getElementById("last_played").className = "card show card_" + game.last_played; + document.getElementById("last_played").className = "card show card_" + view.last_played; action_button("pickup_british_cu", "Pick up British CU"); action_button("pickup_american_cu", "Pick up American CU"); @@ -333,30 +333,30 @@ function on_update() { e.classList.remove("year_1781"); e.classList.remove("year_1782"); e.classList.remove("year_1783"); - if (game.war_ends) - e.classList.add("year_" + game.war_ends); + if (view.war_ends) + e.classList.add("year_" + view.war_ends); e = document.getElementById("played_british_reinforcements"); e.classList.remove("ops_1"); e.classList.remove("ops_2"); e.classList.remove("ops_3"); - e.classList.add("ops_" + game.played_british_reinforcements); + e.classList.add("ops_" + view.played_british_reinforcements); e = document.getElementById("played_american_reinforcements_1"); e.classList.remove("ops_1"); e.classList.remove("ops_2"); e.classList.remove("ops_3"); - if (game.played_american_reinforcements.length >= 1) - e.classList.add("ops_" + game.played_american_reinforcements[0]); + if (view.played_american_reinforcements.length >= 1) + e.classList.add("ops_" + view.played_american_reinforcements[0]); e = document.getElementById("played_american_reinforcements_2"); e.classList.remove("ops_1"); e.classList.remove("ops_2"); e.classList.remove("ops_3"); - if (game.played_american_reinforcements.length >= 2) - e.classList.add("ops_" + game.played_american_reinforcements[1]); + if (view.played_american_reinforcements.length >= 2) + e.classList.add("ops_" + view.played_american_reinforcements[1]); - let cards = game.hand; + let cards = view.hand; for (let c = 1; c <= 110; ++c) { ui.cards[c].classList.remove('enabled'); if (cards && cards.includes(c)) @@ -376,11 +376,11 @@ function on_update() { update_units(); - if (player != game.active) + if (player != view.active) return; - for (let action of Object.keys(game.actions)) { - let args = game.actions[action]; + for (let action of Object.keys(view.actions)) { + let args = view.actions[action]; switch (action) { case 'card_play_event': case 'card_discard_event': @@ -419,92 +419,73 @@ function on_update() { } } -let current_popup_card = 0; +function is_action(action, card) { + return view.actions && view.actions[action] && view.actions[action].includes(card) +} -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'); +function show_popup_menu(evt, menu_id, target_id, title) { + let menu = document.getElementById(menu_id) + + let show = false + for (let item of menu.querySelectorAll("li")) { + let action = item.dataset.action + if (action) { + if (is_action(action, target_id)) { + show = true + item.classList.add("action") + item.classList.remove("disabled") + item.onclick = function () { + send_action(action, target_id) + hide_popup_menu() + evt.stopPropagation() + } + } else { + item.classList.remove("action") + item.classList.add("disabled") + item.onclick = null + } + } } - 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; + if (show) { + menu.onmouseleave = hide_popup_menu + menu.style.display = "block" + if (title) { + let item = menu.querySelector("li.title") + if (item) { + item.onclick = hide_popup_menu + item.textContent = title + } + } + + let w = menu.clientWidth + let h = menu.clientHeight + let x = Math.max(5, Math.min(evt.clientX - w / 2, window.innerWidth - w - 5)) + let y = Math.max(5, Math.min(evt.clientY - 12, window.innerHeight - h - 40)) + menu.style.left = x + "px" + menu.style.top = y + "px" + + return true } -} -function on_card_play_event() { - send_action('card_play_event', current_popup_card); - hide_popup_menu(); -} -function on_card_discard_event() { - send_action('card_discard_event', current_popup_card); - hide_popup_menu(); + return false } -function on_card_campaign() { - send_action('card_campaign', current_popup_card); - hide_popup_menu(); -} -function on_card_ops_general() { - send_action('card_ops_general', current_popup_card); - hide_popup_menu(); -} -function on_card_ops_pc() { - send_action('card_ops_pc', current_popup_card); - hide_popup_menu(); -} -function on_card_ops_reinforcements() { - send_action('card_ops_reinforcements', current_popup_card); - hide_popup_menu(); -} -function on_card_ops_queue() { - send_action('card_ops_queue', current_popup_card); - hide_popup_menu(); -} -function on_card_ops_queue() { - send_action('card_ops_queue', current_popup_card); - hide_popup_menu(); -} -function on_card_battle_play() { - send_action('card_battle_play', current_popup_card); - hide_popup_menu(); -} -function on_card_battle_discard() { - send_action('card_battle_discard', current_popup_card); - hide_popup_menu(); -} -function on_exchange_for_discard() { - send_action('exchange_for_discard', current_popup_card); - hide_popup_menu(); + +function hide_popup_menu() { + document.getElementById("popup").style.display = "none" } function on_card(evt) { - if (game.actions) { + if (view.actions) { let c = evt.target.id.split("+")[1] | 0; - let menu = []; - for (let action in game.actions) - if (Array.isArray(game.actions[action]) && game.actions[action].includes(c)) - menu.push(action); - if (menu.length > 0) { - current_popup_card = c; - show_popup_menu(evt, menu); - } + show_popup_menu(evt, "popup", c, CARDS[c].title) + evt.stopPropagation() } } function get_action_from_arg(x) { - for (let action of Object.keys(game.actions)) { - let args = game.actions[action]; + for (let action of Object.keys(view.actions)) { + let args = view.actions[action]; if (Array.isArray(args) && args.includes(x)) return action; } @@ -512,7 +493,7 @@ function get_action_from_arg(x) { } function on_space(evt) { - if (game.actions) { + if (view.actions) { let space = evt.target.id; let action = get_action_from_arg(space); if (action) @@ -521,7 +502,7 @@ function on_space(evt) { } function on_general(evt) { - if (game.actions) { + if (view.actions) { let general = evt.target.id; let action = get_action_from_arg(general); if (action) @@ -533,7 +514,3 @@ function toggle_markers() { document.querySelector("#map").classList.toggle("hide_markers"); } -scroll_with_middle_mouse("main", 2); -init_map_zoom(); -init_shift_zoom(); -init_client(["American", "British"]); @@ -7,6 +7,11 @@ exports.scenarios = [ "Historical" ]; +exports.roles = [ + "American", + "British", +]; + const CARDS = require('./cards'); const DATA = require('./data'); const SPACES = DATA.SPACES; @@ -63,34 +68,82 @@ let states = {}; let events = {}; let game; +let view; function random(n) { - return Math.floor(((game.seed = game.seed * 48271 % 0x7fffffff) / 0x7fffffff) * n); + return (game.seed = game.seed * 200105 % 34359738337) % n +} + +function logbr() { + if (game.log.length > 0 && game.log[game.log.length-1] !== "") + game.log.push(""); } function log(s) { game.log.push(s); } +function logp(s) { + game.log.push(game.active[0] + " " + s); +} + +function object_copy(original) { + if (Array.isArray(original)) { + let n = original.length + let copy = new Array(n) + for (let i = 0; i < n; ++i) { + let v = original[i] + if (typeof v === "object" && v !== null) + copy[i] = object_copy(v) + else + copy[i] = v + } + return copy + } else { + let copy = {} + for (let i in original) { + let v = original[i] + if (typeof v === "object" && v !== null) + copy[i] = object_copy(v) + else + copy[i] = v + } + return copy + } +} + function clear_undo() { - game.undo = []; + if (game.undo) { + game.undo.length = 0 + } } function push_undo() { - game.undo.push(JSON.stringify(game, (k,v) => { - if (k === 'undo') return undefined; - if (k === 'log') return v.length; - return v; - })); + if (game.undo) { + let copy = {} + for (let k in game) { + let v = game[k] + if (k === "undo") + continue + else if (k === "log") + v = v.length + else if (typeof v === "object" && v !== null) + v = object_copy(v) + copy[k] = v + } + game.undo.push(copy) + } } function pop_undo() { - let undo = game.undo; - let save_log = game.log; - Object.assign(game, JSON.parse(undo.pop())); - game.undo = undo; - save_log.length = game.log; - game.log = save_log; + if (game.undo) { + let save_log = game.log + let save_undo = game.undo + game = save_undo.pop() + save_log.length = game.log + game.log = save_log + game.undo = save_undo + } } function remove_from_array(array, item) { @@ -199,7 +252,7 @@ function create_deck() { } function reshuffle_deck() { - game.log.push("The deck is reshuffled."); + log("Reshuffled the deck."); game.reshuffle = false; game.deck = game.deck.concat(game.discard); game.discard = []; @@ -230,9 +283,9 @@ function active_hand() { function play_card(c, reason) { if (reason) - game.log.push(game.active[0] + " plays [" + c + ": " + CARDS[c].title + "] " + reason); + log(game.active[0] + " played #" + c + " " + reason); else - game.log.push(game.active[0] + " plays [" + c + ": " + CARDS[c].title + "]"); + log(game.active[0] + " played #" + c); if (CARDS[c].reshuffle == 'if_played') game.reshuffle = true; remove_from_array(active_hand(), c); @@ -240,7 +293,7 @@ function play_card(c, reason) { if (!CARDS[c].once) game.discard.push(c); else - game.log.push("Card " + c + " removed from game."); + log("Removed card " + c + "."); } function discard_card_from_hand(hand, c) { @@ -248,16 +301,16 @@ function discard_card_from_hand(hand, c) { game.discard.push(c); if (CARDS[c].reshuffle == 'if_discarded') game.reshuffle = true; - game.log.push(game.active[0] + " discards [" + c + ": " + CARDS[c].title + "]"); + logp("discarded #" + c); } function discard_card(c, reason) { game.last_played = c; discard_card_from_hand(active_hand(), c); if (reason) - game.log.push(game.active[0] + " discards [" + c + ": " + CARDS[c].title + "] " + reason); + logp("discarded #" + c + " " + reason); else - game.log.push(game.active[0] + " discards [" + c + ": " + CARDS[c].title + "]"); + logp("discarded #" + c); } function can_exchange_for_discard(c) { @@ -392,30 +445,30 @@ function is_adjacent_to_american_pc(a) { } function place_british_pc(space) { - game.log.push("B places PC in " + space); + logp("placed PC in " + space); if (game.british_pc_space_list) remove_from_array(game.british_pc_space_list, space); game.pc[space] = BRITISH; } function place_american_pc(space) { - game.log.push("A places PC in " + space); + logp("placed PC in " + space); game.pc[space] = AMERICAN; } function remove_pc(space) { if (game.active == BRITISH) - game.log.push("B removes PC in " + space); + logp("removed PC in " + space); else - game.log.push("A removes PC in " + space); + logp("removed PC in " + space); game.pc[space] = undefined; } function flip_pc(space) { if (game.active == BRITISH) - game.log.push("B flips PC in " + space); + logp("flipped PC in " + space); else - game.log.push("A flips PC in " + space); + logp("flipped PC in " + space); game.pc[space] = ENEMY[game.pc[space]]; } @@ -693,13 +746,13 @@ function capture_washington() { function capture_british_general(where) { let g = find_british_general(where); - game.log.push(g + " is captured!"); + log(g + " was captured!"); move_general(g, CAPTURED_GENERALS); } function capture_american_or_french_general(where) { let g = find_american_or_french_general(where); - game.log.push(g + " is captured!"); + log(g + " was captured!"); if (g == WASHINGTON) capture_washington(); else @@ -715,7 +768,7 @@ function capture_enemy_general(where) { function remove_benedict_arnold() { if (game.generals[ARNOLD].location) { - game.log.push("Arnold is removed from the game!"); + log("Removed Arnold from the game!"); game.generals[ARNOLD].location = null; } } @@ -756,11 +809,11 @@ function place_british_reinforcements(who, count, where) { move_general(already_there, BRITISH_REINFORCEMENTS); } if (who) { - game.log.push("B reinforces " + where + " with " + who); + logp("reinforced " + where + " with " + who); move_general(who, where); } if (count > 0) { - game.log.push("B reinforces " + where + " with " + count + " CU"); + logp("reinforced " + where + " with " + count + " CU"); move_british_cu(BRITISH_REINFORCEMENTS, where, count); } } @@ -775,10 +828,10 @@ function place_american_reinforcements(who, count, where) { move_general(already_there, AMERICAN_REINFORCEMENTS); } if (who) { - game.log.push("A reinforces " + where + " with " + who); + logp("reinforced " + where + " with " + who); move_general(who, where); } - game.log.push("A reinforces " + where + " with " + count + " CU"); + logp("reinforced " + where + " with " + count + " CU"); place_american_cu(where, count); } @@ -792,10 +845,10 @@ function place_french_reinforcements(who, where) { move_general(already_there, AMERICAN_REINFORCEMENTS); } if (who) { - game.log.push("A reinforces " + where + " with " + who); + logp("reinforced " + where + " with " + who); move_general(who, where); } - game.log.push("A reinforces " + where + " with the French CU"); + logp("reinforced " + where + " with the French CU"); move_cu(FRENCH, FRENCH_REINFORCEMENTS, where, count_french_cu(FRENCH_REINFORCEMENTS)); move_cu(FRENCH, AMERICAN_REINFORCEMENTS, where, count_french_cu(AMERICAN_REINFORCEMENTS)); } @@ -848,7 +901,7 @@ function intercept_army(who, from, to) { } function overrun(where) { - game.log.push(game.active[0] + " overruns CU in " + where); + logp("overran CU in " + where); let cu; if (game.active == BRITISH) cu = find_american_cu(where) || find_french_cu(where); @@ -889,7 +942,7 @@ function surrender_british_army(where) { } function disperse_continental_congress(where) { - game.log.push("Contintental Congress dispersed!"); + log("Contintental Congress dispersed!"); game.congress = CONTINENTAL_CONGRESS_DISPERSED; game.congress_was_dispersed = true; } @@ -897,25 +950,25 @@ function disperse_continental_congress(where) { /* MOVE GENERATORS */ function gen_action(action, argument) { - if (!game.actions) - game.actions = {} + if (!view.actions) + view.actions = {} if (argument != undefined) { - if (!(action in game.actions)) - game.actions[action] = [ argument ]; + if (!(action in view.actions)) + view.actions[action] = [ argument ]; else - game.actions[action].push(argument); + view.actions[action].push(argument); } else { - game.actions[action] = 1; + view.actions[action] = 1; } } function gen_action_undo() { - if (!game.actions) - game.actions = {} + if (!view.actions) + view.actions = {} if (game.undo && game.undo.length > 0) - game.actions.undo = 1; + view.actions.undo = 1; else - game.actions.undo = 0; + view.actions.undo = 0; } function gen_pass() { @@ -1003,15 +1056,16 @@ function gen_place_american_pc_in(list_of_colonies) { function goto_committees_of_correspondence() { log(".h2.american Committes of Correspondence"); - log(""); + logbr(); game.active = AMERICAN; game.state = 'committees_of_correspondence'; game.coc = THE_13_COLONIES.slice(); } states.committees_of_correspondence = { + inactive: "Committees of Correspondence", prompt: function (current) { - game.prompt = "Committees of Correspondence: Place 1 PC marker in each of the 13 colonies. " + game.coc.length + " left."; + view.prompt = "Committees of Correspondence: Place 1 PC marker in each of the 13 colonies. " + game.coc.length + " left."; if (game.coc.length > 0) gen_place_american_pc_in(game.coc); else @@ -1030,9 +1084,9 @@ states.committees_of_correspondence = { } function goto_for_the_king() { - log(""); + logbr(); log(".h2.british For the King"); - log(""); + logbr(); delete game.coc; game.active = BRITISH; game.state = 'for_the_king'; @@ -1041,8 +1095,9 @@ function goto_for_the_king() { } states.for_the_king = { + inactive: "For the King", prompt: function (current) { - game.prompt = "For the King: Place 3 PC markers. " + game.count + " left."; + view.prompt = "For the King: Place 3 PC markers. " + game.count + " left."; if (game.count > 0) gen_british_pc_ops(); else @@ -1075,7 +1130,7 @@ function automatic_victory() { game.active = "None"; game.result = BRITISH; game.state = 'game_over'; - game.log.push(game.victory); + log(game.victory); return true; } if (n_british == 0) { @@ -1083,16 +1138,16 @@ function automatic_victory() { game.active = "None"; game.result = AMERICAN; game.state = 'game_over'; - game.log.push(game.victory); + log(game.victory); return true; } return false; } function goto_start_year() { - log(""); + logbr(); log(".h1 Year " + game.year); - log(""); + logbr(); // Prisoner exchange for (let g of BRITISH_GENERALS) @@ -1142,7 +1197,7 @@ function goto_start_year() { states.british_declare_first = { prompt: function (current) { - game.prompt = "Declare yourself as the first player by playing a campaign card?"; + view.prompt = "Declare yourself as the first player by playing a campaign card?"; gen_pass(); for (let c of CAMPAIGN_CARDS) { if (game.b_hand.includes(c)) { @@ -1152,7 +1207,7 @@ states.british_declare_first = { }, card_campaign: function (c) { delete game.congress_was_dispersed; - game.log.push("B goes first by playing a campaign card"); + logp("went first by playing a campaign card"); game.active = BRITISH; goto_campaign(c); }, @@ -1168,16 +1223,16 @@ states.british_declare_first = { states.choose_first_player = { prompt: function (current) { - game.prompt = "Choose who will play the first strategy card."; + view.prompt = "Choose who will play the first strategy card."; gen_action('american_first'); gen_action('british_first'); }, american_first: function (c) { - game.log.push("A goes first"); + logp("went first"); goto_strategy_phase(AMERICAN); }, british_first: function (c) { - game.log.push("B goes first"); + logp("went first"); goto_strategy_phase(BRITISH); }, } @@ -1187,17 +1242,18 @@ states.choose_first_player = { function goto_strategy_phase(new_active) { game.active = new_active; game.state = 'strategy_phase'; - log(""); + logbr(); if (game.active === AMERICAN) log(".h2.american American Turn"); else log(".h2.british British Turn"); - log(""); + logbr(); } states.strategy_phase = { + inactive: "strategy phase", prompt: function (current) { - game.prompt = "Play a strategy card."; + view.prompt = "Play a strategy card."; gen_strategy_plays(active_hand()); }, card_campaign: function (c) { @@ -1250,7 +1306,7 @@ states.strategy_phase = { let d = game.discard.pop(); discard_card(c); active_hand().push(d); - game.log.push(game.active[0] + " picks up " + d + ": " + CARDS[d].title); + logp("picked up up #" + d); }, } @@ -1272,7 +1328,7 @@ function end_strategy_card() { } if (!game.french_alliance_triggered && game.french_alliance == 9) { - game.log.push("The French sign an alliance with the Americans!"); + log("The French signed an alliance with the Americans!"); game.french_alliance_triggered = true; if (game.french_navy == FRENCH_REINFORCEMENTS) { game.save_active = game.active; @@ -1350,7 +1406,7 @@ function gen_strategy_plays(hand) { states.discard_event_pc_action = { prompt: function (current) { - game.prompt = "Place, flip, or remove PC marker."; + view.prompt = "Place, flip, or remove PC marker."; gen_pass(); if (game.active == BRITISH) gen_british_discard_event_pc_action(); @@ -1419,7 +1475,7 @@ function goto_ops_pc(count) { states.ops_pc = { prompt: function (current) { - game.prompt = "Place or flip PC markers. " + game.count + " left."; + view.prompt = "Place or flip PC markers. " + game.count + " left."; gen_pass(); if (game.count > 0) { if (game.active == BRITISH) @@ -1507,8 +1563,8 @@ function goto_ops_reinforcements(c) { states.ops_british_reinforcements_who = { prompt: function (current) { - game.prompt = "Reinforcements: choose an available general or pass to bring only CU." - game.prompt += " Carrying " + game.count + " British CU."; + view.prompt = "Reinforcements: choose an available general or pass to bring only CU." + view.prompt += " Carrying " + game.count + " British CU."; gen_pass(); gen_british_reinforcements_who(); }, @@ -1532,8 +1588,8 @@ states.ops_british_reinforcements_who = { states.ops_british_reinforcements_where = { prompt: function (current) { - game.prompt = "Reinforcements: choose a port space."; - game.prompt += " Carrying " + game.count + " British CU."; + view.prompt = "Reinforcements: choose a port space."; + view.prompt += " Carrying " + game.count + " British CU."; gen_british_reinforcements_where(); }, drop_british_cu: function () { @@ -1551,7 +1607,7 @@ states.ops_british_reinforcements_where = { states.ops_american_reinforcements_who = { prompt: function (current) { - game.prompt = "Reinforcements: choose an available general or pass to bring only CU."; + view.prompt = "Reinforcements: choose an available general or pass to bring only CU."; gen_pass(); gen_american_reinforcements_who(); }, @@ -1569,7 +1625,7 @@ states.ops_american_reinforcements_who = { states.ops_american_reinforcements_where = { prompt: function (current) { - game.prompt = "Reinforcements: choose a space."; + view.prompt = "Reinforcements: choose a space."; gen_american_reinforcements_where(game.who); }, place_reinforcements: function (space) { @@ -1646,11 +1702,11 @@ function goto_ops_general(c) { states.ops_general_who = { prompt: function (current) { if (game.campaign && game.landing_party) - game.prompt = "Campaign: Activate a general or use a landing party. " + game.campaign + " left."; + view.prompt = "Campaign: Activate a general or use a landing party. " + game.campaign + " left."; else if (game.campaign) - game.prompt = "Campaign: Activate a general. " + game.campaign + " left."; + view.prompt = "Campaign: Activate a general. " + game.campaign + " left."; else - game.prompt = "Activate a general with strategy rating " + game.count + " or lower."; + view.prompt = "Activate a general with strategy rating " + game.count + " or lower."; if (game.landing_party) gen_landing_party(); gen_activate_general(); @@ -1714,7 +1770,7 @@ function goto_remove_general(where) { states.remove_general = { prompt: function (current) { - game.prompt = "Remove a general to the reinforcements box."; + view.prompt = "Remove a general to the reinforcements box."; gen_remove_general(); }, select_general: function (g) { @@ -1732,7 +1788,7 @@ function goto_remove_general_after_intercept() { states.remove_general_after_intercept = { prompt: function (current) { - game.prompt = "Remove a general to the reinforcements box."; + view.prompt = "Remove a general to the reinforcements box."; gen_remove_general(); }, select_general: function (g) { @@ -1751,7 +1807,7 @@ function goto_remove_general_after_retreat(where) { states.remove_general_after_retreat = { prompt: function (current) { - game.prompt = "Remove a general to the reinforcements box."; + view.prompt = "Remove a general to the reinforcements box."; gen_remove_general(); }, select_general: function (g) { @@ -1807,27 +1863,27 @@ function goto_ops_general_move(g, marblehead) { states.ops_general_move = { prompt: function (current) { - game.prompt = "Move " + game.who + " with "; + view.prompt = "Move " + game.who + " with "; if (game.carry_british > 0) { - game.prompt += game.carry_british + " British CU."; + view.prompt += game.carry_british + " British CU."; } else if (game.carry_french + game.carry_american > 0) { if (game.carry_french > 0) { if (game.carry_american > 0) { - game.prompt += game.carry_french + " French CU and "; - game.prompt += game.carry_american + " American CU."; + view.prompt += game.carry_french + " French CU and "; + view.prompt += game.carry_american + " American CU."; } else { - game.prompt += game.carry_french + " French CU."; + view.prompt += game.carry_french + " French CU."; } } else { - game.prompt += game.carry_american + " American CU."; + view.prompt += game.carry_american + " American CU."; } } else { - game.prompt += game.carry_american + " no CU."; + view.prompt += game.carry_american + " no CU."; } if (game.count == 1) - game.prompt += " " + game.count + " move left."; + view.prompt += " " + game.count + " move left."; else if (game.count > 1) - game.prompt += " " + game.count + " moves left."; + view.prompt += " " + game.count + " moves left."; // Cannot stop on enemy general if (!has_enemy_general(location_of_general(game.who))) @@ -1946,16 +2002,15 @@ function goto_intercept(from, where) { states.intercept = { prompt: function (current) { - game.prompt = "Intercept " + game.save_who + " in " + game.where + "?"; + view.prompt = "Intercept " + game.save_who + " in " + game.where + "?"; gen_pass(); gen_intercept(); }, select_general: function (g) { - // TODO: roll for intercept! game.moved[g] = 1; let die = roll_d6(); if (die <= GENERALS[g].agility) { - game.log.push(g + " intercepts (" + die + " <= " + GENERALS[g].agility + ")"); + log(g + " intercepted (" + die + " <= " + GENERALS[g].agility + ")"); game.did_intercept = 1; let save_carry_british = game.carry_british; @@ -1974,7 +2029,7 @@ states.intercept = { else end_intercept(); } else { - game.log.push(g + " fails to intercept (" + die + " > " + GENERALS[g].agility + ")"); + log(g + " failed to intercept (" + die + " > " + GENERALS[g].agility + ")"); if (!can_intercept_to(game.where)) end_intercept(); } @@ -2103,8 +2158,8 @@ function goto_campaign(c) { /* EVENTS */ events.the_war_ends = function (c, card) { - game.log.push(game.active[0] + " plays " + c + ": " + CARDS[c].title); - game.log.push("The war will end in " + card.year); + logp("played #" + c); + log("The war will end in " + card.year); game.last_played = c; remove_from_array(active_hand(), c); if (game.war_ends) @@ -2140,13 +2195,13 @@ function advance_french_alliance(count) { game.french_alliance += count; if (game.french_alliance > 9) game.french_alliance = 9; - game.log.push("French alliance advances to " + count); + log("French alliance advanced to " + count); } } function lose_regular_advantage() { if (game.regulars) { - game.log.push("The British Regulars Advantage is lost!"); + log("British Regulars Advantage lost!"); game.regulars = false; advance_french_alliance(2); } @@ -2156,7 +2211,7 @@ events.baron_von_steuben_trains_the_continental_army = function (c, card) { play_card(c); if (is_general_on_map(WASHINGTON)) { let where = location_of_general(WASHINGTON); - game.log.push("A places 2 CU with Washington in " + where); + logp("placed 2 CU with Washington in " + where); place_american_cu(where, 2); lose_regular_advantage(); } @@ -2184,7 +2239,7 @@ events.remove_british_pc_from = function (c, card) { states.remove_british_pc_from = { prompt: function (current) { - game.prompt = "Remove British PC markers from " + game.where.join(", ") + ". " + game.count + " left."; + view.prompt = "Remove British PC markers from " + game.where.join(", ") + ". " + game.count + " left."; gen_pass(); gen_remove_british_pc_from(game.where); }, @@ -2209,7 +2264,7 @@ events.remove_american_pc = function (c, card) { states.remove_american_pc = { prompt: function (current) { - game.prompt = "Remove American PC markers. " + game.count + " left."; + view.prompt = "Remove American PC markers. " + game.count + " left."; gen_pass(); gen_remove_american_pc(); }, @@ -2233,7 +2288,7 @@ events.remove_american_pc_from = function (c, card) { states.remove_american_pc_from = { prompt: function (current) { - game.prompt = "Remove American PC markers from " + game.where.join(", ") + ". " + game.count + " left."; + view.prompt = "Remove American PC markers from " + game.where.join(", ") + ". " + game.count + " left."; gen_pass(); gen_remove_american_pc_from(game.where); }, @@ -2259,7 +2314,7 @@ events.remove_american_pc_from_non_port = function (c, card) { states.remove_american_pc_from_non_port = { prompt: function (current) { - game.prompt = "Remove American PC markers from non-Port space in " + game.where.join(", ") + ". " + game.count + " left."; + view.prompt = "Remove American PC markers from non-Port space in " + game.where.join(", ") + ". " + game.count + " left."; gen_pass(); gen_remove_american_pc_from_non_port(game.where); }, @@ -2284,7 +2339,7 @@ events.remove_american_pc_within_two_spaces_of_a_british_general = function (c, states.remove_american_pc_within_two_spaces_of_a_british_general = { prompt: function (current) { - game.prompt = "Remove American PC markers within two spaces of a British general. " + game.count + " left."; + view.prompt = "Remove American PC markers within two spaces of a British general. " + game.count + " left."; gen_pass(); gen_remove_american_pc_within_two_spaces_of_a_british_general(); }, @@ -2309,7 +2364,7 @@ events.place_american_pc = function (c, card) { states.place_american_pc = { prompt: function (current) { - game.prompt = "Place American PC markers. " + game.count + " left."; + view.prompt = "Place American PC markers. " + game.count + " left."; gen_pass(); gen_place_american_pc(); }, @@ -2333,7 +2388,7 @@ events.place_american_pc_in = function (c, card) { states.place_american_pc_in = { prompt: function (current) { - game.prompt = "Place American PC markers in " + game.where.join(", ") + ". " + game.count + " left."; + view.prompt = "Place American PC markers in " + game.where.join(", ") + ". " + game.count + " left."; gen_pass(); gen_place_american_pc_in(game.where); }, @@ -2359,7 +2414,7 @@ events.lord_sandwich_coastal_raids = function (c, card) { states.lord_sandwich_coastal_raids = { prompt: function (current) { - game.prompt = "Remove two or flip one American PC in a port space."; + view.prompt = "Remove two or flip one American PC in a port space."; gen_pass(); gen_lord_sandwich_coastal_raids(game.where); }, @@ -2395,7 +2450,7 @@ events.remove_american_cu = function (c, card) { states.remove_american_cu = { prompt: function (current) { - game.prompt = "Remove one American CU from any space."; + view.prompt = "Remove one American CU from any space."; gen_pass(); gen_remove_american_cu(); }, @@ -2433,7 +2488,7 @@ events.pennsylvania_and_new_jersey_line_mutinies = function (c, card) { states.pennsylvania_and_new_jersey_line_mutinies = { prompt: function (current) { - game.prompt = "Remove two American CUs from the map, one each from two different spaces."; + view.prompt = "Remove two American CUs from the map, one each from two different spaces."; gen_pass(); gen_pennsylvania_and_new_jersey_line_mutinies(game.where); }, @@ -2465,7 +2520,7 @@ events.john_glovers_marblehead_regiment = function (c, card) { states.john_glovers_marblehead_regiment_who = { prompt: function (current) { - game.prompt = "Activate an American general."; + view.prompt = "Activate an American general."; gen_activate_general(); }, select_general: function (g) { @@ -2483,8 +2538,8 @@ events.declaration_of_independence = function (c, card) { states.declaration_of_independence = { prompt: function (current) { - game.prompt = "Declaration of Independence: Place 1 PC marker in each of the 13 colonies. "; - game.prompt += game.doi.length + " left."; + view.prompt = "Declaration of Independence: Place 1 PC marker in each of the 13 colonies. "; + view.prompt += game.doi.length + " left."; gen_pass(); gen_place_american_pc_in(game.doi); }, @@ -2520,7 +2575,7 @@ function goto_george_washington_captured() { states.george_washington_captured = { prompt: function (current) { - game.prompt = "George Washington is captured! Remove American PC markers. " + game.count + " left."; + view.prompt = "George Washington is captured! Remove American PC markers. " + game.count + " left."; gen_pass(); gen_remove_american_pc(); }, @@ -2587,7 +2642,7 @@ function goto_retreat_before_battle() { states.retreat_before_battle = { prompt: function (current) { - game.prompt = "Attempt retreat before battle?"; + view.prompt = "Attempt retreat before battle?"; gen_pass(); gen_defender_retreat(); }, @@ -2597,12 +2652,12 @@ states.retreat_before_battle = { agility += 2; let roll = roll_d6(); if (roll <= agility) { - game.log.push("A successfully retreats before battle: " + roll + " <= " + agility); + logp("successfully retreated before battle: " + roll + " <= " + agility); pickup_max_american_cu(game.where); move_army(game.who, game.where, to); goto_remove_general_after_retreat_before_battle(to); } else { - game.log.push("A fails to retreat before battle: " + roll + " > " + agility); + logp("failed to retreat before battle: " + roll + " > " + agility); end_retreat_before_battle(); } }, @@ -2623,7 +2678,7 @@ function goto_remove_general_after_retreat_before_battle(to) { states.remove_general_after_retreat_before_battle = { prompt: function (current) { - game.prompt = "Remove a general to the reinforcements box."; + view.prompt = "Remove a general to the reinforcements box."; gen_remove_general(); }, select_general: function (g) { @@ -2715,7 +2770,7 @@ function goto_play_attacker_battle_card() { states.play_attacker_battle_card = { prompt: function (current) { - game.prompt = "Attack: Play or discard event for DRM."; + view.prompt = "Attack: Play or discard event for DRM."; gen_pass(); gen_battle_card(); }, @@ -2755,7 +2810,7 @@ function goto_play_defender_battle_card() { states.play_defender_battle_card = { prompt: function (current) { - game.prompt = "Defend: Play or discard event for DRM."; + view.prompt = "Defend: Play or discard event for DRM."; gen_pass(); gen_battle_card(); }, @@ -3010,9 +3065,9 @@ function resolve_battle() { capture_american_or_french_general(game.where); } - game.log.push("BRITISH BATTLE REPORT:\n" + b_log.join("\n")); - game.log.push("AMERICAN BATTLE REPORT:\n" + a_log.join("\n")); - game.log.push(victor + " victory in " + game.where + "!"); + log("BRITISH BATTLE REPORT:\n" + b_log.join("\n")); + log("AMERICAN BATTLE REPORT:\n" + a_log.join("\n")); + log(victor + " victory in " + game.where + "!"); if (victor == AMERICAN) advance_french_alliance(1); @@ -3036,7 +3091,7 @@ function goto_retreat_after_battle(victor) { states.retreat_after_battle = { prompt: function (current) { - game.prompt = "Retreat after battle."; + view.prompt = "Retreat after battle."; gen_action('surrender'); if (game.active == game.attacker) gen_attacker_retreat(); @@ -3044,7 +3099,7 @@ states.retreat_after_battle = { gen_defender_retreat(); }, move: function (to) { - game.log.push(game.active[0] + " retreats to " + to); + logp("retreated to " + to); if (game.active == BRITISH) retreat_british_army(game.where, to); else @@ -3060,7 +3115,7 @@ states.retreat_after_battle = { let where = game.where; end_battle(); - game.log.push(active[0] + " surrenders"); + logp("surrendered"); if (active == BRITISH) surrender_british_army(where); else @@ -3071,6 +3126,9 @@ states.retreat_after_battle = { function end_battle() { game.active = game.attacker; + if (game.active == BRITISH && game.congress == game.where) + disperse_continental_congress(game.where); + if (game.british_losses >= 3) lose_regular_advantage(); @@ -3097,22 +3155,22 @@ function end_battle() { function apply_single_winter_attrition(owner, space) { let die = roll_d6(); - game.log.push(owner[0] + " attrition roll " + die + " in " + space); + log(owner[0] + " attrition roll " + die + " in " + space); if (die <= 3) { - game.log.push(owner[0] + " lose 1 CU in " + space); + log(owner[0] + " lost 1 CU in " + space); remove_cu(owner, space, 1); } } function apply_winter_attrition(owner, space, n) { let half = Math.floor(n / 2); - game.log.push(owner[0] + " lose " + half + " CU in " + space); + log(owner[0] + " lost " + half + " CU in " + space); remove_cu(owner, space, half); } function goto_winter_attrition_phase() { - game.log.push(""); - game.log.push("Winter Attrition"); + logbr(); + log("Winter Attrition"); for (let space in SPACES) { let wq = is_winter_quarter_space(space); @@ -3148,13 +3206,13 @@ function goto_winter_attrition_phase() { // TODO: let player choose (but why would he ever choose the french?) let lose_american = Math.min(half, n_american); - game.log.push(owner[0] + " lose " + lose_american + " American CU in " + space); + log(owner[0] + " lost " + lose_american + " American CU in " + space); remove_cu(AMERICAN, space, n_american); half -= lose_american; n_american -= lose_american; if (half > 0) { - game.log.push(owner[0] + " lose " + half + " French CU in " + space); + log(owner[0] + " lost " + half + " French CU in " + space); remove_cu(FRENCH, space, half); } } @@ -3187,11 +3245,11 @@ function gen_place_french_navy() { states.place_french_navy_trigger = { prompt: function (current) { - game.prompt = "Place the French Navy in a blockade zone."; + view.prompt = "Place the French Navy in a blockade zone."; gen_place_french_navy(); }, place_navy: function (zone) { - game.log.push("A places French Navy."); + logp("placed French Navy."); game.french_navy = zone; game.active = game.save_active; delete game.save_active; @@ -3201,11 +3259,11 @@ states.place_french_navy_trigger = { states.place_french_navy = { prompt: function (current) { - game.prompt = "Place the French Navy in a blockade zone."; + view.prompt = "Place the French Navy in a blockade zone."; gen_place_french_navy(); }, place_navy: function (zone) { - game.log.push("A places French Navy."); + logp("placed French Navy."); game.french_navy = zone; goto_political_control_phase(); }, @@ -3289,7 +3347,7 @@ function spread_british_path(seen, from) { } function remove_isolated_american_pc_segment() { - game.log.push("Removing isolated American PC"); + log("Removed isolated American PC"); let seen = {}; for (let space in SPACES) { if (is_american_pc_root(space)) { @@ -3303,7 +3361,7 @@ function remove_isolated_american_pc_segment() { } function remove_isolated_british_pc_segment() { - game.log.push("Removing isolated British PC"); + log("Removed isolated British PC"); let seen = {}; for (let space in SPACES) { if (is_british_pc_root(space)) { @@ -3340,7 +3398,7 @@ function goto_political_control_phase() { states.return_continental_congress = { prompt: function () { - game.prompt = "Return Continental Congress to a space in the 13 colonies."; + view.prompt = "Return Continental Congress to a space in the 13 colonies."; if (gen_place_continental_congress() == 0) gen_pass(); }, @@ -3362,7 +3420,7 @@ function goto_political_control_phase_2() { states.european_war = { prompt: function () { - game.prompt = "European War: Remove 2 British CU from any spaces. " + game.count + " left."; + view.prompt = "European War: Remove 2 British CU from any spaces. " + game.count + " left."; gen_pass(); gen_remove_british_cu(); }, @@ -3394,7 +3452,7 @@ function norths_government_falls() { game.active = "None"; game.state = 'game_over'; - game.log.push(game.victory); + log(game.victory); } function goto_end_phase() { @@ -3418,17 +3476,13 @@ function goto_end_phase() { states.game_over = { prompt: function () { - game.prompt = game.victory; + view.prompt = game.victory; } } /* CLIENT/SERVER COMMS */ -exports.ready = function (scenario, options, players) { - return players.length === 2; -} - -exports.setup = function (seed, scenario, players) { +exports.setup = function (seed, scenario, options) { setup_game(seed); return game; } @@ -3447,23 +3501,21 @@ exports.action = function (state, current, action, arg) { throw new Error("Invalid action: " + action); } } + + update_colony_control(); + return game; } function list_actions(current) { - game.actions = {} - game.prompt = ""; + view.actions = {} states[game.state].prompt(current); } exports.view = function(state, current) { game = state; - list_actions(current); - - update_colony_control(); - - let view = { + view = { active: state.active, year: state.year, war_ends: state.war_ends, @@ -3498,11 +3550,13 @@ exports.view = function(state, current) { view.hand = []; if (current == state.active) { + list_actions(current); gen_action_undo(); - view.prompt = state.prompt; - view.actions = state.actions; } else { - view.prompt = "Waiting for " + game.active + " player \u2014 " + game.prompt; + let inactive = states[game.state].inactive; + if (typeof inactive !== 'string') + inactive = game.state; + view.prompt = "Waiting for " + game.active + " player \u2014 " + inactive + "."; } return view; @@ -1,3 +1 @@ insert or ignore into titles ( title_id, title_name, bgg ) values ( 'washingtons-war', 'Washington''s War', 38996 ); -insert or replace into roles values ( 'washingtons-war', 'American' ); -insert or replace into roles values ( 'washingtons-war', 'British' ); |