コード例 #1
0
ファイル: DecisionTree.cs プロジェクト: ohadsas/Foosbot-final
        /// <summary>
        /// Only if ball is near the rod new location will be sent to communication layer.
        /// Method is based on distance, ball speed and BALL_DISTANCE_FACTOR, BALL_MAX_SPEED
        /// This method added to support Amit's requirement, to be able to set new position of rod based on distance to it.
        /// </summary>
        /// <param name="ballCoords">Ball Future Coordinates to respond to</param>
        /// <param name="currentRod">Current responding rod</param>
        /// <returns>[True] if we are near the rod or high speed, [False] otherwise</returns>
        protected bool IsBallNearTheRod(BallCoordinates ballCoords, IRod currentRod, int stopperPosition)
        {
            //By changing this parameter we set system sensitivity
            const double BALL_DISTANCE_FACTOR = 3000;
            const double BALL_MAX_SPEED       = 100;

            if (!ballCoords.IsDefined)
            {
                return(false);
            }

            double distanceFactor = Convert.ToDouble(TABLE_WIDTH) / Math.Abs(ballCoords.X - currentRod.RodXCoordinate);

            double speedFactor = 1;

            if (ballCoords.Vector != null && ballCoords.Vector.IsDefined)
            {
                speedFactor += Math.Abs(ballCoords.Vector.X / BALL_MAX_SPEED);
            }

            double diff = (double)Math.Abs(currentRod.State.DcPosition - stopperPosition) / (double)(currentRod.PlayerCount);

            bool result = (distanceFactor * diff * speedFactor > BALL_DISTANCE_FACTOR);

            return(result);
        }
コード例 #2
0
ファイル: DecisionTree.cs プロジェクト: ohadsas/Foosbot-final
        /// <summary>
        /// Calculate actual linear movement (Y Axe) for current rod to perform
        /// Is based on desired linear move type
        /// </summary>
        /// <param name="rod">Current rod</param>
        /// <param name="respondingPlayer">Responding player in current rod (1 based index)</param>
        /// <param name="bfc">Ball Future coordinates</param>
        /// <param name="desiredLinearMove">Desired Linear Move Type</param>
        /// <returns>New rod coordinate to move to (Axe Y)</returns>
        protected int CalculateNewRodCoordinate(IRod rod, int respondingPlayer, BallCoordinates bfc, eLinearMove desiredLinearMove)
        {
            //Define actual desired rod coordinate to move to
            //NOTE: responding player might be undefined will be -1
            switch (desiredLinearMove)
            {
            case eLinearMove.BALL_Y:
                return(_helper.LocateRespondingPlayer(rod, bfc.Y, respondingPlayer));

            //    return bfc.Y - _helper.CalculateCurrentPlayerYCoordinate(rod, _currentRodYCoordinate[rod.RodType], respondingPlayer);

            //case eLinearMove.LEFT_BALL_DIAMETER:
            //    return (-1) * 2 * BALL_RADIUS;
            //case eLinearMove.RIGHT_BALL_DIAMETER:
            //    return 2 * BALL_RADIUS;
            case eLinearMove.VECTOR_BASED:
                if (rod.Intersection.IsDefined)
                {
                    int stopperPosition = _helper.LocateRespondingPlayer(rod, rod.Intersection.Y, respondingPlayer);
                    return((IsBallNearTheRod(bfc, rod, stopperPosition)) ? stopperPosition : rod.State.DcPosition);
                }
                //return rod.IntersectionY - _helper.CalculateCurrentPlayerYCoordinate(rod, _currentRodYCoordinate[rod.RodType], respondingPlayer);
                return(rod.State.DcPosition);

            //case eLinearMove.BEST_EFFORT:
            //    return rod.BestEffort;
            default:
                return(rod.State.DcPosition);
            }
        }
コード例 #3
0
 /// <summary>
 /// Verify Player Count on given rod is beetween 1 to 5.
 /// </summary>
 /// <param name="rod">Current rod</param>
 /// <exception cref="ArgumentException">Thrown in case player count on rod is not in range of 1 to 5</exception>
 private void VerifyPlayerCountOnRod(IRod rod)
 {
     if (rod.PlayerCount < 1 || rod.PlayerCount > 5)
     {
         throw new ArgumentException(String.Format("[{0}] Number of players on rod {1} is incorrect {2}!",
                                                   MethodBase.GetCurrentMethod().Name, rod.RodType.ToString(), rod.PlayerCount));
     }
 }
