summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--about.html1
-rw-r--r--play.css41
-rw-r--r--play.html91
-rw-r--r--play.js197
-rw-r--r--rules.js366
-rw-r--r--title.sql2
6 files changed, 349 insertions, 349 deletions
diff --git a/about.html b/about.html
index 71b5eee..3a39766 100644
--- a/about.html
+++ b/about.html
@@ -1,7 +1,6 @@
<p>
Unlicensed game prototype!
-<br clear=left>
<ul>
<li><a href="/washingtons-war/info/rulebook.html">Rulebook</a>
diff --git a/play.css b/play.css
index 9b3d60c..d2c6c28 100644
--- a/play.css
+++ b/play.css
@@ -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;
}
diff --git a/play.html b/play.html
index 435c237..9236937 100644
--- a/play.html
+++ b/play.html
@@ -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()">&#x1F41E; Save</div>
- <div class="menu_item" onclick="send_restore()">&#x1F41E; Restore</div>
- <div class="menu_separator"></div>
- <div class="menu_item" onclick="send_restart()">&#x26a0; 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">
diff --git a/play.js b/play.js
index 3e1e763..3a0c7ec 100644
--- a/play.js
+++ b/play.js
@@ -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, "&amp;");
text = text.replace(/</g, "&lt;");
@@ -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"]);
diff --git a/rules.js b/rules.js
index 09f5a11..70891a4 100644
--- a/rules.js
+++ b/rules.js
@@ -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;
diff --git a/title.sql b/title.sql
index be6fe09..675540a 100644
--- a/title.sql
+++ b/title.sql
@@ -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' );