Пример #1
0
    void Update()
    {
        engineOutputRPMText.text       = "Engine RPM: " + EngineHelpers.SpeedToRPM(engine.EngineSpeed).ToString("0");
        transmissionInputRPMText.text  = "In RPM: " + EngineHelpers.SpeedToRPM(engine.TransmissionInputSpeed).ToString("0");
        transmissionOutputRPMText.text = "Out RPM: " + EngineHelpers.SpeedToRPM(engine.GetTransmissionOutputSpeed()).ToString("0");
        torqueText.text = "Torque: " + engine.EngineTorque;
        clutchText.text = "Clutch: " + engine.ClutchAmount;
        gearText.text   = "" + (engine.CurrentGear + 1);

        Vector3 p = engineOutputVisual.transform.localPosition;

        p.z = Mathf.Lerp(engineOutputClutchMinZ, engineOutputClutchMaxZ, engine.ClutchAmount);
        engineOutputVisual.transform.localPosition = p;

        UpdateEngineOutputVisuals();
        UpdateTransmissionInputVisuals();
        UpdateTransmissionOutputVisuals();

        slipWarningIcon.SetActive(engine.ClutchAmount > 0f && !engine.ClutchLocked);
        lockIcon.SetActive(engine.ClutchLocked);
    }
Пример #2
0
        public void GetNumericOptionType(string option, string key, double?expected)
        {
            var actualVal = EngineHelpers.GetNumericOptionType(option, key);

            Assert.AreEqual(expected, actualVal);
        }
Пример #3
0
        public void GetStringDefault(string option, string expected)
        {
            var actual = EngineHelpers.GetStringDefault(option);

            Assert.AreEqual(expected, actual);
        }
Пример #4
0
        public void GetNumericDefault(string option, double?expected)
        {
            var actual = EngineHelpers.GetNumericDefault(option);

            Assert.AreEqual(expected, actual);
        }
Пример #5
0
        public void GetType(string options, OptionType expectedType)
        {
            var actualType = EngineHelpers.GetOptionType(options);

            Assert.AreEqual(expectedType, actualType);
        }
Пример #6
0
 /// <summary>
 /// Inverts the Y axis and moves to index base A and 1 instead of 0,0.
 /// </summary>
 /// <param name="p"></param>
 /// <returns></returns>
 private string DecodePosition(Point p)
 {
     return(EngineHelpers.DecodePosition((int)p.X, (int)p.Y, BoardEdgeSize));
 }
