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

Username/Email:
  

Password
  





Search Forums

(Advanced Search)

Forum Statistics
» Members: 497
» Latest member: VikRam2025
» Forum threads: 2,851
» Forum posts: 26,694

Full Statistics

Latest Threads
Who wants to PLAY?
Forum: QBJS, BAM, and Other BASICs
Last Post: dbox
1 hour ago
» Replies: 3
» Views: 64
_CONSOLEINPUT is blocking
Forum: General Discussion
Last Post: mdijkens
2 hours ago
» Replies: 6
» Views: 60
Most efficient way to bui...
Forum: General Discussion
Last Post: mdijkens
2 hours ago
» Replies: 7
» Views: 61
Fun with Ray Casting
Forum: a740g
Last Post: a740g
Today, 05:50 AM
» Replies: 10
» Views: 216
Very basic key mapping de...
Forum: SMcNeill
Last Post: a740g
Today, 02:33 AM
» Replies: 1
» Views: 48
Methods in types
Forum: General Discussion
Last Post: bobalooie
Today, 01:02 AM
» Replies: 0
» Views: 45
QBJS - ANSI Draw
Forum: QBJS, BAM, and Other BASICs
Last Post: dbox
Yesterday, 04:09 PM
» Replies: 3
» Views: 99
Cautionary tale of open, ...
Forum: General Discussion
Last Post: doppler
Yesterday, 10:23 AM
» Replies: 3
» Views: 105
Extended KotD #23 and #24...
Forum: Keyword of the Day!
Last Post: SMcNeill
Yesterday, 09:51 AM
» Replies: 0
» Views: 52
Big problem for me.
Forum: General Discussion
Last Post: JRace
Yesterday, 05:11 AM
» Replies: 11
» Views: 201

 
  QB64TUTORIAL.COM is ready
Posted by: TerryRitchie - 09-28-2022, 03:56 AM - Forum: Learning Resources and Archives - Replies (28)

The new tutorial is ready for use:

https://www.qb64tutorial.com

I've added new commands, more in-depth concepts, and of course the new look and feel. I'll post a banner on the old tutorial site directing everyone to the new site.

Have a look around and please report anything you find incorrect or needs fixing. I've probably looked over everything really well 5 times but I'm sure I missed something.

The old tutorial asset file will not work with this new version. I renamed the "Tasks" in the old tutorial to "Lessons" in this one. The new subdirectory names in the asset file reflect this. Also, I made modifications to some of the source code that will only be reflected in the new asset file.

Let me know what you think.

Also, I eventually want to create a lesson on Real-time/World Physics. I would really appreciate any help with this subject matter. Perhaps you want to write the lesson? Of course anyone that writes anything for the tutorial would get full credit. Have an idea for a lesson? Let me know. Now that I'm using Google Sites I can make modifications and additions quickly and easily.

Terry

Print this item

  Roots and powers playing nicely together...
Posted by: Pete - 09-28-2022, 01:00 AM - Forum: General Discussion - Replies (28)

So I decided on the long division methods over the approximation methods for nth roots then thought, why not apply these to decimal powers? It worked, because of the inverse relationship. So this is really choppy right now, and needs more work, but it looks like it is getting the digits correct.

What does it do?

Nth roots for whole numbers greater than zero.
Decimal roots for whole numbers greater than zero.
Mixed roots (Number >1 with decimal) for whole numbers greater than zero.
Powers for whole numbers greater than zero.
Decimal powers for whole numbers greater than zero.
Mixed powers (Power >1 with decimal) for whole numbers greater than zero.

So after I debug this for a bit, I want to see if I can figure out what needs to be done to go from whole numbers to mixed numbers with decimals and negative numbers.

Code: (Select All)
$CONSOLE:ONLY
DIM SHARED limit&&
PRINT "Demo does not display decimal point yet, and fails with zero roots/powers.": PRINT
DO
    INPUT "Input 1 for general roots or 2 for decimal powers: "; k$

    SELECT CASE k$
        CASE "1"
            LINE INPUT "Whole number: "; n$
            LINE INPUT "Root: "; r$
            j&& = INSTR(r$, ".")
            IF j&& THEN ' Decimal or mixed whole and decimal.
                IF j&& = 1 THEN ' Decimal only root. OKAY
                    pow$ = "1" + STRING$(LEN(r$) - 1, "0")
                    r$ = MID$(r$, INSTR(r$, ".") + 1)
                    ''PRINT n$, r$, pow$
                    greatest_common_factor pow$, r$
                    ''PRINT n$, r$, pow$: SLEEP
                    IF r$ <> "1" THEN GOSUB root_calc ELSE d$ = n$
                    tmp$ = d$
                    FOR i&& = 1 TO VAL(pow$) - 1
                        d$ = sm_mult$(tmp$, d$)
                    NEXT
                    sm_rt$ = d$
                    EXIT DO
                ELSE ' Mixed whole and decimal root. OKAY
                    r_whole$ = MID$(r$, 1, INSTR(r$, ".") - 1)
                    r$ = MID$(r$, INSTR(r$, ".") + 1)
                    pow$ = "1" + STRING$(LEN(r$), "0")
                    ''PRINT n$, r$, pow$
                    greatest_common_factor pow$, r$
                    ''PRINT n$, r$, pow$
                    tmp$ = sm_mult$(r_whole$, pow$)
                    r$ = sm_add$(tmp$, r$)
                    ''PRINT n$, r$: SLEEP
                    IF r$ <> "1" THEN GOSUB root_calc ELSE d$ = n$
                    ''PRINT d$: SLEEP
                    tmp$ = d$ ' Combine both parts.
                    FOR i&& = 1 TO VAL(pow$) - 1
                        tmp$ = sm_mult$(tmp$, d$)
                    NEXT
                    sm_rt$ = tmp$
                    ''PRINT sm_rt$
                    EXIT DO
                END IF
            ELSE ' Whole root. OKAY
                IF r$ <> "1" THEN GOSUB root_calc ELSE d$ = n$
            END IF
            sm_rt$ = d$
            EXIT DO
        CASE "2"
            LINE INPUT "Number: "; n$
            LINE INPUT "Power: "; pow$
            j&& = INSTR(pow$, ".")
            IF j&& THEN ' Decimal or mixed whole and decimal.
                IF j&& = 1 THEN ' Decimal only. OKAY
                    r$ = "1" + STRING$(LEN(pow$) - 1, "0")
                    pow$ = MID$(pow$, INSTR(pow$, ".") + 1)
                    ''PRINT pow$, r$
                    greatest_common_factor pow$, r$
                    ''PRINT pow$, r$: SLEEP
                    IF r$ <> "1" THEN GOSUB root_calc ELSE d$ = n$
                    sm_rt$ = d$
                    EXIT DO
                ELSE ' Mixed whole number and decimal. OKAY
                    d_whole$ = n$
                    FOR i&& = 1 TO VAL(MID$(pow$, 1, INSTR(pow$, ".") - 1)) - 1
                        d_whole$ = sm_mult$(d_whole$, n$)
                    NEXT
                    pow$ = MID$(pow$, INSTR(pow$, ".") + 1)
                    r$ = "1" + STRING$(LEN(pow$), "0")
                    greatest_common_factor pow$, r$
                    ''PRINT n$, d_whole$, r$, pow$: SLEEP
                    IF r$ <> "1" THEN GOSUB root_calc ELSE d$ = n$
                    ''PRINT d$, d_whole$: SLEEP
                    d$ = sm_mult$(d_whole$, d$)
                    sm_rt$ = d$
                    EXIT DO
                END IF
            ELSE ' Whole number OKAY
                d$ = n$
                FOR i&& = 1 TO VAL(pow$) - 1
                    d$ = sm_mult$(d$, n$)
                NEXT
                sm_rt$ = d$
                EXIT DO
            END IF
    END SELECT
LOOP

PRINT "Answer: "; sm_rt$: PRINT
RUN

root_calc:
' Decimal root conversion.
r = VAL(r$)
nu&& = INSTR(n$, ".") - 1: IF nu&& < 0 THEN nu&& = LEN(n$)
h&& = (r - (r - nu&& MOD r)) + 1
t$ = MID$(n$, 1, h&& - 1): d$ = "0"
limit&& = 16
' Calculate Pascal's Triangle.
REDIM p$(r + 1)
FOR i1&& = 1 TO r + 1
    p&& = 1
    FOR j1&& = 1 TO i1&&
        p$(j1&&) = LTRIM$(STR$(p&&))
        p&& = p&& * (i1&& - j1&&) \ j1&&
    NEXT
NEXT

DO
    oldx$ = "0"
    lcnt&& = lcnt&& + 1
    FOR j = 1 TO 10
        x$ = "0"
        FOR i&& = 1 TO r
            REM PRINT "(10 ^"; (i&& - 1); "*"; p$(i&&); "* d ^"; i&& - 1; " * j ^"; (r + 1 - i&&); ") + ";
            REM x = x + 10 ^ (i&& - 1) * VAL(p$(i&&)) * d ^ (i&& - 1) * j ^ (r + 1 - i&&)
            tmp$ = "1"
            FOR k% = 1 TO i&& - 1
                tmp$ = sm_mult$(tmp$, "10")
            NEXT
            tmp$ = sm_mult$(tmp$, p$(i&&))
            tmp2$ = "1"
            FOR k% = 1 TO i&& - 1
                tmp2$ = sm_mult$(tmp2$, d$)
            NEXT
            IF d$ = "0" AND k% = 1 THEN tmp2$ = "1" ' zero^0 = 1
            tmp3$ = sm_mult$(tmp$, tmp2$)
            tmp$ = "1"
            FOR k% = 1 TO r + 1 - i&&
                tmp$ = sm_mult$(tmp$, LTRIM$(STR$(j)))
            NEXT
            tmp2$ = sm_mult$(tmp3$, tmp$)
            x$ = sm_add(x$, tmp2$)
        NEXT
        IF LEN(x$) > LEN(t$) OR LEN(x$) = LEN(t$) AND x$ > t$ THEN EXIT FOR
        oldx$ = x$
    NEXT
    d$ = d$ + LTRIM$(STR$(j - 1))
    IF LEFT$(d$, 1) = "0" THEN d$ = MID$(d$, 2) ' Remove leading zero.
    tmp1$ = sm_sub$(t$, oldx$)
    tmp2$ = MID$(n$, h&&, r) + STRING$(r - LEN(MID$(n$, h&&, r)), "0")
    t$ = tmp1$ + tmp2$
    IF LEFT$(t$, 1) = "0" THEN t$ = MID$(t$, 2) 'Remove leading zero.
    h&& = h&& + r
    IF t$ = STRING$(LEN(t$), "0") AND h&& >= LEN(n$) OR lcnt&& = limit&& THEN EXIT DO
    IF dpx&& = 0 THEN ' Decimal point relocator. Limited to && size unless converted to string.
        IF h&& >= nu&& THEN
            dpx&& = INT(nu&& / 2 + .5)
            IF dpx&& = 0 THEN dpx&& = -1 ' Do not set to zero as -1 accomplishes the same thing and prevents ongoing loops here.
        END IF
    END IF
LOOP
dpx&& = 0 ' Remove this when all decimal situations are included.
IF dpx&& THEN
    sm_rt$ = MID$(d$, 0, dpx&& + 1) + "." + MID$(d$, dpx&& + 1)
ELSE
    sm_rt$ = d$
END IF

RETURN

SUB sm_greater_lesser (stringmatha$, stringmathb$, gl%)
    compa$ = stringmatha$: compb$ = stringmathb$ ' So original variables do not get changed.
    DO
        WHILE -1 ' Falx loop.
            IF gl% = 2 THEN EXIT WHILE ' For bypassing sign and decimal adjustments when only positive non-decimal numbers are being evaluated.
            ' Remove trailing zeros after a decimal point.
            IF INSTR(compa$, ".") THEN
                DO UNTIL RIGHT$(compa$, 1) <> "0" AND RIGHT$(compa$, 1) <> "." AND RIGHT$(compa$, 1) <> "-"
                    compa$ = MID$(compa$, 1, LEN(compa$) - 1)
                LOOP
            END IF
            IF INSTR(compb$, ".") THEN
                DO UNTIL RIGHT$(compb$, 1) <> "0" AND RIGHT$(compb$, 1) <> "." AND RIGHT$(compb$, 1) <> "-"
                    compb$ = MID$(compb$, 1, LEN(compb$) - 1)
                LOOP
            END IF

            IF MID$(compa$, 1, 2) = "-0" OR compa$ = "" OR compa$ = "-" THEN compa$ = "0"
            IF MID$(compb$, 1, 2) = "-0" OR compb$ = "" OR compb$ = "-" THEN compb$ = "0"

            ' A - and +
            j% = 0: k% = 0
            IF LEFT$(compa$, 1) = "-" THEN j% = -1
            IF LEFT$(compb$, 1) = "-" THEN k% = -1
            IF k% = 0 AND j% THEN gl% = -1: EXIT DO
            IF j% = 0 AND k% THEN gl% = 1: EXIT DO

            j&& = INSTR(compa$, ".")
            k&& = INSTR(compb$, ".")

            ' A starting decimal and non-decimal.
            IF j&& = 0 AND k&& = 1 THEN
                IF compa$ = "0" THEN gl% = -1 ELSE gl% = 1
                EXIT DO
            END IF
            IF k&& = 0 AND j&& = 1 THEN
                IF compb$ = "0" THEN gl% = 1 ELSE gl% = -1
                EXIT DO
            END IF

            ' remove decimals and align.
            j2&& = 0: k2&& = 0
            IF j&& <> 0 OR k&& <> 0 THEN
                IF j&& THEN compa$ = MID$(compa$, 1, INSTR(compa$, ".") - 1) + MID$(compa$, INSTR(compa$, ".") + 1): j2&& = LEN(compa$) - j&& + 1
                IF k&& THEN compb$ = MID$(compb$, 1, INSTR(compb$, ".") - 1) + MID$(compb$, INSTR(compb$, ".") + 1): k2&& = LEN(compb$) - k&& + 1
                compa$ = compa$ + STRING$(k2&& - j2&&, "0")
                compb$ = compb$ + STRING$(j2&& - k2&&, "0")
            END IF
            EXIT WHILE
        WEND

        ' Remove leading zeros if any.
        DO UNTIL LEFT$(compa$, 1) <> "0"
            compa$ = MID$(compa$, 2)
        LOOP
        IF compa$ = "" THEN compa$ = "0"
        DO UNTIL LEFT$(compb$, 1) <> "0"
            compb$ = MID$(compb$, 2)
        LOOP
        IF compb$ = "" THEN compb$ = "0"

        ' Both positive or both negative whole numbers.

        SELECT CASE LEN(compa$)
            CASE IS < LEN(compb$)
                gl% = -1
            CASE IS = LEN(compb$)
                IF compa$ = compb$ THEN
                    gl% = 0
                ELSEIF compa$ > compb$ THEN gl% = 1
                ELSEIF compa$ < compb$ THEN gl% = -1
                END IF
            CASE IS > LEN(compb$)
                gl% = 1
        END SELECT
        EXIT DO
    LOOP
END SUB

SUB sm_add_subtract_router (stringmatha$, operator$, stringmathb$, runningtotal$)
    DIM AS _INTEGER64 a, c, s
    a1$ = stringmatha$: b1$ = stringmathb$
    s = 18: i&& = 0: c = 0

    a$ = stringmatha$: b$ = stringmathb$: op$ = operator$

    IF op$ = "-" THEN
        IF LEFT$(b$, 1) = "-" THEN b$ = MID$(b$, 2) ELSE b$ = "-" + b$
    END IF

    IF INSTR(a$, ".") <> 0 OR INSTR(b$, ".") <> 0 THEN
        decimal% = -1
        IF INSTR(a$, ".") <> 0 THEN
            dec_a&& = LEN(MID$(a$, INSTR(a$, ".") + 1))
            a$ = MID$(a$, 1, INSTR(a$, ".") - 1) + MID$(a$, INSTR(a$, ".") + 1)
        END IF
        IF INSTR(b$, ".") <> 0 THEN
            dec_b&& = LEN(MID$(b$, INSTR(b$, ".") + 1))
            b$ = MID$(b$, 1, INSTR(b$, ".") - 1) + MID$(b$, INSTR(b$, ".") + 1)
        END IF
        ' Line up decimal places by inserting trailing zeros.
        IF dec_b&& > dec_a&& THEN
            j&& = dec_b&&
            a$ = a$ + STRING$(dec_b&& - dec_a&&, "0")
        ELSE
            j&& = dec_a&&
            b$ = b$ + STRING$(dec_a&& - dec_b&&, "0")
        END IF
    END IF

    IF LEFT$(a$, 1) = "-" OR LEFT$(b$, 1) = "-" THEN
        IF LEFT$(a$, 1) = "-" AND LEFT$(b$, 1) = "-" THEN
            sign$ = "": a$ = MID$(a$, 2): b$ = MID$(b$, 2)
        ELSE
            IF LEFT$(a$, 1) = "-" THEN a$ = MID$(a$, 2): sign_a$ = "-"
            IF LEFT$(b$, 1) = "-" THEN b$ = MID$(b$, 2): sign_b$ = "-"

            IF LEFT$(a1$, 1) = "-" THEN a1_x$ = MID$(a1$, 2) ELSE a1_x$ = a1$
            IF LEFT$(b1$, 1) = "-" THEN b1_x$ = MID$(b1$, 2) ELSE b1_x$ = b1$

            sm_greater_lesser a1_x$, b1_x$, gl%

            IF gl% < 0 THEN
                IF LEN(sign_b$) THEN sign$ = "-": SWAP a$, b$
            ELSE
                IF LEN(sign_a$) THEN sign$ = "-": SWAP sign_a$, sign_b$
            END IF
        END IF
    END IF

    z$ = ""
    ' Addition and subtraction of digits.
    DO
        i&& = i&& + s
        x1$ = MID$(a$, LEN(a$) - i&& + 1, s)
        x2$ = MID$(b$, LEN(b$) - i&& + 1, s)
        IF LEN(x2$) > LEN(x1$) THEN SWAP x1$, x2$
        a = VAL(sign_a$ + x1$) + VAL(sign_b$ + x2$) + c
        IF x1$ + x2$ = "" AND c = 0 THEN EXIT DO
        c = 0
        IF a > VAL(STRING$(s, "9")) THEN a = a - 10 ^ s: c = 1
        IF a < 0 THEN a = a + 10 ^ s: c = -1 ' a will never be less than 0.
        tmp$ = LTRIM$(STR$(a))
        z$ = STRING$(LEN(x1$) - LEN(tmp$), "0") + tmp$ + z$
    LOOP

    IF decimal% THEN
        z$ = MID$(z$, 1, LEN(z$) - j&&) + "." + MID$(z$, LEN(z$) - j&& + 1)
    END IF

    ' Remove any leading zeros.
    DO
        IF LEFT$(z$, 1) = "0" THEN z$ = MID$(z$, 2) ELSE EXIT DO
    LOOP

    IF z$ = "" OR z$ = "0" THEN z$ = "0" ELSE z$ = LEFT$(sign$, 1) + z$

    runningtotal$ = z$

    sign$ = "": sign_a$ = "": sign_b$ = "": i&& = 0: j&& = 0: decimal% = 0: c = 0
END SUB

FUNCTION sm_add$ (stringmatha$, stringmathb$)
    operator$ = "+"
    sm_add_subtract_router stringmatha$, operator$, stringmathb$, runningtotal$
    sm_add$ = runningtotal$
END FUNCTION

FUNCTION sm_sub$ (stringmatha$, stringmathb$)
    operator$ = "-"
    sm_add_subtract_router stringmatha$, operator$, stringmathb$, runningtotal$
    sm_sub$ = runningtotal$
END FUNCTION

