diff --git a/app/AppXhr.scala b/app/AppXhr.scala index b2d16d998f..69262aa4bb 100644 --- a/app/AppXhr.scala +++ b/app/AppXhr.scala @@ -10,7 +10,7 @@ import scalaz.effects._ final class AppXhr( val gameRepo: GameRepo, messenger: Messenger, - ai: Ai, + ai: () ⇒ Ai, finisher: Finisher, val versionMemo: VersionMemo, aliveMemo: AliveMemo, @@ -39,7 +39,7 @@ final class AppXhr( _ ← finisher.moveFinish(g3, color) } yield () else if (g3.player.isAi && g3.playable) for { - aiResult ← ai(g3) map (_.err) + aiResult ← ai()(g3) map (_.err) (newChessGame, move) = aiResult g4 = g3.update(newChessGame, move) _ ← save(g1, g4) diff --git a/app/Starter.scala b/app/Starter.scala index c35fcb0465..458323f223 100644 --- a/app/Starter.scala +++ b/app/Starter.scala @@ -10,7 +10,7 @@ final class Starter( entryRepo: EntryRepo, val versionMemo: VersionMemo, lobbySocket: lobby.Lobby, - ai: Ai) extends IOTools { + ai: () ⇒ Ai) extends IOTools { def start(game: DbGame, entryData: String): IO[DbGame] = for { _ ← if (game.variant == Standard) io() else gameRepo saveInitialFen game @@ -18,7 +18,7 @@ final class Starter( entry ⇒ entryRepo add entry flatMap { _ ⇒ lobbySocket addEntry entry }, io()) g2 ← if (game.player.isHuman) io(game) else for { - aiResult ← ai(game) map (_.err) + aiResult ← ai()(game) map (_.err) (newChessGame, move) = aiResult } yield game.update(newChessGame, move) } yield g2 diff --git a/app/SystemEnv.scala b/app/SystemEnv.scala index d82931556b..359f527677 100644 --- a/app/SystemEnv.scala +++ b/app/SystemEnv.scala @@ -91,7 +91,7 @@ final class SystemEnv(config: Config) { // frequently updated by a scheduled actor var remoteAiHealth = false - def ai: Ai = config getString "ai.use" match { + def ai: () ⇒ Ai = () ⇒ config getString "ai.use" match { case "remote" ⇒ remoteAiHealth.fold(remoteAi, craftyAi) case "crafty" ⇒ craftyAi case _ ⇒ stupidAi diff --git a/app/db/HistoryRepo.scala b/app/db/HistoryRepo.scala index 58cf9d46d3..607437f609 100644 --- a/app/db/HistoryRepo.scala +++ b/app/db/HistoryRepo.scala @@ -14,11 +14,11 @@ final class HistoryRepo(collection: MongoCollection) { val tsKey = (System.currentTimeMillis / 1000).toString collection.update( DBObject("_id" -> username), - DBObject("$set" -> (("entries." + tsKey) -> DBObject( + $set (("entries." + tsKey) -> DBObject( "t" -> entryType, "e" -> elo, "g" -> gameId - ))), + )), false, false ) } diff --git a/system/src/main/scala/ai/CraftyServer.scala b/system/src/main/scala/ai/CraftyServer.scala index dbb449f434..9136ea9de5 100644 --- a/system/src/main/scala/ai/CraftyServer.scala +++ b/system/src/main/scala/ai/CraftyServer.scala @@ -4,7 +4,7 @@ package ai import lila.chess.{ Game, Move } import model._ -import java.io.File +import java.io.ByteArrayInputStream import scala.io.Source import scala.sys.process.Process import scalaz.effects._ @@ -18,10 +18,8 @@ final class CraftyServer( else if (fen.isEmpty) "Empty fen".failNel else success(runCrafty(fen, level)) - def runCrafty(oldFen: String, level: Int): IO[String] = for { - file ← writeFile("lichess_crafty_", input(oldFen, level)) - output ← io { Process(command(level)) #< file !! } - } yield extractFen(output) + def runCrafty(oldFen: String, level: Int): IO[String] = + io { Process(command(level)) #< input(oldFen, level) !! } map extractFen private def extractFen(output: String) = { output.lines.find(_ contains "setboard") map { line ⇒ @@ -35,14 +33,14 @@ final class CraftyServer( bookPath | "", craftyTime(level)) - private def input(fen: String, level: Int) = List( + private def input(fen: String, level: Int) = new ByteArrayInputStream(List( "skill %d" format craftySkill(level), "book random 1", "book width 10", "setboard %s" format fen, "move", "savepos", - "quit") + "quit") mkString "\n" getBytes "UTF-8") private def craftyTime(level: Int) = (level / 10f).toString take 4 @@ -50,21 +48,4 @@ final class CraftyServer( case 8 ⇒ 100 case l ⇒ l * 12 } - - private def writeFile(prefix: String, data: List[String]): IO[File] = io { - File.createTempFile(prefix, ".tmp") ~ { file ⇒ - try { - file.deleteOnExit - } - catch { - case e ⇒ println("Error deleting crafty file on exit: " + e.getMessage) - } - printToFile(file)(p ⇒ data foreach p.println) - } - } - - private def printToFile(f: java.io.File)(op: java.io.PrintWriter ⇒ Unit) { - val p = new java.io.PrintWriter(f) - try { op(p) } finally { p.close() } - } } diff --git a/system/src/main/scala/ai/RemoteAi.scala b/system/src/main/scala/ai/RemoteAi.scala index 6dcf403e40..409ebaa1f6 100644 --- a/system/src/main/scala/ai/RemoteAi.scala +++ b/system/src/main/scala/ai/RemoteAi.scala @@ -9,15 +9,12 @@ import dispatch._ final class RemoteAi(remoteUrl: String) extends Ai with FenBased { - private class AiHttp extends Http with thread.Safety { - + private lazy val http = new Http with thread.Safety { override def make_logger = new Logger { def info(msg: String, items: Any*) {} def warn(msg: String, items: Any*) { println("WARN: " + msg.format(items: _*)) } } } - - private lazy val http = new AiHttp private lazy val urlObj = url(remoteUrl) def apply(dbGame: DbGame): IO[Valid[(Game, Move)]] = { diff --git a/todo b/todo index 41299dc67b..6d1ef4cfe0 100644 --- a/todo +++ b/todo @@ -5,4 +5,3 @@ ping nbm http://en.lichess.org/@/noworkingmen elo graph missing need ability to cancel rematch compress player.ps notation -move ai to marty