Пример #7
0
        /// <summary>
        /// Adds rows and columns to the grid based on the BoardEdgeSize property,
        /// and then populates the grid with GamePiece instances.
        /// </summary>
        private void CreateBoard()
        {
            //return;

            var edgesize = BoardEdgeSize;

            if (edgesize == 0 || _gameBorder == null || _gridContainer == null)
            {
                return;
            }

            _pieces = new Dictionary <string, GamePiece>();

            for (int i = _gridContainer.Children.Count - 1; i >= 0; i--)
            {
                var e = _gridContainer.Children[i];
                if (!(e is Grid || e is Border))
                {
                    _gridContainer.Children.Remove(e);
                }
            }
            //_gridContainer.Children.Clear();
            _gridContainer.ColumnDefinitions.Clear();
            _gridContainer.RowDefinitions.Clear();

            // Add left and top column and row.
            _gridContainer.RowDefinitions.Add(new RowDefinition {
                Height = new GridLength(0, GridUnitType.Auto)
            });
            _gridContainer.ColumnDefinitions.Add(new ColumnDefinition {
                Width = new GridLength(0, GridUnitType.Auto)
            });

            // Add columns and rows for pieces.
            for (int i = 0; i < edgesize * 2; i++)
            {
                _gridContainer.RowDefinitions.Add(new RowDefinition {
                    Height = new GridLength(1, GridUnitType.Star)
                });
                _gridContainer.ColumnDefinitions.Add(new ColumnDefinition {
                    Width = new GridLength(1, GridUnitType.Star)
                });
            }

            // Add right and bottom column and row.
            _gridContainer.RowDefinitions.Add(new RowDefinition {
                Height = new GridLength(0, GridUnitType.Auto)
            });
            _gridContainer.ColumnDefinitions.Add(new ColumnDefinition {
                Width = new GridLength(0, GridUnitType.Auto)
            });

            // Put grids in the right place.
            Grid.SetColumnSpan(_gameBorder, edgesize * 2);
            Grid.SetRowSpan(_gameBorder, edgesize * 2);
            Grid.SetColumnSpan(_messageDisplay, edgesize * 2);
            Grid.SetRowSpan(_messageDisplay, edgesize * 2);


            double lineThickness = edgesize == 9 ? 2.2 : (edgesize == 13 ? 1.8 : 1.5);

            // Add row labels and lines.
            for (int row = 0; row < edgesize; row++)
            {
                // Create row labels.
                if (ShowHeaders)
                {
                    var tb = CreateTextBlock((edgesize - row).ToString());
                    tb.HorizontalAlignment = HorizontalAlignment.Right;
                    tb.VerticalAlignment   = VerticalAlignment.Center;
                    tb.SetValue(Grid.RowSpanProperty, 2);
                    tb.SetValue(Grid.RowProperty, (row * 2) + 1);
                    _gridContainer.Children.Add(tb);

                    tb = CreateTextBlock((edgesize - row).ToString());
                    tb.HorizontalAlignment = HorizontalAlignment.Left;
                    tb.VerticalAlignment   = VerticalAlignment.Center;
                    tb.SetValue(Grid.ColumnProperty, (edgesize * 2) + 1);
                    tb.SetValue(Grid.RowSpanProperty, 2);
                    tb.SetValue(Grid.RowProperty, (row * 2) + 1);
                    _gridContainer.Children.Add(tb);
                }

                // Create horizontal line.
                var line = new Line
                {
                    StrokeThickness     = lineThickness - .5,
                    Stroke              = LineBrush,
                    HorizontalAlignment = HorizontalAlignment.Stretch,
                    VerticalAlignment   = VerticalAlignment.Center,
                    X1 = -5,
                    X2 = short.MaxValue,
                };

                line.SetValue(Grid.ColumnProperty, 2);
                line.SetValue(Grid.ColumnSpanProperty, (edgesize * 2) - 2);
                line.SetValue(Grid.RowProperty, (row * 2) + 1);
                line.SetValue(Grid.RowSpanProperty, 2);

                _gridContainer.Children.Add(line);
            }

            // Add dots
            switch (edgesize)
            {
            case 9:
                AddDot(2, 2);
                AddDot(6, 2);
                AddDot(4, 4);
                AddDot(2, 6);
                AddDot(6, 6);
                break;

            case 13:
                AddDot(3, 3);
                AddDot(6, 3);
                AddDot(9, 3);
                AddDot(3, 6);
                AddDot(6, 6);
                AddDot(9, 6);
                AddDot(3, 9);
                AddDot(6, 9);
                AddDot(9, 9);
                break;

            case 19:
                AddDot(3, 3);
                AddDot(9, 3);
                AddDot(15, 3);
                AddDot(3, 9);
                AddDot(9, 9);
                AddDot(15, 9);
                AddDot(3, 15);
                AddDot(9, 15);
                AddDot(15, 15);
                break;
            }

            // Add column labels and lines.
            for (int col = 0; col < edgesize; col++)
            {
                // Create column labels.
                if (ShowHeaders)
                {
                    var letter = EngineHelpers.GetColumnLetter(col);
                    var tb     = CreateTextBlock(letter);
                    tb.HorizontalAlignment = HorizontalAlignment.Center;
                    tb.SetValue(Grid.ColumnSpanProperty, 2);
                    tb.SetValue(Grid.ColumnProperty, (col * 2) + 1);
                    _gridContainer.Children.Add(tb);

                    tb = CreateTextBlock(letter);
                    tb.HorizontalAlignment = HorizontalAlignment.Center;
                    tb.SetValue(Grid.RowProperty, (edgesize * 2) + 1);
                    tb.SetValue(Grid.ColumnSpanProperty, 2);
                    tb.SetValue(Grid.ColumnProperty, (col * 2) + 1);
                    _gridContainer.Children.Add(tb);
                }

                // Create vertical line.
                var line = new Line
                {
                    StrokeThickness     = lineThickness,
                    Stroke              = LineBrush,
                    HorizontalAlignment = HorizontalAlignment.Center,
                    VerticalAlignment   = VerticalAlignment.Stretch,
                    Y1 = -5,
                    Y2 = short.MaxValue,
                };

                line.SetValue(Grid.RowProperty, 2);
                line.SetValue(Grid.RowSpanProperty, (edgesize * 2) - 2);
                line.SetValue(Grid.ColumnProperty, (col * 2) + 1);
                line.SetValue(Grid.ColumnSpanProperty, 2);

                _gridContainer.Children.Add(line);
            }

            // Smaller boards allow more space between pieces.
            _circleMargin = edgesize == 9 ? 6 : (edgesize == 13 ? 4 : 3);

            for (int row = 0; row < edgesize; row++)
            {
                for (int column = 0; column < edgesize; column++)
                {
                    // Create piece (every other row/column) and set its column, row, colspan, and rowspan.
                    var gamePiece = new GamePiece(EngineHelpers.DecodePosition(column, row, edgesize), _circleMargin, null, GoColor.Black, false, false, false);
                    gamePiece.SetValue(Grid.ColumnProperty, (column * 2) + 1);
                    gamePiece.SetValue(Grid.ColumnSpanProperty, 2);
                    gamePiece.SetValue(Grid.RowProperty, (row * 2) + 1);
                    gamePiece.SetValue(Grid.RowSpanProperty, 2);

                    gamePiece.Click += GamePieceOnClick;

                    _pieces[DecodePosition(new Point(column, row))] = gamePiece;

                    _gridContainer.Children.Add(gamePiece);
                }
            }

            //_gameBorder.Visibility = Visibility.Visible;

            AttemptLinkToPieces();
        }
