Benny Bunny, the new recruit in the Burrowville Fire Service, is left in charge while the Firebug tries to burn down the fire station. Fires flash up at random along five floors of girders; Benny puts them out by stamping on them or by running over a fire bucket so that it falls onto the flames below. He climbs ladders to go up and slides down poles to go down, losing energy when he steps on a fire or bumps into the Firebug, and losing it fast whenever more than seven fires are burning at once. Touching a bucket restores energy, dropping one on the Firebug’s head earns a bonus and sends him back to his corner, and getting all 20 buckets to the bottom of the screen moves Benny on to the next of five named screens, from the Roof Garden to the Station Storeroom. Control is with keys 9 and 0, or a joystick in the left Timex port.
The title screen reads “Benny Bunny – FIREFIGHTER”. A REM says the program works in either Timex or Spectrum mode, and another says it was entered by Keith and Tom Skapinski. A related article, “Firefighter” by T. Sherwood, appeared in the LISTing Newsletter in August 1991.
Program Analysis
Structure
- Lines 1–3: colours and REMs, then a jump to setup at 6003.
- Lines 100–995: main loop. Each pass animates Benny and the Firebug in two frames, checks collisions and the tile under Benny’s feet, and may start a new fire.
- Lines 1305–1499: climbing up a ladder or sliding down a pole, four rows at a time, with a rising or falling three-note BEEP.
- Lines 1605–1699: a falling bucket, which puts out fires, can hit the Firebug, and when it reaches row 20 counts toward the 20 needed for the next screen.
- Lines 3205–3299, 4005–4099, 4210–4450: stamping on a fire, game over, hitting the Firebug, and bonking him with a bucket.
- Lines 6003–6300: setup.
CLEAR (USR "A")-100reserves space below the UDGs, then a 29-byte machine code routine and UDGs A–R are POKEd from DATA with a checksum test (16582). - Lines 7003–7690: builds a screen with random ladders, poles and buckets, draws the status bar in the lower screen and plays a tune until a key is pressed.
- Lines 9205–9480: animated title with menu (0 quit, 1 instructions, 2 start) and the instruction pages.
- Line 9500: saves a tape copy as
FIRE/FTR.; it is reached only by a manualGO TO 9500.
Collision by attribute
The game reads the board through ATTR instead of keeping a map. Floor cells are INK 1; PAPER 5 (attribute 41), fires are flashing yellow on red (150), and the side walls are attribute 2, which Benny cannot walk into. Line 600 turns the attribute under his feet straight into a subroutine number with GO SUB ATTR (x+2,y)*100+1000: ladders (INK 3) go to 1300, poles (INK 4) to 1400 and buckets (INK 6) to 1600. None of those exact lines exists, so each GO SUB lands on the next line in the program. The Firebug uses the same test in line 420 to ride ladders and poles while it drifts toward Benny, with an occasional random step away.
Sound routine
The machine code at USR "A"-99 is a short beeper routine that toggles the speaker bit on port 254, keeping the border colour read from 23624. Before each call the BASIC POKEs z+3 (number of steps), z+5 (length of each step) and z+24 with 28 or 29 (INC E or DEC E), so the same routine gives falling or rising sweeps for fires, buckets, bonuses and the end of the game. The first DATA byte is 199 (RST 0); line 9205 POKEs it to 243 (DI) and line 9215 adds a RET at z+29 before the routine is ever called.
Notable Techniques
- Joystick reading through the TS2068 AY chip:
OUT 245,14selects register 14, andIN 502returns 251 for left and 247 for right. - Every sprite move is two
PRINT OVER 1; INK 8passes: one to erase the old frame and one to draw the new one, so the background is left intact. GO SUBtargets computed fromATTRvalues replace anIFchain for ladder, pole and bucket handling.- The score, fire count, high score, bucket count and screen number are printed with
PRINT #0on the lower screen, under a header of UDG dividers. - The energy bar on row 21 is UDG blocks, grown and erased two cells at a time.
- The title animation and the start-of-screen tune both
RESTORE 9296and step through the same 32 notes.
Potential Issues
- Line 9284 sends key 3, which is not shown on the menu, to the disk resave line 9992. It still saves the program over again, now to tape.
- The DATA in line 9295 is never read, because both tunes
RESTORE 9296. It looks like an earlier copy of 9296 with two notes different. - Line 7065 is code disabled with
REM ", which would have opened gaps in the floors.
This copy came from a Larken disk and was converted to load from tape. The RANDOMIZE USR 100 disk prefixes and the LOGICALL menu load were removed, the autostart was corrected and the LKDOS variables marker was dropped. It was tested in ZEsarUX through the title, instructions, controls and play screen.
Source Code
1 PAPER 7: BORDER 7: INK 0: CLS : GO TO 6000: REM This program works in Timex or Spectrum mode.
2 REM ***ENTERED by Keith & Tom Skapinski
3 REM ***LEFT JOYSTICK PORT***
100 FOR p=1 TO 3
110 FOR i=1 TO 2
120 OUT 245,14: LET y1=y+((INKEY$="0" OR IN 502=247) AND ATTR (x,y+1)<>2)-((INKEY$="9" OR IN 502=251) AND ATTR (x,y-1)<>2)
140 PRINT INK 8; OVER 1;AT x,y;a$(3-i);AT x+1,y;b$(3-i);AT x,y1;a$(i);AT x+1,y1;b$(i): LET y=y1
220 IF ATTR (x+2,y)=150 THEN GO SUB 3200
410 LET b1=b+(y>b)-(y<b)
415 IF RND>.8 THEN LET b1=b+(b>y AND b<30)-(b<y AND b>1)
420 LET a1=a+4*((ATTR (a+2,b1)=4)-(ATTR (a+2,b1)=3))
430 PRINT OVER 1; INK 8;AT a,b;c$(3-i);AT a+1,b;i$(3-i);AT a1,b1;c$(i);AT a1+1,b1;i$(i): LET a=a1: LET b=b1
490 IF a=x AND b=y THEN GO SUB 4200
600 IF ATTR (x+2,y)<7 THEN GO SUB ATTR (x+2,y)*100+1000
920 NEXT i: NEXT p
930 LET q=(1+INT (RND*5))*4: LET r=1+INT (RND*30): IF ATTR (q,r)=41 THEN PRINT FLASH 1; INK 6; PAPER 2;AT q,r;"e": LET u=u+1: PRINT #0;AT 1,1; PAPER 8;u;" ": IF u>7 THEN LET f=f-2: PRINT AT 21,f+6;" ": IF f=0 THEN GO TO 4000
995 GO TO 100
1305 OUT 245,14: IF IN 502=255 AND INKEY$="" THEN PRINT INK 8; OVER 1;AT x,y;a$(i);AT x+1,y;b$(i): LET x=x-4: PRINT INK 8; OVER 1;AT x,y;a$(i);AT x+1,y;b$(i): FOR j=12 TO 36 STEP 12: BEEP .03,j: NEXT j
1399 RETURN
1405 OUT 245,14: IF IN 502=255 AND INKEY$="" THEN PRINT OVER 1; INK 8;AT x,y;a$(i);AT x+1,y;b$(i): LET x=x+4: PRINT OVER 1; INK 8;AT x,y;a$(i);AT x+1,y;b$(i): FOR j=36 TO 12 STEP -12: BEEP .03,j: NEXT j
1499 RETURN
1605 POKE z+3,70: POKE z+5,5: POKE z+24,28
1610 LET j=x+2
1620 PRINT INK 1; PAPER 5;AT j,y;e$(e)
1625 FOR j=j+1 TO j+3: PRINT AT j,y; INK 6;"g"
1627 LET l=USR z
1628 IF ATTR (j+1,y)=150 THEN POKE z+3,0: POKE z+5,2: POKE z+24,29: LET l=USR z: LET s=s+35: LET u=u-1: PRINT #0;AT 1,8; PAPER 8;s;AT 1,1;u;" "
1630 IF ATTR (a-1,b)=6 THEN GO SUB 4400
1635 IF ATTR (j+1,y)=6 THEN POKE z+3,150: LET l=USR z: POKE z+3,70: PRINT AT j,y;" ": LET j=j+1: GO TO 1625
1637 PRINT AT j,y;" ": NEXT j
1642 PRINT AT j,y; INK 6;"g"
1650 IF j=20 THEN PRINT INK 1; PAPER 5;AT 20,y;e$(e): POKE z+3,60: POKE z+5,30: POKE z+24,28: LET l=USR z: LET g=g+1: PRINT #0;AT 1,21; PAPER 8;g: IF g=20 THEN LET e=e+1: GO TO 7000
1672 LET f=f+2*(f<23): PRINT AT 21,0; INK 3;"ENERGY"; INK 2;"rrrr";: FOR j=5 TO f: PRINT INK 4;"r";: NEXT j
1699 RETURN
3205 POKE z+3,130: POKE z+5,2: POKE z+24,28: LET l=USR z
3210 LET u=u-1: LET s=s+15: PRINT #0;AT 1,1; PAPER 8;u;" ";AT 1,8;s
3220 PRINT INK 1; PAPER 5;AT x+2,y;e$(e)
3230 LET f=f-2: PRINT AT 21,f+6;" ": IF f=0 THEN GO TO 4000
3299 RETURN
4005 PRINT AT 21,0; INK 6; FLASH 1;"ENERGY"
4010 IF S>H THEN LET H=S
4020 LET C=0: LET E=1: LET S=0
4025 POKE Z+3,0: POKE Z+5,25: POKE Z+24,28: LET L=USR Z
4080 PRINT AT 21,0; INK 5; FLASH 1;"ALL ENERGY LOST "; INVERSE 1;" PRESS A KEY "
4090 IF INKEY$<>"" THEN GO TO 4090
4091 IF INKEY$="" THEN GO TO 4091
4099 GO TO 9200
4210 POKE Z+3,30: POKE Z+5,255: POKE Z+24,28: LET L=USR Z
4220 LET F=F-4: PRINT AT 21,F+6;" ": IF F<1 THEN GO TO 4000
4230 PRINT AT A,B; OVER 1; INK 8;C$(I);AT A+1,B;I$(I)
4250 LET A=18: LET B=1+29*INT (RND*2): PRINT INK 8; OVER 1;AT A,B;C$(I);AT A+1,B;I$(I): RETURN
4410 PRINT AT A,B; OVER 1; INK 8;C$(I);AT A,B; FLASH 1; INK 4;"e"
4430 FOR K=1 TO 8: POKE Z+5,K: LET L=USR Z: LET L=USR Z: NEXT K: POKE Z+5,5
4440 PRINT AT A,B;" ": LET A=18: LET B=1+29*INT (RND*2): PRINT INK 8; OVER 1;AT A,B;C$(I);AT A+1,B;I$(I)
4450 LET S=S+85: PRINT #0;AT 1,8; PAPER 8;S: RETURN
6003 PAPER 0: INK 7: BORDER 0: CLS
6005 CLEAR (USR "A")-100
6007 PRINT AT 10,0; FLASH 1;" PLEASE STAND BY. "
6010 RESTORE 6010
6015 LET Z=(USR "A")-99
6016 LET M=0
6020 FOR I=Z TO Z+28
6025 READ J: LET M=M+J: POKE I,J: NEXT I
6026 FOR I=USR "A" TO USR "R"+7
6027 READ J: LET M=M+J: POKE I,J: NEXT I
6028 IF M<>16582 THEN PRINT "ERROR IN DATA...6030-6094": STOP
6030 DATA 199,17,16,2,38,1,58,72,92,31,31,31,14,254,238,16,237,121,67,16,254,37,32,244,1,21
6050 DATA 32,232,251,112,154,159,61,93,117,124,56,8,62,93,157,21,116,119,7,14,89,249,188,186,174,62,28,16,124,186,185,168,46,238,224
6060 DATA 43,184,109,46,228,62,164,25,0,255,54,127,0,0,0,0,60,66,0,255,126,126,60,60
6070 DATA 231,36,60,126,255,153,255,126,0,0,0,0,0,0,129,102
6080 DATA 239,239,239,0,254,254,254,0,66,126,66,126,66,126,66,126
6090 DATA 40,40,40,40,40,40,40,40
6091 DATA 36,60,126,255,153,255,126,231,36,36,36,231,231,0,0,0
6093 DATA 8,8,28,28,62,62,119,99,73,107,34,62,28,28,8,8
6094 DATA 255,239,221,179,78,53,72,18,0,1,1,255,255,0,0,0
6200 LET a$="ac": LET b$="bd": LET e$="jqjag": LET f$="korfk": LET g$="lpplp"
6210 LET c$="hi": LET i$="nm"
6220 LET c=0: LET e=1: LET s=0: LET h=0: LET f=24
6230 DIM d$(5,24): POKE z+24,28: LET d$(1)="Burrowville Fire Station": LET d$(2)=" The Roof Garden ": LET d$(3)=" Fire Station Basement "
6240 LET d$(4)=" Benny's Office ": LET d$(5)=" Station Storeroom "
6300 GO TO 9200
7003 LET c=c+1
7005 IF e>5 THEN LET e=1
7010 LET u=0: LET g=0
7020 CLS
7030 FOR j=2 TO 20: PRINT INK 2;AT j,0;" ";AT j,31;" ": NEXT j
7040 PRINT PAPER 2; INK 6;AT 0,3;" ";d$(e);" "
7041 PRINT INK 3;AT 1,1;"' ";AT 0,1;".:"; PAPER 1;AT 0,2;"' "
7042 PRINT INK 3;AT 0,30;":.";AT 1,30;"' "; PAPER 1;AT 0,29;" '"
7060 FOR j=4 TO 20 STEP 4: FOR k=0 TO 31: PRINT AT j,k; INK 1; PAPER 5;e$(e): NEXT k: PRINT INK j/4; PAPER 0;"ffffffffffffffffffffffffffffffff": NEXT j
7065 REM " FOR j=4 TO 16 STEP 4: LET l=INT (RND*15)+1: PRINT INK 4;AT j,l;" ";AT j+1,l;" ";AT j,l+15;" ";AT j+1,l+15;" ": NEXT j
7080 FOR j=1 TO 3: PRINT AT j,0; INK 2;"j";AT j,31;"j";AT j+16,0;"j";AT j+16,31;"j": NEXT j
7320 FOR i=4 TO 16 STEP 4: LET k=0
7322 LET j=(INT (RND*8))*4+1
7324 IF ATTR (i,j)=41 THEN FOR l=-2 TO 1: PRINT INK 4;AT i+l,j;g$(e): NEXT l: LET k=k+1
7326 IF k<3 THEN GO TO 7322
7328 NEXT i
7330 FOR i=4 TO 16 STEP 4: LET k=0
7332 LET j=(INT (RND*15))*2+1
7334 IF ATTR (i,j)=41 AND ATTR (i+4,j)=41 THEN FOR l=1 TO 4: PRINT INK 3;AT i+l,j;f$(e): NEXT l: LET k=k+1
7336 IF k<3 THEN GO TO 7332
7338 NEXT i
7340 FOR i=4 TO 16 STEP 4: LET k=0
7350 LET j=2*(1+INT (RND*14))
7355 IF ATTR (i,j)=41 THEN PRINT AT i,j; INK 6;"g": LET k=k+1
7360 IF k<5 THEN GO TO 7350
7370 NEXT i
7450 LET f=24: PRINT AT 21,0; INK 3;"ENERGY"; INK 2;"rrrr"; INK 4;"rrrrrrrrrrrrrrrrrrrr "
7456 PRINT #0; PAPER 2;AT 0,0;"lFIRES lSCORE lHIGH lg lSCREENl l l l l l l "
7460 PRINT #0; PAPER 8;AT 1,1;U;AT 1,8;S;AT 1,15;H;AT 1,21;G;AT 1,25;C
7470 LET U=0: LET X=2: LET Y=30: LET A=18: LET B=1+29*INT (RND*2)
7480 PRINT OVER 1; INK 8;AT X,Y;A$(2);AT X+1,Y;B$(2);AT A,B;C$(2);AT A+1,B;I$(2)
7605 POKE Z+3,0: POKE Z+5,2: POKE Z+24,29
7610 LET L=USR Z: RESTORE 9296
7620 FOR J=1 TO 32: READ K: BEEP .12,K-40: OUT 245,14: IF IN 502=255 AND INKEY$="" THEN NEXT J: GO TO 7610
7690 GO TO 100
9205 CLS : POKE Z,243: PRINT '' PAPER 2;" Benny Bunny - FIREFIGHTER ";AT 21,0;" 0=QUIT 1=INSTRUCTIONS 2=START "
9207 FOR J=5 TO 18: PRINT INK 1; PAPER 5;AT J,0;"jjkjjjjojjjjjljjjpjjjjkjjjjjljjj";AT J,RND*29; FLASH 1; INK 2; PAPER 6;"e"; INVERSE 1;"e": NEXT J
9208 PRINT AT 13,0; INK 4;"gffgfffffffffffffffffffffffffgfg"
9215 POKE Z+29,201
9220 FOR N=52 TO 28 STEP -12: RESTORE 9296
9230 FOR J=4 TO 19: FOR I=1 TO 2
9235 PRINT AT 14,J;" ";A$(I);" ";C$(I);AT 15,J;" g";B$(I);" ";I$(I)
9250 READ K: BEEP .1,K-N: NEXT I
9280 IF INKEY$="" THEN NEXT J: PRINT AT 14,J;" ";AT 15,J;" ": PAUSE 6: NEXT N: GO TO 9220
9284 IF INKEY$="3" THEN GO TO 9990
9285 IF INKEY$="0" THEN GO TO 9998
9286 IF INKEY$="2" THEN GO TO 6301
9287 IF INKEY$<>"1" THEN GO TO 9280
9295 DATA 30,54,30,42,30,66,30,54,28,52,28,40,28,64,28,52,33,57,33,45,33,69,33,57
9296 DATA 31,54,30,42,30,66,30,54,28,52,28,40,28,64,28,52,22,57,33,45,33,69,33,57
9297 DATA 30,42,54,66,30,42,30,66
9340 CLS : INK 6: PRINT '''"BENNY IS THE NEW RECRUIT IN THE BURROWVILLE FIRE SERVICE. WHEN HE IS LEFT IN CHARGE, THE FIREBUG TRIES TO BURN DOWN THE FIRE STATION !"
9345 PRINT ''"BENNY MUST PUT OUT THE FIRES BY STAMPING ON THEM, OR BY RUNNING OVER A FIRE BUCKET WHICH WILL FALL ON TO THE FLAMES."
9350 PRINT ''"HE LOSES SOME ENERGY WHEN HE STEPS ON A FIRE, OR IF HE BUMPS INTO THE FIREBUG."
9355 PRINT ''' INVERSE 1;"ALSO HE LOSES ENERGY VERY FAST IF THERE ARE MORE THAN 7 FIRES ON THE SCREEN AT THE SAME TIME."
9360 PRINT ''"THE GAME ENDS IF BENNY LOSES ALLHIS ENERGY."
9365 PRINT ''"HE GAINS EXTRA ENERGY WHENEVER HE TOUCHES A FIRE BUCKET."
9370 PRINT ''"HE GETS POINTS FOR PUTTING OUT FIRES, AND IF HE DROPS A BUCKET ON TO THE FIREBUG'S HEAD, HE GETS A BONUS AND THE FIREBUG IS SENT BACK TO THE CORNER."
9375 PRINT ''''''"IF BENNY DROPS ALL 20 BUCKETS TOTHE BOTTOM OF THE SCREEN, HE WILL RESTART ON A NEW SCREEN."
9380 PRINT PAPER 2;''''" CONTROLS ": PRINT ';" LEFT....9 RIGHT....0 "
9381 PRINT '"You may also use a joystick in the left Timex port."''
9385 PRINT ''"BENNY WILL CLIMB THE LADDERS TO MOVE UP, AND SLIDE DOWN."''
9470 INK 7: PRINT #0;" PRESS A KEY TO START"
9480 PAUSE 0: GO TO 6301
9485 STOP
9500 SAVE "FIRE/FTR.": BEEP 1,15: VERIFY "FIRE/FTR.": BEEP 1,60: BEEP 1,60
9510 STOP
9992 SAVE "FRFGTR.B1" LINE 1: BEEP 1,15: BEEP 1,60: BEEP 1,60
9998 REM was LKDOS-onlyNote: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.



