Main
using System;
using System.Collections;
using System.Collections.Generic;
using Sifteo;
using Libraries;

namespace App
{
    // Purpose:
    // Use to contain the judge piece.
    // The judge pieced decides who is the winner, handles reseting pieces.
    // Press the judge piece to reset the game.
    public class JudgeCubeWrapper : GameCubeWrapper
    {
        // Purpose:
        // States the game judge can be in.
        public enum JudgeState
        {
            e_atTitleScreen,            // Waiting at the title screen.
            e_waitingForPlayers,        // Waiting for the players to make their choices.
            e_showingWLT,               // Showing the wins/losses/ties stats.
            e_matchResult               // Showing the match result after both players have made their decisions.
        }
       
        // Purpose:
        // Store the results for a match.
        private class MatchResults
        {
            // Who won.
            public GameCubeWrapper m_playerWinner = null;

            // Who lost.
            public GameCubeWrapper m_playerLoser = null;

            // Tied.
            public GameCubeWrapper m_tie1 = null;
            public GameCubeWrapper m_tie2 = null;

            // Side the winner is on.
            public Cube.Side m_winnerSide = Cube.Side.NONE;
        }

        // Purpose:
        // Constructor.
        // app      -
        // cube     - Cube the properties are for.
        // cubeType - What type of cube it is.
        public JudgeCubeWrapper(RPSApp app,
                                Cube cube,
                                CubeType cubeType)  : base(app, cube, cubeType)
        {
            m_textDisplay.m_renderIfCubeRender = true;
            m_textDisplay.SetLayer(1);
            m_textDisplay.SetRenderOrder(0);

            m_useRenderSkip = true;

            m_cube.FlipEvent += OnFlip;
            int size = 32;
            int center = (128 - size)/2;
           
            // Cube connected sprites.
            Sprite sprite;
            sprite = new Sprite(m_app.m_images.m_connectJudgeEmpty, center, 0, 0, 0, size, size, 1, Sprite.Rotation.e_rot270, false);
            sprite.SetID(m_topArrowID);
            sprite.m_renderIfCubeRender = true;
            sprite.SetLayer(1);
            sprite.SetRenderOrder(0);
            m_objs.StoreObj(sprite);

            sprite = new Sprite(m_app.m_images.m_connectJudgeEmpty, 0, center, 0, 0, size, size, 1, Sprite.Rotation.e_rot180, false);
            sprite.SetID(m_leftArrowID);
            sprite.m_renderIfCubeRender = true;
            sprite.SetLayer(1);
            sprite.SetRenderOrder(0);
            m_objs.StoreObj(sprite);

            sprite = new Sprite(m_app.m_images.m_connectJudgeEmpty, center, 128-size, 0, 0, size, size, 1, Sprite.Rotation.e_rot90, false);
            sprite.SetID(m_bottomArrowID);
            sprite.m_renderIfCubeRender = true;
            sprite.SetLayer(1);
            sprite.SetRenderOrder(0);
            m_objs.StoreObj(sprite);

            sprite = new Sprite(m_app.m_images.m_connectJudgeEmpty, 128-size, center, 0, 0, size, size, 1, Sprite.Rotation.e_none, false);
            sprite.SetID(m_rightArrowID);
            sprite.m_renderIfCubeRender = true;
            sprite.SetLayer(1);
            sprite.SetRenderOrder(0);
            m_objs.StoreObj(sprite);
       
        }  

        // Purpose:
        // Update the render with objects that need to be rendered.
        protected override void UpdateRenderer()
        {
            base.UpdateRenderer();

            if((null != m_textDisplay) && m_textDisplay.m_needsRender && m_textDisplay.m_show)
                m_renderer.Insert(m_textDisplay);
        }

        // Purpose:
        // Check if a new render is needed.  Override and check sprites/backgrounds/whatever.
        // Returns true if a render is needed, false if not.
        protected override bool CheckNeedsRender()
        {
            if(base.CheckNeedsRender())
            {
                return true;
            }
            else
            {
                if((null != m_textDisplay) && m_textDisplay.m_needsRender)
                    return true;
            }

            return false;
        }

