header
main about me projects resume code samples
#include "HexstaticBoard.h"
#include "PieceManager.h"
#include "SpriteManager.h"
#include "AEEStdLib.h"
#include "Types.h"


//******************************************************************
// CHexstaticBoard
//******************************************************************
CHexstaticBoard::CHexstaticBoard()
{
     Initialize();
}


//******************************************************************
// ~CHexstaticBoard
//******************************************************************
CHexstaticBoard::~CHexstaticBoard()
{
     Clear();
}


//******************************************************************
// operator new
//******************************************************************
void* CHexstaticBoard::operator new(size_t tdSize)
{
     CHexstaticBoard * pObj = (CHexstaticBoard*)MALLOC(tdSize);
     return pObj;
}


//******************************************************************
// operator delete
//******************************************************************
void CHexstaticBoard::operator delete(void *pMem)
{
     FREE(pMem);
}


//******************************************************************
// Initialize
//******************************************************************
void CHexstaticBoard::Initialize()
{
     m_pHeldPiece = NULL;

     m_ucDrawTypes = 0;

     m_bAcceptInput = false;
     m_cCurrState = NGameBoardStuff::NO_STATE;

     m_shHighligherInd = -1;
     m_shHeldPieceInd = -1;
     m_shHeldBackground = -1;
     m_ucPieceSpriteSize = 0;
}


//******************************************************************
// Clear
//******************************************************************
void CHexstaticBoard::Clear()
{
     ClearBoard();
}


//******************************************************************
// ShiftUp
//******************************************************************
bool CHexstaticBoard::ShiftUp()
{
     // First, check the top row to see if there are any pieces in it.
     // If so, fail and end.
     if(!TopRowEmpty())
          return false;

     // Staring at the second piece row, go through all the rows and move the pieces up to the next row.
     int iInd = m_iNumC*2;
     for(int iR = 1; iR < m_iBottomRow; ++iR)
     {
          for(int iC = 0; iC < m_iNumC; ++iC)
          {
               StorePiece(m_pGamePieces[iInd], iC, iR);
               m_pGamePieces[iInd++] = NULL;
          }
     }
          
     // Shift the selection boards up as well.
     CalcSelectionBoarderPos();

     m_ucDrawTypes |= NGameBoardStuff::SET_BOARD_SPRITE_DATA;

     // Succeded, end.
     return true;
}


//******************************************************************
// TopRowEmpty
//******************************************************************
bool CHexstaticBoard::TopRowEmpty()
{
     for(int iInd = 0; iInd < m_iNumC; ++iInd)
     {
          if((NULL != m_pGamePieces[iInd + m_iNumC]) && (m_pPieceManager->m_cCurrPieceRowDispColor != m_pGamePieces[iInd + m_iNumC]->m_cHexType))
               return false;
     }

     // No pieces, succeded.
     return true;
}


//******************************************************************
// ClearBoard
//******************************************************************
void CHexstaticBoard::ClearBoard()
{
     if(NULL != m_pHeldPiece)
     {
          m_pPieceManager->ReinsertPiece(m_pHeldPiece);
          m_pHeldPiece = NULL;
     }

     m_clCurrPieceInd.Set(-1, 0);

     m_clLastPlaced.Set(-1, -1);

     m_bAcceptInput = false;
     m_bBlink = false;
     m_cCurrState = NGameBoardStuff::NO_STATE;
     m_iMultiplier = 0;

     for(int iInd = 0; iInd < m_iBoardSize; ++iInd)
     {
          if(NULL != m_pGamePieces[iInd])
          {
               m_pPieceManager->ReinsertPiece(m_pGamePieces[iInd]);
               m_pGamePieces[iInd] = NULL;
          }
     }
}


//******************************************************************
// TopPlayRowFilled
//******************************************************************
bool CHexstaticBoard::TopPlayRowFilled()
{
     for(int iC = 0; iC < m_iNumC; ++iC)
     {
          // Empty spot.
          if(NULL == m_pGamePieces[iC+m_iNumC])
               return false;
     }

     // No empty spots.
     return true;
}


