-
Etienne Kneuss authoredEtienne Kneuss authored
Game.scala 5.20 KiB
import leon.lang._
import leon.annotation._
import leon.lang.synthesis._
import leon.collection._
object Test {
case class Pos(x: Int, y: Int) {
def up = Pos(x, y-1)
def down = Pos(x, y+1)
def left = Pos(x-1, y)
def right = Pos(x+1, y)
def isValid(s: State) = {
x >= 0 && y >= 0 &&
x < s.map.size.x && y < s.map.size.y &&
!(s.map.walls contains this)
}
def distance(o: Pos) = {
(if (o.x < x) (x-o.x) else (o.x-x)) +
(if (o.y < y) (y-o.y) else (o.y-y))
}
}
case class Map(walls: Set[Pos], size: Pos)
abstract class Action;
case object MoveUp extends Action
case object MoveDown extends Action
case object MoveLeft extends Action
case object MoveRight extends Action
case object Quit extends Action
case class State(pos: Pos,
monster: Pos,
stop: Boolean,
map: Map) {
def isValid = {
pos.isValid(this) && monster.isValid(this)
}
}
def step(s: State)(implicit o: Oracle[Action]): State = {
require(s.isValid)
val u = display(s)
stepMonster(stepPlayer(s)(o.left))
}
def stepMonster(s: State) = {
require(s.isValid)
if (s.pos == s.monster) {
State(s.pos, s.monster, true, s.map)
} else {
val mp = choose {
(res: Pos) =>
res.distance(s.monster) <= 1 &&
res.distance(s.pos) <= s.monster.distance(s.pos) &&
res.isValid(s)
}
State(s.pos, mp, mp != s.pos, s.map)
}
} ensuring { _.isValid }
def stepPlayer(s: State)(implicit o: Oracle[Action]) = {
val action: Action = ???
val ns = action match {
case Quit =>
State(s.pos, s.monster, true, s.map)
case _ if s.stop =>
s
case MoveUp if s.pos.y > 0 =>
State(s.pos.up, s.monster, s.stop, s.map)
case MoveDown =>
State(s.pos.down, s.monster, s.stop, s.map)
case MoveLeft if s.pos.x > 0 =>
State(s.pos.left, s.monster, s.stop, s.map)
case MoveRight =>
State(s.pos.right, s.monster, s.stop, s.map)
case _ =>
s
}
if (ns.isValid) ns else s
}
def steps(s: State, b: Int)(implicit o: Oracle[Action]): State = {
if (b == 0 || s.stop) {
s
} else {
steps(step(s)(o), b-1)(o.right)
}
}
def play(s: State)(implicit o: Oracle[Action]): State = {
steps(s, -1)
}
@extern
def display(s: State): Int = {
print('╔')
for (x <- 0 until s.map.size.x) {
print('═')
}
println('╗')
for (y <- 0 until s.map.size.y) {
print('║')
for (x <- 0 until s.map.size.x) {
val c = Pos(x,y)
if (s.map.walls contains c) {
print('X')
} else if (s.pos == c) {
print('o')
} else if (s.monster == c) {
print('m')
} else {
print(" ")
}
}
println('║')
}
print('╚')
for (x <- 0 until s.map.size.x) {
print('═')
}
println('╝')
42
}
@extern
def main(args: Array[String]) {
abstract class OracleSource[T] extends Oracle[T] {
def branch: OracleSource[T]
def value: T
lazy val v: T = value
lazy val l: OracleSource[T] = branch
lazy val r: OracleSource[T] = branch
override def head = v
override def left = l
override def right = r
}
class Keyboard extends OracleSource[Action] {
def branch = new Keyboard
def value = {
var askAgain = false
var action: Action = Quit
do {
if (askAgain) println("?")
askAgain = false
print("> ")
readLine().trim match {
case "up" =>
action = MoveUp
case "down" =>
action = MoveDown
case "left" =>
action = MoveLeft
case "right" =>
action = MoveRight
case "quit" =>
action = Quit
case _ =>
askAgain = true
}
} while(askAgain)
action
}
}
class Random extends OracleSource[Action] {
def value = {
readLine()
scala.util.Random.nextInt(4) match {
case 0 =>
MoveUp
case 1 =>
MoveDown
case 2 =>
MoveLeft
case 3 =>
MoveRight
case _ =>
MoveUp
}
}
def branch = new Random
}
val map = Map(Set(Pos(2,2), Pos(2,3), Pos(4,4), Pos(5,5)), Pos(10,10))
val init = State(Pos(0,0), Pos(4,5), false, map)
play(init)(new Random)
}
def test1() = {
withOracle{ o: Oracle[Action] =>
{
val map = Map(Set(Pos(2,2), Pos(2,3), Pos(4,4), Pos(5,5)), Pos(10,10))
val init = State(Pos(0,0), Pos(4,4), false, map)
steps(init, 5)(o)
} ensuring {
_.pos == Pos(0,3)
}
}
}
def validStep(s: State) = {
require(s.map.size.x > 3 && s.map.size.y > 3 && s.pos != s.monster && s.isValid && !s.stop)
val ns = withOracle { o: Oracle[Action] =>
{
stepPlayer(s)(o)
} ensuring {
res => res.isValid && !res.stop
}
}
stepMonster(ns)
} ensuring {
res => res.isValid && !res.stop
}
}