Bill Rogers wrote:Fred your opening statement about chess pieces not caring about where they have been is not entire true. Pawns always must know where they have been as they can not move backwards and a king at times must also remember where he has been as in the case where he moved out of check? If this seems like nit-picking, then I applogise it was only meant it the to point out a small but missed fact.
Bill
Not at all Bill, I appreciate your comment and while I agree in chess terms, I have not stored this information with a piece object. Not saying my way is better or anything, but in my program a piece doesn't really move or keep track of itself, if that's what you are implying. Therefore objectification is not a must. The program only knows that a character 'P' occupies a certain array cell. And because it is an upper case P, it will not attempt to transfer the character to an array cell with a larger row index.
See what I mean about it doesn't matter where the pawn has been? Likewise for en passant, There is a variable called epTarget which contains the co-ordinate of the enpassant target square. So en-passant is a property of the position, not the pawn.
like wise with castling priveleges. The king does not remember that it has moved. As soon as a character 'K', or 'R', is shifted within the array, , a game variable of type boolean is set to say that White can no longer castle.
mathmoi wrote:
In my current engine I did something just inbetween theses two extrem. I have a class CPiece wich is just a wrapper around a unsigned int. Using operator overloading it can be use as an integer.
That's very cool. We ended up using just an enum for piece types, but a separate ChessPiece class would definitely make some things simpler.
mathmoi wrote:
In my current engine I did something just inbetween theses two extrem. I have a class CPiece wich is just a wrapper around a unsigned int. Using operator overloading it can be use as an integer.
That's very cool. We ended up using just an enum for piece types, but a separate ChessPiece class would definitely make some things simpler.
I am very interested. What sort of things get simpler, please describe in chessic terms, not just pure algorithmic terms. Thank You.
mathmoi wrote:
In my current engine I did something just inbetween theses two extrem. I have a class CPiece wich is just a wrapper around a unsigned int. Using operator overloading it can be use as an integer.
That's very cool. We ended up using just an enum for piece types, but a separate ChessPiece class would definitely make some things simpler.
I am very interested. What sort of things get simpler, please describe in chessic terms, not just pure algorithmic terms. Thank You.
It's nothing that couldn't be done procedurally, but having a ChessPiece class means that you can group all the relevant function in the same class. Instead of this:
Note the constructors which will implicitly convert integers and characters into ChessPiece objects. So you can still do "ChessPiece piece = integer_piece_code" as if ChessPiece was an integer.
Aleks Peshkov wrote:Objects in OOP not necessary correlate with real world objects.
Yes, you surely could do that. But the first rule in design is to "model the real world". That is the 'ideal' case. Designers of course have all the freedom to deviate from that.
Straustroop in an interview told that the reason to organize a new class is to keep invariant inside.
What invariant holds mentioned ChessPiece? Not much, except keeping a numeric variable in a small range. While it is a good style to declare such basic types, such trivial basic types will not make your program OO. It still decorated plain C.
Example of useful invariant: an object of Position class is always valid and complete representation of a chess position.
Aleks Peshkov wrote:Straustroop in an interview told that the reason to organize a new class is to keep invariant inside.
What invariant holds mentioned ChessPiece? Not much, except keeping a numeric variable in a small range. While it is a good style to declare such basic types, such trivial basic types will not make your program OO. It still decorated plain C.
Example of useful invariant: an object of Position class is always valid and complete representation of a chess position.
If you design a chess program based on "piece list", the piece definition could be something like this:
class CPiece
{
public:
bool IsPinned(); // whether or not the piece is pinned
GetMovesSquares(CSquareList &list); // the list of squares that the piece can move to
CPieceType GetPieceType(); // returns P,N,B,R,Q,K
CPieceColor GetPieceColor(); // return B or W
CBoardFile GetBoardFile(); // return the board file where the piece is
CBoardRank GetBoardRank(); // return the board rank where the piece is
bool IsHanging(); // whether or not the piece can be captured by the opponent without a recapture response
ETC, ETC...
}
class CBoard
{
private:
List<CPiece> PieceList;
public:
GetPieceList (List<CPiece> &PieceList);
MovePiece (CPiece &Piece, CBoardFile file, CBoardRank rank); // move this piece, update it, and update all affected pieces
ETC, ETC...
}
Note that those are the actual things that a human player sees about a chess piece on a physical chess board.
I have a piece list type of data structure, but It's not really about objects. Give the particular design of my java program, it seems to work well.
my position array is a simple char[][]. As I think I mentioned early, my program really isn't piece centric.
My pieces are really just characters uppercase for white and lower case for black. corresponding to the piece characters in a fen string.
I have two arrays of strings, call them wp and bp for white pieces and black pieces. One array element for each piece as the game progresses. The actual layout of each element is as follows...
position 0 is the piece itself i.e. K, k, P, p, etc.
position 1 is the row co-ordinate of the array cell where the piece resides.
position 2 is the col co-ordinate of the array cell
the rest of the string consists of digit pairs which are the array co-ordinates of all possible destination squares the piece can move to on an empty board. I have programmatically created large static arrays so that these destination strings don't have to be re-calculated all the time. I have a pretty good method for initializing and keeping this stuff up to date.
For convenience, the king is always the first element in each array.
Anyways, the purpose of this arrangement is to narrow down the selection of possible moves to be evaluated for legality. My move checker for the most part just needs to consider whetehr there are any pieces in the way of the source square and the potential destination square.
anyways, it's a first effort. I'm sure there will be changes in the future.
mathmoi wrote:
In my current engine I did something just inbetween theses two extrem. I have a class CPiece wich is just a wrapper around a unsigned int. Using operator overloading it can be use as an integer.
That's very cool. We ended up using just an enum for piece types, but a separate ChessPiece class would definitely make some things simpler.
I have started to avoid OOP when it is simple name mangling like in this case, there is even not inheritance here, just plain simple syntactic sugar.
I prefer structs + functions C style because it allows a better splitting of interface (header file) from implementation (.cpp) instead in class definition, tipically in the header, you need to put also the "private" parts.
It even does not allow a better speed but you can get the same speed of splitted struct + functions with the added burden that it is easier, if you don't know very well how compiler transaltes your code, to fall in some hidden copy or pointer indirection trap that hurts performances.
IMHO OOP is good for inheritance and polymorphism, although the latter only for non performance crtical parts.
Marco that is music to my ears. I agree what you say about OOP. It gets held up as the holy grail of all computer programming, but I really think it gets overdone, and used when it really isn't necessary. Not saying it applies to all pieces situations, but in a lot of cases I really think things get "over-ooped".