add player input

This commit is contained in:
Sorrel Bri 2019-08-07 16:26:24 -07:00
parent 70e0e18815
commit 793d2bbb06
3 changed files with 75 additions and 86 deletions

View file

@ -13,8 +13,8 @@ a working game of go for a 9x9 board that
- [x] logs game record - [x] logs game record
- [x] allows players to pass or resign - [x] allows players to pass or resign
- [x] ends game upon 2 consecutive passes - [x] ends game upon 2 consecutive passes
- [ ] calculates estimated score at game end - [x] calculates estimated score at game end
- [ ] compares board groups to most common dead shapes - [x] suggests dead groups
- [x] allows users to override dead group estimates - [x] allows users to override dead group estimates
- [ ] allows users to submit finalized score to game record - [ ] allows users to submit finalized score to game record
- [ ] displays game record as string - [ ] displays game record as string
@ -27,7 +27,7 @@ stretch goals
- [ ] add stone placement sounds - [ ] add stone placement sounds
superstretch goals superstretch goals
- [x] allows users to select board size (9x9, 13x13, 19x19) - [ ] allows users to select board size (9x9, 13x13, 19x19)
- [ ] allows users to load .sgf main lines - [ ] allows users to load .sgf main lines
- [ ] allow for responsivity in the form of - [ ] allow for responsivity in the form of
- - [ ] 9x9 games simply stretch with screen size - - [ ] 9x9 games simply stretch with screen size

View file

@ -33,7 +33,7 @@
<div id="player-meta"> <div id="player-meta">
<div data-player-meta="black"> <div data-player-meta="black">
<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">
<div class="menu-line"> <div class="menu-line">
<span class="menu-heading">Rank:</span><span id="black-rank">9k</span><input type="button" id="black-rank-up" value="▲"><input type="button" id="black-rank-down" value="▼"> <span class="menu-heading">Rank:</span><span id="black-rank">9k</span><input type="button" id="black-rank-up" value="▲"><input type="button" id="black-rank-down" value="▼">
</div> </div>
@ -43,11 +43,11 @@
</div> </div>
<div data-player-meta="white"> <div data-player-meta="white">
<h4 class="menu-heading">White</h4> <h4 class="menu-heading">White</h4>
<span class="menu-heading">Name:</span><input type="text" name="white-name"> <span class="menu-heading">Name:</span><input type="text" name="white-name">
<div class="menu-heading"> <div class="line">
<span class="menu-heading">Rank:</span><span id="white-rank">9k</span><input type="button" id="white-rank-up" value="▲"><input type="button" id="white-rank-down" value="▼"> <span class="menu-heading">Rank:</span><span id="white-rank">9k</span><input type="button" id="white-rank-up" value="▲"><input type="button" id="white-rank-down" value="▼">
</div> </div>
<div class="menu-heading"> <div class="menu-line">
<input type="checkbox" name="white-rank-certain"><label for="white-rank-certain">Rank Certainty</label> <input type="checkbox" name="white-rank-certain"><label for="white-rank-certain">Rank Certainty</label>
</div> </div>
</div> </div>
@ -59,8 +59,8 @@
To override Browser Go's suggestion, use the sliders above. Be sure to check the 'rank certainty' box if you're club-rated.<br><br> To override Browser Go's suggestion, use the sliders above. Be sure to check the 'rank certainty' box if you're club-rated.<br><br>
When the game begins, click on a legal point on the board to make a move. The active player's bowl will be highlighted. To pass, click on your bowl. When the game begins, click on a legal point on the board to make a move. The active player's bowl will be highlighted. To pass, click on your bowl.
This will only be possible on your turn. To resign click on your capture tray. After the game ends, groups and territory will display Browser Go's estimate for final state. This will only be possible on your turn. To resign click on your capture tray. After the game ends, groups and territory will display Browser Go's estimate for final state.
Simply click on a group to change a group between live and dead, or a point between territory and dame. Simply click on a group to change a group between live and dead, or a point between territory and dame.<br><br>
I've got great things planned for the future, though! Lookout for new releases on <a href="https://github.com/sorrelbri/browser-go">the GitHub page!</a></p> For now, your game can't be saved. I've got great things planned for the future, though! Lookout for new releases and suggest new features on <a href="https://github.com/sorrelbri/browser-go">the GitHub page!</a></p>
<p id="game-record"></p> <p id="game-record"></p>
</div> </div>
<div id="game-update-space"> <div id="game-update-space">

