public T_Move SetToInterceptCourse(T_Move move, T_Reveal reveal, Dictionary<T_Move, T_Reveal> merchantsDict) { //Pick the closest merchant, either newly revealed or existing. double distance = 1000000000000000; T_Move closestKey = null; Vec2D location = new Vec2D(GetLocation(move, reveal)); foreach (T_Move key in merchantsDict.Keys) { double thisDistance = new Vec2D(location).ScalerDistanceTo(new Vec2D(GetLocation(key,merchantsDict[key]))); if (thisDistance < distance) { closestKey = key; distance = thisDistance; } } double merchantSpeed = closestKey.Throttle*GetMaxSpeed(closestKey); Vec2D merchantStart = new Vec2D(GetLocation(closestKey, merchantsDict[closestKey])); Vec2D merchantDestination = new Vec2D((LocationValue)closestKey.Location.Item); Vec2D interceptPoint = GetInterceptPoint(merchantStart, merchantDestination, merchantSpeed, location, GetMaxSpeed(move)); move.Location = new T_Location(); move.Location.Item = interceptPoint.ToLocationValue(); Console.WriteLine("setting pirate " + move.ID + " on intercept course to merchant " + closestKey.ID); return move; }
public T_Move SetToInterceptCourse(T_Move move, T_Reveal reveal, Dictionary <T_Move, T_Reveal> merchantsDict) { //Pick the closest merchant, either newly revealed or existing. double distance = 1000000000000000; T_Move closestKey = null; Vec2D location = new Vec2D(GetLocation(move, reveal)); foreach (T_Move key in merchantsDict.Keys) { double thisDistance = new Vec2D(location).ScalerDistanceTo(new Vec2D(GetLocation(key, merchantsDict[key]))); if (thisDistance < distance) { closestKey = key; distance = thisDistance; } } double merchantSpeed = closestKey.Throttle * GetMaxSpeed(closestKey); Vec2D merchantStart = new Vec2D(GetLocation(closestKey, merchantsDict[closestKey])); Vec2D merchantDestination = new Vec2D((LocationValue)closestKey.Location.Item); Vec2D interceptPoint = GetInterceptPoint(merchantStart, merchantDestination, merchantSpeed, location, GetMaxSpeed(move)); move.Location = new T_Location(); move.Location.Item = interceptPoint.ToLocationValue(); Console.WriteLine("setting pirate " + move.ID + " on intercept course to merchant " + closestKey.ID); return(move); }
/// <summary> /// Calculates an intercept course for "imminent threat" pirates /// </summary> /// <param name="currentItem"></param> /// <param name="dmID"></param> public override void Generate(T_Item currentItem, String dmID) { if (currentItem.Parameters.ThreatType == T_ThreatType.Nonimminent) { return; } Dictionary <T_Move, T_Reveal> dict = GetActionsAsDictionary(currentItem.Action); //This dictionary is a copy Dictionary <T_Move, T_Reveal> newDict = new Dictionary <T_Move, T_Reveal>(dict); //Find that pirate T_Move move = null; T_Reveal reveal = null; foreach (T_Move key in dict.Keys) { if (dict[key] == null) { if (ddd.GetSeamateObject(key.ID).Owner == "Pirate DM") { move = key; reveal = dict[key]; newDict.Remove(key); break; } } else { if (dict[key].Owner == "Pirate DM") { move = key; reveal = dict[key]; newDict.Remove(key); break; } } } if (move == null) { return; } move = SetToInterceptCourse(move, reveal, newDict); //Reset the pirate's move and reveal in dictionary. newDict[move] = reveal; //Translate dictionary back into action array. currentItem.Action = GetActionsFromDictionary(newDict); }
public LocationValue GetLocation(T_Move move, T_Reveal reveal) { if (reveal == null) { return(ddd.GetSeamateObject(move.ID).Location); } else { return((LocationValue)reveal.Location.Item); } }
public String GetOwner(T_Move move, T_Reveal reveal) { if (reveal == null) { return(ddd.GetSeamateObject(move.ID).Owner); } else { return(reveal.Owner); } }
/// <summary> /// Creates a new reveal event and returns it. /// </summary> /// <param name="id">Vessel ID</param> /// <param name="owner">Name of DM</param> /// <param name="location">Location for reveal</param> /// <returns></returns> protected T_Reveal MakeReveal(String id, String owner, Vec2D location) { T_Reveal reveal = new T_Reveal(); reveal.ID = id; reveal.Owner = owner; reveal.State = "FullyFunctional"; reveal.Location = new T_Location(); reveal.StartupParameters = new T_StartupParameters(); reveal.StartupParameters.Items = new string[0]; reveal.Location.Item = location.ToLocationValue(); return(reveal); }
/// <summary> /// Sets IFF on or off. This is a setting in the reveal event. /// /// </summary> /// <param name="on"></param> /// <param name="isPirate"></param> /// <param name="reveal"></param> protected T_Reveal SetIFF(bool on, bool isPirate, T_Threat threat, T_Reveal reveal) { //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 (on && !isPirate) SetIFFOn(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 && threat == T_Threat.Unambiguous) SetIFFOn(isPirate, reveal); } return reveal; }
public void SetIFF(bool isPirate, T_Reveal reveal) { String iff = ""; if (isPirate) { iff = "Pirate"; } else { iff = "Friendly"; } reveal.StartupParameters.Items = new string[2]; reveal.StartupParameters.Items.SetValue("ObjectName", 0); reveal.StartupParameters.Items.SetValue(iff, 1); Console.WriteLine("Just set IFF for vessel " + reveal.ID); }
/// <summary> /// Adds a new move and reveal event to action list. THis adds a previously unrevealed vessel into play /// Move event will be a "dummy" empty move with no destination defined yet /// </summary> /// <param name="id"></param> /// <param name="location"></param> protected void CreateRevealAndEmptyMove(String id, String owner, Vec2D location) { T_Reveal reveal = new T_Reveal(); reveal.ID = id; reveal.Owner = owner; reveal.State = "FullyFunctional"; reveal.Location = new T_Location(); reveal.StartupParameters = new T_StartupParameters(); reveal.StartupParameters.Items = new string[0]; reveal.Location.Item = location.ToLocationValue(); T_Move move = new T_Move(); move.ID = id; move.Location = new T_Location(); actions.Add(reveal); actions.Add(move); }
/// <summary> /// Sets IFF on or off. This is a setting in the reveal event. /// /// </summary> /// <param name="on"></param> /// <param name="isPirate"></param> /// <param name="reveal"></param> protected T_Reveal SetIFF(bool on, bool isPirate, T_Threat threat, T_Reveal reveal) { //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 (on && !isPirate) { SetIFFOn(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 && threat == T_Threat.Unambiguous) { SetIFFOn(isPirate, reveal); } } return(reveal); }
//public void IdentifyActions(Object[] actions) //{ // if (actions.Length == 0) return; // //What we will have at this point: one pirate (primary), one merchant (primary), or one pirate (primary) and one merchant (secondary). // bool doSecondPass = false; // foreach (Object action in actions) // { // //Get move actions // T_Move tempMove = action as T_Move; // if (tempMove != null) //it's a move // { // DDDAdapter.SeamateObject seamateObject = ddd.GetSeamateObject(tempMove.ID); // if (seamateObject != null) //object is already in play // { // if (seamateObject.Owner == "Pirate DM") // { // isPirate = true; // //Pirate is always primary if he exists // if (primaryMove == null) primaryMove = tempMove; // else // { // secondaryMove = primaryMove; // primaryMove = tempMove; // } // } // else //it's a merchant // { // if (primaryMove == null) primaryMove = tempMove; // else secondaryMove = tempMove; // } // } // else //object is not yet in play - has just been revealed // { // //how do we figure out who owns it?!! // doSecondPass = true; // } // } // else // { // T_Reveal tempReveal = action as T_Reveal; // if (tempReveal.Owner == "Pirate DM") // { // isPirate = true; // if (primaryReveal == null) primaryReveal = tempReveal; // else // { // secondaryReveal = primaryReveal; // primaryReveal = tempReveal; // } // } // else //merchant // { // if (primaryReveal == null) primaryReveal = tempReveal; // else secondaryReveal = tempReveal; // } // } // } // //Do second pass only to match up reveals with unmarked move actions // if (doSecondPass) // { // foreach (Object action in actions) // { // T_Move tempMove = action as T_Move; // if (tempMove != null && ddd.GetSeamateObject(tempMove.ID) == null) // { // if (primaryReveal.ID == tempMove.ID) // primaryMove = tempMove; // else secondaryMove = tempMove; // } // } // } // if (primaryReveal != null) // location = (LocationValue)primaryReveal.Location.Item; // else // location = ddd.GetSeamateObject(primaryMove.ID).Location; //} /// <summary> /// Goes through the list of actions to create a dictionary of reveal and move events. /// </summary> /// <param name="actions"></param> public Dictionary <T_Move, T_Reveal> GetActionsAsDictionary(Object[] actions) { Dictionary <T_Move, T_Reveal> dict = new Dictionary <T_Move, T_Reveal>(); if (actions.Length == 0) { return(dict); } //What we will have at this point: one pirate (primary) and a bunch of merchants! //Set all moves as keys. They are good keys because every vessel will be moved exactly once. foreach (Object action in actions) { T_Move tempMove = action as T_Move; if (tempMove != null) //it's a move { dict.Add(tempMove, null); } } //Set all reveals as values. Some keys will have null values because some vessels are already in play. foreach (Object action in actions) { T_Reveal tempReveal = action as T_Reveal; if (tempReveal != null) //&& ddd.GetSeamateObject(tempMove.ID) == null) // ? weird? { foreach (T_Move key in dict.Keys) { if (key.ID == tempReveal.ID) { dict[key] = tempReveal; break; } } } } return(dict); }
//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; }
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(); }
public override void Generate(T_Item currentItem, String dmID) { dict = GetActionsAsDictionary(currentItem.Action); //This generator modifies move events e.g. keys, so write changes to this one because we'll be //iterating over the original. Dictionary <T_Move, T_Reveal> newDict = new Dictionary <T_Move, T_Reveal>(); foreach (T_Move key in dict.Keys) { T_Move move = key; T_Reveal reveal = dict[key]; bool isPirate = (GetOwner(move, reveal) == "Pirate DM"); bool ambiguity = !(currentItem.Parameters.Threat == T_Threat.Unambiguous); //Vessel's desired perceived ambiguity //If it's a merchant and resources are available, always make merchants UNambiguous (so IFF is likely to be on). Per Courtney -Lisa if (!isPirate && currentItem.Parameters.PlayerResources == T_ResourceAvailability.Available) { ambiguity = false; } //Is it in a sea lane? If it is being newly revealed, yes because it's already in an entry region //and entry regions are the ends of sea lanes. Otherwise, check. List <PolygonValue> seaLanes = ddd.GetAllSeaLanes(); bool locationInSeaLane = false; if (reveal != null) { locationInSeaLane = true; } else { LocationValue location = GetLocation(move, reveal); foreach (PolygonValue seaLane in seaLanes) { if (Polygon2D.IsPointInside(new Polygon2D(seaLane), new Vec2D(location))) { locationInSeaLane = true; } } } bool onInterceptCourse = isPirate; //all pirates are on intercept course, no merchant can be bool hasIFFon = false; if (reveal == null) //Object already exists in play { String displayName = ddd.GetSeamateObject(move.ID).ObjectName; if (!displayName.StartsWith("unknown")) { hasIFFon = true; } } //Pick row from ambiguity table using existing constraints. bool[] selectedRow = PickRowFromAmbiguityTable(onInterceptCourse, hasIFFon, locationInSeaLane, ambiguity); reveal = SetIFF(selectedRow[0], isPirate, currentItem.Parameters.Threat, reveal); //alters reveal event move.Throttle = GetNewSpeed(selectedRow[1], move); move.Location.Item = GetNewDestination(selectedRow[2], onInterceptCourse).ToLocationValue(); //Add modified move and reveal to new dictionary. newDict[move] = reveal; } currentItem.Action = GetActionsFromDictionary(newDict); }
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); }
//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); }
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(); }