FUNCTION sm_mult$ (stringmatha$, stringmathb$)
    DIM AS _INTEGER64 a, c, aa, cc, s, ss
    z$ = "": sign$ = "": mult&& = 0: h&& = 0: i&& = 0: j&& = 0: c = 0: decimal% = 0
    zz$ = "": ii&& = 0: jj&& = 0
    s = 8: ss = 18

    a$ = stringmatha$: b$ = stringmathb$

    IF INSTR(a$, "-") <> 0 OR INSTR(b$, "-") <> 0 THEN
        IF INSTR(a$, "-") <> 0 AND INSTR(b$, "-") <> 0 THEN
            a$ = MID$(a$, 2): b$ = MID$(b$, 2)
        ELSE
            IF INSTR(a$, "-") <> 0 THEN a$ = MID$(a$, 2) ELSE b$ = MID$(b$, 2)
            sign$ = "-"
        END IF
    END IF

    IF INSTR(a$, ".") <> 0 OR INSTR(b$, ".") <> 0 THEN
        decimal% = -1
        IF INSTR(a$, ".") <> 0 THEN
            dec_a&& = LEN(MID$(a$, INSTR(a$, ".") + 1))
            a$ = MID$(a$, 1, INSTR(a$, ".") - 1) + MID$(a$, INSTR(a$, ".") + 1)
        END IF
        IF INSTR(b$, ".") <> 0 THEN
            dec_b&& = LEN(MID$(b$, INSTR(b$, ".") + 1))
            b$ = MID$(b$, 1, INSTR(b$, ".") - 1) + MID$(b$, INSTR(b$, ".") + 1)
        END IF
    END IF

    IF LEN(a$) < LEN(b$) THEN SWAP a$, b$ ' Needed so x1$ is always the largest for leading zero replacements.
    ' Multiplication of digits.
    DO
        h&& = h&& + s: i&& = 0
        x2$ = MID$(b$, LEN(b$) - h&& + 1, s)
        DO
            i&& = i&& + s
            x1$ = MID$(a$, LEN(a$) - i&& + 1, s)
            a = VAL(x1$) * VAL(x2$) + c
            c = 0
            tmp$ = LTRIM$(STR$(a))
            IF LEN(tmp$) > s THEN c = VAL(MID$(tmp$, 1, LEN(tmp$) - s)): tmp$ = MID$(tmp$, LEN(tmp$) - s + 1)
            z$ = STRING$(LEN(x1$) - LEN(tmp$), "0") + tmp$ + z$
        LOOP UNTIL i&& >= LEN(a$) AND c = 0

        jj&& = jj&& + 1

        IF jj&& > 1 THEN
            ii&& = 0: cc = 0
            aa$ = holdaa$
            bb$ = z$ + STRING$((jj&& - 1) * s, "0")
            ' Addition only of digits.
            DO
                ii&& = ii&& + ss
                xx1$ = MID$(aa$, LEN(aa$) - ii&& + 1, ss)
                xx2$ = MID$(bb$, LEN(bb$) - ii&& + 1, ss)
                IF LEN(xx1$) < LEN(xx2$) THEN SWAP xx1$, xx2$
                aa = VAL(xx1$) + VAL(xx2$) + cc
                IF xx1$ + xx2$ = "" AND cc = 0 THEN EXIT DO ' Prevents leading zeros.
                cc = 0
                IF aa > VAL(STRING$(ss, "9")) THEN aa = aa - 10 ^ ss: cc = 1
                tmp$ = LTRIM$(STR$(aa))
                zz$ = STRING$(LEN(xx1$) - LEN(tmp$), "0") + tmp$ + zz$
            LOOP

            DO WHILE LEFT$(zz$, 1) = "0"
                IF LEFT$(zz$, 1) = "0" THEN zz$ = MID$(zz$, 2)
            LOOP
            IF zz$ = "" THEN zz$ = "0"

            holdaa$ = zz$
        ELSE
            holdaa$ = z$ + STRING$(jj&& - 1, "0")
        END IF

        z$ = "": zz$ = ""

    LOOP UNTIL h&& >= LEN(b$)

    z$ = holdaa$

    IF decimal% THEN
        DO UNTIL LEN(z$) >= dec_a&& + dec_b&&
            z$ = "0" + z$
        LOOP

        z$ = MID$(z$, 0, LEN(z$) - (dec_a&& + dec_b&& - 1)) + "." + MID$(z$, LEN(z$) - (dec_a&& + dec_b&&) + 1)

        DO UNTIL RIGHT$(z$, 1) <> "0" AND RIGHT$(z$, 1) <> "."
            z$ = MID$(z$, 1, LEN(z$) - 1)
        LOOP
    END IF

    IF STRING$(LEN(z$), "0") = z$ OR z$ = "" OR z$ = "0" THEN z$ = "0" ELSE z$ = sign$ + z$

    decimal% = 0: sign$ = ""

    runningtotal$ = z$
    sm_mult$ = z$
END FUNCTION

FUNCTION sm_div$ (stringmatha$, stringmathb$)
    hold_stringmatha$ = stringmatha$: hold_stringmathb$ = stringmathb$
    q$ = "": divisor$ = stringmathb$: dividend$ = stringmatha$
    DO ' Falx loop.
        'Strip off neg(s) and determine quotent sign.
        IF LEFT$(divisor$, 1) = "-" THEN divisor$ = MID$(divisor$, 2): q$ = "-"
        IF LEFT$(dividend$, 1) = "-" THEN dividend$ = MID$(dividend$, 2): IF q$ = "-" THEN q$ = "" ELSE q$ = "-"

        ' Quick results for divisor 1 or 0.
        IF dividend$ = "0" THEN q$ = "0": EXIT DO
        IF divisor$ = "1" THEN q$ = dividend$: EXIT DO
        IF divisor$ = "0" THEN q$ = "Division by zero not possible.": EXIT DO

        ' Determine decimal direction. -1 to left, +1 to right.
        gl% = 0: sm_greater_lesser divisor$, dividend$, gl%
        IF betatest% AND gl% = 1 THEN PRINT divisor$; " > "; dividend$; " Move decimal to the left"
        IF betatest% AND gl% = 0 THEN PRINT divisor$; " = "; dividend$
        IF betatest% AND gl% = -1 THEN PRINT divisor$; " < "; dividend$; " Move deciml to the right."
        IF gl% = 1 THEN ' Divisor is larger than dividend so decimal moves to the left.
            div_decimal% = -1 ' Move decimal point to the left.
        ELSEIF gl% = -1 THEN
            div_decimal% = 1 ' Move decimal point to the right.
        ELSE
            ' Divisor and dividend are the same number.
            q$ = q$ + "1": EXIT DO
        END IF
        divisor_ratio_dividend% = gl%

        ' Strip off decimal point(s) and determine places in these next 2 routines.
        dp&& = 0: dp2&& = 0: j2&& = 0
        temp&& = INSTR(divisor$, ".")
        IF temp&& THEN
            divisor$ = MID$(divisor$, 1, temp&& - 1) + MID$(divisor$, temp&& + 1)
            IF temp&& = 1 THEN
                DO UNTIL LEFT$(divisor$, 1) <> "0" ' Strip off any leading zeros on divisor only.
                    divisor$ = MID$(divisor$, 2)
                    dp&& = dp&& + 1
                LOOP
                dp&& = dp&& + 1
            ELSE
                dp&& = -(temp&& - 2)
            END IF
        ELSE
            dp&& = -(LEN(divisor$) - 1)
        END IF
        temp&& = INSTR(dividend$, ".")
        IF temp&& THEN
            dividend$ = MID$(dividend$, 1, temp&& - 1) + MID$(dividend$, temp&& + 1)
            IF temp&& = 1 THEN
                DO UNTIL LEFT$(dividend$, 1) <> "0" ' Strip off any leading zeros on divisor only.
                    dividend$ = MID$(dividend$, 2)
                    dp2&& = dp2&& + 1
                LOOP
                dp2&& = dp2&& + 1
            ELSE
                dp2&& = -(temp&& - 2)
            END IF
        ELSE
            dp2&& = -(LEN(dividend$) - 1)
        END IF
        IF betatest% THEN COLOR 11: PRINT "Divisor decimal moves "; LTRIM$(STR$(dp&&)); ". Dividend decimal moves"; LTRIM$(STR$(dp2&&)); ". Quotent decimal ABS("; LTRIM$(STR$(dp&&)); " - "; LTRIM$(STR$(dp2&&)); ") =";: COLOR 14: PRINT ABS(dp&& - dp2&&);: COLOR 11: PRINT "+ any adjustment.": COLOR 7
        dp&& = ABS(dp&& - dp2&&)

        IF betatest% THEN PRINT "Divisor 1st# = "; MID$(divisor$, 1, 1); "  Remainder 1st# = "; MID$(dividend$, 1, 1)

        ' Adjust decimal place for instances when divisor is larger than remainder the length of the divisor.
        j% = 0
        IF MID$(divisor$, 1, 1) > MID$(dividend$, 1, 1) THEN
            j% = 1
            IF betatest% THEN PRINT "Larger divisor, so move quotent decimal one place back to: ";: COLOR 14: PRINT LTRIM$(STR$(dp&&)): COLOR 7
        ELSEIF MID$(divisor$, 1, 1) = MID$(dividend$, 1, 1) THEN
            IF LEN(divisor$) = LEN(dividend$) THEN
                IF divisor$ > dividend$ THEN j% = 1
            ELSE
                IF LEN(divisor$) > LEN(dividend$) THEN
                    temp$ = dividend$ + STRING$(LEN(divisor$) - LEN(dividend$), "0")
                ELSE
                    temp$ = MID$(dividend$, 1, LEN(divisor$))
                END IF
                IF divisor$ > temp$ THEN j% = 1
            END IF
            IF betatest% THEN
                IF j% THEN PRINT "Larger divisor than dividend at LEN(divisor$), so move quotent decimal one place back to: ";: COLOR 14: PRINT LTRIM$(STR$(dp&&)): COLOR 7
                IF j% = 0 THEN PRINT "Smaller divisor than dividend at LEN(divisor$), so no quotent decimal place adjustment needed. Quotent decimal place = ";: COLOR 14: PRINT LTRIM$(STR$(dp&&)): COLOR 7
            END IF
        ELSE
            j% = 0
            IF betatest% THEN PRINT "Smaller divisor, so no quotent decimal place adjustment needed. Quotent decimal place = ";: COLOR 14: PRINT LTRIM$(STR$(dp&&)): COLOR 7
        END IF
        IF j% THEN dp&& = dp&& - div_decimal%

        origdividend$ = dividend$
        ' Determine length of divisor and dividend to begin initial long divison step.
        gl% = 2: sm_greater_lesser divisor$, MID$(dividend$, 1, LEN(divisor$)) + STRING$(LEN(divisor$) - LEN(dividend$), "0"), gl%
        divisor_ratio_dividend% = gl%
        IF gl% = 1 AND MID$(dividend$, 1, 1) <> "0" THEN
            dividend$ = MID$(dividend$, 1, LEN(divisor$) + 1) + STRING$(LEN(divisor$) + 1 - LEN(dividend$), "0")
        ELSE
            dividend$ = MID$(dividend$, 1, LEN(divisor$)) + STRING$(LEN(divisor$) - LEN(dividend$), "0")
        END IF

        ' Long divison loop. Mult and subtraction of dividend and remainder.
        k&& = 0
        IF betatest% THEN PRINT "Begin long divison loop..."
        DO
            SELECT CASE MID$(divisor$, 1, 1)
                CASE IS < MID$(dividend$, 1, 1)
                    adj_rem_len% = 0
                CASE IS = MID$(dividend$, 1, 1)
                    gl% = 2: sm_greater_lesser divisor$, MID$(dividend$, 1, LEN(divisor$)), gl%
                    IF gl% = 1 THEN adj_rem_len% = 1 ELSE adj_rem_len% = 0
                CASE IS > MID$(dividend$, 1, 1)
                    adj_rem_len% = 1
            END SELECT
            IF j2&& = 0 THEN j2&& = LEN(divisor$) + adj_rem_len%
            DO
                IF LEN(divisor$) > LEN(dividend$) THEN
                    w3&& = 0: runningtotal$ = dividend$: stringmathb$ = "0"
                    IF betatest% THEN PRINT: COLOR 3: PRINT "Divisor is larger so "; dividend$; " \ "; divisor$; " =";: COLOR 5: PRINT w3&&: COLOR 7
                    EXIT DO
                END IF
                IF LEN(divisor$) = LEN(dividend$) THEN
                    gl% = 2: sm_greater_lesser divisor$, dividend$, gl%
                    IF gl% = 1 THEN
                        w3&& = 0: runningtotal$ = dividend$: stringmathb$ = "0"
                        IF betatest% THEN COLOR 9: PRINT "Length of divisor is the same as remainder but remainder is smaller so w3&& = ";: COLOR 5: PRINT "0": COLOR 7
                        EXIT DO
                    END IF
                END IF
                SELECT CASE LEN(dividend$)
                    CASE IS > 2
                        w3&& = VAL(MID$(dividend$, 1, 2 + adj_rem_len%)) \ VAL(MID$(divisor$, 1, 2))
                        IF betatest% THEN PRINT MID$(dividend$, 1, 2 + adj_rem_len%); " \ "; MID$(divisor$, 1, 2); " =";
                    CASE ELSE
                        w3&& = VAL(MID$(dividend$, 1, 1 + adj_rem_len%)) \ VAL(MID$(divisor$, 1, 1))
                        IF betatest% THEN PRINT MID$(dividend$, 1, 1 + adj_rem_len%); " \ "; MID$(divisor$, 1, 1); " =";
                END SELECT
                IF betatest% THEN COLOR 5: PRINT " " + LTRIM$(STR$(w3&&));: COLOR 7: PRINT ". Begin mult est. at or one above this number."
                IF w3&& < 9 THEN w3&& = w3&& + 1 ELSE IF w3&& = 10 THEN w3&& = 9
                DO
                    stringmatha$ = divisor$: stringmathb$ = LTRIM$(STR$(w3&&))
                    runningtotal$ = sm_mult$(divisor$, LTRIM$(STR$(w3&&)))
                    gl% = 2: sm_greater_lesser runningtotal$, dividend$, gl%
                    IF gl% <= 0 OR w3&& = 0 THEN EXIT DO
                    IF betatest% THEN COLOR 8: PRINT "Mult loop:"; w3&&; "* "; divisor$; " = "; runningtotal$: COLOR 7
                    w3&& = w3&& - 1
                LOOP
                stringmatha$ = dividend$: stringmathb$ = runningtotal$
                sm_add_subtract_router dividend$, "-", stringmathb$, runningtotal$
                EXIT DO
            LOOP
            IF betatest% THEN PRINT LTRIM$(STR$(w3&&)); " * "; divisor$; " = "; stringmathb$; " | "; stringmatha$; " - "; stringmathb$; " = "; runningtotal$; " Remainder and drop-down = ";
            j2&& = j2&& + 1
            drop$ = "0": MID$(drop$, 1, 1) = MID$(origdividend$, j2&&, 1)
            IF runningtotal$ <> "0" THEN remainder$ = runningtotal$ ELSE remainder$ = ""
            dividend$ = remainder$ + drop$
            w3$ = LTRIM$(STR$(w3&&))
            temp$ = ""
            IF div_decimal% = -1 THEN
                IF dp&& AND k&& = 0 THEN
                    q$ = q$ + "." + STRING$(dp&& - 1, "0")
                    IF w3&& = 0 THEN w3$ = ""
                END IF
            END IF
            IF div_decimal% >= 0 THEN
                IF dp&& = k&& THEN
                    temp$ = "."
                END IF
            END IF
            q$ = q$ + w3$ + temp$
            IF betatest% AND remainder$ = "" THEN betatemp$ = CHR$(34) + CHR$(34) ELSE IF betatest% THEN betatemp$ = remainder$
            IF betatest% AND MID$(origdividend$, j2&&, 1) = "" THEN betatemp2$ = CHR$(34) + CHR$(34) ELSE IF betatest% THEN betatemp2$ = MID$(origdividend$, j2&&, 1)
            IF betatest% THEN PRINT dividend$; " ("; betatemp$; " +  "; drop$; ") at:"; j2&&; "of "; origdividend$; "  Loop"; k&& + 1; "Quotent = ";: COLOR 14, 4: PRINT q$;: COLOR 7, 0: PRINT: SLEEP
            ' Check to terminate
            IF div_decimal% = -1 THEN
                ' Decimal to left.
                IF remainder$ = "" AND MID$(origdividend$, j2&&, 1) = "" OR LEN(q$) >= limit&& THEN EXIT DO
            ELSE
                ' Decimal to right.
                IF remainder$ = "" AND MID$(origdividend$, j2&&, 1) = "" AND k&& >= dp&& OR LEN(q$) >= limit&& THEN EXIT DO
            END IF

            IF INKEY$ = " " THEN EXIT DO
            k&& = k&& + 1
        LOOP
        EXIT DO
    LOOP
    IF RIGHT$(q$, 1) = "." AND divisor$ <> "0" THEN runningtotal$ = MID$(q$, 1, LEN(q$) - 1) ELSE runningtotal$ = q$
    sm_div$ = runningtotal$
    stringmatha$ = hold_stringmatha$: stringmathb$ = hold_stringmathb$
END FUNCTION

SUB greatest_common_factor (gfca$, gfcb$)
    IF betatest% THEN PRINT "Pre-GFC "; gfca$; " / "; gfcb$
    numerator$ = gfca$: denominator$ = gfcb$
    ' Make both numbers positive.
    IF MID$(gfca$, 1, 1) = "-" THEN gfca$ = MID$(gfca$, 2)
    IF MID$(gfcb$, 1, 1) = "-" THEN gfcb$ = MID$(gfcb$, 2)

    CALL sm_greater_lesser(gfca$, gfcb$, gl%)
    IF gl% THEN SWAP gfca$, gfcb$

    DO
        stringmatha$ = gfca$: stringmathb$ = gfcb$
        runningtotal$ = sm_div$(stringmatha$, stringmathb$)
        IF INSTR(runningtotal$, ".") THEN runningtotal$ = MID$(runningtotal$, 1, INSTR(runningtotal$, ".") - 1)
        stringmatha$ = runningtotal$: stringmathb$ = gfcb$
        runningtotal$ = sm_mult$(stringmatha$, stringmathb$)
        stringmatha$ = gfca$: stringmathb$ = runningtotal$
        runningtotal$ = sm_sub$(stringmatha$, stringmathb$)
        SWAP gfca$, gfcb$: gfcb$ = runningtotal$
        IF runningtotal$ = "0" THEN EXIT DO
    LOOP

    stringmatha$ = numerator$: stringmathb$ = gfca$
    IF betatest% THEN PRINT "GFC = "; gfca$
    numerator$ = sm_div$(stringmatha$, stringmathb$)
    stringmatha$ = denominator$: stringmathb$ = gfca$
    denominator$ = sm_div$(stringmatha$, stringmathb$)
    gfca$ = numerator$: gfcb$ = denominator$ ' Needed to pass back.
    IF betatest% THEN PRINT "Fraction: "; numerator$; " / "; denominator$
END SUB

Wat I like is this format reduces fractions, which helps eliminates some rounding errors. For example, if the computation requires something like find the .2 root of 6, well,  2/10 root of 6 would be square root of 6 = 2.449489742783178 ^ 10 = 7,775.9999999999968826892081723528 whereas reducing 2/10 to 1/5 leaves us with 6^5 = 7,776.

Again, to solve for the discrepancy if reducing the fraction is not possible, or just doesn't matter, means I would have to get numbers lik the square root of 6 in either enough digits to reach the terminating decimal or convert the remainder and digits calculated to a fraction. So yes, Virginia, there is a Santa Clause, and I'd bet he'd rather shove his fat ascii down chimneys all night than mess with stuff.


Pete

EDIT: Screwy forum didn't register post contents.

Print this item

  b+ String Math Update
Posted by: bplus - 09-26-2022, 06:01 PM - Forum: Works in Progress - Replies (11)

I have Square Root worked out better faster and accurate to any decimal places (currently set 100) and conversions Dec2Bin$ strings and Bin2Dec$, still working on Real Number Power$

Dec2Bin$ and Bin2Dec$ don't work like bit math for negative values but like decimal numbers ie a minus sign says it's negative and no sign means it's positive. There is no checking if the test$ binary you enter is just 1's and zero's so don't test that and say it's not working. So to test -8.375 try -1000.011

