3 Copyright (c) Scott Gasch
17 $Id: testmove.c 345 2007-12-02 22:56:42Z scott $
26 _TestPickRandomPieceLocation(POSITION *pos)
31 Test code: supports TestLiftPlaceSlidePiece. Picks a random square
32 where there is a piece on board.
44 ULONG u = RANDOM_COLOR;
49 if ((TRUE == v) && (pos->uPawnCount[u]))
51 w = rand() % pos->uPawnCount[u];
52 c = pos->cPawns[u][w];
56 ASSERT(pos->uNonPawnCount[u][0]);
57 w = rand() % pos->uNonPawnCount[u][0];
58 c = pos->cNonPawns[u][w];
60 ASSERT(IS_ON_BOARD(c));
66 TestLiftPlaceSlidePiece(void)
71 Test code. Tests LiftPiece, PlacePiece and SlidePiece.
83 #define NUM_LOOPS 1000000
89 UINT64 u64Start = SystemReadTimeStampCounter();
92 Trace("Testing Lift/Place/Slide Piece... ");
93 if (FALSE == FenToPosition(&pos,
94 "RNBKQBNR/PPPPPPPP/8/8/8/8/pppppppp/rnbkqbnr"
97 UtilPanic(TESTCASE_FAILURE,
98 NULL, NULL, NULL, NULL,
102 memset(p, 0, sizeof(p));
107 case 0: // slide piece
108 cFrom = _TestPickRandomPieceLocation(&pos);
113 while(!IS_EMPTY(pos.rgSquare[cTo].pPiece));
116 // Make sure bishops slide to their color or else
117 // pos->uWhiteSqBishopCount gets messed up.
119 if (IS_BISHOP(pos.rgSquare[cFrom].pPiece))
121 while ((IS_WHITE_SQUARE_COOR(cTo) !=
122 IS_WHITE_SQUARE_COOR(cFrom)) ||
123 (!IS_EMPTY(pos.rgSquare[cTo].pPiece)))
130 // Note: a speedup in move.c caused a divorce between
131 // SlidePiece and SlidePawn and caused the necessity
134 if (IS_PAWN(pos.rgSquare[cFrom].pPiece))
136 SlidePawn(&pos, cFrom, cTo);
140 SlidePiece(&pos, cFrom, cTo);
149 cFrom = _TestPickRandomPieceLocation(&pos);
151 while(IS_KING(pos.rgSquare[cFrom].pPiece));
152 p[u] = LiftPiece(&pos, cFrom);
157 case 2: // PlacePiece
165 while(!IS_EMPTY(pos.rgSquare[cTo].pPiece));
166 PlacePiece(&pos, cTo, p[u]);
172 while(v < NUM_LOOPS);
173 u64End = SystemReadTimeStampCounter();
176 printf(" L/P/S bench: %" COMPILER_LONGLONG_UNSIGNED_FORMAT
178 (u64End - u64Start) / (UINT64)NUM_LOOPS);
183 TestExposesCheck(void)
188 Test code. Tests ExposesCheck.
200 typedef struct _TEST_EXPOSES_CHECK
211 TEST_EXPOSES_CHECK x[] =
213 { "k2r4/8/8/3p4/8/8/3K4/8 w - - 0 1",
215 { "k2q4/8/8/3p4/8/8/3K4/8 w - - 0 1",
217 { "k5b1/8/8/3p4/8/1K6/8/8 w - - 0 1",
219 { "k5q1/8/8/3p4/8/1K6/8/8 w - - 0 1",
221 { "k7/8/8/1K1p2r1/8/8/8/8 w - - 0 1",
223 { "k7/8/8/1K1p2q1/8/8/8/8 w - - 0 1",
225 { "k7/8/2K5/3p4/8/8/6b1/8 w - - 0 1",
227 { "k7/8/2K5/3p4/8/8/6q1/8 w - - 0 1",
229 { "k7/3K4/8/3p4/8/8/3r4/8 w - - 0 1",
231 { "k7/3K4/8/3p4/8/8/3q4/8 w - - 0 1",
233 { "k7/5K2/8/3p4/2b5/8/8/8 w - - 0 1",
235 { "k7/5K2/8/3p4/2q5/8/8/8 w - - 0 1",
237 { "k7/8/8/1r1pK3/8/8/8/8 w - - 0 1",
239 { "k7/8/8/1q1pK3/8/8/8/8 w - - 0 1",
241 { "k7/8/2b5/3p4/8/5K2/8/8 w - - 0 1",
243 { "k7/8/2q5/3p4/8/5K2/8/8 w - - 0 1",
246 { "8/5k2/8/3N4/8/1B6/8/6K1 w - - 0 1",
248 { "8/5k2/8/3N4/8/1Q6/8/6K1 w - - 0 1",
250 { "3k4/8/8/3N4/8/8/8/3R2K1 w - - 0 1",
252 { "8/3k4/8/3N4/8/8/8/3Q2K1 w - - 0 1",
254 { "8/8/8/Q2Nk3/8/8/8/6K1 w - - 0 1",
256 { "8/8/8/R2Nk3/8/8/8/6K1 w - - 0 1",
258 { "8/1Q6/8/3N4/8/5k2/8/6K1 w - - 0 1",
260 { "8/1B6/8/3N4/8/5k2/8/6K1 w - - 0 1",
262 { "8/3R4/8/3N4/8/3k4/8/6K1 w - - 0 1",
264 { "8/3Q4/8/3N4/8/3k4/8/6K1 w - - 0 1",
266 { "6Q1/8/8/3N4/8/8/k7/6K1 w - - 0 1",
268 { "6B1/8/8/3N4/8/8/k7/6K1 w - - 0 1",
270 { "8/8/8/k2N1R2/8/8/8/6K1 w - - 0 1",
272 { "8/8/8/k2N1Q2/8/8/8/6K1 w - - 0 1",
274 { "8/1k6/8/3N4/8/5Q2/8/6K1 w - - 0 1",
276 { "8/1k6/8/3N4/8/5B2/8/6K1 w - - 0 1",
278 { "8/5k2/4p3/3N4/8/1Q6/8/6K1 w - - 0 1",
280 { "8/5k2/4p3/3N4/8/1B6/8/6K1 w - - 0 1",
282 { "8/8/8/1Q1Np1k1/8/8/8/6K1 w - - 0 1",
284 { "8/8/8/1R1Np1k1/8/8/8/6K1 w - - 0 1",
286 { "8/1B6/8/3N4/4p3/5k2/8/6K1 w - - 0 1",
288 { "8/1Q6/8/3N4/4p3/5k2/8/6K1 w - - 0 1",
290 { "8/3R4/8/3N4/3p4/3k4/8/6K1 w - - 0 1",
292 { "8/3Q4/8/3N4/3p4/3k4/8/6K1 w - - 0 1",
294 { "8/5B2/8/3N4/2p5/1k6/8/6K1 w - - 0 1",
296 { "8/5Q2/8/3N4/2p5/1k6/8/6K1 w - - 0 1",
298 { "8/8/8/1krN1R2/8/8/8/6K1 w - - 0 1",
300 { "8/8/8/1krN1Q2/8/8/8/6K1 w - - 0 1",
302 { "8/1k6/2r5/3N4/8/5Q2/8/6K1 w - - 0 1",
306 Trace("Testing ExposesCheck...\n");
311 if (FALSE == FenToPosition(&pos, x[u].szFen))
313 Bug("TestExposesCheck: FEN reader choked on a good FEN.\n");
316 if (x[u].cFrom != ExposesCheck(&pos, x[u].cRemove, x[u].cTo))
318 Bug("TestExposesCheck: ExposesCheck is broken on position %u!\n",
332 Test code. Tests IsAttacked (and InCheck).
344 typedef struct _TEST_IS_ATTACKED
355 TEST_IS_ATTACKED x[] =
357 { "7k/4n3/3P4/3K4/8/8/8/8 w - - 0 1",
359 { "7k/8/3Pp3/3K4/8/8/8/8 w - - 0 1",
361 { "7k/8/2pP4/3K4/8/8/8/8 w - - 0 1",
363 { "7k/2n5/3P4/3K4/8/8/8/8 w - - 0 1",
365 { "7k/8/1n1P4/3K4/8/8/8/8 w - - 0 1",
367 { "7k/8/3P1n2/3K4/8/8/8/8 w - - 0 1",
369 { "6bk/8/3P4/3K4/8/8/8/8 w - - 0 1",
371 { "6qk/8/3P4/3K4/8/8/8/8 w - - 0 1",
373 { "6bk/8/3PN3/3K4/8/8/8/8 w - - 0 1",
375 { "6bk/8/3Pr3/3K4/8/8/8/8 w - - 0 1",
377 { "7k/8/3P4/3K3q/8/8/8/8 w - - 0 1",
379 { "7k/8/3P4/3K3r/8/8/8/8 w - - 0 1",
381 { "7k/8/3P4/3KQ2q/8/8/8/8 w - - 0 1",
383 { "7k/8/3P4/3K4/8/8/8/7b w - - 0 1",
385 { "7k/8/3P4/3K4/8/8/8/7q w - - 0 1",
387 { "7k/8/3P4/3K4/8/3r4/3q4/3r4 w - - 0 1",
389 { "7k/8/3P4/3K4/3P4/3r4/3q4/3r4 w - - 0 1",
391 { "7k/8/3P4/3K4/3p4/3r4/3q4/3r4 w - - 0 1",
393 { "7k/8/3P4/3K4/3p4/3rn3/3q4/3r4 w - - 0 1",
395 { "7k/8/3P4/3K4/2b5/1b6/b7/8 w - - 0 1",
397 { "7k/8/3P4/3K4/2r5/1b6/b7/8 w - - 0 1",
399 { "K7/8/8/3k4/3p1N2/8/8/8 w - - 0 1",
401 { "K7/8/8/3k4/3p4/4N3/8/8 w - - 0 1",
403 { "K7/8/8/3k4/3p4/2N5/8/8 w - - 0 1",
405 { "K7/8/8/3k4/1N1p4/8/8/8 w - - 0 1",
407 { "K7/8/8/3k4/2Pp4/8/8/8 w - - 0 1",
409 { "K7/8/8/3k4/3pP3/8/8/8 w - - 0 1",
411 { "K5Q1/5B2/8/3k4/3p4/8/8/8 w - - 0 1",
413 { "K5Q1/5B2/4R3/3k4/3p4/8/8/8 w - - 0 1",
415 { "K5Q1/8/8/3k4/3p4/8/8/8 w - - 0 1",
417 { "K2R4/8/8/3k4/3p4/8/8/8 w - - 0 1",
419 { "K2R4/3Q4/8/3k4/3p4/8/8/8 w - - 0 1",
421 { "K2R4/3Q4/3p4/3k4/3p4/8/8/8 w - - 0 1",
423 { "K2R4/3Q4/3p1N2/3k4/3p4/8/8/8 w - - 0 1",
425 { "K7/1B6/8/3k4/3p4/8/8/8 w - - 0 1",
427 { "K7/8/8/Q2k4/3p4/8/8/8 w - - 0 1",
429 { "K7/8/8/3k4/3p4/8/B7/8 w - - 0 1",
433 Trace("Testing IsAttacked...\n");
438 if (FALSE == FenToPosition(&pos, x[u].szFen))
440 Bug("TestIsAttacked: FEN reader choked on a good FEN.\n");
443 if (x[u].fAnswer != IsAttacked(x[u].cSquare, &pos, x[u].uSide))
445 Bug("TestIsAttacked: ExposesCheck is broken on position %u!\n",
454 TestMakeUnmakeMove(void)
456 typedef struct _TEST_MAKE_MOVE
466 SEARCHER_THREAD_CONTEXT *ctx;
468 POSITION *pos = NULL;
473 "8/8/8/2k5/4p3/8/2KP4/8 w - - 0 1",
475 { MAKE_MOVE(D2, D4, WHITE_PAWN, 0, 0, MOVE_FLAG_SPECIAL) },
476 { MAKE_MOVE(E4, D3, BLACK_PAWN, WHITE_PAWN, 0, MOVE_FLAG_SPECIAL | MOVE_FLAG_CHECKING | MOVE_FLAG_ESCAPING_CHECK)},
477 { MAKE_MOVE(C2, D3, WHITE_KING, BLACK_PAWN, 0, MOVE_FLAG_ESCAPING_CHECK) },
478 { MAKE_MOVE(0, 0, 0, 0, 0, 0) }
483 "5r1k/3KP3/8/8/8/8/8/8 w - - 0 1",
485 { MAKE_MOVE(E7, F8, WHITE_PAWN, BLACK_ROOK, WHITE_QUEEN, MOVE_FLAG_SPECIAL | MOVE_FLAG_CHECKING) },
486 { MAKE_MOVE(H8, G8, BLACK_KING, 0, 0, MOVE_FLAG_ESCAPING_CHECK) },
487 { MAKE_MOVE(H8, H7, BLACK_KING, 0, 0, MOVE_FLAG_ESCAPING_CHECK) },
488 { MAKE_MOVE(0, 0, 0, 0, 0, 0) }
490 { TRUE, FALSE, TRUE }
493 "8/8/4K3/8/k2p3R/8/4P3/8 w - - 0 1",
495 { MAKE_MOVE(E2, E4, WHITE_PAWN, 0, 0, MOVE_FLAG_SPECIAL) },
496 { MAKE_MOVE(D4, E3, BLACK_PAWN, WHITE_PAWN, 0, MOVE_FLAG_SPECIAL) },
497 { MAKE_MOVE(D4, D3, BLACK_PAWN, 0, 0, 0) },
498 { MAKE_MOVE(E4, E5, WHITE_PAWN, 0, 0, MOVE_FLAG_CHECKING) },
499 { MAKE_MOVE(D3, D2, BLACK_PAWN, 0, 0, MOVE_FLAG_ESCAPING_CHECK) },
500 { MAKE_MOVE(A4, B4, BLACK_KING, 0, 0, MOVE_FLAG_ESCAPING_CHECK) },
501 { MAKE_MOVE(A4, A3, BLACK_KING, 0, 0, MOVE_FLAG_ESCAPING_CHECK) },
502 { MAKE_MOVE(0, 0, 0, 0, 0, 0) }
504 { TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE }
507 "3k4/8/6r1/8/8/8/8/R3K2R w KQ - 0 1",
509 { MAKE_MOVE(E1, G1, WHITE_KING, 0, 0, MOVE_FLAG_SPECIAL) },
510 { MAKE_MOVE(H1, H2, WHITE_ROOK, 0, 0, 0) },
511 { MAKE_MOVE(G6, D6, BLACK_ROOK, 0, 0, 0) },
512 { MAKE_MOVE(E1, C1, WHITE_KING, 0, 0, MOVE_FLAG_SPECIAL) },
513 { MAKE_MOVE(H2, H1, WHITE_ROOK, 0, 0, 0) },
514 { MAKE_MOVE(D6, A6, BLACK_ROOK, 0, 0, 0) },
515 { MAKE_MOVE(E1, G1, WHITE_KING, 0, 0, MOVE_FLAG_SPECIAL) },
516 { MAKE_MOVE(E1, C1, WHITE_KING, 0, 0, MOVE_FLAG_SPECIAL | MOVE_FLAG_CHECKING) },
517 { MAKE_MOVE(A6, D6, BLACK_ROOK, 0, 0, MOVE_FLAG_ESCAPING_CHECK) },
518 { MAKE_MOVE(0, 0, 0, 0, 0, 0) }
520 { FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE }
527 ctx = SystemAllocateMemory(sizeof(SEARCHER_THREAD_CONTEXT));
529 pos = SystemAllocateMemory(sizeof(POSITION) * 10);
532 for (u = 0; u < ARRAY_LENGTH(x); u++)
534 if (FALSE == FenToPosition(&p, x[u].szFen))
536 UtilPanic(INCONSISTENT_STATE,
537 NULL, NULL, NULL, NULL,
540 InitializeSearcherContext(&p, ctx);
542 for (v = 0; v < ARRAY_LENGTH(x[u].mv); v++)
544 if (x[u].mv[v].uMove == 0) break;
545 memcpy(&(pos[v]), &(ctx->sPosition), sizeof(POSITION));
547 fOk = MakeUserMove(ctx, x[u].mv[v]);
548 if (fOk != x[u].ok[v])
550 UtilPanic(TESTCASE_FAILURE,
551 NULL, "MakeUserMove", NULL, NULL,
556 UnmakeMove(ctx, x[u].mv[v]);
557 if (FALSE == PositionsAreEquivalent(&(ctx->sPosition),
560 UtilPanic(TESTCASE_FAILURE,
561 NULL, "MakeMove / UnmakeMove", NULL, NULL,
564 fOk = MakeUserMove(ctx, x[u].mv[v]);
569 SystemFreeMemory(ctx);
570 SystemFreeMemory(pos);