예제 #1
0
 /// <summary>
 /// Returns a boolean value expressing whether or not a new vessel can be added to an existing group while fulfilling
 /// grouping constraints.
 /// One grouping: Every item in the group must be within the one-grouping parameter of each other.
 /// Two grouping: At least one pair in the group must be separated by the two-grouping parameter.
 /// </summary>
 /// <param name="oneOrTwo">Must be "One" or "Two" for a one- or two-grouping</param>
 /// <param name="newVessel">Vessel to be added to the group</param>
 /// <param name="otherVessels">Existing group of vessels</param>
 /// <returns></returns>
 private bool MatchesGroupingCriteria(T_Groupings grouping, DDDAdapter.SeamateObject newVessel, List <DDDAdapter.SeamateObject> otherVessels)
 {
     if (otherVessels.Contains(newVessel))
     {
         return(false);
     }
     if (grouping == T_Groupings.One)
     {
         foreach (DDDAdapter.SeamateObject vessel in otherVessels)
         {
             double distance = new Vec2D(vessel.Location).ScalerDistanceTo(new Vec2D(newVessel.Location));
             if (distance > oneGroupingDistance)
             {
                 return(false);
             }
         }
         return(true);
     }
     else
     {
         foreach (DDDAdapter.SeamateObject vessel in otherVessels)
         {
             double distance = new Vec2D(vessel.Location).ScalerDistanceTo(new Vec2D(newVessel.Location));
             if (distance > twoGroupingDistance)
             {
                 return(true);
             }
         }
         return(false);
     }
 }
예제 #2
0
        /// <summary>
        /// Determines whether a merchant is within grouping constraints of previously chosen pirates.
        /// </summary>
        /// <param name="vessel">Merchant</param>
        /// <returns>Boolean</returns>
        private bool MatchesGroupingConstraints(DDDAdapter.SeamateObject vessel)
        {
            if (vessel.Intent != "")
            {
                return(false);
            }

            if (grouping == T_Groupings.One)
            {
                foreach (T_Move key in dict.Keys)
                {
                    Vec2D  otherVesselLocation = new Vec2D(GetLocation(key, dict[key]));
                    double distance            = new Vec2D(vessel.Location).ScalerDistanceTo(otherVesselLocation);
                    if (distance > oneGroupingDistance)
                    {
                        return(false);
                    }
                }
                return(true);
            }
            else
            {
                return(true);
            }
        }
예제 #3
0
        /// <summary>
        /// Returns a boolean value expressing whether or not a vessel is suitable to be chosen to express a stimuli.
        /// </summary>
        /// <param name="vessel"></param>
        /// <returns></returns>
        private bool IsReusable(DDDAdapter.SeamateObject vessel)
        {
            //merchants may be attacked by multiple pirates, so it's ok to choose them even if they
            //already have an intent.
            bool isMerchantOrNotOnAttackCourse = ((vessel.Owner == "Merchant DM") || (vessel.Intent == ""));

            return(vessel.Owner == owner && Polygon2D.IsPointInside(domain, new Vec2D(vessel.Location)) && isMerchantOrNotOnAttackCourse);
        }
예제 #4
0
        /// <summary>
        /// Adds a new move event to the action list.  Does not contain a destination yet
        /// </summary>
        /// <param name="vessel"></param>
        protected void CreateEmptyMove(DDDAdapter.SeamateObject vessel)
        {
            T_Move move = new T_Move();

            move.ID       = vessel.ID;
            move.Location = new T_Location();
            actions.Add(move);
        }
예제 #5
0
        public double GetMaxSpeed(T_Move move)
        {
            DDDAdapter.SeamateObject seamateObject = ddd.GetSeamateObject(move.ID);
            if (seamateObject.MaximumSpeed > 0)
            {
                return(seamateObject.MaximumSpeed);
            }
            String className = ddd.GetSeamateObject(move.ID).ClassName;
            //if (className.Trim() == "") //handles erroneous blank className, remove this code when Adam fixes
            //    return 75;
            Dictionary <string, DataValue> speciesStateParameters = ddd.GetSpeciesStateParameters(className, "FullyFunctional");

            return(((DoubleValue)speciesStateParameters["MaximumSpeed"]).value);
        }
