I just have a few questions about randomizers that don't seem to be covered in the wiki: - What games use the uncommon randomizers seen in Lockjaw? (8-bag, 14-bag, Strict History) - What games use randomizers besides 7-bag, History 6 rolls, Memoryless, and the three listed above? (I know TGM1 uses History 4 rolls, and some games use Bags of sizes other than 7, 8, and 14, but I'm not sure which ones.) - Do all History randomizers use the last four pieces? I vaguely recall that some game used the last three pieces in a Strict History randomizer. - What randomizer do Tetris (NES/Tengen), Tetris (Atari), Tetris DX (GBC), and Tetris (Sega) use? I'm assuming Memoryless for the first three and History for Sega, but I don't know whether Sega is Strict History or 4/6 rolls. Any answers would be greatly appreciated.
Tetris Online Japan's game prior to Minna de Tetris used 8-bag. I don't know of any games to use 14-bag, but The New Tetris uses 63-bag. As far as I know, Lockjaw is the only game to feature Strict History. NES and GB have each have their own method of reducing the likelihood of direct repetition. GB's method is such that repetition occurs when the number generated (in the range of 0-31 inclusive) is either 30 or 31. (EDIT: Zaphod's reported GB randomizer behavior turned out not to be so. After checking the disassembly, it essentially does ((DIVIDER_REGISTER-1)*4) % 0x1C to generate a new piece id, then will re-roll up to three times so long as (candidateRNG | lastRNG | lastPieceGenerated == lastPieceGenerated). I question the quality of using a timer register directly as a source of randomness, and I'm not convinced of using OR operators for the "equality" check considering that it can lead to certain pieces being more/less likely after one another based on the bit patterns representing each. Even with more rolls and more values in the history, it manages to be a slightly less "reputable" randomizer than NES's.) NES's method consists of two rolls: the first from 0-7 and a second from 0-6 if the first consisted of a repeat or a 7. As far as I know, TGM is the only commercial series to use a History randomizer and has always used the last four piece. I believe Tengen and Atari are both memoryless and -- if what is true for Tengen holds for Atari -- deterministic. I haven't spent much time with TDX, but my guess is that it is memoryless as well. Sega definitely does not use a History randomizer; it is memoryless and deterministic. When the game starts, it generates 1000 piece looping sequence.
NullpoMino has all of the randomizers you mentioned built-in (as BagBonus, DoubleBag, and StrictHistoryRandomizer respectively) although none of them are in use in the rules that we packed in. It also includes some other randomizers such as NES, GB, and randomizers that are based on distance weighting. As for the strict history, the only games that use strict history as far as we know are LJ and Nullpo, and both use a four-piece history. As a side note, I just ran it through my sequence analyzer and found that it performs worse than standard randomizers like TAP's, in that it will give you more droughts. For example: Code: Drought length | 3 hist strict | TGM1 (4h4r) | TAP (4h6r) ---------------|---------------|-------------|------------ 10 | 13.35 % | 11.88 % | 9.852 % 12 | 7.508 % | 6.050 % | 4.608 % 15 | 3.166 % | 2.200 % | 1.470 % 20 | .7510% | .4077% | .2204% So, you're more than three times as likely to get a huge drought (20 pieces) in a 3-history strict randomizer than in 4-history 6-rolls (TAP)... crazy! Might still be interesting to play with, though. Perhaps TDX should be analyzed...?
Any non-commercial (fan-made) games with a History randomizer besides those that emulate TGM? (ex. Don't count Heboris, NullpoMino, etc.) Also, on the note of Strict History, are there any options besides the ones listed below in Lockjaw that are exclusive to fan-made games? The ones I can think of right now are: - Rhythm speed curve - Hide falling piece - Instant DAS - TOD rotation - Floor kick limits of 2-5
DTET might, but it hasn't been extensively investigated yet. Other than that, there probably isn't much else unless you count games that also use History in their non-TGM modes like Blockbox. - DTET and Blockbox Rotation Systems - 180 Rotation key (or DTET's two-key 180s) - Buffered rotation: DTET will attempt to rotate a piece until successful while a given rotation button is held (i.e. rotation is triggered when moving out of a position where the rotation was blocked so long as the key is still down) - Instant Left/Right macros - Typing control schemes: any placement in the field is instantly accessible through one keypress (or two in schemes where rotation is still managed traditionally). - Deep drop: - Shiftlock: piece is prevented from acting on DAS charge maintained from the previous one until the drop key is released - Fractional garbage, Reduced attack power, Divide hole change rate by remaining opponents, and other sorts of alternatives to TTC's attack targeting system without using the full force of Send To All. I'm sure there are others, but these are the ones I can think of off the top of my head.
You forgot to explain what Deep Drop is. If a piece can fit underneath existing ones it will drop right through them. Very useful in the typing control games where sliding under an overhang would otherwise be impossible.
I seem to remember that 14-bag dated to a purported BPS employee's suggestion of how to change the Random Generator, back in the pre-HD days. That was LJ65, a fan game for NES. It uses a variant of strict history that avoids the last 3 instead of avoiding the last 4, but that's because random number generators on an 8-bit platform really want to have a power of two possibilities. Avoiding the last 3 lets the game choose one of the four least recently used, and four is a power of two. But then I droughts aren't quite as much of a problem there because of the common 2-wide combo play style. "Rhythm" was my attempt at a twist on Death/Shirase, except more forgiving because it allows the player to "bank" unused time for trickier placements of later pieces. "Hide falling piece" was a suggestion from caffeine as to how to learn to play by feel rather than by sight. If you can't see the piece until it lands, you have to memorize the finesse patterns. "Deep drop" dates to this discussion. As Caithness points out, Typomino also uses it. "TOD rotation" is used in TOD and LJ65. It's essentially SRS with TGM's wall kicks: 1 cell right, 1 cell left, and 1 cell up. (LJ65 calls TOD rotation "CENTER" and Ti rotation "BOTTOM".) The official Lockjaw support topic used to be right here on TC.net, but it got locked during a period last year when TC.net banned discussion of fan games as an effort to help TGM4 get released (start, end).
More info. The sega randomizer has a list of seeds it cycles through, and stores the most recently used one in NVRAM. Each game started uses the next seed in the sequence. The number of seeds is currently unknown. Sometimes it will skip the first piece in the sequence, but never when powering on from a cleared nvram. Atari/Tengen tetris is memoryless and also doesn't gather entropy during gameplay. this is so that when playing two player, both players get the same sequence. NES tetris by Nintendo does collect entropy during play, and is thus vulnerable to luck abuse during TAS play. Most games that do not use bag do not gather entropy during gameplay, so that they can give both players the same pieces in a versus match. Most games that DO use bag do not bother to do this. They will give both players a different sequence, but still deal out all seven before repeating.
I recently reverse engineered the Sega randomizers (there's two). The System 16A versions have the 1000-piece-looping behavior already well-documented, but the B-system versions have a completely different one. Some newly discovered details about the System 16A randomizer: There's a 32-bit internal randomizer state; it's 0x00000000 at power-on, or after clearing SRAM. The internal PRNG is called one extra time for selecting the gameover monkey animation, changing the randomizer state. So you can either hit start to skip the animation (so the PRNG won't be called), or wait it out; the PRNG is called right when the animation begins, so you can skip that call if you hit start while the monkey stands there. You'll have a different randomizer state next game depending on which choice you make. If you always make the same choice (skipping or waiting) you can know the internal randomizer state, and the upcoming game's piece sequence, by viewing the number of games played in the service menu, with the assistance of some code I've written; using it might be considered cheating, however... The B-System randomizer is different, and is a proper memoryless randomizer: It also has a 32-bit randomizer state, set to 0x00000000 every time the system is powered up (because the B-System version has no SRAM). The PRNG is used every time the next piece is needed (so it's "on-demand"); it doesn't generate a looping 1000-piece sequence. The game internally has separate randomizer states and PRNGs for the piece sequence and the monkey animation, so skipping or waiting for the monkey makes no difference for the piece sequence of the next game. The piece sequence is just one sequence, continuing between games (until 0x00000000, or some other previously generated seed, is generated again; I haven't checked how long that takes). The PRNGs in each version are completely different; when I was looking at the 68000 assembly, I felt as if the PRNG was completely redone for the B-System version. It's also clear the assembly was hand-written (this is somewhat relevant, because there were usable C compilers for the 68000 at the time Sega's arcade Tetris games were made). I've made a utility to let anyone experiment with the randomizers. The code could be repurposed for use in clones. I redid the algorithms so they're more nicely represented in C, but they're equivalent to the 68000 assembly. The code uses C99 exact-width integer types, so you'll have to provide your own appropriate typedefs if you're using a C89 compiler (but the code is otherwise C89-compliant). I'm not providing any binaries, so you have to compile it yourself.
About time. Now you need to check out all of the possible piece sequences, and figure out if they are foreverable. They most likely are. If you can bravo on the 1000th piece, that is definite proof.
okay, i think I get it now. Starting a game generates the 1000 piece sequence, and advances the state of the RNG 1000 times. Assuming all seeds can be used, this means there's actually possibly a 4,294,967,296 piece sequence, of which 1000 consecutive pieces are picked from. The monkey animation advances the state of the RNG once. If you don't skip the monkey, you get the first piece skipped, and one tacked onto the end. Time to mess with the program you made.
For anyone that knows how to use the MAME debugger, using the "tetris2" ROM set, you can investigate the System 16A randomizer in its original form. (Also, be sure you use a "focus 0" command, as the debugger starts up focusing on the Z80 sound CPU, not the 68000.) Look at the 4 bytes starting at memory position FFE028 to see the seed, and if you're feeling comfortable with 68000 assembly, you can set a breakpoint at 003FE2 to see the code that generates the 1000 piece sequence before a game starts, writing the sequence 1-byte-per-piece starting at FFE400. For the B-System version, use the "tetrist" ROM set, and set a breakpoint at 00585E, with the 4-byte seed stored starting at 8046E4. (You don't need to use the focus command with the B-System version, it's focused on the 68000 by default.) Also, you can set a watchpoint for d@FFE028 to see the monkey animation thing happening at gameover, for completeness. When looking at the assembly in the debugger, it helps to know the mapping between tetrominoes and the bytes the code uses to refer to them. For System 16A, it's 00=I, 01=Z, 02=S, 03=O, 04=T, 05=L, 06=J. For B-System, it's 01=I, 02=L, 03=J, 04=S, 05=Z, 06=T, 07=O. (00 isn't used in the B-System.) My C code has the same mapping for each randomizer, so it's easy to compare the accuracy of my code to the originals. As a note to clone devs, looking at the C code for the System 16A randomizer, the value of the 'seed' variable at any time is what you'd save before your program closes, and restore it to that same value the next time. You could also have persistence for the B-System randomizer, if you wanted to implement it as well.