1/***************************************************************************
2* KBlocks, a falling blocks game for KDE *
3* Copyright (C) 2010 Zhongjie Cai <squall.leonhart.cai@gmail.com> *
4* *
5* This program is free software; you can redistribute it and/or modify *
6* it under the terms of the GNU General Public License as published by *
7* the Free Software Foundation; either version 2 of the License, or *
8* (at your option) any later version. *
9***************************************************************************/
10#include "KBlocksField.h"
11
12KBlocksField::KBlocksField(int width, int height)
13{
14 mWidth = width;
15 mHeight = height;
16
17 mCurModifyID = 0;
18 mLastModifyID = -1;
19
20 maEncodeData = new unsigned char[mWidth * mHeight / 8 + 1];
21 for(int i = 0; i < mWidth * mHeight / 8 + 1; ++i)
22 {
23 maEncodeData[i] = 0;
24 }
25
26 maBoard = new bool*[mHeight];
27 for(int i = 0; i < mHeight; i++)
28 {
29 maBoard[i] = new bool[mWidth];
30 for(int j = 0; j < mWidth; j++)
31 {
32 maBoard[i][j] = false;
33 }
34 }
35}
36
37KBlocksField::KBlocksField(FieldInterface * p)
38{
39 mWidth = p->getWidth();
40 mHeight = p->getHeight();
41
42 mCurModifyID = 0;
43 mLastModifyID = -1;
44
45 maEncodeData = new unsigned char[mWidth * mHeight / 8 + 1];
46 for(int i = 0; i < mWidth * mHeight / 8 + 1; ++i)
47 {
48 maEncodeData[i] = 0;
49 }
50
51 maBoard = new bool*[mHeight];
52 for(int i = 0; i < mHeight; i++)
53 {
54 maBoard[i] = new bool[mWidth];
55 for(int j = 0; j < mWidth; j++)
56 {
57 maBoard[i][j] = p->getCell(j, i);
58 }
59 }
60}
61
62KBlocksField::~KBlocksField()
63{
64 for(int i = 0; i < mHeight; i++)
65 {
66 delete [] maBoard[i];
67 }
68 delete [] maBoard;
69 delete [] maEncodeData;
70}
71
72bool KBlocksField::getCell(int xPos, int yPos)
73{
74 if ( (xPos < 0) || (xPos >= mWidth) || (yPos >= mHeight) )
75 {
76 return true;
77 }
78 if (yPos < 0)
79 {
80 return false; // Allow blocks to be placed above top
81 }
82
83 return maBoard[yPos][xPos];
84}
85
86void KBlocksField::setCell(int xPos, int yPos, bool value)
87{
88 if ( ((xPos < 0) || (xPos >= mWidth))
89 || ((yPos < 0) || (yPos >= mHeight)) )
90 {
91 return;
92 }
93 maBoard[yPos][xPos] = value;
94 mCurModifyID += 1;
95}
96
97void KBlocksField::copy(FieldInterface * p)
98{
99 for(int i = 0; i < mHeight; i++)
100 {
101 for(int j = 0; j < mWidth; j++)
102 {
103 maBoard[i][j] = p->getCell(j, i);
104 }
105 }
106}
107
108void KBlocksField::clear()
109{
110 for(int i = 0; i < mHeight; i++)
111 {
112 for(int j = 0; j < mWidth; j++)
113 {
114 maBoard[i][j] = false;
115 }
116 }
117 mCurModifyID = 0;
118}
119
120bool KBlocksField::checkFilledLine(int lineID)
121{
122 for(int i = 0; i < mWidth; i++)
123 {
124 if (maBoard[lineID][i] == false)
125 {
126 return false;
127 }
128 }
129 return true;
130}
131
132void KBlocksField::removeFilledLine(int lineID)
133{
134 for(int i = lineID; i > 0; i--)
135 {
136 for(int j = 0; j < mWidth; j++)
137 {
138 maBoard[i][j] = maBoard[i-1][j];
139 }
140 }
141 mCurModifyID += 1;
142}
143
144bool KBlocksField::addPunishLine(int lineCount, int punishSeed)
145{
146 bool result = true;
147
148 for(int i = 0; i < mWidth; i++)
149 {
150 if (maBoard[0][i])
151 {
152 result = false;
153 break;
154 }
155 }
156
157 for(int i = 0; i < mHeight - 1; i++)
158 {
159 for(int j = 0; j < mWidth; j++)
160 {
161 maBoard[i][j] = maBoard[i+1][j];
162 }
163 }
164
165 for(int i = 0; i < mWidth; i++)
166 {
167 maBoard[mHeight-1][i] = true;
168 }
169
170 for(int i = 0; i < lineCount; i++)
171 {
172 maBoard[mHeight-1][punishSeed] = false;
173 punishSeed = (punishSeed + lineCount) % mWidth;
174 }
175
176 mCurModifyID += 1;
177
178 return result;
179}
180
181int KBlocksField::getModifyID()
182{
183 return mCurModifyID;
184}
185
186int KBlocksField::encodeData(unsigned char * data)
187{
188 int byteCounter = 0;
189 int loopCounter = 0;
190
191 if (mLastModifyID != mCurModifyID)
192 {
193 mLastModifyID = mCurModifyID;
194 for(int i = 0; i < mHeight; i++)
195 {
196 for(int j = 0; j < mWidth; j++)
197 {
198 byteCounter = loopCounter / 8;
199 if (maBoard[i][j])
200 {
201 maEncodeData[byteCounter] |= (1 << (loopCounter % 8));
202 }
203 else
204 {
205 maEncodeData[byteCounter] &= ~(1 << (loopCounter % 8));
206 }
207 loopCounter++;
208 }
209 }
210 }
211
212 byteCounter = mWidth * mHeight / 8;
213 for(int i = 0; i < byteCounter; i++)
214 {
215 data[i] = maEncodeData[i];
216 }
217
218 return byteCounter;
219}
220
221void KBlocksField::decodeData(unsigned char * data)
222{
223 int byteCounter = 0;
224 int loopCounter = 0;
225
226 for(int i = 0; i < mHeight; i++)
227 {
228 for(int j = 0; j < mWidth; j++)
229 {
230 byteCounter = loopCounter / 8;
231 if (((data[byteCounter] >> (loopCounter % 8)) & 0x01) == 0x01)
232 {
233 maBoard[i][j] = true;
234 }
235 else
236 {
237 maBoard[i][j] = false;
238 }
239 loopCounter++;
240 }
241 }
242
243 for(int i = 0; i < byteCounter; i++)
244 {
245 maEncodeData[i] = data[i];
246 }
247
248 mCurModifyID = 0;
249 mLastModifyID = 0;
250}
251
252int KBlocksField::getWidth()
253{
254 return mWidth;
255}
256
257int KBlocksField::getHeight()
258{
259 return mHeight;
260}
261
262bool KBlocksField::equals(KBlocksField * rhs)
263{
264 if ((rhs->getWidth() != mWidth) || (rhs->getHeight() != mHeight))
265 {
266 return false;
267 }
268 for(int i = 0; i < mHeight; i++)
269 {
270 for(int j = 0; j < mWidth; j++)
271 {
272 if (maBoard[i][j] != rhs->getCell(j, i))
273 {
274 return false;
275 }
276 }
277 }
278 return true;
279}
280
281int KBlocksField::getBlockHeight(int xPos)
282{
283 for (int i = 0; i < mHeight; ++i)
284 {
285 if (maBoard[i][xPos])
286 {
287 return (mHeight - i);
288 }
289 }
290 return 0;
291}
292
293int KBlocksField::getFreeHeight(int xPos)
294{
295 for (int i = 0; i < mHeight; ++i)
296 {
297 if (maBoard[i][xPos])
298 {
299 return i;
300 }
301 }
302 return mHeight;
303}
304
305void KBlocksField::getSignature(int * data)
306{
307 for (int i = 0; i < mWidth; ++i)
308 {
309 data[i] = getBlockHeight(i);
310 }
311}
312