Meta-modelling and Coded Operational Semantics with AToM3 

  Assignment Goal

The goal of this assignment is to build a formalism to model RPGame in AToM3:
  1. Implement abstract syntax using CD_ClassDiagramsV3, enrich with constraints on the ASG if necessary, create a concrete syntax, and generate a modelling environment. Do this incrementally.
  2. [optional] Create a nice buttons menu for your RPGame modelling formalism environment that you generated in step 1. (In order to do this, open the generated _META file as a model.)
  3. Make your RPGame visually more appealing by adding constraints that move/resize/... model elements. Find useful constraints.
  4. Implement operational semantics in Python. (To be able to execute the code, create a button (see step 2) that imports your implemented Python module.)

Write a report that discusses your solution. Your report should include an overview of your solution, with focus on the difficulties you encountered and how you solved them.

You will have to complete this assignment in groups of 2. Submit your assignment on Blackboard before Friday 16 November 2012 at 14h00.

Contact Bart Meyers if you have a problem.

RPGame Requirements

An RPGame consists of a world that is divided into scenes (or "levels"), such as Forest, Desert, Castle, etc.

In each scene, there are a number of connected tiles.

Tiles can be connected to each other from the left, right, top or bottom. This way, a map is created for each scene.

In the game, there is one hero, and there can be villains.

Each of these characters is located on a tile, and only one character can be on a tile at the same time.

A tile can be an empty tile, or a trap, or a door (all on which the characters can stand), or an obstacle (no one can stand on obstacles).

A character can move from one adjacent tile to another (provided it is not an obstacle or it is not occupied).

A door is a portal to a door on another scene. The hero can pass through the door to enter another scene. If the hero goes back through the door, he goes back to the original door at the original scene.

The hero can attack villains and vice versa, if they stand on adjacent tiles.

Villains do not attack each other.

A trap hurts the hero, but not a villain (they have set these traps...).

The hero and a villain have a health value that depicts how much damage they can take. The default health for the hero and for a villain is 100 (although it can be set otherwise. The health always has a strictly positive value.

The hero, a villain and a trap have a damage value that depicts how much damage they inflict. The hero and a villain inflict damage (according to their damage value) if they choose to attack (when on a tile adjacent to their adversary's tile). A trap inflicts damage (according to their damage value) on the hero if the hero steps onto it. Damage is always strictly positive.

On a "standard" tile (not a trap, obstacle or door), there can be an item. An item can be picked up by the hero by walking on its tile. Every item can only be picked up once. Items can be a key, a weapon, or a goal.

A door can be locked, and the hero must pick up a particular key (for that door) to be able to enter doors.

A hero can pick up a weapon, that can give the hero additional damage, according to the damage of the weapon.

A hero can pick up a goal. The hero wins if he can pick up all goals. There must be at least one goal in the game.

The game is simulated in time slices: first, the hero gets one chance to move or attack. Then, all the villains in the same scene, each get their chance to move or attack. The order in which the villains get their chance is not determined.

Villains in a different scene from the "active" scene (i.e., the scene in which the hero currently resides) do not do anything.

When the hero achieves the goals, or dies, the game is over.

An example of an execution/simulation trace is shown here.

  Useful Links

  • AToM3 main page: http://msdl.cs.mcgill.ca/projects/projects/AToM3/
  • AToM3 download: http://msdl.cs.mcgill.ca/projects/projects/AToM3/atom3.zip
  • AToM3 tutorials:
  • AToM3 programming API for manipulating objects, models, visual objects etc. using Python: http://atom3.cs.mcgill.ca/people/jlara/AToM3_Programming/index.dtml
  • Example constraints and actions
  • .

    Constraints and actions are described in the meta-model (a Class Diagram) of the language you're modelling. Constraints and actions are either global (under the global Edit button) or object-specific (when you edit an individual Class or Association). Constraints and actions are triggered by one or more events. Those events may pertain to abstract syntax (such as the EDIT event) or to the concrete syntax (such as the MOVE event). In the case of constraints, a distinction is made between pre-conditions and post-conditions. The latter are evaluated after the event has taken effect. If a post-condition fails, the model's state is rolled back to what it was before the event.

    Constraints and actions can be edited insided AToM3. As the editor widget inside AToM3 leaves a lot to be desired, we recommend that you write your constraint and action code outside AToM3, using your favourite editor. You keep this code in files (e.g., Constraints.py and Actions.py), typically in the same directory where you keep the meta-model for your language.

    In AToM3, where you would normally write the entire action, now just put the following:

    from <pythonfile> import <function>
    <function>(<parameters>)
    So for example, if you have an Actions.py helper file containing the doAction(hero) method in the same directory as your meta-model, you can put the following code in an action in the Hero class in your meta-model:
    from Actions import doAction
    doAction(self)

    In the case of a constraint, your function must return either None to indicate True or a string to indicate False (and the string will be displayed to let the user know that the constraint was violated and why).

    You can do a similar thing in a button (when you open your _META.py file as a model instead of a formalism), but in this case self is an instance of the ATOM3 class, so you can access your model by using self.ASGroot.

    If you use calls to Python modules like this, you will notice that if you change something in your Python module, you will have to restart AToM3 to see your changes. This can make debugging very tedious. This script allows you to explicitly unload your module from memory without having to quit AToM3, so that the new version of your code is executed. Unzip this script in your "User External" folder so that the path of unload.py is "User External/unload/unload.py". Use the script as follows in your AToM3 code snippet:

    from unload.unload import unload_mods
    unload_mods("Actions")
    from Actions import doAction
    doAction(self)
    You can use as many string parameters denoting modules (use their full name!) in the unload_mods call as you want.