1 ON ERROR REPORT : PRINT ;" at ";ERL : END 2 REM config init 3 F%=OPENIN("config"):D$=FNgs:FOR K%=1 TO LEN(D$) STEP 3:VDU EVAL(MID$(D$,K%,3)):NEXT K%:K%=VAL(FNgs):IF K% THEN DIM I% 3:I%?0=K%:I%?1=VAL(FNgs):I%?2=VAL(FNgs):K%=1 4 D$=FNgs+" ":M$=FNgs:CLOSE#F% 5 REM io init 6 PRINT "Bob and Trev: Resurrection+"'"Loading" 7 REM static vars - to remove 8 CLASS_WEAPON%=0 9 CLASS_AMMO%=1 10 CLASS_ARMOUR%=2 11 CLASS_BOOK%=3 12 CLASS_MAGAZINE%=4 13 CLASS_DRINK%=5 14 CLASS_FOOD%=6 15 CLASS_ITEM%=7 16 CLASS_MONSTER%=8 17 CLASS_CASH%=9 18 TYPE_PLAYER%=96 19 TYPE_CORPSE%=98 20 TYPE_NUTDEVICE%=73 21 TYPE_MICROWAVE%=95 22 TYPE_READINGGLASSES%=57 23 TILE_FLOOR%=0 24 TILE_DOWNSTAIRS%=1 25 TILE_UPSTAIRS%=2 26 TILE_WALL%=3 : REM Anything here and above is novis. Except upstairs2! 27 TILE_WINDOW%=4 28 TILE_OPENWINDOW%=5 29 TILE_BROKENWINDOW%=6 30 REM TILE_LOCKEDWINDOW%=7 31 TILE_DOOR%=7 32 TILE_OPENDOOR%=8 33 TILE_BROKENDOOR%=9 34 REM TILE_LOCKEDDOOR%=11 35 TILE_UPSTAIRS2%=10 : REM these two must be at the end, and have the same offsets as each other from their discovered counterparts 36 TILE_WALL2%=11 37 NUM_TYPES%=100 38 FIGHT_COEF=2 39 FIGHT_A=0.95 40 FIGHT_B=1.3 41 XP_RATE=2 42 FIRE_COEF=2.23 43 BOOM_COEF=2 44 REM memory init 45 DIM m% 880,o% 7*255,d% 13,s% 14,v% 4,b% 6 46 p%=0:v%!0=0 47 REM data init 48 F%=OPENIN("dundat") 49 DIM D% EXT#F% 50 PROCRA(D%,EXT#F%) 51 CLOSE#F% 52 T%=D%+6:C%=D%+D%?0+(D%?1)*256:M%=D%+D%?2+(D%?3)*256:S%=D%+D%?4+(D%?5)*256 53 REM game init 54 INPUT "Name";N$ 55 F%=OPENUP(N$) 56 IF F%=0 THEN F%=OPENOUT(N$):CLOSE#F%:F%=OPENUP(N$):PROCnew ELSE PROCcont 57 ON ERROR COLOUR63:REPORT:PRINT ;" at ";ERL;" >>";:ON ERROR OFF:_%=GET:PROCkill(0,"Error "+STR$(ERR)+" at "+STR$(ERL)) 58 REPEAT 59 t%=t%+1 60 IF (t% MOD FNSpeed(0))=0 THEN c%=0:PROCplayer:IF (t% MOD ((5+s%?11)*FNSpeed(0)))=0 THEN s%?12=s%?12-1:IF s%?12<2 THEN PROCkill(0,"Hunger") 61 IF (t% MOD (20-s%?11))=0 AND o%?6CLASS_MONSTER% THEN c%=254 ELSE IF o%?(c%*7+4) AND 192 AND (t% MOD FNSpeed(c%))=0 THEN PROCmonster 64 NEXT c% 65 UNTIL 0 66 DEF PROCnew:REM start new game 67 PROCtopl("Initialising") 68 PROCFA(d%,13,0):PROCFA(b%,5,0):PROCFA(o%,7*53,255) 69 t%=0:z%=0:zm%=0 70 !s%=0:s%!4=0:s%?8=0:s%?9=RND(2):s%?10=RND(2):s%?11=RND(2):s%?12=100:s%?13=0 71 PROCWA(d%,6):PROCWA(d%,13):PROCWA(b%,5):PROCWA(s%,14) 72 _c%=TYPE_PLAYER%:o%?0=_c%:o%?1=RND(38):o%?2=RND(20):_2%=0:_3%=1:PROCmspawn 73 PROCWA(o%,7*53) 74 H%=PTR#F% 75 PROCgenlevel 76 ENDPROC 77 DEF PROCcont:REM continue game 78 PROCtopl("Restoring game") 79 PROCRA(d%,4):t%=d%!0:z%=BGET#F%:zm%=BGET#F% 80 PROCRA(d%,13):PROCRA(b%,5):PROCRA(s%,14) 81 PROCRA(o%,7*53) 82 H%=PTR#F% 83 PROCrestore 84 ENDPROC 85 DEF PROCrestore:REM restore current level from savefile 86 PROCtopl("Loading") 87 PTR#F%=H%+1854*z% 88 FOR _%=0 TO 878 STEP 2 89 _2%=BGET#F% 90 m%?_%=_2% AND 15 91 m%?(_%+1)=_2% DIV 16 92 NEXT _% 93 PROCRA(o%+7*53,7*202) 94 PROCcinc(o%?1,o%?2) 95 FOR _%=53 TO 254 96 IF o%?(_%*7)<255 AND o%?(_%*7+1)<40 THEN PROCcinc(o%?(_%*7+1),o%?(_%*7+2)) 97 NEXT _% 98 PROCaredraw(0) 99 ENDPROC 100 DEF PROCsave:REM save current player state, level to savefile 101 PROCtopl("Saving") 102 PTR#F%=0 103 REM Remnants of PROCWW here 104 _%=t%:FOR _2%=0TO3:BPUT#F%,_%:_%=_%DIV256:NEXT _2% 105 BPUT#F%,z%:BPUT#F%,zm%:PROCWA(d%,13):PROCWA(b%,5):PROCWA(s%,14):PROCWA(o%,7*53) 106 PTR#F%=H%+1854*z% 107 _2%=0:_3%=0 108 FOR _%=0 TO 878 STEP 2 109 BPUT#F%,(m%?_% AND 15)+m%?(_%+1)*16 110 NEXT _% 111 PROCWA(o%+7*53,7*202) 112 ENDPROC 113 DEF PROCWA(_%,_2%):REM write array 114 _2%=_2%+_%:REPEAT:BPUT#F%,?_%:_%=_%+1:UNTIL _%=_2%:ENDPROC 115 DEF PROCRA(_%,_2%):REM read array 116 _2%=_2%+_%:REPEAT:?_%=BGET#F%:_%=_%+1:UNTIL _%=_2%:ENDPROC 117 DEF PROCFA(_%,_2%,_3%):REM Fill array 118 _2%=_2%+_%:REPEAT:?_%=_3%:_%=_%+1:UNTIL _%=_2%:ENDPROC 119 DEF FNCoO(_%):REM class of object 120 IF _%=255 OR o%?(_%*7)=255 THEN =255 ELSE =FNPoT(o%?(_%*7),0) 121 DEF FNPoT(_%,_2%):REM property of type 122 =_2%?(T%+T%?(_%*2)+((T%?(_%*2+1))*256)) 123 DEF FNSpeed(_%):REM Speed of monster 124 _2%=o%?(_%*7+4) AND 63:_2%=INT(FNPoT(o%?(_%*7),18)+((_2%*(FNPoT(o%?(_%*7),23)-128))/8)) 125 IF _2%<1 THEN =1 ELSE =_2% 126 DEF FNmonprop(_%,_2%):REM property #_2% of monster _% (not speed!) 127 =FNPoT(o%?(_%*7),_2%+14)+INT((o%?(_%*7+4) AND 63)*(FNPoT(o%?(_%*7),_2%+19)-128)/8)+(_%=0 AND _2%=1 AND s%?8) 128 DEF FNmax(_a%,_b%) 129 IF _a%>_b% THEN =_a% ELSE =_b% 130 DEF FNmin(_a%,_b%) 131 IF _a%<_b% THEN =_a% ELSE =_b% 132 DEF PROCgenlevel:REM generate new level 133 PROCtopl("Building level") 134 zm%=z% 135 _%=o%+7*53:_2%=1:REM room list start, numrooms 136 _3% = o%+7*255-3:_4%=0:REM edge list start, numedges 137 _%?0=0:_%?1=0:_%?2=38:_%?3=20:_%?4=0 : REM first room 138 _5%=0 : REM current room ID 139 REPEAT:REM try split 140 _6%=_%?(_5%*5+2)-_%?(_5%*5):_7%=_%?(_5%*5+3)-_%?(_5%*5+1) 141 IF z%=30THEN _5%=1ELSE IF _6%>_7% THEN PROCsplit(_6%,_7%,0) ELSE PROCsplit(_7%,_6%,1) 142 UNTIL _5%>=_2% 143 REM Render 144 FOR _5%=0 TO 879:m%?_5%=TILE_FLOOR%:NEXT _5% 145 _5%=(z%>0)AND1 146 IF z%<30THEN PROCwall(0,0,1,39,_5%):PROCwall(0,0,40,21,_5%):PROCwall(0,21,1,39,_5%):PROCwall(39,0,40,21,_5%) 147 FOR _5%=0 TO _4%-1 148 _6%=_%+_3%?(-_5%*3)*5:_7%=_%+_3%?(-_5%*3+1)*5:_8%=_3%?(-_5%*3+2) 149 IF _4%=0THEN ELSE IF _8% AND 128 THEN _c%=FNmax(_6%?0,_7%?0):PROCwall(_c%,_7%?1,1,FNmin(_6%?2,_7%?2)-_c%,_8% AND 127) ELSE _c%=FNmax(_6%?1,_7%?1):PROCwall(_7%?0,_c%,40,FNmin(_6%?3,_7%?3)-_c%,_8%) 150 NEXT _5% 151 FOR _5%=1 TO 9 152 IF FNmovedir(MID$(".hjklyubn",_5%,1)) AND m%?(o%?1+x%+40*(o%?2+y%))=TILE_FLOOR% THEN _5%=9 153 NEXT _5% 154 o%?1=o%?1+x%:o%?2=o%?2+y%:m%?(o%?1+40*o%?2)=TILE_DOWNSTAIRS%+64 155 _5%=RND(_2%)-1 156 IF z%<30 THEN REPEAT:_x%=_%?(_5%*5)+RND(_%?(_5%*5+2)-_%?(_5%*5)):_y%=_%?(_5%*5+1)+RND(_%?(_5%*5+3)-_%?(_5%*5+1)):UNTIL m%?(_x%+40*_y%)<>TILE_DOWNSTAIRS%+64:m%?(_x%+40*_y%)=TILE_UPSTAIRS2% 157 PROCFA(o%+7*53,7*202,255) 158 REM monsters, items 159 _2%=53:_3%=254 160 _5%=0:FOR _%=0 TO NUM_TYPES%-1:IF FNPoT(_%,11)<=z%ANDFNPoT(_%,12)>=z%THEN _5%=_5%+FNPoT(_%,10) 161 NEXT _% 162 FOR _%=0 TO 30+z% 163 _x%=RND(38):_y%=RND(20):_6%=RND(_5%)-1 164 _c%=-1 165 REPEAT 166 _c%=_c%+1 167 IF FNPoT(_c%,11)<=z%ANDFNPoT(_c%,12)>=z%THEN _6%=_6%-FNPoT(_c%,10) 168 UNTIL _6%<0 169 IF z%=30AND_%=0THEN _c%=TYPE_NUTDEVICE% 170 IF FNPoT(_c%,0)=CLASS_MONSTER% THEN _4%=_2% ELSE _4%=_3% 171 IF M%?((m%?(_x%+_y%*40) AND 31)*3+2) AND 1 THEN o%?(_4%*7)=_c%:o%?(_4%*7+1)=_x%:o%?(_4%*7+2)=_y%:o%?(_4%*7+3)=0:PROCcinc(_x%,_y%) 172 IF o%?(_2%*7)<255 THEN PROCmspawn:_2%=_2%+1 173 IF o%?(_3%*7)<255 THEN PROCispawn:_3%=_3%-1 174 IF _3%-_2%<9 THEN _%=99 175 NEXT _% 176 FOR _%=_3%+1TO254:PROCswap(_2%,_%):IF o%?(_2%*7+1)>40ANDFNCoO(_2%)=CLASS_WEAPON%THEN o%?(o%?(_2%*7+2)*7+5)=_2%ELSE _w%=o%?(o%?(_2%*7+2)*7+5):IF o%?(_2%*7+1)>40ANDFNCoO(_2%)=CLASS_AMMO%AND_w%<255ANDFNPoT(o%?(_w%*7),13)=FNPoT(o%?(_2%*7),9)THEN o%?(_w%*7+5)=_2%:o%?(_2%*7+3)=4 177 _2%=_2%+1:NEXT _% 178 p%=0:PROCsave:PROCaredraw(0) 179 ENDPROC 180 DEF PROCwall(_x%,_y%,_s%,_l%,_t%):REM plot wall 181 _x%=m%+_x%+40*_y% 182 FOR _p%=0 TO _l%*_s% STEP _s% 183 IF (_t% AND 1)=1 AND (_p%+1) MOD 3=0 THEN _x%?_p%=TILE_WINDOW% ELSE _x%?_p%=TILE_WALL2% 184 NEXT _p% 185 IF _t% AND 2 THEN _p%=INT(_l%DIV2)*_s%:_x%?_p%=TILE_DOOR% 186 ENDPROC 187 DEF PROCsplit(_6%,_7%,_h%):REM split current room w or h 188 IF _6%<=6 OR _7%<=3 THEN _5%=_5%+1 : ENDPROC 189 _7%=RND(_6%-(3+_h%))+2 190 IF _7%<3 OR _6%-_7%<3 THEN _5%=_5%+1 : ENDPROC 191 _%?(_2%*5)=(1-_h%)*_7%+_%?(_5%*5):_%?(_2%*5+1)=_h%*_7%+_%?(_5%*5+1):_%?(_2%*5+2)=_%?(_5%*5+2):_%?(_2%*5+3)=_%?(_5%*5+3):_%?(_2%*5+4)=0:_%?(_5%*5+2+_h%)=_%?(_2%*5+_h%)-1:_2%=_2%+1 192 _a%=_5%:_b%=_2%-1:REM ...fall through into inlined addedges 193 REM add edges between _a% and _b% 194 _n%=_4%:_3%?(-_n%*3)=_a%:_3%?(-_n%*3+1)=_b%:_3%?(-_n%*3+2)=_h%*128+2:_n%=_n%+1 195 IF _n%=1 THEN _3%?2=_h%*128+2 : _4%=1 : ENDPROC 196 FOR _c%=0 TO _4%-1 197 REM check far edge 198 IF _3%?(-_c%*3)=_a% AND (_3%?(-_c%*3+2) AND 128)=_h%*128 THEN _3%?(-_c%*3)=_b% 199 REM check edges: right/down followed by left/up 200 FOR _e%=0 TO 1 201 _o%=_3%?(-_c%*3+1-_e%) 202 IF _3%?(-_c%*3+_e%)=_a% AND _%?(_o%*5+_h%)>=_%?(_b%*5+_h%) THEN _3%?(-_c%*3+_e%)=_b% 203 IF _3%?(-_c%*3+_e%)=_a% AND _%?(_o%*5+2+_h%)>=_%?(_b%*5+_h%) THEN _3%?(-_n%*3+_e%)=_b% : _3%?(-_n%*3+1-_e%)=_o% : _3%?(-_n%*3+2)=(1-_h%)*128 : _n%=_n%+1 204 NEXT _e% 205 NEXT _c% 206 IF _n%-_4%>1 THEN _a%=RND(_n%-_4%)+_4%-1:_3%?(-_a%*3+2)=(_3%?(-_a%*3+2) AND 128)+2 207 _4%=_n% 208 ENDPROC 209 DEF PROCmspawn:REM fill in _2%'s details 210 _d=(z%-FNPoT(_c%,11))*(FNPoT(_c%,13)-1)/(FNPoT(_c%,12)-FNPoT(_c%,11)) 211 o%?(_2%*7+4)=_d:_d=_d-o%?(_2%*7+4) 212 o%?(_2%*7+4)=o%?(_2%*7+4)+1+((RND(1)<_d)AND1) 213 o%?(_2%*7+5)=255:o%?(_2%*7+6)=FNmonprop(_2%,0) 214 REM items 215 IF FNPoT(_c%,28)=255 THEN ENDPROC 216 _6%=28 217 REPEAT 218 IF RND(99)<(FNPoT(_c%,_6%+1)-128)+(FNPoT(_c%,_6%+2)-128)*(o%?(_2%*7+4)-1) THEN o%?(_3%*7)=FNPoT(_c%,_6%):o%?(_3%*7+1)=255:o%?(_3%*7+2)=_2%:o%?(_3%*7+3)=0:PROCispawn:_3%=_3%-SGN(_3%-53) 219 _6%=_6%+3 220 UNTIL FNPoT(_c%,_6%)=255 221 ENDPROC 222 DEF PROCispawn:REM fill in _3%'s details 223 _t%=FNPoT(o%?(_3%*7),0): REM Yessir, these variable names make sense... 224 IF _t%=CLASS_MAGAZINE% THEN k%=RND(13) ELSE k%=0 225 o%?(_3%*7+4)=k%:IF _t%=CLASS_MAGAZINE% OR _t%=CLASS_BOOK% THEN k%=RND(3) ELSE IF _t%=CLASS_WEAPON% THEN k%=255 ELSE k%=0 226 o%?(_3%*7+5)=k%:IF _t%=CLASS_AMMO% OR o%?(_3%*7+2)=0 AND (_t%=CLASS_FOOD% OR _t%=CLASS_DRINK%) THEN k%=SQR(RND(500)) ELSE k%=1 227 o%?(_3%*7+6)=k% 228 ENDPROC 229 DEF FNvc(_x%,_y%):REM Return visible character at _x%,_y% 230 IF m%?(_x%+40*_y%)<64 THEN =FNvtc(_x%,_y%) 231 IF o%?1=_x% AND o%?2=_y% THEN =FNtc(?o%) 232 FOR _z%=53 TO 254 233 IF o%?(_z%*7)<255 AND o%?(_z%*7+1)=_x% AND o%?(_z%*7+2)=_y% THEN _z%=o%+(_z%*7) 234 NEXT _z% 235 IF _z%<256 THEN PROCkill(0,"Chaos theory") 236 IF FNPoT(_z%?-1,0)=CLASS_MONSTER% THEN _z%?3=_z%?3 OR 192 237 =FNtc(_z%?-1) 238 DEF FNvtc(_x%,_y%):REM Return visible tile character at _x%,_y% 239 _b%=m%?(_x%+_y%*40) AND 31:PROCk(M%?(_b%*3+2)) 240 IF _b%=TILE_OPENWINDOW% OR _b%=TILE_OPENDOOR% THEN =FNcheckneighbour(_x%,_y%,45) 241 IF _b%=TILE_WINDOW% OR _b%=TILE_DOOR% THEN =FNcheckneighbour(_x%,_y%,124) 242 =M%?(_b%*3+1) 243 DEF FNnvc(_b%):REM Return non-visible character for _b% 244 _b%=_b%AND31:IF (M%?(_b%*3+2) AND 2)=2 AND _b%<>TILE_DOWNSTAIRS% AND _b%<>TILE_UPSTAIRS% THEN =32 245 _b%=M%?(_b%*3+1) 246 IF _b%<32 THEN =32 ELSE PROCk(0):=_b% 247 DEF FNcheckneighbour(_x%,_y%,_z%):REM Calculate what type of door/window we need 248 IF _x%=0 OR _x%=39 THEN =_z% 249 _x%=m%?(_x%+1+_y%*40) AND 31 250 IF _x%=TILE_WALL% OR _x%=TILE_WALL2% THEN =_z% EOR 81 ELSE =_z% 251 DEF FNtc(_t%):REM Return type character for _t% 252 PROCk(FNPoT(_t%,8)):IF FNPoT(_t%,0)=CLASS_MONSTER% THEN =FNPoT(_t%,24) ELSE =C%?(FNPoT(_t%,0)*2) 253 DEF PROCmonster:REM Move monster 254 x%=o%?1-o%?(c%*7+1):y%=o%?2-o%?(c%*7+2) 255 IF (o%?(c%*7+4) AND 64)=0 THEN x%=-x%:y%=-y% ELSE IF ABS(x%)<2 AND ABS(y%)<2 THEN PROCfight(0):ENDPROC 256 IF (ABS(x%)=ABS(y%) OR x%*y%=0) AND o%?(c%*7+5)<255 THEN _w%=o%?(c%*7+5):IF FNmax(ABS(x%),ABS(y%))<=FNPoT(o%?(_w%*7),14) AND o%?(_w%*7+5)<255 THEN x%=SGN(x%):y%=SGN(y%):PROCfire:ENDPROC 257 IF o%?(c%*7+4) AND 128 THEN x%=SGN(x%):y%=SGN(y%) ELSE x%=RND(3)-2:y%=RND(3)-2:_%=FNmove:ENDPROC 258 IF FNmove THEN ENDPROC ELSE IF RND(2)=1 THEN x%=0 ELSE y%=0 259 IF FNmove THEN ENDPROC ELSE x%=RND(3)-2:y%=RND(3)-2:_%=FNmove:ENDPROC 260 DEF PROCtopl(m$):REM topl message 261 PROCk(0):IF m$="" THEN p%=0 262 IF LEN(m$)>37 THEN PRINT TAB(p%,0);m$;" >>";:PROCeol:p%=GET:PROCaredraw(VPOS):ENDPROC 263 IF p%+LEN(m$)>37 THEN PRINT TAB(p%,0);">>";:p%=GET:p%=0 264 PRINT TAB(p%,0);m$;:IF p%=0 THEN PROCeol 265 p%=p%+LEN(m$)+SGN(LEN(m$)) 266 ENDPROC 267 DEF PROCtopl0(m$):REM topl if player 268 IF c%=0 THEN PROCtopl(m$) 269 ENDPROC 270 DEF FNmovedir(k$):REM parse yuhj.klbn direction into x%,y%. Takes rightmost char from input! 271 x%=INSTR("yhbk.juln",RIGHT$(k$,1))-1:IF x%<0 THEN =0 ELSE y%=(x% MOD 3)-1:x%=(x% DIV 3)-1:=1 272 DEF PROCmoveorfight:REM mon/player move-or-fight in x%,y% 273 _%=FNmonat(o%?(c%*7+1)+x%,o%?(c%*7+2)+y%) 274 IF _%<255 AND _%<>c% THEN PROCfight(_%) ELSE _%=FNmove 275 ENDPROC 276 DEF FNqc(_b%):REM Return quick count string 277 _b%=_b%DIV64 278 IF _b%=1 THEN ="1 item." ELSE IF _b%=3 THEN ="3+ items." ELSE =STR$(_b%)+" items." 279 DEF FNmove:REM mon/player move in x%,y%, 1 on success 280 IF FNtarginlevel=0 THEN PROCkill(c%,"Falling"):=1 ELSE _b%=FNmonat(x%+_x%,y%+_y%):IF _b%=c% THEN k%=1:=1 ELSE IF _b%<255 THEN PROCtopl0("Blocked"):k$="":=0 ELSE _b%=m%?(x%+_x%+(y%+_y%)*40):IF (M%?((_b% AND 31)*3+2) AND 1)=0 THEN PROCtopl0("Blocked"):k$="":=0 281 IF c%=0 AND _b% AND 192 THEN PROCtopl(FNqc(_b%)) 282 o%?(c%*7+1)=x%+_x%:o%?(c%*7+2)=y%+_y%:PROCcdec(_x%,_y%):PROCcinc(x%+_x%,y%+_y%):PROCfredraw(_x%,_y%):PROCoredraw(c%):k%=1 283 =1 284 DEF PROChear(_%):REM highlight object location if unseen 285 IF _%=0 OR (m%?(o%?(_%*7+1)+40*o%?(_%*7+2)) AND 32) THEN ENDPROC ELSE PROCk(0):PRINT TAB(o%?(_%*7+1),o%?(_%*7+2)+1);"I";:ENDPROC 286 DEF FNhitmiss(_t%,_d):REM Return 0 if we hit the target, 1 if we missed; _d is dx offset; prints messages for hit/miss 287 _t%=FNmonprop(c%,3)-FNmonprop(_t%,3):IF _t%>0 THEN _d=(_t%+2)/(_t%+3)+_d ELSE IF _t%<0 THEN _d=-3/(_t%-3)+_d ELSE _d=0.75+_d 288 IF RND(1)<_d ELSE IF c%=0 THEN PROCtopl("You miss."):=1 ELSE PROCtopl(FNname(c%)+" misses"):=1 289 IF c%=0 THEN PROCtopl("You hit!") ELSE PROCtopl(FNname(c%)+" hits!") 290 =0 291 DEF PROCfight(_t%):REM fight _t%. Assumes in range, etc.! 292 k%=1:PROChear(_t%):PROChear(c%) 293 IF FNhitmiss(_t%,0) THEN ENDPROC 294 _w%=o%?(c%*7+5) 295 IF _w%<255 THEN _d=FNsci(o%?(_w%*7),4)*FNmin(FNcount(_w%),2):_w%=o%?(_w%*7) ELSE _d=1 296 _d=_d*SQR(FNmonprop(c%,2)*FIGHT_COEF/_d) 297 IF _w%<255 THEN _d=_d*FNPoT(_w%,6)*SGN(FNPoT(_w%,7)) 298 PROChurt(_t%,_d,_w%,FNname(c%)) 299 ENDPROC 300 DEF FNsci(_%,_2%):REM return scientific notation number _2% for type _% 301 _%=T%+T%?(_%*2)+((T%?(_%*2+1))*256)+_2% 302 =?_%*10^(_%?1-128) 303 DEF FNmonat(_x%,_y%):REM return monster at location 304 IF m%?(_x%+40*_y%)<64 THEN =255 ELSE IF o%?1=_x% AND o%?2=_y% THEN =0 305 FOR _%=53 TO 254 306 IF FNCoO(_%)<>CLASS_MONSTER% THEN _%=510 ELSE IF o%?(_%*7+1)=_x% AND o%?(_%*7+2)=_y% THEN _%=_%+255 307 NEXT _% 308 IF _%=255 THEN =255 ELSE =_%-256 309 DEF PROCkill(_%,r$):REM kill monster/player/object 310 IF _%=0 THEN PROCgameover(r$) ELSE _x%=o%?(_%*7+1):_y%=o%?(_%*7+2):_e%=o%?(_%*7+5) 311 IF FNCoO(_%)=CLASS_WEAPON% AND _e%<255 THEN o%?(_e%*7+3)=o%?(_e%*7+3)AND251:PROCkill(_e%,"") ELSE IF FNCoO(_%)=CLASS_AMMO% AND o%?(_%*7+3) AND 4 THEN PROCaunload(_%) 312 IF FNCoO(_%)<>CLASS_MONSTER% THEN o%?(_%*7)=255:PROCcdec(_x%,_y%):PROCfredraw(_x%,_y%):ENDPROC 313 IF c%=0 THEN s%!4=s%!4+1:PROCxp(FNmonprop(_%,0)*(o%?(_%*7+4) AND 63)) 314 IF m%?(_x%+_y%*40) AND 32 THEN PROCtopl(FNname(_%)+" dies!") 315 _e%=53 316 FOR _c%=53 TO 254 317 IF o%?(_c%*7)<255 AND o%?(_c%*7+1)=255 AND o%?(_c%*7+2)=_% THEN o%?(_c%*7+1)=_x%:o%?(_c%*7+2)=_y%:PROCcinc(_x%,_y%):_6%=o%+(_c%*7+5):IF FNCoO(_c%)=CLASS_WEAPON% AND ?_6%<255 THEN o%?(?_6%*7+3)=o%?(?_6%*7+3)AND251:?_6%=255 318 IF FNCoO(_c%)=CLASS_MONSTER% THEN _e%=_c% ELSE IF o%?(_c%*7)<255 AND o%?(_c%*7+1)=255 AND o%?(_c%*7+2)=_e% THEN o%?(_c%*7+2)=_% 319 NEXT _c% 320 IF RND(2)=1 THEN o%?(_%*7+5)=o%?(_%*7):o%?(_%*7)=TYPE_CORPSE%:o%?(_%*7+3)=0:o%?(_%*7+4)=0:o%?(_%*7+6)=1 ELSE o%?(_%*7)=255:PROCcdec(_x%,_y%) 321 PROCswap(_%,_e%):PROCfredraw(_x%,_y%) 322 ENDPROC 323 DEF PROCgameover(r$):REM game over for the player... 324 REM Show reason 325 PROCtopl(r$+" kills you! >>"):k%=GET 326 REM Prepare score info. First, BBC compatible TIME$ hack... 327 T$="1":ON ERROR T$="" 328 IF T$="1" THEN T$=" ("+TIME$+")" 329 REM Destroy savefile 330 ON ERROR OFF:CLOSE#F%:OSCLI(D$+N$) 331 PROCtopl("Saving") 332 _d=0:FOR c%=1 TO 52:_%=o%?(c%*7):IF _%<255 THEN _d=_d+FNsci(_%,2)*FNcount(c%):IF FNCoO(c%)=CLASS_MAGAZINE% OR FNCoO(c%)=CLASS_BOOK% THEN _d=_d+o%?(c%*7+5)^2*FNsci(_%,2)*FNcount(c%) 333 NEXT c% 334 F%=OPENUP("logfile"):IF F%=0 THEN F%=OPENOUT("logfile") ELSE PTR#F%=EXT#F% 335 S$=r$+" killed "+N$+" (Xp"+STR$(o%?4)+"/"+STR$(s%!0)+" HP"+STR$(o%?6)+"/"+STR$(FNmonprop(0,0))+" St"+STR$(FNmonprop(0,2))+" Dx"+STR$(FNmonprop(0,3))+" In"+STR$(s%?9)+" Wi"+STR$(s%?10)+" Co"+STR$(s%?11)+") on turn "+STR$(t%)+" on level "+STR$(z%)+"/"+STR$(zm%)+". But he got "+STR$(s%!4) 336 @%=&102020A:S$=S$+" kills and looted "+M$+STR$(_d)+"!"+T$:@%=&90A 337 FOR c%=1 TO LEN(S$):BPUT#F%,ASC(MID$(S$,c%,1)):NEXT c%:BPUT#F%,10:CLOSE#F% 338 PRINT TAB(0,0);S$'"(press a key)";:PROCeol 339 c%=GET:PROCFA(d%,13,255):PROCFA(b%,5,255):o%?6=0:PROCdesc(255,0):PRINT 340 END 341 DEF PROCaunload(_%):REM Unload this ammo from a weapon 342 FOR _e%=0TO254 343 IF FNCoO(_e%)=CLASS_WEAPON% AND o%?(_e%*7+5)=_% THEN o%?(_e%*7+5)=255:o%?(_%*7+3)=o%?(_%*7+3) AND 251:_e%=255 344 NEXT _e% 345 IF _e%=255 THEN PROCkill(0,"Schrodinger's cat") ELSE ENDPROC 346 DEF PROCfredraw(_x%,_y%):REM force redraw if visible 347 IF _x%>39 THEN ENDPROC 348 _b%=m%?(_x%+40*_y%) 349 IF _b% AND 32 THEN PRINT TAB(_x%,_y%+1);CHR$(FNvc(_x%,_y%)); 350 ENDPROC 351 DEF PROCoredraw(_%):REM redraw object if visible 352 _%=o%+7*_% 353 IF ?_%<255 AND m%?(_%?1+40*_%?2) AND 32 THEN PRINT TAB(_%?1,_%?2+1);CHR$(FNtc(?_%)); 354 ENDPROC 355 DEF PROCaredraw(_%):REM Redraw top _% lines/all (if player alive!) 356 IF o%?6=0 THEN ENDPROC 357 IF _%=0 THEN CLS:_%=21ELSE PRINT TAB(0,0);SPC(40);:IF _%>21THEN _%=21 358 _7%=m% 359 FOR _y%=0 TO _% 360 PRINT TAB(0,_y%+1); 361 FOR _x%=0 TO 39 362 p%=?_7% 363 IF p% AND 32 THEN PRINT CHR$(FNvc(_x%,_y%)); ELSE PRINT CHR$(FNnvc(p%)); 364 _7%=_7%+1 365 NEXT _x% 366 NEXT _y% 367 p%=0:IF _%=21THEN PROCstatbar 368 ENDPROC 369 DEF FNtarginlevel:REM =1 if x%,y% offset in level.Also sets _x%,_y% to c% coords 370 _x%=o%?(c%*7+1):_y%=o%?(c%*7+2):IF _x%+x%<0 OR _x%+x%>39 OR _y%+y%<0 OR _y%+y%>21 THEN =0 ELSE =1 371 DEF PROCopen:REM open door 372 _b%=m%?(x%+_x%+(y%+_y%)*40) 373 IF (M%?((_b% AND 31)*3+2) AND 4)=0 THEN PROCtopl0("Can't open that"):k$="" ELSE m%?(x%+_x%+(y%+_y%)*40)=_b%+1:k%=1:PROCfredraw(x%+_x%,y%+_y%) 374 ENDPROC 375 DEF PROCclose:REM close door 376 _b%=m%?(x%+_x%+(y%+_y%)*40) 377 IF (M%?((_b% AND 31)*3+2) AND 8)=0 OR (_b% AND 192) THEN PROCtopl0("Can't close that"):k$="" ELSE m%?(x%+_x%+(y%+_y%)*40)=_b%-1:k%=1:PROCfredraw(x%+_x%,y%+_y%) 378 ENDPROC 379 DEF PROCvis:REM Update vis 380 REM First, flush old vis 381 _c%=m%+v%?0+v%?1*40 382 FOR y%=v%?1 TO v%?3 383 PRINT TAB(v%?0,y%+1); 384 FOR x%=v%?0 TO v%?2 385 _b%=?_c% 386 PRINT CHR$(FNnvc(_b%)); 387 ?_c%=_b% AND 223 388 _c%=_c%+1 389 NEXT x% 390 _c%=_c%+39-v%?2+v%?0 391 NEXT y% 392 REM We scan out from the player until we hit walls, doors, or windows 393 x%=o%?1+1:y%=o%?2+1:_x%=x%-2:_y%=y%-2 394 REPEAT:x%=x%-1:UNTIL FNnovis(x%,o%?2) 395 REPEAT:y%=y%-1:UNTIL FNnovis(o%?1,y%) 396 REPEAT:_x%=_x%+1:UNTIL FNnovis(_x%,o%?2) 397 REPEAT:_y%=_y%+1:UNTIL FNnovis(o%?1,_y%) 398 v%?0=x%:v%?1=y%:v%?2=_x%:v%?3=_y% 399 _7%=m%+x%+40*y% 400 FOR _c%=y% TO _y% 401 PRINT TAB(x%,_c%+1); 402 FOR _a%=x% TO _x% 403 _b%=?_7% OR 32 404 IF (_b% AND 31)>=TILE_UPSTAIRS2% THEN _b%=_b%-(TILE_UPSTAIRS2%-TILE_UPSTAIRS%) 405 ?_7%=_b% 406 PRINT CHR$(FNvc(_a%,_c%)); 407 _7%=_7%+1 408 NEXT _a% 409 _7%=_7%+39-_x%+x% 410 NEXT _c% 411 ENDPROC 412 DEF FNnovis(_x%,_y%):REM return true if we can't see through this 413 IF _x%<=0 OR _y%<=0 OR _x%>=39 OR _y%>=21 THEN =1 ELSE _b%=(m%?(_x%+40*_y%)) AND 31:IF _b%>=TILE_WALL% AND _b%<>TILE_UPSTAIRS2% THEN =1 ELSE =0 414 DEF PROCcinc(_x%,_y%):REM contents-increment at _x%,_y% 415 IF _x%<40THEN _x%=m%+_x%+40*_y%:_y%=?_x%+64:IF _y%<256 THEN ?_x%=_y% 416 ENDPROC 417 DEF PROCcdec(_x%,_y%):REM contents-decrement at _x%,_y% 418 IF _x%>39 THEN ENDPROC ELSE _b%=m%?(_x%+40*_y%)-64:IF _b%<0 THEN PROCkill(0,"Chaos theory") ELSE IF _b%<127 THEN m%?(_x%+40*_y%)=_b%:ENDPROC 419 _b%=_b% AND 63 420 IF o%?1=_x% AND o%?2=_y% THEN _b%=_b%+64 421 FOR _c%=53 TO 254 422 IF o%?(_c%*7)<255 AND o%?(_c%*7+1)=_x% AND o%?(_c%*7+2)=_y% THEN _b%=_b%+64 423 NEXT _c% 424 m%?(_x%+40*_y%)=_b% OR (192 AND _b%>255) 425 ENDPROC 426 DEF PROCup:REM move up one level 427 k%=1:PROCsave:z%=z%+1:IF z%>zm%THEN PROCgenlevel ELSE PROCrestore 428 ENDPROC 429 DEF PROCdown:REM move down one level 430 IF z%>0THEN k%=1:PROCsave:z%=z%-1:PROCrestore:ENDPROC 431 FOR _%=1TO52:IF(o%?_%*7)=TYPE_NUTDEVICE%THEN PROCtopl("You escape with the "+FNname(_%)+"!"):PROCtopl("You win! >>"):k%=GET:p%=0:PROCtopl("But..."):PROCkill(0,"Global thermonuclear war") 432 NEXT _% 433 PROCkill(0,"Cowardice") 434 DEF PROCdesc(_x%,_y%):REM describe everything at location, with inventory codes 435 IF _x%<40 AND (m%?(_x%+40*_y%) AND 32)=0 THEN PROCtopl("You can't see that far"):ENDPROC 436 _i%=0:_h%=0:p%=254:PRINT TAB(0,0); 437 IF _x%<40THEN PRINT FNstr(M%?((m%?(_x%+40*_y%) AND 31)*3));:PROCeol ELSE PRINT"Inside ";FNname(_y%);":";:PROCeol:IF _y%=0THEN p%=52 438 FOR _c%=0 TO p% 439 IF o%?(_c%*7)<255 AND o%?(_c%*7+1)=_x% AND o%?(_c%*7+2)=_y% THEN PRINT 'FNli(_c%);FNname(_c%);:PROCeol 440 NEXT _c% 441 PRINT '"(press a key)";:PROCeol:p%=GET:PROCaredraw(FNmax(VPOS,_h%)):k$="" 442 ENDPROC 443 DEF PROCeol:REM Print string that clears to end-of-line, but leaves cursor in place 444 _6%=40-POS:_7%=VPOS:PRINT SPC(_6%);TAB(40-_6%,_7%); 445 ENDPROC 446 DEF FNstr(_%):REM Expand string 447 LOCAL s$,e% 448 s$="":_%=S%+_%*2 449 e%=S%+_%?2+256*(_%?3) 450 _%=S%+?_%+256*(_%?1) 451 REPEAT 452 IF ?_%>127 THEN s$=s$+FNstr(?_%) ELSE s$=s$+CHR$(?_%) 453 _%=_%+1 454 UNTIL _%=e% 455 =s$ 456 DEF FNname(_o%):REM Return name of object 457 LOCAL _c% 458 IF _o%=0 THEN =FNstr(FNPoT(TYPE_PLAYER%,1))+" "+N$ 459 _t%=o%?(_o%*7):_c%=FNPoT(_t%,0) 460 IF _o%=o%?5 THEN s$=" (wielded)" ELSE IF _c%=CLASS_ARMOUR% AND o%?(_o%*7+3) AND 2 THEN s$=" (worn)" ELSE IF (_c%=CLASS_FOOD% OR _c%=CLASS_DRINK%) AND o%?(_o%*7+3) AND 2 THEN s$=" (hot)" ELSE s$="" 461 IF _c%=CLASS_MAGAZINE% THEN IF FNgb(b%,FNPoT(_t%,13)+o%?(_o%*7+4)) THEN s$=" #"+STR$(o%?(_o%*7+4))+FNcond(o%?(_o%*7+5)) ELSE IF o%?(_o%*7+5)=3 THEN s$=FNcond(3) 462 IF _c%=CLASS_BOOK% THEN IF FNgb(d%,_t%) THEN s$=FNcond(o%?(_o%*7+5)) ELSE IF o%?(_o%*7+5)=3 THEN s$=FNcond(3) 463 IF _t%=TYPE_CORPSE% THEN s$=" ("+FNtname(o%?(_o%*7+5))+")"+s$ 464 IF FNPoT(_t%,0)=CLASS_WEAPON% AND o%?(_o%*7+5)<255 THEN s$=s$+" (loaded)" ELSE IF FNPoT(_t%,0)=CLASS_AMMO% AND o%?(_o%*7+3) AND 4 THEN s$=s$+" (loaded)" 465 =FNtname(_t%)+FNstrcount(_o%)+s$ 466 DEF FNtname(_t%):REM Return name of type 467 IF FNgb(d%,_t%) THEN =FNstr(FNPoT(_t%,1)) ELSE =FNstr(FNPoT(_t%,9)) 468 DEF FNgb(_a%,_b%):REM Return bit _b% from array _a% 469 =_a%?(_b%DIV8) AND 2^(_b% AND 7) 470 DEF PROCsb(_a%,_b%):REM Set bit _b% from array _a% 471 _a%?(_b%DIV8)=_a%?(_b%DIV8) OR 2^(_b% AND 7) 472 ENDPROC 473 DEF FNcond(_c%):REM Return book/mag condition string 474 IF _c%=0 THEN =" (illegible)" ELSE IF _c%=1 THEN =" (worn)" ELSE IF _c%=2 THEN =" (pristine)" ELSE =" (shrink-wrapped)" 475 DEF FNcount(_o%):REM Return count number for object 476 LOCAL _c%,_n% 477 _n%=C%?(FNCoO(_o%)*2+1) 478 IF _n%=0THEN=1 479 _c%=0 480 _o%=o%+_o%*7 481 FOR _n%=7-_n% TO 6 482 _c%=_c%*256+_o%?_n% 483 NEXT _n% 484 =_c% 485 DEF PROCisplit(_s%,_d%,_n%):REM remove up to _n% count from _s%, adding to _d% (creating as needed, or discarding if _d%=255). Kills _s% if consumed. Negative _n% and _d%=255 will increase _s% count, but no overflow checks. Don't use for non-stackables. 486 LOCAL _c% 487 _c%=FNcount(_s%)-_n%:IF _c%<0 THEN _n%=-_c%:_c%=0:REM Don't underflow! 488 _7%=C%?(FNCoO(_s%)*2+1) 489 IF _d%=255 ELSE IF o%?(_d%*7)<255 THEN _n%=_n%+FNcount(_d%) ELSE FOR _6%=0 TO 6-_7%:o%?(_d%*7+_6%)=o%?(_s%*7+_6%):NEXT _6% 490 IF _d%=255 ELSE IF _n%>=2^(_7%*8) THEN _c%=_c%+_n%-2^(_7%*8)-1:_n%=2^(_7%*8)-1 491 IF _c%=0 THEN PROCkill(_s%,"") ELSE FOR _6%=6 TO 7-_7% STEP -1:o%?(_s%*7+_6%)=_c% MOD 256:_c%=_c% DIV 256:NEXT _6% 492 IF _d%<255 THEN FOR _6%=6 TO 7-_7% STEP -1:o%?(_d%*7+_6%)=_n% MOD 256:_n%=_n% DIV 256:NEXT _6% 493 ENDPROC 494 REM DEF FNissame(_a%,_b%):REM true if we can stack two/from these items 495 REM _a%=o%+_a%*7:_b%=o%+_b%*7 496 REM IF ?_a%<>?_b% THEN =0 497 REM _7%=C%?(FNPoT(?_a%,0)*2+1) 498 REM IF _7%=4THEN=1 499 REM IF _a%?3<>_b%?3 OR _a%?4<>_b%?4 THEN =0 500 REM IF _7%=2 OR _a%?5=_b%?5 THEN =1 ELSE =0 501 DEF FNstrcount(_o%):REM Return count as string 502 _o%=FNcount(_o%) 503 IF _o%<2 THEN ="" ELSE =" * "+STR$(_o%) 504 DEF FNli(_x%):REM Return inventory assignment if _x%<>0 505 IF _x%=0 THEN ="" 506 IF _x%<53 THEN _i%=_x% ELSE _i%=_i%+1 507 IF VPOS>22 THEN PRINT "(more)";:PROCeol:_x%=GET:_h%=21:CLS 508 IF _i%<27 THEN _i%=_i%+58 509 =CHR$(_i%+38)+":" 510 DEF PROCstatbar:REM draw status bar 511 PROCk(0):PRINT TAB(0,23);"Floor:";z%;" HP:";o%?6;"/";FNmonprop(0,0);" AC:";FNmonprop(0,1);" Xp:";(o%?4 AND 63);"/";s%!0;SPC(3) 512 PRINT TAB(0,24);"St:";FNmonprop(0,2);" Dx:";FNmonprop(0,3);" In:";s%?9;" Wi:";s%?10;" Co:";s%?11; 513 IF s%?12<20 THEN PRINT " Famished"; ELSE IF s%?12<50 THEN PRINT " Peckish "; ELSE IF s%?12>200 THEN PRINT " Tubby "; ELSE PRINT SPC(9); 514 ENDPROC 515 DEF PROCk(k%):REM change colour. 0=white, 64=green, 128=blue 516 IF K%=0 OR (K% EOR k%)<64 THEN ENDPROC 517 K%=k% OR 1 518 COLOUR I%?(k%DIV64) 519 ENDPROC 520 DEF PROCwhat:REM Identify tile/etc. 521 PROCtopl("Move the cursor, press . to identify") 522 _x%=o%?1:_y%=o%?2 523 REPEAT 524 PRINT TAB(_x%,_y%+1); 525 k$=GET$ 526 IF FNmovedir(k$)=0 THEN k%=1:PROCtopl("") ELSE IF x%=0 AND y%=0 THEN PROCdesc(_x%,_y%):k%=1 ELSE _x%=(_x%+x%+40) MOD 40:_y%=(_y%+y%+22) MOD 22 527 UNTIL k%=1 528 ENDPROC 529 DEF FNlind(_%):REM return list index for ASCII code _% or 0 530 IF _%>122 THEN =0 ELSE IF _%>96 THEN =_%-96 ELSE IF _%>90 THEN =0 ELSE IF _%>64 THEN =_%-38 ELSE =0 531 DEF PROCtake:REM player take cmd 532 _f%=0 533 FOR _c%=52 TO 1 STEP -1 534 IF o%?(_c%*7)=255 THEN _f%=_c% 535 NEXT _c% 536 IF _f%=0 THEN PROCkill(0,"Kleptomania") 537 IF ((m%?(o%?1+o%?2*40)) AND 192)=128 THEN _%=1 ELSE PROCinvcmd("Take"):IF _%=0 THEN ENDPROC 538 FOR _c%=53 TO 254 539 IF o%?(_c%*7)<255 AND o%?(_c%*7+1)=o%?1 AND o%?(_c%*7+2)=o%?2 THEN _%=_%-1 540 IF _%=0 THEN PROCswap(_f%,_c%):o%?(_f%*7+1)=255:o%?(_f%*7+2)=0:_c%=254:k%=1:PROCcdec(o%?1,o%?2):PROCtopl("Taken:"+FNli(_f%)+FNname(_f%)) 541 NEXT _c% 542 ENDPROC 543 DEF PROCdrop:REM player drop cmd 544 PROCinvcmd("Drop") 545 IF _%=0 OR o%?(_%*7)=255 THEN ENDPROC 546 _f%=0 547 FOR _c%=53 TO 254 548 IF o%?(_c%*7)=255 THEN _f%=_c%:_c%=254 549 NEXT _c% 550 IF _f%=0 THEN PROCkill(0,"Structural collapse") 551 IF _%=o%?5 THEN o%?5=255:PROCtopl("Now empty handed.") 552 _c%=FNCoO(_%) 553 IF _c%=CLASS_ARMOUR% AND o%?(_%*7+3) AND 2 THEN PROCremove(_%) ELSE IF _c%=CLASS_WEAPON% AND o%?(_%*7+5)<255 THEN PROCammo(_%) ELSE IF _c%=CLASS_AMMO% AND o%?(_%*7+3) AND 4 THEN PROCaunload(_%) 554 PROCswap(_f%,_%):o%?(_f%*7+1)=o%?1:o%?(_f%*7+2)=o%?2:k%=1:PROCcinc(o%?1,o%?2):PROCtopl("Dropped: "+FNname(_f%)) 555 ENDPROC 556 DEF PROCswap(_a%,_b%):REM raw swap of two objects 557 _a%=o%+_a%*7:_b%=o%+_b%*7 558 FOR _c%=0 TO 6 559 _d%=_a%?_c%:_a%?_c%=_b%?_c%:_b%?_c%=_d% 560 NEXT _c% 561 ENDPROC 562 DEF PROCtryfight:REM Player try and fight in x%,y% dir 563 k%=1:IF x%=0 AND y%=0 THEN PROCkill(0,"Angst") 564 _%=FNmonat(o%?1+x%,o%?2+y%):IF _%=255 AND o%?5<255 THEN _%=FNPoT(o%?(o%?5*7),7):IF _%>1 THEN x%=x%*_%:y%=y%*_%:_%=FNmonat(o%?1+x%,o%?2+y%) 565 IF _%<255 AND _%>0 THEN PROCfight(_%) ELSE PROCtopl("You flail your arms at nothingness.") 566 ENDPROC 567 DEF PROCremove(_%):REM Player armour remove. Must be armour! 568 o%?(_%*7+3)=o%?(_%*7+3)-2:s%?8=s%?8-FNPoT(o%?(_%*7),14):PROCtopl(FNname(_%)+" removed."):k%=1 569 ENDPROC 570 DEF PROCwear(_%):REM Try wearing _% 571 REM Check if we have any similar types worn 572 _f%=FNPoT(o%?(_%*7),13) 573 FOR _c%=1 TO 52 574 IF FNCoO(_c%)=CLASS_ARMOUR% AND o%?(_c%*7+3) AND 2 THEN IF (FNPoT(o%?(_c%*7),13) AND _f%)>1 THEN PROCtopl("Already wearing "+FNname(_c%)):_c%=55:k$="" 575 NEXT _c% 576 IF _c%<55 THEN PROCtopl("Worn: "+FNname(_%)):o%?(_%*7+3)=o%?(_%*7+3)+2:s%?8=s%?8+FNPoT(o%?(_%*7),14):k%=1 577 ENDPROC 578 DEF FNgs:REM No GET$# in BASIC II... 579 S$="" 580 REPEAT 581 C%=BGET#F% 582 S$=S$+CHR$(C%) 583 UNTIL C%<32 584 =LEFT$(S$,LEN(S$)-1) 585 DEF PROCxp(_%):REM award xp to player, advance levels 586 s%!0=s%!0+_% 587 IF XP_RATE^(o%?4+5)>s%!0 THEN ENDPROC ELSE o%?4=o%?4+1:o%?6=o%?6+(FNPoT(?o%,19)-128)/8:_%=RND(4):s%?(_%+7)=FNmin(s%?(_%+7)+1,255) 588 IF _%=2THEN k$="geeky!"ELSE IF _%=3THEN k$="nerdy!"ELSE k$="tough!" 589 PROCtopl("You feel more "+k$) 590 ENDPROC 591 DEF PROCammo(_%):REM Load/unload weapon _% 592 _a%=o%?(_%*7+5) 593 IF _a%<255 THEN o%?(_a%*7+3)=o%?(_a%*7+3) AND 251:o%?(_%*7+5)=255:PROCtopl("Unloaded: "+FNname(_a%)+" from "+FNname(_%)):k%=1:ENDPROC 594 p%=0:PROCtopl("Load what?"):k$=k$+GET$:_a%=FNlind(ASC(RIGHT$(k$,1))):IF o%?(_a%*7)=255OR_a%=0THEN ENDPROC ELSE IF FNCoO(_a%)<>CLASS_AMMO%ORFNPoT(o%?(_a%*7),9)<>FNPoT(o%?(_%*7),13)THEN PROCtopl("It won't fit"):k$="":ENDPROC ELSE _b%=o%?(_a%*7+3):IF _b%AND4THEN PROCtopl("Already in use!"):k$="":ENDPROC 595 PROCtopl("Loaded: "+FNname(_a%)):o%?(_a%*7+3)=_b% OR 4:o%?(_%*7+5)=_a%:k$="" 596 ENDPROC 597 DEF PROCfire:REM player/monster fire in x%,y% dir 598 k%=1:_w%=o%?(c%*7+5):_a%=o%?(_w%*7+5):_r%=FNPoT(o%?(_w%*7),14) 599 _t%=255:_7%=TIME 600 REPEAT 601 IF FNtarginlevel=0 THEN _t%=-1 ELSE _x%=_x%+x%:_y%=_y%+y%:PRINT TAB(_x%,_y%+1);CHR$(FNtc(o%?(_a%*7)));:_b%=m%?(_x%+_y%*40):IF M%?((_b% AND 31)*3+2) AND 1 THEN _t%=FNmonat(_x%,_y%) ELSE _r%=0:x%=x%-SGN(x%):y%=y%-SGN(y%) 602 REPEAT:UNTIL TIME-_7%>10:_7%=TIME 603 IF _b% AND 32 THEN PROCfredraw(_x%,_y%) ELSE PRINT TAB(_x%,_y%+1);CHR$(FNnvc(_b%)); 604 IF _t%<255 THEN _r%=0 ELSE _r%=_r%-1:IF _r%>0 THEN x%=x%+SGN(x%):y%=y%+SGN(y%) 605 UNTIL _r%<1 606 REM _t%=-1 means out-of-bounds 607 REM else _t% is target monster, and x%,y% target offset 608 _%=_a%:_a%=o%?(_a%*7) 609 PROCisplit(_%,255,1) : REM For now, always consume ammo 610 REM hurt target 611 IF _t%=-1 THEN ENDPROC ELSE IF _t%=255 THEN PROChurtwall(_x%,_y%,0):ENDPROC ELSE IF FNhitmiss(_t%,0.1) THEN ENDPROC 612 _w%=o%?(_w%*7) 613 _d=FNsci(_a%,4)*FNPoT(_w%,14)*FNPoT(_a%,6)*FIRE_COEF 614 PROChurt(_t%,_d,_a%,FNtname(_a%)+" fired by "+FNname(c%)) 615 ENDPROC 616 DEF PROChurtwall(_x%,_y%,_z%):REM Hurt level at _x%,_y%. If _z%=1, also hurt doors, else only windows 617 IF _x%<0 OR _x%>39 OR _y%<0 OR _y%>21 THEN ENDPROC 618 PRINT TAB(_x%,_y%+1); : REM Preperation... 619 _x%=m%+_x%+_y%*40:_y%=?_x% AND 31 620 IF _y%>=TILE_WINDOW% AND _y%<=TILE_OPENWINDOW% THEN _y%=TILE_BROKENWINDOW% ELSE IF _y%>=TILE_DOOR% AND _y%<=TILE_OPENDOOR% AND _z% THEN _y%=TILE_BROKENDOOR% 621 ?_x%=(?_x% AND 224)+_y% 622 IF (?_x% AND 224)=32 THEN PRINT CHR$(M%?(_y%*3+1)); 623 ENDPROC 624 DEF PROCboom(_w%,_d,_a%,_b%):REM Explosion at _a%,_b% from weapon _w% 625 LOCAL x%,y%,_5%,_4% 626 REM Check everywhere 627 FOR _5%=1 TO 9 628 _4%=FNmovedir(MID$(".hjklyubn",_5%,1)):_4%=FNmonat(_a%+x%,_b%+y%):IF _4%<255 THEN PROChurt(_4%,_d,255,FNname(c%)+"'s exploding "+FNtname(_w%)) 629 PROChurtwall(_a%+x%,_b%+y%,1):IF _5%=1THEN _d=SQR(_d) 630 NEXT _5% 631 PROChurtwall(_a%,_b%,1) 632 ENDPROC 633 DEF PROChurt(_t%,_d,_w%,m$):REM Apply _d pre-armour damage to _t% using _w%. death message m$. Applies cut/explo damage as appropriate. Uses _d%. 634 _d%=FNmonprop(_t%,1) 635 IF _w%<255 THEN IF FNPoT(_w%,8) AND 16 AND RND(1)>0.6 THEN PROCtopl("It cuts!"):_d%=_d%-5 636 IF _w%<255 THEN IF FNPoT(_w%,8) AND 1 THEN PROCtopl("It explodes!"):_d=_d^BOOM_COEF:PROCboom(_w%,_d,o%?(_t%*7+1),o%?(_t%*7+2)):PROCkill(_w%,""):ENDPROC 637 IF _d%>0 THEN _d=_d*FIGHT_A^(_d%^FIGHT_B) 638 _d%=INT(_d) 639 IF RND(1)<_d-_d% THEN _d%=_d%+1 ELSE IF _d%=0 THEN PROCtopl("Pathetic!") 640 _d%=o%?(_t%*7+6)-_d% 641 IF _d%<=0 THEN PROCkill(_t%,m$) ELSE o%?(_t%*7+6)=_d% 642 ENDPROC 643 DEF PROCeat(_%):REM player eat item... 644 IF o%?(_%*7)=TYPE_CORPSE% THEN _x%=5:_y%=26 ELSE _x%=0:_y%=13 645 s%?12=FNmin(s%?12+FNPoT(o%?(_%*7+_x%),_y%+(o%?(_%*7+3) AND 2)DIV2),255) 646 PROCtopl("Eaten: "+FNname(_%)):PROCisplit(_%,255,1):k%=1 647 ENDPROC 648 DEF PROCcook(_%):REM player cook item... 649 IF FNPoT(o%?(_%*7),8) AND 4 THEN PROCtopl("It explodes!"):PROCkill(_%,""):PROCboom(o%?5,100,o%?1,o%?2):PROCkill(o%?5,""):k%=1:ENDPROC 650 IF FNCoO(_%)<>CLASS_FOOD% AND FNCoO(_%)<>CLASS_DRINK% THEN PROCtopl("Interesting"):k%=1:ENDPROC 651 o%?(_%*7+3)=o%?(_%*7+3) OR 2:PROCtopl("Toasty!") 652 ENDPROC 653 DEF PROCread:REM Player read _%... 654 _c%=FNCoO(_%):_w%=0:FOR _2%=1 TO 52:IF o%?(_2%*7)=TYPE_READINGGLASSES%ANDo%?(_2%*7+3)AND2THEN _w%=1:_2%=52 655 NEXT _2% 656 k%=1:_2%=o%?(_%*7+5) 657 IF _w%=0 AND _2%<2 THEN PROCtopl("Too worn to read."):ENDPROC 658 IF _2%>0 THEN o%?(_%*7+5)=_2%-1 659 IF FNgb(b%,FNPoT(o%?(_%*7),13)+o%?(_%*7+4)) THEN PROCtopl("Already read."):ENDPROC 660 PROCsb(d%,o%?(_%*7)):PROCsb(b%,FNPoT(o%?(_%*7),13)+o%?(_%*7+4)) 661 PROCtopl("You feel smarter!"):IF _c%=CLASS_BOOK% THEN PROCxp(FNsci(o%?(_%*7),2)*FNcount(_%)*(_2%+1)*s%?9):ENDPROC 662 REM Else identify 663 _2%=_2%^s%?10 664 FOR _c%=1 TO 52:_w%=o%?(_c%*7):IF _w%<255ANDFNgb(d%,_w%)=0THEN PROCsb(d%,_w%):_2%=_2%-1:IF _2%=0THEN _c%=52 665 NEXT _c% 666 IF _2%<5 THEN ENDPROC 667 FOR _c%=1 TO _2% STEP 5:PROCsb(d%,RND(NUM_TYPES%)-1):NEXT _c% 668 ENDPROC 669 DEF PROCinvcmd(P$):REM Prompt player for inventory command, read the key, convert to item ID 670 PROCtopl(P$+" what?"):_%=GET:k$=k$+CHR$(_%):_%=FNlind(_%) 671 ENDPROC 672 DEF PROCplayer:REM Move player 673 REM first, vis 674 IF (m%?(o%?1+o%?2*40) AND 32)=0 THEN PROCvis 675 PROCstatbar:p%=0:k%=0 676 REM get input magics 677 REPEAT 678 PROCk(0):PRINT TAB(o%?1,o%?2+1);:k$=GET$ 679 IF FNmovedir(k$) THEN PROCmoveorfight ELSE _%=m%?(o%?1+o%?2*40):IF k$="<" AND (_% AND 31)=TILE_UPSTAIRS% THEN PROCup ELSE IF k$=">" AND (_% AND 31)=TILE_DOWNSTAIRS% THEN PROCdown ELSE IF k$="," AND _%>127 THEN PROCtake 680 IF k$="m" THEN k$=k$+GET$ : IF FNmovedir(k$) THEN _%=FNmove 681 IF k$="F" THEN k$=k$+GET$ : IF FNmovedir(k$) THEN PROCtryfight 682 IF k$="f" AND o%?5<255 AND o%?(o%?5*7+5)<255 THEN k$=k$+GET$ : IF FNmovedir(k$) AND k$<>"k." THEN PROCfire 683 IF k$="Q" THEN PROCkill(0,"Apathy") ELSE IF k$="S" THEN PROCsave : CLOSE#F% : CLS : PRINT "Game saved, ";N$ : END ELSE IF k$="i" THEN PROCdesc(255,0) ELSE IF k$="/" THEN PROCwhat ELSE IF k$="d" THEN PROCdrop 684 IF k$="o" THEN k$=k$+GET$ : IF FNmovedir(k$) AND FNtarginlevel THEN PROCopen 685 IF k$="c" THEN k$=k$+GET$ : IF FNmovedir(k$) AND FNtarginlevel THEN PROCclose 686 IF k$="H" AND o%?5<255 THEN o%?5=255:PROCtopl("Now empty handed."):k%=1 ELSE IF k$="w" AND o%?5=255 THEN PROCinvcmd("Wield"):IF _% AND o%?(_%*7)<255 THEN PROCtopl("Now wielding "+FNname(_%)):o%?5=_%:k%=1 687 IF k$="T" THEN PROCinvcmd("Remove"):IF FNCoO(_%)=CLASS_ARMOUR% AND o%?(_%*7+3) AND 2 THEN PROCremove(_%) 688 IF k$="W" THEN PROCinvcmd("Wear"):IF FNCoO(_%)=CLASS_ARMOUR% AND (o%?(_%*7+3) AND 2)=0 THEN PROCwear(_%) 689 IF k$="e" THEN PROCinvcmd("Eat"):IF FNCoO(_%)=CLASS_FOOD% THEN PROCeat(_%) 690 IF k$="q" THEN PROCinvcmd("Drink"):IF FNCoO(_%)=CLASS_DRINK% THEN s%?12=FNmin(s%?12+FNPoT(o%?(_%*7),13+(o%?(_%*7+3) AND 2)DIV2),255):PROCtopl("Drunk: "+FNname(_%)):PROCisplit(_%,255,1):k%=1 691 IF k$="L" AND o%?5<255 AND FNPoT(o%?(o%?5*7),14) THEN PROCammo(o%?5) ELSE IF k$="C" AND o%?5<255 AND o%?(o%?6*7)=TYPE_MICROWAVE% THEN PROCinvcmd("Cook"):IF _%>0 AND _%<>o%?5 THEN PROCcook(_%) 692 IF k$="r" THEN PROCinvcmd("Read"):IF FNCoO(_%)=CLASS_BOOK% OR FNCoO(_%)=CLASS_MAGAZINE% THEN PROCread 693 IF k$<>"" AND k%=0 THEN PROCtopl("Bad key '"+k$+"'") 694 UNTIL k% 695 IF p%=0 THEN PROCtopl("") 696 ENDPROC