begin endgame logic, render dame

This commit is contained in:
Sorrel Bri 2019-08-06 14:13:51 -07:00
parent da8d360a5f
commit 358bfe20d4
3 changed files with 153 additions and 60 deletions

View file

@ -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 {
@ -350,4 +363,65 @@ td .dot .seki {
grid-template-rows: auto auto 60vw auto; grid-template-rows: auto auto 60vw auto;
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;
}
}

View file

@ -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>

View file

@ -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