1 | // |
---|
2 | // Monsterz |
---|
3 | // |
---|
4 | // Copyright: (c) 2005-2011 Sam Hocevar <sam@hocevar.net> |
---|
5 | // This program is free software; you can redistribute it and/or |
---|
6 | // modify it under the terms of the Do What The Fuck You Want To |
---|
7 | // Public License, Version 2, as published by Sam Hocevar. See |
---|
8 | // http://sam.zoy.org/projects/COPYING.WTFPL for more details. |
---|
9 | // |
---|
10 | |
---|
11 | #if defined HAVE_CONFIG_H |
---|
12 | # include "config.h" |
---|
13 | #endif |
---|
14 | |
---|
15 | #include <cmath> |
---|
16 | #include <cstdlib> |
---|
17 | #include <ctime> |
---|
18 | #include <cstring> |
---|
19 | |
---|
20 | #include "core.h" |
---|
21 | |
---|
22 | using namespace std; |
---|
23 | using namespace lol; |
---|
24 | |
---|
25 | #include "board.h" |
---|
26 | #include "piece.h" |
---|
27 | #include "score.h" |
---|
28 | #include "thumbs.h" |
---|
29 | #include "mash.h" |
---|
30 | #include "monsterz.h" |
---|
31 | |
---|
32 | /* |
---|
33 | * Board implementation class |
---|
34 | */ |
---|
35 | |
---|
36 | class BoardData |
---|
37 | { |
---|
38 | friend class Board; |
---|
39 | |
---|
40 | private: |
---|
41 | Board::game_t game; |
---|
42 | |
---|
43 | ivec2 dim, size; |
---|
44 | int minnpieces, npieces, maxnpieces; |
---|
45 | |
---|
46 | TileSet *screen, *board, *tiles, *icons; |
---|
47 | int click, whip; |
---|
48 | |
---|
49 | struct Pair |
---|
50 | { |
---|
51 | int id; |
---|
52 | Piece *piece; |
---|
53 | } |
---|
54 | pairs[MAX_WIDTH][MAX_HEIGHT]; |
---|
55 | |
---|
56 | /* Hunt */ |
---|
57 | struct Pair grabbed; |
---|
58 | int nmoves; |
---|
59 | ivec2 src_cell, dst_cell; |
---|
60 | |
---|
61 | /* Fusion */ |
---|
62 | struct Pair current[2]; |
---|
63 | int next[2], rotation; |
---|
64 | |
---|
65 | Score *score; |
---|
66 | |
---|
67 | Mash *mashes; |
---|
68 | Emitter *emitter; |
---|
69 | Thumbs *thumbs; |
---|
70 | |
---|
71 | ivec2 oldmouse; |
---|
72 | ivec3 oldbuttons; |
---|
73 | float whipdelay; |
---|
74 | |
---|
75 | enum |
---|
76 | { |
---|
77 | HUNT_IDLE, |
---|
78 | HUNT_BADCLICK, |
---|
79 | HUNT_GRAB, |
---|
80 | } |
---|
81 | state; |
---|
82 | }; |
---|
83 | |
---|
84 | /* |
---|
85 | * Public Board class |
---|
86 | */ |
---|
87 | |
---|
88 | Board::Board(game_t game, ivec2 dim, int minnpieces, int maxnpieces) |
---|
89 | : data(new BoardData()) |
---|
90 | { |
---|
91 | data->game = game; |
---|
92 | |
---|
93 | switch (data->game) |
---|
94 | { |
---|
95 | case GAME_HUNT: |
---|
96 | data->size = 48; |
---|
97 | break; |
---|
98 | } |
---|
99 | |
---|
100 | data->dim = dim; |
---|
101 | data->minnpieces = minnpieces; |
---|
102 | data->npieces = minnpieces; |
---|
103 | data->maxnpieces = maxnpieces; |
---|
104 | data->screen = Tiler::Register(PNG_BACKGROUND, ivec2(640, 480), 0, 1.0f); |
---|
105 | data->board = Tiler::Register(PNG_BOARD, 384, 0, 1.0f); |
---|
106 | data->tiles = Tiler::Register(PNG_TILES, data->size, 0, 1.0f); |
---|
107 | data->icons = Tiler::Register(PNG_ICONS, 24, 0, 1.0f); |
---|
108 | data->click = Sampler::Register(WAV_CLICK); |
---|
109 | data->whip = Sampler::Register(WAV_WHIP); |
---|
110 | |
---|
111 | data->emitter = new Emitter(data->tiles, vec3(0, -0.0006f, 0)); |
---|
112 | Ticker::Ref(data->emitter); |
---|
113 | |
---|
114 | data->thumbs = new Thumbs(0); |
---|
115 | Ticker::Ref(data->thumbs); |
---|
116 | |
---|
117 | switch (data->game) |
---|
118 | { |
---|
119 | case GAME_HUNT: |
---|
120 | Fill(); |
---|
121 | data->thumbs->SetMax(data->npieces); |
---|
122 | data->state = BoardData::HUNT_IDLE; |
---|
123 | break; |
---|
124 | } |
---|
125 | |
---|
126 | data->mashes = NULL; |
---|
127 | data->whipdelay = 0.0f; |
---|
128 | |
---|
129 | data->score = new Score(0); |
---|
130 | data->score->SetPos(ivec3(624, 432, 20)); |
---|
131 | Ticker::Ref(data->score); |
---|
132 | |
---|
133 | position = ivec3(24, 72, 1); |
---|
134 | bbox[0] = position; |
---|
135 | bbox[1] = bbox[0] + ivec3(384, 384, 0); |
---|
136 | |
---|
137 | Input::TrackMouse(this); |
---|
138 | } |
---|
139 | |
---|
140 | void Board::TickGame(float deltams) |
---|
141 | { |
---|
142 | Entity::TickGame(deltams); |
---|
143 | |
---|
144 | ivec3 buttons = Input::GetMouseButtons(); |
---|
145 | |
---|
146 | /* Do not whip too often, the sound may become annoying */ |
---|
147 | data->whipdelay -= deltams; |
---|
148 | |
---|
149 | /* Get rid of finished mashes */ |
---|
150 | for (Mash **it = &data->mashes; *it; ) |
---|
151 | { |
---|
152 | if ((*it)->IsDead()) |
---|
153 | { |
---|
154 | Ticker::Unref(*it); |
---|
155 | *it = (*it)->nextmash; |
---|
156 | } |
---|
157 | else |
---|
158 | it = &(*it)->nextmash; |
---|
159 | } |
---|
160 | |
---|
161 | switch (data->state) |
---|
162 | { |
---|
163 | case BoardData::HUNT_IDLE: |
---|
164 | /* Should we start dragging something? */ |
---|
165 | if (buttons[0] && !data->oldbuttons[0] && mousepos.x != -1) |
---|
166 | { |
---|
167 | ivec2 cell = mousepos / data->size; |
---|
168 | if (data->pairs[cell.x][cell.y].piece->Grab(ivec2(0, 0))) |
---|
169 | { |
---|
170 | Sampler::PlaySample(data->click); |
---|
171 | data->grabbed = data->pairs[cell.x][cell.y]; |
---|
172 | data->src_cell = mousepos / data->size; |
---|
173 | data->dst_cell = ivec2(-1); |
---|
174 | data->state = BoardData::HUNT_GRAB; |
---|
175 | } |
---|
176 | else |
---|
177 | data->state = BoardData::HUNT_BADCLICK; |
---|
178 | } |
---|
179 | break; |
---|
180 | |
---|
181 | case BoardData::HUNT_GRAB: |
---|
182 | if (mousepos.x != -1) |
---|
183 | { |
---|
184 | /* Mouse is still in the window, keep grabbing */ |
---|
185 | data->grabbed.piece->Grab(mousepos - data->oldmouse); |
---|
186 | ivec2 cur_pos = data->grabbed.piece->GetPos() |
---|
187 | + data->grabbed.piece->GetOffset(); |
---|
188 | ivec2 cur_cell = (cur_pos + data->size / 2) / data->size; |
---|
189 | if (cur_cell.i < 0 || cur_cell.i >= data->dim.i |
---|
190 | || cur_cell.j < 0 || cur_cell.j >= data->dim.j |
---|
191 | || (cur_pos - cur_cell * data->size).sqlen() > data->size.sqlen() / 8 |
---|
192 | || (cur_cell - data->src_cell).sqlen() != 1) |
---|
193 | cur_cell = ivec2(-1); |
---|
194 | /* If potential target changed, update our cache. */ |
---|
195 | if (cur_cell != data->dst_cell) |
---|
196 | { |
---|
197 | if (data->whipdelay < 0.0f) |
---|
198 | { |
---|
199 | Sampler::PlaySample(data->whip); |
---|
200 | data->whipdelay = DELAY_WHIP; |
---|
201 | } |
---|
202 | if (data->dst_cell != ivec2(-1)) |
---|
203 | data->pairs[data->dst_cell.i] |
---|
204 | [data->dst_cell.j].piece->Ungrab(data->dst_cell * data->size); |
---|
205 | if (cur_cell != ivec2(-1)) |
---|
206 | data->pairs[cur_cell.i] |
---|
207 | [cur_cell.j].piece->Ungrab(data->src_cell * data->size); |
---|
208 | data->dst_cell = cur_cell; |
---|
209 | } |
---|
210 | } |
---|
211 | |
---|
212 | /* Move initiated: if valid, perform immediately. */ |
---|
213 | if (data->dst_cell != ivec2(-1)) |
---|
214 | { |
---|
215 | ivec2 cell_a = data->src_cell; |
---|
216 | ivec2 cell_b = data->dst_cell; |
---|
217 | |
---|
218 | if (Switch(cell_a, cell_b)) |
---|
219 | data->state = BoardData::HUNT_IDLE; |
---|
220 | } |
---|
221 | |
---|
222 | /* Mouse released, or exited window, or dragged too far. */ |
---|
223 | if (!buttons[0] || mousepos.x == -1 |
---|
224 | || (data->src_cell * data->size - data->grabbed.piece->GetPos() |
---|
225 | - data->grabbed.piece->GetOffset()).sqlen() > 100 * 100) |
---|
226 | { |
---|
227 | ivec2 cell_a = data->src_cell; |
---|
228 | BoardData::Pair a = data->pairs[cell_a.i][cell_a.j]; |
---|
229 | a.piece->Ungrab(cell_a * data->size); |
---|
230 | |
---|
231 | if (data->dst_cell != ivec2(-1)) |
---|
232 | { |
---|
233 | ivec2 cell_b = data->dst_cell; |
---|
234 | BoardData::Pair b = data->pairs[cell_b.i][cell_b.j]; |
---|
235 | b.piece->Ungrab(cell_b * data->size); |
---|
236 | } |
---|
237 | |
---|
238 | data->state = BoardData::HUNT_IDLE; |
---|
239 | } |
---|
240 | break; |
---|
241 | |
---|
242 | case BoardData::HUNT_BADCLICK: |
---|
243 | if (!buttons[0]) |
---|
244 | data->state = BoardData::HUNT_IDLE; |
---|
245 | break; |
---|
246 | } |
---|
247 | |
---|
248 | data->oldmouse = mousepos; |
---|
249 | data->oldbuttons = buttons; |
---|
250 | } |
---|
251 | |
---|
252 | void Board::TickDraw(float deltams) |
---|
253 | { |
---|
254 | Entity::TickDraw(deltams); |
---|
255 | |
---|
256 | Scene::GetDefault()->AddTile(data->board, 0, position, 0); |
---|
257 | Scene::GetDefault()->AddTile(data->screen, 0, ivec3(0, 0, 10), 0); |
---|
258 | |
---|
259 | switch (data->game) |
---|
260 | { |
---|
261 | case GAME_HUNT: |
---|
262 | break; |
---|
263 | } |
---|
264 | } |
---|
265 | |
---|
266 | /* Fill the board with an initial position. We ensure no pieces are |
---|
267 | * aligned and at least one move is possible. */ |
---|
268 | void Board::Fill() |
---|
269 | { |
---|
270 | srand(rand() ^ time(NULL)); |
---|
271 | |
---|
272 | int list[MAX_WIDTH][MAX_HEIGHT]; |
---|
273 | do |
---|
274 | { |
---|
275 | for (int j = 0; j < data->dim.j; j++) |
---|
276 | for (int i = 0; i < data->dim.i; i++) |
---|
277 | data->pairs[i][j].id = 1 + rand() % data->npieces; |
---|
278 | } while (ListMashes(list) || !(data->nmoves = ListMoves(list))); |
---|
279 | |
---|
280 | /* Spawn pieces */ |
---|
281 | for (int j = 0; j < data->dim.j; j++) |
---|
282 | for (int i = 0; i < data->dim.i; i++) |
---|
283 | { |
---|
284 | ivec2 newpos = ivec2(i, j + data->dim.j) * data->size; |
---|
285 | int id = data->pairs[i][j].id; |
---|
286 | data->pairs[i][j].piece = new Piece(Piece::PIECE_HUNT, |
---|
287 | data->emitter, ivec2(i, j), id); |
---|
288 | data->pairs[i][j].piece->SetPos(newpos); |
---|
289 | data->pairs[i][j].piece->Move(ivec2(i, j) * data->size); |
---|
290 | if (j) |
---|
291 | data->pairs[i][j].piece->SetBelow(data->pairs[i][j - 1].piece); |
---|
292 | Ticker::Ref(data->pairs[i][j].piece); |
---|
293 | } |
---|
294 | } |
---|
295 | |
---|
296 | bool Board::Switch(ivec2 cell_a, ivec2 cell_b) |
---|
297 | { |
---|
298 | BoardData::Pair a = data->pairs[cell_a.i][cell_a.j]; |
---|
299 | BoardData::Pair b = data->pairs[cell_b.i][cell_b.j]; |
---|
300 | data->pairs[cell_a.i][cell_a.j] = b; |
---|
301 | data->pairs[cell_b.i][cell_b.j] = a; |
---|
302 | |
---|
303 | /* Check whether this is a valid move by testing all patterns. |
---|
304 | * If the move is invalid, cancel the swap and bail out */ |
---|
305 | int list[MAX_WIDTH][MAX_HEIGHT]; |
---|
306 | |
---|
307 | if (!ListMashes(list)) |
---|
308 | { |
---|
309 | data->pairs[cell_a.i][cell_a.j] = a; |
---|
310 | data->pairs[cell_b.i][cell_b.j] = b; |
---|
311 | return false; |
---|
312 | } |
---|
313 | |
---|
314 | /* Perform the swap */ |
---|
315 | a.piece->SetCell(cell_b); |
---|
316 | a.piece->Ungrab(cell_b * data->size); |
---|
317 | b.piece->SetCell(cell_a); |
---|
318 | b.piece->Ungrab(cell_a * data->size); |
---|
319 | |
---|
320 | /* Swap above and below cells */ |
---|
321 | if (cell_a.i == cell_b.i) |
---|
322 | { |
---|
323 | Piece *tmpa = a.piece->GetAbove(); |
---|
324 | Piece *tmpb = b.piece->GetAbove(); |
---|
325 | if (tmpb == a.piece) |
---|
326 | { |
---|
327 | tmpb = b.piece->GetBelow(); |
---|
328 | b.piece->SetAbove(tmpa); |
---|
329 | b.piece->SetBelow(a.piece); |
---|
330 | a.piece->SetBelow(tmpb); |
---|
331 | } |
---|
332 | else /* tmpa == b.piece */ |
---|
333 | { |
---|
334 | tmpa = a.piece->GetBelow(); |
---|
335 | a.piece->SetAbove(tmpb); |
---|
336 | a.piece->SetBelow(b.piece); |
---|
337 | b.piece->SetBelow(tmpa); |
---|
338 | } |
---|
339 | } |
---|
340 | else |
---|
341 | { |
---|
342 | Piece *tmpa = a.piece->GetAbove(); |
---|
343 | Piece *tmpb = b.piece->GetAbove(); |
---|
344 | a.piece->SetAbove(tmpb); |
---|
345 | b.piece->SetAbove(tmpa); |
---|
346 | tmpa = a.piece->GetBelow(); |
---|
347 | tmpb = b.piece->GetBelow(); |
---|
348 | a.piece->SetBelow(tmpb); |
---|
349 | b.piece->SetBelow(tmpa); |
---|
350 | } |
---|
351 | |
---|
352 | int multiplier = 20; |
---|
353 | |
---|
354 | /* Remove matching pieces and store them in Mash objects */ |
---|
355 | do |
---|
356 | { |
---|
357 | Mash *mash = new Mash(data->emitter); |
---|
358 | Ticker::Ref(mash); |
---|
359 | |
---|
360 | for (int j = data->dim.j; j--;) for (int i = 0; i < data->dim.i; i++) |
---|
361 | { |
---|
362 | if (!list[i][j]) |
---|
363 | continue; |
---|
364 | |
---|
365 | /* The mash becomes the new owner of the disappearing piece */ |
---|
366 | mash->AddPiece(data->pairs[i][j].piece); |
---|
367 | data->thumbs->AddCount(data->pairs[i][j].id, 1); |
---|
368 | |
---|
369 | #if 0 // Test for piece creation |
---|
370 | if (list[i][j] >= 2) |
---|
371 | { |
---|
372 | Piece *old = data->pairs[i][j].piece; |
---|
373 | int id = 1 + rand() % data->npieces; |
---|
374 | data->pairs[i][j].id = id; |
---|
375 | data->pairs[i][j].piece = new Piece(Piece::PIECE_HUNT, data->emitter, ivec2(i, j), id); |
---|
376 | data->pairs[i][j].piece->SetBelow(old->GetBelow()); |
---|
377 | data->pairs[i][j].piece->SetAbove(old->GetAbove()); |
---|
378 | Ticker::Ref(data->pieces[i][j].piece); |
---|
379 | list[i][j] = 0; |
---|
380 | } |
---|
381 | else |
---|
382 | #endif |
---|
383 | { |
---|
384 | Piece *below = data->pairs[i][data->dim.j - 1].piece; |
---|
385 | |
---|
386 | /* Change coordinates for the whole column above */ |
---|
387 | for (int j2 = j + 1; j2 < data->dim.j; j2++) |
---|
388 | { |
---|
389 | data->pairs[i][j2 - 1] = data->pairs[i][j2]; |
---|
390 | data->pairs[i][j2 - 1].piece->SetCell(ivec2(i, j2 - 1)); |
---|
391 | data->pairs[i][j2 - 1].piece->Move(ivec2(i, j2 - 1) * data->size); |
---|
392 | list[i][j2 - 1] = list[i][j2]; |
---|
393 | } |
---|
394 | |
---|
395 | /* Spawn a new piece above all the others and attach it to |
---|
396 | * the board. */ |
---|
397 | ivec2 newpos = ivec2(i * data->size.x, |
---|
398 | below->GetPos().y + data->size.y); |
---|
399 | ivec2 newcell = ivec2(i, data->dim.j - 1); |
---|
400 | int id = 1 + rand() % data->npieces; |
---|
401 | Piece *tmp = new Piece(Piece::PIECE_HUNT, data->emitter, |
---|
402 | newcell, id); |
---|
403 | tmp->SetBelow(below); |
---|
404 | tmp->SetPos(newpos); |
---|
405 | tmp->Move(newcell * data->size); |
---|
406 | Ticker::Ref(tmp); |
---|
407 | data->pairs[i][data->dim.j - 1].id = id; |
---|
408 | data->pairs[i][data->dim.j - 1].piece = tmp; |
---|
409 | list[i][data->dim.j - 1] = 0; |
---|
410 | } |
---|
411 | } |
---|
412 | |
---|
413 | mash->nextmash = data->mashes; |
---|
414 | data->mashes = mash; |
---|
415 | |
---|
416 | data->score->Add(multiplier); |
---|
417 | multiplier *= 2; |
---|
418 | } |
---|
419 | while(ListMashes(list)); |
---|
420 | |
---|
421 | data->nmoves = ListMoves(list); |
---|
422 | |
---|
423 | if (data->nmoves == 0) |
---|
424 | { |
---|
425 | Mash *mash = new Mash(data->emitter); |
---|
426 | Ticker::Ref(mash); |
---|
427 | |
---|
428 | for (int j = data->dim.j; j--;) for (int i = 0; i < data->dim.i; i++) |
---|
429 | mash->AddPiece(data->pairs[i][j].piece); |
---|
430 | |
---|
431 | mash->nextmash = data->mashes; |
---|
432 | data->mashes = mash; |
---|
433 | |
---|
434 | Piece *below[MAX_WIDTH]; |
---|
435 | for (int i = 0; i < data->dim.i; i++) |
---|
436 | below[i] = data->pairs[i][data->dim.j - 1].piece; |
---|
437 | |
---|
438 | Fill(); |
---|
439 | |
---|
440 | for (int i = 0; i < data->dim.i; i++) |
---|
441 | data->pairs[i][0].piece->SetBelow(below[i]); |
---|
442 | } |
---|
443 | |
---|
444 | return true; |
---|
445 | } |
---|
446 | |
---|
447 | /* Fill an array with the list of pieces that should disappear due to |
---|
448 | * 3-piece or more alignments. */ |
---|
449 | int Board::ListMashes(int list[MAX_WIDTH][MAX_HEIGHT]) |
---|
450 | { |
---|
451 | int ret = 0; |
---|
452 | |
---|
453 | for (int j = 0; j < data->dim.j; j++) |
---|
454 | for (int i = 0; i < data->dim.i; i++) |
---|
455 | list[i][j] = 0; |
---|
456 | |
---|
457 | for (int j = 0; j < data->dim.j; j++) |
---|
458 | for (int i = 0; i < data->dim.i; i++) |
---|
459 | { |
---|
460 | int id = data->pairs[i][j].id; |
---|
461 | |
---|
462 | if (i + 2 < data->dim.i && data->pairs[i + 1][j].id == id |
---|
463 | && data->pairs[i + 2][j].id == id) |
---|
464 | { |
---|
465 | list[i][j]++; |
---|
466 | list[i + 1][j] += 2; |
---|
467 | list[i + 2][j]++; |
---|
468 | ret = 1; |
---|
469 | } |
---|
470 | |
---|
471 | if (j + 2 < data->dim.j && data->pairs[i][j + 1].id == id |
---|
472 | && data->pairs[i][j + 2].id == id) |
---|
473 | { |
---|
474 | list[i][j]++; |
---|
475 | list[i][j + 1] += 2; |
---|
476 | list[i][j + 2]++; |
---|
477 | ret = 1; |
---|
478 | } |
---|
479 | } |
---|
480 | |
---|
481 | return ret; |
---|
482 | } |
---|
483 | |
---|
484 | /* Fill an array with the list of pieces that can be moved. A value of 1 |
---|
485 | * indicates the piece can be moved right. A value of 2 means it can be |
---|
486 | * moved up, and a value of 3 means both moves are possible. The number |
---|
487 | * of possible moves is returned. */ |
---|
488 | int Board::ListMoves(int moves[MAX_WIDTH][MAX_HEIGHT]) |
---|
489 | { |
---|
490 | int ret = 0; |
---|
491 | |
---|
492 | for (int j = 0; j < data->dim.j; j++) |
---|
493 | for (int i = 0; i < data->dim.i; i++) |
---|
494 | moves[i][j] = 0; |
---|
495 | |
---|
496 | for (int j = 0; j < data->dim.j; j++) |
---|
497 | for (int i = 0; i < data->dim.i; i++) |
---|
498 | { |
---|
499 | /* Copy neighbourhood to a local buffer */ |
---|
500 | int tmp[6][6]; |
---|
501 | |
---|
502 | for (int dj = -2; dj <= 3; dj++) |
---|
503 | for (int di = -2; di <= 3; di++) |
---|
504 | if (j + dj >= 0 && j + dj < data->dim.j |
---|
505 | && i + di >= 0 && i + di < data->dim.i) |
---|
506 | tmp[2 + di][2 + dj] = data->pairs[i + di][j + dj].id; |
---|
507 | else |
---|
508 | tmp[2 + di][2 + dj] = 0; |
---|
509 | |
---|
510 | /* +--+--+--+--+--+--+ |
---|
511 | * | | |25| | | | |
---|
512 | * +--+--+--+--+--+--+ |
---|
513 | * | | |24|34| | | |
---|
514 | * +--+--+--+--+--+--+ |
---|
515 | * |03|13|c |33|43| | |
---|
516 | * +--+--+--+--+--+--+ |
---|
517 | * |02|12|a |b |42|52| |
---|
518 | * +--+--+--+--+--+--+ |
---|
519 | * | |11|21|31| | | |
---|
520 | * +--+--+--+--+--+--+ |
---|
521 | * | | |20|30| | | |
---|
522 | * +--+--+--+--+--+--+ */ |
---|
523 | int a = tmp[2][2]; |
---|
524 | int b = tmp[3][2] ? tmp[3][2] : -1; |
---|
525 | int c = tmp[2][3] ? tmp[2][3] : -1; |
---|
526 | |
---|
527 | /* Try moving right */ |
---|
528 | if ((a == tmp[3][0] && a == tmp[3][1]) || |
---|
529 | (a == tmp[3][1] && a == tmp[3][3]) || |
---|
530 | (a == tmp[3][3] && a == tmp[3][4]) || |
---|
531 | (a == tmp[4][2] && a == tmp[5][2]) || |
---|
532 | (b == tmp[2][0] && b == tmp[2][1]) || |
---|
533 | (b == tmp[2][1] && b == tmp[2][3]) || |
---|
534 | (b == tmp[2][3] && b == tmp[2][4]) || |
---|
535 | (b == tmp[0][2] && b == tmp[1][2])) |
---|
536 | { |
---|
537 | moves[i][j] |= 1; |
---|
538 | ret++; |
---|
539 | } |
---|
540 | |
---|
541 | /* Try moving up */ |
---|
542 | if ((a == tmp[0][3] && a == tmp[1][3]) || |
---|
543 | (a == tmp[1][3] && a == tmp[3][3]) || |
---|
544 | (a == tmp[3][3] && a == tmp[4][3]) || |
---|
545 | (a == tmp[2][4] && a == tmp[2][5]) || |
---|
546 | (c == tmp[0][2] && c == tmp[1][2]) || |
---|
547 | (c == tmp[1][2] && c == tmp[3][2]) || |
---|
548 | (c == tmp[3][2] && c == tmp[4][2]) || |
---|
549 | (c == tmp[2][0] && c == tmp[2][1])) |
---|
550 | { |
---|
551 | moves[i][j] |= 2; |
---|
552 | ret++; |
---|
553 | } |
---|
554 | } |
---|
555 | |
---|
556 | return ret; |
---|
557 | } |
---|
558 | |
---|
559 | Board::~Board() |
---|
560 | { |
---|
561 | Input::UntrackMouse(this); |
---|
562 | |
---|
563 | switch (data->game) |
---|
564 | { |
---|
565 | case GAME_HUNT: |
---|
566 | for (int j = 0; j < data->dim.j; j++) |
---|
567 | for (int i = 0; i < data->dim.i; i++) |
---|
568 | { |
---|
569 | data->pairs[i][j].piece->SetBelow(NULL); |
---|
570 | Ticker::Unref(data->pairs[i][j].piece); |
---|
571 | } |
---|
572 | break; |
---|
573 | } |
---|
574 | Ticker::Unref(data->thumbs); |
---|
575 | Ticker::Unref(data->score); |
---|
576 | while (data->mashes) |
---|
577 | { |
---|
578 | Ticker::Unref(data->mashes); |
---|
579 | data->mashes = data->mashes->nextmash; |
---|
580 | } |
---|
581 | /* FIXME: the emitter may be destroyed after the Tiler is removed, |
---|
582 | * because the last Tiler tick may be done just after the emitter |
---|
583 | * scheduled its sprites! In theory, the emitter should reference |
---|
584 | * the tileset. */ |
---|
585 | Ticker::Unref(data->emitter); |
---|
586 | Tiler::Deregister(data->screen); |
---|
587 | Tiler::Deregister(data->board); |
---|
588 | Tiler::Deregister(data->tiles); |
---|
589 | Tiler::Deregister(data->icons); |
---|
590 | Sampler::Deregister(data->click); |
---|
591 | Sampler::Deregister(data->whip); |
---|
592 | delete data; |
---|
593 | } |
---|
594 | |
---|