예제 #6
0
        /// <summary>
        /// Takes an EXISTING merchant and pirate and returns their shortest potential intercept time.
        /// </summary>
        /// <param name="merchant"></param>
        /// <param name="pirate"></param>
        /// <returns></returns>

        protected double PotentialTimeToIntercept(DDDAdapter.SeamateObject pirate, DDDAdapter.SeamateObject merchant)
        {
            Vec2D  pirateLocation = new Vec2D(pirate.Location);
            double pirateSpeed    = GetMaxSpeed(pirate);

            double merchantSpeed       = merchant.Throttle * merchant.MaximumSpeed;
            Vec2D  merchantStart       = new Vec2D(merchant.Location);
            Vec2D  merchantDestination = new Vec2D(merchant.DestinationLocation);
            Vec2D  interceptPoint      = GetInterceptPoint(merchantStart, merchantDestination, merchantSpeed, pirateLocation, pirateSpeed);

            double timeToIntercept = merchantStart.ScalerDistanceTo(interceptPoint) / merchantSpeed;

            return(timeToIntercept);
        }
예제 #7
0
        protected double GetMaxSpeed(DDDAdapter.SeamateObject seamateObject)
        {
            if (seamateObject.MaximumSpeed > 0)
            {
                return(seamateObject.MaximumSpeed);
            }
            String className = seamateObject.ClassName;

            if (className.Trim() == "") //handles erroneous blank className, remove this code when Adam fixes
            {
                return(75);
            }
            Dictionary <string, DataValue> speciesStateParameters = ddd.GetSpeciesStateParameters(className, "FullyFunctional");

            return(((DoubleValue)speciesStateParameters["MaximumSpeed"]).value);
        }
예제 #8
0
        /// <summary>
        /// Checks whether an existing pirate is either positioned within a 60s attack range of an existing vessel, or within 60s of an entry region.
        /// </summary>
        /// <param name="pirate"></param>
        /// <returns></returns>
        Boolean PirateIsWithinOneMinuteAttackRange(DDDAdapter.SeamateObject pirate, List <PolygonValue> entryRegions)
        {
            foreach (DDDAdapter.SeamateObject vessel in revealedSeaVessels)
            {
                //First compare all the existing merchants' positions to see if they are within range.
                if (vessel.Owner == "Merchant DM")
                {
                    if (PotentialTimeToIntercept(pirate, vessel) < 60)
                    {
                        return(true);
                    }
                }
                else
                {
                    continue;  //ignore merchants or fleet ships
                }
            }

            //There was no existing merchant in range.  Now we need to check if any entry region is in range
            //to possibly create a merchant there.  I do this by iterating over each boundary point and checking if any of them
            //is reachable by the pirate in 60 seconds.

            foreach (PolygonValue entryRegion in entryRegions)
            {
                foreach (PolygonValue.PolygonPoint entryPoint in entryRegion.points)
                {
                    Vec2D  point       = new Vec2D(entryPoint.X, entryPoint.Y);
                    double distance    = point.ScalerDistanceTo(new Vec2D(pirate.Location));
                    double timeToPoint = distance / pirate.MaximumSpeed;
                    if (timeToPoint < 60)
                    {
                        return(true);
                    }
                }
            }

            //If we got this far, there is no existing merchant or entry region in which to create a merchant
            //reachable by the pirate in 60 sec.
            return(false);
        }
