int MancalaBoard::util_value(int player_turn, int root_player){ if(moves_available(player_turn) == 0){ //If this is the case then the game is over and you need to add all stones from the opposing side to their mancala if(player_turn == 1){ for(int i=p2_cell_start; i <= p2_cell_end; i++){ p2_mancala += cells[i]; cells[i] = 0; } } else if(player_turn == 2){ for(int i=0; i <= p1_cell_end; i++){ p1_mancala += cells[i]; cells[i] = 0; } } } if(root_player == 1){ return p1_mancala - p2_mancala; } else{ return p2_mancala - p1_mancala; } }
bool MancalaBoard::checkMoveValid(int move, int player_num){ int count = moves_available(player_num); int *options = next_moves(player_num); for (int i=0; i<count; ++i) { if(options[i] == move){ delete options; return true; } } delete options; return false; }
bool MancalaBoard::checkGameOver(int player_turn){ if(moves_available(player_turn) == 0){ //If this is the case then the game is over and you need to add all stones from the opposing side to their mancala if(player_turn == 1){ for(int i=p2_cell_start; i <= p2_cell_end; i++){ p2_mancala += cells[i]; cells[i] = 0; return true; } } else if(player_turn == 2){ for(int i=0; i <= p1_cell_end; i++){ p1_mancala += cells[i]; cells[i] = 0; return true; } } } return false; }
int* MancalaBoard::next_moves(int player_num){ int count = moves_available(player_num); int *result = new int[count]; if(player_num == 1){ int j = 0; for(int i=0; i <= p1_cell_end; i++){ if(cells[i] != 0){ result[j] = i; j++; } } } else if(player_num == 2){ int j = 0; for(int i=p2_cell_start; i <= p2_cell_end; i++){ if(cells[i] != 0){ result[j] = i - num_cells; j++; } } } return result; }
/* parses options and stores the main game loop */ int main(int argc, char **argv) { /* init ncurses environment */ initscr(); cbreak(); noecho(); curs_set(FALSE); /* init variables */ file = ".hs2048g"; hs = 0; s = 0; sl = 0; SZ = 4; MAXVAL = 4; CALLOC2D(g, SZ); load_score(); int n_blocks = 1; /* parse options */ int c; while ((c = getopt(argc, argv, "rchs:b:")) != -1) { switch (c) { // color support - assumes your terminal can display colours // should still work regardless case 'c': start_color(); init_pair(1, 1, 0); init_pair(2, 2, 0); init_pair(3, 3, 0); init_pair(4, 4, 0); init_pair(5, 5, 0); init_pair(6, 6, 0); init_pair(7, 7, 0); break; // different board sizes case 's': FREE2D(g, SZ); int optint = atoi(optarg); SZ = optint > 4 ? optint : 4; CALLOC2D(g, SZ); break; // different block spawn rate case 'b': n_blocks = atoi(optarg); break; // reset hiscores case 'r': endwin(); printf("Are you sure you want to reset your highscores? (Y)es or (N)o\n"); int response; if ((response = getchar()) == 'y' || response == 'Y') { FILE *fd = fopen(file, "w+"); fclose(fd); } exit(EXIT_SUCCESS); // help menu case 'h': endwin(); printf("Controls:\n" " hjkl, wasd Movement\n" " q Quit\n" "\n" "Usage:\n" " 2048 [options]\n" "\n" "Options:\n" " -s <size> Set the grid border length\n" " -b <rate> Set the block spawn rate\n" " -c Enables color support\n"); exit(EXIT_SUCCESS); } } int width = SZ * (MAXVAL + 2) + 1; int height = SZ * (MAXVAL + 2) + 3; // might center in middle of screen WINDOW *gamewin = newwin(height, width, 1, 1); keypad(gamewin, TRUE); /* random seed */ srand((unsigned int)time(NULL)); ITER(2, rand_block()); draw_grid(gamewin); int key, moved; while (1) { /* will goto this if we didn't get a valid keypress */ retry:; moved = 0; key = wgetch(gamewin); sl = 0; /* should check if anything changed during merge and if not retry */ switch (key) { case 'h': case 'a': case KEY_LEFT: moved = TURN(DL); break; case 'l': case 'd': case KEY_RIGHT: moved = TURN(DR); break; case 'j': case 's': case KEY_DOWN: moved = TURN(DD); break; case 'k': case 'w': case KEY_UP: moved = TURN(DU); break; case 'q': FREE2D(g, SZ); erase(); refresh(); endwin(); save_score(); exit(EXIT_SUCCESS); default: goto retry; } if (!moves_available()) { endwin(); printf("\n" "YOU LOSE! - Your score was %d\n", s); save_score(); exit(EXIT_SUCCESS); } if (moved) { ITER(n_blocks, rand_block()); draw_grid(gamewin); } } }
//Enocdes rules of the game, pretty crazy function //excepts a 0-indexed move relative to the player's cells from left to right bool MancalaBoard::make_move(int player, int cell){ checkGameOver(player); if(player == 1){ if(cell > p1_cell_end || cell < 0){ std::cout << "Invalid move for p1" << std::endl; return false; } int num_moves = cells[cell]; cells[cell] = 0; int pos = cell; //current position during loop while(num_moves > 0){ if(pos < p1_cell_end){//iterating through own player's cells just move to next cell pos++; if(num_moves == 1){//ending on own side (check if cell is empty) if(cells[pos] == 0){ p1_mancala += cells[pos + num_cells]; cells[pos + num_cells] = 0; cells[pos] = 0; p1_mancala ++; } else{ cells[pos]++; } } else{ cells[pos]++; } } else if(pos == p1_cell_end){//at the end of player's row, add to mancala and begin iterating backwards p1_mancala++; pos = p2_cell_end + 1; } else{//at other player's side add to their cell and iterate if(pos == p2_cell_start){//reset to bottom cell pos = p1_cell_start; if(num_moves == 1){//ending on own side (check if cell is empty) if(cells[pos] == 0){ p1_mancala += cells[pos + num_cells]; cells[pos + num_cells] = 0; cells[pos] = 0; p1_mancala ++; } else{ cells[pos]++; } } else{ cells[pos]++; } } else{ pos--; cells[pos]++; } } num_moves--; } if(pos == p2_cell_end + 1)//bonus move! { if(moves_available(player) > 0){ return true; } else{ checkGameOver(player); } } } else if(player == 2){ if(cell >= num_cells || cell < 0){ std::cout << "Invalid move for p2" << std::endl; return false; } cell = cell + num_cells;//convert to upper cell location in internal state representation int num_moves = cells[cell]; cells[cell] = 0; int pos = cell;//current position during iteration //A move involves placing a stone into the next cell and updating position accordingly while(num_moves > 0){ if(pos > p2_cell_start){//iterating through player's own cells (CCW => negative) pos--; if(num_moves == 1){ if(cells[pos] == 0){//ending in void cell on own side p2_mancala += cells[pos - num_cells]; cells[pos - num_cells] = 0; cells[pos] = 0; p2_mancala++; } else{ cells[pos]++; } } else{ cells[pos]++; } } else if(pos == p2_cell_start){//at the end of the player's row, add to mancala and begin iterating forwards p2_mancala++; pos = p1_cell_start - 1; } else{//on p1's side increment forwards if(pos == p1_cell_end){//reset to top cell pos = p2_cell_end; if(num_moves == 1){ if(cells[pos] == 0){ p2_mancala += cells[pos - num_cells]; cells[pos - num_cells] = 0; cells[pos] = 0; p2_mancala++; } else{ cells[pos]++; } } else{ cells[pos]++; } } else{ pos++; cells[pos]++; } } num_moves--; } if(pos == p1_cell_start - 1){//bonus move! if(moves_available(player) > 0){ return true; } else{ checkGameOver(player); } } } return false;//performed action with no bonus move }