//******************************************************************
// Draw
//******************************************************************
void CHexstaticBoard::Draw()
{
     // Set the sprite data array, when needed.
     if(m_ucDrawTypes & NGameBoardStuff::SET_BOARD_SPRITE_DATA)
          FillBoardDataArray();

     if(m_ucDrawTypes & NGameBoardStuff::BLINK_GROUPS)
          SetGroupsAsBlinking();

     if(m_ucDrawTypes & NGameBoardStuff::SET_EXTRA_SPRITE_DATA)
          FillExtraSpritesDataArray();

     // Draw the board, if needed.
     if(0 != m_ucDrawTypes)
     {
          DrawBoard();
          m_ucDrawTypes = 0;
     }

     // Draw the extra sprites.
     if(NULL != m_pSpriteData)
          m_pSpriteM->Draw(m_pSpriteData + m_shHighligherInd);
}


//******************************************************************
// StartBoard
//******************************************************************
void CHexstaticBoard::StartBoard()
{
     m_iLevelIncrease = 0;
     m_iTotNumPiecesRemoved = 0;
     m_iNumRemoved = 0;
     m_iBottomRow = m_iNumR-2;
     m_iMultiplier = 0;
     m_bBlink = false;

     // Wait a between user shifts.  Since we are just starting, set it to 
     // the end right away.
     m_clWaitBetweenShiftsTimer.STimeToWait(500);
     m_clWaitBetweenShiftsTimer.SetToEnd();

     // Set the game state.
     m_cCurrState = NGameBoardStuff::NORMAL_UPDATE_STATE;

     m_bAcceptInput = true;

     // Reset the shift timer.
     m_clShiftUpTimer.ResetTimePassed();
     
     // Reset the selection object positions.
     m_clCurrPieceInd.Set(m_iNumC/2, m_iNumR/2);
     CalcSelectionBoarderPos();

     // Fill the top row with the boarder unusable objects.
     for(int iC = 0; iC < m_iNumC; ++iC)
          StorePiece(m_pPieceManager->GetRowDispPiece(), iC, 0);

     // Fill the bottom row with random pieces.
     InsertRandomPieces(m_iBottomRow);

     // Fill the base row with unusable pieces.
     for(int iC2 = 0; iC2 < m_iNumC; ++iC2)
          StorePiece(m_pPieceManager->GetNonPlayablePiece(), iC2, m_iBottomRow+1);

     FillSpriteDataArray();
}


//******************************************************************
// GPercentRemStateLeft
//******************************************************************
int CHexstaticBoard::GPercentRemStateLeft()
{
     // Not even in the state.
     if(NGameBoardStuff::REMOVAL_STATE != m_cCurrState)
          return 0;

     return 100 - m_clGeneralTimer.GTimePassPercent();
}


//******************************************************************
// GNumRemoved
//******************************************************************
int CHexstaticBoard::GNumRemoved()
{
     int iNumRem = m_iNumRemoved;
     m_iNumRemoved = 0;
     return iNumRem;     
}


//******************************************************************
// GScoreMulti
//******************************************************************
int CHexstaticBoard::GScoreMulti()
{
     return m_iMultiplier;
}


//******************************************************************
// GCurrState
//******************************************************************
char CHexstaticBoard::GCurrState()
{
     return m_cCurrState;
}


//******************************************************************
// GLevelIncrease
//******************************************************************
int CHexstaticBoard::GLevelIncrease()
{
     int iLevIncrease = m_iLevelIncrease;
     m_iLevelIncrease = 0;
     return iLevIncrease;     
}


//******************************************************************
// SettleAllColumns
//******************************************************************
bool CHexstaticBoard::SettleAllColumns()
{     
     bool bSettled = false;

     for(int iC = 0; iC < m_iNumC; ++iC)
          bSettled = SettleColumn(iC, m_iBottomRow) ? true : bSettled;
     return bSettled;
}


