diff --git a/js/src/test/scala/com/mogproject/mogami/bench/BenchmarkJS.scala b/js/src/test/scala/com/mogproject/mogami/bench/BenchmarkJS.scala index 93254fe..ead35a8 100644 --- a/js/src/test/scala/com/mogproject/mogami/bench/BenchmarkJS.scala +++ b/js/src/test/scala/com/mogproject/mogami/bench/BenchmarkJS.scala @@ -46,11 +46,49 @@ object BenchmarkJS extends scalajs.js.JSApp with Benchmark with TestData { val s4 = State.parseSfenString("4RB1k1/5s3/7n1/5s1LP/9/7r1/9/9/6K2 b b4g2s3n3l17p") // Karolina, mate in 13 val s5 = State.parseSfenString("k1+P4n1/2L+P2sL1/r4+P+P1P/+BpP+Pl1+Rg1/NP1S+PP+p1g/2L+p1g+P1+P/Ps1G1+P1N1/1sN1P4/B8 b -") // Kemuri val s6 = State.parseSfenString("g1+P1k1+P+P+L/1p3P3/+R+p2pp1pl/1NNsg+p2+R/+b+nL+P1+p3/1P3ssP1/2P1+Ps2N/4+P1P1L/+B5G1g b -") // Microcosmos, mate in 1535 + val s7 = State.parseSfenString("5n1k1/5p3/5s1p1/8N/7P1/9/9/9/9 b R2Br4g3s2n4l15p") // mate in 13 + val s8 = State.parseSfenString("5B1n1/8k/6Rpp/9/9/9/9/9/9 b rb4g4s3n4l16p") // mate in 5 involving Uchifuzume + val s9 = State.parseSfenString("5n1k1/5ps2/7p1/8N/7P1/9/9/9/9 b RBrb4g3s2n4l15p") // mate in 11 benchMateSolver(s1) benchMateSolver(s2) // benchMateSolver(s3) -// benchMateSolver(s4) + benchMateSolver(s4) // benchMateSolver(s5) // benchMateSolver(s6) + benchMateSolver(s8) + benchMateSolver(s9) } } + +/* + * Result + * + +[2017-05-14] Mac (2.9 GHz Intel Core i7) + +benchMateSolver + +- avg: 1.723s, min: 1.474s, max: 2.19s + +Some(List(5二金, 同玉, 5三金, 同玉, 5四と, 6二玉, 6三金, 5一玉, 5二金打)) +benchMateSolver + +- avg: 9.773s, min: 8.538s, max: 12.113s + +Some(List(3一飛, 2一香, 1二銀, 同玉, 2四桂, 1一玉, 1二香)) +benchMateSolver + +- avg: 74.166s, min: 73.511s, max: 74.967s + +Some(List(2三角成, 3一香, 3三桂, 同銀引, 同馬, 2三香, 3一飛成, 同銀, 1二銀, 同玉, 1三香, 2一玉, 1一香成)) +benchMateSolver + +- avg: 0.069s, min: 0.061s, max: 0.083s + +Some(List(2三角不成, 2二玉, 3二飛成, 1一玉, 1二角成)) +benchMateSolver + +- avg: 5.287s, min: 4.402s, max: 6.252s + +Some(List(3一飛, 1二玉, 3二飛成, 1三玉, 2四角, 1四玉, 1五銀, 2五玉, 3五竜, 1六玉, 2六竜)) + */ \ No newline at end of file diff --git a/jvm/src/debug/debug.sc b/jvm/src/debug/debug.sc index 0c903c9..ae5b6f3 100644 --- a/jvm/src/debug/debug.sc +++ b/jvm/src/debug/debug.sc @@ -9,9 +9,10 @@ val s3 = State.parseSfenString("1+P2Ss2l/1+S5b1/k1p4p1/1p+r1G2n1/p7p/P1N2S3/KPP1 val s4 = State.parseSfenString("4RB1k1/5s3/7n1/5s1LP/9/7r1/9/9/6K2 b b4g2s3n3l17p") // Karolina, mate in 13 val s5 = State.parseSfenString("k1+P4n1/2L+P2sL1/r4+P+P1P/+BpP+Pl1+Rg1/NP1S+PP+p1g/2L+p1g+P1+P/Ps1G1+P1N1/1sN1P4/B8 b -") // Kemuri val s6 = State.parseSfenString("g1+P1k1+P+P+L/1p3P3/+R+p2pp1pl/1NNsg+p2+R/+b+nL+P1+p3/1P3ssP1/2P1+Ps2N/4+P1P1L/+B5G1g b -") // Microcosmos, mate in 1535 +val s7 = State.parseSfenString("4R1lk1/5s3/6+B2/7rP/9/9/9/9/6K2 b Sb4g2s4n3l17p") -val r3 = MateSolver.solve(s3) -r3.get.map(_.toJapaneseNotationString) +val r7 = MateSolver.solve(s7) +r7.get.map(_.toJapaneseNotationString) //val r2 = MateSolver.solve(s2) //r2.get.map(_.toJapaneseNotationString) diff --git a/shared/src/main/scala/com/mogproject/mogami/core/game/Game.scala b/shared/src/main/scala/com/mogproject/mogami/core/game/Game.scala index b181899..4a36fdb 100644 --- a/shared/src/main/scala/com/mogproject/mogami/core/game/Game.scala +++ b/shared/src/main/scala/com/mogproject/mogami/core/game/Game.scala @@ -193,6 +193,13 @@ object Game extends CsaGameReader with SfenGameReader with KifGameReader { type Position = Int // regarding offset + // workaround for IntelliJ IDEA + override def parseSfenString(s: String)(implicit stateCache: StateCache): Game = super.parseSfenString(s) + override def parseUsenString(s: String)(implicit stateCache: StateCache): Game = super.parseUsenString(s) + override def parseKifString(nel: NonEmptyLines): Game = super.parseKifString(nel) + override def parseKi2String(nel: NonEmptyLines): Game = super.parseKi2String(nel) + override def parseCsaString(nel: NonEmptyLines): Game = super.parseCsaString(nel) + case class GamePosition(branch: BranchNo, position: Position) { require(branch >= 0, "branch must not be negative") require(position >= 0, "position must not be negative") diff --git a/shared/src/main/scala/com/mogproject/mogami/mate/MateSolver.scala b/shared/src/main/scala/com/mogproject/mogami/mate/MateSolver.scala index bab6de6..bfbb2a6 100644 --- a/shared/src/main/scala/com/mogproject/mogami/mate/MateSolver.scala +++ b/shared/src/main/scala/com/mogproject/mogami/mate/MateSolver.scala @@ -97,7 +97,9 @@ object MateSolver { findImmediateCheckmate(st, checkMoves) match { case Some(s) => // found an immediate checkmate - f(removeVerifiedThis(sofar), if (solution.isEmpty) mateSolverStateCache.set(s) :: sofar.map(_.head) else solution, isUnProven) + // println(s"im: ${depth + 1}") + // take a longer solution + f(removeVerifiedThis(sofar), if (solution.length <= depth) mateSolverStateCache.set(s) :: sofar.map(_.head) else solution, isUnProven) case None => if (checkMoves.isEmpty) { f(removeVerified(sofar), Nil, isUnProven = isUnProven) // no solution @@ -119,7 +121,9 @@ object MateSolver { if (mateSolverStateCache.get(sofar.tail.head.head).get.createMoveFromNextState(st).get.isPawnDrop) { f(removeParentNode(sofar), Nil, isUnProven) // Uchifuzume } else { - f(removeVerified(sofar), if (solution.isEmpty) sofar.map(_.head) else solution, isUnProven) + // found a solution + // println(s"fd: ${depth}") + f(removeVerified(sofar), if (solution.length < depth) sofar.map(_.head) else solution, isUnProven) } } else { // println(s"df ${depth}: " + sortMoves(legalMoves).map(_.toJapaneseNotationString)) diff --git a/shared/src/test/scala/com/mogproject/mogami/bench/Benchmark.scala b/shared/src/test/scala/com/mogproject/mogami/bench/Benchmark.scala index 918e4de..7adfeaf 100644 --- a/shared/src/test/scala/com/mogproject/mogami/bench/Benchmark.scala +++ b/shared/src/test/scala/com/mogproject/mogami/bench/Benchmark.scala @@ -95,7 +95,7 @@ trait Benchmark { var ret: Option[Seq[Move]] = None withBenchmark { - ret = MateSolver.solve(state, timeLimitMillis = 60000) + ret = MateSolver.solve(state, timeLimitMillis = 2 * 60 * 1000) }.print() println(ret.map(_.map(_.toJapaneseNotationString))) } diff --git a/shared/src/test/scala/com/mogproject/mogami/mate/MateSolverSpec.scala b/shared/src/test/scala/com/mogproject/mogami/mate/MateSolverSpec.scala index b85f5fb..32ff238 100644 --- a/shared/src/test/scala/com/mogproject/mogami/mate/MateSolverSpec.scala +++ b/shared/src/test/scala/com/mogproject/mogami/mate/MateSolverSpec.scala @@ -3,7 +3,6 @@ package com.mogproject.mogami.mate import com.mogproject.mogami._ import org.scalatest.prop.GeneratorDrivenPropertyChecks import org.scalatest.{FlatSpec, MustMatchers} -import com.mogproject.mogami.core.state.StateCache.Implicits._ /** * @@ -27,7 +26,8 @@ class MateSolverSpec extends FlatSpec with MustMatchers with GeneratorDrivenProp "4k4/9/4P4/9/9/9/9/9/9 b G2r2b3g4s4n4l17p", "9/9/7B1/6R2/3rg4/4k4/9/4PP3/9 b b3g4s4n4l16p", "6Rsk/7r1/8+P/9/9/9/9/9/9 b GN2b3g3s3n4l17p", - "5B1n1/8k/6Rpp/9/9/9/9/9/9 b rb4g4s3n4l16p" + "5B1n1/8k/6Rpp/9/9/9/9/9/9 b rb4g4s3n4l16p", + "4R1lk1/5s3/6+B2/7rP/9/9/9/9/6K2 b Sb4g2s4n3l17p" ).map(State.parseSfenString) MateSolver.solve(s(0)).map(_.map(_.toCsaString)) mustBe Some(List("+0052KI")) @@ -38,6 +38,7 @@ class MateSolverSpec extends FlatSpec with MustMatchers with GeneratorDrivenProp Some(List("+4123KA", "-1222OU", "+3332RY", "-2211OU", "+2312UM")), Some(List("+4123KA", "-1222OU", "+3332RY", "-2211OU", "+3212RY")) ).contains(MateSolver.solve(s(3)).map(_.map(_.toCsaString))) mustBe true + MateSolver.solve(s(4)).map(_.map(_.toCsaString)) mustBe Some(List("+5131RY", "-4231GI", "+0012GI", "-2112OU", "+0013KY", "-1221OU", "+1311NY")) } it must "return empty seq when there is no solution" in {