#include <iostream>
#include <list>
#include "matrix.h"
#include "deque.h"
#include "stringAMV.h"
#include "mathAMV.h"
#include "pointer.h"
#include "REEvaluator.h"
namespace amv {
struct position {
int row,col;
position(): row(0), col(0)
{
}
position(int r, int c): row(r), col(c)
{
}
bool operator==(const position &p) const
{
return (row==p.row && col==p.col);
}
};
enum piece_type { KNIGHT, KING, QUEEN, BISHOP, PAWN, CASTLE };
class round;
class piece {
public:
static const unsigned int hAttack, vAttack, dAttack, lAttack, onlyForward, onlyOneSquare;
const unsigned int traits;
piece_type pt;
position pos;
int value;
char letter;
bool color;
bool moved;
matrix<ipointer<piece> > *pChessboard;
piece(piece_type t, const position &p, int v, char l, bool c, matrix<ipointer<piece> > *pCb, const unsigned int tr):
pt(t), pos(p), value(v), letter(l), color(c), pChessboard(pCb), traits(tr), moved(false)
{
}
virtual piece *clone() const
{
return new piece(*this);
}
void setChessboard(matrix<ipointer<piece> > *pCb)
{
pChessboard=pCb;
}
virtual bool move(const position &newPos)
{
(*pChessboard)[newPos.row][newPos.col]=this;
(*pChessboard)[pos.row][pos.col].untie();
pos=newPos;
if(!moved)
moved=true;
return true;
}
bool capture(const position &newPos)
{
(*pChessboard)[newPos.row][newPos.col]=ipointer<piece>(); return piece::move(newPos);
}
virtual void getPositions(deque<position> &dp) const
{
}
void gethPositions(deque<position> &dp) const
{
int i;
for(i=pos.col+1; i<(*pChessboard).columns(); ++i)
{
if((*pChessboard)[pos.row][i])
{
if((*pChessboard)[pos.row][i]->getColor()!=getColor())
dp.push_back(position(pos.row,i));
break;
}
else
dp.push_back(position(pos.row,i));
}
for(i=pos.col-1; i>=0; --i)
{
if((*pChessboard)[pos.row][i])
{
if((*pChessboard)[pos.row][i]->getColor()!=getColor())
dp.push_back(position(pos.row,i));
break;
}
else
dp.push_back(position(pos.row,i));
}
}
void getvPositions(deque<position> &dp) const
{
int i;
for(i=pos.row+1; i<(*pChessboard).rows(); ++i)
{
if((*pChessboard)[i][pos.col])
{
if((*pChessboard)[i][pos.col]->getColor()!=getColor())
dp.push_back(position(i,pos.col));
break;
}
else
dp.push_back(position(i,pos.col));
}
for(i=pos.row-1; i>=0; --i)
{
if((*pChessboard)[i][pos.col])
{
if((*pChessboard)[i][pos.col]->getColor()!=getColor())
dp.push_back(position(i,pos.col));
break;
}
else
dp.push_back(position(i,pos.col));
}
}
void getdPositions(deque<position> &dp) const
{
int i,j;
for(i=pos.row+1, j=pos.col+1; i<(*pChessboard).rows() && j<pChessboard->columns(); ++i, ++j)
if((*pChessboard)[i][j])
{
if((*pChessboard)[i][j]->getColor()!=getColor())
dp.push_back(position(i,j));
break;
}
else
dp.push_back(position(i,j));
for(i=pos.row-1, j=pos.col+1; i>=0 && j<pChessboard->columns(); --i, ++j)
if((*pChessboard)[i][j])
{
if((*pChessboard)[i][j]->getColor()!=getColor())
dp.push_back(position(i,j));
break;
}
else
dp.push_back(position(i,j));
for(i=pos.row+1, j=pos.col-1; i<(*pChessboard).rows() && j>=0; ++i, --j)
if((*pChessboard)[i][j])
{
if((*pChessboard)[i][j]->getColor()!=getColor())
dp.push_back(position(i,j));
break;
}
else
dp.push_back(position(i,j));
for(i=pos.row-1, j=pos.col-1; i>=0 && j>=0; --i, --j)
if((*pChessboard)[i][j])
{
if((*pChessboard)[i][j]->getColor()!=getColor())
dp.push_back(position(i,j));
break;
}
else
dp.push_back(position(i,j));
}
virtual void revalue()
{
}
bool getColor() const
{
return color;
}
bool isValidPosition(const position &p) const
{
if(p.row<0 || p.row>=pChessboard->rows())
return false;
if(p.col<0 || p.col>=pChessboard->columns())
return false;
return true;
}
bool isPieceBetween(const position &p)
{
int i,j;
if(p.col==pos.col) {
if(pos.row>p.row)
{
for(i=p.row+1; i<pos.row; ++i)
if((*pChessboard)[i][pos.col])
return true;
}
else
{
for(i=pos.row+1; i<p.row; ++i)
if((*pChessboard)[i][pos.col])
return true;
}
return false;
}
if(p.row==pos.row) {
if(pos.col>p.col)
{
for(i=p.col+1; i<pos.col; ++i)
if((*pChessboard)[pos.row][i])
return true;
}
else
{
for(i=pos.col+1; i<p.col; ++i)
if((*pChessboard)[pos.row][i])
return true;
}
return false;
}
if(abs(p.row-pos.row)==abs(p.col-pos.col)) {
if(p.col>pos.col)
{
if(p.row>pos.row)
{
for(i=pos.row+1, j=pos.col+1; i<p.row; ++i, ++j)
if((*pChessboard)[i][j])
return true;
}
else
{
for(i=pos.row-1, j=pos.col+1; i>p.row; --i, ++j)
if((*pChessboard)[i][j])
return true;
}
}
else
{
if(p.row>pos.row)
{
for(i=pos.row+1, j=pos.col-1; i<p.row; ++i, --j)
if((*pChessboard)[i][j])
return true;
}
else
{
for(i=pos.row-1, j=pos.col-1; i>p.row; --i, --j)
if((*pChessboard)[i][j])
return true;
}
}
return false;
}
return false;
}
bool isAttacked()
{
int i,j;
for(i=pos.row+1; i<(*pChessboard).rows(); ++i)
if((*pChessboard)[i][pos.col])
if((*pChessboard)[i][pos.col]->getColor()!=getColor())
{
if((*pChessboard)[i][pos.col]->traits & piece::vAttack)
return true;
else
break;
}
else
break;
for(i=pos.row-1; i>=0; --i)
if((*pChessboard)[i][pos.col])
if((*pChessboard)[i][pos.col]->getColor()!=getColor())
{
if((*pChessboard)[i][pos.col]->traits & piece::vAttack)
return true;
else
break;
}
else
break;
for(i=pos.col+1; i<(*pChessboard).columns(); ++i)
if((*pChessboard)[pos.row][i])
if((*pChessboard)[pos.row][i]->getColor()!=getColor())
{
if((*pChessboard)[pos.row][i]->traits & piece::hAttack)
return true;
else
break;
}
else
break;
for(i=pos.col-1; i>=0; --i)
if((*pChessboard)[pos.row][i])
if((*pChessboard)[pos.row][i]->getColor()!=getColor())
{
if((*pChessboard)[pos.row][i]->traits & piece::hAttack)
return true;
else
break;
}
else
break;
for(i=pos.row+1, j=pos.col+1; i<(*pChessboard).rows() && j<pChessboard->columns(); ++i, ++j)
if((*pChessboard)[i][j])
if((*pChessboard)[i][j]->getColor()!=getColor())
{
if(getColor())
{ if(((*pChessboard)[i][j]->traits & piece::dAttack)
&& ((*pChessboard)[i][j]->traits & piece::onlyForward)
&& ((*pChessboard)[i][j]->traits & piece::onlyOneSquare))
{
if(i-pos.row==1)
return true;
else
break;
}
else
if(((*pChessboard)[i][j]->traits & piece::dAttack))
return true;
else
break;
}
else
{
if(((*pChessboard)[i][j]->traits & piece::dAttack)
&& ((*pChessboard)[i][j]->traits & piece::onlyForward)
&& ((*pChessboard)[i][j]->traits & piece::onlyOneSquare))
{
break;
}
else
if(((*pChessboard)[i][j]->traits & piece::dAttack))
return true;
else
break;
}
}
else
break;
for(i=pos.row-1, j=pos.col+1; i>=0 && j<pChessboard->columns(); --i, ++j)
if((*pChessboard)[i][j])
if((*pChessboard)[i][j]->getColor()!=getColor())
{
if(getColor())
{
if(((*pChessboard)[i][j]->traits & piece::dAttack)
&& ((*pChessboard)[i][j]->traits & piece::onlyForward)
&& ((*pChessboard)[i][j]->traits & piece::onlyOneSquare))
{
break;
}
else
if(((*pChessboard)[i][j]->traits & piece::dAttack))
return true;
else
break;
}
else
{
if(((*pChessboard)[i][j]->traits & piece::dAttack)
&& ((*pChessboard)[i][j]->traits & piece::onlyForward)
&& ((*pChessboard)[i][j]->traits & piece::onlyOneSquare))
{
if(pos.row-i==1)
return true;
else
break;
}
else
if(((*pChessboard)[i][j]->traits & piece::dAttack))
return true;
else
break;
}
}
else
break;
for(i=pos.row+1, j=pos.col-1; i<(*pChessboard).rows() && j>=0; ++i, --j)
if((*pChessboard)[i][j])
if((*pChessboard)[i][j]->getColor()!=getColor())
{
if(getColor())
{
if(((*pChessboard)[i][j]->traits & piece::dAttack)
&& ((*pChessboard)[i][j]->traits & piece::onlyForward)
&& ((*pChessboard)[i][j]->traits & piece::onlyOneSquare))
{
if(i-pos.row==1)
return true;
else
break;
}
else
if(((*pChessboard)[i][j]->traits & piece::dAttack))
return true;
else
break;
}
else
{
if(((*pChessboard)[i][j]->traits & piece::dAttack)
&& ((*pChessboard)[i][j]->traits & piece::onlyForward)
&& ((*pChessboard)[i][j]->traits & piece::onlyOneSquare))
{
break;
}
else
if(((*pChessboard)[i][j]->traits & piece::dAttack))
return true;
else
break;
}
}
else
break;
for(i=pos.row-1, j=pos.col-1; i>=0 && j>=0; --i, --j)
if((*pChessboard)[i][j])
if((*pChessboard)[i][j]->getColor()!=getColor())
{
if(getColor())
{
if(((*pChessboard)[i][j]->traits & piece::dAttack)
&& ((*pChessboard)[i][j]->traits & piece::onlyForward)
&& ((*pChessboard)[i][j]->traits & piece::onlyOneSquare))
{
break;
}
else
if(((*pChessboard)[i][j]->traits & piece::dAttack))
return true;
else
break;
}
else
{
if(((*pChessboard)[i][j]->traits & piece::dAttack)
&& ((*pChessboard)[i][j]->traits & piece::onlyForward)
&& ((*pChessboard)[i][j]->traits & piece::onlyOneSquare))
{
if(pos.row-i==1)
return true;
else
break;
}
else
if(((*pChessboard)[i][j]->traits & piece::dAttack))
return true;
else
break;
}
}
else
break;
position lPositions[8];
lPositions[0]=position(pos.row+2,pos.col+1);
lPositions[1]=position(pos.row+1,pos.col+2);
lPositions[2]=position(pos.row-1,pos.col+2);
lPositions[3]=position(pos.row-2,pos.col+1);
lPositions[4]=position(pos.row-2,pos.col-1);
lPositions[5]=position(pos.row-1,pos.col-2);
lPositions[6]=position(pos.row+1,pos.col-2);
lPositions[7]=position(pos.row+2,pos.col-1);
for(i=0; i<8; ++i)
{
if(isValidPosition(lPositions[i]))
if((*pChessboard)[lPositions[i].row][lPositions[i].col])
if((*pChessboard)[lPositions[i].row][lPositions[i].col]->getColor()!=getColor() && ((*pChessboard)[lPositions[i].row][lPositions[i].col]->traits & piece::lAttack))
return true;
}
return false;
}
friend ostream &operator<<(ostream &os, const piece &p)
{
return os<<p.letter;
}
};
const unsigned int piece::hAttack=0x0001, piece::vAttack=0x0002,
piece::dAttack=0x0004, piece::lAttack=0x0008, piece::onlyForward=0x0010, piece::onlyOneSquare=0x0020;
struct movement {
ipointer<piece> pPiece;
position pos1,pos2;
movement(): pPiece(), pos1(), pos2()
{
}
movement(const ipointer<piece> &pP, const position &p1, const position &p2):
pPiece(pP), pos1(p1), pos2(p2)
{
}
};
class bishop: public piece {
public:
bishop(bool color, const position &p, matrix<ipointer<piece> > *pCb): piece(BISHOP,p,3,color? 'B': 'b', color,pCb,piece::dAttack)
{
}
piece *clone() const
{
return new bishop(*this);
}
bool move(const position &newPos)
{
int colDif=abs(newPos.col-pos.col);
int rowDif=abs(newPos.row-pos.row);
if(rowDif==colDif)
{
if(isPieceBetween(newPos))
return false;
if((*pChessboard)[newPos.row][newPos.col])
{
return capture(newPos);
}
else
{
return piece::move(newPos);
}
}
else
return false;
}
void getPositions(deque<position> &dp) const
{
getdPositions(dp);
}
};
class knight: public piece {
public:
knight(bool color, const position &p, matrix<ipointer<piece> > *pCb): piece(KNIGHT,p,3,color? 'H': 'h', color,pCb,piece::lAttack)
{
}
piece *clone() const
{
return new knight(*this);
}
bool move(const position &newPos)
{
int colDif=abs(newPos.col-pos.col);
int rowDif=abs(newPos.row-pos.row);
if(colDif+rowDif==3)
{
if((*pChessboard)[newPos.row][newPos.col])
return capture(newPos);
else
return piece::move(newPos);
}
else
return false;
}
void getPositions(deque<position> &dp) const
{
int i;
position lPositions[8];
lPositions[0]=position(pos.row+2,pos.col+1);
lPositions[1]=position(pos.row+1,pos.col+2);
lPositions[2]=position(pos.row-1,pos.col+2);
lPositions[3]=position(pos.row-2,pos.col+1);
lPositions[4]=position(pos.row-2,pos.col-1);
lPositions[5]=position(pos.row-1,pos.col-2);
lPositions[6]=position(pos.row+1,pos.col-2);
lPositions[7]=position(pos.row+2,pos.col-1);
for(i=0; i<8; ++i)
{
if(isValidPosition(lPositions[i]))
{
if((*pChessboard)[lPositions[i].row][lPositions[i].col])
{
if((*pChessboard)[lPositions[i].row][lPositions[i].col]->getColor()!=getColor())
dp.push_back(lPositions[i]);
}
else
dp.push_back(lPositions[i]);
}
}
}
};
class castle: public piece {
public:
castle(bool color,const position &p, matrix<ipointer<piece> > *pCb): piece(CASTLE,p,5,color? 'C': 'c', color,pCb,piece::hAttack|piece::vAttack)
{
}
piece *clone() const
{
return new castle(*this);
}
bool move(const position &newPos)
{
int colDif=abs(newPos.col-pos.col);
int rowDif=abs(newPos.row-pos.row);
if((!colDif && rowDif) || (colDif && !rowDif))
{
if(isPieceBetween(newPos))
return false;
if((*pChessboard)[newPos.row][newPos.col])
return capture(newPos);
else
return piece::move(newPos);
}
else
return false;
}
void getPositions(deque<position> &dp) const
{
getvPositions(dp);
gethPositions(dp);
}
};
class queen: public piece {
public:
queen(bool color, const position &p, matrix<ipointer<piece> > *pCb): piece(QUEEN,p,9,color? 'Q': 'q', color,pCb,piece::hAttack|piece::vAttack|piece::dAttack)
{
}
piece *clone() const
{
return new queen(*this);
}
bool move(const position &newPos)
{
int colDif=abs(newPos.col-pos.col);
int rowDif=abs(newPos.row-pos.row);
if((!colDif && rowDif) || (colDif && !rowDif) || (colDif==rowDif))
{
if(isPieceBetween(newPos))
return false;
if((*pChessboard)[newPos.row][newPos.col])
return capture(newPos);
else
return piece::move(newPos);
}
else
return false;
}
void getPositions(deque<position> &dp) const
{
getvPositions(dp);
gethPositions(dp);
getdPositions(dp);
}
};
class king: public piece {
public:
king(bool color, const position &p, matrix<ipointer<piece> > *pCb): piece(KING,p,39,color? 'K': 'k', color,pCb,piece::hAttack|piece::vAttack|piece::dAttack)
{
}
piece *clone() const
{
return new king(*this);
}
bool move(const position &newPos)
{
int colDif=abs(newPos.col-pos.col);
int rowDif=abs(newPos.row-pos.row);
if((!colDif && rowDif) || (colDif && !rowDif) || (colDif==rowDif))
{
if(colDif<2 && rowDif<2)
{
if((*pChessboard)[newPos.row][newPos.col])
return capture(newPos);
else
return piece::move(newPos);
}
else
return false;
}
else
return false;
}
bool move1(const position &newPos)
{
return piece::move(newPos);
}
void getPositions(deque<position> &dp) const
{
position kpositions[8];
kpositions[0]=position(pos.row+1,pos.col-1);
kpositions[1]=position(pos.row+1,pos.col);
kpositions[2]=position(pos.row+1,pos.col+1);
kpositions[3]=position(pos.row,pos.col-1);
kpositions[4]=position(pos.row,pos.col+1);
kpositions[5]=position(pos.row-1,pos.col-1);
kpositions[6]=position(pos.row-1,pos.col);
kpositions[7]=position(pos.row-1,pos.col+1);
for(int i=0; i<8; ++i)
{
if(isValidPosition(kpositions[i]))
{
if((*pChessboard)[kpositions[i].row][kpositions[i].col])
{
if((*pChessboard)[kpositions[i].row][kpositions[i].col]->getColor()!=getColor())
dp.push_back(kpositions[i]);
}
else
dp.push_back(kpositions[i]);
}
}
}
};
class pawn: public piece {
public:
pawn(bool color, const position &p, matrix<ipointer<piece> > *pCb): piece(PAWN,p,1,color? 'P': 'p', color,pCb,piece::dAttack|piece::onlyForward|piece::onlyOneSquare)
{
}
piece *clone() const
{
return new pawn(*this);
}
bool move(const position &newPos, const movement &lastMovement, const char crown)
{
if(lastMovement.pPiece)
{
pawn *pp1;
if((pp1=dynamic_cast<pawn *>((piece *)(lastMovement.pPiece))) &&
(abs(lastMovement.pos2.row-lastMovement.pos1.row)==2) &&
(newPos.col==lastMovement.pos2.col) &&
(abs(lastMovement.pos2.row-newPos.row)==1))
{
piece::move(newPos);
if(color)
(*pChessboard)[newPos.row-1][newPos.col]=ipointer<piece>(); else
(*pChessboard)[newPos.row+1][newPos.col]=ipointer<piece>();
return true;
}
}
int colDif=abs(newPos.col-pos.col);
int rowDif=abs(newPos.row-pos.row);
bool toCapture(colDif==1 && rowDif==1);
if(colDif>1 || rowDif>2)
return false;
if((color && newPos.row<pos.row) || (!color && newPos.row>pos.row))
return false;
if(rowDif==2 && moved)
return false;
if(rowDif==2 && colDif==1)
return false;
if(toCapture)
{
if((*pChessboard)[newPos.row][newPos.col])
{
capture(newPos);
if(newPos.row==0 || newPos.row==pChessboard->rows()-1)
{
switch(crown)
{
case 'q':
(*pChessboard)[pos.row][pos.col]=ipointer<piece>(new queen(color,pos,pChessboard));
break;
case 'c':
(*pChessboard)[pos.row][pos.col]=ipointer<piece>(new castle(color,pos,pChessboard));
break;
case 'b':
(*pChessboard)[pos.row][pos.col]=ipointer<piece>(new bishop(color,pos,pChessboard));
break;
case 'h':
(*pChessboard)[pos.row][pos.col]=ipointer<piece>(new knight(color,pos,pChessboard));
break;
default:
(*pChessboard)[pos.row][pos.col]=ipointer<piece>(new queen(color,pos,pChessboard));
}
}
return true;
}
else
return false;
}
else
{
if(isPieceBetween(newPos) || (*pChessboard)[newPos.row][newPos.col])
return false;
piece::move(newPos);
if(newPos.row==0 || newPos.row==pChessboard->rows()-1)
{
switch(crown)
{
case 'q':
(*pChessboard)[pos.row][pos.col]=ipointer<piece>(new queen(color,pos,pChessboard));
break;
case 'c':
(*pChessboard)[pos.row][pos.col]=ipointer<piece>(new castle(color,pos,pChessboard));
break;
case 'b':
(*pChessboard)[pos.row][pos.col]=ipointer<piece>(new bishop(color,pos,pChessboard));
break;
case 'h':
(*pChessboard)[pos.row][pos.col]=ipointer<piece>(new knight(color,pos,pChessboard));
break;
default:
(*pChessboard)[pos.row][pos.col]=ipointer<piece>(new queen(color,pos,pChessboard));
}
}
return true;
}
}
void getPositions(deque<position> &dp, const movement &lastMovement) const
{
if(getColor())
{
if(!moved && !(*pChessboard)[pos.row+2][pos.col] && !(*pChessboard)[pos.row+1][pos.col])
dp.push_back(position(pos.row+2,pos.col));
if(isValidPosition(position(pos.row+1,pos.col)) && !(*pChessboard)[pos.row+1][pos.col])
dp.push_back(position(pos.row+1,pos.col));
if(isValidPosition(position(pos.row+1,pos.col-1)) && (*pChessboard)[pos.row+1][pos.col-1] && (*pChessboard)[pos.row+1][pos.col-1]->getColor()!=getColor())
dp.push_back(position(pos.row+1,pos.col-1));
if(isValidPosition(position(pos.row+1,pos.col+1)) && (*pChessboard)[pos.row+1][pos.col+1] && (*pChessboard)[pos.row+1][pos.col+1]->getColor()!=getColor())
dp.push_back(position(pos.row+1,pos.col+1));
}
else
{
if(!moved && !(*pChessboard)[pos.row-2][pos.col] && !(*pChessboard)[pos.row-1][pos.col])
dp.push_back(position(pos.row-2,pos.col));
if(isValidPosition(position(pos.row-1,pos.col)) && !(*pChessboard)[pos.row-1][pos.col])
dp.push_back(position(pos.row-1,pos.col));
if(isValidPosition(position(pos.row-1,pos.col-1)) && (*pChessboard)[pos.row-1][pos.col-1] && (*pChessboard)[pos.row-1][pos.col-1]->getColor()!=getColor())
dp.push_back(position(pos.row-1,pos.col-1));
if(isValidPosition(position(pos.row-1,pos.col+1)) && (*pChessboard)[pos.row-1][pos.col+1] && (*pChessboard)[pos.row-1][pos.col+1]->getColor()!=getColor())
dp.push_back(position(pos.row-1,pos.col+1));
}
if(lastMovement.pPiece)
{
pawn *pp1;
if((pp1=dynamic_cast<pawn *>((piece *)(lastMovement.pPiece))) &&
(abs(lastMovement.pos2.row-lastMovement.pos1.row)==2) &&
(abs(pos.col-lastMovement.pos2.col)==1) &&
(lastMovement.pos2.row==pos.row))
{
dp.push_back(position((color)? pos.row+1: pos.row-1,(pos.col>lastMovement.pos2.col)? pos.col-1: pos.col+1));
}
}
}
};
class round {
matrix<ipointer<piece> > chessboard;
bool go;string player1;
string player2;
int playerId1;
int playerId2;
movement lastMovement;
deque<movement> movements;
int winner;bool finished;
bool proposedTie;
mutable string message;
int messageFor;
static int playerId;
static REEvaluator REEround;
round(const round &r): chessboard(r.chessboard), go(r.go), player1(r.player1), player2(r.player2),
playerId1(r.playerId1), playerId2(r.playerId2), lastMovement(r.lastMovement), movements(r.movements),
winner(r.winner), finished(r.finished), proposedTie(r.proposedTie), message(r.message), messageFor(r.messageFor)
{
int i,j;
for(i=0; i<chessboard.rows(); ++i)
for(j=0; j<chessboard.columns(); ++j)
if(chessboard[i][j])
chessboard[i][j]->setChessboard(&chessboard);
}
public:
round(): chessboard(8,8), go(true), player1(), player2(),
playerId1(0), playerId2(0), winner(0), finished(false), proposedTie(false),
message(), messageFor(0)
{
int j;
for(int i=0; i<chessboard.rows(); ++i)
for(j=0; j<chessboard.columns(); ++j)
chessboard[i][j]=0;
chessboard[0][0]=new castle(true,position(0,0),&chessboard);
chessboard[0][1]=new knight(true,position(0,1),&chessboard);
chessboard[0][2]=new bishop(true,position(0,2),&chessboard);
chessboard[0][3]=new queen(true,position(0,3),&chessboard);
chessboard[0][4]=new king(true,position(0,4),&chessboard);
chessboard[0][5]=new bishop(true,position(0,5),&chessboard);
chessboard[0][6]=new knight(true,position(0,6),&chessboard);
chessboard[0][7]=new castle(true,position(0,7),&chessboard);
for(j=0; j<chessboard.columns(); ++j)
chessboard[1][j]=new pawn(true,position(1,j),&chessboard);
chessboard[7][0]=new castle(false,position(7,0),&chessboard);
chessboard[7][1]=new knight(false,position(7,1),&chessboard);
chessboard[7][2]=new bishop(false,position(7,2),&chessboard);
chessboard[7][3]=new queen(false,position(7,3),&chessboard);
chessboard[7][4]=new king(false,position(7,4),&chessboard);
chessboard[7][5]=new bishop(false,position(7,5),&chessboard);
chessboard[7][6]=new knight(false,position(7,6),&chessboard);
chessboard[7][7]=new castle(false,position(7,7),&chessboard);
for(j=0; j<chessboard.columns(); ++j)
chessboard[6][j]=new pawn(false,position(6,j),&chessboard);
}
bool hasMessage(int pId) const
{
return (messageFor==pId && message.size());
}
string getMessage(int pId) const
{
string temp;
if(pId==messageFor)
{
temp=message;
message.clear();
}
return temp;
}
int canPlay(bool &color,const string &s)
{
if(playerId1>0 && playerId2>0)
{
return 0;
}
else if(playerId1==0)
{
playerId1=++playerId;
player1=s;
color=true;
return playerId1;
}
else if(playerId2==0)
{
playerId2=++playerId;
player2=s;
color=false;
return playerId2;
}
}
bool isTie() const
{
if(movements.size()<6)
return false;
else
{ deque<movement>::size_type size=movements.size();
if((movements[size-1].pos1==movements[size-5].pos1 && movements[size-1].pos2==movements[size-5].pos2) &&
(movements[size-2].pos1==movements[size-6].pos1 && movements[size-2].pos2==movements[size-6].pos2))
return true;
else
return false;
}
}
bool isValidPosition(const position &pos)
{
if(pos.row<0 || pos.row>=chessboard.rows())
return false;
if(pos.col<0 || pos.col>=chessboard.columns())
return false;
return true;
}
king *findKing(bool color)
{
king *pk;
for(int i=0; i<chessboard.rows(); ++i)
for(int j=0; j<chessboard.columns(); ++j)
if(chessboard[i][j] && chessboard[i][j]->getColor()==color)
if(pk=dynamic_cast<king *>((piece *)chessboard[i][j]))
return pk;
return 0;
}
bool canMove(int pId) const
{
int i, j;
for(i=0; i<chessboard.rows(); ++i)
for(j=0; j<chessboard.columns(); ++j)
{
if(((bool)chessboard[i][j]) && chessboard[i][j]->getColor()==go)
{
pawn *pp;
deque<position> dp;
if(pp=dynamic_cast<pawn *>((piece *)chessboard[i][j]))
pp->getPositions(dp,lastMovement);
else
chessboard[i][j]->getPositions(dp);
for(int k=0; k<dp.size(); ++k)
{
round rtemp1(*this);
string s1(convertToLetters(position(i,j),dp[k]));
rtemp1.play(pId,s1,true);
king *pk1;
if(pk1=rtemp1.findKing(go))
{
if(pk1->isAttacked())
continue;
else
goto finMate;
}
else
{
}
}
}
else
continue;
}
finMate:
;
if(i==chessboard.rows() && j==chessboard.columns())
return false;
else
return true;
}
bool play(int pId, const string &s, bool noRecursive=false) {
if(!noRecursive)
{
if(finished)
{
messageFor=pId;
message="Partida terminada\n";
if(!winner)
message+="Fue tablas\n";
else if(winner>0)
message+="Ganó blancas\n";
else
message+="Ganó negras\n";
return false;
}
if(pId==playerId1)
{
if(!go)
{
messageFor=pId;
message="No es turno de blancas";
return false;
}
}
else if(pId==playerId2)
{
if(go)
{
messageFor=pId;
message="No es turno de negras";
return false;
}
}
else
{
messageFor=pId;
message="Identificación de jugador inválida";
return false;
}
if(!(REEround.eval(s)))
{
messageFor=pId;
message="Jugada inválida";
return false;
}
if(proposedTie && !(s[0]=='=' || s[0]=='#'))
{
messageFor=pId;
message="Hay una propuesta de tablas, ¿Acepta (=, sí; #, no)?";
return false;
}
if(s[0]=='-')
{
proposedTie=true;
go=!go;
messageFor=(pId==playerId1? playerId2: playerId1);
message="Hay una propuesta de tablas, ¿Acepta (=, sí; #, no)?";
return true;
}
else if(s[0]=='/')
{
finished=true;
if(go)
{
winner=-1;
messageFor=(pId==playerId1? playerId2: playerId1);
message="Blancas abandonan, Negras gana la partida";
}
else
{
winner=1;
messageFor=(pId==playerId1? playerId2: playerId1);
message="Negras abandonan, Blancas gana la partida";
}
return true;
}
else if(s[0]=='=')
{
if(proposedTie)
{
finished=true;
winner=0;
proposedTie=false;
messageFor=pId;
message="La partida terminó: tablas";
return true;
}
else
{
messageFor=pId;
message="Este símbolo es válido sólo cuando hay una propuesta de tablas";
return false;
}
}
else if(s[0]=='#')
{
if(proposedTie)
{
proposedTie=false;
go=!go;
messageFor=(pId==playerId1? playerId2: playerId1);
message="Se ha rechazado la propuesta de tablas";
return true;
}
else
{
messageFor=pId;
message="Este símbolo es válido sólo cuando hay una propuesta de tablas";
return false;
}
}
round rtemp(*this);
if(!(rtemp.play(pId,s,true)))
{
messageFor=rtemp.messageFor;
message=rtemp.message;
return false;
}
if(rtemp.isTie())
{
finished=true;
winner=0;
messageFor=pId;
message="Tablas por repetición de jugadas";
}
king *pwk, *pbk;
if(!rtemp.go)
{
if(pwk=rtemp.findKing(true))
if(pwk->isAttacked())
{
messageFor=pId;
message="Imposible, Rey blanco atacado: "+s;
return false;
}
if(pbk=rtemp.findKing(false))
{
if(pbk->isAttacked())
{
if(rtemp.canMove(pId))
{
messageFor=(pId==playerId1? playerId2: playerId1);
message="++ Jaque";
}
else
{
finished=true;
winner=1;
messageFor=(pId==playerId1? playerId2: playerId1);
message="+++ Jaque Mate";
}
}
else
{
if(!rtemp.canMove(pId))
{
finished=true;
winner=0;
messageFor=pId;
message="Rey negro ahogado, tablas";
}
}
}
}
else
{
if(pbk=rtemp.findKing(false))
if(pbk->isAttacked())
{
messageFor=pId;
message="Imposible, Rey negro atacado: "+s;
return false;
}
if(pwk=rtemp.findKing(true))
{
if(pwk->isAttacked())
{
if(rtemp.canMove(pId))
{
messageFor=(pId==playerId1? playerId2: playerId1);
message="++ Jaque";
}
else
{
finished=true;
winner=-1;
messageFor=(pId==playerId1? playerId2: playerId1);
message="+++ Jaque Mate";
}
}
else
{
if(!rtemp.canMove(pId))
{
finished=true;
winner=0;
messageFor=pId;
message="Rey blanco ahogado, tablas";
}
}
}
}
}
if(s[0]=='o')
{
king *pk;
if(go)
pk=dynamic_cast<king *>((piece *)chessboard[0][4]);
else
pk=dynamic_cast<king *>((piece *)chessboard[7][4]);
if(pk)
{
if(pk->getColor()==go)
{
if(pk->isAttacked())
{
messageFor=pId;
message="El rey está en Jaque, imposible enrocar";
return false;
}
}
else
{
messageFor=pId;
message="El rey ha sido movido, imposible enrocar";
return false;
}
}
else
{
messageFor=pId;
message="El rey ha sido movido, imposible enrocar";
return false;
}
if(s.size()<5)
{
if(moveKingCastle1(pId))
{
go=!go;
lastMovement=movement(ipointer<piece>(),position(),position());
movements.push_back(lastMovement);
return true;
}
else
return false;
}
else
{
if(moveKingCastle2(pId))
{
go=!go;
lastMovement=movement(ipointer<piece>(),position(),position());
movements.push_back(lastMovement);
return true;
}
else
return false;
}
}
else
{
int row1, col1, row2, col2;
row1=convertRow(s[1]);
col1=convertColumn(s[0]);
row2=convertRow(s[4]);
col2=convertColumn(s[3]);
if(isValidPosition(position(row1,col1)) && isValidPosition(position(row2,col2)))
{
if(row1==row2 && col1==col2)
{
messageFor=pId;
message="Es la misma posición";
return false;
}
if(chessboard[row1][col1] && (chessboard[row1][col1]->getColor()==go)) {
if(chessboard[row2][col2]) { if(chessboard[row1][col1]->getColor()==chessboard[row2][col2]->getColor())
{
messageFor=pId;
message="Hay otra pieza del mismo color";
return false;
}
}
pawn *pp; if(pp=dynamic_cast<pawn *>((piece *)chessboard[row1][col1]))
{
char crown='q';
if(6<s.size())
crown=s[s.size()-1];
if(!(pp->move(position(row2,col2),lastMovement,crown)))
{
messageFor=pId;
message="Jugada inválida";
return false;
}
else
{
go=!go;
lastMovement=movement(chessboard[row2][col2],position(row1,col1),position(row2,col2));
movements.push_back(lastMovement);
return true;
}
}
else
{
if(!(chessboard[row1][col1]->move(position(row2,col2))))
{
messageFor=pId;
message="Jugada inválida";
return false;
}
else
{
go=!go;
lastMovement=movement(chessboard[row2][col2],position(row1,col1),position(row2,col2));
movements.push_back(lastMovement);
return true;
}
}
}
else
{
messageFor=pId;
message="No hay una pieza en la posición o es del contrincante";
return false; }
}
else
{
messageFor=pId;
message="Una de las posiciones es inválida";
return false;
}
}
}
bool moveKingCastle1(int pId)
{
if(go)
{
if(chessboard[0][4] && chessboard[0][7])
{
if(chessboard[0][4]->moved || chessboard[0][7]->moved)
{
messageFor=pId;
message="Ha movido o el rey o la torre";
return false;
}
else
{
if(chessboard[0][4]->isPieceBetween(position(0,7)))
{
messageFor=pId;
message="Hay una pieza entre el rey y la torre";
return false;
}
else
{
king *pk;
chessboard[0][7]->move(position(0,5));
if(pk=dynamic_cast<king *>((piece *)chessboard[0][4]))
return pk->move1(position(0,6));
else
{
messageFor=pId;
message="Error grave, infórmelo al autor";
return false;
}
}
}
}
else
{
messageFor=pId;
message="Una de las piezas ha sido movida";
return false;
}
}
else
{
if(chessboard[7][4] && chessboard[7][7])
{
if(chessboard[7][4]->moved || chessboard[7][7]->moved)
{
messageFor=pId;
message="Ha movido o el rey o la torre";
return false;
}
else
{
if(chessboard[7][4]->isPieceBetween(position(7,7)))
{
messageFor=pId;
message="Hay una pieza entre el rey y la torre";
return false;
}
else
{
king *pk;
chessboard[7][7]->move(position(7,5));
if(pk=dynamic_cast<king *>((piece *)chessboard[7][4]))
return pk->move1(position(7,6));
else
{
messageFor=pId;
message="Error grave, infórmelo al autor";
return false;
}
}
}
}
else
{
messageFor=pId;
message="Una de las piezas ha sido movida";
return false;
}
}
}
bool moveKingCastle2(int pId)
{
if(go)
{
if(chessboard[0][4] && chessboard[0][0])
{
if(chessboard[0][4]->moved || chessboard[0][0]->moved)
{
messageFor=pId;
message="Ha movido o el rey o la torre";
return false;
}
else
{
if(chessboard[0][4]->isPieceBetween(position(0,0)))
{
messageFor=pId;
message="Hay una pieza entre el rey y la torre";
return false;
}
else
{
king *pk;
chessboard[0][0]->move(position(0,3));
if(pk=dynamic_cast<king *>((piece *)chessboard[0][4]))
return pk->move1(position(0,2));
else
{
messageFor=pId;
message="Error grave, infórmelo al autor";
return false;
}
}
}
}
else
{
messageFor=pId;
message="Una de las piezas ha sido movida";
return false;
}
}
else
{
if(chessboard[7][4] && chessboard[7][0])
{
if(chessboard[7][4]->moved || chessboard[7][0]->moved)
{
messageFor=pId;
message="Ha movido o el rey o la torre";
return false;
}
else
{
if(chessboard[7][4]->isPieceBetween(position(7,0)))
{
messageFor=pId;
message="Hay una pieza entre el rey y la torre";
return false;
}
else
{
king *pk;
chessboard[7][0]->move(position(7,3));
if(pk=dynamic_cast<king *>((piece *)chessboard[7][4]))
return pk->move1(position(7,2));
else
{
messageFor=pId;
message="Error grave, infórmelo al autor";
return false;
}
}
}
}
else
{
messageFor=pId;
message="Una de las piezas ha sido movida";
return false;
}
}
}
int convertColumn(char c) const
{
switch(c)
{
case 'a': return 0;
case 'b': return 1;
case 'c': return 2;
case 'd': return 3;
case 'e': return 4;
case 'f': return 5;
case 'g': return 6;
case 'h': return 7;
default: return -1;
}
}
int convertRow(char c) const
{
switch(c)
{
case '1': return 0;
case '2': return 1;
case '3': return 2;
case '4': return 3;
case '5': return 4;
case '6': return 5;
case '7': return 6;
case '8': return 7;
default: return -1;
}
}
char convertColumnToLetter(int n) const
{
switch(n)
{
case 0: return 'a';
case 1: return 'b';
case 2: return 'c';
case 3: return 'd';
case 4: return 'e';
case 5: return 'f';
case 6: return 'g';
case 7: return 'h';
default: return '\0';
}
}
char convertRowToLetter(int n) const
{
switch(n)
{
case 0: return '1';
case 1: return '2';
case 2: return '3';
case 3: return '4';
case 4: return '5';
case 5: return '6';
case 6: return '7';
case 7: return '8';
default: return '\0';
}
}
string convertToLetters(const position &pos1, const position &pos2) const
{
string s;
s.resize(5);
s[0]=convertColumnToLetter(pos1.col);
s[1]=convertRowToLetter(pos1.row);
s[2]='-';
s[3]=convertColumnToLetter(pos2.col);
s[4]=convertRowToLetter(pos2.row);
return s;
}
friend ostream &operator<<(ostream &os,const round &r)
{
os<<std::endl<<r.player2<<" (Black) Vs. "<<r.player1<<" (White)"<<std::endl;
os<<std::endl<<"\xc2\xc4\xc2\xc4\xc2\xc4\xc2\xc4\xc2\xc4\xc2\xc4\xc2\xc4\xc2\xc4\xc2"<<std::endl;
for(int i=r.chessboard.rows()-1; i>=0; --i)
{
os<<'\xb3';
for(int j=0; j<r.chessboard.columns(); ++j)
{
if(r.chessboard[i][j])
os<<*(r.chessboard[i][j]);
else
os<<' ';
os<<'\xb3';
}
os<<' '<<(i+1)<<std::endl;
if(i>0)
os<<"\xc5\xc4\xc5\xc4\xc5\xc4\xc5\xc4\xc5\xc4\xc5\xc4\xc5\xc4\xc5\xc4\xc5"<<std::endl;
}
os<<"\xc1\xc4\xc1\xc4\xc1\xc4\xc1\xc4\xc1\xc4\xc1\xc4\xc1\xc4\xc1\xc4\xc1"<<std::endl;
os<<std::endl;
os<<" a b c d e f g h"<<std::endl;
return os;
}
};
int round::playerId=0;
REEvaluator round::REEround="\\-|=|#|/|(o<\\-<o)|(o<\\-<o<\\-<o)|(([a-h]<[1-8])<\\-<([a-h]<[1-8])<(=<(b|h|c|q))?)";
}
using namespace amv;
void main()
{
int id1, id2;
bool color1, color2;
string squit("salir"),s1,s2;
round partida;
std::cout<<partida;
if(!(id1=partida.canPlay(color1,"Kasparov")))
{
std::cerr<<"Jugador 1 no aceptado\n";
return;
}
if(!(id2=partida.canPlay(color2,"Karpov")))
{
std::cerr<<"Jugador 2 no aceptado\n";
return;
}
for(;;)
{
if(partida.hasMessage(id1))
std::cerr<<partida.getMessage(id1)<<std::endl;
std::cout<<"White"<<':';
std::cin>>s1;
if(s1==squit)
break;
while(true)
{
if(partida.play(id1,s1))
{
if(partida.hasMessage(id1))
std::cerr<<partida.getMessage(id1)<<std::endl;
break;
}
if(partida.hasMessage(id1))
std::cerr<<partida.getMessage(id1)<<std::endl;
std::cout<<"White"<<':';
std::cin>>s1;
if(s1==squit)
goto fin;
}
std::cout<<partida;
if(partida.hasMessage(id2))
std::cerr<<partida.getMessage(id2)<<std::endl;
std::cout<<"Black"<<':';
std::cin>>s2;
if(s2==squit)
break;
while(true)
{
if(partida.play(id2,s2))
{
if(partida.hasMessage(id2))
std::cerr<<partida.getMessage(id2)<<std::endl;
break;
}
if(partida.hasMessage(id2))
std::cerr<<partida.getMessage(id2)<<std::endl;
std::cout<<"Black"<<':';
std::cin>>s2;
if(s2==squit)
goto fin;
}
std::cout<<partida;
}
fin:;
std::cout<<"\n*** Autor: Ariel Medina ***\n";
}