public bool Play()
        {
            IEnumerable <HornClause> satisfiedTerminalClauses;

            try
            {
                if (!CheckIfAllPlayersAreUpAndRunning())
                {
                    return(false);
                }

                var traceListener        = DebugAndTraceHelper.GetListeners(DebugAndTraceHelper.StateChannelId).FirstOrDefault();
                var ieWebBrowserListener = traceListener as IEWebBrowserListener;

                // show this in the game manager's web browser
                var initialStateAsXML = TheGeneralGame.GetStateAsCompleteXML();
                DebugAndTraceHelper.WriteTraceLine(initialStateAsXML, DebugAndTraceHelper.StateChannelId);

                TurnRecord initialTurnRecord = new TurnRecord();
                initialTurnRecord.IsInitialState           = true;
                initialTurnRecord.GameState.GameStateAsXML = initialStateAsXML;
                //initialTurnRecord.GameState.GameStateAsHTML = ieWebBrowserListener == null ? "" : ieWebBrowserListener.ieWebBrowser.DocumentText;
                TurnRecords.Add(initialTurnRecord);

                IFormatter formatter       = new BinaryFormatter();
                var        historyFileName = DebugAndTraceHelper.CustomLocation + DebugAndTraceHelper.BaseFileName + "_" +
                                             (DateTime.Now.ToShortDateString() + "_" + DateTime.Now.ToLongTimeString()).Replace(" ", "_").Replace(@"/", "-").Replace(":", "-") + ".his";

                DebugAndTraceHelper.WriteTraceLine("Starting Players...", DebugAndTraceHelper.StatusStripChannelId);
                StartAllPlayers();

                var prevMoves = new List <Move>();
                DebugAndTraceHelper.WriteTraceLine("Checking for game termination...", DebugAndTraceHelper.StatusStripChannelId);
                bool gameHasTerminated = TheGeneralGame.FindTerminal(out satisfiedTerminalClauses);
                Move terminalMove      = null;
                while (!gameHasTerminated)
                {
                    DebugAndTraceHelper.WriteTraceLine("Waiting for next moves...", DebugAndTraceHelper.StatusStripChannelId);
                    var nextMoves = GetNextMoves(prevMoves);
                    RecordMoves(nextMoves);

                    DebugAndTraceHelper.WriteTraceLine("**** moves ****", DebugAndTraceHelper.ManagerChannelId);
                    foreach (Move nextMove in nextMoves)
                    {
                        DebugAndTraceHelper.WriteTraceLine(nextMove.Role + " makes move " + nextMove.TheMove, DebugAndTraceHelper.ManagerChannelId);
                    }

                    // ToDo:
                    DebugAndTraceHelper.WriteTraceLine("Checking for game termination...", DebugAndTraceHelper.StatusStripChannelId);

                    TheGeneralGame.ApplyMoves(nextMoves);
                    if (TheGeneralGame.FindTerminal(out satisfiedTerminalClauses))
                    {
                        gameHasTerminated = true;
                        DebugAndTraceHelper.WriteTraceLine(
                            String.Format("******** Game Ended for reason(s) {0} ********",
                                          String.Join(", ", satisfiedTerminalClauses)), DebugAndTraceHelper.ManagerChannelId);
                        terminalMove = nextMoves.Where(n => !n.IsNoop()).FirstOrDefault();
                    }

                    var stateAsXML = TheGeneralGame.GetStateAsCompleteXML();
                    DebugAndTraceHelper.WriteTraceLine(stateAsXML, DebugAndTraceHelper.StateChannelId);

                    prevMoves = nextMoves;

                    // serialize the history information
                    TurnRecord thisTurnRecord = new TurnRecord();
                    thisTurnRecord.Turn = TheGeneralGame.CurrentTurn;
                    thisTurnRecord.GameState.GameStateAsXML      = stateAsXML;
                    thisTurnRecord.GameState.GameStateFromProlog =
                        TheGeneralGame.PrologEngine.ListAll(sortAlphabetically: false).Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries).ToList();
                    thisTurnRecord.Moves = nextMoves;
                    //thisTurnRecord.GameState.GameStateAsHTML = ieWebBrowserListener == null ? "" : ieWebBrowserListener.ieWebBrowser.DocumentText;
                    thisTurnRecord.IsTerminalState = gameHasTerminated;
                    TurnRecords.Add(thisTurnRecord);
                    using (FileStream s = File.Create(historyFileName))
                    {
                        formatter.Serialize(s, TurnRecords);
                    }

                    if (gameHasTerminated)
                    {
                        DebugAndTraceHelper.WriteTraceLine("Game has ended", DebugAndTraceHelper.StatusStripChannelId);
                    }
                    else
                    {
                        if (StartNextMoveEvent != null && (!AllowFreeRunningOfTurnsWithNoPlayerMoves || nextMoves.Where(n => !n.IsTheRandomRole() && !n.IsNoop()).Any()))
                        {
                            DebugAndTraceHelper.WriteTraceLine("Please click next turn button to go to next turn...", DebugAndTraceHelper.StatusStripChannelId);
                            StartNextMoveEvent.WaitOne();
                        }
                        else
                        {
                            if (MilliSecondsBetweenFreeRunningMoves >= 0)
                            {
                                if (AllowFreeRunningOfTurnsWithNoPlayerMoves && !nextMoves.Where(n => !n.IsTheRandomRole() && !n.IsNoop()).Any())
                                {
                                    Thread.Sleep(MilliSecondsBetweenFreeRunningMoves / 4);
                                }
                                else
                                {
                                    Thread.Sleep(MilliSecondsBetweenFreeRunningMoves);
                                }
                            }
                        }
                    }
                }

                var scores = TheGeneralGame.FindScores();
                DebugAndTraceHelper.WriteTraceLine("**** scores ****", DebugAndTraceHelper.ManagerChannelId);
                foreach (Score score in scores)
                {
                    DebugAndTraceHelper.WriteTraceLine(score, DebugAndTraceHelper.ManagerChannelId);
                }

                StopAllPlayers(terminalMove);

                return(true);
            }
            catch (Exception ex)
            {
                throw;
            }
        }
        public bool PlayFromHistoryFile(string filePath)
        {
            int currentTurnIndex = 0;
            int previousTurnIndex;

            IFormatter formatter = new BinaryFormatter();

            using (FileStream s = File.OpenRead(filePath))
            {
                TurnRecords = (List <TurnRecord>)formatter.Deserialize(s);
            }

            bool?goForward = null;

            while (true)
            {
                if (goForward != null)
                {
                    if (goForward.Value)
                    {
                        foreach (Move move in TurnRecords[currentTurnIndex].Moves)
                        {
                            // output the moves that got us to this new state
                            DebugAndTraceHelper.WriteTraceLine(move.Role + " makes move " + move.TheMove, DebugAndTraceHelper.ManagerChannelId);
                        }
                    }
                    else
                    {
                        foreach (Move move in TurnRecords[currentTurnIndex + 1].Moves)
                        {
                            // output the moves that we are undoing to get to this state
                            DebugAndTraceHelper.WriteTraceLine(move.Role + " makes move " + move.TheMove, DebugAndTraceHelper.ManagerChannelId);
                        }
                    }
                }

                DebugAndTraceHelper.WriteTraceLine(TurnRecords[currentTurnIndex].GameState.GameStateAsXML, DebugAndTraceHelper.StateChannelId);

                if (StartNextMoveEvent != null)
                {
                    DebugAndTraceHelper.WriteTraceLine("Please click prev/next turn button to go to prev/next turn...", DebugAndTraceHelper.StatusStripChannelId);

                    goForward = null;
                    while (goForward == null)
                    {
                        if (StartNextMoveEvent.WaitOne(5))
                        {
                            goForward = true;
                        }
                        else if (PrevMoveEvent.WaitOne(5))
                        {
                            goForward = false;
                        }
                    }
                }
                else
                {
                    if (MilliSecondsBetweenFreeRunningMoves > 0)
                    {
                        Thread.Sleep(MilliSecondsBetweenFreeRunningMoves);
                    }

                    goForward = true;
                }

                previousTurnIndex = currentTurnIndex;
                if (goForward.Value)
                {
                    currentTurnIndex = Math.Min(currentTurnIndex + 1, TurnRecords.Max(n => n.Turn));
                }
                else
                {
                    currentTurnIndex = Math.Max(currentTurnIndex - 1, 0);
                }

                if (currentTurnIndex != previousTurnIndex)
                {
                    TheGeneralGame.PrologEngine.Reset();
                    foreach (string gameStateLine in TurnRecords[currentTurnIndex].GameState.GameStateFromProlog)
                    {
                        var foo = PrologEngine.CleanUpExistingPrologClauseForAsserting(gameStateLine);
                        TheGeneralGame.PrologEngine.Assert(PrologEngine.CleanUpExistingPrologClauseForAsserting(gameStateLine));
                    }
                }
            }

            return(true);
        }