/*************************************************************************************/ /* Hamster-Programm von Kai Fuchs, IF 97/01 */ /*************************************************************************************/ #include #include #include "hamster.h" #define HMS_MITTEX HMS_MAXXEXT-1 /* --> HMS_MITTEX=63 */ #define HMS_MITTEY HMS_MAXYEXT-1 /* --> HMS_MITTEY=63 */ #define HMS_MAXFELDER 32767 /* --> hoechste Int-Zahl */ /* Deklaration eines 'Gedaechtnisfeldes' fuer bereits betretene Felder */ int feld[HMS_MAXXEXT+HMS_MITTEX][HMS_MAXYEXT+HMS_MITTEY]; /* --> Matrix vom Format 127x127 */ /* Deklaration eines 'Gedaechtnisfeldes' fuer bereits gesichtete Mauern */ unsigned char mauern[HMS_MAXXEXT+HMS_MITTEX][HMS_MAXYEXT+HMS_MITTEY]; /* --> Matrix vom Format 127x127 */ /* Funktion zum Ueberfuehren der Hamsterposition in Char-Variablen */ void hms_pos2(HAMSTER *hms, char *hx, char *hy) { int x,y; hms_pos(hms,&x,&y); /* Position in Int x und Int y uebernehmen ...*/ *hx=x; /* und als Char hx bzw. */ *hy=y; /* Char hy abspeichern */ } /* Funktion zum Setzen der Bits in mauern[HMS_MITTEX+x][HMS_MITTEY+y] */ void setze_bit(char x, char y, char bit_nr, unsigned char wert) { char bits[4]; /* max. 4 verschiedene Mauern pro Feld moeglich */ int z; /* z : Zaehlvariable */ for (z=0; z<=3; z++) /* Bits 3 bis 0 entschluesseln */ { bits[z]=(mauern[HMS_MITTEX+x][HMS_MITTEY+y] & 1); /* z. Bit entschluesseln */ mauern[HMS_MITTEX+x][HMS_MITTEY+y]>>=1; /* und die mauern-Variabele auf */ /* naechstes Bit vorbereiten */ } if ((bit_nr<4) && (bit_nr>=0)) bits[(int)bit_nr]=wert; /* bei richtiger Bit-Nummer entsprechendes Bit setzen */ mauern[HMS_MITTEX+x][HMS_MITTEY+y]=0; /* mauern-Variable auf neue Kodierung vorbereiten */ for (z=3; z>=0; z--) /* Bits 3 bis 0 verschluesseln */ { mauern[HMS_MITTEX+x][HMS_MITTEY+y]<<=1; /* Variable vorbereiten und */ mauern[HMS_MITTEX+x][HMS_MITTEY+y]+=bits[z]; /* z. Bit verschluesseln */ } } /* Funktion zum Merken von gesichteten Mauern */ void setze_mauer(HAMSTER *hms) { char x,y; /* Variablen fuer x,y-Koordinaten */ hms_pos2(hms,&x,&y); /* Positionskoordinaten bestimmen */ switch (hms_dir(hms)) /* je nachdem, wo der Hamster hinschaut... */ { case HMS_SOUTH : setze_bit(x, y, HMS_SOUTH, 1); /* im aktuellen Feld die Mauer im Sueden merken */ setze_bit(x, y-1, HMS_NORTH, 1); /* und im Feld suedlich des aktu- ellen Feldes eine Mauer im Nor- den merken */ break; case HMS_WEST : setze_bit(x, y, HMS_WEST, 1); /* im aktuellen Feld die Mauer im Westen merken */ setze_bit(x-1, y, HMS_EAST, 1); /* und im Feld westlich des aktu- ellen Feldes eine Mauer im Osten merken */ break; case HMS_NORTH : setze_bit(x, y, HMS_NORTH, 1); /* im aktuellen Feld die Mauer im Norden merken */ setze_bit(x, y+1, HMS_SOUTH, 1); /* und im Feld noerdlich des aktu- ellen Feldes eine Mauer im Sueden merken */ break; case HMS_EAST : setze_bit(x, y, HMS_EAST, 1); /* im aktuellen Feld die Mauer im Osten merken */ setze_bit(x+1, y, HMS_WEST, 1); /* und im Feld oestlich des aktu- ellen Feldes eine Mauer im Westen merken */ } } /* Funktion zum Erinnern, ob im Feld [x,y] eine Mauer in angegebener Richtung (bit_nr) war */ char mauer(char x, char y, char bit_nr) { unsigned char a, b=1; /* a Hilfsvariable */ /* b 2er-Potenz (Anfang: 2^0) */ for (a=1; a<=bit_nr; a++) b*=2; /* errechnet 2^bit_nr */ if ((bit_nr<4) && (bit_nr>=0)) /* nur 4 moegliche Himmelsrichtungen */ return (mauern[HMS_MITTEX+x][HMS_MITTEY+y] & b); /* liefert 0, wenn in entsprechender Himmelsrichtung keine Mauer; 2^bit_nr sonst */ return 0; /* bei falscher Himmelsrichtung: 0 --> (keine Mauer) */ } /* Funktion, die die Markierung des Feldes direkt vor dem Hamster liefert */ int feld_vorn(HAMSTER *hms) { char x,y; /* Variablen fuer x,y-Koordinaten */ hms_pos2(hms,&x,&y); /* Positionskoordinaten bestimmen */ switch (hms_dir(hms)) /* je nachdem, wo der Hamster hinschaut... */ { case HMS_SOUTH : y--; /* y-Koordinate des naechsten Feldes ist um */ break; /* eins kleiner, als die des aktuellen Feldes */ case HMS_WEST : x--; /* x-Koordinate des naechsten Feldes ist um */ break; /* eins kleiner, als die des aktuellen Feldes */ case HMS_NORTH : y++; /* y-Koordinate des naechsten Feldes ist um */ break; /* eins groesser, als die des aktuellen Feldes */ case HMS_EAST : x++; /* x-Koordinate des naechsten Feldes ist um */ /* eins groesser, als die des aktuellen Feldes */ } return feld[HMS_MITTEX+x][HMS_MITTEY+y]; /* Markierung des naechsten Feldes wird zurueckgegeben */ } /* Funktion, die die Markierung des Feldes direkt vor dem Hamster setzt */ void setze_feld_vorn(HAMSTER *hms, int m) /* m : Markierung fuer das naechste Feld */ { char x,y; /* Variablen fuer x,y-Koordinaten */ hms_pos2(hms,&x,&y); /* Positionskoordinaten bestimmen */ switch (hms_dir(hms)) /* je nachdem, wo der Hamster hinschaut... */ { case HMS_SOUTH : y--; /* y-Koordinate des naechsten Feldes ist um */ break; /* eins kleiner, als die des aktuellen Feldes */ case HMS_WEST : x--; /* x-Koordinate des naechsten Feldes ist um */ break; /* eins kleiner, als die des aktuellen Feldes */ case HMS_NORTH : y++; /* y-Koordinate des naechsten Feldes ist um */ break; /* eins groesser, als die des aktuellen Feldes */ case HMS_EAST : x++; /* x-Koordinate des naechsten Feldes ist um */ /* eins groesser, als die des aktuellen Feldes */ } feld[HMS_MITTEX+x][HMS_MITTEY+y]=m; /* versieht das naechste Feld mit der angegebenen Markierung */ } /* Funktion, die die Markierung des Feldes direkt hinter dem Hamster liefert */ int feld_hinten(HAMSTER *hms) { char x,y; /* Variablen fuer x,y-Koordinaten */ hms_pos2(hms,&x,&y); /* Positionskoordinaten bestimmen */ switch (hms_dir(hms)) /* je nachdem, wo der Hamster hinschaut... */ { case HMS_SOUTH : y++; /* y-Koordinate des hinteren Feldes ist um */ break; /* eins groesser, als die des aktuellen Feldes */ case HMS_WEST : x++; /* x-Koordinate des hinteren Feldes ist um */ break; /* eins groesser, als die des aktuellen Feldes */ case HMS_NORTH : y--; /* y-Koordinate des hinteren Feldes ist um */ break; /* eins kleiner, als die des aktuellen Feldes */ case HMS_EAST : x--; /* x-Koordinate des hinteren Feldes ist um */ /* eins kleiner, als die des aktuellen Feldes */ } return feld[HMS_MITTEX+x][HMS_MITTEY+y]; /* Markierung des Feldes hinter dem Hamster wird zurueckgegeben */ } /* Funktion zum testen, ob das naechste Feld betretbar ist oder nicht */ char betretbar(HAMSTER *hms) { char x,y; /* Variablen fuer x,y-Koordinaten */ hms_pos2(hms,&x,&y); /* Positionskoordinaten bestimmen */ if (hms_look(hms)==HMS_WALL) return 0; /* naechstes Feld nicht betretbar, wenn eine Mauer im Weg ist ==> 0 */ /* naechstes Feld darf betreten werden, wenn ...*/ return ((feld_vorn(hms)==0) /* ... es vorher noch nie betreten wurde (Markierung=0) */ || (((feld_vorn(hms)-feld[HMS_MITTEX+x][HMS_MITTEY+y])>=0) /* ODER wenn es die gleiche oder groessere Markierung traegt, wie das aktuelle Feld */ && (feld_vorn(hms) 0 zurueckgeben */ if (hms_look(hms)==HMS_CORN) return 1;/* wenn Mais auf naechstem Feld liegt: auf jeden Fall draufgehen */ hms_pos2(hms,&x,&y); /* Positionskoordinaten bestimmen */ z=feld[HMS_MITTEX+x][HMS_MITTEY+y] ; /* z=(Markierung des aktuellen Feldes) */ switch (hms_dir(hms)) /* je nachdem, wo der Hamster hinschaut... */ { case HMS_SOUTH : if (y>-HMS_MITTEY) /* wenn der Hamster nicht am unteren Rand steht: naechstes Feld ist eine Sackgasse, wenn es : */ if ((mauer(x, y-1, HMS_SOUTH) || ((feld[HMS_MITTEX+x ][HMS_MITTEY+y-2]z-4) && (feld[HMS_MITTEX+x ][HMS_MITTEY+y-2])) || (feld[HMS_MITTEX+x ][HMS_MITTEY+y-2]==HMS_MAXFELDER)) /* nach Sueden durch eine Mauer ODER einen unbetretbaren Weg begrenzt ist */ && (mauer(x, y-1, HMS_WEST) || ((feld[HMS_MITTEX+x-1][HMS_MITTEY+y-1]z-4) && (feld[HMS_MITTEX+x-1][HMS_MITTEY+y-1])) || (feld[HMS_MITTEX+x-1][HMS_MITTEY+y-1]==HMS_MAXFELDER)) /* UND nach Westen durch eine Mauer ODER einen unbetretbaren Weg begrenzt ist */ && (mauer(x, y-1, HMS_EAST) || ((feld[HMS_MITTEX+x+1][HMS_MITTEY+y-1]z-4) && (feld[HMS_MITTEX+x+1][HMS_MITTEY+y-1])) || (feld[HMS_MITTEX+x+1][HMS_MITTEY+y-1]==HMS_MAXFELDER))) /* UND nach Osten durch eine Mauer ODER einen unbetretbaren Weg begrenzt ist */ return 0; /* 0 = 'SACKGASSE !!!' */ break; case HMS_WEST : if (x>-HMS_MITTEX) /* wenn der Hamster nicht am linken Rand steht : naechstes Feld ist eine Sackgasse, wenn es : */ if ((mauer(x-1, y, HMS_SOUTH) || ((feld[HMS_MITTEX+x-1][HMS_MITTEY+y-1]z-4) && (feld[HMS_MITTEX+x-1][HMS_MITTEY+y-1])) || (feld[HMS_MITTEX+x-1][HMS_MITTEY+y-1]==HMS_MAXFELDER)) /* nach Sueden durch eine Mauer oder einen unbetretbaren Weg begrenzt ist */ && (mauer(x-1, y, HMS_NORTH) || ((feld[HMS_MITTEX+x-1][HMS_MITTEY+y+1]z-4) && (feld[HMS_MITTEX+x-1][HMS_MITTEY+y+1])) || (feld[HMS_MITTEX+x-1][HMS_MITTEY+y+1]==HMS_MAXFELDER)) /* UND nach Norden durch eine Mauer ODER einen unbetretbaren Weg begrenzt ist */ && (mauer(x-1, y, HMS_WEST) || ((feld[HMS_MITTEX+x-2][HMS_MITTEY+y ]z-4) && (feld[HMS_MITTEX+x-2][HMS_MITTEY+y ])) || (feld[HMS_MITTEX+x-2][HMS_MITTEY+y ]==HMS_MAXFELDER))) /* UND nach Westen durch eine Mauer ODER einen unbetretbaren Weg begrenzt ist */ return 0; /* 0 = 'SACKGASSE !!!' */ break; case HMS_NORTH : if (yz-4) && (feld[HMS_MITTEX+x ][HMS_MITTEY+y+2])) || (feld[HMS_MITTEX+x ][HMS_MITTEY+y+2]==HMS_MAXFELDER)) /* nach Norden durch eine Mauer oder einen unbetretbaren Weg begrenzt ist */ && (mauer(x, y+1, HMS_WEST) || ((feld[HMS_MITTEX+x-1][HMS_MITTEY+y+1]z-4) && (feld[HMS_MITTEX+x-1][HMS_MITTEY+y+1])) || (feld[HMS_MITTEX+x-1][HMS_MITTEY+y+1]==HMS_MAXFELDER)) /* UND nach Westen durch eine Mauer ODER einen unbetretbaren Weg begrenzt ist */ && (mauer(x, y+1, HMS_EAST) || ((feld[HMS_MITTEX+x+1][HMS_MITTEY+y+1]z-4) && (feld[HMS_MITTEX+x+1][HMS_MITTEY+y+1])) || (feld[HMS_MITTEX+x+1][HMS_MITTEY+y+1]==HMS_MAXFELDER))) /* UND nach Osten durch eine Mauer ODER einen unbetretbaren Weg begrenzt ist */ return 0; /* 0 = 'SACKGASSE !!!' */ break; case HMS_EAST : if (xz-4) && (feld[HMS_MITTEX+x+1][HMS_MITTEY+y-1])) || (feld[HMS_MITTEX+x+1][HMS_MITTEY+y-1]==HMS_MAXFELDER)) /* nach Sueden durch eine Mauer oder einen unbetretbaren Weg begrenzt ist */ && (mauer(x+1, y, HMS_EAST) || ((feld[HMS_MITTEX+x+2][HMS_MITTEY+y ]z-4) && (feld[HMS_MITTEX+x+2][HMS_MITTEY+y ])) || (feld[HMS_MITTEX+x+2][HMS_MITTEY+y ]==HMS_MAXFELDER)) /* UND nach Osten durch eine Mauer ODER einen unbetretbaren Weg begrenzt ist */ && (mauer(x+1, y, HMS_NORTH) || ((feld[HMS_MITTEX+x+1][HMS_MITTEY+y+1]z-4) && (feld[HMS_MITTEX+x+1][HMS_MITTEY+y+1])) || (feld[HMS_MITTEX+x+1][HMS_MITTEY+y+1]==HMS_MAXFELDER))) /* UND nach Norden durch eine Mauer ODER einen unbetretbaren Weg begrenzt ist */ return 0; /* 0 = 'SACKGASSE !!!' */ } return 1; /* wenn keine Sackgasse festgestellt wurde : 1 zurueckliefern */ } /* Funktion, die den Hamster nach rechts oben im Labyrinth zuerst gehen laesst */ void rechts_oben(HAMSTER *hms) { switch (hms_dir(hms)) /* je nachdem, wo der Hamster hinschaut... */ { case HMS_SOUTH : hms_turn(hms,HMS_POS); /* wird er nach Osten oder */ break; case HMS_WEST : hms_turn(hms,HMS_NEG); /* nach Norden gedreht */ break; } } /* Funktion, die den Hamster nach rechts unten im Labyrinth zuerst gehen laesst */ void rechts_unten(HAMSTER *hms) { switch (hms_dir(hms)) /* je nachdem, wo der Hamster hinschaut... */ { case HMS_WEST : hms_turn(hms,HMS_POS); /* wird er nach Sueden oder */ break; case HMS_NORTH : hms_turn(hms,HMS_NEG); /* nach Osten gedreht */ break; } } /* Funktion, die den Hamster nach links oben im Labyrinth zuerst gehen laesst */ void links_oben(HAMSTER *hms) { switch (hms_dir(hms)) /* je nachdem, wo der Hamster hinschaut... */ { case HMS_SOUTH : hms_turn(hms,HMS_NEG); /* wird er nach Westen oder */ break; case HMS_EAST : hms_turn(hms,HMS_POS); /* nach Norden gedreht */ } } /* Funktion, die den Hamster nach links unten im Labyrinth zuerst gehen laesst */ void links_unten(HAMSTER *hms) { switch (hms_dir(hms)) /* je nachdem, wo der Hamster hinschaut... */ { case HMS_NORTH : hms_turn(hms,HMS_POS); /* wird er nach Westen oder */ break; case HMS_EAST : hms_turn(hms,HMS_NEG); /* nach Sueden gedreht */ } } /* Funktion, die den Hamster, wenn er in der Naehe einer Hauptdiagonalen steht, zunaechst in die Ecken des Labyrinths gehen laesst */ void selectweg(HAMSTER *hms) { char x, y; /* Variablen fuer x,y-Koordinaten */ hms_pos2(hms, &x, &y); /* Positionskoordinaten bestimmen */ if (abs(abs(x)-abs(y))<2) /* wenn sich x- und y-Koordinate um hoechstens den Wert 1 unterscheiden, so befindet sich der Hamster nahe einer Hauptdiagonalen */ { /* --> Unterscheidung, in welche Ecke der Hamster gehen soll */ if (x>0) /* wenn sich Hamster im rechten Bereich ... */ { if (y>0) rechts_oben(hms); /* ... und im oberen Bereich befindet: --> GEHE NACH RECHTS-OBEN */ else rechts_unten(hms); /* ... und im unteren Bereich befindet: --> GEHE NACH RECHTS-UNTEN */ } else /* wenn sich Hamster im linken Bereich ... */ { if (y>0) links_oben(hms); /* ... und im oberen Bereich befindet: --> GEHE NACH LINKS-OBEN */ else links_unten(hms); /* ... und im unteren Bereich befindet: --> GEHE NACH LINKS-UNTEN */ } } } /* rekursive Funktion zum Entscheiden, wie der Hamster weitergehen soll */ unsigned char bewege_hms(HAMSTER *hms, int entf) { unsigned char h, ausgaenge, zurueck, nochmal; int merk; /* h : Zaehlvariable ausgaenge : Anzahl der vom aktuellen Feld aus betretbaren Nachbarfelder zurueck : Richtung, aus der der Hamster das aktuelle Feld betreten hat nochmal : 1.) Rueckgabewert der naechsten 'bewege_hms'-Funktion, der angibt, ob der Hamster noch Mais zuruecklassen musste (nochmal==1) ODER ob er den gesamten Mais einsammeln konnte (nochmal==0) 2.) Rueckgabewert der aktuellen 'bewege_hms'-Funktion, der angibt, ob das aktuelle Feld nochmals betreten werden muss, weil der Hamster noch Mais zuruecklassen musste (nochmal==1) ODER ob er den gesamten Mais einsammeln konnte (nochmal==0) merk : wenn Abkuerzung gesichtet wurde : Markierung des Feldes, was eine Abkuerzung ermoeglicht sonst : (Markierung des aktuellen Feldes)-2 */ char x, y; /* Variablen fuer x,y-Koordinaten */ ausgaenge=0; /* Anzahl der betretbaren Nachbarfelder ist Null */ hms_pos2(hms, &x, &y); /* Positionskoordinaten bestimmen */ feld[HMS_MITTEX+x][HMS_MITTEY+y]=entf; /* aktuelles Feld bekommt spezifische Markierung (=Entfernung zum Ausgang) */ /* bei vorliegender Implementierung der Himmelsrichtungen ist es moeglich, die entgegengesetzte Himmelsrichtung (aus der der Hamster ja kam) rechnerisch zu bestimmen: */ zurueck=(hms_dir(hms)+2)%4; /* ((aktuelle Blickrichtung)+2) mod 4 = a) (0+2) mod 4 = 2 ==> (OSTEN +2) mod 4 = WESTEN b) (1+2) mod 4 = 3 ==> (NORDEN +2) mod 4 = SUEDEN c) (2+2) mod 4 = 0 ==> (WESTEN +2) mod 4 = OSTEN d) (3+2) mod 4 = 1 ==> (SUEDEN +2) mod 4 = NORDEN */ if ((x==0) && (y==0)) zurueck=4; /* wenn der Hamster auf seinem Ausgangsfeld steht, so darf er sich keine 'echte' Rueckrichtung merken, da er ja dieses Feld nicht von einem anderen Feld aus betreten hat */ merk=entf-2; /* ein Feld, was einen kuerzeren Weg zum Ausgangsfeld angibt, muss eine kleinere Markierung als (entf-2) aufweisen */ for (h=1; h<=4; h++) /* Schleife 4-mal ausfuehren (wegen 4 Himmelsrichtungen) */ { if ((keine_Sackgasse(hms)) && (hms_dir(hms)!=zurueck)) /* wenn der Hamster nicht in eine Sackgasse und auch nicht in Richtung des Feldes, von dem er gekommen ist, blickt : */ { if (entf falls Maximum von HMS_MAXFELDER erreicht: zurueck */ { while (hms_dir(hms)!=zurueck) hms_turn(hms, HMS_POS); /* Hamster dreht sich, bis er in die Richtung schaut, aus der er gekommen ist */ nochmal=hms_corn(hms)-hms_take(hms,HMS_MAXLOAD); /* Hamster zaehlt, wieviel Mais auf seinem Feld liegt (hms_corn(hms)) und nimmt soviel auf, wie er kann (hms_take(hms,HMS_MAXLOAD)) wegen vorliegender Implementation der Funktionen 'hms_corn' und 'hms_take' ist es dem Programm moeglich, zu berechnen, ob er dieses Feld noch einmal betreten muss (um noch vorhandenen Mais einzusammeln) oder ob er es 'vergessen' kann: Wenn er das Feld abraeumt ist die Differenz 'nochmal' Null; wenn er nicht mehr alles in sein Maul bekommt, ist 'nochmal' groesser als Null (aber <255 ! --> daher keine Zahlenbereichsueberschreitung) weil der Hamster 'gezwungen' wird, zurueckzugehen, darf er sich dieses Feld noch freihalten, falls er von einem anderen Feld aus guenstiger auf dieses Feld kommt; falls bereits eine Abkuerzung gefunden wurde, soll es nur von dort aus erlaubt sein, das aktuelle Feld zu betreten */ h=0; /* im Normalfall soll das aktuelle Feld mit '0' markiert werden... */ if (merk<(entf-2)) /* ausser, es wurde eine Abkuerzung gefunden: */ { h=merk+1; /* Feld soll entsprechend der Abkuerzung markiert werden */ nochmal=0; /* und soll dann nicht nochmal vom vorigen Feld betreten werden */ } feld[HMS_MITTEX+x][HMS_MITTEY+y]=h; /* aktuelles Feld wird markiert */ h=hms_move(hms); /* Hamster geht auf das Feld, von dem aus er das aktuelle Feld betreten hat */ if (nochmal) return 1; /* wenn er noch Mais zurueckgelassen hat, so merkt er sich das */ return 0; /* wenn er das Feld abgeraeumt hat, so braucht er es nicht noch einmal betreten */ } if (ausgaenge>1) /* wenn es mehr als eine Moeglichkeit gibt, das aktuelle Feld zu verlassen */ { selectweg(hms); /* Hamster dreht sich eventuell in Richtung einer Ecke des Labyrinths */ for (h=1; h<=ausgaenge; h++) /* Hamster prueft alle Moeglichkeiten */ { nochmal=0; /* 'nochmal' dient hier nur als Hilfsvariable! dient dazu, dass der Hamster sich in unguenstigen Fael- len nicht endlos im Kreis bewegt */ while (((keine_Sackgasse(hms)==0) || (hms_dir(hms)==zurueck)) && (4>nochmal++)) hms_turn(hms, HMS_POS); /* Hamster dreht sich, solange das Feld vor ihm eine Sackgasse oder das Feld ist, von dem aus er das aktuelle Feld betreten hat; wegen '&& (4>nochmal++)' dreht sich der Hamster aber maximal um 360 Grad */ if (nochmal<5) /* Hamster hat einen moeglichen Weg gefunden, wenn er sich um weniger als 360 Grad gedreht hat */ do /* Schleife dann wird mindestens einmal ausgefuehrt */ { nochmal=hms_move(hms); /* Hamster geht auf das naechste Feld */ nochmal=bewege_hms(hms,entf+1); /* erneuter Funktionsaufruf, wobei festgelegt wird, dass das naechste Feld eine um eins groessere Ent- fernung zum Ausgangsfeld hat; der Rueckgabewert wird an 'nochmal' uebergeben *************************************************************************************** alles Folgende innerhalb der 'if (ausgaenge>1)'-Schleife wird erst nach der Rueckkehr des Hamsters auf das Feld(x,y) ausgefuehrt ! **************************************************************************************/ if ((feld_hinten(hms)hms_drop(hms,hms_load(hms))) /* falls die Anzahl der Maiskoerner, die der Hamster im Maul hat, groesser ist, als die Anzahl der Maiskoerner, die er ablegen kann, so kann er folgern, dass das Feld schon zu voll ist, um noch Mais abzulegen; er muss dann seinen Mais zum naechsten Knotenfeld bringen: */ { nochmal=hms_take(hms,HMS_MAXLOAD); /* Hamster fuellt sich sein Maul voll */ nochmal=1; /* merkt sich, dass er dieses Feld nochmals be- treten muss */ while (hms_dir(hms)!=zurueck) hms_turn(hms, HMS_POS); /* Hamster dreht sich, bis er in die Richtung schaut, aus der er gekommen ist*/ feld[HMS_MITTEX+x][HMS_MITTEY+y]=0; /* markiert aktuelles Feld als 'noch betretbar' */ h=hms_move(hms); /* Hamster geht auf das Feld, von dem aus er das aktuelle Feld betreten hat */ return nochmal; /* Variable 'nochmal'(=1) wird zurueckgeliefert */ } if ((nochmal==0) && (feld_hinten(hms)==0)) hms_turn(hms, HMS_NEG); /* Die Konstellation, dass sowohl 'nochmal' als auch die Markierung des Feldes hin- ter dem Hamster Null ist, kommt nur nach einem Spezialfall vor: der Hamster er- reichte kurz zuvor die HMS_MAXFELDER-Felder-Grenze (siehe oben), die verhindert, dass der Hamster sich zu weit vom Ausgangsfeld entfernt. Um zu verhindern, dass der Hamster dann von dem aktuellen Feld aus das vermeintlich noch nicht betre- tene (HMS_MAXFELDER.)Feld noch einmal betritt, muss er einfach um -90 Grad ge- dreht werden; da er sich sonst immer in positiver Richtung dreht, bekommt er dieses (HMS_MAXFELDER.)Feld innerhalb der 'if (ausgaenge>1)'-Schleife nicht mehr zu 'Gesicht' */ if (nochmal) /* falls der Hamster noch einmal zurueck muss, um */ { /* noch verbliebenen Mais einzusammeln, so dreht */ hms_turn(hms, HMS_POS); /* er sich um 180 Grad und blickt somit in die Richtung */ hms_turn(hms, HMS_POS); /* von der aus er auf das aktuelle Feld zurueck kam */ } } while (nochmal); /* das Ganze wiederholt er so lange, wie noch Mais ueber den aktuellen Ausgang zu bergen ist */ } nochmal=(hms_corn(hms)-hms_take(hms,HMS_MAXLOAD)); /* Differenz aus Gesamtmais auf dem Feld und aufgenommenem Mais ist entweder groesser als Null, wenn der Hamster nicht den gesamten Mais aufnehmen konnte, oder gleich Null, wenn der Hamster das aktuelle Feld leerraeumen konnte; bei einer Differenz groesser als Null muss der Hamster dieses Feld nochmals betreten, um es abzuraeumen */ if (nochmal) /* falls der Hamster das Feld nicht abraeumen konnte... */ { feld[HMS_MITTEX+x][HMS_MITTEY+y]=0; /* markiert er das aktuelles Feld so, dass es nochmals betreten werden kann */ nochmal=1; /* Hamster merkt sich, dass er dieses Feld noch- mals betreten muss */ } else /* wenn der Hamster den gesamten Mais des Feldes aufgenommen hat... */ { feld[HMS_MITTEX+x][HMS_MITTEY+y]=HMS_MAXFELDER; /* markiert er das aktuelle Feld als nicht mehr betretbar */ if (merk==(entf-2)) mauern[HMS_MITTEX+x][HMS_MITTEY+y]=15; /* falls er zu diesem Feld keinen besseren Weg gefunden hat, so grenzt er es in Gedan- ken in Mauern ein */ } } else if (ausgaenge==1) /* wenn es nur eine Moeglichkeit gibt, das Feld vorwaerts zu verlassen (Schlauch) */ { while ((keine_Sackgasse(hms)==0) || (hms_dir(hms)==zurueck)) hms_turn(hms, HMS_POS); /* Hamster dreht sich solange, bis er den gesichteten Ausgang gefunden hat */ nochmal=hms_move(hms); /* Hamster geht durch den Ausgang aufs naechste Feld */ nochmal=bewege_hms(hms,entf+1); /* erneuter Funktionsaufruf, wobei festgelegt wird, dass das naechste Feld eine um eins groessere Entfer- nung zum Ausgangsfeld hat; der Rueckgabewert wird an die Variable 'nochmal' uebergeben *************************************************************************************** alles Folgende innerhalb der 'if (ausgaenge==1)'-Schleife wird erst nach der Rueckkehr des Hamsters auf das Feld(x,y) ausgefuehrt ! **************************************************************************************/ if ((feld_hinten(hms) Hamster muss jetzt den im Maul befindlichen Mais ablegen */ feld[HMS_MITTEX+x][HMS_MITTEY+y]=merk+1; /* Hamster markiert das Feld als ein nur ueber die Abkuerzung betretbares Feld */ } while ((hms_dir(hms)!=zurueck) && (zurueck!=4)) hms_turn(hms, HMS_POS); /* Hamster dreht sich solange, bis er in die Richtung schaut, von der aus er das aktu- elle Feld betreten hat. Wenn er auf dem Ausgangsfeld steht, so ist 'zurueck'=4 --> Hamster braucht sich nicht zu drehen, weil er dieses Feld von seinem dort befindlichen Erdloch aus betreten hat */ if ((x) || (y)) h=hms_move(hms); /* Hamster betritt (wenn er nicht auf dem Ausgangs- feld steht) das Feld von dem aus er gekommen ist */ return nochmal; /* Rueckgabe der Information, ob Mais zurueckgelassen wurde oder nicht, an die aufrufende Funktion */ } /* Hauptfunktion zum Bewegen des Hamsters */ void hms_ctrl (HAMSTER *hms) { int x, y; /* Koordinatenvariablen zur Initialisierung der beiden Gedaechtnismatrizen */ for (x=HMS_MITTEX+HMS_MITTEX; x>=0; x--) /* jede Spalte der Matrizen wird initialisiert */ for (y=HMS_MITTEY+HMS_MITTEY; y>=0; y--) /* jede Zeile der Matrizen wird initialisiert */ { feld[x][y]=0; /* alle Labyrinthfelder werden als betretbar markiert */ mauern[x][y]=0; /* kein Feld ist zuerst von Mauern umgeben */ } while (bewege_hms(hms,1)) x=hms_drop(hms,hms_load(hms)); /* solange 'bewege_hms' einen Wert ungleich Null zurueckliefert; also solange noch Mais einzusammeln ist, laesst der Hamster den im Maul befindlichen Mais ueber dem Ausgangsfeld (seinem Erdloch) fallen */ x=hms_drop(hms,hms_load(hms)); /* wenn kein Mais mehr einzusammeln ist, muss der Ham- ster lediglich noch den restlichen Mais in seinem Maul fallen lassen... */ }/* ...und damit ist er dann fuer den Winter geruestet */