prev | toc | next
 

Argo Programmer Guide


3.1 Argo Programming Overview

Argo is meant to be an extensible system. Staff utilities such as +define go a long way toward allowing staff members to add things to the system to tailor it to their worlds. However, inevitably, people will think of worthwhile additions that require modification or extension of the MUF programs supporting the system. Argo grew, over a period of several years, in the process acquiring what might be called a coral-reef architecture... As a result, adding to or modifying the system isn't trivial, but it is definitely allowed. If you would like to change or extend Argo, you are welcome too.

This page provides an overview of how the system hangs together (to whatever extent it really does hang together)... subsequent pages deal with more specific issues that you will face as you work with the code.

What can feasibly be included here is included... But there is no substitute for diving into the code itself. These pages are meant as an overview and jumpstart, but adding reliable programs to the system will also require reading the code of existing Argo program. (Adding and modifying Argo programs is probably not the place to start if you are new to MUF programming... spend some time with the tutorial on MUF in The MUCK Manual first.)

Programs:

Argo consists of a libary of shared code, lib-argo. Lib-argo is also the link point of the +install and +uninstall commands, used to add and remove system components. These components are for the most part the `asys-' programs: MUF programs handling either a single Argo command (asys-sheet, handling the +sheet command, would be an example), a group of closely related commands (such as the monetary commands handled by asys-money or the rumor and influence commands handled by asys-rumors), or a set of `coded effects', which are not called directly by a command, but are instead invoked by the events manager (asys-eventmgr), which calls other programs as needed to handle events in combat, spell casting, and other uses of abilites that trigger coded effects. These programs called by the event manager are usually not called directly by any commands: asys-stdspells, which handles spells cast with the +cast command, would be an example. Subsequent pages detail the function calls available from lib-argo, and provide skeleton programs for new commands and coded abilities, along with discussion of issues related to each.

Data Storage:

All stateful data used by Argo is stored in the @a/ propdir, either on the room parenting an Argo realm (if there is only one realm on the MUCK, this will always be room #0), or on a specific, Argo-enabled object, such as a player or weapon. System components (installed programs, command actions) are stored as dbrefs. Within the event system, target objects are also stored as dbrefs. Elsewhere, objects are stored as reflist strings. Process IDs, system times and amounts of time that must pass before an event completes (such as the effects of a spell wearing off or completion of making an object) are stored as integers. All other data is stored as strings.

Below is a brief tour of the Argo data propdirs on the different types of objects. Very few MUCKs will have all these propdirs... some are created when database entries of a new type are made for the first time, and some are not applicable to certain MUCKs (a CyberPunk MUCK probably won't have a propdir for spells, for example).

Realm Parent Rooms

Room #0 is used as the parent room in all examples. The name of each property or propdir is followed by an indicator of its scope: data with a MUCK-wide scope is stored on room #0, and is the same for all realms; data with a realm-wide scope is stored on the parent room for a realm, and only applies within that realm (room #0 can be the parent of a realm on a MUCK that has multiple subrealms... in other words, #0 will often hold both MUCK-wide and realm-wide data).

@a/banks/ (Scope: Realm)
This propdir holds information about banks and accounts within them, organized by bank name. If no banks have been set up, this propdir will not exist. If rooms numbers #420 and #1191 had been configured as locations of BankOne, typing ex #0=@a/banks/bankone/branches would show:

    str /@a/banks/BankOne/branches:#420 #1191

This propdir also holds account information for players, organized by bank name: if player #123 had deposited 1 large coin and 20 small coins at BankOne in the global realm, examining the propdir would show the following:

    str /@a/banks/BankOne/123/large_coins:1
    str /@a/banks/BankOne/123/smallcoins:20

Argo modifies the branch information with the +banks command, and the account information with the +deposit and +withdraw commands. Added programs can do likewise.

@a/calls/ (Scope: MUCK)
The @a/calls/ propdir is used to store the dbrefs of programs that should be called in order to handle various events. As such, it is most often referenced by asys-eventmgr. An example: if the asys-thieves command, which handles the Lockpicking skill, has dbref #321, typing ex #0=@a/calls/uselockpicking will display:

    ref /@a/calls/uselockpicking/asys-thieves:asys-thieves(#321FWM3)

The `use' prefix tells Argo that this is for skill named `lockpicking', rather than an ability of another type; the dbref indicates the program to call when players invoke the skill with +use lockpicking. Working with these program calls is discussed in more detail in later sections of the Programmer Guide.

@a/cat_list/ (Scope: MUCK)
This propdir holds the display names of databse categories, such as @a/cat_list/npcs:NPC. It is referenced when showing the categories available for viewing, with commands such as +list, or modified with commands such as +define.

The category list is stored on all realm parent rooms... so, while it may be referenced as though it exists at a realm-wide scope, categories should be the same throughout the MUCK.

@a/cg_locs (Scope: MUCK)
This property (not propdir) holds a reflist of all configured character generation rooms.

@a/comm_list/ (Scope: MUCK)
The @a/comm_list/ propdir holds the dbrefs of Argo command actions, organized by command name. If the command has been renamed with the +rename command, the value of the original command name will be not the dbref of the command action, but a `go to' string providing a cross reference to the current property holding the command dbref. For example, if the +vote command had been renamed to vote, but the +will command had not been renamed, the @a/comm_list/ propdir would contain the following:

    @a/comm_list/+vote:go to vote
    @a/comm_list/+will:+will(#343E)
    @a/comm_list/vote:vote:(#409E)

The command list directory is used to display command names with commands such as +list, and to help ensure that no-longer-needed Argo commands are recycled when a program is uninstalled. New Argo command programs will need to add themselves to this list when they are installed, and remove themselves when uninstalled; the skeleton programs discussed later in the Guide include functions for doing this.

@a/creatures/ (Scope: Realm)
This propdir holds the abilities and levels for all creatures defined in the realm's database. Each creature type's entry is organized much like an individual player's @a/ propdir, as discussed below.

@a/dataobj (Scope: Realm)
This property (not propdir) servers two purposes. Its existence on a room indicates that this is the parent room object holding the data for a realm. The value of the property is the name of the realm:

    @a/dataobj:Global

So, this property, on room #0, indicates that #0 is the parent of a realm named `Global'.

@a/dis-ad/ (Scope: Realm)
The @a/dis-ad/ propdir holds information about all defined advantages and disadvantages. The value of an advantage will be a positive integer; the value of a disadvantage will be a negative integer. Triggered effects are stored in a list, named `trigs', under the named dis-ad. For example, if the Anemic disadvantage had a value of 1 point, and a triggered effect of reducing the Constitution stat by one, the propdir would contain the following:

    str @a/dis-ad/Anemic/:-1
    str @a/dis-ad/Anemic/trigs#/:1
    str @a/dis-ad/Anemic/trigs#/1:stats,con,-1

This format for storing an ability modification or requirement, stats,con,-1 or <category>/<instance>/<level> is used in a number of places in the database.

@a/docs/ (Scope: MUCK)
This propdir holds all documents in the online manual, organized as lists named for the document topic. Directly modifying the contents of this propdir is not recommended: use +man #edit to change the manual's contents.

@a/dtemp (Scope: MUCK)
This propdir holds temporary data used when defining objects. New Argo programs will seldom need to access or modify its contents directly.

@a/groups/ (Scope: Realm)
The groups propdir simply holds an integer string indicating the minimum status level required to belong to a group. The status level is used when players try to join a group by using the +skills command to acquire the relevant Influence skill... A more common use of the directory is to loop through its properties to obtain a list of all currently defined groups.

@a/jobs (Scope: Realm)
This propdir holds the data defining a job... for example, `Blacksmith':

    str @a/jobs/Blacksmith/hmod:0
    str @a/jobs/Blacksmith/injchance:2
    str @a/jobs/Blacksmith/injdam:1d6
    str @a/jobs/Blacksmith/preqs#/1:skills,smith,1
    str @a/jobs/Blacksmith/preqs#/:1
    str @a/jobs/Blacksmith/salary:10

The hmod property is the hiring modifier. Injchance and injdam are the chance for on-the-job injury and the amount of damage taken when injured, respectively. The preqs list contains ability sets, in the standard format (<category>/<instance>/<level>), defining the qualifications for the job. The salary property is the job's salary, in small coins.

@a/objects/ (Scope: Realm)
This propdir contains the definition data for all objects. Conceivably, new Argo programs will need to modify this data directly. More commonly, the directory will be referenced to determine the qualities of an object (very few Argo properties are stored on the objects themselves: whenever possible, the property is not copied to the object... instead, the realm's @a/objects/ propdir is accessed, using the object's @a/name property as a key. This allows modifications of object definitions to retroactively apply to existing instances of an object, and saves a bit of database space).

Object definitions are one of the more complicated structures. For example, the standard Broadsword:

    str @a/objects/Broadsword/class/melee weapons:1
    str @a/objects/Broadsword/class/swords:1
    str @a/objects/Broadsword/class/weapons:1
    str @a/objects/Broadsword/combat/bable:1
    str @a/objects/Broadsword/combat/dable:1
    str @a/objects/Broadsword/combat/dam:2d6
    str @a/objects/Broadsword/combat/hands:1
    str @a/objects/Broadsword/combat/minstr:12
    str @a/objects/Broadsword/combat/pable:1
    str @a/objects/Broadsword/combat/parry:1
    str @a/objects/Broadsword/combat/skills/swords:1
    str @a/objects/Broadsword/combat/type:conventional
    str @a/objects/Broadsword/cost:80
    str @a/objects/Broadsword/create/materials/steel:6
    str @a/objects/Broadsword/create/prereqs/skills/armorer:1
    str @a/objects/Broadsword/create/prereqs/skills/swords:1
    str @a/objects/Broadsword/create/rolls/skills/armorer:0
    int @a/objects/Broadsword/create/time:172800
    str @a/objects/Broadsword/create/tools/forge tools:1
    str @a/objects/Broadsword/desc#/1:A straight-bladed....
    str @a/objects/Broadsword/desc#/:1
    str @a/objects/Broadsword/name:Broadsword
    str @a/objects/Broadsword/repair/skills/armorer:1
    int @a/objects/Broadsword/repair/time:7200
    str @a/objects/Broadsword/repair/tools/forge tools:1

The subdirectories directly beneath the object name (`Broadsword' in this case) contain data pertaining to a specific use of the object: the class subdirectory holds the object classes instantiated by the object; the combat directory holds values refrenced by the combat system; the create and repair directories hold information needed by the +make and +repair commands.

Some notes about properties in the combat directory: a true value for bable indicates that the weapon can be blocked, dable indicates that it can be dodged, and pable indicates that it can be parried. The true value stored in the parry property indicates that this weapon can be used to parry. The dam property is a dice string indicating the amount of damage done with a successfaul attack. The skills propdir includes skills that can be invoked to use the weapon. Minstr is the minimum Strength required to use the weapon. The value of hands will be 1 or 2, indicating how many hands are required when using it. The type property holds the weapon's damage type, which will be `conventional' for all ordinary weapons.

Note that ability levels specified in the create/ and repair/ directories are stored in a form that differs from the `standard' format for recording ability levels mentioned elsewhere on this page. The reasons for this difference are, um, lost in the mists of time. One hypothesis: this way works better, but wasn't hit upon until relatively late in Argo's development, and other programs that record or read ability levels have not been rewritten to take advantage of it.

@a/prog_list/ (Scope: MUCK)
This propdir lists installed Argo programs, organized by name and stored by dbref:

    ref /@a/prog_list/asys-active:asys-active(#286FWM3)
    ref /@a/prog_list/asys-approve:asys-approve(#289FWM3)
    ref /@a/prog_list/asys-approved:asys-approved(#290FWM3)
    ref /@a/prog_list/asys-award:asys-award(#291FWM3)
    ref /@a/prog_list/asys-background:asys-background(#292FWM3)
    (etc.)

Your programs can loop through this directory to obtain a list of all currently installed Argo programs. It may also be used as a reliable way to find a particular program: the property will always be named for the `official' Argo name of the program, even if the program object itself has been renamed.

@a/psiabs/ (Scope: Realm)
This directory holds the definitions for psionic abilities. For example...

    str /@a/psiabs/Obscure/def:@a/stats/pre
    str /@a/psiabs/Obscure/fat:16
    str /@a/psiabs/Obscure/preqs#/1:dis-ad,Psionic Aptitude,1
    str /@a/psiabs/Obscure/preqs#/2:skills,Mental Discipline,6
    str /@a/psiabs/Obscure/preqs#/:2
    str /@a/psiabs/Obscure/:int,13,0

The top-level property of this propdir (@a/psiabls/Obscure) holds the basic ability definition: the base stat for the Obscure psionic ability is Intelligence; its intelligence rating is 13, it doesn't cost any money to learn the ability. The def property indicates the ability used as a defence against the psionic ability; the fat property indicates its fatigue cost. The preqs list holds definitions for prerequisites required to learn the psiab, in the standard format.

Note that the ability definition data stored here has nothing to do with the Obscure ability's coded effects. The data here is created when the ability is defined, and referenced when the ability is learned and used. If the ability is used with the generic RP commands (+prove and +roll), success or failure will be displayed, but nothing further will happen. If it is used as part of the psionics system, with the +focus command, then the psionics system (asys-psionics) will verify that the user has the ability, the target is valid, etc., and then call the events manager (asys-eventmgr) to handle actual execution of the ability. On the user's turn to act, the event manager will confirm that the ability can be used (target is still valid, user has enough fatigue, etc.), and will then see if any other programs have been set up to handle the use of this ability. If not, control will be returned to asys-psionics, which will treat it as a `null ability', making any necessary rolls, displaying the results, and recording the expenditure of 16 points of fatigue. And that's all that will happen... no changes to the database indicating that the target object is obscured will be applied.

In order for coded effects to be applied, some program must be installed, in a way that lets the event manager recognize that it should be called when this ability is used. In the case of Obscure, there is such a program... asys-stdpsiabs:

    str @a/calls/focusobscure:asys-stdpsiabs(#636FWLM3)

The events manager checks the global @a/calls/ propdir to determine if another program should be called to handle any particular event. The property focusobscure indicates that when the focus command is used with the Obscure ability, asys-stdpsiabs should be called to handle the event. This called program may apply any coded effects as needed. Programming Psiabs discusses how to set up these program calls in more detail.

@a/realms (Scope: MUCK)
This property (not propdir) is a reflist of all realm parent rooms.

@a/recycle (Scope: MUCK)
This property (not propdir) is a reflist of items that should be checked for recycle times. This and a number of related properties store dbrefs for items that are due for `high priority checks'... Determinations that need to be made on a turn-by-turn basis:

    @a/stop_listen
    @a/relock
    @a/reveal
    @a/uncontrol
    @a/return
    @a/recycle
    @a/uncontrol

The @a/stop_listen prop records a reflist of objects which are currently set with a _listen prop, because of something like the Clairsentience psiab. The @a/relock prop is a reflist of objects that have their _/lk lock property reset by Argo, and will need to be returned to their original lock values. Objects in the @a/reveal reflist are currently set `hidden' or `invisible'... They need to be checked for when this effect expires. The @a/recycle reflist holds objects that will need to be recycled at some point in the near future. @a/uncontrol holds a reflist of objects — usually puppets — which someone can control via the +control command.

The `rules' for recording these objects along with supporting data are rather involved and piecemeal... you'll need to grep through the Argo programs to find examples of how they are used and study the code in order to duplicate the functionality.

@a/rumors/ (Scope: Realm)
This propdir holds data for existing rumors, organized by group.

    str @a/rumors/Underworld/1/instig:#217
    str @a/rumors/Underworld/1/status:whispered
    str @a/rumors/Underworld/1/: That guy Hammer's got a soft spot
      Rico, the skinny kid who lives over the dry goods store on
      Front street... You wanna put pressure on Hammer? Squeeze Rico.
    str @a/rumors/Underworld/:Word on the street is...

The instig prop is the dbref of the player who started the roomer; status is the rumor's status (whispered, muttered, widespread, etc.).

@a/scanner (Scope: MUCK)
This property is the process ID of the system scanner. If ISPID? returns true for this int, the scanner is running.

    @a/skills/Lockpicking/nodef:yes
    @a/skills/Lockpicking/tools/lockpicks:1
    @a/skills/Lockpicking/:dex,8,0

This is a fairly typical entry for a skill with coded effects. The top-level prop (@a/skills/Lockpicking:dex,8,0) indicates that the base stat for the skill is Dexterity, that its intelligence rating is 8, and that it costs no money to learn. It has a true value for the nodef prop, indicating that it it cannot be rolled at default values: a player must explicitly know the skill in order to use it. The value of 1 for tools/lockpicks indicates that the player must have one intance of an object with the class `lockpicks' as well.

@a/staff/ (Scope: MUCK)
The @a/staff/ propdir holds information for displaying a list of the Argo staff:

    @a/staff/header#/1:___The Dark Star Rising Staff_______________________________
    @a/staff/header#/:1
    @a/staff/members:#2 #517
    @a/staff/trailer#/1:____________________________________________________________
    @a/staff/trailer#/:1

The header and trailer lists are information to be shown befor and after the listing of staff members, respectively, set with the +staff #format command. The members property is a reflist of staff members, set when players are added to or removed from the staff roster with +staff #add and +staff #remove. Note that this reflist is used only for getting a list of players to show when the +staff command is used... Argo determines whether a player has staff privileges by checking for a true value for the @a/staff property on the player object.

@a/stats/ (Scope: MUCK)
This propdir simply holds the display name of the various stats:

    @a/stats/con:Constitution
    @a/stats/cra:Craft Skill
    @a/stats/dex:Dexterity
    @a/stats/int:Intelligence
    @a/stats/phy:Physical Skill
    @a/stats/pre:Presence
    @a/stats/str:Strength

@a/sysparms/ (Scope: Realm)
The @a/sysparms/ propdir holds the system parameters for the realm, as discussed in Setting System Parameters.

@a/temp/ (Scope: MUCK)
This propdir hold temporary data, organized by player dbref (for example, temp data for player #123 would be stored in #0's @a/temp/123 propdir). Individual player propdirs in @a/temp/ are routinely written to by Argo programs, and deleted by the initialization routine called by most Argo commands. Newly added programs should probably follow this method. If there's a chance that a player could enter another Argo command while the data is still needed, use #0's @a/dtemp/ propdir, and then explicitly delete the data when you're sure it is no longer needed.

@a/version (Scope: MUCK)
This property holds the version number of the currently installed Argo system. Numerous programs use the presense of an @a/version property to verify that an object is Argo-enabled, and future versions of the system will use this prop to coordinate sanity checks... So, don't fool around with the version prop.

@a/vote/ (Scope: MUCK)
This propdir holds data for the player voting system:

    int @a/vote/start:966816720
    str @a/vote/voted/293:1
    str a/vote/votes/517:1

The start property holds the systime when the current voting period started. The voted/293 property above indicates that player #293 has voted one time this interval. The votes/517 property indicates that plyaer #517 has received one vote this interval.

prev | toc | top | next