[ List Earliest Comments Only For Pages | Games | Rated Pages | Rated Games | Subjects of Discussion ]
Check out Janggi (Korean Chess), our featured variant for December, 2024.
Check out Janggi (Korean Chess), our featured variant for December, 2024.
Move legality testing will be based on a move generator. This generates the pseuo-legal moves that are possible in the given position, always being fully aware of any side effects these moves might have. These moves are then compared to the input move, and if there is a match we know the input move was pseuo-legal. Normally we consider a move a match only if all the parameters ori, desti, promo, suicide, freedrop and dropped of the input move are equal to their counterparts orisqr, destsqr, locustsqr, dropsqr and unload of the generated move. But for moves with implied side effects we only match ori, desti and promo (the latter should be 0), and accept what the move generator specifies as side effects. E.g. for castling the locustsqr would be at the Rook to make it disappear, and the dropsqr would indicate where we must drop a Rook to make it reappear.
To make this process efficient, we generate only moves of the piece that according to the input is going to move. For moves that were already tested for legality before (now played for setting up the current position) we even take a short-cut on that: we only generate the moves with implied side effects, to calculate and perform those. The subroutine GenMoves will thus have three parameters: the piece type and start location from which its moves should be generated, and a Boolean that indicates whether we want all moves of the piece, or just those with implied side effects. In the latter case most pieces would of course have no moves at all; in orthodox Chess only the KIng (castling) and Pawns (e.p.) have moves with side efects.
The move descriptions come from the table legdefs, and where in this table the description of the given piece type starts is given by a function with the name of the piece type. This function has an additional argument, indicating whether we want all moves or just those with implied side effects. The latter will be found behind the former in the legdefs table, so that we can just start later in the table to get only those. Each move description will start with a number indicating how many legs the move has (where each leg is a leap or a ride). Each leg is then described by 4 numbers: range, sideway and vertical step, and mode. We call the subroutine NextLeg to interpret these. To get to the next move of a piece the table index then has to be incremented by 1 plus 4 times the number of legs. A dummy move with 0 legs indicates we are done with this piece, and ends the loop by terminating the subroutine though verify. A global variable hit can cause the loop to terminate early; there is usually no need to go on generating moves after we found the one we were looking for.
The routine NextLeg does the real work. It calls itself recursively in case there is more than one leg, to do the follow-up legs. Its first parameter controls the depth of this recursion, the next specifies where in legdefs to find the four numbers that describe the leg. Then follow a number of squares: the start square of the move, and the start square of the leg (which for the first leg are of course the same), then the squares for the side effects (starting at the default 0) locustsqr and dropsqr. Finally there is a parameter with which we can request an exact length of a ride when it is non-zero.
We will not go into the details of NextLeg now. When it succeeds in constructing the move according to the description in legdefs, it will eventually call a routine GotMove, passing it the parameters that describe the move and all its side effects. Because we will want to use the move generator for various purposes (e.g. testing whether a given move is pseuo-legal, regeneration of implied side effects, testing whether we can capture a royal piece, making a table of legal moves...), a global variable task will specify what this routine must do. For now we will only have 'task 1', regeneration of the implied side effects.
The move generator always specifies the side effects, and whether these are implied. If they are explicit, they will be automatically applied by Game Courier's execution of the input move. If they were implied, we perform any locust capture, and remember whether we should drop a piece somewhere, so we can do that later.
Why not immediately do all implied side efects? Well, we cannot always make the freedrop of a castling Rook before Game Courier has made the input move, as in some castlings the Rook then would clobber the King. So we must apply the freedrop after feeding the move to Game Courier.
Note that this code doesn't worry about promotions yet.