Skip to content

Instantly share code, notes, and snippets.

@corck
Created June 9, 2021 15:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save corck/ea311104a7f9004b8fc5bbb1f1e47204 to your computer and use it in GitHub Desktop.
Save corck/ea311104a7f9004b8fc5bbb1f1e47204 to your computer and use it in GitHub Desktop.
Chubbies Generation Code
'''
The MIT License
Copyright (c) 2021 Chubbies NFT
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
'''
# This is the exact code used to generate the gifs for all 10000 Chubbies NFT and the json for properties for OpenSea.
# It will need some editing to work for another project as the code was meant to work for Chubbies' needs specifically.
from PIL import Image
import json
import random
import sys
import os
import time
# TODO
# [x] Function to generate the rare pool
# [x] Function to divide rare arrays into 10 and replace indices in each bucket
# [x] Function to analyze the array and report on the traits.
# [x] Deduplicate Chubbies
# Create output paths if it don't exist
if not os.path.exists('output'):
os.makedirs('output')
os.makedirs('output/json')
os.makedirs('output/gifs')
# Special Treatment Chubbies, like Mewtwo
SPECIAL_LAB_CHUBBY_0 = 0
SPECIAL_LAB_CHUBBY_9999 = 9999
# Directory paths
background_path = "./chubbies/background/"
shadow_path = "./chubbies/shadow/"
face_path = "./chubbies/face/"
bottom_path = "./chubbies/bottom/"
head_path = "./chubbies/head/"
top_path = "./chubbies/top/"
accessories_path = "./chubbies/accessories/"
filetype = ".png"
# Field Names
TOP_COSTUME_NAME = "Top Costume"
BOTTOM_COSTUME_NAME = "Bottom Costume"
HEAD_RACE_NAME = "Head Race"
BOTTOM_RACE_NAME = "Bottom Race"
FACE_NAME = "Face"
HAIRSTYLE_NAME = "Hairstyle"
HUMAN_SKIN_TONE_NAME = "Human Skin Tone"
CAT_COLOR_TYPE_NAME = "Cat Color Type"
ACCESSORIES_NAME = "Accessories"
SHININESS_NAME = "Shininess"
BACKGROUND_NAME = "Background"
HUMAN_BOTTOM_NAME = "Human Bottom"
COSTUME_TOKEN_NAME = "Token"
METHOD_NAME = "Method"
METHOD_LAB_GROWN = "Lab-Grown"
METHOD_NATURAL = "Natural"
METHOD_GODMODE = "God Mode"
SET_NAME = "Set"
SET_MATCHED_NAME = "Yay"
SET_MISMATCHED_NAME = "Nah"
SET_TYPE_NAME = "Set Type"
SET_TYPE_HUMAN_RACE_NAME = "Human Race"
SET_TYPE_NON_HUMAN_RACE_NAME = "Non-Human Race"
SET_TYPE_COSTUME_NAME = "Costume"
BACKGROUND_NORMAL_RARITY = 8
bottom_with_skin_tone = {"Human_Duck Tube", "Banana", "Human_Duck Tube_shiny", "Banana_shiny", "Human_Jeans", "Human_Jeans_shiny"}
HUMAN_RACE_NAME = "Human"
CAT_RACE_NAME = "Cat"
#### Rarity Chart
# RACE
HEAD_RACE_OPTIONS = {"Alien": 50, "Ape": 250, "Monkey": 1000, "Robot": 700, "Snowman": 100, "Squid": 300, "Zombie": 200, CAT_RACE_NAME: 1000, HUMAN_RACE_NAME: 6500}
BOTTOM_RACE_OPTIONS = {"Alien": 50, "Snowman": 100, "Ape": 250, "Squid": 400, "Robot": 700, "Monkey": 800, "Zombie": 200, CAT_RACE_NAME: 1000, HUMAN_RACE_NAME: 6500}
# COSTUMES
TOP_COSTUME_OPTIONS = {"Apple": 200, "Astronaut": 50, "Avocado": 400, "Banana": 200, "Cat": 800, "Chicken": 500, "Kaiju": 250, "Kuma": 800, "Milk Cow": 500, "Monkey": 800, "Penguin": 500, "Pig": 500, "Raccoon": 500, "Shiba": 800, "Special Monkey": 10}
BOTTOM_COSTUME_OPTIONS = {"Apple": 100, "Astronaut": 50, "Avocado": 300, "Banana": 200, "Cat": 800, "Chicken": 500, "Kaiju": 250, "Kuma": 800, "Milk Cow" : 500, "Monkey": 800, "Penguin": 500, "Pig": 500, "Raccoon": 500, "Shiba": 800}
# FACE
FACE_OPTIONS = {"-_-": 3, "-_- Blushed": 3, "+w+": 1, "|_|": 3, "|_| Blushed": 3, "Alien": 1, "Angry": 3, "Ape": 1, "Cat": 3, "Cat Blushed": 3, "o_o": 3, "o_o Blushed": 3, "Zombie": 1
}
# ACCESSORIES
ACCESSORIES_OPTIONS = {"": 850, "Butterfly": 25, "Diamond Hands": 25, "Propeller Hat": 25, "My Wifes Sunglasses": 25, "Sunglasses": 25, "Crown": 25}
SHININESS_OPTIONS = {"shiny": 1, "": 50}
COSTUME_TOKEN_OPTIONS = {"": 1, "Heart": 1, "Skull": 1}
# HUMAN-ONLY
HUMAN_SKIN_TONE_OPTIONS = {"light": 1, "medium": 1, "brown": 1, "dark": 1}
HUMAN_BOTTOM_OPTIONS = {"Duck Tube": 1, "Jeans": 5}
HAIRSTYLE_OPTIONS = {"Afro": 1, "Long": 2, "Short": 3}
# CAT-ONLY
CAT_COLOR_TYPE_OPTIONS = {"Black": 3, "Pusheen": 7}
# BACKGROUNDS
BACKGROUND_OPTIONS = {"Ao English": BACKGROUND_NORMAL_RARITY, "Celeste": BACKGROUND_NORMAL_RARITY, "Chocolate Web": BACKGROUND_NORMAL_RARITY, "Disco": 1, "Eerie Black": BACKGROUND_NORMAL_RARITY, "French Violet": BACKGROUND_NORMAL_RARITY, "Indigo": BACKGROUND_NORMAL_RARITY, "Lavender Blue": BACKGROUND_NORMAL_RARITY, "Medium Champagne": BACKGROUND_NORMAL_RARITY, "Melon": BACKGROUND_NORMAL_RARITY, "Night Club": BACKGROUND_NORMAL_RARITY, "Nyanza": BACKGROUND_NORMAL_RARITY, "Orange Yellow": BACKGROUND_NORMAL_RARITY, "Pastel Pink": BACKGROUND_NORMAL_RARITY, "Rainbow": 1, "Resting Lab": BACKGROUND_NORMAL_RARITY, "Ruby Red": BACKGROUND_NORMAL_RARITY, "Sapphire": BACKGROUND_NORMAL_RARITY, "Secret Forest": 1, "Silver": BACKGROUND_NORMAL_RARITY, "Sky": 1, "Space": 1, "White": BACKGROUND_NORMAL_RARITY, "Working Lab": 1
}
final_version_skin_properties = []
######################################################################################################
def is_fruit_costume(name):
return name in ["Banana", "Apple", "Avocado", "Astronaut"]
# Concatenate image
def image_cat(background, bottom, bottom_skintone, is_human, head, top, face, face_color, skin_tone, accessories, shiny):
medium_skin_tone = (250, 206, 171, 255)
light_skin_tone = (255, 225, 201, 255)
brown_skin_tone = (213, 157, 103, 255)
dark_skin_tone = (111, 63, 60, 255)
medium_skin_shadow = (231, 170, 154, 255)
light_skin_shadow = (255, 188, 157, 255)
brown_skin_shadow = (172, 110, 53, 255)
dark_skin_shadow = (89, 44, 48, 255)
black = (0, 0, 0, 255)
white = (255, 255, 255, 255)
short_head_medium_skin_shadow = (205, 162, 118, 255)
image = Image.open(background)
pix = image.load()
width, height = image.size
skin_properties = [bottom, head, top, face]
for current in range(len(skin_properties)):
if skin_properties[current] == "":
continue
elif skin_properties[current] == top and not is_human:
new_image = Image.open(skin_properties[current]).convert("RGBA")
new_pix = new_image.load()
for i in range(width):
for j in range(height):
if new_pix[i, j][3] != 0:
if new_pix[i, j] == medium_skin_tone or new_pix[i, j] == medium_skin_shadow or new_pix[i, j] == short_head_medium_skin_shadow:
continue
else:
pix[i, j] = new_pix[i, j]
elif skin_properties[current] == top or skin_properties[current] == head or (skin_properties[current] == bottom and bottom_skintone):
new_image = Image.open(skin_properties[current]).convert("RGBA")
new_pix = new_image.load()
for i in range(width):
for j in range(height):
if new_pix[i, j][3] != 0:
if new_pix[i, j] == medium_skin_tone:
if skin_tone == "light":
pix[i, j] = light_skin_tone
elif skin_tone == "brown":
pix[i, j] = brown_skin_tone
elif skin_tone == "dark":
pix[i, j] = dark_skin_tone
elif skin_tone == "medium":
pix[i, j] = medium_skin_tone
else:
continue
elif new_pix[i, j] == medium_skin_shadow or new_pix[i, j] == short_head_medium_skin_shadow:
if skin_tone == "light":
pix[i, j] = light_skin_shadow
elif skin_tone == "brown":
pix[i, j] = brown_skin_shadow
elif skin_tone == "dark":
pix[i, j] = dark_skin_shadow
elif skin_tone == "medium":
pix[i, j] = new_pix[i, j]
else:
continue
else:
pix[i, j] = new_pix[i, j]
else:
new_image = Image.open(skin_properties[current]).convert("RGBA")
new_pix = new_image.load()
for i in range(width):
for j in range(height):
if new_pix[i, j][3] != 0:
pix[i, j] = new_pix[i, j]
if face_color == "white":
new_image = Image.open(face).convert("RGBA")
new_pix = new_image.load()
for i in range(width):
for j in range(height):
if new_pix[i, j] == black:
pix[i, j] = white
if accessories != "":
new_image = Image.open(accessories).convert("RGBA")
new_pix = new_image.load()
for i in range(width):
for j in range(height):
if new_pix[i, j][3] != 0:
pix[i, j] = new_pix[i, j]
if shiny != "":
new_image = Image.open(shiny).convert("RGBA")
new_pix = new_image.load()
for i in range(width):
for j in range(height):
if new_pix[i, j][3] != 0:
pix[i, j] = new_pix[i, j]
return image
def gen_all_properties(num_tokens):
total_tokens = num_tokens * 5
random_use_bottom_costumes = random.choices([0, 1], weights=[50, 50], k=total_tokens)
# Races
random_head_races = random.choices(list(HEAD_RACE_OPTIONS.keys()), weights=HEAD_RACE_OPTIONS.values(), k=total_tokens)
random_top_costumes = random.choices(list(TOP_COSTUME_OPTIONS.keys()), weights=TOP_COSTUME_OPTIONS.values(), k=total_tokens)
random_bottom_races = random.choices(list(BOTTOM_RACE_OPTIONS.keys()), weights=BOTTOM_RACE_OPTIONS.values(), k=total_tokens)
random_bottom_costumes = random.choices(list(BOTTOM_COSTUME_OPTIONS.keys()), weights=BOTTOM_COSTUME_OPTIONS.values(), k=total_tokens)
random_faces = random.choices(list(FACE_OPTIONS.keys()), weights=FACE_OPTIONS.values(), k=total_tokens)
random_shininess = random.choices(list(SHININESS_OPTIONS.keys()), weights=SHININESS_OPTIONS.values(), k=total_tokens)
random_accessories = random.choices(list(ACCESSORIES_OPTIONS.keys()), weights=ACCESSORIES_OPTIONS.values(), k=total_tokens)
random_backgrounds = random.choices(list(BACKGROUND_OPTIONS.keys()), weights=BACKGROUND_OPTIONS.values(), k=total_tokens)
# Human only
random_skin_tones = random.choices(list(HUMAN_SKIN_TONE_OPTIONS.keys()), weights=HUMAN_SKIN_TONE_OPTIONS.values(), k=total_tokens)
random_hair_styles = random.choices(list(HAIRSTYLE_OPTIONS.keys()), weights=HAIRSTYLE_OPTIONS.values(), k=total_tokens)
random_human_bottoms = random.choices(list(HUMAN_BOTTOM_OPTIONS.keys()), weights=HUMAN_BOTTOM_OPTIONS.values(), k=total_tokens)
# Cats only
random_cat_colors = random.choices(list(CAT_COLOR_TYPE_OPTIONS.keys()), weights=CAT_COLOR_TYPE_OPTIONS.values(), k=total_tokens)
random_costume_badges = random.choices(list(COSTUME_TOKEN_OPTIONS.keys()), weights=COSTUME_TOKEN_OPTIONS.values(), k=total_tokens)
property_maps = []
dedup_set = set()
# Generate GIFs
for i in range(total_tokens):
property_map = {
TOP_COSTUME_NAME: random_top_costumes[i],
BOTTOM_COSTUME_NAME: random_bottom_costumes[i] if random_use_bottom_costumes[i] else "",
HEAD_RACE_NAME: random_head_races[i],
BOTTOM_RACE_NAME: random_bottom_races[i] if not random_use_bottom_costumes[i] else "",
FACE_NAME: random_faces[i],
SHININESS_NAME: random_shininess[i],
ACCESSORIES_NAME: random_accessories[i],
BACKGROUND_NAME: random_backgrounds[i],
HUMAN_BOTTOM_NAME: random_human_bottoms[i] if random_bottom_races[i] == HUMAN_RACE_NAME else "",
HAIRSTYLE_NAME: random_hair_styles[i] if random_head_races[i] == HUMAN_RACE_NAME else "",
HUMAN_SKIN_TONE_NAME: random_skin_tones[i] if random_head_races[i] == HUMAN_RACE_NAME or random_bottom_races[i] == HUMAN_RACE_NAME or random_bottom_costumes[i] == "Banana" else "",
CAT_COLOR_TYPE_NAME: random_cat_colors[i] if random_head_races[i] == CAT_RACE_NAME or random_bottom_races[i] == CAT_RACE_NAME else "",
COSTUME_TOKEN_NAME: random_costume_badges[i] if (random_bottom_costumes[i] in BOTTOM_COSTUME_OPTIONS) and not is_fruit_costume(random_bottom_costumes[i]) else "",
METHOD_NAME: METHOD_NATURAL,
}
criteria = "".join(property_map.values())
if not duplicate(property_map, dedup_set):
dedup_set.add(criteria)
property_maps.append(property_map)
if (len(property_maps) == num_tokens):
break
return (property_maps, dedup_set)
# gen all the sets and distribute them equally into buckets
def gen_all_sets(property_maps, dedup_set, num_buckets):
costume_set_maps = []
race_set_maps =[]
shiny_costume_set_maps = []
shiny_race_set_maps = []
rare_dedup_index_set = set()
rare_dedup_index_set.add(SPECIAL_LAB_CHUBBY_0)
rare_dedup_index_set.add(SPECIAL_LAB_CHUBBY_9999)
for option in TOP_COSTUME_OPTIONS.keys():
if option in BOTTOM_COSTUME_OPTIONS.keys():
new_property_map = {METHOD_NAME: METHOD_LAB_GROWN}
new_property_map[TOP_COSTUME_NAME] = option
new_property_map[BOTTOM_COSTUME_NAME] = option
new_property_map[BOTTOM_RACE_NAME] = ""
if not is_fruit_costume(option):
new_property_map[COSTUME_TOKEN_NAME] = random.choices(list(COSTUME_TOKEN_OPTIONS.keys()), weights=COSTUME_TOKEN_OPTIONS.values(), k=1)[0]
if option == "Banana":
new_property_map[HUMAN_SKIN_TONE_NAME] = "dark"
for i in range(6):
costume_set_maps.append(new_property_map)
for option in HEAD_RACE_OPTIONS.keys():
if option in BOTTOM_RACE_OPTIONS.keys():
new_property_map = {METHOD_NAME: METHOD_LAB_GROWN}
new_property_map[HEAD_RACE_NAME] = option
new_property_map[BOTTOM_RACE_NAME] = option
new_property_map[TOP_COSTUME_NAME] = ""
new_property_map[BOTTOM_COSTUME_NAME] = ""
if option == HUMAN_RACE_NAME:
for human_bottom_option in HUMAN_BOTTOM_OPTIONS:
for hair_style_option in HAIRSTYLE_OPTIONS:
for skin_tone_option in HUMAN_SKIN_TONE_OPTIONS:
new_property_map[HAIRSTYLE_NAME] = hair_style_option
new_property_map[HUMAN_BOTTOM_NAME] = human_bottom_option
new_property_map[HUMAN_SKIN_TONE_NAME] = skin_tone_option
race_set_maps.append(new_property_map)
elif option == CAT_RACE_NAME:
for cat_color_option in CAT_COLOR_TYPE_OPTIONS:
new_property_map[CAT_COLOR_TYPE_NAME] = cat_color_option
race_set_maps.append(new_property_map)
else:
for i in range(6):
race_set_maps.append(new_property_map)
for option in TOP_COSTUME_OPTIONS.keys():
if option in BOTTOM_COSTUME_OPTIONS.keys():
new_property_map = {METHOD_NAME: METHOD_LAB_GROWN}
new_property_map[TOP_COSTUME_NAME] = option
new_property_map[BOTTOM_COSTUME_NAME] = option
new_property_map[BOTTOM_RACE_NAME] = ""
new_property_map[SHININESS_NAME] = "shiny"
if not is_fruit_costume(option):
new_property_map[COSTUME_TOKEN_NAME] = random.choice(list(COSTUME_TOKEN_OPTIONS.keys()))
if option == "Banana":
new_property_map[HUMAN_SKIN_TONE_NAME] = "dark"
shiny_costume_set_maps.append(new_property_map)
print("Generating Shiny sets")
for option in HEAD_RACE_OPTIONS.keys():
if option in BOTTOM_RACE_OPTIONS.keys():
new_property_map = {METHOD_NAME: METHOD_LAB_GROWN}
new_property_map[HEAD_RACE_NAME] = option
new_property_map[BOTTOM_RACE_NAME] = option
new_property_map[TOP_COSTUME_NAME] = ""
new_property_map[BOTTOM_COSTUME_NAME] = ""
new_property_map[SHININESS_NAME] = "shiny"
if option == HUMAN_RACE_NAME:
for human_bottom_option in HUMAN_BOTTOM_OPTIONS:
for hair_style_option in HAIRSTYLE_OPTIONS:
for skin_tone_option in HUMAN_SKIN_TONE_OPTIONS:
new_property_map[HAIRSTYLE_NAME] = hair_style_option
new_property_map[HUMAN_BOTTOM_NAME] = human_bottom_option
new_property_map[HUMAN_SKIN_TONE_NAME] = skin_tone_option
shiny_race_set_maps.append(new_property_map)
elif option == CAT_RACE_NAME:
for cat_color_option in CAT_COLOR_TYPE_OPTIONS:
new_property_map[CAT_COLOR_TYPE_NAME] = cat_color_option
shiny_race_set_maps.append(new_property_map)
else:
shiny_race_set_maps.append(new_property_map)
shiny_race_set_maps.append(new_property_map)
rares = [costume_set_maps, race_set_maps, shiny_costume_set_maps, shiny_race_set_maps]
print("Distributing Sets")
for rare_set in rares:
random.shuffle(rare_set)
distribute_to_buckets(property_maps, rare_set, num_buckets, dedup_set, rare_dedup_index_set)
print(f"Added {len(rare_set)} rare items")
def gen_gif(index, property_maps):
images = []
property_map = property_maps[index]
for i in range(1, 6):
shiny_extension = "_shiny" if property_map[SHININESS_NAME] != "" else ""
# Special treatment
bottom_property = property_map[BOTTOM_RACE_NAME] if len(property_map[BOTTOM_RACE_NAME]) > 0 else property_map[BOTTOM_COSTUME_NAME]
bottom_filename = bottom_property
head_property = property_map[HEAD_RACE_NAME]
head_filename = head_property
if (property_map[HEAD_RACE_NAME] == HUMAN_RACE_NAME):
head_filename += "_" + property_map[HAIRSTYLE_NAME]
if (property_map[BOTTOM_RACE_NAME] == HUMAN_RACE_NAME):
bottom_filename += "_" + property_map[HUMAN_BOTTOM_NAME]
if (property_map[HEAD_RACE_NAME] == CAT_RACE_NAME):
head_filename += "_" + property_map[CAT_COLOR_TYPE_NAME]
if (property_map[BOTTOM_RACE_NAME] == CAT_RACE_NAME):
bottom_filename += "_" + property_map[CAT_COLOR_TYPE_NAME]
if (COSTUME_TOKEN_NAME in property_map) and (len(property_map[COSTUME_TOKEN_NAME]) > 0) and (len(property_map[BOTTOM_COSTUME_NAME]) > 0) and (not is_fruit_costume(property_map[BOTTOM_COSTUME_NAME])):
bottom_filename += "_" + property_map[COSTUME_TOKEN_NAME]
# def image_cat(background, bottom, bottom_skintone, is_human, head, top, face, face_color, skin_tone, accessories, shiny):
currentimage = image_cat(
background_path + property_map[BACKGROUND_NAME] + str(i) + filetype,
bottom_path + bottom_filename + shiny_extension + str(i) + filetype,
bottom_filename in bottom_with_skin_tone,
property_map[HEAD_RACE_NAME] == HUMAN_RACE_NAME,
head_path + head_filename + shiny_extension + str(i) + filetype,
top_path + property_map[TOP_COSTUME_NAME] + shiny_extension + str(i) + filetype if property_map[TOP_COSTUME_NAME] != "" else "",
face_path + property_map[FACE_NAME] + str(i) + filetype,
"white" if property_map[HEAD_RACE_NAME] == CAT_RACE_NAME and property_map[CAT_COLOR_TYPE_NAME] == "Black" and property_map[SHININESS_NAME] != "shiny" else "black",
property_map[HUMAN_SKIN_TONE_NAME] if HUMAN_SKIN_TONE_NAME in property_map.keys() else "",
accessories_path + property_map[ACCESSORIES_NAME] + str(i) + filetype if property_map[ACCESSORIES_NAME] != "" else "",
accessories_path + "shiny" + str(i) + filetype if property_map[SHININESS_NAME] == "shiny" else ""
)
images.append(currentimage)
images[0].save("./output/gifs/" +str(index) + '.gif', save_all=True, append_images=images[1:], duration=150, loop=0)
def gen_all_gifs(property_maps):
for index in range(len(property_maps)):
if index % 20 == 0:
print(index)
gen_gif(index, property_maps)
# Like Epidemic Cards in Pandemic
def distribute_to_buckets(property_maps, distribute_maps, num_buckets, dedup_set, rare_dedup_index_set):
num_tokens = len(property_maps) #10000
bucket_size = int(num_tokens/num_buckets) #1000
num_per_bucket = int(len(distribute_maps) / num_buckets)
num_per_bucket = 1 if num_per_bucket == 0 else num_per_bucket
# print(f"len(distribute_maps): {len(distribute_maps)}")
# print(f"bucket_size Size: {bucket_size}")
# print(f"num_per_bucket: {bucket_size}")
for distribute_map_index in range(len(distribute_maps)):
bucket_index = int(distribute_map_index / num_per_bucket)
if bucket_index >= num_buckets:
bucket_index = num_buckets - 1
while True:
target_index = int(bucket_index * bucket_size + random.choice(range(bucket_size)))
#print(f"target_index: {target_index}")
if (target_index >= len(property_maps)):
continue
new_property_map = property_maps[target_index] | distribute_maps[distribute_map_index]
if not (target_index in rare_dedup_index_set and duplicate(new_property_map, dedup_set)):
break
property_maps[target_index] = new_property_map
rare_dedup_index_set.add(target_index)
dedup_set.add(get_duplicate_criteria(new_property_map))
def get_duplicate_criteria(property_map):
return "".join(property_map.values())
# Check Duplicates
def duplicate(property_map, dedup_set):
return get_duplicate_criteria(property_map)in dedup_set
# Just to make sure
def duplicate_sanity_check(property_maps):
new_sanity_dedup_set = set()
for i in range(len(property_maps)):
property_map = property_maps[i]
if duplicate(property_map, new_sanity_dedup_set):
print("MAYDAY, there's a duplicate Chubby who sneaked in!!! SOMETHING IS VERY WRONG.")
sys.exit()
# Print Analytics
def print_insights(property_maps, num_buckets):
num_tokens = len(property_maps)
bucket_size = int(num_tokens/num_buckets)
property_rarity_counts = [{
"race sets": 0,
"costume sets": 0,
"lab-grown": 0,
"natural": 0
} for x in range(num_buckets)]
for index in range(num_tokens):
bucket_index = int(index / bucket_size)
property_map = property_maps[index]
if property_map[TOP_COSTUME_NAME] == property_map[BOTTOM_COSTUME_NAME]:
property_rarity_counts[bucket_index]["costume sets"] += 1
if property_map[HEAD_RACE_NAME] == property_map[BOTTOM_RACE_NAME]:
property_rarity_counts[bucket_index]["race sets"] += 1
for index in range(len(property_rarity_counts)):
num_race_set = property_rarity_counts[index]["race sets"]
num_costumes_set = property_rarity_counts[index]["costume sets"]
print(f"Bucket {index}: {num_race_set} race sets {num_costumes_set} costume sets")
# Creating Mewtwos
def incubate_lab_grown_chubby_gods(property_maps, dedup_set):
# Husband's pick
property_maps[SPECIAL_LAB_CHUBBY_0] = {
TOP_COSTUME_NAME: "Astronaut",
BOTTOM_COSTUME_NAME: "Astronaut",
HEAD_RACE_NAME: "Alien",
BOTTOM_RACE_NAME: "",
FACE_NAME: "Alien",
SHININESS_NAME: "shiny",
ACCESSORIES_NAME: "Diamond Hands",
BACKGROUND_NAME: "Space",
METHOD_NAME: METHOD_GODMODE,
}
# Wife's pick
property_maps[SPECIAL_LAB_CHUBBY_9999] = {
TOP_COSTUME_NAME: "Pig",
BOTTOM_COSTUME_NAME: "",
HEAD_RACE_NAME: "Human",
BOTTOM_RACE_NAME: "Human",
FACE_NAME: "Cat Blushed",
SHININESS_NAME: "shiny",
ACCESSORIES_NAME: "Propeller Hat",
BACKGROUND_NAME: "Sky",
HUMAN_BOTTOM_NAME: "Duck Tube",
HAIRSTYLE_NAME: "Afro",
HUMAN_SKIN_TONE_NAME: "light",
METHOD_NAME: METHOD_GODMODE,
}
def output_json(property_maps, image_url):
for index in range(len(property_maps)):
property_map = property_maps[index]
data = {}
data["attributes"] = []
if property_map[HEAD_RACE_NAME] != HUMAN_RACE_NAME and property_map[BOTTOM_RACE_NAME] != HUMAN_RACE_NAME:
property_map[HUMAN_SKIN_TONE_NAME] = ""
if (property_map[BOTTOM_RACE_NAME] != "" and property_map[BOTTOM_RACE_NAME] != HUMAN_RACE_NAME) or (property_map[BOTTOM_RACE_NAME] == "" and property_map[BOTTOM_COSTUME_NAME] != ""):
property_map[HUMAN_BOTTOM_NAME] = ""
if property_map[BOTTOM_RACE_NAME] != "" or is_fruit_costume(property_map[BOTTOM_COSTUME_NAME]):
property_map[COSTUME_TOKEN_NAME] = ""
if property_map[HEAD_RACE_NAME] != CAT_RACE_NAME and property_map[BOTTOM_RACE_NAME] != CAT_RACE_NAME:
property_map[CAT_COLOR_TYPE_NAME] = ""
if property_map[HEAD_RACE_NAME] != HUMAN_RACE_NAME:
property_map[HAIRSTYLE_NAME] = ""
is_race_set = (HEAD_RACE_NAME in property_map) and (BOTTOM_RACE_NAME in property_map) and (property_map[HEAD_RACE_NAME] == property_map[BOTTOM_RACE_NAME])
is_costume_set = (TOP_COSTUME_NAME in property_map) and (BOTTOM_COSTUME_NAME in property_map) and (property_map[TOP_COSTUME_NAME] == property_map[BOTTOM_COSTUME_NAME]) and property_map[TOP_COSTUME_NAME] != ""
is_human_race_set = is_race_set and property_map[BOTTOM_RACE_NAME] == HUMAN_RACE_NAME
is_non_human_race_set = is_race_set and property_map[BOTTOM_RACE_NAME] != HUMAN_RACE_NAME
is_set = is_race_set or is_costume_set
property_map[SET_NAME] = SET_MATCHED_NAME if is_set else SET_MISMATCHED_NAME
if is_set:
if is_costume_set:
property_map[SET_TYPE_NAME] = SET_TYPE_COSTUME_NAME
elif is_human_race_set:
property_map[SET_TYPE_NAME] = SET_TYPE_HUMAN_RACE_NAME
elif is_non_human_race_set:
property_map[SET_TYPE_NAME] = SET_TYPE_NON_HUMAN_RACE_NAME
else:
property_map[SET_TYPE_NAME] = ""
else:
property_map[SET_TYPE_NAME] = ""
for key in property_map.keys():
data["attributes"].append({
"trait_type": key,
"value": property_map[key]
})
data["description"] = "Chubbies are 10000 programmatically generated cute things living on the Ethereum Blockchain. Chubbies are cute and cuteness is justice, so Chubbies are JUSTICE."
data["external_url"] = "https://chubbies.io"
data["image"] = str(image_url) + str(index) + ".gif"
data["name"] = "Chubbies #" + str(index)
with open("./output/json/" + str(index), 'w') as f:
json.dump(data, f)
def main():
num_tokens = 10000 #input("Enter number of GIFS to generate: ")
tic = time.perf_counter()
num_buckets = 10
random.seed(0)
# Generate all properties
(property_maps, dedup_set) = gen_all_properties(int(num_tokens))
print(f"We have {len(property_maps)} Chubbies ready to be made.")
print("Distributing all Lab-grown Sets....")
gen_all_sets(property_maps, dedup_set, num_buckets)
print("Creating Gods....")
incubate_lab_grown_chubby_gods(property_maps, dedup_set)
print("Duplicate Sanity Check....")
duplicate_sanity_check(property_maps)
# Generate all gifs
gen_all_gifs(property_maps)
print_insights(property_maps, num_buckets)
toc = time.perf_counter()
print(f"Ran Chubbies GIF generation in {toc - tic:0.4f} seconds")
# Ask for Image URL to override the external
image_url = "https://gateway.pinata.cloud/ipfs/QmNdNTQVE4BUpERFwVTxX2RwZNbTCSwQr5pZ83EJJsBfWW/" #input("Enter Image URL Prefix: ")
output_json(property_maps, image_url)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment