Thankful For Mathematics

Making this post to appreciate the TADS 3 system, for all the functions available to the BigNumber class.

You didn’t have to give us 32 digits of precision, trigonometry functions, sqrt, and so much more. How many IF titles do you think would have used such things?

Well, when you’re implementing heckin’ orbital mechanics into an IF game, suddenly you’re using all of those functions at their full 32 digits of precision.

So thank you for going the extra mile to implement these into the library for us TADS 3 authors to use.

6 Likes

On the one hand yeah, it’s nice to have 'em. On the other hand arithmetic with BigNumbers is sloooooow. Like painfully slow. If you’re just doing one or two calculations per turn it’s not too bad, but you really can’t do anything too involved or things are going to slow to a crawl, even on a modern, comparatively high-end computer.

Really I think if you were designing an IF authoring system from scratch today and wanted to ensure portability (the reason for using a bespoke virtual machine in Inform and TADS) you’d be better off going with something like JavaScript (or Python), which will run more or less everywhere these days (although I don’t know how many JS implementations are available on retro hardware, for people that care about that sort of thing) and in-browser or CLI (via node) is blazingly fast, particularly with anything involving floating point or bitwise opeations, compared to TADS3.

I tried doing a bunch of comparatively elaborate AI stuff for NPCs in my WIP and had to scale back/scrap a lot of it because it’s just not practical to do anything that involves a bunch of iterations (involving BigNumber math) every turn. Like I implemented a fast integer sqrt() in TADS3 specifically because BigNumber.sqrt() was too slow.

Glad it’s working for your purposes, though. Sounds like a cool project.

2 Likes

Here’s the problem, though: There’s no Adv3Lite on JavaScript, and I’m not making a whole parser game library for JavaScript that aims to work as well as Adv3Lite.

But yeah, the slowdown is something I’m trying to keep in mind. Most stuff in the game will use a lot simpler math. The really complex elliptical stuff will only be used by the player character, for the most part.

I think a lot of the slowdown comes from garbage collection, too. Any time I can reuse stuff, I do. Every time a BigNumber is created, it’s a new object, I think, and it’s gotta get cleaned up by the end.

Wondering what I could get away with by building and approximation from the real math, and then interpolating between points of the approximation.

4 Likes

Sorry I meant to write more but had to drive to something for a bit. I also just want to state for the record that I’m just sorta dumping my thoughts right now. These are not meant to be counter-arguments or anything; you are 100% correct about the concerns of BigNumber lag.


Another thing I wanted to say was that orbital mechanics (when you’re using conic approximations) don’t require (as much) iteration, compared to a full n-body physics simulation. You just need a moment in time, measured in seconds, and it gives you the true anomaly (angle/theta) and radius.

Even then, the algorithm (yes, algorithm, because Kepler hates you) to find true anomaly can get really expensive.

So to explain more about this:

I was thinking of having a basic orbit object, and then a “baked” orbit object, where after all the adjustments are made, the baked version divides the period into 36 segments of time (uniting true anomaly, radius, and time, ideally as approximated integers). That way, if I want to find an orbital position at a certain time from a baked orbit, I’m dealing with only integers, up until the single interpolation bit.

Of course, orbital mechanics normally requires way more precision than this. In fact, this subject is quite notorious for testing the extreme limits of data precision, for this reason.

However, the benefit of writing an IF title that will convey things through text is that the player is not able to see the rough outline of the orbit, and it still functions about the same.

Worst case scenario, a fellow enthusiast will check my math, and I’ll be off by less than 10% maybe, but I’m certain they’ll understand lol.

The only reason why I’m going through this much work is:

  1. I’m an orbital mechanics enthusiast.
  2. I would like some way for a nav computer to help the player schedule things like intercepts, fly-bys, captures, etc. Even if the actual fine-tuning will be handled by the computer, the computer still needs a way to plot things over time and position.

The main concern I have with BigNumber lag is that while I have experienced it in a previous project, I am also currently running on a Linux, which was originally designed to be an overnight hobbyist-level “supercomputer”. I had to move to this as my main rig after I lost my laptop for a while, but now I can’t go back lol. (Turns out I don’t do enough stuff that absolutely requires a GPU to run.)