Code: (Select All)
Option _Explicit
_Title "String Math Powers 2022-09-22" ' b+ try to do powers with string math
' directly from "String Math 2021-06-14" ' b+ from SM2 (2021 June) a bunch of experiments to fix and improve speeds.
' June 2021 fix some old String Math procedures, better nInverse with new LT frunction, remove experimental procedures.
' Now with decent sqrRoot it works independent of Mr$() = Math Regulator that handles signs and decimals and calls to
' add$(), subtr$, mult$, divide$ (100 significant digits),  add$(), subtr$, mult$ are exact!
' If you need higher precsion divide, I recommend use nInverse on denominator (integer)
' then add sign and decimal and mult$() that number with numerator to get divsion answer in higher precision than 100.
' (See how Mr$() handles division and just call nInverse$ with what precision you need.)
' The final function showDP$() is for displaying these number to a set amount of Decimal Places.

' The main code is sampler of tests performed with these functions.
' 2022-09-22 a little fix to MR$ for Function change versions QB64 v2.0+
' Attempt to do Powers with SQRs of 2 Multipliers
' needs to be able to convert a number into a binary String
' might also need a Table setup for nested SQR's of 2
' needs a decent BigSQR$ string function for SQR
' 2022-09-25 this is one frustration after another LT does not work for strings??? but < does?
' try some more with BigSQR concentrate on Integer part first, just get that right
' 2022-09-26 Bin2Dec$ Function seems OK

$Console:Only

Randomize Timer

'Dim As Double i ' testing Dec2Bin$
'Dim p2$, x$, sum$
'p2$ = "1"
'For i = 1 To 50
'    p2$ = mr$(p2$, "/", "2")
'    x$ = mr$(x$, "+", "1")
'    sum$ = mr$(x$, "+", p2$)
'    Print sum$, Dec2Bin$(sum$)
'    'Sleep
'Next
'Print: Print " Square Roots:"
'Dim b$, intger$
'For i = 1 To 50
'    b$ = Str$(i + 1 / (2 ^ i))
'    Print b$, bigSQR$(b$)
'Next
'intger$ = "10000000000000000000000000000000000000000000000000000000000000000"
'Print: Print "Bonus SQR of "; intger$; " Len  = "; Len(intger$); " is:"
'b$ = bigSQR$(intger$)
'Print b$, " Len Integer Part ="; Len(Mid$(b$, 1, InStr(b$, ".") - 1))
'intger$ = "100000000000000000000000000000000000000000000000000000000000000000"
'Print: Print "Bonus SQR of "; intger$; " Len = "; Len(intger$); " is:"
'b$ = bigSQR$(intger$)
'Print b$, " Len Integer Part ="; Len(Mid$(b$, 1, InStr(b$, ".") - 1))
'Print: Print " Square Roots:"

'  ============ For comparison this was the old routine
'Print: Print "Square Roots the old way of estimation:"
'For i = 1 To 50
'    b$ = Str$(i + 1 / (2 ^ i))
'    Print b$, sqrRoot$(b$)
'Next
'intger$ = "10000000000000000000000000000000000000000000000000000000000000000"
'Print: Print "Bonus SQR of "; intger$; " Len  = "; Len(intger$); " is:"
'b$ = sqrRoot$(intger$)
'Print b$, " Len Integer Part ="; Len(b$)
'intger$ = "100000000000000000000000000000000000000000000000000000000000000000"
'Print: Print "Bonus SQR of "; intger$; " Len = "; Len(intger$); " is:"
'b$ = sqrRoot$(intger$)
'Print b$, " Len Integer Part ="; Len(Mid$(b$, 1, InStr(b$, ".") - 1))
' ============================================================================

' OK now test the new Power$ routine
'Print power$("5", ".333333333333333333333333333333333") ' 2     ' no this ain't work in well at all
Dim test$, ans$
Do
    Input "Enter a Binary with/without - sgn or decimal "; test$
    ans$ = Bin2Dec$(test$)
    Print "Decimal is: "; ans$
    Print "Check conversion back: "; Dec2Bin$(ans$)
Loop Until test$ = ""

' x to the power of pow
Function power$ (xx$, pow$) '                    so far this sucks, decimal is lost and digits only good for about 10 places 10% of dp in SQR(2)'s
    Dim build$, ip$, fp$, x$, bs$, runningXSQR$
    Dim As Long dot, i
    x$ = _Trim$(xx$)
    dot = InStr(pow$, ".")
    If dot Then
        ip$ = Mid$(pow$, 1, dot - 1)
        fp$ = Mid$(pow$, dot) ' keep dot
    Else
        ip$ = pow$
        fp$ = ""
    End If
    'integer part or power
    build$ = "1"
    If ip$ <> "" Then
        While LTE("0", ip$)
            build$ = mr$(build$, "*", x$)
            ip$ = mr$(ip$, "-", "1")
        Wend
    End If
    If fp$ = "" Or fp$ = "." Then power$ = build$: Exit Function
    build$ = build$ + "."
    'now for the fraction part convert decimal to Binary
    bs$ = Dec2Bin$(fp$)
    'at moment we haven't taken any sqr of x
    runningXSQR$ = mr$(x$, "*", x$)
    'run through all the 0's and 1's in the bianry expansion of the fraction part of the power float
    For i = 1 To Len(bs$)
        'this is the matching sqr of the sqr of the sqr... of x
        runningXSQR$ = bigSQR$(runningXSQR$)
        'for every 1 in the expansion, multiple our build with the running sqr of ... sqr of x
        If Mid$(bs$, i, 1) = "1" Then build$ = mr$(build$, "*", runningXSQR$)
    Next
    'our build should be a estimate or x to power of pow
    power$ = build$
End Function

Function Bin2Dec$ (bn$) ' bn$ is binary string number with possible neg sign and decimal
    Dim b$, sgn$, ip$, fp$, p2$, build$
    Dim As Long dot, i
    b$ = _Trim$(bn$)
    If Left$(b$, 1) = "-" Then sgn$ = "-": b$ = Mid$(b$, 2) Else sgn$ = ""
    dot = InStr(b$, ".")
    If dot Then
        ip$ = Mid$(b$, 1, dot - 1)
        fp$ = Mid$(b$, dot + 1)
    Else
        ip$ = b$
        fp$ = ""
    End If
    p2$ = "1"
    For i = Len(ip$) To 1 Step -1
        If Mid$(ip$, i, 1) = "1" Then build$ = mr$(build$, "+", p2$)
        p2$ = mr$(p2$, "*", "2")
    Next
    If fp$ <> "" Then
        build$ = build$ + "."
        p2$ = "1"
        For i = 1 To Len(fp$)
            p2$ = mr$(p2$, "/", "2")
            If Mid$(fp$, i, 1) = "1" Then build$ = mr$(build$, "+", p2$)
        Next
    End If
    Bin2Dec$ = sgn$ + build$
End Function


Function bigSQR$ (number$)
    Dim ip$, fp$, n$, calc$, remainder$, new$, test$
    Dim As Long dot, dp, i, pulldown, cal, digit, maxDec
    maxDec = 100

    ' divide number into integer part, ip$ and fraction part, fp$  , figure decimal places to left of decimal then even up front and back
    dot = InStr(number$, ".")
    If dot Then
        ip$ = _Trim$(Mid$(number$, 1, dot - 1))
        fp$ = Left$(_Trim$(Mid$(number$, dot + 1)) + String$(2 * maxDec, "0"), 2 * maxDec)
    Else
        ip$ = _Trim$(number$)
        If Len(ip$) Mod 2 = 1 Then ip$ = "0" + ip$
        fp$ = String$(2 * maxDec, "0")
    End If
    dp = Int((Len(ip$) + 1) / 2)
    If Len(ip$) Mod 2 = 1 Then ip$ = "0" + ip$
    n$ = ip$ + fp$
    For i = 1 To Len(n$) Step 2
        pulldown = Val(Mid$(n$, i, 2))
        If i = 1 Then
            cal = Int(Sqr(pulldown))
            remainder$ = _Trim$(Str$(pulldown - cal * cal))
            calc$ = _Trim$(Str$(cal))
        Else
            new$ = mr$("100", "*", remainder$)
            new$ = mr$(new$, "+", _Trim$(Str$(pulldown)))
            For digit = 9 To 0 Step -1
                'test$ = (20 * Val(calc$) + digit) * digit
                test$ = mr$("20", "*", calc$)
                test$ = mr$(test$, "+", _Trim$(Str$(digit)))
                test$ = mr$(test$, "*", _Trim$(Str$(digit)))
                If LTE(test$, new$) Then Exit For
            Next
            calc$ = calc$ + _Trim$(Str$(digit))
            remainder$ = mr$(new$, "-", test$)
        End If
    Next
    If dp Then
        calc$ = Mid$(calc$, 1, dp) + "." + Mid$(calc$, dp + 1)
    Else
        calc$ = "." + calc$
    End If
    bigSQR$ = calc$
End Function

' New stuff
Function Dec2Bin$ (Dec$)
    Dim sgn$, d$, ip$, fp$, b$, tp$
    Dim As Long dot, c
    If _Trim$(Left$(Dec$, 1)) = "-" Then
        sgn$ = "-": d$ = Mid$(_Trim$(Dec$), 2)
    Else
        sgn$ = "": d$ = _Trim$(Dec$)
    End If
    dot = InStr(d$, ".")
    If dot Then
        ip$ = Mid$(d$, 1, dot - 1): fp$ = Mid$(d$, dot)
    Else ' all integer
        ip$ = d$: fp$ = "."
    End If
    tp$ = "2"
    If LTE(tp$, ip$) Then
        While LTE(tp$, ip$)
            tp$ = mr$(tp$, "*", "2")
        Wend
    End If
    While LT("1", tp$)
        tp$ = mr$(tp$, "/", "2")
        If LTE(tp$, "1") Then b$ = b$ + ip$: Exit While
        If LT(ip$, tp$) Then
            b$ = b$ + "0"
        Else
            b$ = b$ + "1"
            ip$ = mr$(ip$, "-", tp$)
        End If
    Wend
    b$ = b$ + "." ' cross over point to fractions
    tp$ = "1"
    'Print "start fp$ "; fp$
    While c < 200 'And LT("0", fp$)
        tp$ = mr$(tp$, "/", "2")
        'If LT(fp$, tp$) Then ' for some reason LT is not working but < is
        If fp$ < tp$ Then ' for some reason LT is not working but < is
            b$ = b$ + "0"
        Else
            b$ = b$ + "1"
            fp$ = mr$(fp$, "-", tp$)
            If LTE(fp$, "0") Then Exit While
        End If
        c = c + 1
    Wend
    Dec2Bin$ = sgn$ + b$ ' b$ = build of 0,1 and .
End Function


' 2022-09-25 Use BigSQR$ it's way faster, no estimating!
' ==  String Math 2021-06-14 Procedure start here (aprox 412 LOC for copy/paste into your app) ==
Function sqrRoot$ (nmbr$)
    Dim n$, guess$, lastGuess$, other$, sum$, imaginary$, loopcnt
    If Left$(nmbr$, 1) = "-" Then 'handle neg numbers
        imaginary$ = "*i": n$ = Mid$(nmbr$, 2)
    Else
        imaginary$ = "": n$ = nmbr$
    End If
    guess$ = mr$(n$, "/", "2")
    other$ = n$
    Do
        loopcnt = loopcnt + 1
        If (Mid$(guess$, 1, 105) = Mid$(lastGuess$, 1, 105)) Then
            ' go past 100 matching digits for 100 digit precision
            sqrRoot$ = Mid$(other$, 1, 101) + imaginary$
            ' try other factor for guess$  sometimes it nails answer without all digits
            Exit Function
        Else
            lastGuess$ = guess$
            sum$ = mr$(guess$, "+", other$)
            guess$ = mr$(sum$, "/", "2")
            other$ = mr$(n$, "/", guess$)
        End If
    Loop
End Function

Function add$ (a$, b$) 'add 2 positive integers assume a and b are just numbers no - signs
    'set a and b numbers to same length and multiple of 18 so can take 18 digits at a time
    Dim As Long la, lb, m, g
    Dim sa As _Unsigned _Integer64, sb As _Unsigned _Integer64, co As _Unsigned _Integer64
    Dim fa$, fb$, t$, new$, result$
    la = Len(a$): lb = Len(b$)
    If la > lb Then m = Int(la / 18) + 1 Else m = Int(lb / 18) + 1
    fa$ = Right$(String$(m * 18, "0") + a$, m * 18)
    fb$ = Right$(String$(m * 18, "0") + b$, m * 18)

    'now taking 18 digits at a time Thanks Steve McNeill
    For g = 1 To m
        sa = Val(Mid$(fa$, (m - g) * 18 + 1, 18))
        sb = Val(Mid$(fb$, (m - g) * 18 + 1, 18))
        t$ = Right$(String$(36, "0") + _Trim$(Str$(sa + sb + co)), 36)
        co = Val(Mid$(t$, 1, 18))
        new$ = Mid$(t$, 19)
        result$ = new$ + result$
    Next
    If co Then result$ = Str$(co) + result$
    add$ = result$
End Function

' This is used in nInverse$ not by Mr$ because there it saves time!
Function subtr1$ (a$, b$)
    Dim As Long la, lb, lResult, i, ca, cb, w
    Dim result$, fa$, fb$

    la = Len(a$): lb = Len(b$)
    If la > lb Then lResult = la Else lResult = lb
    result$ = Space$(lResult)
    fa$ = result$: fb$ = result$
    Mid$(fa$, lResult - la + 1) = a$
    Mid$(fb$, lResult - lb + 1) = b$
    For i = lResult To 1 Step -1
        ca = Val(Mid$(fa$, i, 1))
        cb = Val(Mid$(fb$, i, 1))
        If cb > ca Then ' borrow 10
            Mid$(result$, i, 1) = Right$(Str$(10 + ca - cb), 1)
            w = i - 1
            While w > 0 And Mid$(fa$, w, 1) = "0"
                Mid$(fa$, w, 1) = "9"
                w = w - 1
            Wend
            Mid$(fa$, w, 1) = Right$(Str$(Val(Mid$(fa$, w, 1)) - 1), 1)
        Else
            Mid$(result$, i, 1) = Right$(Str$(ca - cb), 1)
        End If
    Next
    subtr1$ = result$
End Function

' 2021-06-08 fix up with new mr call that decides the sign and puts the greater number first
Function subtr$ (sum$, minus$) ' assume both numbers are positive all digits
    Dim As Long m, g, p
    Dim VB As _Unsigned _Integer64, vs As _Unsigned _Integer64, tenE18 As _Unsigned _Integer64
    Dim ts$, tm$, sign$, LG$, sm$, t$, result$

    ts$ = _Trim$(sum$): tm$ = _Trim$(minus$) ' fixed subtr$ 2021-06-05
    If trim0(ts$) = trim0$(tm$) Then subtr$ = "0": Exit Function 'proceed knowing not equal
    tenE18 = 1000000000000000000 'yes!!! no dang E's
    sign$ = ""
    m = Int(Len(ts$) / 18) + 1
    LG$ = Right$(String$(m * 18, "0") + ts$, m * 18)
    sm$ = Right$(String$(m * 18, "0") + tm$, m * 18)

    'now taking 18 digits at a time From Steve I learned we can do more than 1 digit at a time
    For g = 1 To m
        VB = Val(Mid$(LG$, m * 18 - g * 18 + 1, 18))
        vs = Val(Mid$(sm$, m * 18 - g * 18 + 1, 18))
        If vs > VB Then
            t$ = Right$(String$(18, "0") + _Trim$(Str$(tenE18 - vs + VB)), 18)
            p = (m - g) * 18
            While p > 0 And Mid$(LG$, p, 1) = "0"
                Mid$(LG$, p, 1) = "9"
                p = p - 1
            Wend
            If p > 0 Then Mid$(LG$, p, 1) = _Trim$(Str$(Val(Mid$(LG$, p, 1)) - 1))
        Else
            t$ = Right$(String$(18, "0") + _Trim$(Str$(VB - vs)), 18)
        End If
        result$ = t$ + result$
    Next
    subtr$ = result$
End Function

Function TrimLead0$ (s$) 'for treating strings as number (pos integers)
    Dim copys$
    Dim As Long i, find
    copys$ = _Trim$(s$) 'might as well remove spaces too
    i = 1: find = 0
    While i < Len(copys$) And Mid$(copys$, i, 1) = "0"
        i = i + 1: find = 1
    Wend
    If find = 1 Then copys$ = Mid$(copys$, i)
    If copys$ = "" Then TrimLead0$ = "0" Else TrimLead0$ = copys$
End Function

' catchy? mr$ for math regulator  cop$ = " + - * / " 1 of 4 basic arithmetics
' Fixed so that add and subtract have signs calc'd in Mr and correct call to add or subtract made
' with bigger minus smaller in subtr$() call
Function mr$ (a$, cop$, b$)
    Dim op$, ca$, cb$, aSgn$, bSgn$, postOp$, sgn$, rtn$
    Dim As Long adp, bdp, dp, lpop, aLTb

    op$ = _Trim$(cop$) 'save fixing each time
    ca$ = _Trim$(a$): cb$ = _Trim$(b$) 'make copies in case we change
    'strip signs and decimals
    If Left$(ca$, 1) = "-" Then
        aSgn$ = "-": ca$ = Mid$(ca$, 2)
    Else
        aSgn$ = ""
    End If
    dp = InStr(ca$, ".")
    If dp > 0 Then
        adp = Len(ca$) - dp
        ca$ = Mid$(ca$, 1, dp - 1) + Mid$(ca$, dp + 1)
    Else
        adp = 0
    End If
    If Left$(cb$, 1) = "-" Then
        bSgn$ = "-": cb$ = Mid$(cb$, 2)
    Else
        bSgn$ = ""
    End If
    dp = InStr(cb$, ".")
    If dp > 0 Then
        bdp = Len(cb$) - dp
        cb$ = Mid$(cb$, 1, dp - 1) + Mid$(cb$, dp + 1)
    Else
        bdp = 0
    End If
    If op$ = "+" Or op$ = "-" Or op$ = "/" Then 'add or subtr  even up strings on right of decimal
        'even up the right sides of decimals if any
        If adp > bdp Then dp = adp Else dp = bdp
        If adp < dp Then ca$ = ca$ + String$(dp - adp, "0")
        If bdp < dp Then cb$ = cb$ + String$(dp - bdp, "0")
    ElseIf op$ = "*" Then
        dp = adp + bdp
    End If
    If op$ = "*" Or op$ = "/" Then
        If aSgn$ = bSgn$ Then sgn$ = "" Else sgn$ = "-"
    End If

    'now according to signs and op$ call add$ or subtr$
    If op$ = "-" Then ' make it adding according to signs because that is done for + next!
        If bSgn$ = "-" Then bSgn$ = "" Else bSgn$ = "-" ' flip bSgn$ with op$
        op$ = "+" ' turn this over to + op already done! below
    End If
    If op$ = "+" Then
        If aSgn$ = bSgn$ Then 'really add
            postOp$ = add$(ca$, cb$)
            sgn$ = aSgn$
        ElseIf aSgn$ <> bSgn$ Then 'have a case of subtraction
            'but which is first and which is 2nd and should final sign be pos or neg
            If TrimLead0$(ca$) = TrimLead0(cb$) Then 'remove case a = b
                mr$ = "0": Exit Function
            Else
                aLTb = LTE(ca$, cb$)
                If aSgn$ = "-" Then
                    If aLTb Then ' b - a = pos
                        postOp$ = subtr$(cb$, ca$)
                        sgn$ = ""
                    Else '  a > b so a - sgn wins  - (a - b)
                        postOp$ = subtr$(ca$, cb$)
                        sgn$ = "-"
                    End If
                Else ' b has the - sgn
                    If aLTb Then ' result is -
                        postOp$ = subtr$(cb$, ca$)
                        sgn$ = "-"
                    Else ' result is pos
                        postOp$ = subtr$(ca$, cb$)
                        sgn$ = ""
                    End If
                End If
            End If
        End If
    ElseIf op$ = "*" Then
        postOp$ = mult$(ca$, cb$)
    ElseIf op$ = "/" Then
        postOp$ = divide$(ca$, cb$)
    End If ' which op
    If op$ <> "/" Then 'put dp back
        lpop = Len(postOp$) ' put decimal back if there is non zero stuff following it
        If Len(Mid$(postOp$, lpop - dp + 1)) Then ' fix 1 extra dot appearing in 10000! ?!
            If TrimLead0$(Mid$(postOp$, lpop - dp + 1)) <> "0" Then '  .0   or .00 or .000  ??
                postOp$ = Mid$(postOp$, 1, lpop - dp) + "." + Mid$(postOp$, lpop - dp + 1)
            End If
        End If
    End If
    rtn$ = trim0$(postOp$) 'trim lead 0's then tack on sign
    If rtn$ <> "0" Then mr$ = sgn$ + rtn$ Else mr$ = rtn$
