A move, i.e., an object of class MOVE stores several facts. First of all there are the from and the to position which are objects of class POS. The move knows about it being a castle move. Castle moves have from and to positions that refer to the movement of the king.
During the process of analyzing a move, further information is gathered and stored in the move object. This information is necessary to later on un-do a move. The attribute piece stores a pointer to the piece that is moved by a move. If the move kills an opponent piece, that piece can be reached by the attribute kills. The fact whether the kings have moved belongs to the status of the board. A move of a king might change that status. To preserve the fact that a particular move has changed that status, the king_chg flag has been introduced. Another flag for un-doing moves is pawn_chg. If a pawn reaches the base line of the opponent, the pawn can be exchanged to a knight or a queen. The pawn_chg flag indicates such an exchange. Although a board knows about the last move, the previous move is kept in the move object.
class MOVE is attr from, to : POS; attr isk_castle : BOOL; attr isq_castle : BOOL; attr isquit : BOOL; attr piece : $PIECE; attr kills : $PIECE; attr king_chg : BOOL; attr pawn_chg : BOOL; attr prev_move : MOVE;
The MOVE class offers two create routines and is thus a good example of overloading. The first version of the create routine, accepts a move in standard chess notation, e.g. ``a2-a3". For this version of create it does not matter, whether the board actually has a piece on the from position since this is checked later on. In contrast to the first version of the create routine, the second version deals with an existing $PIECE object. Since a piece has an actual position, only the destination position is required as parameter.
This code of the create routine is written rather fail safe. The given string is checked for conforming syntax. If there is an error, the from and to position of the move object remain void.
The first branch of the if-elsif cascade handles the q-castle (lines 21-28). The second branch handles the k-castle (lines 29-36) Then the ``quit" case is considered. The fourth case (lines 39-47) and fifth case (lines 48-57) both deal with ordinary moves: They check for syntax ``<p1>-<p2>" and test whether p1 and p2 refer to existing positions of the board. The string class offers a substring routine which has two parameters. It is used for example in line 40. The first argument refers to the starting position of the substring, the second argument specifies the number of characters to be returned. The difference between the fourth and the fifth case is that in the latter the the separating ``-" can be omitted so that ``<p1><p2>" is accepted.
create(move:STR, white_to_move:BOOL):SAME is ret ::= new; ret.isk_castle := false; ret.isq_castle := false; ret.isquit := false; ret.piece := void; ret.kills := void; ret.king_chg := false; ret.pawn_chg := false; if void(move) then return ret; end; if move.size >= 5 and move.head(5) = "o-o-o" then ret.from := #POS; ret.to := #POS; ret.isq_castle := true; if white_to_move then ret.from.pos := "e1"; ret.to.pos := "c1"; else ret.from.pos := "e8"; ret.to.pos := "c8"; end; elsif move.size >= 3 and move.head(3) = "o-o" then ret.from := #POS; ret.to := #POS; ret.isk_castle := true; if white_to_move then ret.from.pos := "e1"; ret.to.pos := "g1"; else ret.from.pos := "e8"; ret.to.pos := "g8"; end; elsif move.size >= 4 and move.head(4) = "quit" then ret.isquit := true; elsif move.size >= 5 then str_from ::= move.substring(0,2); if POS::check_pos(str_from) then ret.from := #POS; ret.from.pos := str_from; end; str_to ::= move.substring(3,2); if POS::check_pos(str_to) then ret.to := #POS; ret.to.pos := str_to; end; elsif move.size >=4 then str_from ::= move.substring(0,2); if POS::check_pos(str_from) then ret.from := #POS; ret.from.pos := str_from; end; str_to ::= move.substring(2,2); if POS::check_pos(str_to) then ret.to := #POS; ret.to.pos := str_to; end; end; return ret; end; -- of first version of create
The routine create is overloaded in class MOVE, i.e., there are two routines called create that are distinguished by their list of formal parameters and/or return parameter. Whereas the create routine given above expects a string and a boolean value as parameters, the second create routine expects a piece and a (target) position.
create(piece:$PIECE, to:POS):SAME is ret ::= new; ret.isk_castle := false; ret.isq_castle := false; ret.isquit := false; ret.from := #POS; ret.from.pos := piece.position.str; ret.to := #POS; ret.to.pos := to.str; ret.piece := void; ret.kills := void; ret.king_chg := false; ret.pawn_chg := false; if piece.isking then if piece.iswhite then if piece.position = "e1" and to = "c1" then ret.isq_castle := true; end; if piece.position = "e1" and to = "g1" then ret.isk_castle := true; end; else if piece.position = "e8" and to = "c8" then ret.isq_castle := true; end; if piece.position = "e8" and to = "g8" then ret.isk_castle := true; end; end; end; return ret; end; -- of second version of create isok:BOOL is return ~void(from) and ~void(to); end; end; -- of class MOVE