Skip to content

Latest commit

 

History

History
987 lines (826 loc) · 30.2 KB

06-kittyverse.md

File metadata and controls

987 lines (826 loc) · 30.2 KB

Day 6 - kittyverse Gem - Inside the CryptoKitties 256-Bit Genome - Slice 'n' Dice Unique Bits 'n' Bytes - 48 Genes (12 Traits x 4 P, H1, H2, H3) - Build Your Own CryptoKitties Gene Reader - The Future is Meow

Written by {% avatar geraldb %} Gerald Bauer

A code monkey formerly at Big Korupto. Jobless no coiner having fun staying poor and wrong. Writing the Get Rich Quick "Business Blockchain" Bible - The Secrets of Free Easy Money.

  • Fabulous Persian Spock Gerbil Gold Cottoncandy - Extremely rare gen 5 swift virgin | 2.9 ETH
  • Rarity: 0.00264% Gen 5 JAGUAR FABULOUS GOLD DALI!! VIRGIN!
  • Rarity: 0.0015% Princess Bubblegum is now for sale! Gen 12 | Brisk | Virgin | Chartreux | Bubblegum | Otaku | Emeraldgreen | Saycheese | Mauveover | Spock - Starts ETH 20/Ends ETH 10
  • Gold ducat, Gen 5, Virgin, Swift. Very cheap
  • Cheap Gen 1 cute kittie with rare genes! Only 0.125 ETH
  • UNIQUE Virgin Peach Googly Gold Mauveover gen:2 cooldown:1 0.87992% RARE
  • SUPER CHEAP: Gerbil, Ragdoll, Scarlet, Chestnut, Cotton Candy!!! 0.02 ETH (~$14)
  • I'm giving away a Gen 1 FAST Gold for free...

-- CrypotKittiesMarket

At the heart of crypto collectibles (or digital assets) on the blockchain are unique bits & bytes. For CryptoKitties this is a 256-bit integer that holds the super "sekretoooo" genome / genes.

Let's use Kitty #1001 as an example and look at the "magic" 256-bit integer number:

# A 256-bit super "sekretoooo" integer genome

# hexadecimal (base 16)
genome = 0x00004a52931ce4085c14bdce014a0318846a0c808c60294a6314a34a1295b9ce
# decimal (base 10)
genome = 512955438081049600613224346938352058409509756310147795204209859701881294
# binary (base 2)
genome = 0b010010100101001010010011000111001110010000001000010111000001010010111101110011100000000101001010000000110001100010000100\
           011010100000110010000000100011000110000000101001010010100110001100010100101000110100101000010010100101011011100111001110

Let's convert from decimal (base 10) to hexadecimal (base 16 - 2^4) and binary (base 2 that is, 0 and 1):

p genome    # printed as decimal (base 10) by default
#=> 512955438081049600613224346938352058409509756310147795204209859701881294

p genome.to_s(16)
#=> "4a52931ce4085c14bdce014a0318846a0c808c60294a6314a34a1295b9ce"

p genome.to_s(2)
#=> "10010100101001010010011000111001110010000001000010111000001010010111101110011100000000101001010000000110001100010000100\
#     011010100000110010000000100011000110000000101001010010100110001100010100101000110100101000010010100101011011100111001110"

So what? Thanks to Kai Turner who first deciphered the CryptoKitties 256-bit genome in The CryptoKitties Genome Project: On Dominance, Inheritance and Mutation on January 2018 we know today that the genome breaks down into 5-bit chunks. And every 5-bit chunk is a gene. And four 5-bit chunks - known as the primary (p), hidden 1 (h1), hidden 2 (h2), and hidden 3 (h3) gene or dominant (d), 1st recessive (r1), 2nd recessive (r2), and 3rd recessive (r3) - get grouped into a trait (e.g. fur, pattern, eye color, eye shape, base color, highlight color, and so on) resulting in 12 trait groups of 4 (x 5-bit) genes (that is, 12 x 4 x 5-bit = 240 bits) with the remaining leading 16 bits "unused" and zeroed-out (e.g. 0x0000).

Let's break the genome into 5-bit chunks using Base32.encode from the kittyverse gem.

require 'kittyverse'