So, there’s always going to be a nagging concern in the back of my mind that the lag will be way more noticeable for someone else, when I’m not seeing it at all. Once I get this to a testing state, I would love to have someone on a really low-end rig try it, and let me know if it’s unplayable. I don’t want to inadvertently create the IF sphere’s version of “but can it run Crysis?”.

3 Likes

well, being a Naval historian, Naval fire control equations are my run-of-mill general programming problem, whose are best tackled with general programming language (I tend to use Fortran)

and, the best site for an orbital mechanics enthutiast:

Virtual Apollo Guidance Computer

Best regards from Italy,
dott. Piergiorgio.

3 Likes

Oh yeah, I understand. I meant generic “you”: anyone who sat down to implement a new IF authoring system today would probably be better off using one of the many languages/environments that already exist on virtually every platform instead of rolling their own virtual machine.

It’s difficult to isolate the exact trouble spots (because afaik there aren’t debugging tools like valgrind or gdb or anything like that for TADS3 code), but in my testing there wasn’t really any way to squeeze better performance out of it by doing a lot of hand-holding for memory management. Like you can assign two variables to random BigNumber values and then iterate through a big loop where you’re discarding any results involving them (e.g. by just putting a comparison in a conditional) and it’s still several orders of magnitude slower than doing the same thing with integers. I assume this tells us that the compiler isn’t taking advantage of anything available on the local architecture and is just using its own floating point implementation in the vm. I haven’t tried digging through the source code to be sure though.

I don’t know what your basic gameplay loop is going to look like, but if the player always has some physical constraints on how they can approach problems (that is, only so much fuel/specific thrust/delta v/whatever) and you know the orbits they’re going to be doing/attempting, you can probably just precompute a whole bunch of orbital elements for “valid” (as in orbit successfully achieved) solutions and then handle them at runtime via lookup table instead of computation. And then handle failure states (spin endlessly through space, smoking crater, whatever) via canned failure messages. Because although TADS doesn’t let you take advantage of modern computer architectures computationally, the huge amounts of memory/disk we have today are something that it’s fairly easy to take advantage of.

So basically the thing you’re talking about above (computing the orbital elements for a given game state, storing the results, and then interpolating to get a value at a specific point in the orbit) is absolutely a valid approach, but you can think much bigger.

For example, I wrote a poker-playing AI in TADS3/adv3 that’s about 90% table lookups, which means that it takes less time than evaluating the parse tree for the typed command.

You will get the compiler complaining if you store very large arrays; t3make by default worries about whether or not your game will run on a 16 bit machine, but you can suppress the warnings by compiling with the -w-15001 flag.

2 Likes

Oh, fascinating…! I was considering doing this at first, but I had some concerns about hitting some kind of memory limit. I wasn’t sure what TADS3 considers “too much”.

But yeah, the player will be stringing together transfers, slingshots, captures, etc, but it’ll be using only pre-determined altitudes. One concern was initial pre-computation time, and also (again) memory ceilings.

This was something I did in a C# version of this kinda game idea, but the loading time was rather long, and this was in C#.

2 Likes

It’s unfortunate that the T3VM doesn’t have any floating point opcodes. I’m not trying to convert anyone, but if anyone’s project truly does need a lot of floating point maths and it’s running far too slowly, Glulx now has both 32 and 64 bit floating point opcodes. They’re usable from both Inform 6 and 7.

4 Likes

You can precompute the values using a PreinitObject, which executes after compilation but before runtime (for release builds, at least, but t3make can be configured to do it for debug as well). If the precomputed values are stored in a global table, it will be saved in the image file.

3 Likes

How widely-supported are the double opcodes at this point? I didn’t realize any interpreters supported them yet.

1 Like

Parchment, Lectrote, Windows Glk, Spatterlight all already support them, and Gargoyle will in the next release. The main gap is the mobile interpreters.

2 Likes

Wait, what???

You can code in stuff to be pre-computed, and it saves the results during author compile, so it doesn’t happen during the player starting the game???

Jim, you are going to absolutely blow my mind, if I’m understanding you correctly. This changes everything.

2 Likes