A weird little randomizer I came up with recently. I haven't tested it much in-game. Its droughts aren't as bad as TAP's (it's somewhere between bag and 2bag), but the chance of doubles is higher (but not as bad as full random). From the file: Pieces are taken from a set bag (such as JILTSOZ) in order, repeating, to fill a window of a fixed size (I use 4, but any number > 1 works; higher numbers behave more like full random, but still with shorter droughts). Each time a piece is needed, it is chosen randomly from the window, and then replaced with the next piece in the bag order. The order of the bag is notably important when the window size is smaller than the bag -- this limits what the first piece can be (only JILT, with my parameters). Code: ''' the Forever Bag Pieces are taken from a set bag (such as JILTSOZ) in order, repeating, to fill a window of a fixed size (I use 4, but any number > 1 works; higher numbers behave more like full random, but still with shorter droughts). Each time a piece is needed, it is chosen randomly from the window, and then replaced with the next piece in the bag order. The order of the bag is notably important when the window size is smaller than the bag -- this limits what the first piece can be (only JILT, with my parameters). Worst droughts: full random > nes > tap > 2bag > foreverbag > bag > flatbag Chance of doubles: full random > 2bag > foreverbag > nes > bag > tap > flatbag Bagginess: flatbag > bag > tap > foreverbag > 2bag > nes > full random flatbag = JILTSOZ dealt in order, repeating forever 2bag = one bag of two sets of JILTSOZ (14 piece bag) bagginess = percent of 7-piece windows which have all 7 pieces ''' import random class ForeverBag: def __init__(self, bag, windowsize): self.bag = list(bag) self.size = windowsize self.window = [] self.i = 0 for i in range(self.size): self.window.append(self.bag[self.i]) self.i = (self.i + 1) % len(self.bag) def next(self): r = random.randint(0, self.size - 1) p = self.window[r] self.window[r] = self.bag[self.i] self.i = (self.i + 1) % len(self.bag) return p if __name__ == '__main__': fb = ForeverBag('jiltsoz', 4) for i in range(10): s = '' for i in range(40): s += fb.next() print s

Ah so it is. If you shuffle the bag each time it is exhausted, it removes that bias (which I believe is determined by the order of the bag) -- the result looks pretty close to 2bag, but presumably without seams.