1 /* ----====----====----====----====----====----====----====----====----====----
2 GameController.m (jeweltoy)
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
28 #import "GameController.h"
34 @implementation GameController
40 hiScores = [[NSUserDefaults standardUserDefaults] arrayForKey:@"hiScores"];
42 //NSLog(@"hiScores : %@",hiScores);
44 if ((!hiScores)||([hiScores count] < 8))
46 //NSLog(@"Creating High Score Tables");
47 hiScores = [self makeBlankHiScoresWith:hiScores];
48 [[NSUserDefaults standardUserDefaults] setObject:hiScores forKey:@"hiScores"];
52 noMoreMovesString = [[NSBundle mainBundle]
53 localizedStringForKey:@"NoMoreMovesHTML"
55 jeweltoyStartString = [[NSBundle mainBundle]
56 localizedStringForKey:@"JewelToyStartHTML"
58 gameOverString = [[NSBundle mainBundle]
59 localizedStringForKey:@"GameOverHTML"
61 titleImage = [NSImage imageNamed:@"title"];
63 gameNames = [hiScores objectAtIndex:0];
64 gameScores = [hiScores objectAtIndex:1];
66 game = [[Game alloc] init];
67 animationTimerLock = [[NSLock alloc] init];
69 gemMoveSize = GEM_GRAPHIC_SIZE;
70 gemMoveSpeed = GEM_MOVE_SPEED;
71 gemMoveSteps = gemMoveSize / gemMoveSpeed;
73 useAlternateGraphics = [[NSUserDefaults standardUserDefaults] boolForKey:@"useAlternateGraphics"];
74 useImportedGraphics = [[NSUserDefaults standardUserDefaults] boolForKey:@"useImportedGraphics"];
76 useCustomBackgrounds = [[NSUserDefaults standardUserDefaults] boolForKey:@"useCustomBackgrounds"];
77 customBackgroundFolderPath = [[NSUserDefaults standardUserDefaults] stringForKey:@"customBackgroundFolderPath"];
78 if (!customBackgroundFolderPath)
79 customBackgroundFolderPath = [[NSBundle mainBundle] localizedStringForKey:@"PicturesFolderPath"
88 [noMoreMovesString release];
89 noMoreMovesString = nil;
91 [jeweltoyStartString release];
92 jeweltoyStartString = nil;
94 [gameOverString release];
100 [animationTimerLock release];
101 animationTimerLock = nil;
114 [gameWindow setFrameAutosaveName:@"gameWindow"];
115 //useAlternateGraphics = [[NSUserDefaults standardUserDefaults] boolForKey:@"useAlternateGraphics"];
118 - (void)windowWillClose:(NSNotification *)aNotification
120 id obj = [aNotification object];
121 if (obj == aboutPanel)
123 //NSLog(@"Someone closed the 'About' window");
127 if (obj == prefsPanel)
129 //NSLog(@"Someone closed the 'Preferences' window");
130 useAlternateGraphics = [prefsAlternateGraphicsButton state];
131 [[NSUserDefaults standardUserDefaults] setBool:useAlternateGraphics
132 forKey:@"useAlternateGraphics"];
133 [[NSUserDefaults standardUserDefaults] setBool:useImportedGraphics
134 forKey:@"useImportedGraphics"];
136 useCustomBackgrounds = [prefsCustomBackgroundCheckbox state];
137 [[NSUserDefaults standardUserDefaults] setBool:useCustomBackgrounds
138 forKey:@"useCustomBackgrounds"];
139 [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"customBackgroundFolderPath"];
140 [[NSUserDefaults standardUserDefaults] setObject:[prefsCustomBackgroundFolderTextField stringValue]
141 forKey:@"customBackgroundFolderPath"];
144 //[gameView loadImageArray];
145 [gameView graphicSetUp];
146 [gameView newBackground];
147 if (game) [game setSpritesFrom:[gameView spriteArray]];
148 [gameView setNeedsDisplay:YES];
153 if (obj == gameWindow)
155 //NSLog(@"Someone closed the window - shutting down JewelToy");
156 [NSApp terminate:self];
161 - (void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
163 #pragma unused (returnCode, contextInfo)
164 [prefsCustomBackgroundFolderTextField setStringValue:[[sheet filenames] objectAtIndex:0]];
167 - (IBAction)prefsGraphicDropAction:(id)sender
169 #pragma unused (sender)
171 // slice and dice importedImage, saving images to defaults
172 NSImage *importedImage = [prefsAlternateGraphicsImageView image];
176 NSRect cropRect = NSMakeRect(0.0,0.0,[importedImage size].width/7.0,[importedImage size].height);
177 NSRect gemRect = NSMakeRect(0.0,0.0,48.0,48.0);
178 NSSize imageSize = NSMakeSize(48.0,48.0);
179 for (i = 0; i < 7; i++)
181 NSImage *gemImage = [[NSImage alloc] initWithSize:imageSize];
182 NSString *key = [NSString stringWithFormat:@"tiffGemImage%d", i];
183 cropRect.origin.x = i * [importedImage size].width/7.0;
184 [gemImage lockFocus];
185 [[NSColor clearColor] set];
187 [importedImage drawInRect:gemRect fromRect:cropRect operation:NSCompositeSourceOver fraction:1.0];
188 [gemImage unlockFocus];
189 [[NSUserDefaults standardUserDefaults] setObject:[gemImage TIFFRepresentation] forKey:key];
190 if (i == 0) [iv1 setImage:gemImage];
191 if (i == 1) [iv2 setImage:gemImage];
192 if (i == 2) [iv3 setImage:gemImage];
193 if (i == 3) [iv4 setImage:gemImage];
194 if (i == 4) [iv5 setImage:gemImage];
195 if (i == 5) [iv6 setImage:gemImage];
196 if (i == 6) [iv7 setImage:gemImage];
199 useImportedGraphics = YES;
204 - (IBAction)prefsCustomBackgroundCheckboxAction:(id)sender
206 //NSLog(@"prefsCustomBackgroundCheckboxAction");
208 if (sender!=prefsCustomBackgroundCheckbox)
210 [prefsSelectFolderButton setEnabled:[prefsCustomBackgroundCheckbox state]];
211 [prefsCustomBackgroundFolderTextField setEnabled:[prefsCustomBackgroundCheckbox state]];
215 - (IBAction)prefsSelectFolderButtonAction:(id)sender
217 #pragma unused (sender)
219 NSOpenPanel *op=[NSOpenPanel openPanel];
221 //NSLog(@"prefsSelectFolderButtonAction");
222 [op setCanChooseDirectories:YES];
223 [op setCanChooseFiles:NO];
224 // get a sheet going to let the user pick a folder to scan for pictures
225 [op beginSheetForDirectory:[prefsCustomBackgroundFolderTextField stringValue] file:NULL types:NULL modalForWindow:prefsPanel modalDelegate:self didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:) contextInfo:NULL];
229 - (BOOL) validateMenuItem: (NSMenuItem*) aMenuItem
231 if (aMenuItem == easyGameMenuItem)
232 return [easyGameButton isEnabled];
233 if (aMenuItem == hardGameMenuItem)
234 return [hardGameButton isEnabled];
235 if (aMenuItem == toughGameMenuItem)
236 return [toughGameButton isEnabled];
237 if (aMenuItem == freePlayMenuItem)
238 return [easyGameButton isEnabled];
239 if (aMenuItem == abortGameMenuItem)
240 return [abortGameButton isEnabled];
241 if (aMenuItem == pauseGameMenuItem)
242 return [pauseGameButton isEnabled];
244 // only allow viewing and reset of scores between games
246 if (aMenuItem == showHighScoresMenuItem)
247 return [easyGameButton isEnabled];
248 if (aMenuItem == resetHighScoresMenuItem)
249 return [easyGameButton isEnabled];
253 - (IBAction)startNewGame:(id)sender
255 //NSLog(@"gameController.startNewGame messaged gameView:%@",gameView);
257 [easyGameButton setEnabled:NO];
258 [hardGameButton setEnabled:NO];
259 [toughGameButton setEnabled:NO];
260 [abortGameButton setEnabled:YES];
261 [pauseGameButton setEnabled:YES];
267 if ((sender==easyGameButton)||(sender==easyGameMenuItem))
269 //NSLog(@"debug - hiScores = %@\n...hiScores.count = %d",hiScores,[hiScores count]);
271 gameTime = 600.0; // ten minutes
272 [gameView setHTMLHiScoreLegend:[[NSBundle mainBundle]
273 localizedStringForKey:@"EasyHighScoresHTML"
274 value:nil table:nil]];
276 if ((sender==hardGameButton)||(sender==hardGameMenuItem))
279 gameTime = 180.0; // three minutes
280 [gameView setHTMLHiScoreLegend:[[NSBundle mainBundle]
281 localizedStringForKey:@"HardHighScoresHTML"
282 value:nil table:nil]];
285 if ((sender==toughGameButton)||(sender==toughGameMenuItem))
288 gameTime = 90.0; // one and a half minutes
289 [gameView setHTMLHiScoreLegend:[[NSBundle mainBundle]
290 localizedStringForKey:@"ToughHighScoresHTML"
291 value:nil table:nil]];
293 if (sender==freePlayMenuItem)
296 gameTime = 3600.0; // one hour FWIW
297 freePlay = YES;// FREEPLAY
298 [gameView setHTMLHiScoreLegend:[[NSBundle mainBundle]
299 localizedStringForKey:@"FreePlayHighScoresHTML"
300 value:nil table:nil]];
303 freePlay = NO;// FREEPLAY
304 gameNames = [hiScores objectAtIndex:gameLevel*2];
305 gameScores = [hiScores objectAtIndex:gameLevel*2+1];
306 [game wholeNewGameWithSpritesFrom:[gameView spriteArray]];
309 [scoreTextField setStringValue:[NSString stringWithFormat:@"%d",[game score]]];
310 [scoreTextField setNeedsDisplay:YES];
311 [bonusTextField setStringValue:[NSString stringWithFormat:@"x%d",[game bonusMultiplier]]];
312 [bonusTextField setNeedsDisplay:YES];
315 [game setMuted:muted];
316 [gameView setGame:game];
317 [gameView setLegend:nil];
318 [gameView setPaused:NO];
319 [gameView setMuted:muted];
320 [gameView setShowHint:!freePlay];// FREEPLAY
322 [timerView setTimerRunningEvery:0.5/gameSpeed
323 decrement:(0.5/gameTime)
325 whenRunOut:@selector(runOutOfTime)
326 whenRunOver:@selector(bonusAwarded)];
330 [timerView setDecrement:0.0];// FREEPLAY MW
331 [timerView setTimer:0.0];
334 [timerView setPaused:YES];
336 [gameView setLastMoveDate];
337 [self startAnimation:@selector(waitForFirstClick)];
340 - (IBAction)abortGame:(id)sender
342 #pragma unused (sender)
344 [abortGameButton setEnabled:NO];
345 if (paused) [self togglePauseMode:self];
346 [pauseGameButton setEnabled:NO];
348 [self waitForFirstClick];
350 - (IBAction)receiveHiScoreName:(id)sender
352 #pragma unused (sender)
355 int score = [hiScorePanelScoreTextField intValue];
356 NSString *name = [hiScorePanelNameTextField stringValue];
358 [NSApp endSheet:hiScorePanel];
359 [hiScorePanel close];
361 //NSLog(@"receiving HiScoreName:%@ %d",name,score);
363 // reset arrays to gameLevel
364 gameNames = [hiScores objectAtIndex:gameLevel*2];
365 gameScores = [hiScores objectAtIndex:gameLevel*2+1];
367 for (i = 0; i < 10; i++)
369 if (score > [[gameScores objectAtIndex:i] intValue])
371 [gameScores insertObject:[NSNumber numberWithInt:score] atIndex:i];
372 [gameScores removeObjectAtIndex:10];
373 [gameNames insertObject:name atIndex:i];
374 [gameNames removeObjectAtIndex:10];
379 [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"hiScores"]; // or it won't work!?!
380 [[NSUserDefaults standardUserDefaults] setObject:hiScores forKey:@"hiScores"];
382 //NSLog(@"written high-scores to preferences");
384 gameState = GAMESTATE_GAMEOVER;
385 [gameView showHighScores:gameScores andNames:gameNames];
386 [gameView setLastMoveDate]; //reset timer so scores show for 20s
389 - (IBAction)togglePauseMode:(id)sender
391 //NSLog(@"Pause game toggled, sender state is %d",[sender state]);
392 if (sender == pauseGameButton)
393 paused = [pauseGameButton state];
397 [pauseGameButton setState:paused];
398 [timerView setPaused:paused];
401 [gameView setPaused:YES];
402 [gameView setHTMLLegend:[[NSBundle mainBundle]
403 localizedStringForKey:@"PausedHTML"
404 value:nil table:nil]];
405 [pauseGameMenuItem setTitle:[[NSBundle mainBundle]
406 localizedStringForKey:@"ContinueGameMenuItemTitle"
407 value:nil table:nil]];
411 [gameView setPaused:NO];
412 [gameView setLegend:nil];
413 [pauseGameMenuItem setTitle:[[NSBundle mainBundle]
414 localizedStringForKey:@"PauseGameMenuItemTitle"
415 value:nil table:nil]];
419 - (IBAction)toggleMute:(id)sender
421 if (sender == muteButton)
422 muted = [muteButton state];
426 [muteButton setState:muted];
427 [gameView setMuted:muted];
428 [game setMuted:muted];
431 [muteMenuItem setTitle:[[NSBundle mainBundle]
432 localizedStringForKey:@"UnMuteGameMenuItemTitle"
433 value:nil table:nil]];
435 [muteMenuItem setTitle:[[NSBundle mainBundle]
436 localizedStringForKey:@"MuteGameMenuItemTitle"
437 value:nil table:nil]];
441 - (IBAction)orderFrontAboutPanel:(id)sender
443 #pragma unused (sender)
445 //NSLog(@"GameController showAboutPanel called");
447 [NSBundle loadNibNamed:@"About" owner:self];
448 [aboutPanel setFrameAutosaveName:@"aboutPanel"];
449 [aboutPanel makeKeyAndOrderFront:self];
452 - (IBAction)orderFrontPreferencesPanel:(id)sender
454 #pragma unused (sender)
457 [NSBundle loadNibNamed:@"Preferences" owner:self];
460 [prefsStandardGraphicsButton setState:!useAlternateGraphics];
461 [prefsAlternateGraphicsButton setState:useAlternateGraphics];
463 [prefsCustomBackgroundCheckbox setState:useCustomBackgrounds];
464 [prefsCustomBackgroundFolderTextField setStringValue:customBackgroundFolderPath];
465 [prefsSelectFolderButton setEnabled:[prefsCustomBackgroundCheckbox state]];
466 [prefsCustomBackgroundFolderTextField setEnabled:[prefsCustomBackgroundCheckbox state]];
468 if ([[NSUserDefaults standardUserDefaults] dataForKey:@"tiffGemImage0"])
471 for (i = 0; i < 7; i++)
473 NSString *key = [NSString stringWithFormat:@"tiffGemImage%d", i];
474 NSData *tiffData = [[NSUserDefaults standardUserDefaults] dataForKey:key];
475 NSImage *gemImage = [[NSImage alloc] initWithData:tiffData];
476 if (i == 0) [iv1 setImage:gemImage];
477 if (i == 1) [iv2 setImage:gemImage];
478 if (i == 2) [iv3 setImage:gemImage];
479 if (i == 3) [iv4 setImage:gemImage];
480 if (i == 4) [iv5 setImage:gemImage];
481 if (i == 5) [iv6 setImage:gemImage];
482 if (i == 6) [iv7 setImage:gemImage];
487 [prefsPanel setFrameAutosaveName:@"prefsPanel"];
488 [prefsPanel makeKeyAndOrderFront:self];
491 - (IBAction)showHighScores:(id)sender
493 #pragma unused (sender)
495 // rotate which scores to show
496 gameNames = [hiScores objectAtIndex:gameLevel*2];
497 gameScores = [hiScores objectAtIndex:gameLevel*2+1];
499 [gameView setHTMLHiScoreLegend:[[NSBundle mainBundle]
500 localizedStringForKey:@"EasyHighScoresHTML"
501 value:nil table:nil]];
502 else if (gameLevel==1)
503 [gameView setHTMLHiScoreLegend:[[NSBundle mainBundle]
504 localizedStringForKey:@"HardHighScoresHTML"
505 value:nil table:nil]];
506 else if (gameLevel==2)
507 [gameView setHTMLHiScoreLegend:[[NSBundle mainBundle]
508 localizedStringForKey:@"ToughHighScoresHTML"
509 value:nil table:nil]];
510 else if (gameLevel==3)
511 [gameView setHTMLHiScoreLegend:[[NSBundle mainBundle]
512 localizedStringForKey:@"FreePlayHighScoresHTML"
513 value:nil table:nil]];
514 gameLevel = (gameLevel +1)%4;
516 [gameView showHighScores:gameScores andNames:gameNames];
517 [gameView setLastMoveDate]; //reset timer so scores show for 20s
520 - (IBAction)resetHighScores:(id)sender
522 // don't rotate which scores to show
524 // blank the hi scores
527 hiScores = [[self makeBlankHiScoresWith:nil] retain];
528 [[NSUserDefaults standardUserDefaults] setObject:hiScores forKey:@"hiScores"];
530 [self showHighScores:sender]; //call the show scores routine
533 - (NSArray *)makeBlankHiScoresWith:(NSArray *)oldScores
537 NSMutableArray *result = [NSMutableArray arrayWithCapacity:0];
539 if (oldScores) result = [NSMutableArray arrayWithArray:oldScores];
541 //for (i = 0; i < 3; i++)
542 while ([result count] < 8)
544 NSMutableArray *scores = [NSMutableArray arrayWithCapacity:0];
545 NSMutableArray *names = [NSMutableArray arrayWithCapacity:0];
546 for (j = 0; j < 10; j++)
548 [scores addObject:[NSNumber numberWithInt:1000]];
549 [names addObject:[[NSBundle mainBundle]
550 localizedStringForKey:@"AnonymousName"
551 value:nil table:nil]];
553 [result addObject:names];
554 [result addObject:scores];
556 return [NSArray arrayWithArray:result];
561 gameState = GAMESTATE_GAMEOVER;
562 [abortGameButton setEnabled:NO];
563 [pauseGameButton setEnabled:NO];
565 [gameView setHTMLLegend:gameOverString];
567 [self startAnimation:@selector(waitForFirstClick)];
570 - (void)checkHiScores
573 // reset arrays with gameLevel
574 gameNames = [hiScores objectAtIndex:gameLevel*2];
575 gameScores = [hiScores objectAtIndex:gameLevel*2+1];
576 for (i = 0; i < 10; i++)
578 if ([game score] > [[gameScores objectAtIndex:i] intValue])
580 [hiScorePanelScoreTextField
581 setStringValue:[NSString stringWithFormat:@"%d",[game score]]];
582 [NSApp beginSheet:hiScorePanel
583 modalForWindow:gameWindow
590 [gameView showHighScores:gameScores andNames:gameNames];
596 [gameView newBackground];
598 if (!muted) [[NSSound soundNamed:@"yes"] play];
600 if (!freePlay) { // FREEPLAY MW
601 [game increaseBonusMultiplier];
602 [timerView decrementMeter:0.5];
604 [game increaseBonusMultiplier];
605 [timerView decrementMeter:1];
608 if (gameSpeed < SPEED_LIMIT) // capping speed limit
609 gameSpeed = gameSpeed * 1.5;
610 //NSLog(@"...gamesSpeed %f",gameSpeed);
611 [timerView setTimerRunningEvery:0.5/gameSpeed
612 decrement:(0.5/gameTime)
614 whenRunOut:@selector(runOutOfTime)
615 whenRunOver:@selector(bonusAwarded)];
617 if (freePlay) [timerView setDecrement:0];// FREEPLAY
620 - (void)startAnimation:(SEL)andThenSelector
622 [animationTimerLock lock];
625 timer = [[NSTimer scheduledTimerWithTimeInterval:TIMER_INTERVAL
627 selector:@selector(animate)
629 repeats:YES] retain];
631 whatNext = andThenSelector;
633 [gameView setAnimating:YES];
635 [animationTimerLock unlock];
638 - (void)animationEnded
640 //NSLog(@"gameController.animationEnded messaged");
642 [animationTimerLock lock];
644 [gameView setAnimating:NO];
646 [animationTimerLock unlock];
648 if (whatNext) [self performSelector:whatNext];
650 [gameView setNeedsDisplay:YES];
653 - (void)waitForNewGame
655 [self checkHiScores];
657 [game wholeNewGameWithSpritesFrom:[gameView spriteArray]];
658 [gameView setLegend:titleImage];
659 [easyGameButton setEnabled:YES];
660 [hardGameButton setEnabled:YES];
661 [toughGameButton setEnabled:YES];
662 [abortGameButton setEnabled:NO];
663 [pauseGameButton setEnabled:NO];
668 //NSLog(@"newBoard1");
670 [self startAnimation:@selector(newBoard2)];
678 //NSLog(@"newBoard2");
679 for (int i = 0; i < 8; i++) {
680 for (int j = 0; j < 8; j++) {
681 gem = [game gemAt:i:j];
684 //[gem setImage:[[gameView imageArray] objectAtIndex:r]];
685 [gem setSprite:[[gameView spriteArray] objectAtIndex:r]];
686 gem._positionOnBoard = NSMakePoint(i, j);
687 gem._positionOnScreen = NSMakePoint(i * 48, (i + j + 8) * 48);
691 [gameView newBackground];
692 [gameView setLegend:nil];
693 [self startAnimation:@selector(testForThreesAgain)];
696 - (void)waitForFirstClick
698 //NSLog(@"waitForFirstClick");
699 /*- if (!freePlay) MW CHANGE -*/ [timerView setPaused:NO];
702 [timerView setTimer:0.5];
703 gameState = GAMESTATE_GAMEOVER;
704 [game explodeGameOver];
705 [self startAnimation:@selector(waitForNewGame)];
708 if (![game boardHasMoves])
710 [timerView setPaused:YES];
711 [gameView setHTMLLegend:noMoreMovesString];
714 if (freePlay) [self startAnimation:@selector(runOutOfTime)];// FREEPLAY
715 else [self startAnimation:@selector(newBoard1)];// FREEPLAY
719 gameState = GAMESTATE_AWAITINGFIRSTCLICK;
722 - (void)receiveClickAt:(int)x :(int)y
725 if ((x < 0)||(x > 383)||(y < 0)||(y > 383)) return;
726 if (gameState == GAMESTATE_AWAITINGFIRSTCLICK)
728 chxa = floor(x / 48);
729 chya = floor(y / 48);
730 gameState = GAMESTATE_AWAITINGSECONDCLICK;
731 [gameView setNeedsDisplay:YES];
734 if (gameState == GAMESTATE_AWAITINGSECONDCLICK)
736 chxb = floor(x / 48);
737 chyb = floor(y / 48);
738 if ((chxb != chxa)^(chyb != chya)) // xor!
740 int d = (chxa - chxb) * (chxa - chxb) + (chya - chyb) * (chya - chyb);
741 //NSLog(@"square distance ==%d",d);
744 gameState = GAMESTATE_FRACULATING;
745 [gameView setNeedsDisplay:YES];
746 [gameView setLastMoveDate];
747 /*- MW CHANGE if (!freePlay) -*/ [timerView setPaused:YES];
748 [self tryMoveSwapping:chxa:chya and:chxb:chyb];
752 // fall out of routine setting first click location
753 chxa = floor(x / 48);
754 chya = floor(y / 48);
755 gameState = GAMESTATE_AWAITINGSECONDCLICK;
756 [gameView setNeedsDisplay:YES];
761 - (void)tryMoveSwapping:(int)xA :(int)yA and:(int)xB :(int)yB
764 int xxa, yya, xxb, yyb;
766 //NSLog(@"tryMoveSwapping");
792 // store swap positions
793 chxa = xxa; chya = yya;
794 chxb = xxb; chyb = yyb;
797 if (chxa < chxb) { // swapping horizontally
798 [[game gemAt:chxa:chya] setVelocity:gemMoveSpeed:0:gemMoveSteps];
799 [[game gemAt:chxb:chyb] setVelocity:-gemMoveSpeed:0:gemMoveSteps];
801 else { // swapping vertically
802 [[game gemAt:chxa:chya] setVelocity:0:gemMoveSpeed:gemMoveSteps];
803 [[game gemAt:chxb:chyb] setVelocity:0:-gemMoveSpeed:gemMoveSteps];
806 [game swap:chxa:chya and:chxb:chyb];
807 gameState = GAMESTATE_SWAPPING;
809 [self startAnimation:@selector(testForThrees)];
812 - (void)testForThrees
815 int oldScore = [game score];
816 //NSLog(@"testForThrees");
817 anyThrees = ([game testForThreeAt:chxa:chya])|([game testForThreeAt:chxb:chyb]);
818 [scoreTextField setStringValue:[NSString stringWithFormat:@"%d",[game score]]];
819 [scoreTextField setNeedsDisplay:YES];
820 [bonusTextField setStringValue:[NSString stringWithFormat:@"x%d",[game bonusMultiplier]]];
821 [bonusTextField setNeedsDisplay:YES];
822 if ([game score] > oldScore) [timerView incrementMeter:[game collectGemsFaded]/GEMS_FOR_BONUS];
824 [self startAnimation:@selector(removeThreesAndReplaceGems)]; // fade gems
831 //// repeat: remove threes
832 - (void)removeThreesAndReplaceGems
835 //NSLog(@"removeThreesAndReplaceGems");
837 [game removeFadedGemsAndReorganiseWithSpritesFrom:[gameView spriteArray]];
839 [self startAnimation:@selector(testForThreesAgain)]; // gems fall down
842 - (void)testForThreesAgain
845 int oldScore = [game score];
846 //NSLog(@"testForThreesAgain");
847 anyThrees = [game checkBoardForThrees];
848 [scoreTextField setStringValue:[NSString stringWithFormat:@"%d",[game score]]];
849 [scoreTextField setNeedsDisplay:YES];
850 [bonusTextField setStringValue:[NSString stringWithFormat:@"x%d",[game bonusMultiplier]]];
851 [bonusTextField setNeedsDisplay:YES];
852 if ([game score] > oldScore) [timerView incrementMeter:[game collectGemsFaded]/GEMS_FOR_BONUS];
854 [self startAnimation:@selector(removeThreesAndReplaceGems)]; // fade gems
856 [self waitForFirstClick];
858 //// allow gems to fall
860 //// until there are no threes
866 if (!muted) [[NSSound soundNamed:@"no"] play];
869 if (chxa < chxb) { // swapping horizontally
870 [[game gemAt:chxa:chya] setVelocity:4:0:12];
871 [[game gemAt:chxb:chyb] setVelocity:-4:0:12];
873 else { // swapping vertically
874 [[game gemAt:chxa:chya] setVelocity:0:4:12];
875 [[game gemAt:chxb:chyb] setVelocity:0:-4:12];
878 [game swap:chxa:chya and:chxa:chya];
879 gameState = GAMESTATE_SWAPPING;
880 [self startAnimation:@selector(waitForFirstClick)];
888 - (BOOL) gameIsPaused {
892 - (BOOL) useCustomBackgrounds {
893 return useCustomBackgrounds;
896 - (NSPoint) crossHair1Position {
897 return NSMakePoint(chxa * 48,chya * 48);
900 - (NSPoint) crossHair2Position {
901 return NSMakePoint(chxb * 48,chyb * 48);