/*
 * c't-Bot
 * 
 * This program 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. 
 * This program 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.
 * You should have received a copy of the GNU General Public 
 * License along with this program; if not, write to the Free 
 * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307, USA.
 * 
 */

/*! @file 	behaviour_solve_maze.c
 * @brief 	Wandfolger durchs Labyrinth
 * 
 * @author 	Benjamin Benz (bbe@heise.de)
 * @date 	03.11.06
*/

#include "bot-logic/bot-logik.h"
#include <math.h>
#include <stdlib.h>
#include "log.h"

#ifdef BEHAVIOUR_SOLVE_MAZE_AVAILABLE

/* Parameter fuer das check_wall_behaviour() */
int8 wall_detected;				/*!< enthaelt True oder False, je nach Ergebnis des Verhaltens */
int8 check_direction;			/*!< enthaelt CHECK_WALL_LEFT oder CHECK_WALL_RIGHT */
int16 wall_distance;			/*!< enthaelt gemessene Entfernung */

/* Konstanten fuer check_wall_behaviour-Verhalten */
#define CHECK_WALL_RIGHT			0
#define CHECK_WALL_LEFT				1

/* Parameter fuer das measure_angle_behaviour() */
int8 measure_direction;			/*!< enthaelt MEASURE_RIGHT oder MEASURE_LEFT */
int16 measure_distance;			/*!< enthaelt maximale Messentfernung, enthaelt nach der Messung die Entfernung */
int16 measured_angle;			/*!< enthaelt gedrehten Winkel oder 0, falls nichts entdeckt */
#ifdef MEASURE_MOUSE_AVAILABLE
	int16 start_heading;		/*!< Blickwinkel des Bots zu Beginn der Messung */
#else
	int16 startEncL;				/*!< enthaelt Encoderstand zu Beginn der Messung */
	int16 startEncR;				/*!< enthaelt Encoderstand zu Beginn der Messung */
#endif
/* Konstanten fuer measure_angle_behaviour-Verhalten */
#define MEASURE_LEFT				1
#define MEASURE_RIGHT				-1


/*!
 * Das Verhalten dreht sich um 45 Grad in die angegebene Richtung (0=rechts, 1=links)
 * und prueft, ob auf dem Sensor auf der Seite der angegebenen Richtung eine Wand
 * im Abstand von 12cm zu sehen ist. Wenn dem so ist, wird die Variable wall_present
 * auf True gesetzt, sonst False */
