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 "KBlocksLayout.h"
11
12KBlocksLayout::KBlocksLayout(FieldInterface * pF, PieceInterface * pA, PieceInterface * pN)
13{
14 mpGameField = pF;
15 mpActivePiece = pA;
16 mpNextPiece = pN;
17
18 mPieceCellCount = mpActivePiece->getCellCount();
19 mpLastPiecePos = new QPoint*[mPieceCellCount];
20 for(int i = 0; i < mPieceCellCount; i++)
21 {
22 mpLastPiecePos[i] = new QPoint(0, 0);
23 }
24
25 mWidth = mpGameField->getWidth();
26 mHeight = mpGameField->getHeight();
27 boardInfo = new int*[mHeight];
28 for(int i = 0; i < mHeight; i++)
29 {
30 boardInfo[i] = new int[mWidth];
31 for(int j = 0; j < mWidth; j++)
32 {
33 boardInfo[i][j] = -1;
34 }
35 }
36
37 prepareInfo = new int*[PREPARE_AREA_WIDTH];
38 for(int i = 0; i < PREPARE_AREA_WIDTH; i++)
39 {
40 prepareInfo[i] = new int[PREPARE_AREA_WIDTH];
41 for(int j = 0; j < PREPARE_AREA_WIDTH; j++)
42 {
43 prepareInfo[i][j] = -1;
44 }
45 }
46}
47
48KBlocksLayout::~KBlocksLayout()
49{
50 for(int i = 0; i < mHeight; i++)
51 {
52 delete [] boardInfo[i];
53 }
54 delete [] boardInfo;
55
56 for(int i = 0; i < PREPARE_AREA_WIDTH; i++)
57 {
58 delete [] prepareInfo[i];
59 }
60 delete [] prepareInfo;
61
62 for(int i = 0; i < mPieceCellCount; i++)
63 {
64 delete mpLastPiecePos[i];
65 }
66 delete [] mpLastPiecePos;
67}
68
69void KBlocksLayout::beginUpdate(QList<int> * list)
70{
71 int px = 0;
72 int py = 0;
73 list->clear();
74 for(int i = 0; i < mPieceCellCount; i++)
75 {
76 px = mpLastPiecePos[i]->x();
77 py = mpLastPiecePos[i]->y();
78 list->append(px);
79 list->append(py);
80 if ((px >= 0) && (px < mWidth)
81 && (py >= 0) && (py < mHeight))
82 {
83 boardInfo[py][px] = -1;
84 }
85 }
86}
87
88void KBlocksLayout::updateLayout(int type, const QList<int> & dataList)
89{
90 switch(type)
91 {
92 case KBlocksLayout_Update_FreezePiece:
93 updateFreezePiece(dataList);
94 break;
95 case KBlocksLayout_Update_RemoveLine:
96 updateRemoveLine(dataList);
97 break;
98 case KBlocksLayout_Update_PunishLine:
99 updatePunishLine(dataList);
100 break;
101 }
102}
103
104void KBlocksLayout::endUpdate()
105{
106 int px = 0;
107 int py = 0;
108 int activePieceColor = mpActivePiece->getType();
109 for(int i = 0; i < mPieceCellCount; i++)
110 {
111 px = mpActivePiece->getCellPosX(i);
112 py = mpActivePiece->getCellPosY(i);
113 mpLastPiecePos[i]->setX(px);
114 mpLastPiecePos[i]->setY(py);
115 if ((px >= 0) && (px < mWidth)
116 && (py >= 0) && (py < mHeight))
117 {
118 boardInfo[py][px] = activePieceColor;
119 }
120 }
121
122 updatePrepareArea();
123}
124
125void KBlocksLayout::updateSnapshot()
126{
127 for(int y = 0; y < mHeight; y++)
128 {
129 for(int x = 0; x < mWidth; x++)
130 {
131 if (mpGameField->getCell(x, y))
132 {
133 boardInfo[y][x] = 0; // TODO : what color is better here?
134 }
135 else
136 {
137 boardInfo[y][x] = -1;
138 }
139 }
140 }
141
142 endUpdate();
143}
144
145int KBlocksLayout::getFieldColor(int posX, int posY)
146{
147 if ((posX < 0) || (posX >= mWidth) || (posY < 0) || (posY >= mHeight))
148 {
149 return -1;
150 }
151
152 return boardInfo[posY][posX];
153}
154
155int KBlocksLayout::getPrepareColor(int posX, int posY)
156{
157 if ((posX < 0) || (posX >= PREPARE_AREA_WIDTH) || (posY < 0) || (posY >= PREPARE_AREA_WIDTH))
158 {
159 return -1;
160 }
161
162 return prepareInfo[posY][posX];
163}
164
165void KBlocksLayout::updatePrepareArea()
166{
167 for(int i = 0; i < PREPARE_AREA_WIDTH; i++)
168 {
169 for(int j = 0; j < PREPARE_AREA_WIDTH; j++)
170 {
171 prepareInfo[i][j] = -1;
172 }
173 }
174
175 int nextPieceColor = mpNextPiece->getType();
176 for(int i = 0; i < 4; i++)
177 {
178 int posX = mpNextPiece->getCellPosX(i);
179 int posY = mpNextPiece->getCellPosY(i);
180 prepareInfo[posY][posX] = nextPieceColor;
181 }
182}
183
184void KBlocksLayout::updateFreezePiece(const QList<int> & dataList)
185{
186 QList<int> tmpList = dataList;
187 int freezeColor = tmpList.takeFirst();
188 int loopCount = tmpList.size() / 2;
189 for(int i = 0; i < loopCount; i++)
190 {
191 int posX = tmpList[i * 2];
192 int posY = tmpList[i * 2 + 1];
193 if ((posX >= 0) && (posX < mWidth)
194 && (posY >= 0) && (posY < mHeight))
195 {
196 boardInfo[posY][posX] = freezeColor;
197 }
198 }
199}
200
201void KBlocksLayout::updateRemoveLine(const QList<int> & dataList)
202{
203 int lineCount = dataList.size();
204 for(int k = 0; k < lineCount; k++)
205 {
206 for(int i = dataList[k]; i > 0; i--)
207 {
208 for(int j = 0; j < mWidth; j++)
209 {
210 boardInfo[i][j] = boardInfo[i - 1][j];
211 }
212 }
213 for(int j = 0; j < mWidth; j++)
214 {
215 boardInfo[0][j] = -1;
216 }
217 }
218}
219
220void KBlocksLayout::updatePunishLine(const QList<int> & dataList)
221{
222 int punishColor = mpNextPiece->getType(); // TODO : this color or new color?
223 int lineCount = dataList.size();
224 for(int k = 0; k < lineCount; k++)
225 {
226 for(int i = 0; i < mHeight - dataList[k]; i++)
227 {
228 for(int j = 0; j < mWidth; j++)
229 {
230 boardInfo[i][j] = boardInfo[i + dataList[k]][j];
231 }
232 }
233 for(int i = mHeight - dataList[k]; i < mHeight; i++)
234 {
235 for(int j = 0; j < mWidth; j++)
236 {
237 if (mpGameField->getCell(j, i))
238 {
239 boardInfo[i][j] = punishColor;
240 }
241 else
242 {
243 boardInfo[i][j] = -1;
244 }
245 }
246 }
247 }
248}
249