//
    public void OnChgDropdown(Dropdown ddobj, GamePenguin.PenguinColor col)
    {
        GamePenguin.PenguinColor col2;

        // Update which colors are selected, and player status
        //
        m_refSC.PlayersActiveStatus[col] = (GameManager.PlayerStatus)ddobj.value;

        // Repeatedly scan current selections until all inconsistencies are removed
        //
        while (true)
        {
            col2 = ValidateDropdown(col);

            if (col2 == GamePenguin.PenguinColor._None)
            {
                break;
            }

            m_refSC.PlayersActiveStatus[col2] = GameManager.PlayerStatus.Human;
        }

        // Update display after validation
        //
        UpdateDropdowns();

        // Set status of play button, based on if two or more players are enabled
        //
        SetPlayBtn();
    }
예제 #2
0
    /// <summary>
    /// Get sequence of players taking turns for AI move evaluation (Also works backwards)
    /// </summary>
    /// <param name="prevPlayer">Player that just finsihed moving or being evaluated</param>
    /// <param name="direction">Move forward (1) or backward (-1) one player?</param>
    /// <remarks>
    /// CALLED BY: NextEvalPlayer(), PrevEvalPlayer(), AIBrain::Minimax**()
    /// </remarks>
    /// <returns></returns>
    ///
    public GamePenguin.PenguinColor GetPlayerIndex(GamePenguin.PenguinColor prevPlayer, int direction)
    {
        int newPlayerIndex = (int)prevPlayer;

        do
        {
            // Avoid underflow if going backwards
            //
            if (direction < 0 && newPlayerIndex == (int)GamePenguin.PenguinColor.Red)
            {
                newPlayerIndex = (int)GamePenguin.PenguinColor._None;
            }

            newPlayerIndex += direction;  // Increment/Decrement to next/previous player

            // Wrap around from end of list to start
            //
            if (direction > 0 && newPlayerIndex == (int)GamePenguin.PenguinColor._None)
            {
                newPlayerIndex = (int)GamePenguin.PenguinColor.Red;
            }
        } while (!tablePlayerPenguins.ContainsKey((GamePenguin.PenguinColor)newPlayerIndex));  // Skip index values for inactive players (Not in list)

        return((GamePenguin.PenguinColor)newPlayerIndex);
    }
    /// <summary>
    /// Verify values selected in dropdowns and remove inconsistencies (i.e. More than 1 "Youngest" or "AI")
    /// </summary>
    /// <param name="lastChanged">
    /// The player color the user just changed.  This is assumed to be the choice the user wants, and any
    ///  previous selection of "AI" or "Youngest" is what gets changed.
    /// </param>
    /// <returns>
    /// Returns color value that is redundant ("AI" or "Youngest") and should be changed to "Human" (because we can have any number of human players)
    /// </returns>
    /// <remarks>
    /// (This requires its own method/loop because you cannot modify a container
    ///   while it's being looped through -- So we have to break and restart whenever
    ///   a problem is found.)
    /// </remarks>
    ///
    GamePenguin.PenguinColor ValidateDropdown(GamePenguin.PenguinColor lastChanged)
    {
        GamePenguin.PenguinColor lastAIFound = GamePenguin.PenguinColor._None;
        GamePenguin.PenguinColor lastYgFound = GamePenguin.PenguinColor._None;

        foreach (GamePenguin.PenguinColor c in m_refSC.PlayersActiveStatus.Keys)
        {
            if (m_refSC.PlayersActiveStatus[c] == GameManager.PlayerStatus.Youngest)
            {
                if (lastYgFound != GamePenguin.PenguinColor._None)  // One was previously found
                {
                    return((lastYgFound == lastChanged) ? c : lastYgFound);
                }
                else
                {
                    lastYgFound = c;
                }
            }
            else if (m_refSC.PlayersActiveStatus[c] == GameManager.PlayerStatus.AI)
            {
                if (lastAIFound != GamePenguin.PenguinColor._None)  // One was previously found
                {
                    return((lastAIFound == lastChanged) ? c : lastAIFound);
                }
                else
                {
                    lastAIFound = c;
                }
            }
        }

        return(GamePenguin.PenguinColor._None);   // No issues -- Validation can end
    }
