예제 #1
0
        private void BestMove(int maxDepth)
        {
            if (null == _gameBoard)
            {
                throw new NoBoardException();
            }

            if (_gameBoard.GameIsOver)
            {
                throw new GameIsOverException();
            }

            StopPonder();

            CancellationToken token = OnStartAsyncCommand();

            Task <Move> task = _gameAI.GetBestMoveAsync(_gameBoard.Clone(), maxDepth, Config.MaxHelperThreads, token);

            task.Wait();

            if (null == task.Result)
            {
                throw new Exception("Null move returned!");
            }

            ConsoleOut(NotationUtils.ToBoardSpaceMoveString(_gameBoard, task.Result));

            OnEndAsyncCommand();
        }
예제 #2
0
        private void BestMove(TimeSpan maxTime)
        {
            if (null == _gameBoard)
            {
                throw new NoBoardException();
            }

            if (_gameBoard.GameIsOver)
            {
                throw new GameIsOverException();
            }

            StopPonder();

            CancellationToken token = OnStartAsyncCommand();

            if (maxTime < TimeSpan.MaxValue)
            {
                _asyncCommandCTS.CancelAfter(maxTime);
            }

            Task <Move> task = _gameAI.GetBestMoveAsync(_gameBoard, maxTime, Config.MaxHelperThreads, token);

            task.Wait();

            if (null == task.Result)
            {
                throw new Exception("Null move returned!");
            }

            ConsoleOut(NotationUtils.ToBoardSpaceMoveString(_gameBoard, task.Result));

            OnEndAsyncCommand();
        }
예제 #3
0
        private void Play(string moveString)
        {
            if (null == _gameBoard)
            {
                throw new NoBoardException();
            }

            if (_gameBoard.GameIsOver)
            {
                throw new GameIsOverException();
            }

            Move move = null;

            try
            {
                move = NotationUtils.ParseMoveString(_gameBoard, moveString);
            }
            catch (Exception)
            {
                throw new InvalidMoveException(move);
            }

            NotationUtils.TryNormalizeBoardSpaceMoveString(moveString, out moveString);

            _gameBoard.Play(move, moveString);

            StopPonder();

            ConsoleOut(_gameBoard.ToGameString());
        }
예제 #4
0
 private void OnBestMoveFound(object sender, BestMoveFoundEventArgs args)
 {
     if (null != _gameBoard && !_isPondering && Config.ReportIntermediateBestMoves)
     {
         ConsoleOut("{0};{1};{2:0.00}", NotationUtils.ToBoardSpaceMoveString(_gameBoard, args.Move), args.Depth, args.Score);
     }
 }
예제 #5
0
            double evaluateFingerObstacleCost(FingerState state, float minPreparation, NoteChord obsNote, float startPosition, int startHeight, int pitch)
            {
                float  deltaX   = startPosition - Piano.KeyPositions[pitch];
                float  deltaY   = startHeight - Piano.getKeyHeight(pitch);
                double distance = Math.Min(Math.Sqrt(deltaX * deltaX + deltaY * deltaY), 5) + 1;

                float prepareTime = startTime - minPreparation;

                float importance = NotationUtils.getNoteImportanceInChord(obsNote, state.Pitch);

                debug += string.Format("O{0},{1},{2},{3};", state.Pitch, prepareTime, state.Release, state.Press);

                if (prepareTime >= state.Release)
                {
                    double coeff = CostCoeff.FINGER_MOVE_SPEED_PUNISH * Math.Pow(0.1, (startTime - state.Release) / minPreparation);
                    return(coeff * distance);
                }
                else if (prepareTime >= state.Press)
                {
                    double speedCost  = CostCoeff.FINGER_MOVE_SPEED_PUNISH * distance;
                    double cutoffCost = CostCoeff.NOTE_CUTOFF_PUNISH * importance * (state.Release - prepareTime) / (state.Release - state.Press);

                    return(speedCost + cutoffCost);
                }
                else
                {
                    return(CostCoeff.OMIT_KEY_PUNISH * importance);
                }
            }