void bot_check_wall_behaviour(Behaviour_t *data) {
	/* Konstantenfuer check_wall_behaviour-Verhalten */
	#define CORRECT_NEAR				0
	#define CORRECT_NONE				1
	#define CORRECT_FAR					2
	/* Zustaende fuer check_wall_behaviour-Verhalten */
	#define CHECK_WALL_TURN				0
	#define CHECK_WALL_SENS				1
	#define CHECK_WALL_TURN_BACK		2
	#define CHECK_WALL_FINISHED			3
	#define CHECK_WALL_CORRECT			4
	
	static int8 checkState=CHECK_WALL_TURN;
	/* wenn die Wand noch da ist aber aus dem Blickfeld rueckt, Entfernung und Winkel korrigieren */
	static int8 correctDistance=CORRECT_NONE;	
	/* letzte, gueltige Distanz fuer Abweichungsberechnung */
	static int16 lastDistance=0;
	/* enthaelt anzahl der +/-5 identischen Messungen */
	static int8 measureCount=0;
	/* letzter Messwert */
	static int16 lastSensor=0;
	
	int16 sensor;	/* fuer temporaer benutzte Senorwerte */

	switch(checkState) {
		case CHECK_WALL_TURN:
			/* haben wir links oder rechts eine Wand? */
			if (check_direction==CHECK_WALL_LEFT) {
				checkState=CHECK_WALL_SENS;
				bot_turn(data,45);
				break;	
			} else {
				checkState=CHECK_WALL_SENS;
				bot_turn(data,-45);
				break;
			}
			
		case CHECK_WALL_SENS:
			if (check_direction==CHECK_WALL_LEFT) {
				sensor=sensDistL;
			} else {
				sensor=sensDistR;
			}
			/* dafuer sorgen, dass wir nur verlaessliche Werte haben
			 * dazu muss der wert dreimal nacheinander max. um +/- 5
			 * unterschiedlich sein */
			 if (measureCount==0) {
			 	lastSensor=sensor;
			 	measureCount++;
			 	break;
			 }
			 if (sensor>=lastSensor-5 && sensor<=lastSensor+5 && measureCount<4) {
			 	/* Messwert ist ok */
			 	measureCount++;
			 	break;
			 } else  if (measureCount<4) {
			 	/* Messwert weicht zu doll ab -> von Neuem messen */
			 	measureCount=0;
			 	break;
			 }
			 /* ok, wir hatten drei Messungen mit nahezu identischen Werten */
			
			/* keine wand in eingestellter Maximalentfernung? */
			if (sensor>IGNORE_DISTANCE) {
				correctDistance=CORRECT_NONE; /* dann auch keine Korrektur */
				lastDistance=0;				  /* auch kein Vergleichswert */
				wall_detected=False;		  /* keine Wand da */
			} else if (sensor<OPTIMAL_DISTANCE-ADJUST_DISTANCE) {
				/* bot hat den falschen Abstand zur Wand, zu nah dran */
				wall_detected=True;
				correctDistance=CORRECT_NEAR;
			} else if (sensor>OPTIMAL_DISTANCE+ADJUST_DISTANCE) {
				/* bot hat den falschen Abstand zur Wand, zu weit weg */
				wall_detected=True;
				correctDistance=CORRECT_FAR;
			} else {
				/* perfekter Abstand */
				correctDistance=CORRECT_NONE;
				wall_detected=True;
			}
			wall_distance=sensor;
			/* Wenn Korrektur noetig, dann durchfuehren, sonst gleich zurueckdrehen */
			if (correctDistance==CORRECT_NONE) checkState=CHECK_WALL_TURN_BACK;
			else checkState=CHECK_WALL_CORRECT;
			break;

			
		case CHECK_WALL_TURN_BACK:
			checkState=CHECK_WALL_FINISHED;
			int16 turnAngle=45;
			
			/* welcher Sensorwert wird gebraucht? */
			if (check_direction==CHECK_WALL_LEFT) {
				sensor=sensDistL;
			} else {
				sensor=sensDistR;
			}
			/* wenn vorhanden, aus letztem Abstand und aktuellem Abstand
			 * Korrekturwinkel berechnen, falls vorheriger Abstand da.
			 * wird durch Abstand>IGNORE_DISTANCE zurueckgesetzt */
			if (lastDistance!=0) {
				turnAngle=turnAngle+(lastDistance-wall_distance)/10;
			}
			if (sensor<IGNORE_DISTANCE) lastDistance=sensor;
			if (check_direction==CHECK_WALL_LEFT) {
				bot_turn(data,-turnAngle);
			} else {
				bot_turn(data,turnAngle);
			}
			break;
		
		case CHECK_WALL_FINISHED:
			/* ok, check beendet -> Verhalten verlassen */
			checkState=CHECK_WALL_TURN;
			return_from_behaviour(data);
			break; 
			
		case CHECK_WALL_CORRECT:
			/* Abhaengig von der Seite, auf der die Wand ist, Entfernung korrigieren */
			if (check_direction==CHECK_WALL_LEFT) {
				sensor=sensDistL;
			} else {
				sensor=sensDistR;
			}
			if (sensor-OPTIMAL_DISTANCE<0) {
				speedWishLeft=-BOT_SPEED_SLOW;
				speedWishRight=-BOT_SPEED_SLOW;
			} else if (sensor-OPTIMAL_DISTANCE>0) {
				speedWishLeft=BOT_SPEED_SLOW;
				speedWishRight=BOT_SPEED_SLOW;
			}
			else {
				checkState=CHECK_WALL_TURN_BACK;
				speedWishLeft=BOT_SPEED_STOP;
				speedWishRight=BOT_SPEED_STOP;
			}
			break;
			
			
		default:
			checkState=CHECK_WALL_TURN;
			return_from_behaviour(data);
			break;
	}
}
 

