summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README5
-rw-r--r--play.css331
-rw-r--r--play.html415
-rw-r--r--play.js (renamed from ui.js)419
-rw-r--r--rules.js51
-rw-r--r--title.sql3
6 files changed, 546 insertions, 678 deletions
diff --git a/README b/README
new file mode 100644
index 0000000..705aef7
--- /dev/null
+++ b/README
@@ -0,0 +1,5 @@
+This game is implemented with the generous permission of Columbia Games.
+
+Rules and art assets are Copyright 2002-2019 Columbia Games and Jerry Taylor.
+
+Source code to this digital implementation is Copyright 2021-2022 Tor Andersson.
diff --git a/play.css b/play.css
new file mode 100644
index 0000000..813dfab
--- /dev/null
+++ b/play.css
@@ -0,0 +1,331 @@
+main { background-color: slategray; }
+aside { background-color: silver; }
+header { background-color: silver; }
+header.your_turn { background-color: orange; }
+#role_England .role_name { background-color: salmon; }
+#role_Scotland .role_name { background-color: skyblue; }
+#turn_info { background-color: gainsboro; }
+.role_vp { float: right; }
+
+#log { background-color: whitesmoke; }
+#log div { padding-left: 20px; text-indent: -12px; }
+#log .st { background-color: darkslategray; color: white; font-weight: bold; }
+#log .S { background-color: lightblue; }
+#log .E { background-color: pink; }
+#log .bs { background-color: gainsboro; }
+#log .br { font-style: italic; text-decoration: underline; }
+
+/* CARDS */
+
+.hand {
+ margin: 25px;
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+ min-height: 344px;
+ gap: 24px;
+}
+
+.card_back{background-image: url('cards/card_back.svg')}
+
+.card_truce{background-image:url('cards/card_truce.jpg')}
+.card_herald{background-image:url('cards/card_herald.jpg')}
+.card_sea_move{background-image:url('cards/card_sea_move.jpg')}
+.card_pillage{background-image:url('cards/card_pillage.jpg')}
+.card_victuals{background-image:url('cards/card_victuals.jpg')}
+.card_1{background-image:url('cards/card_1.jpg')}
+.card_2{background-image:url('cards/card_2.jpg')}
+.card_3{background-image:url('cards/card_3.jpg')}
+
+.card {
+ background-size: cover;
+ background-repeat: no-repeat;
+ width: 224px;
+ height: 344px;
+ border-radius: 12px;
+ background-color: #883737;
+ box-shadow: 1px 1px 5px rgba(0,0,0,0.5);
+ transition: 100ms;
+ display: none;
+}
+
+.card.show {
+ display: block;
+}
+
+.card.enabled:hover {
+ transform: translateY(-8px);
+}
+
+.card.enabled {
+ cursor: pointer;
+}
+
+.card.disabled {
+ filter: grayscale(100%);
+}
+
+.role_info {
+ overflow: clip; /* clip dropshadow from filter:grayscale() stacking context */
+ padding-top: 16px;
+}
+
+.role_info .card {
+ width: 168px;
+ height: 258px;
+ border-radius: 9px;
+ margin: 0 auto 16px auto;
+}
+
+.role_info .card:not(:hover) {
+ margin: 0 auto;
+ height: 96px;
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0;
+}
+
+/* MAP */
+
+#mapwrap {
+ box-shadow: 0px 1px 10px rgba(0,0,0,0.5);
+ width: 1688px;
+ height: 1950px;
+}
+
+#map {
+ background-color: darkslategray;
+ width: 1688px;
+ height: 1950px;
+ background-repeat: no-repeat;
+ background-size: cover;
+}
+
+#map { background-image: url("map75.jpg") }
+@media (min-resolution: 97dpi) {
+ #map { background-image: url("map150.jpg") }
+}
+
+#map svg {
+ position: absolute;
+}
+
+#map svg image {
+ pointer-events: none;
+}
+
+#map svg path.area {
+ opacity: 0;
+ fill-opacity: 0.4;
+ fill: white;
+}
+#map svg path.area.where {
+ opacity: 1;
+ fill: darkslategray;
+}
+#map svg path.area.highlight {
+ cursor: pointer;
+ opacity: 1;
+ fill: white;
+}
+
+#map.hide_blocks #blocks {
+ visibility: hidden;
+}
+
+/* TURN MARKER */
+
+div.turn {
+ pointer-events: none;
+ position: absolute;
+ width: 66px;
+ height: 66px;
+ background-size: cover;
+ background-repeat: no-repeat;
+ background-image: url(turn_marker.jpg);
+ box-shadow: 1px 1px 3px rgba(0,0,0,0.5);
+ border-radius: 4px;
+ transition: 700ms ease;
+}
+
+div.turn.year_1297 { left: 1511px; top: 221px; }
+div.turn.year_1298 { left: 1511px; top: 306px; }
+div.turn.year_1299 { left: 1511px; top: 392px; }
+div.turn.year_1300 { left: 1511px; top: 478px; }
+div.turn.year_1301 { left: 1511px; top: 563px; }
+div.turn.year_1302 { left: 1511px; top: 649px; }
+div.turn.year_1303 { left: 1511px; top: 734px; }
+div.turn.year_1304 { left: 1511px; top: 820px; }
+div.turn.year_1305 { left: 1511px; top: 906px; }
+div.turn.year_1306 { left: 1511px; top: 992px; }
+div.turn.year_1307 { left: 1511px; top: 1077px; }
+div.turn.year_1308 { left: 1511px; top: 1163px; }
+div.turn.year_1309 { left: 1511px; top: 1249px; }
+div.turn.year_1310 { left: 1511px; top: 1334px; }
+div.turn.year_1311 { left: 1511px; top: 1420px; }
+div.turn.year_1312 { left: 1511px; top: 1506px; }
+div.turn.year_1313 { left: 1511px; top: 1591px; }
+div.turn.year_1314 { left: 1511px; top: 1677px; }
+
+/* BLOCKS */
+
+body.shift .block.known:hover {
+ transform: scale(2) !important;
+ transition: 100ms;
+ z-index: 100;
+}
+
+.oldblocks div.block { border-radius: 8px; }
+.newblocks div.block { border-radius: 4px; }
+
+#map div.block {
+ position: absolute;
+}
+
+#battle div.block {
+ position: relative;
+}
+
+div.block {
+ background-size: 700% 400%;
+ background-repeat: no-repeat;
+ width: 60px;
+ height: 60px;
+ box-shadow: 0px 0px 3px black;
+}
+
+.oldblocks div.block.England { border: 3px solid brown; background-color: brown; }
+.oldblocks div.block.Scotland { border: 3px solid #06a; background-color: #06a; }
+.oldblocks div.block.highlight { border-color: white; }
+.oldblocks div.block.selected { border-color: yellow; }
+.oldblocks div.block.highlight { box-shadow: 0px 0px 4px 1px white; }
+.oldblocks div.block.selected { box-shadow: 0 0 4px 1px yellow; }
+
+.newblocks div.block.England { border: 2px solid #a12; background-color: #a12; }
+.newblocks div.block.Scotland { border: 2px solid #059; background-color: #059; }
+.newblocks div.block.highlight { box-shadow: 0px 0px 2px 3px white; }
+.newblocks div.block.selected { box-shadow: 0px 0px 2px 3px yellow; }
+
+.oldblocks .battle_menu.hit div.block.highlight { border: 3px solid black; box-shadow: 0px 0px 3px black; }
+.newblocks .battle_menu.hit div.block.highlight { box-shadow: 0px 0px 2px 3px black; }
+
+div.block.highlight { cursor: pointer; }
+div.block.moved { filter: grayscale(50%) brightness(80%); }
+div.block.highlight.moved { filter: grayscale(60%) brightness(95%); }
+
+div.block.r1 { transform: rotate(-90deg); }
+div.block.r2 { transform: rotate(-180deg); }
+div.block.r3 { transform: rotate(-270deg); }
+
+div.block:hover { z-index: 1; }
+
+div.block {
+ transition-property: top, left, transform;
+ transition-duration: 700ms, 700ms, 200ms;
+ transition-timing-function: ease;
+}
+
+/* HERALD DIALOG */
+
+#herald {
+ background-color: white;
+ border: 1px solid black;
+ position: fixed;
+ top: 80px;
+ left: 36px;
+ box-shadow: 0px 5px 10px 0px rgba(0,0,0,0.5);
+ z-index: 50;
+ user-select: none;
+ display: none;
+}
+#herald.show {
+ display: block;
+}
+#herald_header {
+ font-weight: bold;
+ cursor: move;
+ border-bottom: 1px solid black;
+ background-color: lightsteelblue;
+ padding: 3px 1em;
+}
+.herald_noble {
+ padding: 3px 1em;
+ display: none;
+}
+.herald_noble:hover {
+ color: white;
+ background-color: black;
+}
+.herald_noble.show {
+ display: block;
+}
+
+/* BATTLE BOARD */
+
+#battle { background-color: silver; }
+#battle_message { background-color: lightsteelblue; }
+#battle_header { background-color: steelblue; color: white; }
+#FR, #ER { background-color: #acacac; }
+
+/* BLOCKS */
+
+.oldblocks .known.Scotland{background-image:url(old_blocks_scotland.png)}
+.oldblocks .known.England{background-image:url(old_blocks_england.png)}
+.newblocks .known.Scotland{background-image:url(new_blocks_scotland.png)}
+.newblocks .known.England{background-image:url(new_blocks_england.png)}
+
+.known.block_11{background-position:0px 0px}
+.known.block_12{background-position:-60px 0px}
+.known.block_13{background-position:-120px 0px}
+.known.block_14{background-position:-180px 0px}
+.known.block_15{background-position:-240px 0px}
+.known.block_16{background-position:-300px 0px}
+.known.block_17{background-position:-360px 0px}
+.known.block_21{background-position:0px -60px}
+.known.block_22{background-position:-60px -60px}
+.known.block_23{background-position:-120px -60px}
+.known.block_24{background-position:-180px -60px}
+.known.block_25{background-position:-240px -60px}
+.known.block_26{background-position:-300px -60px}
+.known.block_27{background-position:-360px -60px}
+.known.block_31{background-position:0px -120px}
+.known.block_32{background-position:-60px -120px}
+.known.block_33{background-position:-120px -120px}
+.known.block_34{background-position:-180px -120px}
+.known.block_35{background-position:-240px -120px}
+.known.block_36{background-position:-300px -120px}
+.known.block_37{background-position:-360px -120px}
+.known.block_41{background-position:0px -180px}
+.known.block_42{background-position:-60px -180px}
+.known.block_43{background-position:-120px -180px}
+.known.block_44{background-position:-180px -180px}
+.known.block_45{background-position:-240px -180px}
+.known.block_46{background-position:-300px -180px}
+.known.block_47{background-position:-360px -180px}
+.known.block_61{background-position:0px 0px}
+.known.block_62{background-position:-60px 0px}
+.known.block_63{background-position:-120px 0px}
+.known.block_64{background-position:-180px 0px}
+.known.block_65{background-position:-240px 0px}
+.known.block_66{background-position:-300px 0px}
+.known.block_67{background-position:-360px 0px}
+.known.block_71{background-position:0px -60px}
+.known.block_72{background-position:-60px -60px}
+.known.block_73{background-position:-120px -60px}
+.known.block_74{background-position:-180px -60px}
+.known.block_75{background-position:-240px -60px}
+.known.block_76{background-position:-300px -60px}
+.known.block_77{background-position:-360px -60px}
+.known.block_81{background-position:0px -120px}
+.known.block_82{background-position:-60px -120px}
+.known.block_83{background-position:-120px -120px}
+.known.block_84{background-position:-180px -120px}
+.known.block_85{background-position:-240px -120px}
+.known.block_86{background-position:-300px -120px}
+.known.block_87{background-position:-360px -120px}
+.known.block_91{background-position:0px -180px}
+.known.block_92{background-position:-60px -180px}
+.known.block_93{background-position:-120px -180px}
+.known.block_94{background-position:-180px -180px}
+.known.block_95{background-position:-240px -180px}
+.known.block_96{background-position:-300px -180px}
+.known.block_97{background-position:-360px -180px}
diff --git a/play.html b/play.html
index 4de6c2c..4de0aac 100644
--- a/play.html
+++ b/play.html
@@ -6,290 +6,26 @@
<title>HAMMER OF THE SCOTS</title>
<link rel="icon" href="Scottish_Thistle_(Heraldry).svg">
<link rel="stylesheet" href="/fonts/fonts.css">
-<link rel="stylesheet" href="/common/grid.css">
-<link rel="stylesheet" href="/common/battle_abc.css">
-<link rel="stylesheet" href="blocks.css">
-<script defer src="/socket.io/socket.io.min.js"></script>
-<script defer src="/common/client.js"></script>
+<link rel="stylesheet" href="/common/play.css">
+<link rel="stylesheet" href="/common/columbia.css">
+<link rel="stylesheet" href="play.css">
+<script defer src="/common/play.js"></script>
<script defer src="data.js"></script>
-<script defer src="ui.js"></script>
-<style>
-
-#grid_center { background-color: slategray; }
-#grid_role { background-color: silver; }
-#grid_top { background-color: silver; }
-#grid_top.your_turn { background-color: orange; }
-.one .role_name { background-color: salmon; }
-.two .role_name { background-color: skyblue; }
-#turn_info { background-color: gainsboro; }
-
-#log { background-color: whitesmoke; }
-#log .st { background-color: darkslategray; color: white; font-weight: bold; }
-#log .S { background-color: pink; }
-#log .E { background-color: lightblue; }
-#log .bs { background-color: gainsboro; }
-#log .br { font-style: italic; text-decoration: underline; }
-
-/* CARDS */
-
-.card_back{background-image: url('cards/card_back.svg')}
-.card_truce{background-image:url('cards/card_truce.jpg')}
-.card_herald{background-image:url('cards/card_herald.jpg')}
-.card_sea_move{background-image:url('cards/card_sea_move.jpg')}
-.card_pillage{background-image:url('cards/card_pillage.jpg')}
-.card_victuals{background-image:url('cards/card_victuals.jpg')}
-.card_1{background-image:url('cards/card_1.jpg')}
-.card_2{background-image:url('cards/card_2.jpg')}
-.card_3{background-image:url('cards/card_3.jpg')}
-
-.card, .small_card {
- background-color: #893739;
-}
-
-.card {
- width: 225px;
- height: 350px;
- border-radius: 10px;
- background-color: #883737;
-}
-
-.card.enabled:hover {
- transform: scale(1.1);
-}
-
-.role_info { padding: 15px; }
-.small_card { width: 90px; height: 140px; border-radius: 4px; }
-.small_card:hover { width: 180px; height: 280px; border-radius: 8px; }
-
-@media (max-height: 800px) {
- .role_info { padding: 15px 0 0 0; }
- .small_card { width: 180px; height: 80px; border-radius: 8px 8px 0 0; }
- .small_card:hover { width: 180px; height: 280px; border-radius: 8px; margin-bottom: 15px; }
-}
-
-@media (min-height: 1200px) {
- .small_card { width: 180px; height: 280px; border-radius: 8px; }
-}
-
-/* MAP */
-
-#mapwrap {
- position: relative;
- box-shadow: 0px 1px 10px rgba(0,0,0,0.5);
- width: 1688px;
- height: 1950px;
-}
-
-#map {
- position: absolute;
- background-color: darkslategray;
- width: 1688px;
- height: 1950px;
-}
-
-#map svg {
- position: absolute;
-}
-
-#map svg image {
- pointer-events: none;
-}
-
-#map svg path.area {
- opacity: 0;
- fill-opacity: 0.4;
- fill: white;
-}
-#map svg path.area.where {
- opacity: 1;
- fill: darkslategray;
-}
-#map svg path.area.highlight {
- cursor: pointer;
- opacity: 1;
- fill: white;
-}
-
-#map.hide_blocks #blocks {
- visibility: hidden;
-}
-
-/* TURN MARKER */
-
-div.turn {
- pointer-events: none;
- position: absolute;
- width: 66px;
- height: 66px;
- background-size: cover;
- background-repeat: no-repeat;
- background-image: url(turn_marker.jpg);
- box-shadow: 1px 1px 3px rgba(0,0,0,0.5);
- border-radius: 4px;
- transition: 700ms ease;
-}
-
-
-div.turn.year_1297 { left: 1511px; top: 221px; }
-div.turn.year_1298 { left: 1511px; top: 306px; }
-div.turn.year_1299 { left: 1511px; top: 392px; }
-div.turn.year_1300 { left: 1511px; top: 478px; }
-div.turn.year_1301 { left: 1511px; top: 563px; }
-div.turn.year_1302 { left: 1511px; top: 649px; }
-div.turn.year_1303 { left: 1511px; top: 734px; }
-div.turn.year_1304 { left: 1511px; top: 820px; }
-div.turn.year_1305 { left: 1511px; top: 906px; }
-div.turn.year_1306 { left: 1511px; top: 992px; }
-div.turn.year_1307 { left: 1511px; top: 1077px; }
-div.turn.year_1308 { left: 1511px; top: 1163px; }
-div.turn.year_1309 { left: 1511px; top: 1249px; }
-div.turn.year_1310 { left: 1511px; top: 1334px; }
-div.turn.year_1311 { left: 1511px; top: 1420px; }
-div.turn.year_1312 { left: 1511px; top: 1506px; }
-div.turn.year_1313 { left: 1511px; top: 1591px; }
-div.turn.year_1314 { left: 1511px; top: 1677px; }
-
-/* BLOCKS */
-
-body.shift .block.known:hover {
- transform: scale(2) !important;
- transition: 100ms;
- z-index: 100;
-}
-
-.oldblocks div.block { border-radius: 8px; }
-.newblocks div.block { border-radius: 4px; }
-
-#map div.block {
- position: absolute;
-}
-
-#battle div.block {
- position: relative;
-}
-
-div.block {
- background-size: cover;
- background-repeat: no-repeat;
- width: 60px;
- height: 60px;
- box-shadow: 0px 0px 3px black;
-}
-
-.oldblocks div.block.England { border: 3px solid brown; background-color: brown; }
-.oldblocks div.block.Scotland { border: 3px solid #06a; background-color: #06a; }
-.oldblocks div.block.highlight { border-color: white; }
-.oldblocks div.block.selected { border-color: yellow; }
-.oldblocks div.block.highlight { box-shadow: 0px 0px 4px 1px white; }
-.oldblocks div.block.selected { box-shadow: 0 0 4px 1px yellow; }
-
-.newblocks div.block.England { border: 2px solid #a12; background-color: #a12; }
-.newblocks div.block.Scotland { border: 2px solid #059; background-color: #059; }
-.newblocks div.block.highlight { box-shadow: 0px 0px 2px 3px white; }
-.newblocks div.block.selected { box-shadow: 0px 0px 2px 3px yellow; }
-
-.oldblocks .battle_menu.hit div.block.highlight { border: 3px solid black; box-shadow: 0px 0px 3px black; }
-.newblocks .battle_menu.hit div.block.highlight { box-shadow: 0px 0px 2px 3px black; }
-
-div.block.highlight { cursor: pointer; }
-div.block.moved { filter: grayscale(50%) brightness(80%); }
-div.block.highlight.moved { filter: grayscale(60%) brightness(95%); }
-
-div.block.r1 { transform: rotate(-90deg); }
-div.block.r2 { transform: rotate(-180deg); }
-div.block.r3 { transform: rotate(-270deg); }
-
-div.block:hover { z-index: 1; }
-
-div.block {
- transition-property: top, left, transform;
- transition-duration: 700ms, 700ms, 200ms;
- transition-timing-function: ease;
-}
-
-/* HERALD DIALOG */
-
-.herald {
- background-color: white;
- border: 1px solid black;
- position: absolute;
- top: 100px;
- left: 100px;
- box-shadow: 0px 5px 10px 0px rgba(0,0,0,0.5);
- z-index: 50;
- user-select: none;
- visibility: hidden;
-}
-.herald.show {
- visibility: visible;
-}
-.herald_header {
- font-weight: bold;
- cursor: move;
- border-bottom: 1px solid black;
- background-color: lightsteelblue;
- padding: 3px 1em;
-}
-.herald_noble {
- padding: 3px 1em;
- display: none;
-}
-.herald_noble:hover {
- color: white;
- background-color: black;
-}
-.herald_noble.show {
- display: block;
-}
-
-/* BATTLE BOARD */
-
-#battle { background-color: silver; }
-#battle_message { background-color: lightsteelblue; }
-#battle_header { background-color: steelblue; color: white; }
-.battle_separator { background-color: steelblue; }
-
-.battle_line.enemy .battle_menu_list { min-height: 0; }
-.battle_reserves > td > div { height: 66px; }
-.battle_a_cell > div { min-width: 240px; }
-.battle_b_cell > div { min-width: 240px; }
-.battle_c_cell > div { min-width: 240px; }
-
-</style>
+<script defer src="play.js"></script>
</head>
<body class="oldblocks">
-<div id="status"></div>
-
-<div id="chat_window">
-<div id="chat_header">Chat</div>
-<div id="chat_text"></div>
-<form id="chat_form" action=""><input id="chat_input" autocomplete="off"></form>
+<div id="battle">
+<div id="battle_header"></div>
+<div id="ER"></div>
+<div id="EF"></div>
+<div id="FF"></div>
+<div id="FR"></div>
+<div id="battle_message"></div>
</div>
-<table id="battle">
-<tr>
-<th id="battle_header" colspan=4></th>
-<tr class="battle_reserves enemy">
-<td colspan=4><div id="ER"></div></td>
-<tr class="battle_line enemy">
-<td class="battle_a_cell"><div id="EA"></div></td>
-<td class="battle_b_cell"><div id="EB"></div></td>
-<td class="battle_c_cell"><div id="EC"></div></td>
-<tr class="battle_separator">
-<td colspan=4>
-<tr class="battle_line friendly">
-<td class="battle_a_cell"><div id="FA"></div></td>
-<td class="battle_b_cell"><div id="FB"></div></td>
-<td class="battle_c_cell"><div id="FC"></div></td>
-<tr class="battle_reserves friendly">
-<td colspan=4><div id="FR"></div></td>
-<tr>
-<th id="battle_message" colspan=4></th>
-</table>
-
-<div class="herald">
-<div class="herald_header">Name an enemy noble:</div>
+<div id="herald">
+<div id="herald_header">Name an enemy noble:</div>
<div id="herald+Angus" class="herald_noble" onclick="on_herald('Angus')">Angus</div>
<div id="herald+Argyll" class="herald_noble" onclick="on_herald('Argyll')">Argyll</div>
<div id="herald+Atholl" class="herald_noble" onclick="on_herald('Atholl')">Atholl</div>
@@ -305,113 +41,60 @@ div.block {
<div id="herald+Steward" class="herald_noble" onclick="on_herald('Steward')">Steward</div>
</div>
-<div id="grid_window">
-
- <div id="grid_top">
- <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="old_block_style()">Classic labels</div>
- <div class="menu_item" onclick="new_block_style()">New labels</div>
- <div class="menu_separator"></div>
- <div class="menu_item" onclick="window.open('info/notes.html', '_blank')">Notes</div>
- <div class="menu_item" onclick="window.open('info/rules.html', '_blank')">Rules</div>
- <div class="menu_item" onclick="window.open('info/cards.html', '_blank')">Cards</div>
- <div class="menu_item" onclick="window.open('info/blocks.html', '_blank')">Blocks</div>
- <div class="resign menu_separator"></div>
- <div class="resign menu_item" onclick="confirm_resign()">Resign</div>
- </div>
+<header>
+ <div id="toolbar">
+ <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="old_block_style()">Classic labels</div>
+ <div class="menu_item" onclick="new_block_style()">New labels</div>
+ <div class="menu_separator"></div>
+ <div class="menu_item" onclick="window.open('info/notes.html', '_blank')">Notes</div>
+ <div class="menu_item" onclick="window.open('info/rules.html', '_blank')">Rules</div>
+ <div class="menu_item" onclick="window.open('info/cards.html', '_blank')">Cards</div>
+ <div class="menu_item" onclick="window.open('info/blocks.html', '_blank')">Blocks</div>
+ <div class="resign menu_separator"></div>
+ <div class="resign menu_item" onclick="confirm_resign()">Resign</div>
</div>
-
- <div class="image_button" onclick="toggle_blocks()"><img src="/images/earth-africa-europe.svg"></div>
- <div class="image_button" onclick="toggle_zoom()"><img src="/images/magnifying-glass.svg"></div>
- <div class="image_button" onclick="toggle_log()"><img src="/images/scroll-quill.svg"></div>
- <div id="chat_button" class="image_button" onclick="toggle_chat()"><img src="/images/chat-bubble.svg"></div>
-
- <div id="prompt">Connecting...</div>
-
- <button id="end_pillage_button" onclick="on_button_end_pillage()" class="hide">
- End pillage
- </button>
- <button id="end_builds_button" onclick="on_button_end_builds()" class="hide">
- End builds
- </button>
- <button id="end_disbanding_button" onclick="on_button_end_disbanding()" class="hide">
- End disbanding
- </button>
- <button id="winter_button" onclick="on_button_winter()" class="hide">
- Winter
- </button>
- <button id="disband_button" onclick="on_button_disband()" class="hide">
- Disband
- </button>
- <button id="eliminate_button" onclick="on_button_eliminate()" class="hide">
- Eliminate
- </button>
- <button id="end_retreat_button" onclick="on_button_end_retreat()" class="hide">
- End retreat
- </button>
- <button id="end_regroup_button" onclick="on_button_end_regroup()" class="hide">
- End regroup
- </button>
- <button id="end_move_phase_button" onclick="on_button_end_move_phase()" class="hide">
- End move phase
- </button>
- <button id="crown_bruce_button" onclick="on_crown_bruce()" class="hide">
- Coronation: Bruce
- </button>
- <button id="crown_comyn_button" onclick="on_crown_comyn()" class="hide">
- Coronation: Comyn
- </button>
- <button id="return_of_the_king_button" onclick="on_return_of_the_king()" class="hide">
- Return of the King
- </button>
- <button id="play_event_button" onclick="on_button_play_event()" class="hide">
- Play event
- </button>
- <button id="pass_button" onclick="on_button_pass()" class="hide">
- Pass
- </button>
- <button id="undo_button" onclick="on_button_undo()" class="hide">
- Undo
- </button>
-
- <div id="rematch_button" class="image_button hide" onclick="send_rematch()"><img src="/images/cycle.svg"></div>
- <div id="exit_button" class="image_button hide" onclick="send_exit()"><img src="/images/exit-door.svg"></div>
</div>
+ <div class="icon_button" onclick="toggle_blocks()"><img src="/images/earth-africa-europe.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>
+ <div id="prompt"></div>
+ <div id="actions"></div>
+</header>
- <div id="grid_role">
-
- <div class="role one">
+<aside>
+ <div id="roles">
+ <div class="role" id="role_England">
<div class="role_name">
England
<div class="role_vp" id="england_vp"></div>
<div class="role_user">-</div>
</div>
<div class="role_info">
- <div class="small_card card_back" id="england_card"></div>
+ <div class="show card card_back" id="england_card"></div>
</div>
</div>
-
- <div class="role two">
+ <div class="role" id="role_Scotland">
<div class="role_name">
Scotland
<div class="role_vp" id="scotland_vp"></div>
<div class="role_user">-</div>
</div>
<div class="role_info">
- <div class="small_card card_back" id="scotland_card"></div>
+ <div class="show card card_back" id="scotland_card"></div>
</div>
</div>
-
<div id="turn_info">-</div>
</div>
-
<div id="log"></div>
+</aside>
- <div id="grid_center">
+<main>
<div id="mapwrap">
<div id="map">
@@ -888,11 +571,10 @@ c50 53 55 80 28 143 -18 42 -21 62 -16 107 17 147 18 179 6 245 -15 91 -56
<div id="turn" class="turn year_1297"></div>
<div id="blocks"></div>
<div id="offmap" style="visibility:hidden"></div>
-
</div>
</div>
-<div class="hand">
+<div id="cards" class="hand">
<div id="card+1" class="card card_herald"></div>
<div id="card+2" class="card card_pillage"></div>
<div id="card+3" class="card card_sea_move"></div>
@@ -925,7 +607,8 @@ c50 53 55 80 28 143 -18 42 -21 62 -16 107 17 147 18 179 6 245 -15 91 -56
<div id="back+5" class="card card_back"></div>
</div>
- </div>
+</main>
+
+<footer id="status"></footer>
-</div>
</body>
diff --git a/ui.js b/play.js
index 8d525ff..d971c9c 100644
--- a/ui.js
+++ b/play.js
@@ -42,8 +42,7 @@ let ui = {
cards: {},
card_backs: {},
areas: {},
- known: {},
- secret: { England: {}, Scotland: {} },
+ blocks: {},
battle_menu: {},
battle_block: {},
present: new Set(),
@@ -95,32 +94,28 @@ const STEP_TEXT = [ 0, "I", "II", "III", "IIII" ];
function block_name(who) {
if (who === "Edward")
- return game.edward === 1 ? "Edward I" : "Edward II";
+ return view.edward === 1 ? "Edward I" : "Edward II";
if (who === "King")
return "Scottish King";
return BLOCKS[who].name;
}
-function on_focus_secret_block(evt) {
- let owner = evt.target.owner;
- let text = (owner === ENGLAND) ? "English" : "Scottish";
- document.getElementById("status").textContent = text;
-}
-
-function on_blur_secret_block(evt) {
- document.getElementById("status").textContent = "";
-}
-
-function on_click_secret_block(evt) {
+function is_known_block(b) {
+ return (view.game_over || BLOCKS[b].owner === player);
}
function on_focus_map_block(evt) {
let b = evt.target.block;
- let s = game.known[b][1];
- let text = block_name(b);
- text += " " + BLOCKS[b].move + "-" + STEP_TEXT[s] + "-" + BLOCKS[b].combat;
- if (BLOCKS[b].mortal)
- text += ' \u271d';
+ let text;
+ if (is_known_block(b)) {
+ let s = BLOCKS[b].steps;
+ text = block_name(b);
+ text += " " + BLOCKS[b].move + "-" + STEP_TEXT[s] + "-" + BLOCKS[b].combat;
+ if (BLOCKS[b].mortal)
+ text += ' \u271d';
+ } else {
+ text = (BLOCKS[b].owner === ENGLAND) ? "English" : "Scottish";
+ }
document.getElementById("status").textContent = text;
}
@@ -130,7 +125,7 @@ function on_blur_map_block(evt) {
function on_click_map_block(evt) {
let b = evt.target.block;
- if (!game.battle)
+ if (!view.battle)
send_action('block', b);
}
@@ -144,13 +139,13 @@ function is_battle_reserve(who, list) {
function on_focus_battle_block(evt) {
let b = evt.target.block;
let msg = block_name(b);
- if (is_battle_reserve(b, game.battle.ER))
+ if (is_battle_reserve(b, view.battle.ER))
msg = "English Reserve";
- if (is_battle_reserve(b, game.battle.SR))
+ if (is_battle_reserve(b, view.battle.SR))
msg = "Scottish Reserve";
- if (game.actions && game.actions.battle_fire && game.actions.battle_fire.includes(b))
+ if (view.actions && view.actions.battle_fire && view.actions.battle_fire.includes(b))
msg = "Fire with " + msg;
- if (game.actions && game.actions.battle_hit && game.actions.battle_hit.includes(b))
+ if (view.actions && view.actions.battle_hit && view.actions.battle_hit.includes(b))
msg = "Take hit on " + msg;
document.getElementById("status").textContent = msg;
}
@@ -206,66 +201,6 @@ function on_herald(noble) {
send_action('noble', noble);
}
-function on_button_undo(evt) {
- send_action('undo');
-}
-
-function on_button_play_event(evt) {
- send_action('play_event');
-}
-
-function on_button_end_move_phase(evt) {
- send_action('end_move_phase');
-}
-
-function on_button_end_regroup(evt) {
- send_action('end_regroup');
-}
-
-function on_button_end_retreat(evt) {
- send_action('end_retreat');
-}
-
-function on_button_eliminate(evt) {
- send_action('eliminate');
-}
-
-function on_button_disband(evt) {
- send_action('disband');
-}
-
-function on_button_winter(evt) {
- send_action('winter');
-}
-
-function on_button_end_disbanding(evt) {
- send_action('end_disbanding');
-}
-
-function on_button_end_builds(evt) {
- send_action('end_builds');
-}
-
-function on_button_end_pillage(evt) {
- send_action('end_pillage');
-}
-
-function on_button_pass(evt) {
- send_action('pass');
-}
-
-function on_crown_bruce(evt) {
- send_action('crown_bruce');
-}
-
-function on_crown_comyn(evt) {
- send_action('crown_comyn');
-}
-
-function on_return_of_the_king(evt) {
- send_action('return_of_the_king');
-}
-
function build_battle_button(menu, b, c, click, enter, img_src) {
let img = new Image();
img.draggable = false;
@@ -310,10 +245,11 @@ function build_battle_block(b, block) {
menu.classList.add("battle_menu");
menu.appendChild(element);
menu.appendChild(menu_list);
+ menu.block = b;
ui.battle_menu[b] = menu;
}
-function build_known_block(b, block) {
+function build_map_block(b, block) {
let element = document.createElement("div");
element.classList.add("block");
element.classList.add("known");
@@ -323,19 +259,7 @@ function build_known_block(b, block) {
element.addEventListener("mouseleave", on_blur_map_block);
element.addEventListener("click", on_click_map_block);
element.block = b;
- return element;
-}
-
-function build_secret_block(b, block) {
- let element = document.createElement("div");
- element.classList.add("block");
- element.classList.add("secret");
- element.classList.add(BLOCKS[b].owner);
- element.addEventListener("mouseenter", on_focus_secret_block);
- element.addEventListener("mouseleave", on_blur_secret_block);
- element.addEventListener("click", on_click_secret_block);
- element.owner = BLOCKS[b].owner;
- return element;
+ ui.blocks[b] = element;
}
function build_map() {
@@ -362,17 +286,12 @@ function build_map() {
element.addEventListener("click", on_click_area);
ui.areas[name] = element;
}
- ui.secret.England[name] = [];
- ui.secret.Scotland[name] = [];
}
- ui.secret.England.offmap = [];
- ui.secret.Scotland.offmap = [];
for (let b in BLOCKS) {
let block = BLOCKS[b];
build_battle_block(b, block);
- ui.known[b] = build_known_block(b, block);
- ui.secret[BLOCKS[b].owner].offmap.push(build_secret_block(b, block));
+ build_map_block(b, block);
}
}
@@ -514,99 +433,37 @@ function update_map() {
let overflow = { England: [], Scotland: [] };
let layout = {};
- document.getElementById("turn").setAttribute("class", "turn year_" + game.year);
+ document.getElementById("turn").setAttribute("class", "turn year_" + view.year);
for (let area in AREAS)
- layout[area] = { Scotland: [], England: [] };
-
- // Move secret blocks to overflow queue if there are too many in a location
- for (let area in AREAS) {
- for (let color of [ENGLAND, SCOTLAND]) {
- if (game.secret[color]) {
- let max = game.secret[color][area] ? game.secret[color][area][0] : 0;
- while (ui.secret[color][area].length > max) {
- overflow[color].push(ui.secret[color][area].pop());
- }
- }
- }
- }
-
- // Add secret blocks if there are too few in a location
- for (let area in AREAS) {
- for (let color of [ENGLAND, SCOTLAND]) {
- if (game.secret[color]) {
- let max = game.secret[color][area] ? game.secret[color][area][0] : 0;
- while (ui.secret[color][area].length < max) {
- if (overflow[color].length > 0) {
- ui.secret[color][area].push(overflow[color].pop());
- } else {
- let element = ui.secret[color].offmap.pop();
- show_block(element);
- ui.secret[color][area].push(element);
- }
- }
- }
- }
- }
-
- // Remove any blocks left in the overflow queue
- for (let color of [ENGLAND, SCOTLAND]) {
- while (overflow[color].length > 0) {
- let element = overflow[color].pop();
- hide_block(element);
- ui.secret[color].offmap.push(element);
- }
- }
-
- // Hide formerly known blocks
- for (let b in BLOCKS) {
- if (!(b in game.known)) {
- hide_block(ui.known[b]);
- }
- }
-
- // Add secret blocks to layout
- for (let area in AREAS) {
- for (let color of [ENGLAND, SCOTLAND]) {
- let i = 0, n = 0, m = 0;
- if (game.secret[color] && game.secret[color][area]) {
- n = game.secret[color][area][0];
- m = game.secret[color][area][1];
- }
- for (let element of ui.secret[color][area]) {
- if (i++ < n - m)
- element.classList.remove("moved");
- else
- element.classList.add("moved");
- layout[area][color].push(element);
+ layout[area] = { north: [], south: [] };
+
+ for (let b in view.location) {
+ let info = BLOCKS[b];
+ let element = ui.blocks[b];
+ let area = view.location[b];
+ if (area in AREAS) {
+ let moved = view.moved[b] ? " moved" : "";
+ if (is_known_block(b)) {
+ let image = " block_" + info.image;
+ let steps = " r" + (info.steps - view.steps[b]);
+ let known = " known";
+ element.classList = info.owner + known + " block" + image + steps + moved;
+ } else {
+ element.classList = info.owner + " block" + moved;
}
- }
- }
-
- // Add known blocks to layout
- for (let b in game.known) {
- let area = game.known[b][0];
- if (area) {
- let steps = game.known[b][1];
- let moved = game.known[b][2];
- let element = ui.known[b];
- let color = BLOCKS[b].owner;
-
- layout[area][color].push(element);
-
- show_block(element);
- update_steps(b, steps, element);
-
- if (moved)
- element.classList.add("moved");
+ if (info.owner === SCOTLAND)
+ layout[area].north.push(element);
else
- element.classList.remove("moved");
+ layout[area].south.push(element);
+ show_block(element);
+ } else {
+ hide_block(element);
}
}
- // Layout blocks on map
for (let area in AREAS)
- layout_blocks(area, layout[area].Scotland, layout[area].England);
+ layout_blocks(area, layout[area].north, layout[area].south);
// Mark selections and highlights
@@ -616,27 +473,27 @@ function update_map() {
ui.areas[where].classList.remove('where');
}
}
- if (game.actions && game.actions.area)
- for (let where of game.actions.area)
+ if (view.actions && view.actions.area)
+ for (let where of view.actions.area)
ui.areas[where].classList.add('highlight');
- if (game.where)
- ui.areas[game.where].classList.add('where');
+ if (view.where)
+ ui.areas[view.where].classList.add('where');
for (let b in BLOCKS) {
- ui.known[b].classList.remove('highlight');
- ui.known[b].classList.remove('selected');
+ ui.blocks[b].classList.remove('highlight');
+ ui.blocks[b].classList.remove('selected');
}
- if (!game.battle) {
- if (game.actions && game.actions.block)
- for (let b of game.actions.block)
- ui.known[b].classList.add('highlight');
- if (game.who)
- ui.known[game.who].classList.add('selected');
+ if (!view.battle) {
+ if (view.actions && view.actions.block)
+ for (let b of view.actions.block)
+ ui.blocks[b].classList.add('highlight');
+ if (view.who)
+ ui.blocks[view.who].classList.add('selected');
}
}
function update_cards() {
- let cards = game.hand;
+ let cards = view.hand;
for (let c = 1; c <= 25; ++c) {
ui.cards[c].classList.remove('enabled');
if (cards && cards.includes(c))
@@ -645,28 +502,45 @@ function update_cards() {
ui.cards[c].classList.remove('show');
}
- if (player === 'Observer') {
- let n = game.hand.length;
- for (let c = 1; c <= 5; ++c)
- if (c <= n)
- ui.card_backs[c].classList.add("show");
- else
- ui.card_backs[c].classList.remove("show");
- }
+ let n = view.hand.length;
+ for (let c = 1; c <= 5; ++c)
+ if (c <= n && player === 'Observer')
+ ui.card_backs[c].classList.add("show");
+ else
+ ui.card_backs[c].classList.remove("show");
- if (game.actions && game.actions.play) {
- for (let c of game.actions.play)
+ if (view.actions && view.actions.play) {
+ for (let c of view.actions.play)
ui.cards[c].classList.add('enabled');
}
- if (!game.e_card)
- document.getElementById("england_card").className = "small_card card_back";
+ if (!view.e_card)
+ document.getElementById("england_card").className = "show card card_back";
else
- document.getElementById("england_card").className = "small_card " + CARDS[game.e_card].image;
- if (!game.s_card)
- document.getElementById("scotland_card").className = "small_card card_back";
+ document.getElementById("england_card").className = "show card " + CARDS[view.e_card].image;
+ if (!view.s_card)
+ document.getElementById("scotland_card").className = "show card card_back";
else
- document.getElementById("scotland_card").className = "small_card " + CARDS[game.s_card].image;
+ document.getElementById("scotland_card").className = "show card " + CARDS[view.s_card].image;
+}
+
+function compare_blocks(a, b) {
+ let aa = BLOCKS[a].combat;
+ let bb = BLOCKS[b].combat;
+ if (aa === bb)
+ return (a < b) ? -1 : (a > b) ? 1 : 0;
+ return (aa < bb) ? -1 : (aa > bb) ? 1 : 0;
+}
+
+function insert_battle_block(root, node, block) {
+ for (let i = 0; i < root.children.length; ++i) {
+ let prev = root.children[i];
+ if (compare_blocks(prev.block, block) > 0) {
+ root.insertBefore(node, prev);
+ return;
+ }
+ }
+ root.appendChild(node);
}
function update_battle() {
@@ -675,10 +549,13 @@ function update_battle() {
ui.present.clear();
- for (let [block, steps, moved] of list) {
+ for (let block of list) {
ui.present.add(block);
- if (block === game.who)
+ if (!cell.contains(ui.battle_menu[block]))
+ insert_battle_block(cell, ui.battle_menu[block], block);
+
+ if (block === view.who)
ui.battle_block[block].classList.add("selected");
else
ui.battle_block[block].classList.remove("selected");
@@ -689,23 +566,23 @@ function update_battle() {
ui.battle_menu[block].classList.remove('retreat');
ui.battle_menu[block].classList.remove('pass');
- if (game.actions && game.actions.block && game.actions.block.includes(block))
+ if (view.actions && view.actions.block && view.actions.block.includes(block))
ui.battle_block[block].classList.add("highlight");
- if (game.actions && game.actions.battle_fire && game.actions.battle_fire.includes(block))
+ if (view.actions && view.actions.battle_fire && view.actions.battle_fire.includes(block))
ui.battle_menu[block].classList.add('fire');
- if (game.actions && game.actions.battle_retreat && game.actions.battle_retreat.includes(block))
+ if (view.actions && view.actions.battle_retreat && view.actions.battle_retreat.includes(block))
ui.battle_menu[block].classList.add('retreat');
- if (game.actions && game.actions.battle_pass && game.actions.battle_pass.includes(block))
+ if (view.actions && view.actions.battle_pass && view.actions.battle_pass.includes(block))
ui.battle_menu[block].classList.add('pass');
- if (game.actions && game.actions.battle_hit && game.actions.battle_hit.includes(block))
+ if (view.actions && view.actions.battle_hit && view.actions.battle_hit.includes(block))
ui.battle_menu[block].classList.add('hit');
- update_steps(block, steps, ui.battle_block[block], false);
+ update_steps(block, view.steps[block], ui.battle_block[block]);
if (reserve)
ui.battle_block[block].classList.add("secret");
else
ui.battle_block[block].classList.remove("secret");
- if (moved)
+ if (view.moved[block])
ui.battle_block[block].classList.add("moved");
else
ui.battle_block[block].classList.remove("moved");
@@ -716,10 +593,7 @@ function update_battle() {
}
for (let b in BLOCKS) {
- if (ui.present.has(b)) {
- if (!cell.contains(ui.battle_menu[b]))
- cell.appendChild(ui.battle_menu[b]);
- } else {
+ if (!ui.present.has(b)) {
if (cell.contains(ui.battle_menu[b]))
cell.removeChild(ui.battle_menu[b]);
}
@@ -727,66 +601,58 @@ function update_battle() {
}
if (player === ENGLAND) {
- fill_cell("FR", game.battle.ER, true);
- fill_cell("FA", game.battle.EA, false);
- fill_cell("FB", game.battle.EB, false);
- fill_cell("FC", game.battle.EC, false);
- fill_cell("EA", game.battle.SA, false);
- fill_cell("EB", game.battle.SB, false);
- fill_cell("EC", game.battle.SC, false);
- fill_cell("ER", game.battle.SR, true);
+ fill_cell("FR", view.battle.ER, true);
+ fill_cell("FF", view.battle.EF, false);
+ fill_cell("EF", view.battle.SF, false);
+ fill_cell("ER", view.battle.SR, true);
} else {
- fill_cell("ER", game.battle.ER, true);
- fill_cell("EA", game.battle.EA, false);
- fill_cell("EB", game.battle.EB, false);
- fill_cell("EC", game.battle.EC, false);
- fill_cell("FA", game.battle.SA, false);
- fill_cell("FB", game.battle.SB, false);
- fill_cell("FC", game.battle.SC, false);
- fill_cell("FR", game.battle.SR, true);
+ fill_cell("ER", view.battle.ER, true);
+ fill_cell("EF", view.battle.EF, false);
+ fill_cell("FF", view.battle.SF, false);
+ fill_cell("FR", view.battle.SR, true);
}
}
function on_update() {
- show_action_button("#undo_button", "undo");
- show_action_button("#pass_button", "pass");
- show_action_button("#play_event_button", "play_event");
- show_action_button("#end_move_phase_button", "end_move_phase");
- show_action_button("#end_regroup_button", "end_regroup");
- show_action_button("#end_retreat_button", "end_retreat");
- show_action_button("#winter_button", "winter");
- show_action_button("#eliminate_button", "eliminate");
- show_action_button("#disband_button", "disband");
- show_action_button("#end_disbanding_button", "end_disbanding");
- show_action_button("#end_builds_button", "end_builds");
- show_action_button("#end_pillage_button", "end_pillage");
- show_action_button("#crown_bruce_button", "crown_bruce");
- show_action_button("#crown_comyn_button", "crown_comyn");
- show_action_button("#return_of_the_king_button", "return_of_the_king");
-
- document.getElementById("england_vp").textContent = game.e_vp;
- document.getElementById("scotland_vp").textContent = game.s_vp;
- document.getElementById("turn_info").textContent = `Turn ${game.turn} of Year ${game.year}`;
+ action_button("crown_bruce", "Crown Bruce");
+ action_button("crown_comyn", "Crown Comyn");
+ action_button("return_of_the_king", "Return of the King");
+ action_button("play_event", "Play event");
+ action_button("winter", "Winter");
+ action_button("eliminate", "Eliminate");
+ action_button("disband", "Disband");
+ action_button("end_move_phase", "End move phase");
+ action_button("end_regroup", "End regroup");
+ action_button("end_retreat", "End retreat");
+ action_button("end_disbanding", "End disbanding");
+ action_button("end_builds", "End builds");
+ action_button("end_pillage", "End pillage");
+ action_button("pass", "Pass");
+ action_button("undo", "Undo");
+
+ document.getElementById("england_vp").textContent = view.e_vp;
+ document.getElementById("scotland_vp").textContent = view.s_vp;
+ document.getElementById("turn_info").textContent = `Turn ${view.turn} of Year ${view.year}`;
update_cards();
update_map();
- if (game.actions && game.actions.noble) {
- document.querySelector(".herald").classList.add("show");
+ if (view.actions && view.actions.noble) {
+ document.getElementById("herald").classList.add("show");
for (let noble of NOBLES) {
let element = document.getElementById("herald+" + noble);
- if (game.actions.noble.includes(noble))
+ if (view.actions.noble.includes(noble))
element.classList.add("show");
else
element.classList.remove("show");
}
} else {
- document.querySelector(".herald").classList.remove("show");
+ document.getElementById("herald").classList.remove("show");
}
- if (game.battle) {
- document.getElementById("battle_header").textContent = game.battle.title;
- document.getElementById("battle_message").textContent = game.battle.flash;
+ if (view.battle) {
+ document.getElementById("battle_header").textContent = view.battle.title;
+ document.getElementById("battle_message").textContent = view.battle.flash;
document.getElementById("battle").classList.add("show");
update_battle();
} else {
@@ -795,8 +661,5 @@ function on_update() {
}
drag_element_with_mouse("#battle", "#battle_header");
-drag_element_with_mouse(".herald", ".herald_header");
-scroll_with_middle_mouse("#grid_center", 2);
-init_map_zoom();
-init_shift_zoom();
-init_client([ "England", "Scotland" ]);
+drag_element_with_mouse("#herald", "#herald_header");
+scroll_with_middle_mouse("main", 2);
diff --git a/rules.js b/rules.js
index 05e9cc8..6a20e79 100644
--- a/rules.js
+++ b/rules.js
@@ -110,7 +110,7 @@ function clear_undo() {
function push_undo() {
game.undo.push(JSON.stringify(game, (k,v) => {
- if (k === 'undo') return undefined;
+ if (k === 'undo') return 0;
if (k === 'log') return v.length;
return v;
}));
@@ -119,7 +119,7 @@ function push_undo() {
function pop_undo() {
let undo = game.undo;
let save_log = game.log;
- Object.assign(game, JSON.parse(undo.pop()));
+ game = JSON.parse(undo.pop());
game.undo = undo;
save_log.length = game.log;
game.log = save_log;
@@ -756,9 +756,10 @@ function start_year() {
}
function start_game_turn() {
- let turn = 6 - game.e_hand.length;
+ game.turn = 6 - game.e_hand.length;
+
log("");
- log("Start Turn " + turn + " of Year " + game.year + ".");
+ log("Start Turn " + game.turn + " of Year " + game.year + ".");
// Reset movement and attack tracking state
game.truce = false;
@@ -2803,8 +2804,8 @@ states.game_over = {
function make_battle_view() {
let battle = {
- EA: [], EB: [], EC: [], ER: [],
- SA: [], SB: [], SC: [], SR: [],
+ EF: [], ER: [],
+ SF: [], SR: [],
flash: game.flash
};
@@ -2814,17 +2815,13 @@ function make_battle_view() {
function fill_cell(cell, owner, fn) {
for (let b in BLOCKS)
if (game.location[b] === game.where & block_owner(b) === owner && fn(b))
- cell.push([b, game.steps[b], game.moved[b]?1:0])
+ cell.push(b);
}
fill_cell(battle.ER, ENGLAND, b => is_battle_reserve(b));
- fill_cell(battle.EA, ENGLAND, b => !is_battle_reserve(b) && block_initiative(b) === 'A');
- fill_cell(battle.EB, ENGLAND, b => !is_battle_reserve(b) && block_initiative(b) === 'B');
- fill_cell(battle.EC, ENGLAND, b => !is_battle_reserve(b) && block_initiative(b) === 'C');
+ fill_cell(battle.EF, ENGLAND, b => !is_battle_reserve(b));
fill_cell(battle.SR, SCOTLAND, b => is_battle_reserve(b));
- fill_cell(battle.SA, SCOTLAND, b => !is_battle_reserve(b) && block_initiative(b) === 'A');
- fill_cell(battle.SB, SCOTLAND, b => !is_battle_reserve(b) && block_initiative(b) === 'B');
- fill_cell(battle.SC, SCOTLAND, b => !is_battle_reserve(b) && block_initiative(b) === 'C');
+ fill_cell(battle.SF, SCOTLAND, b => !is_battle_reserve(b));
return battle;
}
@@ -2871,7 +2868,7 @@ exports.action = function (state, current, action, arg) {
S[action](arg, current);
else
throw new Error("Invalid action: " + action);
- return state;
+ return game;
}
exports.resign = function (state, current) {
@@ -2884,7 +2881,7 @@ exports.resign = function (state, current) {
game.victory = current + " resigned.";
game.result = ENEMY[current];
}
- return state;
+ return game;
}
function observer_hand() {
@@ -2894,6 +2891,8 @@ function observer_hand() {
return hand;
}
+exports.is_checkpoint = (a, b) => a.turn !== b.turn;
+
exports.view = function(state, current) {
game = state;
@@ -2909,8 +2908,9 @@ exports.view = function(state, current) {
hand: (current === ENGLAND) ? game.e_hand : (current === SCOTLAND) ? game.s_hand : observer_hand(),
who: (game.active === current) ? game.who : null,
where: game.where,
- known: {},
- secret: { Scotland: {}, England: {} },
+ location: game.location,
+ steps: game.steps,
+ moved: game.moved,
battle: null,
active: game.active,
prompt: null,
@@ -2922,22 +2922,5 @@ exports.view = function(state, current) {
if (states[game.state].show_battle)
view.battle = make_battle_view();
- for (let b in BLOCKS) {
- let a = game.location[b];
- if (current === block_owner(b) || game.state === 'game_over') {
- if (a)
- view.known[b] = [a, game.steps[b], game.moved[b] ? 1 : 0];
- } else {
- if (a) {
- let list = view.secret[block_owner(b)];
- if (!(a in list))
- list[a] = [0, 0];
- list[a][0]++;
- if (game.moved[b])
- list[a][1]++;
- }
- }
- }
-
return view;
}
diff --git a/title.sql b/title.sql
new file mode 100644
index 0000000..c53d64c
--- /dev/null
+++ b/title.sql
@@ -0,0 +1,3 @@
+insert or replace into titles ( title_id, title_name, bgg ) values ( 'hammer-of-the-scots', 'Hammer of the Scots', 3685 );
+insert or replace into roles values ( 'hammer-of-the-scots', 'England' );
+insert or replace into roles values ( 'hammer-of-the-scots', 'Scotland' );