/*
 * Created on 23.11.2004
 *
 */
package de.farafin.snEADy;

import java.io.FileNotFoundException;

import de.farafin.snEADy.communication.D_GameInfo;
import de.farafin.snEADy.communication.D_Level;
import de.farafin.snEADy.communication.D_PlayerData;
import de.farafin.snEADy.communication.D_RecoverData;
import de.farafin.snEADy.communication.I_Constants;
import de.farafin.snEADy.communication.I_PlayFieldConstants;
import de.farafin.snEADy.control.C_Human;
import de.farafin.snEADy.control.GaphixStuff.M_GraphixEngineUI;
import de.farafin.snEADy.inOut.C_FileClassLoader;
import de.farafin.snEADy.inOut.C_LevelLoader;
import de.farafin.snEADy.inOut.C_LogFileReader;
import de.farafin.snEADy.inOut.C_LogFileWriter;
import de.farafin.snEADy.inOut.E_LevelFileException;

/**
 * The main is for the organisation of the program. should the game be paused or what should be
 * initialized.. all this is handled by the M_Main.
 * Also the dataflow from gameEngine to the controll interface is lead over main.
 * 
 * @author roland, lars
 * 
 * @version $Revision: 1.117 $ 
 */ 
public final class M_Main implements I_Main_interface, I_Constants, I_GameStats, I_PlayFieldConstants
{
	//-------------------------------------------------------------------------------------
	//- attributes ------------------------------------------------------------------------
	//-------------------------------------------------------------------------------------

	// modules
	/** an instance of the gameEngine module */
	private M_GameEngine gameEngine;

	/** the instance of the graphic module */
	private M_GraphixEngineUI gui;
	
	/** the game info that the manEngine gets after the play feald changed */
	private D_GameInfo gameInfo;
	
	/** the initial gameInfo. its stored to make it possible to restart teh game. */
	private D_GameInfo initGameInfo;

	/** The current game State.. */
	private int gameState;
	
	//** for storing the restart script. */
	//private C_LogFileWriter startWriter = null;
	
	//** for reading the restart script. */
	//private C_LogFileReader startReader = null;

	/** if control needs some time, it must be looked, so that nothing bad can happen.. not very
	 * clean... sorry */
	private boolean lockedControl = false;
	
	/** logs what was told to the control function from the beginning on.
	 * DO NOT USE AS SCRIPT */
	private C_LogFileWriter controlLog = null;

	/** parameter set of GameParameter */
	private final GameParameter parameter;
	
	// others
	/** the instance of the main Engine.. there is always only one per program */
	private static M_Main instance;
	
	/** the debug monitor for the player */
	private final C_DebugMonitor monitor;
	
	/** Version Number */
	private static int version = 1000;
	
	
	//-------------------------------------------------------------------------------------
	//- constructor -----------------------------------------------------------------------
	//-------------------------------------------------------------------------------------

	/**
	 * constructor of M_Main
	 * @see #getInstance()
	 */
	private M_Main()
	{
		this.gameState = PROG_INIT;
		this.parameter = new GameParameter();
		this.monitor = new C_DebugMonitor();
		
		this.gameInfo = new D_GameInfo();
		this.initGameInfo = null;
		//this.startWriter = new C_LogFileWriter("scripts", "restart.script");
		//this.startReader = null;
		this.lockedControl = false;
		this.controlLog = new C_LogFileWriter("logs", "control.log");

		instance = this;
		
		this.gameEngine = M_GameEngine.getInstance();
	}
	
	//-------------------------------------------------------------------------------------
	//- private methods -------------------------------------------------------------------
	//-------------------------------------------------------------------------------------
	
	
	/**
	 * @param className the name of the class that should be loaded
	 * @return an instance of the loaded class or null if the load failed
	 */
	private Class loadPlayerClass(String className)
	{
		try
		{
			// Dadurch, dass jedesmal ein neuer ClassLoader angelegt
			// wird, werden die Klassen stets neu geladen.

			Class c = new C_FileClassLoader("player").loadClass(className, true);
			return c;
		}
		catch(Exception e)
		{
			System.out.println("WARNING: player wasnt loaded \n\t" + e);
			
			return null;
		}
	}
	
	/* (non-Javadoc)
	 * @see de.farafin.snEADy.I_Main_interface#getPlayerComment(java.lang.String)
	 */
	public String getPlayerComment(String playerName)
	{
		String s = null;
		Class c = loadPlayerClass(playerName);
		if(c == null) return "";
		
		try
		{
			s =  (String)c.getField("comment").get(null);
		}
		catch(IllegalArgumentException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
			return "";
		}
		catch(SecurityException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
			return "";
		}
		catch(IllegalAccessException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
			return "";
		}
		catch(NoSuchFieldException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
			return "";
		}
		
		return s;
	}
	
	/* (non-Javadoc)
	 * @see de.farafin.snEADy.I_Main_interface#getLevelHeader(java.lang.String)
	 */
	public D_Level getLevelHeader(String levelName)
	{
		C_LevelLoader levelLoader = new C_LevelLoader();
		D_Level level = null; 
		try	{level = levelLoader.loadLevelHeader(levelName);}
		catch(FileNotFoundException e)
		{
			// this happends when a file is not found
			
			/*
			 * TODO #lars: compute the case that the file was not found!
			 */			
			System.out.println("WARNING: " + e);
			return null;
		}
		catch(E_LevelFileException e)
		{
			// this happends if somewhere in the level file, the format is not interpretable by
			// the level loader because of wrong characters or wrong formation

			/*
			 * TODO #lars compute the case that the file has a wrong format!
			 */			
			System.out.println("WARNING: " + e);
			return null;
		}

		return level;
	}

	/**
	 * Loads a level of a specified file. Also computes errors of the file and the case that
	 * the file is not found.
	 * 
	 * @param levelName the name of the level that should be loaded
	 * @return the level
	 */
	private D_Level loadLevel(String levelName)
	{
		C_LevelLoader levelLoader = new C_LevelLoader();
		D_Level level = null; 
		try	{level = levelLoader.loadLevel(levelName);}
		catch(FileNotFoundException e)
		{
			// this happends when a file is not found
			
			System.out.println("WARNING: " + e);
			return null;
		}
		catch(E_LevelFileException e)
		{
			// this happends if somewhere in the level file, the format is not interpretable by
			// the level loader because of wrong characters or wrong formation

			System.out.println("WARNING: " + e);
			return null;
		}

		return level;
	}
	
	/** starts the game at the beginning, just to say: starts the gameEngine Maincycle
	 * @param initData
	 */
	private void startGame(D_GameInfo initData)
	{
		this.gameEngine.initGame(initData);
		this.gameState = GAME_PAUSE;
		gameEngine.start();
	}

	/** recover a saved game
	 * @param recoverData
	 */
	private void recover(D_RecoverData recoverData)
	{
	// TODO Auto-generated method stub

	}


	/** loads and computs the start script.
	 * @param args the arguments which are given the program
	 */
	private void startScript(String[] args)
	{
		String fileName = null;
		this.controlLog.storeLine("Program arguments:");
		this.controlLog.storeLine("\t");
		for(int i = 0; i<args.length; i++)
		{
			this.controlLog.addToLastLine(args[i] + " ");
			if(args[i].startsWith("-script"))
			{
				i++;
				fileName = args[i] + ".script";
			}
		}
		
		if(fileName == null)
		{
			fileName = "default.script";
		}

		this.controlLog.storeLine("load Script: " + fileName);
		loadScript("scripts", fileName);
		
		gui.setActive(true);
	}
	
	/**
	 * @param root
	 * @param fileName
	 * @return boolean
	 */
	private boolean loadScript(String root, String fileName)
	{
		C_LogFileReader script = null;
		String line = null;
		try
		{
			script = new C_LogFileReader(root, fileName);
			
			while(!script.isFinished())
			{
				// read line
				line = script.readNextLine();
				// scipp everything behind "%"
				line = line.split("%")[0];
				// perform command
				control(line);
			}
		}
		catch (FileNotFoundException e)
		{
			System.out.println("WARNING: Script wasn't loaded!\n" + e);
			return false;
		}
		return true;		
	}
	
	//-------------------------------------------------------------------------------------
	//- public methods --------------------------------------------------------------------
	//-------------------------------------------------------------------------------------
	
