#include /* Einbinden von Standartbibliotheken */ #include "hamster.h" /* Erstellen von globalen Variablen */ unsigned char maze [129][129]; /* Erstellen eines zweidimensionalen Feldes, mit einer Größe von 1 Byte, zur Speicherung des Labyrintes. */ unsigned char nach_hause [129][129]; /* Erstellen eines zweidimensionalen Feldes, mit einer Größe von 2 Byte, zur Speicherung der Entfernung zum Ursprung. */ int x, y; /* Erstellung von diversen globalen Variablen, zur Speicherung von x und y Koordinaten. */ /* Funktion, die den Hamster nach Osten dreht. */ void look_e (HAMSTER *hms) { switch (hms_dir(hms)) /* Prüft ab in welche Richtung der Hamster sieht und entscheidet dann wie er sich dreht. */ { case HMS_EAST : break; case HMS_NORTH : hms_turn(hms,HMS_RIGHT); break; case HMS_WEST : hms_turn(hms,HMS_RIGHT); hms_turn(hms,HMS_RIGHT); break; case HMS_SOUTH : hms_turn(hms,HMS_LEFT); break; } } /* Funktion, die den Hamster nach Norden dreht. */ void look_n (HAMSTER *hms) { switch (hms_dir(hms)) /* Prüft ab in welche Richtung der Hamster sieht und entscheidet dann wie er sich dreht. */ { case HMS_EAST : hms_turn(hms,HMS_LEFT); break; case HMS_NORTH : break; case HMS_WEST : hms_turn(hms,HMS_RIGHT); break; case HMS_SOUTH : hms_turn(hms,HMS_RIGHT); hms_turn(hms,HMS_RIGHT); break; } } /* Funktion, die den Hamster nach Westen dreht. */ void look_w (HAMSTER *hms) { switch (hms_dir(hms)) /* Prüft ab in welche Richtung der Hamster sieht und entscheidet dann wie er sich dreht. */ { case HMS_EAST : hms_turn(hms,HMS_RIGHT); hms_turn(hms,HMS_RIGHT); break; case HMS_NORTH : hms_turn(hms,HMS_LEFT); break; case HMS_WEST : break; case HMS_SOUTH : hms_turn(hms,HMS_RIGHT); break; } } /* Funktion, die den Hamster nach Süden dreht. */ void look_s (HAMSTER *hms) { switch (hms_dir(hms)) /* Prüft ab in welche Richtung der Hamster sieht und entscheidet dann wie er sich dreht. */ { case HMS_EAST : hms_turn(hms,HMS_RIGHT); break; case HMS_NORTH : hms_turn(hms,HMS_RIGHT); hms_turn(hms,HMS_RIGHT); break; case HMS_WEST : hms_turn(hms,HMS_LEFT); break; case HMS_SOUTH : break; } } /* Funktion, die den Hamster einen Schritt nach Osten gehen läßt. */ void go_e (HAMSTER *hms) { look_e (hms); /* Ruft die Funktion auf, die den Hamster nach Osten dreht. */ hms_move (hms); /* Geht ein Schritt vor. */ } /* Funktion, die den Hamster einen Schritt nach Norden gehen läßt. */ void go_n (HAMSTER *hms) { look_n (hms); /* Ruft die Funktion auf, die den Hamster nach Norden dreht. */ hms_move (hms); /* Geht ein Schritt vor. */ } /* Funktion, die den Hamster einen Schritt nach Westen gehen läßt. */ void go_w (HAMSTER *hms) { look_w (hms); /* Ruft die Funktion auf, die den Hamster nach Westen dreht. */ hms_move (hms); /* Geht ein Schritt vor. */ } /* Funktion, die den Hamster einen Schritt nach Süden gehen läßt. */ void go_s (HAMSTER *hms) { look_s (hms); /* Ruft die Funktion auf, die den Hamster nach Süden dreht. */ hms_move (hms); /* Geht ein Schritt vor. */ } /* Funktion, die die Position des Hamsters bestimmt. */ void pos (HAMSTER *hms) { hms_pos (hms, &x, &y); /* Bestimmung der Position. */ x += 64; /* Zu x und y Koordinate werden 64 hinzuaddiert, da bei zweidimensionalen */ y += 64; /* Feldern die erste Dimension nicht negativ werden darf. */ } /* Funktion, die das Feld, auf dem sich der Hamster befindet, untersucht und speichert */ /* Genaueres zu dieser Funktion, siehe Beleg */ void umsehen (HAMSTER *hms) { int z; pos(hms); /* Bestimmung der Position. */ maze [x][y] = 0; /* Das Feld, auf dem der Hamster steht, wird auf 0 gesetzt */ for (z=1;z<=4;z++) /* Die Schleife wird 4-mal durchlaufen. Für jede Richtung einmal. */ { hms_turn(hms,HMS_RIGHT); /* Wenn der Hamster eine Wand sieht addiert er je nach Richtung einen Wert zu dem Feld hinzu, */ if (hms_look(hms)==HMS_WALL) { switch (hms_dir(hms)) { case HMS_EAST : maze [x][y] += 1 ;break; case HMS_NORTH : maze [x][y] += 2 ;break; case HMS_WEST : maze [x][y] += 4 ;break; case HMS_SOUTH : maze [x][y] += 8 ;break; } } } } /* Funktion, die den Hamster in eine bestimmte Richtung drehen läßt und zurückgibt ob sich vor ihm eine Wand befindet. */ int look_wall(HAMSTER *hms, int rich) { switch (rich) { case 0 : /* Osten */ { look_e(hms); if (hms_look(hms) == HMS_WALL) return (1); else return (0); break; } case 1 : /* Westen */ { look_w(hms); if (hms_look(hms) == HMS_WALL) return (1); else return (0); break; } case 2 : /* Norden */ { look_n(hms); if (hms_look(hms) == HMS_WALL) return (1); else return (0); break; } case 3 : /* Süden */ { look_s(hms); if (hms_look(hms) == HMS_WALL) return (1); else return (0); break; } } return (1); } /* Funktion, die den Abstand zum Ursprung berechnet. */ void abst (HAMSTER *hms) { int min; pos (hms); if (nach_hause [x][y] == 0) return; /* Wenn der Abstand 0 beträgt wird die Funktion abgebrochen */ /* Folgender Algorithmus überprüft, ob sich ein Feld mit einen geringeren Abstand benachbart ist. Wenn ja, wird das Minimum um eins erhöht und als neuen Abstand genommen. Da man bei benachbarten Felden überprüfen muß, ob sich dort eine Wand befindet, habe ich eine Fallunterscheidung für alle Labyrintentypen gemacht. */ switch (maze [x][y]) { case 0 : { min = nach_hause [x+1][y]; if (nach_hause[x][y+1] < min) min = nach_hause [x][y+1]; if (nach_hause[x-1][y] < min) min = nach_hause [x-1][y]; if (nach_hause[x][y-1] < min) min = nach_hause [x][y-1]; min ++; nach_hause [x][y] = min; break; } case 1 : { min = nach_hause [x][y+1]; if (nach_hause[x-1][y] < min) min = nach_hause [x-1][y]; if (nach_hause[x][y-1] < min) min = nach_hause [x][y-1]; min ++; nach_hause [x][y] = min; break; } case 2 : { min = nach_hause [x+1][y]; if (nach_hause[x-1][y] < min) min = nach_hause [x-1][y]; if (nach_hause[x][y-1] < min) min = nach_hause [x][y-1]; min ++; nach_hause [x][y] = min; break; } case 3 : { min = nach_hause [x-1][y]; if (nach_hause[x][y-1] < min) min = nach_hause [x][y-1]; min ++; nach_hause [x][y] = min; break; } case 4 : { min = nach_hause [x+1][y]; if (nach_hause[x][y+1] < min) min = nach_hause [x][y+1]; if (nach_hause[x][y-1] < min) min = nach_hause [x][y-1]; min ++; nach_hause [x][y] = min; break; } case 5 : { min = nach_hause [x][y+1]; if (nach_hause[x][y-1] < min) min = nach_hause [x][y-1]; min ++; nach_hause [x][y] = min; break; } case 6 : { min = nach_hause [x+1][y]; if (nach_hause[x][y-1] < min) min = nach_hause [x][y-1]; min ++; nach_hause [x][y] = min; break; } case 7 : { min = nach_hause [x][y-1]; min ++; nach_hause [x][y] = min; break; } case 8 : { min = nach_hause [x+1][y]; if (nach_hause[x][y+1] < min) min = nach_hause [x][y+1]; if (nach_hause[x-1][y] < min) min = nach_hause [x-1][y]; min ++; nach_hause [x][y] = min; break; } case 9 : { min = nach_hause [x][y+1]; if (nach_hause[x-1][y] < min) min = nach_hause [x-1][y]; min ++; nach_hause [x][y] = min; break; } case 10 : { min = nach_hause [x+1][y]; if (nach_hause[x-1][y] < min) min = nach_hause [x-1][y]; min ++; nach_hause [x][y] = min; break; } case 11 : { min = nach_hause [x-1][y]; min ++; nach_hause [x][y] = min; break; } case 12 : { min = nach_hause [x+1][y]; if (nach_hause[x][y+1] < min) min = nach_hause [x][y+1]; min ++; nach_hause [x][y] = min; break; } case 13 : { min = nach_hause [x][y+1]; min ++; nach_hause [x][y] = min; break; } case 14 : { min = nach_hause [x+1][y]; min ++; nach_hause [x][y] = min; break; } } pos(hms); } /* Funktion, die den Hamster das eingesammelte Korn wegbringen und wieder zum Ausgangsort zurückgehen läßt. */ void wegbringen (HAMSTER *hms) { int abstand2 = 0, richtung, z1, z2, control = 0; unsigned char go_back [129][129]; /* Für den Rückweg wird ein Feld erzeugt. */ for(z1=0;z1<=128;z1++) { for(z2=0;z2<=128;z2++) { go_back [z1][z2] = 255; } } pos (hms); go_back [x][y] = abstand2; /* Position des Hamsters wird gespeichert */ richtung = hms_dir(hms); /* Richtung, in die der Hamster sieht, wird gespeichert */ /* Schleife wird so lange durchlaufen, bis der Hamster zu Hause ist, oderer auf ein Feld trift wo weniger als 243 Körner liegen. */ /* Die Funktion wird im Beleg genauer beschrieben. */ while ((nach_hause [x][y] != 0) && (control == 0)) { pos (hms); if ((nach_hause [x][y] > nach_hause [x+1][y]) && (look_wall(hms,0) == 0)) { go_e (hms); if ((hms_corn(hms) != 0) && (hms_corn(hms) < 243)) control = 1; } else { if ((nach_hause [x][y] > nach_hause [x-1][y]) && (look_wall(hms,1) == 0)) { go_w (hms); if ((hms_corn(hms) != 0) && (hms_corn(hms) < 243)) control = 1; } else { if ((nach_hause [x][y] > nach_hause [x][y+1]) && (look_wall(hms,2) == 0)) { go_n (hms); if ((hms_corn(hms) != 0) && (hms_corn(hms) < 243)) control = 1; } else { if ((nach_hause [x][y] > nach_hause [x][y-1]) && (look_wall(hms,3) == 0)) { go_s (hms); if ((hms_corn(hms) != 0) && (hms_corn(hms) < 243)) control = 1; } else { fprintf(stderr,"\nFinde den Weg nach Hause nicht.\n"); } } } } pos (hms); abstand2 ++; go_back [x][y] = abstand2; } hms_drop(hms,HMS_MAXLOAD); /* Der Hamster geht zum Ausgangsort zurück. */ while (go_back [x][y] != 0) { pos (hms); if (go_back [x][y] == go_back [x+1][y] + 1) go_e (hms); if (go_back [x][y] == go_back [x-1][y] + 1) go_w (hms); if (go_back [x][y] == go_back [x][y+1] + 1) go_n (hms); if (go_back [x][y] == go_back [x][y-1] + 1) go_s (hms); } /* Der Hamster dreht sich in die Ursprungrichtung. */ switch (richtung) { case 0 : look_e (hms) ; break; case 1 : look_n (hms) ; break; case 2 : look_w (hms) ; break; case 3 : look_s (hms) ; break; } } /* Funtion gibt an, welches Feld sich vor dem Hamster befindet. */ int vorraus (HAMSTER *hms) { pos (hms); switch (hms_dir(hms)) { case HMS_EAST : x++ ;break; case HMS_NORTH : y++ ;break; case HMS_WEST : x-- ;break; case HMS_SOUTH : y-- ;break; } return (maze [x][y]); } /* Funktion läßt den Hamster einen Schritt zurückgehen. */ void zurueck (HAMSTER * hms) { if (nach_hause [x][y] != 0) abst(hms); hms_turn(hms,HMS_RIGHT); hms_turn(hms,HMS_RIGHT); if (hms_look(hms)!=HMS_WALL) hms_move (hms); hms_turn(hms,HMS_RIGHT); hms_turn(hms,HMS_RIGHT); if (nach_hause [x][y] != 0) abst(hms); } /* Herzstück der Hamstersteuerrung */ /* Die Funktion steuert dern Hamster, sie entscheidet wann welche Unterfuntionen aufgerufen werden und wohin der Hamster geht. */ void suchen (HAMSTER *hms) { int a; if (maze [x][y] == 255) umsehen (hms); /* Wenn das Feld unbekannt ist, sieht der Hamster sich nach Wänden um. */ if (nach_hause [x][y] != 0) abst (hms); /* Der Hamster ruft ständig die Abstandsberechnung für den Rückweg auf. */ pos (hms); for (a=1;a<=4;a++) /* Schleife wird 4-mal durchlaufen. Für jede Richtung ein mal. */ { hms_turn(hms,HMS_RIGHT); /* Wenn sich vor dem Hamster keine Wand befindet und der Rückweg zum Startfeld nicht größer als 120 Schritte entfernt ist und das Feld vor ihm unbekannt ist geht er einen Schritt. */ if ((hms_look(hms) != HMS_WALL) && (nach_hause [x][y] <= 120) && (vorraus (hms) == 255)) { if (a <= 4) hms_drop(hms,HMS_MAXLOAD); /* Überprüfung, ob der Hamster auf dieses Feld noch einmal zurückkommt, wenn ja legt er alle Körner ab. */ if (hms_look(hms)!=HMS_WALL) hms_move (hms); suchen(hms); /* Danach wird die Funktion Rekursiv aufgerufen. */ hms_take(hms,HMS_MAXLOAD); /* Wenn der Hamster voll ist und auf den aktuellen Feld liegt noch ein Korn bringt er die Körner zurück. */ while (hms_corn(hms) != 0 && hms_load(hms)==HMS_MAXLOAD) { wegbringen(hms); hms_take(hms,HMS_MAXLOAD); } /* Da der Hamster rekursiv geht muß er am Ende jedes Aufrufs einen Schritt zurück gehen. */ zurueck(hms); } } } /* Funktion zum initialisieren der Felder und starten des Hamsters. */ void hms_ctrl (HAMSTER *hms) { int z1, z2; for(z1=0;z1<=128;z1++) { for(z2=0;z2<=128;z2++) { maze [z1][z2] = 255; /* Feld zur Speicherung des Labyrintes. */ nach_hause [z1][z2] = 255; /* Feld zur Speicherung des Rückweges. */ } } pos (hms); nach_hause [x][y] = 0; suchen (hms); /* Starten des Hamsters. */ hms_drop(hms,HMS_MAXLOAD); /* Falls der Hamster noch Körner hat legt er sie ab. */ }