Skip to content

Instantly share code, notes, and snippets.

@shuuki
Last active November 30, 2017 06:01
Show Gist options
  • Save shuuki/c299403fa7eb3afa08fd97a995d2b6d2 to your computer and use it in GitHub Desktop.
Save shuuki/c299403fa7eb3afa08fd97a995d2b6d2 to your computer and use it in GitHub Desktop.
Little Go
#controls
button#game_new New
label Board
select#board_size
option 9
option 13
option 19
label Mode
select#game_mode
option Play
option Edit
#board
#play
span#game_moves
button#game_pass Pass
//button#game_resign Resign
label Turn
label#game_turns 1
label#game_next Black to Play
#log
label Log
textarea#game_log
//#edit
#o_score
button -
button +
#x_score
button -
button +

Little Go

a little simplistic implementation of the ancient boardgame Go, using box drawing and emoji. click a space once for black, twice for white, and three times to empty. choose a size for the board and click new to reset.

made nov 23 2017 from an idea sketch i found dated feb 6 2016.

A Pen by Something Formed on CodePen.

License.

// array reverse
function reversal(arr) {
var result = [];
var i = null;
for (i = arr.length-1; i >= 0; i -= 1)
{
result.push(arr[i]);
}
return result;
}
// get html elements
const board = document.getElementById('board')
const boardSize = document.getElementById('board_size')
const gameNew = document.getElementById('game_new')
const gameMode = document.getElementById('game_mode')
const gamePass = document.getElementById('game_pass')
const gameResign = document.getElementById('game_resign')
const gameMoves = document.getElementById('game_moves')
const gameTurns = document.getElementById('game_turns')
const gameLog = document.getElementById('game_log')
const gameNext = document.getElementById('game_next')
const play = document.getElementById('play')
// game mode checker
function modeCheck(e) {
let md = gameMode.options[gameMode.selectedIndex].value
if (md==='Edit') {
play.classList.add('hidden')
}
else if (md==='Play') {
play.classList.remove('hidden')
}
//console.log(md)
}
// listen for game mode change
gameMode.addEventListener('change', modeCheck, false);
// game globals
var gameOn = true;
var turn = 1;
var turnLog = [];
function turnAdvance() {
if (gameOn === true) {
turn += 1;
gameTurns.textContent = turn;
if (turn%2 === 0) {
gameNext.textContent = 'White to Play';
}
else if (turn%2 === 1) {
gameNext.textContent = 'Black to Play';
}
}
else {
gameNext.textContent = 'Game Over';
}
let turnLogOut = reversal(turnLog);
gameLog.textContent = turnLogOut.join('\n');
//console.log(turnLog)
}
function newGame(e) {
makeBoard(e);
gameOn = true;
turn = 0;
turnLog = [];
gameTurns.textContent = turn;
if (gameMoves.classList.contains('hidden')) {
gameMoves.classList.remove('hidden')
}
turnAdvance()
}
function playPass(e) {
if (gameOn === true) {
if (turn%2 === 1) {
turnLog.push(turn+' B Pass')
turnAdvance()
}
else if (turn%2 === 0) {
turnLog.push(turn+' W Pass')
turnAdvance()
}
// check game log for pass on last turn
let lastTurn = turnLog[turn-2].split(' ')[2];
// end game if both players pass
if (turn>4 && lastTurn === 'Pass') {
gameOn = false;
gameNext.textContent = 'Game Over';
gameMoves.classList.add('hidden')
turnLog.push('Pass End')
turnAdvance()
}
//console.log(turn)
}
}
// listen for board new board
gameNew.addEventListener('click', newGame, false);
boardSize.addEventListener('change', newGame, false);
// listen for pass
gamePass.addEventListener('click', playPass, false);
/*
//board.addEventListener('click', mover, false);
function mover(e) {
//e.buttons > 0 &&
if (e.path[0].classList.contains('space')) {
flipSpace3(e.path[0]);
console.log(e.path[0])
//e.path[0].className = 'space X'
}
}
*/
// space maker
// drops in default space element
function makeSpace(i) {
let dx = document.createElement('div');
dx.id = i;
dx.classList.add('space','empty')
dx.textContent = '+';
//dx.textContent = '\u254B'; // +
return dx;
}
// flip space
// cycles through possible states for spaces
// deprecated ascii-only variant
function flipSpaceEmoji(e) {
if (e.target.textContent === '\u254B') // +
e.target.textContent = '\u26AB'; // X
else if (e.target.textContent === '\u26AB') // X
e.target.textContent = '\u26AA'; // O
else if (e.target.textContent === '\u26AA') // O
e.target.textContent = '\u254B'; // +
return e.target;
}
// stylesheet class switching variant
function flipSpaceSprite(e) {
if (e.target.classList.contains('empty')) {
e.target.classList.replace('empty', 'black')
e.target.textContent = 'X';
}
else if (e.target.classList.contains('black')) {
e.target.classList.replace('black', 'white')
e.target.textContent = 'O';
}
else if (e.target.classList.contains('white')) {
e.target.classList.replace('white', 'empty')
e.target.textContent = '+';
}
//console.log(e.target)
return e.target;
}
//
function spaceToCoord(i) {
let bs = boardSize.options[boardSize.selectedIndex].value,
blah = Math.floor(i/bs)+1,
boo = Math.floor(i%bs)+1;
return boo + ',' + blah;
}
// play stones
function playStone(e) {
if (e.target.classList.contains('empty') === true) {
// can move in empty spaces
if (turn%2===1) {
e.target.textContent = 'X';
e.target.classList.replace('empty', 'black')
turnLog.push(turn + ' B ' + spaceToCoord(e.target.id))
}
else if (turn%2===0) {
e.target.textContent = 'O';
e.target.classList.replace('empty', 'white')
turnLog.push(turn + ' W ' + spaceToCoord(e.target.id))
}
turnAdvance();
}
else if (e.target.classList.contains('empty') === false) {
// can't move in occupied spaces
}
//return e.target;
}
function spaceCheck (e) {
let md = gameMode.options[gameMode.selectedIndex].value
if (md==='Edit') {
flipSpaceSprite(e)
}
else if (md==='Play' && gameOn === true) {
playStone(e)
}
//console.log(md)
}
// board maker
// builds board and attaches event listeners to spaces
function makeBoard() {
// board size selector
let bs = boardSize.options[boardSize.selectedIndex].value,
// board length
bl = bs*bs;
// reset board
board.innerHTML = '';
board.className = 's'+bs;
// build board
for(let i = 0; i < bl; i++) {
let nsp = makeSpace(i);
board.appendChild(nsp);
let ex = document.getElementsByClassName('space')[i];
ex.addEventListener('click', spaceCheck, false);
if (i%bs === bs-1) {
board.appendChild(document.createElement('br'));
}
}
return bl;
}
makeBoard();
body {
background: #222;
color: #888;
font-size: 10pt;
margin: 0;
user-select: none;
}
.hidden {
display: none;
}
#controls,
#play,
#log {
//text-align: center;
padding: 0.5em;
}
#game_log {
height: 2em;
font-family: monospace;
width: 8em;
}
#board {
background: #a7794a;
background: #e9c797;
display: inline-block;
padding: 0;
line-height: 0;
text-align: center;
user-select: none;
white-space: nowrap;
//width: 100%;
}
.space {
display: inline-block;
line-height: 1;
text-align: center;
color: transparent;
}
@n: 10vw; // 9x9
@tt: 7vw; // 13x13
@nt: 4.8vw; // 19x19
.s9 .space {
font-size: @n;
height: @n;
width: @n;
}
.s13 .space {
font-size: @tt;
height: @tt;
width: @tt;
}
.s19 .space {
font-size: @nt;
height: @nt;
width: @nt;
}
// empty space on board
.E, .empty {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAxOS4xLjAsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiDQoJIHZpZXdCb3g9IjAgMCA3MiA3MiIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNzIgNzI7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxwb2x5Z29uIHBvaW50cz0iNzIsMzQgMzgsMzQgMzgsMCAzNCwwIDM0LDM0IDAsMzQgMCwzOCAzNCwzOCAzNCw3MiAzOCw3MiAzOCwzOCA3MiwzOCAiLz4NCjxwb2x5Z29uIHBvaW50cz0iNzIsMzQgMzgsMzQgMzgsMCAzNCwwIDM0LDM0IDAsMzQgMCwzOCAzNCwzOCAzNCw3MiAzOCw3MiAzOCwzOCA3MiwzOCAiLz4NCjwvc3ZnPg0K');
}
// black stone on board
.X {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAxOS4xLjAsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiDQoJIHZpZXdCb3g9IjAgMCA3MiA3MiIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNzIgNzI7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxnPg0KCTxwYXRoIGQ9Ik03MiwzNGgtOS4xQzYxLjksMjAuNyw1MS4zLDEwLjEsMzgsOS4xVjBoLTR2OS4xQzIwLjcsMTAuMSwxMC4xLDIwLjcsOS4xLDM0SDB2NGg5LjFjMSwxMy4zLDExLjYsMjMuOSwyNC45LDI0LjlWNzJoNA0KCQl2LTkuMWMxMy4zLTEsMjMuOS0xMS42LDI0LjktMjQuOUg3MlYzNHoiLz4NCjwvZz4NCjwvc3ZnPg0K');
}
// white stone on board
.O {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAxOS4xLjAsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiDQoJIHZpZXdCb3g9IjAgMCA3MiA3MiIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNzIgNzI7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+DQoJLnN0MHtmaWxsOiNGRkZGRkY7fQ0KPC9zdHlsZT4NCjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik0zNS45LDYxLjFMMzQsNjFjLTEyLjItMS0yMi4xLTEwLjktMjMtMjMuMUwxMC45LDM2bDAuMS0xLjlDMTEuOSwyMS44LDIxLjgsMTEuOSwzNC4xLDExbDEuOS0wLjF2MGwxLjksMC4xDQoJQzUwLjIsMTEuOSw2MC4xLDIxLjgsNjEsMzQuMWwwLjEsMS45bDAsMEw2MSwzNy45Yy0xLjEsMTIuMi0xMSwyMi4xLTIzLjIsMjNMMzUuOSw2MS4xTDM1LjksNjEuMXoiLz4NCjxwYXRoIGQ9Ik0zNiwxMi44bDEuNywwLjFjMTEuMywwLjgsMjAuNCw5LjksMjEuMiwyMS4ybDAuMSwxLjdsLTAuMSwxLjdDNTguMSw0OC44LDQ5LDU3LjksMzcuNyw1OC43TDM2LDU4LjhsLTEuNy0wLjENCglDMjMsNTcuOSwxMy45LDQ4LjgsMTMuMSwzNy41TDEzLDM1LjhsMC4xLTEuN2MwLjgtMTEuMyw5LjktMjAuNCwyMS4yLTIxLjJMMzYsMTIuOCBNMzgtMC4xaC00VjlDMjAuNywxMCwxMC4xLDIwLjYsOS4xLDMzLjlIMHY0DQoJaDkuMWMxLDEzLjMsMTEuNiwyMy45LDI0LjksMjQuOXY5LjFoNHYtOS4xYzEzLjMtMSwyMy45LTExLjYsMjQuOS0yNC45SDcydi00aC05LjFDNjEuOSwyMC42LDUxLjMsMTAsMzgsOVYtMC4xTDM4LTAuMXoiLz4NCjwvc3ZnPg0K');
}
.black {
background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgNzIgNzIiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDcyIDcyOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PGc+PGNpcmNsZSBjeD0iMzYiIGN5PSIzNiIgcj0iMjciLz48L2c+PC9zdmc+);
}
.white {
background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgNzIgNzIiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDcyIDcyOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PHN0eWxlIHR5cGU9InRleHQvY3NzIj4uc3Qwe2ZpbGw6I0ZGRkZGRjt9PC9zdHlsZT48Zz48cGF0aCBjbGFzcz0ic3QwIiBkPSJNMzYsNjFjLTEzLjgsMC0yNS0xMS4yLTI1LTI1czExLjItMjUsMjUtMjVzMjUsMTEuMiwyNSwyNVM0OS44LDYxLDM2LDYxeiIvPjxwYXRoIGQ9Ik0zNiwxM2MxMi43LDAsMjMsMTAuMywyMywyM1M0OC43LDU5LDM2LDU5UzEzLDQ4LjcsMTMsMzZTMjMuMywxMywzNiwxMyBNMzYsOUMyMS4xLDksOSwyMS4xLDksMzZzMTIuMSwyNywyNywyN3MyNy0xMi4xLDI3LTI3UzUwLjksOSwzNiw5TDM2LDl6Ii8+PC9nPjwvc3ZnPg==);
}
<link href="https://codepen.io/somethingformed/pen/wJKaKd" rel="stylesheet" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment