Merge branch 'master' into websocket
* master: Don't create remote AI http class Use a byte array input stream in crafty server Delay AI service creation to continuously check remote AI health Fix user elo history game saving Conflicts: app/Starter.scala todo
This commit is contained in:
commit
4a5c791989
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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() }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)]] = {
|
||||
|
|
Loading…
Reference in a new issue