00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "GameData.h"
00020 #include <QtDebug>
00021
00022
00023 GameData::GameData (BoardLayout * boardlayout) {
00024 m_width = boardlayout->m_width;
00025 m_height = boardlayout->m_height;
00026 m_depth = boardlayout->m_depth;
00027 m_maxTiles = (m_width*m_height*m_depth)/4;
00028
00029 Highlight = QByteArray(m_width*m_height*m_depth, 0);
00030 Mask = QByteArray(m_width*m_height*m_depth, 0);
00031 Board = QByteArray(m_width*m_height*m_depth, 0);
00032 POSITION e;
00033 MoveList = QVector<POSITION>(m_maxTiles, e);
00034 tilePositions = QVector<POSITION>(m_maxTiles, e);
00035 PosTable = QVector<POSITION>(m_maxTiles, e);
00036 positionDepends = QVector<DEPENDENCY>(m_maxTiles);
00037
00038
00039 boardlayout->copyBoardLayout((UCHAR *) getMaskBytes(), MaxTileNum);
00040 }
00041
00042 GameData::~GameData () {
00043
00044 }
00045
00046 void GameData::putTile( short e, short y, short x, UCHAR f ){
00047 setBoardData(e,y,x,f);
00048 setBoardData(e,y+1,x,f);
00049 setBoardData(e,y+1,x+1,f);
00050 setBoardData(e,y,x+1,f);
00051 }
00052
00053 bool GameData::tilePresent(int z, int y, int x) {
00054 if ((y<0)||(x<0)||(z<0)||(y>m_height-1)||(x>m_width-1)||(z>m_depth-1)) return false;
00055 return(BoardData(z,y,x)!=0 && MaskData(z,y,x) == '1');
00056 }
00057
00058 bool GameData::partTile(int z, int y, int x) {
00059 return (BoardData(z,y,x) != 0);
00060 }
00061
00062 UCHAR GameData::MaskData(short z, short y, short x){
00063 if ((y<0)||(x<0)||(z<0)||(y>m_height-1)||(x>m_width-1)||(z>m_depth-1)) return 0;
00064 return Mask.at((z*m_width*m_height)+(y*m_width)+x);
00065 }
00066
00067 UCHAR GameData::HighlightData(short z, short y, short x){
00068 if ((y<0)||(x<0)||(z<0)||(y>m_height-1)||(x>m_width-1)||(z>m_depth-1)) return 0;
00069 return Highlight.at((z*m_width*m_height)+(y*m_width)+x);
00070 }
00071
00072 void GameData::setHighlightData(short z, short y, short x, UCHAR value) {
00073 if ((y<0)||(x<0)||(z<0)||(y>m_height-1)||(x>m_width-1)||(z>m_depth-1)) return ;
00074 Highlight[(z*m_width*m_height)+(y*m_width)+x] = value;
00075 }
00076
00077 UCHAR GameData::BoardData(short z, short y, short x){
00078 if ((y<0)||(x<0)||(z<0)||(y>m_height-1)||(x>m_width-1)||(z>m_depth-1)) return 0;
00079 return Board.at((z*m_width*m_height)+(y*m_width)+x);
00080 }
00081
00082 void GameData::setBoardData(short z, short y, short x, UCHAR value) {
00083 if ((y<0)||(x<0)||(z<0)||(y>m_height-1)||(x>m_width-1)||(z>m_depth-1)) return ;
00084 Board[(z*m_width*m_height)+(y*m_width)+x] = value;
00085 }
00086
00087 POSITION& GameData::MoveListData(short i) {
00088 if ((i>=MoveList.size())|| (i<0)) {
00089 qDebug() << "Attempt to access GameData::MoveListData with invalid index";
00090 i=0 ;
00091 }
00092 return MoveList[i];
00093 }
00094
00095 void GameData::setMoveListData(short i, POSITION& value){
00096 if ((i>=MoveList.size()) || (i<0)) return ;
00097 MoveList[i] = value;
00098 }
00099
00100
00101
00102
00103
00104 void GameData::generateTilePositions() {
00105
00106 numTilesToGenerate = 0;
00107
00108 for (int z=0; z< m_depth; z++) {
00109 for (int y=0; y< m_height; y++) {
00110 for (int x=0; x< m_width; x++) {
00111 setBoardData(z,y,x,0);
00112 if (MaskData(z,y,x) == '1') {
00113 tilePositions[numTilesToGenerate].x = x;
00114 tilePositions[numTilesToGenerate].y = y;
00115 tilePositions[numTilesToGenerate].e = z;
00116 tilePositions[numTilesToGenerate].f = 254;
00117 numTilesToGenerate++;
00118 }
00119 }
00120 }
00121 }
00122 }
00123
00124
00125
00126
00127
00128 void GameData::generatePositionDepends() {
00129
00130
00131 for (int i = 0; i < numTilesToGenerate; i++) {
00132
00133
00134 int x = tilePositions[i].x;
00135 int y = tilePositions[i].y;
00136 int z = tilePositions[i].e;
00137
00138
00139 positionDepends[i].lhs_dep[0] = tileAt(x-1, y, z);
00140 positionDepends[i].lhs_dep[1] = tileAt(x-1, y+1, z);
00141
00142
00143 if (positionDepends[i].lhs_dep[1] == positionDepends[i].lhs_dep[0]) {
00144 positionDepends[i].lhs_dep[1] = -1;
00145 }
00146
00147
00148 positionDepends[i].rhs_dep[0] = tileAt(x+2, y, z);
00149 positionDepends[i].rhs_dep[1] = tileAt(x+2, y+1, z);
00150
00151
00152 if (positionDepends[i].rhs_dep[1] == positionDepends[i].rhs_dep[0]) {
00153 positionDepends[i].rhs_dep[1] = -1;
00154 }
00155
00156
00157 positionDepends[i].turn_dep[0] = tileAt(x, y, z+1);
00158 positionDepends[i].turn_dep[1] = tileAt(x+1, y, z+1);
00159 positionDepends[i].turn_dep[2] = tileAt(x+1, y+1, z+1);
00160 positionDepends[i].turn_dep[3] = tileAt(x, y+1, z+1);
00161
00162
00163 for (int j = 0; j < 3; j++) {
00164 for (int k = j+1; k < 4; k++) {
00165 if (positionDepends[i].turn_dep[j] ==
00166 positionDepends[i].turn_dep[k]) {
00167 positionDepends[i].turn_dep[k] = -1;
00168 }
00169 }
00170 }
00171
00172
00173 positionDepends[i].place_dep[0] = tileAt(x, y, z-1);
00174 positionDepends[i].place_dep[1] = tileAt(x+1, y, z-1);
00175 positionDepends[i].place_dep[2] = tileAt(x+1, y+1, z-1);
00176 positionDepends[i].place_dep[3] = tileAt(x, y+1, z-1);
00177
00178
00179 for (int j = 0; j < 3; j++) {
00180 for (int k = j+1; k < 4; k++) {
00181 if (positionDepends[i].place_dep[j] ==
00182 positionDepends[i].place_dep[k]) {
00183 positionDepends[i].place_dep[k] = -1;
00184 }
00185 }
00186 }
00187
00188
00189 positionDepends[i].filled = false;
00190 positionDepends[i].free = false;
00191 }
00192 }
00193
00194
00195
00196
00197
00198
00199 int GameData::tileAt(int x, int y, int z) {
00200
00201 for (int i = 0; i < numTilesToGenerate; i++) {
00202 if (tilePositions[i].e == z) {
00203 if ((tilePositions[i].x == x && tilePositions[i].y == y) ||
00204 (tilePositions[i].x == x-1 && tilePositions[i].y == y) ||
00205 (tilePositions[i].x == x-1 && tilePositions[i].y == y-1) ||
00206 (tilePositions[i].x == x && tilePositions[i].y == y-1)) {
00207
00208 return i;
00209 }
00210 }
00211 }
00212 return -1;
00213 }
00214
00215
00216
00217 bool GameData::generateSolvableGame() {
00218
00219
00220
00221 for (int i = 0; i < numTilesToGenerate; i++) {
00222
00223
00224 int position, cnt = 0;
00225 do {
00226 position = (int) random.getLong(numTilesToGenerate);
00227 if (cnt++ > (numTilesToGenerate*numTilesToGenerate)) {
00228 return false;
00229 }
00230 } while (tilePositions[position].e != 0);
00231
00232
00233
00234 if (onlyFreeInLine(position)) {
00235 positionDepends[position].free = true;
00236 }
00237 }
00238
00239
00240
00241 for (int i = 0; i < numTilesToGenerate; i++) {
00242 if (tilePositions[i].e == 0 && onlyFreeInLine(i)) {
00243 positionDepends[i].free = true;
00244 }
00245 }
00246
00247
00248 int lastPosition = -1;
00249 int position = -1;
00250 int position2 = -1;
00251
00252
00253 for (int i = 0; i < numTilesToGenerate; i++) {
00254
00255
00256 if ((i % 144) == 0) {
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267 randomiseFaces();
00268 }
00269
00270
00271
00272 if ((i & 1) == 0) {
00273 lastPosition = -1;
00274 }
00275
00276
00277
00278 if ((position = selectPosition(lastPosition)) < 0) {
00279 return false;
00280 }
00281 if (i < numTilesToGenerate-1) {
00282 if ((position2 = selectPosition(lastPosition)) < 0) {
00283 return false;
00284 }
00285 if (tilePositions[position2].e > tilePositions[position].e) {
00286 position = position2;
00287 }
00288 }
00289
00290
00291 placeTile(position, tilePair[i % 144]);
00292
00293
00294 lastPosition = position;
00295 }
00296
00297
00298 return true;
00299 }
00300
00301
00302
00303
00304
00305 bool GameData::onlyFreeInLine(int position) {
00306
00307 int i, i0, w;
00308 int lin, rin, out;
00309
00310
00311 QVector<int> nextLeft = QVector<int>(m_maxTiles, 0);
00312 QVector<int> nextRight = QVector<int>(m_maxTiles, 0);
00313
00314
00315 lin = 0;
00316 out = 0;
00317 nextLeft[lin++] = position;
00318 do {
00319 w = nextLeft[out++];
00320 if (positionDepends[w].free || positionDepends[w].filled) {
00321 return false;
00322 }
00323 if ((i = positionDepends[w].lhs_dep[0]) != -1) {
00324 nextLeft[lin++] = i;
00325 }
00326 i0 = i;
00327 if ((i = positionDepends[w].lhs_dep[1]) != -1 && i0 != i) {
00328 nextLeft[lin++] = i;
00329 }
00330 }
00331 while (lin > out) ;
00332
00333
00334 rin = 0;
00335 out = 0;
00336 nextRight[rin++] = position;
00337 do {
00338 w = nextRight[out++];
00339 if (positionDepends[w].free || positionDepends[w].filled) {
00340 return false;
00341 }
00342 if ((i = positionDepends[w].rhs_dep[0]) != -1) {
00343 nextRight[rin++] = i;
00344 }
00345 i0 = i;
00346 if ((i = positionDepends[w].rhs_dep[1]) != -1 && i0 != i) {
00347 nextRight[rin++] = i;
00348 }
00349 }
00350 while (rin > out) ;
00351
00352
00353 return true;
00354 }
00355
00356
00357 int GameData::selectPosition(int lastPosition) {
00358
00359 int position, cnt = 0;
00360 bool goodPosition = false;
00361
00362
00363 while (!goodPosition) {
00364
00365
00366 do {
00367 position = random.getLong(numTilesToGenerate);
00368 if (cnt++ > (numTilesToGenerate*numTilesToGenerate)) {
00369 return -1;
00370 }
00371 } while (!positionDepends[position].free);
00372
00373
00374 goodPosition = true;
00375
00376
00377 if (lastPosition != -1) {
00378
00379
00380 for (int i = 0; i < 4; i++) {
00381 if (positionDepends[position].place_dep[i] == lastPosition) {
00382 goodPosition = false;
00383 }
00384 }
00385 for (int i = 0; i < 2; i++) {
00386 if ((positionDepends[position].lhs_dep[i] == lastPosition) ||
00387 (positionDepends[position].rhs_dep[i] == lastPosition)) {
00388 goodPosition = false;
00389 }
00390 }
00391 }
00392 }
00393
00394 return position;
00395 }
00396
00397
00398 void GameData::placeTile(int position, int tile) {
00399
00400
00401 tilePositions[position].f = tile;
00402 putTile(tilePositions[position]);
00403
00404
00405
00406
00407
00408 positionDepends[position].filled = true;
00409 positionDepends[position].free = false;
00410
00411
00412 int depend;
00413 for (int i = 0; i < 4; i++) {
00414 if ((depend = positionDepends[position].turn_dep[i]) != -1) {
00415 updateDepend(depend);
00416 }
00417 }
00418 for (int i = 0; i < 2; i++) {
00419 if ((depend = positionDepends[position].lhs_dep[i]) != -1) {
00420 updateDepend(depend);
00421 }
00422 if ((depend = positionDepends[position].rhs_dep[i]) != -1) {
00423 updateDepend(depend);
00424 }
00425 }
00426 }
00427
00428
00429
00430
00431 void GameData::updateDepend(int position) {
00432
00433
00434 if (position >= 0 && !positionDepends[position].filled) {
00435
00436
00437
00438 int depend;
00439 for (int i = 0; i < 4; i++) {
00440 if ((depend = positionDepends[position].place_dep[i]) != -1) {
00441 if (!positionDepends[depend].filled) {
00442 return ;
00443 }
00444 }
00445 }
00446
00447
00448
00449 if (onlyFreeInLine(position)) {
00450 positionDepends[position].free = true;
00451 return;
00452 }
00453
00454
00455 bool lfilled = false;
00456
00457
00458 if ((positionDepends[position].lhs_dep[0] != -1) ||
00459 (positionDepends[position].lhs_dep[1] != -1)) {
00460
00461
00462 lfilled = true;
00463
00464 for (int i = 0; i < 2; i++) {
00465 if ((depend = positionDepends[position].lhs_dep[i]) != -1) {
00466 if (!positionDepends[depend].filled) {
00467 lfilled = false;
00468 }
00469 }
00470 }
00471 }
00472
00473
00474 bool rfilled = false;
00475
00476
00477 if ((positionDepends[position].rhs_dep[0] != -1) ||
00478 (positionDepends[position].rhs_dep[1] != -1)) {
00479
00480
00481 rfilled = true;
00482
00483 for (int i = 0; i < 2; i++) {
00484 if ((depend = positionDepends[position].rhs_dep[i]) != -1) {
00485 if (!positionDepends[depend].filled) {
00486 rfilled = false;
00487 }
00488 }
00489 }
00490 }
00491
00492
00493
00494 positionDepends[position].free = (lfilled || rfilled);
00495 }
00496 }
00497
00498
00499
00500 bool GameData::generateStartPosition2() {
00501
00502
00503 for (int i = 0; i < numTilesToGenerate; i++) {
00504
00505
00506 int x = tilePositions[i].x;
00507 int y = tilePositions[i].y;
00508 int z = tilePositions[i].e;
00509
00510
00511 setBoardData(z,y,x,0);
00512
00513
00514 positionDepends[i].filled = false;
00515 positionDepends[i].free = false;
00516
00517
00518 tilePositions[i].f = 254;
00519 }
00520
00521
00522
00523
00524 if (generateSolvableGame()) {
00525 TileNum = MaxTileNum;
00526 return true;
00527 } else {
00528 return false;
00529 }
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542 int remaining = numTilesToGenerate;
00543 randomiseFaces();
00544
00545 for (int tile=0; tile <numTilesToGenerate; tile+=2) {
00546 int p1;
00547 int p2;
00548
00549 if (remaining > 2) {
00550 p2 = p1 = random.getLong(remaining-2);
00551 int bail = 0;
00552 while (p1 == p2) {
00553 p2 = random.getLong(remaining-2);
00554
00555 if (bail >= 100) {
00556 if (p1 != p2) {
00557 break;
00558 }
00559 }
00560 if ((tilePositions[p1].y == tilePositions[p2].y) &&
00561 (tilePositions[p1].e == tilePositions[p2].e)) {
00562
00563 bail++;
00564 p2=p1;
00565 continue;
00566 }
00567 }
00568 } else {
00569 p1 = 0;
00570 p2 = 1;
00571 }
00572 POSITION a, b;
00573 a = tilePositions[p1];
00574 b = tilePositions[p2];
00575 tilePositions[p1] = tilePositions[remaining - 1];
00576 tilePositions[p2] = tilePositions[remaining - 2];
00577 remaining -= 2;
00578
00579 getFaces(a, b);
00580 putTile(a);
00581 putTile(b);
00582 }
00583
00584 TileNum = MaxTileNum;
00585 return 1;
00586 }
00587
00588 void GameData::getFaces(POSITION &a, POSITION &b) {
00589 a.f = tilePair[tilesUsed];
00590 b.f = tilePair[tilesUsed+1];
00591 tilesUsed += 2;
00592
00593 if (tilesUsed >= 144) {
00594 randomiseFaces();
00595 }
00596 }
00597
00598 void GameData::randomiseFaces() {
00599 int nr;
00600 int numAlloced=0;
00601
00602
00603 for( nr=0; nr<9*4; nr++)
00604 tilePair[numAlloced++] = TILE_CHARACTER+(nr/4);
00605 for( nr=0; nr<9*4; nr++)
00606 tilePair[numAlloced++] = TILE_BAMBOO+(nr/4);
00607 for( nr=0; nr<9*4; nr++)
00608 tilePair[numAlloced++] = TILE_ROD+(nr/4);
00609 for( nr=0; nr<4; nr++)
00610 tilePair[numAlloced++] = TILE_FLOWER+nr;
00611 for( nr=0; nr<4; nr++)
00612 tilePair[numAlloced++] = TILE_SEASON+nr;
00613 for( nr=0; nr<4*4; nr++)
00614 tilePair[numAlloced++] = TILE_WIND+(nr/4);
00615 for( nr=0; nr<3*4; nr++)
00616 tilePair[numAlloced++] = TILE_DRAGON+(nr/4);
00617
00618
00619
00620
00621
00622 int at=0;
00623 int to=0;
00624 for (int r=0; r<200; r++) {
00625
00626
00627 to=at;
00628 while (to==at) {
00629 to = random.getLong(144);
00630
00631 if ((to & 1) != 0)
00632 to--;
00633
00634 }
00635 UCHAR tmp = tilePair[at];
00636 tilePair[at] = tilePair[to];
00637 tilePair[to] = tmp;
00638 tmp = tilePair[at+1];
00639 tilePair[at+1] = tilePair[to+1];
00640 tilePair[to+1] = tmp;
00641
00642
00643 at+=2;
00644 if (at >= 144)
00645 at =0;
00646 }
00647
00648 tilesAllocated = numAlloced;
00649 tilesUsed = 0;
00650 }
00651
00652
00653
00654 bool isFlower( UCHAR Tile )
00655 {
00656 return( Tile >= TILE_FLOWER && Tile <=TILE_FLOWER+3 );
00657 }
00658 bool isSeason( UCHAR Tile )
00659 {
00660 return( Tile >= TILE_SEASON && Tile <=TILE_SEASON+3 );
00661 }
00662 bool isBamboo(UCHAR t) {
00663 return( t >= TILE_BAMBOO && t <TILE_BAMBOO+9);
00664 }
00665 bool isCharacter(UCHAR t) {
00666 return( t <TILE_CHARACTER + 9);
00667 }
00668 bool isRod(UCHAR t) {
00669 return( t >= TILE_ROD && t <TILE_ROD + 9);
00670 }
00671 bool isDragon(UCHAR t) {
00672 return( t >= TILE_DRAGON && t < TILE_DRAGON +3);
00673 }
00674 bool isWind(UCHAR t) {
00675 return( t >= TILE_WIND && t < TILE_WIND +4);
00676 }
00677
00678 bool GameData::isMatchingTile( POSITION& Pos1, POSITION& Pos2 )
00679 {
00680
00681 if( memcmp( &Pos1, &Pos2, sizeof(POSITION) ) )
00682 {
00683 UCHAR FA = Pos1.f;
00684 UCHAR FB = Pos2.f;
00685
00686 if( (FA == FB)
00687 || ( isFlower( FA ) && isFlower( FB ) )
00688 || ( isSeason( FA ) && isSeason( FB ) ) )
00689 return( true );
00690 }
00691 return( false );
00692 }
00693
00694
00695 void GameData::setRemovedTilePair(POSITION &a, POSITION &b) {
00696
00697 if (isFlower(a.f)) {
00698 removedFlower[a.f-TILE_FLOWER]++;
00699 removedFlower[b.f-TILE_FLOWER]++;
00700 return;
00701 }
00702
00703 if (isSeason(a.f)) {
00704 removedSeason[a.f-TILE_SEASON]++;
00705 removedSeason[b.f-TILE_SEASON]++;
00706 return;
00707 }
00708 if (isCharacter(a.f)) {
00709 removedCharacter[a.f - TILE_CHARACTER]+=2;
00710 return;
00711 }
00712
00713 if (isBamboo(a.f)) {
00714 removedBamboo[a.f - TILE_BAMBOO]+=2;
00715 return;
00716 }
00717 if (isRod(a.f)) {
00718 removedRod[a.f - TILE_ROD]+=2;
00719 return;
00720 }
00721 if (isDragon(a.f)){
00722 removedDragon[a.f - TILE_DRAGON]+=2;
00723 return;
00724 }
00725 if (isWind(a.f)){
00726 removedWind[a.f - TILE_WIND]+=2;
00727 return;
00728 }
00729 }
00730
00731
00732 void GameData::clearRemovedTilePair(POSITION &a, POSITION &b) {
00733
00734 if (isFlower(a.f)) {
00735 removedFlower[a.f-TILE_FLOWER]--;
00736 removedFlower[b.f-TILE_FLOWER]--;
00737 return;
00738 }
00739
00740 if (isSeason(a.f)) {
00741 removedSeason[a.f-TILE_SEASON]--;
00742 removedSeason[b.f-TILE_SEASON]--;
00743 return;
00744 }
00745 if (isCharacter(a.f)) {
00746 removedCharacter[a.f - TILE_CHARACTER]-=2;
00747 return;
00748 }
00749
00750 if (isBamboo(a.f)) {
00751 removedBamboo[a.f - TILE_BAMBOO]-=2;
00752 return;
00753 }
00754 if (isRod(a.f)){
00755 removedRod[a.f - TILE_ROD]-=2;
00756 return;
00757 }
00758 if (isDragon(a.f)){
00759 removedDragon[a.f - TILE_DRAGON]-=2;
00760 return;
00761 }
00762 if (isWind(a.f)){
00763 removedWind[a.f - TILE_WIND]-=2;
00764 return;
00765 }
00766 }
00767
00768
00769
00770 void GameData::initialiseRemovedTiles() {
00771 for (int pos=0; pos<9; pos++) {
00772 removedCharacter[pos]=0;
00773 removedBamboo[pos]=0;
00774 removedRod[pos]=0;
00775 removedDragon[pos %3] = 0;
00776 removedFlower[pos % 4] = 0;
00777 removedWind[pos % 4] = 0;
00778 removedSeason[pos % 4] = 0;
00779
00780 }
00781
00782 }
00783
00784
00785
00786 bool GameData::findMove( POSITION& posA, POSITION& posB )
00787 {
00788 short Pos_Ende = MaxTileNum;
00789
00790 for( short E=0; E< m_depth; E++ )
00791 {
00792 for( short Y=0; Y< m_height-1; Y++ )
00793 {
00794 for( short X=0; X< m_width-1; X++ )
00795 {
00796 if( MaskData(E,Y,X) != (UCHAR) '1' )
00797 continue;
00798 if( ! BoardData(E,Y,X) )
00799 continue;
00800 if( E < m_depth-1 )
00801 {
00802 if( BoardData(E+1,Y,X) || BoardData(E+1,Y+1,X) ||
00803 BoardData(E+1,Y,X+1) || BoardData(E+1,Y+1,X+1) )
00804 continue;
00805 }
00806 if( X< m_width-2 && (BoardData(E,Y,X-1) || BoardData(E,Y+1,X-1)) &&
00807 (BoardData(E,Y,X+2) || BoardData(E,Y+1,X+2)) )
00808 continue;
00809
00810 Pos_Ende--;
00811 PosTable[Pos_Ende].e = E;
00812 PosTable[Pos_Ende].y = Y;
00813 PosTable[Pos_Ende].x = X;
00814 PosTable[Pos_Ende].f = BoardData(E,Y,X);
00815
00816
00817
00818
00819 }
00820 }
00821 }
00822
00823 short iPosCount = 0;
00824
00825
00826
00827
00828
00829 while( Pos_Ende < MaxTileNum-1 && iPosCount < m_maxTiles-2)
00830 {
00831 for( short Pos = Pos_Ende+1; Pos < MaxTileNum; Pos++)
00832 {
00833 if( isMatchingTile(PosTable[Pos], PosTable[Pos_Ende]) )
00834 {
00835 if (iPosCount < m_maxTiles-2) {
00836 PosTable[iPosCount++] = PosTable[Pos_Ende];
00837 PosTable[iPosCount++] = PosTable[Pos];
00838 }
00839 }
00840 }
00841 Pos_Ende++;
00842 }
00843
00844 if( iPosCount>=2 )
00845 {
00846 random.setSeed(0);
00847 short Pos = random.getLong(iPosCount) & -2;
00848 posA = PosTable[Pos];
00849 posB = PosTable[Pos+1];
00850
00851 return( true );
00852 }
00853 else
00854 return( false );
00855 }
00856
00857 int GameData::moveCount( )
00858 {
00859 short Pos_Ende = MaxTileNum;
00860
00861 for( short E=0; E< m_depth; E++ )
00862 {
00863 for( short Y=0; Y< m_height-1; Y++ )
00864 {
00865 for( short X=0; X< m_width-1; X++ )
00866 {
00867 if( MaskData(E,Y,X) != (UCHAR) '1' )
00868 continue;
00869 if( ! BoardData(E,Y,X) )
00870 continue;
00871 if( E < m_depth-1 )
00872 {
00873 if( BoardData(E+1,Y,X) || BoardData(E+1,Y+1,X) ||
00874 BoardData(E+1,Y,X+1) || BoardData(E+1,Y+1,X+1) )
00875 continue;
00876 }
00877 if( X< m_width-2 && (BoardData(E,Y,X-1) || BoardData(E,Y+1,X-1)) &&
00878 (BoardData(E,Y,X+2) || BoardData(E,Y+1,X+2)) )
00879 continue;
00880
00881 Pos_Ende--;
00882 PosTable[Pos_Ende].e = E;
00883 PosTable[Pos_Ende].y = Y;
00884 PosTable[Pos_Ende].x = X;
00885 PosTable[Pos_Ende].f = BoardData(E,Y,X);
00886
00887 }
00888 }
00889 }
00890
00891 short iPosCount = 0;
00892
00893 while( Pos_Ende < MaxTileNum-1 && iPosCount < m_maxTiles-2)
00894 {
00895 for( short Pos = Pos_Ende+1; Pos < MaxTileNum; Pos++)
00896 {
00897 if( isMatchingTile(PosTable[Pos], PosTable[Pos_Ende]) )
00898 {
00899 if (iPosCount < m_maxTiles-2) {
00900 PosTable[iPosCount++] = PosTable[Pos_Ende];
00901 PosTable[iPosCount++] = PosTable[Pos];
00902 }
00903 }
00904 }
00905 Pos_Ende++;
00906 }
00907
00908 return iPosCount/2;
00909 }
00910
00911
00912
00913
00914
00915 short GameData::findAllMatchingTiles( POSITION& posA )
00916 {
00917 short Pos = 0;
00918
00919 for( short E=0; E< m_depth; E++ )
00920 {
00921 for( short Y=0; Y< m_height-1; Y++ )
00922 {
00923 for( short X=0; X< m_width-1; X++ )
00924 {
00925 if( MaskData(E,Y,X) != (UCHAR) '1' )
00926 continue;
00927 if( ! BoardData(E,Y,X) )
00928 continue;
00929 if( E < m_depth-1 )
00930 {
00931 if( BoardData(E+1,Y,X) || BoardData(E+1,Y+1,X) ||
00932 BoardData(E+1,Y,X+1) || BoardData(E+1,Y+1,X+1) )
00933 continue;
00934 }
00935 if( X< m_width-2 && (BoardData(E,Y,X-1) || BoardData(E,Y+1,X-1)) &&
00936 (BoardData(E,Y,X+2) || BoardData(E,Y+1,X+2)) )
00937 continue;
00938
00939 PosTable[Pos].e = E;
00940 PosTable[Pos].y = Y;
00941 PosTable[Pos].x = X;
00942 PosTable[Pos].f = BoardData(E,Y,X);
00943
00944 if( isMatchingTile(posA, PosTable[Pos]) )
00945 Pos++;
00946 }
00947 }
00948 }
00949 return Pos;
00950 }
00951
00952 bool GameData::loadFromStream(QDataStream & in)
00953 {
00954 in >> Board;
00955 in >> Mask;
00956 in >> Highlight;
00957 in >> allow_undo;
00958 in >> allow_redo;
00959 in >> TileNum;
00960 in >> MaxTileNum;
00961
00962
00963 in >> m_maxTiles;
00964
00965
00966 for (int i = 0; i < m_maxTiles; ++i) {
00967 POSITION thispos;
00968 in >> thispos.e;
00969 in >> thispos.y;
00970 in >> thispos.x;
00971 in >> thispos.f;
00972 setMoveListData( i, thispos);
00973 }
00974 return true;
00975 }
00976
00977 bool GameData::saveToStream(QDataStream & out)
00978 {
00979 out << Board;
00980 out << Mask;
00981 out << Highlight;
00982 out << allow_undo;
00983 out << allow_redo;
00984 out << TileNum;
00985 out << MaxTileNum;
00986
00987 out << m_maxTiles;
00988
00989 for (int i = 0; i < m_maxTiles; ++i) {
00990 POSITION thispos = MoveList.at(i);
00991 out << (quint16) thispos.e;
00992 out << (quint16) thispos.y;
00993 out << (quint16) thispos.x;
00994 out << (quint16) thispos.f;
00995 }
00996
00997 return true;
00998 }
00999
01000 void GameData::shuffle() {
01001 int count = 0;
01002
01003
01004 for (int e=0; e<m_depth; e++) {
01005 for (int y=0; y<m_height; y++) {
01006 for (int x=0; x<m_width; x++) {
01007 if (BoardData(e,y,x) && MaskData(e,y,x) == '1') {
01008 PosTable[count].e = e;
01009 PosTable[count].y = y;
01010 PosTable[count].x = x;
01011 PosTable[count].f = BoardData(e,y,x);
01012 count++;
01013 }
01014 }
01015 }
01016
01017 }
01018
01019
01020
01021
01022 for (int ran=0; ran < 400; ran++) {
01023 int pos1 = random.getLong(count);
01024 int pos2 = random.getLong(count);
01025 if (pos1 == pos2)
01026 continue;
01027 BYTE f = PosTable[pos1].f;
01028 PosTable[pos1].f = PosTable[pos2].f;
01029 PosTable[pos2].f = f;
01030 }
01031
01032
01033 for (int p=0; p<count; p++)
01034 putTile(PosTable[p]);
01035 }