158 lines
4 KiB
Python
158 lines
4 KiB
Python
# Design meta-model
|
|
woods_mm_cs = """
|
|
Animal:Class {
|
|
abstract = True;
|
|
}
|
|
|
|
Bear:Class
|
|
:Inheritance (Bear -> Animal)
|
|
|
|
Man:Class {
|
|
lower_cardinality = 1;
|
|
upper_cardinality = 2;
|
|
constraint = `get_value(get_slot(this, "weight")) > 20`;
|
|
}
|
|
:Inheritance (Man -> Animal)
|
|
|
|
|
|
Man_weight:AttributeLink (Man -> Integer) {
|
|
name = "weight";
|
|
optional = False;
|
|
}
|
|
|
|
afraidOf:Association (Man -> Animal) {
|
|
source_upper_cardinality = 6;
|
|
target_lower_cardinality = 1;
|
|
}
|
|
"""
|
|
# Runtime meta-model
|
|
woods_rt_mm_cs = woods_mm_cs + """
|
|
AnimalState:Class {
|
|
abstract = True;
|
|
}
|
|
AnimalState_dead:AttributeLink (AnimalState -> Boolean) {
|
|
name = "dead";
|
|
optional = False;
|
|
}
|
|
of:Association (AnimalState -> Animal) {
|
|
source_lower_cardinality = 1;
|
|
source_upper_cardinality = 1;
|
|
target_lower_cardinality = 1;
|
|
target_upper_cardinality = 1;
|
|
}
|
|
|
|
BearState:Class {
|
|
constraint = `get_type_name(get_target(get_outgoing(this, "of")[0])) == "Bear"`;
|
|
}
|
|
:Inheritance (BearState -> AnimalState)
|
|
BearState_hunger:AttributeLink (BearState -> Integer) {
|
|
name = "hunger";
|
|
optional = False;
|
|
constraint = ```
|
|
val = get_value(get_target(this))
|
|
val >= 0 and val <= 100
|
|
```;
|
|
}
|
|
|
|
ManState:Class {
|
|
constraint = `get_type_name(get_target(get_outgoing(this, "of")[0])) == "Man"`;
|
|
}
|
|
:Inheritance (ManState -> AnimalState)
|
|
|
|
attacking:Association (AnimalState -> ManState) {
|
|
# Animal can only attack one Man at a time
|
|
target_upper_cardinality = 1;
|
|
|
|
# Man can only be attacked by one Animal at a time
|
|
source_upper_cardinality = 1;
|
|
|
|
constraint = ```
|
|
attacker = get_source(this)
|
|
if get_type_name(attacker) == "BearState":
|
|
# only BearState has 'hunger' attribute
|
|
hunger = get_value(get_slot(attacker, "hunger"))
|
|
else:
|
|
hunger = 100 # Man can always attack
|
|
attacker_dead = get_value(get_slot(attacker, "dead"))
|
|
attacked_state = get_target(this)
|
|
attacked_dead = get_value(get_slot(attacked_state, "dead"))
|
|
(
|
|
hunger >= 50
|
|
and not attacker_dead # cannot attack while dead
|
|
and not attacked_dead # cannot attack whoever is dead
|
|
)
|
|
```;
|
|
}
|
|
|
|
attacking_starttime:AttributeLink (attacking -> Integer) {
|
|
name = "starttime";
|
|
optional = False;
|
|
constraint = ```
|
|
val = get_value(get_target(this))
|
|
_, clock = get_all_instances("Clock")[0]
|
|
current_time = get_slot_value(clock, "time")
|
|
val >= 0 and val <= current_time
|
|
```;
|
|
}
|
|
|
|
# Just a clock singleton for keeping the time
|
|
Clock:Class {
|
|
lower_cardinality = 1;
|
|
upper_cardinality = 1;
|
|
}
|
|
Clock_time:AttributeLink (Clock -> Integer) {
|
|
name = "time";
|
|
optional = False;
|
|
constraint = `get_value(get_target(this)) >= 0`;
|
|
}
|
|
"""
|
|
|
|
# Our design model - the part that doesn't change
|
|
woods_m_cs = """
|
|
george:Man {
|
|
weight = 80;
|
|
}
|
|
bill:Man {
|
|
weight = 70;
|
|
}
|
|
|
|
teddy:Bear
|
|
mrBrown:Bear
|
|
|
|
# george is afraid of both bears
|
|
:afraidOf (george -> teddy)
|
|
:afraidOf (george -> mrBrown)
|
|
|
|
# the men are afraid of each other
|
|
:afraidOf (bill -> george)
|
|
:afraidOf (george -> bill)
|
|
"""
|
|
|
|
# Our runtime model - the part that changes with every execution step
|
|
woods_rt_initial_m_cs = woods_m_cs + """
|
|
georgeState:ManState {
|
|
dead = False;
|
|
}
|
|
:of (georgeState -> george)
|
|
|
|
billState:ManState {
|
|
dead = False;
|
|
}
|
|
:of (billState -> bill)
|
|
|
|
teddyState:BearState {
|
|
dead = False;
|
|
hunger = 40;
|
|
}
|
|
:of (teddyState -> teddy)
|
|
|
|
mrBrownState:BearState {
|
|
dead = False;
|
|
hunger = 80;
|
|
}
|
|
:of (mrBrownState -> mrBrown)
|
|
|
|
clock:Clock {
|
|
time = 0;
|
|
}
|
|
"""
|