/* Generated by Interface Builder */

#import "GameBrain.h"
#import "PreferencesBrain.h"
#import "PlayerUpView.h"
#import "InfoController.h"
#import "FruitView.h"
#import "WinDel.h"
#import <stdio.h>
#import <string.h>

static int ghostScores[4] = { 200, 400, 800, 1600 };


@implementation GameBrain

- init		// designated initializer sets up game variables
{		// to sensible values.
    score = 0;
    level = 0;
    paused = NO;
    ranOnce = NO;
	
    return self;
}

/* methods to get at important variables */
- (int)startLevel { return [preferencesBrain startLevel]; }
- (int)level      { return level;      }
- (int)speed      { return speed;      }
- (int)paused     { return paused;     }

- showHigh
{			// update the "high score field	
    [topScoreText setIntValue:[highScoreTable highScore:0]];
    return self;
}

- addToScore:(int)increment	// update the player's score
{
    score += increment;
	if (score - lastBonus >= pointsToNextBonus) {
		[pacsLeft incPacs];
		lastBonus += pointsToNextBonus;
		// assures bonus at 10000, 35000, 55000, 75000, and every 25000 after
		if ((pointsToNextBonus < 20000) || ((pointsToNextBonus == 20000) &&
			(lastBonus >= 75000)))
				pointsToNextBonus += 5000;
	}
    [scoreText setIntValue:score];
    if ((score > [highScoreTable highScore:0]) && ![gameScreen demoMode]) {
        [topScoreText setIntValue:score];
    }
    return self;
}

- zeroScore
{
    score = 0;			// clear score
    [self addToScore:0];	// force display
    return self;
}

- gameOver:sender		// end the game, take high scores, etc.
{				// calls gameOver method (this is IB wrapper)
    [self gameOver];
    return self;
}

- pauseGame:sender		// toggle pause status of the game
{
    const char *title = [pauseMenuCell title];
    
    if (!strcmp(title,"Pause")) {  // returns zero if equal
        [self pause];
    } else {
        [self unpause];
    } 
    return self;
}

- (int)pause				// pause game  
{
    if ([gameScreen gameState]==GAMEOVER) return NO; // no pausing if over
    [pauseMenuCell setTitle:"Unpause"];
    [gameScreen pause:self];
	[gameWindow setTitle:"PacMan - Paused"];
    paused = YES;
    return YES;
}

- unpause			// unpause game  
{
    if ([gameScreen gameState]==GAMEOVER) {
		[pauseMenuCell setEnabled:NO];
		return self; // no pausing if over
	}
    [pauseMenuCell setTitle:"Pause"];
    [gameScreen unpause:self];
	[gameWindow setTitle:"PacMan"];
    paused = NO;
    return self;
}

- startNewGame:sender		// starts a new game
{    
    if (([preferencesBrain alert]) && ([gameScreen gameState]!=GAMEOVER)) {
        if ([highScoreTable highScore:9] < score) {
            if (NXRunAlertPanel("You've got a high score!",
    	        "Do you want to throw away the current game?",
	        "You betcha!", "Um, no.", NULL) != NX_ALERTDEFAULT) {
		return self;  // allow "graceful escape"
	    }
	} else {
            if (NXRunAlertPanel(NULL,
    	        "Do you want to throw away the current game?",
				"You betcha!", "Um, no.", NULL) != NX_ALERTDEFAULT) {
			return self;  // allow "graceful escape"
			}
		}
    }
    [topScoreText setIntValue:[highScoreTable highScore:0]];
    score = 0;
	level = 0;
	lastBonus = 0;
	pointsToNextBonus = 10000;	// first bonus at 10000 points
    ranOnce = YES;
    [pauseMenuCell setEnabled:YES];
    [scoreText setIntValue:score];
    [self nextLevel:self];   // by the nextLevel: method.
    if (paused) [self unpause];
    [gameWindow makeKeyAndOrderFront:self];
	[pacsLeft setNumUp:3];	// start with 3 pacs
    [gameScreen restartGame];
    return self;
}

- unpauseGame:sender		// unpause the game 
{
    return [self pauseGame:sender]; // handles toggle of menuCell
}

- nextLevel:sender		// move to next level-- called when all viruses
				// are gone or to start game
{
    level++;
    [levelText setIntValue:level];
	[fruitBasket showLevel:level];
	[gameScreen setUpScreen];
    return self;
}

- gameOver			// tidy up game, allow high score name entry
				
{
	// remove demo mode title...
	if ([gameScreen demoMode]) [gameWindow setTitle:"PacMan"];
	// if not demo, it's possible to get a high score entry...
	else [highScoreTable putInHighScores:score];
    [pauseMenuCell setEnabled:NO];
    return self;
}


