That's a good point about the Eye. In non-TAS gametime speedruns, there's some debate about whether Priest or Wizard is faster; Wizards get the best starting inventory for a speedrun (especially with RNG manipulation involved via setting the initial real-time-clock time), but they are the only class which cannot wish for the Eye. (Wizard seems to be faster without TAS tools involved, incidentally, so maybe the Eye doesn't save that much time. An interesting additional point comes up with regards to the starting seed; NetHack's difficulty level depends on the date and the phase of the moon (which I'd forgotten about until recently). Would it be worth starting a game on the least optimal date/moon combination - a new moon on Friday 13 - in order to "play at hardest difficulty"? (If allowing an arbitrary start time, you'd probably want a neutral moon phase to reduce the amount of text that you have to skip through.)
If the stairs are very close to each other, it's conceivable that walking between the stairs and climbing them normally could be faster than a c!oGL due to the smaller amount of text that's displayed. (I agree that c!oGLs are a very useful item when optimising the ascension run, though; and I've been wondering what the fastest way to manipulate the 50 or so you'd want for a TAS is. Polypile or alchemy, using a large potion shop for feed material, most likely.)
There is, incidentally, a rather neat sequence break on the ascension run; I've confirmed it exists, but it's still an open question as to whether it saves time or not. The trick is to take the Amulet through the portal into the Wizard of Yendor's Tower, then teleport the Amulet out of the tower (this is the bit that's probably a bug in the game), go back through the portal and level-teleport to where the Amulet is, thus skipping several levels of Gehennom (luck manipulation could maximise the number of levels that could be skipped this way). Whether it's optimal or not depends on the length of time those levels would take to be generated by the game; if it generates them quickly than c!oGLing through would probably be faster.
As for whether blindness helps, I'm not sure; that would need to be tested. (You'd get some idea of what was going on anyway due to walking into walls as a method of luck manipulation, which reveals the walls.) Being blind generally costs in-game turns when you walk over an item, but not if you know the item's there in advance and use m-direction to move. It's also possible that hallucinating is the fastest method to manipulate luck, which wouldn't work well in conjunction with blindness.
Hardest is new moon, friday 13th, at midnight. Easiest is full moon, day, not friday 13th.
I don't like this view towards text minimisation, especially since the text a) tells you what's going on, and b) provides much of the flavour of NetHack. I had a thought about another goal: minimal RNG calls. Complete NetHack with as few RNG calls as possible. This means you want a short in-game time (because the RNG is called for things like room noises) and also a short real time (because extended RNG manipulation is punished). However it also means most of the effort would be spent skipping through places with lots of monsters as fast as possible (valley, castle). It also means you don't have to care about minimising text; indeed, you could try to put a few YAFMs into the run for entertainment. I don't know if this is a better idea than shortest realtime, so I'd be willing to hear your ideas.
EDIT: Another thought: shortest input (ie fewest keypresses).
It may yet be the case that the text doesn't actually take that much time compared to generating dungeon layout etc. I imagine it will depend on whether you use JPC-RR's "Emulate I/O delay" option, but I don't know for sure.
My view of RNG manipulation for NH is not to ask "how can I shuffle the RNG to get what I want?" but rather "how can I use the numbers that the RNG has lined up in the best way?". The same call to Rand() will result in different outcomes for rn2(3), rn2(2), rnl(5), or rnz(100), and you have so many concurrent goals in NH that the very next number to come out of the generator should surely be useful for *one* of those goals. It might even be sensible to write a program to outline the upcoming RNG rolls and show what values they give for various rn*(N) function calls, so you can scan and identify which action would benefit most from those rolls. (Of course some desired actions, such as getting a death drop, would require the results of several rolls in succession: one to hit the monster, one for damage, one for death drop probability, one for item class, one for item type, possibly one for enchantment.)
I am in favor of a "fewest turns"-movie. About advancing the RNG by moving into a wall, perhaps this could be counted somehow, either adding it to the regular turns or counting the number of "dead" turns. Nobody wants to see someone walking into a wall 50 times.
Another question for those of you who have digged into the source: are all of the levels layouts and monster placements done when the game starts? Or when you reach that level?
When you reach the level. The level graph (which level connects to which) is decided at the start of the game, but levels that actually match those connections are only generated when they're necessary.
You would need to be very careful about trying to define a "minimum turns and RNG manipulations" run, by the way. There are other ways to manipulate the RNG that don't involve turn-taking actions at all (repeatedly renaming an item to an invalid name, for instance), but they're slower than simply walking into a wall and also more annoying to watch. (At least it would be clearer what was going on.)
I sort-of dislike arbitrary goals, though. Would a run requiring no more than 50 manipulations per turn be obsoleted by a run requiring no more than 60, for instance, if it were ten turns faster? The reason I still believe realtime would be the best goal is that at least it's non-arbitrary, and tends to encourage speed and lack of dawdling by its very nature. (You could make a slowed-down encode on the same path so that people could see what was going on, if it wasn't clear enough.) FWIW, minimum (turns + manipulations) wouldn't be very different from minimum realtime anyway, as those are the actions that would be taking up most of the time; the major difference would be that it would be necessary to polyself into a particularly fast form to save turns (hasted air elemental seems to be the usual choice), and as air elementals are intrinsically blind, we'd have the problem of running around the entire dungeon blind that was mentioned above.
You're thinking about this the wrong way. Truncated's proposal is to change from "minimum turns" to "minimum actions", considering any command to the game as an action whether it advances the turn counter or not. Which would basically be nethack's equivalent to aiming for lowest real-time instead of lowest game-displayed time.
Of course, given two equivalent length sets of input, the one with the lower game-displayed time will probably be preferred as more impressive.
By the way "least actions taken" is no more arbitrary a goal than "fastest completion", it simply has less precedent on the site.
Edit: for clarification, least actions taken and fastest time both measure performance based on a single aspect of gameplay to the exclusion of all else, and there is no particular reasoning to justify the selection of the time aspect as compared to any other single aspect. This is the definition of arbitrary.
How fleeting are all human passions compared with the massive continuity of ducks.
The lowest realtime has the problem of NetHack not running at a set framerate... so it will depend on the speed of the computer you emulate, I think.
I guess this has been said already. Not sure how this will be solved.
In that case, mightn't "fewest keystrokes" work as a goal? Similar to "minimum actions", but easier to count. (It does have the problem of typing something like "n1000k" to walk into a wall 1000 times, though.)
EDIT: Kerio pointed out on IRC that repeating actions this way doesn't work on actions that fail, like walking into walls. So perhaps it wouldn't be abusable like that.
In that case, mightn't "fewest keystrokes" work as a goal? Similar to "minimum actions", but easier to count. (It does have the problem of typing something like "n1000k" to walk into a wall 1000 times, though.)
Well, it could, but it is a little bit less analagous to time in a game that is rather incongruous with the concept of frames.
But it has the advantage of being clearly defined and easy to count. Is "n1000k" one action or a thousand? Is using the travel (_) command one action? Is paying for 5 items 1 action or 5? Does it depend on whether you took itemized billing?
I suppose one definition is that an action is anything you can do from the standard playing mode (the mode in which hjkl will move you, z will zap a wand etc). By this definition all of the above are single actions. This is still harder to count than simple keystrokes, and I don't think it will result in particularly different results.
Perhaps we should consider banning repeated commands (n1000k) to prevent luck manipulation from becoming trivial.
PS I'm working on a tool to simulate and explore the RNG, to indicate what the results of mkobj(), makemon(), etc would be if executed using any upcoming RNG values. Hopefully this should make it easier to farm necessary items without having to go to the trouble of repeated savestate abuse.
PS I'm working on a tool to simulate and explore the RNG, to indicate what the results of mkobj(), makemon(), etc would be if executed using any upcoming RNG values. Hopefully this should make it easier to farm necessary items without having to go to the trouble of repeated savestate abuse.
If you do this, remember to use the algorithm DOS NetHack uses, rather than one of the many others NetHack can use. It uses DGJPP's standard library random number generator, but happily it turns out to use exactly the same algorithm as the one in NetHack's sys/share/random.c (even the code is almost identical). My own RNG-search version of NetHack is modified to use that copy.
If you do this, remember to use the algorithm DOS NetHack uses, rather than one of the many others NetHack can use. It uses DGJPP's standard library random number generator, but happily it turns out to use exactly the same algorithm as the one in NetHack's sys/share/random.c (even the code is almost identical). My own RNG-search version of NetHack is modified to use that copy.
I've already been through the DJGPP source and confirmed that my tool's output matches the output of nh343dos using DJGPP's gdb. Now it's just a matter of mocking up all the rn*() functions, mkobj(), makemon(), and so on.
I'm not exactly convinced that a non-glitched any% NetHack TAS would be so entertaining to watch, because it's something the community has already watched, somehow, in nht's (2185 turns) and maud's (2239 turns) games.
On the other hand, a glitched any% TAS would involve starting a tourist, wielding and then applying a cream pie, dropping and picking up things and then whacking a monster, or something like that - NetHack has a couple of serious bugs that allow for memory manipulation, involving a dangling pointer due to object destruction without cleared references.
On the subject of counting actions...
There are several ways in which it's possible to count time in a NetHackish way (i.e. entirely independent of the system clock). Luckily, each can be counted objectively.
The common method of counting used for "gametime speedruns" in the NetHack community is in-game turn count. This can be displayed on the screen (via the "score" option), and corresponds, objectively, to the number of times line 138 of src/allmain.c runs. This has the issue with luck manipulation explained above.
Another possibility would be to count "number of time-consuming actions"; that is, counting movement, fighting, item use, etc, but not inventory check, setting options, etc. It corresponds, objectively, to the number of times a hypothetical command inserted on line 296 of src/allmain.c runs (that line is blank in the NetHack source). This has the same problem with luck-manipulation, though, as luck can be manipulated entirely via non-time-consuming actions.
Another possibility is what the NetHack source terms "number of player inputs", counting any time the user gives a command to the game that returns back to the main loop. This is most easily measured at line 304 of src/allmain.c, and would count a repeated command like n20s as 20 commands; I think it also counts a "run" command, like G2, as multiple commands, though, which might or might not be unexpected, and I'm having trouble working out how it counts things like "m6" (as one or two commands). One downs ide to this method is that the number of player inputs is not easily extractable from the game, and would be hard to compare with non-TAS speedruns. (However, you could create an encode with a version of NetHack hacked to show player-input count.)
Also possible would be to count various lines in rhack(); for instance, src/cmd.c line 1810 or 1813, which would both count inputs in slightly different ways. (rhack() has two jobs: requesting input from the player, and actually running the command the player requested.)
Finally, you could simply count keystrokes, which at least has the advantage of being objective without a need for any modification to the source.
I'm not exactly convinced that a non-glitched any% NetHack TAS would be so entertaining to watch, because it's something the community has already watched, somehow, in nht's (2185 turns) and maud's (2239 turns) games.
On the other hand, a glitched any% TAS would involve starting a tourist, wielding and then applying a cream pie, dropping and picking up things and then whacking a monster, or something like that - NetHack has a couple of serious bugs that allow for memory manipulation, involving a dangling pointer due to object destruction without cleared references.
Those are not TASes. They did not use savestates, and did not manipulate luck (except via the mechanism of starting the game repeatedly until good inventory was found, in Maud's case). They also both abused bones files. Just because a good non-TAS speedrun exists does not mean a TAS would not be interesting.
A glitched any% could be a fun diversion, but would hardly show any of the game; it would consist of a few random actions on the dlvl 1 upstairs, followed by arbitrarily winning. (And it would be hard to define just what counted as a "win" in a situation where running arbitrary code is possible.)
Those are not TASes. They did not use savestates, and did not manipulate luck (except via the mechanism of starting the game repeatedly until good inventory was found, in Maud's case). They also both abused bones files. Just because a good non-TAS speedrun exists does not mean a TAS would not be interesting.
Yeah, but the fact that you never get stopped by the mysterious force in gehennom, and the fact that you find things on the ground instead of a big pile is not enough change, imho, to need a proper TAS - that said, I'll happily watch one, if only to know what's the actual lower bound in turncount (I mean, if you end up choosing that as the way to measure the time).
A glitched any% could be a fun diversion, but would hardly show any of the game; it would consist of a few random actions on the dlvl 1 upstairs, followed by arbitrarily winning. (And it would be hard to define just what counted as a "win" in a situation where running arbitrary code is possible.)
I didn't know you could run arbitrary code - I thought pointer black magic was limited by the stack/heap separation; anyway, I seem to recall that the end condition for a RPG-like game like NetHack was just to reach the final cutscene somehow - pray.c, starting with line 1290: pline("An invisible choir sings, and you are bathed in radiance...");
Another possibility for the goal, after discussion on IRC: minimum in-game turncount, minimum realtime without sacrificing turns. It's probably possible to calculate a definitive lower bound on the number of turns needed to win; and hopefully it wouldn't take a massively long time to achieve it.
I've also been wondering about strategy in the endgame (where teleportation is banned and c!oGLs don't help). The fastest way to move on the plane of Earth appears to be to box yourself in with a scroll of earth, then pray, so that (with a bit of luck manipulation) your god drops you next to the portal to rescue you from your predicament. Similarly, the fastest way to move on the plane of Fire is quite possibly to fall into lava and get life-saved (although I haven't tested this). I hope that these techniques are optimal, because they would certainly be dramatic and fun to watch. (It's not often that you can "damage boost" in NetHack!)
I suppose one definition is that an action is anything you can do from the standard playing mode (the mode in which hjkl will move you, z will zap a wand etc). By this definition all of the above are single actions. This is still harder to count than simple keystrokes, and I don't think it will result in particularly different results.
Pressing "z" might not look as action, because it pop up a menu and you can still cancel it without visible impact on the gameplay, but if you try ctrl+A(redo previous action/command), nethack should popup the wand menu again!
That said, I didn't browse the source code of the game, but I'm sure that nethack have an action/command history with at least one entrie(last action). So, in order to evaluate how many action you get so far... maybe we could check some in game data memory or increment an "action counter" with lua everytime the last action/input is overwrited. (I don't know if this is possible if the player do the same action consecutively, but there should be a way).
That said, I didn't browse the source code of the game, but I'm sure that nethack have an action/command history with at least one entrie(last action). So, in order to evaluate how many action you get so far... maybe we could check some in game data memory or increment an "action counter" with lua everytime the last action/input is overwrited. (I don't know if this is possible if the player do the same action consecutively, but there should be a way).
Unfortunately, it doesn't work like that. NetHack uses something like three or four different and conflicting mechanisms to do what you're assuming is just the one mechanism, including things like recording keypresses; movement is handled differently from other actions, for instance. Also, the action repeat code is mixed in for the code for paralysis, and also with the code for multi-turn actions. Memory watching isn't, therefore, going to lead to a particularly sane definition of what an action is.
Some would just say that it's NetHack that's not sane. :)
Shortest input is what other TASes are pretty much doing right now - the only difference would be that "no input" is not a valid input - it makes sense if you consider each input from the player as a "frame".
Does NetHack even accept more than one key at a time? Barring metakeys to change the meaning of the input character, anyway. It seems to me that conflating keys and frames is a natural approach to such a game.
Pyrel - an open-source rewrite of the Angband roguelike game in Python.
Shortest input is what other TASes are pretty much doing right now - the only difference would be that "no input" is not a valid input - it makes sense if you consider each input from the player as a "frame".
Yeah, since nothing happens when there's no input in Nethack, it seems silly to count it in terms of frames. Per keystroke seems best here(perhaps per-command(which would make a difference for extended commands like #enhance)), but since there's no advantage to increased frames, why bother putting the goal in terms of frames?
I would think counting by the least frames makes the most sense because it's easy to do and it's how all the other runs on this site are done. Saying you should time it by something else like number of inputs seems silly to me because there is already an established timing method