Page 1 of 1

bruteforce peg solitaire (english version) solver

Posted: Mon Jun 09, 2008 6:19 am
by alokdube
Just wrote a brute force English version peg solitaire (http://en.wikipedia.org/wiki/Peg_solitaire) solver. uses iterative algorithms to find solutions.
The fact that the board is symmetric (you can flip the board upside down or turn it by 90deg incrementally etc) gives you the advantage of being able to match 7 solutions to any possible board combination
example below, 1 indicates no marble, 2 indicates "no hole" and 0 indicates marble, so the board area is essentially the 1s and the 0s
sample board:

__000__
__000__
0100000
0000000
0000000
__000__
__000__

so if one finds solns for the 1st "1" (hole) being at (2,0), (2,1),(2,2),(3,0),(3,1),(3,2) and (3,3) one can simply flip the board around in different ways and the similar transactions will apply to the rest of the board

The present code does not rely on already found solutions, am adding the same in a while
Right now I have used this code to find the 7 basic solutions only
Code attached below, comments welcome as always :o)

Code: Select all

;we define the board, 2 is not allowed i.e no space, 1 is no marble, 0 is marble present

Global Dim Board.b(32,6,6)

Board(0,0,0)=2
Board(0,0,1)=2
Board(0,0,2)=0
Board(0,0,3)=0
Board(0,0,4)=0
Board(0,0,5)=2
Board(0,0,6)=2

Board(0,1,0)=2
Board(0,1,1)=2
Board(0,1,2)=0
Board(0,1,3)=0
Board(0,1,4)=0
Board(0,1,5)=2
Board(0,1,6)=2

Board(0,2,0)=0
Board(0,2,1)=0
Board(0,2,2)=0
Board(0,2,3)=0
Board(0,2,4)=0
Board(0,2,5)=0
Board(0,2,6)=0

Board(0,3,0)=0
Board(0,3,1)=0
Board(0,3,2)=0
Board(0,3,3)=1
Board(0,3,4)=0
Board(0,3,5)=0
Board(0,3,6)=0

Board(0,4,0)=0
Board(0,4,1)=0
Board(0,4,2)=0
Board(0,4,3)=0
Board(0,4,4)=0
Board(0,4,5)=0
Board(0,4,6)=0

Board(0,5,0)=2
Board(0,5,1)=2
Board(0,5,2)=0
Board(0,5,3)=0
Board(0,5,4)=0
Board(0,5,5)=2
Board(0,5,6)=2

Board(0,6,0)=2
Board(0,6,1)=2
Board(0,6,2)=0
Board(0,6,3)=0
Board(0,6,4)=0
Board(0,6,5)=2
Board(0,6,6)=2

Structure move_store
fromrow.b
fromcol.b
torow.b
tocol.b
EndStructure

Global move=0
Global Dim moves_made.move_store(32,32)
Global Dim move_store_count(32)
;the above array is of the form : move_num , move_stack
;move number is the actual board move and the stack contains upto 32
;moves already made in this movenum
;the moves_store_count keeps track of the number of moves in the stack


Procedure Print_board()
PrintN(":::::::::::::::::::::::::::::::::::::::::")
For m=0 To 31
PrintN(":::::::::::::::::::::"+Str(m)+":::::::::::::::::::::")
For r=0 To 6
For c =0 To 6
Print(Str(Board(m,r,c)))
Next c
PrintN("")
Next r
Next m
;Input()
EndProcedure


Procedure Copy_board (board_from, board_to)
For i=0 To 6
For j=0 To 6
Board(board_to,i,j)=Board(board_from,i,j)
Next j
Next i
EndProcedure

For i = 0 To 32
move_store_count(i)=0
Copy_board(0,i)
Next i



;the algo is as follows:
;at each move apply a mask to find a marble with empty adjacency.
;once u reach 32 moves, check how many are left... 
;if at any stage no move to make
;backtrack
;at each move fill the moves_made(movenum)\fromx.fromy,tox,toy
;keep going till one marble left at move 32

;This procedure Brings the board back to the given move num (enter the present movenum too)
;it adjusts all other boards,move,moves_store_count to reflect the game at to_move_num
Procedure Retract_move(from_move_num,to_move_num)
move=to_move_num
For i = to_move_num+1 To from_move_num
move_store_count(i)=0
Copy_board(0,i)
Next i
EndProcedure

Procedure Is_Move_made(movenum,fromrow,fromcol,torow,tocol);check if the move is already made
result=0
If Not(move_store_count(movenum)=0); if there is any move already registered in the store
  For i = 1 To move_store_count(movenum)
  If (moves_made(movenum,i)\fromrow=fromrow)And(moves_made(movenum,i)\fromcol=fromcol)And(moves_made(movenum,i)\torow=torow)And(moves_made(movenum,i)\tocol=tocol)
   result=1
   Break
  EndIf 
  Next i
EndIf
ProcedureReturn (result)  
EndProcedure

Procedure Update_board_with_move (board_move, fromx ,fromy,tox,toy,removex,removey)
Board(board_move,fromx,fromy)=1
Board(board_move,removex,removey)=1
Board(board_move,tox,toy)=0
move_store_count(board_move)=move_store_count(board_move)+1
moves_made(board_move,move_store_count(board_move))\fromrow=fromx
moves_made(board_move,move_store_count(board_move))\fromcol=fromy
moves_made(board_move,move_store_count(board_move))\torow=tox
moves_made(board_move,move_store_count(board_move))\tocol=toy
EndProcedure

Procedure Make_move(movenum.b);movenum is the move being made
marble_present=0
move_found=0
;PrintN("inside make_move"+Str(movenum))
For row=0 To 6
For column=0 To 6


;we first check if there is a marble at the given position
If Board(movenum-1,row,column)=0
;we have found a marble, now we look around it
marble_present=1
;PrintN ("marble found")

;we now check the 1+adjacencies for a blank square
;1st we check up and if the move is already made (2 rows up, same col, fromx=row, fromy=col,tox=row-2,toy=col)
If Not((row=0) Or(row=1)) And (move_found=0)
If Board(movenum-1,row-2,column)=1 And Board(movenum-1,row-1,column)=0 And Is_Move_made(movenum,row,column,row-2,column)=0
;vacant spot on top found, we can make a move
;1st we copy the board(movenum-1) To board(movenum)
;PrintN("row=0 or row=1")
Copy_Board(movenum-1,movenum)
;then we change board(movenum) for the move
Update_board_with_move(movenum,row,column,row-2,column,row-1,column)
move_found=1
;done with move
Break 2
EndIf
EndIf
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;if no move found up, we look down and see if the move is already made
;(2 rows down, same col, fromx=row, fromy=col,tox=row+2,toy=col)
If Not((row=5) Or(row=6)) And (move_found=0)
If Board(movenum-1,row+2,column)=1 And Board(movenum-1,row+1,column)=0 And Is_Move_made(movenum,row,column,row+2,column)=0
;vacant spot found below, we can make a move
;1st we copy the board(movenum-1) To board(movenum)
;PrintN("row=5 or row=6")
Copy_Board(movenum-1,movenum)
;then we change board(movenum) for the move
Update_board_with_move(movenum,row,column,row+2,column,row+1,column)
move_found=1
;done with move
Break 2
EndIf
EndIf
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;if no move found up, and down we look left and see if the move is already made
;(same row, 2 cols left, fromx=row, fromy=col,tox=row,toy=col-2)
If Not((column=0) Or(column=1)) And (move_found=0)
If Board(movenum-1,row,column-2)=1 And Board(movenum-1,row,column-1)=0 And Is_Move_made(movenum,row,column,row,column-2)=0
;vacant spot found to the left, we can make a move
;1st we copy the board(movenum-1) To board(movenum)
;PrintN("col=0 or col=1")
Copy_Board(movenum-1,movenum)
;then we change board(movenum) for the move
Update_board_with_move(movenum,row,column,row,column-2,row,column-1)
move_found=1
;done with move
Break 2
EndIf
EndIf
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;if no move found up,down and left we look right and see if the move is already made
;(same row, 2 cols right, fromx=row, fromy=col,tox=row,toy=col+2)
If Not((column=5) Or(column=6)) And (move_found=0)
If Board(movenum-1,row,column+2)=1 And Board(movenum-1,row,column+1)=0 And Is_Move_made(movenum,row,column,row,column+2)=0
;vacant spot found to the right, we can make a move
;1st we copy the board(movenum-1) To board(movenum)
;PrintN("col=5 or col=6")
Copy_Board(movenum-1,movenum)
;then we change board(movenum) for the move
Update_board_with_move(movenum,row,column,row,column+2,row,column+1)
move_found=1
;done with move
Break 2
EndIf
EndIf
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



EndIf;marble_present ends here
marble_present=0
;PrintN(Str(column)+":"+Str(row))
Next column
Next row
;PrintN("Returning from Make_move:"+Str(move_found))
ProcedureReturn move_found

EndProcedure

OpenConsole()
EnableGraphicalConsole(1)

PrintN ("Calculating...")

move=1

Repeat
;PrintN (Str(move))
If Make_move(move)=1
;PrintN ("move found:"+Str(move))
move=move+1
Else
;PrintN ("move not found:"+Str(move))
Retract_move(move,move-1)

;Print_board()
;Input()
EndIf
;If move=31
;Print_board()
;Input()
;EndIf
;If move>29
;PrintN ("move retracted::"+Str(move))
;ConsoleLocate(20,0)
;PrintN(Str(move))
;EndIf
Until move=32

Print_board()
Input()

Re: bruteforce peg solitaire (english version) solver

Posted: Mon Jun 09, 2008 6:50 am
by DarkDragon
alokdube wrote:The fact that the board is symmetric (you can flip the board upside down or turn it by 90deg incrementally etc) gives you the advantage of being able to match 7 solutions to any possible board combination
Possible boards (showed in German Wikipedia):
http://upload.wikimedia.org/wikipedia/c ... shapes.svg

Your code should be reformatted.
It would be nice if there would be a visualization or something like that.

@daniel

Posted: Mon Jun 09, 2008 6:52 am
by alokdube
no, the way we play it here (we call it brainvita) is that the 1st empty peg can be anywhere on the english board. solve the same till only 1 peg is left.

@Daniel

Posted: Mon Jun 09, 2008 1:46 pm
by alokdube
well , I never saw so many version of peg solitaire before,
funfun for the weekend, ill try the European one later today

