/*
 * c't-Bot - Robotersimulator fuer den 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 	map.c  
 * @brief 	Karte 
 * @author 	Benjamin Benz (bbe@heise.de)
 * @date 	19.09.06
*/
#include <stdio.h>
#include "ct-Bot.h"
#include "bot-local.h"
#include "sensor_correction.h"
#include "map.h"
#include "mmc.h"
#include "mini-fat.h"
#include "mmc-vm.h"

#ifdef MAP_AVAILABLE
#include <math.h>
#include <stdlib.h>

/*
 * Eine Karte ist wie folgt organisiert:
 * Es gibt Sektionen zu je MAP_SECTION_POINTS * MAP_SECTION_POINTS. 
 * Diese Sektionen enthalten direkt die Pixel-Daten
 * Auf dem PC haelt (noch) ein uebergeordnetes Array haelt die einzelnen Sections 
 * So laesst sich leicht eine Karte aufbauen, 
 * ohne dass viel Platz fuer unbenutzte Felder draufgeht
 * 
 * Auf dem MCU passt eine Sektion in einen Flashblock, bzw immer 2 Sektionen in einen Block
 * Es stehen immer 2 Sections also 1 Flash-Block im SRAM und werden bei Bedarf gewechselt
 * 
 * Felder sind vom Typ int8 und haben einen Wertebereich von -128 bis 127
 * 0 bedeutet: wir wissen nichts über das Feld
 * negative Werte bedeuten: Hinderniss
 * postivie Werte bedeuten: freier Weg
 * je größer der Betrag ist, desto sicherer die Aussage über das Feld
 * Der Wert -128 ist Löchern vorbehalten und wird dann auch nicht durch die Abstandssensoren verändert
 * (Achtung, die Locherkennung ist derzeit noch nicht fertig impelementiert)
 *
 * Felder werden wie folgt aktualisiert:
 * Wird ein Punkt als frei betrachtet, erhoehen wir den Wert des Feldes um MAP_STEP_FREE
 * Wird ein Punkt als belegt erkannt, ziehen wir um ihn einen Streukreis mit dem Radius MAP_RADIUS. 
 * Das Zentrum des Kreises wird um MAP_STEP_OCCUPIED dekrementiert, nach aussen hin immer weniger
 * Wird ein Feld als Loch erkannt, setzen wir den Wert fest auf -128 (Achtung, derzeit noch nicht fertig impelementiert)
 */

#define MAP_SECTIONS ((( MAP_SIZE*MAP_RESOLUTION)/MAP_SECTION_POINTS))

#define MAP_STEP_FREE		2	/*!< Um diesen Wert wird ein Feld inkrementiert, wenn es als frei erkannt wird */
#define MAP_STEP_OCCUPIED	10	/*!< Um diesen Wert wird ein Feld dekrementiert, wenn es als belegt erkannt wird */

#define MAP_RADIUS			10	/*!< Umkreis einen Messpunkt, der als Besetzt aktualisiert wird (Streukreis) [mm]*/
#define MAP_RADIUS_FIELDS	(MAP_RESOLUTION*MAP_RADIUS/1000)	/*!< Umkreis einen Messpunkt, der als Besetzt aktualisiert wird (Streukreis) [Felder]*/

#define MAP_PRINT_SCALE				/*!< Soll das PGM eine Skala erhalten */
#define MAP_SCALE	(MAP_RESOLUTION/2)	/*!< Alle wieviel Punkte kommt wein Skalen-Strich */

#ifdef SHRINK_MAP_ONLINE
	uint16 map_min_x=MAP_SIZE*MAP_RESOLUTION/2; /*!< belegter Bereich der Karte [Kartenindex]: kleinste X-Koordinate */
	uint16 map_max_x=MAP_SIZE*MAP_RESOLUTION/2; /*!< belegter Bereich der Karte [Kartenindex]: groesste X-Koordinate */
	uint16 map_min_y=MAP_SIZE*MAP_RESOLUTION/2; /*!< belegter Bereich der Karte [Kartenindex]: kleinste Y-Koordinate */
	uint16 map_max_y=MAP_SIZE*MAP_RESOLUTION/2; /*!< belegter Bereich der Karte [Kartenindex]: groesste Y-Koordinate  */
#endif

