IEnumerator co_mainLoop() { m_state = State.Ready; IPCConnection.Message message = null; while (m_state != State.GameOver) // 게임오버 스테이트에 도달할 때까지 계속 반복 { // 1. solver index 입력 m_requestedInput = InputType.SolverIndex; // solver index를 골라야함 while ((message = ProcessMessage()) == null) // 유의미한 메세지 리턴받을 때까지 기다린다. { yield return(null); } if (m_state == State.GameOver) // 게임 종료시 루프 빠져나오기 { break; } if (message.header == IPCConnection.Message.Header.Await) // 입력 기다리는 경우 - solver index임! { //Debug.Log("Solver index await"); m_state = State.SelectSolver; m_waitForInput = true; //Debug.Log("waiting for input : " + m_requestedInput); } while (m_waitForInput) // 입력 해결될 때까지 기다린다. { yield return(null); } // 2. SolverStart 기다리기 while ((message = ProcessMessage()) == null) // 유의미한 메세지 리턴받을 때까지 기다린다. { yield return(null); } if (m_state == State.GameOver) // 게임 종료시 루프 빠져나오기 { break; } if (m_state != State.WaitingSolver) // WaitingSolver 상태가 아닌 경우엔 뭔가 잘못된 것임 { Debug.LogErrorFormat("wrong state {0} - must be WaitingSolver", m_state); m_state = State.GameOver; break; } // 3. Solver answer 혹은 유저입력 m_requestedInput = InputType.MovePosition; while ((message = ProcessMessage()) == null) // 유의미한 메세지 리턴받을 때까지 기다린다. { yield return(null); } if (m_state == State.GameOver) // 게임 종료시 루프 빠져나오기 { break; } if (message.header == IPCConnection.Message.Header.Await) // 입력 기다리는 경우 - solver index임! { m_state = State.SelectSolver; m_waitForInput = true; //Debug.Log("waiting for input : " + m_requestedInput); while (m_waitForInput) // 입력 해결될 때까지 기다린다. { yield return(null); } while ((message = ProcessMessage()) == null) // Solver Answer까지 기다린다 { yield return(null); } if (m_state == State.GameOver) // 게임 종료시 루프 빠져나오기 { break; } } // 3-1. 진짜로 solver 응답 처리 if (m_state == State.SolverAnswered) // solver가 답을 준 경우 (아마 이 경우밖에 없을것임) { var paramStr = message.message.Split(new char[] { ':' }, 2)[1]; var paramArr = paramStr.Split(new char[] { ',' }, 3); m_gameState.PlaceNewMove(int.Parse(paramArr[0]), int.Parse(paramArr[1]), paramArr[2]); } // 4. result 기다리기 while ((message = ProcessMessage()) == null) // 유의미한 메세지 리턴받을 때까지 기다린다. { yield return(null); } } Debug.Log("Game Over!"); // connection을 정리한다. m_connection.Kill(); // 보험... m_connection = null; }
/// <summary> /// 메세지를 폴링하고 처리할 수 있는 것들은 처리하고, 외부에서 처리해야할 메세지는 리턴한다. /// </summary> /// <returns></returns> IPCConnection.Message ProcessMessage() { IPCConnection.Message message = null; while ((message = m_connection.PollReceive()) != null) // polling하다가 null을 만나버린 경우엔 그냥 루프를 빠져나온다. { if (message.header == IPCConnection.Message.Header.Terminate) // 프로세스가 갑자기 종료되는 경우, 에러 처리 { m_gameState.SetStatus(GameState.Status.Error); // gamestate는 에러 상태로 맞추기 m_state = State.GameOver; break; // Terminate 메세지가 리턴된다. } else if (message.header == IPCConnection.Message.Header.Await) // Await를 만나면 그대로 리턴한다. { break; // Await 메세지가 리턴된다. } else { var msg = message.message; //Debug.Log("[message] " + msg); if (msg == c_msgHeader_solverStart) // solverStart 메세지를 만난 경우, 스테이트 변경 { m_state = State.WaitingSolver; break; // 메세지 리턴된다. } else if (msg.StartsWith(c_msgHeader_move)) // solver가 수를 둔 경우, 스테이트 변경하고 리턴 { m_state = State.SolverAnswered; break; // 메세지 리턴된다. } else if (msg.StartsWith(c_msgHeader_result)) // 게임이 종료되는 경우, 스테이트 변경하고 리턴 { var code = int.Parse(msg.Split(':')[1]); switch (code) // result code에 따라 gamestate세팅 { case 1: // 게임 진행중일 때에도 스테이트는 보내줘야한다. m_gameState.SetStatus(GameState.Status.Playing); break; case 2: m_gameState.SetStatus(GameState.Status.Draw); m_state = State.GameOver; break; case 10: case 11: m_gameState.SetStatus(GameState.Status.Win); m_state = State.GameOver; break; case 20: case 21: m_gameState.SetStatus(GameState.Status.Error); m_state = State.GameOver; break; } break; // 메세지 리턴된다. } } } return(message); }