1 /* ----====----====----====----====----====----====----====----====----====----
4 JewelToy is a simple game played against the clock.
5 Copyright (C) 2001 Giles Williams
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 ----====----====----====----====----====----====----====----====----====---- */
22 /* kokomonds is a fork of JewelToy.
23 * repository: http://github.com/exterlulz/kokomonds
33 #import "ScoreBubble.h"
43 for (int i = 0; i < 8; i++) {
44 for (int j = 0; j < 8; j++) {
45 board[i][j] = [[Gem alloc] init];
50 scoreBubbles= [[NSMutableArray arrayWithCapacity:12] retain];
56 - (id) initWithImagesFrom:(NSArray *) imageArray
60 srand([[NSDate date] timeIntervalSince1970]); // seed by time
61 for (i = 0; i < 8; i++)
62 for (j = 0; j < 8; j++)
64 // TODO: replace with gem type?
65 int r = [self randomGemTypeAt:i:j];
67 Gem *gem = [[Gem gemWithNumber:r andImage:[imageArray objectAtIndex:r]] retain];
68 gem._positionOnBoard = NSMakePoint(i, j);
69 gem._positionOnScreen = NSMakePoint(i * 48, j * 48);
72 /* TODO: remove, replaced with previous code
73 [board[i][j] setPositionOnBoard:i:j];
74 [board[i][j] setPositionOnScreen:i*48:j*48];
79 scoreBubbles= [[NSMutableArray arrayWithCapacity:12] retain];
87 - (id) initWithSpritesFrom:(NSArray *) spriteArray
91 srand([[NSDate date] timeIntervalSince1970]); // seed by time
92 for (i = 0; i < 8; i++)
93 for (j = 0; j < 8; j++)
95 //int r = (rand() % 3)*2+((i+j)%2);
96 // TODO: replace with gem type?
97 int r = [self randomGemTypeAt:i:j];
98 Gem *gem = [[Gem gemWithNumber:r andSprite:[spriteArray objectAtIndex:r]] retain];
99 gem._positionOnBoard = NSMakePoint(i, j);
100 gem._positionOnScreen = NSMakePoint(i * 48, j * 48);
103 /* TODO: remove, replaced with the previous code
104 [board[i][j] setPositionOnBoard:i:j];
105 [board[i][j] setPositionOnScreen:i*48:j*48];
110 scoreBubbles= [[NSMutableArray arrayWithCapacity:12] retain];
121 for (i = 0; i < 8; i++)
122 for (j = 0; j < 8; j++)
123 [board[i][j] release];
125 [scoreBubbles release];
130 - (void) setImagesFrom:(NSArray *) imageArray
133 for (i = 0; i < 8; i++)
134 for (j = 0; j < 8; j++)
135 [board[i][j] setImage:[imageArray objectAtIndex:[board[i][j] gemType]]];
138 - (void)setSpritesFrom:(NSArray *)spriteArray
141 for (int i = 0; i < 8; i++) {
142 for (int j = 0; j < 8; j++) {
144 [gem setSprite:[spriteArray objectAtIndex:[gem gemType]]];
149 - (int) randomGemTypeAt:(int)x :(int)y
155 return (r & 6); // even
159 return 1; // catch returning 7
162 return (r | 1); // odd
165 - (Gem *) gemAt:(int)x :(int)y {
172 - (NSMutableArray *)scoreBubbles
179 - (void) setMuted:(BOOL)value
184 for (i = 0; i < 8; i++)
185 for (j = 0; j < 8; j++)
186 [board[i][j] setSoundsTink:NULL Sploink:NULL];
188 for (i = 0; i < 8; i++)
189 for (j = 0; j < 8; j++)
190 [board[i][j] setSoundsTink:[NSSound soundNamed:@"tink"] Sploink:[NSSound soundNamed:@"sploink"]];
193 - (void)swap:(int)xa :(int)ya and:(int)xb :(int)yb
195 Gem *swap = board[xa][ya];
196 board[xa][ya] = board[xb][yb];
197 board[xa][ya]._positionOnBoard = NSMakePoint(xa, ya);
198 board[xb][yb] = swap;
199 board[xb][yb]._positionOnBoard = NSMakePoint(xb, yb);
200 sxa = xa; sxb = xb; sya = ya; syb = yb;
204 [self swap:sxa:sya and:sxb:syb];
207 - (BOOL)testForThreeAt:(int) x :(int) y
210 int bonus, linebonus, scorePerGem;
211 float scorebubble_x = -1.0;
212 float scorebubble_y = -1.0;
214 int gemtype = [board[x][y] gemType];
215 tx = x; ty = y; cx = x; cy = y;
217 if (board[x][y].state == GEMSTATE_FADING) {
220 while ((tx > 0)&&([board[tx-1][y] gemType]==gemtype)) tx = tx-1;
221 while ((cx < 7)&&([board[cx+1][y] gemType]==gemtype)) cx = cx+1;
227 scorePerGem = (cx-tx)*5;
228 for (i = tx; i <= cx; i++)
230 linebonus+= scorePerGem;
232 for (j=7; j>y; j--) {
233 if (board[i][j].state != GEMSTATE_FADING) {
234 [board[i][j] shiver]; // MW prepare to fall
238 // to center scorebubble ...
239 scorebubble_x = tx + (cx-tx)/2.0;
245 while ((ty > 0)&&([board[x][ty-1] gemType]==gemtype)) ty = ty-1;
246 while ((cy < 7)&&([board[x][cy+1] gemType]==gemtype)) cy = cy+1;
252 scorePerGem = (cy-ty)*5;
253 for (i = ty; i <= cy; i++)
255 linebonus += scorePerGem;
258 for (j=7; j>cy; j--) {
259 if (board[x][j].state != GEMSTATE_FADING) {
260 [board[x][j] shiver]; // MW prepare to fall
263 // to center scorebubble ...
264 if (scorebubble_x < 0) // only if one hasn't been placed already ! (for T and L shapes)
267 scorebubble_y = ty + (cy-ty)/2.0;
269 else // select the original gem position
286 [scoreBubbles addObject:[ScoreBubble scoreWithValue:bonus*bonusMultiplier
287 at:NSMakePoint(scorebubble_x * 48 + 24, scorebubble_y * 48 + 24)
291 score += bonus * bonusMultiplier;
295 - (BOOL)finalTestForThreeAt:(int)x :(int)y
299 int gemtype = [board[x][y] gemType];
300 tx = x; ty = y; cx = x; cy = y;
302 if (board[x][y].state == GEMSTATE_FADING) return YES;
304 while ((tx > 0)&&([board[tx-1][y] gemType]==gemtype)) tx = tx-1;
305 while ((cx < 7)&&([board[cx+1][y] gemType]==gemtype)) cx = cx+1;
310 for (i = tx; i <= cx; i++)
314 while ((ty > 0)&&([board[x][ty-1] gemType]==gemtype)) ty = ty-1;
315 while ((cy < 7)&&([board[x][cy+1] gemType]==gemtype)) cy = cy+1;
320 for (i = ty; i <= cy; i++)
327 - (BOOL) checkForThreeAt:(int) x :(int) y
330 int gemtype = [board[x][y] gemType];
331 tx = x; ty = y; cx = x; cy = y;
332 while ((tx > 0)&&([board[tx-1][y] gemType]==gemtype)) tx = tx-1;
333 while ((cx < 7)&&([board[cx+1][y] gemType]==gemtype)) cx = cx+1;
336 while ((ty > 0)&&([board[x][ty-1] gemType]==gemtype)) ty = ty-1;
337 while ((cy < 7)&&([board[x][cy+1] gemType]==gemtype)) cy = cy+1;
343 - (BOOL) checkBoardForThrees
347 // CASCADE BONUS increase
350 for (i = 0; i < 8; i++)
351 for (j = 0; j < 8; j++)
352 if (board[i][j].state != GEMSTATE_FADING)
353 result = result | [self testForThreeAt:i:j];
354 // CASCADE BONUS check for reset
355 if (!result) cascade = 1;
360 - (void) showAllBoardMoves
362 // test every possible move
366 for (j = 0; j < 8; j++)
367 for (i = 0; i < 7; i++)
369 [self swap:i:j and:i+1:j];
370 [self finalTestForThreeAt:i:j];
371 [self finalTestForThreeAt:i+1:j];
376 for (i = 0; i < 8; i++)
377 for (j = 0; j < 7; j++)
379 [self swap:i:j and:i:j+1];
380 [self finalTestForThreeAt:i:j];
381 [self finalTestForThreeAt:i:j+1];
385 // over the entire board, set the animationtime for the marked gems higher
386 for (i = 0; i < 8; i++)
387 for (j = 0; j < 8; j++)
389 if (board[i][j].state == GEMSTATE_FADING)
392 [board[i][j] setAnimationCounter:1];
401 - (BOOL) boardHasMoves
403 // test every possible move
407 for (j = 0; j < 8; j++)
408 for (i = 0; i < 7; i++)
410 [self swap:i:j and:i+1:j];
411 result = [self checkForThreeAt:i:j] | [self checkForThreeAt:i+1:j];
422 for (i = 0; i < 8; i++)
423 for (j = 0; j < 7; j++)
425 [self swap:i:j and:i:j+1];
426 result = [self checkForThreeAt:i:j] | [self checkForThreeAt:i:j+1];
438 - (void) removeFadedGemsAndReorganiseWithImagesFrom:(NSArray *) imageArray
441 for (i = 0; i < 8; i++)
446 // let non-faded gems fall into place
447 for (j = 0; j < 8; j++)
449 if (board[i][j].state != GEMSTATE_FADING)
451 column[y] = board[i][j];
452 if (board[i][j]._positionOnScreen.y > y*48)
459 // transfer faded gems to top of column
460 for (j = 0; j < 8; j++)
462 if (board[i][j].state == GEMSTATE_FADING)
465 int r = (rand() % 7);
466 [board[i][j] setGemType:r];
467 [board[i][j] setImage:[imageArray objectAtIndex:r]];
469 column[y] = board[i][j];
470 board[i][j]._positionOnScreen = NSMakePoint(i * 48, (7 + fades) * 48);
477 // OK, shuffling all done - reorganise column
478 for (j = 0; j < 8; j++)
480 board[i][j] = column[j];
481 board[i][j]._positionOnBoard = NSMakePoint(i, j);
486 - (void) removeFadedGemsAndReorganiseWithSpritesFrom:(NSArray *) spriteArray
490 for (int i = 0; i < 8; i++) {
495 // let non-faded gems fall into place
496 for (j = 0; j < 8; j++) {
497 if (board[i][j].state != GEMSTATE_FADING) {
498 column[y] = board[i][j];
499 if (board[i][j]._positionOnScreen.y > y * 48)
508 // transfer faded gems to top of column
509 for (j = 0; j < 8; j++)
511 if (board[i][j].state == GEMSTATE_FADING)
514 int r = (rand() % 7);
515 [board[i][j] setGemType:r];
516 [board[i][j] setSprite:[spriteArray objectAtIndex:r]];
518 column[y] = board[i][j];
519 board[i][j]._positionOnScreen = NSMakePoint(i * 48, (7 + fades) * 48);
526 // OK, shuffling all done - reorganise column
527 for (j = 0; j < 8; j++)
529 board[i][j] = column[j];
530 board[i][j]._positionOnBoard = NSMakePoint(i, j);
538 for (i = 0; i < 8; i++)
539 for (j = 0; j < 8; j++)
546 if (!muted) [[NSSound soundNamed:@"yes"] play];
547 for (i = 0; i < 8; i++)
548 for (j = 0; j < 8; j++)
552 - (void) explodeGameOver
555 if (!muted) [[NSSound soundNamed:@"explosion"] play];
557 for (i = 0; i < 8; i++)
558 for (j = 0; j < 8; j++)
561 [self showAllBoardMoves]; // does a delayed eruption
564 - (void) wholeNewGameWithImagesFrom:(NSArray *) imageArray
567 srand([[NSDate date] timeIntervalSince1970]); // seed by time
568 for (i = 0; i < 8; i++)
569 for (j = 0; j < 8; j++)
571 //int r = (rand() % 3)*2+((i+j)%2);
572 int r = [self randomGemTypeAt:i:j];
573 [board[i][j] setGemType:r];
574 [board[i][j] setImage:[imageArray objectAtIndex:r]];
575 board[i][j]._positionOnBoard = NSMakePoint(i, j);
576 board[i][j]._positionOnScreen = NSMakePoint(i * 48, (15 - j) * 48);
584 - (void) wholeNewGameWithSpritesFrom:(NSArray *) spriteArray
587 srand([[NSDate date] timeIntervalSince1970]); // seed by time
588 for (i = 0; i < 8; i++)
589 for (j = 0; j < 8; j++)
591 //int r = (rand() % 3)*2+((i+j)%2);
592 int r = [self randomGemTypeAt:i:j];
593 [board[i][j] setGemType:r];
594 [board[i][j] setSprite:[spriteArray objectAtIndex:r]];
595 board[i][j]._positionOnBoard = NSMakePoint(i, j);
596 board[i][j]._positionOnScreen = NSMakePoint(i * 48, (15 - j) * 48);
604 - (NSPoint) hintPoint {
605 return NSMakePoint(hintx * 48,hinty * 48);
608 - (float)collectGemsFaded
610 float result = (float)gemsFaded;
619 - (int)bonusMultiplier {
620 return bonusMultiplier;
623 - (void)increaseBonusMultiplier {