소스 검색

Merge reversi from https://github.com/xMasterX/all-the-plugins

# Conflicts:
#	reversi/game_reversi.c
Willy-JL 1 년 전
부모
커밋
cd756a1d42
4개의 변경된 파일114개의 추가작업 그리고 30개의 파일을 삭제
  1. 2 2
      reversi/application.fam
  2. 1 2
      reversi/game_reversi.c
  3. 106 26
      reversi/reversi.c
  4. 5 0
      reversi/reversi.h

+ 2 - 2
reversi/application.fam

@@ -7,13 +7,13 @@ App(
     requires=[
         "gui",
     ],
-    stack_size=1 * 1024,
+    stack_size=2 * 1024,
     order=90,
     fap_icon="game_reversi.png",
     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_version="1.3",
     fap_description="Reversi game, the game controls should be intuitive. Longs press on OK opens the menu to start a new game.",
 )

+ 1 - 2
reversi/game_reversi.c

@@ -12,8 +12,7 @@
 #define FRAME_TOP 3
 #define FRAME_CELL_SIZE 7
 
-#define SAVING_DIRECTORY STORAGE_APP_DATA_PATH_PREFIX
-#define SAVING_FILENAME SAVING_DIRECTORY "/game_reversi.save"
+#define SAVING_FILENAME APP_DATA_PATH("reversi.save")
 
 typedef enum { AppScreenGame, AppScreenMenu } AppScreen;
 

+ 106 - 26
reversi/reversi.c

@@ -5,6 +5,16 @@
 
 // Psst! Most of this file was written with Copilot
 
+const int weights[BOARD_SIZE][BOARD_SIZE] = {
+    {100, -10, 10, 10, 10, 10, -10, 100},
+    {-10, -20, -5, -5, -5, -5, -20, -10},
+    {10, -5, 5, 1, 1, 5, -5, 10},
+    {10, -5, 1, 0, 0, 1, -5, 10},
+    {10, -5, 1, 0, 0, 1, -5, 10},
+    {10, -5, 5, 1, 1, 5, -5, 10},
+    {-10, -20, -5, -5, -5, -5, -20, -10},
+    {100, -10, 10, 10, 10, 10, -10, 100}};
+
 // 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;
@@ -53,52 +63,56 @@ bool has_legal_moves(int8_t board[BOARD_SIZE][BOARD_SIZE], int8_t player_color)
     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;
+int evaluate_board(int8_t board[BOARD_SIZE][BOARD_SIZE], int player) {
+    int score = 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++;
+            if(board[i][j] == player) {
+                score += weights[i][j];
+            } else if(board[i][j] == -player) {
+                score -= weights[i][j];
+            }
         }
     }
-    return white - black;
+    return score;
 }
 
 // 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;
+void make_move(
+    GameState* game_state,
+    int8_t board[BOARD_SIZE][BOARD_SIZE],
+    int x,
+    int y,
+    int player) {
+    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) {
+            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(state->board[r][c] == player) {
+                    if(board[r][c] == player) {
                         r -= i;
                         c -= j;
                         while(r != x || c != y) {
-                            state->board[r][c] = player;
+                            board[r][c] = player;
                             r -= i;
                             c -= j;
                         }
                         break;
                     }
-                    if(state->board[r][c] == 0) break;
+                    if(board[r][c] == 0) break;
                     k++;
                 }
             }
         }
     }
-    state->is_game_over = is_game_over(state->board);
+    game_state->is_game_over = is_game_over(game_state->board);
 }
 
 void init_game(GameState* state) {
@@ -136,11 +150,68 @@ void human_move(GameState* game_state) {
            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,
+            game_state->board,
+            game_state->cursor_x,
+            game_state->cursor_y,
+            game_state->current_player);
         game_state->current_player = -game_state->current_player;
     }
 }
 
+int minimax(
+    GameState* game_state,
+    int8_t board[BOARD_SIZE][BOARD_SIZE],
+    int depth,
+    bool is_maximizing,
+    int player,
+    int alpha,
+    int beta) {
+    if(depth == 0 || is_game_over(board)) {
+        return evaluate_board(board, player);
+    }
+
+    if(is_maximizing) {
+        int max_eval = -1000000;
+        for(int i = 0; i < BOARD_SIZE; i++) {
+            for(int j = 0; j < BOARD_SIZE; j++) {
+                if(is_legal_move(board, i, j, player)) {
+                    int8_t temp_board[BOARD_SIZE][BOARD_SIZE];
+                    memcpy(temp_board, board, sizeof(temp_board));
+                    make_move(game_state, temp_board, i, j, player);
+                    int eval =
+                        minimax(game_state, temp_board, depth - 1, false, -player, alpha, beta);
+                    max_eval = max(max_eval, eval);
+                    alpha = max(alpha, eval);
+                    if(beta <= alpha) {
+                        break;
+                    }
+                }
+            }
+        }
+        return max_eval;
+    } else {
+        int min_eval = 1000000;
+        for(int i = 0; i < BOARD_SIZE; i++) {
+            for(int j = 0; j < BOARD_SIZE; j++) {
+                if(is_legal_move(board, i, j, -player)) {
+                    int8_t temp_board[BOARD_SIZE][BOARD_SIZE];
+                    memcpy(temp_board, board, sizeof(temp_board));
+                    make_move(game_state, temp_board, i, j, -player);
+                    int eval =
+                        minimax(game_state, temp_board, depth - 1, true, player, alpha, beta);
+                    min_eval = min(min_eval, eval);
+                    beta = min(beta, eval);
+                    if(beta <= alpha) {
+                        break;
+                    }
+                }
+            }
+        }
+        return min_eval;
+    }
+}
+
 void computer_move(GameState* game_state) {
     if(game_state->current_player == game_state->human_color) {
         return;
@@ -148,19 +219,28 @@ void computer_move(GameState* game_state) {
     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(is_legal_move(game_state->board, i, j, game_state->current_player)) {
+                int8_t temp_board[BOARD_SIZE][BOARD_SIZE];
+                memcpy(temp_board, game_state->board, sizeof(temp_board));
+                make_move(game_state, temp_board, i, j, game_state->current_player);
+                int score = minimax(
+                    game_state,
+                    temp_board,
+                    3,
+                    false,
+                    -game_state->current_player,
+                    -1000000,
+                    1000000);
+                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);
+        make_move(game_state, game_state->board, 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;

+ 5 - 0
reversi/reversi.h

@@ -3,6 +3,11 @@
 #include <furi.h>
 #include <stdbool.h>
 
+#ifndef __cplusplus
+#define max(a, b) (((a) > (b)) ? (a) : (b))
+#define min(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
 #define BLACK 1
 #define WHITE -1
 #define BOARD_SIZE 8