End Function

Function divide$ (n$, d$) ' goal here is 100 digits precision not 100 digits past decimal
    Dim di$, ndi$
    Dim As Long nD
    If n$ = "0" Then divide$ = "0": Exit Function
    If d$ = "0" Then divide$ = "div 0": Exit Function
    If d$ = "1" Then divide$ = n$: Exit Function

    ' aha! found a bug when d$ gets really huge 100 is no where near enough!!!!
    ' 2021-06-03 fix by adding 100 to len(d$), plus have to go a little past 100 like 200
    di$ = Mid$(nInverse$(d$, Len(d$) + 200), 2) 'chop off decimal point after
    nD = Len(di$)
    ndi$ = mult$(n$, di$)
    ndi$ = Mid$(ndi$, 1, Len(ndi$) - nD) + "." + Right$(String$(nD, "0") + Right$(ndi$, nD), nD)
    divide$ = ndi$
End Function

' This uses Subtr1$ is Positive Integer only!
' DP = Decimal places = says when to quit if don't find perfect divisor before
Function nInverse$ (n$, DP As Long) 'assume decimal at very start of the string of digits returned
    Dim m$(1 To 9), si$, r$, outstr$, d$
    Dim i As Long
    For i = 1 To 9
        si$ = _Trim$(Str$(i))
        m$(i) = mult$(si$, n$)
    Next
    outstr$ = ""
    If n$ = "0" Then nInverse$ = "Div 0": Exit Function
    If n$ = "1" Then nInverse$ = "1": Exit Function
    outstr$ = "." 'everything else n > 1 is decimal 8/17
    r$ = "10"
    Do
        While LT(r$, n$) ' 2021-06-08 this should be strictly Less Than
            outstr$ = outstr$ + "0" '            add 0 to the  output string
            If Len(outstr$) = DP + 1 Then nInverse$ = outstr$: Exit Function 'DP length?
            r$ = r$ + "0"
        Wend
        For i = 9 To 1 Step -1
            If LTE(m$(i), r$) Then d$ = _Trim$(Str$(i)): Exit For
        Next
        outstr$ = outstr$ + d$
        If Len(outstr$) = DP + 1 Then nInverse$ = outstr$: Exit Function
        r$ = subtr1$(r$, mult$(d$, n$)) 'r = r -d*n    ' 2021-06-08 subtr1 works faster
        If TrimLead0$(r$) = "0" Then nInverse$ = outstr$: Exit Function ' add trimlead0$ 6/08
        r$ = r$ + "0" 'add another place
    Loop
End Function

Function mult$ (a$, b$) 'assume both positive integers prechecked as all digits strings
    Dim As Long la, lb, m, g, dp
    Dim As _Unsigned _Integer64 v18, sd, co
    Dim f18$, f1$, t$, build$, accum$

    If a$ = "0" Then mult$ = "0": Exit Function
    If b$ = "0" Then mult$ = "0": Exit Function
    If a$ = "1" Then mult$ = b$: Exit Function
    If b$ = "1" Then mult$ = a$: Exit Function
    'find the longer number and make it a mult of 18 to take 18 digits at a time from it
    la = Len(a$): lb = Len(b$)
    If la > lb Then
        m = Int(la / 18) + 1
        f18$ = Right$(String$(m * 18, "0") + a$, m * 18)
        f1$ = b$
    Else
        m = Int(lb / 18) + 1
        f18$ = Right$(String$(m * 18, "0") + b$, m * 18)
        f1$ = a$
    End If
    For dp = Len(f1$) To 1 Step -1 'dp = digit position of the f1$
        build$ = "" 'line builder
        co = 0
        'now taking 18 digits at a time Thanks Steve McNeill
        For g = 1 To m
            v18 = Val(Mid$(f18$, (m - g) * 18 + 1, 18))
            sd = Val(Mid$(f1$, dp, 1))
            t$ = Right$(String$(19, "0") + _Trim$(Str$(v18 * sd + co)), 19)
            co = Val(Mid$(t$, 1, 1))
            build$ = Mid$(t$, 2) + build$
        Next g
        If co Then build$ = _Trim$(Str$(co)) + build$
        If dp = Len(f1$) Then
            accum$ = build$
        Else
            accum$ = add$(accum$, build$ + String$(Len(f1$) - dp, "0"))
        End If
    Next dp
    mult$ = accum$
End Function

'this function needs TrimLead0$(s$)   ' dang I can't remember if a$ and b$ can have decimals or not
Function LTE (a$, b$) ' a$ Less Than or Equal b$  comparison of 2 strings
    Dim ca$, cb$
    Dim As Long la, lb, i
    ca$ = TrimLead0$(a$): cb$ = TrimLead0(b$)
    la = Len(ca$): lb = Len(cb$)
    If ca$ = cb$ Then
        LTE = -1
    ElseIf la < lb Then ' a is smaller
        LTE = -1
    ElseIf la > lb Then ' a is bigger
        LTE = 0
    ElseIf la = lb Then ' equal lengths
        For i = 1 To Len(ca$)
            If Val(Mid$(ca$, i, 1)) > Val(Mid$(cb$, i, 1)) Then
                LTE = 0: Exit Function
            ElseIf Val(Mid$(ca$, i, 1)) < Val(Mid$(cb$, i, 1)) Then
                LTE = -1: Exit Function
            End If
        Next
    End If
End Function

'need this for ninverse faster than subtr$ for sign
Function LT (a$, b$) ' a$ Less Than or Equal b$  comparison of 2 strings
    Dim ca$, cb$
    Dim As Long la, lb, i
    ca$ = TrimLead0$(a$): cb$ = TrimLead0(b$)
    la = Len(ca$): lb = Len(cb$)
    If la < lb Then ' a is smaller
        LT = -1
    ElseIf la > lb Then ' a is bigger
        LT = 0
    ElseIf la = lb Then ' equal lengths
        For i = 1 To Len(ca$)
            If Val(Mid$(ca$, i, 1)) > Val(Mid$(cb$, i, 1)) Then
                LT = 0: Exit Function
            ElseIf Val(Mid$(ca$, i, 1)) < Val(Mid$(cb$, i, 1)) Then
                LT = -1: Exit Function
            End If
        Next
    End If
End Function

Function TrimTail0$ (s$)
    Dim copys$
    Dim As Long dp, i, find
    copys$ = _Trim$(s$) 'might as well remove spaces too
    TrimTail0$ = copys$
    dp = InStr(copys$, ".")
    If dp > 0 Then
        i = Len(copys$): find = 0
        While i > dp And Mid$(copys$, i, 1) = "0"
            i = i - 1: find = 1
        Wend
        If find = 1 Then
            If i = dp Then
                TrimTail0$ = Mid$(copys$, 1, dp - 1)
            Else
                TrimTail0$ = Mid$(copys$, 1, i)
            End If
        End If
    End If
End Function

Function trim0$ (s$)
    Dim cs$, si$
    cs$ = s$
    si$ = Left$(cs$, 1)
    If si$ = "-" Then cs$ = Mid$(cs$, 2)
    cs$ = TrimLead0$(cs$)
    cs$ = TrimTail0$(cs$)
    If Right$(cs$, 1) = "." Then cs$ = Mid$(cs$, 1, Len(cs$) - 1)
    If si$ = "-" Then trim0$ = si$ + cs$ Else trim0$ = cs$
End Function

' for displaying truncated numbers say to 60 digits
Function showDP$ (num$, nDP As Long)
    Dim cNum$
    Dim As Long dp, d, i
    cNum$ = num$ 'since num$ could get changed
    showDP$ = num$
    dp = InStr(num$, ".")
    If dp > 0 Then
        If Len(Mid$(cNum$, dp + 1)) > nDP Then
            d = Val(Mid$(cNum$, dp + nDP + 1, 1))
            If d > 4 Then
                cNum$ = "0" + cNum$ ' tack on another 0 just in case 9's all the way to left
                dp = dp + 1
                i = dp + nDP
                While Mid$(cNum$, i, 1) = "9" Or Mid$(cNum$, i, 1) = "."
                    If Mid$(cNum$, i, 1) = "9" Then
                        Mid$(cNum$, i, 1) = "0"
                    End If
                    i = i - 1
                Wend
                Mid$(cNum$, i, 1) = _Trim$(Str$(Val(Mid$(cNum$, i, 1)) + 1)) 'last non 9 digit
                cNum$ = Mid$(cNum$, 1, dp + nDP) 'chop it
                showDP$ = trim0$(cNum$)
            Else
                showDP$ = Mid$(cNum$, 1, dp + nDP)
            End If
        End If
    End If
End Function

Print this item

  Wandering In The Cave
Posted by: James D Jarvis - 09-26-2022, 05:08 PM - Forum: Works in Progress - Replies (14)

Wandering In The Cave
A simple cave escape game. Navigate to the exit to escape and win. Watch out for lava, exposure, and toxic slime.

EDIT added functionality to game, see latest post.


Code: (Select All)
'wandering in the cave
'By James D. Jarvis   sept 26,2022
_Title "Wandering In The Cave v0.4"
'use the number keys of  W,S,A,D to find the exit
'press 5 or .  to rest briefly
'
' this is a work in progress and may generate an impossible starting position
'
_Define K As _UNSIGNED LONG
Dim Shared kk, kblack, kfloor, krock, kwater, kslime, klava, krubble, kcrystal, kexit
Dim Shared cave(24, 6), caverunlimit, lightradius
Dim Shared phealth, pstamina, pwounds, ptemp, ppx, ppy, lastx, lasty
Dim cmap As _Unsigned Long
Dim ms As _Unsigned Long
cmap = _NewImage(800, 800, 32)
ms = _NewImage(800, 500, 32)
Screen ms
Print "Wandering In The Cave v0.4"
Print "By James D. Jarvis"
Print
Print "You must escape the cave."
Print
Print "Navigate with the numberpad or WASD"
Print "press any key to start and get a preview of the cave map"
Print "press spacebar after that to start your wandering."
any$ = Input$(1)
Screen cmap
_FullScreen _SquarePixels
Const csx = 1, csy = 2, ctx = 3, cty = 4, cmx = 5, cmy = 6
kfloor = _RGB32(200, 180, 160): kwater = _RGB32(10, 30, 240)
krock = _RGB32(40, 30, 20): kslime = _RGB32(20, 240, 100): klava = _RGB32(200, 5, 5)
krubble = _RGB32(80, 80, 80): kcrystal = _RGB32(250, 250, 0): kexit = _RGB32(255, 0, 255)
Randomize Timer
check$ = "off"
caverunlimit = 500
Do
    _Limit 10
    restartcaves:
    Line (0, 0)-(_Width, _Height), krock, BF
    cave(1, csx) = Int(100 + Rnd * 600)
    cave(1, csy) = Int(100 + Rnd * 600)
    Do
        cave(1, ctx) = Int(100 + Rnd * 600)
        cave(1, cty) = Int(100 + Rnd * 600)
        dx = Abs(cave(1, csx) - cave(1, ctx))
        dy = Abs(cave(1, csy) - cave(1, cty))
        dl = Sqr(dx * dx + dy * dy)
    Loop Until dy > 20 And dx > 20

    cave(1, cmx) = Int((cave(1, csx) + cave(1, ctx)) / 2 + (10 + Rnd * 50) - (10 + Rnd * 50))
    cave(1, cmy) = Int((cave(1, csy) + cave(1, cty)) / 2 + (10 + Rnd * 50) - (10 + Rnd * 50))
    For c = 2 To 24

        Select Case Int(1 + Rnd * 8)
            Case 1, 2, 3
                cave(c, csx) = cave(c - 1, csx)
                cave(c, csy) = cave(c - 1, csy)

            Case 4, 5
                cave(c, csx) = cave(c - 1, cmx)
                cave(c, csy) = cave(c - 1, cmy)

            Case 6, 7, 8
                cave(c, csx) = cave(c - 1, ctx)
                cave(c, csy) = cave(c - 1, cty)
        End Select
        cpl = 0
        Do

            Select Case Int(1 + Rnd * 6)
                Case 1, 2, 3
                    cave(c, ctx) = Int(100 + Rnd * 600)
                    cave(c, cty) = Int(100 + Rnd * 600)
                Case 4, 5, 6
                    If cave(c, csx) <= 400 Then
                        cave(c, ctx) = cave(c, csx) + Int(50 + Rnd * 200)
                    Else
                        cave(c, ctx) = cave(c, csx) - Int(50 + Rnd * 200)
                    End If
                    If cave(c, csy) <= 400 Then
                        cave(c, cty) = cave(c, csy) + Int(50 + Rnd * 200)
                    Else
                        cave(c, cty) = cave(c, csy) - Int(50 + Rnd * 200)
                    End If
            End Select
            dx = Abs(cave(c, csx) - cave(c, ctx))
            dy = Abs(cave(c, csy) - cave(c, cty))
            dl = Sqr(dx * dx + dy * dy)
            cpl = cpl + 1
            If cave(c, ctx) < 50 Then GoTo restartcaves
            If cpl > caverunlimit Then GoTo restartcaves
        Loop Until dy > 20 And dx > 20
        cave(c, cmx) = Int((cave(c, csx) + cave(c, ctx)) / 2 + (10 + Rnd * 50) - (10 + Rnd * 50))
        cave(c, cmy) = Int((cave(c, csy) + cave(c, cty)) / 2 + (10 + Rnd * 50) - (10 + Rnd * 50))
        ' Print cave(c, csx), cave(c, csy), cave(c, ctx), cave(c, cty), dl
    Next c

    For c = 1 To 24
        r = (1 + (1 + Rnd * 6) + (1 + Rnd * 6)) / 2
        xx = cave(c, csx)
        yy = cave(c, csy)
        xtrend = 0: ytrend = 0
        If xx < cave(c, cmx) Then xtrend = 3
        If xx > cave(c, cmx) Then xtrend = -3
        If yy < cave(c, cmy) Then ytrend = 3
        If yy > cave(c, cmy) Then ytrend = -3
        cpl = 0
        Do
            nx = xx + xtrend + xtrend * Int(Rnd * (r * 2)) - Int(Rnd * (r * 2))
            ny = yy + ytrend + ytrend * Int(Rnd * (r * 2)) - Int(Rnd * (r * 2))
            dx = Abs(cave(c, cmx) - nx)
            dy = Abs(cave(c, cmy) - ny)
            dd = Sqr(dx * dx + dy * dy)
            If dx < (r * 10) Then
                nx = cave(c, cmx)
                ny = ny + Int(r + Rnd * (r * 2)) - Int(r + Rnd * (r * 2))
            End If
            If dy < (r * 10) Then
                ny = cave(c, cmy)
                nx = nx + Int(r + Rnd * (r * 2)) - Int(r + Rnd * (r * 2))
            End If
            bumpyline xx, yy, nx, ny, r, kfloor
            xx = nx
            yy = ny
            cpl = cpl + 1
            If cpl > caverunlimit Then GoTo restartcaves
            If cave(c, cmx) < 50 Then GoTo restartcaves
        Loop Until xx = cave(c, cmx) And yy = cave(c, cmy)
    Next

    For c = 1 To 24
        xx = cave(c, cmx)
        yy = cave(c, cmy)
        xtrend = 0: ytrend = 0
        If xx < cave(c, ctx) Then xtrend = 2
        If xx > cave(c, ctx) Then xtrend = -2
        If yy < cave(c, cty) Then ytrend = 2
        If yy > cave(c, cty) Then ytrend = -2
        cpl = 0
        Do
            nx = xx + xtrend + xtrend * Int(Rnd * (r * 2)) - Int(Rnd * (r * 2))
            ny = yy + ytrend + ytrend * Int(Rnd * (r * 2)) - Int(Rnd * (r * 2))
            dx = Abs(cave(c, ctx) - nx)
            dy = Abs(cave(c, cty) - ny)
            dd = Sqr(dx * dx + dy * dy)
            If dx < r * 7 Then
                nx = cave(c, ctx)
                ny = ny + Int(r / 4 + Rnd * (r / 2)) - Int(r / 4 + Rnd * (r / 2))
            End If
            If dy < r * 7 Then
                ny = cave(c, cty)
                nx = nx + Int(r / 4 + Rnd * (r / 2)) - Int(r / 4 + Rnd * (r / 2))
            End If
            bumpyline xx, yy, nx, ny, r, kfloor
            xx = nx
            yy = ny
            cpl = cpl + 1
            If cpl > caverunlimit Then GoTo restartcaves
            If cave(c, ctx) < 50 Then GoTo restartcaves
        Loop Until xx = cave(c, ctx) And yy = cave(c, cty)
    Next

    For c = 1 To 24
        If Rnd * 6 < 3.5 Then
            reps = Int(2 + Rnd * 3)
            For e = 1 To reps
                If Rnd * 10 < 8.5 Then bumpypoly cave(c, csx), cave(c, csy), Int(5 + Int(Rnd * (5 * e))), Int(20 + Rnd * 100), Rnd * 30, 2 + Rnd * 4, kfloor
                If Rnd * 10 < 8.5 Then bumpypoly cave(c, ctx), cave(c, cty), Int(5 + Int(Rnd * (5 * e))), Int(20 + Rnd * 100), Rnd * 30, 2 + Rnd * 4, kfloor
            Next
        End If
    Next c

    'streams
    ns = Int(1 + Rnd * 12)
    If ns < 9 Then addstreams ns, kwater

    'lava flows
    nf = Int(1 + Rnd * 12)
    If nf < 5 Then addstreams nf, klava
    'slime flows
    nf = Int(1 + Rnd * 30)
    If nf < 9 Then addstreams nf, kslime


    'add rubble
    For yy = 1 To 799
        For xx = 1 To 799
            If Int(1 + Rnd * 10) < 4 Then
                For gx = -1 To 1
                    For gy = -1 To 1
                        If Point(xx, yy) = kfloor And Point(xx + gx, yy + gy) = krock Then PSet (xx, yy), krubble
                        If Point(xx, yy) = klava And Point(xx + gx, yy + gy) = krock Then
                            Select Case Int(1 + Rnd * 100)
                                Case 1
                                    PSet (xx + gx, yy + gy), kcrystal
                                Case 2, 3, 4, 5, 6, 7, 8, 9, 10
                                    PSet (xx + gx, yy + gy), krubble
                                Case 11, 12, 13
                                    PSet (xx + gx, yy + gy), kfloor
                            End Select
                        End If
                        If Point(xx, yy) = klava And Point(xx + gx, yy + gy) = kwater Then
                            Select Case Int(1 + Rnd * 300)
                                Case 1
                                    PSet (xx + gx, yy + gy), kcrystal
                                Case 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25
                                    PSet (xx + gx, yy + gy), krubble
                                Case 26, 27, 28, 29, 30, 31, 32, 33
                                    PSet (xx + gx, yy + gy), kfloor
                            End Select
                        End If

                    Next
                Next
            End If
            If Int(1 + Rnd * 1000) < 6 Then
                If Point(xx, yy) = kfloor Then
                    PSet (xx, yy), krubble
                    For gx = -1 To 1
                        For gy = -1 To 1
                            If Int(1 + Rnd * 10) < 3 Then
                                PSet (xx, yy), krubble
                            End If
                        Next
                    Next

                End If
            End If
        Next
    Next
    For puddles = 1 To 20
        pl = Int(1 + Rnd * 6)
        cc = Int(1 + Rnd * 24)
        Select Case pl
            Case 1
                addwater cave(cc, csx), cave(cc, csy), 2
            Case 2
                addwater cave(cc, cmx), cave(cc, cmy), 1
            Case 3
                addwater cave(cc, ctx), cave(cc, cty), 2
            Case 4, 5, 6
                addwater 0, 0, 3
        End Select
    Next

    For slimedrops = 1 To 16
        pl = Int(1 + Rnd * 7)
        cc = Int(1 + Rnd * 24)
        Select Case pl
            Case 1
                addslime cave(cc, csx), cave(cc, csy), 1
            Case 2
                addslime cave(cc, cmx), cave(cc, cmy), 1
            Case 3
                addslime cave(cc, ctx), cave(cc, cty), 1
            Case 4, 5, 6, 7
                addslime 0, 0, 1.5
        End Select
    Next
    For lavapools = 1 To 12
        pl = Int(1 + Rnd * 8)
        cc = Int(3 + Rnd * 22)
        Select Case pl
            Case 1, 2, 3
                addlava cave(cc, csx), cave(cc, csy), 3
            Case 4
                addlava cave(cc, cmx), cave(cc, cmy), 1
            Case 5, 6, 7
                addlava cave(cc, ctx), cave(cc, cty), 2
            Case 8
                addlava 0, 0, 2
        End Select
    Next


    If check$ = "on" Then
        For c = 1 To 24
            Line (cave(c, csx), cave(c, csy))-(cave(c, cmx), cave(c, cmy)), _RGB32(250, 250, 250)
            Line (cave(c, cmx), cave(c, cmy))-(cave(c, ctx), cave(c, cty)), _RGB32(250, 250, 250)
            _PrintString (cave(c, cmx), cave(c, cmy)), _Trim$(Str$(c))
        Next c
    End If
    Do
        _Limit 60
        kk$ = InKey$
    Loop Until kk$ <> ""
    ' Cls
