Automated update

This commit is contained in:
klein panic
2025-02-28 22:00:25 -05:00
parent d891eb5237
commit a5f056237a
23 changed files with 424 additions and 302 deletions

23
Makefile Normal file
View File

@@ -0,0 +1,23 @@
CC = gcc
CFLAGS = -Wall -O2
LIBS = -lX11 -lm
SRC = src/main.c src/coin.c src/animation.c src/gui_animation.c
OBJDIR = obj
OBJ = $(OBJDIR)/main.o $(OBJDIR)/coin.o $(OBJDIR)/animation.o $(OBJDIR)/gui_animation.o
TARGET = coinfipper
all: $(TARGET)
$(TARGET): $(OBJ)
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
$(OBJDIR)/%.o: src/%.c | $(OBJDIR)
$(CC) $(CFLAGS) -c $< -o $@
$(OBJDIR):
mkdir -p $(OBJDIR)
clean:
rm -rf $(OBJDIR) $(TARGET)

View File

@@ -1,3 +0,0 @@
# coinflipper Project
This is a C project generated with the setup tool.

Binary file not shown.

View File

@@ -1,21 +0,0 @@
CC = gcc
CFLAGS = -I../include
OBJDIR = ../obj
SRCDIR = ../src
BINDIR = ../bin
TARGET = $(BINDIR)/coin_flip_random_number
OBJS = $(OBJDIR)/main.o
all: $(TARGET)
$(TARGET): $(OBJS)
@mkdir -p $(BINDIR)
$(CC) $(OBJS) -lncurses -o $(TARGET)
$(OBJDIR)/%.o: $(SRCDIR)/%.c
@mkdir -p $(OBJDIR)
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -rf $(OBJDIR) $(BINDIR)

BIN
coinfipper Executable file

Binary file not shown.

View File

@@ -1,7 +0,0 @@
#ifndef FUNCTIONS_H
#define FUNCTIONS_H
void flip_coin();
void generate_random_number(int lower, int upper);
#endif // FUNCTIONS_H

BIN
obj/animation.o Normal file

Binary file not shown.

BIN
obj/coin.o Normal file

Binary file not shown.

BIN
obj/gui_animation.o Normal file

Binary file not shown.

Binary file not shown.

219
src/animation.c Normal file
View File