Base32.format = :electrologica   # use the Electrologica Alphabet / Variant


# hexadecimal (base 16)
genome = 0x00004a52931ce4085c14bdce014a0318846a0c808c60294a6314a34a1295b9ce  # kitty 1001

p Base32.encode( genome )
#=> "09-09-09-09-06-07-07-04-01-01-14-01-09-15-14-14-00-05-05-00-06-06-04-04-13-08-06-08-01-03-03-00-05-05-05-06-06-05-05-03-09-08-09-09-11-14-14-14"

Bingo! Using a genes / traits chart you can now decipher the genome.


CryptoKitties Genes / Traits Chart

Fur (0-3) • Pattern (4-7) • Eye Color (8-11) • Eye Shape (12-15) • Base Color (16-19) • Highlight Color (20-23) • Accent Color (24-27) • Wild (28-31) • Mouth (32-35) • Environment (36-39) • Secret Y Gene (40-43) • Purrstige (44-47)

Fur (FU) - Genes 0-3:

Kai Code Name Kai Code Name
1 FU00 savannah h FU16 norwegianforest I
2 FU01 selkirk i FU17 mekong I
3 FU02 chantilly j FU18 highlander I
4 FU03 birman k FU19 balinese I
5 FU04 koladiviya m FU20 lynx I
6 FU05 bobtail n FU21 mainecoon I
7 FU06 manul o FU22 laperm I
8 FU07 pixiebob p FU23 persian I
9 FU08 siberian q FU24 fox II
a FU09 cymric r FU25 kurilian II
b FU10 chartreux s FU26 toyger II
c FU11 himalayan t FU27 manx II
d FU12 munchkin u FU28 lykoi III
e FU13 sphynx v FU29 burmilla III
f FU14 ragamuffin w FU30 liger IIII
g FU15 ragdoll x FU31 ?

...

(Source: kittyverse/GENES.md)


Let's try Kitty #1001 as an example. Let's start deciphering from right-to-left ...06-05-05-03-09-08-09-09-11-14-14-14, that is, 14 maps to ragamuffin, 14 to ragamuffin, 14 to ragamuffin, 11 to himalayan, and so on:

Fur (FU) - Genes 0-3:

5-Bit Chunk Gene Trait
14 0 ragamuffin Primary
14 1 ragamuffin Hidden 1
14 2 ragamuffin Hidden 2
11 3 himalayan Hidden 3

Pattern (PA) - Genes 4-7:

5-Bit Chunk Gene Trait
09 4 luckystripe Primary
09 5 luckystripe Hidden 1
08 6 calicool Hidden 2
09 7 luckystripe Hidden 3

Eye Color (EC) - Genes 8-11:

5-Bit Chunk Gene Trait
03 8 mintgreen Primary
05 9 sizzurp Hidden 1
05 10 sizzurp Hidden 2
06 11 chestnut Hidden 3

and so on.

Let's try another kitty #1111:

genome = 0x000042d28390864842e7b9c900c6321086438c6098ca298c728867425cf6b1ac # kitty 1111

p Base32.encode( genome )
#=> "08-11-09-08-07-04-04-06-09-01-01-14-15-14-14-09-00-03-03-03-04-04-04-06-08-14-06-06-01-06-06-10-05-06-06-07-05-02-03-07-08-09-14-15-13-12-13-12"

Again using a genes / traits chart you can now decipher the genome. Let's start from right-to-left ...05-02-03-07-08-09-14-15-13-12-13-12, that is, 12 maps to munchkin, 13 to sphynx, and so on:

Fur (FU) - Genes 0-3:

5-Bit Chunk Gene Trait
12 0 munchkin Primary
13 1 sphynx Hidden 1
12 2 munchkin Hidden 2
13 3 sphynx Hidden 3

Pattern (PA) - Genes 4-7:

5-Bit Chunk Gene Trait
15 4 totesbasic Primary
14 5 totesbasic Hidden 1
09 6 luckystripe Hidden 2
08 7 calicool Hidden 3

Eye Color (EC) - Genes 8-11:

5-Bit Chunk Gene Trait
07 8 strawberry Primary
03 9 mintgreen Hidden 1
02 10 topaz Hidden 2
05 11 isotope Hidden 3

