program VampGirl; uses windows; {$include moonvid.pas} const max_synonyms = 800; max_mobs = 500; // 0..max_mobs, 0 is the player, can go up to 999 max_vars = 100; // 0..max_vars, can go up to 999 mobverbs = 24; // 0..mobverbs, so actually mobverbs+1 mob verbs exist verboz:array[0..255] of string[9]= ('LOOK','TAKE','OPEN','SMASH','SHOW','GIVE','CLOSE','CLIMB','WEAR','EAT', 'REMOVE','KNOCK','KICK','THROW','READ','PLAY','REST','ENTER','TOUCH','DRINK', 'DROP','HELP','TALK','HIT','MOVE','','','','','','','','','','', '','','','','','','','','','','', '','','','','','','','','','','','','','','','','','','','','','','','','', '','','','','','','','','','','','','','','','','','','','','','','','','', '','','','','','','','','','','','','','','','','','','','','','','','','', '','','','','','','','','','','','','','','','','','','','','','','','','', '','','','','','','','','','','','','','','','','','','','','','','','','', '','','','','','','','','','','','','','','','','','','','','','','','','', '','','','','','','','','','','','','','','','','','','','','','','','','', '','','','','','','','','','','', 'AMBIENCE','EXITS','LISTEN','NO','YES','GO','I','QUIT','LOAD','SAVE', 'ENTERED','LOOK','IN','OUT','SOUTHEAST','SOUTHWEST','NORTHEAST','NORTHWEST', 'EAST','WEST','SOUTH','NORTH','UP','DOWN'); var i,j:dword; filu:text; quit:boolean; com,lastcom:string; comchar:char; player:record room : word; inventory : word; score, maxscore : word; end; gamevar : array[0..max_vars] of word; synopoku : word; synonym:array[0..max_synonyms] of record mobling:word; woids:byte; nyymi:string[40]; end; script:array[0..100] of pointer; room:array[0..255] of record name:string[26]; visited:boolean; contains:word; look,listen,entered,exits,ambience, north,south,east,west, northwest,northeast,southwest,southeast, up,down,goout,goin:pointer; end; mob:array[0..max_mobs] of record // can go up to maximum of [0..9999] name:word; // points to primary synonym invisible,closed,worn:boolean; stacknext,contains,clone:word; script:array[0..mobverbs] of pointer; end; procedure releaseall; // The exit procedure - this tries to end the program gracefully. // This is automatically called upon any kind of program termination, // as long as the program starts with addExitProc(@ReleaseAll). begin // Error handling rests here if erroraddr <> NIL then case exitcode of 200: writeln('+++ Division by zero +++ don''t implode the universe +++'); 201: writeln('+++ Range check error +++'); 202: writeln('+++ Stack overflow error +++'); 204: writeln('+++ Null pointer dereferencing +++ is so much fun +++'); 215: writeln('+++ Arithmetic overflow error +++ but why? +++'); 216: writeln('+++ General protection fault +++ have a nice day :) +++'); else writeln('Crash! Runtime error ' + strdec(exitcode) + '!'); end; mv_Quit; for i := 0 to 255 do begin if room[i].look <> NIL then freep(@room[i].look); if room[i].listen <> NIL then freep(@room[i].listen); if room[i].entered<>nil then freep(@room[i].entered); if room[i].exits<>nil then freep(@room[i].exits); if room[i].ambience<>nil then freep(@room[i].ambience); if room[i].north<>nil then freep(@room[i].north); if room[i].south<>nil then freep(@room[i].south); if room[i].west<>nil then freep(@room[i].west); if room[i].east<>nil then freep(@room[i].east); if room[i].up<>nil then freep(@room[i].up); if room[i].down<>nil then freep(@room[i].down); if room[i].goin<>nil then freep(@room[i].goin); if room[i].goout<>nil then freep(@room[i].goout); if room[i].northwest<>nil then freep(@room[i].northwest); if room[i].southwest<>nil then freep(@room[i].southwest); if room[i].northeast<>nil then freep(@room[i].northeast); if room[i].southeast<>nil then freep(@room[i].southeast); end; for i := 0 to 100 do if script[i] <> NIL then freep(@script[i]); for i := 0 to max_mobs do if mob[i].clone = $FFFF then for j := 0 to mobverbs do if mob[i].script[j] <> NIL then freep(@mob[i].script[j]); end; procedure read_ini_file; var sturm : string; muuttuja : byte; begin {$I-} assign(filu, 'vampgirl.ini'); reset(filu); while (eof(filu) = FALSE) and (IOresult = 0) do begin readln(filu, sturm); if (sturm = '') or (sturm[1] = '#') then continue; if upcase(copy(sturm, 1, 4)) = 'MODE' then begin mv_OutputMode := valx(copy(sturm, 5, length(sturm) - 4)); if (mv_OutputMode <> 0) and (mv_OutputMode <> 1) then mv_OutputMode := 0; end; if upcase(copy(sturm, 1, 4)) = 'ROWS' then begin mv_OutputSizeRows := valx(copy(sturm, 5, length(sturm) - 4)); if mv_OutputSizeRows < 25 then mv_OutputSizeRows := 25; if mv_OutputSizeRows > 255 then mv_OutputSizeRows := 255; end; if upcase(copy(sturm, 1, 6)) = 'TILES ' then begin muuttuja := 7; while (muuttuja < length(sturm)) and (sturm[muuttuja] = ' ') do inc(muuttuja); mv_TileName := copy(sturm, muuttuja, length(sturm) - muuttuja + 1); end; if upcase(copy(sturm, 1, 9)) = 'TILESIZEX' then begin mv_TileSizeX := valx(copy(sturm, 10, length(sturm) - 9)); if mv_TileSizeX < 4 then mv_TileSizeX := 4; end; if upcase(copy(sturm, 1, 9)) = 'TILESIZEY' then begin mv_TileSizeY := valx(copy(sturm, 10, length(sturm) - 9)); if mv_TileSizeY < 4 then mv_TileSizeY := 4; end; end; close(filu); {$I+} end; procedure loadtxtscript(mihin : pointer; iduliini : word); // MIHIN must point to the pointer!! var bufu : pointer; stroke : string; sizzle, loix, munki, donitsi : dword; matriza : array[0..99] of dword; loikka : array[0..255] of dword; begin getmem(bufu, 32768); sizzle := 0; loix := 0; repeat readln(filu, stroke); // Jump label (colon followed by two decimal digits) if copy(stroke, 1, 1) = ':' then matriza[valx(copy(stroke, 2, 2))] := sizzle; // Print = 1 + len + string if stroke = 'print' then begin bytearray(bufu^)[sizzle] := 1; bytearray(bufu^)[sizzle + 1] := 0; inc(sizzle, 2); end; if copy(stroke,1,6)='print ' then begin bytearray(bufu^)[sizzle]:=1; bytearray(bufu^)[sizzle+1]:=length(stroke)-6; move(stroke[7],bytearray(bufu^)[sizzle+2],length(stroke)-6); inc(sizzle, length(stroke) - 4); end; // Print Mobs used to be 2 // Remove Mob = 3 + mob number:word if copy(stroke,1,10)='removemob ' then begin bytearray(bufu^)[sizzle]:=3; bytearray(bufu^)[sizzle+1]:=valx(copy(stroke,11,4)) and $FF; bytearray(bufu^)[sizzle+2]:=valx(copy(stroke,11,4)) shr 8; inc(sizzle,3); end; // Jump If True = Jump if Above Zero // Jump If Above = 4 + value:word + jump offset if copy(stroke,1,3)='ja ' then begin loikka[loix] := sizzle + 3; inc(loix); bytearray(bufu^)[sizzle] := 4; munki:=0; donitsi:=4; while (donitsi' ') do begin munki:=munki*10+valx(stroke[donitsi]); inc(donitsi); end; bytearray(bufu^)[sizzle+1]:=munki and $FF; bytearray(bufu^)[sizzle+2]:=munki shr 8; bytearray(bufu^)[sizzle+3]:=valx(copy(stroke,donitsi+1,2)); bytearray(bufu^)[sizzle+4]:=0; inc(sizzle,5); end; if copy(stroke,1,11)='jumpiftrue ' then begin loikka[loix]:=sizzle+3; inc(loix); bytearray(bufu^)[sizzle]:=4; bytearray(bufu^)[sizzle+1]:=0; bytearray(bufu^)[sizzle+2]:=0; bytearray(bufu^)[sizzle+3]:=valx(copy(stroke,12,2)); bytearray(bufu^)[sizzle+4]:=0; inc(sizzle,5); end; // Move Player To = 5 + room number:byte if copy(stroke,1,13)='moveplayerto ' then begin bytearray(bufu^)[sizzle]:=5; bytearray(bufu^)[sizzle+1]:=valx(copy(stroke,14,3)); inc(sizzle,2); end; // Wait More = 6 if stroke='waitmore' then begin bytearray(bufu^)[sizzle]:=6; inc(sizzle); end; // Color = 7 + color value:byte if copy(stroke,1,6)='color ' then begin bytearray(bufu^)[sizzle]:=7; bytearray(bufu^)[sizzle+1]:=valx(copy(stroke,7,3)); inc(sizzle,2); end; // Call = 8 + subscript number:byte if copy(stroke,1,5)='call ' then begin bytearray(bufu^)[sizzle]:=8; if ord(stroke[6])<65 then // global script bytearray(bufu^)[sizzle+1]:=valx(copy(stroke,6,3)) else begin // local room script stroke:=upcase(copy(stroke,6,length(stroke)-5)); for munki:=255 downto 232 do if stroke=verboz[munki] then bytearray(bufu^)[sizzle+1]:=munki; end; inc(sizzle,2); end; // Get Mob = 9 + mob number:word if copy(stroke,1,7)='getmob ' then begin bytearray(bufu^)[sizzle]:=9; bytearray(bufu^)[sizzle+1]:=valx(copy(stroke,8,4)) and $FF; bytearray(bufu^)[sizzle+2]:=valx(copy(stroke,8,4)) shr 8; inc(sizzle,3); end; // Wear Mob = 10 + mob number:word if copy(stroke,1,5)='wear ' then begin bytearray(bufu^)[sizzle]:=10; bytearray(bufu^)[sizzle+1]:=valx(copy(stroke,6,4)) and $FF; bytearray(bufu^)[sizzle+2]:=valx(copy(stroke,6,4)) shr 8; inc(sizzle,3); end; // Put Mob = 11 + mob number:word + room number:byte if copy(stroke,1,7)='putmob ' then begin bytearray(bufu^)[sizzle]:=11; bytearray(bufu^)[sizzle+1]:=valx(copy(stroke,8,4)) and $FF; bytearray(bufu^)[sizzle+2]:=valx(copy(stroke,8,4)) shr 8; bytearray(bufu^)[sizzle+3]:=valx(copy(stroke,13,3)); inc(sizzle,4); end; // CallM = 12 + mob number:word + mob script number:byte if copy(stroke,1,6)='callm ' then begin bytearray(bufu^)[sizzle]:=12; if upcase(copy(stroke,7,4))='SELF' then begin bytearray(bufu^)[sizzle+1]:=iduliini and $FF; bytearray(bufu^)[sizzle+2]:=iduliini shr 8; end else begin bytearray(bufu^)[sizzle+1]:=valx(copy(stroke,7,4)) and $FF; bytearray(bufu^)[sizzle+2]:=valx(copy(stroke,7,4)) shr 8; end; stroke:=upcase(copy(stroke,12,length(stroke)-6)); bytearray(bufu^)[sizzle+3]:=$FF; for munki:=0 to mobverbs do if stroke=verboz[munki] then bytearray(bufu^)[sizzle+3]:=munki; inc(sizzle,4); end; // Mob Present? = 13 + object id if copy(stroke,1,12)='mobpresent? ' then begin bytearray(bufu^)[sizzle]:=13; bytearray(bufu^)[sizzle+1]:=valx(copy(stroke,13,4)) and $FF; bytearray(bufu^)[sizzle+2]:=valx(copy(stroke,13,4)) shr 8; inc(sizzle,3); end; // Random = 14 + limit:word if copy(stroke,1,7)='random ' then begin bytearray(bufu^)[sizzle]:=14; bytearray(bufu^)[sizzle+1]:=valx(copy(stroke,8,length(stroke)-7)) and $FF; bytearray(bufu^)[sizzle+2]:=valx(copy(stroke,8,length(stroke)-7)) shr 8; inc(sizzle,3); end; // Jump If Below = 15 + value:word + jump offset if copy(stroke,1,3)='jb ' then begin loikka[loix]:=sizzle+3; inc(loix); bytearray(bufu^)[sizzle]:=15; munki:=0; donitsi:=4; while (donitsi' ') do begin munki:=munki*10+valx(stroke[donitsi]); inc(donitsi); end; bytearray(bufu^)[sizzle+1]:=munki and $FF; bytearray(bufu^)[sizzle+2]:=munki shr 8; bytearray(bufu^)[sizzle+3]:=valx(copy(stroke,donitsi+1,2)); bytearray(bufu^)[sizzle+4]:=0; inc(sizzle,5); end; // Jump If Equal = 16 + value:word + jump offset if copy(stroke,1,3)='je ' then begin loikka[loix]:=sizzle+3; inc(loix); bytearray(bufu^)[sizzle]:=16; munki:=0; donitsi:=4; while (donitsi' ') do begin munki:=munki*10+valx(stroke[donitsi]); inc(donitsi); end; bytearray(bufu^)[sizzle+1]:=munki and $FF; bytearray(bufu^)[sizzle+2]:=munki shr 8; bytearray(bufu^)[sizzle+3]:=valx(copy(stroke,donitsi+1,2)); bytearray(bufu^)[sizzle+4]:=0; inc(sizzle,5); end; // Jump If Not Equal = 17 + value:word + jump offset if copy(stroke,1,4)='jne ' then begin loikka[loix]:=sizzle+3; inc(loix); bytearray(bufu^)[sizzle]:=17; munki:=0; donitsi:=5; while (donitsi' ') do begin munki:=munki*10+valx(stroke[donitsi]); inc(donitsi); end; bytearray(bufu^)[sizzle+1]:=munki and $FF; bytearray(bufu^)[sizzle+2]:=munki shr 8; bytearray(bufu^)[sizzle+3]:=valx(copy(stroke,donitsi+1,2)); bytearray(bufu^)[sizzle+4]:=0; inc(sizzle,5); end; // Let = 18 + var:word + value:word if copy(stroke,1,4)='let ' then begin bytearray(bufu^)[sizzle]:=18; bytearray(bufu^)[sizzle+1]:=valx(copy(stroke,5,3)) and $FF; bytearray(bufu^)[sizzle+2]:=valx(copy(stroke,5,3)) shr 8; bytearray(bufu^)[sizzle+3]:=valx(copy(stroke,9,length(stroke)-8)) and $FF; bytearray(bufu^)[sizzle+4]:=valx(copy(stroke,9,length(stroke)-8)) shr 8; inc(sizzle,5); end; // Test = 19 + var:word if copy(stroke, 1, 5)='test ' then begin bytearray(bufu^)[sizzle] := 19; bytearray(bufu^)[sizzle + 1] := valx(copy(stroke, 6, 3)) and $FF; bytearray(bufu^)[sizzle + 2] := valx(copy(stroke, 6, 3)) shr 8; inc(sizzle, 3); end; // Jump, unconditional = 20 + jump offset if copy(stroke, 1, 4) = 'jmp ' then begin loikka[loix]:=sizzle+1; inc(loix); bytearray(bufu^)[sizzle]:=20; munki := valx(copy(stroke, 5, length(stroke) - 4)); bytearray(bufu^)[sizzle+1] := munki; bytearray(bufu^)[sizzle+2] := 0; inc(sizzle,3); end; // Add = 21 + var:word + value:word if copy(stroke, 1, 4)='add ' then begin bytearray(bufu^)[sizzle] := 21; bytearray(bufu^)[sizzle+1]:=valx(copy(stroke,5,3)) and $FF; bytearray(bufu^)[sizzle+2]:=valx(copy(stroke,5,3)) shr 8; bytearray(bufu^)[sizzle+3]:=valx(copy(stroke,9,length(stroke)-8)) and $FF; bytearray(bufu^)[sizzle+4]:=valx(copy(stroke,9,length(stroke)-8)) shr 8; inc(sizzle,5); end; // Subtract = 22 + var:word + value:word if copy(stroke, 1, 4)='sub ' then begin bytearray(bufu^)[sizzle] := 22; bytearray(bufu^)[sizzle+1]:=valx(copy(stroke,5,3)) and $FF; bytearray(bufu^)[sizzle+2]:=valx(copy(stroke,5,3)) shr 8; bytearray(bufu^)[sizzle+3]:=valx(copy(stroke,9,length(stroke)-8)) and $FF; bytearray(bufu^)[sizzle+4]:=valx(copy(stroke,9,length(stroke)-8)) shr 8; inc(sizzle,5); end; // Exit = FF if (stroke = 'end') or (stroke = 'exit') then begin bytearray(bufu^)[sizzle] := $FF; inc(sizzle); end; until stroke = 'end'; // Write jump offsets into script while loix > 0 do begin dec(loix); munki := matriza[bytearray(bufu^)[loikka[loix]]] + 4; bytearray(bufu^)[loikka[loix]] := munki and $FF; bytearray(bufu^)[loikka[loix] + 1] := munki shr 8; end; if pointer(mihin^) <> NIL then freep(@pointer(mihin^)); getmem(pointer(mihin^), sizzle + 4); dword(pointer(mihin^)^) := sizzle + 4; // first dword is size of script move(bufu^, (pointer(mihin^) + 4)^, sizzle); freep(@bufu); end; procedure readtxtdata(nametus:string); var strutsi:string; whine,muhis,iidee:word; begin assign(filu,nametus); reset(filu); repeat readln(filu,strutsi); if upcase(copy(strutsi,1,4))='MOB ' then begin iidee:=valx(copy(strutsi,5,4)); repeat readln(filu,strutsi); if copy(strutsi,1,6)='clone ' then begin mob[iidee].clone:=valx(copy(strutsi,7,4)); mob[iidee].invisible:=mob[mob[iidee].clone].invisible; mob[iidee].closed:=mob[mob[iidee].clone].closed; mob[iidee].name:=mob[mob[iidee].clone].name; mob[iidee].contains:=mob[mob[iidee].clone].contains; whine:=synopoku; while whine>0 do begin dec(whine); if synonym[whine].mobling=mob[iidee].clone then begin synonym[synopoku].mobling:=iidee; synonym[synopoku].nyymi:=synonym[whine].nyymi; synonym[synopoku].woids:=synonym[whine].woids; inc(synopoku); end; end; end; if strutsi='invisible' then mob[iidee].invisible:=true; if strutsi='closed' then mob[iidee].closed:=true; if copy(strutsi,1,5)='name ' then begin synonym[synopoku].mobling:=iidee; synonym[synopoku].nyymi:=copy(strutsi,6,length(strutsi)-5); for muhis:=1 to length(synonym[synopoku].nyymi) do if synonym[synopoku].nyymi[muhis]=chr(32) then inc(synonym[synopoku].woids); if mob[iidee].name=$FFFF then mob[iidee].name:=synopoku; inc(synopoku); end; if copy(strutsi, 1, 9) = 'contains ' then begin strutsi := copy(strutsi, 10, length(strutsi) - 9); repeat muhis := valx(strutsi); mob[muhis].stacknext := mob[iidee].contains; mob[iidee].contains := muhis; muhis := pos(',', strutsi); if muhis = 0 then strutsi := '' else strutsi := copy(strutsi, muhis + 1, length(strutsi) - muhis); until strutsi = ''; end; for muhis := 0 to mobverbs do if upcase(strutsi) = verboz[muhis] then loadtxtscript(@mob[iidee].script[muhis], iidee); until upcase(strutsi)='END'; end; if upcase(copy(strutsi,1,7))='SCRIPT ' then begin iidee := valx(copy(strutsi, 8, 3)); loadtxtscript(@script[iidee], iidee); end; if upcase(copy(strutsi,1,5))='ROOM ' then begin iidee:=valx(copy(strutsi,6,3)); room[iidee].name:=copy(strutsi,10,length(strutsi)-9); readln(filu,strutsi); // which objects initially in room while (strutsi<>'') do begin muhis:=valx(copy(strutsi,1,4)); mob[muhis].stacknext:=room[iidee].contains; room[iidee].contains:=muhis; if strutsi[5]=',' then strutsi:=copy(strutsi,6,length(strutsi)-5) else strutsi:=copy(strutsi,5,length(strutsi)-4); end; repeat readln(filu,strutsi); if upcase(strutsi)='LOOK' then loadtxtscript(@room[iidee].look,iidee); if upcase(strutsi)='LISTEN' then loadtxtscript(@room[iidee].listen,iidee); if upcase(strutsi)='ENTERED' then loadtxtscript(@room[iidee].entered,iidee); if upcase(strutsi)='EXITS' then loadtxtscript(@room[iidee].exits,iidee); if upcase(strutsi)='AMBIENCE' then loadtxtscript(@room[iidee].ambience,iidee); if upcase(strutsi)='NORTH' then loadtxtscript(@room[iidee].north,iidee); if upcase(strutsi)='SOUTH' then loadtxtscript(@room[iidee].south,iidee); if upcase(strutsi)='WEST' then loadtxtscript(@room[iidee].west,iidee); if upcase(strutsi)='EAST' then loadtxtscript(@room[iidee].east,iidee); if upcase(strutsi)='DOWN' then loadtxtscript(@room[iidee].down,iidee); if upcase(strutsi)='UP' then loadtxtscript(@room[iidee].up,iidee); if upcase(strutsi)='OUT' then loadtxtscript(@room[iidee].goout,iidee); if upcase(strutsi)='IN' then loadtxtscript(@room[iidee].goin,iidee); if upcase(strutsi)='NORTHWEST' then loadtxtscript(@room[iidee].northwest,iidee); if upcase(strutsi)='SOUTHWEST' then loadtxtscript(@room[iidee].southwest,iidee); if upcase(strutsi)='NORTHEAST' then loadtxtscript(@room[iidee].northeast,iidee); if upcase(strutsi)='SOUTHEAST' then loadtxtscript(@room[iidee].southeast,iidee); until upcase(strutsi)='END'; end; until eof(filu); close(filu); end; procedure insertline(thong : string); // Unloads a string into the logical message window // If the string is too long, split it over several lines... var malibu, tanga : byte; begin mv_Scroll(1); malibu := length(thong); tanga := 0; while malibu > 0 do begin if thong[malibu] = chr(255) then inc(tanga); dec(malibu); end; while length(thong) - tanga shl 1 > mv_Window[1].SizeX do begin malibu := 80; while (thong[malibu] <> chr(32)) and (malibu > 0) do dec(malibu); if malibu = 0 then malibu := 81; mwrite(1, 0, mv_Window[1].SizeY-1, copy(thong, 1, malibu - 1)); if thong[malibu] = chr(32) then thong := copy(thong, malibu + 1, length(thong) - malibu) else thong := copy(thong, malibu, length(thong) - malibu + 1); mv_Scroll(1); tanga := 0; while malibu > 0 do begin if thong[malibu] = chr(255) then inc(tanga); dec(malibu); end; end; mwrite(1, 0, mv_Window[1].SizeY - 1, thong); if mv_OutputMode = 0 then mv_rest(25); mv_GetEvents; end; function mobpresent(kuka,missa:word) : boolean; // Checks if the desired mob is in the stack below MISSA, // also checking the contents of any non-closed mobs var ronkeli:word; begin ronkeli:=missa; while (ronkeli<>$FFFF) do begin if ronkeli=kuka then begin mobpresent:=true; exit; end; if (mob[ronkeli].contains<>$FFFF) and (mob[ronkeli].closed=false) then if mobpresent(kuka,mob[ronkeli].contains) then begin mobpresent:=true; exit; end; ronkeli:=mob[ronkeli].stacknext; end; mobpresent:=false; end; procedure printmobs; var kehveli,stakki:word; staku:array[0..15] of word; begin staku[0]:=room[player.room].contains; kehveli:=0; stakki:=0; while staku[0]<>$FFFF do begin if mob[staku[stakki]].invisible=false then inc(kehveli); if (mob[staku[stakki]].contains<>$FFFF) then begin inc(stakki); if stakki=16 then begin insertline('ÿ4ERROR: Too many levels of nesting in local mobs!'); exit; end; staku[stakki]:=mob[staku[stakki-1]].contains; end else begin staku[stakki]:=mob[staku[stakki]].stacknext; while (staku[stakki]=$FFFF) and (stakki>0) do begin if (staku[stakki]=$FFFF) and (stakki>0) then dec(stakki); staku[stakki]:=mob[staku[stakki]].stacknext; end; end; end; if kehveli=0 then exit; insertline('ÿ3You see here:'); staku[0]:=room[player.room].contains; stakki:=0; while staku[0]<>$FFFF do begin if mob[staku[stakki]].invisible=false then begin insertline('ÿ2'+synonym[mob[staku[stakki]].name].nyymi); end; if (mob[staku[stakki]].contains<>$FFFF) then begin inc(stakki); staku[stakki]:=mob[staku[stakki-1]].contains; end else begin staku[stakki]:=mob[staku[stakki]].stacknext; while (staku[stakki]=$FFFF) and (stakki>0) do begin if (staku[stakki]=$FFFF) and (stakki>0) then dec(stakki); staku[stakki]:=mob[staku[stakki]].stacknext; end; end; end; end; procedure RunScript(manus : pointer); var ofsu : dword; bobska, mookeli, accumulator : word; strutsi : string; savy : byte; begin if manus = NIL then begin insertline('ÿ4ERROR: tried to run a non-existent script!'); exit; end; if dword(manus^) = 0 then begin insertline('ÿ4ERROR: tried to run a script with 0 length!'); exit; end; ofsu := 4; savy := 7; accumulator := 0; repeat case bytearray(manus^)[ofsu] of 1: begin // print move(bytearray(manus^)[ofsu + 1], strutsi, bytearray(manus^)[ofsu + 1] + 1); insertline('ÿ' + strhex(savy) + strutsi); inc(ofsu, bytearray(manus^)[ofsu + 1] + 2); end; 3: begin // removemob bobska:=bytearray(manus^)[ofsu+1] or (bytearray(manus^)[ofsu+2] shl 8); if player.inventory=bobska then player.inventory:=mob[bobska].stacknext; for mookeli:=0 to 255 do if room[mookeli].contains=bobska then room[mookeli].contains:=mob[bobska].stacknext; for mookeli:=0 to max_mobs do begin if mob[mookeli].stacknext=bobska then mob[mookeli].stacknext:=mob[bobska].stacknext; if mob[mookeli].contains=bobska then mob[mookeli].contains:=mob[bobska].stacknext; end; inc(ofsu,3); end; 4: begin // jump if above bobska:=bytearray(manus^)[ofsu+1] or (bytearray(manus^)[ofsu+2] shl 8); if accumulator>bobska then ofsu:=bytearray(manus^)[ofsu+3] or (bytearray(manus^)[ofsu+4] shl 8) else inc(ofsu,5); end; 5: begin // moveplayerto player.room:=bytearray(manus^)[ofsu+1]; if room[player.room].entered<>nil then runscript(room[player.room].entered); insertline('ÿ3'+room[player.room].name); if room[player.room].visited=false then runscript(room[player.room].look); room[player.room].visited:=true; printmobs; inc(ofsu,2); end; 6: begin // waitmore mwrite(2,0,0,'ÿ9-- more --' + space(mv_Window[2].SizeX-10)); mv_SetCursor(2, 10, 0, 16); readkey; mv_scroll(2); mv_SetCursor(2, 0, 0, 16); inc(ofsu); end; 7: begin // color savy := bytearray(manus^)[ofsu+1]; inc(ofsu, 2); end; 8: begin // call case bytearray(manus^)[ofsu+1] of 232: runscript(room[player.room].ambience); 233: runscript(room[player.room].exits); 234: runscript(room[player.room].listen); 242: runscript(room[player.room].entered); 243: runscript(room[player.room].look); 244: runscript(room[player.room].goin); 245: runscript(room[player.room].goout); 246: runscript(room[player.room].southeast); 247: runscript(room[player.room].southwest); 248: runscript(room[player.room].northeast); 249: runscript(room[player.room].northwest); 250: runscript(room[player.room].east); 251: runscript(room[player.room].west); 252: runscript(room[player.room].south); 253: runscript(room[player.room].north); 254: runscript(room[player.room].up); 255: runscript(room[player.room].down); else runscript(script[bytearray(manus^)[ofsu+1]]); end; inc(ofsu,2); end; 9: begin // getmob bobska:=bytearray(manus^)[ofsu+1] or (bytearray(manus^)[ofsu+2] shl 8); mob[bobska].stacknext:=player.inventory; player.inventory:=bobska; inc(ofsu,3); end; 10: begin // wear bobska:=bytearray(manus^)[ofsu+1] or (bytearray(manus^)[ofsu+2] shl 8); if bobska>max_mobs then begin insertline('ÿ4ERROR: Tried to wear mob above max_mobs ('+strdec(bobska)+')!'); exit; end; if mob[bobska].name=$FFFF then begin insertline('ÿ4ERROR: Tried to wear nonexistent mob ('+strdec(bobska)+')!'); end; mob[bobska].worn:=true; inc(ofsu,3); end; 11: begin // putmob bobska:=bytearray(manus^)[ofsu+1] or (bytearray(manus^)[ofsu+2] shl 8); if bobska>max_mobs then begin insertline('ÿ4ERROR: Tried to put mob above max_mobs ('+strdec(bobska)+') into a room!'); exit; end; if mob[bobska].name=$FFFF then begin insertline('ÿ4ERROR: Tried to put nonexistent mob ('+strdec(bobska)+') into a room!'); end; mob[bobska].stacknext:=room[bytearray(manus^)[ofsu+3]].contains; room[bytearray(manus^)[ofsu+3]].contains:=bobska; inc(ofsu,4); end; 12: begin // callm bobska:=bytearray(manus^)[ofsu+1] or (bytearray(manus^)[ofsu+2] shl 8); if bytearray(manus^)[ofsu+3]=$FF then begin insertline('ÿ4ERROR: callm to unknown script'); exit; end; runscript(mob[bobska].script[bytearray(manus^)[ofsu+3]]); inc(ofsu,4); end; 14: begin // random bobska:=bytearray(manus^)[ofsu+1] or (bytearray(manus^)[ofsu+2] shl 8); accumulator:=random(bobska); inc(ofsu,3); end; 15: begin // jump if below bobska:=bytearray(manus^)[ofsu+1] or (bytearray(manus^)[ofsu+2] shl 8); if accumulatorbobska then ofsu:=bytearray(manus^)[ofsu+3] or (bytearray(manus^)[ofsu+4] shl 8) else inc(ofsu,5); end; 18: begin // let var equal something bobska:=bytearray(manus^)[ofsu+1] or (bytearray(manus^)[ofsu+2] shl 8); if bobska>max_vars then begin insertline('ÿ4ERROR: tried to set variable out of range: '+strdec(bobska)+'!'); exit; end; gamevar[bobska] := bytearray(manus^)[ofsu+3] or (bytearray(manus^)[ofsu+4] shl 8); inc(ofsu,5); end; 19: begin // test var bobska := bytearray(manus^)[ofsu + 1] or (bytearray(manus^)[ofsu + 2] shl 8); if bobska > max_vars then begin insertline('ÿ4ERROR: tested variable out of range: ' + strdec(bobska) + '!'); exit; end; accumulator := gamevar[bobska]; inc(ofsu, 3); end; 20: begin // jump, unconditional ofsu := bytearray(manus^)[ofsu+1] or (bytearray(manus^)[ofsu+2] shl 8); end; 21: begin // add to var bobska := bytearray(manus^)[ofsu+1] or (bytearray(manus^)[ofsu+2] shl 8); if bobska > max_vars then begin insertline('ÿ4ERROR: tried to add to a variable out of range: '+strdec(bobska)+'!'); exit; end; inc(gamevar[bobska], bytearray(manus^)[ofsu + 3] or (bytearray(manus^)[ofsu + 4] shl 8)); inc(ofsu,5); end; 22: begin // subtract from var bobska := bytearray(manus^)[ofsu+1] or (bytearray(manus^)[ofsu+2] shl 8); if bobska > max_vars then begin insertline('ÿ4ERROR: tried to subtract from a variable out of range: '+strdec(bobska)+'!'); exit; end; dec(gamevar[bobska], bytearray(manus^)[ofsu + 3] or (bytearray(manus^)[ofsu + 4] shl 8)); inc(ofsu,5); end; $FF: exit; // end or exit else begin insertline('ÿ4ERROR: unrecognized command code ' + strdec(bytearray(manus^)[ofsu]) + ' in script!'); exit; end; end; until ofsu >= dword(manus^); end; procedure parser; var myword : array[1..13] of string[78]; mywords : byte; harveli, kehveli, suffeli : word; trakkin : boolean; tohveli, isoveli, preposition : string; match : array[0..max_synonyms] of word; verb, tarket, objekt : word; begin com := upcase(com); if (com = 'AGAIN') or (com = 'G') then com := upcase(lastcom); // Remove punctuation harveli := 1; while harveli <= length(com) do begin if (com[harveli] = '.') or (com[harveli] = ',') or (com[harveli] = '!') or (com[harveli] = '?') or (com[harveli] = '-') or (com[harveli] = ':') or (com[harveli] = ';') then com := copy(com, 1, harveli - 1) + copy(com, harveli + 1, length(com) - harveli) else inc(harveli); end; // Isolate the words from user input for harveli := 1 to 13 do myword[harveli] := ''; harveli := 1; mywords := 0; trakkin := false; while harveli <= length(com) do begin if (trakkin = FALSE) and (com[harveli] <> chr(32)) then begin trakkin := TRUE; inc(mywords); end else if (trakkin = TRUE) and (com[harveli] = chr(32)) then trakkin := FALSE; if mywords = 10 then begin insertline('They don''t pay me enough to handle commands that long in one go.'); exit; end; if trakkin then myword[mywords] := myword[mywords] + com[harveli]; inc(harveli); end; // Brutally dismember articles, unless more than one in a row harveli := 1; while harveli<=mywords do begin if (myword[harveli]='THE') or (myword[harveli]='A') or (myword[harveli]='AN') then begin dec(mywords); for kehveli:=harveli to mywords do myword[kehveli]:=myword[kehveli+1]; end; inc(harveli); end; // Retire and Replace verb synonyms if (myword[1]='INVENTORY') or (myword[1]='INV') then myword[1]:='I'; if (myword[1]='YEAH') or (myword[1]='SURE') then myword[1]:='YES'; if (myword[1]='NOPE') or (myword[1]='NAH') then myword[1]:='NO'; if (myword[1]='SHOW') and (myword[2]='EXITS') and (mywords=2) then begin myword[1]:='EXITS'; mywords:=1; end; if myword[1]='L' then myword[1]:='LOOK'; if (myword[1]='LOOK') and (myword[2]='AT') then begin dec(mywords); for kehveli:=2 to mywords do myword[kehveli]:=myword[kehveli+1]; end; if (myword[1]='X') or (myword[1]='EXAMINE') then myword[1]:='LOOK'; if (myword[1]='GET') and (myword[2]='DRESSED') and (mywords=2) then begin myword[1]:='WEAR'; myword[2]:='CLOTHES'; end; if (myword[1]='UNDRESS') then if mywords=1 then begin myword[1]:='REMOVE'; myword[2]:='CLOTHES'; mywords:=2; end else myword[1]:='REMOVE'; if (myword[1]='GET') then if (myword[2]='IN') or (myword[2]='INTO') then begin dec(mywords); for kehveli:=2 to mywords do myword[kehveli]:=myword[kehveli+1]; myword[1]:='ENTER'; end; if (myword[1]='GET') and (myword[2]='UP') then begin dec(mywords); for kehveli:=2 to mywords do myword[kehveli]:=myword[kehveli+1]; myword[1]:='STAND'; end; if (myword[1]='GET') and (myword[2]='OUT') then begin dec(mywords); for kehveli:=2 to mywords do myword[kehveli]:=myword[kehveli+1]; myword[1]:='EXIT'; end; if myword[1] = 'EXIT' then myword[1] := 'OUT'; if (myword[1]='TAKE') and (myword[2]='OFF') then begin dec(mywords); for kehveli:=2 to mywords do myword[kehveli]:=myword[kehveli+1]; myword[1]:='REMOVE'; end; if (myword[1]='PUT') and (myword[2]='ON') then begin dec(mywords); for kehveli:=2 to mywords do myword[kehveli]:=myword[kehveli+1]; myword[1]:='WEAR'; end; if (myword[1]='KNOCK') and (myword[2]='ON') then begin dec(mywords); for kehveli:=2 to mywords do myword[kehveli]:=myword[kehveli+1]; end; if (myword[1]='PUT') and (myword[mywords]='ON') then begin dec(mywords); myword[1]:='WEAR'; end; if (myword[1]='TAKE') and (myword[mywords]='OFF') then begin dec(mywords); myword[1]:='REMOVE'; end; if (myword[1]='TALK') and (myword[2]='TO') then begin dec(mywords); for kehveli:=2 to mywords do myword[kehveli]:=myword[kehveli+1]; end; if (myword[1]='LISTEN') and (myword[2]='TO') then begin dec(mywords); for kehveli:=2 to mywords do myword[kehveli]:=myword[kehveli+1]; end; if (myword[1]='PLAY') and (myword[2]='WITH') then begin dec(mywords); for kehveli:=2 to mywords do myword[kehveli]:=myword[kehveli+1]; end; if myword[1]='ARISE' then myword[1]:='STAND'; if (myword[1]='PUSH') or (myword[1]='PULL') then myword[1] := 'MOVE'; if (myword[1]='PUNCH') or (myword[1]='WHACK') or (myword[1]='SLAP') or (myword[1]='STRIKE') then myword[1]:='HIT'; if (myword[1]='CARESS') or (myword[1]='PET') or (myword[1]='STROKE') or (myword[1]='HUG') or (myword[1]='FEEL') or (myword[1]='RUB') then myword[1]:='TOUCH'; if myword[1]='TOSS' then myword[1]:='THROW'; if (myword[1]='CHEW') or (myword[1]='CONSUME') or (myword[1]='DEVOUR') or (myword[1]='SWALLOW') then myword[1]:='EAT'; if (myword[1]='QUAFF') then myword[1]:='DRINK'; if myword[1]='DON' then myword[1]:='WEAR'; if myword[1]='DOFF' then myword[1]:='REMOVE'; if myword[1]='FORCE' then myword[1]:='SMASH'; if myword[1]='BREAK' then myword[1]:='SMASH'; if myword[1]='GO' then if (myword[2]='IN') or (myword[2]='INSIDE') or (myword[2]='INTO') then begin dec(mywords); for kehveli:=2 to mywords do myword[kehveli]:=myword[kehveli+1]; myword[1]:='ENTER'; end; if (myword[1]='SAVE') and (mywords=2) and (myword[2]='GAME') then mywords:=1; if myword[1]='RESTORE' then myword[1]:='LOAD'; if (myword[1]='LOAD') and (mywords=2) and (myword[2]='GAME') then mywords:=1; if (myword[1]='QUIT') and (mywords=2) and (myword[2]='GAME') then mywords:=1; if (myword[1]='LOOK') and (myword[2]='AROUND') and (mywords=2) then mywords:=1; if (myword[1]='PICK') and (myword[2]='UP') then begin dec(mywords); for kehveli:=2 to mywords do myword[kehveli]:=myword[kehveli+1]; myword[1]:='TAKE'; end; if (myword[1]='PICK') and (myword[mywords]='UP') then begin dec(mywords); myword[1]:='TAKE'; end; if myword[1]='GO' then begin if (myword[2]='IN') or (myword[2]='INTO') or (myword[2]='TO') then begin dec(mywords); for kehveli:=2 to mywords do myword[kehveli]:=myword[kehveli+1]; end; if myword[2]='SOUTH' then begin myword[1]:='SOUTH'; mywords:=1; end; if myword[2]='NORTH' then begin myword[1]:='NORTH'; mywords:=1; end; if myword[2]='EAST' then begin myword[1]:='EAST'; mywords:=1; end; if myword[2]='WEST' then begin myword[1]:='WEST'; mywords:=1; end; if myword[2]='UP' then begin myword[1]:='UP'; mywords:=1; end; if myword[2]='DOWN' then begin myword[1]:='DOWN'; mywords:=1; end; if myword[2]='OUT' then begin myword[1]:='OUT'; mywords:=1; end; if myword[2]='SOUTHWEST' then begin myword[1]:='SOUTHWEST'; mywords:=1; end; if myword[2]='NORTHWEST' then begin myword[1]:='NORTHWEST'; mywords:=1; end; if myword[2]='SOUTHEAST' then begin myword[1]:='SOUTHEAST'; mywords:=1; end; if myword[2]='NORTHEAST' then begin myword[1]:='NORTHEAST'; mywords:=1; end; end; if (myword[1]='ENTER') and (mywords=1) then myword[1]:='IN'; if myword[1]='GET' then myword[1]:='TAKE'; if myword[1]='N' then myword[1]:='NORTH'; if myword[1]='S' then myword[1]:='SOUTH'; if myword[1]='E' then myword[1]:='EAST'; if myword[1]='W' then myword[1]:='WEST'; if myword[1]='SW' then myword[1]:='SOUTHWEST'; if myword[1]='SE' then myword[1]:='SOUTHEAST'; if myword[1]='NW' then myword[1]:='NORTHWEST'; if myword[1]='NE' then myword[1]:='NORTHEAST'; if (myword[1]='CLIMB') and (mywords=2) then if myword[2]='UP' then begin myword[1]:='UP'; mywords:=1; end else if myword[2]='DOWN' then begin myword[1]:='DOWN'; mywords:=1; end; if myword[1]='U' then myword[1]:='UP'; if myword[1]='D' then myword[1]:='DOWN'; // Allocate VERB [tarket] [preposition] [object] verb:=$FFFF; tarket:=$FFFF; objekt:=$FFFF; preposition:=''; for harveli:=255 downto 0 do if verboz[harveli]=myword[1] then verb:=harveli; if (verb=$FFFF) or (verb=242) or (verb=232) then begin insertline(myword[1]+' is not in your vocabulary of verbs.'); exit; end; for harveli := 0 to max_synonyms do match[harveli] := $FFFF; if mywords > 1 then begin trakkin := false; suffeli := 0; kehveli := 0; for harveli:=0 to synopoku do if synonym[harveli].woidssuffeli then suffeli:=length(synonym[harveli].nyymi); inc(kehveli); end else if tohveli+'S'=upcase(synonym[harveli].nyymi) then begin match[kehveli]:=harveli; if length(synonym[harveli].nyymi)>suffeli then suffeli:=length(synonym[harveli].nyymi)-1; inc(kehveli); end; end; if kehveli=0 then begin insertline(myword[2]+' is not in your vocabulary of game objects.'); exit; end; // filter out all matches shorter than longest harveli:=0; while harveli$FFFF then begin trakkin:=true; isoveli:=isoveli+synonym[mob[synonym[match[tarket]].mobling].name].nyymi+', '; end; tarket:=harveli; end; end; if tarket=$FFFF then tarket:=match[0] else tarket:=match[tarket]; if trakkin then begin insertline('Which do you mean?'); isoveli:=copy(isoveli,1,length(isoveli)-2)+' or '+synonym[mob[synonym[tarket].mobling].name].nyymi+'?'; insertline(isoveli); exit; end; // cut out target synonym if (mywords>synonym[tarket].woids+2) then begin mywords:=mywords-synonym[tarket].woids-2; for harveli:=1 to mywords do myword[harveli]:=myword[harveli+synonym[tarket].woids+2]; // preposition extraction if (myword[1]='WITH') or (myword[1]='ON') or (myword[1]='IN') or (myword[1]='TO') or (myword[1]='AT') or (myword[1]='INTO') then begin preposition:=myword[1]; for harveli:=1 to mywords-1 do myword[harveli]:=myword[harveli+1]; dec(mywords); insertline(myword[1]+' is not in your vocabulary of prepositions.'); exit; end; // figure out command objekt end; if (verb=20) then begin // special case for DROP, item must be in inventory if (mobpresent(synonym[tarket].mobling,player.inventory)=false) then begin insertline('You smack your forehead upon realizing you weren''t holding it anyway.'); exit; end end else if (synonym[tarket].mobling<>0) and (mobpresent(synonym[tarket].mobling,room[player.room].contains)=false) and (mobpresent(synonym[tarket].mobling,player.inventory)=false) then begin insertline('You can not see it here.'); exit; end; tarket:=synonym[tarket].mobling; // If a clone mob, copy the latest attached scripts from original mob if mob[tarket].clone<>$FFFF then for harveli:=0 to mobverbs do mob[tarket].script[harveli]:=mob[mob[tarket].clone].script[harveli]; end; // If a YES/NO question was asked but is not answered, forget question if gamevar[2]>0 then if (verb<>235) and (verb<>236) then gamevar[2]:=0; // Process command! case verb of 0: begin // look if tarket=$FFFF then begin insertline('ÿ3'+room[player.room].name); runscript(room[player.room].look); printmobs; exit; end; if mob[tarket].script[0]=nil then begin insertline('You see nothing that is not painfully obvious.'); end else runscript(mob[tarket].script[0]); end; 1: begin // take if tarket=$FFFF then begin insertline('You grab a handful of nothing and stuff it in your inventory.'); exit; end; if (mobpresent(tarket,player.inventory)=true) then begin insertline('It''s already a happy member of your ever-growing inventory.'); exit; end; if mob[tarket].script[1]=nil then begin insertline('It bluntly refuses to jump into your pocket.'); end else runscript(mob[tarket].script[1]); end; 2: begin // open if tarket=$FFFF then begin insertline('Open... what?'); exit; end; if mob[tarket].script[2]=nil then begin insertline('It can''t be opened just like that.'); end else runscript(mob[tarket].script[2]); end; 3: begin // smash if tarket=$FFFF then begin insertline('What are you trying to break?'); exit; end; if mob[tarket].script[3]=nil then begin insertline('There is nothing to be gained by smashing the poor thing.'); end else runscript(mob[tarket].script[3]); end; 4: begin // show insertline('You are perplexed by a sudden inability to show things to others!'); insertline('[Commands requiring prepositions are not yet implemented.]'); end; 5: begin // give insertline('You are perplexed by a sudden inability to give things to others!'); insertline('[Commands requiring prepositions are not yet implemented.]'); end; 6: begin // close if tarket=$FFFF then begin insertline('Close... what?'); exit; end; if mob[tarket].script[6]=nil then begin insertline('It can''t be closed just like that.'); end else runscript(mob[tarket].script[6]); end; 7: begin // climb if tarket=$FFFF then begin insertline('You''re climbing in the air / you''re rising with an inner burn'); insertline('Your quest still waits down there / you know you must return'); exit; end; if mob[tarket].script[7]=nil then begin insertline('Trying to climb that would no doubt be amusing, but it''s a waste of time.'); end else runscript(mob[tarket].script[7]); end; 8: begin // wear if tarket=$FFFF then begin insertline('What exactly would you like to wear today, ma''am?'); exit; end; if mob[tarket].script[8]=nil then begin if mob[tarket].worn then begin insertline('You''re already wearing it. And, it looks good on you.'); exit; end; insertline('Even if you could wear it, it wouldn''t look good on you.'); end else runscript(mob[tarket].script[8]); end; 9: begin // eat if tarket=$FFFF then begin insertline('Please specify the object you wish to consume.'); exit; end; if mob[tarket].script[9]=nil then begin insertline('Hmmmm. Tastes a bit funny. Guess it''s not meant for eating.'); end else runscript(mob[tarket].script[9]); end; 10: begin // remove if tarket=$FFFF then begin insertline('Remove... what?'); exit; end; if mob[tarket].script[10]=nil then begin if mob[tarket].worn=false then begin insertline('You''re not wearing it. Which, I suppose, is what you wanted to achieve.'); exit; end; insertline('It refuses to be removed.'); end else runscript(mob[tarket].script[10]); end; 11: begin // knock if tarket=$FFFF then begin insertline('Knock on... what?'); exit; end; if mob[tarket].script[11]=nil then begin insertline('You''re surprised by the absolute lack of reaction to your knocking.'); end else runscript(mob[tarket].script[11]); end; 12: begin // kick if tarket=$FFFF then begin insertline('You kick the ground in frustration.'); exit; end; if mob[tarket].script[12]=nil then begin insertline('Chill. Let your anger build up, and then release it at your REAL target.'); end else runscript(mob[tarket].script[12]); end; 13: begin // throw end; 14: begin // read if tarket=$FFFF then begin insertline('What would you like to read?'); exit; end; if mob[tarket].script[14]=nil then begin insertline('You see nothing to read there.'); end else runscript(mob[tarket].script[14]); end; 15: begin // play if tarket=$FFFF then begin insertline('A momentary playfulness overcomes you, but you are on a quest.'); exit; end; if mob[tarket].script[15]=nil then begin insertline('It''s not particularly playable.'); end else runscript(mob[tarket].script[15]); end; 16: begin // rest insertline('You feel quite perky. No need to sleep now.'); end; 17: begin // enter if tarket=$FFFF then begin insertline('ÿ4ERROR: ENTER without target?! Should have been translated to IN.'); exit; end; if mob[tarket].script[17]=nil then begin insertline('Now, how exactly will a vampire hunter girl get into that?'); end else runscript(mob[tarket].script[17]); end; 18: begin // touch if tarket=$FFFF then begin insertline('What would you like to grant your gentle touch to?'); exit; end; if mob[tarket].script[18]=nil then begin insertline('You have little desire to caress that any more than really necessary.'); end else runscript(mob[tarket].script[18]); end; 19: begin // drink if tarket=$FFFF then begin insertline('You only drink in particular, never in general.'); exit; end; if mob[tarket].script[19]=nil then begin insertline('I regret the need to inform you, but that is not drinkable.'); end else runscript(mob[tarket].script[19]); end; 20: begin // drop if tarket=$FFFF then begin insertline('You drop, then pick yourself up again.'); exit; end; if mob[tarket].script[20]=nil then begin insertline('One of the tips in the handguide was never to drop anything. You intend to'); insertline('abide by that point strictly.'); exit; end else runscript(mob[tarket].script[20]); end; 21: begin // help if tarket=$FFFF then begin if script[1]=nil then begin insertline('No one hears your pleas for help. You feel....... alone.'); exit; end; runscript(script[1]); exit; end; if mob[tarket].script[21]=nil then begin insertline('No appropriate way to render help comes to your mind.'); end else runscript(mob[tarket].script[21]); end; 22: begin // talk if tarket=$FFFF then tarket:=0; // no target -> talk to yourself if mob[tarket].script[22]=nil then begin insertline('You feel no answer would be forthcoming, and decide to remain silent.'); end else runscript(mob[tarket].script[22]); end; 23: begin // hit if tarket=$FFFF then begin insertline('You hit your palm decisively.'); exit; end; if mob[tarket].script[23]=nil then begin insertline('Chill. Let your anger build up, and then release it at your REAL target.'); end else runscript(mob[tarket].script[23]); end; 24: begin // move if tarket=$FFFF then begin insertline('Wherever you go, you remain mobile.'); exit; end; if mob[tarket].script[24] = NIL then insertline('Not a budge rewards your effort.') else runscript(mob[tarket].script[24]); end; 233: begin // exits if room[player.room].exits<>nil then runscript(room[player.room].exits) else begin insertline('You can not make out any way to go.'); end; end; 234: begin // listen if tarket<>$FFFF then begin insertline('You never listen in particular, only in general. Try just plain "listen".'); exit; end; if room[player.room].listen<>nil then runscript(room[player.room].listen) else begin insertline('You perk your ears, holding your breath and stilling your heart. You make out'); insertline('no distinct sounds.'); end; end; 235: begin // no case gamevar[2] of $FF: begin insertline('That''s the spirit. Keep struggling, girl. You''ll make it some day.'); gamevar[2]:=0; end; else runscript(script[3]); end; end; 236: begin // yes case gamevar[2] of $FF: begin quit:=true; end; else runscript(script[2]); end; end; 237: begin // go insertline('That is no place for you to run to, and no place for you to hide.'); end; 238: begin // inventory harveli:=player.inventory; insertline('ÿ3You are carrying:'); while harveli<>$FFFF do begin if mob[harveli].invisible=false then begin if mob[harveli].worn then insertline('ÿ2'+synonym[mob[harveli].name].nyymi+' [worn]') else insertline('ÿ2'+synonym[mob[harveli].name].nyymi); end; harveli:=mob[harveli].stacknext; end; end; 239: begin // quit insertline('You really want to quit the game?'); gamevar[2]:=$FF; end; 240: begin // load end; 241: begin // save end; 244: begin // in if room[player.room].goin=nil then begin insertline('There seems to be nowhere to go in to.'); if room[player.room].exits<>nil then runscript(room[player.room].exits); end else runscript(room[player.room].goin); end; 245: begin // out if room[player.room].goout=nil then begin insertline('There seems to be nowhere to go out to.'); if room[player.room].exits<>nil then runscript(room[player.room].exits); end else runscript(room[player.room].goout); end; 246: begin // southeast if room[player.room].southeast=nil then begin insertline('There seems to be no way to go southeast.'); if room[player.room].exits<>nil then runscript(room[player.room].exits); end else runscript(room[player.room].southeast); end; 247: begin // southwest if room[player.room].southwest=nil then begin insertline('There seems to be no way to go southwest.'); if room[player.room].exits<>nil then runscript(room[player.room].exits); end else runscript(room[player.room].southwest); end; 248: begin // northeast if room[player.room].northeast=nil then begin insertline('There seems to be no way to go northeast.'); if room[player.room].exits<>nil then runscript(room[player.room].exits); end else runscript(room[player.room].northeast); end; 249: begin // northwest if room[player.room].northwest=nil then begin insertline('There seems to be no way to go northwest.'); if room[player.room].exits<>nil then runscript(room[player.room].exits); end else runscript(room[player.room].northwest); end; 250: begin // east if room[player.room].east=nil then begin insertline('There seems to be no way to go east.'); if room[player.room].exits<>nil then runscript(room[player.room].exits); end else runscript(room[player.room].east); end; 251: begin // west if room[player.room].west=nil then begin insertline('There seems to be no way to go west.'); if room[player.room].exits<>nil then runscript(room[player.room].exits); end else runscript(room[player.room].west); end; 252: begin // south if room[player.room].south=nil then begin insertline('There seems to be no way to go south.'); if room[player.room].exits<>nil then runscript(room[player.room].exits); end else runscript(room[player.room].south); end; 253: begin // north if room[player.room].north=nil then begin insertline('There seems to be no way to go north.'); if room[player.room].exits<>nil then runscript(room[player.room].exits); end else runscript(room[player.room].north); end; 254: begin // up if room[player.room].up=nil then begin insertline('There seems to be no way up.'); if room[player.room].exits<>nil then runscript(room[player.room].exits); end else runscript(room[player.room].up); end; 255: begin // down if room[player.room].down=nil then begin insertline('There seems to be no way down.'); if room[player.room].exits<>nil then runscript(room[player.room].exits); end else runscript(room[player.room].down); end; end; end; begin addExitProc(@ReleaseAll); randomize; player.score := 0; player.maxscore := 1; player.room := $FFFF; player.inventory := $FFFF; for i:=0 to 255 do begin room[i].visited:=false; room[i].contains:=$FFFF; end; for i:=0 to max_mobs do begin mob[i].name:=$FFFF; mob[i].closed:=false; mob[i].contains:=$FFFF; mob[i].stacknext:=$FFFF; mob[i].invisible:=false; mob[i].clone:=$FFFF; end; for i := 0 to max_synonyms do begin synonym[i].mobling := $FFFF; synonym[i].woids := 0; synonym[i].nyymi := ''; end; for i := 0 to max_vars do gamevar[i] := 0; synopoku := 0; readtxtdata('mobs.txt'); readtxtdata('rooms.txt'); readtxtdata('scripts.txt'); dec(synopoku); // showbmp('title.bmp'); mv_programname := 'Vampire Hunter Girl'; mv_OutputMode := 1; mv_OutputSizeCols := 80; mv_OutputSizeRows := 30; mv_TileName := '1020Vamp.BMP'; mv_TileSizeX := 10; mv_TileSizeY := 20; read_ini_file; mv_init; with mv_window[0] do begin locx := 0; locy := 0; sizex := 80; sizey := 2; getmem(buffy, sizex * sizey * mv_BlockSize); end; with mv_window[1] do begin locx := 0; locy := 2; sizex := 80; sizey := mv_OutputSizeRows - 3; getmem(buffy, sizex * sizey * mv_BlockSize); end; gamevar[3] := mv_window[1].sizey; with mv_window[2] do begin locx := 0; locy := mv_OutputSizeRows - 1; sizex := 80; sizey := 1; getmem(buffy, sizex * sizey * mv_BlockSize); end; mv_NumWindows := 3; mv_ClearWindows; mwrite(0, 0, 0, ' ÿCVampire Hunter ÿBGirl ÿC Score: ÿB0 of '+strdec(player.maxscore)); mwrite(0, 22, 1, '`-,_,.-~ïù`''~.,. ÿ9Ïÿ7 .,.~''ïù`~-.,_,-ï'); mv_SetCursor(2, 0, 0, 16); quit := false; com := ''; lastcom := ''; runscript(script[0]); mv_Scroll(1); repeat mwrite(2, 0, 0,'ÿF> ' + com + ' '); mv_SetCursor(2, length(com) + 2, 0, 16); i := readkey; if i < 256 then comchar := chr(i) else comchar := chr(0); if (ord(comchar) >= 32) and (length(com) + 4 < mv_Window[2].SizeX) then com := com + comchar; if (comchar = chr(8)) and (com <> '') then com := copy(com, 1, length(com) - 1); if (comchar = chr(13)) then begin mv_Scroll(2); insertline('ÿF> ' + com); mv_Scroll(1); mv_SetCursor(2, 0, 0, 16); if com <> '' then begin parser; if room[player.room].ambience <> nil then runscript(room[player.room].ambience); mv_Scroll(1); lastcom := com; if gamevar[5] <> player.score then begin if gamevar[5] > player.score then insertline('[Your score has gone up by '+strdec(gamevar[5] - player.score)+'.]') else insertline('[Your score has gone down by '+strdec(player.score - gamevar[5])+'.]'); mv_Scroll(1); player.score := gamevar[5]; mwrite(0, 60, 0, 'ÿB'+strdec(player.score)+' of '+strdec(player.maxscore)); end; end; com := ''; end; until (quit) or (mv_EndProgram); end.