static void TestStoreLeaf() { { // first we test an unsolved leaf node CBook book; CHeightInfoX hix(2, 4, false, 60); CQPosition pos("---------------------------O*------*O---------------------------", true); const CValue value=32; book.StoreLeaf(pos.BitBoard(), hix, value); TEST(book.Size()==1); TestULeafPos(book, pos, value, hix); } { // now a solved leaf node CBook book; CQPosition pos("OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO*OOOOOO-----------------", true); const CValue value=64*kStoneValue; CHeightInfoX hix(pos.NEmpty()-hSolverStart, 0, false, pos.NEmpty()); book.StoreLeaf(pos.BitBoard(), hix, value); TEST(book.Size()==1); const CBookData* bd=book.FindData(pos.BitBoard()); TEST(bd!=NULL); TEST(bd->IsLeaf()); TEST(bd->IsProven()); TEST(!bd->IsUleaf()); TEST(!bd->IsBranch()); TEST(bd->Hi()==hix); TEST(bd->Values().vMover==value-book.Boni().whiteBonus); TEST(bd->Values().vOpponent==value-book.Boni().whiteBonus); TEST(bd->Values().vHeuristic==value); } { // now a position with too few empties to go in book CBook book; CQPosition pos("OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO*OOOOOOOOOOOOOOOOOOOOOO-", true); const CValue value=64*kStoneValue; CHeightInfoX hix(pos.NEmpty(), 0, false, pos.NEmpty()); book.StoreLeaf(pos.BitBoard(), hix, value); TEST(book.Size()==0); } }
static void TestStoreRoot() { { CBook book; CHeightInfoX hix(2, 4, false, 60); CQPosition pos("---------------------------O*------*O---------------------------", true); const CValue value=32; const CValue cutoff=-100; book.StoreRoot(pos.BitBoard(), hix, value, cutoff); TEST(book.Size()==1); const CBookData* bd=book.FindData(pos.BitBoard()); TEST(bd!=NULL); TEST(bd->IsBranch()); TEST(!bd->IsUleaf()); TEST(!bd->IsLeaf()); TEST(!bd->IsProven()); TEST(bd->Hi()==hix); // don't test values as they won't be assigned. } { // now a solved root node CBook book; CQPosition pos("OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO*OOOOOO-----------------", true); const CValue value=-64*kStoneValue; CHeightInfoX hix(pos.NEmpty()-hSolverStart, 0, false, pos.NEmpty()); book.StoreRoot(pos.BitBoard(), hix, value, -100); TEST(book.Size()==1); const CBookData* bd=book.FindData(pos.BitBoard()); TEST(bd!=NULL); TEST(bd->IsLeaf()); TEST(bd->IsProven()); TEST(!bd->IsUleaf()); TEST(!bd->IsBranch()); TEST(bd->Hi()==hix); TEST(bd->Values().vMover==value+book.Boni().whiteBonus); TEST(bd->Values().vOpponent==value+book.Boni().whiteBonus); TEST(bd->Values().vHeuristic==value); } }
void calculate_lcs(it xo, it xlo, it xhi, it ylo, it yhi, members & xs_in_lcs) { unsigned const nx = distance(xlo, xhi); if (nx == 0) { // empty range. all done } else if (nx == 1) { // single item in x range. // If it's in the yrange, mark its position in the LCS xs_in_lcs[distance(xo, xlo)] = find(ylo, yhi, *xlo) != yhi; } else { // split the xrange it xmid = xlo + nx / 2; // Find LCS lengths at xmid, working from both ends of the range lengths ll_b, ll_e; std::reverse_iterator<it> hix(xhi), midx(xmid), hiy(yhi), loy(ylo); lcs_lens(xlo, xmid, ylo, yhi, ll_b); lcs_lens(hix, midx, hiy, loy, ll_e); // Find the optimal place to split the y range lengths::const_reverse_iterator e = ll_e.rbegin(); int lmax = -1; it y = ylo, ymid = ylo; for (lengths::const_iterator b = ll_b.begin(); b != ll_b.end(); ++y, ++b, ++e) { if (*b + *e > lmax) { lmax = *b + *e; ymid = y; } } // Split the range and recurse calculate_lcs(xo, xlo, xmid, ylo, ymid, xs_in_lcs); calculate_lcs(xo, xmid, xhi, ymid, yhi, xs_in_lcs); } }
//! Test CBook::StoreSubposition(). //! While we're at it, test negamaxing as well, so store the parent position //! as a branch node and see if it's assigned the right value. static void TestStoreSubposition() { { // test StoreSubposition() when there is no pass after the move. CBook book; CQPosition pos; pos.Initialize(); const CMoveValue mv(F5, 41); CHeightInfoX hix(2, 4, false, pos.NEmpty()); // store subpos in book book.StoreSubposition(pos, mv, hix); TEST(book.Size()==1); // test that subpos went in correctly CQPosition posSub(pos); posSub.MakeMove(mv.move); CHeightInfoX hixSub(1, 4, false, posSub.NEmpty()-1); TestULeafPos(book, posSub, -mv.value, hixSub); // test that pos is valued correctly when we negamax book.StoreRoot(pos.BitBoard(), hix, mv.value, -100); book.NegamaxAll(); const CBookData* pbd=book.FindData(pos.BitBoard()); TEST(pbd!=NULL); TEST(pbd->Values().vHeuristic==mv.value); } { // test StoreSubposition() when there is a pass after the move. CBook book; CQPosition pos("OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO*******-----------------", false); CMoveValue mv(A7, 64*kStoneValue); CHeightInfoX hix(2, 4, false, pos.NEmpty()); // store subpos in book book.StoreSubposition(pos, mv, hix); TEST(book.Size()==1); // test that subpos went in correctly CQPosition posSub(pos); posSub.MakeMoveAndPass(mv.move); CHeightInfoX hixSub(1, 4, false, posSub.NEmpty()-1); TestULeafPos(book, posSub, mv.value, hixSub); // test that pos is valued correctly when we negamax book.StoreRoot(pos.BitBoard(), hix, mv.value, -100); book.NegamaxAll(); const CBookData* pbd=book.FindData(pos.BitBoard()); TEST(pbd!=NULL); TEST(pbd->Values().vHeuristic==mv.value); } { // test StoreSubposition() when there are two passes after the move. // no subposition should be added to the book (we don't store terminal nodes in book.) CBook book; CQPosition pos("OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO******-----------------", false); CMoveValue mv; mv.move=H6; mv.value=64*kStoneValue; CHeightInfoX hix(2, 4, false, pos.NEmpty()); // store subpos in book book.StoreSubposition(pos, mv, hix); TEST(book.Size()==0); // test that pos is valued correctly when we negamax book.StoreRoot(pos.BitBoard(), hix, mv.value, -100); book.NegamaxAll(); const CBookData* pbd=book.FindData(pos.BitBoard()); TEST(pbd!=NULL); TEST(pbd->Values().vHeuristic==mv.value); } }