예제 #6
0
        private void ProcessBestMove(string line, bool tryToPlay)
        {
            try
            {
                Move bestMove = NotationUtils.ParseMoveString(Board, line.Split(';')[0]);

                TargetPiece    = bestMove.PieceName;
                TargetPosition = bestMove.Position;
                TargetMove     = bestMove;
            }
            catch (Exception)
            {
                TargetPiece = PieceName.INVALID;
            }

            if (tryToPlay && CurrentTurnIsEngineAI && CurrentGameSettings.GameMode == GameMode.Play && null != TargetMove)
            {
                if (TargetMove.IsPass)
                {
                    SendCommandInternal("pass");
                }
                else
                {
                    SendCommandInternal("play {0}", NotationUtils.ToBoardSpaceMoveString(Board, TargetMove));
                }
            }
        }
예제 #7
0
        public void SavePGN(Stream outputStream)
        {
            if (null == outputStream)
            {
                throw new ArgumentNullException(nameof(outputStream));
            }

            using (StreamWriter sw = new StreamWriter(outputStream, Encoding.ASCII))
            {
                // Write Mandatory Tags
                sw.WriteLine(GetPGNTag("GameType", EnumUtils.GetExpansionPiecesString(Metadata.GameType)));

                sw.WriteLine(GetPGNTag("Date", Metadata.Date));
                sw.WriteLine(GetPGNTag("Event", Metadata.Event));
                sw.WriteLine(GetPGNTag("Site", Metadata.Site));
                sw.WriteLine(GetPGNTag("Round", Metadata.Round));
                sw.WriteLine(GetPGNTag("White", Metadata.White));
                sw.WriteLine(GetPGNTag("Black", Metadata.Black));

                sw.WriteLine(GetPGNTag("Result", Metadata.Result.ToString()));

                // Write Optional Tags
                foreach (KeyValuePair <string, string> tag in Metadata.OptionalTags)
                {
                    sw.WriteLine(GetPGNTag(tag.Key, tag.Value));
                }

                if (GameBoard.BoardHistory.Count > 0)
                {
                    sw.WriteLine();

                    WritePGNMoveCommentary(sw, 0);

                    // Write Moves
                    int count = 1;
                    foreach (BoardHistoryItem item in GameBoard.BoardHistory)
                    {
                        sw.WriteLine("{0}. {1}", count, NotationUtils.NormalizeBoardSpaceMoveString(item.MoveString));
                        WritePGNMoveCommentary(sw, count);

                        count++;
                    }
                }

                // Write Result
                if (EnumUtils.GameIsOver(Metadata.Result))
                {
                    sw.WriteLine();
                    sw.WriteLine(Metadata.Result.ToString());
                }
            }
        }
예제 #8
0
            public void Parse(string s)
            {
                if (string.IsNullOrWhiteSpace(s))
                {
                    throw new ArgumentNullException(nameof(s));
                }

                s = s.Trim();

                string[] vals = s.Split('\t');

                Board             = GameBoard.ParseGameString(vals[0]);
                InvalidMoveString = vals[1];
                InvalidMove       = NotationUtils.ParseMoveString(Board, vals[1]);
            }
예제 #9
0
        private void ValidMoves()
        {
            if (null == _gameBoard)
            {
                throw new NoBoardException();
            }

            if (_gameBoard.GameIsOver)
            {
                throw new GameIsOverException();
            }

            MoveSet validMoves = _gameBoard.GetValidMoves();

            ConsoleOut(NotationUtils.ToBoardSpaceMoveStringList(_gameBoard, validMoves));
        }
예제 #10
0
            public void Parse(string s)
            {
                if (string.IsNullOrWhiteSpace(s))
                {
                    throw new ArgumentNullException(nameof(s));
                }

                s = s.Trim();

                string[] vals = s.Split('\t');

                Board = GameBoard.ParseGameString(vals[0]);

                ValidMoveStrings = vals[1].Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
                ValidMoves       = new Move[ValidMoveStrings.Length];

                for (int i = 0; i < ValidMoveStrings.Length; i++)
                {
                    ValidMoves[i] = NotationUtils.ParseMoveString(Board, ValidMoveStrings[i]);
                }
            }
예제 #11
0
        public void PlayTargetMove()
        {
            if (CurrentGameSettings.GameMode != GameMode.Play)
            {
                throw new Exception("Please switch the current game to play mode first.");
            }

            if (null == TargetMove)
            {
                throw new Exception("Please select a valid piece and destination first.");
            }

            if (TargetMove.IsPass)
            {
                Pass();
            }
            else
            {
                SendCommand("play {0}", NotationUtils.ToBoardSpaceMoveString(Board, TargetMove));
            }
        }