Loop Until kk$ = " "

'Do
ecave = Int(6 + Rnd * 16)
exitX = cave(ecave, ctx)
exitY = cave(excave, cty)
'Loop Until Point(exitX, exitY) <> krock
PSet (exitX, exitY), kexit

kk$ = ""
'turn based cave exploration
Screen ms
Cls
_Source cmap
_Dest ms
ppx = cave(1, csx): ppy = cave(1, csy)
lightradius = 9: pstamina = 100: phealth = 100: pwounds = 0: ptemp = 98
_PrintMode _KeepBackground
View Print 25 To 30
Do
    'draw location
    rsqrd = lightradius * lightradius
    y = -lightradius
    While y <= lightradius
        x = Int(Sqr(rsqrd - y * y))
        For x2 = ppx - x To ppx + x
            vx = x2 - ppx + 12
            kk = Point(x2, ppy + y)
            Line (vx * 8, (y + 12) * 16)-(vx * 8 + 7, (y + 12) * 16 + 15), kk, BF
        Next
        y = y + 1
    Wend
    Line (598, 18)-(795, 124), krock, BF
    _PrintString ((12) * 8, (12) * 16), "@"
    o$ = "Stamina " + Str$(pstamina)
    _PrintString (600, 20), o$
    o$ = "Health " + Str$(phealth)
    _PrintString (600, 40), o$
    o$ = "Wounds " + Str$(pwounds)
    _PrintString (600, 60), o$
    o$ = "Temperature " + Str$(ptemp)
    _PrintString (600, 80), o$
    edd = Int(Sqr((ppx - exitX) * (ppx - exitX) + (ppy - exitY) * (ppy - exitY)))
    o$ = "Distance to Exit " + Str$(edd)
    _PrintString (600, 100), o$
    Print "Turn", turn

    Do
        _Limit 60
        kk$ = InKey$
    Loop Until kk$ <> ""
    turn = turn + 1
    lastx = ppx
    lasty = ppy
    Select Case kk$
        Case "w", "8"
            If pstamina > 0 And Point(ppx, ppy - 1) <> krock Then ppy = ppy - 1
        Case "s", "2"
            If pstamina > 0 And Point(ppx, ppy + 1) <> krock Then ppy = ppy + 1
        Case "a", "4"
            If pstamina > 0 And Point(ppx - 1, ppy) <> krock Then ppx = ppx - 1
        Case "d", "6"
            If pstamina > 0 And Point(ppx + 1, ppy) <> krock Then ppx = ppx + 1
        Case "7"
            If pstamina > 0 And Point(ppx - 1, ppy - 1) <> krock Then
                ppy = ppy - 1
                ppx = ppx - 1
            End If
        Case "9"
            If pstamina > 0 And Point(ppx + 1, ppy - 1) <> krock Then
                ppy = ppy - 1
                ppx = ppx + 1
            End If

        Case "1"
            If pstamina > 0 And Point(ppx - 1, ppy + 1) <> krock Then
                ppy = ppy + 1
                ppx = ppx - 1
            End If

        Case "3"
            If pstamina > 0 And Point(ppx + 1, ppy + 1) <> krock Then
                ppy = ppy + 1
                ppx = ppx + 1
            End If
        Case "5", "."
            If Int(1 + Rnd * 50) < phealth And pstamina < 100 Then pstamina = pstamina + 1 + Int(Rnd * (phealth / 25))
    End Select
    If Point(ppx, ppy) = krubble Then pwounds = pwounds + checkrubble(ppx, ppy)

    If Int(1 + Rnd * 80 + pwounds) > phealth Then pstamina = pstamina - 1
    If Point(ppx, ppy) = kslime Then
        Print "The slime is nauseating...";
        If Int(Rnd * 120) > phealth Then phealth = phealth - Int(Rnd * 4)
        If Int(Rnd * 120) > phealth Then
            Select Case Int(1 + Rnd * 6)
                Case 1, 2, 3
                    Print " it's making you itch."
                Case 4, 5, 6
                    Print " it's feel's like it is burning you."
                    wounds = wounds + Abs(Int(Rnd * 2 - Rnd * 2))
            End Select
        End If
    End If
    If Point(ppx, ppy) = kwater Then ptemp = ptemp - Int(Abs(Rnd * 2 - Rnd * 2))
    If Point(ppx, ppy) = klava Then
        ptemp = ptemp + 100
        dmg = 10 + Int(Rnd * 20)
        pwounds = pwounds + dmg
        Print "YOU ARE STANDING IN LAVA !!!"
        Print "....suffering "; dmg; " points of damage !"
    End If
    If ptemp < 0 Then
        Print "You are dangerously COLD .... brrrrr"
        pstamina = pstamina - Int(Rnd * 2)
        If Int(1 + Rnd * (50 + Abs(ptemp))) > pstamina Then
            pwounds = pwounds + Int(1 + Rnd * 2)
            phealth = phealth - Int(Rnd * 2)
        End If
    End If
    tcheck = ptemp + Rnd * 10
    If tcheck > 108 Then
        pstamina = pstamina - 1
        Print "You are dangerously warm!"
        If Int(1 + Rnd * ptemp) > pstamina Then
            pwounds = pwounds + 1
            phealth = phealth - Int(Rnd * 2)
        End If
    End If
    If Point(ppx, ppy) = kfloor Then
        If ptemp < 98 Then ptemp = ptemp + 1
        If ptemp > 98 Then ptemp = Int((ptemp + 98) / 2)
    End If
    If pstamina < 20 Then
        Print "You are ";
        If pstamina < 1 Then
            Print "exhausted."
        Else
            Print "fatigued."
        End If
    End If
    If wounds > phealth Then
        Print "You are in intense pain !"
        pstamina = pstamina = Int(Rnd * 2)
    End If
    If Point(ppx, ppy) = kexit Then
        Print
        Print "YOU HAVE FOUND THE EXIT"
        Print
        Print "it took you "; turns; " turns after starting ", start_X, " spaces away from the exit."
        Print
        kk$ = Chr$(27)
    End If

    If phealth < 1 Or pwounds > 99 Then
        Print "YOU HAVE PERISHED DUE TO YOUR POOR CONDITION."
        Print
        Print "(press any key to continue)"
        any$ = Input$(1)
        kk$ = Chr$(27)

    End If


Loop Until kk$ = Chr$(27)
Print "GAME OVER"
Print "play again?"
Print "Y or N?"
Do
    ask$ = Input$(1)
    ask$ = UCase$(ask$)
Loop Until ask$ = "Y" Or ask$ = "N"
If ask$ = "Y" Then
    Screen cmap
    GoTo restartcaves
End If
System


Function checkrubble (xx, yy)
    stumblecheck = Int(1 + Rnd * 120)
    dmg = 0
    If stumblecheck > health Then
        Print "whooops.... you stumbled on the rubble...";
        Select Case Int(1 + Rnd * 20)
            Case 1
                If Point(ppx - 1, ppy - 1) <> krock Then
                    ppx = ppx - 1
                    ppy = ppy - 1
                End If
            Case 2
                If Point(ppx, ppy - 1) <> krock Then
                    ppy = ppy - 1
                End If
            Case 3
                If Point(ppx + 1, ppy + 1) <> krock Then
                    ppx = ppx + 1
                    ppy = ppy + 1
                End If
            Case 4
                If Point(ppx - 1, ppy) <> krock Then
                    ppx = ppx - 1
                End If
            Case 6
                If Point(ppx + 1, ppy) <> krock Then
                    ppx = ppx + 1
                End If
            Case 7
                If Point(ppx - 1, ppy + 1) <> krock Then
                    ppx = ppx - 1
                    ppy = ppy + 1
                End If
            Case 8
                If Point(ppx, ppy + 1) <> krock Then
                    ppy = ppy + 1
                End If
            Case 9
                If Point(ppx + 1, ppy + 1) <> krock Then
                    ppy = ppy + 1
                    ppx = ppx + 1
                End If
            Case 10, 11, 12, 13, 14
                Print " knocking the wind out of you... ";
                pstamina = Int(pstamina / 4)
            Case 15, 16, 17, 18, 19, 20
                ppx = lastx
                ppy = lasty
                Print "you tumble back...";
        End Select
        dmg = Abs(Int((Rnd * 3) - (Rnd * 3)))
        If dmg > 0 Then
            Print "you suffer "; dmg; " points of damage!"
        Else
            Print "."
        End If

    End If
    checkrubble = dmg

End Function
Sub circleBF (cx As Long, cy As Long, r As Long, klr As _Unsigned Long)
    rsqrd = r * r
    y = -r
    While y <= r
        x = Sqr(rsqrd - y * y)
        Line (cx - x, cy + y)-(cx + x, cy + y), klr, BF
        y = y + 1
    Wend
End Sub

Sub rotpoly (cx, cy, rr, shapedeg, turn, klr As _Unsigned Long)
    x = rr * Sin(0.01745329 * turn)
    y = rr * Cos(0.01745329 * turn)
    Line (cx + x, cy + y)-(cx + x, cy + y), klr
    For deg = turn To turn + 360 Step shapedeg
        x2 = rr * Sin(0.01745329 * deg)
        y2 = rr * Cos(0.01745329 * deg)
        Line -(cx + x2, cy + y2), klr
    Next
End Sub
Sub bumpypoly (cx, cy, rr, shapedeg, turn, thk, klr As _Unsigned Long)
    x = rr * Sin(0.01745329 * turn)
    y = rr * Cos(0.01745329 * turn)
    'Line (cx + x, cy + y)-(cx + x, cy + y), klr
    lx = cx + x: ly = cy + y
    For deg = turn To turn + 360 Step shapedeg
        x2 = rr * Sin(0.01745329 * deg)
        y2 = rr * Cos(0.01745329 * deg)
        tv = (Rnd * 6 + Rnd * 6 + 3) / 10
        bumpyline lx, ly, cx + x2, cy + y2, thk * tv, klr
        lx = cx + x2: ly = cy + y2
    Next
End Sub
Sub addwater (pcx, pcy, scale)
    If pcx = 0 Then
        pcx = Int(100 + Rnd * 600)
        pcy = Int(100 + Rnd * 600)
    End If
    prr = Int(6 + Rnd * (12 * scale))
    preps = (3 + Int(Rnd * prr))
    For r = 1 To preps
        pcx = pcx + Int(Rnd * 4) - Int(Rnd * 4)
        pcy = pcy + Int(Rnd * 4) - Int(Rnd * 4)
        rsqrd = prr * prr
        y = -prr
        While y <= prr
            x = Int(Sqr(rsqrd - y * y))
            For x2 = pcx - x To pcx + x
                kk = Point(x2, pcy + y)
                If kk = kfloor Then
                    PSet (x2, pcy + y), kwater
                End If
            Next
            y = y + 1
        Wend
        prr = Int((prr + Int(6 + Rnd * (12 * scale))) / 2)
    Next

End Sub

Sub addslime (pcx, pcy, scale)
    If pcx = 0 Then
        pcx = Int(100 + Rnd * 600)
        pcy = Int(100 + Rnd * 600)
    End If
    prr = Int(6 + Rnd * (12 * scale))
    preps = (3 + Int(Rnd * prr))
    For r = 1 To preps
        pcx = pcx + Int(Rnd * 4) - Int(Rnd * 4)
        pcy = pcy + Int(Rnd * 4) - Int(Rnd * 4)
        rsqrd = prr * prr
        y = -prr
        While y <= prr
            x = Int(Sqr(rsqrd - y * y))
            For x2 = pcx - x To pcx + x
                kk = Point(x2, pcy + y)
                If kk = kfloor Then
                    PSet (x2, pcy + y), kslime
                End If
            Next
            y = y + 1
        Wend
        prr = Int(2 + Rnd * (12 * scale))
    Next

End Sub
Sub addlava (pcx, pcy, scale)
    If pcx = 0 Then
        pcx = Int(100 + Rnd * 600)
        pcy = Int(100 + Rnd * 600)
    End If
    prr = Int(6 + Rnd * (12 * scale))
    preps = (2 + Int(Rnd * (prr / 2)))
    For r = 1 To preps
        pcx = pcx + Int(Rnd * 4) - Int(Rnd * 4)
        pcy = pcy + Int(Rnd * 4) - Int(Rnd * 4)
        rsqrd = prr * prr
        y = -prr
        While y <= prr
            x = Int(Sqr(rsqrd - y * y))
            For x2 = pcx - x To pcx + x
                kk = Point(x2, pcy + y)
                If kk = kfloor Then
                    PSet (x2, pcy + y), klava
                End If
                If kk = kslime Then
                    PSet (x2, pcy + y), klava
                End If
                If kk = kwater Then
                    Select Case Int(Rnd * 10)
                        Case 1
                            PSet (x2, pcy + y), klava
                        Case 2, 3
                            PSet (x2, pcy + y), krock
                        Case 4, 5, 6, 7
                            PSet (x2, pcy + y), kfloor
                        Case 8, 9, 10
                            PSet (x2, pcy + y), krubble
                    End Select
                End If

            Next
            y = y + 1
        Wend
        prr = Int((prr + Int(6 + Rnd * (12 * scale))) / 2)
    Next

End Sub




Sub fatpoly (cx, cy, rr, shapedeg, turn, thk, klr As _Unsigned Long)
    x = rr * Sin(0.01745329 * turn)
    y = rr * Cos(0.01745329 * turn)
    'Line (cx + x, cy + y)-(cx + x, cy + y), klr
    lx = cx + x: ly = cy + y
    For deg = turn To turn + 360 Step shapedeg
        x2 = rr * Sin(0.01745329 * deg)
        y2 = rr * Cos(0.01745329 * deg)
        fatline lx, ly, cx + x2, cy + y2, thk, klr
        lx = cx + x2: ly = cy + y2
    Next
End Sub
Sub bumpyline (x0, y0, x1, y1, r, klr As _Unsigned Long)
    If Abs(y1 - y0) < Abs(x1 - x0) Then
        If x0 > x1 Then
            bumpylineLow x1, y1, x0, y0, r, klr

        Else
            bumpylineLow x0, y0, x1, y1, r, klr
        End If
    Else
        If y0 > y1 Then
            bumpylineHigh x1, y1, x0, y0, r, klr
        Else
            bumpylineHigh x0, y0, x1, y1, r, klr
        End If
    End If
End Sub







Sub fatline (x0, y0, x1, y1, r, klr As _Unsigned Long)
    If Abs(y1 - y0) < Abs(x1 - x0) Then
        If x0 > x1 Then
            lineLow x1, y1, x0, y0, r, klr

        Else
            lineLow x0, y0, x1, y1, r, klr
        End If
    Else
        If y0 > y1 Then
            lineHigh x1, y1, x0, y0, r, klr
        Else
            lineHigh x0, y0, x1, y1, r, klr
        End If
    End If
End Sub
Sub lineLow (x0, y0, x1, y1, r, klr As _Unsigned Long)
    dx = x1 - x0
    dy = y1 - y0
    yi = 1
    If dy < 0 Then
        yi = -1
        dy = -dy
    End If
    'D = (2 * dy) - dx
    d = (dy + dy) - dx
    y = y0
    For x = x0 To x1
        circleBF x, y, r, klr

        If d > 0 Then
            y = y + yi
            ' D = D + (2 * (dy - dx))
            d = d + ((dy - dx) + (dy - dx))
        Else
            ' D = D + 2 * dy
            d = d + dy + dy
        End If
    Next x
End Sub
Sub lineHigh (x0, y0, x1, y1, r, klr As _Unsigned Long)
    dx = x1 - x0
    dy = y1 - y0
    xi = 1
    If dx < 0 Then
        xi = -1
        dx = -dx
    End If
    ' D = (2 * dx) - dy
    D = (dx + dx) - dy
    x = x0
    For y = y0 To y1
        circleBF x, y, r, klr

        If D > 0 Then
            x = x + xi
            ' D = D + (2 * (dx - dy))
            D = D + ((dx - dy) + (dx - dy))
        Else
            ' D = D + 2 * dx
            D = D + dx + dx
        End If
    Next y
End Sub
Sub bumpylineLow (x0, y0, x1, y1, r, klr As _Unsigned Long)
    dx = x1 - x0
    dy = y1 - y0
    yi = 1
    If dy < 0 Then
        yi = -1
        dy = -dy
    End If
    'D = (2 * dy) - dx
    d = (dy + dy) - dx
    y = y0
    For x = x0 To x1
        tv = (Rnd * 6 + Rnd * 6 + 3) / 10
        circleBF x + Rnd * r - Rnd * r, y + Rnd * r - Rnd * 4, r * tv, klr

        If d > 0 Then
            y = y + yi
            ' D = D + (2 * (dy - dx))
            d = d + ((dy - dx) + (dy - dx))
        Else
            ' D = D + 2 * dy
            d = d + dy + dy
        End If
    Next x
End Sub
Sub bumpylineHigh (x0, y0, x1, y1, r, klr As _Unsigned Long)
    dx = x1 - x0
    dy = y1 - y0
    xi = 1
    If dx < 0 Then
        xi = -1
        dx = -dx
    End If
    ' D = (2 * dx) - dy
    D = (dx + dx) - dy
    x = x0
    For y = y0 To y1
        tv = (Rnd * 12 + Rnd * 6 + 3) / 10
        circleBF x + Rnd * r - Rnd * r, y + Rnd * r - Rnd * 4, r * tv, klr

        If D > 0 Then
            x = x + xi
            ' D = D + (2 * (dx - dy))
            D = D + ((dx - dy) + (dx - dy))
        Else
            ' D = D + 2 * dx
            D = D + dx + dx
        End If
    Next y