        // Handle updating anything needed for the cube.
        // If the cube is marked for render, add in anything that needs to be rendered.
        protected override void HandleUpdate()
        {
            base.HandleUpdate ();

            // Update the bob animation for the win.
            if(Cube.Side.NONE != m_winnerSide)
            {
                if((Cube.Side.LEFT == m_winnerSide) || (Cube.Side.RIGHT == m_winnerSide))
                    m_objs.GetAsSprite(m_spriteID).SetPos((int)m_bobAction.GetCurrValue(), 0);
                else if((Cube.Side.TOP == m_winnerSide) || (Cube.Side.BOTTOM == m_winnerSide))
                    m_objs.GetAsSprite(m_spriteID).SetPos(0, (int)m_bobAction.GetCurrValue());
                m_bobAction.Update(1);
                m_objs.GetAsSprite(m_spriteID).m_needsRender = true;
            }

            m_needRender = CheckNeedsRender();
            if(m_needRender)
            {
                if((null != m_textDisplay) && (m_textDisplay.m_renderIfCubeRender))
                    m_renderer.Insert(m_textDisplay);
            }
        }

        // Purpose:
        // Run when a flip occurs.
        // Change game mode if in the current state allows it.
        private void OnFlip(Cube cube,
                            bool newOrientationIsUp)
        {
            if(!newOrientationIsUp)
            {
                if(GameType.e_rockPaperScissor == m_gameType)
                {
                    m_gameTypeChanged = true;
                    m_gameType = GameType.e_pirateZombieMonkeyRobot;
                }
                else if(GameType.e_pirateZombieMonkeyRobot == m_gameType)
                {
                    m_gameTypeChanged = true;
                    m_gameType = GameType.e_rockPaperScissor;          
                }

                StartSelectMode();
            }
        }
       
        // Purpose:
        // Return true if the given ID is a player ID, false if not.
        public bool IsPlayerType(CubeType ID)
        {
            return ((CubeType.e_player1 == ID) ||
               (CubeType.e_player2 == ID) ||
               (CubeType.e_player3 == ID) ||
               (CubeType.e_player4 == ID));
        }

        // Purpose:
        // Set how many players will be in the game.
        public void SetNumPlayers(int num)
        {
            m_numPlayers = num;
            ResetGame();
           
        }

        // Purpose:
        // Set the given player to notify the judge when pressed.
        // Player tells the judge how many players will be in the game.
        private void SetPlayerNotifyCount(CubeType ID,
                                          String image)
        {
            m_app.GetPlayerWrapper(ID).m_objs.GetAsSprite(m_spriteID).SetImage(image, true);
            m_app.GetPlayerWrapper(ID).m_allowButtonPress = true;
            m_app.GetPlayerWrapper(ID).TellJudgeCountOnPress(true);
            m_app.GetPlayerWrapper(ID).SetUseGameRules(false);
        }

        // Purpose:
        // Start the title screen.  
        public void StartTitleScreen()
        {
            // Hide the connection arrows.
            foreach(String sprite in m_sprites)
                m_objs.GetAsSprite(sprite).m_show = false;
       
            m_objs.GetAsSprite(m_spriteID).SetImage(m_app.m_images.m_titleScreen, true);
            m_state = JudgeState.e_atTitleScreen;

            // Set all player cubes to wait.
            foreach(GameCubeWrapper wrapper in m_app.m_cubeWrappers)
            {
                PlayerCubeWrapper player = m_app.GetPlayerWrapper(wrapper.m_cubeType);
                if(null != player)
                {
                   
                    player.m_objs.GetAsSprite(m_spriteID).SetImage(m_app.m_images.m_wait, true);
                    player.SetUseGameRules(true);
                }
            }
        }

