protected override bool PlanetRouteSelected(Planet onwedPlanet, PlanetaryTravelRoute routesFromPlanet)
    {
        PlanetWorstCasePrediction = WorstCasePrediction(onwedPlanet, routesFromPlanet);
        int diff = onwedPlanet.NumShips - PlanetWorstCasePrediction.MaxDesertersAllowed;

        onwedPlanet.RemoveShips(diff);
        return(true);
    }
 protected override void PlanetRouteDeSelected(Planet onwedPlanet, PlanetaryTravelRoute planetTravelMap)
 {
     base.PlanetRouteDeSelected(onwedPlanet, planetTravelMap);
     if (Universe.IsDominating)
     {
     }
     else
     {
         if (onwedPlanet.CanSurviveIncommingAttack)
         {
             if (!PlanetWorstCasePrediction.CanSurviveIncommingAttack)
             {
                 //determine defensive action.
             }
         }
     }
 }
    protected override void CreateAttackPlanForOwnedPlanet(AttackPlan attack, Route attackRoute, PlanetaryTravelRoute planetTravelMap, ref bool continueRoute)
    {
        Planet hostile     = attack.Target;
        Planet onwedPlanet = attack.Source;

        if (!hostile.IsMine)
        {
            //No use for planets that do not produce.
            if (hostile.GrowthRate == 0)
            {
                return;
            }

            // If my enemy is attacking this planet, but not doing this strong enough,
            // Do not attack this planet and let my enemies ships crash and burn.
            if (hostile.IsNeutral && hostile.IsUnderAttack && hostile.CanSurviveIncommingAttack && !hostile.IsOnWishList)
            {
                return;
            }
            double isNeutralBias = 0;
            double defenseBias   = 0;
            if (hostile.IsNeutral)
            {
                isNeutralBias = 1;
                defenseBias   = Math.Max(Math.Min(onwedPlanet.AttackForce / (hostile.NumShips + 1.0), 5), 0) / 2;
            }
            else
            {
                defenseBias = (Math.Max((int)Math.Min(onwedPlanet.AttackForce / (attackRoute.GrowthForTravelDistance + 1), 5), 0)) / 2.0;
            }

            //we are dominating, favor enemy.
            if (Universe.IsDominating)
            {
                if (hostile.IsNeutral)
                {
                    isNeutralBias = -2;
                }
                else
                {
                    isNeutralBias = 2;
                }
            }

            double wishListBias = 0;
            if (hostile.IsOnWishList)
            {
                //	wishListBias = 3;
            }


            //Dominate planet?
            double dominatePlanetBias = 0.0;
            if (!hostile.IsNeutral)
            {
                if ((currentUniverse.Me.ShipCountInBase / 3 > attackRoute.GrowthForTravelDistance + hostile.NumShips) &&
                    (attackRoute.RelativePlanetDistance < 0.3))
                {
                    dominatePlanetBias    = 2.72;
                    attack.DominationMove = true;
                }
            }

            double growthBias = attackRoute.RelativeGrowthRate * 2;

            attack.ShipCount = (int)(onwedPlanet.NumShips * 0.6);

            attack.Sweetness =
                //favor closer planets
                attackRoute.RelativePlanetDistance +
                attackRoute.RelativeUniverseDistance +
                //favor stronger growing planets
                growthBias +
                //favor neutrals, they do not grow.
                isNeutralBias +
                wishListBias +
                dominatePlanetBias +
                defenseBias +
                hostile.GrowthRate
            ;

            attack.Enabled = true;
        }
    }
 protected virtual void PlanetRouteDeSelected(Planet onwedPlanet, PlanetaryTravelRoute planetTravelMap)
 {
 }
 //return true if we should should search this route. false to skip it
 protected virtual bool PlanetRouteSelected(Planet onwedPlanet, PlanetaryTravelRoute routesFromPlanet)
 {
     return(true);
 }
 protected static IOrderedEnumerable <IGrouping <int, Route> > PlanetRouteByDistanceDictionary(PlanetaryTravelRoute routesFromPlanet)
 {
     return(routesFromPlanet.ToLookup(item => item.DistanceInTurns).OrderBy(item => item.Key));;
 }
 protected abstract void CreateAttackPlanForOwnedPlanet(AttackPlan attack, Route attackRoute, PlanetaryTravelRoute planetTravelMap, ref bool continueRoute);
    //worst case prediction assuming everything is pushed to one planet.
    protected Planet WorstCasePrediction(Planet onwedPlanet, PlanetaryTravelRoute routesFromPlanet)
    {
        if (onwedPlanet.PlanetID == 1)
        {
        }
        NearestEnemy = null;
        int lastTurn = 0;
        //copy, can be modified and discarded !
        Planet defender = onwedPlanet.Clone();
        Planet attacker = null;

        // the number of chips all planets can push towards this planet each round
        // Start with a negative value to compensate for the growth rate
        int attackValuePerRound = -defender.GrowthRate;

        // will be decreased by attackValuePerRound  each round.
        int defendingForce = defender.AttackForce;

        foreach (var routes in PlanetRouteByDistanceDictionary(routesFromPlanet))
        {
            //difference with previous turn?
            int turnDiff = routes.Key - lastTurn;
            defendingForce -= turnDiff * attackValuePerRound;

            foreach (var route in routes)
            {
                if (route.TagetPlanetId != defender.PlanetID)
                {
                    attacker = currentUniverse.AllPlanetsOnPlanetId[route.TagetPlanetId];
                    //owner 0 can not attack,
                    if (attacker.Owner > 0)
                    {
                        if (attacker.Owner == defender.Owner)
                        {
                            defendingForce      += (int)attacker.NumShips / 2;
                            attackValuePerRound -= attacker.GrowthRate;
                        }
                        else
                        {
                            if (NearestEnemy == null)
                            {
                                NearestEnemy = route;
                            }
                            attackValuePerRound += attacker.GrowthRate;
                            defendingForce      -= attacker.NumShips;
                        }
                    }
                }
            }

            //did we survive?
            if (defendingForce > 0)
            {
                //So the part that's left standing does not have to be here.
                defender.MaxDesertersAllowed = Math.Max(Math.Min(defendingForce, defender.AttackForce), 0);
                lastTurn = routes.Key;
            }
            else
            {
                //did not survive, the planet is lost
                defender.LostAfterNumberOfTurns       = routes.Key;
                defender.ShipsRequiredToSurviveAttack = (-defendingForce) + 3;
                defender.CanSurviveIncommingAttack    = false;
                break;
            }
        }
        return(defender);
    }
    protected override void CreateAttackPlanForOwnedPlanet(AttackPlan attack, Route attackRoute, PlanetaryTravelRoute planetTravelMap, ref bool continueRoute)
    {
        Planet myPlanet = attack.Source;
        Planet hostile  = attack.Target;

        if (Universe.TurnCount > 1 && hostile.GrowthRate > 0)
        {
            //check to see if we need our strength (and leave some)
            if (myPlanet.IsUnderAttack && myPlanet.CanSurviveIncommingAttack && myPlanet.AttackForce < 10)
            {
                return;
            }
            if (myPlanet.PlanetID == 2)
            {
                if (hostile.PlanetID == 17)
                {
                }
            }

            if (Universe.TurnCount < SuperDefenseCutOffPoint)
            {
                //VERY aggressive move, putting a great army very near me.
                if ((attackRoute.DistanceInTurns < 5) &&
                    (hostile.IsUnderAttack) &&
                    ((double)hostile.Armada.EnemyFleetSize / ((double)myPlanet.AttackForce + 1) > 0.5))
                {
                    //Counter with aggressive defense, I will capture the planet
                    // how many ships needed to block enemy?
                    int shipsNeeded = Math.Max(hostile.Armada.EnemyFleetSize - hostile.Armada.FriendlyFleetSize, hostile.NumShips + attackRoute.GrowthForTravelDistance);
                    currentUniverse.MakeMove(myPlanet, hostile, shipsNeeded + 1);
                    continueRoute = false;
                    return;
                }

                //Close quarters fighting is special. Can I kill him early?
                if (hostile.IsEnemy && (attackRoute.GrowthForTravelDistance + hostile.NumShips) < myPlanet.ShipCountAtStartOfTurn)
                {
                    if (myPlanet.IsUnderAttack)
                    {
                        // Do not lose the planet, be defensive.
                        continueRoute = false;
                        return;
                    }
                    else
                    {
                        if (hostile.CanSurviveIncommingAttack)
                        {
                            //He is still healthy, attack
                            int max = attackRoute.GrowthForTravelDistance + hostile.NumShips + hostile.GrowthRate;
                            currentUniverse.MakeUnsafeMove(myPlanet, hostile, Math.Min(max, myPlanet.NumShips));
                            continueRoute = false;
                            return;
                        }
                        //ok, so this planet is beat. next please.
                    }
                }

                if (NearestEnemy == null || attackRoute.ActualDistance > NearestEnemy.ActualDistance)
                {
                    return;
                }
            }

            if (Universe.IsDominating)
            {
                if (!myPlanet.IsUnderAttack)
                {
                    if (hostile.CanSurviveIncommingAttack)
                    {
                        attack.ShipCount = (int)(myPlanet.AttackForce * 0.9);
                        attack.Enabled   = true;

                        if (hostile.IsNeutral)
                        {
                            attack.Sweetness = (double)hostile.GrowthRate - 2;
                        }
                        if (hostile.IsEnemy)
                        {
                            attack.Sweetness = (double)hostile.GrowthRate;
                        }
                    }
                }
            }
            else
            {
                bool isNear = attackRoute.ActualDistance < Universe.TravelMap.AverageDistance;
                if (myPlanet.PlanetID == 7)
                {
                    if (hostile.PlanetID == 14)
                    {
                    }
                }

                double ConnectedNess = Universe.TravelMap.AverageDistance / attackRoute.TargetConnectiveNess;


                if (isNear || Universe.IsDominating)
                {
                    double powerbase = hostile.GrowthRate;
                    if (hostile.IsNeutral)
                    {
                        powerbase += 0.5;
                    }
                    attack.Sweetness = (Math.Pow(powerbase, ConnectedNess) / (attackRoute.ActualDistance));

                    attack.ShipCount = myPlanet.AttackForce;

                    if (hostile.IsEnemy)
                    {
                        bool fleetStrongrThanPlanet = attackRoute.GrowthForTravelDistance + hostile.NumShips < myPlanet.AttackForce;
                        if (fleetStrongrThanPlanet || hostile.IsOnWishList)
                        {
                            //attack.Sweetness = -(hostile.NumShips + (hostile.GrowthRate * attackRoute.Distance));
                            //attack.Sweetness = Math.Pow(hostile.GrowthRate, 3) / Math.Pow(attackRoute.DistanceInTurns, 1.5);

                            attack.Enabled = true;
                        }
                    }
                    else
                    {
                        if (Universe.IsDominating || hostile.Armada.EffectiveFleetSizeForMe() < myPlanet.AttackForce || hostile.IsOnWishList)
                        {
                            //attack.ShipCount = (int)(hostile.NumShips * 1.10);
                            attack.Enabled = true;
                        }
                    }

                    System.Diagnostics.Debug.WriteLine(
                        "(" + myPlanet.PlanetID + ") " + attack.ShipCount + " ==> (" + hostile.PlanetID + ") C: " + ConnectedNess + "  D: (" + attackRoute.ActualDistance + ") Like:" + attack.Sweetness);
                }
            }
        }
    }
    protected override void CreateAttackPlanForOwnedPlanet(AttackPlan attack, Route attackRoute, PlanetaryTravelRoute planetTravelMap, ref bool continueRoute)
    {
        Planet hostile = attack.Target;
        Planet onwedPlanet = attack.Source;
        if (!hostile.IsMine)
        {
            //No use for planets that do not produce.
            if (hostile.GrowthRate == 0)
            {
                return;
            }

            // If my enemy is attacking this planet, but not doing this strong enough,
            // Do not attack this planet and let my enemies ships crash and burn.
            if (hostile.IsNeutral && hostile.IsUnderAttack && hostile.CanSurviveIncommingAttack && !hostile.IsOnWishList)
            {
                return;
            }
            double isNeutralBias = 0;
            double defenseBias = 0;
            if (hostile.IsNeutral)
            {
                isNeutralBias = 1;
                defenseBias = Math.Max(Math.Min(onwedPlanet.AttackForce / (hostile.NumShips + 1.0), 5), 0) / 2;
            }
            else
            {
                defenseBias = (Math.Max((int)Math.Min(onwedPlanet.AttackForce / (attackRoute.GrowthForTravelDistance + 1), 5), 0)) / 2.0;
            }

            //we are dominating, favor enemy.
            if (Universe.IsDominating)
            {
                if (hostile.IsNeutral)
                {
                    isNeutralBias = -2;
                }
                else
                {
                    isNeutralBias = 2;
                }
            }

            double wishListBias = 0;
            if (hostile.IsOnWishList)
            {
                //	wishListBias = 3;
            }

            //Dominate planet?
            double dominatePlanetBias = 0.0;
            if (!hostile.IsNeutral)
            {
                if ((currentUniverse.Me.ShipCountInBase / 3 > attackRoute.GrowthForTravelDistance + hostile.NumShips)
                    && (attackRoute.RelativePlanetDistance < 0.3))
                {
                    dominatePlanetBias = 2.72;
                    attack.DominationMove = true;
                }
            }

            double growthBias = attackRoute.RelativeGrowthRate * 2;

            attack.ShipCount = (int)(onwedPlanet.NumShips * 0.6);

            attack.Sweetness =
                //favor closer planets
                attackRoute.RelativePlanetDistance +
                attackRoute.RelativeUniverseDistance +
                //favor stronger growing planets
                growthBias +
                //favor neutrals, they do not grow.
                isNeutralBias +
                wishListBias +
                dominatePlanetBias +
                defenseBias +
                hostile.GrowthRate
                ;

            attack.Enabled = true;
        }
    }
 protected virtual IEnumerable<Route> SortRoutesForBattlePlanCreation(PlanetaryTravelRoute planetTravelMap)
 {
     return planetTravelMap;
 }
 //return true if we should should search this route. false to skip it
 protected virtual bool PlanetRouteSelected(Planet onwedPlanet, PlanetaryTravelRoute routesFromPlanet)
 {
     return true;
 }
 protected virtual void PlanetRouteDeSelected(Planet onwedPlanet, PlanetaryTravelRoute planetTravelMap)
 {
 }
 protected abstract void CreateAttackPlanForOwnedPlanet(AttackPlan attack, Route attackRoute, PlanetaryTravelRoute planetTravelMap, ref bool continueRoute);
 protected static IOrderedEnumerable<IGrouping<int, Route>> PlanetRouteByDistanceDictionary(PlanetaryTravelRoute routesFromPlanet)
 {
     return routesFromPlanet.ToLookup(item => item.DistanceInTurns).OrderBy(item => item.Key); ;
 }