Вы находитесь на странице: 1из 28

{$S+}

{$R+} {Range checking off}


{$I-} {I/O checking off}
{$N-} {No numeric coprocessor}

program SneeSnooSnake;

{ COPYRIGHT (C) 1986, 1987, 1989 BRUCE LAMAR ROSENBERG }

Uses
Crt, {Unit found in TURBO.TPL}
Dos; {Unit found in TURBO.TPL}

const
version = '5.0'; { current version of program }
snakefile = 'SNAKE.DAT'; { filename where top 20 scores saved }
lin = 6; {length of straight line to keep from going back over self, i.e.,
goes in straight line for LIN moves. }
snlen = 13; { length of snake, approx. 2 times lin }
toplist = 1;
botlist = 20; { size of score list }
namelen = 21; { length of name & namearray for entry on score list }
p = 1.112; { twelfth root of two squared for generating musical scale }
pctime = 8.460; { time taken by IBM pc to do chkspeed routine }

type
regrec = record
ax,bx,cx,dx,bp,di,si,ds,es,flags: integer;
end;
snptr = ^snrec;
snrec = record
x,y : byte;
next : snptr;
end;
namearray = array [toplist..botlist] of string[namelen];
scorearray = array [toplist..botlist] of real;
namestr = string[namelen];
censtr = string[80];
rnamestr = string[6];

