format.usi.Usi.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of scalashogi_2.13 Show documentation
Show all versions of scalashogi_2.13 Show documentation
Shogi API written in scala. Immutable and free of side effects.
package shogi
package format.usi
import cats.implicits._
sealed trait Usi {
def usi: String
def positions: List[Pos]
}
object Usi {
final case class Move(
orig: Pos,
dest: Pos,
promotion: Boolean = false,
midStep: Option[Pos] = None
) extends Usi {
def keys = orig.key + midStep.fold("")(_.key) + dest.key
def usi = keys + promotionString
def promotionString = if (promotion) "+" else ""
def positions = midStep.fold(List(orig, dest))(List(orig, _, dest))
}
object Move {
private val MoveRegex = """(\d\d?[a-l])(\d\d?[a-l])?(\d\d?[a-l])(\+|=|\?)?""".r
def apply(str: String): Option[Move] =
str match {
case MoveRegex(origS, midStepS, destS, promS) =>
for {
orig <- Pos.allKeys get origS
dest <- Pos.allKeys get destS
prom = promS == "+"
midStep = Option(midStepS).flatMap(Pos.allKeys get _)
} yield Move(orig, dest, prom, midStep)
case _ => None
}
}
final case class Drop(role: DroppableRole, pos: Pos) extends Usi {
def usi = s"${Drop.roleToUsi(role)}*${pos.key}"
def positions = List(pos)
}
object Drop {
def apply(str: String): Option[Drop] =
for {
role <- usiToRole get str.take(1)
pos <- Pos.allKeys get (str.drop(2))
} yield Drop(role, pos)
val roleToUsi: Map[DroppableRole, String] = Map(
Pawn -> "P",
Lance -> "L",
Knight -> "N",
Silver -> "S",
Gold -> "G",
Bishop -> "B",
Rook -> "R"
)
val usiToRole: Map[String, DroppableRole] = roleToUsi map { case (k, v) => v -> k }
}
final case class WithRole(usi: Usi, role: Role)
def apply(usiStr: String): Option[Usi] =
if (usiStr contains '*')
Usi.Drop(usiStr)
else Usi.Move(usiStr)
def readList(moves: String): Option[List[Usi]] =
readList(moves.split(' ').toList)
def readList(moves: Seq[String]): Option[List[Usi]] =
moves.toList.map(apply).sequence
}