I collected together some basic shape plotting routines (circle, ellipse, semicircle, line, etc.) which plot shapes to a character array and display it on the screen (see attached or code box below).
They all seem to work great sending in fixed values, but when I try random values, in many cases the shapes are not visible when they ought to be.
For example:
I have code to make sure the random values keep the shapes within the bounds of the array and screen, so I'm not sure why this would be happening.
I have been beating my head against the wall with this, and am starting to see stars!
If anyone can give this a look and help fix problem, that would be great.
They all seem to work great sending in fixed values, but when I try random values, in many cases the shapes are not visible when they ought to be.
For example:
| Code | Problem |
|---|---|
| PlotCircleFillTopLeft 38, 11, 4, "#", arrScreen() | the rightmost row of the circle is missing |
| PlotCircleTopLeft 59, 25, 1, "#", arrScreen() | shows nothing where the crosshairs indicate the shape should be |
| PlotEllipse 61, 27, 9, 4, "#", arrScreen() | " " |
| PlotEllipseFill 75, 10, 7, 8, "#", arrScreen() | " " |
| PlotEllipseFillTopLeft 91, 16, 2, 1, "#", arrScreen() | " " |
| PlotSemiCircle 63, 2, 1,1, "#", arrScreen() | " " |
| PlotSemiCircleTopLeft 63, 6, 7,2, "#", arrScreen() | " " |
| PlotLine 66, 13, 97, 18, "#", arrScreen() | " " |
| PlotCircle 62, 8, 1, "#", arrScreen() | " " |
I have code to make sure the random values keep the shapes within the bounds of the array and screen, so I'm not sure why this would be happening.
I have been beating my head against the wall with this, and am starting to see stars!
If anyone can give this a look and help fix problem, that would be great.
Code: (Select All)
Option _Explicit
$Color:32
' 32-bit color names = Black Blue Green Cyan Red Magenta Brown White Gray LightBlue LightGreen LightCyan LightRed LightMagenta Yellow BrightWhite
' ================================================================================================================================================================
' BEGIN GLOBAL CONSTANTS
' ================================================================================================================================================================
' SCREEN SIZE
Const cScreenSizeX = 1024 ' 1920 ' 1024
Const cScreenSizeY = 768 ' 1080 ' 768
' Enables or disables debugging
Const cDebugEnabled = _FALSE
' ================================================================================================================================================================
' END GLOBAL CONSTANTS
' ================================================================================================================================================================
' ================================================================================================================================================================
' BEGIN TYPES
' ================================================================================================================================================================
' (none)
' ================================================================================================================================================================
' END TYPES
' ================================================================================================================================================================
' ================================================================================================================================================================
' BEGIN GLOBAL VARIABLES
' ================================================================================================================================================================
' Program info
Dim Shared m_ProgramPath As String: m_ProgramPath = Left$(Command$(0), _InStrRev(Command$(0), "\")) ' executable path
Dim Shared m_ProgramName As String: m_ProgramName = Mid$(Command$(0), _InStrRev(Command$(0), "\") + 1) ' executable filename
' For debugging
Dim Shared m_sDebugFile As String: m_sDebugFile = m_ProgramPath + m_ProgramName + ".txt"
' For error trapping
Dim Shared ErrCount&: ErrCount& = 0 ' count errors
Dim Shared LastRoutine$: LastRoutine$ = "" ' routine name we are in
Dim Shared LastCode$: LastCode$ = "" ' where in the code we are (last command attempted)
Dim Shared ErrDesc$: ErrDesc$ = "" ' description of error
Dim Shared LastError$: LastError$ = "" ' last error message
Dim Shared debug$: debug$ = "" ' for debug messages
' Map dimensions
Dim Shared MaxRow As Integer
Dim Shared MaxCol As Integer
' Arrays
ReDim Shared arrScreen(0, 0) As String * 1 ' arrScreen(y, x) = The map array
' ================================================================================================================================================================
' END GLOBAL VARIABLES
' ================================================================================================================================================================
' ================================================================================================================================================================
' BEGIN EXECUTION STARTS HERE
' ================================================================================================================================================================
' LOCAL VARIABLES
Dim in$
' Start the program
Main
' DONE!
End
' ================================================================================================================================================================
' END EXECUTION STARTS HERE
' ================================================================================================================================================================
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' BEGIN GLOBAL ERROR HANDLER
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ErrorHandler:
'' COUNT THE ERROR
ErrCount& = ErrCount& + 1
' SHOW ERROR + WHERE IN THE PROGRAM WE WERE WHEN ERROR HAPPENED
LastError$ = "Error #" + _ToStr$(Err)
' TRY TO GET ERROR DESCRIPTION
If Err >= 1 And Err <= 1 Then
ErrDesc$ = "Legacy error: NEXT without FOR"
ElseIf Err >= 8 And Err <= 8 Then
ErrDesc$ = "Legacy error: Label not defined"
ElseIf Err >= 12 And Err <= 12 Then
ErrDesc$ = "Legacy error: Illegal in direct mode"
ElseIf Err >= 14 And Err <= 14 Then
ErrDesc$ = "Legacy error: Out of string space"
ElseIf Err >= 16 And Err <= 16 Then
ErrDesc$ = "Legacy error: String formula too complex"
ElseIf Err >= 17 And Err <= 17 Then
ErrDesc$ = "Legacy error: Cannot continue"
ElseIf Err >= 18 And Err <= 18 Then
ErrDesc$ = "Legacy error: Function not defined"
ElseIf Err >= 19 And Err <= 19 Then
ErrDesc$ = "Legacy error: No RESUME"
ElseIf Err >= 24 And Err <= 24 Then
ErrDesc$ = "Legacy error: Device timeout"
ElseIf Err >= 25 And Err <= 25 Then
ErrDesc$ = "Legacy error: Device fault"
ElseIf Err >= 26 And Err <= 26 Then
ErrDesc$ = "Legacy error: FOR without NEXT"
ElseIf Err >= 27 And Err <= 27 Then
ErrDesc$ = "Legacy error: Out of paper"
ElseIf Err >= 29 And Err <= 29 Then
ErrDesc$ = "Legacy error: WHILE without WEND"
ElseIf Err >= 30 And Err <= 30 Then
ErrDesc$ = "Legacy error: WEND without WHILE"
ElseIf Err >= 33 And Err <= 33 Then
ErrDesc$ = "Legacy error: Duplicate label"
ElseIf Err >= 35 And Err <= 35 Then
ErrDesc$ = "Legacy error: Subprogram not defined"
ElseIf Err >= 37 And Err <= 37 Then
ErrDesc$ = "Legacy error: Argument-count mismatch"
ElseIf Err >= 38 And Err <= 38 Then
ErrDesc$ = "Legacy error: Array not defined"
ElseIf Err >= 40 And Err <= 40 Then
ErrDesc$ = "Legacy error: Variable required"
ElseIf Err >= 56 And Err <= 56 Then
ErrDesc$ = "Legacy error: FIELD statement active"
ElseIf Err >= 57 And Err <= 57 Then
ErrDesc$ = "Legacy error: Device I/O error"
ElseIf Err >= 58 And Err <= 58 Then
ErrDesc$ = "Legacy error: File already exists"
ElseIf Err >= 61 And Err <= 61 Then
ErrDesc$ = "Legacy error: Disk full"
ElseIf Err >= 67 And Err <= 67 Then
ErrDesc$ = "Legacy error: Too many files"
ElseIf Err >= 69 And Err <= 69 Then
ErrDesc$ = "Legacy error: Communication-buffer overflow"
ElseIf Err >= 71 And Err <= 71 Then
ErrDesc$ = "Legacy error: Disk not ready"
ElseIf Err >= 72 And Err <= 72 Then
ErrDesc$ = "Legacy error: Disk-media error"
ElseIf Err >= 73 And Err <= 73 Then
ErrDesc$ = "Legacy error: Feature unavailable"
ElseIf Err >= 74 And Err <= 74 Then
ErrDesc$ = "Legacy error: Rename across disks"
ElseIf Err >= 11 And Err <= 11 Then
ErrDesc$ = "Critical error: Division by zero"
ElseIf Err >= 256 And Err <= 256 Then
ErrDesc$ = "Critical error: Out of stack space"
ElseIf Err >= 257 And Err <= 257 Then
ErrDesc$ = "Critical error: Out of memory"
ElseIf Err >= 259 And Err <= 259 Then
ErrDesc$ = "Critical error: Cannot find dynamic library file"
ElseIf Err >= 260 And Err <= 261 Then
ErrDesc$ = "Critical error: Sub/Function does not exist in dynamic library"
ElseIf Err >= 270 And Err <= 270 Then
ErrDesc$ = "Critical error: _GL command called outside of SUB _GL's scope"
ElseIf Err >= 271 And Err <= 271 Then
ErrDesc$ = "Critical error: END/SYSTEM called within SUB _GL's scope"
ElseIf Err >= 300 And Err <= 300 Then
ErrDesc$ = "Critical error: Memory region out of range"
ElseIf Err >= 301 And Err <= 301 Then
ErrDesc$ = "Critical error: Invalid size"
ElseIf Err >= 302 And Err <= 302 Then
ErrDesc$ = "Critical error: Source memory region out of range"
ElseIf Err >= 303 And Err <= 303 Then
ErrDesc$ = "Critical error: Destination memory region out of range"
ElseIf Err >= 304 And Err <= 304 Then
ErrDesc$ = "Critical error: Source and destination memory regions out of range"
ElseIf Err >= 305 And Err <= 305 Then
ErrDesc$ = "Critical error: Source memory has been freed"
ElseIf Err >= 306 And Err <= 306 Then
ErrDesc$ = "Critical error: Destination memory has been freed"
ElseIf Err >= 307 And Err <= 307 Then
ErrDesc$ = "Critical error: Memory already freed"
ElseIf Err >= 308 And Err <= 308 Then
ErrDesc$ = "Critical error: Memory has been freed"
ElseIf Err >= 309 And Err <= 309 Then
ErrDesc$ = "Critical error: Memory not initialized"
ElseIf Err >= 310 And Err <= 310 Then
ErrDesc$ = "Critical error: Source memory not initialized"
ElseIf Err >= 311 And Err <= 311 Then
ErrDesc$ = "Critical error: Destination memory not initialized"
ElseIf Err >= 312 And Err <= 312 Then
ErrDesc$ = "Critical error: Source and destination memory not initialized"
ElseIf Err >= 313 And Err <= 313 Then
ErrDesc$ = "Critical error: Source and destination memory have been freed"
ElseIf Err >= 314 And Err <= 314 Then
ErrDesc$ = "Critical error: _ASSERT failed"
ElseIf Err >= 315 And Err <= 315 Then
ErrDesc$ = "Critical error: _ASSERT failed (check console for description)"
ElseIf Err >= 502 And Err <= 518 Then
ErrDesc$ = "Critical error: Out of memory"
ElseIf Err >= 2 And Err <= 2 Then
ErrDesc$ = "Recoverable error: Syntax error"
ElseIf Err >= 3 And Err <= 3 Then
ErrDesc$ = "Recoverable error: RETURN without GOSUB"
ElseIf Err >= 4 And Err <= 4 Then
ErrDesc$ = "Recoverable error: Out of DATA"
ElseIf Err >= 5 And Err <= 5 Then
ErrDesc$ = "Recoverable error: Illegal function call"
ElseIf Err >= 6 And Err <= 6 Then
ErrDesc$ = "Recoverable error: Overflow"
ElseIf Err >= 7 And Err <= 7 Then
ErrDesc$ = "Recoverable error: Out of memory"
ElseIf Err >= 9 And Err <= 9 Then
ErrDesc$ = "Recoverable error: Subscript out of range"
ElseIf Err >= 10 And Err <= 10 Then
ErrDesc$ = "Recoverable error: Duplicate definition"
ElseIf Err >= 13 And Err <= 13 Then
ErrDesc$ = "Recoverable error: Type mismatch"
ElseIf Err >= 20 And Err <= 20 Then
ErrDesc$ = "Recoverable error: RESUME without error"
ElseIf Err >= 50 And Err <= 50 Then
ErrDesc$ = "Recoverable error: FIELD overflow"
ElseIf Err >= 51 And Err <= 51 Then
ErrDesc$ = "Recoverable error: Internal error"
ElseIf Err >= 52 And Err <= 52 Then
ErrDesc$ = "Recoverable error: Bad file name or number"
ElseIf Err >= 53 And Err <= 53 Then
ErrDesc$ = "Recoverable error: File not found"
ElseIf Err >= 54 And Err <= 54 Then
ErrDesc$ = "Recoverable error: Bad file mode"
ElseIf Err >= 55 And Err <= 55 Then
ErrDesc$ = "Recoverable error: File already open"
ElseIf Err >= 59 And Err <= 59 Then
ErrDesc$ = "Recoverable error: Bad record length"
ElseIf Err >= 62 And Err <= 62 Then
ErrDesc$ = "Recoverable error: Input past end of file"
ElseIf Err >= 63 And Err <= 63 Then
ErrDesc$ = "Recoverable error: Bad record number"
ElseIf Err >= 64 And Err <= 64 Then
ErrDesc$ = "Recoverable error: Bad file name"
ElseIf Err >= 68 And Err <= 68 Then
ErrDesc$ = "Recoverable error: Device unavailable"
ElseIf Err >= 70 And Err <= 70 Then
ErrDesc$ = "Recoverable error: Permission denied"
ElseIf Err >= 75 And Err <= 75 Then
ErrDesc$ = "Recoverable error: Path/File access error"
ElseIf Err >= 76 And Err <= 76 Then
ErrDesc$ = "Recoverable error: Path not found"
ElseIf Err >= 258 And Err <= 258 Then
ErrDesc$ = "Recoverable error: Invalid handle"
Else
ErrDesc$ = "Unknown error"
End If
LastError$ = LastError$ + " (" + ErrDesc$ + ") " + _
"in " + LastRoutine$ + " " + _
"at line " + _ToStr$(_ErrorLine) + " " + _
": " + LastCode$
debug$ = _InputBox$(m_ProgramName, "An unrecoverable error occurred (details below). Click OK to exit.", LastError$)
System
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' END GLOBAL ERROR HANDLER
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' BEGIN PLOT SHAPES DEMO
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' /////////////////////////////////////////////////////////////////////////////
' USES GLOBAL VARIABLES:
' ReDim Shared arrScreen(0, 0) As String * 1 ' arrScreen(y, x) = The map array
' AND MAYBE:
' ReDim Shared arrNext(0, 0) As String * 1 ' arrNext(y, x) = Next generation map = Used by cellular automata algorithm:
Sub Main
Dim RoutineName As String:: RoutineName = "PlotshapesDemo": LastRoutine$ = RoutineName
'ReDim arrScreen(-1, -1) As String
Dim in$
Dim X As Integer
Dim Y As Integer
Dim R As Integer
Dim S As String
Dim XC As Integer
Dim YC As Integer
Dim xRadius As Integer
Dim yRadius As Integer
Dim Q As Integer
Dim L As Integer
Dim MinX As Integer
Dim MaxX As Integer
Dim MinY As Integer
Dim MaxY As Integer
Dim x1 As Integer
Dim x2 As Integer
Dim y1 As Integer
Dim y2 As Integer
Dim iCount As Integer
Dim sNextFunction As String
Dim sNextParams As String
Dim GuideX1 As Integer
Dim GuideY1 As Integer
Dim GuideX2 As Integer
Dim GuideY2 As Integer
Dim bRandomValues As Integer
On Error GoTo ErrorHandler
' Initialize screen + get dimensions
Screen _NewImage(cScreenSizeX, cScreenSizeY, 32)
_ScreenMove 0, 0
MaxRow = _Height / _FontHeight
MaxCol = _Width / _FontWidth
' Define map boundaries
ReDim arrScreen(0 To MaxRow, 0 To MaxCol) As String * 1
' Initialize
MinY = 0
MaxY = MaxRow - 3
MinX = 0
MaxX = MaxCol
S = "#"
bRandomValues = _FALSE
' Get first choice
Cls , Black
Color Black, Cyan:
Locate MaxRow - 2, 5
Input "Enter R to continue with random values, F for fixed values or Q to quit"; in$
in$ = _Trim$(UCase$(in$)): If in$ = "Q" Then Exit Sub
If in$ = "R" Then
bRandomValues = _TRUE
Else
bRandomValues = _FALSE
End If
' Plot shapes
iCount = 0
Do
iCount = iCount + 1
' CLEAR DISPLAY ARRAY
For Y = LBound(arrScreen, 1) To UBound(arrScreen, 1)
For X = LBound(arrScreen, 2) To UBound(arrScreen, 2)
arrScreen(Y, X) = " "
Next X
Next Y
Select Case iCount
Case 1:
If bRandomValues = _TRUE Then
R = RandomNumber%(1, 10)
' FIX: Center (X, Y) must be at least R away from the screen edges
X = RandomNumber%(MinX + R, MaxX - R)
Y = RandomNumber%(MinY + R, MaxY - R)
Else
R = 5
X = 10
Y = 15
End If
GuideX1 = X: GuideY1 = Y: GuideX2 = MinX - 1: GuideY2 = MinY - 1
sNextFunction = "PlotCircle X, Y, R, S, arrScreen()"
sNextParams = "PlotCircle " + _ToStr$(X) + ", " + _ToStr$(Y) + ", " + _ToStr$(R) + ", " + Chr$(34) + S + Chr$(34) + ", " + "arrScreen()"
PlotCircle X, Y, R, S, arrScreen()
Case 2:
If bRandomValues = _TRUE Then
R = RandomNumber%(1, 10)
' FIX: Top-Left corner (X, Y) must be at least 2*R away from MaxX/MaxY
X = RandomNumber%(MinX, MaxX - 2 * R)
Y = RandomNumber%(MinY, MaxY - 2 * R)
Else
R = 5
X = 10
Y = 15
End If
GuideX1 = X: GuideY1 = Y: GuideX2 = MinX - 1: GuideY2 = MinY - 1
sNextFunction = "PlotCircleTopLeft X, Y, R, S, arrScreen()"
sNextParams = "PlotCircleTopLeft " + _ToStr$(X) + ", " + _ToStr$(Y) + ", " + _ToStr$(R) + ", " + Chr$(34) + S + Chr$(34) + ", " + "arrScreen()"
PlotCircleTopLeft X, Y, R, S, arrScreen()
Case 3:
If bRandomValues = _TRUE Then
R = RandomNumber%(1, 10)
' FIX: Center (XC, YC) must be at least R away from the screen edges
XC = RandomNumber%(MinX + R, MaxX - R)
YC = RandomNumber%(MinY + R, MaxY - R)
Else
R = 5
XC = 10
YC = 15
End If
GuideX1 = XC: GuideY1 = YC: GuideX2 = MinX - 1: GuideY2 = MinY - 1
sNextFunction = "PlotCircleFill XC, YC, R, S, arrScreen()"
sNextParams = "PlotCircleFill " + _ToStr$(XC) + ", " + _ToStr$(YC) + ", " + _ToStr$(R) + ", " + Chr$(34) + S + Chr$(34) + ", " + "arrScreen()"
PlotCircleFill XC, YC, R, S, arrScreen()
Case 4:
If bRandomValues = _TRUE Then
R = RandomNumber%(1, 10)
' FIX: Top-Left corner (XC, YC) must be at least 2*R away from MaxX/MaxY
XC = RandomNumber%(MinX, MaxX - 2 * R)
YC = RandomNumber%(MinY, MaxY - 2 * R)
Else
R = 5
XC = 10
YC = 15
End If
GuideX1 = XC: GuideY1 = YC: GuideX2 = MinX - 1: GuideY2 = MinY - 1
sNextFunction = "PlotCircleFillTopLeft XC, YC, R, S, arrScreen()"
sNextParams = "PlotCircleFillTopLeft " + _ToStr$(XC) + ", " + _ToStr$(YC) + ", " + _ToStr$(R) + ", " + Chr$(34) + S + Chr$(34) + ", " + "arrScreen()"
PlotCircleFillTopLeft XC, YC, R, S, arrScreen()
Case 5:
If bRandomValues = _TRUE Then
xRadius = RandomNumber%(1, 10)
yRadius = RandomNumber%(1, 10)
' FIX: Center (XC, YC) must be at least xRadius/yRadius away from screen edges
XC = RandomNumber%(MinX + xRadius, MaxX - xRadius)
YC = RandomNumber%(MinY + yRadius, MaxY - yRadius)
Else
xRadius = 5
yRadius = 8
XC = 10
YC = 15
End If
GuideX1 = XC: GuideY1 = YC: GuideX2 = MinX - 1: GuideY2 = MinY - 1
sNextFunction = "PlotEllipse XC, YC, xRadius, yRadius, S, arrScreen()"
sNextParams = "PlotEllipse " + _ToStr$(XC) + ", " + _ToStr$(YC) + ", " + _ToStr$(xRadius) + ", " + _ToStr$(yRadius) + ", " + Chr$(34) + S + Chr$(34) + ", " + "arrScreen()"
PlotEllipse XC, YC, xRadius, yRadius, S, arrScreen()
Case 6:
If bRandomValues = _TRUE Then
xRadius = RandomNumber%(1, 10)
yRadius = RandomNumber%(1, 10)
' FIX: Top-Left corner (X, Y) must be at least 2*xRadius/2*yRadius away from MaxX/MaxY
X = RandomNumber%(MinX, MaxX - 2 * xRadius)
Y = RandomNumber%(MinY, MaxY - 2 * yRadius)
Else
xRadius = 5
yRadius = 8
X = 10
Y = 15
End If
GuideX1 = X: GuideY1 = Y: GuideX2 = MinX - 1: GuideY2 = MinY - 1
sNextFunction = "PlotEllipseTopLeft X, Y, xRadius, yRadius, S, arrScreen()"
sNextParams = "PlotEllipseTopLeft " + _ToStr$(X) + ", " + _ToStr$(Y) + ", " + _ToStr$(xRadius) + ", " + _ToStr$(yRadius) + ", " + Chr$(34) + S + Chr$(34) + ", " + "arrScreen()"
PlotEllipseTopLeft X, Y, xRadius, yRadius, S, arrScreen()
Case 7:
If bRandomValues = _TRUE Then
xRadius = RandomNumber%(1, 10)
yRadius = RandomNumber%(1, 10)
' FIX: Center (XC, YC) must be at least xRadius/yRadius away from screen edges
XC = RandomNumber%(MinX + xRadius, MaxX - xRadius)
YC = RandomNumber%(MinY + yRadius, MaxY - yRadius)
Else
xRadius = 5
yRadius = 8
XC = 10
YC = 15
End If
GuideX1 = XC: GuideY1 = YC: GuideX2 = MinX - 1: GuideY2 = MinY - 1
sNextFunction = "PlotEllipseFill XC, YC, xRadius, yRadius, S, arrScreen()"
sNextParams = "PlotEllipseFill " + _ToStr$(XC) + ", " + _ToStr$(YC) + ", " + _ToStr$(xRadius) + ", " + _ToStr$(yRadius) + ", " + Chr$(34) + S + Chr$(34) + ", " + "arrScreen()"
PlotEllipseFill XC, YC, xRadius, yRadius, S, arrScreen()
Case 8:
If bRandomValues = _TRUE Then
xRadius = RandomNumber%(1, 10)
yRadius = RandomNumber%(1, 10)
' FIX: Top-Left corner (X, Y) must be at least 2*xRadius/2*yRadius away from MaxX/MaxY
X = RandomNumber%(MinX, MaxX - 2 * xRadius)
Y = RandomNumber%(MinY, MaxY - 2 * yRadius)
Else
xRadius = 5
yRadius = 8
X = 10
Y = 15
End If
GuideX1 = X: GuideY1 = Y: GuideX2 = MinX - 1: GuideY2 = MinY - 1
sNextFunction = "PlotEllipseFillTopLeft X, Y, xRadius, yRadius, S, arrScreen()"
sNextParams = "PlotEllipseFillTopLeft " + _ToStr$(X) + ", " + _ToStr$(Y) + ", " + _ToStr$(xRadius) + ", " + _ToStr$(yRadius) + ", " + Chr$(34) + S + Chr$(34) + ", " + "arrScreen()"
PlotEllipseFillTopLeft X, Y, xRadius, yRadius, S, arrScreen()
Case 9:
If bRandomValues = _TRUE Then
R = RandomNumber%(1, 10)
' FIX: Center (XC, YC) must be at least R away from the screen edges
XC = RandomNumber%(MinX + R, MaxX - R)
YC = RandomNumber%(MinY + R, MaxY - R)
Q = RandomNumber%(1, 4) ' 1=top right, 2=bottom right, 3=bottom left, 4=top left
Else
R = 8
XC = 10
YC = 12
Q = 3
End If
GuideX1 = XC: GuideY1 = YC: GuideX2 = MinX - 1: GuideY2 = MinY - 1
sNextFunction = "PlotSemiCircle XC, YC, R, Q, S, arrScreen()"
sNextParams = "PlotSemiCircle " + _ToStr$(XC) + ", " + _ToStr$(YC) + ", " + _ToStr$(R) + ", " + _ToStr$(Q) + ", " + Chr$(34) + S + Chr$(34) + ", " + "arrScreen()"
PlotSemiCircle XC, YC, R, Q, S, arrScreen()
Case 10:
If bRandomValues = _TRUE Then
R = RandomNumber%(1, 10)
' FIX: Top-Left corner (X, Y) must be at least 2*R away from MaxX/MaxY
X = RandomNumber%(MinX, MaxX - 2 * R)
Y = RandomNumber%(MinY, MaxY - 2 * R)
Q = RandomNumber%(1, 4) ' 1=top right, 2=bottom right, 3=bottom left, 4=top left
Else
R = 8
X = 10
Y = 12
Q = 3
End If
GuideX1 = X: GuideY1 = Y: GuideX2 = MinX - 1: GuideY2 = MinY - 1
sNextFunction = "PlotSemicircleTopLeft X, Y, R, Q, S, arrScreen()"
sNextParams = "PlotSemicircleTopLeft " + _ToStr$(X) + ", " + _ToStr$(Y) + ", " + _ToStr$(R) + ", " + _ToStr$(Q) + ", " + Chr$(34) + S + Chr$(34) + ", " + "arrScreen()"
PlotSemicircleTopLeft X, Y, R, Q, S, arrScreen()
Case 11:
If bRandomValues = _TRUE Then
R = RandomNumber%(1, 10)
' FIX: Center (XC, YC) must be at least R away from the screen edges
XC = RandomNumber%(MinX + R, MaxX - R)
YC = RandomNumber%(MinY + R, MaxY - R)
Q = RandomNumber%(1, 4) ' 1=top right, 2=bottom right, 3=bottom left, 4=top left
Else
R = 8
XC = 10
YC = 12
Q = 3
End If
GuideX1 = XC: GuideY1 = YC: GuideX2 = MinX - 1: GuideY2 = MinY - 1
sNextFunction = "PlotSemiCircleFill XC, YC, R, Q, S, arrScreen()"
sNextParams = "PlotSemiCircleFill " + _ToStr$(XC) + ", " + _ToStr$(YC) + ", " + _ToStr$(R) + ", " + _ToStr$(Q) + ", " + Chr$(34) + S + Chr$(34) + ", " + "arrScreen()"
PlotSemiCircleFill XC, YC, R, Q, S, arrScreen()
Case 12:
If bRandomValues = _TRUE Then
R = RandomNumber%(1, 10)
' FIX: Top-Left corner (X, Y) must be at least 2*R away from MaxX/MaxY
X = RandomNumber%(MinX, MaxX - 2 * R)
Y = RandomNumber%(MinY, MaxY - 2 * R)
Q = RandomNumber%(1, 4) ' 1=top right, 2=bottom right, 3=bottom left, 4=top left
Else
R = 8
X = 10
Y = 12
Q = 3
End If
GuideX1 = X: GuideY1 = Y: GuideX2 = MinX - 1: GuideY2 = MinY - 1
sNextFunction = "PlotSemiCircleFillTopLeft X, Y, R, Q, S, arrScreen()"
sNextParams = "PlotSemiCircleFillTopLeft " + _ToStr$(X) + ", " + _ToStr$(Y) + ", " + _ToStr$(R) + ", " + _ToStr$(Q) + ", " + Chr$(34) + S + Chr$(34) + ", " + "arrScreen()"
PlotSemiCircleFillTopLeft X, Y, R, Q, S, arrScreen()
Case 13:
If bRandomValues = _TRUE Then
L = RandomNumber%(1, 10)
' FIX: Top-Left corner (X, Y) must be at least L away from MaxX/MaxY
X = RandomNumber%(MinX, MaxX - L)
Y = RandomNumber%(MinY, MaxY - L)
Else
X = 5
Y = 3
L = 4
End If
GuideX1 = X: GuideY1 = Y: GuideX2 = MinX - 1: GuideY2 = MinY - 1
sNextFunction = "PlotSquare X, Y, L, S, arrScreen()"
sNextParams = "PlotSquare " + _ToStr$(X) + ", " + _ToStr$(Y) + ", " + _ToStr$(L) + ", " + Chr$(34) + S + Chr$(34) + ", " + "arrScreen()"
PlotSquare X, Y, L, S, arrScreen()
Case Else:
If bRandomValues = _TRUE Then
' Line endpoints are already within the boundary Min/Max X/Y. No change needed.
y1 = RandomNumber%(MinY, MaxY): y2 = y1
x1 = RandomNumber%(MinX, MaxX): x2 = x1
Do
y2 = RandomNumber%(MinY, MaxY)
x2 = RandomNumber%(MinX, MaxX)
Loop Until y2 <> y1 Or x2 <> x1
Else
x1 = 3
y1 = 5
x2 = 6
y2 = 9
End If
GuideX1 = x1: GuideY1 = y1: GuideX2 = x2: GuideY2 = y2
sNextFunction = "PlotLine x1, y1, x2, y2, S, arrScreen()"
sNextParams = "PlotLine " + _ToStr$(x1) + ", " + _ToStr$(y1) + ", " + _ToStr$(x2) + ", " + _ToStr$(y2) + ", " + Chr$(34) + S + Chr$(34) + ", " + "arrScreen()"
PlotLine x1, y1, x2, y2, S, arrScreen()
iCount = 0
End Select
' REFRESH DISPLAY
PlotShapesPrintScreen GuideY1, GuideX1, GuideY2, GuideX2
' SHOW VALUES AND PROMPT USER TO TOGGLE RANDOM OR
Color Black, Cyan:
Locate MaxRow - 5, 5
Print "Generated with " + _IIf(bRandomValues, "random", "fixed") + " values";
Locate MaxRow - 4, 5
Print sNextFunction;
Locate MaxRow - 3, 5
Print sNextParams;
Locate MaxRow - 2, 5
If bRandomValues = _TRUE Then
Input "Enter R to continue with random values, F for change to fixed values, or Q to quit"; in$
Else
Input "Enter R to change to random values, F for continue with fixed values, or Q to quit"; in$
End If
in$ = _Trim$(UCase$(in$))
If in$ = "R" Then
bRandomValues = _TRUE
ElseIf in$ = "F" Then
bRandomValues = _FALSE
ElseIf in$ = "Q" Then
Exit Do
Else
'(UNCHANGED)
End If
Loop
End Sub ' PlotshapesDemo
' /////////////////////////////////////////////////////////////////////////////
' Requires the following populated global variable:
' Dim Shared MaxRow As Integer
' Dim Shared MaxCol As Integer
' ReDim Shared arrScreen(0 To MaxRow, 0 To MaxCol) As String * 1
' Receives GuideY, GuideX
' draws a horizontal line at Y = GuideY
' and a vertical line at X = GuideX
' as a visual guide to line up where we expect the shape to be
Sub PlotShapesPrintScreen (iGuideY1 As Integer, iGuideX1 As Integer, iGuideY2 As Integer, iGuideX2 As Integer)
Dim RoutineName As String:: RoutineName = "PlotShapesPrintScreen": LastRoutine$ = RoutineName
Dim OffsetX As Integer
Dim OffsetY As Integer
Dim iX As Integer
Dim iY As Integer
Dim sValue As String
Dim sNext As String
Dim ToX As Integer
Dim ToY As Integer
Dim fg As _Unsigned Long
Dim bg As _Unsigned Long
Dim GuideY1 As Integer
Dim GuideX1 As Integer
Dim GuideY2 As Integer
Dim GuideX2 As Integer
Dim r As Integer
Dim g As Integer
Dim b As Integer
ReDim arrDisplay(0 To MaxRow, 0 To MaxCol) As String * 1
On Error GoTo ErrorHandler
' ADJUST GUIDELINES PER OFFSET FOR X AND Y COORDINATE NUMBERS
OffsetX = 3
OffsetY = 3
GuideY1 = iGuideY1 + OffsetY
GuideX1 = iGuideX1 + OffsetX
GuideY2 = iGuideY2 + OffsetY
GuideX2 = iGuideX2 + OffsetX
' CLEAR DISPLAY ARRAY
For iY = LBound(arrDisplay, 1) To UBound(arrDisplay, 1)
For iX = LBound(arrDisplay, 2) To UBound(arrDisplay, 2)
arrDisplay(iY, iX) = " "
Next iX
Next iY
' ADD Y COORDINATE NUMBERS ALONG LEFT EDGE
iX = LBound(arrDisplay, 2)
For iY = LBound(arrDisplay, 1) To (UBound(arrDisplay, 1) - OffsetY)
sValue = PadLeft$(_ToStr$(iY), 3)
arrDisplay(iY + OffsetY, iX + 0) = Mid$(sValue, 1, 1)
arrDisplay(iY + OffsetY, iX + 1) = Mid$(sValue, 2, 1)
arrDisplay(iY + OffsetY, iX + 2) = Mid$(sValue, 3, 1)
Next iY
' ADD X COORDINATE NUMBERS ALONG TOP EDGE
iY = LBound(arrDisplay, 1)
For iX = LBound(arrDisplay, 2) To (UBound(arrDisplay, 2) - OffsetX)
sValue = PadLeft$(_ToStr$(iX), 3)
arrDisplay(iY + 0, iX + OffsetX) = Mid$(sValue, 1, 1)
arrDisplay(iY + 1, iX + OffsetX) = Mid$(sValue, 2, 1)
arrDisplay(iY + 2, iX + OffsetX) = Mid$(sValue, 3, 1)
Next iX
'if _TRUE=_FALSE then
' COPY OVER SHAPES (SHIFTED DOWN+RIGHT 3, TO SEE COORDINATE NUMBERS)
For iY = LBound(arrScreen, 2) To UBound(arrScreen, 2) - OffsetY
For iX = LBound(arrScreen, 1) To UBound(arrScreen, 1) - OffsetX
ToY = iY + OffsetY
ToX = iX + OffsetX
if ToY >= lbound(arrDisplay, 1) _
_ANDALSO ToY <= ubound(arrDisplay, 1) _
_ANDALSO ToX >= lbound(arrDisplay, 2) _
_ANDALSO ToX <= ubound(arrDisplay, 2) _
Then
arrDisplay(ToY, ToX) = arrScreen(iY, iX)
End If
Next iX
Next iY
'end if
' PRINT SHAPES
' 32-bit color names = Black Blue Green Cyan Red Magenta Brown White Gray LightBlue LightGreen LightCyan LightRed LightMagenta Yellow BrightWhite
Cls , Black
For iY = LBound(arrDisplay, 1) To UBound(arrDisplay, 1)
For iX = LBound(arrDisplay, 2) To UBound(arrDisplay, 2)
' Alternate bg color for rows/columns
If IsEven%(iY) _AndAlso IsEven%(iX) Then
bg = _RGB32(0, 0, 96)
ElseIf IsOdd%(iY) _AndAlso IsEven%(iX) Then
bg = _RGB32(0, 96, 0)
ElseIf IsEven%(iY) _AndAlso IsOdd%(iX) Then
bg = _RGB32(0, 0, 160)
Else
bg = _RGB32(0, 160, 0)
End If
' Override bg color if it is along one of the guide lines
If iY = GuideY1 Then
bg = _RGB32(192, 192, 0)
ElseIf iY = GuideY2 Then
bg = _RGB32(192, 0, 192)
End If
If iX = GuideX1 Then
bg = _RGB32(192, 192, 0)
ElseIf iX = GuideX2 Then
bg = _RGB32(192, 0, 192)
End If
' Set color for plotted points, text
sNext = arrDisplay(iY, iX)
Select Case sNext
Case "#":
' Color for next plotted point
fg = _RGB32(0, 0, 0)
' Set bg color to inverse of current bg color
r = _Red32(bg): g = _Green32(bg): b = _Blue32(bg)
bg = _RGB32(255 - r, 255 - g, 255 - b)
Case Else
' Assume all else = text
fg = _RGB32(255, 255, 255)
End Select
' Plot next character / point
Color fg, bg
_PrintString (iX * _FontWidth, iY * _FontHeight), arrDisplay(iY, iX)
Next iX
Next iY
End Sub ' PlotShapesPrintScreen
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' END PLOT SHAPES DEMO
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' BEGIN 2D SHAPE PLOTTING FUNCTIONS
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' /////////////////////////////////////////////////////////////////////////////
' More on plotting circles:
' Fast circle drawing in pure Atari BASIC#
' https://atariwiki.org/wiki/Wiki.jsp?page=Super%20fast%20circle%20routine
'
' Drawing a circle in BASIC - fast
' https://www.cpcwiki.eu/forum/programming/drawing-a-circle-in-basic-fast/
' XC,YC = center point of circle
' R = radius
' S = char to draw
' MyArray = 2D string array to plot circle in
Sub PlotCircle (XC As Integer, YC As Integer, R As Integer, S As String, MyArray() As String * 1)
Dim RoutineName As String:: RoutineName = "PlotCircle": LastRoutine$ = RoutineName
Print "PlotCircle XC=" + _ToStr$(XC) + ", YC=" + _ToStr$(YC) + ", R=" + _ToStr$(R) + ", S=" + Chr$(34) + S + Chr$(34) + ", MyArray()"
Dim A As Integer
Dim B As Integer
Dim C As Integer
Dim S2 As String
On Error GoTo ErrorHandler
If Len(S) = 1 Then
S2 = S
Else
If Len(S) = 0 Then
S2 = " "
Else
S2 = Left$(S, 1)
End If
End If
' Handle R=1 explicitly to ensure visibility
If R = 1 Then
PlotPoint XC, YC, S, MyArray()
PlotPoint XC + 1, YC, S, MyArray()
PlotPoint XC - 1, YC, S, MyArray()
PlotPoint XC, YC + 1, S, MyArray()
PlotPoint XC, YC - 1, S, MyArray()
Exit Sub
End If
If R > 0 Then
B = R
C = 0
A = R - 1
Do
PlotPoint YC + B, XC + C, S2, MyArray()
PlotPoint YC - B, XC + C, S2, MyArray()
PlotPoint YC - B, XC - C, S2, MyArray()
PlotPoint YC + B, XC - C, S2, MyArray()
PlotPoint YC + C, XC + B, S2, MyArray()
PlotPoint YC - C, XC + B, S2, MyArray()
PlotPoint YC - C, XC - B, S2, MyArray()
PlotPoint YC + C, XC - B, S2, MyArray()
LastCode$ = "C = C + 1, etc."
C = C + 1
A = A + 1 - C - C
If A < 0 Then
B = B - 1
A = A + B + B
End If
If B < C Then Exit Do
Loop
End If
LastCode$ = ""
End Sub ' PlotCircle
' /////////////////////////////////////////////////////////////////////////////
' Circle plotting wrapper (Top-Left corner input)
Sub PlotCircleTopLeft (X As Integer, Y As Integer, R As Integer, S As String, MyArray() As String * 1)
PlotCircle X + R, Y + R, R, S, MyArray()
End Sub ' PlotCircleTopLeft
' /////////////////////////////////////////////////////////////////////////////
' Re: Is this fast enough as general circle fill?
' https://forum.qb64.org/index.php?topic=298.msg1913#msg1913
' From: SMcNeill
' Date: « Reply #30 on: June 26, 2018, 03:34:18 pm »
'
' Sometimes, computers do things that are completely counter-intuitive to us, and
' we find ourselves having to step back as programmers and simply say, "WOW!!"
' Here's a perfect example of that:
' Here we look at two different circle fill routines -- one, which I'd assume to
' be faster, which precalculates the offset needed to find the endpoints for each
' line which composes a circle, and another, which is the same old CircleFill
' program which I've shared countless times over the years with people on various
' QB64 forums.
'
' When all is said and done though, CircleFill is STILL even faster than
' CircleFillFast, which pregenerates those end-points for us!
' XC,YC = center point of circle
' R = radius
' S = char to draw
' MyArray = 2D string array to plot circle in
Sub PlotCircleFill (XC As Integer, YC As Integer, R1 As Integer, S As String, MyArray() As String * 1)
Dim RoutineName As String:: RoutineName = "PlotCircleFill": LastRoutine$ = RoutineName
Print "PlotCircleFill XC=" + _ToStr$(XC) + ", YC=" + _ToStr$(YC) + ", R1=" + _ToStr$(R1) + ", S=" + Chr$(34) + S + Chr$(34) + ", MyArray()"
Dim R As Integer
Dim RadiusError As Integer
Dim X As Integer
Dim Y As Integer
Dim iLoopX As Integer
Dim iLoopY As Integer
On Error GoTo ErrorHandler
R = Abs(R1)
RadiusError = -R
X = R
Y = 0
If R = 0 Then
'PSET (XC, YC), C
Exit Sub
ElseIf R = 1 Then
' Plot Center
PlotPoint XC, YC, S, MyArray()
' Plot 4 Axial Points
PlotPoint XC + 1, YC, S, MyArray()
PlotPoint XC - 1, YC, S, MyArray()
PlotPoint XC, YC + 1, S, MyArray()
PlotPoint XC, YC - 1, S, MyArray()
Exit Sub
End If
' Draw the middle span here so we don't draw it twice in the main loop,
' which would be a problem with blending turned on.
'LINE (XC - X, YC)-(XC + X, YC), C, BF
For iLoopX = XC - X To XC + X
PlotPoint YC, iLoopX, S, MyArray()
Next iLoopX
While X > Y
RadiusError = RadiusError + Y * 2 + 1
If RadiusError >= 0 Then
If X <> Y + 1 Then
'LINE (XC - Y, YC - X)-(XC + Y, YC - X), C, BF
iLoopY = YC - X
For iLoopX = XC - Y To XC + Y
PlotPoint iLoopY, iLoopX, S, MyArray()
Next iLoopX
'LINE (XC - Y, YC + X)-(XC + Y, YC + X), C, BF
iLoopY = YC + X
For iLoopX = XC - Y To XC + Y
PlotPoint iLoopY, iLoopX, S, MyArray()
Next iLoopX
End If
X = X - 1
RadiusError = RadiusError - X * 2
End If
Y = Y + 1
'LINE (XC - X, YC - Y)-(XC + X, YC - Y), C, BF
iLoopY = YC - Y
For iLoopX = XC - X To XC + X
PlotPoint iLoopY, iLoopX, S, MyArray()
Next iLoopX
'LINE (XC - X, YC + Y)-(XC + X, YC + Y), C, BF
iLoopY = YC + Y
For iLoopX = XC - X To XC + X
PlotPoint iLoopY, iLoopX, S, MyArray()
Next iLoopX
Wend
End Sub ' PlotCircleFill
' /////////////////////////////////////////////////////////////////////////////
' Filled Circle plotting wrapper (Top-Left corner input)
Sub PlotCircleFillTopLeft (X As Integer, Y As Integer, R As Integer, S As String, MyArray() As String * 1)
PlotCircleFill X + R, Y + R, R, S, MyArray()
End Sub ' PlotCircleFillTopLeft
' /////////////////////////////////////////////////////////////////////////////
' Based on CircleFill and PlotCircleTopLeft.
' XC,YC = top left point of circle
' R = radius
' S = char to draw
' MyArray = 2D string array to plot circle in
Sub PlotCircleFillTopLeft_v1 (XC As Integer, YC As Integer, R As Integer, S As String, MyArray() As String * 1)
Dim RoutineName As String:: RoutineName = "PlotCircleFillTopLeft": LastRoutine$ = RoutineName
Print "PlotCircleFillTopLeft XC=" + _ToStr$(XC) + ", YC=" + _ToStr$(YC) + ", R=" + _ToStr$(R) + ", S=" + Chr$(34) + S + Chr$(34) + ", MyArray()"
Dim Radius As Integer
Dim RadiusError As Integer
Dim X As Integer
Dim Y As Integer
Dim iLoopX As Integer
Dim iLoopY As Integer
ReDim arrTemp(0, 0) As String * 1
Dim DY As Integer
Dim DX As Integer
Dim W As Integer
Dim TX As Integer
Dim TY As Integer
Dim MinY As Integer
Dim MaxY As Integer
Dim MinX As Integer
Dim MaxX As Integer
On Error GoTo ErrorHandler
Radius = Abs(R)
RadiusError = -Radius
X = Radius
Y = 0
If Radius = 0 Then
'PSET (XC, YC), C
Exit Sub
End If
' Get total width
W = (Radius * 2) + 1
' Define a temp array
ReDim arrTemp(0 To W, 0 To W) As String * 1
' Get minimum X, Y of target array
MinY = LBound(MyArray, 1)
MaxY = UBound(MyArray, 1)
MinX = LBound(MyArray, 2)
MaxX = UBound(MyArray, 2)
' Draw the middle span here so we don't draw it twice in the main loop,
' which would be a problem with blending turned on.
'LINE (XC - X, YC)-(XC + X, YC), C, BF
For iLoopX = R - X To R + X
PlotPoint R, iLoopX, S, arrTemp()
Next iLoopX
While X > Y
RadiusError = RadiusError + Y * 2 + 1
If RadiusError >= 0 Then
If X <> Y + 1 Then
'LINE (XC - Y, YC - X)-(XC + Y, YC - X), C, BF
iLoopY = R - X
For iLoopX = R - Y To R + Y
PlotPoint iLoopY, iLoopX, S, arrTemp()
Next iLoopX
'LINE (XC - Y, YC + X)-(XC + Y, YC + X), C, BF
iLoopY = R + X
For iLoopX = R - Y To R + Y
PlotPoint iLoopY, iLoopX, S, arrTemp()
Next iLoopX
End If
X = X - 1
RadiusError = RadiusError - X * 2
End If
Y = Y + 1
'LINE (XC - X, YC - Y)-(XC + X, YC - Y), C, BF
iLoopY = R - Y
For iLoopX = R - X To R + X
PlotPoint iLoopY, iLoopX, S, arrTemp()
Next iLoopX
'LINE (XC - X, YC + Y)-(XC + X, YC + Y), C, BF
iLoopY = R + Y
For iLoopX = R - X To R + X
PlotPoint iLoopY, iLoopX, S, arrTemp()
Next iLoopX
Wend
' Copy circle to destination Y,X
For DY = LBound(arrTemp, 1) To UBound(arrTemp, 1)
For DX = LBound(arrTemp, 2) To UBound(arrTemp, 2)
If Len(arrTemp(DY, DX)) > 0 Then
TY = DY + YC
If TY >= MinY Then
If TY <= MaxY Then
TX = DX + XC
If TX >= MinX Then
If TX <= MaxX Then
PlotPoint TY, TX, arrTemp(DY, DX), MyArray()
End If
End If
End If
End If
End If
Next DX
Next DY
End Sub ' PlotCircleFillTopLeft
' /////////////////////////////////////////////////////////////////////////////
' Re: Is this fast enough as general circle fill?
' https://forum.qb64.org/index.php?topic=298.msg3588#msg3588
' From: bplus
' Date: « Reply #59 on: August 30, 2018, 09:18:34 am »
Sub PlotEllipse (XC As Integer, YC As Integer, xRadius As Integer, yRadius As Integer, S As String, MyArray() As String * 1)
Dim RoutineName As String:: RoutineName = "PlotEllipse": LastRoutine$ = RoutineName
Print "PlotEllipse XC=" + _ToStr$(XC) + ", YC=" + _ToStr$(YC) + ", xRadius=" + _ToStr$(xRadius) + ", yRadius=" + _ToStr$(yRadius) + ", S=" + Chr$(34) + S + Chr$(34) + ", MyArray()"
Dim scale As Single
Dim xs As Integer
Dim x As Integer
Dim y As Integer
Dim lastx As Integer
Dim lasty As Integer
Dim iLoopX As Integer
Dim iLoopY As Integer
On Error GoTo ErrorHandler
scale = yRadius / xRadius
xs = xRadius * xRadius
'PSET (XC, YC - yRadius)
PlotPoint YC - yRadius, XC, S, MyArray()
'PSET (XC, YC + yRadius)
PlotPoint YC + yRadius, XC, S, MyArray()
lastx = 0: lasty = yRadius
For x = 1 To xRadius
y = scale * Sqr(xs - x * x)
'LINE (XC + lastx, YC - lasty)-(XC + x, YC - y)
PlotLine XC + lastx, YC - lasty, XC + x, YC - y, S, MyArray()
'LINE (XC + lastx, YC + lasty)-(XC + x, YC + y)
PlotLine XC + lastx, YC + lasty, XC + x, YC + y, S, MyArray()
'LINE (XC - lastx, YC - lasty)-(XC - x, YC - y)
PlotLine XC - lastx, YC - lasty, XC - x, YC - y, S, MyArray()
'LINE (XC - lastx, YC + lasty)-(XC - x, YC + y)
PlotLine XC - lastx, YC + lasty, XC - x, YC + y, S, MyArray()
lastx = x
lasty = y
Next x
End Sub ' PlotEllipse
' /////////////////////////////////////////////////////////////////////////////
' Ellipse plotting wrapper (Top-Left corner input)
Sub PlotEllipseTopLeft (X As Integer, Y As Integer, xRadius As Integer, yRadius As Integer, S As String, MyArray() As String * 1)
PlotEllipse X + xRadius, Y + yRadius, xRadius, yRadius, S, MyArray()
End Sub ' PlotEllipseTopLeft
' /////////////////////////////////////////////////////////////////////////////
' Re: Is this fast enough as general circle fill?
' https://forum.qb64.org/index.php?topic=298.msg3588#msg3588
' From: bplus
' Date: « Reply #59 on: August 30, 2018, 09:18:34 am »
'
' Here is my ellipse and filled ellipse routines, no where near
' Steve's level of performance. The speed is cut in half at
' least because you probably have to do a whole quadrants worth
' of calculations (ellipse not as symmetric as circle).
'
' But I am sure this code can be optimized more than it is:
Sub PlotEllipseFill (XC As Integer, YC As Integer, xRadius As Integer, yRadius As Integer, S As String, MyArray() As String * 1)
Dim RoutineName As String:: RoutineName = "PlotEllipseFill": LastRoutine$ = RoutineName
Print "PlotEllipseFill XC=" + _ToStr$(XC) + ", YC=" + _ToStr$(YC) + ", xRadius=" + _ToStr$(xRadius) + ", yRadius=" + _ToStr$(yRadius) + ", S=" + Chr$(34) + S + Chr$(34) + ", MyArray()"
Dim scale As Single
Dim x As Integer
Dim y As Integer
Dim iLoopX As Integer
Dim iLoopY As Integer
On Error GoTo ErrorHandler
scale = yRadius / xRadius
'LINE (XC, YC - yRadius)-(XC, YC + yRadius), , BF
For iLoopY = YC - yRadius To YC + yRadius
PlotPoint iLoopY, XC, S, MyArray()
Next iLoopY
For x = 1 To xRadius
y = scale * Sqr(xRadius * xRadius - x * x)
'LINE (XC + x, YC - y)-(XC + x, YC + y), , BF
iLoopX = XC + x
For iLoopY = YC - y To YC + y
PlotPoint iLoopY, iLoopX, S, MyArray()
Next iLoopY
'LINE (XC - x, YC - y)-(XC - x, YC + y), , BF
iLoopX = XC - x
For iLoopY = YC - y To YC + y
PlotPoint iLoopY, iLoopX, S, MyArray()
Next iLoopY
Next x
End Sub ' PlotEllipseFill
' /////////////////////////////////////////////////////////////////////////////
' Filled Ellipse plotting wrapper (Top-Left corner input)
Sub PlotEllipseFillTopLeft (X As Integer, Y As Integer, xRadius As Integer, yRadius As Integer, S As String, MyArray() As String * 1)
PlotEllipseFill X + xRadius, Y + yRadius, xRadius, yRadius, S, MyArray()
End Sub ' PlotEllipseFillTopLeft
' /////////////////////////////////////////////////////////////////////////////
' Based on "BRESNHAM.BAS" by Kurt Kuzba. (4/16/96)
' From: http://www.thedubber.altervista.org/qbsrc.htm
' PlotLine x1, y1, x2, y2, S, MyArray()
Sub PlotLine (x1 As Integer, y1 As Integer, x2 As Integer, y2 As Integer, S As String, MyArray() As String * 1)
Dim RoutineName As String:: RoutineName = "PlotLine": LastRoutine$ = RoutineName
Print "PlotLine x1=" + _ToStr$(x1) + ", y1=" + _ToStr$(y1) + ", x2=" + _ToStr$(x2) + ", y2=" + _ToStr$(y2) + ", S=" + Chr$(34) + S + Chr$(34) + ", MyArray()"
Dim iLoop As Integer
Dim steep As Integer: steep = 0
Dim ev As Integer: ev = 0
Dim sx As Integer
Dim sy As Integer
Dim dx As Integer
Dim dy As Integer
On Error GoTo ErrorHandler
If (x2 - x1) > 0 Then
sx = 1
Else
sx = -1
End If
dx = Abs(x2 - x1)
If (y2 - y1) > 0 Then
sy = 1
Else
sy = -1
End If
dy = Abs(y2 - y1)
If (dy > dx) Then
steep = 1
Swap x1, y1
Swap dx, dy
Swap sx, sy
End If
ev = 2 * dy - dx
For iLoop = 0 To dx - 1
If steep = 1 Then
' SPECIAL CASE: x/y are reversed
''PSET (y1, x1), c:
'LOCATE y1, x1 : PRINT S;
PlotPoint x1, y1, S, MyArray()
Else
''PSET (x1, y1), c
'LOCATE x1, y1: PRINT S;
PlotPoint y1, x1, S, MyArray()
End If
While ev >= 0
y1 = y1 + sy
ev = ev - 2 * dx
Wend
x1 = x1 + sx
ev = ev + 2 * dy
Next iLoop
' Ensure the final endpoint is always plotted
''PSET (x2, y2), c
'LOCATE x2, y2: PRINT S;
PlotPoint y2, x2, S, MyArray()
End Sub ' PlotLine
' /////////////////////////////////////////////////////////////////////////////
Sub PlotPoint (Y As Integer, X As Integer, S As String, MyArray() As String * 1)
if Y >= LBound(MyArray, 1) _
_ANDALSO Y <= UBound(MyArray, 1) _
_ANDALSO X >= LBound(MyArray, 2) _
_ANDALSO X <= UBound(MyArray, 2) _
then
MyArray(Y, X) = S
End If
End Sub ' PlotPoint
' /////////////////////////////////////////////////////////////////////////////
' Based on PlotCircle.
' XC,YC = center point of circle
' R = radius
' Q = which quarter of the circle to return
' where 1=top right, 2=bottom right, 3=bottom left, 4=top left
' S = char to draw
' MyArray = 2D string array to plot circle in
Sub PlotSemiCircle (XC As Integer, YC As Integer, R As Integer, Q As Integer, S As String, MyArray() As String * 1)
Dim RoutineName As String:: RoutineName = "PlotSemiCircle": LastRoutine$ = RoutineName
Print "PlotSemiCircle XC=" + _ToStr$(XC) + ", YC=" + _ToStr$(YC) + ", R=" + _ToStr$(R) + ", Q=" + _ToStr$(Q) + ", S=" + Chr$(34) + S + Chr$(34) + ", MyArray()"
Dim A As Integer
Dim B As Integer
Dim C As Integer
Dim S2 As String
On Error GoTo ErrorHandler
If Len(S) = 1 Then
S2 = S
Else
If Len(S) = 0 Then
S2 = " "
Else
S2 = Left$(S, 1)
End If
End If
If R = 1 Then
Select Case Q
Case 1: ' Top Right
PlotPoint XC + 1, YC, S, MyArray()
PlotPoint XC, YC - 1, S, MyArray()
Case 2: ' Bottom Right
PlotPoint XC + 1, YC, S, MyArray()
PlotPoint XC, YC + 1, S, MyArray()
Case 3: ' Bottom Left
PlotPoint XC - 1, YC, S, MyArray()
PlotPoint XC, YC + 1, S, MyArray()
Case 4: ' Top Left
PlotPoint XC - 1, YC, S, MyArray()
PlotPoint XC, YC - 1, S, MyArray()
End Select
Exit Sub
ElseIf R > 0 Then
B = R
C = 0
A = R - 1
Do
' Select quadrant
Select Case Q
Case 1 ' Top-Right
PlotPoint YC - B, XC + C, S2, MyArray()
PlotPoint YC - C, XC + B, S2, MyArray()
Case 2 ' Bottom-Right
PlotPoint YC + B, XC + C, S2, MyArray()
PlotPoint YC + C, XC + B, S2, MyArray()
Case 3 ' Bottom-Left
PlotPoint YC + B, XC - C, S2, MyArray()
PlotPoint YC + C, XC - B, S2, MyArray()
Case 4 ' Top-Left
PlotPoint YC - B, XC - C, S2, MyArray()
PlotPoint YC - C, XC - B, S2, MyArray()
End Select
LastCode$ = "C = C + 1, etc."
C = C + 1
A = A + 1 - C - C
If A < 0 Then ' IF A>=0 THEN 190
B = B - 1
A = A + B + B
End If
If B < C Then Exit Do ' 190 IF B>=C THEN 60
Loop
End If
LastCode$ = ""
End Sub ' PlotSemiCircle
' /////////////////////////////////////////////////////////////////////////////
' Semi-Circle plotting wrapper (Top-Left corner input)
' X,Y = top left point of circle
' R = radius
' Q = which quarter of the circle to return
' where 1=top right, 2=bottom right, 3=bottom left, 4=top left
' like this:
' .......4444111.......
' .....44.......11.....
' ....4...........1....
' ...4.............1...
' ..4...............1..
' .4.................1.
' .4.................1.
' 4...................1
' 4...................1
' 4...................1
' 3...................1
' 3...................2
' 3...................2
' 3...................2
' .3.................2.
' .3.................2.
' ..3...............2..
' ...3.............2...
' ....3...........2....
' .....33.......22.....
' .......3333222.......
' S = char to draw
' MyArray = 2D string array to plot circle in
Sub PlotSemicircleTopLeft (X As Integer, Y As Integer, R As Integer, Q As Integer, S As String, MyArray() As String * 1)
PlotSemiCircle X + R, Y + R, R, Q, S, MyArray()
End Sub ' PlotSemicircleTopLeft
' /////////////////////////////////////////////////////////////////////////////
' Based on CircleFill and PlotSemiCircle
' XC,YC = top left point of circle
' R = radius
' Q = which quarter of the circle to return semicircle from
' where 1=top right, 2=bottom right, 3=bottom left, 4=top left
' like this:
' .......4444111.......
' .....44444411111.....
' ....4444444111111....
' ...444444441111111...
' ..44444444411111111..
' .4444444444111111111.
' .4444444444111111111.
' 444444444441111111111
' 444444444441111111111
' 444444444441111111111
' 333333333331111111111
' 333333333332222222222
' 333333333332222222222
' 333333333332222222222
' .3333333333222222222.
' .3333333333222222222.
' ..33333333322222222..
' ...333333332222222...
' ....3333333222222....
' .....33333322222.....
' .......3333222.......
' S = char to draw
' MyArray = 2D string array to plot semicircle in
Sub PlotSemiCircleFill (XC As Integer, YC As Integer, R As Integer, Q As Integer, S As String, MyArray() As String * 1)
Dim RoutineName As String:: RoutineName = "PlotSemiCircleFill": LastRoutine$ = RoutineName
Print "PlotSemiCircleFill XC=" + _ToStr$(XC) + ", YC=" + _ToStr$(YC) + ", R=" + _ToStr$(R) + ", Q=" + _ToStr$(Q) + ", S=" + Chr$(34) + S + Chr$(34) + ", MyArray()"
Dim Radius As Integer
Dim RadiusError As Integer
Dim X As Integer
Dim Y As Integer
Dim iLoopX As Integer
Dim iLoopY As Integer
ReDim arrTemp(0, 0) As String * 1
Dim DY As Integer
Dim DX As Integer
Dim W As Integer
Dim TX As Integer
Dim TY As Integer
Dim MinY As Integer
Dim MaxY As Integer
Dim MinX As Integer
Dim MaxX As Integer
On Error GoTo ErrorHandler
Radius = Abs(R)
RadiusError = -Radius
X = Radius
Y = 0
If Radius = 0 Then
'PSET (XC, YC), C
Exit Sub
End If
' Get total width
W = (Radius * 2) + 1
' Define a temp array
ReDim arrTemp(0 To W, 0 To W) As String * 1
' Get minimum X, Y of target array
MinY = LBound(MyArray, 1)
MaxY = UBound(MyArray, 1)
MinX = LBound(MyArray, 2)
MaxX = UBound(MyArray, 2)
' Draw the middle span here so we don't draw it twice in the main loop,
' which would be a problem with blending turned on.
'LINE (XC - X, YC)-(XC + X, YC), C, BF
For iLoopX = R - X To R + X
PlotPoint R, iLoopX, S, arrTemp()
Next iLoopX
While X > Y
RadiusError = RadiusError + Y * 2 + 1
If RadiusError >= 0 Then
If X <> Y + 1 Then
'LINE (XC - Y, YC - X)-(XC + Y, YC - X), C, BF
iLoopY = R - X
For iLoopX = R - Y To R + Y
PlotPoint iLoopY, iLoopX, S, arrTemp()
Next iLoopX
'LINE (XC - Y, YC + X)-(XC + Y, YC + X), C, BF
iLoopY = R + X
For iLoopX = R - Y To R + Y
PlotPoint iLoopY, iLoopX, S, arrTemp()
Next iLoopX
End If
X = X - 1
RadiusError = RadiusError - X * 2
End If
Y = Y + 1
'LINE (XC - X, YC - Y)-(XC + X, YC - Y), C, BF
iLoopY = R - Y
For iLoopX = R - X To R + X
PlotPoint iLoopY, iLoopX, S, arrTemp()
Next iLoopX
'LINE (XC - X, YC + Y)-(XC + X, YC + Y), C, BF
iLoopY = R + Y
For iLoopX = R - X To R + X
PlotPoint iLoopY, iLoopX, S, arrTemp()
Next iLoopX
Wend
' Copy semicircle to destination Y,X
' JUST COPY SELECTED QUADRANT:
Select Case Q
Case 1:
' quadrant #1 (Top-Right)
For DY = 0 To Radius
For DX = Radius To W
If Len(arrTemp(DY, DX)) > 0 Then
TY = YC + (DY - Radius)
TX = XC + (DX - Radius)
If TY >= MinY And TY <= MaxY And TX >= MinX And TX <= MaxX Then
PlotPoint TY, TX, arrTemp(DY, DX), MyArray()
End If
End If
Next DX
Next DY
Case 2:
' quadrant #2 (Bottom-Right)
For DY = Radius To W
For DX = Radius To W
If Len(arrTemp(DY, DX)) > 0 Then
TY = YC + (DY - Radius)
TX = XC + (DX - Radius)
If TY >= MinY And TY <= MaxY And TX >= MinX And TX <= MaxX Then
PlotPoint TY, TX, arrTemp(DY, DX), MyArray()
End If
End If
Next DX
Next DY
Case 3:
' quadrant #3 (Bottom-Left)
For DY = Radius To W
For DX = 0 To Radius
If Len(arrTemp(DY, DX)) > 0 Then
TY = YC + (DY - Radius)
TX = XC + (DX - Radius)
If TY >= MinY And TY <= MaxY And TX >= MinX And TX <= MaxX Then
PlotPoint TY, TX, arrTemp(DY, DX), MyArray()
End If
End If
Next DX
Next DY
Case 4:
' quadrant #4 (Top-Left)
For DY = 0 To Radius
For DX = 0 To Radius
If Len(arrTemp(DY, DX)) > 0 Then
TY = YC + (DY - Radius)
TX = XC + (DX - Radius)
If TY >= MinY And TY <= MaxY And TX >= MinX And TX <= MaxX Then
PlotPoint TY, TX, arrTemp(DY, DX), MyArray()
End If
End If
Next DX
Next DY
Case Else:
' (DO NOTHING)
End Select
End Sub ' PlotSemiCircleFill
' /////////////////////////////////////////////////////////////////////////////
' Filled Semi-Circle plotting wrapper (Top-Left corner input)
Sub PlotSemiCircleFillTopLeft (X As Integer, Y As Integer, R As Integer, Q As Integer, S As String, MyArray() As String * 1)
PlotSemiCircleFill X + R, Y + R, R, Q, S, MyArray()
End Sub ' PlotSemiCircleFillTopLeft
' /////////////////////////////////////////////////////////////////////////////
Sub PlotSquare (X1 As Integer, Y1 As Integer, L As Integer, S As String, MyArray() As String * 1)
Dim RoutineName As String:: RoutineName = "PlotSquare": LastRoutine$ = RoutineName
Print "PlotSquare X1=" + _ToStr$(X1) + ", Y1=" + _ToStr$(Y1) + ", L=" + _ToStr$(L) + ", S=" + Chr$(34) + S + Chr$(34) + ", MyArray()"
Dim X As Integer
Dim X2 As Integer
Dim Y As Integer
Dim Y2 As Integer
Dim S2 As String
On Error GoTo ErrorHandler
If Len(S) = 1 Then
S2 = S
Else
If Len(S) = 0 Then
S2 = " "
Else
S2 = Left$(S, 1)
End If
End If
X2 = (X1 + L) - 1
Y2 = (Y1 + L) - 1
For X = X1 To X2
For Y = Y1 To Y2
PlotPoint Y, X, S2, MyArray()
Next Y
Next X
End Sub ' PlotSquare
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' END 2D SHAPE PLOTTING FUNCTIONS
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' BEGIN GENERAL PURPOSE UTILITY ROUTINES #GEN
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' /////////////////////////////////////////////////////////////////////////////
' Returns _TRUE if number n is even
' https://slaystudy.com/qbasic-program-to-check-if-number-is-even-or-odd/
' see also: IsOdd%
Function IsEven% (n)
If n Mod 2 = 0 Then
IsEven% = _TRUE
Else
IsEven% = _FALSE
End If
End Function ' IsEven%
' /////////////////////////////////////////////////////////////////////////////
' Returns _TRUE if number n is odd
' https://slaystudy.com/qbasic-program-to-check-if-number-is-even-or-odd/
' see also: IsEven%
Function IsOdd% (n)
If n Mod 2 = 1 Then
IsOdd% = _TRUE
Else
IsOdd% = _FALSE
End If
End Function ' IsOdd%
' /////////////////////////////////////////////////////////////////////////////
Function PadLeft$ (sValue As String, iWidth As Integer)
PadLeft$ = Right$(String$(iWidth, " ") + sValue, iWidth)
End Function ' PadLeft$
' /////////////////////////////////////////////////////////////////////////////
Function PadRight$ (sValue As String, iWidth As Integer)
PadRight$ = Left$(sValue + String$(iWidth, " "), iWidth)
End Function ' PadRight$
' /////////////////////////////////////////////////////////////////////////////
Function RandomLong& (Min1&, Max1&)
Dim NumSpread As _Unsigned Long
Dim Min2&, Max2&
'THIS DOESN'T WORK:
'NumSpread = (Max1& - Min&) + 1
'BUT THIS DOES:
If Min1& > Max1& Then
Min2& = Max1&
Max2& = Min1&
Else
Min2& = Min1&
Max2& = Max1&
End If
If Min2& < 0 And Max2& > 0 Then
NumSpread = (Max2& + Abs(Min2&)) + 1
ElseIf Min2& < 0 And Max2& < 0 Then
NumSpread = Max2& + Abs(Min2&) + 1
ElseIf Min2& > 0 And Max2& > 0 Then
NumSpread = (Max2& - Min2&) + 1
ElseIf Min2& = 0 And Max2& > 0 Then
NumSpread = Max2&
ElseIf Min2& = 0 And Max2& = 0 Then
NumSpread = 0
End If
' GET RANDOM # BETWEEN Min2& AND Max2&
RandomLong& = Int(Rnd * NumSpread) + Min2&
End Function ' RandomLong&
' /////////////////////////////////////////////////////////////////////////////
' Generate random value between Min and Max inclusive.
Function RandomNumber% (Min%, Max%)
Dim NumSpread%
' SET RANDOM SEED
Randomize Timer
NumSpread% = (Max% - Min%) + 1
RandomNumber% = Int(Rnd * NumSpread%) + Min% ' GET RANDOM # BETWEEN Max% AND Min%
End Function ' RandomNumber%
' /////////////////////////////////////////////////////////////////////////////
' FROM: String Manipulation
' found at abandoned, outdated and now likely malicious qb64 dot net website
' http://www.qb64.[net]/forum/index_topic_5964-0/
'
'SUMMARY:
' Purpose: A library of custom functions that transform strings.
' Author: Dustinian Camburides (dustinian@gmail.com)
' Platform: QB64 (www.qb64.org)
' Revision: 1.6
' Updated: 5/28/2012
'SUMMARY:
'[Replace$] replaces all instances of the [Find] sub-string with the [Add] sub-string within the [Text] string.
'INPUT:
'Text: The input string; the text that's being manipulated.
'Find: The specified sub-string; the string sought within the [Text] string.
'Add: The sub-string that's being added to the [Text] string.
Function Replace$ (Text1 As String, Find1 As String, Add1 As String)
' VARIABLES:
Dim Text2 As String
Dim Find2 As String
Dim Add2 As String
Dim lngLocation As Long ' The address of the [Find] substring within the [Text] string.
Dim strBefore As String ' The characters before the string to be replaced.
Dim strAfter As String ' The characters after the string to be replaced.
' INITIALIZE:
' MAKE COPIESSO THE ORIGINAL IS NOT MODIFIED (LIKE ByVal IN VBA)
Text2 = Text1
Find2 = Find1
Add2 = Add1
lngLocation = InStr(1, Text2, Find2)
' PROCESSING:
' While [Find2] appears in [Text2]...
While lngLocation
' Extract all Text2 before the [Find2] substring:
strBefore = Left$(Text2, lngLocation - 1)
' Extract all text after the [Find2] substring:
strAfter = Right$(Text2, ((Len(Text2) - (lngLocation + Len(Find2) - 1))))
' Return the substring:
Text2 = strBefore + Add2 + strAfter
' Locate the next instance of [Find2]:
lngLocation = InStr(1, Text2, Find2)
' Next instance of [Find2]...
Wend
' OUTPUT:
Replace$ = Text2
End Function ' Replace$
' /////////////////////////////////////////////////////////////////////////////
Function TrueFalse$ (MyValue%)
TrueFalse$ = _IIf(MyValue% = _TRUE, "_TRUE", "_FALSE")
End Function ' TrueFalse$
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' END GENERAL PURPOSE UTILITY ROUTINES @GEN
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

![[Image: qb64pe-lazy-error-message-code-generator.png]](https://i.ibb.co/XZLB3zC8/qb64pe-lazy-error-message-code-generator.png)