//******************************************************************
// Update
//******************************************************************
bool CHexstaticBoard::Update(long lTimePassed)
{
     // Update the timer.  This might not be in use at the time, it don't really matter.
     m_clGeneralTimer.Update(lTimePassed);
     
     // Update the wait between user shifts.
     m_clWaitBetweenShiftsTimer.Update(lTimePassed);

     // Handle game over -
     // The game is in the game over state.  Poor sap.  Anyway, run whatever updates are needed.  If the game over
     // state finishes, return that the game over menu needs to be displayed.
     if(NGameBoardStuff::GAME_OVER_STATE == m_cCurrState)
     {          
          return UpdateGameOver(lTimePassed);
     }

     // Determine if a level change is needed.
     if((NGameBoardStuff::NORMAL_UPDATE_STATE == m_cCurrState))
     {
          // New level.  Handle shifting down and increase the game speed.
          while(m_iLevelIncreasePieceCount-1 < m_iTotNumPiecesRemoved)
          {
               m_iTotNumPiecesRemoved -= m_iLevelIncreasePieceCount;
               ++m_iLevelIncrease;
               m_clShiftUpTimer.STimeToWait(m_clShiftUpTimer.m_lTimeWait - m_iShiftUpTimeDecrease);
          }
     }          

     // Handle removals -
     // There are pieces that are set for removal.  Update the removal timer and remove the pieces.
     // Shift the columns down, and check for removals.  If removals are set, start the removal process again and 
     // exit the update function.
     if(NGameBoardStuff::REMOVAL_STATE == m_cCurrState)
     {
          // Update the blink.
          m_clBlinkTimer.Update(lTimePassed);
          if(0 != m_clBlinkTimer.GetIfTimePassed())
          {
               // Set the sprite data array so that all pieces in groups get shown as blinking.
               m_bBlink = !m_bBlink;
               if(m_bBlink)
                    m_ucDrawTypes |= NGameBoardStuff::BLINK_GROUPS;
               else
                    m_ucDrawTypes |= NGameBoardStuff::SET_BOARD_SPRITE_DATA;;

               m_ucDrawTypes |= NGameBoardStuff::SET_BOARD_SPRITE_DATA;;
               m_clBlinkTimer.ResetTimePassed();
          }

          // See if it is time for the removal.  Handle any events needed if the time is up.
          if(0 != m_clGeneralTimer.GetIfTimePassed())
          {
               // Remove all the pieces tagged for removal.
               m_iNumRemoved = RemoveAllGroupPieces();
               m_ucDrawTypes |= NGameBoardStuff::SET_BOARD_SPRITE_DATA;;

               m_iTotNumPiecesRemoved += m_iNumRemoved;

               // Revert to the update state.
               m_cCurrState = NGameBoardStuff::NORMAL_UPDATE_STATE;
               m_iMultiplier = 0;
               m_bBlink = false;

               // Settle down all the columns.
               // Check the board for removals.
               // Switch to removal state if any groups are found.
               SettleAllColumns();
               if(CheckForAllRemovals())
               {
                    m_cCurrState = NGameBoardStuff::REMOVAL_STATE;
                    ++m_iMultiplier;
                    m_clGeneralTimer.ResetTimePassed();
                    m_clBlinkTimer.ResetTimePassed();
               }

               // Game not over yet.
               return false;
          }
     }

     // Handle shift -
     // No removal events were running or started, so update the shift up timer.
     // Handle the shift up if the timer was finshed.  If the shift up can't happen because the board
     // is filled up to the top, then start the game over update and exit the update function.
     
     // If the shift up gets done, then insert a new line of pieces in the now empty bottom row,
     // and check the bottom row for groups.  If any groups are found, start start the removal state.
     m_clShiftUpTimer.Update(lTimePassed);
     if(m_clShiftUpTimer.GTimePassed())
     {
          if(NGameBoardStuff::NORMAL_UPDATE_STATE == m_cCurrState)
               StartShiftUp();
          else
               m_clShiftUpTimer.SetToEnd();
     }

     // Game not over yet.
     return false;
}


