Welcome, Guest
You have to register before you can post on our site.

Username/Email:
  

Password
  





Search Forums

(Advanced Search)

Forum Statistics
» Members: 483
» Latest member: aplus
» Forum threads: 2,804
» Forum posts: 26,432

Full Statistics

Latest Threads
GNU C++ Compiler error
Forum: Help Me!
Last Post: eoredson
2 hours ago
» Replies: 2
» Views: 72
Fast QB64 base64 encoder ...
Forum: a740g
Last Post: a740g
6 hours ago
» Replies: 3
» Views: 435
Mean user base makes Stev...
Forum: General Discussion
Last Post: bobalooie
7 hours ago
» Replies: 7
» Views: 188
What do you guys like to ...
Forum: General Discussion
Last Post: bplus
7 hours ago
» Replies: 1
» Views: 34
_IIF limits two question...
Forum: General Discussion
Last Post: bplus
8 hours ago
» Replies: 6
» Views: 108
DeflatePro
Forum: a740g
Last Post: a740g
9 hours ago
» Replies: 2
» Views: 60
New QBJS Samples Site
Forum: QBJS, BAM, and Other BASICs
Last Post: dbox
Yesterday, 06:16 PM
» Replies: 25
» Views: 893
Raspberry OS
Forum: Help Me!
Last Post: Jack
Yesterday, 05:42 PM
» Replies: 7
» Views: 152
InForm-PE
Forum: a740g
Last Post: Kernelpanic
Yesterday, 05:22 PM
» Replies: 80
» Views: 6,152
Merry Christmas Globes!
Forum: Programs
Last Post: SierraKen
Yesterday, 03:46 AM
» Replies: 10
» Views: 135

 
  QB64 GPT now available
Posted by: SpriggsySpriggs - 05-17-2024, 05:08 PM - Forum: General Discussion - Replies (5)

I am working on a QB64 GPT. I have been training it on the Wiki as well as some sample programs. Doesn't always produce ready-to-use code, especially when it comes to OpenGL or Windows API. Otherwise, most things it makes should be good. If anyone is willing to concatenate all their samples or libraries into single files, I'd be happy to use them as training data for the GPT. It also has InForm as training data, though I can't say it does too well. I plan on making another GPT that is strictly for helping with making changes to the IDE/compiler.

https://chatgpt.com/g/g-Cufiyami0-qb64-gpt

Print this item

  Orbit Demo SIN and COS
Posted by: bplus - 05-17-2024, 03:59 PM - Forum: bplus - Replies (3)

Orbit sub calculates points about a point cx, cy at a given angle in degrees and radius using trig functions COS and SIN ratios according to degrees.

Code: (Select All)
Option _Explicit
_Title "orbit demo" 'b+ 2024-05-10

'============================== Main
Const Xmax = 1000, Ymax = 700
Const Thick = 2
Const Arc_Radius = 100
Const Sin_color = _RGB32(0, 0, 255)
Const Cos_color = _RGB32(0, 128, 0)
Const Radius_color = _RGB32(255, 0, 0)
Const Ang_color = _RGB32(255, 255, 0)
Const White = _RGB32(255, 255, 255)
Const Origin_color = _RGB32(255, 128, 0)
Dim cx, cy, mx, my, stepX, stepY, Radius, dAng, xOut, yOut, x, y
cx = Xmax / 2: cy = Ymax / 2
Screen _NewImage(Xmax, Ymax, 32)
_ScreenMove 60, 0
_PrintMode _KeepBackground
_MouseMove cx + 100, cy + 100 ' get ball rolling
While 1
    Cls
    Color White
    Locate 2, 18
    Print "Move your mouse clockwise starting at 0 due East to see Basics Angle in Degrees increase."
    Locate 5, 68
    Print "Orbit ";
    Color Origin_color
    Print "X_Origin, Y_Origin,";
    Color Ang_color
    Print " Degrees,";
    Color Radius_color
    Print " Radius,";
    Color White
    Print " xOut, yOut"
    'draw horizontal through center of screen
    Line (70, cy)-(Xmax - 70, cy), Cos_color
    ' draw vertical line through center of screen
    Line (cx, 70)-(cx, Ymax - 70), Sin_color
    'poll mouse
    While _MouseInput: Wend ' updates all mouse stuff except wheel
    mx = _MouseX: my = _MouseY 'get mouse location

    'draw our Color Coded Trig Triangle
    ThickLine cx, cy, mx, cy, 1, Cos_color
    ThickLine mx, cy, mx, my, 1, Sin_color
    ThickLine cx, cy, mx, my, Thick, Radius_color

    stepX = mx - cx: stepY = my - cy
    Radius = (stepX ^ 2 + stepY ^ 2) ^ .5

    'to draw angle need to do some math
    'dAng = mouse angle to 0 Degrees due East
    dAng = _R2D(_Atan2(my - cy, mx - cx))
    If dAng < 0 Then dAng = dAng + 360

    Color Ang_color
    ThickArc cx, cy, Radius, 0, dAng, Thick

    'report all numbers color coded
    Color Ang_color
    Locate 5, 3: Print "Yellow Angle (in Degrees) ~ "; dAng \ 1
    Color Radius_color
    Locate 7, 7: Print "    Length red Radius ~ "; Radius \ 1
    Color Sin_color
    Locate 9, 7: Print " Length blue Opp side ~ "; Abs(stepY) \ 1
    Color Cos_color
    Locate 8, 7: Print "Length green Adj side ~ "; Abs(stepX) \ 1
    Color White
    Locate 11, 1: Print " Ratios: (if no division by 0)"
    If Radius <> 0 Then
        Color Cos_color
        Locate 12, 8: Print "COS = Adj ";
        Color Radius_color
        Print "/ Radius ";
        Color White
        Print "~ "; Left$(Str$(stepX / Radius), 6) '; Cos(_D2R(dAng))  ' double check

        Color Sin_color
        Locate 13, 8: Print "SIN = Opp ";
        Color Radius_color
        Print "/ Radius ";
        Color White
        Print "~ "; Left$(Str$(stepY / Radius), 6) '; Sin(_D2R(dAng)) ' double check
    End If
    Color White
    orbit cx, cy, dAng, Radius, xOut, yOut ' mouse here
    orbit cx, cy, dAng, Radius + 50, x, y ' set label here
    label x, y, "(xOut, yOut) = (" + _Trim$(Str$(xOut \ 1)) + "," + Str$(yOut \ 1) + ")"
    Color Origin_color
    label cx, cy - 10, "(X_Origin, Y_Origin) = (" + _Trim$(Str$(cx)) + "," + Str$(cy) + ")"
    _Display
    _Limit 60