and so on.

What's Base32?

Encoding / decoding numbers in 5-bit chunks is called base 32 because 2^5 (=2 * 2 * 2 * 2 * 2) results in 32 values. Using the Electrologica notation / alphabet (00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31) the conversion chart reads:

Base32 Binary Num Base32 Binary Num Base32 Binary Num Base32 Binary Num
00 00000 0 08 01000 8 16 10000 16 24 11000 24
01 00001 1 09 01001 9 17 10001 17 25 11001 25
02 00010 2 10 01010 10 18 10010 18 26 11010 26
03 00011 3 11 01011 11 19 10011 19 27 11011 27
04 00100 4 12 01100 12 20 10100 20 28 11100 28
05 00101 5 13 01101 13 21 10101 21 29 11101 29
06 00110 6 14 01110 14 22 10110 22 30 11110 30
07 00111 7 15 01111 15 23 10111 23 31 11111 31

What About Kai Notation / Alphabet?

The Kai (Base 32) notation / alphabet is named in honor of Kai Turner who first deciphered the CryptoKitties 256-bit genome in 5-bit chunks. The Kai notation / alphabet follows base56 and uses (123456789abcdefghijkmnopqrstuvwx). The conversion chart reads:

Kai Binary Num Kai Binary Num Kai Binary Num Kai Binary Num
1 00000 0 9 01000 8 h 10000 16 q 11000 24
2 00001 1 a 01001 9 i 10001 17 r 11001 25
3 00010 2 b 01010 10 j 10010 18 s 11010 26
4 00011 3 c 01011 11 k 10011 19 t 11011 27
5 00100 4 d 01100 12 m 10100 20 u 11100 28
6 00101 5 e 01101 13 n 10101 21 v 11101 29
7 00110 6 f 01110 14 o 10110 22 w 11110 30
8 00111 7 g 01111 15 p 10111 23 x 11111 31

Note: - the digit-0 and the letter-l are NOT used in the kai alphabet / notation.

Let's convert the example kitty genomes to Kai notation:

require 'kittyverse'

Base32.format = :kai   # use the Kai Alphabet / Variant


# hexadecimal (base 16)
genome = 0x00004a52931ce4085c14bdce014a0318846a0c808c60294a6314a34a1295b9ce  # kitty 1001

p Base32.encode( genome )
#=> "aaaa788522f2agff16617755e979244166677664a9aacfff"

genome = 0x000042d28390864842e7b9c900c6321086438c6098ca298c728867425cf6b1ac # kitty 1111

p Base32.encode( genome )
#=> "9ca98557a22fgffa144455579f77277b677863489afgeded"

Tip: Use the Base32.fmt helper to pretty print / format the encoded string into a group of four (genes). Example:

# hexadecimal (base 16)
genome = 0x00004a52931ce4085c14bdce014a0318846a0c808c60294a6314a34a1295b9ce  # kitty 1001

p Base32.fmt( Base32.encode( genome ))
#=> "aaaa 7885 22f2 agff 1661 7755 e979 2441 6667 7664 a9aa cfff"

genome = 0x000042d28390864842e7b9c900c6321086438c6098ca298c728867425cf6b1ac # kitty 1111

p Base32.fmt( Base32.encode( genome ))
#=> "9ca9 8557 a22f gffa 1444 5557 9f77 277b 6778 6348 9afg eded"
p Base32.fmt( genome )   # or use the "all-in-one" shortcut
#=> "9ca9 8557 a22f gffa 1444 5557 9f77 277b 6778 6348 9afg eded"

Build Your Own CryptoKitties Gene Reader

Let's code a gene reader that deciphers the genome. Let's automate the lookup of the 5-bit chunks mapping to traits.

Let's again (re)use the kittyverse gem that includes an up-to-date list of all traits. For example, try:

require 'kittyverse'

pp TRAITS     ## pretty print (pp) TRAITS, that is, list of all traits

Resulting in:

