diff --git a/css/main.css b/css/main.css index 5226a3f..1c0e339 100644 --- a/css/main.css +++ b/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; margin: 0; vertical-align: middle; + font-family: 'Raleway', sans-serif; } body { @@ -19,13 +20,15 @@ body { width: 100vw; height: 100vh; background-color: rgba(0,0,0,0.3); - align-items: center; + align-items: flex-start; justify-content: center; visibility: hidden; overflow-y: scroll; + } #menu { + position: relative; background-color: rgb(250, 2250, 255, 0.9); padding: 1vmin; display: grid; @@ -37,6 +40,7 @@ body { "record" "submit"; font: 14px 'La Belle Aurore', cursive; + min-height: 0; } #menu .menu-subblock { @@ -56,7 +60,7 @@ body { font-weight: 300; } -h4.menu-heading { +h4 { font-weight: 600; margin: 1em .25em 0 .25em; font-size: 110%; @@ -100,7 +104,7 @@ div[data-player-meta] label { #instructions, #game-record{ border: 2px solid black; -height: 100% +height: 1; } #instructions:::-webkit-scrollbar-track { @@ -148,6 +152,7 @@ content { align-items: center; justify-content: space-around; flex: 5; + height: 9vmin; } .player-pos#white-pos { @@ -221,8 +226,9 @@ content { align-items: center; } -.name-space p { - margin-bottom: 2vh; +.name-space h4 { + font-size: 120%; + color: rgb(255,240,230) } #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%); } +#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 { width: 85%; height: 85%; @@ -331,8 +344,8 @@ td .dot[data-dot="black"] { td .dot[data-dot="none"] { background-color: transparent; } -td .dot .dame { - +td .dot[data-dot="dame"] { + background-color: purple; } td .dot .seki { @@ -350,4 +363,65 @@ td .dot .seki { grid-template-rows: auto auto 60vw auto; font-size: 14px; } -} \ No newline at end of file +} + +@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; + } + +} diff --git a/index.html b/index.html index 0ee1595..528b198 100644 --- a/index.html +++ b/index.html @@ -28,49 +28,6 @@ Name: Rank: - -
@@ -100,9 +57,9 @@
-

Pass?

+

Pass?

-

Test Name rk

+

Test Name rk

@@ -374,7 +331,7 @@

Pass?

-

Test Name rk

+

Test Name rk

diff --git a/js/main.js b/js/main.js index e10f399..6fd924f 100644 --- a/js/main.js +++ b/js/main.js @@ -15,6 +15,11 @@ const DOTS_DATA = { '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 = { winner: null, turn: 1, // turn logic depends on handicap stones @@ -65,6 +70,7 @@ class Point { this.pos = [ x, y ] this.stone = 0; // this is where move placement will go 0, 1, -1 'k' this.legal; + this.territory; this.capturing = []; this.groupMembers = []; this.neighbors = { @@ -101,8 +107,13 @@ class Point { for (let frn of frns) { this.groupMembers.push(frn); } + console.log(this); + console.log(this.groupMembers) // this.groupMembers = Array.from(new Set(this.groupMembers)); + if (!this.groupMembers.length) return; for (let grpMem in this.groupMembers) { + debugger; + console.log(this); this.groupMembers = Array.from(new Set(this.groupMembers.concat(this.groupMembers[grpMem].groupMembers))); } for (let grpMem in this.groupMembers) { @@ -120,6 +131,7 @@ class Point { this.capturing = this.capturing.concat(opp.groupMembers); }; } + this.capturing = Array.from(new Set(this.capturing)); return this.capturing; } 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) document.getElementById('board').addEventListener('mousemove', hoverPreview); // 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) // click on menu items // click on kifu to display game menu @@ -220,6 +232,7 @@ function playerResign() { function hoverPreview(evt) { evt.stopPropagation(); + if (gameState.pass > 1 || gameState.winner) return; // renders preview stone if move is legal let hover = [ parseInt(evt.target.closest('td').id[0]), parseInt(evt.target.closest('td').id[2]) ]; let point = findPointFromIdx(hover); @@ -265,11 +278,18 @@ function resolveCaptures(point) { } 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(); + if (gameState.pass > 1 || gameState.winner) return; // checks for placement and pushes to cell let placement = [ parseInt(evt.target.closest('td').id[0]), parseInt(evt.target.closest('td').id[2]) ]; let point = findPointFromIdx(placement); @@ -423,16 +443,34 @@ function init() { }; function render(hoverPoint) { + if (gameState.winner || gameState.pass > 1) { + renderTerritory(); + } gameState.gameRecord.length? renderTurn() : renderFirstTurn(); renderBoard(); 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() { document.getElementById(`${STONES_DATA[gameState.turn]}-bowl`).toggleAttribute('data-turn'); } 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() { @@ -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