00001 //--------------------------------------------------------------------------- 00002 /** @file BoardUtilsTest.cpp 00003 */ 00004 //--------------------------------------------------------------------------- 00005 #include <boost/test/auto_unit_test.hpp> 00006 00007 #include "BoardUtils.hpp" 00008 #include "HexBoard.hpp" 00009 00010 using namespace benzene; 00011 00012 //--------------------------------------------------------------------------- 00013 00014 namespace { 00015 00016 BOOST_AUTO_TEST_CASE(BoardUtils_BitsetPacking) 00017 { 00018 BOOST_REQUIRE(MAX_WIDTH >= 7 && MAX_HEIGHT >= 9); 00019 ConstBoard* cb = &ConstBoard::Get(7, 9); 00020 bitset_t b1, b2; 00021 b2 = BoardUtils::PackBitset(*cb, b1); 00022 BOOST_CHECK_EQUAL(BoardUtils::UnpackBitset(*cb, b2), b1); 00023 b1.flip(); 00024 b2 = BoardUtils::PackBitset(*cb, b1); 00025 BOOST_CHECK_EQUAL(BoardUtils::UnpackBitset(*cb, b2), b1 & cb->GetCells()); 00026 BOOST_CHECK_EQUAL(b1.count(), (std::size_t)BITSETSIZE); 00027 BOOST_CHECK_EQUAL(b2.count(), cb->GetCells().count()); 00028 b1.reset(); 00029 b1.set(SWAP_PIECES); 00030 b1.set(NORTH); 00031 b1.set(FIRST_CELL); 00032 int adjustment = 1; 00033 if (FIRST_INVALID != BITSETSIZE) { 00034 b1.set(FIRST_INVALID); 00035 adjustment = 0; 00036 } 00037 b2 = BoardUtils::PackBitset(*cb, b1); 00038 BOOST_CHECK_EQUAL(b1.count(), (std::size_t)(4 - adjustment)); 00039 BOOST_CHECK_EQUAL(b2.count(), 1u); 00040 BOOST_CHECK_EQUAL(BoardUtils::UnpackBitset(*cb, b2), b1 & cb->GetCells()); 00041 } 00042 00043 BOOST_AUTO_TEST_CASE(BoardUtils_RotateAndMirror) 00044 { 00045 BOOST_REQUIRE(MAX_WIDTH >= 11 && MAX_HEIGHT >= 11); 00046 00047 // rotating edges 00048 ConstBoard* cb = &ConstBoard::Get(11, 11); 00049 BOOST_CHECK_EQUAL(BoardUtils::Rotate(*cb, NORTH), SOUTH); 00050 BOOST_CHECK_EQUAL(BoardUtils::Rotate(*cb, EAST), WEST); 00051 BOOST_CHECK_EQUAL(BoardUtils::Rotate(*cb, BoardUtils::Rotate(*cb, EAST)), EAST); 00052 00053 // mirroring edges 00054 BOOST_CHECK_EQUAL(BoardUtils::Mirror(*cb, NORTH), WEST); 00055 BOOST_CHECK_EQUAL(BoardUtils::Mirror(*cb, EAST), SOUTH); 00056 BOOST_CHECK_EQUAL(BoardUtils::Mirror(*cb, BoardUtils::Mirror(*cb, WEST)), WEST); 00057 00058 // rotation of points on board 00059 BOOST_CHECK_EQUAL(BoardUtils::Rotate(*cb, HEX_CELL_F6), HEX_CELL_F6); 00060 BOOST_CHECK_EQUAL(BoardUtils::Rotate(*cb, HEX_CELL_A1), HEX_CELL_K11); 00061 BOOST_CHECK_EQUAL(BoardUtils::Rotate(*cb, HEX_CELL_B1), HEX_CELL_J11); 00062 BOOST_CHECK_EQUAL(BoardUtils::Rotate(*cb, HEX_CELL_A2), HEX_CELL_K10); 00063 BOOST_CHECK_EQUAL(BoardUtils::Rotate(*cb, HEX_CELL_D9), HEX_CELL_H3); 00064 BOOST_CHECK_EQUAL(BoardUtils::Rotate(*cb, HEX_CELL_H3), HEX_CELL_D9); 00065 00066 // mirroring points on board 00067 BOOST_CHECK_EQUAL(BoardUtils::Mirror(*cb, HEX_CELL_F6), HEX_CELL_F6); 00068 BOOST_CHECK_EQUAL(BoardUtils::Mirror(*cb, HEX_CELL_A1), HEX_CELL_A1); 00069 BOOST_CHECK_EQUAL(BoardUtils::Mirror(*cb, HEX_CELL_B1), HEX_CELL_A2); 00070 BOOST_CHECK_EQUAL(BoardUtils::Mirror(*cb, HEX_CELL_A2), HEX_CELL_B1); 00071 BOOST_CHECK_EQUAL(BoardUtils::Mirror(*cb, HEX_CELL_D9), HEX_CELL_I4); 00072 BOOST_CHECK_EQUAL(BoardUtils::Mirror(*cb, HEX_CELL_H3), HEX_CELL_C8); 00073 00074 // rotation of points on rectangular board 00075 cb = &ConstBoard::Get(9, 6); 00076 BOOST_CHECK_EQUAL(BoardUtils::Rotate(*cb, HEX_CELL_A1), HEX_CELL_I6); 00077 BOOST_CHECK_EQUAL(BoardUtils::Rotate(*cb, HEX_CELL_A3), HEX_CELL_I4); 00078 BOOST_CHECK_EQUAL(BoardUtils::Rotate(*cb, HEX_CELL_E3), HEX_CELL_E4); 00079 00080 // rotation of points on board of even dimensions 00081 cb = &ConstBoard::Get(8, 8); 00082 BOOST_CHECK_EQUAL(BoardUtils::Rotate(*cb, HEX_CELL_D4), HEX_CELL_E5); 00083 BOOST_CHECK_EQUAL(BoardUtils::Rotate(*cb, HEX_CELL_D5), HEX_CELL_E4); 00084 00085 // mirroring points on board of even dimensions 00086 BOOST_CHECK_EQUAL(BoardUtils::Mirror(*cb, HEX_CELL_D4), HEX_CELL_D4); 00087 BOOST_CHECK_EQUAL(BoardUtils::Mirror(*cb, HEX_CELL_D5), HEX_CELL_E4); 00088 } 00089 00090 BOOST_AUTO_TEST_CASE(BoardUtils_CentrePoints) 00091 { 00092 BOOST_REQUIRE(MAX_WIDTH >= 10 && MAX_HEIGHT >= 10); 00093 00094 // centre points on odd dimension boards 00095 ConstBoard* cb = &ConstBoard::Get(9, 9); 00096 BOOST_CHECK_EQUAL(BoardUtils::CenterPoint(*cb), HEX_CELL_E5); 00097 BOOST_CHECK_EQUAL(BoardUtils::CenterPoint(*cb), BoardUtils::CenterPointRight(*cb)); 00098 BOOST_CHECK_EQUAL(BoardUtils::CenterPoint(*cb), BoardUtils::CenterPointLeft(*cb)); 00099 00100 // centre points on even dimension boards 00101 cb = &ConstBoard::Get(10, 10); 00102 BOOST_CHECK_EQUAL(BoardUtils::CenterPointLeft(*cb), HEX_CELL_E6); 00103 BOOST_CHECK_EQUAL(BoardUtils::CenterPointRight(*cb), HEX_CELL_F5); 00104 00105 // centre points on rectangular boards 00106 cb = &ConstBoard::Get(7, 10); 00107 BOOST_CHECK_EQUAL(BoardUtils::CenterPointLeft(*cb), HEX_CELL_D5); 00108 BOOST_CHECK_EQUAL(BoardUtils::CenterPointRight(*cb), HEX_CELL_D6); 00109 00110 cb = &ConstBoard::Get(10, 7); 00111 BOOST_CHECK_EQUAL(BoardUtils::CenterPointLeft(*cb), HEX_CELL_E4); 00112 BOOST_CHECK_EQUAL(BoardUtils::CenterPointRight(*cb), HEX_CELL_F4); 00113 } 00114 00115 BOOST_AUTO_TEST_CASE(BoardUtils_CoordsToPoint) 00116 { 00117 BOOST_REQUIRE(MAX_WIDTH >= 8 && MAX_HEIGHT >= 8); 00118 ConstBoard* cb = &ConstBoard::Get(8, 8); 00119 BOOST_CHECK_EQUAL(BoardUtils::CoordsToPoint(*cb, -2, 0), INVALID_POINT); 00120 BOOST_CHECK_EQUAL(BoardUtils::CoordsToPoint(*cb, 0, -2), INVALID_POINT); 00121 BOOST_CHECK_EQUAL(BoardUtils::CoordsToPoint(*cb, -1, -1), INVALID_POINT); 00122 BOOST_CHECK_EQUAL(BoardUtils::CoordsToPoint(*cb, cb->Width(), cb->Height()), INVALID_POINT); 00123 BOOST_CHECK_EQUAL(BoardUtils::CoordsToPoint(*cb, -1, cb->Height()), INVALID_POINT); 00124 BOOST_CHECK_EQUAL(BoardUtils::CoordsToPoint(*cb, cb->Width(), -1), INVALID_POINT); 00125 BOOST_CHECK_EQUAL(BoardUtils::CoordsToPoint(*cb, 0, -1), NORTH); 00126 BOOST_CHECK_EQUAL(BoardUtils::CoordsToPoint(*cb, -1, 0), WEST); 00127 BOOST_CHECK_EQUAL(BoardUtils::CoordsToPoint(*cb, -1, cb->Height()-1), WEST); 00128 BOOST_CHECK_EQUAL(BoardUtils::CoordsToPoint(*cb, cb->Width()-1, cb->Height()), SOUTH); 00129 BOOST_CHECK_EQUAL(BoardUtils::CoordsToPoint(*cb, cb->Width(), cb->Height()-1), EAST); 00130 BOOST_CHECK_EQUAL(BoardUtils::CoordsToPoint(*cb, 0, 0), FIRST_CELL); 00131 BOOST_CHECK_EQUAL(BoardUtils::CoordsToPoint(*cb, cb->Width()-1, cb->Height()-1), 00132 HEX_CELL_H8); 00133 } 00134 00135 BOOST_AUTO_TEST_CASE(BoardUtils_PointInDir) 00136 { 00137 BOOST_REQUIRE(MAX_WIDTH >= 8 && MAX_HEIGHT >= 8); 00138 ConstBoard* cb = &ConstBoard::Get(8, 8); 00139 00140 BOOST_CHECK_EQUAL(BoardUtils::PointInDir(*cb, HEX_CELL_B2, DIR_EAST), HEX_CELL_C2); 00141 BOOST_CHECK_EQUAL(BoardUtils::PointInDir(*cb, HEX_CELL_B2, DIR_NORTH_EAST), HEX_CELL_C1); 00142 BOOST_CHECK_EQUAL(BoardUtils::PointInDir(*cb, HEX_CELL_B2, DIR_NORTH), HEX_CELL_B1); 00143 BOOST_CHECK_EQUAL(BoardUtils::PointInDir(*cb, HEX_CELL_B2, DIR_WEST), HEX_CELL_A2); 00144 BOOST_CHECK_EQUAL(BoardUtils::PointInDir(*cb, HEX_CELL_B2, DIR_SOUTH_WEST), HEX_CELL_A3); 00145 BOOST_CHECK_EQUAL(BoardUtils::PointInDir(*cb, HEX_CELL_B2, DIR_SOUTH), HEX_CELL_B3); 00146 00147 BOOST_CHECK_EQUAL(BoardUtils::PointInDir(*cb, HEX_CELL_A1, DIR_NORTH_EAST), NORTH); 00148 BOOST_CHECK_EQUAL(BoardUtils::PointInDir(*cb, HEX_CELL_A1, DIR_NORTH), NORTH); 00149 BOOST_CHECK_EQUAL(BoardUtils::PointInDir(*cb, HEX_CELL_A1, DIR_WEST), WEST); 00150 BOOST_CHECK_EQUAL(BoardUtils::PointInDir(*cb, HEX_CELL_A1, DIR_SOUTH_WEST), WEST); 00151 00152 BOOST_CHECK_EQUAL(BoardUtils::PointInDir(*cb, NORTH, DIR_SOUTH), NORTH); 00153 BOOST_CHECK_EQUAL(BoardUtils::PointInDir(*cb, NORTH, DIR_EAST), NORTH); 00154 } 00155 00156 BOOST_AUTO_TEST_CASE(BoardUtils_ShiftBitset) 00157 { 00158 BOOST_REQUIRE(MAX_WIDTH >= 8 && MAX_HEIGHT >= 8); 00159 ConstBoard* cb = &ConstBoard::Get(8, 8); 00160 bitset_t b1, b2; 00161 00162 b1.set(HEX_CELL_A1); 00163 BOOST_CHECK(BoardUtils::ShiftBitset(*cb, b1, DIR_EAST, b2)); 00164 BOOST_CHECK(b2.test(HEX_CELL_B1)); 00165 00166 BOOST_CHECK(!BoardUtils::ShiftBitset(*cb, b1, DIR_NORTH, b2)); 00167 BOOST_CHECK(!BoardUtils::ShiftBitset(*cb, b1, DIR_WEST, b2)); 00168 00169 BOOST_CHECK(BoardUtils::ShiftBitset(*cb, b1, DIR_SOUTH, b2)); 00170 BOOST_CHECK(b2.test(HEX_CELL_A2)); 00171 00172 } 00173 00174 BOOST_AUTO_TEST_CASE(BoardUtil_RandomEmptyCell) 00175 { 00176 HexPoint p; 00177 BOOST_REQUIRE(MAX_WIDTH >= 2 && MAX_HEIGHT >= 2); 00178 00179 // test under normal conditions 00180 StoneBoard sb = StoneBoard(2, 2); 00181 00182 p = BoardUtils::RandomEmptyCell(sb); 00183 BOOST_CHECK(sb.Const().IsCell(p)); 00184 sb.StartNewGame(); 00185 BOOST_CHECK(!sb.IsLegal(SWAP_PIECES)); 00186 p = BoardUtils::RandomEmptyCell(sb); 00187 BOOST_CHECK(sb.Const().IsCell(p)); 00188 sb.PlayMove(BLACK, HEX_CELL_A1); 00189 BOOST_CHECK(sb.IsLegal(SWAP_PIECES)); 00190 sb.PlayMove(WHITE, HEX_CELL_A2); 00191 BOOST_CHECK(!sb.IsLegal(SWAP_PIECES)); 00192 BOOST_CHECK_EQUAL(sb.GetPlayed().count(), 6u); 00193 BOOST_CHECK(!sb.IsEmpty(HEX_CELL_A1)); 00194 BOOST_CHECK(!sb.IsEmpty(HEX_CELL_A2)); 00195 00196 p = BoardUtils::RandomEmptyCell(sb); 00197 BOOST_CHECK(sb.Const().IsCell(p)); 00198 BOOST_CHECK(sb.IsEmpty(p)); 00199 BOOST_CHECK(p != HEX_CELL_A1); 00200 BOOST_CHECK(p != HEX_CELL_A2); 00201 00202 // test when one cell left 00203 sb = StoneBoard(1, 1); 00204 sb.StartNewGame(); 00205 p = BoardUtils::RandomEmptyCell(sb); 00206 BOOST_CHECK_EQUAL(p, HEX_CELL_A1); 00207 00208 // test when no cells left 00209 sb = StoneBoard(1, 1); 00210 sb.PlayMove(BLACK, HEX_CELL_A1); 00211 p = BoardUtils::RandomEmptyCell(sb); 00212 BOOST_CHECK_EQUAL(p, INVALID_POINT); 00213 00214 // test when game has been resigned 00215 sb = StoneBoard(1, 1); 00216 sb.StartNewGame(); 00217 sb.PlayMove(WHITE, RESIGN); 00218 BOOST_CHECK(!sb.IsLegal(HEX_CELL_A1)); 00219 p = BoardUtils::RandomEmptyCell(sb); 00220 BOOST_CHECK_EQUAL(p, HEX_CELL_A1); 00221 } 00222 00223 BOOST_AUTO_TEST_CASE(BoardUtil_Decompositions) 00224 { 00225 ICEngine ice; 00226 VCBuilderParam param; 00227 HexBoard brd(7, 7, ice, param); 00228 00229 std::string str(". . . . W B ." 00230 ". . . . . . ." 00231 ". B B B W . ." 00232 ". B B W . . ." 00233 ". . W . . . ." 00234 ". . W . . . ." 00235 ". . . . . . ."); 00236 brd.GetPosition().SetPosition(str); 00237 00238 // Find decomp between E1, B3, WEST, and NORTH. 00239 brd.SetUseDecompositions(false); 00240 brd.ComputeAll(BLACK); 00241 brd.SetUseDecompositions(true); 00242 bitset_t capturedVC; 00243 BOOST_CHECK(BoardUtils::FindCombinatorialDecomposition(brd, BLACK, 00244 capturedVC)); 00245 BOOST_CHECK(capturedVC.any()); 00246 } 00247 00248 BOOST_AUTO_TEST_CASE(BoardUtil_SplitDecompositions) 00249 { 00250 ICEngine ice; 00251 VCBuilderParam param; 00252 HexBoard brd(7, 7, ice, param); 00253 00254 std::string s(". . . . W B ." 00255 ". . . . . . ." 00256 ". B B B W . ." 00257 ". B B W . . ." 00258 ". . W . . . ." 00259 ". . W . . . ." 00260 ". . . . . . ."); 00261 brd.GetPosition().SetPosition(s); 00262 00263 // Find splitting decomp between NORTH, E3, SOUTH. 00264 brd.ComputeAll(WHITE); 00265 HexPoint group; 00266 BOOST_CHECK(BoardUtils::FindSplittingDecomposition(brd, WHITE, group)); 00267 BOOST_CHECK_EQUAL(group, HEX_CELL_E3); 00268 } 00269 00270 } // namespace 00271 00272 //---------------------------------------------------------------------------