Submission Text Full Submission Page
FractalFusion's NES Wheel of Fortune in 1:55.18 (6922 frames). An improvement over PikachuMan's previous submission by about 26 seconds.

Goals

  • Starts from savestate+reset.
  • Aims for fastest time from reset to selecting END on the bonus round which results in a bonus round win.
  • 2P input in a 1P game.
  • Manipulates luck.

Why from savestate+reset instead of power-on?

The game uses the RAM range 0x780-0x7FC as a bitfield for the status of its 1000 puzzles. Bit 0 means puzzle is available for selection; bit 1 means puzzle cannot be selected/has already been done. But the game never initializes this range before using it; as a result, the initial RAM power-on state affects this range. The RAM initialization of FCEUX arbitrarily restricts which puzzles are available at first. However, we can use a preparation movie file to manipulate this range, and then start from a reset. This allows much more flexibility.
The preparation movie file, being also a verification movie file, proves that this RAM setup can be reached from FCEUX's power-on state. Nothing special about FCEUX's power-on state; with the right preparation movie file, this setup can be reached from any power-on state whatsoever. This is because, if the entire RAM range 0x780-0x7FC is filled entirely with 1-bits, the game zeroes the entire range next puzzle.
The preparation movie file is in the resource link in the Other information section below.

Verifying the movie

  • Run Wheel of Fortune-verificationfile.fm2 . Pause at the last frame, when frame display says "692332/692332".
  • Stop the movie.
  • Record a new movie starting from savestate (Record from -> Now).
  • Check the header of the new movie. The savestate in Base64 encoding should be the same as for this submitted movie.

Optimizing the TAS

Optimal puzzles

First, I found out where the puzzles were stored in the ROM (ROM file 0x109DE-0x14617, NES address 04:89CE-05:C607). There are 1000 of them. (At first sight, there appears to be 1002 of them, but one of them is a fake, corresponding to the title screen's WHEEL OF FORTUNE, and the other is a lost puzzle that the game's puzzle selection routine will never hit, ever.)
I used a C++ program to calculate a "score" for each puzzle, representing how long the puzzle takes. It is based off both the time taken to enter the puzzle on the solve screen, and the time for Vanna to reveal the puzzle. Each puzzle is calculated as follows:
  • Let val('A')=1, val('B')=2, ... , val('Z')=26. Let k be the number of letters in the puzzle. Let a(0)=val('A')=1 and a(k)=val(kth letter of puzzle). Let b(k)=a(k)-a(k-1).
  • Then the score of the puzzle is:
score=  42*k
      + sum(1 to k)[min( 1+8*|b(k)| , 117-8*(b(k)-16) , 129-8*(-b(k)-16) )]
      + min( 129-8*(15-a(k)) , 121-8*(a(k)-16) )
