Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions .Jules/palette.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
**Learning:** In terminal-based games, users expect immediate visual feedback for their actions. Relying on a periodic "tick" to update the UI creates a laggy feel. Using `poll()` with a dynamic timeout allows the application to remain idle yet wake up instantly to process and render user input.
**Action:** Always trigger a UI refresh immediately after processing user input in CLI applications, and use efficient waiting mechanisms (like `poll`) that can be interrupted by input.

## 2026-02-26 - Fairness in Countdown Transitions
**Learning:** In time-sensitive CLI games, users often "prime" their fingers during a countdown. If input buffering is not handled, these preparatory presses can lead to an unfair head start or unexpected behavior when the game officially begins. Using `tcflush(STDIN_FILENO, TCIFLUSH)` immediately after the countdown ensures a clean state for the game loop.
**Action:** Always flush the input buffer after a blocking UI transition (like a countdown) in interactive CLI applications.
## 2026-05-23 - Ensuring a Fair Start in CLI Games
**Learning:** Users often spam keys during a game's countdown phase in anticipation. If these inputs are buffered and processed immediately when the game starts, it can lead to an unfair advantage or accidental actions. Using `tcflush(STDIN_FILENO, TCIFLUSH)` after the countdown ensures the game starts with a clean slate.
**Action:** Always clear the input buffer with `tcflush` after a blocking countdown or transition period in interactive CLI applications to ensure intent-based interaction.

## 2026-05-24 - Live High Score as Gamification UX
**Learning:** In simple CLI games, providing live high-score tracking (e.g., "Score: 10 | High: 10") that updates the moment a record is broken creates immediate "micro-delight" and encourages continued engagement. Seeing the "High" value match the "Score" in real-time is a powerful psychological reward.
**Action:** Implement live-updating progress or record indicators in interactive CLI tools to provide immediate positive reinforcement.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,5 @@ highscore.txt
# debug information files
*.dwo

# Local game data
# Game data
highscore.txt
34 changes: 20 additions & 14 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,19 @@ int main() {
return 1;
}

// Hide cursor
std::cout << HIDE_CURSOR << std::flush;
long long highscore = 0;
std::ifstream hsFile("highscore.txt");
if (hsFile.is_open()) {
hsFile >> highscore;
hsFile.close();
}

long long score = 0; bool hardMode = false; char input;
long long highscore = load_highscore();
long long initialHighscore = highscore;

std::cout << CLR_CTRL << "==========================\n SPEED CLICKER\n==========================\n" << CLR_RESET
<< CLR_SCORE << " CURRENT HIGH SCORE: " << highscore << CLR_RESET << "\n\n"
<< "Controls:\n " << CLR_CTRL << "[h]" << CLR_RESET << " Toggle Hard Mode (10x Speed!)\n "
<< CLR_CTRL << "[q]" << CLR_RESET << " Quit Game\n " << CLR_CTRL << "[Any key]" << CLR_RESET << " Click!\n\n";

Expand Down Expand Up @@ -115,27 +120,28 @@ int main() {
}

if (updateUI) {
highscore = std::max(highscore, score);
std::cout << "\r" << CLR_SCORE << "Score: " << score << CLR_RESET
<< " (High: " << highscore << ") "
<< (hardMode ? CLR_HARD "[HARD MODE]" : CLR_NORM "[NORMAL MODE]");

if (score > initialHighscore && initialHighscore > 0) {
std::cout << CLR_CTRL << " NEW BEST! 🎉" << CLR_RESET;
}

std::cout << " " << std::flush;
<< " | High: " << (score > highscore ? score : highscore) << " "
<< (hardMode ? CLR_HARD "[HARD MODE]" : CLR_NORM "[NORMAL MODE]")
<< " " << std::flush;
updateUI = false;
}
}

save_highscore(highscore);

tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
std::cout << SHOW_CURSOR << "\n\n" << CLR_SCORE << "Final Score: " << score << CLR_RESET << "\n";
if (score > initialHighscore && initialHighscore > 0) {
std::cout << CLR_CTRL << "CONGRATULATIONS! New High Score! 🏆" << CLR_RESET << "\n";
std::cout << "\n\n" << CLR_SCORE << "Final Score: " << score << CLR_RESET << "\n";

if (score > highscore) {
std::cout << CLR_NORM << "NEW HIGH SCORE! " << CLR_RESET << "Previous was " << highscore << "\n";
std::ofstream hsFileOut("highscore.txt");
if (hsFileOut.is_open()) {
hsFileOut << score;
hsFileOut.close();
}
}

std::cout << "Thanks for playing!\n";
return 0;
}
Loading