Skip to content

Instantly share code, notes, and snippets.

@embs
Last active June 24, 2017 00:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save embs/b2142557507316fa47b559112b523565 to your computer and use it in GitHub Desktop.
Save embs/b2142557507316fa47b559112b523565 to your computer and use it in GitHub Desktop.
An epic battle CSP specification
*.swp
*.class
-- Warrior's behaviour
channel have_bards_to_sing_worship_songs, sharpen_sword
-- Warrior's attributes
WARRIOR_MAX_SP = 10
SWORD_STAB_SP_COST = 3
SWORD_STAB_DAMAGE = 1
-- Dragon's behaviour
channel fly_in_the_endless_blue_sky, regurgitate_fire
-- Dragon's attributes
DRAGON_MAX_SP = 20
FIRE_SPIT_SP_COST = 3
FIRE_SPIT_DAMAGE = 1
-- Shared behaviour
channel damage_warrior, damage_dragon : {1..5}
-- hp: amount of health points
-- sp: stamina points
WARRIOR(hp, sp) =
have_bards_to_sing_worship_songs -> WARRIOR(hp, sp)
[] hp > 0 and sp < WARRIOR_MAX_SP & sharpen_sword -> WARRIOR(hp, sp + 1)
[] hp > 0 and sp >= SWORD_STAB_SP_COST &
damage_dragon.SWORD_STAB_DAMAGE -> WARRIOR(hp, sp - SWORD_STAB_SP_COST)
[] hp > 0 & damage_warrior?d -> WARRIOR(hp - d, sp)
DRAGON(hp, sp) =
fly_in_the_endless_blue_sky -> DRAGON(hp, sp)
[] hp > 0 and sp < DRAGON_MAX_SP & regurgitate_fire -> DRAGON(hp, sp + 1)
[] hp > 0 and sp >= FIRE_SPIT_SP_COST &
damage_warrior.FIRE_SPIT_DAMAGE -> DRAGON(hp, sp - FIRE_SPIT_SP_COST)
[] hp > 0 & damage_dragon?d -> DRAGON(hp - d, sp)
BATTLE = DOM_QUIXOTE [|{|damage_warrior, damage_dragon|}|] ROCINANTE
DOM_QUIXOTE = WARRIOR(3, 3)
assert DOM_QUIXOTE :[deadlock free]
assert DOM_QUIXOTE :[divergence free]
assert DOM_QUIXOTE :[deterministic]
ROCINANTE = DRAGON(3, 3)
assert ROCINANTE :[deadlock free]
assert ROCINANTE :[divergence free]
assert ROCINANTE :[deterministic]
assert BATTLE :[deadlock free]
assert BATTLE :[divergence free]
assert BATTLE :[deterministic]
#INCLUDE "course.module"
PROC main (SHARED CHAN BYTE out!)
CHAN INT warrior.attacks.dragon :
CHAN INT dragon.attacks.warrior :
TIMER clock :
REC PROC warrior (CHAN INT attack, be.attacked, VAL INT hp, sp)
INT damage, now :
INITIAL INT max.warrior.sp IS 10 :
SEQ -- I'd really like to remove this
CLAIM out! -- this
out.string("--", 0, out!) -- and this lines
ALT
TRUE & SKIP
SEQ
clock ? now -- delay to avoid polluting output
clock ? AFTER now PLUS 10000
CLAIM out!
out.string(".", 0, out!)
warrior(attack, be.attacked, hp, sp)
((hp > 0) AND (sp < max.warrior.sp)) & SKIP
SEQ
CLAIM out!
SEQ
out.string("Warrior recovers 1 sp.*n", 0, out!)
warrior(attack, be.attacked, hp, sp + 1)
((hp > 0) AND (sp >= 3)) & SKIP
SEQ
attack ! 5
warrior(attack, be.attacked, hp, sp - 1)
hp > 0 & be.attacked ? damage
SEQ
CLAIM out!
SEQ
out.string("Warrior receives ", 0, out!)
out.int(damage, 0, out!)
out.string(" damage and now has ", 0, out!)
out.int(hp - damage, 0, out!)
out.string(" hp.*n", 0, out!)
warrior(attack, be.attacked, hp - damage, sp)
:
REC PROC dragon (CHAN INT attack, be.attacked, VAL INT hp, sp)
INT damage, now :
INITIAL INT max.dragon.sp IS 10 :
SEQ -- I'd really like to remove this
CLAIM out! -- this
out.string("--", 0, out!) -- and this lines
ALT
TRUE & SKIP
SEQ
clock ? now -- delay to avoid polluting output
clock ? AFTER now PLUS 10000
CLAIM out!
out.string(".", 0, out!)
dragon(attack, be.attacked, hp, sp)
((hp > 0) AND (sp < max.dragon.sp)) & SKIP
SEQ
CLAIM out!
SEQ
out.string("Dragon recovers 1 sp.*n", 0, out!)
dragon(attack, be.attacked, hp, sp + 1)
((hp > 0) AND (sp >= 3)) & SKIP
SEQ
attack ! 5
dragon(attack, be.attacked, hp, sp - 1)
hp > 0 & be.attacked ? damage
SEQ
CLAIM out!
SEQ
out.string("Dragon receives ", 0, out!)
out.int(damage, 0, out!)
out.string(" damage and now has ", 0, out!)
out.int(hp - damage, 0, out!)
out.string(" hp.*n", 0, out!)
dragon(attack, be.attacked, hp - damage, sp)
:
SEQ
VAL INT warrior.hp IS 10 :
VAL INT warrior.sp IS 3 :
VAL INT dragon.hp IS 10 :
VAL INT dragon.sp IS 3 :
PAR
warrior (warrior.attacks.dragon, dragon.attacks.warrior, warrior.hp, warrior.sp)
dragon (dragon.attacks.warrior, warrior.attacks.dragon, dragon.hp, dragon.sp)
:
import io.threadcso._
object Battle {
val WarriorMaxSp = 10
val SwordStabSpCost = 3
val SwordStabDamage = 1
val DragonMaxSp = 20
val FireSpitSpCost = 3
val FireSpitDamage = 1
val damageWarrior = OneOne[Int]
val damageDragon = OneOne[Int]
def warrior(inflictDamage: ![Int], receiveDamage: ?[Int]) = proc {
var hp : Int = 3
var sp : Int = 3
var damage: Int = 0
println("Come here you @(*&% beast!")
while(hp > 0) {
if(sp < WarriorMaxSp) {
println("Warrior sharpens their sword and recovers 1 SP")
sp = sp + 1
} else {
println("Warrior throws Stopped")
throw new io.threadcso.processimplementation.Stopped()
}
alt(
(sp >= SwordStabSpCost &&& inflictDamage) =!=> { SwordStabDamage } ==> {
sp = sp - SwordStabSpCost
println("Warrior stabs dragon with their sword")
}
|
(hp > 0 &&& receiveDamage) =?=> {
damage => hp = hp - damage
println("Warrior receives " + damage + " damage")
}
)
}
println("Warrior's dead")
}
def dragon(inflictDamage: ![Int], receiveDamage: ?[Int]) = proc {
var hp : Int = 3
var sp : Int = 3
println("Ggggrrrrrrrr")
while(hp > 0) {
if(sp < DragonMaxSp) {
sp = sp + 1
println("Dragon regurgitates fire and recovers 1 SP. Now it has " + sp)
} else {
println("Dragon throws Stopped")
throw new io.threadcso.processimplementation.Stopped()
}
alt(
((hp > 0 && sp >= FireSpitSpCost) &&& inflictDamage) =!=> { FireSpitDamage } ==> {
println("Dragon spits fire all over the warrior"); sp = sp - FireSpitSpCost
}
|
(hp > 0 &&& receiveDamage) =?=> {
damage => hp = hp - damage
println("Dragon receives " + damage + " damage")
}
)
println("Dragon's HP/SP: " + hp + "/" + sp)
}
println("Dragon's dead")
}
def main(args: Array[String]) {
println("Let the battle begin!")
(warrior(damageDragon, damageWarrior) || dragon(damageWarrior, damageDragon))()
exit
}
}
#!/usr/bin/env bash
scalac -cp "*.jar:." Battle.scala
scala -cp "*.jar:." Battle
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment