File indexing completed on 2024-04-28 07:51:24
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 "KBlocksField.h" 0008 0009 KBlocksField::KBlocksField(int width, int height) 0010 { 0011 mWidth = width; 0012 mHeight = height; 0013 0014 mCurModifyID = 0; 0015 mLastModifyID = -1; 0016 0017 maEncodeData = new unsigned char[mWidth * mHeight / 8 + 1]; 0018 for (int i = 0; i < mWidth * mHeight / 8 + 1; ++i) { 0019 maEncodeData[i] = 0; 0020 } 0021 0022 maBoard = new bool*[mHeight]; 0023 for (int i = 0; i < mHeight; i++) { 0024 maBoard[i] = new bool[mWidth]; 0025 for (int j = 0; j < mWidth; j++) { 0026 maBoard[i][j] = false; 0027 } 0028 } 0029 } 0030 0031 KBlocksField::KBlocksField(FieldInterface *p) 0032 { 0033 mWidth = p->getWidth(); 0034 mHeight = p->getHeight(); 0035 0036 mCurModifyID = 0; 0037 mLastModifyID = -1; 0038 0039 maEncodeData = new unsigned char[mWidth * mHeight / 8 + 1]; 0040 for (int i = 0; i < mWidth * mHeight / 8 + 1; ++i) { 0041 maEncodeData[i] = 0; 0042 } 0043 0044 maBoard = new bool*[mHeight]; 0045 for (int i = 0; i < mHeight; i++) { 0046 maBoard[i] = new bool[mWidth]; 0047 for (int j = 0; j < mWidth; j++) { 0048 maBoard[i][j] = p->getCell(j, i); 0049 } 0050 } 0051 } 0052 0053 KBlocksField::~KBlocksField() 0054 { 0055 for (int i = 0; i < mHeight; i++) { 0056 delete [] maBoard[i]; 0057 } 0058 delete [] maBoard; 0059 delete [] maEncodeData; 0060 } 0061 0062 bool KBlocksField::getCell(int xPos, int yPos) 0063 { 0064 if ((xPos < 0) || (xPos >= mWidth) || (yPos >= mHeight)) { 0065 return true; 0066 } 0067 if (yPos < 0) { 0068 return false; // Allow blocks to be placed above top 0069 } 0070 0071 return maBoard[yPos][xPos]; 0072 } 0073 0074 void KBlocksField::setCell(int xPos, int yPos, bool value) 0075 { 0076 if (((xPos < 0) || (xPos >= mWidth)) 0077 || ((yPos < 0) || (yPos >= mHeight))) { 0078 return; 0079 } 0080 maBoard[yPos][xPos] = value; 0081 mCurModifyID += 1; 0082 } 0083 0084 void KBlocksField::copy(FieldInterface *p) 0085 { 0086 for (int i = 0; i < mHeight; i++) { 0087 for (int j = 0; j < mWidth; j++) { 0088 maBoard[i][j] = p->getCell(j, i); 0089 } 0090 } 0091 } 0092 0093 void KBlocksField::clear() 0094 { 0095 for (int i = 0; i < mHeight; i++) { 0096 for (int j = 0; j < mWidth; j++) { 0097 maBoard[i][j] = false; 0098 } 0099 } 0100 mCurModifyID = 0; 0101 } 0102 0103 bool KBlocksField::checkFilledLine(int lineID) 0104 { 0105 for (int i = 0; i < mWidth; i++) { 0106 if (maBoard[lineID][i] == false) { 0107 return false; 0108 } 0109 } 0110 return true; 0111 } 0112 0113 void KBlocksField::removeFilledLine(int lineID) 0114 { 0115 // This function removes line number lineID which has been identified as 0116 // containing no empty cells (by KBlocksField::checkFilledLine). 0117 // 0118 // The line is removed by moving the contents of all cells above 0119 // line #lineID one line down, effectively overwriting the contents 0120 // of line #lineID. 0121 // 0122 // To this end we iterate over all lines, starting at line #lineID and 0123 // ending with the line just below the top line. 0124 0125 for (int i = lineID; i > 0; i--) { 0126 0127 // For each line we iterate over all cells ... 0128 0129 for (int j = 0; j < mWidth; j++) { 0130 0131 // ... and set the content of the cell to the content of the 0132 // same cell one line above. 0133 0134 maBoard[i][j] = maBoard[i - 1][j]; 0135 } 0136 } 0137 0138 // Finally, the top line is filled with empty cells ... 0139 for (int j = 0; j < mWidth; j++) { 0140 maBoard[0][j] = false; 0141 } 0142 0143 // ... and the modification ID is increased by one. 0144 mCurModifyID += 1; 0145 } 0146 0147 bool KBlocksField::addPunishLine(int lineCount, int punishSeed) 0148 { 0149 bool result = true; 0150 0151 for (int i = 0; i < mWidth; i++) { 0152 if (maBoard[0][i]) { 0153 result = false; 0154 break; 0155 } 0156 } 0157 0158 for (int i = 0; i < mHeight - 1; i++) { 0159 for (int j = 0; j < mWidth; j++) { 0160 maBoard[i][j] = maBoard[i + 1][j]; 0161 } 0162 } 0163 0164 for (int i = 0; i < mWidth; i++) { 0165 maBoard[mHeight - 1][i] = true; 0166 } 0167 0168 for (int i = 0; i < lineCount; i++) { 0169 maBoard[mHeight - 1][punishSeed] = false; 0170 punishSeed = (punishSeed + lineCount) % mWidth; 0171 } 0172 0173 mCurModifyID += 1; 0174 0175 return result; 0176 } 0177 0178 int KBlocksField::getModifyID() 0179 { 0180 return mCurModifyID; 0181 } 0182 0183 int KBlocksField::encodeData(unsigned char *data) 0184 { 0185 int byteCounter = 0; 0186 int loopCounter = 0; 0187 0188 if (mLastModifyID != mCurModifyID) { 0189 mLastModifyID = mCurModifyID; 0190 for (int i = 0; i < mHeight; i++) { 0191 for (int j = 0; j < mWidth; j++) { 0192 byteCounter = loopCounter / 8; 0193 if (maBoard[i][j]) { 0194 maEncodeData[byteCounter] |= (1 << (loopCounter % 8)); 0195 } else { 0196 maEncodeData[byteCounter] &= ~(1 << (loopCounter % 8)); 0197 } 0198 loopCounter++; 0199 } 0200 } 0201 } 0202 0203 byteCounter = mWidth * mHeight / 8; 0204 for (int i = 0; i < byteCounter; i++) { 0205 data[i] = maEncodeData[i]; 0206 } 0207 0208 return byteCounter; 0209 } 0210 0211 void KBlocksField::decodeData(unsigned char *data) 0212 { 0213 int byteCounter = 0; 0214 int loopCounter = 0; 0215 0216 for (int i = 0; i < mHeight; i++) { 0217 for (int j = 0; j < mWidth; j++) { 0218 byteCounter = loopCounter / 8; 0219 if (((data[byteCounter] >> (loopCounter % 8)) & 0x01) == 0x01) { 0220 maBoard[i][j] = true; 0221 } else { 0222 maBoard[i][j] = false; 0223 } 0224 loopCounter++; 0225 } 0226 } 0227 0228 for (int i = 0; i < byteCounter; i++) { 0229 maEncodeData[i] = data[i]; 0230 } 0231 0232 mCurModifyID = 0; 0233 mLastModifyID = 0; 0234 } 0235 0236 int KBlocksField::getWidth() 0237 { 0238 return mWidth; 0239 } 0240 0241 int KBlocksField::getHeight() 0242 { 0243 return mHeight; 0244 } 0245 0246 bool KBlocksField::equals(KBlocksField *rhs) 0247 { 0248 if ((rhs->getWidth() != mWidth) || (rhs->getHeight() != mHeight)) { 0249 return false; 0250 } 0251 for (int i = 0; i < mHeight; i++) { 0252 for (int j = 0; j < mWidth; j++) { 0253 if (maBoard[i][j] != rhs->getCell(j, i)) { 0254 return false; 0255 } 0256 } 0257 } 0258 return true; 0259 } 0260 0261 int KBlocksField::getBlockHeight(int xPos) 0262 { 0263 for (int i = 0; i < mHeight; ++i) { 0264 if (maBoard[i][xPos]) { 0265 return (mHeight - i); 0266 } 0267 } 0268 return 0; 0269 } 0270 0271 int KBlocksField::getFreeHeight(int xPos) 0272 { 0273 for (int i = 0; i < mHeight; ++i) { 0274 if (maBoard[i][xPos]) { 0275 return i; 0276 } 0277 } 0278 return mHeight; 0279 } 0280 0281 void KBlocksField::getSignature(int *data) 0282 { 0283 for (int i = 0; i < mWidth; ++i) { 0284 data[i] = getBlockHeight(i); 0285 } 0286 }