//******************************************************************
// CurrPieceAction
//******************************************************************
bool CHexstaticBoard::CurrPieceAction(char cMethod)
{
     // Not in a state that accepts input, end.
     if((NGameBoardStuff::NO_STATE == m_cCurrState) || (NGameBoardStuff::GAME_OVER_STATE == m_cCurrState))
          return false;

     // No input is currently being accepted, end.
     if(!m_bAcceptInput)
          return false;

     // No current selection, do nothing.
     if(-1 == m_clCurrPieceInd.m_tX)
          return false;

     // Move the current selection highlighter left, if possible
     if(NInputActions::MOVE_LEFT == cMethod)
     {
          if(0 != m_clCurrPieceInd.m_tX)
          {
               // Update the display positions for the selection cursor.
               m_ucDrawTypes |= NGameBoardStuff::SET_EXTRA_SPRITE_DATA;
               --m_clCurrPieceInd.m_tX;
               CalcSelectionBoarderPos();
     
               // Action occured, end.
               return true;
          }
     }
     // Move the current selection highligher right, if possible.
     else if(NInputActions::MOVE_RIGHT == cMethod)
     {
          if(m_iNumC != m_clCurrPieceInd.m_tX+1)
          {
               // Update the display positions for the selection cursor.
               m_ucDrawTypes |= NGameBoardStuff::SET_EXTRA_SPRITE_DATA;
               ++m_clCurrPieceInd.m_tX;
               CalcSelectionBoarderPos();

               // Action occured, end.
               return true;
          }
     }
     // Move the current selection highlighter up, if possible
     else if(NInputActions::MOVE_UP == cMethod)
     {
          if(1 != m_clCurrPieceInd.m_tY)
          {
               // Update the display positions for the selection cursor.
               --m_clCurrPieceInd.m_tY;
               m_ucDrawTypes |= NGameBoardStuff::SET_EXTRA_SPRITE_DATA;
               CalcSelectionBoarderPos();

               // Action occured, end.
               return true;
          }
     }
     // Move the current selection highlighter down, if possible.  If the highlighter is already
     // at the bottom of the board, start a shift up event.
     else if(NInputActions::MOVE_DOWN == cMethod)
     {
          // Not at the bottom of the board, move it down.
          if(m_iBottomRow != m_clCurrPieceInd.m_tY)
          {
               // Update the display positions for the selection cursor.
               ++m_clCurrPieceInd.m_tY;
               m_ucDrawTypes |= NGameBoardStuff::SET_EXTRA_SPRITE_DATA;
               CalcSelectionBoarderPos();

               // Action occured, end.
               return true;
          }
          // Already at the bottom of the board, so shift the board up.
          else
          {
               // Only attempt to shift up if in the normal update state.
               // Also keep from shifting immediatly after a previous user activated shift.
               if(NGameBoardStuff::NORMAL_UPDATE_STATE == m_cCurrState && m_clWaitBetweenShiftsTimer.GTimePassed())
               {
                    m_clWaitBetweenShiftsTimer.ResetTimePassed();
                    StartShiftUp();
               }

               // Action succeded.
               return true;
          }
     }
     // Try to remove the current selected piece, or swap it out with the stored piece.
     else if(NInputActions::ACTION == cMethod)
     {
          if(NULL == m_pHeldPiece)
               return RemovePiece();
          else
               return SwapOutPiece();
     }

     return false;
}


