rename GameController.animating property
[exterlulz-kokogems.git] / src / GameController.m
blobc1f2c4079ba1b5d77328793fad02be8e3067817c
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 #import "GameController.h"
23 #import "TimerView.h"
24 #import "Game.h"
25 #import "GameView.h"
26 #import "Gem.h"
28 @implementation GameController
30 @synthesize gameState = _gameState;
32 @dynamic crossHair1Position;
33 @dynamic crossHair2Position;
35 - (id) init
37     self = [super init];
38     
39     hiScores = [[NSUserDefaults standardUserDefaults] arrayForKey:@"hiScores"];
41     //NSLog(@"hiScores : %@",hiScores);
43     if ((!hiScores)||([hiScores count] < 8))
44     {
45         //NSLog(@"Creating High Score Tables");
46         hiScores = [self makeBlankHiScoresWith:hiScores];
47         [[NSUserDefaults standardUserDefaults] setObject:hiScores forKey:@"hiScores"];
48     }
49     [hiScores retain];
50     
51     noMoreMovesString = [[NSBundle mainBundle]
52                             localizedStringForKey:@"NoMoreMovesHTML"
53                             value:nil table:nil];
54     jeweltoyStartString = [[NSBundle mainBundle]
55                             localizedStringForKey:@"JewelToyStartHTML"
56                             value:nil table:nil];
57     gameOverString = [[NSBundle mainBundle]
58                             localizedStringForKey:@"GameOverHTML"
59                             value:nil table:nil];
60     titleImage = [NSImage imageNamed:@"title"];
61     gameLevel = 0;
62     gameNames = [hiScores objectAtIndex:0];
63     gameScores = [hiScores objectAtIndex:1];
64         
65     game = [[Game alloc] init];
66     animationTimerLock = [[NSLock alloc] init];
67     
68     gemMoveSize = GEM_GRAPHIC_SIZE;
69     gemMoveSpeed = GEM_MOVE_SPEED;
70     gemMoveSteps = gemMoveSize / gemMoveSpeed;
71         
72     useAlternateGraphics = [[NSUserDefaults standardUserDefaults] boolForKey:@"useAlternateGraphics"];
73     useImportedGraphics = [[NSUserDefaults standardUserDefaults] boolForKey:@"useImportedGraphics"];
74     
75     useCustomBackgrounds = [[NSUserDefaults standardUserDefaults] boolForKey:@"useCustomBackgrounds"];
76     customBackgroundFolderPath = [[NSUserDefaults standardUserDefaults] stringForKey:@"customBackgroundFolderPath"];
77     if (!customBackgroundFolderPath)
78         customBackgroundFolderPath = [[NSBundle mainBundle] localizedStringForKey:@"PicturesFolderPath"
79                                                                             value:nil table:nil];
80     return self;
83 - (void) dealloc
85     if (noMoreMovesString)      [noMoreMovesString release];
86     if (jeweltoyStartString)    [jeweltoyStartString release];
87     if (gameOverString) [gameOverString release];
88     if (game) [game release];
89     if (animationTimerLock) [animationTimerLock release];
90     if (timer)  [timer release];
91     if (hiScores)       [hiScores release];
92     [super dealloc];
95 - (void)awakeFromNib
97     [gameWindow setFrameAutosaveName:@"gameWindow"];
98     //useAlternateGraphics = [[NSUserDefaults standardUserDefaults] boolForKey:@"useAlternateGraphics"];
101 - (void)windowWillClose:(NSNotification *)aNotification
103     id obj = [aNotification object];
104     if (obj == aboutPanel)
105     {
106         //NSLog(@"Someone closed the 'About' window");
107         aboutPanel = nil;
108         return;
109     }
110     if (obj == prefsPanel)
111     {
112         //NSLog(@"Someone closed the 'Preferences' window");
113         useAlternateGraphics = [prefsAlternateGraphicsButton state];
114         [[NSUserDefaults standardUserDefaults]  setBool:useAlternateGraphics
115                                                 forKey:@"useAlternateGraphics"];
116         [[NSUserDefaults standardUserDefaults]  setBool:useImportedGraphics
117                                                 forKey:@"useImportedGraphics"];
119         useCustomBackgrounds = [prefsCustomBackgroundCheckbox state];
120         [[NSUserDefaults standardUserDefaults]  setBool:useCustomBackgrounds
121                                                 forKey:@"useCustomBackgrounds"];
122         [[NSUserDefaults standardUserDefaults]  removeObjectForKey:@"customBackgroundFolderPath"];
123         [[NSUserDefaults standardUserDefaults]  setObject:[prefsCustomBackgroundFolderTextField stringValue]
124                                                   forKey:@"customBackgroundFolderPath"];
125         if (gameView)
126         {
127             //[gameView loadImageArray];
128             [gameView graphicSetUp];
129             [gameView newBackground];
130             if (game)   [game setSpritesFrom:[gameView spriteArray]];
131             [gameView setNeedsDisplay:YES];
132         }
133         prefsPanel = nil;
134         return;
135     }
136     if (obj == gameWindow)
137     {
138         //NSLog(@"Someone closed the window - shutting down JewelToy");
139         [NSApp terminate:self];
140         return;
141     }
144 - (void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void  *)contextInfo {
145   #pragma unused (returnCode, contextInfo)
146   [prefsCustomBackgroundFolderTextField setStringValue:[[sheet filenames] objectAtIndex:0]];
149 // TODO: move algorithm to its own method
150 - (IBAction)prefsGraphicDropAction
152     //
153     //  slice and dice importedImage, saving images to defaults
154     //
155     NSImage *importedImage = [prefsAlternateGraphicsImageView image];
156     if (importedImage)
157     {
158         int i = 0;
159         NSRect  cropRect = NSMakeRect(0.0,0.0,[importedImage size].width/7.0,[importedImage size].height);
160         NSRect  gemRect = NSMakeRect(0.0,0.0,48.0,48.0);
161         NSSize imageSize = NSMakeSize(48.0,48.0);
162         for (i = 0; i < 7; i++)
163         {
164             NSImage     *gemImage = [[NSImage alloc] initWithSize:imageSize];
165             NSString *key = [NSString stringWithFormat:@"tiffGemImage%d", i];
166             cropRect.origin.x = i * [importedImage size].width/7.0;
167             [gemImage lockFocus];
168             [[NSColor clearColor] set];
169             NSRectFill(gemRect);
170             [importedImage drawInRect:gemRect fromRect:cropRect operation:NSCompositeSourceOver fraction:1.0];
171             [gemImage unlockFocus];
172             [[NSUserDefaults standardUserDefaults]      setObject:[gemImage TIFFRepresentation] forKey:key];
173             if (i == 0) [iv1 setImage:gemImage];
174             if (i == 1) [iv2 setImage:gemImage];
175             if (i == 2) [iv3 setImage:gemImage];
176             if (i == 3) [iv4 setImage:gemImage];
177             if (i == 4) [iv5 setImage:gemImage];
178             if (i == 5) [iv6 setImage:gemImage];
179             if (i == 6) [iv7 setImage:gemImage];
180             [gemImage release];
181         }
182         useImportedGraphics = YES;
183     }
184         
187 - (IBAction)prefsCustomBackgroundCheckboxAction:(id)sender
189     //NSLog(@"prefsCustomBackgroundCheckboxAction");
191     if (sender!=prefsCustomBackgroundCheckbox)
192         return;
193     [prefsSelectFolderButton setEnabled:[prefsCustomBackgroundCheckbox state]];
194     [prefsCustomBackgroundFolderTextField setEnabled:[prefsCustomBackgroundCheckbox state]];
195     
198 - (IBAction)prefsSelectFolderButtonAction
200     NSOpenPanel *op=[NSOpenPanel openPanel];
202     //NSLog(@"prefsSelectFolderButtonAction");
203     [op setCanChooseDirectories:YES];
204     [op setCanChooseFiles:NO];
205     // get a sheet going to let the user pick a folder to scan for pictures
206     [op beginSheetForDirectory:[prefsCustomBackgroundFolderTextField stringValue] file:NULL types:NULL modalForWindow:prefsPanel modalDelegate:self didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:) contextInfo:NULL];
209 - (BOOL) validateMenuItem: (NSMenuItem*) aMenuItem
211     if (aMenuItem == easyGameMenuItem)
212         return [easyGameButton isEnabled];
213     if (aMenuItem == hardGameMenuItem)
214         return [hardGameButton isEnabled];
215     if (aMenuItem == toughGameMenuItem)
216         return [toughGameButton isEnabled];
217     if (aMenuItem == freePlayMenuItem)
218         return [easyGameButton isEnabled];
219     if (aMenuItem == abortGameMenuItem)
220         return [abortGameButton isEnabled];
221     if (aMenuItem == pauseGameMenuItem)
222         return [pauseGameButton isEnabled];
223     //
224     // only allow viewing and reset of scores between games
225     //
226     if (aMenuItem == showHighScoresMenuItem)
227         return [easyGameButton isEnabled];
228     if (aMenuItem == resetHighScoresMenuItem)
229         return [easyGameButton isEnabled];
230     return YES;
233 - (IBAction)startNewGame:(id)sender
235     //NSLog(@"gameController.startNewGame messaged gameView:%@",gameView);
236     
237     [easyGameButton setEnabled:NO];
238     [hardGameButton setEnabled:NO];
239     [toughGameButton setEnabled:NO];
240     [abortGameButton setEnabled:YES];
241     [pauseGameButton setEnabled:YES];
243     abortGame = NO;
244     gameSpeed = 1.0;
245     gameLevel = 0;
246     
247     if ((sender == easyGameButton) ||
248         (sender == easyGameMenuItem)) {
249         //NSLog(@"debug - hiScores = %@\n...hiScores.count = %d",hiScores,[hiScores count]);
250         gameLevel = 0;
251         gameTime = 600.0; // ten minutes
252         [gameView setHTMLHiScoreLegend:[[NSBundle mainBundle]
253                                             localizedStringForKey:@"EasyHighScoresHTML"
254                                             value:nil table:nil]];
255     }
256   // TODO: add else if?
257     if ((sender == hardGameButton) ||
258         (sender == hardGameMenuItem)) {
259         gameLevel = 1;
260         gameTime = 180.0; // three minutes
261         [gameView setHTMLHiScoreLegend:[[NSBundle mainBundle]
262                                             localizedStringForKey:@"HardHighScoresHTML"
263                                             value:nil table:nil]];
264     }
265   // TODO: add else if?
266     if ((sender == toughGameButton) ||
267         (sender == toughGameMenuItem)) {
268         gameLevel = 2;
269         gameTime = 90.0; // one and a half minutes
270         [gameView setHTMLHiScoreLegend:[[NSBundle mainBundle]
271                                             localizedStringForKey:@"ToughHighScoresHTML"
272                                             value:nil table:nil]];
273     }
274   
275     if (sender==freePlayMenuItem)
276     {
277         gameLevel = 3;
278         gameTime = 3600.0; // one hour FWIW
279         freePlay = YES;//       FREEPLAY
280         [gameView setHTMLHiScoreLegend:[[NSBundle mainBundle]
281                                             localizedStringForKey:@"FreePlayHighScoresHTML"
282                                             value:nil table:nil]];
283     }
284     else {
285         freePlay = NO;//        FREEPLAY
286     }
287   
288     gameNames = [hiScores objectAtIndex:gameLevel*2];
289     gameScores = [hiScores objectAtIndex:gameLevel*2+1];
290     [game wholeNewGameWithSpritesFrom:[gameView spriteArray]];
292     [scoreTextField setStringValue:[NSString stringWithFormat:@"%d", game.score]];
293     [scoreTextField setNeedsDisplay:YES];
294     [bonusTextField setStringValue:[NSString stringWithFormat:@"x%d", game.bonusMultiplier]];
295     [bonusTextField setNeedsDisplay:YES];
296     
297     [game setMuted:muted];
298     [gameView setGame:game];
299     [gameView setLegend:nil];
300     [gameView setPaused:NO];
301     [gameView setMuted:muted];
302     [gameView setShowHint:!freePlay];//         FREEPLAY
303     
304     [timerView setTimerRunningEvery:0.5/gameSpeed
305                 decrement:(0.5/gameTime)
306                 withTarget:self
307                 whenRunOut:@selector(runOutOfTime)
308                 whenRunOver:@selector(bonusAwarded)];
309     
310     if (freePlay)
311     {
312         [timerView setDecrement:0.0];// FREEPLAY MW
313         [timerView setTimer:0.0];
314     }
315     
316     [timerView setPaused:YES];
317         
318     [gameView setLastMoveDate];
319     [self startAnimation:@selector(waitForFirstClick)];
322 - (IBAction)abortGame
324     [abortGameButton setEnabled:NO];
325     if (paused) [self togglePauseMode:self];
326     [pauseGameButton setEnabled:NO];
327     abortGame = YES;
328     [self waitForFirstClick];
331 - (IBAction)receiveHiScoreName
333     int         score = [hiScorePanelScoreTextField intValue];
334     NSString    *name = [hiScorePanelNameTextField stringValue];
336     [NSApp endSheet:hiScorePanel];
337     [hiScorePanel close];
338     
339     //NSLog(@"receiving HiScoreName:%@ %d",name,score);
340     
341     // reset arrays to gameLevel    
342     gameNames = [hiScores objectAtIndex:gameLevel*2];
343     gameScores = [hiScores objectAtIndex:gameLevel*2+1];
344     
345     for (int i = 0; i < 10; i++) {
346         if (score > [[gameScores objectAtIndex:i] intValue]) {
347             [gameScores insertObject:[NSNumber numberWithInt:score] atIndex:i];
348             [gameScores removeObjectAtIndex:10];
349           
350             [gameNames  insertObject:name atIndex:i];
351             [gameNames  removeObjectAtIndex:10];
352             break;
353         }
354     }
356     [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"hiScores"];     // or it won't work!?!
357     [[NSUserDefaults standardUserDefaults] setObject:hiScores forKey:@"hiScores"];
359     //NSLog(@"written high-scores to preferences");
360     
361     _gameState = GAMESTATE_GAMEOVER;
362     [gameView showHighScores:gameScores andNames:gameNames];
363     [gameView setLastMoveDate]; //reset timer so scores show for 20s    
366 - (IBAction)togglePauseMode:(id)sender
368     //NSLog(@"Pause game toggled, sender state is %d",[sender state]);
369     if (sender == pauseGameButton)
370         paused = [sender state];
371     else
372         paused = !paused;
373     
374     [pauseGameButton setState:paused];
375     [timerView setPaused:paused];
376     if (paused)
377     {
378         [gameView setPaused:YES];
379         [gameView setHTMLLegend:[[NSBundle mainBundle]
380                             localizedStringForKey:@"PausedHTML"
381                             value:nil table:nil]];
382         [pauseGameMenuItem setTitle:[[NSBundle mainBundle]
383                             localizedStringForKey:@"ContinueGameMenuItemTitle"
384                             value:nil table:nil]];
385     }
386     else
387     {
388         [gameView setPaused:NO];
389         [gameView setLegend:nil];
390         [pauseGameMenuItem setTitle:[[NSBundle mainBundle]
391                             localizedStringForKey:@"PauseGameMenuItemTitle"
392                             value:nil table:nil]];
393     }
396 - (IBAction)toggleMute:(id)sender
398     if (sender == muteButton)
399         muted = [sender state];
400     else
401         muted = !muted;
402     
403     [muteButton setState:muted];
404     [gameView setMuted:muted];
405     [game setMuted:muted];
406     
407     if (muted)
408         [muteMenuItem setTitle:[[NSBundle mainBundle]
409                             localizedStringForKey:@"UnMuteGameMenuItemTitle"
410                             value:nil table:nil]];
411     else
412         [muteMenuItem setTitle:[[NSBundle mainBundle]
413                             localizedStringForKey:@"MuteGameMenuItemTitle"
414                             value:nil table:nil]];
415     
418 - (IBAction)orderFrontAboutPanel
420     //NSLog(@"GameController showAboutPanel called");
421   if (!aboutPanel) {
422         [NSBundle loadNibNamed:@"About" owner:self];
423   }
424     [aboutPanel setFrameAutosaveName:@"aboutPanel"];
425     [aboutPanel makeKeyAndOrderFront:self];
428 - (IBAction)orderFrontPreferencesPanel
430   if (!prefsPanel) {
431         [NSBundle loadNibNamed:@"Preferences" owner:self];
432   }
434     [prefsStandardGraphicsButton setState:!useAlternateGraphics];
435     [prefsAlternateGraphicsButton setState:useAlternateGraphics];
437     [prefsCustomBackgroundCheckbox setState:useCustomBackgrounds];
438     [prefsCustomBackgroundFolderTextField setStringValue:customBackgroundFolderPath];
439     [prefsSelectFolderButton setEnabled:[prefsCustomBackgroundCheckbox state]];
440     [prefsCustomBackgroundFolderTextField setEnabled:[prefsCustomBackgroundCheckbox state]];
441     
442     if ([[NSUserDefaults standardUserDefaults]  dataForKey:@"tiffGemImage0"])
443     {    // set up images!
444         for (int i = 0; i < 7; i++) {
445             NSString    *key = [NSString stringWithFormat:@"tiffGemImage%d", i];
446             NSData      *tiffData = [[NSUserDefaults standardUserDefaults]      dataForKey:key];
447             NSImage     *gemImage = [[NSImage alloc] initWithData:tiffData];
448             if (i == 0) [iv1 setImage:gemImage];
449             if (i == 1) [iv2 setImage:gemImage];
450             if (i == 2) [iv3 setImage:gemImage];
451             if (i == 3) [iv4 setImage:gemImage];
452             if (i == 4) [iv5 setImage:gemImage];
453             if (i == 5) [iv6 setImage:gemImage];
454             if (i == 6) [iv7 setImage:gemImage];
455             [gemImage release];
456         }
457     }
458     
459     [prefsPanel setFrameAutosaveName:@"prefsPanel"];
460     [prefsPanel makeKeyAndOrderFront:self];
463 - (IBAction)showHighScores
465     // rotate which scores to show
466     //
467     gameNames = [hiScores objectAtIndex:gameLevel*2];
468     gameScores = [hiScores objectAtIndex:gameLevel*2+1];
469     if (gameLevel==0)
470     [gameView setHTMLHiScoreLegend:[[NSBundle mainBundle]
471                                             localizedStringForKey:@"EasyHighScoresHTML"
472                                             value:nil table:nil]];
473     else if (gameLevel==1)
474     [gameView setHTMLHiScoreLegend:[[NSBundle mainBundle]
475                                             localizedStringForKey:@"HardHighScoresHTML"
476                                             value:nil table:nil]];
477     else if (gameLevel==2)
478     [gameView setHTMLHiScoreLegend:[[NSBundle mainBundle]
479                                             localizedStringForKey:@"ToughHighScoresHTML"
480                                             value:nil table:nil]];
481     else if (gameLevel==3)
482     [gameView setHTMLHiScoreLegend:[[NSBundle mainBundle]
483                                             localizedStringForKey:@"FreePlayHighScoresHTML"
484                                             value:nil table:nil]];
485     gameLevel = (gameLevel +1)%4;
486     
487     [gameView showHighScores:gameScores andNames:gameNames];
488     [gameView setLastMoveDate]; //reset timer so scores show for 20s    
491 - (IBAction)resetHighScores
493     // don't rotate which scores to show
494     //
495     // blank the hi scores
496     //
497     [hiScores release];
498     hiScores = [[self makeBlankHiScoresWith:nil] retain];
499     [[NSUserDefaults standardUserDefaults] setObject:hiScores forKey:@"hiScores"];
500     
501     [self showHighScores];      //call the show scores routine    
504 - (NSArray *)makeBlankHiScoresWith:(NSArray *)oldScores
506     //int i,j;
507     int j;
508     NSMutableArray      *result = [NSMutableArray arrayWithCapacity:0];
509     
510     if (oldScores)      result = [NSMutableArray arrayWithArray:oldScores];
511     
512     //for (i = 0; i < 3; i++)
513     while ([result count] < 8)
514     {
515         NSMutableArray  *scores = [NSMutableArray arrayWithCapacity:0];
516         NSMutableArray  *names = [NSMutableArray arrayWithCapacity:0];
517         for (j = 0; j < 10; j++)
518         {
519             [scores addObject:[NSNumber numberWithInt:1000]];
520             [names addObject:[[NSBundle mainBundle]
521                                 localizedStringForKey:@"AnonymousName"
522                                 value:nil table:nil]];
523         }
524         [result addObject:names];
525         [result addObject:scores];
526     }
527     return [NSArray arrayWithArray:result];
530 - (void)runOutOfTime
532     _gameState = GAMESTATE_GAMEOVER;
533     [abortGameButton setEnabled:NO];
534     [pauseGameButton setEnabled:NO];
535     abortGame = YES;
536     [gameView setHTMLLegend:gameOverString];
537     [game shake];
538     [self startAnimation:@selector(waitForFirstClick)];
541 - (void)checkHiScores
543     int i;
544     // reset arrays with gameLevel
545     gameNames = [hiScores objectAtIndex:gameLevel*2];
546     gameScores = [hiScores objectAtIndex:gameLevel*2+1];
547     for (i = 0; i < 10; i++)
548     {
549         if (game.score > [[gameScores objectAtIndex:i] intValue])
550         {
551             [hiScorePanelScoreTextField
552                 setStringValue:[NSString stringWithFormat:@"%d", game.score]];
553             [NSApp      beginSheet:hiScorePanel
554                             modalForWindow:gameWindow
555                             modalDelegate:self
556                             didEndSelector:NULL
557                             contextInfo:NULL];
558             return;
559         }
560     }
561     [gameView showHighScores:gameScores andNames:gameNames];
564 - (void)bonusAwarded
567     [gameView newBackground];
569     if (!muted)         [[NSSound soundNamed:@"yes"] play];
571     if (!freePlay) {            // FREEPLAY MW
572         [game increaseBonusMultiplier];
573         [timerView decrementMeter:0.5];
574     } else {
575         [game increaseBonusMultiplier];
576         [timerView decrementMeter:1];
577     }
579     if (gameSpeed < SPEED_LIMIT)                // capping speed limit
580         gameSpeed = gameSpeed * 1.5;
581     //NSLog(@"...gamesSpeed %f",gameSpeed);
582     [timerView setTimerRunningEvery:0.5/gameSpeed
583                 decrement:(0.5/gameTime)
584                 withTarget:self
585                 whenRunOut:@selector(runOutOfTime)
586                 whenRunOver:@selector(bonusAwarded)];
587                 
588     if (freePlay)       [timerView setDecrement:0];//   FREEPLAY
591 - (void)startAnimation:(SEL)andThenSelector
593     [animationTimerLock lock];
594     //
595     if (!timer)
596         timer = [[NSTimer scheduledTimerWithTimeInterval:TIMER_INTERVAL
597                                                   target:gameView
598                                                 selector:@selector(animate)
599                                                 userInfo:self
600                                                  repeats:YES] retain];
601     //
602     whatNext = andThenSelector;
603     //
604   gameView.animating = YES;
605     //
606     [animationTimerLock unlock];
609 - (void)animationEnded
611     //NSLog(@"gameController.animationEnded messaged");
612     
613     [animationTimerLock lock];
614     //
615   gameView.animating = NO;
616     //
617     [animationTimerLock unlock];
618     
619     if (whatNext)       [self performSelector:whatNext];
620         
621     [gameView setNeedsDisplay:YES];
624 - (void)waitForNewGame
626     [self checkHiScores];
627     
628     [game wholeNewGameWithSpritesFrom:[gameView spriteArray]];
629     [gameView setLegend:titleImage];
630     [easyGameButton setEnabled:YES];
631     [hardGameButton setEnabled:YES];
632     [toughGameButton setEnabled:YES];
633     [abortGameButton setEnabled:NO];
634     [pauseGameButton setEnabled:NO];
637 - (void)newBoard1
639     //NSLog(@"newBoard1");
640     [game erupt];
641     [self startAnimation:@selector(newBoard2)];
644 - (void)newBoard2
646     Gem *gem;
647     int i,j,r;
648     //NSLog(@"newBoard2");
649     for (i = 0; i < 8; i++)
650     {
651         for (j = 0; j < 8; j++)
652         {
653             gem = [game gemAt:i:j];
654             //NSLog(@"..gem..%@",gem);
655             r = rand() % 7;
656             [gem setGemType:r];
657             //[gem setImage:[[gameView imageArray] objectAtIndex:r]];
658             [gem setSprite:[[gameView spriteArray] objectAtIndex:r]];
659             [gem setPositionOnBoard:i:j];
660             [gem setPositionOnScreen:i*48:(i+j+8)*48];
661             [gem fall];
662         }
663     }
664     [gameView newBackground];
665     [gameView setLegend:nil];
666     [self startAnimation:@selector(testForThreesAgain)];
669 - (void)waitForFirstClick
671     //NSLog(@"waitForFirstClick");
672     /*- if (!freePlay)  MW CHANGE -*/   [timerView setPaused:NO];
673     if (abortGame)
674     {
675         [timerView setTimer:0.5];
676         _gameState = GAMESTATE_GAMEOVER;
677         [game explodeGameOver];
678         [self startAnimation:@selector(waitForNewGame)];
679         return;
680     }
681     if (![game boardHasMoves])
682     {
683         [timerView setPaused:YES];
684         [gameView setHTMLLegend:noMoreMovesString];
685         [game shake];
686         
687         if (freePlay)   [self startAnimation:@selector(runOutOfTime)];//        FREEPLAY
688         else            [self startAnimation:@selector(newBoard1)];//   FREEPLAY
689         
690         return;
691     }
692     _gameState = GAMESTATE_AWAITINGFIRSTCLICK;
695 - (void)receiveClickAt:(int)x:(int)y
697     if (paused) return;
698     if ((x < 0)||(x > 383)||(y < 0)||(y > 383)) return;
699     if (_gameState == GAMESTATE_AWAITINGFIRSTCLICK)
700     {
701         chx1 = floor(x / 48);
702         chy1 = floor(y / 48);
703         _gameState = GAMESTATE_AWAITINGSECONDCLICK;
704         [gameView setNeedsDisplay:YES];
705         return;
706     }
707     if (_gameState == GAMESTATE_AWAITINGSECONDCLICK)
708     {
709         chx2 = floor(x / 48);
710         chy2 = floor(y / 48);
711         if ((chx2 != chx1)^(chy2 != chy1))      // xor!
712         {
713             int d = (chx1-chx2)*(chx1-chx2)+(chy1-chy2)*(chy1-chy2);
714             //NSLog(@"square distance ==%d",d);
715             if (d==1)
716             {
717                 _gameState = GAMESTATE_FRACULATING;
718                 [gameView setNeedsDisplay:YES];
719                 [gameView setLastMoveDate];
720                 /*- MW CHANGE if (!freePlay) -*/ [timerView setPaused:YES];
721                 [self tryMoveSwapping:chx1:chy1 and:chx2:chy2];
722                 return;
723             }
724         }
725         // fall out of routine setting first click location
726         chx1 = floor(x / 48);
727         chy1 = floor(y / 48);
728         _gameState = GAMESTATE_AWAITINGSECONDCLICK;
729         [gameView setNeedsDisplay:YES];
730     }
733 - (void)tryMoveSwapping:(int)x1:(int)y1 and:(int)x2:(int)y2
735     // do stuff here!!!
736     int xx1, yy1, xx2, yy2;
737     //NSLog(@"tryMoveSwapping");
738     if (x1 != x2)
739     {
740         if (x1 < x2)    { xx1 = x1; xx2 = x2; }
741         else            { xx1 = x2; xx2 = x1; }
742         yy1 = y1;
743         yy2 = y2;
744     }
745     else
746     {
747         if (y1 < y2)    { yy1 = y1; yy2 = y2; }
748         else            { yy1 = y2; yy2 = y1; }
749         xx1 = x1;
750         xx2 = x2;
751     }
752     // store swap positions
753     chx1 = xx1; chy1 = yy1; chx2 = xx2; chy2 = yy2;
754     // swap positions
755     if (chx1 < chx2)    // swapping horizontally
756     {
757         [[game gemAt:chx1:chy1] setVelocity:gemMoveSpeed:0:gemMoveSteps];
758         [[game gemAt:chx2:chy2] setVelocity:-gemMoveSpeed:0:gemMoveSteps];
759     }
760     else                // swapping vertically
761     {
762         [[game gemAt:chx1:chy1] setVelocity:0:gemMoveSpeed:gemMoveSteps];
763         [[game gemAt:chx2:chy2] setVelocity:0:-gemMoveSpeed:gemMoveSteps];
764     }
765     [game swap:chx1:chy1 and:chx2:chy2];
766     _gameState = GAMESTATE_SWAPPING;
767     [self startAnimation:@selector(testForThrees)];
770     // test for threes
771 - (void)testForThrees
773     BOOL anyThrees;
774     int oldScore = game.score;
775     //NSLog(@"testForThrees");
776     anyThrees = ([game testForThreeAt:chx1:chy1])|([game testForThreeAt:chx2:chy2]);
777     [scoreTextField setStringValue:[NSString stringWithFormat:@"%d", game.score]];
778     [scoreTextField setNeedsDisplay:YES];
779     [bonusTextField setStringValue:[NSString stringWithFormat:@"x%d", game.bonusMultiplier]];
780     [bonusTextField setNeedsDisplay:YES];
781     if (game.score > oldScore) [timerView incrementMeter:[game collectFadedGems]/GEMS_FOR_BONUS];
782     if (anyThrees)
783         [self startAnimation:@selector(removeThreesAndReplaceGems)];    // fade gems
784     else
785         [self unSwap];
786 }    
788     //// repeat:        remove threes
789 - (void)removeThreesAndReplaceGems
791     
792     //NSLog(@"removeThreesAndReplaceGems");
793     // deal with fading
794     [game removeFadedGemsAndReorganiseWithSpritesFrom:[gameView spriteArray]];
795     
796     [self startAnimation:@selector(testForThreesAgain)];        // gems fall down
797 }    
799 - (void)testForThreesAgain
801   int oldScore = game.score;
802   BOOL anyThrees = [game checkBoardForThrees];
803   
804   [scoreTextField setStringValue:[NSString stringWithFormat:@"%d", game.score]];
805   [scoreTextField setNeedsDisplay:YES];
806   
807   [bonusTextField setStringValue:[NSString stringWithFormat:@"x%d", game.bonusMultiplier]];
808   [bonusTextField setNeedsDisplay:YES];
809   
810   if (game.score > oldScore) {
811     [timerView incrementMeter:[game collectFadedGems]/GEMS_FOR_BONUS];
812   }
813   if (anyThrees) {
814     [self startAnimation:@selector(removeThreesAndReplaceGems)];        // fade gems
815   }
816   else {
817     [self waitForFirstClick];
818   }
819 }   
820 ////            allow gems to fall
821     ////                test for threes
822     //// until there are no threes
824 - (void)unSwap
826     //NSLog(@"unSwap");
827     
828     if (!muted) [[NSSound soundNamed:@"no"] play];
829     
830     // swap positions
831     if (chx1 < chx2)    // swapping horizontally
832     {
833         [[game gemAt:chx1:chy1] setVelocity:4:0:12];
834         [[game gemAt:chx2:chy2] setVelocity:-4:0:12];
835     }
836     else                // swapping vertically
837     {
838         [[game gemAt:chx1:chy1] setVelocity:0:4:12];
839         [[game gemAt:chx2:chy2] setVelocity:0:-4:12];
840     }
841     [game swap:chx1:chy1 and:chx2:chy2];
842     _gameState = GAMESTATE_SWAPPING;
843     [self startAnimation:@selector(waitForFirstClick)];
844 }    
846 - (BOOL)gameIsPaused {
847   return paused;
850 - (BOOL)useCustomBackgrounds {
851   return useCustomBackgrounds;
854 - (NSPoint)crossHair1Position {
855   return NSMakePoint(chx1 * 48,chy1 * 48);
858 - (NSPoint)crossHair2Position {
859   return NSMakePoint(chx2 * 48,chy2 * 48);
862 @end