Puzzles with best results:
ScorePuzzle #Word
06420818TOOTSIE
06430806BEN HUR
06950340EUCLID
06970199BABE RUTH
07020451MONOCLE
07110442TUXEDO
07130138HONG KONG
07240618HIGH JINKS
07270686SO BE IT
07290010FORT KNOX
07290055BOOT HILL
07380456LULLABY
07450462CHESTNUT
07490922BIRTHDAY
07550803PSYCHO
07610688LOOK IT UP
07630953PAYDAY
07650850THE ILIAD
07660392COCONUT
07820122CAPE COD
07820366HAIRPIN
07820430HAIRPIN
07920969YOM KIPPUR
07930081HONOLULU
07930148ETHIOPIA
07970494SOUR NOTE
07980355GALILEO
(The full list is here. It is sorted by puzzle number though. You can sort by score in another program like Notepad++ . The list was generated using wofscript.cpp . See the resoure link in the Other information section below.)
These scores assume the standard first/second round structure.
Speed-up round is a bit different; you have to choose a letter in the puzzle before you are allowed to solve it. I quickly figured that choosing the U in EUCLID pretty much gives the best result; it saves the four seconds needed to go from E to U to C normally, and no other word comes close. It is also near the left side so Vanna doesn't have to walk far.
In bonus round, you choose five consonants and a vowel and if any of them are in the puzzle, they are turned over before you solve it. It is fastest to choose letters that aren't in the puzzle so Vanna doesn't have to do anything. Note that if the letters you choose uncover the whole puzzle (for example, if the puzzle is PSYCHO and you choose, well, PSYCHO), you still have to select END after the puzzle is uncovered, and no, timing out causes you to lose no matter what, in case you were thinking about abusing that.
The best bonus round puzzle happens to be the one with the best score above; that is, TOOTSIE. ZYXWVU can be selected while on the way to T. (The next couple best are MONOCLE, selecting BDFGHI along the way, and HONG KONG, selecting BCDFJI.)
This conveniently leaves BEN HUR and BABE RUTH for the first and second rounds, respectively. Checking shows that BEN HUR first and BABE RUTH second is a couple frames faster than the other way around.
There is the possibility of having a puzzle show up twice in a single game by zeroing the range 0x780-0x7FC during the game, I checked to see if it was feasible. However, EUCLID and TOOTSIE would be impossible for speed and bonus rounds in this case, and substituting other puzzles in their place would be too costly.
So, in conclusion, the puzzles I use are:
  • First round: BEN HUR (#806)
  • Second round: BABE RUTH (#199)
  • Speed-up round: EUCLID (#340)
  • Bonus round: TOOTSIE (#818)

Spin manipulation

It is possible to manipulate the speed-up round's spin. This is also where 2P input comes in.
I manipulate the spin meter to be as low as possible. It is impossible to manipulate the spin further with 1P input; however, with 2P input, the added delay variance is manipulated to be 0. The speed-up round's puzzle can also be manipulated with 2P input as well.

How to manipulate these puzzles (i.e. 0x780-0x7FC manipulation)

The RNG

The RNG (address 0x0A-0x0C) controls randomness in this game. It is influenced by input most of the time. The address 0x0A merely increments whereas 0x0B and 0x0C are chaotic. Usually, puzzle selection in this game (as well as speed-up round's spin) is determined by the RNG when address 0x0A is 200 (0xC8). At that time, only 38505 out of 65536 values for 0x0B-0x0C are possible.

Puzzle selection rules

As stated earlier, if the entire RAM range 0x780-0x7FC is filled entirely with 1-bits, the game zeroes the entire range next puzzle. (It also zeroes address 0x7FD for whatever reason.)
Now the game selects a puzzle using its puzzle select routine that is intricately connected to the RNG. If the routine gives a puzzle that already has its bit set to 1, it runs the routine again up to 7 more times with slightly different parameters. If that fails, the game stops trying to use its fancy routines. It simply takes a point in the range and finds the first puzzle from there that has bit 0.
Now, there are some limitations for puzzle selection. It is entirely possible that two given puzzles must occur in a particular order and never the other way around. Because of RNG timing, this restriction may be particular to the first/second/bonus rounds (the third speed-up round is less restricted). Puzzles 936-959 and 968-991 are extremely restricted. Fortunately, these limitations do not affect the choice of puzzles that I want.

For the puzzles used in this TAS

  • BEN HUR (#806) can be triggered directly; nothing else needed.
  • BABE RUTH (#199) requires all puzzles 96-198 to be done already (bit 1) as well as a sequence of puzzles for which there exists an RNG value causing the routine to try these puzzles before taking the first available puzzle from 96.
  • EUCLID (#340) requires (for optimal speed-up round spin manipulation) all puzzles 224-339 to be done already (bit 1) as well as a sequence of puzzles for which there exists an RNG value causing the routine to try these puzzles before taking the first available puzzle from 224.
  • TOOTSIE (#818) requires all puzzles 800-817 to be done already (bit 1), including BEN HUR (#806), as well as a sequence of puzzles for which there exists an RNG value causing the routine to try these puzzles before taking the first available puzzle from 800.
Note that the completion of BEN HUR in the first round satisfies the requirements for TOOTSIE in the bonus round.
The following RNG values are used, with the puzzle sequence that the puzzle selection algorithm tries:
  • BEN HUR: C8.C7FA (805 124 800 072 814 038 632 804 800 801 802 ... 806)
  • BABE RUTH: C8.6D39 (123 801 075 815 033 633 807 122 096 097 098 ... 199)
  • EUCLID: 99.2327 (333 918 252 672 998 165 999 251 224 225 226 ... 340)
  • TOOTSIE: C8.C7FA (805 124 800 072 814 038 632 804 800 801 802 ... 818)

Setting up the preparation movie file

The standard method for setting up bits in the 0x780-0x7FC range is to manipulate a particular puzzle for the first round and then immediately reset after the bit is set to 1. However, not all puzzles can be manipulated this way. Some puzzles require a manipulation in the third (speed-up) round. Thus, some puzzles will have to be solved in the first two rounds. As I was trying to optimize the preparation movie file as well, I chose the puzzles with the lowest possible scores.
The preparation movie, made with a lot of input file editing as well as a bunch of C++-generated information files, boils down to this:
(note that this preparation movie uses only one controller instead of two that the TAS uses)
  • Reach the first round and immediately reset after any one bit is set to 1 (no manipulation needed). Repeat this 511 more times. The range 0x780-0x7FC is now filled with 1-bits and will be zeroed out next puzzle.
  • Let the characters below denote the important RNG values to manipulate:
CharacterRNG value at C8.xxxx CharacterRNG value at C8.xxxx
06D39 c440F
1B4C8 d040C
21F30 e440C
3C7FA f040D
44434 gCD7E
58373 h8368
6C31A iC368
7C373 j8369
8C391 kC369
9040E m662A
a040F nD40A
b440E p4615
  • Perform the following manipulations in this order (brackets means solve the first two and manipulate the third for the speed-up round):
41(012)000000111(012)000011111111(012)00111115678(012)0(002)
000011(012)000111(012)0000000(002)(002)(002)00000001(012)
001111(012)00(002)001(012)0000(002)1(012)0011111111(012)
000(002)011111111(012)1(112)1(112)0000000001111111111(012)
(9a2)0000001bcdef(012)00011(012)00011(012)
00000011gg33333333hijk(m1n)m11(31p)

Memory range 0x780-0x7FC should now look like this. This is starting position for the TAS:
00000000 42000000 01900000 FFFFFFFF
FFFFFFFF FFFFFFFF FE000000 FFFFFFFF
FFFFFFFF FFFFFFFF FFFFF000 00000120
00000004 00000000 00000000 00000000
00000000 00000000 00040000 000000C0
00000000 80000000 00000000 00000000
00000000 FDFFC000 02000000 00000000
00000200 00000000 00000000 03

Other stuff

Can this TAS be played directly from power-on?

Sure. Just modify FCEUX's source code to write the above memory for 0x780-0x7FC at power-on and you're set.
OK, if you mean play directly from power-on on console, then probably not. Well, let's look at it closely. You'll need the following binary values for the following addresses ('.' means any bit value):
0x784: .1....1.
0x789: 1..1....
0x78C-0x797: 11111111
0x798: 11111110
0x79C-0x7A9: 11111111
0x7AA: 11110...
0x7CF: 11......
0x7D4: 1.......
0x7E4: 11111101
0x7E5: 11111111
0x7E6: 110.....
0x7F2: ......1.
0x7FC: ......11

Count them. That's 250 bits that must be manipulated at power-on. Assuming each bit can be set independently to 0 or 1 with 0.5 probability each, that's a probability of (0.5)^250 to get a RAM state that works. If you set your NES on fire with a laser beam and throw it into a pool of water, then maybe, just maybe it will give you a RAM state that works.
On the other hand, why bother?

How about console verification?

There is a method which may allow it to be verified as starting from reset (not from power-on) even though we have no idea of the NES power-on state. See the resource link in the Other information section below.
The file Wheel of Fortune-clearmem-e34f x 77.fm2 (which we call file A) sets 77 bits in 0x780-0x7FC using RNG value C8.E34F (resetting immediately after activating each puzzle, except the last one). Run this file over and over until, during running the file, the range 0x780-0x7FC is zeroed out after being filled completely with 1-bits.
To tell if this has happened, see the shape of the last puzzle and compare it with the 77 puzzles in wofconsoleverify-puzzleshapes.txt (#0512-0588). If the puzzle is not in there, then the zeroing out did not happen. If the puzzle is there and does not have a star, then the zeroing out happened (except see the last sentence below). If the puzzle is there and has a star, then run Wheel of Fortune-e34f.fm2 (sets only 1 bit in 0x780-0x7FC using RNG value C8.E34F) and check the displayed puzzle (which should be the next one in the puzzle order) to confirm whether or not it is one of these puzzles. Also, if this is the first time running file A and the displayed puzzle is the last one in the puzzle order (#0588), then the zeroing out cannot be confirmed to have happened.
Since there are only 1000 puzzles, file A needs only to be run at most 13 times. On average, it requires 6.5 times.
Once the range has zeroed out, run Wheel of Fortune-verifyfrom0mem.fm2 to set up the necessary RAM for this TAS. Whether or not any additional puzzles of 0512-0588 have been activated by file A after zeroing out the range does not matter; neither Wheel of Fortune-verifyfrom0mem.fm2 nor the actual TAS are affected.
Note that this whole set-up takes a long time (anywhere from 1h40m to 5h20m, though if power-on RAM is truly random, then it takes on average 3h30m).
Once everything has been set up, just run the TAS (should begin with a reset). The TAS itself requires two controllers, even though the setup files only require one.
I don't know if there are any other important details for sync on a real console, but this is how it works, theoretically.

Other information (disassembly, etc.)

Some more information regarding game mechanics and disassembly can be found at the Game Resources page.
The resource link contains:
  • The verification movie file Wheel of Fortune-verificationfile.fm2 .
  • The files for possible method of console verification Wheel of Fortune-clearmem-e34f x 77.fm2 , wofconsoleverify-puzzleshapes.txt , Wheel of Fortune-verifyfrom0mem.fm2 as described above.
  • The program to generate the full list of puzzles and calculate a score for each one wofscript.cpp . It requires a ROM for this game, renamed zzz.nes .
  • Files to help with RNG manipulation wofrandomtable1.txt , wofrandomtable2.txt wofrandomtable3.txt , wofrandomtable4.txt , as well as the programs to generate them wof.h , wofrandom1.cpp , wofrandom2.cpp , wofrandom3.cpp , wofrandom4.cpp and an intermediate file woftbl .
    • Given the current value of RNG as BC.xxxx, wofrandomtable1.txt gives the input values required to be pressed on 0x0A=BE, C0, C2 to manipulate the RNG from BC.xxxx to C2.0400.
    • Given the desired value of RNG to be C8.xxxx, wofrandomtable2.txt gives the input values required to be pressed on 0x0A=C4, C6, C8 to manipulate the RNG from C2.0400 to C8.xxxx.
    • Given the value of RNG as C8.xxxx, wofrandomtable3.txt reveals the sequence of puzzles that the routine tries, in a standard/bonus round, before taking the first available puzzle from the last number given.
    • Given the value of RNG as C8.xxxx, wofrandomtable4.txt reveals the sequence of puzzles that the routine tries, in a speed-up round, before taking the first available puzzle from the last number given.
There were other program files and tables involved when I figured out how to use 2P input to manipulate the speed-up round, but it is probably too confusing to include them. They pretty much work on the same idea as the above programs and tables anyway.

Thanks

Thanks to PikachuMan, MESHUGGAH, and everyone else in the discussion thread for the previous Wheel of Fortune submission.

Nach: Judging.
FractalFusion: Cancelling this submission as explained in the latter half of this post.


Banned User
Joined: 3/10/2004
Posts: 7698
Location: Finland
adelikat wrote:
I personally support the notion of a TAS being able to control the initial (and arbitrary) ram state.
In principle a TAS is a demonstration of what would it look like if a theoretically superhuman being would play a video game on an actual console/computer. This means that this hypothetical being ought be able to somehow affect the initial RAM state of the console as the game starts. Is this even physically possible? And note that at least I understand this concept to mean that the "superhuman" just plays the game by pressing buttons. He's not able to directly reach into the console itself and start tampering with the electrons directly via some supernatural ability because if he could, then he could just as well modify the RAM after the game has started, as well as the CPU registers, and just skip to the end. So, my take is this: If the hypothetical superhuman player is not allowed to directly touch the RAM after the game has started, then neither should he be allowed to do so before. You would have to demonstrate another way of achieving the desired initial RAM state without directly tampering with it. (Even then it becomes more the philosophical question of what constitutes gameplay, but that's a different pet peeve of mine, so let's not go there right now.)
Emulator Coder
Joined: 3/9/2004
Posts: 4588
Location: In his lab studying psychology to find new ways to torture TASers and forumers
Warp wrote:
In principle a TAS is a demonstration of what would it look like if a theoretically superhuman being would play a video game on an actual console/computer. This means that this hypothetical being ought be able to somehow affect the initial RAM state of the console as the game starts. Is this even physically possible?
Post #357630
Warning: Opinions expressed by Nach or others in this post do not necessarily reflect the views, opinions, or position of Nach himself on the matter(s) being discussed therein.
adelikat
He/Him
Emulator Coder, Site Developer, Site Owner, Expert player (3576)
Joined: 11/3/2004
Posts: 4754
Location: Tennessee
Warp wrote:
This means that this hypothetical being ought be able to somehow affect the initial RAM state of the console as the game starts. Is this even physically possible?
It doesn't mean that this superhuman and CONTROl the random initial state. He only needs to be unbelievably lucky. The super human turns on the NES and it just happens to start in the perfect configuration for his needs.
It's hard to look this good. My TAS projects
Player (26)
Joined: 8/29/2011
Posts: 1206
Location: Amsterdam
feos wrote:
Radiant wrote:
Thankfully, the majority of games initialize their RAM before reading it, and for these games it's actually irrelevant what the initial RAM state of the emulator is.
Post #358364
Interesting. Okay, I think it would make sense to do the following test: add an option to an emulator to start with randomized initial RAM instead of patterned 0000FFFF; then see which of our existing runs on that emulator still sync. Anyway, I believe we had lengthy discussion and a poll about this subject; perhaps that central thread would be a better place for further debate than this grue'd game?
Emulator Coder
Joined: 3/9/2004
Posts: 4588
Location: In his lab studying psychology to find new ways to torture TASers and forumers
Radiant wrote:
add an option to an emulator to start with randomized initial RAM
That would be an utterly invalid starting state with most systems. A central point most seem to be missing is that memory is NOT random. Memory is filled with data from other sources, and these other sources are what can be random. Which means blocks of memory will contain some kind of pattern, which may or may not be discernible. Please see this page to get a better idea how memory is filled: Wiki: Nach/MemoryInit. As proven on that page, the amount of impossible cases greatly outnumber the amount of possible cases. RAM should NOT be filled randomly, as that will in most cases result in a starting state not possible with the hardware. The way I see almost everyone talking about here is a case where there are no relationships between bits of memory, however I haven't seen any mass produced computer system where that is ever the case.
Warning: Opinions expressed by Nach or others in this post do not necessarily reflect the views, opinions, or position of Nach himself on the matter(s) being discussed therein.
Editor, Emulator Coder, Site Developer
Joined: 5/11/2011
Posts: 1108
Location: Murka
Relevant paper: http://www.rfidsec07.etsit.uma.es/slides/papers/paper-12.pdf In short, it claims that individual bits in SRAM are not likely to be heavily affected by external sources. However, each bit will have a probability distribution (which is a fingerprint of the chip and determined by manufacturing variances), and some of them will strongly tend to '0' or '1', others will be close to 50-50 and subject to random variance from heat, etc.
Player (26)
Joined: 8/29/2011
Posts: 1206
Location: Amsterdam
Nach wrote:
Radiant wrote:
add an option to an emulator to start with randomized initial RAM
That would be an utterly invalid starting state with most systems.
I know. The point is not to do new runs with that setting, but to test whether existing runs actually depend on the RAM's initial state.
Joined: 1/13/2007
Posts: 343
There are a few circumstances. 1) power is removed from the system for an extended period of time. this should be the state the emulator presents. what initial states can happen after an extended absence of power? The game that doesn't boot in FCEUX and does on real hardware seems to prove that FCEUX initial state is NOT a valid one by those standards. it's initial state should be one that is likely to happen on a real console. 2) power is left off for a very small amount of time. this causes a minor change in state from what it was when it was powered off. on my c-64, for example this tends to cause one bit in each ram cell to flip on. the same one. this cannot be accurately emulated, so it seems this is NOT valid. 3) power is never actually dropped because person holds reset button while removing cart 1 and inserting cart two. this is possible on real hardware. so it's a valid TASing trick, in my opinion. you dn't even ave to press reset until after swapping the game. a real life example here https://www.youtube.com/watch?v=wyiBuX9y16k the movie attempted a variation of number 3. according to nesdev people, uninitialized ram after long term poweroff is mostly FF, with some memory locations having a single bit at 0. this confirms my experience with c-64 that a quick power off and on flips one of the bits to 1. So seems FCEUX is wrong, and that Nestopia is more correct. However, someone changing games reasonably quickly can produce a very different result (not an uncommon event in real life). So seems "random" initial state should randomly select values from the following pool FF FE FD FB F7 EF DF BF 7F with an extra high priority given to FF if it's to reproduce real world conditions from long term poweroff.
Skilled player (1743)
Joined: 9/17/2009
Posts: 4986
Location: ̶C̶a̶n̶a̶d̶a̶ "Kanatah"
Emulator Coder
Joined: 3/9/2004
Posts: 4588
Location: In his lab studying psychology to find new ways to torture TASers and forumers
jlun2 wrote:
I saw this recently: https://en.wikipedia.org/wiki/Row_hammer How plausible is that effect on any console?
Quite plausible, although is has little to do with power on state, and everything to do with some bits flipping while running. Emulating that means allowing for flipping whatever bit you want if nearby bits are modified at the same time. Systems designed for security often try to defend against this by ensuring no single bit is responsible for a particular setting, and often multiple bits are required to be in agreement, and are stored far away from each other. Cryptography Engineering talks about this, and recommends some distance offsets to use to ensure different values are not next to each other horizontally or vertically in the same cell on currently known popular hardware in order to ensure security objectives.
Warning: Opinions expressed by Nach or others in this post do not necessarily reflect the views, opinions, or position of Nach himself on the matter(s) being discussed therein.
Editor, Active player (459)
Joined: 2/11/2018
Posts: 240
Is this run worth rejudging now there is no genre restriction? I haven't looked into the RAM initialisation issue enough.