diff --git a/server.js b/server.js index c0be258..38d34d4 100644 --- a/server.js +++ b/server.js @@ -1,3 +1,4 @@ +const { textFromBoard } = require('./src/logic') const { Board } = require('./src/backend'); const express = require('express'); @@ -63,7 +64,7 @@ io.on("connection", (socket) => { }); const getApiAndEmit = (socket, board) => { - const response = board.textFromState(); + const response = textFromBoard(board) console.log(response); // Emitting a new message. Will be consumed by the client socket.emit("FromAPI", response); diff --git a/src/backend.js b/src/backend.js index b7eb41e..719bd0f 100644 --- a/src/backend.js +++ b/src/backend.js @@ -41,7 +41,7 @@ function imageFromPiece(piece) { class Board { constructor(props) { - this.state = (props && props.text) ? + this.state = props?.text ? this.stateFromText(props.text) : this.originalState(); } @@ -103,34 +103,6 @@ class Board { return this.stateFromText(text); } - textFromState() { - const turn = (this.state.blackIsNext? 'B' : 'W'); - return turn + this.state.squares.map(square => { - if (!square) { - return '_'; - } - let color = (c) => { - return square.color === BLACK ? c.toUpperCase() : c; - }; - switch (square.type) { - case ROOK: - return color('r'); - case KNIGHT: - return color('n'); - case BISHOP: - return color('b'); - case QUEEN: - return color('q'); - case KING: - return color('k'); - case PAWN: - return color('p'); - default: - return '_'; - } - }).join(''); - } - doReset() { // setState this.state = this.getSetting(SHUFFLING_ENABLED) ? @@ -138,32 +110,6 @@ class Board { this.state.showPopup = false; } - originalState() { - let squares = []; - const mainRow = [ROOK, KNIGHT, BISHOP, QUEEN, KING, BISHOP, KNIGHT, ROOK]; - function add(num, color, type) { - for(let i = 0; i < num; i++) { - squares.push(new Piece(color, type)); - } - } - - mainRow.forEach(type => add(1, WHITE, type)); - add(8, WHITE, PAWN); - add(32, EMPTY, EMPTY); - add(8, BLACK, PAWN); - mainRow.forEach(type => add(1, BLACK, type)); - - return ({ - squares, - blackIsNext: true, - hand: { - heldPiece: null, - }, - showPopup: false, - settings: {}, - }); - } - getXandY(i) { const x = i % 8; const y = Math.floor(i / 8); @@ -506,10 +452,7 @@ class Board { } } -module.exports = { - Board: Board, - Piece: Piece, -} +module.exports = { Board } // export default Board; // export {Board, Piece}; diff --git a/src/backend.test.js b/src/backend.test.js deleted file mode 100644 index 21a0d68..0000000 --- a/src/backend.test.js +++ /dev/null @@ -1,112 +0,0 @@ -import Board from './backend'; -import * as game from './backend'; - -it('detects friendship and enemyship', () => { - const black = new game.Piece(game.BLACK, game.KING); - const black2 = new game.Piece(game.BLACK, game.QUEEN); - const white = new game.Piece(game.WHITE, game.KING); - const white2 = new game.Piece(game.WHITE, game.QUEEN); - const empty = new game.Piece(game.EMPTY, game.EMPTY); - const empty2 = new game.Piece(game.EMPTY, game.EMPTY); - - const truths = [ - black.isFriendOf(black2), - white.isFriendOf(white2), - - black.isEnemyOf(white), - white.isEnemyOf(black), - ]; - for (const truth of truths) { - expect(truth).toBe(true); - } - - const lies = [ - black.isFriendOf(white), black.isFriendOf(empty), - white.isFriendOf(black), white.isFriendOf(empty), - empty.isFriendOf(white), empty.isFriendOf(black), empty.isFriendOf(empty2), - - black.isEnemyOf(black2), black.isEnemyOf(empty), - white.isEnemyOf(white2), white.isEnemyOf(empty), - empty.isEnemyOf(white), empty.isEnemyOf(black), empty.isEnemyOf(empty2), - ]; - for (const lie of lies) { - expect(lie).toBe(false); - } -}); - -it('is created correctly', () => { - const board = new Board(); - const rows = ['B', - 'rnbqkbnr', - 'pppppppp', - '________', - '________', - '________', - '________', - 'PPPPPPPP', - 'RNBQKBNR' - ]; - expect(board.textFromState()).toBe(rows.join('')); - for (const square of board.state.squares) { - expect(square.hasNotMoved()).toBe(true); - } -}); - -it('is created from text correctly', () => { - const rows = ['B', - 'pppppppp', - 'pppppppp', - '________', - '________', - '________', - '________', - 'PPPPPPPP', - 'PPPPPPPP' - ]; - const board = new Board({text: rows.join('')}); - expect(board.textFromState()).toBe(rows.join('')); -}); - -it('detects an obvious checkmate', () => { - const rows = ['B', - 'q_______', - 'q______K', - 'q_______', - '________', - '________', - '________', - '________', - 'k_______' - ]; - const board = new Board({text: rows.join('')}); - const inCheck = board.whoInCheck(); - expect(inCheck.type).toEqual(game.KING); - expect(inCheck.color).toEqual(game.BLACK); -}); - -it('detects basic castling', () => { - const startRows = ['B', - '____k___', - '________', - '________', - '________', - '________', - '________', - 'PPPPPPPP', - 'R___K__R' - ]; - // const endRows = ['B', - // '____k___', - // '________', - // '________', - // '________', - // '________', - // '________', - // 'PPPPPPPP', - // 'R____RK_' - // ]; - let board = new Board({text: startRows.join('')}); - let move = board.isValidMove(60, 62); - expect(move.x).toBe(6); - expect(move.y).toBe(7); -}); diff --git a/src/board.test.js b/src/board.test.js index dbb9883..f7ab5f8 100644 --- a/src/board.test.js +++ b/src/board.test.js @@ -1,6 +1,5 @@ import React from 'react'; -import ReactDOM from 'react-dom'; -import renderer from 'react-test-renderer'; +import { textFromBoard } from './logic'; import Board from './components/Board'; import * as game from './components/Board'; @@ -50,7 +49,7 @@ it('is created correctly', () => { 'PPPPPPPP', 'RNBQKBNR' ]; - expect(board.textFromState()).toBe(rows.join('')); + expect(textFromBoard(board)).toBe(rows.join('')); for (const square of board.state.squares) { expect(square.hasNotMoved()).toBe(true); } @@ -68,7 +67,7 @@ it('is created from text correctly', () => { 'PPPPPPPP' ]; const board = new Board({text: rows.join('')}); - expect(board.textFromState()).toBe(rows.join('')); + expect(textFromBoard(board)).toBe(rows.join('')); }); it('detects an obvious checkmate', () => { diff --git a/src/components/Board.js b/src/components/Board.js index 0b13a19..dd8ca8f 100644 --- a/src/components/Board.js +++ b/src/components/Board.js @@ -2,21 +2,9 @@ import React from 'react'; import Popup from './Popup'; import '../index.css'; -import { Piece } from '../logic'; +import { Piece, startingBoard, PAWN, ROOK, KNIGHT, BISHOP, QUEEN, KING, EMPTY, BLACK, WHITE } from '../logic'; -const BLACK = 0; -const WHITE = 1; - -const PAWN = 0; -const ROOK = 1; -const KNIGHT = 2; -const BISHOP = 3; -const QUEEN = 4; -const KING = 5; - -const EMPTY = -1; - const Images = [ './white_pawn.svg', './white_rook.svg', @@ -83,8 +71,8 @@ class Board extends React.Component { this.onMove = props.onMove; this.lobbyName = props.lobbyName } - this.state = (props && props.text) ? - this.stateFromText(props.text) : this.originalState(); + this.state = props?.text ? + this.stateFromText(props.text) : startingBoard(); } setHand(hand) { @@ -150,68 +138,14 @@ class Board extends React.Component { return this.stateFromText(text); } - textFromState() { - const turn = (this.state.blackIsNext? 'B' : 'W'); - return turn + this.state.squares.map(square => { - if (!square) { - return '_'; - } - let color = (c) => { - return square.color === BLACK ? c.toUpperCase() : c; - }; - switch (square.type) { - case ROOK: - return color('r'); - case KNIGHT: - return color('n'); - case BISHOP: - return color('b'); - case QUEEN: - return color('q'); - case KING: - return color('k'); - case PAWN: - return color('p'); - default: - return '_'; - } - }).join(''); - } - doReset() { this.setState(this.getSetting(SHUFFLING_ENABLED) ? - this.shuffledBackRowState() : this.originalState()); + this.shuffledBackRowState() : startingBoard()); this.setState({ showPopup: false, }); } - originalState() { - let squares = []; - const mainRow = [ROOK, KNIGHT, BISHOP, QUEEN, KING, BISHOP, KNIGHT, ROOK]; - function add(num, color, type) { - for(let i = 0; i < num; i++) { - squares.push(new Piece(color, type)); - } - } - - mainRow.forEach(type => add(1, WHITE, type)); - add(8, WHITE, PAWN); - add(32, EMPTY, EMPTY); - add(8, BLACK, PAWN); - mainRow.forEach(type => add(1, BLACK, type)); - - return ({ - squares, - blackIsNext: true, - hand: { - heldPiece: null, - }, - showPopup: false, - settings: {}, - }); - } - getXandY(i) { const x = i % 8; const y = Math.floor(i / 8); diff --git a/src/logic.js b/src/logic.js index 7721b04..cb52034 100644 --- a/src/logic.js +++ b/src/logic.js @@ -1,3 +1,15 @@ +const BLACK = 0; +const WHITE = 1; + +const PAWN = 0; +const ROOK = 1; +const KNIGHT = 2; +const BISHOP = 3; +const QUEEN = 4; +const KING = 5; + +const EMPTY = -1; + class Piece { constructor(color, type) { this.color = color; @@ -63,4 +75,58 @@ class Piece { } } -export { Piece } \ No newline at end of file +const startingBoard = () => { + let squares = []; + const mainRow = [ROOK, KNIGHT, BISHOP, QUEEN, KING, BISHOP, KNIGHT, ROOK]; + function add(num, color, type) { + for(let i = 0; i < num; i++) { + squares.push(new Piece(color, type)); + } + } + + mainRow.forEach(type => add(1, WHITE, type)); + add(8, WHITE, PAWN); + add(32, EMPTY, EMPTY); + add(8, BLACK, PAWN); + mainRow.forEach(type => add(1, BLACK, type)); + + return ({ + squares, + blackIsNext: true, + hand: { + heldPiece: null, + }, + showPopup: false, + settings: {}, + }); +} + +const textFromBoard = ({ state }) => { + const turn = (this.state.blackIsNext? 'B' : 'W'); + return turn + this.state.squares.map(square => { + if (!square) { + return '_'; + } + let color = (c) => { + return square.color === BLACK ? c.toUpperCase() : c; + }; + switch (square.type) { + case ROOK: + return color('r'); + case KNIGHT: + return color('n'); + case BISHOP: + return color('b'); + case QUEEN: + return color('q'); + case KING: + return color('k'); + case PAWN: + return color('p'); + default: + return '_'; + } + }).join(''); +} + +export { Piece, startingBoard, textFromBoard, PAWN, ROOK, KNIGHT, BISHOP, QUEEN, KING, EMPTY, BLACK, WHITE }