예제 #12
0
    public void load()
    {
        if (!SourceAsset)
        {
            Debug.LogError("SourceAsset is null.");
            return;
        }

        MemoryStream stream = new MemoryStream();

        stream.Write(SourceAsset.bytes, 0, SourceAsset.bytes.Length);
        stream.Position = 0;

        MidiSeq = new Midi.Sequence();
        MidiSeq.Load(stream);

        if (TrackHandIndices == null || TrackHandIndices.Length != MidiSeq.Count)
        {
            TrackHandIndices = Enumerable.Repeat(-1, MidiSeq.Count).ToArray();
        }

        Notation = NotationUtils.parseMidiFile(MidiSeq);
    }
예제 #13
0
    public void run()
    {
        if (MidiSeq.Count == 0)
        {
            Debug.LogWarning("MIDI no track found.");
            return;
        }

        if (!HandConfigLib)
        {
            HandConfigLib = GetComponent <HandConfigLibrary>();
        }

        if (!HandConfigLib)
        {
            Debug.LogError("HandConfigLibrary is null.");
        }

        var trackMap = HandTracksMap;

        Fingering[] results     = new Fingering[trackMap.Count];
        int         resultIndex = 0;

        foreach (var pair in trackMap)
        {
            if (pair.Key >= Hands.Length)
            {
                Debug.LogErrorFormat("Hand index {0} out of hand config range.", pair.Key);
                return;
            }

            Hand hand = Hands[pair.Key];

            int[] trackList = pair.Value;

            NotationTrack[] tracks = new NotationTrack[trackList.Length];
            for (int track = 0; track < trackList.Length; ++track)
            {
                tracks[track] = Notation[trackList[track]];
            }

            Navigator.Track                   = NotationTrack.merge(tracks);
            Navigator.Config                  = HandConfigLib.getConfig(hand.Config);
            Navigator.KeepConstraints         = KeepConstraints;
            Navigator.MinStepCount            = StepCountMin;
            Navigator.MaxStepCount            = StepCountMax;
            Navigator.BubbleLength            = BubbleLength;
            Navigator.EstimationStepIncrement = EstimationStepIncrement;

            if (Navigator.Config == null)
            {
                Debug.LogErrorFormat("Hand config of {0} is null.", hand.Config);
                return;
            }

            Navigator.HandType      = hand.Type;
            Navigator.AdaptionSpeed = hand.AdaptionSpeed;

            results[resultIndex++] = Navigator.run();

            if (DumpTree)
            {
#if UNITY_EDITOR
                UnityEditor.EditorUtility.DisplayProgressBar("FingeringGenerator", "DumpTree ...", 0);
#endif

                FileStream file = new FileStream(Application.dataPath + "/Editor/Log/FingeringNavigatorTreeDump" + pair.Key.ToString() + ".txt", FileMode.Create);

                byte[] bytes = System.Text.Encoding.Default.GetBytes(Navigator.getTreeJsonDump());
#if UNITY_EDITOR
                UnityEditor.EditorUtility.DisplayProgressBar("FingeringGenerator", string.Format("DumpTree {0:n} bytes...", bytes.Length), 0);
#endif
                file.Write(bytes, 0, bytes.Length);

                file.Close();

#if UNITY_EDITOR
                UnityEditor.EditorUtility.ClearProgressBar();
#endif
            }

            /*// dump leaf nodes
             * {
             *      FileStream file = new FileStream(Application.dataPath + "/Editor/Log/leaves.txt", FileMode.Create);
             *
             *      file.WriteByte((byte)'[');
             *      List<FingeringNavigator.TreeNode> leaves = Navigator.TreeLeaves;
             *      leaves.Sort(delegate(FingeringNavigator.TreeNode node1, FingeringNavigator.TreeNode node2)
             *      {
             *              double cost1 = node1.CommittedCost;
             *              double cost2 = node2.CommittedCost;
             *
             *              return cost1.CompareTo(cost2);
             *      });
             *      foreach(var leaf in leaves)
             *      {
             *              byte[] bytes = System.Text.Encoding.Default.GetBytes(leaf.JsonDump);
             *              file.Write(bytes, 0, bytes.Length);
             *              file.WriteByte((byte)',');
             *      }
             *      file.WriteByte((byte)'{');
             *      file.WriteByte((byte)'}');
             *      file.WriteByte((byte)']');
             *
             *      file.Close();
             * }*/
        }

        NotationUtils.appendFingeringToMidiFile(MidiSeq, results);
    }
