Phases are the fuel that make a PbML-described world function and evolve during each turn. Once the Yagga server has read the previously-saved status of every object in the world, the serve make the world evolve and reach a new status. The world evolves following the "phases". Each phase is executed sequentially, from the first specified phase to the last. Phases can consists of sub-phases.
The phases are specified in a file (default file name is "0.phases"), where there is one phase per line:
This file:
INIT
MAIN
CONSTRUCTION.buildings
CONSTRUCTION.ship
END
consists of 4 phases and 2 sub-phases.
Please note that phase/events name are case sensitive, as PbML, so you can write lower-case phases, but the handlers should be written accordingly. Sub phases are a detailed breakdown of a single event. They are particularly useful in event-handling loops (see later). They are specified by following the main phase name with a dot and then the subphase name.
In order to handle a phase a method declares itself as an handler for a particular phase or sub-phase. One method can handle only one phase, but of course, since methods can invoke one another, you can use a method as a real handler, albeit a hidden one, and write several handler whose body consists solely of a call to the actual handler.
1.1.1 PHASES HANDLER RE-INVOKING
Some type of phase handlers may be recalled over and over until they choose to terminate. Such phase handlers have the option to chose to be recalled, not to be called anymore during this event, or to be called only if some other event handler wish to be called in this event/phase.
This behaviour may be useful when an event is to be iterated several times until a certain condition is reached. Let ut think of a simulated fight: every micro-event (consisting of a round of shooting - if ammo is loaded - and damage resolution) should be repeated until a fighter dies or surrender. Please see section 2.1.1 for a detailed explanation.
Sub phases are important in defining sequential sub-phases even when there is the need for the above-mentioned reinvoking behavior.
The engine, for every phase, does the following:
for each phase do
{
do
{
call every handler for subphase 1 of current
phase
call every handler for subphase 2 of current
phase
call every handler for subphase 3 of current
phase
...
}
while(some method needs to be executed)
}
So, during the handling of a single main phase, subphase handlers are called sequentially, then, if necessary, the entire phase is re-handled. At the end of every sub-phase attributes are assigned values as set by "inc/dec by/to" or "set".
As an example, let us investigate the example of simulating combat.
The single phase COMBAT could be split in COMBAT.hit and COMBAT.damage
During the handling of a particular phase each handler is theoretically executed in parallel with every other handler.
In reality handlers are executed sequentially (of course!) but each handler sees data as they were before the start of the phase, and any modification to such data takes place only after every handler has executed.
It is clear that problems occur when several methods access and modify the same set of data. We have solved this problem by insuring that numerical attributes of objects cannot be modified in the standard way: (this is pseudo code, no PbML!)
attribute num of class Airplane;
attribute
crew of class Airplane;
method foo: //handles phase TAKEOFF
num=num+4; //WRONG, not a valid PbML construct
inc num by 4; //Correct
if(crew<4)
inc crew to 8;
method bar: //handles phase TAKEOFF
inc num by 3; //correct
if(crew<4)
inc crew to 10;
By using constructs like "inc xxx by ###", "inc xxx to ###" and so on, we enforce the fact that those modifications will take place only after every method has the chance to execute. Of course it's up to the designer to decide whether to use "inc by" or "inc to".
In the above example, assuming num and crew starts with a value of 0, at the end of the execution of both method num=7 and crew=10! Both "ifs" are executed, because both methods see crew with the value it had at the beginning, that is zero!
The same behaviour applies at the end of each sub-phase, if the phase has any sub-phases.
Please see the grammar for a detailed explanation of the syntax.
This semantics regards only numerical attributes, and (fairly uselessly) boolean and string values.
Boolean and string attributes can be modified only by the set
operator.
Objects, list of scalars and list of objects, whose unique modification operation
is the assignment, are affected immediately in the usual way. Of course this
can lead to unpredictable results if two phase handlers modify, for example,
the same object reference in the same phase, but this cannot be avoided. At
the end of the phase the object reference will have one definite value, but
one cannot tell which. The same holds values and list of scalars (even numerical
ones!) and list of reference to objects.