{:body=>
  {:genes=>"0-3",
   :name=>"Fur",
   :code=>"FU",
   :kai=>
    {"1"=>"savannah",
     "2"=>"selkirk",
     "3"=>"chantilly",
     "4"=>"birman",
     "5"=>"koladiviya",
     "6"=>"bobtail",
     "7"=>"manul",
     "8"=>"pixiebob",
     "9"=>"siberian",
     "a"=>"cymric",
     "b"=>"chartreux",
     "c"=>"himalayan",
     "d"=>"munchkin",
     "e"=>"sphynx",
     "f"=>"ragamuffin",
     "g"=>"ragdoll",
     "h"=>"norwegianforest",
     "i"=>"mekong",
     "j"=>"highlander",
     "k"=>"balinese",
     "m"=>"lynx",
     "n"=>"mainecoon",
     "o"=>"laperm",
     "p"=>"persian",
     "q"=>"fox",
     "r"=>"kurilian",
     "s"=>"toyger",
     "t"=>"manx",
     "u"=>"lykoi",
     "v"=>"burmilla",
     "w"=>"liger",
     "x"=>""}},
 :pattern=>
  {:genes=>"4-7",
   :name=>"Pattern",
   :code=>"PA",
   :kai=>
    {"1"=>"vigilante",
     "2"=>"tiger",
     "3"=>"rascal",
     "4"=>"ganado",
     "5"=>"leopard",
     "6"=>"camo",
     "7"=>"rorschach",
     "8"=>"spangled",
     "9"=>"calicool",
     "a"=>"luckystripe",
     "b"=>"amur",
     "c"=>"jaguar",
     "d"=>"spock",
     "e"=>"mittens",
     "f"=>"totesbasic",
     "g"=>"totesbasic",
     "h"=>"splat",
     "i"=>"thunderstruck",
     "j"=>"dippedcone",
     "k"=>"highsociety",
     "m"=>"tigerpunk",
     "n"=>"henna",
     "o"=>"arcreactor",
     "p"=>"totesbasic",
     "q"=>"scorpius",
     "r"=>"razzledazzle",
     "s"=>"hotrod",
     "t"=>"allyouneed",
     "u"=>"avatar",
     "v"=>"gyre",
     "w"=>"moonrise",
     "x"=>""}},
 :coloreyes=>
  {:genes=>"8-11",
   :name=>"Eye Color",
   :code=>"EC",
   :kai=>
    {"1"=>"thundergrey",
     "2"=>"gold",
     "3"=>"topaz",
     "4"=>"mintgreen",
     "5"=>"isotope",
     "6"=>"sizzurp",
     "7"=>"chestnut",
     "8"=>"strawberry",
     "9"=>"sapphire",
     "a"=>"forgetmenot",
     "b"=>"dahlia",
     "c"=>"coralsunrise",
     "d"=>"olive",
     "e"=>"doridnudibranch",
     "f"=>"parakeet",
     "g"=>"cyan",
     "h"=>"pumpkin",
     "i"=>"limegreen",
     "j"=>"bridesmaid",
     "k"=>"bubblegum",
     "m"=>"twilightsparkle",
     "n"=>"palejade",
     "o"=>"pinefresh",
     "p"=>"eclipse",
     "q"=>"babypuke",
     "r"=>"downbythebay",
     "s"=>"autumnmoon",
     "t"=>"oasis",
     "u"=>"gemini",
     "v"=>"dioscuri",
     "w"=>"kaleidoscope",
     "x"=>""}},
 :eyes=>
  {:genes=>"12-15",
   :name=>"Eye Shape",
   :code=>"ES",
   :kai=>
    {"1"=>"swarley",
     "2"=>"wonky",
     "3"=>"serpent",
     "4"=>"googly",
     "5"=>"otaku",
     "6"=>"simple",
     "7"=>"crazy",
     "8"=>"thicccbrowz",
     "9"=>"caffeine",
     "a"=>"wowza",
     "b"=>"baddate",
     "c"=>"asif",
     "d"=>"chronic",
     "e"=>"slyboots",
     "f"=>"wiley",
     "g"=>"stunned",
     "h"=>"chameleon",
     "i"=>"alien",
     "j"=>"fabulous",
     "k"=>"raisedbrow",
     "m"=>"tendertears",
     "n"=>"hacker",
     "o"=>"sass",
     "p"=>"sweetmeloncakes",
     "q"=>"oceanid",
     "r"=>"wingtips",
     "s"=>"firedup",
     "t"=>"buzzed",
     "u"=>"bornwithit",
     "v"=>"candyshoppe",
     "w"=>"drama",
     "x"=>""}},
 :color1=>
  {:genes=>"16-19",
   :name=>"Base Color",
   :code=>"BC",
   :kai=>
    {"1"=>"shadowgrey",
     "2"=>"salmon",
     "3"=>"meowgarine",
     "4"=>"orangesoda",
     "5"=>"cottoncandy",
     "6"=>"mauveover",
     "7"=>"aquamarine",
     "8"=>"nachocheez",
     "9"=>"harbourfog",
     "a"=>"cinderella",
     "b"=>"greymatter",
     "c"=>"tundra",
     "d"=>"brownies",
     "e"=>"dragonfruit",
     "f"=>"hintomint",
     "g"=>"bananacream",
     "h"=>"cloudwhite",
     "i"=>"cornflower",
     "j"=>"oldlace",
     "k"=>"koala",
     "m"=>"lavender",
     "n"=>"glacier",
     "o"=>"redvelvet",
     "p"=>"verdigris",
     "q"=>"icicle",
     "r"=>"onyx",
     "s"=>"hyacinth",
     "t"=>"martian",
     "u"=>"hotcocoa",
     "v"=>"shamrock",
     "w"=>"firstblush",
     "x"=>""}},
 :color2=>
  {:genes=>"20-23",
   :name=>"Highlight Color",
   :code=>"HC",
   :kai=>
    {"1"=>"cyborg",
     "2"=>"springcrocus",
     "3"=>"egyptiankohl",
     "4"=>"poisonberry",
     "5"=>"lilac",
     "6"=>"apricot",
     "7"=>"royalpurple",
     "8"=>"padparadscha",
     "9"=>"swampgreen",
     "a"=>"violet",
     "b"=>"scarlet",
     "c"=>"barkbrown",
     "d"=>"coffee",
     "e"=>"lemonade",
     "f"=>"chocolate",
     "g"=>"butterscotch",
     "h"=>"ooze",
     "i"=>"safetyvest",
     "j"=>"turtleback",
     "k"=>"rosequartz",
     "m"=>"wolfgrey",
     "n"=>"cerulian",
     "o"=>"skyblue",
     "p"=>"garnet",
     "q"=>"peppermint",
     "r"=>"universe",
     "s"=>"royalblue",
     "t"=>"mertail",
     "u"=>"inflatablepool",
     "v"=>"pearl",
     "w"=>"prairierose",
     "x"=>""}},
 :color3=>
  {:genes=>"24-27",
   :name=>"Accent Color",
   :code=>"AC",
   :kai=>
    {"1"=>"belleblue",
     "2"=>"sandalwood",
     "3"=>"peach",
     "4"=>"icy",
     "5"=>"granitegrey",
     "6"=>"cashewmilk",
     "7"=>"kittencream",
     "8"=>"emeraldgreen",
     "9"=>"kalahari",
     "a"=>"shale",
     "b"=>"purplehaze",
     "c"=>"hanauma",
     "d"=>"azaleablush",
     "e"=>"missmuffett",
     "f"=>"morningglory",
     "g"=>"frosting",
     "h"=>"daffodil",
     "i"=>"flamingo",
     "j"=>"buttercup",
     "k"=>"bloodred",
     "m"=>"atlantis",
     "n"=>"summerbonnet",
     "o"=>"periwinkle",
     "p"=>"patrickstarfish",
     "q"=>"seafoam",
     "r"=>"cobalt",
     "s"=>"mallowflower",
     "t"=>"mintmacaron",
     "u"=>"sully",
     "v"=>"fallspice",
     "w"=>"dreamboat",
     "x"=>""}},
 :wild=>
  {:genes=>"28-31",
   :name=>"Wild",
   :code=>"WE",
   :kai=>
    {"h"=>"littlefoot",
     "i"=>"elk",
     "j"=>"ducky",
     "k"=>"trioculus",
     "m"=>"daemonwings",
     "n"=>"featherbrain",
     "o"=>"flapflap",
     "p"=>"daemonhorns",
     "q"=>"dragontail",
     "r"=>"aflutter",
     "s"=>"foghornpawhorn",
     "t"=>"unicorn",
     "u"=>"dragonwings",
     "v"=>"alicorn",
     "w"=>"wyrm",
     "x"=>""}},
 :mouth=>
  {:genes=>"32-35",
   :name=>"Mouth",
   :code=>"MO",
   :kai=>
    {"1"=>"whixtensions",
     "2"=>"wasntme",
     "3"=>"wuvme",
     "4"=>"gerbil",
     "5"=>"confuzzled",
     "6"=>"impish",
     "7"=>"belch",
     "8"=>"rollercoaster",
     "9"=>"beard",
     "a"=>"pouty",
     "b"=>"saycheese",
     "c"=>"grim",
     "d"=>"fangtastic",
     "e"=>"moue",
     "f"=>"happygokitty",
     "g"=>"soserious",
     "h"=>"cheeky",
     "i"=>"starstruck",
     "j"=>"samwise",
     "k"=>"ruhroh",
     "m"=>"dali",
     "n"=>"grimace",
     "o"=>"majestic",
     "p"=>"tongue",
     "q"=>"yokel",
     "r"=>"topoftheworld",
     "s"=>"neckbeard",
     "t"=>"satiated",
     "u"=>"walrus",
     "v"=>"struck",
     "w"=>"delite",
     "x"=>""}},
 :environment=>
  {:genes=>"36-39",
   :name=>"Environment",
   :code=>"EN",
   :kai=>
    {"h"=>"salty",
     "i"=>"dune",
     "j"=>"juju",
     "k"=>"tinybox",
     "m"=>"myparade",
     "n"=>"finalfrontier",
     "o"=>"metime",
     "p"=>"drift",
     "q"=>"secretgarden",
     "r"=>"frozen",
     "s"=>"roadtogold",
     "t"=>"jacked",
     "u"=>"floorislava",
     "v"=>"prism",
     "w"=>"junglebook",
     "x"=>""}},
 :secret=>{:genes=>"40-43", :name=>"Secret Y Gene", :code=>"SE", :kai=>{}},
 :prestige=>{:genes=>"44-47", :name=>"Purrstige", :code=>"PU", :kai=>{}}}

