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