/// <summary> /// KIF/KI2形式の指し手を与えて、Moveに変換する。指し手の合法性のチェックはここでは行わない。 /// 変換に失敗したときはMove.NONEが返る。 /// </summary> /// <param name="pos"></param> /// <param name="kifMove"></param> /// <returns></returns> public static Move FromKif(this Position pos, string kifMove) { // match.Group[1]: ([▲△▼▽☗☖⛊⛉]?) // match.Group[2]: ([1-9123456789一二三四五六七八九]{2}同?) // match.Group[3]: (同) // match.Group[4]: ([歩香桂銀金角飛玉王と杏圭全馬竜龍]|成[香桂銀]) // match.Group[5]: ([右左]?[上寄引]?|直) // match.Group[6]: (成|不成|打)? // match.Group[7]: (\([1-9]{2}\))? Match match = new Regex(@"([▲△▼▽☗☖⛊⛉]?)(?:([1-9123456789一二三四五六七八九]{2}同?)|(同))[ ]*([歩香桂銀金角飛玉王と杏圭全馬竜龍]|成[香桂銀])(直|[右左]?[上寄引]?)(成|不成|打)?(\([1-9]{2}\))?").Match(kifMove); if (!match.Success) { return(Move.NONE); } Color c0 = pos.sideToMove; Color c1 = FromColor(match.Groups[1].Value); Square sq0; Square sq1 = match.Groups[3].Value == "同" ? pos.State().lastMove.To() : FromSquare(match.Groups[2].Value); if (sq1 == Square.NB) { return(Move.NONE); } Piece pt1 = FromKifPieceType(match.Groups[4].Value); // 駒打ち if (match.Groups[6].Value == "打") { return(Util.MakeMoveDrop(pt1, sq1)); } // 成チェック bool isPromote = (match.Groups[6].Value == "成"); // KIF形式で元座標が示されている場合 if (match.Groups[7].Value.Length == 4) { sq0 = FromSquare(match.Groups[7].Value.Substring(1, 2)); return(isPromote ? Util.MakeMovePromote(sq0, sq1) : Util.MakeMove(sq0, sq1)); } // KI2棋譜用処理 // 駒の移動範囲を調べるため、着手前の駒を求める Piece pt0 = isPromote ? pt1.RawPieceType() : pt1; Bitboard sameBB = pos.AttackersTo(c0, sq1) & pos.Pieces(c0, pt0); if (sameBB.IsZero()) { return(Move.NONE); } if (sameBB.IsOne()) { sq0 = sameBB.Pop(); return(isPromote ? Util.MakeMovePromote(sq0, sq1) : Util.MakeMove(sq0, sq1)); } Bitboard bb; switch (match.Groups[5].Value) { case "右": sq0 = rightMost(c0, sameBB); break; case "左": sq0 = leftMost(c0, sameBB); break; case "直": bb = (KifUtil.lineDirBB(c0, sq1, Direct.D) & sameBB); if (!bb.IsOne()) { return(Move.NONE); } sq0 = bb.Pop(); break; case "上": bb = (KifUtil.dirBB(c0, sq1, Direct.D) & sameBB); if (!bb.IsOne()) { return(Move.NONE); } sq0 = bb.Pop(); break; case "引": bb = (KifUtil.dirBB(c0, sq1, Direct.U) & sameBB); if (!bb.IsOne()) { return(Move.NONE); } sq0 = bb.Pop(); break; case "寄": bb = (Bitboard.RankBB(sq1.ToRank()) & sameBB); if (!bb.IsOne()) { return(Move.NONE); } sq0 = bb.Pop(); break; case "右上": bb = (KifUtil.dirBB(c0, sq1, Direct.D) & sameBB); sq0 = rightMost(c0, bb); break; case "左上": bb = (KifUtil.dirBB(c0, sq1, Direct.D) & sameBB); sq0 = leftMost(c0, bb); break; case "右引": bb = (KifUtil.dirBB(c0, sq1, Direct.U) & sameBB); sq0 = rightMost(c0, bb); break; case "左引": bb = (KifUtil.dirBB(c0, sq1, Direct.U) & sameBB); sq0 = leftMost(c0, bb); break; case "右寄": bb = (Bitboard.RankBB(sq1.ToRank()) & sameBB); sq0 = rightMost(c0, bb); break; case "左寄": bb = (Bitboard.RankBB(sq1.ToRank()) & sameBB); sq0 = leftMost(c0, bb); break; default: return(Move.NONE); } if (sq0 == Square.NB) { return(Move.NONE); } return(isPromote ? Util.MakeMovePromote(sq0, sq1) : Util.MakeMove(sq0, sq1)); }
static string fromSqFormat_KI2(Position pos, Move move) { Color c = pos.sideToMove; Square fromSq = move.From(), toSq = move.To(); Piece p = pos.PieceOn(fromSq), pt = p.PieceType(); Bitboard sameBB = pos.AttackersTo(c, toSq) & pos.Pieces(c, pt); if (!sameBB.IsSet(fromSq)) { return(""); } if (sameBB.IsOne()) { return(""); } if (KifUtil.checkBB(sameBB, Bitboard.RankBB(toSq.ToRank()), fromSq)) { return("寄"); } if (KifUtil.checkBB(sameBB, KifUtil.dirBB(c, toSq, Direct.D), fromSq)) { return("上"); } if (KifUtil.checkBB(sameBB, KifUtil.dirBB(c, toSq, Direct.U), fromSq)) { return("引"); } if (KifUtil.checkBB(sameBB, KifUtil.lineDirBB(c, toSq, Direct.D), fromSq) && ( pt == Piece.SILVER || pt == Piece.GOLD || pt == Piece.PRO_PAWN || pt == Piece.PRO_LANCE || pt == Piece.PRO_KNIGHT || pt == Piece.PRO_SILVER )) { return("直"); } if (KifUtil.checkBB(sameBB, KifUtil.dirOrBB(c, fromSq, Direct.L), fromSq)) { return("左"); } if (KifUtil.checkBB(sameBB, KifUtil.dirOrBB(c, fromSq, Direct.R), fromSq)) { return("右"); } if (KifUtil.checkBB(sameBB, KifUtil.lineDirOrBB(c, fromSq, Direct.L) & Bitboard.RankBB(toSq.ToRank()), fromSq)) { return("左寄"); } if (KifUtil.checkBB(sameBB, KifUtil.lineDirOrBB(c, fromSq, Direct.R) & Bitboard.RankBB(toSq.ToRank()), fromSq)) { return("右寄"); } if (KifUtil.checkBB(sameBB, KifUtil.dirBB(c, toSq, Direct.D) & KifUtil.dirOrBB(c, fromSq, Direct.L), fromSq)) { return("左上"); } if (KifUtil.checkBB(sameBB, KifUtil.dirBB(c, toSq, Direct.D) & KifUtil.dirOrBB(c, fromSq, Direct.R), fromSq)) { return("右上"); } if (KifUtil.checkBB(sameBB, KifUtil.dirBB(c, toSq, Direct.U) & KifUtil.dirOrBB(c, fromSq, Direct.L), fromSq)) { return("左引"); } if (KifUtil.checkBB(sameBB, KifUtil.dirBB(c, toSq, Direct.U) & KifUtil.dirOrBB(c, fromSq, Direct.R), fromSq)) { return("右引"); } // 正常な局面・指し手でここに到達する筈は無い return(""); }