Handle ai first move

This commit is contained in:
Thibault Duplessis 2012-03-26 12:28:15 +02:00
parent 875516529b
commit 4908ab9d1f
14 changed files with 45 additions and 16 deletions

View file

@ -52,6 +52,10 @@ object AppApiC extends LilaController {
Ok(api.activity(gameId, color).toString)
}
def possibleMoves(gameId: String, color: String) = Action {
JsonIOk(api.possibleMoves(gameId, color))
}
def rematchAccept(gameId: String, color: String, newGameId: String) = Action { implicit request
ValidIOk[RematchData](rematchForm)(r
api.acceptRematch(gameId, newGameId, color, r._1, r._2, r._3))

View file

@ -12,11 +12,11 @@ object AppXhrC extends LilaController {
private val syncer = env.appSyncer
def sync(gameId: String, color: String, version: Int, fullId: String) = Action {
JsonOk(syncer.sync(gameId, color, version, Some(fullId)).unsafePerformIO)
JsonIOk(syncer.sync(gameId, color, version, Some(fullId)))
}
def syncPublic(gameId: String, color: String, version: Int) = Action {
JsonOk(syncer.sync(gameId, color, version, None).unsafePerformIO)
JsonIOk(syncer.sync(gameId, color, version, None))
}
def move(fullId: String) = Action { implicit request
@ -26,13 +26,13 @@ object AppXhrC extends LilaController {
}
def ping() = Action { implicit request =>
JsonOk(env.pinger.ping(
JsonIOk(env.pinger.ping(
username = get("username"),
playerKey = get("player_key"),
watcherKey = get("watcher"),
getNbWatchers = get("get_nb_watchers"),
hookId = get("hook_id")
).unsafePerformIO)
))
}
def nbPlayers() = Action {

View file

@ -17,6 +17,8 @@ trait LilaController extends Controller with ContentTypes with RequestGetter {
def JsonOk(map: Map[String, Any]) = Ok(Json generate map) as JSON
def JsonIOk(map: IO[Map[String, Any]]) = JsonOk(map.unsafePerformIO)
def ValidOk(valid: Valid[Unit]) = valid.fold(
e BadRequest(e.list mkString "\n"),
_ Ok("ok")

View file

@ -16,12 +16,12 @@ object LobbyXhrC extends LilaController {
def syncWithoutHook() = sync(None)
private def sync(hookId: Option[String]) = Action { implicit request =>
JsonOk(syncer.sync(
JsonIOk(syncer.sync(
hookId,
getIntOr("auth", 0) == 1,
getIntOr("state", 0),
getIntOr("messageId", 0),
getIntOr("entryId", 0)
).unsafePerformIO)
))
}
}

1
bc
View file

@ -1,3 +1,4 @@
Game.lastMove (and no more in pieces notation)
clock time in milliseconds (and no more floating seconds)
request promotion is not wrapped in options anymore
Game.castles (new field in forsyth format)

View file

@ -2,6 +2,7 @@ package lila.chess
import Pos.posAt
import format.Visual
import com.roundeights.hasher.Hasher
case class Board(pieces: Map[Pos, Piece], history: History) {
@ -106,10 +107,7 @@ case class Board(pieces: Map[Pos, Piece], history: History) {
})
}
def positionHash = {
import com.roundeights.hasher.Implicits._
(actors.values map (_.hash) mkString).md5.toString
}
def positionHash = Hasher(actors.values map (_.hash) mkString).md5.toString
def visual = Visual >> this
@ -120,7 +118,8 @@ object Board {
import Pos._
def apply(pieces: Traversable[(Pos, Piece)]): Board = Board(pieces toMap, History())
def apply(pieces: Traversable[(Pos, Piece)]): Board =
Board(pieces toMap, History())
def apply(pieces: (Pos, Piece)*): Board = Board(pieces toMap, History())

View file

@ -21,6 +21,7 @@ POST /api/alive/:gameId/:color controllers.AppApiC.alive(gameId: String, col
POST /api/draw/:gameId/:color controllers.AppApiC.draw(gameId: String, color: String)
POST /api/draw-accept/:gameId/:color controllers.AppApiC.drawAccept(gameId: String, color: String)
GET /api/activity/:gameId/:color controllers.AppApiC.activity(gameId: String, color: String)
GET /api/possible-moves/:gameId/:color controllers.AppApiC.possibleMoves(gameId: String, color: String)
GET /api/nb-players controllers.AppXhrC.nbPlayers
# Lobby XHR

View file

@ -8,6 +8,7 @@ import scalaz.effects._
case class AppApi(
gameRepo: GameRepo,
ai: Ai,
versionMemo: VersionMemo,
aliveMemo: AliveMemo,
addEntry: (DbGame, String) IO[Unit]) extends IOTools {
@ -40,6 +41,12 @@ case class AppApi(
def start(gameId: String, entryData: String): IO[Unit] = for {
game gameRepo game gameId
_ addEntry(game, entryData)
_ if (game.player.isAi) for {
aiResult ai(game) map (_.toOption err "AI failure")
(newChessGame, move) = aiResult
_ save(game, game.update(newChessGame, move))
} yield ()
else io()
} yield ()
def acceptRematch(
@ -92,6 +99,14 @@ case class AppApi(
def activity(gameId: String, colorName: String): Int =
Color(colorName) some { aliveMemo.activity(gameId, _) } none 0
def possibleMoves(gameId: String, colorName: String): IO[Map[String, Any]] =
for {
color ioColor(colorName)
game gameRepo game gameId
} yield game.toChess.situation.destinations map {
case (from, dests) from.key -> (dests.mkString)
} toMap
private def decodeMessages(messages: String): List[MessageEvent] =
(messages split '$').toList map { MessageEvent("system", _) }
}

View file

@ -40,9 +40,9 @@ final class AppSyncer(
clock.remainingTimes mapKeys (_.name)
} none null)
) filterValues (null !=)
} getOrElse failMap
} getOrElse Map("reload" -> true)
}
} except (e io(failMap))
}
private def renderEvents(events: List[Event], isPrivate: Boolean) =
if (isPrivate) events map {
@ -68,6 +68,4 @@ final class AppSyncer(
}
wait(max(1, duration / sleep))
}
private val failMap = Map("reload" -> true)
}

View file

@ -17,6 +17,7 @@ final class SystemEnv(config: Config) {
lazy val appApi = new AppApi(
gameRepo = gameRepo,
ai = ai,
versionMemo = versionMemo,
aliveMemo = aliveMemo,
addEntry = lobbyApi.addEntry)

View file

@ -54,6 +54,7 @@ class GameRepo(collection: MongoCollection)
d("status", _.status)
d("turns", _.turns)
d("lastMove", _.lastMove)
d("check", _.check)
d("positionHashes", _.positionHashes)
d("castles", _.castles)
for (i 0 to 1) {

View file

@ -14,6 +14,7 @@ case class DbGame(
turns: Int,
clock: Option[Clock],
lastMove: Option[String],
check: Option[Pos],
creatorColor: Color,
positionHashes: String = "",
castles: String = "KQkq",
@ -115,7 +116,8 @@ case class DbGame(
else if (situation.staleMate) Stalemate
else if (situation.autoDraw) Draw
else status,
clock = game.clock
clock = game.clock,
check = if (game.situation.check) game.situation.kingPos else None
)
if (abortable != updated.abortable || (Color.all exists { color

View file

@ -15,6 +15,7 @@ case class RawDbGame(
turns: Int,
clock: Option[RawDbClock],
lastMove: Option[String],
check: Option[String],
creatorColor: String = "white",
positionHashes: String = "",
castles: String = "KQkq",
@ -38,6 +39,7 @@ case class RawDbGame(
turns = turns,
clock = validClock,
lastMove = lastMove,
check = check flatMap posAt,
creatorColor = trueCreatorColor,
positionHashes = positionHashes,
castles = castles,
@ -58,6 +60,7 @@ object RawDbGame {
turns = turns,
clock = clock map RawDbClock.encode,
lastMove = lastMove,
check = check map (_.key),
creatorColor = creatorColor.name,
positionHashes = positionHashes,
castles = castles,

2
todo
View file

@ -0,0 +1,2 @@
start ai with black
outoftime