{$S+} {$R+} {$I-} {$N-}

{Range checking off} {I/O checking off} {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 := 2: begin head^.x := minX; head^.y := 3: begin head^.x := maxX; head^.y := 4: begin head^.x := minX; head^.y := end;

maxY; maxY; minY; minY;

end; end; end; end;

{ { { {

bot. rt. } bot. left } top rt. } top left }

*) (* *)

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 (head^.x (head^.y (head^.y >= <= >= <= blx-bitedx) and blx+bitedx) and bly-bitedy) and 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 if if if (head^.x (head^.x (head^.y (head^.y < > < > L) R) T) B) >= <= >= <= then then then then bcmd bcmd bcmd bcmd := := := := 34; 35; 21; 48; { { { { move move move move L R U D } } } }

if (((head^.x (head^.x (head^.y (head^.y

L-rslack) and R {+rslack} ) and T-rslack) and 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; { 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 } 35 : 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; if (nlen = 1) or (deltx = deltx := trunc(random(3)) xt := head^.x + deltx; { if (xt > maxX) then deltx if (xt < minX) then deltx { let the new increments equal the old }

0) { 0 means no change } then - 1; { gen new x incr, 0, 1, or 2; minus 1} the -1 shifts the increment, so +1 or -1 } := trunc(random(2)) - 1; { scrn rt side limit } := 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 := if head^.x if head^.x head^.y := if head^.y if head^.y head^.x + deltx; { new > maxX then head^.x := < minX then head^.x := head^.y + delty; { new > maxY then head^.y := < minY then head^.x := x location of head maxX; { fail-safe minX; { fail-safe y location of head maxY; { fail-safe 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); end; begin exitsave := exitproc; exitproc := @myexit; GetIntVec(9, OldVec); SetIntVec(9, @ReadScan); repeat { if oldscan <> keyscan then

{call old int vector}

} (* *) write(keyscan:4); OldScan := KeyScan; if keypressed then ch := readkey; { clears dos key buffer }

until false; {ch = #27; } SetIntVec(9, OldVec); end.