@@ -0,0 +1,219 @@
#include "animation.h"
#include "coin.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#include <math.h>
#include <errno.h>
// Internal function declarations
static void run_terminal_animation(const char* final_result);
static void run_framebuffer_animation(const char* final_result);
static int is_framebuffer_available();
static void draw_ascii_coin(int width, int height, const char* face);
static void draw_fb_detailed_coin(char* fbp, struct fb_var_screeninfo vinfo,
struct fb_fix_screeninfo finfo, int centerX,
int centerY, int radius, const char* face);
void run_animation(const char* final_result) {
if (is_framebuffer_available()) {
run_framebuffer_animation(final_result);
} else {
run_terminal_animation(final_result);
}
}
// Try opening /dev/fb0 to see if a framebuffer is available.
static int is_framebuffer_available() {
int fb = open("/dev/fb0", O_RDWR);
if (fb < 0) {
return 0; // Not available.
}
close(fb);
return 1;
}
// Draw an ASCII coin with “engraved” border and pattern.
// If face is nonempty, the coins center will show the final coin flip result.
static void draw_ascii_coin(int width, int height, const char* face) {
for (int y = -height; y <= height; y++) {
for (int x = -width; x <= width; x++) {
float dx = (float)x / width;
float dy = (float)y / height;
if (dx*dx + dy*dy <= 1.0f) {
// Near the edge, print a border engraving.
float dist = dx*dx + dy*dy;
if (dist > 0.85f)
printf("#");
else {
// Alternate pattern to simulate fine engraving detail.
if (((x + y) % 2) == 0)
printf(".");
else
printf(" ");
}
} else {
printf(" ");
}
}
printf("\n");
}
// If space allows, center the coin flip result as if engraved.
if (strlen(face) > 0) {
int totalWidth = width * 2 + 1;
int textLen = strlen(face);
int padding = (totalWidth - textLen) / 2;
for (int i = 0; i < padding; i++) printf(" ");
printf("[%s]\n", face);
} else {
printf("\n");
}
}
// Terminal animation: simulates a coin flip by scaling the coins horizontal radius.
static void run_terminal_animation(const char* final_result) {
int total_frames = 60;
int base_width = 12;
int base_height = 6;
for (int frame = 0; frame < total_frames; frame++) {
float factor = fabs(sin(frame * M_PI / total_frames));
int current_width = (int)(base_width * factor);
if (current_width < 1) current_width = 1;
// Clear the terminal screen.
printf("\033[H\033[J");
draw_ascii_coin(current_width, base_height, "");
usleep(30000);
}
// Final engraved coin.
printf("\033[H\033[J");
draw_ascii_coin(base_width, base_height, final_result);
printf("\nFinal Result: %s\n", final_result);
sleep(2);
}
// Helper to set a pixel in the framebuffer (supports 32bpp and 16bpp).
static void set_pixel(char* fbp, struct fb_var_screeninfo vinfo, long x, long y, unsigned int color) {
if (x < 0 || y < 0 || x >= vinfo.xres || y >= vinfo.yres) return;
long location = (x + y * vinfo.xres) * (vinfo.bits_per_pixel / 8);
if (vinfo.bits_per_pixel == 32) {
*((unsigned int*)(fbp + location)) = color;
} else if (vinfo.bits_per_pixel == 16) {
unsigned short col = (unsigned short)color;
*((unsigned short*)(fbp + location)) = col;
}
}
// Draw a detailed coin on the framebuffer with simulated engravings.
// The coin is drawn as a circle with a dark border, inner engraving line, and a subtle pattern.
// If face is nonempty, extra marks (simulating a portrait or reverse) are drawn.
static void draw_fb_detailed_coin(char* fbp, struct fb_var_screeninfo vinfo,
struct fb_fix_screeninfo finfo, int centerX,
int centerY, int radius, const char* face) {
// Define colors (in 0xRRGGBB format conversion may be needed on some systems).
unsigned int gold = 0xFFD700; // Base gold fill.
unsigned int darkGold = 0xB8860B; // Border and detail.
unsigned int engravingColor = 0x8B7500; // For fine engraving lines.
for (int y = -radius; y <= radius; y++) {
for (int x = -radius; x <= radius; x++) {
float dx = (float)x / radius;
float dy = (float)y / radius;
if (dx*dx + dy*dy <= 1.0f) {
int px = centerX + x;
int py = centerY + y;
float dist = sqrt(dx*dx + dy*dy);
if (dist > 0.9f) {
set_pixel(fbp, vinfo, px, py, darkGold);
} else if (fabs(dist - 0.5f) < 0.05f) {
set_pixel(fbp, vinfo, px, py, engravingColor);
} else {
set_pixel(fbp, vinfo, px, py, gold);
}
}
}
}
// Overlay additional detail based on coin face.
if (strlen(face) > 0) {
if (strcmp(face, "Heads") == 0) {
// Simulate a simplified portrait engraving.
for (int y = -radius/4; y <= radius/4; y++) {
for (int x = -radius/4; x <= radius/4; x++) {
if ((x + y) % 3 == 0) {
set_pixel(fbp, vinfo, centerX + x, centerY + y, darkGold);
}
}
}
} else {
// Simulate reverse-side engraving.
for (int y = -radius/4; y <= radius/4; y++) {
for (int x = -radius/4; x <= radius/4; x++) {
if ((x - y) % 3 == 0) {
set_pixel(fbp, vinfo, centerX + x, centerY + y, darkGold);
}
}
}
}
}
}
// Framebuffer animation: flips the coin with a scaling effect and then renders the final engraved coin.
static void run_framebuffer_animation(const char* final_result) {
int fb_fd = open("/dev/fb0", O_RDWR);
if (fb_fd < 0) {
perror("Error opening /dev/fb0");
return;
}
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;
if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &finfo)) {
perror("Error reading fixed information");
close(fb_fd);
return;
}
if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &vinfo)) {
perror("Error reading variable information");
close(fb_fd);
return;
}
long screensize = vinfo.yres_virtual * finfo.line_length;
char *fbp = (char *) mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0);
if (fbp == MAP_FAILED) {
perror("Error: failed to map framebuffer device to memory");
close(fb_fd);
return;
}
int centerX = vinfo.xres / 2;
int centerY = vinfo.yres / 2;
int radius = (vinfo.yres < vinfo.xres ? vinfo.yres : vinfo.xres) / 8;
int total_frames = 60;
for (int f = 0; f < total_frames; f++) {
float factor = fabs(sin(f * M_PI / total_frames));
int currentRadius = (int)(radius * factor);
if (currentRadius < 1) currentRadius = 1;
// Clear the framebuffer (black).
memset(fbp, 0, screensize);
draw_fb_detailed_coin(fbp, vinfo, finfo, centerX, centerY, currentRadius, "");
usleep(50000);
}
// Final coin engraving showing the actual flip result.
memset(fbp, 0, screensize);
draw_fb_detailed_coin(fbp, vinfo, finfo, centerX, centerY, radius, final_result);
usleep(2000000);
munmap(fbp, screensize);
close(fb_fd);
}

