public static bool WriteGameStateToFile ( String filePath, // e.g., C:\ or C:\foo String fileName, // e.g., tetris_state_YYYYMMDD_HHMMSSMMM.txt STGameState gameState ) { if (true == filePath.EndsWith("\\")) { filePath = filePath.Substring(0, (filePath.Length - 1)); } String filePathAndName = ""; filePathAndName = filePath + "\\" + fileName; STFileWriter file = new STFileWriter( ); bool successfullyOpenedFile = false; successfullyOpenedFile = file.Open(filePathAndName); if (false == successfullyOpenedFile) { return(false); } // Simply print out game state information to the text file. // The order of fields doesn't matter. Fields can be added // or removed. It is the consumer's responsibility to // acquire any fields and compensate for "missing" fields. // NOTE: Not all of these fields are intended to be restored // on loading. Many are DERIVED values, or are session-dependent, // or should be cleared upon loading to give the user the // chance to alter settings. For example, don't restore the // pause/unpaused state, or the video capture state. file.WriteText("fileName \"" + fileName + "\"\r\n"); file.WriteText("localDateAndTime \"" + GetDateStringYYYY_MMM_DD_HH_MM_SS_MMM( ) + "\"\r\n"); file.WriteText("standardTetrisVersion \"" + STGame.GetApplicationName( ) + "\"\r\n"); file.WriteText("\r\n"); file.WriteText("boardWidth " + gameState.mSTBoardCurrent.GetWidth( ) + "\r\n"); file.WriteText("boardHeight " + gameState.mSTBoardCurrent.GetHeight( ) + "\r\n"); file.WriteText("boardCurrent\r\n"); int width = 0; int height = 0; width = gameState.mSTBoardCurrent.GetWidth( ); height = gameState.mSTBoardCurrent.GetHeight( ); int x = 0; int y = 0; for (y = height; y >= 1; y--) // top-down { for (x = 1; x <= width; x++) { int cellShapeCode = 0; cellShapeCode = (int)gameState.mSTBoardCurrent.GetCell(x, y); file.WriteText(" " + String.Format("{0:d}", cellShapeCode)); } file.WriteText("\r\n"); } file.WriteText("\r\n"); file.WriteText("pieceCurrent\r\n"); file.WriteText("shape " + (int)gameState.mSTPieceCurrent.GetByteCodeValue( ) + "\r\n"); file.WriteText("x " + gameState.mSTPieceCurrent.GetX( ) + "\r\n"); file.WriteText("y " + gameState.mSTPieceCurrent.GetY( ) + "\r\n"); file.WriteText("orientation " + gameState.mSTPieceCurrent.GetOrientation( ) + "\r\n"); file.WriteText("\r\n"); int intValue = 0; if (true == gameState.mGameOver) { intValue = 1; } file.WriteText("gameOver " + intValue + "\r\n"); file.WriteText("iterationCountdownSeconds " + gameState.mIterationCountdownSeconds + "\r\n"); file.WriteText("currentPiecePointValue " + gameState.mCurrentPiecePointValue + "\r\n"); file.WriteText("completedRows " + gameState.mCompletedRows + "\r\n"); file.WriteText("\r\n"); file.WriteText("pieceSelectionSource " + (int)gameState.mSTPieceSequence.DirectGetPieceSelectionSource( ) + "\r\n"); file.WriteText("pieceSelectionShapeCurrent " + (int)gameState.mSTPieceSequence.DirectGetCurrentPieceShape( ) + "\r\n"); file.WriteText("pieceSelectionShapeNext " + (int)gameState.mSTPieceSequence.DirectGetNextPieceShape( ) + "\r\n"); file.WriteText("cachedRandomSeedUsedMostRecentlyToInitializeRandomGenerator " + gameState.mSTPieceSequence.DirectGetSeedUsedMostRecentlyToInitializeRandomNumberGenerator( ) + "\r\n"); file.WriteText("currentInternalRandomNumberGeneratorStateForPieceSequence " + gameState.mSTPieceSequence.DirectGetCurrentRandomNumberGeneratorInternalStateValue( ) + "\r\n"); int alternateSZState = 0; if (true == gameState.mSTPieceSequence.DirectGetAlternateSZState( )) { alternateSZState = 1; } file.WriteText("alternatingSZState " + alternateSZState + "\r\n"); file.WriteText("pieceSequenceTotalQueueElements " + gameState.mSTPieceSequence.DirectGetTotalQueueElements( ) + "\r\n"); file.WriteText("pieceSequenceQueueElements " + "\r\n"); int totalQueueElements = 0; totalQueueElements = gameState.mSTPieceSequence.DirectGetTotalQueueElements( ); int indexQueueElement = 0; for (indexQueueElement = 0; indexQueueElement < totalQueueElements; indexQueueElement++) { int queueElementValue = 0; queueElementValue = gameState.mSTPieceSequence.DirectGetQueueElementByIndex(indexQueueElement); file.WriteText(" " + String.Format("{0:d}", queueElementValue)); if (31 == (indexQueueElement % 32)) { file.WriteText("\r\n"); } } file.WriteText("\r\n"); file.WriteText("\r\n"); // User options intValue = 0; if (true == gameState.mPaused) { intValue = 1; } file.WriteText("paused " + intValue + "\r\n"); intValue = 0; if (true == gameState.mShowNextPiece) { intValue = 1; } file.WriteText("showNextPiece " + intValue + "\r\n"); intValue = 0; if (true == gameState.mAI) { intValue = 1; } file.WriteText("aiActive " + intValue + "\r\n"); intValue = 0; if (true == gameState.mSpawnFromVideoCapture) { intValue = 1; } file.WriteText("spawnFromVideoCapture " + intValue + "\r\n"); intValue = 0; if (true == gameState.mOutputToRS232) { intValue = 1; } file.WriteText("outputToRS232 " + intValue + "\r\n"); intValue = 0; if (true == gameState.mAutoRestart) { intValue = 1; } file.WriteText("autoRestart " + intValue + "\r\n"); intValue = 0; if (true == gameState.mAutoWriteFile) { intValue = 1; } file.WriteText("autoWriteFile " + intValue + "\r\n"); file.WriteText("gameSpeedAdjustment " + gameState.mGameSpeedAdjustment + "\r\n"); intValue = 0; if (true == gameState.mShadowMode) { intValue = 1; } file.WriteText("shadowMode " + intValue + "\r\n"); intValue = 0; if (true == gameState.mHintMode) { intValue = 1; } file.WriteText("hintMode " + intValue + "\r\n"); intValue = 0; if (true == gameState.mMonochromeColorMode) { intValue = 1; } file.WriteText("monochromeColorMode " + intValue + "\r\n"); // Currently-selected AI // (be sure to eliminate the double-quotes around the name when reading back in) file.WriteText("currentStrategyName " + "\"" + STStrategyManager.GetCurrentStrategyName( ) + "\"" + "\r\n"); // Statistics for User Consideration Only file.WriteText("\r\n"); file.WriteText("pieceHistogramLength " + (int)gameState.mPieceHistogram.Length + "\r\n"); file.WriteText("pieceHistogram " + "\r\n"); int i = 0; int n = 0; n = gameState.mPieceHistogram.Length; for (i = 0; i < n; i++) { file.WriteText(gameState.mPieceHistogram[i] + "\r\n"); } file.WriteText("\r\n"); file.WriteText("\r\n"); // Height histogram // (find highest index with a non-zero count, and only show indices // up to that index on their own lines, with all subsequent zero // values condensed with 32 such values on a single line) file.WriteText("heightHistogramLength " + (int)gameState.mHeightHistogram.Length + "\r\n"); file.WriteText("heightHistogram " + "\r\n"); int maxIndexWithNonZeroCount = (-1); n = gameState.mHeightHistogram.Length; for (i = 0; i < n; i++) { if (gameState.mHeightHistogram[i] > 0) { maxIndexWithNonZeroCount = i; } } for (i = 0; i <= maxIndexWithNonZeroCount; i++) { file.WriteText(gameState.mHeightHistogram[i] + "\r\n"); } int k = 0; for (i = (maxIndexWithNonZeroCount + 1); i < n; i++) { file.WriteText(gameState.mHeightHistogram[i] + " "); k++; if (0 == (k % 32)) { file.WriteText("\r\n"); } } file.WriteText("\r\n"); file.WriteText("\r\n"); file.WriteText("totalElapsedTimeSeconds " + gameState.mTotalElapsedTimeSeconds + "\r\n"); file.WriteText("score " + gameState.mScore + "\r\n"); file.WriteText("historicHighScore " + gameState.mHistoricHighScore + "\r\n"); file.WriteText("historicHighRows " + gameState.mHistoricHighRows + "\r\n"); file.WriteText("historicHighPieces " + gameState.mHistoricHighPieces + "\r\n"); file.WriteText("historicCumulativeRows " + gameState.mHistoricCumulativeRows + "\r\n"); file.WriteText("historicTotalGames " + gameState.mHistoricTotalGames + "\r\n"); file.WriteText("\r\n"); file.WriteText("historicRowsLength " + (int)gameState.mHistoricRows.Length + "\r\n"); file.WriteText("historicRows " + "\r\n"); n = gameState.mHistoricRows.Length; for (i = 0; i < n; i++) { file.WriteText(gameState.mHistoricRows[i] + "\r\n"); } file.WriteText("\r\n"); file.WriteText("\r\n"); // Derived or copied values file.WriteText("pieceNext\r\n"); file.WriteText("shape " + (int)gameState.mSTPieceNext.GetByteCodeValue( ) + "\r\n"); file.WriteText("x " + gameState.mSTPieceNext.GetX( ) + "\r\n"); file.WriteText("y " + gameState.mSTPieceNext.GetY( ) + "\r\n"); file.WriteText("orientation " + gameState.mSTPieceNext.GetOrientation( ) + "\r\n"); file.WriteText("\r\n"); file.WriteText("pieceBestMove\r\n"); file.WriteText("shape " + (int)gameState.mSTPieceBestMove.GetByteCodeValue( ) + "\r\n"); file.WriteText("x " + gameState.mSTPieceBestMove.GetX( ) + "\r\n"); file.WriteText("y " + gameState.mSTPieceBestMove.GetY( ) + "\r\n"); file.WriteText("orientation " + gameState.mSTPieceBestMove.GetOrientation( ) + "\r\n"); file.WriteText("\r\n"); // state of animation of a an AI-executed move intValue = 0; if (true == gameState.mAnimateAIMovesEnable) { intValue = 1; } file.WriteText("animateAIMovesEnable " + intValue + "\r\n"); file.WriteText("animateAIMovesStartingY " + gameState.mAnimateAIMovesStartingY + "\r\n"); file.WriteText("animateAIMovesFinalSafeY " + gameState.mAnimateAIMovesFinalSafeY + "\r\n"); file.WriteText("animateAITotalInitialCommands " + gameState.mAnimateAITotalInitialCommands + "\r\n"); file.WriteText("animateAICommandsExecuted " + gameState.mAnimateAICommandsExecuted + "\r\n"); file.WriteText("animateAICommandsPerRow " + gameState.mAnimateAICommandsPerRow + "\r\n"); file.WriteText("animateAIMovesPendingRotation " + gameState.mAnimateAIMovesPendingRotation + "\r\n"); file.WriteText("animateAIMovesPendingTranslation " + gameState.mAnimateAIMovesPendingTranslation + "\r\n"); // Derived values // Scaled height histogram file.WriteText("\r\n"); file.WriteText("\r\n"); long sumOfCounts = 0; n = gameState.mHeightHistogram.Length; for (i = 0; i < n; i++) { sumOfCounts += gameState.mHeightHistogram[i]; } if (sumOfCounts > 0) { file.WriteText("scaledHistogramOfPileHeights " + "\r\n"); double fraction = 0.0; for (i = 0; i <= maxIndexWithNonZeroCount; i++) { fraction = ((double)gameState.mHeightHistogram[i] / (double)sumOfCounts); file.WriteText("" + fraction + "\r\n"); } } file.WriteText("\r\n"); file.WriteText("\r\n"); file.Close( ); return(true); }