        // Purpose:
        // Start the mode that decides how many players there will be.
        // display the possible number of players on player cubes and blank out unneeded cubes.
        public void StartNumPlayersMode()
        {
            // Not enough cubes to choose how many players there are.
            if(3 == m_app.GetNumCubes())
            {
                StartSelectMode();
            }
            else
            {
                // Hide the connection arrows.
                foreach(String sprite in m_sprites)
                    m_objs.GetAsSprite(sprite).m_show = false;

                // Clear all the player images.
                foreach(GameCubeWrapper wrapper in m_app.m_cubeWrappers)
                {
                    if(IsPlayerType(wrapper.m_cubeType))
                    {
                        wrapper.m_objs.GetAsSprite(m_spriteID).SetImage(null, true);
                        m_allowButtonPress = false;
                    }
                }

                m_objs.GetAsSprite(m_spriteID).SetImage(m_app.m_images.m_numPlayers, true);
               
                SetCubesSelectNumPlayers();
            }
        }
       
        // Purpose:
        // Set non-judge cubes to handle selecting the number of players.
        // Cube images are change and they are set to give the judge the number of players to use.
        private void SetCubesSelectNumPlayers()
        {
            if(3 <= m_app.GetNumCubes())
            {
                SetPlayerNotifyCount(CubeType.e_player2, m_app.m_images.m_numPlayers2);
            }
            if(4 <= m_app.GetNumCubes())
            {
                SetPlayerNotifyCount(CubeType.e_player3, m_app.m_images.m_numPlayers3);
            }
            if(5 <= m_app.GetNumCubes())
            {
                SetPlayerNotifyCount(CubeType.e_player4, m_app.m_images.m_numPlayers4);
            }
        }

        // Purpose:
        // Set the game to be in the select game mode state.
        // Set all cubes to handle.
        public void StartSelectMode()
        {
            m_ignoreEliminated = false;

            if(JudgeState.e_waitingForPlayers == m_state)
            {
                // Hide the connection arrows, update the cubes with the correct messages.
                foreach(String sprite in m_sprites)
                    m_objs.GetAsSprite(sprite).m_show = false;
               
                // Set all cubes to wait and then set some to handle  player selection.
                foreach(GameCubeWrapper wrapper in m_app.m_cubeWrappers)
                {
                    PlayerCubeWrapper player = m_app.GetPlayerWrapper(wrapper.m_cubeType);
                    if(null != player)
                    {
                        player.m_objs.GetAsSprite(m_spriteID).SetImage(m_app.m_images.m_wait, true);
                        player.m_allowButtonPress = false;
                        player.SetUseGameRules(true);
                    }
                }  
           
                SetCubesSelectNumPlayers();

                // Start screen.
                m_objs.GetAsSprite(m_spriteID).SetImage(m_app.m_images.m_start, true);
                m_allowShowStats = true;
               
                // Set the text display.
                if(GameType.e_rockPaperScissor == m_gameType)
                    m_textDisplay.m_text = m_app.m_text.m_selectRockPaperScissors;
                else if(GameType.e_pirateZombieMonkeyRobot == m_gameType)
                    m_textDisplay.m_text = m_app.m_text.m_selectPirZomMonRob;
                                   
                m_textDisplay.m_centerX = true;            

                m_textDisplay.m_posX = 5;
                m_textDisplay.m_posY = 10;
               
                m_textDisplay.m_show = true;
                m_textDisplay.m_needsRender = true;

                m_allowButtonPress = true;     
            }
        }


        // Store the given cube to the given side.  Updates attached direction sprites.
        //
        // side - Side to set.
        // cube - Cube to store.  If null then the side will be cleared.
        public void SetCubeAtSide(Cube.Side side,
                                  PlayerCubeWrapper cube)
        {
            bool set = true;

            string image = (null != cube) ? m_app.m_images.m_connectJudgeFilled : m_app.m_images.m_connectJudgeEmpty;
            if(Cube.Side.RIGHT == side)
            {
                m_right = cube;
                set = true;
            }
            else if(Cube.Side.LEFT == side)
            {
                m_left = cube;
                set = true;
            }
            else if(Cube.Side.TOP == side)
            {
                m_top = cube;
                set = true;
            }
            else if(Cube.Side.BOTTOM == side)
            {
                m_bottom = cube;
                set = true;
            }
           
            if(set)
            {              
                m_objs.GetAsSprite(m_sprites[(int)side]).SetImage(image, true);
           
                // Orient the cube.
                if(null != cube)
                    cube.m_cube.OrientTo(m_cube);
            }
        }

