1 /*
2 O__/|
3 ___|_/ | __
4 | / | |__
5 | ISHER
6
7 Authored by abakh <abakh@tuta.io>
8 To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to the public domain worldwide. This software is distributed without any warranty.
9
10 You should have received a copy of the CC0 Public Domain Dedication along with this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
11
12 */
13 #include <stdio.h>
14 #include <stdbool.h>
15 #include <stdlib.h>
16 #include <time.h>
17 #include <signal.h>
18 #include <string.h>
19 #include <limits.h>
20 #include <curses.h>
21 #include <unistd.h>
22 #include "config.h"
23 #include "common.h"
24 #define SAVE_TO_NUM 11
25 #define HOOKS 10
26 #define LEN 24
27 #define HLEN LEN/2
28 #define WID 80
29 #define HWID WID/2
30 #ifdef Plan9
usleep(long usec)31 int usleep(long usec) {
32 int second = usec/1000000;
33 long nano = usec*1000 - second*1000000;
34 struct timespec sleepy = {0};
35 sleepy.tv_sec = second;
36 sleepy.tv_nsec = nano;
37 nanosleep(&sleepy, (struct timespec *) NULL);
38 return 0;
39 }
40 #endif
41 // 12 lines of water
42 // 80 columns
43
44 chtype colors[4]={A_NORMAL,A_STANDOUT};
45 byte fish[10]={0};//positions
46 byte caught=-1;
47 bool stop[10]={0};
48 unsigned int count[10]={0};
49 unsigned long score=0;
50 const char sym[]="~:=!@+><;&";
51 byte hook=0, hooknum=0;
52 byte clb,clbtime=0;
53
54 int input;
digit_count(int num)55 byte digit_count(int num){
56 byte ret=0;
57 do{
58 ++ret;
59 num/=10;
60 }while(num);
61 return ret;
62 }
filled_rect(byte sy,byte sx,byte ey,byte ex)63 void filled_rect(byte sy,byte sx,byte ey,byte ex){
64 byte y,x;
65 for(y=sy;y<ey;++y)
66 for(x=sx;x<ex;++x)
67 mvaddch(y,x,' ');
68 }
green_border(void)69 void green_border(void){
70 byte y,x;
71 for(y=0;y<LEN;++y){
72 mvaddch(y,WID-1,' '|colors[2]);
73 mvaddch(y,0,' '|colors[2]);
74 }
75 for(x=0;x<WID;++x){
76 mvaddch(LEN-1,x,' '|colors[2]);
77 mvaddch(0,x,' '|colors[2]);
78 }
79
80 }
star_line(byte y)81 void star_line(byte y){
82 for(byte x=1;x<WID-1;++x)
83 mvaddch(y,x,'.');
84 }
draw(void)85 void draw(void){
86 /*while(LEN< 15 || COL<80)
87 mvprintw(0,0,"Screen size should at least be 80*15 characters");*/
88 attron(colors[0]);
89 filled_rect(0,0,12,80);
90 byte y;
91 mvprintw(0,0," __ Hooks:%d",hooknum);
92 mvprintw(1,0,"|__ Score:%d",score);
93 mvprintw(2,0,"| ISHER");
94 mvprintw(9,32, " O__/");
95 mvprintw(10,32," ___|_/ ");
96 mvprintw(11,32,"| / ");
97
98 if(clbtime){
99 if(count[clb]!=1){
100 mvprintw(9,43,"%d ",count[clb]);
101 switch(clb){
102 case 0:
103 addstr("plastic bags!");
104 break;
105 case 1:
106 addstr("PVC bottles!");
107 break;
108 case 2:
109 addstr("face masks!");
110 break;
111 case 3:
112 addstr("shrimp!");
113 break;
114 case 4:
115 addstr("algae!");
116 break;
117 case 5:
118 addstr("jellyfish!");
119 break;
120 case 6:
121 addstr("molluscs!");
122 break;
123 case 7:
124 addstr("actual fish!");
125 break;
126 case 8:
127 addstr("salmon!");
128 break;
129 case 9:
130 addstr("tuna!");
131 break;
132 }
133 }
134 else{
135 move(9,43);
136 switch(clb){
137 case 0:
138 addstr("A plastic bag!");
139 break;
140 case 1:
141 addstr("A PVC bottle!");
142 break;
143 case 2:
144 addstr("A face mask!");
145 break;
146 case 3:
147 addstr("A shrimp!");
148 break;
149 case 4:
150 addstr("Algae!");
151 break;
152 case 5:
153 addstr("A jellyfish!");
154 break;
155 case 6:
156 addstr("A mollusc!");
157 break;
158 case 7:
159 addstr("Actual fish!");
160 break;
161 case 8:
162 addstr("A salmon!");
163 break;
164 case 9:
165 addstr("A tuna!");
166 break;
167 }
168 }
169 }
170 for(y=-3;y<0;++y)
171 mvaddch(HLEN+y,HWID,ACS_VLINE);
172 attroff(colors[0]);
173 attron(colors[1]);
174 filled_rect(HLEN,0,LEN,WID);
175 for(y=0;y<hook;++y)
176 mvaddch(HLEN+y,HWID,ACS_VLINE);
177 if(caught==-1)
178 mvaddch(HLEN+hook,HWID,')');
179 else
180 mvaddch(HLEN+hook,HWID,sym[caught]);
181 for(y=0;y<10;++y)
182 mvaddch(HLEN+1+y,fish[y],sym[y]);
183 attroff(colors[1]);
184
185 }
save_score(void)186 byte save_score(void){
187 return fallback_to_home("fisher_scores",score,SAVE_TO_NUM);
188
189 }
190
191
show_scores(byte playerrank)192 void show_scores(byte playerrank){
193 attron(colors[3]);
194 filled_rect(0,0,LEN,WID);
195 green_border();
196 if(playerrank==FOPEN_FAIL){
197 mvaddstr(1,0,"Could not open score file");
198 mvprintw(2,0,"However, your score is %ld.",score);
199 refresh();
200 return;
201 }
202 if(playerrank == 0){
203 char formername[60]={0};
204 long formerscore=0;
205 rewind(score_file);
206 fscanf(score_file,"%*s : %*d");
207 if ( fscanf(score_file,"%s : %ld",formername,&formerscore)==2 && formerscore>0){
208 byte a = (LEN-9)/2;
209 star_line(1);
210 star_line(LEN-2);
211 mvaddstr(1,WID/2-8,"CONGRATULATIONS!!");
212 mvprintw(a+1,HWID-10," _____ You bet the");
213 mvprintw(a+2,HWID-10," .' | previous");
214 mvprintw(a+3,HWID-10," .' | record");
215 mvprintw(a+4,HWID-10," | .| | of");
216 mvprintw(a+5,HWID-10," |.' | |%11ld",formerscore);
217 mvprintw(a+6,HWID-10," | | held by");
218 mvprintw(a+7,HWID-10," ___| |___%7s!",formername);
219 mvprintw(a+8,HWID-10," | |");
220 mvprintw(a+9,HWID-10," |____________|");
221 mvprintw(LEN-3,HWID-11,"Press a key to continue");
222 refresh();
223 do{
224 input=getch();
225 }while(input==KEY_UP || input==KEY_DOWN);
226 filled_rect(0,0,LEN,WID);
227 green_border();
228 }
229
230 }
231 //scorefile is still open with w+
232 char pname[60] = {0};
233 long pscore=0;
234 byte rank=0;
235 rewind(score_file);
236 mvaddstr(1,WID/2-4,"HIGH SCORES");
237 attron(colors[3]);
238 while( rank<SAVE_TO_NUM && fscanf(score_file,"%s : %ld\n",pname,&pscore) == 2){
239 star_line(2+2*rank);
240 move(2+2*rank,1);
241 if(rank == playerrank)
242 printw(">>>");
243 printw("%s",pname);
244 mvprintw(2+2*rank,WID-1-digit_count(pscore),"%d",pscore);
245 ++rank;
246 }
247 attroff(colors[3]);
248 refresh();
249 }
help(void)250 void help(void){
251 nocbreak();
252 cbreak();
253 attron(colors[3]);
254 filled_rect(0,0,LEN,WID);
255 green_border();
256 mvprintw(1,HWID-4,"GAME PLAY");
257 mvprintw(3,1,"Catch a fish and reel it in for points");
258 mvprintw(4,1,"The deeper the fish, the more points it is worth.");
259 mvprintw(5,1,"If a fish hits your line, you lose a hook.");
260 mvprintw(6,1,"When you run out of hooks, the game is over!");
261 mvprintw(8,HWID-4,"CONTROLS");
262 mvprintw(10,1,"UP & DOWN: Control the hook");
263 mvprintw(11,1,"q: Quit");
264 mvprintw(13,1,"This is a port of \"Deep Sea Fisher\", a MikeOS game.");
265 attroff(colors[3]);
266 refresh();
267 getch();
268 halfdelay(1);
269 }
sigint_handler(int x)270 void sigint_handler(int x){
271 endwin();
272 puts("Quit.");
273 exit(x);
274 }
main(void)275 int main(void){
276 signal(SIGINT,sigint_handler);
277 initscr();
278 noecho();
279 cbreak();
280 keypad(stdscr,1);
281 srand(time(NULL)%UINT_MAX);
282 for(byte n=0;n<10;++n)
283 fish[n]=rand()%80;
284 if(has_colors()){
285 start_color();
286 init_pair(1,COLOR_BLACK,COLOR_CYAN);
287 init_pair(2,COLOR_BLACK,COLOR_BLUE);
288 init_pair(3,COLOR_WHITE,COLOR_GREEN);
289 init_pair(4,COLOR_BLACK,COLOR_WHITE);
290 for(byte b=0;b<4;++b)
291 colors[b]=COLOR_PAIR(b+1);
292 }
293 byte n;
294 Start:
295 halfdelay(1);
296 curs_set(0);
297 clbtime=0;
298 hook=0;
299 hooknum=HOOKS;
300 score=0;
301 memset(count,0,10*sizeof(unsigned int) );
302 while(1){
303 draw();
304 refresh();
305 input=getch();
306 for(n=0;n<10;++n){
307 if(stop[n]){
308 if(rand()%(n+15)==0)//this is to make the fish move
309 stop[n]=0;
310 continue;
311 }
312 if(n%2)
313 fish[n]--;
314 else
315 fish[n]++;
316 if(fish[n]<0)
317 fish[n]=79;
318 if(fish[n]>79)
319 fish[n]=0;//appear on the other end
320 if(fish[n]==40){
321 if(hook>n+1){
322 caught= -1;
323 hook=0;
324 --hooknum;
325 }
326 if(hook==n+1 && caught==-1){
327 caught=n;
328 if(n%2)
329 fish[n]=79;
330 else
331 fish[n]=0;
332 }
333 }
334 if(rand()%(14-n)==0)//this is to make it stop
335 stop[n]=1;
336 }
337 if(input==KEY_UP){
338 if(hook>0)
339 --hook;
340 if(hook==0 && caught!=-1){
341 count[caught]++;
342 score+=(caught+1)*(caught+1);
343 clb=caught;
344 clbtime=10;//celebrate catching the fish
345 caught=-1;
346 }
347 }
348 if(input==KEY_DOWN){
349 if(hook<11)
350 ++hook;
351 if(fish[hook-1]==40 && caught==-1){
352 caught=hook-1;
353 if(n%2)
354 fish[hook-1]=0;
355 else
356 fish[hook-1]=79;
357 }
358 }
359 if(input=='?' || input==KEY_F(1))
360 help();
361 if(input=='q')
362 break;
363 if(!hooknum)
364 break;
365 if(input!=ERR){
366 usleep(100000);
367 flushinp();
368 }
369 }
370 flushinp();
371 nocbreak();
372 cbreak();
373 curs_set(1);
374 show_scores(save_score());
375 attron(colors[2]);
376 mvprintw(LEN-1,HWID-11,"Wanna play again? (y/n)");
377 attroff(colors[2]);
378 do{
379 input=getch();
380 }while(input==KEY_UP || input==KEY_DOWN);
381 if(input!='q' && input!='n' && input!='N')
382 goto Start;
383 endwin();
384 return 0;
385 }
386