private static bool TryFindBestBillIngredientsInSet_AllowMix(List <Thing> availableThings, Building_CokeFurnace bill, List <ThingCount> chosen) { chosen.Clear(); for (int i = 0; i < bill.SelectedRecipe.ingredients.Count; i++) { IngredientCount ingredientCount = bill.SelectedRecipe.ingredients[i]; float num = ingredientCount.GetBaseCount(); for (int j = 0; j < availableThings.Count; j++) { Thing thing = availableThings[j]; if (ingredientCount.filter.Allows(thing) && ingredientCount.IsFixedIngredient) { float num2 = bill.SelectedRecipe.IngredientValueGetter.ValuePerUnitOf(thing.def); int num3 = Mathf.Min(Mathf.CeilToInt(num / num2), thing.stackCount); ThingCountUtility.AddToList(chosen, thing, num3); num -= (float)num3 * num2; if (num <= 0.0001f) { break; } } } if (num > 0.0001f) { return(false); } } return(true); }
public static bool TryFindBestRecipeIngredientsInSet_AllowMix(this RecipeDef recipeDef, List <Thing> availableThings, List <ThingCount> chosen) { chosen.Clear(); foreach (var ingredientCount in recipeDef.ingredients) { var baseCount = ingredientCount.GetBaseCount(); foreach (var thing in availableThings) { if (!ingredientCount.filter.Allows(thing)) { continue; } var ingredientValue = recipeDef.IngredientValueGetter.ValuePerUnitOf(thing.def); var countToAdd = Mathf.Min(Mathf.CeilToInt(baseCount / ingredientValue), thing.stackCount); ThingCountUtility.AddToList(chosen, thing, countToAdd); baseCount -= countToAdd * ingredientValue; if (baseCount <= 9.99999974737875E-05) { break; } } if (baseCount > 9.99999974737875E-05) { return(false); } } return(true); }
private static bool TryFindBestBillIngredientsInSet_AllowMix( List <Thing> availableThings, Bill bill, List <ThingCount> chosen) { chosen.Clear(); availableThings.Sort((t, t2) => bill.recipe.IngredientValueGetter.ValuePerUnitOf(t2.def).CompareTo(bill.recipe.IngredientValueGetter.ValuePerUnitOf(t.def))); for (int index1 = 0; index1 < bill.recipe.ingredients.Count; ++index1) { IngredientCount ingredient = bill.recipe.ingredients[index1]; float baseCount = ingredient.GetBaseCount(); for (int index2 = 0; index2 < availableThings.Count; ++index2) { Thing availableThing = availableThings[index2]; if (ingredient.filter.Allows(availableThing) && (ingredient.IsFixedIngredient || bill.ingredientFilter.Allows(availableThing))) { float num = bill.recipe.IngredientValueGetter.ValuePerUnitOf(availableThing.def); int countToAdd = Mathf.Min(Mathf.CeilToInt(baseCount / num), availableThing.stackCount); ThingCountUtility.AddToList(chosen, availableThing, countToAdd); baseCount -= countToAdd * num; if (baseCount <= 9.99999974737875E-05) { break; } } } if (baseCount > 9.99999974737875E-05) { return(false); } } return(true); }
public static bool Prefix(List <Thing> availableThings, Bill bill, List <ThingCount> chosen, ref bool __result) { Pawn trainee = WorkGiver_DoBill_TryFindBestBillIngredients.Trainee; if (trainee != null) { chosen.Clear(); availableThings.Sort((Thing t, Thing t2) => bill.recipe.IngredientValueGetter.ValuePerUnitOf(t2.def).CompareTo(bill.recipe.IngredientValueGetter.ValuePerUnitOf(t.def))); for (int i = 0; i < bill.recipe.ingredients.Count; i++) { IngredientCount ingredientCount = bill.recipe.ingredients[i]; for (int j = 0; j < availableThings.Count; j++) { Thing thing = availableThings[j]; if (ingredientCount.filter.Allows(thing) && (ingredientCount.IsFixedIngredient || bill.ingredientFilter.Allows(thing))) { ThingCountUtility.AddToList(chosen, thing, 1); } } } __result = true; return(false); } return(true); }
public static bool TryFindBestRecipeIngredientsInSet_AllowMix(this RecipeDef recipeDef, List <Thing> availableThings, List <ThingCount> chosen) { chosen.Clear(); for (int ingredientIndex = 0; ingredientIndex < recipeDef.ingredients.Count; ++ingredientIndex) { IngredientCount ingredientCount = recipeDef.ingredients[ingredientIndex]; float baseCount = ingredientCount.GetBaseCount(); for (int thingIndex = 0; thingIndex < availableThings.Count; ++thingIndex) { Thing thing = availableThings[thingIndex]; if (ingredientCount.filter.Allows(thing)) { float ingredientValue = recipeDef.IngredientValueGetter.ValuePerUnitOf(thing.def); int countToAdd = Mathf.Min(Mathf.CeilToInt(baseCount / ingredientValue), thing.stackCount); ThingCountUtility.AddToList(chosen, thing, countToAdd); baseCount -= (float)countToAdd * ingredientValue; if ((double)baseCount <= 9.99999974737875E-05) { break; } } } if ((double)baseCount > 9.99999974737875E-05) { return(false); } } return(true); }
private static bool TryFindBestBillIngredientsInSet(List <Thing> availableThings, ActivityTask task, List <ThingCount> chosenIngThings) { IEnumerable <ThingDefsCount> thingDefsCount = task.ActivityTaskDef.ThingDefsCount; chosenIngThings.Clear(); for (int index1 = 0; index1 < thingDefsCount.Count(); ++index1) { float baseCount = thingDefsCount.ElementAt(index1).Count; for (int index2 = 0; index2 < availableThings.Count; ++index2) { Thing availableThing = availableThings[index2]; if (task.ThingFilter.Allows(availableThing.def)) { float num = task.ActivityTaskDef.IngredientValueGetter.ValuePerUnitOf(availableThing.def); int countToAdd = Mathf.Min(Mathf.CeilToInt(baseCount / num), availableThing.stackCount); ThingCountUtility.AddToList(chosenIngThings, availableThing, countToAdd); baseCount -= (float)countToAdd * num; if ((double)baseCount <= 9.99999974737875E-05) { break; } } } if ((double)baseCount > 9.99999974737875E-05) { return(false); } } return(true); }
internal static bool TryFindBestMixInSet_AllowMix(List <Thing> availableThings, Bill bill, List <ThingCount> chosen) { chosen.Clear(); for (var i = 0; i < bill.recipe.ingredients.Count; i++) { IngredientCount ingredientCount = bill.recipe.ingredients[i]; var num = ingredientCount.GetBaseCount(); for (var j = 0; j < availableThings.Count; j++) { Thing thing = availableThings[j]; if (ingredientCount.filter.Allows(thing) && (ingredientCount.IsFixedIngredient || bill.ingredientFilter.Allows(thing))) { var num2 = bill.recipe.IngredientValueGetter.ValuePerUnitOf(thing.def); var num3 = Mathf.Min(Mathf.CeilToInt(num / num2), thing.stackCount); ThingCountUtility.AddToList(chosen, thing, num3); num -= (float)num3 * num2; if (num <= 0.0001f) { break; } } } if (num > 0.0001f) { return(false); } } return(true); }
private static bool TryFindBestBillIngredientsInSet_NoMix(List <Thing> availableThings, Bill bill, List <ThingCount> chosen) { RecipeDef recipe = bill.recipe; chosen.Clear(); WorkGiver_DoBill.availableCounts.Clear(); WorkGiver_DoBill.availableCounts.GenerateFrom(availableThings); for (int i = 0; i < WorkGiver_DoBill.ingredientsOrdered.Count; i++) { IngredientCount ingredientCount = recipe.ingredients[i]; bool flag = false; for (int j = 0; j < WorkGiver_DoBill.availableCounts.Count; j++) { float num = (float)ingredientCount.CountRequiredOfFor(WorkGiver_DoBill.availableCounts.GetDef(j), bill.recipe); if (num <= WorkGiver_DoBill.availableCounts.GetCount(j)) { if (ingredientCount.filter.Allows(WorkGiver_DoBill.availableCounts.GetDef(j))) { if (ingredientCount.IsFixedIngredient || bill.ingredientFilter.Allows(WorkGiver_DoBill.availableCounts.GetDef(j))) { for (int k = 0; k < availableThings.Count; k++) { if (availableThings[k].def == WorkGiver_DoBill.availableCounts.GetDef(j)) { int num2 = availableThings[k].stackCount - ThingCountUtility.CountOf(chosen, availableThings[k]); if (num2 > 0) { int num3 = Mathf.Min(Mathf.FloorToInt(num), num2); ThingCountUtility.AddToList(chosen, availableThings[k], num3); num -= (float)num3; if (num < 0.001f) { flag = true; float num4 = WorkGiver_DoBill.availableCounts.GetCount(j); num4 -= (float)ingredientCount.CountRequiredOfFor(WorkGiver_DoBill.availableCounts.GetDef(j), bill.recipe); WorkGiver_DoBill.availableCounts.SetCount(j, num4); break; } } } } if (flag) { break; } } } } } if (!flag) { return(false); } } return(true); }
private static bool TryFindBestBillIngredientsInSet_NoMix(List <Thing> availableThings, Building_CokeFurnace bill, List <ThingCount> chosen) { RecipeDef recipe = bill.SelectedRecipe; chosen.Clear(); availableCounts.Clear(); availableCounts.GenerateFrom(availableThings); for (int i = 0; i < ingredientsOrdered.Count; i++) { IngredientCount ingredientCount = recipe.ingredients[i]; bool flag = false; for (int j = 0; j < availableCounts.Count; j++) { float num = ingredientCount.CountRequiredOfFor(availableCounts.GetDef(j), bill.SelectedRecipe); if (num > availableCounts.GetCount(j) || !ingredientCount.filter.Allows(availableCounts.GetDef(j)) || !ingredientCount.IsFixedIngredient) { continue; } for (int k = 0; k < availableThings.Count; k++) { if (availableThings[k].def != availableCounts.GetDef(j)) { continue; } int num2 = availableThings[k].stackCount - ThingCountUtility.CountOf(chosen, availableThings[k]); if (num2 > 0) { int num3 = Mathf.Min(Mathf.FloorToInt(num), num2); ThingCountUtility.AddToList(chosen, availableThings[k], num3); num -= (float)num3; if (num < 0.001f) { flag = true; float count = availableCounts.GetCount(j); count -= (float)ingredientCount.CountRequiredOfFor(availableCounts.GetDef(j), bill.SelectedRecipe); availableCounts.SetCount(j, count); break; } } } if (flag) { break; } } if (!flag) { return(false); } } return(true); }
internal static bool TryFindBestMixInSet_NoMix(List <Thing> availableThings, Bill bill, List <ThingCount> chosen, List <IngredientCount> ingredientsOrdered) { var availableCounts = new BMixDefCountList(); RecipeDef recipe = bill.recipe; chosen.Clear(); availableCounts.Clear(); availableCounts.GenerateFrom(availableThings); for (var i = 0; i < ingredientsOrdered.Count; i++) { IngredientCount ingredientCount = recipe.ingredients[i]; var flag = false; for (var j = 0; j < availableCounts.Count; j++) { float num = ingredientCount.CountRequiredOfFor(availableCounts.GetDef(j), bill.recipe); if (num > availableCounts.GetCount(j) || !ingredientCount.filter.Allows(availableCounts.GetDef(j)) || (!ingredientCount.IsFixedIngredient && !bill.ingredientFilter.Allows(availableCounts.GetDef(j)))) { continue; } for (var k = 0; k < availableThings.Count; k++) { if (availableThings[k].def != availableCounts.GetDef(j)) { continue; } var num2 = availableThings[k].stackCount - ThingCountUtility.CountOf(chosen, availableThings[k]); if (num2 > 0) { var num3 = Mathf.Min(Mathf.FloorToInt(num), num2); ThingCountUtility.AddToList(chosen, availableThings[k], num3); num -= (float)num3; if (num < 0.001f) { flag = true; var count = availableCounts.GetCount(j); count -= (float)ingredientCount.CountRequiredOfFor(availableCounts.GetDef(j), bill.recipe); availableCounts.SetCount(j, count); break; } } } if (flag) { break; } } if (!flag) { return(false); } } return(true); }
private static bool TryFindBestBillIngredientsInSet_NoMix(List <Thing> availableThings, List <ThingDefCount> neededIngreds, List <ThingCount> chosen) { chosen.Clear(); AssignedThings.Clear(); AvailableCounts.Clear(); AvailableCounts.GenerateFrom(availableThings); foreach (var ingredientCount in neededIngreds) { var flag = false; for (var index2 = 0; index2 < AvailableCounts.Count; ++index2) { float f = ingredientCount.Count; if (!(f <= (double)AvailableCounts.GetCount(index2)) || ingredientCount.ThingDef != AvailableCounts.GetDef(index2)) { continue; } foreach (var item in availableThings) { if (item.def != AvailableCounts.GetDef(index2) || AssignedThings.Contains(item)) { continue; } var countToAdd = Mathf.Min(Mathf.FloorToInt(f), item.stackCount); ThingCountUtility.AddToList(chosen, item, countToAdd); f -= countToAdd; AssignedThings.Add(item); if (f < 1.0 / 1000.0) { flag = true; var val = AvailableCounts.GetCount(index2) - ingredientCount.Count; AvailableCounts.SetCount(index2, val); break; } } if (flag) { break; } } if (!flag) { return(false); } } return(true); }
static bool Prefix(WorkGiver_DoBill __instance, Bill bill, Pawn pawn, ref List <ThingCount> chosen, ref bool __result) { if (bill.recipe == WTH_DefOf.WTH_Craft_VanometricModule) { Thing thing = pawn.Map.spawnedThings.FirstOrDefault( (Thing t) => (t.GetInnerIfMinified().def == ThingDefOf.VanometricPowerCell) && bill.IsFixedOrAllowedIngredient(t) && pawn.CanReach(t, Verse.AI.PathEndMode.Touch, Danger.Deadly) && !t.IsForbidden(pawn) && t is MinifiedThing); if (thing != null) { ThingCountUtility.AddToList(chosen, thing, 1); __result = true; return(false); } } if (bill.recipe.defName.Contains("WTH_Mount")) { Predicate <Thing> isMounted = (Thing t) => t.TryGetComp <CompMountable>() is CompMountable comp && comp.Active; Thing thing = pawn.Map.spawnedThings.FirstOrDefault( (Thing t) => (t.GetInnerIfMinified() is Building_TurretGun) && bill.IsFixedOrAllowedIngredient(t) && pawn.CanReach(t, Verse.AI.PathEndMode.Touch, Danger.Deadly) && !t.IsForbidden(pawn) && !isMounted(t) && t is MinifiedThing); if (thing != null) { ThingCountUtility.AddToList(chosen, thing, 1); __result = true; return(false); } } return(true); }
private static bool TryFindRestrictedIngridients(ActivityTask task, Pawn pawn, Thing giver, List <ThingCount> chosenIngThings) { chosenIngThings.Clear(); newRelevantThings.Clear(); if (task.HumanlikeIngredient.ConcretePawn == null && task.AnimalIngredient.ConcretePawn == null) { return(false); } Predicate <Thing> baseValidator = (Predicate <Thing>)(t => { if (t.Spawned && !t.IsForbidden(pawn) && ((double)(t.Position - giver.Position).LengthHorizontalSquared < (double)task.IngredientSearchRadius * (double)task.IngredientSearchRadius && task.ThingFilter.Allows(t.def))) { return(pawn.CanReserve((LocalTargetInfo)t, 1, -1, (ReservationLayerDef)null, false)); } return(false); }); if (task.HumanlikeIngredient.ConcretePawn != null) { if (baseValidator(task.HumanlikeIngredient.ConcretePawn)) { ThingCountUtility.AddToList(chosenIngThings, task.HumanlikeIngredient.ConcretePawn, 1); return(true); } } if (task.AnimalIngredient.ConcretePawn != null) { if (baseValidator(task.AnimalIngredient.ConcretePawn)) { ThingCountUtility.AddToList(chosenIngThings, task.AnimalIngredient.ConcretePawn, 1); return(true); } } return(false); }
private static bool TryFindBestBillIngredients(Bill bill, Pawn pawn, Thing billGiver, List <ThingCount> chosen) { chosen.Clear(); newRelevantThings.Clear(); IntVec3 rootCell = (IntVec3)GetBillGiverRootCellInfo.Invoke(bill, new object[] { billGiver, pawn }); Region rootReg = rootCell.GetRegion(pawn.Map, RegionType.Set_Passable); if (rootReg == null) { return(false); } relevantThings.Clear(); bool foundAll = false; Predicate <Thing> baseValidator = (Thing t) => t.Spawned && !t.IsForbidden(pawn) && (t.Position - billGiver.Position).LengthHorizontalSquared < bill.ingredientSearchRadius * bill.ingredientSearchRadius && ((!t.def.tradeTags.NullOrEmpty() && t.def.tradeTags.Contains(TechStrings.bookTraderTag)) || t is Building_BookStore) && pawn.CanReserve(t, 1, -1, null, false); TraverseParms traverseParams = TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false); RegionEntryPredicate entryCondition = null; if (Math.Abs(999f - bill.ingredientSearchRadius) >= 1f) { float radiusSq = bill.ingredientSearchRadius * bill.ingredientSearchRadius; entryCondition = delegate(Region from, Region r) { if (!r.Allows(traverseParams, false)) { return(false); } CellRect extentsClose = r.extentsClose; int num = Math.Abs(billGiver.Position.x - Math.Max(extentsClose.minX, Math.Min(billGiver.Position.x, extentsClose.maxX))); if (num > bill.ingredientSearchRadius) { return(false); } int num2 = Math.Abs(billGiver.Position.z - Math.Max(extentsClose.minZ, Math.Min(billGiver.Position.z, extentsClose.maxZ))); return(num2 <= bill.ingredientSearchRadius && (num * num + num2 * num2) <= radiusSq); }; } else { entryCondition = ((Region from, Region r) => r.Allows(traverseParams, false)); } int adjacentRegionsAvailable = rootReg.Neighbors.Count((Region region) => entryCondition(rootReg, region)); int regionsProcessed = 0; RegionProcessor regionProcessor = delegate(Region r) { List <Thing> items = r.ListerThings.ThingsMatching(ThingRequest.ForGroup(ThingRequestGroup.HaulableEver)); for (int i = 0; i < items.Count; i++) { Thing thing = items[i]; if (ReachabilityWithinRegion.ThingFromRegionListerReachable(thing, r, PathEndMode.ClosestTouch, pawn) && baseValidator(thing) && IsSelected(thing, bill)) { newRelevantThings.Add(thing); } } List <Thing> buildings = r.ListerThings.ThingsMatching(ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial)); for (int i = 0; i < buildings.Count; i++) { Thing thing = buildings[i]; if (ReachabilityWithinRegion.ThingFromRegionListerReachable(thing, r, PathEndMode.ClosestTouch, pawn) && baseValidator(thing)) { List <Thing> innerList = ContainsSelected(thing, bill); if (!innerList.NullOrEmpty()) { newRelevantThings.AddRange(innerList); } } } regionsProcessed++; if (newRelevantThings.Count > 0 && regionsProcessed > adjacentRegionsAvailable) { relevantThings.AddRange(newRelevantThings); newRelevantThings.Clear(); ThingCountUtility.AddToList(chosen, FindNearest(relevantThings, rootCell), 1); foundAll = true; return(true); } return(false); }; RegionTraverser.BreadthFirstTraverse(rootReg, entryCondition, regionProcessor, 99999, RegionType.Set_Passable); relevantThings.Clear(); newRelevantThings.Clear(); return(foundAll); }
public static bool TryFindBestRecipeIngredientsInSet_NoMix(this RecipeDef recipeDef, List <Thing> availableThings, List <ThingCount> chosen) { chosen.Clear(); List <IngredientCount> ingredientsOrdered = new List <IngredientCount>(); HashSet <Thing> assignedThings = new HashSet <Thing>(); DefCountList availableCounts = new DefCountList(); availableCounts.GenerateFrom(availableThings); for (int ingredientIndex = 0; ingredientIndex < recipeDef.ingredients.Count; ++ingredientIndex) { IngredientCount ingredientCount = recipeDef.ingredients[ingredientIndex]; if (ingredientCount.filter.AllowedDefCount == 1) { ingredientsOrdered.Add(ingredientCount); } } for (int ingredientIndex = 0; ingredientIndex < recipeDef.ingredients.Count; ++ingredientIndex) { IngredientCount ingredientCount = recipeDef.ingredients[ingredientIndex]; if (!ingredientsOrdered.Contains(ingredientCount)) { ingredientsOrdered.Add(ingredientCount); } } for (int orderedIndex = 0; orderedIndex < ingredientsOrdered.Count; ++orderedIndex) { IngredientCount ingredientCount = recipeDef.ingredients[orderedIndex]; bool hasAllRequired = false; for (int countsIndex = 0; countsIndex < availableCounts.Count; ++countsIndex) { float countRequiredFor = (float)ingredientCount.CountRequiredOfFor(availableCounts.GetDef(countsIndex), recipeDef); if ( ((double)countRequiredFor <= (double)availableCounts.GetCount(countsIndex)) && (ingredientCount.filter.Allows(availableCounts.GetDef(countsIndex))) ) { for (int thingsIndex = 0; thingsIndex < availableThings.Count; ++thingsIndex) { if ( (availableThings[thingsIndex].def == availableCounts.GetDef(countsIndex)) && (!assignedThings.Contains(availableThings[thingsIndex])) ) { int countToAdd = Mathf.Min(Mathf.FloorToInt(countRequiredFor), availableThings[thingsIndex].stackCount); ThingCountUtility.AddToList(chosen, availableThings[thingsIndex], countToAdd); countRequiredFor -= (float)countToAdd; assignedThings.Add(availableThings[thingsIndex]); if ((double)countRequiredFor < 1.0 / 1000.0) { hasAllRequired = true; float val = availableCounts.GetCount(countsIndex) - ingredientCount.GetBaseCount(); availableCounts.SetCount(countsIndex, val); break; } } } if (hasAllRequired) { break; } } } if (!hasAllRequired) { return(false); } } return(true); }
public static bool TryFindBestRecipeIngredientsInSet_NoMix(this RecipeDef recipeDef, List <Thing> availableThings, List <ThingCount> chosen) { chosen.Clear(); var ingredientsOrdered = new List <IngredientCount>(); var assignedThings = new HashSet <Thing>(); var availableCounts = new DefCountList(); availableCounts.GenerateFrom(availableThings); foreach (var ingredientCount in recipeDef.ingredients) { if (ingredientCount.filter.AllowedDefCount == 1) { ingredientsOrdered.Add(ingredientCount); } } foreach (var ingredientCount in recipeDef.ingredients) { if (!ingredientsOrdered.Contains(ingredientCount)) { ingredientsOrdered.Add(ingredientCount); } } for (var orderedIndex = 0; orderedIndex < ingredientsOrdered.Count; ++orderedIndex) { var ingredientCount = recipeDef.ingredients[orderedIndex]; var hasAllRequired = false; for (var countsIndex = 0; countsIndex < availableCounts.Count; ++countsIndex) { var countRequiredFor = (float)ingredientCount.CountRequiredOfFor(availableCounts.GetDef(countsIndex), recipeDef); if (!(countRequiredFor <= (double)availableCounts.GetCount(countsIndex)) || !ingredientCount.filter.Allows(availableCounts.GetDef(countsIndex))) { continue; } foreach (var thing in availableThings) { if (thing.def != availableCounts.GetDef(countsIndex) || assignedThings.Contains(thing)) { continue; } var countToAdd = Mathf.Min(Mathf.FloorToInt(countRequiredFor), thing.stackCount); ThingCountUtility.AddToList(chosen, thing, countToAdd); countRequiredFor -= countToAdd; assignedThings.Add(thing); if (!(countRequiredFor < 1.0 / 1000.0)) { continue; } hasAllRequired = true; var val = availableCounts.GetCount(countsIndex) - ingredientCount.GetBaseCount(); availableCounts.SetCount(countsIndex, val); break; } if (hasAllRequired) { break; } } if (!hasAllRequired) { return(false); } } return(true); }
private static bool TryFindBestBillIngredientsInSet_NoMix2( List <Thing> availableThings, Bill bill, List <ThingCount> chosen, IntVec3 rootCell, bool alreadySorted, List <IngredientCount> ingredientsOrdered) { if (!alreadySorted) { Comparison <Thing> comparison = (t1, t2) => ((float)(t1.Position - rootCell).LengthHorizontalSquared).CompareTo((t2.Position - rootCell).LengthHorizontalSquared); availableThings.Sort(comparison); } RecipeDef recipe = bill.recipe; chosen.Clear(); //WorkGiver_DoBill.availableCounts.Clear(); DefCountList availableCounts = new DefCountList(); availableCounts.GenerateFrom(availableThings); for (int index1 = 0; index1 < ingredientsOrdered.Count; ++index1) { IngredientCount ingredient = recipe.ingredients[index1]; bool flag = false; for (int index2 = 0; index2 < availableCounts.Count; ++index2) { float f = ingredient.CountRequiredOfFor(availableCounts.GetDef(index2), bill.recipe); if ((recipe.ignoreIngredientCountTakeEntireStacks || f <= availableCounts.GetCount(index2)) && ingredient.filter.Allows(availableCounts.GetDef(index2)) && (ingredient.IsFixedIngredient || bill.ingredientFilter.Allows(availableCounts.GetDef(index2)))) { for (int index3 = 0; index3 < availableThings.Count; ++index3) { if (availableThings[index3].def == availableCounts.GetDef(index2)) { int num = availableThings[index3].stackCount - ThingCountUtility.CountOf(chosen, availableThings[index3]); if (num > 0) { if (recipe.ignoreIngredientCountTakeEntireStacks) { ThingCountUtility.AddToList(chosen, availableThings[index3], num); return(true); } int countToAdd = Mathf.Min(Mathf.FloorToInt(f), num); ThingCountUtility.AddToList(chosen, availableThings[index3], countToAdd); f -= countToAdd; if (f < 1.0 / 1000.0) { flag = true; float val = availableCounts.GetCount(index2) - ingredient.CountRequiredOfFor(availableCounts.GetDef(index2), bill.recipe); availableCounts.SetCount(index2, val); break; } } } } if (flag) { break; } } } if (!flag) { return(false); } } return(true); }
static bool TryFindBestBillIngredientsInSet_AllowMix(List <Thing> availableThings, Bill bill, List <ThingCount> chosen) { chosen.Clear(); List <ThingCount> chosenInThisStep = new List <ThingCount>(); for (int i = 0; i < bill.recipe.ingredients.Count; i++) { IngredientCount ingredientCount = bill.recipe.ingredients[i]; float num = ingredientCount.GetBaseCount(); chosenInThisStep.Clear(); for (int j = 0; j < availableThings.Count; j++) { Thing thing = availableThings[j]; if (ingredientCount.filter.Allows(thing)) { if (ingredientCount.IsFixedIngredient || bill.ingredientFilter.Allows(thing)) { float num2 = bill.recipe.IngredientValueGetter.ValuePerUnitOf(thing.def); int num3 = Mathf.Min(Mathf.CeilToInt(num / num2), thing.stackCount); ThingCountUtility.AddToList(chosen, thing, num3); ThingCountUtility.AddToList(chosenInThisStep, thing, num3); num -= (float)num3 * num2; if (num <= 0.0001f) { break; } } } } if (num > 0.0001f) { return(false); } //patch: do another pass eliminating as many resources as possible. starting with the biggest resources, //have we allocated more than we may need? And at least 2 different things. if (num < -0.0001f && chosenInThisStep.Count > 1) { num = -num; chosenInThisStep.SortByDescending(ta => bill.recipe.IngredientValueGetter.ValuePerUnitOf(ta.Thing.def)); for (int j = 0; j < chosenInThisStep.Count && num > 0.0001f; j++) { ThingCount ta = chosenInThisStep[j]; float valuePerUnit = bill.recipe.IngredientValueGetter.ValuePerUnitOf(ta.Thing.def); //can we remove at least one instance of the current ingredient? if (valuePerUnit < num) { //determine how many instances we can remove int instancesToRemove = 0; while (valuePerUnit < num && instancesToRemove < ta.Count) { num -= valuePerUnit - 0.0001f; //adding a small amount since the precision loss of float causes problems where subtraction leads to 0.04999 instead of 0.05 instancesToRemove++; } if (instancesToRemove != 0) { ThingCountUtility.AddToList(chosen, ta.Thing, -instancesToRemove); } } } } chosen.RemoveAll(ta => ta.Count <= 0); } return(true); }
private static bool TryFindBestBillIngredientsInSet_NoMix(List <Thing> availableThings, Bill bill, List <ThingCount> chosen, IntVec3 rootCell, bool alreadySorted) { if (!alreadySorted) { Comparison <Thing> comparison = delegate(Thing t1, Thing t2) { float num4 = (t1.Position - rootCell).LengthHorizontalSquared; float value = (t2.Position - rootCell).LengthHorizontalSquared; return(num4.CompareTo(value)); }; availableThings.Sort(comparison); } RecipeDef recipe = bill.recipe; chosen.Clear(); availableCounts.Clear(); availableCounts.GenerateFrom(availableThings); for (int i = 0; i < ingredientsOrdered.Count; i++) { IngredientCount ingredientCount = recipe.ingredients[i]; bool flag = false; for (int j = 0; j < availableCounts.Count; j++) { float num = ingredientCount.CountRequiredOfFor(availableCounts.GetDef(j), bill.recipe); if ((!recipe.ignoreIngredientCountTakeEntireStacks && num > availableCounts.GetCount(j)) || !ingredientCount.filter.Allows(availableCounts.GetDef(j)) || (!ingredientCount.IsFixedIngredient && !bill.ingredientFilter.Allows(availableCounts.GetDef(j)))) { continue; } for (int k = 0; k < availableThings.Count; k++) { if (availableThings[k].def != availableCounts.GetDef(j)) { continue; } int num2 = availableThings[k].stackCount - ThingCountUtility.CountOf(chosen, availableThings[k]); if (num2 > 0) { if (recipe.ignoreIngredientCountTakeEntireStacks) { ThingCountUtility.AddToList(chosen, availableThings[k], num2); return(true); } int num3 = Mathf.Min(Mathf.FloorToInt(num), num2); ThingCountUtility.AddToList(chosen, availableThings[k], num3); num -= (float)num3; if (num < 0.001f) { flag = true; float count = availableCounts.GetCount(j); count -= (float)ingredientCount.CountRequiredOfFor(availableCounts.GetDef(j), bill.recipe); availableCounts.SetCount(j, count); break; } } } if (flag) { break; } } if (!flag) { return(false); } } return(true); }
private static bool TryFindBestBillIngredientsInSet_NoMix( List <Thing> availableThings, Bill bill, List <ThingCount> chosen) { var recipe = bill.recipe; chosen.Clear(); availableCounts.Clear(); // 利用可能な材料リストとその個数 // Things側はゲーム中に見えているThingのリスト // Counts側は、違うThingでも個数をまとめている availableCounts.GenerateFrom(availableThings); // レシピが必要としている材料の種類だけループ foreach (var ingredientCount in recipe.ingredients) { var isIngredientFound = false; for (var j = 0; j < availableCounts.Count; j++) { // 利用可能な物 var curDef = availableCounts.GetDef(j); var curCount = availableCounts.GetCount(j); // レシピ完遂のためにそれが何個必要なのか var requiredCount = (float)ingredientCount.CountRequiredOfFor(curDef, bill.recipe); var remainRequiredCount = requiredCount; // 利用可能な個数は必要数より少ない if (requiredCount > curCount) { continue; } // レシピとして許可されていない if (!ingredientCount.filter.Allows(curDef)) { continue; } // レシピの固定材料でもなければ billとして許可されているわけでもない if (!ingredientCount.IsFixedIngredient && !bill.ingredientFilter.Allows(curDef)) { continue; } // Thingの検索 foreach (var availableThing in availableThings) { // 探している物ではない if (availableThing.def != curDef) { continue; } // 未使用の材料数(全個数から、既に追加されている個数を引いた数) var unusedCount = availableThing.stackCount - ThingCountUtility.CountOf(chosen, availableThing); // 未使用数0以下 if (unusedCount <= 0) { continue; } // そのスタックからいくつ使うか(必要数と未使用数のうち小さい方) var actualUseCount = Mathf.Min(Mathf.FloorToInt(remainRequiredCount), unusedCount); // リストに加える ThingCountUtility.AddToList(chosen, availableThing, actualUseCount); // 残りの必要個数を減らす remainRequiredCount -= actualUseCount; // まだ必要であれば続けて探す if (remainRequiredCount >= 0.001f) { continue; } // その材料は全部見つかった // ⇒残りの利用可能数を減らす isIngredientFound = true; availableCounts.SetCount(j, curCount - requiredCount); break; } // その材料は全部見つかったので残りは探さなくていい if (isIngredientFound) { break; } } // 1個でも見つからない材料があればダメ if (!isIngredientFound) { return(false); } } // 全部見つかったのでOK return(true); }