===============================================================================
Universal Doom Map Format Specification v0.99 - 04/30/08

Written by James "Quasar" Haley - haleyjd@hotmail.com
===============================================================================

=======================================
I. Grammar / Syntax
=======================================

    translation_unit := global_expr_list
    global_expr_list := global_expr global_expr_list
    global_expr := block | assignment_expr
    block := identifier '{' expr_list '}'
    expr_list := assignment_expr expr_list
    assignment_expr := identifier '=' value ';'
    identifier := [A-Za-z0-9_]+
    value := integer | float | quoted_string | unquoted_string
    integer := [+-]?[1-9]+[0-9]* | 0[0-9]+ | 0x[0-9A-Fa-f]+
    float := [+-]?[0-9]+'.'[0-9]*([eE][+-]?[0-9]+)?
    quoted_string := "([^"\\]*(\\.[^"\\]*)*)"
    unquoted_string := [^{}();"'\n\t ]+


Global assignments and named/indexed global blocks are the only top-level
entities supported. There are no comments. Whitespace is strictly ignored.

Blocks begin with a keyword identifier. An example of a minimally-defined
entity follows:

    linedef { id = 1; }

Compliant parsers will ignore all unknown keywords in global assignments, 
block-level assignments, and block headers. Compliant parsers should attempt
to preserve as much of such information as is possible by using a flexible
mapping such as hashing.

A field which specifies "boolean" semantics shall accept unquoted string
value "true" to mean that the field is asserted, and unquoted string value 
"false" to meant that the field is unasserted.

Fields which do not appear in a block take on their default value. This
allows minimal specification.


=======================================
II. Implementation Semantics
=======================================

------------------------------------
II.A : Storage and Retrieval of Data
------------------------------------

Block-defined entities are written and read in top-to-bottom order. For
example, the following linedefs can be assigned in order to a contiguous
block of memory serving as the implementing port's lines array:

    linedef { id = 1; }
    linedef { id = 2; }
    linedef { id = 3; }
    linedef { id = 4; }
    

-----------------------------------
II.B : Storage Within Archive Files
-----------------------------------

UDMF maps shall be layed out within the archive directory as follows:

    (HEADER)
    TEXTMAP
    ... 
    ENDMAP

(HEADER) = Any lump name from 1 to 8 characters. Serves as the name of the map.
TEXTMAP  = Single UDMF lump containing all data for the map.
...      = Blockmap, reject, BSP tree, and port-specific lumps, if any. The
           format and presence of these resources are not defined by UDMF.
ENDMAP   = Required closing lump.

Implementing editors and source ports may distinguish a UDMF map from a
traditional binary map by testing the name of the first directory entry
following the map header. Implementing resource editors will be capable of
keeping all lumps for the map, even non-standard ones, together by properly
scanning for the ENDMAP entry. Non-implementing resource editors will not
recognize the sequence of lumps as a map, and may thus be less likely to
interfere with the order or presence of the lumps.

Use of non-implementing resource editors to manipulate UDMF-map-containing WAD
files is not recommended, however.
    
    
--------------------------------
II.C : Implementation Dependence
--------------------------------

A port's list of supported non-standard fields must be provided to implementing
editors, where they can be provided to the end user as controls, as options
in a dropbox, or through the ability to input any arbitrary 
"identifier = value;" pair in a text box.

Every UDMF map must contain somewhere within the file one or more "namespace" 
identifier statements, which declare the source port implementation relative to 
which this map is to be interpreted. The last such statement parsed shall be the
one which defines the value of the "namespace" variable for the map.

Example:

    namespace = ZDoom;
    
Implementing source ports may ignore this information, or they may use it to 
perform automatic runtime translation of maps they would otherwise be unable to 
support.

Implementing source ports should publicly document the value of the "namespace"
variable they intend to identify with when establishing support for UDMF, and
avoid conflicts with existing implementations at all costs.


=======================================
III. Standardized Fields
=======================================

The UDMF v0.99 specification considers the following fields standard. They must
be supported by all implementing source ports and editors. Comments shown within
the following blocks are for illustrative purposes only; this is not valid UDMF
syntax.

   linedef
   {
      id = <integer>; // ID of line. Interpreted as tag or scripting id.
                      // Default = -1.
      
      v1 = <integer>; // Index of first vertex. No valid default.
      v2 = <integer>; // Index of second vertex. No valid default.
      
      blocking      = <string>; // true = line blocks things. Default = false.
      blockmonsters = <string>; // true = line blocks monsters. Default = false.
      twosided      = <string>; // true = line is 2S. Default = false.
      dontpegtop    = <string>; // true = upper texture unpegged. Def = false.
      dontpegbottom = <string>; // true = lower texture unpegged. Def = false.
      secret        = <string>; // true = drawn as 1S on map. Default = false.
      soundblock    = <string>; // true = blocks sound. Default = false.
      dontdraw      = <string>; // true = line never drawn on map. Def = false.
      mapped        = <string>; // true = always appears on map. Def = false.
      passuse       = <string>; // true = passes use action. Default = false.
      repeatspecial = <string>; // true = repeatable special. Default = false.
      
      playercross   = <string>; // true = player can cross. Default = false.
      playeruse     = <string>; // true = player can use. Default = false.
      monstercross  = <string>; // true = monster can cross. Default = false.
      impact        = <string>; // true = projectile can activate. Def = false.
      push          = <string>; // true = player/monster can push. Def = false.
      missilecross  = <string>; // true = projectile can cross. Default = false.
      
      // TODO: other standardized SPAC combinations?
      
      special = <integer>; // Special. Default = 0.
      arg0    = <integer>; // Argument 0. Default = 0.
      arg1    = <integer>; // Argument 1. Default = 0.
      arg2    = <integer>; // Argument 2. Default = 0.
      arg3    = <integer>; // Argument 3. Default = 0.
      arg4    = <integer>; // Argument 4. Default = 0.
      
      frontside = <integer>; // Sidedef 1 index. No valid default.
      backside  = <integer>; // Sidedef 2 index. Default = -1.
   }
   
   sidedef
   {
      offsetx = <integer>; // X Offset. Default = 0.
      offsety = <integer>; // Y Offset. Default = 0.
      
      texturetop    = <string>; // Upper texture. Default = "-".
      texturebottom = <string>; // Lower texture. Default = "-".
      texturemiddle = <string>; // Middle texture. Default = "-".
      
      sector = <integer>; // Sector index. No valid default.
   }
   
   vertex
   {
      x = <integer>; // X coordinate. No valid default.
      y = <integer>; // Y coordinate. No valid default.
   }
   
   sector
   {
      floorheight   = <integer>; // Floor height. Default = 0.
      ceilingheight = <integer>; // Ceiling height. Default = 0.
      
      floorpic   = <string>; // Floor flat. No valid default.
      ceilingpic = <string>; // Ceiling flat. No valid default.
      
      lightlevel = <integer>; // Light level. Default = 255? (FIXME)
      
      special = <integer>; // Sector special. Default = 0.
      tag     = <integer>; // Sector tag. Default = 0.
   }
   
   thing
   {
      tid = <integer>; // Thing ID. Default = 0.
      
      x = <integer>; // X coordinate. No valid default.
      y = <integer>; // Y coordinate. No valid default.
      
      height = <integer>; // Z height relative to floor. Default = 0.
                          // (Relative to ceiling for SPAWNCEILING items).
                          
      angle = <integer>; // Map angle of thing. Default = 0 (East).
      
      type = <integer>; // DoomedNum. No valid default.
      
      easy      = <string>; // true = in skills 1/2. Default = false.
      normal    = <string>; // true = in skill 3. Default = false.
      hard      = <string>; // true = in skill 4/5. Default = false.
      ambush    = <string>; // true = thing is deaf. Default = false.
      notsingle = <string>; // true = not in SP mode. Default = false.
      notdm     = <string>; // true = not in DM mode. Default = false.
      notcoop   = <string>; // true = not in Coop. Default = false.
      dormant   = <string>; // true = dormant thing. Default = false.
      class0    = <string>; // true = Present for pclass 0. Default = false.
      class1    = <string>; // true = Present for pclass 1. Default = false.
      class2    = <string>; // true = Present for pclass 2. Default = false.
      
      special = <integer>; // Scripting special. Default = 0;
      arg0    = <integer>; // Argument 0. Default = 0.
      arg1    = <integer>; // Argument 1. Default = 0.
      arg2    = <integer>; // Argument 2. Default = 0.
      arg3    = <integer>; // Argument 3. Default = 0.
      arg4    = <integer>; // Argument 4. Default = 0.
   }
   
   
===============================================================================
EOF
===============================================================================