// get rid of gotos // add reasons // add game solts #include #define FULL &(SCR_RECT){{0,0,159,99}} #define VERSION 0 typedef struct { char name[9]; char password[9]; unsigned char flags; // 0 0 0 0 0 0 gameInProgress passwordProtected unsigned int solved[4]; unsigned int hints; unsigned int resigns; unsigned long time[4]; } user; INT_HANDLER oldint5=NULL; volatile unsigned long tick; DEFINE_INT_HANDLER (myint5handler) { tick++; ExecuteHandler(oldint5); } char fname[18],message[11],name[9],why[70]; enum filetype {SOLVE,GAME,SUDOPUZZ}; enum keys {Eenter=13,Eback=257,Eclear=263,Eescape,Eapps,Emode,Ef1=268,Ef2,Ef3,Ef4,Ef5,Ef6,Ef7,Ef8,Ehome=277,Ecatalog,Eup=337,Eleft,Eleftup,Edown,Eupdown,Eleftdown,Eleftupdown,Eright,Eupright,Eleftright,Eleftupright,Erightdown,Euprightdown,Eleftdownright,Euprightleftdown,E2nddimondalpha,Edimondalpha=380,E2nddimondshiftalpha=384,E2ndescape=4360,E2ndup=4433,E2ndleft,E2ndleftup,E2nddown,E2ndupdown,E2ndleftdown,E2ndrightupdown,E2ndright,E2ndupright,E2ndleftright,E2ndleftupright,E2ndrightdown,E2nduprightdown,E2ndleftdownright,E2nduprightleftdown,Edimondenter=16397,Edimondback=16641,Edimondclear=16647,Edimondescape,Edimondapps,Edimondmode,Edimondup=16721,Edimondleft,Edimondleftup,Edimonddown,Edimondupdown,Edimondleftdown,Edimondrightupdown,Edimondright,Edimondupright,Edimondleftright,Edimondleftupright,Edimondrightdown,Edimonduprightdown,Edimondleftdownright,Edimonduprightleftdown}; unsigned char ask(),check(),cnob,explain,grid[9][9],layer,level,loadGame(),loadUser(),locked[9][9],logical(unsigned char ll),marks[9][9][9],nob,ol[9][9][10],saveGame(); unsigned long time; user u1; void disp(),displl(),dispss(),*ds,fillol(unsigned char ll),findFile(),help(),load(),loadll(),*ls,play(),mygetsn(char *str,unsigned char n,unsigned char flags,unsigned char height),put(unsigned char x,unsigned char y,unsigned char num),reset(unsigned char all),save(),savell(),saveUser(),solve(),solver(),tellmewhy(),userSettings(); void _main(void) { /* sprintf(u1.name,"CoolGuy"); u1.flags=0; u1.solved[0]=7; u1.solved[1]=3; u1.solved[2]=3; u1.solved[3]=1; u1.hints=12; u1.resigns=0; u1.time[0]=(unsigned long)4284*19; u1.time[1]=(unsigned long)2526*19; u1.time[2]=(unsigned long)3798*19; u1.time[3]=(unsigned long)1987*19; saveUser(); return; */ int k; if (!GrayOn()) return; tick=0; oldint5=GetIntVec(AUTO_INT_5); SetIntVec(AUTO_INT_5,myint5handler); if (!(ds=malloc(LCD_SIZE))) goto end; if (!(ls=malloc(LCD_SIZE))) goto end; randomize(); u1.name[0]=0; while (1) { GraySetAMSPlane(LIGHT_PLANE); clrscr(); if (u1.name[0]) printf("Welcome %s!\n",u1.name); printf("F1 - Solver\nF2 - Play Sudoku!\nF3 - "); if (u1.name[0]) printf("Log out"); else printf("Load user"); printf("\nF4 - New user\nF5 - User settings"); GraySetAMSPlane(DARK_PLANE); clrscr(); if (u1.name[0]) printf("Welcome %s!\n",u1.name); printf("F1 - Solver\nF2 - Play Sudoku!\nF3 - "); if (u1.name[0]) printf("Log out"); else printf("Load user"); printf("\nF4 - New user\nF5 - User settings"); do k=ngetchx();while ((kEf5)&&k!=Eescape); if (k==Ef1) solver(); else if (k==Ef2) play(); else if (k==Ef3) { if (u1.name[0]) u1.name[0]=0; else { GraySetAMSPlane(LIGHT_PLANE); clrscr(); printf("Who are you?"); GraySetAMSPlane(DARK_PLANE); clrscr(); printf("Who are you?"); mygetsn(u1.name,9,0b0000,10); if (loadUser()) u1.name[0]=0; } } else if (k==Ef4) { u1.name[0]=0; loadUser(); } else if (k==Ef5) { if (u1.name[0]) userSettings(); } else if (k==Eescape) break; } end:; SetIntVec(AUTO_INT_5,oldint5); GrayOff(); if (ds) free(ds); if (ls) free(ls); } unsigned char ask() { int k; GraySetAMSPlane(LIGHT_PLANE); DrawStr(1,92,"Yes",A_NORMAL); DrawStr(144,92,"No",A_NORMAL); GraySetAMSPlane(DARK_PLANE); DrawStr(1,92,"Yes",A_NORMAL); DrawStr(144,92,"No",A_NORMAL); do k=ngetchx();while (k!=Ef1&&k!=Ef5); return (k==Ef1); } unsigned char check() { unsigned char a,b,c,d,e,f,fin; fin=0; for (a=1;a<=9;a++) { for (b=0;b<9;b++) { d=0; e=0; for (c=0;c<9;c++) { if (grid[b][c]==a) d++; if (grid[c][b]==a) e++; } if (d==0||e==0) fin=1; if (d>1||e>1) return 2; } } for (a=1;a<=9;a++) { for (b=0;b<9;b+=3) { for (c=0;c<9;c+=3) { f=0; for (d=0;d<3;d++) { for (e=0;e<3;e++) { if (grid[b+d][c+e]==a) f++; } } if (f==0) fin=1; if (f>1) return 2; } } } return fin; } unsigned char loadGame() { /* 0 - Everything's fine 1 - File not found 2 - Un supported version 3 - Unknown/corrupted/wrong filetype 4 - Wrong user */ FILE *f1; unsigned char a,b,c; sprintf(fname,"userpuz"); findFile(); if (!fname[0]) return 0; EM_moveSymFromExtMem(SYMSTR(fname),HS_NULL); f1=fopen(fname,"rb"); if (!f1) return 1; if (fgetc(f1)!=VERSION) return 2; a=fgetc(f1); b=0; switch (a) { case SOLVE: for (a=0;a<9;a++) { for (b=0;b<9;b++) { for (c=0;c<9;c++) marks[a][b][c]=0; grid[a][b]=fgetc(f1); locked[a][b]=fgetc(f1); } } break; case GAME: do { name[b]=fgetc(f1); b++; } while (name[b-1]); if (strcmp(name,u1.name)) return 4; for (a=0;a<9;a++) { for (b=0;b<9;b++) { for (c=0;c<9;c++) marks[a][b][c]=fgetc(f1); grid[a][b]=fgetc(f1); locked[a][b]=fgetc(f1); } } fread(&time,sizeof(long),1,f1); level=fgetc(f1); break; default:return 3;break; } fclose(f1); remove(fname); sprintf(message,"Loaded"); return 0; } unsigned char loadUser() { char tmp[9]; FILE *f1; if (!u1.name[0]) { GraySetAMSPlane(LIGHT_PLANE); clrscr(); printf("What's your name?\n"); GraySetAMSPlane(DARK_PLANE); clrscr(); printf("What's your name?\n"); mygetsn(u1.name,9,0b000,10); GraySetAMSPlane(LIGHT_PLANE); clrscr(); printf("Do you want your account\nto be password protected?"); GraySetAMSPlane(DARK_PLANE); clrscr(); printf("Do you want your account\nto be password protected?"); if (ask()) { u1.flags=1; GraySetAMSPlane(LIGHT_PLANE); clrscr(); printf("Password"); GraySetAMSPlane(DARK_PLANE); clrscr(); printf("Password"); mygetsn(u1.password,9,0b1111,10); } else { u1.flags=0; u1.password[0]=0; } u1.solved[0]=0; u1.solved[1]=0; u1.solved[2]=0; u1.solved[3]=0; u1.time[0]=0; u1.time[1]=0; u1.time[2]=0; u1.time[3]=0; u1.hints=0; u1.resigns=0; saveUser(); return 0; } sprintf(fname,"%s",u1.name); findFile(); if (fname[0]) EM_moveSymFromExtMem(SYMSTR(fname),HS_NULL); f1=fopen(fname,"rb"); if (!f1) return 1; if (fgetc(f1)!=VERSION) return 2; fread(&u1,sizeof(user),1,f1); fclose(f1); EM_moveSymToExtMem(SYMSTR(fname),HS_NULL); if (u1.flags&1) { GraySetAMSPlane(LIGHT_PLANE); clrscr(); printf("Tell me your password!"); GraySetAMSPlane(DARK_PLANE); clrscr(); printf("Tell me your password!"); mygetsn(tmp,9,0b1111,10); if (strcmp(tmp,u1.password)) return 3; } return 0; } unsigned char logical(unsigned char ll) { unsigned char a,b,c,changed,d,e,f; changed=0; why[0]=0; if (!ll) { GraySetAMSPlane(LIGHT_PLANE); DrawStr(103,6,"Progress",A_NORMAL); DrawClipRect(&(WIN_RECT){96,17,157,21},FULL,A_NORMAL); GraySetAMSPlane(DARK_PLANE); DrawStr(103,6,"Progress",A_NORMAL); DrawClipRect(&(WIN_RECT){96,17,157,21},FULL,A_NORMAL); } cnob=0; top:; if (why[0]) { if (ll||!explain) why[0]=0; else tellmewhy(); } cnob++; if (!ll) ScrRectFill(&(SCR_RECT){{97,18,97+((58*cnob)/nob),20}},FULL,A_NORMAL); fillol((ll!=0)); for (a=0;a<9;a++) { for (b=0;b<9;b++) { d=0; e=0; for (c=0;c<9;c++) { if (ol[a][c][b]==0) d++; if (ol[c][a][b]==0) e++; } if (d==1) { for (c=0;c<9;c++) { if (ol[a][c][b]==0) { sprintf(why,"Cell r%dc%d is a %dbecause it's theonly cell in therow it will fit",a+1,c+1,b+1); grid[a][c]=b+1; if (ll==1) locked[a][c]=1; changed=1; put(c,a,b+49); if (ll==2) { nob=a; cnob=c; return 1; } goto top; } } } if (e==1) { for (c=0;c<9;c++) { if (ol[c][a][b]==0) { sprintf(why,"Cell r%dc%d is a %dbecause it's theonly cell in thecolumn it will\nfit",c+1,a+1,b+1); grid[c][a]=b+1; if (ll==1) locked[c][a]=1; changed=1; put(a,c,b+49); if (ll==2) { nob=c; cnob=a; return 1; } goto top; } } } if (grid[a][b]) continue; if (ol[a][b][9]==8) { for (c=0;c<9;c++) { if (!ol[a][b][c]) { sprintf(why,"Cell r%dc%d is a %dbecause it's theonly number thatfits in the cell",a+1,b+1,c+1); grid[a][b]=c+1; if (ll==1) locked[a][b]=1; changed=1; put(b,a,c+49); if (ll==2) { nob=a; cnob=b; return 1; } goto top; } } } } } for (a=0;a<9;a+=3) { for (b=0;b<9;b+=3) { for (c=0;c<9;c++) { f=0; for (d=0;d<3;d++) { for (e=0;e<3;e++) { if (!ol[a+d][b+e][c]) f++; } } if (f==1) { for (d=0;d<3;d++) { for (e=0;e<3;e++) { if (!ol[a+d][b+e][c]) { sprintf(why,"Cell r%dc%d is a %dbecause it's theonly cell in thebox it will fit",a+d+1,b+e+1,c+1); grid[a+d][b+e]=c+1; if (ll==1) locked[a+d][b+e]=1; changed=1; if (ll==2) { nob=a+d; cnob=b+e; return 1; } put(b+e,a+d,c+49); goto top; } } } } } } } return changed; } unsigned char saveGame() { FILE *f1; unsigned char a,b,c; sprintf(fname,"userpuz"); findFile(); if (fname[0]) { GraySetAMSPlane(LIGHT_PLANE); clrscr(); printf("Another file already\nexists, do you want to\noverwrite it?"); GraySetAMSPlane(DARK_PLANE); clrscr(); printf("Another file already\nexists, do you want to\noverwrite it?"); if (!ask()) return 1; EM_moveSymFromExtMem(SYMSTR(fname),HS_NULL); } else sprintf(fname,"userpuz"); f1=fopen(fname,"wb"); if (!f1) return 1; fputc(VERSION,f1); fputc(GAME,f1); a=0; do { fputc(u1.name[a],f1); a++; } while (u1.name[a-1]); for (a=0;a<9;a++) { for (b=0;b<9;b++) { for (c=0;c<9;c++) fputc(marks[a][b][c],f1); fputc(grid[a][b],f1); fputc(locked[a][b],f1); } } fwrite(&time,sizeof(long),1,f1); fputc(level,f1); fputc(0,f1); fputc('S',f1); fputc('d',f1); fputc('k',f1); fputc('u',f1); fputc(0,f1); fputc(OTH_TAG,f1); fclose(f1); EM_moveSymToExtMem(SYMSTR(fname),HS_NULL); return 0; } void disp() { unsigned char a,b; PortSet(ds,239,127); clrscr(); for (a=2;a<=92;a+=10) { ScrRectFill(&(SCR_RECT){{a,2,a,92}},FULL,A_NORMAL); ScrRectFill(&(SCR_RECT){{2,a,92,a}},FULL,A_NORMAL); } for (a=0;a<9;a++) { for (b=0;b<9;b++) { if (grid[a][b]) DrawChar(b*10+4,a*10+4,grid[a][b]+48,A_NORMAL); } } PortSet(ls,239,127); clrscr(); ScrRectFill(&(SCR_RECT){{2,2,92,92}},FULL,A_NORMAL); for (a=2;a<=92;a+=10) { ScrRectFill(&(SCR_RECT){{a,2,a,92}},FULL,A_REVERSE); ScrRectFill(&(SCR_RECT){{2,a,92,a}},FULL,A_REVERSE); } for (a=2;a<=92;a+=30) { ScrRectFill(&(SCR_RECT){{a,2,a,92}},FULL,A_NORMAL); ScrRectFill(&(SCR_RECT){{2,a,92,a}},FULL,A_NORMAL); } for (a=0;a<9;a++) { for (b=0;b<9;b++) { if (grid[a][b]&&!(locked[a][b]&1)) DrawChar(b*10+4,a*10+4,grid[a][b]+48,A_REVERSE); } } memcpy(GrayGetPlane(DARK_PLANE),ds,LCD_SIZE); memcpy(GrayGetPlane(LIGHT_PLANE),ls,LCD_SIZE); } void displl() { unsigned char a,b; for (a=0;a<9;a++) { for (b=0;b<9;b++) put(b,a,grid[a][b]+48); } } void dispss() { unsigned char a; GraySetAMSPlane(LIGHT_PLANE); ScrRectFill(&(SCR_RECT){{95,26,158,89}},FULL,A_NORMAL); DrawLine(116,27,116,88,A_REVERSE); DrawLine(137,27,137,88,A_REVERSE); DrawLine(96,47,157,47,A_REVERSE); DrawLine(96,68,157,68,A_REVERSE); GraySetAMSPlane(DARK_PLANE); for (a=0;a<4;a++) { DrawLine(95+21*a,26,95+21*a,89,A_NORMAL); DrawLine(95,26+21*a,158,26+21*a,A_NORMAL); } } void fillol(unsigned char ll) { unsigned char a,b,c,d,e,f; if (ll) { for (a=0;a<9;a++) { for (b=0;b<9;b++) { for (c=0;c<10;c++) ol[a][b][c]=0; } } } for (a=0;a<9;a++) { for (b=0;b<9;b++) { if (grid[a][b]&&(ll||!(locked[a][b]&2))) { ol[a][b][9]=9; locked[a][b]|=2; for (c=0;c<9;c++) ol[a][b][c]=1; for (c=0;c<9;c++) { if (!ol[a][c][grid[a][b]-1]) { ol[a][c][grid[a][b]-1]=1; ol[a][c][9]++; } if (!ol[c][b][grid[a][b]-1]) { ol[c][b][grid[a][b]-1]=1; ol[c][b][9]++; } } if (a<3) e=0; else if (a<6) e=3; else e=6; if (b<3) f=0; else if (b<6) f=3; else f=6; for (c=e;c='A'&&fname[a]<='Z') fname[a]+=32; a++; } SYM_ENTRY *SymPtr; SymPtr=SymFindFirst(NULL,FO_RECURSE); while (SymPtr) { if (SymPtr->flags.bits.folder) sprintf(folder,"%s",SymPtr->name); else { if (!strcmp(SymPtr->name,fname)) { sprintf(fname,"%s\\%s",folder,SymPtr->name); return; } } SymPtr=SymFindNext(); } fname[0]=0; } void help() { } void load() { FILE *f1; unsigned char a,b; sprintf(fname,"puz"); findFile(); if (fname[0]) EM_moveSymFromExtMem(SYMSTR(fname),HS_NULL); f1=fopen(fname,"rb"); if (!f1) return; if (fgetc(f1)!=VERSION) return; a=fgetc(f1); switch (a) { case SOLVE: for (a=0;a<9;a++) { for (b=0;b<9;b++) { grid[a][b]=fgetc(f1); locked[a][b]=fgetc(f1); } } break; case GAME: for (a=0;a<9;a++) { for (b=0;b<9;b++) { fseek(f1,9,SEEK_CUR); grid[a][b]=fgetc(f1); locked[a][b]=fgetc(f1); } } break; default:return;break; } fclose(f1); sprintf(message,"Loaded"); } void loadll() { char name[9]; FILE *f1; unsigned char a,b; sprintf(name,"sudoll%d",layer); f1=fopen(name,"rb"); if (!f1) { printf_xy(96,56,"Error loading"); return; } for (a=0;a<9;a++) { for (b=0;b<9;b++) { grid[a][b]=fgetc(f1); locked[a][b]=fgetc(f1); } } fclose(f1); remove(name); } void mygetsn(char *str,unsigned char n,unsigned char flags,unsigned char height) { /* flags bit 0 - hide chars bit 1 - include numbers bit 2 - include special chars bit 3 - include spaces */ int k; unsigned char a; a=0; do { str[a]=0; if (a'9') { if (!(flags&1)) k=0; } else if (k==32) { if (!(flags&8)) k=0; } else if (!((k>='a'&&k<='z')||(k>='A'&&k<='Z')||k==Eback)) { if (!(flags&4)) k=0; } if (k) { if (k==Eback) { if (a>0) { GraySetAMSPlane(LIGHT_PLANE); DrawChar(a*FontCharWidth(0),height,32,A_REPLACE); GraySetAMSPlane(DARK_PLANE); DrawChar(a*FontCharWidth(0),height,32,A_REPLACE); a--; GraySetAMSPlane(LIGHT_PLANE); DrawChar(a*FontCharWidth(0),height,32,A_REPLACE); GraySetAMSPlane(DARK_PLANE); DrawChar(a*FontCharWidth(0),height,32,A_REPLACE); } } else { if (a=Ef1&&k<=Ef4)||(k==Ef5&&level==1)||k==Eescape)); if (k==Eescape) return; else if (k==Ef5) { fclose(f1); a=loadGame(); if (a) { GraySetAMSPlane(LIGHT_PLANE); clrscr(); switch (a) { case 1:printf("I can't find a game");break; case 2:printf("This version is too new");break; case 3:printf("I can't load this file");break; case 4: if (name[0])printf("You need to be logged in\nas %s to resume this\ngame",name); else printf("You can't be logged in to resume this game"); break; } GraySetAMSPlane(DARK_PLANE); clrscr(); switch (a) { case 1:printf("I can't find a game");break; case 2:printf("This version is too new");break; case 3:printf("I can't load this file");break; case 4: if (name[0])printf("You need to be logged in\nas %s to resume this\ngame",name); else printf("You can't be logged in to resume this game"); break; } ngetchx(); goto top; } } else { if (u1.name[0]&&u1.flags&2) { GraySetAMSPlane(LIGHT_PLANE); clrscr(); printf("You have a game in\nprogress. Are you sure youwant to quit that game andstart a new one?"); GraySetAMSPlane(DARK_PLANE); clrscr(); printf("You have a game in\nprogress. Are you sure youwant to quit that game andstart a new one?"); if (ask()) { u1.resigns++; u1.flags&=0b11111101; } else goto top; } level=k-Ef1; fseek(f1,(81*5)*(level)+81*(rand()%5),SEEK_CUR); c=rand()%4; for (a=0;a<9;a++) { for (b=0;b<9;b++) { switch (c) { case 0:grid[a][b]=fgetc(f1)-48;break; case 1:grid[b][8-a]=fgetc(f1)-48;break; case 2:grid[8-a][8-b]=fgetc(f1)-48;break; case 3:grid[8-b][a]=fgetc(f1)-48;break; } } temp[9][a]=0; } c=rand()%4; for (a=0;a<9;a++) { for (b=0;b<9;b++) { switch (c) { case 0:temp[a][b]=grid[a][b];break; case 1:temp[a][b]=grid[8-a][b];break; case 2:temp[a][b]=grid[a][8-b];break; case 3:temp[a][b]=grid[8-a][8-b];break; } } do d=rand()%9;while (temp[9][d]); temp[9][d]=a; } for (a=0;a<9;a++) { for (b=0;b<9;b++) { if (temp[a][b]) { grid[a][b]=temp[9][temp[a][b]-1]+1; locked[a][b]=1; temp[a][b]=1; } else { grid[a][b]=0; locked[a][b]=0; } } } fclose(f1); for (a=0;a<9;a++) { for (b=0;b<9;b++) { for (c=0;c<9;c++) marks[a][b][c]=0; } } } a=0; b=0; csc=1; csr=0; disp(); tick=time; quit=0; while (1) { for (c=0;c<9;c++) { for (d=0;d<9;d++) { GraySetAMSPlane(LIGHT_PLANE); ScrRectFill(&(SCR_RECT){{d*10+4,c*10+4,d*10+10,c*10+10}},FULL,A_NORMAL); if (grid[c][d]&&(!(locked[c][d]&1))) DrawChar(4+10*d,4+10*c,grid[c][d]+48,A_REVERSE); GraySetAMSPlane(DARK_PLANE); if (!grid[c][d]) DrawChar(4+10*d,4+10*c,' ',A_REPLACE); else DrawChar(4+10*d,4+10*c,grid[c][d]+48,A_REPLACE); } } if (!message[0]) { if (level==0&&check()==2) sprintf(message,"Oops"); } GraySetAMSPlane(LIGHT_PLANE); DrawStr(96,6," ",A_REPLACE); DrawStr(96,6,message,A_NORMAL); FontSetSys(F_4x6); DrawStr(1,94,"Hint",A_NORMAL); DrawStr(35,94,"Solve",A_NORMAL); DrawStr(74,94,"New",A_NORMAL); DrawStr(96,94,"Save/Quit",A_NORMAL); DrawStr(142,94,"Help",A_NORMAL); FontSetSys(F_6x8); GraySetAMSPlane(DARK_PLANE); DrawStr(96,6," ",A_REPLACE); DrawStr(96,6,message,A_NORMAL); FontSetSys(F_4x6); DrawStr(1,94,"Hint",A_NORMAL); DrawStr(35,94,"Solve",A_NORMAL); DrawStr(74,94,"New",A_NORMAL); DrawStr(96,94,"Save/Quit",A_NORMAL); DrawStr(142,94,"Help",A_NORMAL); message[0]=0; FontSetSys(F_6x8); dispss(); if (!check()) break; k=0; do { if (a<3*csr||a>3*csr+2||b<3*csc||b>3*csc+2) { if (a<3) csr=0; else if (a<6) csr=1; else csr=2; if (b<3) csc=0; else if (b<6) csc=1; else csc=2; for (c=0;c<3;c++) { for (d=0;d<3;d++) { ScrRectFill(&(SCR_RECT){{96+21*d,27+21*c,115+21*d,46+21*c}},FULL,A_REVERSE); GraySetAMSPlane(LIGHT_PLANE); ScrRectFill(&(SCR_RECT){{96+21*d,27+21*c,115+21*d,46+21*c}},FULL,A_NORMAL); GraySetAMSPlane(DARK_PLANE); if (grid[csr*3+c][csc*3+d]) { FontSetSys(F_8x10); DrawChar(102+21*d,32+21*c,grid[csr*3+c][csc*3+d]+48,A_NORMAL); if (!(locked[csr*3+c][csc*3+d]&1)) { GraySetAMSPlane(LIGHT_PLANE); DrawChar(102+21*d,32+21*c,grid[csr*3+c][csc*3+d]+48,A_REVERSE); GraySetAMSPlane(DARK_PLANE); } FontSetSys(F_6x8); } else { FontSetSys(F_4x6); for (e=0;e<3;e++) { for (f=0;f<3;f++) { if (marks[3*csr+c][3*csc+d][e*3+f]) { DrawChar(97+21*d+6*f,28+21*c+6*e,e*3+f+49,A_NORMAL); } } } FontSetSys(F_6x8); } } } } DrawClipRect(&(WIN_RECT){96+21*(b%3),27+21*(a%3),115+21*(b%3),46+21*(a%3)},FULL,A_NORMAL); DrawClipRect(&(WIN_RECT){b*10+3,a*10+3,b*10+11,a*10+11},FULL,A_NORMAL); k=ngetchx(); DrawClipRect(&(WIN_RECT){b*10+3,a*10+3,b*10+11,a*10+11},FULL,A_REVERSE); DrawClipRect(&(WIN_RECT){96+21*(b%3),27+21*(a%3),115+21*(b%3),46+21*(a%3)},FULL,A_REVERSE); switch (k) { case Eright: case Edimondright: k=Eright; if (b==8) b=0; else b++; break; case Eleft: case Edimondleft: k=Eleft; if (b==0) b=8; else b--; break; case Eup: case Edimondup: k=Eup; if (a==0) a=8; else a--; break; case Edown: case Edimonddown: k=Edown; if (a==8) a=0; else a++; break; case Eclear: case Eback:k='0'; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (!(locked[a][b]&1)) grid[a][b]=k-48; csc++; break; case 16433: case 16434: case 16435: case 16436: case 16437: case 16438: case 16439: case 16440: case 16441: marks[a][b][k-16433]=!marks[a][b][k-16433]; csc++; break; case Ef1: if(logical(2)) { if (why[0]&&explain) tellmewhy(); a=nob; b=cnob; u1.hints++; } csc=3; break; case Ef2: quit=1; explain=0; for (c=0;c<9;c++) { for (d=0;d<9;d++) grid[c][d]*=(locked[c][d]&1); } solve(); for (c=0;c<9;c++) { for (d=0;d<9;d++) locked[c][d]=temp[c][d]; } disp(); if (u1.name[0]&&check()==0) u1.resigns++; csc=3; break; case Ef3:goto top;break; case Ef4: if (!saveGame()) { if (u1.name[0]) u1.flags|=2; k=Eescape; } else { disp(); } break; case Ef5:help();break; case Eescape: GraySetAMSPlane(LIGHT_PLANE); clrscr(); printf("Do you want to save this\ngame?"); GraySetAMSPlane(DARK_PLANE); clrscr(); printf("Do you want to save this\ngame?"); if (ask()) { if (saveGame()) { k=0; disp(); } else u1.flags|=2; } else { if (u1.name[0]) u1.resigns++; } } } while (k==Eleft||k==Eright||k==Eup||k==Edown); if (k==Eescape||quit) break; } if (check()) return; time+=tick; disp(); dispss(); if (!quit) { DrawStr(96,6,"You Win! ",A_REPLACE); GraySetAMSPlane(LIGHT_PLANE); DrawStr(96,6,"You Win! ",A_REPLACE); GraySetAMSPlane(LIGHT_PLANE); ngetchx(); GraySetAMSPlane(LIGHT_PLANE); clrscr(); printf("You Win!\nYou solved the puzzle in\n%lu seconds",time/19); GraySetAMSPlane(DARK_PLANE); clrscr(); printf("You Win!\nYou solved the puzzle in\n%lu seconds",time/19); if (u1.name[0]) { u1.flags&=0b11111101; u1.solved[level]++; u1.time[level]+=time; } } ngetchx(); } void put(unsigned char x,unsigned char y,unsigned char num) { if (num==48) DrawChar(4+10*x,4+10*y,' ',A_REPLACE); else DrawChar(4+10*x,4+10*y,num,A_REPLACE); } void reset(unsigned char all) { unsigned char a,b; for (a=0;a<9;a++) { for (b=0;b<9;b++) { if (all||!locked[a][b]) grid[a][b]=0; if (all) locked[a][b]=1; } } } void save() { FILE *f1; unsigned char a,b; f1=fopen("puz","wb"); if (!f1) return; fputc(VERSION,f1); fputc(SOLVE,f1); for (a=0;a<9;a++) { for (b=0;b<9;b++) { fputc(grid[a][b],f1); fputc(locked[a][b],f1); } } fputc(0,f1); fputc('S',f1); fputc('d',f1); fputc('k',f1); fputc('u',f1); fputc(0,f1); fputc(OTH_TAG,f1); fclose(f1); EM_moveSymToExtMem(SYMSTR(fname),HS_NULL); sprintf(message,"Saved"); } void savell() { char name[9]; FILE *f1; unsigned char a,b; sprintf(name,"sudoll%d",layer); f1=fopen(name,"wb"); if (!f1) { printf_xy(96,56,"Error saving"); return; } for (a=0;a<9;a++) { for (b=0;b<9;b++) { fputc(grid[a][b],f1); fputc(locked[a][b],f1); } } fclose(f1); } void saveUser() { FILE *f1; sprintf(fname,"%s",u1.name); findFile(); if (!fname[0]) sprintf(fname,"%s",u1.name); else EM_moveSymFromExtMem(SYMSTR(fname),HS_NULL); f1=fopen(fname,"wb"); fputc(VERSION,f1); fwrite(&u1,sizeof(user),1,f1); fputc(0,f1); fputc('U',f1); fputc('s',f1); fputc('e',f1); fputc('r',f1); fputc(0,f1); fputc(OTH_TAG,f1); fclose(f1); EM_moveSymToExtMem(SYMSTR(fname),HS_NULL); } void solve() { char name[9]; unsigned char a,b,c,changed[9][9],plock[9][9]; disp(); nob=0; for (a=0;a<9;a++) { for (b=0;b<9;b++) { if (grid[a][b]) { plock[a][b]=1; locked[a][b]=1; } else { plock[a][b]=0; locked[a][b]=0; nob++; } for (c=0;c<10;c++) ol[a][b][c]=0; changed[a][b]=0; } } if (!nob) return; sprintf(message,"Done"); logical(0); if (cnob8) { b=0; a++; if (a>8) goto end; } } top:; c=grid[a][b]; grid[a][b]=0; fillol(1); grid[a][b]=c; do { if (changed[a][b]) { changed[a][b]=0; layer--; loadll(); displl(); goto top; } grid[a][b]++; put(b,a,grid[a][b]+48); if (grid[a][b]>9) { grid[a][b]=0; put(b,a,48); do { if (b==0) { b=8; if (a==0) { sprintf(message,"Insolvable"); goto end; } else a--; } else b--; } while (locked[a][b]&1); goto top; } } while (ol[a][b][grid[a][b]-1]); savell(); changed[a][b]=logical(1); if (changed[a][b]) layer++; } } end:; for (a=0;a<9;a++) { for (b=0;b<9;b++) locked[a][b]=plock[a][b]; } for (a=0;a<=layer;a++) { sprintf(name,"sudoll%d",a); remove(name); } } void solver() { unsigned char a,b; int k; reset(1); a=0; b=0; explain=0; disp(); message[0]=0; while (1) { displl(); GraySetAMSPlane(LIGHT_PLANE); DrawStr(96,6," ",A_REPLACE); DrawStr(96,6,message,A_NORMAL); DrawStr(96,16,"F1 - Solve",A_NORMAL); DrawStr(96,26,"F2 - Clear",A_NORMAL); DrawStr(96,36,"F3 - Reset",A_NORMAL); DrawStr(96,46,"F4 - Save",A_NORMAL); DrawStr(96,56,"F5 - Load",A_NORMAL); FontSetSys(F_4x6); if (explain) DrawStr(0,94,"Explanation on, press Mode to toggle ",A_REPLACE); else DrawStr(0,94,"Explanation off, press Mode to toggle",A_REPLACE); FontSetSys(F_6x8); GraySetAMSPlane(DARK_PLANE); DrawStr(96,6," ",A_REPLACE); DrawStr(96,6,message,A_NORMAL); DrawStr(96,16,"F1 - Solve",A_NORMAL); DrawStr(96,26,"F2 - Clear",A_NORMAL); DrawStr(96,36,"F3 - Reset",A_NORMAL); DrawStr(96,46,"F4 - Save",A_NORMAL); DrawStr(96,56,"F5 - Load",A_NORMAL); FontSetSys(F_4x6); if (explain) DrawStr(0,94,"Explanation on, press Mode to toggle ",A_REPLACE); else DrawStr(0,94,"Explanation off, press Mode to toggle",A_REPLACE); FontSetSys(F_6x8); message[0]=0; DrawClipRect(&(WIN_RECT){b*10+3,a*10+3,b*10+11,a*10+11},FULL,A_NORMAL); k=ngetchx(); DrawClipRect(&(WIN_RECT){b*10+3,a*10+3,b*10+11,a*10+11},FULL,A_REVERSE); switch (k) { case Eright: if (b==8) b=0; else b++; break; case Eleft: if (b==0) b=8; else b--; break; case Eup: if (a==0) a=8; else a--; break; case Edown: if (a==8) a=0; else a++; break; case Eback:k='0'; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': GraySetAMSPlane(LIGHT_PLANE); ScrRectFill(&(SCR_RECT){{4+b*10,4+a*10,10+b*10,10+a*10}},FULL,A_NORMAL); GraySetAMSPlane(DARK_PLANE); ScrRectFill(&(SCR_RECT){{4+b*10,4+a*10,10+b*10,10+a*10}},FULL,A_REVERSE); grid[a][b]=k-48; break; case Ef1:solve();disp();break; case Ef2:reset(1);disp();break; case Ef3:reset(0);disp();break; case Ef4:save();break; case Ef5:load();disp();break; case Emode:explain=!explain;break; } if (k==Eescape) break; } } void tellmewhy() { char scr[2][BitmapSize(&(SCR_RECT){{30,28,129,71}})]; unsigned char a,c,r; GraySetAMSPlane(LIGHT_PLANE); BitmapGet(&(SCR_RECT){{30,28,129,71}},scr[0]); ScrRectFill(&(SCR_RECT){{30,28,129,71}},FULL,A_NORMAL); GraySetAMSPlane(DARK_PLANE); BitmapGet(&(SCR_RECT){{30,28,129,71}},scr[1]); ScrRectFill(&(SCR_RECT){{30,28,129,71}},FULL,A_NORMAL); ScrRectFill(&(SCR_RECT){{31,29,128,70}},FULL,A_REVERSE); a=0; c=0; r=0; while (1) { if (why[a]==0) break; else if (why[a]=='\n') { r++; c=0; a++; } else { DrawChar(32+c*6,30+8*r,why[a],A_NORMAL); c++; if (c>15) { c=0; r++; } a++; } } ngetchx(); GraySetAMSPlane(LIGHT_PLANE); BitmapPut(30,28,scr[0],FULL,A_REPLACE); GraySetAMSPlane(DARK_PLANE); BitmapPut(30,28,scr[1],FULL,A_REPLACE); why[0]=0; } void userSettings() { int k; while (1) { GraySetAMSPlane(LIGHT_PLANE); clrscr(); printf("F1 - Password\n\nF3 - User Stats\nF4 - Reset Stats\nF5 - Delete User"); if (u1.flags&1) DrawStr(84,0,"On",A_NORMAL); else DrawStr(84,0,"Off",A_NORMAL); DrawStr(0,8,"F2 - Change Password",1+2*!(u1.flags&1)); GraySetAMSPlane(DARK_PLANE); clrscr(); printf("F1 - Password\n\nF3 - User Stats\nF4 - Reset Stats\nF5 - Delete User"); if (u1.flags&1) DrawStr(84,0,"On",A_NORMAL); else DrawStr(84,0,"Off",A_NORMAL); DrawStr(0,8,"F2 - Change Password",1+2*!(u1.flags&1)); do k=ngetchx();while (k!=Eescape&&(kEf5)); switch (k) { case Eescape:return;break; case Ef1: if (u1.flags&1) { u1.flags--; break; } u1.flags++; case Ef2: if (!(u1.flags&1)) break; GraySetAMSPlane(LIGHT_PLANE); clrscr(); printf("New password"); GraySetAMSPlane(DARK_PLANE); clrscr(); printf("New password"); mygetsn(u1.password,9,0b1111,10); break; case Ef3: GraySetAMSPlane(LIGHT_PLANE); clrscr(); printf("Stats for %s\n",u1.name); FontSetSys(F_4x6); printf("\n%u total puzzles solved\n\n",u1.solved[0]+u1.solved[1]+u1.solved[2]+u1.solved[3]); if (u1.solved[0]) printf("%u beginner, %lu second average\n",u1.solved[0],u1.time[0]/u1.solved[0]/19); else printf("No beginner solves\n"); if (u1.solved[1]) printf("%u novice, %lu second average\n",u1.solved[1],u1.time[1]/u1.solved[1]/19); else printf("No novice solves\n"); if (u1.solved[2]) printf("%u intermediate, %lu second average\n",u1.solved[2],u1.time[2]/u1.solved[2]/19); else printf("No intermediate solves\n"); if (u1.solved[3]) printf("%u intermediate, %lu second average",u1.solved[3],u1.time[3]/u1.solved[3]/19); else printf("No intermediate solves"); printf("\n\n%lu seconds total solve time\n%u hints used\n%u abandoned puzzles",(u1.time[0]+u1.time[1]+u1.time[2]+u1.time[3])/19,u1.hints,u1.resigns); FontSetSys(F_6x8); GraySetAMSPlane(DARK_PLANE); clrscr(); printf("Stats for %s\n",u1.name); FontSetSys(F_4x6); printf("\n%u total puzzles solved\n\n",u1.solved[0]+u1.solved[1]+u1.solved[2]+u1.solved[3]); if (u1.solved[0]) printf("%u beginner, %lu second average\n",u1.solved[0],u1.time[0]/u1.solved[0]/19); else printf("No beginner solves\n"); if (u1.solved[1]) printf("%u novice, %lu second average\n",u1.solved[1],u1.time[1]/u1.solved[1]/19); else printf("No novice solves\n"); if (u1.solved[2]) printf("%u intermediate, %lu second average\n",u1.solved[2],u1.time[2]/u1.solved[2]/19); else printf("No intermediate solves\n"); if (u1.solved[3]) printf("%u intermediate, %lu second average",u1.solved[3],u1.time[3]/u1.solved[3]/19); else printf("No intermediate solves"); printf("\n\n%lu seconds total solve time\n%u hints used\n%u abandoned puzzles",(u1.time[0]+u1.time[1]+u1.time[2]+u1.time[3])/19,u1.hints,u1.resigns); FontSetSys(F_6x8); ngetchx(); break; case Ef4: GraySetAMSPlane(LIGHT_PLANE); clrscr(); printf("Are you sure you want to\npermanently delete all\nstats for this user?"); GraySetAMSPlane(DARK_PLANE); clrscr(); printf("Are you sure you want to\npermanently delete all\nstats for this user?"); if (ask()) { u1.solved[0]=0; u1.solved[1]=0; u1.solved[2]=0; u1.solved[3]=0; u1.hints=0; u1.resigns=0; u1.time[0]=0; u1.time[1]=0; u1.time[2]=0; u1.time[3]=0; } break; case Ef5: GraySetAMSPlane(LIGHT_PLANE); clrscr(); printf("Are you sure you want to\npermanently delete this\nuser?"); GraySetAMSPlane(DARK_PLANE); clrscr(); printf("Are you sure you want to\npermanently delete this\nuser?"); if (ask()) { remove(u1.name); u1.name[0]=0; return; } break; } saveUser(); } }