var
autodem,demo,dying,deadly,bitten,NoFile,bagged,tooclose,soundon : boolean;
quickout,keyed,ReadOnce,firsttime, timeout : boolean;
CPUspeed,pscore,time,starttime : real;
n2autodem,nticks,bagdelay,i,n : byte;
head, neck, tail : snptr;
nsnakes,ndsnakes,nbites,ndbites : byte;
j,k : byte;
xt,yt,oldx,oldy,deltx,delty : integer;
OldBagCmd,BagCmd,SnooHead,SnooBody,SneeHead,SneeBody,ch,menusel : char;
SnooHdColor,SnooBdColor,SneeHdColor,SneeBdColor : byte;
name : namearray; score : scorearray;
pname : namestr;
rname : rnamestr;
regs : regrec;
dancedelay,blx,bly,oldblx,oldbly : integer;
waitbag,waitsn,autodelay,nrobo,ns : integer;
minX,minY,maxX,maxY,oldtime,alldelay : integer;
KPthisTime,KPlastTime,wipetrail : boolean;
btx,bty,nlen,n2die : integer;
rslack,tcount,L,R,T,B,bagszx,bagszy,bitedx,bitedy : integer;
bagVSsnake,gamespeed,robodelay,difbagged,oldbagged,nbagged : integer;
supvtime,playtime,timeleft,elapsedtime,incrdelay,decrdelay : integer;
KeyScan,OldScan : byte;
OldVec,exitsave : pointer;
{============================================================================}
procedure initialize;
var
ns : byte;
begin
minX := 1;
maxX := 78; {hor. text screen limit, STARTS AT 1 at LEFT, NOT 0! }
{ don't use 80 because screen handler automatically puts in CR,LF }
minY := 1;
maxY := 24; { vert. text screen limit, STARTS AT 1 at TOP, NOT 0! }
{don/t go to line 25 because screen control then starts scrolling }
SnooBody := '%';
SnooHead := '�';
SneeBody := '0';
SneeHead := char(2); { happy face }
SnooHdColor := white;
SnooBdColor := cyan;
SneeHdColor := lightred;
SneeBdColor := lightgreen;
quickout := false;
soundon := true;
autodem := true;
n2autodem:= 10;
autodelay := 100; { time between doticks for self-running prompt }
playtime := 120; { 120 seconds or two minutes }
robodelay := 1;
rslack := 1; { slack distance for robot movement }
dancedelay := 10; { delay for snake dance rate }
alldelay := 1; { starting value, delays both snake and bag movement }
bagdelay := 1;
n2die := 5; { # bites before die }
bagszx := 3; { bag size in x }
bagszy := 2; { bag size in y }
bitedx := 5; { snake striking distance in x }
bitedy := 4; { snake striking distance in y }
supvtime := 3; { interval (seconds) at which supervisegame called }
(*** this time interval is critical to the speed change algorithm ***)
end; { initialize }
{============================================================================}
procedure showoff_init;
begin
demo := true;
soundon := true; { true;}
playtime := 25; { changed from 120 seconds or two minutes }
n2die := 4; { # bites before die }
end;
{============================================================================}
function timer: real;
var
regs: regrec; {assign record}
ah,al,ch,cl,dh: byte;
hr,mn,sc,th : byte;
begin
ah := $2c; { call DOS fcn to get system time }
with regs do
begin
ax := ah shl 8 + al;
end;
intr($21,Dos.Registers(regs)); {call interrupt}
with regs do
begin
hr := cx shr 8; { LO(cx) }
mn := cx mod 256; { HI(cx) }
sc := dx shr 8; { more significant byte }
th := dx mod 256; { less significant byte }
end;
timer := ((hr*3600)+(mn*60)+sc)+(th/100); { returns time in seconds }
end; { function timer }
{----------------------------------------------------------------------------}
function chkspeed : real;

var elapstime, init, fin : real;


nt,nu : integer;
sum : longint;
begin
init := timer;
for nt := 1 to 200 do
begin
for nu := 1 to 1000 do
sum := sum + 1;
end;
fin := timer;
elapstime := fin-init;
chkspeed := elapstime;
end;
{----------------------------------------------------------------------------}
function KeyHit(VAR ch: char) : boolean;
begin
regs.AX := $0600; { call DOS Direct Console I/O }
regs.DX := 255; { choses read func w/o echo }
intr($21,Dos.Registers(regs)); { invoke a DOS function request }
ch := char(regs.AX);
KeyHit := ch <> Chr(0); { return the boolean }
end; { function KeyHit }
{----------------------------------------------------------------------------}
function monochrome: boolean;
var regs : regrec;
begin
intr(17,Dos.Registers(regs));
if (regs.ax) and $0030 = $30 then monochrome := true
else monochrome := false;
end; { function monochrome }
{----------------------------------------------------------------------------}
procedure setvidmode;
var regs : regrec;
begin
with regs do
begin
if monochrome then ax := $0007 else ax := $0003;
end; { with }
intr(16,Dos.Registers(regs));
end; { procedure setvidmode }
{----------------------------------------------------------------------------}
procedure curson;
var regs : regrec;
begin
with regs do
begin
ax := $0100;
if monochrome then cx := $0B0C else cx := $0607;
end; { with }
intr(16,Dos.Registers(regs));
end; { procedure curson }
{----------------------------------------------------------------------------}
procedure cursoff;
var regs : regrec;
begin
with regs do
begin
ax := $0100;
cx := $2000;
end; { with }
intr(16,Dos.Registers(regs));
end; { procedure cursoff }
{----------------------------------------------------------------------------}
procedure cen(cstring : censtr);
begin
gotoxy(40-length(cstring) div 2,wherey);
write(cstring);
end;
{----------------------------------------------------------------------------}
procedure cenln(cstring : censtr);
begin
gotoxy(40-length(cstring) div 2,wherey);
writeln(cstring);
end;
{----------------------------------------------------------------------------}
procedure censcr(cstring : censtr);
begin
gotoxy(40-length(cstring) div 2,12);
write(cstring);
end;
{----------------------------------------------------------------------------}
procedure upscale;
var
n : byte;
s : real;
begin
n := 0;
s:= 880.0;
for n := 1 to 12 do
begin
s := s*p;
if soundon then sound(trunc(s));
delay(30);
nosound;
delay(16-n);
end;
end;
{----------------------------------------------------------------------------}
procedure dnscale;
var
n : byte;
s : real;
begin
n := 0;
s:= 1760.0;
for n := 1 to 12 do
begin
s := s/p;
if soundon then sound(trunc(s));
delay(30);
nosound;
delay(16-n);
end;
end;
{----------------------------------------------------------------------------}
procedure uptweet;
var
i : byte;
s : real;
begin
s := 1760.0;
begin
for i := 1 to 12 do
begin
s := s*p;
if soundon then sound(trunc(s));
delay((16-i));
end;
end;
nosound;
end;
{----------------------------------------------------------------------------}
procedure dntweet;
var
i : byte;
s : real;
begin
s := 3520.0;
begin
for i := 1 to 12 do
begin
s := s/p;
if soundon then sound(trunc(s));
delay((16-i));
end;
end;
nosound;
end;
{----------------------------------------------------------------------------}
procedure dotick;
var
i : byte;
s : real;
begin
s := 1000.0;
begin
if soundon then sound(trunc(s));
delay(4);
end;
nosound;
end;

{----------------------------------------------------------------------------}
function GetKey: char;
var ch : char;
begin
Ch := crt.readkey;
memw[0:$41a] := memw[0:$41c]; {Clears keyboard buffer quickly by
setting head & tail equal to each other}
GetKey := ch;
end;
{----------------------------------------------------------------------------}
procedure ClrKey;
begin
memw[0:$41a] := memw[0:$41c]; {Clears keyboard buffer quickly by
setting head & tail equal to each other}
end;
{----------------------------------------------------------------------------}
procedure AutoContinue;
begin
timeout := false;
nticks := 0;
textcolor(white);
gotoxy(1,25);
write('Press a key for menu ----');
gotoxy(35,25);
write('RUN AUTO DEMO');
gotoxy(25,25);
cursoff;
repeat
delay(autodelay);
dotick;
write('>');
nticks := succ(nticks);
timeout := nticks = n2autodem;
until timeout or keypressed;
if keypressed then
begin
ClrKey;
autodem := false
end else
autodem := true;
curson;
uptweet;
end;
{----------------------------------------------------------------------------}
procedure PressToContinue;
begin
textcolor(white);
gotoxy(1,25);
write('Press a key for menu --- ');
repeat until keypressed;
ClrKey;
end;
{----------------------------------------------------------------------------}
procedure menu; FORWARD;
{----------------------------------------------------------------------------}
procedure afterdeath; { return to menu through here if killed }
var
ncells : integer;
begin
gotoxy(1,1);
port[$3D9] := black;
textcolor(0);
for ncells := 1 to 2000 do write(char(219));
curson;
textbackground(black);
textcolor(white);
end;
{============================================================================}
procedure ZeroScoreArray;
var
n : byte;
begin
for n := toplist to botlist do
begin
name[n] := '';
repeat name[n] := name[n] + '.' until length(name[n]) = namelen;
score[n] := 0;
end;
end;
{----------------------------------------------------------------------------}
procedure WriteScoreArray;
var
infile : text;
n : byte;
begin
assign(infile,snakefile);
rewrite(infile);
for n := toplist to botlist do
begin
writeln(infile,name[n],' ',score[n]);
end;
close(infile);
end;
{----------------------------------------------------------------------------}
procedure ReadScoreArray;
var
infile : text;
n :byte;
begin
assign(infile,snakefile);
{$I-} reset(infile) {$I+}; { check if the 'snake.dat' file exists. }
NoFile := (IOresult = 2);
if NoFile then { if not, then create it }
begin
zeroscorearray;
writescorearray;
end
else
close(infile); { When using autodemo I had to add this to prevent
"too many files open" error.}
assign(infile,snakefile); { NOW that it exists, we can read from it }
reset(infile); { without crashing. }
for n := toplist to botlist do
begin
readln(infile,name[n],score[n]);
end;
close(infile);
end;
{----------------------------------------------------------------------------}
function roboname : rnamestr;

type
tristr = string[3] ;
var
vowels : string[7] ;
consonants : string[20] ;
rname1,rname2 : string[3];
ch : char;
{----------------------------------------------------------------------------}
procedure rnameinit;
begin
consonants := 'bdfgklmnprssttvwz';
vowels := 'aaeeiou';
{ consonants := 'BDFGKLMNPRSSTTVWZ';
vowels := 'AAEEIOU';
}
randomize;
end;
{----------------------------------------------------------------------------}

function triad: tristr;


var tri : string[3]; v1,c1,c2 : integer;
begin
c1 := 1+trunc(random(length(consonants)));
v1 := 1+trunc(random(length(vowels)));
c2 := 1+trunc(random(length(consonants)));
tri := consonants[c1];
tri := tri+ vowels[v1];
tri := tri+ consonants[c2];
triad := tri
end;

begin
rnameinit;
rname1 := triad;
rname2 := triad;
ch := char(ord(rname1[1])-$20); { capitalize first letter of name }
rname1[1] := ch;
roboname := rname1 + rname2;
end;
{----------------------------------------------------------------------------}
procedure robowrite;
var numstr : string[3]; nr : integer;
begin
nrobo := nrobo + 1;
rname := roboname;
str(nrobo:3,numstr);
pname := 'I '+rname+', robot #'+numstr+',';
for nr := 1 to length(pname) do
begin
write(pname[nr]);
dotick;
delay(200);
end;
end;
{----------------------------------------------------------------------------}
procedure checkscore;
var
i,j,k,n,insertpos : byte;
begin
if (pscore < score[botlist]) or (pscore <= 0) then
begin
gotoxy(1,11);
writeln('Sorry Hunter, your score of ',pscore:5:2,' is not in the top 20.');
if pscore < 0 then pscore := 0;
if autodem then AutoContinue else PressToContinue;
exit;
end
else
begin
while keypressed do ch:= readkey;
insertpos := toplist;
if pscore > score[toplist] then
begin
gotoxy(1,11);
writeln('WOW! You scored ',pscore:5:2,'. Hail the New Champion!');
end
else
begin
gotoxy(1,11);
writeln('Jolly Good! Your score of ',pscore:5:2,' is in the top 20.');
end;
writeln;
write('OK, SneeSnoo Snaker, enter your name here :');
for i := 1 to namelen do write('.');
write(':');
gotoxy(wherex-(namelen+1),wherey);
if demo then robowrite
else
read(pname);
repeat pname := pname + '.' until length(pname) = namelen;
{ find insert position }
while pscore < score[insertpos] do insertpos := succ(insertpos);
{ shift all down, starting at list bottom & losing lowest score }
for k := botlist-1 downto insertpos do { botlist > insertpos }
begin { **** must run this loop from bottom up! }
score[k+1] := score[k];
name[k+1] := name[k];
end;
score[insertpos] := pscore; { put new values in their place }
name[insertpos] := pname;
end;
end;
{----------------------------------------------------------------------------}
procedure listscores;
var
n : byte;
begin
clrscr;
cenln('HERE ARE THE SCORES FOR');
cenln('The Top 20 SneeSnoo Snake Snatchers:');
writeln;
for n := toplist to botlist do
begin
gotoxy(12,n+3);
writeln(n:3,'. ',name[n],' scored ',score[n]:5:2,' points per minute.');
end;
if autodem then AutoContinue else PressToContinue;
end;
{=========================== END SCOREBIZ ==============================}
procedure SnakeBiz;
FORWARD;
{----------------------------------------------------------------------------}
procedure die;
var
s : real;
ncells : integer;
nl,nshud : byte;
begin
s := 220;
clrscr;
gotoxy(1,1);
port[$3D9] := 15;
textcolor(15);
textbackground(15);
for ncells := 1 to 2000 do write(chr(219));
textcolor(black);
for nl := 1 to 16 do
begin
gotoxy(1,9 + nl);
cen(' ');
end;
gotoxy(1,15);
cen(' YOUR WORLDLY PROBLEMS ARE OVER. ');
gotoxy(1,18);
cen(' HUNTER, REST IN PEACE! ');
for nshud := 1 to 7 do
begin
s := s/p;
if soundon then sound(trunc(s));
delay(600+30*nshud);
end;
nosound;
afterdeath;
end;
{----------------------------------------------------------------------------}
procedure newsnake;
var
corner,nratl : byte;
begin
randomize;
new(head); new(neck); new(tail);
{ create beginning position for snake }
head^.x :=minX + trunc(random(maxX));
head^.y :=minY + trunc(random(maxY));
(*
for nratl := 1 to 30 do
begin
gotoxy(head^.x,head^.y);
write('#');
dotick;
delay(30);
gotoxy(head^.x,head^.y);
write(' ');
end;

corner := 1 + trunc(trunc(random(4));
case corner of
1: begin head^.x := maxX; head^.y := maxY; end; { bot. rt. }
2: begin head^.x := minX; head^.y := maxY; end; { bot. left }
3: begin head^.x := maxX; head^.y := minY; end; { top rt. }
4: begin head^.x := minX; head^.y := minY; end; { top left }
end;
*)
head^.next := head;
tail := head; neck := head; { set all pointers to head }
(* deltx := trunc(random(3))-1; delty := trunc(random(3))-1;
oldx := deltx; oldy := delty;
*)
nlen:=0; wipetrail := false;
end;
{----------------------------------------------------------------------------}
procedure eraseOldSnake;
begin
repeat { erase old snake }
gotoxy(tail^.x, tail^.y);
write(chr(32)); { write blank over snake tail end }
tail := tail^.next; { link to record one up ahead }
dispose(head^.next); { clear the old tail from memory }
head^.next := tail; { stores value of tail for disposal }
until head^.next = head;
dispose(head^.next);
head:=nil; neck:=nil; tail:=nil;
end;
{----------------------------------------------------------------------------}
procedure bagshut;
var
k,n,nbs : byte;
begin
L := blx - bagszx; R := blx + bagszx;
T := bly - bagszy; B := bly + bagszy;
textcolor(white);
gotoxy(L,T); write('�'); { scanwise order }
gotoxy(R,T); write('�');
gotoxy(L,B); write('�');
gotoxy(R,B); write('�');
uptweet;
bagged :=((head^.x >= blx-bagszx) and
(head^.x <= blx+bagszx) and
(head^.y >= bly-bagszy) and
(head^.y <= bly+bagszy));

tooclose :=((head^.x >= blx-bitedx) and


(head^.x <= blx+bitedx) and
(head^.y >= bly-bitedy) and
(head^.y <= bly+bitedy));

if bagged then
begin
eraseOldSnake;
if deadly then begin
ndsnakes := succ(ndsnakes);
L := blx - bagszx; R := blx + bagszx;
T := bly - bagszy; B := bly + bagszy;
textcolor(SnooBdColor);
gotoxy(L,T); write(SnooBody); { scanwise order }
gotoxy(R,T); write(SnooBody);
gotoxy(L,B); write(SnooBody);
gotoxy(R,B); write(SnooBody);
censcr('Snagged Snoo # ');
textcolor(SnooHdColor);
write(ndsnakes:2,' ',SnooHead);
uptweet;
upscale;
end else begin
nsnakes := succ(nsnakes);
L := blx - bagszx; R := blx + bagszx;
T := bly - bagszy; B := bly + bagszy;
textcolor(SneeBdColor);
gotoxy(L,T); write(SneeBody); { scanwise order }
gotoxy(R,T); write(SneeBody);
gotoxy(L,B); write(SneeBody);
gotoxy(R,B); write(SneeBody);
censcr('Snatched Snee # ');
textcolor(SneeHdColor);
write(nsnakes:2,' ',SneeHead);
upscale; { message displayed while music plays }
end;
gotoxy(10,12); clreol;
end; { bagged the snake }
if not bagged and tooclose then
begin
bitten := true;
if not deadly then
begin
nbites := succ(nbites);
{ change bag temporarily when bitten }
L := blx - bagszx; R := blx + bagszx;
T := bly - bagszy; B := bly + bagszy;
textcolor(SneeHdColor);
gotoxy(L,T); write(SneeHead); { scanwise order }
gotoxy(R,T); write(SneeHead);
gotoxy(L,B); write(SneeHead);
gotoxy(R,B); write(SneeHead);
port[$3d9] := 4; { make border red }
textcolor(SneeHdColor);
censcr('Snee Bite!');
dnscale; { message displayed while music plays }
port[$3d9] := 2; { make border green }
end else
begin
ndbites := succ(ndbites);
if ndbites = n2die then
begin
clrscr;
dying := true;
exit;
end;
L := blx - bagszx; R := blx + bagszx;
T := bly - bagszy; B := bly + bagszy;
textcolor(SnooHdColor);
gotoxy(L,T); write(SnooHead); { scanwise order }
gotoxy(R,T); write(SnooHead);
gotoxy(L,B); write(SnooHead);
gotoxy(R,B); write(SnooHead);
port[$3d9] := 15; { make border bright white }
dntweet;
gotoxy(28,12);
write((n2die-ndbites):2,' More & You DIE!');
dnscale; { message displayed while music plays }
port[$3d9] := 2; { make border green }
end; { if deadly }
for k := 1 to 40 do SnakeBiz; { make snake dance joyfully }
nosound; { turn snake dance sound off }
gotoxy(10,12); clreol;
bitten := false;
end; { bitten by snake }
if bagged then newsnake; { generate new snake starting point }
end;
{----------------------------------------------------------------------------}
procedure fastout;
begin
clrscr;
port[$3D9] := black; { set border to black }
curson; { turn cursor back on }
quickout := true;
{ halt; fast way out of the game if boss comes in }
end;
{----------------------------------------------------------------------------}
procedure robotplayer(VAR bcmd : byte);
begin
if (trunc(random(8)) > 4) then
begin
L := blx-bagszx; R := blx+bagszx; { L = left, R = right }
T := bly-bagszy; B := bly+bagszy; { T = top, B = bottom edges of bag }

if (head^.x < L) then bcmd := 34; { move L }


if (head^.x > R) then bcmd := 35; { move R }
if (head^.y < T) then bcmd := 21; { move U }
if (head^.y > B) then bcmd := 48; { move D }

if (((head^.x >= L-rslack) and


(head^.x <= R {+rslack} ) and
(head^.y >= T-rslack) and
(head^.y <= B {+rslack} )) and (trunc(random(2)) > 0))
then bcmd := 57; { close bag }
end;
end;
{-----------------------------------------------------------------------------}
(*
{$f+}
procedure Myexit;
{$f-}
begin
if exitcode <> 0 then
setintvec(9,oldvec);
exitproc := exitsave;
end;
{-----------------------------------------------------------------------------}
procedure ReadScan; interrupt;
begin
KeyScan := port[$60]; { read the keyboard hardware port }
inline($9C/$FF/$1E/OldVec); {call old int vector}
end;
{----------------------------------------------------------------------------}
*)
procedure BagBiz;
{ ************* bag business **************}
var
BagCmd,nb : byte; ch : char;

begin { read keyboard for inputs controlling bag }


BagCmd := 128;
blx := oldblx; bly := oldbly; { restore bag location to old }

if demo then robotplayer(BagCmd);

(* else
begin
exitsave := exitproc;
exitproc := @myexit;
GetIntVec(9, OldVec);
SetIntVec(9, @ReadScan);

BagCmd := keyscan; { keyscan gotten by Readscan interrupt proc. above }

SetIntVec(9, OldVec); { restore int09 vector before leaving }


end;
See procedure ReadScan above as well as MyExit for ISR
BagCmd:=port[$60];
{ Unless using an AT, can't read keyboard output directly as above,
for XT's must use int09 service routine }
*)

memw[0:$41c] := memw[0:$41a]; { this sets DOS kbd buffer head = tail


thus clearing it, prevents buffer overflow }

begin
case BagCmd of
34 : { bag left }
begin
btx:=blx-1;
if btx-bagszx >= minX then blx := btx;
end;
35 : { bag right }
begin
btx:=blx+1;
if btx+bagszx <= maxX+1 then blx := btx;
end;
21 : { bag up }
begin
bty:=bly-1;
if bty-bagszy >= minY then bly := bty;
end;
48 : { bag down }
begin
bty:=bly+1;
if bty+bagszy <= maxY then bly := bty;
end;
1 : begin
fastout; { esc key to abort current game }
exit;
end;
57 : { spacebar to close bag }
begin
bagshut; { close bag & determine results, }
{ whether bagged, bitten and/or dying }
if dying then exit;
end;
128..255 : begin end;
{ else dotick }
end ;{ case }
end; { if keypressed and case }
if not ((oldbly = bly) and (oldblx = blx)) then
begin
L := oldblx - bagszx; R := oldblx + bagszx; { erase old bag }
T := oldbly - bagszy; B := oldbly + bagszy;
textcolor(black);
gotoxy(L,T); write('�'); { scanwise order }
gotoxy(R,T); write('�');
gotoxy(L,B); write('�');
gotoxy(R,B); write('�');
end;
(* end; { if keypressed and case }
*) L := blx - bagszx; R := blx + bagszx; { draw new bag }
T := bly - bagszy; B := bly + bagszy;
textcolor(yellow);
gotoxy(L,T); write('�'); { scanwise order }
gotoxy(R,T); write('�');
gotoxy(L,B); write('�');
gotoxy(R,B); write('�');
oldblx := blx; oldbly := bly; { save old bag location for erasing bag }

end; { procedure BagBiz and return to playgame }


{----------------------------------------------------------------------------}
procedure updatetime;
begin
time := timer;
elapsedtime := trunc(time - starttime); {must take diff before trunc}
timeleft := trunc(playtime-elapsedtime);
end;
{----------------------------------------------------------------------------}
procedure computescore;
begin
nbagged := nsnakes + (4 * ndsnakes) - nbites - (2 * ndbites);
pscore := 60 * nbagged / elapsedtime;
end;
{----------------------------------------------------------------------------}
procedure displayscorebar;
begin
gotoxy(1,25);
textcolor(white);textbackground(black);
write
(' # Bagged=',nbagged:2,' # Bites=',(nbites + ndbites):2);
write
(' Score=',pscore:5:2,' Time=',timeleft:3);
write
(' Delay=',alldelay:3,' Quit=F1 Send $10');
textbackground(black);
end; { do score bar at bottom of screen }
{----------------------------------------------------------------------------}
procedure SnakeBiz;
var
j,xt, yt : integer;
membytes : real;
begin
nlen := succ(nlen);
if (nlen > snlen) then nlen := 1;

deltx := oldx; delty := oldy; { let the new increments equal the old }

if (nlen = 1) or (deltx = 0) { 0 means no change } then


deltx := trunc(random(3)) - 1; { gen new x incr, 0, 1, or 2; minus 1}
xt := head^.x + deltx; { the -1 shifts the increment, so +1 or -1 }
if (xt > maxX) then deltx := trunc(random(2)) - 1; { scrn rt side limit }
if (xt < minX) then deltx := trunc(random(2)); { scrn left side limit }

if (nlen = 5) or (delty = 0) then


delty := trunc(random(3))-1; {gen new y increment }
yt := head^.y + delty;
if (yt > maxY) then delty := trunc(random(2)) - 1; { screen bottom limit }
if (yt <= minY) then delty := trunc(random(2)); { screen top limit }

head^.x := head^.x + deltx; { new x location of head }


if head^.x > maxX then head^.x := maxX; { fail-safe }
if head^.x < minX then head^.x := minX; { fail-safe }
head^.y := head^.y + delty; { new y location of head }
if head^.y > maxY then head^.y := maxY; { fail-safe }
if head^.y < minY then head^.x := minY; { fail-safe }

oldx := deltx; oldy := delty; { remember the current increments }

if (nlen = snlen) then wipetrail := true;


if wipetrail then { start following the head, erasing last char
once the snake has grown to full length }
begin
gotoxy(tail^.x, tail^.y);
write(chr(32)); { write blank over snake tail end }
tail := tail^.next; { link to record one up ahead }
dispose(head^.next); { clear the old tail from memory }
head^.next := tail; { set head next pointer to new tail }
end;
gotoxy(head^.x,head^.y);
if deadly then
begin { write head for poisonous snake }
textcolor(SnooHdColor);
write(snoohead); { face with fangs }
end else
begin { write head for nonpoisonous snake }
textcolor(SneeHdColor);
write(sneehead); { solid happy face }
end;
gotoxy(neck^.x,neck^.y);
{ overwrite the old head with body symbol }
if deadly then
begin
textcolor(SnooBdColor);
write(SnooBody);
end else
begin
textcolor(SneeBdColor);
write(SneeBody);
end;
if bitten and not dying then
begin
If soundon then sound(trunc(random(2640))+1760);
delay(dancedelay);
end { IF BITTEN: DANCING SOUND FOR SNAKE AFTER BITING HUNTER }
else delay(alldelay);
neck := head; { neck now points to snake's old head record }
new(head); { create a new snake head record }
head^.x := neck^.x; head^.y := neck^.y; { fill with old head loc }
neck^.next := head; { link neck (old head) to new head }
head^.next := tail; { point head next to the new tail (circular list) }
end;
{============================================================================}
procedure controlspeed;
var
incrdelay,decrdelay : integer;
begin
if alldelay <= 100 then
begin
decrdelay := alldelay div 16; { 16, % of delay is consistent
with psychophysical power (S. S. Stevens) law }
incrdelay := alldelay div 32; { 32 }
end else
begin
decrdelay := alldelay div 8; { 8 }
incrdelay := alldelay div 16; { 16 }
end;
difbagged := nbagged - oldbagged;
if difbagged >= 1 then alldelay := alldelay - decrdelay;
{ speeds up the game }
if difbagged <= 0 then alldelay := alldelay + incrdelay;
{ slows down the game }
if alldelay >= 160 then alldelay := 160;
if alldelay <= 50 then alldelay := 50;
oldbagged := nbagged; { nbagged gets incremented in computescore }
end;
{--------------------------------------------------------------------------}
procedure finalscorebiz;
begin
readscorearray; { read scores from SNAKEFILE file }
checkscore; { compare present score with top 20, ask for name if in }
if (pscore < score[botlist]) or (pscore <= 0) then exit;
writescorearray; { write new score array to disk }
listscores; { display new scores to player }
end;
{--------------------------------------------------------------------------}
procedure supervisegame;
begin
{ every 3 seconds, display scores and determine whether to
make snake deadly and/or to speedup or slowdown game }
deadly := false;
if elapsedtime > 0 then computescore;
displayscorebar;
if trunc(random(2)) = 1 then
deadly := true; { make snake deadly half of the time }

{ controlspeed;
}

end;
{--------------------------------------------------------------------------}
procedure setGameScrn;
begin
port[$3D9] := GREEN; { SET BORDER COLOR }
cursoff;
textbackground(black);
clrscr;
end;
{--------------------------------------------------------------------------}
procedure initgame;
begin
bagVSsnake := 13; { # of allowed bag moves per snake move }
gamespeed := 30;
waitsn := round(gamespeed * CPUspeed);
waitbag := round(waitsn / bagVSsnake);
{ the following initialization is necessary }
nsnakes := 0; nbites := 0; ndsnakes := 0; ndbites := 0;
difbagged := 0; nbagged := 0; oldbagged := 0;
blx := 40; bly := 12; oldblx := 40; oldbly := 12;
elapsedtime := 0; timeleft := playtime;
starttime := timer; { gets time for start of game }
time := timer;
alldelay := 1; pscore := 0.0;
bitten := false;
deadly := false;
dying := false;
FirstTime := true;
BagCmd := 'x';
ReadOnce := false;
minX := 1; minY := 1;
maxX :=79; maxY :=24;
quickout := false;
end;
{--------------------------------------------------------------------------}
procedure exitgame;
begin
clrscr; curson;
finalscorebiz;
port[$3d9]:=black;
textcolor(yellow);
clrscr;
end;
{--------------------------------------------------------------------------}
procedure playgame;
var
ncycles : integer;
begin
initgame;
setGameScrn;
newsnake;
repeat
ncycles := succ(ncycles);
if (ncycles mod waitsn = 0) then SnakeBiz;
updatetime;
if not bitten then
begin
if (ncycles mod waitbag = 0) then BagBiz;
if quickout then
begin
(* SetIntVec(9, OldVec); { restore int09 vector before leaving }
*)
exit;
end;
if dying then
begin
(* SetIntVec(9, OldVec); { restore int09 vector before leaving }
*)
exit;
end;
{ next 4 lines are logic for doing supervisegame
once and only once every supvtime seconds }
if elapsedtime > oldtime then tcount := succ(tcount);
if (elapsedtime > oldtime) and (tcount = supvtime) then supervisegame;
{ skips line above if elapsedtime in seconds has not changed }
if tcount > supvtime then tcount := 1;
oldtime := elapsedtime;
end;
bitten := false;
if ncycles = 32000 then ncycles := 0;
until timeleft <= 0; { end of repeat-until loop - main playgame loop }
(* SetIntVec(9, OldVec); { restore int09 vector before leaving }
*)
{ if quickout then exit;
}
exitgame;
end; { playgame and return to menu }
{============================================================================}
procedure intro;
var
tx,ty,tc,nbord : byte;
nw : integer;
begin
cursoff;
randomize;
dancedelay := 20;
textbackground(black);
clrscr;
port[$3D9] := 1+trunc(random(7));
gotoxy(1,2);
write(' ');
textcolor(SneeBdColor);
for nw := 1 to 11 do
begin
write(SneeBody);
dotick;
delay(50);
end;
textcolor(SneeHdColor); write(SneeHead);
write(' S n e e ');
sound(880);
delay(1000);
nosound;
textcolor(SneeHdColor); write(SneeHead);
textcolor(SneeBdColor);
for nw := 1 to 11 do
begin
write(SneeBody);
dotick;
delay(50);
end;
write(' ');

initgame;
bitten := true; dying := false;
minY := 3; maxY := 23;
minX := 2; maxX := 35;
deadly := false; { make the snake a Snee-Snake }
{gotoxy(minX+((maxX-minX) div 2),minY+((maxY-minY) div 2));
}
newsnake;
for nw := 1 to 100 do
begin
snakebiz;
end;
eraseOldSnake;
nosound;

gotoxy(43,2);
textcolor(SnooBdColor);
for nw := 1 to 11 do
begin
write(SnooBody);
dotick;
delay(50);
end;
textcolor(SnooHdColor); write(SnooHead);
write(' S n o o ');
sound(660);
delay(1000);
nosound;
textcolor(SnooHdColor); write(SnooHead);
textcolor(SnooBdColor);
for nw := 1 to 11 do
begin
write(SnooBody);
dotick;
delay(50);
end;

initgame;
bitten := true; dying := false;
minY := 3; maxY := 23;
minX := 45; maxX := 77;
gotoxy(minX+((maxX-minX) div 2),minY+((maxY-minY) div 2));
deadly := true; { make the snake a Snoo-Snake }
newsnake;
for nw := 1 to 100 do
begin
snakebiz;
end;
eraseOldSnake;
nosound;

window(10,5,20,12);
tc := 10+trunc(random(6));
textcolor(tc);
uptweet;
writeln(' 0000 ');
writeln(' 0 00 ');
writeln(' 00 ');
writeln(' 0000 ');
writeln(' 00 ');
writeln(' 00 0 ');
writeln(' 0000 ');
delay(100);
window(23,5,31,12);
tc := 8 + (succ(tc) mod 8);
textcolor(tc);
dntweet;
gotoxy(1,3);
writeln(' 00000 ');
writeln('00 00 ');
writeln('00 00 ');
writeln('00 00 ');
writeln('00 00');
delay(100);
window(34,5,44,12);
tc := 10+ (succ(tc) mod 6);
textcolor(tc);
uptweet;
gotoxy(1,3);
writeln(' 000 ');
writeln('00 00 ');
writeln('00 00 ');
writeln('00 000 ');
writeln(' 000 00');
delay(100);
window(44,5,56,12);
tc := 10+ (succ(tc) mod 6);
textcolor(tc);
dntweet;
writeln('00 ');
writeln(' 00 ');
writeln(' 00 00 ');
writeln(' 00 00 ');
writeln(' 0000 ');
writeln(' 00 000 ');
writeln(' 00 00');
delay(100);
window(58,5,67,12);
tc := 10+ (succ(tc) mod 6);
textcolor(tc);
uptweet;
gotoxy(1,3);
writeln(' 0000 ');
writeln('00 00 ');
writeln('00 000 ');
writeln(' 00 ');
writeln(' 00000 ');
delay(100);
window(1,1,80,25);
gotoxy(69,5);
tc := 10+ (succ(tc) mod 6);
write('TM');
delay(100);
gotoxy(1,14);textcolor(lightred);cen('Version 5.0');
gotoxy(1,16);
cenln('Copyright (C) 1986, 1987, 1989 by Bruce L. Rosenberg');
gotoxy(1,19);
cenln('Version 5.0 of SNEESNOO SNAKE TM has arrived!');
cenln
('Alright, folks, here''s the scoop. I really want to run that');
cenln
('$10,000.00 INTERNATIONAL S N E E S N O O S N A K E (TM) CONTEST');
cenln
('by the end of 1990; but it''s up to you. I need 5000 $10 checks to do it.');
cenln
('If you hotshot SNEESNOO SNAKERS want a chance at the prize, form a club!');
cenln
('Let the AUTO DEMO run for a while. Can you beat the Robot''s scores?');
gotoxy(1,25);
curson;
if autodem then AutoContinue else PressToContinue;
end;
{--------------------------------------------------------------------------}
procedure instruct;
begin
clrscr;
textcolor(lightgreen);
cenln(' INSTRUCTIONS FOR THE GAME OF SNEESNOO SNAKE TM');
writeln;
writeln
('You are a herpetologist for Megalop Zoo. Your assignment is to go to the ');
writeln
('Foetid Forest of Amazonia and catch rare SneeSnoo Snakes. Poisonous Snoo''s');
write
('head is a white ');
write(SnooHead);
write(' & it''s body is a cyan ');
write(SnooBody);
writeln('. Nonvenomous Snee''s head is');
write
('a red ',SneeHead,' & it''s body is a green ');
write(SneeBody);
writeln('. You control movement of a bag,');
writeln
('which is a rectangle. To catch the snake you close the bag. SneeSnoo can ');
writeln
('enter from any side. Closing bag with the Snee head inside , gets 1 snake,');
writeln
('or 4 snakes if a Snoo. If outside bag, but within striking distance, it ');
writeln
('bites and you drop 1 snake, 2 if venomous. Five venomous bites & you DIE!!');
writeln
('Your score is the total number of snakes bagged per minute. You have a time');
writeln
('limit. Time in seconds remaining is shown in the lower right. Good Luck!');
writeln;
textcolor(lightred);
writeln;
cen('C O N T R O L K E Y S');
writeln('
');
cenln('"Y" key moves bag up. ');
cenln('"B" key moves bag down. ');
cenln('"H" key moves bag right.');
cenln('"G" key moves bag left. ');
textcolor(lightgreen);
writeln;
cenln('Space bar closes bag. ESC aborts to DOS during play.');
if autodem then AutoContinue else PressToContinue;
end;
{----------------------------------------------------------------------------}
procedure moreinfo;
begin
clrscr;textcolor(lightgreen);
gotoxy(1,1);
cen(' FURTHER INFORMATION ON THE GAME OF SNEESNOO SNAKE TM ');
gotoxy(1,3);textcolor(yellow);
cenln
('This game was written in TurboPascal 5.5 (TM Borland International). ');
cenln
('It consists of over 1300 lines of code. Although copyrighted by');
cenln
('the author, Bruce L. Rosenberg, approval is given for noncommercial');
cenln
('use and distribution by users'' groups (at a nominal fee) and for placing');
cenln
('on private computer bulletin boards. Consideration will be given to');
cenln
('offers from commercial firms regarding licensing on a royalty basis.');
writeln;
cenln
('Send a $10.00 check for latest version on disk (plus source), and to be');
cenln
('notified about the $10,000.00 INTERNATIONAL SNEESNOO SNAKE CONTEST. This');
cenln
('contest will be held after 5,000 people send $10 each. It''s up to you!');
cenln(
'This offer is for personal use and is not a license for commercial use.');
writeln;
cenln
('Send inquiries and checks to : ');
writeln;
cenln('Bruce L. Rosenberg');
cenln('23 N. Chelsea Avenue');
cenln('Atlantic City, NJ 08401');
writeln;
cenln
('Any suggestions for improvements or ideas for games can be mailed to');
cenln
('the above address, via voice phone evenings at (609) 345-4712, or');
cenln
('leave message on Compuserve, 73547,402.');
if autodem then AutoContinue else PressToContinue;
end;
{----------------------------------------------------------------------------}
procedure options;
var
resp : char;
begin
clrscr;
setvidmode;
soundon := false;
write('Do you want sound? (Y or N) : ');
repeat resp := getKey; until upcase(resp) in ['Y','N'];
if upcase(resp)='Y' then
begin
soundon := true;
upscale;
end;
writeln;
writeln;
if not(monochrome) then
begin
write('You are using a color graphics adapter card.');
textcolor(lightgreen);
writeln;
writeln('And this message should be green on color monitors.');
writeln;
textcolor(yellow);
end else
begin
textcolor(15);
writeln;
Writeln('You are using a monochrome adapter (this should be bright).');
textcolor(7);
writeln('Whereas this message should be dim.');
textcolor(yellow);
end;
writeln;writeln;
write('Do you want to reset all the high scores? (Y or N) : ');
repeat resp := GetKey until upcase(resp) in ['Y','N'];
if (upcase(resp) = 'Y') then
begin
writeln;writeln;
textcolor(white);
write('Press "Y" again to confirm : ');
resp := 'N';
repeat resp := Getkey until upcase(resp) in ['Y','N'];
if (upcase(resp) = 'Y') then
begin
zeroscorearray;
writescorearray;
writeln;writeln;
textcolor(yellow);
writeln('All scores set to zero, history about to be made.');
writeln;writeln;
end; { confirm reset all scores }
end; { first time ask reset scores }
if autodem then AutoContinue else PressToContinue;
end; { options }
{----------------------------------------------------------------------------}
procedure showoff;
begin
showoff_init;
repeat
playgame;
if dying then die; if not autodem then exit;
instruct; if not autodem then exit;
playgame;
if dying then die; if not autodem then exit;
intro; if not autodem then exit;
playgame;
if dying then die; if not autodem then exit;
moreinfo; if not autodem then exit;
until not autodem
end;
{----------------------------------------------------------------------------}
procedure menu;
var
ch : char;
begin
demo := false;
autodem := false;
clrscr;textcolor(lightgreen); port[$3D9] := blue; { sets border }
gotoxy(1,2);
cen('M A I N M E N U F O R S N E E S N O O S N A K E (TM)');
gotoxy(1, wherey + 3);
cen('1. BEGINNING SCREEN ');
gotoxy(1, wherey + 2);
cen('2. GAME INSTRUCTIONS ');
gotoxy(1, wherey + 2);
cen('3. FURTHER INFORMATION');
gotoxy(1, wherey + 2);
cen('4. PLAY GAME ');
gotoxy(1, wherey + 2);
cen('5. AUTO-DEMO ');
gotoxy(1, wherey + 2);
cen('6. DISPLAY SCORES ');
gotoxy(1, wherey + 2);
cen('7. CHANGE OPTIONS ');
gotoxy(1, wherey + 2);
cen('8. EXIT TO DOS ');
gotoxy(1,25);textcolor(white);
write('Please choose one of the above numbers (1 to 8) ... ');
gotoxy(54,25);
repeat menusel := GetKey;
if not (menusel in ['1'..'8']) then
begin
gotoxy(54,25);
write('Wrong key, try again. ');
write(chr(7));
gotoxy(54,25);
clreol;
end;
until menusel in ['1' .. '8'];
dntweet;
uptweet;
case menusel of
'1': intro;
'2': instruct;
'3': moreinfo;
'4': begin
playgame;
if dying then die;
if quickout then
begin
menusel :='8';
exit;
end;
end;
'5': begin
autodem := true;
demo := true;
showoff
end;
'6': begin
readscorearray;
listscores;
end;
'7': options;
'8': exit;
else menu;
end;
end;
{----------------------------------------------------------------------------}
procedure prelimbiz;
begin
nrobo := 0;
clrscr;
censcr('Please wait, checking CPU speed.');
CPUspeed := pctime/chkspeed;
gotoxy(wherex - 32,wherey +2);
write('Speed Relative to IBM PC = ');
write(CPUspeed:5:3);
delay(2500);
clrscr;
end;
{----------------------------------------------------------------------------}
procedure farewell;
begin
curson;
clrscr;
gotoxy(1,10);
cen('Thanks for playing S N E E S N O O S N A K E TM !');
gotoxy(1,12);
cen('Copyright (C) 1986, 1987, 1989 by Bruce L. Rosenberg');
delay(2000);
clrscr;
end;
{----------------------------------------------------------------------------}
BEGIN {MAIN PROGRAM}
prelimbiz; { check CPU speed so game will run same on all PCs. }
initialize;
readscorearray; {checks to see if file there, if not, makes it}
(* intro; { display introductory screen }
if autodem then showoff;
initialize;
*)
repeat menu until menusel = '8';
{ if not quickout then farewell;
}
END.
{============================================================================}
{============================================================================}
{$I-} {$R-} {$S-}
program KeyIn; {compile this to an EXE with TPC, then run it)}
{ by Michael Day }
uses crt,dos; {Example: C>TPC KEYIN }
var KeyScan,OldScan : byte;
ch : char;
OldVec,exitsave : pointer;
{$f+}
procedure Myexit;
{$f-}
begin
if exitcode <> 0 then setintvec(9,oldvec);
exitproc := exitsave;
end;

procedure ReadScan; interrupt;


begin
KeyScan := port[$60];
inline($9C/$FF/$1E/OldVec); {call old int vector}
end;

begin
exitsave := exitproc;
exitproc := @myexit;
GetIntVec(9, OldVec);
SetIntVec(9, @ReadScan);
repeat
{ if oldscan <> keyscan then
}
write(keyscan:4);
OldScan := KeyScan;
(* if keypressed then ch := readkey; { clears dos key buffer }
*)
until false; {ch = #27; }
SetIntVec(9, OldVec);
end.

Вам также может понравиться