From 8e909214fd424c2b236fe8da13f188cfe58d5503 Mon Sep 17 00:00:00 2001
From: Cong <work.congpham.com>
Date: Mon, 18 Mar 2024 12:58:00 +0100
Subject: [PATCH] Initial Commits

---
 .DS_Store              |  Bin 0 -> 6148 bytes
 .vscode/settings.json  |   64 +--
 src/Bishop.cpp         |   31 --
 src/Bishop.h           |   20 -
 src/Board.cpp          |   47 --
 src/Board.h            |   83 ---
 src/Chess.cpp          |   65 +++
 src/Chess.h            |  134 +++++
 src/Game.cpp           | 1183 ++++++++++++++++++++++++++++++++++++++++
 src/Game.h             |   65 +++
 src/Knight.cpp         |   35 --
 src/Knight.h           |   20 -
 src/Piece.cpp          |   38 --
 src/Piece.h            |   75 ---
 src/Rook.cpp           |   15 -
 src/Rook.h             |   20 -
 src/Square.cpp         |   38 --
 src/Square.h           |   66 ---
 src/includes.h         |   14 +
 src/user_interface.cpp |   50 ++
 src/user_interface.h   |   18 +
 21 files changed, 1531 insertions(+), 550 deletions(-)
 create mode 100644 .DS_Store
 delete mode 100644 src/Bishop.cpp
 delete mode 100644 src/Bishop.h
 delete mode 100644 src/Board.cpp
 delete mode 100644 src/Board.h
 create mode 100644 src/Chess.cpp
 create mode 100644 src/Chess.h
 create mode 100644 src/Game.cpp
 create mode 100644 src/Game.h
 delete mode 100644 src/Knight.cpp
 delete mode 100644 src/Knight.h
 delete mode 100644 src/Piece.cpp
 delete mode 100644 src/Piece.h
 delete mode 100644 src/Rook.cpp
 delete mode 100644 src/Rook.h
 delete mode 100644 src/Square.cpp
 delete mode 100644 src/Square.h
 create mode 100644 src/includes.h
 create mode 100644 src/user_interface.cpp
 create mode 100644 src/user_interface.h

diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000000000000000000000000000000000000..4bb39329d0fbb8a0696f1c42de3a39821ebe65d3
GIT binary patch
literal 6148
zcmeHK%WA_w3>?)i1bWG_$Nh!=!4lFh=npiGF9lOW)7*W_Z+G-au`z|5dI%Covpbf&
z_8cq=fb7ow3$O*Sp)2B|VQqR{ePs{9JQ79kaU8mF9Jqv1H<>0j=<tEh{xq-ea3(pR
zpVKXR9Po|9oNP#rI9@3|w!sNsOX{Yl$)r>u6-WhAfmGoB70^aa+dMgDOa)SbRNz+u
z{XP`BVhx-e?bE?vBLJ}_ZN|0D62zheu?9|#WN6~0L@$*XF~rNsm&mJulcSeIV)&3a
zSz<yFJDvA0mJX?o8B>8&V5vak+pYHhSNb3G|FS4|sX!`lR|-hGf7|c)O3_<aFQ>h>
u(BJ7-W3Ht$SSu!4E9OR9@$)RN=$hAS;N)oK<gJ{TKLV;tS}O1#3j6>X`6Xxo

literal 0
HcmV?d00001

diff --git a/.vscode/settings.json b/.vscode/settings.json
index a57998e..0cba2e6 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,65 +1,5 @@
 {
     "files.associations": {
-        "__bit_reference": "cpp",
-        "__config": "cpp",
-        "__debug": "cpp",
-        "__errc": "cpp",
-        "__functional_base": "cpp",
-        "__hash_table": "cpp",
-        "__locale": "cpp",
-        "__mutex_base": "cpp",
-        "__node_handle": "cpp",
-        "__nullptr": "cpp",
-        "__split_buffer": "cpp",
-        "__string": "cpp",
-        "__threading_support": "cpp",
-        "__tuple": "cpp",
-        "algorithm": "cpp",
-        "array": "cpp",
-        "atomic": "cpp",
-        "bit": "cpp",
-        "bitset": "cpp",
-        "cctype": "cpp",
-        "chrono": "cpp",
-        "clocale": "cpp",
-        "cmath": "cpp",
-        "complex": "cpp",
-        "cstdarg": "cpp",
-        "cstddef": "cpp",
-        "cstdint": "cpp",
-        "cstdio": "cpp",
-        "cstdlib": "cpp",
-        "cstring": "cpp",
-        "ctime": "cpp",
-        "cwchar": "cpp",
-        "cwctype": "cpp",
-        "exception": "cpp",
-        "functional": "cpp",
-        "initializer_list": "cpp",
-        "ios": "cpp",
-        "iosfwd": "cpp",
-        "istream": "cpp",
-        "iterator": "cpp",
-        "limits": "cpp",
-        "locale": "cpp",
-        "memory": "cpp",
-        "mutex": "cpp",
-        "new": "cpp",
-        "optional": "cpp",
-        "ostream": "cpp",
-        "ratio": "cpp",
-        "sstream": "cpp",
-        "stdexcept": "cpp",
-        "streambuf": "cpp",
-        "string": "cpp",
-        "string_view": "cpp",
-        "system_error": "cpp",
-        "tuple": "cpp",
-        "type_traits": "cpp",
-        "typeinfo": "cpp",
-        "unordered_map": "cpp",
-        "utility": "cpp",
-        "vector": "cpp"
-    },
-    "C_Cpp.dimInactiveRegions": false
+        "iostream": "cpp"
+    }
 }