	/** writes the game results to result.log */
	private void writeResults()
	{
		C_LogFileWriter writer = new C_LogFileWriter("logs", "result.log");
		writer.storeLine("final Game Time:    " + this.gameInfo.gameTime);
		writer.storeLine("used Level:\n" + this.gameInfo.level + "\n");
		writer.storeLine("===============================================");		
		for(int j = 0; j < this.gameInfo.playerData.length; j++)
		{
			writer.storeLine("player " + j + ":");
			writer.storeLine("\tname:               " + this.gameInfo.playerData[j].name);
			writer.storeLine("\tlength:             " + this.gameInfo.playerData[j].length);
			writer.storeLine("\tPoints:        " + this.gameInfo.playerData[j].killPoints);
			switch(this.gameInfo.playerData[j].snakeStatus)
			{
				case IN_ACTION:
					writer.storeLine("\tstate:              IN_ACTION");
					break;
				case IN_HEAVEN:
					writer.storeLine("\tstate:              IN_HEAVEN");
					break;
				case IN_EXIT:
					writer.storeLine("\tstate:              IN_EXIT");
					break;
				case IN_ERROR_TIME:
					writer.storeLine("\tstate:              IN_ERROR_TIME");
					break;
				case IN_ERROR_SPACE:
					writer.storeLine("\tstate:              IN_ERROR_SPACE");
					break;
				case IN_ERROR_INIT:
					writer.storeLine("\tstate:              IN_ERROR_INIT");
					break;
				case IN_ERROR_EXC:
					writer.storeLine("\tstate:              IN_ERROR_EXC");
					break;
				default:;
			}
			writer.storeLine("-----------------------------------------------");
		}
		writer.safeAndCloseFile();
	}
	
	/** set the gameInfo and updates the graphic
	 * @param gameInfo the game info that should be used. its only a reference-copy
	 * @param humanInstances instances of human player Classes
	 */
	protected void update(D_GameInfo gameInfo, C_Human[] humanInstances)
	{ 
		int snakeCount;
		int i=0;
		// TODO roland: make it possible to compute different gameStats!
		switch(M_Main.getInstance().getGameState())
		{
			case PROG_INIT:
				if(DEBUG) System.out.println("DEBUG WARNING: nothing to do for M_Main.update while PROG_INIT");
				break;
			case PROG_END:
				this.gameInfo = gameInfo;
				writeResults();
				this.quit(0);
				break;
			case GAME_RUNNING:
				snakeCount = 0;
				for(i=0; i<gameInfo.playerData.length; i++)
				{
					if(gameInfo.playerData[i].snakeStatus == IN_ACTION) snakeCount++;
					else if(gameInfo.playerData[i].snakeStatus == IN_EXIT && gameInfo.playerData[i].length >= 1)  snakeCount++;
				}
				if(snakeCount <= 0) this.gameState = GAME_PAUSE;
				this.gameInfo = gameInfo;
				this.gui.update(this.gameInfo, humanInstances);
				break;
			case GAME_INIT:
				this.gameInfo = gameInfo;
				this.gui.update(this.gameInfo, humanInstances);
				break;
			case GAME_PAUSE:
				this.gameInfo = gameInfo;
				this.gui.update(this.gameInfo, humanInstances);
				break;
			case GAME_SAFE:
				// TODO roland: ??
				break;
			case GAME_RECOVER:
				// TODO roland: ??
				break;
			case GAME_ABBORT:
				this.gameInfo = gameInfo;
				writeResults();
				this.gui.update(this.gameInfo, humanInstances);
				M_GameEngine.destroyInstance(this.gameEngine);
				this.gameEngine = null;
				this.gameInfo = null;
				System.gc();
				this.gameInfo = new D_GameInfo();
				this.gameEngine = M_GameEngine.getInstance();
				this.gameState = GAME_INIT;
				/*
				try
				{
					this.startReader = new C_LogFileReader("scripts", "restart.script");
				}
				catch(FileNotFoundException e)
				{
					e.printStackTrace();
					this.startReader = null;
				}
				this.startWriter = new C_LogFileWriter("scripts", "restart.script");
				*/
				break;
		}
	}

	//-------------------------------------------------------------------------------------
	//- public state handling methods -----------------------------------------------------
	//-------------------------------------------------------------------------------------

	/** recover a game with a before safed game.
	 * @param rootPath
	 * @param fileName
	 */
	private void gameRecover(String rootPath, String fileName)
	{
	// TODO Auto-generated method stub

	}
	
	/** Safe the current game */
	private void gameSafe()
	{
	// TODO Auto-generated method stub

	}
	
	// TODO roland: DELETE IMERGYNCY PAUSE CONCEPT
	/**  */
	private void imergencyPause()
	{
		this.gameEngine.imergencyPause();
	}
	
	/** kills all threads and ends the program */
	private void kill()
	{
		if(this.gameEngine != null)	this.gameEngine.kill();
		//this.control.close();
		this.quit(0);
	}
	/** @return Returns the gameState. */
	protected int getGameState(){return gameState;}

	/**
	 * @return Returns the parameter.
	 */
	protected GameParameter getParameter(){return this.parameter;}
	
	/**
	 * @return Returns the monitor.
	 */
	protected C_DebugMonitor getMonitor(){return this.monitor;}
	//-------------------------------------------------------------------------------------
	//- public static methods -------------------------------------------------------------
	//-------------------------------------------------------------------------------------

	/**
	 * prevents that more than one instance of the class exists in the program
	 * 
	 * @return a new instance if it doesnt already exist, if so, it returns the old one
	 */
	protected static M_Main getInstance()
	{
		//if(instance == null) instance = new M_Main();
		return instance;
	}
	
	/**
	 * @param args
	 * 
	 * main method: should work with arguments
	 */
	public static void main(String[] args)
	{
		M_Main main = new M_Main();
		
		main.gui=new M_GraphixEngineUI(main, main.parameter, main.monitor, version);
		 
		main.gameState = GAME_INIT;

		// start game running cycle
		main.startScript(args);
	}
	/*
	 * <li> <b>set SEGMENT_LOSE_RATE</b>, the amount of length a snake should loose each time it runs into
	 * an other snake. Default is 2; must be >= 1<br>
	 * <br>
	 */
	
