Goblins

Developer(s): Jerry Cohler
Date: 198x
Type: Program
Platform(s): TS 2068
Tags: Arcade

Goblins is a dungeon-exploration game in which the player collects eight treasures in sequence and delivers each to a green door while avoiding three pursuing goblins. The screen is constructed procedurally in the GO SUB 8000 routine, which draws a grid of ladder/platform characters and randomly removes some to create openings. All 15 user-defined graphics—including the player sprite, goblin, treasure icons, wall and floor tiles, and a dynamite symbol—are defined via POKE USR in GO SUB 9000 using DATA statements. The player has three lives, five sticks of dynamite (used to blast wall blocks adjacent to the player), and must collect treasures in strict order from the highest level downward. Attribute-color detection (ATTR) drives all collision logic, distinguishing walls (INK 5), the door (INK 32), treasure items (INK 7), and goblin sprites (INK 4) without any coordinate arrays for those objects.


Program Structure

The program is organized into clearly delineated GO SUB routines called from a main loop:

LinesPurpose
9000–9060Define 15 UDGs via POKE USR and READ/DATA
7000–7210Title screen, instructions, and controls display
8000–8150Procedural screen construction (walls, floor, border, treasures)
900–960Initialize goblin positions and player start
100–310Main game loop: player input, goblin AI, collision detection
1000–1060Treasure pickup logic
2000–2040Deliver treasure to door
3000–3040Lose a life
3500–3540Descending BEEP sound effect
4000–4070Dynamite use (four directional cases)
4510–4570Explosion sound effect (ascending then descending)
5000–5050End-of-game “another game?” prompt
6000–6060Win sequence with flashing color cycling

Screen Construction and Attribute-Based Collision

GO SUB 8000 builds the dungeon entirely with PRINT statements using UDG characters and specific INK colors. The routine draws a 2-column-stride grid of ladder pairs (UDG \a, INK 5) across rows 3–19, then randomly erases some with spaces to create gaps. Walls use a brick UDG and the border is drawn with a floor-tile UDG at full width.

All collision detection throughout the program is performed by reading the ATTR value at the relevant screen cell. Because each object type is given a unique INK or PAPER color combination, no separate coordinate arrays are needed for walls, doors, or treasure items:

  • ATTR = 5 — wall/ladder (INK 5, blocks movement)
  • ATTR = 7 — treasure item (INK 7)
  • ATTR = 4 — goblin sprite (INK 4)
  • ATTR = 6 — player carrying treasure (INK 6)
  • ATTR = 32 — green door (INK 32? — actually used for door detection at line 170)
  • ATTR = 134 — player hits a specific combined attribute triggering trap/death sound

UDG Definitions

GO SUB 9000 reads 15 UDG definitions (labeled "A" through "O") from DATA at lines 9040–9050. Each is eight bytes POKEd via POKE USR a$+p,q. The UDGs include wall tiles, floor tiles, the player character, the goblin sprite, treasure icons (eight distinct symbols stored in j$), a dynamite symbol, and a door graphic. This is a standard and efficient technique for custom sprite work.

Player Movement and Input Handling

Lines 120–130 use compound Boolean arithmetic to update the player’s x and y coordinates in a single LET statement each. Each INKEY$ check is ANDed with boundary and ATTR conditions, so no IF statement is needed for movement itself:

  • Line 120: horizontal movement, blocked by walls (ATTR 5) or treasures (ATTR 7) when not carrying
  • Line 130: vertical movement, blocked only by walls (ATTR 5)

The previous position is saved in a, b (line 110), and only if the position changed is the old cell erased (line 150). This avoids unnecessary screen writes.

Goblin AI

Three goblins are tracked in arrays p(3) (column) and q(3) (row). Each frame (lines 190–300), each goblin:

  1. Erases its previous position
  2. Increments its column by +1 each tick (always moves right)
  3. Steps over wall cells by adding 1 again if ATTR = 7 (line 220 — note this checks INK 7, i.e., treasure, not wall; the wall check uses ATTR 5 for vertical movement only)
  4. Adjusts row toward player’s y if the path isn’t blocked (lines 230–240)
  5. Reverses horizontal direction if it hits an INK-4 cell (line 250, checking ATTR = 4)
  6. Bounces off screen edges (line 290)

Catching the player while the player carries treasure (ATTR = 6 at goblin position, line 260) triggers instant death via GO SUB 3500 and GO SUB 3000. Catching the player without treasure (ATTR at goblin matches player, line 160) triggers a life loss only.

Dynamite System

