/*
* Neural Networks Tearm Project
* Martin Johne
* 04.10.2006
*/
#pragma once
#include "LookUpTable.h"
#include "Symmetry.h"
#include "Muele.h"
#include "TestWin.h"

#define FILE_MARK 1649024562	// max long val 4,294,967,295

//! This class provides two neural networks based on a game board.
class CNeuralNetwork
{
public:

	// methods

	CNeuralNetwork(int boardSizeX, int boardSizeY, int boardSizeZ, int winFieldCount, int countHiddenNeurons, bool largeInputVector, CMuele *pMuele);
	~CNeuralNetwork(void);

	//! Gives the output value of the neural network with the given game board as input pattern.
	double propagate(char *pBoard, char player, bool createTheInputVector = true);
	//! Trains the given value to a given game board as input pattern.
	void trainValue(char *pBoard, char player, double trainValue, double learnRate, double maxError);
	//! Returns the best rated move based on the given board.
	int getBestMove(char *pBoard, char player);
	//! Trains the networks through competition, with before initialized parameters.
	void learn();
	//! Trains the networks through competition, with before initialized parameters.
	void learnTest();
	//! Trains the networks through competition, with before initialized parameters.
	void learnTest2();
	//! Sets the learn parameters for the networks for a new training session.
	void setLearnParameters();
    //! Stores the current networks in a file.
	bool saveNet(const wchar_t *pFileName);
	//! Reads the current networks from a file.
    bool loadNet(const wchar_t *pFileName);

	// variables

	int gamesCount, actualCycle;
	unsigned trainingTime;

	int numberInputNeurons;
	int numberHiddenNeurons;

	bool largeInputVector, wasTrained;

	unsigned drawCount, win1Count, win2Count;
	double maxErrorStart, maxErrorEnd;
	double trainRateStart, trainRateEnd;
	double stepSizeStart, stepSizeEnd;

private:

	// methods

	void createInputVector(const char *pBoard);
	void aICompetition( char weakPlayer, int testCount, int &wonPlayer1, int &draws, int &wonPlayer2);
	void resetWeights(char player);
	void deleteUsedMemory();
	void allocateMemory();
	void xorTest();

	// variables

	int boardFieldCount;
	double *pWeightsHidden1, *pWeightsHidden2;
	double *pWeightsOut1, *pWeightsOut2;

	double *pInputVector;
	double *pGradientsHidden;
	double *pOutputHidden;
	
	int boardSizeX, boardSizeY, boardSizeZ;
	int	boardFieldCountPlain;
	int winFieldCount;

	int strengthCount, maxDepth, netRaiting;
	int oldCyclesPlayer1, oldCyclesPlayer2;
	int maxDepthCount;
   
	CSymmetry *pSymmetry;
	CMuele    *pMuele;

	char	  *pBoard;
	CTestWin  *pTestWinPlayer1, *pTestWinPlayer2;

};
