/// <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); } }
/// <summary> /// Returns a list of entry regions in which new pirates can be added while satisfying grouping constraints, given a group of existing pirates. /// </summary> /// <param name="grouping">Grouping constraints</param> /// <param name="group">Group of existing pirates</param> /// <param name="entryRegions">All avilable entry regions</param> /// <returns></returns> private List <PolygonValue> GetMatchingEntryRegions(T_Groupings grouping, List <DDDAdapter.SeamateObject> group, List <PolygonValue> entryRegions) { List <PolygonValue> matchingEntryRegions = new List <PolygonValue>(); //One grouping: matching entry regions must be within certain distance of every individual vessel in group if (grouping == T_Groupings.One) { foreach (PolygonValue region in entryRegions) { Vec2D regionPoint = new Vec2D(region.points.ElementAt(0).X, region.points.ElementAt(0).Y); bool matching = true; foreach (DDDAdapter.SeamateObject vessel in group) { Vec2D vesselPoint = new Vec2D(vessel.Location); if (vesselPoint.ScalerDistanceTo(regionPoint) > oneGroupingDistance) { matching = false; break; } } if (matching) { matchingEntryRegions.Add(region); } } return(matchingEntryRegions); } //Two grouping: any entry region will do, the existing group satisfies constraint else { return(entryRegions); } }
/// <summary> /// Makes a full set of new pirates not involving any existing pirates. /// </summary> /// <param name="grouping"></param> /// <param name="numPirates"></param> /// <param name="entryRegions"></param> /// <param name="unrevealedObjectIDs"></param> private void MakeAllNewPirates(T_Groupings grouping, int numPirates, List <PolygonValue> entryRegions, List <string> unrevealedObjectIDs) { if (unrevealedObjectIDs.Count == 0) { MessageBox.Show("Runtime Engine is out of pirates."); } if (numPirates > unrevealedObjectIDs.Count) { numPirates = unrevealedObjectIDs.Count; } List <Vec2D> locations = MakeLocationsForGroup(grouping, numPirates, entryRegions); foreach (Vec2D location in locations) { string id = unrevealedObjectIDs[random.Next(unrevealedObjectIDs.Count())]; unrevealedObjectIDs.Remove(id); CreateRevealAndEmptyMove(id, owner, location); } }
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)); }
/// <summary> /// Organizes vessels into lists up to the maximum desired grouping size by comparing their locations using grouping constraints. /// </summary> /// <param name="grouping">Grouping constraint from item</param> /// <param name="numPirates">Desired number of vessels in group</param> /// <param name="reusableVessels">A list of vessels to sort</param> /// <returns></returns> private List <List <DDDAdapter.SeamateObject> > GroupVessels(T_Groupings grouping, int numPirates, List <DDDAdapter.SeamateObject> reusableVessels) { List <List <DDDAdapter.SeamateObject> > groupedPirates = new List <List <DDDAdapter.SeamateObject> >(); foreach (DDDAdapter.SeamateObject vessel in reusableVessels) { List <DDDAdapter.SeamateObject> group = new List <DDDAdapter.SeamateObject>(); group.Add(vessel); } for (int i = 0; i < (Math.Min(numPirates, reusableVessels.Count)); i++) { foreach (List <DDDAdapter.SeamateObject> group in groupedPirates) { foreach (DDDAdapter.SeamateObject vessel in reusableVessels) { if (MatchesGroupingCriteria(grouping, vessel, group)) { group.Add(vessel); } } } } return(groupedPirates); }
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(); }
//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); }
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); }
/// <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; } }
/// <summary> /// Organizes vessels into lists up to the maximum desired grouping size by comparing their locations using grouping constraints. /// </summary> /// <param name="grouping">Grouping constraint from item</param> /// <param name="numPirates">Desired number of vessels in group</param> /// <param name="reusableVessels">A list of vessels to sort</param> /// <returns></returns> private List<List<DDDAdapter.SeamateObject>> GroupVessels(T_Groupings grouping, int numPirates, List<DDDAdapter.SeamateObject> reusableVessels) { List<List<DDDAdapter.SeamateObject>> groupedPirates = new List<List<DDDAdapter.SeamateObject>>(); foreach (DDDAdapter.SeamateObject vessel in reusableVessels) { List<DDDAdapter.SeamateObject> group = new List<DDDAdapter.SeamateObject>(); group.Add(vessel); } for (int i = 0; i < (Math.Min(numPirates, reusableVessels.Count)); i++) { foreach (List<DDDAdapter.SeamateObject> group in groupedPirates) { foreach (DDDAdapter.SeamateObject vessel in reusableVessels) { if (MatchesGroupingCriteria(grouping, vessel, group)) group.Add(vessel); } } } return groupedPirates; }
/// <summary> /// Makes a full set of new pirates not involving any existing pirates. /// </summary> /// <param name="grouping"></param> /// <param name="numPirates"></param> /// <param name="entryRegions"></param> /// <param name="unrevealedObjectIDs"></param> private void MakeAllNewPirates(T_Groupings grouping, int numPirates, List<PolygonValue> entryRegions, List<string> unrevealedObjectIDs) { if (unrevealedObjectIDs.Count == 0) MessageBox.Show("Runtime Engine is out of pirates."); if (numPirates > unrevealedObjectIDs.Count) numPirates = unrevealedObjectIDs.Count; List<Vec2D> locations = MakeLocationsForGroup(grouping, numPirates, entryRegions); foreach (Vec2D location in locations) { string id = unrevealedObjectIDs[random.Next(unrevealedObjectIDs.Count())]; unrevealedObjectIDs.Remove(id); CreateRevealAndEmptyMove(id, owner, location); } }
/// <summary> /// Returns a list of entry regions in which new pirates can be added while satisfying grouping constraints, given a group of existing pirates. /// </summary> /// <param name="grouping">Grouping constraints</param> /// <param name="group">Group of existing pirates</param> /// <param name="entryRegions">All avilable entry regions</param> /// <returns></returns> private List<PolygonValue> GetMatchingEntryRegions(T_Groupings grouping, List<DDDAdapter.SeamateObject> group, List<PolygonValue>entryRegions) { List<PolygonValue> matchingEntryRegions = new List<PolygonValue>(); //One grouping: matching entry regions must be within certain distance of every individual vessel in group if (grouping == T_Groupings.One) { foreach (PolygonValue region in entryRegions) { Vec2D regionPoint = new Vec2D(region.points.ElementAt(0).X, region.points.ElementAt(0).Y); bool matching = true; foreach (DDDAdapter.SeamateObject vessel in group) { Vec2D vesselPoint = new Vec2D(vessel.Location); if (vesselPoint.ScalerDistanceTo(regionPoint) > oneGroupingDistance) { matching = false; break; } } if (matching) matchingEntryRegions.Add(region); } return matchingEntryRegions; } //Two grouping: any entry region will do, the existing group satisfies constraint else return entryRegions; }
//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 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(); }