mdbtxt1
mdbtxt2
Proceed to Safety

LNGI Incremental (large numbers game by Katakana)    

LNGI (Large Number Growth Incremental) is an incremental game with fairly straightforward gameplay based on using exponential, tetrational, and pentational growth functions. It is a bit minimalistic in not having any fancy graphics or plot to embellish the large numbers — it is just about making large numbers and nothing fancier than that.

I am a part of the community of xkcd fans that resulted in the incremental game Sandcastle Builder. Inspired by the complexity of that game, I sought out a simpler incremental game and found LNGI. I eventually created a slightly embellished version of LNGI called the Long Wait-For-It (LWFI), containing inside jokes, a bit of graphics that you see when you "win" the game, and an educational interactive mini-game with sliders to generate numbers using exponentiation, tetration, and pentation.

By this time, Eternal Density had also created the minimal incremental game Pure Idle, so I retconned the history of minimal incremental games with my series of games:

Bug Fixes

While working on LNGI for my ottification I discovered problems with the actual numerical calculations in LNGI. These caused odd behaviour in the pentation upgrade gameplay, as well as visual bugs having to do with the number of significant digits in scientific notation displays.

Bug fixes for the loga3() function

LNGI has a "pentational logarithm" function loga3() that is used in a later stage of the game to determine how many "pentation points" you can redeem. I found that it was not monotonic. To fix it, I modified two of the cases in its if..then..else if sequence; I also added flags that allow for debugging, and a demonstration function doing a series of tests on loga3().

// Pentation log var fix_loga3 = true; var la3_debug = false; function loga3(onum) { var inp = ''; if (la3_debug) { inp = JSON.stringify(onum) + "==" + notate(onum,1); // we'll log this } var rv = 0; // The value we'll return, also so we can log it var cs = 0; // Only for showing which if..then..else was triggered if (onum.array.length > 4) { // The number is so big that its pentational log is effectively equal to // the number itself. See mrob.com/pub/math/largenum-2.html#uncomparable rv = O(onum); cs = 1; } else if (onum.array.length == 4) { // The number is a pentational tower where array[3] is the height of // the stack, and array[2], array[1] is the stuff on top, so the // pentational log is the same stack but with 1 less height onum.array[3]--; rv = O(onum); cs = 2; } else if (onum.array.length == 3) { // The number is a tetrational tower, and array[2] is the height // (how many copies of "10^^") with array[1] at the top. if (fix_loga3) { rv = O(onum.array[2]).add(1); // Add 1 assuming top is > 10 cs = 3; } else { rv = O(onum.array[2]); cs = 4; } } else if (onum.array.length == 2 && onum.array[1] >= 10) { // Normal power-tower of height array[1] which is 10 or more // This means it is at least 10^^10 which is 10^^^2 rv = O(2); cs = 5; } else if ((!fix_loga3) && (onum.array[1] < 10 || onum.array.length == 1)) { // Shorter power-tower, but big enough to need an array (therefore more // than 1.798e308) rv = O(1); cs = 6; } else if (fix_loga3 && (onum.array.length >= 1)) { // Not sure how this doesn't trigger the previous case rv = O(1); cs = 7; } else { // A sinple number like "7" or "6.02e23" rv = O(0); cs = 8; } if (la3_debug) { console.log(" loga3(" + inp + ") -> " + notate(rv, 1) + " (case " + cs + ")"); } return rv; } // Demonstration of a bug in loga3() that is fixed by // mrob.com/time/LWFI/lwfi.js function test_la3(s) { var t1 = O(s); console.log(" loga3("+s+" == "+t1.toString()+") = "+loga3(t1).toString()); } function show_la3_bug1() { la3_debug = true; for (const fa3 of [false, true]) { fix_loga3 = fa3; console.log("When fix_loga3 is " + fix_loga3 + ":"); test_la3("10^^9"); // "ought to be" 1 test_la3("10^^200"); // 2 test_la3("10^^10^1000"); // 2 test_la3("10^^10^^9"); // 2 test_la3("10^^10^^200"); // 3 test_la3("10^^10^^10^1000"); // 3 test_la3("10^^10^^10^^9"); // 3 test_la3("10^^10^^10^^200"); // 4 test_la3("10^^10^^10^^10^1000"); // 4 } fix_loga3 = true; la3_debug = false; }

The notate() function

LNGI also has its own number-to-string formatting function that is a little better than the toString() function provided by OmegaNum. I found that it had a somewhat counter-intuitive behaviour of going from 7 significant digits to only three at the 106 boundary: for example, supposing that you pass 1 for the 2nd parameter of notate(), 106/7 is formatted as 142857.1, while 107/7 becomes 1.4e7. This is a rather jarring transition that appears many times while playing LNGI. To make the transition smoother I altered notate() to the following:

// toPrecision without any + sign in the exponent function toP(n, p) { var s = n.toPrecision(p); if (s.indexOf('+') >= 0) { s = s.replace(/\+/, ''); } return s; }    // How to write things ingame function notate(omgnum,fp) { if(O(omgnum).lt("1e6")){ return O(omgnum).toNumber().toFixed(fp); } else if (O(omgnum).lt("1e10")){ return toP(parseFloat(O(omgnum).toString()),fp+3); } else if (O(omgnum).lt("1e100")){ return toP(parseFloat(O(omgnum).toString()),fp+2); } else if (O(omgnum).lt("1e300")){ return toP(parseFloat(O(omgnum).toString()),fp+1); } else if(O(omgnum).lt("ee6")){ return O(omgnum).div(O(10).pow(O(omgnum).log10().floor())) .toNumber().toFixed(fp) + "e" + O(omgnum).log10().floor(); } else if(O(omgnum).slog(10).lt(10)) { return "e" + notate(O(omgnum).log10(),fp); } else if(O(omgnum).lt("10^^^5")) { return "10^^" + notate(O(omgnum).slog(10),fp); } else { return O(omgnum).toHyperE(); } }


Robert Munafo's home pages on AWS    © 1996-2024 Robert P. Munafo.    about    contact
This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License. Details here.

This page was written in the "embarrassingly readable" markup language RHTF, and was last updated on 2024 Aug 24. s.27