;- Norm's Sodoku Project IncludeFile "sodokudlg.pbi" IncludeFile "sodokumath.pbi" IncludeFile "sodokuhlp.pbi" IncludeFile "Helper.pbi" SetHelpFile("sodoku.htm","Waffle's Sodoku Help") Open_Window_Sodoku() Macro SetState(ID,State) SendMessage_(GadgetID(ID),#BM_SETSTATE,state,0) EndMacro Macro GetState(ID) SendMessage_(GadgetID(ID),#BM_GETSTATE,0,0) EndMacro ;- Game Vars Global IsDirty.l=0 Global TextColor.l=Color(0) SetGadgetColor(#Text_0, #PB_Gadget_FrontColor, TextColor) SetState(#BImage_0,1) Global TextNumber.l=1 SetGadgetState(#BNum_0,1) Global DefColor.l=GetGadgetColor(#BString_0,#PB_Gadget_BackColor) CreateMode.l=0 Global Marking.l=0 ;for multiple undos .... Structure Move GID.l VS.s EndStructure Global NewList Undo.Move() ;- LoadPreferences InitSound() OpenPreferences(RunPath+"WSodoku.ini") Sound_Mode=Val(ReadPreferenceString("Sound",Str(#Sound_Default))) If Sound_Mode=#Sound_On Sound_Mode=#Sound_Default EndIf Sound_Custom=ReadPreferenceString("Custom","*.wav") Select Sound_Mode Case #Sound_Off SetMenuItemState(#Menubar_0,#Sound_Off,1) SetMenuItemState(#Menubar_0,#Sound_On,0) Case #Sound_Custom SetMenuItemState(#Menubar_0,#Sound_Off,0) SetMenuItemState(#Menubar_0,#Sound_On,1) If Sound_Custom<>"*.wav" If LoadSound(0,Sound_Custom)=0 MessageRequester("Waffle's Sodoku","Unable to load sound"+Chr(10)+Sound_Custom,#MB_ICONSTOP) Sound_Mode=#Sound_Default SetMenuItemState(#Menubar_0,#Sound_Default,1) SetMenuItemState(#Menubar_0,#Sound_Custom,0) Else SetMenuItemState(#Menubar_0,#Sound_Default,0) SetMenuItemState(#Menubar_0,#Sound_Custom,1) EndIf Else Sound_Mode=#Sound_Default SetMenuItemState(#Menubar_0,#Sound_Default,1) SetMenuItemState(#Menubar_0,#Sound_Custom,0) EndIf Case #Sound_Default SetMenuItemState(#Menubar_0,#Sound_Off,0) SetMenuItemState(#Menubar_0,#Sound_On,1) SetMenuItemState(#Menubar_0,#Sound_Default,1) SetMenuItemState(#Menubar_0,#Sound_Custom,0) EndSelect ;delay to let windows initialize Repeat Delay(10) event=WindowEvent() Until event=0 Width.l=Val(ReadPreferenceString("Width","0")) Height.l=Val(ReadPreferenceString("Height","0")) ;Debug "Resizing to "+Str(Width)+","+Str(Height) If Width ResizeWindow(#Window_Sodoku,#PB_Ignore,#PB_Ignore,width,height) ResizeGame(Width,Height) EndIf ClosePreferences() Procedure SaveString(Key.s,S.s) ;this wraps preferences for easy use OpenPreferences(RunPath+"WSodoku.ini") WritePreferenceString(Key,S) ;Debug "Saving "+Key+","+S ClosePreferences() EndProcedure Procedure.l CheckMove(gid,v) xy=gid-#BString_0 y=Int(xy)/9 x=xy-(9*y) For c2=0 To 8 g=((9*y)+c2)+#BString_0 If g<>gid If Val(GetGadgetText(G))=v ProcedureReturn #False EndIf EndIf g=((9*c2)+x)+#BString_0 If g<>gid If Val(GetGadgetText(G))=v ProcedureReturn #False EndIf EndIf Next c2 ;check if box is free of value gx=Int(x/3) gy=Int(y/3) bx=gx*3 by=gy*3 ex=bx+2 ey=by+2 ;Debug "Box Test X="+Str(bx)+Str(ex)+" Y="+Str(by)+Str(ey) For tx=bx To ex For ty=by To ey g=((9*ty)+tx)+#BString_0 If g<>gid If Val(GetGadgetText(G))=v ProcedureReturn #False EndIf EndIf Next ty Next tx ProcedureReturn #True EndProcedure Procedure ClearGadgets() ;clear string gadgets For SG=#BString_0 To #BString_80 SetGadgetText(SG,"") SetGadgetColor(SG,#PB_Gadget_BackColor,DefColor) SetGadgetData(SG,0) Next SG ;reset buttons For BG=#BSide_0 To #BSide_8 SetGadgetState(BG,0) Next bg For BG=#BTOP_0 To #BTop_8 SetGadgetState(BG,0) Next BG ;and erase undos ClearList(Undo()) EndProcedure Procedure ShowGrid() ;Copy Grid data to Srting Gadgets SG=#BString_0 For Y=0 To 8 For X=0 To 8 If Grid(x,y)\Value SetGadgetText(SG,Str(Grid(x,y)\Value)) If Grid(x,y)\flag SetGadgetColor(SG, #PB_Gadget_FrontColor, 0) SetGadgetData(SG,0-Grid(x,y)\Value) Else If Grid(x,y)\Color SetGadgetColor(SG, #PB_Gadget_FrontColor, Grid(x,y)\Color) EndIf EndIf EndIf SG + 1 Next x Next y EndProcedure Procedure CopyGrid(flag.l) ;copy String Gadgets to Grid SG=#BString_0 For Y=0 To 8 For X=0 To 8 Grid(x,y)\Value=Val(GetGadgetText(SG)) If Grid(x,y)\Value If flag Grid(x,y)\Flag=1 Grid(x,y)\Color=0 If Grid(x,y)\flag SetGadgetColor(SG, #PB_Gadget_FrontColor, 0) SetGadgetData(SG,0-Grid(x,y)\Value) EndIf Else Grid(x,y)\Flag=0 Grid(x,y)\Color=GetGadgetColor(SG,#PB_Gadget_FrontColor) EndIf EndIf SG + 1 Next x Next y EndProcedure Procedure ChangeGadget(gid,num) Static oldgid Static oldnum If GetGadgetData(gid)<0 ;this is a master reserved spot If Val(GetGadgetText(gid))<>0-GetGadgetData(gid) SetGadgetText(gid,Str(0-GetGadgetData(gid))) EndIf If Sound_Mode<>#Sound_Off If Sound_Mode=#Sound_Custom PlaySound(0) Else MessageBeep_(-1) EndIf EndIf ProcedureReturn EndIf If oldgid=gid If oldnum=num If Val(GetGadgetText(gid))=num ;not changing number ProcedureReturn EndIf EndIf Else oldnum=99 EndIf oldgid=gid If num=10 If GetGadgetText(gid)<>"" LastElement(Undo()) AddElement(Undo()) Undo()\VS=GetGadgetText(gid) Undo()\GID=gid SetGadgetText(gid,"") SetGadgetData(gid,0) ProcedureReturn EndIf EndIf If CheckMove(gid,num) ;prepare for undo ;If oldsg<>GadgetID If Str(num)<>GetGadgetText(gid) LastElement(Undo()) AddElement(Undo()) Undo()\VS=GetGadgetText(gid) Undo()\GID=gid ;Debug "Mark "+Str(GadgetID)+" "+Undo()\VS ;oldgid=gid If num>9 SetGadgetText(gid,"") oldnum=0 Else oldnum=num SetGadgetText(gid,Str(num)) SetGadgetColor(gid, #PB_Gadget_FrontColor, TextColor) ;SetGadgetColor(GadgetID,#PB_Gadget_BackColor,DefColor) If Marking SetGadgetColor(gid,#PB_Gadget_BackColor,RGB(255,0,0)) Else SetGadgetColor(gid,#PB_Gadget_BackColor,DefColor) EndIf SetGadgetData(gid,0) EndIf ;Delay(200) IsDirty=#True EndIf ;EndIf Else If oldnum<>num If Sound_Mode<>#Sound_Off If Sound_Mode=#Sound_Custom PlaySound(0) Else MessageBeep_(-1) EndIf EndIf EndIf oldgid=gid oldnum=num EndIf EndProcedure ;- Event Loop SaveSize.l=0 Repeat ; Start of the event loop ;if size gets changed, set savesize to last time of resize Event = WaitWindowEvent(1000) ; This line waits until an event is received from Windows WindowID = EventWindow() ; The Window where the event is generated, can be used in the gadget procedures GadgetID = EventGadget() ; Is it a gadget event? EventType = EventType() ; The event type ;You can place code here, and use the result as parameters for the procedures ;- Game Menu If Event = #PB_Event_Menu MenuID = EventMenu() If MenuID = #Game_New If IsDirty CopyGrid(CreateMode) If PromptForSave(CreateMode) IsDirty=0 EndIf EndIf If IsDirty=0 ClearGadgets() LoadGame(1) ShowGrid() CreateMode=0 EndIf ElseIf MenuID = #Game_Load If IsDirty CopyGrid(CreateMode) If PromptForSave(CreateMode) IsDirty=0 EndIf EndIf If IsDirty=0 ClearGadgets() LoadGame(0) ShowGrid() CreateMode=0 EndIf ElseIf MenuID = #Game_Save If IsDirty CopyGrid(CreateMode) EndIf If SaveGame(CreateMode) IsDirty=0 CreateMode=0 EndIf ElseIf MenuID = #Game_Create If IsDirty CopyGrid(CreateMode) If PromptForSave(CreateMode) IsDirty=0 EndIf EndIf If IsDirty=0 ClearGadgets() NewGame() ShowGrid() CreateMode=0 EndIf ElseIf MenuID = #Game_Enter If IsDirty CopyGrid(CreateMode) If PromptForSave(CreateMode) IsDirty=0 EndIf EndIf If IsDirty=0 ClearGadgets() CreateMode=#True EndIf ElseIf MenuID = #Game_Solve If IsDirty CopyGrid(CreateMode) If PromptForSave(CreateMode) IsDirty=0 EndIf EndIf If IsDirty=0 If SolveGame() MessageRequester("Waffle's Sodoku","Game solved") ShowGrid() Else MessageRequester("Waffle's Sodoku","No Solution Found") CopyGrid(CreateMode) EndIf CreateMode=#False EndIf ElseIf MenuID = #Game_Exit If IsDirty CopyGrid(CreateMode) If PromptForSave(CreateMode) IsDirty=0 EndIf EndIf If IsDirty=0 ;CloseWindow(#Window_Sodoku) Break 1 EndIf ;- Sound Menu ElseIf MenuID = #Sound_On ;Sound_Mode=MenuID If GetMenuItemState(#Menubar_0,#Sound_Custom) Sound_Mode=#Sound_Custom Else Sound_Mode=#Sound_Default SetMenuItemState(#Menubar_0,#Sound_Default,1) EndIf SetMenuItemState(#Menubar_0,MenuID,1) SetMenuItemState(#Menubar_0,#Sound_off,0) SaveString("Sound",Str(Sound_Mode)) ElseIf MenuID = #Sound_Off Sound_Mode=MenuID SetMenuItemState(#Menubar_0,MenuID,1) SetMenuItemState(#Menubar_0,#Sound_On,0) If IsSound(0) StopSound(0) EndIf ElseIf MenuID = #Sound_Custom s.s=OpenFileRequester("Select Sound to use",Sound_Custom,"*.wav|*.wav|*.*|*.*",0) If s If LoadSound(0,s) Sound_Custom=s Sound_Mode=MenuID SetMenuItemState(#Menubar_0,MenuID,1) SetMenuItemState(#Menubar_0,#Sound_On,1) SetMenuItemState(#Menubar_0,#Sound_Default,0) SaveString("Sound",Str(Sound_Mode)) SaveString("Custom",Sound_Custom) Else MessageRequester("Waffle's Sodoku","Unable to load sound"+Chr(10)+s,#MB_ICONSTOP) EndIf EndIf ElseIf MenuID = #Sound_Default Sound_Mode=MenuID SetMenuItemState(#Menubar_0,MenuID,1) SetMenuItemState(#Menubar_0,#Sound_On,1) SetMenuItemState(#Menubar_0,#Sound_Custom,0) SaveString("Sound",Str(Sound_Mode)) If IsSound(0) StopSound(0) EndIf ;- Help Menu ElseIf MenuID = #Help_Undo If LastElement(Undo()) SG=Undo()\GID ;Debug "Undo "+Str(SG)+" "+GetGadgetText(SG)+" to "+Undo()\VS SetGadgetText(SG,Undo()\VS) SetGadgetColor(SG,#PB_Gadget_BackColor,DefColor) SetGadgetData(SG,0) DeleteElement(Undo()) OldSG=SG EndIf ElseIf MenuID = #Help_Delete For GID=#BString_0 To #BString_80 If TextNumber=Val(GetGadgetText(GID)) If GetGadgetData(GID)>=0 SetGadgetText(GID,"") SetGadgetColor(GID,#PB_Gadget_BackColor,DefColor) setgadgetdata(GID,0) EndIf EndIf Next GID ClearList(Undo()) ElseIf MenuID = #Help_Reset For GID=#BString_0 To #BString_80 If GetGadgetData(GID)>=0 SetGadgetText(GID,"") SetGadgetColor(GID,#PB_Gadget_BackColor,DefColor) setgadgetdata(GID,0) EndIf Next GID ClearList(Undo()) ElseIf MenuID = #Help_Rules ;ShowRules() GetHelp("#Rules") ElseIf MenuID = #Help_Help ;ShowHelp() GetHelp("#Contents") ElseIf MenuID = #Help_Menu ;ShowMenu() GetHelp("#Game") ElseIf MenuID = #Help_About ShowAbout() EndIf EndIf ;- String Grid If Event = #PB_Event_Gadget If ( GadgetID >= #BString_0 ) And ( GadgetID<= #BString_80 ) ;If (eventtype=#PB_EventType_LeftClick) Or (eventtype=#PB_EventType_Change) ;If TextNumber=0 ; CallDebugger ;EndIf ;If TextNumber=10 ; CallDebugger ;EndIf If eventtype=#PB_EventType_Focus ;CallDebugger ChangeGadget(GadgetID,TextNumber) ElseIf eventtype=#PB_EventType_Change ;CallDebugger ;ensure only numeric data fixflag.l=0 gt.s=GetGadgetText(GadgetID) If Len(gt)>1 gt=Left(gt,1) fixflag=1 EndIf If Val(gt)=0 If gt<>"" gt="" fixflag=1 EndIf EndIf If fixflag SetGadgetText(GadgetID,gt) EndIf ChangeGadget(GadgetID,Val(gt)) EndIf ;- Vert highlight ElseIf ( GadgetID >= #BTop_0 ) And ( GadgetID<= #BTop_8 ) ;vertical highlight SG=(GadgetID-#BTop_0)+#BString_0 HS=GetGadgetState(GadgetID) For x=1 To 9 If GetGadgetData(SG)>=0 GD=(GetGadgetData(SG)&2)+HS SetGadgetData(SG,GD) If GD If GetGadgetText(SG)="" SetGadgetColor(SG,#PB_Gadget_BackColor,RGB(129,129,129)) Else SetGadgetData(SG,0) EndIf Else SetGadgetColor(SG,#PB_Gadget_BackColor,DefColor) EndIf EndIf SG + 9 Next x ;- Horizontal Highlight ElseIf ( GadgetID >= #BSide_0 ) And ( GadgetID<= #BSide_8 ) ;horizontal highlight SG=((GadgetID-#BSide_0)*9)+#BString_0 HS=2*GetGadgetState(GadgetID) For x=1 To 9 If GetGadgetData(SG)>=0 GD=(GetGadgetData(SG)&1)+HS SetGadgetData(SG,GD) If GD If GetGadgetText(SG)="" SetGadgetColor(SG,#PB_Gadget_BackColor,RGB(129,129,129)) Else SetGadgetData(SG,0) EndIf Else SetGadgetColor(SG,#PB_Gadget_BackColor,DefColor) EndIf EndIf SG + 1 Next x ;- Number Select ElseIf ( GadgetID >= #BNUM_0 ) And ( GadgetID<= #BNUM_8 ) For BG=#BNum_0 To #BNum_8 If GadgetID=BG TextNumber.l=(GadgetID-#BNum_0)+1 ;SetGadgetColor(GadgetID,#PB_Gadget_BackColor,Color(6)) SetGadgetState(GadgetID,1) Else SetGadgetState(BG,0) ;SetGadgetColor(GadgetID,#PB_Gadget_BackColor,1) EndIf Next BG ;and some extra hilights ... If TextNumber>0 For BG=#BString_0 To #BString_80 V=Val(GetGadgetText(BG)) If V>0 If Marking=0 V=999 EndIf If V=TextNumber SetGadgetColor(BG,#PB_Gadget_BackColor,RGB(255,0,0)) Else SetGadgetColor(BG,#PB_Gadget_BackColor,DefColor) EndIf Else SetGadgetColor(BG,#PB_Gadget_BackColor,DefColor) SetGadgetData(BG,0) EndIf Next BG EndIf ;and undo all highlight buttons For BG=#BTop_0 To #BTop_8 SetGadgetState(BG,0) Next BG For BG=#BSide_0 To #BSide_8 SetGadgetState(BG,0) Next BG ;- Color Select ElseIf ( GadgetID >= #BImage_0 ) And ( GadgetID<= #BImage_8 ) TextColor.l=Color(GadgetID-#BImage_0) SetGadgetColor(#Text_0, #PB_Gadget_FrontColor, TextColor) For BG=#BImage_0 To #BImage_8 If GadgetID=BG SetState(GadgetID,1) Else SetState(BG,0) ;SetGadgetColor(GadgetID,#PB_Gadget_BackColor,1) EndIf Next BG ElseIf GadgetID=#BMark Marking=GetGadgetState(GadgetID) If TextNumber>0 For BG=#BString_0 To #BString_80 V=Val(GetGadgetText(BG)) If V>0 If Marking=0 V=999 EndIf If V=TextNumber SetGadgetColor(BG,#PB_Gadget_BackColor,RGB(255,0,0)) Else SetGadgetColor(BG,#PB_Gadget_BackColor,DefColor) EndIf EndIf Next BG EndIf EndIf EndIf If Event=#PB_Event_SizeWindow ;CallDebugger SaveSize=GetTickCount_() ;Debug "SaveSize set to "+Str(SaveSize) ResizeGame(0,0) ElseIf SaveSize ;CallDebugger TT.l=Abs(GetTickCount_()-SaveSize) If TT>1000 SaveSize=0 ;Debug "SaveSize set to 0" SaveString("Width",Str(WindowWidth(#Window_Sodoku))) SaveString("Height",Str(WindowHeight(#Window_Sodoku))) EndIf EndIf If Event=#PB_Event_CloseWindow If IsDirty CopyGrid(CreateMode) If PromptForSave(CreateMode)=0 Event=0 EndIf EndIf EndIf Until Event = #PB_Event_CloseWindow ; End of the event loop CloseHelper() End