int countLines(int *board, int x, int y) { switch(board[xyToIndex(x, y)] & FULL_BOX) { case FULL_BOX: return 4; case THREE_OPEN_TOP: case THREE_OPEN_RIGHT: case THREE_OPEN_BOTTOM: case THREE_OPEN_LEFT: return 3; case TWO_TOP_RIGHT: case TWO_TOP_BOTTOM: case TWO_TOP_LEFT: case TWO_RIGHT_BOTTOM: case TWO_RIGHT_LEFT: case TWO_BOTTOM_TWO: return 2; case TOP_LINE: case RIGHT_LINE: case BOTTOM_LINE: case LEFT_LINE: return 1; default: return 0; } }
uint8_t MatrixDisplay::getPixel(uint8_t displayNum, uint8_t x, uint8_t y, bool useShadow) { // Encode XY to an appropriate XY address uint8_t address = xyToIndex(x, y); // offset to the correct buffer for the display address += backBufferSize * displayNum; uint8_t bit = CalcBit(y); // fetch the value byte from the buffer address = (backBufferSize * displayNum) + address; uint8_t value = 0; if(useShadow) { value = pShadowBuffers[address]; }else{ value = pDisplayBuffers[address]; } return (value & bit) ? 1 : 0; }
void MatrixDisplay::setPixel(uint8_t displayNum, uint8_t x, uint8_t y, uint8_t value, bool paint, bool useShadow) { // calculate a pointer into the display buffer (6 bit offset) uint8_t address = xyToIndex(x, y); uint8_t dispAddress = address; // offset to the correct buffer for the display address += backBufferSize * displayNum; uint8_t bit = CalcBit(y); // ...and apply the value if(value) { if(useShadow) { pShadowBuffers[address] |= bit; }else{ pDisplayBuffers[address] |= bit; } } else { if(useShadow) { pShadowBuffers[address] &= ~bit; }else{ pDisplayBuffers[address] &= ~bit; } } if(useShadow) return; if(!paint) { // flag the display as dirty //pDisplayPins[displayNum] |= DIRTY_BIT; }else{ uint8_t dispAddress = displayXYToIndex(x, y); uint8_t value = pDisplayBuffers[address]; if(y>=4) // Devide y by 4. Work out whether it's odd or even. 8 pixels packed into 1 byte. 16 pixels are in two bytes. We need to figure out whether to shift the buffer { value = pDisplayBuffers[address] >> 4; } writeNibbles(displayNum, dispAddress, &value, 1); }
boardEvaluation *evaluateBoard(int *board, move *lastMove) { // Variables int x, y, i, o; boardEvaluation *temp; // Allocate our structure temp = malloc(sizeof(boardEvaluation)); // Initialize it temp->noSides = 0; temp->oneSides = 0; temp->twoSides = 0; temp->threeSides = 0; temp->playerOneOwned = 0; temp->playerTwoOwned = 0; temp->playerOtherOwned = 0; temp->winner = PLAYER_OTHER; temp->moveLength = -1; // Now we count for (y = 0; y < boardHeight; y++) { for (x = 0; x < boardWidth; x++) { i = countLines(board, x, y); // printf("%d, %d: %d with %d lines\n", x, y, gameBoard[xyToIndex(x, y)], i); switch(i) { case 0: temp->noSides++; break; case 1: temp->oneSides++; break; case 2: temp->twoSides++; break; case 3: temp->threeSides++; break; case 4: o = board[xyToIndex(x, y)] & OWNER_MASK; switch(o) { case OWNED_BY_PLAYER_ONE: temp->playerOneOwned++; break; case OWNED_BY_PLAYER_TWO: temp->playerTwoOwned++; break; case OWNED_BY_OTHER: temp->playerOtherOwned++; break; default: printf("Recieved an unknown owner! It was %d.\n", o); exit(1); } break; default: printf("Box %d, %d had an invalid number of lines! Got %d.\n", x, y, i); exit(1); } } } // Now figure out if someone won if (temp->playerOneOwned + temp->playerTwoOwned + temp->playerOtherOwned == boardWidth * boardHeight) { // The game is over if (temp->playerOneOwned > temp->playerTwoOwned) { temp->winner = PLAYER_ONE; } else if (temp->playerOneOwned == temp->playerTwoOwned) { temp->winner = PLAYER_TIE; } else { temp->winner = PLAYER_TWO; } } else { temp->winner = NO_WINNER_YET; } if (lastMove != null) { temp->moveLength = abs(lastMove->from_x - lastMove->to_x) + abs(lastMove->from_y + lastMove->to_y); } // Return it, note that the caller MUST FREE THE STRUCTURE return temp; }
void runMove(int player, int from_x, int from_y, int to_x, int to_y, int test_only, int *board) { // This function makes a move on the board int x, y, i, count, c; // First, draw the new line if (from_x == to_x) { // It's a virticle line x = from_x; for (i = from_y; i < to_y; i++) { // Mark the left line if needed if (x != boardWidth) board[xyToIndex(x,i)] = board[xyToIndex(x, i)] | LEFT_LINE; // Mark the right line if needed if (x != 0) board[xyToIndex(x - 1, i)] = board[xyToIndex(x - 1, i)] | RIGHT_LINE; } } else { // It's a horizontal line y = from_y; for (i = from_x; i < to_x; i++) { // Mark the top line if needed if (y != boardHeight) board[xyToIndex(i, y)] = board[xyToIndex(i, y)] | TOP_LINE; // Mark the bottom line if needed if (y != 0) board[xyToIndex(i, y - 1)] = board[xyToIndex(i, y - 1)] | BOTTOM_LINE; } } // Now mark any new boxes with the owner for (y = 0; y < boardHeight; y++) { for (x = 0; x < boardWidth; x++) { c = board[xyToIndex(x, y)]; if (((c & FULL_BOX) == FULL_BOX) && ((c & OWNER_MASK) == 0)) { // It's a new box! Mark it as the correct player int bit; switch(player) { case PLAYER_ONE: bit = OWNED_BY_PLAYER_ONE; break; case PLAYER_TWO: bit = OWNED_BY_PLAYER_TWO; break; case PLAYER_OTHER: bit = OWNED_BY_OTHER; break; default: printf("ERROR: Got bad player: %d\n", player); exit(1); } if (test_only == false) { board[xyToIndex(x, y)] = c | bit; // Mark the owner } } } } }
void generateMoveList() { // First, we'll figure out the horizontal moves that are possible int x, y, i, j; int start, end; move *temp; for (y = 0; y < boardHeight; y++) { end = -1; while (end < boardWidth) { start = -1; // First, find the first place where we can start a line for (x = end + 1; x < boardWidth; x++) { if ((gameBoard[xyToIndex(x, y)] & TOP_LINE) == 0) { start = x; break; } } if (start == -1) break; // No free lines on this line // Now that we know where to start, we'll find where to end end = boardWidth; // So if we don't find lines, we have a good endpoint for (x = start; x < boardWidth; x++) { if (gameBoard[xyToIndex(x, y)] & TOP_LINE) { // We found a place with a line! Stop just before it end = x; break; } } // Now that we've got that, we create the list of possible lines for (i = start; i < end; i++) { for (j = i + 1; j <= end; j++) { addPossibleMove(i, y, j, y); } } } } // We have to handle the last line specially, because we have to check for BOTTOM_LINE, not TOP end = -1; y = boardHeight - 1; while (end < boardWidth) { start = -1; // First, find the first place where we can start a line for (x = end + 1; x < boardWidth; x++) { if ((gameBoard[xyToIndex(x, y)] & BOTTOM_LINE) == 0) { start = x; break; } } if (start == -1) break; // No free lines on this line // Now that we know where to start, we'll find where to end end = boardWidth; // So if we don't find lines, we have a good endpoint for (x = start; x < boardWidth; x++) { if (gameBoard[xyToIndex(x, y)] & BOTTOM_LINE) { // We found a place with a line! Stop just before it end = x; break; } } // Now that we've got that, we create the list of possible lines for (i = start; i < end; i++) { for (j = i + 1; j <= end; j++) { addPossibleMove(i, boardHeight, j, boardHeight); } } } // Now, the same thing, only for virticle lines for (x = 0; x < boardWidth; x++) { end = -1; while (end < boardHeight) { start = -1; // First, find the first place where we can start a line for (y = end + 1; y < boardHeight; y++) { if ((gameBoard[xyToIndex(x, y)] & LEFT_LINE) == 0) { start = y; break; } } if (start == -1) break; // No free lines on this line // Now that we know where to start, we'll find where to end end = boardHeight; // So if we don't find lines, we have a good endpoint for (y = start; y < boardHeight; y++) { if (gameBoard[xyToIndex(x, y)] & LEFT_LINE) { // We found a place with a line! Stop just before it end = y; break; } } // Now that we've got that, we create the list of possible lines for (i = start; i < end; i++) { for (j = i + 1; j <= end; j++) { addPossibleMove(x, i, x, j); } } } } // We have to handle the last line specially, because we have to check for BOTTOM_LINE, not TOP end = -1; x = boardWidth - 1; while (end < boardHeight) { start = -1; // First, find the first place where we can start a line for (y = end + 1; y < boardHeight; y++) { if ((gameBoard[xyToIndex(x, y)] & RIGHT_LINE) == 0) { start = y; break; } } if (start == -1) break; // No free lines on this line // Now that we know where to start, we'll find where to end end = boardHeight; // So if we don't find lines, we have a good endpoint for (y = start; y < boardHeight; y++) { if (gameBoard[xyToIndex(x, y)] & RIGHT_LINE) { // We found a place with a line! Stop just before it end = y; break; } } // Now that we've got that, we create the list of possible lines for (i = start; i < end; i++) { for (j = i + 1; j <= end; j++) { addPossibleMove(boardWidth, i, boardWidth, j); } } } // That's it, the possible move list is full! }
void printBoard(int *board) { int x, y, outputLine, c; printf("\n"); // Draw the board (except the last line) for (outputLine = 0; outputLine < 2 * boardHeight; outputLine++) { y = outputLine / 2; for (x = 0; x < boardWidth; x++) { c = board[xyToIndex(x, y)]; if (outputLine % 2 == false) { // This is a horizontal line printf("*"); // Put a dot if (c & TOP_LINE) printf("-"); // There was a line on top else printf(" "); // No line on top } else { // Print the virticle line if needed if (c & LEFT_LINE) printf("|"); // There was a line on left else printf(" "); // Print the box's owner switch(c & OWNER_MASK) { case OWNED_BY_PLAYER_ONE: printf("1"); break; case OWNED_BY_PLAYER_TWO: printf("2"); break; case OWNED_BY_OTHER: printf("X"); break; case OWNED_BY_NO_ONE: printf(" "); break; default: printf("Recieved an unknown owner! It was %d.\n", c & OWNER_MASK); exit(1); } } } // Now the ending characters on the line if (outputLine % 2 == false) { printf("*\n"); // The last dot on thel ine } else { if (board[xyToIndex(x - 1, y)] & RIGHT_LINE) // Is the right line set on the last box? printf("|"); printf("\n"); } } // Now we draw the last line y = boardHeight - 1; for (x = 0; x < boardWidth; x++) { // This is a horizontal line printf("*"); // Put a dot if (board[xyToIndex(x, y)] & BOTTOM_LINE) printf("-"); // There was a line on bottom else printf(" "); // No line on top } printf("*\n\n"); // Print the last dot, and two new lines. }