Added Turbo Pascal reimplementation of Ladder
This commit is contained in:
parent
8139d51b26
commit
9649342652
411
LadderTP/LADACTOR.PAS
Normal file
411
LadderTP/LADACTOR.PAS
Normal file
@ -0,0 +1,411 @@
|
||||
{
|
||||
ReverseDirection makes the actor to go in the opposite direction,
|
||||
it only works when the actor is moving left or right
|
||||
}
|
||||
PROCEDURE ReverseDirection(VAR a : ActorType);
|
||||
BEGIN
|
||||
CASE a.Dir OF
|
||||
LEFT : a.Dir := RIGHT;
|
||||
RIGHT : a.Dir := LEFT;
|
||||
END;
|
||||
END;
|
||||
|
||||
{
|
||||
OnSolid returns true if standing on something solid i.e. Floor,
|
||||
Disappearing floor or a Ladder
|
||||
}
|
||||
FUNCTION OnSolid(a : ActorType) : BOOLEAN;
|
||||
BEGIN
|
||||
OnSolid := (m.Field[a.Y + 1][a.X] IN ['=', '-', 'H', '|'])
|
||||
OR (m.Field[a.Y][a.X] = 'H');
|
||||
END;
|
||||
|
||||
FUNCTION EmptySpace(x, y : INTEGER) : BOOLEAN;
|
||||
BEGIN
|
||||
IF (x < 1) OR (x > LevelCols) THEN
|
||||
EmptySpace := TRUE
|
||||
ELSE
|
||||
EmptySpace := NOT (m.Field[y][x] IN ['|', '=']);
|
||||
END;
|
||||
|
||||
{
|
||||
AboveLadder returns true when the actor is a above a Ladder
|
||||
}
|
||||
FUNCTION AboveLadder(a : ActorType) : BOOLEAN;
|
||||
BEGIN
|
||||
AboveLadder := m.Field[a.Y + 1][a.X] = 'H';
|
||||
END;
|
||||
|
||||
{
|
||||
OnEater returns true when the actor is standing on a Eater
|
||||
}
|
||||
FUNCTION OnEater(a : ActorType) : BOOLEAN;
|
||||
BEGIN
|
||||
OnEater := m.Field[a.Y][a.X] = '*';
|
||||
END;
|
||||
|
||||
{
|
||||
ClampToPlayfield makes sure that if the actor tries to walk or jump off
|
||||
the playfield edges the actor stays inside the playfield and starts falling
|
||||
}
|
||||
PROCEDURE ClampToPlayfield(VAR a : ActorType);
|
||||
BEGIN
|
||||
IF a.Dir IN [LEFT, JUMPLEFT] THEN BEGIN
|
||||
IF a.X < 1 THEN BEGIN
|
||||
a.X := 1;
|
||||
a.Dir := STOPPED;
|
||||
a.DirRequest := NONE;
|
||||
END;
|
||||
END;
|
||||
|
||||
IF a.Dir IN [RIGHT, JUMPRIGHT] THEN BEGIN
|
||||
IF a.X > LevelCols THEN BEGIN
|
||||
a.X := LevelCols;
|
||||
a.Dir := STOPPED;
|
||||
a.DirRequest := NONE;
|
||||
END;
|
||||
END;
|
||||
END;
|
||||
|
||||
{
|
||||
InitActor set the fields of an Actor type to reasonable
|
||||
initial values
|
||||
}
|
||||
PROCEDURE InitActor(VAR a : ActorType; t : KindType; xy : XYtype);
|
||||
BEGIN
|
||||
a.AType := t;
|
||||
a.X := xy.x;
|
||||
a.Y := xy.y;
|
||||
a.Ch := 'X';
|
||||
a.JumpStep := 0;
|
||||
CASE t OF
|
||||
ALAD:
|
||||
BEGIN
|
||||
a.Ch := 'g';
|
||||
a.Dir := STOPPED;
|
||||
a.DirRequest := NONE;
|
||||
END;
|
||||
AROCK:
|
||||
BEGIN
|
||||
a.Ch := 'o';
|
||||
a.Dir := PENDING;
|
||||
a.DirRequest := NONE;
|
||||
END;
|
||||
END;
|
||||
END;
|
||||
|
||||
{
|
||||
Set the Lad's character based on their current direction
|
||||
}
|
||||
PROCEDURE UpdateLadChar(VAR a : ActorType);
|
||||
BEGIN
|
||||
WITH a DO
|
||||
CASE Dir OF
|
||||
STOPPED: Ch := 'g';
|
||||
RIGHT, JUMPRIGHT: Ch := 'p';
|
||||
LEFT, JUMPLEFT: Ch := 'q';
|
||||
FALLING: Ch := 'b';
|
||||
UP, DOWN: Ch := 'p';
|
||||
JUMP:
|
||||
CASE a.DirRequest OF
|
||||
NONE, STOPPED: Ch := 'g';
|
||||
RIGHT, JUMPRIGHT: Ch := 'p';
|
||||
LEFT, JUMPLEFT: Ch := 'q';
|
||||
END;
|
||||
END;
|
||||
END;
|
||||
|
||||
{
|
||||
Update an actor's direction to the latest's request
|
||||
}
|
||||
PROCEDURE UpdateDir(VAR a : ActorType);
|
||||
BEGIN
|
||||
a.Dir := a.DirRequest;
|
||||
a.DirRequest := NONE;
|
||||
END;
|
||||
|
||||
{
|
||||
MoveActor handles the movements of an Actor
|
||||
}
|
||||
PROCEDURE MoveActor(VAR a : ActorType);
|
||||
LABEL
|
||||
loopAgain;
|
||||
VAR
|
||||
jd : ActionType;
|
||||
i : INTEGER;
|
||||
dispenser : DispenserPointerType;
|
||||
BEGIN
|
||||
|
||||
loopAgain: { If just started falling we need to retest all conditions }
|
||||
|
||||
{ A STONE can only be LEFT/RIGHT/DOWN/FALLING or PENDING }
|
||||
IF a.AType = AROCK THEN BEGIN
|
||||
IF (a.Dir = PENDING) AND (a.DirRequest = NONE) THEN
|
||||
EXIT;
|
||||
|
||||
{ If stopped select a random direction }
|
||||
IF a.Dir = STOPPED THEN BEGIN
|
||||
CASE Random(2) OF
|
||||
0: IF (a.X > 1) THEN
|
||||
IF EmptySpace(a.X - 1, a.Y) THEN
|
||||
a.DirRequest := LEFT
|
||||
ELSE
|
||||
a.DirRequest := RIGHT
|
||||
ELSE
|
||||
a.DirRequest := RIGHT;
|
||||
1: IF (a.X < LevelCols) THEN
|
||||
IF EmptySpace(a.X + 1, a.Y) THEN
|
||||
a.DirRequest := RIGHT
|
||||
ELSE
|
||||
a.DirRequest := LEFT
|
||||
ELSE
|
||||
a.DirRequest := LEFT;
|
||||
END;
|
||||
END;
|
||||
|
||||
{ Just reverse direction if at the playfield edge }
|
||||
IF (a.X = 1) OR (a.X = LevelCols) THEN
|
||||
ReverseDirection(a);
|
||||
|
||||
{ Start to fall if not on solid ground }
|
||||
IF (a.Dir <> FALLING) AND NOT OnSolid(a) THEN
|
||||
a.DirRequest := FALLING;
|
||||
|
||||
{ If Der rock just rolled over the top of a ladder then randomize direction }
|
||||
IF AboveLadder(a) AND (a.Dir IN [LEFT, RIGHT]) THEN
|
||||
CASE Random(4) OF
|
||||
0: a.DirRequest := LEFT;
|
||||
1: a.DirRequest := RIGHT;
|
||||
ELSE a.DirRequest := DOWN;
|
||||
END;
|
||||
|
||||
{ If on an Eater kill the stone }
|
||||
IF OnEater(a) THEN BEGIN
|
||||
dispenser := dispensers;
|
||||
IF numDispensers > 1 THEN BEGIN
|
||||
FOR i := 1 TO Random(numDispensers) DO
|
||||
dispenser := dispenser^.next;
|
||||
END;
|
||||
InitActor(a, AROCK, dispenser^.xy);
|
||||
m.AnyRocksPending := TRUE;
|
||||
END;
|
||||
END; { of stone only handling --------------------- }
|
||||
|
||||
{ If stopped or going left or going right and }
|
||||
{ request to do something else, then try to do it }
|
||||
IF (a.DirRequest <> NONE) THEN BEGIN
|
||||
CASE a.Dir OF
|
||||
STOPPED, PENDING:
|
||||
IF a.DirRequest IN [LEFT, RIGHT, UP, DOWN, FALLING] THEN
|
||||
UpdateDir(a);
|
||||
|
||||
JUMPUP:
|
||||
IF a.DirRequest = LEFT THEN
|
||||
a.Dir := JUMPLEFT
|
||||
ELSE IF a.DirRequest = RIGHT THEN
|
||||
a.Dir := JUMPRIGHT;
|
||||
|
||||
RIGHT:
|
||||
IF a.DirRequest IN [LEFT, STOPPED] THEN
|
||||
UpdateDir(a);
|
||||
|
||||
LEFT:
|
||||
IF a.DirRequest IN [RIGHT, STOPPED] THEN
|
||||
UpdateDir(a);
|
||||
|
||||
UP, DOWN:
|
||||
IF a.DirRequest IN [STOPPED, UP, DOWN, RIGHT, LEFT] THEN
|
||||
UpdateDir(a);
|
||||
|
||||
JUMPUP:
|
||||
IF a.DirRequest = LEFT THEN
|
||||
a.Dir := JUMPLEFT
|
||||
ELSE
|
||||
a.Dir := JUMPRIGHT;
|
||||
|
||||
JUMPRIGHT, JUMPLEFT:
|
||||
IF a.DirRequest = STOPPED THEN
|
||||
UpdateDir(a);
|
||||
|
||||
PENDING:
|
||||
UpdateDir(a);
|
||||
|
||||
END;
|
||||
END;
|
||||
|
||||
{ Handle starting of jumps }
|
||||
IF (a.DirRequest = JUMP) THEN BEGIN
|
||||
IF OnSolid(a) THEN BEGIN
|
||||
CASE a.Dir OF
|
||||
|
||||
STOPPED, FALLING: BEGIN
|
||||
a.DirRequest := STOPPED;
|
||||
a.Dir := JUMPUP;
|
||||
a.JumpStep := 1;
|
||||
END;
|
||||
|
||||
LEFT: BEGIN
|
||||
a.DirRequest := a.Dir;
|
||||
a.Dir := JUMPLEFT;
|
||||
a.JumpStep := 1;
|
||||
END;
|
||||
|
||||
JUMPLEFT: BEGIN
|
||||
a.DirRequest := LEFT;
|
||||
a.Dir := JUMPLEFT;
|
||||
a.JumpStep := 1;
|
||||
END;
|
||||
|
||||
RIGHT: BEGIN
|
||||
a.DirRequest := a.Dir;
|
||||
a.Dir := JUMPRIGHT;
|
||||
a.JumpStep := 1;
|
||||
END;
|
||||
|
||||
JUMPRIGHT: BEGIN
|
||||
a.DirRequest := RIGHT;
|
||||
a.Dir := JumpRIGHT;
|
||||
a.JumpStep := 1;
|
||||
END;
|
||||
END
|
||||
END ELSE BEGIN
|
||||
CASE a.Dir OF
|
||||
JUMPUP, FALLING: a.DirRequest := STOPPED;
|
||||
JUMPRIGHT: a.DirRequest := RIGHT;
|
||||
JUMPLEFT: a.DirRequest := LEFT;
|
||||
END;
|
||||
END;
|
||||
END ELSE IF (a.DirRequest = UP) AND (m.Field[a.Y][a.X] = 'H') THEN BEGIN
|
||||
{ If at a ladder and want to go up }
|
||||
a.Dir := UP;
|
||||
a.DirRequest := NONE;
|
||||
END ELSE IF(a.DirRequest = DOWN) AND
|
||||
((m.Field[a.Y][a.X] = 'H') OR (m.Field[a.Y + 1][a.X] = 'H')) THEN BEGIN
|
||||
a.Dir := DOWN;
|
||||
a.DirRequest := NONE;
|
||||
END;
|
||||
|
||||
CASE a.Dir OF
|
||||
|
||||
JUMPUP, JUMPLEFT, JUMPRIGHT: BEGIN
|
||||
{ Do the jumping }
|
||||
jd := jumpPaths[a.Dir, a.JumpStep];
|
||||
IF (a.X + dirs[jd].x >= 1) AND (a.X + dirs[jd].x <= LevelCols) THEN BEGIN
|
||||
CASE m.Field[a.Y + dirs[jd].y][a.X + dirs[jd].x] OF
|
||||
|
||||
'=', '|', '-' : BEGIN
|
||||
{ If bumped into something try falling }
|
||||
IF OnSolid(a) THEN BEGIN
|
||||
a.Dir := a.DirRequest;
|
||||
a.DirRequest := NONE;
|
||||
END ELSE BEGIN
|
||||
CASE a.Dir OF
|
||||
JUMPUP: a.DirRequest := STOPPED;
|
||||
JUMPRIGHT: a.DirRequest := RIGHT;
|
||||
JUMPLEFT: a.DirRequest := LEFT;
|
||||
END;
|
||||
a.Dir := FALLING;
|
||||
END;
|
||||
a.JumpStep := 0;
|
||||
END;
|
||||
|
||||
'H': BEGIN { Jumping onto a ladder }
|
||||
a.Y := a.Y + dirs[jd].y;
|
||||
a.X := a.X + dirs[jd].x;
|
||||
a.Dir := STOPPED;
|
||||
a.DirRequest := NONE;
|
||||
a.JumpStep := 0;
|
||||
END;
|
||||
|
||||
ELSE BEGIN
|
||||
{ Just jumping in air }
|
||||
a.X := a.X + dirs[jd].x;
|
||||
a.Y := a.Y + dirs[jd].y;
|
||||
a.JumpStep := SUCC(a.JumpStep);
|
||||
IF (a.JumpStep > JumpsLen) THEN BEGIN
|
||||
UpdateDir(a);
|
||||
a.JumpStep := 0;
|
||||
END ELSE IF (jumpPaths[a.Dir][a.JumpStep] = ACTIONEND) THEN BEGIN
|
||||
UpdateDir(a);
|
||||
a.JumpStep := 0;
|
||||
END;
|
||||
END;
|
||||
END;
|
||||
END ELSE BEGIN
|
||||
IF OnSolid(a) THEN BEGIN
|
||||
a.Dir := a.DirRequest;
|
||||
a.DirRequest := NONE;
|
||||
END ELSE BEGIN
|
||||
a.Dir := FALLING;
|
||||
a.DirRequest := STOPPED;
|
||||
a.JumpStep := 0;
|
||||
END;
|
||||
END;
|
||||
END;
|
||||
|
||||
STOPPED:
|
||||
IF NOT OnSolid(a) THEN
|
||||
a.Dir := FALLING;
|
||||
|
||||
FALLING: BEGIN
|
||||
{ If falling then continue doing that until not in free space anymore, }
|
||||
{ then continue the previous direction (if any) }
|
||||
IF OnSolid(a) THEN
|
||||
IF a.DirRequest = NONE THEN
|
||||
a.DirRequest := STOPPED
|
||||
ELSE
|
||||
a.Dir := a.DirRequest
|
||||
ELSE
|
||||
a.Y := Succ(a.Y);
|
||||
END;
|
||||
|
||||
UP:
|
||||
{ Climb up until ladder is no more }
|
||||
IF m.Field[a.Y - 1][a.X] IN ['H', '&', '$'] THEN
|
||||
a.Y := Pred(a.Y)
|
||||
ELSE
|
||||
a.Dir := STOPPED;
|
||||
|
||||
DOWN:
|
||||
{ Climb down until ladder is no more }
|
||||
IF a.Dir = DOWN THEN
|
||||
IF m.Field[a.Y + 1][a.X] IN ['H', '&', '$', ' ', '^', '.'] THEN
|
||||
a.Y := Succ(a.Y)
|
||||
ELSE
|
||||
a.Dir := STOPPED;
|
||||
|
||||
LEFT: BEGIN
|
||||
{ Stepped out into the void? Then start falling, }
|
||||
{ but remember the previous direction }
|
||||
IF NOT OnSolid(a) THEN BEGIN
|
||||
a.DirRequest := a.Dir;
|
||||
a.Dir := FALLING;
|
||||
GOTO loopAgain;
|
||||
END;
|
||||
IF EmptySpace(a.X - 1, a.Y) THEN
|
||||
a.X := Pred(a.X)
|
||||
ELSE
|
||||
a.DirRequest := STOPPED;
|
||||
END;
|
||||
|
||||
RIGHT: BEGIN
|
||||
{ Stepped out into the void? Then start falling, }
|
||||
{ but remember the previous direction }
|
||||
IF NOT OnSolid(a) THEN BEGIN
|
||||
a.DirRequest := a.Dir;
|
||||
a.Dir := FALLING;
|
||||
GOTO loopAgain;
|
||||
END;
|
||||
IF EmptySpace(a.X + 1, a.Y) THEN
|
||||
a.X := Succ(a.X)
|
||||
ELSE
|
||||
a.DirRequest := STOPPED;
|
||||
END;
|
||||
END;
|
||||
|
||||
{ Don't allow actor to end up outside of the playfield }
|
||||
ClampToPlayfield(a);
|
||||
IF a.AType = ALAD THEN
|
||||
UpdateLadChar(a);
|
||||
END;
|
||||
|
BIN
LadderTP/LADCONF.COM
Normal file
BIN
LadderTP/LADCONF.COM
Normal file
Binary file not shown.
20
LadderTP/LADCONST.PAS
Normal file
20
LadderTP/LADCONST.PAS
Normal file
@ -0,0 +1,20 @@
|
||||
CONST
|
||||
Version = '1.33TP';
|
||||
DataFileName = 'LADDER.DAT';
|
||||
ConfigFileName = 'LADCONF.COM';
|
||||
NumHighScores = 5; { # of stored high scores }
|
||||
DataFileStrLength = 31; { # chars in data file terminal config strings }
|
||||
DataFileNameLength = 29; { # chars in high score names }
|
||||
CursOffStr = #$1B'[?25l'; { turn cursor off string }
|
||||
CursOnStr = #$1B'[?25h'; { turn cursor on string }
|
||||
NumPlaySpeeds = 5; { # of different playing speeds }
|
||||
BonusTimeDecInterval = 3000; { decrement bonus time every 3 seconds }
|
||||
|
||||
NumLevels = 7; { # of distinct levels }
|
||||
LevelRows = 20; { # of rows in a level map }
|
||||
LevelCols = 79; { # of chars in a level map }
|
||||
MaxDispensers = 3; { max # of rock dispensers on a level }
|
||||
|
||||
JumpsLen = 6; { max # of positions in a jump sequence }
|
||||
|
||||
|
BIN
LadderTP/LADDER.COM
Normal file
BIN
LadderTP/LADDER.COM
Normal file
Binary file not shown.
BIN
LadderTP/LADDER.DAT
Normal file
BIN
LadderTP/LADDER.DAT
Normal file
Binary file not shown.
34
LadderTP/LADDER.PAS
Normal file
34
LadderTP/LADDER.PAS
Normal file
@ -0,0 +1,34 @@
|
||||
{$C-}
|
||||
{$I-}
|
||||
{
|
||||
Ladder: a reimplementation in Turbo Pascal of the classic
|
||||
CP/M game "Ladder", originally written by Yahoo Software (not
|
||||
Yahoo!).
|
||||
|
||||
Ladder is an ASCII character based platform arcade game similar to
|
||||
Donkey Kong. You travel through levels with platforms and ladders
|
||||
where rocks fall down from the top while you collect statues
|
||||
before reaching the exit.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
}
|
||||
PROGRAM ladder;
|
||||
|
||||
{$I LADCONST}
|
||||
{$I LADTYPE}
|
||||
{$I LADVAR}
|
||||
{$I LADICONS}
|
||||
{$I LADUTILS}
|
||||
{$I LADFIELD}
|
||||
{$I LADACTOR}
|
||||
{$I LADPROCS}
|
||||
{$I LADMAIN}
|
||||
|
75
LadderTP/LADFIELD.PAS
Normal file
75
LadderTP/LADFIELD.PAS
Normal file
@ -0,0 +1,75 @@
|
||||
{ LoadMap loads one of the playfields/maps into memory and also }
|
||||
{ returns the coordinates of the initial Lad, and an array of }
|
||||
{ coordinates where the dispensers are. }
|
||||
PROCEDURE LoadMap(VAR lad : XYtype; VAR dispensers : DispenserPointerType; VAR numDispensers : INTEGER);
|
||||
VAR
|
||||
x, y : INTEGER;
|
||||
newDispenser : DispenserPointerType;
|
||||
dispenserPtr : DispenserPointerType;
|
||||
rock1Ptr,rock2Ptr : RockPointerType;
|
||||
BEGIN
|
||||
{ get rid of anay previous rock dispensers }
|
||||
WHILE dispensers <> NIL DO BEGIN
|
||||
dispenserPtr := dispensers^.next;
|
||||
DISPOSE(dispensers);
|
||||
dispensers := dispenserPtr;
|
||||
END;
|
||||
IF m.Level > NumLevels THEN BEGIN
|
||||
ClrScr;
|
||||
WriteLN('Level ', m.Level, ' out of range');
|
||||
CursOn;
|
||||
Halt;
|
||||
END;
|
||||
WITH levels[m.Level] DO BEGIN
|
||||
m.Name := Name;
|
||||
m.InitialBonusTime := InitialBonusTime;
|
||||
m.NumRocks := rocks;
|
||||
|
||||
{ dispose of any previous rocks }
|
||||
WHILE m.Rocks <> NIL DO BEGIN
|
||||
rock1Ptr := m.Rocks^.Next;
|
||||
Dispose(m.Rocks);
|
||||
m.Rocks := rock1Ptr;
|
||||
END;
|
||||
{ allocate new rocks }
|
||||
FOR x := 1 TO Rocks DO BEGIN
|
||||
rock1Ptr := m.Rocks;
|
||||
New(rock2Ptr);
|
||||
m.Rocks := rock2Ptr;
|
||||
m.Rocks^.Next := rock1Ptr;
|
||||
END;
|
||||
m.AnyRocksPending := TRUE;
|
||||
END;
|
||||
{ Prepare the field to be loaded with a new level }
|
||||
FOR y := 1 TO LevelRows DO
|
||||
FOR x := 1 TO LevelCols DO
|
||||
m.Field[y][x] := ' ';
|
||||
dispensers := NIL;
|
||||
numDispensers := 0;
|
||||
FOR y := 1 TO LevelRows DO
|
||||
FOR x := 1 TO LevelCols DO
|
||||
CASE levels[m.Level].layout[y][x] OF
|
||||
'p':
|
||||
BEGIN
|
||||
{ The lad will be put there by the rendered, so no need to have }
|
||||
{ it on the map }
|
||||
lad.x := x;
|
||||
lad.y := y;
|
||||
END;
|
||||
'V':
|
||||
BEGIN
|
||||
m.Field[y][x] := 'V';
|
||||
NEW(newDispenser);
|
||||
newDispenser^.xy.x := x;
|
||||
newDispenser^.xy.y := y;
|
||||
newDispenser^.next := dispensers;
|
||||
dispensers := newDispenser;
|
||||
numDispensers := Succ(numDispensers);
|
||||
END;
|
||||
'.': { TODO - handle the rubber balls }
|
||||
m.Field[y][x] := '.'
|
||||
ELSE
|
||||
m.Field[y][x] := levels[m.Level].layout[y][x];
|
||||
END;
|
||||
END;
|
||||
|
244
LadderTP/LADICONS.PAS
Normal file
244
LadderTP/LADICONS.PAS
Normal file
@ -0,0 +1,244 @@
|
||||
{ Initialized constants for Ladder }
|
||||
|
||||
CONST
|
||||
{
|
||||
p - The place where the lad starts.
|
||||
V - Der Dispenser. Der Rocks roll out of it to squash you flat.
|
||||
* - Der Eaters. They eat the Der Rocks but oddly do not harm you in the slightest
|
||||
= - Floor. You walk on it.
|
||||
H - Ladder. You climb it.
|
||||
| - Wall. You can't walk through it. You're not a ghost....yet.
|
||||
. - Rubber Ball. It's very bouncy. This difference is, it bounces you.
|
||||
$ - Treasure. The lad must get here to finish the level.
|
||||
& - Gold Statue. Money!Money!Money!Money!Money!
|
||||
^ - Fire. Turns you into extra crispy bacon.
|
||||
- - Disposable Floor. Well, you can walk on it once.
|
||||
}
|
||||
levels : ARRAY[1..NumLevels] OF LevelType = (
|
||||
(
|
||||
Name : 'Easy Street';
|
||||
InitialBonusTime : 35;
|
||||
Rocks : 5;
|
||||
Layout : (
|
||||
' V $ ',
|
||||
' H ',
|
||||
' H H ',
|
||||
' =========H================================================== ',
|
||||
' H ',
|
||||
' H ',
|
||||
' H H H ',
|
||||
'================H==========H================== ========H=====================',
|
||||
' & H H | | ',
|
||||
' H Easy Street ',
|
||||
' H H ',
|
||||
' =========H==========H========= ======================= ',
|
||||
' H ',
|
||||
' H ',
|
||||
' H H ',
|
||||
'======================== ====================== =========H============== ',
|
||||
' H ',
|
||||
' H ',
|
||||
'* p H *',
|
||||
'==============================================================================='
|
||||
)
|
||||
),
|
||||
(
|
||||
Name : 'Long Island';
|
||||
InitialBonusTime : 45;
|
||||
Rocks : 8;
|
||||
Layout : (
|
||||
' $ ',
|
||||
' & H ',
|
||||
' H |V V| H ',
|
||||
'====H======================= ========================= ====================== ',
|
||||
' H ',
|
||||
' H ',
|
||||
' H & | . . H ',
|
||||
'========================== ====== =================== ===================H== ',
|
||||
' H ',
|
||||
' | H ',
|
||||
' H | . . H ',
|
||||
'====H===================== ====== ================ ====================== ',
|
||||
' H ',
|
||||
' H | ',
|
||||
' H | . . H ',
|
||||
'========================= ======== ============== ==================H== ',
|
||||
' H ',
|
||||
'============== | H ',
|
||||
' Long Island | p * | * H ',
|
||||
'==============================================================================='
|
||||
)
|
||||
),
|
||||
(
|
||||
Name : 'Ghost Town';
|
||||
InitialBonusTime : 35;
|
||||
Rocks : 5;
|
||||
Layout : (
|
||||
' V V V $ ',
|
||||
' $$$ ',
|
||||
' p H H $$$$$ H',
|
||||
'==========H=== =H==============H',
|
||||
' H H H',
|
||||
' H & H H',
|
||||
' ============== ==== = ====== = ==== =====H===== H',
|
||||
' G ^^^ ^^^^^ ^^^^ ^^^^ ^^^ ^^^ $',
|
||||
' h | ',
|
||||
' o | H & | ',
|
||||
' s ======================H============================== =========== ',
|
||||
' t & H ',
|
||||
' H ',
|
||||
' | H H H ',
|
||||
' T ==================H=================H===================H======= ',
|
||||
' o H H ',
|
||||
' w H ',
|
||||
' n ^ H ',
|
||||
'* ^^^ H *',
|
||||
'==============================================================================='
|
||||
)
|
||||
),
|
||||
(
|
||||
Name : 'Tunnel Vision';
|
||||
InitialBonusTime : 36;
|
||||
Rocks : 5;
|
||||
Layout : (
|
||||
' V V ',
|
||||
' ',
|
||||
' H H | H ',
|
||||
'=====H=====--======H========================== ===----====H=========== ',
|
||||
' H H |&& H ',
|
||||
' H H ================== H ',
|
||||
' H H tunnel H H ',
|
||||
' H =======---===----=================H= H H ',
|
||||
' H | vision H H H ',
|
||||
' H =========---& -----============H H H ',
|
||||
' H H H | H H ',
|
||||
' H H=========----===----================ H ==============',
|
||||
' H & H ',
|
||||
' H | H ',
|
||||
'====---==== H | H ',
|
||||
'| | ================---===---=================== H ',
|
||||
'| === | H H p ',
|
||||
'| $ | H ===H=======',
|
||||
'|* $$$ *| * * * *H *H ',
|
||||
'==============================================================================='
|
||||
)
|
||||
),
|
||||
(
|
||||
Name : 'Point of No Return';
|
||||
InitialBonusTime : 35;
|
||||
Rocks : 7;
|
||||
Layout : (
|
||||
' $ ',
|
||||
' H V ',
|
||||
' H ',
|
||||
' HHHHHHHHHHHHH .HHHHHHHHHHHHHH H p ',
|
||||
' & V H ==H==========',
|
||||
' H H ',
|
||||
' H H . H ',
|
||||
'===H==============-----------============H==== H ',
|
||||
' H H H ',
|
||||
' H =====H============== ',
|
||||
' H H H ',
|
||||
' H &..^^^.....^..^ . ^^ H==--------- H ',
|
||||
' H ============================H & H H ',
|
||||
' H === === === H ---------=================H======',
|
||||
' H H H ',
|
||||
' H & H & H ',
|
||||
' ==========-------------------------=======----------=================== ',
|
||||
' ',
|
||||
'^^^* ^^^^^^^^^^^^^^^^^^^^^^^^^* *^^^^^^^^^^*Point of No Return*^^^^',
|
||||
'==============================================================================='
|
||||
)
|
||||
),
|
||||
(
|
||||
Name : 'Bug City';
|
||||
InitialBonusTime : 37;
|
||||
Rocks : 6;
|
||||
Layout : (
|
||||
' Bug City HHHHHHHH V ',
|
||||
' HHH HHH ',
|
||||
' H >mmmmmmmm ',
|
||||
' H=============== ==================== H ',
|
||||
' H |===== \ / V =====H==========',
|
||||
' H \/ H ',
|
||||
' H | $ H ',
|
||||
' H H | H H ',
|
||||
' H ====H======= p |&H H H ',
|
||||
' H H ======================H ====== ',
|
||||
' H H &| H H ',
|
||||
' H H &| H H }{ =====H==== ',
|
||||
'===H===& H =====================H H H ',
|
||||
' H H H H ',
|
||||
' H H & H ',
|
||||
' ======H=== ======= H <> & H ',
|
||||
' H========== ===== = ============',
|
||||
' }i{ H ',
|
||||
'* H *',
|
||||
'==============================================================================='
|
||||
)
|
||||
),
|
||||
(
|
||||
Name : 'GangLand';
|
||||
InitialBonusTime : 32;
|
||||
Rocks : 6;
|
||||
Layout : (
|
||||
' =Gang Land= V ',
|
||||
' == _ == . ',
|
||||
' p H | [] |_| | & . H ',
|
||||
'===========H | |_| | H === ===================H ',
|
||||
' V H ============= H====== H ',
|
||||
' H H & H ',
|
||||
' H H | | H ',
|
||||
' H H ^^^&&^^^ & ^ ^^^ H H | =============H ',
|
||||
' H======H =======================H===========H===== & H ',
|
||||
' H H H | &&& H ',
|
||||
' H H H | &&&&& H ',
|
||||
' H H H | =============H ',
|
||||
' =====------================= H | $ $ ',
|
||||
' | H | $$$ $$$ ',
|
||||
'====------=== | H | $$$$$ $$$$$ ',
|
||||
' | = | ============= ============ ',
|
||||
' | $ ^ & ',
|
||||
' |^^^^^^^^^^^^^^ $ ^ ====== ',
|
||||
'* . & ^ H*^ ^ ^ ^^^^^^^^^^^^',
|
||||
'==============================================================================='
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
{
|
||||
A moving jump is UR/UR/R/R/DR/DR
|
||||
or UL/UL/L/L/DL/DL
|
||||
A standing jump is U/U/-/D/D
|
||||
|
||||
====================
|
||||
----234-----23------
|
||||
---1---5----14------
|
||||
--0-----6---05------
|
||||
====================
|
||||
}
|
||||
jumpPaths : Array[JUMPRIGHT..JUMPLEFT] OF ActionArrayType = (
|
||||
(UPRIGHT, UPRIGHT, RIGHT, RIGHT, DOWNRIGHT, DOWNRIGHT),
|
||||
(UP, UP, STOPPED, DOWN, DOWN, ACTIONEND),
|
||||
(UPLEFT, UPLEFT, LEFT, LEFT, DOWNLEFT, DOWNLEFT)
|
||||
);
|
||||
|
||||
dirs : ARRAY[STOPPED..JUMPLEFT] OF XYtype = (
|
||||
(x: 0; y: 0), { STOPPED }
|
||||
(x: 0; y:-1), { UP }
|
||||
(x: 1; y:-1), { UPRIGHT }
|
||||
(x: 1; y: 0), { RIGHT }
|
||||
(x: 1; y: 1), { DOWNRIGHT }
|
||||
(x: 0; y: 1), { DOWN }
|
||||
(x:-1; y: 1), { DOWNLEFT }
|
||||
(x:-1; y: 0), { LEFT }
|
||||
(x:-1; y:-1), { UPLEFT }
|
||||
(x: 0; y: 1), { FALLING }
|
||||
(x: 0; y: 0), { JUMP }
|
||||
(x: 0; y: 0), { JUMPRIGHT }
|
||||
(x: 0; y: 0), { JUMPUP }
|
||||
(x: 0; y: 0) { JUMPLEFT }
|
||||
);
|
||||
|
||||
ReadmsWait : ARRAY [1..NumPlaySpeeds] OF INTEGER = (100, 50, 25, 13, 7);
|
||||
|
221
LadderTP/LADMAIN.PAS
Normal file
221
LadderTP/LADMAIN.PAS
Normal file
@ -0,0 +1,221 @@
|
||||
{
|
||||
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.
|
||||
|
393
LadderTP/LADPROCS.PAS
Normal file
393
LadderTP/LADPROCS.PAS
Normal file
@ -0,0 +1,393 @@
|
||||
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;
|
||||
|
96
LadderTP/LADTYPE.PAS
Normal file
96
LadderTP/LADTYPE.PAS
Normal file
@ -0,0 +1,96 @@
|
||||
TYPE
|
||||
Str80Type = STRING[80];
|
||||
ScoreType = (ScoreReset, ScoreRock, ScoreStatue, ScoreMoney);
|
||||
|
||||
NameStringType = STRING[20];
|
||||
LayoutType = ARRAY[1..LevelRows] OF ARRAY[1..LevelCols] OF CHAR;
|
||||
LevelType = RECORD
|
||||
Name : NameStringType;
|
||||
InitialBonusTime : INTEGER;
|
||||
Rocks : INTEGER;
|
||||
Layout : LayoutType;
|
||||
END;
|
||||
|
||||
{ The Action constants define what the Actor currently is, }
|
||||
{ or is requested to be, doing }
|
||||
ActionType = (
|
||||
PENDING,
|
||||
NONE,
|
||||
STOPPED,
|
||||
UP,
|
||||
UPRIGHT,
|
||||
RIGHT,
|
||||
DOWNRIGHT,
|
||||
DOWN,
|
||||
DOWNLEFT,
|
||||
LEFT,
|
||||
UPLEFT,
|
||||
FALLING,
|
||||
JUMP, { Generic jump set by keyhandler }
|
||||
JUMPRIGHT,
|
||||
JUMPUP,
|
||||
JUMPLEFT,
|
||||
ACTIONEND
|
||||
);
|
||||
|
||||
ActionArrayType = ARRAY[1..JumpsLen] OF ActionType;
|
||||
|
||||
KindType = ( ALAD, AROCK );
|
||||
|
||||
RockPointerType = ^ActorType;
|
||||
{ The Actor struct holds info about an actor ie, the Lad or a Rock }
|
||||
ActorType = RECORD
|
||||
AType : KindType;
|
||||
X,Y : INTEGER;
|
||||
Ch : CHAR;
|
||||
Dir, DirRequest : ActionType;
|
||||
JumpStep : INTEGER;
|
||||
Next : RockPointerType;
|
||||
END;
|
||||
|
||||
{ The MapData hold all info about a map }
|
||||
MapDataType = RECORD
|
||||
Name : NameStringType;
|
||||
Field : LayoutType;
|
||||
LadsRemaining : INTEGER;
|
||||
NumRocks : INTEGER;
|
||||
Rocks : RockPointerType;
|
||||
AnyRocksPending : BOOLEAN;
|
||||
Level : INTEGER;
|
||||
Score : INTEGER;
|
||||
InitialBonusTime : INTEGER;
|
||||
RemainingBonusTime : INTEGER;
|
||||
ScoreText : Str80type;
|
||||
END;
|
||||
|
||||
XYtype = RECORD
|
||||
x, y : INTEGER;
|
||||
END;
|
||||
|
||||
DispenserPointerType = ^DispenserType;
|
||||
DispenserType = RECORD
|
||||
xy : XYtype;
|
||||
next : DispenserPointerType;
|
||||
END;
|
||||
|
||||
{ layout of LADDER.DAT data file }
|
||||
DataFileType = RECORD
|
||||
TerminalName : STRING[DataFileStrLength];
|
||||
MoveCsrPrefix : STRING[DataFileStrLength];
|
||||
MoveCsrSeparator : STRING[DataFileStrLength];
|
||||
MoveCsrSuffix : STRING[DataFileStrLength];
|
||||
UnkEscSeq : STRING[DataFileStrLength]; { not sure what this is... initialization? }
|
||||
ClrScrStr : STRING[DataFileStrLength];
|
||||
Flags : ARRAY[0..DataFileStrLength] OF CHAR;
|
||||
Keys : ARRAY[0..DataFileStrLength] OF CHAR;
|
||||
Highs : ARRAY[1..NumHighScores] OF ARRAY[0..DataFileStrLength] OF BYTE;
|
||||
Unused1 : ARRAY[0..DataFileStrLength] OF BYTE;
|
||||
Unused2 : ARRAY[0..DataFileStrLength] OF BYTE; { padding to next 128 bytes }
|
||||
Unused3 : ARRAY[0..DataFileStrLength] OF BYTE;
|
||||
END;
|
||||
|
||||
HighScoreType = RECORD
|
||||
Score : INTEGER;
|
||||
Name : STRING[DataFileNameLength];
|
||||
END;
|
||||
|
24
LadderTP/LADUTILS.PAS
Normal file
24
LadderTP/LADUTILS.PAS
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
Some terminal routines not handled by Turbo Pascal.
|
||||
|
||||
CursOff: turn the cursor off (set the string in LADCONST.PAS)
|
||||
CursOn: turn the cursor on (set the string in LADCONST.PAS)
|
||||
Beep: ring the terminal bell
|
||||
}
|
||||
|
||||
PROCEDURE CursOff;
|
||||
BEGIN
|
||||
Write(CursOffStr);
|
||||
END;
|
||||
|
||||
PROCEDURE CursOn;
|
||||
BEGIN
|
||||
Write(CursOnStr);
|
||||
END;
|
||||
|
||||
PROCEDURE Beep;
|
||||
BEGIN
|
||||
IF sound THEN
|
||||
Write(#7);
|
||||
END;
|
||||
|
17
LadderTP/LADVAR.PAS
Normal file
17
LadderTP/LADVAR.PAS
Normal file
@ -0,0 +1,17 @@
|
||||
VAR
|
||||
dispensers : DispenserPointerType; { rock dispensers linked list }
|
||||
numDispensers : INTEGER; { # of dispensers on current level }
|
||||
lastScore : INTEGER; { score from last completed game }
|
||||
playSpeed : INTEGER;
|
||||
m : MapDataType;
|
||||
lad : ActorType;
|
||||
ladXY : XYtype; { starting position of lad }
|
||||
nextNewLad : INTEGER; { score for next new lad awarded }
|
||||
dataFileContents : DataFileType;
|
||||
highScores : ARRAY[1..NumHighScores] OF HighScoreType;
|
||||
sound : BOOLEAN; { TRUE for sound }
|
||||
insults : BOOLEAN; { TRUE for insults }
|
||||
levelCycle : INTEGER;
|
||||
displayLevel : INTEGER; { displayed map level }
|
||||
upKey, downKey, leftKey, rightKey : CHAR; { lad direction control keys }
|
||||
|
108
LadderTP/README.md
Normal file
108
LadderTP/README.md
Normal file
@ -0,0 +1,108 @@
|
||||
# Ladder
|
||||
|
||||
The classic CP/M game Ladder reverse engineered in Turbo Pascal.
|
||||
|
||||
Original GitHub repository: https://github.com/mecparts/Ladder
|
||||
|
||||
Additional information and compiled version by Anna Christina Naß <acn@acn.wtf>
|
||||
|
||||
I've added a compiled ``LADDER.COM`` file for just playing the game (on a VT100
|
||||
terminal at about 8 MHz, eg. a RC2014), and added more information on
|
||||
compiling the game.
|
||||
|
||||
## Keys
|
||||
|
||||
The file ``LADDER.DAT`` is the configuration file that holds the key definitions.
|
||||
These can be changed by using ``LADCONF.COM`` (the terminal definition
|
||||
in LADCONF is not used! This LADDER uses the Turbo Pascal terminal definitions).
|
||||
|
||||
The default keys in this ``LADDER.DAT`` are:
|
||||
|
||||
Up = 8 Down = 2 Left = 4 Right = 6
|
||||
Jump = Space Stop = Other
|
||||
|
||||
(Jump and Stop are not configurable)
|
||||
|
||||
Also, "bell" sound is enabled and "wise crack marks" are disabled.
|
||||
|
||||
## Compiling notes from Anna:
|
||||
|
||||
To compile LADDER, just use Turbo Pascal from the ``TP/`` directory.
|
||||
It's TP 3.0A for CP/M-80, only without the demo source code.
|
||||
|
||||
* Copy the TP files together with the LADDER files to one disk
|
||||
* The terminal definition is already set to ANSI and the speed is set to 8 MHz (for a
|
||||
standard RC2014), so running TINST is not needed
|
||||
* Run Turbo Pascal using TURBO
|
||||
* Set the compiler options to "compile -> Com-file" (press O, C, Q)
|
||||
* Compile ``LADDER.PAS``: press C (Compile), then enter ``ladder`` as Work file name.
|
||||
|
||||
This should result in a ``LADDER.COM`` file.
|
||||
|
||||
The rest of this file is mostly the README from the original repository.
|
||||
|
||||
# Original README content:
|
||||
|
||||
## About
|
||||
This is a rewrite in Turbo Pascal of the classic CP/M game "Ladder",
|
||||
originally written by Yahoo Software (not Yahoo!).
|
||||
|
||||
Ladder is an ASCII character based platform arcade game similar to
|
||||
Donkey Kong. You travel through levels with platforms and ladders
|
||||
where rocks fall down from the top while you collect statues
|
||||
before reaching the exit.
|
||||
|
||||
Back in 1999 Stephen Ostermiller made a version of [Ladder in
|
||||
Java](http://ostermiller.org/ladder/). Later, Mats Engstrom of
|
||||
SmallRoomLabs started another version in of [Ladder in
|
||||
golang](https://github.com/SmallRoomLabs/ladder). Between my own
|
||||
memories of playing the original game on a Kaypro, and Stephen
|
||||
Ostermiller's and Mats Engstrom's code, I was able to come up
|
||||
with this version.
|
||||
|
||||
This version will use the original LADCONF.COM configuration program
|
||||
and LADDER.DAT configuration file. Since this version is a Turbo
|
||||
Pascal program, the terminal configuration portion of LADCONF
|
||||
isn't used, though it still does set up the movement keys, sound
|
||||
and back chatter options.
|
||||
|
||||
## Compiling the game
|
||||
|
||||
You'd need Turbo Pascal, of course. You'll also need to edit
|
||||
LADCONST.PAS to set the cursor on and off sequences for your
|
||||
terminal. LADDER.PAS is the main part of the program. I've
|
||||
successfully compiled this on a 58K CP/M system, so available RAM
|
||||
isn't a particularly critical limitation.
|
||||
|
||||
Once you've compiled LADDER.COM, copy LADCONF.COM to the same user area.
|
||||
If you don't have a LADDER.DAT file, when you run LADDER the first time
|
||||
it'll automatically load LADCONF to set up the movement keys and
|
||||
options, then transfer you back to LADDER.
|
||||
|
||||
## Limitations
|
||||
|
||||
At the moment, once you've successfully completed the 7th distinct level
|
||||
(Gang Land), the program just cycles through all 7 seven levels over and
|
||||
over again until the bonus time becomes too short to actually finish a
|
||||
level. If anyone knows what the original program actually did (I never
|
||||
managed to get anywhere near to completing the original game), let me
|
||||
know and I'll see what I can do.
|
||||
|
||||
The Delay(ms) call in Turbo Pascal only works for a Z80 running
|
||||
at up to 32MHz (and TINST will only allow you to specify a value of up
|
||||
to 20MHZ if I recall correctly). So if you're trying to run this on a
|
||||
system with an effective clock speed of greater than 32MHz, you're going
|
||||
to have to come up with another mechanism. That's not an insurmountable
|
||||
roadblock though; on my 144MHz-Z80-equivalent RunCPM box running on a
|
||||
Teensy 4.0, I patched the Turbo Pascal runtime to make a call to a BDOS
|
||||
extension I created to call the Arduino's delay() function. Works like
|
||||
a charm. If your system includes any kind of millisecond counter you can
|
||||
read, that's a good spot to start looking.
|
||||
|
||||
## References
|
||||
|
||||
[Original Ladder game](http://www.classiccmp.org/cpmarchives/cpm/Software/WalnutCD/lambda/soundpot/f/ladder13.lbr)<br>
|
||||
[Ladder in Java](http://ostermiller.org/ladder/)<br>
|
||||
[Ladder in golang](https://github.com/SmallRoomLabs/ladder)<br>
|
||||
|
||||
|
181
LadderTP/TP/READ.ME
Normal file
181
LadderTP/TP/READ.ME
Normal file
@ -0,0 +1,181 @@
|
||||
|
||||
Welcome to TURBO PASCAL Version 3.0!
|
||||
------------------------------------
|
||||
|
||||
In spite of all efforts, some errors have found their way into
|
||||
the new TURBO 3.0 manual. This file contains all the necessary
|
||||
corrections and additions, and we apologize for any inconvenience
|
||||
this may cause you.
|
||||
|
||||
Please make a working copy of your TURBO disk and store the ori-
|
||||
ginal in a safe place. For help making a backup copy, please
|
||||
refer to appendix M of the TURBO PASCAL Reference Manual.
|
||||
|
||||
NOTEº Youò TURBÏ PASCAÌ disë haó beeî pre-installeä foò youò <20>
|
||||
Microbeå disë system¬ paù nï attentioî tï thå manuaì witè regardó <20>
|
||||
to installing TURBO PASCAL.
|
||||
|
||||
|
||||
*******************************************
|
||||
* *
|
||||
* Need help with TURBO? Please see *
|
||||
* Appendix N in your Reference Manual *
|
||||
* for answers to common questions. *
|
||||
* *
|
||||
*******************************************
|
||||
|
||||
|
||||
-------------------
|
||||
|
||||
|
||||
Contents of the READ.ME File
|
||||
----------------------------
|
||||
1. CORRECTIONS to the 3.0 Reference Manual [ All versions ]
|
||||
2. OMMISSIONS from the 3.0 Reference Manual [ All versions ]
|
||||
3. New FEATURES [ CP/M-80 ]
|
||||
4. ADDITIONAL FILE LIST [ CP/M-80 ]
|
||||
|
||||
|
||||
-------------------
|
||||
|
||||
|
||||
CORRECTIONS
|
||||
-----------
|
||||
|
||||
|
||||
Page 253 - MOV AL,[BP-1]
|
||||
------------------------
|
||||
The correct statement is: MOV AL,[BP+4]
|
||||
|
||||
|
||||
Page 293 - TURBO-BCD will compile and run any program
|
||||
-----------------------------------------------------
|
||||
Well - almost. The Real functions Sin, Cos, ArcTan, Ln, Exp,
|
||||
and Sqrt and the pre-declared constant Pi are not available
|
||||
in TURBOBCD.
Š
|
||||
|
||||
-------------------
|
||||
|
||||
|
||||
OMISSIONS
|
||||
---------
|
||||
|
||||
|
||||
User Written Error Handlers
|
||||
---------------------------
|
||||
In Turbo Pascal 3.0 you may write your own error handler,
|
||||
which is called in case of an I/O or Run-time error. The
|
||||
procedure must have the following header:
|
||||
|
||||
procedure Error(ErrNo, ErrAddr: Integer);
|
||||
|
||||
The name of the procedure and its parameters are unim-
|
||||
portant, as long as it is a procedure with two value
|
||||
parameters of type Integer.
|
||||
|
||||
The value passed in ErrNo is the error type and number. The
|
||||
most significant byte, i.e. "Hi(ErrNo)", contains the error
|
||||
type, and the least significant byte, i.e. "Lo(ErrNo)",
|
||||
contains the error number (see Appendix F or G in the Turbo
|
||||
Pascal Manual).
|
||||
|
||||
The following error types are defined:
|
||||
|
||||
0 User Break (Ctrl-C).
|
||||
1 I/O error.
|
||||
2 Run-time error.
|
||||
|
||||
In case of a user interrupt (Ctrl-C), the low byte of
|
||||
"ErrNo" is always 1. "ErrAddr" contains the address (offset
|
||||
in Code Segment for 16 bit versions) of the error.
|
||||
|
||||
To activate the error handler, assign its offset address
|
||||
to the standard variable "ErrorPtr", i.e.
|
||||
|
||||
ErrorPtr:=Ofs(Error); { 16 bit } or
|
||||
ErrorPtr:=Addr(Error); { 8 bit }
|
||||
|
||||
There are no limits to what an error handler may do. Typi-
|
||||
cally it will close all open files, output an error mes-
|
||||
sage, and call the Halt standard procedure to terminate the
|
||||
program. If an error handler returns, i.e. if it does
|
||||
not call Halt, or if an error occurs within an error
|
||||
handler, Turbo Pascal will itself output the error message
|
||||
and terminate the program.
|
||||
|
||||
|
||||
|
||||
|
||||
-------------------
Š
|
||||
|
||||
NEW FEATURES OF CP/M-80 IMPLEMENTATION OF
|
||||
TURBO 3.0
|
||||
- AN OVERVIEW -
|
||||
-----------------------------------------
|
||||
|
||||
Inline
|
||||
------
|
||||
A constant identifier used in an INLINE statement does not
|
||||
always generate two bytes of code.
|
||||
|
||||
Files
|
||||
-----
|
||||
New FIB formats.
|
||||
Optional 4th parameter on Blockread/Write returns number of
|
||||
blocks actually read.
|
||||
SeekEoln function.
|
||||
SeekEof function.
|
||||
|
||||
|
||||
Misc.
|
||||
-----
|
||||
Exit procedure - To exit the current block
|
||||
OvrDrive procedure - To specify the drive on which to find overlays
|
||||
ParamCount function - Gives number of characters in the command buffer
|
||||
ParamStr function - Gives the string of characters in the command line
|
||||
|
||||
Overlays
|
||||
--------
|
||||
|
||||
Overlay files are opened and closed every time they are
|
||||
accessed. Therefore, there is never a need to specifically
|
||||
close an overlay file.
|
||||
|
||||
The Y compiler directive is no longer supported. Instead,
|
||||
the OvrPath (MS-DOS) or OvrDrive (CP/M) standard proce-
|
||||
dures may be used to specify the drive and subdirectory
|
||||
in which overlay files reside.
|
||||
|
||||
Please note that run-time error F0 indicates that your over-
|
||||
lay file is missing or is called recursively. (This error
|
||||
number is omitted from the Reference Manual but is included
|
||||
elsewhere in this file.)
|
||||
|
||||
|
||||
-------------------
|
||||
|
||||
TURBO PASCAL Version 3.0
|
||||
CP/M-80
|
||||
Additional File List
|
||||
|
||||
In addition to the list of files mentioned in Chapter 1 of
|
||||
your TURBO Reference Manual, the following files are included
|
||||
on your TURBO disk:
Š
|
||||
Sample programs
|
||||
---------------
|
||||
LISTER PAS - simple program to list your Pascal source
|
||||
CMDLIN PAS - get parameters from the command line
|
||||
|
||||
MC PAS - sample spreadsheet program - MAIN MODULE
|
||||
MC-MOD00 INC - sample spreadsheet program - INCLUDE MODULE 00
|
||||
MC-MOD01 INC - sample spreadsheet program - INCLUDE MODULE 01
|
||||
MC-MOD02 INC - sample spreadsheet program - INCLUDE MODULE 02
|
||||
MC-MOD03 INC - sample spreadsheet program - INCLUDE MODULE 03
|
||||
MC-MOD04 INC - sample spreadsheet program - INCLUDE MODULE 04
|
||||
MC-MOD05 INC - sample spreadsheet program - INCLUDE MODULE 05
|
||||
MC HLP - spreadsheet help file
|
||||
MCDEMO MCS - spreadsheet data file (not for use with TURBO-87)
|
||||
|
||||
---------------------------------------------------------------------
|
||||
|
||||
|
BIN
LadderTP/TP/TINST.COM
Normal file
BIN
LadderTP/TP/TINST.COM
Normal file
Binary file not shown.
BIN
LadderTP/TP/TINST.DTA
Normal file
BIN
LadderTP/TP/TINST.DTA
Normal file
Binary file not shown.
123
LadderTP/TP/TINST.MSG
Normal file
123
LadderTP/TP/TINST.MSG
Normal file
@ -0,0 +1,123 @@
|
||||
1 TURBO Pascal installation menu.
|
||||
2 Choose installation item from the following:
|
||||
3
|
||||
4 [S]creen installation | [C]ommand installation | [Q]uit
|
||||
5
|
||||
6 Enter S, C, or Q:
|
||||
10 Duplicate definition. Error occurred between question
|
||||
11 Commands starting with the same letter must have the same length.
|
||||
Error occurred between question
|
||||
12 The total maximum length of commands are execeeded
|
||||
13 ->
|
||||
|
||||
|
||||
14 CURSOR MOVEMENTS:
|
||||
|
||||
20 Character left
|
||||
21 Alternative
|
||||
22 Character right
|
||||
23 Word left
|
||||
24 Word right
|
||||
25 Line up
|
||||
26 Line down
|
||||
27 Scroll down
|
||||
28 Scroll up
|
||||
29 Page up
|
||||
30 Page down
|
||||
31 To left on line
|
||||
32 To right on line
|
||||
33 To top of page
|
||||
34 To bottom of page
|
||||
35 To top of file
|
||||
36 To end of file
|
||||
37 To begining of block
|
||||
38 To end of block
|
||||
39 To last cursor position
|
||||
|
||||
|
||||
15 INSERT & DELETE:
|
||||
|
||||
40 Insert mode on/off
|
||||
41 Insert line
|
||||
42 Delete line
|
||||
43 Delete to end of line
|
||||
44 Delete right word
|
||||
45 Delete character under cursor
|
||||
46 Delete left character
|
||||
47 Alternative
|
||||
|
||||
|
||||
16 BLOCK COMMANDS:
|
||||
|
||||
48 Mark block begin
|
||||
49 Mark block end
|
||||
50 Mark single word
|
||||
51 Hide/display block
|
||||
52 Copy block
|
||||
53 Move block
|
||||
54 Delete block
|
||||
55 Read block from disk
|
||||
56 Write block to disk
|
||||
|
||||
|
||||
17 MISC. EDITING COMMANDS:
|
||||
|
||||
57 End edit
|
||||
58 Tab
|
||||
59 Auto tab on/off
|
||||
60 Restore line
|
||||
61 Find
|
||||
62 Find & replace
|
||||
63 Repeat last find
|
||||
64 Control character prefix
|
||||
|
||||
101 Nothing
|
||||
^Q: Quit, ^R: Last page, ^C: Next page, <RETURN>: Select terminal:
|
||||
Wait Sorting Definitions
|
||||
Change to:
|
||||
(Y/N)?
|
||||
y
|
||||
n
|
||||
Text file name:
|
||||
Command:
|
||||
Numeric entry expected
|
||||
Legal range is
|
||||
, please re-enter:
|
||||
Choose one of the following terminals:
|
||||
None of the above ( Max. 20 Characters )
|
||||
Delete a definition ( Max. 20 Characters )
|
||||
Which terminal? (Enter no. or ^Q to exit):
|
||||
Delete terminal? (Enter no. or ^Q to exit):
|
||||
Do you want to modify this definition before installation?
|
||||
Terminal type:
|
||||
Send an initialization string to the terminal?
|
||||
Initializaion defined as a command string? (No = a file)
|
||||
Send a reset string to the terminal
|
||||
Reset defined as a command? (No = a file)
|
||||
CURSOR LEAD-IN command:
|
||||
CURSOR POSITIONING COMMAND to send between line and column:
|
||||
CURSOR POSITIONING COMMAND to send after both line and column:
|
||||
Column first
|
||||
OFFSET to add to LINE:
|
||||
OFFSET to add to COLUMN:
|
||||
Binary address
|
||||
Number of ASCII digits (2 or 3):
|
||||
CLEAR SCREEN command:
|
||||
Does CLEAR SCREEN also HOME cursor
|
||||
HOME command:
|
||||
DELETE LINE command:
|
||||
INSERT LINE command:
|
||||
ERASE TO END OF LINE command:
|
||||
START HIGHLIGHTING command:
|
||||
END HIGHLIGHTING command:
|
||||
Number of rows (lines) on your screen:
|
||||
Number of columns on your screen:
|
||||
Delay after CURSOR ADDRESS (0-255 ms):
|
||||
Delay after CLEAR, DELETE and INSERT (0-255 ms):
|
||||
Delay after ERASE TO END OF LINE and HIGHLIGHT (0-255 ms):
|
||||
Is this definition correct?
|
||||
Hardware dependent information
|
||||
Operating frequency of your microprocessor in MHz (for delays):
|
||||
pendent information
|
||||
Operating frequency of your microprocessor in MHz (for delays):
|
||||
|
BIN
LadderTP/TP/TURBO.COM
Normal file
BIN
LadderTP/TP/TURBO.COM
Normal file
Binary file not shown.
101
LadderTP/TP/TURBO.MSG
Normal file
101
LadderTP/TP/TURBO.MSG
Normal file
@ -0,0 +1,101 @@
|
||||
are not allowed
|
||||
can not be
|
||||
constant
|
||||
does not
|
||||
expression
|
||||
identifier
|
||||
file
|
||||
here
|
||||
Integer
|
||||
File
|
||||
Illegal
|
||||
or
|
||||
Undefined
|
||||
match
|
||||
real
|
||||
String
|
||||
Textfile
|
||||
out of range
|
||||
variable
|
||||
overflow
|
||||
expected
|
||||
type
|
||||
Invalid
|
||||
pointer
|
||||
01';'
|
||||
02':'
|
||||
03','
|
||||
04'('
|
||||
05')'
|
||||
06'='
|
||||
07':='
|
||||
08'['
|
||||
09']'
|
||||
10'.'
|
||||
11'..'
|
||||
12BEGIN
|
||||
13DO
|
||||
14END
|
||||
15OF
|
||||
17THEN
|
||||
18TO DOWNTO
|
||||
20Boolean
|
||||
21
|
||||
22
|
||||
23
|
||||
24
|
||||
25
|
||||
26
|
||||
27
|
||||
28Pointer
|
||||
29Record
|
||||
30Simple
|
||||
31Simple
|
||||
32
|
||||
33
|
||||
34
|
||||
35
|
||||
36Type
|
||||
37Untyped
|
||||
40 label
|
||||
41Unknown syntax error
|
||||
42 in preceding definitions
|
||||
43Duplicate label
|
||||
44Type mismatch
|
||||
45
|
||||
46 and CASE selector
|
||||
47Operand(s) operator
|
||||
48 result
|
||||
49 length
|
||||
50 length
|
||||
51 subrange base
|
||||
52Lower bound > upper bound
|
||||
53Reserved word
|
||||
54 assignment
|
||||
55 exceeds line
|
||||
56Error in integer
|
||||
57Error in
|
||||
58 character in
|
||||
60s
|
||||
61s ands
|
||||
62Structureds
|
||||
63s
|
||||
64s and untypeds
|
||||
65Untypeds
|
||||
66I/O
|
||||
67s must be parameters
|
||||
68 componentss
|
||||
69dering of fields
|
||||
70Set base
|
||||
71 GOTO
|
||||
72Label not within current block
|
||||
73 FORWARD procedure(s)
|
||||
74INLINE error
|
||||
75 use of ABSOLUTE
|
||||
90 not found
|
||||
91Unexpected end of source
|
||||
97Too many nested WITH's
|
||||
98Memory
|
||||
99Compilerd WITH's
|
||||
98Memory
|
||||
99Compiler
|
BIN
LadderTP/TP/TURBO.OVR
Normal file
BIN
LadderTP/TP/TURBO.OVR
Normal file
Binary file not shown.
@ -18,6 +18,7 @@ See this repository: https://git.imzadi.de/acn/backgammon-vt100
|
||||
|
||||
* [2048](2048/)
|
||||
* [Ladder](Ladder/)
|
||||
* [Ladder (Turbo Pascal version)](LadderTP/)
|
||||
* [Rogue](Rogue/)
|
||||
* [Wanderer](Wanderer/)
|
||||
* [CatChum](CatChum/)
|
||||
@ -34,7 +35,6 @@ See this repository: https://git.imzadi.de/acn/backgammon-vt100
|
||||
|
||||
* [Gorilla.bas](https://github.com/sblendorio/gorilla-cpm): GORILLA.BAS port to CP/M in Turbo Modula-2. Supported terminals: VT52, VT100, ANSI, ADM-31, KayPro, C128, Memotech monochrome, CPC / Zenith Z19
|
||||
* [Hangman](https://github.com/sblendorio/hangman-cpm): C implementation for CP/M of the classic "hangman" included in "bsdgames" popular package for UNIX
|
||||
* [Ladder](https://github.com/mecparts/Ladder): Turbo Pascal reimplementation of Ladder (see above)
|
||||
|
||||
## HD image
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user