End Sub
Sub addstreams (numstreams, kklr)
    Dim stream(numstreams, 6)

    restartstreams:

    stream(1, csx) = Int(100 + Rnd * 600)
    stream(1, csy) = Int(100 + Rnd * 600)
    Do
        stream(1, ctx) = Int(100 + Rnd * 600)
        stream(1, cty) = Int(100 + Rnd * 600)
        dx = Abs(stream(1, csx) - stream(1, ctx))
        dy = Abs(stream(1, csy) - stream(1, cty))
        dl = Sqr(dx * dx + dy * dy)
    Loop Until dy > 20 And dx > 20

    stream(1, cmx) = Int((stream(1, csx) + stream(1, ctx)) / 2 + (10 + Rnd * 50) - (10 + Rnd * 50))
    stream(1, cmy) = Int((stream(1, csy) + stream(1, cty)) / 2 + (10 + Rnd * 50) - (10 + Rnd * 50))
    For c = 2 To numstreams

        Select Case Int(1 + Rnd * 8)
            Case 1, 2, 3
                stream(c, csx) = stream(c - 1, csx)
                stream(c, csy) = stream(c - 1, csy)

            Case 4, 5
                stream(c, csx) = stream(c - 1, cmx)
                stream(c, csy) = stream(c - 1, cmy)

            Case 6, 7, 8
                stream(c, csx) = stream(c - 1, ctx)
                stream(c, csy) = stream(c - 1, cty)
        End Select
        cpl = 0
        Do

            Select Case Int(1 + Rnd * 6)
                Case 1, 2, 3
                    stream(c, ctx) = Int(100 + Rnd * 600)
                    stream(c, cty) = Int(100 + Rnd * 600)
                Case 4, 5, 6
                    If stream(c, csx) <= 400 Then
                        stream(c, ctx) = stream(c, csx) + Int(50 + Rnd * 200)
                    Else
                        stream(c, ctx) = stream(c, csx) - Int(50 + Rnd * 200)
                    End If
                    If stream(c, csy) <= 400 Then
                        stream(c, cty) = stream(c, csy) + Int(50 + Rnd * 200)
                    Else
                        stream(c, cty) = stream(c, csy) - Int(50 + Rnd * 200)
                    End If
            End Select
            dx = Abs(stream(c, csx) - stream(c, ctx))
            dy = Abs(stream(c, csy) - stream(c, cty))
            dl = Sqr(dx * dx + dy * dy)
            cpl = cpl + 1
            If stream(c, ctx) < 50 Then GoTo restartstreams
            If cpl > caverunlimit Then GoTo restartstreams
        Loop Until dy > 20 And dx > 20
        stream(c, cmx) = Int((stream(c, csx) + stream(c, ctx)) / 2 + (10 + Rnd * 50) - (10 + Rnd * 50))
        stream(c, cmy) = Int((stream(c, csy) + stream(c, cty)) / 2 + (10 + Rnd * 50) - (10 + Rnd * 50))
        ' Print cave(c, csx), cave(c, csy), cave(c, ctx), cave(c, cty), dl
    Next c


    For c = 1 To numstreams
        r = (3 + (1 + Rnd * 6) + (1 + Rnd * 6)) / 4
        xx = stream(c, csx)
        yy = stream(c, csy)
        If Point(xx, yy) = krock Then
            bumpypoly xx, yy, Int(r / 2 + Int(Rnd * (r * 3))), Int(20 + Rnd * 100), Rnd * 30, 2 + Rnd * 4, kfloor
        End If



        xtrend = 0: ytrend = 0
        If xx < stream(c, cmx) Then xtrend = 3
        If xx > stream(c, cmx) Then xtrend = -3
        If yy < stream(c, cmy) Then ytrend = 3
        If yy > stream(c, cmy) Then ytrend = -3
        cpl = 0
        Do
            nx = xx + xtrend + xtrend * Int(Rnd * (r * 2)) - Int(Rnd * (r * 2))
            ny = yy + ytrend + ytrend * Int(Rnd * (r * 2)) - Int(Rnd * (r * 2))
            dx = Abs(stream(c, cmx) - nx)
            dy = Abs(stream(c, cmy) - ny)
            dd = Sqr(dx * dx + dy * dy)
            If dx < (r * 10) Then
                nx = stream(c, cmx)
                ny = ny + Int(r + Rnd * (r * 2)) - Int(r + Rnd * (r * 2))
            End If
            If dy < (r * 10) Then
                ny = stream(c, cmy)
                nx = nx + Int(r + Rnd * (r * 2)) - Int(r + Rnd * (r * 2))
            End If
            bumpyline xx, yy, nx, ny, r, kklr
            xx = nx
            yy = ny
            cpl = cpl + 1
            If cpl > caverunlimit Then GoTo restartstreams
            If stream(c, cmx) < 50 Then GoTo restartstreams
        Loop Until xx = stream(c, cmx) And yy = stream(c, cmy)
    Next
    If Point(nx, ny) = krock Then
        bumpypoly nx, ny, Int(r / 2 + Int(Rnd * r)), Int(20 + Rnd * 100), Rnd * 30, 2 + Rnd * 4, kfloor
    End If

    For c = 1 To numstreams
        xx = stream(c, cmx)
        yy = stream(c, cmy)
        xtrend = 0: ytrend = 0
        If xx < stream(c, ctx) Then xtrend = 2
        If xx > stream(c, ctx) Then xtrend = -2
        If yy < stream(c, cty) Then ytrend = 2
        If yy > stream(c, cty) Then ytrend = -2
        cpl = 0
        Do
            nx = xx + xtrend + xtrend * Int(Rnd * (r * 2)) - Int(Rnd * (r * 2))
            ny = yy + ytrend + ytrend * Int(Rnd * (r * 2)) - Int(Rnd * (r * 2))
            dx = Abs(stream(c, ctx) - nx)
            dy = Abs(stream(c, cty) - ny)
            dd = Sqr(dx * dx + dy * dy)
            If dx < r * 7 Then
                nx = stream(c, ctx)
                ny = ny + Int(r / 4 + Rnd * (r / 2)) - Int(r / 4 + Rnd * (r / 2))
            End If
            If dy < r * 7 Then
                ny = stream(c, cty)
                nx = nx + Int(r / 4 + Rnd * (r / 2)) - Int(r / 4 + Rnd * (r / 2))
            End If
            bumpyline xx, yy, nx, ny, r, kklr
            xx = nx
            yy = ny
            cpl = cpl + 1
            If cpl > caverunlimit Then GoTo restartstreams
            If stream(c, ctx) < 50 Then GoTo restartstreams
        Loop Until xx = stream(c, ctx) And yy = stream(c, cty)
        If Point(nx, ny) = krock Then
            bumpypoly nx, ny, Int(r / 2 + Int(Rnd * r)), Int(20 + Rnd * 100), Rnd * 30, 2 + Rnd * 4, kfloor
        End If
    Next
End Sub

Sub addlavaflows (numstreams)
    Dim stream(numstreams, 6)

    restartflows:

    stream(1, csx) = Int(100 + Rnd * 600)
    stream(1, csy) = Int(100 + Rnd * 600)
    Do
        stream(1, ctx) = Int(100 + Rnd * 600)
        stream(1, cty) = Int(100 + Rnd * 600)
        dx = Abs(stream(1, csx) - stream(1, ctx))
        dy = Abs(stream(1, csy) - stream(1, cty))
        dl = Sqr(dx * dx + dy * dy)
    Loop Until dy > 20 And dx > 20

    stream(1, cmx) = Int((stream(1, csx) + stream(1, ctx)) / 2 + (10 + Rnd * 50) - (10 + Rnd * 50))
    stream(1, cmy) = Int((stream(1, csy) + stream(1, cty)) / 2 + (10 + Rnd * 50) - (10 + Rnd * 50))
    For c = 2 To numstreams

        Select Case Int(1 + Rnd * 8)
            Case 1, 2, 3
                stream(c, csx) = stream(c - 1, csx)
                stream(c, csy) = stream(c - 1, csy)

            Case 4, 5
                stream(c, csx) = stream(c - 1, cmx)
                stream(c, csy) = stream(c - 1, cmy)

            Case 6, 7, 8
                stream(c, csx) = stream(c - 1, ctx)
                stream(c, csy) = stream(c - 1, cty)
        End Select
        cpl = 0
        Do

            Select Case Int(1 + Rnd * 6)
                Case 1, 2, 3
                    stream(c, ctx) = Int(100 + Rnd * 600)
                    stream(c, cty) = Int(100 + Rnd * 600)
                Case 4, 5, 6
                    If stream(c, csx) <= 400 Then
                        stream(c, ctx) = stream(c, csx) + Int(50 + Rnd * 200)
                    Else
                        stream(c, ctx) = stream(c, csx) - Int(50 + Rnd * 200)
                    End If
                    If stream(c, csy) <= 400 Then
                        stream(c, cty) = stream(c, csy) + Int(50 + Rnd * 200)
                    Else
                        stream(c, cty) = stream(c, csy) - Int(50 + Rnd * 200)
                    End If
            End Select
            dx = Abs(stream(c, csx) - stream(c, ctx))
            dy = Abs(stream(c, csy) - stream(c, cty))
            dl = Sqr(dx * dx + dy * dy)
            cpl = cpl + 1
            If stream(c, ctx) < 50 Then GoTo restartflows
            If cpl > caverunlimit Then GoTo restartflows
        Loop Until dy > 20 And dx > 20
        stream(c, cmx) = Int((stream(c, csx) + stream(c, ctx)) / 2 + (10 + Rnd * 50) - (10 + Rnd * 50))
        stream(c, cmy) = Int((stream(c, csy) + stream(c, cty)) / 2 + (10 + Rnd * 50) - (10 + Rnd * 50))
        ' Print cave(c, csx), cave(c, csy), cave(c, ctx), cave(c, cty), dl
    Next c


    For c = 1 To numstreams
        r = (3 + (1 + Rnd * 6) + (1 + Rnd * 6)) / 4
        xx = stream(c, csx)
        yy = stream(c, csy)

        xtrend = 0: ytrend = 0
        If xx < stream(c, cmx) Then xtrend = 3
        If xx > stream(c, cmx) Then xtrend = -3
        If yy < stream(c, cmy) Then ytrend = 3
        If yy > stream(c, cmy) Then ytrend = -3
        cpl = 0
        Do
            nx = xx + xtrend + xtrend * Int(Rnd * (r * 2)) - Int(Rnd * (r * 2))
            ny = yy + ytrend + ytrend * Int(Rnd * (r * 2)) - Int(Rnd * (r * 2))
            dx = Abs(stream(c, cmx) - nx)
            dy = Abs(stream(c, cmy) - ny)
            dd = Sqr(dx * dx + dy * dy)
            If dx < (r * 10) Then
                nx = stream(c, cmx)
                ny = ny + Int(r + Rnd * (r * 2)) - Int(r + Rnd * (r * 2))
            End If
            If dy < (r * 10) Then
                ny = stream(c, cmy)
                nx = nx + Int(r + Rnd * (r * 2)) - Int(r + Rnd * (r * 2))
            End If
            bumpyline xx, yy, nx, ny, r, klava
            xx = nx
            yy = ny
            cpl = cpl + 1
            If cpl > caverunlimit Then GoTo restartflows
            If stream(c, cmx) < 50 Then GoTo restartflows
        Loop Until xx = stream(c, cmx) And yy = stream(c, cmy)
    Next

    For c = 1 To numstreams
        xx = stream(c, cmx)
        yy = stream(c, cmy)
        xtrend = 0: ytrend = 0
        If xx < stream(c, ctx) Then xtrend = 2
        If xx > stream(c, ctx) Then xtrend = -2
        If yy < stream(c, cty) Then ytrend = 2
        If yy > stream(c, cty) Then ytrend = -2
        cpl = 0
        Do
            nx = xx + xtrend + xtrend * Int(Rnd * (r * 2)) - Int(Rnd * (r * 2))
            ny = yy + ytrend + ytrend * Int(Rnd * (r * 2)) - Int(Rnd * (r * 2))
            dx = Abs(stream(c, ctx) - nx)
            dy = Abs(stream(c, cty) - ny)
            dd = Sqr(dx * dx + dy * dy)
            If dx < r * 7 Then
                nx = stream(c, ctx)
                ny = ny + Int(r / 4 + Rnd * (r / 2)) - Int(r / 4 + Rnd * (r / 2))
            End If
            If dy < r * 7 Then
                ny = stream(c, cty)
                nx = nx + Int(r / 4 + Rnd * (r / 2)) - Int(r / 4 + Rnd * (r / 2))
            End If
            bumpyline xx, yy, nx, ny, r, klava
            xx = nx
            yy = ny
            cpl = cpl + 1
            If cpl > caverunlimit Then GoTo restartflows
            If stream(c, ctx) < 50 Then GoTo restartflows
        Loop Until xx = stream(c, ctx) And yy = stream(c, cty)
    Next
End Sub

Print this item

  Idea similar to _exit
Posted by: eoredson - 09-26-2022, 04:26 AM - Forum: Help Me! - Replies (12)

Hi,

I had an idea..

Since _exit traps Control-Break which is int x1B
then why not trap _print with PrintScreen which is int x05

Erik.

Print this item

  Pascal's Triangle and nth roots.
Posted by: Pete - 09-25-2022, 06:26 PM - Forum: General Discussion - Replies (2)

So to finish off my nth root calculator with long division, I needed to incorporate Pascal's Triangle in the binominal expansion algorithm.

Code: (Select All)
DIM AS DOUBLE i, j, r, z
INPUT "root: "; r
FOR i = 1 TO r + 1
    z = 1
    FOR j = 1 TO i
        PRINT z;
        z = z * (i - j) \ j
    NEXT
    PRINT
NEXT


WORKING MODEL FOR NON-DECIMAL ROOTS. NOTE: NO DECIMAL POINT YET in output. I will be adding that later...

Code: (Select All)
$CONSOLE:ONLY
LINE INPUT "Whole number: "; n$
LINE INPUT "Root: "; r$
r = VAL(r$)
nu&& = INSTR(n$, ".") - 1: IF nu&& < 0 THEN nu&& = LEN(n$)
h&& = (r - (r - nu&& MOD r)) + 1
t$ = MID$(n$, 1, h&& - 1): d$ = "0"
limit&& = 16
' Calculate Pascal's Triangle.
REDIM p$(r + 1)
FOR i1&& = 1 TO r + 1
    p&& = 1
    FOR j1&& = 1 TO i1&&
        p$(j1&&) = LTRIM$(STR$(p&&))
        p&& = p&& * (i1&& - j1&&) \ j1&&
    NEXT
NEXT

DO
    oldx$ = "0"
    lcnt&& = lcnt&& + 1
    FOR j = 1 TO 10
        x$ = "0"
        FOR i&& = 1 TO r
            REM PRINT "(10 ^"; (i&& - 1); "*"; p$(i&&); "* d ^"; i&& - 1; " * j ^"; (r + 1 - i&&); ") + ";
            REM x = x + 10 ^ (i&& - 1) * VAL(p$(i&&)) * d ^ (i&& - 1) * j ^ (r + 1 - i&&)
            tmp$ = "1"
            FOR k% = 1 TO i&& - 1
                tmp$ = sm_mult$(tmp$, "10")
            NEXT
            tmp$ = sm_mult$(tmp$, p$(i&&))
            tmp2$ = "1"
            FOR k% = 1 TO i&& - 1
                tmp2$ = sm_mult$(tmp2$, d$)
            NEXT
            IF d$ = "0" AND k% = 1 THEN tmp2$ = "1" ' zero^0 = 1
            tmp3$ = sm_mult$(tmp$, tmp2$)
            tmp$ = "1"
            FOR k% = 1 TO r + 1 - i&&
                tmp$ = sm_mult$(tmp$, LTRIM$(STR$(j)))
            NEXT
            tmp2$ = sm_mult$(tmp3$, tmp$)
            x$ = sm_add(x$, tmp2$)
        NEXT
        IF LEN(x$) > LEN(t$) OR LEN(x$) = LEN(t$) AND x$ > t$ THEN EXIT FOR
        oldx$ = x$
    NEXT
    d$ = d$ + LTRIM$(STR$(j - 1))
    IF LEFT$(d$, 1) = "0" THEN d$ = MID$(d$, 2) ' Remove leading zero.
    tmp1$ = sm_sub$(t$, oldx$)
    tmp2$ = MID$(n$, h&&, r) + STRING$(r - LEN(MID$(n$, h&&, r)), "0")
    t$ = tmp1$ + tmp2$
    IF LEFT$(t$, 1) = "0" THEN t$ = MID$(t$, 2) 'Remove leading zero.
    h&& = h&& + r
    IF t$ = STRING$(LEN(t$), "0") AND h&& >= LEN(n$) OR lcnt&& = limit&& THEN EXIT DO
LOOP
    sm_rt$ = d$
PRINT "Answer: "; sm_rt$: PRINT
RUN

SUB sm_greater_lesser (stringmatha$, stringmathb$, gl%)
    compa$ = stringmatha$: compb$ = stringmathb$ ' So original variables do not get changed.
    DO
        WHILE -1 ' Falx loop.
            IF gl% = 2 THEN EXIT WHILE ' For bypassing sign and decimal adjustments when only positive non-decimal numbers are being evaluated.
            ' Remove trailing zeros after a decimal point.
            IF INSTR(compa$, ".") THEN
                DO UNTIL RIGHT$(compa$, 1) <> "0" AND RIGHT$(compa$, 1) <> "." AND RIGHT$(compa$, 1) <> "-"
                    compa$ = MID$(compa$, 1, LEN(compa$) - 1)
                LOOP
            END IF
            IF INSTR(compb$, ".") THEN
                DO UNTIL RIGHT$(compb$, 1) <> "0" AND RIGHT$(compb$, 1) <> "." AND RIGHT$(compb$, 1) <> "-"
                    compb$ = MID$(compb$, 1, LEN(compb$) - 1)
                LOOP
            END IF

            IF MID$(compa$, 1, 2) = "-0" OR compa$ = "" OR compa$ = "-" THEN compa$ = "0"
            IF MID$(compb$, 1, 2) = "-0" OR compb$ = "" OR compb$ = "-" THEN compb$ = "0"

            ' A - and +
            j% = 0: k% = 0
            IF LEFT$(compa$, 1) = "-" THEN j% = -1
            IF LEFT$(compb$, 1) = "-" THEN k% = -1
            IF k% = 0 AND j% THEN gl% = -1: EXIT DO
            IF j% = 0 AND k% THEN gl% = 1: EXIT DO

            j&& = INSTR(compa$, ".")
            k&& = INSTR(compb$, ".")

            ' A starting decimal and non-decimal.
            IF j&& = 0 AND k&& = 1 THEN
                IF compa$ = "0" THEN gl% = -1 ELSE gl% = 1
                EXIT DO
            END IF
            IF k&& = 0 AND j&& = 1 THEN
                IF compb$ = "0" THEN gl% = 1 ELSE gl% = -1
                EXIT DO
            END IF

            ' remove decimals and align.
            j2&& = 0: k2&& = 0
            IF j&& <> 0 OR k&& <> 0 THEN
                IF j&& THEN compa$ = MID$(compa$, 1, INSTR(compa$, ".") - 1) + MID$(compa$, INSTR(compa$, ".") + 1): j2&& = LEN(compa$) - j&& + 1
                IF k&& THEN compb$ = MID$(compb$, 1, INSTR(compb$, ".") - 1) + MID$(compb$, INSTR(compb$, ".") + 1): k2&& = LEN(compb$) - k&& + 1
                compa$ = compa$ + STRING$(k2&& - j2&&, "0")
                compb$ = compb$ + STRING$(j2&& - k2&&, "0")
            END IF
            EXIT WHILE
        WEND

        ' Remove leading zeros if any.
        DO UNTIL LEFT$(compa$, 1) <> "0"
            compa$ = MID$(compa$, 2)
        LOOP
        IF compa$ = "" THEN compa$ = "0"
        DO UNTIL LEFT$(compb$, 1) <> "0"
            compb$ = MID$(compb$, 2)
        LOOP
        IF compb$ = "" THEN compb$ = "0"

        ' Both positive or both negative whole numbers.

        SELECT CASE LEN(compa$)
            CASE IS < LEN(compb$)
                gl% = -1
            CASE IS = LEN(compb$)
                IF compa$ = compb$ THEN
                    gl% = 0
                ELSEIF compa$ > compb$ THEN gl% = 1
                ELSEIF compa$ < compb$ THEN gl% = -1
                END IF
            CASE IS > LEN(compb$)
                gl% = 1
        END SELECT
        EXIT DO
    LOOP
END SUB

