cordle/src/main.c

241 lines
8.0 KiB
C
Raw Normal View History

2025-12-17 21:24:41 +00:00
/*
2025-12-18 08:59:54 +00:00
* Created by Gregory Gauthier on 06/10/2025.
*/
2025-10-06 13:58:25 +00:00
/* main.c - Entry point and main game loop */
2025-12-17 09:28:00 +00:00
/* Compile with: gcc -std=c90 -o cordle src\/\*.c -Iinclude -lncurses */
2025-10-06 13:58:25 +00:00
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
2026-01-26 14:29:55 +00:00
#include "../include/platform.h"
2025-10-06 13:58:25 +00:00
#include "../include/game.h"
#include "../include/words.h"
#include "../include/ui.h"
/* Parse command line arguments */
2025-12-17 09:28:00 +00:00
void parse_arguments(int argc, char *argv[], char *filename, char *difficulty) {
2025-10-06 13:58:25 +00:00
int i;
/* Default values */
2025-12-17 09:59:33 +00:00
strcpy(filename, "cordle_words_easy.txt");
2025-10-06 13:58:25 +00:00
strcpy(difficulty, "EASY");
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "--easy") == 0) {
2025-12-17 09:59:33 +00:00
strcpy(filename, "cordle_words_easy.txt");
2025-10-06 13:58:25 +00:00
strcpy(difficulty, "EASY");
} else if (strcmp(argv[i], "--medium") == 0) {
2025-12-17 09:59:33 +00:00
strcpy(filename, "cordle_words_medium.txt");
2025-10-06 13:58:25 +00:00
strcpy(difficulty, "MEDIUM");
} else if (strcmp(argv[i], "--hard") == 0) {
2025-12-17 10:08:03 +00:00
strcpy(filename, "cordle_words_hard.txt");
2025-10-06 13:58:25 +00:00
strcpy(difficulty, "HARD");
} else if (strcmp(argv[i], "--techy") == 0) {
2025-12-17 09:59:33 +00:00
strcpy(filename, "cordle_words_techy.txt");
2025-10-06 13:58:25 +00:00
strcpy(difficulty, "TECHNICAL");
} else if (strcmp(argv[i], "--literary") == 0) {
2025-12-17 09:59:33 +00:00
strcpy(filename, "cordle_words_literary.txt");
2025-10-06 13:58:25 +00:00
strcpy(difficulty, "LITERARY");
} else if (strcmp(argv[i], "--cultural") == 0) {
2025-12-17 09:59:33 +00:00
strcpy(filename, "cordle_words_cultural.txt");
2025-10-06 13:58:25 +00:00
strcpy(difficulty, "CULTURAL");
} else if (strcmp(argv[i], "--full") == 0) {
2025-12-17 09:59:33 +00:00
strcpy(filename, "cordle_words_full.txt");
2025-10-06 13:58:25 +00:00
strcpy(difficulty, "FULL");
} else if (strcmp(argv[i], "--wordlist") == 0 && i + 1 < argc) {
strcpy(filename, argv[i + 1]);
strcpy(difficulty, "CUSTOM");
i++; /* Skip next argument */
}
}
}
/* Main game loop */
2025-12-18 08:59:54 +00:00
int main_game_loop(int argc, char *argv[]) {
2025-12-17 09:28:00 +00:00
WINDOW *stdscr;
2025-10-06 13:58:25 +00:00
GameState game;
char filename[MAX_FILENAME];
char difficulty[32];
char message[MAX_MESSAGE] = "";
int message_color = COLOR_DEFAULT;
int height, width, y_pos;
int key;
char temp_guess[WORD_LENGTH + 1];
char win_message[MAX_MESSAGE];
/* Get command line arguments */
parse_arguments(argc, argv, filename, difficulty);
/* Initialize ncurses */
stdscr = initscr();
2025-12-17 09:28:00 +00:00
curs_set(0); /* Hide cursor */
2026-01-26 14:04:05 +00:00
keypad(stdscr, TRUE); /* Enable special key detection */
2025-10-06 13:58:25 +00:00
clear();
/* Initialize colors */
start_color();
init_pair(COLOR_DEFAULT, COLOR_WWHITE, COLOR_BLACK);
init_pair(COLOR_CORRECT, COLOR_BLACK, COLOR_GREEN);
init_pair(COLOR_PRESENT, COLOR_BLACK, COLOR_YELLOW);
init_pair(COLOR_ABSENT, COLOR_WWHITE, COLOR_RED);
init_pair(COLOR_WWHITE, COLOR_WWHITE, COLOR_BLACK);
init_pair(COLOR_UNUSED, COLOR_WWHITE, COLOR_BLACK);
/* Initialize game */
init_game(&game);
if (!load_words(&game, filename)) {
/* Try fallback */
2025-12-17 09:59:33 +00:00
if (strcmp(filename, "cordle_words.txt") != 0 &&
load_words(&game, "cordle_words.txt")) {
2025-10-06 13:58:25 +00:00
strcpy(difficulty, "DEFAULT");
} else {
mvaddstr(0, 0, "Error: Could not load word list");
mvaddstr(1, 0, "Press any key to exit...");
getch();
endwin();
return 1;
}
}
/* Main game loop */
while (1) {
clear();
getmaxyx(stdscr, height, width);
y_pos = 1;
/* Draw components */
draw_title(stdscr, y_pos, difficulty);
y_pos += 2;
draw_board(stdscr, &game, y_pos);
y_pos += MAX_GUESSES * 2 + 1;
draw_keyboard(stdscr, &game, y_pos);
y_pos += 4;
/* Draw message if exists */
if (strlen(message) > 0) {
draw_message(stdscr, message, y_pos, message_color);
y_pos += 2;
}
/* Draw instructions */
if (y_pos + 6 < height) {
draw_instructions(stdscr, y_pos);
}
/* Handle game over */
if (game.game_over) {
y_pos = (height > 20) ? height - 3 : y_pos;
if (game.won) {
sprintf(win_message, "Congratulations! You won in %d guesses!",
2025-12-17 09:28:00 +00:00
game.guess_count);
2025-10-06 13:58:25 +00:00
draw_message(stdscr, win_message, y_pos, COLOR_CORRECT);
} else {
sprintf(win_message, "Game Over! The word was: %s",
2025-12-17 09:28:00 +00:00
game.target_word);
2025-10-06 13:58:25 +00:00
draw_message(stdscr, win_message, y_pos, COLOR_ABSENT);
}
draw_message(stdscr, "Press 'N' for new game or 'Q' to quit",
2025-12-17 09:28:00 +00:00
y_pos + 1, COLOR_DEFAULT);
2025-10-06 13:58:25 +00:00
refresh();
key = getch();
if (key == 'n' || key == 'N') {
/* Start new game */
init_game(&game);
load_words(&game, filename);
strcpy(message, "");
continue;
} else if (key == 'q' || key == 'Q' || key == 27) {
break;
}
continue;
}
refresh();
/* Get input */
key = getch();
/* Handle input */
2025-12-17 09:28:00 +00:00
if (key == 27) {
/* ESC */
2025-10-06 13:58:25 +00:00
break;
2026-01-26 14:04:05 +00:00
} else if (key == KEY_UP || key == KEY_DOWN || key == KEY_LEFT || key == KEY_RIGHT) {
/* Ignore arrow keys to prevent crashes */
continue;
2025-10-06 13:58:25 +00:00
} else if (key == '\n' || key == '\r' || key == KEY_ENTER) {
if (game.current_guess_length == WORD_LENGTH) {
strcpy(temp_guess, game.current_guess);
if (make_guess(&game, temp_guess)) {
game.current_guess[0] = '\0';
game.current_guess_length = 0;
strcpy(message, "");
} else {
2025-12-18 09:13:20 +00:00
/* Validation failed in make_guess or is_valid_word */
strcpy(message, "Not in word list!");
message_color = COLOR_ABSENT;
2025-10-06 13:58:25 +00:00
}
} else {
sprintf(message, "Word must be %d letters!", WORD_LENGTH);
message_color = COLOR_ABSENT;
}
} else if (key == KEY_BACKSPACE || key == 127 || key == '\b') {
if (game.current_guess_length > 0) {
game.current_guess_length--;
game.current_guess[game.current_guess_length] = '\0';
strcpy(message, "");
}
} else if ((key >= 'a' && key <= 'z') || (key >= 'A' && key <= 'Z')) {
if (game.current_guess_length < WORD_LENGTH) {
game.current_guess[game.current_guess_length] = toupper(key);
game.current_guess_length++;
game.current_guess[game.current_guess_length] = '\0';
strcpy(message, "");
}
}
}
endwin();
return 0;
}
/* Main entry point */
2025-12-17 09:28:00 +00:00
int main(int argc, char *argv[]) {
2025-10-06 13:58:25 +00:00
int i;
/* Handle help */
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) {
printf("cordle - C90 Wordle Game\n\n");
printf("Usage: %s [OPTIONS]\n\n", argv[0]);
printf("Difficulty Levels:\n");
printf(" --easy Common everyday words (default)\n");
printf(" --medium Standard vocabulary\n");
printf(" --hard Challenging words\n\n");
printf("Word Categories:\n");
printf(" --techy Technical and scientific terms\n");
printf(" --literary Literary and archaic terms\n");
printf(" --cultural Cultural and international terms\n");
printf(" --full Complete dictionary\n\n");
printf("Custom:\n");
printf(" --wordlist FILE Use custom word list\n\n");
printf("Examples:\n");
printf(" %s --easy\n", argv[0]);
printf(" %s --techy\n", argv[0]);
printf(" %s --wordlist mywords.txt\n", argv[0]);
return 0;
}
}
return main_game_loop(argc, argv);
2025-12-17 09:28:00 +00:00
}