Compare commits

...
20 Commits
Author SHA1 Message Date
david ae45941a78 hi 2026-10-04 18:22:55 -03:00
david 6b3829ef58 i'm suck a fucking genius 2026-09-20 07:59:28 -03:00
david 9cf79cf6c6 buy prizes 2026-09-02 05:42:54 -03:00
david f8e9e17995 prizes 2026-09-01 21:26:03 -03:00
david e47fb3a03b savefile for gameclicker 2026-08-14 15:43:39 -03:00
david e0fd9d5497 you can buy rats now 2026-08-11 23:58:43 -03:00
david f21bfbfacc i remembered my password 2026-08-11 10:32:14 -03:00
david acb78f0835 fixed a couple bugs 2026-07-28 03:23:28 -03:00
david 64d81da061 configure 2026-07-25 15:34:58 -03:00
david 8d63c9dd1c segfault if you go to negative numbers in the maze game... 2026-07-25 05:05:21 -03:00
david 20da733459 grrr 2026-07-24 19:52:49 -03:00
david b145cdc432 i should have written this by hand and not asked claude to do it 2026-07-24 19:45:32 -03:00
david b4353216cc how did that get here 2026-07-24 18:43:26 -03:00
david 63734e8f69 CONFIGURE YAYY BETTER BUILD METHODS git add .git add .git add .! ANYTHING BUT WRITING ACTUAL CODEgit add .git add .git add .git add .git add .git add .git add .git add .git add .git add .git add .git add .git add .git add .git add .git add . 2026-07-24 18:41:53 -03:00
david 9e5372a6db CONFIGURE YAYY BETTER BUILD METHODS lslsls! ANYTHING BUT WRITING ACTUAL CODElslslslslslslslslslslslslslslsls 2026-07-24 18:40:14 -03:00
david d64804517b turns out this was a gentoo thing. most people don't need ltinfo 2026-07-24 17:58:12 -03:00
david 17881c653f fixed a couple bugs 2026-07-23 22:12:42 -03:00
david 9765de97f1 added a box to everyone and cleaned up things a bit 2026-07-22 04:38:12 -03:00
david fa3d08f0a6 did a bunch of this idfk man check the diff 2026-07-20 03:18:40 -03:00
david 60894c955e i should commit every time i do something new instead of whenever i feel like 2026-07-18 22:31:52 -03:00
15 changed files with 5765 additions and 296 deletions

No files matched your search

