// Vertical generation is a no-go for now
        /// <summary>
        /// Create the vertical upper and lower levels of the arena
        /// </summary>
        /// <param name="arena">The placed pieces that will be selected</param>

        /* private void MakeVerticalArena(ICollection<ArenaPiece> arena)
         *  {
         *
         *      List<ArenaPiece> placedHaveTopConns = new List<ArenaPiece>();
         *      List<ArenaPiece> placedHaveBotConns = new List<ArenaPiece>();
         *
         *
         *      (bool t, bool b) verticals;
         *      (bool valid, Transform trn) evaluationResult;
         *
         *      foreach(ArenaPiece a in arena)
         *      {
         *          verticals = a.GetVerticalConnectors();
         *          if(verticals.t)
         *              placedHaveTopConns.Add(a);
         *          if(verticals.b)
         *              placedHaveBotConns.Add(a);
         *      }
         *
         *      // Upper Levels
         *      if(_upperLevelIslandGeneration && placedHaveTopConns.Count > 0)
         *      {
         *
         *          for(int i = 0; i < _upperIslandsCount; i++)
         *          {
         *              int rng = Random.Range(0,placedHaveTopConns.Count);
         *              _selectedPiece = placedHaveTopConns[rng];
         *
         *              pickEvaluatingPiece:
         *
         *              int sortRng = Random.Range(0,_sortedPieces.Count);
         *              int listRng = Random.Range(0,_sortedPieces[sortRng].Count);
         *
         *              _evaluatingPiece = _sortedPieces[sortRng][listRng];
         *
         *              GameObject spawnedPiece =
         *                  Instantiate(_evaluatingPiece).gameObject;
         *              ArenaPiece spawnedScript =
         *                  spawnedPiece.GetComponent<ArenaPiece>();
         *
         *              if(_evaluatingPiece != null)
         *                  evaluationResult =_selectedPiece.EvaluatePieceVertical(
         *                      spawnedScript, true);
         *              else
         *                  goto pickEvaluatingPiece;
         *
         *              if(evaluationResult.valid)
         *              {
         *                  _placedPieces.Add(spawnedScript);
         *
         *              }
         *              else
         *                  Destroy(spawnedPiece);
         *
         *
         *          }
         *
         *      }
         *      else if(!_upperLevelIslandGeneration && placedHaveTopConns.Count > 0)
         *      {
         *
         *          _placedPieces.AddRange(MakeHorizontalArena
         *          (placedHaveTopConns[Random.Range(0, placedHaveTopConns.Count)]));
         *
         *      }
         *
         *      // Lower Levels
         *      if (_lowerLevelIslandGeneration && placedHaveBotConns.Count > 0)
         *      {
         *          int placed = 0;
         *          while(placed < _lowerIslandsCount)
         *          {
         *              int rng = Random.Range(0, placedHaveBotConns.Count);
         *              _selectedPiece = placedHaveBotConns[rng];
         *
         *              foreach (ArenaPiece a in placedHaveBotConns)
         *                  a.wasAnalysed = false;
         *
         *              pickEvaluatingPiece:
         *
         *              int sortRng = Random.Range(0, _sortedPieces.Count);
         *              int listRng = Random.Range(0, _sortedPieces[sortRng].Count);
         *
         *              _evaluatingPiece = _sortedPieces[sortRng][listRng];
         *
         *              GameObject spawnedPiece =
         *                              Instantiate(_evaluatingPiece).gameObject;
         *              ArenaPiece spawnedScript =
         *                  spawnedPiece.GetComponent<ArenaPiece>();
         *
         *              if (_evaluatingPiece != null && !_evaluatingPiece.wasAnalysed)
         *                  evaluationResult = _selectedPiece.EvaluatePieceVertical(
         *                      spawnedScript, false);
         *              else
         *                  goto pickEvaluatingPiece;
         *
         *              if (evaluationResult.valid)
         *              {
         *                  _placedPieces.Add(spawnedScript);
         *                  placed++;
         *
         *              }
         *              else
         *              {
         *                  _evaluatingPiece.wasAnalysed = true;
         *                  Destroy(spawnedPiece);
         *                  goto pickEvaluatingPiece;
         *              }
         *
         *
         *
         *          }
         *
         *
         *      }
         *      else if (!_lowerLevelIslandGeneration && placedHaveBotConns.Count > 0)
         *      {
         *
         *          int rng = Random.Range(0, placedHaveBotConns.Count);
         *          _selectedPiece = placedHaveBotConns[rng];
         *
         *          foreach (ArenaPiece a in placedHaveBotConns)
         *              a.wasAnalysed = false;
         *
         *          pickEvaluatingPiece:
         *
         *          int sortRng = Random.Range(0, _sortedPieces.Count);
         *          int listRng = Random.Range(0, _sortedPieces[sortRng].Count);
         *
         *          _evaluatingPiece = _sortedPieces[sortRng][listRng];
         *
         *          GameObject spawnedPiece =
         *                          Instantiate(_evaluatingPiece).gameObject;
         *          ArenaPiece spawnedScript =
         *              spawnedPiece.GetComponent<ArenaPiece>();
         *
         *          if (_evaluatingPiece != null && !_evaluatingPiece.wasAnalysed)
         *              evaluationResult = _selectedPiece.EvaluatePieceVertical(
         *                  spawnedScript, false);
         *          else
         *              goto pickEvaluatingPiece;
         *
         *          if (evaluationResult.valid)
         *          {
         *              _placedPieces.Add(spawnedScript);
         *              _placedPieces.AddRange(MakeHorizontalArena(spawnedScript));
         *
         *          }
         *          else
         *          {
         *              _evaluatingPiece.wasAnalysed = true;
         *              Destroy(spawnedPiece);
         *              goto pickEvaluatingPiece;
         *          }
         *      }
         *  }*/

        /// <summary>
        /// Select and place the first piece of the arena
        /// </summary>
        private void PickFirstPiece()
        {
            // To be safe if the starters list fails
chooseStarter:

            ArenaPiece choosen = null;


            int choosenIndex = 0;

            _placedPieces = new List <ArenaPiece>();

            if (_setStartingPiece)
            {
                if (_possibleStartingPieces.Count == 0)
                {
                    Debug.LogError(
                        "'Set starting piece' is on but no ArenaPieces were given");
                    _setStartingPiece = false;
                    goto chooseStarter;
                }

                choosenIndex = Random.Range(0, _possibleStartingPieces.Count);
                choosen      = _possibleStartingPieces[choosenIndex];
            }
            else
            {
                if (_generationMethod == GenerationTypes.CORRIDOR ||
                    _generationMethod == GenerationTypes.BRANCH)
                {
                    choosenIndex = Random.Range(
                        0, _sortedPieces[_sortedPieces.Count - 1].Count);

                    choosen = _sortedPieces[_sortedPieces.Count - 1][choosenIndex];
                }

                else
                {
                    choosenIndex = Random.Range(0, _sortedPieces[0].Count);
                    choosen      = _sortedPieces[0][choosenIndex];
                }
            }
            GameObject piece = Instantiate(choosen.gameObject);

            piece.name = arenaName;
            _placedPieces.Add(piece.GetComponent <ArenaPiece>());
        }
        /// <summary>
        /// Populates a horizontal level of the arena
        /// </summary>
        /// <param name="startingPiece"> The first piece of the arena</param>
        /// <returns> The pieces placed during this method's process</returns>
        private List <ArenaPiece> MakeHorizontalArena(ArenaPiece startingPiece)
        {
            int placedAmount = 0;
            int jumpsTaken   = 0;

            uint maxFailures = _maxPieceCount;
            // Pieces placed by this method call
            List <ArenaPiece> arena = new List <ArenaPiece>();
            //List<ArenaPiece> spawnedArena = new List<ArenaPiece>();

            // Check what list of the sorted list the selected belongs to
            int myPieceList = 0;

            for (int i = -1; i < arena.Count; i++)
            {
                int failureCount = 0;
                if (i == -1)
                {
                    _selectedPiece = startingPiece;
                }
                else
                {
                    _selectedPiece = arena[i];
                    //placedAmount++;
                }

                // Pick a piece to evaluate against our selected placed one
selectPiece:

                int rng;
                int wideRng = Random.Range(0, _sortedPieces.Count);
                myPieceList = wideRng;
                if (_sortedPieces[myPieceList].Count != 0)
                {
                    rng = Random.Range(0, _sortedPieces[myPieceList].Count);
                }
                else
                {
                    goto selectPiece;
                }


                _evaluatingPiece = _sortedPieces[myPieceList][rng];



                GameObject spawnedPiece = Instantiate(_evaluatingPiece).gameObject;
                //spawnedPiece.name = arenaName;
                ArenaPiece spawnedScript = spawnedPiece.GetComponent <ArenaPiece>();

                (bool valid, Transform trn)evaluationResult =
                    _selectedPiece.EvaluatePiece(spawnedScript,
                                                 _pieceDistance,
                                                 _pinCountTolerance);

                // If things worked out, spawn the piece in the correct position
                if (evaluationResult.valid)
                {
                    spawnedPiece.name = $"{i}";
                    arena.Add(spawnedScript);
                    placedAmount++;
                    spawnedScript.gameObject.transform.SetParent(_selectedPiece.transform);

                    if (arena.Count >= _maxPieceCount)
                    {
                        return(arena);
                    }
                }
                else
                {
                    if (failureCount > maxFailures)
                    {
                        continue;
                    }

                    // No valid connectors in the given piece
                    Destroy(spawnedPiece);
                    failureCount++;

                    goto selectPiece;
                }


                // if this one has no more free connectors, move on to the next
                // placed piece
                switch (_generationMethod)
                {
                case GenerationTypes.CORRIDOR:
                    continue;

                // For some reason the first branch gets double pieces
                case GenerationTypes.STAR:
                    int[] multi    = new int[] { -1, 1 };
                    int   variance =
                        multi[Random.Range(0, 2)] * _branchSizeVariance;

                    if (placedAmount < _branchPieceCount + variance)
                    {
                        continue;
                    }


                    else if (placedAmount >= _branchPieceCount + variance &&
                             !startingPiece.IsFull())
                    {
                        print($"placed: {placedAmount}, arena: {arena.Count}");
                        placedAmount   = 0;
                        _selectedPiece = startingPiece;

                        // it works dont ask me why
                        i += 1;
                        print($"Selected piece is now {_selectedPiece.gameObject} - index {i}");
                        goto selectPiece;
                    }
                    return(arena);

                case GenerationTypes.BRANCH:
                    int[] mult       = new int[] { -1, 1 };
                    int   multiplier =
                        mult[Random.Range(0, 2)] * _branchSizeVariance;

                    if (placedAmount < _branchPieceCount + multiplier)
                    {
                        continue;
                    }
                    else if (placedAmount > _branchPieceCount + multiplier)
                    {
                        int variableVariance;
                        variableVariance = mult[(int)Random.Range(0,
                                                                  _PieceSkippingVariance + 1)];

                        int dist =
                            (int)_branchGenPieceSkipping + variableVariance * jumpsTaken;

                        int jump = (int)Mathf.Clamp(dist,
                                                    1, arena.Count - 1);

                        if (!arena[0 + jump].IsFull())
                        {
                            print($"{jumpsTaken} - {jump}");
                            placedAmount = 0;
                            //_selectedPiece = arena[jump];
                            i = jump;
                            //i = Mathf.Clamp(i, 0, arena.Count - 1);
                            jumpsTaken++;
                            continue;
                        }
                    }
                    break;
                }


                if (_selectedPiece.IsFull())
                {
                    continue;
                }
                else // else choose another piece to evaluate for this one
                {
                    goto selectPiece;
                }
            }

            return(arena);
        }