8 #ifndef HOG2_ENVIRONMENTS_WITNESS_H
9 #define HOG2_ENVIRONMENTS_WITNESS_H
25 template<
int w
idth,
int height>
31 template<
int w
idth,
int height>
35 return GetEdgeHash<width, height>(
true,
std::min(x1, x2), y1);
37 return GetEdgeHash<width, height>(
false, x1,
std::min(y1, y2));
41 template<
int w
idth,
int height>
44 std::vector<std::pair<int, int>>
path;
68 int x = which % (
width);
69 int y = which / (
width);
75 int x = which % (
width + 1);
76 int y = which / (
width + 1);
81 int x = which % (
width + 1);
82 int y = which / (
width + 1);
91 auto &prevPos =
path[
path.size() - 2];
92 auto &currPos =
path.back();
93 return ((currPos.first == 0 || currPos.first ==
width) && currPos.first == prevPos.first) ||
94 ((currPos.second == 0 || currPos.second ==
height) && currPos.second == prevPos.second);
101 auto &p =
path.back();
102 return (p.first == 0 || p.first ==
width) ||
103 (p.second == 0 || p.second ==
height);
117 return occupiedEdges[GetEdgeHash<width, height>(x1, y1, x2, y2)];
124 occupiedEdges.set(GetEdgeHash<width, height>(x1, y1, x2, y2),
false);
143 template<
int w
idth,
int height>
149 template<
int w
idth,
int height>
203 return !(*
this == a);
205 operator std::string()
const
207 std::stringstream ss;
208 ss <<
"{\"type\":" <<
t <<
",\"param\":" <<
parameter <<
",\"color\":\"" <<
c.
hex() <<
"\"}";
220 template<
int w
idth,
int height>
247 std::array<WitnessPathConstraintType, Witness<width, height>::GetNumPathConstraints()>
pathConstraints;
248 std::array<std::pair<Graphics::point, Graphics::rect>,
284 "Error: width/height must be between 1...8");
324 for (
int x = 0; x <
width; x++)
326 for (
int y = 0; y <
height; y++)
339 for (
int x = 0; x <
width; x++)
341 for (
int y = 0; y <=
height; y++)
348 for (
int x = 0; x <=
width; x++)
350 for (
int y = 0; y <
height; y++)
358 for (
int x = 0; x <
width + 1; x++)
360 for (
int y = 0; y <
height + 1; y++)
374 start.emplace_back(0, 0);
452 start.emplace_back(x, y);
466 if (x == -1 || x ==
width + 1 || y == -1 || y ==
height + 1)
468 goal.emplace_back(x, y);
479 printf(
"Error: invalid goal location\n");
524 for (
int x = 0; x <
width; x++)
526 for (
int y = 0; y <
height; y++)
538 for (
int x = 0; x <
width; x++)
540 for (
int y = 0; y <
height; y++)
572 printf(
"(%d, %d) out of bounds\n", x, y);
575 assert(count >= 1 && count <= 3);
732 const uint16_t
tetrisBits[25] = {0, 0x8000, 0xC000, 0x8800, 0xC800, 0xC400, 0x8C00, 0x4C00, 0xE000, 0x8880, 0xCC00,
733 0xE800, 0x8E00, 0xE200, 0x2E00, 0xC880, 0xC440, 0x88C0, 0x44C0, 0xF000, 0x8888,
734 0xE400, 0x4E00, 0x8C80, 0x4C40};
735 const uint64_t
tetrisBits64[25] = {0, 0x8000000000000000ull, 0xC000000000000000ull, 0x8080000000000000ull,
736 0x80C0000000000000ull, 0x40C0000000000000ull, 0xC080000000000000ull,
737 0xC040000000000000ull,
738 0xE000000000000000ull, 0x8080800000000000ull, 0xC0C0000000000000ull,
739 0x80E0000000000000ull,
740 0xE080000000000000ull, 0x20E0000000000000ull, 0xE020000000000000ull,
741 0x8080C00000000000ull,
742 0x4040C00000000000ull, 0xC080800000000000ull, 0xC040400000000000ull,
743 0xF000000000000000ull,
744 0x8080808000000000ull, 0x40E0000000000000ull, 0xE040000000000000ull,
745 0x80C0800000000000ull,
746 0x40C0400000000000ull};
747 const uint16_t
tetrisSize[25] = {0, 1, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4};
782 printf(
"(%d, %d) out of bounds\n", x, y);
828 std::vector<std::pair<int, int>>
start;
829 std::vector<std::pair<int, int>>
goal;
835 operator std::string()
const
837 std::string quote =
"\"";
838 std::stringstream ss;
839 ss <<
"{\"width\":" <<
width <<
", \"height\":" <<
height <<
", \"start\":[";
840 for (
const auto &s:
start)
842 ss <<
"{\"x\":" << s.first <<
", \"y\":" << s.second <<
"}";
843 if (&s != &
start.back())
846 ss <<
"], \"goal\":[";
847 for (
const auto &g:
goal)
849 ss <<
"{\"x\":" << g.first <<
", \"y\":" << g.second <<
"}";
850 if (&g != &
goal.back())
853 ss <<
"], \"constraints\":{\"regionConstraints\":[";
855 for (
unsigned x = 0; x <
width; ++x)
857 for (
unsigned y = 0; y <
height; ++y)
862 ss <<
"{\"x\":" << x <<
",\"y\":" << y
863 <<
",\"constraint\":" << std::string(
constraint) <<
"}";
872 ss <<
"], \"pathConstraints\":[";
874 if (t != kNoPathConstraint)
883 ss <<
"{\"locationType\":" << p.
t <<
",\"x\":" << p.
x <<
",\"y\":" << p.
y
899 return os << std::string(*
this);
904 std::string input((std::istreambuf_iterator<char>(is)), std::istreambuf_iterator<char>());
905 std::regex wh(
"\"width\":\\s*(\\d+),\\s*\"height\":\\s*(\\d+)");
907 if (!std::regex_search(input, match, wh))
909 std::cerr <<
"incorrect string" << std::endl;
912 int w = std::stoi(match[1].str());
913 int h = std::stoi(match[2].str());
916 std::cerr <<
"unmatched width and height" << std::endl;
919 std::regex regStart(
"\"start\":\\s*\\[(\\{\"x\":\\s*\\d+,\\s*\"y\":\\s*\\d+\\})*\\],");
920 if (!std::regex_search(input, match, regStart))
922 std::cerr <<
"incorrect string" << std::endl;
925 std::regex regXy(
"\"x\":\\s*(\\d+),\\s*\"y\":\\s*(\\d+)");
926 for (
size_t i = 1; i < match.size(); ++i)
928 std::string s = match[i].str();
930 std::regex_search(s, nums, regXy);
931 int x = std::stoi(nums[1].str());
932 int y = std::stoi(nums[2].str());
933 if (std::find(
start.begin(),
start.end(), std::pair<int, int>{x, y}) ==
start.end())
936 std::regex regGoal(
"\"goal\":\\s*\\[(\\{\"x\":\\s*\\d+,\\s*\"y\":\\s*\\d+\\})*\\],");
937 if (!std::regex_search(input, match, regGoal))
939 std::cerr <<
"incorrect string" << std::endl;
942 for (
size_t i = 1; i < match.size(); ++i)
944 std::string s = match[i].str();
946 std::regex_search(s, nums, regXy);
947 int x = std::stoi(nums[1].str());
948 int y = std::stoi(nums[2].str());
949 if (std::find(
goal.begin(),
goal.end(), std::pair<int, int>{x, y}) ==
goal.end())
952 std::regex regConstraints(
"\"constraints\":\\s*\\{\"regionConstraints\":\\s*\\[(.*)\\],\\s*\"pathConstraints\":\\[(.*)\\]\\}");
953 if (!std::regex_search(input, match, regConstraints))
955 std::cerr <<
"incorrect string" << std::endl;
958 std::string rc = match[1].str();
959 std::string pc = match[2].str();
960 std::regex regRegionConstraint(
"\\{\"x\":\\s*(\\d+),\\s*\"y\":\\s*(\\d+),\\s*\"constraint\":\\s*\\{\"type\":\\s*(\\d),\\s*\"param\":\\s*(\\d),\\s*\"color\":\\s*\"(#[a-fA-F0-9]{6})\"\\}");
961 auto begin = std::sregex_iterator(input.begin(), input.end(), regRegionConstraint);
962 auto end = std::sregex_iterator();
963 for (
auto i = begin; i != end; ++i)
966 int x = std::stoi(match[1]);
967 int y = std::stoi(match[2]);
970 std::cerr <<
"incorrect location type" << std::endl;
973 int type = std::stoi(match[3]);
976 std::cerr <<
"incorrect region constraint type" << std::endl;
979 int param = std::stoi(match[4]);
988 std::regex regPathConstraint(
"\\{\"locationType\":\\s*(\\d),\\s*\"x\":\\s*(\\d),\\s*\"y\":\\s*(\\d),\\s*\"constraint\":\\s*(\\d)\\}");
989 begin = std::sregex_iterator(input.begin(), input.end(), regPathConstraint);
990 for (
auto i = begin; i != end; ++i)
993 int locationType = std::stoi(match[1]);
994 if (locationType != 0 && locationType != 1 && locationType != 2)
996 std::cerr <<
"incorrect location type" << std::endl;
999 int x = std::stoi(match[2]);
1000 int y = std::stoi(match[3]);
1003 std::cerr <<
"incorrect location" << std::endl;
1006 int c = std::stoi(match[4]);
1009 std::cerr <<
"incorrect path constraint type" << std::endl;
1012 int p = (locationType == 0) ? (x + y *
width) :
1028 std::string quote =
"\"";
1029 std::string hash =
"{";
1032 hash += quote +
"dim" + quote +
":" + quote + std::to_string(
width) +
"x" + std::to_string(
height) + quote;
1037 hash += quote +
"cc" + quote +
":{";
1038 for (
int x = 0; x <
width; x++)
1040 for (
int y = 0; y <
height; y++)
1042 if (x != 0 || y != 0) hash +=
",";
1061 hash += quote +
"mc" + quote +
":" + quote;
1073 const char *
loc = strstr(s.c_str(),
"dim");
1081 sscanf(
loc,
"%*[^0-9]%cx%c", &a, &b);
1084 printf(
"Width: %d; height: %d\n", w, h);
1096 printf(
"Dimensions do not match, aborting load!\n");
1102 const char *
loc = strstr(s.c_str(),
"mc");
1105 printf(
"Failed loading MC constraints\n");
1109 while (
loc[0] !=
':')
1112 while (
loc[0] !=
'"')
1119 else if (
loc[0] ==
'2')
1127 const char *
loc = strstr(s.c_str(),
"cc");
1130 printf(
"Failed loading CC constraints\n");
1134 while (
loc[0] !=
'{')
1137 for (
int x = 0; x <
width; x++)
1139 for (
int y = 0; y <
height; y++)
1143 printf(
"Unexpected '}', aborting\n");
1146 while (
loc[0] !=
'"')
1150 int cType = atoi(
loc);
1151 while (
loc[0] !=
';')
1154 int param = atoi(
loc);
1155 while (
loc[0] !=
';')
1167 while (
loc[0] !=
',')
1199 for (
int x = 0; x <
width; x++)
1200 for (
int y = 0; y <=
height; y++)
1201 if (index == (x + y *
width))
1203 for (
int x = 0; x <=
width; x++)
1204 for (
int y = 0; y <
height; y++)
1207 for (
int x = 0; x <
width + 1; x++)
1208 for (
int y = 0; y <
height + 1; y++)
1227 mutable std::vector<std::vector < int> *>
1235 int curr, uint64_t board, uint64_t oob, uint64_t posFootprint, uint64_t negFootprint)
const;
1246 else if (p1.
y == p2.
y)
1302 for (
int y = 7; y >= 0; y--)
1304 for (
int x = 0; x < offset; x++)
1306 for (
int x = 0; x < 8; x++)
1308 std::cout << ((val >> (7 - x)) >> ((7 - y) * 8) & 0x1);
1310 std::cout << std::endl;
1315 template<
int w
idth,
int height>
1321 template<
int w
idth,
int height>
1326 if (nodeID.
path.size() == 0)
1328 actions.push_back(
kStart);
1332 int currX = nodeID.
path.back().first;
1333 int currY = nodeID.
path.back().second;
1338 if (goalMap[GetPathIndex(currX, currY)] != 0) actions.push_back(
kEnd);
1353 if (currX > 0 && !nodeID.
Occupied(currX - 1, currY)) actions.push_back(
kLeft);
1355 if (currY > 0 && !nodeID.
Occupied(currX, currY - 1)) actions.push_back(
kDown);
1356 if (currY <
height && !nodeID.
Occupied(currX, currY + 1)) actions.push_back(
kUp);
1359 template<
int w
idth,
int height>
1364 if (nodeID.
path.size() == 0)
1366 actions.push_back(
kStart);
1370 int currX = nodeID.
path.back().first;
1371 int currY = nodeID.
path.back().second;
1376 if (goalMap[(GetPathIndex(currX, currY))] != 0)
1378 actions.push_back(
kEnd);
1410 if (currY >= 0 && currY <=
height)
1412 if (currX > 0 && !GetCannotCrossConstraint(currX - 1, currY)) actions.push_back(
kLeft);
1413 if (currX <
width && !GetCannotCrossConstraint(currX + 1, currY)) actions.push_back(
kRight);
1415 if (currX >= 0 && currX <=
width)
1417 if (currY > 0 && !GetCannotCrossConstraint(currX, currY - 1)) actions.push_back(
kDown);
1418 if (currY <
height && !GetCannotCrossConstraint(currX, currY + 1)) actions.push_back(
kUp);
1422 template<
int w
idth,
int height>
1429 int whichGoal = goalMap[GetPathIndex(s.first, s.second)];
1430 assert(whichGoal != 0);
1431 s = goal[whichGoal - 1];
1460 template<
int w
idth,
int height>
1463 auto len = s.
path.size() + 1;
1468 int whichGoal = goalMap[GetPathIndex(s.
path.back().first, s.
path.back().second)];
1469 assert(whichGoal != 0);
1470 s.
path.push_back(goal[whichGoal - 1]);
1491 s.
path.push_back(start[0]);
1496 s.
path.back().first--;
1502 s.
path.back().first++;
1508 s.
path.back().second++;
1514 s.
path.back().second--;
1523 template<
int w
idth,
int height>
1526 auto len = s.
path.size();
1531 s.
path[len - 1].first, s.
path[len - 1].second, s.
path[len - 2].first, s.
path[len - 2].second);
1537 template<
int w
idth,
int height>
1540 int currX = s.
path.back().first;
1541 int currY = s.
path.back().second;
1545 if (goalMap[GetPathIndex(currX, currY)] != 0)
1566 if (s.
path.size() == 0)
1577 l = kNotValidAction;
1580 else if (GetCannotCrossConstraint(
true, currX - 1, currY))
1582 l = kHitCannotCross;
1585 else if (s.
Occupied(currX - 1, currY))
1595 l = kNotValidAction;
1598 else if (GetCannotCrossConstraint(
true, currX, currY))
1600 l = kHitCannotCross;
1603 else if (s.
Occupied(currX + 1, currY))
1616 l = kNotValidAction;
1619 else if (GetCannotCrossConstraint(
false, currX, currY - 1))
1621 l = kHitCannotCross;
1624 else if (s.
Occupied(currX, currY - 1))
1636 l = kNotValidAction;
1639 else if (GetCannotCrossConstraint(
false, currX, currY))
1641 l = kHitCannotCross;
1644 else if (s.
Occupied(currX, currY + 1))
1655 template<
int w
idth,
int height>
1658 int currX = s.
path.back().first;
1659 int currY = s.
path.back().second;
1663 if (goalMap[GetPathIndex(currX, currY)] != 0)
1675 return s.
path.size() == 0;
1677 return (currX > 0 && !s.
Occupied(currX - 1, currY) && !GetCannotCrossConstraint(
true, currX - 1, currY));
1679 return (currX <
width && !s.
Occupied(currX + 1, currY) && !GetCannotCrossConstraint(
true, currX, currY));
1681 return (currY > 0 && !s.
Occupied(currX, currY - 1) && !GetCannotCrossConstraint(
false, currX, currY - 1));
1683 return (currY <
height && !s.
Occupied(currX, currY + 1) && !GetCannotCrossConstraint(
false, currX, currY));
1688 template<
int w
idth,
int height>
1714 template<
int w
idth,
int height>
1721 template<
int w
idth,
int height>
1728 template<
int w
idth,
int height>
1734 template<
int w
idth,
int height>
1739 return GoalTest(
node);
1742 template<
int w
idth,
int height>
1746 for (
int x = 0; x <
width + 1; x++)
1748 for (
int y = 0; y <
height + 1; y++)
1750 if (GetMustCrossConstraint(x, y) && (!
node.Occupied(x, y)))
return false;
1751 if (GetCannotCrossConstraint(x, y) && (
node.Occupied(x, y)))
return false;
1754 for (
int x = 0; x <
width; x++)
1756 for (
int y = 0; y <=
height; y++)
1758 if (GetMustCrossConstraint(
true, x, y) && !
node.OccupiedEdge(x, y, x + 1, y))
return false;
1759 if (GetCannotCrossConstraint(
true, x, y) &&
node.OccupiedEdge(x, y, x + 1, y))
return false;
1762 for (
int x = 0; x <=
width; x++)
1764 for (
int y = 0; y <
height; y++)
1766 if (GetMustCrossConstraint(
false, x, y) && !
node.OccupiedEdge(x, y, x, y + 1))
return false;
1767 if (GetCannotCrossConstraint(
false, x, y) &&
node.OccupiedEdge(x, y, x, y + 1))
return false;
1808 if (
node.path.size() == 0)
return false;
1815 node.path.back().first >= 0)
1821 for (
int x = 0; x <
width; x++)
1823 for (
int y = 0; y <
height; y++)
1825 if (regionConstraints[x][y].t ==
kTriangle)
1827 int count =
node.OccupiedEdge(x, y, x, y + 1);
1828 count +=
node.OccupiedEdge(x, y, x + 1, y);
1829 count +=
node.OccupiedEdge(x + 1, y, x + 1, y + 1);
1830 count +=
node.OccupiedEdge(x, y + 1, x + 1, y + 1);
1832 if (count != regionConstraints[x][y].parameter)
return false;
1839 constraintCount[
kEraser] == 0)
1851 for (
auto &v: regionList)
1857 int x = GetRegionFromX(i);
1858 int y = GetRegionFromY(i);
1865 c = regionConstraints[x][y].c;
1868 else if (c != regionConstraints[x][y].c)
1880 if (constraintCount[
kStar] > 0)
1882 for (
auto &v: regionList)
1886 int x = GetRegionFromX(i);
1887 int y = GetRegionFromY(i);
1888 rgbColor finishedColor(1.0 / 512.0, 1.0 / 512.0, 1.0 / 512.0);
1890 if (regionConstraints[x][y].t ==
kStar)
1892 if (regionConstraints[x][y].c == finishedColor)
continue;
1894 finishedColor = regionConstraints[x][y].c;
1898 int xx = GetRegionFromX(r);
1899 int yy = GetRegionFromY(r);
1902 regionConstraints[x][y].c == regionConstraints[xx][yy].c)
1905 if (count > 2)
return false;
1908 if (count != 2)
return false;
1914 if (constraintCount[
kTetris] > 0)
1917 tetrisBlockCount.resize(regionList.size());
1920 for (
int x = 0; x < regionList.size(); x++)
1922 const auto &v = *regionList[x];
1923 tetrisBlockCount[x] = 0;
1926 if (regionConstraints[GetRegionFromX(l)][GetRegionFromY(l)].t ==
kTetris)
1928 int whichConstraint = regionConstraints[GetRegionFromX(l)][GetRegionFromY(l)].parameter;
1929 int numPieces = tetrisSize[whichConstraint];
1932 else if (regionConstraints[GetRegionFromX(l)][GetRegionFromY(l)].t ==
kNegativeTetris)
1934 int whichConstraint = regionConstraints[GetRegionFromX(l)][GetRegionFromY(l)].parameter;
1935 int numPieces = tetrisSize[whichConstraint];
1940 if (tetrisBlockCount[x] > 0 && tetrisBlockCount[x] != regionList[x]->size())
1949 for (
int x = 0; x < regionList.size(); x++)
1951 bool hasNegations =
false;
1952 const auto &v = *regionList[x];
1953 if (v.size() == 0)
continue;
1955 tetrisBlocksInRegion.resize(0);
1961 uint64_t xx = GetRegionFromX(l);
1962 uint64_t yy = GetRegionFromY(l);
1965 board |= ((1ull << (7 - xx)) << ((7 - yy) * 8));
1967 if (regionConstraints[GetRegionFromX(l)][GetRegionFromY(l)].t ==
kTetris)
1969 int whichConstraint = regionConstraints[xx][yy].parameter;
1970 tetrisBlocksInRegion.push_back(whichConstraint);
1972 if (regionConstraints[GetRegionFromX(l)][GetRegionFromY(l)].t ==
kNegativeTetris)
1974 int whichConstraint = regionConstraints[xx][yy].parameter;
1975 tetrisBlocksInRegion.push_back(-whichConstraint);
1976 hasNegations =
true;
1991 if (tetrisBlocksInRegion.size() == 0)
continue;
1994 uint64_t oob = ~board;
1995 if (hasNegations) oob = 0;
2001 if (!RecursivelyPlacePieces(0, board, oob, 0, 0))
2013 template<
int w
idth,
int height>
2015 int curr, uint64_t board, uint64_t oob, uint64_t posFootprint, uint64_t negFootprint)
const
2018 if (curr == tetrisBlocksInRegion.size())
return (board == 0) && ((negFootprint & posFootprint) == negFootprint);
2021 int whichBlock = tetrisBlocksInRegion[curr];
2025 whichBlock = -whichBlock;
2032 for (
int x = 0; x <
width - tetrisWH[whichBlock][0] + 1; x++)
2034 for (
int y = 0; y <
height - tetrisWH[whichBlock][1] + 1; y++)
2037 uint64_t block = ((tetrisBits64[whichBlock] >> x) >> (8 * y));
2039 if ((board & oob) == 0)
2041 if (RecursivelyPlacePieces(curr + 1, board, oob, neg ? posFootprint : (posFootprint | block),
2042 neg ? (negFootprint | block) : negFootprint))
2059 template<
int w
idth,
int height>
2062 template<
int w
idth,
int height>
2068 template<
int w
idth,
int height>
2074 template<
int w
idth,
int height>
2077 template<
int w
idth,
int height>
2084 #pragma mark Path Constraints
2087 template<
int w
idth,
int height>
2093 template<
int w
idth,
int height>
2096 return (pathConstraints[which] ==
kMustCross);
2129 template<
int w
idth,
int height>
2135 template<
int w
idth,
int height>
2137 bool horiz,
int x,
int y)
const
2140 return GetMustCrossConstraint(y *
width + x);
2145 template<
int w
idth,
int height>
2152 template<
int w
idth,
int height>
2157 SetMustCrossConstraint(y *
width + x);
2162 template<
int w
idth,
int height>
2188 template<
int w
idth,
int height>
2194 template<
int w
idth,
int height>
2199 RemoveMustCrossConstraint(y *
width + x);
2225 template<
int w
idth,
int height>
2231 template<
int w
idth,
int height>
2237 template<
int w
idth,
int height>
2263 template<
int w
idth,
int height>
2299 template<
int w
idth,
int height>
2325 template<
int w
idth,
int height>
2332 template<
int w
idth,
int height>
2334 bool horiz,
int x,
int y)
const
2337 return GetCannotCrossConstraint(y *
width + x);
2342 template<
int w
idth,
int height>
2344 bool horiz,
int x,
int y)
2347 AddCannotCrossConstraint(y *
width + x);
2352 template<
int w
idth,
int height>
2358 template<
int w
idth,
int height>
2364 template<
int w
idth,
int height>
2369 RemoveCannotCrossConstraint(y *
width + x);
2374 template<
int w
idth,
int height>
2381 #pragma mark Solver Helper Functions
2384 template<
int w
idth,
int height>
2390 for (std::vector<int> *i: regionList)
2393 regionCache.returnItem(i);
2395 regionList.resize(0);
2399 std::vector<int> queue;
2403 for (
int y = 0; y <
height; y++)
2405 for (
int x = 0; x <
width; x++)
2407 if (regions[GetRegionIndex(x, y) ] == 0)
2409 queue.push_back(GetRegionIndex(x, y));
2411 while (regionList.size() < index)
2413 regionList.push_back(regionCache.getItem());
2419 while (queue.size() > 0)
2421 int next = queue.back();
2424 if (regions[next] == 0)
2426 regions[next] = index;
2427 regionList[index - 1]->push_back(next);
2429 int xx = GetRegionFromX(next);
2430 int yy = GetRegionFromY(next);
2431 if (xx > 0 && !s.
OccupiedEdge(xx, yy, xx, yy + 1) && regions[GetRegionIndex(xx - 1, yy)] == 0)
2432 queue.push_back(GetRegionIndex(xx - 1, yy));
2434 regions[GetRegionIndex(xx + 1, yy)] == 0)
2435 queue.push_back(GetRegionIndex(xx + 1, yy));
2436 if (yy > 0 && !s.
OccupiedEdge(xx, yy, xx + 1, yy) && regions[GetRegionIndex(xx, yy - 1)] == 0)
2437 queue.push_back(GetRegionIndex(xx, yy - 1));
2439 regions[GetRegionIndex(xx, yy + 1)] == 0)
2440 queue.push_back(GetRegionIndex(xx, yy + 1));
2492 template<
int w
idth,
int height>
2500 (mouseLoc - GetScreenCoord(start[0].first, start[0].second)).length() < 3 * lineWidth)
2508 if (iws.
ws.path.size() > 0 &&
2509 (iws.
ws.path.back().second >
height || iws.
ws.path.back().second < 0 || iws.
ws.path.back().first >
width ||
2510 iws.
ws.path.back().first < 0))
2521 ApplyAction(iws.
ws,
kEnd);
2532 template<
int w
idth,
int height>
2543 Graphics::point end = GetScreenCoord(iws.
ws.path.back().first, iws.
ws.path.back().second);
2546 if (iws.
ws.path.size() > 1) factor = 1;
2553 std::vector <WitnessAction> moves;
2554 GetMouseActions(iws.
ws, moves);
2562 ApplyAction(iws.
target, m);
2566 if ((mouseLoc - p).length() < dist)
2568 dist = (mouseLoc - p).length();
2575 ApplyAction(iws.
target, a);
2583 int len =
static_cast<int>(iws.
ws.path.size());
2585 if (len >= 2 && iws.
target == iws.
ws.path[len - 2])
2590 UndoAction(iws.
ws, a);
2601 Graphics::point from = GetScreenCoord(iws.
ws.path.back().first, iws.
ws.path.back().second);
2611 else if (from.
x == to.
x && (mouseLoc.
y - from.
y) / (to.
y - from.
y) > 0.9 &&
2618 else if (from.
y == to.
y && (mouseLoc.
x - from.
x) / (to.
x - from.
x) > 0.9 &&
2631 else if (from.
x == to.
x && (mouseLoc.
y - from.
y) / (to.
y - from.
y) < 0.1)
2636 else if (from.
y == to.
y && (mouseLoc.
x - from.
x) / (to.
x - from.
x) < 0.1)
2648 iws.
frac = (mouseLoc.
y - from.
y) / (to.
y - from.
y);
2649 gapSize = lineWidth / fabs(to.
y - from.
y);
2653 iws.
frac = (mouseLoc.
x - from.
x) / (to.
x - from.
x);
2654 gapSize = lineWidth / fabs(to.
x - from.
x);
2662 if ((iws.
target == std::pair<int, int>(0, 0)) && iws.
frac > 0.6f)
2664 else if (iws.
frac > 0.5 - 2 * gapSize && l == kHitCannotCross)
2665 iws.
frac = 0.5 - 2 * gapSize;
2666 else if (iws.
frac > 0.8f && l == kHitLine)
2667 iws.
frac = 1.f - 2 * gapSize;
2677 #pragma mark Visualization
2680 template<
int w
idth,
int height>
2697 {p3.
x - 1.0f * lineWidth, p3.
y - 2.0f * lineWidth, p3.
x + 1.0f * lineWidth,
2698 p3.
y + 2.0f * lineWidth},
2701 {p3.
x - 2.0f * lineWidth, p3.
y - 1.0f * lineWidth, p3.
x + 2.0f * lineWidth,
2702 p3.
y + 1.0f * lineWidth},
2717 if (whichPiece != 0)
2784 float blockSize = gapOffset / 8.0f;
2785 for (
int yy = 0; yy < 4; yy++)
2787 for (
int xx = 0; xx < 4; xx++)
2789 if ((tetrisBits[whichPiece] >> (yy * 4 + xx)) & 1)
2791 Graphics::point p4(-2 * blockSize + xx * blockSize + 0.5f * blockSize - xOff * blockSize,
2792 -2 * blockSize + yy * blockSize + 0.5f * blockSize - yOff * blockSize);
2798 display.
FillRect(inner, backColor);
2822 p.
x += 2 * lineWidth;
2830 p.
x -= 2 * lineWidth;
2832 p.
x += 4 * lineWidth;
2846 template<
int w
idth,
int height>
2854 display.
FillRect({-1, -1, 1, 1}, outerBackColor);
2858 for (
int x = 0; x <=
width; x++)
2860 DoLine(display, GetScreenCoord(x, 0), GetScreenCoord(x,
height), lineColor);
2864 for (
int y = 0; y <=
height; y++)
2866 DoLine(display, GetScreenCoord(0, y), GetScreenCoord(
width, y), lineColor);
2874 display.
FillCircle(GetScreenCoord(0, 0), lineWidth, lineColor);
2878 assert(start.size() > 0);
2879 for (
const auto &i: start)
2880 display.
FillCircle(GetScreenCoord(i.first, i.second), lineWidth * 3.f, lineColor);
2884 for (
int x = 0; x <=
width; x++)
2886 for (
int y = 0; y <=
width; y++)
2889 if ((val = goalMap[GetPathIndex(x, y)]) != 0)
2891 auto endLoc = GetScreenCoord(goal[val - 1].first, goal[val - 1].second);
2892 DoLine(display, GetScreenCoord(x, y), endLoc, lineColor);
2893 display.
FillCircle(endLoc, lineWidth, lineColor);
2906 for (
int x = 0; x <
width + 1; x++)
2908 for (
int y = 0; y <
height + 1; y++)
2910 if (GetMustCrossConstraint(x, y))
2915 else if (GetCannotCrossConstraint(x, y))
2919 display.
FillSquare(pt, lineWidth, backColor);
2960 for (
int x = 0; x <
width; x++)
2962 for (
int y = 0; y <=
height; y++)
2964 if (GetMustCrossConstraint(
true, x, y))
2971 else if (GetCannotCrossConstraint(
true, x, y))
2976 display.
FillSquare(pt, lineWidth, backColor);
2980 for (
int x = 0; x <=
width; x++)
2982 for (
int y = 0; y <
height; y++)
2984 if (GetMustCrossConstraint(
false, x, y))
2991 else if (GetCannotCrossConstraint(
false, x, y))
2996 display.
FillSquare(pt, lineWidth, backColor);
3067 for (
int x = 0; x <
width; x++)
3069 for (
int y = 0; y <
height; y++)
3074 DrawRegionConstraint(display, regionConstraints[x][y], pt);
3079 template<
int w
idth,
int height>
3082 if (s.
path.size() == 0)
3086 display.
FillCircle(GetScreenCoord(start[0].first, start[0].second), lineWidth * 3.f, drawColor);
3087 for (
int x = 1; x < s.
path.size(); x++)
3092 DoLine(display, p1, p2, drawColor);
3096 display.
FillCircle(p1, lineWidth, drawColor);
3098 display.
FillCircle(p2, lineWidth, drawColor);
3104 template<
int w
idth,
int height>
3112 assert((iws.
ws.path.size() == 0));
3114 display.
FrameCircle(GetScreenCoord(start[0].first, start[0].second), lineWidth * 3.f * iws.
frac, drawColor,
3120 Draw(display, iws.
ws);
3127 p2 = p1 + (p2 - p1) * iws.
frac;
3128 DoLine(display, p1, p2, drawColor);
3129 display.
FillCircle(p2, lineWidth, drawColor);
3130 display.
FillCircle(p2, lineWidth * 0.5f, lineColor);
3135 display.
FillCircle(p2, lineWidth * 0.5f, lineColor);
3139 template<
int w
idth,
int height>
3145 template<
int w
idth,
int height>
3151 #endif // HOG2_ENVIRONMENTS_WITNESS_H