💾 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
-=-=-=-=-=-=-
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.)