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