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 | |
12 | KBlocksField::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 | |
37 | KBlocksField::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 | |
62 | KBlocksField::~KBlocksField() |
63 | { |
64 | for(int i = 0; i < mHeight; i++) |
65 | { |
66 | delete [] maBoard[i]; |
67 | } |
68 | delete [] maBoard; |
69 | delete [] maEncodeData; |
70 | } |
71 | |
72 | bool 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 | |
86 | void 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 | |
97 | void 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 | |
108 | void 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 | |
120 | bool 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 | |
132 | void 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 | |
144 | bool 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 | |
181 | int KBlocksField::getModifyID() |
182 | { |
183 | return mCurModifyID; |
184 | } |
185 | |
186 | int 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 | |
221 | void 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 | |
252 | int KBlocksField::getWidth() |
253 | { |
254 | return mWidth; |
255 | } |
256 | |
257 | int KBlocksField::getHeight() |
258 | { |
259 | return mHeight; |
260 | } |
261 | |
262 | bool 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 | |
281 | int 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 | |
293 | int 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 | |
305 | void KBlocksField::getSignature(int * data) |
306 | { |
307 | for (int i = 0; i < mWidth; ++i) |
308 | { |
309 | data[i] = getBlockHeight(i); |
310 | } |
311 | } |
312 | |