///////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//         This example code is from the book:
//
//           Object-Oriented Programming with C++ and OSF/Motif
//         by
//           Douglas Young
//           Prentice Hall, 1992
//           ISBN 0-13-630252-1	
//
//         Copyright 1991 by Prentice Hall
//         All Rights Reserved
//
//  Permission to use, copy, modify, and distribute this software for 
//  any purpose except publication and without fee is hereby granted, provided 
//  that the above copyright notice appear in all copies of the software.
///////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////
// Engine.C: The brains of the tic-tac-toe game
/////////////////////////////////////////////////////////
#include "TicTacToe.h"
#include "Engine.h"
#include "GameBoard.h"
#include "MoveGenerator.h"
#include "Message.h"
#include "Board.h"
#include <stdlib.h>  // Needed for exit()

Engine::Engine ( TicTacToe* game )
{
    _game      = game;
    _gameOver  = FALSE;
    _whoseMove = XX; // Start with X as the first move
    _board = new Board(); // Create the Engine subcomponents
    _moveGenerator = new MoveGenerator();
}


Engine::~Engine()
{
    delete _board;
    delete _moveGenerator;
}

void Engine::reset()
{
    _whoseMove = XX;
    _gameOver  = FALSE;
    _board->clear();
    _game->gameBoard()->clear();
    _game->messageArea()->postMessage ( NEWGAMEMSG );
}

void Engine::recordMove ( int position )
{
    if ( _gameOver ) // Don't accept moves if the game is over
    {
	_game->messageArea()->postAlert( GAMEISOVERMSG );
	return;
    }
    
    // Record the move. If it is valid, display it on the board
    // Otherwise ask the user to pick again.
    
    if ( _board->recordMove ( position, _whoseMove ) == validMove)
    {
	if(_whoseMove == XX)
	    _game->gameBoard()->markX ( position );
	else
	    _game->gameBoard()->markO ( position );
    }
    else
    {
	_game->messageArea()->postAlert ( ILLEGALMOVEMSG );
	return;
    }
    
    // See if this move wins the game for the user
    
    checkForWin();
    
    if ( _gameOver )
	return;
    
    // If this is the game's move, change to X's move and ask the 
    // user to choose a square. If it is the user's move, change to
    // our move and pick a move. Call this function
    // recursively to record the game's choice.
    
    if ( _whoseMove == OO )
    {	
	_whoseMove = XX;
	_game->messageArea()->postMessage ( USERSMOVEMSG );
    }
    else
    {
	_whoseMove = OO;
	recordMove ( _moveGenerator->getNextMove ( _board ) );
    }
}

void Engine::checkForWin()
{
    int      i, *winningSquares;
    markType winner;
    
    // If no one has won yet, just keep playing
    
    if	( ( winner = _board->whoHasWon() ) == NOBODYYET )
    {
	return;
    }
    else if ( winner == TIE)
    {
	// If it's a tie, end the game and notify the user
	
	_gameOver = TRUE;	
	
	for ( i = 0 ; i < 9; i++ )
	    _game->gameBoard()->deemphasizeSquare ( i );
	
	_game->messageArea()->postAlert( TIEGAMEMSG );
    }
    else // Someone won 
    {
	_gameOver = TRUE;	
	
	// Get the mask for the wining pattern 
	
	winningSquares = _board->winningSquares();
	
	// Deactivate each square to prevent input. Highlight
	// the winning squares, and fade others into the background.
	
	for ( i = 0 ; i < 9; i++ )
	{
	    _game->gameBoard()->deactivateSquare ( i );
	    
	    if ( winningSquares[i] )	    
		_game->gameBoard()->highlightSquare ( i );
	    else
		_game->gameBoard()->deemphasizeSquare ( i );
	}
	
	// Finally, alert the user that someone has won
	
	if ( winner  == XX )
	    _game->messageArea()->postAlert ( XWINSMSG );
	else
	    _game->messageArea()->postAlert ( OWINSMSG );	
    }
}

void Engine::quit()
{
    exit ( 0 );
}