//******************************************************************
// SwapOutPiece
//******************************************************************
bool CHexstaticBoard::SwapOutPiece()
{
     
     int iCurrPieceInd = m_clCurrPieceInd.m_tX + m_clCurrPieceInd.m_tY * m_iNumC;
     CGamePiece * pCurrSelected = m_pGamePieces[iCurrPieceInd];
     // No current piece, so just insert.
     if(NULL == pCurrSelected)
     {
          return InsertPiece();
     }
     // If the current selected piece is set for removal, end.
     else if(0 != (NLinkDataVals::GROUPED & pCurrSelected->m_ucLinkData))
     {
          return false;
     }

     // Fill the current piece spot with the stored piece.  Store the old current piece.
     m_pGamePieces[iCurrPieceInd] = NULL;
     StorePiece(m_pHeldPiece, m_clCurrPieceInd.m_tX, m_clCurrPieceInd.m_tY);
     m_pHeldPiece = pCurrSelected;
     m_pHeldPiece->m_clDispP = m_clHeldPieceDisp;

     // Check for groups.
     if(CheckForGroupRemoval(m_clCurrPieceInd.m_tX, m_clCurrPieceInd.m_tY))
     {
          m_cCurrState = NGameBoardStuff::REMOVAL_STATE;
          ++m_iMultiplier;
          m_clGeneralTimer.STimeToWait(m_iRemovalTime);
          m_clBlinkTimer.ResetTimePassed();
     }

     m_ucDrawTypes |= NGameBoardStuff::SET_EXTRA_SPRITE_DATA;
     m_ucDrawTypes |= NGameBoardStuff::SET_BOARD_SPRITE_DATA;;

     // Did the swap, end.
     return true;
}


//******************************************************************
// CalcSelectionBoarderPos
//******************************************************************
void CHexstaticBoard::CalcSelectionBoarderPos()
{
     CalcPixPos(&m_clSelectionBoarder, m_clCurrPieceInd.m_tX, m_clCurrPieceInd.m_tY);
}


//******************************************************************
// InsertPiece
//******************************************************************
bool CHexstaticBoard::InsertPiece()
{
     // If the current board is not empty, then end.
     if(NULL != m_pGamePieces[m_clCurrPieceInd.m_tX + m_clCurrPieceInd.m_tY * m_iNumC])
          return false;

     // Insert the piece into the board.
     StorePiece(m_pHeldPiece, m_clCurrPieceInd.m_tX, m_clCurrPieceInd.m_tY);
     m_pHeldPiece = NULL;

     // If it is in a normal update state, settle and check for groups.
     // Otherwise just check for groups.
     if(NGameBoardStuff::NORMAL_UPDATE_STATE == m_cCurrState)
     {
          if(SettlePieceWithCheck(m_clCurrPieceInd.m_tX, m_clCurrPieceInd.m_tY))
          {
               m_cCurrState = NGameBoardStuff::REMOVAL_STATE;
               ++m_iMultiplier;
               m_clGeneralTimer.STimeToWait(m_iRemovalTime);
               m_clBlinkTimer.ResetTimePassed();
          }
     }
     else
     {
          if(CheckForGroupRemoval(m_clCurrPieceInd.m_tX, m_clCurrPieceInd.m_tY))
          {
               m_cCurrState = NGameBoardStuff::REMOVAL_STATE;
               ++m_iMultiplier;
               m_clGeneralTimer.STimeToWait(m_iRemovalTime);
               m_clBlinkTimer.ResetTimePassed();
          }
     }

     m_ucDrawTypes |= NGameBoardStuff::SET_EXTRA_SPRITE_DATA;
     m_ucDrawTypes |= NGameBoardStuff::SET_BOARD_SPRITE_DATA;;

     // Action took place.  End.
     return true;
}


//******************************************************************
// RemovePiece
//******************************************************************
bool CHexstaticBoard::RemovePiece()
{
     // If the current board is empty or the piece is part of a group, do nothing and end.
     int iCurrInd = m_clCurrPieceInd.m_tX + m_clCurrPieceInd.m_tY * m_iNumC;
     CGamePiece * pCurrPiece = m_pGamePieces[iCurrInd];
     if((NULL == pCurrPiece) || (0 != (NLinkDataVals::GROUPED & pCurrPiece->m_ucLinkData)))
          return false;

     // Pull the piece out of the board and clear the spot it was in.
     m_pHeldPiece = pCurrPiece;
     m_pGamePieces[iCurrInd] = NULL;

     // If in a normal update state, settle the column and check for removals, otherwise do nothing.
     if(NGameBoardStuff::NORMAL_UPDATE_STATE == m_cCurrState)
     {
          if(SettleColumn(m_clCurrPieceInd.m_tX, m_iBottomRow) && CheckForAllRemovals())
          {
               m_cCurrState = NGameBoardStuff::REMOVAL_STATE;
               ++m_iMultiplier;
               m_clGeneralTimer.STimeToWait(m_iRemovalTime);
               m_clBlinkTimer.ResetTimePassed();
          }
     }


     m_ucDrawTypes |= NGameBoardStuff::SET_BOARD_SPRITE_DATA;;
     m_ucDrawTypes |= NGameBoardStuff::SET_EXTRA_SPRITE_DATA;
     return true;
}


