Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
791 changes: 791 additions & 0 deletions jvm/src/test/resources/csa/game/002.csa

Large diffs are not rendered by default.

779 changes: 779 additions & 0 deletions jvm/src/test/resources/ki2/game/005.ki2

Large diffs are not rendered by default.

263 changes: 263 additions & 0 deletions jvm/src/test/resources/kif/game/009.kif

Large diffs are not rendered by default.

783 changes: 783 additions & 0 deletions jvm/src/test/resources/kif/game/010.kif

Large diffs are not rendered by default.

22 changes: 20 additions & 2 deletions jvm/src/test/scala/com/mogproject/mogami/core/JVMGameSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ class JVMGameSpec extends FlatSpec with MustMatchers with GeneratorDrivenPropert

"Game#parseCsaString" must "create games from files" in StateCache.withCache { implicit cache =>
Game.parseCsaString(loadFile("csa/game/001.csa")).trunk.moves.length mustBe 111
val g002 = Game.parseCsaString(loadFile("csa/game/002.csa"))
g002.trunk.moves.length mustBe 258
g002.trunk.status mustBe GameStatus.Jishogi
}

"Game#parseKifString" must "create games from files" in StateCache.withCache { implicit cache =>
Expand Down Expand Up @@ -124,14 +127,29 @@ class JVMGameSpec extends FlatSpec with MustMatchers with GeneratorDrivenPropert
val s8 = loadFile("kif/game/008.kif")
Game.parseKifString(s8).trunk.moves.length mustBe 168

val s9 = loadFile("kif/mate/001.kif")
Game.parseKifString(s9).trunk.moves.length mustBe 59
// Sennichite
val s9 = loadFile("kif/game/009.kif")
val g009 = Game.parseKifString(s9)
g009.trunk.moves.length mustBe 85
g009.trunk.status mustBe GameStatus.Drawn

// Jishogi
val s10 = loadFile("kif/game/010.kif")
val g010 = Game.parseKifString(s10)
g010.trunk.moves.length mustBe 258
g010.trunk.status mustBe GameStatus.Jishogi

val m1 = loadFile("kif/mate/001.kif")
Game.parseKifString(m1).trunk.moves.length mustBe 59
}