/*!
 * Das Verhalten dreht sich um 45 Grad in die angegebene Richtung (0=rechts, 1=links)
 * und prueft, ob auf dem Sensor auf der Seite der angegebenen Richtung eine Wand
 * im Abstand von 12-22cm zu sehen ist. Wenn dem so ist, wird die Variable wall_present
 * auf True gesetzt, sonst False */
void bot_check_wall(Behaviour_t *caller,int8 direction) {
	check_direction=direction;
	wall_detected=False;
	switch_to_behaviour(caller, bot_check_wall_behaviour,NOOVERRIDE);
}

#ifdef MEASURE_MOUSE_AVAILABLE
	/*!
	 * Das Verhalten dreht den Bot in die angegebene Richtung bis ein Hindernis
	 * im Sichtbereich erscheint, das eine Entfernung bis max. zur angegebenen
	 * Distanz zum Bot hat.
	 */
	 
	void bot_measure_angle_behaviour(Behaviour_t *caller) {
		/* Zustaende measure_angle_behaviour-Verhalten */
		#define MEASURE_TURN				0
		#define FOUND_OBSTACLE				1
		#define MEASUREMENT_DONE			2
		
		static int8 measureState=MEASURE_TURN;
	
		/* enthaelt anzahl der +/-5 identischen Messungen */
		static int8 measureCount=0;
		/* letzter Messwert */
		static int16 lastSensor=0;
	
		/* bereits gedrehten Winkel */
		int16 turned_angle=0;
		if (measure_direction>0) {
			if ((int16)heading_mou<start_heading) {
				/* war ein ueberlauf */
				turned_angle=360-start_heading+(int16)heading_mou;
			} else {
				/* sonst normale differenz berechnen */
				turned_angle=(int16)heading_mou-start_heading;
			}
		} else {
			if ((int16)heading_mou>start_heading) {
				/* war ein ueberlauf */
				turned_angle=360-(int16)heading_mou+start_heading;
			} else {
				turned_angle=start_heading-(int16)heading_mou;
			}
			
		}
		
		/* sensorwert abhaengig von der Drehrichtung abnehmen */
		int16 sensor=(measure_direction==MEASURE_LEFT)?sensDistL:sensDistR;
		/* solange drehen, bis Hindernis innerhalb Messstrecke oder 360 Grad komplett */
		switch(measureState){
			case MEASURE_TURN:
				/* nicht mehr als eine komplette Drehung machen! */
				if (turned_angle>=360) {
					measure_direction=-measure_direction;
					measureState=MEASUREMENT_DONE;
					bot_turn(caller,measure_direction*turned_angle);
					measured_angle=0;		/* kein Hindernis gefunden */
					break;
				}
				/* Ist ein Objekt in Reichweite? */
				if (sensor<=measure_distance) {
					speedWishLeft=BOT_SPEED_STOP;
					speedWishRight=BOT_SPEED_STOP;
					measureState=FOUND_OBSTACLE;
					break;
				}
				/* Beginnen, zurueckzudrehen */
				speedWishLeft = (measure_direction > 0) ? -BOT_SPEED_FOLLOW : BOT_SPEED_FOLLOW;
				speedWishRight = (measure_direction > 0) ? BOT_SPEED_FOLLOW : -BOT_SPEED_FOLLOW;
				break;
				
			case FOUND_OBSTACLE:
				 /* dafuer sorgen, dass wir nur verlaessliche Werte haben
				 * dazu muss der wert dreimal nacheinander max. um +/- 5
				 * unterschiedlich sein */
				 if (measureCount==0) {
				 	lastSensor=sensor;
				 	measureCount++;
				 	break;
				 }
				 if (sensor>=lastSensor-5 && sensor<=lastSensor+5 && measureCount<4) {
				 	/* Messwert ist ok */
				 	measureCount++;
				 	break;
				 } else  if (measureCount<4) {
				 	/* Messwert weicht zu doll ab -> von Neuem messen */
				 	measureCount=0;
				 	break;
				 }
				 /* ok, wir hatten drei Messungen mit nahezu identischen Werten */
				measure_distance=sensor;
				/* Hindernis gefunden, nun Bot wieder in Ausgangsstellung drehen */
				measure_direction=-measure_direction;
				measured_angle=turned_angle;
				measureState=MEASUREMENT_DONE;
				bot_turn(caller,measure_direction*turned_angle);
				break;
				
			case MEASUREMENT_DONE:
				measureState=MEASURE_TURN;
				measureCount=0;
				return_from_behaviour(caller);
				break;
		}	
	}
	
	/*!
	 * Das Verhalten dreht den Bot in die angegebene Richtung bis ein Hindernis
	 * im Sichtbereich erscheint, das eine Entfernung bis max. zur angegebenen
	 * Distanz zum Bot hat.
	 */
	
	void bot_measure_angle(Behaviour_t *caller, int8 direction, int16 distance) {
		/* maximale Messentfernung und Richtung setzen */
		measure_direction=direction;
		measure_distance=distance;
		/* Heading zu Anfang des Verhaltens merken */
		start_heading=(int16)heading_mou;
		switch_to_behaviour(caller, bot_measure_angle_behaviour,NOOVERRIDE);	
	}