        // Sets the sprite for the given side to be shown or hidden.
        //
        // side - Side to set.
        // show - Value is true if the sprite should be shown, false if hidden.
        public void ShowHideSideImage(Cube.Side side,
                                      bool show)
        {
            if(Cube.Side.RIGHT == side)
            {
                m_objs.GetAsSprite(m_sprites[(int)side]).m_show = false;
                m_objs.GetAsSprite(m_sprites[(int)side]).m_needsRender = true;
            }
            else if(Cube.Side.LEFT == side)
            {
                m_objs.GetAsSprite(m_sprites[(int)side]).m_show = false;
                m_objs.GetAsSprite(m_sprites[(int)side]).m_needsRender = true;
            }
            else if(Cube.Side.TOP == side)
            {
                m_objs.GetAsSprite(m_sprites[(int)side]).m_show = false;
                m_objs.GetAsSprite(m_sprites[(int)side]).m_needsRender = true;
            }
            else if(Cube.Side.BOTTOM == side)
            {
                m_objs.GetAsSprite(m_sprites[(int)side]).m_show = false;
                m_objs.GetAsSprite(m_sprites[(int)side]).m_needsRender = true;
            }
        }

        // Purpose:
        // Toggle stats display on/off.
        public void ToggleStats()
        {
            // Prevent if disabled.
            if(!m_allowShowStats)
                return;

            // Only show if in the right state.
            if((JudgeState.e_waitingForPlayers == m_state) && (null != m_textDisplay))
            {
                if(!m_textDisplay.m_show)
                {
                    m_textDisplay.m_text = String.Format("Results:\nP1: W:{0} L:{1} T:{2}", m_gameStats.GetSumWinLoseTie(CubeType.e_player1, ResultState.e_win),
                                                                                            m_gameStats.GetSumWinLoseTie(CubeType.e_player1, ResultState.e_lose),
                                                                                            m_gameStats.GetSumWinLoseTie(CubeType.e_player1, ResultState.e_tie));
   
                    m_textDisplay.m_text += String.Format("\nP2: W:{0} L:{1} T:{2}", m_gameStats.GetSumWinLoseTie(CubeType.e_player2, ResultState.e_win),
                                                                                            m_gameStats.GetSumWinLoseTie(CubeType.e_player2, ResultState.e_lose),
                                                                                            m_gameStats.GetSumWinLoseTie(CubeType.e_player2, ResultState.e_tie));
                   
                    if(3 <= m_numPlayers)
                    {
                        m_textDisplay.m_text += String.Format("\nP3: W:{0} L:{1} T:{2}", m_gameStats.GetSumWinLoseTie(CubeType.e_player3, ResultState.e_win),
                                                                                                m_gameStats.GetSumWinLoseTie(CubeType.e_player3, ResultState.e_lose),
                                                                                                m_gameStats.GetSumWinLoseTie(CubeType.e_player3, ResultState.e_tie));
                    }

                    if(4 <= m_numPlayers)
                    {
                        m_textDisplay.m_text += String.Format("\nP4: W:{0} L:{1} T:{2}", m_gameStats.GetSumWinLoseTie(CubeType.e_player4, ResultState.e_win),
                                                                                                m_gameStats.GetSumWinLoseTie(CubeType.e_player4, ResultState.e_lose),
                                                                                                m_gameStats.GetSumWinLoseTie(CubeType.e_player4, ResultState.e_tie));
                    }
                }
               
                m_textDisplay.m_show = !m_textDisplay.m_show;
                m_needRender = true;
            }
        }

        // Purpose:
        // Clear the stored cube for the given side.
        public void ClearSide(Cube.Side side)
        {
            if(Cube.Side.LEFT == side)
                m_left = null;
            else if(Cube.Side.RIGHT == side)
                m_right = null;
            else if(Cube.Side.TOP == side)
                m_top = null;
            else if(Cube.Side.BOTTOM == side)
                m_bottom = null;
        }

