💾 Archived View for thrig.me › blog › 2024 › 05 › 08 › old-math.gmi captured on 2024-05-10 at 10:49:14. Gemini links have been rewritten to link to archived content

View Raw

More Information

-=-=-=-=-=-=-

Old Math

Or, unpacking some BASIC from some version of Oregon Trail (1971). For some 1971 will be extremely recent, but the context is computer games which have not got much history, yet.

    RND(0)*10>((M/100-4)^2+72)/((M/100-4)^2+12)-1

AppleSoft RND returns "the same number" for RND(0) which here would likely not make sense, so we will assume that RND(0) returns something in the 0..1 range, times 10. A math type might look at the rest of the equation and could tell you things about it; for us neck-bearded unix admins another method is to plug numbers into it.

But first we need to have code that works, and hopefully not introduce errors during that process. This is where worked examples are beneficial, as someone then will have data points on what you thought the code should do. Luckily there is some context here that M is for miles and that the Oregon Trail is less than 3,000 miles in length.

    $ perl -E '$M=100;say( (($M/100-4)**2+72)/(($M/100-4)**2+12)-1 )'
    2.85714285714286
    $ perl -E '$M=1000;say( (($M/100-4)**2+72)/(($M/100-4)**2+12)-1 )'
    1.25
    $ perl -E '$M=3000;say( (($M/100-4)**2+72)/(($M/100-4)**2+12)-1 )'
    0.0872093023255813

This is an easy conversion; prefix "M" with a "$" and change any "^" to "**", try some numbers. Converting it to Common LISP is a bit more work, though may better show the structure of the equation, and gives us a second opinion that our numbers are at least wrong in the exact same way (or, possibly, are right).

    (defun calc (miles)
      (1- (/ (+ (expt (- (/ miles 100) 4) 2) 72)
             (+ (expt (- (/ miles 100) 4) 2) 12))))
    (dolist (m '(100 1000 3000))
      (format t "~&~f~&" (calc m)))

The results are the same as the Perl, so if we made an error we made the same error using two very different syntax (but using the same brain that may be prone to the same problem, which is where opinions from other people can help).

    $ sbcl --script oregon-trail-danger.lisp
    2.857143
    1.25
    0.0872093

And now with a loop we can table the equation. I'm using a custom program to feed LISP from vi(1) to SBCL, hence the up-casing of the code.

    SBCL> (LOOP FOR M FROM 0 TO 3000 BY 100
                DO (FORMAT T "~&~d ~f~&" M (CALC M)))
    0 2.142857
    100 2.857143
    200 3.75
    300 4.6153846
    400 5.0
    500 4.6153846
    600 3.75
    700 2.857143
    800 2.142857
    900 1.6216216
    1000 1.25
    1100 0.9836066
    1200 0.7894737
    1300 0.6451613
    1400 0.53571427
    1500 0.45112783
    1600 0.3846154
    1700 0.3314917
    1800 0.28846154
    1900 0.25316456
    2000 0.2238806
    2100 0.19933555
    2200 0.17857143
    2300 0.16085792
    2400 0.14563107
    ...
    SBCL> (LOOP FOR M FROM 0 TO 1000 BY 50
                DO (FORMAT T "~&~d ~f~&" M (CALC M)))
    0 2.142857
    50 2.4742267
    100 2.857143
    150 3.2876713
    200 3.75
    250 4.2105265
    300 4.6153846
    350 4.897959
    400 5.0
    450 4.897959
    500 4.6153846
    550 4.2105265
    600 3.75
    650 3.2876713
    700 2.857143
    750 2.4742267
    800 2.142857
    850 1.8604652
    900 1.6216216
    950 1.4201183
    1000 1.25
    NIL

This is a probability distribution curve; other instances of such code would be rnz from NetHack.

https://nethackwiki.com/wiki/Rnz

Enjoy!

Such equations can be built up and fiddled around with until they give roughly the the desired results. Generating an equation on the fly (for example if the distances or danger levels vary depending on the location or other details) would be a bit more work, but not impossible. Players of Oregon Trail may learn of the equation (or intuit it) and might try to move quicker around the 400 mile mark? (The code involves how likely an attack is on any given turn.)