Posts for ais523


Editor, Experienced Forum User, Published Author, Player (44)
Joined: 7/11/2010
Posts: 1022
Some serious feedback: this started out pretty tedious, but got more enjoyable as it went on. The visuals of the level design are a bit bland, and of course it's got that kaizo thing going on where things don't really look like they seem, but it's interesting to see the character progression as areas go from "really repetitive" to "trivially solved" as they're encountered repeatedly from time to time over the run. The game also manages to have a "sense of place"; despite the map being rather different from Super Metroid's and unfamiliar to me, it didn't take me long to get a sense of how things were connected and to recognise areas that the character had been in before. It's a pity that the start has so many repetitive sequences (especially slowly moving through bombable corridors a bomb at a time), because the middle-to-end is pretty fun to watch. (I'm assuming that you got the intended ending of the game? It's often hard to tell what counts as a win in a Kaizo game.)
Editor, Experienced Forum User, Published Author, Player (44)
Joined: 7/11/2010
Posts: 1022
I doubt that'd work as it'd just affect judge feedback. I'm interested in who'll count as judging the movie, though (the Grue itself, perhaps?) and/or what happens if someone tries to claim it.
Editor, Experienced Forum User, Published Author, Player (44)
Joined: 7/11/2010
Posts: 1022
Thanks for submitting this. I've been arguing for quite a while (over on the IRC channel) that depending on the values of uninitialized memory in a way that's meaningful to the run should be disallowed, and this movie is a great argument as to why. For people who haven't seen the argument before: one of my main concerns is that we measure runs by input length, as it's something that has a hard limit for optimization; the shorter the input, the less precise the instructions you can give to the game, and at some point you can't give instructions that lead to it being cleared. This makes speedrunning an inherently interesting goal for games. (Compare things like "max out the score counter" with no secondary goal like minimum time, or "play as long as possible"; unlike speedrunning games, these will frequently be uninteresting loops of doing the same action forever.) However, preinitializing uninitialized RAM/SRAM allows an end-run around the whole concept of optimizing for shortest input; the instructions you're giving to the game are now mostly not contained in controller input at all, but in the initial conditions. Claiming something like this as a speed record is misleading, because the amount of information given to the game is no longer reflected by the length of the input file. In particular, it makes optimization meaningless (apart from optimization of the portion of the game before the payload is read), as you can get more or less arbitrary effects without adding any additional input (up to the amount of uninitialized RAM/SRAM that exists in the console/cartridge at the time). (You can draw a parallel with code golf, a competition to write a program as short as possible, as opposed to beating a video game as fast as possible. Code golfing competitions disallow things like putting most of the code in the file name, so that it doesn't count against the file size. This is an entirely analogous loophole.)
Editor, Experienced Forum User, Published Author, Player (44)
Joined: 7/11/2010
Posts: 1022
That's because very few games are sufficiently optimized for the primary condition to be an unimprovable tie. So newer TASes nearly always beat older ones on the primary condition (usually time).
Editor, Experienced Forum User, Published Author, Player (44)
Joined: 7/11/2010
Posts: 1022
I would have no objection to a run being obsoleted by a more entertaining run with the same time. If the primary goal is tied, the secondary goal determines which is better.
Editor, Experienced Forum User, Published Author, Player (44)
Joined: 7/11/2010
Posts: 1022
I've now tested the plan for Home:1 and it works! The trap arrangement needs to be tweaked slightly, as you suggested; after several experiments, I got it to work with the portal above 4 and the polytrap below 5. (I don't think the vertical positioning matters much for this, but the horizontal positioning is crucial.) You can make it much more likely to work (almost 50%) by creating a wall of red molds around the area; they're immune to fire, so they don't care about the exploding oil, and block our movement, making it more likely we'll crawl to the right square. One major problem is that in order to do a zero-time artiblast depolymorph, we need an artifact that can blast us in zero time. There are only two options: the MKoT and the PYEC, but both have their own issues. The MKoT is chaotic, and will cost us a turn when blasting us unless we're chaotic too. Unfortunately, we need to be neutral for the Quest unlock and as far as I'm aware, there's no way to change alignment fast enough to save time like that. That leaves the PYEC, which has no alignment issues, but it has a different issue: it gives MR and thus will block a polytrap working. The only fix I can see to this issue is to drop it while climbing out of the water. Unfortunately, if we do that, we're not getting it back, so we won't be able to use zero-time artiblast depolymorph elsewhere in the run. (I hope there's some way to get past the very next hurdle, getting from the Dungeons to the Valley, without it. Using the Orb of Fate's blast seems promising, although we'd need to die twice in response to it in order to "oLS-cancel the action, with no intervening nomul() call. I can't spot one in spoteffects() or drown(), though, so perhaps this is doable after all.) Many of my plans along these lines had problems getting the Bell into inventory, but in this case we can probably just get teleported onto it after we've hit the levport trap to leave the Quest goal level (using a selective autopickup filter to avoid picking up the MR-granting Eye at the same time).
Editor, Experienced Forum User, Published Author, Player (44)
Joined: 7/11/2010
Posts: 1022
The new Super Metroid any% is a great example of what TASing is like, given how clearly different it is from a realtime run. I fear that the second GDQ registration window will fill up just as fast. Do the GDQ people have any special mechanism to make sure that runners (TAS commentators, in this case) get in?
Editor, Experienced Forum User, Published Author, Player (44)
Joined: 7/11/2010
Posts: 1022
After checking, I don't think afternmv is storable after all. The problem is that multi can't be set from a negative value to a positive or zero value without clearing it, and so although we can store it from one cause of helplessness into another, it's going to clear itself as soon as we become non-helpless (and we can't levport down from Home:1 while helpless, as far as I know). This isn't fatal to the plan but it means that we'll need to use some other approach for fixing or working around wounded legs.
Editor, Experienced Forum User, Published Author, Player (44)
Joined: 7/11/2010
Posts: 1022
Is there an objective definition of precisely which glitches are banned here? Is it as simple as "no out of bounds", or are there other sorts of glitches that are banned too?
Editor, Experienced Forum User, Published Author, Player (44)
Joined: 7/11/2010
Posts: 1022
I enjoyed this, mostly because this level of glitchiness is what I've come to expect from any%s (in general). Once you know about a game, you can generally move anywhere without gravity, walls, etc. getting in your way. My main concerns were the grey door skips, mostly because they skip out portions of the game that could have been interesting to watch done "properly". Grey doors are used to block off paths which are later used to ease backtracking, so if you go that way, first, there's no original track, the whole run is basically just backwards backtracking. I don't disagree with this being legal in the category, I just think it's something of a pity it's possible.
Editor, Experienced Forum User, Published Author, Player (44)
Joined: 7/11/2010
Posts: 1022
What was the reason to defeat Junko quickly the last time she shows up on her own, rather than grinding points until the last moment as usual? Does killing her with more time on the clock give more time for the next section?
Editor, Experienced Forum User, Published Author, Player (44)
Joined: 7/11/2010
Posts: 1022
I need to check that, but I'm very hopeful. I did a few checks for obvious problems/brokennesses, and actually discovered that the code is broken in the opposite way to the usual (instead of spoteffects not getting called at all – which is what I feared and would have broken the plan – it appears to get called twice, once in drag_ball and once in teleds). That said, teleds() is past the point where a crawl-out effect can be stored (which is part of the reason I missed this particular line myself). I don't think it's the drowning effect that's being stored here, like in a traditional double-drown. However, I suspect the teleds() effect itself is being stack-stored, and as that contains both a set of the player's x/y, and a spoteffects() call, it looks like it should work. (Or to put it more precisely: we're not storing the action "crawl out of water after drowning", but the action "place the player onto the square they just crawled onto and check for traps there".) I can still see a lot of difficulties with this (beyond verifying that the glitch works – it's very complex – it's going to take some effort to actually get the Bell into our inventory with a route like this, although a team of friendly quantum mechanics is likely enough), but it's very promising and definitely worth testing. (Incidentally, many of the polyforms you listed aren't actually valid as polyforms, but there are enough that are that that won't be a limit on the actual run.)
Editor, Experienced Forum User, Published Author, Player (44)
Joined: 7/11/2010
Posts: 1022
It's basically down to trying to find a new technique to save time somewhere, preferably earlier in the ascension run. The strategy for Water and Astral is pretty much decided now (we can enter Water as an air elemental at the turn 2002-3 boundary, polymorph using the boundary, then enexto across Water, spawn monsters on Astral, enexto across Astral, and sacrifice the Amulet as our four actions). So we need to complete Fire on turn 2002 (in air-E form). The problem is that we can't with present knowledge reach Air until after we've already spent an action on turn 2002 (unless we do so in a slow polyform, which means we'd lose most of our turn 2002 actions); and although there are known fast ways to cross Air (enexto, overflow hurtle), they both seem to be much slower without the help of a turn boundary. There's also some doubt on how long would be spent doing, e.g., polyform adjustment on Fire once we get there (the fastest known way to cross Fire is by jumping but we'd need the Eyes of the Overworld equipped to do that, and we can't glitch the amulet to D:1 while they're in our inventory so we'd need to equip them manually at some point; autopickup is sufficient to get them into our inventory en route). Saving an action any time before Earth would mean that we could arrive on Air and still have the last action on turn 2001 available, which we could use to polymorph into an air-E (and then use the subsequent turn boundary to hatch eggs, polymorph back into p/t, and cross it in a single action). A third fast way to cross Air (that doesn't require a turn boundary or too much luck to manipulate / too much grinding to fit into the turncount) might also work. Incidentally, it may be possible to reach the Sanctum an action earlier via playing a different character. The Valkyrie quest home level is more sequence-break friendly than the Wizard quest home level is (due to being able to generate ice and traps on the same square); I don't know if it's sufficiently good to save an action on the descent to the VS level, but I'm not really looking into it as changing the character would desync the entire run. I originally rejected the Valkyrie as a character because I thought they'd be slower on the Plane of Fire, but there is in fact a square that can possibly hold the portal and that's within jumping range of both characters. Actually manipulating the portal to be there, together with the perfect push from a monster, would be a nightmare, but it it maybe doable. The most promising 2003 that's compatible with the current partial run, therefore, is going to involve finding a timesave somewhere on turn 2000 or 2001. Thanks to the recent breakthrough, we're now only one action off regardless of where on those two turns that action is saved.
Editor, Experienced Forum User, Published Author, Player (44)
Joined: 7/11/2010
Posts: 1022
Right, reading the book takes 2 actions, ringing the Bell probably isn't necessary though if you're fast enough (IIRC this still hasn't been tested yet). Unfortunately, you still have to have it in inventory.
Editor, Experienced Forum User, Published Author, Player (44)
Joined: 7/11/2010
Posts: 1022
A partial breakthrough that still isn't enough to hit 2003: FIQ (the author of the FIQHack variant of NetHack, and who therefore has a lot of experience with NetHack's monster AI) pointed out that it's possible for a covetous monster to teleport onto the Amulet, pick it up, and c!oGL out of the Sanctum all in a single monster turn. The main practical advantage of this is that if we can't reach the Sanctum when we want to (i.e. with an action still to go in turn 2000), we only reach Earth one action late rather than 2. In fact, it's now clearly possible to reach Air by the turn 2001-2 boundary. Unfortunately, that requires an enexto on Earth, and thus being in the wrong polyform. We'd therefore need to somehow save an additional action on the way from the Sanctum to the Planes. Annoyingly, we have a spare action while we're waiting for the monster to c!oGL up (which we could use to equip a "oLS), but we don't have a "oLS-cancellable action on the way up to save with it. The plan in this case would look something like this: 2000 action 1: gain alignment, quest permission, etc. (on player or monster action) 2000 action 2: levport to the Dark One's Dungeon, get the Bell, Eye, etc., on the monster turn 2000 action 3: branchport to the Valley, get the Eye stolen 2000 action 4 ("oLS-cancelled): levport to the VS level 2000 action 4: read the Book, action 1 2000 action 5: read the Book, action 2 2000 action 5 monster turn: we hit a polytrap and a levport trap, so as to end up in the Sanctum by turn boundary Note that until hitting the final polytrap, we're doing all this in a humanoid polyform, so we don't have to worry about vision to read the Book. 2001 action 1: equip a new "oLS, the Amulet gets carried out of the Sanctum on the monster action (imagine a lot of fighting going on here with each monster only acting once) 2001 action 2: "oLS (or level-teleport) out of the sanctum, monsters teleport us onto a levport trap like before and then onto the Amulet, taking us to DL1 in the correct polyform with the Amulet (a big advantage of this plan: we don't need to hit a polytrap on the way up, making generating the VS level easier); autopickup the Eyes of the Overworld 2001 action 3: c!oGL to Earth 2001 action 4: ??? (enexto to Air doesn't work as we end up in a slow polyform for turn boundary) We'd somehow need to either "oLS-cancel action 3 (we can't cancel either of the first two as "oLS-cancelling prevents monsters acting), or else somehow polymorph as a consequence of arriving on Air. Cancelling action 3 is the most promising path at the moment, but that would pretty much require autopicking up an artifact, and getting one of those to Earth before we get there is probably not possible. (I'm wondering if it's somehow possible to get the Wizard of Yendor to carry it up, but getting it to drop in the very narrow window of time we have between migration and autopickup is probably impossible, and getting it to drop on the right square seems even harder.) EDIT: An artifact wouldn't work, it does HP damage and that doesn't kill us when we're polymorphed. It'd have to be a cockatrice corpse instead.
Editor, Experienced Forum User, Published Author, Player (44)
Joined: 7/11/2010
Posts: 1022
Just explaining my Meh vote: some of the movement after getting Chain Rod was interesting, but mostly this run was fairly repetitive. There's not much evidence of creative use of weapons apart from a few Chain Rod tricks which are novel at first but are repeated over and over again all run.
Editor, Experienced Forum User, Published Author, Player (44)
Joined: 7/11/2010
Posts: 1022
Just in case you don't realise: in TASing you're supposed to submit a perfect run, so if you make a mistake, you should rerecord it out (i.e. load an earlier savestate and try the section again).
Editor, Experienced Forum User, Published Author, Player (44)
Joined: 7/11/2010
Posts: 1022
I'd prefer "no save/reset" as the category name. It's more descriptive as to what is actually banned (for example, "warpless" to me would ban things like losing a battle to warp back to a Pokémon Center). You might want to elaborate on what "Psyduck skip" is, somewhat; it's not a term that's familiar to most players of the game (as opposed to something like "Sunyshore guard skip" which is obvious as to what it does, if not how it's done).
Editor, Experienced Forum User, Published Author, Player (44)
Joined: 7/11/2010
Posts: 1022
Aran Jaeger wrote:
Turns from Saturn's video:
That's in a nonstandard format, so I translated it to PGN so that it can be loaded by computer chess programs:
[Date "2017.12.18"]
[White "Saturn"]
[Black "The Chessmaster"]
[Result "1-0"]
[Opening "Philidor Defense: Lopez Countergambit"]

1. e4 e5 2. Nf3 f5 3. Bc4 d6 4. d4 fxe4 5. Nxe5 dxe5 6. Qh5+ Kd7 7. Qf5+ Kc6 8. Qxe5 Nf6 9. Qb5+ Kd6 10. Bf4+ Ke7 11. Qe5+ Be6 12. Qxe6# 1-0
Here's an example computer analysis of the game: https://lichess.org/J083EPLs#0
Editor, Experienced Forum User, Published Author, Player (44)
Joined: 7/11/2010
Posts: 1022
Feedback on storage glitches: although all three variables are probably storable, u.usleep gets unstored whenever nomul is called and you don't end up helpless. And unfortunately, way too many things call nomul (including anything we could use to leave the Dark One's Dungeon without spending time or a "oLS). So we'd somehow need to fall asleep in the middle of the zero-turn stuff on the Home:1, and that doesn't seem to be possible. (For some bizarre reason, an exploding potion of sleep actually causes paralysis-resistable-by-sleep-resistance rather than actual sleep.) We could trigger a sleep trap but we'd then have no way to move off it. I'm beginning to suspect that reaching the VS level faster is in fact completely impossible after all.
Editor, Experienced Forum User, Published Author, Player (44)
Joined: 7/11/2010
Posts: 1022
The operations from 06F8 to 0734 (the second (...) in your post) appear to be a table lookup. They're comparing A (i.e. the old value of (FFE5)) to a range of different values, and setting the value of BC accordingly. (This took me a while to understand because there's a triple negative, e.g. the first test is saying "if subtracting 7 from the value does not borrow, do not continue", but with "borrow" expressed as "not carry"; no wonder it's confusing.) If A is less than or equal to 7h (7 decimal), BC is set to 030Ch (780 decimal). If A is less than or equal to Bh (11 decimal), BC is set to 0734h (1844 decimal). If A is less than or equal to Fh (15 decimal), BC is set to 0B5Ch (2908 decimal). If A is less than or equal to 15h (19 decimal), BC is set to 0F84h (3972 decimal). This table probably continues, but the rest of the table doesn't show in the trace because that's the case that was taken in the trace in question. At that point, the B half of BC is saved back in FFE5, and the code moves on to FFE6, which is zeroed (like in your trace). The C half is saved into C0AB, and the code moves onto a subroutine at 21B1 (which appears to be very long and complex and start with several block copy / block clear routines; this would suggest to me that it's a major loading routine, which wouldn't be surprising if it's called during the player respawning). C0AB doesn't seem to be used immediately, although several values near it are used, so it wouldn't surprise me if it's part of some sort of "this is where the player is" state. I'd strongly recommend at least putting a memory watch on C0AA and C0AB because they seem to be relevant here. 21BC is the first point at which the code gets back to FFE4/FFE5/FFE6 rather than large block copies, and is still inside the long and complex subroutine mentioned earlier. FFE6 is compared to zero; if it actually is zero (as it is in this case), then something fairly small/simple gets skipped (which doesn't show up in the trace because it was skipped). As such, I'd expect FFE6 to be related to "the reason the player respawned". It starts by looking at the memory address (4000 + twice the value in FFE4); 16 bits gets loaded from that memory address into DE (in a painfully indirect way because the Z80 doesn't have any instructions for doing that efficiently, e.g. it has to use all of A/D/E/H/L as temporaries, because addresses like A are useful for doubling a value by adding it to itself). So I assume there's some sort of array starting at 4000. The code then does something very similar again, adding twice the value in FFE5 to the value that was previously in DE (again, in a very indirect way with a bunch of register-shuffling); several consecutive values get read from the resulting address. In C-like pseudocode, we'd write that code something like this:
    extern byte*** a4000; // * = 16-bit pointer to an address
    byte *base = a4000[ffe4][ffe5];
That is, we're taking a hardcoded array that points to another set of arrays, and indexing into it twice to get a base pointer. That pointer's then used to read several values from memory which determine how the game loads from there. Given that we already know that FFE5 is set to 3, 7, B, or F, (and probably other values but the pattern likely continues, it's going up by 4 each time), my guess is that there's an 8-byte structure that contains values describing how a level checkpoint behaves, and several of these structures exist for any given level; presumably, the first structure describes the level spawn point. I'd also guess that ffe4 somehow specifies which level the player is currently playing (that's just a guess but you can probably confirm it with memory watch). The code logged here seems to make sense: there seem to be checkpoints at FFE5 = 7, B, F, etc., and if the player has gone sufficiently past them (i.e. to 8, A, 10 respectively), they'll respawn at that checkpoint. There's no immediate bug there that I can spot. There is something that's bothering me, though: with the part of the code seen in the trace, respawning at say, checkpoint 2 would subsequently put you back at checkpoint 1 if you died without moving from then on, something which the developers are moderately likely to have tested and which is probably undesirable. I have a suspicion, therefore, that the setting of FFE5 in the part of the trace you posted is used only to determine which checkpoint to respawn at, and some other part of the code sets the new value of FFE5. I further have a hunch that the respawn bug you saw is a consequence of the value in FFE5 somehow getting out of sync with the player's/camera's actual x coordinate. You might want to try to work out the relationship between those to see if there's anything unexpected there.
Editor, Experienced Forum User, Published Author, Player (44)
Joined: 7/11/2010
Posts: 1022
goldenband wrote:
Barring that, the next-best option is likely to be (1) either a closed position in which one player builds an attack on one side -- something computers are notoriously bad at evaluating -- until checkmate is inevitable; or (2) some wild sacrificial line where, again, the CPU wolfs down material until it's too late. Here's a post that features some work in that direction by Eduard Nemeth: https://timkr.home.xs4all.nl/chess2/honor.htm And SNES Chessmaster is, of course, far far weaker than the engines featured in that post.
I asked Stockfish to evaluate the Nemeth Gambit out of interest. Amazingly, it turned out that it was actually in its openings book. If playing the "standard variation" that the computers fell for, though, it believes 8. Kd5 – a natural move for lower-skilled computers – to throw away all the advantage that Black has accrued, though. I wonder if we can force Chessmaster into that line? (Incidentally, Stockfish's analysis is that Black's correct continuation is to sacrifice its Knight to buy time to move its King back home. In fact, it believes that Black has to counter-sacrifice a minor piece in more or less any plausible line after Nxe4 has been played, if it wants to keep an advantage. No wonder the line works so well against less advanced engines.)
Editor, Experienced Forum User, Published Author, Player (44)
Joined: 7/11/2010
Posts: 1022
OK, so looking at a few traces of what's happened: $FFEA appears to be an address responsible for controlling some sort of loading routine. Part of this routine can only run during vblank. As such, the value normally moves through a few states: 0: normal 1: loading required 2: vblank portion of loading finished 3: loading finished The value goes from 3 back down to 0, resetting the loading sequence, whenever FFA4 and C0AA differ. (According to MUGG, these values are related to the character's position, one directly, one modulo 8, which makes a lot of sense.) Now, the loading process is meant to go 0→1→2→3 and back to 0, but the code doesn't actually enforce this. What actually happens is that the game sets the value from 0 to 1, some time later waits for an interrupt, then if the value is nonzero, sets it to 3. In other words, the code is assuming that the interrupt that it waited for is the vblank interrupt (which would set the 1 to 2 and do the vblank-critical part of the loading routine; this part of the routine is also what sets $FFE9). This "if the value is nonzero" test is not done immediately after the interrupt ends; it's done fairly late in the computation for that frame. However, the vblank interrupt isn't the only interrupt used by the code. There's also a timer interrupt (which is apparently used for, at least, playing the background music). When this interrupt happens, it satisfies the "wait for an interrupt" requirement in the code, even though the interrupt in question is not vblank. Normally, this doesn't matter; the code runs for quite a while before doing the 2→3 part of the loading sequence, so the odds of a vblank happening by chance before that part starts are very high (guaranteed under normal circumstances because the game's processing normally waits on vblanks, as is the case in most games, so the game's code normally runs at a consistent time relative to vblank). However, what if we had a lag frame recently? In that case, a vblank happened "before the code was ready", and it's possible (and actually observed in the "bug frames") for the vblank to happen right before $FFEA gets set from 0 to 1. Now, suppose a timer interrupt happens to happen right after; that will fulfil the requirement of waiting for an interrupt, so the code for the next frame starts running "early". (You could call this an "antilag" frame; instead of the code running late after vblank, it's running early before vblank.) If the timer interrupt happens quickly enough, the game manages to run all the way through to the 2→3 part of the loading sequence before the next vblank occurs, and runs it even though $FFEA isn't set to 2 (it's set to 1, which is nonzero, all the code was looking for). That means that only the second half of the loading sequence has actually run. Then because $FFEA isn't 1 any more (it unconditionally gets set to 3), the first half of the loading sequence won't run and so permanently ends up not having been run. So the conditions for this to happen are a) a lag frame that happens to run to more or less exactly the right length past vblank (so that the check for loading being required happens just after vblank, not before like it should have been); b) loading actually being required on that frame; c) a timer interrupt (or possibly LCD status interrupt, although I haven't seen that in MUGG's traces) that happens while the game thinks it's waiting for vblank, and fools it into thinking that vblank has already happened. This seems fairly unlikely to happen by chance, which is presumably why the playtesters didn't find it and why it's such a rare glitch.
Editor, Experienced Forum User, Published Author, Player (44)
Joined: 7/11/2010
Posts: 1022
There's a Wikipedia article listing checkmates that are close to a known opening sequence. Finding one that isn't marked as a trap to be avoided in the openings book and is too deep for the engine to see may be a problem, though. The Légal Trap probably doesn't work against a computer because it's hard to persuade it to play the moves necessary to get into the position seen after move 4 (it might potentially be possible if you play the moves out of order?). It's slow enough that a tactical analysis might not find it, though. The Blackburne Shilling Gambit is the sort of thing that lower-skilled computers often fall for but it may well be in the openings book. Those are likely both worth trying before moving on to some of the more blundery mates.
Editor, Experienced Forum User, Published Author, Player (44)
Joined: 7/11/2010
Posts: 1022
JSmith wrote:
It looks like you can deal the unshapeshift damage with a potion of acid inside a cursed oilskin sack instead.
Let's see. In order to get a double-drown glitch, we need to trigger a recursive spoteffects in water_damage, losehp (trivial but requires being an iron golem), split_mon, unleash_all, [not dismount_steed: the devteam thought of that], unmul (if asleep), or emergency_disrobe. Also, we need to not be helpless (after unmul, if any) and be in a polyform with positive speed. Using a potion of acid would trigger in water_damage; that's the right time. Unfortunately, it doesn't appear to do any damage; there's a comment "/* damage player/monster? */" but the actual damage seems not to have been implemented. The boulder dropping trick suggested earlier would trigger in emergency_disrobe, which is also the correct time, but unfortunately we'd need to simultaneously be in water and not in water. I'd checked most of the functions listed above a week or so ago, because this is one of the last remaining pieces necessary in the run and we're so close. One I didn't check was unmul, and it has a fairly interesting codepath to prayer_done, which might potentially be the breakthrough we need. Unfortunately, the only codepath through to rehumanize() that I see there is via p_type -1, which for a neutral character like ours triggers only if we're undead and only with a 10% chance (although 10% is massive in a TAS). Luckily, p_type is a static/global, which means that there might be a storage glitch for it. Note that we're going to need to stack a number of different storage glitches to get this to work – we need to store all of u.usleep, afternmv, and p_type – and although it seems plausible that there's a way to store those (lifesaving looks really promising), I'd need to test because it involves glitches that aren't currently known.