typedef struct {
	int8 section[MAP_SECTION_POINTS][MAP_SECTION_POINTS]; /*!< Einzelne Punkte */
} map_section_t;   /*!< Datentyp fuer die elementarfelder einer Gruppe */


#ifdef MMC_VM_AVAILABLE
	map_section_t * map[2][1];	/*! Array mit den Zeigern auf die Elemente */
	uint32 map_start_block; 	/*! Block, bei dem die Karte auf der MMC-Karte beginnt. Derzeit nur bis 32MByte adressierbar*/
	uint32 map_current_block; 	/*! Block, der aktuell im Puffer steht. Derzeit nur bis 32MByte adressierbar*/
	uint8* map_buffer;			/*! dynamischer Puffer */
#else
	#ifdef MCU
		#ifdef MMC_AVAILABLE
			// Wenn wir die MMC-Karte haben, passen immer 2 Sektionen in den SRAM
			map_section_t * map[2][1];	/*! Array mit den Zeigern auf die Elemente */
			uint32 map_start_block; /*! Block, bei dem die Karte auf der MMC-Karte beginnt. Derzeit nur bis 32MByte adressierbar*/
			uint32 map_current_block; /*! Block, der aktuell im Puffer steht. Derzeit nur bis 32MByte adressierbar*/
			uint8 map_buffer[sizeof(map_section_t)*2]; /*! statischer Puffer */
			uint8 map_current_block_updated; /*! markiert, ob der aktuelle Block gegenueber der MMC-Karte veraendert wurde */
		#else
			// Ohne MMC-Karte nehmen wir nur 1 Sektionen in den SRAM und das wars dann
			map_section_t * map[1][1];	/*! Array mit den Zeigern auf die Elemente */
		#endif
	#else
		map_section_t * map[MAP_SECTIONS][MAP_SECTIONS];	/*! Array mit den Zeigern auf die Elemente */
	#endif
#endif	// MMC_VM_AVAILABLE

/*!
 *  initialisiere die Karte
 * @return 0 wenn alles ok ist
 */
int8 map_init(void){
	#ifndef MMC_VM_AVAILABLE
		#ifdef MMC_AVAILABLE 
			map_start_block=0xFFFFFFFF;
			map_current_block_updated = 0xFF;	// Die MMC-Karte ist erstmal nicht verfuegbar

			if (mmc_get_init_state() != 0) return 1;
			map_start_block= mini_fat_find_block("MAP",map_buffer);
		
			// Die Karte auf den Puffer biegen
			map[0][0]=(map_section_t*)map_buffer;
			map[1][0]=(map_section_t*)(map_buffer+sizeof(map_section_t));		
		
			if (map_start_block != 0xFFFFFFFF){
				map_current_block_updated = False;	// kein Block geladen und daher auch nicht veraendert
				return 1;
			}	
		#endif
	#else
		map_start_block = mmc_fopen("MAP")>>9;	// TODO: Mit Bytes arbeiten und Shiften sparen
		printf("Startaddress of map: 0x%lx \n\r", map_start_block<<9);
		if (map_start_block == 0) return 1;
		map_buffer = mmc_get_data(map_start_block<<9);
		if (map_buffer == NULL) return 1;
		
		// Die Karte auf den Puffer biegen
		map[0][0]=(map_section_t*)map_buffer;
		map[1][0]=(map_section_t*)(map_buffer+sizeof(map_section_t));		
	#endif	// MMC_VM_AVAILABLE	
		
	return 0;
}

/*!
 * liefert einen Zeiger auf die Section zurueck, in der der Punkt liegt.
 * Auf dem MCU kuemmert sie sich darum, die entsprechende Karte aus der MMC-Karte zu laden
 * @param x x-Ordinate der Karte (nicht der Welt!!!)
 * @param y y-Ordinate der Karte (nicht der Welt!!!)
 * @param create Soll das Segment erzeugt werden, falls es noch nicht existiert?
 * @return einen zeiger auf die Karte
 */