9
src/animation.h Normal file
View File

@@ -0,0 +1,9 @@
#ifndef ANIMATION_H
#define ANIMATION_H
// Runs the coin flipping animation for the terminal or framebuffer.
// The final_result ("Heads" or "Tails") is used to choose the engraved design.
void run_animation(const char* final_result);
#endif

BIN
src/animation.o Normal file

Binary file not shown.

13
src/coin.c Normal file
View File

@@ -0,0 +1,13 @@
#include "coin.h"
#include <stdlib.h>
#include <time.h>
const char* flip_coin() {
// Seed random number generator (for a simple example; in a larger program, you might do this once in main)
srand(time(NULL));
if (rand() % 2 == 0)
return "Heads";
else
return "Tails";
}

8
src/coin.h Normal file
View File

@@ -0,0 +1,8 @@
#ifndef COIN_H
#define COIN_H
// Returns "Heads" or "Tails"
const char* flip_coin();
#endif

BIN
src/coin.o Normal file

Binary file not shown.

116
src/gui_animation.c Normal file
View File

@@ -0,0 +1,116 @@
#include "gui_animation.h"
#include "coin.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#ifndef M_PI
#define M_PI 3.14159
#endif
// Draw a detailed coin in the X11 window using drawing primitives.
static void draw_gui_detailed_coin(Display *d, Window win, GC gc, int win_width, int win_height, int radius, const char* face) {
// Define colors.
unsigned long gold = 0xFFD700;
unsigned long darkGold = 0xB8860B;
unsigned long engravingColor = 0x8B7500;
int coin_diameter = radius * 2;
int x = (win_width - coin_diameter) / 2;
int y = (win_height - coin_diameter) / 2;
// Fill coin circle with gold.
XSetForeground(d, gc, gold);
XFillArc(d, win, gc, x, y, coin_diameter, coin_diameter, 0, 360*64);
// Draw outer border.
XSetForeground(d, gc, darkGold);
XDrawArc(d, win, gc, x, y, coin_diameter, coin_diameter, 0, 360*64);
// Draw an inner engraving circle.
int inner_diameter = coin_diameter * 0.7;
int inner_x = (win_width - inner_diameter) / 2;
int inner_y = (win_height - inner_diameter) / 2;
XSetForeground(d, gc, engravingColor);
XDrawArc(d, win, gc, inner_x, inner_y, inner_diameter, inner_diameter, 0, 360*64);
// Overlay text to simulate the coins face engraving.
char text[50];
if (strcmp(face, "Heads") == 0)
snprintf(text, sizeof(text), "LIBERTY");
else
snprintf(text, sizeof(text), "E PLURIBUS UNUM");
/* Instead of using DefaultFont (which is undefined), we load the "fixed" font */
XFontStruct *font = XLoadQueryFont(d, "fixed");
if (!font) {
fprintf(stderr, "Failed to load font 'fixed'\n");
return;
}
XSetFont(d, gc, font->fid);
int text_width = XTextWidth(font, text, strlen(text));
int text_x = (win_width - text_width) / 2;
int text_y = win_height / 2;
XSetForeground(d, gc, darkGold);
XDrawString(d, win, gc, text_x, text_y, text, strlen(text));
XFreeFont(d, font);
}
// GUI animation: uses X11 to animate a coin flip with a scaling (flipping) effect
// and then renders the final detailed coin with engravings.
void run_gui_animation(const char* final_result) {
char *display_name = getenv("DISPLAY");
if (!display_name) {
fprintf(stderr, "No DISPLAY environment variable set. Cannot run GUI animation.\n");
return;
}
Display *d = XOpenDisplay(NULL);
if (d == NULL) {
fprintf(stderr, "Unable to open X display.\n");
return;
}
int screen = DefaultScreen(d);
int win_width = 500, win_height = 500;
Window win = XCreateSimpleWindow(d, RootWindow(d, screen), 100, 100, win_width, win_height, 1,
BlackPixel(d, screen), WhitePixel(d, screen));
XSelectInput(d, win, ExposureMask | KeyPressMask);
XMapWindow(d, win);
// Wait for an expose event.
XEvent e;
while (1) {
XNextEvent(d, &e);
if (e.type == Expose)
break;
}
GC gc = XCreateGC(d, win, 0, 0);
int total_frames = 60;
int coin_radius = 100;
for (int frame = 0; frame < total_frames; frame++) {
XClearWindow(d, win);
float factor = fabs(sin(frame * M_PI / total_frames));
int current_radius = (int)(coin_radius * factor);
if (current_radius < 1) current_radius = 1;
draw_gui_detailed_coin(d, win, gc, win_width, win_height, current_radius, "");
XFlush(d);
usleep(50000);
}
// Final engraved coin.
XClearWindow(d, win);
draw_gui_detailed_coin(d, win, gc, win_width, win_height, coin_radius, final_result);
XFlush(d);
sleep(3);
XCloseDisplay(d);
}