예제 #9
0
        //Pirate generator -- generates or chooses several pirates or friendly vessels in DM domain
        //So either creates a RevealEvent or chooses existing vessel for MoveEvent

        public override void Generate(T_Item currentItem, String dmID)
        {
            if (currentItem.Parameters.Threat == T_Threat.None)
            {
                return;
            }


            actions = currentItem.Action.ToList();

            // Do some setup
            bool isPirate = !(currentItem.Parameters.Threat == T_Threat.None);

            if (isPirate)
            {
                owner = "Pirate DM";
            }
            else
            {
                owner = "Merchant DM";
            }

            PolygonValue domainPV = this.ddd.GetDecisionMakersAreaOfResponsibility(dmID);

            domain = new Polygon2D(domainPV);
            List <string> unrevealedObjectIDs = ddd.GetAllUnrevealedObjectIds(isPirate, true, null);


            //How many pirates should we generate?  These numbers may need tweaking
            int minPirates = Properties.Settings.Default.minPirates;
            int maxPirates = Properties.Settings.Default.maxPirates;
            int numPirates = random.Next(minPirates, maxPirates);


            //Are there any pirates we can reuse, already in play?
            List <DDDAdapter.SeamateObject> reusableVessels = revealedSeaVessels.FindAll(IsReusable);

            if (reusableVessels.Count > 0 && Properties.Settings.Default.reusePirates)
            {
                for (int i = 0; i < numPirates; i++)
                {
                    if (reusableVessels.Count > 0)
                    {
                        DDDAdapter.SeamateObject vessel = reusableVessels[0];
                        reusableVessels.Remove(vessel);
                        CreateEmptyMove(vessel);
                    }
                    else
                    {
                        Vec2D  location = MakeLocationInEntryRegions(entryRegions);
                        string id       = unrevealedObjectIDs[random.Next(unrevealedObjectIDs.Count())];
                        unrevealedObjectIDs.Remove(id);
                        CreateRevealAndEmptyMove(id, owner, location);
                    }
                }


                ////See if any existing pirates can be paired under "grouping" distance constraints
                //List<List<DDDAdapter.SeamateObject>> groupedPirates = GroupVessels(currentItem.Parameters.Groupings, numPirates, reusableVessels);
                //List<List<DDDAdapter.SeamateObject>> groupsOfNumPirateSize = groupedPirates.FindAll(delegate(List<DDDAdapter.SeamateObject> g) { return g.Count >= numPirates; });

                ////Any groups of numPirates?
                //if (groupsOfNumPirateSize.Count > 0)
                //{
                //    //if yes, make dummy move events for them and add to actions list.  done.
                //    foreach (DDDAdapter.SeamateObject pirate in groupsOfNumPirateSize.ElementAt(0))
                //        CreateEmptyMove(pirate);
                //}
                //else
                //{
                //    //Can any of these smaller groupings include an entry region too, so we can add new pirates?
                //    groupedPirates.Sort(delegate(List<DDDAdapter.SeamateObject> g1, List<DDDAdapter.SeamateObject> g2) { return g1.Count.CompareTo(g2.Count); }); //sort by size, largest first
                //    foreach (List<DDDAdapter.SeamateObject> group in groupedPirates)
                //    {
                //        List<PolygonValue> matchingEntryRegions = GetMatchingEntryRegions(currentItem.Parameters.Groupings, group, entryRegions);
                //        if (matchingEntryRegions.Count > 0)
                //        {
                //            //if yes, then make dummy move events for the pirates in grouping, then
                //            foreach (DDDAdapter.SeamateObject pirate in groupsOfNumPirateSize.ElementAt(0))
                //                CreateEmptyMove(pirate);
                //            //Create as many remaining pirates as we need distributed randomly among suitable entry regions.
                //            List<Vec2D> locations = MakeLocationsInEntryRegions(numPirates - group.Count, matchingEntryRegions);
                //            foreach (Vec2D location in locations)
                //            {
                //                string id = unrevealedObjectIDs[random.Next(unrevealedObjectIDs.Count())];
                //                unrevealedObjectIDs.Remove(id);
                //                CreateRevealAndEmptyMove(id, owner, location);
                //            }
                //            break;
                //        }
                //    }

                //    //if no, we couldn't include an entry region (where new pirates would be created) with any existing pirates
                //    if (actions.Count == 0)
                //        //TODO: maybe should make smaller num of pirates if above min rather than making all new?
                //        MakeAllNewPirates(currentItem.Parameters.Groupings,numPirates,entryRegions,unrevealedObjectIDs);
                //}
            }
            //no reusable vessels, we have to create all new pirates
            else
            {
                MakeAllNewPirates(currentItem.Parameters.Groupings, numPirates, entryRegions, unrevealedObjectIDs);
            }

            currentItem.Action = actions.ToArray();
        }