//******************************************************************
// StartShiftUp
//******************************************************************
bool CHexstaticBoard::StartShiftUp()
{
     if(ShiftUp())
     {
          // Insert random pieces into the bottom row, then check for groups.
          // Switch to the removal state if any groups are found.
          InsertRandomPieces(m_iBottomRow);

          // Check for removals.  Reset removal time and state if removals started.
          if(CheckRowForRemovals(m_iBottomRow))
          {
               m_cCurrState = NGameBoardStuff::REMOVAL_STATE;
               ++m_iMultiplier;
               m_clGeneralTimer.STimeToWait(m_iRemovalTime);
               m_clBlinkTimer.ResetTimePassed();

               m_ucDrawTypes |= NGameBoardStuff::SET_BOARD_SPRITE_DATA;;

               // Everything went fine.
               m_clShiftUpTimer.ResetTimePassed();
               return true;
          }
     }
     // Couldn't shift up.  Start the game over update mode.
     else
     {
          StartGameOver();
          return false;
     }


     // Everything went fine.
     m_clShiftUpTimer.ResetTimePassed();
     return true;
}


//******************************************************************
// InsertRandomPieces
//******************************************************************
void CHexstaticBoard::InsertRandomPieces(int iRow)
{
     for(int iC = 0; iC < m_iNumC; ++iC)
          StorePiece(m_pPieceManager->GetRandPlayablePiece(), iC, iRow);
}


//******************************************************************
// StartGameOver
//******************************************************************
void CHexstaticBoard::StartGameOver()
{
     // Set to the update state.
     m_cCurrState = NGameBoardStuff::GAME_OVER_STATE;
     m_iMultiplier = 0;
     m_iNumRemoved = 0;

     // Set the general timer to the amount of time between column removals.
     m_clGeneralTimer.STimeToWait(1000);

     m_iNextColRem = m_iNumC - 1;

     // Need to update the display.
     m_ucDrawTypes |= NGameBoardStuff::SET_EXTRA_SPRITE_DATA;
}


//******************************************************************
// UpdateGameOver
//******************************************************************
bool CHexstaticBoard::UpdateGameOver(long lTimePassed)
{
     // Update the blink.
     m_clBlinkTimer.Update(lTimePassed);
     if(0 != m_clBlinkTimer.GetIfTimePassed())
     {
               // Set the sprite data array so that all pieces in groups get shown as blinking.
               m_bBlink = !m_bBlink;
               if(m_bBlink)
                    m_ucDrawTypes |= NGameBoardStuff::BLINK_GROUPS;
               else
                    m_ucDrawTypes |= NGameBoardStuff::SET_BOARD_SPRITE_DATA;

               m_ucDrawTypes |= NGameBoardStuff::SET_BOARD_SPRITE_DATA;
               m_clBlinkTimer.ResetTimePassed();
     }

     // If the timer has finished, remove all the pieces set for removal.
     // Set the next column to start blinking, and reset the timer.
     // If there aren't anymore columns, then return that the game over state is finished.
     if(0 != m_clGeneralTimer.GetIfTimePassed())
     {
          RemoveAllGroupPieces();
          if(-1 == m_iNextColRem)
               return true;
          SetColToRem(m_iNextColRem--);
          m_clGeneralTimer.ResetTimePassed();
     }

     return false;
}