9
src/gui_animation.h Normal file
View File

@@ -0,0 +1,9 @@
#ifndef GUI_ANIMATION_H
#define GUI_ANIMATION_H
// Runs the GUI-based coin flip animation in an X11 window.
// The final_result ("Heads" or "Tails") determines the engraved design.
void run_gui_animation(const char* final_result);
#endif

BIN
src/gui_animation.o Normal file

Binary file not shown.

View File

@@ -1,190 +1,35 @@
#include <stdio.h>
#include <string.h>
#include "coin.h"
#include "animation.h"
#include "gui_animation.h"
#include <stdlib.h>
#include <time.h>
#include <ncurses.h>
#include <unistd.h> // For usleep()
#include <unistd.h>
#define DELAY 300000 // 300 ms delay for animation
// Function prototypes
void flip_coin();
void generate_random_number(int lower, int upper);
void coin_animation(int result);
void random_number_animation(int num);
void handle_exit();
int main() {
int choice, lower, upper;
srand(time(NULL)); // Seed the random number generator
// Initialize ncurses
initscr();
noecho();
cbreak();
curs_set(0);
keypad(stdscr, TRUE); // Enable arrow keys and special keys
int term_height, term_width;
getmaxyx(stdscr, term_height, term_width); // Get terminal size
while (1) {
clear();
mvprintw(term_height / 2 - 3, (term_width - 35) / 2, "Choose an option (Press 'q' or 'Esc' to quit):");
mvprintw(term_height / 2 - 1, (term_width - 20) / 2, "1. Flip a coin");
mvprintw(term_height / 2, (term_width - 20) / 2, "2. Generate a random number");
mvprintw(term_height / 2 + 1, (term_width - 20) / 2, "3. Exit");
mvprintw(term_height / 2 + 3, (term_width - 20) / 2, "Enter your choice: ");
refresh();
char input = getch();
choice = input - '0';
if (input == 'q' || input == 27) { // 'q' or 'Esc'
handle_exit();
}
switch (choice) {
case 1:
clear();
flip_coin();
break;
case 2:
clear();
mvprintw(4, 4, "Enter the lower bound: ");
echo();
scanw("%d", &lower);
mvprintw(5, 4, "Enter the upper bound: ");
scanw("%d", &upper);
noecho();
clear();
generate_random_number(lower, upper);
break;
case 3:
handle_exit();
break;
default:
mvprintw(10, 4, "Invalid choice, please try again.");
refresh();
usleep(1000000); // Pause for 1 second before clearing
int main(int argc, char **argv) {
int animate_flag = 0;
int gui_flag = 0;
// Parse command-line arguments
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "-A") == 0 || strcmp(argv[i], "--animation") == 0) {
animate_flag = 1;
} else if (strcmp(argv[i], "-G") == 0 || strcmp(argv[i], "--gui") == 0) {
gui_flag = 1;
}
}
endwin(); // End ncurses mode
// Determine coin flip result once.
const char *result = flip_coin();
if (gui_flag) {
run_gui_animation(result);
} else if (animate_flag) {
run_animation(result);
} else {
printf("%s\n", result);
}
return 0;
}
void flip_coin() {
int result = rand() % 2;
coin_animation(result);
if (result == 0)
mvprintw(LINES - 2, (COLS - 7) / 2, "Heads!"); // Align below the animation
else
mvprintw(LINES - 2, (COLS - 7) / 2, "Tails!");
refresh();
usleep(2000000); // Display result for 2 seconds
}
void generate_random_number(int lower, int upper) {
if (lower > upper) {
mvprintw(8, 4, "Invalid range! Lower bound must be less than or equal to upper bound.");
refresh();
usleep(2000000); // Pause for 2 seconds
return;
}
int num = (rand() % (upper - lower + 1)) + lower;
random_number_animation(num);
mvprintw(10, 4, "Random number: %d", num);
refresh();
usleep(2000000); // Display result for 2 seconds
}
void coin_animation(int result) {
const char *flat_coin =
" _______ \n"
" | | \n"
" |_______| \n";
const char *first_circle_coin =
" ______ \n"
" / \\ \n"
" | | \n"
" \\______/ \n";
const char *second_circle_coin =
" ____ \n"
" // \\ \n"
" | | \n"
" \\____// \n";
const char *side_coin_vertical =
" |=| \n"
" |=| \n"
" |=| \n"
" |=| \n";
const char *side_coin_horizontal =
" _______ \n"
" ||||||| \n"
" ¯¯¯¯¯¯¯ \n";
int height = 5; // Height the coin will "move" up
// Center coin horizontally
int x_center = (COLS - 11) / 2;
// Animating the coin going up and down with better alignment
for (int i = 0; i < height; i++) {
clear();
if (i == 2) {
mvprintw(4 + i, x_center, "%s", first_circle_coin); // Coin facing the user at the peak
} else if (i == 1 || i == 3) {
mvprintw(4 + i, x_center, "%s", side_coin_vertical); // Vertical side coin
} else {
mvprintw(4 + i, x_center, "%s", flat_coin); // Flat coin at start and end
}
refresh();
usleep(DELAY);
}
// Display the final result as heads or tails, with proper alignment
clear();
mvprintw(4 + height, x_center, "%s", second_circle_coin); // Show circle coin
if (result == 0) {
mvprintw(6 + height, x_center + 4, "O"); // Center the "O" inside the coin
} else {
mvprintw(6 + height, x_center + 4, "X"); // Center the "X" inside the coin
}
refresh();
}
void random_number_animation(int num) {
char *box_top = "+--------+\n";
char *box_bottom = "+--------+\n";
char number_display[20];
// Handle different number lengths
if (num < 10) {
sprintf(number_display, "| %d |\n", num);
} else if (num < 100) {
sprintf(number_display, "| %d |\n", num);
} else {
sprintf(number_display, "| %d |\n", num);
}
int x_center = (COLS - 10) / 2;
for (int i = 0; i < 5; i++) {
clear();
mvprintw(4, x_center, "%s", box_top);
mvprintw(5, x_center, "%s", number_display);
mvprintw(6, x_center, "%s", box_bottom);
refresh();
usleep(DELAY);
}
}
void handle_exit() {
endwin(); // End ncurses mode
exit(0);
}

