/// <summary> /// 盤面比較 /// </summary> /// <param name="pos"></param> /// <returns></returns> public bool Equals(SPosition pos) { for (int i = 0; i < Square.NSQUARE; i++) { if (this.board[i] != pos.board[i]) { return(false); } } for (int i = 0; i < this.blackHand.Length; i++) { if (this.blackHand[i] != pos.blackHand[i]) { return(false); } } for (int i = 0; i < this.whiteHand.Length; i++) { if (this.whiteHand[i] != pos.whiteHand[i]) { return(false); } } if (this.turn != pos.turn) { return(false); } return(true); }
private static void ReadGikouBook(SBook book, GikouBook gbook ,SPosition pos) { long key = ExportGikouBook.ComputeKey(pos, gbook); SBookState state = book.GetBookState(pos.PositionToString(1)); if (state != null && state.Moves.Count != 0) { // すでに登録されてる? return; } // 局面登録 book.Add(pos, null, 0, 0, 0); List<GikouBookEntry> entrys = gbook.GetEntry(key); if (entrys != null) { foreach (GikouBookEntry en in entrys) { MoveData move = ConvertMove(pos.Turn, en.Move); book.Add(pos, move, (int)en.Frequency, en.Score, 1); } foreach (GikouBookEntry en in entrys) { MoveData move = ConvertMove(pos.Turn, en.Move); pos.Move(move); ReadGikouBook(book, gbook, pos); pos.UnMove(move, null); } } }
/// <summary> /// 指し手の出力 /// </summary> /// <param name="bookstate"></param> /// <param name="position"></param> /// <param name="aperyBook"></param> private static void WriteMoves(SBookState bookstate, SPosition position, AperyBook aperyBook) { if (bookstate == null) { return; } if (bookstate.Count != 0) { return; // 既に出力した } bookstate.Count++; foreach (SBookMove move in bookstate.Moves) { if (move.Weight != 0) { aperyBook.Add(GetKey(position), move.ConvFromToPro(), move.Weight); } MoveData moveData = move.GetMoveData(); if (position.Move(moveData)) { // 再帰呼び出し WriteMoves(move.NextState, position, aperyBook); position.UnMove(moveData, null); } } }
/// <summary> /// SBookをAperyBookに変換して保存する /// </summary> /// <param name="book"></param> /// <param name="filename"></param> public static void ExportApery(this SBook book, string filename) { // 初期局面の出力 AperyBook aperyBook = new AperyBook(); SPosition position = new SPosition(); book.ClearCount(); int cnt = 0; foreach (SBookState state in book.BookStates) { if (state.Position != string.Empty) { // 局面が入っている場合 Sfen.PositionFromString(position, state.Position); } // 指し手出力 if (state.Count == 0 && ((state.Id == 0) || (state.Position != string.Empty))) { WriteMoves(state, position, aperyBook); } cnt++; } aperyBook.Save(filename); }
/// <summary> /// 局面のハッシュキーを取得 /// </summary> /// <param name="position"></param> /// <param name="gikouBook"></param> /// <returns></returns> public static long ComputeKey(SPosition position, GikouBook gikouBook) { long key = 0; SPosition pos = (SPosition)position.Clone(); // 後手番であれば、将棋盤を180度反転して、先手番として扱う if (pos.Turn == PlayerColor.White) { pos.Flip(); } // 盤上の駒 int gikout_sq = 0; foreach (var sq in squareTable) { key += gikouBook.HashSeeds.GetPsq((int)pos.GetPiece(sq), gikout_sq); gikout_sq += 1; } // 持ち駒 foreach (PlayerColor color in new PlayerColor[] { PlayerColor.Black, PlayerColor.White }) { for (int pt = 1; pt < SPosition.HandMax; pt++) { for (int n = pos.GetHand(color, (PieceType)pt); n > 0; n--) { key += gikouBook.HashSeeds.GetHand((int)color, pt); } } } return(key); }
private static void ReadGikouBook(SBook book, GikouBook gbook, SPosition pos) { long key = ExportGikouBook.ComputeKey(pos, gbook); SBookState state = book.GetBookState(pos.PositionToString(1)); if (state != null && state.Moves.Count != 0) { // すでに登録されてる? return; } // 局面登録 book.Add(pos, null, 0, 0, 0); List <GikouBookEntry> entrys = gbook.GetEntry(key); if (entrys != null) { foreach (GikouBookEntry en in entrys) { MoveData move = ConvertMove(pos.Turn, en.Move); book.Add(pos, move, (int)en.Frequency, en.Score, 1); } foreach (GikouBookEntry en in entrys) { MoveData move = ConvertMove(pos.Turn, en.Move); pos.Move(move); ReadGikouBook(book, gbook, pos); pos.UnMove(move, null); } } }
/// <summary> /// SBookをGikou形式に変換して保存する /// </summary> /// <param name="book"></param> /// <param name="filename"></param> public static void ExportGikou(this SBook book, string filename) { // GikouBook gikouBook = new GikouBook(); { SPosition position = new SPosition(); book.ClearCount(); int cnt = 0; foreach (SBookState state in book.BookStates) { if (state.Count == 0 && ((state.Id == 0) || (state.Position != string.Empty))) { if (state.Position != string.Empty) { Sfen.PositionFromString(position, state.Position); } // 指し手の出力 ルートからの局面以外はやねうら王2016には正しく認識されない WriteMoves(state, position, gikouBook); } cnt++; } } gikouBook.Save(filename); }
/// <summary> /// SBookをYaneuraou book形式に変換して保存する /// </summary> /// <param name="book"></param> /// <param name="filename"></param> public static void ExportYaneuraOUbook(this SBook book, string filename) { // using (StreamWriter wr = new StreamWriter(filename, false, Encoding.UTF8)) { wr.WriteLine("#YANEURAOU-DB2016 1.00"); SPosition position = new SPosition(); book.ClearCount(); int cnt = 0; foreach (SBookState state in book.BookStates) { if (state.Count == 0 && ((state.Id == 0) || (state.Position != string.Empty))) { if (state.Position != string.Empty) { Sfen.PositionFromString(position, state.Position); } // 指し手の出力 ルートからの局面以外はやねうら王2016には正しく認識されない WriteMoves(state, position, wr, 1); } cnt++; } } }
/// <summary> /// SPositionからApery用のハッシュキーを取得 /// </summary> /// <param name="position"></param> /// <returns></returns> private static ulong GetKey(SPosition pos) { ulong key = 0; // 盤上の駒 for (AperySquare ap = AperySquare.I9; ap < AperySquare.SquareNum; ap++) { int sq = Square.Make(ap.FileOf(), ap.RankOf()); Piece piece = pos.GetPiece(sq); if (piece != Piece.NoPiece) { int index = (int)piece.ConvAperyPiece(); key ^= AperyBook.ZobPiece[index][(int)ap]; } } // 持ち駒 for (PieceType pt = PieceType.FU; pt < PieceType.King; pt++) { int num = pos.GetHand(pos.Turn, pt); key ^= AperyBook.ZobHand[(int)pt - 1][num]; } if (pos.Turn == PlayerColor.White) { key ^= AperyBook.ZobTurn; } return(key); }
/// <summary> /// 局面追加 /// </summary> public void Add(SPosition pos, MoveData moveData, int weight, int value, int depth) { string key = pos.PositionToString(1); SBookState state = this.GetBookState(key); if (state == null) { // 現在の局面がない場合 state = new SBookState(); state.Games = 1; state.WonBlack = 0; state.WonWhite = 0; state.Position = key; this.books.Add(key, state); this.BookStates.Add(state); } if (moveData != null) { pos.Move(moveData); string next_key = pos.PositionToString(1); SBookState next_state = this.GetBookState(next_key); pos.UnMove(moveData, null); if (next_state == null) { next_state = new SBookState(); next_state.Games = 1; next_state.WonBlack = 0; next_state.WonWhite = 0; next_state.Position = next_key; this.books.Add(next_key, next_state); this.BookStates.Add(next_state); } SBookMove m = new SBookMove(moveData, next_state); SBookMove move = state.GetMove(m); if (move == null) { // 指し手が無い場合は追加 m.Weight = weight; m.Value = value; m.Depth = depth; state.AddMove(m); // next_stateのPositionをクリアする next_state.Position = string.Empty; move = m; } } }
/// <summary> /// 盤面出力 /// </summary> /// <param name="notation"></param> /// <returns></returns> public static string PositionToString(this SPosition position, int num) { string sfen = string.Empty; using (StringWriter wr = new StringWriter()) { WritePosition(position, wr, num); sfen = wr.ToString(); } return(sfen); }
/// <summary> /// 指し手の出力 /// </summary> /// <param name="bookstate"></param> /// <param name="position"></param> /// <param name="aperyBook"></param> private static void WriteMoves(SBookState bookstate, SPosition position, GikouBook gikouBook) { if (bookstate == null) { return; } if (bookstate.Count != 0) { return; // 既に出力した } bookstate.Count++; int count = 0; foreach (SBookMove move in bookstate.Moves) { if (move.Weight != 0) { count++; } } if (count != 0) { long key = ComputeKey(position, gikouBook); foreach (SBookMove move in bookstate.Moves) { if (move.Weight != 0) { gikouBook.Add(key, (uint)move.Weight, (uint)move.Weight, move.Value, move.ConvertGikouMove()); } } } foreach (SBookMove move in bookstate.Moves) { // 指し手の出力 MoveData moveData = move.GetMoveData(); if (position.Move(moveData)) { // 再帰呼び出し WriteMoves(move.NextState, position, gikouBook); position.UnMove(moveData, null); } } }
/// <summary> /// sfen形式の棋譜読み込み /// </summary> /// <param name="notation"></param> /// <param name="sr"></param> public static void ReadNotation(SPosition pos, string str) { Tokenizer tok = new Tokenizer(str); string token; token = tok.Token(); if (token == "position") { token = tok.Token(); } if (token == "startpos") { // 処理なし } else if (token == "sfen") { Sfen.ReadPosition(pos, tok.TokenPosition()); } else if (token == "moves") { tok.Push(token); } else { } token = tok.Token(); if (token == "moves") { while ((token = tok.Token()) != string.Empty) { MoveData moveData = ParseMove(pos, token); if (moveData == null) { break; } if (!pos.Move(moveData)) { break; } } } }
public static SBook Import(string filename) { SBook book = new SBook(); SPosition pos = new SPosition(); try { GikouBook gbook = new GikouBook(filename); ReadGikouBook(book, gbook, pos); } catch (Exception ex) { throw ex; } return(book); }
public static SBook Import(string filename) { SBook book = new SBook(); SPosition pos = new SPosition(); try { GikouBook gbook = new GikouBook(filename); ReadGikouBook(book, gbook, pos); } catch (Exception ex) { throw ex; } return book; }
/// <summary> /// 指し手文字列をパースして指し手を返す /// </summary> public static MoveData ParseMove(SPosition position, string move) { if (move == "resign") { return new MoveData(MoveType.Resign); } else if (move == "win") { // 反則勝ち return new MoveData(MoveType.WinNyugyoku); } else if (move == "draw") { return new MoveData(MoveType.Draw); } else if (move == "pass" || move == "0000") { // uci的には0000でgpsはpass return new MoveData(MoveType.Pass); } if (move.Length < 4) { return null; } MoveData moveData = new MoveData(); if (move[1] == '*') { // 打つ手 moveData.MoveType = MoveType.Drop; PieceType pieceType; if (CharToPieceHashtable.TryGetValue((char)move[0], out pieceType)) { moveData.Piece = (Piece)pieceType | PieceExtensions.PieceFlagFromColor(position.Turn); } else { // 不明な文字列 moveData.Piece = Piece.NoPiece; } int file = FileFromChar(move[2]); int rank = RankFromChar(move[3]); if (file < 0 || rank < 0) { return null; } moveData.ToSquare = Square.Make(file, rank); } else { // 移動 moveData.MoveType = MoveType.Normal; // from int file = FileFromChar(move[0]); int rank = RankFromChar(move[1]); moveData.FromSquare = Square.Make(file, rank); file = FileFromChar(move[2]); rank = RankFromChar(move[3]); if (file < 0 || rank < 0) { return null; } moveData.ToSquare = Square.Make(file, rank); moveData.Piece = position.GetPiece(moveData.FromSquare); if (move.Length >= 5 && move[4] == '+') { // 成り moveData.MoveType = MoveType.Promotion; } } // 盤面を進める if (moveData.MoveType.IsMoveWithoutPass()) { // 指し手の場合 if (position.MoveLast.MoveType.IsMove() && moveData.ToSquare == position.MoveLast.ToSquare) { moveData.MoveType |= MoveType.Same; // 同ほげ用のフラグ設定 } if (position.GetPiece(moveData.ToSquare) != Piece.NoPiece) { moveData.MoveType |= MoveType.Capture; // 駒とったフラグ設定 moveData.CapturePiece = position.GetPiece(moveData.ToSquare); // 駒をいれる } } return moveData; }
///////////////////////////////////////////////////////////////////// /// <summary> /// sfen形式の盤情報を読み込み /// </summary> /// <param name="notation"></param> /// <param name="sr"></param> private static int ReadPosition(SPosition position, string sfen, int index = 0) { int file, rank; int ch; Piece piece; int piece_num; SPosition pos = position; file = 0; rank = 0; if (sfen != string.Empty) { pos.BoardClear(); } // 局面データ while (index < sfen.Length) { ch = sfen[index]; index++; if (ch == ' ') { break; } if (ch == '/') { // 段の区切り file = 0; rank += 1; if (rank >= Square.NRANK) { break; } } else if (ch >= '0' && ch <= '9') { // 数字は駒がないところ file += ch - '0'; } else { piece = Piece.NoPiece; // なり if (ch == '+') { piece |= Piece.PromotionFlag; if (index < sfen.Length) { ch = sfen[index]; index++; if (ch == ' ') { break; } } else { break; } } // 後手 if (ch >= 'a' && ch <= 'z') { piece |= Piece.WhiteFlag; ch = char.ToUpper((char)ch); } // charをPiece変換 PieceType pieceType; if (CharToPieceHashtable.TryGetValue((char)ch, out pieceType)) { piece |= (Piece)pieceType; } else { // 不明な文字列 Debug.Print("parse error"); piece = Piece.NoPiece; } if (piece.TypeOf() != PieceType.NoPieceType) { // 駒がある if (file < Square.NFILE) { pos.SetPiece(file, rank, piece); file++; } } } } // 手番 while (index < sfen.Length) { ch = sfen[index]; index++; if (ch == ' ') { break; } if (ch == 'w') { pos.Turn = PlayerColor.White; } else if (ch == 'b') { pos.Turn = PlayerColor.Black; } } // 持ち駒 while (index < sfen.Length) { ch = sfen[index]; index++; if (ch == ' ') { break; } piece_num = 1; // 枚数 if (ch >= '0' && ch <= '9') { piece_num = ch - '0'; if (index < sfen.Length) { ch = sfen[index]; index++; } else { break; } if (ch == ' ') { break; } else if (ch >= '0' && ch <= '9') { piece_num = (piece_num * 10) + (ch - '0'); if (index < sfen.Length) { ch = sfen[index]; index++; } else { break; } if (ch == ' ') { break; } } } PieceType piece_type; if (CharToPieceHashtable.TryGetValue(char.ToUpper((char)ch), out piece_type)) { if (char.IsUpper((char)ch)) { // 大文字は先手 pos.SetBlackHand(piece_type, piece_num); } else { // 後手 pos.SetWhiteHand(piece_type, piece_num); } } } // n手目 (読み飛ばす while (index < sfen.Length) { ch = sfen[index]; index++; if (ch == ' ') { break; } } return index; }
/// <summary> /// 指し手の出力 /// </summary> /// <param name="bookstate"></param> /// <param name="position"></param> /// <param name="aperyBook"></param> private static void WriteMoves(SBookState bookstate, SPosition position, AperyBook aperyBook) { if (bookstate == null) { return; } if (bookstate.Count != 0) { return; // 既に出力した } bookstate.Count++; foreach (SBookMove move in bookstate.Moves) { if (move.Weight != 0) { aperyBook.Add(GetKey(position), move.ConvFromToPro(), move.Weight); } MoveData moveData = move.GetMoveData(); position.Move(moveData); // 再帰呼び出し WriteMoves(move.NextState, position, aperyBook); position.UnMove(moveData, null); } }
/// <summary> /// SPositionからApery用のハッシュキーを取得 /// </summary> /// <param name="position"></param> /// <returns></returns> private static ulong GetKey(SPosition pos) { ulong key = 0; // 盤上の駒 for (AperySquare ap = AperySquare.I9; ap < AperySquare.SquareNum; ap++) { int sq = Square.Make(ap.FileOf(), ap.RankOf()); Piece piece = pos.GetPiece(sq); if (piece != Piece.NoPiece) { int index = (int)piece.ConvAperyPiece(); key ^= AperyBook.ZobPiece[index][(int)ap]; } } // 持ち駒 for (PieceType pt = PieceType.FU; pt < PieceType.King; pt++) { int num = pos.GetHand(pos.Turn, pt); key ^= AperyBook.ZobHand[(int)pt - 1][num]; } if (pos.Turn == PlayerColor.White) { key ^= AperyBook.ZobTurn; } return key; }
/// <summary> /// 指し手の出力 /// </summary> /// <param name="bookstate"></param> /// <param name="position"></param> /// <param name="aperyBook"></param> private static void WriteMoves(SBookState bookstate, SPosition position, StreamWriter wr, int depth) { if (bookstate == null) { return; } if (bookstate.Count != 0) { return; // 既に出力した } int count = 0; foreach (SBookMove move in bookstate.Moves) { if (move.Weight != 0) { count++; } } bookstate.Count++; if (count != 0) { // 局面の出力 wr.WriteLine("sfen " + position.PositionToString(depth)); foreach (SBookMove move in bookstate.Moves) { if (move.Weight != 0) { // 指し手の出力 MoveData moveData = move.GetMoveData(); string next_str = "none"; SBookMove next_move = GetNextMove(move.NextState); if (next_move != null) { MoveData nextMoveData = next_move.GetMoveData(); next_str = Sfen.MoveToString(nextMoveData); } wr.WriteLine("{0} {1} {3} {4} {2}", Sfen.MoveToString(moveData), next_str, move.Weight, move.Value, move.Depth); } } } foreach (SBookMove move in bookstate.Moves) { // 指し手の出力 MoveData moveData = move.GetMoveData(); if (position.Move(moveData)) { // 再帰呼び出し WriteMoves(move.NextState, position, wr, depth + 1); position.UnMove(moveData, null); } } }
/// <summary> /// 局面の出力 /// </summary> /// <param name="position"></param> /// <param name="sr"></param> private static void WritePosition(SPosition position, TextWriter wr, int movenumber) { int sq = 0; int space = 0; // 盤面出力 for (int rank = 0; rank < Square.NRANK; rank++) { // 段の切り替わりで/を出力 if (rank != 0) { wr.Write('/'); } for (int file = 0; file < Square.NFILE; file++, sq++) { Piece piece = position.GetPiece(sq); char ch; if (piece == Piece.NoPiece) { space++; } else { if (space != 0) { wr.Write(space); space = 0; } if (piece.IsPromoted()) { // 成り wr.Write('+'); } ch = CharFromPieceType(piece.TypeOf()); if (piece.HasFlag(Piece.WhiteFlag)) { ch = char.ToLower(ch); } wr.Write(ch); } } if (space != 0) { wr.Write(space); space = 0; } } // 手番の出力 if (position.Turn == PlayerColor.White) { wr.Write(" w "); } else { wr.Write(" b "); } // 持ち駒の出力 int hand_cnt = 0; for (PieceType pt = PieceType.HI; pt > PieceType.NoPieceType; pt--) { int num = position.GetBlackHand(pt); if (num != 0) { if (num > 1) { wr.Write(num); } wr.Write(CharFromPieceType(pt)); hand_cnt++; } } for (PieceType pt = PieceType.HI; pt > PieceType.NoPieceType; pt--) { int num = position.GetWhiteHand(pt); if (num != 0) { if (num > 1) { wr.Write(num); } char ch = CharFromPieceType(pt); ch = char.ToLower(ch); // 後手は小文字 wr.Write(ch); hand_cnt++; } } if (hand_cnt == 0) { wr.Write("-"); } if (movenumber != 0) { wr.Write(" {0}", movenumber); // 手数 実際には次が何手目か } }
public static SBook ImportYaneuraOu(string filename) { SBook book = new SBook(); try { using (StreamReader sr = new StreamReader(filename)) { string line; SPosition pos = new SPosition(); book.Add(pos, null, 0, 0, 0); // 平手初期局面をいれる while ((line = sr.ReadLine()) != null) { if (line.StartsWith("sfen") || line.StartsWith("startpos") || line.StartsWith("position")) { Sfen.ReadNotation(pos, line); } else if (line.StartsWith("#") || line.StartsWith("//")) { // コメント } else { string[] str_array = line.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); if (str_array.Length >= 5) { MoveData move = Sfen.ParseMove(pos, str_array[0]); if (move.Piece == Piece.NoPiece || pos.GetPiece(move.ToSquare).ColorOf() == move.Piece.ColorOf()) { Debug.WriteLine("bb"); } if (move != null && move.MoveType.IsMoveWithoutPass()) { int weight; int depth = 0; int value = 0; int.TryParse(str_array[2], out value); int.TryParse(str_array[3], out depth); if (int.TryParse(str_array[4], out weight)) { // 指し手の追加 book.Add(pos, move, weight, value, depth); } } } } } } // idの付け直し book.SetIds(); } catch (Exception ex) { throw ex; } return(book); }
/// <summary> /// 指し手文字列をパースして指し手を返す /// </summary> public static MoveData ParseMove(SPosition position, string move) { if (move == "resign") { return(new MoveData(MoveType.Resign)); } else if (move == "win") { // 反則勝ち return(new MoveData(MoveType.WinNyugyoku)); } else if (move == "draw") { return(new MoveData(MoveType.Draw)); } else if (move == "pass" || move == "0000") { // uci的には0000でgpsはpass return(new MoveData(MoveType.Pass)); } if (move.Length < 4) { return(null); } MoveData moveData = new MoveData(); if (move[1] == '*') { // 打つ手 moveData.MoveType = MoveType.Drop; PieceType pieceType; if (CharToPieceHashtable.TryGetValue((char)move[0], out pieceType)) { moveData.Piece = (Piece)pieceType | PieceExtensions.PieceFlagFromColor(position.Turn); } else { // 不明な文字列 moveData.Piece = Piece.NoPiece; } int file = FileFromChar(move[2]); int rank = RankFromChar(move[3]); if (file < 0 || rank < 0) { return(null); } moveData.ToSquare = Square.Make(file, rank); } else { // 移動 moveData.MoveType = MoveType.Normal; // from int file = FileFromChar(move[0]); int rank = RankFromChar(move[1]); moveData.FromSquare = Square.Make(file, rank); file = FileFromChar(move[2]); rank = RankFromChar(move[3]); if (file < 0 || rank < 0) { return(null); } moveData.ToSquare = Square.Make(file, rank); moveData.Piece = position.GetPiece(moveData.FromSquare); if (move.Length >= 5 && move[4] == '+') { // 成り moveData.MoveType = MoveType.Promotion; } } // 盤面を進める if (moveData.MoveType.IsMoveWithoutPass()) { // 指し手の場合 if (position.MoveLast.MoveType.IsMove() && moveData.ToSquare == position.MoveLast.ToSquare) { moveData.MoveType |= MoveType.Same; // 同ほげ用のフラグ設定 } if (position.GetPiece(moveData.ToSquare) != Piece.NoPiece) { moveData.MoveType |= MoveType.Capture; // 駒とったフラグ設定 moveData.CapturePiece = position.GetPiece(moveData.ToSquare); // 駒をいれる } } return(moveData); }
public static SBook ImportYaneuraOu(string filename) { SBook book = new SBook(); try { using (StreamReader sr = new StreamReader(filename)) { string line; SPosition pos = new SPosition(); book.Add(pos, null, 0, 0, 0); // 平手初期局面をいれる while ((line = sr.ReadLine()) != null) { if (line.StartsWith("sfen") || line.StartsWith("startpos") || line.StartsWith("position")) { Sfen.ReadNotation(pos, line); } else if (line.StartsWith("#") || line.StartsWith("//")) { // コメント } else { string[] str_array = line.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); if (str_array.Length >= 5) { MoveData move = Sfen.ParseMove(pos, str_array[0]); if (move.Piece == Piece.NoPiece || pos.GetPiece(move.ToSquare).ColorOf() == move.Piece.ColorOf()) { Debug.WriteLine("bb"); } if (move != null && move.MoveType.IsMoveWithoutPass()) { int weight; int depth = 0; int value = 0; int.TryParse(str_array[2], out value); int.TryParse(str_array[3], out depth); if (int.TryParse(str_array[4], out weight)) { // 指し手の追加 book.Add(pos, move, weight, value, depth); } } } } } } // idの付け直し book.SetIds(); } catch (Exception ex) { throw ex; } return book; }
/// <summary> /// 指し手の出力 /// </summary> /// <param name="bookstate"></param> /// <param name="position"></param> /// <param name="aperyBook"></param> private static void WriteMoves(SBookState bookstate, SPosition position, StreamWriter wr, int depth) { if (bookstate == null) { return; } if (bookstate.Count != 0) { return; // 既に出力した } int count = 0; foreach (SBookMove move in bookstate.Moves) { if (move.Weight != 0) { count++; } } bookstate.Count++; if (count != 0) { // 局面の出力 wr.WriteLine("sfen " + position.PositionToString(depth)); foreach (SBookMove move in bookstate.Moves) { if (move.Weight != 0) { // 指し手の出力 MoveData moveData = move.GetMoveData(); string next_str = "none"; SBookMove next_move = GetNextMove(move.NextState); if (next_move != null) { MoveData nextMoveData = next_move.GetMoveData(); next_str = Sfen.MoveToString(nextMoveData); } wr.WriteLine("{0} {1} {3} {4} {2}", Sfen.MoveToString(moveData), next_str, move.Weight, move.Value, move.Depth); } } } foreach (SBookMove move in bookstate.Moves) { // 指し手の出力 MoveData moveData = move.GetMoveData(); position.Move(moveData); // 再帰呼び出し WriteMoves(move.NextState, position, wr, depth + 1); position.UnMove(moveData, null); } }
/// <summary> /// 盤面比較 /// </summary> /// <param name="pos"></param> /// <returns></returns> public bool Equals(SPosition pos) { for (int i = 0; i < Square.NSQUARE; i++) { if (this.board[i] != pos.board[i]) { return false; } } for (int i = 0; i < this.blackHand.Length; i++) { if (this.blackHand[i] != pos.blackHand[i]) { return false; } } for (int i = 0; i < this.whiteHand.Length; i++) { if (this.whiteHand[i] != pos.whiteHand[i]) { return false; } } if (this.turn != pos.turn) { return false; } return true; }
/// <summary> /// 盤面情報読み込み /// </summary> /// <param name="notation"></param> /// <param name="sfen"></param> public static void PositionFromString(SPosition position, string sfen) { position.Init(); ReadPosition(position, sfen); }
///////////////////////////////////////////////////////////////////// /// <summary> /// sfen形式の盤情報を読み込み /// </summary> /// <param name="notation"></param> /// <param name="sr"></param> private static int ReadPosition(SPosition position, string sfen, int index = 0) { int file, rank; int ch; Piece piece; int piece_num; SPosition pos = position; file = 0; rank = 0; if (sfen != string.Empty) { pos.BoardClear(); } // 局面データ while (index < sfen.Length) { ch = sfen[index]; index++; if (ch == ' ') { break; } if (ch == '/') { // 段の区切り file = 0; rank += 1; if (rank >= Square.NRANK) { break; } } else if (ch >= '0' && ch <= '9') { // 数字は駒がないところ file += ch - '0'; } else { piece = Piece.NoPiece; // なり if (ch == '+') { piece |= Piece.PromotionFlag; if (index < sfen.Length) { ch = sfen[index]; index++; if (ch == ' ') { break; } } else { break; } } // 後手 if (ch >= 'a' && ch <= 'z') { piece |= Piece.WhiteFlag; ch = char.ToUpper((char)ch); } // charをPiece変換 PieceType pieceType; if (CharToPieceHashtable.TryGetValue((char)ch, out pieceType)) { piece |= (Piece)pieceType; } else { // 不明な文字列 Debug.Print("parse error"); piece = Piece.NoPiece; } if (piece.TypeOf() != PieceType.NoPieceType) { // 駒がある if (file < Square.NFILE) { pos.SetPiece(file, rank, piece); file++; } } } } // 手番 while (index < sfen.Length) { ch = sfen[index]; index++; if (ch == ' ') { break; } if (ch == 'w') { pos.Turn = PlayerColor.White; } else if (ch == 'b') { pos.Turn = PlayerColor.Black; } } // 持ち駒 while (index < sfen.Length) { ch = sfen[index]; index++; if (ch == ' ') { break; } piece_num = 1; // 枚数 if (ch >= '0' && ch <= '9') { piece_num = ch - '0'; if (index < sfen.Length) { ch = sfen[index]; index++; } else { break; } if (ch == ' ') { break; } else if (ch >= '0' && ch <= '9') { piece_num = (piece_num * 10) + (ch - '0'); if (index < sfen.Length) { ch = sfen[index]; index++; } else { break; } if (ch == ' ') { break; } } } PieceType piece_type; if (CharToPieceHashtable.TryGetValue(char.ToUpper((char)ch), out piece_type)) { if (char.IsUpper((char)ch)) { // 大文字は先手 pos.SetBlackHand(piece_type, piece_num); } else { // 後手 pos.SetWhiteHand(piece_type, piece_num); } } } // n手目 (読み飛ばす while (index < sfen.Length) { ch = sfen[index]; index++; if (ch == ' ') { break; } } return(index); }