        // Check if the pieces are all ready and handle the match end.
        // Show the winner, etc.
        public void HandleEndMatch()
        {
            // Players that are still in the match.
            List<CubeType> currPlayers = GetCurrPlayers();

            // Determine if there are enough pieces attached to the judge to decide a winner.
            if(currPlayers.Count == GetNumAttached())
            {
                ShowPieceSelections();
               
                // I need the match results for however many players there are.
                // If I need the results of the first player, wins, losses, ties against everybody else.
                // I do the same for the other players.
                // I then add up the results and determine who goes on and who is out.
                int [] wins = new int[currPlayers.Count];
                int [] loses = new int[currPlayers.Count];
                int [] ties = new int[currPlayers.Count];
                int [] resultSums = new int[currPlayers.Count];                

                WLTResults(wins, loses, ties, currPlayers);
               
                // Add up the results.
                // The largest value should win/tie for win.
                int maxVal = 0;
                for(int ind = 0; ind < currPlayers.Count; ++ind)
                {
                    resultSums[ind] = (wins[ind]*100) + ties[ind];
                    if(maxVal < resultSums[ind])
                        maxVal = resultSums[ind];
                }
               
                // Find the potential winners.
                List<CubeType> finalists = new List<CubeType>();
                for(int ind = 0; ind < currPlayers.Count; ++ind)
                {
                    if(resultSums[ind] == maxVal)
                    {
                        // Potential winner/tie.
                        finalists.Add(currPlayers[ind]);       
                    }
                    else
                    {  
                        // Loser
                        m_gameStats.AddStat(currPlayers[ind], ResultState.e_lose, m_app.GetPlayerWrapper(currPlayers[ind]).m_selection);
                        m_app.GetPlayerWrapper(currPlayers[ind]).m_isEliminated = true;
                        m_app.GetPlayerWrapper(currPlayers[ind]).m_ignore = true;
                    }
                }

                // Hide non winner arrows.
                if((null == m_left) || ((null != m_left) && (m_left.m_isEliminated)))
                    ShowHideSideImage(Cube.Side.LEFT, false);
                if((null == m_right) || ((null != m_right) && (m_right.m_isEliminated)))
                    ShowHideSideImage(Cube.Side.RIGHT, false);
                if((null == m_top) || ((null != m_top) && (m_top.m_isEliminated)))
                    ShowHideSideImage(Cube.Side.TOP, false);
                if((null == m_bottom) || ((null != m_bottom) && (m_bottom.m_isEliminated)))
                    ShowHideSideImage(Cube.Side.BOTTOM, false);

                // The finalists are all tied.
                if(finalists.Count > 1)
                {
                    for(int ind = 0; ind < finalists.Count; ++ind)
                        m_gameStats.AddStat(finalists[ind], ResultState.e_tie, m_app.GetPlayerWrapper(finalists[ind]).m_selection);
                    m_objs.GetAsSprite(m_spriteID).SetImage(m_app.m_images.m_tie, true);

                    // Match will continue to the next round.  Ignore eliminated players.
                    m_ignoreEliminated = true; 
                }
                else
                {
                    List<CubeType> playersLeft = GetCurrPlayers();
                    m_bobAction.ResetTime();
                    m_winnerSide = GetSidePlayerStored(playersLeft[0]);

                    // Update stat.
                    m_gameStats.AddStat(playersLeft[0], ResultState.e_win, m_app.GetPlayerWrapper(playersLeft[0]).m_selection);
               
                    if(Cube.Side.LEFT == GetSidePlayerStored(playersLeft[0]))
                    {                  
                        m_textDisplay.SetPos(0, 20);
                        m_textDisplay.m_centerX = true;
                        m_objs.GetAsSprite(m_spriteID).SetImage(m_app.m_images.m_winnerLeft, true);
                    }
                    else if(Cube.Side.RIGHT == GetSidePlayerStored(playersLeft[0]))
                    {
                        m_textDisplay.SetPos(0, 20);
                        m_textDisplay.m_centerX = true;
                        m_objs.GetAsSprite(m_spriteID).SetImage(m_app.m_images.m_winnerRight, true);
                        m_needRender = true;
                    }
                    else if(Cube.Side.TOP == GetSidePlayerStored(playersLeft[0]))
                    {
                        m_textDisplay.SetPos(0, 5);    
                        m_textDisplay.m_centerX = true;            
                        m_objs.GetAsSprite(m_spriteID).SetImage(m_app.m_images.m_winnerTop, true);
                        m_needRender = true;
                    }
                    else if(Cube.Side.BOTTOM == GetSidePlayerStored(playersLeft[0]))
                    {
                        m_textDisplay.SetPos(0, 5);
                        m_textDisplay.m_centerX = true;
                        m_objs.GetAsSprite(m_spriteID).SetImage(m_app.m_images.m_winnerBottom, true);
                        m_needRender = true;
                    }

                    // Remove the connection arrows.
                    foreach(String sprite in m_sprites)
                        m_objs.GetAsSprite(sprite).m_show = false;

                    // Someone won, display the message.   
                    m_textDisplay.m_text = m_app.m_text.m_winner;
                    m_textDisplay.m_show = true;       

                    // Match over.
                    m_ignoreEliminated = false;        
                }
                   
               
                m_state = JudgeState.e_matchResult;
           
                m_bgColor = new Color(0, 255, 255);
                m_allowButtonPress = true;

                // Used for testing, remove when not needed.
                // Output the current game win/loss totals.
                // m_gameStats.LogWinLoseStats();
            }
        }

