! ! ! ! IIIIIIIIIIII NNNNNNN NNNNN VVVVV VVVVV ! IIIIIIIIIIII NNNNNNNN NNNNN VVVVV VVVVV ! IIIIII NNNNNNNNN NNNNN VVVVV VVVVV ! IIIIII NNNNNNNNNN NNNNN VVVVV VVVVV ! IIIIII NNNNNNNNNNN NNNNN VVVVV VVVVV ! IIIIII NNNNN NNNNNN NNNNN VVVVV VVVVV ! IIIIII NNNNN NNNNNN NNNNN VVVVV VVVVV ! IIIIII NNNNN NNNNNNNNNNN VVVVVVVVV ! IIIIII NNNNN NNNNNNNNNN VVVVVVV ! IIIIII NNNNN NNNNNNNNN VVVVV ! IIIIIIIIIIII NNNNN NNNNNNNN VVV ! IIIIIIIIIIII NNNNN NNNNNNN V ! ! ! SPACE INVADERS ! Program written by Stephen H. Muggleton for the VAX. ! Curtated by John W. Machar to run on the FRED machine. ! (also commented by JWM so he could find things easier) ! ! prep options:- d - deimos, e - emas #if d %include "b_deimosspecs" #fi %begin #if e %externalrealfnspec cputime #fi { Declarations } ! Special characters %const %integer esc=27 %const %integer bel=7 %const %integer false=0 %const %integer true=1 ! the program declarations %const %integer restart=14 {event signaled when all invaders are gone} %const %integer new game = 13 %owninteger ship direction=1 %owninteger ship col=-1,timer %owninteger no of men=3 %owninteger score=0 %owninteger max bomb factor=8 %owninteger no of invs=24,leftmost=1,rightmost=8,lowest=3 %owninteger no of bombs=0,sheet no=0 %owninteger shell row=-1,shell col=-1 %integer row,col %owninteger row offset=0,col offset=0 %integer step %owninteger legs in=false %integer tank pos %own %integer random seed %own %byte %array score board (1:4)='0' (*) %own %integer %array no in row (1:3)=8 (*) %own %integer %array no in col (1:8)=3 (*) %own %integer %array bomb row (1:20)=0 (*) %own %integer %array bomb col (1:20)=0 (*) %own %byte %array screen pts (1:24)=true (*) %integer %array barrier (0:79) %const %integer %array new barriers (0:79) = ' ' (7), '4' (5), ' ' (10), '4' (5), ' ' (10), '4' (5), ' ' (10), '4' (5), ' ' (10), '4' (5), ' ' (8) #if d %recordformat ttf(%integer rxcsr, rxbuf, txcsr, txbuf) %ownrecord (ttf) %name tt == k'156170'; ! 016500 for n9 #fi { ROUTINES & FUNCTIONS } %routine wait (%integer how long) {tweak the following to get the correct no of milliseconds} %const %integer scaling constant = 95 %integer i,j %for i = 1,1,(how long * scaling constant) + 50 %cycle j = scaling constant %repeat %end {of wait} %integer %fn test symbol #if d %if tt_rxcsr&8_200 = 0 %then %result = 0 %result = tt_rxbuf&8_177 #fi %result = 0 %end %integer %function random integer {with thanks to George Ross & Gordon Brebner} %const %integer m = 32767 %const %integer a = 23501 %const %integer c = 6923 random seed = (a * random seed + c)&m %result = random seed >> 5 {temporarily less random than usual} %end {of random integer} %integer %fn rem(%integer num, div) %integer x x = num//div %result = num-(x*div) %end %integer %fn random num (%integer max) %result=random integer*max//1000+1 %end {of random num} %routine escape (%integer ch) print symbol (esc) print symbol (ch) %end {of escape} %routine move to (%integer row,col) escape ('Y') {** CURSOR ADDRESS} print symbol (32+row) print symbol (32+col) %end {of move to} %routine wind down {resets the terminal to "nice" mode} escape('j') {set no insert character} escape('l') {unlock the key board} escape('G') {no more nasty graphics} move to (3,25) printstring("We always win you know") move to (23,0) wait(1000) %signal new game %end {of wind down} %byte %map invaders (%integer row,col) %result==screen pts ((row-1)*8+col) %end {of invaders} %routine screen position for (%integer %name inv row,inv col) inv row=2+(inv row-1)*3 + row offset inv col=5+(inv col-1)*4 + col offset %end {of screen position for} %integer %fn hit invader (%integer %name row,col) row=row-2-row offset %result = false %if rem (row,3)=2 row=row//3+1 col=col-4-col offset %result = false %if rem (col,4)=3 col=col//4+1 %result = true %if 1<=row<=3 %and 1<=col<=8 %and invaders (row,col)=true %result = false %end {of hit invader} %routine paint score board %owninteger spacing=true %owninteger digit,temp score,power=1000,next dig temp score=score %for digit=1,1,4 %cycle next dig=temp score//power+'0' temp score=rem (temp score,power) power=power//10 %if next dig#score board (digit) %start %if spacing=true %start move to (0,71+digit) spacing=false %finish score board (digit)=next dig print symbol (next dig) %finish %else %start spacing=true %finish %repeat %end {of paint score board} %routine paint barrier %integer barrier point move to (22,0) escape ('t') {** CLEAR LINE **} wait(0) print symbol (barrier (barrier point)) %for barrier point=0,1,79 %end {of paint barrier} %routine paint no of men move to (0,7) escape ('j') {** RESET INSERT CHARACTER **} print symbol (no of men+'0') %end {of paint no of men} %routine drop bomb %integer bomb no,inv no %return %if no of bombs=5 {enough misery flying about already} %for bomb no=1,1,5 %cycle %exit %if bomb row (bomb no)=0 %repeat %cycle {which invader will drop the bomb ?} inv no=random num (rightmost-leftmost+1)+leftmost-1 %repeat %until no in col (inv no)#0 {he can only drop it if hes alive} bomb row (bomb no)=lowest {bomb falls from lowest row of invaders} bomb col (bomb no)=inv no {from underneath the chosen invader} screen position for (bomb row (bomb no),bomb col (bomb no)) bomb row (bomb no)=bomb row (bomb no)+2 no of bombs=no of bombs+1 {another one "in flight"} move to (bomb row (bomb no),bomb col (bomb no)) print symbol ('k') {graphics down arrow (BOMB)} %end {of drop bomb} %integer %fn on lousy row {true if shell is on same line as invaders heads} %result = true %if shell row=2+row offset %or shell row=5+row offset %orc shell row=8+row offset %result = false %end {of on lousy row} %routine move shell %integer i,j %integer row,col,inv row,inv col,ship score %return %if shell row=-1 {no shell to move at present} escape ('j') {** RESET INSERT CHARACTER **} shell row=shell row-1 {move shell down a row} %if shell row=1 %and ship col-2<=shell col<=ship col+2 %start ship score=50*random num (3) {we have hit a ship so think of a score} %if score//400 < (score+ship score)//400 %start no of men=no of men+1 %if no of men < 9 {max of 9 men} paint no of men {update total} %finish score=score+ship score {update} paint score board {score} timer=random num (4)+35 {determine when next ship will appear} move to (1,ship col-1) ship col=-1 {delete ship} space %if ship score = 50 {centre the score on the target} write(ship score,0) {write the score on the target} shell row=-1 {delete shell} %return %finish %if shell row=0 %start {shell has passed on up} shell row=-1 {delete shell} %return %finish %return %if shell row=-1 {no shell to move} inv row=shell row inv col=shell col %if hit invader (inv row,inv col)=true %start {hit a bug eye-ed monster?} shell row=-1 {delete shell} invaders (inv row,inv col)=false {delete invader} no in row (inv row)=no in row (inv row)-1 {update counters} no in col (inv col)=no in col (inv col)-1 row=inv row;col=inv col screen position for (row,col) %if score//400 < (score+(4-inv row)*10)//400 %start no of men=no of men+1 %if no of men < 9 {9 men max} paint no of men {update men} %finish score=score+(4-inv row)*10 {work out invader score} paint score board {update score} move to (row,col-1); spaces(4) {remove body from the} move to (row+1,col-1); spaces(4) {scene of the crime !} no of invs=no of invs-1 {one less nasty} %if no of invs=0 %start {was it the last one} sheet no=sheet no+1 {another sheet finished} %signal restart {jump to get a new sheet etc} %finish %if inv col=leftmost %start {where is the left most invader now ?} %for j=inv col,1,rightmost %cycle %exit %if no in col (j)#0 %repeat leftmost=j %finish %if inv col=rightmost %start {where is the right most invader now ?} %for j=inv col,-1,leftmost %cycle %exit %if no in col (j)#0 %repeat rightmost=j %finish %if inv row=lowest %start {where is the lowest invader now ?} %for i=inv row,-1,1 %cycle %exit %if no in row (i)#0 %repeat lowest=i %finish %finish %else %start {Missed didn't hit anything} %unless on lousy row=true %start {simple case} move to (shell row,shell col) print symbol ('f') {Draw shell (graphics degree symbol)} wait(0) %finish %finish %end {of move shell} %routine paint legs (%integer there) %if there = false %then spaces(4) %and %return %if legs in=false %start print string("/ \ ") %finish %else %start print string("\ / ") %finish %end {of paint legs} %routine paint invader (%integer row,col,type) move to (row,col-1) %if type=1 %start print string("sil") %finish %else %if type=2 %start print string("lis") %finish %else %if type=3 %start print string(":i:") %finish move to (row+1,col-1) paint legs (true) %end {of paint invader} %routine draw all invaders %integer i,j,row,col %for i=1,1,3 %cycle {for each row of monsters} row=i; col=1 screen position for (row,col) move to (row,0) escape ('f') {** ERASE END OF FIELD} wait(0) move to (row+1,0) escape ('f') {** ERASE END OF FIELD} wait(0) %for j=1,1,8 %cycle {print all extant invaders in this row} row=i;col=j screen position for (row,col) paint invader (row,col,i) %if invaders (i,j)=true %repeat %repeat %end {of draw all invaders} %routine draw tank move to (23,0) escape ('t') {** CLEAR LINE} wait(0) move to (23,tank pos-1) escape ('j') {** RESET INSERT CHARACTER} print string("scl") %end {of draw tank} %routine move ship %if timer=0 %start {is it time for a new ship to appear?} move to (1,0) %if ship col=-1 %start {if necessary, start a new ship off} escape ('t') {** CLEAR LINE} wait(0) ship direction=random num (2) %if ship direction=1 %start {moving left to right} ship col=1 %finish %else %start move to (1,77) {moving right to left} ship col=78 %finish print string("[-]") %finish %else %if (ship col=78 %and ship direction=1) %orc (ship col=1 %and ship direction=2) %start {ship at end of pass so kill it off} ship col=-1 {note theres no ship} timer=random num (4)+35 {generate time till the next ship} escape ('t') {** CLEAR LINE} wait(0) %finish %else %start {there is a ship so move it in the right direction} %if ship direction=1 %start {moving left to right} escape ('i') {** INSERT CHARACTER} print symbol (' ') wait(0) ship col=ship col+1 %finish %else %start {moving right to left} ship col=ship col-1 {move the ship left} escape ('O') {** DELETE CHARACTER} wait(0) %finish %finish ship direction = random num (2) %if random num (200) = 42 %finish %else %start timer=timer-1 {decrement time till next ship appears} %finish %end {of move ship} %routine move bombs %integer n %integer %name b row,bar pt %integer row,col,bomb no,b col %for bomb no=1,1,5 %cycle %unless bomb row (bomb no)=0 %start b row== bomb row (bomb no) b row=b row+1 %if (shell row>=b row>=shell row-2 %and %c bomb col (bomb no)=shell col) %or b row=24 %start {shell neutralises bomb} %unless b row=shell row-1 %or b row=24 %start escape ('j') {** RESET INSERT CHARACTER} move to (b row-1,bomb col (bomb no)) print symbol (' ') %finish b row=0 no of bombs=no of bombs-1 %finish %else %if b row=23 %start; {bomb gets to the ground} move to (22,bomb col (bomb no)) {so should dissappear} escape ('j') {** RESET INSERT CHARACTER} print symbol (' ') {overwrite with a blank} %if tank pos-1<=bomb col (bomb no)<=tank pos+1 %start print symbol (bel) {ie if there was a tank underneath} print symbol (bel) {the bomb: ring funeral bell twice} wait(0) no of men=no of men-1 {another one bites the dust} %if no of men=0 %then wind down {end of the game} move to (23,0) escape ('t') {** CLEAR LINE} wait(0) draw tank {which may have been overwritten} paint no of men {update the number of "OUR BOYS" left} %finish %finish %else %if b row=22 %start; {bomb just off ground - may hit a sheild} escape ('j') {** RESET INSERT CHARACTER} b col=bomb col (bomb no) bar pt==barrier (b col) %if bar pt=' ' %start {bomb goes through} move to (22,b col) print symbol ('k') {draw bomb} %finish %else %start {bomb hits shield} bar pt=bar pt-1 bar pt=' ' %if bar pt='0' {shield is holed} move to (22,b col) print symbol (bar pt) {deplete shield by one} b row=0 no of bombs=no of bombs-1 %finish %finish %finish %repeat row=lowest;col=1 screen position for (row,col) move to (21,0) escape ('M') {** DELETE LINE} wait(0) move to (row+2,0) escape ('L') {** INSERT LINE} wait(0) drop bomb %if (no of bombs<=no of invs//max bomb factor+1 %c %and random num (2)=1) %end {of move bombs} %routine read tank %integer ch,nchar %switch tank action (-1:127) wait (5//no of invs+1) ch = test symbol {if he has then read it in} -> tank action (ch) {and do what he wants} tank action ('4'): {Move the tank left} move to (23,0) ->end %if tank pos=5 {already at farthest left} escape ('O') {** DELETE CHARACTER} wait(0) escape ('O') {** DELETE CHARACTER} wait(0) tank pos=tank pos-2 ->end tank action ('6'): {move the tank right} move to (23,0) ->end %if tank pos=75 {tank at farthest right already} escape ('i') {** INSERT CHARACTER} spaces(2) {fast enough ?} wait(0) tank pos=tank pos+2 ->end tank action ('5'): ! Shell {fire a shell from the tank} ->end %unless shell row=-1 %if barrier (tank pos)=' ' %start {a clear shot out} shell row=22 shell col=tank pos move to (shell row,shell col) escape ('j') {** RESET INSERT CHARACTER} print symbol ('f') {Graphics Degree symbol (shell)} ->end %finish %else %start {shooting our way through a shield} barrier (tank pos)=barrier (tank pos)-1 {deplete shield} barrier (tank pos)=' ' %if barrier (tank pos)='0' {shield holed} move to (22,tank pos) escape ('j') {** RESET INSERT CHARACTER} print symbol (barrier (tank pos)) {draw shield} %finish tank action (*): end: %end {of read tank} %routine frig {***************************FRIG} %integer i,j %on %event restart %start {traps to give a new sheet of invaders} %finish {only signalled in routine: MOVE SHELL} %for i=1,1,3 %cycle {start of initialisation} no in row (i)=8 %for j=1,1,8 %cycle no in col (j)=3 invaders (i,j)=true {all invaders present in sheet to start with} %repeat %repeat timer=random num (4)+35 row offset=2*sheet no+2 col offset=0 leftmost=1;rightmost=8;lowest=3 shell row=-1;no of bombs=0 barrier (i) = new barriers (i) %for i = 0,1,79 bomb row (i)=0 %for i = 1,1,5 no of invs=24 %if sheet no=0 %start {end of sheet initialisation} score board (i)='0' %for i=1,1,4 escape ('v') {** CLEAR PAGE} wait(1) move to (0,2) print string("Men:") move to (0,65) print string("Score:") move to (0,75) print symbol ('0') %finish %else %start move to (1,0) escape ('y') {** CLEAR END OF PAGE} wait(1) %finish paint score board paint no of men escape ('F') {** SET GRAPHICS ON} draw all invaders paint barrier tank pos=39 draw tank wait (0) step=-1 row offset=2*sheet no %cycle row offset=row offset+2 row=lowest col=leftmost screen position for (row,col) %if row>=20 %then %exit {invaders reach the barriers} %if step=-1 %start escape ('i') {** INSERT CHARACTER} step=1 %finish %else %start escape ('j') {** RESET INSERT CHARACTER} step=-1 %finish %cycle wait(1) read tank %for i=1,1,3 %cycle %unless shell row=-1 %start escape ('j') {** RESET INSERT CHARACTER} move to (shell row,shell col) space {fast enough ?} wait(0) %if step = 1 {*!*** insert mode} %finish move ship move bombs move shell %unless shell row=-1 wait(1) read tank row=i;col=1 screen position for (row,col) %unless row=23 %or i>lowest %start %if step=-1 %start move to (row,0) escape ('O') {** DELETE CHARACTER} wait(0) move to (row+1,0) escape ('O') {** DELETE CHARACTER} wait(0) %finish move to (row+1,0) escape ('t') {** CLEAR LINE} wait(0) move to (row+1,col-1) %for j=1,1,8 %cycle wait(0) read tank %if invaders (i,j)=true %start escape ('j') {** RESET INSERT CHARACTER} row=i;col=j screen position for (row,col) move to (row+1,col-1) paint legs (true) %finish legs in=1-legs in %repeat %if step=1 %start escape ('i') {** INSERT CHARACTER} move to (row,0) space wait(0) move to (row+1,0) space wait(0) %finish %finish legs in=1-legs in read tank %repeat wait(0) read tank %if step=1 %start %exit %if col offset+rightmost*4>=75 %finish %else %start %exit %if col offset+(left most-1)*4=0 %finish col offset=col offset+step %repeat escape ('j') {** RESET INSERT CHARACTER} %unless on lousy row=true %start move to (shell row,shell col) space %finish move to (20,0) escape ('M') {** DELETE LINE} wait(0) escape ('M') {** DELETE LINE} wait(0) move to (2,0) escape ('L') {** INSERT LINE} wait(0) escape ('L') {** INSERT LINE} wait(0) draw tank %repeat %end {of frig} %routine frig2 %on new game %start %return %finish frig {*************FRIG} %end #if e random seed = int(cputime*1000) #else random seed = time map hwr(6) tt_rxcsr = 0 #fi %cycle sheet no = 0 no of men = 3 score = 0 frig2 %repeat %end %of %program