<!-- Level DTD : version 1.05 -->
<!-- History of file format :
...
1.05: Added orientation for condition "position".

-->


<!-- first, the internal entities -->

<!-- The test on the game status -->
<!ENTITY % tests "onboard|state|position|turntype|inf|sup|equal|true|false">

<!ENTITY % values "random|turn|leaved|AP|taken|size|dead|blockedentry|value|product|sum">

<!-- We are desining a level ... -->
<!-- The level includes :
      - a map
      - an initialisation
      - a winning condition
     You may had some named zones or zone set at the beginning for later use -->
<!ELEMENT level (zone*,zone_set*,map,global,marine_cfg,genestealer_cfg)>
<!ATTLIST level
        version CDATA #REQUIRED
        edition (first|second|both) #REQUIRED>

<!-- The map basically includes entities -->
<!ELEMENT map (floor|door|entry|bulkhead|extensible|exit)+>
<!-- The size of the level is needed from the beginning ... -->
<!ATTLIST map
	width  CDATA #REQUIRED
	height CDATA #REQUIRED>

<!-- First map entity : the empty floor -->
<!ELEMENT floor (zone)>
<!-- Another entity : the door  -->
<!ELEMENT door (zone)>
<!-- The door can be opened or closed -->
<!ATTLIST door
	open (yes|no) "no"
	vertical (yes|no) "no">
<!-- An entry is where the blip come from -->
<!ELEMENT entry (zone)>
<!ATTLIST entry
        direction (north|south|east|west) #REQUIRED
        maxblip CDATA "3">

<!-- THe bulhead. Normally you can't open them, but sometimes ...-->
<!ELEMENT bulkhead (zone)>
<!ATTLIST bulkhead
	open (yes|no) "yes"
	can_open (yes|no) "no"
        can_closed (yes|no) "yes"
        vertical (yes|no) "no">

<!-- Extensible object. By default, this object is like a wall.
     You need to specify its name and its graphic representation.
     You can specify 
  - if you can see through it and move over it,
  - if it is attackable
  - if it is shootable (and how many shots are needed to destroy it)
  - it it is fireable
  - if a marine can take it (and how many APs it cost to take it)
  - if a marine can drop it and (and how many APs it cost)
  - if a marine can transfer it to another unit (and how many APs it cost)
  - if a marine can shoot or use door with the object taken.

  The ExtensibleObject can be a map object or a unit, it depends and
     where your found it (in a map element or in an action element).
 -->
<!ELEMENT extensible (zone|ref)?>
<!ATTLIST extensible
        desc CDATA #REQUIRED
        graphic (toxinduct|archives|machinery) #REQUIRED
        empty (yes|no) "no"
        attackable (yes|no) "no"
        shootable CDATA "0"
        fireable (yes|no) "no"
        takeable CDATA "0"
        dropable CDATA "0"
        transferable CDATA "0"
        shootwith (yes|no) "yes"
        usedoorwith (yes|no) "yes">


<!-- The exit element contain the object that can exit -->
<!ELEMENT exit (zone)>
<!ATTLIST exit
	player (marine|genestealer) #REQUIRED
        direction (north|south|east|west) #REQUIRED>

<!-- A zone set is there to be able to name them -->
<!ELEMENT zone_set ((zone)*|ref)>
<!-- The zone set name is used to referenced already defined zone sets. When
     used as a reference, the zone set must be empty, if not, it's considered
     as a redefinition -->
<!ATTLIST zone_set
	name ID #IMPLIED>

<!-- A zone desfine a set of cases 
     If needed, we'll be able to define more complexe figures
     and just change the zone definition (for circles or intersections ...) -->
<!ELEMENT zone ((case|rect|zone_set)*|ref)>
<!-- The zone name is used to referenced already defined zones. When used as a
     reference, the zone must be empty, if not, it's considered as a
     redefinition -->
<!ATTLIST zone
	name ID #IMPLIED>
<!-- A single case ... -->
<!ELEMENT case EMPTY>
<!ATTLIST case 
	x CDATA #REQUIRED
	y CDATA #REQUIRED>
<!-- A whole rectangle of cases -->
<!ELEMENT rect EMPTY>
<!ATTLIST rect
	x1 CDATA #REQUIRED
	y1 CDATA #REQUIRED
	x2 CDATA #REQUIRED
	y2 CDATA #REQUIRED>

<!-- Genestealer turn -->
<!ELEMENT genestealer_cfg (init?,begin?,win)>
<!-- Marine turn -->
<!ELEMENT marine_cfg (init?,begin?,win)>
<!-- When is it a draw ? -->
<!ELEMENT draw (cond)>

<!-- The initialisation must initialise the marine AND the genestealer -->
<!ELEMENT init (action+)>

<!-- Win conditions : marine and genestealer can win, but how ? :o) -->
<!ELEMENT win (cond)>

<!ELEMENT begin (action+)>

<!-- Possible actions 
     If cond if verified, do the action, if there is no cond, assume true -->
<!ELEMENT action (cond?,(place|destroy|modify))>

<!ELEMENT place ((object|cat|extensible|sergeant|flamer|terminator|genestealer|blip|squad),
                 zone_set)>
<!ATTLIST place
	number CDATA "1"
	alone (yes|no) "no">

<!ELEMENT destroy (ref|find)>

<!ELEMENT find ((object|sergeant|flamer|terminator|genestealer|blip|door|bulkhead|extensible|flame|entry),
		cond)>

<!-- By default, a squad is a sergeant, a flamer and 3 terminators -->
<!ELEMENT squad ((sergeant|flamer|terminator|genestealer|blip)*|ref)?>
<!ATTLIST squad
	name ID #REQUIRED
	direction (north|south|east|west|none) "none"
	image_set CDATA #IMPLIED>

<!-- units -->
<!ELEMENT sergeant (ref?)>
<!ATTLIST sergeant
	direction (north|south|east|west|none) "none"
	name ID #IMPLIED>
<!ELEMENT flamer (ref?)>
<!ATTLIST flamer
	direction (north|south|east|west|none) "none"
	name ID #IMPLIED
	charger CDATA "1">
<!ELEMENT terminator (ref?)>
<!ATTLIST terminator 
	direction (north|south|east|west|none) "none"
	name ID #IMPLIED>
<!-- generic marine -->
<!ELEMENT marine (ref?)>
<!ATTLIST marine 
	name ID #IMPLIED>
