-
Notifications
You must be signed in to change notification settings - Fork 76
Description
https://harddrop.com/wiki/Random_Generator is a useful link.
Quoting @bb010g:
basically, you don't normally want an algorithm that's friendly in certain ways, you want randomness that's less prone to dick the player over and that advanced players can work with at a higher level. Tetris handles this by allocating a "bag" of each piece type when new tetrominoes are needed, shuffling that, and then passing out from there.
Bags let you do things like avoid really long runs of certain pieces and adjust rarity without being complex or too deterministic.
alternatively, Akira's The Grand Master traditionally handles this by keeping a history of the last N pieces, and then generating a new piece up to M times until a unique piece appears or the limit is reached. https://harddrop.com/wiki/TGM_randomizer
huh, Terror Instinct does a thing where it keeps a 35 piece bag for that generation that starts with 5 of each piece, and when a piece is genned (pulled) from it a piece of the least recent type is put in its place, which keeps pieces from not showing up for a long while.
https://tetrisconcept.net/threads/randomizer-theory.512/page-9#post-55478
# PETE ROOLZ # # you can get a quick sequence out with # python -c 'import tgm; r = tgm.TiRandomizer(); print "".join([r.next() for i in range(70)])' import random import collections # On a Ti randomizer bug: # # > When these 3 conditions are met: # > # > 1. The randomizer has just chosen the most droughted piece # > 2. A reroll happened during the choice of that piece. # > 3. Excluding the first piece of the game, and including this chosen piece, you have received at least one of each of the 7 piece types. # > # > Then the roll that chose that most droughted piece will not update the bag of 35 pieces. # # -- colour_thief, http://tetrisconcept.net/threads/randomizer-theory.512/page-7 def TiRandomizer(): bag = ['j', 'i', 'z', 'l', 'o', 't', 's'] * 5 history = collections.deque(['s', 'z', 's', 'z']) drought_order = ['j', 'i', 'z', 'l', 'o', 't', 's'] count = { 'j' : 0, 'i' : 0, 'z' : 0, 'l' : 0, 'o' : 0, 't' : 0, 's' : 0 } n = 1 # first piece is special first = random.choice(['j','i','l','t']) history.popleft() history.append(first) yield first while True: for roll in range(6): i = random.randint(0, 34) piece = bag[i] if piece not in history: break if roll < 5: bag[i] = drought_order[0] count[piece] += 1 emulate_bug = all ([ piece == drought_order[0], roll > 0, 0 not in count.values() ]) if not emulate_bug: bag[i] = drought_order[0] drought_order.remove(piece) drought_order.append(piece) history.popleft() history.append(piece) yield piece if __name__ == '__main__': r = TiRandomizer() print "".join([r.next() for i in range(70)])anyways, point is that you can keep randomness in a lot of ways while not just calling rand and being done
I should probably just PR something for this