map_section_t * map_get_section(uint16 x, uint16 y, uint8 create){
	uint16 section_x, section_y;
		
	// Berechne in welcher Sektion sich der Punkt befindet
	section_x=x/ MAP_SECTION_POINTS;
	section_y=y/ MAP_SECTION_POINTS;
		
	if ((section_x>= MAP_SECTIONS) || (section_y >= MAP_SECTIONS) ||
		(section_x < 0) || (section_y <0)){
		#ifdef PC
			printf("Versuch auf in Feld ausserhalb der Karte zu zugreifen!! x=%d y=%d\n",x,y);
		#endif
		return NULL;
	}

// cut	
	
	#ifndef MMC_VM_AVAILABLE	
		#ifdef MMC_AVAILABLE // Mit MMC-Karte geht hier einiges anders
			// wenn die Karte nicht sauber initialisiert ist, mache nix!
			if (map_current_block_updated == 0xFF)
				return map[0][0];
				
			// Berechne den gesuchten Block
			uint32 block = section_x + section_y*MAP_SECTIONS;
			block = block >>1;	// es passen immer 2 Sections in einen Block
			block += map_start_block;	// Offset drauf
			
			// Ist der Block noch nicht geladen
			if (map_current_block != block){
				// Wurde der Block im RAM veraendert?
				if (map_current_block_updated == True)
					mmc_write_sector(map_current_block,map_buffer,0);
				
				//Lade den neuen Block
				mmc_read_sector(block,map_buffer);
				map_current_block=block;
				map_current_block_updated = False;
			}
			
			// richtige der beiden sections raussuchen
			uint8 index= section_x & 0x01;
			return map[index][0];	
		#else // ohne MMC-Karte einfach direkt mit dem SRAM arbeiten
			if ((map[section_x][section_y] == NULL) && (create==True)){
				uint16 index_x, index_y;
				map[section_x][section_y]= malloc(sizeof(map_section_t));
				for (index_x=0; index_x<MAP_SECTION_POINTS; index_x++)
					for (index_y=0; index_y<MAP_SECTION_POINTS; index_y++)
						map[section_x][section_y]->section[index_x][index_y]=0;
				
			}
			return map[section_x][section_y];
		#endif	// MMC_AVAILABLE
	#else
		// Berechne den gesuchten Block
		uint32 block = section_x + section_y*MAP_SECTIONS;
		block = block >>1;	// es passen immer 2 Sections in einen Block
		block += map_start_block;	// Offset drauf
		map_buffer = mmc_get_data(block<<9);
		if (map_buffer != NULL){
			map[0][0]=(map_section_t*)map_buffer;
			map[1][0]=(map_section_t*)(map_buffer+sizeof(map_section_t));
			// richtige der beiden sections raussuchen
			uint8 index= section_x & 0x01;
			return map[index][0];
		} else return map[0][0];	
	#endif	// MMC_VM_AVAILABLE
}

/*!
 * liefert den Wert eines Feldes 
 * @param x x-Ordinate der Karte (nicht der Welt!!!)
 * @param y y-Ordinate der Karte (nicht der Welt!!!)
 * @return Wert des Feldes (>0 heisst frei, <0 heisst belegt
 */
int8 map_get_field (uint16 x, uint16 y) {
	uint16 index_x, index_y;
	
	// Suche die Section heraus
	map_section_t * section = map_get_section(x,y,False);

	// Eventuell existiert die Section noch nicht
	if (section == NULL)
		return 0;

	// Berechne den Index innerhalb der Section
	index_x = x % MAP_SECTION_POINTS;
	index_y = y % MAP_SECTION_POINTS;

	return section->section[index_x][index_y];	
}

/*!
 * Setzt den Wert eines Feldes auf den angegebenen Wert
 * @param x x-Ordinate der Karte (nicht der Welt!!!)
 * @param y y-Ordinate der Karte (nicht der Welt!!!)
 * @param value neuer wert des Feldes (> 0 heisst frei, <0 heisst belegt
 */
void map_set_field(uint16 x, uint16 y, int8 value) {
	uint16 index_x, index_y;
			
	// Suche die Section heraus
	map_section_t * section = map_get_section(x,y,True);		

	// Wenn wir keine section zurueck kriegen, stimmt was nicht
	if (section == NULL)
		return;

	// Berechne den Index innerhalb der Section
	index_x = x % MAP_SECTION_POINTS;
	index_y =  y % MAP_SECTION_POINTS;
	
	section->section[index_x][index_y]=value;
	
	#ifdef SHRINK_MAP_ONLINE
		// Belegte Kartengroesse anpassen
		if (x < map_min_x)
			map_min_x=x;
		if (x > map_max_x)
			map_max_x= x;
		if (y < map_min_y)
			map_min_y=y;
		if (y > map_max_y)
			map_max_y= y;
	#endif

	#ifdef MMC_AVAILABLE
		#ifndef MMC_VM_AVAILABLE
			if (map_current_block_updated != 0xFF)
				map_current_block_updated = True;
		#endif
	#endif
	
}

