# 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; } """