- (int)ateGhost
{
	int temp = ghostScores[ghostCount];
	
	[self addToScore:temp];
	ghostCount++; ghostCount &= 0x3;
	return temp;
}

- resetGhostScore
{
	ghostCount = 0;
	return self;
}



/****
*****  Application DELEGATE methods.  Special things to do on startup, unhide,
*****  hide, and so on.
****/

- appWillInit:sender		// after init, but before 1st event.
{
	alert = NXGetAlertPanel("Pac Man",
		"Just a moment while I load the images...", NULL, NULL, NULL);
	[alert makeKeyAndOrderFront:self];
	return self;
}

- appDidInit:sender		// after init, but before 1st event.
{
	[pauseMenuCell setEnabled:NO];
	
	// methods to load the stuff that takes a while.
	[loadingPanel makeKeyAndOrderFront:self];
	[gameScreen loadPix];			// images, background
	[loadingPanel orderOut:self];

	[preferencesBrain readDefaults:self];
    [gameScreen getPreferences];	// set up final init.
    [gameScreen registerWindow];	// set up dragging.
    [[gameScreen animate:self] update];		// start up animation
	[alert orderOut:self];
	NXFreeAlertPanel(alert);
    [topScoreText setIntValue:[highScoreTable highScore:0]];
    [levelText setIntValue:1];
    [scoreText setIntValue:0];
	[fruitBasket showLevel:1];
	[[fruitBasket window] orderFront:self];
	[[scoreText window] orderFront:self];	// get the stats window visible
    [gameWindow makeKeyAndOrderFront:self]; // activate game window
    [gameWindow makeFirstResponder:gameScreen]; // set up first responder
	if ([preferencesBrain firstTimeCheck]) [infoController readme:self];
    else if ([preferencesBrain autoStart]) [self startNewGame:self];
    return self;
}

- appDidBecomeActive:sender
{
    [gameWindow makeKeyAndOrderFront:self];
    [gameWindow makeFirstResponder:gameScreen];
    if ([preferencesBrain autoUnPause]) [self unpause];

	// make sure the windows are layered properly
	if ([[[fruitBasket window] delegate] windowUp])
		[[fruitBasket window] orderFront:self];
	if ([[[scoreText window] delegate] windowUp])
		[[scoreText window] orderFront:self];
	[gameWindow orderFront:self];

    return self;
}

- appDidHide:sender
{
	[self pause];
    return self;	// pause game on Command-h
}

- appDidResignActive:sender
{
    if ([gameScreen demoMode]) return self;
	[self pause];
    return self;	// pause game on app deactivate
}

- appDidUnhide:sender
{
    [gameWindow makeKeyAndOrderFront:self];
    [gameWindow makeFirstResponder:gameScreen];
   if ([preferencesBrain autoUnPause]) [self unpause];
	// make sure the windows are layered properly
	if ([[[fruitBasket window] delegate] windowUp])
		[[fruitBasket window] orderFront:self];
	if ([[[scoreText window] delegate] windowUp])
		[[scoreText window] orderFront:self];
	[gameWindow orderFront:self];
    return self;
}

- appWillTerminate:sender		// update DEFAULTS here 
{
    [preferencesBrain writeDefaults:self];
    [highScoreTable writeHighScores];
    return self;
}					

- quit:sender
{
	if (([gameScreen gameState] != GAMEOVER) && (![gameScreen demoMode]) &&
			([preferencesBrain alert])) {
		// Verify that player wants to leave game
			[self pause];
		if (!NXRunAlertPanel(NULL,
				"There's a game in progress... Do you really want to quit?",
				"Absolutely.", "No way!", NULL)) {
			return [self unpause];
	}	}
	return [NXApp terminate:sender];
}

- windowDidResginMain:sender	// do pause if window loses main status
{
    [self pause];
	return self;	// pause game
}

- windowDidResignKey:sender		// do pause if window loses key status
{
    [self pause];
	return self;	// pause game
}

- windowDidBecomeKey:sender		// do unpause if window gains key status 
{
    [gameWindow makeFirstResponder:gameScreen];
    if ([preferencesBrain autoUnPause]) [self unpause];	// unpause on unhide*/
	return self;
}

- windowDidMove:sender		// move fruit basket and status with game window 
{
    NXRect gameFrame;
	
	[gameWindow getFrame:&gameFrame];
    [[fruitBasket window] moveTo:(NX_X(&gameFrame) - 137)
		:(NX_Y(&gameFrame) - 37)];
    [[scoreText window] moveTo:(NX_X(&gameFrame) - 137)
		:NX_Y(&gameFrame)];
	return self;
}


@end
