Skip to content

Commit a92acc9

Browse files
committed
Fixed #27 - do not ask for promotion piece when promotion is illegal.
All user interfaces for human players had a flaw: if promotion was illegal because it would leave the mover in check, there was still a callback to the UI that asked what piece to promote to. Now we make sure promotion to queen is legal before even asking. All 4 promotion pieces are equally legal; there is no case where one is legal and the others aren't.
1 parent 0efcfd9 commit a92acc9

File tree

3 files changed

+39
-43
lines changed

3 files changed

+39
-43
lines changed

src/chess.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,7 @@ int ConvertSquareToNybble ( SQUARE );
325325

326326
#define SPECIAL_MOVE_MASK 0xF0
327327

328+
struct MoveList;
328329

329330
struct Move // A nice 32-bit structure!
330331
{
@@ -344,7 +345,7 @@ struct Move // A nice 32-bit structure!
344345
}
345346

346347
void Fix ( unsigned long openBookData, ChessBoard & );
347-
bool Fix ( const ChessBoard &, int Source, int Dest, SQUARE OptionalProm, ChessUI & );
348+
void Fix ( const ChessBoard &, const MoveList& LegalMoves, int Source, int Dest, SQUARE OptionalProm, ChessUI & );
348349

349350
bool ShouldIgnore() const
350351
{

src/human.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ bool HumanChessPlayer::GetMove (
6363
}
6464

6565
// This checks for pawn promotion and stuff like that.
66-
move.Fix ( board, source, dest, promIndex, userInterface );
66+
move.Fix(board, legalMoves, source, dest, promIndex, userInterface);
6767

6868
// Regenerate legal moves in case they edited the board.
6969
board.GenMoves(legalMoves);

src/misc.cpp

Lines changed: 36 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -310,8 +310,9 @@ SQUARE Move::actualOffsets (
310310
}
311311

312312

313-
bool Move::Fix (
313+
void Move::Fix (
314314
const ChessBoard &Board,
315+
const MoveList &LegalMoves,
315316
int Source,
316317
int Dest,
317318
SQUARE OptionalProm,
@@ -323,22 +324,25 @@ bool Move::Fix (
323324
{
324325
source = Source;
325326
dest = Dest;
326-
return true;
327+
return;
327328
}
328329

329330
// --- end of Suggest Move code.
330331

332+
source = 0;
333+
dest = 0;
334+
score = 0;
335+
331336
if ( Source<OFFSET(2,2) || Source>OFFSET(9,9) ||
332-
Dest<OFFSET(2,2) || Dest>OFFSET(9,9) ||
333-
Board.GetSquareContents(Source) == OFFBOARD ||
334-
Board.GetSquareContents(Dest) == OFFBOARD )
337+
Dest<OFFSET(2,2) || Dest>OFFSET(9,9) ||
338+
Board.GetSquareContents(Source) == OFFBOARD ||
339+
Board.GetSquareContents(Dest) == OFFBOARD )
335340
{
336-
return false;
341+
return;
337342
}
338343

339-
source = BYTE ( Source );
340-
dest = BYTE ( Dest );
341-
score = 0;
344+
source = BYTE(Source);
345+
dest = BYTE(Dest);
342346

343347
// Check for special moves...
344348

@@ -347,27 +351,23 @@ bool Move::Fix (
347351

348352
ChessSide side = Board.WhiteToMove() ? SIDE_WHITE : SIDE_BLACK;
349353

350-
SQUARE move_piece = Board.GetSquareContents ( Source );
354+
SQUARE move_piece = Board.GetSquareContents(Source);
351355
SQUARE prom;
352356
int moveVector = Dest - Source;
353357

354-
if ( Source == OFFSET(6,2) && Dest == OFFSET(8,2) &&
355-
(move_piece & WK_MASK) )
358+
if ( Source == OFFSET(6,2) && Dest == OFFSET(8,2) && (move_piece & WK_MASK) )
356359
{
357360
dest = SPECIAL_MOVE_KCASTLE;
358361
}
359-
else if ( Source == OFFSET(6,2) && Dest == OFFSET(4,2) &&
360-
(move_piece & WK_MASK) )
362+
else if ( Source == OFFSET(6,2) && Dest == OFFSET(4,2) && (move_piece & WK_MASK) )
361363
{
362364
dest = SPECIAL_MOVE_QCASTLE;
363365
}
364-
else if ( Source == OFFSET(6,9) && Dest == OFFSET(8,9) &&
365-
(move_piece & BK_MASK) )
366+
else if ( Source == OFFSET(6,9) && Dest == OFFSET(8,9) && (move_piece & BK_MASK) )
366367
{
367368
dest = SPECIAL_MOVE_KCASTLE;
368369
}
369-
else if ( Source == OFFSET(6,9) && Dest == OFFSET(4,9) &&
370-
(move_piece & BK_MASK) )
370+
else if ( Source == OFFSET(6,9) && Dest == OFFSET(4,9) && (move_piece & BK_MASK) )
371371
{
372372
dest = SPECIAL_MOVE_QCASTLE;
373373
}
@@ -389,23 +389,25 @@ bool Move::Fix (
389389
{
390390
if (OptionalProm == 0)
391391
{
392-
if ( (Board.GetSquareContents(Dest) & enemyMask) == 0 )
393-
{
394-
// We do this because we already know it's not legal.
395-
// This avoids a spurious call to the UI.
396-
prom = Q_INDEX;
397-
}
392+
// Avoid asking for promotion piece if promotion isn't even legal.
393+
// Try promotion to queen to see if that is legal.
394+
// If promoting to a queen is legal, then underpromoting is legal too.
395+
if (moveVector == pawn_dir + EAST)
396+
dest = SPECIAL_MOVE_PROMOTE_CAP_EAST | Q_INDEX;
398397
else
399-
{
400-
prom = Ui.PromotePawn ( Dest, side );
401-
}
398+
dest = SPECIAL_MOVE_PROMOTE_CAP_WEST | Q_INDEX;
399+
400+
if (LegalMoves.IsLegal(*this))
401+
prom = Ui.PromotePawn(Dest, side);
402+
else
403+
prom = Q_INDEX; // caller will also notice promotion is illegal
402404
}
403405
else
404406
{
405407
prom = OptionalProm;
406408
}
407409

408-
if ( moveVector == pawn_dir + EAST )
410+
if (moveVector == pawn_dir + EAST)
409411
dest = SPECIAL_MOVE_PROMOTE_CAP_EAST | prom;
410412
else
411413
dest = SPECIAL_MOVE_PROMOTE_CAP_WEST | prom;
@@ -420,29 +422,22 @@ bool Move::Fix (
420422
{
421423
if (OptionalProm == 0)
422424
{
423-
if ( Board.GetSquareContents(Dest) != EMPTY )
424-
{
425-
// We know this isn't a legal move already, because
426-
// there's something blocking the pawn promotion.
427-
// Go ahead and make the move an illegal queen promotion.
428-
// This avoids a spurious call to the UI to ask the
429-
// user what piece to promote it to.
430-
prom = Q_INDEX;
431-
}
425+
// Avoid asking for promotion piece if promotion isn't even legal.
426+
// If promoting to a queen is legal, then underpromoting is legal too.
427+
dest = SPECIAL_MOVE_PROMOTE_NORM | Q_INDEX;
428+
if (LegalMoves.IsLegal(*this))
429+
prom = Ui.PromotePawn(Dest, side);
432430
else
433-
prom = Ui.PromotePawn ( Dest, side );
431+
prom = Q_INDEX; // caller will also notice promotion is illegal
434432
}
435433
else
436434
{
437435
prom = OptionalProm;
438436
}
439-
440437
dest = SPECIAL_MOVE_PROMOTE_NORM | prom;
441438
}
442439
}
443440
}
444-
445-
return true;
446441
}
447442

448443

0 commit comments

Comments
 (0)