The player starts with five sticks of dynamite (d=5). GO SUB 4000 (line 4000) handles four cases based on player row and which adjacent cell is a wall (ATTR = 7): right-of-player-above, left-of-player-above, right-of-player-below, and left-of-player-below. Each successful use prints a FLASH INK 2 double-UDG explosion graphic, calls the sound routine (GO SUB 4500, lines 4510–4570), erases the graphic, decrements d, and erases a dynamite indicator from the status bar. When d=0, the word GONE is printed with FLASH.

Note that GO SUB 4500 is called but defined at line 4510 — there is no line 4500 — which works correctly because BASIC searches for the nearest line at or after the target.

Bugs and Anomalies

  • Line 3010: LET l=1-1 always sets lives to zero rather than decrementing by one (LET l=l-1 was intended). This means any goblin contact immediately depletes all lives.
  • Line 7030 is referenced by GO TO at line 7050 but does not exist in the listing; the loop presumably targets line 7040 or loops to the nearest available line.
  • Line 7130: PRINT 0; should almost certainly be PRINT #0; (print to lower screen); as written it prints a zero then continues with AT and attributes, producing a stray character.
  • Line 8140 contains two embedded \{18}\{1} and \{16}\{0} sequences mid-string, which are AT and INK control codes embedded directly in the PRINT string — a valid but unusual technique to set attributes inline.
  • The j$ string (line 80) holds eight UDG characters for treasure display, but since UDGs are accessed by letter and j$ is built as a string of UDG chars \g through \n, indexing with j$(t) in line 2010 correctly retrieves each treasure’s symbol in sequence.
  • Line 5040’s condition z$ <>"y" OR z$ <>"Y" OR z$ <>"n" OR z$ <>"N" is always true (a string cannot equal all four values simultaneously), making the GO TO 5010 unconditional when neither y/Y nor n/N was entered — which is the intended behavior but written incorrectly using OR instead of AND.

Sound Effects

Three sound routines are used: a simple BEEP .005 scattered through screen construction for feedback during drawing; a descending chromatic glide in GO SUB 3500 (50 to 0 step −2) for death/transition effects; and an ascending-then-descending two-phase sweep in lines 4510–4570 for the dynamite explosion.

Content

Appears On

Related Products

Related Articles

Related Content

Image Gallery

