PureMondrian

Applications, Games, Tools, User libs and useful stuff coded in PureBasic
User avatar
jacdelad
Addict
Addict
Posts: 2010
Joined: Wed Feb 03, 2021 12:46 pm
Location: Riesa

PureMondrian

Post by jacdelad »

Hi #PB_All,
I want to show you my first real game, PureMondrian (thank me later that I never released my really first game!).
Image

Background: I love board games and have a very huge collection (about 2100, mostly rare and historical editions) but I also love small, quick games, as long as it has strictly defined rules; e.g. logic games and such. My parents gifted me Mondrian Blocks (https://www.google.com/search?q=mondria ... UTF-8#ip=1), which is nice to play on the easy modes, but really hard on the harder ones. The game itself is based on the art of Piet Mondrian. Now, I played it a lot but couldn't solve the hardest ones. So naturally I programmed a solver (to my surprise, really all riddles that come with the game are solvable). It was only logical to also rebuild the game.

Personal background: I recently quit my job, but still have to work until the end of octobre in this sh**hole, because they won't let me go earlier ("See how important you are?" - Yeah, I wish they would have shown earlier...). So now I extend my breaks and only do the bare minimum in hope they will fire me earlier. This led to a lot of time while working, which was the opportunity to make this game.

Content: 88 riddles in 4 difficulties for you to solve. Plus an auto-solver (the solutions are not built-in, they are calculated! This game should work on all platforms, but I only tested Windows 10/11 x64 with PureBasic 6.11 x64. Compile it with DPI-Aware OFF!

Some legal stuff: I'm not good at this, so I'll make it short. I explicitely allow to modify the code for personal use, but not for releasing it anywhere, except this thread. You may also put a compiled version of the original code created by me wherever you want, as long as you add a note to this thread and my creatorship. In all cases: You are explicitely NOT allowed to make any kind of money or donation or whatever with this!

How to play: Put all shapes into the square. No overlapping, of course. The black ones are fixed, accoring to the task. Drag the tiles, right click while dragging to rotate it, right click on a plced tile to remove it.

Code: Select all

;PureMondrian 1.0 by Jac de Lad
EnableExplicit

Enumeration Window
  #MainWindow
EndEnumeration
Enumeration Gadget
  #Canvas
  #List
  #SolveButton
  #InfoButton
  #Difficulty
  #Language
EndEnumeration

Structure Occupied
  X.a
  Y.a
  EX.a
  EY.a
EndStructure

Structure MPos
  X.a
  Y.a
  Rot.a
  EX.a
  EY.a
EndStructure

Structure Tile
  X.a
  Y.a
  InitX.a
  InitY.a
  NowX.b
  NowY.a
  NowRot.a
  Color.l
  Fixed.a
  DragX.w
  DragY.w
  DragW.w
  DragH.w
  DragRot.a
  RPosition.a
  List Position.MPos()
EndStructure

Structure XY
  X.a
  Y.a
EndStructure

Structure Task
  Difficulty.a
  Tile1X.a
  Tile1Y.a
  Tile2X.a
  Tile2Y.a
  Tile2R.a
  Tile3X.a
  Tile3Y.a
  Tile3R.a
  Image.i
EndStructure

Global Dim Field.a(7,7),NewList Tiles.Tile(),NewList PositionMatrix.MPos(),Thread.i,NewList Tasks.Task(),Background.l,Language.a,DragTile.b=-1,MX.w,MY.w,X.w,Y.w,Solved.a=#True,NoDrop.a

Procedure Draw(Mode)
  Protected PL.a,MX.w,MY.w
  Protected X.w,Y.w,W.w,H.w,PX.w,PY.w,PEX.w,PEY.w
  StartDrawing(CanvasOutput(#Canvas))
  Box(0,0,OutputWidth(),OutputHeight(),Background)
  If Not mode
    For X=1 To 9
      Line(40*X,40,1,320,#Green)
      Line(40,40*X-1,320,1,#Green)
    Next
  EndIf
  ForEach Tiles()
    If Not Mode
      FirstElement(Tiles()\Position())
    EndIf
    If Mode Or Tiles()\Fixed
      Box(41+40*Tiles()\Position()\X,41+40*Tiles()\Position()\Y,40*(Tiles()\Position()\EX-Tiles()\Position()\X+1)-2,40*(Tiles()\Position()\EY-Tiles()\Position()\Y+1)-2,Tiles()\Color)
    EndIf
    If Not Mode And Not Tiles()\Fixed
      If Tiles()\NowX=-1
        If DragTile=ListIndex(Tiles())
          PushListPosition(Tiles())
          PL=#True
        Else
          Box(Tiles()\DragX,Tiles()\DragY,Tiles()\DragW,Tiles()\DragH,Tiles()\Color)
        EndIf
      Else
        If Tiles()\NowRot
          Box(41+40*Tiles()\NowX,41+40*Tiles()\NowY,40*Tiles()\Y-2,40*Tiles()\X-2,Tiles()\Color)
        Else
          Box(41+40*Tiles()\NowX,41+40*Tiles()\NowY,40*Tiles()\X-2,40*Tiles()\Y-2,Tiles()\Color)
        EndIf
      EndIf
    EndIf
  Next
  If PL
    PopListPosition(Tiles())
    MX=WindowMouseX(#MainWindow)
    MY=WindowMouseY(#MainWindow)
    If Tiles()\DragRot
      X=MX-0.8*Tiles()\DragH
      Y=MY-0.8*Tiles()\DragW
      W=Tiles()\DragH*1.6
      H=Tiles()\DragW*1.6
    Else
      X=MX-0.8*Tiles()\DragW
      Y=MY-0.8*Tiles()\DragH
      W=Tiles()\DragW*1.6
      H=Tiles()\DragH*1.6
    EndIf
    
    PX=Round((X-41)/40,#PB_Round_Nearest)
    PY=Round((Y-41)/40,#PB_Round_Nearest)
    PEX=PX+Round((W-41)/40,#PB_Round_Nearest)
    PEY=PY+Round((H-41)/40,#PB_Round_Nearest)
    NoDrop=#False
    
    If PX<0 Or PY<0 Or PEX>7 Or PEY>7
      NoDrop=#True
    Else
      For MX=PX To PEX
        For MY=PY To PEY
          If Field(MX,MY)>0
            NoDrop=#True
            Break
          EndIf
        Next
      Next
      
    EndIf
    
    If NoDrop
      Box(X,Y,W,H,#Gray)
    Else
      Box(X,Y,W,H,#Green)
    EndIf
  EndIf
  StopDrawing()
EndProcedure

Macro CreateTile(MyX,MyY,MyInitX,MyInitY,MyColor,MyFixed=#False)
  AddElement(Tiles())
  Tiles()\X=MyX
  Tiles()\Y=MyY
  Tiles()\InitX=MyInitX
  Tiles()\InitY=MyInitY
  Tiles()\Color=MyColor
  Tiles()\Fixed=MyFixed
EndMacro
CreateTile(1,1,0,0,#Black,#True)
CreateTile(2,1,0,0,#Black,#True)
CreateTile(3,1,0,0,#Black,#True)
CreateTile(4,3,6,3,#Blue)
CreateTile(3,3,3,3,#White)
CreateTile(5,2,6,1,#Red)
CreateTile(4,2,2,1,#White)
CreateTile(3,2,0,3,#Red)
CreateTile(2,2,0,1,#White)
CreateTile(5,1,0,0,#Yellow)
CreateTile(4,1,5,0,#Yellow)

Procedure Solve()
  Protected X.a,Y.a,*Pos.Tile,*MPos.MPos,NewList Locked.XY(),Position.w,Del.a,NewList Occupied.Tile(),Dim Field.a(7,7),Done.a,error.a
  
  ;Teilematrix erstellen
  ForEach Tiles()
    If Not Tiles()\Fixed
      ClearList(Tiles()\Position())
      Tiles()\RPosition=0
      For X=0 To 7
        For Y=0 To 7
          If X+Tiles()\X<=8 And Y+Tiles()\Y<=8
            AddElement(Tiles()\Position())
            Tiles()\Position()\X=X
            Tiles()\Position()\Y=Y
            Tiles()\Position()\Rot=0
          EndIf
          If Tiles()\X<>Tiles()\Y And X+Tiles()\Y<=8 And Y+Tiles()\X<=8
            AddElement(Tiles()\Position())
            Tiles()\Position()\X=X
            Tiles()\Position()\Y=Y
            Tiles()\Position()\Rot=1
          EndIf
        Next
      Next
    EndIf
  Next
  
  ;Gesperrte Positionen ermitteln
  ForEach Tiles()
    If Tiles()\Fixed
      ForEach Tiles()\Position()
        If Tiles()\Position()\Rot
          For X=0 To Tiles()\Y-1
            For Y=0 To Tiles()\X-1
              AddElement(Locked())
              Locked()\X=Tiles()\Position()\X+X
              Locked()\Y=Tiles()\Position()\Y+Y
            Next  
          Next
          ;           Tiles()\Position()\EX=Tiles()\Position()\X+Tiles()\Y-1
          ;           Tiles()\Position()\EY=Tiles()\Position()\Y+Tiles()\X-1
        Else
          For X=0 To Tiles()\X-1
            For Y=0 To Tiles()\Y-1
              AddElement(Locked())
              Locked()\X=Tiles()\Position()\X+X
              Locked()\Y=Tiles()\Position()\Y+Y
            Next  
          Next  
          ;           Tiles()\Position()\EX=Tiles()\Position()\X+Tiles()\X-1
          ;           Tiles()\Position()\EY=Tiles()\Position()\Y+Tiles()\Y-1
        EndIf
      Next
    EndIf
  Next
  
  ;Teilematrix ausdünnen
  ForEach Tiles()
    If Not Tiles()\Fixed
      Position=ListSize(Tiles()\Position())-1
      Repeat
        SelectElement(Tiles()\Position(),Position)
        Del=#False
        ForEach Locked()
          If Tiles()\Position()\Rot
            If Locked()\X>=Tiles()\Position()\X And Locked()\X<Tiles()\Position()\X+Tiles()\Y And Locked()\Y>=Tiles()\Position()\Y And Locked()\Y<Tiles()\Position()\Y+Tiles()\X
              DeleteElement(Tiles()\Position(),1)
              Del=#True
              Break
            EndIf
          Else
            If Locked()\X>=Tiles()\Position()\X And Locked()\X<Tiles()\Position()\X+Tiles()\X And Locked()\Y>=Tiles()\Position()\Y And Locked()\Y<Tiles()\Position()\Y+Tiles()\Y
              DeleteElement(Tiles()\Position(),1)
              Del=#True
              Break
            EndIf
          EndIf
        Next
        If Not Del
          If Tiles()\Position()\Rot
            Tiles()\Position()\EX=Tiles()\Position()\X+Tiles()\Y-1
            Tiles()\Position()\EY=Tiles()\Position()\Y+Tiles()\X-1
          Else
            Tiles()\Position()\EX=Tiles()\Position()\X+Tiles()\X-1
            Tiles()\Position()\EY=Tiles()\Position()\Y+Tiles()\Y-1
          EndIf
        EndIf
        Position-1
      Until Position<0
    EndIf
  Next
  
  ;Brute-Force-Placement-Attacke
  Protected Count.q
  
  Repeat
    
    ;Teile prüfen
    FreeArray(Field())
    Dim Field(7,7)
    Done=#True
    ForEach Tiles()
      If Not Tiles()\Fixed
        SelectElement(Tiles()\Position(),Tiles()\RPosition)
        For X=Tiles()\Position()\X To Tiles()\Position()\EX
          For Y=Tiles()\Position()\Y To Tiles()\Position()\EY
            If Field(X,Y)
              Done=#False
              Break 3
            Else
              Field(X,Y)=1
            EndIf
          Next
        Next
      EndIf
    Next  
    
    If Done
      Break
    EndIf
    
    Tiles()\RPosition+1
    Repeat
      If Tiles()\RPosition>=ListSize(Tiles()\Position())
        Tiles()\RPosition=0
        If PreviousElement(Tiles())
          Tiles()\RPosition+1
        Else
          If Language
            MessageRequester("Error","There was no solution found!",#PB_MessageRequester_Error)
          Else
            MessageRequester("Fehler","Es konnte keine Lösung gefunden werden!",#PB_MessageRequester_Error)
          EndIf
          error=#True
          Break 2
        EndIf
      Else
        Break
      EndIf
    ForEver
    Count+1
    
  ForEver
  
  If Not error
    Solved=#True
    Draw(#True)
    DisableGadget(#SolveButton,#True)
  EndIf
  
EndProcedure

Procedure LoadList(Difficulty)
  ClearGadgetItems(#List)
  ForEach Tasks()
    If Tasks()\Difficulty=Difficulty
      If Language
        AddGadgetItem(#List,-1,"Riddle "+Str(ListIndex(Tasks())+1),ImageID(Tasks()\Image))
      Else
        AddGadgetItem(#List,-1,"Rätsel "+Str(ListIndex(Tasks())+1),ImageID(Tasks()\Image))
      EndIf
    EndIf
    SetGadgetItemData(#List,CountGadgetItems(#List)-1,@Tasks())
  Next
  StartDrawing(CanvasOutput(#Canvas))
  Box(0,0,400,400,Background)
  StopDrawing()
  DisableGadget(#SolveButton,#True)
EndProcedure

Procedure LoadTasks()
  Protected *Mem=?Tasks,Size.a=4
  Repeat
    AddElement(Tasks())
    Tasks()\Difficulty=PeekA(*Mem)
    Tasks()\Tile1X=PeekA(*Mem+1)
    Tasks()\Tile1Y=PeekA(*Mem+2)
    Tasks()\Tile2X=PeekA(*Mem+3)
    Tasks()\Tile2Y=PeekA(*Mem+4)
    Tasks()\Tile2R=PeekA(*Mem+5)
    Tasks()\Tile3X=PeekA(*Mem+6)
    Tasks()\Tile3Y=PeekA(*Mem+7)
    Tasks()\Tile3R=PeekA(*Mem+8)
    Tasks()\Image=CreateImage(#PB_Any,8*Size+4,8*Size+4,24,#Green)
    StartDrawing(ImageOutput(Tasks()\Image))
    Box(2,2,8*Size,8*Size,Background)
    Box(2+Tasks()\Tile1X*Size,2+Tasks()\Tile1Y*Size,Size,Size,#Black)
    If Tasks()\Tile2R
      Box(2+Tasks()\Tile2X*Size,2+Tasks()\Tile2Y*Size,Size,Size*2,#Black)
    Else
      Box(2+Tasks()\Tile2X*Size,2+Tasks()\Tile2Y*Size,Size*2,Size,#Black)
    EndIf
    If Tasks()\Tile3R
      Box(2+Tasks()\Tile3X*Size,2+Tasks()\Tile3Y*Size,Size,Size*3,#Black)
    Else
      Box(2+Tasks()\Tile3X*Size,2+Tasks()\Tile3Y*Size,Size*3,Size,#Black)
    EndIf
    StopDrawing()
    *Mem+9
  Until *Mem>=?TasksEnd
EndProcedure

Procedure LoadTask(Task)
  Protected X.a
  ForEach Tiles()
    ClearList(Tiles()\Position())
  Next
  ChangeCurrentElement(Tasks(),Task)
  FirstElement(Tiles())
  AddElement(Tiles()\Position())
  Tiles()\Position()\X=Tasks()\Tile1X
  Tiles()\Position()\Y=Tasks()\Tile1Y
  NextElement(Tiles())
  AddElement(Tiles()\Position())
  Tiles()\Position()\X=Tasks()\Tile2X
  Tiles()\Position()\Y=Tasks()\Tile2Y
  Tiles()\Position()\Rot=Tasks()\Tile2R
  NextElement(Tiles())
  AddElement(Tiles()\Position())
  Tiles()\Position()\X=Tasks()\Tile3X
  Tiles()\Position()\Y=Tasks()\Tile3Y
  Tiles()\Position()\Rot=Tasks()\Tile3R
  FreeArray(Field())
  Dim Field(7,7)
  ForEach Tiles()
    If Tiles()\Fixed
      ForEach Tiles()\Position()
        If Tiles()\Position()\Rot
          Tiles()\Position()\EX=Tiles()\Position()\X+Tiles()\Y-1
          Tiles()\Position()\EY=Tiles()\Position()\Y+Tiles()\X-1
          For X=1 To Tiles()\X
            Field(Tiles()\Position()\X,Tiles()\Position()\Y+X-1)=1
          Next
        Else
          Tiles()\Position()\EX=Tiles()\Position()\X+Tiles()\X-1
          Tiles()\Position()\EY=Tiles()\Position()\Y+Tiles()\Y-1
          For X=1 To Tiles()\X
            Field(Tiles()\Position()\X+X-1,Tiles()\Position()\Y)=1
          Next
        EndIf
      Next
    Else
      Tiles()\NowX=-1
      Tiles()\NowRot=0
      Tiles()\DragRot=0
      Tiles()\DragX=41+30*Tiles()\InitX
      Tiles()\DragY=401+30*Tiles()\InitY
      Tiles()\DragW=25*Tiles()\X-2
      Tiles()\DragH=25*Tiles()\Y-2
    EndIf
  Next
  Solved=#False
EndProcedure

OpenWindow(#MainWindow,0,0,700,630,"PureMondrian",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
CompilerIf #PB_Compiler_OS=#PB_OS_Windows
  Background.l=GetSysColor_(#COLOR_BTNFACE)
CompilerElse
  StartDrawing(WindowOutput(#MainWindow))
  Background=Point(0,0)
  StopDrawing()
CompilerEndIf
SetGadgetFont(#PB_Default,FontID(LoadFont(#PB_Any,"Verdana",10,#PB_Font_HighQuality)))
CanvasGadget(#Canvas,0,0,400,600,#PB_Canvas_ClipMouse)
StartDrawing(CanvasOutput(#Canvas))
Box(0,0,OutputWidth(),OutputHeight(),Background)
StopDrawing()
ListIconGadget(#List,400,0,300,600,"Riddle",180,#PB_ListIcon_AlwaysShowSelection|#PB_ListIcon_FullRowSelect|#PB_ListIcon_GridLines)
SetGadgetAttribute(#List, #PB_ListIcon_DisplayMode, #PB_ListIcon_LargeIcon)
ComboBoxGadget(#Difficulty,400,600,200,30)
AddGadgetItem(#Difficulty,-1,"Einfach")
AddGadgetItem(#Difficulty,-1,"Mittel")
AddGadgetItem(#Difficulty,-1,"Schwer")
AddGadgetItem(#Difficulty,-1,"Meister")
SetGadgetState(#Difficulty,0)
ButtonGadget(#Language,600,600,100,30,"Sprache")
ButtonGadget(#InfoButton,0,600,100,30,"Info")
ButtonGadget(#SolveButton,150,600,100,30,"Lösen")
DisableGadget(#SolveButton,#True)
LoadTasks()
LoadList(0)

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
    Case #PB_Event_Gadget
      Select EventType()
        Case #PB_EventType_LeftClick
          Select EventGadget()
            Case #InfoButton
              If Language
                MessageRequester("Information",~"PureMondrian\r\nby Jac de Lad\r\n\r\nHow to play:\r\nSelect a riddle. Drag and drop the tiles to build a 8x8-square; the black pieces are locked. While moving a part, rotate it with the right mouse button. Remove a placed tile with a right click on it.\r\n\r\nIn case of despair, use the solve button.",#PB_MessageRequester_Info)
              Else
                MessageRequester("Information",~"PureMondrian\r\nby Jac de Lad\r\n\r\nSpielanleitung:\r\nWähle ein Rätsel. Ziehe die Teile auf das 8x8-Quadrat; die schwarzen Teile sind vorgegeben. Während des Ziehens kann ein Teil mit der rechten Maustaste gedreht werden. Klicken sie mit rechts auf ein bereits platziertes Teil, um es zu entfernen.\r\n\r\nSollten sie verzweifeln, nutzen sie den Lösungsbutton.",#PB_MessageRequester_Info)
              EndIf
            Case #SolveButton
              Solve()
            Case #Language
              Language=1-Language
              If Language
                SetGadgetText(#Language,"Language")
                SetGadgetText(#SolveButton,"Solve")
                SetGadgetItemText(#Difficulty,0,"Easy")
                SetGadgetItemText(#Difficulty,1,"Medium")
                SetGadgetItemText(#Difficulty,2,"Hard")
                SetGadgetItemText(#Difficulty,3,"Master")
              Else  
                SetGadgetText(#Language,"Sprache")
                SetGadgetText(#SolveButton,"Lösen")
                SetGadgetItemText(#Difficulty,0,"Einfach")
                SetGadgetItemText(#Difficulty,1,"Mittel")
                SetGadgetItemText(#Difficulty,2,"Schwer")
                SetGadgetItemText(#Difficulty,3,"Meister")
              EndIf
              X=GetGadgetState(#List)
              LoadList(GetGadgetState(#Difficulty))
              SetGadgetState(#List,X)
              PostEvent(#PB_Event_Gadget,#MainWindow,#List,#PB_EventType_Change)
          EndSelect
        Case #PB_EventType_LeftButtonDown  
          Select EventGadget()
            Case #Canvas
              If Not Solved
                
                Y=#True
                MX=Round((GetGadgetAttribute(#Canvas,#PB_Canvas_MouseX)-61)/40,#PB_Round_Nearest)
                MY=Round((GetGadgetAttribute(#Canvas,#PB_Canvas_MouseY)-61)/40,#PB_Round_Nearest)
                If MX>=0 And MY>=0 And MX<=7 And MY<=7
                  X=Field(MX,MY)
                  If X>2
                    DragTile=X
                    SelectElement(Tiles(),X)
                    Tiles()\NowX=-1
                    For MX=0 To 7
                      For MY=0 To 7
                        If Field(MX,MY)=X
                          Field(MX,MY)=0
                        EndIf
                      Next  
                    Next
                    Y=#False
                  EndIf
                EndIf
                
                If Y  
                  MX=GetGadgetAttribute(#Canvas,#PB_Canvas_MouseX)
                  MY=GetGadgetAttribute(#Canvas,#PB_Canvas_MouseY)
                  ForEach Tiles()
                    If MX>=Tiles()\DragX And MX<=Tiles()\DragX+Tiles()\DragW And MY>=Tiles()\DragY And MY<=Tiles()\DragY+Tiles()\DragH And Tiles()\NowX=-1
                      DragTile=ListIndex(Tiles())
                      Break
                    EndIf
                  Next
                EndIf
                
                Draw(#False)
              EndIf
          EndSelect
        Case #PB_EventType_LeftButtonUp  
          Select EventGadget()
            Case #Canvas
              If Not Solved
                If DragTile>-1 And Not NoDrop
                  MX=GetGadgetAttribute(#Canvas,#PB_Canvas_MouseX)
                  MY=GetGadgetAttribute(#Canvas,#PB_Canvas_MouseY)
                  SelectElement(Tiles(),DragTile)
                  
                  If Tiles()\DragRot
                    X=MX-0.8*Tiles()\DragH
                    Y=MY-0.8*Tiles()\DragW
                  Else
                    X=MX-0.8*Tiles()\DragW
                    Y=MY-0.8*Tiles()\DragH
                  EndIf
                  
                  Tiles()\NowX=Round((X-41)/40,#PB_Round_Nearest)
                  Tiles()\NowY=Round((Y-41)/40,#PB_Round_Nearest)
                  Tiles()\NowRot=Tiles()\DragRot
                  
                  If Tiles()\NowRot
                    For X=Tiles()\NowX To Tiles()\NowX+Tiles()\Y-1
                      For Y=Tiles()\NowY To Tiles()\NowY+Tiles()\X-1
                        Field(X,Y)=ListIndex(Tiles())
                      Next
                    Next
                  Else
                    For X=Tiles()\NowX To Tiles()\NowX+Tiles()\X-1
                      For Y=Tiles()\NowY To Tiles()\NowY+Tiles()\Y-1
                        Field(X,Y)=ListIndex(Tiles())
                      Next
                    Next
                  EndIf
                  
                EndIf
                DragTile=-1
                Draw(#False)
                
                X=0
                ForEach Tiles()
                  If Tiles()\Fixed Or Tiles()\NowX<>-1
                    X+1
                  EndIf
                Next
                If X=11
                  Solved=#True
                  DisableGadget(#SolveButton,#True)
                  If Language
                    MessageRequester("Solved!","Hooray, you solved the riddle!",#PB_MessageRequester_Info)
                  Else
                    MessageRequester("Gelöst!","Hurra, sie haben das Rätsel gelöst!",#PB_MessageRequester_Info)
                  EndIf
                EndIf
                
              EndIf
          EndSelect
        Case #PB_EventType_MouseMove
          Select EventGadget()
            Case #Canvas
              If DragTile<>-1
                Draw(#False)
              EndIf
          EndSelect
        Case #PB_EventType_RightClick
          Select EventGadget()
            Case #Canvas
              If DragTile=-1
                If Not Solved
                  MX=Round((GetGadgetAttribute(#Canvas,#PB_Canvas_MouseX)-61)/40,#PB_Round_Nearest)
                  MY=Round((GetGadgetAttribute(#Canvas,#PB_Canvas_MouseY)-61)/40,#PB_Round_Nearest)
                  If MX>=0 And MY>=0 And MX<=7 And MY<=7
                    X=Field(MX,MY)
                    If X>2
                      SelectElement(Tiles(),X)
                      Tiles()\NowX=-1
                      For MX=0 To 7
                        For MY=0 To 7
                          If Field(MX,MY)=X
                            Field(MX,MY)=0
                          EndIf
                        Next  
                      Next
                      Draw(#False)
                    EndIf
                  EndIf
                EndIf
                
              Else
                SelectElement(Tiles(),DragTile)
                Tiles()\DragRot=1-Tiles()\DragRot
                Draw(#False)
              EndIf
          EndSelect
        Case #PB_EventType_Change
          Select EventGadget()
            Case #List
              If GetGadgetState(#List)=-1
                StartDrawing(CanvasOutput(#Canvas))
                Box(0,0,OutputWidth(),OutputHeight(),Background)
                StopDrawing()
                DisableGadget(#SolveButton,#True)
                Solved=#True
              Else
                LoadTask(GetGadgetItemData(#List,GetGadgetState(#List)))
                Draw(#False)
                DisableGadget(#SolveButton,#False)
              EndIf
            Case #Difficulty
              LoadList(GetGadgetState(#Difficulty))
          EndSelect
      EndSelect
  EndSelect
ForEver

DataSection
  Tasks:
  Data.a 0,0,1,0,4,0,5,3,1
  Data.a 0,2,1,3,6,0,0,2,0
  Data.a 0,3,5,2,4,1,0,2,0
  Data.a 0,1,0,6,7,0,5,2,0
  Data.a 0,1,3,4,2,0,6,2,1
  Data.a 0,1,7,1,6,0,0,2,0
  Data.a 0,0,0,1,3,0,1,5,0
  Data.a 0,7,7,1,5,0,1,2,1
  Data.a 0,2,3,3,2,0,4,4,0
  Data.a 0,6,0,4,4,0,5,5,1
  Data.a 0,0,0,2,0,1,5,3,1
  Data.a 0,0,7,0,5,0,3,0,1
  Data.a 0,2,1,7,5,1,7,0,1
  Data.a 0,6,3,1,2,1,0,5,1
  Data.a 0,2,4,6,2,0,5,0,0
  Data.a 0,3,6,4,1,1,7,0,1
  Data.a 0,7,4,4,4,0,5,7,0
  Data.a 0,3,2,1,3,1,4,7,0
  Data.a 0,3,5,4,5,1,0,1,0
  Data.a 0,7,7,2,4,0,3,7,0
  Data.a 0,7,3,4,3,0,2,0,0
  Data.a 0,1,2,5,4,0,2,0,0
  
  Data.a 1,4,2,5,3,1,1,2,0
  Data.a 1,2,1,3,1,1,0,5,1
  Data.a 1,3,2,7,5,1,7,0,1
  Data.a 1,6,4,2,3,0,0,0,0
  Data.a 1,2,7,4,3,0,7,4,1
  Data.a 1,7,2,7,6,1,4,5,1
  Data.a 1,3,3,0,7,0,2,1,1
  Data.a 1,5,5,7,3,1,4,1,1
  Data.a 1,4,4,1,7,0,3,2,1
  Data.a 1,3,5,7,4,1,0,4,0
  Data.a 1,7,3,2,4,0,3,5,0
  Data.a 1,2,5,7,5,1,3,3,0
  Data.a 1,4,2,5,6,1,2,0,1
  Data.a 1,2,3,7,2,1,4,2,1
  Data.a 1,5,0,0,2,0,0,3,0
  Data.a 1,3,6,0,3,1,5,5,0
  Data.a 1,5,0,0,4,1,3,3,1
  Data.a 1,3,4,4,2,1,2,4,1
  Data.a 1,1,3,3,0,1,5,3,0
  Data.a 1,3,0,0,2,0,5,3,0
  Data.a 1,4,4,3,1,0,0,1,0
  Data.a 1,5,5,3,1,0,0,1,0
  
  Data.a 2,3,1,5,4,1,0,5,1
  Data.a 2,5,5,6,3,0,3,4,0
  Data.a 2,4,3,7,4,1,0,2,0
  Data.a 2,6,3,2,3,0,7,3,1
  Data.a 2,4,3,0,4,0,0,0,0
  Data.a 2,6,3,2,2,0,7,3,1
  Data.a 2,0,0,7,4,1,3,5,1
  Data.a 2,5,3,5,2,1,2,0,0
  Data.a 2,4,5,7,2,1,0,2,1
  Data.a 2,3,3,4,6,1,3,0,0
  Data.a 2,2,4,3,2,1,0,3,0
  Data.a 2,4,2,2,0,0,3,5,1
  Data.a 2,1,4,2,7,0,0,2,1
  Data.a 2,5,4,2,0,0,0,3,1
  Data.a 2,6,4,3,6,1,7,2,1
  Data.a 2,2,2,4,4,1,7,5,1
  Data.a 2,5,3,0,2,0,2,5,0
  Data.a 2,2,2,0,4,0,5,3,0
  Data.a 2,5,4,4,4,1,3,0,1
  Data.a 2,5,3,3,2,0,0,4,0
  Data.a 2,6,3,3,4,1,4,4,0
  Data.a 2,3,4,0,2,1,7,3,1
  
  Data.a 3,5,5,3,0,1,0,7,0
  Data.a 3,4,2,6,5,0,2,7,0
  Data.a 3,3,4,5,0,1,7,3,1
  Data.a 3,4,5,2,0,1,0,5,1
  Data.a 3,2,3,4,5,0,0,0,0
  Data.a 3,4,3,0,2,1,5,0,0
  Data.a 3,3,2,4,2,0,0,0,1
  Data.a 3,2,6,3,3,1,0,7,0
  Data.a 3,1,2,3,7,0,0,0,1
  Data.a 3,5,5,2,6,1,2,0,0
  Data.a 3,3,4,4,6,1,5,7,0
  Data.a 3,3,3,4,2,1,2,7,0
  Data.a 3,5,4,4,3,1,2,0,0
  Data.a 3,4,2,2,4,0,0,0,1
  Data.a 3,2,5,0,2,0,7,5,1
  Data.a 3,5,3,3,4,1,2,0,0
  Data.a 3,4,4,2,6,1,3,0,0
  Data.a 3,2,2,4,0,0,5,1,1
  Data.a 3,2,5,4,3,1,3,0,1
  Data.a 3,2,4,7,3,1,5,5,0
  Data.a 3,2,2,0,6,1,5,4,0
  Data.a 3,2,6,0,3,1,0,7,0
  
  TasksEnd:
EndDataSection
The code reflects the first release. The latest release can be found on GitHub: https://github.com/jacdelad/PureMondrian
Thanks to everyone who came up with all the great suggestions!
Last edited by jacdelad on Mon Jul 22, 2024 11:47 pm, edited 1 time in total.
Good morning, that's a nice tnetennba!

PureBasic 6.21/Windows 11 x64/Ryzen 7900X/32GB RAM/3TB SSD
Synology DS1821+/DX517, 130.9TB+50.8TB+2TB SSD
Axolotl
Addict
Addict
Posts: 837
Joined: Wed Dec 31, 2008 3:36 pm

Re: PureMondrian

Post by Axolotl »

Hi jacdelad
That's cool. Nice work.
Thanks for sharing.

Why not add you copyright (legal note) on the window tile like PureMondirian (c) by jac de lad or on an separate TextGadget().
Easy to say, don't remove the copyrigt line.

You did that on the info dialog. You only need the "copyright (c) ".

BTW I have inserted this line before the main loop to directly start with the english language.

Code: Select all

PostEvent(#PB_Event_Gadget, #MainWindow, #Language) 
Last edited by Axolotl on Sat Jun 29, 2024 4:34 pm, edited 1 time in total.
Just because it worked doesn't mean it works.
PureBasic 6.04 (x86) and <latest stable version and current alpha/beta> (x64) on Windows 11 Home. Now started with Linux (VM: Ubuntu 22.04).
User avatar
jacdelad
Addict
Addict
Posts: 2010
Joined: Wed Feb 03, 2021 12:46 pm
Location: Riesa

Re: PureMondrian

Post by jacdelad »

Yeah I can do this, I'll add some more rifles, so I will do this then.

Thanks for the kind words!
Good morning, that's a nice tnetennba!

PureBasic 6.21/Windows 11 x64/Ryzen 7900X/32GB RAM/3TB SSD
Synology DS1821+/DX517, 130.9TB+50.8TB+2TB SSD
Marc56us
Addict
Addict
Posts: 1600
Joined: Sat Feb 08, 2014 3:26 pm

Re: PureMondrian

Post by Marc56us »

Wow, the kind of little game that seems so simple you forget what time it is! :mrgreen:
Thanks :D
User avatar
jacdelad
Addict
Addict
Posts: 2010
Joined: Wed Feb 03, 2021 12:46 pm
Location: Riesa

Re: PureMondrian

Post by jacdelad »

Thanks. Dare to solve the really hard ones? I got 4 before I surrendered.
Good morning, that's a nice tnetennba!

PureBasic 6.21/Windows 11 x64/Ryzen 7900X/32GB RAM/3TB SSD
Synology DS1821+/DX517, 130.9TB+50.8TB+2TB SSD
Marc56us
Addict
Addict
Posts: 1600
Joined: Sat Feb 08, 2014 3:26 pm

Re: PureMondrian

Post by Marc56us »

jacdelad wrote: Sat Jun 29, 2024 4:54 pm Thanks. Dare to solve the really hard ones? I got 4 before I surrendered.
I'm old, it took me 15 minutes for #1 in Easy Level, so Hard Level around 2030? and Master for the next generation. :mrgreen:
Thanks, I will compile it as exe and put a link on desktop 8)
User avatar
jacdelad
Addict
Addict
Posts: 2010
Joined: Wed Feb 03, 2021 12:46 pm
Location: Riesa

Re: PureMondrian

Post by jacdelad »

Maybe I can add a "just put one tile into the right place"-button as a help.
Good morning, that's a nice tnetennba!

PureBasic 6.21/Windows 11 x64/Ryzen 7900X/32GB RAM/3TB SSD
Synology DS1821+/DX517, 130.9TB+50.8TB+2TB SSD
Marc56us
Addict
Addict
Posts: 1600
Joined: Sat Feb 08, 2014 3:26 pm

Re: PureMondrian

Post by Marc56us »

At first I understood: create an 8x8 square and try to place it between the blocked pieces.
Then I realized that the black pieces could be part of the 8x8 square.

I think the help could be shorter. Example:

- Place all the tiles
- The black tiles are fixed
- To rotate a tile, use the right mouse button

Or something like that.
:wink:
User avatar
jacdelad
Addict
Addict
Posts: 2010
Joined: Wed Feb 03, 2021 12:46 pm
Location: Riesa

Re: PureMondrian

Post by jacdelad »

I'll think about it. The help is part of the riddle. :wink:
Good morning, that's a nice tnetennba!

PureBasic 6.21/Windows 11 x64/Ryzen 7900X/32GB RAM/3TB SSD
Synology DS1821+/DX517, 130.9TB+50.8TB+2TB SSD
Justin
Addict
Addict
Posts: 948
Joined: Sat Apr 26, 2003 2:49 pm

Re: PureMondrian

Post by Justin »

Hi jacdelad,

it looks nice but it's not dpi aware, like a lot of pb code on this forum btw :D

This is how it looks at 200% scaling:
Image
Mr.L
Enthusiast
Enthusiast
Posts: 146
Joined: Sun Oct 09, 2011 7:39 am

Re: PureMondrian

Post by Mr.L »

Very nice! Thanks for the source code, too! It's not easy (for me, at least, but I'm stupid 😉), and it's tempting to press the 'solve' button...
User avatar
jacdelad
Addict
Addict
Posts: 2010
Joined: Wed Feb 03, 2021 12:46 pm
Location: Riesa

Re: PureMondrian

Post by jacdelad »

Justin wrote: Sat Jun 29, 2024 7:38 pm Hi jacdelad,

it looks nice but it's not dpi aware, like a lot of pb code on this forum btw :D

This is how it looks at 200% scaling:
Image
Hi Justin, that's why I wrote you need to disable the dpi aware option. I too have problems when it's enabled, but it works for me, also 200% scaling, when I disable it.
Good morning, that's a nice tnetennba!

PureBasic 6.21/Windows 11 x64/Ryzen 7900X/32GB RAM/3TB SSD
Synology DS1821+/DX517, 130.9TB+50.8TB+2TB SSD
User avatar
jacdelad
Addict
Addict
Posts: 2010
Joined: Wed Feb 03, 2021 12:46 pm
Location: Riesa

Re: PureMondrian

Post by jacdelad »

Mr.L wrote: Sat Jun 29, 2024 7:49 pm Very nice! Thanks for the source code, too! It's not easy (for me, at least, but I'm stupid 😉), and it's tempting to press the 'solve' button...
Just don't tell anybody. :wink:
Good morning, that's a nice tnetennba!

PureBasic 6.21/Windows 11 x64/Ryzen 7900X/32GB RAM/3TB SSD
Synology DS1821+/DX517, 130.9TB+50.8TB+2TB SSD
User avatar
idle
Always Here
Always Here
Posts: 5899
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: PureMondrian

Post by idle »

I was thinking oh this is easy until I realized there were white blocks :lol:
User avatar
moulder61
Enthusiast
Enthusiast
Posts: 193
Joined: Sun Sep 19, 2021 6:16 pm
Location: U.K.

Re: PureMondrian

Post by moulder61 »

@jacdelad

Nice game. :)
Seems to work OK on Void Linux using PB 6.04 LTS. I'm sure it will work on other Linux distributions too.
The only issue I had was that if I have a dark theme, I can't see the black squares very well. If I have a light theme, the white shapes don't show up very well!
So I changed the game background to grey. ;)

Moulder.
"If it ain't broke, fix it until it is!

This message is brought to you thanks to SenselessComments.com

My PB stuff for Linux: "https://u.pcloud.link/publink/show?code ... z3MR0T3jyV
Post Reply