// The following method selects the source to use for piece spawning. public void ClientSelectPieceSelectionSource ( STPieceSelectionSource pieceSelectionSource ) { this.mCachedSelectedPieceShapeCurrent = STPiece.STPieceShape.None; this.mCachedSelectedPieceShapeNext = STPiece.STPieceShape.None; switch (pieceSelectionSource) { case STPieceSelectionSource.Random: { this.mPieceSelectionSource = pieceSelectionSource; } break; case STPieceSelectionSource.AlternatingSAndZ: { this.mPieceSelectionSource = pieceSelectionSource; } break; case STPieceSelectionSource.Queue: { this.mPieceSelectionSource = pieceSelectionSource; } break; default: { this.mPieceSelectionSource = STPieceSelectionSource.Random; } break; } }
// WARNING: Moves requiring rotation must wait until piece has fallen by // at least one row. public override void GetBestMoveOncePerPiece ( STBoard board, STPiece piece, bool nextPieceFlag, // false == no next piece available or known STPiece.STPieceShape nextPieceShape, // None == no piece available or known ref int bestRotationDelta, // 0 or {0,1,2,3} ref int bestTranslationDelta // 0 or {...,-2,-1,0,1,2,...} ) { bestRotationDelta = 0; bestTranslationDelta = 0; // We are given the current board, and the current piece // configuration. Our goal is to evaluate various possible // moves and return the best move we explored. PrivateStrategy ( false, board, piece, ref bestRotationDelta, // 0 or {0,1,2,3} ref bestTranslationDelta // 0 or {...,-2,-1,0,1,2,...} ); }
public void ServerQueueSubmitPiece(STPiece.STPieceShape shape) { int pieceIndex = 0; pieceIndex = (int)STPiece.GetByteCodeValueOfShape(shape); this.mQueue.Add(pieceIndex); }
// The following method is called by the client (i.e., game engine) to // request an update of the current and next pieces. It is possible // that the next piece and possibly the current piece become UNAVAILABLE. // It is the client's responsibility to check for pieces to become // available in the future. // Sources of piece sequences that are external to this application, such as // video capture and network packets, are asynchronous and essentially // non-deterministic (i.e., algorithm and parameters are essentially unknown). // The client must wait for new pieces to become available. // In any case, the following method should be called whenever the client // has consumed the current piece. public void ClientRequestSelectionUpdate( ) { this.mCachedSelectedPieceShapeCurrent = STPiece.STPieceShape.None; this.mCachedSelectedPieceShapeNext = STPiece.STPieceShape.None; switch (this.mPieceSelectionSource) { case STPieceSelectionSource.Random: { this.PrivateAdvanceRandom( ); } break; case STPieceSelectionSource.AlternatingSAndZ: { this.PrivateAdvanceAlternatingSZ( ); } break; case STPieceSelectionSource.Queue: { this.PrivateAdvanceQueue( ); } break; default: { } break; } }
// UNUSED: //private int PrivateQueueGetItem ( ) //{ // if (this.mQueue.Count <= 0) // { // return (0); // } // int value = (this.mQueue[0]); // this.mQueue.RemoveAt( 0 ); // return (value); //} private void PrivateAdvanceQueue( ) { this.mCachedSelectedPieceShapeCurrent = STPiece.STPieceShape.None; this.mCachedSelectedPieceShapeNext = STPiece.STPieceShape.None; if (this.mQueue.Count <= 0) { return; } // We definitely have one shape in the queue int pieceShapeIndexCurrent = 0; pieceShapeIndexCurrent = this.PrivateQueuePeekItem( ); // Remove the shape from the queue this.mQueue.RemoveAt(0); // There might be another shape in the queue. We'll peek. int pieceShapeIndexNext = 0; pieceShapeIndexNext = this.PrivateQueuePeekItem( ); // Set current and next piece shapes this.mCachedSelectedPieceShapeCurrent = STPiece.GetShapeCorrespondingToByteCode((byte)pieceShapeIndexCurrent); this.mCachedSelectedPieceShapeNext = STPiece.GetShapeCorrespondingToByteCode((byte)pieceShapeIndexNext); }
// WARNING: When you get the "best" rotation and translation // from the following function, you must wait until the piece has // its origin at least as low as row 0 (zero) instead of its initial // row -1 (negative one) if any rotations (1,2,3) are required. // Perform all rotations, and then perform translations. This // avoids the problem of getting the piece jammed on the sides // of the board where rotation is impossible. *** // Also, the following strategy does not take advantage of the // possibility of using free-fall and future movements to // slide under overhangs and fill them in. public static void GetBestMoveOncePerPiece ( STBoard board, STPiece piece, bool nextPieceFlag, // false == no next piece available or known STPiece.STPieceShape nextPieceShape, // None == no piece available or known ref int bestRotationDelta, // 0 or {0,1,2,3} ref int bestTranslationDelta // 0 or {...,-2,-1,0,1,2,...} ) { bestRotationDelta = 0; bestTranslationDelta = 0; STStrategy strategy = null; strategy = GetCurrentStrategy(); if (null == strategy) { return; } strategy.GetBestMoveOncePerPiece ( board, piece, nextPieceFlag, // false == no next piece available or known nextPieceShape, // None == no piece available or known ref bestRotationDelta, // 0 or {0,1,2,3} ref bestTranslationDelta // 0 or {...,-2,-1,0,1,2,...} ); }
public virtual void GetBestMoveOncePerPiece ( STBoard board, STPiece piece, bool nextPieceFlag, // false == no next piece available or known STPiece.STPieceShape nextPieceShape, // None == no piece available or known ref int bestRotationDelta, // 0 or {0,1,2,3} ref int bestTranslationDelta // 0 or {...,-2,-1,0,1,2,...} ) { bestRotationDelta = 0; bestTranslationDelta = 0; }
private void PrivateAdvanceAlternatingSZ( ) { if (false == this.mAlternatingSZState) { this.mAlternatingSZState = true; this.mCachedSelectedPieceShapeCurrent = STPiece.STPieceShape.S; this.mCachedSelectedPieceShapeNext = STPiece.STPieceShape.Z; } else { this.mAlternatingSZState = false; this.mCachedSelectedPieceShapeCurrent = STPiece.STPieceShape.Z; this.mCachedSelectedPieceShapeNext = STPiece.STPieceShape.S; } }
private void PrivateAdvanceRandom( ) { int pieceShapeIndexCurrent = 0; pieceShapeIndexCurrent = this.mSTRandom.GetIntegerInRangeUsingCurrentState(1, 7); this.mSTRandom.Advance( ); int pieceShapeIndexNext = 0; pieceShapeIndexNext = this.mSTRandom.GetIntegerInRangeUsingCurrentState(1, 7); // Set current and next piece shapes this.mCachedSelectedPieceShapeCurrent = STPiece.GetShapeCorrespondingToByteCode((byte)pieceShapeIndexCurrent); this.mCachedSelectedPieceShapeNext = STPiece.GetShapeCorrespondingToByteCode((byte)pieceShapeIndexNext); }
// Call the following before each new game, using seed value that is // as random as possible. Calling this method with the same seed value // should start the deterministic generators in the same initial state. public void ClientRequestSelectionGeneratorReset ( long seedValue ) { // Cache seed value this.mCachedRandomSeedUsedMostRecentlyToInitializeRandomGenerator = seedValue; this.mSTRandom.SetState(seedValue); // Clear cached selections this.mCachedSelectedPieceShapeCurrent = STPiece.STPieceShape.None; this.mCachedSelectedPieceShapeNext = STPiece.STPieceShape.None; // FIFO : Simply clear the FIFO. this.mQueue.Clear( ); // S/Z alternating sequence : set phase this.mAlternatingSZState = false; if (0 != (seedValue % 2)) { this.mAlternatingSZState = true; } }
private double PrivateStrategyNextPiece ( STBoard board, STPiece piece, STPiece.STPieceShape nextPieceShape, // None == no piece available or known ref int bestRotationDelta, // 0 or {0,1,2,3} ref int bestTranslationDelta // 0 or {...,-2,-1,0,1,2,...} ) { if (false == piece.IsValid( )) { return(0.0); } int currentBestTranslationDelta = 0; int currentBestRotationDelta = 0; double currentBestMerit = (-1.0e20); int currentBestPriority = 0; int trialTranslationDelta = 0; int trialRotationDelta = 0; double trialMerit = 0.0; int trialPriority = 0; int maxOrientations = 0; bool moveAcceptable = false; int count = 0; STBoard tempBoard = new STBoard(); STPiece tempPiece = new STPiece(); maxOrientations = STPiece.GetMaximumOrientationsOfShape(piece.GetShape()); for ( trialRotationDelta = 0; trialRotationDelta < maxOrientations; trialRotationDelta++ ) { // Make temporary copy of piece, and rotate the copy. tempPiece.CopyFrom(piece); for (count = 0; count < trialRotationDelta; count++) { tempPiece.Rotate(); } // Determine the translation limits for this rotated piece. bool moveIsPossible = false; int minDeltaX = 0; int maxDeltaX = 0; board.DetermineAccessibleTranslationsForPieceOrientation ( tempPiece, ref moveIsPossible, // false==NONE POSSIBLE ref minDeltaX, // Left limit ref maxDeltaX // Right limit ); // Consider all allowed translations for the current rotation. if (true == moveIsPossible) { for ( trialTranslationDelta = minDeltaX; trialTranslationDelta <= maxDeltaX; trialTranslationDelta++ ) { // Evaluate this move // Copy piece to temp and rotate and translate tempPiece.CopyFrom(piece); for (count = 0; count < trialRotationDelta; count++) { tempPiece.Rotate(); } tempPiece.Translate(trialTranslationDelta, 0); moveAcceptable = board.DetermineIfPieceIsWithinBoardAndDoesNotOverlapOccupiedCells ( tempPiece ); if (true == moveAcceptable) { // Since the piece can be (not necessarily GET) at the goal // horizontal translation and orientation, it's worth trying // out a drop and evaluating the move. tempBoard.CopyFrom(board); tempBoard.FullDropAndCommitPieceToBoard(tempPiece); trialPriority = 0; // Okay, now do second move with "Next Piece" int nextPieceBestRotation = 0; // Dummy variable int nextPieceBestTranslation = 0; // Dummy variable STPiece nextPiece = new STPiece(); nextPiece.SetShape(nextPieceShape); nextPiece.SetX(tempBoard.GetPieceSpawnX()); nextPiece.SetY(tempBoard.GetPieceSpawnY() - 1); nextPiece.SetOrientation(1); trialMerit = PrivateStrategy ( true, // Not just a single ply; We are calling from a parent ply. tempBoard, nextPiece, ref nextPieceBestRotation, ref nextPieceBestTranslation ); // If this move is better than any move considered before, // or if this move is equally ranked but has a higher priority, // then update this to be our best move. if ( (trialMerit > currentBestMerit) || ((trialMerit == currentBestMerit) && (trialPriority > currentBestPriority)) ) { currentBestPriority = trialPriority; currentBestMerit = trialMerit; currentBestTranslationDelta = trialTranslationDelta; currentBestRotationDelta = trialRotationDelta; } } } } } // Commit to this move bestTranslationDelta = currentBestTranslationDelta; bestRotationDelta = currentBestRotationDelta; return(currentBestMerit); }
public void DirectSetNextPieceShape(STPiece.STPieceShape nextPieceShape) { this.mCachedSelectedPieceShapeNext = nextPieceShape; }
public void DirectSetCurrentPieceShape(STPiece.STPieceShape currentPieceShape) { this.mCachedSelectedPieceShapeCurrent = currentPieceShape; }