예제 #4
0
    /// <summary>
    /// Build a list of moves from list a valid tiles from AIBoard
    /// </summary>
    /// <param name="player"></param>
    ///
    List <Command.GameMove> GetValidMoves(GamePenguin.PenguinColor player, VPenguin penguin)
    {
        // List of possible moves (Must be unique one for every node in MiniMax tree!)
        //
        List <Command.GameMove> possibleMoves = new List <Command.GameMove>();

        // Get temporary list of tiles current penguin can move to
        //
        m_sourceTileList.Clear();
        //
        m_refBoard.FetchLegalTiles(penguin.currTile, m_sourceTileList);

        possibleMoves.Clear();   // Ensure we have a clean slate

        // Build move object for every legal tile
        //
        foreach (string tileID in m_sourceTileList)
        {
            Command.MovePenguin move = new Command.MovePenguin(penguin, player, tileID, penguin.lastTile);

            possibleMoves.Add(move);
        }

        return(possibleMoves);
    }
예제 #5
0
    /// <summary>
    /// Create physical Penguin game object and place him on input tile
    /// </summary>
    /// <param name="tile">Tile to place penguin</param>
    /// <param name="color">Color of penguin</param>
    /// <param name="bAI">Instantiate AI penguin?</param>
    /// <remarks>
    /// FLOW: State_Initialize::OnTileClicked() => Player::AddPenguin() => GameManager::CreatePenguin()
    /// </remarks>
    ///
    public GamePenguin CreatePenguin(GameTile tile, GamePenguin.PenguinColor color, bool bAI)
    {
        GameObject prefab = null;

        if (bAI)
        {
            prefab = PenguinAIPrefabs[(int)color];    // Choose the prefab for AI
        }
        else
        {
            prefab = PenguinPrefabs[(int)color];                              // Choose the prefab for current player
        }
        Vector3 v3Pos = tile.transform.position;                              // Point to place the penguin at
        Vector3 v3Rot = new Vector3(0.0f, Random.Range(0.0f, 359.99f), 0.0f); // Random initial rotation

        // Instantiate a new penguin
        //
        GameObject gobNewPenguin = Instantiate(prefab, v3Pos, Quaternion.Euler(v3Rot));

        GamePenguin newPenguin = gobNewPenguin.GetComponent <GamePenguin>();

        // Initialize non-GameObject-related data
        //
        newPenguin.InitPenguinData(color, tile, bAI);

        // Link penguin to its tile
        //
        tile.PlacePenguin(newPenguin);

        return(newPenguin);
    }
예제 #6
0
    public void AddPenguin(string tileID, GamePenguin.PenguinColor color)
    {
        List <VPenguin> penguinList;

        VTile tile = tileTable[tileID];

        tile.IsPenguinHere = true;

        VPenguin newPenguin = ScriptableObject.CreateInstance <VPenguin>();

        newPenguin.currTile = tileID;
        newPenguin.lastTile = tileID;
        newPenguin.numFish  = 0;
        newPenguin.isActive = true;

        // Check that color already exists in table, if not, initialize it
        //
        if (!tablePlayerPenguins.ContainsKey(color))
        {
            penguinList = new List <VPenguin>();

            tablePlayerPenguins.Add(color, penguinList);
        }
        else
        {
            penguinList = tablePlayerPenguins[color];
        }

        // Add new penguin to list for player
        //
        penguinList.Add(newPenguin);
    }
예제 #7
0
        public MovePenguin(VPenguin pen, GamePenguin.PenguinColor player, string destTile, string priorTile)
        {
            playerColor = player;

            penguin  = pen;
            toTile   = destTile;
            prevTile = priorTile;
            fromTile = pen.currTile;
        }
예제 #8
0
    /// <summary>
    /// Does this player have a penguin on the designated tile?
    /// </summary>
    /// <param name="color">Player's color</param>
    /// <param name="tile">Tile we're checking for a penguin</param>
    /// <returns>Return the penguin if it's there</returns>
    ///
    public VPenguin GetPenguinOn(GamePenguin.PenguinColor color, GameTile tile)
    {
        List <VPenguin> penguins = m_refAIBoard.tablePlayerPenguins[color];

        foreach (VPenguin pen in penguins)
        {
            if (pen.currTile == tile.tileID)
            {
                return(pen);
            }
        }

        return(null);   // No penguin of correct color found
    }
