int main(int argc, char** argv) { struct Tile* t = Tile_new('f'); printf("tile %c\n", t->color); struct Board* b = Board_new(9,9); struct Tile* t2 = Board_get(b,0,0); printf("tile %c\n", t2->color); Board_print(b); Board_randomize(b); Board_print(b); struct Board* b2 = Board_clone(b); int matches; matches = Board_check_matching_at(b2, 0, 4); printf("board matches %i\n", matches); return 0; }
/* * Retrieves a list of all jump moves currently possible for a player. * * @params: (player) - the player whose moves are to be put in the list * @return: a LinkedList struct of jump moves currently possible for the player, or NULL if any allocation errors occurred */ static struct LinkedList* getPossibleJumps (char** board, int player){ struct LinkedList* jumpMoves = LinkedList_new(&PossibleMove_free); if(jumpMoves == NULL){ //allocation failed return NULL; } for (int x = 1; x <= Board_SIZE; x++){ for (int y = 1; y <= Board_SIZE; y++){ if (Board_evalPiece(board, x, y, player) <= 0){ continue; } for (int i = -1; i <= 1; i += 2){ for (int j = -1; j <= 1; j += 2){ struct Tile* destTile = NULL; if (!isInRange(x+i,y+j) || !isInRange(x+2*i,y+2*j)){ continue; } int pieceIsKing = Board_evalPiece(board, x, y, player) == 3; if (pieceIsKing){ destTile = canKingCaptureInDirection(board, x, y, i, j); } else{ int enemyNearby = Board_evalPiece(board, x+i, y+j, player) < 0; int enemyIsCapturable = Board_isEmpty(board, x+2*i, y+2*j); if(enemyNearby && enemyIsCapturable){ destTile = Tile_new(x+2*i, y+2*j); if (destTile == NULL){ // allocation failed return NULL; } } } if (!destTile){ continue; } struct LinkedList* jumpSteps = LinkedList_new(&Tile_free); if (jumpSteps == NULL){ // allocation failed Tile_free(destTile); return NULL; } LinkedList_add(jumpSteps, destTile); struct PossibleMove* possibleJumpMove = PossibleMove_new(x, y, jumpSteps, board); if (possibleJumpMove == NULL){ // allocation failed Tile_free(destTile); LinkedList_free(jumpSteps); return NULL; } populateJumpList(jumpMoves, possibleJumpMove); } } } } return jumpMoves; }
/* * Creates a new PossibleMove structure, consisting of the starting tile, * a list of tiles that are part of the move itself, and the state of the * board after this particular move has been carried out. * * @params: start - a pointer to the starting tile, moves - a pointer to the list of individual tile moves, * board - the board before the move * @return: NULL if any allocation errors occurred, the structure otherwise */ struct PossibleMove* PossibleMove_new(int x, int y, struct LinkedList* steps, char** board){ struct PossibleMove* move; move = (struct PossibleMove*)calloc(1, sizeof(struct PossibleMove)); if (!move){ return NULL; } move->start = Tile_new(x, y); if (!(move->start)){ free(move); return NULL; } move->steps = steps; move->board = Board_getPossibleBoard(board, move); return move; }
/* * Gets a list of all single step moves currently possible for a player. * * @params: (player) - the player whose moves are to be put in the list * @return: a list of single step moves currently possible for the player, or NULL if any allocation errors occurred */ static struct LinkedList* getPossibleSingleMoves (char** board, int player){ struct LinkedList* possibleSingleMoves = LinkedList_new(&PossibleMove_free); if (possibleSingleMoves == NULL){ return NULL; } int forward = (player == BLACK) ? -1 : 1; /* for each player's different direction of "forward" */ for (int x = 1; x <= Board_SIZE; x++){ for (int y = 1; y <= Board_SIZE; y++){ if (Board_evalPiece(board, x, y, player) <= 0){ //this tile doesn't contain one of this player's pieces continue; } for (int sideward = -1; sideward <= 1; sideward += 2){ for (int k = -Board_SIZE; k <= Board_SIZE; k++){ if (!isInRange(x+k*sideward, y+k)){ continue; } int pieceIsKing = Board_evalPiece(board, x, y, player) == 3; if (!pieceIsKing && k != forward){ continue; } if(Board_isEmpty(board, x+k*sideward, y+k)){ struct Tile* destTile = Tile_new(x+k*sideward, y+k); if (destTile == NULL){ // allocation failed return NULL; } struct LinkedList* singleSteps = LinkedList_new(&Tile_free); if (singleSteps == NULL){ // allocation failed Tile_free(destTile); return NULL; } LinkedList_add(singleSteps, destTile); struct PossibleMove* possibleSingleMove = PossibleMove_new(x, y, singleSteps, board); if (possibleSingleMove == NULL){ // allocation failed Tile_free(destTile); LinkedList_free(singleSteps); return NULL; } LinkedList_add(possibleSingleMoves, possibleSingleMove); } if (!pieceIsKing && k == forward){ break; } } } } } return possibleSingleMoves; }
/* * Checks whether a king in a given position can capture an enemy in a given direction * * @params: (x, y) - the coordinates of the given position * (dirX, dirY) - the coordinates if the direction * @return: NULL if no such enemy exists, the tile of the enemy otherwise */ static struct Tile* canKingCaptureInDirection(char** board, int x, int y, int dirX, int dirY){ int player = Board_getColor(board, x, y); int i = 1; int foundFirstEnemyInThisDirection = 0; while(isInRange(x+(i+1)*dirX, y+(i+1)*dirY)){ int enemyNearby = Board_evalPiece(board, x+i*dirX, y+i*dirY, player)<0; int enemyIsCapturable = Board_isEmpty(board, x+(i+1)*dirX, y+(i+1)*dirY); if (enemyNearby && enemyIsCapturable && !foundFirstEnemyInThisDirection){ return Tile_new(x+(i+1)*dirX, y+(i+1)*dirY); } if (enemyNearby){ foundFirstEnemyInThisDirection = 1; // to eliminate the possibility of capturing several pieces in one jump } i++; } return NULL; }
/* * Populates the list of possible jumps, recursively. * * @params: (possibleJumps) - the list to be populated * (possibleMove) - the move that parts of it will be populated in the list. */ static void populateJumpList(struct LinkedList* possibleJumps, struct PossibleMove* possibleMove){ struct Tile* lastStep = PossibleMove_getLastStep(possibleMove); char** board = possibleMove->board; int x = lastStep->x; int y = lastStep->y; //checking if another jump is possible after current last jump int found = 0; for (int i = -1; i <= 1; i += 2){ for (int j = -1; j <= 1; j += 2){ if (!isInRange(x+i,y+j) || !isInRange(x+2*i,y+2*j)){ continue; } struct Tile* currentLastStep = PossibleMove_getLastStep(possibleMove); int player = Board_getColorByTile(possibleMove->board, currentLastStep); int enemyNearby = (Board_evalPiece(board, x+i, y+j, player) < 0); int enemyIsCapturable = Board_isEmpty(board,x+2*i, y+2*j); int justCrowned = (player == WHITE && y == Board_SIZE) || (player == BLACK && y == 1); if(enemyNearby && enemyIsCapturable && !justCrowned){ //found another possible jump after current last step struct PossibleMove* currentMoveClone = PossibleMove_clone(possibleMove); struct LinkedList* currentSteps = currentMoveClone->steps; struct Tile* extraTile = Tile_new(x+2*i, y+2*j); LinkedList_add(currentSteps, extraTile); char oldX = currentLastStep->x; int oldY = currentLastStep->y; int newX = extraTile->x; int newY = extraTile->y; Board_move(currentMoveClone->board, oldX, oldY, newX, newY); populateJumpList(possibleJumps, currentMoveClone); found = 1; } } } if (found){ PossibleMove_free(possibleMove); return; } LinkedList_add(possibleJumps, possibleMove); }