rpg-combat-pi-01/specs/magical-objects.allium
Willem van den Ende 31984bbd9d Consolidate all .allium specs into specs/
- Move .pi/specs/ files into specs/ (healing, factions, merged magical-objects)
- Move src/*.allium files into specs/ (levels, changing-level)
- Delete .pi/specs/ directory
- Document specs/ convention in AGENTS.md
2026-06-15 08:16:12 +01:00

190 lines
4.8 KiB
Plaintext

-- allium: 3
-- allium: magical-objects
------------------------------------------------------------
-- Value Types
------------------------------------------------------------
value Health {
value: Integer
requires: value >= 0
}
value Faction {
name: String
}
value Level {
value: Integer
requires: value >= 1 and value <= 10
}
------------------------------------------------------------
-- Enumerations
------------------------------------------------------------
enum Status {
alive | destroyed
}
------------------------------------------------------------
-- Entities
------------------------------------------------------------
entity Character {
name: String
health: Health
status: Status
level: Level
factions: Set<Faction>
}
entity MagicalObject {
health: Health
maxHealth: Integer
status: Status
}
entity HealingObject {
health: Health
maxHealth: Integer
status: Status
}
entity MagicalWeapon {
health: Health
maxHealth: Integer
status: Status
damage: Integer
owner: Character
}
------------------------------------------------------------
-- Rules
------------------------------------------------------------
rule HealingObjectHealsCharacter {
when: CharacterUsesHealingObject(character, object, amount)
requires: object.status = alive
requires: character.status = alive
requires: amount >= 0
ensures:
character.health.value = character.health.value + min(amount, object.health.value, Level.maxHealthForLevel(character.level) - character.health.value)
object.health.value = object.health.value - min(amount, object.health.value, Level.maxHealthForLevel(character.level) - character.health.value)
if object.health.value = 0:
object.status = destroyed
else:
object.status = alive
}
rule HealingObjectDestroyedCannotHeal {
when: CharacterUsesHealingObject(character, object, amount)
requires: object.status = destroyed
ensures:
character.health.value = character.health.value
object.health.value = object.health.value
}
rule DeadCannotUseHealingObject {
when: CharacterUsesHealingObject(character, object, amount)
requires: character.status = dead
ensures:
character.health.value = character.health.value
object.health.value = object.health.value
}
rule HealingObjectZeroHealIsNoOp {
when: CharacterUsesHealingObject(character, object, amount)
requires: object.status = alive
requires: character.status = alive
requires: amount >= 0
requires: min(amount, object.health.value, Level.maxHealthForLevel(character.level) - character.health.value) = 0
ensures:
character.health.value = character.health.value
object.health.value = object.health.value
}
rule MagicalWeaponDealsDamage {
when: CharacterUsesWeapon(owner, weapon, target)
requires: weapon.status = alive
requires: owner.status = alive
requires: owner = weapon.owner
ensures:
target.health.value = max(0, target.health.value - weapon.damage)
weapon.health.value = weapon.health.value - 1
if weapon.health.value = 0:
weapon.status = destroyed
else:
weapon.status = alive
}
rule DeadCannotUseWeapon {
when: CharacterUsesWeapon(owner, weapon, target)
requires: owner.status = dead
ensures:
target.health.value = target.health.value
weapon.health.value = weapon.health.value
weapon.status = weapon.status
target.status = target.status
}
rule NonOwnerCannotUseWeapon {
when: CharacterUsesWeapon(thief, weapon, target)
requires: thief != weapon.owner
ensures:
target.health.value = target.health.value
weapon.health.value = weapon.health.value
weapon.status = weapon.status
target.status = target.status
}
rule WeaponDestroyedCannotDealDamage {
when: CharacterUsesWeapon(owner, weapon, target)
requires: weapon.status = destroyed
ensures:
target.health.value = target.health.value
weapon.health.value = weapon.health.value
weapon.status = weapon.status
target.status = target.status
}
------------------------------------------------------------
-- Invariants
------------------------------------------------------------
invariant MagicalObjectHealthNonNegative {
for m in MagicalObjects:
m.health.value >= 0
}
invariant MagicalObjectHealthNeverExceedsMax {
for m in MagicalObjects:
m.health.value <= m.maxHealth
}
invariant MagicalObjectDestroyedAtZeroHealth {
for m in MagicalObjects:
m.health.value = 0 implies m.status = destroyed
}
invariant MagicalObjectAliveAtPositiveHealth {
for m in MagicalObjects:
m.health.value > 0 implies m.status = alive
}