2013-03-22 11:53:13 -06:00
|
|
|
package lila.game
|
2012-05-14 14:36:32 -06:00
|
|
|
|
2014-02-12 16:23:18 -07:00
|
|
|
import lila.common.PimpedJson._
|
2012-05-14 14:36:32 -06:00
|
|
|
import play.api.libs.json._
|
|
|
|
|
2013-05-24 11:04:49 -06:00
|
|
|
import chess.Pos.{ piotr, allPiotrs }
|
2015-03-31 07:59:44 -06:00
|
|
|
import chess.{ PromotableRole, Pos, Color, Situation, Move => ChessMove, Clock => ChessClock, Status }
|
2014-02-12 16:23:18 -07:00
|
|
|
import lila.chat.{ Line, UserLine, PlayerLine }
|
2012-05-14 14:36:32 -06:00
|
|
|
|
|
|
|
sealed trait Event {
|
|
|
|
def typ: String
|
|
|
|
def data: JsValue
|
|
|
|
def only: Option[Color] = None
|
|
|
|
def owner: Boolean = false
|
2012-06-10 08:48:06 -06:00
|
|
|
def watcher: Boolean = false
|
2013-06-05 12:03:30 -06:00
|
|
|
def troll: Boolean = false
|
2012-05-14 14:36:32 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
object Event {
|
|
|
|
|
2015-04-27 14:36:43 -06:00
|
|
|
def fromMove(move: ChessMove, situation: Situation): List[Event] =
|
|
|
|
Move(move, situation) :: List(
|
2015-06-15 17:26:39 -06:00
|
|
|
(move.capture ifTrue move.enpassant) map { Event.Enpassant(_, !move.color) }, // BC
|
|
|
|
move.promotion map { Promotion(_, move.dest) }, // BC
|
|
|
|
move.castle map { case (king, rook) => Castling(king, rook, move.color) } // BC
|
2015-04-27 14:36:43 -06:00
|
|
|
).flatten
|
2012-05-14 14:36:32 -06:00
|
|
|
|
|
|
|
def fromSituation(situation: Situation): List[Event] = List(
|
2015-06-15 17:26:39 -06:00
|
|
|
situation.check ?? situation.kingPos map Check.apply, // BC
|
|
|
|
situation.threefoldRepetition option Threefold, // BC
|
|
|
|
Some(Premove(situation.color) // BC
|
|
|
|
)).flatten
|
2012-05-14 14:36:32 -06:00
|
|
|
|
|
|
|
def possibleMoves(situation: Situation, color: Color): Event =
|
2013-09-30 15:10:42 -06:00
|
|
|
PossibleMoves(color, (color == situation.color) ?? situation.destinations)
|
2012-05-14 14:36:32 -06:00
|
|
|
|
|
|
|
sealed trait Empty extends Event {
|
|
|
|
def data = JsNull
|
|
|
|
}
|
|
|
|
|
2013-03-30 15:30:47 -06:00
|
|
|
object Start extends Empty {
|
2012-05-14 14:36:32 -06:00
|
|
|
def typ = "start"
|
|
|
|
}
|
|
|
|
|
2015-04-27 14:36:43 -06:00
|
|
|
case class Move(
|
|
|
|
orig: Pos,
|
|
|
|
dest: Pos,
|
|
|
|
color: Color,
|
|
|
|
san: String,
|
|
|
|
fen: String,
|
2015-06-15 17:26:39 -06:00
|
|
|
check: Boolean,
|
|
|
|
threefold: Boolean,
|
|
|
|
promotion: Option[Promotion],
|
|
|
|
enpassant: Option[Enpassant],
|
|
|
|
castle: Option[Castling]) extends Event {
|
2012-05-14 14:36:32 -06:00
|
|
|
def typ = "move"
|
2013-04-01 21:43:01 -06:00
|
|
|
def data = Json.obj(
|
2015-04-28 10:14:14 -06:00
|
|
|
// legacy data
|
2013-04-01 21:43:01 -06:00
|
|
|
"from" -> orig.key,
|
|
|
|
"to" -> dest.key,
|
2014-10-21 15:23:04 -06:00
|
|
|
"color" -> color.name,
|
2015-04-28 10:14:14 -06:00
|
|
|
// new data
|
|
|
|
"uci" -> s"${orig.key}${dest.key}",
|
2015-04-27 14:36:43 -06:00
|
|
|
"san" -> san,
|
|
|
|
"fen" -> fen,
|
2015-06-15 17:26:39 -06:00
|
|
|
"check" -> check.option(true),
|
|
|
|
"threefold" -> threefold.option(true),
|
|
|
|
"promotion" -> promotion.map(_.data),
|
|
|
|
"enpassant" -> enpassant.map(_.data),
|
|
|
|
"castle" -> castle.map(_.data)
|
2015-04-27 14:36:43 -06:00
|
|
|
).noNull
|
2012-05-14 14:36:32 -06:00
|
|
|
}
|
|
|
|
object Move {
|
2015-04-27 14:36:43 -06:00
|
|
|
def apply(move: ChessMove, situation: Situation): 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),
|
2015-06-15 17:26:39 -06:00
|
|
|
check = situation.check,
|
|
|
|
threefold = situation.threefoldRepetition,
|
|
|
|
promotion = move.promotion.map { Promotion(_, move.dest) },
|
|
|
|
enpassant = (move.capture ifTrue move.enpassant).map {
|
|
|
|
Event.Enpassant(_, !move.color)
|
|
|
|
},
|
|
|
|
castle = move.castle.map {
|
|
|
|
case (king, rook) => Castling(king, rook, move.color)
|
|
|
|
})
|
2012-05-14 14:36:32 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
case class PossibleMoves(
|
|
|
|
color: Color,
|
|
|
|
moves: Map[Pos, List[Pos]]) extends Event {
|
2014-05-10 04:39:38 -06:00
|
|
|
def typ = "possibleMoves"
|
2012-05-14 14:36:32 -06:00
|
|
|
def data =
|
|
|
|
if (moves.isEmpty) JsNull
|
|
|
|
else JsObject(moves map {
|
2014-02-17 02:12:19 -07:00
|
|
|
case (o, d) => o.key -> JsString(d map (_.key) mkString)
|
2012-05-14 14:36:32 -06:00
|
|
|
} toList)
|
|
|
|
override def only = Some(color)
|
|
|
|
}
|
|
|
|
|
2015-01-11 16:56:03 -07:00
|
|
|
case class Enpassant(pos: Pos, color: Color) extends Event {
|
2012-05-14 14:36:32 -06:00
|
|
|
def typ = "enpassant"
|
2015-01-11 16:56:03 -07:00
|
|
|
def data = Json.obj(
|
|
|
|
"key" -> pos.key,
|
|
|
|
"color" -> color.name)
|
2012-05-14 14:36:32 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
case class Castling(king: (Pos, Pos), rook: (Pos, Pos), color: Color) extends Event {
|
|
|
|
def typ = "castling"
|
2013-04-01 21:43:01 -06:00
|
|
|
def data = Json.obj(
|
|
|
|
"king" -> Json.arr(king._1.key, king._2.key),
|
|
|
|
"rook" -> Json.arr(rook._1.key, rook._2.key),
|
|
|
|
"color" -> color.name
|
|
|
|
)
|
2012-05-14 14:36:32 -06:00
|
|
|
}
|
|
|
|
|
2014-02-12 16:23:18 -07:00
|
|
|
case class RedirectOwner(
|
|
|
|
color: Color,
|
2014-08-13 16:14:03 -06:00
|
|
|
id: String,
|
2014-02-12 16:23:18 -07:00
|
|
|
cookie: Option[JsObject]) extends Event {
|
2012-05-14 14:36:32 -06:00
|
|
|
def typ = "redirect"
|
2014-02-12 16:23:18 -07:00
|
|
|
def data = Json.obj(
|
2014-08-13 16:14:03 -06:00
|
|
|
"id" -> id,
|
|
|
|
"url" -> s"/$id",
|
2014-02-12 16:23:18 -07:00
|
|
|
"cookie" -> cookie
|
|
|
|
).noNull
|
2012-05-14 14:36:32 -06:00
|
|
|
override def only = Some(color)
|
|
|
|
override def owner = true
|
|
|
|
}
|
|
|
|
|
|
|
|
case class Promotion(role: PromotableRole, pos: Pos) extends Event {
|
|
|
|
def typ = "promotion"
|
2013-04-01 21:43:01 -06:00
|
|
|
def data = Json.obj(
|
|
|
|
"key" -> pos.key,
|
|
|
|
"pieceClass" -> role.toString.toLowerCase
|
|
|
|
)
|
2012-05-14 14:36:32 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
case class Check(pos: Pos) extends Event {
|
|
|
|
def typ = "check"
|
|
|
|
def data = JsString(pos.key)
|
|
|
|
}
|
|
|
|
|
2014-01-31 18:02:32 -07:00
|
|
|
case class PlayerMessage(line: PlayerLine) extends Event {
|
2012-05-14 14:36:32 -06:00
|
|
|
def typ = "message"
|
2014-01-31 18:02:32 -07:00
|
|
|
def data = Line toJson line
|
2012-05-14 14:36:32 -06:00
|
|
|
override def owner = true
|
2014-01-31 18:02:32 -07:00
|
|
|
override def troll = false
|
2012-05-14 14:36:32 -06:00
|
|
|
}
|
|
|
|
|
2014-01-31 18:02:32 -07:00
|
|
|
case class UserMessage(line: UserLine, w: Boolean) extends Event {
|
2012-06-10 08:48:06 -06:00
|
|
|
def typ = "message"
|
2014-01-31 18:02:32 -07:00
|
|
|
def data = Line toJson line
|
|
|
|
override def troll = line.troll
|
|
|
|
override def watcher = w
|
2014-02-19 11:52:22 -07:00
|
|
|
override def owner = !w
|
2012-06-10 08:48:06 -06:00
|
|
|
}
|
|
|
|
|
2013-03-30 15:30:47 -06:00
|
|
|
object End extends Empty {
|
2012-05-14 14:36:32 -06:00
|
|
|
def typ = "end"
|
|
|
|
}
|
|
|
|
|
2013-03-30 15:30:47 -06:00
|
|
|
object Threefold extends Empty {
|
2014-05-10 04:39:38 -06:00
|
|
|
def typ = "threefoldRepetition"
|
2012-05-14 14:36:32 -06:00
|
|
|
}
|
|
|
|
|
2014-10-03 02:10:12 -06:00
|
|
|
case object Reload extends Empty {
|
|
|
|
def typ = "reload"
|
|
|
|
}
|
|
|
|
case object ReloadOwner extends Empty {
|
|
|
|
def typ = "reload"
|
2013-05-18 09:26:37 -06:00
|
|
|
override def owner = true
|
|
|
|
}
|
2013-05-18 07:51:26 -06:00
|
|
|
|
2012-05-14 14:36:32 -06:00
|
|
|
case class Premove(color: Color) extends Empty {
|
|
|
|
def typ = "premove"
|
|
|
|
override def only = Some(color)
|
2013-05-30 04:18:26 -06:00
|
|
|
override def owner = true
|
2012-05-14 14:36:32 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
case class Clock(white: Float, black: Float) extends Event {
|
|
|
|
def typ = "clock"
|
2013-04-01 21:43:01 -06:00
|
|
|
def data = Json.obj(
|
|
|
|
"white" -> white,
|
|
|
|
"black" -> black
|
|
|
|
)
|
2012-05-14 14:36:32 -06:00
|
|
|
}
|
|
|
|
object Clock {
|
|
|
|
def apply(clock: ChessClock): Clock = Clock(
|
|
|
|
clock remainingTime Color.White,
|
|
|
|
clock remainingTime Color.Black)
|
|
|
|
}
|
|
|
|
|
2014-11-30 03:22:23 -07:00
|
|
|
case class CorrespondenceClock(white: Float, black: Float) extends Event {
|
|
|
|
def typ = "cclock"
|
|
|
|
def data = Json.obj("white" -> white, "black" -> black)
|
|
|
|
}
|
|
|
|
object CorrespondenceClock {
|
|
|
|
def apply(clock: lila.game.CorrespondenceClock): CorrespondenceClock =
|
|
|
|
CorrespondenceClock(clock.whiteTime, clock.blackTime)
|
|
|
|
}
|
|
|
|
|
2014-07-31 13:06:22 -06:00
|
|
|
case class CheckCount(white: Int, black: Int) extends Event {
|
|
|
|
def typ = "checkCount"
|
|
|
|
def data = Json.obj(
|
|
|
|
"white" -> white,
|
|
|
|
"black" -> black
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2015-03-31 07:59:44 -06:00
|
|
|
case class State(
|
|
|
|
color: Color,
|
|
|
|
turns: Int,
|
2015-04-01 04:38:47 -06:00
|
|
|
status: Option[Status],
|
2015-03-31 07:59:44 -06:00
|
|
|
whiteOffersDraw: Boolean,
|
|
|
|
blackOffersDraw: Boolean) extends Event {
|
2012-05-14 14:36:32 -06:00
|
|
|
def typ = "state"
|
2013-04-01 21:43:01 -06:00
|
|
|
def data = Json.obj(
|
|
|
|
"color" -> color.name,
|
2015-03-31 07:59:44 -06:00
|
|
|
"turns" -> turns,
|
2015-04-01 04:38:47 -06:00
|
|
|
"status" -> status.map { s =>
|
|
|
|
Json.obj(
|
|
|
|
"id" -> s.id,
|
|
|
|
"name" -> s.name)
|
|
|
|
},
|
2015-03-31 07:59:44 -06:00
|
|
|
"wDraw" -> whiteOffersDraw.option(true),
|
|
|
|
"bDraw" -> blackOffersDraw.option(true)
|
|
|
|
).noNull
|
2012-05-14 14:36:32 -06:00
|
|
|
}
|
|
|
|
|
2015-04-21 13:21:26 -06:00
|
|
|
case class TakebackOffers(
|
|
|
|
white: Boolean,
|
|
|
|
black: Boolean) extends Event {
|
|
|
|
def typ = "takebackOffers"
|
|
|
|
def data = Json.obj(
|
|
|
|
"white" -> white.option(true),
|
|
|
|
"black" -> black.option(true)
|
|
|
|
).noNull
|
2015-04-21 13:22:55 -06:00
|
|
|
override def owner = true
|
2015-04-21 13:21:26 -06:00
|
|
|
}
|
|
|
|
|
2012-05-14 14:36:32 -06:00
|
|
|
case class Crowd(
|
|
|
|
white: Boolean,
|
|
|
|
black: Boolean,
|
2012-06-10 15:37:11 -06:00
|
|
|
watchers: List[String]) extends Event {
|
2012-05-14 14:36:32 -06:00
|
|
|
def typ = "crowd"
|
2013-04-01 21:43:01 -06:00
|
|
|
def data = Json.obj(
|
|
|
|
"white" -> white,
|
|
|
|
"black" -> black,
|
2013-05-10 07:32:45 -06:00
|
|
|
"watchers" -> watchers)
|
2012-05-14 14:36:32 -06:00
|
|
|
}
|
|
|
|
}
|