예제 #10
0
        public override void Generate(T_Item currentItem, String dmID)
        {
            //Identify what's already in actions list.
            foreach (Object action in currentItem.Action)
            {
                if (action as T_Move != null)
                {
                    primaryMove = (T_Move)action;
                }
                if (action as T_Reveal != null)
                {
                    primaryReveal = (T_Reveal)action;
                }
            }
            LocationValue location          = GetLocation(primaryMove, primaryReveal);
            bool          isPirate          = GetOwner(primaryMove, primaryReveal) == "Pirate DM";
            PolygonValue  pirateEntryRegion = null;

            if (isPirate)
            {
                foreach (PolygonValue region in entryRegions)
                {
                    if (Polygon2D.IsPointInside(new Polygon2D(region), new Vec2D(location)))
                    {
                        pirateEntryRegion = region;
                        break;
                    }
                }
            }


            List <Object> list = currentItem.Action.ToList();

            List <string> unrevealedObjectIDs = ddd.GetAllUnrevealedObjectIds(false, true, null);

            if (primaryReveal != null)
            {
                unrevealedObjectIDs.Remove(primaryReveal.ID);
            }


            int minStimuli = 0;

            //If threat type is imminent, we need to guarantee there will be a merchant for the pirate to attack.
            if (currentItem.Parameters.ThreatType == T_ThreatType.Imminent)
            {
                minStimuli = 1;
            }


            int maxStimuli;

            //If resources need to be available, then two is maximum of stimulus events.
            if (T_ResourceAvailability.Available == currentItem.Parameters.PlayerResources)
            {
                maxStimuli = 2;
            }
            //If resources are unavailable, there must be at least 3 total stimulus events, and max can be higher.
            else
            {
                minStimuli = 3;
                maxStimuli = 5;
            }

            int numStimuliToGenerate = this.changingNumber(minStimuli, 60, minStimuli, maxStimuli); //probably minStimuli but could be up to maxStimuli


            //If our probability criteria says we should add vessels, try and populate reusable objects list
            List <DDDAdapter.SeamateObject> reuseableObjects = new List <DDDAdapter.SeamateObject>();

            if (shouldAddNewVessel(revealedSeaVessels))
            {
                reuseableObjects = findObjectsInPlay(location, pirateEntryRegion, currentItem.Parameters.Groupings, false);
            }

            for (int i = 0; i < numStimuliToGenerate; i++)
            {
                T_Move move = new T_Move();

                //Try and recycle objects to create stimulus.
                if (reuseableObjects.Count != 0)
                {
                    Shuffle(reuseableObjects);
                    DDDAdapter.SeamateObject objectForReuse = null;
                    //see if any eligible vessels are stopped, if so, use one of them
                    foreach (DDDAdapter.SeamateObject possiblyStoppedVessel in reuseableObjects)
                    {
                        if (possiblyStoppedVessel.Throttle == 0) //yes, it is stopped
                        {
                            //Console.WriteLine("GRoupingGenerator: Picking a stopped vessel " + possiblyStoppedVessel.ID + " to reuse.");
                            objectForReuse = possiblyStoppedVessel;
                            break;
                        }
                    }
                    //randomly pick one of the suitable objects to create a stimulus
                    if (objectForReuse == null)
                    {
                        objectForReuse = reuseableObjects[random.Next(reuseableObjects.Count)];
                    }

                    move.ID = objectForReuse.ID;
                    reuseableObjects.Remove(objectForReuse);
                    //Console.WriteLine("GroupingGenerator: Moving existing merchant " + objectForReuse.ID);
                }
                else //Reveal and move new merchant.
                {
                    T_Reveal reveal = new T_Reveal();
                    reveal.Owner                   = "Merchant DM";
                    reveal.State                   = "FullyFunctional";
                    reveal.StartupParameters       = new T_StartupParameters();
                    reveal.StartupParameters.Items = new string[0];
                    reveal.ID = unrevealedObjectIDs[random.Next(unrevealedObjectIDs.Count)]; //pick a random new object
                    unrevealedObjectIDs.Remove(reveal.ID);                                   //take it out of the available list

                    //ADDED 11/10/11:  To make sure that the merchants don't end up in the same entry region as a newly created pirate,
                    //if there's a new pirate, instead of iterating over all entry regions we'll remove the pirate's region from the list first.
                    if (pirateEntryRegion != null)
                    {
                        entryRegions.Remove(pirateEntryRegion);
                    }

                    Vec2D point = null;

                    //If two grouping, pick points in entry regions until one is > 100 away
                    if (currentItem.Parameters.Groupings == T_Groupings.Two)
                    {
                        while (true)
                        {
                            point = new Polygon2D(entryRegions[random.Next(entryRegions.Count)]).PointInside();
                            if (point.ScalerDistanceTo(new Vec2D(location)) > twoGroupingDistance)
                            {
                                break;
                            }
                        }
                    }
                    //If one grouping, see if any entry region is within 50km.  If so, pick a point in that entry region.
                    //It's possible that no entry region may be within 50km.  In that case, pick a point in the closest one.

                    if (currentItem.Parameters.Groupings == T_Groupings.One)
                    {
                        double       closestDistance = 100000000;
                        PolygonValue closestRegion   = null;
                        Shuffle(entryRegions);

                        foreach (PolygonValue entryRegion in entryRegions)
                        {
                            Polygon2D entry2D  = new Polygon2D(entryRegion);
                            double    distance = Polygon2D.ScalarDistanceToPolygon(entry2D, new Vec2D(location));

                            if (distance < oneGroupingDistance)
                            {
                                point = entry2D.PointInside();
                                break;
                            }
                            else
                            {
                                if (distance < closestDistance)
                                {
                                    closestDistance = distance;
                                    closestRegion   = entryRegion;
                                }
                            }
                        }
                        if (point == null)
                        {
                            //Console.WriteLine("GroupingGenerator: Unable to place vessel in an entry region AND <100km away.  Placing in closest entry region " + closestDistance + " away.");
                            point = new Polygon2D(closestRegion).PointInside();
                        }
                    }
                    reveal.Location      = new T_Location();
                    reveal.Location.Item = point.ToLocationValue();
                    list.Add(reveal);

                    move.ID = reveal.ID;
                    //Console.WriteLine("GroupingGenerator: Revealing new merchant " + reveal.ID + " and moving it");
                }

                move.Location = new T_Location();
                list.Add(move);
            }

            currentItem.Action = list.ToArray();
        }
