/* _ | '. | : |.' ARRT */ #include #include #include #include #include #include #include #include #include #include #include "config.h" #define SAVE_TO_NUM 11 #define LEN 24 #define HLEN LEN/2 #define WID 80 #define HWID WID/2 #define SHOTS_WHEN_STARTING 10 #define randint(a,b) ((a)+(rand()%((b+1)-(a)))) typedef signed char byte; #ifdef Plan9 int usleep(long usec) { int second = usec/1000000; long nano = usec*1000 - second*1000000; struct timespec sleepy = {0}; sleepy.tv_sec = second; sleepy.tv_nsec = nano; nanosleep(&sleepy, (struct timespec *) NULL); return 0; } #endif // 12 lines of water // 80 columns chtype colors[3]={0}; long score=0; char error [150]={0}; FILE* scorefile; chtype background[LEN][WID]; int input; typedef struct aim{ char sign; float y,x; float angle; float v; byte brake; bool visible; }aim; aim aims[26]; aim landed_aims[SHOTS_WHEN_STARTING];//so an aim couldn't pass below one that has already landed, doesn't make sense visually. byte shots,aims_to_stop; char msg[150]={0}; byte msg_show=0; byte digit_count(int num){ byte ret=0; do{ ++ret; num/=10; }while(num); return ret; } void filled_rect(byte sy,byte sx,byte ey,byte ex){ byte y,x; for(y=sy;yy,(byte)a->x); long points; if(distance>HLEN){ points=-2*pow(2,distance-HLEN); } else if((byte) a->y == HLEN && (byte) a->x == HWID){ points=1000000; } else{ points=pow(2,HLEN-distance); } return points; } void aim_lands(aim *a){ landed_aims[SHOTS_WHEN_STARTING-aims_to_stop]=*a; --aims_to_stop; score+=calculate_points(a); a->visible=0; float distance= center_distance((byte)a->y,(byte)a->x); if((byte)a->y==HLEN && (byte)a->x==HWID){ strcpy(msg,"Bravo!"); } else if(distance<2){ strcpy(msg,"Very close..."); } else{ goto NoMessage; } msg_show=30; NoMessage: return; } void move_aim(aim *a){ if(a->brake==1){ return; } else if(a->brake>0){ --a->brake; } bool bounce; bounce=0; //bounce when hitting the borders, and don't get stuck there if(a->x<0 || (int)a->x>=WID-1 || ((int)a->x==13 && a->y<=7 ) ){ a->angle =M_PI- a->angle; bounce=1; } if(a->y <0 || (int)a->y >= LEN-1 || (a->x<=13 && (int)a->y==7)){ a->angle =0- a->angle; bounce=1; } if(a->x<0)//these are for getting unstuck a->x=1; if(a->y<0) a->y=1; if(a->x>=WID) a->x=WID-1; if(a->y>=LEN) a->y=LEN-1; if((int)a->x==13 && a->y<7) a->x=14; if(a->x<=13 && (int)a->y==7) a->y=8; while(a->angle<0){//preventing overflow a->angle +=M_PI*2; } //move a->x+=cos(a->angle)*a->v; a->y+=sin(a->angle)*a->v; if(bounce && a->x>=WID-1)//getting unstuck a->x=WID-1; if(bounce && a->y>=LEN-1) a->y=LEN-1; if(bounce){//bounce in a slightly different direction than it should be a->angle +=randint(-1,1)*0.1; } if(a->x<13 && a->y<7){// don't go into the logo area if(13 - a->x < 7 - a->y){ a->y=8; } else{ a->x=14; } } if(a->brake==1){//the aim has just been stopped aim_lands(a); } } void star_line(byte y){ for(byte x=1;x=scorebuff[location] ){ fprintf(scorefile,"%s : %ld\n",getenv("USER"),score); ret=location; wroteit=1; } if(location0){ 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"); mvprintw(a+4,HWID-10," | .| | of"); mvprintw(a+5,HWID-10," |.' | |%11ld",formerscore); mvprintw(a+6,HWID-10," | | held by"); mvprintw(a+7,HWID-10," ___| |___%7s!",formername); mvprintw(a+8,HWID-10," | |"); 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); red_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>>"); printw("%s",pname); mvprintw(2+2*rank,WID-1-digit_count(pscore),"%d",pscore); ++rank; } attroff(colors[3]); refresh(); } void help(void){ nocbreak(); cbreak(); attron(colors[3]); filled_rect(0,0,LEN,WID); red_border(); mvprintw(1,HWID-4,"GAME PLAY"); mvprintw(3,1,"If you hit a letter on keyboard, the letter on the"); mvprintw(4,1,"screen will soon stop. You have to aim for the"); mvprintw(5,1,"center of the target using the moving letters."); attroff(colors[3]); refresh(); getch(); halfdelay(1); } void sigint_handler(int x){ endwin(); puts("Quit."); exit(x); } int main(void){ signal(SIGINT,sigint_handler); initscr(); noecho(); cbreak(); keypad(stdscr,1); srand(time(NULL)%UINT_MAX); if(has_colors()){ start_color(); init_pair(1,COLOR_RED,COLOR_BLACK); init_pair(2,COLOR_YELLOW,COLOR_BLACK); init_pair(3,COLOR_GREEN,COLOR_BLACK); for(byte b=0;b<3;++b) colors[b]=COLOR_PAIR(b+1); } byte n; make_background(); Start: erase(); halfdelay(1); curs_set(0); score=0; msg_show=0; aims_to_stop=shots=SHOTS_WHEN_STARTING; fill_aims(); while(1){ draw(); refresh(); input=getch(); if(input=='?' || input==KEY_F(1)) help(); if(input>='a' && input<='z'){ input=input-'a'+'A'; } if(input>='A' && input<='Z' && shots){ if(!aims[input-'A'].brake){ aims[input-'A'].brake=15; --shots; } } if(input=='Q'){ strcpy(msg,"Ctrl-C to quit."); msg_show=50; } if(input!=ERR){ usleep(100000); flushinp(); } if(!aims_to_stop){ break; } for(int i=0;i<26;++i){ move_aim(aims+i); } } End: flushinp(); nocbreak(); cbreak(); curs_set(1); end_scene(); showscores(scorewrite()); attron(colors[0]|A_STANDOUT); mvprintw(LEN-1,HWID-11,"Wanna play again? (y/n)"); attroff(colors[0]|A_STANDOUT); do{ input=getch(); }while(input==KEY_UP || input==KEY_DOWN); if(input!='q' && input!='n' && input!='N') goto Start; endwin(); return 0; }