예제 #1
0
    public int BlockCount()
    {
        Cell.CellOcc oppType = SignResourceStorage.GetOppositeOfSign(type);
        bool         block1  = blockField1.type == oppType || blockField1.type == Cell.CellOcc.BLOCKED;
        bool         block2  = blockField2.type == oppType || blockField2.type == Cell.CellOcc.BLOCKED;

        if (block1 && block2)
        {
            return(2);
        }
        else if (block1 || block2)
        {
            return(1);
        }
        else
        {
            return(0);
        }
    }
예제 #2
0
    /// <summary>
    /// A recursive minimax algorithm with alpha beta pruning
    /// </summary>
    private EvaluationResult EvaluateField(EvaluationField[,] field, Cell.CellOcc whoseTurn, int deepCount, List <IntVector2> pointsInGame, float alpha, float beta)
    {
        EvaluationResult result = new EvaluationResult(whoseTurn == HumanType ? int.MaxValue : int.MinValue, new IntVector2());

        List <IntVector2> been = new List <IntVector2>();
        int pointsInGameLength = pointsInGame.Count;

        bool alphaBetaEnd = false;

        // Go through the places where we can place
        // Call NewSignPlaced with field and position where we want to place
        for (int j = pointsInGame.Count - 1; j >= 0; j--)
        {
            // In each direction
            for (int i = -1; i <= 1 && !alphaBetaEnd; i++)
            {
                for (int k = -1; k <= 1 && !alphaBetaEnd; k++)
                {
                    // we just skip a place if we feel like, just to make AI a bit easier
                    if (rand.NextDouble() <= leaveOutChance + pointsInGame.Count / (float)afterSignCountMiss)
                    {
                        continue;
                    }

                    IntVector2 pos = new IntVector2(pointsInGame[j].x + i, pointsInGame[j].y + k);
                    // Not 0 0 and in bounds
                    if (!(i == 0 && k == 0) && /*&& pos.x >= 0 && pos.x < field.GetLength(0) && pos.y >= 0 && pos.y < field.GetLength(1)*/
                        field[pos.x, pos.y].type == Cell.CellOcc.NONE && !been.Contains(pos))       // if we haven't checked this position and the type of cell we are examining is NONE, so empty
                    {
                        been.Add(pos);

                        // Data so we can revert the field back (because recursive algorithm)
                        List <PlaceData> placed;
                        List <PlaceData> removed;

                        // Set the examined cell to the current's sign
                        field[pos.x, pos.y].type = whoseTurn;
                        // Place that sign and while that's happening determine signsinarow
                        NewSignPlaced(field, pos, out placed, out removed);
                        pointsInGame.Add(new IntVector2(pos));

                        // Go recursively until DIFFICULTY
                        EvaluationResult evalResult;
                        if (deepCount == DEEP_MAX)
                        {
                            float aiPoint, humanPoint;
                            GetPointsFromSignsInARow(field, pointsInGame, pos, out aiPoint, out humanPoint);

                            if (whoseTurn == AIType)
                            {
                                evalResult.points = aiPoint + humanPoint * 1.5f;
                            }
                            else
                            {
                                evalResult.points = aiPoint * 1.5f + humanPoint;
                            }
                            evalResult.fieldPos = new IntVector2(pos);
                        }
                        else
                        {
                            evalResult = EvaluateField(field, SignResourceStorage.GetOppositeOfSign(whoseTurn), deepCount + 1, pointsInGame, alpha, beta);
                        }

                        // If it is human's turn we search for min value - MINIMIZER
                        if (whoseTurn == HumanType)
                        {
                            if (result.points > evalResult.points)
                            {
                                result.points   = evalResult.points;
                                result.fieldPos = new IntVector2(pos);
                            }

                            beta = Mathf.Min(beta, result.points);
                            // If the points here is smaller than the best value for the parent maximizer then we don't have to search further because this minimizer
                            // potentially has the chance of picking this minimum value, which the parent maximizer will never pick otherwise if this minimizer
                            // doesn't pick this vaue it's only gonna pick a smaller one which is even worse for the maximizer
                            // so just stop the search
                            if (result.points <= alpha)
                            {
                                alphaBetaEnd = true;
                            }
                        }
                        // Otherwise if it is AI's turn we search for the max points - MAXIMIZER
                        else if (whoseTurn == AIType)
                        {
                            if (result.points < evalResult.points)
                            {
                                result.points   = evalResult.points;
                                result.fieldPos = new IntVector2(pos);
                            }

                            alpha = Mathf.Max(alpha, result.points);
                            // if the point is higher then the minimizer minimum then we don't need to search further because this maximizer
                            // will surely pick a greater value for the parent minimizer, than it already has
                            if (result.points >= beta)
                            {
                                alphaBetaEnd = true;
                            }
                        }

                        // Revert the field back
                        for (int l = 0; l < placed.Count; l++)
                        {
                            field[placed[l].fieldPos.x, placed[l].fieldPos.y].signsInARow.Remove(placed[l].signInARow);
                        }
                        for (int l = 0; l < removed.Count; l++)
                        {
                            field[removed[l].fieldPos.x, removed[l].fieldPos.y].signsInARow.Add(removed[l].signInARow);
                        }

                        field[pos.x, pos.y].type = Cell.CellOcc.NONE;

                        pointsInGame.RemoveAt(pointsInGame.Count - 1);
                    }
                }
            }
        }

        return(result);
    }
예제 #3
0
    public override void NextTurn(int[] gridPos, out Cell.CellOcc won)
    {
        Cell.CellOcc didWin;
        base.NextTurn(gridPos, out didWin);

        // Send to client that sign has been placed
        PlayGamesPlatform.Instance.RealTime.SendMessageToAll(true, Encoding.Unicode.GetBytes(
                                                                 GPMessageStrings.SIGN_PLACED + "#" + gridPos[0].ToString() + "#" + gridPos[1].ToString() + "#" + SignResourceStorage.GetOppositeOfSign(whoseTurn).ToString()
                                                                 ));

        // also send whose turn it is
        PlayGamesPlatform.Instance.RealTime.SendMessageToAll(true, Encoding.Unicode.GetBytes(
                                                                 GPMessageStrings.TURN_OF + "#" + whoseTurn.ToString()
                                                                 ));

        if (didWin == Cell.CellOcc.X || didWin == Cell.CellOcc.O)
        {
            if (didWin == Cell.CellOcc.X)
            {
                xScore++;
            }
            else
            {
                oScore++;
            }

            scoring.SetScore(xScore, oScore);

            // send score to client
            PlayGamesPlatform.Instance.RealTime.SendMessageToAll(true, Encoding.Unicode.GetBytes(
                                                                     GPMessageStrings.SEND_SCORE + "#" + xScore.ToString() + "#" + oScore.ToString()
                                                                     ));
        }

        won = didWin;
    }