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

                                 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 "../PieceType.h"
#include "CylindricalBoard.h"


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


CylindricalBoard::CylindricalBoard
	( int ranks, 
	  int files ):
		Board(ranks, files)
{
	boardWrapsAround = true;
}

void CylindricalBoard::PostInitialize()
{
	//	first, call the base class's PostInitialize, since most of what it 
	//	does is correct; we'll change the differences after
	Board::PostInitialize();

	//	re-initialize movement matricies, accounting for cylindrical board 
	for( int x = 0; x < directionCount; x++ )
	{
		Direction &direction = directions[x];
		ASSERT(direction.GetOppositeDirectionNumber() >= 0 && direction.GetOppositeDirectionNumber() < directionCount);
		movementMatrix[x] = new int[GetNumberOfSquares()];
		for( int rank = 0; rank < nRanks; rank++ )
		{
			for( int file = 0; file < nFiles; file++ )
			{
				int squareNumber = rank * GetNumberOfFiles() + file;
				int newRank = rank + direction.GetRankDifference();
				int newFile = file + direction.GetFileDifference();
				//	perform cylindrical "rolling"
				if( newFile >= nFiles )
					newFile = newFile - nFiles;
				else if( newFile < 0 )
					newFile = newFile + nFiles;
				bool stillOnBoard = newRank >= 0 && newRank < nRanks;
				if( stillOnBoard )
				{
					int nextSquareNumber = newRank * GetNumberOfFiles() + newFile;
					movementMatrix[x][squareNumber] = nextSquareNumber;
				}
				else
					movementMatrix[x][squareNumber] = -1;
			}
		}
	}

	//	re-initialize direction look-up matrix; this code is roughly the same 
	//	as it was in Board::Initialize(), but we need to re-do it, since the 
	//	movement matricies have changed. 
	for( int from = 0; from < nSquares; from++ )
		for( int to = 0; to < nSquares; to++ )
		{
			directionLookup[from][to][0] = -1;
			directionLookup[from][to][1] = -1;
			directionLookup[from][to][2] = -1;
			directionLookup[from][to][3] = -1;
			int directionsMatched = 0;
			
			for( int x = 0; x < directionCount; x++ )
			{
				Direction &dir = directions[x];
				int *matrix = movementMatrix[x];
				int square = matrix[from];
				while( square != -1 && square != from )
				{
					if( square == to )
					{
						ASSERT(directionsMatched < 4);
						directionLookup[from][to][directionsMatched++] = x;
						square = -1;
					}
					else
						square = matrix[square];
				}
			}
		}
}