コード例 #4
0
        /// <summary>
        /// Choose player to respond on current rod and action to perform
        /// </summary>
        /// <param name="rod">Current rod</param>
        /// <param name="bfc">Ball Future Coordinates</param>
        /// <param name="respondingPlayer">Responding Player index (1 based) on current rod [out]</param>
        /// <returns>Rod Action to be performed</returns>
        protected RodAction DefineActionAndRespondingPlayer(IRod rod, BallCoordinates bfc, out int respondingPlayer)
        {
            if (rod == null)
            {
                throw new ArgumentException(String.Format(
                                                "[{0}] Unable to define action and responding player while rod argument is NULL!",
                                                MethodBase.GetCurrentMethod().Name));
            }

            if (bfc == null || !bfc.IsDefined)
            {
                throw new ArgumentException(String.Format(
                                                "[{0}] Unable to define action and responding player while ball coordinates are NULL or UNDEFINED!",
                                                MethodBase.GetCurrentMethod().Name));
            }

            RodAction action = null;

            respondingPlayer = -1;
            switch (_helper.IsBallInSector(bfc.X, rod.RodXCoordinate, rod.DynamicSector))
            {
            //Ball is in Current Rod Sector
            case eXPositionSectorRelative.IN_SECTOR:
                action           = SubTree.Decide(rod, bfc);
                respondingPlayer = SubTree.RespondingPlayer;
                break;

            /* OLD :
             *  //The Big Sub Tree
             *  action = EnterDecisionTreeBallInSector(rod, bfc, out respondingPlayer);
             */

            //Ball is ahead of Current Rod Sector
            case eXPositionSectorRelative.AHEAD_SECTOR:
                //Ball Vector Direction is TO Current Rod and we have intersection point
                if (_helper.IsBallVectorToRod(bfc.Vector) &&
                    rod.Intersection.IsDefined)
                {
                    action = new RodAction(rod.RodType, eRotationalMove.DEFENCE, eLinearMove.VECTOR_BASED);

                    //Define responding player index
                    BallYPositionToPlayerYCoordinate(bfc.Y, rod);
                    respondingPlayer = this.RespondingPlayer;
                }
                else
                {
                    //Ball Vector Direction is FROM Current Rod
                    action = new RodAction(rod.RodType, eRotationalMove.DEFENCE, eLinearMove.BEST_EFFORT);
                }
                break;

            //Ball is behind Current Rod Sector
            case eXPositionSectorRelative.BEHIND_SECTOR:
                action = new RodAction(rod.RodType, eRotationalMove.RISE, eLinearMove.BEST_EFFORT);
                break;
            }
            return(action);
        }
コード例 #5
0
        /*
         * Currently not in use methods. Need to verify if needed before TESTING
         */

        /// <summary>
        /// Calculate current Player Y coordinate
        /// </summary>
        /// <param name="rod">Current rod</param>
        /// <param name="currentRodYCoordinate">Current Rod Y coordinates (stopper)</param>
        /// <param name="playerIndex">Chosen player index to perform action (index 1 based)</param>
        /// <returns>Chosen player Y coordinate</returns>
        /// <exception cref="ArgumentOutOfRangeException">Thrown in case player index is out of range</exception>
        public int CalculateCurrentPlayerYCoordinate(IRod rod, int currentRodYCoordinate, int playerIndex)
        {
            if (playerIndex > rod.PlayerCount || playerIndex < 1)
            {
                throw new ArgumentOutOfRangeException(String.Format(
                                                          "Player index {0} for rod type {1} is wrong! Players count is {2}",
                                                          playerIndex, rod.RodType, rod.PlayerCount));
            }

            return(rod.OffsetY + currentRodYCoordinate + rod.PlayerDistance * (playerIndex - 1));
        }
コード例 #6
0
ファイル: FullDecisionTree.cs プロジェクト: djjosse/Foosbot
        /// <summary>
        /// Choose player to respond on current rod and action to perform
        /// </summary>
        /// <param name="rod">Current rod</param>
        /// <param name="bfc">Ball Future Coordinates</param>
        /// <param name="respondingPlayer">Responding Player index (1 based) on current rod [out]</param>
        /// <returns>Rod Action to be performed</returns>
        protected RodAction DefineActionAndRespondingPlayer(IRod rod, BallCoordinates bfc, out int respondingPlayer)
        {
            if (rod == null)
                throw new ArgumentException(String.Format(
                     "[{0}] Unable to define action and responding player while rod argument is NULL!",
                        MethodBase.GetCurrentMethod().Name));

            if (bfc == null || !bfc.IsDefined)
                throw new ArgumentException(String.Format(
                    "[{0}] Unable to define action and responding player while ball coordinates are NULL or UNDEFINED!",
                        MethodBase.GetCurrentMethod().Name));

            RodAction action = null;
            respondingPlayer = -1;
            switch (_helper.IsBallInSector(bfc.X, rod.RodXCoordinate, rod.DynamicSector))
            {
                //Ball is in Current Rod Sector
                case eXPositionSectorRelative.IN_SECTOR:
                    action = SubTree.Decide(rod, bfc);
                    respondingPlayer = SubTree.RespondingPlayer;
                    break;

                    /* OLD :
                     *  //The Big Sub Tree
                     *  action = EnterDecisionTreeBallInSector(rod, bfc, out respondingPlayer);
                     */

                //Ball is ahead of Current Rod Sector
                case eXPositionSectorRelative.AHEAD_SECTOR:
                    //Ball Vector Direction is TO Current Rod and we have intersection point
                    if (_helper.IsBallVectorToRod(bfc.Vector) &&
                            rod.Intersection.IsDefined)
                    {
                        action = new RodAction(rod.RodType, eRotationalMove.DEFENCE, eLinearMove.VECTOR_BASED);
                        
                        //Define responding player index
                        BallYPositionToPlayerYCoordinate(bfc.Y, rod);
                        respondingPlayer = this.RespondingPlayer;
                    }
                    else
                    {
                        //Ball Vector Direction is FROM Current Rod
                        action = new RodAction(rod.RodType, eRotationalMove.DEFENCE, eLinearMove.BEST_EFFORT);
                    }
                    break;
                //Ball is behind Current Rod Sector
                case eXPositionSectorRelative.BEHIND_SECTOR:
                    action = new RodAction(rod.RodType, eRotationalMove.RISE, eLinearMove.BEST_EFFORT);
                    break;
            }
            return action;
        }
