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

Username/Email:
  

Password
  





Search Forums

(Advanced Search)

Forum Statistics
» Members: 308
» Latest member: Donaldvem
» Forum threads: 1,741
» Forum posts: 17,901

Full Statistics

Latest Threads
The QB64 IDE shell
Forum: Utilities
Last Post: JasonPag
09-16-2024, 05:37 PM
» Replies: 9
» Views: 762
Importance regarding Ches...
Forum: Utilities
Last Post: JasonPag
09-01-2024, 06:34 PM
» Replies: 0
» Views: 31
Chess and Analysis and En...
Forum: Utilities
Last Post: JasonPag
08-28-2024, 02:37 PM
» Replies: 0
» Views: 32
DAY 009:_PutImage
Forum: Keyword of the Day!
Last Post: grymmjack
09-02-2023, 02:57 PM
» Replies: 54
» Views: 2,032
Fall Banner Contest?
Forum: Site Suggestions
Last Post: grymmjack
08-31-2023, 11:50 PM
» Replies: 36
» Views: 1,261
ColorPicker - Function th...
Forum: Dav
Last Post: Dav
08-31-2023, 11:04 PM
» Replies: 3
» Views: 315
Goals(1) = New Tile()
Forum: Works in Progress
Last Post: RhoSigma
08-31-2023, 09:45 PM
» Replies: 3
» Views: 127
micro(A)v11
Forum: QBJS, BAM, and Other BASICs
Last Post: bplus
08-31-2023, 09:14 PM
» Replies: 90
» Views: 3,589
Updating The Single Most ...
Forum: QBJS, BAM, and Other BASICs
Last Post: bplus
08-31-2023, 09:13 PM
» Replies: 7
» Views: 254
QBJS Image Question
Forum: QBJS, BAM, and Other BASICs
Last Post: bplus
08-31-2023, 05:49 PM
» Replies: 5
» Views: 155

 
  Accumulation of many *.exe files
Posted by: dcromley - 04-28-2022, 03:52 PM - Forum: Help Me! - Replies (4)

I know QBPE is a compiler, which makes it great, but I end up with MANY *.exe files that accumulate that I don't want.  Can I choose to have a "temp.exe" for example that would overwrite the previous version?

Print this item

  Math Function Plot
Posted by: dcromley - 04-28-2022, 03:46 PM - Forum: Programs - No Replies

Working (playing) with the "PSET hat" program, I wanted to see some math functions.  So another QB64 program was needed.

I know there are online function plotting and other QBPE programs, but I like simplicity, and I like my own.  So here is what I use for plotting functions.  Since you have to compile it to put in your functions, I put in comments to document the use of it.  I hope it is clear.  This version has a variety of functions for demonstration.  I reserve the right to edit this to later versions.

Code: (Select All)
_Title "FunctionPlot" ' V1.0 dcromley 2022
Option _Explicit
DefSng A-Z: DefInt I-N: DefStr S
Screen _NewImage(1000, 750, 256)
Cls 0, 15: Color 0, 15
Dim Shared ulo, uhi, vlo, vhi, xlo, xhi, ylo, yhi
Dim Shared u, v, x, y, c, nfunc, xold, yold
ulo = 10: uhi = 989: vlo = 739: vhi = 10 ' screen limits

xyinit -8, 8, 1, -6, 6, 1 ' xlo xhi xdel; ylo yhi ydel =#= world limits
' the above line means x from -8 to +8 and grid lines every 1; 0 would be no grid lines

For nfunc = 1 To 9
  c = 0 ' default color
  For u = ulo To uhi: x = zxu(u) ' x
    If nfunc = 1 Then y = 1 - x ^ 2 / 2
    If nfunc = 2 Then y = Cos(x)
    If nfunc = 3 Then c = 2: y = Sin(x)
    If nfunc = 4 Then GoTo continue1 ' skip
    If nfunc = 5 Then y = func5(x)
    If nfunc = 6 Then y = func6(x, 1)
    If nfunc = 7 Then GoTo continue1
    If nfunc = 8 Then GoTo continue1
    If nfunc = 9 Then GoTo continue1
    If u > ulo Then zline xold, yold, x, y, c ' the plot lines
    xold = x: yold = y
    continue1:
  Next u