	/* (non-Javadoc)
	 * @see de.farafin.GameParameter.I_Main_interface#control(java.lang.String)
	 */
	/** possible Comments: All commands are posed in the string. without the ',' at the end! <br>
	 * <br>
	 * <li> <b>set</b>, the command to set a parameter that can be set at any time<br>
	 * <br>
	 * <li> For the next two parameter the calculation is equal: if points are computed, the
		* calculation starts in the point a snake losses a segment or dies.
		* and gives all snakes that have at least one segment in the calculation radius its points.
		* it only counts the nearest segment of the snake, and the nearer the segment is, the more
		* points are given. The calculation is for both of the next identical:
		* The distance is defined as Manhatten distance: that meens d = dx + dy.
		* The fields near the center gains points of this amount: 2^(POINTS_..._RADIUS - d)
		* <br>
		* If a snake runns into an other snake, the other snake gets additionally the maximum
		* points. the maximum number is 2^(..._POINTS_RADIUS - 1). -1 because the center gets
		* 2^(..._POINTS_RADIUS)
		* <br>
	 *   
	 * <li> <b>set damage_points_radius</b>, the point radius if the head of a snake runns
	 	* 	into a wall or other snake. Default is 3; must be >= 1
	 	* <br> 
	 * <li> <b>set kill_points_radius</b>, the point radius if a snake is killed.
	 	* Default is 6; must be >= 0<br>
	 	* <br> 
	 * <li> <b>set easy_points</b>, if a snake bites it self, all snakes which touch
	 	* the snake at any point, gains easy_points number of points. Default is 0; must be >= 0<br>
	 	* <br>
	 * <li> As the bonus points the two parameters above, if snake runns into an other, the other
		* gains extra stuff. But this time, it gains Length. It is a floating point parameter
		* because it should be possible to gain for example 0.5 length each time a Snake runs
		* into an other snake. The value is stored and if its greater than 1 the snake gets the length. 
	 * <li> <b>set damage_length_grow</b>, the length a snake gets each time an other snake runs
	 	* into it. Default is 0.5; must be >= 0.0
	 	* <br>
	 * <li> <b>set kill_point_goodies</b>, If a nake dies, it imitats this number of point goodies.
		* each with goody_points_value points. kill_point_goodies is the number of point-goodies that
		* should be spreed out when a snake dies. Default is 5, must be >= 0
		* <br>
		* <br>
	 * <li> Because we have a discrete time in that game we need some tricks to reallize different
	 * speeds. so we decided to make it this way: each snake can think x times until the body mooves.
	 * the thinking times are constant, but the number of thinking times until the body moves can change. 
	 * <li> <b>set min_move_delay</b>, the minimum number of thinking cycles a snake can have.
	 	* Default is 2; must be >= 1
	 	* <br> 
	 * <li> <b>set init_move_delay</b>, the initial number of thinking cycles a snake can have.
	 	* Default is 4; it must be true: min_move_delay <= init_move_delay <= max_move_delay
	 	* <br>
	 * <li> <b>set max_move_delay</b>, the maximum number of thinking cycles a snake can have.
	 	* Default is 6; must be > INIT_SNAKE_DELAY
	 	* <br>
	 * <li> <b>set init_length</b>, the lenth the snake should start with Default is 10
	 	* <br>
	 	* <br>
	 * <li> <b>set auto_grow_delay</b>, each auto_grow_delay number gameTime cycles, a snake gains
		* one length. if the value is 1, the game is Tron-Style. Default is 20; must be >= 1
		* <br>
	 * <li> <b>set auto_slowdown_delay</b>, after auto_slowdown_delay number of gameTime cycles,
	 	* the snake will get one DELAY-point slower. Default is 1000; must be >= 1
		* <br>
		* <br>
	 * <li> <b>set max_goody_occ_delay</b>, the time until the next goody occures is uniform
	 	* distributed. after a randum number of cycles, the next goody occures on the fied.. Default
	 	* is 200; must be >= 1
	 	* <br>
	 * <li> To reallize different estimations of wich goodies occures, there is a second uniform
		 * distributed random value. The propability of that a goody is placed on the field, is
		 * GOODY_.._OCC / (sum of all GOODY_.._OCC)
		 * <br>
	 * <li> <b>set goody_speed_occ</b>, speed goodies. Default is 2; must be >= 0
	 	* <br>
	 * <li> <b>set goody_slowdown_occ</b>, speed goodies. Default is 1; must be >= 0
	 	* <br>
	 * <li> <b>set goody_length_occ</b>, length goodies. Default is 7; must be >= 0
	 	* <br>
	 * <li> <b>set goody_points_occ</b>, points goodies. Default is 0; must be >= 0
	 	* <br>
	 * <li> <b>set goody_shorter_occ</b>, shorter goodies. Default is 0; must be >= 0
	 	* <br>
	 	* <br>
	 * <li> <b>set goody_length_value</b>, The length a snake gets each time it eats a length-goody.
	 	* Default is 20; must be >= 0
	 	* <br>
	 * <li> <b>set goody_points_value</b>, The points a snake gets each time it eats a points-goody.
	 	* Default is 10; must be >= 0
	 	* <br>
	 * <li> <b>set goody_shorter_value</b>, The length a snake losses each time it eats a shorter-goody.
	 	* Default is 5; must be >= 0
		* <br>
	 * <li> <b>set min_cycle_ms</b>, this is ment for the game with human players. because if each player
		* runns as fast as it can, the game might be very fluctating in its speed.
		* To give the player at least the chacne to react iof the computer calculates very fast,
		* this value is set to a minimum of time in Milliseconds a game cycle will take<br>
		* note if there are many player in the field, the game will slow down because there are more
		* player that needs its time ti think. even if you like to run the game as fast as possible,
		* if the player need more time for their calculation, the game might be much slower than min_cycle_ms.
		* <br>
		* min_cycle_ms must be less than max_thinking_ms, if it is set to more than max_thinking_ms,
		* max_thinking_ms is set to min_cycle_ms.<br>
		* Default is 50, must be >= 1
		* <br>
	 * <li> <b>set max_thinking_ms</b>, sets the number of milli-seconds each player should think. this
		* number is indipendent from timeout_ms. it is the time in milliseconds each player should think maximum.
		* This is too the value (de.farafin.snEADy.player.GameInfo.thinkingMS),
		* the player is given for his calculation.
		* <br>
		* max_thinking_ms must be bigger than min_cycle_ms and less than timeout_ms. if max_thinking_ms
		* doesnt fit into this intervall, min_cycle_ms bzw timeout_ms is set to max_thinking_ms.
		* Default is 100, must be >= 1
		* <br>
	 * <li> <b>set timeout_ms</b>, timeout_ms is the deadline in milliseconds for the player.
	 	* if the player needs more time than timeout_ms, the player will be kicked.
	 	* if the value is 0, it will be waited until the player is done with calculation, no kick at all.
	 	* if timeout is not 0, it must be bigger than max_thinking_ms, if it is not, max_thinking_ms
	 	* is set to timeout_ms.
		* default is 100, must be >= 0
		* <br>
	 * <li> <b>set analyse_ms</b>, At the frist thinking phasis, this time is added to the normal
		* timeout_ms each player has. At the very first thinking phasis (gameTime == 0), the player
		* should be able to analyse the board. This time should be set large enough to
		* make this analyse possible. Default is 10000; must be >= 1.
		* <br>
		* <br>
	 * <li> <b>set max_player_mem</b>sets the maximum size (in kB) a loaded player is allowed to
		* allocate during the game. if the player takes too much, he will be kicked out of the game.
		* If max_player_mem is set to 0, there will be no check for the player memory.
		* Default is 8192 (= 8MB); must be >= 0
		* <br>
	 * <li> <b>set max_mem_check_delay</b>, The mem check is very time consuming, so its not done
		* every cycle. To avoid every bad Idea, the next check time is computed by a random number
		* with uniform distibution. This is the maximum number of Cycles between two checks.
		* Default is 100, must be >= 1
		* <br>
		* <br>
	 * <li> <b>set exit_time</b>, sets the number of the gameCycle in which the exit should open.
		* if its not set, it never occurs. Default is 5000, must be >= 0
		* <br>
	 * <li> <b>set suddend_time</b>, sets the number of the gameCycle in which the Sudden Death
		* should start. if its not set, it never happends. Default is 7000, must be >= 0
		* <br>
	 * <li> <b>set survival_points</b>, the bonus points a snake gets if it survives(reaches the exit).
		 * survival_points * the place the snake reaches the exit (the last snake gets most points).
		 * Default is 50, must be >= 0 <br>
		 * <br>
	 * <li> <b>set show_subcycles</b>, the graphic can be updated often or not so often.
		* 1: the game field is printed one time after every player thought one time
			* (its updated synchonized with the gameTime)
			* <br>
		* 0: the game field is printed each time after a player thought
			* <br>
		* Default is 0; must be 1 or 0
		* <br>
	 * <li> <b>set logging</b>, bool: should logFiles be written for this game? 1 = yes, 0 = no
	 	* Default is 1; must be 1 or 0
	 	* <br>
	 * <li> <b>set print_calc_ms</b>, if set to 1, the milliseconds each player needed for its moove
		* is printed, else its not printed. Remember, printing everythin into the console consumts
		* a lot of system power. read the player.log if you are interested in  a longer simulation.
		*  Default is 0; must be 1 or 0
		* <br>
	 * <li> <b>set print_player_mem</b>, if set to 1, each time the space of a player is calculated,
		* the result is printed, else its not printed. Default is 0; must be 1 or 0
		* <br>
	 * <li> <b>loadplayer player_name</b>, loads a new player with the specified name.
		* The name is the name of the class file of the player. (Linux/Solaris: watch big Letters here!)
		* <br>
	 * <li> <b>loadhuman player_name</b>, loads a new human and gives it the name.
		* <br>
	 * <li> <b>delplayer number</b>, delets the player with the given number.
		* its the index of the array that is given to gui.
		* <br>
	 * <li> <b>delplayer name</b>, deletes the first player with the given name.
	 	* <br> 
	 * <li> <b>loadlevel level_name</b>, loads the level with the specified name.
		* The name is the filename of the level. (Linux/Solaris: watch big Letters here!)
		* <br> 
	 * <li> <b>run</b>, starts the game if it is not running;
		* pauses game if its running and resums if it is pause (realization of the run button)
		* <br>
	 * <li> <b>start</b>, starts the game
	 	* <br>
	 * <li> <b>stop</b>, stops the game and returns to the initialization mode,
	 	* loads the same configuration as it was before the game was started.
	 	* <br> 
	 * <li> <b>pause</b>, if the game is running and it should be paused,
		* this function stops the current calculation process. but it is waited until the actual
		* player ends his thinking phases and updates the world one more time. After pause ended,
		* the next cycle starts with the calculation of the next player.
		* If you need an absolute pause at once, use imergancyPause.
		* <br>
	 * <li> <b>print</b>, printrs the actual play field into the console
	 	* <br>
	 * <li> <b>quit</b>, ends the program in a gently way, writs log fiels usw.
	 	* <br>
	 * <li> <b>kill</b>, kills the program. no log fiels are written.
	 	* WARNING: there are depricated methods used!!
	 	* <br>
	 * <li> <b>emergencyPause</b>, pauses the program imidiatly,
	 	* WARNING: there are depricated methods used!!
	 	* <br>
	 * <li> <b>openmonitor</b>, openes the debug monitor if it isn't still opended.
	 	* <br>
	 * <li> <b>closemonitor</b>, closes the debug monitor if it isn't still closed.
	 	* <br>
	 * 
	 * @param command the command that should performed
	 * @return if it was sucessfull computed
	 */	
	synchronized public boolean control(String command)
	{
		//String tmp = null;
		int number = 0;
		int i = 0;
		int j = 0;
		int k = 0;
		int counter = 0;
		String []commandArray;
		//String root = null, fileName = null;
		//String tmp;
		boolean bool = false;
		D_PlayerData[] pData;
		
		this.controlLog.storeLine(command);		
		
		if(this.gameInfo == null)
		{
			this.gameInfo = new D_GameInfo();
			this.gameInfo.exitTime = parameter.getExit_time();
			this.gameInfo.suddenDeath = parameter.getSuddend_time();
		}
		
		if(lockedControl)
		{
			this.controlLog.addToLastLine("-locked control-\tfalse");
			return false;
		}
		
		// TODO roland: make some eastereggs :P
		if(command == null)
		{
			System.out.println("WARNING: empty command string!!");

			this.controlLog.addToLastLine("-null command-\tfalse");
			return false;
		}
		//if(DEBUG) System.out.println("DEBUG M_Main.control: '" + command + "'");
		
		if(command.length() <= 1)
		{
			this.controlLog.addToLastLine(" ");
			return false;
		}
		
		System.out.println(command);
		
		/*
		// store commands for restart
		if(this.startWriter != null)
		{
			if(!command.startsWith("loadScript")
				&& !command.startsWith("restart")
				&& !command.startsWith("start")
				&& !command.startsWith("run"));	this.startWriter.storeLine(command);			
		}
		*/
		commandArray = command.split(" ");
		
		if(commandArray == null || commandArray.length < 1 || commandArray[0] == null || commandArray[0].length() <= 1)
		{
			System.out.println("WARNING: <Empty Command>");
			this.controlLog.addToLastLine("\tfalse");
			return false;
		}
		
		commandArray[0] = commandArray[0].toLowerCase();
		
		if(commandArray[0].equals("loadplayer"))
		{
		//	if(DEBUG) System.out.println("DEBUG M_Main.control: ###loadPlayer ");
			if(this.gameState != GAME_INIT)
			{
				System.out.println("WARNING: Game is not in initialization context, " +
						"end a possibly running game and try again.");
				if(DEBUG) System.out.println("DEBUG WARNING in M_Main.control: gameState:" + this.gameState);
				this.controlLog.addToLastLine("\tfalse");
				return false;
			}
			if(this.gameInfo.level != null && this.gameInfo.level.maxPlayer <= this.gameInfo.playerData.length)
			{
				System.out.println("WARNING: can not load an other Player. Maximal number of players (" + this.gameInfo.level.maxPlayer + ") was reached.");
				this.controlLog.addToLastLine("\tfalse");
				return false;	
			}
			if(this.gameInfo.playerData.length >= MAX_PLAYERS)
			{
				System.out.println("WARNING: can not load an other Player. Maximal number of players (" + MAX_PLAYERS + ") was reached.");
				this.controlLog.addToLastLine("\tfalse");
				return false;
			}
			if(commandArray.length <= 1)
			{
				System.out.println("WARNING: Please specify the player you whish to load.");
				this.controlLog.addToLastLine("\tfalse");
				return false;
			}
			Class newPlayerClass = this.loadPlayerClass(commandArray[1]);
			
			try
			{
				if(DEBUG) System.out.println("DEBUG M_Main.control: " +	((newPlayerClass.getField("comment")).get(null)));
			}
			catch(IllegalArgumentException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			catch(SecurityException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			catch(IllegalAccessException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			catch(NoSuchFieldException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			
			
			if(newPlayerClass == null)
			{
				System.out.println("WARNING: Player couldnt be loaded.");
				this.controlLog.addToLastLine("\tfalse");
				return false;
			}
			
			pData = this.gameInfo.playerData;
			
			// add the player
			this.gameInfo.playerData = new D_PlayerData[this.gameInfo.playerData.length + 1];
			for(i = 0; i < pData.length; i++)
			{
				this.gameInfo.playerData[i] = pData[i];
			}
			this.gameInfo.playerData[this.gameInfo.playerData.length-1] = new D_PlayerData(this.gameInfo.playerData.length-1, newPlayerClass, this.parameter);
			
			if(this.gameInfo.level != null)
			{
			
				if(this.gameInfo.playerData.length > this.gameInfo.level.maxPlayer)
				{
					System.out.println("WARNING: loading was successfull, but there are too many player loaded for this arena!\n"
							+ "\tmaxPlayer: " + this.gameInfo.level.maxPlayer + " actual player Number: " + this.gameInfo.playerData.length);
				}			
				else
				{
					bool = false;
					for(i=0;i<this.gameInfo.level.height&&!bool;i++)
					{
						for(j=0;j<this.gameInfo.level.width&&!bool;j++)
						{
							if(this.gameInfo.level.playField[i][j] == this.gameInfo.playerData[this.gameInfo.playerData.length-1].ownChar)
							{
								this.gameInfo.playerData[this.gameInfo.playerData.length-1].headPos.y = i; 
								this.gameInfo.playerData[this.gameInfo.playerData.length-1].headPos.x = j;
								bool = true;
							}
						}
					}
					bool = false;
				}
			}
			
			
			this.gui.update(this.gameInfo, null);

			this.controlLog.addToLastLine("\ttrue");
			return true;
		}
		else if(commandArray[0].equals("loadhuman"))
		{
		//	if(DEBUG) System.out.println("DEBUG M_Main.control: ###loadPlayer ");
			if(this.gameState != GAME_INIT)
			{
				System.out.println("WARNING: Game is not in initialization context, " +
						"end a possibly running game and try again.");
				if(DEBUG) System.out.println("DEBUG WARNING in M_Main.control: gameState:" + this.gameState);
				this.controlLog.addToLastLine("\tfalse");
				return false;
			}
			if(this.gameInfo.level != null && this.gameInfo.level.maxPlayer <= this.gameInfo.playerData.length)
			{
				System.out.println("WARNING: can not load an other Player. Maximal number of players (" + this.gameInfo.level.maxPlayer + ") was reached.");
				this.controlLog.addToLastLine("\tfalse");
				return false;	
			}
			if(this.gameInfo.playerData.length >= MAX_PLAYERS)
			{
				System.out.println("WARNING: can not load an other Player. Maximal number of players (" + MAX_PLAYERS + ") was reached.");
				this.controlLog.addToLastLine("\tfalse");
				return false;
			}
			counter = 0;
			for(i = 0; i< this.gameInfo.playerData.length; i++)
			{
				if(this.gameInfo.playerData[i].playerClass.getName().endsWith("C_Human")) counter ++;
			}
			if(counter >= MAX_HUMAN_PLAYERS)
			{
				System.out.println("WARNING: can not load an other human Player. Maximal number of players (" + MAX_HUMAN_PLAYERS + ") was reached.");
				this.controlLog.addToLastLine("\tfalse");
				return false;
			}

			Class newPlayerClass = C_Human.class;
			pData = this.gameInfo.playerData;
			
			// add the player
			this.gameInfo.playerData = new D_PlayerData[this.gameInfo.playerData.length + 1];
			for(i = 0; i < pData.length; i++)
			{
				this.gameInfo.playerData[i] = pData[i];
			}
			if(commandArray.length > 1)	this.gameInfo.playerData[this.gameInfo.playerData.length-1] = new D_PlayerData(this.gameInfo.playerData.length-1, newPlayerClass, commandArray[1], this.parameter);
			else this.gameInfo.playerData[this.gameInfo.playerData.length-1] = new D_PlayerData(this.gameInfo.playerData.length-1, newPlayerClass, "Nameless", this.parameter);
			
			if(this.gameInfo.level != null && this.gameInfo.playerData.length > this.gameInfo.level.maxPlayer)
			{
				System.out.println("WARNING: loading was successfull, but there are too many player loaded for this arena!\n"
						+ "\tmaxPlayer: " + this.gameInfo.level.maxPlayer + " actual player Number: " + this.gameInfo.playerData.length);
			}
			else
			{
				for(i=0; i<this.gameInfo.level.height; i++)
				{
					for(j=0; j<this.gameInfo.level.width; j++)
					{
						if(PLAYER_0 <= this.gameInfo.level.playField[i][j] && this.gameInfo.level.playField[i][j] <= PLAYER_9)
						{
							for(k=0; k<this.gameInfo.playerData.length; k++)
							{
								if(this.gameInfo.level.playField[i][j] == this.gameInfo.playerData[k].ownChar)
								{
									this.gameInfo.playerData[k].headPos.y = i;
									this.gameInfo.playerData[k].headPos.x = j;
								}
							}
						}
					}
				}
			}
			
			this.gui.update(this.gameInfo, null);

			this.controlLog.addToLastLine("\ttrue");
			return true;
		}
		else if(commandArray[0].equals("delplayer")) // TODO: add name delete
		{
		//	if(DEBUG) System.out.println("DEBUG M_Main.control: ###deletePlayer");
			if(this.gameState != GAME_INIT)
			{
				System.out.println("WARNING: Game is not in initialization context, " +
						"end a possibly running game and try again.");
				if(DEBUG) System.out.println("DEBUG WARNING in M_Main.control: gameState:" + this.gameState);
				this.controlLog.addToLastLine("\tfalse");
				return false;
			}
			if(this.gameInfo.playerData == null || this.gameInfo.playerData.length == 0)
			{
				System.out.println("WARNING: no player loaded that can be deleted!");
				this.controlLog.addToLastLine("\tfalse");
				return false;
			}
			if(commandArray.length <= 1)
			{
				System.out.println("WARNING: There was no Player specified that should be deleted." +
						"by default the last player will be deleted.");
				number = this.gameInfo.playerData.length-1;
			}
			else
			{
				if(!commandArray[1].matches("[0-9]"))
				{
					System.out.println("WARNING: the parameter '" + commandArray[1] + "' is no number between 0 and 9!");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				number = Integer.parseInt(commandArray[1]);
			}
			if(number >= this.gameInfo.playerData.length)
			{
				System.out.println("WARNING: Player with number '" + number + "' doesn't exists.");
				this.controlLog.addToLastLine("\tfalse");
				return false;
			}
			// set player Instance null
			this.gameInfo.playerData[number] = null;

			// make a new array with one less players
			pData = this.gameInfo.playerData;
			this.gameInfo.playerData = new D_PlayerData[pData.length - 1];
			i = 0;
			for(j = 0; j < this.gameInfo.playerData.length; j++)
			{
				if(j==number) i = 1;
				this.gameInfo.playerData[j] = pData[j+i];
				if(i == 1) this.gameInfo.playerData[j].ownChar--;
			}
			for(i=0; i<this.gameInfo.level.height; i++)
			{
				for(j=0; j<this.gameInfo.level.width; j++)
				{
					if(PLAYER_0 <= this.gameInfo.level.playField[i][j] && this.gameInfo.level.playField[i][j] <= PLAYER_9)
					{
						for(k=0; k<this.gameInfo.playerData.length; k++)
						{
							if(this.gameInfo.level.playField[i][j] == this.gameInfo.playerData[k].ownChar)
							{
								this.gameInfo.playerData[k].headPos.y = i;
								this.gameInfo.playerData[k].headPos.x = j;
							}
						}
					}
				}
			}
			
			this.gui.update(this.gameInfo, null);

			this.controlLog.addToLastLine("\ttrue");
			return true;
		}
		else if(commandArray[0].equals("loadlevel"))
		{
		//	if(DEBUG) System.out.println("DEBUG M_Main.control: ###loadLevel");
			if(this.gameState != GAME_INIT)
			{
				System.out.println("WARNING: Game is not in initialization context," +
						"end a possibly running game and try again.");
				if(DEBUG) System.out.println("DEBUG WARNING in M_Main.control: gameState:" + this.gameState);
				this.controlLog.addToLastLine("\tfalse");
				return false;
			}
			this.gameInfo.level = this.loadLevel(commandArray[1]);
			if(this.gameInfo.level == null)
			{
				this.controlLog.addToLastLine("\tfalse");
				return false;
			}
			
			if(this.gameInfo.level.comment.length() > 0) this.monitor.sneadySayIm(this.gameInfo.level.comment);
			if(this.gameInfo.level.autor.length() > 0) this.monitor.sneadySayIm("by " + this.gameInfo.level.autor);

			if(this.gameInfo.playerData.length > this.gameInfo.level.maxPlayer)
			{
				System.out.println("WARNING: loading of level was successfull, but there are too many players loaded for this level!\n"
						+ "\tmaxPlayer: " + this.gameInfo.level.maxPlayer + " actual player Number: " + this.gameInfo.playerData.length + "\n"
						+ "The last " + (this.gameInfo.playerData.length - this.gameInfo.level.maxPlayer) + " are skipped.");

				pData = this.gameInfo.playerData;
				this.gameInfo.playerData = new D_PlayerData[this.gameInfo.level.maxPlayer];
				
				for(i=0; i<this.gameInfo.level.maxPlayer; i++)
				{
					this.gameInfo.playerData[i] = pData[i];
				}
			}

			for(i=0; i<this.gameInfo.level.height; i++)
			{
				for(j=0; j<this.gameInfo.level.width; j++)
				{
					if(PLAYER_0 <= this.gameInfo.level.playField[i][j] && this.gameInfo.level.playField[i][j] <= PLAYER_9)
					{
						for(k=0; k<this.gameInfo.playerData.length; k++)
						{
							if(this.gameInfo.level.playField[i][j] == this.gameInfo.playerData[k].ownChar)
							{
								this.gameInfo.playerData[k].headPos.y = i;
								this.gameInfo.playerData[k].headPos.x = j;
							}
						}
					}
				}
			}
			
			
			this.gui.update(this.gameInfo, null);

			this.controlLog.addToLastLine("\ttrue");
			return true;
		}
		else if(commandArray[0].equals("start"))
		{
		//	if(DEBUG) System.out.println("DEBUG M_Main.control: ###start");
			if(this.gameState != GAME_INIT)
			{
				System.out.println("WARNING: Game is not in initialization context," +
						"end a possibly running game and try again.");
				if(DEBUG) System.out.println("DEBUG WARNING in M_Main.control: gameState:" + this.gameState);
				this.controlLog.addToLastLine("\tfalse");
				return false;
			}
			if(this.gameInfo.playerData.length <= 0)
			{
				System.out.println("WARNING: There are no players loaded!");
				this.controlLog.addToLastLine("\tfalse");
				return false;
			}
			if(this.gameInfo.level == null)
			{
				System.out.println("WARNING: There is no level loaded!");
				this.controlLog.addToLastLine("\tfalse");
				return false;
			}
			if(this.gameInfo.playerData.length > this.gameInfo.level.maxPlayer)
			{
				System.out.println("WARNING: There are too many players loaded.\n"
						+ "\t " + this.gameInfo.playerData.length + " loaded, max player for this level is " + this.gameInfo.level.maxPlayer + "\n"
						+ "\t the last " +  (this.gameInfo.level.maxPlayer-this.gameInfo.playerData.length) + " player won't be loaded." );
			}

			control("min_cycle_ms 1");
			// if a human player was loaded make a moderate game speed
			if(this.gameInfo.playerData != null)
			{
				for(i=0; i<this.gameInfo.playerData.length; i++)
				{
					if(this.gameInfo.playerData[i].playerClass.getName().endsWith("C_Human"))
					{
						control("set min_cycle_ms 50");
						break;
					}					
				}
			}
			
			this.initGameInfo = (D_GameInfo)this.gameInfo.clone();
			this.parameter.setExit_time(this.gameInfo.exitTime);
			this.parameter.setSuddend_time(this.gameInfo.suddenDeath);
			gui.setActive(false);
			this.lockedControl = true;
			// start the game
			this.startGame(this.gameInfo);
			// safes the start script for return to the same position after the game ended.
			//this.startWriter.safeAndCloseFile();
			//this.startWriter = null;
			
			// wait one second at the beginning of the game.
			synchronized(this)
			{
				try
				{
					wait(1000);
				}
				catch(InterruptedException e)
				{
					e.printStackTrace();
				}
			}
			this.lockedControl = false;
			
			// wait until the human starts the game with the run-button
			this.control("pause");
			gui.setActive(true);
			
			this.gui.update(this.gameInfo, null);

			this.controlLog.addToLastLine("\ttrue");
			return true;
		}
		else if(commandArray[0].equals("run"))
		{
		//	if(DEBUG) System.out.println("DEBUG M_Main.control: ###pause");
			if(this.gameState != GAME_RUNNING && this.gameState != GAME_PAUSE && this.gameState != GAME_INIT)
			{
				System.out.println("WARNING: Game is not in running, pause or initialization context");
				if(DEBUG) System.out.println("DEBUG WARNING in M_Main.control: gameState:" + this.gameState);
				this.controlLog.addToLastLine("\tfalse");
				return false;
			}
			
			if(this.gameState == GAME_RUNNING) gameState = GAME_PAUSE;
			else if(this.gameState == GAME_PAUSE) gameState = GAME_RUNNING;
			else if(this.gameState == GAME_INIT) control("start");

			this.gui.update(this.gameInfo, null);

			this.controlLog.addToLastLine("\ttrue");
			return true;
		}
		else if(commandArray[0].equals("pause"))
		{
		//	if(DEBUG) System.out.println("DEBUG M_Main.control: ###pause");
			if(this.gameState != GAME_RUNNING && this.gameState != GAME_PAUSE)
			{
				System.out.println("WARNING: Game is not in running or pause context");
				if(DEBUG) System.out.println("DEBUG WARNING in M_Main.control: gameState:" + this.gameState);
				this.controlLog.addToLastLine("\tfalse");
				return false;
			}
			
			if(this.gameState == GAME_RUNNING) gameState = GAME_PAUSE;
			else if(this.gameState == GAME_PAUSE) gameState = GAME_RUNNING;
			
			this.gui.update(this.gameInfo, null);

			this.controlLog.addToLastLine("\ttrue");
			return true;
		}
		else if(commandArray[0].equals("stop"))
		{
			if(this.gameState != GAME_RUNNING && this.gameState != GAME_PAUSE)
			{
				System.out.println("WARNING: you can't stop a game thats not running ;-)");
				this.controlLog.addToLastLine("\tfalse");
				return false;
			}
			
			gui.setActive(false);
			this.gameState = GAME_ABBORT;
			
			lockedControl = true;
			try
			{
				//wait(2000 + 2*GameParameter.THINKING_MS);
				this.gameEngine.join();
			}
			catch(InterruptedException e)
			{
				e.printStackTrace();
			}
			lockedControl = false;
			
			//this.gameInfo = (D_GameInfo)initGameInfo.clone();
			this.gameInfo.copyOnMe(initGameInfo);
			this.gameInfo.gameRunning = false;

			//while(!startReader.isFinished())
			//{
			//	tmp = startReader.readNextLine();
			//	if(!tmp.startsWith("restart")) control(tmp);
			//}

			gui.setActive(true);
			this.controlLog.addToLastLine("\ttrue");
			//return true;
			
			this.gui.update(this.gameInfo, null);

			this.controlLog.addToLastLine("\ttrue");
			return true;
		}
		else if(commandArray[0].equals("loadscript"))
		{
			if(commandArray.length <= 1)
			{
				System.out.println("WARNING: There was no script specified that should be loaded.");
				this.controlLog.addToLastLine("\tfalse");
				return false;
			}
			if(!this.loadScript("scripts", commandArray[1] + ".script"))
			{
				this.controlLog.addToLastLine("\tfalse");
				return false;	
			}
			this.gui.update(this.gameInfo, null);

			this.controlLog.addToLastLine("\ttrue");
			return true;
		}		
		else if(commandArray[0].equals("quit"))
		{
		//	if(DEBUG) System.out.println("DEBUG M_Main.control: ###quit");
			if(this.gameState == GAME_RUNNING || this.gameState == GAME_PAUSE)
			{
				if(DEBUG) System.out.println("DEBUG M_Main.control: PROG_END");
				this.gameState = PROG_END;
			}
			else
			{
				this.quit(0);
			}
			this.gui.update(this.gameInfo, null);

			this.controlLog.addToLastLine("\ttrue");
			return true;
		}
		else if(commandArray[0].equals("kill"))
		{
			System.out.println("KILL WAS PERFORMED! DEPRECATED METHODS USED TO END THE GAME!\n" +
					"\tPlease only use if 'quit' doesn't work!");
			this.kill();

			this.controlLog.addToLastLine("\ttrue");
			return true;
		}			
		else if(commandArray[0].equals("imergencyPause"))
		{
			System.out.println("IMERGENCY_PAUSE WAS PERFORMED! DEPRECATED METHODS USED TO HOLD THE GAME!\n" +
			"\tPlease only use if 'run' or 'pause' doesn't work!");
			this.imergencyPause();
			
			this.gui.update(this.gameInfo, null);

			this.controlLog.addToLastLine("\ttrue");
			return true;
		}
		else if(commandArray[0].equals("save"))
		{
			System.out.println("WARNING: command '" + commandArray[0] + "' not implemented jet!");		
		//	System.out.println("DEBUG M_Main.control: ###save"); 

			this.controlLog.addToLastLine("\ttrue");
			return true;
		}
		else if(commandArray[0].equals("restore"))
		{
			System.out.println("WARNING: command '" + commandArray[0] + "' not implemented jet!");
		//	System.out.println("DEBUG M_Main.control: ###restore");
			this.controlLog.addToLastLine("\ttrue");
			return true;
		}
		
		else if(commandArray[0].equals("print_playfield"))
		{
			if(this.gameInfo.level != null) monitor.sneadySayIm(this.gameInfo.level.toString());
			
			this.controlLog.addToLastLine("\ttrue");
			return true;
		}
		else if(commandArray[0].equals("print_parameter"))
		{
			monitor.sneadySayIm(parameter.toString());
			this.controlLog.addToLastLine("\ttrue");
			return true;
		}
		else if(commandArray[0].equals("openmonitor"))
		{
			this.monitor.setVisible(true);
			this.gui.update(this.gameInfo, null);

			this.controlLog.addToLastLine("\ttrue");
			return true;
		}
		else if(commandArray[0].equals("closemonitor"))
		{
			this.monitor.setVisible(false);
			this.gui.update(this.gameInfo, null);

			this.controlLog.addToLastLine("\ttrue");
			return true;
		}		
		else if(commandArray[0].equals("set"))
		{
			if(commandArray.length <= 2)
			{
				System.out.println("WARNING: There are too less Parameter for this command! You need to specify the variable and its value.");
				this.controlLog.addToLastLine("\tfalse");
				return false;
			}
			
			commandArray[1] = commandArray[1].toLowerCase();
			
			if(commandArray[1].equals("damage_points_radius"))
			{
				if(!commandArray[2].matches("[0-9]*"))
				{
					System.out.println("WARNING: the parameter '" + commandArray[2] + "' is no number!");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				parameter.setDamage_points_radius(Integer.parseInt(commandArray[2]));

				this.gui.update(this.gameInfo, null);

				this.controlLog.addToLastLine("\ttrue");
				return true;
			}
			else if(commandArray[1].equals("kill_points_radius"))
			{
				if(!commandArray[2].matches("[0-9]*"))
				{
					System.out.println("WARNING: the parameter '" + commandArray[2] + "' is no number!");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				parameter.setKill_points_radius(Integer.parseInt(commandArray[2]));

				this.gui.update(this.gameInfo, null);

				this.controlLog.addToLastLine("\ttrue");
				return true;
			}
			else if(commandArray[1].equals("easy_points"))
			{
				if(!commandArray[2].matches("[0-9]*"))
				{
					System.out.println("WARNING: the parameter '" + commandArray[2] + "' is no number!");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				parameter.setEasy_points(Integer.parseInt(commandArray[2]));

				this.gui.update(this.gameInfo, null);

				this.controlLog.addToLastLine("\ttrue");
				return true;
			}
			else if(commandArray[1].equals("damage_length_grow"))
			{
				if(!commandArray[2].matches("[0-9]*[.][0-9]*"))
				{
					System.out.println("WARNING: the parameter '" + commandArray[2] + "' is no float-number!");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				parameter.setDamage_length_grow(Float.parseFloat(commandArray[2]));

				this.gui.update(this.gameInfo, null);

				this.controlLog.addToLastLine("\ttrue");
				return true;
			}
			else if(commandArray[1].equals("kill_point_goodies"))
			{
				if(!commandArray[2].matches("[0-9]*"))
				{
					System.out.println("WARNING: the parameter '" + commandArray[2] + "' is no number!");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				parameter.setKill_point_goodies(Integer.parseInt(commandArray[2]));

				this.gui.update(this.gameInfo, null);

				this.controlLog.addToLastLine("\ttrue");
				return true;
			}
			else if(commandArray[1].equals("min_move_delay"))
			{
				if(!commandArray[2].matches("[0-9]*"))
				{
					System.out.println("WARNING: the parameter '" + commandArray[2] + "' is no number!");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				number = Integer.parseInt(commandArray[2]);
				if(number < 1)
				{
					System.out.println("WARNING: min_move_delay must be >= 1");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				parameter.setMin_move_delay(number);

				this.gui.update(this.gameInfo, null);

				this.controlLog.addToLastLine("\ttrue");
				return true;
			}
			else if(commandArray[1].equals("init_move_delay"))
			{
				if(!commandArray[2].matches("[0-9]*"))
				{
					System.out.println("WARNING: the parameter '" + commandArray[2] + "' is no number!");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				number = Integer.parseInt(commandArray[2]);
				if(number < parameter.getMin_move_delay() || parameter.getMax_move_delay() < number)
				{
					System.out.println("WARNING: init_move_delay of '" + number + "' does not fit between " + parameter.getMin_move_delay() + " and " + parameter.getMax_move_delay() + ".");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				
				parameter.setInit_move_delay(number);
				
				if(this.gameInfo.playerData != null)
				{
					for(i = 0; i<this.gameInfo.playerData.length;i++)
					{
						this.gameInfo.playerData[i].waitCycles = parameter.getInit_move_delay();
					}
				}
				
				if(this.gameInfo.level != null) this.gui.update(this.gameInfo, null);


				this.gui.update(this.gameInfo, null);

				this.controlLog.addToLastLine("\ttrue");
				return true;
			}
			else if(commandArray[1].equals("max_move_delay"))
			{
				if(!commandArray[2].matches("[0-9]*"))
				{
					System.out.println("WARNING: the parameter '" + commandArray[2] + "' is no number!");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				number = Integer.parseInt(commandArray[2]);
				if(number <= parameter.getMin_move_delay())
				{
					System.out.println("WARNING: MAX_SNAKE_DELAY must be > min_move_delay of " + parameter.getMin_move_delay());
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				parameter.setMax_move_delay(number);

				this.gui.update(this.gameInfo, null);

				this.controlLog.addToLastLine("\ttrue");
				return true;
			}
			else if(commandArray[1].equals("init_length"))
			{
				if(!commandArray[2].matches("[0-9]*"))
				{
					System.out.println("WARNING: the parameter '" + commandArray[2] + "' is no number!");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				number = Integer.parseInt(commandArray[2]);
				if(number < 2)
				{
					System.out.println("WARNING: the init length of a snake must be init_length >= 2.");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				parameter.setInit_length(number);

				this.gui.update(this.gameInfo, null);

				this.controlLog.addToLastLine("\ttrue");
				return true;
			}
			else if(commandArray[1].equals("auto_grow_delay"))
			{
				if(!commandArray[2].matches("[0-9]*"))
				{
					System.out.println("WARNING: the parameter '" + commandArray[2] + "' is no number!");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				number = Integer.parseInt(commandArray[2]);
				if(number < 1)
				{
					System.out.println("WARNING: AUTO_GROW must be >= 1");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				parameter.setAuto_grow_delay(number);

				this.gui.update(this.gameInfo, null);

				this.controlLog.addToLastLine("\ttrue");
				return true;
			}
			else if(commandArray[1].equals("auto_slowdown_delay"))
			{
				if(!commandArray[2].matches("[0-9]*"))
				{
					System.out.println("WARNING: the parameter '" + commandArray[2] + "' is no number!");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				number = Integer.parseInt(commandArray[2]);
				if(number < 0)
				{
					System.out.println("WARNING: auto_slowdown_delay must be >= 0");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				parameter.setAuto_slowdown_delay(number);

				this.gui.update(this.gameInfo, null);

				this.controlLog.addToLastLine("\ttrue");
				return true;
			}
			else if(commandArray[1].equals("max_goody_occ_delay"))
			{
				if(!commandArray[2].matches("[0-9]*"))
				{
					System.out.println("WARNING: the parameter '" + commandArray[2] + "' is no number!");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				number = Integer.parseInt(commandArray[2]);
				if(number < 1)
				{
					System.out.println("WARNING: max_goody_occ_delay must be >= 1");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				parameter.setMax_goody_occ_delay(number);

				this.gui.update(this.gameInfo, null);

				this.controlLog.addToLastLine("\ttrue");
				return true;
			}	
			else if(commandArray[1].equals("goody_speed_occ"))
			{
				if(!commandArray[2].matches("[0-9]*"))
				{
					System.out.println("WARNING: the parameter '" + commandArray[2] + "' is no number!");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				number = Integer.parseInt(commandArray[2]);
				if(number < 0)
				{
					System.out.println("WARNING: goody_speed_occ must be >= 0");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				parameter.setGoody_speed_occ(number);

				this.gui.update(this.gameInfo, null);

				this.controlLog.addToLastLine("\ttrue");
				return true;
			}
			else if(commandArray[1].equals("goody_slowdown_occ"))
			{
				if(!commandArray[2].matches("[0-9]*"))
				{
					System.out.println("WARNING: the parameter '" + commandArray[2] + "' is no number!");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				number = Integer.parseInt(commandArray[2]);
				if(number < 0)
				{
					System.out.println("WARNING: goody_slowdown_occ must be >= 0");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				parameter.setGoody_slowdown_occ(number);

				this.gui.update(this.gameInfo, null);

				this.controlLog.addToLastLine("\ttrue");
				return true;
			}
			else if(commandArray[1].equals("goody_length_occ"))
			{
				if(!commandArray[2].matches("[0-9]*"))
				{
					System.out.println("WARNING: the parameter '" + commandArray[2] + "' is no number!");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				number = Integer.parseInt(commandArray[2]);
				if(number < 0)
				{
					System.out.println("WARNING: goody_length_occ must be >= 0");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				parameter.setGoody_length_occ(number);

				this.gui.update(this.gameInfo, null);

				this.controlLog.addToLastLine("\ttrue");
				return true;
			}
			else if(commandArray[1].equals("goody_points_occ"))
			{
				if(!commandArray[2].matches("[0-9]*"))
				{
					System.out.println("WARNING: the parameter '" + commandArray[2] + "' is no number!");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				number = Integer.parseInt(commandArray[2]);
				if(number < 0)
				{
					System.out.println("WARNING: goody_points_occ must be >= 0");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				parameter.setGoody_points_occ(number);

				this.gui.update(this.gameInfo, null);

				this.controlLog.addToLastLine("\ttrue");
				return true;
			}
			else if(commandArray[1].equals("goody_shorter_occ"))
			{
				if(!commandArray[2].matches("[0-9]*"))
				{
					System.out.println("WARNING: the parameter '" + commandArray[2] + "' is no number!");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				number = Integer.parseInt(commandArray[2]);
				if(number < 0)
				{
					System.out.println("WARNING: goody_shorter_occ must be >= 0");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				parameter.setGoody_shorter_occ(number);

				this.gui.update(this.gameInfo, null);

				this.controlLog.addToLastLine("\ttrue");
				return true;
			}
			else if(commandArray[1].equals("goody_length_value"))
			{
				if(!commandArray[2].matches("[0-9]*"))
				{
					System.out.println("WARNING: the parameter '" + commandArray[2] + "' is no number!");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				number = Integer.parseInt(commandArray[2]);
				if(number < 0)
				{
					System.out.println("WARNING: goody_length_value must be >= 0");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				parameter.setGoody_length_value(number);

				this.gui.update(this.gameInfo, null);

				this.controlLog.addToLastLine("\ttrue");
				return true;
			}
			else if(commandArray[1].equals("goody_points_value"))
			{
				if(!commandArray[2].matches("[0-9]*"))
				{
					System.out.println("WARNING: the parameter '" + commandArray[2] + "' is no number!");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				number = Integer.parseInt(commandArray[2]);
				if(number < 0)
				{
					System.out.println("WARNING: goody_points_value must be >= 0");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				parameter.setGoody_points_value(number);

				this.gui.update(this.gameInfo, null);

				this.controlLog.addToLastLine("\ttrue");
				return true;
			}
			else if(commandArray[1].equals("goody_shorter_value"))
			{
				if(!commandArray[2].matches("[0-9]*"))
				{
					System.out.println("WARNING: the parameter '" + commandArray[2] + "' is no number!");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				number = Integer.parseInt(commandArray[2]);
				if(number < 0)
				{
					System.out.println("WARNING: goody_shorter_value must be >= 0");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				parameter.setGoody_shorter_value(number);

				this.gui.update(this.gameInfo, null);

				this.controlLog.addToLastLine("\ttrue");
				return true;
			}
			else if(commandArray[1].equals("min_cycle_ms")) //TODO: watch playerhandler
			{
			//	if(DEBUG) System.out.println("DEBUG M_Main.control: ###thinkingMS");
				if(!commandArray[2].matches("[0-9]*"))
				{
					System.out.println("WARNING: the parameter '" + commandArray[2] + "' is no number!");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				number = Integer.parseInt(commandArray[2]);
				if(number < 1)
				{
					System.out.println("WARNING: min_cycle_ms must be >= 1");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				parameter.setMin_cycle_ms(number);
				if(this.parameter.getMax_thinking_ms() < number)
				{
					this.control("set max_thinking_ms " + number);
				}

				this.gui.update(this.gameInfo, null);

				this.controlLog.addToLastLine("\ttrue");
				return true;
			}
			else if(commandArray[1].equals("max_thinking_ms")) //TODO: watch playerhandler
			{
			//	if(DEBUG) System.out.println("DEBUG M_Main.control: ###thinkingMS");
				if(!commandArray[2].matches("[0-9]*"))
				{
					System.out.println("WARNING: the parameter '" + commandArray[2] + "' is no number!");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				number = Integer.parseInt(commandArray[2]);
				if(number < 1)
				{
					System.out.println("WARNING: max_thinking_ms must be >= 1");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				parameter.setMax_thinking_ms(number);
				if(this.parameter.getMin_cycle_ms() > number)
				{
					this.control("set min_cycle_ms " + number);
				}
				if(this.parameter.getTimeout_ms() > 0 && number > this.parameter.getTimeout_ms())
				{
					this.control("set timeout_ms " + number);
				}

				this.gui.update(this.gameInfo, null);

				this.controlLog.addToLastLine("\ttrue");
				return true;
			}
			else if(commandArray[1].equals("analyse_ms"))
			{
				//	if(DEBUG) System.out.println("DEBUG M_Main.control: ###thinkingMS");
				if(!commandArray[2].matches("[0-9]*"))
				{
					System.out.println("WARNING: the parameter '" + commandArray[2] + "' is no number!");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				number = Integer.parseInt(commandArray[2]);
				if(number < 1)
				{
					System.out.println("WARNING: analyse_ms must be >= 1");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				parameter.setAnalyse_ms(number);

				this.gui.update(this.gameInfo, null);

				this.controlLog.addToLastLine("\ttrue");
				return true;
			}
			else if(commandArray[1].equals("timeout_ms")) //TODO: if its 0 no check, else watch player hanldler
			{
				if(!commandArray[2].matches("[0-9]*"))
				{
					System.out.println("WARNING: the parameter '" + commandArray[2] + "' is no number!");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				number = Integer.parseInt(commandArray[2]);
				if(number < 0)
				{
					System.out.println("WARNING: timeout must be >= 0");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				parameter.setTimeout_ms(number);
				
				if(number > 0 && number < this.parameter.getMax_thinking_ms())
				{
					this.control("set max_thinking_ms " + number);
				}

				this.gui.update(this.gameInfo, null);

				this.controlLog.addToLastLine("\ttrue");
				return true;
			}
			else if(commandArray[1].equals("max_player_mem")) //TODO: if its 0 : no check
			{
				if(!commandArray[2].matches("[0-9]*"))
				{
					System.out.println("WARNING: the parameter '" + commandArray[2] + "' is no number!");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				parameter.setMax_player_mem((Integer.parseInt(commandArray[2])));

				this.gui.update(this.gameInfo, null);

				this.controlLog.addToLastLine("\ttrue");
				return true;
			}
			else if(commandArray[1].equals("max_mem_check_delay"))
			{
				if(!commandArray[2].matches("[0-9]*"))
				{
					System.out.println("WARNING: the parameter '" + commandArray[2] + "' is no number!");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				number = Integer.parseInt(commandArray[2]);
				if(number < 0)
				{
					System.out.println("WARNING: max_mem_check_delay must be >= 1");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				parameter.setMax_mem_check_delay(number);

				this.gui.update(this.gameInfo, null);

				this.controlLog.addToLastLine("\ttrue");
				return true;
			}
			else if(commandArray[1].equals("exit_time"))
			{
			//	if(DEBUG) System.out.println("DEBUG M_Main.control: ###exitTime");
				if(!commandArray[2].matches("[0-9]*"))
				{
					System.out.println("WARNING: the parameter '" + commandArray[2] + "' is no number!");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				parameter.setExit_time(Integer.parseInt(commandArray[2]));
				this.gameInfo.exitTime = parameter.getExit_time();

				this.gui.update(this.gameInfo, null);

				this.controlLog.addToLastLine("\ttrue");
				return true;
			}
			else if(commandArray[1].equals("suddend_time"))
			{
			//	if(DEBUG) System.out.println("DEBUG M_Main.control: ###sDTime");
				if(!commandArray[2].matches("[0-9]*"))
				{
					System.out.println("WARNING: the parameter '" + commandArray[2] + "' is no number!");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				parameter.setSuddend_time(Integer.parseInt(commandArray[2]));
				this.gameInfo.suddenDeath = parameter.getSuddend_time();

				this.gui.update(this.gameInfo, null);

				this.controlLog.addToLastLine("\ttrue");
				return true;
			}
			else if(commandArray[1].equals("survival_points"))
			{
			//	if(DEBUG) System.out.println("DEBUG M_Main.control: ###sDTime");
				if(!commandArray[2].matches("[0-9]*"))
				{
					System.out.println("WARNING: the parameter '" + commandArray[2] + "' is no number!");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				parameter.setSurvival_points(Integer.parseInt(commandArray[2]));

				this.gui.update(this.gameInfo, null);

				this.controlLog.addToLastLine("\ttrue");
				return true;
			}
			else if(commandArray[1].equals("show_subcycles"))
			{
				if(!commandArray[2].matches("[01]") || commandArray[2].length() > 1)
				{
					System.out.println("WARNING: the parameter '" + commandArray[2] + "' is no boolean number!");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				number = Integer.parseInt(commandArray[2]);
				if(number != 0 && number != 1)
				{
					System.out.println("WARNING: show_subcycles must be 0 or 1");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				parameter.setShow_subcycles(number);

				this.gui.update(this.gameInfo, null);

				this.controlLog.addToLastLine("\ttrue");
				return true;
			}
			else if(commandArray[1].equals("logging"))
			{
				if(!commandArray[2].matches("[01]") || commandArray[2].length() > 1)
				{
					System.out.println("WARNING: the parameter '" + commandArray[2] + "' is no boolean number!");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				number = Integer.parseInt(commandArray[2]);
				if(number != 0 && number != 1)
				{
					System.out.println("WARNING: logging must be 0 or 1");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				parameter.setLogging(number);

				this.gui.update(this.gameInfo, null);

				this.controlLog.addToLastLine("\ttrue");
				return true;
			}
			else if(commandArray[1].equals("print_calc_ms"))
			{
				if(!commandArray[2].matches("[01]") || commandArray[2].length() > 1)
				{
					System.out.println("WARNING: the parameter '" + commandArray[2] + "' is no boolean number!");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				number = Integer.parseInt(commandArray[2]);
				if(number != 0 && number != 1)
				{
					System.out.println("WARNING: print_calc_ms must be 0 or 1");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				parameter.setPrint_calc_ms(number);

				this.gui.update(this.gameInfo, null);

				this.controlLog.addToLastLine("\ttrue");
				return true;
			}
			else if(commandArray[1].equals("print_player_mem"))
			{
				if(!commandArray[2].matches("[01]") || commandArray[2].length() > 1)
				{
					System.out.println("WARNING: the parameter '" + commandArray[2] + "' is no boolean number!");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				number = Integer.parseInt(commandArray[2]);
				if(number != 0 && number != 1)
				{
					System.out.println("WARNING: print_player_mem must be 0 or 1");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				parameter.setPrint_player_mem(number);

				this.gui.update(this.gameInfo, null);

				this.controlLog.addToLastLine("\ttrue");
				return true;
			}
			else if(commandArray[1].equals("no_thread_calc"))
			{
				if(!commandArray[2].matches("[01]") || commandArray[2].length() > 1)
				{
					System.out.println("WARNING: the parameter '" + commandArray[2] + "' is no boolean number!");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				number = Integer.parseInt(commandArray[2]);
				if(number != 0 && number != 1)
				{
					System.out.println("WARNING: print_player_mem must be 0 or 1");
					this.controlLog.addToLastLine("\tfalse");
					return false;
				}
				parameter.setNo_thread_calc(number);

				this.gui.update(this.gameInfo, null);

				this.controlLog.addToLastLine("\ttrue");
				return true;
			}
			else
			{
				if(DEBUG) System.out.println("DEBUG M_Main.control: ###else");
				System.out.println("WARNING in M_Main.controlInterface: Unknown parameter '" + commandArray[1] + "' !!");
				this.controlLog.addToLastLine("\tfalse");
				return false;
			}
		}
		else
		{
			if(DEBUG) System.out.println("DEBUG M_Main.control: ###else");
			System.out.println("WARNING in M_Main.controlInterface: Unknown command '" + commandArray[0] + "' !!");
			this.controlLog.storeLine("false");
			return false;
		}
	}
	
	/** ends the program
	 * @param x the parameter of exit
	 * */
	private void quit(int x)
	{
		this.controlLog.storeLine("end Game");
		if(parameter.getLogging() == 1) this.controlLog.safeAndCloseFile();
		if(DEBUG) System.out.println("DEBUG M_Main.quit: ### end Program ###");
		System.exit(x);
	}
}

/* TODO road map:
 * =========================Für das Spiel======================================
 * roland:
 *  -	schlangen von menschen ziehen im ersten zug gearde aus...
 *  -	security tests.. allgemeines bettatesting des level loaders
 *  -	level design test
 *  -	logging of complete games.. must be more effitient than normal logs of players or commands..
 *  -	log für init game
 *  -	verringere Anzahl konstanten
 * 
 * fixed
 *  -	game stoppt wenn alle schlangen weg sind
 *  -	speicher von neuen spielern wird kopntrolleirt fixed
 *  -	im playerInfo sind jetzt thinkingMS und analyseMS drin.
 *  -	restart vernünftig implementiert.. nicht mehr die krücke von bisher.
 * 
 * lars:
 *  -	debugging
 *  -	Implementiere "load Level" - Dialog
 *  -	Implementierung "Obtions" - Dialog um Konstanten festlegen zu können.
 *  -	Implementiere "load Player" - Dialog
 * 
 * =====================Webseite+Doku und drum rum=============================
 * roland:
 *  -	Standardparametersatz für ein Spiel mit Menschlichen Spielern
 *  -	Standardparametersatz für den Wettbewerb
 *  -	schreiben der Installationshinweise
 *  -	schreiben von HowTo's:
 * 		-	level design
 * 		-	scripting
 * 		-	was bedeuten die logs, lesen der logs?
 *	 	-	spieler programmieren
 *  -	finale Festlegung der Standardparameter
 *  -	finale Festlegung der Spielmodie
 * 		-	Tron
 * 		-	Fast
 * 		-	Normal
 * 		-	Team
 *  -	entferne Rechtschreibfehler
 *  -	schreibe finale Doku
 * 
 * lars:
 *  -	doku schreiben
 *  -	präsi schreiben
 *  -	designe WebSeite für GameParameter
 *  
 * ============================================================================
 * BUILD FINAL VERSION
 * roland: parameter in I_Constants/sneady und I_PlayerConstants anpassen und abgleichen
 *  -	finde Möglichkeit den thread für die spieler zu vereinfachen, so dass nicht jedes mal
 * 		ein neuer erzeugt werden muss.
 * 
 * 
 * Fixed since v0.9
 * 	- spiel wird auf einmal langsamer
 * 	- logausgabe verbessert
 * 	- optionsmenü (noch nicht ganz vollständig)
 * 	- level hat comment als tag
 *  - level hat autor als tag
 *  - die blöden Doppelpunkte im level sind weg (stört auch nicht wenn sie da sind)
 *  - regeländerung für die Punkteberechnung! Wenn eine schlange sich selber beißt, dann bekommen alle schlangen die sie berüren einen punkt.
 *  - schlangen geben jetzt punkte wenn sie eingeringelt sind.
 * 
 */