SUB sm_add_subtract_router (stringmatha$, operator$, stringmathb$, runningtotal$)
    DIM AS _INTEGER64 a, c, s
    a1$ = stringmatha$: b1$ = stringmathb$
    s = 18: i&& = 0: c = 0

    a$ = stringmatha$: b$ = stringmathb$: op$ = operator$

    IF op$ = "-" THEN
        IF LEFT$(b$, 1) = "-" THEN b$ = MID$(b$, 2) ELSE b$ = "-" + b$
    END IF

    IF INSTR(a$, ".") <> 0 OR INSTR(b$, ".") <> 0 THEN
        decimal% = -1
        IF INSTR(a$, ".") <> 0 THEN
            dec_a&& = LEN(MID$(a$, INSTR(a$, ".") + 1))
            a$ = MID$(a$, 1, INSTR(a$, ".") - 1) + MID$(a$, INSTR(a$, ".") + 1)
        END IF
        IF INSTR(b$, ".") <> 0 THEN
            dec_b&& = LEN(MID$(b$, INSTR(b$, ".") + 1))
            b$ = MID$(b$, 1, INSTR(b$, ".") - 1) + MID$(b$, INSTR(b$, ".") + 1)
        END IF
        ' Line up decimal places by inserting trailing zeros.
        IF dec_b&& > dec_a&& THEN
            j&& = dec_b&&
            a$ = a$ + STRING$(dec_b&& - dec_a&&, "0")
        ELSE
            j&& = dec_a&&
            b$ = b$ + STRING$(dec_a&& - dec_b&&, "0")
        END IF
    END IF

    IF LEFT$(a$, 1) = "-" OR LEFT$(b$, 1) = "-" THEN
        IF LEFT$(a$, 1) = "-" AND LEFT$(b$, 1) = "-" THEN
            sign$ = "": a$ = MID$(a$, 2): b$ = MID$(b$, 2)
        ELSE
            IF LEFT$(a$, 1) = "-" THEN a$ = MID$(a$, 2): sign_a$ = "-"
            IF LEFT$(b$, 1) = "-" THEN b$ = MID$(b$, 2): sign_b$ = "-"

            IF LEFT$(a1$, 1) = "-" THEN a1_x$ = MID$(a1$, 2) ELSE a1_x$ = a1$
            IF LEFT$(b1$, 1) = "-" THEN b1_x$ = MID$(b1$, 2) ELSE b1_x$ = b1$

            sm_greater_lesser a1_x$, b1_x$, gl%

            IF gl% < 0 THEN
                IF LEN(sign_b$) THEN sign$ = "-": SWAP a$, b$
            ELSE
                IF LEN(sign_a$) THEN sign$ = "-": SWAP sign_a$, sign_b$
            END IF
        END IF
    END IF

    z$ = ""
    ' Addition and subtraction of digits.
    DO
        i&& = i&& + s
        x1$ = MID$(a$, LEN(a$) - i&& + 1, s)
        x2$ = MID$(b$, LEN(b$) - i&& + 1, s)
        IF LEN(x2$) > LEN(x1$) THEN SWAP x1$, x2$
        a = VAL(sign_a$ + x1$) + VAL(sign_b$ + x2$) + c
        IF x1$ + x2$ = "" AND c = 0 THEN EXIT DO
        c = 0
        IF a > VAL(STRING$(s, "9")) THEN a = a - 10 ^ s: c = 1
        IF a < 0 THEN a = a + 10 ^ s: c = -1 ' a will never be less than 0.
        tmp$ = LTRIM$(STR$(a))
        z$ = STRING$(LEN(x1$) - LEN(tmp$), "0") + tmp$ + z$
    LOOP

    IF decimal% THEN
        z$ = MID$(z$, 1, LEN(z$) - j&&) + "." + MID$(z$, LEN(z$) - j&& + 1)
    END IF

    ' Remove any leading zeros.
    DO
        IF LEFT$(z$, 1) = "0" THEN z$ = MID$(z$, 2) ELSE EXIT DO
    LOOP

    IF z$ = "" OR z$ = "0" THEN z$ = "0" ELSE z$ = LEFT$(sign$, 1) + z$

    runningtotal$ = z$

    sign$ = "": sign_a$ = "": sign_b$ = "": i&& = 0: j&& = 0: decimal% = 0: c = 0
END SUB

FUNCTION sm_add$ (stringmatha$, stringmathb$)
    operator$ = "+"
    sm_add_subtract_router stringmatha$, operator$, stringmathb$, runningtotal$
    sm_add$ = runningtotal$
END FUNCTION

FUNCTION sm_sub$ (stringmatha$, stringmathb$)
    operator$ = "-"
    sm_add_subtract_router stringmatha$, operator$, stringmathb$, runningtotal$
    sm_sub$ = runningtotal$
END FUNCTION

FUNCTION sm_mult$ (stringmatha$, stringmathb$)
    DIM AS _INTEGER64 a, c, aa, cc, s, ss
    z$ = "": sign$ = "": mult&& = 0: h&& = 0: i&& = 0: j&& = 0: c = 0: decimal% = 0
    zz$ = "": ii&& = 0: jj&& = 0
    s = 8: ss = 18

    a$ = stringmatha$: b$ = stringmathb$

    IF INSTR(a$, "-") <> 0 OR INSTR(b$, "-") <> 0 THEN
        IF INSTR(a$, "-") <> 0 AND INSTR(b$, "-") <> 0 THEN
            a$ = MID$(a$, 2): b$ = MID$(b$, 2)
        ELSE
            IF INSTR(a$, "-") <> 0 THEN a$ = MID$(a$, 2) ELSE b$ = MID$(b$, 2)
            sign$ = "-"
        END IF
    END IF

    IF INSTR(a$, ".") <> 0 OR INSTR(b$, ".") <> 0 THEN
        decimal% = -1
        IF INSTR(a$, ".") <> 0 THEN
            dec_a&& = LEN(MID$(a$, INSTR(a$, ".") + 1))
            a$ = MID$(a$, 1, INSTR(a$, ".") - 1) + MID$(a$, INSTR(a$, ".") + 1)
        END IF
        IF INSTR(b$, ".") <> 0 THEN
            dec_b&& = LEN(MID$(b$, INSTR(b$, ".") + 1))
            b$ = MID$(b$, 1, INSTR(b$, ".") - 1) + MID$(b$, INSTR(b$, ".") + 1)
        END IF
    END IF

    IF LEN(a$) < LEN(b$) THEN SWAP a$, b$ ' Needed so x1$ is always the largest for leading zero replacements.
    ' Multiplication of digits.
    DO
        h&& = h&& + s: i&& = 0
        x2$ = MID$(b$, LEN(b$) - h&& + 1, s)
        DO
            i&& = i&& + s
            x1$ = MID$(a$, LEN(a$) - i&& + 1, s)
            a = VAL(x1$) * VAL(x2$) + c
            c = 0
            tmp$ = LTRIM$(STR$(a))
            IF LEN(tmp$) > s THEN c = VAL(MID$(tmp$, 1, LEN(tmp$) - s)): tmp$ = MID$(tmp$, LEN(tmp$) - s + 1)
            z$ = STRING$(LEN(x1$) - LEN(tmp$), "0") + tmp$ + z$
        LOOP UNTIL i&& >= LEN(a$) AND c = 0

        jj&& = jj&& + 1

        IF jj&& > 1 THEN
            ii&& = 0: cc = 0
            aa$ = holdaa$
            bb$ = z$ + STRING$((jj&& - 1) * s, "0")
            ' Addition only of digits.
            DO
                ii&& = ii&& + ss
                xx1$ = MID$(aa$, LEN(aa$) - ii&& + 1, ss)
                xx2$ = MID$(bb$, LEN(bb$) - ii&& + 1, ss)
                IF LEN(xx1$) < LEN(xx2$) THEN SWAP xx1$, xx2$
                aa = VAL(xx1$) + VAL(xx2$) + cc
                IF xx1$ + xx2$ = "" AND cc = 0 THEN EXIT DO ' Prevents leading zeros.
                cc = 0
                IF aa > VAL(STRING$(ss, "9")) THEN aa = aa - 10 ^ ss: cc = 1
                tmp$ = LTRIM$(STR$(aa))
                zz$ = STRING$(LEN(xx1$) - LEN(tmp$), "0") + tmp$ + zz$
            LOOP

            DO WHILE LEFT$(zz$, 1) = "0"
                IF LEFT$(zz$, 1) = "0" THEN zz$ = MID$(zz$, 2)
            LOOP
            IF zz$ = "" THEN zz$ = "0"

            holdaa$ = zz$
        ELSE
            holdaa$ = z$ + STRING$(jj&& - 1, "0")
        END IF

        z$ = "": zz$ = ""

    LOOP UNTIL h&& >= LEN(b$)

    z$ = holdaa$

    IF decimal% THEN
        DO UNTIL LEN(z$) >= dec_a&& + dec_b&&
            z$ = "0" + z$
        LOOP

        z$ = MID$(z$, 0, LEN(z$) - (dec_a&& + dec_b&& - 1)) + "." + MID$(z$, LEN(z$) - (dec_a&& + dec_b&&) + 1)

        DO UNTIL RIGHT$(z$, 1) <> "0" AND RIGHT$(z$, 1) <> "."
            z$ = MID$(z$, 1, LEN(z$) - 1)
        LOOP
    END IF

    IF STRING$(LEN(z$), "0") = z$ OR z$ = "" OR z$ = "0" THEN z$ = "0" ELSE z$ = sign$ + z$

    decimal% = 0: sign$ = ""

    runningtotal$ = z$
    sm_mult$ = z$
END FUNCTION

FUNCTION sm_div$ (stringmatha$, stringmathb$)
    hold_stringmatha$ = stringmatha$: hold_stringmathb$ = stringmathb$
    q$ = "": divisor$ = stringmathb$: dividend$ = stringmatha$
    DO ' Falx loop.
        'Strip off neg(s) and determine quotent sign.
        IF LEFT$(divisor$, 1) = "-" THEN divisor$ = MID$(divisor$, 2): q$ = "-"
        IF LEFT$(dividend$, 1) = "-" THEN dividend$ = MID$(dividend$, 2): IF q$ = "-" THEN q$ = "" ELSE q$ = "-"

        ' Quick results for divisor 1 or 0.
        IF dividend$ = "0" THEN q$ = "0": EXIT DO
        IF divisor$ = "1" THEN q$ = dividend$: EXIT DO
        IF divisor$ = "0" THEN q$ = "Division by zero not possible.": EXIT DO

        ' Determine decimal direction. -1 to left, +1 to right.
        gl% = 0: sm_greater_lesser divisor$, dividend$, gl%
        IF betatest% AND gl% = 1 THEN PRINT divisor$; " > "; dividend$; " Move decimal to the left"
        IF betatest% AND gl% = 0 THEN PRINT divisor$; " = "; dividend$
        IF betatest% AND gl% = -1 THEN PRINT divisor$; " < "; dividend$; " Move deciml to the right."
        IF gl% = 1 THEN ' Divisor is larger than dividend so decimal moves to the left.
            div_decimal% = -1 ' Move decimal point to the left.
        ELSEIF gl% = -1 THEN
            div_decimal% = 1 ' Move decimal point to the right.
        ELSE
            ' Divisor and dividend are the same number.
            q$ = q$ + "1": EXIT DO
        END IF
        divisor_ratio_dividend% = gl%

        ' Strip off decimal point(s) and determine places in these next 2 routines.
        dp&& = 0: dp2&& = 0: j2&& = 0
        temp&& = INSTR(divisor$, ".")
        IF temp&& THEN
            divisor$ = MID$(divisor$, 1, temp&& - 1) + MID$(divisor$, temp&& + 1)
            IF temp&& = 1 THEN
                DO UNTIL LEFT$(divisor$, 1) <> "0" ' Strip off any leading zeros on divisor only.
                    divisor$ = MID$(divisor$, 2)
                    dp&& = dp&& + 1
                LOOP
                dp&& = dp&& + 1
            ELSE
                dp&& = -(temp&& - 2)
            END IF
        ELSE
            dp&& = -(LEN(divisor$) - 1)
        END IF
        temp&& = INSTR(dividend$, ".")
        IF temp&& THEN
            dividend$ = MID$(dividend$, 1, temp&& - 1) + MID$(dividend$, temp&& + 1)
            IF temp&& = 1 THEN
                DO UNTIL LEFT$(dividend$, 1) <> "0" ' Strip off any leading zeros on divisor only.
                    dividend$ = MID$(dividend$, 2)
                    dp2&& = dp2&& + 1
                LOOP
                dp2&& = dp2&& + 1
            ELSE
                dp2&& = -(temp&& - 2)
            END IF
        ELSE
            dp2&& = -(LEN(dividend$) - 1)
        END IF
        IF betatest% THEN COLOR 11: PRINT "Divisor decimal moves "; LTRIM$(STR$(dp&&)); ". Dividend decimal moves"; LTRIM$(STR$(dp2&&)); ". Quotent decimal ABS("; LTRIM$(STR$(dp&&)); " - "; LTRIM$(STR$(dp2&&)); ") =";: COLOR 14: PRINT ABS(dp&& - dp2&&);: COLOR 11: PRINT "+ any adjustment.": COLOR 7
        dp&& = ABS(dp&& - dp2&&)

        IF betatest% THEN PRINT "Divisor 1st# = "; MID$(divisor$, 1, 1); "  Remainder 1st# = "; MID$(dividend$, 1, 1)

        ' Adjust decimal place for instances when divisor is larger than remainder the length of the divisor.
        j% = 0
        IF MID$(divisor$, 1, 1) > MID$(dividend$, 1, 1) THEN
            j% = 1
            IF betatest% THEN PRINT "Larger divisor, so move quotent decimal one place back to: ";: COLOR 14: PRINT LTRIM$(STR$(dp&&)): COLOR 7
        ELSEIF MID$(divisor$, 1, 1) = MID$(dividend$, 1, 1) THEN
            IF LEN(divisor$) = LEN(dividend$) THEN
                IF divisor$ > dividend$ THEN j% = 1
            ELSE
                IF LEN(divisor$) > LEN(dividend$) THEN
                    temp$ = dividend$ + STRING$(LEN(divisor$) - LEN(dividend$), "0")
                ELSE
                    temp$ = MID$(dividend$, 1, LEN(divisor$))
                END IF
                IF divisor$ > temp$ THEN j% = 1
            END IF
            IF betatest% THEN
                IF j% THEN PRINT "Larger divisor than dividend at LEN(divisor$), so move quotent decimal one place back to: ";: COLOR 14: PRINT LTRIM$(STR$(dp&&)): COLOR 7
                IF j% = 0 THEN PRINT "Smaller divisor than dividend at LEN(divisor$), so no quotent decimal place adjustment needed. Quotent decimal place = ";: COLOR 14: PRINT LTRIM$(STR$(dp&&)): COLOR 7
            END IF
        ELSE
            j% = 0
            IF betatest% THEN PRINT "Smaller divisor, so no quotent decimal place adjustment needed. Quotent decimal place = ";: COLOR 14: PRINT LTRIM$(STR$(dp&&)): COLOR 7
        END IF
        IF j% THEN dp&& = dp&& - div_decimal%

        origdividend$ = dividend$
        ' Determine length of divisor and dividend to begin initial long divison step.
        gl% = 2: sm_greater_lesser divisor$, MID$(dividend$, 1, LEN(divisor$)) + STRING$(LEN(divisor$) - LEN(dividend$), "0"), gl%
        divisor_ratio_dividend% = gl%
        IF gl% = 1 AND MID$(dividend$, 1, 1) <> "0" THEN
            dividend$ = MID$(dividend$, 1, LEN(divisor$) + 1) + STRING$(LEN(divisor$) + 1 - LEN(dividend$), "0")
        ELSE
            dividend$ = MID$(dividend$, 1, LEN(divisor$)) + STRING$(LEN(divisor$) - LEN(dividend$), "0")
        END IF

        ' Long divison loop. Mult and subtraction of dividend and remainder.
        k&& = 0
        IF betatest% THEN PRINT "Begin long divison loop..."
        DO
            SELECT CASE MID$(divisor$, 1, 1)
                CASE IS < MID$(dividend$, 1, 1)
                    adj_rem_len% = 0
                CASE IS = MID$(dividend$, 1, 1)
                    gl% = 2: sm_greater_lesser divisor$, MID$(dividend$, 1, LEN(divisor$)), gl%
                    IF gl% = 1 THEN adj_rem_len% = 1 ELSE adj_rem_len% = 0
                CASE IS > MID$(dividend$, 1, 1)
                    adj_rem_len% = 1
            END SELECT
            IF j2&& = 0 THEN j2&& = LEN(divisor$) + adj_rem_len%
            DO
                IF LEN(divisor$) > LEN(dividend$) THEN
                    w3&& = 0: runningtotal$ = dividend$: stringmathb$ = "0"
                    IF betatest% THEN PRINT: COLOR 3: PRINT "Divisor is larger so "; dividend$; " \ "; divisor$; " =";: COLOR 5: PRINT w3&&: COLOR 7
                    EXIT DO
                END IF
                IF LEN(divisor$) = LEN(dividend$) THEN
                    gl% = 2: sm_greater_lesser divisor$, dividend$, gl%
                    IF gl% = 1 THEN
                        w3&& = 0: runningtotal$ = dividend$: stringmathb$ = "0"
                        IF betatest% THEN COLOR 9: PRINT "Length of divisor is the same as remainder but remainder is smaller so w3&& = ";: COLOR 5: PRINT "0": COLOR 7
                        EXIT DO
                    END IF
                END IF
                SELECT CASE LEN(dividend$)
                    CASE IS > 2
                        w3&& = VAL(MID$(dividend$, 1, 2 + adj_rem_len%)) \ VAL(MID$(divisor$, 1, 2))
                        IF betatest% THEN PRINT MID$(dividend$, 1, 2 + adj_rem_len%); " \ "; MID$(divisor$, 1, 2); " =";
                    CASE ELSE
                        w3&& = VAL(MID$(dividend$, 1, 1 + adj_rem_len%)) \ VAL(MID$(divisor$, 1, 1))
                        IF betatest% THEN PRINT MID$(dividend$, 1, 1 + adj_rem_len%); " \ "; MID$(divisor$, 1, 1); " =";
                END SELECT
                IF betatest% THEN COLOR 5: PRINT " " + LTRIM$(STR$(w3&&));: COLOR 7: PRINT ". Begin mult est. at or one above this number."
                IF w3&& < 9 THEN w3&& = w3&& + 1 ELSE IF w3&& = 10 THEN w3&& = 9
                DO
                    stringmatha$ = divisor$: stringmathb$ = LTRIM$(STR$(w3&&))
                    runningtotal$ = sm_mult$(divisor$, LTRIM$(STR$(w3&&)))
                    gl% = 2: sm_greater_lesser runningtotal$, dividend$, gl%
                    IF gl% <= 0 OR w3&& = 0 THEN EXIT DO
                    IF betatest% THEN COLOR 8: PRINT "Mult loop:"; w3&&; "* "; divisor$; " = "; runningtotal$: COLOR 7
                    w3&& = w3&& - 1
                LOOP
                stringmatha$ = dividend$: stringmathb$ = runningtotal$
                sm_add_subtract_router dividend$, "-", stringmathb$, runningtotal$
                EXIT DO
            LOOP
            IF betatest% THEN PRINT LTRIM$(STR$(w3&&)); " * "; divisor$; " = "; stringmathb$; " | "; stringmatha$; " - "; stringmathb$; " = "; runningtotal$; " Remainder and drop-down = ";
            j2&& = j2&& + 1
            drop$ = "0": MID$(drop$, 1, 1) = MID$(origdividend$, j2&&, 1)
            IF runningtotal$ <> "0" THEN remainder$ = runningtotal$ ELSE remainder$ = ""
            dividend$ = remainder$ + drop$
            w3$ = LTRIM$(STR$(w3&&))
            temp$ = ""
            IF div_decimal% = -1 THEN
                IF dp&& AND k&& = 0 THEN
                    q$ = q$ + "." + STRING$(dp&& - 1, "0")
                    IF w3&& = 0 THEN w3$ = ""
                END IF
            END IF
            IF div_decimal% >= 0 THEN
                IF dp&& = k&& THEN
                    temp$ = "."
                END IF
            END IF
            q$ = q$ + w3$ + temp$
            IF betatest% AND remainder$ = "" THEN betatemp$ = CHR$(34) + CHR$(34) ELSE IF betatest% THEN betatemp$ = remainder$
            IF betatest% AND MID$(origdividend$, j2&&, 1) = "" THEN betatemp2$ = CHR$(34) + CHR$(34) ELSE IF betatest% THEN betatemp2$ = MID$(origdividend$, j2&&, 1)
            IF betatest% THEN PRINT dividend$; " ("; betatemp$; " +  "; drop$; ") at:"; j2&&; "of "; origdividend$; "  Loop"; k&& + 1; "Quotent = ";: COLOR 14, 4: PRINT q$;: COLOR 7, 0: PRINT: SLEEP
            ' Check to terminate
            IF div_decimal% = -1 THEN
                ' Decimal to left.
                IF remainder$ = "" AND MID$(origdividend$, j2&&, 1) = "" OR LEN(q$) >= limit&& THEN EXIT DO
            ELSE
                ' Decimal to right.
                IF remainder$ = "" AND MID$(origdividend$, j2&&, 1) = "" AND k&& >= dp&& OR LEN(q$) >= limit&& THEN EXIT DO
            END IF

            IF INKEY$ = " " THEN EXIT DO
            k&& = k&& + 1
        LOOP
        EXIT DO
    LOOP
    IF RIGHT$(q$, 1) = "." AND divisor$ <> "0" THEN runningtotal$ = MID$(q$, 1, LEN(q$) - 1) ELSE runningtotal$ = q$
    sm_div$ = runningtotal$
    stringmatha$ = hold_stringmatha$: stringmathb$ = hold_stringmathb$
