-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPiece.cpp
More file actions
154 lines (120 loc) · 7.27 KB
/
Piece.cpp
File metadata and controls
154 lines (120 loc) · 7.27 KB
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include <iostream>
#include <string>
#include "Piece.h"
Piece::Piece()
{ // constructor 1: (default)
neverMoved = true; // mostly used for pawns
isCaptured = false; // this piece has not been captured
row = -1; // uninitialized, 1-based row # location of this piece (1..8)
col = -1; // uninitialized, 1-based col # location of this piece (1..8 corresponds to a...h)
ptype = "bad"; // string name of type of piece like "rook" "king", "queen", etc. Different from specified piece name below
isWhite = true; // true if a white piece, else black
name = "unknown"; // r1b, p1b, p4b, kib, etc.
board = nullptr; // a "back-pointer" to an instance of the ChessBoard by each piece
}
Piece::Piece(int _row, int _col, bool _isWhite, std::string _name )
{ // constructor 2
if(_row < 1 || _row > 8)
{
std::cout << "piece() constructor: row = " << _row << " is out of bounds. Placing piece at row = 1 by default." << std::endl;
_row = 1;
}
if(_col < 1 || _col > 8)
{
std::cout << "piece() constructor: column = " << colNames[_col] << " is out of bounds. Placing piece at column = 1 by default." << std::endl;
_col = 1;
}
neverMoved = true; // this piece has never been moved
row = _row; // 1-based row # location of this piece (1..8)
col = _col; // 1-based col # location of this piece (1..8 corresponds to a...h)
ptype = "unknown"; // string name of type of piece like "rook" "king", "queen", etc. Different than specified piece name below
isWhite = _isWhite; // true if white piece, otherwise black
name = _name; // r1b, p1b, p4b, kib, etc.
board = nullptr; // a "back-pointer" to an instance of the ChessBoard by each piece
}
// return a string that describes if this piece is White or Blank, based on the the isWhite bool member
std::string Piece::colorName(){ return ( isWhite ? "White" : "Black" );}
// destructor - invoked from destructor of derived class
Piece :: ~Piece(){ std::cout<<"Destructing piece base class" << std::endl; }
// member functions
// print out a debug description of each piece
void Piece :: printMe()
{
std::cout << "Color: " << colorName();
std::cout << "Type: " << ptype << ", ";
std::cout << "Location = (" << row << "," << colNames[col] << ") ";
std::cout << "Is Captured = " << (isCaptured ? "True" : "False") << std::endl;
}
/*
Boolean method to see if the row, col location specified is "legal" or not (to avoid crashing when bad input is provided). Note that this is 1-based and not zero-based.
*/
bool Piece :: isOnBoard(int _row, int _col){
if((_row<1 || _row > 8) || (_col<1 || _col > 8) ){
return false; // NO it is not a legal row col specification
}
else
return true; // YES it is a legal row col specification
}
/*
This is a virtual method that SHOULD be overwritten in each derived class. That means we will never really call this method, unless some derived class has not yet implemented this method. In that case, this method would serve as a fall-back method to simply see if the row, col specification is legal or not. As such, this is really just a debug method that should not be called once the game is fully implemented.
*/
bool Piece :: isLegalMoveTo(int _row, int _col) {
std::cout << "Baseclass isLegalMoveTo() here.." << std::endl;
if (isOnBoard(_row, _col))
return true;
else
return false;
} // virtual method to be implemented in derived classes
/*
This is the generic (base class) method that all pieces can use (it is NOT over-ridden by a derived class). Please note, however, that this method DOES call a method isLegalMoveTo() that IS over-ridden by a derived class. This technique allows a base-class method to call a derived method, which is the "key aspect" of this assignment. See **** below where this method is called.
*/
bool Piece::moveTo(int _row, int _col, bool silent )
{ // return true if the piece can move to the requested 1-based row, col location
if(row==_row && col==_col)
{ // if the move is not to the same location
if (!silent) std::cout << "piece.moveTo() : " << colorName() << " " << ptype << " move from (" << row << ", " << colNames[col] << ") to (" << _row << ", " << colNames[_col] << ") is a NON-move (the piece did not move). Abort Move." << std::endl;;
return false;
}
if(!isOnBoard(_row, _col))
{ // if the move is actually on the board
if (!silent) std::cout << "piece.moveTo() : " << colorName() << " " << ptype << " move from (" << row << ", " << colNames[col] << ") to (" << _row << ", " << colNames[_col] << ") is off the board. Abort Move." << std::endl;;
return false;
}
else if (!isLegalMoveTo(_row, _col))
{ // **** this will call the method from the inherited class, not the Piece class
if (!silent) std::cout << "piece.moveTo() : " << colorName() << " " << ptype << " move from (" << row << ", " << colNames[col] << ") to (" << _row << ", " << colNames[_col] << ") is not valid for the " << ptype <<". Abort Move." << std::endl;;
return false;
}
// make the move...
int origRow = row; // remember the original piece location in case the move leaves the current king in check
int origCol = col;
bool origCapture = false;
Piece* capturedPiece = nullptr; // a pointer to a piece we may land on, below
if (this->board->isOccupied(_row, _col))
{ // now check to see if we made a capture of a previously uncaptured piece
capturedPiece = this->board->pieceAt(_row, _col); // get the piece at this location
origCapture = capturedPiece->isCaptured; // record this so we can undo it below, if the king is still in check
capturedPiece->isCaptured = true; // indicate that the piece we landed on is captured
}
row=_row; // update the row location of this piece
col=_col; // update the col location of this piece
// Is my King in Check from this move?
if (board->isKingInCheck(this->isWhite, true))
{
/*
(true -> DO SILENT) If this move puts or leaves this piece's same-color king in check , then we cannot make it.
*/
if (!silent) std::cout << board->redTextStart << "piece.moveTo() : " << colorName() << " " << ptype << " move from (" << origRow << ", " << colNames[origCol] << ") to (" << _row << ", " << colNames[_col] << ") is not valid because it would put (or leave) its own King in check. Abort Move." << board->coloredTextEnd << std::endl;
row = origRow; // put this piece back to its original location
col = origCol;
if (capturedPiece != nullptr)
capturedPiece->isCaptured = origCapture; // return the captured piece to the chess board for continued play
return false;
}
// report the successful move
std::cout << "piece.moveTo() : " << colorName() << " " << ptype << " moves from (" << origRow << ", " << colNames[origCol] << ") to (" << _row << ", " << colNames[_col] << ")." << std::endl;
if (capturedPiece != nullptr && capturedPiece->isCaptured)
std::cout << board->yellowTextStart << "piece.moveTo() : " << colorName() << " " << ptype << " captures " << capturedPiece->colorName() << " " << capturedPiece->ptype << board->coloredTextEnd << std::endl;
neverMoved = false; // record that this piece has been moved from its original location
return true; // return true to indicate a successful move
}