コード例 #7
0
ファイル: DecisionHelper.cs プロジェクト: djjosse/Foosbot
        /// <summary>
        /// Verify if there is enough space to move the rod from current rod Y coordinate to new Y coordinate
        /// New Y coordinate is rod Y coordinate with provided movement (negative or positive)
        /// </summary>
        /// <param name="rod">Current rod</param>
        /// <param name="currentRodYCoordinate">Current rod Y coordinate to move from, including ROD_START_Y </param>
        /// <param name="movement">Y delta to move from current rod Y coordinate (could be negative)</param>
        /// <returns>[True] in case there is enough space to move, [False] otherwise</returns>
        public bool IsEnoughSpaceToMove(IRod rod, int currentRodYCoordinate, int movement)
        {
            //Check if potential start of rod stopper is in range
            int potentialStartY = currentRodYCoordinate + movement;
            if (potentialStartY < ROD_START_Y)
                return false;

            //Check if potential end of rod stopper is in range
            int potentialEndY = potentialStartY + rod.StopperDistance;
            if (potentialEndY > ROD_END_Y)
                return false;

            //We are good, we have space to move!
            return true;
        }
コード例 #8
0
ファイル: DecisionHelper.cs プロジェクト: djjosse/Foosbot
        /// <summary>
        /// Get all players Y coordinates per current rod
        /// </summary>
        /// <param name="rodType">Current rod</param>
        /// <param name="rodCoordinate">Y Coordinate of current rod (stopper coordinate)</param>
        /// <returns>Array contains player Y in index of player number + 1
        /// <example>Player 1 Y coordinate is stored in array[0]</example>
        /// </returns>
        /// <exception cref="ArgumentNullException">Thrown in case rod is null</exception>
        public int[] AllCurrentPlayersYCoordinates(IRod rod, int rodCoordinate)
        {
            if (rod == null)
                throw new ArgumentNullException(String.Format(
                    "[{0}] Unable to calculate all players Y coordinates on rod because rod is NULL!",
                        MethodBase.GetCurrentMethod().Name));

            VerifyPlayerCountOnRod(rod);
            VerifyYRodCoordinate(rod.StopperDistance, rodCoordinate);

            int[] players = new int[rod.PlayerCount];
            for (int i = 0; i < rod.PlayerCount; i++)
            {
                players[i] = rodCoordinate + rod.OffsetY + i * rod.PlayerDistance;
            }
            return players;
        }
コード例 #9
0
        /// <summary>
        /// Main Decision Flow Method
        /// </summary>
        /// <param name="rod">Rod to use for decision</param>
        /// <param name="bfc">Ball Future coordinates</param>
        /// <returns>Rod Action to perform</returns>
        public override RodAction Decide(IRod rod, BallCoordinates bfc)
        {
            //Player to respond  (index base is 0)
            int respondingPlayer = -1;

            //Chose responding player on rod and define action to perform
            RodAction action = DefineActionAndRespondingPlayer(rod, bfc, out respondingPlayer);

            //Define actual desired rod coordinate to move to
            int startStopperDesiredY = CalculateNewRodCoordinate(rod, respondingPlayer, bfc, action.Linear);

            action.DcCoordinate = rod.NearestPossibleDcPosition(startStopperDesiredY);

            //Set last decided rod and player coordinates
            rod.State.DcPosition    = action.DcCoordinate;
            rod.State.ServoPosition = action.Rotation;
            return(action);
        }
コード例 #10
0
ファイル: FullDecisionTree.cs プロジェクト: djjosse/Foosbot
        /// <summary>
        /// Main Decision Flow Method
        /// </summary>
        /// <param name="rod">Rod to use for decision</param>
        /// <param name="bfc">Ball Future coordinates</param>
        /// <returns>Rod Action to perform</returns>
        public override RodAction Decide(IRod rod, BallCoordinates bfc)
        {
            //Player to respond  (index base is 0)
            int respondingPlayer = -1;

            //Chose responding player on rod and define action to perform
            RodAction action = DefineActionAndRespondingPlayer(rod, bfc, out respondingPlayer);

            //Define actual desired rod coordinate to move to
            int startStopperDesiredY = CalculateNewRodCoordinate(rod, respondingPlayer, bfc, action.Linear);
            action.DcCoordinate = rod.NearestPossibleDcPosition(startStopperDesiredY);

            //Set last decided rod and player coordinates 
            rod.State.DcPosition = action.DcCoordinate;
            if (_helper.ShouldSetServoStateFromTree(rod.RodType))
                rod.State.ServoPosition = action.Rotation;
            return action;
        }
