Hacker Newsnew | past | comments | ask | show | jobs | submit | SeenNotHeard's commentslogin

One limitation not mentioned is that Action! didn't support recursion. This had to do with how local variables were stored.

Whether it was the best language for 8-bit programming, it certainly was a great fit for the 6502, as the language targeted the peculiarities of that chip. Accessing hardware-specific features of the 8-bit Atari's was a snap, which was necessary in order to do anything more interesting than sieves or print loops.

Action! probably could've been ported to the Apple line, but 8-bits were winding down by the time it was released. Porting to 16-bit machines like the IBM PC or Mac (or even the Atari ST) would have been a tougher sell, since Pascal and C were better established by that point, and worked well on those machines.

Two bad things about Action!: Charging a license fee to distribute the runtime, and that dumb bang in the name.


The lack of recursion was not a practical limitation on the Atari. Base systems were 16K and you really didn't have space for recursion. And the license fee for the runtime didn't feel that painful compared to the other options.


I think a bigger problem for recursion support is the 6502 being limited to a 256 byte stack by its 8-bit stack pointer.


Wasn't recursion a problem for early C and Pascal in those days anyway? They didn't have tail call optimisations.

As in after X recursion, you'd get in trouble as the memory kept allocating new stack frames for every recurse...


No, recursion still works well without TCO (though as a Schemer, I love TCO). I was programming in BCPL in the early 1970s, and it handled recursive procedures with aplomb. The big revolution was realizing that, if you don't allow access to automatic variables declared in outer scopes, you could store all the variables in the stack frame, and access them with a small offset from the stack or frame pointer. That made automatic variables just about as fast as static ones (which, on System/360, had to be accessed via a base register), with small overheads at call and return sites.

Again on System/360, I benchmarked BCPL procedure call costs against subroutine call costs in Fortran G (the non-optimizing compiler). BCPL was about 3 times faster.