#else
/*!
 * Das Verhalten dreht den Bot in die angegebene Richtung bis ein Hindernis
 * im Sichtbereich erscheint, das eine Entfernung bis max. zur angegebenen
 * Distanz zum Bot hat.
 */
 
void bot_measure_angle_behaviour(Behaviour_t *caller) {
	/* Zustaende measure_angle_behaviour-Verhalten */
	#define MEASURE_TURN				0
	#define FOUND_OBSTACLE				1
	#define TURN_COMPLETED				2
	#define TURN_BACK					3
	#define CORRECT_ANGLE				4
	#define MEASUREMENT_DONE			5
	
	static int8 measureState=MEASURE_TURN;

	/* bereits gedrehte Strecke errechnen */
	int16 turnedLeft=(measure_direction>0)?-(sensEncL-startEncL):(sensEncL-startEncL);
	int16 turnedRight=(measure_direction>0)?(sensEncR-startEncR):-(sensEncR-startEncR);
	int16 turnedSteps=(abs(turnedLeft)+abs(turnedRight))/2;
	
	/* sensorwert abhaengig von der Drehrichtung abnehmen */
	int16 sensor=(measure_direction==MEASURE_LEFT)?sensDistL:sensDistR;
	/* solange drehen, bis Hindernis innerhalb Messstrecke oder 360� komplett */
	switch(measureState){
		case MEASURE_TURN:
			/* nicht mehr als eine komplette Drehung machen! */
			if (turnedSteps>=ANGLE_CONSTANT) {
				speedWishLeft=BOT_SPEED_STOP;
				speedWishRight=BOT_SPEED_STOP;
				measureState=TURN_COMPLETED;
				measured_angle=0;		/* kein Hindernis gefunden */
				break;
			}
			/* Ist ein Objekt in Reichweite? */
			if (sensor<=measure_distance) {
				measure_distance=sensor;
				speedWishLeft=BOT_SPEED_STOP;
				speedWishRight=BOT_SPEED_STOP;
				measureState=FOUND_OBSTACLE;
				break;
			}
			/* Beginnen, zurueckzudrehen */
			speedWishLeft = (measure_direction > 0) ? -BOT_SPEED_SLOW : BOT_SPEED_SLOW;
			speedWishRight = (measure_direction > 0) ? BOT_SPEED_SLOW : -BOT_SPEED_SLOW;
			break;
			
		case FOUND_OBSTACLE:
			/* Hindernis gefunden, nun Bot wieder in Ausgangsstellung drehen */
			measure_direction=-measure_direction;
			measured_angle=(int16)((long)(turnedSteps*360)/ANGLE_CONSTANT);
			measureState=TURN_BACK;
			speedWishLeft = (measure_direction > 0) ? -BOT_SPEED_SLOW : BOT_SPEED_SLOW;
			speedWishRight = (measure_direction > 0) ? BOT_SPEED_SLOW : -BOT_SPEED_SLOW;
			break;
			
		case TURN_COMPLETED:
			/* bot steht wieder in Ausgangsrichtung, Verhalten beenden */
			speedWishLeft=BOT_SPEED_STOP;
			speedWishRight=BOT_SPEED_STOP;
			measureState=CORRECT_ANGLE;
			break;
			
		case TURN_BACK:
			/* Bot in Ausgangsposition drehen */
			if ((turnedLeft+turnedRight)/2>=0) {
				speedWishLeft=BOT_SPEED_STOP;
				speedWishRight=BOT_SPEED_STOP;
				measureState=TURN_COMPLETED;
				break;
			}
			speedWishLeft = (measure_direction > 0) ? -BOT_SPEED_SLOW : BOT_SPEED_SLOW;
			speedWishRight = (measure_direction > 0) ? BOT_SPEED_SLOW : -BOT_SPEED_SLOW;
			break;
			
		case CORRECT_ANGLE:
			/* Evtl. etwas zuruecksetzen, falls wir zu weit gefahren sind */
			if (turnedRight>0) {
				/* rechts zu weit gefahren..langsam zurueck */
				speedWishRight = (measure_direction > 0) ? -BOT_SPEED_SLOW : BOT_SPEED_SLOW;
			} else if (turnedRight<0) {
				/* rechts noch nicht weit genug...langsam vor */
				speedWishRight = (measure_direction > 0) ? BOT_SPEED_SLOW : -BOT_SPEED_SLOW;
			} else {
				/* Endposition erreicht, rechtes Rad anhalten */
				speedWishRight = BOT_SPEED_STOP;
			}		
			if (turnedLeft<0) {
				/* links zu weit gefahren..langsam zurueck */
				speedWishLeft = (measure_direction > 0) ? -BOT_SPEED_SLOW : BOT_SPEED_SLOW;				
			} else if (turnedLeft>0) {
				/* links noch nicht weit genug...langsam vor */
				speedWishLeft = (measure_direction > 0) ? BOT_SPEED_SLOW : -BOT_SPEED_SLOW;
			} else {
				/* Endposition erreicht, linkes Rad anhalten */
				speedWishLeft = BOT_SPEED_STOP;
			}
			if (speedWishLeft == BOT_SPEED_STOP && speedWishRight == BOT_SPEED_STOP) {
				/* beide Raeder haben nun wirklich die Endposition erreicht, daher anhalten */
				measureState=MEASUREMENT_DONE;
			}
			break;
			
		case MEASUREMENT_DONE:
			measureState=MEASURE_TURN;
			return_from_behaviour(caller);
			break;
	}	
}

