Random NFT

Often for genuine NFT you need to randomly allocate NFT to a minter. This is a recipe how to allocate random item on each mint without wasting too much gas.

randomize_lt();
;; Randomize through number of available choices in collection
int index = rand(collection_size - minted);
int value = 0;
;; Check if index was used, if used, dict should store skipped index (see code after)
(slice existing, int found) = cache.udict_get?(32, index);
if (found) {
value = existing~load_uint(32);
} else {
value = index;
}
;; Store tail in cache[index], because random in next function call would not include it
(slice tailValue, int foundTail) = cache.udict_get?(32, collection_size - minted - 1);
if (foundTail) {
cache~udict_set(32, index, tailValue);
} else {
cache~udict_set_builder(32, index, begin_cell().store_uint(collection_size - minted - 1, 32));
}
;; Cleanup tail
cache~udict_delete?(32, collection_size - minted - 1);