Compare commits

...

2 Commits

  1. 117
      dataUnit.pas
  2. 23
      gameUnit.pas
  3. 16
      heroEnemy.pas
  4. 225
      moversProc.pas
  5. 8
      toolsProc.pas

@ -3,34 +3,44 @@ Unit dataUnit;
Interface Interface
type Type
TMoverType = (glider, walker, pusher); TMoverType = (glider, walker, pusher);
TMoverDir = (up, left, down, right); TMoverDir = (up, left, down, right);
Const Const
maxHeight = 20; maxHeight = 20;
maxWidth = 40; maxWidth = 40;
empty = '.'; empty = '.';
man = '&'; man = '&';
gem = '*'; gem = '*';
movers : array[TMoverType, TMoverDir] of char = wall = '#';
( wallSlip = '@';
('^','>','v','<'), earth = 'H';
('u','r','d','l'), boulder = '0';
('U','R','D','L') block = 'M';
); magnetx = 'N';
gliders = ['^','>','v','<']; magnety = 'Z';
walkers = ['u','r','d','l']; turnerRight = 'a';
pushers = ['U','R','D','L']; turnerLeft = 'c';
UpMovers = ['u', 'U', '^']; monster = '%';
walkable = [empty,earth,gem];
movers : array[TMoverType, TMoverDir] Of char =
(
('^','>','v','<'),
('u','r','d','l'),
('U','R','D','L')
);
gliders = ['^','>','v','<'];
walkers = ['u','r','d','l'];
pushers = ['U','R','D','L'];
UpMovers = ['u', 'U', '^'];
DownMovers = ['d', 'D', 'v']; DownMovers = ['d', 'D', 'v'];
LeftMovers = ['l', 'L', '<']; LeftMovers = ['l', 'L', '<'];
RightMovers = ['r', 'R', '>']; RightMovers = ['r', 'R', '>'];
walkable = [empty,'H',gem]; magnets = [magnetx,magnety];
magnets = ['N','Z']; pushable = [block,boulder,turnerLeft,turnerRight]
pushable = ['M','0','c','a'] + magnets + gliders + walkers + pushers;
+ magnets + gliders + walkers + pushers; slipery = [wallSlip,boulder,gem] + gliders;
slipery = ['@','0',gem] + gliders;
enemies = ['%']; enemies = ['%'];
@ -54,47 +64,47 @@ Type GameState = Record
next : string; next : string;
End; End;
function readLevel(levelFile, levelID:String; var succes: Boolean): GameState; Function readLevel(levelFile, levelID:String; Var succes: Boolean): GameState;
Implementation Implementation
Uses sysutils; Uses sysutils;
function convert(x: Char):Char; Function convert(x: Char): Char;
Begin Begin
Case x of Case x Of
'K': Exit(man); 'K': Exit(man);
' ': Exit(empty); ' ': Exit(empty);
'5': Exit('#'); '5': Exit(wall);
'1'..'4','6'..'9': Exit('@'); '1'..'4','6'..'9': Exit(wallSlip);
'e': Exit('H'); 'e': Exit(earth);
'b': Exit('M'); 'b': Exit(block);
's': Exit('Z'); 's': Exit(magnety);
'~','E','C','[': Exit('%'); '~','E','C','[': Exit(monster);
'B': Exit('0'); 'B': Exit(boulder);
else Exit(x); Else Exit(x);
End; End;
End; End;
function readLevel(levelFile, levelID:String; var succes: Boolean): GameState; Function readLevel(levelFile, levelID:String; Var succes: Boolean): GameState;
Var Var
aFile: textfile; aFile: textfile;
thisID: String; thisID: String;
row, col: integer; row, col: integer;
x :Char; x : Char;
Begin Begin
succes := false; succes := false;
Assign(aFile,levelFile); Assign(aFile,levelFile);
Reset(aFile); Reset(aFile);
readLn(aFile, thisID); readLn(aFile, thisID);
If length(levelID) <> 0 then If length(levelID) <> 0 Then
repeat Repeat
If EOF(aFile) then If EOF(aFile) Then
Exit; Exit;
readLn(aFile, thisID); readLn(aFile, thisID);
until compareStr(thisID,levelID) = 0 Until compareStr(thisID,levelID) = 0
else Else
readLn(aFile, thisID); readLn(aFile, thisID);
readLevel.ID := thisID; readLevel.ID := thisID;
readLn(aFile, readLevel.clue); readLn(aFile, readLevel.clue);
@ -109,30 +119,29 @@ Begin
Begin Begin
read(aFile, x); read(aFile, x);
readLevel.map[row,col] := convert(x); readLevel.map[row,col] := convert(x);
Case readLevel.map[row,col] Of Case readLevel.map[row,col] Of
man: man:
Begin Begin
readLevel.manRow := row; readLevel.manRow := row;
readLevel.manCol := col; readLevel.manCol := col;
End; End;
'%': monster:
Begin Begin
inc (readLevel.numEnemies); inc (readLevel.numEnemies);
readLevel.enemy[readLevel.numEnemies].col := col; readLevel.enemy[readLevel.numEnemies].col := col;
readLevel.enemy[readLevel.numEnemies].row := row; readLevel.enemy[readLevel.numEnemies].row := row;
End; End;
gem: inc(readLevel.goal); gem: inc(readLevel.goal);
End; End;
End; End;
readLn(aFile); readLn(aFile);
End; End;
If not EOF(aFile) then If Not EOF(aFile) Then
readLn(aFile,readLevel.next) readLn(aFile,readLevel.next)
else Else
readLevel.next := ''; readLevel.next := '';
Close(aFile); Close(aFile);
succes := true; succes := true;
End; End;
End. End.

