Commit f6c221a4 by WangChenxi

Add games

parents
File added
File added
#include <assert.h>
#include "CBoard.h"
// Create nice colours in the console output
#define TTY_YELLOW ""
#define TTY_BLUE ""
#define TTY_NORM ""
/***************************************************************
* operator <<
* This displays the current board configuration on the stream.
***************************************************************/
std::ostream& operator <<(std::ostream &os, const CBoard &rhs)
{
static const char pieces[] = "kqrbnp.PNBRQK";
for (int row=8; row>=1; --row)
{
os << TTY_NORM << row << " ";
for (int col=1; col<=8; ++col)
{
int number = (row+1)*10+col;
int piece = rhs.m_board[number];
if (piece != IV)
{
if (piece < 0)
os << TTY_BLUE;
else if (piece > 0)
os << TTY_YELLOW;
else
os << TTY_NORM;
os << pieces[piece+6] << " ";
}
}
os << std::endl;
}
os << TTY_NORM;
os << " a b c d e f g h" << std::endl;
switch (rhs.m_side_to_move)
{
case 1 : os << "White to move" << std::endl; break;
case -1 : os << "Black to move" << std::endl; break;
}
os << std::endl;
os << "Material : " << rhs.m_material << std::endl;
if (rhs.isKingInCheck())
{
os << "You are in check!" << std::endl;
}
return os;
} // end of std::ostream& operator <<(std::ostream &os, const CBoard &rhs)
/***************************************************************
* newGame
* This resets the board configuration to the initial game setup
***************************************************************/
void CBoard::newGame()
{
e_piece initial[120] = {
IV, IV, IV, IV, IV, IV, IV, IV, IV, IV,
IV, IV, IV, IV, IV, IV, IV, IV, IV, IV,
IV, WR, WN, WB, WQ, WK, WB, WN, WR, IV,
IV, WP, WP, WP, WP, WP, WP, WP, WP, IV,
IV, EM, EM, EM, EM, EM, EM, EM, EM, IV,
IV, EM, EM, EM, EM, EM, EM, EM, EM, IV,
IV, EM, EM, EM, EM, EM, EM, EM, EM, IV,
IV, EM, EM, EM, EM, EM, EM, EM, EM, IV,
IV, BP, BP, BP, BP, BP, BP, BP, BP, IV,
IV, BR, BN, BB, BQ, BK, BB, BN, BR, IV,
IV, IV, IV, IV, IV, IV, IV, IV, IV, IV,
IV, IV, IV, IV, IV, IV, IV, IV, IV, IV} ;
m_board.reserve(120);
for (int i=0; i<120; ++i)
{
m_board[i] = initial[i];
}
m_side_to_move = 1;
m_material = 0;
} // end of newGame
/***************************************************************
* isSquareThreatened
* Returns true if OTHER side to move threatens this square
***************************************************************/
bool CBoard::isSquareThreatened(const CSquare& sq) const
{
if (m_side_to_move > 0)
{
// Check for pawns
if (m_board[sq + NW] == BP || m_board[sq + NE] == BP)
return true;
// Check for knigts
{
int dirs[8] = {NNW, NNE, NWW, NEE, SSW, SSE, SWW, SEE};
for (int k=0; k<8; ++k)
{
int dir = dirs[k];
if (m_board[sq + dir] == BN)
return true;
}
}
// Check for diagonal (bishop and queen)
{
int dirs[4] = {NW, NE, SW, SE};
for (int k=0; k<4; ++k)
{
int dir = dirs[k];
int sq2 = sq;
while (1)
{
sq2 += dir;
if (m_board[sq2] == BB || m_board[sq2] == BQ)
return true;
if (m_board[sq2] != EM)
break;
}
}
}
// Check for horizontal/vertical (rook and queen)
{
int dirs[4] = {N, S, W, E};
for (int k=0; k<4; ++k)
{
int dir = dirs[k];
int sq2 = sq;
while (1)
{
sq2 += dir;
if (m_board[sq2] == BR || m_board[sq2] == BQ)
return true;
if (m_board[sq2] != EM)
break;
}
}
}
// Check for king
{
int dirs[8] = {NW, NE, SW, SE, N, S, W, E};
for (int k=0; k<8; ++k)
{
int dir = dirs[k];
if (m_board[sq + dir] == BK)
return true;
}
}
}
else
{
// Check for pawns
if (m_board[sq + SW] == WP || m_board[sq + SE] == WP)
return true;
// Check for knigts
{
int dirs[8] = {NNW, NNE, NWW, NEE, SSW, SSE, SWW, SEE};
for (int k=0; k<8; ++k)
{
int dir = dirs[k];
if (m_board[sq + dir] == WN)
return true;
}
}
// Check for diagonal (bishop and queen)
{
int dirs[4] = {NW, NE, SW, SE};
for (int k=0; k<4; ++k)
{
int dir = dirs[k];
int sq2 = sq;
while (1)
{
sq2 += dir;
if (m_board[sq2] == WB || m_board[sq2] == WQ)
return true;
if (m_board[sq2] != EM)
break;
}
}
}
// Check for horizontal/vertical (rook and queen)
{
int dirs[4] = {N, S, W, E};
for (int k=0; k<4; ++k)
{
int dir = dirs[k];
int sq2 = sq;
while (1)
{
sq2 += dir;
if (m_board[sq2] == WR || m_board[sq2] == WQ)
return true;
if (m_board[sq2] != EM)
break;
}
}
}
// Check for king
{
int dirs[8] = {NW, NE, SW, SE, N, S, W, E};
for (int k=0; k<8; ++k)
{
int dir = dirs[k];
if (m_board[sq + dir] == WK)
return true;
}
}
}
return false;
} // end of isSquareThreatened
/***************************************************************
* find_legal_moves
* This generates a complete list of all pseudo-legal moves.
* A pseudo-legal move does not consider, whether the king will
* be in check. This is handled else-where.
***************************************************************/
void CBoard::find_legal_moves(CMoveList &moves) const
{
moves.clear();
if (m_side_to_move > 0)
for (int i=A1; i<=H8; ++i)
{
int8_t piece = m_board[i];
int j;
switch (piece)
{
case WP : // White pawn
j = i + 10; // One square forward
if (m_board[j] == EM)
{
if (i > 80) // Check for promotion
{
{
CMove move(piece, i, j, EM, WQ);
moves.push_back(move);
}
{
CMove move(piece, i, j, EM, WR);
moves.push_back(move);
}
{
CMove move(piece, i, j, EM, WB);
moves.push_back(move);
}
{
CMove move(piece, i, j, EM, WN);
moves.push_back(move);
}
}
else // regular pawn move
{
CMove move(piece, i, j, EM);
moves.push_back(move);
}
j = i + 20; // Two squares forward
if (m_board[j] == EM)
{
if (i < 40) // Only from second rank
{
CMove move(piece, i, j, EM);
moves.push_back(move);
}
}
}
j = i + 9; // Diagonal capture
if ((m_board[j] != IV && m_board[j] < 0))
{
if (i > 80) // Check for promotion
{
{
CMove move(piece, i, j, m_board[j], WQ);
moves.push_back(move);
}
{
CMove move(piece, i, j, m_board[j], WR);
moves.push_back(move);
}
{
CMove move(piece, i, j, m_board[j], WB);
moves.push_back(move);
}
{
CMove move(piece, i, j, m_board[j], WN);
moves.push_back(move);
}
}
else
{
CMove move(piece, i, j, m_board[j]);
moves.push_back(move);
}
}
j = i + 11; // Diagonal capture
if ((m_board[j] != IV && m_board[j] < 0))
{
if (i > 80) // Check for promotion
{
{
CMove move(piece, i, j, m_board[j], WQ);
moves.push_back(move);
}
{
CMove move(piece, i, j, m_board[j], WR);
moves.push_back(move);
}
{
CMove move(piece, i, j, m_board[j], WB);
moves.push_back(move);
}
{
CMove move(piece, i, j, m_board[j], WN);
moves.push_back(move);
}
}
else
{
CMove move(piece, i, j, m_board[j]);
moves.push_back(move);
}
}
break;
case WN : // White knight
{
int dirs[8] = {NNW, NNE, NWW, NEE, SSW, SSE, SWW, SEE};
for (int k=0; k<8; ++k)
{
int dir = dirs[k];
j = i+dir;
if (m_board[j] != IV)
if (m_board[j] <= 0)
{
CMove move(piece, i, j, m_board[j]);
moves.push_back(move);
}
}
}
break;
case WB : // White bishop
{
int dirs[4] = {NE, NW, SE, SW};
for (int k=0; k<4; ++k)
{
int dir = dirs[k];
j = i;
while (1)
{
j += dir;
if (m_board[j] == IV) break;
if (m_board[j] <= 0)
{
CMove move(piece, i, j, m_board[j]);
moves.push_back(move);
if (m_board[j] < 0)
break;
}
else
break;
}
}
}
break;
case WR : // White rook
{
int dirs[4] = {N, E, S, W};
for (int k=0; k<4; ++k)
{
int dir = dirs[k];
j = i;
while (1)
{
j += dir;
if (m_board[j] == IV) break;
if (m_board[j] <= 0)
{
CMove move(piece, i, j, m_board[j]);
moves.push_back(move);
if (m_board[j] < 0)
break;
}
else
break;
}
}
}
break;
case WQ : // White queen
{
int dirs[8] = {NE, NW, SE, SW, N, E, S, W};
for (int k=0; k<8; ++k)
{
int dir = dirs[k];
j = i;
while (1)
{
j += dir;
if (m_board[j] == IV) break;
if (m_board[j] <= 0)
{
CMove move(piece, i, j, m_board[j]);
moves.push_back(move);
if (m_board[j] < 0)
break;
}
else
break;
}
}
}
break;
case WK : // White king
{
int dirs[8] = {NE, NW, SE, SW, N, E, S, W};
for (int k=0; k<8; ++k)
{
int dir = dirs[k];
j = i+dir;
if (m_board[j] != IV)
if (m_board[j] <= 0)
{
CMove move(piece, i, j, m_board[j]);
moves.push_back(move);
}
}
}
break;
default : // Invalid, wrong color, or empty
continue;
}
}
else
for (int i=A1; i<=H8; ++i)
{
int8_t piece = m_board[i];
int j;
switch (piece)
{
case BP : // Black pawn
j = i - 10; // One squre forward
if (m_board[j] == EM)
{
if (i < 40) // Check for promotion
{
{
CMove move(piece, i, j, EM, BQ);
moves.push_back(move);
}
{
CMove move(piece, i, j, EM, BR);
moves.push_back(move);
}
{
CMove move(piece, i, j, EM, BB);
moves.push_back(move);
}
{
CMove move(piece, i, j, EM, BN);
moves.push_back(move);
}
}
else // Regular pawn move
{
CMove move(piece, i, j, EM);
moves.push_back(move);
}
j = i - 20; // Two squares forward
if (m_board[j] == EM)
{
if (i > 80) // Only from seventh rank
{
CMove move(piece, i, j, EM);
moves.push_back(move);
}
}
}
j = i - 9; // Diagonal capture
if ((m_board[j] != IV && m_board[j] > 0))
{
if (i < 40) // Check for promotion
{
{
CMove move(piece, i, j, m_board[j], BQ);
moves.push_back(move);
}
{
CMove move(piece, i, j, m_board[j], BR);
moves.push_back(move);
}
{
CMove move(piece, i, j, m_board[j], BB);
moves.push_back(move);
}
{
CMove move(piece, i, j, m_board[j], BN);
moves.push_back(move);
}
}
else
{
CMove move(piece, i, j, m_board[j]);
moves.push_back(move);
}
}
j = i - 11; // Diagonal capture
if ((m_board[j] != IV && m_board[j] > 0))
{
if (i < 40) // Check for promotion
{
{
CMove move(piece, i, j, m_board[j], BQ);
moves.push_back(move);
}
{
CMove move(piece, i, j, m_board[j], BR);
moves.push_back(move);
}
{
CMove move(piece, i, j, m_board[j], BB);
moves.push_back(move);
}
{
CMove move(piece, i, j, m_board[j], BN);
moves.push_back(move);
}
}
else
{
CMove move(piece, i, j, m_board[j]);
moves.push_back(move);
}
}
break;
case BN : // Black knight
{
int dirs[8] = {NNW, NNE, NWW, NEE, SSW, SSE, SWW, SEE};
for (int k=0; k<8; ++k)
{
int dir = dirs[k];
j = i+dir;
if (m_board[j] != IV)
if (m_board[j] >= 0)
{
CMove move(piece, i, j, m_board[j]);
moves.push_back(move);
}
}
}
break;
case BB : // Black bishop
{
int dirs[4] = {NE, NW, SE, SW};
for (int k=0; k<4; ++k)
{
int dir = dirs[k];
j = i;
while (1)
{
j += dir;
if (m_board[j] == IV) break;
if (m_board[j] >= 0)
{
CMove move(piece, i, j, m_board[j]);
moves.push_back(move);
if (m_board[j] > 0)
break;
}
else
break;
}
}
}
break;
case BR : // Black rook
{
int dirs[4] = {N, E, S, W};
for (int k=0; k<4; ++k)
{
int dir = dirs[k];
j = i;
while (1)
{
j += dir;
if (m_board[j] == IV) break;
if (m_board[j] >= 0)
{
CMove move(piece, i, j, m_board[j]);
moves.push_back(move);
if (m_board[j] > 0)
break;
}
else
break;
}
}
}
break;
case BQ : // Black queen
{
int dirs[8] = {NE, NW, SE, SW, N, E, S, W};
for (int k=0; k<8; ++k)
{
int dir = dirs[k];
j = i;
while (1)
{
j += dir;
if (m_board[j] == IV) break;
if (m_board[j] >= 0)
{
CMove move(piece, i, j, m_board[j]);
moves.push_back(move);
if (m_board[j] > 0)
break;
}
else
break;
}
}
}
break;
case BK : // Black king
{
int dirs[8] = {NE, NW, SE, SW, N, E, S, W};
for (int k=0; k<8; ++k)
{
int dir = dirs[k];
j = i+dir;
if (m_board[j] != IV)
if (m_board[j] >= 0)
{
CMove move(piece, i, j, m_board[j]);
moves.push_back(move);
}
}
}
break;
default : // Invalid, wrong color, or empty
continue;
}
}
} // end of void CBoard::find_legal_moves(CMoveList &moves) const;
/***************************************************************
* make_move
* This updates the board according to the move
***************************************************************/
void CBoard::make_move(const CMove &move)
{
switch (move.m_captured)
{
case WP : case BP : m_material += 1; break;
case WN : case BN : m_material += 3; break;
case WB : case BB : m_material += 3; break;
case WR : case BR : m_material += 5; break;
case WQ : case BQ : m_material += 9; break;
default : break;
}
switch (move.m_promoted)
{
case WN : case BN : m_material += 3-1; break;
case WB : case BB : m_material += 3-1; break;
case WR : case BR : m_material += 5-1; break;
case WQ : case BQ : m_material += 9-1; break;
default : break;
}
m_board[move.m_to] = m_board[move.m_from];
if (move.m_promoted != EM)
m_board[move.m_to] = move.m_promoted;
m_board[move.m_from] = EM;
m_side_to_move = -m_side_to_move;
m_material = -m_material;
} // end of void CBoard::make_move(const CMove &move)
/***************************************************************
* undo_move
* This reverses the effect of make_move
***************************************************************/
void CBoard::undo_move(const CMove &move)
{
m_material = -m_material;
switch (move.m_captured)
{
case WP : case BP : m_material -= 1; break;
case WN : case BN : m_material -= 3; break;
case WB : case BB : m_material -= 3; break;
case WR : case BR : m_material -= 5; break;
case WQ : case BQ : m_material -= 9; break;
default : break;
}
switch (move.m_promoted)
{
case WN : case BN : m_material -= 3-1; break;
case WB : case BB : m_material -= 3-1; break;
case WR : case BR : m_material -= 5-1; break;
case WQ : case BQ : m_material -= 9-1; break;
default : break;
}
m_board[move.m_from] = move.m_piece;
m_board[move.m_to] = move.m_captured;
m_side_to_move = -m_side_to_move;
} // end of void CBoard::undo_move(const CMove &move)
/***************************************************************
* IsMoveValid
* This returns true, if the move is legal.
***************************************************************/
bool CBoard::IsMoveValid(CMove &move) const
{
CMoveList moves;
find_legal_moves(moves);
for (unsigned int i=0; i<moves.size(); ++i)
{
if (moves[i] == move)
{
move.m_piece = m_board[move.m_from];
move.m_captured = m_board[move.m_to];
return true;
}
}
return false;
} // end of bool CBoard::IsMoveValid(CMove &move)
/***************************************************************
* get_value
*
* It returns an integer value showing how good the position
* is for the side to move.
*
* This is a very simple evaluation function. Only two factors are
* considered:
* 1. The material balance:
* * Pawn 100
* * Knight 300
* * Bishop 300
* * Rook 500
* * Queen 900
* 2. The difference in number of legal moves of both players.
*
* The latter tends to favor positions, where the computer
* has many legal moves. This implies centralization and development.
***************************************************************/
int CBoard::get_value()
{
CMoveList moves;
find_legal_moves(moves);
int my_moves = moves.size();
swap_sides();
find_legal_moves(moves);
int his_moves = moves.size();
swap_sides();
return (my_moves-his_moves) + 100*m_material;
} // end of int CBoard::get_value()
/***************************************************************
* Returns true if player to move is in check.
***************************************************************/
bool CBoard::isKingInCheck() const
{
e_piece king;
CSquare kingSquare = 0;
if (m_side_to_move == 1)
king = WK;
else
king = BK;
// Look for our king
for (int i=A1; i<=H8; ++i)
{
if (m_board[i] == king)
{
kingSquare = i;
break;
}
}
/*if(kingSquare == 0){
if(m_side_to_move == 1){
std::cout << "BLACK WIN!" << std::endl;
}else{
std::cout << "WHITE WIN!" << std::endl;
}
}*/
//assert (kingSquare != 0); // The king MUST be somewhere
return isSquareThreatened(kingSquare);
} // end of isKingInCheck
/***************************************************************
* Returns true if player NOT to move is in check.
***************************************************************/
bool CBoard::isOtherKingInCheck() const
{
((CBoard *)this)->m_side_to_move = -m_side_to_move;
bool retval = isKingInCheck();
((CBoard *)this)->m_side_to_move = -m_side_to_move;
return retval;
} // end of isOtherKingInCheck
/***************************************************************
* Returns true if Game Over
***************************************************************/
int CBoard::isGameOver() const
{
e_piece king;
CSquare kingSquare = 0;
int over = 0;
if (m_side_to_move == 1)
king = WK;
else
king = BK;
// Look for our king
for (int i=A1; i<=H8; ++i)
{
if (m_board[i] == king)
{
kingSquare = i;
break;
}
}
if(kingSquare == 0){
if(m_side_to_move == 1){
over = 1;//BLACK WIN!
}else{
over = 2;//WHITE WIN!
//std::cout << "WHITE WIN!" << std::endl;
}
}
//assert (kingSquare != 0); // The king MUST be somewhere
return over;
} // end of isGameOver
CBoard.o CBoard.d : CBoard.cc \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/assert.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/cdefs.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_symbol_aliasing.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_posix_availability.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/stdlib.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__config \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/pthread.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/stdlib.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/Availability.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/AvailabilityVersions.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/AvailabilityInternal.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/machine/_types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/_types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/wait.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_pid_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_id_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/signal.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/appleapiopts.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/machine/signal.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/signal.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/machine/_mcontext.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/_mcontext.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/mach/machine/_structs.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/mach/i386/_structs.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/machine/types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_int8_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_int16_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_int32_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_int64_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_u_int8_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_u_int16_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_u_int32_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_u_int64_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_intptr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_uintptr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_attr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_sigaltstack.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_ucontext.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_sigset_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_size_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_uid_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/resource.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/stdint.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/12.0.0/include/stdint.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/stdint.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_uint8_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_uint16_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_uint32_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_uint64_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_intmax_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_uintmax_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_timeval.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/machine/endian.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/endian.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_endian.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/libkern/_OSByteOrder.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/libkern/i386/_OSByteOrder.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/alloca.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_ct_rune_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_rune_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_wchar_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_null.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/malloc/_malloc.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_dev_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_mode_t.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/math.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/math.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/type_traits \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cstddef \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__cxx_version \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/12.0.0/include/stddef.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__nullptr \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/limits \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__undef_macros \
CBoard.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/iosfwd \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/wchar.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/wchar.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_mbstate_t.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/12.0.0/include/stdarg.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/stdio.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/stdio.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_stdio.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_va_list.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/stdio.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_ctermid.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_off_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_ssize_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/time.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_clock_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_time_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_timespec.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_wctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/__wctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_wint_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_wctype_t.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/ctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/ctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_ctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/runetype.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__bit_reference \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/bit \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__debug \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/algorithm \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/initializer_list \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cstring \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/string.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/string.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_rsize_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_errno_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/strings.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/utility \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__tuple \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cstdint \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/typeinfo \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/exception \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cstdlib \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/new \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/iterator \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__functional_base \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__functional_base_03 \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/tuple \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/stdexcept \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/atomic \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cassert \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/functional \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__functional_03 \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/climits \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/limits.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/12.0.0/include/limits.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/limits.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/machine/limits.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/limits.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/_limits.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/syslimits.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__split_buffer \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/string \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/string_view \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__string \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cstdio \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cwchar \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cwctype \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cctype \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/wctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/wctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_wctrans_t.h \
CMove.h CSquare.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/iostream \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/ios \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__locale \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/mutex \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__mutex_base \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/chrono \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/ctime \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/ratio \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/system_error \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__errc \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cerrno \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/errno.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/errno.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/errno.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__threading_support \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/pthread/sched.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/pthread/pthread_impl.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_cond_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_condattr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_key_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_mutex_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_mutexattr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_once_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_rwlock_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_rwlockattr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/pthread/qos.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/qos.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_mach_port_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sched.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/locale.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/locale.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_locale.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_xlocale.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/_ctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/__wctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/_stdio.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/_stdlib.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/_string.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/_time.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/_wchar.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/stddef.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/_wctype.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/streambuf \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/istream \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/ostream \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/locale \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/nl_types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_u_char.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_u_short.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_u_int.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_caddr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_blkcnt_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_blksize_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_gid_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_in_addr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_in_port_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_ino_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_ino64_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_key_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_nlink_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_useconds_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_suseconds_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fd_def.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fd_setsize.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fd_set.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fd_clr.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fd_zero.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fd_isset.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fd_copy.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fsblkcnt_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fsfilcnt_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_nl_item.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__bsd_locale_defaults.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/bitset \
CMoveList.h
#include <vector>
#include <string>
#include "CMove.h"
#include "CMoveList.h"
#ifndef _C_BOARD_H_
#define _C_BOARD_H_
// The board is represented as an array of 120 elements.
// arranged in 12 rows and 10 columns.
// The following diagram shows the numbering of the elements.
// Note: The square A1 is element number 21
//
// 110 111 112 113 114 115 116 117 118 119
// 100 101 102 103 104 105 106 107 108 109
// 90 A1 92 93 94 95 96 97 H8 99
// 80 81 82 83 84 85 86 87 88 89
// 70 71 72 73 74 75 76 77 78 79
// 60 61 62 63 64 65 66 67 68 69
// 50 51 52 53 54 55 56 57 58 59
// 40 41 42 43 44 45 46 47 48 49
// 30 31 32 33 34 35 36 37 H2 39
// 20 A1 22 23 24 25 26 27 H1 29
// 10 11 12 13 14 15 16 17 18 19
// 0 1 2 3 4 5 6 7 8 9
//
// Each element contains one of the following values:
// 0 : Empty
// 1 : White Pawn
// 2 : White Knight
// 3 : White Bishop
// 4 : White Rook
// 5 : White Queen
// 6 : White King
// -1 : Black Pawn
// -2 : Black Knight
// -3 : Black Bishop
// -4 : Black Rook
// -5 : Black Queen
// -6 : Black King
// 99 : INVALID
enum // Directions
{
N = 10, S = -10, E = -1, W = 1,
NW = 11, SW = -9, NE = 9, SE = -11,
NNW = 21, NNE = 19, NWW = 12, NEE = 8,
SSW = -19, SSE = -21, SWW = -8, SEE = -12
};
/***************************************************************
* declaration of CBoard
***************************************************************/
class CBoard
{
public:
CBoard() { newGame(); }
// Copy constructor
CBoard(const CBoard& rhs);
void newGame();
void find_legal_moves(CMoveList &moves) const;
void make_move(const CMove &move);
void undo_move(const CMove &move);
int get_value();
bool IsMoveValid(CMove &move) const;
bool isKingInCheck() const;
int isGameOver() const;//add
bool isOtherKingInCheck() const;
friend std::ostream& operator <<(std::ostream &os, const CBoard &rhs);
private:
bool isSquareThreatened(const CSquare& sq) const;
void swap_sides() {m_side_to_move = -m_side_to_move;}
std::vector<int8_t> m_board;
int m_side_to_move;
int m_material;
}; // end of class CBoard
#endif // _C_BOARD_H_
File added
#include <sstream>
#include <assert.h>
#include "CMove.h"
std::ostream& operator <<(std::ostream &os, const CMove &rhs)
{
return os << rhs.ToShortString();
} // end of std::ostream& operator <<(std::ostream &os, const CMove &rhs)
static char pieces[] = "kqrbnp.PNBRQK";
std::string CMove::ToShortString() const
{
std::stringstream ss;
assert (m_captured != IV);
ss << m_from;
ss << m_to;
if (m_promoted != EM)
{
ss << (char) tolower(pieces[m_promoted+6]);
}
return ss.str();
}
std::string CMove::ToLongString() const
{
std::stringstream ss;
assert (m_captured != IV);
ss << pieces[m_piece+6];
ss << m_from;
if (m_captured != EM)
ss << "*";
else
ss << "-";
ss << m_to;
if (m_promoted != EM)
{
ss << "=";
ss << (char) tolower(pieces[m_promoted+6]);
}
return ss.str();
}
// Returns NULL if error
const char * CMove::FromString(const char *s)
{
if (m_from.FromString(s) || m_to.FromString(s+2))
return NULL;
s += 4;
m_piece = EM;
m_captured = EM;
m_promoted = EM;
if (m_to.row() == 1)
{
switch (tolower(s[0]))
{
case 'q' : m_promoted = BQ; s++; break;
case 'r' : m_promoted = BR; s++; break;
case 'b' : m_promoted = BB; s++; break;
case 'n' : m_promoted = BN; s++; break;
case ' ' : break;
case '\0': break;
default : return NULL;
}
}
else if (m_to.row() == 8)
{
switch (tolower(s[0]))
{
case 'q' : m_promoted = WQ; s++; break;
case 'r' : m_promoted = WR; s++; break;
case 'b' : m_promoted = WB; s++; break;
case 'n' : m_promoted = WN; s++; break;
case ' ' : break;
case '\0': break;
default : return NULL;
}
}
while (s[0] == ' ')
s++;
return s;
} /* end of FromString */
CMove.o CMove.d : CMove.cc \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/sstream \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__config \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/pthread.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/ostream \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/ios \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/iosfwd \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/wchar.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/wchar.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/cdefs.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_symbol_aliasing.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_posix_availability.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/machine/_types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/_types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/Availability.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/AvailabilityInternal.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_null.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_size_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_mbstate_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/machine/types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_int8_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_int16_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_int32_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_int64_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_u_int8_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_u_int16_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_u_int32_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_u_int64_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_intptr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_uintptr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_ct_rune_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_rune_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_wchar_t.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/12.0.0/include/stdarg.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/stdio.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/stdio.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_stdio.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_va_list.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/stdio.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_ctermid.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_off_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_ssize_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/time.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_clock_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_time_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_timespec.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_wctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/__wctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_wint_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_wctype_t.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/ctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/ctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_ctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/runetype.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__locale \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/string \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/string_view \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__string \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/algorithm \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/initializer_list \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cstddef \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__cxx_version \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/12.0.0/include/stddef.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__nullptr \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/type_traits \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cstring \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/string.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/string.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_rsize_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_errno_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/strings.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/utility \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__tuple \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cstdint \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/stdint.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/12.0.0/include/stdint.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/stdint.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_uint8_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_uint16_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_uint32_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_uint64_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_intmax_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_uintmax_t.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__debug \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/typeinfo \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/exception \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cstdlib \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/stdlib.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/stdlib.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/wait.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_pid_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_id_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/signal.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/appleapiopts.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/machine/signal.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/signal.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/machine/_mcontext.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/_mcontext.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/mach/machine/_structs.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/mach/i386/_structs.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_attr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_sigaltstack.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_ucontext.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_sigset_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_uid_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/resource.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_timeval.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/machine/endian.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/endian.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_endian.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/libkern/_OSByteOrder.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/libkern/i386/_OSByteOrder.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/alloca.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/malloc/_malloc.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_dev_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_mode_t.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/math.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/math.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/limits \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__undef_macros \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/new \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/iterator \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__functional_base \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__functional_base_03 \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/tuple \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/stdexcept \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/atomic \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cassert \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/assert.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/functional \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__functional_03 \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/bit \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cstdio \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cwchar \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cwctype \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cctype \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/wctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/wctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_wctrans_t.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/mutex \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__mutex_base \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/chrono \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/ctime \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/ratio \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/climits \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/limits.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/12.0.0/include/limits.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/limits.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/machine/limits.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/limits.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/_limits.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/syslimits.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/system_error \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__errc \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cerrno \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/errno.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/errno.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/errno.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__threading_support \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/pthread/pthread_impl.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/pthread/sched.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/pthread_impl.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_cond_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_condattr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_key_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_mutex_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_mutexattr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_once_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_rwlock_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_rwlockattr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/pthread/qos.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/qos.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_mach_port_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sched.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/locale.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/locale.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_locale.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_xlocale.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/_ctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/__wctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/_stdio.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/_stdlib.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/_string.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/_time.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/_wchar.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/_wctype.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/streambuf \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/locale \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/nl_types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_u_char.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_u_short.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_u_int.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_caddr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_blkcnt_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_blksize_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_gid_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_in_addr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_in_port_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_ino_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_ino64_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_key_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_nlink_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_useconds_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_suseconds_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fd_def.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fd_setsize.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fd_set.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fd_clr.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fd_zero.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fd_isset.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fd_copy.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fsblkcnt_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fsfilcnt_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_nl_item.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__bsd_locale_defaults.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/bitset \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__bit_reference \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/istream \
CMove.h CSquare.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/iostream
#ifndef _C_MOVE_H_
#define _C_MOVE_H_
#include "CSquare.h"
typedef enum {
EM = 0, // Empty
WP = 1, // White Pawn
WN = 2, // White Knight
WB = 3, // White Bishop
WR = 4, // White Rook
WQ = 5, // White Queen
WK = 6, // White King
BP = -1, // Black Pawn
BN = -2, // Black Knight
BB = -3, // Black Bishop
BR = -4, // Black Rook
BQ = -5, // Black Queen
BK = -6, // Black King
IV = 99 // INVALID
} e_piece;
/***************************************************************
* declaration of CMove
***************************************************************/
class CMove
{
public:
friend class CBoard;
friend std::ostream& operator <<(std::ostream &os, const CMove &rhs);
// Constructors
CMove() : m_piece(IV), m_captured(IV) {}
CMove(const char *str) : m_captured(IV) { FromString(str); }
CMove(int8_t piece, const CSquare& from, const CSquare& to, int8_t captured = EM, int8_t promoted=EM) :
m_from(from), m_to(to), m_piece(piece), m_captured(captured), m_promoted(promoted) {}
const char * FromString(const char *s); // Returns NULL if error
// Accessor functions
std::string ToShortString() const;
std::string ToLongString() const;
CSquare From(void) const {return m_from;}
CSquare To(void) const {return m_to;}
bool Valid(void) const { return m_captured != IV; }
bool is_captured_piece_a_king(void) const { return (m_captured == WK || m_captured == BK); }
bool is_it_a_capture(void) const { return (m_captured != EM); }
bool operator==(const CMove& rhs) const
{
if (rhs.From() != From())
return false;
if (rhs.To() != To())
return false;
return true;
}
private:
CSquare m_from;
CSquare m_to;
int8_t m_piece;
int8_t m_captured;
int8_t m_promoted;
}; /* end of CMove */
#endif // _C_MOVE_H_
File added
#include "CMoveList.h"
std::ostream& operator <<(std::ostream &os, const CMoveList &rhs)
{
for (std::vector<CMove>::const_iterator it = rhs.m_moveList.begin(); it != rhs.m_moveList.end(); ++it)
{
os << (*it).ToShortString() << " ";
}
return os;
} // end of std::ostream& operator <<(std::ostream &os, const CMoveList &rhs)
CMoveList.o CMoveList.d : CMoveList.cc CMoveList.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/iostream \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__config \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/pthread.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/ios \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/iosfwd \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/wchar.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/wchar.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/cdefs.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_symbol_aliasing.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_posix_availability.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/machine/_types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/_types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/Availability.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/AvailabilityInternal.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_null.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_size_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_mbstate_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/machine/types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_int8_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_int16_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_int32_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_int64_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_u_int8_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_u_int16_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_u_int32_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_u_int64_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_intptr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_uintptr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_ct_rune_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_rune_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_wchar_t.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/12.0.0/include/stdarg.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/stdio.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/stdio.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_stdio.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_va_list.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/stdio.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_ctermid.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_off_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_ssize_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/time.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_clock_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_time_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_timespec.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_wctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/__wctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_wint_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_wctype_t.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/ctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/ctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_ctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/runetype.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__locale \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/string \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/string_view \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__string \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/algorithm \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/initializer_list \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cstddef \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__cxx_version \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/12.0.0/include/stddef.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__nullptr \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/type_traits \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cstring \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/string.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/string.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_rsize_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_errno_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/strings.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/utility \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__tuple \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cstdint \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/stdint.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/12.0.0/include/stdint.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/stdint.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_uint8_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_uint16_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_uint32_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_uint64_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_intmax_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_uintmax_t.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__debug \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/typeinfo \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/exception \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cstdlib \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/stdlib.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/stdlib.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/wait.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_pid_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_id_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/signal.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/appleapiopts.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/machine/signal.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/signal.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/machine/_mcontext.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/_mcontext.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/mach/machine/_structs.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/mach/i386/_structs.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_attr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_sigaltstack.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_ucontext.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_sigset_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_uid_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/resource.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_timeval.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/machine/endian.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/endian.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_endian.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/libkern/_OSByteOrder.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/libkern/i386/_OSByteOrder.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/alloca.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/malloc/_malloc.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_dev_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_mode_t.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/math.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/math.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/limits \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__undef_macros \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/new \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/iterator \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__functional_base \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__functional_base_03 \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/tuple \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/stdexcept \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/atomic \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cassert \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/assert.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/functional \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__functional_03 \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/bit \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cstdio \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cwchar \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cwctype \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cctype \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/wctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/wctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_wctrans_t.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/mutex \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__mutex_base \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/chrono \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/ctime \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/ratio \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/climits \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/limits.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/12.0.0/include/limits.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/limits.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/machine/limits.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/limits.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/_limits.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/syslimits.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/system_error \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__errc \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cerrno \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/errno.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/errno.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/errno.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__threading_support \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/pthread/pthread_impl.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/pthread/sched.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/pthread_impl.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_cond_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_condattr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_key_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_mutex_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_mutexattr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_once_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_rwlock_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_rwlockattr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/pthread/qos.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/qos.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_mach_port_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sched.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/locale.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/locale.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_locale.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_xlocale.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/_ctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/__wctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/_stdio.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/_stdlib.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/_string.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/_time.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/_wchar.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/_wctype.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/streambuf \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/istream \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/ostream \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/locale \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/nl_types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_u_char.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_u_short.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_u_int.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_caddr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_blkcnt_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_blksize_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_gid_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_in_addr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_in_port_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_ino_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_ino64_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_key_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_nlink_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_useconds_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_suseconds_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fd_def.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fd_setsize.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fd_set.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fd_clr.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fd_zero.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fd_isset.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fd_copy.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fsblkcnt_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fsfilcnt_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_nl_item.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__bsd_locale_defaults.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/bitset \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__bit_reference \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__split_buffer \
CMove.h CSquare.h
#ifndef _C_MOVELIST_H_
#define _C_MOVELIST_H_
#include <iostream>
#include <vector>
#include "CMove.h"
/***************************************************************
* declaration of CMoveList
*
* This is a wrapper for the std::vector class.
* It contains an array of moves.
***************************************************************/
class CMoveList
{
public:
CMoveList()
{
// Pre-allocate space for a large number of moves.
// This is a slight optimization.
m_moveList.reserve(100);
}
friend std::ostream& operator <<(std::ostream &os, const CMoveList &rhs);
void push_back(const CMove& move)
{
m_moveList.push_back(move);
}
void clear()
{
m_moveList.clear();
}
unsigned int size() const
{
return m_moveList.size();
}
const CMove & operator [] (unsigned int ix) const { return m_moveList[ix]; }
private:
std::vector<CMove> m_moveList;
}; /* end of CMoveList */
#endif // _C_MOVELIST_H_
#ifndef _C_SQUARE_H_
#define _C_SQUARE_H_
#include <stdint.h>
#include <iostream>
// Useful enumerations to conveniently address specific squares on the board
enum // Squares
{
A8 = 91, B8, C8, D8, E8, F8, G8, H8,
A7 = 81, B7, C7, D7, E7, F7, G7, H7,
A6 = 71, B6, C6, D6, E6, F6, G6, H6,
A5 = 61, B5, C5, D5, E5, F5, G5, H5,
A4 = 51, B4, C4, D4, E4, F4, G4, H4,
A3 = 41, B3, C3, D3, E3, F3, G3, H3,
A2 = 31, B2, C2, D2, E2, F2, G2, H2,
A1 = 21, B1, C1, D1, E1, F1, G1, H1,
};
/***************************************************************
* declaration of CSquare
*
* This class encapsulates the notion of a square.
* This class converts between an internal (0 - 119)
* and a (column,row) representation.
***************************************************************/
class CSquare
{
public:
CSquare(uint32_t square = 0) :
m_sq(square) {}
operator int() const { return m_sq; } // Implicit conversion to integer
int row() const {return (m_sq/10) - 1;} // returns 1 - 8
int col() const {return (m_sq%10);} // returns 1 - 8
friend std::ostream& operator <<(std::ostream &os, const CSquare &rhs)
{
char c = (rhs.m_sq%10) + 'a' - 1;
char r = (rhs.m_sq/10) + '1' - 2;
return os << c << r;
}
int FromString(const char *s)
{
uint32_t col = s[0] - 'a';
uint32_t row = s[1] - '1';
m_sq = row*10 + col + 21;
return (col >= 8 || row >= 8);
// Returns true if error
}
private:
uint8_t m_sq; // Internal representation, 0 - 119.
}; /* end of class CSquare */
#endif // _C_SQUARE_H_
<!DOCTYPE html>
<html>
<head>
<title>mchess design documentation</title>
<style>
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
th, td {
padding: 5px;
text-align: right;
}
</style>
</head>
<body>
This document is a description of the design of <em>mchess</em> and
<em>mchess2</em>
<h1>Piece representation</h1>
The chess board consists of 64 squares. Each square may be empty or contain a
white or black piece. Each piece is given an integer value (this is not
related to the <em>worth</em> of the piece in number of pawns).
<p/>
This enumeration is called <em>e_piece</em> and is defined in the file
<em>CMove.h</em>:
<pre>
typedef enum {
EM = 0, // Empty
WP = 1, // White Pawn
WN = 2, // White Knight
WB = 3, // White Bishop
WR = 4, // White Rook
WQ = 5, // White Queen
WK = 6, // White King
BP = -1, // Black Pawn
BN = -2, // Black Knight
BB = -3, // Black Bishop
BR = -4, // Black Rook
BQ = -5, // Black Queen
BK = -6, // Black King
IV = 99 // INVALID
} e_piece;
</pre>
The above is merely an enumeration, and the actual numerical values are
arbitrary. However, I do in the following rely on the fact that:
<ul>
<li>The empty space has value zero</li>
<li>All white pieces have positive values</li>
<li>All black pieces have negative values</li>
</ul>
<p/>
Additionally, I have a special value for an <em>invalid</em> piece. This has
several uses, the foremost will be explained in the following.
<h1>Square representation</h1>
An important function in a chess engine is to be able to generate a list of all
legal moves in a given position. This function is used all the time, and
therefore must be as fast as possible.
<p/>
When writing such a function, one must first consider how to represent the
board configuration, i.e. where each piece is placed, or equivalently, which
piece is on a given square.
<p/>
I've chosen to represent the board as a simple
one-dimensional array of integers. Each index in the array corresponds to a
particular square, and each value in the array is the corresponding piece,
according to the enumeration above.
<p/>
When generating a list of legal moves, it is necessary to check if a piece is
about to move outside the edge of the board. For instance, a rook on H1 can not
move to the right.
<p/>
This is dealt with in a very smart way: The board is <em>enlarged</em>, so that
it is surrounded by two layers of invalid squares. This gives a total of 12
rows of ten squares each, i.e. 120 elements in the array.
<table>
<tr>
<td>110</td>
<td>111</td>
<td>112</td>
<td>113</td>
<td>114</td>
<td>115</td>
<td>116</td>
<td>117</td>
<td>118</td>
<td>119</td>
</tr>
<tr>
<td>100</td>
<td>101</td>
<td>102</td>
<td>103</td>
<td>104</td>
<td>105</td>
<td>106</td>
<td>107</td>
<td>108</td>
<td>109</td>
</tr>
<tr>
<td>90</td>
<td><b>A8</b></td>
<td><b>B8</b></td>
<td><b>C8</b></td>
<td><b>D8</b></td>
<td><b>E8</b></td>
<td><b>F8</b></td>
<td><b>G8</b></td>
<td><b>H8</b></td>
<td>99</td>
</tr>
<tr>
<td>80</td>
<td><b>A7</b></td>
<td><b>B7</b></td>
<td><b>C7</b></td>
<td><b>D7</b></td>
<td><b>E7</b></td>
<td><b>F7</b></td>
<td><b>G7</b></td>
<td><b>H7</b></td>
<td>89</td>
</tr>
<tr>
<td>70</td>
<td><b>A6</b></td>
<td><b>B6</b></td>
<td><b>C6</b></td>
<td><b>D6</b></td>
<td><b>E6</b></td>
<td><b>F6</b></td>
<td><b>G6</b></td>
<td><b>H6</b></td>
<td>79</td>
</tr>
<tr>
<td>60</td>
<td><b>A5</b></td>
<td><b>B5</b></td>
<td><b>C5</b></td>
<td><b>D5</b></td>
<td><b>E5</b></td>
<td><b>F5</b></td>
<td><b>G5</b></td>
<td><b>H5</b></td>
<td>69</td>
</tr>
<tr>
<td>50</td>
<td><b>A4</b></td>
<td><b>B4</b></td>
<td><b>C4</b></td>
<td><b>D4</b></td>
<td><b>E4</b></td>
<td><b>F4</b></td>
<td><b>G4</b></td>
<td><b>H4</b></td>
<td>59</td>
</tr>
<tr>
<td>40</td>
<td><b>A3</b></td>
<td><b>B3</b></td>
<td><b>C3</b></td>
<td><b>D3</b></td>
<td><b>E3</b></td>
<td><b>F3</b></td>
<td><b>G3</b></td>
<td><b>H3</b></td>
<td>49</td>
</tr>
<tr>
<td>30</td>
<td><b>A2</b></td>
<td><b>B2</b></td>
<td><b>C2</b></td>
<td><b>D2</b></td>
<td><b>E2</b></td>
<td><b>F2</b></td>
<td><b>G2</b></td>
<td><b>H2</b></td>
<td>39</td>
</tr>
<tr>
<td>20</td>
<td><b>A1</b></td>
<td><b>B1</b></td>
<td><b>C1</b></td>
<td><b>D1</b></td>
<td><b>E1</b></td>
<td><b>F1</b></td>
<td><b>G1</b></td>
<td><b>H1</b></td>
<td>29</td>
</tr>
<tr>
<td>10</td>
<td>11</td>
<td>12</td>
<td>13</td>
<td>14</td>
<td>15</td>
<td>16</td>
<td>17</td>
<td>18</td>
<td>19</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
</table>
<p/>
When testing whether a move is legal, it is enough to test if the target square
is empty or contains an enemy piece. It is not even necessary to exlicitly test
for invalid squares.
<p/>
An enumeration is used to define the index of each square. This enumeration is
defined in the file <em>CSquare.h</em>. This is purely for code readability,
i.e. if I refer to a square as E2 it is more readable, than using the integer
35.
<pre>
enum // Squares
{
A8 = 91, B8, C8, D8, E8, F8, G8, H8,
A7 = 81, B7, C7, D7, E7, F7, G7, H7,
A6 = 71, B6, C6, D6, E6, F6, G6, H6,
A5 = 61, B5, C5, D5, E5, F5, G5, H5,
A4 = 51, B4, C4, D4, E4, F4, G4, H4,
A3 = 41, B3, C3, D3, E3, F3, G3, H3,
A2 = 31, B2, C2, D2, E2, F2, G2, H2,
A1 = 21, B1, C1, D1, E1, F1, G1, H1,
};
</pre>
<h2>The CSquare class</h2>
It does become necessary to determine the row and/or column number of a given
square, for instance when checking for pawn promotion. Therefore I've chosen
to write a class <em>CSquare</em> to handle this. The following is the
essential ingredients:
<pre>
class CSquare
{
public:
int row() const {return (m_sq/10) - 1;} // returns 1 - 8
int col() const {return (m_sq%10);} // returns 1 - 8
operator int() const { return m_sq; } // Implicit conversion to integer
private:
uint8_t m_sq; // Internal representation, 0 - 119.
}; // end of class CSquare
</pre>
The conversion operator <em>int()</em> allows the CSquare class to be used
directly as an array index.
<h1>Move representation</h1>
The next to consider is how to represent a move. Obviously, we need an
originating square, and a target square. However, this is not quite enough.
When a pawn reaches the back rank, it may promote to any other piece, and this
must be given as well.
<h2>The CMove class</h2>
The class CMove is used to represent a single chess move. The essential
ingredients in this class are:
<pre>
class CMove
{
public:
CSquare From(void) const {return m_from;}
CSquare To(void) const {return m_to;}
private:
CSquare m_from;
CSquare m_to;
int8_t m_promoted; // This handles pawn promotion.
}; // end of CMove
</pre>
<p/>
Note the member variable <em>m_promoted</em>. This is only used during pawn
promotion, where it contains the piece that the pawn promotes to. In case of an
ordinary move, the variable is not used, and should be set to zero (empty).
<h2>Enhancements</h2>
This class contains two additional private member variables:
<pre>
int8_t m_piece;
int8_t m_captured;
</pre>
The first, <em>m_piece</em>, contains the current piece being moved, the second
variable, <em>m_captured</em>, contains the piece being captured, if any. They
are both used only for printing the current move to the user.
<h2>The CMoveList class</h2>
When generating a list of all the legal moves in a chess position, it becomes necessary to
manipulate lists of moves. I've found it convenient to write a separate class just for this:
<pre>
class CMoveList
{
public:
void clear()
{
m_moveList.clear();
}
void push_back(const CMove& move)
{
m_moveList.push_back(move);
}
unsigned int size() const
{
return m_moveList.size();
}
const CMove & operator [] (unsigned int ix) const { return m_moveList[ix]; }
private:
std::vector<CMove> m_moveList;
}; // end of CMoveList
</pre>
<p/>
The purpose of this class is just to encapsulate the semantics of an ordinary
array. Here I've chosen to implement the array using the <em>std::vector</em>
container class.
<p/>
When populating the list, the functions <em>clear()</em> and <em>push_back(move)</em> are used.
When examining the list, the functions <em>size()</em> and <em>operator []</em> are used.
<h1>Board representation</h1>
<h2>The CBoard class</h2>
This class is defined in the file <em>CBoard.h</em> and contains all the
information defining the current position on the board. Of course, this
includes the above mentioned array. Additionally, it includes an integer value
that specifies whether it is the white or the black pieces to move.
<pre>
class CBoard
{
public:
void newGame();
void find_legal_moves(CMoveList &moves) const;
void make_move(const CMove &move);
int get_value();
private:
std::vector<int8_t> m_board;
int m_side_to_move;
}; // end of class CBoard
</pre>
<p/>
The function <em>newGame()</em> resets the board to the starting position, the
function <em>make_move()</em> updates the board position with the supplied
move, and finally <em>find_legal_moves()</em> generates a list of all legal moves
in the current board position.
<h2>Enhancements</h2>
To improve performance, I've added another member variable that keeps track of
the current material balance.
<pre>
int m_material;
</pre>
This is kind of like a cache. Instead of
calculating the material balance after each move, it is much faster to check
for captures and promotion, and adjust the current cache incrementally.
<h1>Searching for the best move</h1>
<h2>The AI class</h2>
This class contains an implementation of the alpha-beta pruning algorithm.
This is a complicated function, and is best described in <a
href="http://en.wikipedia.org/wiki/Alpha%E2%80%93beta_pruning">wikipedia</a>
and the <a href="http://chessprogramming.wikispaces.com/Alpha-Beta">chess
programming</a> site.
The class interface is very simple, however:
<pre>
class AI
{
public:
AI(CBoard& board) : m_board(board) { }
CMove find_best_move();
private:
int search(int alpha, int beta, int level);
CBoard& m_board;
}; // end of class AI
</pre>
Note that the <em>m_board</em> variable is a reference. This is to avoid making copies of the entire <em>CBoard</em> class.
<h1>Final remarks</h1>
These are the basic ingredients necessary to make a working chess engine.
There only remains to write a <em>main()</em> function that instantiates a
<em>CBoard</em> and a <em>AI</em> object. The you must read the user input and
call <em>ai.find_best_move()</em>.
</body>
</html>
sources = main.cc
sources += CBoard.cc
sources += CMove.cc
sources += ai.cc
sources += CMoveList.cc
program = mchess
TARGET = linux
#TARGET = windows
objects = $(sources:.cc=.o)
depends = $(sources:.cc=.d)
OPTIONS = -W -Wall
OPTIONS += -O3
OPTIONS += -g # debug info
#OPTIONS += -pg # profiling
ifeq ($(TARGET),linux)
CC = g++
else
CC = i686-w64-mingw32-g++
OPTIONS += -static-libgcc -static-libstdc++
program := $(program).exe
endif
$(program): $(objects) Makefile
$(CC) -o $@ $(objects) $(OPTIONS)
cp $@ $(HOME)/bin
%.d: %.cc Makefile
set -e; $(CC) -M $(CPPFLAGS) $(DEFINES) $(INCLUDE_DIRS) $< \
| sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \
[ -s $@ ] || rm -f $@
include $(depends)
%.o : %.cc Makefile
$(CC) $(OPTIONS) $(DEFINES) $(INCLUDE_DIRS) -c $< -o $@
clean:
-rm -f $(objects)
-rm -f $(depends)
-rm -f $(program)
mchess
======
This is a simple (minimalistic) chess engine, but functional never the less.
It is meant as a starting point for writing your own chess engine. Use it for
inspiration :-)
This is actually a part of the answer:
http://www.quora.com/How-do-I-get-started-with-my-own-chess-engine/answer/Michael-J%C3%B8rgensen-2
Features
========
- Includes a simple alpha-beta search strategy.
- Searches a fixed depth of four ply.
- A simple console (ASCII) user interface.
Documentation
=============
The design is documented in the file DOC.html.
The source code has comments in most places. Otherwise, the best place for a high level description is the
above link.
Additionally, the directory doc contains some additional information on writing chess engines.
TODO
====
- Castling
- En passant
- UCI interface (for GUI)
- Time control
- Opening book
#include <stdlib.h> // exit()
#include "ai.h"
#include "CMoveList.h"
/***************************************************************
* search
*
* This is a very basic (Fail-Soft Negamax) alpha-beta search.
* For details, see e.g.
* http://chessprogramming.wikispaces.com/Alpha-Beta
* and
* http://en.wikipedia.org/wiki/Alpha-beta_pruning
*
* Parameter values are:
* * alpha, beta. The search window
* * level. The number of ply (half-moves) to search.
*
* The value returned by this function is
* * positive, if the side to move has an advantage (is winning).
* * negative, if the side to move is losing.
* * zero, if the position is equal.
* * 900+, if the opponent is check-mated.
* * -999, if the side to move is check-mated.
**=************************************************************/
int AI::search(int alpha, int beta, int level)
{
if (level == 0)
return m_board.get_value(); // We are at leaf, just return the static evaluation.
CMoveList moves;
m_board.find_legal_moves(moves);
int best_val = -999; // Assume the worst
// Search through all legal moves
for (unsigned int i=0; i<moves.size(); ++i)
{
if (best_val >= beta)
{
// This is the alpha-beta pruning.
// Stop searching, if we already have found a "killer" move.
break;
}
if (best_val > alpha)
{
// This is part of the alpha-beta pruning too.
// Tighten the search window.
alpha = best_val;
}
const CMove& move = moves[i];
if (move.is_captured_piece_a_king())
{
return 900 + level; // Opponent's king can be captured. That means he is check-mated.
}
// Do a recursive search
m_board.make_move(move);
int num = -search(-beta, -alpha, level-1);
m_board.undo_move(move);
if (num > best_val)
{
// Store the best value so far.
best_val = num;
}
}
return best_val;
} // end of int search
/***************************************************************
* find_best_move
*
* This is the main AI.
* It returns what it considers to be the best legal move in the
* current position.
***************************************************************/
CMove AI::find_best_move()
{
// Make a list of all legal moves
CMoveList moves;
m_board.find_legal_moves(moves);
std::cout << "info string " << moves.size() << " legal moves." << std::endl;
CMoveList best_moves; // Array of the (one or more) best moves so far
int best_val = -999;
// Search through all legal moves
for (unsigned int i=0; i<moves.size(); ++i)
{
CMove move = moves[i];
// Get value of current move
m_board.make_move(move);
int val = -search(-999, 999, 4);
m_board.undo_move(move);
std::cout << "info string " << val << " : " << move << std::endl;
if (val > best_val)
{
best_val = val;
best_moves.clear();
best_moves.push_back(move);
}
else if (val == best_val)
{
best_moves.push_back(move);
}
}
if (best_moves.size() == 0)
{
std::cout << "BUG: No legal moves!" << std::endl;
exit(1);
}
return best_moves[rand() % best_moves.size()];
} // end of find_best_move
ai.o ai.d : ai.cc \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/stdlib.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__config \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/pthread.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/stdlib.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/Availability.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/AvailabilityVersions.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/AvailabilityInternal.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/cdefs.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_symbol_aliasing.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_posix_availability.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/machine/_types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/_types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/wait.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_pid_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_id_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/signal.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/appleapiopts.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/machine/signal.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/signal.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/machine/_mcontext.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/_mcontext.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/mach/machine/_structs.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/mach/i386/_structs.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/machine/types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_int8_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_int16_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_int32_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_int64_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_u_int8_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_u_int16_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_u_int32_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_u_int64_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_intptr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_uintptr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_attr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_sigaltstack.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_ucontext.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_sigset_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_size_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_uid_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/resource.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/stdint.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/12.0.0/include/stdint.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/stdint.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_uint8_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_uint16_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_uint32_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_uint64_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_intmax_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_uintmax_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_timeval.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/machine/endian.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/endian.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_endian.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/libkern/_OSByteOrder.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/libkern/i386/_OSByteOrder.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/alloca.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_ct_rune_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_rune_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_wchar_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_null.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/malloc/_malloc.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_dev_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_mode_t.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/math.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/math.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/type_traits \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cstddef \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__cxx_version \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/12.0.0/include/stddef.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__nullptr \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/limits \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__undef_macros \
ai.h CBoard.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/iosfwd \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/wchar.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/wchar.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_mbstate_t.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/12.0.0/include/stdarg.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/stdio.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/stdio.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_stdio.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_va_list.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/stdio.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_ctermid.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_off_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_ssize_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/time.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_clock_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_time_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_timespec.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_wctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/__wctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_wint_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_wctype_t.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/ctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/ctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_ctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/runetype.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__bit_reference \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/bit \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__debug \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/algorithm \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/initializer_list \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cstring \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/string.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/string.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_rsize_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_errno_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/strings.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/utility \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__tuple \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cstdint \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/typeinfo \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/exception \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cstdlib \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/new \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/iterator \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__functional_base \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__functional_base_03 \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/tuple \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/stdexcept \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/atomic \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cassert \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/assert.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/functional \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__functional_03 \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/climits \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/limits.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/12.0.0/include/limits.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/limits.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/machine/limits.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/limits.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/_limits.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/syslimits.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__split_buffer \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/string \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/string_view \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__string \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cstdio \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cwchar \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cwctype \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cctype \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/wctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/wctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_wctrans_t.h \
CMove.h CSquare.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/iostream \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/ios \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__locale \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/mutex \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__mutex_base \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/chrono \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/ctime \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/ratio \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/system_error \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__errc \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cerrno \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/errno.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/errno.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/errno.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__threading_support \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/pthread/sched.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/pthread/pthread_impl.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_cond_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_condattr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_key_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_mutex_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_mutexattr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_once_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_rwlock_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_rwlockattr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/pthread/qos.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/qos.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_mach_port_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sched.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/locale.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/locale.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_locale.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_xlocale.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/_ctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/__wctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/_stdio.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/_stdlib.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/_string.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/_time.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/_wchar.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/stddef.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/_wctype.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/streambuf \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/istream \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/ostream \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/locale \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/nl_types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_u_char.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_u_short.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_u_int.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_caddr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_blkcnt_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_blksize_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_gid_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_in_addr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_in_port_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_ino_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_ino64_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_key_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_nlink_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_useconds_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_suseconds_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fd_def.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fd_setsize.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fd_set.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fd_clr.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fd_zero.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fd_isset.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fd_copy.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fsblkcnt_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fsfilcnt_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_nl_item.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__bsd_locale_defaults.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/bitset \
CMoveList.h
#ifndef _AI_H_
#define _AI_H_
#include "CBoard.h"
class AI
{
public:
AI(CBoard& board) : m_board(board) { }
CMove find_best_move();
private:
int search(int alpha, int beta, int level);
CBoard& m_board;
}; // end of class AI
#endif // _AI_H_
File added
/*
Base class for environments of RL.
Following features:
Discrete and fix-size action space.
Used as:
Experiment environment;
Environment in Agents' mind
*/
//EnCode for move(action)::
/*
from_id 64
to_id 64
captured 10
promoted 8
stone 17
Attention: all this coding part should be >= 0
*/
//action = from_id * 64^4 + to_id * 64^3 + captured * 64^2 + promoted * 64^1 = stone * 64^0
#include <cstdlib>
#include <string>
class Chess: public BaseEnv {
public:
Chess();
~Chess();
virtual int Move(int action) = 0;
virtual bool IsFinish() = 0;
virtual void GetResult(float& res) = 0;
virtual void GetFeature(BaseFeature& feature) = 0;
virtual void GetActionNum() = 0;
virtual void GetInputDim(vector<int>& input_dim) = 0;
virtual void GetLegalAction(vector<int>& action) = 0;
virtual bool IsLegal(int action) = 0;
virtual std::string action2str(int action) = 0;
//virtual void TransformFeatures(BaseFeature& feature, int transform_mode) = 0;
//virtual void TransformPolicy(int transform_mode) = 0; // this is reverse mode of TransformFeature
protected:
virtual void Init() = 0;
};
\ No newline at end of file
#include "chess_comm.h"
#include <cstring>
#include <mutex>
// #include <glog/logging.h>
#define x first
#define y second
using namespace std;
using namespace ChessComm;
ChessHashValuePair g_hash_weight[BORDER_SIZE][BORDER_SIZE];
ChessCoordId g_log2_table[67];
uint64_t g_zobrist_board_hash_weight[4][CHESSBOARD_SIZE];
uint64_t g_zobrist_player_hash_weight[4];
namespace ChessFunction {
bool InBoard(const ChessCoordId id) {
return 0 <= id && id < CHESSBOARD_SIZE;
}
bool InBoard(const ChessCoordId x, const ChessCoordId y) {
return 0 <= x && x < BORDER_SIZE
&& 0 <= y && y < BORDER_SIZE;
}
bool IsUnset(const ChessCoordId id) {
return COORD_UNSET == id;
}
bool IsUnset(const ChessCoordId x, const ChessCoordId y) {
return COORD_UNSET == CoordToId(x, y);
}
bool IsResign(const ChessCoordId id) {
return COORD_RESIGN == id;
}
bool IsResign(const ChessCoordId x, const ChessCoordId y) {
return COORD_RESIGN == CoordToId(x, y);
}
void IdToCoord(const ChessCoordId id, ChessCoordId &x, ChessCoordId &y) {
if (COORD_RESIGN == id) {
x = y = COORD_RESIGN;
} else if (!InBoard(id)) {
x = y = COORD_UNSET;
} else {
x = id / BORDER_SIZE;
y = id % BORDER_SIZE;
}
}
ChessCoordId CoordToId(const ChessCoordId x, const ChessCoordId y) {
if (COORD_RESIGN == x && COORD_RESIGN == y) {
return COORD_RESIGN;
}
if (!InBoard(x, y)) {
return COORD_UNSET;
}
return x * BORDER_SIZE + y;
}
void StrToCoord(const string &str, ChessCoordId &x, ChessCoordId &y) {
// CHECK_EQ(str.length(), 2) << "string[" << str << "] length not equal to 2";
x = str[0] - 'a';
y = str[1] - 'a';
if (!InBoard(x, y)) {
x = y = COORD_UNSET;
}
}
string CoordToStr(const ChessCoordId x, const ChessCoordId y) {
char buffer[3];
if (!InBoard(x, y)) {
buffer[0] = buffer[1] = 'z';
} else {
buffer[0] = x + 'a';
buffer[1] = y + 'a';
}
return string(buffer, 2);
}
std::string IdToStr(const ChessCoordId id) {
ChessCoordId x, y;
IdToCoord(id, x, y);
return CoordToStr(x, y);
}
ChessCoordId StrToId(const std::string &str) {
ChessCoordId x, y;
StrToCoord(str, x, y);
return CoordToId(x, y);
}
void ActionToId(const int &action, const ChessCoordId &from_id, const ChessCoordId &to_id, ChessStoneColor &captured_stone, ChessStoneColor &promoted_stone, ChessStoneColor &stone){
int code[5];
int i;
if(action == COORD_RESIGN){
from_id = to_id = COORD_RESIGN;
captured_stone = promoted_stone = stone = EMPTY;
}else if(action == COORD_UNSET){
from_id = to_id = COORD_UNSET;
captured_stone = promoted_stone = stone = EMPTY;
}else{
for(i = 0; i < 5; i++){
code[i] = 0;
}
for(i = 0; i < 5; i++){
code[i] = action % 64;
action = action / 64;
}
from_id = code[4];
to_id = code[3];
captured_stone = code[2];
promoted_stone = code[1];
stone = code[0];
}
}
void IdToAction(const ChessCoordId &from_id, const ChessCoordId &to_id, ChessStoneColor &captured_stone, ChessStoneColor &promoted_stone, ChessStoneColor &stone, const int &action){
int code[5];
int i, j;
for(i = 0; i < 5; i++){
code[i] = 1;
}
if(from_id == COORD_RESIGN || to_id == COORD_RESIGN){
action = COORD_RESIGN;
}else if(!InBoard(from_id) || !InBoard(to_id)){
action = COORD_UNSET;
}else if(from_id >= 0 && to_id >= 0 && captured_stone >= 0 && promoted_stone >= 0 && stone >= 0){
for(i = 0; i < 5; i++){
for(j = i; j > 0; j--){
code[i] *= 64;
}
}
action = from_id * code[4] + to_id * code[3] + captured_stone * code[2] + promoted_stone * code[1] + stone * code[0];
}
}
once_flag CreateGlobalVariables_once;
void CreateGlobalVariables() {
call_once(
CreateGlobalVariables_once,
[]() {
CreateHashWeights();
CreateQuickLog2Table();
CreateZobristHash();
}
);
}
void CreateHashWeights() {
g_hash_weight[0][0] = ChessHashValuePair(1, 1);
for (ChessCoordId i = 1; i < CHESSBOARD_SIZE; ++i) {
g_hash_weight[i / BORDER_SIZE][i % BORDER_SIZE] =
ChessHashValuePair(g_hash_weight[(i - 1) / BORDER_SIZE][(i - 1) % BORDER_SIZE].x * g_hash_unit.x,
g_hash_weight[(i - 1) / BORDER_SIZE][(i - 1) % BORDER_SIZE].y * g_hash_unit.y);
}
}
void CreateQuickLog2Table() {
memset(g_log2_table, -1, sizeof(g_log2_table));
int tmp = 1;
for (ChessCoordId i = 0; i < 64; ++i) {
g_log2_table[tmp] = i;
tmp *= 2;
tmp %= 67;
}
}
#if defined(_WIN32) || defined(_WIN64)
static int rand_r(unsigned int *seed)
{
unsigned int next = *seed;
int result;
next *= 1103515245;
next += 12345;
result = (unsigned int)(next / 65536) % 2048;
next *= 1103515245;
next += 12345;
result <<= 10;
result ^= (unsigned int)(next / 65536) % 1024;
next *= 1103515245;
next += 12345;
result <<= 10;
result ^= (unsigned int)(next / 65536) % 1024;
*seed = next;
return result;
}
#endif
void CreateZobristHash() {
uint32_t seed = 0xdeadbeaf;
for (int i = 0; i < 4; ++i) {
g_zobrist_player_hash_weight[i] = (uint64_t) rand_r(&seed) << 32 | rand_r(&seed);
for (int j = 0; j < CHESSBOARD_SIZE; ++j) {
g_zobrist_board_hash_weight[i][j] = (uint64_t) rand_r(&seed) << 32 | rand_r(&seed);
}
}
}
} // namespace ChessFunction
#undef y
#undef x
#pragma once
#include <inttypes.h>
#include <string>
#include <vector>
//Chess Board Id:
// 0 1 2 3 4 5 6 7
// 8 9 10 11 12 13 14 15
// 16 17 18 19 20 21 22 23
// 24 25 26 27 28 29 30 31
// 32 33 34 35 36 37 38 39
// 40 41 42 43 44 45 46 47
// 48 49 50 51 52 53 54 55
// 56 57 58 59 60 61 62 63
//End
// Return code of functions should be "int"
typedef uint8_t ChessStoneColor; // Stone color
typedef int16_t ChessCoordId; // Stone IDs or coordinates
typedef int16_t ChessSize; // Counts of visit times, used blocks, .. or other count
namespace ChessComm {
const ChessCoordId BORDER_SIZE = 8; // sxk_modify
const ChessCoordId CHESSBOARD_SIZE = BORDER_SIZE * BORDER_SIZE;
const ChessCoordId COORD_UNSET = -2;
//const ChessCoordId COORD_PASS = -1;
const ChessCoordId COORD_RESIGN = -3;
const ChessStoneColor EMPTY = 0;
const ChessStoneColor BLACK = 1;
const ChessStoneColor WHITE = 2;
const ChessStoneColor WALL = 3;
const ChessStoneColor WHITE_PAWN = 4;
const ChessStoneColor WHITE_KNIGHT = 5;
const ChessStoneColor WHITE_BISHOP = 6;
const ChessStoneColor WHITE_ROOK = 7;
const ChessStoneColor WHITE_QUEEN = 8;
const ChessStoneColor WHITE_KING = 9;
const ChessStoneColor BLACK_PAWN = 10;
const ChessStoneColor BLACK_KNIGHT = 11;
const ChessStoneColor BLACK_BISHOP = 12;
const ChessStoneColor BLACK_ROOK = 13;
const ChessStoneColor BLACK_QUEEN = 14;
const ChessStoneColor BLACK_KING = 15;
const ChessStoneColor COLOR_UNKNOWN = -1;
const char *const COLOR_STRING[] = { "Empty", "Black", "White", "Wall", "White Pawn", "White Knight", "White Bishop", "White Rook", "White Queen", "White King", "Black Pawn", "Black Knight", "Black Bishop", "Black Rook", "Black Queen", "Black King" };
const ChessCoordId N = -8;
const ChessCoordId S = 8;
const ChessCoordId E = 1;
const ChessCoordId W = -1;
const ChessCoordId NW = -9;
const ChessCoordId SW = 7;
const ChessCoordId NE = -7;
const ChessCoordId SE = 9;
const ChessCoordId NNW = -17;
const ChessCoordId NNE = -15;
const ChessCoordId NWW = -10;
const ChessCoordId NEE = -6;
const ChessCoordId SSW = 15;
const ChessCoordId SSE = 17;
const ChessCoordId SWW = 6;
const ChessCoordId SEE = 10;
} // namespace ChessComm
namespace ChessFeature {
const int SIZE_HISTORYEACHSIDE = 16;
const int SIZE_PLAYERCOLOR = 1;
const int STARTPOS_HISTORYEACHSIDE = 0;
const int STARTPOS_PLAYERCOLOR = STARTPOS_HISTORYEACHSIDE + SIZE_HISTORYEACHSIDE;
const int FEATURE_COUNT = STARTPOS_PLAYERCOLOR + SIZE_PLAYERCOLOR;
} // namespace ChessFeature
namespace ChessFunction {
extern bool InBoard(const ChessCoordId id);
extern bool InBoard(const ChessCoordId x, const ChessCoordId y);
extern bool IsUnset(const ChessCoordId id);
extern bool IsUnset(const ChessCoordId x, const ChessCoordId y);
extern bool IsResign(const ChessCoordId id);
extern bool IsResign(const ChessCoordId x, const ChessCoordId y);
extern void IdToCoord(const ChessCoordId id, ChessCoordId &x, ChessCoordId &y);
extern ChessCoordId CoordToId(const ChessCoordId x, const ChessCoordId y);
extern void StrToCoord(const std::string &str, ChessCoordId &x, ChessCoordId &y);
extern std::string CoordToStr(const ChessCoordId x, const ChessCoordId y);
extern std::string IdToStr(const ChessCoordId id);
extern ChessCoordId StrToId(const std::string &str);
extern void ActionToId(const int &action, const ChessCoordId &from_id, const ChessCoordId &to_id, ChessStone &captured_stone, ChessStone &promoted_stone, ChessStone &stone);
extern void IdToAction(const ChessCoordId &from_id, const ChessCoordId &to_id, ChessStone &captured_stone, ChessStone &promoted_stone, ChessStone &stone, const int &action);
extern void CreateGlobalVariables();
extern void CreateHashWeights();
extern void CreateQuickLog2Table();
extern void CreateZobristHash();
} // namespace ChessFunction
//typedef std::pair<ChessCoordId, ChessCoordId> ChessPosition;
typedef std::pair<uint64_t, uint64_t> ChessHashValuePair;
extern ChessHashValuePair g_hash_weight[ChessComm::BORDER_SIZE][ChessComm::BORDER_SIZE];
const ChessHashValuePair g_hash_unit(3, 7);
extern uint64_t g_zobrist_board_hash_weight[4][ChessComm::CHESSBOARD_SIZE];
extern uint64_t g_zobrist_player_hash_weight[4];
//action_count:统计已落子数,state:统计棋局状态,0未分胜负,1黑胜,2白胜,3平局
//extern int action_count = 0;
//extern int state = 0;
extern ChessCoordId g_log2_table[67];
#define FOR_EACHCOORD(id) for (ChessCoordId id = 0; id < ChessComm::CHESSBOARD_SIZE; ++id)
#include "chess_env.h"
#include <algorithm>
#include <cmath>
using namespace std;
using namespace ChessComm;
using namespace ChessFunction;
using namespace ChessFeature;
ChessEnv::ChessEnv() {
CreateGlobalVariables();
FOR_EACHCOORD(i) {
stones_[i].self_id = i;
}
action_list_.clear();
feature_history_list_.clear();
memset(board_state_, 0, sizeof(board_state_));
memset(move_count_, 0, sizeof(move_count_));
current_player_ = WHITE;
last_action_ = COORD_UNSET;
is_resign_ = false;
state_ = 0;
material_ = 0;
board_hash_states_.clear();
zobrist_hash_value_ = 0;
}
//ChessEnv::ChessEnv(const ChessEnv &ge) : ChessEnv() {
// CopyFrom(ge);
// }
ChessEnv::~ChessEnv() {
}
// void ChessEnv::CopyFrom(const ChessEnv &src) {
// *this = src;
// }
void ChessEnv::GetSensibleMove() {
// Add new feature plane
string plane;
// white
{
plane = "";
FOR_EACHCOORD(id) {
if (board_state_[id] == WHITE) {
plane += "1";
} else {
plane += "0";
}
}
feature_history_list_.push_back(plane);
}
// black
{
plane = "";
FOR_EACHCOORD(id) {
if (board_state_[id] == BLACK) {
plane += "1";
} else {
plane += "0";
}
}
feature_history_list_.push_back(plane);
}
Find_Legal_Moves();
}
int ChessState::Move(int action) {
ChessCoordId from_id, to_id;
ChessStoneColor captured_stone, promoted_stone, piece;
Find_Legal_Moves();
if (!IsLegal(action)) {
return -1;
}
if(IsResign(action)){
is_resign_ = true;
return 0;
}
last_action_ = action;
{
zobrist_hash_value_ ^= g_zobrist_player_hash_weight[Self()];
zobrist_hash_value_ ^= g_zobrist_player_hash_weight[Opponent()];
zobrist_hash_value_ ^= g_zobrist_board_hash_weight[Self()][action];
}
ChessFunction::ActionToId(action, from_id, to_id, captured_stone, promoted_stone, piece);
++move_count_[action];
switch (captured_stone)
{
case ChessComm::WHITE_PAWN : case ChessComm::BLACK_PAWN : material_ -= 1; break;
case ChessComm::WHITE_KNIGHT : case ChessComm::BLACK_KNIGHT : material_ -= 3; break;
case ChessComm::WHITE_BISHOP : case ChessComm::BLACK_BISHOP : material_ -= 3; break;
case ChessComm::WHITE_ROOK : case ChessComm::BLACK_ROOK : material_ -= 5; break;
case ChessComm::WHITE_QUEEN : case ChessComm::BLACK_QUEEN : material_ -= 9; break;
default : break;
}
switch (promoted_stone)
{
case ChessComm::WHITE_KNIGHT : case ChessComm::BLACK_KNIGHT : material_ -= 3 - 1; break;
case ChessComm::WHITE_BISHOP : case ChessComm::BLACK_BISHOP : material_ -= 3 - 1; break;
case ChessComm::WHITE_ROOK : case ChessComm::BLACK_ROOK : material_ -= 5 - 1; break;
case ChessComm::WHITE_QUEEN : case ChessComm::BLACK_QUEEN : material_ -= 9 - 1; break;
default : break;
}
board_state_[to_id] = board_state_[from_id];
if (promoted_stone != ChessComm::EMPTY){
board_state_[to_id] = promoted_stone;
}
board_state_[from_id] = ChessComm::EMPTY;
HandOff();
material_ = - material_;
GetSensibleMove();
return 0;
}
bool ChessEnv::IsSquareThreatened(ChessCoordId& id) const{
if(ChessFunction::InBoard(id)){
if (current_player_ == ChessComm::WHITE){
// Check for pawns
if (board_state_[id + ChessComm::NW] == ChessComm::BLACK_PAWN || board_state_[id + ChessComm::NE] == ChessComm::BLACK_PAWN){
return true;
}
// Check for knigts
{
int dirs[8] = {ChessComm::NNW, ChessComm::NNE, ChessComm::NWW, ChessComm::NEE, ChessComm::SSW, ChessComm::SSE, ChessComm::SWW, ChessComm::SEE};
for (int k = 0; k < 8; ++k){
int dir = dirs[k];
if (board_state_[id + dir] == ChessComm::BLACK_KNIGHT){
return true;
}
}
}
// Check for diagonal (bishop and queen)
{
int dirs[4] = {ChessComm::NW, ChessComm::NE, ChessComm::SW, ChessComm::SE};
for (int k = 0; k < 4; ++k){
int dir = dirs[k];
int id2 = id;
while (1){
id2 += dir;
if (board_state_[id2] == ChessComm::BLACK_BISHOP || board_state_[id2] == ChessComm::BLACK_QUEEN){
return true;
}
if (board_state_[id2] != ChessComm::EMPTY){
break;
}
}
}
}
// Check for horizontal/vertical (rook and queen)
{
int dirs[4] = {ChessComm::N, ChessComm::S, ChessComm::W, ChessComm::E};
for (int k = 0; k < 4; ++k)
{
int dir = dirs[k];
int id2 = id;
while (1){
id2 += dir;
if (board_state_[id2] == ChessComm::BLACK_ROOK || board_state_[id2] == ChessComm::BLACK_QUEEN){
return true;
}
if (board_state_[id2] != ChessComm::EMPTY){
break;
}
}
}
}
// Check for king
{
int dirs[8] = {ChessComm::NW, ChessComm::NE, ChessComm::SW, ChessComm::SE, ChessComm::N, ChessComm::S, ChessComm::W, ChessComm::E};
for (int k = 0; k < 8; ++k){
int dir = dirs[k];
if (board_state_[id + dir] == ChessComm::BLACK_KING){
return true;
}
}
}
}else{
// Check for pawns
if (board_state_[id + ChessComm::SW] == ChessComm::WHITE_PAWN || board_state_[id + ChessComm::SE] == ChessComm::WHITE_PAWN){
return true;
}
// Check for knigts
{
int dirs[8] = {ChessComm::NNW, ChessComm::NNE, ChessComm::NWW, ChessComm::NEE, ChessComm::SSW, ChessComm::SSE, ChessComm::SWW, ChessComm::SEE};
for (int k = 0; k < 8; ++k){
int dir = dirs[k];
if (board_state_[id + dir] == ChessComm::WHITE_KNIGHT){
return true;
}
}
}
// Check for diagonal (bishop and queen)
{
int dirs[4] = {ChessComm::NW, ChessComm::NE, ChessComm::SW, ChessComm::SE};
for (int k = 0; k < 4; ++k){
int dir = dirs[k];
int id2 = id;
while (1){
id2 += dir;
if (board_state_[id2] == ChessComm::WHITE_BISHOP || board_state_[id2] == ChessComm::WHITE_QUEEN){
return true;
}
if (board_state_[id2] != ChessComm::EMPTY){
break;
}
}
}
}
// Check for horizontal/vertical (rook and queen)
{
int dirs[4] = {ChessComm::N, ChessComm::S, ChessComm::W, ChessComm::E};
for (int k = 0; k < 4; ++k){
int dir = dirs[k];
int id2 = id;
while (1){
id2 += dir;
if (board_state_[id2] == ChessComm::WHITE_ROOK || board_state_[id2] == ChessComm::WHITE_QUEEN){
return true;
}
if (board_state_[id2] != ChessComm::EMPTY){
break;
}
}
}
}
// Check for king
{
int dirs[8] = {ChessComm::NW, ChessComm::NE, ChessComm::SW, ChessComm::SE,ChessComm:: N, ChessComm::S, ChessComm::W, ChessComm::E};
for (int k = 0; k < 8; ++k){
int dir = dirs[k];
if (board_state_[id + dir] == ChessComm::WHITE_KING){
return true;
}
}
}
}
}
return false;
}
bool ChessEnv::IsKingInCheck() const{
ChessStoneColor king;
ChessCoordId kingid = ChessComm::COORD_UNSET;
if (current_player_ == ChessComm::WHITE){
king = ChessComm::WHITE_KING;
}
else if(current_player_ == ChessComm::BLACK){
king = ChessComm::BLACK_KING;
}
// Look for our king
FOR_EACHCOORD(id){
if(board_state_[id] == king){
kingid = id;
break;
}
}
return isSquareThreatened(kingid);
} // end of isKingInCheck
void ChessEnv::Find_Legal_Moves() const{
action_list_.clear();
int action;
if (current_player_ == ChessComm::WHITE){
for (int i = 0; i < ChessComm::CHESSBOARD_SIZE; ++i){
ChessStoneColor piece = board_state_[i];
int j;
switch (piece){
case ChessComm::WHITE_PAWN : // White pawn
//j = i + 10; // One square forward
j = i - ChessComm::BORDER_SIZE; // One square forward
if (m_board[j] == EM){
//if (i > 80) // Check for promotion
if (i < 2 * ChessComm::BORDER_SIZE) // Check for promotion
{
{
ChessFunction::IdToAction(i, j, ChessComm::EMPTY, ChessComm::WHITE_QUEEN, piece, action);
//CMove move(piece, i, j, EM, WQ);
action_list_.push_back(action);
}
{
ChessFunction::IdToAction(i, j, ChessComm::EMPTY, ChessComm::WHITE_ROOK, piece, action);
//CMove move(piece, i, j, EM, WR);
action_list_.push_back(action);
}
{
ChessFunction::IdToAction(i, j, ChessComm::EMPTY, ChessComm::WHITE_BISHOP, piece, action);
//CMove move(piece, i, j, EM, WB);
action_list_.push_back(action);
}
{
ChessFunction::IdToAction(i, j, ChessComm::EMPTY, ChessComm::WHITE_KNIGHT, piece, action);
//CMove move(piece, i, j, EM, WN);
action_list_.push_back(action);
}
}
else // regular pawn move
{
ChessFunction::IdToAction(i, j, ChessComm::EMPTY, ChessComm::EMPTY, piece, action);
//CMove move(piece, i, j, EM);
action_list_.push_back(action);
}
//j = i + 20; // Two squares forward
j = i - 2 * ChessComm::BORDER_SIZE;
if (board_state_[j] == ChessComm::EMPTY){
//if (i < 40) // Only from second rank
if(i >= 6 * ChessComm::BORDER_SIZE)
{
ChessFunction::IdToAction(i, j, ChessComm::EMPTY, ChessComm::EMPTY, piece, action);
//CMove move(piece, i, j, EM);
action_list_.push_back(action);
}
}
}
//j = i + 9; // Diagonal capture
j = i - ChessComm::BORDER_SIZE - 1;
//if ((m_board[j] != IV && m_board[j] < 0))
if ((ChessFunction::InBoard(j) && current_player_ == ChessComm::BLACK))
{
//if (i > 80) // Check for promotion
if (i < 2 * ChessComm::BORDER_SIZE) // Check for promotion
{
{
ChessFunction::IdToAction(i, j, board_state_[j], ChessComm::WHITE_QUEEN, piece, action);
//CMove move(piece, i, j, m_board[j], WQ);
action_list_.push_back(action);
}
{
ChessFunction::IdToAction(i, j, board_state_[j], ChessComm::WHITE_ROOK, piece, action);
//CMove move(piece, i, j, m_board[j], WR);
action_list_.push_back(action);
}
{
ChessFunction::IdToAction(i, j, board_state_[j], ChessComm::WHITE_BISHOP, piece, action);
//CMove move(piece, i, j, m_board[j], WB);
action_list_.push_back(action);
}
{
ChessFunction::IdToAction(i, j, board_state_[j], ChessComm::WHITE_KNIGHT, piece, action);
//CMove move(piece, i, j, m_board[j], WN);
action_list_.push_back(action);
}
}
else
{
ChessFunction::IdToAction(i, j, board_state_[j], ChessComm::EMPTY, piece, action);
//CMove move(piece, i, j, m_board[j]);
action_list_.push_back(action);
}
}
//j = i + 11; // Diagonal capture
j = i - ChessComm::BORDER_SIZE + 1;
//if ((m_board[j] != IV && m_board[j] < 0))
if((ChessFunction::InBoard(j) && current_player_ == ChessComm::BLACK))
{
//if (i > 80) // Check for promotion
if(i < 2 * ChessComm::BORDER_SIZE)
{
{
ChessFunction::IdToAction(i, j, board_state_[j], ChessComm::WHITE_QUEEN, piece, action);
//CMove move(piece, i, j, m_board[j], WQ);
action_list_.push_back(action);
}
{
ChessFunction::IdToAction(i, j, board_state_[j], ChessComm::WHITE_ROOK, piece, action);
//CMove move(piece, i, j, m_board[j], WR);
action_list_.push_back(action);
}
{
ChessFunction::IdToAction(i, j, board_state_[j], ChessComm::WHITE_BISHOP, piece, action);
//CMove move(piece, i, j, m_board[j], WB);
action_list_.push_back(action);
}
{
ChessFunction::IdToAction(i, j, board_state_[j], ChessComm::WHITE_KNIGHT, piece, action);
//CMove move(piece, i, j, m_board[j], WN);
action_list_.push_back(action);
}
}
else
{
ChessFunction::IdToAction(i, j, board_state_[j], ChessComm::EMPTY, piece, action);
//CMove move(piece, i, j, m_board[j]);
action_list_.push_back(action);
}
}
break;
case ChessComm::WHITE_KNIGHT : // White knight
{
int dirs[8] = {ChessComm::NNW, ChessComm::NNE, ChessComm::NWW, ChessComm::NEE, ChessComm::SSW, ChessComm::SSE, ChessComm::SWW, ChessComm::SEE};
for (int k = 0; k < 8; ++k)
{
int dir = dirs[k];
j = i + dir;
//if (m_board[j] != IV)
if (ChessFunction::InBoard(j)){
//if (m_board[j] <= 0)
if(current_player_ == ChessComm::BLACK || board_state_[j] == ChessComm::EMPTY)
{
ChessFunction::IdToAction(i, j, board_state_[j], ChessComm::EMPTY, piece, action);
//CMove move(piece, i, j, m_board[j]);
action_list_.push_back(action);
}
}
}
}
break;
case ChessComm::WHITE_BISHOP : // White bishop
{
int dirs[4] = {ChessComm::NE, ChessComm::NW, ChessComm::SE, ChessComm::SW};
for (int k = 0; k < 4; ++k)
{
int dir = dirs[k];
j = i;
while (1)
{
j += dir;
//if (m_board[j] == IV) break;
if(!InBoard(j)){
break;
}
//if (m_board[j] <= 0)
if(current_player_ == ChessComm::BLACK || board_state_[j] == ChessComm::EMPTY)
{
ChessFunction::IdToAction(i, j, board_state_[j], ChessComm::EMPTY, piece, action);
//CMove move(piece, i, j, m_board[j]);
action_list_.push_back(action);
//if (m_board[j] < 0)
if(current_player_ == ChessComm::BLACK){
break;
}
}
else{
break;
}
}
}
}
break;
case ChessComm::WHITE_ROOK : // White rook
{
int dirs[4] = {ChessComm::N, ChessComm::E, ChessComm::S, ChessComm::W};
for (int k = 0; k < 4; ++k)
{
int dir = dirs[k];
j = i;
while (1)
{
j += dir;
//if (m_board[j] == IV) break;
if(!InBoard(j)){
break;
}
//if (m_board[j] <= 0)
if(current_player_ == ChessComm::BLACK || board_state_[j] == ChessComm::EMPTY)
{
ChessFunction::IdToAction(i, j, board_state_[j], ChessComm::EMPTY, piece, action);
//CMove move(piece, i, j, m_board[j]);
action_list_.push_back(action);
//if (m_board[j] < 0)
if(current_player_ == ChessComm::BLACK){
break;
}
}
else{
break;
}
}
}
}
break;
case ChessComm::WHITE_QUEEN : // White queen
{
int dirs[8] = {ChessComm::NE, ChessComm::NW, ChessComm::SE, ChessComm::SW, ChessComm::N, ChessComm::E, ChessComm::S, ChessComm::W};
for (int k = 0; k < 8; ++k)
{
int dir = dirs[k];
j = i;
while (1)
{
j += dir;
//if (m_board[j] == IV) break;
if(!InBoard(j)){
break;
}
//if (m_board[j] <= 0)
if(current_player_ == ChessComm::BLACK || board_state_[j] == ChessComm::EMPTY)
{
ChessFunction::IdToAction(i, j, board_state_[j], ChessComm::EMPTY, piece, action);
//CMove move(piece, i, j, m_board[j]);
action_list_.push_back(action);
//if (m_board[j] < 0)
if(current_player_ == ChessComm::BLACK){
break;
}
}
else{
break;
}
}
}
}
break;
case ChessComm::WHITE_KING : // White king
{
int dirs[8] = {ChessComm::NE, ChessComm::NW, ChessComm::SE, ChessComm::SW, ChessComm::N, ChessComm::E, ChessComm::S, ChessComm::W};
for (int k = 0; k < 8; ++k)
{
int dir = dirs[k];
j = i + dir;
//if (m_board[j] != IV)
if(ChessFunction::InBoard(j)){
//if (m_board[j] <= 0)
if(current_player_ == ChessComm::BLACK || board_state_[j] == ChessComm::EMPTY)
{
ChessFunction::IdToAction(i, j, board_state_[j], ChessComm::EMPTY, piece, action);
//CMove move(piece, i, j, m_board[j]);
action_list_.push_back(action);
}
}
}
}
break;
default : // Invalid, wrong color, or empty
continue;
}
}
}
else{
//for (int i=A1; i<=H8; ++i)
for(int i = 0; i < ChessComm::CHESSBOARD_SIZE; i++)
{
ChessStoneColor piece = board_state_[i];
int j;
switch (piece)
{
case ChessComm::BLACK_PAWN : // Black pawn
//j = i - 10; // One squre forward
j = i + ChessComm::BORDER_SIZE; // One squre forward
//if (m_board[j] == EM)
if(board_state_[j] == ChessComm::EMPTY)
{
//if (i < 40) // Check for promotion
if(i >= 6 * ChessComm::BORDER_SIZE)
{
{
ChessFunction::IdToAction(i, j, ChessComm::EMPTY, ChessComm::BLACK_QUEEN, piece, action);
//CMove move(piece, i, j, EM, BQ);
action_list_.push_back(action);
}
{
ChessFunction::IdToAction(i, j, ChessComm::EMPTY, ChessComm::BLACK_ROOK, piece, action);
//CMove move(piece, i, j, EM, BR);
action_list_.push_back(action);
}
{
ChessFunction::IdToAction(i, j, ChessComm::EMPTY, ChessComm::BLACK_BISHOP, piece, action);
//CMove move(piece, i, j, EM, BB);
action_list_.push_back(action);
}
{
ChessFunction::IdToAction(i, j, ChessComm::EMPTY, ChessComm::BLACK_KNIGHT, piece, action);
//CMove move(piece, i, j, EM, BN);
action_list_.push_back(action);
}
}
else // Regular pawn move
{
ChessFunction::IdToAction(i, j, ChessComm::EMPTY, ChessComm::EMPTY, piece, action);
//CMove move(piece, i, j, EM);
action_list_.push_back(action);
}
//j = i - 20; // Two squares forward
j = i + 2 * ChessComm::BORDER_SIZE; // Two squares forward
//if (m_board[j] == EM)
if(board_state_[j] == ChessComm::EMPTY)
{
//if (i > 80) // Only from seventh rank
if (i < 2 * ChessComm::BORDER_SIZE) // Only from seventh rank
{
ChessFunction::IdToAction(i, j, ChessComm::EMPTY, ChessComm::EMPTY, piece, action);
//CMove move(piece, i, j, EM);
action_list_.push_back(action);
}
}
}
//j = i - 9; // Diagonal capture
j = i + ChessComm::BORDER_SIZE + 1; // Diagonal capture
//if ((m_board[j] != IV && m_board[j] > 0))
if(ChessFunction::InBoard(j) && current_player_ == ChessComm::WHITE)
{
//if (i < 40) // Check for promotion
if (i >= 6 * ChessComm::BORDER_SIZE) // Check for promotion
{
{
ChessFunction::IdToAction(i, j, board_state_[j], ChessComm::BLACK_QUEEN, piece, action);
//CMove move(piece, i, j, m_board[j], BQ);
action_list_.push_back(action);
}
{
ChessFunction::IdToAction(i, j, board_state_[j], ChessComm::BLACK_ROOK, piece, action);
//CMove move(piece, i, j, m_board[j], BR);
action_list_.push_back(action);
}
{
ChessFunction::IdToAction(i, j, board_state_[j], ChessComm::BLACK_BISHOP, piece, action);
//CMove move(piece, i, j, m_board[j], BB);
action_list_.push_back(action);
}
{
ChessFunction::IdToAction(i, j, board_state_[j], ChessComm::BLACK_KNIGHT, piece, action);
//CMove move(piece, i, j, m_board[j], BN);
action_list_.push_back(action);
}
}
else
{
ChessFunction::IdToAction(i, j, board_state_[j], ChessComm::EMPTY, piece, action);
//CMove move(piece, i, j, m_board[j]);
action_list_.push_back(action);
}
}
//j = i - 11; // Diagonal capture
j = i + ChessComm::BORDER_SIZE - 1;
//if ((m_board[j] != IV && m_board[j] > 0))
if(ChessComm::InBoard[j] && current_player_ == ChessComm::WHITE)
{
//if (i < 40) // Check for promotion
if(i >= 6 * ChessComm::BORDER_SIZE)
{
{
ChessFunction::IdToAction(i, j, board_state_[j], ChessComm::BLACK_QUEEN, piece, action);
//CMove move(piece, i, j, m_board[j], BQ);
action_list_.push_back(action);
}
{
ChessFunction::IdToAction(i, j, board_state_[j], ChessComm::BLACK_ROOK, piece, action);
//CMove move(piece, i, j, m_board[j], BR);
action_list_.push_back(action);
}
{
ChessFunction::IdToAction(i, j, board_state_[j], ChessComm::BLACK_BISHOP, piece, action);
//CMove move(piece, i, j, m_board[j], BB);
action_list_.push_back(action);
}
{
ChessFunction::IdToAction(i, j, board_state_[j], ChessComm::BLACK_KNIGHT, piece, action);
//CMove move(piece, i, j, m_board[j], BN);
action_list_.push_back(action);
}
}
else
{
ChessFunction::IdToAction(i, j, board_state_[j], ChessComm::EMPTY, piece, action);
//CMove move(piece, i, j, m_board[j]);
action_list_.push_back(action);
}
}
break;
case ChessComm::BLACK_KNIGHT : // Black knight
{
int dirs[8] = {ChessComm::NNW, ChessComm::NNE, ChessComm::NWW, ChessComm::NEE, ChessComm::SSW, ChessComm::SSE, ChessComm::SWW, ChessComm::SEE};
for (int k = 0; k < 8; ++k)
{
int dir = dirs[k];
j = i + dir;
//if (m_board[j] != IV)
if(ChessFunction::InBoard(j)){
//if (m_board[j] >= 0)
if(current_player_ == ChessComm::WHITE || board_state_[j] == ChessComm::EMPTY)
{
ChessFunction::IdToAction(i, j, board_state_[j], ChessComm::EMPTY, piece, action);
//CMove move(piece, i, j, m_board[j]);
action_list_.push_back(action);
}
}
}
}
break;
case ChessComm::BLACK_BISHOP : // Black bishop
{
int dirs[4] = {ChessComm::NE, ChessComm::NW, ChessComm::SE, ChessComm::SW};
for (int k = 0; k < 4; ++k)
{
int dir = dirs[k];
j = i;
while (1)
{
j += dir;
//if (m_board[j] == IV) break;
if(!InBoard(j)){
break;
}
//if (m_board[j] >= 0)
if(current_player_ == ChessComm::WHITE || board_state_[j] == ChessComm::EMPTY)
{
ChessFunction::IdToAction(i, j, board_state_[j], ChessComm::EMPTY, piece, action);
//CMove move(piece, i, j, m_board[j]);
action_list_.push_back(action);
//if (m_board[j] > 0)
if(current_player_ == ChessComm::White){
break;
}
}
else{
break;
}
}
}
}
break;
case ChessComm::BLACK_ROOK : // Black rook
{
int dirs[4] = {ChessComm::N, ChessComm::E, ChessComm::S, ChessComm::W};
for (int k = 0; k < 4; ++k)
{
int dir = dirs[k];
j = i;
while (1)
{
j += dir;
//if (m_board[j] == IV) break;
if(!InBoard(j)){
break;
}
//if (m_board[j] >= 0)
if(current_player_ == ChessComm::WHITE || board_state_[j] == ChessComm:EMPTY)
{
ChessFunction::IdToAction(i, j, board_state_[j], ChessComm::EMPTY, piece, action);
//CMove move(piece, i, j, m_board[j]);
action_list_.push_back(action);
//if (m_board[j] > 0)
if(current_player_ == ChessComm::WHITE){
break;
}
}
else{
break;
}
}
}
}
break;
case ChessComm::BLACK_QUEEN : // Black queen
{
int dirs[8] = {ChessComm::NE, ChessComm::NW, ChessComm::SE, ChessComm::SW, ChessComm::N, ChessComm::E, ChessComm::S, ChessComm::W};
for (int k = 0; k < 8; ++k)
{
int dir = dirs[k];
j = i;
while (1)
{
j += dir;
//if (m_board[j] == IV) break;
if(!InBoard(j)){
break;
}
//if (m_board[j] >= 0)
if(current_player_ == ChessComm::WHITE || board_state_[j] == ChessComm::EMPTY)
{
ChessFunction::IdToAction(i, j, board_state_[j], ChessComm::EMPTY, piece, action);
//CMove move(piece, i, j, m_board[j]);
action_list_.push_back(action);
//if (m_board[j] > 0)
if(current_player_ == ChessComm::WHITE){
break;
}
}
else{
break;
}
}
}
}
break;
case ChessComm::BLACK_KING: // Black king
{
int dirs[8] = {ChessComm::NE, ChessComm::NW, ChessComm::SE, ChessComm::SW, ChessComm::N, ChessComm::E, ChessComm::S, ChessComm::W};
for (int k = 0; k < 8; ++k)
{
int dir = dirs[k];
j = i + dir;
//if (m_board[j] != IV)
if(ChessFunction::InBoard(j)){
//if (m_board[j] >= 0)
if(current_player_ == ChessComm::WHITE || board_state_[j] == ChessComm::EMPTY)
{
ChessFunction::IdToAction(i, j, board_state_[j], ChessComm::EMPTY, piece, action);
//CMove move(piece, i, j, m_board[j]);
action_list_.push_back(action);
}
}
}
}
break;
default : // Invalid, wrong color, or empty
continue;
}
}
}
}
bool ChessEnv::IsMoveValid(int &action) const{
ChessCoordId from_id, to_id;
ChessStoneColor captured_stone, promoted_stone, piece;
for (unsigned int i=0; i < action_list_.size(); ++i){
if (action_list_[i] == action){
ChessFunction::ActionToId(action, from_id, to_id, captured_stone, promoted_stone, piece);
piece = board_state_[from_id];
captured_stone = board_state_[to_id];
ChessFunction::IdToAction(from_id, to_id, captured_stone, promoted_stone, piece);
return true;
}
}
return false;
}
int ChessEnv::CalcResult() const {
ChessStoneColor king;
CSquare kingid = ChessComm::COORD_UNSET;
if (current_player_ == ChessComm::WHITE){
king = ChessComm::WHITE_KING;
}
else if(current_player_ == ChessComm::BLACK){
king = ChessComm::BLACK_KING;
}
FOR_EACHCOORD(id){
if(board_state_[id] == king){
kingid = id;
break;
}
}
if(kingid == ChessComm::COORD_UNSET){
if(current_player_ == ChessComm::WHITE){
state_ = 1;//BLACK WIN!
}else if (current_player_ == ChessComm::BLACK){
state_ = 2;//WHITE WIN!
}
}
return state_;
}
ChessStoneColor ChessEnv::GetWinner() const {
int result = CalcResult();
if (result == 3){
return CHessComm::EMPTY;
}else if (result == 1){
return ChessComm::BLACK;
}else if(result == 2){
return ChessComm::WHITE;
}
}
void ChessEnv::GetResult(float& res) {
if (GetWinner() == ChessComm::EMPTY){
res = 0.0f;
}else{
res = GetWinner() == CurrentPlayer() ? -1.0f : 1.0f;
}
}
vector<bool> ChessEnv::GetFeature(BaseFeature& feature) const { // HWC
feature.clear();
feature.resize(CHESSBOARD_SIZE * (SIZE_HISTORYEACHSIDE + 1));
//vector<bool> feature(CHESSBOARD_SIZE * (SIZE_HISTORYEACHSIDE + 1), 0);
// because push white into history first,
// if next player is white,
// we should get planes swap of each two planes
int reverse_plane = int(Self() == WHITE);
for (ChessSize i = 0; i < SIZE_HISTORYEACHSIDE && i < feature_history_list_.size(); ++i) {
const string &feature_str = *(feature_history_list_.rbegin() + (i ^ reverse_plane));
for (int j = 0, k = i; j < CHESSBOARD_SIZE; ++j, k += (SIZE_HISTORYEACHSIDE + 1)) {
feature[k] = feature_str[j] - '0';
}
}
if (Self() == WHITE) {
for (int j = 0, k = SIZE_HISTORYEACHSIDE; j < CHESSBOARD_SIZE; ++j, k += (SIZE_HISTORYEACHSIDE + 1)) {
feature[k] = 1;
}
}
return feature;
}
int ChessEnv::GetActionNum() {//include RESIGN
return 1073741824 + 1;
}
void ChessEnv::GetInputDim(vector<int>& input_dim) {
input_dim.clear();
input_dim.push_back(SIZE_HISTORYEACHSIDE);
input_dim.push_back(BORDER_SIZE);
input_dim.push_back(BORDER_SIZE)
}
void ChessEnv::GetLegalAction(vector<int>& action) {
action.clear();
for (unsigned int i=0; i < action_list_.size(); ++i){
action.push_back(action_list_[i]);
}
}
std::string ChessEnv::action2str(int action){
ChessCoordId from_id, to_id;
ChessStoneColor captured_stone, promoted_stone, piece;
ChessFunction::ActionToId(action, from_id, to_id, captured_stone, promoted_stone, piece);
char buffer[12];
buffer[0] = 'f';
buffer[1] = 'r';
buffer[2] = 'o';
buffer[3] = 'm';
buffer[4] = ':';
buffer[7] = 't';
buffer[8] = 'o';
buffer[9] = ':';
ChessCoordId from_x, from_y, to_x, to_y;
ChessFunction::IdToCoord(from_id, from_x, from_y);
ChessFunction::IdToCoord(to_id, to_x, to_y);
if (!InBoard(from_x, from_y)) {
buffer[5] = buffer[6] = 'z';
} else if(InBoard(from_x, from_y)){
buffer[5] = from_x + 'a';
buffer[6] = from_y + 'a';
}
if (!InBoard(to_x, to_y)) {
buffer[10] = buffer[11] = 'z';
} else if(InBoard(to_x, to_y)){
buffer[10] = to_x + 'a';
buffer[11] = to_y + 'a';
}
return string(buffer, 12);
}
/*void ChessEnv::TransformCoord(ChessCoordId &x, ChessCoordId &y, int mode, bool reverse = false)
{
if (reverse) {
if (mode & 4) std::swap(x, y);
if (mode & 2) y = ChessComm::BORDER_SIZE - y - 1;
if (mode & 1) x = ChessComm::BORDER_SIZE - x - 1;
} else {
if (mode & 1) x = ChessComm::BORDER_SIZE - x - 1;
if (mode & 2) y = ChessComm::BORDER_SIZE - y - 1;
if (mode & 4) std::swap(x, y);
}
}*/
// void ChessEnv::TransformFeatures(BaseFeature& feature, int transform_mode) {
// BaseFeature ret(feature.size());
// int depth = features.size() / ChessComm::CHESSBOARD_SIZE;
// for (int i = 0; i < ChessComm::CHESSBOARD_SIZE; ++i) {
// ChessCoordId x, y;
// ChessFunction::IdToCoord(i, x, y);
// TransformCoord(x, y, mode);
// int j = ChessFunction::CoordToId(x, y);
// for (int k = 0; k < depth; ++k) {
// ret[i * depth + k] = features[j * depth + k];
// }
// }
// feature = std::move(ret);
// }
// void TransformPolicy(int transform_mode) {
// }
#include "chess_comm.h"
#include "base_env.h"
#include <cstdlib>
#include <cstring>
#include <stack>
#include <string>
#include <unordered_set>
#include <vector>
#if defined(_WIN32) || defined(_WIN64)
# include <intrin.h>
# define __builtin_popcount __popcnt
# define __builtin_popcountll __popcnt64
#endif
typedef vector<bool> BaseFeature;
struct ChessStone {
ChessCoordId self_id; // Id of this stone
ChessCoordId next_id; // Use like link-list
ChessCoordId parent_id; // Use like union-find-set (rooted by tail)
// inline void SetSelfId(ChessCoordId id) { self_id = id; }
inline void Reset(ChessCoordId id = ChessComm::COORD_UNSET) {
next_id = parent_id = self_id;
}
} ;
class ChessEnv: public BaseEnv {
public:
ChessEnv();
// ChessEnv(const ChessEnv &ge);
~ChessEnv();
int Move(int action) override;
bool IsFinish() override { return ((state_ != 0 ? true : false) || is_resign_); }
void GetResult(float& res) override;
void GetFeature(BaseFeature& feature) override;
int GetActionNum() override;
void GetInputDim(vector<int>& input_dim) override;
void GetLegalAction(vector<int>& action) override;
bool IsLegal(int action) override { return ChessFunction::IsResign(action) || IsMoveValid(action); }
//std::string action2str(int action) override { return ChessFunction::IdToStr(const ChessCoordId action); }
std::string action2str(int action) override;
int CurrentPlayer() override { return current_player_; }
protected:
// void Init();
// void CopyFrom(const ChessEnv &src);
//int ChessResult(ChessCoordId x, ChessCoordId y) const;
int CalcResult() const;
ChessStoneColor GetWinner() const;
inline void HandOff() { current_player_ = Opponent(); }
inline ChessStoneColor Opponent(const ChessStoneColor color = ChessComm::COLOR_UNKNOWN) const {
return ChessComm::BLACK + ChessComm::WHITE
- (ChessComm::COLOR_UNKNOWN != color ? color : current_player_);
}
inline ChessStoneColor Self() const { return current_player_; }
inline ChessCoordId GetLastMove() const { return last_action_; }
// inline ChessStoneColor CurrentPlayer() const { return current_player_; }
//void ChessEnv::TransformCoord(ChessCoordId &x, ChessCoordId &y, int mode, bool reverse = false)
void GetSensibleMove();
bool IsSquareThreatened(ChessCoordId& id) const;
bool IsKingInCheck() const
void Find_Legal_Moves() const;
bool IsMoveValid(int& action) const;
protected:
// board utils
std::vector<std::int> action_list_;
ChessStone stones_[ChessComm::CHESSBOARD_SIZE];
ChessStoneColor board_state_[ChessComm::CHESSBOARD_SIZE];
ChessStoneColor current_player_;
int last_action_;
bool is_resign_;
int state_;
int material_;
// hash board state
std::unordered_set<uint64_t> board_hash_states_;
uint64_t zobrist_hash_value_;
// features
ChessSize move_count_[1073741824];
std::vector<std::string> feature_history_list_;
};
#include <iostream>
#include <stdlib.h>
#include "CBoard.h"
#include "ai.h"
/***************************************************************
* main
*
* This is where it all starts!
***************************************************************/
int main()
{
srand(time(0)); // Seed the random number generator.
CBoard board;
AI ai(board);
int judge = 0;
while (true) // Repeat forever
{
// Display board
std::cout << board;
std::cout << "Input command : ";
// Read input from player
std::string str;
getline(std::cin, str);
std::cout << std::endl;
// Parse input from player
if (std::cin.eof() || str == "quit")
{
exit(1);
}
if (str.compare(0, 5, "move ") == 0)
{
CMove move;
if (move.FromString(str.c_str()+5) == NULL)
{
// Could not parse move.
std::cout << "Try again. Use long notation, e.g. e2e4" << std::endl;
continue; // Go back to beginning
}
if (board.IsMoveValid(move))
{
board.make_move(move);
bool check = board.isOtherKingInCheck();
judge = board.isGameOver();
board.undo_move(move);
if (check)
{
std::cout << "You are in CHECK! Be serious!" << std::endl;
//continue;
}
/*if(judge == 1){
std::cout << "BLACK WIN!" << std::endl;
return 0;
}else if(judge == 2){
std::cout << "WHITE WIN!" << std::endl;
return 0;
}*/
std::cout << "You move : " << move << std::endl;
board.make_move(move);
if(judge == 1){
std::cout << "BLACK WIN!" << std::endl;
exit(1);
}else if(judge == 2){
std::cout << "WHITE WIN!" << std::endl;
exit(1);
}
}
else
{
std::cout << "Move " << move << " is not legal." << std::endl;
continue;
}
} // end of "move "
else if (str.compare(0, 2, "go") == 0)
{
CMove best_move = ai.find_best_move();
std::cout << "bestmove " << best_move << std::endl;
judge = board.isGameOver();
/*if(judge == 1){
std::cout << "BLACK WIN!" << std::endl;
return 0;
}else if(judge == 2){
std::cout << "WHITE WIN!" << std::endl;
return 0;
}*/
board.make_move(best_move);
if(judge == 1){
std::cout << "BLACK WIN!" << std::endl;
exit(1);
}else if(judge == 2){
std::cout << "WHITE WIN!" << std::endl;
exit(1);
}
} // end of "go"
else if (str == "show")
{
CMoveList moves;
board.find_legal_moves(moves);
// std::cout << moves.ToShortString() << std::endl;
std::cout << moves << std::endl;
}
else
{
std::cout << "Unknown command" << std::endl;
std::cout << "Valid commands are: quit, move, go, show" << std::endl;
}
} // end of while (true)
return 0;
} // end of int main()
main.o main.d : main.cc \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/iostream \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__config \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/pthread.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/ios \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/iosfwd \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/wchar.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/wchar.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/cdefs.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_symbol_aliasing.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_posix_availability.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/machine/_types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/_types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/Availability.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/AvailabilityVersions.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/AvailabilityInternal.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_null.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_size_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_mbstate_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/machine/types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_int8_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_int16_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_int32_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_int64_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_u_int8_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_u_int16_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_u_int32_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_u_int64_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_intptr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_uintptr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_ct_rune_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_rune_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_wchar_t.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/12.0.0/include/stdarg.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/stdio.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/stdio.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_stdio.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_va_list.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/stdio.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_ctermid.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_off_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_ssize_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/time.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_clock_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_time_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_timespec.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_wctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/__wctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_wint_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_wctype_t.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/ctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/ctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_ctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/runetype.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__locale \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/string \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/string_view \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__string \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/algorithm \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/initializer_list \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cstddef \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__cxx_version \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/12.0.0/include/stddef.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__nullptr \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/type_traits \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cstring \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/string.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/string.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_rsize_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_errno_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/strings.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/utility \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__tuple \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cstdint \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/stdint.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/12.0.0/include/stdint.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/stdint.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_uint8_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_uint16_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_uint32_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_uint64_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_intmax_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_uintmax_t.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__debug \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/typeinfo \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/exception \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cstdlib \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/stdlib.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/stdlib.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/wait.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_pid_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_id_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/signal.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/appleapiopts.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/machine/signal.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/signal.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/machine/_mcontext.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/_mcontext.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/mach/machine/_structs.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/mach/i386/_structs.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_attr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_sigaltstack.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_ucontext.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_sigset_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_uid_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/resource.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_timeval.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/machine/endian.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/endian.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_endian.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/libkern/_OSByteOrder.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/libkern/i386/_OSByteOrder.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/alloca.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/malloc/_malloc.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_dev_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_mode_t.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/math.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/math.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/limits \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__undef_macros \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/new \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/iterator \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__functional_base \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__functional_base_03 \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/tuple \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/stdexcept \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/atomic \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cassert \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/assert.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/functional \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__functional_03 \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/bit \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cstdio \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cwchar \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cwctype \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cctype \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/wctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/wctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_wctrans_t.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/mutex \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__mutex_base \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/chrono \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/ctime \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/ratio \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/climits \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/limits.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/12.0.0/include/limits.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/limits.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/machine/limits.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/limits.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/i386/_limits.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/syslimits.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/system_error \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__errc \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cerrno \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/errno.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/errno.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/errno.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__threading_support \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/pthread/sched.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/pthread/pthread_impl.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_cond_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_condattr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_key_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_mutex_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_mutexattr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_once_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_rwlock_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_rwlockattr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_pthread/_pthread_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/pthread/qos.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/qos.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_mach_port_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sched.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/locale.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/locale.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_locale.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_xlocale.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/_ctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/__wctype.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/_stdio.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/_stdlib.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/_string.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/_time.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/_wchar.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/stddef.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xlocale/_wctype.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/streambuf \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/istream \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/ostream \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/locale \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/nl_types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/types.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_u_char.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_u_short.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_u_int.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_caddr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_blkcnt_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_blksize_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_gid_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_in_addr_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_in_port_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_ino_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_ino64_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_key_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_nlink_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_useconds_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_suseconds_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fd_def.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fd_setsize.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fd_set.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fd_clr.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fd_zero.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fd_isset.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fd_copy.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fsblkcnt_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_fsfilcnt_t.h \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_types/_nl_item.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__bsd_locale_defaults.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/bitset \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__bit_reference \
CBoard.h \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector \
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__split_buffer \
CMove.h CSquare.h CMoveList.h ai.h
File added
File added
/*
* Filename: AI.cpp
* Author: Aaron Schraner
* Date: April 12, 2015
* Purpose: Artificial Intelligence member functions for connect 4 program
* CST 136
*/
#include "AI.h"
#include "Board.h"
//pick a spot and drop AI tile
void AI::runAI()
{
//try to find one-move wins first
if( (!SpecialAI(board->p2)) && (!SpecialAI(board->p1)))
NormalAI();
//if none are found, put a tile close to the last one
}
//log moves if desired
#ifdef LOGMOVES
void AI::runAI(std::vector<Move*> &v)
{
runAI();
v.push_back(new Move(lastX, lastY, board->p2));
}
#endif
//AI for cases where nobody can win in 1 move
void AI::NormalAI()
{
//if this isn't the first move
if(lastX>=0&&lastY>=0)
{
for(int i=travelDir;i<8;i++)
{
//try all directions adjacent to this tile, starting with
//the last successful direction
//if the spot I want is blank
if(board->relTo(lastX, lastY, i, 1)==' ')
{
//put a tile there and save the coordinates
lastX+=rtX[i];
lastY=board->drop(lastX, board->p2);
//save the direction
travelDir=i;
//exit the function
return;
}
}
}
//if a successful match wasn't found
{
do
{
//put it somewhere random, keep trying until either success
//or board fills up
srand(time(NULL)-randoff);
randoff++;
lastX = rand() % ( board->getWidth() );
} while(
(lastY=board->drop(lastX, board->p2)) == -1 && //repeat if placing fails
!board->full() ); //break if board is full
}
}
//AI for cases in which <player> can win in one move
bool AI::SpecialAI(char player)
{
Board bcopy(board->getHeight(), board->getWidth());
//create another board
//iterate through all columns
for(int x=0; x<board->getWidth(); x++)
{
for(int a=0; a<board->getWidth(); a++)
for(int b=0; b<board->getHeight(); b++)
bcopy.board[b][a]=board->board[b][a];
//copy the original board into the new one
int z=bcopy.drop(x,player); //try placing a tile in column i
if(bcopy.won(x,z,player)) //if that beat the game
{
board->drop(x,board->p2); //put my piece there
lastX=x;
lastY=z; //and save the coords
return true; //and exit
}
bcopy.clear();
}
return false; //if nothing beat the game in one move, return false
}
//did the AI just win?
bool AI::justWon()
{
return board->won(lastX, lastY, board->p2);
}
/*
* Filename: AI.h
* Author: Aaron Schraner
* Date: April 12, 2015
* Purpose: Artificial intelligence (solver)
* class definition for connect 4 program
* CST 136
*/
#ifndef AI_H
#define AI_H
#include "Board.h"
//for logging moves
#ifdef LOGMOVES
#include "Move.h"
#include <vector>
#endif
class AI
{
private:
Board* board; //board to operate on
int lastX, lastY; //hold last move
const int8_t rtX[8];
int randoff; //used to change random seed in less than clock resolution
int travelDir; //keep track of travel direction
public:
AI(Board *b): board(b), //set board
rtX{-1,0,1,-1,1,-1,0,1}, //init rtX
travelDir(0) {}; //set initial travel direction to left
void runAI(); //run AI on board
#ifdef LOGMOVES
void runAI(std::vector<Move*> &v); //run AI on board and log move
#endif
void NormalAI(); //AI when no one-move wins exist
bool SpecialAI(char player); //AI when game can be won or saved in one move
bool justWon(); //did I just win?
};
#endif
/*
* Filename: Board.cpp
* Author: Aaron Schraner
* Date: April 12, 2015
* Purpose: Board member functions for connect 4 program
* CST 136
*/
#include <iostream>
#include "Board.h"
using std::cout;
using std::endl;
using std::setw;
using std::left;
void Board::print()
{
//print number heading 1-width
for(int x=0;x<width;x++)
cout << "| " << setw(2) << left << x+1;
cout << "|" << endl;
//print divider line
for(int x=0;x<width;x++)
cout << "----";
cout << "-\n";
//print each row
for(int y=0;y<height;y++)
{
cout << "| ";
for(int x=0;x<width;x++)
cout << board[y][x] << " | ";
cout << "\n";
for(int x=0;x<width;x++)
cout << "----";
cout << "-\n";
}
}
void Board::clear()
{
for(int y=0;y<height;y++)
for(int x=0;x<width;x++)
board[y][x]=' ';
//reset entire board to spaces
}
Board::Board(int r, int c):height(r),width(c)
{
//allocate board
board = new char* [height];
for(int i = 0; i < height; i++)
board[i]=new char [width];
clear();
p1='X';
p2='O';
//access board with board[Y][X] for coordinate (X,Y)
}
Board::~Board()
{
//de-allocate board
for(int i=0; i<height; i++)
delete[] board[i];
delete board;
}
bool Board::place(int x, int y, char pc)
{
//attempt to place a tile at given coordinates
if(board[y][x]==' ')
{
board[y][x]=pc;
return true;
}
return false;
}
//returns the character relative to a point [x,y] in direction [op]
//that is [d] steps away (d=0 returns board[y][x])
char Board::relTo(int x, int y, int op, int d)
{
// | op directions
//\|/
//0 1 2
//3 X 4
//5 6 7
if(x<0||y<0||x>=width||y>=height)
return 0;
//if it's out of range, do nothing and fail
if(d<0)
{
//if distance is negative, make it positive and flip direction
op=(op+4)%4;
d=-d;
}
if(op>3)
{
//if op>3, use mathemagics to make it between 0 and 3
op=op%4;
d=-d;
}
if(d==0)
return board[y][x]; //if distance is 0
switch(op)
{
case 0: //up and left
if( y-d >= 0 && y-d < height && x-d >= 0 && x-d < width )
return board[y-d][x-d];
return 0;
case 1: //up and center
if(y-d>=0&&y-d<height)
return board[y-d][x];
return 0;
case 2: //up and right
if( y-d >= 0 && y-d < height && x+d >= 0 && x+d < width )
return board[y-d][x+d];
return 0;
case 3: //center and left
if(x-d>=0&&x-d<width)
return board[y][x-d];
return 0;
}
}
bool Board::won(int x, int y, char pc)
{
int depth=0;
int inDir[4]={0}; //how many pieces in a row:
//0: diagonally TL->BR
//1: vertically
//2: diagonally TR->BL
//3: horizontally
//first iterate through all 8 adjacent tiles
for(int i=0; i<8; i++)
//add the number of adjacent pieces in some direction
//to the proper inDir direction
for(int d=1;(d<WIN)&&(relTo(x,y,i,d)==pc);d++)
inDir[i%4]++;
//if some direction has more or greater than WIN-1 (usually 3) tiles, we have won
for(int i=0;i<4;i++)
if(inDir[i]>=WIN-1)
return true;
return false;
//otherwise, we have not.
}
//drop a piece in some column
int Board::drop(int col, char pc)
{
//if the column is full, fail.
if(board[0][col]!=' ')
return -1;
int i;
for(i=0;i<height&&board[i][col]==' ';i++);
board[--i][col]=pc; //otherwise put (pc) in the lowest empty spot
return i;
// ---IMPORTANT---
//returns the Y coordinate of where the tile was placed
}
int Board::getHeight() const
{
return height;
}
int Board::getWidth() const
{
return width;
}
//is the board full?
bool Board::full()
{
for(int x=0; x<width; x++)
for(int y=0;y<height;y++)
if(board[y][x]==' ')
return false;
//if any blank spaces are found, it can't be full
return true; //if none are found, it is full.
}
/*
* Filename: Board.h
* Author: Aaron Schraner
* Date: April 12, 2015
* Purpose: Board class for connect 4 program
* CST 136
*/
#ifndef BOARD_H
#define BOARD_H
#define WIN 4 //want to play connect 5?
#include <iostream>
#include <iomanip>
class Board
{
public:
Board(int r, int c); //constructor (rows,columns)
~Board(); //destructor
void print(); //display board
void clear(); //erase board
bool place(int x, int y, char pc); //place a tile
char p1; //player 1 (Human / X)
char p2; //player 2 (Computer / O)
bool won(int x, int y, char pc); //did this move win?
int drop(int col, char pc); //drop a piece at specified column
int getWidth() const; //return width
int getHeight() const; //return height
bool full(); //is the board full?
friend class AI; //so AI can access board and relTo
private:
char** board;
int height;
int width;
char relTo(int x, int y, int op, int d);
};
#endif
CC=g++
CFLAGS=-std=c++11 -DLOGMOVES
default:Connect4
Connect4:connectfour.cpp Board.h Board.cpp AI.h AI.cpp
$(CC) $(CFLAGS) -o Connect4 connectfour.cpp Board.cpp AI.cpp
run:Connect4
./Connect4
clean:
rm Connect4
/*
* Filename: Move.h (optional for connect4)
* Author: Aaron Schraner
* Date: April 12, 2015
* Purpose: Move class for connect 4 program move logging (useful for contests)
* CST 136
*/
#ifndef MOVE_H
#define MOVE_H
#include <iostream>
using std::cout;
using std::endl;
//Move class
//for keeping track of player and computer moves
class Move
{
private:
int x,y;
char piece;
public:
Move(int X, int Y, char P): x(X), y(Y), piece(P) {}
//construct move
//display move
void print()
{
cout << "[" << piece << "] (" << x << ", " << y << ")" << endl;
}
};
#endif
/*
Base class for environments of RL.
Following features:
Discrete and fix-size action space.
Used as:
Experiment environment;
Environment in Agents' mind
*/
#include <cstdlib>
#include <string>
class Connect4: public BaseEnv {
public:
Connect4();
~Connect4();
virtual int Move(int action) = 0;
virtual bool IsFinish() = 0;
virtual void GetResult(float& res) = 0;
virtual void GetFeature(BaseFeature& feature) = 0;
virtual void GetActionNum() = 0;
virtual void GetInputDim(vector<int>& input_dim) = 0;
virtual void GetLegalAction(vector<int>& action) = 0;
virtual bool IsLegal(int action) = 0;
virtual std::string action2str(int action) = 0;
//virtual void TransformFeatures(BaseFeature& feature, int transform_mode) = 0;
//virtual void TransformPolicy(int transform_mode) = 0; // this is reverse mode of TransformFeature
protected:
virtual void Init() = 0;
};
\ No newline at end of file
#include "connect4_comm.h"
#include <cstring>
#include <mutex>
// #include <glog/logging.h>
#define x first
#define y second
using namespace std;
using namespace Connect4Comm;
Connect4HashValuePair g_hash_weight[BORDER_SIZE_HEIGHT][BORDER_SIZE_LENGTH];
Connect4CoordId g_log2_table[67];
uint64_t g_zobrist_board_hash_weight[4][CONNECT4BOARD_SIZE];
uint64_t g_zobrist_player_hash_weight[4];
namespace Connect4Function {
bool InBoard(const Connect4CoordId id) {
return 0 <= id && id < CONNECT4BOARD_SIZE;
}
bool InBoard(const Connect4CoordId x, const Connect4CoordId y) {
return 0 <= x && x < BORDER_SIZE_HEIGHT
&& 0 <= y && y < BORDER_SIZE_LENGTH;
}
bool IsUnset(const Connect4CoordId id) {
return COORD_UNSET == id;
}
bool IsUnset(const Connect4CoordId x, const Connect4CoordId y) {
return COORD_UNSET == CoordToId(x, y);
}
bool IsResign(const Connect4CoordId id) {
return COORD_RESIGN == id;
}
bool IsResign(const Connect4CoordId x, const Connect4CoordId y) {
return COORD_RESIGN == CoordToId(x, y);
}
void IdToCoord(const Connect4CoordId id, Connect4CoordId &x, Connect4CoordId &y) {
if (COORD_RESIGN == id) {
x = y = COORD_RESIGN;
} else if (!InBoard(id)) {
x = y = COORD_UNSET;
} else {
x = id / BORDER_SIZE_LENGTH;
y = id % BORDER_SIZE_LENGTH;
}
}
Connect4CoordId CoordToId(const Connect4CoordId x, const Connect4CoordId y) {
if (COORD_RESIGN == x && COORD_RESIGN == y) {
return COORD_RESIGN;
}
if (!InBoard(x, y)) {
return COORD_UNSET;
}
return x * BORDER_SIZE_LENGTH + y;
}
void StrToCoord(const string &str, Connect4CoordId &x, Connect4CoordId &y) {
// CHECK_EQ(str.length(), 2) << "string[" << str << "] length not equal to 2";
x = str[0] - 'a';
y = str[1] - 'a';
if (!InBoard(x, y)) {
x = y = COORD_UNSET;
}
}
string CoordToStr(const Connect4CoordId x, const Connect4CoordId y) {
char buffer[3];
if (!InBoard(x, y)) {
buffer[0] = buffer[1] = 'z';
} else {
buffer[0] = x + 'a';
buffer[1] = y + 'a';
}
return string(buffer, 2);
}
std::string IdToStr(const Connect4CoordId id) {
Connect4CoordId x, y;
IdToCoord(id, x, y);
return CoordToStr(x, y);
}
Connect4CoordId StrToId(const std::string &str) {
Connect4CoordId x, y;
StrToCoord(str, x, y);
return CoordToId(x, y);
}
once_flag CreateGlobalVariables_once;
void CreateGlobalVariables() {
call_once(
CreateGlobalVariables_once,
[]() {
CreateHashWeights();
CreateQuickLog2Table();
CreateZobristHash();
}
);
}
void CreateHashWeights() {
g_hash_weight[0][0] = Connect4HashValuePair(1, 1);
for (Connect4CoordId i = 1; i < CONNECT4BOARD_SIZE; ++i) {
g_hash_weight[i / BORDER_SIZE_LENGTH][i % BORDER_SIZE_LENGTH] =
Connect4HashValuePair(g_hash_weight[(i - 1) / BORDER_SIZE_LENGTH][(i - 1) % BORDER_SIZE_LENGTH].x * g_hash_unit.x,
g_hash_weight[(i - 1) / BORDER_SIZE_LENGTH][(i - 1) % BORDER_SIZE_LENGTH].y * g_hash_unit.y);
}
}
void CreateQuickLog2Table() {
memset(g_log2_table, -1, sizeof(g_log2_table));
int tmp = 1;
for (Connect4CoordId i = 0; i < 64; ++i) {
g_log2_table[tmp] = i;
tmp *= 2;
tmp %= 67;
}
}
#if defined(_WIN32) || defined(_WIN64)
static int rand_r(unsigned int *seed)
{
unsigned int next = *seed;
int result;
next *= 1103515245;
next += 12345;
result = (unsigned int)(next / 65536) % 2048;
next *= 1103515245;
next += 12345;
result <<= 10;
result ^= (unsigned int)(next / 65536) % 1024;
next *= 1103515245;
next += 12345;
result <<= 10;
result ^= (unsigned int)(next / 65536) % 1024;
*seed = next;
return result;
}
#endif
void CreateZobristHash() {
uint32_t seed = 0xdeadbeaf;
for (int i = 0; i < 4; ++i) {
g_zobrist_player_hash_weight[i] = (uint64_t) rand_r(&seed) << 32 | rand_r(&seed);
for (int j = 0; j < CONNECT4BOARD_SIZE; ++j) {
g_zobrist_board_hash_weight[i][j] = (uint64_t) rand_r(&seed) << 32 | rand_r(&seed);
}
}
}
} // namespace Connect4Function
#undef y
#undef x
#include <inttypes.h>
#include <string>
#include <vector>
// Return code of functions should be "int"
typedef uint8_t Connect4StoneColor; // Stone color
typedef int16_t Connect4CoordId; // Stone IDs or coordinates
typedef int16_t Connect4Size; // Counts of visit times, used blocks, ..
namespace Connect4Comm {
const Connect4CoordId BORDER_SIZE_LENGTH = 12; // sxk_modify
const Connect4CoordId BORDER_SIZE_HEIGHT = 7;
const Connect4CoordId CONNECT4BOARD_SIZE = BORDER_SIZE_LENGTH * BORDER_SIZE_HEIGHT;
const Connect4CoordId COORD_UNSET = -2;
//const Connect4CoordId COORD_PASS = -1;
const Connect4CoordId COORD_RESIGN = -3;
const Connect4StoneColor EMPTY = 0;
const Connect4StoneColor BLACK = 1;
const Connect4StoneColor WHITE = 2;
const Connect4StoneColor WALL = 3;
const Connect4StoneColor COLOR_UNKNOWN = -1;
//const char *const COLOR_STRING[] = { "Empty", "Black", "White"};
const char *const COLOR_STRING[] = { "Empty", "Black", "White", "Wall" };
} // namespace Connect4Comm
namespace Connect4Feature {
const int SIZE_HISTORYEACHSIDE = 16;
const int SIZE_PLAYERCOLOR = 1;
const int STARTPOS_HISTORYEACHSIDE = 0;
const int STARTPOS_PLAYERCOLOR = STARTPOS_HISTORYEACHSIDE + SIZE_HISTORYEACHSIDE;
const int FEATURE_COUNT = STARTPOS_PLAYERCOLOR + SIZE_PLAYERCOLOR;
} // namespace Connect4Feature
namespace Connect4Function {
extern bool InBoard(const Connect4CoordId id);
extern bool InBoard(const Connect4CoordId x, const Connect4CoordId y);
extern bool IsUnset(const Connect4CoordId id);
extern bool IsUnset(const Connect4CoordId x, const Connect4CoordId y);
extern bool IsResign(const Connect4CoordId id);
extern bool IsResign(const Connect4CoordId x, const Connect4CoordId y);
extern void IdToCoord(const Connect4CoordId id, Connect4CoordId &x, Connect4CoordId &y);
extern Connect4CoordId CoordToId(const Connect4CoordId x, const Connect4CoordId y);
extern void StrToCoord(const std::string &str, Connect4CoordId &x, Connect4CoordId &y);
extern std::string CoordToStr(const Connect4CoordId x, const Connect4CoordId y);
extern std::string IdToStr(const Connect4CoordId id);
extern Connect4CoordId StrToId(const std::string &str);
extern void CreateGlobalVariables();
extern void CreateHashWeights();
extern void CreateQuickLog2Table();
extern void CreateZobristHash();
} // namespace Connect4Function
//typedef std::pair<Connect4CoordId, Connect4CoordId> Connect4Position;
typedef std::pair<uint64_t, uint64_t> Connect4HashValuePair;
extern Connect4HashValuePair g_hash_weight[Connect4Comm::BORDER_SIZE_HEIGHT][Connect4Comm::BORDER_SIZE_LENGTH];
const Connect4HashValuePair g_hash_unit(3, 7);
extern uint64_t g_zobrist_board_hash_weight[4][Connect4Comm::CONNECT4BOARD_SIZE];
extern uint64_t g_zobrist_player_hash_weight[4];
//state:统计棋局状态,0未分胜负,1黑胜,2白胜,3平局
//extern int state;
//extern int action_count;
extern Connect4CoordId g_log2_table[67];
#define FOR_EACHCOORD(id) for (Connect4CoordId id = 0; id < Connect4Comm::CONNECT4BOARD_SIZE; ++id)
#include "connect4_env.h"
#include <algorithm>
#include <cmath>
using namespace std;
using namespace Connect4Comm;
using namespace Connect4Function;
using namespace Connect4Feature;
Connect4Env::Connect4Env() {
CreateGlobalVariables();
FOR_EACHCOORD(i) {
stones_[i].self_id = i;
}
feature_history_list_.clear();
memset(board_state_, 0, sizeof(board_state_));
memset(legal_move_map_, 1, sizeof(legal_move_map_));
memset(move_count_, 0, sizeof(move_count_));
current_player_ = BLACK;
last_position_ = COORD_UNSET;
is_resign_ = false;
state_ = 0;
action_count_ = 0;
board_hash_states_.clear();
zobrist_hash_value_ = 0;
}
//Connect4Env::Connect4Env(const Connect4Env &ge) : Connect4Env() {
// CopyFrom(ge);
// }
Connect4Env::~Connect4Env() {
}
// void Connect4Env::CopyFrom(const Connect4Env &src) {
// *this = src;
// }
void Connect4Env::GetSensibleMove() {
// Add new feature plane
string plane;
// black
{
plane = "";
FOR_EACHCOORD(id) {
if (board_state_[id] == BLACK) {
plane += "1";
} else {
plane += "0";
}
}
feature_history_list_.push_back(plane);
}
// white
{
plane = "";
FOR_EACHCOORD(id) {
if (board_state_[id] == WHITE) {
plane += "1";
} else {
plane += "0";
}
}
feature_history_list_.push_back(plane);
}
memset(legal_move_map_, 0, sizeof(legal_move_map_));
Find_Legal_Moves();
}
int Connect4State::Move(int action) {
Find_Legal_Moves();
if (!IsLegal(action)) {
return -1;
}
if(IsResign(action)){
is_resign_ = true;
return 0;
}
last_position_ = to;
{
zobrist_hash_value_ ^= g_zobrist_player_hash_weight[Self()];
zobrist_hash_value_ ^= g_zobrist_player_hash_weight[Opponent()];
zobrist_hash_value_ ^= g_zobrist_board_hash_weight[Self()][action];
}
++move_count_[action];
board_state_[action] = Self();
++action_count_;
HandOff();
GetSensibleMove();
return 0;
}
void Connect4Env::Find_Legal_Moves() const{
Connect4CoordId i, j, id;
for(id = 0; id < Connect4Comm::CONNECT4BOARD_SIZE; id++){
legal_move_map_[id] = false;
}
for(j = 0; j < Connect4Comm::BORDER_SIZE_LENGTH; j++){
if(board_state_[Connect4Function::CoordToId(0, j)] != Connect4Comm::EMPTY){
continue;
}
for(i = 0;(i < Connect4Comm::BORDER_SIZE_HEIGHT && board_state_[Connect4Function::CoordToId(i, j)] == Connect4Comm::EMPTY); i++);
legal_move_map_[Connect4Function::CoordToId(--i, j)] = true;
}
}
int Connect4Env::dir_x() const{
static int angle = 135; //角度,从零开始,每次增加45度,135度的下一次回到零
if(angle < 135){
angle+=45;
}else{
angle = 0;
}
switch(angle){
case 0:
return 0;
break;
case 45:case 90:case 135:
return 1;
break;
default:
printf("error angle\n");
return 0;
break;
}
}
int Connect4Env::dir_y() const{
static int angle = 135; //角度,从零开始,每次增加45度,135度的下一次回到零
if(angle < 135){
angle+=45;
}else{
angle = 0;
}
switch(angle){
case 0: case 45:
return 1;
break;
case 90:
return 0;
break;
case 135:
return -1;
break;
default:
printf("error angle.\n");
return 0;
break;
}
}
int Connect4Env::Connect4Result(Connect4CoordId x, Connect4CoordId y) const{
Connect4StoneColor type; //如果最后落子为黑子,其为1,白子为2
int left_1[4] = {0,0,0,0}; //记录x轴反方相同棋子的个数
int right_1[4] = {0,0,0,0}; //记录x轴正方相同棋子的个数
int i, j;
int a, b;
if(action_count_ >= Connect4Comm::CONNECT4BOARD_SIZE){
state_ = 3;
}
if(is_resign_){
if(current_player_ == Connect4Comm::BLACK){
state_ = 2;
}else if(current_player_ == Connect4Comm::WHITE){
state_ = 1;
}
}
if(state_ != 0){ //如果游戏结束
return state_;
}
type = board_state_[Connect4Function::CoordToId(x, y)];
//type = current_player_;
for(i = 0; i < 4; i++){
j = 1; a = dir_x(); b = dir_y();
while((x + j * a < Connect4Comm::BORDER_SIZE_HEIGHT) && (y + j * b < Connect4Comm::BORDER_SIZE_LENGTH) && (x + j * a >= 0) && (y + j * b >= 0) && (board[Connect4Function::CoordToId(x + j * a, y + j * b)] == type)){ //当x轴正向的子与之相同时(前面的条件是为了保证不越界)
j++;
right_1[i]++;
}
j = 1;
while((x - j * a < Connect4Comm::BORDER_SIZE_HEIGHT) && (y - j * b <= Connect4Comm::BORDER_SIZE_LENGTH) && (x - j * a >= 0) && (y - j * b >= 0) && (board[Connect4Function::CoordToId(x - j * a, y - j * b)] == type)) //当x轴反向的子与之相同时
{
j++;
left_1[i]++;
}
}
for(i = 0; i < 4; i++){
if(type == Connect4Comm::WHITE){ //如果刚才为白棋落子,那么不进行禁手判断
if((left_1[i] + right_1[i]) >= 3){ //白棋只判断是否胜利
state_ = 2;
return state_;
}else{ //继续下一根轴检测
continue;
}
}else{ //如果是黑棋,需要考虑禁手状态
if((left_1[i] + right_1[i]) >= 3){ //胜利
state_ = 1; //将状态改为对应的棋子胜利
return state_; //结束函数
}
}
}
return state_;
}
int Connect4Env::CalcResult() const{
//Connect4StoneColor type;
Connect4CoordId x, y;
int result = 0;
FOR_EACHCOORD(i) {
if(board_state_[i] == Connect4Comm::EMPTY){
continue;
}else{
Connect4Function::IdToCoord(i, x, y);
result = Connect4Result(x, y);
if(result != 0){
return result;
}
}
}
return result;
}
Connect4StoneColor Connect4Env::GetWinner() const {
int result = CalcResult();
if (result == 3){
return Connect4Comm::EMPTY;
}else if (result == 1){
return Connect4Comm::BLACK;
}else if(result == 2){
return Connect4Comm::WHITE;
}
}
void Connect4Env::GetResult(float& res) {
if (GetWinner() == Connect4Comm::EMPTY){
res = 0.0f;
}else{
res = GetWinner() == CurrentPlayer() ? -1.0f : 1.0f;
}
}
vector<bool> Connect4Env::GetFeature(BaseFeature& feature) const { // HWC
feature.clear();
feature.resize(CONNECT4BOARD_SIZE * (SIZE_HISTORYEACHSIDE + 1));
// because push black into history first,
// if next player is black,
// we should get planes swap of each two planes
int reverse_plane = int(Self() == BLACK);
for (Connect4Size i = 0; i < SIZE_HISTORYEACHSIDE && i < feature_history_list_.size(); ++i) {
const string &feature_str = *(feature_history_list_.rbegin() + (i ^ reverse_plane));
for (int j = 0, k = i; j < CONNECT4BOARD_SIZE; ++j, k += (SIZE_HISTORYEACHSIDE + 1)) {
feature[k] = feature_str[j] - '0';
}
}
if (Self() == BLACK) {
for (int j = 0, k = SIZE_HISTORYEACHSIDE; j < CONNECT4BOARD_SIZE; ++j, k += (SIZE_HISTORYEACHSIDE + 1)) {
feature[k] = 1;
}
}
return feature;
}
int Connect4Env::GetActionNum() {//include RESIGN
return Connect4Comm::CONNECT4BOARD_SIZE + 1;
}
void Connect4Env::GetInputDim(vector<int>& input_dim) {
input_dim.clear();
input_dim.push_back(SIZE_HISTORYEACHSIDE);
input_dim.push_back(BORDER_SIZE_HEIGHT);
input_dim.push_back(BORDER_SIZE_LENGTH)
}
void Connect4Env::GetLegalAction(vector<int>& action) {
action.clear();
FOR_EACHCOORD(id) {
if (legal_move_map_[id]) {
action.push_back(id);
}
}
}
/*void Connect4Env::TransformCoord(Connect4CoordId &x, Connect4CoordId &y, int mode, bool reverse = false)
{
if (reverse) {
if (mode & 4) std::swap(x, y);
if (mode & 2) y = Connect4Comm::BORDER_SIZE_LENGTH - y - 1;
if (mode & 1) x = Connect4Comm::BORDER_SIZE_HEIGHT - x - 1;
} else {
if (mode & 1) x = Connect4Comm::BORDER_SIZE_HEIGHT - x - 1;
if (mode & 2) y = Connect4Comm::BORDER_SIZE_LENGTH - y - 1;
if (mode & 4) std::swap(x, y);
}
}*/
// void Connect4Env::TransformFeatures(BaseFeature& feature, int transform_mode) {
// BaseFeature ret(feature.size());
// int depth = features.size() / Connect4Comm::CONNECT4BOARD_SIZE;
// for (int i = 0; i < Connect4Comm::CONNECT4BOARD_SIZE; ++i) {
// Connect4CoordId x, y;
// Connect4Function::IdToCoord(i, x, y);
// TransformCoord(x, y, mode);
// int j = Connect4Function::CoordToId(x, y);
// for (int k = 0; k < depth; ++k) {
// ret[i * depth + k] = features[j * depth + k];
// }
// }
// feature = std::move(ret);
// }
// void TransformPolicy(int transform_mode) {
// }
#include "connect4_comm.h"
#include "base_env.h"
#include <cstdlib>
#include <cstring>
#include <stack>
#include <string>
#include <unordered_set>
#include <vector>
#if defined(_WIN32) || defined(_WIN64)
# include <intrin.h>
# define __builtin_popcount __popcnt
# define __builtin_popcountll __popcnt64
#endif
struct Connect4Stone {
Connect4CoordId self_id; // Id of this stone
Connect4CoordId next_id; // Use like link-list
Connect4CoordId parent_id; // Use like union-find-set (rooted by tail)
// inline void SetSelfId(Connect4CoordId id) { self_id = id; }
inline void Reset(Connect4CoordId id = Connect4Comm::COORD_UNSET) {
next_id = parent_id = self_id;
}
} ;
class Connect4Env: public BaseEnv {
public:
Connect4Env();
// Connect4Env(const Connect4Env &ge);
~Connect4Env();
int Move(int action) override;
bool IsFinish() override { return ((state_ != 0 ? true : false) || is_resign_); }
void GetResult(float& res) override;
void GetFeature(BaseFeature& feature) override;
int GetActionNum() override;
void GetInputDim(vector<int>& input_dim) override;
void GetLegalAction(vector<int>& action) override;
bool IsLegal(int action) override { return Connect4Function::IsResign(action) || legal_move_map_[action]; }
std::string action2str(int action) override { return Connect4Function::IdToStr(const Connect4CoordId action); }
int CurrentPlayer() override { return current_player_; }
// void TransformFeatures(BaseFeature& feature, int transform_mode);
// void TransformPolicy(int transform_mode); // this is reverse mode of TransformFeature
protected:
// void Init();
// void CopyFrom(const Connect4Env &src);
int Connect4Result(Connect4CoordId x, Connect4CoordId y) const;
int CalcResult() const;
Connect4StoneColor GetWinner() const;
inline void HandOff() { current_player_ = Opponent(); }
inline Connect4StoneColor Opponent(const Connect4StoneColor color = Connect4Comm::COLOR_UNKNOWN) const {
return Connect4Comm::BLACK + Connect4Comm::WHITE
- (Connect4Comm::COLOR_UNKNOWN != color ? color : current_player_);
}
inline Connect4StoneColor Self() const { return current_player_; }
inline Connect4CoordId GetLastMove() const { return last_position_; }
// inline Connect4StoneColor CurrentPlayer() const { return current_player_; }
//void Connect4Env::TransformCoord(Connect4CoordId &x, Connect4CoordId &y, int mode, bool reverse = false)
void GetSensibleMove();
void Find_Legal_Moves() const{
int dir_x() const;
int dir_y() const;
protected:
// board utils
Connect4Stone stones_[Connect4Comm::CONNECT4BOARD_SIZE];
Connect4StoneColor board_state_[Connect4Comm::CONNECT4BOARD_SIZE];
Connect4StoneColor current_player_;
Connect4CoordId last_position_;
bool is_resign_;
int state_;
int action_count_;
// hash board state
std::unordered_set<uint64_t> board_hash_states_;
uint64_t zobrist_hash_value_;
// features
bool legal_move_map_[Connect4Comm::CONNECT4BOARD_SIZE];
Connect4Size move_count_[Connect4Comm::CONNECT4BOARD_SIZE];
std::vector<std::string> feature_history_list_;
};
#include <stdio.h>
#include <math.h> //因为包含math.h,所以利用gcc进行编译的时候需要在最后加上 -lm 参数
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <iostream>
#define SIZE 15 //棋盘大小
#define CHARSIZE 3
using namespace std;
char initRecordBorard(); //初始化棋盘
void displayBoard(int s[SIZE][SIZE]); //显示棋盘函数,参数为棋盘上每一格的状态
void input_computer(int v[SIZE][SIZE]); //计算机落子,参数为棋盘上每一格的分值
void input_player(int s[SIZE][SIZE]); //玩家落子,参数为棋盘上每一格的状态
int score_calculator(int s[SIZE][SIZE],int mod); //计算各点的分值,并返回一个最大分数
void victory_judger(int s[SIZE][SIZE],int current_y,int current_x); //胜利与否判断
void settle_accounts(int state,char turn); //结算程序
void clear_string(void); //清空多余的无用的输入
void help(void); //显示可以使用的指令
void back(int n); //悔棋函数,输入为悔棋的步数
int dir_x(void); //返回x方向,如右45°时返回1,向上时为0,向左上时为-1,其中有一个静态变量,每调用一次,角度调转45°,由于只需要判断水平,竖直,左右倾斜,所以每调用4次为一个循环。
int dir_y(void); //返回y方向,功能同上。
int scan(int x,int y); //扫描以点(x+1,y+1)为中心5*5范围内的棋子个数
int calculation(int i,int j,int mod); //计算点(x+1,y+1)的分值
int score_attack(int left[4][4],int right[4][4]); //输入棋子周围的状态,计算进攻得分
int score_defense(int x,int y); //输入棋子位置,计算防守扣分
int score_add_to_defense(int x,int y); //输入棋子位置(x,y),计算防守加分
int score_step2(int x,int y); //输入棋子位置(x,y),计算第二步棋的加分
bool live_four(int left[4],int right[4]); //判断输入的是否为活四,是返回1,不是返回0
bool live_three(int left[4],int right[4]); //判断输入的是否为活三,是返回1,不是返回0
void Ban(int s[SIZE][SIZE]);
char turn; //先后手储存变量 turn '1'代表玩家先手 '2'代表电脑先手 '3'表示玩家对战
int state; //战局状态 0 表示平局 1 表示黑子胜利 -1 表示白子胜利 -2 表示平局 2 表示黑子禁手
int rd; //已落子总数
int s[SIZE][SIZE]; //记录棋盘上每一格的状态,前一个坐标表示行,后一个表示列,-1表示黑子,1表示白子
bool legal_move[SIZE][SIZE];
int v[SIZE][SIZE]; //记录棋盘上每一格的分值,前一个坐标表示行,后一个表示列
int l[SIZE*SIZE]; //记录每一步的落子,共SIZE*SIZE个位置,l[rd-1]为第rd颗子的坐标(l[rd-1]=current_x*SIZE+current_y)
int current_x; //记录上一步落子的横向位置,范围为0~SIZE-1
int current_y; //记录上一步落子的纵向位置,范围为0~SIZE-1
int x,y; //行号和列号
int xl,yl;
/*操作方式说明:开始选择游戏模式,1代表玩家先手,2代表电脑先手,3代表玩家对战,进入游戏中,直接输入对应坐标(如H10)即可,与此同时也可以输入对应指令:
输入 he 显示命令列表; 输入 ba 悔棋; 输入 en 结束游戏; 输入 re 重新开始游戏。游戏胜负判定后,输入y为继续一局新的游戏,输入别的东西为退出游戏。*/
//棋盘使用的是GBK编码,每一个中文字符占用2个字节。
//棋盘基本模板
//char aInitDisplayBoardArray[SIZE][SIZE*CHARSIZE+1] =
//char ca[] = "┏┯┯┯┯┯┯┯┯┯┯┯┯┯┓";
char aInitDisplayBoardArray[SIZE][SIZE*CHARSIZE+1] =
{
"┏┯┯┯┯┯┯┯┯┯┯┯┯┯┓",
"┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨",
"┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨",
"┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨",
"┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨",
"┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨",
"┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨",
"┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨",
"┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨",
"┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨",
"┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨",
"┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨",
"┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨",
"┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨",
"┗┷┷┷┷┷┷┷┷┷┷┷┷┷┛"
};
char aDisplayBoardArray[SIZE][SIZE*CHARSIZE+1]; //此数组用于显示棋盘
char play1Pic[]="●"; //正常的黑棋子状态
char play1CurrentPic[]="▲"; //刚落子的黑棋子状态
char play2Pic[]="◎"; //正常的白棋子状态
char play2CurrentPic[]="△"; //刚落子的白棋子状态
//main函数
int main()
{
restart: //restart从这里开始
turn=initRecordBorard();
if(turn=='1') //turn '1'代表玩家先手 '2'代表电脑先手 '3'表示玩家对战
{
while(state==0)
{
displayBoard(s);
input_player(s);
victory_judger(s,current_x,current_y);
switch(state)
{
case 50: //重启指令,输入re
goto restart;
break;
case 37: //结束指令,输入en
goto end;
break;
case 1:case -1:case -2: case 2: //胜负已分
goto end;
break;
default:
break;
}
computer_first: //电脑先手的人机对战将从这里开始执行
score_calculator(s,1); //人机对战
input_computer(v);
victory_judger(s,current_x,current_y);
}
}
else if(turn=='2')
goto computer_first;
else if(turn=='3') //玩家对战
{
while(state==0)
{
Ban(s);
displayBoard(s);
input_player(s);
victory_judger(s,current_x,current_y);
Ban(s);
switch(state)
{
case 50: //重启指令,输入re
goto restart;
break;
case 37: //结束指令,输入en
goto end;
break;
case 1:case -1:case -2: case 2: //胜负已分
goto end;
break;
default:
break;
}
displayBoard(s);
input_player(s);
victory_judger(s,current_x,current_y);
switch(state)
{
case 50: //重启指令,输入re
goto restart;
break;
case 37: //结束指令,输入en
goto end;
break;
case 1:case -1:case -2: case 2: //胜负已分
goto end;
break;
default:
break;
}
}
}
else
{
printf("Turn error!");
goto restart;
}
end: //在一个不断落子的循环中,直到一方胜利(即state改变),或者棋子数>=sIZE*sIZE,或者输入结束指令,会通过goto来到这里
settle_accounts(state,turn); //结算程序
displayBoard(s);
printf("Do you want to try again?(If yse, please enter y. If no, enter whatever you want.\n)");
if(getchar() == 'y')
{
clear_string();
goto restart;
}
return 0;
}
//初始化棋盘格局
char initRecordBorard(void)
{
int i,j;
extern int state; //战局状态
extern int rd; //已落子数
extern int s[SIZE][SIZE]; //记录棋盘上每一格的状态
extern int v[SIZE][SIZE]; //记录棋盘上每一格的分值
extern int current_x,current_y; //记录上一步落子
extern int l[SIZE*SIZE]; //记录每一步的落子
char turn;
state=0;
rd=0;
current_x=-1;
current_y=-1;
for(j=0;j<SIZE;j++) //通过双重循环,将s,v,l这三个数组清0
for(i=0;i<SIZE;i++)
{
s[i][j]=0;
v[i][j]=0;
l[SIZE*i+j]=0;
}
displayBoard(s);
printf("Who move first?(1 is you , 2 is me,\n and 3 is person_to_person.\n Enter 1 or 2 or 3.\n");
turn=getchar();
while(turn!='1' && turn!='2' && turn!='3')
{
printf("Wrong choice!\n");
turn=getchar();
}
if(getchar()!='\n')
{
printf("Wrong choice! Try again.\n");
clear_string();
turn=initRecordBorard();
}
system("clear"); //清屏
if (turn == '2')
{
srand(time(0));
switch(rand()%9+1) //电脑先手时,调用<time.h>里的库函数srand和rand,产生随机数,使得第一颗黑棋随机落在中心区域的九个位置之一
{
case 1:
v[6][6]=1; break;
case 2:
v[6][7]=1; break;
case 3:
v[6][8]=1; break;
case 4:
v[7][6]=1; break;
case 5:
v[7][7]=1; break;
case 6:
v[7][8]=1; break;
case 7:
v[8][6]=1; break;
case 8:
v[8][7]=1; break;
case 9:
v[8][8]=1; break;
default:
break;
}
}
else
;
return turn;
}
void displayBoard(int s[SIZE][SIZE]) //打印棋盘
{
extern int current_x; //记录上一步落子
extern int current_y; //记录上一步落子
extern int xl;
extern int yl;
extern int rd;
int i,j;
int xnow; //当前落子的行号
char ynow; //当前落子的列号
for(i=0;i<SIZE+1;i++) //将aInitDisplayBoardArray中记录的空棋盘,复制到aDisplayBoardArray中
for(j=0;j<(2*SIZE+1);j++)
aDisplayBoardArray[i][j]=aInitDisplayBoardArray[i][j];
for(i=0;i<SIZE;i++){ //扫描数组s,当遇到非0的元素,将●或者◎复制到aDisplayBoardArray的相应位置上
for(j=0;j<SIZE;j++)
{
switch(s[i][j])
{
case -2:
aDisplayBoardArray[SIZE-i-1][2*j]=play1CurrentPic[0];
aDisplayBoardArray[SIZE-i-1][2*j+1]=play1CurrentPic[1];
break;
case -1:
aDisplayBoardArray[SIZE-i-1][2*j]=play1Pic[0];
aDisplayBoardArray[SIZE-i-1][2*j+1]=play1Pic[1];
break;
case 2:
aDisplayBoardArray[SIZE-i-1][2*j]=play2CurrentPic[0];
aDisplayBoardArray[SIZE-i-1][2*j+1]=play2CurrentPic[1];
break;
case 1:
aDisplayBoardArray[SIZE-i-1][2*j]=play2Pic[0];
aDisplayBoardArray[SIZE-i-1][2*j+1]=play2Pic[1];
default:
break;
}
if(s[i][j]==-2)
s[i][j]=-1;
if(s[i][j]==2)
s[i][j]=1;
}
}
printf(" Work of :王晨曦\n"); //在棋盘上方显示“作者: ...”这句话
for(i=0;i<SIZE;i++)
printf("%3d%s\n",SIZE-i,aDisplayBoardArray[i]); //将aDisplayBoardArray输出到屏幕上
//输出最下面的一行字母A B ....
printf(" ");
for(i=0;i<SIZE;i++)
printf("%2c",'A'+i);
printf("\n");
ynow=yl+'A';
xnow=xl+1;
if(rd >= 1)
printf("My latest choice:%d %c\n",xnow,ynow); //输出当前落子的位置
else
;
}
void input_player(int s[SIZE][SIZE]) //玩家落子
{
extern int current_x;
extern int current_y;
extern int state;
extern int rd;
int y;
int x;
extern int v[SIZE][SIZE];
extern int l[SIZE*SIZE]; //记录每一步的落子
if(rd>=SIZE*SIZE)
{
state=-2; //平局
return;
}
printf("Which place would you like to choose?\n");
if(rd<=10)
printf("You could input H10 or anything like this.\n");
y=getchar()-'A'+1;
scanf("%d",&x);
if(y<=SIZE && y>=1 && x<=SIZE && x>=1 && getchar()=='\n') //输入的是正确的位置
{
if(s[x-1][y-1]==0)
{
current_x=x-1;
current_y=y-1;
l[rd]=current_x*SIZE+current_y;
switch(rd%2)
{
case 0:
s[x-1][y-1]=-1;
rd++;
v[x-1][y-1]=-1;
break;
case 1:
s[x-1][y-1]=1;
rd++;
v[x-1][y-1]=-1;
break;
default:
printf("rd error!\n");
break;
}
}
else
{
printf("You can't choose here.Be serious!\n");
input_player(s);
}
}
else if(y<=58 && y>=33) //如果输入的是指令的话,第一次gerchar()得到的应是一个小写字母,对应计算式得到y的值应在33到58中间
{
switch(y)
{
case 40: //h对应的数字,显示指令
help();
clear_string();
input_player(s); //重新落子
break;
case 50: //r对应的数字,重启游戏
state=50;
clear_string();
break;
case 34: //b对应的数字,悔棋
back(2); //悔两步棋,回到上一次落子
clear_string();
system("clear"); //清屏
displayBoard(s); //打印棋盘
input_player(s);
break;
case 37: //e对应的数字,结束游戏
state=37;
clear_string();
break;
default:
printf("Wrong instructions,enter 'he' to view optional instructions.\n");
clear_string();
input_player(s); //重新落子
break;
}
}
else
{
printf("Wrong choice!\n");
clear_string();
input_player(s);
}
}
void input_computer(int v[SIZE][SIZE]) //计算机落子
{
int i,j;
int max=-1,i_max,j_max;
extern int current_x;
extern int current_y;
extern int rd;
extern int s[SIZE][SIZE];
extern int l[SIZE*SIZE]; //记录每一步的落子
extern int state;
extern int xl,yl;
if (rd >= SIZE*SIZE)
{
state = -2; //平局
return;
}
for(i=0;i<=SIZE-1;i++)
{
for(j=0;j<=SIZE-1;j++)
{
if(v[i][j]>max)
{
max=v[i][j];
i_max=i;
j_max=j;
}
else
;
}
}
if(s[i_max][j_max]==0)
{
current_x=i_max;
current_y=j_max;
xl=i_max;
yl=j_max;
l[rd]=current_x*SIZE+current_y;
switch(rd%2)
{
case 0:
s[i_max][j_max]=-2;
rd++;
v[i_max][j_max]=-1;
break;
case 1:
s[i_max][j_max]=2;
rd++;
v[i_max][j_max]=-1;
break;
default:
printf("rd error!\n");
break;
}
}
else
printf("I seems stucked.\n");
}
void help(void)
{
printf("输入\'ba\'悔棋 \t 输入\'en\'结束游戏 \t 输入\'re\'重新开始游戏 \n");
}
void back(int n) //悔棋,输入为悔棋的步数
{
extern int rd; //已落子数
extern int s[SIZE][SIZE]; //记录棋盘上每一格的状态
extern int v[SIZE][SIZE]; //记录棋盘上每一格的分值
extern int current_x; //记录上一步落子
extern int current_y; //记录上一步落子
extern int l[SIZE*SIZE]; //记录每一步的落子
int i;
for(i=0;i<n;i++)
{
s[l[rd-1-i]/SIZE][l[rd-1-i]%SIZE]=0; //状态清零
v[l[rd-1-i]/SIZE][l[rd-1-i]%SIZE]=0; //值清零
}
rd-=n; //局数减少
current_x=l[rd-1]/SIZE;
current_y=l[rd-1]%SIZE;
Ban(s);
}
void clear_string() //清空多余的无用的输入
{
char c;
while((c=getchar())!='\n')
;
}
/* 接下来的部分是整个程序的核心部分,也是最复杂的部分,内部多次错综复杂的多次调用很容易把人绕晕,于是我在此进行一些概括性的说明:
1.分数运算的大体思路:通过调用score_calculator,输入s[SIZE][SIZE]为整个棋盘的棋子状态,-1为黑子,1为白子,0为空,同时输入mod为1,正常计算这个棋盘上所有点的分值,
进入之后,它将进行点的筛选,滤去不需要考虑的点,留下我们需要的,并通过调用calculation函数,输入点的横纵坐标和mod4(这个为最后设计好的综合性算法,一个点的分值由
这一点的进攻得分,这一点的防守得分,这一点的防守疏漏扣分和这一点的第二步期望分数构成,具体比例为1,0.8,-0.7,0.6)进行这一点的分数计算,所有点计算完毕之后寻找并
返回分数最大值。
2.除上面的所提到的mod外,其它mod都是为了节省程序长度方便调用以实现相应功能而设计的,初次读时其实可以略过它们,在之后程序调用时都有些它们相应的含义,对号入座即可。
3.虽说一个点的得分由4个分数构成,但它们其实都是通过计算score_attack而得来:进攻得分为直接计算这一点的score_attack;防守得分为跳过己方落子,敌方的棋子落在这一点的
score_attack;防守疏忽扣分为自己将棋子落在这里,敌方下一颗棋子的最高score_attack;第二步的期望分数为这一步落子在这一点,下一步对手采用calculation的mod1(一个注重
防守的计算方式)进行落子,之后如果我们仍能形成双三、双四、三四、活四,甚至是直接胜利,那么给予这个点一个不少的加分。
4.score_attack的计算中引入了我自己的概念:meaningful_pieces——有意义的棋子数。这个函数的输入为棋子四个方向上周围的八颗棋子的状态,之后对每一个方向上的有意义的棋
子数进行判断,再根据有意义棋子数的多少给予相应的进攻得分。没有简单地对每一种情况进行分析,而是采取一种抽象的计算方式,是由于设计初期没有想明白要如何
分别讨论每一种情况,后期又觉得那本身太过麻烦,还容易出现疏漏,这样的计算方式得出来的结果也还不错,于是继续沿用了下去。
*/
void victory_judger(int s[SIZE][SIZE],int x,int y) //判断胜负(以第i行第j列为中心判断)
{
extern int state; //该变量用于改写棋盘状态
extern int rd; //该变量用于判断最后落子的是黑棋还是白棋
int type; //如果最后落子为黑子,其为1,白子为2
int i, j;
int a, b;
int left_1[4] = {0,0,0,0}; //记录x轴反方相同棋子的个数
int right_1[4] = {0,0,0,0}; //记录x轴正方相同棋子的个数
if(rd >= SIZE * SIZE){
state = -2;
}
if(state != 0){ //如果游戏结束
return;
}
switch(rd%2)
{
case 1:
type=-1;
break;
case 0:
type=1;
break;
default:
printf("error rd.");
break;
}
for(i = 0; i < 4; i++){
j = 1; a = dir_x(); b = dir_y();
while((x + j * a < SIZE) && (y + j * b < SIZE) && (x + j * a >= 0) && (y + j * b >= 0) && (s[x + j * a][y + j * b] == type)){ //当x轴正向的子与之相同时(前面的条件是为了保证不越界)
j++;
right_1[i]++;
}
j = 1;
while((x - j * a < SIZE) && (y - j * b <= SIZE) && (x - j * a >= 0) && (y - j * b >= 0) && (s[x - j * a][y - j * b] == type)) //当x轴反向的子与之相同时
{
j++;
left_1[i]++;
}
}
for(i = 0; i < 4; i++){
if(rd % 2 == 0){ //如果刚才为白棋落子,那么不进行禁手判断
if((left_1[i] + right_1[i]) >= 3){ //白棋只判断是否胜利
state = -1;
return;
}else{ //继续下一根轴检测
continue;
}
}else{ //如果是黑棋,需要考虑禁手状态
if((left_1[i] + right_1[i]) >= 3){ //胜利
state = 1; //将状态改为对应的棋子胜利
return; //结束函数
}
}
}
if(!legal_move[x][y] && rd % 2 == 0){
state = 1;
}
if(!legal_move[x][y] && rd % 2 != 0){
state = -1;
}
return;
}
void settle_accounts(int state,char turn) //结算程序 ***这个程序在main函数中只调用一次,当程序判断某一方胜利,或棋盘已经落满或玩家终止游戏时,程序会直接通过goto跳转到这个函数开始运行
{
extern int rd;
if(state==-2) //如果是平局
printf("Our match ended in a draw!\n");
else if(state==2)
printf("Black ban, and White victory!\n");
else if(turn=='1')
{
if(state==1)
switch(rd/25)
{
case 0:case 1:case 2:case 3:
case 4:case 5: case 6:
printf("Game over,and you win.\n");
break;
default:
printf("You win!\n");
break;
}
else if(state==-1)
switch(rd/25)
{
case 0:case 1:case 2:case 3:
case 4:case 5: case 6:
printf("Game over,and I win.\n");
break;
default:
printf("I win!\n");
break;
}
else
printf("I don't want to say anything else......\n");
}
else if(turn=='2') //如果为电脑先手,立场对转,继续使用上面的话语
{
state=-state;
turn='1';
settle_accounts(state, turn);
}
else if(turn=='3')
{
if(state==1)
printf("The black win!\n");
else if(state==-1)
printf("The white win!\n");
else
;
}
else
;
}
int dir_x(void)
{
static int angle=135; //角度,从零开始,每次增加45度,135度的下一次回到零
if(angle<135)
angle+=45;
else
angle=0;
switch(angle)
{
case 0:
return 0;
break;
case 45:case 90:case 135:
return 1;
break;
default:
printf("error angle\n");
return 0;
break;
}
}
int dir_y(void)
{
static int angle=135; //角度,从零开始,每次增加45度,135度的下一次回到零
if(angle<135)
angle+=45;
else
angle=0;
switch(angle)
{
case 0: case 45:
return 1;
break;
case 90:
return 0;
break;
case 135:
return -1;
break;
default:
printf("error angle.\n");
return 0;
break;
}
}
int scan(int x,int y) //扫描以点(x+1,y+1)为中心5*5范围内的棋子个数
{
extern int s[SIZE][SIZE];
int i,j;
int val=0; //返回值
for(i=0;i<5;i++)
for(j=0;j<5;j++)
if(x-2+i>=0 && x-2+i<=SIZE-1 && y-2+j>=0 && y-2+j<=SIZE-1) //如果在界内
if(s[x-2+i][y-2+j]==-1 || s[x-2+i][y-2+j]==1)
val++;
return val;
}
bool live_four(int left[4],int right[4]) //判断输入的序列是否是活四,这里略去了两头四四的情况没有考虑,不过这里的活四只是为了判断是否为活三而准备,如果已经是两头四四的话那已经形成了禁手,是否是活三变得没有意义
{
int type = -1; //需要判断的只有黑子
int i,j;
int a,b; //a为一变量,b为临时储存a的值
int left_1 = 0; //记录左方相同子的个数
int right_1 = 0; //记录右方相同子的个数
int count = 0; //统计可以形成5的点数
/*先判断一下是否还没放子的时候就已经是5颗了*/
for(j = 0; j < 4 && right[j] == type; j++){ //当右边的子与之相同时(前面的条件是为了保证不越界)
right_1++;
}
for(j = 0; j < 4 && left[j] == type; j++){ //当左边的子与之相同时(前面的条件是为了保证不越界)
left_1++;
}
if(left_1 + right_1 == 4){ //如果已经五连,那么不是活四,返回0,如果没有五连,什么也不做
return false;
}
for(a = 0; a < 8; a++){
left_1 = 0;
right_1 = 0;
if(a < 4){ //将left和right上的0依次改为type再判断是否形成五连,形成则可形成五连的点加1,注:这里的0是初始化给的0而非EMPTY,a<4是统计left
b = a;
if(left[a] == 0){
left[a] = type;
}else{
continue;
}
}else if(a >= 4){//a>=4是统计right
b = a;
a-=4;
if(right[a] == 0){
right[a] = type;
}else{
a = b;
continue;
}
}
for(j = 0; j < 4 && right[j] == type; j++){ //当左边的子与之相同时(前面的条件是为了保证不越界)
right_1++;
}
for(j = 0; j < 4 && left[j] == type; j++){ //当左边的子与之相同时(前面的条件是为了保证不越界)
left_1++;
}
if(left_1 + right_1 == 4){ //如果形成五连
count++;
}
if(b < 4){ //将改的值改回去
left[a] = 0;
}
else if(b >= 4){
right[a] = 0;
}
a = b;
}
if(count == 2){
return true;
}else{
return false;
}
}
bool live_three(int left[4],int right[4]) //判断是否为活三
{
int type = -1; //因为白棋不用判断,所以必为黑棋
int i,j;
int a,b; //a为一变量,b为临时储存a的值
if(live_four(left, right)){ //已经是活四,就不再是活三了
return false;
}
for(a = 0; a < 8; a++){
if(a < 4){ //将left和right上的0依次改为type再判断是否形成活四,注:这里的0是初始化给的0而非EMPTY,a<4是统计left
b = a;
if(left[a] == 0){
left[a] = type;
}else{
continue;
}
}else if(a >= 4){//a>=4是统计right
b = a;
a-=4;
if(right[a] == 0){
right[a] = type;
}else{
a = b;
continue;
}
}
if(live_four(left,right)){ //如果加一步之后形成活四,那么是活三
if(b < 4){ //将改的值改回去
left[a] = 0;
}else if(b >= 4){
right[a] = 0;
}
return true;
}else {
if(b < 4){ //将改的值改回去
left[a] = 0;
}else if(b >= 4){
right[a] = 0;
}
}
a = b;
}
return false;
}
void Ban(int s[SIZE][SIZE]){
int i, j;
for(i = 0; i < SIZE; i++){
for(j = 0; j < SIZE; j++){
legal_move[i][j] = false;
}
}
for(j = 0; j < SIZE; j++){
if(s[0][j] != 0){
printf("j = %d,board:%d,this col is full!!!!\n",j,s[14][j]);
continue;
}
for(i = 0;(i < SIZE && s[i][j] == 0); i++);
legal_move[--i][j] = true;
printf("after1: i = %d, j = %d,legal:%d,board:%d\n",i,j,legal_move[i][j],s[i][j]);
}
for(i = 0; i < SIZE; i++){
for(j = 0; j < SIZE; j++){
printf("after2: i = %d, j = %d,legal:%d,board:%d\n",i,j,legal_move[i][j],s[i][j]);
}
}
}
int score_calculator(int s[SIZE][SIZE],int mod) //计算所有点的分值,mod1为正常的分数计算,mod2为计算并返回最高的进攻分值,mod3为score_step2中己方第一次落子后,对手通过calculation的mod1(偏防守型的综合计算方式)得到v_d并依据其进行落子,mod4计算最高的进攻得分(但加入了判断是否胜利,如果胜利的话会给一个高分)
{
extern int v[SIZE][SIZE];
int i,j;
int max_score=0;
int v_d[SIZE][SIZE]; //为了储存score_defense或score_step2的值而创建的临时数组
for(i=0;i<SIZE;i++) //初始化数组v_d
for(j=0;j<SIZE;j++)
v_d[i][j]=0;
for(i=0;i<SIZE;i++)
for(j=0;j<SIZE;j++)
{
if(s[i][j]==-1 || s[i][j]==1) //如果此处已经落子,跳过此点分值计算
continue;
else
;
if(scan(i,j)<1) //如果以这点为中心5*5的范围内没有棋子,我们不计算它
continue;
else
;
if(mod==1)
v[i][j]=calculation(i,j,4); //使用最后的综合算法计算这一点的分值
else if(mod==2)
v_d[i][j]=calculation(i,j,2); //计算这点的进攻分
else if(mod==3)
v_d[i][j]=calculation(i,j,1); //利用偏防御性的综合算法进行计算
else if(mod==4) //mod4时,先判断落子在此处是否会胜利,不会的话再进行分数计算
{
rd++;
victory_judger(s,i,j);
if(state!=0)
{
if(state==pow(-1,rd%2+1)) //如果己方胜利
v_d[i][j]=499999;
else
v_d[i][j]=-499999; //如果碰到禁手
state=0;
rd--;
}
else
{
rd--;
v_d[i][j]=calculation(i,j,2);
}
}
}
for(i=0;i<SIZE;i++) //寻找最大值并返回
for(j=0;j<SIZE;j++)
{
if(mod==1)
{
if(v[i][j]>max_score)
max_score=v[i][j];
else
;
}
else if(mod==2 || mod==4)
{
if(v_d[i][j]>max_score)
max_score=v_d[i][j];
else
;
}
}
if(mod==3)
{
input_computer(v_d);
return 0;
}
return max_score;
}
int calculation(int x,int y,int mod) //计算点(x+1,y+1)的分值
{
extern int s[SIZE][SIZE];
int left[4][4]={ {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0} }; //用来储存这个点四个方向左边的棋子状态
int right[4][4]={ {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0} }; //用来储存这个点四个方向右边的棋子状态
int a,b;
int i,j;
int score;
for(i=0;i<4;i++) //将点(x+1,y+1)水平,右斜,竖直,左斜的方向上4个棋子的状态读入上面两个数组中
{
a=dir_x(); b=dir_y();
for(j=1;j<5;j++)
{
if(x+j*a<=SIZE-1 && x+j*a>=0 && y+j*b<=SIZE-1 && y+j*b>=0) //如果这颗子在边界内
{
right[i][j-1]=s[x+j*a][y+j*b];
}
else
right[i][j-1]=-2; //如果不在边界内
if(x-j*a<=SIZE-1 && x-j*a>=0 && y-j*b<=SIZE-1 && y-j*b>=0) //如果这颗子在边界内
{
left[i][j-1]=s[x-j*a][y-j*b];
}
else
left[i][j-1]=-2; //如果不在边界内
}
}
switch(mod) //用mod来区分计算总分数和防守分数,mod1为总分,mod2为防守分数
{
case 1:
score=score_attack(left,right)+0.8*(score_add_to_defense(x,y))-0.7*(score_defense(x,y)); //较为偏重防守的算法
return score;
break;
case 2: case 3:
return score_attack(left,right);
break;
case 4:
score=score_attack(left,right)+0.8*(score_add_to_defense(x,y))-0.7*(score_defense(x,y))
+0.6*score_step2(x,y); //最后使用的综合算法
return score;
break;
default:
printf("wrong mod.\n");
break;
}
}
int score_attack(int left[4][4],int right[4][4]) //输入棋子周围的状态,计算进攻得分
{
extern int rd; //为了分辨棋子的种类
int i,j;
float a,b;
int type; //如果最后落子为黑子,其为-1,白子为1
float meaningful_pieces[4]={0,0,0,0};
int fo_l[4],fo_r[4]; //为上面数组中第一个其它棋子或是边界外的位置
int score=0; //分值
int left_ex[4][6]; //为了扩展left和right数组的大小,以实现一种统一,方便用循环来判断,以减少程序的长度
int right_ex[4][6];
int count[5]={0,0,0,0,0}; //统计有效棋子大于等于0、1、2、3、4的方向
int le[4]={0,0,0,0},ri[4]={0,0,0,0}; //对左右两边的状态进行编码,百位与fo_l/fo_r的值相同,剩下的0和1按二进制来编码,left[i][0]的权为8,left[i][3]的权为1,加入此编码的目的是为了解决c语言无法将两数组直接比较,于是换一种方便的表示方式来比较他们。
switch(rd%2) //如果最后落子为黑子,本次应下的为白子,故type为1,最后落子为白子,那么type为-1
{
case 1:
type=1;
break;
case 0:
type=-1;
break;
default:
printf("error rd.");
break;
}
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
if(left[i][j]!=type && left[i][j]!=0) //如果不是相同棋子也不是空位的话
{
fo_l[i]=j; //第一个其它棋子,或是边界外
break;
}
if(j==4) //如果四个都没有对手的棋子的话,空间充足
fo_l[i]=j;
for(j=0;j<4;j++)
if(right[i][j]!=type && right[i][j]!=0) //如果不是相同棋子也不是空位的话
{
fo_r[i]=j; //第一个其它棋子,或是边界外
break;
}
if(j==4) //如果四个都没有对手的棋子的话,空间充足
fo_r[i]=j;
if(fo_l[i]+fo_r[i]<=3) //两个对手的棋子之间的间隔小于等于4,没有意义
continue;
left_ex[i][0]=type;
right_ex[i][0]=type;
for(j=0;j<4;j++) //将left和right的值复制到ex数组里
{
left_ex[i][j+1]=left[i][j];
right_ex[i][j+1]=right[i][j];
}
left_ex[i][5]=-type;
right_ex[i][5]=-type;
for(j=0;j<fo_l[i];j++)
{
if(fo_r[i]==0)
meaningful_pieces[i]-=0.75; //如果反向第一颗是对手棋子或者边界的话,有意义棋子数减0.75
if(left[i][j]==type)
{
if(left_ex[i][j]==type && (left_ex[i][j+2]==type || left_ex[i][j+2]==0)) //如果这个棋子的右一个为相同棋子,且左边没有边界或对手棋子,那么这个棋子为一个有意义的棋子
meaningful_pieces[i]++;
else //如果左边有棋子,右边有边界或者对手棋子,这个棋子为0.25个有意义的棋子
{
a=1; //定义为这个棋子的价值
if(left_ex[i][j]==0) //如果左边为空的,它的价值变为一半
a*=0.5;
if(left_ex[i][j+2]==-type || left_ex[i][j+2]==-2) //如果右边为边界或对手棋子,它的价值变为四分之一
a*=0.25;
if(left_ex[i][j]==0 && left_ex[i][j-1]==0) //如果空了两个格,a的值变为0.05,由于0的左边必定为相同子,所以不必担心此越界问题
a*=0.1;
meaningful_pieces[i]+=a; //将这个棋子的值加上
}
}
}
for(j=0;j<fo_r[i];j++)
{
if(fo_l[i]==0)
meaningful_pieces[i]-=0.75; //如果反向第一颗是对手棋子或者边界的话,有意义棋子数减0.75
if(right[i][j]==type)
{
if(right_ex[i][j]==type && (right_ex[i][j+2]==type || right_ex[i][j+2]==0)) //如果这个棋子的左一个为相同棋子,且右边没有边界或对手棋子,那么这个棋子为一个有意义的棋子
meaningful_pieces[i]++;
else //如果右边有棋子,或左边有边界或者对手棋子.
{
b=1; //定义为这个棋子的价值
if(right_ex[i][j]==0) //如果右边为空的,它的价值变为一半
b*=0.5;
if(right_ex[i][j+2]==-type || right_ex[i][j+2]==-2) //如果左边为边界或对手棋子,它的价值变为四分之一
b*=0.25;
if(right_ex[i][j]==0 && right_ex[i][j-1]==0) //如果空了两个格,a的值变为0.05,由于0的右边必定为相同子,所以不必担心此越界问题
b*=0.1;
meaningful_pieces[i]+=b; //将这个棋子的值加上
}
}
}
}
for(i=0;i<4;i++) //统计4个方向中有意义棋子数大于等于0、1、2、3、4的个数
{
if(meaningful_pieces[i]>0)
count[0]++;
for(j=0;j<4;j++)
if(meaningful_pieces[j]>=(i+1))
count[i+1]++;
}
for(i=0;i<4;i++) //用le和ri对左右两边的状态进行编码,百位与fo_l/fo_r的值相同,剩下的0和1按二进制来编码,left[i][0]的权为8,left[i][3]的权为1,加入此编码的目的是为了解决c语言无法将两数组直接比较,于是换一种方便的表示方式来比较他们。
{
for(j=0;j<fo_l[i];j++)
le[i]+=abs(left[i][j])*pow(2,3-j); //剩下的0和1按二进制来编码,left[i][0]的权为8,left[i][3]的权为1
le[i]+=100*fo_l[i]; //百位与fo_l/fo_r的值相同
}
for(i=0;i<4;i++) //用le和ri对左右两边的状态进行编码,百位与fo_l/fo_r的值相同,剩下的0和1按二进制来编码,right[i][0]的权为8,right[i][3]的权为1,加入此编码的目的是为了解决c语言无法将两数组直接比较,于是换一种方便的表示方式来比较他们。
{
for(j=0;j<fo_r[i];j++)
ri[i]+=abs(right[i][j])*pow(2,3-j); //剩下的0和1按二进制来编码,right[i][0]的权为8,right[i][3]的权为1
ri[i]+=100*fo_r[i]; //百位与fo_l/fo_r的值相同
}
for(i=0;i<4;i++) //为因为上面简洁算法而被低估的一些状况进行修正
{
if(le[i]==406 && right[i][0]==0 && meaningful_pieces[i]<2) //XXX0A0AA0情形且meaningful_pieces小于2的情况,下同,X表示任意,0表示空,A表示我方棋子,B表示对方棋子
count[2]++;
if(ri[i]==406 && left[i][0]==0 && meaningful_pieces[i]<2)
count[2]++;
if(le[i]==108 && ri[i]==306) //XXBAA0AAB情况 下同
count[2]++;
if(le[i]==306 && ri[i]==108)
count[2]++;
if(le[i]==108 && ri[i]==310) //XXBAAA0AB情况 下同
count[2]++;
if(le[i]==310 && ri[i]==108)
count[2]++;
}
score=10*count[0]+100*count[1]+1000*count[2]+10000*count[3]+100000*count[4];
return score;
}
int score_defense(int x,int y) //输入棋子坐标,计算防守扣分
{
extern int v[SIZE][SIZE];
extern int s[SIZE][SIZE];
extern int rd;
extern int state;
int de_score;
switch(rd%2) //手动落子
{
case 0:
s[x][y]=-1;
rd++;
break;
case 1:
s[x][y]=1;
rd++;
break;
default:
printf("error rd.\n");
break;
}
de_score=score_calculator(s,2); //调用分数计算程序的mod2来计算防守分数
victory_judger(s,x,y);
if(state!=0) //如果我方落子后胜利了,给这个点一个大量的加分
{
if(state==pow(-1,rd%2+1))
de_score=-999999; //赋值,为加分,所以为负值
else //我方落在了禁手上
de_score=999999; //给一个大扣分
state=0; //将state重置
}
rd--; //归位
s[x][y]=0;
return de_score;
}
int score_add_to_defense(int x,int y) //输入棋子坐标,计算防守加分
{
extern int rd;
extern int state;
int de_score;
rd++;
de_score=calculation(x,y,3); //调用分数计算程序的mod3来计算这一点的防守分数
rd--;
victory_judger(s,x,y); //如果对方落子后胜利了,那么给这点一个大量的防守加分,由于本程序用于在落子后计算,所以在落子就计算时不需要加rd
if(state!=0)
{
if(state==pow(-1,rd%2+1)) //对手胜利,给一个大防守加分
de_score=999999; //赋值
else
de_score=-999999; //对手碰到禁手,不防守这点,减分
state=0;
}
return de_score;
}
int score_step2(int x,int y)
{
extern int v[SIZE][SIZE];
extern int s[SIZE][SIZE];
extern int rd;
extern int state;
extern int current_x; //记录上一步落子
extern int current_y; //记录上一步落子
extern int l[SIZE*SIZE]; //记录每一步的落子
int step2_score;
int i;
v[x][y]=9999999;
input_computer(v);
score_calculator(s,3); //mod3状态下的权衡分数计算偏防守,如果在对面防守了的情况下,我们的第二步仍能够胜利、形成活四、形成双三等,给予对应的加分
//本应放在这里进行的落子由于无法读取v_d而放在了score_calculator中
step2_score=score_calculator(s,4); //利用mod4计算最高的进攻得分并判断是否会胜利
i=0;
s[l[rd-1-i]/SIZE][l[rd-1-i]%SIZE]=0; //状态清零
i=1;
s[l[rd-1-i]/SIZE][l[rd-1-i]%SIZE]=0; //状态清零
rd-=2; //局数减少
if(step2_score>2000)
return step2_score;
else
return 0;
}
/*
* Filename: connectfour.cpp
* Author: Aaron Schraner
* Date: April 12, 2015
* Purpose: connect 4 program implementation
* CST 136
*/
#include <iostream>
#include <iomanip>
#include <stdlib.h>//
#include <time.h> // for rand()
#include "Board.h"
#include "AI.h"
//define LOGMOVES if you want to know who moved where at the end
#ifdef LOGMOVES
#include "Move.h"
#include <vector>
#endif
using namespace std;
void promptForSize(int& height, int& width)
{
height=0;
width=0;
//initialize so we don't exit the loop due to garbage
do
{
cout << "Enter the board height (must be greater than 3)\n> ";
cin >> height;
}
while(height<4);
do
{
cout << "Enter the board width (must be greater than 3)\n> ";
cin >> width;
}
while(width<4);
//prompt for and store width and height
}
int main()
{
#ifdef LOGMOVES
cout << "Moves will be logged.\n";
#endif
//size of board
int height,width;
//get size
promptForSize(height,width);
//create board
Board board(height,width);
cout << "Board created\n";
int colToDrop=0; //column user wants to drop into
bool cont=true; //continue
AI myAI(&board); //create an AI
//if we are logging moves, make a vector to store them
#ifdef LOGMOVES
vector<Move*> moves;
#endif
do
{
//user's turn
board.print(); //print the board
do {
cout << "What column would you like to drop your piece into?\n> ";
cin >> colToDrop;
}
while(colToDrop < 1 || colToDrop > width);
//prompt for and store desired column
//we like to start at 0, not 1.
colToDrop--;
int res=board.drop(colToDrop, board.p1); //drop tile and store Y coordinate
//log move if desired
#ifdef LOGMOVES
moves.push_back(new Move(colToDrop, res, board.p1));
#endif
//if that move won the game
if(board.won(colToDrop, res, board.p1))
{
//say so and break
cout << board.p1 << " wins!\n";
cont=false;
break;
}
if(board.full()) //if the board is full, break.
{
cout << "Board full! Nobody wins.\n";
cont=false;
break;
}
//if we're also logging the AI's moves
#ifdef LOGMOVES
myAI.runAI(moves); //run the AI and log its moves
#else //otherwise
myAI.runAI(); //just run the AI
#endif
//if the AI just won
if(myAI.justWon())
{
//say so and break
cout << board.p2 << " wins!\n";
cont=false;
break;
}
//if the board is full, break.
if(board.full())
{
cout << "Board full! Nobody wins.\n";
cont=false;
break;
}
} while(cont);
//when the game is over, print the final board.
board.print();
//and if desired, show all the game moves
#ifdef LOGMOVES
cout << "Played with size " << width << "x" << height << endl;
for(int i=0; i<moves.size(); i++)
{
moves[i]->print();
delete moves[i];
}
#endif
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleIdentifier</key>
<string>com.apple.xcode.dsym.GoBang_GBK</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>dSYM</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>
/*
Base class for environments of RL.
Following features:
Discrete and fix-size action space.
Used as:
Experiment environment;
Environment in Agents' mind
*/
#include <cstdlib>
#include <string>
class GoBang: public BaseEnv {
public:
GoBang();
~GoBang();
virtual int Move(int action) = 0;
virtual bool IsFinish() = 0;
virtual void GetResult(float& res) = 0;
virtual void GetFeature(BaseFeature& feature) = 0;
virtual void GetActionNum() = 0;
virtual void GetInputDim(vector<int>& input_dim) = 0;
virtual void GetLegalAction(vector<int>& action) = 0;
virtual bool IsLegal(int action) = 0;
virtual std::string action2str(int action) = 0;
//virtual void TransformFeatures(BaseFeature& feature, int transform_mode) = 0;
//virtual void TransformPolicy(int transform_mode) = 0; // this is reverse mode of TransformFeature
protected:
virtual void Init() = 0;
};
\ No newline at end of file
#include "gobang_comm.h"
#include <cstring>
#include <mutex>
// #include <glog/logging.h>
#define x first
#define y second
using namespace std;
using namespace GoBangComm;
GoBangHashValuePair g_hash_weight[BORDER_SIZE][BORDER_SIZE];
GoBangCoordId g_log2_table[67];
uint64_t g_zobrist_board_hash_weight[4][GOBANGBOARD_SIZE];
uint64_t g_zobrist_player_hash_weight[4];
namespace GoBangFunction {
bool InBoard(const GoBangCoordId id) {
return 0 <= id && id < GOBANGBOARD_SIZE;
}
bool InBoard(const GoBangCoordId x, const GoBangCoordId y) {
return 0 <= x && x < BORDER_SIZE
&& 0 <= y && y < BORDER_SIZE;
}
bool IsUnset(const GoBangCoordId id) {
return COORD_UNSET == id;
}
bool IsUnset(const GoBangCoordId x, const GoBangCoordId y) {
return COORD_UNSET == CoordToId(x, y);
}
bool IsResign(const GoBangCoordId id) {
return COORD_RESIGN == id;
}
bool IsResign(const GoBangCoordId x, const GoBangCoordId y) {
return COORD_RESIGN == CoordToId(x, y);
}
void IdToCoord(const GoBangCoordId id, GoBangCoordId &x, GoBangCoordId &y) {
if (COORD_RESIGN == id) {
x = y = COORD_RESIGN;
} else if (!InBoard(id)) {
x = y = COORD_UNSET;
} else {
x = id / BORDER_SIZE;
y = id % BORDER_SIZE;
}
}
GoBangCoordId CoordToId(const GoBangCoordId x, const GoBangCoordId y) {
if (COORD_RESIGN == x && COORD_RESIGN == y) {
return COORD_RESIGN;
}
if (!InBoard(x, y)) {
return COORD_UNSET;
}
return x * BORDER_SIZE + y;
}
void StrToCoord(const string &str, GoBangCoordId &x, GoBangCoordId &y) {
// CHECK_EQ(str.length(), 2) << "string[" << str << "] length not equal to 2";
x = str[0] - 'a';
y = str[1] - 'a';
if (!InBoard(x, y)) {
x = y = COORD_UNSET;
}
}
string CoordToStr(const GoBangCoordId x, const GoBangCoordId y) {
char buffer[3];
if (!InBoard(x, y)) {
buffer[0] = buffer[1] = 'z';
} else {
buffer[0] = x + 'a';
buffer[1] = y + 'a';
}
return string(buffer, 2);
}
std::string IdToStr(const GoBangCoordId id) {
GoBangCoordId x, y;
IdToCoord(id, x, y);
return CoordToStr(x, y);
}
GobangCoordId StrToId(const std::string &str) {
GobangCoordId x, y;
StrToCoord(str, x, y);
return CoordToId(x, y);
}
once_flag CreateGlobalVariables_once;
void CreateGlobalVariables() {
call_once(
CreateGlobalVariables_once,
[]() {
CreateHashWeights();
CreateQuickLog2Table();
CreateZobristHash();
}
);
}
void CreateHashWeights() {
g_hash_weight[0][0] = GoBangHashValuePair(1, 1);
for (GoBangCoordId i = 1; i < GOBANGBOARD_SIZE; ++i) {
g_hash_weight[i / BORDER_SIZE][i % BORDER_SIZE] =
GoBangHashValuePair(g_hash_weight[(i - 1) / BORDER_SIZE][(i - 1) % BORDER_SIZE].x * g_hash_unit.x,
g_hash_weight[(i - 1) / BORDER_SIZE][(i - 1) % BORDER_SIZE].y * g_hash_unit.y);
}
}
void CreateQuickLog2Table() {
memset(g_log2_table, -1, sizeof(g_log2_table));
int tmp = 1;
for (GoBangCoordId i = 0; i < 64; ++i) {
g_log2_table[tmp] = i;
tmp *= 2;
tmp %= 67;
}
}
#if defined(_WIN32) || defined(_WIN64)
static int rand_r(unsigned int *seed)
{
unsigned int next = *seed;
int result;
next *= 1103515245;
next += 12345;
result = (unsigned int)(next / 65536) % 2048;
next *= 1103515245;
next += 12345;
result <<= 10;
result ^= (unsigned int)(next / 65536) % 1024;
next *= 1103515245;
next += 12345;
result <<= 10;
result ^= (unsigned int)(next / 65536) % 1024;
*seed = next;
return result;
}
#endif
void CreateZobristHash() {
uint32_t seed = 0xdeadbeaf;
for (int i = 0; i < 4; ++i) {
g_zobrist_player_hash_weight[i] = (uint64_t) rand_r(&seed) << 32 | rand_r(&seed);
for (int j = 0; j < GOBANGBOARD_SIZE; ++j) {
g_zobrist_board_hash_weight[i][j] = (uint64_t) rand_r(&seed) << 32 | rand_r(&seed);
}
}
}
} // namespace GoBangFunction
#undef y
#undef x
#pragma once
#include <inttypes.h>
#include <string>
#include <vector>
// Return code of functions should be "int"
typedef uint8_t GoBangStoneColor; // Stone color
typedef int16_t GoBangCoordId; // Stone IDs or coordinates
typedef int16_t GoBangSize; // Counts of visit times, used blocks, .. or other count
namespace GoBangComm {
const GoBangCoordId BORDER_SIZE = 15; // sxk_modify
const GoBangCoordId GOBANGBOARD_SIZE = BORDER_SIZE * BORDER_SIZE;
const GoBangCoordId COORD_UNSET = -2;
//const GoBangCoordId COORD_PASS = -1;
const GoBangCoordId COORD_RESIGN = -3;
const GoBangStoneColor EMPTY = 0;
const GoBangStoneColor BLACK = 1;
const GoBangStoneColor WHITE = 2;
const GoBangStoneColor WALL = 3;
const GoBangStoneColor COLOR_UNKNOWN = -1;
const char *const COLOR_STRING[] = { "Empty", "Black", "White", "Wall" };
} // namespace GoBangComm
namespace GoBangFeature {
const int SIZE_HISTORYEACHSIDE = 16;
const int SIZE_PLAYERCOLOR = 1;
const int STARTPOS_HISTORYEACHSIDE = 0;
const int STARTPOS_PLAYERCOLOR = STARTPOS_HISTORYEACHSIDE + SIZE_HISTORYEACHSIDE;
const int FEATURE_COUNT = STARTPOS_PLAYERCOLOR + SIZE_PLAYERCOLOR;
} // namespace GoBangFeature
namespace GoBangFunction {
extern bool InBoard(const GoBangCoordId id);
extern bool InBoard(const GoBangCoordId x, const GoBangCoordId y);
extern bool IsUnset(const GoBangCoordId id);
extern bool IsUnset(const GoBangCoordId x, const GoBangCoordId y);
extern bool IsResign(const GoBangCoordId id);
extern bool IsResign(const GoBangCoordId x, const GoBangCoordId y);
extern void IdToCoord(const GoBangCoordId id, GoBangCoordId &x, GoBangCoordId &y);
extern GoBangCoordId CoordToId(const GoBangCoordId x, const GoBangCoordId y);
extern void StrToCoord(const std::string &str, GoBangCoordId &x, GoBangCoordId &y);
extern std::string CoordToStr(const GoBangCoordId x, const GoBangCoordId y);
extern std::string IdToStr(const GoBangCoordId id);
extern GoBangCoordId StrToId(const std::string &str);
extern void CreateGlobalVariables();
extern void CreateHashWeights();
extern void CreateQuickLog2Table();
extern void CreateZobristHash();
} // namespace GoBangFunction
//typedef std::pair<GoBangCoordId, GoBangCoordId> GoBangPosition;
typedef std::pair<uint64_t, uint64_t> GoBangHashValuePair;
extern GoBangHashValuePair g_hash_weight[GoBangComm::BORDER_SIZE][GoBangComm::BORDER_SIZE];
const GoBangHashValuePair g_hash_unit(3, 7);
extern uint64_t g_zobrist_board_hash_weight[4][GoBangComm::GOBANGBOARD_SIZE];
extern uint64_t g_zobrist_player_hash_weight[4];
//action_count:统计已落子数,state:统计棋局状态,0未分胜负,1黑胜,2白胜,3平局
//extern int action_count = 0;
//extern int state = 0;
extern GoBangCoordId g_log2_table[67];
#define FOR_EACHCOORD(id) for (GoBangCoordId id = 0; id < GoBangComm::GOBANGBOARD_SIZE; ++id)
#include "gobang_env.h"
#include <algorithm>
#include <cmath>
using namespace std;
using namespace GoBangComm;
using namespace GoBangFunction;
using namespace GoBangFeature;
GoBangEnv::GoBangEnv() {
CreateGlobalVariables();
FOR_EACHCOORD(i) {
stones_[i].self_id = i;
}
feature_history_list_.clear();
memset(board_state_, 0, sizeof(board_state_));
memset(legal_move_map_, 1, sizeof(legal_move_map_));
memset(move_count_, 0, sizeof(move_count_));
current_player_ = BLACK;
last_position_ = COORD_UNSET;
is_resign_ = false;
state_ = 0;
action_count_ = 0;
board_hash_states_.clear();
zobrist_hash_value_ = 0;
}
//GoBangEnv::GoBangEnv(const GoBangEnv &ge) : GoBangEnv() {
// CopyFrom(ge);
// }
GoBangEnv::~GoBangEnv() {
}
// void GoBangEnv::CopyFrom(const GoBangEnv &src) {
// *this = src;
// }
void GoBangEnv::GetSensibleMove() {
// Add new feature plane
string plane;
// black
{
plane = "";
FOR_EACHCOORD(id) {
if (board_state_[id] == BLACK) {
plane += "1";
} else {
plane += "0";
}
}
feature_history_list_.push_back(plane);
}
// white
{
plane = "";
FOR_EACHCOORD(id) {
if (board_state_[id] == WHITE) {
plane += "1";
} else {
plane += "0";
}
}
feature_history_list_.push_back(plane);
}
memset(legal_move_map_, 0, sizeof(legal_move_map_));
FOR_EACHCOORD(i) {
if (EMPTY != board_state_[i]) {
continue;
}
legal_move_map_[i] = true;
GoBangCoordId x, y;
IdToCoord(i, x, y);
if(current_player_ == BLACK && Ban(x,y)){
legal_move_map_[i] = false;
}
}
}
int GoBangState::Move(int action) {
if (!IsLegal(action)) {
return -1;
}
if(IsResign(action)){
is_resign_ = true;
return 0;
}
last_position_ = action;
{
zobrist_hash_value_ ^= g_zobrist_player_hash_weight[Self()];
zobrist_hash_value_ ^= g_zobrist_player_hash_weight[Opponent()];
zobrist_hash_value_ ^= g_zobrist_board_hash_weight[Self()][action];
}
++move_count_[action];
board_state_[action] = Self();
++action_count_;
HandOff();
GetSensibleMove();
return 0;
}
int GoBangEnv::dir_x() const{
static int angle = 135; //角度,从零开始,每次增加45度,135度的下一次回到零
if(angle < 135){
angle+=45;
}else{
angle = 0;
}
switch(angle){
case 0:
return 0;
break;
case 45:case 90:case 135:
return 1;
break;
default:
printf("error angle\n");
return 0;
break;
}
}
int GoBangEnv::dir_y() const{
static int angle = 135; //角度,从零开始,每次增加45度,135度的下一次回到零
if(angle < 135){
angle+=45;
}else{
angle = 0;
}
switch(angle){
case 0: case 45:
return 1;
break;
case 90:
return 0;
break;
case 135:
return -1;
break;
default:
printf("error angle.\n");
return 0;
break;
}
}
bool GoBangEnv::live_four(int left[4], int right[4]) const{ //判断输入的序列是否是活四,这里略去了两头四四的情况没有考虑,不过这里的活四只是为了判断是否为活三而准备,如果已经是两头四四的话那已经形成了禁手,是否是活三变得没有意义
GoBangStoneColor type = GoBangComm::BLACK; //需要判断的只有黑子
int i,j;
int a,b; //a为一变量,b为临时储存a的值
int left_1 = 0; //记录左方相同子的个数
int right_1 = 0; //记录右方相同子的个数
int count = 0; //统计可以形成5的点数
/*先判断一下是否还没放子的时候就已经是5颗了*/
for(j = 0; j < 4 && right[j] == type; j++){ //当右边的子与之相同时(前面的条件是为了保证不越界)
right_1++;
}
for(j = 0; j < 4 && left[j] == type; j++){ //当左边的子与之相同时(前面的条件是为了保证不越界)
left_1++;
}
if(left_1 + right_1 == 4){ //如果已经五连,那么不是活四,返回0,如果没有五连,什么也不做
return false;
}
for(a = 0; a < 8; a++){
left_1 = 0;
right_1 = 0;
if(a < 4){ //将left和right上的0依次改为type再判断是否形成五连,形成则可形成五连的点加1,注:这里的0是初始化给的0而非EMPTY,a<4是统计left
b = a;
if(left[a] == 0){
left[a] = type;
}else{
continue;
}
}else if(a >= 4){//a>=4是统计right
b = a;
a-=4;
if(right[a] == 0){
right[a] = type;
}else{
a = b;
continue;
}
}
for(j = 0; j < 4 && right[j] == type; j++){ //当左边的子与之相同时(前面的条件是为了保证不越界)
right_1++;
}
for(j = 0; j < 4 && left[j] == type; j++){ //当左边的子与之相同时(前面的条件是为了保证不越界)
left_1++;
}
if(left_1 + right_1 == 4){ //如果形成五连
count++;
}
if(b < 4){ //将改的值改回去
left[a] = 0;
}
else if(b >= 4){
right[a] = 0;
}
a = b;
}
if(count == 2){
return true;
}else{
return false;
}
}
bool GoBangEnv::live_three(int left[4], int right[4]) const{ //判断是否为活三
GoBangStoneColor type = GoBangComm::BLACK; //因为白棋不用判断,所以必为黑棋
int i,j;
int a,b; //a为一变量,b为临时储存a的值
if(live_four(left, right)){ //已经是活四,就不再是活三了
return false;
}
for(a = 0; a < 8; a++){
if(a < 4){ //将left和right上的0依次改为type再判断是否形成活四,注:这里的0是初始化给的0而非EMPTY,a<4是统计left
b = a;
if(left[a] == 0){
left[a] = type;
}else{
continue;
}
}else if(a >= 4){//a>=4是统计right
b = a;
a-=4;
if(right[a] == 0){
right[a] = type;
}else{
a = b;
continue;
}
}
if(live_four(left,right)){ //如果加一步之后形成活四,那么是活三
if(b < 4){ //将改的值改回去
left[a] = 0;
}else if(b >= 4){
right[a] = 0;
}
return true;
}else {
if(b < 4){ //将改的值改回去
left[a] = 0;
}else if(b >= 4){
right[a] = 0;
}
}
a = b;
}
return false;
}
bool GoBangEnv::Ban(GoBangCoordId x, GoBangCoordId y) const{
GoBangStoneColor type = GoBangComm::BLACK; // 黑棋判断禁手
int left[4][4] = { {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0} }; //用来储存这个点沿x轴反方向四轴的棋子状态
int right[4][4] = { {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0} }; //用来储存这个点沿x轴正方向四轴的棋子状态
int left_2[4] = {0,0,0,0}; //为live_three函数传递参数而准备的数组,下同
int right_2[4] = {0,0,0,0};
int i,j; //j为倍数
int a,b;
int fo_l[4],fo_r[4]; //表示上面数组中第一个其它棋子或是边界外的位置
int count[2] = {0,0}; //统计活三、活四或冲四的个数
int le[4] = {0,0,0,0},ri[4] = {0,0,0,0}; //对左右两边的状
for(i = 0; i < 4; i++){ //将点(x+1,y+1)水平,右斜,竖直,左斜的方向上4个棋子的状态读入上面两个数组中
a = dir_x(); b = dir_y();
for(j = 1; j < 5; j++){
if((x + j * a < GoBangComm::BORDER_SIZE) && (x + j * a >= 0) && (y + j * b < GoBangComm::BORDER_SIZE) && (y + j * b >= 0)){ //如果这颗子在边界内
int id = GoBangFunction::CoordToId(x + j * a, y + j * b);
right[i][j - 1] = board_state_[id];
}
else{
right[i][j - 1] = -2; //如果不在边界内
}
if((x - j * a < GoBangComm::BORDER_SIZE) && (x - j * a >= 0) && (y - j * b < GoBangComm::BORDER_SIZE) && (y - j * b >= 0)){ //如果这颗子在边界内
int id = GoBangFunction::CoordToId(x - j * a, y - j * b);
left[i][j - 1] = board_state_[id];
}
else{
left[i][j - 1] = -2; //如果不在边界内
}
}
}
for(i = 0; i < 4; i++){
for(j = 0; j < 4; j++){
if(left[i][j] != type && left[i][j] != 0){ //如果不是相同棋子也不是空位的话
fo_l[i] = j; //第一个其它棋子,或是边界外
break;
}
}
if(j == 4){ //如果四个都没有对手的棋子的话,空间充足
fo_l[i] = j;
}
for(j = 0; j < 4; j++){
if(right[i][j] != type && right[i][j] != 0){ //如果不是相同棋子也不是空位的话
fo_r[i]=j; //第一个其它棋子,或是边界外
break;
}
}
if(j == 4){ //如果四个都没有对手的棋子的话,空间充足
fo_r[i] = j;
}
}
for(i = 0; i < 4; i++){ //用le和ri对左右两边的状态进行编码,百位与fo_l/fo_r的值相同,剩下的0和1按二进制来编码,left[i][0]的权为8,left[i][3]的权为1,加入此编码的目的是为了解决c语言无法将两数组直接比较,于是换一种方便的表示方式来比较它们。
for(j = 0; j < fo_l[i]; j++){
le[i]+=abs(left[i][j])*pow(2,3-j); //剩下的0和1按二进制来编码,left[i][0]的权为8,left[i][3]的权为1
}
le[i]+=100*fo_l[i]; //百位与fo_l/fo_r的值相同
}
for(i = 0; i < 4; i++){ //用le和ri对左右两边的状态进行编码,百位与fo_l/fo_r的值相同,剩下的0和1按二进制来编码,right[i][0]的权为8,right[i][3]的权为1,加入此编码的目的是为了解决c语言无法将两数组直接比较,于是换一种方便的表示方式来比较它们。
for(j = 0; j < fo_r[i]; j++){
ri[i]+=abs(right[i][j])*pow(2,3-j); //剩下的0和1按二进制来编码,right[i][0]的权为8,right[i][3]的权为1
}
ri[i]+=100*fo_r[i]; //百位与fo_l/fo_r的值相同
}
for(i = 0; i < 4; i++){
switch(le[i] % 100){ //统计活四和冲四的个数
case 0:
if((ri[i] % 100) == 11 || (ri[i] % 100) == 13 || (ri[i] % 100) == 14 || (ri[i] % 100) == 7)
count[1]++;
break;
case 4:
if((ri[i] % 100) == 12)
count[1]++;
else if((ri[i] % 100) == 13) //特殊的两头四四
count[1]+=2;
break;
case 6:
if((ri[i] % 100) == 8)
count[1]++;
else if((ri[i] % 100) == 11) //特殊的两头四四
count[1]+=2;
break;
case 7:
if((ri[i] % 100) == 12)
count[1]++;
else if((ri[i] % 100) == 7) //特殊的两头四四
count[1]+=2;
break;
case 8:
if((ri[i] % 100) ==12 || (ri[i] % 100) == 6 || (ri[i] % 100) == 10)
count[1]++;
break;
case 10:
if((ri[i] % 100) == 10) //特殊的两头四四
count[1]+=2;
break;
case 11:
if((ri[i] % 100) == 0)
count[1]++;
else if((ri[i] % 100) == 6) //特殊的两头四四
count[1]+=2;
break;
case 12:
if((ri[i] % 100)==8 || (ri[i] % 100) == 4)
count[1]++;
break;
case 13:
if((ri[i] % 100) == 0)
count[1]++;
else if((ri[i] % 100) == 4) //特殊的两头四四
count[1]+=2;
break;
case 14:
if((ri[i]%100) == 0)
count[1]++;
break;
default:
break;
}
}
for(i = 0; i < 4; i++){ //统计活三的个数
for(j = 0; j < 4; j++){
left_2[j] = left[i][j]; //将数组left、right的第i行复制到left_2、right_2
right_2[j] = right[i][j];
}
if(live_three(left_2, right_2))
count[0]++;
}
if(count[0] >= 2 || count[1] >= 2){ //如果形成三三禁手或是四四禁手,白棋胜利
return true; //黑子禁手状态
}
return false;
}
int GoBangEnv::GobangResult(GoBangCoordId x, GoBangCoordId y) const{
GoBangStoneColor type; //如果最后落子为黑子,其为1,白子为2
int left_1[4] = {0,0,0,0}; //记录x轴反方相同棋子的个数
int right_1[4] = {0,0,0,0}; //记录x轴正方相同棋子的个数
int i, j;
int a, b;
if(action_count_ >= GoBangComm::GOBANGBOARD_SIZE){
state_ = 3;
}
if(is_resign_){
if(current_player_ == GoBangComm::BLACK){
state_ = 2;
}else if(current_player_ == GoBangComm::WHITE){
state_ = 1;
}
}
if(state_ != 0){ //如果游戏结束
return state_;
}
type = board_state_[GoBangFunction::CoordToId(x, y)];
//type = current_player_;
for(i = 0; i < 4; i++){
j = 1; a = dir_x(); b = dir_y();
while((x + j * a < GoBangComm::BORDER_SIZE) && (y + j * b < GoBangComm::BORDER_SIZE) && (x + j * a >= 0) && (y + j * b >= 0) && (board[GoBangFunction::CoordToId(x + j * a, y + j * b)] == type)){ //当x轴正向的子与之相同时(前面的条件是为了保证不越界)
j++;
right_1[i]++;
}
j = 1;
while((x - j * a < GoBangComm::BORDER_SIZE) && (y - j * b <= GoBangComm::BORDER_SIZE) && (x - j * a >= 0) && (y - j * b >= 0) && (board[GoBangFunction::CoordToId(x - j * a, y - j * b)] == type)) //当x轴反向的子与之相同时
{
j++;
left_1[i]++;
}
}
for(i = 0; i < 4; i++){
if(type == GoBangComm::WHITE){ //如果刚才为白棋落子,那么不进行禁手判断
if((left_1[i] + right_1[i]) >= 4){ //白棋只判断是否胜利
state_ = 2;
return state_;
}else{ //继续下一根轴检测
continue;
}
}else{ //如果是黑棋,需要考虑禁手状态
if((left_1[i] + right_1[i]) == 4){ //胜利
state_ = 1; //将状态改为对应的棋子胜利
return state_; //结束函数
}
else if((left_1[i]+right_1[i]) > 4){ //长连禁手
state_ = 2; //黑子禁手状态,白棋获胜
return state_;
}
}
}
if(type == GoBangComm::WHITE){ //如果是白子,即使没有胜利也不进行下面的判断
return state_;
}
/*如果是黑子落子且没有胜利,那么继续进行禁手判断*/
if(Ban(x, y)){
state_ = 2;
return state_;
}
return state_;
}
int GoBangEnv::CalcResult() const {
GoBangCoordId x, y;
int result = 0;
FOR_EACHCOORD(i) {
if(board_state_[i] == GoBangComm::EMPTY){
continue;
}else{
GoBangFunction::IdToCoord(i, x, y);
result = GobangResult(x, y);
if(result != 0){
return result;
}
}
}
return result;
}
GoBangStoneColor GoBangEnv::GetWinner() const {
int result = CalcResult();
if (result == 3){
return GoBangComm::EMPTY;
}else if (result == 1){
return GoBangComm::BLACK;
}else if(result == 2){
return GoBangComm::WHITE;
}
}
void GoBangEnv::GetResult(float& res) {
if (GetWinner() == GoBangComm::EMPTY){
res = 0.0f;
}else{
res = GetWinner() == CurrentPlayer() ? -1.0f : 1.0f;
}
}
vector<bool> GoBangEnv::GetFeature(BaseFeature& feature) const { // HWC
feature.clear();
feature.resize(GOBANGBOARD_SIZE * (SIZE_HISTORYEACHSIDE + 1));
//vector<bool> feature(GOBANGBOARD_SIZE * (SIZE_HISTORYEACHSIDE + 1), 0);
// because push black into history first,
// if next player is black,
// we should get planes swap of each two planes
int reverse_plane = int(Self() == BLACK);
for (GoBangSize i = 0; i < SIZE_HISTORYEACHSIDE && i < feature_history_list_.size(); ++i) {
const string &feature_str = *(feature_history_list_.rbegin() + (i ^ reverse_plane));
for (int j = 0, k = i; j < GOBANGBOARD_SIZE; ++j, k += (SIZE_HISTORYEACHSIDE + 1)) {
feature[k] = feature_str[j] - '0';
}
}
if (Self() == BLACK) {
for (int j = 0, k = SIZE_HISTORYEACHSIDE; j < GOBANGBOARD_SIZE; ++j, k += (SIZE_HISTORYEACHSIDE + 1)) {
feature[k] = 1;
}
}
return feature;
}
int GoBangEnv::GetActionNum() {//include RESIGN
return GoBangComm::GOBANGBOARD_SIZE + 1;
}
void GoBangEnv::GetInputDim(vector<int>& input_dim) {
input_dim.clear();
input_dim.push_back(SIZE_HISTORYEACHSIDE);
input_dim.push_back(BORDER_SIZE);
input_dim.push_back(BORDER_SIZE)
}
void GoBangEnv::GetLegalAction(vector<int>& action) {
action.clear();
FOR_EACHCOORD(id) {
if (legal_move_map_[id]) {
action.push_back(id);
}
}
}
/*void GoBangEnv::TransformCoord(GoBangCoordId &x, GoBangCoordId &y, int mode, bool reverse = false)
{
if (reverse) {
if (mode & 4) std::swap(x, y);
if (mode & 2) y = GoBangComm::BORDER_SIZE - y - 1;
if (mode & 1) x = GoBangComm::BORDER_SIZE - x - 1;
} else {
if (mode & 1) x = GoBangComm::BORDER_SIZE - x - 1;
if (mode & 2) y = GoBangComm::BORDER_SIZE - y - 1;
if (mode & 4) std::swap(x, y);
}
}*/
// void GoBangEnv::TransformFeatures(BaseFeature& feature, int transform_mode) {
// BaseFeature ret(feature.size());
// int depth = features.size() / GoBangComm::GOBANGBOARD_SIZE;
// for (int i = 0; i < GoBangComm::GOBANGBOARD_SIZE; ++i) {
// GoBangCoordId x, y;
// GoBangFunction::IdToCoord(i, x, y);
// TransformCoord(x, y, mode);
// int j = GoBangFunction::CoordToId(x, y);
// for (int k = 0; k < depth; ++k) {
// ret[i * depth + k] = features[j * depth + k];
// }
// }
// feature = std::move(ret);
// }
// void TransformPolicy(int transform_mode) {
// }
#include "gobang_comm.h"
#include "base_env.h"
#include <cstdlib>
#include <cstring>
#include <stack>
#include <string>
#include <unordered_set>
#include <vector>
#if defined(_WIN32) || defined(_WIN64)
# include <intrin.h>
# define __builtin_popcount __popcnt
# define __builtin_popcountll __popcnt64
#endif
typedef vector<bool> BaseFeature;
struct GoBangStone {
GoBangCoordId self_id; // Id of this stone
GoBangCoordId next_id; // Use like link-list
GoBangCoordId parent_id; // Use like union-find-set (rooted by tail)
// inline void SetSelfId(GoBangCoordId id) { self_id = id; }
inline void Reset(GoBangCoordId id = GoBangComm::COORD_UNSET) {
next_id = parent_id = self_id;
}
} ;
class GoBangEnv: public BaseEnv {
public:
GoBangEnv();
// GoBangEnv(const GoBangEnv &ge);
~GoBangEnv();
int Move(int action) override;
bool IsFinish() override { return ((state_ != 0 ? true : false) || is_resign_); }
void GetResult(float& res) override;
void GetFeature(BaseFeature& feature) override;
int GetActionNum() override;
void GetInputDim(vector<int>& input_dim) override;
void GetLegalAction(vector<int>& action) override;
bool IsLegal(int action) override { return GoBangFunction::IsResign(action) || legal_move_map_[action]; }
std::string action2str(int action) override { return GoBangFunction::IdToStr(const GoBangCoordId action); }
int CurrentPlayer() override { return current_player_; }
protected:
// void Init();
// void CopyFrom(const GoBangEnv &src);
int GobangResult(GoBangCoordId x, GoBangCoordId y) const;
int CalcResult() const;
GoBangStoneColor GetWinner() const;
inline void HandOff() { current_player_ = Opponent(); }
inline GoBangStoneColor Opponent(const GoBangStoneColor color = GoBangComm::COLOR_UNKNOWN) const {
return GoBangComm::BLACK + GoBangComm::WHITE
- (GoBangComm::COLOR_UNKNOWN != color ? color : current_player_);
}
inline GoBangStoneColor Self() const { return current_player_; }
inline GoBangCoordId GetLastMove() const { return last_position_; }
// inline GoBangStoneColor CurrentPlayer() const { return current_player_; }
//void GoBangEnv::TransformCoord(GoBangCoordId &x, GoBangCoordId &y, int mode, bool reverse = false)
void GetSensibleMove();
int dir_x() const;
int dir_y() const;
bool live_four(int left[4], int right[4]) const;
bool live_three(int left[4], int right[4]) const;
bool Ban(GoBangCoordId x, GoBangCoordId y) const;
protected:
// board utils
GoBangStone stones_[GoBangComm::GOBANGBOARD_SIZE];
GoBangStoneColor board_state_[GoBangComm::GOBANGBOARD_SIZE];
GoBangStoneColor current_player_;
GoBangCoordId last_position_;
bool is_resign_;
int state_;
int action_count_;
// hash board state
std::unordered_set<uint64_t> board_hash_states_;
uint64_t zobrist_hash_value_;
// features
bool legal_move_map_[GoBangComm::GOBANGBOARD_SIZE];
GoBangSize move_count_[GoBangComm::GOBANGBOARD_SIZE];
std::vector<std::string> feature_history_list_;
};
#include <stdio.h>
#include <math.h> //因为包含math.h,所以利用gcc进行编译的时候需要在最后加上 -lm 参数
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <iostream>
#define SIZE 15 //棋盘大小
#define CHARSIZE 3
using namespace std;
char initRecordBorard(); //初始化棋盘
void displayBoard(int s[SIZE][SIZE]); //显示棋盘函数,参数为棋盘上每一格的状态
void input_computer(int v[SIZE][SIZE]); //计算机落子,参数为棋盘上每一格的分值
void input_player(int s[SIZE][SIZE]); //玩家落子,参数为棋盘上每一格的状态
int score_calculator(int s[SIZE][SIZE],int mod); //计算各点的分值,并返回一个最大分数
void victory_judger(int s[SIZE][SIZE],int current_y,int current_x); //胜利与否判断
void settle_accounts(int state,char turn); //结算程序
void clear_string(void); //清空多余的无用的输入
void help(void); //显示可以使用的指令
void back(int n); //悔棋函数,输入为悔棋的步数
int dir_x(void); //返回x方向,如右45°时返回1,向上时为0,向左上时为-1,其中有一个静态变量,每调用一次,角度调转45°,由于只需要判断水平,竖直,左右倾斜,所以每调用4次为一个循环。
int dir_y(void); //返回y方向,功能同上。
int scan(int x,int y); //扫描以点(x+1,y+1)为中心5*5范围内的棋子个数
int calculation(int i,int j,int mod); //计算点(x+1,y+1)的分值
int score_attack(int left[4][4],int right[4][4]); //输入棋子周围的状态,计算进攻得分
int score_defense(int x,int y); //输入棋子位置,计算防守扣分
int score_add_to_defense(int x,int y); //输入棋子位置(x,y),计算防守加分
int score_step2(int x,int y); //输入棋子位置(x,y),计算第二步棋的加分
bool live_four(int left[4],int right[4]); //判断输入的是否为活四,是返回1,不是返回0
bool live_three(int left[4],int right[4]); //判断输入的是否为活三,是返回1,不是返回0
bool Ban(int s[SIZE][SIZE], int x, int y);
char turn; //先后手储存变量 turn '1'代表玩家先手 '2'代表电脑先手 '3'表示玩家对战
int state; //战局状态 0 表示平局 1 表示黑子胜利 -1 表示白子胜利 -2 表示平局 2 表示黑子禁手
int rd; //已落子总数
int s[SIZE][SIZE]; //记录棋盘上每一格的状态,前一个坐标表示行,后一个表示列,-1表示黑子,1表示白子
int v[SIZE][SIZE]; //记录棋盘上每一格的分值,前一个坐标表示行,后一个表示列
int l[SIZE*SIZE]; //记录每一步的落子,共SIZE*SIZE个位置,l[rd-1]为第rd颗子的坐标(l[rd-1]=current_x*SIZE+current_y)
int current_x; //记录上一步落子的横向位置,范围为0~SIZE-1
int current_y; //记录上一步落子的纵向位置,范围为0~SIZE-1
int x,y; //行号和列号
int xl,yl;
/*操作方式说明:开始选择游戏模式,1代表玩家先手,2代表电脑先手,3代表玩家对战,进入游戏中,直接输入对应坐标(如H10)即可,与此同时也可以输入对应指令:
输入 he 显示命令列表; 输入 ba 悔棋; 输入 en 结束游戏; 输入 re 重新开始游戏。游戏胜负判定后,输入y为继续一局新的游戏,输入别的东西为退出游戏。*/
//棋盘使用的是GBK编码,每一个中文字符占用2个字节。
//棋盘基本模板
//char aInitDisplayBoardArray[SIZE][SIZE*CHARSIZE+1] =
//char ca[] = "┏┯┯┯┯┯┯┯┯┯┯┯┯┯┓";
char aInitDisplayBoardArray[SIZE][SIZE*CHARSIZE+1] =
{
"┏┯┯┯┯┯┯┯┯┯┯┯┯┯┓",
"┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨",
"┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨",
"┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨",
"┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨",
"┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨",
"┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨",
"┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨",
"┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨",
"┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨",
"┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨",
"┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨",
"┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨",
"┠┼┼┼┼┼┼┼┼┼┼┼┼┼┨",
"┗┷┷┷┷┷┷┷┷┷┷┷┷┷┛"
};
char aDisplayBoardArray[SIZE][SIZE*CHARSIZE+1]; //此数组用于显示棋盘
char play1Pic[]="●"; //正常的黑棋子状态
char play1CurrentPic[]="▲"; //刚落子的黑棋子状态
char play2Pic[]="◎"; //正常的白棋子状态
char play2CurrentPic[]="△"; //刚落子的白棋子状态
//main函数
int main()
{
restart: //restart从这里开始
turn=initRecordBorard();
if(turn=='1') //turn '1'代表玩家先手 '2'代表电脑先手 '3'表示玩家对战
{
while(state==0)
{
displayBoard(s);
input_player(s);
victory_judger(s,current_x,current_y);
switch(state)
{
case 50: //重启指令,输入re
goto restart;
break;
case 37: //结束指令,输入en
goto end;
break;
case 1:case -1:case -2: case 2: //胜负已分
goto end;
break;
default:
break;
}
computer_first: //电脑先手的人机对战将从这里开始执行
score_calculator(s,1); //人机对战
input_computer(v);
victory_judger(s,current_x,current_y);
}
}
else if(turn=='2')
goto computer_first;
else if(turn=='3') //玩家对战
{
while(state==0)
{
displayBoard(s);
input_player(s);
victory_judger(s,current_x,current_y);
switch(state)
{
case 50: //重启指令,输入re
goto restart;
break;
case 37: //结束指令,输入en
goto end;
break;
case 1:case -1:case -2: case 2: //胜负已分
goto end;
break;
default:
break;
}
displayBoard(s);
input_player(s);
victory_judger(s,current_x,current_y);
switch(state)
{
case 50: //重启指令,输入re
goto restart;
break;
case 37: //结束指令,输入en
goto end;
break;
case 1:case -1:case -2: case 2: //胜负已分
goto end;
break;
default:
break;
}
}
}
else
{
printf("Turn error!");
goto restart;
}
end: //在一个不断落子的循环中,直到一方胜利(即state改变),或者棋子数>=sIZE*sIZE,或者输入结束指令,会通过goto来到这里
settle_accounts(state,turn); //结算程序
displayBoard(s);
printf("Do you want to try again?(If yse, please enter y. If no, enter whatever you want.\n)");
if(getchar() == 'y')
{
clear_string();
goto restart;
}
return 0;
}
//初始化棋盘格局
char initRecordBorard(void)
{
int i,j;
extern int state; //战局状态
extern int rd; //已落子数
extern int s[SIZE][SIZE]; //记录棋盘上每一格的状态
extern int v[SIZE][SIZE]; //记录棋盘上每一格的分值
extern int current_x,current_y; //记录上一步落子
extern int l[SIZE*SIZE]; //记录每一步的落子
char turn;
state=0;
rd=0;
current_x=-1;
current_y=-1;
for(j=0;j<SIZE;j++) //通过双重循环,将s,v,l这三个数组清0
for(i=0;i<SIZE;i++)
{
s[i][j]=0;
v[i][j]=0;
l[SIZE*i+j]=0;
}
displayBoard(s);
printf("Who move first?(1 is you , 2 is me,\n and 3 is person_to_person.\n Enter 1 or 2 or 3.\n");
turn=getchar();
while(turn!='1' && turn!='2' && turn!='3')
{
printf("Wrong choice!\n");
turn=getchar();
}
if(getchar()!='\n')
{
printf("Wrong choice! Try again.\n");
clear_string();
turn=initRecordBorard();
}
system("clear"); //清屏
if (turn == '2')
{
srand(time(0));
switch(rand()%9+1) //电脑先手时,调用<time.h>里的库函数srand和rand,产生随机数,使得第一颗黑棋随机落在中心区域的九个位置之一
{
case 1:
v[6][6]=1; break;
case 2:
v[6][7]=1; break;
case 3:
v[6][8]=1; break;
case 4:
v[7][6]=1; break;
case 5:
v[7][7]=1; break;
case 6:
v[7][8]=1; break;
case 7:
v[8][6]=1; break;
case 8:
v[8][7]=1; break;
case 9:
v[8][8]=1; break;
default:
break;
}
}
else
;
return turn;
}
void displayBoard(int s[SIZE][SIZE]) //打印棋盘
{
extern int current_x; //记录上一步落子
extern int current_y; //记录上一步落子
extern int xl;
extern int yl;
extern int rd;
int i,j;
int xnow; //当前落子的行号
char ynow; //当前落子的列号
for(i=0;i<SIZE+1;i++) //将aInitDisplayBoardArray中记录的空棋盘,复制到aDisplayBoardArray中
for(j=0;j<(2*SIZE+1);j++)
aDisplayBoardArray[i][j]=aInitDisplayBoardArray[i][j];
for(i=0;i<SIZE;i++){ //扫描数组s,当遇到非0的元素,将●或者◎复制到aDisplayBoardArray的相应位置上
for(j=0;j<SIZE;j++)
{
switch(s[i][j])
{
case -2:
aDisplayBoardArray[SIZE-i-1][2*j]=play1CurrentPic[0];
aDisplayBoardArray[SIZE-i-1][2*j+1]=play1CurrentPic[1];
break;
case -1:
aDisplayBoardArray[SIZE-i-1][2*j]=play1Pic[0];
aDisplayBoardArray[SIZE-i-1][2*j+1]=play1Pic[1];
break;
case 2:
aDisplayBoardArray[SIZE-i-1][2*j]=play2CurrentPic[0];
aDisplayBoardArray[SIZE-i-1][2*j+1]=play2CurrentPic[1];
break;
case 1:
aDisplayBoardArray[SIZE-i-1][2*j]=play2Pic[0];
aDisplayBoardArray[SIZE-i-1][2*j+1]=play2Pic[1];
default:
break;
}
if(s[i][j]==-2)
s[i][j]=-1;
if(s[i][j]==2)
s[i][j]=1;
}
}
printf(" Work of :王晨曦\n"); //在棋盘上方显示“作者: ...”这句话
for(i=0;i<SIZE;i++)
printf("%3d%s\n",SIZE-i,aDisplayBoardArray[i]); //将aDisplayBoardArray输出到屏幕上
//输出最下面的一行字母A B ....
printf(" ");
for(i=0;i<SIZE;i++)
printf("%2c",'A'+i);
printf("\n");
ynow=yl+'A';
xnow=xl+1;
if(rd >= 1)
printf("My latest choice:%d %c\n",xnow,ynow); //输出当前落子的位置
else
;
}
void input_player(int s[SIZE][SIZE]) //玩家落子
{
extern int current_x;
extern int current_y;
extern int state;
extern int rd;
int y;
int x;
extern int v[SIZE][SIZE];
extern int l[SIZE*SIZE]; //记录每一步的落子
if(rd>=SIZE*SIZE)
{
state=-2; //平局
return;
}
printf("Which place would you like to choose?\n");
if(rd<=10)
printf("You could input H10 or anything like this.\n");
y=getchar()-'A'+1;
scanf("%d",&x);
if(y<=SIZE && y>=1 && x<=SIZE && x>=1 && getchar()=='\n') //输入的是正确的位置
{
if(s[x-1][y-1]==0)
{
current_x=x-1;
current_y=y-1;
l[rd]=current_x*SIZE+current_y;
switch(rd%2)
{
case 0:
s[x-1][y-1]=-1;
rd++;
v[x-1][y-1]=-1;
break;
case 1:
s[x-1][y-1]=1;
rd++;
v[x-1][y-1]=-1;
break;
default:
printf("rd error!\n");
break;
}
}
else
{
printf("You can't choose here.Be serious!\n");
input_player(s);
}
}
else if(y<=58 && y>=33) //如果输入的是指令的话,第一次gerchar()得到的应是一个小写字母,对应计算式得到y的值应在33到58中间
{
switch(y)
{
case 40: //h对应的数字,显示指令
help();
clear_string();
input_player(s); //重新落子
break;
case 50: //r对应的数字,重启游戏
state=50;
clear_string();
break;
case 34: //b对应的数字,悔棋
back(2); //悔两步棋,回到上一次落子
clear_string();
system("clear"); //清屏
displayBoard(s); //打印棋盘
input_player(s);
break;
case 37: //e对应的数字,结束游戏
state=37;
clear_string();
break;
default:
printf("Wrong instructions,enter 'he' to view optional instructions.\n");
clear_string();
input_player(s); //重新落子
break;
}
}
else
{
printf("Wrong choice!\n");
clear_string();
input_player(s);
}
}
void input_computer(int v[SIZE][SIZE]) //计算机落子
{
int i,j;
int max=-1,i_max,j_max;
extern int current_x;
extern int current_y;
extern int rd;
extern int s[SIZE][SIZE];
extern int l[SIZE*SIZE]; //记录每一步的落子
extern int state;
extern int xl,yl;
if (rd >= SIZE*SIZE)
{
state = -2; //平局
return;
}
for(i=0;i<=SIZE-1;i++)
{
for(j=0;j<=SIZE-1;j++)
{
if(v[i][j]>max)
{
max=v[i][j];
i_max=i;
j_max=j;
}
else
;
}
}
if(s[i_max][j_max]==0)
{
current_x=i_max;
current_y=j_max;
xl=i_max;
yl=j_max;
l[rd]=current_x*SIZE+current_y;
switch(rd%2)
{
case 0:
s[i_max][j_max]=-2;
rd++;
v[i_max][j_max]=-1;
break;
case 1:
s[i_max][j_max]=2;
rd++;
v[i_max][j_max]=-1;
break;
default:
printf("rd error!\n");
break;
}
}
else
printf("I seems stucked.\n");
}
void help(void)
{
printf("输入\'ba\'悔棋 \t 输入\'en\'结束游戏 \t 输入\'re\'重新开始游戏 \n");
}
void back(int n) //悔棋,输入为悔棋的步数
{
extern int rd; //已落子数
extern int s[SIZE][SIZE]; //记录棋盘上每一格的状态
extern int v[SIZE][SIZE]; //记录棋盘上每一格的分值
extern int current_x; //记录上一步落子
extern int current_y; //记录上一步落子
extern int l[SIZE*SIZE]; //记录每一步的落子
int i;
for(i=0;i<n;i++)
{
s[l[rd-1-i]/SIZE][l[rd-1-i]%SIZE]=0; //状态清零
v[l[rd-1-i]/SIZE][l[rd-1-i]%SIZE]=0; //值清零
}
rd-=n; //局数减少
current_x=l[rd-1]/SIZE;
current_y=l[rd-1]%SIZE;
}
void clear_string() //清空多余的无用的输入
{
char c;
while((c=getchar())!='\n')
;
}
/* 接下来的部分是整个程序的核心部分,也是最复杂的部分,内部多次错综复杂的多次调用很容易把人绕晕,于是我在此进行一些概括性的说明:
1.分数运算的大体思路:通过调用score_calculator,输入s[SIZE][SIZE]为整个棋盘的棋子状态,-1为黑子,1为白子,0为空,同时输入mod为1,正常计算这个棋盘上所有点的分值,
进入之后,它将进行点的筛选,滤去不需要考虑的点,留下我们需要的,并通过调用calculation函数,输入点的横纵坐标和mod4(这个为最后设计好的综合性算法,一个点的分值由
这一点的进攻得分,这一点的防守得分,这一点的防守疏漏扣分和这一点的第二步期望分数构成,具体比例为1,0.8,-0.7,0.6)进行这一点的分数计算,所有点计算完毕之后寻找并
返回分数最大值。
2.除上面的所提到的mod外,其它mod都是为了节省程序长度方便调用以实现相应功能而设计的,初次读时其实可以略过它们,在之后程序调用时都有些它们相应的含义,对号入座即可。
3.虽说一个点的得分由4个分数构成,但它们其实都是通过计算score_attack而得来:进攻得分为直接计算这一点的score_attack;防守得分为跳过己方落子,敌方的棋子落在这一点的
score_attack;防守疏忽扣分为自己将棋子落在这里,敌方下一颗棋子的最高score_attack;第二步的期望分数为这一步落子在这一点,下一步对手采用calculation的mod1(一个注重
防守的计算方式)进行落子,之后如果我们仍能形成双三、双四、三四、活四,甚至是直接胜利,那么给予这个点一个不少的加分。
4.score_attack的计算中引入了我自己的概念:meaningful_pieces——有意义的棋子数。这个函数的输入为棋子四个方向上周围的八颗棋子的状态,之后对每一个方向上的有意义的棋
子数进行判断,再根据有意义棋子数的多少给予相应的进攻得分。没有简单地对每一种情况进行分析,而是采取一种抽象的计算方式,是由于设计初期没有想明白要如何
分别讨论每一种情况,后期又觉得那本身太过麻烦,还容易出现疏漏,这样的计算方式得出来的结果也还不错,于是继续沿用了下去。
*/
void victory_judger(int s[SIZE][SIZE],int x,int y) //判断胜负(以第i行第j列为中心判断)
{
extern int state; //该变量用于改写棋盘状态
extern int rd; //该变量用于判断最后落子的是黑棋还是白棋
int type; //如果最后落子为黑子,其为1,白子为2
int i, j;
int a, b;
int left_1[4] = {0,0,0,0}; //记录x轴反方相同棋子的个数
int right_1[4] = {0,0,0,0}; //记录x轴正方相同棋子的个数
if(rd >= SIZE * SIZE){
state = -2;
}
if(state != 0){ //如果游戏结束
return;
}
switch(rd%2)
{
case 1:
type=-1;
break;
case 0:
type=1;
break;
default:
printf("error rd.");
break;
}
for(i = 0; i < 4; i++){
j = 1; a = dir_x(); b = dir_y();
while((x + j * a < SIZE) && (y + j * b < SIZE) && (x + j * a >= 0) && (y + j * b >= 0) && (s[x + j * a][y + j * b] == type)){ //当x轴正向的子与之相同时(前面的条件是为了保证不越界)
j++;
right_1[i]++;
}
j = 1;
while((x - j * a < SIZE) && (y - j * b <= SIZE) && (x - j * a >= 0) && (y - j * b >= 0) && (s[x - j * a][y - j * b] == type)) //当x轴反向的子与之相同时
{
j++;
left_1[i]++;
}
}
for(i = 0; i < 4; i++){
if(rd % 2 == 0){ //如果刚才为白棋落子,那么不进行禁手判断
if((left_1[i] + right_1[i]) >= 4){ //白棋只判断是否胜利
state = -1;
return;
}else{ //继续下一根轴检测
continue;
}
}else{ //如果是黑棋,需要考虑禁手状态
if((left_1[i] + right_1[i]) == 4){ //胜利
state = 1; //将状态改为对应的棋子胜利
return; //结束函数
}else if((left_1[i]+right_1[i]) > 4){ //长连禁手
state = 2; //黑子禁手状态,白棋获胜
return;
}
}
}
if(rd % 2 == 0){ //如果是白子,即使没有胜利也不进行下面的判断
return;
}
/*如果是黑子落子且没有胜利,那么继续进行禁手判断*/
if(Ban(s, x, y)){
printf("Ban!BAN!!BAN!!!Be Serious!");
state = 2;
return;
}
return;
}
void settle_accounts(int state,char turn) //结算程序 ***这个程序在main函数中只调用一次,当程序判断某一方胜利,或棋盘已经落满或玩家终止游戏时,程序会直接通过goto跳转到这个函数开始运行
{
extern int rd;
if(state==-2) //如果是平局
printf("Our match ended in a draw!\n");
else if(state==2)
printf("Black ban, and White victory!\n");
else if(turn=='1')
{
if(state==1)
switch(rd/25)
{
case 0:case 1:case 2:case 3:
case 4:case 5: case 6:
printf("Game over,and you win.\n");
break;
default:
printf("You win!\n");
break;
}
else if(state==-1)
switch(rd/25)
{
case 0:case 1:case 2:case 3:
case 4:case 5: case 6:
printf("Game over,and I win.\n");
break;
default:
printf("I win!\n");
break;
}
else
printf("I don't want to say anything else......\n");
}
else if(turn=='2') //如果为电脑先手,立场对转,继续使用上面的话语
{
state=-state;
turn='1';
settle_accounts(state, turn);
}
else if(turn=='3')
{
if(state==1)
printf("The black win!\n");
else if(state==-1)
printf("The white win!\n");
else
;
}
else
;
}
int dir_x(void)
{
static int angle=135; //角度,从零开始,每次增加45度,135度的下一次回到零
if(angle<135)
angle+=45;
else
angle=0;
switch(angle)
{
case 0:
return 0;
break;
case 45:case 90:case 135:
return 1;
break;
default:
printf("error angle\n");
return 0;
break;
}
}
int dir_y(void)
{
static int angle=135; //角度,从零开始,每次增加45度,135度的下一次回到零
if(angle<135)
angle+=45;
else
angle=0;
switch(angle)
{
case 0: case 45:
return 1;
break;
case 90:
return 0;
break;
case 135:
return -1;
break;
default:
printf("error angle.\n");
return 0;
break;
}
}
int scan(int x,int y) //扫描以点(x+1,y+1)为中心5*5范围内的棋子个数
{
extern int s[SIZE][SIZE];
int i,j;
int val=0; //返回值
for(i=0;i<5;i++)
for(j=0;j<5;j++)
if(x-2+i>=0 && x-2+i<=SIZE-1 && y-2+j>=0 && y-2+j<=SIZE-1) //如果在界内
if(s[x-2+i][y-2+j]==-1 || s[x-2+i][y-2+j]==1)
val++;
return val;
}
bool live_four(int left[4],int right[4]) //判断输入的序列是否是活四,这里略去了两头四四的情况没有考虑,不过这里的活四只是为了判断是否为活三而准备,如果已经是两头四四的话那已经形成了禁手,是否是活三变得没有意义
{
int type = -1; //需要判断的只有黑子
int i,j;
int a,b; //a为一变量,b为临时储存a的值
int left_1 = 0; //记录左方相同子的个数
int right_1 = 0; //记录右方相同子的个数
int count = 0; //统计可以形成5的点数
/*先判断一下是否还没放子的时候就已经是5颗了*/
for(j = 0; j < 4 && right[j] == type; j++){ //当右边的子与之相同时(前面的条件是为了保证不越界)
right_1++;
}
for(j = 0; j < 4 && left[j] == type; j++){ //当左边的子与之相同时(前面的条件是为了保证不越界)
left_1++;
}
if(left_1 + right_1 == 4){ //如果已经五连,那么不是活四,返回0,如果没有五连,什么也不做
return false;
}
for(a = 0; a < 8; a++){
left_1 = 0;
right_1 = 0;
if(a < 4){ //将left和right上的0依次改为type再判断是否形成五连,形成则可形成五连的点加1,注:这里的0是初始化给的0而非EMPTY,a<4是统计left
b = a;
if(left[a] == 0){
left[a] = type;
}else{
continue;
}
}else if(a >= 4){//a>=4是统计right
b = a;
a-=4;
if(right[a] == 0){
right[a] = type;
}else{
a = b;
continue;
}
}
for(j = 0; j < 4 && right[j] == type; j++){ //当左边的子与之相同时(前面的条件是为了保证不越界)
right_1++;
}
for(j = 0; j < 4 && left[j] == type; j++){ //当左边的子与之相同时(前面的条件是为了保证不越界)
left_1++;
}
if(left_1 + right_1 == 4){ //如果形成五连
count++;
}
if(b < 4){ //将改的值改回去
left[a] = 0;
}
else if(b >= 4){
right[a] = 0;
}
a = b;
}
if(count == 2){
return true;
}else{
return false;
}
}
bool live_three(int left[4],int right[4]) //判断是否为活三
{
int type = -1; //因为白棋不用判断,所以必为黑棋
int i,j;
int a,b; //a为一变量,b为临时储存a的值
if(live_four(left, right)){ //已经是活四,就不再是活三了
return false;
}
for(a = 0; a < 8; a++){
if(a < 4){ //将left和right上的0依次改为type再判断是否形成活四,注:这里的0是初始化给的0而非EMPTY,a<4是统计left
b = a;
if(left[a] == 0){
left[a] = type;
}else{
continue;
}
}else if(a >= 4){//a>=4是统计right
b = a;
a-=4;
if(right[a] == 0){
right[a] = type;
}else{
a = b;
continue;
}
}
if(live_four(left,right)){ //如果加一步之后形成活四,那么是活三
if(b < 4){ //将改的值改回去
left[a] = 0;
}else if(b >= 4){
right[a] = 0;
}
return true;
}else {
if(b < 4){ //将改的值改回去
left[a] = 0;
}else if(b >= 4){
right[a] = 0;
}
}
a = b;
}
return false;
}
bool Ban(int s[SIZE][SIZE], int x, int y){
int type = -1; // 黑棋判断禁手
int left[4][4] = { {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0} }; //用来储存这个点沿x轴反方向四轴的棋子状态
int right[4][4] = { {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0} }; //用来储存这个点沿x轴正方向四轴的棋子状态
int left_2[4] = {0,0,0,0}; //为live_three函数传递参数而准备的数组,下同
int right_2[4] = {0,0,0,0};
int i,j; //j为倍数
int a,b;
int fo_l[4],fo_r[4]; //表示上面数组中第一个其它棋子或是边界外的位置
int count[2] = {0,0}; //统计活三、活四或冲四的个数
int le[4] = {0,0,0,0},ri[4] = {0,0,0,0}; //对左右两边的状
for(i = 0; i < 4; i++){ //将点(x+1,y+1)水平,右斜,竖直,左斜的方向上4个棋子的状态读入上面两个数组中
a = dir_x(); b = dir_y();
for(j = 1; j < 5; j++){
if((x + j * a < SIZE) && (x + j * a >= 0) && (y + j * b < SIZE) && (y + j * b >= 0)){ //如果这颗子在边界内
right[i][j - 1] = s[x + j * a][y + j * b];
}
else{
right[i][j - 1] = -2; //如果不在边界内
}
if((x - j * a < SIZE) && (x - j * a >= 0) && (y - j * b < SIZE) && (y - j * b >= 0)){ //如果这颗子在边界内
left[i][j - 1] = s[x - j * a][y - j * b];
}
else{
left[i][j - 1] = -2; //如果不在边界内
}
}
}
for(i = 0; i < 4; i++){
for(j = 0; j < 4; j++){
if(left[i][j] != type && left[i][j] != 0){ //如果不是相同棋子也不是空位的话
fo_l[i] = j; //第一个其它棋子,或是边界外
break;
}
}
if(j == 4){ //如果四个都没有对手的棋子的话,空间充足
fo_l[i] = j;
}
for(j = 0; j < 4; j++){
if(right[i][j] != type && right[i][j] != 0){ //如果不是相同棋子也不是空位的话
fo_r[i]=j; //第一个其它棋子,或是边界外
break;
}
}
if(j == 4){ //如果四个都没有对手的棋子的话,空间充足
fo_r[i] = j;
}
}
for(i = 0; i < 4; i++){ //用le和ri对左右两边的状态进行编码,百位与fo_l/fo_r的值相同,剩下的0和1按二进制来编码,left[i][0]的权为8,left[i][3]的权为1,加入此编码的目的是为了解决c语言无法将两数组直接比较,于是换一种方便的表示方式来比较它们。
for(j = 0; j < fo_l[i]; j++){
le[i]+=abs(left[i][j])*pow(2,3-j); //剩下的0和1按二进制来编码,left[i][0]的权为8,left[i][3]的权为1
}
le[i]+=100*fo_l[i]; //百位与fo_l/fo_r的值相同
}
for(i = 0; i < 4; i++){ //用le和ri对左右两边的状态进行编码,百位与fo_l/fo_r的值相同,剩下的0和1按二进制来编码,right[i][0]的权为8,right[i][3]的权为1,加入此编码的目的是为了解决c语言无法将两数组直接比较,于是换一种方便的表示方式来比较它们。
for(j = 0; j < fo_r[i]; j++){
ri[i]+=abs(right[i][j])*pow(2,3-j); //剩下的0和1按二进制来编码,right[i][0]的权为8,right[i][3]的权为1
}
ri[i]+=100*fo_r[i]; //百位与fo_l/fo_r的值相同
}
for(i = 0; i < 4; i++){
switch(le[i] % 100){ //统计活四和冲四的个数
case 0:
if((ri[i] % 100) == 11 || (ri[i] % 100) == 13 || (ri[i] % 100) == 14 || (ri[i] % 100) == 7)
count[1]++;
break;
case 4:
if((ri[i] % 100) == 12)
count[1]++;
else if((ri[i] % 100) == 13) //特殊的两头四四
count[1]+=2;
break;
case 6:
if((ri[i] % 100) == 8)
count[1]++;
else if((ri[i] % 100) == 11) //特殊的两头四四
count[1]+=2;
break;
case 7:
if((ri[i] % 100) == 12)
count[1]++;
else if((ri[i] % 100) == 7) //特殊的两头四四
count[1]+=2;
break;
case 8:
if((ri[i] % 100) ==12 || (ri[i] % 100) == 6 || (ri[i] % 100) == 10)
count[1]++;
break;
case 10:
if((ri[i] % 100) == 10) //特殊的两头四四
count[1]+=2;
break;
case 11:
if((ri[i] % 100) == 0)
count[1]++;
else if((ri[i] % 100) == 6) //特殊的两头四四
count[1]+=2;
break;
case 12:
if((ri[i] % 100)==8 || (ri[i] % 100) == 4)
count[1]++;
break;
case 13:
if((ri[i] % 100) == 0)
count[1]++;
else if((ri[i] % 100) == 4) //特殊的两头四四
count[1]+=2;
break;
case 14:
if((ri[i]%100) == 0)
count[1]++;
break;
default:
break;
}
}
for(i = 0; i < 4; i++){ //统计活三的个数
for(j = 0; j < 4; j++){
left_2[j] = left[i][j]; //将数组left、right的第i行复制到left_2、right_2
right_2[j] = right[i][j];
}
if(live_three(left_2, right_2))
count[0]++;
}
if(count[0] >= 2 || count[1] >= 2){ //如果形成三三禁手或是四四禁手,白棋胜利
return true; //黑子禁手状态
}
return false;
}
int score_calculator(int s[SIZE][SIZE],int mod) //计算所有点的分值,mod1为正常的分数计算,mod2为计算并返回最高的进攻分值,mod3为score_step2中己方第一次落子后,对手通过calculation的mod1(偏防守型的综合计算方式)得到v_d并依据其进行落子,mod4计算最高的进攻得分(但加入了判断是否胜利,如果胜利的话会给一个高分)
{
extern int v[SIZE][SIZE];
int i,j;
int max_score=0;
int v_d[SIZE][SIZE]; //为了储存score_defense或score_step2的值而创建的临时数组
for(i=0;i<SIZE;i++) //初始化数组v_d
for(j=0;j<SIZE;j++)
v_d[i][j]=0;
for(i=0;i<SIZE;i++)
for(j=0;j<SIZE;j++)
{
if(s[i][j]==-1 || s[i][j]==1) //如果此处已经落子,跳过此点分值计算
continue;
else
;
if(scan(i,j)<1) //如果以这点为中心5*5的范围内没有棋子,我们不计算它
continue;
else
;
if(mod==1)
v[i][j]=calculation(i,j,4); //使用最后的综合算法计算这一点的分值
else if(mod==2)
v_d[i][j]=calculation(i,j,2); //计算这点的进攻分
else if(mod==3)
v_d[i][j]=calculation(i,j,1); //利用偏防御性的综合算法进行计算
else if(mod==4) //mod4时,先判断落子在此处是否会胜利,不会的话再进行分数计算
{
rd++;
victory_judger(s,i,j);
if(state!=0)
{
if(state==pow(-1,rd%2+1)) //如果己方胜利
v_d[i][j]=499999;
else
v_d[i][j]=-499999; //如果碰到禁手
state=0;
rd--;
}
else
{
rd--;
v_d[i][j]=calculation(i,j,2);
}
}
}
for(i=0;i<SIZE;i++) //寻找最大值并返回
for(j=0;j<SIZE;j++)
{
if(mod==1)
{
if(v[i][j]>max_score)
max_score=v[i][j];
else
;
}
else if(mod==2 || mod==4)
{
if(v_d[i][j]>max_score)
max_score=v_d[i][j];
else
;
}
}
if(mod==3)
{
input_computer(v_d);
return 0;
}
return max_score;
}
int calculation(int x,int y,int mod) //计算点(x+1,y+1)的分值
{
extern int s[SIZE][SIZE];
int left[4][4]={ {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0} }; //用来储存这个点四个方向左边的棋子状态
int right[4][4]={ {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0} }; //用来储存这个点四个方向右边的棋子状态
int a,b;
int i,j;
int score;
for(i=0;i<4;i++) //将点(x+1,y+1)水平,右斜,竖直,左斜的方向上4个棋子的状态读入上面两个数组中
{
a=dir_x(); b=dir_y();
for(j=1;j<5;j++)
{
if(x+j*a<=SIZE-1 && x+j*a>=0 && y+j*b<=SIZE-1 && y+j*b>=0) //如果这颗子在边界内
{
right[i][j-1]=s[x+j*a][y+j*b];
}
else
right[i][j-1]=-2; //如果不在边界内
if(x-j*a<=SIZE-1 && x-j*a>=0 && y-j*b<=SIZE-1 && y-j*b>=0) //如果这颗子在边界内
{
left[i][j-1]=s[x-j*a][y-j*b];
}
else
left[i][j-1]=-2; //如果不在边界内
}
}
switch(mod) //用mod来区分计算总分数和防守分数,mod1为总分,mod2为防守分数
{
case 1:
score=score_attack(left,right)+0.8*(score_add_to_defense(x,y))-0.7*(score_defense(x,y)); //较为偏重防守的算法
return score;
break;
case 2: case 3:
return score_attack(left,right);
break;
case 4:
score=score_attack(left,right)+0.8*(score_add_to_defense(x,y))-0.7*(score_defense(x,y))
+0.6*score_step2(x,y); //最后使用的综合算法
return score;
break;
default:
printf("wrong mod.\n");
break;
}
}
int score_attack(int left[4][4],int right[4][4]) //输入棋子周围的状态,计算进攻得分
{
extern int rd; //为了分辨棋子的种类
int i,j;
float a,b;
int type; //如果最后落子为黑子,其为-1,白子为1
float meaningful_pieces[4]={0,0,0,0};
int fo_l[4],fo_r[4]; //为上面数组中第一个其它棋子或是边界外的位置
int score=0; //分值
int left_ex[4][6]; //为了扩展left和right数组的大小,以实现一种统一,方便用循环来判断,以减少程序的长度
int right_ex[4][6];
int count[5]={0,0,0,0,0}; //统计有效棋子大于等于0、1、2、3、4的方向
int le[4]={0,0,0,0},ri[4]={0,0,0,0}; //对左右两边的状态进行编码,百位与fo_l/fo_r的值相同,剩下的0和1按二进制来编码,left[i][0]的权为8,left[i][3]的权为1,加入此编码的目的是为了解决c语言无法将两数组直接比较,于是换一种方便的表示方式来比较他们。
switch(rd%2) //如果最后落子为黑子,本次应下的为白子,故type为1,最后落子为白子,那么type为-1
{
case 1:
type=1;
break;
case 0:
type=-1;
break;
default:
printf("error rd.");
break;
}
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
if(left[i][j]!=type && left[i][j]!=0) //如果不是相同棋子也不是空位的话
{
fo_l[i]=j; //第一个其它棋子,或是边界外
break;
}
if(j==4) //如果四个都没有对手的棋子的话,空间充足
fo_l[i]=j;
for(j=0;j<4;j++)
if(right[i][j]!=type && right[i][j]!=0) //如果不是相同棋子也不是空位的话
{
fo_r[i]=j; //第一个其它棋子,或是边界外
break;
}
if(j==4) //如果四个都没有对手的棋子的话,空间充足
fo_r[i]=j;
if(fo_l[i]+fo_r[i]<=3) //两个对手的棋子之间的间隔小于等于4,没有意义
continue;
left_ex[i][0]=type;
right_ex[i][0]=type;
for(j=0;j<4;j++) //将left和right的值复制到ex数组里
{
left_ex[i][j+1]=left[i][j];
right_ex[i][j+1]=right[i][j];
}
left_ex[i][5]=-type;
right_ex[i][5]=-type;
for(j=0;j<fo_l[i];j++)
{
if(fo_r[i]==0)
meaningful_pieces[i]-=0.75; //如果反向第一颗是对手棋子或者边界的话,有意义棋子数减0.75
if(left[i][j]==type)
{
if(left_ex[i][j]==type && (left_ex[i][j+2]==type || left_ex[i][j+2]==0)) //如果这个棋子的右一个为相同棋子,且左边没有边界或对手棋子,那么这个棋子为一个有意义的棋子
meaningful_pieces[i]++;
else //如果左边有棋子,右边有边界或者对手棋子,这个棋子为0.25个有意义的棋子
{
a=1; //定义为这个棋子的价值
if(left_ex[i][j]==0) //如果左边为空的,它的价值变为一半
a*=0.5;
if(left_ex[i][j+2]==-type || left_ex[i][j+2]==-2) //如果右边为边界或对手棋子,它的价值变为四分之一
a*=0.25;
if(left_ex[i][j]==0 && left_ex[i][j-1]==0) //如果空了两个格,a的值变为0.05,由于0的左边必定为相同子,所以不必担心此越界问题
a*=0.1;
meaningful_pieces[i]+=a; //将这个棋子的值加上
}
}
}
for(j=0;j<fo_r[i];j++)
{
if(fo_l[i]==0)
meaningful_pieces[i]-=0.75; //如果反向第一颗是对手棋子或者边界的话,有意义棋子数减0.75
if(right[i][j]==type)
{
if(right_ex[i][j]==type && (right_ex[i][j+2]==type || right_ex[i][j+2]==0)) //如果这个棋子的左一个为相同棋子,且右边没有边界或对手棋子,那么这个棋子为一个有意义的棋子
meaningful_pieces[i]++;
else //如果右边有棋子,或左边有边界或者对手棋子.
{
b=1; //定义为这个棋子的价值
if(right_ex[i][j]==0) //如果右边为空的,它的价值变为一半
b*=0.5;
if(right_ex[i][j+2]==-type || right_ex[i][j+2]==-2) //如果左边为边界或对手棋子,它的价值变为四分之一
b*=0.25;
if(right_ex[i][j]==0 && right_ex[i][j-1]==0) //如果空了两个格,a的值变为0.05,由于0的右边必定为相同子,所以不必担心此越界问题
b*=0.1;
meaningful_pieces[i]+=b; //将这个棋子的值加上
}
}
}
}
for(i=0;i<4;i++) //统计4个方向中有意义棋子数大于等于0、1、2、3、4的个数
{
if(meaningful_pieces[i]>0)
count[0]++;
for(j=0;j<4;j++)
if(meaningful_pieces[j]>=(i+1))
count[i+1]++;
}
for(i=0;i<4;i++) //用le和ri对左右两边的状态进行编码,百位与fo_l/fo_r的值相同,剩下的0和1按二进制来编码,left[i][0]的权为8,left[i][3]的权为1,加入此编码的目的是为了解决c语言无法将两数组直接比较,于是换一种方便的表示方式来比较他们。
{
for(j=0;j<fo_l[i];j++)
le[i]+=abs(left[i][j])*pow(2,3-j); //剩下的0和1按二进制来编码,left[i][0]的权为8,left[i][3]的权为1
le[i]+=100*fo_l[i]; //百位与fo_l/fo_r的值相同
}
for(i=0;i<4;i++) //用le和ri对左右两边的状态进行编码,百位与fo_l/fo_r的值相同,剩下的0和1按二进制来编码,right[i][0]的权为8,right[i][3]的权为1,加入此编码的目的是为了解决c语言无法将两数组直接比较,于是换一种方便的表示方式来比较他们。
{
for(j=0;j<fo_r[i];j++)
ri[i]+=abs(right[i][j])*pow(2,3-j); //剩下的0和1按二进制来编码,right[i][0]的权为8,right[i][3]的权为1
ri[i]+=100*fo_r[i]; //百位与fo_l/fo_r的值相同
}
for(i=0;i<4;i++) //为因为上面简洁算法而被低估的一些状况进行修正
{
if(le[i]==406 && right[i][0]==0 && meaningful_pieces[i]<2) //XXX0A0AA0情形且meaningful_pieces小于2的情况,下同,X表示任意,0表示空,A表示我方棋子,B表示对方棋子
count[2]++;
if(ri[i]==406 && left[i][0]==0 && meaningful_pieces[i]<2)
count[2]++;
if(le[i]==108 && ri[i]==306) //XXBAA0AAB情况 下同
count[2]++;
if(le[i]==306 && ri[i]==108)
count[2]++;
if(le[i]==108 && ri[i]==310) //XXBAAA0AB情况 下同
count[2]++;
if(le[i]==310 && ri[i]==108)
count[2]++;
}
score=10*count[0]+100*count[1]+1000*count[2]+10000*count[3]+100000*count[4];
return score;
}
int score_defense(int x,int y) //输入棋子坐标,计算防守扣分
{
extern int v[SIZE][SIZE];
extern int s[SIZE][SIZE];
extern int rd;
extern int state;
int de_score;
switch(rd%2) //手动落子
{
case 0:
s[x][y]=-1;
rd++;
break;
case 1:
s[x][y]=1;
rd++;
break;
default:
printf("error rd.\n");
break;
}
de_score=score_calculator(s,2); //调用分数计算程序的mod2来计算防守分数
victory_judger(s,x,y);
if(state!=0) //如果我方落子后胜利了,给这个点一个大量的加分
{
if(state==pow(-1,rd%2+1))
de_score=-999999; //赋值,为加分,所以为负值
else //我方落在了禁手上
de_score=999999; //给一个大扣分
state=0; //将state重置
}
rd--; //归位
s[x][y]=0;
return de_score;
}
int score_add_to_defense(int x,int y) //输入棋子坐标,计算防守加分
{
extern int rd;
extern int state;
int de_score;
rd++;
de_score=calculation(x,y,3); //调用分数计算程序的mod3来计算这一点的防守分数
rd--;
victory_judger(s,x,y); //如果对方落子后胜利了,那么给这点一个大量的防守加分,由于本程序用于在落子后计算,所以在落子就计算时不需要加rd
if(state!=0)
{
if(state==pow(-1,rd%2+1)) //对手胜利,给一个大防守加分
de_score=999999; //赋值
else
de_score=-999999; //对手碰到禁手,不防守这点,减分
state=0;
}
return de_score;
}
int score_step2(int x,int y)
{
extern int v[SIZE][SIZE];
extern int s[SIZE][SIZE];
extern int rd;
extern int state;
extern int current_x; //记录上一步落子
extern int current_y; //记录上一步落子
extern int l[SIZE*SIZE]; //记录每一步的落子
int step2_score;
int i;
v[x][y]=9999999;
input_computer(v);
score_calculator(s,3); //mod3状态下的权衡分数计算偏防守,如果在对面防守了的情况下,我们的第二步仍能够胜利、形成活四、形成双三等,给予对应的加分
//本应放在这里进行的落子由于无法读取v_d而放在了score_calculator中
step2_score=score_calculator(s,4); //利用mod4计算最高的进攻得分并判断是否会胜利
i=0;
s[l[rd-1-i]/SIZE][l[rd-1-i]%SIZE]=0; //状态清零
i=1;
s[l[rd-1-i]/SIZE][l[rd-1-i]%SIZE]=0; //状态清零
rd-=2; //局数减少
if(step2_score>2000)
return step2_score;
else
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <time.h>
#include <assert.h>
#include <limits.h>
#define Board_Size 10
#define TRUE 1
#define FALSE 0
#define Hashsize 67108864 //(2GB)67108864 (4GB)134217728 (8GB)268435456
//等待ms
void Delay(unsigned int mseconds);
//讀取最新一步
void Read_File( char *c );
//讀檔並開始遊戲
char Load_File( void );
//初始化棋盤
void Init();
//判斷下子合法性
int Play_a_Move( int x, int y);
//顯示棋盤狀況
void Show_Board_and_Set_Legal_Moves( void );
//下子
int Put_a_Stone( int x, int y );
//判斷是否在棋盤內
int In_Board( int x, int y );
//判斷是否可吃棋
int Check_Cross( int x, int y, int update );
//判斷d方向是否可吃棋,update為執行吃棋訊號
int Check_Straight_Army( int x, int y, int d, int update );
//更新合法步,返回合法步數
int Find_Legal_Moves(int color);
//判斷是否終局
int Check_EndGame( void );
//更新比數
int Compute_Grades(int flag ,int isL);
//決定下棋點
void Computer_Think( int *x, int *y);
//MinMax
int Search(int myturn, int mylevel);
//遞迴深度搜索
int search_next(int x, int y, int myturn, int mylevel, int alpha, int beta);
//排序函數
int comparH(const void* a,const void* b);
//U64 隨機數產生器
long long int rand64(void);
//計算zobristHash
long long int getHash(void);
//計算穩定子
int StableDiscs(int me);
int search_deep = 4;
int Search_Counter;
int Computer_Take;
int Winner;
int Now_Board[ Board_Size ][ Board_Size ];
int Legal_Moves[ Board_Size ][ Board_Size ];
int Legal_Move_Index[50][3];
int HandNumber;
int sequence[100];
int Black_Count, White_Count;
int Turn = 0; // 0 is black or 1 is white
int Stones[2]= {1,2}; // 1: black, 2: white
int DirX[8] = {0, 1, 1, 1, 0, -1, -1, -1};
int DirY[8] = {-1, -1, 0, 1, 1, 1, 0, -1};
int LastX, LastY;
int resultX, resultY;
typedef struct location{
int i;
int j;
int g;
} Location;
int B, W;
int Dynamicdeep = 10; //動態深度
int DynamicdeepS = 0; //加深開始手數
int DynamicdeepE = 0; //加深結束手數
int deepStart = 4; //初始深度
int deepEnd = 8; //最終深度
int endTime = 80; //終局搜索 Pefect End
int fS = 4; //穩定子權重 StableDiscs Weight
int fRandomMove = true; //初始隨機下子
int RandomMove = 2; //初始隨機手數
int fiterative = true; //遞代加深 Iterative Deepening
int fMTD = true; //記憶測試 MTD Memory-enhanced Test Driver
int alpha_beta_option = true; //AB剪枝 Alpha-Beta
double historyAttenua = 0.2; //歷史衰減 History attenuation coefficient
Location history[2][100][100]; //歷史表 Move Ordering
int zhash = true; //置換表 transposition table
struct{
long long int checksum;
char depth;
char entry_type; //0=exact, 1=lower_bound, 2=upper_bound
int g;
} hashtable[2][Hashsize];
long long int zobrist[2][Board_Size][Board_Size]; //Zobrist Hash
//測試資料
long long int Hashnode = 0;
long long int Searchnode = 0;
long long int Grades = 0;
//---------------------------------------------------------------------------
int main(void){
char compcolor = 'W', c[10];
int column_input = -1, row_input = -1;
int rx, ry, m=0, n;
FILE *fp;
Init();
printf("Computer take?(B/W/All/File play as first/file play as Second/Load and play): ");
scanf("%c", &compcolor);
Show_Board_and_Set_Legal_Moves();
if (compcolor == 'L' || compcolor == 'l')
compcolor = Load_File();
if ( compcolor == 'B' || compcolor == 'b'){
Computer_Think( &rx, &ry );
printf("Computer played %c%d\n", rx+97, ry+1);
Play_a_Move( rx, ry );
Show_Board_and_Set_Legal_Moves();
}
if ( compcolor == 'A' || compcolor == 'a')
while ( m++ < Board_Size * Board_Size ){
Computer_Think( &rx, &ry );
if ( !Play_a_Move( rx, ry )){
printf("Wrong Computer moves %c%d\n", rx+97, ry+1);
scanf("%d", &n);
break;
}
if ( rx == -1 )
printf("Computer Pass\n");
else
printf("Computer played %c%d\n", rx+97, ry+1);
if ( Check_EndGame() )
return 0;
Show_Board_and_Set_Legal_Moves();
}
if ( compcolor == 'F'){
Computer_Think( &rx, &ry );
Play_a_Move( rx, ry );
}
while ( m++ < Board_Size*Board_Size ){
for(;;){
if ( compcolor == 'F' || compcolor == 'S' ){
fp = fopen( "of.txt", "r" );
fscanf( fp, "%d", &n );
fclose( fp );
c[2]=' ';
if (compcolor == 'F' ){
if ( n % 2 == 0 )
Read_File( c );
else{
Delay(101);
continue;
}
}
else{
if ( n % 2 == 1 )
Read_File( c );
else{
Delay(101);
continue;
}
}
}
if ( compcolor == 'B' || compcolor == 'b'){
printf("input White move:(a-h 1-8), or PASS\n");
scanf("%s", c);
}
else if ( compcolor == 'W' || compcolor == 'w'){
printf("input Black move:(a-h 1-8), or PASS\n");
scanf("%s", c);
}
if ( c[0] == 'P' || c[0] == 'p')
row_input = column_input = -1;
else if ( c[0] == 'M' || c[0] == 'm' ){
Computer_Think( &rx, &ry );
if ( !Play_a_Move( rx, ry )){
printf("Wrong Computer moves %c%dŝ\n", rx+97, ry+1);
scanf("%d", &n);
break;
}
if ( rx == -1 )
printf("Computer Pass");
else
printf("Computer played %c%d\n", rx+97, ry+1);
if ( Check_EndGame() )
break;
Show_Board_and_Set_Legal_Moves();
}
else{
row_input= c[0] - 97;
if (c[2] == '0'){
column_input = 9;
}
else{
column_input = c[1] - 49;
}
}
if ( !Play_a_Move(row_input, column_input) ){
printf("%c%d is a Wrong move!\n", c[0], column_input+1);
}
else
break;
}
if ( Check_EndGame() )
return 0;
Show_Board_and_Set_Legal_Moves();
Computer_Think( &rx, &ry );
printf("Computer played %c%d\n", rx+97, ry+1);
Play_a_Move( rx, ry );
if ( Check_EndGame() )
return 0;;
Show_Board_and_Set_Legal_Moves();
}
printf("Game is over");
scanf("%d", &n);
return 0;
}
void Delay(unsigned int mseconds){
clock_t goal = mseconds + clock();
while (goal > clock());
}
void Read_File( char *c ){
FILE *fp;
char tc[10];
fp = fopen( "of.txt", "r" );
while ( (fscanf( fp, "%s", tc ) ) != EOF ){
c[2] = 'a';
c[0] = tc[0];
if (tc[2] == 48){
c[1] = '1';
c[2] = '0';
}
else{
c[1] = tc[1];
}
}
}
char Load_File( void ){
FILE *fp;
char tc[10];
int row_input, column_input, n;
fp = fopen( "of.txt", "r" );
assert( fp != NULL );
fscanf( fp, "%d", &n );
printf("n = %d\n",n);
while ( (fscanf( fp, "%s", tc ) ) != EOF ){
column_input = tc[0] - 97;
row_input = tc[1] - 49;
if (tc[2] == 48){
column_input = 9;
}
if ( !Play_a_Move(row_input, column_input) )
printf("%c%d is a Wrong move\n", tc[0], column_input+1);
Show_Board_and_Set_Legal_Moves();
tc[2] =' ';
}
return ( n%2 == 1 )? 'B' : 'W';
}
void Init(){
srand( (unsigned)time(NULL) );
Computer_Take = 0;
memset(Now_Board, 0, sizeof(int) * Board_Size * Board_Size);
Now_Board[4][4] = Now_Board[5][5] = 2;//white, dark
Now_Board[4][5] = Now_Board[5][4] = 1;//black, light
HandNumber = 0;
memset(sequence, -1, sizeof(int) * Board_Size * Board_Size);
Turn = 0;
LastX = LastY = -1;
Black_Count = White_Count = 0;
Search_Counter = 0;
Winner = 0;
//初始化歷史表
Location tempL;
for( int i = 0,m = 0; i < Board_Size; i++ ){
for( int j = 0; j < Board_Size; j++,m++){
tempL.i = i;
tempL.j = j;
tempL.g = -1;
for(int k = 0; k<Board_Size*Board_Size; k++){
history[0][k][m] = tempL;
history[1][k][m] = tempL;
}
}
}
//初始化置換表
for( int i = 0; i < Board_Size; i++ ){
for( int j = 0; j < Board_Size; j++){
zobrist[0][i][j] = rand64();
zobrist[1][i][j] = rand64();
}
}
}
int Play_a_Move( int x, int y){
FILE *fp;
if ( x == -1 && y == -1){
fp = fopen( "of.txt", "r+" );
fprintf( fp, "%2d\n", HandNumber+1 );
fclose(fp);
fp = fopen("of.txt", "a");
fprintf( fp, "p9\n" );
fclose( fp );
sequence[HandNumber] = -1;
HandNumber ++;
Turn = 1 - Turn;
return 1;
}
if ( !In_Board(x,y))
return 0;
Find_Legal_Moves( Stones[Turn] );
if( Legal_Moves[x][y] == FALSE )
return 0;
if( Put_a_Stone(x,y) ){
Check_Cross(x,y,1);
Compute_Grades( TRUE ,0);
return 1;
}
else
return 0;
return 1;
}
int Put_a_Stone(int x, int y){
FILE *fp;
if( Now_Board[x][y] == 0){
sequence[HandNumber] = Turn;
if (HandNumber == 0)
fp = fopen( "of.txt", "w" );
else
fp = fopen( "of.txt", "r+" );
fprintf( fp, "%2d\n", HandNumber+1 );
HandNumber ++;
fclose(fp);
Now_Board[x][y] = Stones[Turn];
fp = fopen("of.txt", "a");
fprintf( fp, "%c%d\n", x+97, y+1 );;
fclose( fp );
LastX = x;
LastY = y;
Turn = 1 - Turn;
return TRUE;
}
return FALSE;
}
void Show_Board_and_Set_Legal_Moves( void ){
int i,j;
Find_Legal_Moves( Stones[Turn] );
//printf("a b c d e f g h i j\n");
for(i=0 ; i<Board_Size ; i++){
for(j=0 ; j<Board_Size ; j++){
if( Now_Board[j][i] > 0 ){
if ( Now_Board[j][i] == 2 )
printf("W ");//white
else
printf("B ");//black
}
if (Now_Board[j][i] == 0){
if ( Legal_Moves[j][i] == 1)
printf("? ");
else printf(". ");
}
}
printf(" %d\n", i+1);
}
printf("\n");
printf("a b c d e f g h i j\n");
}
int Check_Cross(int x, int y, int update){
int k, dx, dy;
if( ! In_Board(x,y) || Now_Board[x][y] == 0)
return FALSE;
int army = 3 - Now_Board[x][y];
int army_count = 0;
for( k=0 ; k<8 ; k++ ){
dx = x + DirX[k];
dy = y + DirY[k];
if( In_Board(dx,dy) && Now_Board[dx][dy] == army ){
army_count += Check_Straight_Army( x, y, k, update ) ;
}
}
if(army_count >0)
return TRUE;
else
return FALSE;
}
int Check_Straight_Army(int x, int y, int d, int update){
int me = Now_Board[x][y];
int army = 3 - me;
int army_count=0;
int found_flag=FALSE;
int flag[ Board_Size ][ Board_Size ] = {{0}};
int i, j;
int tx, ty;
tx = x;
ty = y;
for(i=0 ; i<Board_Size ; i++){
tx += DirX[d];
ty += DirY[d];
if(In_Board(tx,ty) ){
if( Now_Board[tx][ty] == army ){
army_count ++;
flag[tx][ty] = TRUE;
}
else if( Now_Board[tx][ty] == me){
found_flag = TRUE;
break;
}
else
break;
}
else
break;
}
if( (found_flag == TRUE) && (army_count > 0) && update){
for(i=0 ; i<Board_Size ; i++)
for(j=0; j<Board_Size ; j++)
if(flag[i][j]==TRUE){
if(Now_Board[i][j] != 0)
Now_Board[i][j]= 3 - Now_Board[i][j];
}
}
if( (found_flag == TRUE) && (army_count > 0))
return army_count;
else return 0;
}
int In_Board(int x, int y){
if( x >= 0 && x < Board_Size && y >= 0 && y < Board_Size )
return TRUE;
else
return FALSE;
}
int Check_EndGame( void ){
int lc1, lc2;
lc2 = Find_Legal_Moves( Stones[1 - Turn] );
lc1 = Find_Legal_Moves( Stones[Turn] );
if ( lc1==0 && lc2==0 ){
if(Black_Count > White_Count){
printf("Black Win!\n");
if(Winner == 0)
Winner = 1;
}
else if(Black_Count < White_Count){
printf("White Win!\n");
if(Winner == 0)
Winner = 2;
}
else{
printf("Draw\n");
Winner = 0;
}
Show_Board_and_Set_Legal_Moves();
printf("Game is over\n");
printf("Hashnode = %12.lld \n",Hashnode);
printf("Searchnode = %12.lld \n",Searchnode);
printf("Grades = %12.lld \n",Grades);
scanf("%d", &lc1);
return TRUE;
}
return FALSE;
}
int comparH(const void* a,const void* b){
Location* aa = (Location*)a;
Location* bb = (Location*)b;
return bb->g - aa->g;
}
void Computer_Think( int *x, int *y ){
if (fRandomMove && HandNumber < RandomMove ) { //初始隨機下子
int lm = Find_Legal_Moves( Stones[Turn]);
int RMV = ( rand() % lm ) +1 ;
*x = Legal_Move_Index[RMV][1];
*y = Legal_Move_Index[RMV][2];
return;
}
else{
time_t clockBegin, clockEnd;
static int think_time=0;
int flag = 0;
//歷史表衰減
if(historyAttenua != 0){
for(int i=0; i<Board_Size*Board_Size; i++){
for(int j=0; j<Board_Size*Board_Size; j++){
history[0][i][j].g *= historyAttenua;
history[1][i][j].g *= historyAttenua;
}
}
}
//動態深度
if(DynamicdeepS <= HandNumber && HandNumber <= DynamicdeepE){
deepEnd = Dynamicdeep+2;
}
//終局搜索
else if(HandNumber >= endTime){
deepEnd = (Board_Size*Board_Size) - HandNumber;
}
else{
deepEnd = Dynamicdeep;
}
clockBegin = clock();
resultX = resultY = -1;
Search_Counter = 0;
flag = Search( Turn, 0);
clockEnd = clock();
think_time += (clockEnd - clockBegin)/1000;
printf("used thinking time= %d min. %d.%d sec.\n", think_time/60000, (think_time%60000)/1000, (think_time%60000)%1000);
if( flag ){
*x = resultX;
*y = resultY;
}
else{
*x = *y = -1;
return;
}
}
}
int Search(int myturn, int mylevel){
if(Find_Legal_Moves(Stones[myturn]) <= 0)
return FALSE;
int B[ Board_Size ][ Board_Size ];
int L[ Board_Size ][ Board_Size ];
memcpy( B, Now_Board, sizeof(int) * Board_Size * Board_Size );
memcpy( L, Legal_Moves, sizeof(int) * Board_Size * Board_Size );
Location min, max;
min.i = min.j = -1; min.g = INT_MAX;
max.i = max.j = -1; max.g = INT_MIN;
int i, j, k, test, g;
int alpha = INT_MIN, beta = INT_MAX;
for( k = 0; k < Board_Size*Board_Size; k++ ){
i = history[myturn][mylevel][k].i;
j = history[myturn][mylevel][k].j;
if(L[i][j] == TRUE){
memcpy(Now_Board, B, sizeof(int) * Board_Size * Board_Size );
Now_Board[i][j] = Stones[myturn];
Check_Cross(i,j,TRUE);
//遞代加深
for(search_deep = deepStart, g=0; search_deep <= deepEnd; search_deep+=2){
if(fiterative == FALSE)
search_deep = deepEnd;
//MTD
if(fMTD){
beta = INT_MAX;
alpha = INT_MIN;
test = g;
do{
g = search_next(i,j, 1-myturn, mylevel+1, test-1, test);
if (g < test)
test = beta = g;
else{
alpha = g;
test = g + 1;
}
}while( alpha < beta );
}
else
g = search_next(i,j, 1-myturn, mylevel+1, alpha, beta);
}
if( myturn == 0 ){ // max level
if( g > max.g ){
max.g = g;
max.i = i;
max.j = j;
}
}
else{
if( g < min.g ){ // min level
min.g = g;
min.i = i;
min.j = j;
}
}
// cutoff
if( alpha_beta_option )
if( alpha >= beta){
i = Board_Size;
j = Board_Size;
}
}
}
memcpy( Now_Board, B, sizeof(int) * Board_Size * Board_Size );
if( myturn == 0 ){
resultX = max.i;
resultY = max.j;
return TRUE;
}
else{
resultX = min.i;
resultY = min.j;
return TRUE;
}
return FALSE;
}
int search_next( int x, int y, int myturn, int mylevel, int alpha, int beta ){
long long int hash64;
long long int hash32;
if( mylevel >= search_deep ){
hash64 = getHash();
hash32 = hash64 & (Hashsize-1);
hashtable[myturn][hash32].checksum = hash64;
hashtable[myturn][hash32].depth = 0;
hashtable[myturn][hash32].entry_type = 0;
hashtable[myturn][hash32].g = Compute_Grades( FALSE ,0);
return hashtable[myturn][hash32].g;
}
if(Find_Legal_Moves( Stones[myturn] ) <= 0){
return Compute_Grades( FALSE ,1);
}
Search_Counter++;
int i,j,k,g=0;
int B[ Board_Size ][ Board_Size ];
int L[ Board_Size ][ Board_Size ];
memcpy( B, Now_Board, sizeof(int) * Board_Size * Board_Size );
memcpy( L, Legal_Moves, sizeof(int) * Board_Size * Board_Size );
int fentry_type = 2;
for( k = 0; k < Board_Size*Board_Size; k++ ){
i = history[myturn][mylevel][k].i;
j = history[myturn][mylevel][k].j;
if(L[i][j] == TRUE){
memcpy(Now_Board, B, sizeof(int) * Board_Size * Board_Size );
Now_Board[i][j] = Stones[myturn];
Check_Cross(i,j, TRUE) ;
hash64 = getHash();
hash32 = hash64 & (Hashsize-1);
int flag = false;
if(zhash && hashtable[1-myturn][hash32].checksum == hash64 &&
hashtable[1-myturn][hash32].depth >= search_deep-(mylevel+1)){
if(hashtable[1-myturn][hash32].entry_type == 0){
Hashnode++;
g = hashtable[1-myturn][hash32].g;
flag = true;
}
else if(hashtable[1-myturn][hash32].entry_type == 1){
if((1-myturn) == 0 && hashtable[1-myturn][hash32].g >= beta){
Hashnode++;
g = hashtable[1-myturn][hash32].g;
flag = true;
}
else if((1-myturn) == 1 && hashtable[1-myturn][hash32].g <= alpha){
Hashnode++;
g = hashtable[1-myturn][hash32].g;
flag = true;
}
}
else if(hashtable[1-myturn][hash32].entry_type == 2){
if ((1-myturn) == 0 && hashtable[1-myturn][hash32].g <= alpha){
Hashnode++;
g = hashtable[1-myturn][hash32].g;
flag = true;
}
else if((1-myturn) == 1 && hashtable[1-myturn][hash32].g >= beta){
Hashnode++;
g = hashtable[1-myturn][hash32].g;
flag = true;
}
}
}
if(flag == false){
Searchnode++;
g = search_next(i,j, 1-myturn, mylevel+1, alpha, beta);
}
if(myturn==0){ // max ply
if(g > alpha){
alpha = g;
history[myturn][mylevel][k].g += 2*mylevel*mylevel; //普通的節點
fentry_type = 0;
}
history[myturn][mylevel][k].g -= 2*mylevel*mylevel; //較差的節點
}
else{ // min ply
if(g < beta){
beta = g;
history[myturn][mylevel][k].g += 2*mylevel*mylevel; //普通的節點
fentry_type = 0;
}
history[myturn][mylevel][k].g -= 2*mylevel*mylevel; //較差的節點
}
// cutoff
if( alpha_beta_option )
if( alpha >= beta ){
i = Board_Size;
j = Board_Size;
history[myturn][mylevel][k].g += 16*mylevel*mylevel; //優先的節點
fentry_type = 1;
break;
}
}
}
memcpy(Now_Board, B, sizeof(int) * Board_Size * Board_Size);
//排序節點優先度
qsort(history[myturn][mylevel], Board_Size * Board_Size, sizeof(history[myturn][mylevel][0]), comparH);
hash64 = getHash();
hash32 = hash64 & (Hashsize-1);
if(myturn == 0){ //max level
if(hashtable[myturn][hash32].depth <= search_deep-mylevel){
hashtable[myturn][hash32].checksum = hash64;
hashtable[myturn][hash32].depth = search_deep-mylevel;
hashtable[myturn][hash32].entry_type = fentry_type;
hashtable[myturn][hash32].g = alpha;
}
return alpha;
}
else{ //min level
if(hashtable[myturn][hash32].depth <= search_deep-mylevel){
hashtable[myturn][hash32].checksum = hash64;
hashtable[myturn][hash32].depth = search_deep-mylevel;
hashtable[myturn][hash32].entry_type = fentry_type;
hashtable[myturn][hash32].g = beta;
}
return beta;
}
}
long long int rand64(void) {
return rand() ^ ((long long int)rand() << 15) ^ ((long long int)rand() << 30) ^ ((long long int)rand() << 45) ^ ((long long int)rand() << 60);
}
long long int getHash(void){
long long int hash=0;
for(int i=0; i < Board_Size; i++){
for(int j=0; j < Board_Size; j++){
if(Now_Board[i][j] == 1){
hash ^= zobrist[0][i][j];
}
else if(Now_Board[i][j] == 2){
hash ^= zobrist[1][i][j];
}
}
}
return hash;
}
int Find_Legal_Moves( int color ){
int i,j;
int me = color;
int legal_count = 0;
Legal_Move_Index[0][0] = 0;
B = W = 0;
for( i = 0; i < Board_Size; i++ )
for( j = 0; j < Board_Size; j++ )
Legal_Moves[i][j] = 0;
for( i = 0; i < Board_Size; i++ )
for( j = 0; j < Board_Size; j++ ){
if( Now_Board[i][j] == 0 ){
//剪枝加速
if( i>0 && i<Board_Size-1 && j>0 && j<Board_Size-1 ){
if((Now_Board[i-1][j-1] == 0 || Now_Board[i-1][j-1] == me) &&
(Now_Board[i-1][j] == 0 || Now_Board[i-1][j] == me) &&
(Now_Board[i-1][j+1] == 0 || Now_Board[i-1][j+1] == me) &&
(Now_Board[i][j-1] == 0 || Now_Board[i][j-1] == me) &&
(Now_Board[i][j+1] == 0 || Now_Board[i][j+1] == me) &&
(Now_Board[i+1][j-1] == 0 || Now_Board[i+1][j-1] == me) &&
(Now_Board[i+1][j] == 0 || Now_Board[i+1][j] == me) &&
(Now_Board[i+1][j+1] == 0 || Now_Board[i+1][j+1] == me)){
continue;
}
}
Now_Board[i][j] = me;
if( Check_Cross(i,j,FALSE) == TRUE ){
Legal_Moves[i][j] = TRUE;
legal_count++;
Legal_Move_Index[0][0] = legal_count;
Legal_Move_Index[legal_count][1] = i ;
Legal_Move_Index[legal_count][2] = j ;
}
Now_Board[i][j] = 0;
}
else if( Now_Board[i][j] == 1 ){
B++;
}
else if( Now_Board[i][j] == 2 ){
W++;
}
}
return legal_count;
}
int Compute_Grades(int flag, int isL){
if(flag){
Find_Legal_Moves( 1 );
Black_Count = B;
White_Count = W;
printf("Grade: Black %d, White %d\n", B, W);
return 0;
}
Grades++;
//中局
if( HandNumber < endTime ){
int SB, SW, BM;
SB = StableDiscs(1);
SW = StableDiscs(2);
if( isL == 0 ){
BM = Find_Legal_Moves( 1 );
}
else{
BM = Legal_Move_Index[0][0];
}
return ( fS*(SB - SW) + BM);
}
//尾局
else{
if( isL == 0 ){
B = 0;
for(int i=0; i<Board_Size; i++)
for(int j=0; j<Board_Size; j++){
if( Now_Board[i][j] == 1 ){
B++;
}
}
}
return ( B );
}
}
int StableDiscs(int me){
int i, j, k, num = 0;
int a=0,b=0,c=0,d=0;
//左上角
i = 0;
j = 0;
if(Now_Board[i][j] == me){
num++;
for(k=1; k<Board_Size; k++){
if(Now_Board[i+k][j] != me)
break;
num++;
}
if(k == Board_Size)
a++;
for(k=1; k<Board_Size; k++){
if(Now_Board[i][j+k] != me)
break;
num++;
}
if(k == Board_Size)
d++;
}
//右上角
i = Board_Size-1;
j = 0;
if(Now_Board[i][j] == me){
num++;
for(k=1; k<Board_Size; k++){
if(Now_Board[i-k][j] != me)
break;
num++;
}
if(k == Board_Size)
a++;
for(k=1; k<Board_Size; k++){
if(Now_Board[i][j+k] != me)
break;
num++;
}
if(k == Board_Size)
b++;
}
//左下角
i = 0;
j = Board_Size-1;
if(Now_Board[i][j] == me){
num++;
for(k=1; k<Board_Size; k++){
if(Now_Board[i+k][j] != me)
break;
num++;
}
if(k == Board_Size)
c++;
for(k=1; k<Board_Size; k++){
if(Now_Board[i][j-k] != me)
break;
num++;
}
if(k == Board_Size)
d++;
}
//右下角
i = Board_Size-1;
j = Board_Size-1;
if(Now_Board[i][j] == me){
num++;
for(k=1; k<Board_Size; k++){
if(Now_Board[i-k][j] != me)
break;
num++;
}
if(k == Board_Size)
c++;
for(k=1; k<Board_Size; k++){
if(Now_Board[i][j-k] != me)
break;
num++;
}
if(k == Board_Size)
b++;
}
if(a > 1)
num -= Board_Size;
if(b > 1)
num -= Board_Size;
if(c > 1)
num -= Board_Size;
if(d > 1)
num -= Board_Size;
return num;
}
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <time.h>
#include <assert.h>
#include <limits.h>
#define Board_Size 8
#define TRUE 1
#define FALSE 0
#define Hashsize 67108864 //(2GB)67108864 (4GB)134217728 (8GB)268435456
//等待ms
void Delay(unsigned int mseconds);
//讀取最新一步
void Read_File( char *c );
//讀檔並開始遊戲
char Load_File( void );
//初始化棋盤
void Init();
//判斷下子合法性
int Play_a_Move( int x, int y);
//顯示棋盤狀況
void Show_Board_and_Set_Legal_Moves( void );
//下子
int Put_a_Stone( int x, int y );
//判斷是否在棋盤內
int In_Board( int x, int y );
//判斷是否可吃棋
int Check_Cross( int x, int y, int update );
//判斷d方向是否可吃棋,update為執行吃棋訊號
int Check_Straight_Army( int x, int y, int d, int update );
//更新合法步,返回合法步數
int Find_Legal_Moves(int color);
//判斷是否終局
int Check_EndGame( void );
//更新比數
int Compute_Grades(int flag ,int isL);
//決定下棋點
void Computer_Think( int *x, int *y);
//MinMax
int Search(int myturn, int mylevel);
//遞迴深度搜索
int search_next(int x, int y, int myturn, int mylevel, int alpha, int beta);
//排序函數
int comparH(const void* a,const void* b);
//U64 隨機數產生器
long long int rand64(void);
//計算zobristHash
long long int getHash(void);
//計算穩定子
int StableDiscs(int me);
int search_deep = 4;
int Search_Counter;
int Computer_Take;
int Winner;
int Now_Board[ Board_Size ][ Board_Size ];
int Legal_Moves[ Board_Size ][ Board_Size ];
int Legal_Move_Index[50][3];
int HandNumber;
int sequence[Board_Size*Board_Size];
int Black_Count, White_Count;
int Turn = 0; // 0 is black or 1 is white
int Stones[2]= {1,2}; // 1: black, 2: white
int DirX[8] = {0, 1, 1, 1, 0, -1, -1, -1};
int DirY[8] = {-1, -1, 0, 1, 1, 1, 0, -1};
int LastX, LastY;
int resultX, resultY;
typedef struct location{
int i;
int j;
int g;
} Location;
int B, W;
int Dynamicdeep = 10; //動態深度
int DynamicdeepS = 0; //加深開始手數
int DynamicdeepE = 0; //加深結束手數
int deepStart = 4; //初始深度
int deepEnd = 8; //最終深度
int endTime = 46; //終局搜索 Pefect End
int fS = 4; //穩定子權重 StableDiscs Weight
int fRandomMove = true; //初始隨機下子
int RandomMove = 2; //初始隨機手數
int fiterative = true; //遞代加深 Iterative Deepening
int fMTD = true; //記憶測試 MTD Memory-enhanced Test Driver
int alpha_beta_option = true; //AB剪枝 Alpha-Beta
double historyAttenua = 0.2; //歷史衰減 History attenuation coefficient
Location history[2][Board_Size*Board_Size][Board_Size*Board_Size]; //歷史表 Move Ordering
int zhash = true; //置換表 transposition table
struct{
long long int checksum;
char depth;
char entry_type; //0=exact, 1=lower_bound, 2=upper_bound
int g;
} hashtable[2][Hashsize];
long long int zobrist[2][Board_Size][Board_Size]; //Zobrist Hash
//測試資料
long long int Hashnode = 0;
long long int Searchnode = 0;
long long int Grades = 0;
//---------------------------------------------------------------------------
int main(void){
char compcolor = 'W', c[10];
int column_input = -1, row_input = -1;
int rx, ry, m=0, n;
FILE *fp;
Init();
printf("Computer take?(B/W/All/File play as first/file play as Second/Load and play): ");
scanf("%c", &compcolor);
Show_Board_and_Set_Legal_Moves();
if (compcolor == 'L' || compcolor == 'l')
compcolor = Load_File();
if ( compcolor == 'B' || compcolor == 'b'){
Computer_Think( &rx, &ry );
printf("Computer played %c%d\n", rx+97, ry+1);
Play_a_Move( rx, ry );
Show_Board_and_Set_Legal_Moves();
}
if ( compcolor == 'A' || compcolor == 'a')
while ( m++ < Board_Size * Board_Size ){
Computer_Think( &rx, &ry );
if ( !Play_a_Move( rx, ry )){
printf("Wrong Computer moves %c%d\n", rx+97, ry+1);
scanf("%d", &n);
break;
}
if ( rx == -1 )
printf("Computer Pass\n");
else
printf("Computer played %c%d\n", rx+97, ry+1);
if ( Check_EndGame() )
return 0;
Show_Board_and_Set_Legal_Moves();
}
if ( compcolor == 'F'){
Computer_Think( &rx, &ry );
Play_a_Move( rx, ry );
}
while ( m++ < Board_Size*Board_Size ){
for(;;){
if ( compcolor == 'F' || compcolor == 'S' ){
fp = fopen( "of.txt", "r" );
fscanf( fp, "%d", &n );
fclose( fp );
c[2]=' ';
if (compcolor == 'F' ){
if ( n % 2 == 0 )
Read_File( c );
else{
Delay(101);
continue;
}
}
else{
if ( n % 2 == 1 )
Read_File( c );
else{
Delay(101);
continue;
}
}
}
if ( compcolor == 'B' || compcolor == 'b'){
printf("input White move:(a-h 1-8), or PASS\n");
scanf("%s", c);
}
else if ( compcolor == 'W' || compcolor == 'w'){
printf("input Black move:(a-h 1-8), or PASS\n");
scanf("%s", c);
}
if ( c[0] == 'P' || c[0] == 'p')
row_input = column_input = -1;
else if ( c[0] == 'M' || c[0] == 'm' ){
Computer_Think( &rx, &ry );
if ( !Play_a_Move( rx, ry )){
printf("Wrong Computer moves %c%dŝ\n", rx+97, ry+1);
scanf("%d", &n);
break;
}
if ( rx == -1 )
printf("Computer Pass");
else
printf("Computer played %c%d\n", rx+97, ry+1);
if ( Check_EndGame() )
break;
Show_Board_and_Set_Legal_Moves();
}
else{
row_input= c[0] - 97;
if (c[2] == '0'){
column_input = 9;
}
else{
column_input = c[1] - 49;
}
}
if ( !Play_a_Move(row_input, column_input) ){
printf("%c%d is a Wrong move!\n", c[0], column_input+1);
}
else
break;
}
if ( Check_EndGame() )
return 0;
Show_Board_and_Set_Legal_Moves();
Computer_Think( &rx, &ry );
printf("Computer played %c%d\n", rx+97, ry+1);
Play_a_Move( rx, ry );
if ( Check_EndGame() )
return 0;;
Show_Board_and_Set_Legal_Moves();
}
printf("Game is over");
scanf("%d", &n);
return 0;
}
void Delay(unsigned int mseconds){
clock_t goal = mseconds + clock();
while (goal > clock());
}
void Read_File( char *c ){
FILE *fp;
char tc[10];
fp = fopen( "of.txt", "r" );
while ( (fscanf( fp, "%s", tc ) ) != EOF ){
c[2] = 'a';
c[0] = tc[0];
if (tc[2] == 48){
c[1] = '1';
c[2] = '0';
}
else{
c[1] = tc[1];
}
}
}
char Load_File( void ){
FILE *fp;
char tc[10];
int row_input, column_input, n;
fp = fopen( "of.txt", "r" );
assert( fp != NULL );
fscanf( fp, "%d", &n );
printf("n = %d\n",n);
while ( (fscanf( fp, "%s", tc ) ) != EOF ){
column_input = tc[0] - 97;
row_input = tc[1] - 49;
if (tc[2] == 48){
column_input = 9;
}
if ( !Play_a_Move(row_input, column_input) )
printf("%c%d is a Wrong move\n", tc[0], column_input+1);
Show_Board_and_Set_Legal_Moves();
tc[2] =' ';
}
return ( n%2 == 1 )? 'B' : 'W';
}
void Init(){
srand( (unsigned)time(NULL) );
Computer_Take = 0;
memset(Now_Board, 0, sizeof(int) * Board_Size * Board_Size);
/* 10X10
Now_Board[4][4] = Now_Board[5][5] = 2;
Now_Board[4][5] = Now_Board[5][4] = 1;
*/
Now_Board[3][3] = Now_Board[4][4] = 2;
Now_Board[3][4] = Now_Board[4][3] = 1;
HandNumber = 0;
memset(sequence, -1, sizeof(int) * Board_Size * Board_Size);
Turn = 0;
LastX = LastY = -1;
Black_Count = White_Count = 0;
Search_Counter = 0;
Winner = 0;
//初始化歷史表
Location tempL;
for( int i = 0,m = 0; i < Board_Size; i++ ){
for( int j = 0; j < Board_Size; j++,m++){
tempL.i = i;
tempL.j = j;
tempL.g = -1;
for(int k = 0; k<Board_Size*Board_Size; k++){
history[0][k][m] = tempL;
history[1][k][m] = tempL;
}
}
}
//初始化置換表
for( int i = 0; i < Board_Size; i++ ){
for( int j = 0; j < Board_Size; j++){
zobrist[0][i][j] = rand64();
zobrist[1][i][j] = rand64();
}
}
}
int Play_a_Move( int x, int y){
FILE *fp;
if ( x == -1 && y == -1){
fp = fopen( "of.txt", "r+" );
fprintf( fp, "%2d\n", HandNumber+1 );
fclose(fp);
fp = fopen("of.txt", "a");
fprintf( fp, "p9\n" );
fclose( fp );
sequence[HandNumber] = -1;
HandNumber ++;
Turn = 1 - Turn;
return 1;
}
if ( !In_Board(x,y))
return 0;
Find_Legal_Moves( Stones[Turn] );
if( Legal_Moves[x][y] == FALSE )
return 0;
if( Put_a_Stone(x,y) ){
Check_Cross(x,y,1);
Compute_Grades( TRUE ,0);
return 1;
}
else
return 0;
return 1;
}
int Put_a_Stone(int x, int y){
FILE *fp;
if( Now_Board[x][y] == 0){
sequence[HandNumber] = Turn;
if (HandNumber == 0)
fp = fopen( "of.txt", "w" );
else
fp = fopen( "of.txt", "r+" );
fprintf( fp, "%2d\n", HandNumber+1 );
HandNumber ++;
fclose(fp);
Now_Board[x][y] = Stones[Turn];
fp = fopen("of.txt", "a");
fprintf( fp, "%c%d\n", x+97, y+1 );;
fclose( fp );
LastX = x;
LastY = y;
Turn = 1 - Turn;
return TRUE;
}
return FALSE;
}
void Show_Board_and_Set_Legal_Moves( void ){
int i,j;
Find_Legal_Moves( Stones[Turn] );
// printf("a b c d e f g h\n");
for(i=0 ; i<Board_Size ; i++){
for(j=0 ; j<Board_Size ; j++){
if( Now_Board[j][i] > 0 ){
if ( Now_Board[j][i] == 2 )
printf("W ");//white
else
printf("B ");//black
}
if (Now_Board[j][i] == 0){
if ( Legal_Moves[j][i] == 1)
printf("? ");
else printf(". ");
}
}
printf(" %d\n", i+1);
}
printf("\n");
printf("a b c d e f g h\n");
}
int Check_Cross(int x, int y, int update){
int k, dx, dy;
if( ! In_Board(x,y) || Now_Board[x][y] == 0)
return FALSE;
int army = 3 - Now_Board[x][y];
int army_count = 0;
for( k=0 ; k<8 ; k++ ){
dx = x + DirX[k];
dy = y + DirY[k];
if( In_Board(dx,dy) && Now_Board[dx][dy] == army ){
army_count += Check_Straight_Army( x, y, k, update ) ;
}
}
if(army_count >0)
return TRUE;
else
return FALSE;
}
int Check_Straight_Army(int x, int y, int d, int update){
int me = Now_Board[x][y];
int army = 3 - me;
int army_count=0;
int found_flag=FALSE;
int flag[ Board_Size ][ Board_Size ] = {{0}};
int i, j;
int tx, ty;
tx = x;
ty = y;
for(i=0 ; i<Board_Size ; i++){
tx += DirX[d];
ty += DirY[d];
if(In_Board(tx,ty) ){
if( Now_Board[tx][ty] == army ){
army_count ++;
flag[tx][ty] = TRUE;
}
else if( Now_Board[tx][ty] == me){
found_flag = TRUE;
break;
}
else
break;
}
else
break;
}
if( (found_flag == TRUE) && (army_count > 0) && update){
for(i=0 ; i<Board_Size ; i++)
for(j=0; j<Board_Size ; j++)
if(flag[i][j]==TRUE){
if(Now_Board[i][j] != 0)
Now_Board[i][j]= 3 - Now_Board[i][j];
}
}
if( (found_flag == TRUE) && (army_count > 0))
return army_count;
else return 0;
}
int In_Board(int x, int y){
if( x >= 0 && x < Board_Size && y >= 0 && y < Board_Size )
return TRUE;
else
return FALSE;
}
int Check_EndGame( void ){
int lc1, lc2;
lc2 = Find_Legal_Moves( Stones[1 - Turn] );
lc1 = Find_Legal_Moves( Stones[Turn] );
if ( lc1==0 && lc2==0 ){
if(Black_Count > White_Count){
printf("Black Win!\n");
if(Winner == 0)
Winner = 1;
}
else if(Black_Count < White_Count){
printf("White Win!\n");
if(Winner == 0)
Winner = 2;
}
else{
printf("Draw\n");
Winner = 0;
}
Show_Board_and_Set_Legal_Moves();
printf("Game is over\n");
printf("Hashnode = %12.lld \n",Hashnode);
printf("Searchnode = %12.lld \n",Searchnode);
printf("Grades = %12.lld \n",Grades);
scanf("%d", &lc1);
return TRUE;
}
return FALSE;
}
int comparH(const void* a,const void* b){
Location* aa = (Location*)a;
Location* bb = (Location*)b;
return bb->g - aa->g;
}
void Computer_Think( int *x, int *y ){
if (fRandomMove && HandNumber < RandomMove ) { //初始隨機下子
int lm = Find_Legal_Moves( Stones[Turn]);
int RMV = ( rand() % lm ) +1 ;
*x = Legal_Move_Index[RMV][1];
*y = Legal_Move_Index[RMV][2];
return;
}
else{
time_t clockBegin, clockEnd;
static int think_time=0;
int flag = 0;
//歷史表衰減
if(historyAttenua != 0){
for(int i=0; i<Board_Size*Board_Size; i++){
for(int j=0; j<Board_Size*Board_Size; j++){
history[0][i][j].g *= historyAttenua;
history[1][i][j].g *= historyAttenua;
}
}
}
//動態深度
if(DynamicdeepS <= HandNumber && HandNumber <= DynamicdeepE){
deepEnd = Dynamicdeep+2;
}
//終局搜索
else if(HandNumber >= endTime){
deepEnd = (Board_Size*Board_Size) - HandNumber;
}
else{
deepEnd = Dynamicdeep;
}
clockBegin = clock();
resultX = resultY = -1;
Search_Counter = 0;
flag = Search( Turn, 0);
clockEnd = clock();
think_time += (clockEnd - clockBegin)/1000;
printf("used thinking time= %d min. %d.%d sec.\n", think_time/60000, (think_time%60000)/1000, (think_time%60000)%1000);
if( flag ){
*x = resultX;
*y = resultY;
}
else{
*x = *y = -1;
return;
}
}
}
int Search(int myturn, int mylevel){
if(Find_Legal_Moves(Stones[myturn]) <= 0)
return FALSE;
int B[ Board_Size ][ Board_Size ];
int L[ Board_Size ][ Board_Size ];
memcpy( B, Now_Board, sizeof(int) * Board_Size * Board_Size );
memcpy( L, Legal_Moves, sizeof(int) * Board_Size * Board_Size );
Location min, max;
min.i = min.j = -1; min.g = INT_MAX;
max.i = max.j = -1; max.g = INT_MIN;
int i, j, k, test, g;
int alpha = INT_MIN, beta = INT_MAX;
for( k = 0; k < Board_Size*Board_Size; k++ ){
i = history[myturn][mylevel][k].i;
j = history[myturn][mylevel][k].j;
if(L[i][j] == TRUE){
memcpy(Now_Board, B, sizeof(int) * Board_Size * Board_Size );
Now_Board[i][j] = Stones[myturn];
Check_Cross(i,j,TRUE);
//遞代加深
for(search_deep = deepStart, g=0; search_deep <= deepEnd; search_deep+=2){
if(fiterative == FALSE)
search_deep = deepEnd;
//MTD
if(fMTD){
beta = INT_MAX;
alpha = INT_MIN;
test = g;
do{
g = search_next(i,j, 1-myturn, mylevel+1, test-1, test);
if (g < test)
test = beta = g;
else{
alpha = g;
test = g + 1;
}
}while( alpha < beta );
}
else
g = search_next(i,j, 1-myturn, mylevel+1, alpha, beta);
}
if( myturn == 0 ){ // max level
if( g > max.g ){
max.g = g;
max.i = i;
max.j = j;
}
}
else{
if( g < min.g ){ // min level
min.g = g;
min.i = i;
min.j = j;
}
}
// cutoff
if( alpha_beta_option )
if( alpha >= beta){
i = Board_Size;
j = Board_Size;
}
}
}
memcpy( Now_Board, B, sizeof(int) * Board_Size * Board_Size );
if( myturn == 0 ){
resultX = max.i;
resultY = max.j;
return TRUE;
}
else{
resultX = min.i;
resultY = min.j;
return TRUE;
}
return FALSE;
}
int search_next( int x, int y, int myturn, int mylevel, int alpha, int beta ){
long long int hash64;
long long int hash32;
if( mylevel >= search_deep ){
hash64 = getHash();
hash32 = hash64 & (Hashsize-1);
hashtable[myturn][hash32].checksum = hash64;
hashtable[myturn][hash32].depth = 0;
hashtable[myturn][hash32].entry_type = 0;
hashtable[myturn][hash32].g = Compute_Grades( FALSE ,0);
return hashtable[myturn][hash32].g;
}
if(Find_Legal_Moves( Stones[myturn] ) <= 0){
return Compute_Grades( FALSE ,1);
}
Search_Counter++;
int i,j,k,g=0;
int B[ Board_Size ][ Board_Size ];
int L[ Board_Size ][ Board_Size ];
memcpy( B, Now_Board, sizeof(int) * Board_Size * Board_Size );
memcpy( L, Legal_Moves, sizeof(int) * Board_Size * Board_Size );
int fentry_type = 2;
for( k = 0; k < Board_Size*Board_Size; k++ ){
i = history[myturn][mylevel][k].i;
j = history[myturn][mylevel][k].j;
if(L[i][j] == TRUE){
memcpy(Now_Board, B, sizeof(int) * Board_Size * Board_Size );
Now_Board[i][j] = Stones[myturn];
Check_Cross(i,j, TRUE) ;
hash64 = getHash();
hash32 = hash64 & (Hashsize-1);
int flag = false;
if(zhash && hashtable[1-myturn][hash32].checksum == hash64 &&
hashtable[1-myturn][hash32].depth >= search_deep-(mylevel+1)){
if(hashtable[1-myturn][hash32].entry_type == 0){
Hashnode++;
g = hashtable[1-myturn][hash32].g;
flag = true;
}
else if(hashtable[1-myturn][hash32].entry_type == 1){
if((1-myturn) == 0 && hashtable[1-myturn][hash32].g >= beta){
Hashnode++;
g = hashtable[1-myturn][hash32].g;
flag = true;
}
else if((1-myturn) == 1 && hashtable[1-myturn][hash32].g <= alpha){
Hashnode++;
g = hashtable[1-myturn][hash32].g;
flag = true;
}
}
else if(hashtable[1-myturn][hash32].entry_type == 2){
if ((1-myturn) == 0 && hashtable[1-myturn][hash32].g <= alpha){
Hashnode++;
g = hashtable[1-myturn][hash32].g;
flag = true;
}
else if((1-myturn) == 1 && hashtable[1-myturn][hash32].g >= beta){
Hashnode++;
g = hashtable[1-myturn][hash32].g;
flag = true;
}
}
}
if(flag == false){
Searchnode++;
g = search_next(i,j, 1-myturn, mylevel+1, alpha, beta);
}
if(myturn==0){ // max ply
if(g > alpha){
alpha = g;
history[myturn][mylevel][k].g += 2*mylevel*mylevel; //普通的節點
fentry_type = 0;
}
history[myturn][mylevel][k].g -= 2*mylevel*mylevel; //較差的節點
}
else{ // min ply
if(g < beta){
beta = g;
history[myturn][mylevel][k].g += 2*mylevel*mylevel; //普通的節點
fentry_type = 0;
}
history[myturn][mylevel][k].g -= 2*mylevel*mylevel; //較差的節點
}
// cutoff
if( alpha_beta_option )
if( alpha >= beta ){
i = Board_Size;
j = Board_Size;
history[myturn][mylevel][k].g += 16*mylevel*mylevel; //優先的節點
fentry_type = 1;
break;
}
}
}
memcpy(Now_Board, B, sizeof(int) * Board_Size * Board_Size);
//排序節點優先度
qsort(history[myturn][mylevel], Board_Size * Board_Size, sizeof(history[myturn][mylevel][0]), comparH);
hash64 = getHash();
hash32 = hash64 & (Hashsize-1);
if(myturn == 0){ //max level
if(hashtable[myturn][hash32].depth <= search_deep-mylevel){
hashtable[myturn][hash32].checksum = hash64;
hashtable[myturn][hash32].depth = search_deep-mylevel;
hashtable[myturn][hash32].entry_type = fentry_type;
hashtable[myturn][hash32].g = alpha;
}
return alpha;
}
else{ //min level
if(hashtable[myturn][hash32].depth <= search_deep-mylevel){
hashtable[myturn][hash32].checksum = hash64;
hashtable[myturn][hash32].depth = search_deep-mylevel;
hashtable[myturn][hash32].entry_type = fentry_type;
hashtable[myturn][hash32].g = beta;
}
return beta;
}
}
long long int rand64(void) {
return rand() ^ ((long long int)rand() << 15) ^ ((long long int)rand() << 30) ^ ((long long int)rand() << 45) ^ ((long long int)rand() << 60);
}
long long int getHash(void){
long long int hash=0;
for(int i=0; i < Board_Size; i++){
for(int j=0; j < Board_Size; j++){
if(Now_Board[i][j] == 1){
hash ^= zobrist[0][i][j];
}
else if(Now_Board[i][j] == 2){
hash ^= zobrist[1][i][j];
}
}
}
return hash;
}
int Find_Legal_Moves( int color ){
int i,j;
int me = color;
int legal_count = 0;
Legal_Move_Index[0][0] = 0;
B = W = 0;
for( i = 0; i < Board_Size; i++ )
for( j = 0; j < Board_Size; j++ )
Legal_Moves[i][j] = 0;
for( i = 0; i < Board_Size; i++ )
for( j = 0; j < Board_Size; j++ ){
if( Now_Board[i][j] == 0 ){
//剪枝加速
if( i>0 && i<Board_Size-1 && j>0 && j<Board_Size-1 ){
if((Now_Board[i-1][j-1] == 0 || Now_Board[i-1][j-1] == me) &&
(Now_Board[i-1][j] == 0 || Now_Board[i-1][j] == me) &&
(Now_Board[i-1][j+1] == 0 || Now_Board[i-1][j+1] == me) &&
(Now_Board[i][j-1] == 0 || Now_Board[i][j-1] == me) &&
(Now_Board[i][j+1] == 0 || Now_Board[i][j+1] == me) &&
(Now_Board[i+1][j-1] == 0 || Now_Board[i+1][j-1] == me) &&
(Now_Board[i+1][j] == 0 || Now_Board[i+1][j] == me) &&
(Now_Board[i+1][j+1] == 0 || Now_Board[i+1][j+1] == me)){
continue;
}
}
Now_Board[i][j] = me;
if( Check_Cross(i,j,FALSE) == TRUE ){
Legal_Moves[i][j] = TRUE;
legal_count++;
Legal_Move_Index[0][0] = legal_count;
Legal_Move_Index[legal_count][1] = i ;
Legal_Move_Index[legal_count][2] = j ;
}
Now_Board[i][j] = 0;
}
else if( Now_Board[i][j] == 1 ){
B++;
}
else if( Now_Board[i][j] == 2 ){
W++;
}
}
return legal_count;
}
int Compute_Grades(int flag, int isL){
if(flag){
Find_Legal_Moves( 1 );
Black_Count = B;
White_Count = W;
printf("Grade: Black %d, White %d\n", B, W);
return 0;
}
Grades++;
//中局
if( HandNumber < endTime ){
int SB, SW, BM;
SB = StableDiscs(1);
SW = StableDiscs(2);
if( isL == 0 ){
BM = Find_Legal_Moves( 1 );
}
else{
BM = Legal_Move_Index[0][0];
}
return ( fS*(SB - SW) + BM);
}
//尾局
else{
if( isL == 0 ){
B = 0;
for(int i=0; i<Board_Size; i++)
for(int j=0; j<Board_Size; j++){
if( Now_Board[i][j] == 1 ){
B++;
}
}
}
return ( B );
}
}
int StableDiscs(int me){
int i, j, k, num = 0;
int a=0,b=0,c=0,d=0;
//左上角
i = 0;
j = 0;
if(Now_Board[i][j] == me){
num++;
for(k=1; k<Board_Size; k++){
if(Now_Board[i+k][j] != me)
break;
num++;
}
if(k == Board_Size)
a++;
for(k=1; k<Board_Size; k++){
if(Now_Board[i][j+k] != me)
break;
num++;
}
if(k == Board_Size)
d++;
}
//右上角
i = Board_Size-1;
j = 0;
if(Now_Board[i][j] == me){
num++;
for(k=1; k<Board_Size; k++){
if(Now_Board[i-k][j] != me)
break;
num++;
}
if(k == Board_Size)
a++;
for(k=1; k<Board_Size; k++){
if(Now_Board[i][j+k] != me)
break;
num++;
}
if(k == Board_Size)
b++;
}
//左下角
i = 0;
j = Board_Size-1;
if(Now_Board[i][j] == me){
num++;
for(k=1; k<Board_Size; k++){
if(Now_Board[i+k][j] != me)
break;
num++;
}
if(k == Board_Size)
c++;
for(k=1; k<Board_Size; k++){
if(Now_Board[i][j-k] != me)
break;
num++;
}
if(k == Board_Size)
d++;
}
//右下角
i = Board_Size-1;
j = Board_Size-1;
if(Now_Board[i][j] == me){
num++;
for(k=1; k<Board_Size; k++){
if(Now_Board[i-k][j] != me)
break;
num++;
}
if(k == Board_Size)
c++;
for(k=1; k<Board_Size; k++){
if(Now_Board[i][j-k] != me)
break;
num++;
}
if(k == Board_Size)
b++;
}
if(a > 1)
num -= Board_Size;
if(b > 1)
num -= Board_Size;
if(c > 1)
num -= Board_Size;
if(d > 1)
num -= Board_Size;
return num;
}
/*
Base class for environments of RL.
Following features:
Discrete and fix-size action space.
Used as:
Experiment environment;
Environment in Agents' mind
*/
#include <cstdlib>
#include <string>
class Othello: public BaseEnv {
public:
Othello();
~Othello();
virtual int Move(int action) = 0;
virtual bool IsFinish() = 0;
virtual void GetResult(float& res) = 0;
virtual void GetFeature(BaseFeature& feature) = 0;
virtual void GetActionNum() = 0;
virtual void GetInputDim(vector<int>& input_dim) = 0;
virtual void GetLegalAction(vector<int>& action) = 0;
virtual bool IsLegal(int action) = 0;
virtual std::string action2str(int action) = 0;
//virtual void TransformFeatures(BaseFeature& feature, int transform_mode) = 0;
//virtual void TransformPolicy(int transform_mode) = 0; // this is reverse mode of TransformFeature
protected:
virtual void Init() = 0;
};
\ No newline at end of file
#include "othello_comm.h"
#include <cstring>
#include <mutex>
// #include <glog/logging.h>
#define x first
#define y second
using namespace std;
using namespace OthelloComm;
OthelloHashValuePair g_hash_weight[BORDER_SIZE][BORDER_SIZE];
OthelloCoordId g_log2_table[67];
uint64_t g_zobrist_board_hash_weight[4][OTHELLOBOARD_SIZE];
uint64_t g_zobrist_player_hash_weight[4];
namespace OthelloFunction {
bool InBoard(const OthelloCoordId id) {
return 0 <= id && id < OTHELLOBOARD_SIZE;
}
bool InBoard(const OthelloCoordId x, const OthelloCoordId y) {
return 0 <= x && x < BORDER_SIZE
&& 0 <= y && y < BORDER_SIZE;
}
bool IsPass(const OthelloCoordId id) {
return COORD_PASS == id;
}
bool IsPass(const OthelloCoordId x, const OthelloCoordId y) {
return COORD_PASS == CoordToId(x, y);
}
bool IsUnset(const OthelloCoordId id) {
return COORD_UNSET == id;
}
bool IsUnset(const OthelloCoordId x, const OthelloCoordId y) {
return COORD_UNSET == CoordToId(x, y);
}
bool IsResign(const OthelloCoordId id) {
return COORD_RESIGN == id;
}
bool IsResign(const OthelloCoordId x, const OthelloCoordId y) {
return COORD_RESIGN == CoordToId(x, y);
}
void IdToCoord(const OthelloCoordId id, OthelloCoordId &x, OthelloCoordId &y) {
if (COORD_PASS == id) {
x = y = COORD_PASS;
} else if (COORD_RESIGN == id) {
x = y = COORD_RESIGN;
} else if (!InBoard(id)) {
x = y = COORD_UNSET;
} else {
x = id / BORDER_SIZE;
y = id % BORDER_SIZE;
}
}
OthelloCoordId CoordToId(const OthelloCoordId x, const OthelloCoordId y) {
if (COORD_PASS == x && COORD_PASS == y) {
return COORD_PASS;
}
if (COORD_RESIGN == x && COORD_RESIGN == y) {
return COORD_RESIGN;
}
if (!InBoard(x, y)) {
return COORD_UNSET;
}
return x * BORDER_SIZE + y;
}
void StrToCoord(const string &str, OthelloCoordId &x, OthelloCoordId &y) {
// CHECK_EQ(str.length(), 2) << "string[" << str << "] length not equal to 2";
x = str[0] - 'a';
y = str[1] - 'a';
if (str == "zz") {
x = y = COORD_PASS;
} else if (!InBoard(x, y)) {
x = y = COORD_UNSET;
}
}
string CoordToStr(const OthelloCoordId x, const OthelloCoordId y) {
char buffer[3];
if (!InBoard(x, y)) {
buffer[0] = buffer[1] = 'z';
} else {
buffer[0] = x + 'a';
buffer[1] = y + 'a';
}
return string(buffer, 2);
}
std::string IdToStr(const OthelloCoordId id) {
OthelloCoordId x, y;
IdToCoord(id, x, y);
return CoordToStr(x, y);
}
OthelloCoordId StrToId(const std::string &str) {
OthelloCoordId x, y;
StrToCoord(str, x, y);
return CoordToId(x, y);
}
once_flag CreateGlobalVariables_once;
void CreateGlobalVariables() {
call_once(
CreateGlobalVariables_once,
[]() {
CreateHashWeights();
CreateQuickLog2Table();
CreateZobristHash();
}
);
}
void CreateHashWeights() {
g_hash_weight[0][0] = OthelloHashValuePair(1, 1);
for (OthelloCoordId i = 1; i < OTHELLOBOARD_SIZE; ++i) {
g_hash_weight[i / BORDER_SIZE][i % BORDER_SIZE] =
OthelloHashValuePair(g_hash_weight[(i - 1) / BORDER_SIZE][(i - 1) % BORDER_SIZE].x * g_hash_unit.x,
g_hash_weight[(i - 1) / BORDER_SIZE][(i - 1) % BORDER_SIZE].y * g_hash_unit.y);
}
}
void CreateQuickLog2Table() {
memset(g_log2_table, -1, sizeof(g_log2_table));
int tmp = 1;
for (OthelloCoordId i = 0; i < 64; ++i) {
g_log2_table[tmp] = i;
tmp *= 2;
tmp %= 67;
}
}
#if defined(_WIN32) || defined(_WIN64)
static int rand_r(unsigned int *seed)
{
unsigned int next = *seed;
int result;
next *= 1103515245;
next += 12345;
result = (unsigned int)(next / 65536) % 2048;
next *= 1103515245;
next += 12345;
result <<= 10;
result ^= (unsigned int)(next / 65536) % 1024;
next *= 1103515245;
next += 12345;
result <<= 10;
result ^= (unsigned int)(next / 65536) % 1024;
*seed = next;
return result;
}
#endif
void CreateZobristHash() {
uint32_t seed = 0xdeadbeaf;
for (int i = 0; i < 4; ++i) {
g_zobrist_player_hash_weight[i] = (uint64_t) rand_r(&seed) << 32 | rand_r(&seed);
for (int j = 0; j < OTHELLOBOARD_SIZE; ++j) {
g_zobrist_board_hash_weight[i][j] = (uint64_t) rand_r(&seed) << 32 | rand_r(&seed);
}
}
}
} // namespace OthelloFunction
#undef y
#undef x
#pragma once
#include <inttypes.h>
#include <string>
#include <vector>
// Return code of functions should be "int"
typedef uint8_t OthelloStoneColor; // Stone color
typedef int16_t OthelloCoordId; // Stone IDs or coordinates
typedef int16_t OthelloSize; // Counts of visit times, used blocks, ..
namespace OthelloComm {
const OthelloCoordId BORDER_SIZE = 8; // sxk_modify
const OthelloCoordId OTHELLOBOARD_SIZE = BORDER_SIZE * BORDER_SIZE;
const OthelloCoordId COORD_UNSET = -2;
const OthelloCoordId COORD_PASS = -1;
const OthelloCoordId COORD_RESIGN = -3;
const OthelloStoneColor EMPTY = 0;
const OthelloStoneColor BLACK = 1;
const OthelloStoneColor WHITE = 2;
const OthelloStoneColor WALL = 3;
const OthelloStoneColor COLOR_UNKNOWN = -1;
//const char *const COLOR_STRING[] = { "Empty", "Black", "White"};
const char *const COLOR_STRING[] = { "Empty", "Black", "White", "Wall" };
const OthelloCoordId DirX[8] = {0, 1, 1, 1, 0, -1, -1, -1};
const OthelloCoordId DirY[8] = {-1, -1, 0, 1, 1, 1, 0, -1};
} // namespace OthelloComm
namespace OthelloFeature {
const int SIZE_HISTORYEACHSIDE = 16;
const int SIZE_PLAYERCOLOR = 1;
const int STARTPOS_HISTORYEACHSIDE = 0;
const int STARTPOS_PLAYERCOLOR = STARTPOS_HISTORYEACHSIDE + SIZE_HISTORYEACHSIDE;
const int FEATURE_COUNT = STARTPOS_PLAYERCOLOR + SIZE_PLAYERCOLOR;
} // namespace OthelloFeature
namespace OthelloFunction {
extern bool InBoard(const OthelloCoordId id);
extern bool InBoard(const OthelloCoordId x, const OthelloCoordId y);
extern bool IsPass(const OthelloCoordId id);
extern bool IsPass(const OthelloCoordId x, const OthelloCoordId y);
extern bool IsUnset(const OthelloCoordId id);
extern bool IsUnset(const OthelloCoordId x, const OthelloCoordId y);
extern bool IsResign(const OthelloCoordId id);
extern bool IsResign(const OthelloCoordId x, const OthelloCoordId y);
extern void IdToCoord(const OthelloCoordId id, OthelloCoordId &x, OthelloCoordId &y);
extern OthelloCoordId CoordToId(const OthelloCoordId x, const OthelloCoordId y);
extern void StrToCoord(const std::string &str, OthelloCoordId &x, OthelloCoordId &y);
extern std::string CoordToStr(const OthelloCoordId x, const OthelloCoordId y);
extern std::string IdToStr(const OthelloCoordId id);
extern OthelloCoordId StrToId(const std::string &str);
extern void CreateGlobalVariables();
extern void CreateHashWeights();
extern void CreateQuickLog2Table();
extern void CreateZobristHash();
} // namespace OthelloFunction
//typedef std::pair<OthelloCoordId, OthelloCoordId> OthelloPosition;
typedef std::pair<uint64_t, uint64_t> OthelloHashValuePair;
extern OthelloHashValuePair g_hash_weight[OthelloComm::BORDER_SIZE][OthelloComm::BORDER_SIZE];
const OthelloHashValuePair g_hash_unit(3, 7);
extern uint64_t g_zobrist_board_hash_weight[4][OthelloComm::OTHELLOBOARD_SIZE];
extern uint64_t g_zobrist_player_hash_weight[4];
//state:统计棋局状态,0未分胜负,1黑胜,2白胜,3平局
//extern int state;
//extern int B, W;
extern OthelloCoordId g_log2_table[67];
#define FOR_EACHCOORD(id) for (OthelloCoordId id = 0; id < OthelloComm::OTHELLOBOARD_SIZE; ++id)
#include "othello_env.h"
#include <algorithm>
#include <cmath>
using namespace std;
using namespace OthelloComm;
using namespace OthelloFunction;
using namespace OthelloFeature;
OthelloEnv::OthelloEnv() {
CreateGlobalVariables();
FOR_EACHCOORD(i) {
stones_[i].self_id = i;
}
feature_history_list_.clear();
memset(board_state_, 0, sizeof(board_state_));
memset(legal_move_map_, 1, sizeof(legal_move_map_));
memset(move_count_, 0, sizeof(move_count_));
current_player_ = BLACK;
last_position_ = COORD_UNSET;
is_resign_ = false;
state_ = 0;
turn_ = 0;
B_ = 0;
W_ = 0;
board_hash_states_.clear();
zobrist_hash_value_ = 0;
}
//OthelloEnv::OthelloEnv(const OthelloEnv &ge) : OthelloEnv() {
// CopyFrom(ge);
// }
OthelloEnv::~OthelloEnv() {
}
// void OthelloEnv::CopyFrom(const OthelloEnv &src) {
// *this = src;
// }
void OthelloEnv::GetSensibleMove() {
// Add new feature plane
string plane;
// black
{
plane = "";
FOR_EACHCOORD(id) {
if (board_state_[id] == BLACK) {
plane += "1";
} else {
plane += "0";
}
}
feature_history_list_.push_back(plane);
}
// white
{
plane = "";
FOR_EACHCOORD(id) {
if (board_state_[id] == WHITE) {
plane += "1";
} else {
plane += "0";
}
}
feature_history_list_.push_back(plane);
}
memset(legal_move_map_, 0, sizeof(legal_move_map_));
Find_Legal_Moves(current_player_);
}
int OthelloState::Move(int action) {
Find_Legal_Moves(current_player_);
if (!IsLegal(action)) {
return -1;
}
if(IsResign(action)){
is_resign_ = true;
return 0;
}
last_position_ = to;
{
zobrist_hash_value_ ^= g_zobrist_player_hash_weight[Self()];
zobrist_hash_value_ ^= g_zobrist_player_hash_weight[Opponent()];
if (!IsPass(action)) {
zobrist_hash_value_ ^= g_zobrist_board_hash_weight[Self()][action];
}
}
if (IsPass(action)) {
HandOff();
GetSensibleMove();
return 0;
}
OthelloCoordId x, y;
++move_count_[action];
board_state_[action] = Self();
IdToCoord(to, x, y);
Check_Cross(x, y, 1);
HandOff();
GetSensibleMove();
return 0;
}
int OthelloEnv::Check_Straight_Army(OthelloCoordId x, OthelloCoordId y, int d, int update) const{
int me = board_state_[OthelloFunction::CoordToId(x, y)];
int army = 3 - me;
//int army = Opponent(me);
int army_count = 0;
bool found_flag = false;
int flag[OthelloComm::BORDER_SIZE][OthelloComm::BORDER_SIZE] = {{0}};
OthelloCoordId i, j;
OthelloCoordId tx, ty;
tx = x;
ty = y;
for(i = 0; i < OthelloComm::BORDER_SIZE; i++){
tx+=OthelloComm::DirX[d];
ty+=OthelloComm::DirY[d];
if(OthelloFunction::In_Board(tx, ty)){
if(board_state_[OthelloFunction::CoordToId(tx, ty)] == army ){
army_count ++;
flag[tx][ty] = 1;
}else if(board_state_[OthelloFunction::CoordToId(tx, ty)] == me){
found_flag = true;
break;
}else{
break;
}
}else{
break;
}
}
if(found_flag && (army_count > 0) && update){
for(i = 0; i < OthelloComm::BORDER_SIZE; i++)
for(j = 0; j < OthelloComm::BORDER_SIZE; j++)
if(flag[i][j] == 1){
if(board_state_[OthelloFunction::CoordToId(i, j)] != OthelloComm::EMPTY){
board_state_[OthelloFunction::CoordToId(i, j)] = 3 - board[OthelloFunction::CoordToId(i,j)];
//board_state_[OthelloFunction::CoordToId(i, j)] = Opponent(board_state_[OthelloFunction::CoordToId(i, j)]);
}
}
}
if(found_flag && (army_count > 0)){
return army_count;
}else{
return 0;
}
}
bool OthelloEnv::Check_Cross(OthelloCoordId x, OthelloCoordId y, int update) const{
int k;
OthelloCoordId dx, dy;
if(!OthelloFunction::In_Board(x, y) || board_state_[OthelloFunction::CoordToId(x, y)] == OthelloComm::EMPTY){
return false;
}
int army = 3 - board_state_[OthelloFunction::CoordToId(x, y)];
int army_count = 0;
for(k = 0 ; k < 8 ; k++ ){
dx = x + OthelloComm::DirX[k];
dy = y + OthelloComm::DirY[k];
if(OthelloFunction::In_Board(dx, dy) && board_state_[OthelloFunction::CoordToId(dx, dy)] == army ){
army_count += Check_Straight_Army(x, y, k, update) ;
}
}
if(army_count > 0){
return true;
}else{
return false;
}
}
int OthelloEnv::Find_Legal_Moves(int color) const{
OthelloCoordId i,j;
int me = color;
int legal_count = 0;
int Legal_Move_Index[50][3];
int Legal_Moves[OthelloComm::BORDER_SIZE][OthelloComm::BORDER_SIZE];
Legal_Move_Index[0][0] = 0;
B_ = W_ = 0;
for(i = 0; i < OthelloComm::BORDER_SIZE; i++ ){
for(j = 0; j < OthelloComm::BORDER_SIZE; j++){
Legal_Moves[i][j] = 0;
legal_move_map_[OthelloFunction::CoordToId(i, j)] = false;
}
}
for(i = 0; i < OthelloComm::BORDER_SIZE; i++ ){
for(j = 0; j < OthelloComm::BORDER_SIZE; j++ ){
if(board_state_[OthelloFunction::CoordToId(i, j)] == EMPTY){
if(i > 0 && i < OthelloComm::BORDER_SIZE - 1 && j > 0 && j < OthelloComm::BORDER_SIZE - 1){
if((board_state_[OthelloFunction::CoordToId(i - 1, j - 1)] == OthelloComm::EMPTY || board_state_[OthelloFunction::CoordToId(i - 1, j - 1)] == me) &&
(board_state_[OthelloFunction::CoordToId(i - 1, j)] == OthelloComm::EMPTY || board_state_[OthelloFunction::CoordToId(i - 1, j)] == me) &&
(board_state_[OthelloFunction::CoordToId(i - 1, j + 1)] == OthelloComm::EMPTY || board_state_[OthelloFunction::CoordToId(i - 1, j + 1)] == me) &&
(board_state_[OthelloFunction::CoordToId(i, j - 1)] == OthelloComm::EMPTY || board_state_[OthelloFunction::CoordToId(i, j - 1)] == me) &&
(board_state_[OthelloFunction::CoordToId(i, j + 1)] == OthelloComm::EMPTY || board_state_[OthelloFunction::CoordToId(i, j + 1)] == me) &&
(board_state_[OthelloFunction::CoordToId(i + 1, j - 1)] == OthelloComm::EMPTY || board_state_[OthelloFunction::CoordToId(i + 1, j - 1)] == me) &&
(board_state_[OthelloFunction::CoordToId(i + 1, j)] == OthelloComm::EMPTY || board_state_[OthelloFunction::CoordToId(i + 1, j)] == me) &&
(board_state_[OthelloFunction::CoordToId(i + 1, j + 1)] == OthelloComm::EMPTY || board_state_[OthelloFunction::CoordToId(i + 1, j + 1)] == me)){
continue;
}
}
board_state_[OthelloFunction::CoordToId(i, j)] = me;
if(Check_Cross(i, j, 0)){
Legal_Moves[i][j] = 1;
legal_move_map_[OthelloComm::CoordToId(i, j)] = true;
legal_count++;
Legal_Move_Index[0][0] = legal_count;
Legal_Move_Index[legal_count][1] = i ;
Legal_Move_Index[legal_count][2] = j ;
}
board_state_[OthelloFunction::CoordToId(i, j)] = 0;
}else if(board_state_[OthelloFunction::CoordToId(i, j)] == OthelloComm::BLACK){
B_++;
}else if(board_state_[OthelloFunction::CoordToId(i, j)] == OthelloComm::WHITE){
W_++;
}
}
}
return legal_count;
}
int OthelloEnv::CalcResult() const{
int lg_b, lg_w;
if(is_resign_){
if(current_player_ == OthelloComm::BLACK){
state_ = 2;
}else if(current_player_ == OthelloComm::WHITE){
state_ = 1;
}
}
if(state_ != 0){
return state_;
}
lg_b = Find_Legal_Moves(OthelloComm::BLACK);
lg_w = Find_Legal_Moves(OthelloComm::WHITE);
if(B_ == 0){
state_ = 2;
return state_;
}
if(W_ == 0){
state_ = 1;
return state_;
}
if ( lg_b == 0 && lg_w == 0 ){
if(B_ > W_){
state_ = 1;
return state_;
}else if(B_ < W_){
state_ = 2;
return state_;
}else{
state_ = 3;
return state_;
}
}
return state_;
}
OthelloStoneColor OthelloEnv::GetWinner() const {
int result = CalcResult();
if (result == 3){
return OthelloComm::EMPTY;
}else if (result == 1){
return OthelloComm::BLACK;
}else if(result == 2){
return OthelloComm::WHITE;
}
}
void OthelloEnv::GetResult(float& res) {
if (GetWinner() == OthelloComm::EMPTY){
res = 0.0f;
}else{
res = GetWinner() == CurrentPlayer() ? -1.0f : 1.0f;
}
}
vector<bool> OthelloEnv::GetFeature(BaseFeature& feature) const { // HWC
feature.clear();
feature.resize(OTHELLOBOARD_SIZE * (SIZE_HISTORYEACHSIDE + 1));
// because push black into history first,
// if next player is black,
// we should get planes swap of each two planes
int reverse_plane = int(Self() == BLACK);
for (OthelloSize i = 0; i < SIZE_HISTORYEACHSIDE && i < feature_history_list_.size(); ++i) {
const string &feature_str = *(feature_history_list_.rbegin() + (i ^ reverse_plane));
for (int j = 0, k = i; j < OTHELLOBOARD_SIZE; ++j, k += (SIZE_HISTORYEACHSIDE + 1)) {
feature[k] = feature_str[j] - '0';
}
}
if (Self() == BLACK) {
for (int j = 0, k = SIZE_HISTORYEACHSIDE; j < OTHELLOBOARD_SIZE; ++j, k += (SIZE_HISTORYEACHSIDE + 1)) {
feature[k] = 1;
}
}
return feature;
}
int OthelloEnv::GetActionNum() {//include PASS and RESIGN
return OthelloComm::OTHELLOBOARD_SIZE + 2;
}
void OthelloEnv::GetInputDim(vector<int>& input_dim) {
input_dim.clear();
input_dim.push_back(SIZE_HISTORYEACHSIDE);
input_dim.push_back(BORDER_SIZE);
input_dim.push_back(BORDER_SIZE)
}
void OthelloEnv::GetLegalAction(vector<int>& action) {
action.clear();
FOR_EACHCOORD(id) {
if (legal_move_map_[id]) {
action.push_back(id);
}
}
}
/*void OthelloEnv::TransformCoord(OthelloCoordId &x, OthelloCoordId &y, int mode, bool reverse = false)
{
if (reverse) {
if (mode & 4) std::swap(x, y);
if (mode & 2) y = OthelloComm::BORDER_SIZE - y - 1;
if (mode & 1) x = OthelloComm::BORDER_SIZE - x - 1;
} else {
if (mode & 1) x = OthelloComm::BORDER_SIZE - x - 1;
if (mode & 2) y = OthelloComm::BORDER_SIZE - y - 1;
if (mode & 4) std::swap(x, y);
}
}*/
// void OthelloEnv::TransformFeatures(BaseFeature& feature, int transform_mode) {
// BaseFeature ret(feature.size());
// int depth = features.size() / OthelloComm::OTHELLOBOARD_SIZE;
// for (int i = 0; i < OthelloComm::OTHELLOBOARD_SIZE; ++i) {
// OthelloCoordId x, y;
// OthelloFunction::IdToCoord(i, x, y);
// TransformCoord(x, y, mode);
// int j = OthelloFunction::CoordToId(x, y);
// for (int k = 0; k < depth; ++k) {
// ret[i * depth + k] = features[j * depth + k];
// }
// }
// feature = std::move(ret);
// }
// void TransformPolicy(int transform_mode) {
// }
#include "othello_comm.h"
#include "base_env.h"
#include <cstdlib>
#include <cstring>
#include <stack>
#include <string>
#include <unordered_set>
#include <vector>
#if defined(_WIN32) || defined(_WIN64)
# include <intrin.h>
# define __builtin_popcount __popcnt
# define __builtin_popcountll __popcnt64
#endif
struct OthelloStone {
OthelloCoordId self_id; // Id of this stone
OthelloCoordId next_id; // Use like link-list
OthelloCoordId parent_id; // Use like union-find-set (rooted by tail)
// inline void SetSelfId(OthelloCoordId id) { self_id = id; }
inline void Reset(OthelloCoordId id = OthelloComm::COORD_UNSET) {
next_id = parent_id = self_id;
}
} ;
class OthelloEnv: public BaseEnv {
public:
OthelloEnv();
// OthelloEnv(const OthelloEnv &ge);
~OthelloEnv();
int Move(int action) override;
bool IsFinish() override { return ((state_ != 0 ? true : false) || is_resign_); }
void GetResult(float& res) override;
void GetFeature(BaseFeature& feature) override;
int GetActionNum() override;
void GetInputDim(vector<int>& input_dim) override;
void GetLegalAction(vector<int>& action) override;
bool IsLegal(int action) override { return OthelloFunction::IsResign(action) || OthelloFunction::IsPass(action) || legal_move_map_[action]; }
std::string action2str(int action) override { return OthelloFunction::IdToStr(const OthelloCoordId action); }
int CurrentPlayer() override { return current_player_; }
// void TransformFeatures(BaseFeature& feature, int transform_mode);
// void TransformPolicy(int transform_mode); // this is reverse mode of TransformFeature
protected:
// void Init();
// void CopyFrom(const OthelloEnv &src);
int CalcResult() const;
OthelloStoneColor GetWinner() const;
inline void HandOff() { current_player_ = Opponent(); }
inline OthelloStoneColor Opponent(const OthelloStoneColor color = OthelloComm::COLOR_UNKNOWN) const {
return OthelloComm::BLACK + OthelloComm::WHITE
- (OthelloComm::COLOR_UNKNOWN != color ? color : current_player_);
}
inline OthelloStoneColor Self() const { return current_player_; }
inline OthelloCoordId GetLastMove() const { return last_position_; }
// inline OthelloStoneColor CurrentPlayer() const { return current_player_; }
//void OthelloEnv::TransformCoord(OthelloCoordId &x, OthelloCoordId &y, int mode, bool reverse = false)
void GetSensibleMove();
bool Check_Cross(OthelloCoordId x, OthelloCoordId y, int update) const;
int Check_Straight_Army(OthelloCoordId x, OthelloCoordId y, int d, int update) const;
int Find_Legal_Moves(int color) const;
protected:
// board utils
OthelloStone stones_[OthelloComm::OTHELLOBOARD_SIZE];
OthelloStoneColor board_state_[OthelloComm::OTHELLOBOARD_SIZE];
OthelloStoneColor current_player_;
OthelloCoordId last_position_;
bool is_resign_;
int state_;
int B_;
int W_;
// hash board state
std::unordered_set<uint64_t> board_hash_states_;
uint64_t zobrist_hash_value_;
// features
bool legal_move_map_[OthelloComm::OTHELLOBOARD_SIZE];
OthelloSize move_count_[OthelloComm::OTHELLOBOARD_SIZE];
std::vector<std::string> feature_history_list_;
};
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleIdentifier</key>
<string>com.apple.xcode.dsym.othello10</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>dSYM</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleIdentifier</key>
<string>com.apple.xcode.dsym.othello8</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>dSYM</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>
...现已初步实现四种棋类的扩展代码...
每个文件夹代表一种棋类:
Chess ... 国际象棋
Connect4 ... 平面四子棋
GoBang ... 五子棋
Othello ... 黑白棋
棋类文件夹中的文件夹(棋类英文小写字母开头)封装了基于师兄已完成工作的棋类子类代码...和我们的AlphaGoZero框架相对应
棋类文件夹里面的代码和可执行文件为原有棋类代码及其编译结果
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment