fuzzyworld

dao-game / commit

Improved animation, but winning check isn't done yet.

481788e8e19398df266419bd9fb1d90d9d538665 · Pavel Safronov · 2022-02-26 19:14:16 -0800 · parents 773cf7f10b6f

Improved animation, but winning check isn't done yet.
 game.js | 175 ++++++++++++++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 131 insertions(+), 44 deletions(-)

diff --git a/game.js b/game.js
index 0efce2a..0715a22 100644
--- a/game.js
+++ b/game.js
@@ -1,3 +1,33 @@
+class Coord {
+    /**
+     * Creates an instance of Coord.
+     * @param {number} row
+     * @param {number} col
+     * @memberof Coord
+     */
+    constructor(row, col) {
+        this.row = row;
+        this.col = col;
+    }
+
+    /**
+     * @param {Coord} coord
+     * @memberof Coord
+     */
+    add(coord) {
+        this.row += coord.row;
+        this.col += coord.col;
+    }
+
+    /**
+     * @param {Coord} otherCoord
+     * @memberof Coord
+     */
+    equals(otherCoord) {
+        return (this.col === otherCoord.col && this.row === otherCoord.col);
+    }
+}
+
 // Constants
 const selectedPieceClassName = 'selected-piece';
 const selectedPlayerTextClassName = 'selected-player-text';
@@ -13,6 +43,24 @@ const board = [
 ];
 const rows = 4;
 const cols = 4;
+// clock face directions
+const allDirections = [
+    { row: 1, col: 0 }, // up
+    { row: 1, col: 1 }, // up-right
+    { row: 0, col: 1 }, // right
+    { row: -1, col: 1 }, // right-down
+    { row: -1, col: 0 }, // down
+    { row: -1, col: -1 }, // down-left
+    { row: 0, col: -1 }, // left
+    { row: 1, col: -1 }, // left-up
+]
+/** @type {Coord[]} */
+const squareCoords = [
+    new Coord(0, 0),
+    new Coord(3, 0),
+    new Coord(3, 3),
+    new Coord(0, 3),
+];
 
 // DOM references
 const cells = () => Array.from(document.querySelectorAll("td"));
@@ -46,18 +94,6 @@ const removeListeners = () => {
     listeners.length = 0;
 }
 
-class Coord {
-    /**
-     * Creates an instance of Coord.
-     * @param {number} row
-     * @param {number} col
-     * @memberof Coord
-     */
-    constructor(row, col) {
-        this.row = row;
-        this.col = col;
-    }
-}
 /**
  * @param {Coord} data
  * @return {number} 
@@ -73,23 +109,13 @@ const coordToBoardIndex = ({ row, col }) => {
 const boardIndexToCoord = (index) => {
     const col = index % 4;
     const row = Math.floor(index / 4);
-    return { row, col };
+    return new Coord(row, col);
 };
 
 const resetBoard = () => {
-    // resetPieces
-    /** @param {Element} piece */
-    const resetPiece = (piece) => {
-        //piece.classList.remove(selectedPieceClassName);
-        // piece.classList.remove(activePlayerPieceClassName);
-    };
-    redPieces().forEach(resetPiece);
-    bluePieces().forEach(resetPiece);
-
     // resetCells
     cells().forEach(cell => {
         cell.classList.remove(blinkingClassName);
-        cell.style.zIndex = 0
     });
 
     // remove all listeners