/*!
 * liefert den Wert eines Feldes 
 * @param x x-Ordinate der Welt 
 * @param y y-Ordinate der Welt
 * @return Wert des Feldes (>0 heisst frei, <0 heisst belegt
 */
int8 map_get_point (float x, float y){
	//Ort in Kartenkoordinaten
	uint16 X = world_to_map(x);
	uint16 Y = world_to_map(y);
	
	return map_get_field(X,Y);
}

/*!
 * aendert den Wert eines Feldes um den angegebenen Betrag 
 * @param x x-Ordinate der Karte (nicht der Welt!!!)
 * @param y y-Ordinate der Karte (nicht der Welt!!!)
 * @param value Betrag um den das Feld veraendert wird (>= heisst freier, <0 heisst belegter
 */
void map_update_field (uint16 x, uint16 y, int8 value) {

	int16 tmp= map_get_field(x,y);
	if (tmp == -128)	// Nicht aktualiseren, wenn es sich um ein Loch handelt
		return;
			
	tmp+=value;
	
	// pruefen, ob kein ueberlauf stattgefunden hat und das Feld nicht schon als Loch (-128) markiert ist
	if ((tmp < 128) && (tmp > -128))
		map_set_field(x,y,(int8)tmp);
}

/*!
 * markiert ein Feld als frei -- drueckt den Feldwert etwas mehr in Richtung "frei"
 * @param x x-Ordinate der Karte (nicht der Welt!!!)
 * @param y y-Ordinate der Karte (nicht der Welt!!!)
 */
void map_update_free (uint16 x, uint16 y) {
  map_update_field(x,y,MAP_STEP_FREE);
}

/*!
 * aendert den Wert eines Feldes um den angegebenen Betrag 
 * @param x x-Ordinate der Karte (nicht der Welt!!!)
 * @param y y-Ordinate der Karte (nicht der Welt!!!)
 * @param value Betrag um den das Feld veraendert wird (>= heisst freier, <0 heisst belegter
 */
#if MAP_RADIUS_FIELDS > 0
	void map_update_field_circle(uint16 x, uint16 y, int8 radius, int8 value) {
		int16 dX,dY;
	    uint16 h=radius*radius;
		for(dX = -radius; dX <= radius; dX++){
	      for(dY = -radius; dY <= radius; dY++) {
	           if(dX*dX + dY*dY <= h)	 
	           	 map_update_field (x + dX, y + dY,value);
	      }
		}
	}
#endif

/*!
 * markiert ein Feld als belegt -- drueckt den Feldwert etwas mehr in Richtung "belegt"
 * @param x x-Ordinate der Karte (nicht der Welt!!!)
 * @param y y-Ordinate der Karte (nicht der Welt!!!)
 */
void map_update_occupied (uint16 x, uint16 y) {
  // Nur wenn ein Umkreis gewuenscht ist, auch einen malen
  #if MAP_RADIUS_FIELDS > 0
	  uint8 r;
	  for (r=1; r<=MAP_RADIUS_FIELDS; r++){
	  	map_update_field_circle(x,y,r,-MAP_STEP_OCCUPIED/MAP_RADIUS_FIELDS);
	  }
  #else 
  	map_update_field(x,y,-MAP_STEP_OCCUPIED);
  #endif
}

/*!
 * Konvertiert eine Weltkoordinate in eine Kartenkoordinate
 * @param koord Weltkordiante
 * @return kartenkoordinate
 */
uint16 world_to_map(float koord){
	uint16 tmp = koord * MAP_RESOLUTION / 1000  + (MAP_SIZE*MAP_RESOLUTION/2);
		
	return tmp;
}

/*!
 * Konvertiert eine Kartenkoordinate in eine Weltkoordinate
 * @param map_koord kartenkoordinate
 * @return Weltkordiante
 */
float map_to_world(uint16 map_koord){
	float tmp = (map_koord - (MAP_SIZE*MAP_RESOLUTION/2)) / MAP_RESOLUTION * 1000;
			
	return tmp;
}

