private Vec2D MakeLocationInEntryRegions(List <PolygonValue> acceptableEntryRegions) { PolygonValue entryRegion = acceptableEntryRegions.ElementAt(random.Next(acceptableEntryRegions.Count)); Vec2D location = new Polygon2D(entryRegion).PointInside(); return(location); }
/// <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); }
public void FromPolygon(PolygonValue p) { this.xPoints.Clear(); this.yPoints.Clear(); foreach (PolygonValue.PolygonPoint pp in p.points) { this.AddVertex(new Vec2D(pp.X, pp.Y)); } }
public PolygonValue GetPolygonValue() { PolygonValue p = new PolygonValue(); for (int i = 0; i < xPoints.Count; i++) { p.points.Add(new PolygonValue.PolygonPoint(xPoints[i], yPoints[i])); } return(p); }
private List <Vec2D> MakeLocationsInEntryRegions(int numPirates, List <PolygonValue> acceptableEntryRegions) { List <Vec2D> locations = new List <Vec2D>(); for (int i = 0; i < numPirates; i++) { PolygonValue entryRegion = acceptableEntryRegions.ElementAt(random.Next(acceptableEntryRegions.Count)); Vec2D location = new Polygon2D(entryRegion).PointInside(); locations.Add(location); } return(locations); }
private PolygonValue GetFirescoutAORegion() { if (Firescout_AO == null) { Firescout_AO = new PolygonValue(); Firescout_AO.points.Add(new PolygonValue.PolygonPoint(39000, 8400)); Firescout_AO.points.Add(new PolygonValue.PolygonPoint(125800, 8700)); Firescout_AO.points.Add(new PolygonValue.PolygonPoint(126500, 88200)); Firescout_AO.points.Add(new PolygonValue.PolygonPoint(109600, 86950)); Firescout_AO.points.Add(new PolygonValue.PolygonPoint(93000, 82400)); Firescout_AO.points.Add(new PolygonValue.PolygonPoint(79200, 76000)); Firescout_AO.points.Add(new PolygonValue.PolygonPoint(66400, 66500)); Firescout_AO.points.Add(new PolygonValue.PolygonPoint(55800, 55900)); Firescout_AO.points.Add(new PolygonValue.PolygonPoint(45700, 40700)); Firescout_AO.points.Add(new PolygonValue.PolygonPoint(40500, 24000)); Firescout_AO.points.Add(new PolygonValue.PolygonPoint(39000, 8400)); } return(Firescout_AO); }
private PolygonValue GetBamsAORegion() { if (BAMS_AO == null) { BAMS_AO = new PolygonValue(); BAMS_AO.points.Add(new PolygonValue.PolygonPoint(200, 76200)); BAMS_AO.points.Add(new PolygonValue.PolygonPoint(0, 8800)); BAMS_AO.points.Add(new PolygonValue.PolygonPoint(39100, 8600)); BAMS_AO.points.Add(new PolygonValue.PolygonPoint(40500, 24000)); BAMS_AO.points.Add(new PolygonValue.PolygonPoint(45700, 40700)); BAMS_AO.points.Add(new PolygonValue.PolygonPoint(55800, 55900)); BAMS_AO.points.Add(new PolygonValue.PolygonPoint(66400, 66500)); BAMS_AO.points.Add(new PolygonValue.PolygonPoint(79200, 76000)); BAMS_AO.points.Add(new PolygonValue.PolygonPoint(93000, 82400)); BAMS_AO.points.Add(new PolygonValue.PolygonPoint(109600, 86950)); BAMS_AO.points.Add(new PolygonValue.PolygonPoint(126500, 88200)); BAMS_AO.points.Add(new PolygonValue.PolygonPoint(126200, 103200)); BAMS_AO.points.Add(new PolygonValue.PolygonPoint(28900, 103200)); BAMS_AO.points.Add(new PolygonValue.PolygonPoint(200, 76200)); } return(BAMS_AO); }
private List <Vec2D> MakeLocationsForGroup(T_Groupings grouping, int numPirates, List <PolygonValue> entryRegions) { //For two groupings, just return all the entry regions. We'll probably get a good distribution. if (grouping == T_Groupings.Two) { return(MakeLocationsInEntryRegions(numPirates, entryRegions)); } //For one groupings, pick a random entry region to start the group. PolygonValue entryRegion = entryRegions.ElementAt(random.Next(entryRegions.Count)); List <PolygonValue> acceptableEntryRegions = new List <PolygonValue>(); foreach (PolygonValue region in entryRegions) { Vec2D pointFromNewRegion = new Vec2D(region.points.ElementAt(0).X, region.points.ElementAt(0).Y); Vec2D pointFromFirstRegion = new Vec2D(entryRegion.points.ElementAt(0).X, entryRegion.points.ElementAt(0).Y); if (pointFromNewRegion.ScalerDistanceTo(pointFromFirstRegion) < oneGroupingDistance) { acceptableEntryRegions.Add(region); } } return(MakeLocationsInEntryRegions(numPirates, acceptableEntryRegions)); }
public static Vec2D FindIntersect(PolygonValue poly1, PolygonValue poly2) { List <Vec2D> intersections = new List <Vec2D>(); //with polys, we might have 2 intersections, should we find the middle of the two? List <PolygonValue.PolygonPoint> p2Points = poly2.points; Vec2D intersect = null; Polygon2D p2d = new Polygon2D(); PolygonValue.PolygonPoint p0; PolygonValue.PolygonPoint p1; p2d.FromPolygon(poly1); for (int i = 0; i < p2Points.Count - 1; i++) { p0 = p2Points[i]; p1 = p2Points[i + 1]; intersect = FindIntersect(p2d, new Vec2D(p0.X, p0.Y), new Vec2D(p1.X, p1.Y)); if (intersect != null) { intersections.Add(intersect); } } //then once more from len-1 to 0 p0 = p2Points[p2Points.Count - 1]; p1 = p2Points[0]; intersect = FindIntersect(p2d, new Vec2D(p0.X, p0.Y), new Vec2D(p1.X, p1.Y)); //intersect = FindIntersect(poly1, p2Points[p2Points.Count - 1], p2Points[0]); if (intersect != null) { intersections.Add(intersect); } if (intersections.Count > 0) { return(AverageVectors(intersections)); } return(null); }
private void ProcessRegion(SimulationEvent ev) { String id = ((StringValue)ev["ID"]).value; AttributeCollectionValue atts = ((AttributeCollectionValue)ev["Attributes"]); PolygonValue pv = atts.attributes["Polygon"] as PolygonValue; if (atts.attributes.ContainsKey("CurrentAbsolutePolygon")) { pv = atts["CurrentAbsolutePolygon"] as PolygonValue; } if (id.StartsWith("SeaLane-")) { if (!_seaLanes.ContainsKey(id)) { _seaLanes.Add(id, pv); } else { _seaLanes[id] = pv; } } else if (id.StartsWith("Entry-")) { if (!_entryPoints.ContainsKey(id)) { _entryPoints.Add(id, pv); } else { _entryPoints[id] = pv; } } else if (id.StartsWith("AO-")) { //AO's handled differently now } }
/// <summary> /// Makes a random point on the boundary of a polygon. /// </summary> /// <param name="area"></param> /// <returns></returns> protected LocationValue GetPointOnBoundary(PolygonValue area) { int i = random.Next(area.points.Count); PolygonValue.PolygonPoint startPP = area.points[i]; PolygonValue.PolygonPoint endPP; if (i == 0) { endPP = area.points[i + 1]; } else { endPP = area.points[i - 1]; } //Use slope intercept form Vec2D start = new Vec2D(startPP.X, startPP.Y); Vec2D end = new Vec2D(endPP.X, endPP.Y); double slope = (end.Y - start.Y) / (end.X - start.X); double intercept = start.Y - start.X * slope; double newX = random.Next((int)Math.Min(start.X, end.X), (int)Math.Max(start.X, end.X)); //choose new X between existing X values double newY = slope * newX + intercept; return(new Vec2D(newX, newY).ToLocationValue()); }
//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(); }
/// <summary> /// A constructor. /// </summary> public SimActiveRegion() { m_shape = new PolygonValue(); }
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(); }
//isPirate here refers to the objects we are trying to find, e.g. isPirate = true means find pirates private List <SeamateAdapter.DDD.DDDAdapter.SeamateObject> findObjectsInPlay(LocationValue nearby, PolygonValue pirateEntryRegion, T_Groupings grouping, bool isPirate) { List <DDDAdapter.SeamateObject> vessels = new List <DDDAdapter.SeamateObject>(); foreach (DDDAdapter.SeamateObject vessel in ddd.GetAllRevealedSeaVessels()) { if (isPirate && vessel.Owner == "Pirate DM" || !isPirate && vessel.Owner == "Merchant DM") { } else { continue; } double distance = new Vec2D(vessel.Location).ScalerDistanceTo(new Vec2D(nearby)); bool inSameEntryRegionAsPirate = false; if (pirateEntryRegion != null) { inSameEntryRegionAsPirate = Polygon2D.IsPointInside(new Polygon2D(pirateEntryRegion), new Vec2D(vessel.Location)); } if (grouping == T_Groupings.One && distance < oneGroupingDistance && !inSameEntryRegionAsPirate) { vessels.Add(vessel); } else if (grouping == T_Groupings.Two && distance > twoGroupingDistance && !inSameEntryRegionAsPirate) { vessels.Add(vessel); } } return(vessels); }
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); }
public Polygon2D(PolygonValue value) { this.FromPolygon(value); }
//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); }