diff --git a/main.c b/main.c
index 209af01f8fd18e3d0bc26d8dbe4943d1da6f2faf..801fe257e881c2b2581a5305d219429edd1bb61e 100644
--- a/main.c
+++ b/main.c
@@ -7,49 +7,36 @@
 #include <stdlib.h>
 #include "puissance.h"
 
-void play_against_random_ai(puissance game) {
-    int selected_col_index = -1;
-
-    while(game.state == ONGOING) {
-        if (game.current_player == PLAYER_ONE) {
-            printf("\nColumn number? (starts at 1):");
-            do {
-                scanf("%d", &selected_col_index);
-                selected_col_index -= 1;
-            } while (manual_play(&game, selected_col_index) == false);
-        } else {
-            random_play(&game);
-        }
-        print_game(game);
-    }
+void print_help() {
+    printf("Usage: puissance4 <mode> <row> <col>\n");
+    printf("    mode  specifies the mode:\n");
+    printf("        1 = single player game (random),\n");
+    printf("        2 = single player game (AI),\n");
+    printf("        3 = two players game\n");
+    printf("    row   specifies the number of rows (>= 4)\n");
+    printf("    col   specifies the number of columns (>= 4)\n");
 }
 
-void play_against_smart_ai(puissance game) {
+void play_game(puissance game) {
     int selected_col_index = -1;
 
     while(game.state == ONGOING) {
-        if (game.current_player == PLAYER_ONE) {
+        // First player action (always a human)
+        if (game.current_player == PLAYER_ONE || game.mode == TWO_PLAYERS) {
             printf("\nColumn number? (starts at 1):");
             do {
                 scanf("%d", &selected_col_index);
                 selected_col_index -= 1;
             } while (manual_play(&game, selected_col_index) == false);
-        } else {
-            smart_play(&game);
         }
-        print_game(game);
-    }
-}
-
-void play_against_human(puissance game) {
-    int selected_col_index = -1;
-
-    while(game.state == ONGOING) {
-        do {
-            printf("\nColumn number? (starts at 1):");
-            scanf("%d", &selected_col_index);
-            selected_col_index -= 1;
-        } while (manual_play(&game, selected_col_index) == false);
+        // Second player action (can be the computer)
+        else {
+            if (game.mode == RAND_AI) {
+                random_play(&game);
+            } else {
+                smart_play(&game);
+            };
+        }
         print_game(game);
     }
 }
@@ -58,32 +45,24 @@ int main(int argc, char *argv[]) {
     srand(0);
     puissance game;
 
+    // Get game arguments
     if (argc != 4) {
-        printf("The program must have 3 arguments.\n");
+        print_help();
         return EXIT_FAILURE;
     }
-
     GameMode mode = atoi(argv[1]) - 1;
-    int nb_rows = atoi(argv[2]);
-    int nb_cols = atoi(argv[3]);
+    int rows = atoi(argv[2]);
+    int cols = atoi(argv[3]);
 
-    game_init(&game, mode, nb_rows, nb_cols);
-    printf("Board size is %dx%d (rows x col)", nb_rows, nb_cols);
+    // Initialize the game
+    game_init(&game, mode, rows, cols);
+    printf("Board size is %dx%d (rows x col)", rows, cols);
     print_game(game);
 
-    switch (mode) {
-        case RAND_AI:
-            play_against_random_ai(game);
-            break;
-        case SMART_AI:
-            play_against_smart_ai(game);
-            break;
-        case TWO_PLAYERS:
-            play_against_human(game);
-            break;
-    }
+    // Start playing
+    play_game(game);
 
+    // Free the memory and exit the program
     game_destroy(&game);
-    
     return EXIT_SUCCESS;
 }
diff --git a/puissance.c b/puissance.c
index 9026ba1109a0f037e7e63018f644bc540a96ca5f..4df082382b7bb4c259d796c920319b2c8da169c4 100644
--- a/puissance.c
+++ b/puissance.c
@@ -142,7 +142,6 @@ GameResult get_winning_player(puissance *p) {
         p->state = PLAYER_TWO_WIN;
     }
     return p->state;
-
 }
 
 GameResult vertical_game_check(puissance *p, int last_col_index_played) {
@@ -253,6 +252,10 @@ GameResult diagonal_game_check(puissance *p, int last_col_index_played) {
     if (diagonal_parse(p, 1, 1, last_row_index_played, last_col_index_played)) {
         return get_winning_player(p);
     }
+    // down left
+    if (diagonal_parse(p, 1, -1, last_row_index_played, last_col_index_played)) {
+        return get_winning_player(p);
+    }
     // up left
     if (diagonal_parse(p, -1, -1, last_row_index_played, last_col_index_played)) {
         return get_winning_player(p);
@@ -261,10 +264,6 @@ GameResult diagonal_game_check(puissance *p, int last_col_index_played) {
     if (diagonal_parse(p, -1, 1, last_row_index_played, last_col_index_played)) {
         return get_winning_player(p);
     }
-    // down left
-    if (diagonal_parse(p, 1, -1, last_row_index_played, last_col_index_played)) {
-        return get_winning_player(p);
-    }
 
     return ONGOING;
 }
@@ -274,12 +273,16 @@ GameResult verify_space_remaining(puissance *p) {
         return p->state;
     }
     bool space_available = false;
+    int top_row_index = 0;
+
+    // Verify that at least one cell at the top row is empty.
     for (int i = 0; i < p->col; i++) {
-        if (p->data[0][i] == EMPTY_CELL_VALUE) {
+        if (p->data[top_row_index][i] == EMPTY_CELL_VALUE) {
             space_available = true;
             break;
         }
     }
+    // If no cells at top is empty, then the game can't continue, so it's a draw.
     if (space_available == false) {
         p->state = DRAW;
     }
@@ -368,38 +371,42 @@ bool random_play(puissance *p) {
     return true;
 }
 
-bool smart_play(puissance *p) {
+bool search_optimal_action(puissance *p, bool simulate_player_one) {
     bool move_validated = false;
-    // Search for a wining action
+
+    // Search the optimal action by simulating each possible action
+    // Not the must memory efficient but this method is easily implemented and should work without problems
     for (int i = 0; i < p->col; i++) {
         puissance copy = game_copy(p);
+        if (simulate_player_one) {
+            copy.current_player = PLAYER_ONE;
+        }
 
         if (manual_play(&copy, i)) {
             if (copy.state != ONGOING) {
                 move_validated = manual_play(p, i);
             }
         }
+
         game_destroy(&copy);
         if (move_validated) {
             return move_validated;
         }
     }
+    return move_validated;
+}
 
-    // Try to prevent the user to win
-    for (int i = 0; i < p->col; i++) {
-        puissance copy = game_copy(p);
-        copy.current_player = PLAYER_ONE;
+bool smart_play(puissance *p) {
+    // Search for a wining action
+    if (search_optimal_action(p, false)) {
+        return true;
+    }
 
-        if (manual_play(&copy, i)) {
-            if (copy.state != ONGOING) {
-                move_validated = manual_play(p, i);
-            }
-        }
-        game_destroy(&copy);
-        if (move_validated) {
-            return move_validated;
-        }
+    // Try to prevent the user to win
+    if (search_optimal_action(p, true)) {
+        return true;
     }
+
     // If nothing has been done, do something random
     return random_play(p);
 }