private PopulationProvider FindBestHousing(
        Predicate <PopulationProvider> isViable,
        Func <PopulationProvider, PopulationProvider, bool> isBetter
        )
    {
        PopulationProvider current = null;

        foreach (Vector3Int position in BuildingMap.cellBounds.allPositionsWithin)
        {
            GameObject tileLogic = BuildingMap.GetInstantiatedObject(position);
            if (tileLogic == null || !tileLogic.activeSelf)
            {
                continue;
            }

            var candidate = tileLogic.GetComponent <PopulationProvider>();
            if (
                candidate != null &&
                isViable(candidate) &&
                (ReferenceEquals(current, null) || isBetter(candidate, current))
                )
            {
                current = candidate;
            }
        }

        return(current);
    }
    public void RemovePopulation()
    {
        PopulationProvider targetHousing = FindBestHousing(
            candidate => candidate.ResidentCount > 0,
            (candidate, current) => candidate.ConstructionOrder > current.ConstructionOrder
            );

        if (ReferenceEquals(targetHousing, null))
        {
            Debug.LogWarning("Can't find population to kill! Are you sure there are still people alive?");
            return;
        }

        targetHousing.Portraits.Pop();
        Population.value--;
    }
    public GameObject HousePopulation(Sprite portrait)
    {
        PopulationProvider targetHousing = FindBestHousing(
            candidate => candidate.ResidentCount < candidate.Capacity,
            (candidate, current) => candidate.ConstructionOrder < current.ConstructionOrder
            );

        if (ReferenceEquals(targetHousing, null))
        {
            _extraPopulation.Push(portrait);
            Population.value++;
            return(null);
        }

        targetHousing.Portraits.Push(portrait);

        Population.value++;

        return(targetHousing.gameObject);
    }