diff --git a/Makefile b/Makefile index 6fe37bb..445c935 100644 --- a/Makefile +++ b/Makefile @@ -1,23 +1,29 @@ # -*- Makefile -*- - -CFLAGS= -O3 -lncurses -Wno-unused-result -#-O3 --std=c99 -lcurses -DNO_MOUSE for BSD curses -#adding --std=c99 makes warnings in GNU, and the blame is upon glibc feature test macros. my code is correct. - -all: jewels sudoku mines reversi checkers battleship rabbithole sos pipes fifteen memoblocks fisher muncher miketron redsquare darrt +ifndef $(CFLAGS) + CFLAGS= -O3 -lncurses -Wno-unused-result + #-O3 --std=c99 -lcurses -DNO_MOUSE for NetBSD curses + #adding --std=c99 makes warnings in GNU, and the blame is upon glibc feature test macros. my code is correct. +endif +ifndef $(GAMES_DIR) + GAMES_DIR=/usr/games +endif +ifndef $(SCORES_DIR) + SCORES_DIR=/usr/games +endif +all: jewels sudoku mines reversi checkers battleship rabbithole sos pipes fifteen memoblocks fisher muncher miketron redsquare darrt snakeduel scorefiles: - touch /usr/games/pp_scores - touch /usr/games/jw_scores - touch /usr/games/mt_scores - touch /usr/games/mnch_scores - touch /usr/games/fsh_scores - touch /usr/games/drt_scores - chmod 666 /usr/games/pp_scores - chmod 666 /usr/games/jw_scores - chmod 666 /usr/games/mt_scores - chmod 666 /usr/games/mnch_scores - chmod 666 /usr/games/fsh_scores - chmod 666 /usr/games/drt_scores + touch $(SCORES_DIR)/pp_scores + touch $(SCORES_DIR)/jw_scores + touch $(SCORES_DIR)/mt_scores + touch $(SCORES_DIR)/mnch_scores + touch $(SCORES_DIR)/fsh_scores + touch $(SCORES_DIR)/drt_scores + chmod 666 $(SCORES_DIR)/pp_scores + chmod 666 $(SCORES_DIR)/jw_scores + chmod 666 $(SCORES_DIR)/mt_scores + chmod 666 $(SCORES_DIR)/mnch_scores + chmod 666 $(SCORES_DIR)/fsh_scores + chmod 666 $(SCORES_DIR)/drt_scores jewels: jewels.c config.h $(CC) jewels.c $(CFLAGS) -o ./jewels @@ -51,12 +57,13 @@ redsquare: redsquare.c config.h $(CC) redsquare.c $(CFLAGS) -o ./redsquare darrt: darrt.c config.h $(CC) darrt.c $(CFLAGS) -lm -o ./darrt -clean: - rm ./jewels ./sudoku ./checkers ./mines ./reversi ./battleship ./rabbithole ./sos ./pipes ./fifteen ./memoblocks ./fisher ./muncher ./miketron ./redsquare ./darrt -uninstall: - rm $(PREFIX)/jewels $(PREFIX)/sudoku $(PREFIX)/checkers $(PREFIX)/mines $(PREFIX)/reversi $(PREFIX)/battleship $(PREFIX)/rabbithole $(PREFIX)/sos $(PREFIX)/pipes $(PREFIX)/fifteen $(PREFIX)/memoblocks $(PREFIX)/fisher $(PREFIX)/muncher $(PREFIX)/miketron $(PREFIX)/redsquare $(PREFIX)/darrt -copy_sources: - cp Makefile config.h jewels.c sudoku.c mines.c reversi.c checkers.c battleship.c rabbithole.c sos.c pipes.c fifteen.c memoblocks.c fisher.c muncher.c miketron.c redsquare.c darrt.c $(PREFIX) -install: scorefiles jewels sudoku mines reversi checkers battleship rabbithole sos pipes fifteen memoblocks fisher muncher miketron redsquare darrt - cp jewels sudoku mines reversi checkers battleship rabbithole sos pipes fifteen memoblocks fisher muncher miketron redsquare darrt $(PREFIX) + +snakeduel: snakeduel.c config.h + $(CC) snakeduel.c $(CFLAGS) -o ./snakeduel +clean: + rm ./jewels ./sudoku ./checkers ./mines ./reversi ./battleship ./rabbithole ./sos ./pipes ./fifteen ./memoblocks ./fisher ./muncher ./miketron ./redsquare ./darrt ./snakeduel +uninstall: + rm $(GAMES_DIR)/jewels $(GAMES_DIR)/sudoku $(GAMES_DIR)/checkers $(GAMES_DIR)/mines $(GAMES_DIR)/reversi $(GAMES_DIR)/battleship $(GAMES_DIR)/rabbithole $(GAMES_DIR)/sos $(GAMES_DIR)/pipes $(GAMES_DIR)/fifteen $(GAMES_DIR)/memoblocks $(GAMES_DIR)/fisher $(GAMES_DIR)/muncher $(GAMES_DIR)/miketron $(GAMES_DIR)/redsquare $(GAMES_DIR)/darrt $(GAMES_DIR)/snakeduel +install: scorefiles jewels sudoku mines reversi checkers battleship rabbithole sos pipes fifteen memoblocks fisher muncher miketron redsquare darrt snakeduel + cp jewels sudoku mines reversi checkers battleship rabbithole sos pipes fifteen memoblocks fisher muncher miketron redsquare darrt snakeduel $(GAMES_DIR) diff --git a/snakeduel.c b/snakeduel.c new file mode 100644 index 0000000..c391c5a --- /dev/null +++ b/snakeduel.c @@ -0,0 +1,778 @@ +/* + _ _ +(_ | : + _)NAKE |.'UEL + +Authored by abakh +No rights are reserved and this software comes with no warranties of any kind to the extent permitted by law. + +compile with -lm -lncurses +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "config.h" +#define SAVE_TO_NUM 10 +#define MINLEN 10 +#define MAXLEN 127 +#define MINWID 40 +#define MAXWID 127 +#define LOSE -(MAXWID*MAXLEN) +#define WIN_LIMIT 5 +//#define REPORT 0 +#ifdef REPORT + #define reportif(x) if(x){fprintf(lol,#x" is true\n");fflush(lol);} + #define reportd(x) if(REPORT){fprintf(lol, #x": %ld\n",(long)x);fflush(lol);} + #define reports(x) if(REPORT){fprintf(lol, "line %d: %s\n",__LINE__,x);fflush(lol);} +#else + #define reportif(x) + #define reportd(x) + #define reports(x) +#endif + +enum {UP=0,RIGHT,DOWN,LEFT}; +enum {BLOCK=0,SURVIVAL,MIRROR,IMITATE}; +typedef signed char byte; +/* The Plan9 compiler can not handle VLAs */ +#ifdef NO_VLA +#define len 10 +#define wid 40 + +#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 + + +#else +int len,wid; +#endif//NO_VLA +typedef struct snake{ + int y; + int x; + byte direction; + byte fp; + byte strategy; + byte score; + chtype color; +} snake; +snake p;//player +snake c;//computer +byte pscore; +byte cscore; +chtype colors[6]={0}; +byte constant_change={0}; + +bool must_win=0; +FILE* lol; + +void logo(void){ + mvaddstr(0,0," _ _"); + mvaddstr(1,0,"(_ | : "); + mvaddstr(2,0," _)NAKE |.'UEL"); +} +void rectangle(void){ + for(int y=0;y<=len;++y){ + mvaddch(3+y,0,ACS_VLINE); + mvaddch(4+y,1+wid,ACS_VLINE); + } + for(int x=0;x<=wid;++x){ + mvaddch(3,x,ACS_HLINE); + mvaddch(4+len,x,ACS_HLINE); + } + mvaddch(3,0,ACS_ULCORNER); + mvaddch(4+len,0,ACS_LLCORNER); + mvaddch(3,1+wid,ACS_URCORNER); + mvaddch(4+len,1+wid,ACS_LRCORNER); +} + +void swap(byte* a,byte* b){ + byte s= *a; + *a=*b; + *b=s; +} +void swap_long(long* a,long* b){ + long s= *a; + *a=*b; + *b=s; +} +byte opposite(byte direction){ + switch(direction){ + case UP: + return DOWN; + case DOWN: + return UP; + case LEFT: + return RIGHT; + case RIGHT: + return LEFT; + default: + abort(); + } +} +snake fake_move(snake s){ + switch(s.direction){ + case UP: + s.y=s.y-1; + break; + case DOWN: + s.y=s.y+1; + break; + case LEFT: + s.x=s.x-1; + break; + case RIGHT: + s.x=s.x+1; + break; + } + return s; +} + +bool blocked(byte board[len][wid],snake s){ + s=fake_move(s); + return ( s.y<0 || s.y >=len || s.x<0 || s.x>=wid || board[s.y][s.x] ); +} +bool better_change_way(byte board[len][wid],snake s){ + if(blocked(board,s)){ + return 1; + } + s=fake_move(s); + if(blocked(board,s)){ + return 1; + } + return 0; +} +void putfp(byte board[len][wid],snake s){ + if(s.x>=0 && s.y>=0 && s.xy_dist){ + swap(&directions[0],&directions[1]); + } + if(x_dist==y_dist && x_dist<3 && directions[0]==me.direction){ + swap(&directions[0],&directions[1]); + } + +} +void avoid(snake me,int y, int x, byte directions[4]){ + purs(me,y,x,directions); + for(byte i=0;i<4;++i){ + directions[i]=opposite(directions[i]); + } +} +void shuffle(byte directions[4]){ + byte a=rand()%4; + byte b=rand()%4; + swap(&directions[a],&directions[b]); +} +void enemy_avoid(snake me,snake enemy,byte directions[4]){ + avoid(me,enemy.y,enemy.x,directions); +} +void enemy_pursue(snake me,snake enemy,byte directions[4]){ + purs(me,enemy.y,enemy.x,directions); +} +void enemy_block(byte board[len][wid],snake me, snake enemy,byte directions[4]){ + snake ahead=enemy; + switch(enemy.direction){ + case UP: + if(me.y>enemy.y)//me is to the down of the enemy, so cannot plan to block it's way in advance + goto JustPursue; + break; + case DOWN: + if(me.yenemy.x) + goto JustPursue; + break; + default: + abort(); + } + + for(byte i=0;i<10;++i){ + if(blocked(board,ahead)||ahead.y==me.y||ahead.x==me.x){ + purs(me,ahead.y,ahead.x,directions); + return; + } + ahead=fake_move(ahead); + } + JustPursue: + purs(me,ahead.y,ahead.x,directions); +} +void enemy_mirror(snake me,snake enemy,byte directions[4]){ + int y,x; + y=len-1-enemy.y; + x=wid-1-enemy.x; + purs(me,y,x,directions); +} +void enemy_block_mirror(snake me,snake enemy,byte directions[4]){ + int y_dist=abs(me.y-enemy.y); + int x_dist=abs(me.x-enemy.x); + + if(y_dist>x_dist){ + purs(me,len-1-enemy.y,enemy.x,directions); + } + else{ + purs(me,enemy.y,wid-1-enemy.x,directions); + } +} +void move_to_top(byte array[4],byte index){ + byte newtop=array[index]; + for(byte i=index;i>0;--i){ + array[i]=array[i-1]; + } + array[0]=newtop; +} +void leave_escapes(byte board[len][wid],snake me,byte directions[4]){ + byte s=3; + for(byte i=0;i<4;i++){ + me.direction=directions[s]; + if(!better_change_way(board,me)){ + move_to_top(directions,s); + } + else{ + --s; + } + } +} +long go_deep(byte board[len][wid],snake me,bool randomize){ + reports("****go deep***"); + if(randomize){ + reports("randomize"); + } + long m=0; + byte bumps=0; + static byte inc=1; + if(randomize){ + inc=-inc; + } + while(!blocked(board,me)){ + me=fake_move(me); + ++m; + if(m>len+wid){ + return m; + } + if(blocked(board,me)||(randomize&&!(rand()%10))){ + snake f=me; + byte i; + + if(randomize){ + f.direction=rand()%4; + } + + for(i=0;i<4;++i){ + if(f.direction!=opposite(me.direction) || blocked(board,f)){ + me=f; + break; + } + else{ + f.direction+=4+inc; + f.direction%=4; + } + } + + reports("***BUMP!***"); + reportd(bumps); + reportd(m); + + if(bumps==4){ + return m; + } + else{ + ++bumps; + } + + } + } + return m; + +} +long mnvrblty(byte board[len][wid],snake me,byte depth){ + long m=0; + long max=0,n,max_n; + while(m<=4 && !blocked(board,me)){ + me=fake_move(me); + ++m; + if(depth){ + snake f=me; + max_n=0; + for(byte i=0;i<4;++i){ + n=0; + if(i==opposite(me.direction)){ + continue; + } + f.direction=i; + for(byte j=0;j<10;++j){ + n=go_deep(board,f,j%2); + if(max_nlen+wid){ + return max_n; + } + } + reports("Then the maximum became:"); + reportd(max_n); + } + if(maxdirection); + int y_dist=(abs(me->y-enemy->y)); + int x_dist=(abs(me->x-enemy->x)); + int dist=(y_dist+x_dist); + long g=go_deep(board,*me,1); + reportd(g); + long max_survival; + byte directions[4]={0,1,2,3}; + long advantages[4]={0}; + if(me->strategy==IMITATE ){ + if(abs(me->y-(len-1-enemy->y))+abs(me->x-(wid-1-enemy->x))>3){ + me->strategy=SURVIVAL; + } + else{ + me->strategy=IMITATE; + } + } + else if(g<20){ + me->strategy=SURVIVAL; + } + else if( dist<20){ + me->strategy=BLOCK; + } + else{ + me->strategy=MIRROR; + } + bool change_path=0; + if(better_change_way(board,*me)){ + change_path=1; + } + else if(me->strategy==IMITATE){ + change_path=1; + } + else if(me->strategy==SURVIVAL){ + reports("SURVIVAL!@#"); + change_path=1; + } + else if(me->strategy==MIRROR){ + change_path=better_change_way(board,*me) || ((me->x%2)&&(me->y%3==2)) || ((me->x%2==0)&&(me->y%3==0)); + if(better_change_way(board,*me) && !change_path){ + reports("fuck you"); + } + } + else if(me->strategy==BLOCK){ + reports("BLOCK!@#"); + change_path= !(rand()%(dist+1)) || !(rand()%(x_dist+1)) || !(rand()%(y_dist+1));//this one wants to leave escapes + + if(!change_path && dist<40 && !(rand()%(dist/2+1))){//this one wants to kill + change_path=1; + } + } + + if(change_path){ + if(me->strategy==IMITATE){ + enemy_mirror(*me,*enemy,directions); + } + if(me->strategy==MIRROR){ + enemy_mirror(*me,*enemy,directions); + //shuffle(directions); + leave_escapes(board,*me,directions); + reports("did the leave escapes shit"); + reports("MIRROR"); + } + else if(me->strategy==BLOCK){ + if(dist<7){ + enemy_pursue(*me,*enemy,directions); + } + /*else if(dist<20){ + enemy_block(board,*me,*enemy,directions); + }*/ + else{ + enemy_block(board,*me,*enemy,directions); + } + leave_escapes(board,*me,directions); + reports("BLOCK"); + } + + else if(me->strategy==SURVIVAL){ + rank_for_survival(board,*me,advantages,directions); + reports("SURVIVAL and I am acting upon it"); + + } + + for(byte i=0;i<4;++i){//if one way is blocked, go for others + reportd(directions[i]); + f.direction=directions[i]; + if(!blocked(board,f)){ + if(better_change_way(board,f)){ + reports("YET THIS MOTHER FUCKER CHOSE:"); + reportd(i); + } + *me=f; + move_snake(board,me); + return 1; + } + else{ + reports("this fucker didn't choose:"); + reportd(directions[i]); + reports("because that way was supposedly blocked."); + } + } + return LOSE; + } + + reports("went on"); + move_snake(board,me); + return 1; +} +void init_game(byte board[len][wid]){ + if(p.score>c.score+2 && rand()%2){ + must_win=1; + } + if(must_win && p.score>c.score){ + c.strategy=IMITATE; + } + else{ + c.strategy=MIRROR; + } + + c.direction=0; + c.y=len/2; + c.x=wid*9/20; + c.fp=4; + c.color=colors[rand()%6]; + p.direction=0; + p.y=len/2; + p.x=wid*11/20; + p.fp=8; + + do{ + p.color=colors[rand()%6]; + }while(p.color==c.color); + + for(byte y=0;y3 || (argc==2 && !strcmp("help",argv[1])) ){ + printf("Usage: %s [len wid]\n",argv[0]); + return EXIT_FAILURE; + } + if(argc==2){ + puts("Give both dimensions."); + return EXIT_FAILURE; + } + if(argc==3){ + bool lool = sscanf(argv[1],"%d",&len) && sscanf(argv[2],"%d",&wid); + if(!lool){ + puts("Invalid input."); + return EXIT_FAILURE; + } + if(len500 || wid>500){ + puts("At least one of your given dimensions is either too small or too big."); + return EXIT_FAILURE; + } + + } + else{ + autoset=1; + } + #endif + initscr(); + #ifndef NO_VLA + if(autoset){ + len=LINES-7; + if(lenMAXLEN) + len=MAXLEN; + + wid=COLS-5; + if(widMAXWID) + wid=MAXWID; + } + #endif + srand(time(NULL)%UINT_MAX); + byte board[len][wid]; + byte win_limit=WIN_LIMIT; + + reportd(len); + reportd(wid); + noecho(); + cbreak(); + keypad(stdscr,1); + if(has_colors()){ + start_color(); + use_default_colors(); + init_pair(1,COLOR_RED,-1); + init_pair(2,COLOR_YELLOW,-1); + init_pair(3,COLOR_GREEN,-1); + init_pair(4,COLOR_CYAN,-1); + init_pair(5,COLOR_MAGENTA,-1); + init_pair(6,COLOR_BLUE,-1); + for(byte b= 0;b<6;++b){ + colors[b]=COLOR_PAIR(b+1); + } + colors[1]|=A_BOLD; + } + Start: + if(c.score==win_limit || p.score==win_limit){ + win_limit=WIN_LIMIT; + c.score=p.score=0; + must_win=0; + } + if(c.score==p.score && p.score==win_limit-1){ + ++win_limit; + } + curs_set(0); + halfdelay(1); + init_game(board); + erase(); + int preinput=0,input=0; + while(1){ + logo(); + draw(board); + refresh(); + preinput=input; + input = getch(); + if( input == KEY_F(1) || input=='?' ) + help(); + if( input==KEY_F(2) ) + gameplay(); + if( (input=='k' || input==KEY_UP) && p.y>0 && p.direction != DOWN ){ + p.direction=UP; + } + if( (input=='j' || input==KEY_DOWN) && p.y0 && p.direction != RIGHT){ + p.direction=LEFT; + } + if( (input=='l' || input==KEY_RIGHT) && p.x