@ -1,15 +1,16 @@
Unit GameUnit; Unit GameUnit;
Interface Interface
Uses Uses
dataUnit; dataUnit;
Procedure playLevel(var theGS: dataUnit.GameState); Procedure playLevel(Var theGS: dataUnit.GameState);
Implementation Implementation
Uses Uses
crt, crt,
Math, Math,
heroEnemy, heroEnemy,
@ -18,7 +19,7 @@ moversProc;
Procedure writeMap(Var theGS: dataUnit.GameState); Procedure writeMap(Var theGS: dataUnit.GameState);
Var Var
col: integer; col: integer;
row: integer; row: integer;
Begin Begin
@ -31,9 +32,9 @@ Begin
End; End;
End; End;
Procedure playLevel(var theGS: dataUnit.GameState); Procedure playLevel(Var theGS: dataUnit.GameState);
Var Var
move: boolean; move: boolean;
Begin Begin
randomize; randomize;
@ -47,7 +48,7 @@ Begin
(* Player turn *) (* Player turn *)
Repeat Repeat
move := True; move := True;
Case readKey Of Case readKey Of
'i': moveMan(theGS, -1, 0); 'i': moveMan(theGS, -1, 0);
'j': moveMan(theGS, 0, -1); 'j': moveMan(theGS, 0, -1);
'k': moveMan(theGS, 1, 0); 'k': moveMan(theGS, 1, 0);
@ -67,11 +68,11 @@ Begin
writeMap(theGS); writeMap(theGS);
gotoxy(theGS.mapWidth Div 2 - 4, theGS.mapHeight Div 2); gotoxy(theGS.mapWidth Div 2 - 4, theGS.mapHeight Div 2);
If theGS.goal = 0 Then If theGS.goal = 0 Then
Begin Begin
Write('You Win!'); Write('You Win!');
End End
Else Else
Write('You Lose!'); Write('You Lose!');
gotoxy(1, theGS.mapHeight + 2); gotoxy(1, theGS.mapHeight + 2);
writeLn('Press ENTER to continue.'); writeLn('Press ENTER to continue.');
readLn; readLn;

@ -12,7 +12,7 @@ Implementation
Procedure moveMan(Var theGS:GameState;rowStep,colStep:integer); Procedure moveMan(Var theGS:GameState;rowStep,colStep:integer);
Var Var
move: boolean = false; move: boolean = false;
nextTile: char; nextTile: char;
Begin Begin
@ -27,8 +27,8 @@ Begin
(* Move man *) (* Move man *)
If move Or (nextTile In walkable) Then If move Or (nextTile In walkable) Then
Begin Begin
(* Colect diamonds while where at it *) (* Colect gems while where at it *)
If nextTile = '*' Then If nextTile = gem Then
dec(theGS.goal); dec(theGS.goal);
(* The moving *) (* The moving *)
theGS.map[theGS.manRow, theGS.manCol] := empty; theGS.map[theGS.manRow, theGS.manCol] := empty;
@ -41,7 +41,7 @@ End;
Procedure moveEnemies(Var theGS:GameState); Procedure moveEnemies(Var theGS:GameState);
Var Var
i, row, col, rowstep, colstep, tries: integer; i, row, col, rowstep, colstep, tries: integer;
Begin Begin
For i := 1 To theGS.numEnemies Do For i := 1 To theGS.numEnemies Do
@ -66,12 +66,12 @@ Begin
For tries := 4 Downto 1 Do For tries := 4 Downto 1 Do
Begin Begin
(* If there's an obstacle. *) (* If there's an obstacle. *)
If theGS.map[row+rowstep, col+colstep] <> '.' Then If theGS.map[row+rowstep, col+colstep] <> empty Then
Begin Begin
If random(1) = 0 then If random(1) = 0 Then
colstep := -colstep colstep := -colstep
Else Else
rowstep := -rowstep; rowstep := -rowstep;
If tries Mod 2 = 0 Then If tries Mod 2 = 0 Then
Begin Begin
(* Ol' swap trick *) (* Ol' swap trick *)