コード例 #11
0
        /// <summary>
        /// Get all players Y coordinates per current rod
        /// </summary>
        /// <param name="rodType">Current rod</param>
        /// <param name="rodCoordinate">Y Coordinate of current rod (stopper coordinate)</param>
        /// <returns>Array contains player Y in index of player number + 1
        /// <example>Player 1 Y coordinate is stored in array[0]</example>
        /// </returns>
        /// <exception cref="ArgumentNullException">Thrown in case rod is null</exception>
        public int[] AllCurrentPlayersYCoordinates(IRod rod, int rodCoordinate)
        {
            if (rod == null)
            {
                throw new ArgumentNullException(String.Format(
                                                    "[{0}] Unable to calculate all players Y coordinates on rod because rod is NULL!",
                                                    MethodBase.GetCurrentMethod().Name));
            }

            VerifyPlayerCountOnRod(rod);
            VerifyYRodCoordinate(rod.StopperDistance, rodCoordinate);

            int[] players = new int[rod.PlayerCount];
            for (int i = 0; i < rod.PlayerCount; i++)
            {
                players[i] = rodCoordinate + rod.OffsetY + i * rod.PlayerDistance;
            }
            return(players);
        }
コード例 #12
0
        /// <summary>
        /// Verify if there is enough space to move the rod from current rod Y coordinate to new Y coordinate
        /// New Y coordinate is rod Y coordinate with provided movement (negative or positive)
        /// </summary>
        /// <param name="rod">Current rod</param>
        /// <param name="currentRodYCoordinate">Current rod Y coordinate to move from, including ROD_START_Y </param>
        /// <param name="movement">Y delta to move from current rod Y coordinate (could be negative)</param>
        /// <returns>[True] in case there is enough space to move, [False] otherwise</returns>
        public bool IsEnoughSpaceToMove(IRod rod, int currentRodYCoordinate, int movement)
        {
            //Check if potential start of rod stopper is in range
            int potentialStartY = currentRodYCoordinate + movement;

            if (potentialStartY < ROD_START_Y)
            {
                return(false);
            }

            //Check if potential end of rod stopper is in range
            int potentialEndY = potentialStartY + rod.StopperDistance;

            if (potentialEndY > ROD_END_Y)
            {
                return(false);
            }

            //We are good, we have space to move!
            return(true);
        }
コード例 #13
0
        /// <summary>
        /// Main Decision Flow Method desides on action and sets property of responding player
        /// </summary>
        /// <param name="rod">Rod to use for decision</param>
        /// <param name="bfc">Ball Future coordinates</param>
        /// <returns>Rod Action to perform</returns>
        public override RodAction Decide(IRod rod, BallCoordinates bfc)
        {
            //Get relative Y position and set Responding Player
            eYPositionPlayerRelative relativeY = BallYPositionToPlayerYCoordinate(bfc.Y, rod);

            //Get relative X position
            eXPositionRodRelative relativeX = BallXPositionToRodXPosition(bfc.X, rod);

            RodAction action = new RodAction(rod.RodType);

            /*
             * For Alpha this is good enough to make a kick.
             * For Beta need to define the actual sub tree.
             */
            if (relativeX.Equals(eXPositionRodRelative.FRONT))
            {
                action = new RodAction(rod.RodType, eRotationalMove.KICK, eLinearMove.VECTOR_BASED);
            }
            if (relativeX.Equals(eXPositionRodRelative.BACK))
            {
                action = new RodAction(rod.RodType, eRotationalMove.RISE, eLinearMove.VECTOR_BASED);
            }
            if (relativeX.Equals(eXPositionRodRelative.CENTER))
            {
                action = new RodAction(rod.RodType, eRotationalMove.KICK, eLinearMove.BALL_Y);
            }

            //Define actual desired rod coordinate to move to
            int startStopperDesiredY = CalculateNewRodCoordinate(rod, RespondingPlayer, bfc, action.Linear);

            action.DcCoordinate = rod.NearestPossibleDcPosition(startStopperDesiredY);

            //Set last decided rod and player coordinates
            rod.State.DcPosition    = action.DcCoordinate;
            rod.State.ServoPosition = action.Rotation;

            return(action);
        }
コード例 #14
0
ファイル: DecisionTree.cs プロジェクト: djjosse/Foosbot
 /// <summary>
 /// Main Decision Flow Method
 /// </summary>
 /// <param name="rod">Rod to use for decision</param>
 /// <param name="bfc">Ball Future coordinates</param>
 /// <returns>Rod Action to perform</returns>
 public abstract RodAction Decide(IRod rod, BallCoordinates bfc);
