Chapter 18

User-Defined Data Objects

He touched the fish, saying in a terrible voice, `Fish, fish, are you doing your duty?' To these words the fish lifting up their heads replied, `Yes, yes. If you reckon, we reckon. If you pay your debts, we pay ours. If you fly, we conquer, and are content.'
--The Vizier who was Punished, The Arabian Nights

Most of the time, the data objects you create will be pre-defined, or at least derived from one of the pre-defined types. However, it is possible to make your own datum from scratch. Such an object may be useful for your own specialized purpose when you don't need all the extra baggage associated with the built-in types.

1. Defining a Datum

To define a new data type, simply derive it from the root, rather than from an existing object type. The following code demonstrates the syntax by defining a Quest datum.

Quest
   var
      mob/sponsor
      quest_obj_type
      reward_obj_type
      desc

   proc
      Check()
         var/mob/M
         var/obj/O
         for(M in view(sponsor,1))
            O = locate(quest_obj_type) in M
            if(O)
               Reward(M,O)
               return 1
      Reward(mob/M,obj/O)
         var/obj/R = new reward_obj_type(M)
         O.Move(sponsor)
         M << "You have completed the quest!"
         M << "[sponsor] takes [O] and rewards you with \an [R]."

As you can see, object variables and procs are defined just as with any other data object. Inheritance works the same too, so you can derive new types from ones you have already defined.

2. Object Variables

Generic data objects are intended to have as small of a pre-defined "footprint" as possible. As a result, there are very few built-in variables. These are described in the following list.

  • type contains the type path of the object.

  • tag contains an optional unique text identifier for the object. Once you have assigned this, you may use locate(tag) to get a reference to the datum.

  • vars is the list of variables belonging to the object. The items in the list are the variable names. Each one is associated with the value of the variable itself. See section 12.7 for an example.

    3. Object Procedures

    There are only a few pre-defined procedures for data objects. These all have the same meaning as for the atomic objects which have already been introduced. Figure 18.27 lists the procedures and the page where you may find a full description.

    Figure 18.27: Abstract Object Procedures

    Procedure See Page
    New [7.2]
    Del [7.2]
    Topic [7.6]
    Read [12.4]
    Write [12.4]

    4. Creation of Data Objects

    The new instruction is used to create data objects and del is used to destroy them. The following example shows how the previously defined quest object might be used.

    mob/king
       var/quests[0]
    
       verb/beg()  //get a new quest
          set src in view()
          var/Quest/q = RandQuest()
          usr << q.desc
          quests += q
    
       verb/bow()  //finish quest
          set src in view()
          var/Quest/q
          for(q in quests)
             if(q.Check())
                quests -= q
                return
    
       proc/RandQuest()
          var/qtype = pick(typesof(/Quest) - /Quest)
          var/Quest/q = new qtype()
          q.sponsor = src
          return q
    
    Quest/Goblin
       quest_obj_type = /obj/corpse/goblin
       reward_obj_type = /obj/potion/newlife
       desc = "Bring us the head of a goblin and ye shall have new life!"
    
    Quest/Ring
       quest_obj_type = /obj/magic_ring
       reward_obj_type = /obj/wand/lightning
       desc = "Bring us a golden ring and thy reward shall be great!"
    

    By begging the king, one receives a new quest. With the requested object in hand, one must simply bow before the king to receive the reward. The typesof instruction was used here to pick a quest randomly from all that are defined in the code.

    Obviously one could add all sorts of improvements to this basic system. For example, other types of rewards and requests could be added. However, it is a good start and a nice demonstration of a user-defined datum.

    Note that we never bothered to delete the quest when it was finished but simply remove it from the list. Since there are no longer any references to the object anywhere, it will be automatically deleted by the garbage collector.