Skip to content
Snippets Groups Projects
Commit 034a59ca authored by tanguy.cavagna's avatar tanguy.cavagna :desktop:
Browse files

fckn broken entropy

parent 5b2ae213
No related branches found
No related tags found
No related merge requests found
conf.h 0 → 100644
#ifndef CONF_H_
#define CONF_H_
// Game setup
#define TRIES_COUNT 6
#define WORD_LENGHT 5
// Enums
typedef enum Gamemode { SOLO, VERSUS, TOOL_ASSISTED } Gamemode;
typedef enum Pattern { WRONG, MISPLACED, CORRECT, NAP } Pattern; // NAP => Not A Pattern (Only used when computing all possible patterns)
#endif
\ No newline at end of file
tmp.txt 0 → 100644
AddressSanitizer:DEADLYSIGNAL
=================================================================
==43005==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x5577b8bb4608 bp 0x7fffa0d74860 sp 0x7fffa0d745c0 T0)
==43005==The signal is caused by a READ memory access.
==43005==Hint: address points to the zero page.
#0 0x5577b8bb4608 in handle_controls wordle/wordle.c:58
#1 0x5577b8bb4e85 in launch_game wordle/wordle.c:261
#2 0x5577b8baca69 in main /home/toguy/dev/hepia/sequencial-programming/wordle/main.c:18
#3 0x7f4b4553afcf in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
#4 0x7f4b4553b07c in __libc_start_main_impl ../csu/libc-start.c:409
#5 0x5577b8bacbd4 in _start (/home/toguy/dev/hepia/sequencial-programming/wordle/bin/main+0x3bd4)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV wordle/wordle.c:58 in handle_controls
==43005==ABORTING
make: *** [Makefile:18: main] Error 1
......@@ -12,24 +12,44 @@ void test_compute_matches_should_remain_BALAI(void) {
// Act
set_gamemode(MENU_SOLO);
init_tool();
set_answer("BALAI");
char *answer = "BALAI";
set_answer(answer);
printf("ANSWER: %s\n\n", answer);
set_try("BRUTE");
Pattern *pattern = generate_pattern();
possibility_t **p = compute_matches("BRUTE", pattern);
save_computed_matches(p);
free(pattern);
pattern = NULL;
set_try("SALUT");
pattern = generate_pattern();
p = compute_matches("SALUT", pattern);
save_computed_matches(p);
for (int i = 0; i < get_remaining_bank_count(); i++)
printf("%s\t%f\n", p[i]->word, p[i]->entropy);
free(pattern);
pattern = NULL;
//
// printf("\n\n");
//
// set_try("BLOCS");
// pattern = generate_pattern();
// p = compute_matches("BLOCS", pattern);
//
// for (int i = 0; i < get_remaining_bank_count(); i++)
// printf("%s\t%f\n", p[i]->word, p[i]->entropy);
//
// free(pattern);
// pattern = NULL;
//
// printf("\n\n");
//
// set_try("BILLY");
// pattern = generate_pattern();
// p = compute_matches("BILLY", pattern);
//
// for (int i = 0; i < get_remaining_bank_count(); i++)
// printf("%s\t%f\n", p[i]->word, p[i]->entropy);
//
// free(pattern);
// Assert
TEST_ASSERT_EQUAL_INT(get_remaining_bank_count(), 1);
......@@ -39,5 +59,4 @@ void test_compute_matches_should_remain_BALAI(void) {
free(target);
destroy_possibilities(p);
destroy_tool();
}
......@@ -8,21 +8,6 @@ char **remaining_bank;
int remaining_bank_count;
possibility_t **possibilities;
/**
* @brief Create a possibility
*
* @param word
* @param entropy
* @return
*/
possibility_t *create_possibility(char *word, double entropy) {
possibility_t *p = malloc(sizeof(possibility_t));
p->word = calloc(WORD_LENGHT + 1, sizeof(char));
strcpy(p->word, word);
p->entropy = entropy;
return p;
}
/**
* @brief Destroiy a given matches set
*
......@@ -56,6 +41,10 @@ matches_t *filter_out_remaining_bank(char *word, Pattern *pattern) {
char current_word[WORD_LENGHT + 1];
strcpy(current_word, remaining_bank[j]);
// Exclude current word
if (strcmp(current_word, word) == 0)
continue;
bool valid_word = true;
for (int i = 0; i < WORD_LENGHT; i++) {
// Filter out the non-valid words
......@@ -115,14 +104,12 @@ double compute_entropy(char *word) {
matches_t *matches = filter_out_remaining_bank(word, (Pattern[WORD_LENGHT]){*curr[0], *curr[1], *curr[2], *curr[3], *curr[4]});
// Skip unmatch pattern
if (matches->count == 0) {
destroy_matches(matches);
break;
if (matches->count != 0) {
// Apply Shannon's formula
double px = ((double)matches->count / (double)remaining_bank_count);
sum += px * (log2(1 / px));
}
// Apply Shannon's formula
double px = ((double)matches->count / (double)remaining_bank_count);
sum += px * (log2(1 / px));
destroy_matches(matches);
// Go to next pattern
......@@ -146,6 +133,21 @@ double compute_entropy(char *word) {
return sum;
}
/**
* @brief Create a possibility
*
* @param word
* @param entropy
* @return
*/
possibility_t *create_possibility(char *word) {
possibility_t *p = malloc(sizeof(possibility_t));
p->word = calloc(WORD_LENGHT + 1, sizeof(char));
strcpy(p->word, word);
p->entropy = compute_entropy(word);
return p;
}
/**
* @brief Compare two given possibilites
*
......@@ -216,8 +218,9 @@ possibility_t **compute_matches(char *word, Pattern *pattern) {
possibility_count = matches->count;
possibilities = realloc(possibilities, possibility_count * sizeof(possibility_t *));
for (int i = 0; i < possibility_count; i++)
possibilities[i] = create_possibility(matches->words[i], 0.0); // compute_entropy(matches->words[i])
possibilities[i] = create_possibility(matches->words[i]);
save_computed_matches(possibilities);
destroy_matches(matches);
// Sort possibilities by entropy ASC
......
#ifndef TOOL_H
#define TOOL_H
#include "../conf.h"
#include "../word-bank/bank.h"
#include "../wordle/wordle.h"
#include <math.h>
#include <stdbool.h>
......
......@@ -11,6 +11,7 @@
// Windows
WINDOW *ui_window = NULL;
WINDOW *help = NULL;
WINDOW *tool = NULL;
char main_title[8][64] = {"$$\\ $$\\ $$$$$$\\ $$$$$$$\\ $$$$$$$\\ $$\\ $$$$$$$$\\ ",
"$$ | $\\ $$ |$$ __$$\\ $$ __$$\\ $$ __$$\\ $$ | $$ _____|",
......@@ -90,6 +91,17 @@ void hide_help() {
help = NULL;
}
/**
* @brief Hide the tool subwindow
*/
void hide_tool() {
wclear(ui_window);
delwin(tool);
refresh();
tool = NULL;
}
//==========================
// PUBLIC
//==========================
......@@ -151,6 +163,7 @@ bool init_term() {
void cleanup_term() {
curs_set(1);
nocbreak();
delwin(tool);
delwin(help);
delwin(ui_window);
endwin();
......@@ -237,7 +250,35 @@ void toggle_help() {
wrefresh(help);
}
void show_gameboard(int tries_count, int word_length, char **tries, int **validations, int score) {
void toggle_tool(int count, char words[count][WORD_LENGHT + 1], double *entropies) {
// Delete existing instance of the subwindow
if (tool != NULL) {
hide_tool();
return;
}
// Create new instance of the subwindow
tool = subwin(ui_window, LINES - 2, 30, 1, 1);
refresh();
if (tool == NULL) {
cleanup_term();
exit(EXIT_FAILURE);
}
scrollok(tool, TRUE);
box(tool, 0, 0);
mvwprintw(tool, 0, 1, " Tool "); // Title
// Content
for (int i = 0; i < count; i++)
mvwprintw(tool, 2 + i, 1, "%s\t%f\n", words[i], entropies[i]);
refresh();
wrefresh(tool);
}
void show_gameboard(int tries_count, int word_length, char **tries, Pattern **patterns, int score) {
for (int i = 0; i < tries_count; i++) {
// Draw current try letters
for (int j = 0; j < word_length; j++) {
......@@ -248,9 +289,9 @@ void show_gameboard(int tries_count, int word_length, char **tries, int **valida
}
// Letters
if (validations[i][j] == 1)
if (patterns[i][j] == MISPLACED)
attron(COLOR_PAIR(ORANGE_PAIR));
if (validations[i][j] == 2)
if (patterns[i][j] == CORRECT)
attron(COLOR_PAIR(GREEN_PAIR));
mvaddch(GAMEBOARD_Y_OFFSET + i - menu_offset_modifer() + 5, TERM_MID_COLS - word_length + (j * 2), tries[i][j]);
......
#ifndef UI_H_
#define UI_H_
#include "../conf.h"
#include <ncurses.h>
#include <stdbool.h>
#include <stdio.h>
......@@ -96,15 +97,24 @@ int show_menu();
*/
void toggle_help();
/**
* @brief Toggle the tool window
*
* @param count
* @param words
* @param entropies
*/
void toggle_tool(int count, char words[count][WORD_LENGHT + 1], double *entropies);
/**
* @brief Show the gameboard
*
* @param tries_count
* @param word_length
* @param tries
* @param validations
* @param patterns
* @param score
*/
void show_gameboard(int tries_count, int word_length, char **tries, int **validations, int score);
void show_gameboard(int tries_count, int word_length, char **tries, Pattern **patterns, int score);
#endif
\ No newline at end of file
......@@ -8,7 +8,8 @@ bool _game_finished = false;
int score = 0;
char **tries;
char *chosen_word;
int **validations;
Pattern **patterns;
possibility_t **remaining_possibilities;
int current_try_id = 0;
int current_try_letter_id = 0;
......@@ -30,7 +31,7 @@ void render_game() {
break;
}
show_gameboard(TRIES_COUNT, WORD_LENGHT, tries, validations, score);
show_gameboard(TRIES_COUNT, WORD_LENGHT, tries, patterns, score);
}
/**
......@@ -44,6 +45,23 @@ void handle_controls(int key) {
toggle_help();
break;
case KEYBIND_TAG:
if (mode == TOOL_ASSISTED) {
if (current_try_id == 0)
break;
char words[get_remaining_bank_count()][WORD_LENGHT + 1];
double entropies[get_remaining_bank_count()];
for (int i = 0; i < get_remaining_bank_count(); i++) {
strcpy(words[i], remaining_possibilities[i]->word);
entropies[i] = remaining_possibilities[i]->entropy;
}
toggle_tool(get_remaining_bank_count(), words, entropies);
}
break;
case KEYBIND_QUIT:
terminate_game();
break;
......@@ -52,10 +70,10 @@ void handle_controls(int key) {
if (!validate_guess(tries[current_try_id]))
break;
// Validations
// Patterns
Pattern *pattern = generate_pattern();
for (int i = 0; i < WORD_LENGHT; i++)
validations[current_try_id][i] = pattern[i];
patterns[current_try_id][i] = pattern[i];
free(pattern);
current_try_id += 1;
......@@ -64,10 +82,12 @@ void handle_controls(int key) {
// Place correct letters from previous in the current one
if (current_try_id < TRIES_COUNT) {
for (int i = 0; i < WORD_LENGHT; i++) {
if (validations[current_try_id - 1][i] == CORRECT)
if (patterns[current_try_id - 1][i] == CORRECT)
tries[current_try_id][i] = tries[current_try_id - 1][i];
}
}
remaining_possibilities = compute_matches(tries[current_try_id - 1], patterns[current_try_id - 1]);
break;
}
}
......@@ -76,6 +96,8 @@ void handle_controls(int key) {
// PUBLIC
//==========================
void initialize_game() {
init_tool();
// Reset game variables
_game_finished = false;
current_try_id = 0;
......@@ -86,10 +108,10 @@ void initialize_game() {
set_answer(get_random_word());
tries = calloc(TRIES_COUNT, sizeof(char *));
validations = malloc(sizeof(int *) * TRIES_COUNT);
patterns = malloc(sizeof(Pattern *) * TRIES_COUNT);
for (int i = 0; i < TRIES_COUNT; i++) {
validations[i] = calloc(WORD_LENGHT + 1, sizeof(int));
patterns[i] = calloc(WORD_LENGHT + 1, sizeof(Pattern));
tries[i] = calloc(WORD_LENGHT + 1, sizeof(char)); // +1 because of \0
}
}
......@@ -97,16 +119,20 @@ void initialize_game() {
void terminate_game() { _game_finished = true; }
void destroy_game() {
destroy_tool();
for (int i = 0; i < TRIES_COUNT; i++) {
free(tries[i]);
free(validations[i]);
free(patterns[i]);
}
free(tries);
free(validations);
free(patterns);
}
void restart_game() {
destroy_tool();
init_tool();
score += (TRIES_COUNT - current_try_id) * 10;
set_answer(get_random_word());
......@@ -115,7 +141,7 @@ void restart_game() {
for (int i = 0; i < TRIES_COUNT; i++) {
for (int j = 0; j < WORD_LENGHT; j++) {
validations[i][j] = 0;
patterns[i][j] = WRONG;
tries[i][j] = '\0';
}
}
......@@ -125,7 +151,7 @@ bool lose_condition() { return (current_try_id > TRIES_COUNT - 1); }
bool win_condition() {
for (int i = 0; i < WORD_LENGHT; i++) {
if (validations[current_try_id - (current_try_id > 0 ? 1 : 0)][i] != CORRECT)
if (patterns[current_try_id - (current_try_id > 0 ? 1 : 0)][i] != CORRECT)
return false;
}
......@@ -135,7 +161,7 @@ bool win_condition() {
bool validate_letter(int key) { return (islower(key) || isupper(key)); }
Pattern *generate_pattern() {
Pattern *validation = calloc(WORD_LENGHT, sizeof(int));
Pattern *pattern = calloc(WORD_LENGHT, sizeof(int));
char cpy[WORD_LENGHT + 1];
strcpy(cpy, chosen_word);
......@@ -144,20 +170,20 @@ Pattern *generate_pattern() {
continue;
if (tries[current_try_id][i] == chosen_word[i]) {
validation[i] = CORRECT;
pattern[i] = CORRECT;
cpy[i] = ' ';
continue;
}
char *addr;
if ((addr = strchr(chosen_word, tries[current_try_id][i])) != NULL) {
validation[i] = MISPLACED;
pattern[i] = MISPLACED;
cpy[(int)(addr - chosen_word)] = ' '; // Get the index of the found char and replace with space
continue;
}
}
return validation;
return pattern;
}
bool validate_guess(char current_try[WORD_LENGHT]) {
......
#ifndef WORDLE_H_
#define WORDLE_H_
#include "../conf.h"
#include "../tool/tool.h"
#include "../ui/ui.h"
#include "../word-bank/bank.h"
#include <ctype.h>
#include <stdbool.h>
#include <string.h>
// Game setup
#define TRIES_COUNT 6
#define WORD_LENGHT 5
// Enums
typedef enum Gamemode { SOLO, VERSUS, TOOL_ASSISTED } Gamemode;
typedef enum Pattern { WRONG, MISPLACED, CORRECT, NAP } Pattern; // NAP => Not A Pattern (Only used when computing all possible patterns)
/**
* @brief Initialize the game
*/
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment