create magical objects spec

This commit is contained in:
Willem van den Ende 2026-06-14 14:05:28 +01:00
parent fb61fb85ed
commit 1c9d4ad66b
2 changed files with 183 additions and 0 deletions

View File

@ -0,0 +1,182 @@
-- allium: 3
-- allium: magical-objects
-- Scope: Magical Objects (Healing Objects and Weapons)
-- Includes: MagicalObject base, HealingObject, MagicalWeapon, Character interactions
-- Excludes:
-- - Magical Object to Magical Object interactions (not in story)
-- - Magical Object factions (they are neutral)
-- - Characters healing Magical Objects (forbidden by story)
------------------------------------------------------------
-- Entities and Variants
------------------------------------------------------------
entity MagicalObject {
health: Health
maxHealth: Health
status: alive | destroyed
is_alive: status = alive
is_destroyed: status = destroyed
transitions status {
alive -> destroyed
terminal: destroyed
}
}
entity HealingObject : MagicalObject {
-- Healing objects transfer health to characters
-- They cannot deal damage
}
entity MagicalWeapon : MagicalObject {
damage: Integer -- fixed damage amount
owner: Character -- only the owner can use this weapon
-- Weapons cannot give health to characters
}
------------------------------------------------------------
-- Rules
------------------------------------------------------------
rule HealingObjectHealsCharacter {
when: CharacterUsesHealingObject(character, object, amount)
requires: object.status = alive
requires: character.status = alive
requires: amount >= 0
let objectRemaining = object.health
let characterMax = Level.maxHealthForLevel(character.level)
let characterHeadroom = characterMax - character.health
let actualHeal = min(amount, objectRemaining, characterHeadroom)
ensures:
if actualHeal > 0:
character.health = character.health + actualHeal
object.health = object.health - actualHeal
if object.health = 0:
object.status = destroyed
else:
object.status = alive
else:
character.health = character.health
object.health = object.health
}
rule HealingObjectDestroyedCannotHeal {
when: CharacterUsesHealingObject(character, object, amount)
requires: object.status = destroyed
ensures:
character.health = character.health
object.health = object.health
}
rule DeadCannotUseHealingObject {
when: CharacterUsesHealingObject(character, object, amount)
requires: character.status = dead
ensures:
character.health = character.health
object.health = object.health
}
rule HealingObjectZeroHealIsNoOp {
when: CharacterUsesHealingObject(character, object, amount)
requires: object.status = alive
requires: character.status = alive
requires: amount >= 0
requires: min(amount, object.health, Level.maxHealthForLevel(character.level) - character.health) = 0
ensures:
character.health = character.health
object.health = object.health
}
rule MagicalWeaponDealsDamage {
when: CharacterUsesWeapon(owner, weapon, target)
requires: weapon.status = alive
requires: owner.status = alive
requires: owner = weapon.owner
ensures:
target.health = max(0, target.health - weapon.damage)
if target.health = 0:
target.status = dead
weapon.health = weapon.health - 1
if weapon.health = 0:
weapon.status = destroyed
else:
weapon.status = alive
}
rule DeadCannotUseWeapon {
when: CharacterUsesWeapon(owner, weapon, target)
requires: owner.status = dead
ensures:
target.health = target.health
weapon.health = weapon.health
}
rule NonOwnerCannotUseWeapon {
when: CharacterUsesWeapon(thief, weapon, target)
requires: thief != weapon.owner
ensures:
target.health = target.health
weapon.health = weapon.health
}
rule WeaponDestroyedCannotDealDamage {
when: CharacterUsesWeapon(owner, weapon, target)
requires: weapon.status = destroyed
ensures:
target.health = target.health
weapon.health = weapon.health
}
------------------------------------------------------------
-- Invariants
------------------------------------------------------------
invariant MagicalObjectHealthNonNegative {
for m in MagicalObjects:
m.health >= 0
}
invariant MagicalObjectHealthNeverExceedsMax {
for m in MagicalObjects:
m.health <= m.maxHealth
}
invariant MagicalObjectDestroyedAtZeroHealth {
for m in MagicalObjects:
m.health = 0 implies m.status = destroyed
}
invariant MagicalObjectAliveAtPositiveHealth {
for m in MagicalObjects:
m.health > 0 implies m.status = alive
}
invariant HealingObjectDoesNotDealDamage {
for h in HealingObjects, t in Characters:
not exists amount: CharacterUsesHealingObject(t, h, amount) implies t.health >= t.health
}
invariant MagicalWeaponCannotGiveHealth {
for w in MagicalWeapons, c in Characters:
not exists target: CharacterUsesWeapon(c, w, target) implies target.health <= target.health
}

View File

@ -50,6 +50,7 @@ This is a description of the business rules we should support in the game engine
- Healing Magical Objects cannot deal Damage - Healing Magical Objects cannot deal Damage
3. Characters can deal Damage by using a Magical Weapon. 3. Characters can deal Damage by using a Magical Weapon.
- A Character can only use a Magical Weapon they own
- These Magical Objects deal a fixed amount of damage when they are used - These Magical Objects deal a fixed amount of damage when they are used
- The amount of damage is fixed at the time the weapon is created - The amount of damage is fixed at the time the weapon is created
- Every time the weapon is used, the Health is reduced by 1 - Every time the weapon is used, the Health is reduced by 1