Пример #1
0
        /// <summary>
        /// Makes a point which is in the closest entry region to the group of pirates, 
        /// TODO: but not in the same entry region as any of them.
        /// </summary>
        /// <param name="pirates">The move events representing pirates</param>
        /// <param name="entryRegions">All entry regions</param>
        /// <returns>A random point in the closest entry region to the group of pirates</returns>
        private Vec2D GetPointInClosestEntryRegion(Dictionary<T_Move,T_Reveal> pirates, List<PolygonValue> entryRegions) {
            Vec2D point = new Vec2D(0,0);
            double closestDistance = 100000000;
            PolygonValue closestRegion = null;
            Shuffle(entryRegions);
            T_Move randomPirate = pirates.Keys.ToList().ElementAt(0);
            LocationValue location = GetLocation(randomPirate, pirates[randomPirate]);
            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)
            {
                point = new Polygon2D(closestRegion).PointInside();
            }
            return point;
        }
Пример #2
0
        public bool SpecialGenerate(T_Item currentItem, String dmID)
        {

            Dictionary<T_Move,T_Reveal> dict = GetActionsAsDictionary(currentItem.Action);
            Dictionary<T_Move, T_Reveal> newDict = new Dictionary<T_Move,T_Reveal>();
            
            List<PolygonValue> seaLanes = ddd.GetAllSeaLanes();
            PolygonValue domain = this.ddd.GetDecisionMakersAreaOfResponsibility(dmID);


            foreach (T_Move key in dict.Keys)
            {
                T_Move move = key;
                T_Reveal reveal = dict[key];
                

                //Is this vessel a pirate?
                bool isPirate = false;
                if (reveal!=null) //there's a reveal event
                {
                    if (reveal.Owner == "Pirate DM")
                        isPirate = true;
                } 
                else if (ddd.GetSeamateObject(move.ID).Owner == "Pirate DM")
                    isPirate = true;


                //Vessel's desired perceived ambiguity
                bool ambiguity = true;
                if (currentItem.Parameters.Threat == T_Threat.Unambiguous)
                    ambiguity = false;
                //If it's a merchant and resources aren't unavailable, always make merchants UNambiguous (so IFF is likely to be on)
                if (!isPirate && currentItem.Parameters.PlayerResources == T_ResourceAvailability.Available)
                    ambiguity = false;


                //Is it in a sea lane?  If it is already in play check, Yes if it is being revealed in an entry region
                bool locationInSeaLane = false;
                LocationValue location;
                if (reveal == null) //already in play
                    location = ddd.GetSeamateObject(move.ID).Location;
                else
                    location = (LocationValue)reveal.Location.Item;

                foreach (PolygonValue seaLane in seaLanes)
                {
                    Polygon2D seaLane2D = new Polygon2D(seaLane);
                    if (Polygon2D.IsPointInside(seaLane2D, new Vec2D(location)))
                    {
                        locationInSeaLane = true;
                        break;
                    }
                }

                //Intercept course
               bool onInterceptCourse = false;
               if (currentItem.Parameters.ThreatType == T_ThreatType.Imminent && isPirate)
                    onInterceptCourse = true;

                //IFF
               bool hasIFFon = false;

                //Is its IFF already on?
                if (move == null) //Object already exists in play
                {
                    String displayName = ddd.GetSeamateObject(move.ID).ObjectName; 
                    if (!displayName.StartsWith("unknown")) //Object has IFF set on
                        hasIFFon = true;
                }


                //Pick row from ambiguity table using existing constraints.
                Shuffle(ambiguityTable);
                bool[] selectedRow = null;
                foreach (bool[] row in ambiguityTable)
                {
                    if ((!onInterceptCourse || row[2])          //if onInterceptCourse is true, only allow course to be "on"/true ... if onInterceptCourse is false, either value is OK
                         && (!hasIFFon || row[0])                //same as above for hasIFFon and IFF
                        && (!locationInSeaLane || row[3])       //same as above for inSeaLane and location
                        && ambiguity == row[4])                 // ambiguity must match

                        selectedRow = row;
                }
                if (selectedRow == null)
                {
                    return false;
                    //Console.WriteLine("Impossible scenario");
                    //selectedRow = ambiguityTable[random.Next(ambiguityTable.Length)];
                    //TODO: Wipe out actions, go back to Threat Generator and make a new object
                }
               // Console.WriteLine("AmbiguityGenerator: Making settings for an " + currentItem.Parameters.ThreatType.ToString() + " vessel.  IFF should be on?" + selectedRow[0]);

                //Create scenario described in ambiguity table

                //IFF =================================
                //If we're revealing a new vessel, we can set its IFF on if we need to.  Default is off so we don't 
                // have to do anything.  We can't change existing ships.
                if (reveal != null)
                {
                    if (selectedRow[0] && !isPirate)
                        SetIFF(isPirate, reveal);

                    //If it's a pirate, ignore what it says in the ambiguity table.  
                    //Unambiguous == IFF ON always.  Ambiguous = IFF OFF always
                    if (isPirate && currentItem.Parameters.Threat == T_Threat.Unambiguous)
                        SetIFF(isPirate, reveal);
                    
                }

                //SPEED ===============================   
                double maxSpeed = GetMaxSpeed(move);

                double newSpeed;
                if (selectedRow[1])  //speed 69-84 m/s
                    newSpeed = random.Next(69, Math.Max((int)maxSpeed,84));
                else
                {  //speed <69 or >84 m/s
                    if (maxSpeed > 84)
                        newSpeed = random.Next(84, (int)maxSpeed);
                    else
                        newSpeed = random.Next(20, 68);
                }
                move.Throttle = ((double)newSpeed / (double)maxSpeed);



                //COURSE =================================
                if (selectedRow[2])
                {
                    if (onInterceptCourse) // we will take care of this later
                    {
                        
                    }
                    else //if (locationInSeaLane)
                    {
                        //pick any entry region and send it there.
                        Polygon2D entryRegion2D = new Polygon2D(entryRegions[random.Next(entryRegions.Count)]);
                        Vec2D point = entryRegion2D.PointInside();
                        move.Location = new T_Location();
                        move.Location.Item = point.ToLocationValue();
                    }
                }
                else
                {
                    //just send it anywhere ... probably won't be in a sea lane
                    Vec2D point = new Polygon2D(domain).PointInside(); //TODO: this should be in whole scenario boundaries, not just DM domain
                    move.Location = new T_Location();
                    move.Location.Item = point.ToLocationValue();

                    //TODO:  Send it to the edge of the universe.  Just kidding ... to edge of sea region.
                    ddd.GetDecisionMakersAreaOfResponsibility("BAMS DM");
                    ddd.GetDecisionMakersAreaOfResponsibility("Firescout DM");

                }
                //Add modified move and reveal back to dictionary.
                newDict[move] = reveal;
            }
            currentItem.Action = GetActionsFromDictionary(newDict);
            return true;
        }
Пример #3
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();
        }