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 } }