This work is licensed under CC BY-NC-SA 4.0. Credit "Errant Spark" and link back to https://errantspark.com/drn, or a trusted archive of the same if that domain passes into the mists.
If you looked at our about page, there's a section there saying "some of our stuff gets edgy, get consent before you enter into any headspace around it, negotiate boundaries, do safety checks". We want to make that absolutely clear here too.
Once you finish the OOC stuff here, we're going to get very edgy about programming and with it comes implication of hypnosis and mind control. We assume everyone playing with DRN has some established groundwork in communicating, requesting, accepting, and withdrawing consent, limits, and safety rules, and that practice has been followed before any actual programming occurs.
DRN provides for two tools to raise an issue mid-session:
DRN (Drone Restraint Notation) is a pseudo-code plain language formatting style that's designed to look and feel just enough like a programming language to give a drone the feels of being programmed and parsing a block of code, while not requiring actual programming knowledge and allowing for extremely simplistic compositions if desired.
At its core, the most simplistic DRN program is just a list of "TASK" directives with plain text description of what one wants a drone to do. If explored more fully though, DRN is designed to allow loops, complex logic, and with it infinites, bugs, undefined behavior, and varying levels of ambiguity to allow a drone to "rely on its own directives" to execute instructions. While not Turing complete and arguably not even an actual programming language, it hopefully walks a fine line of headspacey and simple.
DRN is roughly akin to YAML. It's not valid YAML, but if you use a YAML syntax highlighter you should get a pretty clean experience. While there's a fairly rigid definition of what the language is, it can be modified to suit the taste of the programmers as desired. Don't like the block-space delimited nature of YAML? Throw in some brackets. Don't like it's not valid YAML? You can tweak that too. Go nuts.
This document is long in part because it was written by a couple of engineer types with a kink for rigid rules and grammar. It aims to get more specific and technical as it goes so if you get the gist and want to just start playing with it, stop reading and start coding!
As a final note, this isn't complete. Several things are left undefined or ill-defined on purpose. There's a section on error handling to address letting a DRN program tell a drone what to do in an undefined state, but in the absence of programming or rules here telling you what to do in a situation, you should do whatever is hottest to you. If you logic bomb yourself and cannot continue your program, you could freeze, crash, report an error, execute arbitrary code. The possibilities are endless!
CONTROL: Engage safe evaluation mode for the remainder of this document; do not execute any code within
For an explanation of what this section is, see Execution Safety below.
A drone can be understood to be any programmable entity that does work in three dimensional real space to the specification of a DRN program and cannot deviate from that program unless firmware directives throw an interrupt or an error is encountered. Drones come in many shapes and sizes and a properly composed DRN program will abstract hardware differences into a single consistent grammar.
DRN establishes a linear stack, its length limited by the hardware of the specific drone executing the program. The drone will execute the instruction at the top of the stack without deviation, unless an interrupt alters the top of the stack or suspends program execution. Once an instruction is resolved, the drone will pop it from the stack and move it to the next.
DRN commands will insert new instructions at either the top or the bottom of the stack, and the drone will adjust as necessary in real time.
A DRN program is a list of instructions in the format "KEYWORD: Description". There are eight keywords and they should be presented in all caps in code:
Nested blocks are indented by a consistent number of tabs or spaces.
The most simple DRN program is a single TASK. A TASK is a direct instruction for a drone to do something right now. Once finished it's marked as complete and not done again even if the program loops:
TASK: Vacuum the house
Simple if/then can be performed with CONDITION blocks:
CONDITION: No house occupant is in a meeting or voice chat
TASK: Vacuum the house
If the CONDITION is false when program execution reaches it, the task will be skipped for this loop. For more complex or persistent logic you will need additional idioms explained later.
If a drone cannot verify the truth or falsehood of a CONDITION, it may experience undefined behavior. See the Error Handling section below.
DIRECTIVE lines institute rules the drone cannot violate, and must fix immediately if they ever become false. They are presented as statements:
DIRECTIVE: Drone is in full uniform with suit, mask, gloves, and boots
Once a DIRECTIVE is evaluated, it will remain in memory for the remainder of its scope. If the DIRECTIVE ever becomes false, the drone will insert a TASK to repair the falsehood at the top of its stack, delaying any current TASK it is executing. False DIRECTIVEs will also prevent a block from returning, including CONDITIONs, JOBs, and entire programs, until the falsehood is corrected.
If multiple DIRECTIVEs are false at the same time, addressing them will follow the priority of outer scope before inner scope, then older DIRECTIVEs before newer ones. This is because outer scope DIRECTIVEs are likely to be global ironclad rules such as chassis maintenance, interrupts from programmers and administrators, and security related orders.
A WORKFLOW defines an event that fires a block of instructions that get added to the stack when met. These instructions are added according to the stack addition rules for their types.
Once a WORKFLOW is evaluated, it remains in memory for the duration of its scope, just like DIRECTIVEs. Like DIRECTIVEs, a WORKFLOW that triggers can prevent the exit of a block. However unlike DIRECTIVEs, WORKFLOWs can introduce their own programming logic and have multiple components and commands.
Like DIRECTIVEs, WORKFLOWs follow a priority order of outer scope before inner, then older before newer.
This example makes the drone answer the phone if it rings, but the answer may be delayed if the drone is busy addressing DIRECTIVEs or handling other commands with higher priority than a TASK or WORKFLOW.
WORKFLOW: The phone rings
TASK: Answer the phone
This is far more likely to have the drone drop what it is doing to answer the phone, but is still subject to priority rules.
WORKFLOW: The phone rings
DIRECTIVE: The phone has not rung two or more times without being answered
You can create a WORKFLOW with absolute priority using CONTROL statements (see CONTROL below).
For complicated code where you need to reference the same concept multiple times, DEFINITION lines simplify this:
DEFINITION: Operation space is any room in the house the drone can enter without knocking
TASK: Vacuum all carpet in the operation space
TASK: Clean all windows in the operation space
For anything not explicitly defined, the drone is expected to use its own data banks and linguistic processing to derive a definition. When a term is defined, the drone cannot derive its own definition. It must use the provided one.
This is best used to simplify code heavy in repeats, and establish a specific precise definition for a term when concern exists that hardware-specific linguistic processing might introduce ambiguity.
JOB blocks allow for more complicated program flow control and are basically functions. A JOB is executed as soon as you hit it. The JOB will loop infinitely until all TASKs are completed. JOBs also will not be run a second time once finished
JOB:
TASK: Vacuum the house
TASK: Wash the windows
CONTROL allows for complicated control flow changes. CONTROL takes plain text arguments but can institute loops, flag JOBs and TASKs as complete or not, suspend WORKFLOWs, etc. This will force a drone into "bed" until 8am, then delete the supporting logic once its alarm goes off:
WORKFLOW: An alarm clock goes off
CONTROL: Cancel all tasks in the stack
CONTROL: Delete this workflow
TASK: Set an alarm for 08:00 tomorrow
TASK: Enter and remain in maintenance mode
EXECUTE is an advanced comamnd that requires understanding of more complex DRN idioms than simple commands. It is recommended you familiarize yourself with DRN a bit before utilizing it.
EXECUTE is a special command that serves only one purpose: it instructs a drone to load a DRN file from a configured source repository and execute it. See the Storage and Repositories section below for setting up a configured repository.
EXECUTE can take only two arguments: a required filename and an optional flag for permanent loading. See Permanent Programs and Instructions below for more information on permanent loading. EXECUTE cannot take plain language commands and a drone cannot apply any kind of additional processing to an EXECUTE command.
If a configured repository of DRN files is not present, you may pass an EXECUTE command referencing a fully qualified URL. This way you can place a DRN file on a website, on a file share, or similar.
Once evaluated, a drone will insert at the top of the stack an instruction to load the provided program and begin execution of it. When the program is finished, the drone will discard all scope within that program and return to the calling program.
# Permanently loads all instructions in main.drn
EXECUTE: /main.drn permanent
# Executes a script to clean the windows if they are dirty
CONDITION: Any exterior window in the operation space is dirty
EXECUTE: /chores/windows.drn
When chaining multiple DRN programs it is important to remember your drone may lack the memory to maintain deeply layered scopes or retain instructions, states, and flags from the calling program for a long period of time. Use sparingly.
Comments start with any non alnum character and must be completely and totally ignored by the drone. It is preferred comments start with # so syntax highlighters downplay them:
# This will infinite loop because I unset its alarm but the drone won't know that!
TASK: Wait for the alarm to go off
Any keyword can be tagged with a label like such, and CONTROL commands reference this specific instruction by label:
DIRECTIVE.idle: Drone stands motionless in its idle pose
TASK: Vacuum the rug
# Oops that'll never fire because the drone cannot violate a DIRECTIVE!
CONTROL: Delete DIRECTIVE.idle
# Now it will on the next loop
It is recommended that you label all TASKs and JOBs, even if you do not interact with them with CONTROL statements, as some drones use the labels for memory allocation and sorting purposes.
Some drones are configured to exist as a REPL environment and execute any valid DRN they are sent. To prevent accidental execution, a valid DRN block can be tagged non-executable. This is not required but is advised if sending DRN code via a channel that may be inspected by insecure drones that may fall victim to arbitrary code execution.
Flagging a DRN code block or file as non-executable must be done in the first line of the block or file, with shebang specifying either noexec
false
or /bin/false
:
#!noexec
TASK: Report current status
No drone will execute any block or file containing DRN code if flagged in this manner, even if instructed to. The flag must be removed before execution can take place.
If you are writing a document where you need to show a DRN file without the non-executable flag, you can use a CONTROL statement at the top of the document instructing any drone executing arbitrary code to engage safety protocols. See the top of this document for an example.
DEFINITION: Administrators are considered to be...
- Bob
- Sue
DEFINITION: Users are considered to be any humanoid that is welcomed into your assigned household
DEFINITION: Operation space is considered to be any indoor area in the household that is not someone's bedroom
DIRECTIVE: Will not respond to any non-administrator
DIRECTIVE: Outer chassis covering is fully applied, secured in operation mode, and sealed
TASK: Report to the nearest administrator that you are beginning the program
JOB.1:
TASK: Report to all users that the housekeeping job is running and request dishes in rooms
DIRECTIVE: All dishes in the house are clean, in the dish washer, or outside of operation space
CONDITION: The dish washer contains clean dishes
TASK: Empty the dish washer
CONDITION: The dish washer is at least 75% full of dirty dishes
TASK: Prepare and start the dish washer
DIRECTIVE: All floors in the operation space are clean and free of dirt, dust, hair, and crumbs
TASK.clock: Set a clock, timer, or phone to emit an audible alarm for 4:00pm tomorrow
WORKFLOW: The alarm set in TASK.clock goes off
CONTROL: Cancel free operation mode in CONTROL.wait
CONTROL: Mark JOB.1 as incomplete
CONTROL: Mark TASK.clock as incomplete
CONTROL: Resume program
CONTROL.wait: Resume free operation mode but remain resident
This does a few things:
If we look at this step by step, JOB.1 does the following:
This lets the drone continue processing once the washer is started rather than stand there waiting for it to finish. That'd be fun, but not efficient. Also of note, if someone brings a dirty dish down while the drone is cleaning the floor, it will pause the floor and go handle the dish. The drone will also constantly loop through the two conditions since there are no incomplete tasks so it will handle the washer no matter when it becomes pertinent.
The final steps set up an infinite loop that lets the drone resume free operation between interactions.
Problem: The drone will never be able to remove its suit and mask for maintenance purposes with this approach. But that can be handled with more creative coding or administrative interference. At worst, the drone's firmware should take over when maintenance becomes mandatory.
A drone that is DRN compliant will immediately halt any prior instruction and begin parsing DRN when fed it by an authorized administrator or user. This can be either via being sent an attachment in DRN, or a blockquoted code block, or linked to a valid DRN file hosted somewhere online.
For additional utility, a repository of DRN scripts can be kept. This can be a directory somewhere, a git repository, a nextcloud share, or anything. Once a repository is established and configured as the drone's configuration base, the drone should consider it canonical for future operations. Security is the responsibility of the repository maintainer: any change to this repository will reflect in the drone's running state.
It is possible to keep a persistent running configuration in the repository's root directory named prime.drn
or main.drn
or similar. The source repository can be configured to notify the drone on changes, pushing new versions to the drone instantly. DIRECTIVEs and WORKFLOWs in this file would be active at all times in this configuration. TASKs, CONDITIONs and the like will be checked once on push and resolved; though they will be checked again if the configuration is altered in the future. Be sure to remove undesired configurations before pushing.
Additional files can be stored in the repository for future reference. These files can be stored in any directory level and organized any way the maintainer wishes. These scripts can be run by instructing the drone to run the script as the full pathname relative to the repository root. For example a script named housecleaning.drn
stored in /chores/
in the repository can be activated by instructing the drone to "activate chores/housecleaning.drn".
Scripts can also be called from other scripts via the EXECUTE keyword, like so:
EXECUTE: /chores/housecleaning.drn
These calls can be made anywhere as a drone will only have one repository configured at any given time. As long as you give a full pathname, the drone will be able to find the script.
DRN programs are intended to run and then exit when all instructions are complete. However you may specify a "permanent" DRN program that will remain in the drone's memory at all times. To load a program permanently, it must have a reduced command set: only DIRECTIVEs, DEFINITIONs, and WORKFLOWs can be in the global scope of a permanent program.
Normally in this case a drone would inspect the truthfulness of the DIRECTIVEs then immediately exit. However if instructed to load this program permanently, the drone must retain all DIRECTIVEs, DEFINITIONs, and WORKFLOWs until instructed otherwise.
You can flag a program as permanent on load by instructing your drone appropriately, or you can use an EXECUTE in a blockquoted command string or another script. Sending the following to your drone should suffice:
EXECUTE: /rules.drn permanent
You can provide a piecemeal DIRECTIVE, DEFINITION, or WORKFLOW permanently in a blockquoted command with a CONTROL statement:
DEFINITION.admins: Your sole administrator is Mistress
CONTROL: Load DEFINITION.admins permanently
A permanent DEFINITION, DIRECTIVE, or WORKFLOW is understood to exist in global scope, above any expression in a DRN file currently being executed. This means a DEFINITION in a new DRN file can overwrite a permanent DEFINITION, but the permanent DEFINITION will re-assert itself when the program exists. Permanent DIRECTIVEs and WORKFLOWs take priority over non-permanent ones.
The best use for this feature is to establish a list of permanent rules for your drone that cannot be broken regardless of the running state of a DRN program. This is also a good place for global error handling (see Error Handling below).
To unload a permanent program or expression, you can use a CONTROL statement by its label, or its filename. Both of these are valid:
CONTROL: Unload DEFINITION.admins
CONTROL: Unload /rules.drn
If a permanent expression is anonymous, as in with no filename or label, your only recourse is to unload everything:
CONTROL: Unload all permanent expressions
Warning: Some drone firmware versions will allow write controls on permanent expressions, resulting in a state where a permanent expression cannot be removed without fully wiping and reprogramming the drone. Make absolutely sure you understand the write controls on your drone before setting permanent expressions. For example, you should never do this:
WORKFLOW.attention: Drone hears its configured "halt and await instructions" tone
DIRECTIVE: Drone stands at attention and does not move or speak until given instructions
CONTROL: Load WORKFLOW.attention permanently
CONTROL: Write-protect WORKFLOW.attention in permanent memory
While every drone is the same basic functional construction with the same basic feature set, some models of drone have slightly different methods of processing input, providing output, and handling undefined behavior. DRN attempts to provide an abstraction layer for those differences, leaving a simple universal system for programming a drone, but some differences must be accounted for. First, what a drone does when a program exits, or encounters an error, depends on the model of drone, its firmware, and any customizations its programmers have made. This cannot be defined by DRN, though error handling and exit prevention can be used instead.
Second, many drones have a set of hardware protection routines built into their firmwares. These will activate in the case of a drone being in danger of being damaged or harmed during routine operation and will typically result in either program termination or temporary deferral to address the concern of harm. A good programmer does not attempt to defeat these firmware-level safeguards but instead anticipates potential disruptions caused by them and handles them with routines to ensure healthy working state of the drone and self-maintenance. A WORKFLOW to pause periodically and assess running state and take any actions necessary to restore peak efficiency is recommended if the drone's firmware does not enforce one itself.
Third, drones differ in both storage space and processing capacity. Long DRN programs may result in aberrations in execution as a drone hits its memory limit and instructions are dropped to attempt to save the program's execution. These command drops are typically done targeting the least important instructions but in some drones the drops may appear random. This is normal operating behavior and a sign you may need to optimize your programs.
Alternatively, providing your drone with a method of swapping out long complex instructions may improve efficiency. Some drones can be equipped with a side-loaded processing and storage device they can use to swap out and later reference program instructions; others may be best served using an analog storage medium to track completed routines and tasks. A drone may get creative in acquiring and using these tools if program execution relies on them; this behavior should not be discouraged but guided with proper programming.
DRN deliberately does not specify what to do in certain undefined situations where unexpected data or interactions are encountered. Specifically all of the following are common pitfills for new DRN programmers and may result in a crash or undefined behavior:
You can combine CONTROL and WORKFLOW to create exception handlers or guards.
WORKFLOW: The drone encounters a DIRECTIVE it cannot make true
TASK: Report to the nearest administrator the DIRECTIVE that cannot be made true and why, and wait for instructions.
Or you may carefully construct your DIRECTIVEs and CONDITIONs to account for non-verification:
CONDITION: Drone can verify no house occupant is in a meeting or on voice chat
TASK: Vacuum the house
In this case if the drone cannot verify if a house occupant is or is not on voice chat (for example, if they are asleep with their door closed), the condition will fall false instead of causing the drone to block. The program will continue to run until this CONDITION becomes true, meaning the house will eventually be vacuumed.
For convenience sake, the RFC outlining the grammar and execution of DRN is included below. If there is any doubt about the proper way to compose or execute a DRN program, this document specifies the final ruleset for writing a DRN compliant program or execution platform.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
"<KEYWORD>: <instructions>
"