Dragon Slayer is a graphical action game. Your knight starts beside a lake and must cross to the castle, collect arrows at its door and shoot the dragon flying overhead, while the dragon swoops and breathes fire. The status line shows arrows, lives (four to start) and dragons slain; when the game ends it announces whether the knight or the dragon won and offers another game.
The REMs credit Richard Snowden, say it was printed in PC Weekly, and note that it was typed in by Clem Taylor.
Program Analysis
MOVESET copies the character set to new memory and READCHARS redefines characters for the knight, dragon, arrows and castle; CASTLE and LAKE draw the scene, and PLAY runs the game loop, reading the keyboard with KEYROW.
Potential Issues
MOVESETreads the character-set pointer at the fixed address 167722. That works on a Minerva ROM, but on the JS ROM in QLRun the program stops with “bad parameter” at line 1380.
It came from a QL owner’s floppy copies of QUANTA and IQLUG library material, imaged double-stepped so that only half of each disk survived; this file read back complete. The download holds the files exactly as recovered and a QL5A floppy image, Dragon Slayer.img, with the same files and their QDOS headers. Mount the image as FLP1_ (drop it on the QLRun page, or use it as a floppy image in sQLux, QPC2 or Q-emuLator) and type lrun flp1_slayer_bas.
Tested in QLRun: it runs with the Minerva ROM (shown in the screenshots); with the JS ROM it stops at line 1380.
Source Code
10 REMark Dragon Slayer
20 REMark BY Richard Snowden
25 REMark printed in PC Weekly
26 REMark typed by clem taylor
30 REMark
120 MOVESET
130 READCHARS
140 CASTLE 280,166
150 DOOR 280,166,5
160 LAKE
170 INIT
180 PLAY
190 STOP
200 DEFine PROCedure CASTLE(X,Y)
210 WINDOW #1,465,210,32,2:WINDOW #0,465,46,32,210:BEEP
220 FOR I=0 TO 2:BORDER #I,0,0:SCALE #I,256,0,0:INK #I,7:PAPER #I,0:CLS #I:OVER #I,0
230 MODE 8
240 LINE X,Y:INK 2:FILL 1:LINE_R 50,0 TO 0,40 TO -50,0 TO 0,-40
250 INK 2,3:FILL 1:LINE_R 0,40 TO 10,5 TO 50,0 TO -10,-5
260 INK 2,0:FILL 1:LINE_R TO 10,5 TO 0,-40 TO -10,-5 TO 0,40
270 INK 0:FILL 1:LINE X,Y
280 LINE_R 3,10 TO 0,20 TO 3,5 TO 3,-5 TO 0,-20 TO -6,0
290 FILL 1:LINE X+38,Y:LINE_R 3,10 TO 0,20
300 INK 3:FILL 1:LINE X,Y:LINE_R 0,40 TO 5,10 TO 5,-10 TO -10,0
310 INK 3,0:FILL 1:LINE_R 5,10 TO 10,5 TO 5,-10 TO -10,-5 TO -5,10
320 INK 3:FILL 1:LINE X+38,Y:LINE_R 0,40 TO 5,10 TO 5,-10 TO -10,0
330 INK 3,0:FILL 1:LINE_R 5,10 TO 10,5 TO 5,-10 TO -10,-5 TO -5,10
340 FILL 0:OVER -1:CSIZE 3,1:CSIZE #0,0,1:OVER #0,1
350 FOR I= 10 TO 0 STEP -2:INK #0,1+6*(I=0):CURSOR #0,I, (10-I) :PRINT #0,"QL Dragon Slayer"
360 OVER #0,0:END DEFine
370 DEFine PROCedure DOOR(X,Y,COLOUR)
380 LINE X+25,Y:OVER 0:INK COLOUR:FILL 1
390 LINE_R -10,0 TO 0,30 TO 10,5 TO 10,-5 TO 0,-30 TO -10,0:OVER -1
400 END DEFine
410 DEFine PROCedure INIT
420 X=20:Y=150:DIRN=33:FX=330:FY=50:LIVES=4:DRAS=-1
430 DX=270:DY=80:PO=37:FIRE=0:ARR=6:INC=0
440 END DEFine
450 DEFine PROCedure PLAY
460 KNIGHT X,Y:DRA DX,DY,PO:ARROW FX,FY:ARROWSLEFT:LIVESLEFT:DRASLEFT
470 REPeat LOOP
480 K1=KEYROW(1)
490 IF K1&&2 : IF X>8 THEN KNIGHT X,Y :X=X-8:DIRN=35:KNIGHT X,Y
500 IF K1&&16 : IF X<420 THEN KNIGHT X,Y:X=X+8:DIRN=33:KNIGHT X,Y
510 IF K1&&4 : IF Y>8 THEN KNIGHT X,Y :Y=Y-8 :KNIGHT X,Y
520 IF K1&&128: IF Y<180 THEN KNIGHT X,Y:Y=Y+8 :KNIGHT X,Y
530 IF KEYROW(7)&&4:IF ARR>0:IF NOT FIRE THEN FIRE=1:FX=X:FY=Y:FP=10*(DIRN=33)-10*(DIRN=35):INC=DIRN=33:ARR=ARR-1:ARROWSLEFT:ARROW FX,FY:BEEP 0,10,-2,100,-2,100
540 IF FIRE:IF FX<10 OR FX>420 THEN FIRE=0:ARROW FX,FY:FX=330:FY=50:BEEP:ELSE ARROW FX,FY:FX=FX+FP:ARROW FX,FY
550 IF FX<DX+50 :IF FX>DX:IF FY>DY -10:IF FY<DY+10 THEN BUMP DX,DY,4:DRASLEFT
560 IF ARR=0:IF Y<80 :IF X>326 AND X<334: IF Y>40 THEN DOOR 80,166,0
570 IF ARR=0:IF Y<72 : IF Y>60:IF X>326 AND X<334 THEN ARR=6:KNIGHT X,Y:X=20:Y=150:DOOR 280,166,5:KNIGHT X,Y:ARROWSLEFT:FOR S=255 TO 10 STEP -1:BEEP 1600,S,-255,500,-255,500
580 R=DOT(X,Y)
590 IF R THEN BUMP X,Y,1:LIVESLEFT
600 IF FIRE>Y-10:IF DY<Y+10 THEN DRA DX,DY,PO:DY=(DY+2)*(DY<170):DRA DX,DY,PO
610 IF RND(40)<5 THEN
620 IF FIRE THEN ARROW FX,FY
630 BREATH DX,DY:DRA DX,DY,PO
640 IF DX>X THEN PO=37:DX=DX-8
650 IF DX<X THEN PO=42:DX=DX+8*(DX<366)
660 IF DY>Y :IF DY>18 THEN DY=DY-8:IF DOT (DX+(PO=42)*40,DY) THEN DY=80
670 IF DX<Y THEN DY=DY+8:IF DOT(DX+ (PO=42)*40,DY) THEN DY=130
680 DRA DX,DY,PO
690 IF FIRE THEN ARROW FX,FY
700 END IF
710 END REPeat LOOP
720 END DEFine
730 DEFine PROCedure ARROW (X,Y)
740 INK 3:CURSOR X,Y:PRINT CHR$(188+INC)
750 END DEFine
760 DEFine PROCedure ARROWSLEFT: AT #0,0,20:PRINT #0,"Arrows:";:FOR I=1 TO ARR:PRINT #0,CHR$(189)
770 CLS #0,4:END DEFine
780 DEFine PROCedure BREATH (BX,BY)
790 LOCal W,P
800 BEEP 16000,255,-200,20,-200,20,9,0
810 IF PO=37:P=RND(40):P=P*(P<BX):W=BX-P:ELSE P=BX+50:W=RND(320 TO 440)-P:IF W<P THEN W=440-P
820 IF BY>20:IF BY<72:IF BX<320:IF PO<>37 THEN W=300-P:W=W*(P<290)
830 BLOCK W,40,P,BY-10,2,0
840 IF X>P:IF X<P+W:IF Y>BY-30:IF Y<BY+30 THEN BUMP X,Y,2:LIVESLEFT
850 BLOCK W,40,P,BY-10,2,0
860 IF FIRE THEN BEEP 0,10,-2,100,-2,100
870 END DEFine
880 DEFine PROCedure DRA(X,Y,D)
890 INK 4
900 CURSOR X,Y:PRINT CHR$(D):CURSOR X+10,Y:PRINT CHR$(D+1):CURSOR X+20,Y:PRINT CHR$(D+2):CURSOR X+30,Y:PRINT CHR$(D+3)
910 END DEFine
920 DEFine PROCedure BUMP(CX,CY,COLOUR)
930 LOCal P,R,F
940 BEEP 0,2,50,50,50,7,7:INK COLOUR
950 LINE CX/440*420,(190-CY)/190*256:FILL 0
960 FOR P= 1 TO 2
970 FOR R=1 TO 50 STEP -5:CIRCLE_R 0,0,R
980 FOR R=50 TO 1 STEP -5:CIRCLE_R 0,0,R
990 NEXT P:BEEP
1000 END DEFine
1010 DEFine PROCedure LIVESLEFT:LIVES=LIVES-1:AT #0,1,16:PRINT #0,"Lives:";:FOR I = 1 TO LIVES:PRINT #0,CHR$(134);:NEXT I:PRINT #0," "
1020 KNIGHT X,Y:X=20:Y=150:KNIGHT X,Y:IF LIVES=0 THEN GAMEOVER
1030 END DEFine
1040 DEFine PROCedure DRASLEFT:DRAS=DRAS+1:AT #0,1,26:PRINT #0,"Dragons:";DRAS;
1050 DRA DX,DY,PO:DX=270:DY=80:PO=37:DRA DX,DY,PO:FIRE=0:ARROW FX,FY:FX=330:FY=50:IF DRAS=10 THEN GAMEOVER
1060 END DEFine
1070 DEFine FuNction DOT(DX,DY)
1080 P=131072+(DX+32)*.2530612+(DY+2)+128
1090 RETurn PEEK(P)+PEEK(P+1)+PEEK(P+2560)+PEEK(P+2561)
1100 END DEFine
1110 DEFine PROCedure LAKE
1120 INK 1:FILL 1
1130 LINE 0,160 TO 52,150 TO 43,130 TO 0,130 TO 0,160:FILL 1
1140 LINE 75,145 TO 390,110 TO 390,80 TO 64,125 TO 75,150
1150 END DEFine
1160 DEFine PROCedure SCREEN
1170 OVER -1:CSIZE 0,0:BEEP 0,255,-60,100,-25,100
1180 FOR T=1 TO 2
1190 FOR P=10 TO 0 STEP -1
1200 AT P,P+1:FOR X=P TO 36-P:INK ( X MOD 7)+1:PRINT CHR$(41);
1210 FOR Y=P TO 19-P:AT Y,37-P:INK ((Y+3) MOD 6)+1:PRINT CHR$(41)
1220 FOR X=37-P TO P STEP -1:AT 20-P,X:INK (X MOD 7)+1:PRINT CHR$(41);
1230 FOR X=20-P TO P STEP -1:AT Y,P:INK ((Y+3) MOD 6)+1:PRINT CHR$(41)
1240 NEXT P:BEEP 0,0,-200,200,-200,200:NEXT T:BEEP
1250 END DEFine
1260 DEFine PROCedure GAMEOVER
1270 AT #0,0,0:CSIZE #0,1,1:CLS #0:BEEP 0,255,-60,-70,-25,100
1280 IF DRAS=10 THEN PRINT #0,"The Knight won";:PAUSE 50:PRINT #0," this time":ELSE PRINT #0,"The dragon won";:PAUSE 50:PRINT #0," as per usual"
1290 PAUSE 50:CSIZE #0,3,1
1300 PRINT #0,"Another game (Y/N)";:I$=INKEY$(8000)
1310 IF I$="Y" THEN RUN 140:ELSE SCREEN:STOP
1320 END DEFine
1330 DEFine PROCedure MOVESET
1340 SET=167722
1350 OLDBASE=PEEK_L(SET)
1360 NEWBASE=RESPR(875)
1370 FOR M=0 TO 875 STEP 4
1380 POKE_L NEWBASE+M,PEEK_L (OLDBASE+M)
1390 NEXT M
1400 POKE_L SET,NEWBASE
1410 END DEFine
1420 DEFine PROCedure READCHARS
1430 RESTORE
1440 NUMBEROFCHARS=13
1450 FOR CHAR=1 TO NUMBEROFCHARS
1460 READ C:CHARBASE=NEWBASE+10+(C-32)*9
1470 FOR DAT=1 TO 9
1480 READ D:POKE CHARBASE+DAT,D
1490 NEXT DAT
1500 NEXT CHAR
1510 END DEFine
1520 REMark
1530 DATA 33,24,24,16,52,92,20,24,36,72
1540 DATA 34,24,24,16,52,92,52,24,40,68
1550 DATA 35,48,48,16,88,116,80,56,72,36
1560 DATA 36,48,48,16,88,116,88,48,40,68
1570 DATA 37,0,16,96,16,104,4,4,0,0
1580 DATA 38,0,0,4,24,48,64,64,48,12
1590 DATA 39,0,40,84,0,0,0,0,0,124
1600 DATA 40,0,0,68,44,60,56,32,32,64
1610 DATA 41,124,68,84,84,84,84,84,68,124
1620 DATA 42,0,0,68,72,104,120,120,8,4
1630 DATA 43,0,40,84,0,0,0,0,0,124
1640 DATA 44,0,0,112,8,4,4,8,48,64
1650 DATA 45,0,16,12,16,28,96,64,0,0
1660 DEFine PROCedure KNIGHT(X,Y)
1670 INK 7:CURSOR X,Y:PRINT CHR$(DIRN+X/8 MOD 2)
1680 END DEFineNote: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