View file

@ -234,6 +234,10 @@ const whiteNameInputEl = document.querySelector('input[name="white-name"]')
const blackNameDisplayEl = document.querySelector('h4#black-player-name'); const blackNameDisplayEl = document.querySelector('h4#black-player-name');
const whiteNameDisplayEl = document.querySelector('h4#white-player-name'); const whiteNameDisplayEl = document.querySelector('h4#white-player-name');
const gameHudEl = document.querySelector('#game-hud p'); const gameHudEl = document.querySelector('#game-hud p');
const dateEl = document.getElementById('date');
const boardSizeEl = document.getElementById('board-size-radio');
const komiDisplayEl = document.getElementById('komi');
const handiDisplayEl = document.getElementById('handicap');
// store modal #menu for displaying game info // store modal #menu for displaying game info
// store // store
@ -254,6 +258,8 @@ document.getElementById('player-meta').addEventListener('click', clickUpdatePlay
document.getElementById('player-meta').addEventListener('change', clickUpdatePlayerMeta); document.getElementById('player-meta').addEventListener('change', clickUpdatePlayerMeta);
document.querySelector('input[name="komi-suggest"]').addEventListener('click', clickKomiSuggestion); document.querySelector('input[name="komi-suggest"]').addEventListener('click', clickKomiSuggestion);
gameHudEl.addEventListener('click', clickGameHud); gameHudEl.addEventListener('click', clickGameHud);
boardSizeEl.addEventListener('click', clickBoardSize);
document.querySelector('input[name="game-start"]').addEventListener('click', clickSubmitStart);
/*----- functions -----*/ /*----- functions -----*/
@ -262,11 +268,15 @@ init();
let findPointFromIdx = (arr) => boardState.find( point => point.pos[0] === arr[0] && point.pos[1] === arr[1] ); let findPointFromIdx = (arr) => boardState.find( point => point.pos[0] === arr[0] && point.pos[1] === arr[1] );
function changeUpdateKomi() { function changeUpdateKomi() {
document.getElementById('komi').textContent = komiSliderEl.value; komiDisplayEl.textContent = komiSliderEl.value;
gameState.komi = komiSliderEl.value;
renderMenu();
} }
function changeUpdateHandicap() { function changeUpdateHandicap() {
document.getElementById('handicap').textContent = handiSliderEl.value; handiDisplayEl.textContent = handiSliderEl.value !== 1 ? handiSliderEl.value : 0;
gameState.handicap = handiSliderEl.value !== 1 ? handiSliderEl.value : 0;
renderMenu();
} }
function clickUpdatePlayerMeta(evt) { function clickUpdatePlayerMeta(evt) {
@ -288,14 +298,20 @@ function clickUpdatePlayerMeta(evt) {
} }
if (evt.target.name = 'black-rank-certain') gameState.playerMeta.b.rankCertain = !gameState.playerMeta.b.rankCertain; if (evt.target.name = 'black-rank-certain') gameState.playerMeta.b.rankCertain = !gameState.playerMeta.b.rankCertain;
if (evt.target.name = 'white-rank-certain') gameState.playerMeta.w.rankCertain = !gameState.playerMeta.w.rankCertain; if (evt.target.name = 'white-rank-certain') gameState.playerMeta.w.rankCertain = !gameState.playerMeta.w.rankCertain;
blackRankEl.textContent = RANKS[gameState.playerMeta.b.rank]; renderMenu();
whiteRankEl.textContent = RANKS[gameState.playerMeta.w.rank];
} }
function clickKomiSuggestion() { function clickBoardSize() {
let sugg = KOMI_REC[Math.abs(gameState.playerMeta.w.rank - gameState.playerMeta.b.rank)]; gameState.boardSize = boardSizeEl.value;
let handi = HANDI_REC[Math.abs(gameState.playerMeta.w.rank - gameState.playerMeta.b.rank)]; renderMenu();
}
function clickKomiSuggestion(evt) {
debugger;
evt.stopPropagation();
let sugg = KOMI_REC[gameState.boardSize][Math.abs(gameState.playerMeta.w.rank - gameState.playerMeta.b.rank)];
let handi = HANDI_REC[gameState.boardSize][Math.abs(gameState.playerMeta.w.rank - gameState.playerMeta.b.rank)];
gameState.komi = sugg; gameState.komi = sugg;
gameState.handicap = handi; gameState.handicap = handi;
renderMenu(); renderMenu();
@ -312,8 +328,28 @@ function clickSubmitStart() {
initGame(); initGame();
} }
function renderKomi() {
komiSliderEl.value = gameState.komi;
komiDisplayEl.textContent = gameState.komi;
if (gameState.gameRecord.length) komiSliderEl.setAttribute('disabled', true);
}
function renderHandiSlider() {
handiSliderEl.value = gameState.handicap;
handiDisplayEl.textContent = gameState.handicap;
if (gameState.gameRecord.length) handiSliderEl.setAttribute('disabled', true);
}
function renderBoardSizeRadio() {
boardSizeEl.value = gameState.boardSize;
if (gameState.gameRecord.length) boardSizeEl.setAttribute('disabled', true);
}
function renderMenu() { function renderMenu() {
komiSliderEl.value = sugg; dateEl.textContent = gameState.gameMeta.date;
renderKomi()
renderHandiSlider();
renderBoardSizeRadio();
blackNameDisplayEl.textContent = gameState.playerMeta.b.name; blackNameDisplayEl.textContent = gameState.playerMeta.b.name;
whiteNameDisplayEl.textContent = gameState.playerMeta.w.name; whiteNameDisplayEl.textContent = gameState.playerMeta.w.name;
blackRankEl.textContent = RANKS[gameState.playerMeta.b.rank]; blackRankEl.textContent = RANKS[gameState.playerMeta.b.rank];
@ -332,7 +368,7 @@ function playerPass() {
gameState.pass++; gameState.pass++;
if (gameState.pass === 2) return endGame(); if (gameState.pass === 2) return endGame();
gameState.turn*= -1; gameState.turn*= -1;
render(); renderGame();
} }
function clickMenu() { function clickMenu() {
@ -344,12 +380,12 @@ function clickMenu() {
function startMenu() { function startMenu() {
modalEl.style.visibility = 'visible'; modalEl.style.visibility = 'visible';
renderMenu; renderMenu();
} }
function clickCloseMenu(evt) { function clickCloseMenu(evt) {
evt.stopPropagation(); evt.stopPropagation();
if (evt.target.className === "modal") modalEl.style.visibility = 'hidden'; if (evt.target.className === "modal" && gameState.gameRecord.length) modalEl.style.visibility = 'hidden';
} }
function clickResign(evt) { function clickResign(evt) {
@ -421,7 +457,7 @@ function editTerritory(evt) {
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);
point.cycleTerritory(); point.cycleTerritory();
render(); renderGame();
} }
function checkKo(point, cap) { function checkKo(point, cap) {
@ -445,7 +481,7 @@ function clickBoard(evt) {
clearCaptures(); clearCaptures();
gameState.gameRecord.push(`${STONES_DATA[gameState.turn]}: ${point.pos}`) gameState.gameRecord.push(`${STONES_DATA[gameState.turn]}: ${point.pos}`)
gameState.turn*= -1; gameState.turn*= -1;
render(); renderGame();
} }
function clearKo() { function clearKo() {
@ -487,28 +523,26 @@ function getDate() {
function init() { function init() {
gameState.gameMeta.date = getDate(); gameState.gameMeta.date = getDate();
gameState.komi = 5.5; // get komi from player input gameState.komi = 5.5; // get komi from player input
startMenu();
gameState.winner = null; gameState.winner = null;
gameState.pass = null; gameState.pass = null;
// gameState.handicap = ; // get handicap from player input
gameState.turn = gameState.handicap ? -1 : 1;
gameState.boardSize = 9; gameState.boardSize = 9;
gameState.playerState.bCaptures = 0; gameState.playerState.bCaptures = 0;
gameState.playerState.wCaptures = 0; gameState.playerState.wCaptures = 0;
// get any future meta from player input gameState.gameRecord = [];
// gameState.playerMeta.b // get from player input boardState = [];
// gameState.playerMeta.w // get from player input startMenu();
gameState.gameRecord = []; // clear game record from previous game
// gameState.boardState // create board from user input
//need init player meta
initBoard();
// testing board state for moves at [32]
gameState.turn = 1;
render();
}; };
function initGame() {
gameState.winner = null;
gameState.pass = null;
gameState.turn = gameState.handicap ? -1 : 1;
initBoard();
renderGame();
}
function render() { function renderGame() {
if (gameState.winner || gameState.pass > 1) { if (gameState.winner || gameState.pass > 1) {
renderTerritory(); renderTerritory();
renderMessage(); renderMessage();
@ -527,7 +561,7 @@ function renderMessage() {
else if (gameState.winner && gameState.pass > 1) { else if (gameState.winner && gameState.pass > 1) {
gameHudEl.style.visibility = 'visible'; gameHudEl.style.visibility = 'visible';
gameHudEl.style.cursor = 'default'; gameHudEl.style.cursor = 'default';
gameHudEl.textContent = `${gameState.playerMeta[gameState.winner === 1 ? 'b' : 'w'].name} won by ${Math.abs(gameState.playerState.wScore - gameState.playerState.bScore)}`; gameHudEl.textContent = `${gameState.playerMeta[gameState.winner === 1 ? 'b' : 'w'].name || STONES_DATA[gameState.winner]} won by ${Math.abs(gameState.playerState.wScore - gameState.playerState.bScore)}`;
} else if (gameState.pass > 1) { } else if (gameState.pass > 1) {
gameHudEl.style.visibility = 'visible'; gameHudEl.style.visibility = 'visible';
gameHudEl.textContent = 'click to finalize game' gameHudEl.textContent = 'click to finalize game'
@ -599,7 +633,7 @@ function calculateWinner() {
+ blackTerritory; + blackTerritory;
gameState.winner = gameState.playerState.wScore > gameState.playerState.bScore ? -1 : 1; gameState.winner = gameState.playerState.wScore > gameState.playerState.bScore ? -1 : 1;
gameState.gameRecord.push(`${STONES_DATA[gameState.winner]}: +${Math.abs(gameState.playerState.wScore - gameState.playerState.bScore)}`) gameState.gameRecord.push(`${STONES_DATA[gameState.winner]}: +${Math.abs(gameState.playerState.wScore - gameState.playerState.bScore)}`)
render(); renderGame();
} }
function endGameSetTerritory() { function endGameSetTerritory() {
@ -636,7 +670,7 @@ function emptyPointSetTerritory(emptyPoints) {
return acc + wNbr; return acc + wNbr;
}, 0); }, 0);
pt.groupMembers.forEach(grp => { pt.groupMembers.forEach(grp => {
if (Math.abs(b - w) < 4) grp.territory = 'd' if (Math.abs(b - w) < 4 && b && w) grp.territory = 'd'
else grp.territory = b > w ? 1 : -1; else grp.territory = b > w ? 1 : -1;
}) })
}); });
@ -644,54 +678,9 @@ function emptyPointSetTerritory(emptyPoints) {
function endGame() { function endGame() {
if (!gameState.winner) endGameSetTerritory() if (!gameState.winner) endGameSetTerritory()
renderGame();
// 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
// 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
render();
} }
// game-end
// render territory counts
// checkLegalMove
// clear overlay
// if move is not '0', move is illegal (opposing player or 'k' for ko)
// iterate through neighboring points in clockwise order
// if anyone is '0' move is legal - call render preview
// if neighboring point is opposing player
// cycle through opposing player group marking points as overlay: 'chk' when checked and
// overlay: 'hold' if they are neighboring points of opposing player color
// if any neighboring point is '0' terminate cycle and move to next neighboring point of original move
// if there are unchecked points of 'hold' return
// if no boardState: 0 points, move is legal overlay: 'l'
// set all 'chk' to 'x' to represent stones that will be captured upon move
// if neighboring point is player's
// cycle through player group marking points as overlay: 'chk' || 'hold'
// if any neighboring point is '0' ternminate cycle and mark point as 'l'
// set move
// if checkLegalMove has returned '0' i2llegal move message?
// if move state is 'l'
// push boardState to lastState
// push 'l' move to boardState
// resolve captures
// for all 'x' in overlay
// count number and add to playerCaptures
// set boardState to '0'
// pass--
// push move to game record
// game record: [ 0: handicapStones Obj, 1: 1stMove([moveState[],moveState[][])] // game record: [ 0: handicapStones Obj, 1: 1stMove([moveState[],moveState[][])]
// pass() pass++ and player turn to other player // pass() pass++ and player turn to other player
// gameEnd when pass = 2 // gameEnd when pass = 2