예제 #11
0
        //Threat generator -- generates or chooses ONE pirate or friendly vessel in DM domain
        //So either creates a RevealEvent or chooses existing vessel for MoveEvent
        public List <DDDAdapter.SeamateObject> GenerateWithTriedItems(T_Item currentItem, String dmID, List <DDDAdapter.SeamateObject> triedVessels)
        {
            //make a copy of the input which we'll modify and return at the end
            List <DDDAdapter.SeamateObject> returnTriedVessels = new List <DDDAdapter.SeamateObject>(triedVessels);

            String owner;
            bool   isPirate;

            if (currentItem.Parameters.Threat == T_Threat.None)
            {
                isPirate = false;
                owner    = "Merchant DM";
            }
            else
            {
                isPirate = true;
                owner    = "Pirate DM";
            }


            PolygonValue domainPV = this.ddd.GetDecisionMakersAreaOfResponsibility(dmID);
            Polygon2D    domain   = new Polygon2D(domainPV);

            List <Object> actions = new List <object>();

            if (shouldAddNewVessel(revealedSeaVessels))
            {
                Console.WriteLine("ThreatGenerator: I'm trying to reuse a vessel because there are " + revealedSeaVessels.Count + " in play already and/or probability told me to.");
                List <DDDAdapter.SeamateObject> vessels = new List <DDDAdapter.SeamateObject>();
                //Find all vessels of the appropriate type (pirate or merchant) within the BAMS/Firescout's range.
                foreach (DDDAdapter.SeamateObject vessel in revealedSeaVessels)
                {
                    if (vessel.Owner == owner && Polygon2D.IsPointInside(domain, new Vec2D(vessel.Location)))
                    {
                        vessels.Add(vessel);
                    }
                }
                Console.WriteLine("ThreatGenerator: Found " + vessels.Count + " to reuse");

                if (vessels.Count > 0)
                {
                    //manage the list of previously tried objects
                    if (triedVessels.Count == vessels.Count)
                    {
                        returnTriedVessels = new List <DDDAdapter.SeamateObject>();
                    }
                    foreach (DDDAdapter.SeamateObject alreadyTried in returnTriedVessels)
                    {
                        vessels.Remove(alreadyTried);
                    }

                    Shuffle(vessels);
                    DDDAdapter.SeamateObject vessel = null;
                    //see if any eligible vessels are stopped, if so, use one of them
                    foreach (DDDAdapter.SeamateObject possiblyStoppedVessel in vessels)
                    {
                        if (possiblyStoppedVessel.Throttle == 0) //yes, it is stopped
                        {
                            Console.WriteLine("ThreatGenerator: Picking a stopped vessel " + possiblyStoppedVessel.ID + " to reuse.");
                            vessel = possiblyStoppedVessel;
                            break;
                        }
                    }
                    //we didn't find any stopped vessels, so pick a random eligible one.
                    if (vessel == null)
                    {
                        vessel = vessels[random.Next(vessels.Count)];
                    }
                    returnTriedVessels.Add(vessel);
                    T_Move move = new T_Move();
                    move.ID       = vessel.ID;
                    move.Location = new T_Location();

                    actions.Add(move);
                }
            }

            if (actions.Count() == 0) //we couldn't find a ship or need more vessels
            {                         //reveal a random new one
                Console.WriteLine("ThreatGenerator: I'm revealing a new vessel, either couldn't find a ship or need more vessels.");
                List <string> unrevealedObjectIDs = ddd.GetAllUnrevealedObjectIds(isPirate, true, null);

                T_Reveal reveal = new T_Reveal();
                reveal.ID                      = unrevealedObjectIDs[random.Next(unrevealedObjectIDs.Count())];
                reveal.Owner                   = owner;
                reveal.State                   = "FullyFunctional";
                reveal.Location                = new T_Location();
                reveal.StartupParameters       = new T_StartupParameters();
                reveal.StartupParameters.Items = new string[0];

                T_Move move = new T_Move();
                move.ID       = reveal.ID;
                move.Location = new T_Location();
                Vec2D point;
                List <PolygonValue> entryRegions = ddd.GetAllEntryRegions();
                //TODO: Write a safe PointInsideMultipleDomains() function.  This could theoretically loop forever with a terrible scenario
                while (true)
                {
                    point = new Polygon2D(entryRegions[random.Next(entryRegions.Count)]).PointInside();
                    if (Polygon2D.IsPointInside(domain, point))
                    {
                        break;
                    }
                }
                reveal.Location.Item = point.ToLocationValue();

                actions.Add(reveal);
                actions.Add(move);
                Console.WriteLine("ThreatGenerator: Just revealed a pirate " + reveal.ID);
            }


            currentItem.Action = actions.ToArray();
            return(returnTriedVessels);
        }
