public Tuple <int, StructuredAlias> Generate1RandomAliasFromRealMap(StructuredAlias realMap)
    {
        mainMap  = realMap.AliasMap;
        gridType = ParameterManager.Instance.GridType;
        Vector2Int startMainMap = realMap.start;
        int        width        = realMap.AliasMap.GetLength(0);
        int        height       = realMap.AliasMap.GetLength(1);

        //Map initialization.
        int i = 0;

        Tuple <int, StructuredAlias> AliasTuple;

        Vector2Int startAlias = realMap.start;
        Vector2Int endAlias   = realMap.end;
        float      dst        = 0;

        TileObject[,] aliasMap = new TileObject[width, height];

        while (i < 1)
        {
            //define here the width, height, start and end  of the chosen map


            genMan.connectedGenerator.setBaseGeneratorParameters(gridType, width, height, startAlias, endAlias, i, false);
            genMan.cellularAutomataGenerator.setBaseGeneratorParameters(gridType, width, height, startAlias, endAlias, i, false);
            genMan.primGenerator.setBaseGeneratorParameters(gridType, width, height, startAlias, endAlias, i, false);

            switch (pRNG_Alias.Next() % 3)
            {
            case 0:
                aliasMap = genMan.connectedGenerator.generateMapGeneral(ParameterManager.Instance.IsTrapsOnMapBorder, (float)pRNG_Alias.NextDouble());
                break;

            case 1:
                float prcObsCA = (float)pRNG_Alias.NextDouble();
                aliasMap = genMan.cellularAutomataGenerator.generateMapGeneral(ParameterManager.Instance.IsTrapsOnMapBorder, prcObsCA, 1 + (prcObsCA <= .5f && !(i % 2 == 1) ? 0 : pRNG_Alias.Next(0, 6)), 5, i % 2 == 1, 0, 0);
                break;

            case 2:
                aliasMap = genMan.primGenerator.generateMapGeneral(ParameterManager.Instance.IsTrapsOnMapBorder, (float)pRNG_Alias.NextDouble());
                break;

            default:
                ErrorManager.ManageError(ErrorManager.Error.HARD_ERROR, "AliasManager: no map generator found.");
                break;
            }

            foreach (var m in BaseAliasCollisionMask)
            {
                if (Utility.in_bounds_General(new Vector2Int(startMainMap.x + m.x, startMainMap.y + m.y), mainMap.GetLength(0), mainMap.GetLength(1)) &&
                    Utility.in_bounds_General(new Vector2Int(startAlias.x + m.x, startAlias.y + m.y), aliasMap.GetLength(0), aliasMap.GetLength(1)))
                {
                    aliasMap[startAlias.x + m.x, startAlias.y + m.y].type = ParameterManager.Instance.MapToPlay[startMainMap.x + m.x, startMainMap.y + m.y].type;
                }
            }

            if (MapEvaluator.isEndReachable(aliasMap, gridType, startAlias, endAlias, ParameterManager.Instance.allowAutosolverForAlias).First() == endAlias)
            {
                //if the map has a path from start to end, add it
                dst = MapEvaluator.BinaryMapSimilarity(mainMap, aliasMap, startMainMap, startAlias);

                i++;
            }
        }


        AliasTuple = new Tuple <int, StructuredAlias>(Guid.NewGuid().GetHashCode(), new StructuredAlias(aliasMap, startAlias, endAlias, dst));
        return(AliasTuple);
    }
    public void GenerateAndTestAliasMaps()
    {
        Vector2Int startMainMap = ParameterManager.Instance.StartCell;
        int        width        = ParameterManager.Instance.MapToPlay.GetLength(0);
        int        height       = ParameterManager.Instance.MapToPlay.GetLength(1);


        BaseAliasCollisionMask = getMainMapKMaxMinCells(mainMap, gridType, ParameterManager.Instance.minStepsSolution, ParameterManager.Instance.minStepsSolution, startMainMap, 0f);
        HashSet <Vector2Int>[,] AliasCollisionMaskMatrix = new HashSet <Vector2Int> [ParameterManager.Instance.maxStepsSolution - ParameterManager.Instance.minStepsSolution, MAX_ALIASMASKS];

        if (ParameterManager.Instance.maxStepsSolution > ParameterManager.Instance.minStepsSolution)
        {
            for (int h = 0; h < ParameterManager.Instance.maxStepsSolution - ParameterManager.Instance.minStepsSolution; h++)
            {
                for (int k = 0; k < MAX_ALIASMASKS; k++)
                {
                    AliasCollisionMaskMatrix[h, k] = getMainMapKMaxMinCells(mainMap, gridType, ParameterManager.Instance.minStepsSolution, ParameterManager.Instance.minStepsSolution + h + 1, startMainMap, ((k + 1) * 1.0f) / (MAX_ALIASMASKS));;
                }
            }
        }
        else
        {
            AliasCollisionMaskMatrix = null;
        }

        //Map initialization.
        int i = 0;



        Vector2Int startAlias = ParameterManager.Instance.StartCell;
        Vector2Int endAlias   = ParameterManager.Instance.EndCell;


        while (i < MAX_ALIAS)
        {
            //define here the width, height, start and end  of the chosen map
            TileObject[,] aliasMap = new TileObject[width, height];

            genMan.connectedGenerator.setBaseGeneratorParameters(gridType, width, height, startAlias, endAlias, i, false);
            genMan.cellularAutomataGenerator.setBaseGeneratorParameters(gridType, width, height, startAlias, endAlias, i, false);
            genMan.primGenerator.setBaseGeneratorParameters(gridType, width, height, startAlias, endAlias, i, false);

            switch (i % 3)
            {
            case 0:
                aliasMap = genMan.connectedGenerator.generateMapGeneral(ParameterManager.Instance.IsTrapsOnMapBorder, (float)pRNG_Alias.NextDouble());
                break;

            case 1:
                aliasMap = genMan.cellularAutomataGenerator.generateMapGeneral(ParameterManager.Instance.IsTrapsOnMapBorder, (float)pRNG_Alias.NextDouble(), 1 + i % 5, 5, i % 2 == 1, 0, 0);
                break;

            case 2:
                aliasMap = genMan.primGenerator.generateMapGeneral(ParameterManager.Instance.IsTrapsOnMapBorder, (float)pRNG_Alias.NextDouble());
                break;

            default:
                ErrorManager.ManageError(ErrorManager.Error.HARD_ERROR, "AliasManager: no map generator found.");
                break;
            }

            //Apply mask...
            //from zero to kMinStep and up to some cells at kMaxStep
            if (ParameterManager.Instance.maxStepsSolution > ParameterManager.Instance.minStepsSolution)
            {
                for (int x = 0; x < aliasMap.GetLength(0); x++)
                {
                    for (int y = 0; y < aliasMap.GetLength(1); y++)
                    {
                        if (Utility.in_bounds_General(new Vector2Int(startMainMap.x + x, startMainMap.y + y), width, height))
                        {
                            if (AliasCollisionMaskMatrix[i % AliasCollisionMaskMatrix.GetLength(0), i % AliasCollisionMaskMatrix.GetLength(1)].Contains(new Vector2Int(x - startAlias.x, y - startAlias.y)))
                            {
                                aliasMap[x, y].type = ParameterManager.Instance.MapToPlay[startMainMap.x + x, startMainMap.y + y].type;
                            }
                        }
                    }
                }
            }
            else
            {
                //only from zero to kMinStep
                foreach (var m in BaseAliasCollisionMask)
                {
                    if (Utility.in_bounds_General(new Vector2Int(startMainMap.x + m.x, startMainMap.y + m.y), mainMap.GetLength(0), mainMap.GetLength(1)) &&
                        Utility.in_bounds_General(new Vector2Int(startAlias.x + m.x, startAlias.y + m.y), aliasMap.GetLength(0), aliasMap.GetLength(1)))
                    {
                        aliasMap[startAlias.x + m.x, startAlias.y + m.y].type = ParameterManager.Instance.MapToPlay[startMainMap.x + m.x, startMainMap.y + m.y].type;
                    }
                }
            }

            if (MapEvaluator.isEndReachable(aliasMap, gridType, startAlias, endAlias, ParameterManager.Instance.allowAutosolverForAlias).First() == endAlias)
            {//if the map has a path from start to end, add it
                float dst = MapEvaluator.BinaryMapSimilarity(mainMap, aliasMap, startMainMap, startAlias);
                SimilarMapsQueue.Enqueue(aliasMap, dst);
            }
            i++;
        }
    }
    public Dictionary <int, StructuredAlias> GenerateNRandomAliasFromRealMap(StructuredAlias realMap, int N)
    {
        mainMap  = realMap.AliasMap;
        gridType = ParameterManager.Instance.GridType;
        Vector2Int startMainMap = realMap.start;
        int        width        = realMap.AliasMap.GetLength(0);
        int        height       = realMap.AliasMap.GetLength(1);

        //Map initialization.
        int i = 0;

        Dictionary <int, StructuredAlias> AliasBatch = new Dictionary <int, StructuredAlias>();

        Vector2Int startAlias = realMap.start;
        Vector2Int endAlias   = realMap.end;
        SimplePriorityQueue <TileObject[, ]> tmpPQ = new SimplePriorityQueue <TileObject[, ]>();
        bool isAliasSameAsReal = true;

        while (i < N)
        {
            //define here the width, height, start and end  of the chosen map
            TileObject[,] aliasMap = new TileObject[width, height];

            genMan.connectedGenerator.setBaseGeneratorParameters(gridType, width, height, startAlias, endAlias, (i % 2 == 0?1:-1) * RNG_Alias.Next(), false);
            genMan.cellularAutomataGenerator.setBaseGeneratorParameters(gridType, width, height, startAlias, endAlias, (i % 2 == 0 ? 1 : -1) * RNG_Alias.Next(), false);
            genMan.primGenerator.setBaseGeneratorParameters(gridType, width, height, startAlias, endAlias, (i % 2 == 0 ? 1 : -1) * RNG_Alias.Next(), false);

            switch (i % 3)
            {
            case 0:
                aliasMap = genMan.connectedGenerator.generateMapGeneral(ParameterManager.Instance.IsTrapsOnMapBorder, (float)RNG_Alias.NextDouble());
                break;

            case 1:
                float prcObsCA = (float)RNG_Alias.NextDouble();
                aliasMap = genMan.cellularAutomataGenerator.generateMapGeneral(ParameterManager.Instance.IsTrapsOnMapBorder, prcObsCA, 1 + (prcObsCA <= .5f && !(i % 2 == 1)?0:RNG_Alias.Next(0, 6)), 5, i % 2 == 1, 0, 0);
                break;

            case 2:
                aliasMap = genMan.primGenerator.generateMapGeneral(ParameterManager.Instance.IsTrapsOnMapBorder, (float)RNG_Alias.NextDouble());
                break;

            default:
                ErrorManager.ManageError(ErrorManager.Error.HARD_ERROR, "AliasManager: no map generator found.");
                break;
            }

            foreach (var m in BaseAliasCollisionMask)
            {
                if (Utility.in_bounds_General(new Vector2Int(startMainMap.x + m.x, startMainMap.y + m.y), mainMap.GetLength(0), mainMap.GetLength(1)) &&
                    Utility.in_bounds_General(new Vector2Int(startAlias.x + m.x, startAlias.y + m.y), aliasMap.GetLength(0), aliasMap.GetLength(1)))
                {
                    aliasMap[startAlias.x + m.x, startAlias.y + m.y].type = realMap.AliasMap[startMainMap.x + m.x, startMainMap.y + m.y].type;
                }
            }

            for (int h = 0; h < width; h++)
            {
                for (int k = 0; k < height; k++)
                {
                    isAliasSameAsReal &= (aliasMap[h, k].type == realMap.AliasMap[h, k].type);

                    if (!isAliasSameAsReal)
                    {
                        break;
                    }
                }
                if (!isAliasSameAsReal)
                {
                    break;
                }
            }

            if (MapEvaluator.isEndReachable(aliasMap, gridType, startAlias, endAlias, ParameterManager.Instance.allowAutosolverForAlias).First() == endAlias && !isAliasSameAsReal)
            {
                //if the map has a path from start to end, add it
                float dst = MapEvaluator.BinaryMapSimilarity(mainMap, aliasMap, startMainMap, startAlias);
                tmpPQ.Enqueue(aliasMap, dst);


                i++;
            }
        }

        i = 0;
        TileObject[,] tmpStrAlias;
        while (i < N)
        {
            if (ParameterManager.Instance.considerSimilar)
            {
                float dst = tmpPQ.GetPriority(tmpPQ.First());
                tmpStrAlias = tmpPQ.Dequeue();

                AliasBatch.Add(Guid.NewGuid().GetHashCode(), new StructuredAlias(tmpStrAlias, startAlias, endAlias, dst));

                i++;
            }

            if (ParameterManager.Instance.considerNovelty && i < N)
            {
                tmpStrAlias = tmpPQ.Last();
                float dst = tmpPQ.GetPriority(tmpStrAlias);
                tmpPQ.Remove(tmpStrAlias);

                AliasBatch.Add(Guid.NewGuid().GetHashCode(), new StructuredAlias(tmpStrAlias, startAlias, endAlias, dst));

                i++;
            }
        }

        return(AliasBatch);
    }