@ -1,151 +1,154 @@
unit moversProc;
interface Unit moversProc;
uses dataUnit; Interface
procedure moveMovers(var g: GameState); Uses dataUnit;
implementation Procedure moveMovers(Var g: GameState);
function turnMover(c: char; d: integer): char; Implementation
const
Function turnMover(c: char; d: integer): char;
Const
period = ord(high(TMoverDir))+1; period = ord(high(TMoverDir))+1;
var
Var
j, x: integer; j, x: integer;
i :TMoverType; i : TMoverType;
begin Begin
for i := low(TMoverType) to high(TMoverType) do For i := low(TMoverType) To high(TMoverType) Do
for j := ord(low(TMoverDir)) to ord(high(TMoverDir)) do For j := ord(low(TMoverDir)) To ord(high(TMoverDir)) Do
if c = movers[i, TMoverDir(j)] then If c = movers[i, TMoverDir(j)] Then
begin Begin
x := (j+d) mod period; x := (j+d) Mod period;
Exit(movers[i, TMoverDir(x)]); Exit(movers[i, TMoverDir(x)]);
end; End;
Exit(c); Exit(c);
end; End;
procedure rotateStep(var rstep, cstep: integer; clockWise: boolean); Procedure rotateStep(Var rstep, cstep: integer; clockWise: boolean);
begin Begin
cstep := cstep + rstep; cstep := cstep + rstep;
rstep := cstep - rstep; rstep := cstep - rstep;
cstep := cstep - rstep; cstep := cstep - rstep;
if clockWise then If clockWise Then
cstep := -cstep cstep := -cstep
else Else
rstep := -rstep; rstep := -rstep;
end; End;
Procedure moveMover(Var g: GameState; row, col, rstep, cstep: integer);
procedure moveMover(var g: GameState; row, col, rstep, cstep: integer); Var
var rns : integer = 0;
rns : integer = 0; cns : integer = 0;
cns : integer = 0; Begin
begin
(* I don't move if I'm cought by a magnet *) (* I don't move if I'm cought by a magnet *)
If (rstep <> 0) and (g.map[row - rstep, col] = 'Z') then Exit; If (rstep <> 0) And (g.map[row - rstep, col] = magnety) Then Exit;
If (cstep <> 0) and (g.map[row, col - cstep] = 'N') then Exit; If (cstep <> 0) And (g.map[row, col - cstep] = magnetx) Then Exit;
(* I don't move beyond the map *) (* I don't move beyond the map *)
if (col + cstep > g.mapWidth) or (col + cstep < 1) or If (col + cstep > g.mapWidth) Or (col + cstep < 1) Or
(row + rstep > g.mapHeight) or (row + rstep < 1) then (row + rstep > g.mapHeight) Or (row + rstep < 1) Then
begin Begin
if g.map[row,col] in pushers then If g.map[row,col] In pushers Then
g.map[row, col] := turnMover(g.map[row,col], 2); g.map[row, col] := turnMover(g.map[row,col], 2);
Exit; Exit;
end; End;
(* Turners turn me *) (* Turners turn me *)
case g.map[row + rstep, col + cstep] of Case g.map[row + rstep, col + cstep] Of
'a': 'a':
begin Begin
g.map[row, col] := turnMover(g.map[row,col], 1); g.map[row, col] := turnMover(g.map[row,col], 1);
rotateStep(rstep, cstep, True); rotateStep(rstep, cstep, True);
end; End;
'c': 'c':
begin Begin
g.map[row, col] := turnMover(g.map[row,col], -1); g.map[row, col] := turnMover(g.map[row,col], -1);
rotateStep(rstep, cstep, False); rotateStep(rstep, cstep, False);
end; End;
end; End;
(* Simple movement *) (* Simple movement *)
if g.map[row + rstep, col + cstep] = empty then If g.map[row + rstep, col + cstep] = empty Then
begin Begin
g.map[row + rstep, col + cstep] := g.map[row,col]; g.map[row + rstep, col + cstep] := g.map[row,col];
g.map[row, col] := empty; g.map[row, col] := empty;
Exit; Exit;
end; End;
(* Pushers turn around and push pushables *) (* Pushers turn around and push pushables *)
if (g.map[row,col] in pushers) then If (g.map[row,col] In pushers) Then
begin Begin
if (g.map[row + rstep, col + cstep] in pushable) and If (g.map[row + rstep, col + cstep] In pushable) And
(g.map[row + 2 * rstep, col + 2 * cstep] = empty) then (g.map[row + 2 * rstep, col + 2 * cstep] = empty) Then
begin Begin
g.map[row + 2 * rstep, col + 2 * cstep] := g.map[row + rstep, col + cstep]; g.map[row + 2 * rstep, col + 2 * cstep] := g.map[row + rstep, col + cstep];
g.map[row + rstep, col + cstep] := empty; g.map[row + rstep, col + cstep] := empty;
end; End;
g.map[row, col] := turnMover(g.map[row,col], 2); g.map[row, col] := turnMover(g.map[row,col], 2);
Exit; Exit;
end; End;
(* Gliders slip on slipery things*) (* Gliders slip on slipery things*)
if (g.map[row,col] in gliders) and If (g.map[row,col] In gliders) And
(g.map[row + rstep, col + cstep] in slipery) then (g.map[row + rstep, col + cstep] In slipery) Then
begin Begin
if cstep <> 0 then If cstep <> 0 Then
rns := 2 * random(1) - 1 rns := 2 * random(1) - 1
else Else
cns := 2 * random(1) - 1; cns := 2 * random(1) - 1;
if (g.map[row + rns, col + cns] = empty) and If (g.map[row + rns, col + cns] = empty) And
(g.map[row + rstep + rns, col + cstep + cns] = empty) then (g.map[row + rstep + rns, col + cstep + cns] = empty) Then
begin Begin
g.map[row + rstep + rns, col + cstep + cns] := g.map[row,col]; g.map[row + rstep + rns, col + cstep + cns] := g.map[row,col];
g.map[row, col] := empty; g.map[row, col] := empty;
end End
else if (g.map[row - rns, col - cns] = empty) and Else If (g.map[row - rns, col - cns] = empty) And
(g.map[row + rstep - rns, col + cstep - cns] = empty) then (g.map[row + rstep - rns, col + cstep - cns] = empty) Then
begin Begin
g.map[row + rstep - rns, col + cstep - cns] := g.map[row,col]; g.map[row + rstep - rns, col + cstep - cns] := g.map[row,col];
g.map[row, col] := empty; g.map[row, col] := empty;
end; End;
end; End;
end; End;
procedure moveMovers(var g: GameState); Procedure moveMovers(Var g: GameState);
var Var
idx, row, col, Width, Height: integer; idx, row, col, Width, Height: integer;
begin Begin
Width := g.mapWidth; Width := g.mapWidth;
Height := g.mapHeight; Height := g.mapHeight;
for idx := 0 to Height * Width - 1 do For idx := 0 To Height * Width - 1 Do
begin Begin
(* for up movers *) (* for up movers *)
row := idx div Width + 1; row := idx Div Width + 1;
col := idx mod Width + 1; col := idx Mod Width + 1;
if (g.map[row, col] in UpMovers) then If (g.map[row, col] In UpMovers) Then
moveMover(g, row, col, -1, 0); moveMover(g, row, col, -1, 0);
(* for left movers *) (* for left movers *)
col := idx div Height + 1; col := idx Div Height + 1;
row := idx mod Height + 1; row := idx Mod Height + 1;
if (g.map[row, col] in LeftMovers) then If (g.map[row, col] In LeftMovers) Then
moveMover(g, row, col, 0, -1); moveMover(g, row, col, 0, -1);
(* for down movers *) (* for down movers *)
row := Height - idx div Width + 1; row := Height - idx Div Width + 1;
col := Width - idx mod Width + 1; col := Width - idx Mod Width + 1;
if (g.map[row, col] in DownMovers) then If (g.map[row, col] In DownMovers) Then
moveMover(g, row, col, 1, 0); moveMover(g, row, col, 1, 0);
(* for Right movers *) (* for Right movers *)
col := Width - idx div Height + 1; col := Width - idx Div Height + 1;
row := Height - idx mod Height + 1; row := Height - idx Mod Height + 1;
if (g.map[row, col] in RightMovers) then If (g.map[row, col] In RightMovers) Then
moveMover(g, row, col, 0, 1); moveMover(g, row, col, 0, 1);
end; End;
end; End;
end. End.

@ -22,7 +22,7 @@ End;
Procedure doMagnet(Var g:GameState); Procedure doMagnet(Var g:GameState);
Var Var
row, col, i, s: integer; row, col, i, s: integer;
rstep: integer = 0; rstep: integer = 0;
cstep: integer = 0; cstep: integer = 0;
@ -30,9 +30,9 @@ Begin
For row := 1 To g.mapHeight Do For row := 1 To g.mapHeight Do
For col := 1 To g.mapWidth Do For col := 1 To g.mapWidth Do
Begin Begin
Case g.map[row,col] Of Case g.map[row,col] Of
'N': cstep := 1; magnetx: cstep := 1;
'Z': rstep := 1; magnety: rstep := 1;
Else continue; Else continue;
End; End;
For i := 0 To 1 Do For i := 0 To 1 Do

Loading…
Cancel
Save