That's quite a list that you do not have to type in. Let's use the new TRAITS hash to "automagically" decipher the genome.

# hexadecimal (base 16)
genome = 0x00004a52931ce4085c14bdce014a0318846a0c808c60294a6314a34a1295b9ce  # kitty 1001

genes_kai = Base32.encode( genome )
p genes_kai
#=> "aaaa788522f2agff16617755e979244166677664a9aacfff"
genes_kai = genes_kai.reverse    # for easy array access reverse string
p genes_kai
#=> "fffcaa9a466776661442979e55771661ffga2f225887aaaa"

puts "Fur (FU) - Genes 0-3:"
puts " 0 | #{TRAITS[:body][:kai][genes_kai[0]]}"
puts " 1 | #{TRAITS[:body][:kai][genes_kai[1]]}"
puts " 2 | #{TRAITS[:body][:kai][genes_kai[2]]}"
puts " 3 | #{TRAITS[:body][:kai][genes_kai[3]]}"
puts
puts "Pattern (PA) - Genes 4-7:"
puts " 4 | #{TRAITS[:pattern][:kai][genes_kai[4]]}"
puts " 5 | #{TRAITS[:pattern][:kai][genes_kai[5]]}"
puts " 6 | #{TRAITS[:pattern][:kai][genes_kai[6]]}"
puts " 7 | #{TRAITS[:pattern][:kai][genes_kai[7]]}"
puts
puts "Eye Color (EC) - Genes 8-11:"
puts " 8 | #{TRAITS[:coloreyes][:kai][genes_kai[8]]}"
puts " 9 | #{TRAITS[:coloreyes][:kai][genes_kai[9]]}"
puts "10 | #{TRAITS[:coloreyes][:kai][genes_kai[10]]}"
puts "11 | #{TRAITS[:coloreyes][:kai][genes_kai[11]]}"
puts
puts "Eye Shape (ES) - Genes 12-15:"
puts "12 | #{TRAITS[:eyes][:kai][genes_kai[12]]}"
puts "13 | #{TRAITS[:eyes][:kai][genes_kai[13]]}"
puts "14 | #{TRAITS[:eyes][:kai][genes_kai[14]]}"
puts "15 | #{TRAITS[:eyes][:kai][genes_kai[15]]}"
puts
puts "Base Color (BC) - Genes 16-19:"
puts "16 | #{TRAITS[:color1][:kai][genes_kai[16]]}"
puts "17 | #{TRAITS[:color1][:kai][genes_kai[17]]}"
puts "18 | #{TRAITS[:color1][:kai][genes_kai[18]]}"
puts "19 | #{TRAITS[:color1][:kai][genes_kai[19]]}"
puts
puts "Highlight Color (HC) - Genes 20-23:"
puts "20 | #{TRAITS[:color2][:kai][genes_kai[20]]}"
puts "21 | #{TRAITS[:color2][:kai][genes_kai[21]]}"
puts "22 | #{TRAITS[:color2][:kai][genes_kai[22]]}"
puts "23 | #{TRAITS[:color2][:kai][genes_kai[23]]}"
puts
puts "Accent Color (AC) - Genes 24-27:"
puts "24 | #{TRAITS[:color3][:kai][genes_kai[24]]}"
puts "25 | #{TRAITS[:color3][:kai][genes_kai[25]]}"
puts "26 | #{TRAITS[:color3][:kai][genes_kai[26]]}"
puts "27 | #{TRAITS[:color3][:kai][genes_kai[27]]}"
puts
puts "Mouth (MO) - Genes 32-35:"
puts "32 | #{TRAITS[:mouth][:kai][genes_kai[32]]}"
puts "33 | #{TRAITS[:mouth][:kai][genes_kai[33]]}"
puts "34 | #{TRAITS[:mouth][:kai][genes_kai[34]]}"
puts "35 | #{TRAITS[:mouth][:kai][genes_kai[35]]}"

