/* mines.c by Michael Thorpe and Graham Hughes 2011-04-11 */ #include #include #include #include #include #include #define USAGE "usage: mines [-dfh] [-ms <#>]\n" #define MAX_GUESSES 100 #define SLEEP_LEN 2500 #define GUESS_LEN 1000000 #define CHAR_THINK '+' #define CHAR_NOLONG '_' #define CHAR_BLANK ' ' #define CHAR_FLAG 'F' unsigned short board_width=80,board_height=24; typedef void (*atexitfunc)(void); int togo; int minestogo; int nummines=-1; int dolongscan=1; int slow_mode=0; /* Pauses SLEEP_LEN usec after each automatic guess */ int demomode=0; /* Guesses and sleeps GUESS_LEN usec over and over*/ int numshortscans=0,numlongscans=0; char **board,**imagined; int shortscan(); int longscan(); int clickat(int y,int x); void flagat(int y,int x); int shortscan() { int x,y,flags,blanks; int doagain=0; numshortscans++; for(y=0;y= '0' && imagined[y][x] <= '9') { flags=imagined[y][x]-'0'; blanks=0; if(y>0) { if(x>0 && CHAR_FLAG==imagined[y-1][x-1]) flags--; if(CHAR_FLAG==imagined[y-1][x]) flags--; if(x0 && CHAR_FLAG==imagined[y][x-1]) flags--; if(x0 && CHAR_FLAG==imagined[y+1][x-1]) flags--; if(CHAR_FLAG==imagined[y+1][x]) flags--; if(x0) { if(x>0 && CHAR_BLANK==imagined[y-1][x-1]) blanks++; if(CHAR_BLANK==imagined[y-1][x]) blanks++; if(x0 && CHAR_BLANK==imagined[y][x-1]) blanks++; if(x0 && CHAR_BLANK==imagined[y+1][x-1]) blanks++; if(CHAR_BLANK==imagined[y+1][x]) blanks++; if(x0) { if(x>0 && CHAR_BLANK==imagined[y-1][x-1]) clickat(y-1,x-1), doagain=1; if(CHAR_BLANK==imagined[y-1][x]) clickat(y-1,x), doagain=1; if(x0 && CHAR_BLANK==imagined[y][x-1]) clickat(y,x-1), doagain=1; if(x0 && CHAR_BLANK==imagined[y+1][x-1]) clickat(y+1,x-1), doagain=1; if(CHAR_BLANK==imagined[y+1][x]) clickat(y+1,x), doagain=1; if(x0) { if(x>0 && CHAR_BLANK==imagined[y-1][x-1]) flagat(y-1,x-1), doagain=1; if(CHAR_BLANK==imagined[y-1][x]) flagat(y-1,x), doagain=1; if(x0 && CHAR_BLANK==imagined[y][x-1]) flagat(y,x-1), doagain=1; if(x0 && CHAR_BLANK==imagined[y+1][x-1]) flagat(y+1,x-1), doagain=1; if(CHAR_BLANK==imagined[y+1][x]) flagat(y+1,x), doagain=1; if(xmin,a->max); for(i=0;in;i++) fprintf(f,",(%d,%d)",a->x[i],a->y[i]); fprintf(f,"}"); } ls *newls(int min,int max) { ls *new; if(0==(new=(ls *)malloc(sizeof(ls)))) return(0); new->next=0; new->prev=last; if(base) { last->next=new; last=new; } else base=last=new; new->min=min; new->max=max; new->n=0; numalloced++; return(new); } void rmls(ls *a) { if(a==0) return; if(a->prev) a->prev->next=a->next; if(a->next) a->next->prev=a->prev; if(a==base) base=a->next; if(a==last) last=a->prev; numalloced--; free(a); } int lsintsize(ls *a,ls *b) { int i,j,k=0; for(i=0;in;i++) for(j=0;jn;j++) if(a->x[i]==b->x[j] && a->y[i]==b->y[j]) k++; #ifdef DEBUG if(k) { fprintf(debug,"lsintsize("); fputls(debug,a); fprintf(debug,","); fputls(debug,b); fprintf(debug,")=%d\n",k); } #endif return(k); } ls *lssub(ls *a,ls *b) { int i,j; ls *t; t=newls(a->min-b->max,a->max-b->min); for(i=j=0;in;i++) { if(jn && a->x[i]==b->x[j] && a->y[i]==b->y[j]) j++; else t->x[t->n]=a->x[i],t->y[t->n++]=a->y[i]; } #ifdef DEBUG if(j != b->n) { fprintf(debug,"Whathefuck? lssub(%p,%p) {j=%d}\na=",a,b,j,b->n); fputls(debug,a); fprintf(debug,"\nb="); fputls(debug,b); fprintf(debug,"\nt="); fputls(debug,t); fprintf(debug,"\n"); } fprintf(debug,"lssub("); fputls(debug,a); fprintf(debug,","); fputls(debug,b); fprintf(debug,")="); fputls(debug,t); fprintf(debug,"\n"); #endif return(t); } int longscan() { int i,j,x,y,res=0; ls *a,*b,*c,*d; numlongscans++; base=last=0; for(y=0;y0) { if(x>0 && CHAR_BLANK==imagined[y-1][x-1]) j++; if(CHAR_BLANK==imagined[y-1][x]) j++; if(x0 && CHAR_BLANK==imagined[y][x-1]) j++; if(x0 && CHAR_BLANK==imagined[y+1][x-1]) j++; if(CHAR_BLANK==imagined[y+1][x]) j++; if(x0) { if(x>0 && CHAR_FLAG==imagined[y-1][x-1]) i--; if(CHAR_FLAG==imagined[y-1][x]) i--; if(x0 && CHAR_FLAG==imagined[y][x-1]) i--; if(x0 && CHAR_FLAG==imagined[y+1][x-1]) i--; if(CHAR_FLAG==imagined[y+1][x]) i--; if(x=j) { fprintf(debug,"Whatthefuck?!?!? Why is i=%d,j=%d at (%d,%d)?\n",i,j,x,y); fprintf(debug,"board=\""); for(j=y-1;j=0&&j>=0&&i=0&&j>=0&&i0) { if(x>0 && CHAR_BLANK==imagined[y-1][x-1]) a->x[a->n]=x-1,a->y[a->n++]=y-1; if(CHAR_BLANK==imagined[y-1][x]) a->x[a->n]=x,a->y[a->n++]=y-1; if(xx[a->n]=x+1,a->y[a->n++]=y-1; } if(x>0 && CHAR_BLANK==imagined[y][x-1]) a->x[a->n]=x-1,a->y[a->n++]=y; if(xx[a->n]=x+1,a->y[a->n++]=y; if(y0 && CHAR_BLANK==imagined[y+1][x-1]) a->x[a->n]=x-1,a->y[a->n++]=y+1; if(CHAR_BLANK==imagined[y+1][x]) a->x[a->n]=x,a->y[a->n++]=y+1; if(xx[a->n]=x+1,a->y[a->n++]=y+1; } #ifdef DEBUG fprintf(debug,"Created ");fputls(debug,a);fprintf(debug,"\n"); #endif } } for(a=base;a != last;a=a->next) { c=last; for(b=a->next;b != c->next;b=b->next) { if(a->n==0 || b->n==0) continue; if(a->n==b->n) continue; i=lsintsize(a,b); if(i==a->n && in) d=lssub(b,a); else if(i==b->n && in) d=lssub(a,b); else continue; if(d->max==0) { for(i=0;in;i++) if(imagined[d->y[i]][d->x[i]]==CHAR_BLANK) { clickat(d->y[i],d->x[i]); res++; } rmls(d); } else if(d->min==d->n) { for(i=0;in;i++) if(imagined[d->y[i]][d->x[i]]==CHAR_BLANK) { flagat(d->y[i],d->x[i]); res++; } rmls(d); } } } cleanup: if(base) { for(a=(b=base)->next;a;a=(b=a)->next) { free(b); numalloced--; } free(b); numalloced--; } return(res); } int clickat(int y,int x) { int i,j; #ifdef DEBUG fprintf(debug,"clickat(%d,%d)\n",y,x); #endif if(board[y][x]=='*') { imagined[y][x]='X'; for(i=0;i0) { if(x>0 && '*'==board[y-1][x-1]) i++; if('*'==board[y-1][x]) i++; if(x0 && '*'==board[y][x-1]) i++; if(x0 && '*'==board[y+1][x-1]) i++; if('*'==board[y+1][x]) i++; if(x'9') { if(imagined[y][x] == CHAR_FLAG) { imagined[y][x] = CHAR_BLANK; togo++; minestogo++; } else { imagined[y][x] = CHAR_FLAG; togo--; minestogo--; } mvaddch(y,x,imagined[y][x]); } } void ponder(int y,int x) { move(board_height,0); printw("%c",CHAR_THINK); move(y,x); refresh(); while(0 set number of mines in play\n" " -r <#> set initial random seed\n" " -s slow down automatic guesses\n" ,stdout); exit(0); break; case 'l': dolongscan=0; break; case 'm': nummines=strtoul(optarg,&s,10); if(*s) goto badargs; break; case 'r': srand(strtoul(optarg,&s,10)); if(*s) goto badargs; break; case 's': slow_mode=1; break; default: fprintf(stderr,"Error: getopt returned '%c'\n",c); return(1); break; } } if(optind0) x--; break; case 'j': case 'B': if(y0) y--; break; case 'l': case 'C': if(x