コード例 #15
0
ファイル: DecisionTree.cs プロジェクト: ohadsas/Foosbot-final
 /// <summary>
 /// Get Current Ball Position relative to current rod in Axe X
 /// </summary>
 /// <param name="xBallPosition">X ball coordinate</param>
 /// <param name="currentRod">Current rod</param>
 /// <returns>X position relative to current rod</returns>
 protected eXPositionRodRelative BallXPositionToRodXPosition(int xBallPosition, IRod currentRod)
 {
     if (xBallPosition - BALL_RADIUS > currentRod.RodXCoordinate)
     {
         return(eXPositionRodRelative.FRONT);
     }
     if (xBallPosition + BALL_RADIUS < currentRod.RodXCoordinate)
     {
         return(eXPositionRodRelative.BACK);
     }
     return(eXPositionRodRelative.CENTER);
 }
コード例 #16
0
 /// <summary>
 /// Get Y coordinate of rod stopper to bring responding player to desired Y coordinate
 /// </summary>
 /// <param name="rod">Current rod</param>
 /// <param name="desiredY">Desired Y coordinate to reach by responding player</param>
 /// <param name="respondingPlayer">One-Based Player Index in rod</param>
 /// <returns>Y coordinate of rod stopper to bring palyer to desired Y coordinate</returns>
 public int LocateRespondingPlayer(IRod rod, int desiredY, int respondingPlayer)
 {
     return(desiredY - rod.OffsetY - rod.PlayerDistance * (respondingPlayer - 1));
 }
コード例 #17
0
ファイル: DecisionHelper.cs プロジェクト: djjosse/Foosbot
 /// <summary>
 /// Get Y coordinate of rod stopper to bring responding player to desired Y coordinate
 /// </summary>
 /// <param name="rod">Current rod</param>
 /// <param name="desiredY">Desired Y coordinate to reach by responding player</param>
 /// <param name="respondingPlayer">One-Based Player Index in rod</param>
 /// <returns>Y coordinate of rod stopper to bring palyer to desired Y coordinate</returns>
 public int LocateRespondingPlayer(IRod rod, int desiredY, int respondingPlayer)
 {
     return desiredY - rod.OffsetY - rod.PlayerDistance * (respondingPlayer - 1);
 }
コード例 #18
0
ファイル: DecisionHelper.cs プロジェクト: djjosse/Foosbot
 /// <summary>
 /// Verify Player Count on given rod is beetween 1 to 5.
 /// </summary>
 /// <param name="rod">Current rod</param>
 /// <exception cref="ArgumentException">Thrown in case player count on rod is not in range of 1 to 5</exception>
 private void VerifyPlayerCountOnRod(IRod rod)
 {
     if (rod.PlayerCount < 1 || rod.PlayerCount > 5)
         throw new ArgumentException(String.Format("[{0}] Number of players on rod {1} is incorrect {2}!",
             MethodBase.GetCurrentMethod().Name, rod.RodType.ToString(), rod.PlayerCount));
 }
コード例 #19
0
ファイル: DecisionTree.cs プロジェクト: djjosse/Foosbot
 /// <summary>
 /// Get Current Ball Position relative to current rod in Axe X
 /// </summary>
 /// <param name="xBallPosition">X ball coordinate</param>
 /// <param name="currentRod">Current rod</param>
 /// <returns>X position relative to current rod</returns>
 protected eXPositionRodRelative BallXPositionToRodXPosition(int xBallPosition, IRod currentRod)
 {
     if (xBallPosition - BALL_RADIUS > currentRod.RodXCoordinate)
         return eXPositionRodRelative.FRONT;
     if (xBallPosition + BALL_RADIUS < currentRod.RodXCoordinate)
         return eXPositionRodRelative.BACK;
     return eXPositionRodRelative.CENTER;
 }
コード例 #20
0
ファイル: DecisionTree.cs プロジェクト: djjosse/Foosbot
        /// <summary>
        /// Only if ball is near the rod new location will be sent to communication layer.
        /// Method is based on distance, ball speed and BALL_DISTANCE_FACTOR, BALL_MAX_SPEED
        /// This method added to support Amit's requirement, to be able to set new position of rod based on distance to it.
        /// </summary>
        /// <param name="ballCoords">Ball Future Coordinates to respond to</param>
        /// <param name="currentRod">Current responding rod</param>
        /// <returns>[True] if we are near the rod or high speed, [False] otherwise</returns>
        protected bool IsBallNearTheRod(BallCoordinates ballCoords, IRod currentRod, int stopperPosition)
        {
            //By changing this parameter we set system sensitivity
            const double BALL_DISTANCE_FACTOR = 3000;
            const double BALL_MAX_SPEED = 100;

            if (!ballCoords.IsDefined)
                return false;

            double distanceFactor = Convert.ToDouble(TABLE_WIDTH) / Math.Abs(ballCoords.X - currentRod.RodXCoordinate);

            double speedFactor = 1;
            if (Vector2D.NotNullAndDefined(ballCoords.Vector))
            {
                speedFactor += Math.Abs(ballCoords.Vector.X / BALL_MAX_SPEED);
            }

            double diff = (double)Math.Abs(currentRod.State.DcPosition - stopperPosition) / (double)(currentRod.PlayerCount);

            bool result = (distanceFactor * diff * speedFactor > BALL_DISTANCE_FACTOR);
            return result;
        }