prints

Fur (FU) - Genes 0-3:
 0 | ragamuffin
 1 | ragamuffin
 2 | ragamuffin
 3 | himalayan

Pattern (PA) - Genes 4-7:
 4 | luckystripe
 5 | luckystripe
 6 | calicool
 7 | luckystripe

Eye Color (EC) - Genes 8-11:
 8 | mintgreen
 9 | sizzurp
10 | sizzurp
11 | chestnut

Eye Shape (ES) - Genes 12-15:
12 | crazy
13 | simple
14 | simple
15 | simple

Base Color (BC) - Genes 16-19:
16 | shadowgrey
17 | orangesoda
18 | orangesoda
19 | salmon

Highlight Color (HC) - Genes 20-23:
20 | swampgreen
21 | royalpurple
22 | swampgreen
23 | lemonade

Accent Color (AC) - Genes 24-27:
24 | granitegrey
25 | granitegrey
26 | kittencream
27 | kittencream

Mouth (MO) - Genes 32-35:
32 | happygokitty
33 | happygokitty
34 | soserious
35 | pouty

Note: Every trait has four genes (primary, hidden 1, hidden 2, and hidden 3). The primary gene is the "cattribute", that is, the visible trait listed on the official kitty profile page. Let's (double) check for the Kitty #1001:

  • Fur: ragamuffin
  • Pattern: luckystripe
  • Eye Color: mintgreen
  • Eye Shape: crazy
  • Base Color: shadowgrey
  • Highlight Color: swampgreen
  • Accent Color: granitegrey
  • Mouth: happygokitty

