1 /*
2  _       _
3 (_      | :
4  _)NAKE |.'UEL
5 
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 <curses.h>
14 #include <string.h>
15 #include <stdlib.h>
16 #include <stdbool.h>
17 #include <limits.h>
18 #include <time.h>
19 #include <signal.h>
20 #include <unistd.h>
21 #include <assert.h>
22 #include "config.h"
23 #define SAVE_TO_NUM 10
24 #define MINLEN 10
25 #define MAXLEN 127
26 #define MINWID 40
27 #define MAXWID 127
28 #define LOSE -(MAXWID*MAXLEN)
29 #define WIN_LIMIT 5
30 //#define REPORT 0
31 #ifdef REPORT
32 	#define reportif(x) if(x){fprintf(lol,#x" is true\n");fflush(lol);}
33 	#define reportd(x) if(REPORT){fprintf(lol, #x": %ld\n",(long)x);fflush(lol);}
34 	#define reports(x) if(REPORT){fprintf(lol, "line %d: %s\n",__LINE__,x);fflush(lol);}
35 #else
36 	#define reportif(x)
37 	#define reportd(x)
38 	#define reports(x)
39 #endif
40 
41 enum {UP=0,RIGHT,DOWN,LEFT};
42 enum {BLOCK=0,SURVIVAL,MIRROR,IMITATE};
43 /* The Plan9 compiler can not handle VLAs */
44 #ifdef NO_VLA
45 #define len 36
46 #define wid 80
47 
48 #ifdef Plan9
usleep(long usec)49 int usleep(long usec) {
50     int second = usec/1000000;
51     long nano = usec*1000 - second*1000000;
52     struct timespec sleepy = {0};
53     sleepy.tv_sec = second;
54     sleepy.tv_nsec = nano;
55     nanosleep(&sleepy, (struct timespec *) NULL);
56     return 0;
57 }
58 #endif
59 
60 
61 #else
62 int len,wid;
63 #endif//NO_VLA
64 typedef struct snake{
65 	int y;
66 	int x;
67 	byte direction;
68 	byte fp;
69 	byte strategy;
70 	byte score;
71 	chtype color;
72 } snake;
73 snake p;//player
74 snake c;//computer
75 byte pscore;
76 byte cscore;
77 chtype colors[6]={0};
78 byte constant_change={0};
79 
80 bool must_win=0;
81 FILE* lol;
82 
logo(void)83 void logo(void){
84 	mvaddstr(0,0," _       _");
85 	mvaddstr(1,0,"(_      | :  ");
86 	mvaddstr(2,0," _)NAKE |.'UEL");
87 }
rectangle(void)88 void rectangle(void){
89 	for(int y=0;y<=len;++y){
90 		mvaddch(3+y,0,ACS_VLINE);
91 		mvaddch(4+y,1+wid,ACS_VLINE);
92 	}
93 	for(int x=0;x<=wid;++x){
94 		mvaddch(3,x,ACS_HLINE);
95 		mvaddch(4+len,x,ACS_HLINE);
96 	}
97 	mvaddch(3,0,ACS_ULCORNER);
98 	mvaddch(4+len,0,ACS_LLCORNER);
99 	mvaddch(3,1+wid,ACS_URCORNER);
100 	mvaddch(4+len,1+wid,ACS_LRCORNER);
101 }
102 
swap(byte * a,byte * b)103 void swap(byte* a,byte* b){
104 	byte s= *a;
105 	*a=*b;
106 	*b=s;
107 }
swap_long(long * a,long * b)108 void swap_long(long* a,long* b){
109 	long s= *a;
110 	*a=*b;
111 	*b=s;
112 }
opposite(byte direction)113 byte opposite(byte direction){
114 	switch(direction){
115 		case UP:
116 			return DOWN;
117 		case DOWN:
118 			return UP;
119 		case LEFT:
120 			return RIGHT;
121 		case RIGHT:
122 			return LEFT;
123 		default:
124 			abort();
125 	}
126 }
fake_move(snake s)127 snake fake_move(snake s){
128 	switch(s.direction){
129 		case UP:
130 			s.y=s.y-1;
131 		break;
132 		case DOWN:
133 			s.y=s.y+1;
134 		break;
135 		case LEFT:
136 			s.x=s.x-1;
137 		break;
138 		case RIGHT:
139 			s.x=s.x+1;
140 		break;
141 	}
142 	return s;
143 }
144 
blocked(byte board[len][wid],snake s)145 bool blocked(byte board[len][wid],snake s){
146 	s=fake_move(s);
147 	return ( s.y<0 || s.y >=len || s.x<0 || s.x>=wid || board[s.y][s.x] );
148 }
better_change_way(byte board[len][wid],snake s)149 bool better_change_way(byte board[len][wid],snake s){
150 	if(blocked(board,s)){
151 		return 1;
152 	}
153 	s=fake_move(s);
154 	if(blocked(board,s)){
155 		return 1;
156 	}
157 	return 0;
158 }
putfp(byte board[len][wid],snake s)159 void putfp(byte board[len][wid],snake s){
160 	if(s.x>=0 && s.y>=0 && s.x<wid && s.y<len){
161 		board[s.y][s.x]=s.fp+opposite(s.direction);//putting direction for wiping
162 	}
163 }
move_snake(byte board[len][wid],snake * s)164 void move_snake(byte board[len][wid],snake *s){
165 	assert(!blocked(board,*s));
166 	*s=fake_move(*s);
167 	putfp(board,*s);
168 }
purs(snake me,int y,int x,byte directions[4])169 void purs(snake me,int y,int x,byte directions[4]){
170 	if(me.y<y){
171 		directions[0]=DOWN;
172 		directions[3]=UP;
173 	}
174 	else{
175 		directions[0]=UP;
176 		directions[3]=DOWN;
177 	}
178 
179 	if(me.x<x){
180 		directions[1]=RIGHT;
181 		directions[2]=LEFT;
182 	}
183 	else{
184 		directions[1]=LEFT;
185 		directions[2]=RIGHT;
186 	}
187 	int x_dist=abs(x-me.x);
188 	int y_dist=abs(y-me.y);
189 
190 	if(x_dist>y_dist){
191 		swap(&directions[0],&directions[1]);
192 	}
193 	if(x_dist==y_dist && x_dist<3 && directions[0]==me.direction){
194 		swap(&directions[0],&directions[1]);
195 	}
196 
197 }
avoid(snake me,int y,int x,byte directions[4])198 void avoid(snake me,int y, int x, byte directions[4]){
199 	purs(me,y,x,directions);
200 	for(byte i=0;i<4;++i){
201 		directions[i]=opposite(directions[i]);
202 	}
203 }
shuffle(byte directions[4])204 void shuffle(byte directions[4]){
205 	byte a=rand()%4;
206 	byte b=rand()%4;
207 	swap(&directions[a],&directions[b]);
208 }
enemy_avoid(snake me,snake enemy,byte directions[4])209 void enemy_avoid(snake me,snake enemy,byte directions[4]){
210 	avoid(me,enemy.y,enemy.x,directions);
211 }
enemy_pursue(snake me,snake enemy,byte directions[4])212 void enemy_pursue(snake me,snake enemy,byte directions[4]){
213 	purs(me,enemy.y,enemy.x,directions);
214 }
enemy_block(byte board[len][wid],snake me,snake enemy,byte directions[4])215 void enemy_block(byte board[len][wid],snake me, snake enemy,byte directions[4]){
216 	snake ahead=enemy;
217 	switch(enemy.direction){
218 		case UP:
219 			if(me.y>enemy.y)//me is to the down of the enemy, so cannot plan to block it's way in advance
220 				goto JustPursue;
221 			break;
222 		case DOWN:
223 			if(me.y<enemy.y)
224 				goto JustPursue;
225 			break;
226 		case RIGHT:
227 			if(me.x<enemy.x)
228 				goto JustPursue;
229 			break;
230 		case LEFT:
231 			if(me.x>enemy.x)
232 				goto JustPursue;
233 			break;
234 		default:
235 			abort();
236 	}
237 
238 	for(byte i=0;i<10;++i){
239 		if(blocked(board,ahead)||ahead.y==me.y||ahead.x==me.x){
240 			purs(me,ahead.y,ahead.x,directions);
241 			return;
242 		}
243 		ahead=fake_move(ahead);
244 	}
245 	JustPursue:
246 	purs(me,ahead.y,ahead.x,directions);
247 }
enemy_mirror(snake me,snake enemy,byte directions[4])248 void enemy_mirror(snake me,snake enemy,byte directions[4]){
249 	int y,x;
250 	y=len-1-enemy.y;
251 	x=wid-1-enemy.x;
252 	purs(me,y,x,directions);
253 }
enemy_block_mirror(snake me,snake enemy,byte directions[4])254 void enemy_block_mirror(snake me,snake enemy,byte directions[4]){
255 	int y_dist=abs(me.y-enemy.y);
256 	int x_dist=abs(me.x-enemy.x);
257 
258 	if(y_dist>x_dist){
259 		purs(me,len-1-enemy.y,enemy.x,directions);
260 	}
261 	else{
262 		purs(me,enemy.y,wid-1-enemy.x,directions);
263 	}
264 }
move_to_top(byte array[4],byte index)265 void move_to_top(byte array[4],byte index){
266 	byte newtop=array[index];
267 	for(byte i=index;i>0;--i){
268 		array[i]=array[i-1];
269 	}
270 	array[0]=newtop;
271 }
leave_escapes(byte board[len][wid],snake me,byte directions[4])272 void leave_escapes(byte board[len][wid],snake me,byte directions[4]){
273 	byte s=3;
274 	for(byte i=0;i<4;i++){
275 		me.direction=directions[s];
276 		if(!better_change_way(board,me)){
277 			move_to_top(directions,s);
278 		}
279 		else{
280 			--s;
281 		}
282 	}
283 }
go_deep(byte board[len][wid],snake me,bool randomize)284 long go_deep(byte board[len][wid],snake me,bool randomize){
285 	reports("****go deep***");
286 	if(randomize){
287 		reports("randomize");
288 	}
289 	long m=0;
290 	byte bumps=0;
291 	static byte inc=1;
292 	if(randomize){
293 		inc=-inc;
294 	}
295 	while(!blocked(board,me)){
296 		me=fake_move(me);
297 		++m;
298 		if(m>len+wid){
299 			return m;
300 		}
301 		if(blocked(board,me)||(randomize&&!(rand()%10))){
302 			snake f=me;
303 			byte i;
304 
305 			if(randomize){
306 				f.direction=rand()%4;
307 			}
308 
309 			for(i=0;i<4;++i){
310 				if(f.direction!=opposite(me.direction) || blocked(board,f)){
311 					me=f;
312 					break;
313 				}
314 				else{
315 					f.direction+=4+inc;
316 					f.direction%=4;
317 				}
318 			}
319 
320 			reports("***BUMP!***");
321 			reportd(bumps);
322 			reportd(m);
323 
324 			if(bumps==4){
325 				return m;
326 			}
327 			else{
328 				++bumps;
329 			}
330 
331 		}
332 	}
333 	return m;
334 
335 }
mnvrblty(byte board[len][wid],snake me,byte depth)336 long mnvrblty(byte board[len][wid],snake me,byte depth){
337 	long m=0;
338 	long max=0,n,max_n;
339 	while(m<=4 && !blocked(board,me)){
340 		me=fake_move(me);
341 		++m;
342 		if(depth){
343 			snake f=me;
344 			max_n=0;
345 			for(byte i=0;i<4;++i){
346 				n=0;
347 				if(i==opposite(me.direction)){
348 					continue;
349 				}
350 				f.direction=i;
351 				for(byte j=0;j<10;++j){
352 					n=go_deep(board,f,j%2);
353 					if(max_n<n){
354 						max_n=n;
355 					}
356 					if(max_n>len+wid){
357 						return max_n;
358 					}
359 				}
360 				reports("Then the maximum became:");
361 				reportd(max_n);
362 			}
363 			if(max<m+max_n){
364 				max=m+max_n;
365 			}
366 		}
367 	}
368 	return max;
369 }
sort_directions(long data[4],byte directions[4])370 void sort_directions(long data[4],byte directions[4]){
371 	bool not_sorted=1;
372 	while(not_sorted){
373 		not_sorted=0;
374 		for(byte i=0;i<3;++i){
375 			if(data[i]<data[i+1]){
376 				swap_long(&data[i],&data[i+1]);
377 				swap(&directions[i],&directions[i+1]);
378 				not_sorted=1;
379 			}
380 		}
381 	}
382 }
rank_for_survival(byte board[len][wid],snake me,long advantages[4],byte directions[4])383 void rank_for_survival(byte board[len][wid],snake me,long advantages[4],byte directions[4]){
384 	long max_adv,adv,sum,sum_positives;
385 	for(byte i=0;i<4;++i){
386 		reports("inspecting various directions");
387 		reportd(i);
388 		adv=sum=sum_positives=0;
389 		max_adv=LONG_MIN;
390 		me.direction= directions[i];
391 		adv=mnvrblty(board,me,2);//advantage(board,*me,*enemy,depth-1);
392 		reports("advantage is");
393 		reportd(adv);
394 		if(max_adv<adv){
395 			max_adv=adv;
396 		}
397 		advantages[i]=max_adv;
398 
399 		reportd(advantages[i]);
400 	}
401 
402 	sort_directions(advantages,directions);
403 	reportd(advantages[0]);
404 	reportd(directions[0]);
405 	reportd(advantages[1]);
406 	reportd(directions[1]);
407 	reportd(advantages[2]);
408 	reportd(directions[2]);
409 	reportd(advantages[3]);
410 	reportd(directions[3]);
411 }
draw(byte board[len][wid])412 void draw(byte board[len][wid]){
413 	int y,x;
414 	rectangle();
415 	mvprintw(1,16,"Computer's wins: %d",c.score);
416 	mvprintw(2,16,"Your wins: %d",p.score);
417 	for(y=0;y<len;++y){
418 		for(x=0;x<wid;++x){
419 			switch(board[y][x]/4){
420 				case 1:
421 					mvaddch(4+y,x+1,' '|A_STANDOUT|c.color);
422 				break;
423 				case 2:
424 					mvaddch(4+y,x+1,' '|A_STANDOUT|p.color);
425 				break;
426 			}
427 			if(board[y][x]<0)
428 				mvaddch(4+y,x+1,'0'-board[y][x]);
429 		}
430 	}
431 }
help(void)432 void help(void){
433 	nocbreak();
434 	cbreak();
435 	erase();
436 	logo();
437 	attron(A_BOLD);
438 	mvprintw(3,0,"  **** THE CONTROLS ****");
439 	attroff(A_BOLD);
440 	mvprintw(4,0,"hjkl/ARROW KEYS : Change direction");
441 	mvprintw(5,0,"q : Quit");
442 	mvprintw(6,0,"F1 & F2: Help on controls & gameplay");
443 	mvprintw(8,0,"Press a key to continue");
444 	refresh();
445 	getch();
446 	erase();
447 	halfdelay(1);
448 }
gameplay(void)449 void gameplay(void){
450 	nocbreak();
451 	cbreak();
452 	erase();
453 	logo();
454 	attron(A_BOLD);
455 	mvprintw(3,0,"  **** THE GAMEPLAY ****");
456 	attroff(A_BOLD);
457 	move(4,0);
458 	printw("Don't hit the walls, the other snake and yourself. Kill the other snake.\n");
459 	refresh();
460 	getch();
461 	erase();
462 	halfdelay(1);
463 }
sigint_handler(int x)464 void sigint_handler(int x){
465 	endwin();
466 	puts("Quit.");
467 	exit(x);
468 }
decide(byte board[len][wid],snake * me,snake * enemy)469 long decide(byte board[len][wid],snake *me,snake *enemy){
470 	//do the move that gives the enemy least advantage (or move randomly at depth 0)
471 	//return 0 if you fail to find a way out
472 	snake f=*me;//f:future
473 	static long turn=0;
474 	reports(" **MOVE***********");
475 	reportd(turn);
476 	++turn;
477 	reportd(me->direction);
478 	int y_dist=(abs(me->y-enemy->y));
479 	int x_dist=(abs(me->x-enemy->x));
480 	int dist=(y_dist+x_dist);
481 	long g=go_deep(board,*me,1);
482 	reportd(g);
483 	byte directions[4]={0,1,2,3};
484 	long advantages[4]={0};
485 	if(me->strategy==IMITATE ){
486 		if(abs(me->y-(len-1-enemy->y))+abs(me->x-(wid-1-enemy->x))>3){
487 			me->strategy=SURVIVAL;
488 		}
489 		else{
490 			me->strategy=IMITATE;
491 		}
492 	}
493 	else if(g<20){
494 		 me->strategy=SURVIVAL;
495 	}
496 	else if( dist<20){
497 		me->strategy=BLOCK;
498 	}
499 	else{
500 		me->strategy=MIRROR;
501 	}
502 	bool change_path=0;
503 	if(better_change_way(board,*me)){
504 		change_path=1;
505 	}
506 	else if(me->strategy==IMITATE){
507 		change_path=1;
508 	}
509 	else if(me->strategy==SURVIVAL){
510 		reports("SURVIVAL!@#");
511 		change_path=1;
512 	}
513 	else if(me->strategy==MIRROR){
514 		change_path=better_change_way(board,*me) || ((me->x%2)&&(me->y%3==2)) || ((me->x%2==0)&&(me->y%3==0));
515 		if(better_change_way(board,*me) && !change_path){
516 			reports("fuck you");
517 		}
518 	}
519 	else if(me->strategy==BLOCK){
520 		reports("BLOCK!@#");
521 	       	change_path= !(rand()%(dist+1)) || !(rand()%(x_dist+1)) || !(rand()%(y_dist+1));//this one wants to leave escapes
522 
523 		if(!change_path && dist<40 && !(rand()%(dist/2+1))){//this one wants to kill
524 			change_path=1;
525 		}
526 	}
527 
528 	if(change_path){
529 		if(me->strategy==IMITATE){
530 			enemy_mirror(*me,*enemy,directions);
531 		}
532 		if(me->strategy==MIRROR){
533 			enemy_mirror(*me,*enemy,directions);
534 			//shuffle(directions);
535 			leave_escapes(board,*me,directions);
536 			reports("did the leave escapes shit");
537 			reports("MIRROR");
538 		}
539 		else if(me->strategy==BLOCK){
540 			if(dist<7){
541 				enemy_pursue(*me,*enemy,directions);
542 			}
543 			/*else if(dist<20){
544 				enemy_block(board,*me,*enemy,directions);
545 			}*/
546 			else{
547 				enemy_block(board,*me,*enemy,directions);
548 			}
549 			leave_escapes(board,*me,directions);
550 			reports("BLOCK");
551 		}
552 
553 		else if(me->strategy==SURVIVAL){
554 			rank_for_survival(board,*me,advantages,directions);
555 			reports("SURVIVAL and I am acting upon it");
556 
557 		}
558 
559 		for(byte i=0;i<4;++i){//if one way is blocked, go for others
560 			reportd(directions[i]);
561 			f.direction=directions[i];
562 			if(!blocked(board,f)){
563 				if(better_change_way(board,f)){
564 					reports("YET THIS MOTHER FUCKER CHOSE:");
565 					reportd(i);
566 				}
567 				*me=f;
568 				move_snake(board,me);
569 				return 1;
570 			}
571 			else{
572 				reports("this fucker didn't choose:");
573 				reportd(directions[i]);
574 				reports("because that way was supposedly blocked.");
575 			}
576 		}
577 		return LOSE;
578 	}
579 
580 	reports("went on");
581 	move_snake(board,me);
582 	return 1;
583 }
init_game(byte board[len][wid])584 void init_game(byte board[len][wid]){
585 	if(p.score>c.score+2 && rand()%2){
586 		must_win=1;
587 	}
588 	if(must_win && p.score>c.score){
589 		c.strategy=IMITATE;
590 	}
591 	else{
592 		c.strategy=MIRROR;
593 	}
594 
595 	c.direction=0;
596 	c.y=len/2;
597 	c.x=wid*9/20;
598 	c.fp=4;
599 	c.color=colors[rand()%6];
600 	p.direction=0;
601 	p.y=len/2;
602 	p.x=wid*11/20;
603 	p.fp=8;
604 
605 	do{
606 		p.color=colors[rand()%6];
607 	}while(p.color==c.color);
608 
609 	for(byte y=0;y<len;++y){
610 		for(byte x=0;x<wid;++x){
611 			board[y][x]=0;
612 		}
613 	}
614 }
main(int argc,char ** argv)615 int main(int argc, char** argv){
616 	#ifdef REPORT
617 	lol=fopen("lol","w");
618 	fflush(lol);
619 	#endif
620 	bool autoset=0;
621 	signal(SIGINT,sigint_handler);
622 	#ifndef NO_VLA
623 	if(argc>3 || (argc==2 && !strcmp("help",argv[1])) ){
624 		printf("Usage: %s [len wid]\n",argv[0]);
625 		return EXIT_FAILURE;
626 	}
627 	if(argc==2){
628 		puts("Give both dimensions.");
629 		return EXIT_FAILURE;
630 	}
631 	if(argc==3){
632 		bool lool = sscanf(argv[1],"%d",&len) && sscanf(argv[2],"%d",&wid);
633 		if(!lool){
634 			puts("Invalid input.");
635 			return EXIT_FAILURE;
636 		}
637 		if(len<MINLEN || wid<MINWID || len>500 || wid>500){
638 			puts("At least one of your given dimensions is either too small or too big.");
639 			return EXIT_FAILURE;
640 		}
641 
642 	}
643 	else{
644 		autoset=1;
645 	}
646 	#endif
647 	initscr();
648 	#ifndef NO_VLA
649 	if(autoset){
650 		len=LINES-7;
651 		if(len<MINLEN)
652 			len=MINLEN;
653 		else if(len>MAXLEN)
654 			len=MAXLEN;
655 
656 		wid=COLS-5;
657 		if(wid<MINWID)
658 			wid=MINWID;
659 		else if(wid>MAXWID)
660 			wid=MAXWID;
661 	}
662 	#endif
663 	srand(time(NULL)%UINT_MAX);
664 	byte board[len][wid];
665 	byte win_limit=WIN_LIMIT;
666 
667 	reportd(len);
668 	reportd(wid);
669 	noecho();
670 	cbreak();
671 	keypad(stdscr,1);
672 	if(has_colors()){
673 		start_color();
674 		use_default_colors();
675 		init_pair(1,COLOR_RED,-1);
676 		init_pair(2,COLOR_YELLOW,-1);
677 		init_pair(3,COLOR_GREEN,-1);
678 		init_pair(4,COLOR_CYAN,-1);
679 		init_pair(5,COLOR_MAGENTA,-1);
680 		init_pair(6,COLOR_BLUE,-1);
681 		for(byte b= 0;b<6;++b){
682 			colors[b]=COLOR_PAIR(b+1);
683 		}
684 		colors[1]|=A_BOLD;
685 	}
686 	Start:
687 	if(c.score==win_limit || p.score==win_limit){
688 		win_limit=WIN_LIMIT;
689 		c.score=p.score=0;
690 		must_win=0;
691 	}
692 	if(c.score==p.score && p.score==win_limit-1){
693 		++win_limit;
694 	}
695 	curs_set(0);
696 	halfdelay(1);
697 	init_game(board);
698 	erase();
699 	int preinput=0,input=0;
700 	while(1){
701 		logo();
702 		draw(board);
703 		refresh();
704 		preinput=input;
705 		input = getch();
706 		if( input == KEY_F(1) || input=='?' )
707 			help();
708 		if( input==KEY_F(2) )
709 			gameplay();
710 		if( (input=='k' || input==KEY_UP) && p.y>0 && p.direction != DOWN ){
711 			p.direction=UP;
712 		}
713 		if( (input=='j' || input==KEY_DOWN) && p.y<len-1 && p.direction != UP ){
714 			p.direction=DOWN;
715 		}
716 		if( (input=='h' || input==KEY_LEFT) && p.x>0 && p.direction != RIGHT){
717 			p.direction=LEFT;
718 		}
719 		if( (input=='l' || input==KEY_RIGHT) && p.x<wid-1 && p.direction != LEFT){
720 			p.direction=RIGHT;
721 		}
722 		if( input=='q')
723 			sigint_handler(0);
724 		if( input=='p'){
725 			nocbreak();
726 			cbreak();
727 			erase();
728 			logo();
729 			attron(A_BOLD);
730 			mvaddstr(1,13,"PAUSED");
731 			attroff(A_BOLD);
732 			getch();
733 			halfdelay(1);
734 		}
735 		if(input!=ERR){
736 			if(preinput==input){//if it wasn't there, hitting two keys in less than 0.1 sec would not work
737 				usleep(100000);
738 				flushinp();
739 			}
740 		}
741 
742 
743 		for(byte i=0;i<2;++i){
744 			if(blocked(board,p)){
745 				++c.score;
746 				reports("player died");
747 				goto Die;
748 			}
749 			else{
750 				move_snake(board,&p);
751 			}
752 
753 			/*if(decide(board,&p,&c) == LOSE){//move, if failed die.
754 				++c.score;
755 				reports("computer died");
756 				goto Die;
757 			}*/
758 			if(decide(board,&c,&p) == LOSE){//move, if failed die.
759 				++p.score;
760 				reports("computer died");
761 				goto Die;
762 			}
763 		}
764 		refresh();
765 	}
766 	Die:
767 	nocbreak();
768 	cbreak();
769 	draw(board);
770 	refresh();
771 	mvprintw(5+len,0,"Game over! Wanna play again?(y/n)");
772 	curs_set(1);
773 	input=getch();
774 	if( input!= 'N' &&  input!= 'n' && input!='q')
775 		goto Start;
776 	endwin();
777 	return EXIT_SUCCESS;
778 }
779