コード例 #21
0
ファイル: DecisionTree.cs プロジェクト: djjosse/Foosbot
        /// <summary>
        /// Calculate actual linear movement (Y Axe) for current rod to perform
        /// Is based on desired linear move type
        /// </summary>
        /// <param name="rod">Current rod</param>
        /// <param name="respondingPlayer">Responding player in current rod (1 based index)</param>
        /// <param name="bfc">Ball Future coordinates</param>
        /// <param name="desiredLinearMove">Desired Linear Move Type</param>
        /// <returns>New rod coordinate to move to (Axe Y)</returns>
        protected int CalculateNewRodCoordinate(IRod rod, int respondingPlayer, BallCoordinates bfc, eLinearMove desiredLinearMove)
        {
            int pos;
            //Define actual desired rod coordinate to move to
            //NOTE: responding player might be undefined will be -1
            switch (desiredLinearMove)
            {
                case eLinearMove.BALL_Y:
                    return _helper.LocateRespondingPlayer(rod, bfc.Y, respondingPlayer);
                //    return bfc.Y - _helper.CalculateCurrentPlayerYCoordinate(rod, _currentRodYCoordinate[rod.RodType], respondingPlayer);

                case eLinearMove.LEFT_BALL_DIAMETER:
                    pos = rod.NearestPossibleDcPosition(_helper.LocateRespondingPlayer(rod, bfc.Y, respondingPlayer));
                    return pos + (-1) * 2 * BALL_RADIUS;
                case eLinearMove.RIGHT_BALL_DIAMETER:
                    pos = rod.NearestPossibleDcPosition(_helper.LocateRespondingPlayer(rod, bfc.Y, respondingPlayer));
                    return pos + 2 * BALL_RADIUS;
                case eLinearMove.VECTOR_BASED:
                    if (rod.Intersection.IsDefined)
                    {
                        int stopperPosition = _helper.LocateRespondingPlayer(rod, rod.Intersection.Y, respondingPlayer);
                        return (IsBallNearTheRod(bfc, rod, stopperPosition)) ? stopperPosition : rod.State.DcPosition;
                    }
                    //return rod.IntersectionY - _helper.CalculateCurrentPlayerYCoordinate(rod, _currentRodYCoordinate[rod.RodType], respondingPlayer);
                    return rod.State.DcPosition;
                //case eLinearMove.BEST_EFFORT:
                //    return rod.BestEffort;
                default:
                    return rod.State.DcPosition;
            }
        }
コード例 #22
0
ファイル: DecisionTree.cs プロジェクト: djjosse/Foosbot
        /// <summary>
        /// Define Ball Y position relative to responding player of current rod and
        /// re define index of responding rod setting the property Responding Player
        /// </summary>
        /// <param name="yBallCoordinate">Current ball Y coordinate</param>
        /// <param name="currentRod">Current rod</param>
        /// <param name="playerToResponse">Responding player[out] (index base is 0)</param>
        /// <returns>Ball Y position relative to responding player</returns>
        protected eYPositionPlayerRelative BallYPositionToPlayerYCoordinate(int yBallCoordinate, IRod currentRod)
        {
            //set default responding player
            RespondingPlayer = -1;

            //get array of players and their Y coordinates (player i stored in array index i - 1)
            int[] currentPlayerYs = _helper.AllCurrentPlayersYCoordinates(currentRod, currentRod.State.DcPosition);

            //calculate movements for each player to reach the ball (Y Axe only)
            int[] movements = _helper.CalculateYMovementForAllPlayers(currentPlayerYs, yBallCoordinate);

            //convert movement to distance on Y Axe (Absolute value)
            int[] absoluteDistance = movements.Select(x => Math.Abs(x)).ToArray();

            //get index of fist minimal distance (movement is here: movements[minIndexFirst])
            int minIndexFirst = Array.IndexOf(absoluteDistance, absoluteDistance.Min());

            //eliminate the first minimal distance
            absoluteDistance[minIndexFirst] = TABLE_WIDTH * 100;

            //get index of second minimal distance (movement is here: movements[minIndexSecond])
            int minIndexSecond = Array.IndexOf(absoluteDistance, absoluteDistance.Min());

            //chosen movement to perform
            int movement = 0;

            //Define actual player to response 
            if (_helper.IsEnoughSpaceToMove(currentRod, currentRod.State.DcPosition, movements[minIndexFirst]))
            {
                //as index starts from 0 => first one is 1
                RespondingPlayer = minIndexFirst + 1;
                movement = movements[minIndexFirst];
            }
            else if (_helper.IsEnoughSpaceToMove(currentRod, currentRod.State.DcPosition, movements[minIndexSecond]))
            {
                //as index starts from 0 => first one is 1
                RespondingPlayer = minIndexSecond + 1;
                movement = movements[minIndexSecond];
            }
            else //In case we have no way to move for all the players
            {
                RespondingPlayer = minIndexFirst + 1;
                movement = 0;
            }

            //In case we reach the ball - no move needed
            if (Math.Abs(movement) < PLAYER_WIDTH)
                return eYPositionPlayerRelative.CENTER;
            else if (movement > 0)
                return eYPositionPlayerRelative.RIGHT;
            else // (movement < 0)
                return eYPositionPlayerRelative.LEFT;
        }
