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;
|
|||
|
|