add warnings to the project
[exterlulz-kokogems.git] / src / GameController.m
bloba91d9164ee8669e0c25de28a43e889bf1b86a494
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
141     [prefsCustomBackgroundFolderTextField setStringValue:[[sheet filenames] objectAtIndex:0]];
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];
204 - (BOOL) validateMenuItem: (NSMenuItem*) aMenuItem
206     if (aMenuItem == easyGameMenuItem)
207         return [easyGameButton isEnabled];
208     if (aMenuItem == hardGameMenuItem)
209         return [hardGameButton isEnabled];
210     if (aMenuItem == toughGameMenuItem)
211         return [toughGameButton isEnabled];
212     if (aMenuItem == freePlayMenuItem)
213         return [easyGameButton isEnabled];
214     if (aMenuItem == abortGameMenuItem)
215         return [abortGameButton isEnabled];
216     if (aMenuItem == pauseGameMenuItem)
217         return [pauseGameButton isEnabled];
218     //
219     // only allow viewing and reset of scores between games
220     //
221     if (aMenuItem == showHighScoresMenuItem)
222         return [easyGameButton isEnabled];
223     if (aMenuItem == resetHighScoresMenuItem)
224         return [easyGameButton isEnabled];
225     return YES;
228 - (IBAction)startNewGame:(id)sender
230     //NSLog(@"gameController.startNewGame messaged gameView:%@",gameView);
231     
232     [easyGameButton setEnabled:NO];
233     [hardGameButton setEnabled:NO];
234     [toughGameButton setEnabled:NO];
235     [abortGameButton setEnabled:YES];
236     [pauseGameButton setEnabled:YES];
238     abortGame = NO;
239     gameSpeed = 1.0;
240     gameLevel = 0;
241     
242     if ((sender==easyGameButton)||(sender==easyGameMenuItem))
243     {
244         //NSLog(@"debug - hiScores = %@\n...hiScores.count = %d",hiScores,[hiScores count]);
245         gameLevel = 0;
246         gameTime = 600.0; // ten minutes
247         [gameView setHTMLHiScoreLegend:[[NSBundle mainBundle]
248                                             localizedStringForKey:@"EasyHighScoresHTML"
249                                             value:nil table:nil]];
250     }
251     if ((sender==hardGameButton)||(sender==hardGameMenuItem))
252     {
253         gameLevel = 1;
254         gameTime = 180.0; // three minutes
255         [gameView setHTMLHiScoreLegend:[[NSBundle mainBundle]
256                                             localizedStringForKey:@"HardHighScoresHTML"
257                                             value:nil table:nil]];
259     }
260     if ((sender==toughGameButton)||(sender==toughGameMenuItem))
261     {
262         gameLevel = 2;
263         gameTime = 90.0; // one and a half minutes
264         [gameView setHTMLHiScoreLegend:[[NSBundle mainBundle]
265                                             localizedStringForKey:@"ToughHighScoresHTML"
266                                             value:nil table:nil]];
267     }
268     if (sender==freePlayMenuItem)
269     {
270         gameLevel = 3;
271         gameTime = 3600.0; // one hour FWIW
272         freePlay = YES;//       FREEPLAY
273         [gameView setHTMLHiScoreLegend:[[NSBundle mainBundle]
274                                             localizedStringForKey:@"FreePlayHighScoresHTML"
275                                             value:nil table:nil]];
276     }
277     else
278         freePlay = NO;//        FREEPLAY
279     gameNames = [hiScores objectAtIndex:gameLevel*2];
280     gameScores = [hiScores objectAtIndex:gameLevel*2+1];
281     [game wholeNewGameWithSpritesFrom:[gameView spriteArray]];
284     [scoreTextField setStringValue:[NSString stringWithFormat:@"%d",[game score]]];
285     [scoreTextField setNeedsDisplay:YES];
286     [bonusTextField setStringValue:[NSString stringWithFormat:@"x%d",[game bonusMultiplier]]];
287     [bonusTextField setNeedsDisplay:YES];
289     
290     [game setMuted:muted];
291     [gameView setGame:game];
292     [gameView setLegend:nil];
293     [gameView setPaused:NO];
294     [gameView setMuted:muted];
295     [gameView setShowHint:!freePlay];//         FREEPLAY
296     
297     [timerView setTimerRunningEvery:0.5/gameSpeed
298                 decrement:(0.5/gameTime)
299                 withTarget:self
300                 whenRunOut:@selector(runOutOfTime)
301                 whenRunOver:@selector(bonusAwarded)];
302     
303     if (freePlay)
304     {
305         [timerView setDecrement:0.0];// FREEPLAY MW
306         [timerView setTimer:0.0];
307     }
308     
309     [timerView setPaused:YES];
310         
311     [gameView setLastMoveDate];
312     [self startAnimation:@selector(waitForFirstClick)];
315 - (IBAction)abortGame:(id)sender
317     [abortGameButton setEnabled:NO];
318     if (paused) [self togglePauseMode:self];
319     [pauseGameButton setEnabled:NO];
320     abortGame = YES;
321     [self waitForFirstClick];
323 - (IBAction)receiveHiScoreName:(id)sender
325     int         i;
326     int         score = [hiScorePanelScoreTextField intValue];
327     NSString    *name = [hiScorePanelNameTextField stringValue];
329     [NSApp endSheet:hiScorePanel];
330     [hiScorePanel close];
331     
332     //NSLog(@"receiving HiScoreName:%@ %d",name,score);
333     
334     // reset arrays to gameLevel    
335     gameNames = [hiScores objectAtIndex:gameLevel*2];
336     gameScores = [hiScores objectAtIndex:gameLevel*2+1];
337     
338     for (i = 0; i < 10; i++)
339     {
340         if (score > [[gameScores objectAtIndex:i] intValue])
341         {
342             [gameScores insertObject:[NSNumber numberWithInt:score] atIndex:i];
343             [gameScores removeObjectAtIndex:10];
344             [gameNames  insertObject:name atIndex:i];
345             [gameNames  removeObjectAtIndex:10];
346             break;
347         }
348     }
350     [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"hiScores"];     // or it won't work!?!
351     [[NSUserDefaults standardUserDefaults] setObject:hiScores forKey:@"hiScores"];
353     //NSLog(@"written high-scores to preferences");
354     
355     gameState = GAMESTATE_GAMEOVER;
356     [gameView showHighScores:gameScores andNames:gameNames];
357     [gameView setLastMoveDate]; //reset timer so scores show for 20s    
360 - (IBAction)togglePauseMode:(id)sender
362     //NSLog(@"Pause game toggled, sender state is %d",[sender state]);
363     if (sender == pauseGameButton)
364         paused = [sender state];
365     else
366         paused = !paused;
367     
368     [pauseGameButton setState:paused];
369     [timerView setPaused:paused];
370     if (paused)
371     {
372         [gameView setPaused:YES];
373         [gameView setHTMLLegend:[[NSBundle mainBundle]
374                             localizedStringForKey:@"PausedHTML"
375                             value:nil table:nil]];
376         [pauseGameMenuItem setTitle:[[NSBundle mainBundle]
377                             localizedStringForKey:@"ContinueGameMenuItemTitle"
378                             value:nil table:nil]];
379     }
380     else
381     {
382         [gameView setPaused:NO];
383         [gameView setLegend:nil];
384         [pauseGameMenuItem setTitle:[[NSBundle mainBundle]
385                             localizedStringForKey:@"PauseGameMenuItemTitle"
386                             value:nil table:nil]];
387     }
390 - (IBAction)toggleMute:(id)sender
392     if (sender == muteButton)
393         muted = [sender state];
394     else
395         muted = !muted;
396     
397     [muteButton setState:muted];
398     [gameView setMuted:muted];
399     [game setMuted:muted];
400     
401     if (muted)
402         [muteMenuItem setTitle:[[NSBundle mainBundle]
403                             localizedStringForKey:@"UnMuteGameMenuItemTitle"
404                             value:nil table:nil]];
405     else
406         [muteMenuItem setTitle:[[NSBundle mainBundle]
407                             localizedStringForKey:@"MuteGameMenuItemTitle"
408                             value:nil table:nil]];
409     
412 - (IBAction)orderFrontAboutPanel:(id)sender
414     //NSLog(@"GameController showAboutPanel called");
415     if (!aboutPanel)
416         [NSBundle loadNibNamed:@"About" owner:self];
417     [aboutPanel setFrameAutosaveName:@"aboutPanel"];
418     [aboutPanel makeKeyAndOrderFront:self];
421 - (IBAction)orderFrontPreferencesPanel:(id)sender
423     if (!prefsPanel)
424         [NSBundle loadNibNamed:@"Preferences" owner:self];
426     [prefsStandardGraphicsButton setState:!useAlternateGraphics];
427     [prefsAlternateGraphicsButton setState:useAlternateGraphics];
429     [prefsCustomBackgroundCheckbox setState:useCustomBackgrounds];
430     [prefsCustomBackgroundFolderTextField setStringValue:customBackgroundFolderPath];
431     [prefsSelectFolderButton setEnabled:[prefsCustomBackgroundCheckbox state]];
432     [prefsCustomBackgroundFolderTextField setEnabled:[prefsCustomBackgroundCheckbox state]];
433     
434     if ([[NSUserDefaults standardUserDefaults]  dataForKey:@"tiffGemImage0"])
435     {    // set up images!
436         int i = 0;
437         for (i = 0; i < 7; i++)
438         {
439             NSString    *key = [NSString stringWithFormat:@"tiffGemImage%d", i];
440             NSData      *tiffData = [[NSUserDefaults standardUserDefaults]      dataForKey:key];
441             NSImage     *gemImage = [[NSImage alloc] initWithData:tiffData];
442             if (i == 0) [iv1 setImage:gemImage];
443             if (i == 1) [iv2 setImage:gemImage];
444             if (i == 2) [iv3 setImage:gemImage];
445             if (i == 3) [iv4 setImage:gemImage];
446             if (i == 4) [iv5 setImage:gemImage];
447             if (i == 5) [iv6 setImage:gemImage];
448             if (i == 6) [iv7 setImage:gemImage];
449             [gemImage release];
450         }
451     }
452     
453     [prefsPanel setFrameAutosaveName:@"prefsPanel"];
454     [prefsPanel makeKeyAndOrderFront:self];
457 - (IBAction)showHighScores:(id)sender
459     // rotate which scores to show
460     //
461     gameNames = [hiScores objectAtIndex:gameLevel*2];
462     gameScores = [hiScores objectAtIndex:gameLevel*2+1];
463     if (gameLevel==0)
464     [gameView setHTMLHiScoreLegend:[[NSBundle mainBundle]
465                                             localizedStringForKey:@"EasyHighScoresHTML"
466                                             value:nil table:nil]];
467     else if (gameLevel==1)
468     [gameView setHTMLHiScoreLegend:[[NSBundle mainBundle]
469                                             localizedStringForKey:@"HardHighScoresHTML"
470                                             value:nil table:nil]];
471     else if (gameLevel==2)
472     [gameView setHTMLHiScoreLegend:[[NSBundle mainBundle]
473                                             localizedStringForKey:@"ToughHighScoresHTML"
474                                             value:nil table:nil]];
475     else if (gameLevel==3)
476     [gameView setHTMLHiScoreLegend:[[NSBundle mainBundle]
477                                             localizedStringForKey:@"FreePlayHighScoresHTML"
478                                             value:nil table:nil]];
479     gameLevel = (gameLevel +1)%4;
480     
481     [gameView showHighScores:gameScores andNames:gameNames];
482     [gameView setLastMoveDate]; //reset timer so scores show for 20s    
485 - (IBAction)resetHighScores:(id)sender
487     // don't rotate which scores to show
488     //
489     // blank the hi scores
490     //
491     [hiScores release];
492     hiScores = [[self makeBlankHiScoresWith:nil] retain];
493     [[NSUserDefaults standardUserDefaults] setObject:hiScores forKey:@"hiScores"];
494     
495     [self showHighScores:sender];       //call the show scores routine    
498 - (NSArray *)makeBlankHiScoresWith:(NSArray *)oldScores
500     //int i,j;
501     int j;
502     NSMutableArray      *result = [NSMutableArray arrayWithCapacity:0];
503     
504     if (oldScores)      result = [NSMutableArray arrayWithArray:oldScores];
505     
506     //for (i = 0; i < 3; i++)
507     while ([result count] < 8)
508     {
509         NSMutableArray  *scores = [NSMutableArray arrayWithCapacity:0];
510         NSMutableArray  *names = [NSMutableArray arrayWithCapacity:0];
511         for (j = 0; j < 10; j++)
512         {
513             [scores addObject:[NSNumber numberWithInt:1000]];
514             [names addObject:[[NSBundle mainBundle]
515                                 localizedStringForKey:@"AnonymousName"
516                                 value:nil table:nil]];
517         }
518         [result addObject:names];
519         [result addObject:scores];
520     }
521     return [NSArray arrayWithArray:result];
524 - (void)runOutOfTime
526     gameState = GAMESTATE_GAMEOVER;
527     [abortGameButton setEnabled:NO];
528     [pauseGameButton setEnabled:NO];
529     abortGame = YES;
530     [gameView setHTMLLegend:gameOverString];
531     [game shake];
532     [self startAnimation:@selector(waitForFirstClick)];
535 - (void)checkHiScores
537     int i;
538     // reset arrays with gameLevel
539     gameNames = [hiScores objectAtIndex:gameLevel*2];
540     gameScores = [hiScores objectAtIndex:gameLevel*2+1];
541     for (i = 0; i < 10; i++)
542     {
543         if ([game score] > [[gameScores objectAtIndex:i] intValue])
544         {
545             [hiScorePanelScoreTextField
546                 setStringValue:[NSString stringWithFormat:@"%d",[game score]]];
547             [NSApp      beginSheet:hiScorePanel
548                             modalForWindow:gameWindow
549                             modalDelegate:self
550                             didEndSelector:NULL
551                             contextInfo:NULL];
552             return;
553         }
554     }
555     [gameView showHighScores:gameScores andNames:gameNames];
558 - (void)bonusAwarded
561     [gameView newBackground];
563     if (!muted)         [[NSSound soundNamed:@"yes"] play];
565     if (!freePlay) {            // FREEPLAY MW
566         [game increaseBonusMultiplier];
567         [timerView decrementMeter:0.5];
568     } else {
569         [game increaseBonusMultiplier];
570         [timerView decrementMeter:1];
571     }
573     if (gameSpeed < SPEED_LIMIT)                // capping speed limit
574         gameSpeed = gameSpeed * 1.5;
575     //NSLog(@"...gamesSpeed %f",gameSpeed);
576     [timerView setTimerRunningEvery:0.5/gameSpeed
577                 decrement:(0.5/gameTime)
578                 withTarget:self
579                 whenRunOut:@selector(runOutOfTime)
580                 whenRunOver:@selector(bonusAwarded)];
581                 
582     if (freePlay)       [timerView setDecrement:0];//   FREEPLAY
585 - (void)startAnimation:(SEL)andThenSelector
587     [animationTimerLock lock];
588     //
589     if (!timer)
590         timer = [[NSTimer scheduledTimerWithTimeInterval:TIMER_INTERVAL
591                                                   target:gameView
592                                                 selector:@selector(animate)
593                                                 userInfo:self
594                                                  repeats:YES] retain];
595     //
596     whatNext = andThenSelector;
597     //
598     [gameView setAnimating:YES];
599     //
600     [animationTimerLock unlock];
603 - (void)animationEnded
605     //NSLog(@"gameController.animationEnded messaged");
606     
607     [animationTimerLock lock];
608     //
609     [gameView setAnimating:NO];
610     //
611     [animationTimerLock unlock];
612     
613     if (whatNext)       [self performSelector:whatNext];
614         
615     [gameView setNeedsDisplay:YES];
618 - (void)waitForNewGame
620     [self checkHiScores];
621     
622     [game wholeNewGameWithSpritesFrom:[gameView spriteArray]];
623     [gameView setLegend:titleImage];
624     [easyGameButton setEnabled:YES];
625     [hardGameButton setEnabled:YES];
626     [toughGameButton setEnabled:YES];
627     [abortGameButton setEnabled:NO];
628     [pauseGameButton setEnabled:NO];
631 - (void)newBoard1
633     //NSLog(@"newBoard1");
634     [game erupt];
635     [self startAnimation:@selector(newBoard2)];
638 - (void)newBoard2
640     Gem *gem;
641     int i,j,r;
642     //NSLog(@"newBoard2");
643     for (i = 0; i < 8; i++)
644     {
645         for (j = 0; j < 8; j++)
646         {
647             gem = [game gemAt:i:j];
648             //NSLog(@"..gem..%@",gem);
649             r = rand() % 7;
650             [gem setGemType:r];
651             //[gem setImage:[[gameView imageArray] objectAtIndex:r]];
652             [gem setSprite:[[gameView spriteArray] objectAtIndex:r]];
653             [gem setPositionOnBoard:i:j];
654             [gem setPositionOnScreen:i*48:(i+j+8)*48];
655             [gem fall];
656         }
657     }
658     [gameView newBackground];
659     [gameView setLegend:nil];
660     [self startAnimation:@selector(testForThreesAgain)];
663 - (void)waitForFirstClick
665     //NSLog(@"waitForFirstClick");
666     /*- if (!freePlay)  MW CHANGE -*/   [timerView setPaused:NO];
667     if (abortGame)
668     {
669         [timerView setTimer:0.5];
670         gameState = GAMESTATE_GAMEOVER;
671         [game explodeGameOver];
672         [self startAnimation:@selector(waitForNewGame)];
673         return;
674     }
675     if (![game boardHasMoves])
676     {
677         [timerView setPaused:YES];
678         [gameView setHTMLLegend:noMoreMovesString];
679         [game shake];
680         
681         if (freePlay)   [self startAnimation:@selector(runOutOfTime)];//        FREEPLAY
682         else            [self startAnimation:@selector(newBoard1)];//   FREEPLAY
683         
684         return;
685     }
686     gameState = GAMESTATE_AWAITINGFIRSTCLICK;
689 - (void)receiveClickAt:(int)x:(int)y
691     if (paused) return;
692     if ((x < 0)||(x > 383)||(y < 0)||(y > 383)) return;
693     if (gameState == GAMESTATE_AWAITINGFIRSTCLICK)
694     {
695         chx1 = floor(x / 48);
696         chy1 = floor(y / 48);
697         gameState = GAMESTATE_AWAITINGSECONDCLICK;
698         [gameView setNeedsDisplay:YES];
699         return;
700     }
701     if (gameState == GAMESTATE_AWAITINGSECONDCLICK)
702     {
703         chx2 = floor(x / 48);
704         chy2 = floor(y / 48);
705         if ((chx2 != chx1)^(chy2 != chy1))      // xor!
706         {
707             int d = (chx1-chx2)*(chx1-chx2)+(chy1-chy2)*(chy1-chy2);
708             //NSLog(@"square distance ==%d",d);
709             if (d==1)
710             {
711                 gameState = GAMESTATE_FRACULATING;
712                 [gameView setNeedsDisplay:YES];
713                 [gameView setLastMoveDate];
714                 /*- MW CHANGE if (!freePlay) -*/ [timerView setPaused:YES];
715                 [self tryMoveSwapping:chx1:chy1 and:chx2:chy2];
716                 return;
717             }
718         }
719         // fall out of routine setting first click location
720         chx1 = floor(x / 48);
721         chy1 = floor(y / 48);
722         gameState = GAMESTATE_AWAITINGSECONDCLICK;
723         [gameView setNeedsDisplay:YES];
724     }
728 - (void)tryMoveSwapping:(int)x1:(int)y1 and:(int)x2:(int)y2
730     // do stuff here!!!
731     int xx1, yy1, xx2, yy2;
732     //NSLog(@"tryMoveSwapping");
733     if (x1 != x2)
734     {
735         if (x1 < x2)    { xx1 = x1; xx2 = x2; }
736         else            { xx1 = x2; xx2 = x1; }
737         yy1 = y1;
738         yy2 = y2;
739     }
740     else
741     {
742         if (y1 < y2)    { yy1 = y1; yy2 = y2; }
743         else            { yy1 = y2; yy2 = y1; }
744         xx1 = x1;
745         xx2 = x2;
746     }
747     // store swap positions
748     chx1 = xx1; chy1 = yy1; chx2 = xx2; chy2 = yy2;
749     // swap positions
750     if (chx1 < chx2)    // swapping horizontally
751     {
752         [[game gemAt:chx1:chy1] setVelocity:gemMoveSpeed:0:gemMoveSteps];
753         [[game gemAt:chx2:chy2] setVelocity:-gemMoveSpeed:0:gemMoveSteps];
754     }
755     else                // swapping vertically
756     {
757         [[game gemAt:chx1:chy1] setVelocity:0:gemMoveSpeed:gemMoveSteps];
758         [[game gemAt:chx2:chy2] setVelocity:0:-gemMoveSpeed:gemMoveSteps];
759     }
760     [game swap:chx1:chy1 and:chx2:chy2];
761     gameState = GAMESTATE_SWAPPING;
762     [self startAnimation:@selector(testForThrees)];
765     // test for threes
766 - (void)testForThrees
768     BOOL anyThrees;
769     int oldScore = [game score];
770     //NSLog(@"testForThrees");
771     anyThrees = ([game testForThreeAt:chx1:chy1])|([game testForThreeAt:chx2:chy2]);
772     [scoreTextField setStringValue:[NSString stringWithFormat:@"%d",[game score]]];
773     [scoreTextField setNeedsDisplay:YES];
774     [bonusTextField setStringValue:[NSString stringWithFormat:@"x%d",[game bonusMultiplier]]];
775     [bonusTextField setNeedsDisplay:YES];
776     if ([game score] > oldScore) [timerView incrementMeter:[game collectGemsFaded]/GEMS_FOR_BONUS];
777     if (anyThrees)
778         [self startAnimation:@selector(removeThreesAndReplaceGems)];    // fade gems
779     else
780         [self unSwap];
781 }    
783     //// repeat:        remove threes
784 - (void)removeThreesAndReplaceGems
786     
787     //NSLog(@"removeThreesAndReplaceGems");
788     // deal with fading
789     [game removeFadedGemsAndReorganiseWithSpritesFrom:[gameView spriteArray]];
790     
791     [self startAnimation:@selector(testForThreesAgain)];        // gems fall down
792 }    
794 - (void)testForThreesAgain
796     BOOL anyThrees;
797     int oldScore = [game score];
798     //NSLog(@"testForThreesAgain");
799     anyThrees = [game checkBoardForThrees];
800     [scoreTextField setStringValue:[NSString stringWithFormat:@"%d",[game score]]];
801     [scoreTextField setNeedsDisplay:YES];
802     [bonusTextField setStringValue:[NSString stringWithFormat:@"x%d",[game bonusMultiplier]]];
803     [bonusTextField setNeedsDisplay:YES];
804     if ([game score] > oldScore) [timerView incrementMeter:[game collectGemsFaded]/GEMS_FOR_BONUS];
805     if (anyThrees)
806         [self startAnimation:@selector(removeThreesAndReplaceGems)];    // fade gems
807     else
808         [self waitForFirstClick];
809 }   
810     ////                allow gems to fall
811     ////                test for threes
812     //// until there are no threes
814 - (void)unSwap
816     //NSLog(@"unSwap");
817     
818     if (!muted) [[NSSound soundNamed:@"no"] play];
819     
820     // swap positions
821     if (chx1 < chx2)    // swapping horizontally
822     {
823         [[game gemAt:chx1:chy1] setVelocity:4:0:12];
824         [[game gemAt:chx2:chy2] setVelocity:-4:0:12];
825     }
826     else                // swapping vertically
827     {
828         [[game gemAt:chx1:chy1] setVelocity:0:4:12];
829         [[game gemAt:chx2:chy2] setVelocity:0:-4:12];
830     }
831     [game swap:chx1:chy1 and:chx2:chy2];
832     gameState = GAMESTATE_SWAPPING;
833     [self startAnimation:@selector(waitForFirstClick)];
834 }    
837 - (int) gameState
839     return gameState;
842 - (BOOL) gameIsPaused
844     return paused;
847 - (BOOL) useCustomBackgrounds
849     return useCustomBackgrounds;
852 - (NSPoint) crossHair1Position
854     return NSMakePoint(chx1*48,chy1*48);
857 - (NSPoint) crossHair2Position
859     return NSMakePoint(chx2*48,chy2*48);
862 @end