complexify the codebase. Current excuse: crazyhouse.
parent
b2e80952c2
commit
d9c0ff3eef
|
@ -6,7 +6,7 @@ import akka.actor._
|
|||
import akka.pattern.ask
|
||||
import scala.concurrent.duration._
|
||||
|
||||
import chess.format.UciMove
|
||||
import chess.format.Uci
|
||||
import lila.analyse.Info
|
||||
import lila.common.Chronometer
|
||||
import lila.game.{ Game, GameRepo }
|
||||
|
@ -32,10 +32,10 @@ final class Client(
|
|||
(millis - config.moveTime(level)) / 1000f
|
||||
}
|
||||
(for {
|
||||
uciMove ← (UciMove(moveResult.move) toValid s"${game.id} wrong bestmove: $moveResult").future
|
||||
uciMove ← (Uci.Move(moveResult.move) toValid s"${game.id} wrong bestmove: $moveResult").future
|
||||
result ← game.toChess(uciMove.orig, uciMove.dest, uciMove.promotion).future
|
||||
(c, move) = result
|
||||
progress1 = game.update(c, move)
|
||||
progress1 = game.update(c, Left(move))
|
||||
progress = progress1.game.clock.filter(_.isRunning).fold(progress1) { clock =>
|
||||
val newClock = clock.giveTime(move.color, aiLagSeconds)
|
||||
progress1.flatMap(_ withClock newClock) + lila.game.Event.Clock(newClock)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package lila.analyse
|
||||
|
||||
import chess.format.UciMove
|
||||
import chess.format.Uci
|
||||
|
||||
case class Evaluation(
|
||||
score: Option[Score],
|
||||
|
@ -26,7 +26,7 @@ object Evaluation {
|
|||
case first :: rest if first != move => first :: rest
|
||||
case _ => Nil
|
||||
}
|
||||
val best = variation.headOption flatMap UciMove.apply
|
||||
val best = variation.headOption flatMap Uci.Move.apply
|
||||
Info(
|
||||
ply = index + 1 + startedAtPly,
|
||||
score = after.score,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package lila.analyse
|
||||
|
||||
import chess.Color
|
||||
import chess.format.UciMove
|
||||
import chess.format.Uci
|
||||
|
||||
case class Info(
|
||||
ply: Int,
|
||||
|
@ -10,7 +10,7 @@ case class Info(
|
|||
// variation is first in UCI, then converted to PGN before storage
|
||||
variation: List[String] = Nil,
|
||||
// best is always in UCI (used for hilight)
|
||||
best: Option[UciMove] = None) {
|
||||
best: Option[Uci.Move] = None) {
|
||||
|
||||
def turn = 1 + (ply - 1) / 2
|
||||
|
||||
|
@ -57,7 +57,7 @@ object Info {
|
|||
case Array(cp) => Info(ply, Score(cp)).some
|
||||
case Array(cp, ma) => Info(ply, Score(cp), parseIntOption(ma)).some
|
||||
case Array(cp, ma, va) => Info(ply, Score(cp), parseIntOption(ma), va.split(' ').toList).some
|
||||
case Array(cp, ma, va, be) => Info(ply, Score(cp), parseIntOption(ma), va.split(' ').toList, UciMove piotr be).some
|
||||
case Array(cp, ma, va, be) => Info(ply, Score(cp), parseIntOption(ma), va.split(' ').toList, Uci.Move piotr be).some
|
||||
case _ => none
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
package lila.analyse
|
||||
|
||||
import chess.format.pgn.Dumper
|
||||
import chess.format.UciMove
|
||||
import chess.format.Uci
|
||||
import chess.{ Replay, Move, Situation }
|
||||
import scalaz.Validation.FlatMap._
|
||||
|
||||
import lila.common.LilaException
|
||||
|
||||
|
@ -25,7 +26,7 @@ private[analyse] object UciToPgn {
|
|||
def uciToPgn(ply: Int, variation: List[String]): Valid[List[PgnMove]] = for {
|
||||
situation ← if (ply == replay.setup.startedAtTurn + 1) success(replay.setup.situation)
|
||||
else replay moveAtPly ply map (_.situationBefore) toValid "No move found"
|
||||
ucis ← variation.map(UciMove.apply).sequence toValid "Invalid UCI moves " + variation
|
||||
ucis ← variation.map(Uci.Move.apply).sequence toValid "Invalid UCI moves " + variation
|
||||
moves ← ucis.foldLeft[Valid[(Situation, List[Move])]](success(situation -> Nil)) {
|
||||
case (scalaz.Success((sit, moves)), uci) =>
|
||||
sit.move(uci.orig, uci.dest, uci.promotion) prefixFailuresWith s"ply $ply " map { move =>
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 6961025066a29b6907db4b243bad7c4a8abb68d2
|
||||
Subproject commit e92da748fb3976b4351cf9c847810035e4bd3786
|
|
@ -40,7 +40,7 @@ object BSONHandlers {
|
|||
)
|
||||
}
|
||||
|
||||
private[game] implicit val gameBSONHandler = new BSON[Game] {
|
||||
implicit val gameBSONHandler = new BSON[Game] {
|
||||
|
||||
import Game.BSONFields._
|
||||
import PgnImport.pgnImportBSONHandler
|
||||
|
|
|
@ -5,7 +5,7 @@ import play.api.libs.json._
|
|||
|
||||
import chess.Pos
|
||||
import chess.Pos.{ piotr, allPiotrs }
|
||||
import chess.{ PromotableRole, Pos, Color, Situation, Move => ChessMove, Clock => ChessClock, Status }
|
||||
import chess.{ PromotableRole, Pos, Color, Situation, Move => ChessMove, Drop => ChessDrop, Clock => ChessClock, Status }
|
||||
import lila.chat.{ Line, UserLine, PlayerLine }
|
||||
import lila.common.Maths.truncateAt
|
||||
|
||||
|
@ -31,7 +31,6 @@ object Event {
|
|||
case class Move(
|
||||
orig: Pos,
|
||||
dest: Pos,
|
||||
color: Color,
|
||||
san: String,
|
||||
fen: String,
|
||||
check: Boolean,
|
||||
|
@ -65,7 +64,6 @@ object Event {
|
|||
def apply(move: ChessMove, situation: Situation, state: State, clock: Option[Event]): Move = Move(
|
||||
orig = move.orig,
|
||||
dest = move.dest,
|
||||
color = move.piece.color,
|
||||
san = chess.format.pgn.Dumper(move),
|
||||
fen = chess.format.Forsyth.exportBoard(situation.board),
|
||||
check = situation.check,
|
||||
|
@ -82,6 +80,45 @@ object Event {
|
|||
possibleMoves = situation.destinations)
|
||||
}
|
||||
|
||||
case class Drop(
|
||||
role: chess.Role,
|
||||
pos: Pos,
|
||||
san: String,
|
||||
fen: String,
|
||||
check: Boolean,
|
||||
threefold: Boolean,
|
||||
state: State,
|
||||
clock: Option[Event],
|
||||
possibleMoves: Map[Pos, List[Pos]]) extends Event {
|
||||
def typ = "drop"
|
||||
def data = Json.obj(
|
||||
"uci" -> s"${role.pgn}@${pos.key}",
|
||||
"san" -> san,
|
||||
"fen" -> fen,
|
||||
"check" -> check.option(true),
|
||||
"threefold" -> threefold.option(true),
|
||||
"ply" -> state.turns,
|
||||
"status" -> state.status,
|
||||
"winner" -> state.winner,
|
||||
"wDraw" -> state.whiteOffersDraw.option(true),
|
||||
"bDraw" -> state.blackOffersDraw.option(true),
|
||||
"clock" -> clock.map(_.data),
|
||||
"dests" -> PossibleMoves.json(possibleMoves)
|
||||
).noNull
|
||||
}
|
||||
object Drop {
|
||||
def apply(drop: ChessDrop, situation: Situation, state: State, clock: Option[Event]): Drop = Drop(
|
||||
role = drop.piece.role,
|
||||
pos = drop.pos,
|
||||
san = chess.format.pgn.Dumper(drop),
|
||||
fen = chess.format.Forsyth.exportBoard(situation.board),
|
||||
check = situation.check,
|
||||
threefold = situation.threefoldRepetition,
|
||||
state = state,
|
||||
clock = clock,
|
||||
possibleMoves = situation.destinations)
|
||||
}
|
||||
|
||||
case class PossibleMoves(
|
||||
color: Color,
|
||||
moves: Map[Pos, List[Pos]]) extends Event {
|
||||
|
|
|
@ -4,7 +4,7 @@ import chess.Color.{ White, Black }
|
|||
import chess.format.Uci
|
||||
import chess.Pos.piotr, chess.Role.forsyth
|
||||
import chess.variant.{ Variant, Crazyhouse }
|
||||
import chess.{ History => ChessHistory, CheckCount, Castles, Role, Board, Move, Pos, Game => ChessGame, Clock, Status, Color, Piece, Mode, PositionHash }
|
||||
import chess.{ History => ChessHistory, CheckCount, Castles, Role, Board, Move, Drop, MoveOrDrop, Pos, Game => ChessGame, Clock, Status, Color, Piece, Mode, PositionHash }
|
||||
import org.joda.time.DateTime
|
||||
import scala.concurrent.duration.FiniteDuration
|
||||
|
||||
|
@ -150,7 +150,7 @@ case class Game(
|
|||
|
||||
def update(
|
||||
game: ChessGame,
|
||||
move: Move,
|
||||
moveOrDrop: MoveOrDrop,
|
||||
blur: Boolean = false,
|
||||
lag: Option[FiniteDuration] = None): Progress = {
|
||||
val (history, situation) = (game.board.history, game.situation)
|
||||
|
@ -158,7 +158,7 @@ case class Game(
|
|||
def copyPlayer(player: Player) = player.copy(
|
||||
blurs = math.min(
|
||||
playerMoves(player.color),
|
||||
player.blurs + (blur && move.color == player.color).fold(1, 0))
|
||||
player.blurs + (blur && moveOrDrop.fold(_.color, _.color) == player.color).fold(1, 0))
|
||||
)
|
||||
|
||||
val updated = copy(
|
||||
|
@ -197,7 +197,10 @@ case class Game(
|
|||
updated.playableCorrespondenceClock map Event.CorrespondenceClock.apply
|
||||
}
|
||||
|
||||
val events = Event.Move(move, situation, state, clockEvent) ::
|
||||
val events = moveOrDrop.fold(
|
||||
Event.Move(_, situation, state, clockEvent),
|
||||
Event.Drop(_, situation, state, clockEvent)
|
||||
) ::
|
||||
{
|
||||
// abstraction leak, I know.
|
||||
(updated.variant.threeCheck && situation.check) ?? List(Event.CheckCount(
|
||||
|
|
|
@ -2,7 +2,7 @@ package lila.importer
|
|||
|
||||
import akka.actor.ActorRef
|
||||
import chess.Color
|
||||
import chess.format.UciMove
|
||||
import chess.format.Uci
|
||||
import lila.game.{ Game, Player, Source, GameRepo, Pov }
|
||||
import lila.hub.actorApi.map.Tell
|
||||
import lila.round.actorApi.round._
|
||||
|
@ -28,7 +28,7 @@ final class Live(
|
|||
GameRepo game id flatMap {
|
||||
_ filter (g => g.playable && g.imported) match {
|
||||
case None => fufail("No such playing game: " + id)
|
||||
case Some(game) => UciMove(move) match {
|
||||
case Some(game) => Uci(move) match {
|
||||
case None => move match {
|
||||
case "1-0" => fuccess {
|
||||
roundMap ! Tell(game.id, Resign(game.blackPlayer.id))
|
||||
|
@ -48,12 +48,10 @@ final class Live(
|
|||
}
|
||||
}
|
||||
|
||||
private def applyMove(pov: Pov, move: UciMove) {
|
||||
private def applyMove(pov: Pov, uci: Uci) {
|
||||
roundMap ! Tell(pov.gameId, HumanPlay(
|
||||
playerId = pov.playerId,
|
||||
orig = move.orig.toString,
|
||||
dest = move.dest.toString,
|
||||
prom = move.promotion map (_.name),
|
||||
uci = uci,
|
||||
blur = false,
|
||||
lag = 0.millis
|
||||
))
|
||||
|
|
|
@ -4,6 +4,7 @@ import scala.util.{ Try, Success, Failure }
|
|||
|
||||
import org.joda.time.DateTime
|
||||
import play.api.libs.json._
|
||||
import scalaz.Validation.FlatMap._
|
||||
|
||||
private[opening] case class Generated(
|
||||
fen: String,
|
||||
|
@ -42,7 +43,7 @@ private[opening] object Generated {
|
|||
implicit val generatedMoveJSONRead = Json.reads[Move]
|
||||
implicit val generatedJSONRead = Json.reads[Generated]
|
||||
|
||||
import chess.format.UciMove
|
||||
import chess.format.Uci
|
||||
|
||||
private[opening] def toPgn(
|
||||
situation: chess.Situation,
|
||||
|
@ -52,8 +53,8 @@ private[opening] object Generated {
|
|||
player = situation.color)
|
||||
(uciMoves.foldLeft(Try(game)) {
|
||||
case (game, moveStr) => game flatMap { g =>
|
||||
(UciMove(moveStr) toValid s"Invalid UCI move $moveStr" flatMap {
|
||||
case UciMove(orig, dest, prom) => g(orig, dest, prom) map (_._1)
|
||||
(Uci.Move(moveStr) toValid s"Invalid UCI move $moveStr" flatMap {
|
||||
case Uci.Move(orig, dest, prom) => g(orig, dest, prom) map (_._1)
|
||||
}).fold(errs => Failure(new Exception(errs.shows)), Success.apply)
|
||||
}
|
||||
}) map (_.pgnMoves)
|
||||
|
|
|
@ -2,7 +2,7 @@ package lila.puzzle
|
|||
|
||||
import scala.util.{ Try, Success, Failure }
|
||||
|
||||
import chess.format.{ Forsyth, UciMove }
|
||||
import chess.format.{ Forsyth, Uci }
|
||||
import chess.Game
|
||||
import org.joda.time.DateTime
|
||||
import play.api.libs.json._
|
||||
|
@ -36,8 +36,8 @@ object Generated {
|
|||
private[puzzle] def fenOf(moves: Seq[String]): Try[String] =
|
||||
(moves.init.foldLeft(Try(Game(chess.variant.Standard))) {
|
||||
case (game, moveStr) => game flatMap { g =>
|
||||
(UciMove(moveStr) toValid s"Invalid UCI move $moveStr" flatMap {
|
||||
case UciMove(orig, dest, prom) => g(orig, dest, prom) map (_._1)
|
||||
(Uci.Move(moveStr) toValid s"Invalid UCI move $moveStr" flatMap {
|
||||
case Uci.Move(orig, dest, prom) => g(orig, dest, prom) map (_._1)
|
||||
}).fold(errs => Failure(new Exception(errs.shows)), Success.apply)
|
||||
}
|
||||
}) map { game =>
|
||||
|
|
|
@ -34,10 +34,10 @@ case class Puzzle(
|
|||
def enabled = vote.sum > -9000
|
||||
|
||||
def fenAfterInitialMove: Option[String] = {
|
||||
import chess.format.{ UciMove, Forsyth }
|
||||
import chess.format.{ Uci, Forsyth }
|
||||
for {
|
||||
sit1 <- Forsyth << fen
|
||||
uci <- UciMove(initialMove)
|
||||
uci <- Uci.Move(initialMove)
|
||||
sit2 <- sit1.move(uci.orig, uci.dest, uci.promotion).toOption map (_.situationAfter)
|
||||
} yield Forsyth >> sit2
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ package lila.round
|
|||
import org.joda.time.DateTime
|
||||
import play.api.libs.json._
|
||||
|
||||
import chess.format.UciMove
|
||||
import chess.format.Uci
|
||||
import chess.{ Pos, Move }
|
||||
import lila.game.Game
|
||||
|
||||
|
@ -12,7 +12,7 @@ case class Forecast(
|
|||
steps: Forecast.Steps,
|
||||
date: DateTime) {
|
||||
|
||||
def apply(g: Game, lastMove: Move): Option[(Forecast, UciMove)] =
|
||||
def apply(g: Game, lastMove: Move): Option[(Forecast, Uci.Move)] =
|
||||
nextMove(g, lastMove) map { move =>
|
||||
copy(
|
||||
steps = steps.collect {
|
||||
|
@ -25,7 +25,7 @@ case class Forecast(
|
|||
// accept up to 30 lines of 30 moves each
|
||||
def truncate = copy(steps = steps.take(30).map(_ take 30))
|
||||
|
||||
private def nextMove(g: Game, last: Move) = steps.foldLeft(none[UciMove]) {
|
||||
private def nextMove(g: Game, last: Move) = steps.foldLeft(none[Uci.Move]) {
|
||||
case (None, fst :: snd :: _) if g.turns == fst.ply && fst.is(last) => snd.uciMove
|
||||
case (move, _) => move
|
||||
}
|
||||
|
@ -45,10 +45,10 @@ object Forecast {
|
|||
check: Option[Boolean],
|
||||
dests: String) {
|
||||
|
||||
def is(move: Move) = move.uciString == uci
|
||||
def is(move: UciMove) = move.uci == uci
|
||||
def is(move: Move) = move.toUci.uci == uci
|
||||
def is(move: Uci.Move) = move.uci == uci
|
||||
|
||||
def uciMove = UciMove(uci)
|
||||
def uciMove = Uci.Move(uci)
|
||||
}
|
||||
|
||||
implicit val forecastStepJsonFormat = Json.format[Step]
|
||||
|
|
|
@ -8,7 +8,7 @@ import org.joda.time.DateTime
|
|||
import scala.concurrent.duration.Duration
|
||||
import scala.concurrent.Promise
|
||||
|
||||
import chess.format.UciMove
|
||||
import chess.format.Uci
|
||||
import chess.Pos
|
||||
import Forecast.Step
|
||||
import lila.game.{ Pov, Game }
|
||||
|
@ -44,13 +44,11 @@ final class ForecastApi(coll: Coll, roundMap: akka.actor.ActorSelection) {
|
|||
uciMove: String,
|
||||
steps: Forecast.Steps): Funit =
|
||||
if (!pov.isMyTurn) fufail("not my turn")
|
||||
else UciMove(uciMove).fold[Funit](fufail(s"Invalid move $uciMove")) { uci =>
|
||||
else Uci.Move(uciMove).fold[Funit](fufail(s"Invalid move $uciMove")) { uci =>
|
||||
val promise = Promise[Unit]
|
||||
roundMap ! Tell(pov.game.id, actorApi.round.HumanPlay(
|
||||
playerId = pov.playerId,
|
||||
orig = uci.orig.key,
|
||||
dest = uci.dest.key,
|
||||
prom = uci.promotion.map(_.name),
|
||||
uci = uci,
|
||||
blur = true,
|
||||
lag = Duration.Zero,
|
||||
promise = promise.some))
|
||||
|
@ -73,7 +71,7 @@ final class ForecastApi(coll: Coll, roundMap: akka.actor.ActorSelection) {
|
|||
else fuccess(fc.some)
|
||||
}
|
||||
|
||||
def nextMove(g: Game, last: chess.Move): Fu[Option[UciMove]] = g.forecastable ?? {
|
||||
def nextMove(g: Game, last: chess.Move): Fu[Option[Uci.Move]] = g.forecastable ?? {
|
||||
loadForPlay(Pov player g) flatMap {
|
||||
case None => fuccess(none)
|
||||
case Some(fc) => fc(g, last) match {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package lila.round
|
||||
|
||||
import chess.format.Forsyth
|
||||
import chess.format.{ Forsyth, Uci }
|
||||
import chess.Pos.posAt
|
||||
import chess.{ Status, Role, Color }
|
||||
import chess.{ Status, Role, Color, MoveOrDrop }
|
||||
import scalaz.Validation.FlatMap._
|
||||
|
||||
import actorApi.round.{ HumanPlay, AiPlay, ImportPlay, DrawNo, TakebackNo, PlayResult, Cheat, ForecastPlay }
|
||||
|
@ -19,20 +19,26 @@ private[round] final class Player(
|
|||
uciMemo: UciMemo) {
|
||||
|
||||
def human(play: HumanPlay, round: ActorRef)(pov: Pov): Fu[Events] = play match {
|
||||
case HumanPlay(playerId, origS, destS, promS, blur, lag, promiseOption) => pov match {
|
||||
case HumanPlay(playerId, uci, blur, lag, promiseOption) => pov match {
|
||||
case Pov(game, color) if game playableBy color => {
|
||||
(for {
|
||||
orig ← posAt(origS) toValid "Wrong orig " + origS
|
||||
dest ← posAt(destS) toValid "Wrong dest " + destS
|
||||
promotion = Role promotable promS
|
||||
newChessGameAndMove ← game.toChess(orig, dest, promotion, lag)
|
||||
(newChessGame, move) = newChessGameAndMove
|
||||
} yield game.update(newChessGame, move, blur, lag.some) -> move).prefixFailuresWith(s"$pov ")
|
||||
(uci match {
|
||||
case Uci.Move(orig, dest, prom) => game.toChess.apply(orig, dest, prom, lag) map {
|
||||
case (ncg, move) => ncg -> (Left(move): MoveOrDrop)
|
||||
}
|
||||
case Uci.Drop(role, pos) => game.toChess.drop(role, pos, lag) map {
|
||||
case (ncg, drop) => ncg -> (Right(drop): MoveOrDrop)
|
||||
}
|
||||
}).map {
|
||||
case (newChessGame, moveOrDrop) =>
|
||||
game.update(newChessGame, moveOrDrop, blur, lag.some) -> moveOrDrop
|
||||
}.prefixFailuresWith(s"$pov ")
|
||||
.fold(errs => ClientErrorException.future(errs.shows), fuccess).flatMap {
|
||||
case (progress, move) =>
|
||||
case (progress, moveOrDrop) =>
|
||||
(GameRepo save progress) >>-
|
||||
(pov.game.hasAi ! uciMemo.add(pov.game, move)) >>-
|
||||
notifyMove(move, progress.game) >>
|
||||
moveOrDrop.left.toOption.foreach { move =>
|
||||
pov.game.hasAi ! uciMemo.add(pov.game, move)
|
||||
} >>-
|
||||
notifyMove(moveOrDrop, progress.game) >>
|
||||
progress.game.finished.fold(
|
||||
moveFinish(progress.game, color) map { progress.events ::: _ }, {
|
||||
cheatDetector(progress.game) addEffect {
|
||||
|
@ -41,7 +47,9 @@ private[round] final class Player(
|
|||
if (progress.game.playableByAi) round ! AiPlay
|
||||
if (pov.opponent.isOfferingDraw) round ! DrawNo(pov.player.id)
|
||||
if (pov.player.isProposingTakeback) round ! TakebackNo(pov.player.id)
|
||||
if (pov.game.forecastable) round ! ForecastPlay(move)
|
||||
moveOrDrop.left.toOption.ifTrue(pov.game.forecastable).foreach { move =>
|
||||
round ! ForecastPlay(move)
|
||||
}
|
||||
} inject progress.events
|
||||
}) >>- promiseOption.foreach(_.success(()))
|
||||
}
|
||||
|
@ -60,7 +68,7 @@ private[round] final class Player(
|
|||
case Pov(game, color) if game.turnOf(color) && game.playableEvenImported =>
|
||||
game.toChess(orig, dest, promotion).future.flatMap {
|
||||
case (newChessGame, move) =>
|
||||
val progress = game.update(newChessGame, move)
|
||||
val progress = game.update(newChessGame, Left(move))
|
||||
(GameRepo save progress) >>-
|
||||
(progress.game.finished ?? moveFinish(progress.game, color)) inject Nil
|
||||
}
|
||||
|
@ -72,20 +80,21 @@ private[round] final class Player(
|
|||
(game.playable && game.player.isAi).fold(
|
||||
engine.play(game, game.aiLevel | 1) flatMap {
|
||||
case lila.ai.actorApi.PlayResult(progress, move, _) =>
|
||||
notifyMove(move, progress.game)
|
||||
notifyMove(Left(move), progress.game)
|
||||
moveFinish(progress.game, game.turnColor) map { progress.++ }
|
||||
},
|
||||
fufail(s"Not AI turn")
|
||||
) prefixFailure s"[ai play] game ${game.id} turn ${game.turns}"
|
||||
|
||||
private def notifyMove(move: chess.Move, game: Game) {
|
||||
private def notifyMove(moveOrDrop: MoveOrDrop, game: Game) {
|
||||
val color = moveOrDrop.fold(_.color, _.color)
|
||||
bus.publish(MoveEvent(
|
||||
gameId = game.id,
|
||||
color = move.color,
|
||||
color = color,
|
||||
fen = Forsyth exportBoard game.toChess.board,
|
||||
move = move.keyString,
|
||||
move = moveOrDrop.fold(_.toUci.keys, _.toUci.uci),
|
||||
mobilePushable = game.mobilePushable,
|
||||
opponentUserId = game.player(!move.color).userId,
|
||||
opponentUserId = game.player(!color).userId,
|
||||
simulId = game.simulId
|
||||
), 'moveEvent)
|
||||
}
|
||||
|
|
|
@ -179,8 +179,7 @@ private[round] final class Round(
|
|||
case ForecastPlay(lastMove) => handle { game =>
|
||||
forecastApi.nextMove(game, lastMove) map { mOpt =>
|
||||
mOpt foreach { move =>
|
||||
self ! HumanPlay(
|
||||
game.player.id, move.orig.key, move.dest.key, move.promotion.map(_.name), false, 0.seconds)
|
||||
self ! HumanPlay(game.player.id, move, false, 0.seconds)
|
||||
}
|
||||
Nil
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import scala.concurrent.Promise
|
|||
import akka.actor._
|
||||
import akka.pattern.{ ask, pipe }
|
||||
import chess.Color
|
||||
import chess.format.Uci
|
||||
import play.api.libs.json.{ JsObject, Json }
|
||||
|
||||
import actorApi._, round._
|
||||
|
@ -44,14 +45,25 @@ private[round] final class SocketHandler(
|
|||
{
|
||||
case ("p", o) => o int "v" foreach { v => socket ! PingVersion(uid, v) }
|
||||
case ("move", o) => parseMove(o) foreach {
|
||||
case (orig, dest, prom, blur, lag) =>
|
||||
case (move, blur, lag) =>
|
||||
member push ackEvent
|
||||
val promise = Promise[Unit]
|
||||
promise.future onFailure {
|
||||
case _: Exception => socket ! Resync(uid)
|
||||
}
|
||||
round(HumanPlay(
|
||||
playerId, orig, dest, prom, blur, lag.millis, promise.some
|
||||
playerId, move, blur, lag.millis, promise.some
|
||||
))
|
||||
}
|
||||
case ("drop", o) => parseDrop(o) foreach {
|
||||
case (drop, blur, lag) =>
|
||||
member push ackEvent
|
||||
val promise = Promise[Unit]
|
||||
promise.future onFailure {
|
||||
case _: Exception => socket ! Resync(uid)
|
||||
}
|
||||
round(HumanPlay(
|
||||
playerId, drop, blur, lag.millis, promise.some
|
||||
))
|
||||
}
|
||||
case ("rematch-yes", _) => round(RematchYes(playerId))
|
||||
|
@ -137,9 +149,19 @@ private[round] final class SocketHandler(
|
|||
orig ← d str "from"
|
||||
dest ← d str "to"
|
||||
prom = d str "promotion"
|
||||
move <- Uci.Move.fromStrings(orig, dest, prom)
|
||||
blur = (d int "b") == Some(1)
|
||||
lag = d int "lag"
|
||||
} yield (orig, dest, prom, blur, ~lag)
|
||||
} yield (move, blur, ~lag)
|
||||
|
||||
private def parseDrop(o: JsObject) = for {
|
||||
d ← o obj "d"
|
||||
role ← d str "role"
|
||||
pos ← d str "pos"
|
||||
drop <- Uci.Drop.fromStrings(role, pos)
|
||||
blur = (d int "b") == Some(1)
|
||||
lag = d int "lag"
|
||||
} yield (drop, blur, ~lag)
|
||||
|
||||
private val ackEvent = Json.obj("t" -> "ack")
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import scala.concurrent.duration.FiniteDuration
|
|||
import scala.concurrent.Promise
|
||||
|
||||
import chess.Color
|
||||
import chess.format.Uci
|
||||
|
||||
import lila.game.{ Game, Event, PlayerRef }
|
||||
import lila.socket.SocketMember
|
||||
|
@ -93,9 +94,7 @@ package round {
|
|||
|
||||
case class HumanPlay(
|
||||
playerId: String,
|
||||
orig: String,
|
||||
dest: String,
|
||||
prom: Option[String],
|
||||
uci: Uci,
|
||||
blur: Boolean,
|
||||
lag: FiniteDuration,
|
||||
promise: Option[Promise[Unit]] = None) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package lila.socket
|
||||
|
||||
import chess.format.UciMove
|
||||
import chess.format.Uci
|
||||
import lila.common.PimpedJson._
|
||||
import play.api.libs.json.JsObject
|
||||
|
||||
|
@ -17,7 +17,7 @@ case class AnaMove(
|
|||
case (game, move) => Step(
|
||||
ply = game.turns,
|
||||
move = game.pgnMoves.lastOption.map { san =>
|
||||
Step.Move(UciMove(move), san)
|
||||
Step.Move(Uci(move), san)
|
||||
},
|
||||
fen = chess.format.Forsyth >> game,
|
||||
check = game.situation.check,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package lila.socket
|
||||
|
||||
import chess.format.UciMove
|
||||
import chess.format.Uci
|
||||
import chess.Pos
|
||||
|
||||
import play.api.libs.functional.syntax._
|
||||
|
@ -27,16 +27,16 @@ case class Step(
|
|||
|
||||
object Step {
|
||||
|
||||
case class Move(uci: UciMove, san: String) {
|
||||
case class Move(uci: Uci, san: String) {
|
||||
def uciString = uci.uci
|
||||
}
|
||||
|
||||
case class Eval(
|
||||
cp: Option[Int] = None,
|
||||
mate: Option[Int] = None,
|
||||
best: Option[UciMove])
|
||||
best: Option[Uci.Move])
|
||||
|
||||
private implicit val uciJsonWriter: Writes[UciMove] = Writes { uci =>
|
||||
private implicit val uciJsonWriter: Writes[Uci.Move] = Writes { uci =>
|
||||
JsString(uci.uci)
|
||||
}
|
||||
private implicit val evalJsonWriter = Json.writes[Eval]
|
||||
|
|
Loading…
Reference in New Issue