61 if ((y < 0) || (x < 0) || (z < 0) || (y >
m_height - 1) || (x >
m_width - 1)
76 if ((y < 0) || (x < 0) || (z < 0) || (y >
m_height - 1) || (x >
m_width - 1)
86 if ((y < 0) || (x < 0) || (z < 0) || (y >
m_height - 1) || (x >
m_width - 1)
96 if ((y < 0) || (x < 0) || (z < 0) || (y >
m_height - 1) || (x >
m_width - 1)
106 if ((y < 0) || (x < 0) || (z < 0) || (y >
m_height - 1) || (x >
m_width - 1)
116 if ((y < 0) || (x < 0) || (z < 0) || (y >
m_height - 1) || (x >
m_width - 1)
126 if ((i >= MoveList.size()) || (i < 0)) {
127 qDebug() <<
"Attempt to access GameData::MoveListData with invalid index";
136 if ((i >= MoveList.size()) || (i < 0)) {
147 numTilesToGenerate = 0;
149 for (
int z = 0; z <
m_depth; z++) {
150 for (
int y = 0; y <
m_height; y++) {
151 for (
int x = 0; x <
m_width; x++) {
154 tilePositions[numTilesToGenerate].x = x;
155 tilePositions[numTilesToGenerate].y = y;
156 tilePositions[numTilesToGenerate].e = z;
157 tilePositions[numTilesToGenerate].f = 254;
158 numTilesToGenerate++;
172 for (
int i = 0; i < numTilesToGenerate; i++) {
175 int x = tilePositions[i].x;
176 int y = tilePositions[i].y;
177 int z = tilePositions[i].e;
180 positionDepends[i].lhs_dep[0] = tileAt(x - 1, y, z);
181 positionDepends[i].lhs_dep[1] = tileAt(x - 1, y + 1, z);
184 if (positionDepends[i].lhs_dep[1] == positionDepends[i].lhs_dep[0]) {
185 positionDepends[i].lhs_dep[1] = -1;
189 positionDepends[i].rhs_dep[0] = tileAt(x + 2, y, z);
190 positionDepends[i].rhs_dep[1] = tileAt(x + 2, y + 1, z);
193 if (positionDepends[i].rhs_dep[1] == positionDepends[i].rhs_dep[0]) {
194 positionDepends[i].rhs_dep[1] = -1;
198 positionDepends[i].turn_dep[0] = tileAt(x, y, z + 1);
199 positionDepends[i].turn_dep[1] = tileAt(x + 1, y, z + 1);
200 positionDepends[i].turn_dep[2] = tileAt(x + 1, y + 1, z + 1);
201 positionDepends[i].turn_dep[3] = tileAt(x, y + 1, z + 1);
204 for (
int j = 0; j < 3; j++) {
205 for (
int k = j + 1; k < 4; k++) {
206 if (positionDepends[i].turn_dep[j] == positionDepends[i].turn_dep[k]) {
207 positionDepends[i].turn_dep[k] = -1;
213 positionDepends[i].place_dep[0] = tileAt(x, y, z - 1);
214 positionDepends[i].place_dep[1] = tileAt(x + 1, y, z - 1);
215 positionDepends[i].place_dep[2] = tileAt(x + 1, y + 1, z - 1);
216 positionDepends[i].place_dep[3] = tileAt(x, y + 1, z - 1);
219 for (
int j = 0; j < 3; j++) {
220 for (
int k = j + 1; k < 4; k++) {
221 if (positionDepends[i].place_dep[j] == positionDepends[i].place_dep[k]) {
222 positionDepends[i].place_dep[k] = -1;
228 positionDepends[i].filled =
false;
229 positionDepends[i].free =
false;
233 int GameData::tileAt(
int x,
int y,
int z)
240 for (
int i = 0; i < numTilesToGenerate; i++) {
241 if (tilePositions[i].e == z) {
242 if ((tilePositions[i].x == x && tilePositions[i].y == y)
243 || (tilePositions[i].x == x - 1 && tilePositions[i].y == y)
244 || (tilePositions[i].x == x - 1 && tilePositions[i].y == y - 1)
245 || (tilePositions[i].x == x && tilePositions[i].y == y - 1)) {
254 bool GameData::generateSolvableGame()
258 for (
int i = 0; i < numTilesToGenerate; i++) {
260 int position, cnt = 0;
263 position = (int)
random.getLong(numTilesToGenerate);
265 if (cnt++ > (numTilesToGenerate*numTilesToGenerate)) {
268 }
while (tilePositions[position].e != 0);
272 if (onlyFreeInLine(position)) {
273 positionDepends[position].free =
true;
279 for (
int i = 0; i < numTilesToGenerate; i++) {
280 if (tilePositions[i].e == 0 && onlyFreeInLine(i)) {
281 positionDepends[i].free =
true;
286 int lastPosition = -1;
291 for (
int i = 0; i < numTilesToGenerate; i++) {
294 if ((i % 144) == 0) {
316 if ((position = selectPosition(lastPosition)) < 0) {
320 if (i < numTilesToGenerate - 1) {
321 if ((position2 = selectPosition(lastPosition)) < 0) {
324 if (tilePositions[position2].e > tilePositions[position].e) {
325 position = position2;
330 placeTile(position, tilePair[i % 144]);
333 lastPosition = position;
340 bool GameData::onlyFreeInLine(
int position)
357 nextLeft[lin++] = position;
361 if (positionDepends[w].free || positionDepends[w].filled) {
365 if ((i = positionDepends[w].lhs_dep[0]) != -1) {
371 if ((i = positionDepends[w].lhs_dep[1]) != -1 && i0 != i) {
379 nextRight[rin++] = position;
382 w = nextRight[out++];
384 if (positionDepends[w].free || positionDepends[w].filled) {
388 if ((i = positionDepends[w].rhs_dep[0]) != -1) {
389 nextRight[rin++] = i;
394 if ((i = positionDepends[w].rhs_dep[1]) != -1 && i0 != i) {
395 nextRight[rin++] = i;
403 int GameData::selectPosition(
int lastPosition)
405 int position, cnt = 0;
406 bool goodPosition =
false;
409 while (!goodPosition) {
413 position =
random.getLong(numTilesToGenerate);
415 if (cnt++ > (numTilesToGenerate*numTilesToGenerate)) {
418 }
while (!positionDepends[position].free);
424 if (lastPosition != -1) {
427 for (
int i = 0; i < 4; i++) {
428 if (positionDepends[position].place_dep[i] == lastPosition) {
429 goodPosition =
false;
433 for (
int i = 0; i < 2; i++) {
434 if ((positionDepends[position].lhs_dep[i] == lastPosition)
435 || (positionDepends[position].rhs_dep[i] == lastPosition)) {
436 goodPosition =
false;
445 void GameData::placeTile(
int position,
int tile)
448 tilePositions[position].f = tile;
449 putTile(tilePositions[position]);
455 positionDepends[position].filled =
true;
456 positionDepends[position].free =
false;
461 for (
int i = 0; i < 4; i++) {
462 if ((depend = positionDepends[position].turn_dep[i]) != -1) {
463 updateDepend(depend);
467 for (
int i = 0; i < 2; i++) {
468 if ((depend = positionDepends[position].lhs_dep[i]) != -1) {
469 updateDepend(depend);
472 if ((depend = positionDepends[position].rhs_dep[i]) != -1) {
473 updateDepend(depend);
478 void GameData::updateDepend(
int position)
484 if (position >= 0 && !positionDepends[position].filled) {
489 for (
int i = 0; i < 4; i++) {
490 if ((depend = positionDepends[position].place_dep[i]) != -1) {
491 if (!positionDepends[depend].filled) {
499 if (onlyFreeInLine(position)) {
500 positionDepends[position].free =
true;
506 bool lfilled =
false;
509 if ((positionDepends[position].lhs_dep[0] != -1)
510 || (positionDepends[position].lhs_dep[1] != -1)) {
515 for (
int i = 0; i < 2; i++) {
516 if ((depend = positionDepends[position].lhs_dep[i]) != -1) {
517 if (!positionDepends[depend].filled) {
525 bool rfilled =
false;
528 if ((positionDepends[position].rhs_dep[0] != -1)
529 || (positionDepends[position].rhs_dep[1] != -1)) {
534 for (
int i = 0; i < 2; i++) {
535 if ((depend = positionDepends[position].rhs_dep[i]) != -1) {
536 if (!positionDepends[depend].filled) {
545 positionDepends[position].free = (lfilled || rfilled);
552 for (
int i = 0; i < numTilesToGenerate; i++) {
555 int x = tilePositions[i].x;
556 int y = tilePositions[i].y;
557 int z = tilePositions[i].e;
563 positionDepends[i].filled =
false;
564 positionDepends[i].free =
false;
567 tilePositions[i].f = 254;
573 if (generateSolvableGame()) {
592 int remaining = numTilesToGenerate;
595 for (
int tile = 0; tile < numTilesToGenerate; tile += 2) {
600 p2 = p1 =
random.getLong(remaining - 2);
604 p2 =
random.getLong(remaining - 2);
612 if ((tilePositions[p1].y == tilePositions[p2].y)
613 && (tilePositions[p1].e == tilePositions[p2].e)) {
629 a = tilePositions[p1];
630 b = tilePositions[p2];
632 tilePositions[p1] = tilePositions[remaining - 1];
633 tilePositions[p2] = tilePositions[remaining - 2];
649 a.
f = tilePair[tilesUsed];
650 b.
f = tilePair[tilesUsed + 1];
653 if (tilesUsed >= 144) {
658 void GameData::randomiseFaces()
664 for (nr = 0; nr < 9 * 4; ++nr) {
668 for (nr = 0; nr < 9 * 4; ++nr) {
672 for (nr = 0; nr < 9 * 4; ++nr) {
673 tilePair[numAlloced++] =
TILE_ROD + (nr / 4);
676 for (nr = 0; nr < 4; ++nr) {
680 for (nr = 0; nr < 4; ++nr) {
684 for (nr = 0; nr < 4 * 4; ++nr) {
685 tilePair[numAlloced++] =
TILE_WIND + (nr / 4);
688 for (nr = 0; nr < 3 * 4; ++nr) {
697 for (
int r = 0; r < 200; r++) {
709 UCHAR tmp = tilePair[at];
710 tilePair[at] = tilePair[to];
712 tmp = tilePair[at + 1];
713 tilePair[at + 1] = tilePair[to + 1];
714 tilePair[to + 1] = tmp;
723 tilesAllocated = numAlloced;
765 if (memcmp(&Pos1, &Pos2,
sizeof(
POSITION))) {
874 removedCharacter[
pos] = 0;
875 removedBamboo[
pos] = 0;
877 removedDragon[
pos % 3] = 0;
878 removedFlower[
pos % 4] = 0;
879 removedWind[
pos % 4] = 0;
880 removedSeason[
pos % 4] = 0;
888 for (
short E = 0; E <
m_depth; E++) {
889 for (
short Y = 0; Y <
m_height - 1; Y++) {
890 for (
short X = 0; X <
m_width - 1; X++) {
899 if (E < m_depth - 1) {
912 PosTable[Pos_Ende].e = E;
913 PosTable[Pos_Ende].y = Y;
914 PosTable[Pos_Ende].x = X;
915 PosTable[Pos_Ende].f =
BoardData(E, Y, X);
926 while (Pos_Ende <
MaxTileNum - 1 && iPosCount < m_maxTiles - 2) {
927 for (
short Pos = Pos_Ende + 1; Pos <
MaxTileNum; Pos++) {
929 if (iPosCount < m_maxTiles - 2) {
930 PosTable[iPosCount++] = PosTable[Pos_Ende];
931 PosTable[iPosCount++] = PosTable[Pos];
939 if (iPosCount >= 2) {
941 short Pos =
random.getLong(iPosCount) & -2;
942 posA = PosTable[Pos];
943 posB = PosTable[Pos + 1];
955 for (
short E = 0; E <
m_depth; E++) {
956 for (
short Y = 0; Y <
m_height - 1; Y++) {
957 for (
short X = 0; X <
m_width - 1; X++) {
966 if (E < m_depth - 1) {
979 PosTable[Pos_Ende].e = E;
980 PosTable[Pos_Ende].y = Y;
981 PosTable[Pos_Ende].x = X;
982 PosTable[Pos_Ende].f =
BoardData(E, Y, X);
989 while (Pos_Ende <
MaxTileNum - 1 && iPosCount < m_maxTiles - 2) {
990 for (
short Pos = Pos_Ende + 1; Pos <
MaxTileNum; Pos++) {
992 if (iPosCount < m_maxTiles - 2) {
993 PosTable[iPosCount++] = PosTable[Pos_Ende];
994 PosTable[iPosCount++] = PosTable[Pos];
1002 return iPosCount / 2;
1009 for (
short E = 0; E <
m_depth; E++) {
1010 for (
short Y = 0; Y <
m_height - 1; Y++) {
1011 for (
short X = 0; X <
m_width - 1; X++) {
1020 if (E < m_depth - 1) {
1032 PosTable[Pos].e = E;
1033 PosTable[Pos].y = Y;
1034 PosTable[Pos].x = X;
1089 out << (quint16) thispos.
e;
1090 out << (quint16) thispos.
y;
1091 out << (quint16) thispos.
x;
1092 out << (quint16) thispos.
f;
1104 for (
int e = 0; e <
m_depth; e++) {
1105 for (
int y = 0; y <
m_height; y++) {
1106 for (
int x = 0; x <
m_width; x++) {
1108 PosTable[count].e = e;
1109 PosTable[count].y = y;
1110 PosTable[count].x = x;
1120 for (
int ran = 0; ran < 400; ran++) {
1121 int pos1 =
random.getLong(count);
1122 int pos2 =
random.getLong(count);
1128 BYTE f = PosTable[pos1].f;
1129 PosTable[pos1].f = PosTable[pos2].f;
1130 PosTable[pos2].f = f;
1134 for (
int p = 0; p < count; p++) {
void putTile(short e, short y, short x, UCHAR f)
Method Description.
void generateTilePositions()
int m_height
Member Description.
void generatePositionDepends()
void initialiseRemovedTiles()
USHORT e
Member Description.
void copyBoardLayout(UCHAR *to, unsigned short &numTiles)
Description.
char * getMaskBytes()
Method Description.
GameData(BoardLayout *boardlayout)
Constructor.
void clearRemovedTilePair(POSITION &a, POSITION &b)
void setMoveListData(short i, POSITION &value)
Method Description.
POSITION & MoveListData(short i)
Method Description.
~GameData()
Default Destructor.
bool isCharacter(UCHAR t)
bool generateStartPosition2()
USHORT x
Member Description.
UCHAR MaskData(short z, short y, short x)
Method Description.
UCHAR BoardData(short z, short y, short x)
Method Description.
int m_width
Member Description.
bool saveToStream(QDataStream &out)
bool loadFromStream(QDataStream &in)
USHORT y
Member Description.
short findAllMatchingTiles(POSITION &posA)
bool tilePresent(int z, int y, int x)
Method Description.
bool isMatchingTile(POSITION &Pos1, POSITION &Pos2)
int m_depth
Member Description.
void setBoardData(short z, short y, short x, UCHAR value)
Method Description.
bool findMove(POSITION &posA, POSITION &posB)
This class implements methods for loading and manipulating board.
UCHAR HighlightData(short z, short y, short x)
Method Description.
void setHighlightData(short z, short y, short x, UCHAR value)
Method Description.
bool partTile(int z, int y, int x)
Method Description.
bool isFlower(UCHAR Tile)
bool isSeason(UCHAR Tile)
USHORT f
Member Description.
void setRemovedTilePair(POSITION &a, POSITION &b)