#include "TestWin.h"
#include "Muele.h"
#include <memory.h>

CTestWin::CTestWin(const char *pBoard, char *pWinBoard, int boardSizeX, int boardSizeY, int boardSizeZ, char playerToTest, int winFieldCount, int returnImmediately)
:pBoard(pBoard), pWinnerBoard(pWinBoard), boardSizeX(boardSizeX), boardSizeY(boardSizeY), boardSizeZ(boardSizeZ), whichPlayer(playerToTest),
 winFieldCount(winFieldCount), returnImmediately(returnImmediately)
{
	boardFieldCount = boardSizeX * boardSizeY * boardSizeZ;
	boardFieldCountPlain = boardSizeX * boardSizeY;
	winFieldCountTimesX = winFieldCount * boardSizeX;
}

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

CTestWin::~CTestWin(void)
{
}

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

bool CTestWin::testWin()
{
	int tmpAddr;
	bool win = false;
   
	if ( boardSizeX >= winFieldCount )
	{
		// check for win in x direction in every z plain
		for ( int iz = 0; iz < boardFieldCount; iz+=boardFieldCountPlain )
			for ( int iy = 0; iy < boardFieldCountPlain; iy+=boardSizeX )
				for ( int ix = 0; ix <= boardSizeX - winFieldCount; ix++ )
				{
					//tmpAddr = iz + iy + ix;
					for ( int ic = 0; ic < winFieldCount; ic++ )
						if ( *(pBoard + iz + iy + ix + ic) != whichPlayer ) goto break1;

					if ( returnImmediately ) return true; else win = true;
					memset( pWinnerBoard + iz + iy + ix , whichPlayer, winFieldCount);
break1:;
				}

		// check for win in diagonal x direction over several z plains
		if ( boardSizeZ >= winFieldCount )
		{
			for ( int iy = 0; iy < boardSizeY ; iy++ )
				for ( int iz = 0; iz <= boardSizeZ - winFieldCount; iz++ )
					for ( int ix = 0; ix <= boardSizeX - winFieldCount; ix++ )
					{
						tmpAddr = iz * boardFieldCountPlain + iy * boardSizeX + ix;
						for ( int ic = 0; ic < winFieldCount; ic++ )
							if ( *(pBoard + tmpAddr + ic * boardFieldCountPlain + ic) != whichPlayer ) goto break5;

						if ( returnImmediately ) return true; else win = true;
						for ( int ic = 0; ic < winFieldCount; ic++ )
							*(pWinnerBoard + tmpAddr + ic * boardFieldCountPlain + ic) = whichPlayer;
break5:;
						tmpAddr+=(winFieldCount - 1) * boardFieldCountPlain;
						for ( int ic = 0; ic < winFieldCount; ic++ )
							if ( *(pBoard + tmpAddr - ic * boardFieldCountPlain + ic) != whichPlayer ) goto break6;

						if ( returnImmediately ) return true; else win = true;
						for ( int ic = 0; ic < winFieldCount; ic++ )
							*(pWinnerBoard + tmpAddr - ic * boardFieldCountPlain + ic) = whichPlayer;
break6:;
					}

		} // boardSizeZ >= winFieldCount 
	} // boardSizeX >= winFieldCount

	if ( boardSizeY >= winFieldCount )
	{
		// check for win in y direction in every z plain
		for ( int iz = 0; iz < boardFieldCount; iz+=boardFieldCountPlain )
			for ( int iy = 0; iy <= boardFieldCountPlain - winFieldCountTimesX; iy+=boardSizeX )
				for ( int ix = 0; ix < boardSizeX ; ix++ )
				{
					tmpAddr = iz + iy + ix;
					for ( int ic = 0; ic < winFieldCount; ic++ )
						if ( *(pBoard + tmpAddr + ic * boardSizeX ) != whichPlayer ) goto break2;

					if ( returnImmediately ) return true; else win = true;
					for ( int ic = 0; ic < winFieldCount; ic++ )
						*(pWinnerBoard + tmpAddr + ic * boardSizeX ) = whichPlayer;

break2:;
				}

		// check for win in diagonal y direction over several z plains
		if ( boardSizeZ >= winFieldCount )
		{
			for ( int ix = 0; ix < boardSizeX ; ix++ )
				for ( int iz = 0; iz <= boardSizeZ - winFieldCount; iz++ )
					for ( int iy = 0; iy <= boardSizeY - winFieldCount; iy++ )
					{
						tmpAddr = iz * boardFieldCountPlain + iy * boardSizeX + ix;
						for ( int ic = 0; ic < winFieldCount; ic++ )
							if ( *(pBoard + tmpAddr + ic * boardFieldCountPlain + ic * boardSizeX) != whichPlayer ) goto break7;

						if ( returnImmediately ) return true; else win = true;
						for ( int ic = 0; ic < winFieldCount; ic++ )
							*(pWinnerBoard + tmpAddr + ic * boardFieldCountPlain + ic * boardSizeX) = whichPlayer;
break7:;
						tmpAddr+=(winFieldCount - 1) * boardFieldCountPlain;
						for ( int ic = 0; ic < winFieldCount; ic++ )
							if ( *(pBoard + tmpAddr - ic * boardFieldCountPlain + ic * boardSizeX) != whichPlayer ) goto break8;

						if ( returnImmediately ) return true; else win = true;
						for ( int ic = 0; ic < winFieldCount; ic++ )
							*(pWinnerBoard + tmpAddr - ic * boardFieldCountPlain + ic * boardSizeX) = whichPlayer;
break8:;
					}
		} // boardSizeZ >= winFieldCount 

		if ( boardSizeX >= winFieldCount )
		{
			// check for win in diagonal x direction in every z plain
			for ( int iz = 0; iz < boardSizeZ ; iz++ )
				for ( int iy = 0; iy <= boardSizeY - winFieldCount ; iy++ )
					for ( int ix = 0; ix <= boardSizeX - winFieldCount; ix++ )
					{
						tmpAddr = iz * boardFieldCountPlain + iy * boardSizeX + ix;
						for ( int ic = 0; ic < winFieldCount; ic++ )
							if ( *(pBoard + tmpAddr + ic * boardSizeX + ic) != whichPlayer ) goto break3;

						if ( returnImmediately ) return true; else win = true;
						for ( int ic = 0; ic < winFieldCount; ic++ )
							*(pWinnerBoard + tmpAddr + ic * boardSizeX + ic) = whichPlayer;
break3:;
						tmpAddr += ( winFieldCount - 1 ) * boardSizeX;
						for ( int ic = 0; ic < winFieldCount; ic++ )
							if ( *(pBoard + tmpAddr - ic * boardSizeX + ic) != whichPlayer ) goto break4;

						if ( returnImmediately ) return true; else win = true;
							for ( int ic = 0; ic < winFieldCount; ic++ )
								*(pWinnerBoard + tmpAddr - ic * boardSizeX + ic) = whichPlayer;
break4:;
					}
			if ( boardSizeZ >= winFieldCount )
			{
				// check for win in diagonal x and  y directionen over different z plains
				for ( int iz = 0; iz <= boardSizeZ - winFieldCount; iz++ )
					for ( int iy = 0; iy <= boardSizeY - winFieldCount; iy++ )
						for ( int ix = 0; ix <= boardSizeX - winFieldCount; ix++ )
						{
							tmpAddr = iz * boardFieldCountPlain + iy * boardSizeX + ix;
							for ( int ic = 0; ic < winFieldCount; ic++ )
								if ( *(pBoard + tmpAddr + ic * boardFieldCountPlain + ic * boardSizeX + ic) != whichPlayer ) goto break10;

							if ( returnImmediately ) return true; else win = true;
							for ( int ic = 0; ic < winFieldCount; ic++ )
								*(pWinnerBoard + tmpAddr + ic * boardFieldCountPlain + ic * boardSizeX + ic) = whichPlayer;
break10:;
							tmpAddr += ( winFieldCount - 1) * boardFieldCountPlain;
							for ( int ic = 0; ic < winFieldCount; ic++ )
								if ( *(pBoard + tmpAddr - ic * boardFieldCountPlain + ic * boardSizeX + ic) != whichPlayer ) goto break11;

							if ( returnImmediately ) return true; else win = true;
							for ( int ic = 0; ic < winFieldCount; ic++ )
								*(pWinnerBoard + tmpAddr - ic * boardFieldCountPlain + ic * boardSizeX + ic) = whichPlayer;
break11:;
							tmpAddr += ( winFieldCount - 1) * boardSizeX;
							for ( int ic = 0; ic < winFieldCount; ic++ )
								if ( *(pBoard + tmpAddr - ic * boardFieldCountPlain - ic * boardSizeX + ic) != whichPlayer ) goto break12;

							if ( returnImmediately ) return true; else win = true;
							for ( int ic = 0; ic < winFieldCount; ic++ )
								*(pWinnerBoard + tmpAddr - ic * boardFieldCountPlain - ic * boardSizeX + ic) = whichPlayer;
break12:;
							tmpAddr -= ( winFieldCount - 1) * boardFieldCountPlain;
							for ( int ic = 0; ic < winFieldCount; ic++ )
								if ( *(pBoard + tmpAddr + ic * boardFieldCountPlain - ic * boardSizeX + ic) != whichPlayer ) goto break13;

							if ( returnImmediately ) return true; else win = true;
							for ( int ic = 0; ic < winFieldCount; ic++ )
								*(pWinnerBoard + tmpAddr + ic * boardFieldCountPlain - ic * boardSizeX + ic) = whichPlayer;
break13:;
						}


			} //boardSizeZ >= winFieldCount
		} //boardSizeX >= winFieldCount
	} // boardSizeY >= winFieldCount

	// check for win in z direction
	if ( boardSizeZ >= winFieldCount )
	{
		for ( int ix = 0; ix < boardSizeX; ix++ )
			for ( int iy = 0; iy < boardSizeY; iy++ )
				for ( int iz = 0; iz <= boardSizeZ - winFieldCount; iz++ )
				{
					tmpAddr = iz * boardFieldCountPlain + iy * boardSizeX + ix;
					for ( int ic = 0; ic < winFieldCount; ic++ )
						if ( *(pBoard + tmpAddr + ic * boardFieldCountPlain ) != whichPlayer ) goto break9;

					if ( returnImmediately ) return true; else win = true;
					for ( int ic = 0; ic < winFieldCount; ic++ )
						*(pWinnerBoard + tmpAddr + ic * boardFieldCountPlain ) = whichPlayer;
break9:;
				}
	} // boardSizeZ >= winFieldCount 

	return win;
}
