Przeglądaj źródła

Squashed 'reversi/' changes from 2250e48d9..d0e05bc5d

d0e05bc5d fixing some big bugs
d54991381 bump versions and set bt trigger to use keys from ble remote
155f2f9dd fix plugins, remove dupe
d8333fc10 categories part 1
9f1155448 more manifestos, xbox controller and videopoker ufbt fixes
96a9ab34a Add Screenshots
dea4ea289 API 31 / unzip sources
REVERT: 2250e48d9 Switch from ValueMutex to furi_mutex
REVERT: 54b6667ed bugfix: correctly handle menu states
REVERT: a093cba29 Upload artifacts from GitHub Actions
REVERT: a87ac1fc9 Merge pull request #1 from dimat/actions
REVERT: bd9731412 fix compiler warnings
REVERT: c0b810c8c Integrate GitHub actions
REVERT: 694d62360 cleanup: reduce indentation
REVERT: 03e22baaa Screenshot for game over
REVERT: 88ecbdd7c Flipper Zero GUI
REVERT: 7a829002c initial working version in text mode and not refactored

git-subtree-dir: reversi
git-subtree-split: d0e05bc5dccd1fdb319a7f16999b184914a4de6b
Willy-JL 2 lat temu
rodzic
commit
4dc156de3a
8 zmienionych plików z 385 dodań i 383 usunięć
  1. 0 2
      .gitignore
  2. 7 2
      application.fam
  3. 248 238
      game_reversi.c
  4. BIN
      img/1.png
  5. BIN
      img/2.png
  6. BIN
      img/3.png
  7. 122 133
      reversi.c
  8. 8 8
      reversi.h

+ 0 - 2
.gitignore

@@ -1,2 +0,0 @@
-reversi
-compile_flags.txt

+ 7 - 2
application.fam