@@ -116,20 +142,9 @@ const setActivePlayerPieces = () => {
  * @returns {number[]}
  */
 const getAllowedMoveIndicesForIndex = (boardIndex) => {
-    // clock face directions
-    const directions = [
-        { row: 1, col: 0 }, // up
-        { row: 1, col: 1 }, // up-right
-        { row: 0, col: 1 }, // right
-        { row: -1, col: 1 }, // right-down
-        { row: -1, col: 0 }, // down
-        { row: -1, col: -1 }, // down-left
-        { row: 0, col: -1 }, // left
-        { row: 1, col: -1 }, // left-up
-    ]
     const coord = boardIndexToCoord(boardIndex);
 
-    const farthestCoords = directions
+    const farthestCoords = allDirections
         .map(direction => getFarthestCoord(coord, direction))
         .filter(farCoord => farCoord !== undefined);
 
@@ -175,8 +190,6 @@ const getPieceElementById = (pieceId) => {
 
 /** @param {Event} event */
 const selectPiece = (event) => {
-    // resetBoard();
-    // setActivePlayerPieces();
     const previousSelectedPieceId = selectedPieceId;
     if (previousSelectedPieceId >= 0) {
         const previousPiece = getPieceElementById(previousSelectedPieceId);
@@ -225,12 +238,6 @@ const makeMove = (destIndex) => {
     const cellWidth = cells()[0].clientWidth;
     const cellHeight = cells()[0].clientHeight;
 
-    const diffX = coordDiff.col * cellWidth;
-    const diffY = coordDiff.row * cellHeight;
-
-    // const startCell = cells()[pieceIndex];
-    // const destCell = cells()[destIndex];
-
     removeListeners();
 
     const animation = piece.animate([
@@ -252,9 +259,10 @@ const makeMove = (destIndex) => {
         board[pieceIndex] = null;
         board[destIndex] = pieceId;
 
-        checkForWin();
         const elem = getPieceElementById(pieceId);
         elem.classList.remove(selectedPieceClassName);
+
+        checkForWin();
         nextMove();
     };
 }
@@ -282,8 +290,87 @@ const nextMove = () => {
     setActivePlayerPieces();
 };
 
+/**
+ * @param {Element[]} elements
+ * @returns {number[]}
+ */
+const elementsToBoardIndexes = (elements) => {
+    const indices = elements.map(pp => {
+        const pieceId = Number.parseInt(pp.id);
+        const pieceIndex = board.indexOf(pieceId);
+        return pieceIndex;
+    });
+    return indices;
+};
+/**
+ * @param {Element[]} elements
+ * @return {Coord[]} 
+ */
+const elementsToCoords = (elements) => {
+    const indices = elementsToBoardIndexes(elements);
+    const coords = indices.map(pieceIndex => boardIndexToCoord(pieceIndex));
+    return coords;
+};
+
+/**
+ * @param {Coord[]} coords
+ * @returns {boolean}
+ */
+const doCoordsFormSquare = (coords) => {
+    const areInSquare = coords.some((cornerCoord) => {
+        const offsetCoords = allDirections.map(d => cornerCoord.add(d));
+        const presentOffsets = coords.filter(c => offsetCoords.includes(c)).length;
+        const isSquare = presentOffsets === 4;
+        return isSquare;
+    });
+    return areInSquare;
+};
+
 const checkForWin = () => {
     console.error(`testing win for ${isRedTurn ? 'red' : 'blue'}`);
+    return;
+
+    const playerCoords = elementsToCoords(
+        isRedTurn ? redPieces() : bluePieces())
+    const otherCoords = elementsToCoords(
+        isRedTurn ? bluePieces() : redPieces());
+
+    // winning conditions:
+    // 1. all in one row
+    // 2. all in one column
+    // 3. all in corners
+    // 4. all in square
+    // losing conditions:
+    // 1. on three sides of an opponent
+
+    const firstPiece = playerCoords[0];
+    const allInRow = playerCoords.every(pc => pc.row === firstPiece.row)
+    const allInCol = playerCoords.every(pc => pc.col === firstPiece.col)
+    const allInCorners = playerCoords.every(pc => squareCoords.filter(sc => pc.equals(sc)).length > 0);
+    const allInSquare = doCoordsFormSquare(playerCoords);
+
+    const winnerName = isRedTurn ? 'Red' : 'Blue';
+    let isWinner = false;
+    if (allInRow) {
+        alert(`${winnerName} wins by forming a row`)
+        isWinner = true;
+    }
+    if (allInCol) {
+        alert(`${winnerName} wins by forming a column`)
+        isWinner = true;
+    }
+    if (allInCorners) {
+        alert(`${winnerName} wins by putting pieces in corners`)
+        isWinner = true;
+    }
+    if (allInSquare) {
+        alert(`${winnerName} wins by forming a square`)
+        isWinner = true;
+    }
+
+    if (isWinner) {
+        document.location.reload();
+    }
 };