static bool Prefix()
        {
            return(Patcher.Run(() =>
            {
                if (!Input.GetKeyDown(KeyCode.E))
                {
                    return true;
                }

                SituationController situation = GameBoard.GetOpenSituation();

                if (situation != null)
                {
                    foreach (var slot in SituSlotController.GetAllSlots(situation).AsEnumerable().Reverse())
                    {
                        var stack = slot.GetElementStackInSlot() as ElementStackToken;
                        if (stack != null)
                        {
                            stack.ReturnToTabletop(new Context(Context.ActionSource.PlayerDrag));
                            break;
                        }
                    }
                }

                return false;
            }));
        }
        static bool Prefix(RecipeSlot __instance)
        {
            return(Patcher.Run(() =>
            {
                // If neither shift is down give back control to the game immediately
                if (!Input.GetKey(KeyCode.LeftShift) && !Input.GetKey(KeyCode.RightShift))
                {
                    return true;
                }

                var slot = __instance;
                var situation = GameBoard.GetOpenSituation();

                if (situation == null || slot.GetElementStackInSlot() != null || !SituSlotController.GetAllEmptySlots(situation).Contains(slot))
                {
                    return true;
                }

                foreach (var stack in Positions.GetStacksRelativeTo(situation))
                {
                    if (SituSlotController.StackMatchesSlot(stack, slot))
                    {
                        SituSlotController.MoveStackIntoSlot(stack as ElementStackToken, slot);
                        break;
                    }
                }

                return false;
            }));
        }
        private static void HandleOngoing(SituationController situation)
        {
            var emptySlot = SituSlotController.GetFirstEmptyRecipeSlot(situation);

            if (emptySlot != null)
            {
                PopulateSlotWithNearbyStacks(situation, emptySlot);
            }
        }
        public static bool PopulateSlotWithNearbyStacks(SituationController situation, RecipeSlot slotToFill)
        {
            // Trying to fill all the slots
            var candidateStacks = Positions.GetAdjacentStacks(situation, Mod.AutomationDistance);

            foreach (var stack in candidateStacks)
            {
                if (SituSlotController.StackMatchesSlot(stack, slotToFill))
                {
                    var tokenAndSlot = new TokenAndSlot
                    {
                        RecipeSlot = slotToFill,
                        Token      = situation.situationToken as SituationToken
                    };
                    SituSlotController.FillSlotEventually(tokenAndSlot, stack as ElementStackToken);
                    return(true); // Successfully found a token for this slot
                }
            }
            return(false); // Failed to find a token for this slot
        }
        private static void HandleUnstarted(SituationController situation)
        {
            // Do nothing if we are paused
            if (Registry.Retrieve <TabletopManager>().GetPausedState())
            {
                return;
            }

            // Do nothing until at least a second has passed since last completion for smoother UX
            situationLastCompletionTimes.TryGetValue(situation, out DateTime lastCompletionTime);
            if ((lastCompletionTime != null) && ((DateTime.Now - lastCompletionTime).TotalSeconds < 1.2))
            {
                return;
            }

            var emptySlot = SituSlotController.GetFirstEmptyRecipeSlot(situation);

            // If no more slots can be filled we can try to activate the recipe
            if (emptySlot == null)
            {
                situation.AttemptActivateRecipe();
                return;
            }

            // Try to fill the slot and return if successful
            if (PopulateSlotWithNearbyStacks(situation, emptySlot))
            {
                return;
            }

            // We have slots to fill but nothing to fill them with. Possibly we already filled our primary slot
            // and just cannot find any "extra" cards. If that's the case we can activate the recipe with partially filled slots.
            var primarySlot = (situation.situationWindow as SituationWindow).GetPrimarySlot();

            if (primarySlot != null && primarySlot.GetElementStackInSlot() != null)
            {
                situation.AttemptActivateRecipe();
            }
        }
        static bool Prefix(ElementStackToken __instance)
        {
            return(Patcher.Run(() =>
            {
                // If neither shift is down give back control to the game immediately
                if (!Input.GetKey(KeyCode.LeftShift) && !Input.GetKey(KeyCode.RightShift))
                {
                    return true;
                }

                // Do not move cards in Mansus. Supporting this could be a future addition
                if (TabletopManager.IsInMansus())
                {
                    return false;
                }

                var stack = __instance;
                var situation = GameBoard.GetOpenSituation();
                List <RecipeSlot> slots = null;

                if (situation == null)
                {
                    foreach (var closedSituation in Positions.GetSituationsRelativeTo(stack))
                    {
                        if (closedSituation.CanAcceptStackWhenClosed(stack))
                        {
                            closedSituation.OpenWindow();
                            situation = closedSituation;
                            break;
                        }
                    }
                }

                if (situation == null)
                {
                    // Let controller handle the fail state
                    SituSlotController.MoveStackIntoSlot(stack, null);
                }
                else
                {
                    var populatedSlot = false;
                    slots = SituSlotController.GetAllEmptySlots(situation);
                    for (int i = 0; i < slots.Count; i++)
                    {
                        if (SituSlotController.StackMatchesSlot(stack, slots[i]))
                        {
                            SituSlotController.MoveStackIntoSlot(stack, slots[i]);
                            populatedSlot = true;
                            break;
                        }
                    }

                    // There is no slot available for us, allow the controller to handle the fail state
                    if (!populatedSlot)
                    {
                        SituSlotController.MoveStackIntoSlot(stack, null);
                    }
                }

                return false;
            }));
        }