@@ -1,5 +1,5 @@
 App(
-    appid="game_reversi",
+    appid="reversi",
     name="Reversi",
     apptype=FlipperAppType.EXTERNAL,
     entry_point="game_reversi_app",
@@ -10,5 +10,10 @@ App(
     stack_size=1 * 1024,
     order=90,
     fap_icon="game_reversi.png",
-    fap_category="Games"
+    fap_category="Games",
+    fap_icon_assets_symbol="game_reversi",
+    fap_author="@dimat",
+    fap_weburl="https://github.com/zyuhel/flipperzero-racegame",
+    fap_version="1.2",
+    fap_description="Reversi game, the game controls should be intuitive. Longs press on OK opens the menu to start a new game.",
 )

+ 248 - 238
game_reversi.c

@@ -15,16 +15,13 @@
 #define SAVING_DIRECTORY "/ext/apps/Games"
 #define SAVING_FILENAME SAVING_DIRECTORY "/game_reversi.save"
 
-typedef enum {
-  AppScreenGame,
-  AppScreenMenu
-} AppScreen;
+typedef enum { AppScreenGame, AppScreenMenu } AppScreen;
 
 typedef struct {
-  GameState game;
-  AppScreen screen;
-  uint8_t selected_menu_item;
-  FuriMutex* mutex;
+    GameState game;
+    AppScreen screen;
+    uint8_t selected_menu_item;
+    FuriMutex* mutex;
 } AppState;
 
 #define MENU_ITEMS_COUNT 2
@@ -39,120 +36,128 @@ static void input_callback(InputEvent* input_event, void* ctx) {
     furi_message_queue_put(event_queue, input_event, FuriWaitForever);
 }
 
-static void draw_callback(Canvas *const canvas, void *ctx) {
-  furi_assert(ctx);
-
-  const AppState *app_state = ctx;
-  furi_mutex_acquire(app_state->mutex, FuriWaitForever);
-  if (app_state == NULL)
-    return;
-  const GameState *game_state = &app_state->game;
-
-  canvas_clear(canvas);
-  canvas_set_color(canvas, ColorBlack);
-
-  for (uint8_t i = 0; i <= BOARD_SIZE; i++) {
-    canvas_draw_line(canvas, FRAME_LEFT + FRAME_CELL_SIZE * i, FRAME_TOP,
-                     FRAME_LEFT + FRAME_CELL_SIZE * i,
-                     FRAME_TOP + FRAME_CELL_SIZE * BOARD_SIZE);
-    canvas_draw_line(canvas, FRAME_LEFT, FRAME_TOP + FRAME_CELL_SIZE * i,
-                     FRAME_LEFT + FRAME_CELL_SIZE * BOARD_SIZE,
-                     FRAME_TOP + FRAME_CELL_SIZE * i);
-  }
-  //
-  // draw cursor
-  canvas_set_color(canvas, ColorWhite);
-  canvas_draw_frame(canvas, FRAME_LEFT + FRAME_CELL_SIZE * game_state->cursor_x,
-                    FRAME_TOP + FRAME_CELL_SIZE * game_state->cursor_y,
-                    FRAME_CELL_SIZE + 1, FRAME_CELL_SIZE + 1);
-
-  canvas_set_color(canvas, ColorBlack);
-  // draw pieces
-  int blacks = 0, whites = 0;
-  const int radius = FRAME_CELL_SIZE >> 1;
-  for (uint8_t i = 0; i < BOARD_SIZE; i++) {
-    for (uint8_t j = 0; j < BOARD_SIZE; j++) {
-      if (!game_state->board[i][j]) {
-        continue;
-      }
-      if (game_state->board[i][j] == BLACK) {
-        canvas_draw_disc(
-            canvas, 
-            FRAME_LEFT + FRAME_CELL_SIZE * i + radius + 1,
-            FRAME_TOP + FRAME_CELL_SIZE * j + radius + 1, 
-            radius);
-        blacks++;
-      } else {
-        canvas_draw_circle(
-            canvas, 
-            FRAME_LEFT + FRAME_CELL_SIZE * i + radius + 1,
-            FRAME_TOP + FRAME_CELL_SIZE * j + radius + 1, 
-            radius);
-        whites++;
-      }
+static void draw_callback(Canvas* const canvas, void* ctx) {
+    furi_assert(ctx);
+    const AppState* app_state = ctx;
+    furi_mutex_acquire(app_state->mutex, FuriWaitForever);
+
+    const GameState* game_state = &app_state->game;
+
+    canvas_clear(canvas);
+    canvas_set_color(canvas, ColorBlack);
+
+    for(uint8_t i = 0; i <= BOARD_SIZE; i++) {
+        canvas_draw_line(
+            canvas,
+            FRAME_LEFT + FRAME_CELL_SIZE * i,
+            FRAME_TOP,
+            FRAME_LEFT + FRAME_CELL_SIZE * i,
+            FRAME_TOP + FRAME_CELL_SIZE * BOARD_SIZE);
+        canvas_draw_line(
+            canvas,
+            FRAME_LEFT,
+            FRAME_TOP + FRAME_CELL_SIZE * i,
+            FRAME_LEFT + FRAME_CELL_SIZE * BOARD_SIZE,
+            FRAME_TOP + FRAME_CELL_SIZE * i);
+    }
+    //
+    // draw cursor
+    canvas_set_color(canvas, ColorWhite);
+    canvas_draw_frame(
+        canvas,
+        FRAME_LEFT + FRAME_CELL_SIZE * game_state->cursor_x,
+        FRAME_TOP + FRAME_CELL_SIZE * game_state->cursor_y,
+        FRAME_CELL_SIZE + 1,
+        FRAME_CELL_SIZE + 1);
+
+    canvas_set_color(canvas, ColorBlack);
+    // draw pieces
+    int blacks = 0, whites = 0;
+    const int radius = FRAME_CELL_SIZE >> 1;
+    for(uint8_t i = 0; i < BOARD_SIZE; i++) {
+        for(uint8_t j = 0; j < BOARD_SIZE; j++) {
+            if(!game_state->board[i][j]) {
+                continue;
+            }
+            if(game_state->board[i][j] == BLACK) {
+                canvas_draw_disc(
+                    canvas,
+                    FRAME_LEFT + FRAME_CELL_SIZE * i + radius + 1,
+                    FRAME_TOP + FRAME_CELL_SIZE * j + radius + 1,
+                    radius);
+                blacks++;
+            } else {
+                canvas_draw_circle(
+                    canvas,
+                    FRAME_LEFT + FRAME_CELL_SIZE * i + radius + 1,
+                    FRAME_TOP + FRAME_CELL_SIZE * j + radius + 1,
+                    radius);
+                whites++;
+            }
+        }
     }
-  }
-
-  canvas_set_font(canvas, FontPrimary);
-  // draw score
-  char score_str[25];
-  memset(score_str, 0, sizeof(score_str));
-  snprintf(score_str, sizeof(score_str), "%d - %d", whites, blacks);
-
-  canvas_draw_str_aligned(canvas, 70, 3, AlignLeft, AlignTop, score_str);
-
-  canvas_set_font(canvas, FontSecondary);
-  if (game_state->is_game_over) {
-    canvas_draw_str_aligned(canvas, 70, 20, AlignLeft, AlignTop, "Game over");
-
-    canvas_draw_str_aligned(canvas, 
-        70, 
-        FRAME_TOP + FRAME_CELL_SIZE * BOARD_SIZE, 
-        AlignLeft, AlignBottom, 
-        "Press OK");
 
     canvas_set_font(canvas, FontPrimary);
-
-    if (whites == blacks) {
-      canvas_draw_str_aligned(canvas, 70, 30, AlignLeft, AlignTop, "DRAW");
-    } else if (((game_state->human_color == WHITE) && whites > blacks) ||
-               ((game_state->human_color == BLACK) && blacks > whites)) {
-      canvas_draw_str_aligned(canvas, 70, 30, AlignLeft, AlignTop, "YOU WIN");
+    // draw score
+    char score_str[25];
+    memset(score_str, 0, sizeof(score_str));
+    snprintf(score_str, sizeof(score_str), "%d - %d", whites, blacks);
+
+    canvas_draw_str_aligned(canvas, 70, 3, AlignLeft, AlignTop, score_str);
+
+    canvas_set_font(canvas, FontSecondary);
+    if(game_state->is_game_over) {
+        canvas_draw_str_aligned(canvas, 70, 20, AlignLeft, AlignTop, "Game over");
+
+        canvas_draw_str_aligned(
+            canvas,
+            70,
+            FRAME_TOP + FRAME_CELL_SIZE * BOARD_SIZE,
+            AlignLeft,
+            AlignBottom,
+            "Press OK");
+
+        canvas_set_font(canvas, FontPrimary);
+
+        if(whites == blacks) {
+            canvas_draw_str_aligned(canvas, 70, 30, AlignLeft, AlignTop, "DRAW");
+        } else if(
+            ((game_state->human_color == WHITE) && whites > blacks) ||
+            ((game_state->human_color == BLACK) && blacks > whites)) {
+            canvas_draw_str_aligned(canvas, 70, 30, AlignLeft, AlignTop, "YOU WIN");
+        } else {
+            canvas_draw_str_aligned(canvas, 70, 30, AlignLeft, AlignTop, "YOU LOSE");
+        }
+    } else if(game_state->current_player == game_state->human_color) {
+        canvas_draw_str_aligned(canvas, 70, 12, AlignLeft, AlignTop, "Your turn");
     } else {
-      canvas_draw_str_aligned(canvas, 70, 30, AlignLeft, AlignTop, "YOU LOSE");
+        canvas_draw_str_aligned(canvas, 70, 12, AlignLeft, AlignTop, "Computer turn");
     }
-  } else if (game_state->current_player == game_state->human_color) {
-    canvas_draw_str_aligned(canvas, 70, 12, AlignLeft, AlignTop, "Your turn");
-  } else {
-    canvas_draw_str_aligned(canvas, 70, 12, AlignLeft, AlignTop,
-                            "Computer turn");
-  }
-
-  if (app_state->screen == AppScreenMenu) {
-    draw_menu(canvas, app_state);
-  }
-
-  furi_mutex_release(app_state->mutex);
+
+    if(app_state->screen == AppScreenMenu) {
+        draw_menu(canvas, app_state);
+    }
+
+    furi_mutex_release(app_state->mutex);
 }
 
 static void draw_menu(Canvas* const canvas, const AppState* app_state) {
-  gray_canvas(canvas);
-  canvas_set_color(canvas, ColorWhite);
-  canvas_draw_rbox(canvas, 28, 16, 72, 32, 4);
-  canvas_set_color(canvas, ColorBlack);
-  canvas_draw_rframe(canvas, 28, 16, 72, 32, 4);
-
-  for (int i = 0; i < MENU_ITEMS_COUNT; i++) {
-    if (i == app_state->selected_menu_item) {
-      canvas_set_color(canvas, ColorBlack);
-      canvas_draw_box(canvas, 34, 20 + 12 * i, 60, 12);
-    }
+    gray_canvas(canvas);
+    canvas_set_color(canvas, ColorWhite);
+    canvas_draw_rbox(canvas, 28, 16, 72, 32, 4);
+    canvas_set_color(canvas, ColorBlack);
+    canvas_draw_rframe(canvas, 28, 16, 72, 32, 4);
+
+    for(int i = 0; i < MENU_ITEMS_COUNT; i++) {
+        if(i == app_state->selected_menu_item) {
+            canvas_set_color(canvas, ColorBlack);
+            canvas_draw_box(canvas, 34, 20 + 12 * i, 60, 12);
+        }
 
-    canvas_set_color(canvas, i == app_state->selected_menu_item ? ColorWhite
-                                                                : ColorBlack);
-    canvas_draw_str_aligned(canvas, 64, 26 + 12 * i, AlignCenter, AlignCenter,
-                            popup_menu_strings[i]);
-  }
+        canvas_set_color(canvas, i == app_state->selected_menu_item ? ColorWhite : ColorBlack);
+        canvas_draw_str_aligned(
+            canvas, 64, 26 + 12 * i, AlignCenter, AlignCenter, popup_menu_strings[i]);
+    }
 }
 
 static void gray_canvas(Canvas* const canvas) {
@@ -199,151 +204,156 @@ void save_game(const GameState* game_state) {
     furi_record_close(RECORD_STORAGE);
 }
 
-bool handle_key_game(GameState *game_state, InputKey key) {
-  switch (key) {
-  case InputKeyBack:
-    save_game(game_state);
-    return false;
-    break;
-  case InputKeyOk:
-    if (game_state->is_game_over) {
-      init_game(game_state);
-      save_game(game_state);
-    } else {
-      human_move(game_state);
-    }
-    break;
-  case InputKeyUp:
-    if (game_state->cursor_y > 0) {
-      game_state->cursor_y--;
-    } else {
-      game_state->cursor_y = BOARD_SIZE - 1;
-    }
-    break;
-  case InputKeyDown:
-    if (game_state->cursor_y < BOARD_SIZE - 1) {
-      game_state->cursor_y++;
-    } else {
-      game_state->cursor_y = 0;
-    }
-    break;
-  case InputKeyLeft:
-    if (game_state->cursor_x > 0) {
-      game_state->cursor_x--;
-    } else {
-      game_state->cursor_x = BOARD_SIZE - 1;
-    }
-    break;
-  case InputKeyRight:
-    if (game_state->cursor_x < BOARD_SIZE - 1) {
-      game_state->cursor_x++;
-    } else {
-      game_state->cursor_x = 0;
+bool handle_key_game(GameState* game_state, InputKey key) {
+    switch(key) {
+    case InputKeyBack:
+        save_game(game_state);
+        return false;
+        break;
+    case InputKeyOk:
+        if(game_state->is_game_over) {
+            init_game(game_state);
+            save_game(game_state);
+        } else {
+            human_move(game_state);
+        }
+        break;
+    case InputKeyUp:
+        if(game_state->cursor_y > 0) {
+            game_state->cursor_y--;
+        } else {
+            game_state->cursor_y = BOARD_SIZE - 1;
+        }
+        break;
+    case InputKeyDown:
+        if(game_state->cursor_y < BOARD_SIZE - 1) {
+            game_state->cursor_y++;
+        } else {
+            game_state->cursor_y = 0;
+        }
+        break;
+    case InputKeyLeft:
+        if(game_state->cursor_x > 0) {
+            game_state->cursor_x--;
+        } else {
+            game_state->cursor_x = BOARD_SIZE - 1;
+        }
+        break;
+    case InputKeyRight:
+        if(game_state->cursor_x < BOARD_SIZE - 1) {
+            game_state->cursor_x++;
+        } else {
+            game_state->cursor_x = 0;
+        }
+        break;
+    default:
+        break;
     }
-    break;
-  default:
-    break;
-  }
-  return true;
+    return true;
 }
 
-bool handle_key_menu(AppState *app_state, InputKey key) {
-  switch (key) {
-  case InputKeyUp:
-    if (app_state->selected_menu_item > 0) {
-      app_state->selected_menu_item--;
-    }
-    break;
-  case InputKeyDown:
-    if (app_state->selected_menu_item < MENU_ITEMS_COUNT - 1) {
-      app_state->selected_menu_item++;
-    }
-    break;
-  case InputKeyOk:
-    if (app_state->selected_menu_item == 1) {
-      // new game
-      init_game(&app_state->game);
-      save_game(&app_state->game);
+bool handle_key_menu(AppState* app_state, InputKey key) {
+    switch(key) {
+    case InputKeyUp:
+        if(app_state->selected_menu_item > 0) {
+            app_state->selected_menu_item--;
+        }
+        break;
+    case InputKeyDown:
+        if(app_state->selected_menu_item < MENU_ITEMS_COUNT - 1) {
+            app_state->selected_menu_item++;
+        }
+        break;
+    case InputKeyOk:
+        if(app_state->selected_menu_item == 1) {
+            // new game
+            init_game(&app_state->game);
+            save_game(&app_state->game);
+        }
+        app_state->screen = AppScreenGame;
+        break;
+    default:
+        break;
     }
-    app_state->screen = AppScreenGame;
-    break;
-  default:
-    break;
-  }
-  return true;
+    return true;
 }
 
 // returns `true` if the event loop should keep going
 bool handle_key(AppState* app_state, InputKey key) {
-  GameState* game_state = &app_state->game;
+    GameState* game_state = &app_state->game;
 
-  switch (app_state->screen) {
+    switch(app_state->screen) {
     case AppScreenGame:
-      return handle_key_game(game_state, key);
-      break;
+        return handle_key_game(game_state, key);
+        break;
     case AppScreenMenu:
-      return handle_key_menu(app_state, key);
-      break;
-  }
-  return true;
+        return handle_key_menu(app_state, key);
+        break;
+    }
+    return true;
 }
 
 int32_t game_reversi_app() {
-  AppState app_state;
-  app_state.screen = AppScreenGame;
-  if (!load_game(&app_state.game)) {
-    init_game(&app_state.game);
-  }
-
-  app_state.mutex = furi_mutex_alloc(FuriMutexTypeNormal);
-  if (!app_state.mutex) {
-    return 255;
-  }
-  InputEvent input;
-  FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
-
-  ViewPort* view_port = view_port_alloc();
-  view_port_draw_callback_set(view_port, draw_callback, &app_state);
-  view_port_input_callback_set(view_port, input_callback, event_queue);
-
-  Gui* gui = furi_record_open(RECORD_GUI);
-  gui_add_view_port(gui, view_port, GuiLayerFullscreen);
-  bool is_finished = false;
-
-  while(!is_finished) {
-    // check if it's computer's turn
-    if (!app_state.game.is_game_over && (app_state.game.current_player != app_state.game.human_color)) {
-      computer_move(&app_state.game);
+    AppState app_state;
+    app_state.screen = AppScreenGame;
+    if(!load_game(&app_state.game)) {
+        init_game(&app_state.game);
+    }
+
+    app_state.mutex = furi_mutex_alloc(FuriMutexTypeNormal);
+    if(!app_state.mutex) {
+        return 255;
     }
-    FuriStatus event_status = furi_message_queue_get(event_queue, &input, FuriWaitForever);
-    if(event_status == FuriStatusOk) {
-      // handle only press event, ignore repeat/release events
-
-      if (input.type == InputTypeLong && input.key == InputKeyOk && app_state.screen == AppScreenGame) {
-        furi_mutex_acquire(app_state.mutex, FuriWaitForever);
-        app_state.selected_menu_item = 0;
-        app_state.screen = AppScreenMenu;
+    InputEvent input;
+    FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
+
+    ViewPort* view_port = view_port_alloc();
+    view_port_draw_callback_set(view_port, draw_callback, &app_state);
+    view_port_input_callback_set(view_port, input_callback, event_queue);
+
+    Gui* gui = furi_record_open(RECORD_GUI);
+    gui_add_view_port(gui, view_port, GuiLayerFullscreen);
+    bool is_finished = false;
+
+    while(!is_finished) {
+        // check if it's computer's turn
+        if(!app_state.game.is_game_over &&
+           (app_state.game.current_player != app_state.game.human_color)) {
+            computer_move(&app_state.game);
+        }
+        FuriStatus event_status = furi_message_queue_get(event_queue, &input, 100);
+        if(event_status == FuriStatusOk) {
+            // handle only press event, ignore repeat/release events
+
+            if(input.type == InputTypeLong && input.key == InputKeyOk &&
+               app_state.screen == AppScreenGame) {
+                furi_mutex_acquire(app_state.mutex, FuriWaitForever);
+                app_state.selected_menu_item = 0;
+                app_state.screen = AppScreenMenu;
+                
+                furi_mutex_release(app_state.mutex);
+                view_port_update(view_port);
+                continue;
+            }
+            if(input.type != InputTypePress) continue;
+
+            furi_mutex_acquire(app_state.mutex, FuriWaitForever);
+            is_finished = !handle_key(&app_state, input.key);
+
+            furi_mutex_release(app_state.mutex);
+            view_port_update(view_port);
+        }
         view_port_update(view_port);
-        furi_mutex_release(app_state.mutex);
-        continue;
-      }
-      if (input.type != InputTypePress) continue;
-
-      furi_mutex_acquire(app_state.mutex, FuriWaitForever);
-      is_finished = !handle_key(&app_state, input.key);
-      view_port_update(view_port);
-      furi_mutex_release(app_state.mutex);
     }
-  }
 
-  gui_remove_view_port(gui, view_port);
-  furi_record_close(RECORD_GUI);
+    gui_remove_view_port(gui, view_port);
+    furi_record_close(RECORD_GUI);
 
-  view_port_free(view_port);
+    view_port_free(view_port);
 
-  furi_message_queue_free(event_queue);
+    furi_message_queue_free(event_queue);
 
-  furi_mutex_free(app_state.mutex);
+    furi_mutex_free(app_state.mutex);
 
-  return 0;
+    return 0;
 }

BIN
img/1.png


BIN
img/2.png


BIN
img/3.png


+ 122 - 133
reversi.c

@@ -6,174 +6,163 @@
 // Psst! Most of this file was written with Copilot
 
 // Check if the move is legal by checking if it results in any opponent pieces being captured
-bool is_legal_move(int8_t board[BOARD_SIZE][BOARD_SIZE], int row, int col,
-                   int player) {
-  if (board[row][col] != 0)
-    return false;
-  int opponent = -player;
-  for (int i = -1; i <= 1; i++) {
-    for (int j = -1; j <= 1; j++) {
-      if (i == 0 && j == 0)
-        continue;
-      int r = row + i, c = col + j;
-      if (r >= 0 && r < BOARD_SIZE && c >= 0 && c < BOARD_SIZE &&
-          board[r][c] == opponent) {
-        int k = 2;
-        while (true) {
-          r += i;
-          c += j;
-          if (r < 0 || r >= BOARD_SIZE || c < 0 || c >= BOARD_SIZE)
-            break;
-          if (board[r][c] == player)
-            return true;
-          if (board[r][c] == 0)
-            break;
-          k++;
+bool is_legal_move(int8_t board[BOARD_SIZE][BOARD_SIZE], int row, int col, int player) {
+    if(board[row][col] != 0) return false;
+    int opponent = -player;
+    for(int i = -1; i <= 1; i++) {
+        for(int j = -1; j <= 1; j++) {
+            if(i == 0 && j == 0) continue;
+            int r = row + i, c = col + j;
+            if(r >= 0 && r < BOARD_SIZE && c >= 0 && c < BOARD_SIZE && board[r][c] == opponent) {
+                int k = 2;
+                while(true) {
+                    r += i;
+                    c += j;
+                    if(r < 0 || r >= BOARD_SIZE || c < 0 || c >= BOARD_SIZE) break;
+                    if(board[r][c] == player) return true;
+                    if(board[r][c] == 0) break;
+                    k++;
+                }
+            }
         }
-      }
     }
-  }
-  return false;
+    return false;
 }
 
 // Check if the game is over by checking if there are no more moves left for
 // either player
 bool is_game_over(int8_t board[BOARD_SIZE][BOARD_SIZE]) {
-  for (int i = 0; i < BOARD_SIZE; i++) {
-    for (int j = 0; j < BOARD_SIZE; j++) {
-      if (is_legal_move(board, i, j, BLACK) ||
-          is_legal_move(board, i, j, WHITE)) {
-        return false;
-      }
+    for(int i = 0; i < BOARD_SIZE; i++) {
+        for(int j = 0; j < BOARD_SIZE; j++) {
+            if(is_legal_move(board, i, j, BLACK) || is_legal_move(board, i, j, WHITE)) {
+                return false;
+            }
+        }
     }
-  }
-  return true;
+    return true;
 }
 
-bool has_legal_moves(int8_t board[BOARD_SIZE][BOARD_SIZE],
-                     int8_t player_color) {
-  for (int i = 0; i < BOARD_SIZE; i++) {
-    for (int j = 0; j < BOARD_SIZE; j++) {
-      if (is_legal_move(board, i, j, player_color)) {
-        return true;
-      }
+bool has_legal_moves(int8_t board[BOARD_SIZE][BOARD_SIZE], int8_t player_color) {
+    for(int i = 0; i < BOARD_SIZE; i++) {
+        for(int j = 0; j < BOARD_SIZE; j++) {
+            if(is_legal_move(board, i, j, player_color)) {
+                return true;
+            }
+        }
     }
-  }
-  return false;
+    return false;
 }
 
 // Calculate the heuristic value of the current board. This function can
 // be replaced with a more complex evaluation function that takes into
 // account factors such as mobility, piece square tables, etc.
 int heuristic(int8_t board[BOARD_SIZE][BOARD_SIZE]) {
-  int white = 0, black = 0;
-  for (int i = 0; i < BOARD_SIZE; i++) {
-    for (int j = 0; j < BOARD_SIZE; j++) {
-      if (board[i][j] == 1)
-        white++;
-      if (board[i][j] == -1)
-        black++;
+    int white = 0, black = 0;
+    for(int i = 0; i < BOARD_SIZE; i++) {
+        for(int j = 0; j < BOARD_SIZE; j++) {
+            if(board[i][j] == 1) white++;
+            if(board[i][j] == -1) black++;
+        }
     }
-  }
-  return white - black;
+    return white - black;
 }
 
 // Make a move on the board and capture any opponent pieces
-void make_move(GameState *state, int x, int y, int player) {
-  state->board[x][y] = player;
-  int opponent = -player;
-  for (int i = -1; i <= 1; i++) {
-    for (int j = -1; j <= 1; j++) {
-      if (i == 0 && j == 0)
-        continue;
-      int r = x + i, c = y + j;
-      if (r >= 0 && r < BOARD_SIZE && c >= 0 && c < BOARD_SIZE &&
-          state->board[r][c] == opponent) {
-        int k = 2;
-        while (true) {
-          r += i;
-          c += j;
-          if (r < 0 || r >= BOARD_SIZE || c < 0 || c >= BOARD_SIZE)
-            break;
-          if (state->board[r][c] == player) {
-            r -= i;
-            c -= j;
-            while (r != x || c != y) {
-              state->board[r][c] = player;
-              r -= i;
-              c -= j;
+void make_move(GameState* state, int x, int y, int player) {
+    state->board[x][y] = player;
+    int opponent = -player;
+    for(int i = -1; i <= 1; i++) {
+        for(int j = -1; j <= 1; j++) {
+            if(i == 0 && j == 0) continue;
+            int r = x + i, c = y + j;
+            if(r >= 0 && r < BOARD_SIZE && c >= 0 && c < BOARD_SIZE &&
+               state->board[r][c] == opponent) {
+                int k = 2;
+                while(true) {
+                    r += i;
+                    c += j;
+                    if(r < 0 || r >= BOARD_SIZE || c < 0 || c >= BOARD_SIZE) break;
+                    if(state->board[r][c] == player) {
+                        r -= i;
+                        c -= j;
+                        while(r != x || c != y) {
+                            state->board[r][c] = player;
+                            r -= i;
+                            c -= j;
+                        }
+                        break;
+                    }
+                    if(state->board[r][c] == 0) break;
+                    k++;
+                }
             }
-            break;
-          }
-          if (state->board[r][c] == 0)
-            break;
-          k++;
         }
-      }
     }
-  }
-  state->is_game_over = is_game_over(state->board);
+    state->is_game_over = is_game_over(state->board);
 }
 
-void init_game(GameState *state) {
-  for (int i = 0; i < BOARD_SIZE; i++) {
-    for (int j = 0; j < BOARD_SIZE; j++) {
-      state->board[i][j] = 0;
+void init_game(GameState* state) {
+    for(int i = 0; i < BOARD_SIZE; i++) {
+        for(int j = 0; j < BOARD_SIZE; j++) {
+            state->board[i][j] = 0;
+        }
     }
-  }
 
-  // Place the initial pieces
-  int mid = BOARD_SIZE / 2;
-  state->board[mid - 1][mid - 1] = WHITE;
-  state->board[mid][mid] = WHITE;
-  state->board[mid - 1][mid] = BLACK;
-  state->board[mid][mid - 1] = BLACK;
+    // Place the initial pieces
+    int mid = BOARD_SIZE / 2;
+    state->board[mid - 1][mid - 1] = WHITE;
+    state->board[mid][mid] = WHITE;
+    state->board[mid - 1][mid] = BLACK;
+    state->board[mid][mid - 1] = BLACK;
 
-  state->cursor_x = mid - 1;
-  state->cursor_y = mid + 1;
+    state->cursor_x = mid - 1;
+    state->cursor_y = mid + 1;
 
-  // Set up turn order
-  state->human_color = WHITE;
-  state->current_player = WHITE;
+    // Set up turn order
+    state->human_color = WHITE;
+    state->current_player = WHITE;
 
-  state->is_game_over = false;
+    state->is_game_over = false;
 }
 
-void human_move(GameState *game_state) {
-  if (game_state->current_player != game_state->human_color) {
-    return;
-  }
+void human_move(GameState* game_state) {
+    if(game_state->current_player != game_state->human_color) {
+        return;
+    }
 
-  if (is_legal_move(game_state->board, game_state->cursor_x,
-                    game_state->cursor_y, game_state->current_player)) {
-    make_move(game_state, game_state->cursor_x, game_state->cursor_y,
-              game_state->current_player);
-    game_state->current_player = -game_state->current_player;
-  }
+    if(is_legal_move(
+           game_state->board,
+           game_state->cursor_x,
+           game_state->cursor_y,
+           game_state->current_player)) {
+        make_move(
+            game_state, game_state->cursor_x, game_state->cursor_y, game_state->current_player);
+        game_state->current_player = -game_state->current_player;
+    }
 }
 
-void computer_move(GameState *game_state) {
-  if (game_state->current_player == game_state->human_color) {
-    return;
-  }
-  int best_row = -1, best_col = -1, best_score = -1000000;
-  for (int i = 0; i < BOARD_SIZE; i++) {
-    for (int j = 0; j < BOARD_SIZE; j++) {
-      if (!is_legal_move(game_state->board, i, j, game_state->current_player)) {
-        continue;
-      }
-      int score = heuristic(game_state->board);
-      if (score > best_score) {
-        best_score = score;
-        best_row = i;
-        best_col = j;
-      }
+void computer_move(GameState* game_state) {
+    if(game_state->current_player == game_state->human_color) {
+        return;
+    }
+    int best_row = -1, best_col = -1, best_score = -1000000;
+    for(int i = 0; i < BOARD_SIZE; i++) {
+        for(int j = 0; j < BOARD_SIZE; j++) {
+            if(!is_legal_move(game_state->board, i, j, game_state->current_player)) {
+                continue;
+            }
+            int score = heuristic(game_state->board);
+            if(score > best_score) {
+                best_score = score;
+                best_row = i;
+                best_col = j;
+            }
+        }
+    }
+    if(best_row != -1) {
+        make_move(game_state, best_row, best_col, game_state->current_player);
+    }
+    if(has_legal_moves(game_state->board, game_state->human_color)) {
+        game_state->current_player = -game_state->current_player;
     }
-  }
-  if (best_row != -1) {
-    make_move(game_state, best_row, best_col, game_state->current_player);
-  }
-  if (has_legal_moves(game_state->board, game_state->human_color)) {
-    game_state->current_player = -game_state->current_player;
-  }
 }

+ 8 - 8
reversi.h

@@ -8,14 +8,14 @@
 #define BOARD_SIZE 8
 
 typedef struct {
-  int8_t board[BOARD_SIZE][BOARD_SIZE];
-  int8_t current_player;
-  int8_t human_color;
-  uint8_t cursor_x;
-  uint8_t cursor_y;
-  uint8_t is_game_over;
+    int8_t board[BOARD_SIZE][BOARD_SIZE];
+    int8_t current_player;
+    int8_t human_color;
+    uint8_t cursor_x;
+    uint8_t cursor_y;
+    uint8_t is_game_over;
 } GameState;
 
 void init_game(GameState* state);
-void computer_move(GameState *game_state);
-void human_move(GameState *game_state);
+void computer_move(GameState* game_state);
+void human_move(GameState* game_state);