+5
View File
@@ -1 +1,6 @@
petratc
obj/
config.log
config.status
autom4te.cache/
Makefile
-18
View File
@@ -1,18 +0,0 @@
CC = gcc
CFLAGS = -Wall -Wextra -O2 -pipe
LDLIBS = -lncurses -ltinfo
TARGET = petratc
SRC = petratc.c $(wildcard games/*.c)
PREFIX = /usr/local
$(TARGET): $(SRC)
$(CC) $(CFLAGS) -o $(TARGET) $(SRC) $(LDLIBS)
install: $(TARGET)
install -D $(TARGET) $(DESTDIR)$(PREFIX)/bin/$(TARGET)
uninstall:
rm -f $(DESTDIR)$(PREFIX)/bin/$(TARGET)
clean:
rm -f $(TARGET)
+27
View File
@@ -0,0 +1,27 @@
CC = @CC@
CFLAGS = -Wall -Wextra -O2 -pipe
LDLIBS = @CURSES_LIB@
TARGET = petratc
CONF = configure configure~ config.log config.status Makefile autom4te.cache/
SRC = petratc.c rat.c $(wildcard games/*.c)
OBJ = $(SRC:%.c=obj/%.o)
PREFIX = /usr/local
$(TARGET): $(OBJ)
$(CC) $(CFLAGS) -o $(TARGET) $(OBJ) $(LDLIBS)
install: $(TARGET)
install -D $(TARGET) $(DESTDIR)$(PREFIX)/bin/$(TARGET)
uninstall:
rm -f $(DESTDIR)$(PREFIX)/bin/$(TARGET)
obj/%.o: %.c
@mkdir -p $(@D)
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -f $(TARGET) $(OBJ)
bigclean:
rm -rf $(TARGET) $(OBJ) $(CONF)
+12 -2
View File
@@ -2,11 +2,21 @@
# installing:
```term
make && sudo make install
./configure && make && sudo make install
```
also, you'll need `ncurses-devel` to compile it
that's pretty much it lol
you have no clue what sudo is? check the [wiki](https://github.com/davideldios7/petratc/wiki) out!
# IF IT FAILS
if for whatever reason `./configure` fails try running this
```term
make bigclean && autoconf && ./configure && make
```
you will need autoconf installed though
# you have no clue what sudo is? check the [wiki](https://github.com/davideldios7/petratc/wiki) out!
# if someone wants to make a game please make a pull request i don't know how to code
Vendored Executable
+4671
View File
File diff suppressed because it is too large. Load diff
+22
View File
@@ -0,0 +1,22 @@
AC_INIT([petratc], [1.0])
AC_CONFIG_SRCDIR([petratc.c])
AC_PROG_CC
#what if i have pdcurses or just curses and not ncurses idk
#this will be useful only when i decide to port it to widnows
CURSES_LIB=""
AC_CHECK_LIB([ncurses], [initscr], [CURSES_LIB="-lncurses"])
AS_IF([test "x$CURSES_LIB" = "x"],
[AC_CHECK_LIB([curses], [initscr], [CURSES_LIB="-lcurses"])])
AS_IF([test "x$CURSES_LIB" = "x"],
[AC_CHECK_LIB([pdcurses], [initscr], [CURSES_LIB="-lpdcurses"])])
AS_IF([test "x$CURSES_LIB" = "x"],
[AC_MSG_ERROR([no curses library found (ncurses, curses, pdcurses)])])
#in mac having -ltinfo in your makefile gives you a linker error
#whereas in linux you need it
AC_CHECK_LIB([tinfo], [setupterm], [CURSES_LIB="$CURSES_LIB -ltinfo"])
AC_SUBST([CURSES_LIB])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
-9
View File
@@ -1,9 +0,0 @@
#ifndef defs_h
#define defs_h
void gameguess(void);
void gamecatch(void);
void gamemaze(void);
void gameclicker(void);
#endif
+23 -29
View File
@@ -1,8 +1,3 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <ncurses.h>
#include "../rat.h"
/*
@@ -34,13 +29,13 @@
// i just realized this is basically cmatrix with a little guy at the bottom
*/
#define width 40
#define height getmaxy(stdscr)
#define maxdrops 70
static int running;
static int won;
static int howmany;
static int width;
static int height;
typedef struct{
@@ -85,17 +80,11 @@ static void stop() {
void gamecatch(){
srand(time(NULL)); //@sagucs hey
static int initialized = 0;
if(initialized == 0){ initscr();}else{refresh();} // turns out you don't wanna call initscr() many times per session so do this because it glitches otherwise
++initialized;
howmany = 0;
noecho();
cbreak();
nodelay(stdscr, TRUE);
keypad(stdscr, TRUE);
curs_set(0);
WINDOW *win = ratdrawbox();
howmany = 0;
width = 40;
height = getmaxy(win) - 2;
cursor curs = {width / 2, {"(>.<)_", "_(>.<)"}, 0};
@@ -103,10 +92,9 @@ void gamecatch(){
running = 1;
while (running) {
if(!running){stop();}
int ch = getch();
switch (ch) {
case 'q': case 'Q': stop(); break;
case 'q': case 'Q': running = 0; break;
case 'a': case 'A': case KEY_LEFT:
curs.posx-= 2;
if(curs.posx < 0) curs.posx = width - 6;
@@ -123,18 +111,24 @@ void gamecatch(){
if (!running) break;
if (rand() % 10 < 3) spawndrops();
clear();
mvprintw(0, width + 2, "caught: %d/30", howmany);
mvprintw(1, width + 2, "(catch 30 to win!)");
mvprintw(2, width + 2, "move with A and D");
mvprintw(3, width + 2, "or the or the corresponding arrows");
werase(win);
box(win, 0, 0);
mvwvline(win, 1, width + 1, ACS_VLINE, height);
mvwaddch(win, 0, width + 1, ACS_TTEE);
mvwaddch(win, height + 1, width + 1, ACS_BTEE);
/*this should do it*/
mvwprintw(win, 1, width + 3, "caught: %d/30", howmany);
mvwprintw(win, 2, width + 3, "(catch 30 to win!)");
mvwprintw(win, 3, width + 3, "move with A and D");
mvwprintw(win, 4, width + 3, "or the or the corresponding arrows");
for (int i = 0; i < maxdrops; i++) {
if (droop[i].active) {
mvaddstr(droop[i].posy, droop[i].posx, droop[i].symbol);
mvwaddstr(win, droop[i].posy + 1, droop[i].posx + 1, droop[i].symbol);
droop[i].posy++;
if (droop[i].posy >= height) droop[i].active = 0;
@@ -143,14 +137,14 @@ void gamecatch(){
droop[i].posx <= curs.posx + 5) {
droop[i].active = 0;
howmany++;
if(howmany == 30){won = 1; running = 0; stop();}
if(howmany == 30){won = 1; running = 0;}
}
}
}
mvaddstr(height - 1, curs.posx, curs.face[curs.direction]);
mvwaddstr(win, height, curs.posx + 1, curs.face[curs.direction]);
refresh();
wrefresh(win);
usleep(100000);
}
+689 -36
View File
@@ -1,15 +1,12 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <ncurses.h>
#include "../rat.h"
#define width getmaxx(stdscr)
#define height getmaxy(stdscr)
/*
i lowkey stole the art of the little rat and the cheese from the internet lol
https://asciiart.website/art/752
*/
static int running;
int running;
int row = 1;
static void stop() {
clear();
@@ -18,43 +15,699 @@ static void stop() {
running = 0;
}
static char *cheeseart = {
" ()() ____\n (..) /|o |\n /\\/\\ /o| o|\nc\\db/o... /o_|_o_|"
};
//i hate this
/*
//i need to make a system based on intergers to represent non-int numbers like 0.5 or five trillion as 5T instead of 500000000000 or whatever
//how do i tell a computer that 1000 = 1k and 10000 = 10k and 1000000 = 1M and that etc
//i'll use powers of 10
//1^10x0 = 1 1^1(10x1) = 10 1^1(10x2) = 100 1^1(10x3) = 1k
// x*10^y <-- this is what i store
//1 becomes X. x can range from 0 to 999, when it reaches 999 it adds 1 to y and x goes back to 0
//is this memory safe????? yeah sure i don't see why it wouldnt
//x is a float or a double i think a double yeah a double
//
//and then print that as it should so 2.3^10x3 = 2.3k
//and also other functions to add or substract from this using regular numbers
//wait i could just do powers of 1000
//x is still 0.0 - 999.999 but it's x*1000^y
//55.3* 1000^2 = 55300000
//
//once x reaches 999.999 it wraps back to 0 and adds 1 to y
//then check y so that y = 0 is units, y = 1 is k, y = 2 is M, y = 3 is B, y = 4 is T, etc
*/
/*
//a bignum is just a scientific notation number
// x ^ 1000^y
// 55300 = 55.3*1000^1
// double x = 55.3
// int y = 1
*/
typedef struct bignum{
double x;
int y;
}bignum;
typedef struct ratworker{
char *name;
bignum price;
////line 67 six seveeennn
bignum clicks;
bignum multiplier; //the more you buy the more expensive the unit becomes
bignum owned;
}ratworker;
typedef struct{
char *name;
bignum price;
bignum multiplier;
char *whichstat;
int howmanystat; //how many times itc alls addstat() for that stat
}prizes;
#define nhowmanytiers 11
#define nhowmanyprizes 10
static char *digit[] = {
"", "K", "M", "B", "T",
"Qa", "Qi", "Sx", "Sp",
"Oc", "No", "Dc"
// up to y=11 (10^36) there's no way someone gets farther than this
};
static bignum normalize(double regnum){
bignum b;
double val = regnum;
int y = 0;
while (fabs(val) >= 1000) {
val /= 1000.0;
y++;
}
while (val != 0.0 && fabs(val) < 1) {
val *= 1000.0;
y--;
}
b.x = val;
b.y = y;
return b;
}
static bignum normalizebignum(bignum b){
double val = b.x;
int y = b.y;
while (fabs(val) >= 1000) {
val /= 1000.0;
y++;
}
while (val != 0.0 && fabs(val) < 1) {
val *= 1000.0;
y--;
}
b.x = val;
b.y = y;
return b;
}
static bignum addbignum(bignum a, bignum b){
bignum result;
if(a.y == b.y){
result.x = a.x + b.x;
result.y = a.y;
} else if(a.y > b.y){
double bx = b.x;
for(int i = a.y - b.y; i > 0; i--) bx /= 1000.0;
result.x = a.x + bx;
result.y = a.y;
} else {
double ax = a.x;
for(int i = b.y - a.y; i > 0; i--) ax /= 1000.0;
result.x = ax + b.x;
result.y = b.y;
}
return normalizebignum(result);
}
static bignum subbignum(bignum a, bignum b){
bignum result;
if(a.y == b.y){
result.x = a.x - b.x;
result.y = a.y;
} else if(a.y > b.y){
double bx = b.x;
for(int i = a.y - b.y; i > 0; i--) bx /= 1000.0;
result.x = a.x - bx;
result.y = a.y;
} else {
double ax = a.x;
for(int i = b.y - a.y; i > 0; i--) ax /= 1000.0;
result.x = ax - b.x;
result.y = b.y;
}
return normalizebignum(result);
}
static bignum mulbignum(bignum a, bignum b){
bignum result;
result.x = a.x * b.x;
result.y = a.y + b.y;
return normalizebignum(result);
}
static bignum divbignum(bignum a, bignum b){
bignum result;
result.x = a.x / b.x;
result.y = a.y - b.y;
return normalizebignum(result);
}
/*
* returns 1 if a is larger
* returns 0 if same number
* returns -1 is a is tiny
*/
static int comparebignum(bignum a, bignum b){
//branch predictors will hate this function :sob:
if(a.y == b.y){
if(a.x == b.x){
return 0;
}else if(a.x > b.x){
return 1;
}else return -1;
}else if(a.y > b.y){
return 1;
} else return -1;
}
static bignum addmixregbig(bignum a, double regnum){
return addbignum(a, normalize(regnum));
}
static bignum submixregbig(bignum a, double regnum){
return subbignum(a, normalize(regnum));
}
static bignum mulmixregbig(bignum a, double regnum){
return mulbignum(a, normalize(regnum));
}
static bignum divmixregbig(bignum a, double regnum){
return divbignum(a, normalize(regnum));
}
/* clamps a bignum to zero if it somehow goes negative */
static bignum clampnonneg(bignum b){
if(b.x < 0.0 || b.y < 0) return (bignum){0.0, 0};
return b;
}
static bignum calculateworkerincome(ratworker worker){
return mulbignum(worker.clicks, worker.owned);
}
static bignum calculatetotalincome(ratworker workers[], int n){
bignum total = {0.0, 0};
for(int i = 0; i < n; i++){
total = addbignum(total, calculateworkerincome(workers[i]));
}
return total;
}
static int buyworker(bignum *cheeses, ratworker *worker){
if(comparebignum(*cheeses, worker->price) < 0) return 0; //nigga broke
*cheeses = subbignum(*cheeses, worker->price);
*cheeses = clampnonneg(*cheeses);
worker->owned = addmixregbig(worker->owned, 1.0);
worker->price = mulbignum(worker->price, worker->multiplier);
return 1;
}
static int buyprize(bignum *cheeses, prizes *prize){
if(comparebignum(*cheeses, prize->price) < 0) return 0;
*cheeses = subbignum(*cheeses, prize->price);
*cheeses = clampnonneg(*cheeses);
prize->price = mulbignum(prize->price, prize->multiplier);
float *stat = NULL;
if(strcmp(prize->whichstat, "hunger") == 0) stat = &rat.hunger;
else if(strcmp(prize->whichstat, "health") == 0) stat = &rat.health;
else if(strcmp(prize->whichstat, "love") == 0) stat = &rat.love;
else if(strcmp(prize->whichstat, "fun") == 0) stat = &rat.fun;
else if(strcmp(prize->whichstat, "clean") == 0) stat = &rat.clean;
if(stat){
for(int i = 0; i < prize->howmanystat; i++){
addstat(stat);
}
}
return 1;
}
static char *bignumprint(bignum b) {
//32 bytes is more than enough for 124.24 trillion idk
char *nice = malloc(32 * sizeof(char));
if(nice == NULL) return NULL;
if(b.y >= 0 && b.y < 12) {
snprintf(nice, 32, "%.2lf%s", b.x, digit[b.y]);
} else{
snprintf(nice, 32, "%.2lfe3*%d", b.x, b.y);
}
return nice;
}
//wide = art and score side by side
//narrow = art on topand score below
typedef enum { layoutnarrow, layoutwide } layoutmode;
//bounding box of the drawn cheese art in winlocal coordinates for click detection
static int artrow0, artcol0, artrows, artcols;
static layoutmode getlayout(WINDOW *win){
return (getmaxx(win) >= getmaxy(win) * 2) ? layoutwide : layoutnarrow;
}
static void drawwin(WINDOW *win, bignum cheeses, ratworker workers[], int n){
werase(win);
box(win, 0, 0);
int winw = getmaxx(win);
layoutmode mode = getlayout(win);
char artcopy[2048];
strncpy(artcopy, cheeseart, sizeof(artcopy));
artcopy[sizeof(artcopy)-1] = '\0';
int artcol = 2;
int artrow = 1;
int scorecol, scorewrapw;
if(mode == layoutwide){
scorecol = winw / 2 - 25;
scorewrapw = winw - scorecol - 2;
} else {
scorecol = 2;
scorewrapw = winw - 4;
}
int row = artrow;
int widest = 0;
char *line = strtok(artcopy, "\n");
while(line){
mvwprintw(win, row, artcol, "%s", line);
int len = strlen(line);
if(len > widest) widest = len;
row++;
line = strtok(NULL, "\n");
}
//save where the art landed so the click handler knows what to hit-test against
artrow0 = artrow;
artcol0 = artcol;
artrows = row - artrow;
artcols = widest;
char *scorestr = bignumprint(cheeses);
char scoremsg[64];
if(scorestr != NULL) {
snprintf(scoremsg, sizeof(scoremsg), "cheese: %s", scorestr);
free(scorestr);
} else {
snprintf(scoremsg, sizeof(scoremsg), "cheese: ERROR");
}
char *incomestr = bignumprint(calculatetotalincome(workers, n));
char incomemsg[64];
if(incomestr != NULL) {
snprintf(incomemsg, sizeof(incomemsg), "income/s: %s", incomestr);
free(incomestr);
} else {
snprintf(incomemsg, sizeof(incomemsg), "income/s: ERROR");
}
if(mode == layoutwide){
mvwprintw(win, 1, scorecol, "%s", scoremsg);
mvwprintw(win, 2, scorecol, "%s", incomemsg);
wrapprint(win, 3, scorecol, scorewrapw, "click the cheese!");;
} else {
int scorerow = artrow0 + artrows + 1;
wrapprint(win, scorerow, scorecol, scorewrapw, scoremsg);
wrapprint(win, scorerow+1, scorecol, scorewrapw, incomemsg);
wrapprint(win, scorerow+2, scorecol, scorewrapw, "click the cheese!");
}
}
#define shopwidth 45
static void drawshop(WINDOW *win, ratworker workers[], int n, int selected, bignum cheeses, int active){
int winh = getmaxy(win);
int winw = getmaxx(win);
int shoph = n + 2;
if(shoph > winh / 2) shoph = winh / 2;
if(shoph > winh - 2) shoph = winh - 2;
int shopw = shopwidth;
if(shopw > winw - 4) shopw = winw - 4;
if(shoph < 3 || shopw < 10) return;
//if that skip it
int shopy;
if(getlayout(win) == layoutwide){
shopy = 1;
}else{
int pshoph = (nhowmanyprizes + 2);
if(pshoph > winh / 2) pshoph = winh / 2;
shopy = winh - shoph - pshoph - 1;
if(shopy < 1) shopy = 1;
}
int shopx = winw - shopw - 2;
mvwhline(win, shopy, shopx + 1, 0, shopw - 2);
mvwhline(win, shopy + shoph - 1, shopx + 1, 0, shopw - 2);
mvwvline(win, shopy + 1, shopx, 0, shoph - 2);
mvwvline(win, shopy + 1, shopx + shopw - 1, 0, shoph - 2);
mvwaddch(win, shopy, shopx, ACS_ULCORNER);
mvwaddch(win, shopy, shopx + shopw - 1, ACS_URCORNER);
mvwaddch(win, shopy + shoph - 1, shopx, ACS_LLCORNER);
mvwaddch(win, shopy + shoph - 1, shopx + shopw - 1, ACS_LRCORNER);
if(active) wattron(win, A_BOLD | A_REVERSE);
mvwprintw(win, shopy, shopx + 2, " workers (tab,up/down,enter) ");
if(active) wattroff(win, A_BOLD | A_REVERSE);
int availw = shopw - 2;
int visible = shoph - 2;
int start = 0;
if(selected >= visible) start = selected - visible + 1;
if(start > n - visible) start = n - visible;
if(start < 0) start = 0;
for(int i = start; i < start + visible && i < n; i++){
ratworker *w = &workers[i];
char *pricestr = bignumprint(w->price);
char *ownedstr = bignumprint(w->owned);
char rightstr[32];
snprintf(rightstr, sizeof(rightstr), "$%s x%s",
pricestr ? pricestr : "?", ownedstr ? ownedstr : "?");
if(pricestr) free(pricestr);
if(ownedstr) free(ownedstr);
int rightlen = strlen(rightstr);
int namewidth = availw - rightlen - 1; //-1 for a gap column
if(namewidth < 0) namewidth = 0;
char row[64];
//fill the whole width first so shrinking a wider row doesn't leave weird gaps
snprintf(row, sizeof(row), "%-*.*s", availw, availw, "");
int affordable = comparebignum(cheeses, w->price) >= 0;
if(active && i == selected) wattron(win, A_REVERSE);
else if(!affordable) wattron(win, A_DIM);
mvwprintw(win, shopy + 1 + (i - start), shopx + 1, "%s", row);
mvwprintw(win, shopy + 1 + (i - start), shopx + 1, "%-*.*s", namewidth, namewidth, w->name);
mvwprintw(win, shopy + 1 + (i - start), shopx + 1 + availw - rightlen, "%s", rightstr);
if(active && i == selected) wattroff(win, A_REVERSE);
else if(!affordable) wattroff(win, A_DIM);
}//bwehghg
}
#define pshopwidth 45
static void drawpshop(WINDOW *win, prizes prize[], int n, int selected, bignum cheeses, int active){
int winh = getmaxy(win);
int winw = getmaxx(win);
int shoph = n + 2;
if(shoph > winh / 2) shoph = winh / 2;
if(shoph > winh - 2) shoph = winh - 2;
int shopw = pshopwidth;
if(shopw > winw - 4) shopw = winw - 4;
if(shoph < 3 || shopw < 10) return;
//if that skip it
int shopx = winw - shopw - 2;
int shopy;
if(getlayout(win) == layoutwide){
int wshoph = nhowmanytiers + 2;
if(wshoph > winh / 2) wshoph = winh / 2;
shopy = 1 + wshoph;
if(shopy + shoph > winh - 1) shopy = winh - shoph - 1;
} else {
shopy = winh - shoph - 1;
if(shopy < 1) shopy = 1;
}
mvwhline(win, shopy, shopx + 1, 0, shopw - 2);
mvwhline(win, shopy + shoph - 1, shopx + 1, 0, shopw - 2);
mvwvline(win, shopy + 1, shopx, 0, shoph - 2);
mvwvline(win, shopy + 1, shopx + shopw - 1, 0, shoph - 2);
mvwaddch(win, shopy, shopx, ACS_ULCORNER);
mvwaddch(win, shopy, shopx + shopw - 1, ACS_URCORNER);
mvwaddch(win, shopy + shoph - 1, shopx, ACS_LLCORNER);
mvwaddch(win, shopy + shoph - 1, shopx + shopw - 1, ACS_LRCORNER);
if(active) wattron(win, A_BOLD | A_REVERSE);
mvwprintw(win, shopy, shopx + 2, " prizes (tab/up/down/enter) ");
if(active) wattroff(win, A_BOLD | A_REVERSE);
int availw = shopw - 2;
int visible = shoph - 2;
int start = 0;
if(selected >= visible) start = selected - visible + 1;
if(start > n - visible) start = n - visible;
if(start < 0) start = 0;
for(int i = start; i < start + visible && i < n; i++){
prizes *p = &prize[i];
char *pricestr = bignumprint(p->price);
char rightstr[32];
snprintf(rightstr, sizeof(rightstr), "$%s",
pricestr ? pricestr : "?");
if(pricestr) free(pricestr);
int rightlen = strlen(rightstr);
int namewidth = availw - rightlen - 1; //-1 for a gap column
if(namewidth < 0) namewidth = 0;
char row[64];
//fill the whole width first so shrinking a wider row doesn't leave weird gaps
snprintf(row, sizeof(row), "%-*.*s", availw, availw, "");
int affordable = comparebignum(cheeses, p->price) >= 0;
if(active && i == selected) wattron(win, A_REVERSE);
else if(!affordable) wattron(win, A_DIM);
mvwprintw(win, shopy + 1 + (i - start), shopx + 1, "%s", row);
mvwprintw(win, shopy + 1 + (i - start), shopx + 1, "%-*.*s", namewidth, namewidth, p->name);
mvwprintw(win, shopy + 1 + (i - start), shopx + 1 + availw - rightlen, "%s", rightstr);
if(active && i == selected) wattroff(win, A_REVERSE);
else if(!affordable) wattroff(win, A_DIM);
}//bwehghg
}
//i guess i will use this in a game... and i have plans
//for another game that will also require saving hehe
#ifdef __APPLE__
#define clickerpath "%s/Library/Application Support/rat"
#define clickersavepath "%s/Library/Application Support/rat/clicker.txt"
#else
#define clickerpath "%s/.local/share/rat"
#define clickersavepath "%s/.local/share/rat/clicker.txt"
#endif
static void clickersave(bignum cheeses, ratworker workers[], int n, prizes prize[], int n2){
char path[256];
snprintf(path, sizeof(path), clickerpath, getenv("HOME"));
mkdir(path, 0755);
snprintf(path, sizeof(path), clickersavepath, getenv("HOME"));
FILE *f = fopen(path, "w");
if(!f) return;
fprintf(f, "%lf\n%d\n", cheeses.x, cheeses.y);
for(int i = 0; i < n; i++){
fprintf(f, "%lf\n%d\n%lf\n%d\n",
workers[i].price.x, workers[i].price.y,
workers[i].owned.x, workers[i].owned.y);
}
for(int i = 0; i < n2; i++){
fprintf(f, "%lf\n%d\n", prize[i].price.x, prize[i].price.y);
}
fclose(f);
}
static void clickerload(bignum *cheeses, ratworker workers[], int n, prizes prize[], int n2){
char path[256];
snprintf(path, sizeof(path), clickersavepath, getenv("HOME"));
FILE *f = fopen(path, "r");
if(!f) return;
if(fscanf(f, "%lf\n%d\n", &cheeses->x, &cheeses->y) != 2){
fprintf(stderr, "error: failed to load clicker save data.\n");
fclose(f);
return;
}
for(int i = 0; i < n; i++){
if(fscanf(f, "%lf\n%d\n%lf\n%d\n",
&workers[i].price.x, &workers[i].price.y,
&workers[i].owned.x, &workers[i].owned.y) != 4){
fprintf(stderr, "error: failed to load clicker save data.\n");
break;
}
}
for(int i = 0; i < n2; i++){
if(fscanf(f, "%lf\n%d\n", &prize[i].price.x, &prize[i].price.y) != 2){
break;
}
}
fclose(f);
}
//i should make a version of this that just saves a big string
//so i can use many
//like generate the "save file" that returns a pointer to a char
//and then propersave(*thatchar, "file.txt") and it makes file.txt
//and it saves *thatchar to it idk this seems like a job for claude
typedef enum { SHOP_WORKERS, SHOP_PRIZES } shopmode;
static void draweverything(WINDOW *win, bignum cheeses, ratworker workers[], prizes prize[], int n, int n2,
int currentworker, int currentprize, shopmode active){
drawwin(win, cheeses, workers, n);
drawshop(win, workers, n, currentworker, cheeses, active == SHOP_WORKERS);
drawpshop(win, prize, n2, currentprize, cheeses, active == SHOP_PRIZES);
wrefresh(win);
}
#define spacedebouncems 20
static long nowms(void) {
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return ts.tv_sec * 1000L + ts.tv_nsec / 1000000L;
}
void gameclicker(){
srand(time(NULL));
static int initialized = 0;
if(!initialized){ initscr();}else{refresh();}
++initialized;
noecho();
cbreak();
nodelay(stdscr, TRUE);
keypad(stdscr, TRUE);
curs_set(0);
WINDOW *win = ratdrawbox();
mousemask(BUTTON1_PRESSED, NULL);
mouseinterval(0); //don't wait to resolve single vs double click
int winh = height * 0.96;
int winw = width * 0.96;
int boxy = (height - winh) / 2;
int boxx = (width - winw) / 2;
WINDOW *win = newwin(winh, winw, boxy, boxx);
box(win, 0, 0); //box?
running = 1;
bignum cheeses = {0.0, 0};
bignum onecheese = {1.0, 0}; //what a single click is worth
int currentworker = 0;
int currentprize = 0;
shopmode activeshop = SHOP_WORKERS;
static ratworker workers[nhowmanytiers] = {
//name, bignum price,clicks/tick,multiplier,owned (howmanyowned)
{ "small rat", {10.0, 0}, {1.0, 0}, {1.15, 0}, {0.0, 0} },
{ "brown rat", {20.0, 0}, {2.0, 0}, {1.15, 0}, {0.0, 0} },
{ "fancy rat", {25.0, 0}, {4.0, 0}, {1.14, 0}, {0.0, 0} },
{ "fat rat", {130.0, 0}, {10.0, 0}, {1.13, 0}, {0.0, 0} },
{ "evil rat", {400.0, 0}, {15.0, 0}, {1.13, 0}, {0.0, 0} },
{ "rat farm", {1.2, 1}, {25.0, 0}, {1.12, 0}, {0.0, 0} },
{ "cheese mill", {3.0, 1}, {30.0, 0}, {1.11, 0}, {0.0, 0} },
{ "dairy factory", {9.0, 1}, {50.0, 0}, {1.11, 0}, {0.0, 0} },
{ "cheese research institute", {9.5, 1}, {80.0, 0}, {1.05, 0}, {0.0, 0} },
{ "cheese accelerator", {30.0, 1}, {100.0, 0}, {1.11, 0}, {0.0, 0} },
{ "the cheese singularity", {120.0, 1}, {250.0, 0}, {1.10, 0}, {0.0, 0} },
};
static prizes prize[nhowmanyprizes] = {
{"solid cheese", {100.0, 0}, {1.15, 0}, "hunger", 2},
{"cheese mountain", {5000.0, 0}, {1.15, 0}, "hunger", 8},
{"cheese wheel", {500.0, 0}, {1.15, 0}, "health", 1},
{"medical cheese", {8000.0, 0}, {1.15, 0}, "health", 5},
{"cheese fountain", {2000.0, 0}, {1.15, 0}, "love", 3},
{"love cheese cake", {15000.0, 0}, {1.15, 0}, "love", 7},
{"squeaky cheese", {300.0, 0}, {1.15, 0}, "fun", 2},
{"party cheese", {12000.0, 0}, {1.15, 0}, "fun", 6},
{"cheese soap", {400.0, 0}, {1.15, 0}, "clean", 2},
{"cheese bubbles", {9000.0, 0}, {1.15, 0}, "clean", 5}
};
//should i wrap all this into a macro in rat.h to not have to write all of this every time i make a new game?
running = 1;
mvwprintw(win, row ++, 2, "hi");
clickerload(&cheeses, workers, nhowmanytiers, prize, nhowmanyprizes);
draweverything(win, cheeses, workers, prize, nhowmanytiers, nhowmanyprizes, currentworker, currentprize, activeshop);
time_t lasttime = time(NULL);
static int spaceheld = 0;
static long lastspacetime = 0;
while(running){
if(!running){stop();}
int ch = getch();
switch (ch) {
case 'q': case 'Q': stop(); break;
}
wrefresh(win);
int ch;
while((ch = getch()) != ERR){ //drain the whole queue each frame so rapid clicks/keys aren't ignored
switch (ch) {
case 'q': case 'Q': running = 0; break;
case '\t':
activeshop = (activeshop == SHOP_WORKERS) ? SHOP_PRIZES : SHOP_WORKERS;
break;
case KEY_UP:
if(activeshop == SHOP_WORKERS){
if(currentworker > 0) currentworker--;
} else {
if(currentprize > 0) currentprize--;
}
break;
case KEY_DOWN:
if(activeshop == SHOP_WORKERS){
if(currentworker < nhowmanytiers - 1) currentworker++;
} else {
if(currentprize < nhowmanyprizes - 1) currentprize++;
}
break;
case '\n': case KEY_ENTER:
if(activeshop == SHOP_WORKERS)
buyworker(&cheeses, &workers[currentworker]);
else
buyprize(&cheeses, &prize[currentprize]);
break;
case ' ': {
long now = nowms();
if(!spaceheld){
cheeses = addbignum(cheeses, onecheese);
spaceheld = 1;
}
lastspacetime = now;
break;
}
case KEY_MOUSE: {
MEVENT event;
if(getmouse(&event) == OK && (event.bstate & BUTTON1_PRESSED)){
int y = event.y, x = event.x;
//translate the screen click into winlocal coordinates
if(wmouse_trafo(win, &y, &x, FALSE)){
if (y >= artrow0 && y < artrow0 + artrows &&
x >= artcol0 && x < artcol0 + artcols){
cheeses = addbignum(cheeses, onecheese);
}
}
}
break;
}
}
if(!running) break;
}
if(spaceheld && (nowms() - lastspacetime) > spacedebouncems){
spaceheld = 0;
}
time_t currenttime = time(NULL);
if(currenttime >= lasttime +1){
cheeses = addbignum(cheeses, calculatetotalincome(workers, nhowmanytiers));
cheeses = clampnonneg(cheeses);
lasttime = currenttime;
}
if(running) draweverything(win, cheeses, workers, prize, nhowmanytiers, nhowmanyprizes, currentworker, currentprize, activeshop);
usleep(16667); //60 fps according to google ai overview lmao
}
clickersave(cheeses, workers, nhowmanytiers, prize, nhowmanyprizes);
stop();
}
+7 -52
View File
@@ -1,45 +1,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ncurses.h>
#include "../rat.h"
#define boxw 45
#define boxh 25
#define maxhistory 4
static int wrapprint(WINDOW *win, int row, int col, int maxwidth, const char *msg){
char copy[256];
strncpy(copy, msg, sizeof(copy));
copy[sizeof(copy)-1] = '\0';
char line[256] = "";
char *word = strtok(copy, " ");
while(word){
int linelen = strlen(line);
int wordlen = strlen(word);
int extra = (linelen > 0) ? 1 : 0;
if(linelen + extra + wordlen > maxwidth){
mvwprintw(win, row++, col, "%s", line);
line[0] = '\0';
linelen = 0;
extra = 0;
}
if(linelen > 0) strcat(line, " ");
strcat(line, word);
word = strtok(NULL, " ");
}
if(strlen(line) > 0){
mvwprintw(win, row++, col, "%s", line);
}
return row;
}
static void drawwin(WINDOW *win, int artpick, const char *msg, int history[], int histcount){
werase(win);
@@ -57,9 +19,9 @@ static void drawwin(WINDOW *win, int artpick, const char *msg, int history[], in
}
row++;
wrapprint(win, row, 2, boxw - 4, msg);
wrapprint(win, row, 2, getmaxx(win) - 4, msg);
int inputrow = boxh - 3;
int inputrow = getmaxy(win) - 3;
for(int i = 0; i < histcount; i++){
@@ -75,20 +37,13 @@ void gameguess(){
int solved = 0;
int range = 100;
srand(time(NULL));
int correct = (rand() % (range + 1));
int history[maxhistory];
int histcount = 0;
static int initialized = 0;
if(initialized == 0){ initscr(); }else{ refresh(); }
++initialized;
noecho();
cbreak();
curs_set(0);
WINDOW *win = newwin(boxh, boxw, 1, 1);
WINDOW *win = ratdrawbox();
char msg[96];
snprintf(msg, sizeof(msg), "let's play a game, squeak!~ you gues a number between 0 and %d!", range);
@@ -100,7 +55,7 @@ void gameguess(){
echo();
char buf[16];
mvwgetnstr(win, boxh - 3, 2, buf, sizeof(buf) - 1);
mvwgetnstr(win, getmaxy(win) - 3, 2, buf, sizeof(buf) - 1);
noecho();
if((buf[0] == 'q' || buf[0] == 'Q') && buf[1] == '\0'){
@@ -108,10 +63,10 @@ void gameguess(){
echo();
char confirm[16];
mvwgetnstr(win, boxh - 3, 2, confirm, sizeof(confirm) - 1);
mvwgetnstr(win, getmaxy(win) - 3, 2, confirm, sizeof(confirm) - 1);
noecho();
if((confirm[0] == 'q' || confirm[0] == 'Q' || confirm[0] == 'y' || confirm[0] == 'Y') && confirm[1] == '\0'){
if((confirm[0] == 'q' || confirm[0] == 'Q' || confirm[0] == 'y' || confirm[0] == 'Y')){
quitgame = 1;
break;
} else if((confirm[0] == 'n' || confirm[0] == 'N') && confirm[1] == '\0'){
+85 -59
View File
@@ -1,9 +1,3 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <ncurses.h>
#include <string.h>
#include "../rat.h"
/*
@@ -17,12 +11,12 @@
// you start at the top and end at the bottom if i ever wanna automate taking care of the rat
*/
#define width getmaxx(stdscr)
#define height getmaxy(stdscr)
static int running;
static int won;
static int found;
static int width;
static int height;
static WINDOW *win;
typedef struct{
@@ -37,7 +31,7 @@ static void stop() {
clear();
refresh();
endwin();
if(won){addstat(&rat.fun); printf("the rat feels less hungry...\n\n");}
if(won){addstat(&rat.fun);}
won = 0;
found = 0;
running = 0;
@@ -64,7 +58,15 @@ void lerw() {
char *vis = calloc(total, 1); //visited
int *px = malloc(total * sizeof(int)); //path x
int *py = malloc(total * sizeof(int)); //path y
int *ip = malloc(total * sizeof(int)); // index of path
int *ip = malloc(total * sizeof(int)); // index of path
if(vis == NULL || px == NULL || py == NULL || ip == NULL) {
free(vis);
free(px);
free(py);
free(ip);
return;
}
vis[0] = 1;
grid[1][1] = grid[1][2] = grid[2][1] = grid[2][2] = ' '; //these should be open always
int vc = 1;
@@ -85,26 +87,29 @@ void lerw() {
int pl = 1;
int cx = sx, cy = sy;
while (!vis[cy * cw + cx]) {
while (!vis[cy * cw + cx]) {
int dir = rand() % 4;
int nx = cx + ddx[dir];
int ny = cy + ddy[dir];
if (nx < 0 || nx >= cw || ny < 0 || ny >= ch) continue;
int ni = ny * cw + nx;
if (vis[ni]) {
cx = nx; cy = ny;
continue;
}
if (ip[ni] >= 0) {
int idx = ip[ni];
for (int i = idx + 1; i < pl; i++)
ip[py[i] * cw + px[i]] = -1;
for (int i = idx + 1; i < pl; i++) ip[py[i] * cw + px[i]] = -1;
pl = idx + 1;
cx = nx; cy = ny;
} else {
px[pl] = nx; py[pl] = ny;
cx = nx; cy = ny;
} else {
px[pl] = nx; py[pl] = ny;
ip[ni] = pl++;
cx = nx; cy = ny;
cx = nx; cy = ny;
}
}
//each cell as 2x2
for (int i = 0; i < pl; i++) {
int gx = 3*px[i]+1, gy = 3*py[i]+1;
@@ -197,12 +202,26 @@ static void properrestart(cursor *curs, int *W, int *H) {
for (int y = 0; y < *H; y++) free(grid[y]);
free(grid);
*W = getmaxx(stdscr);
*H = getmaxy(stdscr);
width = getmaxx(win) - 2;
height = getmaxy(win) - 2;
*W = width;
*H = height;
grid = malloc(*H * sizeof(char *));
for (int y = 0; y < *H; y++)
if(grid == NULL) {
running = 0;
return;
}
for (int y = 0; y < *H; y++) {
grid[y] = malloc(*W * sizeof(char));
if(grid[y] == NULL) {
// Free already allocated rows
for(int i = 0; i < y; i++) free(grid[i]);
free(grid);
running = 0;
return;
}
}
lerw();
spawncheeses();
@@ -215,41 +234,46 @@ static void properrestart(cursor *curs, int *W, int *H) {
void gamemaze(){
srand(time(NULL));
static int initialized = 0;
if(initialized == 0){ initscr();}else{refresh();}
++initialized;
int W = getmaxx(stdscr);
int H = getmaxy(stdscr);
win = ratdrawbox();
width = getmaxx(win) - 2;
height = getmaxy(win) - 2;
grid = malloc(H * sizeof(char *)); //those who allocate memory
for (int y = 0; y < H; y++)
grid[y] = malloc(W * sizeof(char));
int W = width;
int H = height;
grid = malloc(H * sizeof(char *)); //those who allocate memory
if(grid == NULL) {
stop();
return;
}
for (int y = 0; y < H; y++) {
grid[y] = malloc(W * sizeof(char));
if(grid[y] == NULL) {
for(int i = 0; i < y; i++) free(grid[i]);
free(grid);
stop();
return;
}
}
lerw();
spawncheeses();
found = 0;
noecho();
cbreak();
nodelay(stdscr, TRUE);
keypad(stdscr, TRUE);
curs_set(0);
cursor curs = {1, 1, {"@"}};
running = 1;
while (running) {
if (!running) stop();
int ch = getch();
switch (ch) {
case 'q': case 'Q': stop(); break;
case 'q': case 'Q': running = 0; break;
case 'r': case 'R': properrestart(&curs, &W, &H); break;
case 'a': case 'A': case KEY_LEFT:
if(!iswall(curs.posy, curs.posx - 1)){
curs.posx -= 1;
if(curs.posx > 0 && !iswall(curs.posy, curs.posx - 1)){
curs.posx -= 1;
}
break;
case 'd': case 'D': case KEY_RIGHT:
@@ -258,7 +282,7 @@ void gamemaze(){
}
break;
case 'w': case 'W': case KEY_UP:
if (!iswall(curs.posy - 1, curs.posx)){
if (curs.posy > 0 && !iswall(curs.posy - 1, curs.posx)){
curs.posy -= 1;
}
break;
@@ -273,20 +297,20 @@ void gamemaze(){
checkexit(&curs);
if (!running) break;
clear();
werase(win);
box(win, 0, 0);
mvprintw(0, width/3+1, "move around the maze and find food!");
mvprintw(1, width/3+1, "you've collected %d/5 cheeses", found);
mvprintw(2, width/3+1, "(only if you find food your rat will be less hungry)");
mvprintw(height/1.5-2, width/3+1, "btw sometimes the maze is impossible just press R");
mvprintw(height/1.5-1, width/3+1, "if that's the case");
mvwprintw(win, 1, width/3+2, "move around the maze and find food!");
mvwprintw(win, 2, width/3+2, "you've collected %d/5 cheeses", found);
mvwprintw(win, 3, width/3+2, "(only if you find food your rat will be less hungry)");
for (int y = 0; y < H; y++)
for (int x = 0; x < W; x++){
if (grid[y][x] == '#') mvaddch(y, x, '#');
else if (grid[y][x] == 'O') {
int dist = abs(y - curs.posy) + abs(x - curs.posx);
if (dist <= 5) mvaddch(y, x, 'O');
for (int y = 0; y < H; y++){
for (int x = 0; x < W; x++){
if (grid[y][x] == '#') mvwaddch(win, y+1, x+1, '#');
else if (grid[y][x] == 'O') {
int dist = abs(y - curs.posy) + abs(x - curs.posx);
if (dist <= 5) mvwaddch(win, y+1, x+1, 'O');
}
}
}
@@ -294,17 +318,19 @@ void gamemaze(){
int hmsg = ((height/2) - 1) / 2;
int msgw = 3 * wmsg + 1;
int msgh = 3 * hmsg + 1;
mvprintw(msgh, msgw-2, "^ leave through here");
mvwprintw(win, msgh+1, msgw-2+1, "^ leave through here");
mvaddstr(curs.posy, curs.posx, curs.face[0]);
mvwaddstr(win, curs.posy+1, curs.posx+1, curs.face[0]);
refresh();
wrefresh(win);
usleep(50000);
}
for (int y = 0; y < H; y++)
free(grid[y]);
for (int y = 0; y < H; y++){
free(grid[y]);
}
free(grid);
//those two for loops were giving me warnings on my lsp so i just fixed them
stop();
}
+18
View File
@@ -0,0 +1,18 @@
#include "../rat.h"
static int running;
static void stop() {
clear();
refresh();
endwin();
running = 0;
}
void ratrace(){
}
+24 -91
View File
@@ -5,25 +5,17 @@
#include <string.h>
#include <sys/stat.h>
#include "rat.h"
#include "defs.h"
#ifdef __APPLE__
#define ratpath "%s/Library/Application Support/rat"
#define ratsave "%s/Library/Application Support/rat/rat.txt"
#else
#define ratpath "%s/.local/share/rat"
#define ratsave "%s/.local/share/rat/rat.txt"
#endif
char *ratart[] = {
" .---.\n (\\./) \\.......-\n >' '< (__.'\"\"\"\"\"\"\n \" ` \" \"_",
" .---.\n-......./ (\\./)\n \"\"\"\"\"\"'.__) >' '<\n _\" \" ` \"",
" .---.\n (\\./) \\.......-\n >= =< (__.'\"\"\"\"\"\"\n \" ` \" \"_",
" .---.\n (\\./) \\.......-\n >0 0< (__.'\"\"\"\"\"\"\n \" ` \" \"_",
" .---.\n (\\./) \\.......-\n >^ ^< (__.'\"\"\"\"\"\"\n \" ` \" \"_",
};
char *ratart[] = {
" .---.\n (\\./) \\.......-\n >' '< (__.'\"\"\"\"\"\"\n \" ` \" \"_",
" .---.\n-......./ (\\./)\n \"\"\"\"\"\"'.__) >' '<\n _\" \" ` \"",
" .---.\n (\\./) \\.......-\n >= =< (__.'\"\"\"\"\"\"\n \" ` \" \"_",
" .---.\n (\\./) \\.......-\n >0 0< (__.'\"\"\"\"\"\"\n \" ` \" \"_",
" .---.\n (\\./) \\.......-\n >^ ^< (__.'\"\"\"\"\"\"\n \" ` \" \"_",
};
char *messages[] = {
char *messages[] = {
"squeak!",
"squeak! !",
"squeak",
@@ -31,73 +23,19 @@
"SQUEAK",
"SQUEAK!!",
"SQUEAAAKKKKK",
};
};
void addstat(float *guy){
char *funfact[] = {
"press q to exit games !",
"rats love cheese!",
"i am sleepy.."
};
if(*guy < 98.5){
*guy += 1.5;
} else{*guy += 0.05;}
}
Rat rat;
void save(void) {
char path[256];
snprintf(path, sizeof(path), ratpath, getenv("HOME"));
mkdir(path, 0755);
snprintf(path, sizeof(path), ratsave, getenv("HOME"));
FILE *f = fopen(path, "w");
if (!f) return;
fprintf(f, "%f\n%f\n%f\n%f\n%f\n%d\n",
rat.hunger, rat.love, rat.fun, rat.clean, rat.health, rat.age);
fclose(f);
}
void load(void) {
char path[256];
snprintf(path, sizeof(path), ratsave, getenv("HOME"));
FILE *f = fopen(path, "r");
if (!f) {
rat.hunger = 80.0f;
rat.love = 80.0f;
rat.fun = 80.0f;
rat.clean = 80.0f;
rat.health = 80.0f;
rat.age = time(NULL);
return;
}
if(fscanf(f, "%f\n%f\n%f\n%f\n%f\n%d\n",
&rat.hunger, &rat.love, &rat.fun, &rat.clean, &rat.health, &rat.age) != 6){
fprintf(stderr, "error: failed to initialize save data.\n");
}
//this should shut the compiler up
fclose(f);
}
float decay(float current, float dayspassed, float rate) {
float result = current - (dayspassed * rate);
return result < 0.0f ? 0.0f : result;
}
void setstat(){
int timenow = time(NULL);
int newage = timenow - rat.age;
float days = newage / 86400.0f; //one day
rat.hunger = decay(rat.hunger, days, 50.0f); //hungry beast
rat.love = decay(rat.love, days, 1.1f); //rats love you they won't hate you easly
rat.fun = decay(rat.fun, days, 25.0f);
rat.clean = decay(rat.clean, days, 5.0f);//rats are surprisingly clean they clean themselves so slow
rat.health = decay(rat.health, days, 0.6f);
rat.age = timenow;
}
//this is better yeah
/*i was cleaning the code up a bit and what the fuck is this
//it's so funny Rat rat
*/
void printrat(WINDOW *win){
werase(win);
@@ -117,6 +55,7 @@ void printrat(WINDOW *win){
row++;
int howmany = sizeof(messages) / sizeof(messages[0]);
int facts = sizeof(funfact) / sizeof(funfact[0]);
mvwprintw(win, row++, 2, "%s", messages[rand() % howmany]);
row++;
@@ -133,6 +72,7 @@ void printrat(WINDOW *win){
mvwprintw(win, row++, 2, "5: clicker the cheese! (all up)");
mvwprintw(win, row++, 2, "9: print me! (refreshes stats)");
mvwprintw(win, row++, 2, "0: exit...");
mvwprintw(win, row++ +1, 1, "fun fact: %s", funfact[rand() % facts]);
wrefresh(win);
}
@@ -144,14 +84,8 @@ int truing = 1;
load();
setstat();
initscr();
cbreak();
noecho();
keypad(stdscr, TRUE);
curs_set(0);
WINDOW *win = newwin(25, 45, 1, 1);
WINDOW *win = ratdrawbox();
printrat(win);
while(truing){
@@ -167,13 +101,13 @@ int truing = 1;
case '2':
endwin();
gamemaze();
//printf("the maze is really dark squeak...\n\n");
/*printf("the maze is really dark squeak...\n\n");*/
refresh();
break;
case '4':
endwin();
gamecatch();
//printf("your rat feels cleaner!\n\n");
/*printf("your rat feels cleaner!\n\n");*/
refresh();
break;
case '5':
@@ -184,7 +118,7 @@ int truing = 1;
case '9': break;
case '0': truing = 0; break;
}
// i will put those printfs where the squeaks go but i have no clue how to do that today
/* i will put those printfs where the squeaks go but i have no clue how to do that today */
if(truing) printrat(win);
}
@@ -195,4 +129,3 @@ int truing = 1;
printf("bye bye~~\n");
return(0);
}
+159
View File
@@ -0,0 +1,159 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <ncurses.h>
#include <string.h>
#include <sys/stat.h>
#include "rat.h"
/*functions used in initilization/main menu (not games)*/
#ifdef __APPLE__
#define ratpath "%s/Library/Application Support/rat"
#define ratsave "%s/Library/Application Support/rat/rat.txt"
#else
#define ratpath "%s/.local/share/rat"
#define ratsave "%s/.local/share/rat/rat.txt"
#endif
void save(void) {
char path[256];
snprintf(path, sizeof(path), ratpath, getenv("HOME"));
mkdir(path, 0755);
snprintf(path, sizeof(path), ratsave, getenv("HOME"));
FILE *f = fopen(path, "w");
if (!f) return;
fprintf(f, "%f\n%f\n%f\n%f\n%f\n%d\n",
rat.hunger, rat.love, rat.fun, rat.clean, rat.health, rat.age);
fclose(f);
}
void load(void) {
char path[256];
snprintf(path, sizeof(path), ratsave, getenv("HOME"));
FILE *f = fopen(path, "r");
if (!f) {
rat.hunger = 80.0f;
rat.love = 80.0f;
rat.fun = 80.0f;
rat.clean = 80.0f;
rat.health = 80.0f;
rat.age = time(NULL);
return;
}
if(fscanf(f, "%f\n%f\n%f\n%f\n%f\n%d\n",
&rat.hunger, &rat.love, &rat.fun, &rat.clean, &rat.health, &rat.age) != 6){
fprintf(stderr, "error: failed to initialize save data.\n");
}
/*this should shut the compiler up*/
fclose(f);
}
void addstat(float *guy){
if(*guy < 98.5){
*guy += 1.5;
} else{*guy += 0.05;}
}
float decay(float current, float dayspassed, float rate) {
float result = current - (dayspassed * rate);
return result < 0.0f ? 0.0f : result;
}
void setstat(){
int timenow = time(NULL);
int newage = timenow - rat.age;
float days = newage / 86400.0f; /*one day*/
rat.hunger = decay(rat.hunger, days, 50.0f); /*hungry beast*/
rat.love = decay(rat.love, days, 1.1f); /*rats love you they won't hate you easly*/
rat.fun = decay(rat.fun, days, 25.0f);
rat.clean = decay(rat.clean, days, 5.0f);/*rats are surprisingly clean they clean themselves so slow*/
rat.health = decay(rat.health, days, 0.6f);
rat.age = timenow;
}
#define minlines 25
#define mincols 80
static void checkminsize(void){
if(LINES >= minlines && COLS >= mincols) return;
clear();
mvprintw(0, 0, "terminal too small! need at least %dx%d, got %dx%d.", mincols, minlines, COLS, LINES);
mvprintw(1, 0, "press any key to exit...");
refresh();
nodelay(stdscr, FALSE);
getch();
save();
endwin();
exit(1);
}
WINDOW *ratdrawbox(void){
static int initialized = 0;
if(!initialized){ initscr(); }else{ refresh(); }
++initialized;
checkminsize();
noecho();
cbreak();
nodelay(stdscr, TRUE);
keypad(stdscr, TRUE);
curs_set(0);
int winh = getmaxy(stdscr) * 0.97;
int winw = getmaxx(stdscr) * 0.97;
int boxy = (getmaxy(stdscr) - winh) / 2;
int boxx = (getmaxx(stdscr) - winw) / 2;
return newwin(winh, winw, boxy, boxx);
}
int wrapprint(WINDOW *win, int row, int col, int maxwidth, const char *msg){
if(msg == NULL) return row;
char copy[256];
strncpy(copy, msg, sizeof(copy) - 1);
copy[sizeof(copy)-1] = '\0';
char line[256] = "";
char *word = strtok(copy, " ");
while(word){
int linelen = strlen(line);
int wordlen = strlen(word);
int extra = (linelen > 0) ? 1 : 0;
if(linelen + extra + wordlen > maxwidth){
mvwprintw(win, row++, col, "%s", line);
line[0] = '\0';
linelen = 0;
extra = 0;
}
if(linelen > 0) {
if(strlen(line) + 1 < sizeof(line)) {
strcat(line, " ");
}
}
if(strlen(line) + strlen(word) < sizeof(line)) {
strcat(line, word);
}
word = strtok(NULL, " ");
}
if(strlen(line) > 0){
mvwprintw(win, row++, col, "%s", line);
}
return row;
}
+23
View File
@@ -1,6 +1,15 @@
#ifndef rat_h
#define rat_h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <unistd.h>
#include <ncurses.h>
#include <sys/stat.h>
typedef struct {
float hunger;
float love;
@@ -11,8 +20,22 @@ typedef struct {
} Rat;
extern char *ratart[];
extern char *funfact[];
extern char *messages[];
extern Rat rat;
void load(void);
void save(void);
void setstat(void);
void addstat(float *guy);
WINDOW *ratdrawbox(void);
int wrapprint(WINDOW *win, int row, int col, int maxwidth, const char *msg);
void gameguess(void);
void gamecatch(void);
void gamemaze(void);
void gameclicker(void);
#endif