/*! 
 * Aktualisiert die Karte mit den Daten eines Sensors
 * @param x X-Achse der Position des Sensors
 * @param y Y-Achse der Position des Sensors
 * @param head Blickrichtung im Bogenmaß
 * @param dist Sensorwert 
 */ 
void update_map_sensor(float x, float y, float h, int16 dist){
	//Ort des Sensors in Kartenkoordinaten
	uint16 X = world_to_map(x);
	uint16 Y = world_to_map(y);
	
	uint16 d;
	if (dist==SENS_IR_INFINITE)
		d=SENS_IR_MAX_DIST;
	else 
		d=dist;
		
		
	
	// Hinderniss, dass der Sensor sieht in Weltkoordinaten
	float PH_x = x + (DISTSENSOR_POS_FW + d) * cos(h);
	float PH_y = y + (DISTSENSOR_POS_FW + d) * sin(h);
	// Hinderniss, dass der linke Sensor sieht in Kartenkoordinaten
	uint16 PH_X = world_to_map(PH_x);
	uint16 PH_Y = world_to_map(PH_y);
	
	if ((dist > 80 ) && (dist <SENS_IR_INFINITE))
			map_update_occupied(PH_X,PH_Y);
	


	// Nun markiere alle Felder vor dem Hinderniss als frei
	uint16 i;

	uint16 lX = X; 	//	Beginne mit dem Feld, in dem der Sensor steht
	uint16 lY = Y; 
	
	int8 sX = (PH_X < X ? -1 : 1);  
	uint16 dX=abs(PH_X - X);		// Laenge der Linie in X-Richtung
	
	int8 sY = (PH_Y < Y ? -1 : 1); 
	uint16 dY =abs(PH_Y - Y);	// Laenge der Linie in Y-Richtung

	if (dX >= dY) {			// Hangle Dich an der laengeren Achse entlang
	  dY--;	// stoppe ein Feld vor dem Hinderniss
	  uint16 lh = dX / 2;
	  for (i=0; i<dX; ++i) {
	    map_update_free (lX+i*sX, lY);
	    lh += dY;
	    if (lh >= dX) {
	      lh -= dX;
	      lY += sY;
	    }
	  }
	} else {
	  dX--; // stoppe ein Feld vor dem Hinderniss
	  uint16 lh = dY / 2;
	  for (i=0; i<dY; ++i) {
	    map_update_free (lX, lY+i*sY);
	    lh += dX;
	    if (lh >= dY) {
	      lh -= dY;
	      lX += sX;
	    }
	  }
	}	
}

/*!
 * Aktualisiert den Standkreis der internen Karte
 * @param x X-Achse der Position
 * @param y Y-Achse der Position
 */
void update_map_location(float x, float y){
	int16 x_map = world_to_map(x);
	int16 y_map = world_to_map(y);
	
	// Aktualisiere zuerst die vom Bot selbst belegte Flaeche
	#define dim BOT_DIAMETER/2*MAP_RESOLUTION/100
	int16 dX,dY;
	for(dX = -dim; dX <= dim; dX++)
      for(dY = -dim; dY <= dim; dY++) {
           if(dX*dX + dY*dY <= dim*dim)	 
           	 map_update_free (x_map + dX, y_map + dY);
     }
}

/*!
 * Aktualisiert die interne Karte anhand der Sensordaten
 * @param x X-Achse der Position
 * @param y Y-Achse der Position
 * @param head Blickrichtung in Grad
 * @param distL Sensorwert links
 * @param distR Sensorwert rechts
 */
void update_map(float x, float y, float head, int16 distL, int16 distR){
//	printf("update_map: x=%f, y=%f, head=%f, distL=%d, distR=%d\n",x,y,head,distL,distR);
	
    float h= head * M_PI /180;
	        
    //Ort des rechten Sensors in Weltkoordinaten
    float Pr_x = x + (DISTSENSOR_POS_SW * sin(h));
	float Pr_y = y - (DISTSENSOR_POS_SW * cos(h));

    //Ort des linken Sensors in Weltkoordinaten
    float Pl_x = x - (DISTSENSOR_POS_SW * sin(h));
	float Pl_y = y + (DISTSENSOR_POS_SW * cos(h));

	update_map_sensor(Pl_x,Pl_y,h,distL);
	update_map_sensor(Pr_x,Pr_y,h,distR);
}



