How to stop infinite loops in turn based game.

Unity freezes (presumably because there is an infinite loop) when I run this code.

My logic is:
I call updateTurn, which organizes the players by speed and calls actionPhase on the next fastest unit. actionPhase sets the turnState to 1, which turns on the actionPhase GUI. At this point the player clicks the move button, which sets the turnState to 2. While turnState is 2, update polls the users mouseclicks until a valid move is made, at which point turnState is updated to 9, ending the turn.

All methods work properly on their own EXCEPT actionPhase, which always freezes the game. How can I stop the infinite loop from happening?

Sorry about the formatting. I swear it’s impossible to copy/paste code :frowning:

	//Update turn orders players by speed and then calls action phase on them
	void updateTurn()
	{
		int playerSize = players.Count;
		int index = 0;
		PlayerStats ps;
		//turnState = 0;
				
		print("Turn Started");
				
		//calculate fastest player
		sortPlayersBySpeed();
		index = 0;
		
		//ps = players[index].GetComponent<PlayerStats>();
		
		index = 0;				
		while(index < playerSize)
		{
			print("entering loop");
			ps = players[index].GetComponent<PlayerStats>();
			if(ps.dead == false)
			{
				print("Starting Action Phase " + index);
				actionPhase(players[index]);
				print("Ended Action Phase" + index);
			}			
                index++;
                }
	}


void actionPhase(GameObject player){
		turnState = 1;
		
		while(turnState != 9)
		{
			switch(turnState)
			{
			case 0:
				//No player selected
				break;
			case 1:
				//player selected, actionphase begun, wait for GUI
				break;
			case 2:
				//move selected, update is getting new click positions
				print("move selected");
				if(moveValid(player, clickPosition) == true)
				{
					StartCoroutine(moveObject(player, clickPosition));
					turnState = 9;
				}
				break;
			case 9:
				print("turns over");
				return;

			}
		}
	}

void OnGUI () {
		if(turnState == 1 || turnState == 2 || turnState == 8)
		{
			if (GUI.Button (new Rect (10,10, 100, 50), moveButton)) 
			{
				print ("you clicked move");
				if(turnState == 1)
				{
					turnState = 2;
				}
			}
		}
    }

	// Update is called once per frame
	void Update () {
		if(turnState == 2 || turnState == 8)
		{
			clickPosition = getTaggedClickPos("Ground");
			print(clickPosition);
		}
  	}

Just desk-checking your code in actionPhase (should actually be ActionPhase. We capitalize functions in C#) simply and plainly reveals your infinite loop:

  1. set turnState to 1
  2. Begin a while loop, while turnState is not equal to 9
  3. turnState is equal to 1, so go to case 1 and… break.
  4. Now, we are still in the while loop, so continue from 2. (turnState is still 1)

Always remember, break is one level only. In a switch, break will break out of the switch. Nothing more, nothing less.

After reading Benprod’s reply, it seems like the whole turn sequencing is borked, and needs an overhaul.

So, there’s an “action queue” like finalFantasy Tactics, of who goes when. The loop at the bottom of updateTurn goes through the whole list, giving each player a turn using actionPhase. actionPhase completely runs a player’s turn, returning when the player has finished.

BUT this should all happen over many frames!! So actionPhase and updateTurn should be coroutines – yield return null; in actionPhase, and yield startCoroutine(actionPhase..) in updateTurn.

But otherwise the style of programming doesn’t feel like a coroutine. As normal code, get rid of all the loops. ActionPhase would just check what you did this frame, and if it was the “confirm action” button, say that player is done. UpdateTurn just runs actionPhase for the current player. If they were done, resort the list (and check the new 1st player next frame.)

You have quite many while loops & thingies there.

Instead of “waiting for state 9…”, you could consider something like here. This is partially pseudo code, so plenty of figuring it out here. But hopefully this gives some idea about what you could consider doing: break the code into smaller pieces, treat each turn phase in separate blocks. This isn’t the final code, you still need to think how you want to arrange your code.

Currently your breaks in line 45, where it can never leave the “while” loop… here’s bit of code to hopefully help you out :slight_smile:


void updateTurn() {
   switch currentTurnPhase {
     case "newturn":
        initTurn(); 
        currentPlayer = getNextPlayer(); //this one finds the next alive player on the list
        currentTurnPhase = "playerturn";
        break;

     case "playerturn":
        if (clickedMoveSomewhere) { 
          currentPlayer = getNextPlayer(); //returns null in case this was the last chap
        }
        if (currentPlayer == null) {
           //nobody left, let's end the turn
           currentTurnPhase = "endturn";
        }
        break;

     case "endturn":
           // do something
           ...
           // start a new turn
           currentTurnPhase = "newturn"
           break;
 }

}