diff --git a/dataUnit.pas b/dataUnit.pas new file mode 100644 index 0000000..c7b08fc --- /dev/null +++ b/dataUnit.pas @@ -0,0 +1,138 @@ + +Unit dataUnit; + +Interface + +type + TMoverType = (glider, walker, pusher); + TMoverDir = (up, left, down, right); + +Const + maxHeight = 20; + maxWidth = 40; + empty = '.'; + man = '&'; + 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']; + LeftMovers = ['l', 'L', '<']; + RightMovers = ['r', 'R', '>']; + walkable = [empty,'H',gem]; + magnets = ['N','Z']; + pushable = ['M','0','c','a'] + + magnets + gliders + walkers + pushers; + slipery = ['@','0',gem] + gliders; + enemies = ['%']; + + + +Type Position = Record + col: integer; + row: integer; +End; + +Type GameState = Record + ID : string; + map : array [1..maxHeight, 1..maxWidth] Of char; + mapHeight : integer; + mapWidth : integer; + manRow : integer; + manCol : integer; + goal : integer; + enemy : array [1..10] Of Position; + numEnemies : integer; + clue : string; + next : string; +End; + +function readLevel(levelFile, levelID:String; var succes: Boolean): GameState; + +Implementation + +Uses sysutils; + +function convert(x: Char):Char; +Begin + Case x of + 'K': Exit(man); + ' ': Exit(empty); + '5': Exit('#'); + '1'..'4','6'..'9': Exit('@'); + 'e': Exit('H'); + 'b': Exit('M'); + 's': Exit('Z'); + '~','E','C','[': Exit('%'); + 'B': Exit('0'); + else Exit(x); + End; +End; + +function readLevel(levelFile, levelID:String; var succes: Boolean): GameState; + +Var + aFile: textfile; + thisID: String; + row, col: integer; + x :Char; +Begin + succes := false; + Assign(aFile,levelFile); + Reset(aFile); + readLn(aFile, thisID); + If length(levelID) <> 0 then + repeat + If EOF(aFile) then + Exit; + readLn(aFile, thisID); + until compareStr(thisID,levelID) = 0 + else + readLn(aFile, thisID); + readLevel.ID := thisID; + readLn(aFile, readLevel.clue); + readLn(aFile); + readLevel.mapHeight := 20; + readLevel.mapWidth := 30; + readLevel.numEnemies := 0; + readLevel.goal := 0; + For row := 1 To readLevel.mapHeight Do + Begin + For col:= 1 To readLevel.mapWidth Do + Begin + read(aFile, x); + readLevel.map[row,col] := convert(x); + Case readLevel.map[row,col] Of + man: + Begin + readLevel.manRow := row; + readLevel.manCol := col; + End; + '%': + Begin + inc (readLevel.numEnemies); + readLevel.enemy[readLevel.numEnemies].col := col; + readLevel.enemy[readLevel.numEnemies].row := row; + End; + gem: inc(readLevel.goal); + End; + End; + readLn(aFile); + End; + If not EOF(aFile) then + readLn(aFile,readLevel.next) + else + readLevel.next := ''; + Close(aFile); + succes := true; +End; + +End. + diff --git a/heroEnemy.pas b/heroEnemy.pas new file mode 100644 index 0000000..5c70784 --- /dev/null +++ b/heroEnemy.pas @@ -0,0 +1,103 @@ + +Unit heroEnemy; + +Interface + +Uses dataUnit, Math; + +Procedure moveMan(Var theGS:GameState;rowStep,colStep:integer); +Procedure moveEnemies(Var theGS:GameState); + +Implementation + +Procedure moveMan(Var theGS:GameState;rowStep,colStep:integer); + +Var + move: boolean = false; + nextTile: char; +Begin + nextTile := theGS.map[theGS.manRow+rowStep, theGS.manCol+colStep]; + (* Push the boulder *) + If (nextTile In pushable) And + (theGS.map[theGS.manRow+2*rowStep, theGS.manCol+2*colStep] = empty) Then + Begin + theGS.map[theGS.manRow+2*rowStep, theGS.manCol+2*colStep] := nextTile; + move := true; + End; + (* Move man *) + If move Or (nextTile In walkable) Then + Begin + (* Colect diamonds while where at it *) + If nextTile = '*' Then + dec(theGS.goal); + (* The moving *) + theGS.map[theGS.manRow, theGS.manCol] := empty; + theGS.manRow := theGS.manRow + rowStep; + theGS.manCol := theGS.manCol + colStep; + theGS.map[theGS.manRow, theGS.manCol] := man; + End; +End; + + +Procedure moveEnemies(Var theGS:GameState); + +Var + i, row, col, rowstep, colstep, tries: integer; +Begin + For i := 1 To theGS.numEnemies Do + Begin + col := theGS.enemy[i].col; + row := theGS.enemy[i].row; + rowstep := theGS.manRow - row; + colstep := theGS.manCol - col; + (* Figures out general direction. *) + If abs(rowstep) > abs(colstep) Then + colstep := 0 + Else If abs(colstep) > abs(rowstep) Then + rowstep := 0 + Else If random(2) = 0 Then + rowstep := 0 + Else + colstep := 0; + (* Restrict movement to vecinity. *) + rowstep := min(max(-1,rowstep),1); + colstep := min(max(-1,colstep),1); + (* Try to move there. *) + For tries := 4 Downto 1 Do + Begin + (* If there's an obstacle. *) + If theGS.map[row+rowstep, col+colstep] <> '.' Then + Begin + If random(1) = 0 then + colstep := -colstep + Else + rowstep := -rowstep; + If tries Mod 2 = 0 Then + Begin + (* Ol' swap trick *) + colstep := colstep + rowstep; + rowstep := colstep - rowstep; + colstep := colstep - rowstep; + End + End + Else + Begin + (* Move the enemy. *) + theGS.map[row+rowstep, col+colstep] := theGS.map[row,col]; + theGS.map[row,col] := empty; + col := col+colstep; + row := row+rowstep; + theGS.enemy[i].col := col; + theGS.enemy[i].row := row; + (* Attack man *) + If abs(col-theGS.manCol) + abs(row-theGS.manRow) <= 1 Then + Begin + theGS.goal := -1; + End; + break; + End; + End; + End; +End; + +End.