Wend


'      !!!!!!   featuring the use of this SUB routine   !!!!
Sub orbit (X_Origin, Y_Origin, Degrees, Radius, xOut, yOut) ' all default single  should be ok
    xOut = X_Origin + Radius * Cos(_D2R(Degrees))
    yOut = Y_Origin + Radius * Sin(_D2R(Degrees))
End Sub

Sub label (xc, yc, text$)
    Dim th2, pw2
    th2 = _FontHeight / 2
    pw2 = _PrintWidth(text$) / 2
    _PrintString (xc - pw2 + 1.25, yc - th2 + .5), text$
End Sub

Sub ThickArc (xCenter, yCenter, arcRadius, dAngleStart, dAngleEnd, rThick)
    Dim rAngle, rAngleStart, rAngleEnd, x1, y1, Stepper
    'draws an Arc with center at xCenter, yCenter, Radius from center is arcRadius

    'for SmallBASIC angle 0 Degrees is due East and angle increases clockwise towards South

    'THIS SUB IS SETUP TO DRAW AN ARC IN CLOCKWISE DIRECTION

    'dAngleStart is where to start Angle in Degrees
    ' so make the dAngleStart the first ray clockwise from 0 Degrees that starts angle drawing clockwise

    'dAngleEnd is where the arc ends going clockwise with positive Degrees
    ' so if the arc end goes past 0 Degrees clockwise from dAngleStart
    '  express the end angle as 360 + angle

    'rThick is the Radius of the many,many tiny circles this will draw to make the arc thick
    ' so if rThick = 2 the circles will have a Radius of 2 pixels and arc will be 4 pixels thick
    If arcRadius < 1 Then PSet (xCenter, yCenter): Exit Sub
    rAngleStart = _D2R(dAngleStart): rAngleEnd = _D2R(dAngleEnd)
    If Int(rThick) = 0 Then Stepper = 1 / (arcRadius * _Pi) Else Stepper = rThick / (arcRadius * _Pi / 2)
    For rAngle = rAngleStart To rAngleEnd Step Stepper
        x1 = arcRadius * Cos(rAngle): y1 = arcRadius * Sin(rAngle)
        If Int(rThick) < 1 Then
            PSet (xCenter + x1, yCenter + y1)
        Else
            fcirc xCenter + x1, yCenter + y1, rThick, Ang_color
        End If
    Next
End Sub

Sub ThickLine (x1, y1, x2, y2, rThick, K As _Unsigned Long)
    Dim length, stepx, stepy, dx, dy, i

    'x1,y1 is one endpoint of line
    'x2,y2 is the other endpoint of the line
    'rThick is the Radius of the tiny circles that will be drawn
    '   from one end point to the other to create the thick line
    'Yes, the line will then extend beyond the endpoints with circular ends.

    stepx = x2 - x1
    stepy = y2 - y1
    length = (stepx ^ 2 + stepy ^ 2) ^ .5
    If length Then
        dx = stepx / length: dy = stepy / length
        For i = 0 To length
            fcirc x1 + dx * i, y1 + dy * i, rThick, K
        Next
    End If
End Sub

