replace more Game fields with Game.chess
parent
e618d542f4
commit
6e3b1c4057
|
@ -56,7 +56,7 @@ object Editor extends LilaController {
|
|||
OptionResult(GameRepo game id) { game =>
|
||||
Redirect {
|
||||
if (game.playable) routes.Round.watcher(game.id, "white")
|
||||
else routes.Editor.load(get("fen") | (chess.format.Forsyth >> game.toChess))
|
||||
else routes.Editor.load(get("fen") | (chess.format.Forsyth >> game.chess))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -265,7 +265,7 @@ object Round extends LilaController with TheftPrevention {
|
|||
OptionResult(GameRepo game id) { game =>
|
||||
Redirect("%s?fen=%s#%s".format(
|
||||
routes.Lobby.home(),
|
||||
get("fen") | (chess.format.Forsyth >> game.toChess),
|
||||
get("fen") | (chess.format.Forsyth >> game.chess),
|
||||
mode
|
||||
))
|
||||
}
|
||||
|
|
|
@ -49,14 +49,13 @@ object UserAnalysis extends LilaController with TheftPrevention {
|
|||
|
||||
private[controllers] def makePov(from: SituationPlus): Pov = Pov(
|
||||
lila.game.Game.make(
|
||||
game = chess.Game(
|
||||
chess = chess.Game(
|
||||
situation = from.situation,
|
||||
turns = from.turns
|
||||
),
|
||||
whitePlayer = lila.game.Player.white,
|
||||
blackPlayer = lila.game.Player.black,
|
||||
mode = chess.Mode.Casual,
|
||||
variant = from.situation.board.variant,
|
||||
source = lila.game.Source.Api,
|
||||
pgnImport = None
|
||||
).copy(id = "synthetic"),
|
||||
|
|
|
@ -29,7 +29,7 @@ trait ChessgroundHelper {
|
|||
}
|
||||
|
||||
def chessground(pov: Pov)(implicit ctx: Context): Html = chessground(
|
||||
board = pov.game.toChess.board,
|
||||
board = pov.game.board,
|
||||
orient = pov.color,
|
||||
lastMove = pov.game.history.lastMove.map(_.origDest) ?? {
|
||||
case (orig, dest) => List(orig, dest)
|
||||
|
|
|
@ -61,7 +61,7 @@ trait GameHelper { self: I18nHelper with UserHelper with AiHelper with StringHel
|
|||
}
|
||||
case _ => "Game is still being played"
|
||||
}
|
||||
val moves = s"${game.toChess.fullMoveNumber} moves"
|
||||
val moves = s"${game.chess.fullMoveNumber} moves"
|
||||
s"$p1 plays $p2 in a $mode $speedAndClock game of $variant. $result after $moves. Click to replay, analyse, and discuss the game!"
|
||||
}
|
||||
|
||||
|
@ -218,7 +218,7 @@ trait GameHelper { self: I18nHelper with UserHelper with AiHelper with StringHel
|
|||
val title = withTitle ?? s"""title="${gameTitle(game, pov.color)}""""
|
||||
val cssClass = isLive ?? ("live live_" + game.id)
|
||||
val live = isLive ?? game.id
|
||||
val fen = Forsyth exportBoard game.toChess.board
|
||||
val fen = Forsyth exportBoard game.board
|
||||
val lastMove = ~game.lastMoveKeys
|
||||
val variant = game.variant.key
|
||||
val tag = if (withLink) "a" else "span"
|
||||
|
@ -235,7 +235,7 @@ trait GameHelper { self: I18nHelper with UserHelper with AiHelper with StringHel
|
|||
isLive ?? ("live live_" + pov.game.id),
|
||||
isLive ?? pov.game.id,
|
||||
pov.color.name,
|
||||
Forsyth exportBoard pov.game.toChess.board,
|
||||
Forsyth exportBoard pov.game.board,
|
||||
~pov.game.lastMoveKeys,
|
||||
blank ?? """ target="_blank""""
|
||||
)
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<dt>PGN</dt>
|
||||
<dd>@Html(pov.game.pgnMoves.mkString("<br />"))</dd>
|
||||
<dt>FEN</dt>
|
||||
<dd>@{chess.format.Forsyth.>>(pov.game.toChess)}</dd>
|
||||
<dd>@{chess.format.Forsyth.>>(pov.game.chess)}</dd>
|
||||
@if(playing) {
|
||||
<dt>Your color</dt>
|
||||
<dd>@pov.color.name</dd>
|
||||
|
|
|
@ -23,7 +23,7 @@ object Accuracy {
|
|||
implicit def povToPovLike(pov: Pov): PovLike = PovLike(
|
||||
color = pov.color,
|
||||
startColor = pov.game.startColor,
|
||||
startedAtTurn = pov.game.startedAtTurn
|
||||
startedAtTurn = pov.game.chess.startedAtTurn
|
||||
)
|
||||
|
||||
def diffsList(pov: PovLike, analysis: Analysis): List[Int] =
|
||||
|
|
|
@ -38,7 +38,7 @@ final class LobbyApi(
|
|||
def nowPlaying(pov: Pov) = Json.obj(
|
||||
"fullId" -> pov.fullId,
|
||||
"gameId" -> pov.gameId,
|
||||
"fen" -> (chess.format.Forsyth exportBoard pov.game.toChess.board),
|
||||
"fen" -> (chess.format.Forsyth exportBoard pov.game.board),
|
||||
"color" -> pov.color.name,
|
||||
"lastMove" -> ~pov.game.lastMoveKeys,
|
||||
"variant" -> Json.obj(
|
||||
|
|
|
@ -44,7 +44,7 @@ final class UserGameApi(
|
|||
.add("rating" -> p.rating)
|
||||
.add("ratingDiff" -> p.ratingDiff)
|
||||
}),
|
||||
"fen" -> Forsyth.exportBoard(g.toChess.board),
|
||||
"fen" -> Forsyth.exportBoard(g.board),
|
||||
"winner" -> g.winnerColor.map(_.name),
|
||||
"bookmarks" -> g.bookmarks
|
||||
).add("bookmarked" -> bookmarked)
|
||||
|
|
|
@ -36,20 +36,25 @@ private[challenge] final class Joiner(onStart: String => Unit) {
|
|||
}
|
||||
}
|
||||
val game = Game.make(
|
||||
game = chessGame,
|
||||
chess = chessGame,
|
||||
whitePlayer = makePlayer(chess.White, c.finalColor.fold(challengerUser, destUser)),
|
||||
blackPlayer = makePlayer(chess.Black, c.finalColor.fold(destUser, challengerUser)),
|
||||
mode = (realVariant == chess.variant.FromPosition).fold(Mode.Casual, c.mode),
|
||||
variant = realVariant,
|
||||
source = (realVariant == chess.variant.FromPosition).fold(Source.Position, Source.Friend),
|
||||
mode = realVariant.fromPosition.fold(Mode.Casual, c.mode),
|
||||
source = realVariant.fromPosition.fold(Source.Position, Source.Friend),
|
||||
daysPerTurn = c.daysPerTurn,
|
||||
pgnImport = None
|
||||
).copy(id = c.id).|> { g =>
|
||||
state.fold(g) {
|
||||
case sit @ SituationPlus(Situation(board, _), _) => g.copy(
|
||||
variant = chess.variant.FromPosition,
|
||||
history = board.history,
|
||||
turns = sit.turns
|
||||
chess = g.chess.copy(
|
||||
situation = g.situation.copy(
|
||||
board = g.board.copy(
|
||||
history = board.history,
|
||||
variant = chess.variant.FromPosition
|
||||
)
|
||||
),
|
||||
turns = sit.turns
|
||||
)
|
||||
)
|
||||
}
|
||||
}.start
|
||||
|
|
|
@ -97,7 +97,7 @@ final class Analyser(
|
|||
variant = game.variant,
|
||||
moves = moves take maxPlies mkString " "
|
||||
),
|
||||
startPly = game.startedAtTurn,
|
||||
startPly = game.chess.startedAtTurn,
|
||||
sender = sender
|
||||
)
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ final class Player(
|
|||
}
|
||||
|
||||
private def makeWork(game: Game, level: Int): Fu[Work.Move] =
|
||||
if (game.toChess.situation playable true)
|
||||
if (game.situation playable true)
|
||||
if (game.turns <= maxPlies) GameRepo.initialFen(game) zip uciMemo.get(game) map {
|
||||
case (initialFen, moves) => Work.Move(
|
||||
_id = Work.makeId,
|
||||
|
@ -31,7 +31,7 @@ final class Player(
|
|||
variant = game.variant,
|
||||
moves = moves mkString " "
|
||||
),
|
||||
currentFen = FEN(Forsyth >> game.toChess),
|
||||
currentFen = FEN(Forsyth >> game.chess),
|
||||
level = level,
|
||||
clock = game.clock.map { clk =>
|
||||
Work.Clock(
|
||||
|
|
|
@ -4,8 +4,8 @@ import org.joda.time.DateTime
|
|||
import reactivemongo.bson._
|
||||
import scala.collection.breakOut
|
||||
|
||||
import chess.variant.{ Variant, Crazyhouse, ThreeCheck }
|
||||
import chess.{ CheckCount, Color, Clock, White, Black, Status, Mode, UnmovedRooks, History => ChessHistory }
|
||||
import chess.variant.{ Variant, Crazyhouse }
|
||||
import chess.{ CheckCount, Color, Clock, White, Black, Status, Mode, UnmovedRooks, History => ChessHistory, Game => ChessGame }
|
||||
|
||||
import lila.db.BSON
|
||||
import lila.db.dsl._
|
||||
|
@ -60,132 +60,146 @@ object BSONHandlers {
|
|||
|
||||
implicit val gameBSONHandler: BSON[Game] = new BSON[Game] {
|
||||
|
||||
import Game.BSONFields._
|
||||
import Game.{ BSONFields => F }
|
||||
import PgnImport.pgnImportBSONHandler
|
||||
import Player.playerBSONHandler
|
||||
|
||||
private val emptyPlayerBuilder = playerBSONHandler.read(BSONDocument())
|
||||
|
||||
def reads(r: BSON.Reader): Game = {
|
||||
val winC = r boolO winnerColor map Color.apply
|
||||
val (whiteId, blackId) = r str playerIds splitAt 4
|
||||
val uids = ~r.getO[List[String]](playerUids)
|
||||
val (whiteUid, blackUid) = (uids.headOption.filter(_.nonEmpty), uids.lift(1).filter(_.nonEmpty))
|
||||
def player(field: String, color: Color, id: Player.Id, uid: Player.UserId): Player = {
|
||||
val builder = r.getO[Player.Builder](field)(playerBSONHandler) | emptyPlayerBuilder
|
||||
val win = winC map (_ == color)
|
||||
builder(color)(id)(uid)(win)
|
||||
}
|
||||
val gameVariant = Variant(r intD variant) | chess.variant.Standard
|
||||
val plies = r int turns
|
||||
|
||||
val decoded = r.bytesO(huffmanPgn).map { PgnStorage.Huffman.decode(_, plies) } | {
|
||||
val clm = r.get[CastleLastMove](castleLastMove)
|
||||
val gameVariant = Variant(r intD F.variant) | chess.variant.Standard
|
||||
val plies = r int F.turns
|
||||
val turnColor = Color.fromPly(plies)
|
||||
|
||||
val decoded = r.bytesO(F.huffmanPgn).map { PgnStorage.Huffman.decode(_, plies) } | {
|
||||
val clm = r.get[CastleLastMove](F.castleLastMove)
|
||||
PgnStorage.Decoded(
|
||||
pgnMoves = PgnStorage.OldBin.decode(r bytesD oldPgn, plies),
|
||||
pieces = BinaryFormat.piece.read(r bytes binaryPieces, gameVariant),
|
||||
positionHashes = r.getO[chess.PositionHash](positionHashes) | Array.empty,
|
||||
unmovedRooks = r.getO[UnmovedRooks](unmovedRooks) | UnmovedRooks.default,
|
||||
pgnMoves = PgnStorage.OldBin.decode(r bytesD F.oldPgn, plies),
|
||||
pieces = BinaryFormat.piece.read(r bytes F.binaryPieces, gameVariant),
|
||||
positionHashes = r.getO[chess.PositionHash](F.positionHashes) | Array.empty,
|
||||
unmovedRooks = r.getO[UnmovedRooks](F.unmovedRooks) | UnmovedRooks.default,
|
||||
lastMove = clm.lastMove,
|
||||
castles = clm.castles,
|
||||
format = PgnStorage.OldBin
|
||||
)
|
||||
}
|
||||
|
||||
val g = Game(
|
||||
id = r str id,
|
||||
whitePlayer = player(whitePlayer, White, whiteId, whiteUid),
|
||||
blackPlayer = player(blackPlayer, Black, blackId, blackUid),
|
||||
pgnMoves = decoded.pgnMoves,
|
||||
pieces = decoded.pieces,
|
||||
history = ChessHistory(
|
||||
lastMove = decoded.lastMove,
|
||||
castles = decoded.castles,
|
||||
positionHashes = decoded.positionHashes,
|
||||
unmovedRooks = decoded.unmovedRooks,
|
||||
checkCount = if (gameVariant == ThreeCheck) {
|
||||
val counts = r.intsD(checkCount)
|
||||
CheckCount(~counts.headOption, ~counts.lastOption)
|
||||
} else Game.emptyCheckCount
|
||||
val winC = r boolO F.winnerColor map Color.apply
|
||||
val uids = ~r.getO[List[String]](F.playerUids)
|
||||
val (whiteUid, blackUid) = (uids.headOption.filter(_.nonEmpty), uids.lift(1).filter(_.nonEmpty))
|
||||
def makePlayer(field: String, color: Color, id: Player.Id, uid: Player.UserId): Player = {
|
||||
val builder = r.getO[Player.Builder](field)(playerBSONHandler) | emptyPlayerBuilder
|
||||
val win = winC map (_ == color)
|
||||
builder(color)(id)(uid)(win)
|
||||
}
|
||||
val (whiteId, blackId) = r str F.playerIds splitAt 4
|
||||
val wPlayer = makePlayer(F.whitePlayer, White, whiteId, whiteUid)
|
||||
val bPlayer = makePlayer(F.blackPlayer, Black, blackId, blackUid)
|
||||
|
||||
val createdAt = r date F.createdAt
|
||||
val status = r.get[Status](F.status)
|
||||
|
||||
val chessGame = ChessGame(
|
||||
situation = chess.Situation(
|
||||
chess.Board(
|
||||
pieces = decoded.pieces,
|
||||
history = ChessHistory(
|
||||
lastMove = decoded.lastMove,
|
||||
castles = decoded.castles,
|
||||
positionHashes = decoded.positionHashes,
|
||||
unmovedRooks = decoded.unmovedRooks,
|
||||
checkCount = if (gameVariant.threeCheck) {
|
||||
val counts = r.intsD(F.checkCount)
|
||||
CheckCount(~counts.headOption, ~counts.lastOption)
|
||||
} else Game.emptyCheckCount
|
||||
),
|
||||
variant = gameVariant,
|
||||
crazyData = gameVariant.crazyhouse option r.get[Crazyhouse.Data](F.crazyData)
|
||||
),
|
||||
color = turnColor
|
||||
),
|
||||
pgnStorage = decoded.format,
|
||||
status = r.get[Status](status),
|
||||
pgnMoves = decoded.pgnMoves,
|
||||
clock = r.getO[Color => Clock](F.clock) {
|
||||
clockBSONReader(createdAt, wPlayer.berserk, bPlayer.berserk)
|
||||
} map (_(turnColor)),
|
||||
turns = plies,
|
||||
startedAtTurn = r intD startedAtTurn,
|
||||
daysPerTurn = r intO daysPerTurn,
|
||||
binaryMoveTimes = r bytesO moveTimes,
|
||||
mode = Mode(r boolD rated),
|
||||
variant = gameVariant,
|
||||
next = r strO next,
|
||||
bookmarks = r intD bookmarks,
|
||||
createdAt = r date createdAt,
|
||||
movedAt = r.dateD(movedAt, r date createdAt),
|
||||
metadata = Metadata(
|
||||
source = r intO source flatMap Source.apply,
|
||||
pgnImport = r.getO[PgnImport](pgnImport)(PgnImport.pgnImportBSONHandler),
|
||||
tournamentId = r strO tournamentId,
|
||||
simulId = r strO simulId,
|
||||
tvAt = r dateO tvAt,
|
||||
analysed = r boolD analysed
|
||||
)
|
||||
startedAtTurn = r intD F.startedAtTurn
|
||||
)
|
||||
|
||||
val gameClock = r.getO[Color => Clock](clock)(clockBSONReader(g.createdAt, g.whitePlayer.berserk, g.blackPlayer.berserk)) map (_(g.turnColor))
|
||||
|
||||
g.copy(
|
||||
clock = gameClock,
|
||||
crazyData = (g.variant == Crazyhouse) option r.get[Crazyhouse.Data](crazyData),
|
||||
Game(
|
||||
id = r str F.id,
|
||||
whitePlayer = wPlayer,
|
||||
blackPlayer = bPlayer,
|
||||
chess = chessGame,
|
||||
pgnStorage = decoded.format,
|
||||
status = status,
|
||||
daysPerTurn = r intO F.daysPerTurn,
|
||||
binaryMoveTimes = r bytesO F.moveTimes,
|
||||
clockHistory = for {
|
||||
clk <- gameClock
|
||||
bw <- r bytesO whiteClockHistory
|
||||
bb <- r bytesO blackClockHistory
|
||||
history <- BinaryFormat.clockHistory.read(clk.limit, bw, bb, g.flagged, g.id)
|
||||
} yield history
|
||||
clk <- chessGame.clock
|
||||
bw <- r bytesO F.whiteClockHistory
|
||||
bb <- r bytesO F.blackClockHistory
|
||||
history <- BinaryFormat.clockHistory.read(clk.limit, bw, bb, (status == Status.Outoftime).option(turnColor))
|
||||
} yield history,
|
||||
mode = Mode(r boolD F.rated),
|
||||
next = r strO F.next,
|
||||
bookmarks = r intD F.bookmarks,
|
||||
createdAt = createdAt,
|
||||
movedAt = r.dateD(F.movedAt, createdAt),
|
||||
metadata = Metadata(
|
||||
source = r intO F.source flatMap Source.apply,
|
||||
pgnImport = r.getO[PgnImport](F.pgnImport)(PgnImport.pgnImportBSONHandler),
|
||||
tournamentId = r strO F.tournamentId,
|
||||
simulId = r strO F.simulId,
|
||||
tvAt = r dateO F.tvAt,
|
||||
analysed = r boolD F.analysed
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
def writes(w: BSON.Writer, o: Game) = BSONDocument(
|
||||
id -> o.id,
|
||||
playerIds -> (o.whitePlayer.id + o.blackPlayer.id),
|
||||
playerUids -> w.strListO(List(~o.whitePlayer.userId, ~o.blackPlayer.userId)),
|
||||
whitePlayer -> w.docO(playerBSONHandler write ((_: Color) => (_: Player.Id) => (_: Player.UserId) => (_: Player.Win) => o.whitePlayer)),
|
||||
blackPlayer -> w.docO(playerBSONHandler write ((_: Color) => (_: Player.Id) => (_: Player.UserId) => (_: Player.Win) => o.blackPlayer)),
|
||||
status -> o.status,
|
||||
turns -> o.turns,
|
||||
startedAtTurn -> w.intO(o.startedAtTurn),
|
||||
clock -> (o.clock map { c => clockBSONWrite(o.createdAt, c) }),
|
||||
checkCount -> o.history.checkCount.nonEmpty.option(o.history.checkCount),
|
||||
daysPerTurn -> o.daysPerTurn,
|
||||
moveTimes -> o.binaryMoveTimes,
|
||||
whiteClockHistory -> clockHistory(White, o.clockHistory, o.clock, o.flagged),
|
||||
blackClockHistory -> clockHistory(Black, o.clockHistory, o.clock, o.flagged),
|
||||
rated -> w.boolO(o.mode.rated),
|
||||
variant -> o.variant.exotic.option(o.variant.id).map(w.int),
|
||||
crazyData -> o.crazyData,
|
||||
next -> o.next,
|
||||
bookmarks -> w.intO(o.bookmarks),
|
||||
createdAt -> w.date(o.createdAt),
|
||||
movedAt -> w.date(o.movedAt),
|
||||
source -> o.metadata.source.map(_.id),
|
||||
pgnImport -> o.metadata.pgnImport,
|
||||
tournamentId -> o.metadata.tournamentId,
|
||||
simulId -> o.metadata.simulId,
|
||||
tvAt -> o.metadata.tvAt.map(w.date),
|
||||
analysed -> w.boolO(o.metadata.analysed)
|
||||
F.id -> o.id,
|
||||
F.playerIds -> (o.whitePlayer.id + o.blackPlayer.id),
|
||||
F.playerUids -> w.strListO(List(~o.whitePlayer.userId, ~o.blackPlayer.userId)),
|
||||
F.whitePlayer -> w.docO(playerBSONHandler write ((_: Color) => (_: Player.Id) => (_: Player.UserId) => (_: Player.Win) => o.whitePlayer)),
|
||||
F.blackPlayer -> w.docO(playerBSONHandler write ((_: Color) => (_: Player.Id) => (_: Player.UserId) => (_: Player.Win) => o.blackPlayer)),
|
||||
F.status -> o.status,
|
||||
F.turns -> o.chess.turns,
|
||||
F.startedAtTurn -> w.intO(o.chess.startedAtTurn),
|
||||
F.clock -> (o.chess.clock map { c => clockBSONWrite(o.createdAt, c) }),
|
||||
F.checkCount -> o.history.checkCount.nonEmpty.option(o.history.checkCount),
|
||||
F.daysPerTurn -> o.daysPerTurn,
|
||||
F.moveTimes -> o.binaryMoveTimes,
|
||||
F.whiteClockHistory -> clockHistory(White, o.clockHistory, o.chess.clock, o.flagged),
|
||||
F.blackClockHistory -> clockHistory(Black, o.clockHistory, o.chess.clock, o.flagged),
|
||||
F.rated -> w.boolO(o.mode.rated),
|
||||
F.variant -> o.board.variant.exotic.option(w int o.board.variant.id),
|
||||
F.crazyData -> o.board.crazyData,
|
||||
F.next -> o.next,
|
||||
F.bookmarks -> w.intO(o.bookmarks),
|
||||
F.createdAt -> w.date(o.createdAt),
|
||||
F.movedAt -> w.date(o.movedAt),
|
||||
F.source -> o.metadata.source.map(_.id),
|
||||
F.pgnImport -> o.metadata.pgnImport,
|
||||
F.tournamentId -> o.metadata.tournamentId,
|
||||
F.simulId -> o.metadata.simulId,
|
||||
F.tvAt -> o.metadata.tvAt.map(w.date),
|
||||
F.analysed -> w.boolO(o.metadata.analysed)
|
||||
) ++ {
|
||||
o.pgnStorage match {
|
||||
case f @ PgnStorage.OldBin => $doc(
|
||||
oldPgn -> f.encode(o.pgnMoves),
|
||||
binaryPieces -> BinaryFormat.piece.write(o.pieces),
|
||||
positionHashes -> o.history.positionHashes,
|
||||
unmovedRooks -> o.history.unmovedRooks,
|
||||
castleLastMove -> CastleLastMove.castleLastMoveBSONHandler.write(CastleLastMove(
|
||||
F.oldPgn -> f.encode(o.pgnMoves),
|
||||
F.binaryPieces -> BinaryFormat.piece.write(o.board.pieces),
|
||||
F.positionHashes -> o.history.positionHashes,
|
||||
F.unmovedRooks -> o.history.unmovedRooks,
|
||||
F.castleLastMove -> CastleLastMove.castleLastMoveBSONHandler.write(CastleLastMove(
|
||||
castles = o.history.castles,
|
||||
lastMove = o.history.lastMove
|
||||
))
|
||||
)
|
||||
case f @ PgnStorage.Huffman => $doc(
|
||||
huffmanPgn -> f.encode(o.pgnMoves)
|
||||
F.huffmanPgn -> f.encode(o.pgnMoves)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,13 +42,13 @@ object BinaryFormat {
|
|||
if (flagged) decoded :+ Centis(0) else decoded
|
||||
}
|
||||
|
||||
def read(start: Centis, bw: ByteArray, bb: ByteArray, flagged: Option[Color], gameId: String) = Try {
|
||||
def read(start: Centis, bw: ByteArray, bb: ByteArray, flagged: Option[Color]) = Try {
|
||||
ClockHistory(
|
||||
readSide(start, bw, flagged has White),
|
||||
readSide(start, bb, flagged has Black)
|
||||
)
|
||||
}.fold(
|
||||
e => { logger.warn(s"Exception decoding history on game $gameId", e); none },
|
||||
e => { logger.warn(s"Exception decoding history", e); none },
|
||||
some
|
||||
)
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@ package lila.game
|
|||
import chess.Color.{ White, Black }
|
||||
import chess.format.{ Uci, FEN }
|
||||
import chess.opening.{ FullOpening, FullOpeningDB }
|
||||
import chess.variant.{ Variant, Crazyhouse }
|
||||
import chess.{ PieceMap, MoveMetrics, History => ChessHistory, CheckCount, Castles, Board, MoveOrDrop, Pos, Game => ChessGame, Clock, Status, Color, Mode, PositionHash, UnmovedRooks, Centis, Situation }
|
||||
import chess.variant.{ Variant, Standard }
|
||||
import chess.{ Speed, PieceMap, MoveMetrics, History => ChessHistory, CheckCount, Castles, Board, MoveOrDrop, Pos, Game => ChessGame, Clock, Status, Color, Mode, PositionHash, UnmovedRooks, Centis, Situation }
|
||||
import org.joda.time.DateTime
|
||||
|
||||
import lila.common.Sequence
|
||||
|
@ -16,20 +16,13 @@ case class Game(
|
|||
id: String,
|
||||
whitePlayer: Player,
|
||||
blackPlayer: Player,
|
||||
pgnMoves: PgnMoves,
|
||||
pieces: PieceMap,
|
||||
history: ChessHistory,
|
||||
chess: ChessGame,
|
||||
pgnStorage: PgnStorage,
|
||||
status: Status,
|
||||
turns: Int, // = ply
|
||||
startedAtTurn: Int,
|
||||
clock: Option[Clock] = None,
|
||||
daysPerTurn: Option[Int],
|
||||
binaryMoveTimes: Option[ByteArray] = None,
|
||||
clockHistory: Option[ClockHistory] = Option(ClockHistory()),
|
||||
mode: Mode = Mode.default,
|
||||
variant: Variant = Variant.default,
|
||||
crazyData: Option[Crazyhouse.Data] = None,
|
||||
next: Option[String] = None,
|
||||
bookmarks: Int = 0,
|
||||
createdAt: DateTime = DateTime.now,
|
||||
|
@ -37,6 +30,14 @@ case class Game(
|
|||
metadata: Metadata
|
||||
) {
|
||||
|
||||
def situation = chess.situation
|
||||
def board = chess.situation.board
|
||||
def history = chess.situation.board.history
|
||||
def variant = chess.situation.board.variant
|
||||
def turns = chess.turns
|
||||
def clock = chess.clock
|
||||
def pgnMoves = chess.pgnMoves
|
||||
|
||||
val players = List(whitePlayer, blackPlayer)
|
||||
|
||||
def player(color: Color): Player = color match {
|
||||
|
@ -74,7 +75,7 @@ case class Game(
|
|||
def turnOf(c: Color): Boolean = c == turnColor
|
||||
def turnOf(u: User): Boolean = player(u) ?? turnOf
|
||||
|
||||
def playedTurns = turns - startedAtTurn
|
||||
def playedTurns = turns - chess.startedAtTurn
|
||||
|
||||
def flagged = (status == Status.Outoftime).option(turnColor)
|
||||
|
||||
|
@ -154,17 +155,6 @@ case class Game(
|
|||
}
|
||||
}
|
||||
|
||||
lazy val toChess: ChessGame = ChessGame(
|
||||
situation = Situation(
|
||||
Board(pieces, history, variant, crazyData),
|
||||
Color.fromPly(turns)
|
||||
),
|
||||
pgnMoves = pgnMoves,
|
||||
clock = clock,
|
||||
turns = turns,
|
||||
startedAtTurn = startedAtTurn
|
||||
)
|
||||
|
||||
def update(
|
||||
game: ChessGame,
|
||||
moveOrDrop: MoveOrDrop,
|
||||
|
@ -182,12 +172,8 @@ case class Game(
|
|||
val updated = copy(
|
||||
whitePlayer = copyPlayer(whitePlayer),
|
||||
blackPlayer = copyPlayer(blackPlayer),
|
||||
pgnMoves = game.pgnMoves,
|
||||
pieces = game.board.pieces,
|
||||
history = game.board.history,
|
||||
turns = game.turns,
|
||||
crazyData = game.situation.board.crazyData,
|
||||
binaryMoveTimes = (!isPgnImport && !clock.isDefined).option {
|
||||
chess = game,
|
||||
binaryMoveTimes = (!isPgnImport && !chess.clock.isDefined).option {
|
||||
BinaryFormat.moveTime.write {
|
||||
binaryMoveTimes.?? { t =>
|
||||
BinaryFormat.moveTime.read(t, playedTurns)
|
||||
|
@ -199,7 +185,6 @@ case class Game(
|
|||
ch <- clockHistory
|
||||
} yield ch.record(turnColor, clk),
|
||||
status = game.situation.status | status,
|
||||
clock = game.clock,
|
||||
movedAt = DateTime.now
|
||||
)
|
||||
|
||||
|
@ -212,17 +197,17 @@ case class Game(
|
|||
blackOffersDraw = blackPlayer.isOfferingDraw
|
||||
)
|
||||
|
||||
val clockEvent = updated.clock map Event.Clock.apply orElse {
|
||||
val clockEvent = updated.chess.clock map Event.Clock.apply orElse {
|
||||
updated.playableCorrespondenceClock map Event.CorrespondenceClock.apply
|
||||
}
|
||||
|
||||
val events = moveOrDrop.fold(
|
||||
Event.Move(_, game.situation, state, clockEvent, updated.crazyData),
|
||||
Event.Drop(_, game.situation, state, clockEvent, updated.crazyData)
|
||||
Event.Move(_, game.situation, state, clockEvent, updated.board.crazyData),
|
||||
Event.Drop(_, game.situation, state, clockEvent, updated.board.crazyData)
|
||||
) ::
|
||||
{
|
||||
// abstraction leak, I know.
|
||||
(updated.variant.threeCheck && game.situation.check) ?? List(Event.CheckCount(
|
||||
(updated.board.variant.threeCheck && game.situation.check) ?? List(Event.CheckCount(
|
||||
white = updated.history.checkCount.white,
|
||||
black = updated.history.checkCount.black
|
||||
))
|
||||
|
@ -231,8 +216,6 @@ case class Game(
|
|||
Progress(this, updated, events)
|
||||
}
|
||||
|
||||
def check = toChess.situation.checkSquare
|
||||
|
||||
def lastMoveKeys: Option[String] = history.lastMove map {
|
||||
case Uci.Drop(target, _) => s"$target$target"
|
||||
case m: Uci.Move => m.keys
|
||||
|
@ -266,7 +249,7 @@ case class Game(
|
|||
def playableCorrespondenceClock: Option[CorrespondenceClock] =
|
||||
playable ?? correspondenceClock
|
||||
|
||||
def speed = chess.Speed(clock.map(_.config))
|
||||
def speed = Speed(chess.clock.map(_.config))
|
||||
|
||||
def perfKey = PerfPicker.key(this)
|
||||
def perfType = PerfType(perfKey)
|
||||
|
@ -343,7 +326,7 @@ case class Game(
|
|||
clock.ifTrue(berserkable && !player(color).berserk).map { c =>
|
||||
val newClock = c goBerserk color
|
||||
Progress(this, copy(
|
||||
clock = Some(newClock),
|
||||
chess = chess.copy(clock = Some(newClock)),
|
||||
clockHistory = clockHistory.map(history => {
|
||||
if (history(color).isEmpty) history
|
||||
else history.reset(color).record(color, newClock)
|
||||
|
@ -367,7 +350,7 @@ case class Game(
|
|||
status = status,
|
||||
whitePlayer = whitePlayer.finish(winner contains White),
|
||||
blackPlayer = blackPlayer.finish(winner contains Black),
|
||||
clock = newClock,
|
||||
chess = chess.copy(clock = newClock),
|
||||
clockHistory = for {
|
||||
clk <- clock
|
||||
history <- clockHistory
|
||||
|
@ -404,10 +387,10 @@ case class Game(
|
|||
!Game.isOldHorde(this)
|
||||
|
||||
def ratingVariant =
|
||||
if (isTournament && variant == chess.variant.FromPosition) chess.variant.Standard
|
||||
if (isTournament && variant.fromPosition) Standard
|
||||
else variant
|
||||
|
||||
def fromPosition = variant == chess.variant.FromPosition || source.??(Source.Position==)
|
||||
def fromPosition = variant.fromPosition || source.??(Source.Position==)
|
||||
|
||||
def imported = source contains Source.Import
|
||||
|
||||
|
@ -443,7 +426,7 @@ case class Game(
|
|||
private def outoftimeCorrespondence: Boolean =
|
||||
playableCorrespondenceClock ?? { _ outoftime turnColor }
|
||||
|
||||
def isCorrespondence = speed == chess.Speed.Correspondence
|
||||
def isCorrespondence = speed == Speed.Correspondence
|
||||
|
||||
def isSwitchable = nonAi && (isCorrespondence || isSimul)
|
||||
|
||||
|
@ -455,7 +438,7 @@ case class Game(
|
|||
|
||||
def isClockRunning = clock ?? (_.isRunning)
|
||||
|
||||
def withClock(c: Clock) = Progress(this, copy(clock = Some(c)))
|
||||
def withClock(c: Clock) = Progress(this, copy(chess = chess.copy(clock = Some(c))))
|
||||
|
||||
def correspondenceGiveTime = Progress(this, copy(movedAt = DateTime.now))
|
||||
|
||||
|
@ -465,7 +448,7 @@ case class Game(
|
|||
correspondenceClock.map(_.estimateTotalTime) getOrElse 1200
|
||||
|
||||
def timeForFirstMove: Centis = Centis ofSeconds {
|
||||
import chess.Speed._
|
||||
import Speed._
|
||||
val base = if (isTournament) speed match {
|
||||
case UltraBullet => 11
|
||||
case Bullet => 16
|
||||
|
@ -480,7 +463,7 @@ case class Game(
|
|||
case Rapid => 30
|
||||
case _ => 35
|
||||
}
|
||||
if (variant == chess.variant.Chess960) (base * 2) atMost 90
|
||||
if (variant.chess960) (base * 2) atMost 90
|
||||
else base
|
||||
}
|
||||
|
||||
|
@ -500,7 +483,7 @@ case class Game(
|
|||
def onePlayerHasMoved = playedTurns > 0
|
||||
def bothPlayersHaveMoved = playedTurns > 1
|
||||
|
||||
def startColor = Color(startedAtTurn % 2 == 0)
|
||||
def startColor = Color(chess.startedAtTurn % 2 == 0)
|
||||
|
||||
def playerMoves(color: Color): Int =
|
||||
if (color == startColor) (playedTurns + 1) / 2
|
||||
|
@ -551,7 +534,9 @@ case class Game(
|
|||
def pgnImport = metadata.pgnImport
|
||||
def isPgnImport = pgnImport.isDefined
|
||||
|
||||
def resetTurns = copy(turns = 0, startedAtTurn = 0)
|
||||
def resetTurns = copy(
|
||||
chess = chess.copy(turns = 0, startedAtTurn = 0)
|
||||
)
|
||||
|
||||
lazy val opening: Option[FullOpening.AtPly] =
|
||||
if (fromPosition || !Variant.openingSensibleVariants(variant)) none
|
||||
|
@ -632,11 +617,10 @@ object Game {
|
|||
private[game] val emptyCheckCount = CheckCount(0, 0)
|
||||
|
||||
def make(
|
||||
game: ChessGame,
|
||||
chess: ChessGame,
|
||||
whitePlayer: Player,
|
||||
blackPlayer: Player,
|
||||
mode: Mode,
|
||||
variant: Variant,
|
||||
source: Source,
|
||||
pgnImport: Option[PgnImport],
|
||||
daysPerTurn: Option[Int] = None
|
||||
|
@ -646,24 +630,11 @@ object Game {
|
|||
id = IdGenerator.game,
|
||||
whitePlayer = whitePlayer,
|
||||
blackPlayer = blackPlayer,
|
||||
pgnMoves = Vector.empty,
|
||||
pieces = game.board.pieces,
|
||||
history = ChessHistory(
|
||||
lastMove = none,
|
||||
castles = game.board.history.castles,
|
||||
positionHashes = game.board.history.positionHashes,
|
||||
checkCount = emptyCheckCount,
|
||||
unmovedRooks = game.board.unmovedRooks
|
||||
),
|
||||
pgnStorage = PgnStorage(variant, List(whitePlayer.userId, blackPlayer.userId).flatten),
|
||||
chess = chess,
|
||||
pgnStorage = PgnStorage(chess.situation.board.variant, List(whitePlayer.userId, blackPlayer.userId).flatten),
|
||||
status = Status.Created,
|
||||
turns = game.turns,
|
||||
startedAtTurn = game.startedAtTurn,
|
||||
clock = game.clock,
|
||||
daysPerTurn = daysPerTurn,
|
||||
mode = mode,
|
||||
variant = variant,
|
||||
crazyData = game.board.crazyData,
|
||||
metadata = Metadata(
|
||||
source = source.some,
|
||||
pgnImport = pgnImport,
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package lila.game
|
||||
|
||||
import chess.variant.{ Crazyhouse, ThreeCheck }
|
||||
import chess.{ Color, White, Black, Clock, CheckCount, UnmovedRooks }
|
||||
import Game.BSONFields._
|
||||
import reactivemongo.bson._
|
||||
|
@ -59,15 +58,15 @@ private[game] object GameDiff {
|
|||
a.pgnStorage match {
|
||||
case f @ PgnStorage.OldBin =>
|
||||
d(oldPgn, _.pgnMoves, writeBytes compose f.encode)
|
||||
d(binaryPieces, _.pieces, writeBytes compose BinaryFormat.piece.write)
|
||||
d(binaryPieces, _.board.pieces, writeBytes compose BinaryFormat.piece.write)
|
||||
d(positionHashes, _.history.positionHashes, w.bytes)
|
||||
d(unmovedRooks, _.history.unmovedRooks, writeBytes compose BinaryFormat.unmovedRooks.write)
|
||||
d(castleLastMove, makeCastleLastMove, CastleLastMove.castleLastMoveBSONHandler.write)
|
||||
// since variants are always OldBin
|
||||
if (a.variant == ThreeCheck)
|
||||
if (a.variant.threeCheck)
|
||||
dOpt(checkCount, _.history.checkCount, (o: CheckCount) => o.nonEmpty option { BSONHandlers.checkCountWriter write o })
|
||||
if (a.variant == Crazyhouse)
|
||||
dOpt(crazyData, _.crazyData, (o: Option[Crazyhouse.Data]) => o map BSONHandlers.crazyhouseDataBSONHandler.write)
|
||||
if (a.variant.crazyhouse)
|
||||
dOpt(crazyData, _.board.crazyData, (o: Option[chess.variant.Crazyhouse.Data]) => o map BSONHandlers.crazyhouseDataBSONHandler.write)
|
||||
case f @ PgnStorage.Huffman =>
|
||||
d(huffmanPgn, _.pgnMoves, writeBytes compose f.encode)
|
||||
}
|
||||
|
|
|
@ -274,7 +274,7 @@ object GameRepo {
|
|||
val userIds = g2.userIds.distinct
|
||||
val fen = initialFen.map(_.value) orElse {
|
||||
(!g2.variant.standardInitialPosition)
|
||||
.option(Forsyth >> g2.toChess)
|
||||
.option(Forsyth >> g2.chess)
|
||||
.filter(Forsyth.initial !=)
|
||||
}
|
||||
val checkInHours =
|
||||
|
|
|
@ -15,10 +15,10 @@ object JsonView {
|
|||
"perf" -> PerfPicker.key(game),
|
||||
"rated" -> game.rated,
|
||||
"initialFen" -> initialFen.fold(chess.format.Forsyth.initial)(_.value),
|
||||
"fen" -> (Forsyth >> game.toChess),
|
||||
"fen" -> (Forsyth >> game.chess),
|
||||
"player" -> game.turnColor,
|
||||
"turns" -> game.turns,
|
||||
"startedAtTurn" -> game.startedAtTurn,
|
||||
"startedAtTurn" -> game.chess.startedAtTurn,
|
||||
"source" -> game.source,
|
||||
"status" -> game.status,
|
||||
"createdAt" -> game.createdAt
|
||||
|
@ -27,7 +27,7 @@ object JsonView {
|
|||
.add("tournamentId" -> game.tournamentId)
|
||||
.add("winner" -> game.winnerColor)
|
||||
.add("lastMove" -> game.lastMoveKeys)
|
||||
.add("check" -> game.check.map(_.key))
|
||||
.add("check" -> game.situation.checkSquare.map(_.key))
|
||||
.add("rematch" -> game.next)
|
||||
|
||||
implicit val statusWrites: OWrites[chess.Status] = OWrites { s =>
|
||||
|
|
|
@ -9,9 +9,9 @@ import chess.format.{ Forsyth, FEN, Uci }
|
|||
final class PngExport(url: String, size: Int) {
|
||||
|
||||
def fromGame(game: Game): Fu[Enumerator[Array[Byte]]] = apply(
|
||||
fen = FEN(Forsyth >> game.toChess),
|
||||
fen = FEN(Forsyth >> game.chess),
|
||||
lastMove = game.lastMoveKeys,
|
||||
check = game.toChess.situation.checkSquare,
|
||||
check = game.situation.checkSquare,
|
||||
orientation = game.firstColor.some,
|
||||
logHint = s"game ${game.id}"
|
||||
)
|
||||
|
|
|
@ -32,18 +32,12 @@ object Rewind {
|
|||
val newGame = game.copy(
|
||||
whitePlayer = rewindPlayer(game.whitePlayer),
|
||||
blackPlayer = rewindPlayer(game.blackPlayer),
|
||||
pgnMoves = rewindedGame.pgnMoves,
|
||||
pieces = rewindedGame.board.pieces,
|
||||
history = rewindedHistory,
|
||||
turns = rewindedGame.turns,
|
||||
chess = rewindedGame.copy(clock = newClock),
|
||||
binaryMoveTimes = game.binaryMoveTimes.map { binary =>
|
||||
val moveTimes = BinaryFormat.moveTime.read(binary, game.playedTurns)
|
||||
BinaryFormat.moveTime.write(moveTimes.dropRight(1))
|
||||
},
|
||||
clockHistory = game.clockHistory.map(_.update(!color, _.dropRight(1))),
|
||||
crazyData = rewindedSituation.board.crazyData,
|
||||
status = game.status,
|
||||
clock = newClock,
|
||||
movedAt = DateTime.now
|
||||
)
|
||||
Progress(game, newGame)
|
||||
|
|
|
@ -87,18 +87,13 @@ case class ImportData(pgn: String, analyse: Option[String]) {
|
|||
}
|
||||
|
||||
val dbGame = Game.make(
|
||||
game = replay.state,
|
||||
chess = replay.state,
|
||||
whitePlayer = Player.white withName name(_.White, _.WhiteElo),
|
||||
blackPlayer = Player.black withName name(_.Black, _.BlackElo),
|
||||
mode = Mode.Casual,
|
||||
variant = variant,
|
||||
source = Source.Import,
|
||||
pgnImport = PgnImport.make(user = user, date = date, pgn = pgn).some
|
||||
) |> { g =>
|
||||
g.copy(
|
||||
pgnMoves = replay.state.pgnMoves
|
||||
).start
|
||||
}
|
||||
).start
|
||||
|
||||
Preprocessed(dbGame, replay, result, initialFen, parsed)
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ class DataFormTest extends Specification with ValidationMatchers {
|
|||
1. Bd7 b4 2. Kf7 b3 3. Ke8 b2 4. Kd8 g6 5. Bxc7# { Black is checkmated } 1-0"""
|
||||
|
||||
ImportData(pgn, None).preprocess(None) must beSuccess.like {
|
||||
case s => s.game.toChess.board.history.castles must_== Castles.none
|
||||
case s => s.game.history.castles must_== Castles.none
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ object Chart {
|
|||
def games = povs.map { pov =>
|
||||
Json.obj(
|
||||
"id" -> pov.game.id,
|
||||
"fen" -> (chess.format.Forsyth exportBoard pov.game.toChess.board),
|
||||
"fen" -> (chess.format.Forsyth exportBoard pov.game.board),
|
||||
"color" -> pov.player.color.name,
|
||||
"lastMove" -> ~pov.game.lastMoveKeys,
|
||||
"user1" -> gameUserJson(pov.player),
|
||||
|
|
|
@ -57,27 +57,25 @@ private[lobby] object Biter {
|
|||
}
|
||||
|
||||
private def makeGame(hook: Hook) = Game.make(
|
||||
game = ChessGame(
|
||||
chess = ChessGame(
|
||||
situation = Situation(hook.realVariant),
|
||||
clock = hook.clock.toClock.some
|
||||
),
|
||||
whitePlayer = Player.white,
|
||||
blackPlayer = Player.black,
|
||||
mode = hook.realMode,
|
||||
variant = hook.realVariant,
|
||||
source = lila.game.Source.Lobby,
|
||||
pgnImport = None
|
||||
)
|
||||
|
||||
private def makeGame(seek: Seek) = Game.make(
|
||||
game = ChessGame(
|
||||
chess = ChessGame(
|
||||
situation = Situation(seek.realVariant),
|
||||
clock = none
|
||||
),
|
||||
whitePlayer = Player.white,
|
||||
blackPlayer = Player.black,
|
||||
mode = seek.realMode,
|
||||
variant = seek.realVariant,
|
||||
source = lila.game.Source.Lobby,
|
||||
daysPerTurn = seek.daysPerTurn,
|
||||
pgnImport = None
|
||||
|
|
|
@ -59,14 +59,13 @@ private final class GameStarter(
|
|||
whiteUser: (User.ID, Perf),
|
||||
blackUser: (User.ID, Perf)
|
||||
) = Game.make(
|
||||
game = chess.Game(
|
||||
chess = chess.Game(
|
||||
situation = chess.Situation(chess.variant.Standard),
|
||||
clock = pool.clock.toClock.some
|
||||
),
|
||||
whitePlayer = Player.white.withUser(whiteUser._1, whiteUser._2),
|
||||
blackPlayer = Player.black.withUser(blackUser._1, blackUser._2),
|
||||
mode = chess.Mode.Rated,
|
||||
variant = chess.variant.Standard,
|
||||
source = lila.game.Source.Pool,
|
||||
pgnImport = None
|
||||
)
|
||||
|
|
|
@ -40,7 +40,7 @@ private final class PushApi(
|
|||
"gameId" -> game.id,
|
||||
"fullId" -> pov.fullId,
|
||||
"color" -> pov.color.name,
|
||||
"fen" -> Forsyth.exportBoard(game.toChess.board),
|
||||
"fen" -> Forsyth.exportBoard(game.board),
|
||||
"lastMove" -> game.lastMoveKeys,
|
||||
"win" -> pov.win
|
||||
)
|
||||
|
@ -139,7 +139,7 @@ private final class PushApi(
|
|||
"gameId" -> pov.game.id,
|
||||
"fullId" -> pov.fullId,
|
||||
"color" -> pov.color.name,
|
||||
"fen" -> Forsyth.exportBoard(pov.game.toChess.board),
|
||||
"fen" -> Forsyth.exportBoard(pov.game.board),
|
||||
"lastMove" -> pov.game.lastMoveKeys,
|
||||
"secondsLeft" -> pov.remainingSeconds
|
||||
)
|
||||
|
|
|
@ -36,7 +36,7 @@ private[round] final class Finisher(
|
|||
other(game, _.Aborted, none)
|
||||
} else {
|
||||
val winner = Some(!game.player.color) filterNot { color =>
|
||||
game.toChess.board.variant.insufficientWinningMaterial(game.toChess.situation.board, color)
|
||||
game.variant.insufficientWinningMaterial(game.board, color)
|
||||
}
|
||||
apply(game, _.Outoftime, winner) >>-
|
||||
winner.?? { w => playban.flag(game, !w) }
|
||||
|
|
|
@ -110,7 +110,7 @@ final class JsonView(
|
|||
).add("clock" -> game.clock.map(clockJson))
|
||||
.add("correspondence" -> game.correspondenceClock)
|
||||
.add("takebackable" -> takebackable)
|
||||
.add("crazyhouse" -> pov.game.crazyData)
|
||||
.add("crazyhouse" -> pov.game.board.crazyData)
|
||||
.add("possibleMoves" -> possibleMoves(pov))
|
||||
.add("possibleDrops" -> possibleDrops(pov))
|
||||
.add("expiration" -> game.expirable.option {
|
||||
|
@ -204,7 +204,7 @@ final class JsonView(
|
|||
division: Option[chess.Division] = none
|
||||
) = {
|
||||
import pov._
|
||||
val fen = Forsyth >> game.toChess
|
||||
val fen = Forsyth >> game.chess
|
||||
Json.obj(
|
||||
"game" -> Json.obj(
|
||||
"id" -> gameId,
|
||||
|
@ -256,13 +256,13 @@ final class JsonView(
|
|||
|
||||
private def possibleMoves(pov: Pov): Option[Map[String, String]] =
|
||||
(pov.game playableBy pov.player) option {
|
||||
pov.game.toChess.situation.destinations map {
|
||||
pov.game.situation.destinations map {
|
||||
case (from, dests) => from.key -> dests.mkString
|
||||
}
|
||||
}
|
||||
|
||||
private def possibleDrops(pov: Pov): Option[JsValue] = (pov.game playableBy pov.player) ?? {
|
||||
pov.game.toChess.situation.drops map { drops =>
|
||||
pov.game.situation.drops map { drops =>
|
||||
JsString(drops.map(_.key).mkString)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ private[round] final class Player(
|
|||
|
||||
def fishnet(game: Game, uci: Uci, currentFen: FEN, round: ActorRef)(implicit proxy: GameProxy): Fu[Events] =
|
||||
if (game.playable && game.player.isAi) {
|
||||
if (currentFen == FEN(Forsyth >> game.toChess))
|
||||
if (currentFen == FEN(Forsyth >> game.chess))
|
||||
applyUci(game, uci, blur = false, metrics = fishnetLag)
|
||||
.fold(errs => fufail(ClientError(errs.shows)), fuccess).flatMap {
|
||||
case Flagged => finisher.outOfTime(game)
|
||||
|
@ -76,10 +76,10 @@ private[round] final class Player(
|
|||
|
||||
private def applyUci(game: Game, uci: Uci, blur: Boolean, metrics: MoveMetrics): Valid[MoveResult] =
|
||||
(uci match {
|
||||
case Uci.Move(orig, dest, prom) => game.toChess.apply(orig, dest, prom, metrics) map {
|
||||
case Uci.Move(orig, dest, prom) => game.chess(orig, dest, prom, metrics) map {
|
||||
case (ncg, move) => ncg -> (Left(move): MoveOrDrop)
|
||||
}
|
||||
case Uci.Drop(role, pos) => game.toChess.drop(role, pos, metrics) map {
|
||||
case Uci.Drop(role, pos) => game.chess.drop(role, pos, metrics) map {
|
||||
case (ncg, drop) => ncg -> (Right(drop): MoveOrDrop)
|
||||
}
|
||||
}).map {
|
||||
|
@ -95,7 +95,7 @@ private[round] final class Player(
|
|||
val color = moveOrDrop.fold(_.color, _.color)
|
||||
val moveEvent = MoveEvent(
|
||||
gameId = game.id,
|
||||
fen = Forsyth exportBoard game.toChess.board,
|
||||
fen = Forsyth exportBoard game.board,
|
||||
move = moveOrDrop.fold(_.toUci.keys, _.toUci.uci)
|
||||
)
|
||||
// publish all moves
|
||||
|
@ -124,8 +124,8 @@ private[round] final class Player(
|
|||
}
|
||||
|
||||
private def moveFinish(game: Game, color: Color)(implicit proxy: GameProxy): Fu[Events] = game.status match {
|
||||
case Status.Mate => finisher.other(game, _.Mate, game.toChess.situation.winner)
|
||||
case Status.VariantEnd => finisher.other(game, _.VariantEnd, game.toChess.situation.winner)
|
||||
case Status.Mate => finisher.other(game, _.Mate, game.situation.winner)
|
||||
case Status.VariantEnd => finisher.other(game, _.VariantEnd, game.situation.winner)
|
||||
case status @ (Status.Stalemate | Status.Draw) => finisher.other(game, _ => status, None)
|
||||
case _ => fuccess(Nil)
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@ private[round] final class Rematcher(
|
|||
}
|
||||
users <- UserRepo byIds pov.game.userIds
|
||||
} yield Game.make(
|
||||
game = ChessGame(
|
||||
chess = ChessGame(
|
||||
situation = Situation(
|
||||
board = Board(pieces, variant = pov.game.variant).withCastles {
|
||||
situation.fold(Castles.init)(_.situation.board.history.castles)
|
||||
|
@ -95,7 +95,6 @@ private[round] final class Rematcher(
|
|||
whitePlayer = returnPlayer(pov.game, White, users),
|
||||
blackPlayer = returnPlayer(pov.game, Black, users),
|
||||
mode = if (users.exists(_.lame)) chess.Mode.Casual else pov.game.mode,
|
||||
variant = pov.game.variant,
|
||||
source = pov.game.source | Source.Lobby,
|
||||
daysPerTurn = pov.game.daysPerTurn,
|
||||
pgnImport = None
|
||||
|
|
|
@ -20,9 +20,8 @@ case class AiConfig(
|
|||
def >> = (variant.id, timeMode.id, time, increment, days, level, color.name, fen).some
|
||||
|
||||
def game = fenGame { chessGame =>
|
||||
val realVariant = chessGame.board.variant
|
||||
Game.make(
|
||||
game = chessGame,
|
||||
chess = chessGame,
|
||||
whitePlayer = Player.make(
|
||||
color = ChessColor.White,
|
||||
aiLevel = creatorColor.black option level
|
||||
|
@ -32,8 +31,7 @@ case class AiConfig(
|
|||
aiLevel = creatorColor.white option level
|
||||
),
|
||||
mode = Mode.Casual,
|
||||
variant = realVariant,
|
||||
source = (realVariant == chess.variant.FromPosition).fold(Source.Position, Source.Ai),
|
||||
source = (chessGame.board.variant.fromPosition).fold(Source.Position, Source.Ai),
|
||||
daysPerTurn = makeDaysPerTurn,
|
||||
pgnImport = None
|
||||
)
|
||||
|
|
|
@ -15,11 +15,10 @@ private[setup] case object ApiConfig extends Config {
|
|||
val days = 2
|
||||
|
||||
def game = Game.make(
|
||||
game = makeGame,
|
||||
chess = makeGame,
|
||||
whitePlayer = Player.white,
|
||||
blackPlayer = Player.black,
|
||||
mode = mode,
|
||||
variant = variant,
|
||||
source = Source.Api,
|
||||
pgnImport = None
|
||||
)
|
||||
|
|
|
@ -74,9 +74,15 @@ trait Positional { self: Config =>
|
|||
val game = builder(chessGame)
|
||||
state.fold(game) {
|
||||
case sit @ SituationPlus(Situation(board, _), _) => game.copy(
|
||||
variant = chess.variant.FromPosition,
|
||||
history = board.history,
|
||||
turns = sit.turns
|
||||
chess = game.chess.copy(
|
||||
situation = game.situation.copy(
|
||||
board = game.board.copy(
|
||||
history = board.history,
|
||||
variant = chess.variant.FromPosition
|
||||
)
|
||||
),
|
||||
turns = sit.turns
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ final class JsonView(getLightUser: LightUser.Getter) {
|
|||
private def gameJson(hostId: String)(g: Game) = Json.obj(
|
||||
"id" -> g.id,
|
||||
"status" -> g.status.id,
|
||||
"fen" -> (chess.format.Forsyth exportBoard g.toChess.board),
|
||||
"fen" -> (chess.format.Forsyth exportBoard g.board),
|
||||
"lastMove" -> ~g.lastMoveKeys,
|
||||
"orient" -> g.playerByUserId(hostId).map(_.color)
|
||||
)
|
||||
|
|
|
@ -186,14 +186,13 @@ final class SimulApi(
|
|||
whiteUser = hostColor.fold(host, user)
|
||||
blackUser = hostColor.fold(user, host)
|
||||
game1 = Game.make(
|
||||
game = chess.Game(
|
||||
chess = chess.Game(
|
||||
situation = chess.Situation(pairing.player.variant),
|
||||
clock = simul.clock.chessClockOf(hostColor).start.some
|
||||
),
|
||||
whitePlayer = lila.game.Player.white,
|
||||
blackPlayer = lila.game.Player.black,
|
||||
mode = chess.Mode.Casual,
|
||||
variant = pairing.player.variant,
|
||||
source = lila.game.Source.Simul,
|
||||
pgnImport = None
|
||||
)
|
||||
|
|
|
@ -15,7 +15,7 @@ final class AutoPairing(
|
|||
val user1 = usersMap get pairing.user1 err s"Missing pairing user1 $pairing"
|
||||
val user2 = usersMap get pairing.user2 err s"Missing pairing user2 $pairing"
|
||||
val game1 = Game.make(
|
||||
game = chess.Game(
|
||||
chess = chess.Game(
|
||||
variantOption = tour.variant.some,
|
||||
fen = tour.position.some.filterNot(_.initial).map(_.fen)
|
||||
) |> { g =>
|
||||
|
@ -29,9 +29,6 @@ final class AutoPairing(
|
|||
whitePlayer = GamePlayer.white,
|
||||
blackPlayer = GamePlayer.black,
|
||||
mode = tour.mode,
|
||||
variant =
|
||||
if (tour.position.initial) tour.variant
|
||||
else chess.variant.FromPosition,
|
||||
source = Source.Tournament,
|
||||
pgnImport = None
|
||||
)
|
||||
|
|
|
@ -227,7 +227,7 @@ final class JsonView(
|
|||
}
|
||||
Json.obj(
|
||||
"id" -> game.id,
|
||||
"fen" -> (chess.format.Forsyth exportBoard game.toChess.board),
|
||||
"fen" -> (chess.format.Forsyth exportBoard game.board),
|
||||
"color" -> (game.variant match {
|
||||
case chess.variant.RacingKings => chess.White
|
||||
case _ => game.firstColor
|
||||
|
|
Loading…
Reference in New Issue