From e67121e495f294eb7e9cca0158ab04a9c6794a6e Mon Sep 17 00:00:00 2001 From: abdulrahman Date: Fri, 21 Sep 2018 20:12:39 +0430 Subject: [PATCH] first commit --- README.md | 39 +++ games/battleship.c | 560 +++++++++++++++++++++++++++++++++++++++++ games/checkers.c | 604 +++++++++++++++++++++++++++++++++++++++++++++ games/jewels.c | 365 +++++++++++++++++++++++++++ games/mines.c | 266 ++++++++++++++++++++ games/reversi.c | 340 +++++++++++++++++++++++++ games/sudoku.c | 287 +++++++++++++++++++++ screenshot.png | Bin 0 -> 9662 bytes 8 files changed, 2461 insertions(+) create mode 100644 README.md create mode 100644 games/battleship.c create mode 100644 games/checkers.c create mode 100644 games/jewels.c create mode 100644 games/mines.c create mode 100644 games/reversi.c create mode 100644 games/sudoku.c create mode 100644 screenshot.png diff --git a/README.md b/README.md new file mode 100644 index 0000000..e94fdf1 --- /dev/null +++ b/README.md @@ -0,0 +1,39 @@ +# New BSD Games + +The TUI games i made for NetBSD ( If they accept these ). + +These include: + +Jewels (A game with a gameplay similiar to that of Tetris, NOT my invention) +Sudoku +Mines (Minesweeper) +Reversi +Checkers +Battleship + +### Prerequisites + +ALL you need is a C compiler with C99 enabled , the standard library and libncurses (the dev package if you are on debian). + +### How to run + +Just download them somehow and compile them with ncurses being linked. + +Normally: + +``` +cc "address_to_sourcefiles/game_name.c" -lncurses -o "address_to_binaries/game_name" +``` + +I am too lazy to write a script for this. + +### How do these look like + +![Screenshot including the checkers game and the battleship one] (screenshot.png) + + +### License + +Public Domain. + +I am living outside the Berne convention , This would be public domain anyway. diff --git a/games/battleship.c b/games/battleship.c new file mode 100644 index 0000000..d34d68a --- /dev/null +++ b/games/battleship.c @@ -0,0 +1,560 @@ +#include +#include +#include +#include +#include +#include +#define MISS -2 +#define SEA -1 +#define HIT 0 +#define ENGLISH_LETTERS 26 +#define NOTHING -1 +#define ALL 0x7c +#define RED 3 +#define CYAN 2 +/* + _ +|_) +|_)ATTLESHIP + +copyright Hossein Bakhtiarifar 2018 (c) +No rights are reserved and this software comes with no warranties of any kind to the extent permitted by law. + +compile with -lncurses +*/ +typedef signed char byte; +typedef unsigned char bitbox; +bool multiplayer; +byte py,px;//cursor + +chtype colors[4]={0}; + +byte game[2][10][10];//main board +bool computer[2] = {0}; +byte score[2] = {0};//set by header() +bitbox sunk[2]={0}; +byte just_sunk[2]={0};//to be displayed for human players + +byte firstinrowy , firstinrowx ; +byte lastinrowy ,lastinrowx; +byte goindirection; +byte shotinvain; +void sigint_handler(int x){ + endwin(); + puts("Quit."); + exit(x); +} +void rectangle(byte sy,byte sx){ + for(byte y=0;y<=10+1;y++){ + mvaddch(sy+y,sx,ACS_VLINE); + mvaddch(sy+y,sx+10*2,ACS_VLINE); + } + for(byte x=0;x<=10*2;x++){ + mvaddch(sy,sx+x,ACS_HLINE); + mvaddch(sy+10+1,sx+x,ACS_HLINE); + } + mvaddch(sy,sx,ACS_ULCORNER); + mvaddch(sy+10+1,sx,ACS_LLCORNER); + mvaddch(sy,sx+10*2,ACS_URCORNER);- + mvaddch(sy+10+1,sx+10*2,ACS_LRCORNER); +} +void print_type(byte type){ + switch(type){ + case(2): + addstr("patrol boat"); + break; + case(3): + addstr("destroyer"); + break; + case(4): + addstr("battleship"); + break; + case(5): + addstr("carrier"); + break; + case(6): + addstr("submarine"); + break; + } +} +void MID(byte *y , byte *x, byte direction){ + switch(direction){ + case(0): + *x=*x-1; + break; + case(1): + *y=*y-1; + break; + case(2): + *x=*x+1; + break; + case(3): + *y=*y+1; + break; + } +} +void genocide(bool side , byte type){ + byte y,x; + for(y=0;y<10;y++){ + for(x=0;x<10;x++){ + if(game[side][y][x] == type) + game[side][y][x] = SEA; + } + } +} +void header(bool side){ + score[0]=score[1]=0; + byte y,x; + for(y=0;y<10;y++){ + for(x=0;x<10;x++){ + if(game[!side][y][x] == HIT) + score[side]++; + if(game[side][y][x] == HIT) + score[!side]++; + } + } + mvaddch(0,1, '_'); + mvprintw(1,0,"|_) %2d:%2d",score[side],score[!side]); + mvprintw(2,0,"|_)ATTLESHIP "); +} + +void draw(bool side,byte sy,byte sx){//the game's board + rectangle(sy,sx); + chtype ch ; + byte y,x; + for(y=0;y<10;y++){ + for(x=0;x<10;x++){ + ch =A_NORMAL; + if(y==py && x==px) + ch |= A_STANDOUT; + if(game[side][y][x] == HIT) + ch |= 'X'|colors[RED]; + else if(game[side][y][x] > 0 ) + ch |= ACS_BLOCK|colors[side]; + else if(game[side][y][x]== MISS) + ch |= 'O'|colors[CYAN]; + else + ch |= '~'|colors[CYAN]; + + mvaddch(sy+1+y,sx+x*2+1,ch); + } + } +} +void draw_trackboard(bool side,byte sy,byte sx){ + rectangle(sy,sx); + chtype ch ; + byte y,x; + for(y=0;y<10;y++){ + for(x=0;x<10;x++){ + ch =A_NORMAL; + if(y==py && x==px-10) + ch |= A_STANDOUT; + + if(game[!side][y][x] == HIT) + ch |= '*'|colors[RED]; + else if(game[!side][y][x]== MISS) + ch |= '~'|colors[CYAN]; + else + ch |= '.'; + + mvaddch(sy+1+y,sx+x*2+1,ch); + } + } + refresh(); +} + +void autoset(bool side){ + byte y=0,x=0,direction=0, invain=0; + byte realy,realx; + byte l; + for(byte type=2;type<7;type++){ + SetLocation: + realy=random()%10; + realx=random()%10; + invain=0; + SetDirection: + y=realy; + x=realx; + direction=random()%4; + for(l=0;(type != 6 && l=10 || x>=10 || game[side][y][x] != SEA ){ + genocide(side,type); + invain++; + direction= (direction+1)%4; + if(invain<4) + goto SetDirection; + else + goto SetLocation;//endless loop + } + else{ + game[side][y][x]=type; + MID(&y,&x,direction); + } + } + } +} + +void set_the_board(bool side){ + if( computer[side] ){ + autoset(side); + return; + } + erase(); + mvaddch(0,1, '_'); + mvaddstr(1,0,"|_) Set your board"); + mvaddstr(2,0,"|_)ATTLESHIP"); + mvaddstr(16,0,"Press RETURN to specify the location and press R to rotate the ship."); + int input; + byte y=0,x=0,direction=0, invain=0; + byte realy,realx; + byte l; + py=px=0; + for(byte type=2;type<7;type++){ + mvaddstr(15,0,"Put your "); + print_type(type); + addstr(" in its position: "); + SetLocation: + while(1){ + draw(side,3,0); + refresh(); + input = getch(); + if( (input=='k' || input==KEY_UP) && py>0) + py--; + if( (input=='j' || input==KEY_DOWN) && py<9) + py++; + if( (input=='h' || input==KEY_LEFT) && px>0) + px--; + if( (input=='l' || input==KEY_RIGHT) && px<9) + px++; + if( input=='\n' ) + break; + if( input=='q' ) + sigint_handler(EXIT_SUCCESS); + } + + + realy=y=py; + realx=x=px; + invain=0; + SetDirection: + y=realy; + x=realx; + for(l=0;(type != 6 && l=10 || x>=10 || game[side][y][x] != SEA ){ + genocide(side,type); + invain++; + direction= (direction+1)%4; + if(invain<4) + goto SetDirection; + else + goto SetLocation;//endless loop + } + else{ + game[side][y][x]=type; + MID(&y,&x,direction); + } + } + while(1){ + invain=0; + draw(side,3,0); + input=getch(); + if( input== 'r' || input == 'R' ){ + genocide(side,type); + direction= (direction+1)%4; + goto SetDirection; + } + else + break; + } + } +} + +void turn_shift(void){ + if(!multiplayer) + return; + char key = 'a'+(random()%ENGLISH_LETTERS); + int input1,input2,input3; + input1=input2=input3=0; + erase(); + beep(); + mvaddch(0,1, '_'); + mvaddstr(1,0,"|_) Anti-cheater"); + mvaddstr(2,0,"|_)ATTLESHIP"); + mvaddstr(4,0,"********************"); + mvprintw(5,0," Type '%c' 3 times ",key); + mvaddstr(6,0," before "); + mvaddstr(7,0," proceeding "); + mvaddstr(8,0," to the game "); + mvaddstr(10,0,"********************"); + refresh(); + while(1){ + input3=input2; + input2=input1; + input1=getch(); + if( (input1==input2) && (input2==input3) && (input3==key) ) + break; + } + erase(); +} +byte shoot(bool turn, byte y , byte x){ + byte s = game[!turn][y][x]; + if(s>0){ + game[!turn][y][x]=HIT; + return 1; + } + else if(s==HIT || s==MISS || y<0 || x<0 || y>9 || x>9 ){ //didn't shoot at all + return -1; + } + else{ + game[!turn][y][x]=MISS; + return 0; + } + +} +void sink_announce(bool side){ + byte type,y,x; + for(type=2;type<7;type++){ + for(y=0;y<10;y++){ + for(x=0;x<10;x++){ + if( game[!side][y][x] == type ) + goto Next; + } + } + //there is no instance of 'type' in the opponet's board + if( ( (1 << type) | sunk[!side] ) != sunk[!side] ){ + sunk[!side] |= (1 << type); + if(computer[side]){ + lastinrowy=lastinrowx=firstinrowy=firstinrowx=-1; + shotinvain=0; + } + else{ + just_sunk[!side]=type;//leave to be displayed by you_sunk + } + return; + } + + + Next: + continue; + } +} +void you_sunk(bool side){ + if( just_sunk[!side] == 3) + mvaddstr(15,0,"You have destroyed my destroyer!!"); + else if( just_sunk[!side]){ + mvaddstr(15,0,"You have sunk my "); + print_type(just_sunk[!side]); + addstr("!!"); + } + just_sunk[!side]=0; +} +void cheat(bool side){ + /* its actually an anti-cheat, the player can place all their ships adjacent to the others and in the same direction, + and the algorithm will often play in a way that it will be left with some isolated tiles being unshot (with their ships being shot before). + a human will *very easily* find the tiles with logical thinking, but the computer is random and it will take such a long time for it + that it will often lose the winning game. + + this function still doesn't make a win,it's randomly executed.*/ + byte y,x; + for(y=0;y<10;y++){ + for(x=0;x<10;x++){ + if(game[!side][y][x]>0){ + shoot(side,y,x); + firstinrowy=y; + firstinrowx=x; + return; + } + } + } +} +void decide(bool side){// sink_announce is responsible for unsetting this variables + byte y,x,r; + Again: + if( firstinrowy == NOTHING ){ + if( score[!side] > 13 && score[side]9 || x>9) && r==NOTHING){ + goto Again; + } + } + r= shoot(side,y,x); + if(r==1){ + lastinrowy=y;//continue from the imaginary firstinrow + lastinrowx=x; + } + if(r==NOTHING) + goto Again; + } + + } + else{ + lastinrowy= y; + lastinrowx= x; + } + + if( r != NOTHING ) + return; + } + } + else{ + y=lastinrowy; + x=lastinrowx; + MID(&y,&x,goindirection); + r=shoot(side,y,x); + if( r == 1 ){ + lastinrowy=y; + lastinrowx=x; + } + else{ + lastinrowy=lastinrowx=NOTHING; + goindirection=(goindirection+2)%4; + } + if( r != NOTHING ) + return; + else{ + goto Again; + } + } +} +int main(int argc , char** argv){ + initscr(); + curs_set(0); + noecho(); + cbreak(); + keypad(stdscr,1); + if( has_colors() ){ + start_color(); + use_default_colors(); + init_pair(1,COLOR_GREEN,-1); + init_pair(2,COLOR_YELLOW,-1); + init_pair(3,COLOR_CYAN,-1); + init_pair(4,COLOR_RED,-1); + for(byte b=0;b<4;b++) + colors[b]=COLOR_PAIR(b+1); + } + int input; + printw("Choose type of the game:\n"); + printw("1 : Single Player*\n"); + printw("2 : Multi Player\n"); + input=getch(); + if(input == '2'){ + multiplayer=1; + computer[1]=computer[0]=0; + } + else{ + multiplayer=0; + computer[1]=1; + computer[0]=0; + } + Start: + firstinrowy=firstinrowx=lastinrowy=lastinrowx=goindirection=-1; + shotinvain=0; + sunk[0]=sunk[1]=0; + memset(game,SEA,200); + srandom(time(NULL)%UINT_MAX); + erase(); + + set_the_board(0); + turn_shift(); + set_the_board(1); + bool won; + bool turn=1; + Turn: + px=10; + py=0; + sink_announce(turn); + if( sunk[0]==ALL ){ + won=1; + goto End; + } + else if( sunk[1]==ALL ){ + won=0; + goto End; + } + //the turn starts HERE + turn=!turn; + turn_shift(); + if( computer[turn] ){ + decide(turn); + goto Turn; + } + else{ + erase(); + you_sunk(turn); + while(1){ + header(turn); + draw(turn,3,0); + draw_trackboard(turn,3,22); + refresh(); + input=getch(); + if( (input=='k' || input==KEY_UP) && py>0) + py--; + if( (input=='j' || input==KEY_DOWN) && py<9) + py++; + if( (input=='h' || input==KEY_LEFT) && px>10) + px--; + if( (input=='l' || input==KEY_RIGHT) && px<19) + px++; + if( input=='q') + sigint_handler(EXIT_SUCCESS); + if( input=='\n'){ + byte r=shoot(turn,py,px-10); + if(r != -1){ + goto Turn; + } + } + } + } + End: + erase(); + header(won); + draw(won,3,0); + draw_trackboard(won,3,22); + if( computer[won] ) + mvaddstr(15,0,"Hahaha! I won! "); + else + mvprintw(15,0,"Player %d won the game.",won+1); + addstr(" Wanna play again? (y/N)"); + refresh(); + curs_set(1); + input=getch(); + if( input=='y' || input=='Y' ){ + curs_set(0); + goto Start; + } + endwin(); + return 0; +} diff --git a/games/checkers.c b/games/checkers.c new file mode 100644 index 0000000..a5ef9e6 --- /dev/null +++ b/games/checkers.c @@ -0,0 +1,604 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#define LIGHT -1 +#define DARK 1 +#define KING 2 +#define DOESNT_MATTER 1 +#define IMAGINARY 0 +#define NORMAL 1 +#define ALT_IMG 2 +#define ALT_NRM 3 +#define WIN 100000 +/* + .-. +| ' +'._.HECKERS + +copyright Hossein Bakhtiarifar 2018 (c) +No rights are reserved and this software comes with no warranties of any kind to the extent permitted by law. + + +Compile with -lncurses +*/ +typedef signed char byte; +byte py,px;//cursor +byte cy,cx;//selected(choosen) piece +int dpt; +byte game[8][8]; +byte computer[2]={0,0}; +byte score[2];//set by header() +bool endgame=false; +byte jumpagainy , jumpagainx; +bool kinged;//if a piece jumps over multiple others and becomes a king it cannot continue jumping +void rectangle(byte sy,byte sx){ + byte y,x; + for(y=0;y<=8+1;y++){ + mvaddch(sy+y,sx,ACS_VLINE); + mvaddch(sy+y,sx+8*2,ACS_VLINE); + } + for(x=0;x<=8*2;x++){ + mvaddch(sy,sx+x,ACS_HLINE); + mvaddch(sy+8+1,sx+x,ACS_HLINE); + } + mvaddch(sy,sx,ACS_ULCORNER); + mvaddch(sy+8+1,sx,ACS_LLCORNER); + mvaddch(sy,sx+8*2,ACS_URCORNER); + mvaddch(sy+8+1,sx+8*2,ACS_LRCORNER); +} +void header(void){ + score[0]=score[1]=0; + byte y,x; + for(y=0;y<8;y++){ + for(x=0;x<8;x++){ + if(game[y][x]){ + if(game[y][x]<0) + score[0]++; + else + score[1]++; + } + } + } + mvprintw(0,0," .-."); + mvprintw(1,0,"| ' %2d:%2d",score[0],score[1]); + mvprintw(2,0,"'._,HECKERS "); +} +void draw(byte sy,byte sx){//the game's board + rectangle(sy,sx); + chtype ch ; + byte y,x; + for(y=0;y<8;y++){ + for(x=0;x<8;x++){ + ch=A_NORMAL; + if(y==py && x==px) + ch |= A_STANDOUT; + if(y==cy && x==cx) + ch |= A_BOLD; + if(game[y][x]){ + if(game[y][x]<0){ + if(has_colors()) + ch|=COLOR_PAIR(1); + else + ch |= A_UNDERLINE; + } + if(abs(game[y][x])<2) + ch |='O'; + else + ch |='K'; + } + else if( (y%2) != (x%2) ) + ch|='.'; + else + ch|=' '; + mvaddch(sy+1+y,sx+x*2+1,ch); + } + } +} +void fill(void){ + byte y,x; + for(y=0;y<8;y++){ + for(x=0;x<8;x++){ + game[y][x]=0; + if( (y%2) != (x%2)){ + if(y<3) game[y][x]=1; + if(y>4) game[y][x]=-1; + } + } + } +} +bool in(byte A[4],byte B[4],byte a,byte b){ + for(byte c=0;c<4;c++) + if(A[c]==a && B[c]==b) + return true; + return false; +} +bool moves(byte ty,byte tx,byte mvy[4],byte mvx[4]){ + bool ret=0; + byte ndx=0; + byte t= game[ty][tx]; + move(15,0); + byte dy,dx; + for(dy=-1;dy<2;dy++){ + for(dx=-1;dx<2;dx++){ + if( !dy || !dx || (!ty && dy<0) || (!tx && dx<0) || (dy==-t) || (ty+dy>=8) || (tx+dx>=8) ) + ; + else if(!game[ty+dy][tx+dx]){ + ret=1; + mvy[ndx]=ty+dy; + mvx[ndx]=tx+dx; + ndx++; + } + else + ndx++; + } + } + return ret; +} +bool can_move(byte side){//would be much faster than applying moves() on every tile + byte y , x ,t, dy , dx; + for(y=0;y<8;y++){ + for(x=0;x<8;x++){ + if( (t=game[y][x])*side > 0 ){ + for(dy=-1;dy<2;dy++){ + for(dx=-1;dx<2;dx++){ + if( !dy || !dx || (!y && dy<0) || (!x && dx<0) || (dy==-t) || (y+dy>=8) || (x+dx>=8) ) + ; + else if( !game[y+dy][x+dx] ) + return 1; + } + } + } + } + } + return 0; + +} +bool jumps(byte ty,byte tx,byte mvy[4],byte mvx[4]){ + bool ret=0; + byte ndx=0; + byte ey,ex; + byte t= game[ty][tx]; + byte dy,dx; + for(dy=-1;dy<2;dy++){ + for(dx=-1;dx<2;dx++){ + ey = dy*2; + ex = dx*2; + if(!dy || !dx ||(dy==-t)|| (ty+ey<0) || (tx+ex<0) || (ty+ey>=8) || (tx+ex>=8) ) + ; + else if(!game[ty+ey][tx+ex] && game[ty+dy][tx+dx]*t<0){ + ret=1; + mvy[ndx]=ty+ey; + mvx[ndx]=tx+ex; + ndx++; + } + else + ndx++; + } + } + return ret; +} +byte can_jump(byte ty,byte tx){ + byte dy,dx,t=game[ty][tx]; + byte ey,ex; + byte ret=0; + for(dy=-1;dy<2;dy++){ + for(dx=-1;dx<2;dx++){ + ey=dy*2; + ex=dx*2; + if((dy==-t)||(ty+ey<0)||(tx+ex<0)||(ty+ey>=8)||(tx+ex>=8) ) + ; + else if(!game[ty+dy*2][tx+dx*2]&&game[ty+dy][tx+dx]*t<0){ + ret++; + if(ret>1) + return ret; + } + + } + } + return ret; +} +byte forced_jump(byte side){ + byte y,x; + byte foo,ret; + foo=ret=0; + for(y=0;y<8;y++){ + for(x=0;x<8;x++){ + if(game[y][x]*side>0 && (foo=can_jump(y,x)) ) + ret+=foo; + if(ret>1) + return ret; + } + } + return ret; +} +byte cmove(byte fy,byte fx,byte sy,byte sx){//really move/jump , move is a curses function + byte a = game[fy][fx]; + byte ret=0; + game[fy][fx]=0; + game[sy][sx]=a; + if(abs(fy-sy) == 2){ + ret =game[(fy+sy)/2][(fx+sx)/2]; + game[(fy+sy)/2][(fx+sx)/2]=0; + } + return ret; +} +bool king(byte y,byte x){ + byte t= (4-y)*game[y][x]; + if( (y==7 || !y) && t<0 && t>-5 ){ + game[y][x]*=2; + return 1; + } + return 0; +} +double advantage(byte side){ + unsigned char own,opp; + own=opp=0; + byte foo; + byte y,x; + for(y=0;y<8;y++){ + for(x=0;x<8;x++){ + foo=game[y][x]*side; + if(foo>0){ + own++;//so it wont sacrfice two pawns for a king ( 2 kings == 3 pawns) + own+=foo; + } + else if(foo<0){ + opp++; + opp-=foo; + } + } + } + if(!own) + return 0; + else if(!opp) + return WIN; + else + return (double)own/opp; +} +double posadvantage(byte side){ + double adv=0; + double oppadv=0; + byte foo; + byte y,x; + byte goal= (side>0)*7 , oppgoal=(side<0)*7; + /*This encourages the AI to king its pawns and concentrate its kings in the center. + The idea is : With forces in the center, movements to all of the board would be in the game tree horizon(given enough depth); + and with forces being focused , its takes less movements to make an attack. */ + for(y=0;y<8;y++){ + for(x=0;x<8;x++){ + foo=game[y][x]*side; + if(foo>0){ + adv+=foo; + adv++; + if(foo==1) + adv+= 1/( abs(y-goal) );//adding positional value + else if(foo==2) + adv+= 1/( fabs(y-3.5)+ fabs(x-3.5) ); + } + else if( foo<0 ){ + oppadv-=foo; + oppadv++; + if(foo==-1) + adv+=1/( abs(y-oppgoal) ); + else if(foo==-2) + adv+= 1/( fabs(y-3.5)+ fabs(x-3.5) ); + } + } + } + if(!adv) + return 0; + else if( !oppadv ) + return WIN; + else + return adv/oppadv; + return adv; +} +double decide(byte side,byte depth,byte s){ + byte fj=forced_jump(side);//only one legal jump if returns 1 + byte nextturn; + + byte mvy[4],mvx[4]; + byte n; + + bool didking; + byte captured; + + double adv=0; + byte toy,tox; + byte y,x; + + double wrstadv=WIN+1; + + double bestadv=0; + byte besttoy,besttox; + byte besty,bestx; + bestx=besty=besttox=besttoy=-100; + bool canmove=0; + + byte nexts ; + if(s == IMAGINARY || s == NORMAL ) + nexts=IMAGINARY; + else + nexts=ALT_IMG; + + for(y=0;y<8;y++){ + for(x=0;x<8;x++){ + if(fj && (s==NORMAL || s==ALT_NRM) && jumpagainy>=0 && (jumpagainy!=y || jumpagainx!=x) ) + continue; + if(game[y][x]*side>0){ + canmove=0; + memset(mvy,-1,4); + memset(mvx,-1,4); + if(fj) + canmove=jumps(y,x,mvy,mvx); + else + canmove=moves(y,x,mvy,mvx); + if(canmove){ + for(n=0;n<4;n++){ + if(mvy[n] != -1){//a real move + toy=mvy[n]; + tox=mvx[n]; + captured=cmove(y,x,toy,tox);//do the imaginary move + if(fj && can_jump(toy,tox) ) //its a double jump + nextturn=side; + else + nextturn=-side; + didking=king(toy,tox); + + //see the advantage you get + if(fj==1 && (s==ALT_NRM || s==NORMAL) ) + adv= DOESNT_MATTER; + else if(!depth){ + if(s==IMAGINARY || s==NORMAL) + adv=advantage(side); + else + adv=posadvantage(side); + } + else{ + if(nextturn==side) + adv=decide(nextturn,depth,nexts); + else{ + adv=decide(nextturn,depth-!fj,nexts); + if(adv==WIN) + adv=0; + else if(adv) + adv=1/adv; + else + adv=WIN; + } + } + //undo the imaginary move + if(didking) + game[toy][tox]/=2; + game[y][x]=game[toy][tox]; + game[toy][tox]=0; + if(fj) + game[(toy+y)/2][(tox+x)/2]=captured; + + if(besty<0 || adv>bestadv || (adv==bestadv && ( random()%2 )) ){ + besty=y; + bestx=x; + besttoy=toy; + besttox=tox; + bestadv=adv; + } + if(adv= 0 ){ + if(endgame && fj!=1 && s==NORMAL && bestadv==wrstadv ){ + if(wrstadv == WIN){//the randomization in the algorithm may cause an illusion of inevitable win + if(depth > 1) + decide(side,depth-1,NORMAL); + else + goto Move; + } + else + decide(side,depth,ALT_NRM); + } + else{ + Move: + cmove(besty,bestx,besttoy,besttox); + kinged=king(besttoy,besttox); + if(!kinged && can_jump(besttoy,besttox) ){ + jumpagainy = besttoy; + jumpagainx = besttox; + } + else + jumpagainy=jumpagainx=-1; + } + } + return bestadv; +} +void sigint_handler(int x){ + endwin(); + puts("Quit."); + exit(x); +} +int main(int argc,char** argv){ + dpt=3; + if(argc>2){ + printf("Usage: %s [AIpower]\n",argv[0]); + return EXIT_FAILURE; + } + if(argc==2){ + if(sscanf(argv[1],"%d",&dpt) && dpt<128 && dpt>0) + ; + else{ + puts("That should be a number from 1 to 127."); + return EXIT_FAILURE; + } + } + initscr(); + noecho(); + cbreak(); + keypad(stdscr,1); + int input ; + printw("Black plays first.\n Choose type of the black player(H/c)\n" ); + input=getch(); + if(input=='c'){ + computer[0]=dpt; + printw("Computer.\n"); + } + else{ + computer[0]=0; + printw("Human.\n"); + } + printw("Choose type of the white player(h/C)\n"); + input=getch(); + if(input=='h'){ + computer[1]=0; + printw("Human.\n"); + } + else{ + computer[1]=dpt; + printw("Computer.\n"); + } + if(has_colors()){ + start_color(); + use_default_colors(); + init_pair(1,COLOR_RED,-1); + } + signal(SIGINT,sigint_handler); + Start: + srandom(time(NULL)%UINT_MAX); + fill(); + cy=cx=-1; + py=px=0; + byte mvy[4],mvx[4]; + memset(mvy,-1,4); + memset(mvx,-1,4); + byte turn=1; + bool t=1; + bool fj; + byte result; + byte todraw=0; + double adv = 1;//used to determine when the game is a draw + double previousadv =1; + Turn: + jumpagainy=jumpagainx=-1; + kinged=0; + turn =-turn; + t=!t;//t == turn<0 that's turn in binary/array index format + fj = forced_jump(turn); + erase(); + flushinp(); + header(); + draw(3,0); + if(t){ + previousadv=adv; + adv= advantage(1) + (score[0]*score[1]);//just taking the dry scores to account too,nothing special + if(previousadv==adv) + todraw++; + else + todraw=0; + } + if(!score[0] || (turn==-1 && !fj && !can_move(-1))){ + result=1; + goto End; + } + else if(!score[1] || (turn==1 && !fj && !can_move(1))){ + result=-1; + goto End; + } + else if(todraw==50){ // 50 turns without any gained advantage for each side + result=0; + goto End; + } + endgame= score[t]<=5 || score[!t]<=5; + draw(3,0); + refresh(); + while(computer[t]){ + mvprintw(13,0,"Thinking..."); + refresh(); + computer[t]=dpt+ (score[!t] != score[t]) + endgame; + decide(turn,computer[t],1); + if(!(fj && jumpagainy>=0 && !kinged )){ + goto Turn; + } + } + while(1){ + erase(); + draw(3,0); + header(); + refresh(); + input=getch(); + if( (input=='k' || input==KEY_UP) && py>0) + py--; + if( (input=='j' || input==KEY_DOWN) && py<7) + py++; + if( (input=='h' || input==KEY_LEFT) && px>0) + px--; + if( (input=='l' || input==KEY_RIGHT) && px<7) + px++; + if( input=='q'){ + result=2; + goto End; + } + if(input=='\n'){ + if(game[py][px]*turn>0){ + cy=py; + cx=px; + memset(mvy,-1,4); + memset(mvx,-1,4); + if(!fj) + moves(py,px,mvy,mvx); + jumps(py,px,mvy,mvx); + } + if( in(mvy,mvx,py,px) && !(jumpagainy>=0 && (cy !=jumpagainy || cx != jumpagainx) ) ){ + memset(mvy,-1,4); + memset(mvx,-1,4); + cmove(cy,cx,py,px); + kinged=king(py,px); + cy=-1; + cx=-1; + if( !(fj && can_jump(py,px) && !kinged ) ){ + goto Turn; + } + else{ + jumpagainy=py; + jumpagainx=px; + } + } + } + } + End: + move(13,0); + switch(result){ + case -1: + printw("The black side has won the game."); + break; + case 0: + printw("Draw."); + break; + case 1: + printw("The white side has won the game."); + break; + case 2: + printw("You resigned."); + } + printw(" Wanna rematch?(y/N)"); + curs_set(1); + input=getch(); + if(input=='y' || input=='Y'){ + byte b=computer[0]; + computer[0]=computer[1]; + computer[1]=b; + goto Start; + } + endwin(); + return EXIT_SUCCESS; +} diff --git a/games/jewels.c b/games/jewels.c new file mode 100644 index 0000000..8152b8a --- /dev/null +++ b/games/jewels.c @@ -0,0 +1,365 @@ +#include +#include +#include +#include +#include +#define LEN 17 +#define WID 19 +#define DELAY 2 +#define SAVE_TO_NUM 10 +#define DEF_ADDRESS "JewelScores" + +/* +Jewels + + +copyright Hossein Bakhtiarifar 2018 (c) +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]; +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(DEF_ADDRESS,"r")) ){ + deforno=1; + } + else{ + deforno=0; + if( !(scorefile = fopen(getenv("JW_SCORES"),"r")) ){ + printf("\nNo accessible score files found.\n"); + 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=itreached || score>=scorebuff[location]) ){ + fprintf(scorefile,"%s : %ld\n",getenv("USER"),score); + ret=location; + wroteit=1; + } + if(location*>*>Top %d<*<*<\n",SAVE_TO_NUM); + while( rank>>"); + 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(void){ + bool ret =0; + chtype c,uc; + byte n; + byte y,x; + for(y=0;y=0;n--) + board[y][x-n]=0; + n=0; + score+=30; + } + } + } + for(x=0;x=0;n--) + board[y-n][x]=0; + n=0; + score+=30; + } + } + } + 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); + for(byte y=0;y= 10){ + falls=fall(); + stop=0; + } + else if(input=='l') + jmove(0,+1); + else if(input=='j') + jmove(0,-1); + else if(input=='k') + 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(); + } + while(explode()){ // explode, fall, explode, fall until nothing is left + 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; +} diff --git a/games/mines.c b/games/mines.c new file mode 100644 index 0000000..51782ae --- /dev/null +++ b/games/mines.c @@ -0,0 +1,266 @@ +#include +#include +#include +#include +#include +#include +/* +|\/| +| |INES + + +copyright Hossein Bakhtiarifar 2018 (c) +No rights are reserved and this software comes with no warranties of any kind to the extent permitted by law. + +compile with -lncurses +*/ +typedef signed char byte; +int len,wid,py,px; +int untouched; +int mscount; +chtype colors[6]={0}; +void rectangle(int sy,int sx){ + for(int y=0;y<=len+1;y++){ + mvaddch(sy+y,sx,ACS_VLINE); + mvaddch(sy+y,sx+wid*2,ACS_VLINE); + } + for(int x=0;x<=wid*2;x++){ + mvaddch(sy,sx+x,ACS_HLINE); + mvaddch(sy+len+1,sx+x,ACS_HLINE); + } + mvaddch(sy,sx,ACS_ULCORNER); + mvaddch(sy+len+1,sx,ACS_LLCORNER); + mvaddch(sy,sx+wid*2,ACS_URCORNER); + mvaddch(sy+len+1,sx+wid*2,ACS_LRCORNER); +} + +void draw(int sy,int sx,byte board[len][wid]){ + rectangle(sy,sx); + chtype attr ; + char prnt; + int y,x; + for(y=0;y9) + prnt='?'; + + mvaddch(sy+1+y,sx+x*2+1,attr|prnt); + } + } +} +void drawmines(int sy,int sx,byte board[len][wid],bool mines[len][wid]){ + int y,x; + for(y=0;y=0 && board[ty][tx] <9) + return 0; + + if(board[ty][tx]<0 || board[ty][tx]>8){//untouched + board[ty][tx]=0; + untouched--; + } + int y,x; + for(y=ty-1;y=len) + break; + for (x=tx-1;x=wid) + break; + + if(mines[y][x]) + board[ty][tx]++; + } + } + + if(!board[ty][tx]){ + for(y=ty-1;y=len) + break; + for(x=tx-1;x=wid) + break; + + click(board,mines,y,x); + } + + } + } + return 0; +} + +void sigint_handler(int x){ + endwin(); + puts("Quit."); + exit(x); +} +int main(int argc, char** argv){ + signal(SIGINT,sigint_handler); + if(argc>4 || (argc==2 && !strcmp("help",argv[1])) ){ + printf("Usage: %s [len wid [minescount]]\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<5 || wid<5 || len>1000 || wid>1000){ + puts("At least one of your given dimensions is too small or too big."); + return EXIT_FAILURE; + } + + } + else + len=wid=8; + if(argc==4){ + if( !sscanf(argv[3],"%d",&mscount)){ + puts("Invalid input."); + return EXIT_FAILURE; + } + if( mscount<5 || mscount>= len*wid){ + puts("Too few/many mines."); + return EXIT_FAILURE; + } + } + else + mscount = len*wid/6; + srandom(time(NULL)%UINT_MAX); + Start: + initscr(); + curs_set(0); + noecho(); + cbreak(); + keypad(stdscr,1); + if(has_colors()){ + start_color(); + use_default_colors(); + init_pair(1,COLOR_BLUE,-1); + init_pair(2,COLOR_GREEN,-1); + init_pair(3,COLOR_YELLOW,-1); + init_pair(4,COLOR_RED,-1); + init_pair(5,COLOR_RED,COLOR_YELLOW); + init_pair(6,COLOR_RED,COLOR_MAGENTA); + for(byte b= 0;b<6;b++){ + colors[b]=COLOR_PAIR(b+1); + } + + } + py=px=0; + untouched=len*wid; + int flags=0; + byte board[len][wid]; + bool mines[len][wid]; + char result[70]; + int input; + + memset(board,-1,len*wid); + memset(mines,false,len*wid); + mine(mines); + + while(1){ + erase(); + mvprintw(1,0,"|\\/| Flags:%d\n",flags); + mvprintw(2,0,"| |INES Mines:%d\n",mscount); + draw(3,0,board); + refresh(); + if(untouched<=mscount){ + strcpy(result,"You won!"); + break; + } + input = getch(); + if( (input=='k' || input==KEY_UP) && py>0) + py--; + if( (input=='j' || input==KEY_DOWN) && py0) + px--; + if( (input=='l' || input==KEY_RIGHT) && px +#include +#include +#include +/* + _ +|_) +| \EVERSI + + +copyright Hossein Bakhtiarifar 2018 (c) +No rights are reserved and this software comes with no warranties of any kind to the extent permitted by law. + +compile with -lncurses +*/ +typedef signed char byte; +byte py,px;//cursor +const char piece[2] = "OX"; +char game[8][8];//main board +byte computer[2] = {0,0}; +byte score[2];//set by header() + +void rectangle(byte sy,byte sx){ + for(byte y=0;y<=8+1;y++){ + mvaddch(sy+y,sx,ACS_VLINE); + mvaddch(sy+y,sx+8*2,ACS_VLINE); + } + for(byte x=0;x<=8*2;x++){ + mvaddch(sy,sx+x,ACS_HLINE); + mvaddch(sy+8+1,sx+x,ACS_HLINE); + } + mvaddch(sy,sx,ACS_ULCORNER); + mvaddch(sy+8+1,sx,ACS_LLCORNER); + mvaddch(sy,sx+8*2,ACS_URCORNER); + mvaddch(sy+8+1,sx+8*2,ACS_LRCORNER); +} + +void header(void){//buse + score[0]=score[1]=0; + for(byte y=0;y<8;y++){ + for(byte x=0;x<8;x++){ + if(game[y][x]){ + if(game[y][x]==piece[0]) + score[0]++; + else + score[1]++; + } + } + } + mvaddch(0,1, '_'); + mvprintw(1,0,"|_) %2d:%2d",score[0],score[1]); + mvprintw(2,0,"| \\EVERSI "); +} + +void draw(byte sy,byte sx){//the game's board + rectangle(sy,sx); + chtype attr ; + for(byte y=0;y<8;y++){ + for(byte x=0;x<8;x++){ + attr=A_NORMAL; + if(y==py && x==px) + attr |= A_STANDOUT; + if(game[y][x]) + mvaddch(sy+1+y,sx+x*2+1,attr|game[y][x]); + else + mvaddch(sy+1+y,sx+x*2+1,attr|'.'); + } + } +} + +bool can_reverse(byte ty , byte tx,char board[8][8],char piece){//can do a move there? + byte y,x,count; + if(board[ty][tx]) + return false; + for(byte dy=-1;dy<2;dy++){ //changes the direction + for(byte dx=-1;dx<2;dx++){ + if(dx==0&&dy==0)//infinite + dx=1; + count=0; + y=ty+dy; + x=tx+dx; + while(1){ + if(y<0 || y>=8 ||x<0 || x>=8){//reaches edges of the board + count=0; + break; + } + if(!board[y][x]){//gap + count=0; + break; + } + + if(board[y][x]!=piece){ + count++; + y+=dy; + x+=dx; + } + else + break;//same color + } + if(count) + return true; + } + } + return false; +} + +void reverse(byte ty,byte tx,char board[8][8],char piece){ + board[ty][tx]=piece; + byte y,x; + for(byte dy=-1;dy<2;dy++){//changes the direction + for(byte dx=-1;dx<2;dx++){ + if(dy==0 && dx==0) + dx=1; + y=ty+dy; + x=tx+dx; + while(1){ + if(y<0 || y>=8 || x<0 || x>=8) + break; + if(!board[y][x]) + break; + if(board[y][x]!=piece){ + y+=dy; + x+=dx; + } + else{ //of same kind + while(y!=ty || x!=tx){ //reverse the disks + board[y][x]=piece; + y-=dy; + x-=dx; + } + break; + } + } + } + } +} + +bool can_move(char board[8][8],char piece){//can move at all? + for(byte y=0;y<8;y++) + for(byte x=0;x<8;x++) + if(can_reverse(y,x,board,piece)) + return true; + return false; +} + +double advantage(char board[8][8],char piece){ + double own=0; + double opp=0; + for(byte y=0;y<8;y++){ + for(byte x=0;x<8;x++){ + if(board[y][x]){ + if(board[y][x]==piece){ + own++; + if( ((y==7 || y==0)&&(x!=7 && x!=0)) || ((x==7 || x==0)&&(y!=7 && y!=0)) )//edges + own+=100; + if( (y==7 || y==0)&&(x==7 || x==0) )//corners + own+=10000; + } + else{ + opp++; + if( ((y==7 || y==0)&&(x!=7 && x!=0)) || ((x==7 || x==0)&&(y!=7 && y!=0)) ) + opp+=100; + if( (y==7 || y==0)&&(x==7 || x==0) ) + opp+=10000; + } + } + + } + } + return own/opp; +} + +void cp(char A[8][8],char B[8][8]){ + for(byte y=0;y<8;y++) + for(byte x=0;x<8;x++) + B[y][x]=A[y][x]; +} + +double decide(char board[8][8],char piece,char opponet,byte depth){//AI algorithm + if(!can_move(board,piece)) + return 0; + char plan[8][8]; + double adv,bestadv; + adv=bestadv=0; + byte besty,bestx; + for(byte y=0;y<8;y++){ + for(byte x=0;x<8;x++){ + if(can_reverse(y,x,board,piece) ){ + cp(board,plan);//backtrack + reverse(y,x,plan,piece); + if(depth){ + adv= decide(plan,opponet,piece,depth-1);//least benefit for the opponet + if(adv) //the opponet can make a move + adv = 1/adv; + else + adv=advantage(plan,piece); + } + else + adv=advantage(plan,piece); + if(adv>bestadv){ + bestadv=adv; + besty=y; + bestx=x; + } + } + } + } + reverse(besty,bestx,board,piece);//do the move + return bestadv; +} + +void sigint_handler(int x){ + endwin(); + puts("Quit."); + exit(x); +} + +int main(int argc , char** argv){ + int depth=3; + if(argc>2){ + printf("Usage:%s [AIpower]",argv[0]); + return EXIT_FAILURE; + } + if(argc==2){ + if(sscanf(argv[1],"%d",&depth) && depth<128 && 0=2) + goto End; + + turn = !turn; + if(computer[turn]){ + if(can_move(game,piece[turn])){ + mvprintw(13,0,"Thinking..."); + refresh(); + decide(game,piece[turn],piece[!turn],computer[turn]); + cantmove=0; + } + else + cantmove++; + goto Turn; + + } + + if(!can_move(game,piece[turn])){ + cantmove++; + goto Turn; + } + else{ + cantmove=0; + while(1){ //human control + erase(); + header(); + draw(3,0); + input=getch(); + if( (input=='k' || input==KEY_UP) && py>0) + py--; + if( (input=='j' || input==KEY_DOWN) && py<7) + py++; + if( (input=='h' || input==KEY_LEFT) && px>0) + px--; + if( (input=='l' || input==KEY_RIGHT) && px<7) + px++; + if( input=='q') + sigint_handler(0); + if(input=='\n'){ + if(can_reverse(py,px,game,piece[turn])){ + reverse(py,px,game,piece[turn]); + goto Turn; + } + + } + + } + } + End: + if(score[0]==score[1]) + mvprintw(13,0,"Draw!!"); + else if(score[0] > score[1]) + mvprintw(13,0,"'%c' won.",piece[0]); + else + mvprintw(13,0,"'%c' won.",piece[1]); + + printw(" Wanna play again?(y/N)"); + curs_set(1); + input=getch(); + + if(input == 'Y' || input == 'y') + goto Start; + endwin(); + return EXIT_SUCCESS; +} diff --git a/games/sudoku.c b/games/sudoku.c new file mode 100644 index 0000000..b052be1 --- /dev/null +++ b/games/sudoku.c @@ -0,0 +1,287 @@ +#include +#include +#include +#include //to seed random +#include +#include +/* + _ +(_ + _)UDOKU + + +copyright Hossein Bakhtiarifar 2018 (c) +No rights are reserved and this software comes with no warranties of any kind to the extent permitted by law. + +compile with -lncurses +*/ +typedef unsigned char byte; +byte size,s,ds;//s=size*size +byte py,px; +byte diff; +unsigned int filled; +chtype colors[6]={0}; +void cross(byte sy,byte sx,chtype start,chtype middle,chtype end){ //to simplify drawing tables + mvaddch(sy,sx,start); + byte f = 2*size; + for(char n=1;ns) + return 1; + for(byte y=0;y3 || (argc==2 && !strcmp("help",argv[1])) ){ + printf("Usage: %s [size [ diff]]\n",argv[0]); + return EXIT_FAILURE; + } + + if(argc>1 ){ + if(strlen(argv[1])>1 || argv[1][0]-'0'>7 || argv[1][0]-'0'< 2){ + printf("2 <= size <= 7\n"); + return EXIT_FAILURE; + } + else + size = *argv[1]-'0'; + } + else + size=3; + if(argc>2){ + if (strlen(argv[2])>1 || argv[2][0]-'0'>4 || argv[2][0]-'0'<= 0 ){ + printf("1 <= diff <=4\n"); + return EXIT_FAILURE; + } + else + diff = *argv[2]-'0'+1; + } + else + diff=2; + + + + Start: + initscr(); + noecho(); + cbreak(); + keypad(stdscr,1); + curs_set(0); + srandom(time(NULL)%UINT_MAX); + if( has_colors() ){ + start_color(); + use_default_colors(); + init_pair(1,COLOR_YELLOW,-1); + init_pair(2,COLOR_GREEN,-1); + init_pair(3,COLOR_BLUE,-1); + init_pair(4,COLOR_CYAN,-1); + init_pair(5,COLOR_MAGENTA,-1); + init_pair(6,COLOR_RED,-1); + for(byte b=0;b<6;b++){ + colors[b]=COLOR_PAIR(b+1); + } + } + filled =0; + s=size*size; + ds=s+size; + char board[s][s]; + char empty[s][s]; + char game[s][s]; + memset(board,0,s*s); + memset(empty,0,s*s); + memset(game,0,s*s); + int input=0 ; + fill(board); + mkpuzzle(board,empty,game); + py=px=0; + + while(1){ + erase(); + draw(3,0,empty,game); + header(0,0); + refresh(); + if(filled == s*s) + break; + input = getch(); + if(input == KEY_UP && py) + py--; + if(input == KEY_DOWN && py{Ew6(Ir3f}&e?mPJ*@Sv zcdxb1Ik|nC%f#_B#{&Q+x_-53Cje$R08GKyF|dYxnxe()Py8$TCcxF{bJ2=7H4ezQ$5aFLTi@GlJ{uc?08pe_D54 z)jYa7F<|ghI2r&8RTwhXc$c&G-eLeeuH*+x7XeV?i#!3~{FSE}aveL4hFrjB0aKC7 zoOy+#kn8bkbr!rlTj9}+VfZdfpM7u?sF{NFwLbs-c;M_2W_%k={sd?GBxm?3s38

