A little app to simulate every possible move in Connect Four.
1#include "core.h"
2#include "helpers.h"
3
4#include <math.h>
5#include "SDL.h"
6#include "SDL_timer.h"
7#include <stdio.h>
8#include <stdlib.h>
9
10struct Game
11{
12 uint8_t num_moves;
13 uint8_t* moves;
14};
15
16struct BoardAndLastMove
17{
18 BoardState state;
19 uint8_t last_move_player;
20 int8_t last_move_row;
21 int8_t last_move_col;
22};
23
24const uint64_t NUM_GAMES = 10000000;
25const uint8_t MAX_NUM_MOVES = 30;
26
27void run_profile(const char* label, int8_t (*make_move_func)(uint8_t, uint8_t, BoardState))
28{
29 uint64_t total_num_moves = 0;
30 Game* games = (Game*)malloc(sizeof(Game) * NUM_GAMES);
31 for (uint64_t i = 0; i < NUM_GAMES; ++i)
32 {
33 games[i].num_moves = (uint8_t)SDL_rand(MAX_NUM_MOVES) + 1;
34 games[i].moves = (uint8_t*)malloc(sizeof(uint8_t) * games[i].num_moves);
35 for (uint8_t j = 0; j < games[i].num_moves; ++j)
36 {
37 games[i].moves[j] = (uint8_t)SDL_rand(7);
38 }
39 total_num_moves += games[i].num_moves;
40 }
41
42 BoardAndLastMove* states = (BoardAndLastMove*)malloc(sizeof(BoardAndLastMove) * NUM_GAMES);
43 for (uint64_t i = 0; i < NUM_GAMES; ++i)
44 {
45 init_board(states[i].state);
46 }
47
48 uint64_t make_move_start_time = SDL_GetPerformanceCounter();
49 for (uint64_t i = 0; i < NUM_GAMES; ++i)
50 {
51 uint8_t player = 0;
52 for (uint8_t j = 0; j < games[i].num_moves; ++j)
53 {
54 int8_t col = games[i].moves[j];
55 int8_t row = make_move_func(player, col, states[i].state);
56 if (row >= 0)
57 {
58 states[i].last_move_player = player;
59 states[i].last_move_row = row;
60 states[i].last_move_col = col;
61 player = 1 - player;
62 }
63 }
64 }
65 uint64_t make_move_end_time = SDL_GetPerformanceCounter();
66
67 double_t make_move_total_time_ns = (double_t)(make_move_end_time - make_move_start_time) / ((double_t)SDL_GetPerformanceFrequency() / 1000000000);
68 double_t make_move_avg_time_ns = make_move_total_time_ns / total_num_moves;
69 double_t make_move_num_per_us = 1000 / make_move_avg_time_ns;
70 printf("%s(): %f times / μs. (total time to make %lu moves: %f ms\n", label, make_move_num_per_us, total_num_moves, make_move_total_time_ns / 1000000);
71
72 double_t make_move_time_to_finish_sec = ((double_t)(make_move_end_time - make_move_start_time) / SDL_GetPerformanceFrequency()) * (4531985219092.0 / total_num_moves);
73 char make_move_time_to_finish_str[256];
74 sprint_friendly_time(make_move_time_to_finish_sec, make_move_time_to_finish_str);
75 printf("-- Time to complete 4531985219092 moves: %s.\n", make_move_time_to_finish_str);
76
77 bool* wins = (bool*)malloc(sizeof(bool) * NUM_GAMES); // basically just to keep the compiler from optimizing out check_for_win
78 uint64_t check_for_win_start_time = SDL_GetPerformanceCounter();
79 for (uint64_t i = 0; i < NUM_GAMES; ++i)
80 {
81 wins[i] = check_for_win(states[i].state, states[i].last_move_player, states[i].last_move_row, states[i].last_move_col);
82 }
83 uint64_t check_for_win_end_time = SDL_GetPerformanceCounter();
84
85 double_t check_for_win_total_time_ns = (double_t)(check_for_win_end_time - check_for_win_start_time) / ((double_t)SDL_GetPerformanceFrequency() / 1000000000);
86 double_t check_for_win_avg_time_ns = check_for_win_total_time_ns / NUM_GAMES;
87 double_t check_for_win_num_per_us = 1000 / check_for_win_avg_time_ns;
88 printf("check_for_win(): %f times / μs. (total time to check %lu games: %f ms\n", check_for_win_num_per_us, NUM_GAMES, check_for_win_total_time_ns / 1000000);
89
90 double_t check_for_win_time_to_finish_sec = ((double_t)(check_for_win_end_time - check_for_win_start_time) / SDL_GetPerformanceFrequency()) * (4531985219092.0 / NUM_GAMES);
91 char check_for_win_time_to_finish_str[256];
92 sprint_friendly_time(check_for_win_time_to_finish_sec, check_for_win_time_to_finish_str);
93 printf("-- Time to check 4531985219092 states: %s.\n", check_for_win_time_to_finish_str);
94}
95
96int main()
97{
98 init_core();
99
100 run_profile("make_move", &make_move);
101 run_profile("make_move_lookup_partial", &make_move_lookup_partial);
102 run_profile("make_move_lookup_full", &make_move_lookup_full);
103}