/// <summary> /// Adds the actions pack to the chooser /// </summary> /// <returns>wether the addition was successful</returns> public bool AddActionsPack(ActionsPack pack, double value) { if (pack == null || pack.IsEmpty || value <= 0) { return(false); } // give the pack the consistency bonuses foreach (Command cmd in pack.GetCommands()) { foreach (Pirate pirate in cmd.GetMyPiratesUsed()) { if (pirate != null && this.executingEvents[pirate.Id] == cmd.SourceEvent) { value += EVENT_CONSISTENCY_BONUS; } if (pirate != null && this.turnsSinceActive[pirate.Id] != -1 && this.game.GetAllMyPiratesCount() > this.game.ActionsPerTurn) { value += PIRATE_CONSISTENCY_BONUS / this.turnsSinceActive[pirate.Id]; } } } this.list.Add(new KeyValuePair <double, ActionsPack>(value, pack)); return(true); }
/// <summary> /// Tries to add the actions of another ActionsPack into this one, and returns wether the addition succeeded. /// NOTE: The other ActionsPack must have the same "game-context" as this one! /// </summary> public bool AddActions(ActionsPack other) { // cannot execute a null object if (other == null) { return(false); } // if the pack is not given in the same context if (other.game != this.game) { return(false); } // tries to add other.resourcesPack to the resources, but continue only if the addition succeeded (the two ResourcesPack do not overlap) if (!this.resourcesPack.AddResources(other.resourcesPack)) { return(false); } // add the commands this.stableCommands.AddRange(other.stableCommands); this.unstableCommands.AddRange(other.unstableCommands); return(true); }
/// <summary> /// Creates a new ActionsPack, which will be based on the ActionsPack given /// </summary> public ActionsPack(ActionsPack other) { this.resourcesPack = new ResourcesPack(other.resourcesPack); this.stableCommands = new List <Command>(other.stableCommands); this.unstableCommands = new List <Command>(other.unstableCommands); this.game = other.game; }
/// <summary> /// Returns the best ActionsPack the can be fabricated from the contained ActionsPacks /// </summary> public ActionsPack ChooseBestStableCombination() { this.game.Log(LogType.ActionsChoosing, LogImportance.Important, "Packs' count: {0}", this.list.Count); // sort the list, by descending order this.list.Sort(new ReverseKeyValueComparer <double, ActionsPack>()); // initialize the heuristics this.game.Log(LogType.Timing, LogImportance.SomewhatImportant, "start heuristics calculation: {0}", this.game.GetTimeRemaining()); this.heuristics = new HeuristicsManager(this.list, this.game); this.game.Log(LogType.Timing, LogImportance.SomewhatImportant, "end heuristics calculation: {0}", this.game.GetTimeRemaining()); // will be used to hold the best option ActionsPack bestOption = new ActionsPack(this.game); // start up the recursion this.chooseBestStableCombination(new ActionsPack(this.game), // no packs until now; no need to track this pack, as it will be cleared out anyways 0, // 0 value until now bestOption, // the best option until now 0, // and its value 0, // choose from the start this.game.MaxCommandsPerTurn); // the maximum count of ActionsPacks that can be merged // update the consistency bonus // reset executing events for (int i = 0; i < this.executingEvents.Length; i++) { this.executingEvents[i] = -1; } // reset turns since active for (int i = 0; i < this.turnsSinceActive.Length; i++) { Pirate curPirate = game.GetMyPirate(i); if (curPirate.State == PirateState.Drunk || curPirate.State == PirateState.Lost || curPirate.Location.Equals(curPirate.InitialLocation)) { this.turnsSinceActive[i] = -1; } else if (this.turnsSinceActive[i] != -1) { this.turnsSinceActive[i] += 1; } } // update the arrays foreach (Command cmd in bestOption.GetCommands()) { foreach (Pirate pirate in cmd.GetMyPiratesUsed()) { if (pirate != null) { this.executingEvents[pirate.Id] = cmd.SourceEvent; this.turnsSinceActive[pirate.Id] = 1; } } } // return the best option return(bestOption); }
/// <summary> /// Returns a new ActionsPack, containing the command given, or null if one couldn't be fabricated correctly /// </summary> public static ActionsPack NewCommandPack(Game game, Command cmd) { ActionsPack ap = new ActionsPack(game); if (!ap.AddCommand(cmd)) { return(null); } return(ap); }
/// <summary> /// Returns the best value of a stable combination of ActionsPacks, and changes currentBestPacks accordingly /// </summary> /// <param name="chosenPacksUntilNow">The packs that were chosen before the ones we choose now</param> /// <param name="valueUntilNow">The value of the packs that were chosen before</param> /// <param name="currentBestPacks">The packs combination which is currently the best</param> /// <param name="currentBestValue">The value of currentBestPacks</param> /// <param name="startAt">The first index in the list to start choose from</param> /// <param name="maxDepth">The count of ActionsPacks that can be merged</param> /// <returns>The best value of a stable combination of ActionsPacks, until now</returns> private double chooseBestStableCombination(ActionsPack chosenPacksUntilNow, double valueUntilNow, ActionsPack currentBestPacks, double currentBestValue, int startAt, int maxDepth) { // if we can choose no more OR we're out of time if (startAt >= this.list.Count || maxDepth <= 0 || this.game.GetTimeRemaining() <= this.exitTime) { // if this pack is stable and better than the best one if (valueUntilNow > currentBestValue && chosenPacksUntilNow.GetState() == ActionsPackState.Stable) { // change the maximum currentBestPacks.Clear(this.game); currentBestPacks.AddActions(chosenPacksUntilNow); //this.game.Log("New best value {0}, at {1}", valueUntilNow, this.game.GetTimeRemaining()); return(valueUntilNow); } else { // change nothing return(currentBestValue); } } // if we cannot possibly choose better combination else if (valueUntilNow + this.list[startAt].Key * maxDepth <= currentBestValue) { // change nothing return(currentBestValue); } int nextIndex; double newValue; // try to add the current pack to the previous ones if (chosenPacksUntilNow.AddActions(this.list[startAt].Value)) { // if the addition was successful, than check for a better combination including this pack nextIndex = this.heuristics.NextPossiblePackIndex(startAt, chosenPacksUntilNow); newValue = chooseBestStableCombination(chosenPacksUntilNow, valueUntilNow + this.list[startAt].Key, currentBestPacks, currentBestValue, nextIndex, maxDepth - 1); if (newValue > currentBestValue) { currentBestValue = newValue; } chosenPacksUntilNow.RemoveActions(this.list[startAt].Value); } // check for a better combination excluding this pack nextIndex = this.heuristics.NextPossiblePackIndex(startAt, chosenPacksUntilNow); newValue = chooseBestStableCombination(chosenPacksUntilNow, valueUntilNow, currentBestPacks, currentBestValue, nextIndex, maxDepth); if (newValue > currentBestValue) { currentBestValue = newValue; } // return the best value we could achieve return(currentBestValue); }
/// <summary> /// Removes the actions and resources of the other ActionsPack from this one /// </summary> public void RemoveActions(ActionsPack other) { if (other == null) { return; } this.resourcesPack.RemoveResources(other.resourcesPack); this.stableCommands = this.stableCommands.Except(other.stableCommands).ToList(); this.unstableCommands = this.unstableCommands.Except(other.unstableCommands).ToList(); }
//////////Static Methods////////// /// <summary> /// Returns a new ActionsPack, containing the command given, or null if one couldn't be fabricated correctly /// </summary> public static ActionsPack NewCommandPack(Game game, Command cmd, int groupId) { ActionsPack ap = ActionsPack.NewCommandPack(game, cmd); if (ap == null) { return(null); } if (!ap.AddToGroup(groupId)) { return(null); } return(ap); }