예제 #12
0
        /// <summary>
        /// Calculates an intercept course for all pirates
        /// </summary>
        /// <param name="currentItem"></param>
        /// <param name="dmID"></param>

        public override void Generate(T_Item currentItem, String dmID)
        {
            Dictionary <T_Move, T_Reveal> dict = GetActionsAsDictionary(currentItem.Action);
            //Make new dictionaries; they will be copies containing either merchants or pirates
            Dictionary <T_Move, T_Reveal> merchantsDict = new Dictionary <T_Move, T_Reveal>();
            Dictionary <T_Move, T_Reveal> piratesDict   = new Dictionary <T_Move, T_Reveal>();

            //Copy pirates and merchants into dictionaries
            foreach (T_Move key in dict.Keys)
            {
                if (GetOwner(key, dict[key]) == "Pirate DM")
                {
                    piratesDict.Add(key, dict[key]);
                }
                else
                {
                    merchantsDict.Add(key, dict[key]);
                }
            }

            if (piratesDict.Keys.Count == 0)
            {
                return;
            }

            //This dictionary of pirates is the one we'll use to save intercept courses.
            Dictionary <T_Move, T_Reveal> piratesWithInterceptCourse = new Dictionary <T_Move, T_Reveal>();

            //Set each pirate on the shortest intercept course to a newly revealed or existing merchant.
            foreach (T_Move pirateMove in piratesDict.Keys)
            {
                Vec2D pirateLocation = new Vec2D(GetLocation(pirateMove, piratesDict[pirateMove]));

                //=========Check newly revealed merchants created in this item to find closest ===========================//
                double timeToIntercept       = 1000000000000000;
                Vec2D  closestInterceptPoint = null;
                T_Move closestNewMerchant    = null;

                foreach (T_Move merchantMove in merchantsDict.Keys)
                {
                    double merchantSpeed           = merchantMove.Throttle * GetMaxSpeed(merchantMove);
                    Vec2D  merchantStart           = new Vec2D(GetLocation(merchantMove, merchantsDict[merchantMove]));
                    Vec2D  merchantDestination     = new Vec2D((LocationValue)merchantMove.Location.Item);
                    Vec2D  interceptPoint          = GetInterceptPoint(merchantStart, merchantDestination, merchantSpeed, pirateLocation, GetMaxSpeed(pirateMove));
                    double merchantTimeToIntercept = merchantStart.ScalerDistanceTo(interceptPoint) / merchantSpeed;
                    if (merchantTimeToIntercept < timeToIntercept)
                    {
                        closestNewMerchant    = merchantMove;
                        closestInterceptPoint = interceptPoint;
                        timeToIntercept       = merchantTimeToIntercept;
                    }
                }

                //============Check merchants already revealed, see if one is closer ========================
                //TODO: make sure any merchants we will move in this round are not being compared
                DDDAdapter.SeamateObject closestRevealedMerchant = null;

                foreach (DDDAdapter.SeamateObject vessel in revealedSeaVessels)
                {
                    //Compare all the existing merchants' positions to see if they are closer.

                    //if (vessel.ID == closestNewMerchant.ID) continue;

                    if (vessel.Owner == "Merchant DM")
                    {
                        double merchantSpeed       = vessel.Throttle * vessel.MaximumSpeed;
                        Vec2D  merchantStart       = new Vec2D(vessel.Location);
                        Vec2D  merchantDestination = new Vec2D(vessel.DestinationLocation);
                        Vec2D  interceptPoint      = GetInterceptPoint(merchantStart, merchantDestination, merchantSpeed, pirateLocation, GetMaxSpeed(pirateMove));

                        double merchantTimeToIntercept = merchantStart.ScalerDistanceTo(interceptPoint) / merchantSpeed;
                        if (merchantTimeToIntercept < timeToIntercept)
                        {
                            closestNewMerchant      = null;
                            closestRevealedMerchant = vessel;
                            closestInterceptPoint   = interceptPoint;
                            timeToIntercept         = merchantTimeToIntercept;
                        }
                    }
                    else
                    {
                        continue;  //ignore pirates or fleet ships
                    }
                }


                if (closestInterceptPoint == null)
                {
                    return;
                }
                //Make a new move for the pirate, containing the pirate's intercept course.
                T_Move moveWithInterceptCourse = new T_Move();
                moveWithInterceptCourse.ID            = pirateMove.ID;
                moveWithInterceptCourse.Throttle      = 1.0;
                moveWithInterceptCourse.Location      = new T_Location();
                moveWithInterceptCourse.Location.Item = closestInterceptPoint.ToLocationValue();



                //Set the pirate and merchant's "Intent" relating to the intercept in their SimObjects
                if (closestNewMerchant != null)
                {
                    ddd.UpdateObjectAttribute(closestNewMerchant.ID, "Intent", "Being intercepted:" + pirateMove.ID + ":" + timeToIntercept, "AGENT"); //Merchant
                    ddd.UpdateObjectAttribute(pirateMove.ID, "Intent", "Intercepting:" + closestNewMerchant.ID + ":" + timeToIntercept, "AGENT");      //Pirate
                }
                else if (closestRevealedMerchant != null)
                {
                    ddd.UpdateObjectAttribute(closestRevealedMerchant.ID, "Intent", "Being intercepted:" + pirateMove.ID + ":" + timeToIntercept, "AGENT"); //Merchant
                    ddd.UpdateObjectAttribute(pirateMove.ID, "Intent", "Intercepting:" + closestRevealedMerchant.ID + ":" + timeToIntercept, "AGENT");      //Pirate
                }
                else
                {
                    Console.Error.WriteLine("Fix intercept generator");
                }


                //Add the pirate's updated move and reveal to pirate dictionary.
                piratesWithInterceptCourse[moveWithInterceptCourse] = piratesDict[pirateMove];
            }

            //Add altered pirates back to merchants, and reset the action array.
            currentItem.Action = GetActionsFromDictionary(merchantsDict.Concat(piratesWithInterceptCourse).ToDictionary(kvp => kvp.Key, kvp => kvp.Value));
        }
