void Game::play(Directions direction) { if (!can_play()) return; play_event pl_event = m_client.play(direction); if (pl_event.played()) { process_play(pl_event); m_window.update_score(std::to_string(m_score) + (m_won ? " (Won)" : "")); } }
//https://en.wikipedia.org/wiki/Negamax#Negamax_with_alpha_beta_pruning int negamax(Game *game, int alpha, int beta, int depth, int *best) { int j; //current column int cut = 0; //did we get a CUT at some point? int best_score = DEFEAT; //best score we've seen so far int one_decision = 0; //have we ever taken a real decision? if (!depth) return CUT; //the search space is often way too large for (j=0; j<game->cols; j++) { if (can_play(game, j)) { play(game, j); { int v; if (victory(game, j)) //this has to be done here v = VICTORY; //since the last move is unknown... else { int trash; //we don't care about the next move v = -negamax(game, -beta, -alpha, depth-1, &trash); } if (-v == CUT) //check the original return value cut = 1; else { v /= 2; //so, longer paths are less interesting one_decision = 1; //update best* variables if (best_score < v) { best_score = v; *best = j; } alpha = MAX(alpha, v); } } undo(game, j); if (alpha >= beta) break; //prune } } return (!one_decision && cut) ? CUT : best_score; }
enum plugin_status plugin_start(const void* parameter) { int button; int i; (void)parameter; if (!can_play()) { rb->splash(4*HZ, "No track to resume! This plugin will resume a track " "at a specific time. Therefore, you need to first play" " one, and then pause it and start the plugin again."); quit = true; } while(!quit) { button = get_button(); if (button == PLA_EXIT || button == PLA_CANCEL) quit = true; FOR_NB_SCREENS(i) { draw(rb->screens[i]); } if (waiting) { if (rem_seconds() <= 0) { quit = done = true; play(); } } else { switch (button) { case PLA_UP: case PLA_UP_REPEAT: #ifdef HAVE_SCROLLWHEEL case PLA_SCROLL_FWD: case PLA_SCROLL_FWD_REPEAT: #endif alarm[current] = (alarm[current] + 1) % maxval[current]; break; case PLA_DOWN: case PLA_DOWN_REPEAT: #ifdef HAVE_SCROLLWHEEL case PLA_SCROLL_BACK: case PLA_SCROLL_BACK_REPEAT: #endif alarm[current] = (alarm[current] + maxval[current] - 1) % maxval[current]; break; case PLA_LEFT: case PLA_LEFT_REPEAT: case PLA_RIGHT: case PLA_RIGHT_REPEAT: current = (current + 1) % 2; break; case PLA_SELECT: case PLA_SELECT_REPEAT: { if (rem_seconds() < 0) tomorrow = true; waiting = true; break; } default: if (rb->default_event_handler(button) == SYS_USB_CONNECTED) quit = usb = true; break; } } } return (usb) ? PLUGIN_USB_CONNECTED : (done ? PLUGIN_GOTO_WPS : PLUGIN_OK); }
/* Program extracts from Chapter 5 of
enum plugin_status plugin_start(const void* parameter) { int button; int i; (void)parameter; if (!can_play()) { rb->splash(HZ*2, "No track to resume! " "Play or pause one first."); return PLUGIN_ERROR; } pause(); while(!quit) { button = get_button(); if (button == PLA_EXIT || button == PLA_CANCEL) quit = true; FOR_NB_SCREENS(i) { draw(rb->screens[i]); } if (waiting) { if (rem_seconds() <= 0) { quit = done = true; play(); } } else { switch (button) { case PLA_UP: case PLA_UP_REPEAT: #ifdef HAVE_SCROLLWHEEL case PLA_SCROLL_FWD: case PLA_SCROLL_FWD_REPEAT: #endif alarm[current] = (alarm[current] + 1) % maxval[current]; break; case PLA_DOWN: case PLA_DOWN_REPEAT: #ifdef HAVE_SCROLLWHEEL case PLA_SCROLL_BACK: case PLA_SCROLL_BACK_REPEAT: #endif alarm[current] = (alarm[current] + maxval[current] - 1) % maxval[current]; break; case PLA_LEFT: case PLA_LEFT_REPEAT: case PLA_RIGHT: case PLA_RIGHT_REPEAT: current = (current + 1) % 2; break; case PLA_SELECT: case PLA_SELECT_REPEAT: { if (rem_seconds() < 0) tomorrow = true; waiting = true; break; } default: if (rb->default_event_handler(button) == SYS_USB_CONNECTED) quit = usb = true; break; } } } return (usb) ? PLUGIN_USB_CONNECTED : (done ? PLUGIN_GOTO_WPS : PLUGIN_OK); }
int main(void) { board* b = (board*)malloc(sizeof(board)); char** moves = (char**)malloc(SQS_NB*sizeof(char*)); int /*i, moves_nb = 0,*/ directions=0; /* char* initial_moves_b[] = {"E6", "F5", "C4", "D3"}; char* initial_moves_w[] = {"E3", "F4", "C5", "D6"}; */ char piece = '\0'; assert(init_board(b) == 0); /* initial scores*/ assert(get_score(b, WHITE_C) == 2); assert(get_score(b, BLACK_C) == 2); /* /\* possible first moves with white (this is a test, not a normal game) *\/ moves_nb = get_possible_moves(b, WHITE_C, &moves); assert(moves_nb == 4); assert(moves != NULL); assert(compare_moves_arrays(moves, initial_moves_w, moves_nb)); for (i=0; i<moves_nb; i++) { free(moves[i]); moves[i] = NULL; } /\* possible first moves with black *\/ moves_nb = get_possible_moves(b, BLACK_C, &moves); assert(moves_nb == 4); assert(moves != NULL); assert(compare_moves_arrays(moves, initial_moves_b, moves_nb)); for (i=0; i<moves_nb; i++) { free(moves[i]); moves[i] = NULL; } */ /* check if black can play in E6*/ assert(can_play(b, 4, 5, BLACK_C, &directions) == 1); assert(can_play(b, 4, 5, BLACK_C, NULL) == 1); assert(directions == CAN_PLAY_DOWN); /* test a move: * P: player (WHITE_C or BLACK_C) * S: square (e.g. "E6") * SC: score made with this move * SCW: score for white player * SCB: score for black player */ #define T_MOVE(P,S,SC,SCW,SCB) assert(play(b,P,S) == SC); \ assert(get_score(b, WHITE_C) == SCW); \ assert(get_score(b, BLACK_C) == SCB); \ assert(get_piece(b, S, &piece) == 0); \ assert(piece == P) /* black plays in E6*/ T_MOVE(BLACK_C,"E6",2,1,4); /* white plays in F4*/ T_MOVE(WHITE_C,"F4",2,3,3); /* black plays in E3*/ T_MOVE(BLACK_C,"E3",2,2,5); /* white plays in F6*/ T_MOVE(WHITE_C,"F6",2,4,4); /* black plays in F5*/ T_MOVE(BLACK_C,"F5",2,3,6); /* white plays in D6*/ T_MOVE(WHITE_C,"D6",4,7,3); /* black plays in C6*/ T_MOVE(BLACK_C,"C6",2,6,5); /* white plays in G5*/ T_MOVE(WHITE_C,"G5",2,8,4); /* black plays in G6*/ T_MOVE(BLACK_C,"G6",5,4,9); /* white plays in C5*/ T_MOVE(WHITE_C,"C5",2,6,8); /* black plays in C4*/ T_MOVE(BLACK_C,"C4",4,3,12); /* white plays in G7*/ T_MOVE(WHITE_C,"G7",3,6,10); /* black plays in H8 */ T_MOVE(BLACK_C,"H8",4,3,14); /* white plays in C7 */ T_MOVE(WHITE_C,"C7",3,6,12); /* black plays in G4 */ T_MOVE(BLACK_C,"G4",4,3,16); /* white plays in G3 */ T_MOVE(WHITE_C,"G3",2,5,15); /* black plays in F3 */ T_MOVE(BLACK_C,"F3",2,4,17); /* white plays in B4 */ T_MOVE(WHITE_C,"B4",2,6,16); /* black plays in G2 */ T_MOVE(BLACK_C,"G2",2,5,18); /* white plays in H2 */ T_MOVE(WHITE_C,"H2",3,8,16); /* black plays in H3 */ T_MOVE(BLACK_C,"H3",2,7,18); /* white plays in H6 */ T_MOVE(WHITE_C,"H6",5,12,14); /* black plays in H7 */ T_MOVE(BLACK_C,"H7",2,11,16); /* white plays in H4 */ T_MOVE(WHITE_C,"H4",3,14,14); /* black plays in H5 */ T_MOVE(BLACK_C,"H5",4,11,18); /* white plays in F2 */ T_MOVE(WHITE_C,"F2",6,17,13); /* black plays in H1 */ T_MOVE(BLACK_C,"H1",6,12,19); /* white plays in C3 */ T_MOVE(WHITE_C,"C3",2,14,18); /* black plays in A4 */ T_MOVE(BLACK_C,"A4",4,11,22); /* white plays in D3 */ T_MOVE(WHITE_C,"D3",3,14,20); free(moves); free(b); return 0; }
int main(int argc, char *argv[]) { Game *game = create_game(ROWS, COLS); if (argc==3 && !strcmp(argv[1], "display")) { char *p = argv[2]; char *err; while (*p) { int col = *p - '0'; if (col>=0 && col<COLS) { if (can_play(game, col)) { play(game, col); if (victory(game, col)) printf("victory!\n"); } else { err = "illegal move"; goto err_handler; } } else { int i; err = "unknown move syntax"; err_handler: fprintf(stderr, "error: %s.\n%s\n", err, argv[2]); for (i=0; i<p-argv[2]; i++) fprintf(stderr, " "); fprintf(stderr, "^\n"); return 2; } p++; } print_board(game); } else if ((argc==2 || argc==3) && !strcmp(argv[1], "play")) { int j; if (argc==3 && !strcmp(argv[2], "red")) goto red; while (1) { print_board(game); do { printf("Your move: "); if (scanf("%d", &j) != 1) { printf("\n"); goto out; } } while (!can_play(game, j)); play(game, j); if (victory(game, j)) { printf("You've won!\n"); break; } else { int ret = negamax(game, DEFEAT, VICTORY, 12, &j); red: if (ret == CUT) printf("I've got no idea what to do...\n" "I'm gonna try %d.\n", j); else printf("I'll play %d (score %d)\n", j, ret); play(game, j); if (victory(game, j)) { printf("You've lost!\n"); break; } } } print_board(game); } else { fprintf(stderr, "usage:\t%s display moves\n", argv[0]); fprintf(stderr, "\t%s play [yellow|red]\n", argv[0]); fprintf(stderr, "try:\t%s display 01221\n", argv[0]); fprintf(stderr, "\t%s play\n", argv[0]); return 1; } out: destroy_game(game); return 0; }