
/***************************************************************************

                                 ChessV

                   COPYRIGHT (C) 2005 BY GREGORY STRONG

This file is part of ChessV.  ChessV is free software; you can redistribute
it and/or modify it under the terms of the GNU General Public License as 
published by the Free Software Foundation; either version 2 of the License, 
or (at your option) any later version.

ChessV is distributed in the hope that it will be useful, but WITHOUT ANY 
WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
more details; the file 'COPYING' contains the License text, but if for
some reason you need a copy, please write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

****************************************************************************/


#include "StdAfx.h"
#include "AlapoGame.h"
#include "../../Piece.h"
#include "../../ChessV.h"
#include "../../GameParameters.h"


// *** DEBUG MEMORY ALLOCATION *** //
#ifdef _DEBUG
#define new SAFE_NEW
#endif


static int squareBonuses[] = {   0,   0,   0,   0,   0,   0, 
                                 5,  10,  30,  30,  10,   5, 
					            20,  40,  80,  80,  40,  20,
						        75, 105, 145, 145, 105,  75,
						       155, 175, 220, 220, 175, 155,
							   400, 400, 400, 400, 400, 400  };


//	instances of PieceTypes
AlapoLargeSquare AlapoLargeSquare::alapoLargeSquare;
AlapoSmallSquare AlapoSmallSquare::alapoSmallSquare;
AlapoLargeTriangle AlapoLargeTriangle::alapoLargeTriangle;
AlapoSmallTriangle AlapoSmallTriangle::alapoSmallTriangle;
AlapoLargeCircle AlapoLargeCircle::alapoLargeCircle;
AlapoSmallCircle AlapoSmallCircle::alapoSmallCircle;


Game *CreateAlapoGame( Board &brd, Player &plr0, Player &plr1 )
{
	return new AlapoGame( brd, plr0, plr1 );
}


AlapoGame::AlapoGame( Board &board, Player &whitePlayer, Player &blackPlayer ):
	Game(board, whitePlayer, blackPlayer)
{
	//	this game has a different victory condition; disable checkmate
	goalIsCheckmate = false;

	//	'stalemate' in this case can only happen when a player has 
	//	no pieces to move.  although the rules don't specifically say so, 
	//	stalemating your opponent is considered a win.
	stalemateResult = INFINITY;

	//	turn off null-move after 14 pieces have been captured
	endgameCaptureThreshold = 14;

	//	reduce the value of the squares
	boardAverageSquareValue = 50;

	//	razoring and futility pruning margins
	razorMargin = 10000;
	futilityMargin = 4000;
	extendedFutilityMargin = 6000;

	// *** PHASES *** //

	//	we have to set up the phases we wish to have in this game;
	//	we will keep it very simple and have just one
	nPhases = 1;

	//	settings for phase 0
	phases[0].SetNumber( 0 );
	phases[0].SetMobilityFactor( 0 );
	phases[0].SetPawnDeficiencyFactor( 0 );
	phases[0].SetSquareValuesFactor( 1 );
	phases[0].SetKingSafetyFactor( 0 );
	phases[0].SetTropismFactor( 0 );

	// *** INITIALIZATION *** //
	board.Initialize( this, BITBOARD_64 );
}

void AlapoGame::AddPlayerPieceTypes( char *gameName )
{
	//	add the piece types that each player may have
	board.AddPlayerPieceTypeBothPlayers( AlapoLargeSquare::alapoLargeSquare );
	board.AddPlayerPieceTypeBothPlayers( AlapoSmallSquare::alapoSmallSquare );
	board.AddPlayerPieceTypeBothPlayers( AlapoLargeTriangle::alapoLargeTriangle );
	board.AddPlayerPieceTypeBothPlayers( AlapoSmallTriangle::alapoSmallTriangle );
	board.AddPlayerPieceTypeBothPlayers( AlapoLargeCircle::alapoLargeCircle );
	board.AddPlayerPieceTypeBothPlayers( AlapoSmallCircle::alapoSmallCircle );
}

void AlapoGame::ChangeRulesByVariant
	( char *gameName,
	  char *&array,
	  char *&book )
{
	// *** ALAPO *** //
	if( !strcmp( gameName, "Alapo" ) )
	{
		//	set piece-square-value tables
		AlapoLargeSquare::alapoLargeSquare.SetSquareBonuses( 0, squareBonuses );
		AlapoSmallSquare::alapoSmallSquare.SetSquareBonuses( 0, squareBonuses );
		AlapoLargeCircle::alapoLargeCircle.SetSquareBonuses( 0, squareBonuses );
		AlapoSmallCircle::alapoSmallCircle.SetSquareBonuses( 0, squareBonuses );
		AlapoLargeTriangle::alapoLargeTriangle.SetSquareBonuses( 0, squareBonuses );
		AlapoSmallTriangle::alapoSmallTriangle.SetSquareBonuses( 0, squareBonuses );
		//	place pieces
		array = "lsltlclcltls/ssstscscstss/6/6/SSSTSCSCSTSS/LSLTLCLCLTLS";
		//	set name of opening book
		book = "openings\\Alapo.txt";
	}
}

bool AlapoGame::TestForWinLossDraw
	( int &eval )
{
	//	TODO: rewrite this with bitboards

	//	check bank ranks to see if there is a 
	//	piece there of the other player that can't be 
	//	captured.  this is the victory condition of Alapo.
	for( int x = 0;  x < 6; x++ )
	{
		Piece *piece = board.GetSquareContents( x );
		if( piece != NULL && piece->GetPlayerNumber() == 1 )
		{
			//	there's an enemy piece there ... now see 
			//	if it is attacked.  if not, game over!
			if( !IsSquareAttacked( x, 0 ) )
			{
				if( board.GetCurrentPlayerNumber() == 0 )
					eval = -MATE;
				else
					eval = MATE;
				return true;
			}
		}
	}
	for( int x = 30;  x < 36; x++ )
	{
		Piece *piece = board.GetSquareContents( x );
		if( piece != NULL && piece->GetPlayerNumber() == 0 )
		{
			//	there's an enemy piece there ... now see 
			//	if it is attacked.  if not, game over!
			if( !IsSquareAttacked( x, 1 ) )
			{
				if( board.GetCurrentPlayerNumber() == 0 )
					eval = MATE;
				else
					eval = -MATE;
				return true;
			}
		}
	}
	//	nothing special going on; return false
	return false;
}

bool AlapoGame::MoveBeingMade
	( MoveInfo &moveInfo,
	  GameRec &gameRecord )
{
	//	TODO: rewrite this with bitboards

	//	we need to check for a special case of illegal move here; 
	//	if the opponent has a piece on my back rank, I need to take 
	//	it right now; any other move would be illegal
	if( board.GetCurrentPlayerNumber() == 0 )
	{
		for( int x = 0; x < 6; x++ )
		{
			Piece *piece = board.GetSquareContents( x );
			if( piece != NULL && piece->GetPlayerNumber() == 1 )
				return false;
		}
	}
	else
	{
		for( int x = 30; x < 36; x++ )
		{
			Piece *piece = board.GetSquareContents( x );
			if( piece != NULL && piece->GetPlayerNumber() == 0 )
				return false;
		}
	}
	return true;
}
