222 lines
6.6 KiB
Plaintext
222 lines
6.6 KiB
Plaintext
{
|
||
Note that this code makes free use of the dreaded GOTO command.
|
||
}
|
||
VAR
|
||
msecs, bonusTimeTicks, moveInterval, x, y : INTEGER;
|
||
ch : CHAR;
|
||
rockPtr : RockPointerType;
|
||
|
||
LABEL
|
||
restartGame, restartLevel, newLevel;
|
||
|
||
BEGIN { MAIN }
|
||
dispensers := NIL; { initialize our linked lists for dispenser }
|
||
m.Rocks := NIL; { and rocks }
|
||
lastScore := -1;
|
||
playSpeed := 1;
|
||
ReadDataFile;
|
||
|
||
restartGame:
|
||
|
||
m.LadsRemaining := 5;
|
||
m.Level := 1;
|
||
m.Score := 0;
|
||
levelCycle := 1;
|
||
displayLevel := 1;
|
||
nextNewLad := 100;
|
||
CursOn;
|
||
Randomize;
|
||
MainMenu;
|
||
moveInterval := ReadmsWait[playSpeed];
|
||
ClrScr;
|
||
CursOff;
|
||
|
||
newLevel:
|
||
|
||
{ Load a level and show it }
|
||
LoadMap(ladXY, dispensers, numDispensers);
|
||
|
||
restartLevel:
|
||
|
||
m.RemainingBonusTime := m.InitialBonusTime - 2 * (levelCycle - 1);
|
||
InitActor(lad, ALAD, ladXY);
|
||
DisperseRocks;
|
||
|
||
{ Show the initial map on screen }
|
||
DrawMap;
|
||
msecs := 0;
|
||
bonusTimeTicks := 0;
|
||
|
||
WHILE TRUE DO BEGIN
|
||
|
||
Delay(1);
|
||
msecs := Succ(msecs);
|
||
IF msecs >= moveInterval THEN BEGIN
|
||
{ move the Lad and rocks every X milliseconds }
|
||
msecs := 0;
|
||
bonusTimeTicks := bonusTimeTicks + moveInterval;
|
||
IF bonusTimeticks >= BonusTimeDecInterval THEN BEGIN
|
||
{ every 3 seconds, decrement the bonus time/time remaining value }
|
||
bonusTimeTicks := bonusTimeTicks - BonusTimeDecInterval;;
|
||
m.RemainingBonusTime := Pred(m.RemainingBonusTime);
|
||
GotoXY(74, 21);
|
||
Write(m.RemainingBonusTime : 2);
|
||
IF m.RemainingBonusTime <=0 THEN BEGIN
|
||
{ died: do the animation and check if we still have lives left }
|
||
IF LadDeath THEN
|
||
GOTO restartLevel;
|
||
GOTO restartGame;
|
||
END;
|
||
END;
|
||
|
||
IF m.AnyRocksPending THEN BEGIN
|
||
{ pending rocks? see if it's time to start moving }
|
||
rockPtr := m.Rocks;
|
||
m.AnyRocksPending := FALSE;
|
||
WHILE rockPtr <> NIL DO BEGIN
|
||
IF (rockPtr^.Dir = PENDING) THEN
|
||
IF (Random(10) = 0) THEN
|
||
rockPtr^.DirRequest := FALLING
|
||
ELSE
|
||
m.AnyRocksPending := TRUE;
|
||
rockPtr := rockPtr^.Next;
|
||
END;
|
||
END;
|
||
|
||
{ Move the lad according to players wishes }
|
||
IF (lad.Dir <> STOPPED) OR (lad.DirRequest <> NONE) THEN BEGIN
|
||
x := lad.X; y := lad.Y;
|
||
GotoXY(x, y); Write(m.Field[y][x]);
|
||
MoveActor(lad);
|
||
GotoXY(lad.X, lad.Y); Write(lad.Ch);
|
||
IF (x <> lad.X) AND (y = lad.Y) THEN BEGIN
|
||
{ get rid of disappearing flooring }
|
||
IF m.Field[y + 1][x] = '-' THEN BEGIN
|
||
m.Field[y + 1][x] := ' ';
|
||
GotoXY(x, y + 1); Write(' ');
|
||
END;
|
||
END;
|
||
|
||
CASE m.Field[lad.Y][lad.X] OF
|
||
|
||
'$' : BEGIN { at the Gold: level done }
|
||
UpdateScore(ScoreMoney);
|
||
displayLevel := Succ(displayLevel);
|
||
IF (m.Level > levelCycle) OR (m.Level = NumLevels) THEN BEGIN
|
||
{ done with current cycle, recycle to 1st level }
|
||
m.Level := 1;
|
||
levelCycle := SUCC(levelCycle);
|
||
END ELSE BEGIN
|
||
m.Level := Succ(m.Level);
|
||
END;
|
||
GOTO newLevel;
|
||
END;
|
||
|
||
'^': BEGIN { death by fire }
|
||
IF LadDeath THEN
|
||
GOTO restartLevel;
|
||
GOTO restartGame;
|
||
END;
|
||
|
||
'&': BEGIN
|
||
{ found a statue, adjust the score, remove the statue }
|
||
UpdateScore(ScoreStatue);
|
||
m.Field[lad.Y][lad.X] := ' ';
|
||
END;
|
||
|
||
'.': BEGIN {trampoline: choose a random direction }
|
||
CASE Random(5) OF
|
||
0: BEGIN
|
||
lad.Dir := LEFT;
|
||
lad.DirRequest := NONE;
|
||
lad.JumpStep := 0;
|
||
END;
|
||
1: BEGIN
|
||
lad.Dir := RIGHT;
|
||
lad.DirRequest := NONE;
|
||
lad.JumpStep := 0;
|
||
END;
|
||
2: BEGIN
|
||
lad.Dir := JUMPUP;
|
||
lad.DirRequest := STOPPED;
|
||
lad.JumpStep := 1;
|
||
END;
|
||
3: BEGIN
|
||
lad.Dir := JUMPLEFT;
|
||
lad.DirRequest := LEFT;
|
||
lad.JumpStep := 1;
|
||
END;
|
||
4: BEGIN
|
||
lad.Dir := JUMPRIGHT;
|
||
lad.DirRequest := RIGHT;
|
||
lad.JumpStep := 1;
|
||
END;
|
||
END;
|
||
END;
|
||
END;
|
||
END; { of Lad movement handler -------------------------- }
|
||
|
||
{ Move the rock(s) }
|
||
rockPtr := m.Rocks;
|
||
WHILE rockPtr <> NIL DO BEGIN
|
||
{ Don't draw the rock if it's pending }
|
||
IF rockPtr^.Dir <> PENDING THEN BEGIN
|
||
IF Collision(rockPtr) THEN
|
||
IF LadDeath THEN
|
||
GOTO restartLevel
|
||
ELSE
|
||
GOTO restartGame;
|
||
x := rockPtr^.X;
|
||
y := rockPtr^.Y;
|
||
GotoXY(x, y);
|
||
Write(m.Field[y][x]);
|
||
END;
|
||
MoveActor(rockPtr^);
|
||
{ Don't draw the rock if it's pending }
|
||
IF rockPtr^.Dir <> PENDING THEN BEGIN
|
||
IF Collision(rockPtr) THEN
|
||
IF LadDeath THEN
|
||
GOTO restartlevel
|
||
ELSE
|
||
GOTO restartGame;
|
||
GotoXY(rockPtr^.X, rockPtr^.Y);
|
||
Write(rockPtr^.Ch);
|
||
END;
|
||
rockPtr := rockPtr^.Next;
|
||
END; { of rock movement handler ------------------------- }
|
||
{ end of tick handler =================================== }
|
||
END;
|
||
IF KeyPressed THEN BEGIN
|
||
Read(Kbd, ch);
|
||
ch := UpCase(ch);
|
||
IF ch = leftKey THEN BEGIN
|
||
lad.DirRequest := LEFT
|
||
END ELSE IF ch = rightKey THEN BEGIN
|
||
lad.DirRequest := RIGHT
|
||
END ELSE IF ch = upKey THEN BEGIN
|
||
lad.DirRequest := UP
|
||
END ELSE IF ch = downKey THEN BEGIN
|
||
lad.DirRequest := DOWN
|
||
END ELSE IF ch = ' ' THEN BEGIN
|
||
lad.DirRequest := JUMP;
|
||
END ELSE IF ch = #$1B THEN BEGIN
|
||
CursOn;
|
||
GotoXY(1, 23); Write('Type RETURN to continue: ');
|
||
REPEAT
|
||
WHILE NOT KeyPressed DO;
|
||
Read(Kbd, ch);
|
||
UNTIL ch IN [#$0D, #$03];
|
||
IF ch = #$03 THEN { ^C goes back to main menu }
|
||
GOTO restartGame;
|
||
GotoXY(1, 23); ClrEOL;
|
||
CursOff;
|
||
END ELSE IF ch = #$03 THEN BEGIN
|
||
GOTO restartGame
|
||
END ELSE BEGIN
|
||
lad.DirRequest := STOPPED
|
||
END;
|
||
END; { of keypress handler ================================ }
|
||
END;
|
||
END.
|
||
|