Files
gambit/TimeControl.scala

58 lines
2.3 KiB
Scala

package gambit
object TimeControl:
val defaultMovesToGo = 30
val overheadMs = 25L
val maxDepth = 64
final case class Limits(
wtime: Long = -1L,
btime: Long = -1L,
winc: Long = 0L,
binc: Long = 0L,
movestogo: Int = 0,
movetime: Long = -1L,
depth: Int = -1,
infinite: Boolean = false
):
def hasClock: Boolean = wtime >= 0L || btime >= 0L
final case class Plan(depth: Int, timeMs: Long)
def plan(limits: Limits, whiteToMove: Boolean): Plan =
val depth = if limits.depth > 0 then math.min(limits.depth, maxDepth) else maxDepth
val time = budgetMs(limits, whiteToMove)
Plan(depth, time)
def budgetMs(limits: Limits, whiteToMove: Boolean): Long =
if limits.infinite then 0L
else if limits.movetime > 0L then math.max(1L, limits.movetime - overheadMs)
else if limits.hasClock then
val myTime = if whiteToMove then limits.wtime else limits.btime
val myInc = if whiteToMove then limits.winc else limits.binc
if myTime <= 0L then math.max(1L, myInc - overheadMs)
else
val moves = if limits.movestogo > 0 then limits.movestogo else defaultMovesToGo
val base = myTime / moves + myInc * 3L / 4L
val hardCap = math.max(1L, (myTime * 4L) / 5L)
val budget = math.min(base, hardCap)
math.max(1L, budget - overheadMs)
else 0L
def parse(tokens: List[String]): Limits =
var limits = Limits()
var rest = tokens
while rest.nonEmpty do
rest match
case "wtime" :: v :: tail => limits = limits.copy(wtime = v.toLong); rest = tail
case "btime" :: v :: tail => limits = limits.copy(btime = v.toLong); rest = tail
case "winc" :: v :: tail => limits = limits.copy(winc = v.toLong); rest = tail
case "binc" :: v :: tail => limits = limits.copy(binc = v.toLong); rest = tail
case "movestogo" :: v :: tail => limits = limits.copy(movestogo = v.toInt); rest = tail
case "movetime" :: v :: tail => limits = limits.copy(movetime = v.toLong); rest = tail
case "depth" :: v :: tail => limits = limits.copy(depth = v.toInt); rest = tail
case "infinite" :: tail => limits = limits.copy(infinite = true); rest = tail
case _ :: tail => rest = tail
case Nil => rest = Nil
limits