        // Purpose:
        // Reset all the game pieces, include the judge to default values unless it is a match continuation, then eliminated players will be ignored.
        public void ResetGame()
        {
            m_allowShowStats = false;

            m_winnerSide = Cube.Side.NONE;
            m_bobAction.ResetTime();
           
            m_bgColor = Color.Black;

            m_textDisplay.m_show = false;
            m_textDisplay.m_posX = 5;
            m_textDisplay.m_posY = 5;

            // Reset the selection sprites.
            SetCubeAtSide(Cube.Side.BOTTOM, null);
            SetCubeAtSide(Cube.Side.TOP, null);
            SetCubeAtSide(Cube.Side.LEFT, null);
            SetCubeAtSide(Cube.Side.RIGHT, null);

            // Show the selection sprites.
            foreach(String sprite in m_sprites)
                m_objs.GetAsSprite(sprite).SetShow(true);

            m_state = JudgeState.e_waitingForPlayers;

            m_left = null;
            m_right = null;
            m_top = null;
            m_bottom = null;   
           
            // Load the game rules to use.
            if(m_gameTypeChanged)
            {
                m_gameTypeChanged = false;

                if(GameType.e_rockPaperScissor == m_gameType)
                    m_app.m_rules = new RPSRules();
                else if(GameType.e_pirateZombieMonkeyRobot == m_gameType)
                    m_app.m_rules = new MPRNZRules();
               
                m_needRender = true;
            }  

            // Reset all the cubes.
            int playerSetup = 0;
           
            foreach (GameCubeWrapper wrapper in m_app.m_cubeWrappers)
            {
                if(null != wrapper)
                {  
                    wrapper.m_objs.GetAsSprite(m_spriteID).SetPos(0, 0);

                    if(CubeType.e_judge == wrapper.m_cubeType)
                    {
                        m_objs.GetAsSprite(m_spriteID).SetImage(m_app.m_images.m_judge, true);
                        m_needRender = true;
                    }
                    else if(IsPlayerType(wrapper.m_cubeType))
                    {
                        PlayerCubeWrapper player = m_app.GetPlayerWrapper(wrapper.m_cubeType);

                        if(playerSetup < m_numPlayers)
                        {
                            player.SetUseGameRules(false);

                            // Fully reset the cube.
                            if(!(m_ignoreEliminated && player.m_isEliminated))
                            {
                                player.SetSelection("None");
                                player.TellJudgeCountOnPress(false);
                                player.m_isEliminated = false;
                                player.m_ignore = false;
                                player.SetUseGameRules(false);
                            }
                            else
                            {  
                                // Piece was eliminated so make it show that.
                                wrapper.m_objs.GetAsSprite(m_spriteID).SetImage(m_app.m_images.m_eliminated, true);
                            }
                            ++playerSetup;
                        }
                        else
                        {
                            // Not used.
                            wrapper.m_objs.GetAsSprite(m_spriteID).SetImage(null, true);
                            wrapper.m_allowButtonPress = false;
                            player.m_isEliminated = true;
                        }
                    }
                }
            }
        }

