private void LogTrace(string level, string s)
        {
            if (!TraceEnabled)
            {
                return;
            }

            lock (Trace)
            {
                Trace.Append(DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss"));
                Trace.Append(" ");
                Trace.Append(level);
                Trace.Append(" ");
                Trace.AppendLine(s);
            }
        }
Ejemplo n.º 2
0
        public static Job DismountInBase(Pawn pawn, Thing cart)
        {
            Job job = new Job(HaulJobDefOf.DismountInBase);

            job.targetA = cart;
            job.targetB = FindStorageCell(pawn, cart);

            if (job.targetB != IntVec3.Invalid)
            {
                Trace.AppendLine("DismountInBase Job is issued");
                Trace.LogMessage();
                return(job);
            }
            JobFailReason.Is(NoEmptyPlaceForCart);
            Trace.AppendLine("No Job. Reason: " + JobFailReason.Reason);
            Trace.LogMessage();
            return(null);
        }
Ejemplo n.º 3
0
        public static Job HaulWithTools(Pawn pawn, Map map, Thing haulThing = null)
        {
            Trace.stopWatchStart();

            // Job Setting
            bool                useBackpack = false;
            JobDef              jobDef      = null;
            LocalTargetInfo     targetC;
            int                 maxItem;
            int                 thresholdItem;
            int                 reservedMaxItem;
            IEnumerable <Thing> remainingItems;
            bool                shouldDrop;
            //       Thing lastItem = TryGetBackpackLastItem(pawn);
            Apparel_Backpack backpack = TryGetBackpack(pawn);
            //  if (cart == null)
            {
                jobDef  = HaulJobDefOf.HaulWithBackpack;
                targetC = backpack;
                maxItem = backpack.MaxItem;

                // thresholdItem = (int)Math.Ceiling(maxItem * 0.5);
                thresholdItem   = 2;
                reservedMaxItem = backpack.SlotsComp.slots.Count;
                remainingItems  = backpack.SlotsComp.slots;
                shouldDrop      = false;
                useBackpack     = true;
                //       if (lastItem != null)
                //     {
                //         for (int i = 0; i < backpack.slotsComp.slots.Count; i++)
                //         {
                //             if (backpack.slotsComp.slots[i] == lastItem && reservedMaxItem - (i + 1) <= 0)
                //             {
                //                 shouldDrop = false;
                //                 break;
                //             }
                //         }
                //     }
            }


            Job job = new Job(jobDef)
            {
                targetQueueA = new List <LocalTargetInfo>(),
                targetQueueB = new List <LocalTargetInfo>(),
                targetC      = targetC
            };

            if (useBackpack)
            {
                job.countQueue = new List <int>();
            }

            Trace.AppendLine(
                pawn.LabelCap + " In HaulWithTools: " + jobDef.defName + "\n" + "MaxItem: " + maxItem
                + " reservedMaxItem: " + reservedMaxItem);

            // Drop remaining item
            if (shouldDrop)
            {
                Trace.AppendLine("Start Drop remaining item");
                //    bool startDrop = false;
                for (int i = 0; i < remainingItems.Count(); i++)
                {
                    /* if (useBackpack && startDrop == false)
                     * {
                     *   if (remainingItems.ElementAt(i) == lastItem)
                     *   {
                     *       startDrop = true;
                     *   }
                     *   else
                     *   {
                     *       continue;
                     *   }
                     * }
                     */
                    Thing           thing = remainingItems.ElementAt(i);
                    IntVec3         storageCell; //= FindStorageCell(pawn, remainingItems.ElementAt(i), map, job.targetQueueB);
                    StoragePriority currentPriority = HaulAIUtility.StoragePriorityAtFor(thing.Position, thing);
                    if (StoreUtility.TryFindBestBetterStoreCellFor(thing, pawn, pawn.Map, currentPriority, pawn.Faction, out storageCell))
                    {
                        job.targetQueueB.Add(storageCell);
                        break;
                    }
                }

                if (!job.targetQueueB.NullOrEmpty())
                {
                    Trace.AppendLine("Dropping Job is issued");
                    Trace.LogMessage();
                    return(job);
                }

                JobFailReason.Is(NoEmptyPlaceLowerTrans);
                Trace.AppendLine("End Drop remaining item");
                Trace.AppendLine("No Job. Reason: " + JobFailReason.Reason);
                Trace.LogMessage();
                return(null);
            }

            // Collect item
            Trace.AppendLine("Start Collect item");
            IntVec3 searchPos;

            if (haulThing != null)
            {
                searchPos = haulThing.Position;
            }
            else
            {
                searchPos = pawn.Position;
            }

            foreach (SlotGroup slotGroup in map.slotGroupManager.AllGroupsListInPriorityOrder)
            {
                Trace.AppendLine("Start searching slotGroup");
                if (slotGroup.CellsList.Count - slotGroup.HeldThings.Count() < maxItem)
                {
                    continue;
                }

                // Counting valid items
                Trace.AppendLine("Start Counting valid items");
                int thingsCount =
                    map.listerHaulables.ThingsPotentiallyNeedingHauling()
                    .Count(item => slotGroup.Settings.AllowedToAccept(item));

                // Finding valid items
                Trace.AppendLine("Start Finding valid items");

                //ToDo TEST if this works without that line
                if (thingsCount > thresholdItem)
                {
                    Thing thing;
                    if (haulThing == null)
                    {
                        // ClosestThing_Global_Reachable Configuration
                        Predicate <Thing> predicate =
                            item =>
                            !job.targetQueueA.Contains(item) && !item.IsBurning() && !item.IsInAnyStorage() &&
                            (item.def.thingCategories.Exists(
                                 category =>
                                 backpack.SlotsComp.Properties.allowedThingCategoryDefs.Exists(
                                     subCategory =>
                                     subCategory.ThisAndChildCategoryDefs.Contains(category)) &&
                                 !backpack.SlotsComp.Properties.forbiddenSubThingCategoryDefs.Exists(
                                     subCategory =>
                                     subCategory.ThisAndChildCategoryDefs.Contains(category)))) &&
                            slotGroup.Settings.AllowedToAccept(item) &&
                            HaulAIUtility.PawnCanAutomaticallyHaul(pawn, item, true);

                        // && !(item is UnfinishedThing && ((UnfinishedThing)item).BoundBill != null)
                        // && (item.def.IsNutritionSource && !SocialProperness.IsSociallyProper(item, pawn, false, false));
                        thing = GenClosest.ClosestThing_Global_Reachable(
                            searchPos,
                            map,
                            map.listerHaulables.ThingsPotentiallyNeedingHauling(),
                            PathEndMode.ClosestTouch,
                            TraverseParms.For(pawn, pawn.NormalMaxDanger()),
                            9999,
                            predicate);
                        if (thing == null)
                        {
                            continue;
                        }
                    }
                    else
                    {
                        thing = haulThing;
                    }

                    // Find StorageCell
                    IntVec3 storageCell = FindStorageCell(pawn, thing, map, job.targetQueueB);
                    if (storageCell == IntVec3.Invalid)
                    {
                        break;
                    }

                    // Add Queue & Reserve
                    job.targetQueueA.Add(thing);

                    // for backpacks
                    if (useBackpack)
                    {
                        job.countQueue.Add(thing.def.stackLimit);
                    }

                    job.targetQueueB.Add(storageCell);

                    IntVec3 center = thing.Position;

                    // Enqueue SAME items in valid distance
                    Trace.AppendLine("Start Enqueuing SAME items in valid distance");
                    foreach (Thing item in
                             map.listerHaulables.ThingsPotentiallyNeedingHauling()
                             .Where(
                                 item =>
                                 !job.targetQueueA.Contains(item) && !item.IsBurning() && !item.IsInAnyStorage() &&
                                 (item.def.thingCategories.Exists(
                                      category =>
                                      backpack.SlotsComp.Properties.allowedThingCategoryDefs.Exists(
                                          subCategory =>
                                          subCategory.ThisAndChildCategoryDefs.Contains(category)) &&
                                      !backpack.SlotsComp.Properties.forbiddenSubThingCategoryDefs
                                      .Exists(
                                          subCategory =>
                                          subCategory.ThisAndChildCategoryDefs.Contains(
                                              category)))

                                  && slotGroup.Settings.AllowedToAccept(item) &&
                                  HaulAIUtility.PawnCanAutomaticallyHaul(pawn, item, true) &&
                                  center.DistanceToSquared(item.Position) <= ValidDistance)))
                    {
                        job.targetQueueA.Add(item);
                        if (useBackpack)
                        {
                            job.countQueue.Add(item.def.stackLimit);
                        }

                        reservedMaxItem++;

                        if (reservedMaxItem + job.targetQueueA.Count >= maxItem)
                        {
                            break;
                        }
                    }

                    // Find storage cell
                    Trace.AppendLine("Start Finding storage cell");
                    if (reservedMaxItem + job.targetQueueA.Count >= thresholdItem)
                    {
                        StoragePriority currentPriority = HaulAIUtility.StoragePriorityAtFor(thing.Position, thing);
                        IntVec3         storeCell;
                        if (
                            StoreUtility.TryFindBestBetterStoreCellFor(
                                thing,
                                pawn,
                                pawn.Map,
                                currentPriority,
                                pawn.Faction,
                                out storeCell))
                        {
                            job.targetQueueB.Add(storeCell);
                            if (job.targetQueueB.Count >= job.targetQueueA.Count)
                            {
                                break;
                            }
                        }
                    }

                    job.targetQueueA.Clear();
                }
            }

            Trace.AppendLine("Elapsed Time");
            Trace.stopWatchStop();

            // Check job is valid
            if (!job.targetQueueA.NullOrEmpty() && reservedMaxItem + job.targetQueueA.Count > thresholdItem &&
                !job.targetQueueB.NullOrEmpty())
            {
                Trace.AppendLine("Hauling Job is issued");
                Trace.LogMessage();
                return(job);
            }

            if (job.targetQueueA.NullOrEmpty())
            {
                JobFailReason.Is("NoHaulable".Translate());
            }
            else if (reservedMaxItem + job.targetQueueA.Count <= thresholdItem)
            {
                JobFailReason.Is(TooLittleHaulable);
            }
            else if (job.targetQueueB.NullOrEmpty())
            {
                JobFailReason.Is(NoEmptyPlaceLowerTrans);
            }
            Trace.AppendLine("No Job. Reason: " + JobFailReason.Reason);
            Trace.LogMessage();
            return(null);
        }
Ejemplo n.º 4
0
        public static Job HaulWithTools(Pawn pawn, Vehicle_Cart cart = null, Thing haulThing = null)
        {
            Trace.stopWatchStart();

            //Job Setting
            bool                UseBackpack = false;
            JobDef              jobDef      = null;
            TargetInfo          targetC;
            int                 maxItem;
            int                 thresholdItem;
            int                 reservedMaxItem;
            IEnumerable <Thing> remainingItems;
            bool                ShouldDrop;
            Thing               lastItem = TryGetBackpackLastItem(pawn);
            Apparel_Backpack    backpack = TryGetBackpack(pawn);

            if (cart == null)
            {
                jobDef  = HaulJobDefOf.HaulWithBackpack;
                targetC = backpack;
                maxItem = backpack.MaxItem;
                // thresholdItem = (int)Math.Ceiling(maxItem * 0.5);
                thresholdItem   = 2;
                reservedMaxItem = backpack.slotsComp.slots.Count;
                remainingItems  = backpack.slotsComp.slots;
                ShouldDrop      = false;
                UseBackpack     = true;
                if (lastItem != null)
                {
                    for (int i = 0; i < backpack.slotsComp.slots.Count; i++)
                    {
                        if (backpack.slotsComp.slots[i] == lastItem && reservedMaxItem - (i + 1) <= 0)
                        {
                            ShouldDrop = false;
                            break;
                        }
                    }
                }
            }
            else
            {
                if (cart.mountableComp.IsMounted)
                {
                    jobDef = cart.mountableComp.Driver.RaceProps.Animal
                        ? HaulJobDefOf.HaulWithAnimalCart
                        : HaulJobDefOf.HaulWithCart;
                }
                else
                {
                    jobDef = HaulJobDefOf.HaulWithCart;
                }

                targetC = cart;

                maxItem         = cart.MaxItem;
                thresholdItem   = (int)Math.Ceiling(maxItem * 0.25);
                reservedMaxItem = cart.storage.Count;
                remainingItems  = cart.storage;


                ShouldDrop = reservedMaxItem > 0 ? true : false;
            }
            Job job = new Job(jobDef)
            {
                targetQueueA = new List <TargetInfo>(),
                targetQueueB = new List <TargetInfo>(),
                targetC      = targetC
            };

            if (UseBackpack)
            {
                job.numToBringList = new List <int>();
            }

            Trace.AppendLine(pawn.LabelCap + " In HaulWithTools: " + jobDef.defName + "\n"
                             + "MaxItem: " + maxItem + " reservedMaxItem: " + reservedMaxItem);

            //Drop remaining item
            if (ShouldDrop)
            {
                Trace.AppendLine("Start Drop remaining item");
                bool startDrop = false;
                for (int i = 0; i < remainingItems.Count(); i++)
                {
                    if (UseBackpack && startDrop == false)
                    {
                        if (remainingItems.ElementAt(i) == lastItem)
                        {
                            startDrop = true;
                        }
                        else
                        {
                            continue;
                        }
                    }
                    IntVec3 storageCell = FindStorageCell(pawn, remainingItems.ElementAt(i), job.targetQueueB);
                    if (storageCell == IntVec3.Invalid)
                    {
                        break;
                    }
                    job.targetQueueB.Add(storageCell);
                }
                if (!job.targetQueueB.NullOrEmpty())
                {
                    Trace.AppendLine("Dropping Job is issued");
                    Trace.LogMessage();
                    return(job);
                }
                if (!UseBackpack && job.def == HaulJobDefOf.HaulWithCart && !cart.IsInValidStorage())
                {
                    Trace.AppendLine("In DismountInBase");
                    return(DismountInBase(pawn, cart));
                }
                JobFailReason.Is(NoEmptyPlaceLowerTrans);
                Trace.AppendLine("End Drop remaining item");
                Trace.AppendLine("No Job. Reason: " + JobFailReason.Reason);
                Trace.LogMessage();
                return(null);
            }

            //Collect item
            Trace.AppendLine("Start Collect item");
            IntVec3 searchPos;

            if (haulThing != null)
            {
                searchPos = haulThing.Position;
            }
            else if (!UseBackpack)
            {
                searchPos = cart.Position;
            }
            else
            {
                searchPos = pawn.Position;
            }
            foreach (SlotGroup slotGroup in Find.SlotGroupManager.AllGroupsListInPriorityOrder)
            {
                Trace.AppendLine("Start searching slotGroup");
                if (slotGroup.CellsList.Count - slotGroup.HeldThings.Count() < maxItem)
                {
                    continue;
                }

                //Counting valid items
                Trace.AppendLine("Start Counting valid items");
                int thingsCount =
                    ListerHaulables.ThingsPotentiallyNeedingHauling()
                    .Count(item => slotGroup.Settings.AllowedToAccept(item));

                //Finding valid items
                Trace.AppendLine("Start Finding valid items");
                if (thingsCount > thresholdItem)
                {
                    Thing thing;
                    if (haulThing == null)
                    {
                        //ClosestThing_Global_Reachable Configuration
                        Predicate <Thing> predicate = item
                                                      => !job.targetQueueA.Contains(item) && !item.IsBurning() &&
                                                      !item.IsInAnyStorage() &&
                                                      (UseBackpack
                                   ? item.def.thingCategories.Exists(
                                                           category =>
                                                           backpack.slotsComp.Properties.allowedThingCategoryDefs.Exists(
                                                               subCategory =>
                                                               subCategory.ThisAndChildCategoryDefs.Contains(category))
                                                           &&
                                                           !backpack.slotsComp.Properties.forbiddenSubThingCategoryDefs.Exists(
                                                               subCategory =>
                                                               subCategory.ThisAndChildCategoryDefs.Contains(category)))
                                   : cart.allowances.Allows(item)) &&
                                                      !item.IsForbidden(pawn.Faction) &&
                                                      slotGroup.Settings.AllowedToAccept(item) &&
                                                      pawn.CanReserveAndReach(item, PathEndMode.Touch, pawn.NormalMaxDanger());
                        //&& !(item is UnfinishedThing && ((UnfinishedThing)item).BoundBill != null)
                        //&& (item.def.IsNutritionSource && !SocialProperness.IsSociallyProper(item, pawn, false, false));
                        thing = GenClosest.ClosestThing_Global_Reachable(searchPos,
                                                                         ListerHaulables.ThingsPotentiallyNeedingHauling(),
                                                                         PathEndMode.ClosestTouch,
                                                                         TraverseParms.For(pawn, pawn.NormalMaxDanger()),
                                                                         9999,
                                                                         predicate);
                        if (thing == null)
                        {
                            continue;
                        }
                    }
                    else
                    {
                        thing = haulThing;
                    }

                    //Find StorageCell
                    IntVec3 storageCell = FindStorageCell(pawn, thing, job.targetQueueB);
                    if (storageCell == IntVec3.Invalid)
                    {
                        break;
                    }

                    //Add Queue & Reserve
                    job.targetQueueA.Add(thing);
                    //for backpacks
                    if (UseBackpack)
                    {
                        job.numToBringList.Add(thing.def.stackLimit);
                    }

                    job.targetQueueB.Add(storageCell);


                    IntVec3 center = thing.Position;

                    //Enqueue SAME items in valid distance
                    Trace.AppendLine("Start Enqueuing SAME items in valid distance");
                    foreach (Thing item in ListerHaulables.ThingsPotentiallyNeedingHauling().Where(item
                                                                                                   => !job.targetQueueA.Contains(item) && !item.IsBurning() &&
                                                                                                   !item.IsInAnyStorage() &&
                                                                                                   (UseBackpack
                               ? item.def.thingCategories.Exists(
                                                                                                        category =>
                                                                                                        backpack.slotsComp.Properties.allowedThingCategoryDefs.Exists(
                                                                                                            subCategory =>
                                                                                                            subCategory.ThisAndChildCategoryDefs.Contains(category))
                                                                                                        &&
                                                                                                        !backpack.slotsComp.Properties.forbiddenSubThingCategoryDefs.Exists(
                                                                                                            subCategory =>
                                                                                                            subCategory.ThisAndChildCategoryDefs.Contains(category)))
                               : cart.allowances.Allows(item)) &&
                                                                                                   !item.IsForbidden(pawn.Faction) &&
                                                                                                   slotGroup.Settings.AllowedToAccept(item) &&
                                                                                                   pawn.CanReserveAndReach(item, PathEndMode.Touch, pawn.NormalMaxDanger()) &&
                                                                                                   center.DistanceToSquared(item.Position) <= ValidDistance))
                    {
                        job.targetQueueA.Add(item);
                        if (UseBackpack)
                        {
                            job.numToBringList.Add(item.def.stackLimit);
                        }


                        reservedMaxItem++;

                        if (reservedMaxItem + job.targetQueueA.Count >= maxItem)
                        {
                            break;
                        }
                    }

                    //Enqueue other items in valid distance
                    if (reservedMaxItem + job.targetQueueA.Count < maxItem)
                    {
                        Trace.AppendLine("Start Enqueuing items in valid distance");

                        foreach (Thing item in ListerHaulables.ThingsPotentiallyNeedingHauling().Where(item
                                                                                                       => !job.targetQueueA.Contains(item) && !item.IsBurning() &&
                                                                                                       !item.IsInAnyStorage() &&
                                                                                                       (UseBackpack
                                   ? item.def.thingCategories.Exists(
                                                                                                            category =>
                                                                                                            backpack.slotsComp.Properties.allowedThingCategoryDefs.Exists(
                                                                                                                subCategory =>
                                                                                                                subCategory.ThisAndChildCategoryDefs.Contains(category))
                                                                                                            &&
                                                                                                            !backpack.slotsComp.Properties.forbiddenSubThingCategoryDefs.Exists(
                                                                                                                subCategory =>
                                                                                                                subCategory.ThisAndChildCategoryDefs.Contains(category)))
                                   : cart.allowances.Allows(item)) &&
                                                                                                       !item.IsForbidden(pawn.Faction) &&
                                                                                                       slotGroup.Settings.AllowedToAccept(item) &&
                                                                                                       pawn.CanReserveAndReach(item, PathEndMode.Touch, pawn.NormalMaxDanger()) &&
                                                                                                       center.DistanceToSquared(item.Position) <= ValidDistance))
                        {
                            job.targetQueueA.Add(item);
                            if (UseBackpack)
                            {
                                job.numToBringList.Add(item.def.stackLimit);
                            }
                            reservedMaxItem++;

                            if (reservedMaxItem + job.targetQueueA.Count >= maxItem)
                            {
                                break;
                            }
                        }
                    }

                    //Also enqueue items in whiche are not in their best storage cell
                    if (reservedMaxItem + job.targetQueueA.Count < maxItem)
                    {
                        Trace.AppendLine("Start Enqueuing items in valid distance & not in best storage cell");
                        foreach (Thing item in ListerHaulables.ThingsPotentiallyNeedingHauling().Where(item
                                                                                                       => !job.targetQueueA.Contains(item) && !item.IsBurning() &&
                                                                                                       !item.IsInValidBestStorage() &&
                                                                                                       (UseBackpack
                                   ? item.def.thingCategories.Exists(
                                                                                                            category =>
                                                                                                            backpack.slotsComp.Properties.allowedThingCategoryDefs.Exists(
                                                                                                                subCategory =>
                                                                                                                subCategory.ThisAndChildCategoryDefs.Contains(category))
                                                                                                            &&
                                                                                                            !backpack.slotsComp.Properties.forbiddenSubThingCategoryDefs.Exists(
                                                                                                                subCategory =>
                                                                                                                subCategory.ThisAndChildCategoryDefs.Contains(category)))
                                   : cart.allowances.Allows(item)) &&
                                                                                                       !item.IsForbidden(pawn.Faction) &&
                                                                                                       slotGroup.Settings.AllowedToAccept(item) &&
                                                                                                       pawn.CanReserveAndReach(item, PathEndMode.Touch, pawn.NormalMaxDanger()) &&
                                                                                                       center.DistanceToSquared(item.Position) <= ValidDistance))
                        {
                            job.targetQueueA.Add(item);
                            if (UseBackpack)
                            {
                                job.numToBringList.Add(item.def.stackLimit);
                            }
                            reservedMaxItem++;

                            if (reservedMaxItem + job.targetQueueA.Count >= maxItem)
                            {
                                break;
                            }
                        }
                    }

                    //Find storage cell
                    Trace.AppendLine("Start Finding storage cell");
                    if (reservedMaxItem + job.targetQueueA.Count > thresholdItem)
                    {
                        foreach (
                            IntVec3 cell in
                            slotGroup.CellsList.Where(
                                cell =>
                                pawn.CanReserveAndReach(cell, PathEndMode.ClosestTouch, Danger.Some) &&
                                cell.Standable() && cell.GetStorable() == null))
                        {
                            StoragePriority currentPriority = HaulAIUtility.StoragePriorityAtFor(thing.Position, thing);
                            IntVec3         storeCell       = cell;
                            if (
                                !StoreUtility.TryFindBestBetterStoreCellFor(thing, pawn, currentPriority, pawn.Faction,
                                                                            out storeCell))
                            {
                                if (cell.InAllowedArea(pawn))
                                {
                                    job.targetQueueB.Add(cell);
                                }
                                if (job.targetQueueB.Count >= job.targetQueueA.Count)
                                {
                                    break;
                                }
                            }
                            else
                            {
                                if (storeCell.InAllowedArea(pawn))
                                {
                                    job.targetQueueB.Add(storeCell);
                                }
                                if (job.targetQueueB.Count >= job.targetQueueA.Count)
                                {
                                    break;
                                }
                            }
                        }
                        break;
                    }
                    job.targetQueueA.Clear();
                }
            }
            Trace.AppendLine("Elapsed Time");
            Trace.stopWatchStop();

            //Check job is valid
            if (!job.targetQueueA.NullOrEmpty() && reservedMaxItem + job.targetQueueA.Count > thresholdItem &&
                !job.targetQueueB.NullOrEmpty())
            {
                Trace.AppendLine("Hauling Job is issued");
                Trace.LogMessage();
                return(job);
            }
            if (cart != null && job.def == HaulJobDefOf.HaulWithCart && !cart.IsInValidStorage())
            {
                Trace.AppendLine("In DismountInBase: ");
                return(DismountInBase(pawn, cart));
            }

            if (job.targetQueueA.NullOrEmpty())
            {
                JobFailReason.Is("NoHaulable".Translate());
            }
            else if (reservedMaxItem + job.targetQueueA.Count <= thresholdItem)
            {
                JobFailReason.Is(TooLittleHaulable);
            }
            else if (job.targetQueueB.NullOrEmpty())
            {
                JobFailReason.Is(NoEmptyPlaceLowerTrans);
            }
            Trace.AppendLine("No Job. Reason: " + JobFailReason.Reason);
            Trace.LogMessage();
            return(null);
        }