1
0
mirror of https://github.com/abakh/nbsdgames.git synced 2024-06-08 17:20:41 +00:00
nbsdgames/fisher.c

432 lines
9.1 KiB
C
Raw Normal View History

2020-06-20 16:26:54 +00:00
/*
O__/|
___|_/ | __
| / | |__
| ISHER*/
2020-05-18 18:59:29 +00:00
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>
#include <signal.h>
#include <string.h>
#include <limits.h>
#include <curses.h>
#include <unistd.h>
#include "config.h"
#define SAVE_TO_NUM 11
#define HOOKS 10
#define LEN 24
#define HLEN LEN/2
#define WID 80
#define HWID WID/2
2020-06-20 16:26:54 +00:00
typedef signed char byte;
#ifdef Plan9
int usleep(long usec) {
2020-06-14 05:20:44 +00:00
int second = usec/1000000;
long nano = usec*1000 - second*1000000;
struct timespec sleepy = {0};
2020-06-14 05:20:44 +00:00
sleepy.tv_sec = second;
sleepy.tv_nsec = nano;
nanosleep(&sleepy, (struct timespec *) NULL);
return 0;
}
#endif
2020-06-20 16:26:54 +00:00
// 12 lines of water
// 80 columns
2020-05-18 18:59:29 +00:00
chtype colors[4]={A_NORMAL,A_STANDOUT};
byte fish[10]={0};//positions
byte caught=-1;
bool stop[10]={0};
unsigned int count[10]={0};
unsigned long score=0;
const char sym[]="~:=!@+><;&";
byte hook=0, hooknum=0;
char error [150]={0};
byte clb,clbtime=0;
FILE* scorefile;
int input;
byte digit_count(int num){
byte ret=0;
do{
2020-06-20 16:26:54 +00:00
++ret;
2020-05-18 18:59:29 +00:00
num/=10;
}while(num);
return ret;
}
void filled_rect(byte sy,byte sx,byte ey,byte ex){
byte y,x;
2020-06-20 16:26:54 +00:00
for(y=sy;y<ey;++y)
for(x=sx;x<ex;++x)
2020-05-18 18:59:29 +00:00
mvaddch(y,x,' ');
}
void green_border(void){
byte y,x;
2020-06-20 16:26:54 +00:00
for(y=0;y<LEN;++y){
2020-05-18 18:59:29 +00:00
mvaddch(y,WID-1,' '|colors[2]);
mvaddch(y,0,' '|colors[2]);
}
2020-06-20 16:26:54 +00:00
for(x=0;x<WID;++x){
2020-05-18 18:59:29 +00:00
mvaddch(LEN-1,x,' '|colors[2]);
mvaddch(0,x,' '|colors[2]);
}
}
void star_line(byte y){
2020-06-20 16:26:54 +00:00
for(byte x=1;x<WID-1;++x)
2020-05-18 18:59:29 +00:00
mvaddch(y,x,'.');
}
void draw(void){
/*while(LEN< 15 || COL<80)
mvprintw(0,0,"Screen size should at least be 80*15 characters");*/
attron(colors[0]);
byte y,x;
filled_rect(0,0,12,80);
mvprintw(0,0," __ Hooks:%d",hooknum);
mvprintw(1,0,"|__ Score:%d",score);
mvprintw(2,0,"| ISHER");
mvprintw(9,32, " O__/");
mvprintw(10,32," ___|_/ ");
mvprintw(11,32,"| / ");
if(clbtime){
if(count[clb]!=1){
2020-06-21 03:35:03 +00:00
mvprintw(9,43,"%d ",count[clb]);
2020-05-18 18:59:29 +00:00
switch(clb){
case 0:
addstr("plastic bags!");
break;
case 1:
addstr("PVC bottles!");
break;
case 2:
addstr("face masks!");
break;
case 3:
addstr("shrimp!");
break;
case 4:
addstr("algae!");
break;
case 5:
addstr("jellyfish!");
break;
case 6:
addstr("molluscs!");
break;
case 7:
addstr("actual fish!");
break;
case 8:
addstr("salmon!");
break;
case 9:
addstr("tuna!");
break;
}
}
else{
2020-06-21 03:35:03 +00:00
move(9,43);
2020-05-18 18:59:29 +00:00
switch(clb){
case 0:
addstr("A plastic bag!");
break;
case 1:
addstr("A PVC bottle!");
break;
case 2:
addstr("A face mask!");
break;
case 3:
addstr("A shrimp!");
break;
case 4:
addstr("Algae!");
break;
case 5:
addstr("A jellyfish!");
break;
case 6:
addstr("A mollusc!");
break;
case 7:
addstr("Actual fish!");
break;
case 8:
addstr("A salmon!");
break;
case 9:
addstr("A tuna!");
break;
}
}
}
2020-06-20 16:26:54 +00:00
for(y=-3;y<0;++y)
2020-05-18 18:59:29 +00:00
mvaddch(HLEN+y,HWID,ACS_VLINE);
attroff(colors[0]);
attron(colors[1]);
filled_rect(HLEN,0,LEN,WID);
2020-06-20 16:26:54 +00:00
for(y=0;y<hook;++y)
2020-05-18 18:59:29 +00:00
mvaddch(HLEN+y,HWID,ACS_VLINE);
if(caught==-1)
mvaddch(HLEN+hook,HWID,')');
else
mvaddch(HLEN+hook,HWID,sym[caught]);
2020-06-20 16:26:54 +00:00
for(y=0;y<10;++y)
2020-05-18 18:59:29 +00:00
mvaddch(HLEN+1+y,fish[y],sym[y]);
attroff(colors[1]);
}
byte scorewrite(void){// only saves the top 10, returns the place in the chart
bool deforno;
if( !getenv("FSH_SCORES") && (scorefile= fopen(FSH_SCORES,"r")) ){
deforno=1;
}
else{
deforno=0;
if( !(scorefile = fopen(getenv("FSH_SCORES"),"r")) ){
sprintf(error,"No accessible score files found. You can make an empty text file in %s or set FSH_SCORES to such a file to solve this.",FSH_SCORES);
return -1;
}
}
char namebuff[SAVE_TO_NUM][60];
long scorebuff[SAVE_TO_NUM];
memset(namebuff,0,SAVE_TO_NUM*60*sizeof(char) );
memset(scorebuff,0,SAVE_TO_NUM*sizeof(long) );
long fuckingscore =0;
char fuckingname[60]={0};
byte location=0;
while( fscanf(scorefile,"%59s : %ld\n",fuckingname,&fuckingscore) == 2 && location<SAVE_TO_NUM ){
strcpy(namebuff[location],fuckingname);
scorebuff[location] = fuckingscore;
2020-06-20 16:26:54 +00:00
++location;
2020-05-18 18:59:29 +00:00
memset(fuckingname,0,60);
fuckingscore=0;
}
if(deforno)
scorefile = fopen(FSH_SCORES,"w+");//get rid of the previous text first
else
scorefile = fopen(getenv("FSH_SCORES"), "w+") ;
if(!scorefile){
strcpy(error, "The file cannot be opened in w+. ");
return -1;
}
byte itreached=location;
byte ret = -1;
bool wroteit=0;
2020-06-20 16:26:54 +00:00
for(location=0;location<=itreached && location<SAVE_TO_NUM-wroteit;++location){
2020-05-18 18:59:29 +00:00
if(!wroteit && (location>=itreached || score>=scorebuff[location]) ){
fprintf(scorefile,"%s : %ld\n",getenv("USER"),score);
ret=location;
wroteit=1;
}
if(location<SAVE_TO_NUM-wroteit && location<itreached)
fprintf(scorefile,"%s : %ld\n",namebuff[location],scorebuff[location]);
}
fflush(scorefile);
return ret;
}
void showscores(byte playerrank){
byte y,x;
attron(colors[3]);
filled_rect(0,0,LEN,WID);
green_border();
if(*error){
mvaddstr(1,0,error);
mvprintw(2,0,"However, your score is %ld.",score);
refresh();
return;
}
if(playerrank == 0){
char formername[60]={0};
long formerscore=0;
rewind(scorefile);
fscanf(scorefile,"%*s : %*d");
if ( fscanf(scorefile,"%s : %ld",formername,&formerscore)==2 && formerscore>0){
byte a = (LEN-9)/2;
star_line(1);
star_line(LEN-2);
mvaddstr(1,WID/2-8,"CONGRATULATIONS!!");
mvprintw(a+1,HWID-10," _____ You bet the");
mvprintw(a+2,HWID-10," .' | previous");
mvprintw(a+3,HWID-10," .' | record");
2020-06-21 07:02:36 +00:00
mvprintw(a+4,HWID-10," | .| | of");
2020-05-18 18:59:29 +00:00
mvprintw(a+5,HWID-10," |.' | |%11ld",formerscore);
mvprintw(a+6,HWID-10," | | held by");
mvprintw(a+7,HWID-10," ___| |___%7s!",formername);
2020-06-21 07:02:36 +00:00
mvprintw(a+8,HWID-10," | |");
2020-05-18 18:59:29 +00:00
mvprintw(a+9,HWID-10," |____________|");
mvprintw(LEN-3,HWID-11,"Press a key to continue");
refresh();
do{
input=getch();
}while(input==KEY_UP || input==KEY_DOWN);
filled_rect(0,0,LEN,WID);
green_border();
}
}
//scorefile is still open with w+
char pname[60] = {0};
long pscore=0;
byte rank=0;
rewind(scorefile);
mvaddstr(1,WID/2-4,"HIGH SCORES");
attron(colors[3]);
while( rank<SAVE_TO_NUM && fscanf(scorefile,"%s : %ld\n",pname,&pscore) == 2){
star_line(2+2*rank);
move(2+2*rank,1);
if(rank == playerrank)
printw(">>>");
printw("%s",pname);
mvprintw(2+2*rank,WID-1-digit_count(pscore),"%d",pscore);
2020-06-20 16:26:54 +00:00
++rank;
2020-05-18 18:59:29 +00:00
}
attroff(colors[3]);
refresh();
}
void help(void){
nocbreak();
cbreak();
attron(colors[3]);
filled_rect(0,0,LEN,WID);
green_border();
mvprintw(1,HWID-4,"GAME PLAY");
mvprintw(3,1,"Catch a fish and reel it in for points");
mvprintw(4,1,"The deeper the fish, the more points it is worth.");
mvprintw(5,1,"If a fish hits your line, you lose a hook.");
mvprintw(6,1,"When you run out of hooks, the game is over!");
mvprintw(8,HWID-4,"CONTROLS");
mvprintw(10,1,"UP & DOWN: Control the hook");
mvprintw(11,1,"q: Quit");
mvprintw(13,1,"This is a port of \"Deep Sea Fisher\", a MikeOS game.");
attroff(colors[3]);
refresh();
getch();
halfdelay(1);
}
void sigint_handler(int x){
endwin();
puts("Quit.");
exit(x);
}
2020-06-20 16:26:54 +00:00
int main(void){
2020-05-18 18:59:29 +00:00
signal(SIGINT,sigint_handler);
initscr();
noecho();
cbreak();
keypad(stdscr,1);
srand(time(NULL)%UINT_MAX);
2020-06-20 16:26:54 +00:00
for(byte n=0;n<10;++n)
2020-05-18 18:59:29 +00:00
fish[n]=rand()%80;
if(has_colors()){
start_color();
init_pair(1,COLOR_BLACK,COLOR_CYAN);
init_pair(2,COLOR_BLACK,COLOR_BLUE);
init_pair(3,COLOR_WHITE,COLOR_GREEN);
init_pair(4,COLOR_BLACK,COLOR_WHITE);
2020-06-20 16:26:54 +00:00
for(byte b=0;b<4;++b)
2020-05-18 18:59:29 +00:00
colors[b]=COLOR_PAIR(b+1);
}
byte n;
Start:
halfdelay(1);
curs_set(0);
2020-07-09 07:17:33 +00:00
clbtime=0;
2020-05-18 18:59:29 +00:00
hook=0;
hooknum=HOOKS;
score=0;
2020-05-22 01:04:52 +00:00
memset(count,0,10*sizeof(unsigned int) );
2020-05-18 18:59:29 +00:00
while(1){
draw();
refresh();
input=getch();
2020-06-20 16:26:54 +00:00
for(n=0;n<10;++n){
2020-05-18 18:59:29 +00:00
if(stop[n]){
if(rand()%(n+15)==0)//this is to make the fish move
stop[n]=0;
continue;
}
if(n%2)
fish[n]--;
else
fish[n]++;
if(fish[n]<0)
fish[n]=79;
if(fish[n]>79)
fish[n]=0;//appear on the other end
if(fish[n]==40){
if(hook>n+1){
caught= -1;
hook=0;
2020-06-20 16:26:54 +00:00
--hooknum;
2020-05-18 18:59:29 +00:00
}
if(hook==n+1 && caught==-1){
caught=n;
if(n%2)
fish[n]=79;
else
fish[n]=0;
}
}
if(rand()%(14-n)==0)//this is to make it stop
stop[n]=1;
}
2020-06-20 16:26:54 +00:00
if(input==KEY_UP){
2020-05-18 18:59:29 +00:00
if(hook>0)
2020-06-20 16:26:54 +00:00
--hook;
2020-05-18 18:59:29 +00:00
if(hook==0 && caught!=-1){
count[caught]++;
score+=(caught+1)*(caught+1);
clb=caught;
clbtime=10;//celebrate catching the fish
caught=-1;
}
2020-06-20 16:26:54 +00:00
}
2020-05-18 18:59:29 +00:00
if(input==KEY_DOWN){
if(hook<11)
2020-06-20 16:26:54 +00:00
++hook;
2020-05-18 18:59:29 +00:00
if(fish[hook-1]==40 && caught==-1){
caught=hook-1;
if(n%2)
fish[hook-1]=0;
else
fish[hook-1]=79;
}
}
if(input=='?' || input==KEY_F(1))
help();
if(input=='q')
break;
if(!hooknum)
break;
if(input!=ERR){
usleep(100000);
2020-05-18 18:59:29 +00:00
flushinp();
}
}
End:
flushinp();
nocbreak();
cbreak();
curs_set(1);
showscores(scorewrite());
attron(colors[2]);
mvprintw(LEN-1,HWID-11,"Wanna play again? (y/n)");
attroff(colors[2]);
do{
input=getch();
}while(input==KEY_UP || input==KEY_DOWN);
if(input!='q' && input!='n' && input!='N')
goto Start;
endwin();
2020-06-20 16:26:54 +00:00
return 0;
2020-05-18 18:59:29 +00:00
}