/*---------------------------------------------------------------------- File : hamster.c Contents: hamster control program Author : Gunnar Klein History : 10.02.1998 file created by C. Borgelt 07.05.1998 file changed 12.05.1998 file changed 28.05.1998 file changed 05.06.1998 file changed ----------------------------------------------------------------------*/ #include #include #include #include "hamster.h" /*----------------------------------------------------------------------- Structures ------------------------------------------------------------------------*/ /*Struktur zum Merken der Positionen des Hamsters bis er 12 Maiskörner aufgenommen hat nötig, um unnötige Schritte im Rückweg zu verhindern*/ struct way { int x[151]; int y[151]; }way; /*Struktur zum Nachbau des Labyrinths im Speicher Werte für north, south 0 - Feld in dieser Richtung ist leer east, west 1 - auf dem Feld in dieser Richtung liegt Mais 2 - in dieser Richtung befindet sich eine Wand Werte für blocked 0 - Feld ist begehbar 1 - Feld ist künstlich blockiert Werte für seen 0 - Feld ist noch nicht erforscht 1 - Feld wurde erforscht Werte für corn 0 bis 12 - Menge an Mais, der noch auf dem Feld ist */ struct info { int south,north,east,west; int blocked,seen; int corn; }info; /*Feld lab mit der Datenstruktur info als Inhalt*/ /* Start Korrektur, Christian Borgelt, 25.06.1998 */ /* Da die Initialisierung mit ``={0,0};'' sowieso ohne Wirkung ist, */ /* weil globale Variablen immer mit 0 intialisiert werden, kann */ /* sie auch weggelassen werden. I.a. wird dadurch das ausf"uhrbare */ /* Programm deutlich kleiner. */ #if 0 struct info lab[130][130]={0,0}; #else struct info lab[130][130]; #endif /* Ende Korrektur, Christian Borgelt, 25.06.1998 */ /*---------------------------------------------------------------------- Functions ----------------------------------------------------------------------*/ /*---------------------------------------------------------------------- Funktion : GO(hms,goneway,cnt) übergebenene Werte: der Hamster selbst - hms das Feld für die Blickrichtungen - goneway Counter für goneway[] - cnt Rückgabewerte: der veränderte Counter Funktion zur Bewegung des Hamsters. Dabei werden die Position und die Blickrichtung in den Feldern way bzw. goneway abgespeichert. ------------------------------------------------------------------------*/ int go(HAMSTER *hms,int *goneway,int cnt) { int x,y; hms_move(hms);; goneway[cnt]=hms_dir(hms); cnt++; hms_pos(hms,&x,&y); way.x[cnt]=x; way.y[cnt]=y; return (cnt); } /*------------------------------------------------------------------------ Funktion : BLOCK(hms,left,front,right,x,y) übergebene Werte : hms - der Hamster left,front,right - die Aussichten in die jeweiligen Richtungen x,y - Position des Hamsters Rückgabewerte : keine Funktion zum Blockieren von Feldern,auf denen sich kein Mais befindet und die in 3 Richtungen mit Wänden blockiert sind --------------------------------------------------------------------------*/ void block(HAMSTER *hms,int left,int front,int right,int x,int y) { int walls=0; if (x!=0||y!=0){ switch(hms_dir(hms)) {case 0 : if (left==HMS_WALL||lab[64+x][64+y+1].blocked==1) walls++;; if (front==HMS_WALL||lab[64+x+1][64+y].blocked==1) walls++;; if (right==HMS_WALL||lab[64+x][64+y-1].blocked==1) walls++;; if (walls>2) {lab[64+x][64+y].blocked=1;} else {lab[64+x][64+y].blocked=0;}; break; case 1 : if (left==HMS_WALL||lab[64+x-1][64+y].blocked==1) walls++;; if (front==HMS_WALL||lab[64+x][64+y+1].blocked==1) walls++;; if (right==HMS_WALL||lab[64+x+1][64+y].blocked==1) walls++;; if (walls>2) {lab[64+x][64+y].blocked=1;} else {lab[64+x][64+y].blocked=0;}; break; case 2 : if (left==HMS_WALL||lab[64+x][64+y-1].blocked==1) walls++;; if (front==HMS_WALL||lab[64+x-1][64+y].blocked==1) walls++;; if (right==HMS_WALL||lab[64+x][64+y+1].blocked==1) walls++;; if (walls>2) {lab[64+x][64+y].blocked=1;} else {lab[64+x][64+y].blocked=0;}; break; case 3 : if (left==HMS_WALL||lab[64+x+1][64+y].blocked==1) walls++;; if (front==HMS_WALL||lab[64+x][64+y-1].blocked==1) walls++;; if (right==HMS_WALL||lab[64+x-1][64+y].blocked==1) walls++;; if (walls>2) {lab[64+x][64+y].blocked=1;} else {lab[64+x][64+y].blocked=0;}; break; } }; } /*-------------------------------------------------------------------------- Funktion : MAKEMAP(hms,x,y) übergebene Werte: hms - der Hamster x,y - Position des Hamsters Rückgabewerte : keine Erforschen der momentanen Position und Speichern der Ergebnisse im feld lab. ----------------------------------------------------------------------------*/ void makemap(HAMSTER *hms,int x,int y) { int front,left,right,back; /*Umsehen und belegen von front,left,right */ front=hms_look(hms); hms_turn(hms,HMS_LEFT); left=hms_look(hms); hms_turn(hms,HMS_RIGHT);hms_turn(hms,HMS_RIGHT); right=hms_look(hms); /*bei Erforschung des Ausgangsfeldes die Rückseite erforschen, sonst auf leer setzen, da der Weg frei ist*/ if (x==0 && y==0 && lab[64][64].seen==0) {hms_turn(hms,HMS_RIGHT);back=hms_look(hms); hms_turn(hms,HMS_LEFT);hms_turn(hms,HMS_LEFT); } else { /*Zurückdrehen in die Ausgangsrichtung und Belegung von back*/ hms_turn(hms,HMS_LEFT);back=HMS_EMPTY; }; /*Belegung der einzelnen Richtungen mit front,left,right und back*/ switch (hms_dir(hms)) {case 0 : /*Blickrichtung Osten*/ lab[64+x][64+y].north=left; lab[64+x][64+y].east=front; lab[64+x][64+y].south=right; lab[64+x][64+y].west=back; lab[64+x][64+y].seen=1; block(hms,left,front,right,x,y); break; case 1 : /*Blickrichtung Norden*/ lab[64+x][64+y].north=front; lab[64+x][64+y].east=right; lab[64+x][64+y].south=back; lab[64+x][64+y].west=left; lab[64+x][64+y].seen=1; block(hms,left,front,right,x,y); break; case 2 : /*Blickrichtung Westen*/ lab[64+x][64+y].north=right; lab[64+x][64+y].east=back; lab[64+x][64+y].south=left; lab[64+x][64+y].west=front; lab[64+x][64+y].seen=1; block(hms,left,front,right,x,y); break; case 3 : /*Blickrichtung Süden*/ lab[64+x][64+y].north=back; lab[64+x][64+y].east=left; lab[64+x][64+y].south=front; lab[64+x][64+y].west=right; lab[64+x][64+y].seen=1; block(hms,left,front,right,x,y); break; } } /*--------------------------------------------------------------------------- Funktion : BACKDIR(hms,cnt,goneway) übergebene Werte : hms - der Hamster goneway - Feld mit den gespeicherten Richtungsinformationen cnt - Counter für goneway Rückgabewerte : cnt - der veränderte Counter dient dem Zurücklaufen zum Ausgangspunkt ----------------------------------------------------------------------------*/ int backdir(HAMSTER *hms,int cnt,int *goneway) { int tmp,dir,i,x,y; int nomove=0; tmp=cnt; /*Überprüfen ob die nächste Position im Rückweg nocheinmal vorkommt. Bei positiven Ergebnis wird der Counter für den Rückweg auf diese Position gesetzt. */ for (i=cnt-1;i>=0;i--) {if (way.x[i]==way.x[cnt] && way.y[i]==way.y[cnt]) tmp=i;}; cnt=tmp; cnt--; /*Richtung aus der der Hamster an dieser Position kam, aus goneway auslesen,*/ dir=goneway[cnt]; hms_pos(hms,&x,&y); switch (dir) { /*Drehen des Hamsters in die jeweils entgegengesetzte Richtung*/ case HMS_EAST : while (hms_dir(hms)!=HMS_WEST) {hms_turn(hms,HMS_LEFT);} break; case HMS_NORTH : while (hms_dir(hms)!=HMS_SOUTH) {hms_turn(hms,HMS_LEFT);} break; case HMS_WEST : while (hms_dir(hms)!=HMS_EAST) {hms_turn(hms,HMS_LEFT);} break; case HMS_SOUTH : while (hms_dir(hms)!=HMS_NORTH) {hms_turn(hms,HMS_LEFT);} break; } if (hms_look(hms)!=HMS_WALL) {hms_move(hms);}; return cnt; } /*---------------------------------------------------------------------------- Funktion : LOOKNEW(x,y) übergebene Werte : x,y - Position des Hamsters Rückgabewerte : keine Neusetzen der gesehen Maisvorkommen nach Aufnahme von Mais Falls der Hamster Mais aufgenommen hat, und sich nun auf diesem Feld kein Mais mehr befindet, müssen die Informationen auf den umliegenden Felder geändert werden. Ansonsten würde der Hamster immer wieder in dieselbe Richtung laufen. ------------------------------------------------------------------------------*/ void looknew(int x,int y) { if (lab[64+x+1][64+y].west==HMS_CORN) {lab[64+x+1][64+y].west=HMS_EMPTY;}; if (lab[64+x][64+y+1].south==HMS_CORN){lab[64+x][64+y+1].south=HMS_EMPTY;}; if (lab[64+x-1][64+y].east==HMS_CORN) {lab[64+x-1][64+y].east=HMS_EMPTY;}; if (lab[64+x][64+y-1].north==HMS_CORN) {lab[64+x][64+y-1].north=HMS_EMPTY;}; } /*---------------------------------------------------------------------------- Funktion : BLOCKBACK(hms,x,y) übergebene Werte : hms - der Hamster x,y - Position des Hamsters Rückgabewerte : keine Auf Feldern die in der Struktur lab mit "blocked" gekennzeichnet sind werden alle 4 Wände als vorhanden markiert. Dadurch wird vermieden,daß der Hamster immer wieder in Sackgassen hineinläuft. -------------------------------------------------------------------------------*/ void blockback(HAMSTER *hms,int x,int y) { switch (hms_dir(hms)) {case 0 : if (lab[64+x-1][64+y].blocked==1 && lab[64+x-1][64+y].corn==0) {lab[64+x-1][64+y].east=HMS_WALL; lab[64+x-1][64+y].north=HMS_WALL; lab[64+x-1][64+y].south=HMS_WALL; lab[64+x-1][64+y].west=HMS_WALL; lab[64+x][64+y].west=HMS_WALL; block(hms,lab[64+x][64+y].north,lab[64+x][64+y].west,lab[64+x][64+y].south,x,y); };break; case 1 : if (lab[64+x][64+y-1].blocked==1 && lab[64+x][64+y-1].corn==0) {lab[64+x][64+y-1].north=HMS_WALL; lab[64+x][64+y-1].south=HMS_WALL; lab[64+x][64+y-1].east=HMS_WALL; lab[64+x][64+y-1].west=HMS_WALL; lab[64+x][64+y].south=HMS_WALL; block(hms,lab[64+x][64+y].west,lab[64+x][64+y].south,lab[64+x][64+y].east,x,y); };break; case 2 : if (lab[64+x+1][64+y].blocked==1 && lab[64+x+1][64+y].corn==0) {lab[64+x+1][64+y].west=HMS_WALL; lab[64+x+1][64+y].east=HMS_WALL; lab[64+x+1][64+y].north=HMS_WALL; lab[64+x+1][64+y].south=HMS_WALL; lab[64+x][64+y].east=HMS_WALL; block(hms,lab[64+x][64+y].south,lab[64+x][64+y].east,lab[64+x][64+y].north,x,y); };break; case 3 : if (lab[64+x][64+y+1].blocked==1 && lab[64+x][64+y+1].corn==0) {lab[64+x][64+y+1].south=HMS_WALL; lab[64+x][64+y+1].north=HMS_WALL; lab[64+x][64+y+1].east=HMS_WALL; lab[64+x][64+y+1].west=HMS_WALL; lab[64+x][64+y].north=HMS_WALL; block(hms,lab[64+x][64+y].east,lab[64+x][64+y].north,lab[64+x][64+y].west,x,y); };break; } } /*------------------------------------------------------------------------ Hamsterkontrollprogramm --------------------------------------------------------------------------*/ void hms_ctrl (HAMSTER *hms) { int x,y,check=0; int movecnt=0; int turn,sperr=0; int cnt=0; int front,left,right; int goneway[141]; /*Initalisierung des Zufallsgenerators mit der Systemzeit*/ srand((unsigned long)time(NULL)); /*Schleife, die immer wieder durchlaufen wird, bis der Hamster 140 Schritte gemacht hat oder er 7-mal leer über das Ausgangsfeld gelaufen ist*/ while (cnt <= 140&&check<7) { hms_pos(hms, &x, &y); if ((x == 0) && (y == 0)) {/*Hochzählen der Variable zur Überprüfung wie oft der Hamster leer über das Ausgangsfeld gelaufen ist*/ if (hms_load(hms)==0) check++; else check=0;; hms_drop(hms,HMS_MAXLOAD); /*bei Erreichen des Ausgangsfeldes Nullsetzen des Counters für das Feld zur Abspeicherung der Blickrichtungen*/ cnt=0; }; /*wenn der Hamster die maximale Menge Mais trägt zurücklaufen zum Ausgangsfeld*/ if (hms_load(hms)==HMS_MAXLOAD) {cnt=backdir(hms,cnt,goneway); } else /*ansonsten Feststellen der Umgebung und Suche nach Mais*/ { switch (hms_dir(hms)) {case 0 : if (lab[64+x][64+y].seen==0) makemap(hms,x,y);; front=lab[64+x][64+y].east; /* Wenn das Feld bekannt ist Zugriff auf*/ right=lab[64+x][64+y].south; /* die abgespeicherten Werte*/ left=lab[64+x][64+y].north; /* sonst Aufruf von makemap*/ block(hms,left,front,right,x,y); break; case 1 : if (lab[64+x][64+y].seen==0) makemap(hms,x,y);; front=lab[64+x][64+y].north; right=lab[64+x][64+y].east; left=lab[64+x][64+y].west; block(hms,left,front,right,x,y); break; case 2 : if (lab[64+x][64+y].seen==0) makemap(hms,x,y);; front=lab[64+x][64+y].west; right=lab[64+x][64+y].north; left=lab[64+x][64+y].south; block(hms,left,front,right,x,y); break; case 3 : if (lab[64+x][64+y].seen==0) makemap(hms,x,y);; front=lab[64+x][64+y].south; right=lab[64+x][64+y].west; left=lab[64+x][64+y].east; block(hms,left,front,right,x,y); break; } /*Suche nach Mais*/ if (front==HMS_CORN) /*Mais voraus -> geradeaus laufen*/ {cnt=go(hms,goneway,cnt); } else {if (left==HMS_CORN&&right==HMS_CORN) /*nur links und rechts Mais ->zufällige Entscheidung */ {turn=(RAND_MAX/2-rand()>0)?HMS_POS:HMS_NEG; hms_turn(hms,turn); } else /*nur rechts Mais -> Drehung nach rechts*/ {if ((right==HMS_CORN) && (left!=HMS_CORN && front!=HMS_CORN)) { hms_turn(hms,HMS_RIGHT); } else /*nur links Mais -> Drehung nach links*/ {if ((left==HMS_CORN) && (right!=HMS_CORN && front!=HMS_CORN)) {hms_turn(hms,HMS_LEFT); } else /* in allen Richtungen leer -> zufällige Entscheidung*/ {if (front==HMS_EMPTY&&left==HMS_EMPTY&&right==HMS_EMPTY) {turn=rand()%3; if (turn==0) hms_turn(hms,HMS_LEFT);; if (turn==1) hms_turn(hms,HMS_RIGHT);; } else /*voraus ist frei, links und rechts sind Wände -> geradeaus laufen*/ {if (front==HMS_EMPTY&&right==HMS_WALL&&left==HMS_WALL) {/*do nothing*/ }; /*voraus und rechts ist frei -> zufällige Entscheidung*/ if (front==HMS_EMPTY&&right==HMS_EMPTY) {turn=rand()%10; if (turn==1) hms_turn(hms,HMS_RIGHT);; }; /*voraus und links ist frei -> zufällige Entscheidung*/ if (left==HMS_EMPTY&&front==HMS_EMPTY) {turn=rand()%10; if (turn==1) hms_turn(hms,HMS_LEFT);; }; }; /*voraus ist eine Wand, links und rechts sind frei -> zufällige Wahl zw. links und rechts*/ if (front==HMS_WALL && (right==HMS_EMPTY && left==HMS_EMPTY)) {turn=rand()%2; if (turn==0) hms_turn(hms,HMS_LEFT);; if (turn==1) hms_turn(hms,HMS_RIGHT);; }; /*nur rechts freier Weg -> Drehung nach rechts*/ if ((front==HMS_WALL) && (left==HMS_WALL)&&(right!=HMS_WALL)) {hms_turn(hms,HMS_RIGHT); }; /* nur links freier Weg -> Drehung nach links*/ if ((front==HMS_WALL) && (right==HMS_WALL)&&(left!=HMS_WALL)) {hms_turn(hms,HMS_LEFT); }; /* links, rechts und geradeaus sind blockiert -> Drehung und aus der Sackgasse laufen*/ if ((front==HMS_WALL)&&(left==HMS_WALL)&&(right==HMS_WALL)) {hms_turn(hms,HMS_RIGHT); hms_turn(hms,HMS_RIGHT); sperr=1; /* wird gesetzt, um das Sperren zu aktivieren*/ }; }; }; }; cnt=go(hms,goneway,cnt); }; hms_pos(hms,&x,&y); if (hms_corn(hms)) /* Aufnahme von Mais*/ {hms_take(hms,HMS_MAXLOAD);}; if (hms_corn(hms)==0) /* Setzen von "corn" in Struktur lab*/ {looknew(x,y);lab[64+x][64+y].corn=0; } else {lab[64+x][64+y].corn=hms_corn(hms); }; if (sperr==1) {blockback(hms,x,y);sperr=0;}; /* Sperren des Feldes auf dem der Hamster war*/ }; } }