mirror of
https://github.com/abakh/nbsdgames.git
synced 2024-12-04 14:46:22 -05:00
Snakeduel!
This commit is contained in:
parent
5efed29a4f
commit
2882f9b0ab
59
Makefile
59
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)
|
||||
|
||||
|
778
snakeduel.c
Normal file
778
snakeduel.c
Normal file
@ -0,0 +1,778 @@
|
||||
/*
|
||||
_ _
|
||||
(_ | :
|
||||
_)NAKE |.'UEL
|
||||
|
||||
Authored by abakh <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 -lm -lncurses
|
||||
*/
|
||||
#include <curses.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <limits.h>
|
||||
#include <time.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#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.x<wid && s.y<len){
|
||||
board[s.y][s.x]=s.fp+opposite(s.direction);//putting direction for wiping
|
||||
}
|
||||
}
|
||||
void move_snake(byte board[len][wid],snake *s){
|
||||
assert(!blocked(board,*s));
|
||||
*s=fake_move(*s);
|
||||
putfp(board,*s);
|
||||
}
|
||||
void purs(snake me,int y,int x,byte directions[4]){
|
||||
if(me.y<y){
|
||||
directions[0]=DOWN;
|
||||
directions[3]=UP;
|
||||
}
|
||||
else{
|
||||
directions[0]=UP;
|
||||
directions[3]=DOWN;
|
||||
}
|
||||
|
||||
if(me.x<x){
|
||||
directions[1]=RIGHT;
|
||||
directions[2]=LEFT;
|
||||
}
|
||||
else{
|
||||
directions[1]=LEFT;
|
||||
directions[2]=RIGHT;
|
||||
}
|
||||
int x_dist=abs(x-me.x);
|
||||
int y_dist=abs(y-me.y);
|
||||
|
||||
if(x_dist>y_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.y<enemy.y)
|
||||
goto JustPursue;
|
||||
break;
|
||||
case RIGHT:
|
||||
if(me.x<enemy.x)
|
||||
goto JustPursue;
|
||||
break;
|
||||
case LEFT:
|
||||
if(me.x>enemy.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_n<n){
|
||||
max_n=n;
|
||||
}
|
||||
if(max_n>len+wid){
|
||||
return max_n;
|
||||
}
|
||||
}
|
||||
reports("Then the maximum became:");
|
||||
reportd(max_n);
|
||||
}
|
||||
if(max<m+max_n){
|
||||
max=m+max_n;
|
||||
}
|
||||
}
|
||||
}
|
||||
return max;
|
||||
}
|
||||
void sort_directions(long data[4],byte directions[4]){
|
||||
bool not_sorted=1;
|
||||
while(not_sorted){
|
||||
not_sorted=0;
|
||||
for(byte i=0;i<3;++i){
|
||||
if(data[i]<data[i+1]){
|
||||
swap_long(&data[i],&data[i+1]);
|
||||
swap(&directions[i],&directions[i+1]);
|
||||
not_sorted=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void rank_for_survival(byte board[len][wid],snake me,long advantages[4],byte directions[4]){
|
||||
long max_adv,adv,sum,sum_positives;
|
||||
for(byte i=0;i<4;++i){
|
||||
reports("inspecting various directions");
|
||||
reportd(i);
|
||||
adv=sum=sum_positives=0;
|
||||
max_adv=LONG_MIN;
|
||||
me.direction= directions[i];
|
||||
adv=mnvrblty(board,me,2);//advantage(board,*me,*enemy,depth-1);
|
||||
reports("advantage is");
|
||||
reportd(adv);
|
||||
if(max_adv<adv){
|
||||
max_adv=adv;
|
||||
}
|
||||
advantages[i]=max_adv;
|
||||
|
||||
reportd(advantages[i]);
|
||||
}
|
||||
|
||||
sort_directions(advantages,directions);
|
||||
reportd(advantages[0]);
|
||||
reportd(directions[0]);
|
||||
reportd(advantages[1]);
|
||||
reportd(directions[1]);
|
||||
reportd(advantages[2]);
|
||||
reportd(directions[2]);
|
||||
reportd(advantages[3]);
|
||||
reportd(directions[3]);
|
||||
}
|
||||
void draw(byte board[len][wid]){
|
||||
int y,x;
|
||||
rectangle();
|
||||
mvprintw(1,16,"Computer's wins: %d",c.score);
|
||||
mvprintw(2,16,"Your wins: %d",p.score);
|
||||
for(y=0;y<len;++y){
|
||||
for(x=0;x<wid;++x){
|
||||
switch(board[y][x]/4){
|
||||
case 1:
|
||||
mvaddch(4+y,x+1,' '|A_STANDOUT|c.color);
|
||||
break;
|
||||
case 2:
|
||||
mvaddch(4+y,x+1,' '|A_STANDOUT|p.color);
|
||||
break;
|
||||
}
|
||||
if(board[y][x]<0)
|
||||
mvaddch(4+y,x+1,'0'-board[y][x]);
|
||||
}
|
||||
}
|
||||
}
|
||||
void help(void){
|
||||
nocbreak();
|
||||
cbreak();
|
||||
erase();
|
||||
logo();
|
||||
attron(A_BOLD);
|
||||
mvprintw(3,0," **** THE CONTROLS ****");
|
||||
attroff(A_BOLD);
|
||||
mvprintw(4,0,"hjkl/ARROW KEYS : Change direction");
|
||||
mvprintw(5,0,"q : Quit");
|
||||
mvprintw(6,0,"F1 & F2: Help on controls & gameplay");
|
||||
mvprintw(8,0,"Press a key to continue");
|
||||
refresh();
|
||||
getch();
|
||||
erase();
|
||||
halfdelay(1);
|
||||
}
|
||||
void gameplay(void){
|
||||
nocbreak();
|
||||
cbreak();
|
||||
erase();
|
||||
logo();
|
||||
attron(A_BOLD);
|
||||
mvprintw(3,0," **** THE GAMEPLAY ****");
|
||||
attroff(A_BOLD);
|
||||
move(4,0);
|
||||
printw("Don't hit the walls, the other snake and yourself. Kill the other snake.\n");
|
||||
refresh();
|
||||
getch();
|
||||
erase();
|
||||
halfdelay(1);
|
||||
}
|
||||
void sigint_handler(int x){
|
||||
endwin();
|
||||
puts("Quit.");
|
||||
exit(x);
|
||||
}
|
||||
long decide(byte board[len][wid],snake *me,snake *enemy){
|
||||
//do the move that gives the enemy least advantage (or move randomly at depth 0)
|
||||
//return 0 if you fail to find a way out
|
||||
snake f=*me;//f:future
|
||||
static long turn=0;
|
||||
reports(" **MOVE***********");
|
||||
reportd(turn);
|
||||
++turn;
|
||||
reportd(me->direction);
|
||||
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;y<len;++y){
|
||||
for(byte x=0;x<wid;++x){
|
||||
board[y][x]=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
int main(int argc, char** argv){
|
||||
#ifdef REPORT
|
||||
lol=fopen("lol","w");
|
||||
fflush(lol);
|
||||
#endif
|
||||
bool autoset=0;
|
||||
signal(SIGINT,sigint_handler);
|
||||
#ifndef NO_VLA
|
||||
if(argc>3 || (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(len<MINLEN || wid<MINWID || len>500 || 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(len<MINLEN)
|
||||
len=MINLEN;
|
||||
else if(len>MAXLEN)
|
||||
len=MAXLEN;
|
||||
|
||||
wid=COLS-5;
|
||||
if(wid<MINWID)
|
||||
wid=MINWID;
|
||||
else if(wid>MAXWID)
|
||||
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.y<len-1 && p.direction != UP ){
|
||||
p.direction=DOWN;
|
||||
}
|
||||
if( (input=='h' || input==KEY_LEFT) && p.x>0 && p.direction != RIGHT){
|
||||
p.direction=LEFT;
|
||||
}
|
||||
if( (input=='l' || input==KEY_RIGHT) && p.x<wid-1 && p.direction != LEFT){
|
||||
p.direction=RIGHT;
|
||||
}
|
||||
if( input=='q')
|
||||
sigint_handler(0);
|
||||
if( input=='p'){
|
||||
nocbreak();
|
||||
cbreak();
|
||||
erase();
|
||||
logo();
|
||||
attron(A_BOLD);
|
||||
mvaddstr(1,13,"PAUSED");
|
||||
attroff(A_BOLD);
|
||||
getch();
|
||||
halfdelay(1);
|
||||
}
|
||||
if(input!=ERR){
|
||||
if(preinput==input){//if it wasn't there, hitting two keys in less than 0.1 sec would not work
|
||||
usleep(100000);
|
||||
flushinp();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for(byte i=0;i<2;++i){
|
||||
if(blocked(board,p)){
|
||||
++c.score;
|
||||
reports("player died");
|
||||
goto Die;
|
||||
}
|
||||
else{
|
||||
move_snake(board,&p);
|
||||
}
|
||||
|
||||
/*if(decide(board,&p,&c) == LOSE){//move, if failed die.
|
||||
++c.score;
|
||||
reports("computer died");
|
||||
goto Die;
|
||||
}*/
|
||||
if(decide(board,&c,&p) == LOSE){//move, if failed die.
|
||||
++p.score;
|
||||
reports("computer died");
|
||||
goto Die;
|
||||
}
|
||||
}
|
||||
refresh();
|
||||
}
|
||||
Die:
|
||||
nocbreak();
|
||||
cbreak();
|
||||
draw(board);
|
||||
refresh();
|
||||
mvprintw(5+len,0,"Game over! Wanna play again?(y/n)");
|
||||
curs_set(1);
|
||||
input=getch();
|
||||
if( input!= 'N' && input!= 'n' && input!='q')
|
||||
goto Start;
|
||||
endwin();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
Loading…
Reference in New Issue
Block a user