1 /*
2 Jewels
3
4
5 Authored by abakh <abakh@tuta.io>
6 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.
7
8 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/>.
9
10
11 A pair of jewels appear on top of the window, And you can move and rotate them while they are falling down.
12 If you make a vertical or horizontal row of 4 jewels they will explode and add up to your score.
13 Like Tetris,You will lose the game when the center of the uppermost row is filled.
14
15 TODO make it like puyo puyo instead of the remake of what i poorly remembered*/
16 #include <curses.h>
17 #include <time.h>
18 #include <limits.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #include "config.h"
22 #include "common.h"
23 #define LEN 17
24 #define WID 19
25 #define DELAY 2
26 #define SAVE_TO_NUM 10
27
28 chtype board[LEN][WID];
29 chtype colors[6]={0};
30 chtype next1,next2;
31 byte jx,jy; //first jewel's position
32 byte kx,ky;//second jewel's position in relation to that of j
33 long score=0;
34 char* controls = "j,l-Move k-Rotate p-Pause q-Quit";
35
save_score(void)36 byte save_score(void){
37 return fallback_to_home("jewels_scores",score,SAVE_TO_NUM);
38
39 }
show_scores(byte playerrank)40 void show_scores(byte playerrank){
41 if(playerrank==FOPEN_FAIL){
42 printf("Could not open scorefile.");
43 abort();
44 }
45 if(playerrank == 0){
46 char formername[60]={0};
47 long formerscore=0;
48 rewind(score_file);
49 fscanf(score_file,"%*s : %*d\n");
50 if ( fscanf(score_file,"%s : %ld\n",formername,&formerscore)==2){
51 printf("\n*****CONGRATULATIONS!****\n");
52 printf(" _____ You bet the\n");
53 printf(" .' | previous\n");
54 printf(" .' | record\n");
55 printf(" | .| | of\n");
56 printf(" |.' | |%14ld\n",formerscore);
57 printf(" | | held by\n");
58 printf(" ___| |___%11s\n",formername);
59 printf(" | |\n");
60 printf(" |____________|\n");
61 printf("*************************\n");
62 }
63
64 }
65 //scorefile is still open with w+
66 char pname[60] = {0};
67 long pscore=0;
68 byte rank=0;
69 rewind(score_file);
70 printf("\n>*>*>Top %d<*<*<\n",SAVE_TO_NUM);
71 while( rank<SAVE_TO_NUM && fscanf(score_file,"%s : %ld\n",pname,&pscore) == 2){
72 if(rank == playerrank)
73 printf(">>>");
74 printf("%d) %s : %ld\n",rank+1,pname,pscore);
75 ++rank;
76 }
77 putchar('\n');
78 fclose(score_file);
79 }
80 //apply gravity
fall(void)81 bool fall(void){
82 bool jfall,kfall,ret;
83 jfall=kfall=ret=0;
84 for(int y=LEN-1;y>0;--y){
85 chtype c,d;
86 for(int x=WID-1;x>=0;--x){
87 c=board[y][x];
88 d=board[y-1][x];
89 if(!c && d){
90 board[y-1][x]=0;
91 board[y][x]=d;
92 if(y-1==jy && x==jx)
93 jfall=1;
94 if((y-1==jy+ky) && (x==jx+kx))
95 kfall=1;
96 ret=1;
97 }
98 }
99 }
100 if(jfall&&kfall)
101 ++jy;
102 else
103 jy = LEN+1;
104 return ret;
105 }
106 // rotate 90d clockwise in ky/x format
clockwise(byte * y,byte * x)107 void clockwise(byte* y,byte* x){
108 /*
109 o x
110 x xo o ox*/
111 chtype fx,fy;
112 if(*y){
113 fy=0;
114 fx=-*y;
115 }
116 if(*x){
117 fx=0;
118 fy=*x;
119 }
120 *y=fy;
121 *x=fx;
122 }
123
124 //rtt jwls
rotate(void)125 bool rotate(void){//f:future
126 if(jy>LEN)
127 return 0;
128 byte fy,fx;
129 fy=ky;fx=kx;
130 clockwise(&fy,&fx);
131 if( jy+fy<0 || jy+fy>=LEN || jx+fx<0 || jx+fx>=WID )
132 return 0;
133 if(board[jy+fy][jx+fx])
134 return 0;
135 chtype a = board[jy+ky][jx+kx];
136 board[jy+ky][jx+kx]=0;
137 ky=fy;
138 kx=fx;
139 board[jy+ky][jx+kx]=a;
140 return 1;
141 }
142 //mv jwls
jmove(byte dy,byte dx)143 bool jmove(byte dy,byte dx){
144 if(jy>LEN)
145 return 0;
146
147 if(jx+dx>=WID || jx+dx<0 || jx+kx+dx>=WID ||jx+kx+dx<0 || jy+dx<0 ||jx+dx+kx<0)
148 return 0;
149 if( board[jy+ky+dy][jx+kx+dx] )
150 if( !(jy+ky+dy == jy && jx+kx+dx==jx) )
151 return 0;
152
153 if( board[jy+dy][jx+dx])
154 if(!(dx==kx && dy==ky))
155 return 0;
156 //still alive?
157 chtype a = board[jy][jx];
158 chtype b = board[jy+ky][jx+kx];
159 board[jy][jx]=0;
160 board[jy+ky][jx+kx]=0;
161 board[jy+dy][jx+dx]=a;
162 board[jy+ky+dy][jx+kx+dx]=b;
163 jy+=dy;jx+=dx;
164 return 1;
165 }
166 //scoring algorithm
explode(byte combo)167 bool explode(byte combo){
168 bool ret =0;
169 chtype c,uc;
170 byte n;
171 byte y,x;
172 for(y=0;y<LEN;++y){
173 c=uc=n=0;
174 for(x=0;x<WID;++x){
175 uc = c;
176 c = board[y][x];
177 if(c && c == uc){
178 ++n;
179 if(n>=3 && x==WID-1){//the chain ends because the row ends
180 ++x;
181 goto HrExplsn;
182 }
183 }
184 else if(n>=3){
185 HrExplsn:
186 score+=n*10*(n-2)*combo;
187 ret=1;
188 for(;n>=0;--n)
189 board[y][x-1-n]=0;
190 n=0;
191 }
192 else
193 n=0;
194 }
195 }
196 for(x=0;x<WID;++x){
197 c=uc=n=0;
198 for(byte y=0;y<LEN;++y){
199 uc=c;
200 c = board[y][x];
201 if(c && c == uc){
202 ++n;
203 if(n>=3 && y==LEN-1){
204 ++y;
205 goto VrExplsn;
206 }
207 }
208 else if(n>=3){
209 VrExplsn:
210 score+=n*10*(n-2)*combo;
211 ret=1;
212 for(;n>=0;--n)
213 board[y-1-n][x]=0;
214 n=0;
215 }
216 else
217 n=0;
218 }
219 }
220 return ret;
221 }
222
223 //display
draw(void)224 void draw(void){
225 erase();
226 int middle = (COLS/2-1)-(WID/2);
227 chtype a=A_STANDOUT|' ';
228 mvhline(LEN,middle-2,a,WID+4);
229 mvvline(0,middle-1,a,LEN);
230 mvvline(0,middle-2,a,LEN);
231 mvvline(0,middle+WID,a,LEN);
232 mvvline(0,middle+WID+1,a,LEN);
233 mvprintw(0,0,"Score:%d",score);
234 mvaddstr(1,0,"Next:");
235 addch(next1);
236 addch(next2);
237 for(byte y=0;y<LEN;++y){
238 for(byte x=0;x<WID;++x){
239 chtype c = board[y][x];
240 if(c)
241 mvaddch(y,middle+x,c);
242 }
243 }
244 mvaddstr(LINES-2,middle-5,controls);
245 refresh();
246 }
main(void)247 int main(void){
248 initscr();
249 cbreak();
250 halfdelay(DELAY);
251 noecho();
252 curs_set(0);
253 wnoutrefresh(stdscr);
254 keypad(stdscr,1);
255 int input;
256 bool falls;
257 byte stop=0 , combo;
258 char jwstr[] = {'*','^','~','"','$','V'};
259 if(has_colors()){
260 start_color();
261 use_default_colors();
262 init_pair(1,COLOR_RED,-1);
263 init_pair(2,COLOR_GREEN,-1);
264 init_pair(3,COLOR_MAGENTA,-1);
265 init_pair(4,COLOR_BLUE,-1);//array this thing
266 init_pair(5,COLOR_YELLOW,-1);
267 init_pair(6,COLOR_CYAN,-1);
268 for(byte n=0;n<6;++n){
269 colors[n] = COLOR_PAIR(n+1);
270 }
271 }
272
273 srand(time(NULL)%UINT_MAX);
274 byte ran1= rand()%6;
275 byte ran2= rand()%6;
276 next1= colors[ran1]|jwstr[ran1];
277 next2= colors[ran2]|jwstr[ran2];
278 while(1){
279 chtype a,b;
280 a=board[0][WID/2];
281 b=board[0][WID/2-1];
282 if(a || b ){
283 goto Lose;
284 }
285 jy=ky=0;
286 jx=WID/2;
287 kx=-1;
288 board[jy][jx]=next2;
289 board[jy+ky][jx+kx]=next1;
290 ran1= rand()%6;
291 ran2= rand()%6;
292 next1=colors[ran1]|jwstr[ran1];
293 next2=colors[ran2]|jwstr[ran2];
294 falls = 1;
295 while(falls){
296 input = getch();
297
298 if(input != ERR)
299 stop+=1;
300
301 if( stop >= 10){
302 falls=fall();
303 stop=0;
304 }
305 else if(input=='l' || input==KEY_RIGHT)
306 jmove(0,+1);
307 else if(input=='j' || input==KEY_LEFT )
308 jmove(0,-1);
309 else if(input=='k' || input==KEY_UP)
310 rotate();
311 else if(input=='p'){
312 mvaddstr(LINES-2,COLS/2-15,"Paused - Press a key to continue ");
313 refresh();
314 nocbreak();
315 cbreak();
316 getch();
317 halfdelay(DELAY);
318 }
319 else if(input=='q')
320 goto Lose;
321 else if(input==' ')
322 while( (falls=fall()) )
323 stop=0;
324 else{
325 falls=fall();
326 stop=0;
327 }
328 draw();
329 }
330 combo=1;
331 while(explode(combo)){ // explode, fall, explode, fall until nothing is left
332 ++combo;
333 while(fall());
334 draw();
335 }
336 }
337 Lose:
338 nocbreak();
339 endwin();
340 printf("%s _Jewels_ %s\n",jwstr,jwstr);
341 printf("You have scored %ld points.\n",score);
342 show_scores(save_score());
343 return EXIT_SUCCESS;
344 }
345