create magical objects spec
This commit is contained in:
parent
fb61fb85ed
commit
1c9d4ad66b
182
specs/magical-objects.allium
Normal file
182
specs/magical-objects.allium
Normal 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
|
||||||
|
}
|
||||||
@ -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
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user