And the official page:

(Source: cryptokitties.co/kitty/1001)

Bingo! The cattributes match up.

For easy (re)use lets put together a more "generic" print_genes method:

print_genes( 0x00004a52931ce4085c14bdce014a0318846a0c808c60294a6314a34a1295b9ce ) # kitty 1001
print_genes( 0x000042d28390864842e7b9c900c6321086438c6098ca298c728867425cf6b1ac ) # kitty 1111

And the code:

def print_genes( genome )

  genes_kai = Base32.encode( genome )
  genes_kai = genes_kai.reverse    # for easy array access reverse string

  TRAITS.each_with_index do |(trait_key, trait_hash),i|

     # note: skip wild, environment, secret, prestige for now
     next if [:wild,   :environment,
              :secret, :prestige].include? trait_key

     offset = i*4
     puts "#{trait_hash[:name]} (#{trait_hash[:code]}) - Genes #{trait_hash[:genes]}:"
     puts "#{'%2d' % (0+offset)} | #{trait_hash[:kai][genes_kai[0+offset]]}"
     puts "#{'%2d' % (1+offset)} | #{trait_hash[:kai][genes_kai[1+offset]]}"
     puts "#{'%2d' % (2+offset)} | #{trait_hash[:kai][genes_kai[2+offset]]}"
     puts "#{'%2d' % (3+offset)} | #{trait_hash[:kai][genes_kai[3+offset]]}"
     puts
  end