END FUNCTION

Pete

Print this item

  Cannot convert expression type to symbol
Posted by: eoredson - 09-25-2022, 06:10 AM - Forum: Help Me! - Replies (4)

I have this sample code:

  Common Shared Test() As String * 260

which in the status area displays

  Cannot convert expression type to symbol

and I had to drill down to the function declaration using process of elimination to find.

Problem: the error does not state the line number it is in!

could this be fixed in a future mod of Qb64??

Thanks, Erik.

Print this item

  Tvaders
Posted by: James D Jarvis - 09-23-2022, 07:57 PM - Forum: Works in Progress - Replies (15)

A text-mode space invaders-style game.
It's still got a few rough edges and there's a planned game feature not yet coded (shields) but there's enough of a game to share here as a work in progress.

move left with "a" or "<"  
move right with "d" or ">"
to fire press the spacebar

It plays to level 16 currently.

Code: (Select All)
'Tvaders  1-d01
'by James D. Jarvis   ,   you are of course free to modify and share this code as you like
'
'a text-mode qb64 retro-shooter
'
'$dynamic
Screen _NewImage(100, 35, 0)
_Title "Tvaders 1"
Type spritetype
    s As String
    w As Integer 'i wanted to make this a byte but i want to be a tiny bit backwards compatible for folks with different versions
    sx As Integer
    sy As Integer
    hdg As Integer
End Type
Dim Shared a(16) As spritetype
Dim Shared ps As spritetype
Dim Shared ss(10) As spritetype
Dim Shared b(100) As spritetype
Dim Shared aspace(100, 35)
Dim Shared a$, gflag$
Dim Shared shotmax, shotspeed, shottimer, aliencount, aliendelay, alientimer, alive, level, score
Dim Shared boltmax, bolttimer, boltspeed, alienfire, shields
_ControlChr Off
Randomize Timer
Read a$
Read ship$
Read bolt$
Read shot$
ps.s = ship$
ps.w = 8
ps.sx = 32
ps.sy = 31
a(1).s = a$
a(1).w = 8
a(1).sx = 1
a(1).sy = 3
a(1).hdg = 1
For n = 1 To 100
    b(n).s = bolt$
    b(n).w = 1
    b(n).sx = 0
    b(n).sy = 0
Next n
For n = 1 To 10
    ss(n).s = shot$
    ss(n).w = 2
    ss(n).sx = 0
    ss(n).sy = 0
Next n
gflag$ = "GAMEON"
shotmax = 3
shotspeed = 10
shottimer = 0
aliencount = 1
aliendelay = 20
alientimer = 0
alive = aliencounter
level = 1
boltmax = 100
bolttimer = 0
boltspeed = 9


startlevel level
Do
    _Limit 60
    handleshots
    handlealiens
    handlezaps

    Cls
    Locate 1, 1
    Print "LEVEL : "; level
    Locate 1, 40
    Print "Shields : "; shields
    Locate 1, 70
    Print "SCORE : "; score
    Locate 2, 1
    Print "ALive "; alive
    If gflag$ = "BOOM" Then doboom
    For bc = 1 To 100
        If b(bc).sx > 0 Then splat b(bc).s, b(bc).w, b(bc).sx, b(bc).sy
    Next bc

    For ac = 1 To aliencount
        If a(ac).sx > 0 Then
            splat a(ac).s, a(ac).w, a(ac).sx, a(ac).sy

        End If
    Next ac

    splat ps.s, ps.w, ps.sx, ps.sy
    For s = 1 To shotmax
        If ss(s).sx <> 0 Then splat ss(s).s, ss(s).w, ss(s).sx, ss(s).sy
    Next s

    kk$ = InKey$
    If LCase$(kk$) = "a" Or kk$ = "," Or kk$ = "<" Then ps.sx = ps.sx - 1
    If LCase$(kk$) = "d" Or kk$ = "." Or kk$ = ">" Then ps.sx = ps.sx + 1
    If kk$ = " " Then fire ps.sx + 3
    If ps.sx < 1 Then ps.sx = 1
    If ps.sx > 92 Then ps.sx = 92
    If alive < 1 Then nextlevel level
    _Display
Loop Until kk$ = Chr$(27) Or gflag$ = "GAMEOVER"


System

'sprites were orignally drawn in ascii tilemaker and stripped out of the data file without the color data for use here
Data "ÛÛÛÛÛÛÛÛ Û0  0Û ÛÛÛÛÛÛÛÛ ^ ^^ ^ "
Data "   ²²      ÎΠ    ²²²²  ²²^²²^²²"
Data "/\/"
Data "##^^"


Sub fire (fx)
    shotfound = 0
    noshots = 0
    Do
        noshots = noshots + 1
        If ss(noshots).sx = 0 Then shotfound = noshots
    Loop Until shotfound > 0 Or noshots = shotmax
    If shotfound > 0 Then
        ss(shotfound).sx = fx
        ss(shotfound).sy = ps.sy - 2
    End If
End Sub

Sub zap (zx, zy)
    zapfound = 0
    zapcount = 0
    Do
        zapcount = zapcount + 1
        If b(zapcount).sx = 0 Then zapfound = zapcount
    Loop Until zapfound > 1 Or zapcount = boltmax
    If zapcount > 0 Then
        b(zapcount).sx = zx + 4
        b(zapcount).sy = zy + 3
    End If

End Sub
Sub handlezaps
    bolttimer = bolttimer + 1
    If bolttimer = boltspeed Then
        bolttimer = 0
        For n = 1 To 100
            If b(n).sx > 0 Then
                b(n).sy = b(n).sy + 1
                If b(n).sy = 33 Then
                    b(n).sx = 0
                    b(n).sy = 0
                End If
                If b(n).sy = 31 Then
                    For xx = ps.sx To ps.sx + 7
                        If b(n).sx = xx Then playerhit$ = "BOOM"
                        If playerhit$ = "BOOM" Then
                            For rr = 1 To 20
                                _Limit 150
                                For d = 1 To 300
                                    _PrintString (2 + Int(Rnd * 98), 5 + Int(Rnd * 30)), "*"
                                Next d
                                _PrintString (b(n).sx + Int(Rnd * 3), b(n).sy + Int(Rnd * 3)), "BOOM!"
                                gflag$ = "BOOM"
                                _Display

                            Next rr
                        End If
                    Next xx
                End If
            End If
        Next n
    End If
End Sub


Sub handleshots
    shottimer = shottimer + 1
    If shottimer = shotspeed Then
        hittag$ = "miss"
        For s = 1 To shotmax
            For aa = 1 To aliencount
                If a(aa).sx > 0 Then
                    sl = Len(a(aa).s)
                    sh = sl / a(aa).w
                    For y = 1 To sh
                        For x = 1 To a(aa).w
                            If a(aa).sx + x - 1 = ss(s).sx And a(aa).sy + y - 1 = ss(s).sy And hittag$ = "miss" Then hittag$ = "hit"
                        Next x
                    Next
                End If

                If hittag$ = "hit" Then
                    ss(s).sx = 0
                    a(aa).sx = 0
                    alive = alive - 1
                    hittag$ = "miss"
                    score = score + 100
                    Beep
                End If
            Next aa


            ss(s).sy = ss(s).sy - 2
            If ss(s).sy < 1 Then
                ss(s).sx = 0
                ss(s).sy = 0
            End If
        Next s
        shottimer = 0
    End If
End Sub

Sub handlealiens
    alientimer = alientimer + 1
    If alientimer > 32000 Then alientimer = 1
    For n = 1 To aliencount
        If a(n).sx > 0 And (alientimer Mod aliendelay = 0) Then

            a(n).sx = a(n).sx + a(n).hdg
            If a(n).sx > 92 Then
                a(n).sx = 92
                a(n).sy = a(n).sy + 2
                a(n).hdg = a(n).hdg * -1
            End If
            If a(n).sx < 1 Then
                a(n).sx = 1
                a(n).sy = a(n).sy + 2
                a(n).hdg = a(n).hdg * -1
            End If
            If 1 + Int(Rnd * 100) <= alienfire Then zap a(n).sx, a(n).sy

            If a(n).sy = 31 Then

                For xx = ps.sx To ps.sx + 7
                    If a(n).sx = xx Then playerhit$ = "BOOM"
                    If playerhit$ = "BOOM" Then
                        For rr = 1 To 20
                            _Limit 150
                            For d = 1 To 300
                                _PrintString (2 + Int(Rnd * 98), 5 + Int(Rnd * 30)), "*"
                            Next d
                            _PrintString (a(n).sx + Int(Rnd * 3), a(n).sy + Int(Rnd * 3)), "BOOM!"
                            gflag$ = "BOOM"
                            _Display

                        Next rr
                    End If
                Next xx


            End If

        End If
    Next
End Sub




Sub splat (SA$, ww As Integer, sx As Integer, sy As Integer)
    sl = Len(SA$)
    sh = sl / ww
    For y = 1 To sh
        _PrintString (sx, sy - 1 + y), Mid$(SA$, (y - 1) * ww + 1, ww)
    Next
End Sub

Sub startlevel (level)
    For bb = 1 To 100
        b(bb).sx = 0
        b(bb).sy = 0
    Next bb


    Select Case level
        Case 1
            aliencount = 1
            alive = 1
            aliendelay = 20
            a(1).s = a$
            a(1).w = 8
            a(1).sx = 46
            a(1).sy = 3
            a(1).hdg = 1
            shields = 0
            score = 0
            alienfire = 0
        Case 2
            aliencount = 3
            alive = 3
            aliendelay = 20
            For n = 1 To aliencount
                a(n).s = a$
                a(n).w = 8
                a(n).sx = n * 12 + 30
                a(n).sy = 3
                a(n).hdg = 1
            Next n
            shields = 3
            alienfire = 2
        Case 3
            aliencount = 5
            alive = 5
            aliendelay = 19
            For n = 1 To aliencount
                a(n).s = a$
                a(n).w = 8
                a(n).sx = n * 11 + 20
                a(n).sy = 4
                a(n).hdg = 1
            Next n
            shields = shields + 2
            alienfire = 4
        Case 4
            aliencount = 6
            alive = 6
            aliendelay = 19
            For n = 1 To aliencount
                a(n).s = a$
                a(n).w = 8
                a(n).sx = n * 15
                a(n).sy = 5
                a(n).hdg = 1
            Next n
            shields = shields + 2
            alienfire = 6
        Case 5
            aliencount = 7
            alive = 7
            aliendelay = 18
            For n = 1 To aliencount
                a(n).s = a$
                a(n).w = 8
                a(n).hdg = 1
            Next n
            For n = 1 To 5
                a(n).sx = n * 15
                a(n).sy = 1
            Next n
            For n = 6 To 7
                a(n).sx = (n - 5) * 35
                a(n).sy = 5
            Next n

            shields = shields + 2
            alienfire = 6
        Case 6
            aliencount = 8
            alive = 8
            aliendelay = 18
            For n = 1 To aliencount
                a(n).s = a$
                a(n).w = 8
                a(n).hdg = 1
            Next n
            For n = 1 To 3
                a(n).sx = n * 25
                a(n).sy = 3
            Next n
            For n = 4 To aliencount
                a(n).sx = (n - 3) * 12
                a(n).sy = 7
            Next n

            shields = shields + 2
            alienfire = 8
        Case 7
            aliencount = 9
            alive = 9
            aliendelay = 17
            For n = 1 To aliencount
                a(n).s = a$
                a(n).w = 8
                a(n).hdg = 1
            Next n
            For n = 1 To 3
                a(n).sx = n * 12
                a(n).sy = 3
            Next n
            For n = 4 To 6
                a(n).sx = (n - 3) * 12 + 30
                a(n).sy = 7
                a(n).hdg = -1
            Next n
            For n = 7 To 9
                a(n).sx = (n - 6) * 12
                a(n).sy = 11
            Next n


            shields = shields + 2
            alienfire = 8
        Case 8
            aliencount = 10
            alive = 10
            aliendelay = 17
            For n = 1 To aliencount
                a(n).s = a$
                a(n).w = 8
                a(n).hdg = Int(Rnd * 2) - 1
                If a(n).hdg = 0 Then a(n).hdg = 1
                a(n).sx = 12 + Int(Rnd * 8) * 8
                a(n).sy = 1 + Int(Rnd * 3) * 4
            Next n

            shields = shields + 2
            alienfire = 9
        Case 9
            aliencount = 11
            alive = 11
            aliendelay = 16
            For n = 1 To aliencount
                a(n).s = a$
                a(n).w = 8
                a(n).hdg = -2
            Next n
            For n = 1 To 5
                a(n).sx = n * 12 + 12
                a(n).sy = 3

            Next n
            For n = 6 To aliencount
                a(n).sx = (n - 5) * 8
                a(n).sy = 7
            Next n
            shields = shields + 2
            alienfire = 9
        Case 10
            aliencount = 12
            alive = 12
            aliendelay = 16
            For n = 1 To aliencount
                a(n).s = a$
                a(n).w = 8
                a(n).hdg = Int(Rnd * 4) - 2
                If a(n).hdg = 0 Then a(n).hdg = 1
                a(n).sx = 12 + Int(Rnd * 8) * 8
                a(n).sy = 1 + Int(Rnd * 3) * 4
            Next n


            shields = shields + 1
            alienfire = 10
        Case 11
            aliencount = 13
            alive = 13
            aliendelay = 15
            For n = 1 To aliencount
                a(n).s = a$
                a(n).w = 8
                a(n).hdg = -2
            Next n

            For n = 1 To 7
                a(n).sx = n * 12
                a(n).sy = 1 + Int(Rnd * 3) * 4
            Next n

            For n = 8 To aliencount
                a(n).sx = (n - 7) * 12
                a(n).sy = 13
            Next n


            shields = shields + 1
            alienfire = 1
        Case 12
            aliencount = 14
            alive = 14
            aliendelay = 14


            For n = 1 To aliencount
                a(n).s = a$
                a(n).w = 8
            Next n

            For n = 1 To 7
                a(n).sx = n * 9
                a(n).sy = 1
                a(n).hdg = -2
            Next n

            For n = 8 To aliencount
                a(n).sx = (n - 7) * 9
                a(n).sy = 11
                a(n).hdg = 2
            Next n



            shields = shields + 1
            alienfire = 11
        Case 13
            aliencount = 15

            alive = 15
            aliendelay = 13
            For n = 1 To aliencount
                a(n).s = a$
                a(n).w = 8
            Next n

            For n = 1 To 10
                a(n).sx = (n * 9) - 8
                a(n).sy = 2
                a(n).hdg = -2
            Next n

            For n = 11 To aliencount
                a(n).sx = (n - 10) * 9
                a(n).sy = 9
                a(n).hdg = 3
            Next n


            shields = shields + 1
            alienfire = 12
        Case 14
            aliencount = 16
            alive = 16
            aliendelay = 12
            For n = 1 To aliencount
                a(n).s = a$
                a(n).w = 8
            Next n

            For n = 1 To 8
                a(n).sx = (n * 9) - 8
                a(n).sy = 2
                a(n).hdg = -3
            Next n

            For n = 9 To aliencount
                a(n).sx = (n - 8) * 9
                a(n).sy = 11
                a(n).hdg = 3
            Next n

            shields = shields + 1
            alienfire = 13
        Case 15
            aliencount = 16
            alive = 16
            aliendelay = 10
            For n = 1 To aliencount
                a(n).s = a$
                a(n).w = 8
            Next n

            For n = 1 To 9
                a(n).sx = (n * 9) - 8
                a(n).sy = 4
                a(n).hdg = -3
            Next n

            For n = 10 To 14
                a(n).sx = (n - 9) * 9 + 4
                a(n).sy = 9
                a(n).hdg = 3
            Next n
            For n = 15 To aliencount
                a(n).sx = (n - 14) * 20 + 40
                a(n).sy = 13
                a(n).hdg = 4
            Next n



            shields = shields + 1
            alienfire = 14
        Case 16
            aliencount = 16
            alive = 16
            aliendelay = 8
            For n = 1 To aliencount
                a(n).s = a$
                a(n).w = 8
                a(n).hdg = Int(Rnd * 8) - 4
                If a(n).hdg = 0 Then a(n).hdg = 4
            Next n

            For x = 0 To 3
                For y = 1 To 4
                    a(x * 4 + y).sx = x * 20
                    a(x * 4 + y).sy = y * 5
                Next y
            Next x



            shields = shields + 1
            alienfire = 15

    End Select
End Sub

Sub nextlevel (level)
    If level < 17 Then
        score = score + level * 1000
        Locate 10, 10
        Cls
        _KeyClear
        Print "*********************************************************"
        Print "*                                                       *"
        Print "*                 COMPLETED LEVEL                       *"
        Print "*                                                       *"
        Print "*                 PRESS ANY KEY                         *"
        Print "*                                                       *"
        Print "*               TO START NEXT LEVEL                     *"
        Print "*                                                       *"
        Print "*                                                       *"
        Print "*********************************************************"
        _Display
        any$ = Input$(1)
        level = level + 1
        If level < 17 Then startlevel level
        If level = 17 Then gameflag$ = "GAMEOVER"

    End If
    If level = 17 Or gameflag$ = "GAMEOVER" Then
        Cls
        Locate 10, 10
        _KeyClear
        Print "*********************************************************"
        Print "*                                                       *"
        Print "                    CONGRATULATIONS !                    "
        Print "*                                                       *"
        Print "              You Have Defeated the ALIENs!              "
        Print "*                                                       *"
        Print
        Print "           FINAL SCORE : "; score
        Print
        Print "*                 PRESS Y to Play again                 *"
        Print "                                                         "
        Print "*                                                       *"
        Print "*********************************************************"
        _Display
        any$ = Input$(1)
        If any$ = "y" Or any$ = "Y" Then
            gfla$ = "GAMEON"
            startlevel 1

        Else
            Cls

            gflag$ = "GAMEOVER"
        End If

    End If

End Sub
Sub doboom


    _KeyClear
    Locate 10, 10: Print "*********************************************************"
    Locate 11, 10: Print "* ÛÛÛÛÛÛÛÛ                                              *"
    Locate 12, 10: Print "   Û0  0Û          B O O M !                             "
    Locate 13, 10: Print "* ÛÛÛÛÛÛÛÛ                                              *"
    Locate 14, 10: Print "   ^ ^^ ^    You Were Defeated by the ALIENs!              "
    Locate 15, 10: Print "*                                                       *"
    Locate 16, 10: Print
    Locate 17, 10: Print "           FINAL SCORE : "; score
    Locate 18, 10: Print
    Locate 19, 10: Print "*                 PRESS Y to Play again       ÛÛÛÛÛÛÛÛ  *"
    Locate 20, 10: Print "       ÛÛÛÛÛÛÛÛ                                Û0  0Û    "
    Locate 21, 10: Print "*       Û0  0Û                                ÛÛÛÛÛÛÛÛ   *"
    Locate 22, 10: Print "*********************************************************"
    _Display
    any$ = Input$(1)
    If any$ = "y" Or any$ = "Y" Then
        gflag$ = "GAMEON"
        startlevel 1

    Else
        Cls

        gflag$ = "GAMEOVER"
    End If

End Sub

Print this item

  my kid and the microbit
Posted by: James D Jarvis - 09-23-2022, 01:53 PM - Forum: General Discussion - No Replies

My youngest kid just got to fiddle with a microbit in school this week in STEM lab class and rushed home and wrote a space invaders game in smalltalk and javascript in an emulator to try in class. They are a nifty little gadget. The kid liked it so much we ordered one online last night (with a fancy power supply so it can work without being plugged into another device, well....a battery attachment.)  

I of course looked into it and sure enough some folks are programming for them in BASIC. Anyone here know anything else about microbits and BASIC?

Print this item

  Any math experts know what I'm missing here? [Solved]
Posted by: Pete - 09-23-2022, 12:23 AM - Forum: Help Me! - Replies (24)

Print this item