5IUalw7f;bE13j9yGqfuCwt$q zv7ly0A-{~FzsSdFO+ZcxOIqyU&-8My47b<@fY%X8K`Wj|OPFf`a-5zzR)t*2r%byn z7w4VEBJFN1erwUE3S51db!OnuE~|hjza_UB30J3|opv4o#Y;bD4?c@=+!FwFpqgBW z_TK%)>1`&{0Cn0Dex4*MFTo$ ztWStqSg9(7i$4Jc97^~F2Ur6%hY1wnF1LkdAjjOB9&Xcb4yd~LiM4O!hid4QMcLD% zvd3m!Ukqy2&5oKK^Gs?1IuBlAVBB zHf)7s75O+eSk#a$p5jr*_sooN&n~S*r4PWx1$IQ}hWeD=gq|jyDR{FkTo@RoWAsTb zRr32sEpadbgFl`htW@evKx=9e-UKwJ`Hjl8-D(0-=#S|jma?UoJ0QI>U;{OJ zmld{^pERFq5p#5Ti;Kh?N(kSNqS?(?=T|BsVvWfISNzW+?5R`Ic8LI7#EN5Ls(bG|7XP*2HkO z{;|`|i>GP7=8% zpg@ipZ-KTX0f6!;xTK#p_B`|(vYdjktnbEbHF=$;e3VcKaiu4YSjOK?A$2m*L`WAE zW&Lac`W|RT1FF-76D>!SLs23bn-(9}aMTf68^}2l`h5I8>u}2RCxg686#oX54zYLZ z8ht>Nby8RCQcE{_a(MEPy8EzjIc%ue&}V}Siu9?Rrq3c1MBah=_;np>3)s?Fp{wov za$ee|JYF5EZde;pCY=teJLjk@Axpq=bqeGHSl&ycdw%+p`7<#dyYenql^J+-H@q?| zf#N1pu543Tg2wd$X|2|K+(o@r3mHs%tXkMUxSJq1p`w^atI-`0Qz_1#^DizdZJwOr z_9u;37R{^URVF|(xL^z}t(s$FAa&+eaX@LG zfb@8X;Gcp4H8v0IO7Ob9B+b9pYr5-W`ir@B6+W-1ko|KWD6e!n^YP>@h--_n?N1o}ka~p7?NFbeH z5JRFi_t+IQ#AZW*Oc@KIli3jWAc*n1=bh3ccZ>sX^ZZRN#A$Y-mkSy=$og`E?kz4R zo%5}1T~p1Fff{Wr#-Kt|02MnKck(Ir*wXl!g|hf$b8419b;)# z^L!7?67pj}XFNOGSnC}6f%T?AGpf?ba%FNH!B7{z76quaUW_sHNhY97<_ICP!iTYU z9@~$?3i4O?>XU^BjWC#O%b8kZExB!%wO(@%)*gkmNoyz7?u!}=ijo-tGZHQ?-`cDY zSUK}oVxJS-H2P|t+`0KTh}f>Ge@4GvAhHB+k`OAb`Ke;(RIrbXtj_v*+yi*&KrF0t z^!+`68aj?vb>PYuB1=aUh~2G?<7@Rv8+^<_Ym+Jf+m3RDYP zsH}z{D8q|SwMdlFBI2tXH5btnd4tt;rp~D$+0s~nA$D`viAkVnB5PFV{GRK=_f0|! zoEU>C-4rdwH*pHbXtk)uZ#d~faG~Kdl@F2?KFAORf<$7HUIgvq-k@RQFNxNsA z=~8|Ps_a%^iWB6&mJ^V;6gKv(kW3<+JzwFS%- z=$7`lSn(k8@|#4Fe{to6p!riic=go1-ng_w!HFU7=&a@fTIw!(EBJB`CbSv;m{_T3WJPM)S9C$Uh$95ugYd;HL_({g}?!41-BjbP2 zntLN4N=LmJWO)Y8*8z1!(S?U2jLkuGzw}V36R`}s8kzqxO2+hA=Qle9#&aROe-JoZ zczIi9h8h3}5{)eBGkoDdfbKrs)aNIteAuw_=!0H+fxdN+|L(j2(R7>1-N$wSP_G!V z-tJ=!gQ3hdMw!kjukVFcdxFCX8!ki6CxG>6et8XcH&@zCsO7#jJI%3dm7!=oT8X%; zb;Mi?lybf!hbJB?$W8DE;MQAPXdBeef0+wvWQfyTR6KMFx(X@o(CMa*M+`R53P*C) z*o^x<_?W6;I$Q+G3ewi;zNQE7@#aa^vu&WqWMnkU{R`vgeD@BEH%SRT(vnxg9g^WN z9aQRbqnIQDs~G>vhekRyf{eiBsG&HwXCUi>W#etn7q#V@VSq0}a8`5qf^V@y3Ja64 zIzbT9&k@UR@m@8rhiZiCUh8B@6WLGT6Q;Q`_`?1+KD*N3hv@lN7_Ql#klM0ti?6Lt z5L;;w{Ju%>#wfEB!B+(2QLi0vC-H`MqwKUQuBpe!sjx`Qh+n4%fO5gV*r>Cb6%$4{ zc$=y ztoS`rcNj&Btg1Y!AxnCO38`3R!Z5+s5zX&fyCtPoes_feje?_59pI7t_08Uu zy~eRxv@*t0NA!~!6=yEE%!Zf+&aTz8%@xiV5EpJwDy!&!IVG)mtOsBXY2~M6xH<+UvunqGIe^Dw{m< zWXIHXS+EgwSm9D%$Ld}zz9c2!Vksr9zdgp}r&&m!7MYAL0K#qI!YF)`w zMmUoK!&;?dVFUK!@`>B)!fDJQMT5+Q8V2K24(hR|h966$HP;N6zn(VJ{+j%Fuo4`UGv6YAm^UZR$mwfL+x>7v~5Umj` z4`c9`MuF{a(1Yor5KGrUA|Cc$j|Rkf(z=!*i8!=hP~FUjVN-gM+hLNS2=$&wRlOwQ zY<#nBiL}`3%WOpy43ZW=Mm3mTQ)KOb59GM^5_9*Z7|v9C<3W`A`Rfu6&DdN0&IT2U zI>r2Wiq6qGLp_~(Q5l!zRo6o2B$2zy_Klq%F$WjmZv{K$#ZtVC3UJ;*Gogig?V?f3tej$8W_6-Sv<3%|lgR8p!e`I!)W#nCjT)D4kC2hsF5$(S6>k(GFLo~Dxx>})HehLx}mEVyuctmGatCr_AX`JK4YC&k0^nxQD=MNcKkTvy1pz<>Py1-UTQrSJhaFn*v9w9m0riagoBv8-u%W#_L=i01I zUdW&+FMFoaBxhqJ)tS=!buQY9Xl5^cC@w<(D2>Ldn|H2QC9_H7*nAZwt)}HgR!94I zl_w(>2@ZF^%f%e|!W%td0*q-3e*oZ6+ko2BDFe?KZ46M_KPwz?-iq8(t3%(8VsFfu#IV?f++L|0r!JfsfLLGWhU=*++Z+NJAeDmD*|OwNkM2U~ZjIL8Z5qDxD+yp}p_`=v4R;HA-X4~WjD zTLzf^`Rl*??cpC%-2XdeHF_`V&b_env9iM4m{lOgrVA~l^yIt?%*HDz#?PgLCe{Aq zJH6V^DVkb&v(`6V5uX!M6ple{NWQWL8*vN8>fk=}j;*hF>!d7G1g+nn^{>GLDfpPo zaa?h`9WM3EWxlC+eF-nam;vpuR{A${L+scw(J$f(t-Wa_dGa%L3&dj0=c#ko`=ygS zb(x*G4wBdMKCDG*N4D%{Hrq6NV z6WOcF)OFn3W_RxhH4N}*uzxP1&B#X~wL3NO`F26GJ8=$JLRP;#O;k0%K#;ps`O00r zD^+^+hoEq28_7=`pq%2>bwojukiz4>l%CUi_&Xybs3givKUVOG$2+FaROWgos7H`6ZS2lx?=V@GS1u266jSn%@Ja#`9C5ZA*`1E@ufcF%hHmNc4=p z-`i2*>#p3OJ{s%e`697iuv2nQFBUB~Us;QDVyrW*+2 zQOc4Dyuzl83&N0RZRc+@b?qTR?kNk{(}LrxxtdE^Ng6^+nKXcjvX3~hy~+jt_5!nn zhNuIR;}5c8Rr;Y`td%ZSUZ5~@cx$G7V*Fwu>^XQt5srNIgvA{dEjQj#Z8rY)g}~VI ezw*ki`A?p9Lz?>K{IkeduA8@Qy1jAVxBmvP3Qy+% literal 0 HcmV?d00001