394 lines
11 KiB
Plaintext
394 lines
11 KiB
Plaintext
PROCEDURE Instructions;
|
||
BEGIN
|
||
ClrScr;
|
||
WriteLN;
|
||
WriteLN('You are a Lad trapped in a maze. Your mission is is to explore the');
|
||
WriteLN('dark corridors never before seen by human eyes and find hidden');
|
||
WriteLN('treasures and riches');
|
||
WriteLN;
|
||
WriteLN('You control Lad by typing the direction buttons and jumping by');
|
||
WriteLN('typing SPACE. But beware of the falaling rocks called Der rocks.');
|
||
WriteLN('You must find and grasp the treasures (shown as $) BEFORE the');
|
||
WriteLN('bonus time runs out.');
|
||
WriteLN;
|
||
WriteLN('A new Lad will be awarded for every 10,000 points.');
|
||
WriteLN('Extra points are awarded for touching the gold');
|
||
WriteLN('statues (shown as &). You will receive the bonus time points');
|
||
WriteLN('that are left when you have finished the level.');
|
||
WriteLN;
|
||
WriteLN('Type an ESCape to pause the egame.');
|
||
WriteLN;
|
||
WriteLN('Remember, there is more than one way to skin a cat. (Chum)');
|
||
WriteLN;
|
||
WriteLN('Good luck Lad.');
|
||
WriteLN;
|
||
WriteLN;
|
||
WriteLN;
|
||
Write('Type RETURN to return to main menu: ');
|
||
Read;
|
||
END;
|
||
|
||
PROCEDURE ConfigureLadder;
|
||
VAR
|
||
configPgm : FILE;
|
||
Ok : BOOLEAN;
|
||
BEGIN
|
||
{$I-}
|
||
Assign(configPgm, ConfigFileName);
|
||
WriteLN('Linking to configuration program');
|
||
Execute(configPgm);
|
||
Ok := IOresult = 0; { IOresult must be called after failed Execute }
|
||
{$I+}
|
||
WriteLN;
|
||
WriteLN('Unable to link to LADCONF.COM');
|
||
WriteLN('Ladder configuration program missing');
|
||
Halt;
|
||
END;
|
||
|
||
PROCEDURE MainMenu;
|
||
VAR
|
||
ch : CHAR;
|
||
insult : BOOLEAN;
|
||
i, msecs : INTEGER;
|
||
configPgm : FILE;
|
||
BEGIN
|
||
REPEAT
|
||
ClrScr;
|
||
WriteLN(' LL dd dd');
|
||
WriteLN(' LL dd dd tm');
|
||
WriteLN(' LL aaaa ddddd ddddd eeee rrrrrrr');
|
||
WriteLN(' LL aa aa dd dd dd dd ee ee rr rr');
|
||
WriteLN(' LL aa aa dd dd dd dd eeeeee rr');
|
||
WriteLN(' LL aa aa dd dd dd dd ee rr');
|
||
WriteLN(' LLLLLLLL aaa aa ddd dd ddd dd eeee rr');
|
||
WriteLN;
|
||
WriteLN(' Version : ', Version);
|
||
WriteLN('(c) 1982, 1983 Yahoo Software Terminal: ', dataFileContents.TerminalName);
|
||
WriteLN('10970 Ashton Ave. Suite 312 Play speed: ', playSpeed);
|
||
Write( 'Los Angeles, Ca 90024 ');
|
||
WriteLN('Up = ', upKey, ' Down = ',downKey ,' Left = ', leftKey, ' Right = ', rightKey);
|
||
WriteLN(' Jump = Space Stop = Other');
|
||
WriteLN;
|
||
WriteLN('P = Play game High Scores');
|
||
WriteLN('L = Change level of difficulty');
|
||
WriteLN('C = Configure Ladder');
|
||
WriteLN('I = Instructions');
|
||
WriteLN('E = Exit Ladder');
|
||
WriteLN;
|
||
WriteLN;
|
||
Write('Enter one of the above: ');
|
||
{ show high scores }
|
||
FOR i := 1 TO NumHighScores DO BEGIN
|
||
GotoXY(40, i + 15);
|
||
Write(i, ') ');
|
||
IF highScores[i].Score <> 0 THEN
|
||
Write(highScores[i].Score:4, '00 ', highScores[i].Name);
|
||
END;
|
||
IF lastScore <> -1 THEN BEGIN
|
||
GotoXY(40, 22);
|
||
Write('Last Score: ',lastScore,'00');
|
||
END;
|
||
GotoXY(25, 22);
|
||
|
||
{ randomly prompt the user to get a move on }
|
||
insult := FALSE;
|
||
msecs := 0;
|
||
REPEAT
|
||
Delay(1);
|
||
msecs := Succ(msecs);
|
||
IF msecs >= 1000 THEN BEGIN
|
||
msecs := 0;
|
||
IF insults THEN BEGIN
|
||
IF insult THEN BEGIN
|
||
GotoXY(1, 24);
|
||
ClrEol;
|
||
insult := FALSE;
|
||
GotoXY(25, 22);
|
||
END ELSE BEGIN
|
||
i := Random(10);
|
||
IF i > 7 THEN BEGIN
|
||
insult := TRUE;
|
||
GotoXY(1, 24);
|
||
IF i = 8 THEN
|
||
Write('You eat quiche!')
|
||
ELSE
|
||
Write('Come on, we don''t have all day!');
|
||
GotoXY(25, 22);
|
||
END;
|
||
END;
|
||
END;
|
||
END;
|
||
|
||
ch := #0;
|
||
IF KeyPressed THEN BEGIN
|
||
Read(Kbd, ch);
|
||
ch := UpCase(ch);
|
||
IF ch = 'L' THEN BEGIN { change playing speed }
|
||
playSpeed := SUCC(playSpeed MOD NumPlaySpeeds);
|
||
GotoXY(52, 11); Write(playSpeed);
|
||
GotoXY(25, 22);
|
||
END ELSE IF ch = 'I' THEN
|
||
Instructions;
|
||
END;
|
||
UNTIL ch IN ['P','C','I','E'];
|
||
UNTIL ch in ['P', 'C', 'E'];
|
||
IF ch = 'E' THEN BEGIN
|
||
Write('Exiting...');
|
||
GotoXY(1, 24);
|
||
ClrEOL;
|
||
GotoXY(1, 23);
|
||
Halt;
|
||
END ELSE IF ch = 'C' THEN BEGIN { run configuration program }
|
||
GotoXY(1, 23);
|
||
ConfigureLadder;
|
||
END;
|
||
END;
|
||
|
||
|
||
{
|
||
Read the LADDER.DAT file. This is the same file used in the original
|
||
game. We don't use the cursor control stuff (that's handled by Turbo
|
||
Pascal, but do use the control keys, flags and high scores.
|
||
|
||
I'm sure this code could be better, but it does the job.
|
||
}
|
||
PROCEDURE ReadDataFile;
|
||
VAR
|
||
dataFile,configPgm : FILE;
|
||
i, j : INTEGER;
|
||
BEGIN
|
||
{$I-}
|
||
Assign(dataFile, DataFileName);
|
||
Reset(dataFile);
|
||
IF IOresult <> 0 THEN BEGIN
|
||
ConfigureLadder;
|
||
END;
|
||
BlockRead(dataFile, dataFileContents, SizeOf(dataFileContents) DIV 128);
|
||
IF IOresult <> 0 THEN BEGIN
|
||
WriteLN('Ladder not configred');
|
||
WriteLN;
|
||
ConfigureLadder;
|
||
END;
|
||
WITH dataFileContents DO BEGIN
|
||
sound := Flags[0] = 'Y';
|
||
insults := Flags[1] = 'Y';
|
||
downKey := Keys[0];
|
||
leftKey := Keys[1];
|
||
rightKey := Keys[2];
|
||
upKey := Keys[3];
|
||
FOR i := 1 TO NumHighScores DO BEGIN
|
||
highScores[i].Name[0] := CHAR(Highs[i][0]);
|
||
IF Highs[i][0] = 0 THEN
|
||
highScores[i].Score := 0
|
||
ELSE
|
||
highScores[i].Score := Highs[i][1] OR (Highs[i][2] SHL 8);
|
||
FOR j := 1 TO Highs[i][0] DO
|
||
highScores[i].Name[j] := CHAR(Highs[i][j + 2]);
|
||
END;
|
||
END;
|
||
Close(dataFile);
|
||
{$I+}
|
||
END;
|
||
|
||
{
|
||
Update the high scores in LADDER.DAT. See the comments in
|
||
ReadDataFile.
|
||
}
|
||
PROCEDURE WriteDataFile;
|
||
VAR
|
||
dataFile : FILE;
|
||
i, j : INTEGER;
|
||
BEGIN
|
||
{$I-}
|
||
Assign(dataFile, DataFileName);
|
||
Reset(dataFile);
|
||
IF IOresult <> 0 THEN BEGIN
|
||
WriteLN('Reset failed on LADDER.DAT');
|
||
Halt;
|
||
END;
|
||
WITH dataFileContents DO BEGIN
|
||
FOR i := 1 TO NumHighScores DO BEGIN
|
||
Highs[i][0] := Length(highScores[i].Name);
|
||
Highs[i][1] := Lo(highScores[i].Score);
|
||
Highs[i][2] := Hi(highScores[i].Score);
|
||
FOR j := 1 TO Highs[i][0] DO
|
||
Highs[i][j + 2] := ORD(highScores[i].Name[j]);
|
||
END;
|
||
BlockWrite(dataFile, dataFileContents, SizeOf(dataFileContents) DIV 128);
|
||
IF IOresult <> 0 THEN BEGIN
|
||
WriteLN('BlockWrite failed on LADDER.DAT');
|
||
Halt;
|
||
END;
|
||
END;
|
||
Close(dataFile);
|
||
{$I+}
|
||
END;
|
||
|
||
{
|
||
kill the lad off in a horrible death of mixed up characters.
|
||
}
|
||
FUNCTION LadDeath : BOOLEAN;
|
||
CONST
|
||
NumSymbols = 11;
|
||
symbols : ARRAY[1..NumSymbols] OF CHAR = ('p', 'b', 'd', 'q', 'p', 'b', 'd', 'q', '-', '-', '_');
|
||
VAR
|
||
i, j : INTEGER;
|
||
name: STRING[DataFileNameLength];
|
||
ch : CHAR;
|
||
BEGIN
|
||
FOR i := 1 TO NumSymbols DO BEGIN
|
||
Beep;
|
||
GotoXY(lad.X, lad.Y); Write(symbols[i]);
|
||
Delay(150);
|
||
END;
|
||
m.LadsRemaining := Pred(m.LadsRemaining);
|
||
GotoXY(8, 21); Write(m.ladsRemaining : 2);
|
||
LadDeath := m.LadsRemaining > 0;
|
||
IF m.LadsRemaining <= 0 THEN BEGIN
|
||
FOR i := 1 TO NumHighScores DO BEGIN
|
||
WriteLN(highScores[i].Score);
|
||
IF m.Score >= highScores[i].Score THEN BEGIN
|
||
FOR j := NumHighScores - 1 DOWNTO i DO BEGIN
|
||
highScores[j + 1] := highScores[j];
|
||
END;
|
||
ClrScr;
|
||
GotoXY(10, 7);
|
||
FOR j := 1 TO 7 DO
|
||
Write('YAHOO! ');
|
||
WriteLN;
|
||
WriteLN;
|
||
CASE levelCycle OF
|
||
1 : WriteLN('You really don''t deserve this but...');
|
||
2 : WriteLN('Not bad for a young Lad');
|
||
3 : WriteLN('Amazing! You rate!!');
|
||
4 : WriteLN('Looks like we have a Lad-Der here');
|
||
5 : WriteLN('Yeah! Now you are a Lad-Wiz!');
|
||
6 : WriteLN('Wow! You are now a Lad-Guru!');
|
||
ELSE WriteLN('You are a true Lad-Master!!!');
|
||
END;
|
||
WriteLN;
|
||
While KeyPressed DO
|
||
Read(Kbd, ch);
|
||
Write('Enter your name: ');
|
||
CursOn;
|
||
Read(name);
|
||
CursOff;
|
||
GotoXY(1, 17);
|
||
Write('Updating high scores...');
|
||
highScores[i].Score := m.Score;
|
||
highScores[i].Name := name;
|
||
WriteDataFile;
|
||
EXIT;
|
||
END;
|
||
END;
|
||
END;
|
||
END;
|
||
|
||
PROCEDURE DrawMap;
|
||
VAR
|
||
x, y : INTEGER;
|
||
ch : CHAR;
|
||
BEGIN
|
||
FOR y := 1 TO LevelRows DO BEGIN
|
||
GotoXY(1, y);
|
||
FOR x := 1 TO LevelCols DO
|
||
Write(m.Field[y][x]);
|
||
END;
|
||
{ Draw the lad at rest }
|
||
GotoXY(lad.X, lad.Y); Write('g');
|
||
{ Initialize the entire status line }
|
||
GotoXY(1, 21);
|
||
Write('Lads ',m.LadsRemaining : 2,
|
||
' Level ', displayLevel : 2,
|
||
' Score ', m.Score : 5, '00',
|
||
' Bonus time ', m.RemainingBonusTime : 2, '00');
|
||
GotoXY(1, 23); Write('Get ready!');
|
||
Delay(1000);
|
||
WHILE KeyPressed DO
|
||
Read(Kbd, ch);
|
||
GotoXY(1, 23); Write(' ');
|
||
END;
|
||
|
||
{
|
||
Adjusts the score according to some event.
|
||
}
|
||
PROCEDURE UpdateScore(scoreEvent : ScoreType);
|
||
BEGIN
|
||
CASE scoreEvent OF
|
||
|
||
ScoreStatue: BEGIN
|
||
m.Score := m.Score + m.RemainingBonusTime;
|
||
Beep;
|
||
END;
|
||
|
||
ScoreReset: m.Score := 0;
|
||
|
||
ScoreRock: BEGIN
|
||
m.Score := m.Score + 2;
|
||
Beep;
|
||
END;
|
||
|
||
ScoreMoney: BEGIN
|
||
WHILE m.RemainingBonusTime > 0 DO BEGIN
|
||
GotoXY(1, 23); Write('Hooka!'); Beep; Delay(100);
|
||
GotoXY(1, 23); Write(' '); Delay(100);
|
||
m.Score := Succ(m.Score);
|
||
m.RemainingBonusTime := Pred(m.RemainingBonusTime);
|
||
GotoXY(36, 21); Write(m.Score : 5);
|
||
GotoXY(74, 21); Write(m.RemainingBonusTime : 2);
|
||
END;
|
||
END;
|
||
END;
|
||
{ give a new lad if over 10,000 points }
|
||
IF m.Score >= nextNewLad THEN BEGIN
|
||
m.ladsRemaining := Succ(m.ladsRemaining);
|
||
nextNewLad := nextNewLad + 100;
|
||
GotoXY(8, 21); Write(m.ladsRemaining : 2);
|
||
END;
|
||
GotoXY(36, 21);
|
||
Write(m.Score : 5);
|
||
END;
|
||
|
||
{
|
||
Check to see if the Lad has collided with, or jumped over a rock.
|
||
}
|
||
FUNCTION Collision(rockPtr : RockPointerType) : BOOLEAN;
|
||
BEGIN
|
||
Collision := FALSE;
|
||
IF lad.X = rockPtr^.X THEN BEGIN
|
||
IF lad.Y = rockPtr^.Y THEN BEGIN
|
||
Collision := TRUE;
|
||
END ELSE IF (lad.Y = rockPtr^.Y - 1) AND
|
||
(m.Field[lad.Y + 1][lad.X] = ' ') THEN BEGIN
|
||
{ score for jumping rocks }
|
||
UpdateScore(ScoreRock);
|
||
END ELSE IF (lad.Y = rockPtr^.Y - 2) THEN
|
||
IF (m.Field[lad.Y + 1][lad.X] = ' ') AND (m.Field[lad.Y + 2][lad.X] = ' ') THEN BEGIN
|
||
{ score for jumping rocks }
|
||
UpdateScore(ScoreRock);
|
||
END;
|
||
END;
|
||
END;
|
||
|
||
{
|
||
Set each rock up in a random dispenser.
|
||
}
|
||
PROCEDURE DisperseRocks;
|
||
VAR
|
||
rockPtr : RockPointerType;
|
||
dispenserPtr : DispenserPointerType;
|
||
i : INTEGER;
|
||
BEGIN
|
||
rockPtr := m.Rocks;
|
||
WHILE rockPtr <> NIL DO BEGIN
|
||
dispenserPtr := dispensers;
|
||
IF numDispensers > 1 THEN
|
||
FOR i := 1 TO Random(numDispensers) DO
|
||
dispenserPtr := dispenserPtr^.Next;
|
||
InitActor(rockPtr^, AROCK, dispenserPtr^.xy);
|
||
rockPtr := rockPtr^.Next;
|
||
END;
|
||
m.AnyRocksPending := TRUE;
|
||
END;
|
||
|