From f04e3807e429da8581eb6e7ab08e28c581dc0675 Mon Sep 17 00:00:00 2001 From: Isaac Levy Date: Tue, 15 Oct 2024 08:37:26 -0400 Subject: [PATCH 1/2] 16.3.2 - Upgrade scalalib to 11.3.1. - Change typing of Centis to RichOpaqueInt, which improves type safety - Many other OpaqueInts are simply renamed to RelaxedOpaqueInt, if needed to get lila or scalachess to compile. --- build.sbt | 4 ++-- core/src/main/scala/Centis.scala | 2 +- core/src/main/scala/Clock.scala | 8 ++++---- core/src/main/scala/Elo.scala | 2 +- core/src/main/scala/model.scala | 8 ++++---- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/build.sbt b/build.sbt index 9f52114a8..e31c81b97 100644 --- a/build.sbt +++ b/build.sbt @@ -1,7 +1,7 @@ inThisBuild( Seq( scalaVersion := "3.5.1", - version := "16.3.1", + version := "16.3.2", organization := "org.lichess", licenses += ("MIT" -> url("https://opensource.org/licenses/MIT")), publishTo := Option(Resolver.file("file", new File(sys.props.getOrElse("publishTo", "")))), @@ -10,7 +10,7 @@ inThisBuild( ) ) -val scalalibVersion = "11.2.9" +val scalalibVersion = "11.3.1" val commonSettings = Seq( scalacOptions := Seq( diff --git a/core/src/main/scala/Centis.scala b/core/src/main/scala/Centis.scala index 1f8e8304f..78e11dda3 100644 --- a/core/src/main/scala/Centis.scala +++ b/core/src/main/scala/Centis.scala @@ -7,7 +7,7 @@ import scala.concurrent.duration.* // maximum centis = Int.MaxValue / 100 / 60 / 60 / 24 = 248 days opaque type Centis = Int -object Centis extends OpaqueInt[Centis]: +object Centis extends RichOpaqueInt[Centis]: extension (centis: Centis) diff --git a/core/src/main/scala/Clock.scala b/core/src/main/scala/Clock.scala index 8aa7bf042..869392812 100644 --- a/core/src/main/scala/Clock.scala +++ b/core/src/main/scala/Clock.scala @@ -38,7 +38,7 @@ case class Clock( else toNow(t) } - def moretimeable(c: Color) = players(c).remaining < 100 * 60 * 60 * 2 + def moretimeable(c: Color) = players(c).remaining < Centis(100 * 60 * 60 * 2) def isRunning = timer.isDefined @@ -157,13 +157,13 @@ object Clock: private val limitFormatter = DecimalFormat("#.##") opaque type LimitSeconds = Int - object LimitSeconds extends OpaqueInt[LimitSeconds] + object LimitSeconds extends RelaxedOpaqueInt[LimitSeconds] opaque type LimitMinutes = Int - object LimitMinutes extends OpaqueInt[LimitMinutes] + object LimitMinutes extends RelaxedOpaqueInt[LimitMinutes] opaque type IncrementSeconds = Int - object IncrementSeconds extends OpaqueInt[IncrementSeconds] + object IncrementSeconds extends RelaxedOpaqueInt[IncrementSeconds] // All unspecified durations are expressed in centi-seconds case class Config(limitSeconds: LimitSeconds, incrementSeconds: IncrementSeconds): diff --git a/core/src/main/scala/Elo.scala b/core/src/main/scala/Elo.scala index 8f062f94d..ebbd61950 100644 --- a/core/src/main/scala/Elo.scala +++ b/core/src/main/scala/Elo.scala @@ -12,7 +12,7 @@ object KFactor extends OpaqueInt[KFactor]: * https://handbook.fide.com/chapter/B022022 * https://ratings.fide.com/calc.phtml * */ -object Elo extends OpaqueInt[Elo]: +object Elo extends RelaxedOpaqueInt[Elo]: def computeRatingDiff(player: Player, games: Seq[Game]): Int = computeNewRating(player, games) - player.rating diff --git a/core/src/main/scala/model.scala b/core/src/main/scala/model.scala index e987acc46..273ebcaa4 100644 --- a/core/src/main/scala/model.scala +++ b/core/src/main/scala/model.scala @@ -5,14 +5,14 @@ import cats.kernel.Semigroup /** Fullmove number: The number of the full move. * It starts at 1, and is incremented after Black's move. */ opaque type FullMoveNumber = Int -object FullMoveNumber extends OpaqueInt[FullMoveNumber]: +object FullMoveNumber extends RelaxedOpaqueInt[FullMoveNumber]: val initial: FullMoveNumber = 1 extension (e: FullMoveNumber) def ply(turn: Color) = Ply(e * 2 - turn.fold(2, 1)) def next: FullMoveNumber = e + 1 opaque type Ply = Int -object Ply extends OpaqueInt[Ply]: +object Ply extends RelaxedOpaqueInt[Ply]: val initial: Ply = 0 val firstMove: Ply = 1 extension (e: Ply) @@ -25,7 +25,7 @@ object Ply extends OpaqueInt[Ply]: /* The halfmove clock specifies a decimal number of half moves with respect to the 50 move draw rule. * It is reset to zero after a capture or a pawn move and incremented otherwise. */ opaque type HalfMoveClock = Int -object HalfMoveClock extends OpaqueInt[HalfMoveClock]: +object HalfMoveClock extends RelaxedOpaqueInt[HalfMoveClock]: val initial: HalfMoveClock = 0 opaque type Check = Boolean @@ -36,7 +36,7 @@ object ErrorStr extends OpaqueString[ErrorStr]: given Semigroup[ErrorStr] = Semigroup.instance[ErrorStr]((a, b) => s"$a\n$b") opaque type FideId = Int -object FideId extends OpaqueInt[FideId] +object FideId extends RelaxedOpaqueInt[FideId] opaque type PlayerName = String object PlayerName extends OpaqueString[PlayerName] From a0bf698151493143b2cce7cd88ea957d0b843a55 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Fri, 18 Oct 2024 10:38:58 +0200 Subject: [PATCH 2/2] use fewer RelaxedOpaqueInt; FideId can just be OpaqueInt --- core/src/main/scala/Drop.scala | 2 +- core/src/main/scala/Move.scala | 2 +- core/src/main/scala/format/FenReader.scala | 4 ++-- core/src/main/scala/format/pgn/PgnNodeEncoder.scala | 2 +- core/src/main/scala/model.scala | 6 +++--- core/src/main/scala/variant/Variant.scala | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/core/src/main/scala/Drop.scala b/core/src/main/scala/Drop.scala index 96621addd..2848d64df 100644 --- a/core/src/main/scala/Drop.scala +++ b/core/src/main/scala/Drop.scala @@ -22,7 +22,7 @@ case class Drop( h.copy( lastMove = Option(Uci.Drop(piece.role, square)), unmovedRooks = before.unmovedRooks, - halfMoveClock = if piece.is(Pawn) then HalfMoveClock.initial else h.halfMoveClock + 1 + halfMoveClock = if piece.is(Pawn) then HalfMoveClock.initial else h.halfMoveClock.map(_ + 1) ) }, toUci, diff --git a/core/src/main/scala/Move.scala b/core/src/main/scala/Move.scala index 65c12bede..ad387babb 100644 --- a/core/src/main/scala/Move.scala +++ b/core/src/main/scala/Move.scala @@ -30,7 +30,7 @@ case class Move( lastMove = Option(toUci), halfMoveClock = if piece.is(Pawn) || captures || promotes then HalfMoveClock.initial - else h1.halfMoveClock + 1 + else h1.halfMoveClock.map(_ + 1) ) var castleRights: Castles = h1.castles diff --git a/core/src/main/scala/format/FenReader.scala b/core/src/main/scala/format/FenReader.scala index b05534059..ead700ef6 100644 --- a/core/src/main/scala/format/FenReader.scala +++ b/core/src/main/scala/format/FenReader.scala @@ -91,10 +91,10 @@ trait FenReader: val halfMoveClock = HalfMoveClock .from(splitted.lift(0).flatMap(_.toIntOption)) - .map(_.atLeast(HalfMoveClock.initial).atMost(100)) + .map(_.atLeast(HalfMoveClock.initial).atMost(HalfMoveClock(100))) val fullMoveNumber = FullMoveNumber .from(splitted.lift(1).flatMap(_.toIntOption)) - .map(_.atLeast(FullMoveNumber.initial).atMost(500)) + .map(_.atLeast(FullMoveNumber.initial).atMost(FullMoveNumber(500))) (halfMoveClock, fullMoveNumber) def readPly(fen: FullFen): Option[Ply] = diff --git a/core/src/main/scala/format/pgn/PgnNodeEncoder.scala b/core/src/main/scala/format/pgn/PgnNodeEncoder.scala index 886b50d30..bd03ee3e1 100644 --- a/core/src/main/scala/format/pgn/PgnNodeEncoder.scala +++ b/core/src/main/scala/format/pgn/PgnNodeEncoder.scala @@ -86,4 +86,4 @@ object PgnNodeEncoder: private def isWhiteTurn: Boolean = ply.isOdd private def turnNumber: FullMoveNumber = - ply.fullMoveNumber + ply.value % 2 - 1 + ply.fullMoveNumber.map(_ + ply.value % 2 - 1) diff --git a/core/src/main/scala/model.scala b/core/src/main/scala/model.scala index 273ebcaa4..92fae5b53 100644 --- a/core/src/main/scala/model.scala +++ b/core/src/main/scala/model.scala @@ -5,7 +5,7 @@ import cats.kernel.Semigroup /** Fullmove number: The number of the full move. * It starts at 1, and is incremented after Black's move. */ opaque type FullMoveNumber = Int -object FullMoveNumber extends RelaxedOpaqueInt[FullMoveNumber]: +object FullMoveNumber extends RichOpaqueInt[FullMoveNumber]: val initial: FullMoveNumber = 1 extension (e: FullMoveNumber) def ply(turn: Color) = Ply(e * 2 - turn.fold(2, 1)) @@ -25,7 +25,7 @@ object Ply extends RelaxedOpaqueInt[Ply]: /* The halfmove clock specifies a decimal number of half moves with respect to the 50 move draw rule. * It is reset to zero after a capture or a pawn move and incremented otherwise. */ opaque type HalfMoveClock = Int -object HalfMoveClock extends RelaxedOpaqueInt[HalfMoveClock]: +object HalfMoveClock extends RichOpaqueInt[HalfMoveClock]: val initial: HalfMoveClock = 0 opaque type Check = Boolean @@ -36,7 +36,7 @@ object ErrorStr extends OpaqueString[ErrorStr]: given Semigroup[ErrorStr] = Semigroup.instance[ErrorStr]((a, b) => s"$a\n$b") opaque type FideId = Int -object FideId extends RelaxedOpaqueInt[FideId] +object FideId extends OpaqueInt[FideId] opaque type PlayerName = String object PlayerName extends OpaqueString[PlayerName] diff --git a/core/src/main/scala/variant/Variant.scala b/core/src/main/scala/variant/Variant.scala index 5b6b18519..d8f44b78b 100644 --- a/core/src/main/scala/variant/Variant.scala +++ b/core/src/main/scala/variant/Variant.scala @@ -133,7 +133,7 @@ abstract class Variant private[variant] ( def applyVariantEffect(moves: List[Move]): List[Move] = if hasMoveEffects then moves.map(addVariantEffect) else moves - def fiftyMoves(history: History): Boolean = history.halfMoveClock >= 100 + def fiftyMoves(history: History): Boolean = history.halfMoveClock >= HalfMoveClock(100) def isIrreversible(move: Move): Boolean = (move.piece.is(Pawn)) || move.captures || move.promotes || move.castles