end

Resulting in

Fur (FU) - Genes 0-3:
 0 | ragamuffin
 1 | ragamuffin
 2 | ragamuffin
 3 | himalayan

Pattern (PA) - Genes 4-7:
 4 | luckystripe
 5 | luckystripe
 6 | calicool
 7 | luckystripe

Eye Color (EC) - Genes 8-11:
 8 | mintgreen
 9 | sizzurp
10 | sizzurp
11 | chestnut

Eye Shape (ES) - Genes 12-15:
12 | crazy
13 | simple
14 | simple
15 | simple

Base Color (BC) - Genes 16-19:
16 | shadowgrey
17 | orangesoda
18 | orangesoda
19 | salmon

Highlight Color (HC) - Genes 20-23:
20 | swampgreen
21 | royalpurple
22 | swampgreen
23 | lemonade

Accent Color (AC) - Genes 24-27:
24 | granitegrey
25 | granitegrey
26 | kittencream
27 | kittencream

Mouth (MO) - Genes 32-35:
32 | happygokitty
33 | happygokitty
34 | soserious
35 | pouty

See a difference? There's no difference :-).

Note: The kittyverse gem has a built-in gene reader and pretty printer. Let's try it:

genome = Genome.new( 0x00004a52931ce4085c14bdce014a0318846a0c808c60294a6314a34a1295b9ce )
puts genome.build_tables    # outputs tables in text with markdown formatting

Resulting in:


Fur (FU) - Genes 0-3:

Gene Binary Kai Trait
0 01110 f ragamuffin p
1 01110 f ragamuffin h1
2 01110 f ragamuffin h2
3 01011 c himalayan h3

p = primary, h1 = hidden 1, h2 = hidden 2, h3 = hidden 3

Pattern (PA) - Genes 4-7:

Gene Binary Kai Trait
4 01001 a luckystripe p
5 01001 a luckystripe h1
6 01000 9 calicool h2
7 01001 a luckystripe h3

Eye Color (EC) - Genes 8-11:

Gene Binary Kai Trait
8 00011 4 mintgreen p
9 00101 6 sizzurp h1
10 00101 6 sizzurp h2
11 00110 7 chestnut h3

Eye Shape (ES) - Genes 12-15:

Gene Binary Kai Trait
12 00110 7 crazy p
13 00101 6 simple h1
14 00101 6 simple h2
15 00101 6 simple h3

Base Color (BC) - Genes 16-19:

Gene Binary Kai Trait
16 00000 1 shadowgrey p
17 00011 4 orangesoda h1
18 00011 4 orangesoda h2
19 00001 2 salmon h3

Highlight Color (HC) - Genes 20-23:

Gene Binary Kai Trait
20 01000 9 swampgreen p
21 00110 7 royalpurple h1
22 01000 9 swampgreen h2
23 01101 e lemonade h3

Accent Color (AC) - Genes 24-27:

Gene Binary Kai Trait
24 00100 5 granitegrey p
25 00100 5 granitegrey h1
26 00110 7 kittencream h2
27 00110 7 kittencream h3

Mouth (MO) - Genes 32-35:

Gene Binary Kai Trait
32 01110 f happygokitty p
33 01110 f happygokitty h1
34 01111 g soserious h2
35 01001 a pouty h3

Find Out More

References