//******************************************************************
// Create
//******************************************************************
void CHexstaticBoard::Create(unsigned char ucNumC,
                                unsigned char ucNumR)
{
     CreateBoard(ucNumC, ucNumR);
     CreateSpriteDataArray();
}


//******************************************************************
// CreateSpriteDataArray
//******************************************************************
void CHexstaticBoard::CreateSpriteDataArray()
{
     // For the board pieces, current held piece, current piece background, and current segment highligher.
     // The last slot is off course the end designator and thus doesn't get used.
     int iNumSlots = m_iBoardSize + 3 + 2;
     m_pSpriteData = (AEESpriteCmd*)MALLOC(sizeof(AEESpriteCmd) * iNumSlots);
     MEMSET(m_pSpriteData, 0, sizeof(AEESpriteCmd)*iNumSlots);
     
     m_shHeldPieceInd = m_iBoardSize + 3;
     m_shHeldBackground = m_iBoardSize + 2;
     m_shHighligherInd = m_iBoardSize + 1;

     // Set all the board piece data slots.
     for(int iPieceInd = 0; iPieceInd < m_iBoardSize; ++iPieceInd)
     {          
          m_pSpriteData[iPieceInd].unSpriteIndex = 0;
          m_pSpriteData[iPieceInd].unSpriteSize = SPRITE_SIZE_END;
          m_pSpriteData[iPieceInd].unComposite = 0;
          m_pSpriteData[iPieceInd].unLayer = 0;
     }

     // Now set the defaults for the special slots, like the selection highlighter, the current held background,
     // and the current held piece.
     m_pSpriteData[m_shHeldPieceInd].unSpriteIndex = 0;
     m_pSpriteData[m_shHeldPieceInd].unSpriteSize = SPRITE_SIZE_END;
     m_pSpriteData[m_shHeldPieceInd].unComposite = 0;
     m_pSpriteData[m_shHeldPieceInd].unLayer = 0;

     m_pSpriteData[m_shHeldBackground].unSpriteIndex = 0;
     m_pSpriteData[m_shHeldBackground].unSpriteSize = SPRITE_SIZE_END;
     m_pSpriteData[m_shHeldBackground].unComposite = 0;
     m_pSpriteData[m_shHeldBackground].unLayer = 0;

     m_pSpriteData[m_shHighligherInd].unSpriteIndex = 0;
     m_pSpriteData[m_shHighligherInd].unSpriteSize = SPRITE_SIZE_END;
     m_pSpriteData[m_shHighligherInd].unComposite = 0;
     m_pSpriteData[m_shHighligherInd].unLayer = 0;

     m_pSpriteData[iNumSlots-1].unSpriteIndex = 0;
     m_pSpriteData[iNumSlots-1].unSpriteSize = SPRITE_SIZE_END;
     m_pSpriteData[iNumSlots-1].unComposite = 0;
     m_pSpriteData[iNumSlots-1].unLayer = 0;
}


//******************************************************************
// FillboardDataArray
//******************************************************************
void CHexstaticBoard::FillBoardDataArray()
{
     int iSpriteInd = 0;
     CGamePiece * pCurrPice = NULL;
     for(int iBoardInd = 0; iBoardInd < m_iBoardSize; ++iBoardInd)
     {
          if(NULL != (pCurrPice = m_pGamePieces[iBoardInd]))
          {
               m_pSpriteData[iSpriteInd].x = pCurrPice->m_clDispP.m_tX;
               m_pSpriteData[iSpriteInd].y = pCurrPice->m_clDispP.m_tY;
               m_pSpriteData[iSpriteInd].unSpriteSize = m_ucPieceSpriteSize;
               m_pSpriteData[iSpriteInd].unSpriteIndex = pCurrPice->m_cHexType;
               ++iSpriteInd;
          }
     }

     // Set the slot after the board pieces with the end data.
     m_pSpriteData[iSpriteInd].unSpriteSize = SPRITE_SIZE_END;
}