Пример #8
0
        protected static async Task DisplayErrorCode(GoResultCode code)
        {
            var msg = EngineHelpers.GetResultCodeFriendlyMessage(code);

            await DisplayMessage("Whoops", msg);
        }
Пример #9
0
        private void ContinueGameFromState(GoGameState state)
        {
            // Player1 is always black, Player2 is always white.
            Player1 = new PlayerViewModel(state.Player1, GoColor.Black);
            Player2 = new PlayerViewModel(state.Player2, GoColor.White);

            _players = new[] { Player1, Player2 };

            WhoseTurn = state.WhoseTurn == GoColor.Black ? 0 : 1;
            OnPropertyChanged(nameof(WhoseTurn));
            CurrentTurnColor = _players[_whoseTurn].Color;

            SetState(state.Status, state.WinMargin);

            // Note that setting BoardEdgeSize triggers the board control to generate.
            BoardEdgeSize = state.Size;

            // Build a temporary dictionary with ALL the piece states in it, all set to
            // contain an empty PieceState initially.
            var tmpPieces = new Dictionary <string, PieceStateViewModel>();

            for (int x = 0; x < state.Size; x++)
            {
                for (int y = 0; y < state.Size; y++)
                {
                    var position = EngineHelpers.DecodePosition(x, y, state.Size);
                    tmpPieces.Add(position, new PieceStateViewModel(position, null, null, false, false, false));
                }
            }

            // This actually updates the UI.  Note that we can't add anything to Pieces after
            // this point because Pieces is a Dictionary, which can't be observed by the GameBoard
            // control.  From here forward, we simply update individual pieces inside Pieces; we
            // don't add or remove from it.
            Pieces = tmpPieces;

            int blackPrisoners = 0;
            int whitePrisoners = 0;

            // Save history.
            History = new ObservableCollection <GoMoveHistoryItem>();
            foreach (var h in state.GoMoveHistory)
            {
                History.Insert(0, h);
                if (h.Move.Color == GoColor.Black)
                {
                    blackPrisoners += h.Result.CapturedStones.Split(' ').Count(x => x != String.Empty);
                }
                else
                {
                    whitePrisoners += h.Result.CapturedStones.Split(' ').Count(x => x != String.Empty);
                }
            }

            Player1.Prisoners = Player1.Color == GoColor.Black ? blackPrisoners : whitePrisoners;
            Player2.Prisoners = Player2.Color == GoColor.Black ? blackPrisoners : whitePrisoners;

            // Set piece states for all the existing white and black pieces.
            SetPieces(state.BlackPositions, GoColor.Black);
            SetPieces(state.WhitePositions, GoColor.White);

            var latestNormalPiece = GetLatestNormalMovePieceFromHistory();

            if (latestNormalPiece != null)
            {
                latestNormalPiece.IsNewPiece = true;
            }

            // Correct Sequence value.
            //FixSequenceValuesForColor(state, GoColor.Black);
            //FixSequenceValuesForColor(state, GoColor.White);

            RaiseAllPiecesChanged();
            RaiseCommandsChanged();
        }