"Game#parseKi2String" must "create games from files" in StateCache.withCache { implicit cache =>
Game.parseKi2String(loadFile("ki2/game/001.ki2")).trunk.moves.length mustBe 111
Game.parseKi2String(loadFile("ki2/game/002.ki2")).trunk.moves.length mustBe 111
Game.parseKi2String(loadFile("ki2/game/003.ki2")).trunk.moves.length mustBe 34
Game.parseKi2String(loadFile("ki2/game/004.ki2")).trunk.moves.length mustBe 27
val g005 = Game.parseKi2String(loadFile("ki2/game/005.ki2"))
g005.trunk.moves.length mustBe 258
g005.trunk.status mustBe GameStatus.Jishogi
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ case class Branch(initialHash: StateHash,
case Some(IllegalMove(_)) => IllegallyMoved
case Some(Resign(_)) => Resigned
case Some(TimeUp(_)) => TimedUp
case Some(DeclareWin(_)) => Jishogi
case _ =>
if (lastState.isMated) {
if (lastMove.exists(m => m.isCheck && m.isPawnDrop))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ object GameStatus {

case object Resigned extends GameStatus

case object Jishogi extends GameStatus
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ trait CsaGameReader extends CsaGameFactory[Game] {
val special = MoveBuilderCsa.parseTime(NonEmptyLines(pending)) match {
case ((Resign.csaKeyword, _), tm) => Resign(tm)
case ((TimeUp.csaKeyword, _), tm) => TimeUp(tm)
case ((DeclareWin.csaKeyword | DeclareWin.csaKeyword2, _), tm) => DeclareWin(tm)
case ((Pause.csaKeyword, _), _) => Pause
case _ => throw new RecordFormatException(n, s"unknown special move: ${x}")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,10 @@ trait KifBranchReader extends KifGameIO {
case ((Resign.kifKeyword, _), tm) => Some(Resign(tm))
case ((TimeUp.kifKeyword, _), tm) => Some(TimeUp(tm))
case ((TimeUp.kifKeyword2, _), tm) => Some(TimeUp(tm))
case ((DeclareWin.kifKeyword, _), tm) => Some(DeclareWin(tm))
case ((Pause.kifKeyword, _), _) => Some(Pause)
case ((s, _), _) if s.contains('詰') => None // ignore
case ((s, _), _) if s.contains("千日手") => None // ignore
case _ => throw new RecordFormatException(n, s"unknown special move: ${x}")
}
special.map(sp => sofar.copy(finalAction = Some(sp))).getOrElse(sofar)
Expand Down Expand Up @@ -264,7 +266,7 @@ trait KifGameReader extends KifBranchReader with KifGameIO with KifGameFactory[G
}

protected[io] def splitMovesKi2(lines: Lines): Lines = lines.flatMap {
case (x, n) if isNormalMoveKi2(x) => x.replaceAll("▲", " ▲").replaceAll("[△▽]", " △").split(" ").filter(_.nonEmpty).map((_, n))
case (x, n) if isNormalMoveKi2(x) => x.replaceAll("▲", " ▲").replaceAll("[△▽]", " △").replaceAll(" ", "").split(" ").filter(_.nonEmpty).map((_, n))
case _ => Seq.empty
}

Expand Down Expand Up @@ -350,17 +352,21 @@ trait KifGameReader extends KifBranchReader with KifGameIO with KifGameFactory[G
sofar.copy(finalAction = Some(IllegalMove(mv)))
case (Nil, None, Some((x, n))) => // ends with a special move except illegal move
val special = if (x.contains(TimeUp.ki2Keyword)) {
TimeUp()
Some(TimeUp())
} else if (x.contains(IllegalMove.ki2Keyword)) {
throw new RecordFormatException(n, s"unexpected illegal move: ${x}")
} else if (x.contains("勝ち")) {
Resign()
Some(Resign())
} else if (x.contains(Pause.ki2Keyword)) {
Pause
Some(Pause)
} else if (x.contains("千日手")) {
None
} else if (x.contains(DeclareWin.kifKeyword)) {
Some(DeclareWin())
} else {
throw new RecordFormatException(n, s"unknown special move: ${x}")
}
sofar.copy(finalAction = Some(special))
sofar.copy(finalAction = special)
case (Nil, None, None) => sofar // ends without errors
case ((x, n) :: xs, None, _) =>
val bldr = MoveBuilderKi2.parseKi2String(NonEmptyLines(n, x))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ object SpecialMove {
case Some(Resign.usenKeyword) => Resign()
case Some(TimeUp.usenKeyword) => TimeUp()
case Some(Pause.usenKeyword) => Pause
case Some(DeclareWin.usenKeyword) => DeclareWin()
case Some(IllegalMove.usenKeyword) =>
IllegalMove(MoveBuilderSfen.parseUsenString(s.drop(1)).toMove(lastState, lastMoveTo, isStrict = false).getOrElse(
throw new RecordFormatException(1, s"invalid illegal move: ${s.drop(1)}")
Expand Down Expand Up @@ -130,4 +131,32 @@ case object Pause extends SpecialMove {
override def toKi2String(currentPlayer: Player, numMoves: Int): String = makeKi2String(numMoves, ki2Keyword)
}

// todo: impl KACHI, [+-]ILLEGAL_ACTION

/**
* Declare win
*
* @param elapsedTime elapsed time
*/
case class DeclareWin(elapsedTime: Option[Int] = None) extends SpecialMove {
override def toCsaString: String = DeclareWin.csaKeyword + timeToCsaString(elapsedTime)

override def toKifString: String = DeclareWin.kifKeyword + timeToKifString(elapsedTime)

override def toUsenString: String = DeclareWin.usenKeyword.toString

override def toJapaneseNotationString: String = DeclareWin.kifKeyword

override def toWesternNotationString: String = "Declare Win"

override def toKi2String(currentPlayer: Player, numMoves: Int): String = makeKi2String(numMoves, DeclareWin.kifKeyword)

}

object DeclareWin {
val csaKeyword = "%JISHOGI"
val csaKeyword2 = "%KACHI"
val kifKeyword = "持将棋"
val usenKeyword = 'j'
}

// todo: impl [+-]ILLEGAL_ACTION