        // Purpose:
        // Get how many pieces are attached to the judge.
        public int GetNumAttached()
        {
            int count = 0;
            if(null != m_left)
                ++count;
            if(null != m_right)
                ++count;
            if(null != m_top)
                ++count;
            if(null != m_bottom)
                ++count;

            return count;
        }
       
        // Purpose:
        // Show the selection types for all attached pieces.
        public void ShowPieceSelections()
        {
            if(null != m_left)
                m_left.SetSelection(m_left.m_selection);
            if(null != m_right)
                m_right.SetSelection(m_right.m_selection);
            if(null != m_top)
                m_top.SetSelection(m_top.m_selection);
            if(null != m_bottom)
                m_bottom.SetSelection(m_bottom.m_selection);       
        }

        // Purpose:
        // Render the cube.
        public override void Render(bool paint)
        {
            base.Render(false);

            if(paint)
                m_cube.Paint();
        }

        // Purpose:
        // Retrive which side of the judge cube has the cube with the given ID.
        // ID - ID of the cube to find.
        //
        // Return:
        // Value is the side the cube was on, NONE if not found.
        private Cube.Side GetSidePlayerStored(CubeType ID)
        {
            if((null != m_left) && (m_left.m_cubeType == ID))
                return Cube.Side.LEFT;
            else if((null != m_right) && (m_right.m_cubeType == ID))
                return Cube.Side.RIGHT;
            else if((null != m_top) && (m_top.m_cubeType == ID))
                return Cube.Side.TOP;
            else if((null != m_bottom) && (m_bottom.m_cubeType == ID))
                return Cube.Side.BOTTOM;
            else
                return Cube.Side.NONE;
        }

        // Purpose:
        // Find the results of pitting all valid players against each other.  The arrays will be filled up with the results.
        // Stores the number of wins.
        // Stores the number of losses.    
        // Stores the number of ties.
        // Stores the players to check.  Results will be filled in for the arrays in this order.
        private void WLTResults(int[] wins,
                                int[] loses,
                                int[] ties,
                                List<CubeType> currPlayers)
        {
                for(int ind = 0; ind < currPlayers.Count; ++ind)
                {
                    foreach(CubeType playerAgainst in currPlayers)
                    {
                        if(currPlayers[ind] != playerAgainst)
                        {
                            MatchResults results = DetermineWinner(m_app.GetPlayerWrapper(currPlayers[ind]), m_app.GetPlayerWrapper(playerAgainst), Cube.Side.NONE, Cube.Side.NONE);
                            if((null != results.m_playerWinner) && (currPlayers[ind] == results.m_playerWinner.m_cubeType))
                                ++wins[ind];
                            else if((null != results.m_playerLoser) && (currPlayers[ind] == results.m_playerLoser.m_cubeType))
                                ++loses[ind];
                            else
                                ++ties[ind];
                        }
                    }
                }
        }

        // Purpose:
        // Return a list that contains all the players who are currently in the game (not eliminated).
        private List<CubeType> GetCurrPlayers()
        {
            List<CubeType> players = new List<CubeType>();
            foreach(GameCubeWrapper wrapper in m_app.m_cubeWrappers)
            {
                PlayerCubeWrapper player = m_app.GetPlayerWrapper(wrapper.m_cubeType);
                if((null != player) && !player.m_isEliminated)
                    players.Add(wrapper.m_cubeType);
            }
            return players;
        }

