IEnumerator GameLoop()
    {
        Stopwatch watch = new Stopwatch();

        //Main loop
        while (true)
        {
            CallTurnStartGlobal();

            //Player turn sequence
            player.AddEnergy(energyPerTurn);
            while (player.energy > 0)
            {
                //Set up local turn
                player.StartTurn();

                //Run the actual turn itself
                IEnumerator turn = player.LocalTurn();
                while (player.energy > 0 && turn.MoveNext())
                {
                    if (turn.Current != GameAction.StateCheck)
                    {
                        yield return(turn.Current);
                    }
                }

                //Turn is ended!
                player.EndTurn();
            }


            watch.Restart();
            for (int i = 0; i < Map.current.monsters.Count; i++)
            {
                //Taken too much time? Quit then! (Done before monster update to handle edge case on last call)
                if (watch.ElapsedMilliseconds > MONSTER_UPDATE_MS)
                {
                    watch.Stop();
                    yield return(null);

                    watch.Restart();
                }

                Monster m = Map.current.monsters[i];

                m.AddEnergy(energyPerTurn);
                while (m.energy > 0 && !m.IsDead())
                {
                    //Set up local turn
                    m.StartTurn();

                    //Run the actual turn itself
                    IEnumerator turn = m.LocalTurn();
                    while (m.energy > 0 && turn.MoveNext())
                    {
                        if (turn.Current != GameAction.StateCheck)
                        {
                            watch.Stop();
                            yield return(turn.Current);

                            watch.Restart();
                        }
                        else
                        {
                            //Edge case - take a break during a check if we need to!
                            //Should make things a lot more fluid with complicated monster turns
                            if (watch.ElapsedMilliseconds > MONSTER_UPDATE_MS)
                            {
                                watch.Stop();
                                yield return(null);

                                watch.Restart();
                            }
                        }
                    }

                    //Turn is ended!
                    m.EndTurn();
                }
            }
            watch.Stop();

            //Clean up anybody who's dead
            for (int i = Map.current.monsters.Count - 1; i >= 0; i--)
            {
                Monster monster = Map.current.monsters[i];
                if (monster.IsDead())
                {
                    Map.current.monsters.RemoveAt(i);
                    Destroy(monster.gameObject);
                }
            }

            CallTurnEndGlobal();

            turn++;

            if (nextLevel != -1)
            {
                MoveLevel();
            }
        }
    }