Changeset - 3463e3d12e78
[Not reviewed]
default
0 1 0
Jason Maltzen (jmaltzen) - 7 years ago 2018-05-18 18:07:15
jason.maltzen@unsanctioned.net
Fix a bug where recipe generation could use up to 1 more than MaxConcentration
1 file changed with 17 insertions and 8 deletions:
0 comments (0 inline, 0 general)
RecipeGenerator.cs
Show inline comments
...
 
@@ -160,64 +160,72 @@ namespace DesertPaintLab
 
            public int Compare(Reagent reagent1, Reagent reagent2)
 
            {
 
                return (int)reagent1.Cost - (int)reagent2.Cost;
 
            }
 
        }
 

	
 
        public void InitRecipes(SortedDictionary<string, PaintRecipe> initialRecipes)
 
        {
 
            if (running)
 
            {
 
                return;
 
            }
 
            recipeCosts.Clear();
 
            recipes.Clear();
 
            foreach (PaintRecipe recipe in initialRecipes.Values)
 
            {
 
                //PaintRecipe recipeCopy = new PaintRecipe(recipe);
 
                AddCheapestRecipe(recipe);
 
            }
 
        }
 

	
 
        private void InitSortedReagents()
 
        {
 
            costSortedReagents.Clear();
 
            foreach (string name in ReagentManager.Names)
 
            {
 
                Reagent reagent = ReagentManager.GetReagent(name);
 
                costSortedReagents.Add(reagent);
 
            }
 
            costSortedReagents.Sort(new ReagentCostSort());
 
        }
 

	
 
        // Generate paint recipes.
 
        // minConcentration - the minimum permitted concentration in a recipe (10 for paint, 50 for ribbons)
 
        // maxConcentration - the maximum concentrataion for a recipe
 
        // minReagents - the minimum number of ingredients in a recipe
 
        // maxReagents - the maximum number of ingredients allowed in a recipe
 
        // fullQuantityDepth - at this depth of ingredient or below, allow up to fullQuantity of any reagent
 
        // fullQuantity - the maximum amount of any reagent to permit up to the full quantity depth. After that, reagents are limited by the
 
        //                per-reagent value
 
        public void BeginRecipeGeneration(uint minConcentration, uint maxConcentration, uint minReagents, uint maxReagents, uint fullQuantityDepth, uint fullQuantity)
 
        {
 
            if (running)
 
            {
 
                // Already running - don't start again
 
                return;
 
            }
 

	
 
            this.MinConcentration = minConcentration;
 
            this.MaxConcentration = maxConcentration;
 
            this.MinReagents = minReagents;
 
            this.MaxReagents = maxReagents;
 
            this.FullQuantity = fullQuantity;
 
            this.FullQuantityDepth = fullQuantityDepth;
 

	
 
            // first, sort reagents by cost.
 
            InitSortedReagents();
 

	
 
            totalReagents = (uint)costSortedReagents.Count;
 

	
 
            // Pre-populate recipes list with:
 
            // 1) 1-ingredient recipes @ min concentration for all enabled ingredients with a count >= min concentration
 
            // 2) any previously-generated recipes
 
            int enabledReagentCount = 0;
 
            PaintRecipe recipe = new PaintRecipe();
 
            recipe.Reactions = reactions;
 
            foreach (Reagent reagent in costSortedReagents)
 
            {
 
                if (reagent.Enabled)
 
                {
 
                    if (!reagent.IsCatalyst && ((reagent.RecipeMax >= minConcentration) || ((FullQuantityDepth > 0) && (FullQuantity >= minConcentration))))
 
                    {
...
 
@@ -463,94 +471,95 @@ namespace DesertPaintLab
 
                        }
 
                    }
 
                    else
 
                    {
 
                        success = false;
 
                        break;
 
                    }
 
                }
 
                return success;
 
            }
 
        }
 

	
 
        private void Generate()
 
        {
 
            RecipeSearchNode node;
 

	
 
            lock(workerLock)
 
            {
 
                ++runningThreads;
 
            }
 

	
 
            bool ok = true;
 
            do
 
            {
 
                lock (workerLock)
 
                {
 
                    ok = searchQueue.TryDequeue(out node);
 
                }
 
                if (ok)
 
                {
 
                    if (Mode == SearchType.DEPTH_FIRST)
 
                    {
 
                        uint targetQuantity = (node.ReagentCount <= FullQuantityDepth) ? ((uint)node.ReagentCount * FullQuantity) : node.MaxConcentration + 1;
 
                        uint targetQuantity = (node.ReagentCount <= FullQuantityDepth)
 
                            ? ((uint)node.ReagentCount * FullQuantity) 
 
                            : node.MaxConcentration + 1;
 
                        do {
 
                            --targetQuantity;
 
                            node.InitForQuantity(targetQuantity);
 
                        } while (targetQuantity > MinConcentration && (node.CurrentTargetQuantity != node.UsedQuantity));
 
    
 
                        while ((ok = IterateDepthFirst(node)) && !requestCancel)
 
                        {
 
                            if (Progress != null)
 
                            {
 
                                Progress(this, null);
 
                            }
 
                        }
 
                    }
 
                    else
 
                    {
 
                        // breadth-first search
 
                        uint targetQuantity = MinConcentration-1;
 
                        uint quantityLimit = (node.ReagentCount <= FullQuantityDepth) ? (FullQuantity * (uint)node.ReagentCount) : node.MaxConcentration;
 
                        uint targetQuantity = MinConcentration - 1;
 
                        uint quantityLimit = (node.ReagentCount <= FullQuantityDepth) 
 
                            ? (FullQuantity * (uint)node.ReagentCount) 
 
                            : node.MaxConcentration;
 
                        do {
 
                            ++targetQuantity;
 
                            node.InitForQuantity(targetQuantity);
 
                        } while ((targetQuantity <= quantityLimit) && (node.CurrentTargetQuantity != node.UsedQuantity));
 
                        } while ((targetQuantity < quantityLimit) && (node.CurrentTargetQuantity != node.UsedQuantity));
 
    
 
                        while ((ok = IterateBreadthFirst(node)) && !requestCancel)
 
                        {
 
                            if (Progress != null)
 
                            {
 
                                Progress(this, null);
 
                            }
 
                            Progress?.Invoke(this, null);
 
                        }
 
                    }
 
                    if (ok)
 
                    {
 
                        // stopped because cancel was requested - requeue the node in its current state for resume
 
                        searchQueue.Enqueue(node);
 
                    }
 
                }
 
            } while (!requestCancel && ok);
 

	
 
            bool done = false;
 
            lock(workerLock)
 
            {
 
                --runningThreads;
 
                //generatorThreads.Remove(Thread.CurrentThread);
 

	
 
                done = (runningThreads == 0);
 
            }
 
            if (done)
 
            {
 
                running = false;
 
                requestCancel = false;
 
                if (Finished != null)
 
                {
 
                    Finished(this, null);
 
                }
 
            }
 
        }
 

	
 
        // Add the cheapest recipe to the recipe list
 
        // returns the discarded recipe from the pair (or null if no original recipe to replace)
 
        private void AddCheapestRecipe(PaintRecipe recipe)
0 comments (0 inline, 0 general)