Пример #10
0
        private GoAreaResponse CalculateAreaValues(string dead)
        {
            var rval = new GoAreaResponse(GoResultCode.Success);

            // Split into arrays, and work out dead/undead white and black subsets.
            var deads  = dead.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            var blacks = _state.BlackPositions.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

            rval.BlackDead = deads.Where(d => blacks.Any(b => b == d)).ToList();
            var nonDeadBlacks = blacks.Where(b => deads.All(p => p != b)).Select(p => p.EncodePosition(_state.Size)).ToArray();
            var whites        = _state.WhitePositions.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

            rval.WhiteDead = deads.Where(d => whites.Any(w => w == d)).ToList();
            var nonDeadWhites = whites.Where(w => deads.All(p => p != w)).Select(p => p.EncodePosition(_state.Size)).ToArray();

            // Build game grid based on _state.BlackPositions and _state.WhitePositions,
            // excluding any dead stones.
            var grid = new GoColor?[_state.Size, _state.Size];

            foreach (var p in nonDeadWhites)
            {
                grid[p.X, p.Y] = GoColor.White;
            }
            foreach (var p in nonDeadBlacks)
            {
                grid[p.X, p.Y] = GoColor.Black;
            }

            // For each held position, determine the number of neighboring liberties
            // that are empty and don't eventually touch a different color.
            rval.BlackArea = GetContiguousAreaForHeldPoints(GoColor.Black, nonDeadBlacks);
            rval.WhiteArea = GetContiguousAreaForHeldPoints(GoColor.White, nonDeadWhites);

            // Local functions are cool.
            List <string> GetContiguousAreaForHeldPoints(GoColor color, Point[] heldPoints)
            {
                var result = new List <string>(_state.Size ^ 2);

                foreach (var held in heldPoints)
                {
                    foreach (var p in GetNeighborPositions(held))
                    {
                        // If is a liberty (no color), traverse it.
                        if (grid[p.X, p.Y] == null)
                        {
                            Debug.Assert(grid[held.X, held.Y].HasValue, "grid[held.X, held.Y].HasValue");

                            var liberties = new List <Point>(_state.Size ^ 2);
                            if (!AllNeighborsAreLibertiesOrColor(p, color, liberties))
                            {
                                continue;
                            }
                            foreach (var l in liberties)
                            {
                                var s = EngineHelpers.DecodePosition(l.X, l.Y, _state.Size);
                                if (!result.Contains(s))
                                {
                                    result.Add(s);
                                }
                            }
                        }
                    }

                    // Add held point (which is alive) because we want
                    // area not just territory.
                    var heldDecoded = EngineHelpers.DecodePosition(held.X, held.Y, _state.Size);
                    if (!result.Contains(heldDecoded))
                    {
                        result.Add(heldDecoded);
                    }
                }

                return(result);
            }

            // Local functions are cool.
            bool AllNeighborsAreLibertiesOrColor(Point point, GoColor color, List <Point> visited)
            {
                visited.Add(point);

                // Traverse through not already visited neighbors.
                foreach (var neighbor in GetNeighborPositions(point))
                {
                    if (visited.Contains(neighbor))
                    {
                        continue;
                    }

                    var neighborColor = grid[neighbor.X, neighbor.Y];

                    // If neighbors is a liberty (no color), traverse it.
                    if (neighborColor == null)
                    {
                        // Self-recursive call.
                        if (!AllNeighborsAreLibertiesOrColor(neighbor, color, visited))
                        {
                            // A neighbor was opposite color, abort up the chain.
                            return(false);
                        }
                    }
                    else if (neighborColor == OppositeColor(color))
                    {
                        // Neighbor is opposite color, abort all the way up the chain.
                        return(false);
                    }

                    // Neighbor is same color, this is a boundary, don't traverse it
                    // but continue to next neighbor.
                }
                return(true);
            }

            // Local functions are cool.
            // Iterates over the neighbors.  Using yield
            // allows caller to abort without iterating
            // all neighboring points.  References
            // _state.Size to determine edges of the board.
            IEnumerable <Point> GetNeighborPositions(Point p)
            {
                // has a left
                if (p.X > 0)
                {
                    yield return(new Point(p.X - 1, p.Y));
                }
                // has a right
                if (p.X < _state.Size - 1)
                {
                    yield return(new Point(p.X + 1, p.Y));
                }

                // has an upper
                if (p.Y > 0)
                {
                    yield return(new Point(p.X, p.Y - 1));
                }
                // has a lower
                if (p.Y < _state.Size - 1)
                {
                    yield return(new Point(p.X, p.Y + 1));
                }
            }

            return(rval);
        }