/*!
 * Das Verhalten dreht den Bot in die angegebene Richtung bis ein Hindernis
 * im Sichtbereich erscheint, das eine Entfernung bis max. zur angegebenen
 * Distanz zum Bot hat.
 */

void bot_measure_angle(Behaviour_t *caller, int8 direction, int16 distance) {
	/* maximale Messentfernung und Richtung setzen */
	measure_direction=direction;
	measure_distance=distance;
	/* Encoderwerte zu Anfang des Verhaltens merken */
	startEncL=sensEncL;
	startEncR=sensEncR;
	switch_to_behaviour(caller, bot_measure_angle_behaviour,NOOVERRIDE);	
}
#endif
/*!
 * Das Verhalten findet seinen Weg durch ein Labyrinth, das nach gewissen Grundregeln gebaut ist
 * in nicht immer optimaler Weise aber in jedem Fall. Es arbeitet nach dem Hoehlenforscher-Algorithmus.
 * Einschraenkung: Objekte im Labyrinth, die Endlossschleifen verursachen koennen, z.b. ein einzeln
 * stehender Pfeiler im Labyrinth um den der Bot dann immer wieder herum fahren wuerde. 
 */
void bot_solve_maze_behaviour(Behaviour_t *data){
	/* Zustaende fuer das bot_solve_maze_behaviour-Verhalten */
	#define CHECK_FOR_STARTPAD			0
	#define CHECK_FOR_WALL_RIGHT		1
	#define CHECK_FOR_WALL_LEFT			2
	#define CHECK_WALL_PRESENT			3
	#define SOLVE_MAZE_LOOP				4
	#define SOLVE_TURN_WALL				5
	#define CHECK_CONDITION				6
	#define TURN_TO_BRANCH				7
	#define DETECTED_CROSS_BRANCH		8
	#define APPROACH_CORNER				9
	#define AVOID_ABYSS					10
	#define REACHED_GOAL				11
	static int8 mazeState=CHECK_FOR_STARTPAD;
	static int8 followWall=-1;
	static int8 checkedWalls=0;
	
	int16 distance;
	double x;
	switch(mazeState) {
		case CHECK_FOR_STARTPAD:
			/* Wo beginnen wir, nach einer Wand zu suchen? 
			 * Abgrund- und Kollisions-Verhalten ausschalten */
			#ifdef BEHAVIOUR_AVOID_COL_AVAILABLE
				deactivateBehaviour(bot_avoid_col_behaviour);
			#endif
			#ifdef BEHAVIOUR_AVOID_BORDER_AVAILABLE
				deactivateBehaviour(bot_avoid_border_behaviour);
			#endif
			/* sieht nach, ob der Bot auf einem definierten Startpad steht und
			 * beginnt dann mit der Suche gleich an der richtigen Wand */
			/* Zuserst bei nach Startpad1 gucken */
			checkedWalls=0;
			if ((sensLineL>=STARTPAD1-10 && sensLineL<=STARTPAD1+10) ||
				(sensLineR>=STARTPAD1-10 && sensLineR<=STARTPAD1+10)) {
				mazeState=CHECK_FOR_WALL_LEFT;
				break;
			}
			mazeState=CHECK_FOR_WALL_RIGHT;
			break;
			
		case CHECK_FOR_WALL_RIGHT:

			mazeState=CHECK_WALL_PRESENT;
			followWall=CHECK_WALL_RIGHT;
			bot_check_wall(data,followWall);
			break;
			
		case CHECK_FOR_WALL_LEFT:
		
			followWall=CHECK_WALL_LEFT;
			bot_check_wall(data,followWall);
			mazeState=CHECK_WALL_PRESENT;
			break;
			
		
		case CHECK_WALL_PRESENT:
			/* wenn keine Wand gefunden aber links noch nicht nachgesehen, andere 
			 * Richtung checken, sonst vorfahren */
			checkedWalls++;
			if (wall_detected==False){
				/* Wand noch nicht entdeckt...haben wir schon beide gecheckt? */
				if (checkedWalls<2) {
					if (followWall==CHECK_WALL_RIGHT) {
						mazeState=CHECK_FOR_WALL_LEFT;
						break;
					} else {
						mazeState=CHECK_FOR_WALL_RIGHT;
						break;
					}
				} else {
					/* keine wand? dann vorfahren und selbes prozedere nochmal */
					bot_drive_distance(data,0,BOT_SPEED_NORMAL,BOT_DIAMETER);
					mazeState=CHECK_FOR_WALL_RIGHT;
					checkedWalls=0;
					break;
				}
			}
			/* ok, wir haben unsere richtung im labyrinth gefunden jetzt dieser 
			 * nur noch folgen bis Ziel, Abzweig oder Abgrund */
			mazeState=SOLVE_MAZE_LOOP;
			break;
			
		case SOLVE_MAZE_LOOP:
			/* Einen Schritt (=halbe BOT-Groesse) vorwaerts */
			mazeState=SOLVE_TURN_WALL;
			bot_drive_distance(data,0,BOT_SPEED_NORMAL,BOT_DIAMETER);
			break;
			
		case SOLVE_TURN_WALL:
			/* Ziel erreicht? */
			if ((sensLineL>GROUND_GOAL-20 && sensLineL<GROUND_GOAL+20) || 
			    (sensLineR>GROUND_GOAL-20 && sensLineR<GROUND_GOAL+20)) {
				/* Bot hat Ziel erreicht...aus Freude einmal um die Achse drehen */
				bot_turn(data,360);
				mazeState=REACHED_GOAL;
				break;
			}
			/* checken, ob wand vor uns (Abstand 2.5*Bot-Durchmesser in mm) */
			distance=(sensDistL+sensDistR)/2;
			if (distance<=25*BOT_DIAMETER) { // umrechnen 10*BOT_DIAMETER, da letzteres in cm angegeben wird
				/* berechnete Entfernung zur Wand abzueglich optimale Distanz fahren */
				mazeState=DETECTED_CROSS_BRANCH;
				bot_drive_distance(data,0,BOT_SPEED_NORMAL,(distance-OPTIMAL_DISTANCE)/10);
				break;
			}
			/* Zur Wand drehen....ist die Wand noch da? */
			mazeState=CHECK_CONDITION;
			bot_check_wall(data,followWall);
			break;
			
		case CHECK_CONDITION:
			/* Solange weiter, wie die Wand zu sehen ist */
			if (wall_detected==True) {
				mazeState=SOLVE_MAZE_LOOP;
				break;
			}
			/* messen, wo genau die Ecke ist */
			mazeState=APPROACH_CORNER;
			if (followWall==CHECK_WALL_LEFT){
				bot_measure_angle(data,MEASURE_LEFT,300);
			} else {
				bot_measure_angle(data,MEASURE_RIGHT,300);
			} 
			break;

		case TURN_TO_BRANCH:
			/* nun in Richtung Abzweig drehen , dann mit Hauptschleife weiter*/
			mazeState=SOLVE_MAZE_LOOP;
			if (followWall==CHECK_WALL_RIGHT) {
				bot_turn(data,-90);
			} else {
				bot_turn(data,90);
			}
			break;
			
		case DETECTED_CROSS_BRANCH:
			/* Bot faehrt auf eine Ecke zu, in Richtung Gang drehen */
			if (followWall==CHECK_WALL_LEFT) {
				mazeState=SOLVE_MAZE_LOOP;
				bot_turn(data,-90);
			} else {
				mazeState=SOLVE_MAZE_LOOP;
				bot_turn(data,90);
			}
			break;
			
		case APPROACH_CORNER:
			/* ok, nun strecke bis zur Kante berechnen */
			x=measure_distance*cos(measured_angle*M_PI/180)/10+BOT_DIAMETER*1.5;
			mazeState=TURN_TO_BRANCH;
			bot_drive_distance(data,0,BOT_SPEED_NORMAL,(int16)x);
			break;
			
		case REACHED_GOAL:
			mazeState=CHECK_WALL_RIGHT;
			speedWishLeft=BOT_SPEED_STOP;
			speedWishRight=BOT_SPEED_STOP;
			return_from_behaviour(data);
			break;
	}
}