a better front end

Posted: Mon Aug 04, 2008 10:23 am
by alokdube

Code: Select all

;we define the board, 2 is not allowed i.e no space, 1 is no marble, 0 is marble present

Global Dim Board.b(32,6,6)

Board(0,0,0)=2
Board(0,0,1)=2
Board(0,0,2)=0
Board(0,0,3)=0
Board(0,0,4)=0
Board(0,0,5)=2
Board(0,0,6)=2

Board(0,1,0)=2
Board(0,1,1)=2
Board(0,1,2)=0
Board(0,1,3)=0
Board(0,1,4)=0
Board(0,1,5)=2
Board(0,1,6)=2

Board(0,2,0)=0
Board(0,2,1)=0
Board(0,2,2)=0
Board(0,2,3)=0
Board(0,2,4)=0
Board(0,2,5)=0
Board(0,2,6)=0

Board(0,3,0)=0
Board(0,3,1)=0
Board(0,3,2)=0
Board(0,3,3)=1
Board(0,3,4)=0
Board(0,3,5)=0
Board(0,3,6)=0

Board(0,4,0)=0
Board(0,4,1)=0
Board(0,4,2)=0
Board(0,4,3)=0
Board(0,4,4)=0
Board(0,4,5)=0
Board(0,4,6)=0

Board(0,5,0)=2
Board(0,5,1)=2
Board(0,5,2)=0
Board(0,5,3)=0
Board(0,5,4)=0
Board(0,5,5)=2
Board(0,5,6)=2

Board(0,6,0)=2
Board(0,6,1)=2
Board(0,6,2)=0
Board(0,6,3)=0
Board(0,6,4)=0
Board(0,6,5)=2
Board(0,6,6)=2

Structure move_store
fromrow.b
fromcol.b
torow.b
tocol.b
EndStructure

Global move=0
Global Dim moves_made.move_store(32,32)
Global Dim move_store_count(32)


;CreateGadgetList(WindowID(0))

Global startx=210
Global starty=200

Procedure Draw_window(cnt)
StartDrawing(WindowOutput(0))

DrawImage(ImageID(cnt),startx,starty)
SetGadgetText(2,Str(cnt))
StopDrawing()

EndProcedure

Procedure Print_board()

For m=0 To 31
CreateImage(m, 210, 210)
StartDrawing(ImageOutput(m))
;BackColor(RGB($FF,$FF,$CC))

FillArea(0,0,RGB($FF,$FF,$CC),RGB($FF,$FF,$CC))


For r=0 To 6
For c =0 To 6