예제 #14
0
        public static GameRecording LoadSGF(Stream inputStream, string fileName = null)
        {
            if (null == inputStream)
            {
                throw new ArgumentNullException(nameof(inputStream));
            }

            GameMetadata metadata = new GameMetadata();

            List <string> moveList = new List <string>();

            Dictionary <string, Stack <string> > backupPositions = new Dictionary <string, Stack <string> >();

            string rawResult         = "";
            bool   lastMoveCompleted = true;
            bool   whiteTurn         = true;

            using (StreamReader sr = new StreamReader(inputStream))
            {
                string line = null;
                while ((line = sr.ReadLine()) != null)
                {
                    line = line.Trim();
                    if (!string.IsNullOrWhiteSpace(line))
                    {
                        // Line has contents
                        Match m = null;
                        if ((m = Regex.Match(line, @"SU\[(.*)\]")).Success)
                        {
                            metadata.SetTag("GameType", m.Groups[1].Value.ToUpper().Replace("HIVE", EnumUtils.NoExpansionsString).Replace("-", "+"));
                        }
                        else if ((m = Regex.Match(line, @"EV\[(.*)\]")).Success)
                        {
                            metadata.SetTag("Event", m.Groups[1].Value);
                        }
                        else if ((m = Regex.Match(line, @"PC\[(.*)\]")).Success)
                        {
                            metadata.SetTag("Site", m.Groups[1].Value);
                        }
                        else if ((m = Regex.Match(line, @"RO\[(.*)\]")).Success)
                        {
                            metadata.SetTag("Round", m.Groups[1].Value);
                        }
                        else if ((m = Regex.Match(line, @"DT\[(.+)\]")).Success)
                        {
                            string rawDate = m.Groups[1].Value;
                            metadata.SetTag("SgfDate", rawDate);

                            rawDate = Regex.Replace(rawDate, @"(\D{3}) (\D{3}) (\d{2}) (\d{2}):(\d{2}):(\d{2}) (.{3,}) (\d{4})", @"$1 $2 $3 $4:$5:$6 $8");

                            if (DateTime.TryParseExact(rawDate, SgfDateFormats, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime parsed))
                            {
                                metadata.SetTag("Date", parsed.ToString("yyyy.MM.dd"));
                            }
                            else
                            {
                                foreach (CultureInfo ci in CultureInfo.GetCultures(CultureTypes.AllCultures))
                                {
                                    if (DateTime.TryParseExact(rawDate, SgfDateFormats, ci, DateTimeStyles.None, out parsed))
                                    {
                                        metadata.SetTag("Date", parsed.ToString("yyyy.MM.dd"));
                                        break;
                                    }
                                }
                            }
                        }
                        else if ((m = Regex.Match(line, @"P0\[id ""(.*)""\]")).Success)
                        {
                            metadata.SetTag("White", m.Groups[1].Value);
                        }
                        else if ((m = Regex.Match(line, @"P1\[id ""(.*)""\]")).Success)
                        {
                            metadata.SetTag("Black", m.Groups[1].Value);
                        }
                        else if ((m = Regex.Match(line, @"RE\[(.+)\]")).Success)
                        {
                            rawResult = m.Groups[1].Value;
                            metadata.SetTag("SgfResult", m.Groups[1].Value);
                        }
                        else if ((m = Regex.Match(line, @"GN\[(.+)\]")).Success)
                        {
                            metadata.SetTag("SgfGameName", m.Groups[1].Value);
                        }
                        else if ((m = Regex.Match(line, @"((move (w|b))|(dropb)|(pdropb)) ([a-z0-9]+) ([a-z] [0-9]+) ([a-z0-9\\\-\/\.]*)", RegexOptions.IgnoreCase)).Success)
                        {
                            // Initial parse
                            string movingPiece = m.Groups[m.Groups.Count - 3].Value.ToLower();
                            string destination = m.Groups[m.Groups.Count - 1].Value.ToLower().Replace("\\\\", "\\");

                            string backupPos = m.Groups[m.Groups.Count - 2].Value;

                            // Remove unnecessary numbers
                            movingPiece = movingPiece.Replace("m1", "m").Replace("l1", "l").Replace("p1", "p");
                            destination = destination.Replace("m1", "m").Replace("l1", "l").Replace("p1", "p");

                            // Add missing color indicator
                            if (movingPiece == "b1" || movingPiece == "b2" || !(movingPiece.StartsWith("b") || movingPiece.StartsWith("w")))
                            {
                                movingPiece = (whiteTurn ? "w" : "b") + movingPiece;
                            }

                            // Fix missing destination
                            if (destination == ".")
                            {
                                if (moveList.Count == 0)
                                {
                                    destination = "";
                                }
                                else
                                {
                                    destination = backupPositions[backupPos].Peek();
                                }
                            }

                            // Remove move that wasn't commited
                            if (!lastMoveCompleted)
                            {
                                moveList.RemoveAt(moveList.Count - 1);
                            }

                            moveList.Add(string.Format("{0} {1}", movingPiece, destination));

                            foreach (Stack <string> stack in backupPositions.Values)
                            {
                                if (stack.Count > 0 && stack.Peek() == movingPiece)
                                {
                                    stack.Pop();
                                    break;
                                }
                            }

                            if (!backupPositions.ContainsKey(backupPos))
                            {
                                backupPositions.Add(backupPos, new Stack <string>());
                            }

                            backupPositions[backupPos].Push(movingPiece);

                            lastMoveCompleted = false;
                        }
                        else if ((m = Regex.Match(line, @"P(0|1)\[[0-9]+ pass\]")).Success)
                        {
                            moveList.Add(NotationUtils.BoardSpacePass);

                            lastMoveCompleted = false;
                        }
                        else if ((m = Regex.Match(line, @"P(0|1)\[[0-9]+ done\]")).Success)
                        {
                            lastMoveCompleted = true;
                            whiteTurn         = !whiteTurn;
                        }
                        else if ((m = Regex.Match(line, @"P(0|1)\[[0-9]+ resign\]")).Success)
                        {
                            rawResult = m.Groups[1].Value == "0" ? BoardState.BlackWins.ToString() : BoardState.WhiteWins.ToString();
                        }
                    }
                }
            }

            GameBoard gameBoard = new GameBoard(metadata.GameType);

            foreach (string moveString in moveList)
            {
                Move move = null;
                try
                {
                    move = NotationUtils.ParseMoveString(gameBoard, moveString);
                }
                catch (Exception ex)
                {
                    throw new Exception(string.Format("Unable to parse '{0}'.", moveString), ex);
                }

                gameBoard.TrustedPlay(move, NotationUtils.NormalizeBoardSpaceMoveString(moveString));
            }

            // Set result
            if (rawResult.Contains(metadata.White))
            {
                metadata.SetTag("Result", BoardState.WhiteWins.ToString());
            }
            else if (rawResult.Contains(metadata.Black))
            {
                metadata.SetTag("Result", BoardState.BlackWins.ToString());
            }
            else if (rawResult == "The game is a draw")
            {
                metadata.SetTag("Result", BoardState.Draw.ToString());
            }
            else if (Enum.TryParse(rawResult, out BoardState parsed))
            {
                metadata.SetTag("Result", parsed.ToString());
            }
            else
            {
                metadata.SetTag("Result", gameBoard.BoardState.ToString());
            }

            return(new GameRecording(gameBoard, GameRecordingSource.SGF, metadata)
            {
                FileName = fileName?.Trim()
            });
        }
