{ 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.