コード例 #23
0
ファイル: DecisionTree.cs プロジェクト: ohadsas/Foosbot-final
        /// <summary>
        /// Define Ball Y position relative to responding player of current rod and
        /// re define index of responding rod setting the property Responding Player
        /// </summary>
        /// <param name="yBallCoordinate">Current ball Y coordinate</param>
        /// <param name="currentRod">Current rod</param>
        /// <param name="playerToResponse">Responding player[out] (index base is 0)</param>
        /// <returns>Ball Y position relative to responding player</returns>
        protected eYPositionPlayerRelative BallYPositionToPlayerYCoordinate(int yBallCoordinate, IRod currentRod)
        {
            //set default responding player
            RespondingPlayer = -1;

            //get array of players and their Y coordinates (player i stored in array index i - 1)
            int[] currentPlayerYs = _helper.AllCurrentPlayersYCoordinates(currentRod, currentRod.State.DcPosition);

            //calculate movements for each player to reach the ball (Y Axe only)
            int[] movements = _helper.CalculateYMovementForAllPlayers(currentPlayerYs, yBallCoordinate);

            //convert movement to distance on Y Axe (Absolute value)
            int[] absoluteDistance = movements.Select(x => Math.Abs(x)).ToArray();

            //get index of fist minimal distance (movement is here: movements[minIndexFirst])
            int minIndexFirst = Array.IndexOf(absoluteDistance, absoluteDistance.Min());

            //eliminate the first minimal distance
            absoluteDistance[minIndexFirst] = TABLE_WIDTH * 100;

            //get index of second minimal distance (movement is here: movements[minIndexSecond])
            int minIndexSecond = Array.IndexOf(absoluteDistance, absoluteDistance.Min());

            //chosen movement to perform
            int movement = 0;

            //Define actual player to response
            if (_helper.IsEnoughSpaceToMove(currentRod, currentRod.State.DcPosition, movements[minIndexFirst]))
            {
                //as index starts from 0 => first one is 1
                RespondingPlayer = minIndexFirst + 1;
                movement         = movements[minIndexFirst];
            }
            else
            {
                //as index starts from 0 => first one is 1
                RespondingPlayer = minIndexSecond + 1;
                movement         = movements[minIndexSecond];
            }

            //In case we reach the ball - no move needed
            if (Math.Abs(movement) < PLAYER_WIDTH)
            {
                return(eYPositionPlayerRelative.CENTER);
            }
            else if (movement > 0)
            {
                return(eYPositionPlayerRelative.RIGHT);
            }
            else // (movement < 0)
            {
                return(eYPositionPlayerRelative.LEFT);
            }
        }
コード例 #24
0
ファイル: DecisionHelper.cs プロジェクト: djjosse/Foosbot
        /*
         * Currently not in use methods. Need to verify if needed before TESTING
         */

        /// <summary>
        /// Calculate current Player Y coordinate
        /// </summary>
        /// <param name="rod">Current rod</param>
        /// <param name="currentRodYCoordinate">Current Rod Y coordinates (stopper)</param>
        /// <param name="playerIndex">Chosen player index to perform action (index 1 based)</param>
        /// <returns>Chosen player Y coordinate</returns>
        /// <exception cref="ArgumentOutOfRangeException">Thrown in case player index is out of range</exception>
        public int CalculateCurrentPlayerYCoordinate(IRod rod, int currentRodYCoordinate, int playerIndex)
        {
            if (playerIndex > rod.PlayerCount || playerIndex < 1)
                throw new ArgumentOutOfRangeException(String.Format(
                    "Player index {0} for rod type {1} is wrong! Players count is {2}",
                        playerIndex, rod.RodType, rod.PlayerCount));

            return rod.OffsetY + currentRodYCoordinate + rod.PlayerDistance * (playerIndex - 1);
        }
