A little app to simulate every possible move in Connect Four.
at main 4.2 kB view raw
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}