/*!
 * Das Verhalten findet seinen Weg durch ein Labyrinth, das nach gewissen Grundregeln gebaut ist
 * in nicht immer optimaler Weise aber in jedem Fall. Es arbeitet nach dem Hoehlenforscher-Algorithmus.
 * Einschraenkung: Objekte im Labyrinth, die Endlossschleifen verursachen koennen, z.b. ein einzeln
 * stehender Pfeiler im Labyrinth um den der Bot dann immer wieder herum fahren wuerde. 
 */
 
void bot_solve_maze(Behaviour_t *caller){
	LOG_DEBUG(("bot_solve_maze()"));
	switch_to_behaviour(caller, bot_solve_maze_behaviour,NOOVERRIDE);
}

/*!
 * Initialisiert den Hoelenforscher
 * @param prio_main Prioritaet des Hoehlenforschers (typ. 100)
 * @param prio_helper Prioritaet der Hilfsfunktionen (typ. 42)
 * @param active ACTIVE wenn der hoehlenforcher sofort starten soll, sonst INACTIVE
 */
void bot_solve_maze_init(int8 prio_main,int8 prio_helper, int8 active){
	// Verhalten, um ein Labyrinth nach der Hoehlenforscher-Methode loesen 
	insert_behaviour_to_list(&behaviour, new_behaviour(prio_main, bot_solve_maze_behaviour,active));
	
	insert_behaviour_to_list(&behaviour, new_behaviour(prio_helper--, bot_measure_angle_behaviour,INACTIVE));
	insert_behaviour_to_list(&behaviour, new_behaviour(prio_helper, bot_check_wall_behaviour,INACTIVE));
	
}
#endif
