public void CopyFrom(STPiece piece) { this.mShape = piece.mShape; this.mX = piece.mX; this.mY = piece.mY; this.mOrientation = piece.mOrientation; }
public void Rotate() { // only rotate if currently valid if (false == this.IsValid()) { return; } // First, retrieve maximum non-redundant orientation values int totalOrientations = 0; totalOrientations = STPiece.GetMaximumOrientationsOfShape(this.mShape); if (0 == totalOrientations) { return; } // Add one to current orientation value int newOrientation = (this.mOrientation + 1); // Force newOrientation to range 1..totalOrientations newOrientation = 1 + ((((newOrientation - 1) % totalOrientations) + totalOrientations) % totalOrientations); this.mOrientation = newOrientation; }
public void CommitPieceToBoard ( STPiece piece ) { if (null == this.mCells) { return; } if (false == piece.IsValid( )) { return; } // Fast check: If piece origin lies outside board, adding is not acceptable. if (piece.GetX( ) < 1) { return; } if (piece.GetY( ) < 1) { return; } if (piece.GetX( ) > this.GetWidth( )) { return; } if (piece.GetY( ) > this.GetHeight( )) { return; } // Consider the absolute position of all points of the piece, and set the // corresponding cells on the board. int boardX = 0; int boardY = 0; int totalCells = 0; totalCells = piece.GetTotalCells( ); int cellIndex = 0; for (cellIndex = 1; cellIndex <= totalCells; cellIndex++) { piece.GetTranslatedCellXY(cellIndex, ref boardX, ref boardY); // Fill in cell on the board. // (Note: board will silently discard cells with invalid (x,y).) this.SetCell(boardX, boardY, piece.GetByteCodeValue()); } }
public static bool GetCellOffsetXYOccupiedForShape ( STPieceShape shape, // O,I,S,Z,L,J,T; None int orientation, // 1,2,3,4; 0 == none int x, int y ) { if (STPieceShape.None == shape) { return(false); } // force orientation to range 1..totalOrientations int totalOrientations = 0; totalOrientations = STPiece.GetMaximumOrientationsOfShape(shape); if (0 == totalOrientations) { return(false); } orientation = 1 + ((((orientation - 1) % totalOrientations) + totalOrientations) % totalOrientations); // Loop through all cells and test against supplied cell. int totalCells = 0; totalCells = STPiece.GetTotalCellsForShape(shape); int cellIndex = 0; for (cellIndex = 1; cellIndex <= totalCells; cellIndex++) { int cellX = 0; int cellY = 0; STPiece.GetCellOffsetXYForShape(shape, orientation, cellIndex, ref cellX, ref cellY); if ((x == cellX) && (y == cellY)) { return(true); } } return(false); }
public void SetOrientation(int orientation) { int totalOrientations = 0; totalOrientations = STPiece.GetMaximumOrientationsOfShape(this.mShape); if (0 == totalOrientations) { this.mOrientation = 0; return; } orientation = 1 + ((((orientation - 1) % totalOrientations) + totalOrientations) % totalOrientations); this.mOrientation = orientation; }
public int GetOrientation() { int totalOrientations = 0; totalOrientations = STPiece.GetMaximumOrientationsOfShape(this.mShape); if (0 == totalOrientations) { this.mOrientation = 0; return(0); } this.mOrientation = 1 + ((((this.mOrientation - 1) % totalOrientations) + totalOrientations) % totalOrientations); return(this.mOrientation); }
// WARNING: The following method will unconditionally add the piece to // the board, even if putting the piece down at the starting location // (let alone dropping) is not acceptable (i.e., overlaps occupied cells). public void FullDropAndCommitPieceToBoard ( STPiece piece ) { if (null == this.mCells) { return; } if (false == piece.IsValid( )) { return; } // Drop piece as far as it will go. A drop of zero distance is possible. this.DropPieceAsFarAsPossibleButDoNotModifyBoard(piece); // Commit the translated piece to the board this.CommitPieceToBoard(piece); }
public void GetTranslatedCellXY ( int cellIndex, // 1,2,3,4; 0 == none ref int x, ref int y ) { x = 0; y = 0; if (cellIndex < 1) { return; } if (cellIndex > 4) { return; } int cellX = 0; int cellY = 0; STPiece.GetCellOffsetXYForShape(this.mShape, this.mOrientation, cellIndex, ref cellX, ref cellY); x = this.mX + cellX; y = this.mY + cellY; }
public void DetermineAccessibleTranslationsForPieceOrientation ( STPiece piece, ref bool movePossible, // false == no moves possible ref int minDeltaX, // displacement to left-most limit ref int maxDeltaX // displacement to right-most limit ) { movePossible = false; // false == no moves possible minDeltaX = 0; // displacement to left-most limit maxDeltaX = 0; // displacement to right-most limit if (null == this.mCells) { return; } if (false == piece.IsValid()) { return; } // Get dimensions of board int width = 0; width = this.GetWidth(); // int height = 0; // height = this.GetHeight(); STPiece tempPiece = new STPiece(); bool moveAcceptable = false; int trialTranslationDelta = 0; // Check if we can move at all. moveAcceptable = this.DetermineIfPieceIsWithinBoardAndDoesNotOverlapOccupiedCells(piece); if (true == moveAcceptable) { movePossible = true; } else { return; } // Scan from center to left to find left limit. bool stillAcceptable = true; for ( trialTranslationDelta = 0; ((trialTranslationDelta >= (-(width))) && (true == stillAcceptable)); trialTranslationDelta-- ) { // Copy piece to temp and translate tempPiece.CopyFrom(piece); tempPiece.Translate(trialTranslationDelta, 0); moveAcceptable = this.DetermineIfPieceIsWithinBoardAndDoesNotOverlapOccupiedCells(tempPiece); if (true == moveAcceptable) { minDeltaX = trialTranslationDelta; } else { stillAcceptable = false; } } // Scan from center to right to find right limit. stillAcceptable = true; for ( trialTranslationDelta = 0; ((trialTranslationDelta <= width) && (true == stillAcceptable)); trialTranslationDelta++ ) { // Copy piece to temp and translate tempPiece.CopyFrom(piece); tempPiece.Translate(trialTranslationDelta, 0); moveAcceptable = this.DetermineIfPieceIsWithinBoardAndDoesNotOverlapOccupiedCells(tempPiece); if (true == moveAcceptable) { maxDeltaX = trialTranslationDelta; } else { stillAcceptable = false; } } }
public bool DetermineIfPieceIsWithinBoardAndDoesNotOverlapOccupiedCells ( STPiece piece ) { if (null == this.mCells) { return(false); } if (false == piece.IsValid()) { return(false); } // Fast check: If piece origin lies outside board, goal is not acceptable. if (piece.GetX() < 1) { return(false); } if (piece.GetY() < 1) { return(false); } if (piece.GetX() > this.GetWidth()) { return(false); } if (piece.GetY() > this.GetHeight()) { return(false); } // Consider the board position of all cells of the piece. // If any of the piece cells lie outside the board, then the goal // is not acceptable. // If any of the piece cells coincide with an occupied cell of the board, // then the goal is not acceptable. int totalCells = 0; totalCells = piece.GetTotalCells( ); int cellIndex = 0; for (cellIndex = 1; cellIndex <= totalCells; cellIndex++) { int boardX = 0; int boardY = 0; piece.GetTranslatedCellXY(cellIndex, ref boardX, ref boardY); // board-relative cell must be in the board area if (boardX < 1) { return(false); } if (boardX > this.GetWidth( )) { return(false); } if (boardY < 1) { return(false); } if (boardY > this.GetHeight( )) { return(false); } // board-relative cell cannot overlap an occupied cell of the board. if ((byte)0 != this.GetCell(boardX, boardY)) { return(false); } } // If we made it to this point, the goal is acceptable. return(true); }
// The following counts the number of cells (0..4) of a piece that would // be eliminated by dropping the piece. public int CountPieceCellsEliminated ( STPiece piece ) { if (null == this.mCells) { return(0); } if (false == piece.IsValid( )) { return(0); } // Copy piece and board so that this measurement is not destructive. STBoard copyOfBoard = new STBoard(); copyOfBoard.CopyFrom(this); STPiece copyOfPiece = new STPiece(); copyOfPiece.CopyFrom(piece); // Drop copy of piece on to the copy of the board copyOfBoard.FullDropAndCommitPieceToBoard(copyOfPiece); // Scan rows. For each full row, check all board Y values for the // piece. If any board Y of the piece matches the full row Y, // increment the total eliminated cells. int pieceCellsEliminated = 0; int width = 0; int height = 0; width = copyOfBoard.GetWidth( ); height = copyOfBoard.GetHeight( ); int y = 0; for (y = 1; y <= height; y++) { bool fullRow = false; fullRow = true; // hypothesis int x = 0; for (x = 1; ((x <= width) && (true == fullRow)); x++) { byte cellValue = (byte)0; cellValue = copyOfBoard.GetCell(x, y); if ((byte)0 == cellValue) { fullRow = false; } } if (true == fullRow) { // Find any matching board-relative Y values in dropped copy of piece. int totalCells = 0; totalCells = piece.GetTotalCells( ); int cellIndex = 0; for (cellIndex = 1; cellIndex <= totalCells; cellIndex++) { int boardX = 0; int boardY = 0; copyOfPiece.GetTranslatedCellXY(cellIndex, ref boardX, ref boardY); if (boardY == y) { pieceCellsEliminated++; // Moohahahaaa! } } } } return(pieceCellsEliminated); }
public void DropPieceAsFarAsPossibleButDoNotModifyBoard ( STPiece piece ) { if (null == this.mCells) { return; } if (false == piece.IsValid( )) { return; } // Special case: cannot place piece at starting location. bool goalAcceptable = false; goalAcceptable = this.DetermineIfPieceIsWithinBoardAndDoesNotOverlapOccupiedCells(piece); if (false == goalAcceptable) { // cannot drop piece at all return; } // Try successively larger drop distances, up to the point of failure. // The last successful drop distance becomes our drop distance. int boardHeight = 0; int lastSuccessfulDropDistance = 0; bool firstFailureEncountered = false; int trialDropDistance = 0; boardHeight = this.GetHeight(); STPiece tempPiece = new STPiece(); tempPiece.CopyFrom(piece); for ( trialDropDistance = 0; ((false == firstFailureEncountered) && (trialDropDistance <= boardHeight)); trialDropDistance++ ) { // Set temporary piece to new trial Y tempPiece.SetY(piece.GetY( ) - trialDropDistance); goalAcceptable = this.DetermineIfPieceIsWithinBoardAndDoesNotOverlapOccupiedCells(tempPiece); if (false == goalAcceptable) { // We failed to drop this far. Stop drop search. firstFailureEncountered = true; } else { lastSuccessfulDropDistance = trialDropDistance; } } // Simply update the piece Y value. piece.SetY(piece.GetY( ) - lastSuccessfulDropDistance); }
public static void GetCellOffsetXYForShape ( STPieceShape shape, // O,I,S,Z,L,J,T; None int orientation, // 1,2,3,4; 0 == none int cellIndex, // 1,2,3,4; 0 == none ref int x, ref int y ) { x = 0; y = 0; // force cellIndex to range 1..4 cellIndex = 1 + (((cellIndex - 1) % 4 + 4) % 4); // force orientation to range 1..totalOrientations int totalOrientations = 0; totalOrientations = STPiece.GetMaximumOrientationsOfShape(shape); if (0 == totalOrientations) { return; } orientation = 1 + ((((orientation - 1) % totalOrientations) + totalOrientations) % totalOrientations); if (STPieceShape.None == shape) { return; } if (STPieceShape.O == shape) { // orientation 1,2,3,4 : (-1, -1), ( 0, -1), ( 0, 0), (-1, 0) if (1 == cellIndex) { x = -1; y = -1; } else if (2 == cellIndex) { x = 0; y = -1; } else if (3 == cellIndex) { x = 0; y = 0; } else if (4 == cellIndex) { x = -1; y = 0; } } if (STPieceShape.I == shape) { // orientation 1,3: (-2, 0), (-1, 0), ( 0, 0), ( 1, 0) // orientation 2,4: ( 0, -2), ( 0, -1), ( 0, 0), ( 0, 1) if ((1 == orientation) || (3 == orientation)) { if (1 == cellIndex) { x = -2; y = 0; } else if (2 == cellIndex) { x = -1; y = 0; } else if (3 == cellIndex) { x = 0; y = 0; } else if (4 == cellIndex) { x = 1; y = 0; } } else { if (1 == cellIndex) { x = 0; y = -2; } else if (2 == cellIndex) { x = 0; y = -1; } else if (3 == cellIndex) { x = 0; y = 0; } else if (4 == cellIndex) { x = 0; y = 1; } } } if (STPieceShape.S == shape) { // orientation 1,3: (-1, -1), ( 0, -1), ( 0, 0), ( 1, 0) // orientation 2,4: ( 1, -1), ( 0, 0), ( 1, 0), ( 0, 1) if ((1 == orientation) || (3 == orientation)) { if (1 == cellIndex) { x = -1; y = -1; } else if (2 == cellIndex) { x = 0; y = -1; } else if (3 == cellIndex) { x = 0; y = 0; } else if (4 == cellIndex) { x = 1; y = 0; } } else { if (1 == cellIndex) { x = 1; y = -1; } else if (2 == cellIndex) { x = 0; y = 0; } else if (3 == cellIndex) { x = 1; y = 0; } else if (4 == cellIndex) { x = 0; y = 1; } } } if (STPieceShape.Z == shape) { // orientation 1,3: ( 0, -1), ( 1, -1), (-1, 0), ( 0, 0) // orientation 2,4: ( 0, -1), ( 0, 0), ( 1, 0), ( 1, 1) if ((1 == orientation) || (3 == orientation)) { if (1 == cellIndex) { x = 0; y = -1; } else if (2 == cellIndex) { x = 1; y = -1; } else if (3 == cellIndex) { x = -1; y = 0; } else if (4 == cellIndex) { x = 0; y = 0; } } else { if (1 == cellIndex) { x = 0; y = -1; } else if (2 == cellIndex) { x = 0; y = 0; } else if (3 == cellIndex) { x = 1; y = 0; } else if (4 == cellIndex) { x = 1; y = 1; } } } if (STPieceShape.L == shape) { // orientation 1: (-1, -1), (-1, 0), ( 0, 0), ( 1, 0) // orientation 2: ( 0, -1), ( 1, -1), ( 0, 0), ( 0, 1) // orientation 3: (-1, 0), ( 0, 0), ( 1, 0), ( 1, 1) // orientation 4: ( 0, -1), ( 0, 0), (-1, 1), ( 0, 1) if (1 == orientation) { if (1 == cellIndex) { x = -1; y = -1; } else if (2 == cellIndex) { x = -1; y = 0; } else if (3 == cellIndex) { x = 0; y = 0; } else if (4 == cellIndex) { x = 1; y = 0; } } else if (2 == orientation) { if (1 == cellIndex) { x = 0; y = -1; } else if (2 == cellIndex) { x = 1; y = -1; } else if (3 == cellIndex) { x = 0; y = 0; } else if (4 == cellIndex) { x = 0; y = 1; } } else if (3 == orientation) { if (1 == cellIndex) { x = -1; y = 0; } else if (2 == cellIndex) { x = 0; y = 0; } else if (3 == cellIndex) { x = 1; y = 0; } else if (4 == cellIndex) { x = 1; y = 1; } } else { if (1 == cellIndex) { x = 0; y = -1; } else if (2 == cellIndex) { x = 0; y = 0; } else if (3 == cellIndex) { x = -1; y = 1; } else if (4 == cellIndex) { x = 0; y = 1; } } } if (STPieceShape.J == shape) { // orientation 1: ( 1, -1), (-1, 0), ( 0, 0), ( 1, 0) // orientation 2: ( 0, -1), ( 0, 0), ( 0, 1), ( 1, 1) // orientation 3: (-1, 0), ( 0, 0), ( 1, 0), (-1, 1) // orientation 4: (-1, -1), ( 0, -1), ( 0, 0), ( 0, 1) if (1 == orientation) { if (1 == cellIndex) { x = 1; y = -1; } else if (2 == cellIndex) { x = -1; y = 0; } else if (3 == cellIndex) { x = 0; y = 0; } else if (4 == cellIndex) { x = 1; y = 0; } } else if (2 == orientation) { if (1 == cellIndex) { x = 0; y = -1; } else if (2 == cellIndex) { x = 0; y = 0; } else if (3 == cellIndex) { x = 0; y = 1; } else if (4 == cellIndex) { x = 1; y = 1; } } else if (3 == orientation) { if (1 == cellIndex) { x = -1; y = 0; } else if (2 == cellIndex) { x = 0; y = 0; } else if (3 == cellIndex) { x = 1; y = 0; } else if (4 == cellIndex) { x = -1; y = 1; } } else { if (1 == cellIndex) { x = -1; y = -1; } else if (2 == cellIndex) { x = 0; y = -1; } else if (3 == cellIndex) { x = 0; y = 0; } else if (4 == cellIndex) { x = 0; y = 1; } } } if (STPieceShape.T == shape) { // orientation 1: ( 0, -1), (-1, 0), ( 0, 0), ( 1, 0) // orientation 2: ( 0, -1), ( 0, 0), ( 1, 0), ( 0, 1) // orientation 3: (-1, 0), ( 0, 0), ( 1, 0), ( 0, 1) // orientation 4: ( 0, -1), (-1, 0), ( 0, 0), ( 0, 1) if (1 == orientation) { if (1 == cellIndex) { x = 0; y = -1; } else if (2 == cellIndex) { x = -1; y = 0; } else if (3 == cellIndex) { x = 0; y = 0; } else if (4 == cellIndex) { x = 1; y = 0; } } else if (2 == orientation) { if (1 == cellIndex) { x = 0; y = -1; } else if (2 == cellIndex) { x = 0; y = 0; } else if (3 == cellIndex) { x = 1; y = 0; } else if (4 == cellIndex) { x = 0; y = 1; } } else if (3 == orientation) { if (1 == cellIndex) { x = -1; y = 0; } else if (2 == cellIndex) { x = 0; y = 0; } else if (3 == cellIndex) { x = 1; y = 0; } else if (4 == cellIndex) { x = 0; y = 1; } } else { if (1 == cellIndex) { x = 0; y = -1; } else if (2 == cellIndex) { x = -1; y = 0; } else if (3 == cellIndex) { x = 0; y = 0; } else if (4 == cellIndex) { x = 0; y = 1; } } } }
public STGameState( ) { // Core Game State // Board and Piece mSTBoardCurrent = new STBoard(); mSTPieceCurrent = new STPiece(); // Core Game State Variables mGameOver = false; mIterationCountdownSeconds = 0.0; mCurrentPiecePointValue = 0; // starts at 24+(3*(level-1)) mCompletedRows = 0; // Piece Sequence Generator mSTPieceSequence = new STPieceSequence(); // User Options mPaused = false; mShowNextPiece = false; mAI = false; mSpawnFromVideoCapture = false; mOutputToRS232 = false; mAutoRestart = false; mAutoWriteFile = false; // Game Speed Adjustment // -2, -3, -4,... : Slow Mode (delay proportional to index) // -1 : Normal, Clipped at 0.20 sec/row // 0 : Normal // +1 : Fast Mode (still render bound) // +2 : Very Fast Mode (still render bound) // +3, +4, +5,... : Multiple moves per rendered frame mGameSpeedAdjustment = 0; mShadowMode = false; mHintMode = false; mMonochromeColorMode = false; // Statistics for User Consideration Only // Updated at piece spawning or row completion mPieceHistogram = new long[8]; // Count of each piece type mHeightHistogram = new long[202]; // Height after each landing mTotalElapsedTimeSeconds = 0.0; mScore = 0; // Only updated when game ends mHistoricHighScore = 0; mHistoricHighRows = 0; mHistoricHighPieces = 0; mHistoricCumulativeRows = 0; // Used to get average: rows / games mHistoricTotalGames = 0; mHistoricRows = new long[20]; // Past games [0]==most recent // Cached Derived or Copied Values // Next Piece (Not always used or available; Only 'kind' aspect is relevant) mSTPieceNext = new STPiece(); // Best Move (determined by relevant AI upon piece spawning) mSTPieceBestMove = new STPiece(); // state of animation of a an AI-executed move mAnimateAIMovesEnable = true; mAnimateAIMovesStartingY = 0; mAnimateAIMovesFinalSafeY = 0; mAnimateAITotalInitialCommands = 0; mAnimateAICommandsExecuted = 0; mAnimateAICommandsPerRow = 0; mAnimateAIMovesPendingRotation = 0; mAnimateAIMovesPendingTranslation = 0; // RUN-TIME STATE INFORMATION (DO NOT STORE IN A FILE) // video capture related mPreviousClassification = (-1); mSelectionState = 0; mSelectionX1 = 0; mSelectionY1 = 0; mSelectionX2 = 0; mSelectionY2 = 0; mCalibrationModeFlag = false; // false == OFF mCalibrationModeShapeCode = 0; // 1..7 shape // file list mFirstItem = 0; mRelativeItem = 0; mShowFileList = false; mLoadFlag = false; // miscellaneous mRenderFrameNumber = 0; mShowInstructionPage = 0; mShowConsole = false; mReportedFrameRate = 0.0f; }