begin endgame logic, render dame
This commit is contained in:
parent
da8d360a5f
commit
358bfe20d4
3 changed files with 153 additions and 60 deletions
90
css/main.css
90
css/main.css
|
@ -1,9 +1,10 @@
|
||||||
@import url('https://fonts.googleapis.com/css?family=La+Belle+Aurore|Raleway:300,600');
|
@import url('https://fonts.googleapis.com/css?family=La+Belle+Aurore|Raleway:300|Raleway:600');
|
||||||
|
|
||||||
* {
|
* {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
|
font-family: 'Raleway', sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
@ -19,13 +20,15 @@ body {
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
background-color: rgba(0,0,0,0.3);
|
background-color: rgba(0,0,0,0.3);
|
||||||
align-items: center;
|
align-items: flex-start;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#menu {
|
#menu {
|
||||||
|
position: relative;
|
||||||
background-color: rgb(250, 2250, 255, 0.9);
|
background-color: rgb(250, 2250, 255, 0.9);
|
||||||
padding: 1vmin;
|
padding: 1vmin;
|
||||||
display: grid;
|
display: grid;
|
||||||
|
@ -37,6 +40,7 @@ body {
|
||||||
"record"
|
"record"
|
||||||
"submit";
|
"submit";
|
||||||
font: 14px 'La Belle Aurore', cursive;
|
font: 14px 'La Belle Aurore', cursive;
|
||||||
|
min-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#menu .menu-subblock {
|
#menu .menu-subblock {
|
||||||
|
@ -56,7 +60,7 @@ body {
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
}
|
}
|
||||||
|
|
||||||
h4.menu-heading {
|
h4 {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
margin: 1em .25em 0 .25em;
|
margin: 1em .25em 0 .25em;
|
||||||
font-size: 110%;
|
font-size: 110%;
|
||||||
|
@ -100,7 +104,7 @@ div[data-player-meta] label {
|
||||||
|
|
||||||
#instructions, #game-record{
|
#instructions, #game-record{
|
||||||
border: 2px solid black;
|
border: 2px solid black;
|
||||||
height: 100%
|
height: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#instructions:::-webkit-scrollbar-track {
|
#instructions:::-webkit-scrollbar-track {
|
||||||
|
@ -148,6 +152,7 @@ content {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-around;
|
justify-content: space-around;
|
||||||
flex: 5;
|
flex: 5;
|
||||||
|
height: 9vmin;
|
||||||
}
|
}
|
||||||
|
|
||||||
.player-pos#white-pos {
|
.player-pos#white-pos {
|
||||||
|
@ -221,8 +226,9 @@ content {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.name-space p {
|
.name-space h4 {
|
||||||
margin-bottom: 2vh;
|
font-size: 120%;
|
||||||
|
color: rgb(255,240,230)
|
||||||
}
|
}
|
||||||
|
|
||||||
#board-space {
|
#board-space {
|
||||||
|
@ -291,6 +297,13 @@ content {
|
||||||
background: conic-gradient(#000 0%, rgba(0,0,0,0) 1%, rgba(0,0,0,0) 74%, #000 75%, rgba(0,0,0,0) 76%, rgba(0,0,0,0) 99%, #000 100%);
|
background: conic-gradient(#000 0%, rgba(0,0,0,0) 1%, rgba(0,0,0,0) 74%, #000 75%, rgba(0,0,0,0) 76%, rgba(0,0,0,0) 99%, #000 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#board-space td * * div.hoshi { /* to be added later */
|
||||||
|
background: radial-gradient(circle farthest-corner at center, #000 0%, #000 30%, rgba(0,0,0,0) 50%);
|
||||||
|
z-index: 3;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%
|
||||||
|
}
|
||||||
|
|
||||||
td .stone {
|
td .stone {
|
||||||
width: 85%;
|
width: 85%;
|
||||||
height: 85%;
|
height: 85%;
|
||||||
|
@ -331,8 +344,8 @@ td .dot[data-dot="black"] {
|
||||||
td .dot[data-dot="none"] {
|
td .dot[data-dot="none"] {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
td .dot .dame {
|
td .dot[data-dot="dame"] {
|
||||||
|
background-color: purple;
|
||||||
}
|
}
|
||||||
td .dot .seki {
|
td .dot .seki {
|
||||||
|
|
||||||
|
@ -351,3 +364,64 @@ td .dot .seki {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media only screen and (min-width: 500px) {
|
||||||
|
.player-pos {
|
||||||
|
height: 14vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
#kifu {
|
||||||
|
order: 0;
|
||||||
|
height: 12vh;
|
||||||
|
width: 9vh;
|
||||||
|
background-color: #FFF;
|
||||||
|
transform: rotate(-20deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bowl {
|
||||||
|
margin: 2vh;
|
||||||
|
height: 12vh;
|
||||||
|
width: 12vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.caps-space {
|
||||||
|
margin: 1vh;
|
||||||
|
height: 8vh;
|
||||||
|
width: 8vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
#board-space {
|
||||||
|
margin: 0 auto;
|
||||||
|
/* grid-area: board-space; */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
background-color: #EAB24E;
|
||||||
|
/* width: 90vmin; */
|
||||||
|
/* height: 90vmin; */
|
||||||
|
padding: 1vmin;
|
||||||
|
z-index: 1;
|
||||||
|
box-shadow: -2vmin 4vmin 3vmin rgba(145, 92, 23, 0.5);
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#board-space table {
|
||||||
|
display: flex;
|
||||||
|
align-items: stretch;
|
||||||
|
justify-content: space-between;
|
||||||
|
height: 72vmin;
|
||||||
|
width: 72min;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#board-space td {
|
||||||
|
height: 8vmin;
|
||||||
|
width: 8vmin;
|
||||||
|
background: conic-gradient(#000 0%, rgba(0,0,0,0) 1%, rgba(0,0,0,0) 24%, #000 25%, rgba(0,0,0,0) 26%, rgba(0,0,0,0) 49%, #000 50%, rgba(0,0,0,0) 51%, rgba(0,0,0,0) 74%, #000 75%, rgba(0,0,0,0) 76%, rgba(0,0,0,0) 99%, #000 100%);
|
||||||
|
border-radius: 50% solid black;
|
||||||
|
color: black;
|
||||||
|
margin: auto;
|
||||||
|
padding: 0;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
49
index.html
49
index.html
|
@ -28,49 +28,6 @@
|
||||||
<h4 class="menu-heading">Black</h4>
|
<h4 class="menu-heading">Black</h4>
|
||||||
<span class="menu-heading">Name:</span><input type="text" name="black-name">
|
<span class="menu-heading">Name:</span><input type="text" name="black-name">
|
||||||
<span class="menu-heading">Rank:</span><input type="number" id="black-rank" max="38" steps="1" placeholder="15" name="black-rank">
|
<span class="menu-heading">Rank:</span><input type="number" id="black-rank" max="38" steps="1" placeholder="15" name="black-rank">
|
||||||
<!-- <div id=> -->
|
|
||||||
<!-- <datalist class="rank-tick">
|
|
||||||
<span>30k</span>
|
|
||||||
<span>29k</span>
|
|
||||||
<span>28k</span>
|
|
||||||
<span>27k</span>
|
|
||||||
<span>26k</span>
|
|
||||||
<span>25k</span>
|
|
||||||
<span>24k</span>
|
|
||||||
<span>23k</span>
|
|
||||||
<span>22k</span>
|
|
||||||
<span>21k</span>
|
|
||||||
<span>20k</span>
|
|
||||||
<span>19k</span>
|
|
||||||
<span>18k</span>
|
|
||||||
<span>17k</span>
|
|
||||||
<span>16k</span>
|
|
||||||
<span>15k</span>
|
|
||||||
<span>14k</span>
|
|
||||||
<span>13k</span>
|
|
||||||
<span>12k</span>
|
|
||||||
<span>11k</span>
|
|
||||||
<span>10k</span>
|
|
||||||
<span>9k</span>
|
|
||||||
<span>8k</span>
|
|
||||||
<span>7k</span>
|
|
||||||
<span>6k</span>
|
|
||||||
<span>5k</span>
|
|
||||||
<span>4k</span>
|
|
||||||
<span>3k</span>
|
|
||||||
<span>2k</span>
|
|
||||||
<span>1k</span>
|
|
||||||
<span>1d</span>
|
|
||||||
<span>2d</span>
|
|
||||||
<span>3d</span>
|
|
||||||
<span>4d</span>
|
|
||||||
<span>5d</span>
|
|
||||||
<span>6d</span>
|
|
||||||
<span>7d</span>
|
|
||||||
<span>8d</span>
|
|
||||||
<span>9d</span>
|
|
||||||
</ul>
|
|
||||||
</div> -->
|
|
||||||
<input type="checkbox" name="black-rank-certain"><label for="black-rank-certain">Rank Certainty</label>
|
<input type="checkbox" name="black-rank-certain"><label for="black-rank-certain">Rank Certainty</label>
|
||||||
</div>
|
</div>
|
||||||
<div data-player-meta="white">
|
<div data-player-meta="white">
|
||||||
|
@ -100,9 +57,9 @@
|
||||||
</div>
|
</div>
|
||||||
<content>
|
<content>
|
||||||
<div id="white-pos" class="player-pos">
|
<div id="white-pos" class="player-pos">
|
||||||
<div id="white-bowl" class="bowl"><p>Pass?</p></div>
|
<div id="white-bowl" class="bowl"><p>Pass?</p><div id="stone-image"></div></div>
|
||||||
<div id="white-player-space" class="name-space">
|
<div id="white-player-space" class="name-space">
|
||||||
<p id="white-player-name">Test Name rk</p>
|
<h4 id="white-player-name">Test Name rk</h4>
|
||||||
<div id="white-caps-space" class="caps-space"><p id="white-caps"></p></div>
|
<div id="white-caps-space" class="caps-space"><p id="white-caps"></p></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -374,7 +331,7 @@
|
||||||
<div id="black-pos" class="player-pos">
|
<div id="black-pos" class="player-pos">
|
||||||
<div id="black-bowl" class="bowl"><p>Pass?</p></div>
|
<div id="black-bowl" class="bowl"><p>Pass?</p></div>
|
||||||
<div id="black-player-space" class="name-space">
|
<div id="black-player-space" class="name-space">
|
||||||
<p id="black-player-name">Test Name rk</p>
|
<h4 id="black-player-name">Test Name rk</h4>
|
||||||
<div id="black-caps-space" class="caps-space"><p id="black-caps"></p></div>
|
<div id="black-caps-space" class="caps-space"><p id="black-caps"></p></div>
|
||||||
</div> <div id="kifu">
|
</div> <div id="kifu">
|
||||||
<table>
|
<table>
|
||||||
|
|
72
js/main.js
72
js/main.js
|
@ -15,6 +15,11 @@ const DOTS_DATA = {
|
||||||
's': 'seki'
|
's': 'seki'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ranks = ['30k', '29k', '28k', '27k', '26k', '25k', '24k', '23k', '22k', '21k', '20k',
|
||||||
|
'19k', '18k', '17k', '16k', '15k', '14k', '13k', '12k', '11k', '10k',
|
||||||
|
'9k', '8k', '7k', '6k', '5k', '4k', '3k', '2k', '1k',
|
||||||
|
'1d', '2d', '3d', '4d', '5d', '6d', '7d', '8d', '9d']
|
||||||
|
|
||||||
const gameState = {
|
const gameState = {
|
||||||
winner: null,
|
winner: null,
|
||||||
turn: 1, // turn logic depends on handicap stones
|
turn: 1, // turn logic depends on handicap stones
|
||||||
|
@ -65,6 +70,7 @@ class Point {
|
||||||
this.pos = [ x, y ]
|
this.pos = [ x, y ]
|
||||||
this.stone = 0; // this is where move placement will go 0, 1, -1 'k'
|
this.stone = 0; // this is where move placement will go 0, 1, -1 'k'
|
||||||
this.legal;
|
this.legal;
|
||||||
|
this.territory;
|
||||||
this.capturing = [];
|
this.capturing = [];
|
||||||
this.groupMembers = [];
|
this.groupMembers = [];
|
||||||
this.neighbors = {
|
this.neighbors = {
|
||||||
|
@ -101,8 +107,13 @@ class Point {
|
||||||
for (let frn of frns) {
|
for (let frn of frns) {
|
||||||
this.groupMembers.push(frn);
|
this.groupMembers.push(frn);
|
||||||
}
|
}
|
||||||
|
console.log(this);
|
||||||
|
console.log(this.groupMembers)
|
||||||
// this.groupMembers = Array.from(new Set(this.groupMembers));
|
// this.groupMembers = Array.from(new Set(this.groupMembers));
|
||||||
|
if (!this.groupMembers.length) return;
|
||||||
for (let grpMem in this.groupMembers) {
|
for (let grpMem in this.groupMembers) {
|
||||||
|
debugger;
|
||||||
|
console.log(this);
|
||||||
this.groupMembers = Array.from(new Set(this.groupMembers.concat(this.groupMembers[grpMem].groupMembers)));
|
this.groupMembers = Array.from(new Set(this.groupMembers.concat(this.groupMembers[grpMem].groupMembers)));
|
||||||
}
|
}
|
||||||
for (let grpMem in this.groupMembers) {
|
for (let grpMem in this.groupMembers) {
|
||||||
|
@ -120,6 +131,7 @@ class Point {
|
||||||
this.capturing = this.capturing.concat(opp.groupMembers);
|
this.capturing = this.capturing.concat(opp.groupMembers);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
this.capturing = Array.from(new Set(this.capturing));
|
||||||
return this.capturing;
|
return this.capturing;
|
||||||
}
|
}
|
||||||
checkGroup = () => { // liberty is true when called by move false when called by check Capture
|
checkGroup = () => { // liberty is true when called by move false when called by check Capture
|
||||||
|
@ -155,7 +167,7 @@ const handiSliderEl = document.querySelector('input[name="handicap-slider"]');
|
||||||
// ::hover-over on board to preview move (with legal move logic)
|
// ::hover-over on board to preview move (with legal move logic)
|
||||||
document.getElementById('board').addEventListener('mousemove', hoverPreview);
|
document.getElementById('board').addEventListener('mousemove', hoverPreview);
|
||||||
// click on board to play move
|
// click on board to play move
|
||||||
document.getElementById('board').addEventListener('click', clickPlaceStone);
|
document.getElementById('board').addEventListener('click', clickBoard);
|
||||||
// ::hover-over on either bowl for pass, one-level undo options (CSS implementation)
|
// ::hover-over on either bowl for pass, one-level undo options (CSS implementation)
|
||||||
// click on menu items
|
// click on menu items
|
||||||
// click on kifu to display game menu
|
// click on kifu to display game menu
|
||||||
|
@ -220,6 +232,7 @@ function playerResign() {
|
||||||
|
|
||||||
function hoverPreview(evt) {
|
function hoverPreview(evt) {
|
||||||
evt.stopPropagation();
|
evt.stopPropagation();
|
||||||
|
if (gameState.pass > 1 || gameState.winner) return;
|
||||||
// renders preview stone if move is legal
|
// renders preview stone if move is legal
|
||||||
let hover = [ parseInt(evt.target.closest('td').id[0]), parseInt(evt.target.closest('td').id[2]) ];
|
let hover = [ parseInt(evt.target.closest('td').id[0]), parseInt(evt.target.closest('td').id[2]) ];
|
||||||
let point = findPointFromIdx(hover);
|
let point = findPointFromIdx(hover);
|
||||||
|
@ -265,11 +278,18 @@ function resolveCaptures(point) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkKo(point, cap) {
|
function checkKo(point, cap) {
|
||||||
if (point.getLiberties().length === 1 && cap.checkNeighbors(stone => stone.stone === gameState.turn * -1)) return true;
|
console.log(point);
|
||||||
|
console.log(point.getLiberties());
|
||||||
|
console.log(cap);
|
||||||
|
console.log(cap.checkNeighbors());
|
||||||
|
console.log(`${STONES_DATA[gameState.turn]}: ${point.pos[0]},${point.pos[1]}`)
|
||||||
|
if (!point.getLiberties().length && cap.checkNeighbors().filter(stone => stone.stone === gameState.turn * -1)
|
||||||
|
&& point.capturing.length === 1) return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function clickPlaceStone(evt) {
|
function clickBoard(evt) {
|
||||||
evt.stopPropagation();
|
evt.stopPropagation();
|
||||||
|
if (gameState.pass > 1 || gameState.winner) return;
|
||||||
// checks for placement and pushes to cell
|
// checks for placement and pushes to cell
|
||||||
let placement = [ parseInt(evt.target.closest('td').id[0]), parseInt(evt.target.closest('td').id[2]) ];
|
let placement = [ parseInt(evt.target.closest('td').id[0]), parseInt(evt.target.closest('td').id[2]) ];
|
||||||
let point = findPointFromIdx(placement);
|
let point = findPointFromIdx(placement);
|
||||||
|
@ -423,16 +443,34 @@ function init() {
|
||||||
};
|
};
|
||||||
|
|
||||||
function render(hoverPoint) {
|
function render(hoverPoint) {
|
||||||
|
if (gameState.winner || gameState.pass > 1) {
|
||||||
|
renderTerritory();
|
||||||
|
}
|
||||||
gameState.gameRecord.length? renderTurn() : renderFirstTurn();
|
gameState.gameRecord.length? renderTurn() : renderFirstTurn();
|
||||||
renderBoard();
|
renderBoard();
|
||||||
renderCaps();
|
renderCaps();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderTerritory() {
|
||||||
|
console.log('rendering territory')
|
||||||
|
boardState.forEach(val => {
|
||||||
|
let stoneElem = document.getElementById(`${val.pos[0]}-${val.pos[1]}`).childNodes[1].childNodes[0];
|
||||||
|
console.log(stoneElem)
|
||||||
|
stoneElem.setAttribute("data-dot", DOTS_DATA[val.territory]);
|
||||||
|
})
|
||||||
|
console.log('rendering finished')
|
||||||
|
}
|
||||||
|
|
||||||
function renderFirstTurn() {
|
function renderFirstTurn() {
|
||||||
document.getElementById(`${STONES_DATA[gameState.turn]}-bowl`).toggleAttribute('data-turn');
|
document.getElementById(`${STONES_DATA[gameState.turn]}-bowl`).toggleAttribute('data-turn');
|
||||||
}
|
}
|
||||||
function renderTurn() {
|
function renderTurn() {
|
||||||
document.querySelectorAll(`.bowl`).forEach(bowl => bowl. toggleAttribute('data-turn'));
|
if (gameState.winner || gameState.pass > 1) document.querySelectorAll(`.bowl`).forEach(bowl => {
|
||||||
|
bowl.removeAttribute('data-turn');
|
||||||
|
bowl.toggleAttribute('data-turn');
|
||||||
|
|
||||||
|
});
|
||||||
|
document.querySelectorAll(`.bowl`).forEach(bowl => bowl.toggleAttribute('data-turn'));
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderBoard() {
|
function renderBoard() {
|
||||||
|
@ -455,8 +493,32 @@ function renderPreview(hoverPoint) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function endGame() {
|
function endGameSetTerritory() {
|
||||||
|
console.log('ending game');
|
||||||
|
boardState.forEach(pt => {
|
||||||
|
pt.territory = pt.stone ? 'd' : 'd'
|
||||||
|
console.log(pt);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function endGame() {
|
||||||
|
endGameSetTerritory()
|
||||||
|
|
||||||
|
// join all remaining groups
|
||||||
|
// check remaining groups life
|
||||||
|
// search empty spaces on board for deadShapes
|
||||||
|
// compare spaces to rotations of deadShapes[...]
|
||||||
|
// 'd' if empty spaces
|
||||||
|
|
||||||
|
render();
|
||||||
|
// return dead group suggestion
|
||||||
|
// users can flip status of any dead group overlay( 1, -1 )
|
||||||
|
// confirm state
|
||||||
|
// calculate score = points in overlay for each player + captures
|
||||||
|
// render final board state with dead groups removed
|
||||||
|
// log game record
|
||||||
|
// stringify according to .sgf format
|
||||||
|
// log as text
|
||||||
}
|
}
|
||||||
|
|
||||||
// functions
|
// functions
|
||||||
|
|
Loading…
Reference in a new issue