diff options
-rw-r--r-- | README | 5 | ||||
-rw-r--r-- | play.css | 331 | ||||
-rw-r--r-- | play.html | 415 | ||||
-rw-r--r-- | play.js (renamed from ui.js) | 419 | ||||
-rw-r--r-- | rules.js | 51 | ||||
-rw-r--r-- | title.sql | 3 |
6 files changed, 546 insertions, 678 deletions
@@ -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} @@ -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> @@ -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); @@ -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' ); |