예제 #9
0
    public void SetScoreDisplay(GamePenguin.PenguinColor color, int score)
    {
        Text guiText = null;

        if (m_scoreGUIMap.ContainsKey(color))
        {
            guiText = m_scoreGUIMap[color];
        }

        if (guiText)
        {
            guiText.text = score.ToString();
        }
    }
예제 #10
0
    /// <summary>
    /// After player's last penguin is removed from game and casn no longer move.
    ///   indicate this by "ghosting out" the score display.
    /// </summary>
    /// <param name="color">Player no longer playing</param>
    ///
    void GhostScorePanel(GamePenguin.PenguinColor color)
    {
        GameObject panel = GetScorePanel(color);

        Text[] texts = panel.GetComponentsInChildren <Text>();

        foreach (Text txt in texts)
        {
            txt.color     = Color.gray;        // Grayed-out
            txt.fontStyle = FontStyle.Italic;  // Just to emphasize the point
        }

        UpdateScore();   // Update the display
    }
예제 #11
0
    public Text textScores;   // List of their scores

    /// <summary>
    /// Populate screen with final results
    /// </summary>
    ///
    public void DisplayScores()
    {
        int highestScore = 0;

        bool bTie = false;

        GamePenguin.PenguinColor winningColor = GamePenguin.PenguinColor._None;

        textWon.text    = "";
        textColors.text = "";
        textScores.text = "";

        for (GamePenguin.PenguinColor color = GamePenguin.PenguinColor.Red; color < GamePenguin.PenguinColor._None; color++)
        {
            if (m_refSC.AllPlayerScores.ContainsKey(color))   // Ignore colors not playing this session
            {
                int score = m_refSC.AllPlayerScores[color];

                textColors.text += color.ToString() + ":\n";
                textScores.text += score.ToString() + "\n";

                // Determine who got the most fish
                //
                if (score > highestScore)
                {
                    highestScore = score;
                    winningColor = color;

                    bTie = false;
                }
                else if (score == highestScore)
                {
                    bTie = true;
                }
            }
        }

        // If this game ended in a tie for first place
        //   (TODO: To be entirely "According to Hoyle", if there's a tie in fish score,
        //     the win should go to who won the most tiles.)
        //
        if (bTie)
        {
            textWon.text = "This Game is a Draw!";
        }
        else
        {
            textWon.text = winningColor.ToString() + " Won!";
        }
    }
예제 #12
0
    /// <summary>
    /// Build a list of all possible moves for current player
    /// </summary>
    /// <param name="currPlayer"></param>
    /// <returns></returns>
    ///
    public List <Command.GameMove> BuildMoveList(GamePenguin.PenguinColor currPlayer)
    {
        List <Command.GameMove> allPossibleMoves = new List <Command.GameMove>();

        List <VPenguin> penguins = m_refBoard.tablePlayerPenguins[currPlayer];

        // Accumulate all moves this player can make with any of their penguins
        //
        foreach (VPenguin pen in penguins)
        {
            // Get all of current player's legal moves (Placed in possibleMoves)
            //
            List <Command.GameMove> thisPensPossibleMoves = GetValidMoves(currPlayer, pen);

            allPossibleMoves.AddRange(thisPensPossibleMoves);
        }

        return(allPossibleMoves);
    }
예제 #13
0
    /// <summary>
    /// Add a player to game
    /// </summary>
    /// <param name="color">Player's penguin color</param>
    /// <param name="bFirstPlayer">Will this be the first player to move?</param>
    /// <param name="bAIPlayer">Should this player be controlled by the computer? (otherwise, human player)</param>
    ///
    public void CreatePlayer(GamePenguin.PenguinColor color, bool bFirstPlayer, bool bAIPlayer)
    {
        Player newPlayer;

        if (bAIPlayer)
        {
            newPlayer = ScriptableObject.CreateInstance <PlayerAI>();
        }
        //
        else
        {
            newPlayer = ScriptableObject.CreateInstance <PlayerHuman>();
        }

        newPlayer.Color = color;

        newPlayer.IsStartingPlayer = bFirstPlayer;

        m_players.Add(newPlayer);        // Player is now in game

        m_allPlayerScores.Add(color, 0); // Start keeping score

        m_numActivePlayers++;
    }