예제 #15
0
        public static GameRecording LoadPGN(Stream inputStream, string fileName = null)
        {
            if (null == inputStream)
            {
                throw new ArgumentNullException(nameof(inputStream));
            }

            GameMetadata metadata = new GameMetadata();

            List <string> moveList = new List <string>();

            string rawResult = "";

            string multiLineCommentary = null;

            using (StreamReader sr = new StreamReader(inputStream, Encoding.ASCII))
            {
                string line = null;
                while ((line = sr.ReadLine()) != null)
                {
                    line = line.Trim();

                    if (null != multiLineCommentary)
                    {
                        // Line is part of multiline commentary
                        multiLineCommentary += Environment.NewLine + line;

                        if (multiLineCommentary.EndsWith("}"))
                        {
                            // End of multiline commentary
                            metadata.SetMoveCommentary(moveList.Count, multiLineCommentary);
                            multiLineCommentary = null;
                        }
                    }
                    else if (line.StartsWith("[") && line.EndsWith("]"))
                    {
                        // Line is a tag
                        KeyValuePair <string, string> kvp = ParsePGNTag(line);
                        if (kvp.Key == "Result")
                        {
                            rawResult = kvp.Value;
                        }
                        else
                        {
                            metadata.SetTag(kvp.Key, kvp.Value);
                        }
                    }
                    else if (line.StartsWith("{") && line.EndsWith("}"))
                    {
                        // Line is a single line of commentary
                        metadata.SetMoveCommentary(moveList.Count, line);
                    }
                    else if (line.StartsWith("{") && null == multiLineCommentary)
                    {
                        multiLineCommentary = line;
                    }
                    else if (!string.IsNullOrWhiteSpace(line))
                    {
                        // Line is a move or result
                        if (Enum.TryParse(line, out BoardState lineResult))
                        {
                            rawResult = lineResult.ToString();
                        }
                        else
                        {
                            // Not a result, add as moveString
                            moveList.Add(line.TrimStart('.', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'));
                        }
                    }
                }
            }

            GameBoard gameBoard = new GameBoard(metadata.GameType);

            foreach (string moveString in moveList)
            {
                Move move = null;
                try
                {
                    move = NotationUtils.ParseMoveString(gameBoard, moveString);
                }
                catch (Exception ex)
                {
                    throw new Exception(string.Format("Unable to parse '{0}'.", moveString), ex);
                }

                gameBoard.TrustedPlay(move, moveString);
            }

            // Set result
            if (Enum.TryParse(rawResult, out BoardState result))
            {
                metadata.SetTag("Result", result.ToString());
            }
            else
            {
                metadata.SetTag("Result", gameBoard.BoardState.ToString());
            }

            return(new GameRecording(gameBoard, GameRecordingSource.PGN, metadata)
            {
                FileName = fileName?.Trim()
            });
        }
예제 #16
0
        public ObservableBoardHistory(BoardHistory boardHistory, BoardHistory activeBoardHistory = null, Action <int> moveNumberChangedCallback = null)
        {
            _boardHistory              = boardHistory ?? throw new ArgumentNullException(nameof(boardHistory));
            _activeBoardHistory        = activeBoardHistory ?? boardHistory;
            _moveNumberChangedCallback = moveNumberChangedCallback;

            if (_activeBoardHistory.Count > _boardHistory.Count)
            {
                throw new ArgumentException("Active history has more moves than history.");
            }

            int countWidth = _boardHistory.Count.ToString().Length;

            for (int i = 0; i < _boardHistory.Count; i++)
            {
                BoardHistoryItem item = _boardHistory[i];

                string countString = (i + 1).ToString().PadLeft(countWidth) + ". ";
                string moveString  = AppVM.ViewerConfig.NotationType == NotationType.BoardSpace ? NotationUtils.NormalizeBoardSpaceMoveString(item.MoveString) : item.ToString();

                bool isActive   = i < _activeBoardHistory.Count;
                bool isLastMove = i + 1 == _activeBoardHistory.Count;

                Items.Add(new ObservableBoardHistoryItem(countString + moveString, isActive, isLastMove));
            }
        }
예제 #17
0
        Choice evaluateChordChoice(FingerChord chord, int index)
        {
            float deltaTime = index > 0 ? NoteSeq[index].start - NoteSeq[index - 1].start : 0;

            NoteChord note = NoteSeq[index];

            HandConfig.RangePair wrists = Config.getFingerChordWristRange(chord);

            double cost = 0;

            // wrist position naturality reward
            if (wrists.left != null)
            {
                float distance = Math.Abs(wrists.left.middle - -HandConfig.WristNaturePosition);
                cost = Math.Pow(distance / 14, 4) * CostCoeff.WRIST_POSITION_NATURALITY_REWARD;
            }

            if (wrists.right != null)
            {
                float distance = Math.Abs(wrists.right.middle - HandConfig.WristNaturePosition);
                cost = Math.Pow(distance / 14, 4) * CostCoeff.WRIST_POSITION_NATURALITY_REWARD;
            }

            // wrist crowd punish
            if (wrists.left != null && wrists.right != null)
            {
                float distance = Math.Max(Math.Abs(wrists.left.high - wrists.right.low), Math.Abs(wrists.right.high - wrists.left.low));
                if (distance < 5)
                {
                    cost += CostCoeff.WRIST_CROWD_PUNISH * (5f - distance) / 5f;
                }
            }

            foreach (Finger f in chord.Values)
            {
                // shift fingers punish
                if (Math.Abs((int)f) > 10)
                {
                    cost += CostCoeff.SHIFT_FINGERS_PUNISH;
                }
            }

            int leftFingerCount  = 0;
            int rightFingerCount = 0;

            foreach (var pair in chord)
            {
                if (pair.Value != Finger.EMPTY)
                {
                    // black key short punish
                    if (Piano.isBlackKey(pair.Key))
                    {
                        int finger = Math.Abs((int)pair.Value);
                        int first  = (int)Math.Floor(finger / 10f) - 1;
                        int second = finger % 10 - 1;

                        float sh = HandConfig.BlackKeyShort[second];
                        if (first >= 0)
                        {
                            sh = Math.Max(HandConfig.BlackKeyShort[first], sh);
                        }

                        cost += sh * CostCoeff.BLACK_KEY_SHORT_PUNISH;
                    }

                    if (pair.Value > Finger.EMPTY)
                    {
                        ++rightFingerCount;
                    }
                    else if (pair.Value < Finger.EMPTY)
                    {
                        ++leftFingerCount;
                    }
                }
                else
                {
                    // omit key punish
                    float importance = NotationUtils.getNoteImportanceInChord(note, pair.Key);
                    cost += CostCoeff.OMIT_KEY_PUNISH * importance;
                }
            }

            // multiple fingers punish
            if (leftFingerCount > 0)
            {
                float value = leftFingerCount / 5f;
                cost += CostCoeff.MULTIPLE_FINGERS_PUNISH * value * value;
            }
            if (rightFingerCount > 0)
            {
                float value = rightFingerCount / 5f;
                cost += CostCoeff.MULTIPLE_FINGERS_PUNISH * value * value;
            }

            return(new Choice {
                chord = chord, staticCost = cost, wrists = wrists, deltaTime = deltaTime, node = new TreeNodeChoice()
            });
        }
예제 #18
0
        private void ProcessEngineOutput(EngineCommand command, string[] outputLines)
        {
            string errorMessage       = "";
            string invalidMoveMessage = "";

            for (int i = 0; i < outputLines.Length; i++)
            {
                if (outputLines[i].StartsWith("err"))
                {
                    errorMessage += outputLines[i].Substring(outputLines[i].IndexOf(' ') + 1) + Environment.NewLine;
                }
                else if (outputLines[i].StartsWith("invalidmove"))
                {
                    invalidMoveMessage += outputLines[i].Substring(outputLines[i].IndexOf(' ') + 1) + Environment.NewLine;
                }
            }

            if (!string.IsNullOrWhiteSpace(errorMessage))
            {
                throw new EngineErrorException(errorMessage.Trim(), outputLines);
            }

            if (!string.IsNullOrWhiteSpace(invalidMoveMessage))
            {
                throw new EngineInvalidMoveException(invalidMoveMessage.Trim(), outputLines);
            }

            string firstLine = "";
            string lastLine  = "";

            if (null != outputLines && outputLines.Length > 0)
            {
                firstLine = outputLines[0];
                lastLine  = outputLines[outputLines.Length - 1];
            }

            // Update other properties
            switch (command)
            {
            case EngineCommand.NewGame:
            case EngineCommand.Play:
            case EngineCommand.Pass:
            case EngineCommand.Undo:
                Board = !string.IsNullOrWhiteSpace(firstLine) ? GameBoard.ParseGameString(firstLine, true) : null;
                break;

            case EngineCommand.ValidMoves:
                ValidMoves = !string.IsNullOrWhiteSpace(firstLine) ? NotationUtils.ParseMoveStringList(Board, firstLine) : null;
                break;

            case EngineCommand.BestMove:
                // Update the target move (and potentially auto-play it)
                ProcessBestMove(lastLine, true);
                TryStopTimedCommand();
                break;

            case EngineCommand.Options:
                string[] optionLines = new string[outputLines.Length];
                Array.Copy(outputLines, optionLines, optionLines.Length);
                EngineOptions.ParseEngineOptionLines(optionLines);
                break;

            case EngineCommand.Info:
                ID = firstLine.StartsWith("id ") ? firstLine.Substring(3).Trim() : "Unknown";
                EngineCapabilities = new EngineCapabilities(lastLine);
                break;

            default:
                break;
            }
        }