<!ELEMENT blip (ref?)>
<!-- This attribute allow the level to deactivate the waiting rule for the
     blips (this rule specifies that a blip has to wait one turn before
     entering if a marine is near the entry -->
<!ATTLIST blip
	name ID #IMPLIED
	wait (yes|no) "yes"
	size (random|0|1|2|3|4|5|6) "random">
<!ELEMENT genestealer (ref?)>
<!ATTLIST genestealer
	direction (north|south|east|west|none) "none"
	name ID #IMPLIED>
<!-- generic alien -->
<!ELEMENT alien (ref?)>
<!ATTLIST alien
	name ID #IMPLIED>

<!-- object -->
<!ELEMENT object EMPTY>
<!-- We may change the CDATA for the list of valid object in the future -->
<!ATTLIST object
	type CDATA #REQUIRED>
<!ELEMENT cat (ref?)>
<!ATTLIST cat
	name ID #IMPLIED>

<!-- A condition is define as a logical connector and some test on the game
     status -->
<!ELEMENT cond (condref| %tests;|and|or|not|eval)>

<!-- If switch_yes is yes, the test is a switch: if it's true once in the game,
     it stays true until the end 
     If switch_no is yes, the test is a switch but it will keep its value once
     it becomes false
     If both are true, the test will keep its first value -->
<!ATTLIST cond
	switch_yes (yes|no) "no"
	switch_no (yes|no) "no"
	name ID #IMPLIED>
<!ELEMENT condref EMPTY>
<!ATTLIST condref
	name IDREF #REQUIRED>
<!-- The connectors ... 
     The subconditions are evaluated until we can know the value of the
     connector, not after -->
<!ELEMENT and (cond,cond+)>
<!ATTLIST and
	test_all (yes|no) "no">
<!ELEMENT or (cond,cond+)>
<!ATTLIST or
	test_all (yes|no) "no">
<!ELEMENT not (cond)>
<!ELEMENT true EMPTY>
<!ELEMENT false EMPTY>
<!-- Is there any number of unit killed ? -->
<!ELEMENT dead EMPTY>
<!-- there must be at least as mush as min killed must less than max, do max =
     0 means no kill -->
<!ATTLIST dead
	type (marine|genestealer|flamer|terminator|captain|cat|extensible) #REQUIRED>
<!-- Is there some unit in a given position ? Use this to find and reference a unit.
     All found units are referenced and in the tests involving the reference -->
<!ELEMENT position (zone)>
<!ATTLIST position
	type (terminator|flamer|captain|genestealer|marine|blip|alien|cat|extensible) #REQUIRED
	name ID #IMPLIED
        dir1 CDATA "none"
        dir2 CDATA "none"
        dir3 CDATA "none">
<!-- How is the map zone ? -->
<!ELEMENT state (zone)>
<!-- If entire is set to "yes", so all the cases of the zone have to be in the
     defined state. Else, at least one case has to be in that state
     Here's an exmplanation for the states :
      - onfire : The flamer put the zone on fire and there is still some fire
	just before the end of the turn
      - free : There is nothing on the zone, if there is a door or a bulkhead
	it's open, etc.
      - blocked : Something block the way, a closed door, a closed bulkhead, an
	OBJECT
      - occupied : There is a unit on the case (any unit)
     -->
<!ATTLIST state
	entire (yes|no) #REQUIRED
	state (onfire|free|blocked|occupied) #REQUIRED>
<!-- Test if something is on the board succeed if there is at least one -->
<!ELEMENT onboard EMPTY>
<!ATTLIST onboard
	type (object|terminator|flamer|captain|genestealer|marine|blip) #REQUIRED
	name ID #IMPLIED>

<!-- test if previous turn was marine, genestealer or cat turn. -->
<!ELEMENT turntype EMPTY>
<!ATTLIST turntype
        type (marine|genestealer|cat) #REQUIRED>

<!-- test the equality of two values -->
<!ELEMENT equal ((%values;),(%values;))>

<!-- test if the first value is inferior to the second -->
<!ELEMENT inf ((%values;),(%values;))>

<!-- test if the first value is superior to the second -->
<!ELEMENT sup ((%values;),(%values;))>

<!-- the eval block allows for computations -->
<!ELEMENT eval (%values;)>
<!ATTLIST eval
	name ID #REQUIRED>

<!ELEMENT sum ((%values;),(%values;)+)>

<!ELEMENT product ((%values;),(%values;)+)>


<!-- Return the left action points of a unit as a reference can contains many
     units "op" is the operation to decide which value to return :
      - min  = minimum of the APs
      - max  = maximum of the APs
      - sum  = sum of the APs
      - prod = product of the APs
      - mean = mean of the APs (rounded) -->
<!ELEMENT AP EMPTY>
<!ATTLIST AP
	op (min|max|sum|prod|mean) "max"
	ref IDREF #REQUIRED>

<!-- return the number of taken object of a unit as a reference.
     In the current implementation a unit can take only one object. -->
<!ELEMENT taken EMPTY>
<!ATTLIST taken
        ref IDREF #REQUIRED>

<!-- Return the current turn (first turn is 1) -->
<!ELEMENT turn EMPTY>

<!-- return the number of entries blocked by closed bulkhead -->
<!ELEMENT blockedentry EMPTY>

<!-- Test if a certain amount of unit leaved the board -->
<!ELEMENT leaved EMPTY>
<!ATTLIST leaved
	type (terminator|flamer|captain|genestealer|marine|blip|alien|cat|extensible) #REQUIRED >

<!-- Reference of an object -->
<!ELEMENT ref EMPTY>
<!ATTLIST ref
	name IDREF #REQUIRED>

<!-- number may be "inf" for MAX_INT value ... -->
<!ELEMENT value EMPTY>
<!ATTLIST value
	number CDATA #REQUIRED>

<!ELEMENT random EMPTY>
<!ATTLIST random
        max CDATA "6">

<!-- Return the number of elements in a reference -->
<!ELEMENT size EMPTY>
<!ATTLIST size
	ref IDREF #REQUIRED>

<!-- Global configuration
     It includes an initialisation to do before the other ones, the draw
     condition and the first to play -->
<!ELEMENT global (leveldesc,init?,draw?,first,winpriority,turnmsg?)>
<!ELEMENT leveldesc (title,author?,narration?,objectives?,forces?,conditions?, objective_squares?)>

<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT narration (#PCDATA)>
<!ELEMENT objectives (#PCDATA)>
<!ELEMENT forces (#PCDATA)>
<!ELEMENT conditions (#PCDATA)>

<!ELEMENT objective_squares (zone_set)>

<!ELEMENT first EMPTY>
<!ATTLIST first
	player (marine|genestealer) #REQUIRED>
<!ELEMENT winpriority EMPTY>
<!ATTLIST winpriority
	player (marine|genestealer) #REQUIRED>

<!ELEMENT turnmsg ((fixedmsg|%values;)*)>
<!ELEMENT fixedmsg EMPTY>
<!ATTLIST fixedmsg 
           msg CDATA #REQUIRED>
