A little app to simulate every possible move in Connect Four.

Profile metric for time to do all moves

+3 -3
CMakeLists.txt
···
add_subdirectory(SDL EXCLUDE_FROM_ALL)
-
add_executable(ConnectFour main.cpp core.cpp)
+
add_executable(ConnectFour main.cpp core.cpp helpers.cpp)
target_link_libraries(ConnectFour PRIVATE SDL3::SDL3)
target_include_directories(ConnectFour PRIVATE SDL/include/SDL3)
-
add_executable(ConnectFour-Profile profile.cpp core.cpp)
+
add_executable(ConnectFour-Profile profile.cpp core.cpp helpers.cpp)
target_link_libraries(ConnectFour-Profile PRIVATE SDL3::SDL3)
target_include_directories(ConnectFour-Profile PRIVATE SDL/include/SDL3)
···
)
foreach(TEST_NAME ${TEST_LIST})
-
add_executable(${TEST_NAME} tests/${TEST_NAME}.cpp core.cpp)
+
add_executable(${TEST_NAME} tests/${TEST_NAME}.cpp core.cpp helpers.cpp)
target_link_libraries(${TEST_NAME} PRIVATE SDL3::SDL3)
target_include_directories(${TEST_NAME} PRIVATE SDL/include/SDL3)
add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME})
+11 -45
core.cpp
···
#include "core.h"
+
#include "helpers.h"
#include <cassert>
#include <math.h>
···
return false;
}
-
uint64_t total_moves_evaluated = 0;
-
uint64_t wins_found = 0;
-
uint64_t dead_ends_found = 0;
-
uint8_t min_depth = 50;
+
uint64_t total_moves_evaluated;
+
uint64_t wins_found;
+
uint64_t dead_ends_found;
+
uint8_t min_depth;
uint64_t time_of_last_print;
uint64_t get_move_score_start_time;
-
void sprint_friendly_time(double_t total_seconds, char* buffer)
-
{
-
uint32_t days = (uint32_t)(total_seconds / (60 * 60 * 24));
-
total_seconds -= days * 60.0 * 60.0 * 24.0;
-
uint32_t hours = (uint32_t)(total_seconds / (60 * 60));
-
total_seconds -= hours * 60.0 * 60.0;
-
uint32_t minutes = (uint32_t)(total_seconds / 60);
-
total_seconds -= minutes * 60.0;
-
uint32_t seconds = (uint32_t)total_seconds;
-
-
if (days > 0)
-
{
-
snprintf(buffer, 256, "%d day%s, %d hour%s, %d minute%s, %d second%s",
-
days, days > 1 ? "s" : "",
-
hours, hours > 1 ? "s" : "",
-
minutes, minutes > 1 ? "s" : "",
-
seconds, seconds > 1 ? "s": "");
-
}
-
else if (hours > 0)
-
{
-
snprintf(buffer, 256, "%d hour%s, %d minute%s, %d second%s",
-
hours, hours > 1 ? "s" : "",
-
minutes, minutes > 1 ? "s" : "",
-
seconds, seconds > 1 ? "s": "");
-
}
-
else if (minutes > 0)
-
{
-
snprintf(buffer, 256, "%d minute%s, %d second%s",
-
minutes, minutes > 1 ? "s" : "",
-
seconds, seconds > 1 ? "s": "");
-
}
-
else
-
{
-
snprintf(buffer, 256, "%d second%s",
-
seconds, seconds > 1 ? "s": "");
-
}
-
}
-
int32_t get_move_score(uint8_t player, uint8_t player_this_turn, uint8_t col, BoardState state, bool *move_possible, uint8_t depth)
{
uint64_t time_current = SDL_GetTicks();
···
printf("Total moves: %llu (%f%%), wins found: %llu, dead-ends found: %llu, depth: %d\n", total_moves_evaluated, percent_completed, wins_found, dead_ends_found, min_depth);
-
char* friendly_time_string = (char*)malloc(sizeof(char) * 512);
+
char friendly_time_string[256];
sprint_friendly_time(time_to_complete, friendly_time_string);
printf("- Time to complete: %s\n", friendly_time_string);
-
free(friendly_time_string);
}
BoardState state_new;
memcpy(state_new, state, sizeof(BoardState));
-
int8_t row = make_move(player_this_turn, col, state_new);
+
int8_t row = make_move_lookup_full(player_this_turn, col, state_new);
*move_possible = row >= 0;
if (*move_possible == false)
{
···
bool move_possible;
get_move_score_start_time = SDL_GetTicks();
time_of_last_print = get_move_score_start_time;
+
total_moves_evaluated = 0;
+
wins_found = 0;
+
dead_ends_found = 0;
+
min_depth = 50;
return get_move_score(0, 0, 0, state, &move_possible, 1);
}
+41
helpers.cpp
···
+
#include "helpers.h"
+
+
#include <stdio.h>
+
+
void sprint_friendly_time(double_t total_seconds, char buffer[256])
+
{
+
uint32_t days = (uint32_t)(total_seconds / (60 * 60 * 24));
+
total_seconds -= days * 60.0 * 60.0 * 24.0;
+
uint32_t hours = (uint32_t)(total_seconds / (60 * 60));
+
total_seconds -= hours * 60.0 * 60.0;
+
uint32_t minutes = (uint32_t)(total_seconds / 60);
+
total_seconds -= minutes * 60.0;
+
uint32_t seconds = (uint32_t)total_seconds;
+
+
if (days > 0)
+
{
+
snprintf(buffer, 256, "%d day%s, %d hour%s, %d minute%s, %d second%s",
+
days, days > 1 ? "s" : "",
+
hours, hours > 1 ? "s" : "",
+
minutes, minutes > 1 ? "s" : "",
+
seconds, seconds > 1 ? "s": "");
+
}
+
else if (hours > 0)
+
{
+
snprintf(buffer, 256, "%d hour%s, %d minute%s, %d second%s",
+
hours, hours > 1 ? "s" : "",
+
minutes, minutes > 1 ? "s" : "",
+
seconds, seconds > 1 ? "s": "");
+
}
+
else if (minutes > 0)
+
{
+
snprintf(buffer, 256, "%d minute%s, %d second%s",
+
minutes, minutes > 1 ? "s" : "",
+
seconds, seconds > 1 ? "s": "");
+
}
+
else
+
{
+
snprintf(buffer, 256, "%d second%s",
+
seconds, seconds > 1 ? "s": "");
+
}
+
}
+5
helpers.h
···
+
#pragma once
+
+
#include <math.h>
+
+
void sprint_friendly_time(double_t total_seconds, char buffer[256]);
+1 -1
main.cpp
···
int main()
{
-
SDL_Init(0);
+
init_core();
BoardState state = { 1, 1, 1, 1, 1, 1, 1 };
uint8_t player = 0;
+11
profile.cpp
···
#include "core.h"
+
#include "helpers.h"
#include <math.h>
#include "SDL.h"
···
double_t make_move_num_per_us = 1000 / make_move_avg_time_ns;
printf("%s(): %f times / μs. (total time to make %llu moves: %f ms\n", label, make_move_num_per_us, total_num_moves, make_move_total_time_ns / 1000000);
+
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);
+
char make_move_time_to_finish_str[256];
+
sprint_friendly_time(make_move_time_to_finish_sec, make_move_time_to_finish_str);
+
printf("-- Time to complete 4531985219092 moves: %s.\n", make_move_time_to_finish_str);
+
bool* wins = (bool*)malloc(sizeof(bool) * NUM_GAMES); // basically just to keep the compiler from optimizing out check_for_win
uint64_t check_for_win_start_time = SDL_GetPerformanceCounter();
for (uint64_t i = 0; i < NUM_GAMES; ++i)
···
double_t check_for_win_avg_time_ns = check_for_win_total_time_ns / NUM_GAMES;
double_t check_for_win_num_per_us = 1000 / check_for_win_avg_time_ns;
printf("check_for_win(): %f times / μs. (total time to check %llu games: %f ms\n", check_for_win_num_per_us, NUM_GAMES, check_for_win_total_time_ns / 1000000);
+
+
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);
+
char check_for_win_time_to_finish_str[256];
+
sprint_friendly_time(check_for_win_time_to_finish_sec, check_for_win_time_to_finish_str);
+
printf("-- Time to check 4531985219092 states: %s.\n", check_for_win_time_to_finish_str);
}
int main()