If Not(Board(m,r,c)=2)
DrawingMode(#PB_2DDrawing_Outlined)
;FrontColor(RGB($00,$00,$00))
FrontColor(RGB($FF,$FF,$CC))
Box(30*c, 30*r, 30, 30)
DrawingMode(#PB_2DDrawing_Default)

If Board(m,r,c)=1
Circle(30*c+15,30*r+15,10,RGB($FF,$CC,$FF))
EndIf

If Board(m,r,c)=0
Circle(30*c+15,30*r+15,10,RGB($FF,$00,$00))
EndIf

EndIf

Next c
Next r
StopDrawing()
;Delay(2000)
Next m


LoadFont(0, "Arial", 16)

cnt=0
ButtonGadget(0,20,20,30,30,"<<")
ButtonGadget(1,550,20,30,30,">>")

SetGadgetFont(#PB_Default, FontID(0))
TextGadget(2, 297,540, 30, 20,Str(cnt),#PB_Text_Center)

SetGadgetColor(2,#PB_Gadget_BackColor,RGB($FF,$FF,$CC))
SetGadgetColor(2,#PB_Gadget_FrontColor,RGB($FF,$00,$00))
Draw_window(cnt)
Delay(2)
Draw_window(cnt)

Repeat  

EventID = WaitWindowEvent()

; If KeyboardPushed(#PB_Key_Left)
;  If cnt=0
;  cnt=0
;  Else 
;  cnt=cnt-1
; EndIf
; EndIf
 
; If KeyboardPushed(#PB_Key_Right)
; If cnt=31
; cnt=31
; Else
; cnt=cnt+1
; EndIf
; EndIf


If EventID = #PB_Event_Gadget
Select EventGadget()

Case 0
If cnt>0
cnt=cnt-1
Else 
cnt=0
EndIf
Draw_window(cnt)




Case 1
If cnt<31
cnt=cnt+1
Else 
cnt=31
EndIf
Draw_window(cnt)


EndSelect
EndIf



Until EventID = #PB_Event_CloseWindow
EndProcedure

Procedure Copy_board (board_from, board_to)
For i=0 To 6
For j=0 To 6
Board(board_to,i,j)=Board(board_from,i,j)
Next j
Next i
EndProcedure

For i = 0 To 32
move_store_count(i)=0
Copy_board(0,i)
Next i

;the above array is of the form : move_num , move_stack
;move number is the actual board move and the stack contains upto 30 moves already made in this movenum
;the moves_store_count keeps track of the number of moves in the stack

;the algo is as follows:
;at each move apply a mask to find a marble with empty adjacency.
;once u reach 30 moves, check how many are left... 
;if at any stage no move to make
;backtrack
;at each move fill the moves_made(movenum)\fromx.fromy,tox,toy
;keep going till one marble left at move 30

;This procedure Brings the board back to the given move num (enter the present movenum too)
;it adjusts all other boards,move,moves_store_count to reflect the game at to_move_num

Procedure Retract_move(from_move_num,to_move_num)
move=to_move_num
For i = to_move_num+1 To from_move_num
move_store_count(i)=0
Copy_board(0,i)
Next i
EndProcedure

Procedure Is_Move_made(movenum,fromrow,fromcol,torow,tocol);check if the move is already made
result=0
If Not(move_store_count(movenum)=0); if there is any move already registered in the store
  For i = 1 To move_store_count(movenum)
  If (moves_made(movenum,i)\fromrow=fromrow)And(moves_made(movenum,i)\fromcol=fromcol)And(moves_made(movenum,i)\torow=torow)And(moves_made(movenum,i)\tocol=tocol)
   result=1
   Break
  EndIf 
  Next i
EndIf
ProcedureReturn (result)  
EndProcedure

Procedure Update_board_with_move (board_move, fromx ,fromy,tox,toy,removex,removey)
Board(board_move,fromx,fromy)=1
Board(board_move,removex,removey)=1
Board(board_move,tox,toy)=0
move_store_count(board_move)=move_store_count(board_move)+1
moves_made(board_move,move_store_count(board_move))\fromrow=fromx
moves_made(board_move,move_store_count(board_move))\fromcol=fromy
moves_made(board_move,move_store_count(board_move))\torow=tox
moves_made(board_move,move_store_count(board_move))\tocol=toy
EndProcedure

Procedure Make_move(movenum.b);movenum is the move being made
marble_present=0
move_found=0
;PrintN("inside make_move"+Str(movenum))
For row=0 To 6
For column=0 To 6


;we first check if there is a marble at the given position
If Board(movenum-1,row,column)=0
;we have found a marble, now we look around it
marble_present=1
;PrintN ("marble found")

;we now check the 1+adjacencies for a blank square
;1st we check up and if the move is already made (2 rows up, same col, fromx=row, fromy=col,tox=row-2,toy=col)
If Not((row=0) Or(row=1)) And (move_found=0)
If Board(movenum-1,row-2,column)=1 And Board(movenum-1,row-1,column)=0 And Is_Move_made(movenum,row,column,row-2,column)=0
;vacant spot on top found, we can make a move
;1st we copy the board(movenum-1) To board(movenum)
;PrintN("row=0 or row=1")
Copy_Board(movenum-1,movenum)
;then we change board(movenum) for the move
Update_board_with_move(movenum,row,column,row-2,column,row-1,column)
move_found=1
;done with move
Break 2
EndIf
EndIf
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;if no move found up, we look down and see if the move is already made
;(2 rows down, same col, fromx=row, fromy=col,tox=row+2,toy=col)
If Not((row=5) Or(row=6)) And (move_found=0)
If Board(movenum-1,row+2,column)=1 And Board(movenum-1,row+1,column)=0 And Is_Move_made(movenum,row,column,row+2,column)=0
;vacant spot found below, we can make a move
;1st we copy the board(movenum-1) To board(movenum)
;PrintN("row=5 or row=6")
Copy_Board(movenum-1,movenum)
;then we change board(movenum) for the move
Update_board_with_move(movenum,row,column,row+2,column,row+1,column)
move_found=1
;done with move
Break 2
EndIf
EndIf
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;if no move found up, and down we look left and see if the move is already made
;(same row, 2 cols left, fromx=row, fromy=col,tox=row,toy=col-2)
If Not((column=0) Or(column=1)) And (move_found=0)
If Board(movenum-1,row,column-2)=1 And Board(movenum-1,row,column-1)=0 And Is_Move_made(movenum,row,column,row,column-2)=0
;vacant spot found to the left, we can make a move
;1st we copy the board(movenum-1) To board(movenum)
;PrintN("col=0 or col=1")
Copy_Board(movenum-1,movenum)
;then we change board(movenum) for the move
Update_board_with_move(movenum,row,column,row,column-2,row,column-1)
move_found=1
;done with move
Break 2
EndIf
EndIf
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;if no move found up,down and left we look right and see if the move is already made
;(same row, 2 cols right, fromx=row, fromy=col,tox=row,toy=col+2)
If Not((column=5) Or(column=6)) And (move_found=0)
If Board(movenum-1,row,column+2)=1 And Board(movenum-1,row,column+1)=0 And Is_Move_made(movenum,row,column,row,column+2)=0
;vacant spot found to the right, we can make a move
;1st we copy the board(movenum-1) To board(movenum)
;PrintN("col=5 or col=6")
Copy_Board(movenum-1,movenum)
;then we change board(movenum) for the move
Update_board_with_move(movenum,row,column,row,column+2,row,column+1)
move_found=1
;done with move
Break 2
EndIf
EndIf
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



EndIf;marble_present ends here
marble_present=0
;PrintN(Str(column)+":"+Str(row))
Next column
Next row
;PrintN("Returning from Make_move:"+Str(move_found))
ProcedureReturn move_found

EndProcedure



;;;Main Procedure goes here


OpenConsole()




move=1
PrintN("Calculating...")
Repeat




If Make_move(move)=1

move=move+1
Else

Retract_move(move,move-1)

EndIf


Until move=32
CloseConsole()
OpenWindow(0, 216, 0, 602, 681, "Brainvita", #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_TitleBar )
CreateGadgetList(WindowID(0))
SetWindowColor(0,RGB($FF,$FF,$CC))
Print_board()
[/code]

gui version

Posted: Thu Aug 07, 2008 4:26 pm
by alokdube

Code: Select all


;we define the board, 2 is not allowed i.e no space, 1 is no marble, 0 is marble present

Global Dim Board.b(32,6,6)

Board(0,0,0)=2
Board(0,0,1)=2
Board(0,0,2)=0
Board(0,0,3)=0
Board(0,0,4)=0
Board(0,0,5)=2
Board(0,0,6)=2

Board(0,1,0)=2
Board(0,1,1)=2
Board(0,1,2)=0
Board(0,1,3)=0
Board(0,1,4)=0
Board(0,1,5)=2
Board(0,1,6)=2

Board(0,2,0)=0
Board(0,2,1)=0
Board(0,2,2)=0
Board(0,2,3)=0
Board(0,2,4)=0
Board(0,2,5)=0
Board(0,2,6)=0

Board(0,3,0)=0
Board(0,3,1)=0
Board(0,3,2)=0
Board(0,3,3)=0
Board(0,3,4)=0
Board(0,3,5)=0
Board(0,3,6)=0

Board(0,4,0)=0
Board(0,4,1)=0
Board(0,4,2)=0
Board(0,4,3)=0
Board(0,4,4)=0
Board(0,4,5)=0
Board(0,4,6)=0

Board(0,5,0)=2
Board(0,5,1)=2
Board(0,5,2)=0
Board(0,5,3)=0
Board(0,5,4)=0
Board(0,5,5)=2
Board(0,5,6)=2

Board(0,6,0)=2
Board(0,6,1)=2
Board(0,6,2)=0
Board(0,6,3)=0
Board(0,6,4)=0
Board(0,6,5)=2
Board(0,6,6)=2

Structure move_store
fromrow.b
fromcol.b
torow.b
tocol.b
EndStructure

Global move=0
Global Dim moves_made.move_store(32,32)
Global Dim move_store_count(32)


;CreateGadgetList(WindowID(0))

Global startx=210
Global starty=200

Procedure Draw_window(cnt)
SetGadgetState(8,ImageID(cnt))
SetGadgetText(2,Str(cnt))
EndProcedure

Procedure Make_image(m)
CreateImage(m, 210, 210)
StartDrawing(ImageOutput(m))
;BackColor(RGB($FF,$FF,$CC))

FillArea(0,0,RGB($FF,$FF,$CC),RGB($FF,$FF,$CC))


For r=0 To 6
For c =0 To 6



If Not(Board(m,r,c)=2)
DrawingMode(#PB_2DDrawing_Outlined)
;FrontColor(RGB($00,$00,$00))
FrontColor(RGB($FF,$FF,$CC))
Box(30*c, 30*r, 30, 30)
DrawingMode(#PB_2DDrawing_Default)

If Board(m,r,c)=1
Circle(30*c+15,30*r+15,10,RGB($FF,$CC,$FF))
EndIf

If Board(m,r,c)=0
Circle(30*c+15,30*r+15,10,RGB($FF,$00,$00))
EndIf

EndIf

Next c
Next r
StopDrawing()


EndProcedure

Procedure Print_board()

For m=0 To 31
Make_image(m)
;Delay(2000)
Next m
cnt=0




ButtonGadget(0,20,20,30,30,"<<")
ButtonGadget(1,550,20,30,30,">>")


Draw_window(cnt)
Delay(2)
Draw_window(cnt)

Repeat  

EventID = WaitWindowEvent()

; If KeyboardPushed(#PB_Key_Left)
;  If cnt=0
;  cnt=0
;  Else 
;  cnt=cnt-1
; EndIf
; EndIf
 
; If KeyboardPushed(#PB_Key_Right)
; If cnt=31
; cnt=31
; Else
; cnt=cnt+1
; EndIf
; EndIf


If EventID = #PB_Event_Gadget
Select EventGadget()

Case 0
If cnt>0
cnt=cnt-1
Else 
cnt=0
EndIf
Draw_window(cnt)




Case 1
If cnt<31
cnt=cnt+1
Else 
cnt=31
EndIf
Draw_window(cnt)


EndSelect
EndIf



Until EventID = #PB_Event_CloseWindow
EndProcedure

Procedure Copy_board (board_from, board_to)
For i=0 To 6
For j=0 To 6
Board(board_to,i,j)=Board(board_from,i,j)
Next j
Next i
EndProcedure

For i = 0 To 32
move_store_count(i)=0
Copy_board(0,i)
Next i

;the above array is of the form : move_num , move_stack
;move number is the actual board move and the stack contains upto 30 moves already made in this movenum
;the moves_store_count keeps track of the number of moves in the stack

;the algo is as follows:
;at each move apply a mask to find a marble with empty adjacency.
;once u reach 30 moves, check how many are left... 
;if at any stage no move to make
;backtrack
;at each move fill the moves_made(movenum)\fromx.fromy,tox,toy
;keep going till one marble left at move 30

;This procedure Brings the board back to the given move num (enter the present movenum too)
;it adjusts all other boards,move,moves_store_count to reflect the game at to_move_num

Procedure Retract_move(from_move_num,to_move_num)
move=to_move_num
For i = to_move_num+1 To from_move_num
move_store_count(i)=0
Copy_board(0,i)
Next i
EndProcedure

Procedure Is_Move_made(movenum,fromrow,fromcol,torow,tocol);check if the move is already made
result=0
If Not(move_store_count(movenum)=0); if there is any move already registered in the store
  For i = 1 To move_store_count(movenum)
  If (moves_made(movenum,i)\fromrow=fromrow)And(moves_made(movenum,i)\fromcol=fromcol)And(moves_made(movenum,i)\torow=torow)And(moves_made(movenum,i)\tocol=tocol)
   result=1
   Break
  EndIf 
  Next i
EndIf
ProcedureReturn (result)  
EndProcedure

Procedure Update_board_with_move (board_move, fromx ,fromy,tox,toy,removex,removey)
Board(board_move,fromx,fromy)=1
Board(board_move,removex,removey)=1
Board(board_move,tox,toy)=0
move_store_count(board_move)=move_store_count(board_move)+1
moves_made(board_move,move_store_count(board_move))\fromrow=fromx
moves_made(board_move,move_store_count(board_move))\fromcol=fromy
moves_made(board_move,move_store_count(board_move))\torow=tox
moves_made(board_move,move_store_count(board_move))\tocol=toy
EndProcedure

Procedure Make_move(movenum.b);movenum is the move being made
marble_present=0
move_found=0
;PrintN("inside make_move"+Str(movenum))
For row=0 To 6
For column=0 To 6


;we first check if there is a marble at the given position
If Board(movenum-1,row,column)=0
;we have found a marble, now we look around it
marble_present=1
;PrintN ("marble found")

;we now check the 1+adjacencies for a blank square
;1st we check up and if the move is already made (2 rows up, same col, fromx=row, fromy=col,tox=row-2,toy=col)
If Not((row=0) Or(row=1)) And (move_found=0)
If Board(movenum-1,row-2,column)=1 And Board(movenum-1,row-1,column)=0 And Is_Move_made(movenum,row,column,row-2,column)=0
;vacant spot on top found, we can make a move
;1st we copy the board(movenum-1) To board(movenum)
;PrintN("row=0 or row=1")
Copy_Board(movenum-1,movenum)
;then we change board(movenum) for the move
Update_board_with_move(movenum,row,column,row-2,column,row-1,column)
move_found=1
;done with move
Break 2
EndIf
EndIf
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;if no move found up, we look down and see if the move is already made
;(2 rows down, same col, fromx=row, fromy=col,tox=row+2,toy=col)
If Not((row=5) Or(row=6)) And (move_found=0)
If Board(movenum-1,row+2,column)=1 And Board(movenum-1,row+1,column)=0 And Is_Move_made(movenum,row,column,row+2,column)=0
;vacant spot found below, we can make a move
;1st we copy the board(movenum-1) To board(movenum)
;PrintN("row=5 or row=6")
Copy_Board(movenum-1,movenum)
;then we change board(movenum) for the move
Update_board_with_move(movenum,row,column,row+2,column,row+1,column)
move_found=1
;done with move
Break 2
EndIf
EndIf
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;if no move found up, and down we look left and see if the move is already made
;(same row, 2 cols left, fromx=row, fromy=col,tox=row,toy=col-2)
If Not((column=0) Or(column=1)) And (move_found=0)
If Board(movenum-1,row,column-2)=1 And Board(movenum-1,row,column-1)=0 And Is_Move_made(movenum,row,column,row,column-2)=0
;vacant spot found to the left, we can make a move
;1st we copy the board(movenum-1) To board(movenum)
;PrintN("col=0 or col=1")
Copy_Board(movenum-1,movenum)
;then we change board(movenum) for the move
Update_board_with_move(movenum,row,column,row,column-2,row,column-1)
move_found=1
;done with move
Break 2
EndIf
EndIf
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;if no move found up,down and left we look right and see if the move is already made
;(same row, 2 cols right, fromx=row, fromy=col,tox=row,toy=col+2)
If Not((column=5) Or(column=6)) And (move_found=0)
If Board(movenum-1,row,column+2)=1 And Board(movenum-1,row,column+1)=0 And Is_Move_made(movenum,row,column,row,column+2)=0
;vacant spot found to the right, we can make a move
;1st we copy the board(movenum-1) To board(movenum)
;PrintN("col=5 or col=6")
Copy_Board(movenum-1,movenum)
;then we change board(movenum) for the move
Update_board_with_move(movenum,row,column,row,column+2,row,column+1)
move_found=1
;done with move
Break 2
EndIf
EndIf
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



EndIf;marble_present ends here
marble_present=0
;PrintN(Str(column)+":"+Str(row))
Next column
Next row
;PrintN("Returning from Make_move:"+Str(move_found))
ProcedureReturn move_found

EndProcedure



;;;Main Procedure goes here

OpenWindow(0, 216, 0, 602, 681, "Brainvita", #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_TitleBar )

CreateGadgetList(WindowID(0))
SetWindowColor(0,RGB($FF,$FF,$CC))

ImageGadget(8,startx,starty,210,210,0)
Make_image(0)

LoadFont(0, "Arial", 16)
LoadFont(3, "Arial", 12)

SetGadgetFont(#PB_Default, FontID(3))
TextGadget   (7,  10, 610, 190,  20, "Select the empty hole....", #PB_Text_Center)
SetGadgetColor(7,#PB_Gadget_BackColor,RGB($FF,$FF,$CC))
SetGadgetColor(7,#PB_Gadget_FrontColor,RGB($FF,$00,$00))
SetGadgetFont(#PB_Default, FontID(0))
TextGadget(2, 297,540, 30, 20,Str(cnt),#PB_Text_Center)

SetGadgetColor(2,#PB_Gadget_BackColor,RGB($FF,$FF,$CC))
SetGadgetColor(2,#PB_Gadget_FrontColor,RGB($FF,$00,$00))

Draw_window(0)
eve=0
Repeat
Event= WaitWindowEvent()


Select Event
 Case #PB_Event_Gadget
 Select EventGadget()
 Case 8
   Select EventType()
   Case #PB_EventType_LeftClick  
   x=WindowMouseX(0)
   y=WindowMouseY(0) 
       
   If ((x>=210) And (x<=210 +30*7) And (y>=210) And (y<=210+30*7))
   my=(x-210)/30
   mx=(y-210)/30
   
 Board(0,mx,my)=1
 eve=1
EndIf
   EndSelect
EndSelect
EndSelect
Until eve=1
Make_image(0)
Draw_window(0)
SetGadgetText(7,"calculating")
;

;OpenConsole()

ProgressBarGadget(6,  250, 600, 190,  30, 0, 32)
SetGadgetState (6, move)

move=1
;PrintN("Calculating...")
Repeat




If Make_move(move)=1

move=move+1
Else

Retract_move(move,move-1)

EndIf

SetGadgetState (6, move)
Until move=32
;CloseConsole()
FreeGadget(6)
FreeGadget(7)

Print_board()


lighter version

Posted: Mon Aug 11, 2008 7:52 am
by alokdube
seems that the progress bar really slows things down like hell,
a faster version

Code: Select all

;we define the board, 2 is not allowed i.e no space, 1 is no marble, 0 is marble present

Global Dim Board.b(32,6,6)



Structure move_store
fromrow.b
fromcol.b
torow.b
tocol.b
EndStructure

Global move=0
Global Dim moves_made.move_store(32,32)
Global Dim move_store_count(32)


;CreateGadgetList(WindowID(0))

Global startx=210
Global starty=200

Procedure Draw_window(cnt)
SetGadgetState(8,ImageID(cnt))
SetGadgetText(2,Str(cnt))
EndProcedure

Procedure Make_image(m)
CreateImage(m, 210, 210)
StartDrawing(ImageOutput(m))
;BackColor(RGB($FF,$FF,$CC))

FillArea(0,0,RGB($FF,$FF,$CC),RGB($FF,$FF,$CC))


For r=0 To 6
For c =0 To 6



If Not(Board(m,r,c)=2)
DrawingMode(#PB_2DDrawing_Outlined)
;FrontColor(RGB($00,$00,$00))
FrontColor(RGB($FF,$FF,$CC))
Box(30*c, 30*r, 30, 30)
DrawingMode(#PB_2DDrawing_Default)

If Board(m,r,c)=1
Circle(30*c+15,30*r+15,10,RGB($FF,$CC,$FF))
EndIf

If Board(m,r,c)=0
Circle(30*c+15,30*r+15,10,RGB($FF,$00,$00))
EndIf

EndIf

Next c
Next r
StopDrawing()


EndProcedure

Procedure Print_board()

For m=0 To 31
Make_image(m)
;Delay(2000)
Next m
LoadFont(4, "Arial", 9)
SetGadgetFont(#PB_Default, FontID(4))
ButtonGadget(0,20,20,30,30,"<<")
ButtonGadget(1,550,20,30,30,">>")
ButtonGadget(3,285,20,40,30,"New")
Draw_window(0)
SetGadgetFont(#PB_Default, FontID(0))

EndProcedure

Procedure Copy_board (board_from, board_to)
For i=0 To 6
For j=0 To 6
Board(board_to,i,j)=Board(board_from,i,j)
Next j
Next i
EndProcedure

For i = 0 To 32
move_store_count(i)=0
Copy_board(0,i)
Next i

;the above array is of the form : move_num , move_stack
;move number is the actual board move and the stack contains upto 30 moves already made in this movenum
;the moves_store_count keeps track of the number of moves in the stack

;the algo is as follows:
;at each move apply a mask to find a marble with empty adjacency.
;once u reach 30 moves, check how many are left... 
;if at any stage no move to make
;backtrack
;at each move fill the moves_made(movenum)\fromx.fromy,tox,toy
;keep going till one marble left at move 30

;This procedure Brings the board back to the given move num (enter the present movenum too)
;it adjusts all other boards,move,moves_store_count to reflect the game at to_move_num

Procedure Retract_move(from_move_num,to_move_num)
move=to_move_num
For i = to_move_num+1 To from_move_num
move_store_count(i)=0
Copy_board(0,i)
Next i
EndProcedure

Procedure Is_Move_made(movenum,fromrow,fromcol,torow,tocol);check if the move is already made
result=0
If Not(move_store_count(movenum)=0); if there is any move already registered in the store
  For i = 1 To move_store_count(movenum)
  If (moves_made(movenum,i)\fromrow=fromrow)And(moves_made(movenum,i)\fromcol=fromcol)And(moves_made(movenum,i)\torow=torow)And(moves_made(movenum,i)\tocol=tocol)
   result=1
   Break
  EndIf 
  Next i
EndIf
ProcedureReturn (result)  
EndProcedure

Procedure Update_board_with_move (board_move, fromx ,fromy,tox,toy,removex,removey)
Board(board_move,fromx,fromy)=1
Board(board_move,removex,removey)=1
Board(board_move,tox,toy)=0
move_store_count(board_move)=move_store_count(board_move)+1
moves_made(board_move,move_store_count(board_move))\fromrow=fromx
moves_made(board_move,move_store_count(board_move))\fromcol=fromy
moves_made(board_move,move_store_count(board_move))\torow=tox
moves_made(board_move,move_store_count(board_move))\tocol=toy
EndProcedure

Procedure Make_move(movenum.b);movenum is the move being made
marble_present=0
move_found=0
;PrintN("inside make_move"+Str(movenum))
For row=0 To 6
For column=0 To 6


;we first check if there is a marble at the given position
If Board(movenum-1,row,column)=0
;we have found a marble, now we look around it
marble_present=1
;PrintN ("marble found")

;we now check the 1+adjacencies for a blank square
;1st we check up and if the move is already made (2 rows up, same col, fromx=row, fromy=col,tox=row-2,toy=col)
If Not((row=0) Or(row=1)) And (move_found=0)
If Board(movenum-1,row-2,column)=1 And Board(movenum-1,row-1,column)=0 And Is_Move_made(movenum,row,column,row-2,column)=0
;vacant spot on top found, we can make a move
;1st we copy the board(movenum-1) To board(movenum)
;PrintN("row=0 or row=1")
Copy_Board(movenum-1,movenum)
;then we change board(movenum) for the move
Update_board_with_move(movenum,row,column,row-2,column,row-1,column)
move_found=1
;done with move
Break 2
EndIf
EndIf
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;if no move found up, we look down and see if the move is already made
;(2 rows down, same col, fromx=row, fromy=col,tox=row+2,toy=col)
If Not((row=5) Or(row=6)) And (move_found=0)
If Board(movenum-1,row+2,column)=1 And Board(movenum-1,row+1,column)=0 And Is_Move_made(movenum,row,column,row+2,column)=0
;vacant spot found below, we can make a move
;1st we copy the board(movenum-1) To board(movenum)
;PrintN("row=5 or row=6")
Copy_Board(movenum-1,movenum)
;then we change board(movenum) for the move
Update_board_with_move(movenum,row,column,row+2,column,row+1,column)
move_found=1
;done with move
Break 2
EndIf
EndIf
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;if no move found up, and down we look left and see if the move is already made
;(same row, 2 cols left, fromx=row, fromy=col,tox=row,toy=col-2)
If Not((column=0) Or(column=1)) And (move_found=0)
If Board(movenum-1,row,column-2)=1 And Board(movenum-1,row,column-1)=0 And Is_Move_made(movenum,row,column,row,column-2)=0
;vacant spot found to the left, we can make a move
;1st we copy the board(movenum-1) To board(movenum)
;PrintN("col=0 or col=1")
Copy_Board(movenum-1,movenum)
;then we change board(movenum) for the move
Update_board_with_move(movenum,row,column,row,column-2,row,column-1)
move_found=1
;done with move
Break 2
EndIf
EndIf
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;if no move found up,down and left we look right and see if the move is already made
;(same row, 2 cols right, fromx=row, fromy=col,tox=row,toy=col+2)
If Not((column=5) Or(column=6)) And (move_found=0)
If Board(movenum-1,row,column+2)=1 And Board(movenum-1,row,column+1)=0 And Is_Move_made(movenum,row,column,row,column+2)=0
;vacant spot found to the right, we can make a move
;1st we copy the board(movenum-1) To board(movenum)
;PrintN("col=5 or col=6")
Copy_Board(movenum-1,movenum)
;then we change board(movenum) for the move
Update_board_with_move(movenum,row,column,row,column+2,row,column+1)
move_found=1
;done with move
Break 2
EndIf
EndIf
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



EndIf;marble_present ends here
marble_present=0
;PrintN(Str(column)+":"+Str(row))
Next column
Next row
;PrintN("Returning from Make_move:"+Str(move_found))
ProcedureReturn move_found

EndProcedure



;;;Main Procedure goes here

OpenWindow(0, 216, 0, 602, 681, "Brainvita",  #PB_Window_TitleBar| #PB_Window_MinimizeGadget )

CreateGadgetList(WindowID(0))



Repeat


SetWindowColor(0,RGB($FF,$FF,$CC))
newgame_request=0

Board(0,0,0)=2
Board(0,0,1)=2
Board(0,0,2)=0
Board(0,0,3)=0
Board(0,0,4)=0
Board(0,0,5)=2
Board(0,0,6)=2

Board(0,1,0)=2
Board(0,1,1)=2
Board(0,1,2)=0
Board(0,1,3)=0
Board(0,1,4)=0
Board(0,1,5)=2
Board(0,1,6)=2

Board(0,2,0)=0
Board(0,2,1)=0
Board(0,2,2)=0
Board(0,2,3)=0
Board(0,2,4)=0
Board(0,2,5)=0
Board(0,2,6)=0

Board(0,3,0)=0
Board(0,3,1)=0
Board(0,3,2)=0
Board(0,3,3)=0
Board(0,3,4)=0
Board(0,3,5)=0
Board(0,3,6)=0

Board(0,4,0)=0
Board(0,4,1)=0
Board(0,4,2)=0
Board(0,4,3)=0
Board(0,4,4)=0
Board(0,4,5)=0
Board(0,4,6)=0

Board(0,5,0)=2
Board(0,5,1)=2
Board(0,5,2)=0
Board(0,5,3)=0
Board(0,5,4)=0
Board(0,5,5)=2
Board(0,5,6)=2

Board(0,6,0)=2
Board(0,6,1)=2
Board(0,6,2)=0
Board(0,6,3)=0
Board(0,6,4)=0
Board(0,6,5)=2
Board(0,6,6)=2

move=0

startx=210
starty=200

For i = 0 To 32
move_store_count(i)=0
Copy_board(0,i)
Next i

ImageGadget(8,startx,starty,210,210,0)
Make_image(0)

LoadFont(0, "Arial", 12)
LoadFont(3, "Arial", 12)

SetGadgetFont(#PB_Default, FontID(3))
TextGadget   (7,  210, 610, 190,  20, "Select the empty hole....", #PB_Text_Center)
SetGadgetColor(7,#PB_Gadget_BackColor,RGB($FF,$FF,$CC))
SetGadgetColor(7,#PB_Gadget_FrontColor,RGB($FF,$00,$00))
SetGadgetFont(#PB_Default, FontID(0))
TextGadget(2, 297,540, 30, 20,Str(cnt),#PB_Text_Center)

SetGadgetColor(2,#PB_Gadget_BackColor,RGB($FF,$FF,$CC))
SetGadgetColor(2,#PB_Gadget_FrontColor,RGB($FF,$00,$00))

Draw_window(0)
eve=0

Repeat
Event= WaitWindowEvent()

If Event=#PB_Event_CloseWindow
End
EndIf

Select Event
 Case #PB_Event_Gadget
 Select EventGadget()
 Case 8
   Select EventType()
   Case #PB_EventType_LeftClick  
   x=WindowMouseX(0)
   y=WindowMouseY(0) 
       
   If ((x>=210) And (x<=210 +30*7) And (y>=210) And (y<=210+30*7))
   my=(x-210)/30
   mx=(y-210)/30
   
 Board(0,mx,my)=1
 eve=1
EndIf
   EndSelect
EndSelect
EndSelect
Until eve=1
Make_image(0)
Draw_window(0)
SetGadgetText(7,"calculating")
;




;ProgressBarGadget(6,  240, 600, 190,  30, 0, 32)
;SetGadgetState (6, move)

move=1

Repeat



If WindowEvent()=#PB_Event_CloseWindow
End
EndIf

If Make_move(move)=1

move=move+1
Else

Retract_move(move,move-1)

EndIf


Until move=32

SetGadgetText(7,"Done!")



Print_board()





cnt=0
Repeat  

EventID = WaitWindowEvent()

cleareddone=0

If EventID = #PB_Event_Gadget

Select EventGadget()

Case 0

If cnt>0
cnt=cnt-1
Else 
cnt=0
EndIf
If cleareddone=0
FreeGadget(7)
cleareddone=1
EndIf
Draw_window(cnt)

Case 1

If cnt<31
cnt=cnt+1
Else 
cnt=31
EndIf

If cleareddone=0
FreeGadget(7)
cleareddone=1
EndIf

Draw_window(cnt)

Case 3
newgame_request=1

EndSelect
EndIf

Until newgame_request=1 Or EventID = #PB_Event_CloseWindow
FreeGadget(0)
FreeGadget(1)
FreeGadget(3)

;the program should contiue exectuing unless the previous exit was due to a close window event

Until EventID = #PB_Event_CloseWindow



a mutithreaded version

Posted: Thu Jan 22, 2009 10:48 am
by alokdube

Code: Select all

;we define the board, 2 is not allowed i.e no space, 1 is no marble, 0 is marble present

Global Dim Board.b(9,32,6,6)
;board 32 is dummy board/stack
Global solved=0
Global solved_thread=10

#debug=0

Structure move_store
fromrow.b
fromcol.b
torow.b
tocol.b
EndStructure


Global Dim moves_made.move_store(9,32,32)
Global Dim move_store_count(9,32)


;CreateGadgetList(WindowID(0))

Global startx=210
Global starty=200

If (#debug)
OpenConsole()
EndIf

Procedure Draw_window(thread,cnt)

SetGadgetState(8,ImageID(cnt))
SetGadgetText(2,Str(cnt))
EndProcedure

Procedure Make_image(thread,m)

CreateImage(m, 210, 210)
StartDrawing(ImageOutput(m))
;BackColor(RGB($FF,$FF,$CC))

FillArea(0,0,RGB($FF,$FF,$CC),RGB($FF,$FF,$CC))


For r=0 To 6
For c =0 To 6



If Not(Board(thread,m,r,c)=2)
DrawingMode(#PB_2DDrawing_Outlined)
;FrontColor(RGB($00,$00,$00))
FrontColor(RGB($FF,$FF,$CC))
Box(30*c, 30*r, 30, 30)
DrawingMode(#PB_2DDrawing_Default)

If Board(thread,m,r,c)=1
Circle(30*c+15,30*r+15,10,RGB($FF,$CC,$FF))
EndIf

If Board(thread,m,r,c)=0
Circle(30*c+15,30*r+15,10,RGB($FF,$00,$00))
EndIf

EndIf

Next c
Next r
StopDrawing()


EndProcedure

Procedure Print_board(thread)

For m=0 To 31
Make_image(thread,m)
;Delay(2000)
Next m
LoadFont(4, "Arial", 9)
SetGadgetFont(#PB_Default, FontID(4))
ButtonGadget(0,20,20,30,30,"<<")
ButtonGadget(1,550,20,30,30,">>")
ButtonGadget(3,285,20,40,30,"New")
Draw_window(thread,0)
SetGadgetFont(#PB_Default, FontID(0))

EndProcedure

Procedure Copy_board (thread_from,board_from, thread_to,board_to)

For i=0 To 6
For j=0 To 6
Board(thread_to,board_to,i,j)=Board(thread_from,board_from,i,j)
Next j
Next i
EndProcedure


;the above array is of the form : move_num , move_stack
;move number is the actual board move and the stack contains upto 30 moves already made in this movenum
;the moves_store_count keeps track of the number of moves in the stack

;the algo is as follows:
;at each move apply a mask to find a marble with empty adjacency.
;once u reach 30 moves, check how many are left... 
;if at any stage no move to make
;backtrack
;at each move fill the moves_made(movenum)\fromx.fromy,tox,toy
;keep going till one marble left at move 30


;This procedure Brings the board back to the given move num (enter the present movenum too)
;it adjusts all other boards,move,moves_store_count to reflect the game at to_move_num

Procedure Retract_move(thread,from_move_num,to_move_num)

move=to_move_num
For i = to_move_num+1 To from_move_num
move_store_count(thread,i)=0
Copy_board(thread,0,thread,i)
Next i
ProcedureReturn move
EndProcedure

Procedure Is_Move_made(thread,movenum,fromrow,fromcol,torow,tocol);check if the move is already made

result=0
If Not(move_store_count(thread,movenum)=0); if there is any move already registered in the store
  For i = 1 To move_store_count(thread,movenum)
  If (moves_made(thread,movenum,i)\fromrow=fromrow)And(moves_made(thread,movenum,i)\fromcol=fromcol)And(moves_made(thread,movenum,i)\torow=torow)And(moves_made(thread,movenum,i)\tocol=tocol)
   result=1
   Break
  EndIf 
  Next i
EndIf
ProcedureReturn (result)  
EndProcedure

Procedure Update_board_with_move (thread,board_move, fromx ,fromy,tox,toy,removex,removey)

Board(thread,board_move,fromx,fromy)=1
Board(thread,board_move,removex,removey)=1
Board(thread,board_move,tox,toy)=0
move_store_count(thread,board_move)=move_store_count(thread,board_move)+1
moves_made(thread,board_move,move_store_count(thread,board_move))\fromrow=fromx
moves_made(thread,board_move,move_store_count(thread,board_move))\fromcol=fromy
moves_made(thread,board_move,move_store_count(thread,board_move))\torow=tox
moves_made(thread,board_move,move_store_count(thread,board_move))\tocol=toy
EndProcedure

Procedure Make_move(thread,movenum.b);movenum is the move being made

marble_present=0
move_found=0
;PrintN("inside make_move"+Str(movenum))
For row=0 To 6
For column=0 To 6


;we first check if there is a marble at the given position
If Board(thread,movenum-1,row,column)=0
;we have found a marble, now we look around it
marble_present=1
;PrintN ("marble found")

;we now check the 1+adjacencies for a blank square
;1st we check up and if the move is already made (2 rows up, same col, fromx=row, fromy=col,tox=row-2,toy=col)
If Not((row=0) Or(row=1)) And (move_found=0)
If Board(thread,movenum-1,row-2,column)=1 And Board(thread,movenum-1,row-1,column)=0 And Is_Move_made(thread,movenum,row,column,row-2,column)=0
;vacant spot on top found, we can make a move
;1st we copy the board(movenum-1) To board(movenum)
;PrintN("row=0 or row=1")
Copy_Board(thread,movenum-1,thread,movenum)
;then we change board(movenum) for the move
Update_board_with_move(thread,movenum,row,column,row-2,column,row-1,column)
move_found=1
;done with move
Break 2
EndIf
EndIf
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;if no move found up, we look down and see if the move is already made
;(2 rows down, same col, fromx=row, fromy=col,tox=row+2,toy=col)
If Not((row=5) Or(row=6)) And (move_found=0)
If Board(thread,movenum-1,row+2,column)=1 And Board(thread,movenum-1,row+1,column)=0 And Is_Move_made(thread,movenum,row,column,row+2,column)=0
;vacant spot found below, we can make a move
;1st we copy the board(movenum-1) To board(movenum)
;PrintN("row=5 or row=6")
Copy_Board(thread,movenum-1,thread,movenum)
;then we change board(movenum) for the move
Update_board_with_move(thread,movenum,row,column,row+2,column,row+1,column)
move_found=1
;done with move
Break 2
EndIf
EndIf
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;if no move found up, and down we look left and see if the move is already made
;(same row, 2 cols left, fromx=row, fromy=col,tox=row,toy=col-2)
If Not((column=0) Or(column=1)) And (move_found=0)
If Board(thread,movenum-1,row,column-2)=1 And Board(thread,movenum-1,row,column-1)=0 And Is_Move_made(thread,movenum,row,column,row,column-2)=0
;vacant spot found to the left, we can make a move
;1st we copy the board(movenum-1) To board(movenum)
;PrintN("col=0 or col=1")
Copy_Board(thread,movenum-1,thread,movenum)
;then we change board(movenum) for the move
Update_board_with_move(thread,movenum,row,column,row,column-2,row,column-1)
move_found=1
;done with move
Break 2
EndIf
EndIf
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;if no move found up,down and left we look right and see if the move is already made
;(same row, 2 cols right, fromx=row, fromy=col,tox=row,toy=col+2)
If Not((column=5) Or(column=6)) And (move_found=0)
If Board(thread,movenum-1,row,column+2)=1 And Board(thread,movenum-1,row,column+1)=0 And Is_Move_made(thread,movenum,row,column,row,column+2)=0
;vacant spot found to the right, we can make a move
;1st we copy the board(movenum-1) To board(movenum)
;PrintN("col=5 or col=6")
Copy_Board(thread,movenum-1,thread,movenum)
;then we change board(movenum) for the move
Update_board_with_move(thread,movenum,row,column,row,column+2,row,column+1)
move_found=1
;done with move
Break 2
EndIf
EndIf
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



EndIf;marble_present ends here
marble_present=0
;PrintN(Str(column)+":"+Str(row))
Next column
Next row
;PrintN("Returning from Make_move:"+Str(move_found))
ProcedureReturn move_found

EndProcedure

Procedure Rotate_Board_Clockwise(thread,board)
For col =0 To 6
For row =0 To 6
Board(thread,board,col,6-row)=Board(thread,32,row,col)
Next row
Next col



EndProcedure

Procedure Board_reflect(thread,board)
For col =0 To 6
For row =0 To 6
Board(thread,board,col,6-row)=Board(thread,32,col,row)
Next row
Next col
EndProcedure

Procedure Solve_board(this_thread)
move=1

If (#debug)
PrintN("in "+Str(this_thread))
EndIf
Repeat

If (#debug)
PrintN("move="+Str(move)+" in "+Str(this_thread))
EndIf

If WindowEvent()=#PB_Event_CloseWindow
End
EndIf

If Make_move(this_thread,move)=1

move=move+1
Else

move=Retract_move(this_thread,move,move-1)

EndIf
If (#debug)
PrintN("move="+Str(move)+" in "+Str(this_thread))
EndIf
;SetGadgetText (2, Str(move))
If move=32 
solved=1
solved_thread=this_thread

If(#debug)
PrintN("move="+Str(move)+" in "+Str(this_thread))
EndIf

EndIf

Until solved=1
If (#debug)
PrintN("thread"+Str(this_thread)+"sees solved=1 and solved_thread="+Str(solved_thread))
EndIf

EndProcedure

;;;Main Procedure goes here

OpenWindow(0, 216, 0, 602, 681, "Brainvita",  #PB_Window_TitleBar| #PB_Window_MinimizeGadget )
 ;ShowSunkenBorder( WindowID(0), #True  )
 ;ShowTitlebar   ( WindowID(0), #False )
  ;ShowSmallBorder( WindowID(0), #True  )
;ShowMaximizeButton( WindowID(0), #True )
CreateGadgetList(WindowID(0))



Repeat


For thread=0 To 7
For i = 0 To 32
move_store_count(thread,i)=0
Next i
Next thread

SetWindowColor(0,RGB($FF,$FF,$CC))
newgame_request=0

Board(0,0,0,0)=2
Board(0,0,0,1)=2
Board(0,0,0,2)=0
Board(0,0,0,3)=0
Board(0,0,0,4)=0
Board(0,0,0,5)=2
Board(0,0,0,6)=2

Board(0,0,1,0)=2
Board(0,0,1,1)=2
Board(0,0,1,2)=0
Board(0,0,1,3)=0
Board(0,0,1,4)=0
Board(0,0,1,5)=2
Board(0,0,1,6)=2

Board(0,0,2,0)=0
Board(0,0,2,1)=0
Board(0,0,2,2)=0
Board(0,0,2,3)=0
Board(0,0,2,4)=0
Board(0,0,2,5)=0
Board(0,0,2,6)=0

Board(0,0,3,0)=0
Board(0,0,3,1)=0
Board(0,0,3,2)=0
Board(0,0,3,3)=0
Board(0,0,3,4)=0
Board(0,0,3,5)=0
Board(0,0,3,6)=0

Board(0,0,4,0)=0
Board(0,0,4,1)=0
Board(0,0,4,2)=0
Board(0,0,4,3)=0
Board(0,0,4,4)=0
Board(0,0,4,5)=0
Board(0,0,4,6)=0

Board(0,0,5,0)=2
Board(0,0,5,1)=2
Board(0,0,5,2)=0
Board(0,0,5,3)=0
Board(0,0,5,4)=0
Board(0,0,5,5)=2
Board(0,0,5,6)=2

Board(0,0,6,0)=2
Board(0,0,6,1)=2
Board(0,0,6,2)=0
Board(0,0,6,3)=0
Board(0,0,6,4)=0
Board(0,0,6,5)=2
Board(0,0,6,6)=2

move=0

startx=210
starty=200



ImageGadget(8,startx,starty,210,210,0)
Make_image(0,0)

LoadFont(0, "Arial", 12)
LoadFont(3, "Arial", 12)

SetGadgetFont(#PB_Default, FontID(3))
TextGadget   (7,  210, 610, 190,  20, "Select the empty hole....", #PB_Text_Center)
SetGadgetColor(7,#PB_Gadget_BackColor,RGB($FF,$FF,$CC))
SetGadgetColor(7,#PB_Gadget_FrontColor,RGB($FF,$00,$00))
SetGadgetFont(#PB_Default, FontID(0))
TextGadget(2, 297,540, 30, 20,Str(cnt),#PB_Text_Center)

SetGadgetColor(2,#PB_Gadget_BackColor,RGB($FF,$FF,$CC))
SetGadgetColor(2,#PB_Gadget_FrontColor,RGB($FF,$00,$00))

Draw_window(0,0)
eve=0

Repeat
Event= WaitWindowEvent()

If Event=#PB_Event_CloseWindow
End
EndIf

Select Event
 Case #PB_Event_Gadget
 Select EventGadget()
 Case 8
   Select EventType()
   Case #PB_EventType_LeftClick  
   x=WindowMouseX(0)
   y=WindowMouseY(0) 
       
   If ((x>=210) And (x<=210 +30*7) And (y>=210) And (y<=210+30*7))
 Global  my=(x-210)/30
 Global  mx=(y-210)/30
   
 If Board(0,0,mx,my)=0
  eve=1
 EndIf
EndIf
   EndSelect
EndSelect
EndSelect
Until eve=1



Board(0,0,mx,my)=1
Copy_Board(0,0,0,32)

For thread = 0 To 7
For i = 0 To 32
move_store_count(thread,i)=0
Next i
Next thread


;from here we can start making thread boards

;board 0,32 is already initialized on stack

;thread 1 has board rotated clockwise 1 time
Copy_Board(0,32,1,32)
Copy_Board(0,0,1,0)
Rotate_Board_Clockwise(1,0)
Copy_board(1,0,1,32)

;thread 2 has board rotated clockwise 2 times
Copy_Board(1,32,2,32)
Copy_Board(1,0,2,0)
Rotate_Board_Clockwise(2,0)
Copy_board(2,0,2,32)

;thread 3 has board rotated clockwise 3 times
Copy_Board(2,32,3,32)
Copy_Board(2,0,3,0)
Rotate_Board_Clockwise(3,0)
Copy_board(3,0,3,32)

;thread 4 has board 0 mirrored once
Copy_Board(0,32,4,32)
Copy_Board(0,0,4,0)
Board_reflect(4,0)
Copy_Board(4,0,4,32)

;thread 5 has mirrored board rotated clockwise 1 time
Copy_Board(4,32,5,32)
Copy_Board(4,0,5,0)
Rotate_Board_Clockwise(5,0)
Copy_Board(5,0,5,32)

;thread 6 has mirrored board rotated clockwise 2 time
Copy_Board(5,32,6,32)
Copy_Board(5,0,6,0)
Rotate_Board_Clockwise(6,0)
Copy_Board(6,0,6,32)

;thread 7 has mirrored board rotated clockwise 3 time
Copy_Board(6,32,7,32)
Copy_Board(6,0,7,0)
Rotate_Board_Clockwise(7,0)
Copy_Board(7,0,7,32)


Make_image(0,0)
Draw_window(0,0)
SetGadgetText(7,"calculating")
;

;ProgressBarGadget(6,  240, 600, 190,  30, 0, 32)
;SetGadgetState (6, move)
;For thread=0 To 7
;CreateThread (@Solve_board(),thread)
;Next thread

;Repeat
;Until solved=1

For thread=0 To 7
For i=1 To 31
Copy_Board(thread,0,thread,i)
Next i
Next thread

;For thread=0 To 7
;CreateThread (@Solve_board(),thread)
;Next thread

;If Not((mx=3)And(my=3))
t0=CreateThread(@Solve_board(),0)
ThreadPriority(t0,16)

t1=CreateThread(@Solve_board(),1)
ThreadPriority(t1,16)

t2=CreateThread(@Solve_board(),2)
ThreadPriority(t2,18)

t3=CreateThread(@Solve_board(),3)
ThreadPriority(t3,16)

t4=CreateThread(@Solve_board(),4)
ThreadPriority(t4,16)

t5=CreateThread(@Solve_board(),5)
ThreadPriority(t5,16)

t6=CreateThread(@Solve_board(),6)
ThreadPriority(t6,16)

t7=CreateThread(@Solve_board(),7)
ThreadPriority(t7,16)

;ThreadPriority(CreateThread(@Solve_board(),6),16)
;ThreadPriority(CreateThread(@Solve_board(),7),16)

;Else

;ThreadPriority(CreateThread(@Solve_board(),0),16)
;EndIf



Repeat 
Until solved=1

SetGadgetText(7,"Done! in thread:"+Str(solved_thread))

If solved_thread>3
temp=solved_thread-4
mirrored=1
Else
temp=solved_thread
mirrored=0
EndIf



For i=1 To 4-temp
For j=0 To 31

Copy_board(solved_thread,j,solved_thread,32)
Rotate_Board_Clockwise(solved_thread,j)
Next j
Next i

If mirrored=1
For j=0 To 31
Copy_board(solved_thread,j,solved_thread,32)
Board_reflect(solved_thread,j)
Next j
EndIf

Print_board(solved_thread)

cnt=0
Repeat  

EventID = WaitWindowEvent()

cleareddone=0

If EventID = #PB_Event_Gadget

Select EventGadget()

Case 0

If cnt>0
cnt=cnt-1
Else 
cnt=0
EndIf
If cleareddone=0
FreeGadget(7)
cleareddone=1
EndIf
Draw_window(solved_thread,cnt)

Case 1

If cnt<31
cnt=cnt+1
Else 
cnt=31
EndIf

If cleareddone=0
FreeGadget(7)
cleareddone=1
EndIf

Draw_window(solved_thread,cnt)

Case 3
newgame_request=1

EndSelect
EndIf

Until newgame_request=1 Or EventID = #PB_Event_CloseWindow
FreeGadget(0)
FreeGadget(1)
FreeGadget(3)
solved=0
solved_thread=10

;the program should contiue exectuing unless the previous exit was due to a close window event

Until EventID = #PB_Event_CloseWindow




Posted: Thu Jan 22, 2009 10:49 am
by alokdube
ofcourse the above is a brainless activity considering there are 7 basic solutions but just wanted to see how games work in such and env.

Re: bruteforce peg solitaire (english version) solver

Posted: Wed May 04, 2011 7:44 am
by alokdube
using semaphores instead of waiting for a global to be set, it doesnt really change the exe time much

Code: Select all

;we define the board, 2 is not allowed i.e no space, 1 is no marble, 0 is marble present

Global Dim Board.b(9,32,6,6)
;board 32 is dummy board/stack, the format is board(thread,board,row,col)
Global solved=0
Global solved_thread=10
Global Semaphore = CreateSemaphore()

#debug=0

Structure move_store
fromrow.b
fromcol.b
torow.b
tocol.b
EndStructure


Global Dim moves_made.move_store(9,32,32)
Global Dim move_store_count(9,32)
;the aboves ae per thread

;CreateGadgetList(WindowID(0))

Global startx=210
Global starty=200
Global Dim t(7)

If (#debug)
OpenConsole()
EndIf

Procedure Draw_window(thread,cnt)

SetGadgetState(8,ImageID(cnt))
SetGadgetText(2,Str(cnt))
EndProcedure

Procedure Make_image(thread,m)

CreateImage(m, 210, 210)
StartDrawing(ImageOutput(m))
;BackColor(RGB($FF,$FF,$CC))

FillArea(0,0,RGB($FF,$FF,$CC),RGB($FF,$FF,$CC))


For r=0 To 6
For c =0 To 6



If Not(Board(thread,m,r,c)=2)
DrawingMode(#PB_2DDrawing_Outlined)
;FrontColor(RGB($00,$00,$00))
FrontColor(RGB($FF,$FF,$CC))
Box(30*c, 30*r, 30, 30)
DrawingMode(#PB_2DDrawing_Default)

If Board(thread,m,r,c)=1
Circle(30*c+15,30*r+15,10,RGB($FF,$CC,$FF))
EndIf

If Board(thread,m,r,c)=0
Circle(30*c+15,30*r+15,10,RGB($FF,$00,$00))
EndIf

EndIf

Next c
Next r
StopDrawing()


EndProcedure

Procedure Print_board(thread)

For m=0 To 31
Make_image(thread,m)
;Delay(2000)
Next m
LoadFont(4, "Arial", 9)
SetGadgetFont(#PB_Default, FontID(4))
ButtonGadget(0,20,20,30,30,"<<")
ButtonGadget(1,550,20,30,30,">>")
ButtonGadget(3,285,20,40,30,"New")
Draw_window(thread,0)
SetGadgetFont(#PB_Default, FontID(0))

EndProcedure

Procedure Copy_board (thread_from,board_from, thread_to,board_to)

For i=0 To 6
For j=0 To 6
Board(thread_to,board_to,i,j)=Board(thread_from,board_from,i,j)
Next j
Next i
EndProcedure


;the above array is of the form : move_num , move_stack
;move number is the actual board move and the stack contains upto 30 moves already made in this movenum
;the moves_store_count keeps track of the number of moves in the stack

;the algo is as follows:
;at each move apply a mask to find a marble with empty adjacency.
;once u reach 30 moves, check how many are left... 
;if at any stage no move to make
;backtrack
;at each move fill the moves_made(movenum)\fromx.fromy,tox,toy
;keep going till one marble left at move 30


;This procedure Brings the board back to the given move num (enter the present movenum too)
;it adjusts all other boards,move,moves_store_count to reflect the game at to_move_num

Procedure Retract_move(thread,from_move_num,to_move_num)

move=to_move_num
For i = to_move_num+1 To from_move_num
move_store_count(thread,i)=0
Copy_board(thread,0,thread,i)
Next i
ProcedureReturn move
EndProcedure

Procedure Is_Move_made(thread,movenum,fromrow,fromcol,torow,tocol);check if the move is already made

result=0
If Not(move_store_count(thread,movenum)=0); if there is any move already registered in the store
  For i = 1 To move_store_count(thread,movenum)
  If (moves_made(thread,movenum,i)\fromrow=fromrow)And(moves_made(thread,movenum,i)\fromcol=fromcol)And(moves_made(thread,movenum,i)\torow=torow)And(moves_made(thread,movenum,i)\tocol=tocol)
   result=1
   Break
  EndIf 
  Next i
EndIf
ProcedureReturn (result)  
EndProcedure

Procedure Update_board_with_move (thread,board_move, fromx ,fromy,tox,toy,removex,removey)

Board(thread,board_move,fromx,fromy)=1
Board(thread,board_move,removex,removey)=1
Board(thread,board_move,tox,toy)=0
move_store_count(thread,board_move)=move_store_count(thread,board_move)+1
moves_made(thread,board_move,move_store_count(thread,board_move))\fromrow=fromx
moves_made(thread,board_move,move_store_count(thread,board_move))\fromcol=fromy
moves_made(thread,board_move,move_store_count(thread,board_move))\torow=tox
moves_made(thread,board_move,move_store_count(thread,board_move))\tocol=toy
EndProcedure

Procedure Make_move(thread,movenum.b);movenum is the move being made

marble_present=0
move_found=0
;PrintN("inside make_move"+Str(movenum))
For row=0 To 6
For column=0 To 6


;we first check if there is a marble at the given position
If Board(thread,movenum-1,row,column)=0
;we have found a marble, now we look around it
marble_present=1
;PrintN ("marble found")

;we now check the 1+adjacencies for a blank square
;1st we check up and if the move is already made (2 rows up, same col, fromx=row, fromy=col,tox=row-2,toy=col)
If Not((row=0) Or(row=1)) And (move_found=0)
If Board(thread,movenum-1,row-2,column)=1 And Board(thread,movenum-1,row-1,column)=0 And Is_Move_made(thread,movenum,row,column,row-2,column)=0
;vacant spot on top found, we can make a move
;1st we copy the board(movenum-1) To board(movenum)
;PrintN("row=0 or row=1")
Copy_Board(thread,movenum-1,thread,movenum)
;then we change board(movenum) for the move
Update_board_with_move(thread,movenum,row,column,row-2,column,row-1,column)
move_found=1
;done with move
Break 2
EndIf
EndIf
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;if no move found up, we look down and see if the move is already made
;(2 rows down, same col, fromx=row, fromy=col,tox=row+2,toy=col)
If Not((row=5) Or(row=6)) And (move_found=0)
If Board(thread,movenum-1,row+2,column)=1 And Board(thread,movenum-1,row+1,column)=0 And Is_Move_made(thread,movenum,row,column,row+2,column)=0
;vacant spot found below, we can make a move
;1st we copy the board(movenum-1) To board(movenum)
;PrintN("row=5 or row=6")
Copy_Board(thread,movenum-1,thread,movenum)
;then we change board(movenum) for the move
Update_board_with_move(thread,movenum,row,column,row+2,column,row+1,column)
move_found=1
;done with move
Break 2
EndIf
EndIf
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;if no move found up, and down we look left and see if the move is already made
;(same row, 2 cols left, fromx=row, fromy=col,tox=row,toy=col-2)
If Not((column=0) Or(column=1)) And (move_found=0)
If Board(thread,movenum-1,row,column-2)=1 And Board(thread,movenum-1,row,column-1)=0 And Is_Move_made(thread,movenum,row,column,row,column-2)=0
;vacant spot found to the left, we can make a move
;1st we copy the board(movenum-1) To board(movenum)
;PrintN("col=0 or col=1")
Copy_Board(thread,movenum-1,thread,movenum)
;then we change board(movenum) for the move
Update_board_with_move(thread,movenum,row,column,row,column-2,row,column-1)
move_found=1
;done with move
Break 2
EndIf
EndIf
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;if no move found up,down and left we look right and see if the move is already made
;(same row, 2 cols right, fromx=row, fromy=col,tox=row,toy=col+2)
If Not((column=5) Or(column=6)) And (move_found=0)
If Board(thread,movenum-1,row,column+2)=1 And Board(thread,movenum-1,row,column+1)=0 And Is_Move_made(thread,movenum,row,column,row,column+2)=0
;vacant spot found to the right, we can make a move
;1st we copy the board(movenum-1) To board(movenum)
;PrintN("col=5 or col=6")
Copy_Board(thread,movenum-1,thread,movenum)
;then we change board(movenum) for the move
Update_board_with_move(thread,movenum,row,column,row,column+2,row,column+1)
move_found=1
;done with move
Break 2
EndIf
EndIf
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



EndIf;marble_present ends here
marble_present=0
;PrintN(Str(column)+":"+Str(row))
Next column
Next row
;PrintN("Returning from Make_move:"+Str(move_found))
ProcedureReturn move_found

EndProcedure

Procedure Rotate_Board_Clockwise(thread,board)
For col =0 To 6
For row =0 To 6
Board(thread,board,col,6-row)=Board(thread,32,row,col)
Next row
Next col



EndProcedure

Procedure Board_reflect(thread,board)
For col =0 To 6
For row =0 To 6
Board(thread,board,col,6-row)=Board(thread,32,col,row)
Next row
Next col
EndProcedure

Procedure Solve_board(this_thread)
move=1

If (#debug)
PrintN("in "+Str(this_thread))
EndIf
Repeat

If (#debug)
PrintN("move="+Str(move)+" in "+Str(this_thread))
EndIf

If WindowEvent()=#PB_Event_CloseWindow
End
EndIf

If Make_move(this_thread,move)=1

move=move+1
Else

move=Retract_move(this_thread,move,move-1)

EndIf
If (#debug)
PrintN("move="+Str(move)+" in "+Str(this_thread))
EndIf
;SetGadgetText (2, Str(move))
If move=32 
solved=1
solved_thread=this_thread
SignalSemaphore(Semaphore)


If(#debug)
PrintN("move="+Str(move)+" in "+Str(this_thread))
EndIf

EndIf

Until solved=1
If (#debug)
PrintN("thread"+Str(this_thread)+"sees solved=1 and solved_thread="+Str(solved_thread))
EndIf

EndProcedure

;;;Main Procedure goes here

OpenWindow(0, 216, 0, 602, 681, "Brainvita",  #PB_Window_BorderLess|#PB_Window_TitleBar| #PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget )
 ;ShowSunkenBorder( WindowID(0), #True  )
 ;ShowTitlebar   ( WindowID(0), #False )
  ;ShowSmallBorder( WindowID(0), #True  )
;ShowMaximizeButton( WindowID(0), #True )
;CreateGadgetList(WindowID(0))



Repeat


For thread=0 To 7
For i = 0 To 32
move_store_count(thread,i)=0
Next i
Next thread

SetWindowColor(0,RGB($FF,$FF,$CC))
newgame_request=0

Board(0,0,0,0)=2
Board(0,0,0,1)=2
Board(0,0,0,2)=0
Board(0,0,0,3)=0
Board(0,0,0,4)=0
Board(0,0,0,5)=2
Board(0,0,0,6)=2

Board(0,0,1,0)=2
Board(0,0,1,1)=2
Board(0,0,1,2)=0
Board(0,0,1,3)=0
Board(0,0,1,4)=0
Board(0,0,1,5)=2
Board(0,0,1,6)=2

Board(0,0,2,0)=0
Board(0,0,2,1)=0
Board(0,0,2,2)=0
Board(0,0,2,3)=0
Board(0,0,2,4)=0
Board(0,0,2,5)=0
Board(0,0,2,6)=0

Board(0,0,3,0)=0
Board(0,0,3,1)=0
Board(0,0,3,2)=0
Board(0,0,3,3)=0
Board(0,0,3,4)=0
Board(0,0,3,5)=0
Board(0,0,3,6)=0

Board(0,0,4,0)=0
Board(0,0,4,1)=0
Board(0,0,4,2)=0
Board(0,0,4,3)=0
Board(0,0,4,4)=0
Board(0,0,4,5)=0
Board(0,0,4,6)=0

Board(0,0,5,0)=2
Board(0,0,5,1)=2
Board(0,0,5,2)=0
Board(0,0,5,3)=0
Board(0,0,5,4)=0
Board(0,0,5,5)=2
Board(0,0,5,6)=2

Board(0,0,6,0)=2
Board(0,0,6,1)=2
Board(0,0,6,2)=0
Board(0,0,6,3)=0
Board(0,0,6,4)=0
Board(0,0,6,5)=2
Board(0,0,6,6)=2

move=0

startx=210
starty=200



ImageGadget(8,startx,starty,210,210,0)
Make_image(0,0)

LoadFont(0, "Arial", 12)
LoadFont(3, "Arial", 12)

SetGadgetFont(#PB_Default, FontID(3))
TextGadget   (7,  210, 610, 190,  20, "Select the empty hole....", #PB_Text_Center)
SetGadgetColor(7,#PB_Gadget_BackColor,RGB($FF,$FF,$CC))
SetGadgetColor(7,#PB_Gadget_FrontColor,RGB($FF,$00,$00))
SetGadgetFont(#PB_Default, FontID(0))
TextGadget(2, 297,540, 30, 20,Str(cnt),#PB_Text_Center)

SetGadgetColor(2,#PB_Gadget_BackColor,RGB($FF,$FF,$CC))
SetGadgetColor(2,#PB_Gadget_FrontColor,RGB($FF,$00,$00))

Draw_window(0,0)
eve=0

Repeat
Event= WaitWindowEvent()

If Event=#PB_Event_CloseWindow
End
EndIf

Select Event
 Case #PB_Event_Gadget
 Select EventGadget()
 Case 8
   Select EventType()
   Case #PB_EventType_LeftClick  
   x=WindowMouseX(0)
   y=WindowMouseY(0) 
       
   If ((x>=210) And (x<=210 +30*7) And (y>=210) And (y<=210+30*7))
 Global  my=(x-210)/30
 Global  mx=(y-210)/30
   
 If Board(0,0,mx,my)=0
  eve=1
 EndIf
EndIf
   EndSelect
EndSelect
EndSelect
Until eve=1



Board(0,0,mx,my)=1
Copy_Board(0,0,0,32)

For thread = 0 To 7
For i = 0 To 32
move_store_count(thread,i)=0
Next i
Next thread


;from here we can start making thread boards

;board 0,32 is already initialized on stack

;thread 1 has board rotated clockwise 1 time
Copy_Board(0,32,1,32)
Copy_Board(0,0,1,0)
Rotate_Board_Clockwise(1,0)
Copy_board(1,0,1,32)

;thread 2 has board rotated clockwise 2 times
Copy_Board(1,32,2,32)
Copy_Board(1,0,2,0)
Rotate_Board_Clockwise(2,0)
Copy_board(2,0,2,32)

;thread 3 has board rotated clockwise 3 times
Copy_Board(2,32,3,32)
Copy_Board(2,0,3,0)
Rotate_Board_Clockwise(3,0)
Copy_board(3,0,3,32)

;thread 4 has board 0 mirrored once
Copy_Board(0,32,4,32)
Copy_Board(0,0,4,0)
Board_reflect(4,0)
Copy_Board(4,0,4,32)

;thread 5 has mirrored board rotated clockwise 1 time
Copy_Board(4,32,5,32)
Copy_Board(4,0,5,0)
Rotate_Board_Clockwise(5,0)
Copy_Board(5,0,5,32)

;thread 6 has mirrored board rotated clockwise 2 time
Copy_Board(5,32,6,32)
Copy_Board(5,0,6,0)
Rotate_Board_Clockwise(6,0)
Copy_Board(6,0,6,32)

;thread 7 has mirrored board rotated clockwise 3 time
Copy_Board(6,32,7,32)
Copy_Board(6,0,7,0)
Rotate_Board_Clockwise(7,0)
Copy_Board(7,0,7,32)


Make_image(0,0)
Draw_window(0,0)
SetGadgetText(7,"calculating")
SetCursor_(LoadCursor_(0,#IDC_WAIT))
;

;ProgressBarGadget(6,  240, 600, 190,  30, 0, 32)
;SetGadgetState (6, move)
;For thread=0 To 7
;CreateThread (@Solve_board(),thread)
;Next thread

;Repeat
;Until solved=1

For thread=0 To 7
For i=1 To 31
Copy_Board(thread,0,thread,i)
Next i
Next thread

;For thread=0 To 7
;CreateThread (@Solve_board(),thread)
;Next thread

;If Not((mx=3)And(my=3))

t(0)=CreateThread(@Solve_board(),0)
ThreadPriority(t(0),16)

t(1)=CreateThread(@Solve_board(),1)
ThreadPriority(t(1),16)

t(2)=CreateThread(@Solve_board(),2)
ThreadPriority(t(2),18)

t(3)=CreateThread(@Solve_board(),3)
ThreadPriority(t(3),16)

t(4)=CreateThread(@Solve_board(),4)
ThreadPriority(t(4),16)

t(5)=CreateThread(@Solve_board(),5)
ThreadPriority(t(5),16)

t(6)=CreateThread(@Solve_board(),6)
ThreadPriority(t(6),16)

t(7)=CreateThread(@Solve_board(),7)
ThreadPriority(t(7),16)

;ThreadPriority(CreateThread(@Solve_board(),6),16)
;ThreadPriority(CreateThread(@Solve_board(),7),16)

;Else

;ThreadPriority(CreateThread(@Solve_board(),0),16)
;EndIf


WaitSemaphore(Semaphore)

;if here solved=1
For i=0 To 7
If IsThread(t(i))
KillThread(t(i))
EndIf
Next i

SetGadgetText(7,"Done! in thread:"+Str(solved_thread))

If solved_thread>3
temp=solved_thread-4
mirrored=1
Else
temp=solved_thread
mirrored=0
EndIf



For i=1 To 4-temp
For j=0 To 31
Copy_board(solved_thread,j,solved_thread,32)
Rotate_Board_Clockwise(solved_thread,j)
Next j
Next i

If mirrored=1
For j=0 To 31
Copy_board(solved_thread,j,solved_thread,32)
Board_reflect(solved_thread,j)
Next j
EndIf

Print_board(solved_thread)

cnt=0
Repeat  

EventID = WaitWindowEvent()

cleareddone=0

If EventID = #PB_Event_Gadget

Select EventGadget()

Case 0

If cnt>0
cnt=cnt-1
Else 
cnt=0
EndIf
If cleareddone=0
FreeGadget(7)
cleareddone=1
EndIf
Draw_window(solved_thread,cnt)

Case 1

If cnt<31
cnt=cnt+1
Else 
cnt=31
EndIf

If cleareddone=0
FreeGadget(7)
cleareddone=1
EndIf

Draw_window(solved_thread,cnt)

Case 3
newgame_request=1

EndSelect
EndIf

Until newgame_request=1 Or EventID = #PB_Event_CloseWindow
FreeGadget(0)
FreeGadget(1)
FreeGadget(3)
solved=0
solved_thread=10

;the program should contiue exectuing unless the previous exit was due to a close window event

Until EventID = #PB_Event_CloseWindow