home *** CD-ROM | disk | FTP | other *** search
- (* ------------------------------------------------------ *)
- (* EXPKLUG.PAS *)
- (* Strategiespiel in Turbo Pascal *)
- (* erweiterte Version: "The Intelligent Remix" *)
- (* (c) 1991 Patrick Filipaj & TOOLBOX *)
- (* Erweiterungen von Gerald Arend *)
- (* ------------------------------------------------------ *)
- PROGRAM Explode_Klug;
- {$A+,B-,D-,E-,F-,G-,I-,L-,N-,O-,R-,S-,V-,X+}
- {$M 16384,0,0}
-
- USES
- Crt, Dos;
-
- TYPE
- Location = RECORD
- x, y : SHORTINT;
- END;
- Zelle = RECORD
- Farbe : BYTE;
- Wert : BYTE;
- END;
- Verbund = ARRAY[-1..6, -1..6] OF Zelle;
- Spieler = PROCEDURE(Zahl : BYTE); { Prozeduraler Typ }
-
- VAR
- Feld : Verbund;
- Position : ARRAY[1..2] OF Location;
- Name : ARRAY[1..2] OF STRING[17];
- SpielerA, SpielerB : Spieler;
- Winner : STRING;
- AltAttr : BYTE;
-
- CONST
- Mon = $B800; { Startadresse für Farbbildschirmspeicher, }
- { für Hercules-Karte ändern in Mon = $B000 }
- Farbe: ARRAY[0..3] OF BYTE = { Attribute }
- (White, Yellow, Black OR Green SHL 4, LightGray);
-
- PROCEDURE Cursor(Visible : BOOLEAN);
- VAR
- Regs : Registers;
- BEGIN
- Regs.AH := 1;
- Regs.CH := 6;
- IF Visible THEN Regs.CL := 7 ELSE Regs.CL := 0;
- Intr(16, Regs);
- END;
-
- PROCEDURE Ende;
- BEGIN
- Cursor(TRUE);
- TextAttr := AltAttr;
- WriteLn;
- ClrScr;
- Halt;
- END;
-
- PROCEDURE SpielBeginn;
- VAR
- n : BYTE;
- BEGIN
- TextAttr := Farbe[0];
- ClrScr;
- GotoXY(18, 1);
- WriteLn('* * * * * * * * * * * * * * * * * * * * * *');
- GotoXY(18, 2);
- WriteLn('* * * * E X P L O D E * * * *');
- GotoXY(18, 3);
- WriteLn('* * * * "Klügere" Version mit zwei * * * *');
- GotoXY(18, 4);
- WriteLn('* * * * verschiedenen Algorithmen * * * *');
- GotoXY(18, 5);
- WriteLn('* * * * * * * * * * * * * * * * * * * * * *');
- GotoXY(18, 8);
- WriteLn('* * (c) 1991 Patrick Filipaj & toolbox * *');
- GotoXY(18, 17);
- Write('Computerspieler: "PC1" oder "PC2" eingeben');
- GotoXY(18, 14);
- Write('Name Spieler A: '); ReadLn(Name[1]);
- GotoXY(18, 15);
- Write('Name Spieler B: '); ReadLn(Name[2]);
- FOR n := 1 TO Length(Name[1]) DO
- Name[1][n] := UpCase(Name[1][n]);
- FOR n := 1 TO Length(Name[2]) DO
- Name[2][n] := UpCase(Name[2][n]);
- END;
-
- PROCEDURE InitBildschirm; { Spielfeld aufbauen }
- VAR
- x, y : BYTE;
- BEGIN
- TextAttr := Farbe[0];
- ClrScr;
- GotoXY(28, 3);
- WriteLn('> > E X P L O D E < <');
- TextAttr := Farbe[3];
- FOR y := 0 TO 6 DO BEGIN
- GotoXY(28, 2 * y + 5);
- FOR x := 1 TO 25 DO Write(#196);
- END;
- FOR x := 0 TO 6 DO BEGIN
- FOR y := 5 TO 17 DO BEGIN
- GotoXY(x * 4 + 28, y);
- IF (y MOD 2) = 1 THEN Write(#197)
- ELSE Write(#179);
- END;
- END;
- END;
-
- PROCEDURE InitTabelle(VAR Tabelle : Verbund);
- VAR
- i, j : SHORTINT;
- BEGIN
- FOR i := -1 TO 6 DO BEGIN
- FOR j := -1 TO 6 DO BEGIN
- Tabelle[i, j].Wert := 0;
- Tabelle[i, j].Farbe := Farbe[3];
- END;
- END;
- END;
-
- FUNCTION Total(Tabelle : Verbund; Color : BYTE) : BYTE;
- { zählt die Anzahl der mit einer Farbe besetzten Felder }
- VAR
- x, y, c : SHORTINT;
- BEGIN
- c := 0;
- FOR x := 0 TO 5 DO BEGIN
- FOR y := 0 TO 5 DO BEGIN
- IF Tabelle[x, y].Farbe = Color THEN Inc(c);
- END;
- END;
- Total := c;
- END; { FUNCTION Total }
-
- FUNCTION PointTotal(Tabelle : Verbund; Color : BYTE) : BYTE;
- { addiert die Höhe aller Felder einer Farbe }
- VAR
- x, y, c : BYTE;
- BEGIN
- c := 0;
- FOR x := 0 TO 5 DO BEGIN
- FOR y := 0 TO 5 DO BEGIN
- IF Tabelle[x, y].Farbe = Color THEN
- Inc(c, Tabelle[x, y].Wert);
- END;
- END;
- PointTotal := c;
- END; { PROCEDURE PointTotal }
-
- PROCEDURE ShowTabelle; { alle Feldwerte anzeigen }
- VAR
- x, y : BYTE;
- BEGIN
- FOR x := 0 TO 5 DO BEGIN
- FOR y := 0 TO 5 DO BEGIN
- TextAttr := Feld[x, y].Farbe;
- GotoXY(4 * x + 30, 2 * y + 6);
- IF Feld[x, y].Wert > 0 THEN
- Write(Feld[x, y].Wert)
- ELSE Write(#249);
- END;
- END;
- GotoXY(79, 25);
- END; { PROCEDURE ShowTabelle }
-
- PROCEDURE Blink(x, y : BYTE);
- { Anzeige des inversen Eingabecursors }
- BEGIN
- Mem[Mon:2 * (80 * (5 + 2 * y) + 29 + 4 * x) + 1] :=
- Mem[Mon:2 * (80 * (5 + 2 * y) + 29 + 4 * x) + 1] XOR 192;
- END; { PROCEDURE Blink }
-
- PROCEDURE Eingabe(CursorNummer : BYTE);
- { fragt nach neuer Cursorposition, bei <ESC> Spielende }
- VAR
- x, y : SHORTINT;
- Chr : CHAR;
- BEGIN
- WHILE KeyPressed DO ReadKey;
- x := Position[CursorNummer].x;
- y := Position[CursorNummer].y;
- REPEAT
- Blink(x, y);
- REPEAT
- REPEAT UNTIL KeyPressed;
- Chr := ReadKey;
- IF Chr = #0 THEN Chr := ReadKey;
- UNTIL Chr IN [#13, #72, #75, #77, #80, #27];
- Blink(x, y);
- CASE Chr OF
- #72 : Dec(y); #75 : Dec(x); #77 : Inc(x);
- #80 : Inc(y); #27 : Ende;
- END;
- IF x > 5 THEN x := 5;
- IF x < 0 THEN x := 0;
- IF y < 0 THEN y := 0;
- IF y > 5 THEN y := 5;
- Position[CursorNummer].x := x;
- Position[CursorNummer].y := y;
- UNTIL Chr = #13;
- END;
-
- PROCEDURE PutText(s1, s2 : STRING; TextFarbe : BYTE);
- { Hilfsprozedur für die Ausgabe von Spielkommentaren }
- VAR
- i : INTEGER;
- BEGIN
- TextAttr := Farbe[0];
- GotoXY(1, 21); ClrEol;
- GotoXY(1, 22); ClrEol;
- TextAttr := TextFarbe;
- GotoXY(40 - Length(s1) DIV 2, 22);
- Write(s1);
- GotoXY(40 - Length(s1) DIV 2, 23);
- Write(s2);
- END;
-
- FUNCTION SpielEnde : BOOLEAN;
- { Gewinneranzeige und Endabfrage }
- VAR
- s : STRING;
- BEGIN
- s := 'Der Gewinner ist ' + Winner + ' !!';
- PutText(s, 'Noch ein Spiel? <J>/<N>', Farbe[3]);
- REPEAT UNTIL KeyPressed;
- SpielEnde := NOT(UpCase(ReadKey) IN ['J', 'Y']);
- END;
-
- FUNCTION NoMoreExplosion(VAR Tabelle : Verbund;
- Virtuell : BOOLEAN) : BOOLEAN;
- VAR
- NoChange : BOOLEAN;
- x, y : BYTE;
-
- PROCEDURE Erhohen; { Nachbarstapel bei Explosion erhöhen }
- BEGIN
- Inc(Tabelle[x + 1, y].Wert);
- Tabelle[x + 1, y].Farbe := Tabelle[x, y].Farbe;
- Inc(Tabelle[x - 1, y].Wert);
- Tabelle[x - 1, y].Farbe := Tabelle[x, y].Farbe;
- Inc(Tabelle[x, y + 1].Wert);
- Tabelle[x, y + 1].Farbe := Tabelle[x, y].Farbe;
- Inc(Tabelle[x, y - 1].Wert);
- Tabelle[x, y - 1].Farbe := Tabelle[x, y].Farbe;
- END;
-
- PROCEDURE Is_Explosion(Subtraktor : SHORTINT);
- { checken, ob Feld explodiert }
- BEGIN
- IF Tabelle[x, y].Wert >= Subtraktor THEN BEGIN
- Erhohen;
- Tabelle[x, y].Wert := Tabelle[x, y].Wert - Subtraktor;
- IF Tabelle[x, y].Wert = 0 THEN
- Tabelle[x, y].Farbe := Farbe[3];
- NoChange := FALSE;
- IF NOT Virtuell THEN BEGIN
- ShowTabelle;
- Sound(100);
- Delay(1);
- NoSound;
- Delay(300);
- END;
- END;
- END;
-
- BEGIN { Start NoMoreExplosion }
- NoChange := TRUE;
- FOR x := 1 TO 4 DO
- FOR y := 1 TO 4 DO Is_Explosion(4);
- x := 0;
- FOR y := 1 TO 4 DO Is_Explosion(3);
- y := 0;
- Is_Explosion(2);
- y := 5;
- Is_Explosion(2);
- x := 5;
- FOR y := 1 TO 4 DO Is_Explosion(3);
- y := 0;
- Is_Explosion(2);
- y := 5;
- Is_Explosion(2);
- y := 0;
- FOR x := 1 TO 4 DO Is_Explosion(3);
- y := 5;
- FOR x := 1 TO 4 DO Is_Explosion(3);
- NoMoreExplosion := NoChange;
- END;
-
- PROCEDURE Explosion(VAR Tabelle : Verbund);
- { Hauptschleife für Explosionsabfrage }
- BEGIN
- REPEAT
- IF Total(Tabelle, Farbe[1]) = 0 THEN Winner := Name[2];
- IF Total(Tabelle, Farbe[2]) = 0 THEN Winner := Name[1];
- UNTIL (Winner <> '') OR (NoMoreExplosion(Tabelle, FALSE));
- ShowTabelle;
- Delay(500);
- END;
-
- PROCEDURE VirExplosion(VAR Tabelle : Verbund);
- { "virtuelle" Explosion für Zugvorausberechnung des PCs }
- BEGIN
- REPEAT
- UNTIL NoMoreExplosion(Tabelle, TRUE)
- OR (Total(Tabelle, Farbe[1]) = 0)
- OR (Total(Tabelle, Farbe[2]) = 0);
- END;
-
- {$F+}PROCEDURE Computer1(Zahl : BYTE);{$F-}
- { Computerspieler zieht: Algorithmus aus toolbox 7/8'91 }
- VAR
- VirFeld : Verbund;
- x, y, MaxX, MaxY, MaxWert, Tot : BYTE;
- BEGIN
- MaxWert := 0;
- MaxX := 2;
- MaxY := 2;
- TextAttr := Farbe[Zahl];
- GotoXY(1, 25);
- PutText('Standard-Algorithmus setzt!', '', Farbe[Zahl]);
- FOR x := 0 TO 5 DO BEGIN
- FOR y := 0 TO 5 DO BEGIN
- VirFeld := Feld;
- IF VirFeld[x,y].Farbe IN [Farbe[Zahl], Farbe[3]] THEN
- BEGIN
- Inc(VirFeld[x, y].Wert);
- VirFeld[x, y].Farbe := Farbe[Zahl];
- VirExplosion(VirFeld);
- Tot := PointTotal(VirFeld, Farbe[Zahl]);
- IF (Tot > MaxWert) OR
- ((Tot = MaxWert) AND (Random > 0.75)) THEN BEGIN
- MaxWert := Tot;
- MaxX := x;
- MaxY := y;
- END;
- END;
- END;
- END;
- Position[Zahl].x := MaxX;
- Position[Zahl].y := MaxY;
- Blink(MaxX, MaxY); { Zug anzeigen }
- Delay(1200);
- Blink(MaxX, MaxY);
- Inc(Feld[MaxX, MaxY].Wert);
- Feld[MaxX, MaxY].Farbe := Farbe[Zahl];
- ShowTabelle;
- Explosion(Feld);
- END;
-
- {$F+}PROCEDURE Computer2(Zahl : BYTE); {$F-}
- { Computerspieler zieht: Verbesserte Version des }
- { Computer-Algorithmus aus dem Heft }
- TYPE
- StackType = RECORD
- x, y : BYTE;
- END;
- VAR
- x, y, r : BYTE;
- MinWert : BYTE;
- VirFeld : Verbund;
- Summe : ARRAY[0..5, 0..5] OF BYTE;
- Stack : ARRAY[1..36] OF StackType;
- StackPtr : BYTE;
-
- PROCEDURE MacheZug(Zahl : BYTE; Feld : Verbund);
- { Kernprozedur der Rechnerstrategie; diese Prozedur }
- { spielt einen virtuellen Zug für einen beliebigen }
- { Spieler durch }
- VAR
- x, y : BYTE;
- VirFeld : Verbund;
- Tot : BYTE;
- BEGIN
- FOR x := 0 TO 5 DO
- FOR y := 0 TO 5 DO BEGIN
- VirFeld := Feld; { Spielfeld kopieren }
- IF VirFeld[x,y].Farbe IN [Farbe[Zahl], Farbe[3]] THEN
- BEGIN
- { virtueller Zug, wenn das Feld vom Spieler besetzt ist }
- { oder noch unbelegt ist }
- Inc(VirFeld[x, y].Wert); { Feldwert erhöhen }
- VirFeld[x, y].Farbe := Farbe[Zahl]; { Farbe setzen }
- VirExplosion(VirFeld); { Check auf Explosionen }
- { Minimalauswertung }
- IF Feld[x, y].Farbe IN [Farbe[Zahl], Farbe[3]] THEN
- BEGIN
- Tot := PointTotal(VirFeld, Farbe[Zahl]);
- { Summierung des Resultats }
- IF Tot <= MinWert THEN
- MinWert := Tot;
- END;
- END; { FOR }
- END;
- END; { MacheZug }
-
- BEGIN
- TextAttr := Farbe[Zahl];
- GotoXY(1, 25);
- PutText('"Volon-Tier"-Algorithmus setzt!', '', Farbe[Zahl]);
-
- FOR x := 0 TO 5 DO
- FOR y := 0 TO 5 DO BEGIN
- Summe[x, y] := 255; { Feldoptimum löschen }
- VirFeld := Feld; { Spielfeld kopieren }
- IF VirFeld[x, y].Farbe IN [Farbe[Zahl], Farbe[3]] THEN
- BEGIN
- Inc(VirFeld[x, y].Wert); { eins erhöhen }
- VirFeld[x, y].Farbe := Farbe[Zahl]; { +ggf. färben }
- VirExplosion(VirFeld);
- MinWert := 255;
- MacheZug(Zahl XOR 3, VirFeld);
- { alle Züge des Gegners checken }
- Summe[x, y] := MinWert; { schlechtestes Ergebnis }
- { des Gegners speichern }
- END;
- END;
- { Auswertung der Tabelle "Total" }
- MinWert := 255;
- StackPtr := 0;
- FOR x := 0 TO 5 DO
- FOR y := 0 TO 5 DO
- IF Summe[x, y] <= MinWert THEN BEGIN
- IF Summe[x, y] < MinWert THEN
- StackPtr := 1;
- IF Summe[x, y] = MinWert THEN
- Inc(StackPtr);
- Stack[StackPtr].x := x;
- Stack[StackPtr].y := y;
- MinWert := Summe[x, y];
- END;
-
- r := Random(StackPtr) + 1;
- Position[Zahl].x := Stack[r].x;
- Position[Zahl].y := Stack[r].y;
- Blink(Stack[r].x, Stack[r].y); { Zug anzeigen }
- Delay(1200);
- Blink(Stack[r].x, Stack[r].y); { Zug anzeigen }
- Inc(Feld[Stack[r].x, Stack[r].y].Wert);
- Feld[Stack[r].x, Stack[r].y].Farbe := Farbe[Zahl];
- ShowTabelle;
- Explosion(Feld);
- END;
-
- {$F+}PROCEDURE Mensch(Zahl:BYTE);{$F-}
- { menschlicher Spieler zieht }
- BEGIN
- PutText(Name[Zahl] + ', Sie sind am Setzen!', '',
- Farbe[Zahl]);
- REPEAT
- Eingabe(Zahl);
- UNTIL Feld[Position[Zahl].x, Position[Zahl].y].Farbe
- IN [Farbe[Zahl],Farbe[3]];
- Inc(Feld[Position[Zahl].x, Position[Zahl].y].Wert);
- Feld[Position[Zahl].x, Position[Zahl].y].Farbe :=
- Farbe[Zahl];
- ShowTabelle;
- Delay(350);
- Explosion(Feld);
- END;
-
- BEGIN { Hauptprogramm }
- AltAttr := TextAttr;
- Randomize;
- SpielBeginn;
- SpielerA := Mensch;
- IF Name[1] = 'PC1' THEN SpielerA := Computer1;
- IF Name[1] = 'PC2' THEN SpielerA := Computer2;
- SpielerB := Mensch;
- IF Name[2] = 'PC1' THEN SpielerB := Computer1;
- IF Name[2] = 'PC2' THEN SpielerB := Computer2;
-
- REPEAT
- Position[1].x := 2; Position[1].y := 2;
- Position[2].x := 3; Position[2].y := 3;
- InitBildschirm;
- Cursor(FALSE);
- InitTabelle(Feld);
- ShowTabelle;
- Winner := '';
- SpielerA(1);
- Winner := '';
- REPEAT
- SpielerB(2);
- IF Winner = '' THEN SpielerA(1);
- UNTIL Winner <> '';
- UNTIL SpielEnde;
- Ende;
- END.
- (* ------------------------------------------------------ *)
- (* Ende von EXPKLUG.PAS *)
-