home *** CD-ROM | disk | FTP | other *** search
/ ftp.wwiv.com / ftp.wwiv.com.zip / ftp.wwiv.com / pub / MISC / DNDOOR46.ZIP / DNDDOOR.BAS < prev    next >
BASIC Source File  |  2001-07-11  |  110KB  |  2,416 lines

  1.  Rem * Filename: dnddoor.bas  Version: v4.6 r1.0
  2.  Rem * This subprogram contains the main input and communication routines.
  3.  
  4.  Rem $Include: 'dnddoor.inc'
  5.  
  6.  '  main program. all processing starts here.
  7.  On Error Resume Next ' error trapping
  8.  Stack 4096 ' increase stack space
  9.  Randomize Timer ' reseed random generator
  10.  Call Read.Config ' loads all necessary variables, and configuration
  11.  Call Login ' logs in local or remote player
  12.  Do ' main input loop
  13.     Call Encounter.Monster ' search for random monster encounter
  14.     Call Health.Update ' increment/decrement player statistics
  15.     Call Monster.Attack ' search for active monsters that attack
  16.     Call New.Stats ' recalculate player statistics
  17.     Call Restricted.Login ' compute restrictive time
  18.     Call Rust.Weapon ' get weapon rusting rate
  19.     Call Steal.Treasure ' get treasure stealing rate
  20.     Call Set.Clock ' reset hanging clock
  21.     Call Sorter ' sorts player inventory
  22.     If Room.Rate=False Then ' compare room rate reset
  23.        Call Status.Line(False) ' redisplay status line with player statistics
  24.     Endif
  25.     Call Main.Input ' get and process player input
  26.  Loop ' end main input loop
  27.  End ' prevent drop through of loop into routines
  28.  
  29.  Rem * Configure routine:
  30.  Rem * routine to read command line, dimension and load dynamic arrays,
  31.  Rem * open files, read door file, and read monster class arrays.
  32.  
  33. Sub Read.Config
  34.  On Local Error Resume Next ' local error resume
  35.  Call Get.Command ' read command line
  36.  Call Read.Arrays ' load runtime arrays
  37.  Call Open.Files ' open work files
  38.  Call Read.Door ' read door file
  39.  Call Read.Monclass ' load monster class arrays
  40.  Call System.Type ' store os type
  41.  Call Check.Share ' see if share loaded
  42. End Sub ' end routine to read configure
  43.  
  44.  Rem * routine to process action prompt input. all commands processed
  45.  Rem * in this routine call most major routines.
  46.  
  47. Sub Main.Input
  48.  On Local Error Resume Next ' local error resume
  49.  Graphics.Off=False ' ansi/color on
  50.  Outpt=Action.Prompt ' set prompt (normally Do? is brief, Action? is verbose)
  51.  Upper.Case=True ' set uppercase flag
  52.  Word.Wrap=True ' set word wrap
  53.  Call IO.I ' get player command input
  54.  Upper.Case=False ' reset uppercase flag
  55.  Word.Wrap=False ' reset word wrap
  56.  If Len(Func.Buffer) Then ' process funtion key during remote player on
  57.     Function.Key.Number=Asc(Func.Buffer) ' convert function key to variable
  58.     Func.Buffer=Nul ' reset function key buffer to null
  59.     Call Function.Key(Function.Key.Number) ' process function key
  60.     Exit Sub ' exit routine
  61.  Endif ' end process function key
  62.  Inpt=Ltrim$(Inpt) ' strip leading blanks from command
  63.  If Inpt="?" Then ' command is a question mark
  64.     Graphics.Off=True ' ansi/color to white
  65.     Outpt="Type Hint for for short help, Help for detailed help," ' message
  66.     Call IO.O ' send help output
  67.     Outpt="Catalog for command list, or Commands for detailed command list."
  68.     Call IO.O ' send help output
  69.     Graphics.Off=False ' set ansi/color on
  70.     Exit Sub ' return to main
  71.  Endif ' end question mark command
  72.  If Inpt="??" Then ' check for brief help
  73.     Err=False ' reset error flag
  74.     Redim Array.List(1 To 155) As String*16 ' dimension string array
  75.     If Err=14 Then ' check array size
  76.        Outpt="Out of memory for array." ' make message
  77.        Call IO.O ' send message
  78.        Exit Sub ' exit routine
  79.     Endif ' end check array size
  80.     Restore CommandSet1 ' reset data pointer
  81.     Data.Element=False ' reset data read counter
  82.     For Data.Number=1 To 170 ' loop to read all user commands
  83.        Read Outpt ' read command
  84.        Outpt=Lcase$(Outpt) ' lowercase command
  85.        Mid$(Outpt,1,1)=Ucase$(Mid$(Outpt,1,1)) ' uppercase start
  86.        If Rtrim$(Outpt)<>"<>" Then ' check command name
  87.           Data.Element=Data.Element+1 ' increment data read counter
  88.           Array.List(Data.Element)=Outpt ' store command
  89.        Endif ' end check data read counter
  90.     Next ' end command read loop
  91.     For Sort1=1 To 154 ' bubble sort loop
  92.        For Sort2=Sort1+1 To 154 ' bubble sort inner loop
  93.           If Array.List(Sort1)>Array.List(Sort2) Then ' compare values
  94.              Swap Array.List(Sort1),Array.List(Sort2) ' swap values
  95.           Endif ' end compare values
  96.        Next ' end inner sort
  97.     Next ' end sort loop
  98.     Item.Counter=False ' reset line count
  99.     Line.Counter=2 ' reset page count
  100.     Outpt=Nul ' reset output line
  101.     Previous.Item$=Nul ' reset display item
  102.     For Data.Number=1 To 154 ' loop to read all user commands
  103.        Data.Item$=Rtrim$(Array.List(Data.Number)) ' store command
  104.        If Previous.Item$<>Data.Item$ Then ' compare duplicates
  105.           Previous.Item$=Data.Item$ ' store previous item
  106.           Outpt=Outpt+Data.Item$+Space$(15-Len(Data.Item$)) ' make output line
  107.           Item.Counter=Item.Counter+1
  108.           If Item.Counter=5 Then ' count line length
  109.              Item.Counter=False ' reset line count
  110.              Outpt=Rtrim$(Outpt) ' strip blanks
  111.              Graphics.Off=True ' ansi color off
  112.              Call IO.O ' send output
  113.              Line.Counter=Line.Counter+1 ' increment page count
  114.              If Line.Counter>=User.PageLength Then ' compare to page length
  115.                 Line.Counter=2 ' reset lines counted
  116.                 Call More.Prompt ' routine for more
  117.                 If No Then ' check no reply
  118.                    Exit Sub ' exit routine
  119.                 Endif ' end check reply
  120.              Endif ' end check page count
  121.           Endif ' end counter line length
  122.        Endif ' end compare duplicates
  123.     Next ' end command read loop
  124.     Erase Array.List ' clear temporary array
  125.     Exit Sub ' exit routine
  126.  Endif ' end check help
  127.  Sysop.Command=False ' set sysop entered command flag to false
  128.  If Left$(Inpt,1)="!" Then ' sysop entered a command (sysop prefix of !)
  129.     Sysop.Command=True ' set sysop entered command flag to true
  130.     If Normal.User Then ' verify player has no special character
  131.        Sysop.Command=False ' reset sysop command flag
  132.        Outpt="That command is reserved for DMs only!" ' format message
  133.        Call IO.O ' send output
  134.        Exit Sub ' return to main
  135.     Endif ' end verify normal player
  136.     If Len(Inpt)<=1 Then ' length of command is too brief
  137.        Sysop.Command=False ' reset sysop command flag
  138.        Outpt="That command is reserved for DMs only!" ' message
  139.        Call IO.O ' send output
  140.        Exit Sub ' return to main
  141.     Endif ' end compare command length
  142.     If Inpt="!?" Then ' check for short dm help
  143.        Graphics.Off=True ' ansi color off
  144.        Restore SysopCommands1 ' reset data pointer
  145.        For Last.Command.Number=1 To 18 ' loop to read all nine sysop commands
  146.           Read Outpt ' read command
  147.           If Outpt<>"<>" Then ' check valid command
  148.              Select Case Last.Command.Number ' compare unique command
  149.              Case 1, 2, 3, 4, 5, 6, 7, 9, 12, 14, 16, 17, 18 ' commands
  150.                 Outpt=Lcase$(Outpt) ' lowercase command
  151.                 Mid$(Outpt,1,1)=Ucase$(Mid$(Outpt,1,1)) ' uppercase start
  152.                 Outpt="!"+Outpt ' prepend DM prefix
  153.                 Call IO.O ' send output
  154.              End Select
  155.           Endif ' end check command
  156.        Next ' end command read loop
  157.        Exit Sub ' exit command routine
  158.     Endif
  159.  Endif ' end compute sysop entered a command
  160.  Stored.Parsed.Command1=Inpt ' store the original command entered
  161.  Inpt=Ucase$(Inpt) ' convert original command to upper case
  162.  Stored.Parsed.Command2=Inpt ' store the upper case command
  163.  If Left$(Inpt,1)="\" Then ' verify command is the repeat command character
  164.     User.Command=Previous.Command1 ' restore previous command
  165.     Stored.Parsed.Command1=Previous.Command2 ' restore previous parsed
  166.     Stored.Parsed.Command2=Previous.Command3 ' restore previous parsed
  167.  Else ' not the repeat command
  168.     User.Command=Inpt ' store original command
  169.     Previous.Command1=User.Command ' store original command
  170.     Previous.Command2=Stored.Parsed.Command1 ' store original command
  171.     Previous.Command3=Stored.Parsed.Command2 ' store upper case command
  172.  Endif ' end compare repeat command
  173.  If User.Command=Nul Then ' command entered is null
  174.     Exit Sub ' return to main
  175.  Endif ' end command is null
  176.  Magic.Spell=False ' reset magic spell is being cast flag
  177.  Command.Name=User.Command ' store command entered
  178.  If Instr(Command.Name," ") Then ' check temporary command variable for space
  179.     Command.Name=Left$(Command.Name,Instr(Command.Name," ")-1) ' parse left of
  180.  Endif ' space and store in temporary variable
  181.  Parser=Instr(User.Command," ") ' set parsed flag if command has space
  182.  If Parser=False Then ' check command has no space/parameters
  183.     If Sysop.Command Then ' command entered is sysop command
  184.        Restore SysopCommands1 ' reset data pointer
  185.        Command.Number=False ' set variable containing command number to false
  186.        Command.Name=Mid$(Command.Name,2) ' strip leading ! from command
  187.        For Last.Command.Number=1 To 9 ' loop to read all nine sysop commands
  188.           Read Outpt ' read command
  189.           If Left$(Outpt,Len(Command.Name))=Command.Name Then ' compare to
  190.              Command.Number=Last.Command.Number ' and store command number
  191.              OutX$=Outpt ' store command from data
  192.              Exit For ' exit the loop, command found
  193.           Endif ' end compare
  194.        Next ' end data read loop
  195.        If Command.Number=False Then ' no command found
  196.           Outpt="Unknown command. Type !? for help." ' message
  197.           Call IO.O ' send output
  198.           Exit Sub ' return to main
  199.        Endif ' end check command variable
  200.        Last.Command=OutX$ ' store data command
  201.        Last.Command.Number=Command.Number ' store command number
  202.        Select Case Command.Number ' select routine to call
  203.        Case 1 ' abort function
  204.           Call Abort
  205.        Case 2 ' hint display
  206.           Call Out.File("dmhint.doc")
  207.        Case 3 ' summon random monster
  208.           Call Call.Monster
  209.        Case 4 ' editor routine
  210.           Call Editor ' editor routine
  211.        Case 5 ' read dm help
  212.           Stored.Parsed.Command1="HELP" ' help text to search for
  213.           Call Read.Help(True) ' true equals read dmhelp
  214.        Case 6 ' toggle sysop invisible status
  215.           Call Toggle.Invisible
  216.        Case 7 ' enter room link edit routine
  217.           Call Link.Room
  218.        Case 9 ' display memory, free data space
  219.           Call Display.Memory
  220.        End Select ' end select routine
  221.     Else ' command entered is not sysop command
  222.        If User.Command="OU" Then ' compare player command to parse of OUT
  223.           User.Command="O" ' reset player command to abbreviation of out
  224.        Endif ' end compare player command
  225.        If User.Command="OUT" Then ' compare player command to parse of OUT
  226.           User.Command="O" ' reset player command to abbreviation of out
  227.        Endif ' end compare player command
  228.        ' routine to verify command entered is direction
  229.        Call Get.Direction(Direction.Number)
  230.        If Direction.Number Then ' returned variable true if direction
  231.           Call Go.Direction(Direction.Number) ' routine goes certain direction
  232.           Exit Sub ' return to main
  233.        Endif ' end verify direction entered
  234.        Command.Number=False ' set variable containing command number to false
  235.        Restore CommandSet1 ' reset data pointer
  236.        For Last.Command.Number=1 To 85 ' loop to read all user commands
  237.           Read Last.Command ' read command
  238.           If Command.Name=Left$(Last.Command,Len(Command.Name)) Then  ' compare
  239.              Command.Number=Last.Command.Number ' command from data, left part
  240.              Exit For ' of player command, set variable to command number and
  241.           Endif ' exit data read loop
  242.        Next ' next data item
  243.        If Command.Number=False Then ' loop ended without any matching commands
  244.           Graphics.Off=True ' ansi/color off
  245.           Outpt="Unknown command! Type ? for help or ?? for a brief list of all commands."
  246.           Call IO.O ' send output
  247.           Graphics.Off=False ' ansi/color on
  248.           Exit Sub ' return to main
  249.        Endif ' end command number
  250.        Last.Command.Number=Command.Number ' set command variable to match
  251.        Select Case Command.Number ' select command number
  252.        Case 1 To 4 ' attack commands
  253.           Parsed.Command1=Last.Monster ' restore last monster number attacked
  254.           Last.Command.Number=55 ' attack command number
  255.           Call Attack.Monster ' go attack the monster
  256.        Case 5, 6 ' display the current room
  257.           Call Display.Room
  258.        Case 7, 8 ' panic the character
  259.           Call Panic
  260.        Case 9 ' search the current room
  261.           Call Search.Room
  262.        Case 10, 51 ' update the player file
  263.           Call Put.User.Record ' store the player record
  264.           Outpt="Player file updated." ' message
  265.           Call IO.O ' send output
  266.        Case 11 ' display player information
  267.           Call Display.Stats
  268.        Case 12 ' display player inventory
  269.           Call Display.Inventory
  270.        Case 13 ' kill of the character
  271.           Call Suicide
  272.        Case 14 ' train character (must have 0 experience and enough gold)
  273.           Call Train ' train routine
  274.        Case 15 ' health command
  275.           Call Display.Health
  276.        Case 16 ' appeal for low stats/room w/o exits
  277.           Call Appeal
  278.        Case 17 To 20 ' end session
  279.           Call Quit.Game
  280.        Case 21 ' experience
  281.           Call Display.Experience
  282.        Case 22 ' enter help
  283.           Stored.Parsed.Command1="HELP" ' get help text
  284.           Call Read.Help(False) ' false equals help.dat file
  285.        Case 23 ' hide
  286.           Call Hide.User
  287.        Case 24 ' cast command
  288.           Call Cast.Spell(True) ' true equals enter chant
  289.        Case 25 ' list command
  290.           Call Weapon.List
  291.        Case 26 ' brief mode toggle/must be level 2 at least
  292.           Call Brief.Mode
  293.        Case 27 ' bank command
  294.           Call Bank
  295.        Case 28 To 30 ' display time on/time left
  296.           Call Time.Online
  297.        Case 33 ' ansi on/off
  298.           Call Toggle.ANSI
  299.        Case 39  ' lunge attack command
  300.           Parsed.Command1=Last.Monster ' restore last monster attacked
  301.           Last.Command.Number=39 ' store lunge command number
  302.           Call Attack.Monster ' go attack the monster
  303.        Case 40 ' dodge attack command
  304.           Parsed.Command1=Last.Monster ' restore last monster attacked
  305.           Last.Command.Number=40 ' store dodge command number
  306.           Call Attack.Monster ' go attack the monster
  307.        Case 41 ' display top ten players/create ranklist.dat
  308.           Call Put.User.Record ' store player record
  309.           Call Top.Ten ' generate top ten list
  310.           Call Get.User.Record ' read player record
  311.        Case 42 ' bless w/o parameter
  312.           Call Bless.Self ' therefore bless self
  313.        Case 43 ' curse w/o parameters
  314.           Call Curse.Self ' therefore curse self
  315.        Case 44 ' change password
  316.           Call Change.PassWord ' call routine
  317.           Call Put.User.Record ' put player record
  318.        Case 45 ' mail routine
  319.           Call Mail
  320.        Case 46 ' display list of all players
  321.           Call Put.User.Record ' store player record
  322.           Call User.List ' generate player list
  323.           Call Get.User.Record ' restore player record
  324.        Case 47 ' page sysop
  325.           Call Page.Sysop
  326.        Case 48, 49 ' exit/leave room
  327.           Call Exit.Room
  328.        Case 50 ' climb/go up/up
  329.           Call Climb
  330.        Case 52, 53 ' relogin if player level >1
  331.           Call Relogin
  332.        Case 54 ' display preferences
  333.           Call Display.Prefs ' routine to display preferences
  334.        Case 55 ' change line length
  335.           Call Change.Linelength ' routine to change line length
  336.        Case 56 ' display catalog file
  337.           Call Out.File("catalog.doc") ' display text file
  338.        Case 57 ' toggle linefeed mode
  339.           Call Toggle.Linefeeds ' routine to toggle linefeed mode
  340.        Case 58 ' change pagelength
  341.           Call Change.Pagelength ' routine to change pagelength
  342.        Case 59 ' change echo mode
  343.           Call Toggle.Echo ' routine to toggle echo mode
  344.        Case 60 ' toggle word wrap
  345.           Call Toggle.Wordwrap ' routine to toggle word wrap
  346.        Case 31 To 35 ' attack commands
  347.           Call Attack.Monster ' go attack monster
  348.        Case 61 ' realign once per character
  349.           Call Align
  350.        Case 64 To 75 ' direction entered
  351.           ' set direction of data set number to 1-12
  352.           Direction.Number=Command.Number-63
  353.           ' get the direction and move player
  354.           Call Go.Direction(Direction.Number)
  355.        Case 76 ' display hint file
  356.           Call Out.File("hint.doc") ' display text file
  357.        Case 77 ' toggle inventory sorting preference
  358.           Call Sort.Inventory
  359.        Case 78 ' display summary file
  360.           Call Out.File("summary.doc") ' display text file
  361.        Case 83 ' reroll all character statistics once per character
  362.           Call Reroll.Character
  363.        Case 85 ' wish for an item
  364.           Call Wish.Item
  365.        End Select
  366.     Endif ' end compare player command
  367.  Else ' command has parameter(s)
  368.     Parsed.Command1=Mid$(User.Command,Parser+1) ' get first parsed part of
  369.     Parsed.Command2=Parsed.Command1 ' command and store remaining parsed
  370.     Stored.Parsed.Command1=Mid$(Stored.Parsed.Command1, _
  371.     Instr(Stored.Parsed.Command1," ")+1) ' truncate stored parsed command
  372.     Stored.Parsed.Command2=Mid$(Stored.Parsed.Command2, _
  373.     Instr(Stored.Parsed.Command2," ")+1) ' truncate stored parsed command
  374.     Call Numeric ' store parse number
  375.     If Sysop.Command Then ' command entered is sysop command
  376.        Restore SysopCommands2 ' reset data pointer
  377.        Command.Number=False ' set variable containing command number to false
  378.        Command.Name=Mid$(Command.Name,2) ' strip leading ! from command
  379.        For Last.Command.Number=1 To 9 ' loop to read all nine commands
  380.           Read Outpt ' read command
  381.           If Left$(Outpt,Len(Command.Name))=Command.Name Then ' compare to,
  382.              Command.Number=Last.Command.Number ' set command number variable
  383.              OutX$=Outpt ' store command from data
  384.              Exit For ' exit loop, command found
  385.           Endif ' end compare sysop command
  386.        Next ' end loop through data
  387.        If Command.Number=False Then ' if no matching command in variable
  388.           Outpt="Unknown command. Type !? for help." ' message
  389.           Call IO.O ' send output
  390.           Exit Sub ' return to main
  391.        Endif ' end matching compare
  392.        Last.Command=OutX$ ' store data command
  393.        Last.Command.Number=Command.Number ' store command number
  394.        Select Case Command.Number ' select sysop command number
  395.        Case 2 ' get monster number and call
  396.           Call Summon.Monster
  397.        Case 3 ' get object/treasure name and discard
  398.           Call Discard.Object
  399.        Case 4 ' edit room and room monclass
  400.           Change.Number=Val(Parsed.Command1) ' room number parameter to edit
  401.           If Change.Number>False Then ' check file bounds
  402.              If Change.Number<=Lof(RoomFile)/Len(RoomRecord) Then ' file bounds
  403.                 Call Change.Room(Change.Number) ' edit room number
  404.              Endif ' end check room number range
  405.           Endif ' end check room number range
  406.        Case 5 ' get object/treasure name
  407.           Call Drop.Object ' get from files, drop in room
  408.        Case 6 ' call DM help about command in parameter
  409.           Call DM.Help
  410.        Case 7 ' kill monster name in parameter
  411.           Call Kill.Monster
  412.        Case 8 ' reduce monsters by the value in number parameter
  413.           Call Reduce.Monsters
  414.        Case 9 ' teleport self/online player to room number in parameter
  415.           Call Teleport.User
  416.        End Select ' end select sysop command
  417.     Else ' not sysop command
  418.        Command.Number=False ' set variable containing command number to false
  419.        Restore CommandSet2 ' reset data pointer
  420.        For Last.Command.Number=1 To 85 ' loop to read all user commands
  421.           Read Last.Command ' read command
  422.           If Command.Name=Left$(Last.Command,Len(Command.Name)) Then ' compare
  423.              Command.Number=Last.Command.Number ' to and store command number
  424.              Exit For ' exit read data loop
  425.           Endif ' end compare
  426.        Next ' end data loop
  427.        If Command.Number=False Then ' if command number not matched
  428.           Graphics.Off=True ' ansi/color off
  429.           Outpt="Unknown command! Type ? for help or ?? for a brief list of all commands."
  430.           Call IO.O ' send output
  431.           Graphics.Off=False ' ansi/color on
  432.           Exit Sub ' return to main
  433.        Endif ' end command number match
  434.        Last.Command.Number=Command.Number ' store command number
  435.        Select Case Command.Number ' select command number
  436.        Case 1, 2, 74, 79 ' enter/go object command
  437.           Call Enter.Object
  438.        Case 3 To 5 ' display player information commands
  439.           Call Display.Information
  440.        Case 6 ' cast spell on target
  441.           Call Cast.Spell(False) ' false equals get chant
  442.        Case 7, 8 ' take command
  443.           If Instr(Parsed.Command2," ") Then ' second parameter
  444.              Call Take.From.Container ' must be from container
  445.           Else ' no extra parameters
  446.              Call Take.Object ' must be from room
  447.           Endif ' end compare second parameter
  448.        Case 9, 10 ' drop command
  449.           If Instr(Parsed.Command2," ") Then ' second parameter
  450.              Call Drop.Into.Container ' must be into container
  451.           Else ' no extra parameters
  452.              Call Drop.Item ' must be into room
  453.           Endif ' end compare second parameter
  454.        Case 11, 12 ' sell an item
  455.           Call Pawn.Shop
  456.        Case 13, 14 ' smash commands
  457.           Call Smash.Object
  458.        Case 15 ' close command
  459.           Call Close.Object
  460.        Case 16 ' open command
  461.           Call Open.Object
  462.        Case 17 To 19 ' hold/wield command
  463.           Call Hold.Object
  464.        Case 20 ' wear command
  465.           Call Wear.Object
  466.        Case 21 ' return a weapon command
  467.           Call Return.Object
  468.        Case 22 ' cast spell on target
  469.           Call Cast.Spell(True) ' true equals no chant
  470.        Case 23 ' repair item
  471.           Call Weapons.Shoppe
  472.        Case 24 ' lock command
  473.           Call Lock.Object
  474.        Case 25, 26 ' unlock/picklock commands
  475.           Call Unlock.Object
  476.        Case 27 ' fix command
  477.           Call Fix.Object
  478.        Case 28 ' buy command
  479.           Call Weapons.Shop
  480.        Case 29 ' charge to repair magic item
  481.           Call Alchemist
  482.        Case 30 ' drink command
  483.           Call Drink.Potion
  484.        Case 32 ' throw command
  485.           Call Throw.Object
  486.        Case 33 ' steal command
  487.           Call Steal.Object
  488.        Case 35 ' bless a target
  489.           Call Bless.Object
  490.        Case 36 ' curse a target
  491.           Call Curse.Object
  492.        Case 37 ' fuel command
  493.           Call Fuel.Object
  494.        Case 40, 41 ' talk/parley commands
  495.           Call Talk.To.Monster
  496.        Case 42, 43 ' offer commands
  497.           Call Offer
  498.        Case 44 ' load command
  499.           Call Load.Object
  500.        Case 45 ' fire command
  501.           Call Fire.Object
  502.        Case 46 ' enter vehicle command
  503.           Call Enter.Vehicle
  504.        Case 48, 73 ' ride/go vehicle commands
  505.           Call Ride.Vehicle
  506.        Case 49 ' hide command
  507.           If Instr(Parsed.Command2," ") Then ' second parameter
  508.              Call Drop.Into.Container ' must be hide in container
  509.           Else ' no extra parameters
  510.              Call Drop.Item ' must be hide in room
  511.           Endif ' end check hide parameters
  512.        Case 50 ' search command
  513.           Call Search.Object
  514.        Case 51 ' help w/ parameter of help topic
  515.           Call Read.Help(False) ' read help file
  516.        Case 52 ' identify/extended information
  517.           Call Identify.Object
  518.        Case 55 To 58 ' attack routine
  519.           Last.Command.Number=55
  520.           Call Attack.Monster
  521.        Case 59 To 70, 82 To 85 ' attack routine
  522.           Call Attack.Monster
  523.        Case 71 ' psi mode, attack/defense
  524.           Call Psi.Mode
  525.        Case 72 ' eat command
  526.           Call Eat.Object
  527.        Case 75 ' move command
  528.           Call Move.Object
  529.        Case 76 ' launch command
  530.           Call Launch.Object
  531.        Case 77 ' learn spell, parameter equals spell name to learn
  532.           Call Learn.Spell ' prompts for spell chant
  533.        Case 78 ' light command
  534.           Call Light.Object
  535.        Case 47, 80, 81 ' exit vehicle commands
  536.           Call Exit.Vehicle
  537.        End Select ' end select commmand number
  538.     Endif ' end command type
  539.  Endif ' end parameter type
  540. End Sub ' end command processing
  541.  
  542.  Rem * routine to logoff player and terminate program.
  543.  Rem * any call to this routine results in program termination.
  544.  
  545. Sub Terminate.Program
  546.  On Local Error Resume Next ' local error resume
  547.  Logged.In=False ' reset player logged in flag
  548.  Call Status.Line(-2) ' erase status lines
  549.  Call Put.User.Record ' record player record structure
  550.  Call Clean.Room ' remove extra treasure from room
  551.  Graphics.Off=False ' reset color
  552.  Outpt="Your online time was:" ' make message
  553.  Call IO.O ' display message
  554.  Graphics.Off=True ' reset color
  555.  Call Time.Online ' display time used and time left
  556.  Call More.Prompt ' pause for more
  557.  Call Top.Ten ' top player list
  558.  Call Out.File("logoff.dat") ' display logoff text file
  559.  Outpt="Press "+Enter$+" to exit the adventure:" ' exit program prompt
  560.  No.Echo=True ' no echo of player input
  561.  Line.Length=1 ' get one character
  562.  Call IO.I ' get player input
  563.  No.Echo=False ' reset no echo player input
  564.  Call IO.O ' empty C/R
  565.  Outpt="Returning you to "+BBS.Name+".." ' display return message
  566.  Call IO.O ' send output
  567.  Call Reset.ANSI ' restore local color and remote ansi color
  568.  End ' terminate program
  569. End Sub ' end terminate program routine
  570.  
  571.  Rem * routine to allow player login with another codename.
  572.  
  573. Sub Relogin
  574.  On Local Error Resume Next ' local error resume
  575.  If Normal.User Then ' check non DM
  576.     If UserRecord.Level<=1 Then ' minimum player level requirement to relogin
  577.        Outpt="You can't relogin until level two!" ' display restriction
  578.        Call IO.O ' send output
  579.        Exit Sub ' return from routine
  580.     Endif ' end check minimum level
  581.  Endif ' end check normal player
  582.  Outpt="Are you sure you want to relogin(y/n)? " ' verify player relogin
  583.  No.Input.Out="N" ' default input to no
  584.  Call IO.I ' get player input
  585.  If Yes Then ' verified to suicide
  586.     Logged.In=False ' reset player logged in flag
  587.     Call Put.User.Record ' store player record structure
  588.     Call Clean.Room ' remove extra treasure from room
  589.     Call Login ' get player codename
  590.  Endif ' end check response
  591. End Sub ' end relogin routine
  592.  
  593.  Rem * routine allows player to erase character.
  594.  Rem * sometimes player characters are no longer useful
  595.  Rem * when their statistics become too low.
  596.  
  597. Sub Suicide
  598.  On Local Error Resume Next ' local error resume
  599.  Outpt="Are you sure you want to commit suicide(y/n)? " ' verify player suicide
  600.  No.Input.Out="N" ' default input to no
  601.  Call IO.I ' get player input
  602.  If Yes Then ' verified to suicide
  603.     Logged.In=False ' reset player logged in flag
  604.     Graphics.Off=True ' ansi/color to white
  605.     Outpt="Your character falls into deep sleep.." ' display suicide message
  606.     Call IO.O ' send output
  607.     Outpt="   The Ghods take your player to another world.." ' display
  608.     Call IO.O ' send output
  609.     Graphics.Off=False ' ansi/color to normal
  610.     Call Delete.User ' remove player record from file
  611.     Call Share.Record(UserFile,User.Index) ' put deleted record in player file
  612.     Call Terminate.Program ' end program
  613.  Endif ' end check response
  614. End Sub ' end suicide routine
  615.  
  616.  Rem * routine for normal logoff.
  617.  
  618. Sub Quit.Game
  619.  On Local Error Resume Next ' local error resume
  620.  Graphics.Off=True ' ansi/color to white
  621.  Outpt="Are you sure you want to quit(y/n)? " ' verify player to quit
  622.  No.Input.Out="N" ' default to no
  623.  Call IO.I ' get input
  624.  If Yes Then ' verified to quit
  625.     Logged.In=False ' reset player logged in flag
  626.     Call Terminate.Program ' end program
  627.  Endif ' end check response
  628. End Sub ' end quit routine
  629.  
  630.  Rem * routine to quit and terminate quick.
  631.  
  632. Sub Abort
  633.  On Local Error Resume Next ' local error resume
  634.  Outpt="Are you sure you want to abort(y/n)? " ' verify abort
  635.  No.Input.Out="N" ' default to no
  636.  Call IO.I ' get input
  637.  If Yes Then ' verified yes
  638.     Logged.In=False ' reset player logged in flag
  639.     Outpt="Program task abort!" ' display abort message
  640.     Call IO.O ' output
  641.     Call Put.User.Record ' store player record structure
  642.     Call Reset.ANSI ' restore ansi/color
  643.     Call Status.Line(-2) ' remove status lines
  644.     End ' end program
  645.  Endif ' end check response
  646. End Sub ' end abort routine
  647.  
  648.  Rem * routine reads command line node number 0-9, A-Z, 10-99, and switches.
  649.  
  650. Sub Get.Command
  651.  On Local Error Goto Command.Error ' local error routine
  652.  Locate ,,1 ' turn on cursor
  653.  Max.Row=22 ' set maximum rows on screen before scroll
  654.  Local.Mode=False ' default not local mode
  655.  Node1=False ' reset node number
  656.  Node2=False ' reset node number
  657.  User.Echo=False ' reset preference
  658.  User.LineFeeds=False ' reset preference
  659.  User.LineLength=80 ' reset preference
  660.  User.PageLength=24 ' reset preference
  661.  User.Wordwrap=False ' reset preference
  662.  Command.Line$=Command$ ' store command line
  663.  Do ' loop to remove spaces form command
  664.     Imbedded=Instr(Command.Line$," ") ' check for space
  665.     If Imbedded Then ' verify space
  666.        Command.Line$=Left$(Command.Line$,Imbedded-1)+ _
  667.        Mid$(Command.Line$,Imbedded+1) ' remove space
  668.     Else ' verify space
  669.        Exit Do ' exit no space
  670.     Endif ' end check space
  671.  Loop ' end loop to remove spaces
  672.  If Command.Line$="" Or Command.Line$="/?" Then ' check command
  673.     Goto Command.Error ' jump to command display
  674.  Endif ' end check command
  675.  Imbedded=Instr(Command.Line$,"/P:") ' check port over-ride switch
  676.  If Imbedded Then ' check switch
  677.     Store.Command$=Left$(Command.Line$,Imbedded-1) ' store command line
  678.     Command.Line$=Mid$(Command.Line$,Imbedded+3) ' get remaining command line
  679.     Gosub Get.Numeric ' convert command to value
  680.     Command.Line$=Store.Command$+Command.Line$ ' restore command line
  681.     Port.Value=Int(Val(Value$)) ' store value
  682.     If Port.Value>=1 And Port.Value<=16 Then ' compare value range
  683.        Port.Override=Port.Value ' store value
  684.     Endif ' end compare
  685.     If Port.Override=False Then ' check port value
  686.        Goto Command.Error ' jump to usage
  687.     Endif ' end check port
  688.  Endif ' end check switch
  689.  Imbedded=Instr(Command.Line$,"/B:") ' check baud over-ride switch
  690.  If Imbedded Then ' check switch
  691.     Store.Command$=Left$(Command.Line$,Imbedded-1) ' store command line
  692.     Command.Line$=Mid$(Command.Line$,Imbedded+3) ' get remaining command line
  693.     Gosub Get.Numeric ' convert command to value
  694.     Command.Line$=Store.Command$+Command.Line$ ' restore command line
  695.     Baud.Value!=Int(Val(Value$)) ' store value
  696.     If Baud.Value!>0! Then ' compare value range
  697.        Baud.Override=Cint(Baud.Value!/100!) ' store value
  698.     Endif ' end compare
  699.     If Baud.Override=False Then ' check baud value
  700.        Goto Command.Error ' jump to usage
  701.     Endif ' end check baud
  702.  Endif ' end check switch
  703.  Imbedded=Instr(Command.Line$,"/L") ' check command
  704.  If Imbedded Then ' verify command is local mode
  705.     Command.Line$=Left$(Command.Line$,Imbedded-1)+ _
  706.     Mid$(Command.Line$,Imbedded+2) ' take switch from command
  707.     Command.Line$=Rtrim$(Command.Line$) ' trim command
  708.     Command.Line$=Ltrim$(Command.Line$) ' trim command
  709.     Local.Mode=True ' reset local mode
  710.  Endif ' end verify command switch
  711.  If Len(Command.Line$)=False Then ' check command
  712.     If Local.Mode Or Port.Override Then ' check switches
  713.        Node="<n/a>" ' assign default node type
  714.        Exit Sub ' exit from command line routine
  715.     Endif ' end check switches
  716.  Endif ' end check command
  717.  If Left$(Command.Line$,1)="/" Then ' check for command switch
  718.     Command.Line$=Mid$(Command.Line$,2) ' store command line
  719.     Select Case Len(Command.Line$) ' get length of command line node
  720.     Case 1 ' command line length
  721.        Select Case Command.Line$ ' get command line node number
  722.        Case "0" To "9", "A" To "Z" ' command line node
  723.           Node1=Asc(Command.Line$) ' assign to node type 1 variable
  724.        End Select ' end command line node number
  725.     Case 2 ' command line length
  726.        Select Case Int(Val(Command.Line$)) ' select extended node number
  727.        Case 10 To 99 ' command line node
  728.           Node2=Int(Val(Command.Line$)) ' assign to node type 2 variable
  729.        End Select ' end select node number
  730.     End Select ' end select node number
  731.  Endif ' end check command
  732.  If Node1>False Or Node2>False Then ' verify valid node number
  733.     Exit Sub ' exit routine
  734.  Endif ' end check node number
  735.  
  736. Command.Error:
  737.  Color 15,0 ' color white on black
  738.  Print "Dnddoor usage:"
  739.  Color 14,0 ' color yellow on black
  740.  Print "   Dnddoor [/#] [/L] [/P:x] [/B:<rate>]"
  741.  Color 15,0 ' color white on black
  742.  Print "Where:"
  743.  Color 14,0 ' color yellow on black
  744.  Print "   /# is door node number 0 - 9, A - Z, or 10 - 99."
  745.  Print "   /L to logon without door support."
  746.  Print "   /P:x  over-ride port number (1 to 16)."
  747.  Print "   /B:<rate>  over-ride connect baud rate."
  748.  Color 7,0 ' color white on black
  749.  End ' halt program
  750.  
  751. ' routine to convert string to value
  752. Get.Numeric:
  753.  Value$=Nul ' reset value
  754.  Do ' start convert loop
  755.     Line.Value$=Left$(Command.Line$,1) ' get command line character
  756.     If Line.Value$>="0" And Line.Value$<="9" Then ' check ascii value
  757.        Value$=Value$+Line.Value$ ' store value
  758.        Command.Line$=Mid$(Command.Line$,2) ' get next command character
  759.     Else ' check ascii value
  760.        Exit Do ' exit routine loop
  761.     Endif ' end check ascii value
  762.  Loop ' end convert loop
  763.  Return ' exit form routine
  764. End Sub ' end routine to read command line
  765.  
  766.  Rem * routine reads runtime arrays.
  767.  
  768. Sub Read.Arrays
  769.  On Local Error Goto Arrays.Error ' local error routine
  770.  ' allocate runtime arrays
  771.  Redim Alignment.Name1(1 To 3) As String*7, _
  772.  Alignment.Name2(1 To 3) As String*7, _
  773.  Class.Name(1 To 10) As String*15, _
  774.  Direction(1 To 12) As String*9, _
  775.  High.Class.Name(1 To 10) As String*15, _
  776.  Race(1 To 8) As String*8, _
  777.  Stat(1 To 7) As String*12, _
  778.  Training.Stats(1 To 10,1 To 4) As Integer, _
  779.  Weapon.Type.Name(1 To 4) As String*9
  780.  Restore Config.Data
  781.  For Array.Index1=1 To 10 ' loop through ten class statistic increment array
  782.     For Array.Index2=1 To 4 ' loop through each four class statistic array
  783.        Read Training.Stats(Array.Index1,Array.Index2) ' read statistics
  784.     Next ' loop through
  785.  Next ' loop through
  786.  For Array.Index2=1 To 10 ' loop through high class names
  787.     Read High.Class.Name(Array.Index2) ' read high class names
  788.  Next ' loop through
  789.  For Array.Index2=1 To 8 ' loop through race names
  790.     Read Race(Array.Index2) ' read race names
  791.  Next ' loop through
  792.  For Array.Index2=1 To 10 ' loop through class names
  793.     Read Class.Name(Array.Index2) ' read class names
  794.  Next ' loop through
  795.  For Array.Index2=1 To 7 ' loop through statistic names
  796.     Read Stat(Array.Index2) ' read statistic names
  797.  Next ' loop through
  798.  For Array.Index2=1 To 12 ' loop through direction names
  799.     Read Direction(Array.Index2) ' read direction names
  800.  Next ' loop through
  801.  For Array.Index2=1 To 4 ' loop through weapon proficiency names
  802.     Read Weapon.Type.Name(Array.Index2) ' read weapons proficiency names
  803.  Next ' loop through
  804.  For Array.Index2=1 To 3 ' loop through first set of alignment names
  805.     Read Alignment.Name1(Array.Index2) ' read alignment names
  806.  Next ' loop through
  807.  For Array.Index2=1 To 3 ' loop through second set of alignment names
  808.     Read Alignment.Name2(Array.Index2) ' read alignment names
  809.  Next ' loop through
  810.  Exit Sub ' exit routine
  811. Arrays.Error:
  812.  Color 15, 0 ' color white on black
  813.  Print "Error reading data. Increase RAM size." ' output error message
  814.  Color 7, 0 ' reset color
  815.  End ' halt program
  816. End Sub ' end routine to read arrays
  817.  
  818.  Rem * routine opens runtime file handles.
  819.  
  820. Sub Open.Files
  821.  On Local Error Goto Files.Error ' local error routine
  822.  Close ' close all files
  823.  ' files opened in random mode, opened in share mode for multi access, and each
  824.  ' file record length specified as the length of the random record which will
  825.  ' be used to get/put data to the file. 10 files, 2 mail files. Remaining unopened
  826.  ' files include 2 temp files, 1 help file.
  827.  Open "actions.dat" For Random Shared As #ActionFile Len=Len(ActionRecord)
  828.  Open "messages.dat" For Random Shared As #MessageFile Len=Len(MessageRecord)
  829.  Open "montalk.dat" For Random Shared As #MonTalkFile Len=Len(MonsterTalkRecord)
  830.  Open "monclass.dat" For Random Shared As #MonClassFile Len=Len(MonclassRecord)
  831.  Open "monsters.dat" For Random Shared As #MonsterFile Len=Len(MonsterRecord)
  832.  Open "msgtable.dat" For Random Shared As #TableFile Len=Len(TableRecord)
  833.  Open "nonplyrs.dat" For Random Shared As #NonPlayerFile Len=Len(MonsterRecord)
  834.  Open "objects.dat" For Random Shared As #ObjectFile Len=Len(ObjectRecord)
  835.  Open "rooms.dat" For Random Shared As #RoomFile Len=Len(RoomRecord)
  836.  Open "spells.dat" For Random Shared As #SpellFile Len=Len(SpellRecord)
  837.  Open "treasure.dat" For Random Shared As #TreasureFile Len=Len(TreasureRecord)
  838.  Open "users.dat" For Random Shared As #UserFile Len=Len(UserRecord)
  839.  Exit Sub ' exit routine
  840. Files.Error:
  841.  Color 15, 0 ' color white on black
  842.  ' output error message
  843.  Print "Error"+Str$(Err)+" opening files. Increase files= in config.sys and reboot."
  844.  Color 7, 0 ' reset color
  845.  End ' halt program
  846. End Sub ' end routine to open files
  847.  
  848.  Rem * routine makes door file.
  849.  
  850. Sub Read.Door
  851.  On Local Error Goto Door.Error ' local error routine
  852.  BBS.Name=Nul ' reset name of bbs
  853.  Color.Graphics=True ' default remote ansi color on
  854.  Door.Name=Nul ' reset name of user
  855.  Door.Time=1800! ' reset time remaining
  856.  If Node1 Then ' check node type 1
  857.     Node=Chr$(Node1) ' store node in string form
  858.  Else ' check door node
  859.     If Node2 Then ' check node type 2
  860.        Node=Mid$(Str$(Node2),2) ' store node in string form
  861.     Endif ' end check node
  862.  Endif ' end check node type
  863.  If Local.Mode Then ' verify local command line switch
  864.     BBS.Name="SYSTEM" ' store name of bbs
  865.     Port=False ' reset modem port
  866.     Modem.Baud=96 ' reset modem baud
  867.     Door.Name="LOCAL SYSOP" ' store name of user
  868.     Color.Type=2 ' store color value
  869.     Exit Sub ' exit door file routine
  870.  Endif ' end verify local switch
  871.  If Node1=False And Node2=False Then ' check node type
  872.     BBS.Name="SYSTEM" ' store name of bbs
  873.     Port=False ' reset modem port
  874.     Modem.Baud=96 ' reset modem baud
  875.     Door.Name="REMOTE USER" ' store name of user
  876.     Color.Type=2 ' store color value
  877.     If Port.Override Then ' verify port number for no node
  878.        Port=Port.Override-1 ' store port value
  879.     Endif ' end check port/node
  880.     If Baud.Override Then ' check baud value for no node
  881.        Modem.Baud=Baud.Override ' store baud value
  882.     Endif ' end check baud/node
  883.     Call Set.Driver ' init baud rate
  884.     Exit Sub ' exit routine
  885.  Endif ' end check node type
  886.  If Len(Node)=1 Then ' check node length
  887.     FileName="DORINFO"+Node+".DEF" ' make door info filename
  888.     If Dir$(Filename)=Filename Then ' check file exists
  889.        Call Read.Door.File ' routine to read door file
  890.        Exit Sub ' exit door file routine
  891.     Endif ' end check file
  892.  Endif ' end check node length
  893.  FileName="DINF"+Node+".DEF" ' make door info filename
  894.  If Dir$(Filename)=Filename Then ' check file exists
  895.     Call Read.Door.File ' routine to read door file
  896.     Exit Sub ' exit door file routine
  897.  Endif ' end check file
  898. Door.Error:
  899.  Color 15, 0 ' color white on black
  900.  Print "Error reading door node "+Node+" information file." ' output error message
  901.  Color 7, 0 ' reset color
  902.  End ' halt program
  903. End Sub ' end routine to read door file
  904.  
  905.  Rem * routine reads door file.
  906.  
  907. Sub Read.Door.File
  908.  On Local Error Goto Read.Door.Error
  909.  Close #TempFile ' close work file
  910.  Open FileName For Input Shared As #TempFile ' open the door file for input
  911.  For Door.File.Line=1 To 13 ' loop through all lines in door file
  912.     Line Input #TempFile,Inpt ' read next text line from door file
  913.     Inpt=Ucase$(Inpt) ' convert text string to upper case
  914.     Select Case Door.File.Line ' select which line to process
  915.     Case 1 ' line one
  916.        BBS.Name=Inpt ' store name of bbs
  917.     Case 4 ' line four
  918.        Port=Val(Mid$(Inpt,4,1)) ' set port to value of rightmost character
  919.        If Port=False Then ' port zero speficies local console mode
  920.           Local.Mode=True ' set local mode flag
  921.        Else ' other port number
  922.           Port=Port-1 ' convert modem comm (1-8) to modem port (0-7)
  923.           If Port.Override Then ' check over-ride switch
  924.              Port=Port.Override-1 ' store value
  925.           Endif ' end check switch
  926.        Endif ' end compare port number
  927.     Case 5 ' line five
  928.        Input.Length=Instr(Inpt," ")-3 ' get baud rate
  929.        Inpt=Left$(Inpt,Input.Length) ' store rate
  930.        Modem.Baud=Int(Val(Inpt)) ' store modem baud rate
  931.        If Baud.Override Then ' check over-ride switch
  932.           Modem.Baud=Baud.Override ' store value
  933.        Endif ' end check switch
  934.     Case 7 ' line seven
  935.        Door.Name=Inpt ' store name of user
  936.        If Left$(Inpt,5)="SYSOP" Then ' compare user name to 'sysop'
  937.           Local.Mode=True ' set local mode flag
  938.        Endif 'end compare user name
  939.     Case 8 ' line eight
  940.        If Len(Inpt) Then ' compare length of user last name
  941.           Door.Name=Door.Name+" "+Inpt ' append user last name
  942.        Endif ' end compare user name length
  943.     Case 10 ' line ten
  944.        Color.Type=Int(Val(Inpt)) ' get value of text line
  945.        If Color.Type<2 Then ' compare graphics preference
  946.           Color.Graphics=False ' value other than two sets graphics off
  947.        Endif ' end compare graphcis
  948.     Case 12 ' line twelve
  949.        Door.Time=Val(Inpt)*60! ' store value of text line of remaining time
  950.     End Select ' end process line
  951.  Next ' end loop through file
  952.  Call Set.Driver
  953.  Exit Sub ' exit routine
  954. Read.Door.Error:
  955.  Color 15, 0 ' color white on black
  956.  Print "Error reading door information file: "+FileName ' output error message
  957.  Color 7, 0 ' reset color
  958.  End ' halt program
  959. End Sub ' end routine to read door file
  960.  
  961.  Rem * routine loads runtime file data.
  962.  
  963. Sub Read.Monclass
  964.  On Local Error Goto Monclass.Error ' local error routine
  965.  Locate ,,1 ' turn on cursor
  966.  Monclass.Max=Lof(MonClassFile)/Len(MonclassRecord) ' compute number of records
  967.  If Monclass.Max=False Then ' monster class file, compare to minimum
  968.     Monclass.Max=1 ' and increment if none found
  969.     For Monster.Classes=1 To 10 ' loop through all monsters in class
  970.        MonclassRecord.Monsters(Monster.Classes)=False ' reset to empty
  971.     Next ' end loop
  972.     Call Share.Record(MonClassFile,1) ' write first monster class record if empty
  973.  Endif ' end compare length of file
  974.  ' check upper bounds on monclass file
  975.  If Monclass.Max>1024 Then ' check bounds
  976.     Monclass.Max=1024 ' reset maximum
  977.  Endif ' end check bounds
  978.  ' allocate monster class, rate, and percent arrays
  979.  Redim Monster.Class(1 To Monclass.Max,1 To 10) As Integer, _
  980.  Monster.Percent(1 To Monclass.Max,1 To 10) As Integer, _
  981.  Monster.Rate(1 To Monclass.Max,1 To 10) As Integer
  982.  ' loop through all monster classes in file
  983.  For Monster.Classes=1 To Monclass.Max
  984.     Call Read.Record(MonClassFile,Monster.Classes) ' read monster class record
  985.     For Monster.Class.Number=1 To 10 ' loop through all monsters in record
  986.        ' get monster number in class
  987.        Monster.Array.Number=MonclassRecord.Monsters(Monster.Class.Number)
  988.        ' store in monster class array
  989.        Monster.Class(Monster.Classes,Monster.Class.Number)= _
  990.        Monster.Array.Number
  991.        If Monster.Array.Number>False And _
  992.           Monster.Array.Number<=Lof(MonsterFile)/Len(MonsterRecord) Then
  993.           ' read monster number from monster file
  994.           Call Read.Record(MonsterFile,Monster.Array.Number)
  995.           ' store encounter rate
  996.           Monster.Rate(Monster.Classes,Monster.Class.Number)= _
  997.           MonsterRecord.Rate
  998.           ' store encounter rate percent
  999.           Monster.Percent(Monster.Classes,Monster.Class.Number)= _
  1000.           MonsterRecord.RatePercent
  1001.        Endif ' end compare file bounds
  1002.     Next ' end loop through ten monsters in class
  1003.  Next ' end loop through all monster classes
  1004.  Max.Spells=Lof(SpellFile)/Len(SpellRecord) ' get number of spell records
  1005.  ' check bounds of spell file
  1006.  If Max.Spells>1024 Then ' check bounds
  1007.     Max.Spells=1024 ' reste maximum
  1008.  Endif ' end check bounds
  1009.  Spell.Number=Len(Learned.Spells) ' get length of learned spells array
  1010.  If Max.Spells>Spell.Number Then ' compare spells length
  1011.     ' extended array
  1012.     Learned.Spells=Learned.Spells+String$(Max.Spells-Spell.Number,"0")
  1013.  Endif ' end compare length
  1014.  Exit Sub ' exit routine
  1015. Monclass.Error:
  1016.  Color 15, 0 ' color white on black
  1017.  Print "Error reading arrays. Increase RAM size." ' output error message
  1018.  Color 7, 0 ' reset color
  1019.  End ' halt program
  1020. End Sub ' end configure routine
  1021.  
  1022.  Rem * routine determines if share is loaded
  1023.  
  1024. Sub Check.Share
  1025.  On Local Error Resume Next ' local error resume
  1026.  Inregs.AX=&H1000 ' store dos function call
  1027.  Call Interrupt(&H2F,Inregs,Outregs) ' call multiplex interrupt
  1028.  If (Outregs.AX And &HFF)=&HFF Then ' compare share loaded
  1029.     Share.Installed=True ' store share variable
  1030.  Else ' compare share loaded
  1031.     Share.Installed=False ' store share variable
  1032.  Endif ' end compare share loaded
  1033.  If Win.Major=False Then ' check os type
  1034.     If DOS.Major=7 Then ' check dos type
  1035.        If DOS.Minor=10 Then ' check dos type
  1036.           Share.Installed=False ' disable share for dos 7.10
  1037.        Endif ' end check type
  1038.     Endif ' end check type
  1039.  Endif ' end check os type
  1040. End Sub ' end routine to check for share loaded
  1041.  
  1042.  Rem * routine matches online baud rate.
  1043.  
  1044. Sub Set.Driver
  1045.  On Local Error Resume Next ' local error resume
  1046.  If Local.Mode Then ' check online mode
  1047.     Exit Sub ' return from routine
  1048.  Endif ' end check online mode
  1049.  Call Driver(&H0400) ' initialize port
  1050.  Select Case Modem.Baud ' select baud rate to match
  1051.  Case 3 ' 300 baud
  1052.     Modem.Speed=&H0043 ' calculate baud bits
  1053.  Case 6 ' 600 baud
  1054.     Modem.Speed=&H0063 ' calculate baud bits
  1055.  Case 12 ' 1200 baud
  1056.     Modem.Speed=&H0083 ' calculate baud bits
  1057.  Case 24 ' 2400 baud
  1058.     Modem.Speed=&H00A3 ' calculate baud bits
  1059.  Case 48 ' 4800 baud
  1060.     Modem.Speed=&H00C3 ' calculate baud bits
  1061.  Case 96, 144 ' multiple bauds (set to 9600)
  1062.     Modem.Speed=&H00E3 ' calculate baud bits
  1063.  Case 192, 288 ' multiple bauds (set to 19200)
  1064.     Modem.Speed=&H0003 ' calculate baud bits
  1065.  Case 384, 576, 786, 1152, 2304 ' multiple bauds (set to 38400)
  1066.     Modem.Speed=&H0023 ' calculate baud bits
  1067.  End Select ' end calculate baud bits
  1068.  Call Driver(Modem.Speed) ' set computer to modem baud rate
  1069. End Sub ' end routine to match baud rates
  1070.  
  1071.  Rem * routine to give back time slice in tight loops to multi systems.
  1072.  Rem * input variables:
  1073.  Rem *   Var - number of slices to give back
  1074.  Rem * processing variables:
  1075.  Rem *   Supported.Call - stores valid call flag
  1076.  
  1077. Sub Release.Time(Var)
  1078.  On Local Error Resume Next ' local error resume
  1079.  Static Supported.Call ' define valid call flag
  1080.  If Supported.Call=False Then ' check flag already implemented
  1081.     For Var2=1 To Var ' loop through slices to give
  1082.        Inregs.AX=&H1680 ' set bios call
  1083.        Inregs.BX=&H0000 ' set bios call
  1084.        Call Interrupt(&H2F,Inregs,Outregs) ' call bios routine
  1085.        If (Outregs.AX And &HFF)=&H80 Then ' verify supported call
  1086.           Supported.Call=True ' reset flag
  1087.           Exit For ' exit call loop
  1088.        Endif ' end verify supported call
  1089.     Next ' end slice loop
  1090.  Endif ' end check flag
  1091. End Sub ' end time slice routine
  1092.  
  1093.  Rem * standard output routine to send data to the screen and modem.
  1094.  Rem * input variables:
  1095.  Rem *   Allow.Break - set to true to allow control-k checking.
  1096.  Rem *   Carriage.Return - set to true to suppress cr/lf after output.
  1097.  Rem *   Outpt - contains text to output to screen/modem.
  1098.  Rem * output variables:
  1099.  Rem *   Break - set to true if user entered control-k.
  1100.  Rem *   Carriage.Return, Outpt - reset to zero/null.
  1101.  Rem * processing variables:
  1102.  Rem *   Char.Output$ - character to send to modem/screen.
  1103.  Rem *   Count - loop variable for character of output sent.
  1104.  
  1105. Sub IO.O
  1106.  On Local Error Resume Next ' local error resume
  1107.  If Len(Outpt) Then ' check length of output string
  1108.     Call Out.ANSI ' routine to output ansi sequence to modem/color code locally
  1109.  Endif ' end check output string
  1110.  Count=False ' reset output character counter
  1111.  Do ' output characters loop
  1112.     Call Keyboard(Keyboard.Break) ' routine reads keyboard
  1113.     If Break Then ' check break flag
  1114.        Exit Do ' exit output loop
  1115.     Endif ' end check break flag
  1116.     Count=Count+1 ' increment output counter
  1117.     Gosub IO.Wrap ' subroutine to word wrap
  1118.     If Count>Len(Outpt) Then ' check length of output
  1119.        Exit Do ' exit output loop
  1120.     Endif ' end check length of output
  1121.     Char.Output$=Mid$(Outpt,Count,1) ' get single character to output
  1122.     Call Put.Modem(Char.Output$) ' send character to modem
  1123.     Call Scrn(Char.Output$) ' send character to screen
  1124.  Loop ' output character loop
  1125.  If Carriage.Return=False Then ' check output cr/lf suppressed
  1126.     If Break=False Then ' check control-k flag
  1127.        Call Line.Return ' routine to send cr/lf to modem/screen
  1128.     Endif ' end check control-k flag
  1129.  Endif ' end check i/o cr/lf
  1130.  Carriage.Return=False ' reset supressed cr/lf
  1131.  Outpt=Nul ' reset output
  1132.  Exit Sub ' exit routine
  1133.  
  1134.  ' subroutine to word wrap
  1135. IO.Wrap:
  1136.  If User.Linelength=False Then ' check linelength
  1137.     Return ' exit subroutine
  1138.  Endif ' end check of linelength
  1139.  Select Case User.Wordwrap ' check word wrap preference
  1140.  Case True ' word wrap toggled off
  1141.     If Pos(0)>=User.Linelength Then ' check line length
  1142.        If Mid$(Outpt,Count,1)=" " Then ' check wrapped space
  1143.           Count=Count+1 ' increment space from loop
  1144.        Endif ' end check wrapped space
  1145.        If Count<=Len(Outpt) Then ' check end of line
  1146.           Call Line.Return ' send cr/lf
  1147.        Endif ' check eol
  1148.     Endif ' end check line length
  1149.  Case False ' word wrap toggled on
  1150.     Space.Wrap=Instr(Count+1,Outpt," ") ' store next word
  1151.     If Space.Wrap Then ' find first imbedded space
  1152.        Word$=Mid$(Outpt,Count) ' truncate word
  1153.        Space.Wrap=Instr(2,Word$," ") ' store next word
  1154.        Word$=Left$(Word$,Space.Wrap-1) ' store remaining output of line
  1155.     Else ' store empty remaining word to wrap
  1156.        If Mid$(Outpt,Count,1)=" " Then ' verify last possible word
  1157.           Word$=Mid$(Outpt,Count) ' store last remaining word
  1158.        Else ' calculate last word
  1159.           Word$=Nul ' store empty word
  1160.        Endif ' end calculate last word
  1161.     Endif ' end storing next word to send
  1162.     ' compute line position plus next word
  1163.     If Pos(0)+Len(Word$)>User.Linelength Then
  1164.        If Mid$(Outpt,Count,1)=" " Then ' check next word is space
  1165.           Count=Count+1 ' increment space from loop
  1166.        Endif ' end check next word is space
  1167.        Call Line.Return ' next word wraps, send cr/lf
  1168.     Endif ' end compute wrap length
  1169.  End Select ' end select word wrap preference
  1170.  Return ' exit subroutine
  1171. End Sub ' end routine to send a string to the modem and screen
  1172.  
  1173.  Rem * standard input routine to get data from the keyboard and modem.
  1174.  Rem * input variables:
  1175.  Rem *   Buffer - any previous user input stored during output.
  1176.  Rem *   Carriage.Return - set to true to suppress cr/lf after output.
  1177.  Rem *   Hide - flag to echo mask characters in place of input.
  1178.  Rem *   Line.Length - maximum characters allowed to input.
  1179.  Rem *   No.Echo - do not echo user input.
  1180.  Rem *   No.Input.Out - string to use if no input entered.
  1181.  Rem *   Outpt - contains input prompt.
  1182.  Rem *   Word.Wrap - allow words entered to wrap.
  1183.  Rem * output variables:
  1184.  Rem *   Inpt - contains user input string.
  1185.  Rem *   No.Input - flag set if return entered.
  1186.  Rem *   No - set if N was entered.
  1187.  Rem *   Yes - set if Y was entered.
  1188.  Rem *   Quit - set if Q was entered.
  1189.  Rem * processing variables:
  1190.  Rem *   Buffered.Input$ 0 stores buffered input to add to next input prompt.
  1191.  Rem *   Char$ - current character received from modem/keyboard.
  1192.  Rem *   Char - ascii code of character input.
  1193.  Rem *   Line.Limit - stores length of input line during input.
  1194.  Rem *   Time.Out! - current time character input loop entered.
  1195.  Rem *   Word - set if a word wrapped.
  1196.  Rem *   OutY$, Valid.Char$, Last.Wrap, Last.Word - local work variables.
  1197.  
  1198. Sub IO.I
  1199.  On Local Error Resume Next ' local error resume
  1200.  Static Buffered.Input$ ' stores data input between calls to input routine
  1201.  If Pos(0)>1 Then ' check io supressed cr/lf
  1202.     Call Line.Return ' make cr/lf before input prompt
  1203.  Endif ' end check previous supressed cr/lf
  1204.  Carriage.Return=True ' set cr/lf flag
  1205.  Line.Limit=Len(Outpt) ' reset length of line for io.o
  1206.  Outpt=Outpt+Buffered.Input$ ' add stored data input to input prompt
  1207.  Call IO.O ' output the input prompt
  1208.  Inpt=Buffered.Input$ ' reset input string+data input between calls
  1209.  Buffered.Input$=Nul ' reset data input between calls
  1210.  Do ' loop through input characters
  1211.     Char$=Nul ' reset input character
  1212.     Time.Out!=Timer ' set time loop entered
  1213.     Do While Char$=Nul ' loop until received a character
  1214.        Gosub IO.Timing ' routine to calculate timing values
  1215.        Call Keyboard(Keyboard.Break) ' routine to get any keyboard input
  1216.        ' keyboard input received is a function key/extended key
  1217.        If Keyboard.Break Then
  1218.           Buffer=Nul ' reset type ahead buffer
  1219.           Carriage.Return=False ' reset cr/lf flag
  1220.           No.Input.Out=Nul ' reset null input echo string
  1221.           Exit Sub ' exit routine to process extended keyboard input
  1222.        Endif ' end check keyboard routine flag
  1223.        Call Get.Modem(Input.Char) ' routine to get character from modem
  1224.        If Input.Char Then ' modem input in return variable
  1225.           ' append modem input to buffer variable
  1226.           Buffer=Buffer+Chr$(Input.Char)
  1227.        Endif ' end check modem for character
  1228.        If Len(Buffer) Then ' check buffer contents
  1229.           Char$=Left$(Buffer,1) ' get first buffer character
  1230.           Buffer=Mid$(Buffer,2) ' store buffer minus first character
  1231.        Endif ' end check buffer
  1232.        Call Release.Time(1) ' give up time slice
  1233.     Loop ' end loop until character received
  1234.     Char=Asc(Char$) ' convert character string to ascii integer
  1235.     Select Case Char ' process character ascii integer
  1236.     Case 8 ' backspace
  1237.        If Len(Inpt) Then ' check length of input
  1238.           Inpt=Left$(Inpt,Len(Inpt)-1) ' strip off last character from input
  1239.           Call Back.Space ' routine to send backspace codes
  1240.        Endif ' end check string length
  1241.     Case 13 ' return key
  1242.        If Inpt=Nul Then ' no input in string
  1243.           If Len(No.Input.Out) Then ' check null input echo string
  1244.              Inpt=No.Input.Out ' set input string to default input string
  1245.              OutY$=Lcase$(No.Input.Out) ' convert null input string
  1246.              Call Scrn(OutY$) ' send string to screen
  1247.              If User.Echo=False Then ' check echo mode
  1248.                 Call Put.Modem(OutY$) ' send string to modem
  1249.              Endif ' end check echo mode
  1250.           Endif ' end check null input flag
  1251.        Endif ' end check null input
  1252.        Call Scrn(Chr$(13)) ' send carriage return to screen
  1253.        If User.Echo=False Then ' check echo mode
  1254.           Call Put.Modem(Chr$(13)) ' send carriage return to modem
  1255.        Endif ' end check echo mode
  1256.        Exit Do ' end routine after return key prssed/return input string
  1257.     Case 32 To 127 ' remaining valid input ascii codes
  1258.        If Inpt=Nul Then ' check length of stored input
  1259.           If Upper.Case Then ' verify force uppercase
  1260.              Char$=Ucase$(Char$) ' change first character to uppercase
  1261.           Endif ' end verify force
  1262.        Endif ' end check length
  1263.        Valid.Char$=Char$ ' store character
  1264.        If No.Echo=False Then ' check echo flag
  1265.           If Hidden Then ' check hide flag
  1266.              Valid.Char$=Mask$ ' echo mask character
  1267.           Endif ' end check hide flag
  1268.           If User.Echo=False Then ' check echo mode
  1269.              Call Put.Modem(Valid.Char$) ' echo character entered to modem
  1270.           Endif ' end check echo mode
  1271.           If Word.Wrap=False Then ' check word wrap flag
  1272.              Call Scrn(Valid.Char$) ' echo character entered to screen
  1273.           Endif ' end check word wrap flag
  1274.        Endif ' end check echo flag
  1275.        Inpt=Inpt+Char$ ' append character input to input string
  1276.        ' check echo and word wrap
  1277.        If No.Echo=False And Word.Wrap And User.Wordwrap=False Then
  1278.           Select Case Len(Inpt)+Line.Limit ' check length of input+line length
  1279.           Case 0 To User.Linelength-2 ' position to left, no word wrap
  1280.              Call Scrn(Valid.Char$) ' send echo character
  1281.           Case Else ' position to left, word wrap
  1282.              Last.Word=False ' counter of characters at last word to wrap
  1283.              Word=False ' set flag for word wrapped
  1284.              ' loop through last word reverse
  1285.              For Last.Wrap=Len(Inpt) To 1 Step -1
  1286.                 If Mid$(Inpt,Last.Wrap,1)=" " Then ' locate space of word
  1287.                    For Word.Break=1 To Last.Word ' loop through length of word
  1288.                       Call Back.Space ' routine to backspace
  1289.                    Next ' end loop through word
  1290.                    ' store wrapped word for next i/o
  1291.                    Buffered.Input$=Mid$(Inpt,Last.Wrap+1)
  1292.                    ' truncate word from input string
  1293.                    Inpt=Left$(Inpt,Last.Wrap)
  1294.                    Call Scrn(Chr$(13)) ' send return
  1295.                    Word=True ' word has wrapped flag
  1296.                    Exit For ' end loop for a space
  1297.                 Endif ' end check space location
  1298.                 Last.Word=Last.Word+1 ' increment last word wrapped counter
  1299.              Next
  1300.              If Word=False Then ' check flag for word wrapped
  1301.                 Call Scrn(Chr$(13)) ' send return to screen
  1302.              Endif ' end check word wrapped flag
  1303.              Call Put.Modem(Chr$(13)) ' send return to modem
  1304.              Exit Do ' end input loop
  1305.           End Select ' end check length of input+line length
  1306.        Else ' word wrap flag not set
  1307.           If Line.Length>False Then ' check line length variable
  1308.              If Len(Inpt)>=Line.Length Then ' check input string length
  1309.                 Call Scrn(Chr$(13)) ' send return to screen
  1310.                 Call Put.Modem(Chr$(13)) ' send return to modem
  1311.                 Exit Do ' exit input loop
  1312.              Endif ' end check input string length
  1313.           Else ' check line length
  1314.              ' check right column
  1315.              If Len(Inpt)+Line.Limit>User.Linelength-2 Then
  1316.                 Call Scrn(Chr$(13)) ' send return to screen
  1317.                 Call Put.Modem(Chr$(13)) ' send return to modem
  1318.                 Exit Do ' exit input loop
  1319.              Endif ' end check line limit
  1320.           Endif ' end check line length
  1321.        Endif ' end check word wrap
  1322.     End Select ' end select character ascii code
  1323.  Loop ' end input loop
  1324.  Carriage.Return=False ' reset output cr/lf flag
  1325.  Outpt=Nul ' reset input prompt
  1326.  No.Echo=False ' reset echoing mask character flag
  1327.  No.Input=False ' reset null input flag
  1328.  Line.Length=False ' reset length of input line
  1329.  If Inpt=Nul Then ' check input string to null
  1330.     No.Input=True ' set null input flag
  1331.  Endif ' end check input string length
  1332.  No.Input.Out=Nul ' reset echo string for null input flag
  1333.  If User.Linefeeds=False Then ' check linefeed mode
  1334.     If User.Echo=False Then ' check echo mode
  1335.        Call Put.Modem(Chr$(10)) ' send linefeed
  1336.     Endif ' end check echo mode
  1337.  Endif ' end check linefeed mode
  1338.  Word.Char$=Ucase$(Left$(Inpt,1)) ' get uppercase of first character of input
  1339.  No=(Word.Char$="N") ' set no flag (user entered N as first character)
  1340.  Yes=(Word.Char$="Y") ' set yes flag (user entered Y as first character)
  1341.  Quit=(Word.Char$="Q") ' set quit flag (user entered Q as first character)
  1342.  Continue=(Word.Char$="C") ' set continuous flag
  1343.  Exit Sub ' exit routine to get input string in Inpt
  1344.  
  1345.  Rem * subroutine to verify time limits.
  1346.  
  1347. IO.Timing:
  1348.  ' routine to calculate input timing
  1349.  Call Second.Timer(Time.Expired,Time.Out!,180!)
  1350.  If Time.Expired Then ' timing has expired
  1351.     Call Hang.Up(1) ' routine to hang up modem with message
  1352.  Endif ' end check timing
  1353.  ' routine to calculate time on
  1354.  Call Second.Timer(Time.Expired,Timeon,Time.Left)
  1355.  If Time.Expired Then ' time limit has expired
  1356.     Call Hang.Up(2) ' routine to hang up modem with message
  1357.  Endif ' end check time limit
  1358.  If Two.Minutes.Left=False Then ' check two minutes message flag
  1359.     ' calculate two minutes time
  1360.     Call Second.Timer(Time.Expired,Timeon,Time.Left-120!)
  1361.     If Time.Expired Then ' time has expired, user has two minutes left
  1362.        Two.Minutes.Left=True ' set two minutes message flag
  1363.        Outpt=Nul ' reset output string
  1364.        Call IO.O ' send null return
  1365.        Call Put.Modem(Chr$(7)) ' send beep to modem
  1366.        Outpt="Two Minutes Left!" ' send two minutes remaining message
  1367.        Call IO.O ' to modem
  1368.     Endif ' end check two minutes
  1369.  Endif ' end check two minutes flag
  1370.  Return ' end timing subroutine
  1371. End Sub ' end routine to get input string in Inpt
  1372.  
  1373.  Rem * Routine to send a string to the modem.
  1374.  Rem * input variables:
  1375.  Rem *   Allow.Break - set if control-k checking allowed.
  1376.  Rem *   Local.Mode - flag if the console is operating program.
  1377.  Rem *   Output$ - string to send.
  1378.  Rem * output variables:
  1379.  Rem *   Break - flag set if control-k entered.
  1380.  Rem *   Buffer - any input from modem during output.
  1381.  Rem * processing variables:
  1382.  Rem *   Char - ascii code of character to send.
  1383.  Rem *   Count - loop variable of output string sent.
  1384.  Rem *   Input.Char - local work variable.
  1385.  
  1386. Sub Put.Modem(Output$)
  1387.  On Local Error Resume Next ' local error resume
  1388.  If Local.Mode=False Then ' check if local mode is activated
  1389.     For Count=1 To Len(Output$) ' loop through output string
  1390.        Call Get.Modem(Input.Char) ' routine to get data from modem
  1391.        If Input.Char Then ' character received from modem
  1392.           If Input.Char=11 Then ' check if character is control-k
  1393.              If Allow.Break Then ' check if break allowed
  1394.                 Break=True ' set break flag
  1395.                 Exit Sub ' end routine
  1396.              Endif ' end check break allowed
  1397.           Else ' any other character
  1398.              Buffer=Buffer+Chr$(Input.Char) ' append to input buffer
  1399.           Endif ' end check character is control-k
  1400.        Endif ' end check character received
  1401.        ' convert output string character to ascii
  1402.        Char=Asc(Mid$(Output$,Count,1))
  1403.        Call Driver(&H0100+Char) ' driver routine/send character
  1404.     Next ' end loop through output string
  1405.  Endif ' end check local mode
  1406. End Sub ' end routine to send output to modem
  1407.  
  1408.  Rem * Routine to get a character from the modem.
  1409.  Rem * input variables:
  1410.  Rem *   Local.Mode - flag if console is operating system.
  1411.  Rem * output variables:
  1412.  Rem *   Input.Char - character received from modem.
  1413.  Rem * processing variables:
  1414.  Rem *   Outregs - register of modem status.
  1415.  
  1416. Sub Get.Modem(Input.Char)
  1417.  On Local Error Resume Next ' local error resume
  1418.  Input.Char=False ' set received character to zero
  1419.  If Local.Mode=False Then ' check if local mode is activated
  1420.     Call Driver(&H0300) ' driver routine/get modem status
  1421.     If (Outregs.AX And &HFF)=&HFF Then ' check modem port status
  1422.        Call Status.Line(-2) ' routine to clear lower two console status areas
  1423.        Color 15, 0 ' reset color
  1424.        Outpt=Chr$(13)+"Termination of Dnddoor from missing modem."+Chr$(13)
  1425.        Call Scrn(Outpt) ' send message
  1426.        Outpt="Logoff: port"+Str$(Port)+" at "+FNclock$+", node "+Node+"."+Chr$(13)
  1427.        Call Scrn(Outpt) ' send message
  1428.        Color 7, 0 ' reset color
  1429.        End ' terminate program
  1430.     Endif ' end check carrier
  1431.     If (Outregs.AX And &H80)=False Then ' check modem carrier status
  1432.        Call Status.Line(-2) ' routine to clear lower two console status areas
  1433.        Color 15, 0 ' reset color
  1434.        Outpt=Chr$(13)+"Termination of Dnddoor from lost carrier."+Chr$(13)
  1435.        Call Scrn(Outpt) ' send message
  1436.        Outpt="Logoff: port"+Str$(Port)+" at "+FNclock$+", node "+Node+"."+Chr$(13)
  1437.        Call Scrn(Outpt) ' send message
  1438.        Color 7, 0 ' reset color
  1439.        End ' terminate program
  1440.     Endif ' end check carrier
  1441.     If (Outregs.AX And &H0100)=&H0100 Then ' check character receive ready
  1442.        Call Driver(&H0200) ' driver routine/read character
  1443.        Input.Char=Outregs.AX And &HFF ' return lower byte of register received
  1444.     Endif ' end check character received ready
  1445.  Endif ' end check local mode
  1446. End Sub ' end routine to get a character from the modem
  1447.  
  1448.  Rem * routine to call the dos function for modem access.
  1449.  Rem * input variables:
  1450.  Rem *   Sub.Function - the Bios call 0, 1, 2, 3, or 4.
  1451.  Rem * output variables:
  1452.  Rem *   Outregs - register values of the modem.
  1453.  
  1454. Sub Driver(Sub.Function)
  1455.  On Local Error Resume Next ' local error resume
  1456.  Inregs.AX=Sub.Function ' modem function plus parameters
  1457.  Inregs.DX=Port ' modem port line 0 to 3
  1458.  Call Interrupt(&H14,Inregs,Outregs) ' modem dos function hexidecimal 14
  1459. End Sub ' end routine to call modem function
  1460.  
  1461.  Rem * routine to calculate elapsed time
  1462.  Rem * input variables:
  1463.  Rem *   Start.Time! - equals stored start time from Timer function.
  1464.  Rem *   Wait.Time! - equals elapsed time to calculate in seconds.
  1465.  Rem * output variables:
  1466.  Rem *   Time.Expired - set to true if Wait.Time has elapsed.
  1467.  Rem * working variables:
  1468.  Rem *   Time.Elapsed! - contains time difference.
  1469.  
  1470. Sub Second.Timer(Time.Expired,Start.Time!,Wait.Time!)
  1471.  On Local Error Resume Next ' local error resume
  1472.  Time.Expired=False ' set return flag time has not expired
  1473.  Time.Elapsed!=Timer-Start.Time! ' calculate time elapsed from start time
  1474.  If Time.Elapsed!<0! Then ' check if midnight has passed
  1475.     Time.Elapsed!=Time.Elapsed!+86400! ' increment calculated time elapsed
  1476.  Endif ' end check midnight passed
  1477.  ' compare calculated elapsed time to wait time
  1478.  If Time.Elapsed!>=Wait.Time! Then
  1479.     Time.Expired=True ' set return flag time has expired
  1480.  Endif ' end compare times
  1481. End Sub ' end routine to calculate time
  1482.  
  1483. Rem * Routine to adjust system clock during midnight errors.
  1484.  
  1485. Sub Set.Clock
  1486.  On Local Error Resume Next ' local error resume
  1487.  If Time$>"23:59:59" Then ' compare system time to midnight
  1488.     Sleep 2 ' wait for two seconds for system date to change
  1489.     If Time$="24:00:00" Then ' system clock is stuck
  1490.        Time$="00:00:01" ' reset system time past midnight
  1491.     Endif ' end check stuck system clock
  1492.  Endif ' end check incorrect midnight time
  1493. End Sub ' end routine to adjust system clock
  1494.  
  1495.  Rem * Routine to get and process keyboard entry.
  1496.  Rem * output variables:
  1497.  Rem *   Keyboard.Break - true to exit from IO.I when function key pressed.
  1498.  Rem * work variables:
  1499.  Rem *   Keyboard.Char$ - contains key pressed.
  1500.  
  1501. Sub Keyboard(Keyboard.Break)
  1502.  On Local Error Resume Next ' local error resume
  1503.  Keyboard.Break=False ' reset extended/function key input flag
  1504.  Keyboard.Char$=Nul ' reset next keyboard character
  1505.  Inregs.AX=&H600 ' read direct console function
  1506.  Inregs.DX=&H0FF ' read subfunction
  1507.  Call Interrupt(&H21,Inregs,Outregs) ' routine reads keyboard
  1508.  If (Outregs.Flags And &H40)=&H0 Then ' check zero flag
  1509.     Keyboard.Char$=Chr$(Outregs.AX And &HFF) ' store next character
  1510.     If Asc(Keyboard.Char$)=0 Then ' check for ascii zero
  1511.        Inregs.AX=&H600 ' read direct console function
  1512.        Inregs.DX=&H0FF ' read subfunction
  1513.        Call Interrupt(&H21,Inregs,Outregs) ' routine reads keyboard
  1514.        Keyboard.Char$=Chr$(0)+Chr$(Outregs.AX And &HFF) ' store extended key
  1515.     Endif ' end check ascii
  1516.  Endif ' end check zero flag
  1517.  Select Case Len(Keyboard.Char$) ' process keyboard character type
  1518.  Case 0 ' nothing entered
  1519.     Exit Sub ' end routine
  1520.  Case 1 ' single keystroke
  1521.     Select Case Asc(Keyboard.Char$) ' process single key
  1522.     Case 8, 13, 32 To 127 ' valid keys entered during i/o
  1523.        Buffer=Buffer+Keyboard.Char$ ' append keystroke to buffer
  1524.     Case 11 ' control-k
  1525.        If Allow.Break Then ' check break allowed
  1526.           Break=True ' set break flag
  1527.        Endif ' end check break allowed
  1528.     Case 27 ' escape key
  1529.        If Chat Then ' check in chat flag
  1530.           Chat=False ' set chat exit flag
  1531.           Keyboard.Break=True ' set function/extended key flag
  1532.        Else ' escape key at console
  1533.           If Logged.In Then ' check player in game
  1534.              Call Status.Line(True) ' toggles status line area
  1535.           Endif ' end check player logged in game
  1536.        Endif ' end check flag
  1537.     End Select ' end sigle keystroke
  1538.  Case 2 ' function/extended key
  1539.     Select Case Asc(Right$(Keyboard.Char$,1)) ' process extended key code
  1540.     Case 79 ' end key/terminate key
  1541.        Call Hang.Up(4) ' routine to hang up modem with message
  1542.        Keyboard.Break=True ' set function/extended key flag
  1543.     Case 71 ' home key/chat key
  1544.        If Chat=False Then ' check if already in chat
  1545.           If Local.Mode=False Then ' check local mode not activated
  1546.              If Logged.In Then ' check user logged in flag
  1547.                 Chat=True ' set in chat flag
  1548.                 Call Enter.Chat ' routine to chat with user
  1549.                 Chat=False ' reset in chat flag
  1550.                 Keyboard.Break=True ' set function/extended key flag
  1551.              Endif ' end check user logged in
  1552.           Endif ' end check local mode
  1553.        Endif ' end check chat flag
  1554.     Case 59 To 68 ' function key entered
  1555.        If Logged.In Then ' check user logged in flag
  1556.           Func.Buffer=Right$(Keyboard.Char$,1) ' store function key in buffer
  1557.           Keyboard.Break=True ' set function/extended key flag
  1558.        Endif ' end check user logged in
  1559.     End Select ' end process extended key code
  1560.  End Select ' end process keyboard character type
  1561. End Sub ' end routine to get/process keyboard entry
  1562.  
  1563.  Rem * Routine to send carriage return/linefeed (cr/lf) to screen/modem.
  1564.  
  1565. Sub Line.Return
  1566.  On Local Error Resume Next ' local error resume
  1567.  Call Scrn(Chr$(13)) ' send return character to screen
  1568.  Call Put.Modem(Chr$(13)) ' send cr to modem
  1569.  If User.Linefeeds=False Then ' check linefeed mode
  1570.     Call Put.Modem(Chr$(10)) ' send lf to modem
  1571.  Endif ' end check linefeed mode
  1572. End Sub ' end routine to send cr/lf
  1573.  
  1574.  Rem * Routine to backspace over one previous character.
  1575.  
  1576. Sub Back.Space
  1577.  On Local Error Resume Next ' local error resume
  1578.  ' Store current screen location of cursor column minus one
  1579.  Cursor.Column=Pos(0)-1
  1580.  Locate Csrlin,Cursor.Column,0 ' locate back one space, cursor off
  1581.  Print " "; ' erase character with space
  1582.  Locate Csrlin,Cursor.Column,1 ' locate back one space, cursor on
  1583.  If User.Echo=False Then ' check echo mode
  1584.     Call Put.Modem(Chr$(8)+" "+Chr$(8)) ' send backspace to modem
  1585.  Endif ' end check echo mode
  1586. End Sub ' end routine to backspace
  1587.  
  1588.  Rem * Routine to change color. ANSI to modem, COLOR statement to screen.
  1589.  
  1590. Sub Out.ANSI
  1591.  On Local Error Resume Next ' local error resume
  1592.  Ansi.ColorCode=37 ' default to ANSI white
  1593.  If Graphics.Off=False Then ' check graphics color change flag
  1594.     Color.Code=Color.Code+1 ' increment current ANSI color variable
  1595.     If Color.Code<31 Or Color.Code>36 Then ' check ANSI color bounds
  1596.        Color.Code=31 ' reset to base ANSI color
  1597.     Endif ' end check color bounds
  1598.     Ansi.ColorCode=Color.Code ' store new color code
  1599.  Endif ' end check graphics change flag
  1600.  Call Modem.ANSI(Ansi.ColorCode) ' send ANSI color code number
  1601. End Sub ' end routine to change color
  1602.  
  1603.  Rem * Routine to send ANSI color change code to modem/screen.
  1604.  Rem * input variables:
  1605.  Rem *   Ansi.ColorCode - contains the Ansi color code number.
  1606.  Rem * work variables:
  1607.  Rem *   Ansi.Output$ - stores the Ansi string to send.
  1608.  
  1609. Sub Modem.ANSI(Ansi.ColorCode)
  1610.  On Local Error Resume Next ' local error resume
  1611.  Call Convert.Color(Ansi.ColorCode) ' change screen color
  1612.  If Color.Graphics Then ' check remote ANSI graphics flag
  1613.     ' construct ANSI code
  1614.     Ansi.Output$=Chr$(27)+"[0;1;"+Mid$(Str$(Ansi.ColorCode),2)+"m"
  1615.     Call Put.Modem(Ansi.Output$) ' send code to modem
  1616.  Endif ' end check remote ANSI flag
  1617. End Sub ' end routine to send ANSI code
  1618.  
  1619.  Rem * Routine to reset ANSI color code to default.
  1620.  Rem * work variables:
  1621.  Rem *   Ansi.Output$ - stores the default Ansi color string.
  1622.  
  1623. Sub Reset.ANSI
  1624.  On Local Error Resume Next ' local error resume
  1625.  If Color.Graphics Then ' check remote ANSI graphics flag
  1626.     Ansi.Output$=Chr$(27)+"[0;37m" ' construct ANSI black on white code
  1627.     Call Put.Modem(Ansi.Output$) ' send code to modem
  1628.  Endif ' end check remote ANSI flag
  1629.  Color 7,0 ' reset local screen to black on white
  1630.  Print Nul; ' display a zero length string to change color
  1631. End Sub ' end routine to reset ANSI color code
  1632.  
  1633.  Rem * Routine to change local screen color to ANSI color code number.
  1634.  Rem * input variables:
  1635.  Rem *   Ansi.ColorCode - the Ansi color code number.
  1636.  Rem * work variables:
  1637.  Rem *   Scrn.ColorCode - stores the CGA screen color number.
  1638.  
  1639. Sub Convert.Color(Ansi.ColorCode)
  1640.  On Local Error Resume Next ' local error resume
  1641.  Select Case Ansi.ColorCode ' choose ANSI color code number
  1642.  Case 31 ' ANSI red
  1643.     Scrn.ColorCode=12 ' COLOR statement red
  1644.  Case 32 ' ANSI green
  1645.     Scrn.ColorCode=10 ' COLOR statement green
  1646.  Case 33 ' ANSI yellow
  1647.     Scrn.ColorCode=14 ' COLOR statement yellow
  1648.  Case 34 ' ANSI blue
  1649.     Scrn.ColorCode=9 ' COLOR statement blue
  1650.  Case 35 ' ANSI magenta
  1651.     Scrn.ColorCode=13 ' COLOR statement magenta
  1652.  Case 36 ' ANSI cyan
  1653.     Scrn.ColorCode=11 ' COLOR statement cyan
  1654.  Case 37 ' ANSI white
  1655.     Scrn.ColorCode=15 ' COLOR statement white
  1656.  Case Else ' default ANSI white
  1657.     Scrn.ColorCode=15 ' COLOR statement white
  1658.  End Select ' end choose ANSI color code
  1659.  Color Scrn.ColorCode,0 ' change screen color
  1660. End Sub ' end routine to change local screen color
  1661.  
  1662.  Rem * Routine to process stored function key pressed during remote play.
  1663.  Rem * input variables:
  1664.  Rem *   FunctionKey.Number - the ascii value of the extended function key.
  1665.  
  1666. Sub Function.Key(FunctionKey.Number)
  1667.  On Local Error Resume Next ' local error resume
  1668.  If Logged.In=False Then ' check user is logged in
  1669.     Exit Sub ' exit routine
  1670.  Endif ' end check user logged in
  1671.  If Local.Mode Then ' check console is logged in
  1672.     Select Case FunctionKey.Number ' choose function key number
  1673.     Case 59 ' F1 - !Edit
  1674.        Call IO.O ' empty output
  1675.        Call Editor ' editor routine
  1676.     Case 60 ' F2 - !Status
  1677.        Call IO.O ' empty output
  1678.        Call Display.Memory ' routine to display memory stats
  1679.     Case 61 ' F3 - !Discard
  1680.        Outpt=Action.Prompt+"!DISCARD " ' display action prompt plus command
  1681.        Call IO.I ' get item to discard
  1682.        Parsed.Command1=Ucase$(Inpt) ' store item name
  1683.        Call Discard.Object ' routine to discard item from player inventory
  1684.     Case 62 ' F4 - !Reduce
  1685.        Outpt=Action.Prompt+"!REDUCE " ' display action prompt plus command
  1686.        Call IO.I ' get number
  1687.        Parsed.Command1=Inpt ' store number
  1688.        Call Reduce.Monsters ' routine to reduce monsters in room
  1689.     Case 63 ' F5 - !Call
  1690.        Outpt=Action.Prompt+"!CALL " ' display action prompt plus command
  1691.        Call IO.I ' get monster number
  1692.        Parsed.Command1=Inpt ' store monster number
  1693.        Call Summon.Monster ' routine to get a monster into room
  1694.     Case 64 ' F6 - !Kill
  1695.        Outpt=Action.Prompt+"!KILL " ' display action prompt plus command
  1696.        Call IO.I ' get monster name
  1697.        Parsed.Command1=Ucase$(Inpt) ' store monster name
  1698.        Parsed.Command2=Parsed.Command1 ' store monster name
  1699.        Call Kill.Monster ' routine to kill monster name
  1700.     Case 65 ' F7 - !Teleport
  1701.        Outpt=Action.Prompt+"!TELEPORT " ' display action prompt plus command
  1702.        Call IO.I ' get room number
  1703.        Parsed.Command1=Inpt ' store room number
  1704.        Parsed.Command2=Parsed.Command1 ' store room number
  1705.        Call Teleport.User ' routine to teleport user to a room number
  1706.     Case 66 ' F8 - !Invisibility
  1707.        Call IO.O ' empty output
  1708.        Call Toggle.Invisible ' routine to toggle invisibility mode
  1709.     Case 67 ' F9 - !Get
  1710.        Outpt=Action.Prompt+"!GET " ' display action prompt plus command
  1711.        Call IO.I ' get item name
  1712.        Inpt=Ucase$(Inpt) ' store item name
  1713.        Stored.Parsed.Command2=Inpt ' store item name
  1714.        Call Drop.Object ' routine to get an item
  1715.     Case 68 ' F9 - !Link
  1716.        Call IO.O ' empty output
  1717.        Call Link.Room ' routine to add/remove room links
  1718.     End Select ' end select function key number
  1719.     Exit Sub ' exit routine
  1720.  Endif ' end check console logged in
  1721.  Inpt=Nul ' reset input string
  1722.  Outpt=Nul ' reset output string
  1723.  Call IO.O ' send empty cr/lf
  1724.  Select Case FunctionKey.Number ' choose function key number
  1725.  Case 59 ' F1 - !Edit
  1726.     Outpt="System Operator is using the editor. Please wait.." ' send message
  1727.     Call IO.O ' sysop will edit during game
  1728.     Call Put.User.Record ' store user stats
  1729.     Local.Mode=True ' set local mode
  1730.     Outpt="Sysop: Enter room number to edit, or press enter to start !Edit:"
  1731.     Call IO.O ' write local sysop info message
  1732.     Outpt=Action.Prompt+"!EDIT " ' display action prompt plus command
  1733.     Call IO.I ' get room number to edit(if any)
  1734.     If Inpt<>Nul Then ' determine edit room number
  1735.        Room.Number=Int(Val(Inpt)) ' room number parameter to edit
  1736.        If Room.Number>False And _
  1737.        Room.Number<=Lof(RoomFile)/Len(RoomRecord) Then ' range
  1738.           Call Change.Room(Room.Number) ' edit room from number parameter
  1739.        Endif ' end compare room number range
  1740.     Else ' edit users
  1741.       Call Editor ' editor routine
  1742.     Endif ' end determine edit prompt
  1743.     Local.Mode=False ' reset local mode
  1744.  Case 60 ' F2 - !Status
  1745.     Local.Mode=True ' reset local mode
  1746.     Call Display.Memory ' routine to display memory stats
  1747.     Local.Mode=False ' restore local mode
  1748.  Case 61 ' F3 - !Discard
  1749.     Local.Mode=True ' reset local mode
  1750.     Outpt="Sysop: Enter player inventory treasure name to discard:"
  1751.     Call IO.O ' write local sysop info message
  1752.     Outpt=Action.Prompt+"!DISCARD " ' display action prompt plus command
  1753.     Call IO.I ' get item to discard
  1754.     Parsed.Command1=Ucase$(Inpt) ' store item name
  1755.     Call Discard.Object ' routine to discard item from player inventory
  1756.     Local.Mode=False ' restore local mode
  1757.  Case 62 ' F4 - !Reduce
  1758.     Local.Mode=True ' reset local mode
  1759.     Outpt="Sysop: Enter number of monsters in room to reduce to:"
  1760.     Call IO.O ' write local sysop info message
  1761.     Outpt=Action.Prompt+"!REDUCE " ' display action prompt plus command
  1762.     Call IO.I ' get number
  1763.     Parsed.Command1=Inpt ' store number
  1764.     Call Reduce.Monsters ' routine to reduce monsters in room
  1765.     Local.Mode=False ' restore local mode
  1766.  Case 63 ' F5 - !Call
  1767.     Local.Mode=True ' reset local mode
  1768.     Outpt="Sysop: Enter name or number of monster to call:"
  1769.     Call IO.O ' write local sysop info message
  1770.     Outpt=Action.Prompt+"!CALL " ' display action prompt plus command
  1771.     Call IO.I ' get monster number
  1772.     Local.Mode=False ' restore local mode
  1773.     Parsed.Command1=Inpt ' store monster number
  1774.     Call Summon.Monster ' routine to get a monster into room
  1775.  Case 64 ' F6 - !Kill
  1776.     Local.Mode=True ' reset local mode
  1777.     Outpt="Sysop: Enter name of monster in room to kill off:"
  1778.     Call IO.O ' write local sysop info message
  1779.     Outpt=Action.Prompt+"!KILL " ' display action prompt plus command
  1780.     Call IO.I ' get monster name
  1781.     Local.Mode=False ' restore local mode
  1782.     Parsed.Command1=Ucase$(Inpt) ' store monster name
  1783.     Parsed.Command2=Parsed.Command1 ' store monster name
  1784.     Call Kill.Monster ' routine to kill monster name
  1785.  Case 65 ' F7 - !Teleport
  1786.     Local.Mode=True ' reset local mode
  1787.     Outpt="Sysop: Enter number of room to teleport player to:"
  1788.     Call IO.O ' write local sysop info message
  1789.     Outpt=Action.Prompt+"!TELEPORT " ' display action prompt plus command
  1790.     Call IO.I ' get room number
  1791.     Local.Mode=False ' restore local mode
  1792.     Parsed.Command1=Inpt ' store room number
  1793.     Parsed.Command2=Parsed.Command1 ' store room number
  1794.     Call Teleport.User ' routine to teleport user to a room number
  1795.  Case 66 ' F8 - !Invisibility
  1796.     Call Toggle.Invisible ' routine to toggle invisibility mode
  1797.  Case 67 ' F9 - !Get
  1798.     Local.Mode=True ' reset local mode
  1799.     Outpt="Sysop: Enter name of treasure item to get from treasure file:"
  1800.     Call IO.O ' write local sysop info message
  1801.     Outpt=Action.Prompt+"!GET " ' display action prompt plus command
  1802.     Call IO.I ' get item name
  1803.     Local.Mode=False ' restore local mode
  1804.     Inpt=Ucase$(Inpt) ' store item name
  1805.     Stored.Parsed.Command2=Inpt ' store item name
  1806.     Call Drop.Object ' routine to get an item
  1807.  Case 68 ' F10 - !Link
  1808.     Outpt="System Operator is using the editor. Please wait.." ' send message
  1809.     Call IO.O ' sysop will edit during game
  1810.     Local.Mode=True ' reset local mode
  1811.     Call Link.Room ' routine to add/remove room links
  1812.     Local.Mode=False ' restore local mode
  1813.  End Select ' end choose function key number
  1814.  Outpt=Nul ' reset output string
  1815.  Inpt=Nul ' reset input string
  1816. End Sub ' end routine to process game function keys
  1817.  
  1818.  Rem * Routine to hang up modem with a message.
  1819.  Rem * input variables:
  1820.  Rem *   HangUp.Type - the hang up message to display.
  1821.  
  1822. Sub Hang.Up(HangUp.Type)
  1823.  On Local Error Resume Next ' local error resume
  1824.  Allow.Break=False ' disable break
  1825.  Break=False ' reset control-k flag
  1826.  Buffer=Nul ' reset buffer
  1827.  Func.Buffer=Nul ' reset function key buffer
  1828.  Graphics.Off=True ' turn off graphics color changing
  1829.  Inpt=Nul ' set input string to null
  1830.  Outpt=Nul ' set output string to null
  1831.  Timeon=Timer ' store current time in time on variable
  1832.  Time.Left=180 ' store 3 minutes remaining in variable
  1833.  Call IO.O ' empty output
  1834.  Outpt="Dnddoor terminating at "+FNclock$+", "+Node+"." ' make message
  1835.  Call IO.O ' send message
  1836.  Select Case HangUp.Type ' choose hang up message
  1837.  Case 1 ' type 1
  1838.     Outpt="Connect timeout"
  1839.  Case 2 ' type 2
  1840.     Outpt="Time limit exceeded"
  1841.  Case 4 ' type 4
  1842.     Outpt="Forced logoff"
  1843.  Case 5 ' type 5
  1844.     Outpt="Call limit exceeded"
  1845.  Case 6 ' type 6
  1846.     Call Restriction.Notice ' routine to display restricted time
  1847.  Case 7 ' type 7
  1848.     Outpt="Illegal login attempt"
  1849.  Case 8 ' type 8
  1850.     Outpt="Password verification!"
  1851.  End Select ' end choose hang up message
  1852.  Outpt="Reason: "+Outpt+"."
  1853.  Call IO.O ' display message
  1854.  Call Status.Line(-2) ' clear status line areas
  1855.  Color 7,0 ' reset screen color
  1856.  End ' terminate program
  1857. End Sub ' end routine to hang up modem
  1858.  
  1859.  Rem * Routine to put a character on the screen at current row/column.
  1860.  Rem * input variables:
  1861.  Rem *   Scrn.Char$ - the character to display.
  1862.  
  1863. Sub Scrn(Scrn.Char$)
  1864.  On Local Error Resume Next ' local error resume
  1865.  Row=Csrlin-1 ' calculate current row, minus one for bios offset
  1866.  Column=Pos(0)-1 ' calculate current column, minus one for bios offset
  1867.  Select Case Row ' compare current row
  1868.  Case Is>Max.Row ' will scroll past max.row (status area)
  1869.     Call Scroll.Screen ' scroll the screen
  1870.  Case Max.Row ' scroll at max.row (status area)
  1871.     If Column=User.LineLength Then ' verify column to scroll
  1872.        Print; ' force screen scroll from basic
  1873.        If Scrn.Char$=Chr$(13) Then ' check cr/lf at corner
  1874.           Exit Sub ' return from routine
  1875.        Endif ' end check corner cr/lf
  1876.     Endif ' end verify column
  1877.  End Select ' end compare row
  1878.  Print Scrn.Char$; ' display character at row, column
  1879. End Sub ' end routine to display a character on screen
  1880.  
  1881.  Rem * Routine to scroll screen at Max.Row.
  1882.  ' ----------1006-------------------------------
  1883.  ' INT 10 - VIDEO - SCROLL UP WINDOW
  1884.  '          AH = 06h
  1885.  '          AL = number of lines by which to scroll up
  1886.  '          BH = attribute used to write blank lines at bottom of window
  1887.  '          CH,CL = row,column of window's upper left corner
  1888.  '          DH,DL = row,column of window's lower right corner
  1889. Sub Scroll.Screen
  1890.  On Local Error Resume Next ' local error resume
  1891.  Inregs.AX=&H0601 ' function AH=06, scroll 1 lines
  1892.  Inregs.BX=&H0700 ' attribute of blank line, white on black
  1893.  Inregs.CX=&H0000 ' upper left corner, 0,0
  1894.  Inregs.DX=Max.Row*256+&H4F ' lower right corner, DH=Max.Row,DL=80
  1895.  Call Interrupt(&H10,Inregs,Outregs) ' routine for BIOS call, function Hex10
  1896.  Locate Max.Row+1,1 ' set cursor at lower row, column 1
  1897. End Sub ' end routine to scroll screen
  1898.  
  1899.  Rem * Routine to make users restricted time online output message.
  1900.  
  1901. Sub Restriction.Notice
  1902.  On Local Error Resume Next ' local error resume
  1903.  Outpt="Your calls are restricted from" ' start of message
  1904.  Restrict.Time=UserRecord.FromHour ' store users hour of restricted time
  1905.  If Restrict.Time>12 Then ' compare 24 hour format time to standard time
  1906.     Outpt=Outpt+Str$(UserRecord.FromHour-12) ' decrement to 24 hour format
  1907.     Inpt="pm" ' 24 hour indicator
  1908.  Else ' compare to standard time
  1909.     Outpt=Outpt+Str$(UserRecord.FromHour) ' store hour format
  1910.     Inpt="am" ' 12 hour indicator
  1911.  Endif ' end compare time type
  1912.  ' format string of restricted time from, plus minutes
  1913.  Outpt=Outpt+":"+Right$(Str$(UserRecord.FromMin+100),2)+Inpt+" to"
  1914.  Restrict.Time=UserRecord.ToHour ' store users hour of restricted time
  1915.  If Restrict.Time>12 Then ' compare 24 hour format time to standard time
  1916.     Outpt=Outpt+Str$(UserRecord.ToHour-12) ' decrement to 24 huur format
  1917.     Inpt="pm" ' 24 hour indicator
  1918.  Else ' compare to standard time
  1919.     Outpt=Outpt+Str$(UserRecord.ToHour) ' store hour format
  1920.     Inpt="am" ' 12 hour indicator
  1921.  Endif ' end compare time type
  1922.  ' format string of restricted time to, plus minutes
  1923.  Outpt=Outpt+":"+Right$(Str$(UserRecord.ToMin+100),2)+Inpt+"."
  1924. End Sub ' end routine to make restricted time message
  1925.  
  1926.  Rem * Routine to display a text file.
  1927.  Rem * input variables:
  1928.  Rem *   File.Output$ - filename of file to display.
  1929.  Rem * processing variables:
  1930.  Rem *   Allow.Break - flag to allow control-k.
  1931.  Rem *   Break - set to true if control-k pressed.
  1932.  Rem *   Continue - set to true for continuous output
  1933.  Rem *   Page.Length, Page.Break - paginating variables.
  1934.  
  1935. Sub Out.File(File.Output$)
  1936.  On Local Error Goto OutFile.Error ' local error routine
  1937.  Graphics.Off=True ' turn off graphics color changing
  1938.  File.Page=User.Pagelength ' store pagelength
  1939.  If File.Page=False Then ' check pagelength
  1940.     File.Page=24 ' reset pagelength
  1941.  Endif ' end check pagelength
  1942.  Allow.Break=True ' turn on allow break flag
  1943.  Break=False ' reset control-k flag
  1944.  Continue=False ' reset continuous flag
  1945.  Page.Length=False ' reset page counter
  1946.  Close #TempFile ' close temporary file
  1947.  If Dir$(File.Output$)=Nul Then ' check file exists
  1948.     Outpt="File "+File.Output$+" not found." ' make output
  1949.     Call IO.O ' send output
  1950.     Goto Outfile.Exit ' jump to exit
  1951.  Endif ' end check file exists
  1952.  Open File.Output$ For Random Shared As #TempFile Len=1 ' open the file
  1953.  If Lof(TempFile)=False Then ' check file length
  1954.     Outpt="File "+File.Output$+" length zero." ' make output
  1955.     Call IO.O ' send output
  1956.     Goto Outfile.Exit ' jump to exit
  1957.  Endif ' end check file length
  1958.  Close #TempFile ' close temporary file
  1959.  Open File.Output$ For Input Shared As #TempFile ' open the file
  1960.  Do While Not Eof(TempFile) ' loop through all the text in file
  1961.     Line Input #TempFile,Outpt ' get the next text line
  1962.     Call IO.O ' display the text line
  1963.     If Break Then ' check control-k pressed
  1964.        Exit Do ' exit text input loop
  1965.     Endif ' end check control-k
  1966.     Page.Length=Page.Length+1 ' increment line displayed counter
  1967.     If Page.Length=File.Page Then ' compare page counter
  1968.        Page.Length=False ' reset page counter
  1969.        If Continue=False Then ' check continuous flag
  1970.           Call More.Prompt ' routine to prompt for more
  1971.           If No Then ' check more prompt returned no flag
  1972.              Exit Do ' exit text input loop
  1973.           Endif ' end check more prompt no flag
  1974.        Endif ' end check page counter
  1975.     Endif ' end check continuous flag
  1976.  Loop ' end text file input loop
  1977.  Allow.Break=False ' reset allow break flag
  1978.  If Break Then ' check control-k flag
  1979.     Break=False ' reset control-k flag
  1980.     Outpt=Nul ' set output to null
  1981.     Call IO.O ' send empty return
  1982.  Endif ' end check control-k flag
  1983.  Graphics.Off=False ' reset graphics color changer
  1984.  If Page.Length Then ' check page counter
  1985.     Call More.Prompt ' routine to prompt for more
  1986.  Endif ' end check page counter
  1987. OutFile.Exit:
  1988.  Allow.Break=False ' reset allow break flag
  1989.  Break=False ' reset control-k flag
  1990.  Graphics.Off=False ' reset color change flag
  1991.  Exit Sub ' exit routine
  1992. OutFile.Error:
  1993.  Resume OutFile.Exit
  1994. End Sub ' end routine to display a text file
  1995.  
  1996.  Rem * Routine to display the more prompt.
  1997.  Rem * work variables:
  1998.  Rem *   Allow.Type - store break flag type
  1999.  Rem *   Graphics.Type - stores graphics cycling variable.
  2000.  
  2001. Sub More.Prompt
  2002.  On Local Error Resume Next ' local error resume
  2003.  Allow.Type=Allow.Break ' store break type
  2004.  Allow.Break=False ' disable break during prompt
  2005.  Graphics.Type=Graphics.Off ' store graphics changing flag
  2006.  Graphics.Off=False ' turn off graphics changing
  2007.  Outpt=More$ ' get the more prompt
  2008.  Line.Length=1 ' allow one key input
  2009.  No.Echo=True ' do not echo any key
  2010.  Call IO.I ' input routine
  2011.  Allow.Break=Allow.Type ' restore break type
  2012.  Graphics.Off=Graphics.Type ' restore graphics changing flag
  2013. End Sub
  2014.  
  2015.  Rem * Routine to restrict a room direction to a players level.
  2016.  Rem * input variable:
  2017.  Rem *   Room.Direction - direction to restrict.
  2018.  Rem * output variable:
  2019.  Rem *   Direction.Restricted - set true to restrict player.
  2020.  Rem * work variables:
  2021.  Rem *   Action.Number - contains the room action number.
  2022.  
  2023. Sub Restrict(Room.Direction,Direction.Restricted)
  2024.  On Local Error Resume Next ' local error resume
  2025.  Direction.Restricted=False ' reset return variable
  2026.  Action.Number=RoomRecord.Action ' store room action number
  2027.  If Action.Number>False And _
  2028.  Action.Number<=Lof(ActionFile)/Len(ActionRecord) Then ' check file bounds
  2029.     Call Read.Record(ActionFile,Action.Number) ' read action record
  2030.     Select Case ActionRecord.Level ' determine player level
  2031.     Case Is>False ' player at least room level
  2032.        If UserRecord.Level<ActionRecord.Level Then ' compare levels
  2033.           ' compare room direction
  2034.           If ActionRecord.Restrictions And 2^Room.Direction Then
  2035.              Direction.Restricted=True ' direction restricted flag
  2036.           Endif ' end compare room direction
  2037.        Endif ' end compare levels
  2038.     Case Is<False ' player at most room level
  2039.        If UserRecord.Level>Abs(ActionRecord.Level) Then ' compare levels
  2040.           ' compare room direction
  2041.           If ActionRecord.Restrictions And 2^Room.Direction Then
  2042.              Direction.Restricted=True ' direction restricted flag
  2043.           Endif ' end compare room direction
  2044.        Endif ' end compare levels
  2045.     End Select ' end choose room/player level
  2046.  Endif ' end check file bounds
  2047. End Sub ' end routine to restrict room entrance
  2048.  
  2049.  Rem * Routine to restrict a room direction to entry type.
  2050.  Rem * output variable:
  2051.  Rem *   Direction.Restricted - set true to restrict player.
  2052.  Rem * work variables:
  2053.  Rem *   Action.Number - contains the room action number.
  2054.  
  2055. Sub Restrict.Room.Type(Direction.Restricted)
  2056.  On Local Error Resume Next ' local error resume
  2057.  Call Read.Room.Record(Next.Room) ' read next room number record
  2058.  Direction.Restricted=False ' reset return variable
  2059.  Action.Number=RoomRecord.Action ' store room action number
  2060.  If Action.Number>False And _
  2061.  Action.Number<=Lof(ActionFile)/Len(ActionRecord) Then ' check file bounds
  2062.     Call Read.Record(ActionFile,Action.Number) ' read action record
  2063.     If ActionRecord.Attribute2=Air Then ' verify room is air
  2064.        If Entry.Command<>Fly Then ' verify player fly
  2065.           Direction.Restricted=True ' set restricted flag
  2066.        Endif ' end verify player fly command
  2067.     Endif ' end verify room air attribute
  2068.     If ActionRecord.Attribute2<>Air Then ' verify room is air
  2069.        If Entry.Command=Fly Then ' verify player fly
  2070.           Direction.Restricted=True ' set restricted flag
  2071.        Endif ' end verify player fly command
  2072.     Endif ' end verify room air attribute
  2073.     If ActionRecord.Attribute2=Water Then ' verify room water
  2074.        If Entry.Command<>Swim Then ' verify player swim
  2075.           Direction.Restricted=True ' set restricted flag
  2076.        Endif ' end verify player swim command
  2077.     Endif ' end verify room water attribute
  2078.     If ActionRecord.Attribute2<>Water Then ' verify room water
  2079.        If Entry.Command=Swim Then ' verify player swim
  2080.           Direction.Restricted=True ' set restricted flag
  2081.        Endif ' end verify player swim command
  2082.     Endif ' end verify room water attribute
  2083.  Else ' check file bounds
  2084.     If Entry.Command=Fly Or Entry.Command=Swim Then ' check room entry
  2085.        Direction.Restricted=True ' set restricted flag
  2086.     Endif ' end check room entry
  2087.  Endif ' end check file bounds
  2088.  Call Read.Room.Record(Room) ' read current room record
  2089. End Sub ' end routine to restrict room entrance
  2090.  
  2091.  Rem * Routine to determine validity of a string.
  2092.  Rem * input variables:
  2093.  Rem *   Validate$ - string to verify.
  2094.  Rem *   Length - stores length string must be (an even number).
  2095.  Rem * output variables:
  2096.  Rem *   Validate$ - set to null if invalid.
  2097.  Rem * work variables:
  2098.  Rem *   String.Length - loop counter of string to validate.
  2099.  Rem *   Char - character in string to check.
  2100.  
  2101. Sub Valid(Validate$,Length)
  2102.  On Local Error Resume Next ' local error resume
  2103.  Validate$=Left$(Validate$,Length) ' truncate string to length
  2104.  Validate$=Validate$+Space$(Length-Len(Validate$)) ' extend string length
  2105.  For String.Length=1 To Len(Validate$) ' loop through all characters in string
  2106.     ' get ascii value of string character
  2107.     Char=Asc(Mid$(Validate$,String.Length,1))
  2108.     If Char<32 Or Char>127 Then ' verify bounds of character
  2109.        Validate$=Nul ' return null if not valid
  2110.        Exit Sub ' end routine
  2111.     Endif ' end verify ascii code
  2112.  Next ' end loop
  2113. End Sub ' end routine to determine string validity
  2114.  
  2115.  Rem * Routine to encrypt a string.
  2116.  Rem * input variables:
  2117.  Rem *   Encrypted$ - the string to encrypt.
  2118.  Rem *   Add.Checksum - set to false to add byte checksum.
  2119.  Rem * output variables:
  2120.  Rem *   Encrypted$ - the encrypted string.
  2121.  Rem * work variables:
  2122.  Rem *   Encrypt.Work$ - variable containing encrypted string.
  2123.  Rem *   Encrypt.Count - loop variable.
  2124.  Rem *   Encrypted.Sum - calculated byte encryption variable.
  2125.  Rem *   Encrypt.Work1, Encrypt.Work2, Encrypt.Work3.
  2126.  
  2127. Sub Encrypt(Encrypted$,Add.Checksum)
  2128.  On Local Error Resume Next ' local error resume
  2129.  Encrypt.Work$=Nul ' reset encrypted work variable
  2130.  ' loop through string to encrypt in byte pairs
  2131.  For Encrypt.Count=1 To Len(Encrypted$) Step 2
  2132.     ' get first byte substring of pair
  2133.     Encrypt.Work1=Asc(Mid$(Encrypted$,Encrypt.Count,1))
  2134.     ' get second byte substring of pair
  2135.     Encrypt.Work2=Asc(Mid$(Encrypted$,Encrypt.Count+1,1))
  2136.     If Add.Checksum Then ' check checksum ordering
  2137.        Encrypted.Sum=20000 ' checksum bit off
  2138.     Else ' checksum ordering on
  2139.        Encrypt.Work3=Encrypt.Work1+Encrypt.Work2 ' compute sum
  2140.        ' compute even sum of bytes
  2141.        If Int(Encrypt.Work3/2)=Encrypt.Work3/2 Then
  2142.           Encrypted.Sum=10000 ' checksum bit for even parity
  2143.        Else ' checksum ordering
  2144.           Encrypted.Sum=False ' checksum bit for odd parity
  2145.        Endif ' end check checksum ordering
  2146.     Endif ' end verify checksum used
  2147.     ' convert checksum and bytes to integer
  2148.     Encrypted.Sum=Encrypted.Sum+(Encrypt.Work1-32)*100+(Encrypt.Work2-32)
  2149.     ' convert integer to string
  2150.     Encrypt.Work$=Encrypt.Work$+Mki$(Encrypted.Sum)
  2151.  Next ' end loop through string to encrypt
  2152.  Encrypted$=Encrypt.Work$ ' set return variable to encrypted string
  2153. End Sub ' end routine to encrypt a string
  2154.  
  2155.  Rem * Routine to decrypt a string.
  2156.  Rem * input variables:
  2157.  Rem *   Decrypted$ - the string to decrypt.
  2158.  Rem * output variables:
  2159.  Rem *   Decrypted$ - the decrypted string, or null for checksum error.
  2160.  Rem * work variables:
  2161.  Rem *   Decrypt.Work$ - variable containing encrypted string.
  2162.  Rem *   Decrypt.Count - loop variable.
  2163.  Rem *   Decrypted.Sum - calculated byte encryption variable.
  2164.  Rem *   Decrypt.Work1, Decrypt.Work2, Decrypt.Work3.
  2165.  Rem *   Decrypted.Checksum - contains the bit parity.
  2166.  
  2167. Sub Decrypt(Decrypted$)
  2168.  On Local Error Resume Next ' local error resume
  2169.  Decrypt.Work$=Nul ' reset decrypted work variable
  2170.  ' loop through string to decrypt in byte pairs
  2171.  For Decrypt.Count=1 To Len(Decrypted$) Step 2
  2172.     ' convert the two byte string to integer
  2173.     Decrypted.Sum=Cvi(Mid$(Decrypted$,Decrypt.Count,2))
  2174.     ' divide two byte integer to one byte integer
  2175.     Decrypted.Checksum=Decrypted.Sum\100
  2176.     ' get low byte from pair
  2177.     Decrypt.Work1=Decrypted.Sum-Decrypted.Checksum*100
  2178.     ' adjust byte ascii value
  2179.     Decrypt.Work1=Decrypt.Work1+32
  2180.     ' reset integer of string to high byte
  2181.     Decrypted.Sum=Decrypted.Checksum
  2182.     ' divide byte integer out leaving checksum bit
  2183.     Decrypted.Checksum=Decrypted.Sum\100
  2184.     ' get high byte from pair
  2185.     Decrypt.Work2=Decrypted.Sum-Decrypted.CHecksum*100
  2186.     Decrypt.Work2=Decrypt.Work2+32 ' adjust byte ascii value
  2187.     Decrypt.Work3=Decrypt.Work1+Decrypt.Work2 ' compute sum
  2188.     Select Case Decrypted.Checksum ' select checksum parity
  2189.     Case 0 ' verify the checksum bit for odd parity
  2190.        If Int(Decrypt.Work3/2)=Decrypt.Work3/2 Then ' check not odd parity
  2191.           Decrypted$=Nul ' return null for checksum error
  2192.           Exit Sub ' end routine
  2193.        Endif ' end check not odd parity
  2194.     Case 1 ' verify the checksum bit for even parity
  2195.        If Int(Decrypt.Work3/2)<>Decrypt.Work3/2 Then ' check not even parity
  2196.           Decrypted$=Nul ' return null for checksum error
  2197.           Exit Sub ' end routine
  2198.        Endif ' end check not even parity
  2199.     End Select ' end verify checksum bit
  2200.     ' convert integer bytes to string
  2201.     Decrypt.Work$=Decrypt.Work$+Chr$(Decrypt.Work2)+Chr$(Decrypt.Work1)
  2202.  Next ' end loop through string to decrypt
  2203.  Decrypted$=Decrypt.Work$ ' set return variable to decryptes string
  2204. End Sub ' end routine to decrypt a string
  2205.  
  2206.  Rem * Routine to store a file record
  2207.  Rem * input variables:
  2208.  Rem *   File.Number - number of the file to write record.
  2209.  Rem *   Record.Number - the number of the record to write.
  2210.  
  2211. Sub Share.Record(File.Number,Record.Number)
  2212.  On Local Error Goto Share.Error ' local error trap
  2213.  If Share.Installed Then ' check share loaded
  2214.     Lock File.Number,Record.Number ' lock record number
  2215.  Endif ' end check share loaded
  2216.  Select Case File.Number ' select file number to write a record to
  2217.  Case UserFile ' type 1
  2218.     Put UserFile,Record.Number,UserRecord ' write user record
  2219.  Case NonPlayerFile ' type 2
  2220.     Put NonPlayerFile,Record.Number,MonsterRecord ' write nonplayers record
  2221.  Case ObjectFile ' type 4
  2222.     Put ObjectFile,Record.Number,ObjectRecord ' write object record
  2223.  Case MonsterFile ' type 5
  2224.     Put MonsterFile,Record.Number,MonsterRecord ' write monsters record
  2225.  Case TreasureFile ' type 6
  2226.     Put TreasureFile,Record.Number,TreasureRecord ' write treasure record
  2227.  Case MonTalkFile ' type 7
  2228.     Put MonTalkFile,Record.Number,MonsterTalkRecord ' write monster talk record
  2229.  Case MonClassFile ' type 8
  2230.     Put MonClassFile,Record.Number,MonclassRecord ' write monster class record
  2231.  Case SpellFile ' type 9
  2232.     Put SpellFile,Record.Number,SpellRecord ' write spell record
  2233.  Case TableFile ' type 10
  2234.     Put TableFile,Record.Number,TableRecord ' write message table record
  2235.  Case ActionFile ' type 12
  2236.     Put ActionFile,Record.Number,ActionRecord ' write action record
  2237.  Case TempFile ' type 13
  2238.     Put TempFile,Record.Number,TableRecord ' write temp table record
  2239.  Case HelpFile ' type 15
  2240.     Put HelpFile,Record.Number,HelpRecord
  2241.  End Select ' end select file number
  2242.  If Share.Installed Then ' check share loaded
  2243.     Unlock File.Number,Record.Number ' lock record number
  2244.  Endif ' end check share loaded
  2245.  Exit Sub ' exit record routine
  2246. Share.Error:
  2247.  If Share.Installed Then ' compare share loaded
  2248.     If Err=70 Then ' check record lock error
  2249.        Resume ' resume to same statement
  2250.     Endif ' end check record lock error
  2251.  Endif ' end compare share loaded
  2252.  Resume Next ' resume from error trap
  2253. End Sub ' end routine to write file record using share
  2254.  
  2255.  Rem * Routine to read a file record
  2256.  Rem * input variables:
  2257.  Rem *   File.Number - number of the file to read record.
  2258.  Rem *   Record.Number - the number of the record to read.
  2259.  
  2260. Sub Read.Record(File.Number,Record.Number)
  2261.  On Local Error Goto Share.Read ' local error trap
  2262.  Select Case File.Number ' select file number to read a record to
  2263.  Case UserFile ' type 1
  2264.     Get UserFile,Record.Number,UserRecord ' read user record
  2265.  Case NonPlayerFile ' type 2
  2266.     Get NonPlayerFile,Record.Number,MonsterRecord ' read nonplayers record
  2267.  Case ObjectFile ' type 4
  2268.     Get ObjectFile,Record.Number,ObjectRecord ' read object record
  2269.  Case MonsterFile ' type 5
  2270.     Get MonsterFile,Record.Number,MonsterRecord ' read monsters record
  2271.  Case TreasureFile ' type 6
  2272.     Get TreasureFile,Record.Number,TreasureRecord ' read treasure record
  2273.  Case MonTalkFile ' type 7
  2274.     Get MonTalkFile,Record.Number,MonsterTalkRecord ' read monster talk record
  2275.  Case MonClassFile ' type 8
  2276.     Get MonClassFile,Record.Number,MonclassRecord ' read monster class record
  2277.  Case SpellFile ' type 9
  2278.     Get SpellFile,Record.Number,SpellRecord ' read spell record
  2279.  Case TableFile ' type 10
  2280.     Get TableFile,Record.Number,TableRecord ' read message table record
  2281.  Case ActionFile ' type 12
  2282.     Get ActionFile,Record.Number,ActionRecord ' read action record
  2283.  Case TempFile ' type 13
  2284.     Get TempFile,Record.Number,TableRecord ' read temp table record
  2285.  Case HelpFile ' type 15
  2286.     Get HelpFile,Record.Number,HelpRecord ' read help record
  2287.  End Select ' end select file number
  2288.  Exit Sub ' exit record routine
  2289. Share.Read:
  2290.  If Share.Installed Then ' compare share loaded
  2291.     If Err=70 Then ' check record lock error
  2292.        Resume ' resume to same statement
  2293.     Endif ' end check record lock error
  2294.  Endif ' end compare share loaded
  2295.  Resume Next ' resume from error trap
  2296. End Sub ' end routine to read file record using share
  2297.  
  2298.  Rem * Routine to store a message file record
  2299.  Rem * input variables:
  2300.  Rem *   File.Number - number of the file to write record.
  2301.  Rem *   Record.Number! - the number of the record to write.
  2302.  
  2303. Sub Share.Message(File.Number,Record.Number!)
  2304.  On Local Error Goto Message.Error ' local error trap
  2305.  If Share.Installed Then ' check share loaded
  2306.     Lock File.Number,Record.Number! ' lock record number
  2307.  Endif ' end check share loaded
  2308.  Put File.Number,Record.Number!,MessageRecord ' write message record
  2309.  If Share.Installed Then ' check share loaded
  2310.     Unlock File.Number,Record.Number! ' lock record number
  2311.  Endif ' end check share loaded
  2312.  Exit Sub ' exit record routine
  2313. Message.Error:
  2314.  If Share.Installed Then ' compare share loaded
  2315.     If Err=70 Then ' check record lock error
  2316.        Resume ' resume to same statement
  2317.     Endif ' end check record lock error
  2318.  Endif ' end compare share loaded
  2319.  Resume Next ' resume from error trap
  2320. End Sub ' end routine to write file record using share
  2321.  
  2322.  Rem * Routine to read a message file record
  2323.  Rem * input variables:
  2324.  Rem *   File.Number - number of the file to read record.
  2325.  Rem *   Record.Number! - the number of the record to read.
  2326.  
  2327. Sub Read.Message.Record(File.Number,Record.Number!)
  2328.  On Local Error Goto Message.Read.Error ' local error trap
  2329.  Get File.Number,Record.Number!,MessageRecord ' write message record
  2330.  Exit Sub ' exit record routine
  2331. Message.Read.Error:
  2332.  If Share.Installed Then ' compare share loaded
  2333.     If Err=70 Then ' check record lock error
  2334.        Resume ' resume to same statement
  2335.     Endif ' end check record lock error
  2336.  Endif ' end compare share loaded
  2337.  Resume Next ' resume from error trap
  2338. End Sub ' end routine to write file record using share
  2339.  
  2340.  Rem * Routine to store a room file record
  2341.  Rem * input variables:
  2342.  Rem *   Record.Number! - the number of the record to write.
  2343.  
  2344. Sub Share.Room.Record(Record.Number!)
  2345.  On Local Error Goto Room.Error ' local error trap
  2346.  If Share.Installed Then ' check share loaded
  2347.     Lock RoomFile,Record.Number! ' lock record number
  2348.  Endif ' end check share loaded
  2349.  Put RoomFile,Record.Number!,RoomRecord ' write room record
  2350.  If Share.Installed Then ' check share loaded
  2351.     Unlock RoomFile,Record.Number! ' lock record number
  2352.  Endif ' end check share loaded
  2353.  Exit Sub ' exit record routine
  2354. Room.Error:
  2355.  If Share.Installed Then ' compare share loaded
  2356.     If Err=70 Then ' check record lock error
  2357.        Resume ' resume to same statement
  2358.     Endif ' end check record lock error
  2359.  Endif ' end compare share loaded
  2360.  Resume Next ' resume from error trap
  2361. End Sub ' end routine to write file record using share
  2362.  
  2363.  Rem * Routine to read a room file record
  2364.  Rem * input variables:
  2365.  Rem *   Record.Number! - the number of the record to read.
  2366.  
  2367. Sub Read.Room.Record(Record.Number!)
  2368.  On Local Error Goto Room.Read.Error ' local error trap
  2369.  Get RoomFile,Record.Number!,RoomRecord ' write message record
  2370.  Exit Sub ' exit record routine
  2371. Room.Read.Error:
  2372.  If Share.Installed Then ' compare share loaded
  2373.     If Err=70 Then ' check record lock error
  2374.        Resume ' resume to same statement
  2375.     Endif ' end check record lock error
  2376.  Endif ' end compare share loaded
  2377.  Resume Next ' resume from error trap
  2378. End Sub ' end routine to write file record using share
  2379.  
  2380. SysopCommands1:
  2381.  Data "ABORT","HINT","CALL","EDIT","HELP","INVISIBLE","LINK","<>","STATUS"
  2382.  
  2383. SysopCommands2:
  2384.  Data "<>","CALL","DISCARD","EDIT","GET","HELP","KILL","REDUCE","TELEPORT"
  2385.  
  2386. CommandSet1:
  2387.  Data "KILL","ATTACK","HIT","STRIKE","READ","LOOK","RUN","PANIC","SEARCH","SAVE"
  2388.  Data "INFORMATION","INVENTORY","SUICIDE","TRAIN","HEALTH","APPEAL","BYE","STOP","QUIT","END"
  2389.  Data "EXPERIENCE","HELP","HIDE","CAST","LIST","BRIEF","BANK","TIME","DATE","CLOCK"
  2390.  Data "CHARM","BEGUILE","ANSI","SHIELD","GUARD","<>","<>","<>","LUNGE","DODGE"
  2391.  Data "TOP","BLESS","CURSE","PASSWORD","MAIL","USERS","CHAT","EXIT","LEAVE","CLIMB"
  2392.  Data "STORE","LOGIN","RELOGIN","STATUS","LINELENGTH","CATALOG","LINEFEEDS","PAGELENGTH","ECHO","WORDWRAP"
  2393.  Data "ALIGNMENT","<>","<>","NORTH","EAST","SOUTH","WEST","NORTHEAST","SOUTHEAST","SOUTHWEST"
  2394.  Data "NORTHWEST","UP","DOWN","IN","OUT","HINT","SORT","COMMANDS","<>","<>"
  2395.  Data "<>","<>","REROLL","<>","WISH"
  2396.  
  2397. CommandSet2:
  2398.  Data "GO","ENTER","READ","EXAMINE","LOOK","USE","GET","TAKE","DROP","PUT"
  2399.  Data "SELL","PAWN","BREAK","SMASH","CLOSE","OPEN","DRAW","WIELD","HOLD","WEAR"
  2400.  Data "RETURN","CAST","BUY","LOCK","UNLOCK","PICKLOCK","FIX","REPAIR","RECHARGE","DRINK"
  2401.  Data "<>","THROW","STEAL","<>","BLESS","CURSE","FUEL","<>","<>","TALK"
  2402.  Data "PARLEY","BRIBE","OFFER","LOAD","FIRE","MOUNT","DISMOUNT","RIDE","HIDE","SEARCH"
  2403.  Data "HELP","IDENTIFY","<>","<>","KILL","ATTACK","HIT","STRIKE","BACKSTAB","CIRCLE"
  2404.  Data "FEINT","PARRY","THRUST","CHARGE","TURN","COUNTER","BEMUSE","BEFUDDLE","PUMMEL","RESIST"
  2405.  Data "PSIONIC","EAT","DRIVE","FLY","MOVE","LAUNCH","LEARN","LIGHT","SWIM","EXIT"
  2406.  Data "LEAVE","BEAT","PUNCH","BEWITCH","BEWILDER"
  2407.  
  2408. Config.Data:
  2409.  Data 12,4,6,3,9,6,10,5,10,3,5,4,9,6,5,4,11,5,6,3,11,4,6,3,10,3,7,3,9,6,8,3,125,125,125,125,250,250,250,250
  2410.  Data "Lord","Wizard","Assassin","Bard","Monk","Knight","Priest","Empress","Assistant DM","Dungeon Master"
  2411.  Data "Human","Elf","Gnome","Dwarf","Halfling","Half-elf","Half-orc","Ogre"
  2412.  Data "Fighter","Magic User","Thief","Cleric","Paladin","Ranger","Druid","Lady","Assistant DM","Dungeon Master"
  2413.  Data "Strength","Intelligence","Wisdom","Dexterity","Constitution","Piety","Charisma"
  2414.  Data "north","east","south","west","northeast","southeast","southwest","northwest","up","down","in","out"
  2415.  Data "blunt","pole","sharp","thrusting","good","neutral","evil","lawful","neutral","chaotic"
  2416.