View File

@@ -1,58 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// Function prototypes
void flip_coin();
void generate_random_number(int lower, int upper);
int main() {
int choice, lower, upper;
srand(time(NULL)); // Seed the random number generator
while (1) {
printf("\nChoose an option:\n");
printf("1. Flip a coin\n");
printf("2. Generate a random number\n");
printf("3. Exit\n");
printf("Enter your choice: ");
scanf("%d", &choice);
switch (choice) {
case 1:
flip_coin();
break;
case 2:
printf("Enter the lower bound: ");
scanf("%d", &lower);
printf("Enter the upper bound: ");
scanf("%d", &upper);
generate_random_number(lower, upper);
break;
case 3:
exit(0);
default:
printf("Invalid choice, please try again.\n");
}
}
return 0;
}
void flip_coin() {
int result = rand() % 2;
if (result == 0)
printf("Heads!\n");
else
printf("Tails!\n");
}
void generate_random_number(int lower, int upper) {
if (lower > upper) {
printf("Invalid range! Lower bound must be less than or equal to upper bound.\n");
return;
}
int num = (rand() % (upper - lower + 1)) + lower;
printf("Random number: %d\n", num);
}

BIN
src/main.o Normal file

Binary file not shown.

31
tags
View File

@@ -1,31 +0,0 @@
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
!_TAG_OUTPUT_EXCMD mixed /number, pattern, mixed, or combineV2/
!_TAG_OUTPUT_FILESEP slash /slash or backslash/
!_TAG_OUTPUT_MODE u-ctags /u-ctags or e-ctags/
!_TAG_PATTERN_LENGTH_LIMIT 96 /0 for no limit/
!_TAG_PROC_CWD /home/klein/codeWS/C/coinflipper/ //
!_TAG_PROGRAM_AUTHOR Universal Ctags Team //
!_TAG_PROGRAM_NAME Universal Ctags /Derived from Exuberant Ctags/
!_TAG_PROGRAM_URL https://ctags.io/ /official site/
!_TAG_PROGRAM_VERSION 5.9.0 //
$(OBJDIR)/%.o build/Makefile /^$(OBJDIR)\/%.o: $(SRCDIR)\/%.c$/;" t
$(TARGET) build/Makefile /^$(TARGET): $(OBJS)$/;" t
BINDIR build/Makefile /^BINDIR = ..\/bin$/;" m
CC build/Makefile /^CC = gcc$/;" m
CFLAGS build/Makefile /^CFLAGS = -I..\/include$/;" m
DELAY src/main.c /^#define DELAY /;" d file:
FUNCTIONS_H include/functions.h /^#define FUNCTIONS_H$/;" d
OBJDIR build/Makefile /^OBJDIR = ..\/obj$/;" m
OBJS build/Makefile /^OBJS = $(OBJDIR)\/main.o$/;" m
SRCDIR build/Makefile /^SRCDIR = ..\/src$/;" m
TARGET build/Makefile /^TARGET = $(BINDIR)\/coin_flip_random_number$/;" m
all build/Makefile /^all: $(TARGET)$/;" t
clean build/Makefile /^clean:$/;" t
coin_animation src/main.c /^void coin_animation(int result) {$/;" f typeref:typename:void
coinflipper Project README.md /^# coinflipper Project$/;" c
flip_coin src/main.c /^void flip_coin() {$/;" f typeref:typename:void
generate_random_number src/main.c /^void generate_random_number(int lower, int upper) {$/;" f typeref:typename:void
handle_exit src/main.c /^void handle_exit() {$/;" f typeref:typename:void
main src/main.c /^int main() {$/;" f typeref:typename:int
random_number_animation src/main.c /^void random_number_animation(int num) {$/;" f typeref:typename:void