Source Code

    1 REM ***********************         *Underlined characters*         *are entered in       *         *GRAPHICS mode.       *         *********************** 
   10 PAPER 0:BORDER 0:INK 3:CLS 
   20 PRINT AT 11,5; PAPER 1; INK 7; FLASH 1;" Please wait a moment "
   30 GO SUB 9000:GO SUB 7000
   40 DIM p(3):DIM q(3)
   60 GO SUB 8000:GO SUB 900
   70 LET d=5:LET k=0:LET l=3:LET t=1
   80 LET j$="\g\h\i\j\k\l\m\n"
  100 REM Move man & goblins
  110 LET a=x:LET b=y
  120 LET x=x-(INKEY$="5" AND x>1 AND ATTR (y,x-1) <>5 AND ATTR (y,x-1) <>7)+(INKEY$="8" AND x<30 AND ATTR (y,x+1) <>5 AND ATTR (y,x+1) <>7)
  130 LET y=y-(INKEY$="7" AND y>1 AND ATTR (y-1,x) <>5)+(INKEY$="6" AND y<19 AND ATTR (y+1,x) <>5)
  140 IF INKEY$="0"   THEN GO SUB 4000 
  150 IF a <>x OR b <>y THEN PRINT  AT b,a;" " 
  160 IF ATTR (y,x+1)=7 AND NOT k OR ATTR (y,x-1)=7 AND NOT k THEN  BEEP .1,30:GO SUB 1000
  170 IF ATTR (y,x+1)=32 AND k THEN GO SUB  3500:GO SUB 2000
  180 PRINT AT y,x; FLASH k; INK 6;"\c":BEEP .005,50
  190 FOR z=1 TO 3
  200 PRINT AT q(z),p(z);" "
  210 LET p(z)=p(z)+1
  220 IF ATTR (q(z),p(z))=7 THEN  LET p(z)=p(z)+1
  230 IF q(z)>y AND ATTR (q(z)-1,p(z)) <>5 THEN  LET q(z)=q(z)-1
  240 IF q(z)<y AND ATTR (q(z)+1,p(z)) <>5 THEN  LET q(z)=q(z)+1
  250 IF ATTR (q(z),p(z))=4  THEN  LET p(z)=-p(z)
  260 IF ATTR (q(z),p(z))=6 THEN  GO SUB 3500:GO SUB 3000:GO TO 110
  270 IF ATTR (q(z),p(z))=134  THEN  GO SUB 3500: PRINT AT 21,28; INK 2;"\::\::": GO SUB 5000
  280 PRINT AT q(z),p(z); INK 4;"\d"
  290 IF p(z)=-1 OR p(z)=30  THEN  LET p(z)=-p(z)
  300 NEXT z
  310 GO TO 110
  900 REM Variables
  910 FOR q=1  TO 3
  920 LET p(q)=1
  930 LET q(q)=12+q*2
  940 NEXT q
  950 LET x=30:LET y=2
  960 RETURN 
 1000 REM Take treasure
 1010 FOR c=1  TO 8
 1020 IF t=c AND y=2+2*c  THEN  GO TO 1050
 1030 NEXT c
 1040 IF NOT  k THEN GO SUB 4000: GO TO 1060
 1050 LET k=1:PRINT AT y,x-1;" "; AT y,x+1;" "
 1060 RETURN 
 2000 REM Treasure at door
 2010 PRINT AT 0,8+(t*2); PAPER 2; INK 6;j$(t)
 2020 LET k=0:LET t=t+1
 2030 IF t=9 THEN  GO TO 6000
 2040 RETURN 
 3000 REM Loose life
 3010 LET l=1-1:PRINT AT 21,28+1; INK 2;"\::"
 3020 IF NOT k  THEN PRINT AT  q(z),p(z);" ":PRINT AT q(1),p(1);" ":PRINT AT q(2),p(2);" ":PRINT AT q(3),p(3);" ":GO SUB 900
 3030 IF l=0 THEN PRINT AT 21,29 ; INK 2;"\::":GO SUB 3500:GO TO 5000
 3040 RETURN 
 3500 REM Sound
 3510 FOR s=50 TO 0 STEP -2
 3520 BEEP .01,s
 3530 NEXT s
 3540 RETURN 
 4000 REM Use dynamite
 4010 IF INKEY$ <>"0" OR d=0 THEN  GO TO 4070
 4020 IF INKEY$="0" AND y <>18 AND ATTR (y,x+1)=7 THEN PRINT AT  y+1,x-2; FLASH 1; INK 2;"\a\a": GO SUB 4500:PRINT AT y+1,x-2; FLASH 0;"  ": LET d=d-1:PRINT AT 21,10+d; INK 2;"\::"
 4030 IF INKEY$="0" AND y <>18  AND ATTR (y,x-1)=7  THEN PRINT AT  y+1,x+1; FLASH 1; INK 2;"\a\a": GO SUB 4500:PRINT AT y+1,x+1; FLASH 0;"  ":LET d=d-1: PRINT AT 21,10+d; INK 2;"\::"
 4040 IF INKEY$="0" AND y=18 AND ATTR (y,x+1)=7  THEN PRINT AT y-1 ,x-2; FLASH 1; INK 2;"\a\a": GO SUB 4500:PRINT AT y-1,x-2; FLASH 0;"  ":LET d=d-1:PRINT AT 21,10+d; INK 2;"\::"
 4050 IF INKEY$="0" AND y=18 AND ATTR (y,x-1)=7 THEN PRINT AT y- 1,x+1; FLASH 1; INK 2;"\a\a":GO SUB 4500:PRINT AT y-1,x+1; FLASH 0;"  ":LET d=d-1:PRINT AT 21,10+d; INK 2;"\::"
 4060 IF d=0 THEN PRINT AT 21,10 ; FLASH 1; PAPER 2; INK 6;"GONE'"
 4070 RETURN 
 4510 FOR e=0 TO 50 STEP 6
 4520 BEEP .005,e
 4530 NEXT e
 4540 FOR e=50 TO 20 STEP -1
 4550 BEEP .005,e
 4560 NEXT e
 4570 RETURN 
 5000 REM Another Game?
 5010 INPUT  "     Another Game? (y/n) "; LINE z$
 5020 IF z$="y" OR z$="Y" THEN  CLS :GO TO 40
 5030 IF z$="n" OR z$="N" THEN  CLS : GO TO 5050
 5040 IF z$ <>"y" OR z$ <>"Y" OR z$ <>"n" OR z$ <>"N" THEN GO TO  5010
 5050 PRINT '' INK RND*6; BRIGHT  1; TAB RND*15;"OK,BYE FOR NOW!":  POKE 23692,255:GO TO 5050
 6000 REM Win game
 6010 CLS 
 6020 PRINT AT 10,10; BRIGHT 1; INK INT (RND*6)+1;"WELL DONE''              You have all the treasure"
 6030 LET w= INT (RND*50)
 6040 BEEP .01,w
 6050 IF INKEY$=""  THEN GO TO  6020
 6060 STOP 
 7000 REM Game title
 7010 PAPER 0:BORDER 0:CLS 
 7020 PRINT #0; AT 1,0; INK 7;" Press any key for instructions",
 7040 PRINT AT 19,16; INK INT (RND*6)+1;" by Jerry Cohler":BEEP .01, INT (RND*50)
 7050 IF INKEY$=""  THEN GO TO  7030
 7060 PAUSE 0:BEEP .1,30:CLS  
 7070 REM Instructions"
 7080 PRINT AT 0,4; INK 4; BRIGHT 1;"I N S T R U C T I O N S"
 7090 PRINT AT 2,0; INK 7;"Your quest is to retrieve all   the treasure from the dungeon."
 7100 PRINT AT 5,0; INK 7;"Treasure must be collected in   order (highest level first) and taken to the green door."
 7110 PRINT AT 9,0; INK 7;"Any item not due for collection will block your path (but not   the goblins!!). However, if     adjacent to such a treasure, you can  use your dynamite to blast holesin the floor(or ceiling if on   the bottom level)."
 7120 PRINT AT 17,0; INK 7;"You have three lives - but if   caught by a goblin while in     possesion of treasure it's      instant death'!"
 7130 PRINT 0; AT 1,0; PAPER 6; INK 2; FLASH 1;" Press any keyfor controls..."
 7140 PAUSE 0:BEEP .1,30:CLS 
 7150 REM Game controls
 7160 PRINT AT 3,8; INK 4; BRIGHT 1;"C O N T R O L S"
 7170 PRINT AT 7,1; INK 7;"5     6     7     8       0                                                                    left down    up  right  dynamite"
 7180 PRINT AT 13,6; FLASH 1; INK 6;"\c"; AT 13,8; FLASH 0; INK 7;"treasure collected"
 7190 PRINT AT 21,3; PAPER 2; INK 6; FLASH 1;"Press any key to play..."
 7200 PAUSE 0:CLS :BEEP .1,30
 7210 RETURN 
 8000 REM Screen construction
 8010 FOR a=1 TO 30 STEP 2:FOR b=3 TO 19 STEP 2
 8020 PRINT AT b,a; INK 5;"\a\a":BEEP .005,(b+a)
 8030 NEXT b:NEXT a
 8040 FOR c=3 TO 17 STEP 2
 8050 PRINT AT c,4+ INT (RND*5)*5;"  "
 8060 NEXT c
 8070 PRINT AT 1,1; INK 5;"\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f\f"
 8080 PRINT AT 20,0; PAPER 7; INK 3;"\e\e\e\e\e\e\e\e\e\e\e\e\e\e\e\e\e\e\e\e\e\e\e\e\e\e\e\e\e\e\e\e"
 8090 FOR d=1 TO 19
 8100 PRINT AT d,0; PAPER 7; INK 3;"\e"; AT d,31; PAPER 7; INK 3;"\e":BEEP .005,(50-d)
 8110 NEXT d
 8120 PRINT AT 2,31; PAPER 4; INK 0;"\b"; AT 0,0; PAPER 2; INK 6;" TREASURE                       "
 8130 PRINT AT 21,0; PAPER 2; INK 6;" DYNAMITE \o\o\o\o\o       lives \c\c\c "
 8140 PRINT AT 4,7; INK 7;"\g"; AT 6,22; INK 7;"\h"; AT 8,17; INK 7;"\i"; AT 10,12; INK 7;\{18}\{1}"\j"; AT 12,27; INK 7;"\k"; AT 14,7; INK 7;\{16}\{0}"\l"; AT 16,12; INK 7;"\m"; AT 18,22; INK 7;"\n"
 8150 RETURN 
 9000 REM Graphics
 9010 FOR n=1 TO 15:READ a$
 9020 FOR p=0 TO 7:READ q:POKE USR a$+p,q
 9030 NEXT p:NEXT n
 9040 DATA "A",255,255,219,228,25,164,8,0,"B",255,129,189,189,129,161,129,129,"C",28,28,136,126,29,28,20,54,"D",57,57,17,255,185,57,170,238,"E",34,255,136,255,34,255,136,255,"F",255,255,255,60,24,126,90,24
 9050 DATA "G",8,8,20,20,20,20,28,0,"H",8,20,42,69,42,20,8,0,"I",1,26,4,10,18,32,64,0,"J",16,84,56,254,56,84,16,0,"K",0,2,5,253,69,229,162,0,"L",16,68,40,130,56,186,56,0,"M",0,16,4,18,36,82,8,0,"N",24,189,153,90,126,90,126,0,"O",0,6,24,56,112,224,192,0
 9060 RETURN 
 9990 CLS 

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top