#ifdef PC
	/*!
	 * Schreibt einbe Karte in eine PGM-Datei
	 * @param filename Zieldatei
	 */
	void map_to_pgm(char * filename){
		printf("Speichere Karte nach %s\n",filename);
		FILE *fp = fopen(filename, "w");
		
		uint16 x,y;

		// lokale Variablen mit den defaults befuellen
		uint16 min_x=map_min_x;
		uint16 max_x=map_max_x;
		uint16 min_y=map_min_y;
		uint16 max_y=map_max_y;
		
		#ifdef 	SHRINK_MAP_OFFLINE	// nun muessen wir die Grenezn ermitteln
			// Kartengroesse reduzieren
			int8 free=1;
			while ((min_y < max_y) && (free ==1)){
				for (x=min_x; x<max_x; x++){
					if (map_get_field(x,min_y) != 0){
						free=0;
						break;
					}					
				}
				min_y++;
			}
			free=1;
			while ((min_y < max_y) && (free ==1)){
				for (x=min_x; x<max_x; x++){
					if (map_get_field(x,max_y-1) != 0){
						free=0;
						break;
					}					
				}
				max_y--;
			}
			
			free=1;
			while ((min_x < max_x) && (free ==1)){
				for (y=min_y; y<max_y; y++){
					if (map_get_field(min_x,y) != 0){
						free=0;
						break;
					}					
				}
				min_x++;
			}
			free=1;
			while ((min_x < max_x) && (free ==1)){
				for (y=min_y; y<max_y; y++){
					if (map_get_field(max_x-1,y) != 0){
						free=0;
						break;
					}					
				}
				max_x--;
			}
		
		#endif
			
		uint16 map_size_x=max_x-min_x;
		uint16 map_size_y=max_y-min_y;
		#ifdef MAP_PRINT_SCALE
			fprintf(fp,"P5\n%d %d\n255\n",map_size_x+10,map_size_y+10);
		#else
			fprintf(fp,"P5\n%d %d\n255\n",map_size_x,map_size_y);
		#endif
		printf("Karte beginnt bei X=%d,Y=%d und geht bis X=%d,Y=%d (%d * %d Punkte)\n",min_x,min_y,max_x,max_y,map_size_x,map_size_y);
		
		uint8 tmp;
		for (y=max_y; y> min_y; y--){
			for (x=min_x; x<max_x; x++){
				
				tmp=map_get_field(x,y-1)+128;
				fwrite(&tmp,1,1,fp);
			}

			#ifdef MAP_PRINT_SCALE
				// und noch schnell ne Skala basteln
				for (x=0; x<10; x++){
					if (y % MAP_SCALE == 0)
						tmp=0;
					else tmp=255;
					
					fwrite(&tmp,1,1,fp);
				}
			#endif

		}

		#ifdef MAP_PRINT_SCALE
			for (y=0; y< 10; y++){
				for (x=min_x; x<max_x+10; x++){
					if (x % MAP_SCALE == 0)
						tmp=0;
					else tmp=255;
					
					fwrite(&tmp,1,1,fp);
				}
			}
		#endif
		fclose(fp);
		
	}


	/*! Liest eine Map wieder ein 
	 * @param filename Quelldatei
	 */
	void read_map(char * filename){
		printf("Lese Karte (%s) von MMC/SD (Bot-Format)\n",filename);
		FILE *fp = fopen(filename, "r");
		
		uint8 buffer[512];
		fread(buffer,512,1,fp);
		
		if (buffer[0] != 'M' || buffer[1] != 'A' || buffer[2] != 'P'){
			printf("Datei %s enthaelt keine Karte\n",filename);
			return;
		}
		
		uint16 x,y;	
		uint8 * ptr;

		for (y=0; y< MAP_SECTIONS; y++)
			for (x=0; x< MAP_SECTIONS; x++){
				ptr= (uint8*)map_get_section(x*MAP_SECTION_POINTS, y*MAP_SECTION_POINTS, True);
				fread(ptr,MAP_SECTION_POINTS*MAP_SECTION_POINTS,1,fp);
			}
			
		fclose(fp);
		
	}
#endif



/*!
 * Zeigt die Karte an
 */
void print_map(void){
	#ifdef PC
		map_to_pgm("map.pgm");
	#else
		// Todo: Wie soll der Bot eine Karte ausgeben ....
	#endif
}



#endif
