File indexing completed on 2024-04-28 07:51:25

0001 /***************************************************************************
0002 *   KBlocks, a falling blocks game by KDE                                *
0003 *   SPDX-FileCopyrightText: 2010 Zhongjie Cai <squall.leonhart.cai@gmail.com>       *
0004 *                                                                         *
0005 *   SPDX-License-Identifier: GPL-2.0-or-later
0006 ***************************************************************************/
0007 #include "KBlocksLayout.h"
0008 
0009 KBlocksLayout::KBlocksLayout(FieldInterface *pF, PieceInterface *pA, PieceInterface *pN)
0010 {
0011     mpGameField = pF;
0012     mpActivePiece = pA;
0013     mpNextPiece = pN;
0014 
0015     mPieceCellCount = mpActivePiece->getCellCount();
0016     mpLastPiecePos = new QPoint*[mPieceCellCount];
0017     for (int i = 0; i < mPieceCellCount; i++) {
0018         mpLastPiecePos[i] = new QPoint(0, 0);
0019     }
0020 
0021     mWidth = mpGameField->getWidth();
0022     mHeight = mpGameField->getHeight();
0023     boardInfo = new int *[mHeight];
0024     for (int i = 0; i < mHeight; i++) {
0025         boardInfo[i] = new int[mWidth];
0026         for (int j = 0; j < mWidth; j++) {
0027             boardInfo[i][j] = -1;
0028         }
0029     }
0030 
0031     prepareInfo = new int *[PREPARE_AREA_WIDTH];
0032     for (int i = 0; i < PREPARE_AREA_WIDTH; i++) {
0033         prepareInfo[i] = new int[PREPARE_AREA_WIDTH];
0034         for (int j = 0; j < PREPARE_AREA_WIDTH; j++) {
0035             prepareInfo[i][j] = -1;
0036         }
0037     }
0038 }
0039 
0040 KBlocksLayout::~KBlocksLayout()
0041 {
0042     for (int i = 0; i < mHeight; i++) {
0043         delete [] boardInfo[i];
0044     }
0045     delete [] boardInfo;
0046 
0047     for (int i = 0; i < PREPARE_AREA_WIDTH; i++) {
0048         delete [] prepareInfo[i];
0049     }
0050     delete [] prepareInfo;
0051 
0052     for (int i = 0; i < mPieceCellCount; i++) {
0053         delete mpLastPiecePos[i];
0054     }
0055     delete [] mpLastPiecePos;
0056 }
0057 
0058 void KBlocksLayout::beginUpdate(QList<int> *list)
0059 {
0060     int px = 0;
0061     int py = 0;
0062     list->clear();
0063     for (int i = 0; i < mPieceCellCount; i++) {
0064         px = mpLastPiecePos[i]->x();
0065         py = mpLastPiecePos[i]->y();
0066         list->append(px);
0067         list->append(py);
0068         if ((px >= 0) && (px < mWidth)
0069                 && (py >= 0) && (py < mHeight)) {
0070             boardInfo[py][px] = -1;
0071         }
0072     }
0073 }
0074 
0075 void KBlocksLayout::updateLayout(int type, const QList<int> &dataList)
0076 {
0077     switch (type) {
0078     case KBlocksLayout_Update_FreezePiece:
0079         updateFreezePiece(dataList);
0080         break;
0081     case KBlocksLayout_Update_RemoveLine:
0082         updateRemoveLine(dataList);
0083         break;
0084     case KBlocksLayout_Update_PunishLine:
0085         updatePunishLine(dataList);
0086         break;
0087     }
0088 }
0089 
0090 void KBlocksLayout::endUpdate()
0091 {
0092     int px = 0;
0093     int py = 0;
0094     int activePieceColor = mpActivePiece->getType();
0095     for (int i = 0; i < mPieceCellCount; i++) {
0096         px = mpActivePiece->getCellPosX(i);
0097         py = mpActivePiece->getCellPosY(i);
0098         mpLastPiecePos[i]->setX(px);
0099         mpLastPiecePos[i]->setY(py);
0100         if ((px >= 0) && (px < mWidth)
0101                 && (py >= 0) && (py < mHeight)) {
0102             boardInfo[py][px] = activePieceColor;
0103         }
0104     }
0105 
0106     updatePrepareArea();
0107 }
0108 
0109 void KBlocksLayout::updateSnapshot()
0110 {
0111     for (int y = 0; y < mHeight; y++) {
0112         for (int x = 0; x < mWidth; x++) {
0113             if (mpGameField->getCell(x, y)) {
0114                 boardInfo[y][x] = 0; // TODO : what color is better here?
0115             } else {
0116                 boardInfo[y][x] = -1;
0117             }
0118         }
0119     }
0120 
0121     endUpdate();
0122 }
0123 
0124 int KBlocksLayout::getFieldColor(int posX, int posY)
0125 {
0126     if ((posX < 0) || (posX >= mWidth) || (posY < 0) || (posY >= mHeight)) {
0127         return -1;
0128     }
0129 
0130     return boardInfo[posY][posX];
0131 }
0132 
0133 int KBlocksLayout::getPrepareColor(int posX, int posY)
0134 {
0135     if ((posX < 0) || (posX >= PREPARE_AREA_WIDTH) || (posY < 0) || (posY >= PREPARE_AREA_WIDTH)) {
0136         return -1;
0137     }
0138 
0139     return prepareInfo[posY][posX];
0140 }
0141 
0142 void KBlocksLayout::updatePrepareArea()
0143 {
0144     for (int i = 0; i < PREPARE_AREA_WIDTH; i++) {
0145         for (int j = 0; j < PREPARE_AREA_WIDTH; j++) {
0146             prepareInfo[i][j] = -1;
0147         }
0148     }
0149 
0150     int nextPieceColor = mpNextPiece->getType();
0151     for (int i = 0; i < 4; i++) {
0152         int posX = mpNextPiece->getCellPosX(i);
0153         int posY = mpNextPiece->getCellPosY(i);
0154         prepareInfo[posY][posX] = nextPieceColor;
0155     }
0156 }
0157 
0158 void KBlocksLayout::updateFreezePiece(const QList<int> &dataList)
0159 {
0160     QList<int> tmpList = dataList;
0161     int freezeColor = tmpList.takeFirst();
0162     int loopCount = tmpList.size() / 2;
0163     for (int i = 0; i < loopCount; i++) {
0164         int posX = tmpList[i * 2];
0165         int posY = tmpList[i * 2 + 1];
0166         if ((posX >= 0) && (posX < mWidth)
0167                 && (posY >= 0) && (posY < mHeight)) {
0168             boardInfo[posY][posX] = freezeColor;
0169         }
0170     }
0171 }
0172 
0173 void KBlocksLayout::updateRemoveLine(const QList<int> &dataList)
0174 {
0175     int lineCount = dataList.size();
0176     for (int k = 0; k < lineCount; k++) {
0177         for (int i = dataList[k]; i > 0; i--) {
0178             for (int j = 0; j < mWidth; j++) {
0179                 boardInfo[i][j] = boardInfo[i - 1][j];
0180             }
0181         }
0182         for (int j = 0; j < mWidth; j++) {
0183             boardInfo[0][j] = -1;
0184         }
0185     }
0186 }
0187 
0188 void KBlocksLayout::updatePunishLine(const QList<int> &dataList)
0189 {
0190     int punishColor = mpNextPiece->getType(); // TODO : this color or new color?
0191     int lineCount = dataList.size();
0192     for (int k = 0; k < lineCount; k++) {
0193         for (int i = 0; i < mHeight - dataList[k]; i++) {
0194             for (int j = 0; j < mWidth; j++) {
0195                 boardInfo[i][j] = boardInfo[i + dataList[k]][j];
0196             }
0197         }
0198         for (int i = mHeight - dataList[k]; i < mHeight; i++) {
0199             for (int j = 0; j < mWidth; j++) {
0200                 if (mpGameField->getCell(j, i)) {
0201                     boardInfo[i][j] = punishColor;
0202                 } else {
0203                     boardInfo[i][j] = -1;
0204                 }
0205             }
0206         }
0207     }
0208 }