コード例 #25
0
        /// <summary>
        /// Main Decision Flow Method decides on action and sets property of responding player
        /// </summary>
        /// <param name="rod">Rod to use for decision</param>
        /// <param name="bfc">Ball Future coordinates</param>
        /// <returns>Rod Action to perform</returns>
        public override RodAction Decide(IRod rod, BallCoordinates bfc)
        {
            RodAction action = new RodAction(rod.RodType);

            //Action will be ignored if not enough time passed since last request was made inside sector
            if (!IgnoreDecision(rod.RodType))
            {
                //Get relative Y position and set Responding Player
                eYPositionPlayerRelative relativeY = BallYPositionToPlayerYCoordinate(bfc.Y, rod);

                //Get relative X position
                eXPositionRodRelative relativeX = BallXPositionToRodXPosition(bfc.X, rod);

                /*
                 * Beta Version of inner DECISION TREE
                 */
                switch (relativeX)
                {
                    case eXPositionRodRelative.FRONT:
                        switch (relativeY)
                        {
                            case eYPositionPlayerRelative.RIGHT:
                            case eYPositionPlayerRelative.LEFT:
                                switch (rod.State.ServoPosition)
                                {
                                    case eRotationalMove.RISE:
                                    case eRotationalMove.DEFENCE:
                                        action = new RodAction(rod.RodType, eRotationalMove.DEFENCE, eLinearMove.BALL_Y);
                                        break;
                                    case eRotationalMove.KICK:
                                        action = new RodAction(rod.RodType, eRotationalMove.DEFENCE, eLinearMove.NA);
                                        break;
                                }
                                break;
                            case eYPositionPlayerRelative.CENTER:
                                switch (rod.State.ServoPosition)
                                {
                                    case eRotationalMove.RISE:
                                    case eRotationalMove.DEFENCE:
                                        action = new RodAction(rod.RodType, eRotationalMove.KICK, eLinearMove.NA);
                                        break;
                                    case eRotationalMove.KICK:
                                        if (_helper.IsEnoughSpaceToMove(rod, rod.State.DcPosition, BALL_RADIUS))
                                        {
                                            action = new RodAction(rod.RodType, eRotationalMove.NA, eLinearMove.RIGHT_BALL_DIAMETER);
                                        }
                                        else
                                        {
                                            action = new RodAction(rod.RodType, eRotationalMove.NA, eLinearMove.LEFT_BALL_DIAMETER);
                                        }
                                        break;
                                }
                                break;
                        }
                        break;
                    case eXPositionRodRelative.CENTER:
                    case eXPositionRodRelative.BACK:
                        switch (relativeY)
                        {
                            case eYPositionPlayerRelative.RIGHT:
                            case eYPositionPlayerRelative.LEFT:
                                switch (rod.State.ServoPosition)
                                {
                                    case eRotationalMove.RISE:
                                        action = new RodAction(rod.RodType, eRotationalMove.RISE, eLinearMove.BALL_Y);
                                        break;
                                    case eRotationalMove.DEFENCE:
                                        action = new RodAction(rod.RodType, eRotationalMove.RISE, eLinearMove.NA);
                                        break;
                                    case eRotationalMove.KICK:
                                        action = new RodAction(rod.RodType, eRotationalMove.DEFENCE, eLinearMove.NA);
                                        break;
                                }
                                break;
                            case eYPositionPlayerRelative.CENTER:
                                switch (rod.State.ServoPosition)
                                {
                                    case eRotationalMove.RISE:
                                        action = new RodAction(rod.RodType, eRotationalMove.KICK, eLinearMove.NA);
                                        break;
                                    case eRotationalMove.DEFENCE:
                                    case eRotationalMove.KICK:
                                        if (_helper.IsEnoughSpaceToMove(rod, rod.State.DcPosition, BALL_RADIUS))
                                        {
                                            action = new RodAction(rod.RodType, eRotationalMove.NA, eLinearMove.RIGHT_BALL_DIAMETER);
                                        }
                                        else
                                        {
                                            action = new RodAction(rod.RodType, eRotationalMove.NA, eLinearMove.LEFT_BALL_DIAMETER);
                                        }
                                        break;
                                }
                                break;
                        }
                        break;
                }
                Log.Print(String.Format("Defined action for {0}: [{1}] [{2}]", rod.RodType, action.Rotation, action.Linear),
                    eCategory.Info, LogTag.DECISION);
                ActivateDelay(action);

                //Define actual desired rod coordinate to move to
                int startStopperDesiredY = CalculateNewRodCoordinate(rod, RespondingPlayer, bfc, action.Linear);
                action.DcCoordinate = rod.NearestPossibleDcPosition(startStopperDesiredY);
            }
            else
            {
                Log.Print(String.Format("Ignoring inner tree of {0} for {1} milliseconds", rod.RodType,
                    (ACTION_DELAY - _sectorWatch[rod.RodType].Elapsed).TotalMilliseconds), eCategory.Debug, LogTag.DECISION);
            }

            //Set last decided rod and player coordinates if it was defined
            if (action.Linear!=eLinearMove.NA) rod.State.DcPosition = action.DcCoordinate;
            if (_helper.ShouldSetServoStateFromTree(rod.RodType))
                if (action.Rotation != eRotationalMove.NA) rod.State.ServoPosition = action.Rotation;

            return action;
        }
コード例 #26
0
ファイル: DecisionTree.cs プロジェクト: ohadsas/Foosbot-final
 /// <summary>
 /// Main Decision Flow Method
 /// </summary>
 /// <param name="rod">Rod to use for decision</param>
 /// <param name="bfc">Ball Future coordinates</param>
 /// <returns>Rod Action to perform</returns>
 public abstract RodAction Decide(IRod rod, BallCoordinates bfc);