\ No newline at end of file
diff --git a/src/Bishop.cpp b/src/Bishop.cpp
deleted file mode 100644
index c7eeabb..0000000
--- a/src/Bishop.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-#include "Bishop.h"
-#include <iostream>
-using namespace std;
-
-Bishop:: Bishop(PieceColor color, Position pos)
-{
-    this->color = color;
-    this->pos = pos;
-    this->type = "B";
-}
-
-Bishop::~Bishop()
-{
-}
-
-bool Bishop::isValidMove(Position newPos)
-{
-    if (newPos.x < 0 || newPos.x > 7 || newPos.y < 0 || newPos.y > 7)
-    {
-        return false;
-    }
-    if (newPos.x == pos.x || newPos.y == pos.y)
-    {
-        return false;
-    }
-    if (abs(newPos.x - pos.x) == abs(newPos.y - pos.y))
-    {
-        return true;
-    }
-    return false;
-}
diff --git a/src/Bishop.h b/src/Bishop.h
deleted file mode 100644
index 5af7345..0000000
--- a/src/Bishop.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef _BISHOP_H_
-#define _BISHOP_H_
-#include "Piece.h"
-
-class Bishop : public Piece
-{
-    public:
-        /**
-         * @brief Default constructor for Bishop class.
-         */
-        Bishop(PieceColor color, Position pos);
-        
-        /**
-         * @brief Destructor for Bishop class.
-         */
-        ~Bishop();
-        bool isValidMove(Position newPos);
-};  
-
-#endif
\ No newline at end of file
diff --git a/src/Board.cpp b/src/Board.cpp
deleted file mode 100644
index 9af8245..0000000
--- a/src/Board.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-#include "Board.h"
-#include "Square.h"
-#include <iostream>
-using namespace std;
-
-Board::Board()
-{
-    for (int i = 0; i < 8; i++)
-    {
-        for (int j = 0; j < 8; j++)
-        {
-            squares[i][j] = new Square(i, j);
-        }
-    }
-}
-
-Board::~Board()
-{
-    for (int i = 0; i < 8; i++)
-    {
-        for (int j = 0; j < 8; j++)
-        {
-            delete squares[i][j];
-        }
-        delete squares[i];
-    }
-    delete squares;
-}
-
-Board* Board::getBoard()
-{
-    if (board == nullptr)
-    {
-        board = new Board();
-    }
-    return board;
-}
-
-Square* Board::getSquare(int x, int y) const
-{
-    return squares[x][y];
-}
-
-bool Board::isClearVertical(Square& start, Square& end) const
-{
-    Square* 
-}
\ No newline at end of file
diff --git a/src/Board.h b/src/Board.h
deleted file mode 100644
index 3831561..0000000
--- a/src/Board.h
+++ /dev/null
@@ -1,83 +0,0 @@
-#ifndef _BOARD_H
-#define _BOARD_H
-
-#include <ostream>
-#include "Square.h"
-
-/**
- * @class Board
- * @brief Represents a chess board.
- * 
- * The Board class represents a chess board consisting of 64 squares.
- * It provides methods to access and manipulate the squares on the board.
- */
-class Board
-{
-    private:
-        Square* squares[8][8]; /**< 2D array of Square pointers representing the squares on the board. */
-        static Board* board; /**< Pointer to the singleton instance of the Board class. */
-
-    public:
-        /**
-         * @brief Default constructor.
-         */
-        Board();
-
-        /**
-         * @brief Destructor.
-         */
-        ~Board();
-
-        /**
-         * @brief Get the singleton instance of the Board class.
-         * @return Pointer to the Board instance.
-         */
-        static Board* getBoard();
-
-        /**
-         * @brief Get the square at the specified position on the board.
-         * @param x The x-coordinate of the square.
-         * @param y The y-coordinate of the square.
-         * @return Pointer to the Square object at the specified position.
-         */
-        Square* getSquare(int x, int y) const;
-
-        /**
-         * @brief Check if the vertical path between two squares is clear.
-         * @param start Pointer to the starting square.
-         * @param end Pointer to the ending square.
-         * @return True if the vertical path is clear, false otherwise.
-         */
-        bool isClearVertical(Square& start, Square& end) const;
-
-        /**
-         * @brief Check if the horizontal path between two squares is clear.
-         * @param start Pointer to the starting square.
-         * @param end Pointer to the ending square.
-         * @return True if the horizontal path is clear, false otherwise.
-         */
-        bool isClearHorizontal(Square& start, Square& end) const;
-
-        /**
-         * @brief Check if the diagonal path between two squares is clear.
-         * @param start Pointer to the starting square.
-         * @param end Pointer to the ending square.
-         * @return True if the diagonal path is clear, false otherwise.
-         */
-        bool isClearDiagonal(Square& start, Square& end) const;
-
-        /**
-         * @brief Check if the given square is in the end row of the board.
-         * @param s Pointer to the square to check.
-         * @return True if the square is in the end row, false otherwise.
-         */
-        bool isEndRow(Square& s) const;
-
-        /**
-         * @brief Print the board to the specified output stream.
-         * @param outStream The output stream to print the board to.
-         */
-        void afficher(std::ostream& outStream) const;
-};
-
-#endif
\ No newline at end of file
diff --git a/src/Chess.cpp b/src/Chess.cpp
new file mode 100644
index 0000000..205e136
--- /dev/null
+++ b/src/Chess.cpp
@@ -0,0 +1,65 @@
+#include "includes.h"
+#include "Chess.h"
+
+int Chess::getPieceColor( char chPiece )
+{
+    return ( isupper( chPiece ) ? WHITE_PIECE : BLACK_PIECE );
+}
+
+bool Chess::isWhitePiece( char chPiece )
+{
+    return ( getPieceColor( chPiece ) == WHITE_PIECE ? true : false);
+}
+
+bool Chess::isBlackPiece( char chPiece )
+{
+    return ( getPieceColor( chPiece ) == BLACK_PIECE ? true : false);
+}
+
+string Chess::describePiece( char chPiece )
+{
+    string strPiece;
+    switch( chPiece )
+    {
+        case 'P':
+            strPiece = "White Pawn";
+            break;
+        case 'p':
+            strPiece = "Black Pawn";
+            break;
+        case 'N':
+            strPiece = "White Knight";
+            break;
+        case 'n':
+            strPiece = "Black Knight";
+            break;
+        case 'B':
+            strPiece = "White Bishop";
+            break;
+        case 'b':
+            strPiece = "Black Bishop";
+            break;
+        case 'R':
+            strPiece = "White Rook";
+            break;
+        case 'r':
+            strPiece = "Black Rook";
+            break;
+        case 'Q':
+            strPiece = "White Queen";
+            break;
+        case 'q':
+            strPiece = "Black Queen";
+            break;
+        case 'K':
+            strPiece = "White King";
+            break;
+        case 'k':
+            strPiece = "Black King";
+            break;
+        default:
+            strPiece = "Empty";
+            break;
+    }
+    return strPiece;
+}
\ No newline at end of file
diff --git a/src/Chess.h b/src/Chess.h
new file mode 100644
index 0000000..b7d5556
--- /dev/null
+++ b/src/Chess.h
@@ -0,0 +1,134 @@
+#ifndef _CHESS_H_
+#define _CHESS_H_
+
+#include "includes.h"
+
+/**
+ * @brief The Chess class represents a chess game.
+ */
+class Chess 
+{
+    public:
+    /**
+     * @brief Get the color of a chess piece.
+     * 
+     * @param chPiece The character representation of the chess piece.
+     * @return int The color of the chess piece (0 for white, 1 for black).
+     */
+    static int getPieceColor( char chPiece );
+
+    /**
+     * @brief Check if a chess piece is white.
+     * 
+     * @param chPiece The character representation of the chess piece.
+     * @return bool True if the chess piece is white, false otherwise.
+     */
+    static bool isWhitePiece( char chPiece );
+
+    /**
+     * @brief Check if a chess piece is black.
+     * 
+     * @param chPiece The character representation of the chess piece.
+     * @return bool True if the chess piece is black, false otherwise.
+     */
+    static bool isBlackPiece( char chPiece );
+
+    /**
+     * @brief Describe a chess piece.
+     * 
+     * @param chPiece The character representation of the chess piece.
+     * @return std::string The description of the chess piece.
+     */
+    static string describePiece( char chPiece );
+
+    
+    enum PieceColor
+    {
+        WHITE_PIECE = 0,
+        BLACK_PIECE = 1
+    };
+
+    enum Player
+    {
+        WHITE_PLAYER = 0,
+        BLACK_PLAYER = 1
+    };
+
+    enum Side
+    {
+        QUEEN_SIDE = 2,
+        KING_SIDE  = 3
+    };
+
+    enum Direction
+    {
+        HORIZONTAL = 0,
+        VERTICAL,
+        DIAGONAL,
+        L_SHAPE
+    };
+
+    struct Position
+    {
+        int iRow;
+        int iColumn;
+    };
+
+    struct EnPassant
+    {
+        bool bApplied;
+        Position PawnCaptured;
+    };
+
+    struct Castling
+    {
+        bool bApplied;
+        Position rook_before;
+        Position rook_after;
+    };
+
+    struct Promotion
+    {
+        bool bApplied;
+        char chBefore;
+        char chAfter;
+    };
+
+    struct IntendedMove
+    {
+        char chPiece;
+        Position from;
+        Position to;
+    };
+
+    struct Attacker
+    {
+        Position  pos;
+        Direction dir;
+    };
+
+    struct UnderAttack
+    {
+        bool bUnderAttack;
+        int iNumAttackers;
+        Attacker attacker[9]; //maximum theoretical number of attackers
+    };
+
+    const char initial_board[8][8] =
+    {
+        // This represents the pieces on the board.
+        // Keep in mind that pieces[0][0] represents A1
+        // pieces[1][1] represents B2 and so on.
+        // Letters in CAPITAL are white
+        { 'R',  'N',  'B',  'Q',  'K',  'B',  'N',  'R' },
+        { 'P',  'P',  'P',  'P',  'P',  'P',  'P',  'P' },
+        { 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 },
+        { 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 },
+        { 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 },
+        { 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 },
+        { 'p',  'p',  'p',  'p',  'p',  'p',  'p',  'p' },
+        { 'r',  'n',  'b',  'q',  'k',  'b',  'n',  'r' },
+   };
+};
+
+#endif
diff --git a/src/Game.cpp b/src/Game.cpp
new file mode 100644
index 0000000..1da5328
--- /dev/null
+++ b/src/Game.cpp
@@ -0,0 +1,1183 @@
+#include "Game.h"
+#include "user_interface.h"
+
+Game::Game()
+{
+    m_CurrentTurn = WHITE_PLAYER;
+    m_bGameFinished = false;
+    memcpy( board, initial_board, sizeof(char) * 8 * 8);
+
+    m_bCastlingKingSideAllowed[WHITE_PLAYER] = true;
+    m_bCastlingQueenSideAllowed[WHITE_PLAYER] = true;
+    m_bCastlingKingSideAllowed[BLACK_PLAYER] = true;
+    m_bCastlingQueenSideAllowed[BLACK_PLAYER] = true;
+}
+
+Game::~Game()
+{
+
+}
+
+void Game::movePiece( Position present, Position future, EnPassant* S_enPassant, Castling* S_castling, Promotion* S_promotion )
+{
+    char chPiece = getPieceAtPosition( present);
+    char chCapturedPiece = getPieceAtPosition( future );
+
+    if (0x20 != chCapturedPiece)
+    {
+        if (getPieceColor(chCapturedPiece) == WHITE_PIECE )
+        {
+            white_captured.push_back(chCapturedPiece);
+        }
+        else
+        {
+            black_captured.push_back(chCapturedPiece);
+        }
+    }
+    else if (S_enPassant -> bApplied)
+    {
+        char chCapturedEP = getPieceAtPosition( S_enPassant -> PawnCaptured );
+        if (getPieceColor(chCapturedEP) == WHITE_PIECE )
+        {
+            white_captured.push_back(chCapturedEP);
+        }
+        else
+        {
+            black_captured.push_back(chCapturedEP);
+        }
+
+        board[S_enPassant -> PawnCaptured.iRow][S_enPassant -> PawnCaptured.iColumn] = 0x20;
+    }
+    board[present.iRow][present.iColumn] = 0x20;
+
+    if(S_promotion -> bApplied == true)
+    {
+        board[future.iRow][future.iColumn] = S_promotion -> chAfter;
+    }
+    else
+    {
+        board[future.iRow][future.iColumn] = chPiece;
+    }
+    if (S_castling -> bApplied == true)
+    {
+        char chPiece = getPieceAtPosition( S_castling -> rook_before );
+        board[S_castling -> rook_before.iRow][S_castling -> rook_before.iColumn] = 0x20;
+        board[S_castling -> rook_after.iRow][S_castling -> rook_after.iColumn] = chPiece;
+    }
+
+    if(toupper(chPiece) == 'K')
+    {
+        m_bCastlingKingSideAllowed[getCurrentTurn()] = false;
+        m_bCastlingQueenSideAllowed[getCurrentTurn()] = false;
+    }
+    else if (toupper(chPiece) == 'R')
+    {
+        if (present.iColumn == 0)
+        {
+            m_bCastlingQueenSideAllowed[getCurrentTurn()] = false;
+        }
+        else if (present.iColumn == 7)
+        {
+            m_bCastlingKingSideAllowed[getCurrentTurn()] = false;
+        }
+    }
+    changeTurns();
+}
+
+bool Game::castlingAllowed( Side iSide, int iColor )
+{
+    if (iSide == KING_SIDE)
+    {
+        return m_bCastlingKingSideAllowed[iColor];
+    }
+    else
+    {
+        return m_bCastlingQueenSideAllowed[iColor];
+    }
+}
+
+char Game::getPieceAtPosition(Position pos)
+{
+    return board[pos.iRow][pos.iColumn];
+}
+
+char Game::getPieceAtPosition(int iRow, int iColumn)
+{
+    return board[iRow][iColumn];
+}
+
+char Game::getPiece_considerMove(int iRow, int iColumn, IntendedMove* intended_move)
+{
+    char chPiece;
+    if (intended_move == nullptr)
+    {
+        chPiece = getPieceAtPosition(iRow, iColumn);
+    }
+    else
+    {
+        if(intended_move -> from.iRow == iRow && intended_move -> from.iColumn == iColumn)
+        {
+            chPiece = EMPTY_SQUARE;
+        }
+        else if (intended_move->to.iRow == iRow && intended_move->to.iColumn == iColumn)
+        {
+            chPiece = intended_move->chPiece;
+        }
+        else
+        {
+            chPiece = getPieceAtPosition(iRow, iColumn);
+        }
+    }
+    return chPiece;
+}
+
+Chess::UnderAttack Game::isUnderAttack(int iRow, int iColumn, int iColor, IntendedMove* pintended_move)
+{
+    UnderAttack attack  = {0};
+    // Direction: Horizontal
+    {
+        //Right way
+        for (int i = iColumn + 1;i<8;i++)
+        {
+            char chPieceFound = getPiece_considerMove(iRow, i, pintended_move);
+            if (EMPTY_SQUARE == chPieceFound)
+            {
+                continue;
+            }
+
+            if (getPieceColor(chPieceFound) == iColor)
+            {
+                break;
+            }
+            else if (toupper(chPieceFound) == 'Q' || toupper(chPieceFound) == 'R')
+            {
+                attack.bUnderAttack = true;
+                attack.iNumAttackers++;
+
+                attack.attacker[attack.iNumAttackers-1].pos.iRow = iRow;
+                attack.attacker[attack.iNumAttackers-1].pos.iColumn = i;
+                attack.attacker[attack.iNumAttackers-1].dir = HORIZONTAL;
+                break;
+            }
+            else
+            {
+                break;
+            }
+        }
+        //Left way
+        for (int i = iColumn - 1;i>=0;i--)
+        {
+            char chPieceFound = getPiece_considerMove(iRow, i, pintended_move);
+            if (EMPTY_SQUARE == chPieceFound)
+            {
+                continue;
+            }
+
+            if (getPieceColor(chPieceFound) == iColor)
+            {
+                break;
+            }
+            else if (toupper(chPieceFound) == 'Q' || toupper(chPieceFound) == 'R')
+            {
+                attack.bUnderAttack = true;
+                attack.iNumAttackers++;
+
+                attack.attacker[attack.iNumAttackers-1].pos.iRow = iRow;
+                attack.attacker[attack.iNumAttackers-1].pos.iColumn = i;
+                attack.attacker[attack.iNumAttackers-1].dir = HORIZONTAL;
+                break;
+            }
+            else
+            {
+                break;
+            }
+        }
+    }
+    // Vertical
+    {
+        //Way up
+        for (int i= iRow +1; i<8; i++)
+        {
+            char chPieceFound = getPiece_considerMove(i, iColumn, pintended_move);
+            if (chPieceFound == EMPTY_SQUARE)
+            {
+                continue;
+            }
+            if (getPieceColor(chPieceFound) == iColor)
+            {
+                break;
+            }
+            else if (toupper(chPieceFound) == 'Q' || toupper(chPieceFound) == 'R')
+            {
+                attack.bUnderAttack = true;
+                attack.iNumAttackers++;
+
+                attack.attacker[attack.iNumAttackers-1].pos.iRow = i;
+                attack.attacker[attack.iNumAttackers-1].pos.iColumn = iColumn;
+                attack.attacker[attack.iNumAttackers-1].dir = VERTICAL;
+                break;
+            }
+            else
+            {
+                break;
+            }
+        }
+        //Way down
+        for (int i=iRow - 1;i>=0;i--)
+        {
+            char chPieceFound = getPiece_considerMove(i, iColumn, pintended_move);
+            if (chPieceFound == EMPTY_SQUARE)
+            {
+                continue;
+            }
+            if (getPieceColor(chPieceFound) == iColor)
+            {
+                break;
+            }
+            else if (toupper(chPieceFound) == 'Q' || toupper(chPieceFound) == 'R')
+            {
+                attack.bUnderAttack = true;
+                attack.iNumAttackers++;
+
+                attack.attacker[attack.iNumAttackers-1].pos.iRow = i;
+                attack.attacker[attack.iNumAttackers-1].pos.iColumn = iColumn;
+                attack.attacker[attack.iNumAttackers-1].dir = VERTICAL;
+                break;
+            }
+            else
+            {
+                break;
+            }   
+        }
+    }
+    // Diagonal
+    {
+        // up-right
+        for (int i = iRow + 1, j = iColumn + 1 ; i<8 && j<8; i++, j++)
+        {
+            char chPieceFound = getPiece_considerMove(i, j, pintended_move);
+            if (chPieceFound == EMPTY_SQUARE)
+            {
+                continue;
+            }
+            if (getPieceColor(chPieceFound) == iColor)
+            {
+                break;
+            }
+            else if ((toupper(chPieceFound) == 'P') && (i == iRow + 1) && (j == iColumn + 1) && (iColor == WHITE_PIECE))
+            {
+                attack.bUnderAttack = true;
+                attack.iNumAttackers++;
+
+                attack.attacker[attack.iNumAttackers-1].pos.iRow = i;
+                attack.attacker[attack.iNumAttackers-1].pos.iColumn = j;
+                attack.attacker[attack.iNumAttackers-1].dir = DIAGONAL;
+                break;
+            }
+            else if (toupper(chPieceFound) == 'Q' || toupper(chPieceFound) == 'B')
+            {
+                attack.bUnderAttack = true;
+                attack.iNumAttackers++;
+
+                attack.attacker[attack.iNumAttackers-1].pos.iRow = i;
+                attack.attacker[attack.iNumAttackers-1].pos.iColumn = j;
+                attack.attacker[attack.iNumAttackers-1].dir = DIAGONAL;
+                break;
+            }
+            else
+            {
+                break;
+            }
+        }
+        // up-left
+        {
+            for (int i = iRow + 1, j = iColumn -1 ; i<8 && j>0; i++, j--)
+            {
+                char chPieceFound = getPiece_considerMove(i, j, pintended_move);
+                if (chPieceFound == EMPTY_SQUARE)
+                {
+                    continue;
+                }
+                if (getPieceColor(chPieceFound) == iColor)
+                {
+                    break;
+                }
+                else if ((toupper(chPieceFound) == 'P') && (i == iRow + 1) && (j == iColumn - 1) && (iColor == WHITE_PIECE))
+                {
+                    attack.bUnderAttack = true;
+                    attack.iNumAttackers++;
+
+                    attack.attacker[attack.iNumAttackers-1].pos.iRow = i;
+                    attack.attacker[attack.iNumAttackers-1].pos.iColumn = j;
+                    attack.attacker[attack.iNumAttackers-1].dir = DIAGONAL;
+                    break;
+                }
+                else if (toupper(chPieceFound) == 'Q' || toupper(chPieceFound) == 'B')
+                {
+                    attack.bUnderAttack = true;
+                    attack.iNumAttackers++;
+
+                    attack.attacker[attack.iNumAttackers-1].pos.iRow = i;
+                    attack.attacker[attack.iNumAttackers-1].pos.iColumn = j;
+                    attack.attacker[attack.iNumAttackers-1].dir = DIAGONAL;
+                    break;
+                }
+                else
+                {
+                    break;
+                }
+            }
+        }
+        // down-right
+        {
+            for (int i = iRow - 1, j = iColumn + 1; i > 0 && j < 8; i--, j++)
+            {
+                char chPieceFound = getPiece_considerMove(i, j, pintended_move);
+                if (chPieceFound == EMPTY_SQUARE)
+                {
+                    continue;
+                }
+                if(getPieceColor(chPieceFound) == iColor)
+                {
+                    break;
+                }
+                else if ((toupper(chPieceFound) == 'P') && (i == iRow - 1) && (j == iColumn + 1) && (iColor == BLACK_PIECE))
+                {
+                    attack.bUnderAttack = true;
+                    attack.iNumAttackers++;
+
+                    attack.attacker[attack.iNumAttackers-1].pos.iRow = i;
+                    attack.attacker[attack.iNumAttackers-1].pos.iColumn = j;
+                    attack.attacker[attack.iNumAttackers-1].dir = DIAGONAL;
+                    break;
+                }
+                else if (toupper(chPieceFound) == 'Q' || toupper(chPieceFound) == 'B')
+                {
+                    attack.bUnderAttack = true;
+                    attack.iNumAttackers++;
+
+                    attack.attacker[attack.iNumAttackers-1].pos.iRow = i;
+                    attack.attacker[attack.iNumAttackers-1].pos.iColumn = j;
+                    attack.attacker[attack.iNumAttackers-1].dir = DIAGONAL;
+                    break;
+                }
+                else
+                {
+                    break;
+                }
+            }
+        }
+        // down-left
+        {
+            for (int i = iRow - 1, j = iColumn - 1; i > 0 && j > 0; i--, j--)
+            {
+                char chPieceFound = getPiece_considerMove(i, j, pintended_move);
+                if (chPieceFound == EMPTY_SQUARE)
+                {
+                    continue;
+                }
+                if(getPieceColor(chPieceFound) == iColor)
+                {
+                    break;
+                }
+                else if ((toupper(chPieceFound) == 'P') && (i == iRow - 1) && (j == iColumn - 1) && (iColor == BLACK_PIECE))
+                {
+                    attack.bUnderAttack = true;
+                    attack.iNumAttackers++;
+
+                    attack.attacker[attack.iNumAttackers-1].pos.iRow = i;
+                    attack.attacker[attack.iNumAttackers-1].pos.iColumn = j;
+                    attack.attacker[attack.iNumAttackers-1].dir = DIAGONAL;
+                    break;
+                }
+                else if (toupper(chPieceFound) == 'Q' || toupper(chPieceFound) == 'B')
+                {
+                    attack.bUnderAttack = true;
+                    attack.iNumAttackers++;
+
+                    attack.attacker[attack.iNumAttackers-1].pos.iRow = i;
+                    attack.attacker[attack.iNumAttackers-1].pos.iColumn = j;
+                    attack.attacker[attack.iNumAttackers-1].dir = DIAGONAL;
+                    break;
+                }
+                else
+                {
+                    break;
+                }
+            }
+        }
+    }
+    // L_Shaped
+    {
+        Position knight_moves[8] = { {1,-2}, {2, -1}, {2, 1}, {1, 2},
+                                    {-1, -2}, {-2, -1}, {-2, 1}, {-1, 2} };
+        for (int i=0;i<8;i++)
+        {
+            int iRowToTest = iRow + knight_moves[i].iRow;
+            int iColumnToTest = iColumn + knight_moves[i].iColumn;
+
+            if (iRowToTest < 0 || iRowToTest > 7 || iColumnToTest < 0 || iColumnToTest > 7)
+            {
+                // not exists
+                continue;
+            }
+
+            char chPieceFound = getPiece_considerMove(iRowToTest, iColumnToTest, pintended_move);
+            if (chPieceFound == EMPTY_SQUARE)
+            {
+                // empty
+                continue;
+            }
+            if (getPieceColor(chPieceFound) == iColor)
+            {
+                // same color
+                continue;
+            }
+            else if ((toupper(chPieceFound) == 'N'))
+            {
+                attack.bUnderAttack = true;
+                attack.iNumAttackers++;
+
+                attack.attacker[attack.iNumAttackers-1].pos.iRow = iRowToTest;
+                attack.attacker[attack.iNumAttackers-1].pos.iColumn = iColumnToTest;
+                attack.attacker[attack.iNumAttackers-1].dir = L_SHAPE;
+            }
+        }
+    }
+    return attack;
+}
+bool Game::isReachable(int iRow, int iColumn, int iColor)
+{
+    bool bReachable = false;
+    // Horizontal
+    {
+        // Right way
+        for (int i = iColumn + 1; i<8; i++)
+        {
+            char chPieceFound = getPieceAtPosition(iRow, i);
+            if (EMPTY_SQUARE == chPieceFound)
+            {
+                continue;
+            }
+            if (getPieceColor(chPieceFound) == iColor)
+            {
+                break;
+            }
+            else if (toupper(chPieceFound) == 'Q' || toupper(chPieceFound) == 'R')
+            {
+                bReachable = true;
+                break;
+            }
+            else
+            {
+                break;
+            }
+        }
+        // Left way
+        for (int i= iColumn - 1 ; i>=0;i--)
+        {
+            char chPieceFound = getPieceAtPosition(iRow, i);
+            if (EMPTY_SQUARE == chPieceFound)
+            {
+                continue;
+            }
+            if (getPieceColor(chPieceFound) == iColor)
+            {
+                break;
+            }
+            else if (toupper(chPieceFound) == 'Q' || toupper(chPieceFound) == 'R')
+            {
+                bReachable = true;
+                break;
+            }
+            else
+            {
+                break;
+            }
+        }
+    }
+    // Vertical
+    {
+        //Way up
+        for (int i= iRow+1; i<8; i++)
+        {
+            char chPieceFound = getPieceAtPosition(i, iColumn);
+            if (chPieceFound == EMPTY_SQUARE)
+            {
+                continue;
+            }
+            if(getPieceColor(chPieceFound) == iColor)
+            {
+                break;
+            }
+            else if (toupper(chPieceFound) == 'P' && getPieceColor(chPieceFound) == BLACK_PIECE && (i == iRow +1))
+            {
+                bReachable = true;
+                break;
+            }
+            else if (toupper(chPieceFound) == 'Q' || toupper(chPieceFound) == 'R')
+            {
+                bReachable = true;
+                break;
+            }
+            else
+            {
+                break;
+            }
+        }
+        // Way down
+        for (int i= iRow - 1 ; i>= 0; i--)
+        {
+            char chPieceFound = getPieceAtPosition(i, iColumn);
+            if (chPieceFound == EMPTY_SQUARE)
+            {
+                continue;
+            }
+            if (getPieceColor(chPieceFound) == iColor)
+            {
+                break;
+            }
+            else if (toupper(chPieceFound) == 'P' && getPieceColor(chPieceFound) == WHITE_PIECE && (i == iRow - 1))
+            {
+                bReachable = true;
+                break;
+            }
+            else if (toupper(chPieceFound) == 'Q' || toupper(chPieceFound) == 'R')
+            {
+                bReachable = true;
+                break;
+            }
+            else
+            {
+                break;
+            }
+        }
+    }
+    // Diagonal
+    {
+        // up-right
+        for (int i = iRow+1, j = iColumn + 1; i < 8 && j < 8;i++, j++)
+        {
+            char chPieceFound = getPieceAtPosition(i, j);
+            if (chPieceFound == EMPTY_SQUARE)
+            {
+                continue;
+            }
+            if (getPieceColor(chPieceFound) == iColor)
+            {
+                break;
+            }
+            else if (toupper(chPieceFound) == 'Q' || toupper(chPieceFound) == 'B')
+            {
+                bReachable = true;
+                break;
+            }
+            else
+            {
+                break;
+            }
+        }
+        // up-left
+        for (int i = iRow + 1, j = iColumn - 1; i < 8 && j > 0; i++, j--)
+        {
+            char chPieceFound = getPieceAtPosition(i, j);
+            if (chPieceFound == EMPTY_SQUARE)
+            {
+                continue;
+            }
+            if (getPieceColor(chPieceFound) == iColor)
+            {
+                break;
+            }
+            else if (toupper(chPieceFound) == 'Q' || toupper(chPieceFound) == 'B')
+            {
+                bReachable = true;
+                break;
+            }
+            else
+            {
+                break;
+            }
+        }
+        // down-right
+        for(int i = iRow - 1, j = iColumn + 1; i > 0 && j < 8; i--, j++)
+        {
+            char chPieceFound = getPieceAtPosition(i, j);
+            if (chPieceFound == EMPTY_SQUARE)
+            {
+                continue;
+            }
+            if (getPieceColor(chPieceFound) == iColor)
+            {
+                break;
+            }
+            else if (toupper(chPieceFound) == 'Q' || toupper(chPieceFound) == 'B')
+            {
+                bReachable = true;
+                break;
+            }
+            else
+            {
+                break;
+            }
+        }
+        // down-left
+        for (int i = iRow - 1, j = iColumn - 1; i > 0 && j > 0; i--, j--)
+        {
+            char chPieceFound = getPieceAtPosition(i, j);
+            if (chPieceFound == EMPTY_SQUARE)
+            {
+                continue;
+            }
+            if (getPieceColor(chPieceFound) == iColor)
+            {
+                break;
+            }
+            else if (toupper(chPieceFound) == 'Q' || toupper(chPieceFound) == 'B')
+            {
+                bReachable = true;
+                break;
+            }
+            else
+            {
+                break;
+            }
+        }
+    }
+    // L_SHAPED
+    {
+        Position knight_moves[8] = { {1,-2}, {2, -1}, {2, 1}, {1, 2},
+                                    {-1, -2}, {-2, -1}, {-2, 1}, {-1, 2} };
+        for (int i=0;i<8;i++)
+        {
+            int iRowToTest = iRow + knight_moves[i].iRow;
+            int iColumnToTest = iColumn + knight_moves[i].iColumn;
+
+            if (iRowToTest < 0 || iRowToTest > 7 || iColumnToTest < 0 || iColumnToTest > 7)
+            {
+                // not exists
+                continue;
+            }
+
+            char chPieceFound = getPieceAtPosition(iRowToTest, iColumnToTest);
+            if (chPieceFound == EMPTY_SQUARE)
+            {
+                // empty
+                continue;
+            }
+            if (getPieceColor(chPieceFound) == iColor)
+            {
+                // same color
+                continue;
+            }
+            else if ((toupper(chPieceFound) == 'N'))
+            {
+                bReachable = true;
+                break;
+            }
+        }
+    }
+    return bReachable;
+}
+
+bool Game::isSquareOccupied(int iRow, int iColumn)
+{
+    bool bOccupied = false;
+    if (0x20 != getPieceAtPosition(iRow, iColumn))
+    {
+        bOccupied = true;
+    }
+    return bOccupied;
+}
+
+bool Game::isPathFree(Position startingPos, Position finishingPos, int iDirection)
+{
+    bool bFree = false;
+    
+    switch(iDirection)
+    {
+            case Chess::HORIZONTAL:
+            {
+                // If it's a horizontal move, we assume that the startingPos.iRow == finishingPos.iRow
+                // If the piece wants to mive from column 0 to column 7, we must check if columns 1-6 are free
+                if (startingPos.iColumn == finishingPos.iColumn)
+                {
+                    cout << "Error: Movement is horizontal but column is the same " << endl;
+                }
+
+                // moving to the right
+                else if (startingPos.iColumn < finishingPos.iColumn)
+                {
+                    // setting bFree as initially true, only inside the cases, gurantees that the path is checked
+                    bFree = true;
+
+                    for (int i = startingPos.iColumn + 1; i < finishingPos.iColumn; i++)
+                    {
+                        if (isSquareOccupied( startingPos.iRow, i))
+                        {
+                            bFree = false;
+                            cout << "Horizontal path to the right is not clear" << endl;
+                        }
+                    }
+                }
+                // moving to the left
+                else // if (startingPos.iColumn > finishingPos.iColumn)
+                {
+                    bFree = true;
+                    for (int i = startingPos.iColumn - 1; i > finishingPos.iColumn; i--)
+                    {
+                        if (isSquareOccupied( startingPos.iRow, i))
+                        {
+                            bFree = false;
+                            cout << "Horizontal path to the left is not clear" << endl;
+                        }
+                    }
+                }
+            }
+            break;
+
+            case Chess::VERTICAL:
+            {
+                // If it's a vertical move, we assume that the startingPos.iColumn == finishingPos.iColumn
+                // If the piece wants to move from row 0 to row 7, we must check if rows 1-6 are free
+                if (startingPos.iRow == finishingPos.iRow)
+                {
+                    cout << "Error: Movement is vertical but row is the same " << endl;
+                }
+
+                // moving up
+                else if (startingPos.iRow < finishingPos.iRow)
+                {
+                    bFree = true;
+                    for (int i = startingPos.iRow + 1; i < finishingPos.iRow; i++)
+                    {
+                        if (isSquareOccupied( i, startingPos.iColumn))
+                        {
+                            bFree = false;
+                            cout << "Vertical path up is not clear" << endl;
+                        }
+                    }
+                }
+                // moving down
+                else // if (startingPos.iRow > finishingPos.iRow)
+                {
+                    bFree = true;
+                    for (int i = startingPos.iRow - 1; i > finishingPos.iRow; i--)
+                    {
+                        if (isSquareOccupied( i, startingPos.iColumn))
+                        {
+                            bFree = false;
+                            cout << "Vertical path down is not clear" << endl;
+                        }
+                    }
+                }
+            }
+            break;
+
+            case Chess::DIAGONAL:
+            {
+                //Moving up and right
+                if ((finishingPos.iRow > startingPos.iRow) && (finishingPos.iColumn > startingPos.iColumn))
+                {
+                    bFree = true;
+                    for (int i = 1;i < abs(finishingPos.iRow - startingPos.iRow); i++)
+                    {
+                        if (isSquareOccupied( startingPos.iRow + i, startingPos.iColumn + i))
+                        {
+                            bFree = false;
+                            cout << "Diagonal path up and right is not clear" << endl;
+                        }
+                    }
+                }
+                // moving up and left
+                else if ((finishingPos.iRow > startingPos.iRow) && (finishingPos.iColumn < startingPos.iColumn))
+                {
+                    bFree = true;
+                    for (int i = 1;i < abs(finishingPos.iRow - startingPos.iRow); i++)
+                    {
+                        if (isSquareOccupied( startingPos.iRow + i, startingPos.iColumn - i))
+                        {
+                            bFree = false;
+                            cout << "Diagonal path up and left is not clear" << endl;
+                        }
+                    }
+                }
+                // moving down and right
+                else if ((finishingPos.iRow < startingPos.iRow) && (finishingPos.iColumn > startingPos.iColumn))
+                {
+                    bFree = true;
+                    for (int i = 1;i < abs(finishingPos.iRow - startingPos.iRow); i++)
+                    {
+                        if (isSquareOccupied( startingPos.iRow - i, startingPos.iColumn + i))
+                        {
+                            bFree = false;
+                            cout << "Diagonal path down and right is not clear" << endl;
+                        }
+                    }
+                }
+                // moving down and left
+                else if ((finishingPos.iRow < startingPos.iRow) && (finishingPos.iColumn < startingPos.iColumn))
+                {
+                    bFree = true;
+                    for (int i = 1;i < abs(finishingPos.iRow - startingPos.iRow); i++)
+                    {
+                        if (isSquareOccupied( startingPos.iRow - i, startingPos.iColumn - i))
+                        {
+                            bFree = false;
+                            cout << "Diagonal path down and left is not clear" << endl;
+                        }
+                    }
+                }   
+                else
+                {
+                    cout << "Error: Invalid diagonal movement" << endl;
+                }
+            }
+            break;
+    }  
+    return bFree;
+}
+
+bool Game::canBeBlocked(Position startingPos, Position finishingPos, int iDirection)
+{
+    bool bBlocked = false;
+    Chess::UnderAttack blocker = {0};
+    switch(iDirection)
+    {
+        case Chess::HORIZONTAL:
+        {
+            if(startingPos.iColumn == finishingPos.iColumn)
+            {
+                cout << "Error: Movement is horizontal but column is the same" << endl;
+            }
+            // moving to the right
+            else if (startingPos.iColumn < finishingPos.iColumn)
+            {
+                for (int i = startingPos.iColumn + 1; i < finishingPos.iColumn; i++)
+                {
+                    if (isReachable(startingPos.iRow, i, getOpponentColor()))
+                    {
+                       bBlocked = true;
+                    }
+                }
+            }
+            // moving to the left
+            else // if (startingPos.iColumn > finishingPos.iColumn)
+            {
+                for (int i = startingPos.iColumn - 1; i > finishingPos.iColumn; i--)
+                {
+                    if (isReachable(startingPos.iRow, i, getOpponentColor()))
+                    {
+                        bBlocked = true;
+                    }
+                }
+            }
+        }
+        break;
+
+        case Chess::VERTICAL:
+        {
+            if (startingPos.iRow == finishingPos.iRow)
+            {
+                cout << "Error: Movement is vertical but row is the same" << endl;
+            }
+            // moving up
+            else if (startingPos.iRow < finishingPos.iRow)
+            {
+                for (int i = startingPos.iRow + 1 ; i<finishingPos.iRow; i++)
+                {
+                    if (isReachable(i, startingPos.iColumn, getOpponentColor()))
+                    {
+                        bBlocked = true;
+                    }
+                }
+            }
+            // moving down
+            else // if (startingPos.iRow > finishingPos.iRow)
+            {
+                for (int i = startingPos.iRow - 1; i > finishingPos.iRow; i--)
+                {
+                    if (isReachable(i, startingPos.iColumn, getOpponentColor()))
+                    {
+                        bBlocked = true;
+                    }
+                }
+            }
+        }
+        break;
+
+        case Chess::DIAGONAL:
+        {
+            // up and right
+            if ((finishingPos.iRow > startingPos.iRow) && (finishingPos.iColumn > startingPos.iColumn))
+            {
+                for (int i = 1; i < abs(finishingPos.iRow - startingPos.iRow); i++)
+                {
+                    if (isReachable(startingPos.iRow + i, startingPos.iColumn + i, getOpponentColor()))
+                    {
+                        bBlocked = true;
+                    }
+                }
+            }
+            // up and left
+            else if ((finishingPos.iRow > startingPos.iRow) && (finishingPos.iColumn < startingPos.iColumn))
+            {
+                for (int i = 1; i < abs(finishingPos.iRow - startingPos.iRow); i++)
+                {
+                    if (isReachable(startingPos.iRow + i, startingPos.iColumn - i, getOpponentColor()))
+                    {
+                        bBlocked = true;
+                    }
+                }
+            }
+            // down and right
+            else if ((finishingPos.iRow < startingPos.iRow) && (finishingPos.iColumn > startingPos.iColumn))
+            {
+                for (int i = 1; i < abs(finishingPos.iRow - startingPos.iRow); i++)
+                {
+                    if (isReachable(startingPos.iRow - i, startingPos.iColumn + i, getOpponentColor()))
+                    {
+                        bBlocked = true;
+                    }
+                }
+            }
+            // down and left
+            else if ((finishingPos.iRow < startingPos.iRow) && (finishingPos.iColumn < startingPos.iColumn))
+            {
+                for (int i = 1; i < abs(finishingPos.iRow - startingPos.iRow); i++)
+                {
+                    if (isReachable(startingPos.iRow - i, startingPos.iColumn - i, getOpponentColor()))
+                    {
+                        bBlocked = true;
+                    }
+                }
+            }
+            else
+            {
+                cout << "Error: Invalid diagonal movement" << endl;
+            }
+        }
+    }
+    return bBlocked;
+}
+
+bool Game::isCheckMate()
+{
+    bool bCheckMate = false;
+    // 1, is the king in check?
+    if (playerKingInCheck() == false)
+    {
+        bCheckMate = false;
+    }
+    // 2, Can the king move to another square?
+    Chess::Position king_moves[8] = { {1,-1}, {1,0}, {1,1}, {0,1},
+                                    {-1,1}, {-1,0}, {-1,-1}, {0,-1} };
+    
+    Chess::Position king = findKing(getCurrentTurn());
+    for (int i=0;i<8;i++)
+    {
+        int iRowToTest = king.iRow + king_moves[i].iRow;
+        int iColumnToTest = king.iColumn + king_moves[i].iColumn;
+
+        if (iRowToTest < 0 || iRowToTest > 7 || iColumnToTest < 0 || iColumnToTest > 7)
+        {
+            continue;
+        }
+
+        if (getPieceAtPosition(iRowToTest, iColumnToTest) != EMPTY_SQUARE)
+        {
+            continue;
+        }
+
+        Chess::IntendedMove intended_move;
+        intended_move.chPiece = getPieceAtPosition(king.iRow, king.iColumn);
+        intended_move.from.iRow = king.iRow;
+        intended_move.from.iColumn = king.iColumn;
+        intended_move.to.iRow = iRowToTest;
+        intended_move.to.iColumn = iColumnToTest;
+
+        Chess::UnderAttack king_moved = isUnderAttack(iRowToTest, iColumnToTest, getCurrentTurn(), &intended_move);
+        if (king_moved.bUnderAttack == false)
+        {
+            // this means there's at least one pos when the king move would not be under attack
+            return false;
+        }
+    }
+    // 3, Can the attacking piece be captured? Or be blocked?
+    Chess::UnderAttack king_attacked = isUnderAttack(king.iRow, king.iColumn, getCurrentTurn());
+    if (king_attacked.iNumAttackers == 1)
+    {
+        // Can the attacking piece be captured?
+        Chess::UnderAttack king_attacker = {0};
+        king_attacker = isUnderAttack(king_attacked.attacker[0].pos.iRow, king_attacked.attacker[0].pos.iColumn, getOpponentColor());
+        if (king_attacker.bUnderAttack == true)
+        {
+            // this means the attacking piece can be captured, so it's not a checkmate
+            return false;
+        }
+        else
+        {
+            // Can the attacking piece be blocked?
+            char chAttacker = getPieceAtPosition(king_attacked.attacker[0].pos);
+            switch(toupper(chAttacker))
+            {
+                // if it's a pawn, there's no space in between the king and the pawn
+                case 'P':
+                // if it's a knight, it can't be blocked, this is checkmate
+                case 'N':
+                {
+                    bCheckMate = true;
+                }
+                break;
+
+                case 'B':
+                {
+                    if (canBeBlocked(king_attacked.attacker[0].pos, king, Chess::DIAGONAL) == false)
+                    {
+                        bCheckMate = true;
+                    }
+                }
+                break;
+
+                case 'R':
+                {
+                    if (canBeBlocked(king_attacked.attacker[0].pos, king, king_attacked.attacker[0].dir) == false)
+                    {
+                        bCheckMate = true;
+                    }
+                }
+                break;
+
+                case 'Q':
+                {
+                    if (canBeBlocked(king_attacked.attacker[0].pos, king, king_attacked.attacker[0].dir) == false)
+                    {
+                        bCheckMate = true;
+                    }
+                }
+                break;
+
+                default:
+                {
+                    cout << "Error: Invalid piece" << endl;
+                }
+                break;
+            }
+        }
+    }
+    else
+    {
+        bCheckMate = true;
+    }
+    m_bGameFinished = bCheckMate;
+    return bCheckMate;
+}
+
+bool Game::isKingInCheck(int iColor, IntendedMove* pintended_move)
+{
+    bool bCheck = false;
+    Position king = {0};
+    //Must check if the intended move is to move the king itself
+    if (pintended_move != nullptr && toupper(pintended_move -> chPiece) == 'K')
+    {
+        king.iRow = pintended_move -> to.iRow;
+        king.iColumn = pintended_move -> to.iColumn;
+    }
+    else
+    {
+        king = findKing(iColor);
+    }
+
+    UnderAttack king_attacked = isUnderAttack(king.iRow, king.iColumn, iColor, pintended_move);
+    if (king_attacked.bUnderAttack == true)
+    {
+        bCheck = true;
+    }
+    return bCheck;
+}
+
+bool Game::playerKingInCheck(IntendedMove* intended_move)
+{
+    return isKingInCheck(getCurrentTurn(), intended_move);
+}
+
+bool Game::wouldKingBeInCheck(char chPiece, Position present, Position future, EnPassant* S_enPassant)
+{
+    IntendedMove intended_move;
+    
+    intended_move.chPiece = chPiece;
+    intended_move.from = present;
+    intended_move.to = future;
+    return playerKingInCheck(&intended_move);
+}
+
+Chess::Position Game::findKing(int iColor)
+{
+    char chToLook = (iColor == WHITE_PIECE) ? 'K' : 'k';
+    Position king = {0};
+    for (int i=0;i<8;i++)
+    {
+        for (int j=0;j<8;j++)
+        {
+            if (getPieceAtPosition(i,j) == chToLook)
+            {
+                king.iRow = i;
+                king.iColumn = j;
+            }
+        }
+    }
+    return king;
+}
+
+void Game::changeTurns(void)
+{
+    if (m_CurrentTurn == WHITE_PIECE)
+    {
+        m_CurrentTurn = BLACK_PIECE;
+    }
+    else
+    {
+        m_CurrentTurn = WHITE_PIECE;
+    }
+}
+
+bool Game::isFinished(void)
+{
+    return m_bGameFinished;
+}
+
+int Game::getCurrentTurn(void)
+{
+    return m_CurrentTurn;
+}
+
+int Game::getOpponentColor(void)
+{
+    return (m_CurrentTurn == WHITE_PIECE) ? BLACK_PIECE : WHITE_PIECE;
+}
+
+void Game::parseMove(string move, Position* pFrom, Position* pTo, char* chPromoted)
+{
+    pFrom->iColumn = move[0];
+    pFrom->iRow = move[1];
+    pTo->iColumn = move[3];
+    pTo->iRow = move[4];
+
+    pFrom ->iColumn -= 'A';
+    pTo ->iColumn -= 'A';
+
+    pFrom ->iRow -= '1';
+    pTo ->iRow -= '1';
+
+    if (chPromoted != nullptr)
+    {
+        if(move[5] == '=')
+        {
+            *chPromoted = move[6];
+        }
+        else
+        {
+            *chPromoted = EMPTY_SQUARE;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/Game.h b/src/Game.h
new file mode 100644
index 0000000..ef23c57
--- /dev/null
+++ b/src/Game.h
@@ -0,0 +1,65 @@
+#ifndef _GAME_H_
+#define _GAME_H_
+#include "includes.h"
+#include "Chess.h"
+
+class Game : public Chess
+{
+    public:
+        Game();
+
+        ~Game();
+
+        void movePiece( Position present, Position future, EnPassant* S_enPassant, Castling* S_castling, Promotion* S_promotion );
+
+        bool castlingAllowed( Side iSide, int iColor );
+
+        char getPieceAtPosition( Position pos );
+
+        char getPieceAtPosition( int iRow, int iColumn );
+
+        char getPiece_considerMove( int iRow, int iColumn, IntendedMove* intended_move = nullptr );
+
+        UnderAttack isUnderAttack( int iRow, int iColumn, int iColor, IntendedMove* pintended_move = nullptr );
+
+        bool isReachable( int iRow, int iColumn, int iColor );
+
+        bool isSquareOccupied( int iRow, int iColumn);
+
+        bool isPathFree( Position startingPos, Position finishingPos, int iDirection ); 
+
+        bool canBeBlocked( Position startingPos, Position finishinPos, int iDirection );
+
+        bool isCheckMate();
+
+        bool isKingInCheck( int iColor, IntendedMove* intended_move = nullptr );
+
+        bool playerKingInCheck( IntendedMove* intended_move = nullptr );
+
+        bool wouldKingBeInCheck( char chPiece, Position present, Position future, EnPassant* S_enPassant );
+
+        Position findKing( int iColor );
+
+        void changeTurns( void );
+
+        bool isFinished( void );
+
+        int getCurrentTurn( void );
+
+        int getOpponentColor( void );
+
+        void parseMove(string move, Position* pFrom, Position* pTo, char* chPromoted = nullptr );
+
+        // Save the captured pieces
+        vector<char> white_captured;
+        vector<char> black_captured;
+
+        private:
+            char board[8][8];
+            bool m_bCastlingKingSideAllowed[2];
+            bool m_bCastlingQueenSideAllowed[2];
+            int m_CurrentTurn;
+            bool m_bGameFinished;
+
+};
+#endif
\ No newline at end of file
diff --git a/src/Knight.cpp b/src/Knight.cpp
deleted file mode 100644
index cede3d2..0000000
--- a/src/Knight.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-#include "Knight.h"
-#include <iostream>
-using namespace std;
-
-Knight::Knight(PieceColor color, Position pos)
-{
-    this->color = color;
-    this->pos = pos;
-    this->type = "N";
-}
-
-Knight::~Knight()
-{
-}
-
-bool Knight::isValidMove(Position newPos)
-{
-    if (newPos.x < 0 || newPos.x > 7 || newPos.y < 0 || newPos.y > 7)
-    {
-        return false;
-    }
-    if (newPos.x == pos.x || newPos.y == pos.y)
-    {
-        return false;
-    }
-    if (abs(newPos.x - pos.x) == 2 && abs(newPos.y - pos.y) == 1)
-    {
-        return true;
-    }
-    if (abs(newPos.x - pos.x) == 1 && abs(newPos.y - pos.y) == 2)
-    {
-        return true;
-    }
-    return false;
-}
\ No newline at end of file
diff --git a/src/Knight.h b/src/Knight.h
deleted file mode 100644
index b3d9e26..0000000
--- a/src/Knight.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef _KNIGHT_H
-#define _KNIGHT_H
-#include "Piece.h"
-
-class Knight : public Piece
-{
-    public:
-        /**
-         * @brief Default constructor for Knight class.
-         */
-        Knight(PieceColor color, Position pos);
-        
-        /**
-         * @brief Destructor for Knight class.
-         */
-        ~Knight();
-        bool isValidMove(Position newPos);
-};
-
-#endif
\ No newline at end of file
diff --git a/src/Piece.cpp b/src/Piece.cpp
deleted file mode 100644
index 68ec406..0000000
--- a/src/Piece.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-#include "Piece.h"
-#include <iostream>
-#include <string>
-using namespace std;
-
-// constructor  
-Piece::Piece()
-{
-    type = " ";
-}
-
-// destructor
-Piece::~Piece()
-{
-}
-
-void Piece::draw() const
-{
-    if (color == PieceColor::BLACK)
-    {
-        cout << "B";
-    }
-    else
-    {
-        cout << "W";
-    }
-    cout << type;
-}
-
-void Piece::setPosition(Position pos)
-{
-    this->pos = pos;
-}
-
-PieceColor Piece::getColor()
-{
-    return color;
-}
\ No newline at end of file
diff --git a/src/Piece.h b/src/Piece.h
deleted file mode 100644
index 06af0ff..0000000
--- a/src/Piece.h
+++ /dev/null
@@ -1,75 +0,0 @@
-#ifndef _PIECE_H_
-#define _PIECE_H_
-#include <string>
-
-/**
- * @enum PieceColor
- * @brief Enum class representing the color of a chess piece.
- */
-enum class PieceColor
-{
-    WHITE, ///< White color
-    BLACK  ///< Black color
-};
-
-struct Position
-{
-    int x; ///< The x-coordinate of the position
-    int y; ///< The y-coordinate of the position
-};
-
-
-/**
- * @class Piece
- * @brief Class representing a chess piece.
- */
-class Piece 
-{
-    protected:
-        std::string type;   ///< The type of the piece
-        PieceColor color; ///< The color of the piece
-        Position pos;     ///< The position of the piece on the board
-    public:
-       /**
-        * @brief Default constructor for Piece class.
-        */
-       Piece();
-       
-       /**
-        * @brief Destructor for Piece class.
-        */
-       ~Piece();
-       
-       /**
-        * @brief Draws the piece on the board.
-        */
-       void draw() const;
-       
-       /**
-        * @brief Sets the position of the piece on the board.
-        * @param pos The new position of the piece.
-        */
-       void setPosition(Position pos);
-       
-        /**
-        * @brief Get the Position object
-        * 
-        * @return Position 
-        */
-        Position getPosition();
-
-       /**
-        * @brief Gets the color of the piece.
-        * @return The color of the piece.
-        */
-       PieceColor getColor();
-       
-       /**
-        * @brief Checks if a move to a new position is valid for the piece.
-        * @param newPos The new position to move to.
-        * @return True if the move is valid, false otherwise.
-        */
-       virtual bool isValidMove(Position newPos) = 0;
-};
-
-#endif
\ No newline at end of file
diff --git a/src/Rook.cpp b/src/Rook.cpp
deleted file mode 100644
index c216f3c..0000000
--- a/src/Rook.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-#include "Rook.h"
-#include <iostream>
-using namespace std;
-
-Rook::Rook(PieceColor color, Position pos)
-{
-    this->color = color;
-    this->pos = pos;
-    this->type = "R";
-}
-
-Rook::~Rook()
-{
-}
-
diff --git a/src/Rook.h b/src/Rook.h
deleted file mode 100644
index 3bcb289..0000000
--- a/src/Rook.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef _ROOK_H
-#define _ROOK_H
-#include "Piece.h"
-
-class Rook : public Piece
-{
-    public:
-        /**
-         * @brief Default constructor for Rook class.
-         */
-        Rook(PieceColor color, Position pos);
-        
-        /**
-         * @brief Destructor for Rook class.
-         */
-        ~Rook();
-        bool isValidMove(Position newPos);
-};
-
-#endif
\ No newline at end of file
diff --git a/src/Square.cpp b/src/Square.cpp
deleted file mode 100644
index baa7650..0000000
--- a/src/Square.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-#include "Square.h"
-#include "Piece.h"
-
-Square::Square(int x, int y)
-{   
-    x = x;
-    y = y;
-    piece = nullptr;
-}
-
-Square::~Square()
-{
-}
-
-void Square::setPieceOccupying(Piece* piece)
-{
-    piece = piece;
-}
-
-int Square::getX() const
-{
-    return x;
-}
-
-int Square::getY() const
-{
-    return y;
-}
-
-bool Square::occupied() const
-{
-    return piece != nullptr;
-}
-
-Piece* Square::getPieceOccupying() const
-{
-    return piece;
-}
\ No newline at end of file
diff --git a/src/Square.h b/src/Square.h
deleted file mode 100644
index a729826..0000000
--- a/src/Square.h
+++ /dev/null
@@ -1,66 +0,0 @@
-#ifndef _SQUARE_H
-#define _SQUARE_H
-
-class Piece;
-
-/**
- * @class Square
- * @brief Represents a square on a chessboard.
- */
-class Square
-{
-    private:
-        int x; /**< The x-coordinate of the square. */
-        int y; /**< The y-coordinate of the square. */
-        Piece* piece; /**< The piece occupying the square. */
-
-    public:
-        /**
-         * @brief Constructs a Square object with the given coordinates.
-         * @param x The x-coordinate of the square.
-         * @param y The y-coordinate of the square.
-         */
-        Square(int x, int y);
-
-        /**
-         * @brief Constructs a Square object with default coordinates (0, 0).
-         */
-        Square();
-
-        /**
-         * @brief Destroys the Square object.
-         */
-        ~Square();
-
-        /**
-         * @brief Sets the piece occupying the square.
-         * @param piece A pointer to the Piece object.
-         */
-        void setPieceOccupying(Piece* piece);
-
-        /**
-         * @brief Gets the x-coordinate of the square.
-         * @return The x-coordinate.
-         */
-        int getX() const;
-
-        /**
-         * @brief Gets the y-coordinate of the square.
-         * @return The y-coordinate.
-         */
-        int getY() const;
-
-        /**
-         * @brief Checks if the square is occupied by a piece.
-         * @return True if the square is occupied, false otherwise.
-         */
-        bool occupied() const;
-
-        /**
-         * @brief Gets the piece occupying the square.
-         * @return A pointer to the Piece object.
-         */
-        Piece* getPieceOccupying() const;
-};
-
-#endif
\ No newline at end of file
diff --git a/src/includes.h b/src/includes.h
new file mode 100644
index 0000000..7e4bd4d
--- /dev/null
+++ b/src/includes.h
@@ -0,0 +1,14 @@
+#ifndef _INCLUDES_H
+#define _INCLUDES_H
+#include <stdio.h>
+#include <iostream>
+#include <iomanip>
+#include <string>
+#include <deque>
+#include <vector>
+#include <fstream>
+#include <chrono>
+
+#include <string>
+using namespace std;
+#endif
\ No newline at end of file
diff --git a/src/user_interface.cpp b/src/user_interface.cpp
new file mode 100644
index 0000000..df1ea90
--- /dev/null
+++ b/src/user_interface.cpp
@@ -0,0 +1,50 @@
+#include "user_interface.h"
+#include "Game.h"
+void clearScreen(void)
+{
+    system("cls");
+}
+
+void printMenu(void)
+{
+    cout << "Commands: (N)ew game, (M)ove, (Q)uit" << endl;
+}
+
+void printMessage(string msg)
+{
+    cout << msg << endl;
+}
+
+void printLine(int iLine, int iColor1, int iColor2, Game& game)
+{
+    int CELL = 6;
+    for(int subLine = 0; subLine < CELL/2; subLine++)
+    {
+        for (int iPair = 0; iPair < 4; iPair++)
+        {
+            for (int subColumn = 0; subColumn < CELL; subColumn++)
+            {
+                if (subLine == 1 && subColumn == 3)
+                {
+                    cout << char(game.getPieceAtPosition(iLine, iPair*2) != 0x20 ? game.getPieceAtPosition(iLine, iPair*2) : iColor1);
+                }
+                else cout << char(iColor1);
+            }
+            for (int subColumn = 0; subColumn < CELL; subColumn++)
+            {
+                if (subLine == 1 && subColumn == 3)
+                {
+                    cout << char(game.getPieceAtPosition(iLine, iPair*2+1) != 0x20 ? game.getPieceAtPosition(iLine, iPair*2+1) : iColor2);
+                }
+                else cout << char(iColor2);
+            }
+        }
+        if ( 1 == subLine )
+        {
+            cout << "   " << iLine+1;
+        }
+        cout << "\n";
+
+    }
+    
+}
\ No newline at end of file
diff --git a/src/user_interface.h b/src/user_interface.h
new file mode 100644
index 0000000..5e43bd4
--- /dev/null
+++ b/src/user_interface.h
@@ -0,0 +1,18 @@
+#ifndef _USER_INTERFACE_H_
+#define _USER_INTERFACE_H_
+#include "Chess.h"
+
+#define WHITE_SQUARE 0xDB
+#define BLACK_SQUARE 0xFF
+#define EMPTY_SQUARE 0x20
+
+void createNextMessage( string msg );
+void appendToNextMessage( string msg );
+void clearScreen( void );;
+void printMenu( void );
+void printMessage( string msg );
+void printLine( int iLine, int iColor1, int iColor2, Game& game );
+void printSituation( Game& game );
+void printBoard(Game& game);
+
+#endif
\ No newline at end of file
-- 
GitLab