A4 Engine v2.4 Reference
The A4 Engine is a small engine for 2D action RPG games created by Santiago Ontañón (2014). Versions up to 1.2.2 were created in JavaScript. The current version, 2.4 has been created in C++, but a JavaScript version still exists (cross compiled to JavaScript via Emscripten). The A4 Engine was created specifically to test procedural content generation techniques, and thus, games are completely defined as xml files that are loaded by the game engine for execution. This page is NOT supposed to be a tutorial, but just a reference of the syntax used in the game definition files.
To create a game, the following set of files are needed:
The engine ships with an example game (Aventura 4), that contains all of these files. The main file, the game definition file, is called aventura4.xml and includes references to all the other files.
Outline of the remainder of this page:
Game Definition File
The Game definition file has the following structure:
<A4Game name="My Game Name" title="My Game Title" subtitle="My Game Subtitle"
allowSaveGames="true/false"
allowTalking="true/false"
allowInventory="true/false"
allowMagic="true/false"
allowStats="true/false">
<titleImage>title.png</titleImage>
<story>
<line> ... </line>
...
<line> ... </line>
</story>
<ending id="ENDING_ID">
<line> ... </line>
...
<line> ... </line>
</ending>
<tiles sourcewidth="32" sourceheight="32" targetwidth="32" targetheight="32">
<types file="graphics.png">
...
</types>
<seeThrough file="graphics.png">
...
</seeThrough>
<canDig file="graphics.png">
...
</canDig>
<animation name="coinpurse" dx="1" dy="1" period="4" looping="false" file="graphics2x.png">9</animation>
<animation name="curious" dx="1" dy="1" period="8" looping="true" file="graphics2x.png">74,-1</animation>
<animation name="scared" dx="1" dy="1" period="8" looping="true" file="graphics2x.png">84,-1</animation>
<animation name="angry" dx="1" dy="1" period="8" looping="true" file="graphics2x.png">94,-1</animation>
<animation name="tired" dx="1" dy="1" period="8" looping="true" file="graphics2x.png">104,-1</animation>
<animation name="happy" dx="1" dy="1" period="8" looping="true" file="graphics2x.png">75,-1</animation>
<animation name="magic missile" dx="1" dy="1" period="8" looping="false" file="graphics2x.png">114</animation>
<animation name="fireball" dx="1" dy="1" period="8" looping="false" file="graphics2x.png">124</animation>
<animation name="incinerate" dx="1" dy="1" period="8" looping="false" file="graphics2x.png">134</animation>
</tiles>
<characterDefinition file="characters1.xml"/>
...
<characterDefinition file="charactersn.xml"/>
<objectDefinition file="objects1.xml"/>
...
<objectDefinition file="objectsn.xml"/>
<map file="map1.xml"/>
...
<map file="map1.xml"/>
<player class="PLayerClass1" x="12" y="14" map="0"/>
...
<player class="PLayerClassn" x="12" y="14" map="0"/>
<onStart>
... [script] ...
<onStart/>
... [story state and event rules] ...
</A4Game>
The tags have the following meaning:
- A4Game: this is the main tag, it has one parameter "name", which contains the name of the game (this is an identifier, such as "mygamev1"), "title" is the actual title of the game, such as "The Quest of Something", and "subtitle" is an optional parameter, in case your game title has a subtitle.
- allowSaveGames: determines whether the engine will let the player save and resume games. If this is set to "false", the engine will take the usual rogue-like behavior, with permadeath. If set to "true", the engine will show up to four save-game slots, and the player will be able to freely save and resume games.
- allowTalking/allowInventory/allowMagic/allowStats: activate or deactivate features of the engine (by default they are all active). This disallows the player from using these features. However, characters can still cast spells via scripts, or take and use objects, etc. via scripts even if these features are activated. Basically, this just disables the user form being able to issue those commands, and also removes the corresponding elements from the GUI.
- titleImage: with which you specify the image to be displayed in the background of the main menu.
- story: here you can add a set of lines that contain the back story of your game
- ending: the text to be displayed when a player finishes the game. You can specify several endings, each of them with a different ID (when you execute the "gameComplete" command, you must specify which is the ID of the ending that was triggered).
- tiles: here you define the graphics file that your game will use. You need to specify 4 parameters:
- sourcewidth: the width of each tile in your graphics file.
- sourceheight: the height of each tile in your graphics file.
- targetwidth: the width of each tile when rendered in the game.
- targetheight: the height of each tile when rendered in the game.
For the graphics file, you need to specify three matrices: types, seeThrough, canDig. Each matrix (with one element per tile in the graphics file) specifies whether characters can walk or not over tiles (types): 0 is walkable, 1 is wall, 2 is tree, 3 is choppable tree, 4 is water; whether they can see through them (0) or not (1) (seeThrough) or whether tey can dig (1) on them or not (0) (canDig).
Also, you need to specify some default animations ("coinPurse", etc.), for some graphics that the engine needs to display such as spells, coin purses, and emoticons.
- characterDefinition: specifies the character definition files.
- objectDefinition: specifies the object definition files.
- map: specifies the map definition files.
- player: specifies the class of the character the player will play, and the coordinates and map where it will start. More than one character can be specified, if the player is to control a group.
- onStart: a script that will be executed as soon as the game starts.
Additional
event rules can be added, which will be checked at each frame of the game during gameplay.
back to top
Character Definition Files
Character definition files are used to define player characters, NPCs and enemies. Each file has the following structure:
<Characters>
...
<CharacterClass class="MyCharacterClass" super="SuperClasses" name="My Character Name">
<animation name="animation-name" dx="1" dy="1" period="4" looping="false" file="graphics.png">animation sequence</animation>
...
<animation name="animation-name" dx="1" dy="1" period="4" looping="false" file="graphics.png">animation sequence</animation>
<attribute name="attribute name" value="attribute value"/>
...
<attribute name="attribute name" value="attribute value"/>
<items>
... [objects in the inventory] ...
</items>
... [story state, event, conversation and inference rules] ...
<onStart>
... [script] ...
<onStart/>
<onEnd>
... [script] ...
<onEnd/>
</CharacterClass>
The tags have the following meaning:
- CharacterClass: this is the main tag to define a character, it contains the class name (e.g., "Snake", "Skeleton", "Warrior", etc.)
- SuperClasses: a comma separated list of the super classes. All the definitions in the super classes will be added to the character class. All class hierarchies for characters/objects must end in some base class, that can currently be "Item", "Container", "Character" or "Vehicle". It is possible to add an asterisk to a superclass name, e.g. super="*Skeleton", in this case, "Skeleton" will be a superclass, but its definition is not used to fill in the features of this class.
- animation: this defines how the characters will look when rendered in the screen. The following animations can be defined:
- idle-left/idle-up/idle-right/idle-down: when characters stand still
- moving-***: when characters walk
- attacking-***: when cahracters attack
- interacting-***: when characters use objects
- casting-***: when characters cast spells
- talking-***: when characters talk
- death: when characters die (this animation should NOT be looping, the character will disappear when the animation ends, there is no death animation specified, characters will disappear immediately)
The idle animations must be specified. All the others are optional (their defaults are the idle animations for each direction). For each animation, the following needs to be specified:
- dx,dy: the width and height in tiles of the character
- period: how many frames to hold each frame
- looping: play once or loop
- file: the graphics file from where to get the graphics (must have been specified in the main game definition file first)
- the actual animation sequence: sequence of tile IDs (tiles start counting from 0 in the top-left of a graphics file)
- attribute: the attributes (like hitpoints, move speed, attack, defense, etc.) a character will have. All characters need to specify at least the following attributes: gold, hp, mp, attack, defense, canSwim, walk_speed. Additionally, player characters need to specify: "attack_modifier" and "defense_modifier" (multipliers to the attack bonus of weapons and armor). NPCs and Enemies must specify "gives_experience" (experience when players kill them), "sightRadius" (how far can they see) and picky (whether they are picky or not when talking to them). "respawn" (the probability of this character respawning after death; characters respawn after 2000 cycles of being dead, and only if there is no player character around to prevent the player from seeing an enemy pop out of thin air). "canWalk" (by default it is the opposite of "canSwim", but both can be set to true). All attributes can specify a value, e.g. "4", a range, e.g. "10-20", or an alternative, e.g. "0,2".
If the character should be allowed to level up (right now, this is only allowed for player characters), the attribute "experienceToLevelUp" must be defined. Additionally, for all of those attributes that will be modified when leveling up, you need to specify either a "levelupadd" or a "levelupmultiply" value. For example, if we define an attribute like this: <attribute name="attack" value="1" levelupadd="1-2"/>, then the attribute will start with value "1", and every time the character levels up, 1-2 points will be added. "hp" and "mp" are special attributes, and when they increase, "max_hp" and "max_sp" (implicit attributes that not need be defined) are also increased. Moreover, notice that you also should increase the "experienceToLevelUp" attribute. For example, defining it like this: <attribute name="experienceToLevelUp" value="10" levelupmultiply="1.5"/>
- items: lets you specify items in the inventory of a character. The syntax for defining items, along with a list of predefined items is explained here
- onStart: a script that will be executed as soon as the character spawns.
- onEnd: a script that will be executed as soon as the character dies.
Additional
event rules,
conversation graph and
inference rules can be added, which will be checked at each frame of the game during gameplay. These define how the characters behave in front of story events, or when other characters talk to them. All of these rules have access to a common "memory" of the things the character knows. This is further described in the
AI section.
back to top
Object Definition Files
When defining maps and characters, you might want to add items to the inventory of characters, or objects to the maps, etc. A4 allows you to define items/objects using XML syntax, for example:
<object class="HPPotion" completeRedefinition="true">
<animation name="idle" dx="1" dy="1" period="1" looping="false" file="graphics.png">1</animation>
<attribute name="ID" value="657"/>
<attribute name="name" value="HP Potion+10"/>
<attribute name="gold" value="25"/>
<attribute name="takeable" value="true"/>
<attribute name="usable" value="true"/>
<attribute name="hp" value="10"/>
</object>
>
Where the class of item/object is defined in the "class" attribute, "completeRedefinition" should be set to "true" if we want to redefine completely an object (i.e., if we want the A4 Engine to ignore the object definition file for this type of object).
The subtags are equivalent to those required to define object types in the object definition file. The object definition files have the following structure:
<Objects>
<ObjectClass class="MyObjectClass" super="SuperClasses" name="MyObjectName">
<animation name="animation-name" dx="1" dy="1" period="4" looping="false" file="graphics.png">animation sequence</animation>
...
<animation name="animation-name" dx="1" dy="1" period="4" looping="false" file="graphics.png">animation sequence</animation>
<attribute name="attribute name" value="attribute value"/>
...
<attribute name="attribute name" value="attribute value"/>
<items>
... [objects in the inventory] ...
</items>
... [story state and event rules] ...
</ObjectClass>
...
</Objects>
The tags have the following meaning:
- ObjectClass: this is the main tag to define anew object/item type.
- SuperClasses: a comma separated list of the super classes. All the definitions in the super classes will be added to the object. All class hierarchies for characters/objects must end in some base class, that can currently be "Item", "Container", "Character" or "Vehicle".
- animation: this defines how the objects will look when rendered in the screeen. See the character definition section for more info on this. The default animation for items is called "idle", which you should define for any item. For doors, you should specify the "open" and "closed" animations, for how the door loks when it's open or closed, etc.
- attribute: the attributes the object will have. You need to specify the following attributes: takeable, useable, equipable, value and tile. For vehicles, you also need to specify canSwim and canWalk. Also, items can have the "burrowed" attribute (true/false) to determine whether they are burrowed in the ground (and thus need to be dug out using a spade) or not.
- items: used to specify the items for objects that can contain other items (for Containers such as chests, or bags). Each item entry can include an attribute "probability", which defines the probability with which the character will have this item. For example probability="0.5" means that only 50% of the times a character of this type is spawned, it will have the given item.
Additional
event rules can be added, which will be checked at each frame of the game during gameplay.
Vehicles allow characters that have "canSwim" set to false to move through water (if the vehicle has canSwim=true) and characters that have "canWalk" set to false more through land (if the vehicle has "canWalk=true").
Vehicles have hit points, when a character is attacked while in a vehicle, the vehicle takes the damage. When the vehicle loses all of its hit points, it is destroyed, and drops the character. If a character that cannot swim is dropped in the water, it dies (analogously for a character that cannot walk, dropped on land).
A4 includes a set of default item and object classes that can be used in any game. Specifically, A4 incorporates the following default item/object classes:
- Food (require attributes name, and gold): for food items, you can specify the name, and how expensive it is ("gold")
- Spade (require attribute value): this item can be equipped and used to dig and uncover burrowed items. You can specify the value in gold.
- Key (requires attributes name and ID): keys have no value in gold, but you can specify their name and "ID" (ID must match with the ID of a door, which is the one that the key opens)
- Chest (require attribute name): contains items (specified by the "items" subtag, recursively)
- HPPotion (requires the "hp" attribute): regenerate hit points when used. Their value in gold is automatically calculated as "5 + hp*2"
- MPPotion (requires the "mp" attribute): regenerate magic points when used. Their value is automatically calculated as "5 + mp*2"
- XPPotion (requires the "xp" attribute): gives experience. Their value is automatically calculated as "10 + xp*4"
- A4StrengthPotion (requires the "strength" attribute): permanently increases attack. Their value is automatically calculated as "100 + strength*100"
- A4ConstitutionPotion (requires the "constitution" attribute): permanently increases defense. Their value is automatically calculated as "50 + constitution*50"
- A4LifePotion (requires the "life" attribute): permanently increases max hp. Their value is automatically calculated as "50 + life*25"
- CoinPurse (requires the "gold" attribute): gives gold to the player when taken.
- Scroll (requires the "name", "spell", and "gold" attributes): contains a spell, specified in "spell". The spell is a number, representing one of the spells that A4 engine supports are: 0 is "magic missile", 1 is "heal", 2 is "shield", 3 is "increase", 4 is "decrease", 5 is "fireball", 6 is "magic eye", 7 is "Regenerate" and 8 is "incinerate". See spells for a description of what each spell does.
- Wand (requires the "name", "spell", "charges" and "gold" attributes): contains a spell, specified in "spell". The spell is a number, representing one of the spells that A4 engine supports are: 0 is "magic missile", 1 is "heal", 2 is "shield", 3 is "increase", 4 is "decrease", 5 is "fireball", 6 is "magic eye", 7 is "Regenerate" and 8 is "incinerate". See spells for a description of what each spell does. It also accepts an optional parameter "disappearWhenEmpty" (true/false) that makes the wand disappear when the number of charges reaches 0.
- EquipableItem (name, equipableSlot, attack, defense, magic, canChop, and gold attribues): for all the weapons, armor and rings: equipableSlot is 0 for weapons, 1 for shields/armor, and 2 for rings. "attack" and "defense" are the modifiers for attack and defense of this item, "magic" is the multiplier for the effects of spells (damage, amount healed), "canChop" is a boolean that determines whether this item can chop trees.
- Lever (need the name, leverID, leverState attributes): levers can open and close doors, "leverID" has to match with the "doorID" of a door in the same map. Levers have two states (true/false), which will be rendered as the open and closed animations.
- Door (need the name and closed attributes): "closed" is "true" when the door is closed, and "false", when it's open. Animations for the open and closed states can be provided. An optional attribute "consumeKey" (true/false) determines whether the key is consumed when used to open/close the key (default is true).
Moreover, you can optionally specify a "doorgroup" for any door. When a door is open or closed, all the other doors that share the same doorgroup will also open or close. This is very useful, for example, for when you have the inside and outside of a building and the building door is shown in both maps. Obviously if the player opens one, you want the other one to open too.
- PushableWall: a wall that can be pushed.
- PressurePlate: a button that gets pressed when stepped on. This requires the attribute "pressureRequired", which takes value "1" if the pressure plate is to be activated just by placing any object on top of it, "2" if you need to place a "heavy object" (a pushable wall or a character), and "3" if it's only activated by a player. The two animations used for when it's pressed or unpressed, are "closed" and "open", respectively (like doors).
back to top
Map Definition Files
A4 expects the maps to be in an XML format that extends that of the
TILED map editor (TMX). When creating a map, make sure to add a property called "name" that takes the name of the map as a value. If you open any A4Engine map in
TILED, it might be able to load and display the tile layers. However, if you save the map, it will lose all the scripts, and additional information required by the A4Engine. So, this is not recommended.
Maps are organized in "layers". It is recommended that you define two layers in a map (but you can define more if you want). The first layer will be used for the background tiles and objects (e.g. floor, grass, water, etc.), and the second layer for the foreground objects (walls, trees, etc.).
Each layer is defined as:
<layer name="Tile Layer 1" width="WIDTH" height="HEIGHT">
<data>
<tile gid="TILEID"/>
...
<tile gid="TILEID"/>
</data>
</layer>
Where each "tile" line corresponds to one of the WIDTH*HEIGHT tiles in the map (starting from the top-left corner, and proceeding line by line). The TILEID is the number of the tile in the graphics file (Starting from the top left). Everything that does not have any behavior (floor, walls, trees, rivers, etc.) is defined in the tile layers. Everything that has a behavior (enemies, items that can be picked-up, doors that can be open, etc.) does in the object layers. After you define the tile layers, you need to add the object layers. An object layer is defined as:
<objectgroup name="LAYER NAME" width="WIDTH" height="HEIGHT">
...
<object class="OBJECT CLASS" x="X" y="Y" width="W" height="H"/>
...
</objectgroup>
Notice that the x, y, width, and height of objects is defined in pixels. Object definition follows the exact same format as when defining items in the inventory of characters, as described above.
In addition to the object classes that come predefined with A4Engine, and those that you define in the object and character definition files, in maps, you can specify objects of three additional classes:
For each object defined in any object layers, additional event/story/inference rules, scripts, items, etc. can be added in the same way as in the object and character definition files.
Maps defined in TILED can have a set of "properties". It is very important that you define a property giving a name to your map, like this:
<properties>
<property name="name" value="[MY MAP NAME]"/>
</properties>
Each map must have a different name, since the name is the internal ID that the A4Engine uses to differentiate maps.
Finally, notice that TILED can only be used to author the tile layers. Object layers and other properties of the maps cannot be added in TILED, since it does not support the extended XML format used by the A4 Engine. So, after the map has been saved from TILED, in addition to objects, you can add additional
event rules, and an onStart tag like in the
Game definition file.
back to top
AI
A4 provides some basic functionality to define the AI of Enemies and NPCs in the game. Specifically, the AI of a character is defined based on the following elements:
- Memory: characters can perceive things around them (variable "sightRadius" controls how far can they see). The memory is made of a list of Working Memory Elements (WMEs). A WME is a simple Prolog-like term of the form "f(p1,...,pn)", where "f" is the functor, and "pi" are the parameters, which can be integers, strings, sorts (character or item classes), or a wildcard "?". When a character perceives something, a WME is created in its short term memory with some activation value. This activation value is decreased in 1 at each game time. When the activation reached 0, the WME is forgotten. When a WME has been in the short term memory for a certain amount of time continuously (3000 game cycles, equivalent to 5 minutes of gameplay), it is moved to the long term memory, where it will stay there forever. Moreover, if a character observes evidence against a WME in the long term memory, such WME can eventually be eliminated (each negative piece of evidence subtracts 50 activation points, and when 3000 of those are subtracted, the WME is removed). For example, if a character observes an item at a certain location, it will perceive a WME like "object(13,200,"The forest")", meaning that object with ID 13, was observed at position 200 in the "The forest" map (position starts at 0 in the top left corner, and increases left-to-right, and then to the next row). If such item is observed for very long, the character will "freeze" such WME in the long term memory, and always believe such item will be in that position, even when the character goes away. If someone takes the item away, when the character goes back to those coordinates and observes the contradiction, the WME will start losing activation and eventually, the character will come to terms with the fact that the item is not there, and delete the WME. You can define any type of WME you want, but a list of the WMEs used internally by the engine is described below.
- Behaviors: NPCs and Enemies can have multiple "behaviors" attached to them. Behaviors are executed each time a character can execute an action (i.e. they will not be executed while a character is moving or attacking until the move or attack is done), see more here.
- Rules: many different types of rules can be specified, in addition to behaviors: event rules, conversation graph and inference rules.
The predefined types of WMEs that the A4 engine uses internally are (these WMEs can be used by any of the behaviors or rules to store information, and act as a "blackboard"):
- object(ID,x0,y0,y1,y1,map): created when a character sees an item or character (ID) at a certain position in a given map. When the character observes that another character (ID) has just left the current map to go to another one, then it just observes "object(ID,?,map)", since it knows the ID is in the other map, but doesn't yet know the exact position.
- inventory(ID): created when a character has an item (ID) in her inventory.
- bridge(map2,x0,y0,y1,y1,map): created when a character sees the connection to reach map2.
- is_a(ID,sort): created when a character observes that a certain item or character (ID) is of sort "sort". For example, when a character sees a frog, the following two WMEs will be added: object(21,100,"the forest"), is_a(21,Frog).
- friendly(sort): to store the classes of characters that are considered friendly.
- unfriendly(sort): to store the classes of characters that are considered unfriendly. For example, enemies start with the sort of the player as "unfriendly", and NPCs start with the sort of the player as "friendly".
- location(name,x0,y0,y1,y1,map): can be used to store locations to be used by behaviors, such as "goto".
- WMEs for observed actions: each time an action is observed, a corresponding WME is stored. The following actions are recorded as WMEs: take(ID,ID2), drop(ID,ID2), die(ID), attack(ID,ID2), cast(ID,spell-sort), case(ID,spell-sort,ID2), interact(ID,ID2), embark(ID,ID2), disembark(OD,ID2), talk::[PERF](ID,topic,ID2), give(ID,ID2,ID3). Where "talk::[PERF]" can be talk::hi, talk::bye, talk::trade, talk::ask, talk::inform, depending on the speech act used.
Perception WMEs are created with the minimum activation (they are only active while the object is being perceived), action perception WMEs are created with an activation of 100 (i.e., the character remembers the action for 2 seconds).
back to top
Scripts
A4 allows the specification of scripts for many tasks. A script in A4 is a sequence of actions, where each action is defined in the following way:
<actionName ...action attributes...>
... sub-actions ...
</actionName>
The list of actions that A4 supports is the following:
- Game Logic Actions:
- Character Actions (note, all these actions are executed with priority 10, if there are other behaviors asking for control of the character with higher priority, these scripts will be delayed):
- teleport: automatically transports a character to the desired position. Requires the following attributes:
- x: destination x coordinate (pixel coordinates).
- y: destination y coordinate (pixel coordinates).
- map (optional): destination map (the map name).
- goto: makes a character walk towards a desired position. Requires the same attributes as "teleport".
- use: It can be used in three different ways: 1) with no parameters the character will try to use an object in the current position, 2) with "X", "y" (and optionally "map"), makes a character walk towards a desired position and use an object in that position (e.g., a lever), and 3) with "inventory" it uses the item "inventory" from the inventory.
- take: makes a character walk towards a desired position and take an item in that position. Requires the same attributes as "teleport", but "x" and "y" are also optional (if not provided, the character will just try to pick up an item in the current position)
- interact: makes a character walk towards a desired position and tries to interact with an object there (for example, for opening a door if it has the necessary key). Requires the same attributes as "teleport", but "x" and "y" are also optional (if not provided, the character will just try to embark the transport in the current position)
- chop: makes a character walk towards a desired position and tries to chop a tree there. Requires the same attributes as "teleport".
- embark: makes a character walk towards a desired position and embark the transport in that position. Requires the same attributes as "teleport", but "x" and "y" are also optional (if not provided, the character will just try to embark the transport in the current position)
- disembark: makes a character moves towards a desired position and disembarks the current transport. Requires the same attributes as "teleport", but "x" and "y" are also optional (if not provided, the character will just try to disembark the transport in the current position)
- attack: it requires the parameter "target". It moves toward the character with name "target" and attacks. If the optional parameter "untilDead" is set to "true", it attacks until the target is dead, otherwise, it just attacks once.
- spell: the character casts the spell specified by "spell", if the spell requires a direction, then this can be specified in the "direction" parameter with (north/east/south/west/right/left/up/down/self).
- talk: makes a character say something with a text bubble. It requires the attribute "text" (containing the text that will appear in the text bubble), and it can optionally specify the "performative" ("hi", "bye", "ask", "inform", "trade", "timeout") and "topic" of the talk. If a parameter "angry='true'" is specified, then the character will yell, instead of talk. Finally, a parameter "wait" can be set to true or false, if true, this script will wait until the talk is complete in order to return success.
- talkOther: Same as "talk", but it will be the "other" character that will talk, this can only be used in contexts where the "other" character is defined (e.g., when in a conversation).
- steal: the character will steal an item from the inventory of the other-character (the one which with it is currently engaged in conversation). It requires one parameter "itemName".
- give: the character will give an item to the other-character (the one which with it is currently engaged in conversation). You can specify an item name in the attribute "inventory" (the character will take this item from its own inventory and give it), or as a child xml tag (a new item will be created with this definition and given to the other-character). If the inventory of the other character is full, the item will be dropped in the same coordinate as the other character.
- sell: the character will sell an item to the other-character (the one which with it is currently engaged in conversation). You can specify an item name in the attribute "inventory" (the character will take this item from its own inventory and give it), or as a child xml tag (a new item will be created with this definition and sold to the other-character). If the inventory of the other character is full, the action will fail.
- buy: requires two parameters "seller" (the name of the character who will sell the object), and "object", the name of the object to buy.
- drop: like "give", but the item will be dropped in the coordinates currently being occupied by the character.
- dropGold: a certain amount of gold will be dropped in the coordinates currently being occupied by the character, if the character has enough gold to drop. The amount is specified in the parameter "gold".
- Miscellanea Actions:
All of these actions return "true" or "false" if they could or not be executed successfully, and thus, all can be used as part of the condition of an if-then-else. An if-then-else returns the value of the last action executed internally.
back to top
Event Rules
Event rules are rules that are checked at each execution cycle, triggered by certain events. An event rule is defined as follows:
<eventRule event="EVENT" once="true/false">
... sub-actions ...
</eventRule>
When the event "event" is triggered, this rule will be executed. Currently, the engine supports the following events:
- "use": when an item or a lever or a pressure plate is used
- "pickup": when an item is picked up
- "activate": when a lever or pressure plate is moved to the "on" position
- "deactivate": when a lever or pressure plate is moved to the "off" position
- "drop": when an item is dropped (event is triggered in the item that is dropped)
- "equip": when an item is equipped (event is triggered in the item that is equipped)
- "unequip": when an item is unequipped (event is triggered in the item that is unequipped)
- "open": when a door or container is open
- "close": when a door is closed
- "push": when a movable wall is pushed
- "timer": to specify that something has to be executed after a certain amount of time. It has two additional parameters, "time" and "period". When the game cycle is equal to "time", this rule will fire. Additionally, if a "period" parameter is specified, this rule will fire when the game cycle module "period" is equal to time (this can be used for things that have to be executed periodically)
- "receive": when a character receives an item from another character. It accepts an optional additional parameter "item", specifying the name/class of the item.
- "interact": when an object is interacted with (triggered in the object).
- "start": when the game starts (for game and map scripts) or when an object is first instantiated (for objects).
- "end": triggered in just before an object disappears (e.g., enemy killed, or item used and consumed).
- Events triggered on characters by their actions:
- "action_take": triggered on a character when she takes an item. It accepts an optional additional parameter "item", specifying the name/class of the item.
- "action_drop": triggered on a character when she drops an item. It accepts an optional additional parameter "item", specifying the name/class of the item.
- "action_drop_gold": triggered on a character when she drops gold.
- "action_use": triggered on a character when she uses an item. It accepts an optional additional parameter "item", specifying the name/class of the item.
- "action_equip": triggered on a character when she equips an item. It accepts an optional additional parameter "item", specifying the name/class of the item.
- "action_unequip": triggered on a character when she unequips an item. It accepts an optional additional parameter "item", specifying the name/class of the item.
- "action_interact": triggered on a character when she interacts with an item. It accepts an optional additional parameter "item", specifying the name/class of the item.
- "action_talk": triggered on a character when she talks. It accepts an optional additional parameter "performative", specifying the performative ("hi", "bye", "ask", "inform", "trade", "timeout"). It also accepts an optional parameter "angry" (true/false) to specify whether to trigger only when talking angry or not.
- "action_attack": triggered on a character when she attacks another character. It accepts an optional additional parameter "character", specifying the name/class of the character being attacked. It also accepts an optional parameter "hit" (true/false), that determines whether the event is triggered when the attack successfully hits, or when it is a missed attack.
- "action_spell": triggered on a character when she casts a spell. It accepts an optional additional parameter "spell", specifying the name of the spell.
- "action_give": triggered on a character when she gives an item. It accepts an optional additional parameter "item", specifying the name/class of the item; and an additional parameter "character", specifying the name/type of the character that receives the item.
- "action_sell": triggered on a character when she sells an item. It accepts an optional additional parameter "item", specifying the name/class of the item; and an additional parameter "character", specifying the name/type of the character that receives the item.
- "action_buy": triggered on a character when she buys an item. It accepts an optional additional parameter "item", specifying the name/class of the item; and an additional parameter "character", specifying the name/type of the character from whom the item is bought.
- "action_chop": triggered on a character when she chops a tree. It accepts an optional additional parameter "item", specifying the name/class of the item used to chop.
You can specify whether this rule has to be executed only once, or each time this value is observed with the attribute "once" (default is "false").
back to top
Conversation Graph
Each character (e.g., NPC or enemy) can have a
conversation graph that controls how does the character react while talking with other characters. You can create conversation graphs in two different ways: via a conversation graph file, or via adding individual conversation graph transitions. The first allows you to define a complete conversation graph in a separate XML file. The second allows you to specify a conversation graph transition by transition directly in the character definition. The recommended way to define conversation graphs is as follows: define one or more generic conversation graphs on separate files, and then when defining a new character, you load one conversation graph, and then complete it by defining additional conversation graph transitions.
A conversation graph file in an XML file defined as a set of states where each state has a name and a set of transitions. It is defined in XML as follows:
<conversarionGraph>
<state name="STATE 1 NAME">
<transition actor="ACTOR" performative="PERFORMATIVE" state="TARGET STATE" consume="CONSUME" topic="TOPIC">
... scripts ...
</transition>
</state>
...
<state name="STATE n NAME">
...
</state>
</conversarionGraph>
Each state requires specifying a
name, and a set of transitions. Each transition can specify:
- An actor ("self" or "other"): who is the actor that must talk for this transition to be triggered.
- A performative ("hi", "bye", "ask", "inform", "trade", "timeout"): the performative that the message spoken must have for the transition to be triggered.
- A topic: the specific topic that has to be talked about for the transition to be triggered.
- A target state: the state that this transition connects with.
- Whether the transition consumes the message or not ("true" or "false"): if the transition does not consume the message, then as soon as it is triggered, the same message can trigger another transition (i.e., this is whether the message that triggered the transition is removed or not from the input queue of messages to a character)
- Scripts: scripts that will be executed if the transition is fired (this can be used to make the character talk, for example)
Most of the parameters above are optional. If no actor, performative or topic are specified, that means that any actor, performative or topic can trigger this transition. If no target state is specified, then it is assumed that the transition does not change the state. Consumes by default is "true".
When specifying a character, the following statement can be added to load a conversation graph:
<conversationGraph name="XML FILE NAME"/>
Additionally, character-specific transitions can be added to the loaded conversation graph as follows:
<conversationGraphTransition from="SOURCE STATE" actor="ACTOR" performative="PERFORMATIVE" state="TARGET STATE" consume="CONSUME" topic="TOPIC">
... scripts ...
</conversationGraphTransition>
Basically, it is the same format as the transitions in the conversation graph files, except that a "from" parameter has to be specified (the name of the origin state).
back to top
Inference Rules
Inference rules determine additional inferences that characters (e.g. NPCs) can make, based on the content of their memory. An inference rule is defined as:
<inferenceRule premise="WME1, ..., WMEn" conclusion="WME" frequency="FREQUENCY" activation="ACTIVATION" once="true/false" cooldown="COOLDOWN"/>
At each AI update cycle, the character will have probability "FREQUENCY" of checking this rule (this is to avoid checking rules at each cycle, and also this can control the "intelligence" of different characters). If all the WMEs in the premise are satisfied in the memory of the character, then the conclusion WME will be added to the memory with activation value "ACTIVATION".
For example, if premise = "attack(?1,?2),friendly(?2)" and conclusion="unfriendly(?1)", then when the character sees someone attacking a friendly character, it will be believe that the attacker is unfriendly.
Additionally, parameters "once" (to set if a rule should only be executed once), and "cooldown" (number of game cycles that must pass before the rule can be triggered again) can be specified.
Finally, you can specify scripts (as nested XML statements in the rule) that will be executed when the rule is fired.
note: the subsumption relation used to check the premises is not relative.
back to top
Behaviors
NPCs and Enemies can have multiple "behaviors" attached to them. Behaviors are executed each time a character can execute an action (i.e. they will not be executed while a character is moving or attacking until the move or attack is done). Each behavior can return a desired action. If multiple behaviors return actions, ties are resolved by the priority of each behavior. If a behavior with high priority generates an action in a given cycle, it can be the case that behaviors with low priority are not executed at all during that cycle.
Most of these behaviors make use of the "working memory" that NPCs and Enemies have. The working memory is divided into two parts: short-term and long-term. Each of them is a list of "WMEs" (Working Memory Elements). A WME is a sctructure of the form "type(parameter1, ..., parametern)". WMEs in the short-term memory disappear after a while, WMEs in the long-term memory stay there forever. If a WME stays in the short-term memory for a very long time, it will be moved to the long-term memory.
A4 comes built-in with the following behaviors:
- BLeftRight: makes the character move left until an obstacle is encountered, then right until an obstacle is encountered, and then loop the behavior.
- BUpDown: makes the character move up until an obstacle is encountered, then down until an obstacle is encountered, and then loop the behavior.
- BWander ( requires the forwardFactor, pStop and stopTime attributes): makes the character move around at random. After each time the character moves a whole tile, it has probability "pStop" to stop for "stopTime" cycles. For each movement the character chooses a direction at random from the set of available directions. The direction in which the character moved before has a probability "forwardFactor" times higher than the other directions.
- BWanderInCircles (requires the diameter attribute): the character moves around in clockwise circles, of diameter "diameter"
- BCurious (requires the pickup, sort, and time attributes): the character will walk toward each object/character of sort "sort" not previously seen before. If it is an item and "pickup = true", it will pick it up. For example if "sort = Item", the character will walk and pick up any new items that appear around, if "sort = Object", the character will do that, but also go toward each new character that appears. The effect will wear off "time" cycles after the object is first seen.
- BTired ( requires the timeWalking, and restTime attributes): each time the character walks "timeWalking" game frames, it will get tired, and will have to rest for "restTime" game frames.
- BFleeUnfriendly: flees from any unfriendly character (i.e. WME unfriendly(C) exists, where C is the class of the character, or a superclass).
- BRAttackUnfriendly: attacks any character that is known to be "unfriendly" (i.e. WME unfriendly(C) exists, where C is the class or a superclass of the character).
- BYellToUnfriendly (requires the message attribute): if an unfriendly other-character is seen, the character will get angry, and yell the message "message".
- BGoto (requires the location and radius attributes): makes the character walk to the location called "location" if it is further away than radius pixels away.
- BFollow (requires the target and radius attributes): makes the character walk to the object called "target" if it is further away than radius pixels away.
- BFollowFromWME (requires the radius attribute): follows any character that is flagged as to follow (i.e. WME follow(C) exists, where C is the class or identifier of the character).
- BFollowAngryFriendly (requires the radius attribute): if a friendly character gets angry, the character will go towards it to investigate.
back to top
Spells
Characters that have magic points can cast spells (if they know them). The engine has the following spells implemented (the value in parenthesis is the number of magic points required to cast):
- Magic Missile (1mp): casts a magic missile that travels for 6 tiles and deals 4 points of damage. Its "walk speed" is 8.
- Heal (1mp): heals 5 hit points. It can be cast on self, or on an adjacent character.
- Shield (2mp): adds 5 to the defense, during 1500 game cycles. It can be cast on self, or on an adjacent character.
- Increas (2mp): adds 2 defense and 4 attack during 1500 game cycles. It can be cast on self, or on an adjacent character.
- Decrease (2mp): subtracts 2 defense and 4 attack during 1500 game cycles. It can be cast on self (be careful!), or on an adjacent character.
- Fireball (4mp): casts a magic missile that travels for 10 tiles and deals 12 points of damage to any character within a radius of 1.5 tiles. Its "walk speed" is 8.
- Magic Eye (4mp): lets the character see the complete map (this lasts for only 1500 cycles).
- Regenerate (8mp): heals 50 hit points. It can be cast on self, or on an adjacent character.
- Incinerate (8mp): casts a magic missile that travels for 24 tiles and deals 32 points of damage. Its "walk speed" is 8.
All these effects are multiplied by the magic bonus that some items give. For example, if you have a magic bonus of x1.5, then incinerate will deal 48 damage instead of 32. Spell durations and travel distance are not affected by magic multipliers. For shield, increase and decrease, the bonus multiplier that matters is that of the receiver, not of the caster (i.e., magic has more effect on people with magic multipliers).
back to top