        // Purpose:
        // Determine which player is the winner.
        // player1, player2         - Players to check.
        // player1Side, player2Side - Sides the players are on.
        //
        // Return:
        // Value is results, who won/lost, etc.
        private MatchResults DetermineWinner(PlayerCubeWrapper player1, PlayerCubeWrapper player2,
                                             Cube.Side player1Side, Cube.Side player2Side)
        {
            MatchResults results = new MatchResults();
            ResultState result = m_app.m_rules.ResultAgainst(player1.m_selection, player2.m_selection);
            if(ResultState.e_win == result)
            {  
                results.m_playerWinner = player1;
                results.m_playerLoser = player2;
                results.m_winnerSide = player1Side;
            }
            else if(ResultState.e_lose == result)
            {  
                results.m_playerWinner = player2;
                results.m_playerLoser = player1;
                results.m_winnerSide = player2Side;
            }          
            else if(ResultState.e_tie == result)                                                                                                        // Tie
            {  
                results.m_tie1 = player1;
                results.m_tie2 = player2;
            }
            else
            {
                Log.Debug("Unhandled match result state");
            }

            return results;
        }

        // Purpose:
        // Handle the button press for cubes.  Depending on the cube type and state, perform different actions.
        protected override void OnButton (Cube cube, bool pressed)
        {
            base.OnButton(cube, pressed);

            if (m_allowButtonPress)
            {
                if (!pressed)
                {

                    if(JudgeCubeWrapper.JudgeState.e_atTitleScreen == m_state)
                    {  
                        m_state = JudgeCubeWrapper.JudgeState.e_waitingForPlayers;
                        StartNumPlayersMode();
                    }
                    else
                    {
                        ResetGame();
                    }
                }
            }
        }

        // Purpose:
        // Event.  Called when shaking stops.
        // cube - Cube that shaking stopped for.
        // duration - How long the cube was shaken, in milliseconds.
        protected override void OnShakeStopped(Cube cube, int duration)
        {
            // Wait before counting it as a shake.
            if((CubeType.e_judge == m_cubeType) && (duration > m_shakeMinTime))
            {
                // Show/hide stats.
                JudgeCubeWrapper wrapper =  (JudgeCubeWrapper)cube.userData;
                wrapper.ToggleStats();
            }
        }

        // Which cube is on which side of the cube.
        public PlayerCubeWrapper m_left = null;
        public PlayerCubeWrapper m_right = null;
        public PlayerCubeWrapper m_top = null;
        public PlayerCubeWrapper m_bottom = null;  

        // Current state the judge cube is in.
        public JudgeState m_state;

        // Total number of players involved in the game.
        // This is the max players that can be in it.  Do to losing there might be less in the current match.
        private int m_numPlayers = 2;
       
        // IDs for the different arrows.
        const String m_leftArrowID = "Left";
        const String m_rightArrowID = "Right";
        const String m_topArrowID = "Top";
        const String m_bottomArrowID = "Bottom";
       
        // Stores game arrow sprite IDs.
        private String [] m_sprites = new string[]{m_topArrowID, m_leftArrowID, m_bottomArrowID, m_rightArrowID};

        // Game type to play.
        private GameType m_gameType = GameType.e_rockPaperScissor;

        // Set when the gametime gets change so that the rules can changed when the next match starts.
        private bool m_gameTypeChanged = false;

        // Used to create a bobbing motion for a sprite.
        private BobAction m_bobAction = new BobAction(0, 15, 0, 30, true);

        // Store all the game relates stats, like wins and losses.
        private GameStats m_gameStats = new GameStats();

        // Store which side the winner is on, NONE if there is no winner.
        private Cube.Side m_winnerSide = Cube.Side.NONE;

        // Used when players from one round carry over to the next.  If true, eliminated players won't be included.
        private bool m_ignoreEliminated = false;

        // Whether game stats are allowed to display.  Value is true if they are, false if not.
        private bool m_allowShowStats = false;

        // Text display.
        private Libraries.RenderText m_textDisplay = new Libraries.RenderText("Fontmap", 6, 10, 16);

        // Minimum time a shake must occur for to be counted as a shake.
        private const int m_shakeMinTime = 1000;
    }
}

 
Website copyright (c) 2012 Benjamin Millek, all rights reserved.