예제 #13
0
 private static bool onlyMerchant(DDDAdapter.SeamateObject vessel)
 {
     return(vessel.Owner == "Merchant DM");
 }
예제 #14
0
 /// <summary>
 /// Returns a boolean value expressing whether or not a vessel is stopped.
 /// </summary>
 /// <param name="vessel"></param>
 /// <returns></returns>
 protected bool IsStopped(DDDAdapter.SeamateObject vessel)
 {
     return(vessel.Throttle == 0);
 }
예제 #15
0
        public override void Generate(T_Item currentItem, String dmID)
        {
            actions  = currentItem.Action.ToList();
            dict     = GetActionsAsDictionary(currentItem.Action);
            grouping = currentItem.Parameters.Groupings;


            List <string> unrevealedMerchantIDs = ddd.GetAllUnrevealedObjectIds(false, true, null); //Gets only merchants


            int minStimuli = 1;
            int maxStimuli;

            //If resources need to be available, then two is maximum of stimulus events.
            if (T_ResourceAvailability.Available == currentItem.Parameters.PlayerResources)
            {
                maxStimuli = Properties.Settings.Default.resourceThreshold - 1;
            }
            //If resources are unavailable, there must be at least 3 total stimulus events, and max can be higher.
            else
            {
                minStimuli = Properties.Settings.Default.resourceThreshold;
                maxStimuli = Properties.Settings.Default.resourceThreshold * 2 - 1;
            }

            int numPirates   = dict.Keys.Count;
            int numMerchants = Math.Max(0, random.Next(minStimuli, maxStimuli) - numPirates);

            if (numMerchants == 0)
            {
                return;
            }


            //If our probability criteria says we should add vessels, let's see if we can reuse any existing vessels
            List <DDDAdapter.SeamateObject> reuseableVessels     = new List <DDDAdapter.SeamateObject>();
            List <DDDAdapter.SeamateObject> allExistingMerchants = revealedSeaVessels.FindAll(IsMerchant);

            if (shouldAddNewVessel(revealedSeaVessels))
            {
                reuseableVessels = allExistingMerchants.FindAll(MatchesGroupingConstraints);
            }

            for (int i = 0; i < numMerchants; i++)  //Do once for each merchant we need to create.
            {
                //Try and recycle objects to create stimulus.
                if (reuseableVessels.Count > 0)
                {
                    DDDAdapter.SeamateObject objectForReuse = null;
                    //Make sure we reuse any stopped objects first
                    List <DDDAdapter.SeamateObject> stoppedObjects = reuseableVessels.FindAll(IsStopped);
                    if (stoppedObjects.Count > 0)
                    {
                        objectForReuse = stoppedObjects[random.Next(stoppedObjects.Count)];
                    }
                    else
                    {
                        objectForReuse = reuseableVessels[random.Next(reuseableVessels.Count)];
                    }

                    CreateEmptyMove(objectForReuse);
                    reuseableVessels.Remove(objectForReuse);
                }
                else //Reveal and move new merchant starting at an appropriate point for grouping constraints.
                {
                    Vec2D location = null;
                    if (currentItem.Parameters.Groupings == T_Groupings.One) //Get point in closest entry region
                    {
                        location = GetPointInClosestEntryRegion(dict, entryRegions);
                    }
                    else if (currentItem.Parameters.Groupings == T_Groupings.Two) //Get point in any entry region
                    {
                        location = new Polygon2D(entryRegions[random.Next(entryRegions.Count)]).PointInside();
                    }

                    string id = unrevealedMerchantIDs[random.Next(unrevealedMerchantIDs.Count)];
                    CreateRevealAndEmptyMove(id, "Merchant DM", location);
                    unrevealedMerchantIDs.Remove(id);
                }
            }
            currentItem.Action = actions.ToArray();
        }
예제 #16
0
 private bool IsMerchant(DDDAdapter.SeamateObject vessel)
 {
     return(vessel.Owner == "Merchant DM");
 }