//******************************************************************
// SetGroupsAsBlinking
//******************************************************************
void CHexstaticBoard::SetGroupsAsBlinking()
{
     // Go through all the pieces and set the draw data to blink.
     int iSpriteInd = 0;
     CGamePiece * pCurrPiece = NULL;
     for(int iBoardInd = 0; iBoardInd < m_iBoardSize; ++iBoardInd)
     {
          if((NULL != (pCurrPiece = m_pGamePieces[iBoardInd])))
          {
               if(0 != (pCurrPiece->m_ucLinkData & NLinkDataVals::GROUPED))
                    m_pSpriteData[iSpriteInd].unSpriteIndex = m_pPieceManager->m_cBlinkType;
               ++iSpriteInd;
          }
     }
}



//******************************************************************
// FillextraSpritesDataArray
//******************************************************************
void CHexstaticBoard::FillExtraSpritesDataArray()
{
     // In the game over state, so don't show any of the extra sprites.
     if(NGameBoardStuff::GAME_OVER_STATE == m_cCurrState)
     {
          m_pSpriteData[m_shHighligherInd].unSpriteSize = SPRITE_SIZE_END;
          return;
     }

     // Set the current selection highlighter.
     m_pSpriteData[m_shHighligherInd].x = m_clSelectionBoarder.m_clDispP.m_tX;
     m_pSpriteData[m_shHighligherInd].y = m_clSelectionBoarder.m_clDispP.m_tY;
     m_pSpriteData[m_shHighligherInd].unSpriteSize = m_ucPieceSpriteSize;
     m_pSpriteData[m_shHighligherInd].unSpriteIndex = m_clSelectionBoarder.m_cHexType;


     // Set the current held piece background.
     m_pSpriteData[m_shHeldBackground].x = m_clHeldPieceDisp.m_tX;
     m_pSpriteData[m_shHeldBackground].y = m_clHeldPieceDisp.m_tY;
     m_pSpriteData[m_shHeldBackground].unSpriteSize = m_ucPieceSpriteSize;
     m_pSpriteData[m_shHeldBackground].unSpriteIndex = m_clSelectionBoarder.m_cHexType;

     // Set the current held piece, if needed.  Set the end to be after the current held piece if there is one.  If not, set it as the current held.
     if(NULL != m_pHeldPiece)
     {
          m_pSpriteData[m_shHeldPieceInd].x = m_clHeldPieceDisp.m_tX;
          m_pSpriteData[m_shHeldPieceInd].y = m_clHeldPieceDisp.m_tY;
          m_pSpriteData[m_shHeldPieceInd].unSpriteSize = m_ucPieceSpriteSize;
          m_pSpriteData[m_shHeldPieceInd].unSpriteIndex = m_pHeldPiece->m_cHexType;

          m_pSpriteData[m_shHeldPieceInd+1].unSpriteSize = SPRITE_SIZE_END;
     }
     else
     {
          m_pSpriteData[m_shHeldPieceInd].unSpriteSize = SPRITE_SIZE_END;
     }
}


//******************************************************************
// ShouldRedraw
//******************************************************************
bool CHexstaticBoard::ShouldRedraw()
{
     return (0 != m_ucDrawTypes);
}


//******************************************************************
// FillSpriteDataArray
//******************************************************************
void CHexstaticBoard::FillSpriteDataArray()
{
     m_ucDrawTypes |= NGameBoardStuff::SET_BOARD_SPRITE_DATA;
     m_ucDrawTypes |= NGameBoardStuff::SET_EXTRA_SPRITE_DATA;
}


//******************************************************************
// SSelectionSpriteID
//******************************************************************
void CHexstaticBoard::SSelectionSpriteID(char cID)
{
     m_clSelectionBoarder.m_cHexType = cID;
}


//******************************************************************
// SHeldPiece
//******************************************************************
void CHexstaticBoard::SHeldPieceP(const CPoint & crPoint)
{
     m_clHeldPieceDisp = crPoint;
     m_ucDrawTypes |= NGameBoardStuff::SET_BOARD_SPRITE_DATA;
}