Another step forward in making our first version "1.0" as the new team working on QB64. This release (version 0.5) now:
Has swapped out the mingw compilers to updated versions for Windows users.
Reduced the size of the repo considerably for those who wish to download direct and setup QB64 manually, for whatever reason.
Prepacked Linux and max versions of QB64, which come in at less than 10MB each now.
We've swapped out all the references to the now defunct .net and .org sites that we could find, and replaced them to proper, working links which now connect to our new wiki, forum, and all at qb64phoenix.com.
$Color:0 and $Color:32 has now been tweaked to work with $NoPrefix. Color names will remain the same in all cases, if $Color is used without $NoPrefix. When $Color is used in conjunction with $NoPrefix, the colors of Red, Green, and Blue which would normally conflict with the now underscoreless commands of _Red, _Green, _Blue, have been altered to have NP_appended to them (for No Prefix). Example: Color NP_Red, Orange for a red on orange color.
Click on the big title above to go directly to the release page and grab yourself a copy of the latest version for all your QB64 needs!
Here's a little something I wrote and posted on FidoNet back in 1997. It's just an illustration of some of the styles of line that you can have when you use the LINE command. If nothing else grab one or more of the included constants at the top of the code. When run you will get a small window that shows the linestyles (maybe too small for anything larger than full HD).
Code: (Select All)
'===========================================================================
' Subject: DIFFERENT LINE STYLES Date: 12-22-97 (12:06)
' Author: TarotRedhand Code: QB
'===========================================================================
'Just for a change I am posting a small program that illustrates what
'is probably an underused parameter of a well known command, LINE. If
'you check out either the manual or the help system, you will see that
'the final (optional) parameter that can be passed to the LINE
'statement is one called linestyle. In order to show what this
'parameter can produce when properly used here are 13 (12a? <g>)
'constants, for you to use, that are part of the following small
'program.
This is a dynamic array that resizes itself as you add to or remove from it.
each entry has 2 properties: whichType and Content.
whichType tells what kind of variable is stored, and Content is what the variable contains.
whichType is a _byte and content is always a string. variables are converted to/from strings by the subs/functions.
here is the code, maybe it might be useful:
Code: (Select All)
Option _Explicit
Type Limits
Minimum As _Byte
Maximum As _Unsigned _Integer64
Current As _Unsigned _Integer64
End Type
Type Entry 'global array
whichType As _Byte
Content As String
End Type
Dim Shared theLimit As Limits
ReDim Shared theBase(theLimit.Minimum) As Entry
'
theLimit.Minimum = 0
theLimit.Maximum = 0 - 1
'
theLimit.Current = theLimit.Minimum
' End Declarations
Dim test1%%
Dim test2&&
Dim test3~&&
Dim test4##
Dim test5$
Function trim$ (theInput As String)
trim = LTrim$(RTrim$(theInput))
End Function
Sub add_byte (theInput As _Byte)
add_Item
theBase(theLimit.Current).Content = trim$(Chr$(theInput))
theBase(theLimit.Current).whichType = 1
End Sub
Sub add_int (theInput As _Integer64)
add_Item
theBase(theLimit.Current).Content = trim$(_MK$(_Integer64, theInput))
theBase(theLimit.Current).whichType = 2
End Sub
Sub add_uint (theInput As _Unsigned _Integer64)
add_Item
theBase(theLimit.Current).Content = trim$(_MK$(_Unsigned _Integer64, theInput))
theBase(theLimit.Current).whichType = 3
End Sub
Sub add_float (theInput As _Float)
add_Item
theBase(theLimit.Current).Content = trim$(_MK$(_Float, theInput))
theBase(theLimit.Current).whichType = 5
End Sub
Sub add_str (theInput As String)
add_Item
theBase(theLimit.Current).Content = trim$(theInput)
theBase(theLimit.Current).whichType = 7
End Sub
Sub add_Item
theLimit.Current = theLimit.Current + 1
ReDim _Preserve theBase(theLimit.Current) As Entry
End Sub
Function get_byte%% (Selector As _Unsigned _Integer64)
get_byte = Asc(theBase(Selector).Content)
End Function
Function get_int&& (Selector As _Unsigned _Integer64)
get_int = _CV(_Integer64, theBase(Selector).Content)
End Function
Function get_uint~&& (Selector As _Unsigned _Integer64)
get_uint = _CV(_Unsigned _Integer64, theBase(Selector).Content)
End Function
Function get_float## (Selector As _Unsigned _Integer64)
get_float = _CV(_Float, theBase(Selector).Content)
End Function
Function get_str$ (Selector As _Unsigned _Integer64)
get_str = trim$(theBase(Selector).Content)
End Function
Sub rm_byte (Selector As _Unsigned _Integer64)
theBase(Selector).whichType = 0
theBase(Selector).Content = ""
Dim rm_global_B_inc
For rm_global_B_inc = Selector To theLimit.Current - 1
theBase(rm_global_B_inc).whichType = theBase(rm_global_B_inc + 1).whichType
theBase(rm_global_B_inc).Content = theBase(rm_global_B_inc + 1).Content
Next rm_global_B_inc
rm_Item
End Sub
Sub rm_int (Selector As _Unsigned _Integer64)
theBase(Selector).whichType = 0
theBase(Selector).Content = ""
Dim rm_global_I_inc
For rm_global_I_inc = Selector To theLimit.Current - 1
theBase(rm_global_I_inc).whichType = theBase(rm_global_I_inc + 1).whichType
theBase(rm_global_I_inc).Content = theBase(rm_global_I_inc + 1).Content
Next rm_global_I_inc
rm_Item
End Sub
Sub rm_uint (Selector As _Unsigned _Integer64)
theBase(Selector).whichType = 0
theBase(Selector).Content = ""
Dim rm_global_UI_inc
For rm_global_UI_inc = Selector To theLimit.Current - 1
theBase(rm_global_UI_inc).whichType = theBase(rm_global_UI_inc + 1).whichType
theBase(rm_global_UI_inc).Content = theBase(rm_global_UI_inc + 1).Content
Next rm_global_UI_inc
rm_Item
End Sub
Sub rm_float (Selector As _Unsigned _Integer64)
theBase(Selector).whichType = 0
theBase(Selector).Content = ""
Dim rm_global_F_inc
For rm_global_F_inc = Selector To theLimit.Current - 1
theBase(rm_global_F_inc).whichType = theBase(rm_global_F_inc + 1).whichType
theBase(rm_global_F_inc).Content = theBase(rm_global_F_inc + 1).Content
Next rm_global_F_inc
rm_Item
End Sub
Sub rm_str (Selector As _Unsigned _Integer64)
theBase(Selector).whichType = 0
theBase(Selector).Content = ""
Dim rm_global_S_inc
For rm_global_S_inc = Selector To theLimit.Current - 1
theBase(rm_global_S_inc).whichType = theBase(rm_global_S_inc + 1).whichType
theBase(rm_global_S_inc).Content = theBase(rm_global_S_inc + 1).Content
Next rm_global_S_inc
rm_Item
End Sub
Sub rm_Item
theLimit.Current = theLimit.Current - 1
ReDim _Preserve theBase(theLimit.Current) As Entry
End Sub
Brief = 0
PRINT "NON-BRIEF OUTPUT:"
PRINT "'6s; 4d6 kh3' -- Roll 6 sets of 4 six-sided dice, keep the three highest"
PRINT DiceRoll$
PRINT
PRINT "PRESS <ANY KEY> TO CONTINUE"
SLEEP
PRINT
Brief = 1
PRINT "SEMI-BRIEF OUTPUT:"
PRINT "'6s; 4d6 kh3' -- Roll 6 sets of 4 six-sided dice, keep the three highest"
PRINT DiceRoll$
PRINT
PRINT "PRESS <ANY KEY> TO CONTINUE"
SLEEP
PRINT
Brief = 2
PRINT "MOST BRIEF OUTPUT:"
PRINT "'6s; 4d6 kh3' -- Roll 6 sets of 4 six-sided dice, keep the three highest"
PRINT DiceRoll$
PRINT
PRINT "PRESS <ANY KEY> TO CONTINUE"
SLEEP
PRINT
TYPE DiceRoller_Type
Set AS LONG
SetMod AS LONG
SetReRoll AS STRING * 100
SetOpenRoll AS STRING * 100
SetKeepHigh AS LONG
SetKeepLow AS LONG
SetDiscardHigh AS LONG
SetDiscardLow AS LONG
NumberOfDice AS LONG
DiceSides AS LONG
DiceMod AS LONG
DiceReroll AS STRING * 100
DiceOpenRoll AS STRING * 100
DiceKeepHigh AS LONG
DiceKeepLow AS LONG
DiceDiscardHigh AS LONG
DiceDiscardLow AS LONG
TotalMod AS LONG
END TYPE
SUB StripNumber (m$)
v = VAL(m$)
DO UNTIL v = 0
'PRINT "Stripping number"; m$
m$ = MID$(m$, 2)
v = VAL(m$)
LOOP
DO UNTIL LEFT$(m$, 1) <> "0" 'strip any zeros
m$ = MID$(m$, 2)
LOOP
END SUB
FUNCTION DiceRoll$
SHARED Brief AS LONG
SHARED DiceToRoll AS DiceRoller_Type
IF DiceToRoll.DiceKeepHigh OR DiceToRoll.DiceKeepLow THEN
IF DiceToRoll.DiceDiscardHigh OR DiceToRoll.DiceDiscardLow THEN DiceRoll$ = "Error - Can not keep and discard at the same time.": EXIT FUNCTION
END IF
IF DiceToRoll.NumberOfDice < 1 THEN DiceRoll$ = "Error - No dice to roll!": EXIT FUNCTION
RANDOMIZE TIMER
SHARED DiceToRoll AS DiceRoller_Type
REDIM rolls(0) AS LONG
REDIM SetRolls(0) AS LONG
SetCount = 0
IF Brief = 2 THEN out$ = "("
FOR j = 1 TO DiceToRoll.Set
ReRollSet:
SetTotal = 0
IF Brief = 0 THEN
out$ = out$ + "RAW: ("
ELSEIF Brief = 1 THEN
out$ = out$ + "("
END IF
rollcount = -1
FOR i = 1 TO DiceToRoll.NumberOfDice
ReRollDice:
roll = INT(RND(1) * DiceToRoll.DiceSides) + 1
IF ParseDiceOption(roll, DiceToRoll.DiceReroll) THEN
DiceOK = 0
IF Brief = 0 THEN out$ = out$ + "r" + _TRIM$(STR$(roll)) + ", "
GOTO ReRollDice
END IF
IF ParseDiceOption(roll, DiceToRoll.DiceOpenRoll) THEN
DiceOK = 0
DiceTotal = DiceTotal + roll + DiceToRoll.DiceMod
IF Brief = 0 THEN
out$ = out$ + _TRIM$(STR$(roll)) + "o"
IF DiceToRoll.DiceMod THEN out$ = out$ + " + " + _TRIM$(STR$(DiceToRoll.DiceMod))
out$ = out$ + ","
END IF
rollcount = rollcount + 1
REDIM _PRESERVE rolls(rollcount) AS LONG 'make certain we dont get out of bound errors for crazy reroll scenarios
rolls(rollcount) = roll + DiceToRoll.DiceMod
GOTO ReRollDice
END IF
rollcount = rollcount + 1
REDIM _PRESERVE rolls(rollcount) AS LONG 'make certain we dont get out of bound errors for crazy reroll scenarios
rolls(rollcount) = roll + DiceToRoll.DiceMod
DiceTotal = DiceTotal + roll + DiceToRoll.DiceMod
IF Brief = 0 THEN
out$ = out$ + _TRIM$(STR$(roll))
IF DiceToRoll.DiceMod THEN out$ = out$ + " + " + _TRIM$(STR$(DiceToRoll.DiceMod))
IF i < DiceToRoll.NumberOfDice THEN 'more dice to roll in this set
out$ = out$ + ", "
ELSE 'we're finished
out$ = out$ + ")"
END IF
END IF
NEXT
IF rollcount > 0 THEN Sort rolls() 'No need to try and sort only 1 dice.
IF Brief = 0 THEN
out$ = out$ + "; SORTED: ("
FOR i = 0 TO rollcount
out$ = out$ + _TRIM$(STR$(rolls(i)))
IF i < rollcount THEN out$ = out$ + ", " ELSE out$ = out$ + ")"
NEXT
END IF
REDIM keep(rollcount) AS LONG
IF DiceToRoll.DiceKeepHigh OR DiceToRoll.DiceKeepLow THEN
IF DiceToRoll.DiceKeepHigh THEN
FOR i = DiceToRoll.DiceKeepHigh - 1 TO 0 STEP -1
IF i < rollcount THEN keep(rollcount - i) = -1
NEXT
END IF
IF DiceToRoll.DiceKeepLow THEN
FOR i = 0 TO DiceToRoll.DiceKeepLow - 1
IF i < rollcount THEN keep(i) = -1
NEXT
END IF
ELSEIF DiceToRoll.DiceDiscardHigh OR DiceToRoll.DiceDiscardLow THEN
FOR i = 0 TO rollcount
keep(i) = -1
NEXT
IF DiceToRoll.DiceDiscardHigh THEN
FOR i = DiceToRoll.DiceDiscardHigh - 1 TO 0 STEP -1
IF i < rollcount THEN keep(rollcount - i) = 0
NEXT
END IF
IF DiceToRoll.DiceDiscardLow THEN
FOR i = 0 TO DiceToRoll.DiceDiscardLow - 1
IF i < rollcount THEN keep(i) = 0
NEXT
END IF
ELSE
FOR i = 0 TO rollcount
keep(i) = -1
NEXT
END IF
IF Brief = 0 THEN out$ = out$ + "; KEEP: ("
KeepTotal = 0
kept = 0
FOR i = 0 TO rollcount
IF keep(i) THEN
kept = kept + 1
IF Brief < 2 THEN
IF kept > 1 THEN out$ = out$ + ", "
out$ = out$ + _TRIM$(STR$(rolls(i)))
END IF
KeepTotal = KeepTotal + rolls(i)
END IF
NEXT
IF Brief < 2 THEN out$ = out$ + ") = " + _TRIM$(STR$(KeepTotal))
IF ParseDiceOption(KeepTotal, DiceToRoll.SetReRoll) THEN
IF Brief < 2 THEN out$ = out$ + "r" + CHR$(13)
GOTO ReRollSet
END IF
IF ParseDiceOption(KeepTotal, DiceToRoll.SetOpenRoll) THEN
SetTotal = SetTotal + KeepTotal + DiceToRoll.SetMod
SetCount = SetCount + 1
REDIM _PRESERVE SetRolls(SetCount) AS LONG
SetRolls(SetCount) = SetTotal
GrandTotal = GrandTotal + SetTotal
IF Brief = 2 THEN out$ = out$ + _TRIM$(STR$(SetTotal))
out$ = out$ + "o"
IF Brief < 2 THEN
IF DiceToRoll.SetMod THEN out$ = out$ + " + " + _TRIM$(STR$(DiceToRoll.SetMod))
out$ = out$ + " = " + _TRIM$(STR$(SetTotal))
out$ = out$ + CHR$(13)
ELSE
out$ = out$ + ", "
END IF
Sort SetRolls()
IF Brief = 0 THEN
out$ = out$ + CHR$(13) + CHR$(13) + "Sorted Set: ("
FOR i = 1 TO SetCount
out$ = out$ + _TRIM$(STR$(SetRolls(i)))
IF i < SetCount THEN out$ = out$ + ", " ELSE out$ = out$ + ")"
NEXT
END IF
REDIM keep(SetCount) AS LONG
IF DiceToRoll.SetKeepHigh OR DiceToRoll.SetKeepLow THEN
IF DiceToRoll.SetKeepHigh THEN
FOR i = DiceToRoll.SetKeepHigh - 1 TO 0 STEP -1
IF i < SetCount THEN keep(SetCount - i) = -1
NEXT
END IF
IF DiceToRoll.SetKeepLow THEN
FOR i = 0 TO DiceToRoll.SetKeepLow - 1
IF i < SetCount THEN keep(i) = -1
NEXT
END IF
ELSEIF DiceToRoll.SetDiscardHigh OR DiceToRoll.SetDiscardLow THEN
FOR i = 0 TO SetCount
keep(i) = -1
NEXT
IF DiceToRoll.SetDiscardHigh THEN
FOR i = DiceToRoll.SetDiscardHigh - 1 TO 0 STEP -1
IF i < SetCount THEN keep(SetCount - i) = 0
NEXT
END IF
IF DiceToRoll.SetDiscardLow THEN
FOR i = 0 TO DiceToRoll.SetDiscardLow - 1
IF i < SetCount THEN keep(i) = 0
NEXT
END IF
ELSE
FOR i = 0 TO SetCount
keep(i) = -1
NEXT
END IF
out$ = out$ + CHR$(13) + "Set Kept: ("
IF Brief = 2 THEN out$ = "("
KeepTotal = 0
keep = 0
FOR i = 1 TO SetCount
IF keep(i) THEN
keep = keep + 1
IF keep > 1 THEN out$ = out$ + ", "
out$ = out$ + _TRIM$(STR$(SetRolls(i)))
KeepTotal = KeepTotal + SetRolls(i)
END IF
NEXT
KeepTotal = KeepTotal + DiceToRoll.TotalMod
out$ = out$ + ") = " + _TRIM$(STR$(KeepTotal))
DiceRoll$ = out$
END FUNCTION
FUNCTION ParseDiceOption (num, t_temp$)
SHARED DiceToRoll AS DiceRoller_Type
temp$ = _TRIM$(t_temp$)
IF temp$ = "" THEN EXIT FUNCTION
IF RIGHT$(temp$, 1) <> "," THEN temp$ = temp$ + ","
DO
f = INSTR(temp$, ",")
IF f THEN
o$ = LEFT$(temp$, f - 1)
temp$ = MID$(temp$, f + 1)
o = VAL(MID$(o$, 2))
o$ = LEFT$(o$, 1)
SELECT CASE o$
CASE "=": IF num = o THEN ParseDiceOption = -1: EXIT FUNCTION
CASE "<": IF num < o THEN ParseDiceOption = -1: EXIT FUNCTION
CASE ">": IF num > o THEN ParseDiceOption = -1: EXIT FUNCTION
END SELECT
END IF
LOOP UNTIL f = 0 OR temp$ = ""
END FUNCTION
SUB Sort (Array() AS LONG)
'The dice sorting routine, optimized to use _MEM and a comb sort algorithm.
'It's more than fast enough for our needs here I think. ;)
DIM m AS _MEM
DIM o AS _OFFSET, o1 AS _OFFSET
DIM t AS LONG, t1 AS LONG
m = _MEM(Array())
$CHECKING:OFF
gap = rollcount
DO
gap = 10 * gap \ 13
IF gap < 1 THEN gap = 1
i = 0
swapped = 0
DO
o = m.OFFSET + i * 4
o1 = m.OFFSET + (i + gap) * 4
IF _MEMGET(m, o, LONG) > _MEMGET(m, o1, LONG) THEN
_MEMGET m, o1, t1
_MEMGET m, o, t
_MEMPUT m, o1, t
_MEMPUT m, o, t1
swapped = -1
END IF
i = i + 1
LOOP UNTIL i + gap > UBOUND(Array)
LOOP UNTIL swapped = 0 AND gap = 1
$CHECKING:ON
_MEMFREE m
END SUB
FUNCTION RollEm$ (temp$)
SHARED DiceToRoll AS DiceRoller_Type
text1$ = UCASE$(temp$)
FOR i = 1 TO LEN(text1$) 'check for invalid characters
m$ = MID$(text1$, i, 1)
SELECT CASE m$
CASE "0" TO "9", "+", "-", "D", "K", "H", "L", "S", "T", ";", "=", "<", ">", ",", "R", "O", "B"
text$ = text$ + m$ 'add valid characters to make text$
CASE " " 'do nothing to a space
CASE ELSE
'invalid
END SELECT
NEXT
'IF DiagRollEM THEN PRINT "Verified: "; text$
IF text$ = "" THEN EXIT SUB 'can't do nothing with an empty string
ClearDice
DO
semicolon = INSTR(text$, ";")
IF semicolon THEN
l$ = LEFT$(text$, semicolon - 1)
text$ = MID$(text$, semicolon + 1)
ELSE
l$ = text$
END IF
'IF DiagRollEM THEN PRINT "PROCESSING: "; l$
found = 0
s = INSTR(l$, "S"): IF s THEN found = found + 1
d = INSTR(l$, "D"): IF d THEN found = found + 1
t = INSTR(l$, "T"): IF t THEN found = found + 1
b = INSTR(l$, "B"): IF b THEN found = found + 1
IF found <> 1 THEN EXIT SUB 'we should only find ONE element each pass, and there should always be one. IF not, somebody screwed up.
IF s THEN
DiceToRoll.Set = VAL(LEFT$(l$, s - 1))
IF DiagRollEm THEN PRINT "Number of Sets = "; DiceToRoll.Set
m$ = MID$(l$, s + 1)
pass = 0
DO UNTIL m$ = ""
pass = pass + 1
'IF DiagRollEM THEN PRINT "SUBPROC "; m$
n$ = LEFT$(m$, 1)
IF n$ = "K" OR n$ = "D" THEN n$ = LEFT$(m$, 2)
m$ = MID$(m$, LEN(n$) + 1)
v = VAL(m$)
SELECT CASE n$
CASE "+" '+ set mod
IF v > 0 THEN DiceToRoll.SetMod = v
IF DiagRollEm THEN PRINT "Set Mod"; v
CASE "-" ' - set mod
IF v > 0 THEN DiceToRoll.SetMod = -v
IF DiagRollEm THEN PRINT "Set Mod"; v
CASE "KH" 'keep high
IF v > 0 THEN DiceToRoll.SetKeepHigh = v
IF DiagRollEm THEN PRINT "Keep the Highest"; v; " Sets"
CASE "KL"
IF v > 0 THEN DiceToRoll.SetKeepLow = v
IF DiagRollEm THEN PRINT "Keep the Lowest"; v; " Sets"
CASE "DH"
IF v > 0 THEN DiceToRoll.SetDiscardHigh = v
IF DiagRollEm THEN PRINT "Discard the Highest"; v; " Sets"
CASE "DL"
IF v > 0 THEN DiceToRoll.SetDiscardLow = v
IF DiagRollEm THEN PRINT "Discard the Lowest"; v; " Sets"
CASE "R", "O" 'reroll or open roll
finished = 0: t$ = "": innerpass = 0
DO UNTIL finished
innerpass = innerpass + 1
v = VAL(m$)
IF v <> 0 THEN 'it's an o/r followed by a number
t$ = t$ + "=" + _TRIM$(STR$(v)) + ","
ELSE
n1$ = LEFT$(m$, 1)
SELECT CASE n1$
CASE "="
m$ = MID$(m$, 2)
v = VAL(m$)
t$ = t$ + "=" + _TRIM$(STR$(v)) + ","
CASE "<"
m$ = MID$(m$, 2)
v = VAL(m$)
t$ = t$ + "<" + _TRIM$(STR$(v)) + ","
CASE ">"
m$ = MID$(m$, 2)
v = VAL(m$)
t$ = t$ + ">" + _TRIM$(STR$(v)) + ","
CASE ","
m$ = MID$(m$, 2)
CASE ELSE 'a character not a number, or =<>,
finished = -1
END SELECT
END IF
StripNumber m$
IF n$ = "R" THEN
DiceToRoll.SetReRoll = t$
IF DiagRollEm THEN PRINT "Reroll Sets "; DiceToRoll.SetReRoll
ELSE
DiceToRoll.SetOpenRoll = t$
IF DiagRollEm THEN PRINT "Openroll Sets "; DiceToRoll.SetOpenRoll
END IF
IF m$ = "" THEN finished = -1
IF innerpass > 255 THEN IF DiagRollEm THEN PRINT "Error -- Too many loops processing Set ReRoll or OpenRoll": EXIT FUNCTION
LOOP
END SELECT
StripNumber m$
n$ = LEFT$(m$, 1)
SELECT CASE n$
CASE "K", "D", "R", "O", "+", "-" 'see if it's another command without a comma
CASE ELSE
comma = INSTR(m$, ",")
IF comma THEN m$ = MID$(m$, comma + 1)
END SELECT
IF pass > 100 THEN IF DiagRollEm THEN PRINT "Error - endless processing loop deciphering SET information": EXIT FUNCTION
LOOP
END IF
IF d THEN
v = VAL(LEFT$(l$, d))
IF v < 1 THEN DiceToRoll.NumberOfDice = 1 ELSE DiceToRoll.NumberOfDice = v
IF DiagRollEm THEN PRINT "Number of Dice To Roll = "; DiceToRoll.NumberOfDice
m$ = MID$(l$, d + 1)
v = VAL(m$)
IF v > 0 THEN DiceToRoll.DiceSides = v
StripNumber m$
IF DiagRollEm THEN PRINT "Dice Sides = "; DiceToRoll.DiceSides
pass = 0
DO UNTIL m$ = ""
pass = pass + 1
'IF DiagRollEM THEN PRINT "SUBPROC "; m$
n$ = LEFT$(m$, 1)
IF n$ = "K" OR n$ = "D" THEN n$ = LEFT$(m$, 2)
m$ = MID$(m$, LEN(n$) + 1)
v = VAL(m$)
SELECT CASE n$
CASE "+" '+ set mod
IF v > 0 THEN DiceToRoll.DiceMod = v
IF DiagRollEm THEN PRINT "DM"; v
CASE "-" ' - set mod
IF v > 0 THEN DiceToRoll.DiceMod = -v
IF DiagRollEm THEN PRINT "DM"; v
CASE "KH" 'keep high
IF v > 0 THEN DiceToRoll.DiceKeepHigh = v
IF DiagRollEm THEN PRINT "DKH"; v
CASE "KL"
IF v > 0 THEN DiceToRoll.DiceKeepLow = v
IF DiagRollEm THEN PRINT "DKL"; v
CASE "DH"
IF v > 0 THEN DiceToRollDiceDiscardHigh = v
IF DiagRollEm THEN PRINT "DDH"; v
CASE "DL"
IF v > 0 THEN DiceToRoll.DiceDiscardLow = v
IF DiagRollEm THEN PRINT "DDL"; v
CASE "R", "O" 'reroll or open roll
finished = 0: t$ = "": innerpass = 0
DO UNTIL finished
innerpass = innerpass + 1
v = VAL(m$)
IF v <> 0 THEN 'it's an o/r followed by a number
t$ = t$ + "=" + _TRIM$(STR$(v)) + ","
ELSE
n1$ = LEFT$(m$, 1)
SELECT CASE n1$
CASE "="
m$ = MID$(m$, 2)
v = VAL(m$)
t$ = t$ + "=" + _TRIM$(STR$(v)) + ","
CASE "<"
m$ = MID$(m$, 2)
v = VAL(m$)
t$ = t$ + "<" + _TRIM$(STR$(v)) + ","
CASE ">"
m$ = MID$(m$, 2)
v = VAL(m$)
t$ = t$ + ">" + _TRIM$(STR$(v)) + ","
CASE ","
m$ = MID$(m$, 2)
CASE ELSE 'a character not a number, or =<>,
finished = -1
END SELECT
END IF
StripNumber m$
IF n$ = "R" THEN
DiceToRoll.DiceReroll = t$
IF DiagRollEm THEN PRINT "DR: "; DiceToRoll.DiceReroll
ELSE
DiceToRoll.DiceOpenRoll = t$
IF DiagRollEm THEN PRINT "DO: "; DiceToRoll.DiceOpenRoll
END IF
IF m$ = "" THEN finished = -1
IF innerpass > 255 THEN IF DiagRollEm THEN PRINT "Error -- Too many loops processing Dice ReRoll or OpenRoll": EXIT FUNCTION
LOOP
END SELECT
StripNumber m$
n$ = LEFT$(m$, 1)
SELECT CASE n$
CASE "K", "D", "R", "O", "+", "-" 'see if it's another command without a comma
CASE ELSE
comma = INSTR(m$, ",")
IF comma THEN m$ = MID$(m$, comma + 1)
END SELECT
IF pass > 100 THEN IF DiagRollEm THEN PRINT "Error - endless processing loop deciphering SET information": EXIT FUNCTION
LOOP
END IF
IF t THEN
DiceToRoll.TotalMod = VAL(MID$(l$, 2))
IF DiagRollEm THEN PRINT "Dice Total Modifier = "; DiceToRoll.TotalMod
END IF
IF b THEN
Brief = VAL(MID$(l$, 2))
IF DiagRollEm THEN PRINT "Roll Information Displayed: ";
SELECT CASE Brief
CASE 0: IF DiagRollEm THEN PRINT "Full"
CASE 1: IF DiagRollEm THEN PRINT "Reduced"
CASE 2: IF DiagRollEm THEN PRINT "Final Results Only"
END SELECT
END IF
LOOP UNTIL l$ = text$
RollEm$ = DiceRoll$
END FUNCTION
If you want to make this a library for your own usage, just strip it out at line 70 or so, and save it as whatever library name you want. "DiceRoller.BM" works for me, but make it whatever you'd like...
At that point, usage is rather simple:
'$INCLUDE:'whatever_you_named_your_library.BM" would go at the bottom of your code, and then you can simply use:
result$ = RollEm$(whatever_to_roll$)
This little library is able to do just about anything you'd need it to do, as far as dice rolling for RPGs go, as long as you follow the basic syntax and send it a proper string.
[b]First Concept of Library:[/b] Our "dice rolling formula" is broken down into segments seperated by a semicolon.
[b]Our 4 basic segments are:[/b] Sets Dice Total mod Brief output
[b]For Sets, the syntax is:[/b] ##S -- the number of sets, followed by S
[b]For Dice, the syntax is:[/b] ##D## -- the number of dice, followed by D, followed by the sides on the dice. NOTE: the first set of numbers are optional, so you could simply use D6 to roll a single six sided dice.
[b]For Total modifed, the syntax is:[/b] T## -- T followed by the total to add or subtract to the total dice roll
[b]For Brief output, the syntax is:[/b] ##B -- the number to represent how little output we want, followed by B 0 = full output 1 = reduced output 2 = minimal output (basically only the final results)
[b]Second Concept of Library:[/b] Our segments can be further limited by optional parameters
[b]+## (or -##)[/b] -- add (or subtract) number to segment
[b]KH## [/b]-- Keep the Highest number of "segment" [b]KL## [/b]-- Keep the Lowest number of "segment" [b]DH## [/b]-- Discard the Highest number of "segment" [b]DL## [/b]-- Discard the Lowest number of "segment"
[b]R + [i]stuff[/i][/b] -- Reroll according to [i]stuff[/i] [b]O + [i]stuff[/i][/b]-- Openroll according [i]to stuff[/i]
[i]stuff[/i] -- A string composed of numbers, operators, and commas, to represent what to reroll or openroll. It sounds complex, but its not.
R1 -- Reroll all 1's R=2,=3 -- Reroll all rolls that are equal to 2 and equal to 3 R<4 -- Reroll all rolls that are less than 4
O1<2>3 -- (a silly rule set, but hey, it's an example)... Openroll all 1's, all numbers less than two, and all numbers greater than 3
[b]Putting it all together:[/b]
In the end, what we end up with is formulas which look like the following:
3S;2D10 -- Roll 3 sets; of 2 10-sided dice.
6S;4D6KH3 -- Roll 6 sets; of 4 6-sided dice, keeping the 3 highest rolls
10SKH1KL1;2D10+2 -- Roll 10 sets of dice and only keep the highest set and the lowest set; of 2 10-sided dice, and add 2 to each dice.
Depending on what you want, you can generate some rather impressive formulas and take all the bite out of the dice rolling process completely for your games.
NOTE: Spaces are optional, so if they help you understand your "dice rolling formulas" better, feel free to use them:
4S; 3D10 KH2 O20 R2 ; T1; B2 -- Roll 4 sets of; 3 10-sided dice, keeping the 2 highest dice, and openrolling if the dice total to 20, and rerolling if the dice total to 2; then add 1 to the final total; and all we want to see are the final results...
I turned the powershell stuff into a simple little library for people to make use of in their projects, and here it is:
Code: (Select All)
_Title "Steve's Powershell Speech Library"
Speech_IoR 'initialize or reset speech options
Speech_SaP "Hello World, This is a normal speed demo of David's voice" 'speak and print
_Delay 2
Speech_Speaker "Ziva"
Speech_Say "Hello again. This is a normal speed demo of Ziva's voice." 'just speak this one
_Delay 2
Speech_Speaker "David"
Speech_Speed -10
Speech_SaP "And now I'm speaking as David, but I'm speaking veeery slow."
_Delay 2
Speech_Speaker "Ziva"
Speech_Speed 5
Speech_SaP "And now I'm a very hyper Ziva!"
_Delay 2
Speech_Speed 0
Speech_Volume 30
Speech_SaP "And now I'm whispering to you that I'm done with my demo!"
'$INCLUDE:'TextToSpeech.BM'
As you can see, all the commands are preceeded by "Speech_", to try and help keep the sub names unique, associative, and not interfere with any user variable names and such.
Routines in this little package are:
Speech_IoR -- Init or Reset. Call this first to initialize the settings (and turn volume up to 100, or else you'll be speaking on a MUTE channel)
Speech_Speaker -- Change the default speaker. Currently I only support "David" and "Ziva", but feel free to change or add to this if your system has other voices installed via language/voice packs.
Speech_Speed -- Set a value from -10 to 10 to adjust the speed of the speaker. 0 id default, -10 is sloooow, and 10 is faaaast.
Speech_Volume -- Set a value from 0 to 100 to adjust how loud you're going to be speaking with the voices.
Speech_OutTo -- Use this to change where you want the speech to go. Only options now are your speakers or a file. Since it's not currently in the demo, as I didn't want to randomly save junk to folks drives, an example looks like:
Speech_OutTo "MyTextToFile.wav" Speech_OutTo "Speaker" Speech_OutTo "" 'defaults/resets to speaker
Speech_Say -- Just says the text you specify with the settings you gave it previously.
Speech_SaP -- Says and Prints the text you specify to the screen as a quick print and speak shortcut. Uses previous settings.
Speech_ToWav -- Converts text to a wav file and saves it to the disk where you specify. Since it's not in the short demo above, usage would be as:
Speech_ToWav "Hello World. This is the text I'm saving to a file!", "MyFile.wav"
speak -- This is the master command with all the options built into it. You can skip everything else, if you want to use this as a stand alone command to do everything all at once. Everything else ends up calling this command at the end of the day, so you can bypass some processes if you call this directly.
And that's basically it for now. Windows Speech Synthesizer is quite a powerful little tool, with a ton of options which we can utilize with it, but I figure this is the basics of what someone would need to be able to do with it for a program. It seems to handle what I need from it for now.
If you guys need it to do more, feel free to ask and I'll see about adding extra functionality as people need it. Or, feel free to make the changes necessary yourself and then share them here with us so everybody else can enjoy any extra tweaks you guys add into the code.
To make use of this:
1) Download the library from the attachment below. 2) Move it to your QB64 folder. 3) '$INCLUDE:'TextToSpeech.BM' at the end of your program. 4) Speech_IoR inside your code to initialize everything 5) Call the other subs as you want to make use of them and alter the settings to your specific needs.
Posted by: Pete - 04-27-2022, 08:51 PM - Forum: TheBOB
- No Replies
Abacus.bas by Bob Seguin. Description: Ancient Japanese calculator. Use the mouse to move the beads.
Download: Download the zip file below. Unzip to either your QB64 folder, or for better organization, to a folder you create like "TheBOB-Abacus".
Install: Compile Abacus.bas with QB64 v1.3 or above, and make sure the compiler output is set to create the .exe file in the same folder. See the option in the QB64 IDE RUN menu and check the RUN option: "Output EXE to Source Folder".
Inspired by Petr's 3D printing, I sat down and worked up a simple little routine to make pseudo-3d text of my own, and I wrapped it up into a single neat little SUB with 3 zillion parameters...
Print3D 100, 400, "No 3D, just *italic* style text.", 1, 20, OE20, &HFF00FF00, 0, 0, 1, 1
SUB Print3D (x AS INTEGER, y AS INTEGER, text$, thick AS INTEGER, tilt AS INTEGER,_
f AS LONG, fg AS _UNSIGNED LONG, xchange as integer, ychange as integer,_
scalex as _float, scaley as _float)
DIM copy AS INTEGER
DIM dx1 AS _FLOAT, dx2 AS _FLOAT, dy1 AS _FLOAT, dy2 AS _FLOAT
d = _DEST: s = _SOURCE: font = _FONT
copy = _NEWIMAGE(_WIDTH, _HEIGHT, 32)
_DEST copy: _SOURCE copy
_FONT f
sx1 = 0: sy1 = 0
sx2 = _PRINTWIDTH(text$, copy): sy2 = _FONTHEIGHT(f)
dx1 = x: dy1 = y
dx2 = x + sx2 * scalex: dy2 = y + sy2 * scaley
FOR i = thick TO 0 STEP -1
CLS , 0
COLOR _RGBA32(_RED32(fg), _GREEN32(fg), _BLUE32(fg), 155 + 100 / i), 0
PRINT text$
_MAPTRIANGLE (sx1, sy1)-(sx2, sy1)-(sx1, sy2), copy TO(dx1 + tilt, dy1)-(dx2 + tilt, dy1)-(dx1, dy2), d
_MAPTRIANGLE (sx1, sy2)-(sx2, sy1)-(sx2, sy2), copy TO(dx1, dy2)-(dx2 + tilt, dy1)-(dx2, dy2), d
dx1 = dx1 + xchange: dx2 = dx2 + xchange: dy1 = dy1 + ychange: dy2 = dy2 + ychange
NEXT
_DEST d: _SOURCE s: _FONT font
_FREEIMAGE copy
END SUB
Various thickness is supported. Different tilts are supported. Text can expand from any direction... We can use it to italicize our text if we want to... It scales text to different widths and heights...
It's not a true 3D text, as in we can't rotate it on the x/y/z axis, but it makes a nice imitation text which we can use to create a nice title screen, or such, for our programs.
Play around with it, see what you guys think of it, and I'll be happily awaiting to see how you guys who are much better than me in math will improve/alter this.
Many thanks go to Petr for providing the inspiration for me to sit down and play around with getting this up and going to the point where it is. I'm really quite happy with how it performs and what it can do for us, and I think this will end up going into my toolbox for regular use from now on. And a little demo of some of the various styles of 3d text which we can generate with the routine. Watch and pay attention to which direction the text tilts and turns as the program goes along.
FOR x = -2 TO 2 STEP 0.1
CLS , 0
Print3D 100, 200, "Steve is Awesome!", 5, x * 20, OE20, &HFFFF0000, x, x, 1, 1.25
_LIMIT 3
_DISPLAY
NEXT
FOR x = -2 TO 2 STEP 0.1
CLS , 0
Print3D 100, 200, "Steve is Awesome!", 5, x * 20, OE20, &HFFFF0000, -x, -x, 1, 1.25
_LIMIT 3
_DISPLAY
NEXT
FOR x = -2 TO 2 STEP 0.1
CLS , 0
Print3D 100, 200, "Steve is Awesome!", 5, x * 20, OE20, &HFFFF0000, x, -x, 1, 1.25
_LIMIT 3
_DISPLAY
NEXT
FOR x = -2 TO 2 STEP 0.1
CLS , 0
Print3D 100, 200, "Steve is Awesome!", 5, x * 20, OE20, &HFFFF0000, -x, x, 1, 1.25
_LIMIT 3
_DISPLAY
NEXT
SUB Print3D (x AS INTEGER, y AS INTEGER, text$, thick AS INTEGER, tilt AS INTEGER,_
f AS LONG, fg AS _UNSIGNED LONG, xchange as integer, ychange as integer,_
scalex as _float, scaley as _float)
DIM copy AS INTEGER
DIM dx1 AS _FLOAT, dx2 AS _FLOAT, dy1 AS _FLOAT, dy2 AS _FLOAT
d = _DEST: s = _SOURCE: font = _FONT
copy = _NEWIMAGE(_WIDTH, _HEIGHT, 32)
_DEST copy: _SOURCE copy
_FONT f
sx1 = 0: sy1 = 0
sx2 = _PRINTWIDTH(text$, copy): sy2 = _FONTHEIGHT(f)
dx1 = x: dy1 = y
dx2 = x + sx2 * scalex: dy2 = y + sy2 * scaley
FOR i = thick TO 0 STEP -1
CLS , 0
COLOR _RGBA32(_RED32(fg), _GREEN32(fg), _BLUE32(fg), 155 + 100 / i), 0
PRINT text$
_MAPTRIANGLE (sx1, sy1)-(sx2, sy1)-(sx1, sy2), copy TO(dx1 + tilt, dy1)-(dx2 + tilt, dy1)-(dx1, dy2), d
_MAPTRIANGLE (sx1, sy2)-(sx2, sy1)-(sx2, sy2), copy TO(dx1, dy2)-(dx2 + tilt, dy1)-(dx2, dy2), d
dx1 = dx1 + xchange: dx2 = dx2 + xchange: dy1 = dy1 + ychange: dy2 = dy2 + ychange
NEXT
_DEST d: _SOURCE s: _FONT font
_FREEIMAGE copy
END SUB
Salvaged from the other boards, some of you may have seen this before:
Code: (Select All)
Screen _NewImage(640, 640, 32)
_Title "Number Types and Colors"
Print "Welcome to Steve's Qucik Lesson on Number Types and Colors."
Print
Print "The most important thing to keep in mind in this lesson is that we're going to be talking exclusively about 32-bit color values here. For all other screen modes, this lesson holds much less importance."
Print
Print "Press <ANY KEY> to begin!"
Sleep
Cls , 0
Print "First, let's talk about how SINGLE variable types work (or DON'T work), in regards to 32-bit colors."
Print
Print "Let's choose a nice color and use it to draw a box on the screen."
Print "How about we choose a BLUE box? _RGB32(0, 0, 255)"
Print
Line (50, 90)-(250, 250), _RGB32(0, 0, 255), BF
Locate 18, 1: Print "Looks like a nice BLUE box. Right?"
Print "Press <ANY KEY> to continue!"
Sleep
Cls , 0
Print "Now, let's store that BLUE value inside a SINGLE tyoe variable."
Print "BLUE = _RGB32(0, 0, 255)"
Print ""
Print "Once we've did that, let's draw the exact same box on the screen again with the variable."
BLUE = _RGB32(0, 0, 256)
Line (50, 90)-(250, 250), BLUE, BF
Locate 18, 1: Print "Looks like a nice BLUE box. Right?"
Print "Press <ANY KEY> to continue!"
Sleep
Cls , 0
Print "What do you guys mean, 'What box?'??"
Print "Do you mean to tell me you nice folks DIDN'T see a pretty BLUE box on the last screen??"
Print
Print
Print "Just what the hell happened to it?!!"
Print
Print
Print "For the answer to that, let's print out two values to the screen:"
Print "BLUE = "; BLUE
Print "_RGB32(0, 0, 255) = "; _RGB32(0, 0, 255)
Print
Print "At first glance, those APPEAR to be the same numbers, but let's expand the scientific notation fully:"
Blue&& = BLUE
Print "BLUE = "; Blue&&
Print "_RGB32(0, 0, 255) = "; _RGB32(0, 0, 255)
Print
Print "Press <ANY KEY> to continue!"
Sleep
Cls , 0
Print "HOLY COW, BATMAN!! Was those two numbers DIFFERENT?!!"
Print "BLUE = "; Blue&&; "vs"; _RGB32(0, 0, 255)
Print
Print "Well... They're only a LITTLE different... Right?"
Print "I mean, how bad can one little number difference be? Right??"
Print
Print "For the answer to that, let's look at the HEX values of those numbers:"
Print "BLUE = "; Hex$(Blue&&)
Print "_RGB32(0, 0, 255) - "; Hex$(_RGB32(0, 0, 255))
Print
Print "And to help understand what we're seeing in HEX, break those values down into groups of 2 in your mind."
Print "(I'm too lazy to do it for you..)"
Print "The first two values are ALPHA, followed by RED, followed by GREEN, followed by BLUE."
Print
Print "So BLUE = FF alpha, 00 red 01 green, 00 blue"
Print "_RGB32(0, 0, 0) = FF alpha, 00 red, 00 green, FF blue"
Print
Print "And keep in mine that FF is HEX for the decimal value of 255."
Print
Print "Press <ANY KEY> to continue!"
Sleep
Cls , 0
Print "Since SINGLE values lose precision after numbers get so large, our variable BLUE"
Print "has to round to the nearest scientific notation point and try for the closest"
Print "possible match."
Print
Print "And even though "; Blue&&; " is only one number off from "; _RGB32(0, 0, 255); ","
Print "that number still greatly changes the color value."
Print
Print "It changes it from FF 00 00 FF (255 alpha, 0 red, 0 green, 255 blue) to"
Print "FF 00 01 00 (255 alpha, 0 red, 1 green, 0 blue)."
Print
Print "Our BLUE has become a GREEN, simply by using a SINGLE variable type!!"
Print "(And, it's such a low shade green, my poor eyes can't make it out at all."
Print "To me, the damn 'green box' was just as black as my black screen."
Print "I didn't see it at all!)"
Print "Press <ANY KEY> to continue!"
Sleep
Cls , 0
Print "So, at this point, I think it should be obvious WHY we don't want to store"
Print "color values inside SINGLE variables."
Print
Print "But what about using a normal LONG to hold the values??"
Print
Print "Let's look and see!"
Print
Print "For this, let's draw our box again:"
Line (50, 150)-(250, 250), _RGB32(0, 0, 255), BF
Locate 18, 1: Print "Looks like a nice BLUE box. Right?"
Print
Print "But let's get the POINT value from that box, and store it in a LONG variable."
BLUE& = Point(100, 200)
Print "BLUE& = "; BLUE&
p&& = Point(100, 200)
Print "POINT(100, 200) = "; Point(100, 200)
Print
Print
Print "Again, we're looking at two numbers that don't match!"
Print
Print "FOR THE LOVE OF GOD, WHYYYY??!!!!"
Print "Press <ANY KEY> to continue!"
Sleep
Cls , 0
Print BLUE&; "<>"; p&&
Print
Print "Why are those two numbers so different??"
Print
Print "For that answer, let's look at their HEX values again:"
Print "BLUE& = "; Hex$(BLUE&)
Print "POINT(100, 200) = "; Hex$(p&&)
Print
Print "."
Print "..."
Print "......"
Print
Print "WHAT THE HEX?? Those two values are EXACTLY the same??"
Print
Print "They are. It's just that one of them is stored as a SIGNED LONG, while the other is an UNSIGNED LONG."
Print
Print "HEX wise, they're the same value..."
Print
Print "BUT, can you see where the two numbers might not match if we use them in an IF statement?"
Print
Print "IF "; BLUE&; "="; p&&; "THEN...."
Print
Print "Ummm... That might not work as intended!"
Print
Print "Press <ANY KEY> to continue!"
Sleep
Cls , 0
Print "Even thought the HEX values for "; BLUE&; "and"; p&&;
Print "are EXACTLY the same, the values themselves are quite different."
Print
Print "A LONG will, indeed, hold the proper value for a 32-bit color, as it stores"
Print "all four HEX values properly for us."
Print
Print "As long as our program uses NOTHING but LONG values, you'll never have a"
Print "problem with using LONG as a variable type..."
Print
Print "BUT...."
Print
Print "The moment you start to compare LONG values directly against POINT values,"
Print "your program is going to run into serious issues!"
Print
Print "Because at the end of the day,"; BLUE&; "is not the same as "; p&&
Print
Print
Print "Press <ANY KEY> to continue!"
Sleep
Cls , 0
Print "So, with all those examples, and all that said, let's answer"
Print "the most important question:"
Print
Print "'What TYPE works best for 32-bit colors??"
Print
Print
Print "DOUBLE, _FLOAT, _UNSIGNED LONG, _INTEGER64, _UNSIGNED _INTEGER64"
Print
Print "Of all the types which QB64 offers, only the above are TRULY viable"
Print "to hold a 32-bit color value."
Print
Print "Any type not listed above is going to be problematic at one time or"
Print "another for us!"
Print
Print "And of those suitable types, I personally prefer to keep integer values"
Print "as integers, so I recommend: _UNSIGNED LONG or _INTEGER64."
Print
Print
Print "Press <ANY KEY> to continue!"
Sleep
Cls , 0
Print "And WHY _UNSIGNED LONG??"
Print
Print "Simply because it's only 4 bytes of memory (the minimal we can possibly use for"
Print "32-bit color values), and it's what QB64 uses internally with POINT and such."
Print
Print
Print "So, if _UNSIGNED LONG works so well, WHY would I *ever* use _INTEGER64??"
Print
Print "Becauses sometimes I like to code command values into my colors."
Print "(Such as: NoColor = -1)"
Print
Print "_UNSIGNED LONG *only* holds the values for the colors themselves."
Print "EVERY number from 0 to FFFFFFFF is accounted for as part of our color spectrum."
Print
Print "If I need *special* or unique values for my program, I usually just use _INTEGER64s"
Print "for my variable types and then I can assign negative numbers for those unique values."
Print
Print
Print "Press <ANY KEY> to continue!"
Sleep
Cls , 0
Print "At the end of the day though, when all is said and done, you're still the"
Print "one responsible for your own code!"
Print
Print "Use whichever type works for you, and works best for your needs."
Print
Print "Just keep in mind: Various TYPEs come with various limitations on your code."
Print
Print "_BYTE, INTEGER, (both signed and unsigned) are insane to use..."
Print "SINLGE loses precision. Expect to lose whole shades of blue...."
Print "LONG may cause issues with POINT, if compared directly...."
Print "_UNSIGNED LONG works fine, any ONLY stores 32-bit color values...."
Print "_INTEGER64 works fine, and can store extra values if necessary...."
Print "DOUBLE and _FLOAT both work, but are floating point values...."
Print
Print
Print "And with all that said and summed up, it's now up to YOU guys to decide what"
Print "works best in your own programs."
Print
Print
Print "As I said, I personally recommend _UNSIGNED LONG or _INTEGER64 in special cases."
Print "But the choice, and the debugging, is entirely up to YOU. :D"
Copy. Paste. Compile. I'll let the code speak for itself and hopefully it'll help folks learn a bit more about WHY certain variables are more suitable for use with 32-bit color values than others.