Sub fcirc (CX As Long, CY As Long, R As Long, C As _Unsigned Long)
    Dim Radius As Long, RadiusError As Long
    Dim X As Long, Y As Long
    Radius = Abs(R): RadiusError = -Radius: X = Radius: Y = 0
    If Radius = 0 Then PSet (CX, CY), C: Exit Sub
    Line (CX - X, CY)-(CX + X, CY), C, BF
    While X > Y
        RadiusError = RadiusError + Y * 2 + 1
        If RadiusError >= 0 Then
            If X <> Y + 1 Then
                Line (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
                Line (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
            End If
            X = X - 1
            RadiusError = RadiusError - X * 2
        End If
        Y = Y + 1
        Line (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
        Line (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
    Wend
End Sub
edit: to show when sin and cos go negative. abs() should only be applied to lengths.

Notice 0 Degrees is due East and as the angle in degrees increases the the arc goes CLOCK-WISE about cx, cy from EAST to SOUTH to WEST to NORTH and returns to due EAST at 360 degrees, one complete turn.

   

Print this item

  For..Next
Posted by: Dimster - 05-17-2024, 03:27 PM - Forum: GitHub Discussion - Replies (6)

I don't think there is present option whereby the NEXT (as in the FOR..NEXT) will automatically display the control variable after Next?? When a For is typed you get an automatic warning that you need the NEXT but if the For already has a control variable then could the warning also include the control variable? For x = 1 to 10 "Warning missing NEXT x"

I do appreciate there is a lot less typing if the control variable is not needed to complete the For .. Next but sometimes when I have a lot of nested IF statements with a lot of For..Next loops it is always a missing End If that is somewhere in that mess of code which creates a Program Flow error. Following which For goes to which Next can be a little challenging. So I was thinking is the Flow Error highlighted Next x as the loop where I can find the missing End If (as opposed to the Next y or Next Num etc in the same mess of coding) it could help.

Print this item

  New Alchemy
Posted by: PhilOfPerth - 05-17-2024, 05:09 AM - Forum: Games - Replies (5)


.7z   Alchemy.7z (Size: 355.16 KB / Downloads: 99)

I've re-written the word-game Alchemy with several new innovations, which I think make it more enjoyable.

It has 3 sets of 20 word-pairs, roughly sorted in order of difficulty from easy to  hard. All pairs are 
proven to be solvable, with the current best results stored as three Previous best files. These automatically 
update when the records are beaten, but can be removed and re-started at will. 

It allows re-starting a word-pair, or re-picking the set of words. A random-access word file is included which 
makes the word-checking function much faster.

My thanks to Steve and bplus for their help. 

Code: (Select All)
Common Shared Ln$, SetNum$, Filename$, LineNum, CPL, WordPos, bad$, ok$, a$, Set$()
Common Shared Pairnum, Prev$, First$(), Last$(), Best$(), Name$(), Chain$(), Target$(), Target$, Name$
Common Shared ThisChain$, TryVert, Try$, Tries, MaxTries, Result
Randomize Timer

WWidth = 1275: WHeight = 820
Screen _NewImage(WWidth, WHeight, 32)
SetFont: f& = _LoadFont("C:\WINDOWS\fonts\courbd.ttf", 24, "monospace")
_Font f& '                                                                     install monospace font size 24, giving 32 usable text rows of 66 cols
dw = _DesktopWidth: dh = _DesktopHeight
CPL = WWidth / _PrintWidth("X") '                                              characters per line - used for centring and wiping
lhs = (dw - WWidth) / 2: top = 100 '                                           window left and top locations
_ScreenMove lhs, top

ok$ = "o3l32ceg": bad$ = "o2l16gec" '                                          centre display on target screen
Set1Data:
Data "BADGE","MEDAL","HORSE","SHEEP","SHED","HOUSE","CAR","TRUCK","MAJOR","MINOR"
Data "PASS","FAIL","STEAK","EGGS","SUN","MOON","BIRD","FISH","TOWN","CITY"
Data "COLD","HOT","LOCK","WATCH","CUP","PLATE","PARK","GARDEN","RIPE","ROTTEN"
Data "SHORT","TALL","WAR","PEACE","BIG","SMALL","DRAIN","SEWER","DRESS","SUIT"
Set2Data:
Data "MILK","HONEY","CREAM","CUSTARD","SPICE","SUGAR","RAKE","SHOVEL","WOOL","COTTON"
Data "WEED","FLOWER","EASTER","EGG","LOOK","LISTEN","FOX","HOUND","DANGER","SAFETY"
Data "COPPER","BRASS","LION","TIGER","BOX","CARTON","BOOK","PAPER","GREEN","BROWN"
Data "CHILD","ADULT","DESERT","OASIS","QUERY","RESULT","DUNCE","GENIUS","FATHER","SON"
Set3Data:
Data "PAPER","PENCIL","PRETTY","UGLY","RAISE","LOWER","ROAD","STREET","BLUNT","SHARP"
Data "BLACK","WHITE","MARS","SATURN","COVER","EXPOSE","FORWARD","REVERSE","MODEST","PROUD"
Data "MARRY","DIVORCE","CIRCLE","SQUARE","ANVIL","HAMMER","PATTERN","MODEL","FRINGE","PLAIT"
Data "DARK","LIGHT","RUBY","DIAMOND","BEDROOM","KITCHEN","ANTIQUE","VINTAGE","DUCKLING","SWAN"
Dim Set$(3, 20, 5) '                                                              First, Last, Best, Name and Chain for 3 sets of 20 pairs

CheckFiles: '                                                                     check 3 Set files; if not found create with defaults
For a = 1 To 3
   Filename$ = "Set" + LTrim$(Str$(a))
   txt$ = "Checking " + Filename$
   Centre txt$, 15: _Delay .5
   If Not _FileExists(Filename$) Then
      If a = 1 Then
         Restore Set1Data
      ElseIf a = 2 Then
         Restore Set2Data
      ElseIf a = 3 Then
         Restore Set3Data
      End If
      Open Filename$ For Output As #1
      For b = 1 To 20
         Read first$, last$
         Write #1, first$, last$, "21", "NOT SET", "UNSOLVED"
      Next
      Print "created "; Filename$: Sleep 1
      Close: Cls: Run
   End If
Next

Description

Chooseset:
Centre "Choose from Set 1 to Set 3 (9 TO EXIT)", 15
SetNum$ = ""
While SetNum$ <> "9" And (SetNum$ < "1" Or SetNum$ > "3")
   SetNum$ = InKey$
Wend
If SetNum$ = "9" Then System
Cls
ReDim First$(20), Last$(20), Best$(20), Name$(20), Chain$(20)
ShowPairs
MaxTries = 20: WordPos = 36

InviteChoosePair: '                                                               choose a pair of words to attempt
Yellow: Centre "Choose a pair, from A to T", 29
Centre "Z to re-choose set number", 30 '                                          choose pair Z to change set number
Centre " * to reset this pair's history", 31
Centre "(ESC to quit)", 32 '                                                      Esc quits the game
_KeyClear: k = 0
While k < 1
   _Limit 30
   k = _KeyHit
Wend
Cls

Select Case k
   Case Is = 42, 56 '                                                              press * to reset this pair history
      Wipe "303132"
      Centre "Do you really want to remove the history for this set (y/n)?", 30
      _KeyClear
      k$ = ""
      While k$ = ""
      k$ = InKey$: Wend
      If UCase$(k$) <> "Y" Then
         GoTo Chooseset
      Else
         If SetNum$ = "1" Then
            Restore Set1Data '                                                     start reading pairs at Set1Data
         ElseIf SetNum$ = "2" Then
            Restore Set2Data '                                                     start reading pairs at Set1Data
         ElseIf SetNum$ = "3" Then
            Restore Set3Data '                                                     start reading pairs at Set1Data
         End If
         Filename$ = "Set" + SetNum$
         Open Filename$ For Output As #1 '                                         re-create the Set file with this data
         For a = 1 To 20
            Read first$, last$ '                                                   get the word-pair from data
            Write #1, first$, last$, "21", "NOT SET", "UNSOLVED" '                 write First, Last, Best, Name, and Chain to file
         Next
         Close
         Cls: msg$ = Filename$ + " reset"
         Centre msg$, 15
         Sleep 1
         GoTo Chooseset
      End If
   Case Is = 27 '                                                                  Esc to quit
      System
   Case Is = 90, 122 '                                                             Z or z to re-choose set
      GoTo Chooseset
   Case 65 To 84 '                                                                 selected A to T
      Pairnum = k - 64 '                                                           convert to number 1 to 20 uppercase
   Case 97 To 116 '                                                                a to t
      Pairnum = k - 96 '                                                           convert to number 1 to 20 lower-case
   Case Else '                                                                     if it's none of these, try again
      Play bad$
      GoTo Chooseset
End Select

FirstLook:
Cls: ThisChain$ = "" '                                                             empty the chain for this pair
Prev$ = First$(Pairnum) '                                                          put start word at front of chain
TryVert = 6: remain = 21: Tries = 0
target = Val(Best$(Pairnum)): Name$ = Name$(Pairnum)
msg$ = "Target:" + Str$(target)
Centre msg$, 4 '                                                                   show target details for this pair
Yellow: Centre First$(Pairnum), 5 '                                                show the first word
For a = TryVert To MaxTries + 5
   Print Using "##"; Tab(28); a - 5;
   Centre String$(9, "."), a
Next '                                                                             show 9 dots for each try
Yellow: Centre Last$(Pairnum), 26 '                                                show the target word
_KeyClear

CheckNumTries:
If Tries = MaxTries Then '                                                         check if all tries used yet
   Play bad$
   Wipe "30"
   Red: Centre "You've Used up all of your tries, sorry!", 30
   Wipe "24": White: Sleep 1
   GoTo Chooseset '                                                                if all tries used, advise and restart the same pair
End If

GetTry:
Centre String$(9, "."), TryVert
Yellow:
Wipe "30"
txt$ = "You have" + Str$(20 - Tries) + " tries remaining"
Centre txt$, 30
Yellow
Locate 5, 50: Print "Added"; Tab(60); "Removed"
Sleep 1
'For a = 0 To 2: Locate 5 + a, 5: Print Space$(21):Next
Locate 5, 2: Print "Enter your word"
Locate 6, 2: Print "Space to restart from top"
Locate 7, 2: Print "Esc to quit"
White
Locate TryVert, WordPos - 5: Print Space$(12) '                                    clear the Try space
Locate TryVert, WordPos - 2
Input "", Try$ '                                                                   place cursor outside try-line

Try$ = UCase$(Try$)
Select Case Try$
   Case Is = Chr$(27) '                                                            pressed Esc to quit
      System
   Case Is = Chr$(32) '                                                            pressed space to restart from try 1
      GoTo FirstLook
   Case "A" To "Z", "a" To "z" '
      GoTo Letters
   Case Else
      GoTo GetTry
End Select

Letters:
If Len(Try$) < 2 Or Len(Try$) > 9 Then '                                           check length is 2 to 9 letters
   Play bad$
   Red: Centre "Words from 2 to 9 letters only allowed", 29
   Sleep 1: Wipe "29": White
   Locate TryVert, WordPos
   Print Space$(15) '                                                              if length is wrong, erase,
   GoTo GetTry '                                                                   and start this try again
End If
Tries = Tries + 1
Locate TryVert, WordPos: Print Space$(12)
Centre Space$(9), TryVert
Centre Try$, TryVert

CheckWord '                                                                        Call Sub to Check the Player's Word

TryVert = TryVert + 1
GoTo CheckNumTries

' ------------------------------------------------------------------- subs below -------------------------------------------------------------------

Sub ShowPairs
Filename$ = "Set" + SetNum$
Open Filename$ For Input As #1
For a = 1 To 20
   Input #1, First$(a), Last$(a), Best$(a), Name$(a), Chain$(a)
Next
Close
txt$ = Filename$ + " Word Pairs  "
Yellow: Centre txt$, 5 '                                                           show pair details, but don't show chains
Print: Print Tab(18); "Pair"; Tab(26); "From"; Tab(37); "To"; Tab(44); "Best"; Tab(52); "By"
White
For a = 1 To 20
   Print Tab(19); Chr$(a + 64); Tab(26); First$(a); Tab(36); Last$(a); Tab(45); Best$(a); Tab(50); Name$(a)
Next
Close
Play ok$
End Sub

Sub CheckWord '                                                                    check this word - number of changes ok? valid word?
Added = 0: Added$ = "": Removed = 0: Removed$ = "": Result = 0
CountAddedLetters: '                                                               Find letters in Try$ that were not in Prev$ (so they are added)
temp$ = Prev$ '                                                                    keep prev$ intact while checking
For a = 1 To Len(Try$) '
   l$ = Mid$(Try$, a, 1) '                                                         get a letter from try$,
   po = InStr(temp$, l$) '                                                         find its position in temp$, if any
   If po = 0 Then '                                                                if not in temp$, it was added,                                                                                                                       if not found...
      Added = Added + 1: Added$ = Added$ + l$ '                                    so add to Added$ and increment Added count
   Else '                                                                          if in temp$, replace with a space (stops double-find)
      temp$ = Left$(temp$, po - 1) + " " + Right$(temp$, Len(temp$) - po)
   End If
Next
CountRemovedLetters: '                                                             Find letters in prev$ that are not in try$ (removed)
temp$ = Try$ '                                                                     backup try$ before checking
For a = 1 To Len(Prev$)
   l$ = Mid$(Prev$, a, 1) '                                                        get a letter from prev$
   po = InStr(temp$, l$) '                                                         find its position in try$, if any
   If po = 0 Then '                                                                if not in temp$ it has been removed,
      Removed = Removed + 1: Removed$ = Removed$ + l$ '                            so add to Removed$ and increment the Removed count
   Else '                                                                          if in temp$, replace with a space to (stops double-find)
      temp$ = Left$(temp$, po - 1) + " " + Right$(temp$, Len(temp$) - po)
   End If
Next
Locate TryVert, 50: Print Added$; Tab(60); Removed$
ResultOfCount: '                                                                   check number of added and removed letters
If Added > 1 Or Removed > 1 Then
   Wipe "30"
   Red: Centre "Too many changes!", 30
   Play bad$
   Sleep 1
   Result = 1 '                                                                     flag too many changes with Result = 1
   White
   GoTo ChecksFinished '                                                            bad result, no more checking needed
End If

DictionaryCheck: '                                                                  number of changes was ok, result is zero
Close
Open "RA9" For Random As #1 Len = 13 '                                              random access file with longest word 9 letters
fl = LOF(1) \ 13 + 1 '                                                              get number of words in dictionary
bot = 0: top = fl
While Abs(top - bot) > 1
   srch = Int((top + bot) / 2) ' set section of dictionary to searchrch '           set search point
   Get #1, srch, a$ '                                                               get a word from dictionary at srch point
   a$ = UCase$(a$)
   Select Case a$
      Case Is < Try$ '                                                              try$ is greater than dictionary word
         bot = srch '                                                               move search forward
      Case Is > Try$ '                                                              try$ is less than dictionary word
         top = srch '                                                               move search back
   End Select
   If Try$ = Last$(Pairnum) Then
      msg$ = "Solved in " + LTrim$(Str$(Tries)) + " tries!"
      Result = 2 '                                                                  solved
      Yellow: Centre msg$, 31
      Centre Try$, TryVert
      ' ThisChain$ = First$(Pairnum) + " - " + ThisChain$ ' + Try$ '                    complete the chain
      Exit While
   ElseIf Try$ = a$ Then
      Result = 3 '                                                                  valid word but not Last$
      Centre Try$, TryVert
      Exit While
   End If
Wend
Close

InvalidWord: '                                                                      fall through to here if Try$ not Last$ and not valid
If Result < 2 Then
   Wipe "30"
   Red: Centre "Invalid word!", 30
   Red: Centre Try$, TryVert
   Sleep 1
   ThisChain$ = ThisChain$ + " " + String$(Len(Try$), "*") + " - "
End If
Wipe "30" '                                                                         if we got here it's an invalid word, result still zero
White

ChecksFinished: '
Select Case Result
   Case Is = 0, 1 '                                                                 word failed - too many changes or invalid word
      Red: Centre Try$, TryVert
      ThisChain$ = ThisChain$ + " " + String$(Len(Try$), "*") + " - "
      Play bad$
   Case Is = 2 '                                                                    word ok and last word is found
      msg$ = "Solved in " + LTrim$(Str$(Tries)) + " tries!"
      Yellow: Centre msg$, 31
      Centre Try$, TryVert
      ThisChain$ = First$(Pairnum) + " - " + ThisChain$ + Try$ '                    complete the chain
      If Len(ThisChain$) > CPL - 8 Then ThisChain$ = ThisChain$ + Chr$(13)
   Case Is = 3 '                                                                    word ok but is not Last$
      Centre Try$, TryVert
      ThisChain$ = ThisChain$ + Try$ + " - "
      Play ok$
      Prev$ = Try$
End Select
If Result = 2 Then FinishedPair
Sleep 1: Wipe "3031"
End Sub

Sub FinishedPair
Play ok$: Play ok$: Cls: Yellow
msg$ = "You did it in " + LTrim$(Str$(Tries)) + " changes"
Centre msg$, 15
If Tries < Val(Best$(Pairnum)) Then '                                               if this beats the Best for the current round,
   Centre "New record! Enter your name (or <ENTER> for anonymous)        ", 16
   Locate 16, 60: Input winname$ '                                                  get the player's name,
   If Len(winname$) < 2 Then winname$ = "(ANON)" '                                  if no name is given, player is ANON
   Name$(Pairnum) = UCase$(winname$) '                                              place Name of best player for this pair in array
   Best$(Pairnum) = LTrim$(Str$(Tries)) '                                           place Best score for this pair in array
   Chain$(Pairnum) = ThisChain$ '                                                   this beats previous best so update chain$ for this pair,
   Filename$ = "Set" + SetNum$ '
   Open Filename$ For Output As #1
   Cls
   For a = 1 To 20 '
      Write #1, First$(a), Last$(a), Best$(a), Name$(a), Chain$(a) '                and re-write the history file for this set
   Next
   Close
End If
Cls
Yellow
msg$ = "Best for this pair: " + Best$(Pairnum) + " by " + Name$(Pairnum)
Centre msg$, 15
White: Locate 17, 1: Print ThisChain$
Play ok$
Yellow: Centre "Press a key", 19
Sleep
Run
End Sub

Sub Description
AlchemyDescription:
Yellow: Centre "ALCHEMY", 2: White: Print
Print "   Alchemy (al/ke/mi) is the process of changing items into something"
Print "   different in a mystical way, such as changing ";: Green
Print "STONE";: White: Print " into ";: Green: Print "GOLD.": White
Print "   This game calls upon your skills in this art, to change a word into"
Print "   a totally different one, with the least number of changes.": Print
Print "   In the usual word-swap game, you repeatedly change one letter of a"
Print "   word for a different one, creating a new word, until the final word"
Print "   is produced.": Print
Print "   But in Alchemy you have another tool available to you for the task."
Print "   You can also ";: Green: Print "add";: White: Print " or ";: Green
Print "remove";: White: Print " a letter, before ";: Green
Print "re-arranging";: White: Print " them, so"
Print "   the length of the word may vary as you progress (to max 9 letters)."
Print "   As an example, we can change STONE into GOLD with just 4 changes:"
Green: Centre "STONE - TONE - GONE - LONG - GOLD", 18: White: Print
Print "   There are three sets of word-pairs provided, ranging from easy to";: Print
Print "   difficult, and you are allowed up to 20 changes for each pair. A"
Print "   record is kept of the best score for each pair, and if you beat"
Print "   one of these, your record will replace it (you can restart these"
Print "   records from new at any time).": Print
Print "   By the way, an ";: Green: Print "Easter Egg";: White: Print " with ";
Print "the best recorded solutions for all"
Print "   of the word-pairs is hidden somewhere (hint: you may have to visit"
Print "   Tibet to find it)!"
Yellow: Centre "Press a key to continue", 29
Sleep: Play ok$: Cls
End Sub

Sub Wipe (ln$) '                                                                    ln$ is 2-digit line nums eg "0122" is lines 1 and 22)
For a = 1 To Len(ln$) - 1 Step 2 '                                                  get 2 digits for wipe-line,
   wl = Val(Mid$(ln$, a, 2)) '                                                      and wipe that line
   Locate wl, 1: Print Space$(CPL);
Next
End Sub

Sub Centre (txt$, linenum) '                                                        centres text on selected line
ctr = Int(CPL / 2 - Len(txt$) / 2) + 1 '                                            centre is half of chars per line minus half string-length
Locate linenum, ctr
Print txt$
End Sub

Sub Red
Color _RGB(255, 0, 0)
End Sub

Sub Yellow
Color _RGB(255, 255, 0)
End Sub

Sub White
Color _RGB(255, 255, 255)
End Sub

Sub Green
Color _RGB(0, 255, 0)
End Sub


STEVE FREINDLY EDIT --  Grab the download from here as well, if you need it: 


.7z   Alchemy.7z (Size: 355.16 KB / Downloads: 99)
(Most folks are used to finding these attachments at the bottom of posts, so I just edited it down here as well as leaving it up top as originally posted. Wink )

Print this item

  Fast Primes
Posted by: SMcNeill - 05-16-2024, 08:13 AM - Forum: Utilities - Replies (18)

A quick little method to get prime numbers from 2 to a little over 1,000,000.

Code: (Select All)
Screen _NewImage(1280, 900, 32)
_ScreenMove _Middle
For i = 1 To 999999 'I didn't stop at 1,000,000 just cause I didn't want that last SLEEP/CLS to erase the last page. Big Grin
If IsPrime(i) Then Print i;
If i Mod 12000 = 0 Then Sleep: Cls
Next
Beep 'an audible warning so folks can take their finger off whatever key they're using to spam past the SLEEP statements.
_Delay 2 'and time for them to let go of that key
_KeyClear 'so if they're using ENTER as the "Get on with it damn ya!" key, it won't blow past the manual test.
Print
Print

Print "Feel free to do some independent tesing to see if my response is speedy enough for you:"
Do
Input "Give me a number from 0 to 1,016,064 and I'll tell you if it's prime or not. (Zero quits.) =>"; num
If IsPrime(num) Then
Print num; "is, indeed, a prime number!"
Else
Print "Nope!"; num; "is not prime!"
End If
Loop Until num = 0
System


Function IsPrime (num)
'to check for any given number less than 1,016,064, we only have to do a maximum of 170 comparisons
'as the max value we ever have to check against is the SQR of our number.
'for example, no value higher than 10 could ever be a factor in 100 and be prime!
'so for numbers less than 1,000,000, all we need do is compare them against factors less than 1,000.
'and there's not that many of them, as you can see below!
If num < 2 _Orelse num > 1016064 Then Exit Function
Restore prime_factors
IsPrime = -1
For j = 1 To 10 'broken down to give 10 quick exit points so we don't check every value for an answer.
Read count
For i = 1 To count
Read factor
If num <= factor Then
Exit Function
Else
If num Mod factor = 0 Then IsPrime = 0: Exit Function
End If
Next
If num < factor * factor Then Exit Function
Next

Exit Function
prime_factors: 'for a list of prime factors for numbers from 1 to 1,000,000
Data 25: 'for numbers from 1 to 100
Data 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97: 'factors up to 10,000 (100 ^ 2)
Data 21: 'for numbers from 101 to 200
Data 101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199: 'up to 44,100 (210 ^ 2)
Data 16
Data 211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293: 'up to 93,636 (306 ^ 2)
Data 16
Data 307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397: 'up to 160,000 (400 ^ 2)
Data 17
Data 401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499: 'up to 252,004 (502 ^ 2)
Data 14
Data 503,509,521,523,541,547,557,563,569,571,577,587,593,599: 'up to 360,000 (600 ^ 2)
Data 16
Data 601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691: 'up to 490,000 (700 ^ 2)
Data 14
Data 701,709,719,727,733,739,743,751,757,761,769,773,787,797: 'up to 652,864 (808 ^ 2)
Data 15
Data 809,811,821,823,827,829,839,853,857,859,863,877,881,883,887: 'up to 820,836 (906 ^ 2)
Data 14
Data 907,911,919,929,937,941,947,953,967,971,977,983,991,997: 'up to 1,01,064 (1008 ^ 2)
End Function



Note that this saves no tables, no values.  Uses almost no memory.  It's just direct elimination in the most efficient manner possible, for values from 2 to a little over 1,000,000.  If someone wanted, they could continue this to go further, but it's all I need at the moment for my personal purposes, so I'll just post it as is and leave it for others to work on and enjoy if they ever want to.  Smile

Print this item

  Best way to update PE
Posted by: PhilOfPerth - 05-16-2024, 12:04 AM - Forum: Help Me! - Replies (9)

I'm sure I'm doing it wrong! To update, I currently download the new file (into my Downloads folder), then extract the files to my QB64PE folder (which is directly on the C: drive).
I then go to this new folder in PE, and copy all the files to the PE folder itself. I'm prompted to write over old files found or to skip the copy. 
Is there a quicker/simpler way to update (maybe skipping files that are not changed)?

Print this item

  QB64PE v3.13.1 is now released!
Posted by: SMcNeill - 05-15-2024, 10:49 PM - Forum: Announcements - Replies (9)

https://github.com/QB64-Phoenix-Edition/...ses/latest

Quote:What's Changed
Refactor RAD v2 Opal OPL3 FM Emulator by @a740g in #490

Multiple font related optimization and improvements by @a740g in #491

Especially some monospaced fonts related quirks discovered with the previous release have been fixed

Print this item

  Extended KotD #7: $INCLUDEONCE
Posted by: SMcNeill - 05-15-2024, 07:17 AM - Forum: Keyword of the Day! - Replies (7)

Thanks to @RhoSigma , this wonderful keyword was added into the language a few versions back.  I'm honestly surprised we haven't had more people talk about it, use it, or at least ask about it!  This is one of those commands that I consider to be a *MUST HAVE*  for anyone who does any serious library creation.

What is $INCLUDEONCE?  And what's it do for us that's so nifty?

$INCLUDEONCE is a metacommand that you place inside any of your library files, and no matter how many $INCLUDE statements they show up in, they're only included ONCE in your code.


For example, let's say I write various libraries and I have a Truth.BI file which I make excessive use of:

Truth.BI

Code: (Select All)
CONST True = -1
CONST False = 0
Now, I write a little program which saves files for me to the disk as *.SSF (Steve Special Format) files.  This save file library is going to $INCLUDE:'Truth.BI.

And I also write a little program which loads files for me from the disk, if they're *.SFF files.  This is seperate from the save library as folks may just need one of the routines and not both in their code.  This file would also have in it somewhere the need for $INCLUDE:'Truth.BI'

Now, for my own use, I want to use *both* of the routines in my program -- I want to both save and load files.  So, I write my code for the main program to look something like the following:

Code: (Select All)
$INCLUDE:'SaveSSF.BI'
$INCLUDE:'LoadSSF.BI'

... more code
And, in the IDE, I get warnings and errors and dancing bears growling and trying to eat me as I'm now trying to include Truth.BI twice in my code and that means I'm trying to define the same CONSTs multiple times.   QB64PE doesn't like that type of behavior!!

So what's the simple fix??

Let's go back and change Truth.Bi just a little:
Code: (Select All)
$INCLUDEONCE
CONST True = -1
CONST False = 0
Now, even though that library "Truth.BI" is included in multiple other libraries, and thus included in my code at multiple points, IT'S ONLY ADDED ONCE!!

The first time a file with $INCLUDEONCE in it is $INCLUDEd into your code, it's added to the code.  At each and EVERY point after that, that code is just skipped as you've already included it into your code earlier!!

$INCLUDEONCE, when placed inside a bas/bi/bm file, makes certain that the code in that file is only included one time, no matter how many $INCLUDE statements try to reference that file.

And that's a game changer right there, for anyone who writes and creates library files!  Big Grin

For everyone else, if you don't use $INCLUDE, you can basically just save the brain cells and forget this command even exists.  It ONLY affects $INCLUDE behavior, and does absolutely nothing in any other type code.  Wink

Print this item

  Getting vectors using a lookup table
Posted by: TerryRitchie - 05-14-2024, 08:00 PM - Forum: Programs - Replies (2)

More playing around today. I created a few functions to quickly get vector quantities from a SIN lookup table.

The SIN/COSINE table returns standard results while the conversion functions negate the COSINE value so 0 degrees and 0Pi are north/up.

Code: (Select All)
'+-------------------------------------------------------+
'|   Radian to Vector and Degree to Vector subroutines   |
'|                          by                           |
'|                    Terry Ritchie                      |
'|                       05/14/24                        |
'|                                                       |
'| Convert radians or degrees to vector pairs using a    |
'| pre-calculated lookup table or real-time calculation. |
'| Documentation contained in subs.                      |
'|                                                       |
'| R2VX!(radian, mode) - return radian x vector          |
'| R2VY!(radian, mode) - return radian y vector          |
'| D2VX!(degree, mode) - return degree x vector          |
'| D2VY!(degree, mode) - return degree y vector          |
'| SINE!(Index)        - return SINE   from lookup table |
'| COSINE!(Index)      - return COSINE from lookup table |
'|                                                       |
'| R2VX!, R2VY!, D2VX!, and D2VY! return vector values   |
'| based on the following input values:                  |
'|                                                       |
'|   0 = North    90 = East  180 = South    270 = West   |
'| 0Pi = North  .5Pi = East   Pi = South  1.5Pi = West   |
'|                                                       |
'| Degrees based on 0 to 359, radians from 0 to 2Pi.     |
'+-------------------------------------------------------+

'+--------------------+
'| Begin demo program |
'+--------------------+

CONST MODE% = 0 ' (0 to use lookup table, 1 to calculate in real time)

DIM d AS SINGLE ' counter

SCREEN _NEWIMAGE(640, 480, 32)

' Draw line from center point using degree values passed in

FOR d = 0 TO 359
    LINE (319, 239)-(319 + D2XV(d, MODE) * 200, 239 + D2YV(d, MODE) * 200)
    _DELAY .005
NEXT d
SLEEP
CLS

' Draw line from center point using radian values passed in

FOR d = 0 TO 2 * _PI STEP 2 * _PI / 360
    LINE (319, 239)-(319 + R2XV(d, MODE) * 200, 239 + R2YV(d, MODE) * 200)
    _DELAY .005
NEXT d

'+------------------+
'| End demo program |
'+------------------+

'------------------------------------------------------------------------------------------------------------
FUNCTION R2XV! (rad AS SINGLE, mode AS INTEGER) ' radian to x vector

    '+---------------------------------------------------------------------------+
    '| Converts a radian value passed in to the corresponding x vector value.    |
    '| 0Pi = North/Up, .5Pi = East/Right, Pi = South/Down, 1.5Pi = West/Left.    |
    '|                                                                           |
    '| rad  - the radian value to convert to x vector                            |
    '| mode - 0 return value from lookup table, not 0 return calculated value    |
    '|                                                                           |
    '| Note: To use the lookup table the radian value needs to be converted to a |
    '|       degree value. The lookup table only contains the values for integer |
    '|       degrees ranging from 0 to 359. If you need a more precise           |
    '|       calculation set mode above to a non xero integer value.             |
    '+---------------------------------------------------------------------------+

    IF mode THEN '                 calculate vector?
        R2XV! = SIN(rad) '         yes, return calculated SINE value
    ELSE '                         no, use lookup table
        R2XV! = SINE!(_R2D(rad)) ' return SINE value from table
    END IF

END FUNCTION
'------------------------------------------------------------------------------------------------------------
FUNCTION R2YV! (rad AS SINGLE, mode AS INTEGER) ' radian to y vector

    '+---------------------------------------------------------------------------+
    '| Converts a radian value passed in to the corresponding y vector value.    |
    '| 0Pi = North/Up, .5Pi = East/Right, Pi = South/Down, 1.5Pi = West/Left.    |
    '|                                                                           |
    '| rad  - the radian value to convert to y vector                            |
    '| mode - 0 return value from lookup table, not 0 return calculated value    |
    '|                                                                           |
    '| Note: To use the lookup table the radian value needs to be converted to a |
    '|       degree value. The lookup table only contains the values for integer |
    '|       degrees ranging from 0 to 359. If you need a more precise           |
    '|       calculation set mode above to a non xero integer value.             |
    '+---------------------------------------------------------------------------+

    IF mode THEN '                    calculate vector?
        R2YV! = -COS(rad) '           yes, return calculated COSINE value (negate so 0 = north)
    ELSE '                            no, use lookup table
        R2YV! = -COSINE!(_R2D(rad)) ' return COSINE value from table (negate so 0 = north)
    END IF

END FUNCTION
'------------------------------------------------------------------------------------------------------------
FUNCTION D2XV! (deg AS SINGLE, mode AS INTEGER) ' degree to x vector

    '+---------------------------------------------------------------------------+
    '| Converts a degree value passed in to the corresponding x vector value.    |
    '| 0 = North / Up, 90 = East / Right, 180 = South / Down, 270 = West / Left. |
    '|                                                                           |
    '| deg  - the degree value to convert to x vector                            |
    '| mode - 0 return value from lookup table, not 0 return calculated value    |
    '|                                                                           |
    '| Note: The lookup table only contains SIN/COS values for integer degrees   |
    '|       ranging from 0 to 359. If you need a more precise calculation set   |
    '|       mode above to a non zero integer value.                             |
    '+---------------------------------------------------------------------------+

    IF mode THEN '               calculate vector?
        D2XV! = SIN(_D2R(deg)) ' yes, return calculated SINE value
    ELSE '                       no, use lookup table
        D2XV! = SINE!(deg) '     return SINE value from table
    END IF

END FUNCTION
'------------------------------------------------------------------------------------------------------------
FUNCTION D2YV! (deg AS SINGLE, mode AS INTEGER) ' degree to y vector

    '+---------------------------------------------------------------------------+
    '| Converts a degree value passed in to the corresponding y vector value.    |
    '| 0 = North / Up, 90 = East / Right, 180 = South / Down, 270 = West / Left. |
    '|                                                                           |
    '| deg  - the degree value to convert to y vector                            |
    '| mode - 0 return value from lookup table, not 0 return calculated value    |
    '|                                                                           |
    '| Note: The lookup table only contains SIN/COS values for integer degrees   |
    '|       ranging from 0 to 359. If you need a more precise calculation set   |
    '|       mode above to a non zero integer value.                             |
    '+---------------------------------------------------------------------------+

    IF mode THEN '                 calculate vector?
        D2YV! = -COS(_D2R(deg)) '  yes, return calculated COSINE value (negate so 0 = north)
    ELSE '                         no, use lookup table
        D2YV! = -COSINE!(deg) '    return COSINE value from table (negate so 0 = north)
    END IF

END FUNCTION
'------------------------------------------------------------------------------------------------------------
FUNCTION SINE! (Index AS INTEGER) ' SINE lookup table

    '+--------------------------------------------------+
    '| Returns a SINE value from the SINE lookup table. |
    '|                                                  |
    '| Index - 0 to 359                                 |
    '+--------------------------------------------------+

    STATIC x(360) AS SINGLE ' SINE lookup table persistent values
    DIM d AS INTEGER '        data counter

    '+-----------------------------------------------------------------+
    '| Build the SINE lookup table the first time subroutine is called |
    '+-----------------------------------------------------------------+

    IF x(90) = 0 THEN '          has the lookup table been built?
        DO '                     no, begin data read loop
            READ x(d) '          SINE   0 through  90
            x(180 - d) = x(d) '  SINE  90 through 180
            x(180 + d) = -x(d) ' SINE 180 through 270
            x(360 - d) = -x(d) ' SINE 270 through 360
            d = d + 1 '          increment degree counter
        LOOP UNTIL d = 91 '      leave when all data values read
    END IF
    SINE! = x(Index) '           return SINE

    '+------------------------------------------------------------------------------------------------------+
    '| The values for SINE 0 to 0.5PI (0 to 90 degrees)                                                     |
    '|                                                                                                      |
    '| I know what you're thinking, "Why not just calculate these and then place the values into the array  |
    '| table?" I was getting strange anomolies in the returned values. For instance, sometimes .49999999 or |
    '| .50000001 would show up for .5 and other times numbers like this would appear .58778552520000001.    |
    '| Creating and using this data set ensures consistent values.                                          |
    '+------------------------------------------------------------------------------------------------------+

    DATA 0
    DATA .017452406,.034899496,.052335956,.069756473,.087155742,.104528463,.121869343,.139173100,.156434465
    DATA .173648177,.190808995,.207911690,.224951054,.241921895,.258819045,.275637355,.292371704,.309016994
    DATA .325568154,.342020143,.358367949,.374606593,.390731128,.406736643,.422618261,.438371146,.453990499
    DATA .469471562,.484809620,.500000000,.515038074,.529919264,.544639035,.559192903,.573576436,.587785252
    DATA .601815023,.615661475,.629320391,.642787609,.656059028,.669130606,.681998360,.694658370,.707106781
    DATA .719339800,.731353701,.743144825,.754709580,.766044443,.777145961,.788010753,.798635510,.809016994
    DATA .819152044,.829037572,.838670567,.848048096,.857167300,.866025403,.874619707,.882947592,.891006524
    DATA .898794046,.906307787,.913545457,.920504853,.927183854,.933580426,.939692620,.945518575,.951056516
    DATA .956304755,.961261695,.965925826,.970295726,.974370064,.978147600,.981627183,.984807753,.987688340
    DATA .990268068,.992546151,.994521895,.996194698,.997564050,.998629534,.999390827,.999847695,1.00000000

END FUNCTION
'------------------------------------------------------------------------------------------------------------
FUNCTION COSINE! (Index AS INTEGER) ' COSINE lookup table

    '+---------------------------------------------------+
    '| Returns a COSINE value from the SIN lookup table. |
    '|                                                   |
    '| Index - 0 to 359                                  |
    '+---------------------------------------------------+

    SELECT CASE Index '                     which array index to return?
        CASE 0 TO 89 '                      quadrant 1
            COSINE! = SINE!(90 - Index) '   return equivalent from SINE table
        CASE 90 TO 179 '                    quadrant 2
            COSINE! = -SINE!(Index - 90) '  return equivalent from SINE table
        CASE 180 TO 269 '                   quadrant 3
            COSINE! = -SINE!(270 - Index) ' return equivalent from SINE table
        CASE 270 TO 359 '                   quadrant 4
            COSINE! = SINE!(Index - 270) '  return equivalent from SINE table
    END SELECT

END FUNCTION

Print this item

  Vintage programming
Posted by: BigPete - 05-14-2024, 11:53 AM - Forum: General Discussion - Replies (4)

Greetings all.

100% New here.
I normally program for windows, but i miss the good old days where stuff were so much simpler.
I also realize how much I have forgotten about Qbasic and the stuff I enjoyed.

My request is not really serious, but rather curious as to certain processes that I saw in VBDOS that were carried over into windows.
It is easy to use pre-existing controls in visual designers, but how on earth did Microsoft create those basic controls for VB dos??

Like: On a dos screen in QB64 I set width to 140, 50 which looks much like the old DOS screens.
Drawing boxes with Ascii codes using commands SUBs is pretty fun, but it is just lines and text.

How would one try and create a basic FORM in Screen 0 that looks like VBDOS (the draw is easy) that you could MOVE and open another?
It has to be some image clipping of sorts and event trapping?

I am having loads of fun, but i also realize how much i have become dependent on other people's designers without understanding the core processes that runs it.

Some ideas would be much appreciated.

Regards, Pete

Print this item