That said, as soon as you added multi-tasking (what we'd now call threads), it all went to hell. It's not an accident that one IBM PL/I manual of the 1960s said “Do not use procedures, they are expensive.”

As mentioned by others, it was the tiny stack in the 6502 that killed this approach. I appreciate all those who pine for the 6502, but it made implementing modern (even for the 1970s) languages almost impossible.


C and Pascal still don't have TCO.

But you still need some recursion and C and Pascal can do that.


When would you absolutely need recursion that couldn't be fulfilled with a while loop?


Never, but I can counter with "when do you absolutely need switch that can't be fulfilled with if-else"?

It's a nice to have that makes your life easier


Adaptive quadrature is an algorithm for numerical integration. You have a function of one variable, and two endpoints of a range, and an error limit. You want to return the value of the integral of that function over that range, a value that is no further from the correct value than the error limit.

What you do is, you do a three-point approximation and a five-point approximation. The difference between the two gives you a fairly good estimate of the error. If the difference is too high, you cut the region in half, and recursively call the same function on each half.

That calling twice is what makes it hard for a while loop. I mean, yes, you could do it with a work queue of intervals or something, but it would be much less straightforward than a recursive call.


Hey, this is awesome! I'd never heard of adaptive quadrature before. Thanks for the tip! Here's what I hacked together from your description and looking up the Newton–Cotes formulas to get a reasonable order of convergence:

    local function q(f, start, fstart, mid, fmid, stop, fstop, ε)
       -- Scaled approximation of integral on 3 points using Simpson’s
       -- rule.
       -- <https://en.wikipedia.org/wiki/Newton%E2%80%93Cotes_formulas#Closed_Newton%E2%80%93Cotes_formulas>
       local Q3 = (1/6)*(fstart + 4*fmid + fstop)

       -- Scaled approximation of integral on 5 points.
       local mid1, mid2 = (1/2)*(start + mid), (1/2)*(mid + stop)
       local fmid1, fmid2 = f(mid1), f(mid2)
       -- Boole’s rule, giving exact results for up to cubic polynomials
       -- and an O(h⁷) error.  This means that every additional level of
       -- recursion, adding 1 bit of precision to the independent
       -- variable, gives us 7 more bits of precision for smooth
       -- functions!  So we need like 256 evaluations to get results to
       -- 53-bit machine precision?
       local Q5 = (7/90)*(fstart+fstop) + (32/90)*(fmid1+fmid2) + (12/90)*fmid

       --print(mid, Q3, Q5)

       -- Approximate the error by comparing the two.
       if (stop - start)*math.abs(Q5 - Q3) <= ε then return (stop - start) * Q5 end

       -- Recursively subdivide the interval.
       return
          q(f, start, fstart, mid1, fmid1, mid, fmid, ε) +
          q(f, mid, fmid, mid2, fmid2, stop, fstop, ε)
    end

    function adaquad(f, start, stop, ε)
       local mid = (1/2)*(start + stop)
       -- In some quick testing, ε/2 seems to work okay.
       return q(f, start, f(start), mid, f(mid), stop, f(stop), (1/2)*ε)
    end

    return adaquad
http://canonical.org/~kragen/sw/dev3/adaquad.lua

It's kind of insane that 16 lines of code can do this!


Many algorithms are more simply expressed as recursive functions than stack-based iterators or "while" loops.


You still don't have TCO anyway unless you use [[must_tail]] (or the upcoming become keyword in Rust)


There have been attempts, the results were not promising:

https://intfiction.org/t/first-full-game-available-on-new-ll...


It looks as if the problem for this one was a game design issue. They had the LLM be sarcastic and ignore well known adventure game prompts on purpose. It's an easy fix to make the LLM more obedient and polite.

The biggest issue is attempts to hack the LLM, to get at hidden gamestate. But I feel this can be easily remedied by just not providing the LLM with hidden game state.


The LLM could use a different session to respond to each command.

That would keep its behavior passive and restricted to simply the current state, since it would retain no memory of previous actions.


Yeah many hacks require multiple prompts. So we have a prompt limit and that makes for a really good textual interface for these old style text based games.


Sure. Another comes from Jim Thompson, who said there was only one kind of story: "Things are not as they seem."



Atari's port of Asteroids also supported four joysticks. You could play melee, co-op, or team mode, with four players on the screen at once. It was a blast.

https://www.atarimania.com/8bit/files/Asteroids_manual.pdf


I wrote a four player "Tron lightbikes" game that used all four joysticks. But I was just a kid and didn't really know what I was doing, so there was no collision detection - people being out because they ran into a wall was based on the honor system. lol.


Copyright for me, but not for thee.


That's been true in a financial sense all along. Because the US courts have the American Rule, everybody pays their own lawyer. When you get down to it, determination of copyright violations requires a trial. It's very expensive to assert copyright. That means copyright applies practically only to works owned by the wealthy.


TADS, an OOP language + VM for interactive fiction, has this "value database" model. Once loaded into memory, the compiled image can be updated with values stored in a separate save file. The compiled image itself could store updated values as well.

In fact, it does this during a "preinit" stage that runs immediately after compilation. Once all preinit code finishes executing, the compiled image is overwritten with the updated state. The language includes a "transient" keyword to permit creating objects that should not be stored.

This same mechanism permits in-memory snapshots, which are used for the game's UNDO feature. No need to rewind or memento-ize operations, just return to a previous state.

It's not a general-purpose mechanism. After all, the language is for building games with multiple player-chosen save files, and to permit restarting the game from a known Turn 0 state.


Exactly. As Dr. Hipp writes on the web site, "SQLite does not compete with client/server databases. SQLite competes with fopen()."


INT 2Fh was the so-called "mux" that various TSRs and drivers could hook into for (in essence) interprocess communication. The half-baked idea was to solve the problem of TSRs commandeering other interrupts for one-off needs, which led to lots of collisions.

In order for the mux to work, each TSR had to have its own identifier code. Other than some reserved ranges, no one organized such a namespace, meaning it was possible for two or more TSRs to intercept the same request, leading to the same collision problem.

This note from Ralf Brown's Interrupt List has the gory details:

http://www.ctyme.com/intr/rb-4251.htm

Incomplete list of TSRs and drivers relying on it:

http://www.ctyme.com/intr/int-2f.htm


Some of these problems (esp. Facebook's) look like someone used an existing service framework to code OAuth2, and either didn't or couldn't adjust the framework to conform to spec.

Some of the other problems look like a common problem with scripting—the ease of treating an int like a string, and vice-versa.

"This isn’t about being spec-compliant anymore. I need to know the thought process behind this decision."

May not be a thought process, just a rush to get the service into production, and a lack of attention to detail. Lots of coders treat error-handling as a hassle or optional, hence the 80-20 rule.


Consider applying for YC's Winter 2026 batch! Applications are open till Nov 10

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: