Exemple #1
0
 public Kyokumen(Kyokumen kyokumen, string usimove)
 {
     bammen  = new Koma[9, 9];
     s_mochi = new int[7];
     g_mochi = new int[7];
     teban   = kyokumen.teban;
     Array.Copy(kyokumen.bammen, bammen, kyokumen.bammen.Length);
     Array.Copy(kyokumen.s_mochi, s_mochi, kyokumen.s_mochi.Length);
     Array.Copy(kyokumen.g_mochi, g_mochi, kyokumen.g_mochi.Length);
     proceed(usimove);
 }
        static bool CheckRepetition(Kyokumen kyokumen, List <Kyokumen> history)
        {
            int count = 0;

            foreach (Kyokumen his in history)
            {
                if (kyokumen == his)
                {
                    count++;
                }
            }
            return(count >= 3);
        }
 public static Result match(string matchname, uint byoyomi, Player b, Player w, string startusi = "startpos", string kifupath = @"./kifu.txt")          //開始局面のusiはsfen部分から
 {
     while (true)
     {
         using (Process sente = new Process())
             using (Process gote = new Process()) {
                 try {
                     Console.Write($"waiting setup {b.name}...");
                     b.Start(sente);
                     Console.WriteLine(" readyok.");
                     Console.Write($"waiting setup {w.name}...");
                     w.Start(gote);
                     Console.WriteLine(" readyok.");
                     List <string>   kifu      = new List <string>();
                     List <int>      evals     = new List <int>();
                     int             startmove = 1;
                     List <Kyokumen> history   = new List <Kyokumen>();
                     string          go        = $"go btime 0 wtime 0 byoyomi {byoyomi}";
                     var             starttime = DateTime.Now;
                     string          startsfen = "startpos";
                     if (startusi != "startpos")
                     {
                         string[] tokens = startusi.Split(' ', StringSplitOptions.RemoveEmptyEntries);
                         if (tokens[0] != "startpos")
                         {
                             throw new NotImplementedException();
                         }
                         else
                         {
                             history.Add(new Kyokumen());
                             for (int i = 2; i < tokens.Length; i++)
                             {
                                 kifu.Add(tokens[i]);
                                 history.Add(new Kyokumen(history[history.Count - 1], tokens[i]));
                             }
                             startmove = history.Count;
                         }
                     }
                     else
                     {
                         history.Add(new Kyokumen());
                     }
                     Console.WriteLine($"start at {startusi}");
                     Console.Write($"{starttime.ToString(Kifu.TimeFormat)} {matchname}:");
                     while (true)
                     {
                         if (kifu.Count % 2 == 0)                          //先手
                         {
                             var(move, eval) = GetMove(sente, position(startsfen, kifu), go);
                             kifu.Add(move);
                             evals.Add(eval);
                             Console.Write($" b:{move}({eval})");
                             if (move == "resign")
                             {
                                 Result result = Result.GoteWin;
                                 Kifu.FoutKifu(starttime, matchname, b, w, byoyomi, kifu, startmove, evals, result, kifupath);
                                 sendGameOver(sente, gote, result);
                                 return(result);
                             }
                             else if (move == "win")
                             {
                                 Result result = Result.SenteWin;
                                 Kifu.FoutKifu(starttime, matchname, b, w, byoyomi, kifu, startmove, evals, result, kifupath);
                                 sendGameOver(sente, gote, result);
                                 return(result);
                             }
                             var nextKyokumen = new Kyokumen(history[history.Count - 1], move);
                             if (CheckRepetition(nextKyokumen, history))
                             {
                                 Result result = Result.Repetition;
                                 Kifu.FoutKifu(starttime, matchname, b, w, byoyomi, kifu, startmove, evals, result, kifupath);
                                 sendGameOver(sente, gote, result);
                                 return(result);
                             }
                             if (CheckEndless(history.Count))
                             {
                                 Result result = Result.Draw;
                                 Kifu.FoutKifu(starttime, matchname, b, w, byoyomi, kifu, startmove, evals, result, kifupath);
                                 sendGameOver(sente, gote, result);
                                 return(result);
                             }
                             history.Add(nextKyokumen);
                         }
                         else                          //後手
                         {
                             var(move, eval) = GetMove(gote, position(startsfen, kifu), go);
                             kifu.Add(move);
                             evals.Add(-eval);
                             Console.Write($" w:{move}({-eval})");
                             if (move == "resign")
                             {
                                 Result result = Result.SenteWin;
                                 Kifu.FoutKifu(starttime, matchname, b, w, byoyomi, kifu, startmove, evals, result, kifupath);
                                 sendGameOver(sente, gote, result);
                                 return(result);
                             }
                             else if (move == "win")
                             {
                                 Result result = Result.GoteWin;
                                 Kifu.FoutKifu(starttime, matchname, b, w, byoyomi, kifu, startmove, evals, result, kifupath);
                                 sendGameOver(sente, gote, result);
                                 return(result);
                             }
                             var nextKyokumen = new Kyokumen(history[history.Count - 1], move);
                             if (CheckRepetition(nextKyokumen, history))
                             {
                                 Result result = Result.Repetition;
                                 Kifu.FoutKifu(starttime, matchname, b, w, byoyomi, kifu, startmove, evals, result, kifupath);
                                 sendGameOver(sente, gote, result);
                                 return(result);
                             }
                             if (CheckEndless(history.Count))
                             {
                                 Result result = Result.Draw;
                                 Kifu.FoutKifu(starttime, matchname, b, w, byoyomi, kifu, startmove, evals, result, kifupath);
                                 sendGameOver(sente, gote, result);
                                 return(result);
                             }
                             history.Add(nextKyokumen);
                         }
                     }
                 }
                 catch (Exception e) {
                     Console.WriteLine(e);
                     if (!sente.HasExited)
                     {
                         sente.StandardInput.WriteLine("quit");
                     }
                     if (!gote.HasExited)
                     {
                         gote.StandardInput.WriteLine("quit");
                     }
                 }
                 finally {
                     if (!sente.WaitForExit(100))
                     {
                         try {
                             sente.Kill();
                         }
                         catch (Exception)
                         {
                             //プロセスは既に終了しているので何もしない(waitが終わってkillを呼ぶまでの一瞬の間にプロセスが終了した場合に例外が発生する)
                         }
                     }
                     if (!gote.WaitForExit(100))
                     {
                         try {
                             gote.Kill();
                         }
                         catch (Exception) {
                             //プロセスは既に終了しているので何もしない
                         }
                     }
                 }
             }
     }
 }
        public static void KifulineToCSA()
        {
            Console.WriteLine("input kifu line by kifu.txt");
            Console.Write(">");
            string[] kifuline = Console.ReadLine().Split(':');
            if (kifuline.Length != 3)
            {
                Console.WriteLine("kifu line syntax error.");
                return;
            }
            Console.Write("csa output filename? > ");
            string filename = Console.ReadLine().Split(new char[] { ' ', '.' }, StringSplitOptions.RemoveEmptyEntries)[0] + ".csa";

            using (var fs = new StreamWriter(filename, false)) {
                fs.WriteLine("V2.2");
                //対局情報
                string[] info = kifuline[1].Split(' ');
                // <日:時> <title> (<sente> vs <gote>) <byoyomi>ms: <kifu>
                //対局者情報
                fs.WriteLine($"N+{info[2].Trim('(')}");
                fs.WriteLine($"N-{info[4].Trim(')')}");
                //棋戦名
                fs.WriteLine($@"$EVENT:{info[1]}");
                //持ち時間
                int byoyomi = int.Parse(Regex.Replace(info[5], @"[^0-9]", "")) / 1000;
                fs.WriteLine(@"$TIME_LIMIT:00:00+" + byoyomi.ToString());
                //初期局面
                fs.WriteLine("PI");

                //指し手
                string[] moves    = kifuline[2].Split(' ', StringSplitOptions.RemoveEmptyEntries);
                Kyokumen kyokumen = new Kyokumen();
                bool     kecchaku = false;
                for (int i = 0; i < moves.Length; i++)
                {
                    string usimove = moves[i];
                    if (usimove == "resign")
                    {
                        fs.WriteLine(@"%TORYO");
                        kecchaku = true;
                    }
                    else if (usimove == "win")
                    {
                        fs.WriteLine(@"%KACHI");
                        kecchaku = true;
                    }
                    else
                    {
                        kyokumen.proceed(usimove);
                        fs.WriteLine(Kyokumen.usimove_to_csamove(usimove, kyokumen));
                    }
                    fs.WriteLine("T" + byoyomi.ToString());
                }
                if (!kecchaku)
                {
                    if (moves.Length > Program.drawMoves)
                    {
                        fs.WriteLine(@"%HIKIWAKE");
                    }
                    else
                    {
                        fs.WriteLine(@"SENNICHITE");
                    }
                }

                Console.WriteLine("kifu has been converted.");
            }
        }