private static void Main(string[] args) { var state = @" MOLECULES 0 3 4 0 0 0 2 0 1 2 0 0 MOLECULES 0 3 1 1 2 4 0 0 1 0 1 1 0 4 3 1 3 6 8 0 1 C 1 2 1 0 0 0 10 0 1 C 1 1 1 0 1 2 11 0 1 D 1 3 0 0 0 0 6 1 1 B 10 0 0 0 4 0 7 1 1 E 1 2 0 2 0 0 9 1 1 A 1 0 0 0 2 1 ".Trim(); Settings.DUMP_ALL = true; Settings.DUMP_TURN = -1; ////=== var gameState = new GameState { currentTurn = 102 }; gameState.projects.Add(new Project(0, 0, 4, 4, 0)); gameState.projects.Add(new Project(0, 4, 4, 0, 0)); gameState.projects.Add(new Project(0, 3, 3, 3, 0)); var robotStrategy = new GatherStrategy(gameState); gameState.robotStrategy = robotStrategy; ////=== gameState.Iteration(new StringReader(state)); }
/// <summary> /// Executes the strategy logic in charge of regenerating GP after the gather. /// </summary> /// <returns></returns> public async Task <GpRegenStrategyResult> RegenerateGp(GatheringPointObject node, IGatheringRotation gatherRotation, GatherStrategy gatherStrategy, CordialTime cordialTime, CordialType cordialType) { var rtn = new GpRegenStrategyResult() { StrategyState = GpRegenStrategyResult.GpRegenStrategyResultState.OK, EffectiveCordialType = cordialType, OriginalCordialType = cordialType, }; var useCordial = cordialTime.HasFlag(CordialTime.AfterGather) && this.cordialStock.HasStock() && this.cordialStock.GetCordialCooldown() == TimeSpan.Zero; var currentGp = ExProfileBehavior.Me.CurrentGP; var maxGp = ExProfileBehavior.Me.MaxGP; var missingGp = maxGp - currentGp; var cordial = this.cordialStock.GetBestCordial(missingGp, cordialType); // Return OK if there is no cordial to use if (cordial == null) { rtn.UseState = InventoryItem.UseResult.OK; return(rtn); } // Use the cordial rtn.UseState = await cordial.Use( ExProfileBehavior.Me ); // Log the result this.LogCordialResult( rtn.UseState ?? InventoryItem.UseResult.CantUse, cordial, currentGp ); return(rtn); }
/// <summary> /// Executes the strategy logic in charge of regenerating GP before the gather. /// </summary> /// <returns></returns> public async Task <GpRegenStrategyResult> RegenerateGp(GatheringPointObject node, IGatheringRotation gatherRotation, GatherStrategy gatherStrategy, CordialTime cordialTime, CordialType cordialType) { var rtn = new GpRegenStrategyResult() { EffectiveCordialType = this.effectiveCordialType, OriginalCordialType = this.requestedCordialType, }; // Return OK immediately if there is no node if (node == null) { this.logger.GatheringNodeIsGone(); rtn.StrategyState = GpRegenStrategyResult.GpRegenStrategyResultState.NodeGone; return(rtn); } // Configure the strategy and report to the log this.Configure(node, gatherRotation, gatherStrategy, cordialTime, cordialType); this.logger.LogReport(this); // Return not enough time if player has less than 3 seconds to gather if (this.EffectiveTimeTillGather.TotalSeconds < 3) { this.logger.GatheringNotEnoughTime(); rtn.StrategyState = GpRegenStrategyResult.GpRegenStrategyResultState.NotEnoughTime; return(rtn); } if (this.gatherStrategy == GatherStrategy.GatherOrCollect) { // Return not enough GP if we cannot meet the target breakpoint for the rotation if (this.BreakpointGp > this.TargetGp) { this.logger.RegeneratingNotEnoughGp(); rtn.StrategyState = GpRegenStrategyResult.GpRegenStrategyResultState.NotEnoughGp; return(rtn); } } // Use the cordial if one was selected if (this.Cordial != null) { rtn.UseState = await this.Cordial.Use( ExProfileBehavior.Me, maxTimeout : this.EffectiveTimeTillGather, dismount : true ); this.LogCordialResult(rtn.UseState.Value); // Recalculate player's ability to gather after cordial use failure if (rtn.UseState != InventoryItem.UseResult.OK) { this.effectiveCordialType = CordialType.None; this.CalculateTargetAndCordialSelection(); this.logger.LogReport(this); // Return not enough GP if we cannot meet the target breakpoint for the rotation if (this.BreakpointGp > this.TargetGp) { this.logger.RegeneratingNotEnoughGp(); rtn.StrategyState = GpRegenStrategyResult.GpRegenStrategyResultState.NotEnoughGp; return(rtn); } } } // Handle TouchAndGo overrides if (this.gatherStrategy == GatherStrategy.TouchAndGo) { // Do nothing if this is not ephemeral if (!node.IsEphemeral()) { this.logger.GatheringNodeSkippedNotEphemeral(); rtn.StrategyState = GpRegenStrategyResult.GpRegenStrategyResultState.OK; return(rtn); } if (this.EffectiveTimeToRegenerate.TotalSeconds > MAX_TOUCHANDGO_WAIT) { this.logger.RegeneratingSkippedExceedsEphemeralMaxWait( this.EffectiveTimeToRegenerate.TotalSeconds, MAX_TOUCHANDGO_WAIT ); rtn.StrategyState = GpRegenStrategyResult.GpRegenStrategyResultState.OK; return(rtn); } } // Return OK immediately if the rotation forcefully gathers the item if (gatherRotation.ShouldForceGather(node)) { rtn.StrategyState = GpRegenStrategyResult.GpRegenStrategyResultState.OK; return(rtn); } // Execute wait logic rtn.StrategyState = await this.WaitForGpRegeneration(); return(rtn); }
/// <summary> /// Configures the strategy for use /// </summary> protected void Configure(GatheringPointObject node, IGatheringRotation gatherRotation, GatherStrategy gatherStrategy, CordialTime cordialTime, CordialType cordialType) { if (gatherRotation == null) { throw new ArgumentNullException("gatherRotation"); } // Set gathering parameters this.gatherRotation = gatherRotation; this.gatherStrategy = gatherStrategy; // Set cordial parameters this.cordialTime = cordialTime; this.requestedCordialType = this.effectiveCordialType = cordialType; // Override cordial type if (this.requestedCordialType > CordialType.None) { // Turn off cordial when there is no stock if (!this.cordialStockManager.HasStock()) { this.effectiveCordialType = CordialType.None; this.logger.RegeneratingCordialUseDisabledNoStock(); } // Turn off cordial when node is not ephemeral in TnG strategies if (this.gatherStrategy == GatherStrategy.TouchAndGo && !node.IsEphemeral()) { this.effectiveCordialType = CordialType.None; } } else { this.effectiveCordialType = this.requestedCordialType; } // Set node lifespan parameters this.NodeLifespan = new EffectiveNodeLifespan(NodeHelper.GetNodeLifespan(node), this.gatherRotation.Attributes.RequiredTimeInSeconds); if (this.gatherStrategy == GatherStrategy.TouchAndGo) { this.NodeLifespan.Clamp(TimeSpan.Zero, TimeSpan.FromSeconds(MAX_TOUCHANDGO_WAIT)); } this.EffectiveTimeTillGather = this.NodeLifespan.DeSpawn; // Set GP parameters this.StartingGp = this.CurrentGp; this.MaxGp = ExProfileBehavior.Me.MaxGP; this.EffectiveGp = CharacterResource.GetEffectiveGp(this.NodeLifespan.DeSpawnTicks); // Set breakpoint and cordial parameters this.CalculateTargetAndCordialSelection(); // Calculate regeneration parameters this.RegeneratedGp = (ushort)(this.TargetGp - this.CordialGp - this.StartingGp); if (this.RegeneratedGp < 0) { this.RegeneratedGp = 0; } this.EffectiveTimeToRegenerate = CharacterResource.EstimateExpectedRegenerationTime(this.RegeneratedGp); }