#include <curses.h> #include <time.h> #include <limits.h> #include <string.h> #include <stdlib.h> #include "config.h" #define LEN 17 #define WID 19 #define DELAY 2 #define SAVE_TO_NUM 10 /* Jewels Authored by Hossein Bakhtiarifar <abakh@tuta.io> No rights are reserved and this software comes with no warranties of any kind to the extent permitted by law. compile with -lnucrses A pair of jewels appear on top of the window, And you can move and rotate them while they are falling down. If you make a vertical or horizontal row of 4 jewels they will explode and add up to your score. Like Tetris,You will lose the game when the center of the uppermost row is filled. */ typedef signed char byte; chtype board[LEN][WID]; chtype colors[6]={0}; chtype next1,next2; byte jx,jy; //first jewel's position byte kx,ky;//second jewel's position in relation to that of j long score=0; char* controls = "j,l-Move k-Rotate p-Pause q-Quit"; FILE* scorefile; byte scorewrite(long score){// only saves the top 10 bool deforno; if( !getenv("JW_SCORES") && (scorefile= fopen(JW_SCORES,"r")) ){ deforno=1; } else{ deforno=0; if( !(scorefile = fopen(getenv("JW_SCORES"),"r")) ){ fprintf(stderr,"\nNo accessible score files found. You can make an empty text file in %s or set JW_SCORES to such a file to solve this. \n",JW_SCORES); exit(EXIT_SUCCESS); } } 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; location++; memset(fuckingname,0,60); fuckingscore=0; } if(deforno) scorefile = fopen(JW_SCORES,"w+");//get rid of the text else scorefile = fopen(getenv("JW_SCORES"), "w+") ; if(!scorefile){ printf("\nThe file cannot be opened in w+.\n"); exit(EXIT_SUCCESS); } byte itreached=location; byte ret = -1; bool wroteit=0; for(location=0;location<=itreached && location<SAVE_TO_NUM-wroteit;location++){ 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){ if(playerrank == 0){ char formername[60]={0}; long formerscore=0; rewind(scorefile); fscanf(scorefile,"%*s : %*d\n"); if ( fscanf(scorefile,"%s : %ld\n",formername,&formerscore)==2){ printf("\n*****CONGRATULATIONS!****\n"); printf(" _____ You bet the\n"); printf(" .' | previous\n"); printf(" .' | record\n"); printf(" | .| | of\n"); printf(" |.' | |%14ld\n",formerscore); printf(" | | held by\n"); printf(" ___| |___%11s\n",formername); printf(" | |\n"); printf(" |____________|\n"); printf("*************************\n"); } } //scorefile is still open with w+ char pname[60] = {0}; long pscore=0; byte rank=0; rewind(scorefile); printf("\n>*>*>Top %d<*<*<\n",SAVE_TO_NUM); while( rank<SAVE_TO_NUM && fscanf(scorefile,"%s : %ld\n",pname,&pscore) == 2){ if(rank == playerrank) printf(">>>"); printf("%d) %s : %ld\n",rank+1,pname,pscore); rank++; } putchar('\n'); } //apply gravity bool fall(void){ bool jfall,kfall,ret; jfall=kfall=ret=0; for(int y=LEN-1;y>0;y--){ chtype c,d; for(int x=WID-1;x>=0;x--){ c=board[y][x]; d=board[y-1][x]; if(!c && d){ board[y-1][x]=0; board[y][x]=d; if(y-1==jy && x==jx) jfall=1; if((y-1==jy+ky) && (x==jx+kx)) kfall=1; ret=1; } } } if(jfall&&kfall) jy++; else jy = LEN+1; return ret; } // rotate 90d clockwise in ky/x format void clockwise(byte* y,byte* x){ /* o x x xo o ox*/ chtype fx,fy; if(*y){ fy=0; fx=-*y; } if(*x){ fx=0; fy=*x; } *y=fy; *x=fx; } //rtt jwls bool rotate(void){//f:future if(jy>LEN) return 0; byte fy,fx; fy=ky;fx=kx; clockwise(&fy,&fx); if( jy+fy<0 || jy+fy>=LEN || jx+fx<0 || jx+fx>=WID ) return 0; if(board[jy+fy][jx+fx]) return 0; chtype a = board[jy+ky][jx+kx]; board[jy+ky][jx+kx]=0; ky=fy; kx=fx; board[jy+ky][jx+kx]=a; return 1; } //mv jwls bool jmove(byte dy,byte dx){ if(jy>LEN) return 0; if(jx+dx>=WID || jx+dx<0 || jx+kx+dx>=WID ||jx+kx+dx<0 || jy+dx<0 ||jx+dx+kx<0) return 0; if( board[jy+ky+dy][jx+kx+dx] ) if( !(jy+ky+dy == jy && jx+kx+dx==jx) ) return 0; if( board[jy+dy][jx+dx]) if(!(dx==kx && dy==ky)) return 0; //still alive? chtype a = board[jy][jx]; chtype b = board[jy+ky][jx+kx]; board[jy][jx]=0; board[jy+ky][jx+kx]=0; board[jy+dy][jx+dx]=a; board[jy+ky+dy][jx+kx+dx]=b; jy+=dy;jx+=dx; return 1; } //scoring algorithm bool explode(byte combo){ bool ret =0; chtype c,uc; byte n; byte y,x; for(y=0;y<LEN;y++){ c=uc=n=0; for(x=0;x<WID;x++){ uc = c; c = board[y][x]; if(c && c == uc){ n++; if(n>=3 && x==WID-1){//the chain ends because the row ends x++; goto HrExplsn; } } else if(n>=3){ HrExplsn: score+=n*10*(n-2)*combo; ret=1; for(;n>=0;n--) board[y][x-1-n]=0; n=0; } else n=0; } } for(x=0;x<WID;x++){ c=uc=n=0; for(byte y=0;y<LEN;y++){ uc=c; c = board[y][x]; if(c && c == uc){ n++; if(n>=3 && y==LEN-1){ y++; goto VrExplsn; } } else if(n>=3){ VrExplsn: score+=n*10*(n-2)*combo; ret=1; for(;n>=0;n--) board[y-1-n][x]=0; n=0; } else n=0; } } return ret; } //display void draw(void){ erase(); int middle = (COLS/2-1)-(WID/2); chtype a=A_STANDOUT|' '; mvhline(LEN,middle-2,a,WID+4); mvvline(0,middle-1,a,LEN); mvvline(0,middle-2,a,LEN); mvvline(0,middle+WID,a,LEN); mvvline(0,middle+WID+1,a,LEN); mvprintw(0,0,"Score:%d",score); mvaddstr(1,0,"Next:"); addch(next1); addch(next2); for(byte y=0;y<LEN;y++){ for(byte x=0;x<WID;x++){ chtype c = board[y][x]; if(c) mvaddch(y,middle+x,c); } } mvaddstr(LINES-2,middle-5,controls); refresh(); } int main(void){ initscr(); cbreak(); halfdelay(DELAY); noecho(); curs_set(0); wnoutrefresh(stdscr); keypad(stdscr,1); int input; bool falls; byte stop=0 , combo; char jwstr[] = {'*','^','~','"','$','V'}; if(has_colors()){ start_color(); use_default_colors(); init_pair(1,COLOR_RED,-1); init_pair(2,COLOR_GREEN,-1); init_pair(3,COLOR_MAGENTA,-1); init_pair(4,COLOR_BLUE,-1);//array this thing init_pair(5,COLOR_YELLOW,-1); init_pair(6,COLOR_CYAN,-1); for(byte n=0;n<6;n++){ colors[n] = COLOR_PAIR(n+1); } } srand(time(NULL)%UINT_MAX); byte ran1= rand()%6; byte ran2= rand()%6; next1= colors[ran1]|jwstr[ran1]; next2= colors[ran2]|jwstr[ran2]; while(1){ chtype a,b; a=board[0][WID/2]; b=board[0][WID/2-1]; if(a || b ){ goto Lose; } jy=ky=0; jx=WID/2; kx=-1; board[jy][jx]=next2; board[jy+ky][jx+kx]=next1; ran1= rand()%6; ran2= rand()%6; next1=colors[ran1]|jwstr[ran1]; next2=colors[ran2]|jwstr[ran2]; falls = 1; while(falls){ input = getch(); if(input != ERR) stop+=1; if( stop >= 10){ falls=fall(); stop=0; } else if(input=='l' || input==KEY_RIGHT) jmove(0,+1); else if(input=='j' || input==KEY_LEFT ) jmove(0,-1); else if(input=='k' || input==KEY_UP) rotate(); else if(input=='p'){ mvaddstr(LINES-2,COLS/2-15,"Paused - Press a key to continue "); refresh(); nocbreak(); cbreak(); getch(); halfdelay(DELAY); } else if(input=='q') goto Lose; else if(input==' ') while( (falls=fall()) ) stop=0; else{ falls=fall(); stop=0; } draw(); } combo=1; while(explode(combo)){ // explode, fall, explode, fall until nothing is left combo++; while(fall()); draw(); } } Lose: nocbreak(); endwin(); printf("%s _Jewels_ %s\n",jwstr,jwstr); printf("You have scored %ld points.\n",score); showscores(scorewrite(score)); return EXIT_SUCCESS; }