Next nfunc
zSystem ' end

Function func5 (x) '
  If x < 0 Then func5 = 0: Exit Function
  c = 1 ' blue
  Dim t: t = Sqr(x)
  func5 = Sqr(x) ' Sin(t) + .4 * Sin(3 * x)
End Function

Function func6 (x, N) ' 2 options in this function
  c = 4 ' red
  If N = 1 Then func6 = 8 * (1 / 2 * Cos(x) - 1 / 7 * Cos(3 * x) + 1 / 8 * Cos(5 * x))
  If N = 2 Then func6 = 8 * (.5 * Cos(x) - .125 * Cos(3 * x) + .07 * Cos(5 * x))
End Function

Sub xyinit (xxlo, xxhi, xdel, yylo, yyhi, ydel)
  xlo = xxlo: xhi = xxhi: ylo = yylo: yhi = yyhi ' save to globals
  If xdel > 0 Then ' vertial grid lines
    zline 0, ylo, 0, yhi, c ' y axis
    For x = xdel To zMax(Abs(xlo), Abs(xhi)) Step xdel ' other
      If zBetween(x, xlo, xhi) Then zline x, ylo, x, yhi, 7
      If zBetween(-x, xlo, xhi) Then zline -x, ylo, -x, yhi, 7
    Next x
  End If
  If ydel > 0 Then ' horizontal grid lines
    zline xlo, 0, xhi, 0, c ' x axis
    For y = ydel To zMax(Abs(ylo), Abs(yhi)) Step ydel ' other
      If zBetween(y, ylo, yhi) Then zline xlo, y, xhi, y, 7
      If zBetween(-y, ylo, yhi) Then zline xlo, -y, xhi, -y, 7
    Next y
  End If
End Sub

Sub zline (x1, y1, x2, y2, c)
  Line (zux(x1), zvy(y1))-(zux(x2), zvy(y2)), c
End Sub

Function zux (x)
  zux = zLerplh(ulo, uhi, x, xlo, xhi)
End Function

Function zvy (y)
  zvy = zLerplh(vlo, vhi, y, ylo, yhi)
End Function

Function zxu (u)
  zxu = zLerplh(xlo, xhi, u, ulo, uhi)
End Function

Function zyv (y)
  zyv = zLerplh(ylo, yhi, v, vlo, vhi)
End Function

Function zLerplh (ylo, yhi, x, xlo, xhi)
  zLerplh = ylo + (x - xlo) / (xhi - xlo) * (yhi - ylo)
End Function

Function zBetween (x, a, b)
  If x >= a And x <= b Then zBetween = 1
End Function

Function zMax (a, b)
  If a > b Then zMax = a Else zMax = b
End Function

Function zMin (a, b)
  If a < b Then zMin = a Else zMin = b
End Function

Sub zSystem
  While InKey$ = "": _Limit 60: Wend
  System
End Sub

Print this item

  Who and What is The Phoenix Edition
Posted by: SMcNeill - 04-28-2022, 02:48 PM - Forum: Announcements - Replies (9)

Since QB64 Phoenix Edition is a newly created offshoot of QB64, people have had various questions about who we are, what we're doing, and what ties we have with QB64 -- and they want to know what's up with our new releases.  Let me address those things one at a time for everyone:


Since Fellippe just walked away from the QB64 Team, things turned into a mess almost overnight with the new CEO.  Issues arose on the Discord, and I'm not going into any details over those things here as it'd just be rehashing the same old news over and over by now.  In the end, QB64 as it existed previously was destroyed.  The old team was completely removed from the repo, with all rights to push, pull, merge, or do releases taken from them.  The forums were shut down.  The wiki was taken offline.  QB64 was burnt to the ground.

