private void Player_PonderStarting(object sender, DataEventArgs <Board> e)
        {
            // 予想手を表示
            var ponder = SFENNotationReader.ToMoveData(player.LastPonderMove).ToString(e.Data.ToBoardData());

            FormUtility.SafeInvoke(this, () => { labelPonder.Text = "予想手:" + ponder; });
        }
        void Player_InfoReceived(object sender, ShogiCore.USI.USIInfoEventArgs e)
        {
            string infoDepth = "";
            string infoSelDepth = "";
            string infoTime = "";
            string infoNodes = "";
            string infoNPS = "";
            string infoScore = "";
            string infoCurrMove = "";
            string infoHashFull = "";
            string infoPVOrString = null;
            string pvLengthString = null;
            bool   lowerBound = false, upperBound = false;

            foreach (USIInfo info in e.SubCommands)
            {
                switch (info.Name)
                {
                case "depth": infoDepth = info.Parameters.FirstOrDefault(); break;

                case "seldepth": infoSelDepth = info.Parameters.FirstOrDefault(); break;

                case "time": infoTime = info.Parameters.FirstOrDefault(); break;

                case "nodes": infoNodes = info.Parameters.FirstOrDefault(); break;

                case "nps": infoNPS = info.Parameters.FirstOrDefault(); break;

                case "currmove": infoCurrMove = info.Parameters.FirstOrDefault(); break;

                case "hashfull": infoHashFull = info.Parameters.FirstOrDefault(); break;

                case "score":
                    if (player.LastScoreWasMate)
                    {
                        int    mateCount    = Math.Abs(player.LastScore) - USIPlayer.MateValue;
                        string mateCountStr = mateCount == 0 ? "" : ":" + mateCount.ToString();
                        infoScore = (0 < player.LastScore ? "+Mate" : "-Mate") + mateCountStr;
                    }
                    else
                    {
                        infoScore = player.LastScoreString;
                    }
                    break;

                case "lowerbound": lowerBound = true; break;

                case "upperbound": upperBound = true; break;

                case "pv": {
                    var           pvList   = info.Parameters;
                    BoardData     b        = Board == null ? null : Board.ToBoardData();
                    List <string> itemList = new List <string>();
                    int           pvLength = 0;
                    foreach (var pv in pvList)
                    {
                        try {
                            MoveData moveData = SFENNotationReader.ToMoveData(pv);
                            if (b == null)
                            {
                                itemList.Add(moveData.ToString());
                            }
                            else
                            {
                                itemList.Add(moveData.ToString(b));
                                b.Do(moveData);
                            }
                            pvLength++;
                        } catch (NotationException) {
                            itemList.Add(pv);
                        }
                    }
                    infoPVOrString = string.Concat(itemList.ToArray());
                    pvLengthString = "PV長=" + pvLength;
                }
                break;

                case "string":
                    infoPVOrString = string.Join(" ", info.Parameters);
                    break;
                }
            }

            if (!string.IsNullOrEmpty(infoSelDepth))
            {
                infoDepth += "/" + infoSelDepth;
            }
            long time, nodes, hashFull;

            if (long.TryParse(infoTime, out time))
            {
                infoTime = time.ToString("#,##0");
            }
            if (long.TryParse(infoNodes, out nodes))
            {
                infoNodes = nodes.ToString("#,##0");
            }
            if (long.TryParse(infoHashFull, out hashFull))
            {
                infoHashFull = (hashFull / 10.0).ToString("0.0").PadLeft(5) + "%";
            }
            if (lowerBound)
            {
                infoScore += "↑";
            }
            if (upperBound)
            {
                infoScore += "↓";
            }

            string toolTipText = pvLengthString;

            if (!string.IsNullOrEmpty(infoDepth))
            {
                toolTipText = "深さ=" + infoDepth + " " + toolTipText;
            }

            try {
                FormUtility.SafeInvoke(this, () => {
                    if (!string.IsNullOrEmpty(infoNPS))
                    {
                        long nps;
                        labelNPS.Text = long.TryParse(infoNPS, out nps) ? "NPS:" + nps.ToString("#,##0") : "NPS:" + infoNPS;
                    }
                    if (!string.IsNullOrEmpty(infoCurrMove))
                    {
                        if (Board == null)
                        {
                            labelCurMove.Text = "探索手:" + SFENNotationReader.ToMoveData(infoCurrMove).ToString();
                        }
                        else
                        {
                            labelCurMove.Text = "探索手:" + ShogiCore.Move.FromNotation(Board,
                                                                                     SFENNotationReader.ToMoveData(infoCurrMove)).ToString(Board);
                        }
                    }
                    if (!string.IsNullOrEmpty(infoHashFull))
                    {
                        labelHashFull.Text = "ハッシュ使用率:" + infoHashFull;
                    }
                    if (!string.IsNullOrEmpty(infoPVOrString))
                    {
                        AddListItem(infoTime, infoDepth, infoNodes, infoScore, infoPVOrString, pvLengthString);
                    }
                    double?meanDepth = stat.MeanDepth;
                    double?meanNPS   = stat.MeanNPS;
                    if (meanDepth.HasValue)
                    {
                        labelMeanDepth.Text = "平均深さ:" + meanDepth.Value.ToString("#0.0");
                    }
                    else
                    {
                        labelMeanDepth.Text = "平均深さ:-";
                    }
                    if (meanNPS.HasValue)
                    {
                        labelMeanNPS.Text = "平均NPS:" + meanNPS.Value.ToString("#,##0");
                    }
                    else
                    {
                        labelMeanNPS.Text = "平均NPS:-";
                    }
                });
            } catch {
                // 無視
            }
        }