예제 #14
0
    /// <summary>
    /// Accept move just made by human player and apply it to AI board
    /// </summary>
    /// <param name=""></param>
    /// <param name=""></param>
    ///
    public void UpdateAIBoard(GamePenguin.PenguinColor playerColor, Command.GameMove move)
    {
        Debug.Assert(playerColor == colorCurrentPlayer); // Board should be on current player

        ApplyMove(move);                                 // Apply move to AI board ("move" object is polymorphic)
    }
예제 #15
0
 /// <summary>
 /// Fetch the GUI panel for input player color's score
 /// </summary>
 /// <param name="color">Player Color</param>
 /// <returns>UI Panel</returns>
 ///
 GameObject GetScorePanel(GamePenguin.PenguinColor color)
 {
     return(scorePanels[(int)color]);
 }
예제 #16
0
        }                                           // Check for "island" removal, or just tile penguin is standing on?

        public RemovePenguin(VPenguin pen, GamePenguin.PenguinColor player)
        {
            playerColor = player;
            penguin     = pen;
        }
예제 #17
0
 // Get list of active penguins a player has
 //
 List <VPenguin> GetPlayerPenguins(GamePenguin.PenguinColor player)
 {
     return(tablePlayerPenguins[player]);
 }
예제 #18
0
    /// <summary>
    /// MiniMax with alpha-beta pruning
    /// </summary>
    /// <param name="depth"></param>
    /// <param name="currPlayer"></param>
    /// <returns></returns>
    ///
    public float MinimaxAB(int depth, GamePenguin.PenguinColor currPlayer, List <Command.GameMove> allPossibleMoves, float alpha, float beta)
    {
        float bestHeuristicScore, currHeuristicScore = 0.0f;

        Command.GameMove lastMove;

        if (depth == 0)
        {
            return(m_refBoard.GetHeuristicScore());   // This is a "leaf node" -- Return its heuristic value
        }

        // Find all valid possible moves (Initial call hands current allPossibleMoves for AI, so does
        //  not to be found again on first iteration)
        //
        if (allPossibleMoves == null)
        {
            allPossibleMoves = BuildMoveList(currPlayer);
        }

        // Evaluate list of moves
        //
        if (currPlayer == m_me)   // AI's Turn (Maximizing Player)
        {
            bestHeuristicScore = Mathf.NegativeInfinity;

            foreach (Command.GameMove testMove in allPossibleMoves)
            {
                m_refBoard.PushMove(testMove);  // "Try out" this move on AI Board

                // Get to next node
                //
                currHeuristicScore = MinimaxAB(depth - 1, m_refBoard.GetPlayerIndex(currPlayer, 1), null, alpha, beta);

                // Print info only at uppermost level...
                //
                if (depth == m_depthInPlys)
                {
                    MiniMaxDebugInfo(testMove, currHeuristicScore);
                }

                // Undo move when test on this branch is done
                //
                lastMove = m_refBoard.PopMove();

                // Test heuristic result of this position
                //
                if (currHeuristicScore > alpha)
                {
                    // Print info only at uppermost level...
                    //
                    if (depth == m_depthInPlys)
                    {
                        if (_debugMode)
                        {
                            Debug.Log("New best move...");
                        }

                        MiniMaxDebugInfo(lastMove, currHeuristicScore);

                        m_refBoard.pendingMove = lastMove;
                    }

                    alpha = bestHeuristicScore = currHeuristicScore;
                }

                if (alpha >= beta)
                {
                    break;                  // Prune the tree
                }
            }

            return(bestHeuristicScore);
        }
        else   // Human player's Turn (Minimizing Players)
        {
            bestHeuristicScore = Mathf.Infinity;

            foreach (Command.GameMove testMove in allPossibleMoves)
            {
                m_refBoard.PushMove(testMove);

                currHeuristicScore = MinimaxAB(depth - 1, m_refBoard.GetPlayerIndex(currPlayer, 1), null, alpha, beta);

                // MiniMaxDebugInfo(testMove, currHeuristicScore);

                m_refBoard.PopMove();

                if (currHeuristicScore < beta)
                {
                    beta = bestHeuristicScore = currHeuristicScore;
                }

                if (alpha >= beta)
                {
                    break;                  // Prune the tree
                }
            }

            return(bestHeuristicScore);
        }
    }