Until we stepped in.  The Phoenix Edition worked hard to get the first editable wiki back up on the internet, from an old off-line that had been preserved, so people could have a working reference for the QB64 commands.  We worked to get up a new set of forums so the community could regather and not fragment into a thousand broken pieces.  We've worked hard on gathering up and making all the old resources as available to the public as we possibly can, and hosting as much old information on our servers as we can possibly find and share such as the old Podcasts and transcripts from those.

Most importantly, we've cloned the old repo and have been working fairly fervently to update the source to bring QB64 once again up to a stable version.  If you look at our repo, we've already had 54 commits pushed into it, showing there's been a LOT of activity by the recent team working on things.  We're the new team working hard so that QB64 doesn't die, as the new CEO obviously intended for it to do!



Now, as to who we are, let me reassure the folks that are out there worrying -- we're not some random strangers who just popped up overnight and decided to steal QB64 for our own nefarious gains.  I've personally been with QB64 since about version 0.5, and I've been pushing code into the source and developing QB64 for about 10 years now.   For the folks who don't believe it (there's always a few naysayers out there), here's a simple test you can use to check the verity of my words:  Open the oldest version of QB64.bas that you can find, and simply do a search for "Steve".  Almost instantly you'll see multiple places like " '### STEVE EDIT FOR CONST EXPANSION 10/11/2013" in the source.

That goes all the way back and predates the "QB64 Team" by several years!

And I'm not the only member of The Phoenix Edition who has been working and pushing changes into QB64 since about forever!


[Image: Git-History.png]


As you can see from the above, it's a screenshot taken from the github commit history with Galleon (the original creator of QB64), me, and DSMan all working on pushing changes and enhancements into QB64.  DSMan (Matt) is now back and rejoined The Phoenix Edition, and is working to help us restore QB64 back to a fully stable, working version, once again.  Just like me, he's been around forever and ever, and he's always been one of the people most welcome to help develop the language.  

As for the rest of our team -- Spriggsy, Cobalt, and Maxine, they're a little newer on the QB64 development history than we are, but you'll find their contributions in the old team's source as well.  None of us are "new" to QB64, and all of us have deep ties to the old QB64 Team, and we've worked on the language for ages.



So if we were  part of the QB64 team, why aren't we now?  Why did we migrate over to become "The Phoenix Edition"?


[Image: image.png]

[Image: image.png]

As you can see from the two screenshots above, before RC Cola burned down all the old QB64 content -- the forums, wiki, twitter, youtube, podcasts, and all else he could destroy -- he made a point of kicking and removing everyone from the project.  With the old sites and repo no longer available for us, we had to move on to somewhere, and the domain name and such for qb64phoenix.com was available, so why not it?  QB64.com as a domain name was for sell for close to $2000.  qb64phoenix.com cost $15.00, or so.  Since we were trying to rise up out of the ashes that RC Cola had left us in, it seemed like a fitting new name for the project moving forward.



So, why didn't we just stick with the plain old "QB64" that everyone is used to and knew?  Several reasons.  

First -- to distance ourselves from that drama.  QB64 Team was burned to the ground and destroyed by its CEO.  Who wants to be associated with such an act, and actor?

Second -- so that people won't think they're supporting us if they donate to the "QB64 Team".  If you're sending money to their patreon, buying cups or mugs with the old logo on them, you're not supporting us one bit.  Several people have offered to help donate and pay to help get the new project up and going, but that's not neccessary.  We're hobbyists, and this is our hobby.  We do what we do out of love for the language, and for the fun of expanding upon a language we love, and we don't do it for money.  Nobody is earning a cent anywhere to work for us, and help develop the Phoenix Edition.  Our overhead costs are just what it costs us to host the server and such, and that's all covered here:  Forum Costs and Donations (qb64phoenix.com)

Third -- Even though RC Cola thoroughly kicked and destroyed the old team, he's still the CEO of "Team QB64".  Unlike Galleon, who walked away and passed over the reigns to a new team of developers with his blessing, RC Cola left things in as messy of a state as he possibly could.  His last post on the patreon ended with: 

Quote:We will keep the Github Repo up and if their is enough people wanting to keep it alive please keep developing and we may come back.


...we may come back.

 So there you have it!  What's the future on that?  MAY??  

If we were to just pick up and continue to develop under the plain QB64 banner as before, and RC Cola suddenly decides to come back with a new team in the year or two, where would we be left standing?  How much confusion would that generate for the public?

"Hey Frank, what version of QB64 did you compile your code under?"

"Version 2.7."

"2.7??  But I'm compiling under version 3.2!"

"OH..  You must have that other QB64..."

No thanks.  Not interested in even thinking about that type scenario. 

RC Cola hasn't passed on "QB64" to anyone, and in an attempt to prevent any issues before they could ever arise from that, we're calling ourselves "QB64 Phoenix Edition" or "QBPE" for short.



(04-28-2022, 10:16 AM)Coolman Wrote: thank you for your work. is this version based on qb64 2.01?

To address this concern, let me say, "It absolutely is."  In fact, our version 0.5 picks directly up from the last version of the QB64 team and builds upon it from there.  We're not officially ready to say we're at a version 1.0 (which should tend to state it's a fully stable version), but we're working our way towards that end goal.  When we cloned the repo, we chose to continue work off the development branch, rather than the stable branch.  We didn't want to lose anyone's contributions to the language since v2.02, as the team was moving closer to a version 2.1 release later this year.  

Unfortunately though, some of the people who were developing for v2.1 have walked away from the project for good, like Fellippe.  Before we feel confident in saying everything is 100% stable and glitch free, we need some time to go over what those missing developers were attempting to work on and push into the language.  We need to hunt down anything that connects to the old site and remove dead links, html calls, and all that good stuff.  The QB64 source code has a LOT of lines to sort through, and we're not 100% confident that we've purged all those old, dead, references and such, and we're not 100% certain that all the old works in development are glitch free, so we're not confident about saying we're at version 1.0

IF we'd continued on as just QB64, our version number would probably now be version 2.0.5, but as things stand with the uncertainty about what RC Cola plans to do with the "Team QB64" which he now solely controls, we instead are calling this QB64 Phoenix Edition v0.5.  

You can think, in many ways, of "Phoenix Edition" being 2.0, if you like.  Wink

 

(04-28-2022, 10:44 AM)PhilOfPerth Wrote: Pardon my ignorance, but what's the simplest way to transition from the old tQB64 to the new  one? Will I need to move my "home-grown" files, or anything else, into a new directory?

Simplest way is the same as always -- just download and extract the new version from our github.  If you have your own files saved in a different directory, just be certain to check the option under "RUN" in the IDE for "Export EXE to source folder", so that your EXE will be placed in the proper folders of your choosing.  



Feel free to ask any and all questions and concerns that you guys might have, and I'll be happy to answer them to the best of my ability here for everyone.

Print this item

  Announcing QB64 Phoenix Edition v0.5 Release!
Posted by: admin - 04-28-2022, 03:45 AM - Forum: Announcements - Replies (7)

Release v0.5.0 · QB64-Phoenix-Edition/QB64pe (github.com)

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!

Print this item

  LSTYLES.BAS
Posted by: TarotRedhand - 04-28-2022, 12:09 AM - Forum: Programs - Replies (5)

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.

CONST DenseDotted% = &HAAAA            '| "- - - - - - - - "
CONST MediumDotted% = &H8888          '| "-  -  -  -  "
CONST SparseDotted% = &H8080          '| "-      -      "
CONST OneDot% = &H80                  '| "        -      "
CONST LongDash% = &HFFFC              '| "--------------  "
CONST MediumDash% = &HFCFC            '| "------  ------  "
CONST ShortDash% = &HDDDD              '| "--- --- --- --- "
CONST WideGapped% = &HF0F0            '| "----    ----    "
CONST SparseDash% = &HCCCC            '| "--  --  --  --  "
CONST LongShort% = &HFDBF              '| "------ -- ------"
CONST DashDot% = &HFAFA                '| "----- - ----- - "
CONST DotDashDot% = &H9FE4            '| "-  --------  -  "
CONST SixThreeOne% = &HFCE4            '| "------  ---  -  "

SCREEN 1
COLOR 8, 1
MyY% = 7
Gap% = 14
MyColour% = 3
X1% = 15
X2% = 302
LINE (X1%, MyY%)-(X2%, MyY%), MyColour%
MyY% = MyY% + Gap%
LINE (X1%, MyY%)-(X2%, MyY%), MyColour%, , DenseDotted%
MyY% = MyY% + Gap%
LINE (X1%, MyY%)-(X2%, MyY%), MyColour%, , MediumDotted%
MyY% = MyY% + Gap%
LINE (X1%, MyY%)-(X2%, MyY%), MyColour%, , SparseDotted%
MyY% = MyY% + Gap%
LINE (X1%, MyY%)-(X2%, MyY%), MyColour%, , OneDot%
MyY% = MyY% + Gap%
LINE (X1%, MyY%)-(X2%, MyY%), MyColour%, , LongDash%
MyY% = MyY% + Gap%
LINE (X1%, MyY%)-(X2%, MyY%), MyColour%, , MediumDash%
MyY% = MyY% + Gap%
LINE (X1%, MyY%)-(X2%, MyY%), MyColour%, , ShortDash%
MyY% = MyY% + Gap%
LINE (X1%, MyY%)-(X2%, MyY%), MyColour%, , WideGapped%
MyY% = MyY% + Gap%
LINE (X1%, MyY%)-(X2%, MyY%), MyColour%, , SparseDash%
MyY% = MyY% + Gap%
LINE (X1%, MyY%)-(X2%, MyY%), MyColour%, , LongShort%
MyY% = MyY% + Gap%
LINE (X1%, MyY%)-(X2%, MyY%), MyColour%, , DashDot%
MyY% = MyY% + Gap%
LINE (X1%, MyY%)-(X2%, MyY%), MyColour%, , DotDashDot%
MyY% = MyY% + Gap%
LINE (X1%, MyY%)-(X2%, MyY%), MyColour%, , SixThreeOne%
Q$ = INPUT$(1)
END

Enjoy.

TR

Print this item

  Air Hockey
Posted by: bplus - 04-27-2022, 11:53 PM - Forum: bplus - Replies (18)

Back by popular demand! Smile 

Air Hockey, choose between light and dark versions. I think I like dark more let's see:

[Image: AH-Light.png]    




Zip contains 2 bas source file, 2 Windows exe's and an Arial font file for those that don't have it.



Attached Files
.zip   Air Hockey Light and Dark.zip (Size: 2.63 MB / Downloads: 69)
Print this item

  I was bored so I made this.
Posted by: Keybone - 04-27-2022, 10:14 PM - Forum: Works in Progress - No Replies

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$

add_byte 54
test1%% = get_byte(theLimit.Current)
Print test1%%

add_int 1444443893487
test2&& = get_int(theLimit.Current)
Print test2&&

add_uint 45989379879387398734987
test3~&& = get_uint(theLimit.Current)
Print test3~&&

add_float 80982.39802
test4## = get_float(theLimit.Current)
Print test4##

add_str "boom!"
test5$ = get_str(theLimit.Current)
Print test5$


' Begin modules

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

Print this item

  Steve's Ole Dice Roller
Posted by: SMcNeill - 04-27-2022, 09:14 PM - Forum: SMcNeill - No Replies

Code: (Select All)
SCREEN _NEWIMAGE(1024, 720, 32)
_SCREENMOVE _MIDDLE

CONST DiagRollEm = -1

'The next lines are only needed for manual testing
DIM DiceToRoll AS DiceRoller_Type
DIM SHARED Brief AS LONG

'Feel free to change options as wanted for your program
'DiceToRoll.NumberOfDice = 2
'DiceToRoll.DiceSides = 10
'DiceToRoll.DiceReroll = "=1"
'DiceToRoll.DiceOpenRoll = "=10"
'DiceToRoll.DiceMod = 2
'DiceToRoll.DiceKeepHigh = 1
'DiceToRoll.DiceKeepLow = 1

'DiceToRoll.Set = 10
'DiceToRoll.SetMod = 1
'DiceToRoll.SetReRoll = "<6"
'DiceToRoll.SetOpenRoll = ">10"
'DiceToRoll.TotalMod = 27

'DiceToRoll.SetKeepHigh = 9


PRINT RollEm$("10skh9r2;2d10o20;t2;b2")

PRINT
PRINT "PRESS <ANY KEY> TO CONTINUE"
SLEEP
PRINT

ClearDice
DiceToRoll.Set = 6
DiceToRoll.NumberOfDice = 4
DiceToRoll.DiceSides = 6
DiceToRoll.DiceKeepHigh = 3


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


SUB ClearDice
    SHARED DiceToRoll AS DiceRoller_Type
    DiceToRoll.Set = 0
    DiceToRoll.SetMod = 0
    DiceToRoll.SetReRoll = ""
    DiceToRoll.NumberOfDice = 0
    DiceToRoll.DiceSides = 0
    DiceToRoll.DiceMod = 0
    DiceToRoll.DiceReroll = ""
    DiceToRoll.DiceOpenRoll = ""
    DiceToRoll.DiceKeepHigh = 0
    DiceToRoll.DiceKeepLow = 0
    DiceToRoll.DiceDiscardHigh = 0
    DiceToRoll.DiceDiscardLow = 0
    DiceToRoll.TotalMod = 0
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

            GOTO ReRollSet
        END IF

        SetTotal = SetTotal + KeepTotal + DiceToRoll.SetMod
        SetCount = SetCount + 1
        REDIM _PRESERVE SetRolls(SetCount) AS LONG
        SetRolls(SetCount) = SetTotal
        GrandTotal = GrandTotal + SetTotal

        IF Brief < 2 THEN
            IF DiceToRoll.SetMod THEN
                out$ = out$ + " + " + _TRIM$(STR$(DiceToRoll.SetMod))
                out$ = out$ + " = " + _TRIM$(STR$(SetTotal))
            END IF
            out$ = out$ + CHR$(13)
        ELSE
            out$ = out$ + _TRIM$(STR$(SetTotal))
            IF j < DiceToRoll.Set THEN out$ = out$ + ", " ELSE out$ = out$ + ")"
        END IF


    NEXT
    IF Brief < 2 THEN out$ = out$ + CHR$(13) + "GRAND TOTAL:"

    IF DiceToRoll.TotalMod THEN
        IF Brief < 2 THEN out$ = out$ + STR$(GrandTotal) + " +" + STR$(DiceToRoll.TotalMod)
    END IF

    GrandTotal = GrandTotal + DiceToRoll.TotalMod
    out$ = out$ + " =" + STR$(GrandTotal)

    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...

Print this item

  Text to Speech Library (Windows only)
Posted by: SMcNeill - 04-27-2022, 09:06 PM - Forum: SMcNeill - Replies (11)

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.

It's that simple!  ;D



Attached Files
.bm   TextToSpeech.BM (Size: 2.96 KB / Downloads: 84)
Print this item

  Abacus - Tired of Windows Calculator? Try This Instead!
Posted by: Pete - 04-27-2022, 08:51 PM - Forum: TheBOB - No Replies

Abacus.bas by Bob Seguin.
[Image: Screenshot-657.png]
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".



Attached Files
.7z   TheBOB-Abacus.7z (Size: 11.08 KB / Downloads: 64)
Print this item