Back in 1980, I created a computer game for my TRS-80 Pocket Computer, inspired by Tunnels & Trolls. Given the passing of Rick Loomis, I thought I would dig it out.
As with T&T, I had attributes: ST (Strength), DX (Dexterity), and CN (Constitution, used for hit points). But I skipped LK (Luck) and CH (Charisma), and I used D&D’s WS (Wisdom) instead of T&T’s IQ (Intelligence). Like T&T, and unlike D&D, attributes could increase: in my case, quickly, after every monster, rolling three dice and if the total exceeds an attribute you can increase that attribute; if it doesn’t exceed any attribute, take that amount in gold instead. Powerful characters would gain wealth, while weaker characters would gain power. Unlike in T&T, attributes couldn’t increase past 18, though.
Combat was different. As with T&T, monsters had one number (this MR was based on how deep and how far you were in the dungeon), which was used for all their attributes (CN=3*MR, ST=3*MR, etc.). But missile attacks (F for FIRE, using DX plus a bonus for level deep) lost effectiveness after the first round, melee attacks (A for ATTACK, using ST) quickly lost effectiveness during an encounter, and spell attacks (C for CAST SPELL, using WS) gradually lost effectiveness. If you rolled under your attribute score (on 3 dice), you doubled your result, so better attributes minimized your downside. Your result was compared to the monster’s, and the difference was the damage and determined who it was dealt to (a difference of 0 harmed no one). After killing a monster, you could heal up to the monster’s level, providing the incentive for attacking tougher monsters.
Saving rolls were different too: they were done on three dice instead of two, with no cascading rolls in case of doubles. You had to roll under your attribute to succeed. A wisdom saving roll is needed when looking for traps, and a dexterity saving roll when jumping away from triggered traps or for parrying an attack when fleeing a monster.
A last shout-out to T&T: the troll was the toughest monster!
The Pocket Computer would only display 24 characters at a time. After a PRINT statement, you’d hit a key to see the next PRINT statement.
The Pocket Computer had a Tiny BASIC that lacked the ELSE statement (a common omission), but also RND, DATA, READ, and RESTORE. However, unlike TRS-80 Level I BASIC (my first programming language), which only had two string variables (up to 16 characters each), the PC-1 had 26 string variables of 7 characters each – sort of. They were actually an overlay over the 26 numeric variables: if you used A$, you couldn’t use A (numeric variable), and so forth. Also the array A() would alias these variables: A(1) was the same as A, A(2) was B, etc.
The PC-1 only had 1,425 bytes of RAM available for programming, and I must have hit that limit because my TRS-80 Level II BASIC listing had longer text descriptions and an additional command.
The goal is to collect the most gold. Commands:
- Attack with a sword (uses ST)
- Cast spell (uses WS)
- Fire missile (uses DX)
- Traps? (detects a trap in an empty room using WS)
- Inventory (shows your attributes)
- North
- South
- East
- West
- Up
- Down
You can play Tunnels & Traps with Joshua Bell’s great Applesoft BASIC emulator. Copy and paste the following code, modified a bit to work there:
1 DIM A(26):GOTO 7 3 D=0:FOR I=1TO 3:R=23*R:R=R-32767*INT(R/32767):D=D+R-6*INT(R/6)+1:NEXT :RETURN 5 PRINT "ST"; S; " DX"; F; " WS"; W; " CN"; C; " GD"; G:RETURN 6 GOTO 30 7 PRINT "TUNNELS & TRAPS":INPUT "EXPLORE TUNNEL #?";N:R=N 8 GOSUB 3:S=D:GOSUB 3:F=D:GOSUB 3:W=D:GOSUB 3:C=D:G=0:GOSUB 5 9 PRINT:INPUT "COMMAND?";A$:GOSUB 3:GOSUB 10:GOTO 9 10 IF A$="A" THEN T=S-E:PRINT "SWORD";:GOTO 76 12 IF A$="C" THEN T=W-E/3:PRINT "SPELL";:GOTO 76 13 IF A$="D" THEN Z=Z-1:GOTO 6 14 IF A$="E" THEN X=X+1:GOTO 6 15 IF A$="F" THEN T=(F+L)*(E=0):PRINT "ARROW";:GOTO 76 18 IF A$="I" GOTO 5 20 IF A$="N" THEN Y=Y-1:GOTO 6 22 IF A$="S" THEN Y=Y+1:GOTO 6 23 IF A$="T" THEN T=W:GOTO 62 24 IF A$="U" THEN Z=Z+1:GOTO 6 26 IF A$="W" THEN X=X-1:GOTO 6 28 PRINT "NOR SOU EAST WEST UP DN":PRINT "ATTK CAST FIRE INV TRPS?":RETURN 30 IF M<0THEN GOSUB 62 31 IF M>0THEN A$="X":PRINT "PARRY";:T=W:GOSUB 80 32 L=INT((ABS(X)+ABS(Y)+3*ABS(Z))/3)+1:M=0:GOSUB 3:IF D>7 THEN M=L:REM 38 IF D<5 THEN PRINT "TRAP";:T=F:M=-L 40 IF M=0 THEN PRINT "NOTHING"; 41 IF D<7 THEN M=-L 42 IF M=1 THEN PRINT "IMP"; 44 IF M=2 THEN PRINT "KOBOLD"; 46 IF M=3 THEN PRINT "GOBLIN"; 48 IF M=4 THEN PRINT "HOBGOBLIN"; 50 IF M=5 THEN PRINT "ORC"; 52 IF M=6 THEN PRINT "HALFORC"; 54 IF M=7 THEN PRINT "OGRE"; 56 IF M>7 THEN PRINT "TROLL"; 58 PRINT " HERE!" 60 IF D>4 THEN RETURN 62 GOSUB 3:IF (D<T)AND(M<0) THEN PRINT "YOU JUST ESCAPE A TRAP!":M=0:RETURN 64 IF M>=0 THEN PRINT "NO TRAP DETECTED.":RETURN 66 GOSUB 3:IF A$="T"THEN D=INT(D/2) 68 IF D>L THEN D=L 70 IF D>C THEN D=C-1 72 C=C-D:PRINT "A TRAP CAUSED ";D;" DAMAGE.":RETURN 76 E=E+1:IF M<=0 THEN PRINT "S ARE USELESS HERE!":RETURN 78 GOSUB 3:IF D<T THEN D=D+D 80 P=D:GOSUB 3:IF D<L*2 THEN D=D+D 82 IF P>=D AND A$<>"X" THEN M=M-(P-D)/3:PRINT " HIT FOR ";P-D;" DAMAGE." 83 IF P>=D AND A$="X" THEN PRINT " SUCCEEDED." 84 IF P<D THEN C=C+P-D:PRINT " MISSED.":PRINT "YOU TOOK ";D-P;" DAMAGE." 86 IF C<1 THEN PRINT "YOU DIED IN TUNNEL ";N;"!":GOSUB 5:PRINT:END 88 IF M>0 THEN RETURN 90 PRINT "YOU KILLED IT!":M=0:E=0 91 GOSUB 3:PRINT "ROLL OF ";D;": ";:IF C<L THEN C=L:IF C>18 THEN C=18 92 IF (D<=S)AND(D<=F)AND(D<=W)THEN G=G+D:PRINT "GOLD!":GOTO 5 93 T=23:A(6)=F:A(19)=S:A(23)=W 94 IF (S>=F)AND(S>=W)THEN T=19:U=23:V=6:IF (F>=W)THEN U=6: V=23 95 IF (F>S)AND(F>=W)THEN T=6:U=23:V=19:IF (S>=W)THEN U=19: V=23 96 IF (W>S)AND(W>F)THEN T=23:U=6:V=19:IF (S>=F)THEN U=19: V=6 97 IF D>A(T)THEN GOTO 195 98 IF D>A(U)THEN T=U:GOTO 195 99 T=V 195 IF (T=6)THEN F=F+1:PRINT "DEXTERITY!":GOTO 5 196 IF (T=19)THEN S=S+1:PRINT "STRENGTH!":GOTO 5 197 IF (T=23)THEN W=W+1:PRINT "WISDOM!":GOTO 5 198 GOTO 5
And below is the PC-1 source code. You’ll have to forgive the lack of comments. There wasn’t sufficient memory to have any! And it is spaghetti code, inspired by assembly language: the common subroutines had one-digit line numbers that jumped down because every byte counted, and RETURN took less space than GOTO 9. The whole thing later got much further developed in the comparative luxury of 16KB RAM on the TRS-80 Model I Level 2. But that’s a post for another day.
1:GOTO 7 3:D=0:FOR I=1TO 3:R=23*R:R=R-32767*INT(R/32767):D=D+INT(R/6)+1:NEXT :RETURN 5:PRINT "ST";S;" DX";F;" WS";W;" CN";C;" GD";G:RETURN 6:GOTO 30 7:INPUT "TUNNEL #?";N:R=N 8:GOSUB 3:S=D:GOSUB 3:F=D:GOSUB 3:W=D:GOSUB 3:C=D:GOSUB 5 9:INPUT A$:GOSUB 3:GOSUB 10:GOTO 9 10:IF A$="A"THEN T=S-E:PRINT "SWORD";:GOTO 76 12:IF A$="C"THEN T=W-E/2:PRINT "SPELL";:GOTO 76 13:IF A$="D"THEN Z=Z-1:GOTO 6 14:IF A$="E"THEN X=X+1:GOTO 6 15:IF A$="F"THEN T=F*(E=0):PRINT "ARROW";:GOTO 76 20:IF A$="N"THEN Y=Y-1:GOTO 6 22:IF A$="S"THEN Y=Y+1:GOTO 6 23:IF A$="T"THEN T=W:GOTO 62 24:IF A$="U"THEN Z=Z+1:GOTO 6 26:IF A$="W"THEN X=X-1:GOTO 6 28:RETURN 30:IF M<0GOSUB 62 31:IF M>0THEN A$="X":PRINT "PARRY";:T=F:GOSUB 80 32:L=INT((ABS X+ABS Y+ABS Z)/3):M=0:GOSUB 3:IF D>8THEN M=L 38:IF D<5THEN PRINT "TRAP";:T=F:M=-L 40:IF M=0THEN PRINT "NOTHING"; 41:IF D<7THEN M=-L 42:IF M=1PRINT "IMP"; 44:IF M=2PRINT "KOBOLD"; 46:IF M=3PRINT "GOBLIN"; 48:IF M=4PRINT "HOBGOBLIN"; 50:IF M=5PRINT "ORC"; 52:IF M=6PRINT "HALFORC"; 54:IF M=7PRINT "OGRE"; 56:IF M>7PRINT "TROLL"; 58:PRINT " HERE!" 60:IF D>4 RETURN 62:GOSUB 3:IF (D<T)*(M<0)PRINT "YOU ESCAPE TRAP!":M=0:RETURN 64:IF M>=0PRINT "NOT FOUND":RETURN 66:GOSUB 3:IF A$="T"THEN D=INT(D/2) 68:IF D>LTHEN D=L 70:IF D>CTHEN D=C-1 72:C=C-D:PRINT "TRAP HIT FOR ";D;".":RETURN 75:E=E+1:IF M<=0PRINT "S USELESS HERE!":RETURN 77:GOSUB 3:IF D<TTHEN D=D+D 79:P=D:GOSUB 3:IF D<L*2THEN D=D+D 81:IF (P>=D)*(A$<>"X")THEN M=M-(P-D)/3:PRINT " HIT FOR ";P-D;"." 83:IF (P>=D)*(A$="X")PRINT "!" 84:IF P<DTHEN C=C+P-D:PRINT " MISSED":PRINT "YOU TOOK ";D-P;" HITS." 86:IF C<1PRINT "YOU DIED!":GOSUB 5:END 88:IF M>0RETURN 90:PRINT "YOU SLEW IT!":M=0:E=0 91:GOSUB 3:PRINT "ROLL OF ";D;":";:IF C<LTHEN C=L:IF C>18THEN C=18 92:IF (D<=S)*(D<=F)*(D<=W)THEN G=G+D:PRINT "GD!":GOTO 5 93:IF (S>=F)*(S>=W)THEN T=19:U=23:V=6:IF (F>=W)THEN U=6:V=23 94:IF (F>S)*(F>=W)THEN T=6:U=23:V=19:IF (S>=W)THEN U=19:V=23 95:IF (W>S)*(W>F)THEN T=23:U=6:V=19:IF (S>=F)THEN U=19:V=6 96:IF D>A(T)GOTO 99 97:IF D>A(U)THEN T=U:GOTO 99 98:T=V 99:A(T)=A(T)+1:IF (T=6)PRINT "DX!" 100:IF (T=19)PRINT "ST!" 101:IF (T=23)PRINT "WS!" 102:GOTO 5
You must be logged in to post a comment.