Page 1 sur 2

Pure1010!

Publié : ven. 17/avr./2026 9:54
par Mindphazer
Bonjour à tous
Je vous présente Pure1010!, un clone du jeu 1010! (https://en.namu.wiki/w/1010!) développé avec l'aide de Claude AI (!!)
Le principe est simple : sur un plateau de 10 X 10, combinez des blocs et videz le plateau en les plaçant de manière stratégique pour créer des lignes
Le jeu est fourni avec deux langages (français et anglais), mais il est facile de rajouter des langues supplémentaires (dans la datasection à la fin du listing et dans la procédure InitLang())
Le listing est assez gros, aussi j'ai dû le couper en plusieurs parties

Pour un fonctionnement optimum, j'utilise une police de caractères spéciale (Nunito) et un fichier .png fournis ici :
https://workupload.com/file/3eSymrMP2aD
Il suffit de les télécharger et de les mettre dans le même répertoire que le listing source

Néanmoins, le jeu fonctionne sans ces fichiers

Normalement, le jeu est multi-plateforme (Développé sur MacOS, testé sur Windows 11 et Ubuntu Desktop)
Amusez-vous bien !

Une petite image du jeu (merci Venom pour la suggestion !)
Image

Partie 1

Code : Tout sélectionner

; ┌──────────────────────────────────────────────────────────────────────┐
; │                                                                      │
; │   ▄▄▄▄▄▄▄                       ▄▄▄▄   ▄▄▄▄     ▄▄▄▄   ▄▄▄▄    ▄▄    │
; │   ███▀▀███▄                   ▄█████ ▄██████▄ ▄█████ ▄██████▄  ██    │ 
; │   ███▄▄███▀ ██ ██ ████▄ ▄█▀█▄    ███ ███  ███    ███ ███  ███  ██    │ 
; │   ███▀▀▀▀   ██ ██ ██ ▀▀ ██▄█▀    ███ ███▄▄███    ███ ███▄▄███  ▀▀    │
; │   ███       ▀██▀█ ██    ▀█▄▄▄    ███  ▀████▀     ███  ▀████▀   ██    │
; │                                                                      │
; │                                                                      │
; │                   Code by Mindphazer & Claude AI                     │
; │                                                                      │
; │                           v 1.6 (c) 2026                             │
; │                                                                      │
; │ Compatibilité OS :                                                   │
; │ [x] MacOS   - Main development platform                              │
; │ [x] Windows - [x] DPI aware (hopefully!)                             │
; │ [x] Linux   - Tested on Ubuntu Desktop                               │
; └──────────────────────────────────────────────────────────────────────┘ 

EnableExplicit
Declare CanPlace(pi.i, gr.i, gc.i)
UsePNGImageDecoder()
RegisterFontFile("Nunito-Regular.ttf")
RegisterFontFile("Nunito-Bold.ttf")

;-============== CONSTANTES ==================

#BASE_WINDOW_W   = 650
#BASE_WINDOW_H   = 800
#BASE_CELL_SIZE  = 46
#BASE_GRID_X     = 30
#BASE_GRID_Y     = 90
#GRID_COLS       = 10
#GRID_ROWS       = 10
#BASE_SLOT_Y     = 595
#BASE_PIECE_CELL = 32

#TIMED_DURATION  = 180  ; secondes pour le mode contre-la-montre
#SURVIVAL_PERIOD = 30   ; secondes entre chaque rangée montante

#SHAPE_COUNT     = 19   ; nombre de formes

#COL_BG       = $1A1A2E
#COL_GRID_BG  = $16213E
#COL_GRID_LN  = $0F3460
#COL_TEXT     = $E0E0E0
#COL_SCORE_BG = $0F3460
#COL_GAMEOVER = $CC3333
#COL_GHOST_NO = $444444

; Normal : bleu foncé marine
#BTN_N_TOP  = $13458B   ; haut dégradé normal  → bleu clair-moyen
#BTN_N_BOT  = $03154B   ; bas  dégradé normal  → bleu très foncé
; Hover : un cran plus clair
#BTN_H_TOP  = $2868C0   ; haut hover
#BTN_H_BOT  = $183870   ; bas  hover
; Pressed : sombre, inversé
#BTN_P_TOP  = $081030   ; haut pressed (le plus sombre)
#BTN_P_BOT  = $304890   ; bas  pressed
; disabled
#BTN_D_TOP  = $444444
#BTN_D_BOT  = $888888

; Bordures
#BTN_BORDER     = $000820   ; contour externe très sombre
#BTN_SHINE      = $5888D0   ; reflet haut (biseau clair)
#BTN_SHADE      = $000418   ; ombre bas   (biseau sombre)

; Rayon des coins (unités logiques)
#BTN_RADIUS = 5

; Animation effacement lignes/colonnes
#ANIM_STEPS = 8    ; frames de flash + fondu
#ANIM_DELAY = 35   ; ms par frame

;-============== ENUMERATIONS ==================

; --- Textes
Enumeration
  #TXT_SCORE 
  #TXT_HIGHSCORE
  #TXT_TIME
  #TXT_PIECES
  #TXT_GAMEOVER
  #TXT_FINAL
  #TXT_BEST
  #TXT_REPLAY
  #TXT_CLASSIC
  #TXT_TIMED
  #TXT_CLEARANCE
  #TXT_SURVIVAL
  #TXT_UNDO
  #TXT_QUIT
  #TXT_STOP_GAME
  #TXT_GAMEINPROGRESS 
  #TXT_STARTGAME
  #TXT_MODE
EndEnumeration

Enumeration
  #MainWindow
  #Canvas
  #TimerAnimation
  #TimerTime
  #ButtonNewClassic
  #ButtonNewTimed
  #ButtonNewClearance
  #ButtonNewSurvival
  #ButtonUndo
  #ButtonStop
  #ButtonQuit
  #Font_Big
  #Font_Med
  #Font_Over
  #Font_Small
EndEnumeration

Enumeration
  #MODE_CLASSIC       ; mode classique
  #MODE_TIMED         ; compte à rebours
  #MODE_CLEARANCE     ; plateau pré-rempli
  #MODE_SURVIVAL      ; rangées qui montent
EndEnumeration

;-============== STRUCTURES ==================
Structure Cell
  filled.b
  color.i
  colorindex.i
EndStructure

Structure PieceShape
  rows.i
  cols.i
  cells.b[25]   ; 5x5 max
  color.i
  valid.b
  colorindex.i
EndStructure

Structure ShapeDef
  r.i
  c.i
  d.s
EndStructure

;-============== VARIABLES GLOBALES ==================

; ============================================================
;  Variables globales DPI  (calculées une fois au démarrage)
; ============================================================
Global WINDOW_W.i, WINDOW_H.i
Global CELL_SIZE.i
Global GRID_X.i, GRID_Y.i
Global SLOT_Y.i
Global PIECE_CELL.i
Global SLOT_W.i       ; largeur d'un emplacement de pièce (1/3 de la zone)
Global SLOT_SQUARE.i  ; côté du carré de centrage (= min de la largeur et hauteur dispo)
Global SLOT_ZONE_H.i  ; hauteur disponible pour les pièces (WINDOW_H - SLOT_Y - marge)

CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
  Global FontFactor.f = 1.5
CompilerElse
  Global FontFactor.f = 1.0
CompilerEndIf

Global Dim Textes.s(40)
Global Dim PieceColors.i(10)
Global Dim PieceImages.i(10)
Global Dim Grid.Cell(9, 9)
Global Dim Undo.Cell(9, 9)
Global Dim Pieces.PieceShape(2)
Global Logo = LoadImage(#PB_Any, "Logo.png")
;Global Logo = CatchImage(#PB_Any, ?Logo_png_start)
;Global Cube = LoadImage(#PB_Any, "Cube.png")
Global Cube = CatchImage(#PB_Any, ?Cube_png_start)
Global HS_FILE.s = GetHomeDirectory() + "1010_highscore.dat"
Global Version.s = "1.6"
Global GameMode.i = -1
Global GameBoard.i
Global Dim Shapes.ShapeDef(#SHAPE_COUNT - 1)

Global Score.i          = 0
Global Dim HiScore.i(3)
Global GameOver.b       = #False
Global QuitGame.b       = #False
Global GameInProgress.b = #False
Global PlayingTime

; Drag & Drop
Global DragActive.b = #False
Global DragPiece.i  = -1
Global DragX.i, DragY.i
Global DragOffX.i, DragOffY.i

; Animation effacement
Global AnimActive.b = #False
Global AnimStep.i   = 0
Global AnimTimer.i  = 0
Global AnimBonus.i  = 0
Global Dim AnimRow.b(9)
Global Dim AnimCol.b(9)
Global Dim AnimColor.i(9, 9)

Global UndoAvailable.b = #False
Global UndoScore.i
Global UndoPlayingTime.i
Global UndoGameOver.b
Global UndoGameInProgress.b
Global Dim UndoPieces.PieceShape(2)

Procedure.s GetLanguage()
  ;
  ; Cette fonction permet de récupérer la langue native du système, selon le type d'OS
  ;
  Protected Result.s
  CompilerIf #PB_Compiler_OS = #PB_OS_MacOS               ; Thanks to Danilo
    Protected NSUserDefaults_defs, NSString_locale
    NSUserDefaults_defs = CocoaMessage(0, 0, "NSUserDefaults standardUserDefaults")
    If NSUserDefaults_defs
      NSString_locale = CocoaMessage(0, NSUserDefaults_defs, "objectForKey:$", @"AppleLocale")
      If NSString_locale
        Result = Left(PeekS(CocoaMessage(0, NSString_locale, "UTF8String"), -1, #PB_UTF8), 2)
      EndIf
    EndIf
    ProcedureReturn Result
  CompilerElseIf #PB_Compiler_OS = #PB_OS_Windows         ; Thanks to Rescator
    Define dll.i, text$, len.i, *GetLocaleInfo
	  dll = OpenLibrary(#PB_Any,"kernel32.dll")
	  If dll
	  	CompilerIf #PB_Compiler_Unicode
		  	*GetLocaleInfo = GetFunction(dll, "GetLocaleInfoW")
		  CompilerElse
			*GetLocaleInfo = GetFunction(dll, "GetLocaleInfoA")
	  	CompilerEndIf
	  	If *GetLocaleInfo
	  		len = CallFunctionFast(*GetLocaleInfo, #LOCALE_USER_DEFAULT, $0059, #Null, #Null)
	  		If len
	  			text$ = Space(len - 1)
	  			If CallFunctionFast(*GetLocaleInfo, #LOCALE_USER_DEFAULT, $0059, @text$, len)
	  				Result = text$
	  			EndIf
	  		EndIf
  		EndIf
  		CloseLibrary(dll)
  	EndIf
  	ProcedureReturn Result
	CompilerElseIf #PB_Compiler_OS = #PB_OS_Linux           ; Thanks to AZJIO
		If ExamineEnvironmentVariables()
		  While NextEnvironmentVariable()
		    If Left(EnvironmentVariableName(), 4) = "LANG"
					Result = Left(EnvironmentVariableValue(), 2)
				  Break
				EndIf
		  Wend
		EndIf
		ProcedureReturn Result
  CompilerEndIf
EndProcedure

Procedure InitLang()
  Protected id, l.s, lang.s = GetLanguage()
  Select lang
    Case "fr"
      Restore FRA
    Case "us" , "en"
      Restore US
    Case "ru"
      Restore RUS
    Default
      Restore FRA
  EndSelect
  Repeat
    Read.s l
    If l <> "@@@"
      Textes(id) = l
      id + 1
    EndIf
  Until l = "@@@"
EndProcedure


Procedure InitDPI()
  WINDOW_W    = DesktopScaledX(#BASE_WINDOW_W)
  WINDOW_H    = DesktopScaledY(#BASE_WINDOW_H)
  CELL_SIZE   = DesktopScaledX(#BASE_CELL_SIZE)
  GRID_X      = DesktopScaledX(#BASE_GRID_X)
  GRID_Y      = DesktopScaledY(#BASE_GRID_Y)
  SLOT_Y      = DesktopScaledY(#BASE_SLOT_Y)
  PIECE_CELL  = DesktopScaledX(#BASE_PIECE_CELL)
  SLOT_W      = (WINDOW_W - GRID_X * 2) / 3
  SLOT_ZONE_H = WINDOW_H - SLOT_Y - DesktopScaledY(20)
  Protected slotPad.i = DesktopScaledX(6)
  Protected idealSide.i = 5 * PIECE_CELL + slotPad * 2
  SLOT_SQUARE = idealSide
  If SLOT_W      < SLOT_SQUARE : SLOT_SQUARE = SLOT_W      : EndIf
  If SLOT_ZONE_H < SLOT_SQUARE : SLOT_SQUARE = SLOT_ZONE_H : EndIf
EndProcedure

Procedure InitColors() 
  PieceColors(0) = $FF0000   ; rouge
  PieceColors(1) = $00FF00   ; vert
  PieceColors(2) = $0000FF   ; bleu
  PieceColors(3) = $FFFF00   ; jaune
  PieceColors(4) = $00FFFF   ; cyan
  PieceColors(5) = $FF8800   ; orange
  PieceColors(6) = $387814   ; vert foncé
  PieceColors(7) = $0088FF   ; bleu azur
  PieceColors(8) = $D30094   ; violet
  PieceColors(9) = $9314FF   ; rose (très distinct)
  PieceColors(10) = $444466  ; marron
EndProcedure


Procedure InitShapeDefs()
  Protected r.s, c.s, d.s, i
  Restore shapes
  For i = 0 To #SHAPE_COUNT - 1
    Read.s r
    Read.s c
    Read.s d
    shapes(i)\c = Val(c)
    shapes(i)\r = Val(r)
    shapes(i)\d = d
  Next i
EndProcedure

DataSection
  shapes:
  Data.s "1", "1", "1"
  Data.s "1", "2", "11"
  Data.s "2", "1", "11"
  Data.s "1", "3", "111"
  Data.s "3", "1", "111"
  Data.s "2", "2", "1111"
  Data.s "2", "2", "1110"
  Data.s "2", "2", "1101"
  Data.s "2", "2", "1011"
  Data.s "2", "2", "0111"
  Data.s "1", "4", "1111"
  Data.s "4", "1", "1111"
  Data.s "1", "5", "11111"
  Data.s "5", "1", "11111"
  Data.s "3", "3", "111111111"
  Data.s "3", "3", "111100100"
  Data.s "3", "3", "100100111"
  Data.s "3", "3", "111001001"
  Data.s "3", "3", "001001111"
EndDataSection

Procedure GeneratePiece(idx.i)
  Protected s.i, r.i, c.i, ci.i, Color
  s = Random(#SHAPE_COUNT - 1)
  Color = Random(9)
  Pieces(idx)\rows  = Shapes(s)\r
  Pieces(idx)\cols  = Shapes(s)\c
  Pieces(idx)\color = PieceColors(Color)
  Pieces(idx)\valid = #True
  Pieces(idx)\colorindex = Color
  ci = 0
  For r = 0 To Shapes(s)\r - 1
    For c = 0 To Shapes(s)\c - 1
      If Mid(Shapes(s)\d, ci + 1, 1) = "1"
        Pieces(idx)\cells[r * 5 + c] = 1
      Else
        Pieces(idx)\cells[r * 5 + c] = 0
      EndIf
      ci + 1
    Next
  Next
EndProcedure

Procedure GenerateAllPieces()
  Protected i.i
  For i = 0 To 2 : GeneratePiece(i) : Next
EndProcedure

CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
  Prototype Proto_AppShouldTerminate(Object, Selector, Sender)
  DeclareC AppShouldTerminate(Object, Selector, Sender)
  Global AppDelegate, AppShouldTerminate_.Proto_AppShouldTerminate
  AppDelegate = CocoaMessage(0, CocoaMessage(0, 0, "NSApplication sharedApplication"), "delegate")
  AppShouldTerminate_ = class_replaceMethod_(CocoaMessage(0, AppDelegate, "class"), sel_registerName_("applicationShouldTerminate:"), @AppShouldTerminate(), "v@:@")

  ProcedureC AppShouldTerminate(Object, Selector, Sender)
    QuitGame = #True
    If AppShouldTerminate_
      ProcedureReturn AppShouldTerminate_(Object, Selector, Sender)
    EndIf
  EndProcedure  
CompilerEndIf

Procedure Max(a, b)
  If a > b
    ProcedureReturn a
  Else
    ProcedureReturn b
  EndIf
EndProcedure

Procedure Min(a, b)
  If a < b
    ProcedureReturn a
  Else
    ProcedureReturn b
  EndIf
EndProcedure

; ------------------------------------------------------------
;  FindBestClearZone
;  Cherche la zone rows x cols la plus dense dans la grille
;  et retourne son coin supérieur gauche via *pgr/*pgc.
;  "Plus dense" = celle qui contient le plus de cellules
;  remplies, c'est là qu'il est le plus utile de faire de la place.
; ------------------------------------------------------------
Procedure FindBestClearZone(rows.i, cols.i, *pgr, *pgc)
  Protected r.i, c.i, br.i, bc.i, best.i = -1, count.i
  For r = 0 To 9 - rows
    For c = 0 To 9 - cols
      count = 0
      Protected rr.i, cc.i
      For rr = r To r + rows - 1
        For cc = c To c + cols - 1
          If Grid(cc, rr)\filled : count + 1 : EndIf
        Next
      Next
      If count > best
        best = count
        br = r : bc = c
      EndIf
    Next
  Next
  PokeI(*pgr, br)
  PokeI(*pgc, bc)
EndProcedure

; ------------------------------------------------------------
;  ClearZoneForPiece
;  Vide une zone de taille rows x cols à la position gr, gc.
;  On ne vide que le strict minimum : on cherche d'abord si
;  la pièce peut déjà se placer dans cette zone après un
;  vidage partiel (on retire cellule par cellule jusqu'au
;  premier placement valide).
; ------------------------------------------------------------
Procedure ClearZoneForPiece(pi.i, gr.i, gc.i)
  Protected r.i, c.i, rr.i, cc.i
  ; Collecter les cellules remplies dans la zone, mélangées
  Protected Dim zr.i(24)
  Protected Dim zc.i(24)
  Protected zCount.i = 0
  For rr = gr To gr + Pieces(pi)\rows - 1
    For cc = gc To gc + Pieces(pi)\cols - 1
      If rr <= 9 And cc <= 9 And Grid(cc, rr)\filled
        zr(zCount) = rr : zc(zCount) = cc : zCount + 1
      EndIf
    Next
  Next
  ; Vider une à une jusqu'à ce que le placement soit possible
  Protected idx.i
  For idx = 0 To zCount - 1
    Grid(zc(idx), zr(idx))\filled = #False
    Grid(zc(idx), zr(idx))\color  = 0
    If CanPlace(pi, gr, gc) : Break : EndIf
  Next
EndProcedure

; ------------------------------------------------------------
;  EnsurePieceCanBePlaced
;  Vérifie qu'une pièce peut se placer quelque part sur la grille.
;  Si non, ouvre une zone dans la zone la plus dense.
;  Recommence jusqu'à 5 fois si nécessaire (sécurité).
; ------------------------------------------------------------
Procedure EnsurePieceCanBePlaced(pi.i)
  Protected r.i, c.i, gr.i, gc.i, attempt.i
  For attempt = 0 To 4
    ; Vérifier si au moins une position est libre
    For r = 0 To 9
      For c = 0 To 9
        If CanPlace(pi, r, c) : ProcedureReturn : EndIf
      Next
    Next
    ; Aucune position valide : trouver la zone la plus dense
    ; de la taille de la pièce et y ouvrir de la place
    FindBestClearZone(Pieces(pi)\rows, Pieces(pi)\cols, @gr, @gc)
    ClearZoneForPiece(pi, gr, gc)
  Next
EndProcedure

; ------------------------------------------------------------
;  FillGridPartially
;  Remplit la grille à environ pct% de façon aléatoire,
;  puis garantit que chaque pièce de départ est plaçable.
;  pct recommandé : 35-45 pour le mode déblayage.
; ------------------------------------------------------------
Procedure FillGridPartially(pct.i)
  Protected r.i, c.i, i.i, Color.i

  ; 1. Remplissage aléatoire
  For r = 0 To 9
    For c = 0 To 9
      If Random(99) < pct
        Color = Random(9)
        Grid(c, r)\filled = #True
        Grid(c, r)\color  = PieceColors(Color)
        grid(c, r)\colorindex = Color
      Else
        Grid(c, r)\filled = #False
        Grid(c, r)\color  = 0
      EndIf
    Next
  Next

  ; 2. Générer les pièces de départ
  GenerateAllPieces()

  ; 3. Garantir que chaque pièce peut être placée
  For i = 0 To 2
    EnsurePieceCanBePlaced(i)
  Next
EndProcedure

; Fait monter toutes les rangées d'un cran et insère une
; nouvelle rangée partiellement remplie en bas
Procedure PushRowUp()
  Protected r.i, c.i, i.i
  ; Décaler vers le haut (la rangée 0 disparaît)
  For r = 0 To 8
    For c = 0 To 9
      Grid(c, r)\filled = Grid(c, r + 1)\filled
      Grid(c, r)\color  = Grid(c, r + 1)\color
      Grid(c, r)\colorindex  = Grid(c, r + 1)\colorindex
    Next
  Next
  ; Nouvelle rangée en bas avec des trous (jouable)
  Protected holes.i = 2 + Random(2)   ; 2 à 4 trous
  For c = 0 To 9 
    Grid(c, 9)\filled = #True 
    Grid(c, 9)\color = $444466 
    Grid(c, 9)\colorindex = 10 
  Next
  For i = 1 To holes
    Grid(Random(9), 9)\filled = #False
  Next
EndProcedure

; ============================================================
;  DrawCanvasButton
;  ParentBG : couleur de fond du parent pour masquer les coins
;  State    : 0 = normal, 1 = hover, 2 = pressed
; ============================================================
Procedure DrawCanvasButton(Gadget, Image, State = 0, ParentBG = #COL_BG)
  Protected dx.i = DesktopScaledX(GadgetWidth(Gadget))
  Protected dy.i = DesktopScaledY(GadgetHeight(Gadget))
  Protected rad.i = DesktopScaledX(#BTN_RADIUS)
  Protected offX.i = 0, offY.i = 0
  Protected topCol.i, botCol.i

  Select State
    Case 0 : topCol = #BTN_N_TOP : botCol = #BTN_N_BOT
    Case 1 : topCol = #BTN_H_TOP : botCol = #BTN_H_BOT
    Case 2 : topCol = #BTN_P_TOP : botCol = #BTN_P_BOT : offX = DesktopScaledX(1) : offY = DesktopScaledY(1)
    Case 3 : topCol = #BTN_D_TOP : botCol = #BTN_D_BOT  
  EndSelect

  If Not StartDrawing(CanvasOutput(Gadget)) : ProcedureReturn : EndIf

    ; --- 1. Effacement propre du fond ---
    DrawingMode(#PB_2DDrawing_Default)
    Box(0, 0, dx, dy, ParentBG)

    ; --- 2. Dégradé appliqué directement sur RoundBox ---
    DrawingMode(#PB_2DDrawing_Gradient)
    If State < 2
      LinearGradient(0, 0, 0, dy)    ; haut → bas
    Else
      LinearGradient(0, dy, 0, 0)    ; inversé pour pressed
    EndIf
    GradientColor(0.0, topCol)
    GradientColor(1.0, botCol)
    RoundBox(0, 0, dx, dy, rad, rad, topCol)
    DrawingMode(#PB_2DDrawing_Default)

    ; --- 3. Reflets de bord (biseau) ---
    If State < 2
      Line(rad, 0,      dx - rad * 2, 0, #BTN_SHINE)
      Line(0,   rad,    0, dy - rad * 2, #BTN_SHINE)
      Line(rad, dy - 1, dx - rad * 2, 0, #BTN_SHADE)
      Line(dx - 1, rad, 0, dy - rad * 2, #BTN_SHADE)
    Else
      Line(rad, 0,      dx - rad * 2, 0, #BTN_SHADE)
      Line(0,   rad,    0, dy - rad * 2, #BTN_SHADE)
      Line(rad, dy - 1, dx - rad * 2, 0, #BTN_SHINE)
      Line(dx - 1, rad, 0, dy - rad * 2, #BTN_SHINE)
    EndIf

    ; --- 4. Contour arrondi ---
    DrawingMode(#PB_2DDrawing_Outlined)
    RoundBox(0, 0, dx, dy, rad, rad, #BTN_BORDER)

    ; --- 5. Image centrée ---
    DrawingMode(#PB_2DDrawing_AlphaBlend)
    If IsImage(Image)
      Protected imgW.i = ImageWidth(Image)
      Protected imgH.i = ImageHeight(Image)
      Protected imgX.i = (dx - imgW) / 2 + offX
      Protected imgY.i = (dy - imgH) / 2 + offY
      DrawImage(ImageID(Image), imgX, imgY)
    EndIf
  StopDrawing()
EndProcedure

Procedure DoCanvasButtonEvent()
  Protected Gadget = EventGadget()
  Protected Image  = GetGadgetData(Gadget)
  Select EventType()
    Case #PB_EventType_MouseEnter    : DrawCanvasButton(Gadget, Image, 1)
    Case #PB_EventType_MouseLeave    : DrawCanvasButton(Gadget, Image, 0)
    Case #PB_EventType_LeftButtonDown: DrawCanvasButton(Gadget, Image, 2)
    Case #PB_EventType_LeftButtonUp  : DrawCanvasButton(Gadget, Image, 1)
  EndSelect
EndProcedure

; ============================================================
;  CreateButtonVectorImage — image transparente texte centré
;  Le texte est rendu en vecteur avec ombre subtile.
;  Si IconID > 0 : icône 20x20 à gauche, texte à droite.
; ============================================================
Procedure CreateButtonImage(Image, Width, Height, Text.s, IconID = 0)
  Static FontBtn.i
  Protected dx.i = DesktopScaledX(Width)
  Protected dy.i = DesktopScaledY(Height)
  Protected r1.i
  Protected IconWidth.i = 20
  If Not FontBtn
    Protected fontSize.f = 11 * (DesktopResolutionY() / FontFactor)
    FontBtn = LoadFont(#PB_Any, "Nunito", fontSize, #PB_Font_HighQuality)
  EndIf
  r1 = CreateImage(Image, dx, dy, 32, #PB_Image_Transparent)
  If Image = #PB_Any : Image = r1 : EndIf
  If r1
    If StartDrawing(ImageOutput(Image))
      DrawingFont(FontID(FontBtn))
      Protected tw.f = TextWidth(Text)
      Protected th.f = TextHeight(Text)
      Protected tx.f, ty.f
      If IconID > 0
        Protected iSz.f  = DesktopScaledX(IconWidth)
        Protected Factor.f = ImageWidth(IconID) / IconWidth
        Protected iSzH.f = DesktopScaledY(ImageHeight(IconID) / Factor)
        Protected gap.f  = DesktopScaledX(6)
        Protected totW.f = iSz + gap + tw
        Protected ix.f   = (dx - totW) / 2
        Protected iy.f   = (dy - iSzH) / 2
        DrawingMode(#PB_2DDrawing_AlphaBlend)
        DrawImage(ImageID(IconID), ix, iy, iSz, iSzH)
        tx = ix + iSz + gap
      Else
        tx = (dx - tw) / 2
      EndIf
      ty = (dy - th) / 2

      ; Ombre portée légère
      DrawingMode(#PB_2DDrawing_AlphaBlend | #PB_2DDrawing_Transparent)
      DrawText(tx + DesktopScaledX(1), ty + DesktopScaledY(1), Text, RGBA(0, 0, 0, 140))

      ; Texte blanc cassé
      DrawText(tx, ty, Text, RGBA(235, 235, 235, 255))
      StopDrawing()
    EndIf
  EndIf
  ProcedureReturn r1
EndProcedure

Procedure CanvasButtonGadget(Gadget, x, y, Width, Height, Texte.s, Icone = #False)
  Protected Image = CreateButtonImage(#PB_Any, Width, Height, Texte, Cube * Icone)
  Protected r1 = CanvasGadget(Gadget, x, y, Width, Height)
  If Gadget = #PB_Any : Gadget = r1 : EndIf
  If r1
    SetGadgetData(Gadget, Image)
    DrawCanvasButton(Gadget, Image, 0)
    BindGadgetEvent(Gadget, @DoCanvasButtonEvent())
  EndIf
  ProcedureReturn r1
EndProcedure

Procedure CanPlace(pi.i, gr.i, gc.i)
  Protected r.i, c.i, nr.i, nc.i
  For r = 0 To Pieces(pi)\rows - 1
    For c = 0 To Pieces(pi)\cols - 1
      If Pieces(pi)\cells[r * 5 + c]
        nr = gr + r : nc = gc + c
        If nr < 0 Or nr > 9 Or nc < 0 Or nc > 9 : ProcedureReturn #False : EndIf
        If Grid(nc, nr)\filled                  : ProcedureReturn #False : EndIf
      EndIf
    Next
  Next
  ProcedureReturn #True
EndProcedure

Procedure PlacePiece(pi.i, gr.i, gc.i)
  Protected r.i, c.i
  For r = 0 To Pieces(pi)\rows - 1
    For c = 0 To Pieces(pi)\cols - 1
      If Pieces(pi)\cells[r * 5 + c]
        Grid(gc + c, gr + r)\filled = #True
        Grid(gc + c, gr + r)\color  = Pieces(pi)\color
        Grid(gc + c, gr + r)\colorindex  = Pieces(pi)\colorindex
      EndIf
    Next
  Next
  Pieces(pi)\valid = #False
EndProcedure

Procedure ClearLines()
  Protected r.i, c.i, full.b, count.i, bonus.i
  For r = 0 To 9 : AnimRow(r) = #False : Next
  For c = 0 To 9 : AnimCol(c) = #False : Next
  count = 0
  For r = 0 To 9
    full = #True
    For c = 0 To 9 : If Not Grid(c, r)\filled : full = #False : Break : EndIf : Next
    If full : AnimRow(r) = #True : count + 1 : EndIf
  Next
  For c = 0 To 9
    full = #True
    For r = 0 To 9 : If Not Grid(c, r)\filled : full = #False : Break : EndIf : Next
    If full : AnimCol(c) = #True : count + 1 : EndIf
  Next
  If count = 0 : ProcedureReturn 0 : EndIf
  If count = 1      : bonus = 10
  ElseIf count = 2  : bonus = 20
  ElseIf count >= 3 : bonus = 30 + (count - 3) * 15
  EndIf
  For r = 0 To 9
    For c = 0 To 9
      AnimColor(c, r) = Grid(c, r)\color
    Next
  Next
  AnimActive = #True
  AnimStep   = 0
  ProcedureReturn bonus
EndProcedure

Procedure ApplyClear()
  Protected r.i, c.i
  For r = 0 To 9
    If AnimRow(r)
      For c = 0 To 9 : Grid(c, r)\filled = #False : Grid(c, r)\color = 0 : Grid(c, r)\colorindex = 0 : Next
    EndIf
  Next
  For c = 0 To 9
    If AnimCol(c)
      For r = 0 To 9 : Grid(c, r)\filled = #False : Grid(c, r)\color = 0 : Grid(c, r)\colorindex = 0 : Next
    EndIf
  Next
  AnimActive = #False
EndProcedure

Procedure CheckGameOver()
  Protected i.i, r.i, c.i
  For i = 0 To 2
    If Not Pieces(i)\valid : Continue : EndIf
    For r = 0 To 9
      For c = 0 To 9
        If CanPlace(i, r, c) : ProcedureReturn #False : EndIf
      Next
    Next
  Next
  ProcedureReturn #True
EndProcedure

; ============================================================
;  Conversion coordonnées souris -> cellule grille
;  Les coordonnées souris du CanvasGadget sont déjà en pixels
;  physiques sur Windows DPI-aware, donc on utilise directement
;  les variables GRID_X, CELL_SIZE déjà mises à l'échelle.
; ============================================================
Procedure GetDropCell(mx.i, my.i, *pgr, *pgc)
  Protected snX.i = mx - DragOffX
  Protected snY.i = my - DragOffY
  PokeI(*pgr, (snY - GRID_Y + CELL_SIZE / 2) / CELL_SIZE)
  PokeI(*pgc, (snX - GRID_X + CELL_SIZE / 2) / CELL_SIZE)
EndProcedure

Procedure LoadHiScore()
  Protected f.i, i.i
  If FileSize(HS_FILE) > 0
    f = ReadFile(#PB_Any, HS_FILE)
    If f
      Repeat
        HiScore(i) = Val(ReadString(f)) 
        i + 1
      Until Eof(f) = #True Or i > 3
      CloseFile(f) 
    EndIf
  EndIf
EndProcedure

Procedure SaveHiScore()
  Protected i.i
  Protected f.i = CreateFile(#PB_Any, HS_FILE)
  If f 
    For i = 0 To 3
      WriteStringN(f, Str(HiScore(i))) 
    Next i
    CloseFile(f)
  EndIf
EndProcedure

Procedure ResetGame()
  Protected r.i, c.i
  For r = 0 To 9
    For c = 0 To 9
      Grid(c, r)\filled = #False
      Grid(c, r)\color  = 0
      Grid(c, r)\colorindex = 0
    Next
  Next
  Score          = 0
  GameOver       = #False
  DragActive     = #False
  DragPiece      = -1
  Dim Pieces.PieceShape(2)
  PlayingTime    = 0
  AnimActive     = #False
  AnimStep       = 0
  UndoAvailable  = #False
  DisableGadget(#ButtonUndo, #True)
  DrawCanvasButton(#ButtonUndo, GetGadgetData(#ButtonUndo), 3)
EndProcedure

Procedure NewGame()
  ResetGame()
  Select GameMode
    Case #MODE_TIMED     : PlayingTime = #TIMED_DURATION : GenerateAllPieces()        ; compte à rebours
    Case #MODE_CLEARANCE : PlayingTime = 0 : FillGridPartially(35)                    ; ~35% rempli
    Case #MODE_SURVIVAL  : PlayingTime = 0 : GenerateAllPieces()
    Default              : PlayingTime = 0 : GenerateAllPieces()
  EndSelect
EndProcedure

Procedure Clamp255(v.i)
  If v < 0 : ProcedureReturn 0 : EndIf
  If v > 255 : ProcedureReturn 255 : EndIf
  ProcedureReturn v
EndProcedure

Procedure MixColor(col1.i, col2.i, f.f)
  Protected r = Red(col1)   + (Red(col2)   - Red(col1))   * f
  Protected g = Green(col1) + (Green(col2) - Green(col1)) * f
  Protected b = Blue(col1)  + (Blue(col2)  - Blue(col1))  * f
  ProcedureReturn RGB(Clamp255(r), Clamp255(g), Clamp255(b))
EndProcedure

Procedure DrawCell(x.i, y.i, sz.i, col.i)
  Protected r = Red(col), g = Green(col), b = Blue(col)
  Protected light1 = RGB(Clamp255(r * 1.25), Clamp255(g * 1.25), Clamp255(b * 1.15))
  Protected light2 = RGB(Clamp255(r * 1.08), Clamp255(g * 1.08), Clamp255(b * 1.05))
  Protected dark1  = RGB(r * 0.72, g * 0.72, b * 0.78)
  Protected dark2  = RGB(r * 0.42, g * 0.42, b * 0.48)
  Protected border = RGB(r * 0.30, g * 0.30, b * 0.35)
  Protected inner  = sz - 4

  ; Fond principal, dégradé diagonal doux
  DrawingMode(#PB_2DDrawing_Gradient)
  LinearGradient(x, y, x + sz, y + sz)
  GradientColor(0.00, light1)
  GradientColor(0.45, light2)
  GradientColor(1.00, dark1)
  Box(x, y, sz, sz)

  ; Reflet supérieur discret
  DrawingMode(#PB_2DDrawing_AlphaBlend | #PB_2DDrawing_Gradient)
  LinearGradient(x, y, x, y + sz / 2)
  GradientColor(0.0, RGBA(255, 255, 255, 90))
  GradientColor(1.0, RGBA(255, 255, 255, 0))
  Box(x + 2, y + 2, sz - 4, sz / 2)

  ; Ombre intérieure bas
  LinearGradient(x, y + sz / 2, x, y + sz)
  GradientColor(0.0, RGBA(0, 0, 0, 0))
  GradientColor(1.0, RGBA(0, 0, 0, 80))
  Box(x + 2, y + sz / 2, sz - 4, sz / 2 - 2)
  DrawingMode(#PB_2DDrawing_Default)

  ; Biseau fin, 1 pixel seulement
  Line(x + 1, y + 1, sz - 2, DesktopScaledY(1), MixColor(light1, $FFFFFF, 0.35)) ; haut
  Line(x + 1, y + 1, DesktopScaledX(1), sz - 2, MixColor(light1, $FFFFFF, 0.20)) ; gauche
  Line(x + 1, y + sz - 2, sz - 2, 1, dark2) ; bas
  Line(x + sz - 2, y + 1, 1, sz - 2, dark2) ; droite

  ; Contour externe
  Line(x, y, sz, 1, border)
  Line(x, y, 1, sz, border)
  Line(x, y + sz - 1, sz, 1, RGB(r * 0.18, g * 0.18, b * 0.22))
  Line(x + sz - 1, y, 1, sz, RGB(r * 0.18, g * 0.18, b * 0.22))
EndProcedure

Procedure CenterText(x, y, w, h, texte.s)
  Protected tw = TextWidth(texte)
  Protected th = TextHeight(texte)
  DrawingMode(#PB_2DDrawing_Transparent)
  DrawText(x + (w / 2) - (tw / 2) + 1, y + (h / 2) - (th / 2) + 1, texte, #Black)
  DrawText(x + (w / 2) - (tw / 2), y + (h / 2) - (th / 2), texte)
  DrawingMode(#PB_2DDrawing_Default)
EndProcedure  

Procedure FlashAnimation()
  Protected aStep.i = AnimStep
  Protected aMax.i  = #ANIM_STEPS / 2   ; 4 frames par phase
  Protected aAlpha.i, aShrink.i, aOff.i, aT.i, c.i, r.i
  Protected aX.i, aY.i, aSz.i
  Protected pad2x.i = DesktopScaledX(2)
  Protected pad2y.i = DesktopScaledY(2)
  Protected cellInner.i = CELL_SIZE - pad2x * 2  ; taille intérieure d'une cellule
  
  ; Intensité globale 0..255 : monte en phase flash, descend en phase fondu
  Protected aIntens.i
  If aStep < aMax
    aIntens = (aStep * 255) / (aMax - 1)
  Else
    aIntens = 255 - ((aStep - aMax) * 255) / (aMax - 1)
  EndIf
  If aIntens < 0   : aIntens = 0   : EndIf
  If aIntens > 255 : aIntens = 255 : EndIf
  DrawingMode(#PB_2DDrawing_AlphaBlend)
  Protected haloLayers.i = DesktopScaledX(10)  ; épaisseur totale du halo en px
  Protected hLayer.i, hAlpha.i
  Protected hR.i = 255, hG.i = 238, hB.i = 200  ; teinte blanc-cyan chaude
  For r = 0 To 9
    For c = 0 To 9
      If Not (AnimRow(r) Or AnimCol(c)) : Continue : EndIf
      If Not Grid(c, r)\filled          : Continue : EndIf
      aX  = GRID_X + c * CELL_SIZE + pad2x
      aY  = GRID_Y + r * CELL_SIZE + pad2y
      aSz = cellInner
      ; Couronnes du plus externe au plus interne
      For hLayer = haloLayers To 1 Step -1
        ; Opacité : max au bord de la cellule, nulle à l'extrémité externe
        ; = aIntens * (1 - hLayer/haloLayers)  → 0 au bord ext, aIntens au bord cell
        hAlpha = (aIntens * (haloLayers - hLayer + 1)) / (haloLayers + 1)
        If hAlpha > 0
          ; Rectangle encadrant la cellule, élargi de hLayer px de chaque côté
          Box(aX - hLayer, aY - hLayer, aSz + hLayer * 2,  aSz + hLayer * 2, RGBA(hR, hG, hB, hAlpha))
        EndIf
      Next hLayer
    Next
  Next

  For r = 0 To 9
    For c = 0 To 9
      If Not (AnimRow(r) Or AnimCol(c)) : Continue : EndIf
      If Not Grid(c, r)\filled          : Continue : EndIf
      aX  = GRID_X + c * CELL_SIZE + pad2x
      aY  = GRID_Y + r * CELL_SIZE + pad2y
      aSz = cellInner
      If aStep < aMax
        ; Phase flash : overlay blanc croissant sur la couleur d'origine
        DrawCell(aX, aY, aSz, AnimColor(c, r))
        Box(aX, aY, aSz, aSz, RGBA(255, 255, 255, aIntens))
      Else
        ; Phase fondu : carré blanc qui rétrécit vers le centre
        aT      = aStep - aMax
        aShrink = (aT * (aSz / 2)) / (aMax - 1)
        aOff    = aShrink
        Box(aX, aY, aSz, aSz, #COL_GRID_BG)
        If aSz - 2 * aOff > 0
          Box(aX + aOff, aY + aOff, aSz - 2 * aOff, aSz - 2 * aOff, RGBA(255, 255, 255, aIntens))
        EndIf
      EndIf
    Next
  Next
  DrawingMode(#PB_2DDrawing_Transparent)
EndProcedure

Procedure DrawGhost()
  Protected ghostCol.i
  Protected r.i, c.i, x.i, y.i, i.i
  Protected gr.i, gc.i, sx.i, sy.i, pr.i, pc.i
  GetDropCell(DragX, DragY, @gr, @gc)
  If CanPlace(DragPiece, gr, gc)
    ghostCol = Pieces(DragPiece)\color 
  Else 
    ghostCol = #COL_GHOST_NO 
  EndIf
  DrawingMode(#PB_2DDrawing_AlphaBlend)
  For pr = 0 To Pieces(DragPiece)\rows - 1
    For pc = 0 To Pieces(DragPiece)\cols - 1
      If Pieces(DragPiece)\cells[pr * 5 + pc]
        r = gr + pr : c = gc + pc
        If r >= 0 And r <= 9 And c >= 0 And c <= 9
          x = GRID_X + c * CELL_SIZE + DesktopScaledX(2)
          y = GRID_Y + r * CELL_SIZE + DesktopScaledY(2)
          Box(x, y, CELL_SIZE - DesktopScaledX(4), CELL_SIZE - DesktopScaledY(4), RGBA(Red(ghostCol), Green(ghostCol), Blue(ghostCol), 70))
        EndIf
      EndIf
    Next
  Next
EndProcedure

Procedure DrawGame()
  Protected r.i, c.i, x.i, y.i, i.i
  Protected gr.i, gc.i, sx.i, sy.i, pr.i, pc.i
  Protected slotBorderCol.i = $223366   ; couleur du cadre du slot
  Protected slotBgCol.i     = $0D1A33   ; fond du carré légèrement plus sombre que la grille
  If Not StartDrawing(CanvasOutput(#Canvas)) : ProcedureReturn : EndIf
  If IsImage(GameBoard)
    DrawImage(ImageID(GameBoard), 0, 0)
  Else
    ; Fond
    Box(0, 0, OutputWidth(), OutputHeight(), #COL_BG)
    If IsImage(Logo)
      DrawingMode(#PB_2DDrawing_AlphaBlend)
      DrawImage(ImageID(logo), GRID_X, DesktopScaledX(3), DesktopScaledX(200), DesktopScaledY(83))
    Else
      DrawingFont(FontID(#Font_Big))
      DrawingMode(#PB_2DDrawing_Transparent)
      DrawText(GRID_X, DesktopScaledY(12), "Pure1010!", #COL_TEXT)
    EndIf
    DrawingFont(FontID(#Font_Small))
    FrontColor($555555)
    CenterText(0, OutputHeight() - DesktopScaledY(20), OutputWidth(), DesktopScaledY(20), "Version " + Version + " © 2026 Mindphazer")
    RoundBox(DesktopScaledX(260), DesktopScaledY(8), DesktopScaledX(180), DesktopScaledY(60), 4, 4, #COL_SCORE_BG)
    RoundBox(DesktopScaledX(450), DesktopScaledY(8), DesktopScaledX(180), DesktopScaledY(60), 4, 4, #COL_SCORE_BG)
    RoundBox(OutputWidth() - DesktopScaledX(140), DesktopScaledY(490), DesktopScaledX(120), DesktopScaledY(62), 4, 4, #COL_SCORE_BG)
    DrawingMode(#PB_2DDrawing_Transparent)
    DrawingFont(FontID(#Font_Med))
    DrawText(DesktopScaledX(270), DesktopScaledY(12), Textes(#TXT_SCORE), $AACCFF)
    DrawText(DesktopScaledX(455), DesktopScaledY(12), Textes(#TXT_HIGHSCORE), $FFCC88)
    DrawText(OutputWidth() - DesktopScaledX(130), DesktopScaledY(496), Textes(#TXT_TIME), $90EE90)
    DrawText(GRID_X + DesktopScaledX(20), SLOT_Y - DesktopScaledY(20), Textes(#TXT_PIECES), $888888)
    DrawingMode(#PB_2DDrawing_Default)
    ; Bordure + fond grille
    Box(GRID_X - DesktopScaledX(2), GRID_Y - DesktopScaledY(2), #GRID_COLS * CELL_SIZE + DesktopScaledX(4), #GRID_ROWS * CELL_SIZE + DesktopScaledY(4), #COL_GRID_LN)
    Box(GRID_X, GRID_Y, #GRID_COLS * CELL_SIZE, #GRID_ROWS * CELL_SIZE, #COL_GRID_BG)
     ; Lignes de grille
    For r = 0 To #GRID_ROWS
      Line(GRID_X, GRID_Y + r * CELL_SIZE, #GRID_COLS * CELL_SIZE, DesktopScaledY(1), #COL_GRID_LN)
    Next
    For c = 0 To #GRID_COLS
      Line(GRID_X + c * CELL_SIZE, GRID_Y, DesktopScaledX(1), #GRID_ROWS * CELL_SIZE, #COL_GRID_LN)
    Next  
    ; Dessin des carrés de slot
    For i = 0 To 2
      sx = GRID_X + i * SLOT_W + (SLOT_W - SLOT_SQUARE) / 2
      sy = SLOT_Y + (SLOT_ZONE_H - SLOT_SQUARE) / 2
      Box(sx, sy, SLOT_SQUARE, SLOT_SQUARE, slotBorderCol)
      Box(sx + DesktopScaledX(1), sy + DesktopScaledY(1), SLOT_SQUARE - DesktopScaledX(2), SLOT_SQUARE - DesktopScaledY(2), slotBgCol)
    Next i
    GrabDrawingImage(GameBoard, 0, 0, OutputWidth(), OutputHeight())
  EndIf
  DrawingMode(#PB_2DDrawing_Transparent)
  DrawingFont(FontID(#Font_Big))
  DrawText(DesktopScaledX(270), DesktopScaledY(29), FormatNumber(Score, 0, "", " "), #COL_TEXT)
  If GameMode >= 0
    DrawText(DesktopScaledX(455), DesktopScaledY(29), FormatNumber(HiScore(GameMode), 0, "", " "), #COL_TEXT)
  EndIf
  DrawText(OutputWidth() - DesktopScaledX(130), DesktopScaledY(513), RSet(Str(PlayingTime / 60), 2, "0") + " : " + RSet(Str(PlayingTime % 60), 2, "0"), #COL_TEXT)
  DrawingMode(#PB_2DDrawing_Transparent | #PB_2DDrawing_AlphaBlend)
  DrawingFont(FontID(#Font_Over))
  Protected GameModeTXT.s = ""
  Select GameMode
    Case #MODE_CLASSIC
      GameModeTXT = Textes(#TXT_CLASSIC)
    Case #MODE_TIMED
      GameModeTXT = Textes(#TXT_TIMED)
    Case #MODE_CLEARANCE
      GameModeTXT = Textes(#TXT_CLEARANCE)
    Case #MODE_SURVIVAL
      GameModeTXT = Textes(#TXT_SURVIVAL)
  EndSelect
  DrawText(GRID_X + ((CELL_SIZE * #GRID_COLS) / 2) - (TextWidth(GameModeTXT) / 2), GRID_Y + ((CELL_SIZE * #GRID_ROWS) / 2) - (TextHeight(GameModeTXT) / 2), GameModeTXT, RGBA(44, 125, 161, 80))
  
  ; Cellules remplies
  For r = 0 To 9
    For c = 0 To 9
      If Grid(c, r)\filled
        DrawImage(ImageID(PieceImages(Grid(c, r)\colorindex)), GRID_X + c * CELL_SIZE + DesktopScaledX(1), GRID_Y + r * CELL_SIZE + DesktopScaledY(1), CELL_SIZE - DesktopScaledX(2), CELL_SIZE - DesktopScaledY(2))
      EndIf
    Next
  Next

  ;--- Animation effacement ---
  If AnimActive
    FlashAnimation()
  EndIf
  ; Ghost (aperçu de dépôt)
  If DragActive And DragPiece >= 0
    DrawGhost()
  EndIf
  For i = 0 To 2
    ; Coin supérieur gauche du carré de slot, centré verticalement dans la zone
     sx = GRID_X + i * SLOT_W + (SLOT_W - SLOT_SQUARE) / 2
     sy = SLOT_Y + (SLOT_ZONE_H - SLOT_SQUARE) / 2
    If Not Pieces(i)\valid : Continue : EndIf
    If DragActive And DragPiece = i : Continue : EndIf
     ; Taille en pixels de la pièce dans les slots
    Protected piecePxW.i = Pieces(i)\cols * PIECE_CELL
    Protected piecePxH.i = Pieces(i)\rows * PIECE_CELL
    ; Coin de départ pour centrer la pièce dans le carré
    Protected drawX.i = sx + (SLOT_SQUARE - piecePxW) / 2
    Protected drawY.i = sy + (SLOT_SQUARE - piecePxH) / 2
    For pr = 0 To Pieces(i)\rows - 1
      For pc = 0 To Pieces(i)\cols - 1
        If Pieces(i)\cells[pr * 5 + pc]
          DrawImage(ImageID(PieceImages(Pieces(i)\colorindex)), drawX + pc * PIECE_CELL + DesktopScaledX(1), drawY + pr * PIECE_CELL + DesktopScaledY(1), PIECE_CELL - DesktopScaledX(2), PIECE_CELL - DesktopScaledY(2))
        EndIf
      Next pc
    Next pr
  Next i

  ; Pièce en cours de drag (suit le curseur à taille grille)
  If DragActive And DragPiece >= 0
    If DragY < GRID_Y + CELL_SIZE * #GRID_ROWS
      ClipOutput(GRID_X, GRID_Y, CELL_SIZE * #GRID_COLS, WINDOW_H - GRID_Y)
    EndIf
    
    For pr = 0 To Pieces(DragPiece)\rows - 1
      For pc = 0 To Pieces(DragPiece)\cols - 1
        If Pieces(DragPiece)\cells[pr * 5 + pc]
          x = DragX - DragOffX + pc * CELL_SIZE
          y = DragY - DragOffY + pr * CELL_SIZE
          DrawImage(ImageID(PieceImages(Pieces(DragPiece)\colorindex)), x, y, CELL_SIZE - DesktopScaledX(2), CELL_SIZE - DesktopScaledY(2))
        EndIf
      Next pc
    Next pr
    UnclipOutput()
  EndIf

  ; Overlay Game Over
  If GameOver
    DrawingMode(#PB_2DDrawing_AlphaBlend)
    Box(0, 0, OutputWidth(), OutputHeight(), RGBA(0, 0, 0, 185))
    DrawingMode(#PB_2DDrawing_Transparent)
    DrawingFont(FontID(#Font_Over))
    FrontColor(#COL_GAMEOVER)
    CenterText(0, 0, WINDOW_W, WINDOW_H, Textes(#TXT_GAMEOVER))
    DrawingFont(FontID(#Font_Med))
    FrontColor(#COL_TEXT)      
    CenterText(0, WINDOW_H / 2 + DesktopScaledY(50), WINDOW_W, 20, Textes(#TXT_FINAL) + Str(Score))
    CenterText(0, WINDOW_H / 2 + DesktopScaledY(80), WINDOW_W, 20, Textes(#TXT_BEST) + Str(HiScore(GameMode)))
    CenterText(0, WINDOW_H / 2 + DesktopScaledY(110), WINDOW_W, 20, Textes(#TXT_REPLAY))
  EndIf
  StopDrawing()
EndProcedure

Procedure SaveUndoState()
  CopyArray(Grid(), Undo())
  CopyArray(Pieces(), UndoPieces())
  UndoScore          = Score
  UndoPlayingTime    = PlayingTime
  UndoGameOver       = GameOver
  UndoGameInProgress = GameInProgress
  UndoAvailable = #True
  DisableGadget(#ButtonUndo, #False)
  DrawCanvasButton(#ButtonUndo, GetGadgetData(#ButtonUndo), 0)
EndProcedure

Procedure RestoreUndoState()
  CopyArray(Undo(), Grid())
  CopyArray(UndoPieces(), Pieces())
  Score          = UndoScore
  PlayingTime    = UndoPlayingTime
  GameOver       = UndoGameOver
  GameInProgress = UndoGameInProgress
  DragActive = #False
  DragPiece  = -1
  AnimActive = #False
  AnimStep   = 0
  AnimBonus  = 0
  UndoAvailable = #False
  DisableGadget(#ButtonUndo, #True)
  DrawCanvasButton(#ButtonUndo, GetGadgetData(#ButtonUndo), 3)
  DrawGame()
EndProcedure

Procedure QuitGame()
  Protected Quit = #PB_MessageRequester_Yes
  If Not GameOver And GameInProgress
    Quit = MessageRequester("Attention", Textes(#TXT_GAMEINPROGRESS), #PB_MessageRequester_Warning | #PB_MessageRequester_YesNo)
  EndIf
  If Quit = #PB_MessageRequester_Yes
    QuitGame = #True
  EndIf
EndProcedure

Procedure InitPieces()
  Protected i, Img
  For i = 0 To 10
    Img = CreateImage(#PB_Any, CELL_SIZE, CELL_SIZE, 32) ; ,#PB_Image_TransparentBlack)
    If StartDrawing(ImageOutput(Img))
      DrawCell(0, 0, CELL_SIZE, PieceColors(i))
      StopDrawing()
    EndIf
    PieceImages(i) = Img
  Next i
EndProcedure
  
; ============================================================
;  Gestionnaires d'événements souris
; ============================================================
Procedure HandleMouseDown(mx.i, my.i)
  Protected i.i, hitPR.i, hitPC.i, sx.i, sy.i
  Protected piecePxW.i, piecePxH.i, drawX.i, drawY.i
  If GameOver Or AnimActive : ProcedureReturn : EndIf
  For i = 0 To 2
    If Not Pieces(i)\valid : Continue : EndIf
    ; Coin du carré de slot (identique au rendu)
    sx = GRID_X + i * SLOT_W + (SLOT_W - SLOT_SQUARE) / 2
    sy = SLOT_Y + (SLOT_ZONE_H - SLOT_SQUARE) / 2
    ; Coin de la pièce centrée dans le carré
    piecePxW = Pieces(i)\cols * PIECE_CELL
    piecePxH = Pieces(i)\rows * PIECE_CELL
    drawX = sx + (SLOT_SQUARE - piecePxW) / 2
    drawY = sy + (SLOT_SQUARE - piecePxH) / 2
    If mx >= drawX And mx < drawX + piecePxW And my >= drawY And my < drawY + piecePxH
      hitPC = (mx - drawX) / PIECE_CELL
      hitPR = (my - drawY) / PIECE_CELL
      If hitPR >= 0 And hitPR < Pieces(i)\rows And hitPC >= 0 And hitPC < Pieces(i)\cols And Pieces(i)\cells[hitPR * 5 + hitPC]
        DragActive = #True
        DragPiece  = i
        DragOffX   = hitPC * CELL_SIZE + CELL_SIZE / 2
        DragOffY   = hitPR * CELL_SIZE + CELL_SIZE / 2
        ; On calcule l'offset en pixels de la pièce en slot, puis on le convertit en taille grille
        DragX      = mx
        DragY      = my
      EndIf
      Break
    EndIf
  Next
EndProcedure

Procedure HandleMouseMove(mx.i, my.i)
  If DragActive
    If (mx < GRID_X + CELL_SIZE * #GRID_COLS And mx > GRID_X) Or (my > GRID_Y + CELL_SIZE * #GRID_ROWS)
      DragX = mx
    EndIf
    If my > GRID_Y  
      DragY = my
    EndIf
  EndIf
EndProcedure

Procedure HandleMouseUp(mx.i, my.i)
  Protected gr.i, gc.i, cellsPlaced.i, pr.i, pc.i, i.i, allUsed.b, bonus.i
  If Not DragActive : ProcedureReturn : EndIf
  GetDropCell(mx, my, @gr, @gc)
  If CanPlace(DragPiece, gr, gc)
    cellsPlaced = 0
    For pr = 0 To Pieces(DragPiece)\rows - 1
      For pc = 0 To Pieces(DragPiece)\cols - 1
        If Pieces(DragPiece)\cells[pr * 5 + pc] : cellsPlaced + 1 : EndIf
      Next
    Next
    SaveUndoState()
    PlacePiece(DragPiece, gr, gc)
    Score + cellsPlaced
    bonus = ClearLines()
    AnimBonus = bonus
    If Not AnimActive
      Score + AnimBonus
      If Score > HiScore(GameMode) : HiScore(GameMode) = Score : SaveHiScore() : EndIf
      allUsed = #True
      For i = 0 To 2
        If Pieces(i)\valid : allUsed = #False : Break : EndIf
      Next
      If allUsed : GenerateAllPieces() : EndIf
      If CheckGameOver() : GameOver = #True : EndIf
    EndIf
  EndIf
  DragActive = #False
  DragPiece  = -1
EndProcedure

Procedure HandleCanvasEvents()
  Protected EventType = EventType()
  Select EventType
    Case #PB_EventType_MouseMove
      HandleMouseMove(GetGadgetAttribute(#Canvas, #PB_Canvas_MouseX), GetGadgetAttribute(#Canvas, #PB_Canvas_MouseY))
      If DragActive : DrawGame() : EndIf
    Case #PB_EventType_LeftButtonDown
      HandleMouseDown(GetGadgetAttribute(#Canvas, #PB_Canvas_MouseX), GetGadgetAttribute(#Canvas, #PB_Canvas_MouseY))
      SetGadgetAttribute(#Canvas, #PB_Canvas_Cursor, #PB_Cursor_Hand)
      DrawGame()
    Case #PB_EventType_LeftButtonUp
      HandleMouseUp(GetGadgetAttribute(#Canvas, #PB_Canvas_MouseX), GetGadgetAttribute(#Canvas, #PB_Canvas_MouseY))
      SetGadgetAttribute(#Canvas, #PB_Canvas_Cursor, #PB_Cursor_Default)
      DrawGame()
    Case #PB_EventType_KeyDown
      If GetGadgetAttribute(#Canvas, #PB_Canvas_Key) = #PB_Shortcut_R
        NewGame()
        DrawGame()
      ElseIf GetGadgetAttribute(#Canvas, #PB_Canvas_Key) = #PB_Shortcut_Q
        GameOver = #True
      EndIf 
  EndSelect
EndProcedure

Procedure HandleTimerEvents()
  Select EventTimer()
    Case #TimerAnimation
      If AnimActive
        Protected aAllUsed.b = #True
        Protected aIdx.i
        AnimStep + 1
        If AnimStep >= #ANIM_STEPS
          ApplyClear()
          Score + AnimBonus
          If Score > HiScore(GameMode) : HiScore(GameMode) = Score : SaveHiScore() : EndIf
          For aIdx = 0 To 2
            If Pieces(aIdx)\valid : aAllUsed = #False : Break : EndIf
          Next
          If aAllUsed : GenerateAllPieces() : EndIf
          If CheckGameOver() : GameOver = #True : EndIf
        EndIf
        DrawGame()
      EndIf
    Case #TimerTime
      Select GameMode
        Case #MODE_TIMED
          If GameInProgress And Not GameOver
            PlayingTime - 1          ; décompte
            If PlayingTime <= 0
              PlayingTime = 0
              GameOver = #True       ; temps écoulé
            EndIf
            DrawGame()
          EndIf
        Case #MODE_SURVIVAL
          If GameInProgress And Not GameOver
            PlayingTime + 1
            If PlayingTime % #SURVIVAL_PERIOD = 0
              PushRowUp()            ; fait monter une rangée
              If CheckGameOver() : GameOver = #True : EndIf
            EndIf
            DrawGame()
          EndIf
        Default  ; classique
          If GameInProgress And Not GameOver
            PlayingTime + 1 : DrawGame()
          EndIf
      EndSelect
  EndSelect
EndProcedure

Procedure HandleButtonEvents()
  Protected EvtGadget = EventGadget()
  Protected Quit = #PB_MessageRequester_Yes
  If EventType() = #PB_EventType_LeftClick
    Select EvtGadget
      Case #ButtonNewClassic, #ButtonNewTimed, #ButtonNewClearance, #ButtonNewSurvival
        If Not GameOver And GameInProgress
          Quit = MessageRequester("Attention", Textes(#TXT_GAMEINPROGRESS), #PB_MessageRequester_Warning | #PB_MessageRequester_YesNo)
        EndIf
        If Quit = #PB_MessageRequester_Yes
          Select EvtGadget
            Case #ButtonNewClassic   : GameMode = #MODE_CLASSIC
            Case #ButtonNewTimed     : GameMode = #MODE_TIMED
            Case #ButtonNewClearance : GameMode = #MODE_CLEARANCE
            Case #ButtonNewSurvival  : GameMode = #MODE_SURVIVAL
          EndSelect
          NewGame()
          DrawGame()
          GameInProgress = #True
        EndIf
      Case #ButtonUndo
        RestoreUndoState()
      Case #ButtonStop
        Protected r.i, c.i
        If Not GameOver And GameInProgress
          Quit = MessageRequester("Attention", Textes(#TXT_GAMEINPROGRESS), #PB_MessageRequester_Warning | #PB_MessageRequester_YesNo)
        EndIf
        If Quit = #PB_MessageRequester_Yes
          GameMode  = -1
          ResetGame()
          GameInProgress = #False
          DrawGame()
        EndIf
      Case #ButtonQuit
        QuitGame()
    EndSelect
  EndIf
EndProcedure

; ============================================================
;  Point d'entrée principal
; ============================================================
InitLang()
InitDPI()       ; <-- calcule toutes les dimensions DPI en premier
InitColors()
InitPieces()
InitShapeDefs()
LoadHiScore()

LoadFont(#Font_Big,   "Nunito", 22 * (DesktopResolutionY() / FontFactor), #PB_Font_Bold)
LoadFont(#Font_Med,   "Nunito", 13 * (DesktopResolutionY() / FontFactor))
LoadFont(#Font_Over,  "Nunito", 32 * (DesktopResolutionY() / FontFactor), #PB_Font_Bold)
LoadFont(#Font_Small, "Nunito", 10 * (DesktopResolutionY() / FontFactor))
OpenWindow(#MainWindow, 0, 0, #BASE_WINDOW_W, #BASE_WINDOW_H, "Pure1010!", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget)
CanvasGadget(#Canvas, 0, 0, #BASE_WINDOW_W, #BASE_WINDOW_H, #PB_Canvas_Keyboard | #PB_Canvas_Container)
CanvasButtonGadget(#ButtonNewClassic, #BASE_WINDOW_W - 140, 90, 120, 40, RemoveString(Textes(#TXT_CLASSIC), Textes(#TXT_MODE)), #True)
GadgetToolTip(#ButtonNewClassic, Textes(#TXT_STARTGAME) + " " + Textes(#TXT_CLASSIC))
CanvasButtonGadget(#ButtonNewTimed, #BASE_WINDOW_W - 140, 140, 120, 40, RemoveString(Textes(#TXT_TIMED), Textes(#TXT_MODE)), #True)
GadgetToolTip(#ButtonNewTimed, Textes(#TXT_STARTGAME) + " " + Textes(#TXT_TIMED))
CanvasButtonGadget(#ButtonNewClearance, #BASE_WINDOW_W - 140, 190, 120, 40, RemoveString(Textes(#TXT_CLEARANCE), Textes(#TXT_MODE)), #True)
GadgetToolTip(#ButtonNewClearance, Textes(#TXT_STARTGAME) + " " +  Textes(#TXT_CLEARANCE))
CanvasButtonGadget(#ButtonNewSurvival, #BASE_WINDOW_W - 140, 240, 120, 40, RemoveString(Textes(#TXT_SURVIVAL), Textes(#TXT_MODE)), #True)
GadgetToolTip(#ButtonNewSurvival, Textes(#TXT_STARTGAME) + " " + Textes(#TXT_SURVIVAL))
CanvasButtonGadget(#ButtonUndo, #BASE_WINDOW_W - 140, 300, 120, 40, Textes(#TXT_UNDO))
GadgetToolTip(#ButtonUndo, "Annule le dernier coup joué")
DisableGadget(#ButtonUndo, #True)
DrawCanvasButton(#ButtonUndo, GetGadgetData(#ButtonUndo), 3)
CanvasButtonGadget(#ButtonStop, #BASE_WINDOW_W - 140, 390, 120, 40, Textes(#TXT_STOP_GAME))
CanvasButtonGadget(#ButtonQuit, #BASE_WINDOW_W - 140, 440, 120, 40, textes(#TXT_QUIT))
AddWindowTimer(#MainWindow, #TimerAnimation, #ANIM_DELAY)
AddWindowTimer(#MainWindow, #TimerTime, 1000)
BindGadgetEvent(#Canvas, @HandleCanvasEvents())
BindGadgetEvent(#ButtonNewClassic, @HandleButtonEvents())
BindGadgetEvent(#ButtonNewTimed, @HandleButtonEvents())
BindGadgetEvent(#ButtonNewSurvival, @HandleButtonEvents())
BindGadgetEvent(#ButtonNewClearance, @HandleButtonEvents())
BindGadgetEvent(#ButtonStop, @HandleButtonEvents())
BindGadgetEvent(#ButtonQuit, @HandleButtonEvents())
BindGadgetEvent(#ButtonUndo, @HandleButtonEvents())
BindEvent(#PB_Event_Timer, @HandleTimerEvents())
BindEvent(#PB_Event_CloseWindow, @QuitGame())
SetActiveGadget(#Canvas)
DrawGame()

Define Event 
Repeat
  Event = WaitWindowEvent()
  If Event = #PB_Event_Menu
    CompilerIf #PB_Compiler_OS = #PB_OS_MacOS   
      If EventMenu() = #PB_Menu_Quit
        QuitGame()
      EndIf
    CompilerEndIf
  EndIf
Until QuitGame
SaveHiScore()

;- =================== DataSection
DataSection
  FRA:
  Data.s "SCORE"
  Data.s "MEILLEUR"
  Data.s "TEMPS"
  Data.s "PIÈCES DISPONIBLES"
  Data.s "PARTIE TERMINÉE"
  Data.s "Score final : "
  Data.s "Meilleur    : "
  Data.s "Appuyez sur [R] pour rejouer"
  Data.s "Mode Classique"
  Data.s "Mode Chrono"
  Data.s "Mode Déblayage"
  Data.s "Mode Survie"
  Data.s "Annuler coup"
  Data.s "Quitter"
  Data.s "Arrêter le jeu"
  Data.s "Vous avez une partie en cours, " + #CRLF$ + "Voulez-vous vraiment quitter ?"
  Data.s "Démarrer une partie"
  Data.s "Mode"
  Data.s "@@@"
  
  US:
  Data.s "SCORE"
  Data.s "HI-SCORE"
  Data.s "TIME"
  Data.s "AVAILABLE BLOCKS"
  Data.s "GAME OVER"
  Data.s "Final score : "
  Data.s "High Score    : "
  Data.s "Press [R] to play again"
  Data.s "Classic Mode"
  Data.s "Timed Mode"
  Data.s "Clearance Mode"
  Data.s "Survival Mode"
  Data.s "Undo last turn"
  Data.s "Quit game"
  Data.s "Stop game"
  Data.s "You have a game in progress, " + #CRLF$ + "do you really want to quit ?"
  Data.s "Start a game"
  Data.s "Mode"
  Data.s "@@@"
  
  RUS:
  Data.s "СЧЕТ"
  Data.s "РЕКОРДЫ"
  Data.s "ВРЕМЯ"
  Data.s "ДОСТУПНЫЕ БЛОКИ"
  Data.s "ИГРА ОКОНЧЕНА"
  Data.s "Финальный счет : "
  Data.s "Рекорд    : "
  Data.s "Нажмите [R], чтобы продолжить игру"
  Data.s "Режим Классический"
  Data.s "Режим На время"
  Data.s "Режим Очистка"
  Data.s "Режим Выживание"
  Data.s "Отменить ход"
  Data.s "Выйти из игры"
  Data.s "Остановить игру"
  Data.s "У вас продолжается игра" + #CRLF$ + "вы действительно хотите выйти из игры?"
  Data.s "Начать игру"
  Data.s "Режим"
  Data.s "@@@"
EndDataSection

Re: Pure1010!

Publié : ven. 17/avr./2026 9:55
par Mindphazer
Partie 2

Code : Tout sélectionner

DataSection
  Cube_png_start:
    ; size : 9494 bytes
    Data.q $0A1A0A0D474E5089,$524448490D000000,$5201000031010000,$7F67150000000208,$4E527406000000CB,$F1E500E500E50053,$7009000000824BDB,$00C30E0000735948
    Data.q $64A86FC701C30E00,$54414449B6240000,$D79457F79DEDDA78,$889278E37F9FF7DA,$D0C0330C3A197A5D,$4BA501114044DE91,$8C4B180A08A820EF,$49C931A3468D462D
    Data.q $9CF3EF5DEDFDE49E,$49A2DEC7B05522B5,$EFDCCF7328BB124E,$94C332A2A20333DE,$18F1162EFAF77CBB,$BEEBAEB87F7B99CD,$16162BF5FFDAF7F6,$C2C023E17FD69716
    Data.q $0B12605858589302,$2C49816161624C0B,$B12605858589302C,$C49816161624C0B0,$BBE791DDF67AFB7A,$B316345E1A3B47BA,$0CA2D9CBA5A359E5,$970B654FCD9520B6
    Data.q $EBF24CEACCE945B0,$AEE8FD7B6542FAAA,$4981A1F04777E52E,$1B47BBBBC7AFE32C,$B662DE6C6985D48A,$D8F2EB66CCAD8338,$612A6D88B1B62286,$92AC27BE44EB579B
    Data.q $77E43DF92BFF245F,$DAAA2084B85FDF92,$774D624C118F89D9,$E5198233FF6AFC3D,$29ADD4A3CDAD8D2A,$04FDF9A494E0497D,$A1BA8A557674A2D1,$1260B07C33F47548
    Data.q $9523C39BFF75EF4B,$72872AB624CAEC39,$90FE49C1938A37A8,$1EC15F2CCFF495EA,$754D624C190F803F,$B2566A721108213D,$3F910DF146D3652D,$E2FA9224DCDC8493
    Data.q $BBB1A3EF589306A3,$8E4A72D96C986485,$4158ACC93BE36211,$B1260EC7C66CECC9,$A614CA7E0E0F5926,$49068D1486A777D3,$BD5520B33A93129B,$ADD2C498011E0B77
    Data.q $24799482F37D3F47,$6F7D59249817D63C,$0AF97B7FA62C6CC0,$E8A4C038F187B7F5,$AD9137365AB6D593,$3999166F8D00B5CA,$14980A1E29736C89,$58E4DA26E9FC7AE9
    Data.q $5953D4E3A5E4CCBD,$ECC995D94A425FF2,$75A22930203C56E6,$FCD9CBA517C1D8FF,$34F2CCA6BFC5B4C5,$C2DACA4AF92646BE,$A4C0B0F04F81F574,$36812730E108D7F0
    Data.q $A96BE345B9CA5BF1,$FDD0A4980D21436C,$7AE614981A9E18E1,$9C158AC74B44D9D6,$E49329CB3215F1A6,$14981F1E056D79BF,$8328B2BB7FB8E956,$17B31C89CE338F9E
    Data.q $5B7614BCD933AB99,$F07AFDE498251E1B,$15247223DA17F1C3,$99166F8D13E3296C,$DDCBF632C96CA905,$BAE9EBAF9260AC78,$F5649BCB96494D2A,$53FA3D017D6645BD
    Data.q $C17CF16F9FFEC79B,$B2683A4FA3D69F24,$64AFCAAD7D197AB7,$322D0E5566452A75,$D03E498341E0D437,$F34D2964B29F6478,$32BCA1E630E7D838,$BA7ECC5FCCDFFC96
    Data.q $D68D77724C1D0F11,$A5C79F2EB1D2D015,$74C54DB196641EA3,$3C3ED5FB266941BE,$A36364F5ADC9307D,$2B5F1A0A2D91CFA6,$036C42AFCEB4EB32,$4C7D9F39178DC930
    Data.q $4C39F5FE0CA2D533,$26012D80D8DAFCE1,$39F694777E1EB62D,$E3C2D8855F50A556,$3F7B5D819A5F9D5B,$5BCF5EE69300F6C6,$E902559AB911E9CB,$8E98B795F9D71873
    Data.q $9A4C04FB08713917,$A51CFB46DADE3D63,$ADF0E0A5CD00519A,$186C7BE44995AFCE,$5D6ED0F1D2CA6930,$5EA3A5BC44B9A39F,$2DDD1353D1659664,$CE946BF8D2603CD8
    Data.q $175E0028CCB44A95,$BFDAA34C28952499,$B48D671A4C08BB1D,$1D28D995F61FD3D7,$AAC32FA22AFCE1A7,$93028EC2BFEFD972,$9AF955BBBB27AF86,$4C911873EE62E3B9
    Data.q $4C0B5B1CB5ABF3AD,$0B524A4389E34FEA,$ABF3BA30E7D12011,$CDB1EBADCCC69334,$E9AB35D59394E4C0,$3A9346824052738F,$1BF61768720248BF,$BE95B9B67AD77C98
    Data.q $FCEB4863C8C337C1,$6C5B7C9817E7095A,$236CD07AF743B83C,$8674B955992D218F,$ADD4982136355B65,$F78AB35A337D3FC7,$A32C96645EF800A3,$AFB1498074767FA7
    Data.q $5CAAE90FE86A1B17,$750953664F2C39F4,$4CEC4BF3AF16AD7E,$64A03B26A9D9DD3E,$A9F2BF398E474A29,$59298A4C10BEA4BF,$A5334E5D29907E3D,$78FBE0028EC162A6
    Data.q $3046A6E64A6C8A91,$147448249CF5FC29,$8ABF381E55921E40,$A05260DDDDAFCE35,$59E57223D3357634,$F9CE88BC69F073F0,$50149805F37EC595,$1CFA017576FF71D7
    Data.q $254DB224E57E773C,$A99C70FE34FF9260,$0010E7D0B927A5CA,$0D6BA3BA925A2499,$FD155D639F6DE498,$C8AA0A3412BD5AE1,$036F9FB0963B47A4,$6C69DBDB235A7C93
    Data.q $5F9D70873E899D5C,$60A3AFFB0E656CC9,$AB339FA38E7DF392,$BE08014633D6D197,$012FCE604AB3525F,$48921F485F5A3932,$9A72D7E73A431E46,$9EB5B9260B596D13
    Data.q $3B57479FEAD13676,$FD8338BA58BF4642,$B3F1D281C93053E2,$C400A3039FAD6A2D,$DA124D2C5CD2FCEE,$EFC6C50B49804E9F,$58DB3271E474328E,$972BF3BB1A156484
    Data.q $4CDF8BF3A7E3CA1E,$8F231564D396B68E,$9307693EBF3877A1,$BE9AD1B5B7564966,$8D7E77DDE80E7D14,$A3269305EE8EBF39,$431E4631556EF0F1,$09A4C00AEABF3BFA
    Data.q $0C79188ED5DD5592,$75926D3665664FE9,$F5ED17ACE34981D4,$A6846836655C88F4,$0BBBBD2C5CD2FCE7,$43F4DDDDC6834E4C,$9D11901CFA251F24,$49800FAFD9CB655F
    Data.q $15F2998713B3D6FD,$4C80028C46AAFAF4,$5F9CF7264522FCE0,$76AF4A5CD95265DC,$AFCEA4C80028C5AC,$7C983367450DF415,$073ED2D78FD59BE7,$9914B3211A0C791D
    Data.q $60ADBEDE5CF4E945,$51752ED0F5648DF2,$B99000518A985B06,$6CCAAFCEE6A36603,$FC6C4D49825F5FF6,$11527A3C9AD1DBE9,$FCEB532416423B57,$350DCA933B17296A
    Data.q $37108D01CAAFA734,$F9C8583C34995F9C,$6FA4ECEF9F266165,$FCE93880E7D04BA5,$F261621DC1E67522,$3F28D3F26A03B1C5,$7EBF381E218F2315,$344A9B2A4CE05AFC
    Data.q $3207C423B57000A3,$2614ABAD7E7735AB,$8DD5A8DA66AECA93,$AE6453F88723C63C,$9870837DBD2C5CD6,$518E985D43B0391C,$4ABF3AD4C98F1000,$CF9337E1EE5FB196
    Data.q $1DAB895EAAAE387F,$7CA4E6B4BF38A121,$791B1CABACC932BE,$548BC6809039438C,$5F264265F9C898E6,$0C79181CFB41D27C,$D7B5AB195E50F609,$7E8FCF933AE4EAEF
    Data.q $FA37F9263C8ED6AE,$2F53148BC7C0901C,$328E7EF8F672D961,$863C8C249D2DA4A9,$B88A1B644AFCE7C4,$1E3B360E8EC8E4C5,$99689264BC480E7D,$F263463FA3CD3893
    Data.q $01CFC23C6D117D45,$C7159B1141887D89,$F36ACF9330B56E6E,$808559BC56C0E1E9,$DEDD9E22BEFDA6A5,$7CFDD81EEF261966,$79E056B59D751469,$8EABC457324BD040
    Data.q $BAEF6DAF266E6E7D,$11EF46ACB6C4E7E3,$8CCEAC53F438DE82,$BDE4C7CCC75FF3FD,$187A03FF30313EFF,$F24D04019E354360,$F9BBB05EF4A5A7CA,$F48EDC6673BFFC98
    Data.q $001E2426D0D7BB65,$13B22F758DA9BD04,$91D3C98399E65D7A,$066151E3FD5B7FB2,$AE4D043D1F1EA9BB,$ACDDB0E55D760AD6,$ADA37932D320B8C1,$4F8EA4063399E7E1
    Data.q $21E8F8049F92968B,$E45A5D13964C2DE8,$DD1DEDC7FCFFBFF7,$F90E7FBCE4F26426,$825BCA3FDB79F438,$B64ABAD56F410938,$C2EB80D7B05CF8B1,$5C387262A6999B1E
    Data.q $E3D1E146756B6FDA,$88D9DB0C465BF361,$91FAA6D72682127A,$EE15A70E3E03E5D2,$F8D238BB3C3F0BFD,$095AC931F9DEDE4C,$3174DFC95C03A790,$24CE8B5824FE97DC
    Data.q $238B3BA6AEA64D04,$D02676E81D3AF448,$C87D7DBF19AB67ED,$5BB90FE64BF64CC8,$B2FE44493080BF93,$84A8466EED7D24C7,$55506CE8884457A0,$285CC90E3A941AAF
    Data.q $F94EF3CE53F70A2F,$3D2575ABC9931B39,$94127EAB524175B3,$5816A3A61F695C03,$28135437204BD042,$333DB4F5EDF7097E,$D6E33567C568C316,$D67ED7B26346F5E6
    Data.q $E64FA5CCBF438F90,$25FC065DC80EBE4C,$B61F70D9C175CFFF,$C8169042580A86BD,$24272741F19BC6CE,$FDD61E436E815495,$E1754AF261C6361E,$6AEDC02063FF67BF
    Data.q $B251FBD2911FE788,$D2913FF5F2325107,$EB540263378EBE8B,$ECACA488212D102A,$61C8048171EB9A86,$C9E542C7204BC97F,$C9811AB6746E3359,$24F8EA4E7D9875FF
    Data.q $6CC129B10726CE46,$7CF50E3FDF3498F2,$D035376A03A0A892,$D71E184484C80C9E,$2EABD5A3CDDDB257,$189C804908D37A86,$53EB7729E542C724,$66A5B17932E9C752
    Data.q $5021084A6C07DE78,$90526C437AA8109D,$3482D8C8C4CA4A3A,$3DE0ED4C049626FA,$D43892340C482A3C,$331A5DDC56B6C4D5,$0A449C86B130E3E0,$3EDDEEEE33D99EF7
    Data.q $24F30EA29FC9262D,$15129D480C9990F1,$1C5EA3E1133918AA,$70DB65AF6CD9EF4A,$24269A8D3A121D36,$79259C96F20F4209,$0177E73F29F59BA9,$26CFB30E039509A9
    Data.q $7E87E3EDE4CE1884,$9017790E2ECB9E77,$ECBE9132922CC413,$0D3D6367923A18B2,$74E5DF509098089B,$F7928E5CE4548E35,$C687BFDB7BF75BB8,$11A6AD6D7A5DC971
    Data.q $24D56C7CA9572B27,$03E3301A498D4E0C,$4D326E6CA9A4C048,$84C8258351D63762,$49BBB60ADAE34304,$D8A08C253B7C58DD,$520253800DAB61EB,$A1B1B8CCE67B3BF3
    Data.q $11B0578EFF2640D1,$FEB19922720553DE,$CA5A2D86F937B84C,$884C8A2CD9A2AFAE,$B6C8D5DC3D9234EF,$212E587122B1FD55,$69D4CCE5CC90EAC9,$E1C9739CE3A0D31C
    Data.q $F9C6C24030F93206,$8CB44C9918E4CDEB,$0EE8DCE9C24B9916,$557C42D1E1566452,$D978B8F0D9DB1D47,$A3AF80E3421F5085,$E830EBEC356A3401,$6CAE144F93206369
    Data.q $BE99165F2640DCAC,$229097ED2C666C44,$7D4F884C047E8493,$AEF26B2AAC922A8E,$ECBCFA6C3D7A29C5,$6FBD25FCA5F1430C,$55C2A5499FBC8A71,$72991427265D3315
    Data.q $D391FD396B58617A,$BA39F41E21320652,$E83D1E9BBD5EC89B,$7870600939A3D8EB,$67BEFC1FF99EA89C,$4E081CFCAA4C219B,$991484BF627265D3,$7A6AB6B0C2F44149
    Data.q $A39F6EE21E0F0F22,$8CF532BFBDAF6D81,$9C98BD0E7D4A7DC2,$A4CDEAD73B5FCFF7,$7C98F1A9186FC7EA,$922D3322D1FA6459,$080624930122D88E,$ABA2D12480A71098
    Data.q $68FC8B4B8AD959F1,$C78E3488C1C7C39F,$84F2600C1A1B3BC9,$4664524C06D499F1,$6D9E2B36525132FA,$75C685710991462C,$4CDD143555592495,$31CFBBD3B2F7ED0E
    Data.q $3B8DA7707C172675,$F24C8B4719938E4C,$7331249845C25E95,$94B63442C84C8A0D,$C797DFCAFAC73ED1,$C90F5BBA4E5CC90F,$177AAD468098CE5D,$324CDEBD7D7B787C
    Data.q $6CA9E39321371C3F,$E96C21C999168C8C,$6408B6150D437672,$FEA9BB1D6371D2E6,$3A522F10F9C66151,$264BE3474D1D4A0E,$6726D7E4C01AD6D7,$FA44C7E5125FBC72
    Data.q $9168C36BD11633A8,$A36C805990794389,$03635795AAD18E7D,$C992F8D3130E7D74,$31B331FDF9300675,$32D130FA4497EBA9,$CE1EABA3F3513B36,$BFA5358E7DE4C82F
    Data.q $631B0F0E7DA22DA6,$4CDE9D64CCA639F5,$1337B52315F5FF2A,$F8BCA1CD4C8B2F93,$EB911E1320BF3800,$214DCEFE6BDB606C,$D5DCC261CFBD1A10,$7E74BE645ABE4C02
    Data.q $A78E7DA8C81256E1,$ADDC7B4844BF59A5,$B7932298E7D04C07,$A3BBF47266F4AA5A,$15F9DD7C9825AF8C,$CFA31905F9C2D6CD,$1491BC2FAAACD5D1,$3EAA69EBD769E7D2
    Data.q $996588F6FC992987,$6417E70F55F9CC9C,$665BF93089A39F50,$72439F4D273F29EC,$879AB2604E3442C6,$8B64084AFCE6BE4C,$6C73EEF482FCE032,$F3D82E7690587BAC
    Data.q $C8A639F43342DBA4,$87138BE4E2034DE4,$8D54AFCE6BE4C139,$A32A682FCE1DABF3,$F6895EE6545E9A00,$CD3FB6F3EEB0F1EF,$C15CD1BC99C71A01,$051CF482FCE12673
    Data.q $E3E0311A9DBFBE40,$DD7C98E8873EE660,$BD05F9C3B10745F9,$D27657FD50D8E7DA,$C994700147C37F69,$3B939322E0BFC7E7,$C453205F9CC6AABF,$CEAC9F2012D47640
    Data.q $A60051CD3BEE18BC,$498D0BAF0F82DF56,$3F50014657A0BF38,$CFB8213D7F9B5307,$B931298E7DB2D6D3,$793006658D6BA3F0,$13549334E3B5F190,$CFAF897E70715F9D
    Data.q $D2DEE2B6BC7919A1,$C3392E58639F6D18,$0757C8E4C5A71A61,$57E70DF2069C9328,$50051A625F9C3FAC,$DC4EC79184F41E4F,$87C03B1E4C7A71A7,$8897E709915AF938
    Data.q $19CC79180DCF1CFA,$BCFDD1E4C21AAF26,$15F9D4B366AF9389,$4BF382ACD57E71A1,$ADF1137A2E8E7D80,$403908BD22827094,$D6AEF7D240579A72,$67C99BD12FA8DD1F
    Data.q $5F9D139327E73E47,$7E70907D02766C7E,$1CC7918C61CFA309,$1E4CFEB15D66F261,$E1D57E756F932DE5,$326ECB51D55F1E50,$9C486930CE63C8CE,$A57E735F266FC7DC
    Data.q $E7098DB459E5B284,$BC71E4741CFB0F17,$F98F2308D6C3D7A2,$CBE4C1052FD3E4CB,$FCE7445E3A5222F1,$B400A3378BF383AA,$09CC791CC6A58F23,$CEABE4CEC48A6B26
    Data.q $B932285F9DDD24AF,$F532BFB9AF68E7DC,$9B499E5B1E4609AC,$F0F267F40BAA3799,$F9DC9C98808F8C67,$3C01473717E70955,$C9C40E63C8E1372B,$451BE4C10BAB3799
    Data.q $A58B839155F9D6A6,$50DD49BBA00A3439,$398F23A4CC252B74,$BC3E3E4CFE8D64C1,$C02AFCE24E4CB057,$3C8CD0028F4B3CA1,$639F73E63C8CD2CE,$AF955AEE4806674A
    Data.q $CE2BE4CF8487933F,$BF3846D7E71A95AF,$8DF322E3C8ED2ECC,$E4C0AB159304E63C,$85AAFCEED7CC8BBB,$3DCDAB8F237CCBF3,$CDE9E6564C1398F2,$9C24C2C47B43A3E4
    Data.q $D0EBE03C791D165F,$FC9929873E9C21E3,$919A25F9C24C6442,$A4E2157CB2609CC7,$F4532FCE062FCEDE,$4C0B98F23F2D3A39,$5F87C99BD1CD2F5E,$6BE4C8C56C7C66EC
    Data.q $839F5E32FCE045E3,$2E5964C1398F2323,$0BF3BF1CC8B43498,$8F237439F4E9AFCE,$3FF24C18F230B99D,$8D69AFCE1322D260,$CFA28B1E474F3E3C,$393041C1F5DCC261
    Data.q $E02ABF39D18BF389,$71E46C639F5F7AFC,$A60051B7C1CFA68C,$01B6497AEAD6D265,$A22F1D6F9302EE4C,$235DEBF3806D7E75,$31E4737246A4EF8F,$6BF391349824E207
    Data.q $37AFCE1A58BD1469,$F23B593B27FF1E46,$E701C9300E7D8458,$91771270A6924E57,$3C8FEE72F1E472F9,$980564AD7AEE42E6,$12FCE350ABF3B134,$0AEB8F23E3D2C5E1
    Data.q $BC8AD87AF70427AE,$4983970B265531CF,$B186A751F1178F53,$F23EBD7E7222D915,$E4CAF98F232F91D8,$AD862BF3A069307D,$1E472FD2C5F8102B,$813A941E3C8F8ED7
    Data.q $BFC99FD22C983D46,$B852B9914E9C9FD0,$77F2371E46E97E77,$DB7D8BE4E35F31E4,$6C41895F9CB4E4C0,$45B1E3D2C5DD32F1,$5EE3C8D8F50E7D10,$A4CDEA4015D8F23A
    Data.q $C9337AA5FCD5D59D,$F4B1708D260CD9EE,$E1FBBE972AB60892,$C8C810E7D74BF3B5,$4C05BBDEA932BE63,$E3CBB2928CC8A71A,$47C6BF3B1E2286D8,$263961CFA0F9871E
    Data.q $57E77C8D260C7CF7,$F99151E4C3DA62DE,$EE4C32D200C791B6,$BB3057E70A6AEE46,$6BF3B8E123BE933A,$A10CDDF96B40147C,$E6AEB39300E63C8D,$9C69A4E224C01BA5
    Data.q $F3AEE48F4CC8A45F,$84EAF92068E7D74B,$2BC9991873E8C791,$1BABB3C77FF4D2AB,$AEC7E515F9D09A4C,$1B1CC8A6717E7718,$4C91697D9E523C79,$24C12711398F23A8
    Data.q $CD95F21F70CC8B17,$F287A2C45E36325F,$450DD59ABA00A3B4,$4C18F23D85439337,$C212954BF3B9EF42,$46F888BC6C596596,$725759FB499E5B1E,$69304ECEE4CFE897
    Data.q $E6980D1E4D57E76E,$16C791CE2257943B,$2600D52732613F57,$B196962FD9A4C0BB,$3C8F8D7E72668939,$F932DE63C8DD12AE,$BAE95F9D05A4E229,$051F1CC9D14DA58B
    Data.q $5188EBE83C7919A0,$C775DC90D2601600,$68C2BF3BD1693026,$58C7FA774ABEB991,$CAFFE01000CE6A40,$99304E63C8ED1649,$2E1693049C40629D,$C788B4997C8B5532
    Data.q $751B3AD9124A69F9,$FE48737AA535AFFE,$3557750367628215,$9BD421749D95FF16,$4C62C39F45F63C8E,$046E4E20364ACE5E,$27D251B264EF1693,$84A6AF7DC2575E61
    Data.q $A0DE251B1CC92D3F,$A92842469298C6BD,$048FF22E3B8A493C,$B6A236FC851FAD5D,$5BF482A3E17D752A,$7D0ABBAD420461C9,$3F2600C2B9330B0E,$A41C9B105C9300E9
    Data.q $771FFFB6F19D918A,$7E8213D79EC1739B,$B64545F3C1258CCF,$58428E087740AEBA,$AAAC58D9609443A9,$F52AB07ACB291BC9,$0A338098D5F47A5E,$4A0E37523B4F3EF7
    Data.q $E49C44997F04809D,$53620A4CB04B1246,$BECBDBFC7B04AF82,$D6952E3347B6D3D7,$E45A5E8592770A81,$1D1ABBC04E4A2577,$E21F3D2914B9BE40,$728BCFAFC1206245
    Data.q $629C8A03F29EBE48,$DC99FD24ACE5F672,$F0726585B9260EDE,$5CF24504938F60A5,$C06D2109724325FD,$04A2E481C7DFB1D7,$A941C7F90DF2223C,$E7EEC12E58762123
    Data.q $E826672FB30E9328,$932C31C93036E4CF,$3EB740B9C524D883,$22264CDF884B0699,$C07C6560CB030A4E,$F25805DC80C97F29,$375B93006E5D773B,$3F721299622E4980
    Data.q $6E6C7F53524BD64A,$0724C0DB5BAEE5B1,$D6F508DF0658A6A5,$7D9C74991F109615,$1EFBD414981C6969,$D8B0649201206275,$C9307ACB726262DF,$83247E45EFF60CE5
    Data.q $05260AEE69E6FEC5,$5D0726C151209077,$C4F14B0193E8F60A,$CA876E4981D78FC9,$30CB997EB23147E0,$2329739C98FF3976,$5C9305AF37267F46,$13C425741C93D97F
    Data.q $831E92FE4C8F92A1,$465A30F950CC2938,$458C9C61E4A84498,$18B8A4995568149C,$E411746C583241E4,$A658079260ADDDAE,$7E580BC52911FF04,$0651692FCE69C069
    Data.q $82932607C93049C4,$FC875DFD87FCE246,$42892E4C579CE271,$E9BC249E9BEE149C,$23DFD7D2C7109301,$FC930577218ABE90,$97283E4638F04419,$4BFB9C987F2BEDE0
    Data.q $BE4980B64C01A46A,$740B9C07C6557DBC,$B8BC987F3313053B,$244CA4B70A4C0238,$F088E8949482A525,$81764E20362E4E29,$F1BD4337AFA53E49,$D72610D27157879A
    Data.q $986BFC1930FE4980,$F3CE8345F0F35E0F,$C99C0A4E2044A42E,$87264C579260E1BB,$849824E2334F7FEB,$982764C81ABB944C,$271579260AEE55E4,$897109304980A7CF
    Data.q $DC424C12604973C9,$3050C4B9DE65D261,$E849810930212609,$99FD30A4D9EBB92D,$A5C424C1260CD4DC,$5EA26424C1260938,$093020F885FE6488,$4C08498109302126
    Data.q $4C81A4F507884982,$930D32126093046E,$64C01A06C7CE0BAE,$424C085779C49813,$8849824C12609388,$0930498234764C1F,$4498037F68C98A99,$173C98A99093049C
    Data.q $EF101FD989388FE5,$84981093049824E3,$916E785C9828A4C0,$849824C01B2600CC,$609173C2DBA4C24C,$5260938A9C424C12,$10849832E6624C14,$982908D773032127
    Data.q $C2FBA4C338849C44,$1C424C1260BEE1B3,$0424C1271167938A,$B5772DBD09302126,$C424C12603EE1B3E,$304982864C229D15,$01DE4C9CC8498109,$49824C0C3262FC93
    Data.q $0DE938907A4C3B88,$CE6D261DC424C126,$8A71093049827B04,$312E212609302F49,$981F64C045260219,$2610C849810AEE44,$9824C03C28CF6D3D,$093021260424C084
    Data.q $4F48498109302126,$4981BA074F6CBD26,$305700C989710930,$424C0849C4212609,$7A4CF85260938D6F,$2E5A776930FE4983,$C39310E212609301,$6510D1DC424C1260
    Data.q $24C1EBDB267F45D2,$95F92605BA0C987F,$24E3C0A4C04BFABB,$FE884CF9A797E498,$424E23A77716669E,$C1090BBCCB80D1A6,$06F19BABBA39337A,$46F24C143261FC93
    Data.q $9BD12EE4AEB3767D,$61DAFA509E3FE7C9,$F799EAE8C84983BB,$D649337A35B5EDC1,$1E3B0C8C754F508B,$07A3CFF26746424C,$C83AA2456472610C,$B0D446424C1E3B15
    Data.q $7B894982EBA0D39F,$369E549B1BA3933F,$8C84983D360544AA,$50C485CE69C782F6,$929283E94B249903,$A050BC9304DE4C1F,$6AD4DD7E3339C9FB,$7760D9C24B239338
    Data.q $9571271909307A6C,$29B70DBD59D9F4B9,$A17DCA9B4B62F931,$D3424C1EFB08292A,$A62EB3F6FD6E920E,$04A0658A498B4C44,$DC29046424C15F6F,$4D9F439FF19ACE4F
    Data.q $0D979522FAD1C997,$072419A684982542,$266F55CC7A4C175D,$6C723154ED7C62C9,$8F0A33AC1909307D,$38DBB3B6FC66AD9F,$55AD3CA894348E4C,$2C321260FDD8C1C9
    Data.q $BF39961BCCB80E48,$DCA555A4983D341B,$8498255E8BE91D49,$D263399E7F24AB0C,$66F77CF933863BB3,$0C849825423E6495,$2121747E177B5AC8,$950D24C7E994BDE4
    Data.q $58092A93B92A9169,$59AB92601BC99172,$A70F82EF5D9790EB,$D8F58E6A4CDE9882,$1E909305832116AA,$A7476F7AD6487707,$F196281BDA6498A9,$5ACFEF424C00C001
    Data.q $464BF199CE4F3C83,$AEDA498432F914CC,$E4AED1ED4B50CA2C,$D724C0BD263AD48E,$97324359FB3EC8CA,$4CB0B4932065C3A9,$C6392C288EE4648F,$5D701C80B724E224
    Data.q $16926646ADA38EF0,$2D107BEFA4A4A496,$80C724E21264C1B9,$FEF1EB3F6BD85F74,$CC1499629263E61D,$01F2BC1EFBE91CC8,$7BF325FB2004D093,$A65F55BBDC3F661D
    Data.q $CA8C5972C524CBA6,$2609808FEB154ED7,$84EE14676E81D3A1,$00C7B43E3EB59246,$9F26B2C524C08CA0,$CB4B007A8557B5F1,$BA3C385A4C1D7932,$B3C3E0BCFD39F90F
    Data.q $29261C64D3065E21,$08A9FB46556D9F96,$1845260990323199,$59DAF4E69CFA891E,$63464A0E9CCC2CDD,$A890A3117D664752,$98261512F7699DFC,$693EB7701C784D14
    Data.q $7707C7FF6885D1FD,$144F49332322134E,$73F1952F346C7F7C,$26408312ABBB0550,$6848EBEAB2781498,$1464D1D1FCB9961C,$DB7DCC8EA4CF8C82,$20FA46645A509498
    Data.q $2E5871A482930595,$5DB82C901AB3B1E9,$8EA4C54C76446B96,$CCC687C226468ECC,$1D2A029304C83918,$2CAF2011E79DFBDD,$6352E311EDF67D8D,$264AD5664575265A
    Data.q $59520F76444545C0,$263601732FD93313,$F56490DA7A0E3C6D,$C14D9BDD83DFA47C,$0BFC754B2498398B,$BF6D4C0492A27665,$71CFB3F24E226404,$AD6FC3AF90E67AD2
    Data.q $52EA4C4CC583A6D5,$B5230544CA5D9DD9,$260A6B2A45F22F57,$0D59269A4E2085AF,$3B9A77EECC3AF490,$B991D498E7073ECD,$AA3992A9E6195AAE,$50E0F24C07F470E2
    Data.q $4BCCCD8F7E64BF4E,$200337EE8E4F1129,$AE5EAE6457526016,$0B2B38AE14AB3B94,$23B2F29E3A5B3926,$75B7BFCF60D9E3A5,$3CB149318B0D0D98,$AAB2A48634B94FBA
    Data.q $3EADC9304C042F70,$369E838D89339F87,$992585CCCD4B1B77,$EB1941BAD9FEBDD4,$92609903F68CC94F,$521CE3AF6BA3A503,$30516512EC9F5E3D,$7760994B9B322BA9
    Data.q $982640F287A4C6EA,$2490B6E038E94CB4,$DBB17D1E83E317AB,$3FD4B24985702C52,$906637506616509E,$F564E669304C8A1B,$67FF7C91A13D8F94,$BA9310E04165AB57
    Data.q $EA08B4D1D3F07980,$CD260B2A46F7092F,$5D73911E85CE4472,$8E70080B9F2AA778,$3F28CA2D5D991D49,$BC98BD2FCE01D495,$CD5774F52609E21A,$E4613335759BB5ED
    Data.q $52651CFCD91CE3FB,$5570A950B6B662F7,$CE44714D2605F9C3,$F87F2510BB911E83,$49334E7B6D4E36D9,$A62D574647B7E603,$4981E50E3B886645,$7E55DC6A93911CE3
    Data.q $73CF707035B47F4E,$A84A4C0621F1C99D,$742BBD39302FCE0A,$32EFDAA6484BFB4E,$7E76EECE6CEAD6EF,$E11941BDB323A930,$817E70B1541CC8C3,$B1EFCCB9C88FFD49
    Data.q $43EBF4F5169CBAB5,$CD9752627CE7DE5C,$3840AACE0132E656,$24B655DDD4E4C0BF,$4ED3FF73E6173D59,$3CB14931FE70EFEE,$541D48CF15994076,$E4C13209809A9EA1
    Data.q $6B7FEDBCA755DCBB,$BA9325E6F6CBE4AE,$1E90212626C77654,$9393059522928BCA,$E734E7DD9873911C,$998F3636BF067E46,$A4F5098AB6B991D4,$5F2605F9DB889737
    Data.q $4BF99EB1E82D5775,$A5B778FB2393D852,$64C92D9B2EA4CF79,$34BF3AF120AACEE4,$AEEA499B88AE2A4C,$CDF223F0B93FB6F2,$840B3374F0365B5F,$D1A5987B97E58A49
    Data.q $4CE44BF3A514C8B4,$99DB1E97327223D2,$BD798AEB77361E83,$6D2DCC8EA4C38593,$43AE2D19929C8C4C,$803E3932B144EA79,$3FE794ECB5F67EDC,$7526342C3DF7CB7D
    Data.q $7254DD8328963664,$66A4C9C4BF38F167,$7878A7155DC6B900,$4932615EEC6153E0,$529A7E4C63FBEA96,$C62A4931B12FCE34,$FC97F2AEEA075F21,$32C15D6D211AE367
    Data.q $4496676F9F980BA9,$28F287E0423654D0,$7200E5F260A28993,$D36F0A562BB705D7,$959A9B991D499C0A,$9916C17638CD5251,$A0B072F2610544EA,$E97B73CE8E96D499
    Data.q $E412BEEF91B8F200,$4D664EBA93051576,$B5D8E3A04BF3BD3E,$7C8032BE4CC05271,$493111546F0116CF,$82C9B9948713CC8B,$ABBB8E4E38097E74,$F8235B5F7F1D7C86
    Data.q $EEECA975262E2A5D,$404F287A60E4CACD,$5DC6A064C985D8E3,$A2CDEE79DFBB3F65,$475264629FD922E5,$B1C74DEE132D5B66,$0C27263425F9C20B,$41D8F4F91A9CBF20
    Data.q $B323A932F14CECF1,$7BE12815F9DE9B3C,$45DC80C7A4C63991,$BC43C803B4E44708,$D8A4F6D8A364FEFF,$59A37DD1E645A499,$037F27986CADF4F1,$CA7E401F1C9830A6
    Data.q $243738B9735EF6CB,$4943BDBB2B7B1C98,$DE2FCEA781D4B736,$CE71CFBC80363933,$F2608ADE626955F5,$A4F5099CA5B654D5,$D58F287678E3D8E3,$90076A4C8F897930
    Data.q $4790C4AAEEA42EBB,$37C982137C8AF687,$51978B284F1FD952,$B49329E2FCE5792C,$F6E8133F200CD474,$F6F9303F6C3AF767,$3451A5D1CEC5F980,$3931DE7638C9E595
    Data.q $6BF85F741AB2AEE6,$991A9C981CB6014D,$0E1F153231955B9B,$AFC80309C989F1E5,$34EC6BE1FF3D2565,$904C45F59927A930,$92617CEC71EDC31B,$790074D6EE03AB24
    Data.q $02EEC13FCF83FFB4,$E6511DDF99168693,$59B9DD827F53A12D,$57CE447A499F7264,$6C46F68FF9DC803B,$ADBEC97E8C69302A,$4CB4BF3A6E70D4CA,$E8E9492649C412FE
    Data.q $2EDFE7C803A1E92F,$998EC6930246C1CD,$9D907A5F22CC8D1D,$A3A5A4994726454B,$2BAB5B1EBCCBBF7B,$07FB12F9BECF31E9,$29C55AACC8AC9A4C,$C72631CD520117E7
    Data.q $75760FA422E755DD,$FC7963D34980CF63,$0F50CC06892732A0,$00F8E4C538BF3B8B,$B0AA5ADFFB1F21F2,$5D9DCC8B79A4C055,$E7516B2E3D30724C,$EFDE401B1C985717
    Data.q $300F6C32E166F734,$97E750D7D7323969,$1AEC71996B1549DC,$7200F8E4C92D0326,$DD1C9E225297999B,$96CD903926015D8F,$FE6AE1530A9250AD,$5B9006EA4CB2D322
    Data.q $EDADEFF3C836747F,$D91E584B926009D8,$45F9DD9A558CCCAB,$35267668BC084C99,$9B4F7200E99CE447,$5724C001B1ABF5BB,$7A00B8981B6DD953,$318E643CCFDA365C
    Data.q $9F63A535263E6EE9,$5273D7D9873E9CD3,$7366621F24C1D0F1,$B32FCE3CC3D432A9,$900669B95775A932,$1ACF0BB03E3D07C7,$2CAE387EA966F24C,$7E7626D59DCA50CA
    Data.q $006C6ABB8D498D99,$67E498311E0B6779,$6311633463B03CC0,$4CA4DDA1AB17E74A,$8F0F32A77E401C4E,$C656EECC9FF24C15,$EE97C9C6D32FCE64,$3FBE4612CBABAB2A
    Data.q $5D6644052609A786,$97E76C654DC83291,$36341F72085E4E36,$9006687A0E3C2493,$104F15BBDC3F922F,$654BF6FCC8B10A4C,$F28738CBF398EA5E,$DB8579E0424C9308
    Data.q $7EC3E401F4625CA0,$930383C3AFAFBF4E,$C38B32B77B980F42,$9B17E70469199168,$F21A404FE7123414,$E65DC803E3930637,$C526058781592ADD,$CEA49843037B6644
    Data.q $1F839367638D69AF,$01AC6C393148CB46,$3D3D44979756B6E4,$29718A4C08CF087E,$CEE1A057E75256AB,$AF6FB85EF825362F,$5DD4B655DDB4F39F,$0B9E27477F73E615
    Data.q $68C0FC7991771498,$8BF3BFAB2B7D1276,$AAE979D314939A1A,$776E4019A4EE4019,$8D624C038F02B9AF,$CD20A4CA5D9DCC05,$20D0CEC71D535F9D,$9E7327D65A20F219
    Data.q $BC8DCE71CFAABB8E,$9159358930023C74,$662FA4F3098AAEB9,$BCD18F287DDFFD63,$6F7D408A4F3A21DD,$4019A05F200DD2D4,$C1E4F867F0F8FA1E,$13166966633BD624
    Data.q $98A990D177F2ACE0,$0B5E495220E4C81C,$A0019CD492AFD2F1,$AFF21A911F85C75D,$53589306D3E3D78F,$98D2F32AF647980B,$A5E61D41CFC67760,$C243D8DED6A0261D
    Data.q $9E21AB95F9084A63,$392FE8A229E1C804,$CDA4E738EBDF6DE5,$21F0CB1AF72BF24C,$541CFF5E032C4983,$9F99E8BE9E79AFAE,$8EA5EE1D51CCA8E3,$9E9088FFC8C48D91
    Data.q $0C97F4844F7D740D,$EB7741C7524325CB,$D5E642468459BB5E,$0583E134767F7165,$FE74764F5DD35893,$DCA2E83E33799C51,$7EACEC7FFF324FA5,$79CFB738E7D59FB6
    Data.q $9D7CC97EBCCBBF6E,$C746CEA15F91E65C,$F2610164BF6BE439,$DB5FC67E7AFC947C,$AFE32C498231F03B,$DFD6CF6BFE1F5F47,$70AB7C5753B9AE37,$AF634B2BA4ACB5D9
    Data.q $92BE45125E5D45A4,$B6B5FF5F90AFC9EF,$7C8EB77BFB9EFC88,$C2C2C4981A1F0473,$0B0B126058589302,$2C2C498161624C0B,$B0B126058589302C,$EBABD6161624C0B0
    Data.q $E3806D1FF24503FF,$4549000000001EEA
    Data.b $4E,$44,$AE,$42,$60,$82
    Cube_png_end:
EndDataSection

Re: Pure1010!

Publié : ven. 17/avr./2026 11:46
par Kwai chang caine
Vraiment super beau 8O
J'en revient pas..je me suis surpris à jouer et à pas vouloir lâcher l'affaire, donc c’est un signe pour quelqu'un qui aime pas les jeux :wink:
J'ai fait 465
Encore merci du partage :wink:

Je ne doute pas de tes capacités, mais il a l'air drôlement fort ce CLAUDE pour la programmation 8O
J'ai voulu m'inscrire et il a pas voulu de moi...il m'a dit :

Image

C'est complet !!!! :|

Re: Pure1010!

Publié : ven. 17/avr./2026 12:01
par SPH
Waaa, c'est vrai qu'il est bien présenté !

Bravo :!:

Re: Pure1010!

Publié : ven. 17/avr./2026 12:16
par Mindphazer
@KCC : Merci :D
Claude est victime de son succès : on peut plus s'inscrire, et désormais, tu as droit à une à deux question par tranche horaires 6 heures environ
Cela dit, c'est l'IA qui génère un code PB fonctionnel sans avoir à modifier des tas de trucs :mrgreen:

Re: Pure1010!

Publié : ven. 17/avr./2026 12:16
par Mindphazer
SPH a écrit : ven. 17/avr./2026 12:01 Waaa, c'est vrai qu'il est bien présenté !

Bravo :!:
Merci SPH !

Re: Pure1010!

Publié : sam. 18/avr./2026 7:09
par Kwai chang caine
deux question par tranche horaires 6 heures environ
Quoi... 2 questions seulement toutes les 6 heures ??? 8O
Mais c'est rien du tout, pour faire un code avec Gemini, j'ai du passer une journée entière à lui retourner des morceaux ou le code entier a chaque bug, pour qu'il me renvoie la version corrigée
Imagine... A 2 questions par 6 heures, j'en serai seulement à la 1ere procédure :lol:

C'est vrai que en ce qui concerne les IA et la programmation , j'en ai testé seulement 2 et déjà leurs comportements, leurs puissances, sont vraiment différents sur bien des points

Exactement comme si c'était deux personnes, d'ailleurs ça va pas durer cette histoire, car petit à petit tout le monde va leurs demander quelque chose, de la minette qui lui demande si son rouge à lèvres va avec sa robe, l'ingénieur pour calculer son bâtiment, au cuisto pour élaborer une recette et tout ça en même temps, ça fait des milliers de questions diamétralement différentes à la seconde, sans parler de tous les sites qui l'utilisent pour faciliter les recherches des clients
J'suis vraiment émerveillé par cette technologie 8O et je souffre même un peu pour elle :|

IA c'est la même révolution que l'arrivée des moteurs de recherche pour internet
Désormais peu de personnes utilisent la barre d'adresse... Ça va plus vite de passer par GOOGLE, tanpis pour la planète :|

Re: Pure1010!

Publié : sam. 18/avr./2026 11:04
par Mindphazer
Petite mise à jour cosmétique...
Premier post (partie 1 uniquement) mis à jour

Re: Pure1010!

Publié : sam. 18/avr./2026 11:05
par Mindphazer
@KCC : Gemini j'ai testé... il est assez mauvais en PB :D

Re: Pure1010!

Publié : sam. 18/avr./2026 11:19
par Ar-S
1er test : 503 :)
Petit jeu addictif. Très propre. Claude a l'air bien carré en effet pour du PB.
Merci pour ce partage.

Re: Pure1010!

Publié : sam. 18/avr./2026 13:36
par Bruce33
Merci pour ce jeu.
Il me plaît beaucoup.

Re: Pure1010!

Publié : sam. 18/avr./2026 14:18
par Kwai chang caine
@KCC : Gemini j'ai testé... il est assez mauvais en PB :D
Alors tu devrais essayer ChatBot :wink: :lol:
Au niveau bonne volonté et Silicium qui lache pas l'affaire...ChatBot c'est le top des 2
J'ai passé presque 2 jours à copier/coller des codes faux avec lui :|
Jusqu'au moment ou je lui ai dit que je le remerciais, mais qu'il y arriverait pas :|
Parce que c'était la premiere fois en 30/40 ans que je m'endormais devant mon PC :?
Quand je suis allé mangé, en me lavant les mains j'ai vu CTRL et C et V gravés au bout de chacun de mes pauvres doigts boudinés et gonflés :mrgreen:

Et j'ai appris qu'il existait GEMINI, et là...le jour et la nuit
Par contre Gemini est constament surveillé par j'sais pas quoi, qui lui coupe la sifflette en disant "Ce sujet ne me plait pas, parlons d'autre chose" 8O

Tu m'étonnes je lui demandais un client/serveur RFB que je rêve d'avoir depuis la 1ere fois que j'ai vu VNC de ma vie, mais un truc à 1 clic, pas de sécurité, de Mdp, cryptage, fonctions supplémentaires, etc ...2 exe..point barre
J'ai expliqué que c'était pour aider ma belle-mere (ce qui est vrai au passage) parce que TEAMVIEWVER est le plus simple en installation grace à son serveur déporté, mais il devient l'enfer pour que des trucs qui me servent à rien (Connection, sécurité, MAJ, etc) au point qu'il est encore plus compliqué que VNC...alors j'ai décidé de me le faire moi-même avec l'aide de GEMINI, mais y'a encore du boulot :|

Alors si on peut plus aider les vieux sans finir en prison

Image

Le monde est devenu fou...mais c'est pas nouveau :|

Re: Pure1010!

Publié : dim. 19/avr./2026 16:45
par SPH
Est ce que l'on peux faire tourner d'un quart de tour chaque pièces avant de la poser ? (ce serait super si oui)

Re: Pure1010!

Publié : dim. 19/avr./2026 20:06
par Kwai chang caine
Toi tu veux recréer un TETRIS :mrgreen:

Re: Pure1010!

Publié : dim. 19/avr./2026 20:15
par SPH
Kwai chang caine a écrit : dim. 19/avr./2026 20:06 Toi tu veux recréer un TETRIS :mrgreen:
Bin, ça ressemble :wink: :!:

Bon, tu n'as pas acquiéssé. Cela veux dire que ce n'est pas prévu. :|