├── .gitignore ├── README.md ├── generate_hashes.js ├── generate_images.js ├── generate_metadata.js ├── generate_traits.js ├── package.json ├── tnames.dat ├── traits ├── trait1 │ ├── brown.png │ ├── burgandy.png │ ├── green.png │ ├── grey.png │ ├── lime.png │ ├── orange.png │ ├── pink.png │ ├── purple.png │ ├── steel.png │ ├── turquoise.png │ └── yellow.png ├── trait2 │ ├── circle.png │ ├── decagon.png │ ├── flag.png │ ├── heptagon.png │ ├── hexagon.png │ ├── nonagon.png │ ├── octagon.png │ ├── square.png │ └── triangle.png └── trait3 │ ├── joy.png │ ├── mocking.png │ ├── sad.png │ ├── shrug.png │ └── smile.png └── weights.dat /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package-lock.json 3 | ./images 4 | ./metadata 5 | imagesHashes.csv 6 | imageTraits.csv 7 | rarity.csv -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NFT Generative Art JS 2 | 3 | This is a set of javascript/node scripts for creating generative art. 4 | 5 | Sample traits, weights, and layer images are already provided. 6 | 7 | #### To run with the existing sample assets: 8 | - First, make sure you have node installed, then run `npm i` or `yarn install` to install the necessary node modules. 9 | - Second, update the `collectionNum` variable in the generate_traits.js script to the number of images you want to create. 10 | - Note that the number of images has to be equal to or less than the total number of unique image combinations. 11 | - Third, run the generate_traits.js script with `npm run generate:traits` or `yarn generate:traits`. 12 | - Fourth, run the generate_images.js script with `npm run generate:images` or `yarn generate:images`. 13 | - Fifth, run the generate_hashes.js script with `npm run generate:hashes` or `yarn generate:hashes`. 14 | - Sixth, update the following variables in the generate_metadata.js script to align with your project: `metadataDescription`, `metadataName`, `metadataImageStorageHash`. 15 | - Seventh, run the generate_metadata.js.script with `npm run generate:metadata` or `yarn generate:metadata`. 16 | 17 | #### To run with your own assets: 18 | - Replace the existing traits folders with your art layers, with the bottom layer in folder `trait1`, next layer in folder `trait2` and so on. The image files should be in alphabetical order inside the folders. 19 | - Replace the trait names in the file `tnames.dat` with your trait names, starting with the bottom layer first. 20 | - Replace the trait weights in the file `weights.dat` with your trait weights, starting with the bottom layer and then aligning with the same order (alphabetical) as the images in their respective trait folders. 21 | - Then follow the same steps as above. 22 | 23 | ### Script descriptions 24 | 25 | |**generate_traits.js** | 26 | | :------------- | 27 | |*Inputs* | 28 | |tnames.dat - separate file that lists the name of each trait type | 29 | |weights.dat - separate file that lists the expected occurance of each trait within the overall collection | 30 | |collectionNum - variable of type number to set the number of collection items to generate | 31 | |attributeRules - optional and customizable logic to set rules for trait generation (e.g., trait x cannot appear with trait y) | 32 | |*Outputs* | 33 | |imageTraits.csv - csv file containing list of all collection items' traits. As a csv file, further analysis can be done directly in a terminal or in a more user friendly program like Excel, including modifying individual items directly | 34 | |rarity.csv - csv file that lists each individual trait and the percentage (rarity) of its occurance in the generated collection | 35 | 36 | |**generate_images.js**| 37 | | :------------- | 38 | |*Inputs*| 39 | |imageTraits.csv - file must exist, and is generated from generate_traits.js| 40 | |imgWidth - variable of type number to set the width of each image| 41 | |imgHeight - variable of type number to set the height of each image| 42 | |imageRules - optional and customizable logic to set rules for image generation (e.g., trait x always set as top layer)| 43 | |*Outputs*| 44 | |images folder - folder containing all generated collection images, with files named sequentially (e.g., 1.png, 2.png, ...)| 45 | 46 | |**generate_hashes.js**| 47 | | :------------- | 48 | |*Inputs*| 49 | |images folder and contained image files - must exist, and is generated from generate_images.js| 50 | |*Outputs*| 51 | |imageHashes.csv - csv file that lists the sha256 hash of each image and the 'provenance' hash of all image hashes| 52 | 53 | |**generate_metadata.js**| 54 | | :------------- | 55 | |*Inputs*| 56 | |imageTraits.csv - file must exist, and is generated from generate_traits.js| 57 | |metadataDescription - variable of type string to set the description for the metadata json files| 58 | |metadataName - variable of type string to set the name for the metadata json files| 59 | |metadataImageStorageHash - variable of type string to set the namebase IPFS folder hash for the metadata json files| 60 | |*Outputs*| 61 | |metadata folder - folder containing all generated json files for each image, with files named sequentially| -------------------------------------------------------------------------------- /generate_hashes.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs") 2 | const sha256 = require('js-sha256') 3 | const dir = './images' 4 | const hrstart = process.hrtime() 5 | 6 | /* 7 | * @dev generates a hash of each image and then a 'provenance' hash of all image hashes 8 | */ 9 | 10 | function run() { 11 | let files = fs.readdirSync(dir) 12 | imgNum = files.length 13 | 14 | if (files.length == 0) { 15 | throw new Error('No images. Run generate_images.js first.'); 16 | } 17 | 18 | let provenance = '' 19 | const header = 'Image #,Hash' + '\n' 20 | let csv = header 21 | for (let i = 1; i <= imgNum; i++) { 22 | const base64 = fs.readFileSync(`./images/${i}.png`, 'base64') 23 | const hash = sha256(JSON.stringify(base64)) 24 | csv += i + ',' + hash + '\n' 25 | provenance += hash 26 | } 27 | provenance = sha256(JSON.stringify(provenance)) 28 | csv += 'provenance' + ',' + provenance 29 | fs.writeFileSync('imageHashes.csv', csv) 30 | const hrend = process.hrtime(hrstart) 31 | console.info('Generated Hashes (imageHashes.csv). Execution time (hr): %ds %dms', hrend[0], hrend[1] / 1000000) 32 | } 33 | 34 | run() -------------------------------------------------------------------------------- /generate_images.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs") 2 | const { createCanvas, loadImage } = require('canvas') 3 | const { parse } = require('csv-parse') 4 | 5 | /* 6 | * @dev canvas configuration 7 | */ 8 | const imgWidth = 512 // Change this to desired width of your image 9 | const imgHeight = 512 // Change this to desired height of your image 10 | 11 | /* 12 | * @dev image rules to change things such as order of layers (e.g., ensure a certian trait is always on top) 13 | * example rule is commented out below 14 | * if no rules are needed, then comment out or remove if statement(s) 15 | */ 16 | const imageRules = (_imgAttributes) => { 17 | const attLength = _imgAttributes.length 18 | const newAttributes = [] 19 | for (i = 0; i < attLength; i++) { 20 | const miniArr = [i + 1] 21 | miniArr.push(_imgAttributes[i]) 22 | newAttributes.push(miniArr) 23 | } 24 | // if (_imgAttributes.includes('steel')) { 25 | // newAttributes.push(newAttributes.splice(_imgAttributes.indexOf('steel'), 1)[0]) 26 | // return newAttributes 27 | // } 28 | return newAttributes 29 | } 30 | 31 | const canvas = createCanvas(imgWidth, imgHeight) 32 | const ctx = canvas.getContext("2d") 33 | 34 | const getTraitNames = () => { 35 | return fs.readFileSync('./tnames.dat').toString().trim().split(/\s+/) 36 | } 37 | 38 | const generateImage = async (_traitNames, _nft) => { 39 | const arr = [] 40 | const imgNum = _nft[0] 41 | _nft.shift() 42 | const imgAttributes = imageRules(_nft) 43 | imgAttributes.forEach(async el => { 44 | const imgProm = new Promise(async (resolve) => { 45 | const image = await loadImage(`./traits/trait${el[0]}/${el[1]}.png`); 46 | resolve(image); 47 | }) 48 | arr.push(imgProm) 49 | }) 50 | await Promise.all(arr).then((renderObjectArray) => { 51 | ctx.clearRect(0, 0, imgWidth, imgHeight); 52 | renderObjectArray.forEach((image) => { 53 | ctx.drawImage( 54 | image, 55 | 0, 56 | 0, 57 | imgWidth, 58 | imgHeight 59 | ); 60 | }); 61 | } 62 | ) 63 | fs.writeFileSync( 64 | `./images/${imgNum}.png`, 65 | canvas.toBuffer("image/png") 66 | ); 67 | } 68 | 69 | const run = async () => { 70 | const hrstart = process.hrtime() 71 | const traitNames = getTraitNames() 72 | 73 | const dirExists = fs.statSync('./images', { throwIfNoEntry: false }) 74 | 75 | if (dirExists) { 76 | fs.rmdirSync('./images', { recursive: true }); 77 | } 78 | fs.mkdirSync('./images') 79 | 80 | fs.readFile('./imageTraits.csv', async function (err, fileData) { 81 | if (err && err.errno == -4058) { 82 | throw new Error('No traits. Run generate_traits.js first.'); 83 | } else if (err) console.log(err) 84 | parse(fileData, { columns: false, trim: true }, async function (err, rows) { 85 | if (err) console.log(err); 86 | const fileLen = rows.length 87 | for (let i = 0; i < fileLen; i++) { 88 | if (i == 0) { 89 | continue 90 | } 91 | ; 92 | const nft = rows[i] 93 | await generateImage(traitNames, nft) 94 | } 95 | const hrend = process.hrtime(hrstart) 96 | console.info('Generated Images (./images). Execution time (hr): %ds %dms', hrend[0], hrend[1] / 1000000) 97 | }) 98 | }) 99 | } 100 | 101 | run() 102 | -------------------------------------------------------------------------------- /generate_metadata.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs") 2 | const hrstart = process.hrtime() 3 | 4 | /* 5 | * @dev configuration for the metadata json file 6 | * change below variables to fit your project 7 | * the below code assumes IPFS storage with a file structure of a folder containing images in sequential order 8 | * if using your own hosting service or different file structure, then just update the metadataObj accordingly 9 | */ 10 | const metadataDescription = 'This is a sample project description' 11 | const metadataName = 'Sample Project' 12 | const metadataImageStorageHash = 'Q1234' 13 | 14 | let attData 15 | try { 16 | attData = fs.readFileSync('imageTraits.csv', 'utf8') 17 | } catch (err) { 18 | if (err && err.errno == -4058) { 19 | throw new Error('No traits. Run generate_traits.js first.'); 20 | } else if (err) console.log(err) 21 | } 22 | 23 | const traitNames = fs.readFileSync('tnames.dat').toString().trim().split(/\s+/) 24 | 25 | function run() { 26 | 27 | const dirExists = fs.statSync('./metadata', { throwIfNoEntry: false }) 28 | 29 | if (dirExists) { 30 | fs.rmdirSync('./metadata', { recursive: true }); 31 | } 32 | fs.mkdirSync('./metadata') 33 | 34 | const csvData = [] 35 | let lbreak = attData.split("\n") 36 | lbreak.forEach(res => { 37 | csvData.push(res.split(",")) 38 | }) 39 | let metadataObj = {} 40 | for (let i = 0; i < csvData.length - 1; i++) { 41 | metadataObj.description = metadataDescription 42 | metadataObj.name = metadataName + ' #' + (i + 1) 43 | metadataObj.image = 'ipfs://' + metadataImageStorageHash + '/' + (i + 1) 44 | const atts = [] 45 | for (let b = 0; b < traitNames.length; b++) { 46 | const something = { 47 | trait_type: traitNames[b], 48 | value: csvData[i + 1][b + 1] 49 | } 50 | atts.push(something) 51 | } 52 | metadataObj.attributes = atts 53 | metadataJSON = JSON.stringify(metadataObj) 54 | fs.writeFileSync(`metadata/${i + 1}`, metadataJSON) 55 | } 56 | const hrend = process.hrtime(hrstart) 57 | console.info('Generated MetaData JSON Files (./metadata). Execution time (hr): %ds %dms', hrend[0], hrend[1] / 1000000) 58 | } 59 | 60 | run() -------------------------------------------------------------------------------- /generate_traits.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs") 2 | const weighted = require('weighted') 3 | const sha256 = require('js-sha256') 4 | 5 | /* 6 | * @dev number of items in the collection 7 | */ 8 | const collectionNum = 123 // Change this to your desired collection number 9 | 10 | /* 11 | * @dev attribute rules to prevent certian conmbinations from existing 12 | * example rule is commented out below 13 | * caution - the more rules added may impact the final rarity score compared to the predefined weights 14 | * if no rules are needed, then comment out or remove if statement(s) and only return true 15 | */ 16 | const attributeRules = (_nft) => { 17 | // if (_nft.Background == 'yellow' && (_nft.Shape == 'triangle' || _nft.Shape == 'square')) { 18 | // return false 19 | // } 20 | return true 21 | } 22 | 23 | const getTraitNames = () => { 24 | return fs.readFileSync('./tnames.dat').toString().trim().split(/\s+/) 25 | } 26 | 27 | const getWeights = () => { 28 | return fs.readFileSync('./weights.dat').toString().split(/\r\n/) 29 | } 30 | 31 | const getAttributes = (_traitsAndWeights) => { 32 | const attributes = {} 33 | for (let i = 0; i < _traitsAndWeights.length; i++) { 34 | generatedAttribute = weighted.select(_traitsAndWeights[i][1]) 35 | attributes[_traitsAndWeights[i][0]] = generatedAttribute 36 | } 37 | return attributes 38 | } 39 | 40 | const generateTraitTable = (_traitNames, _nftAttributes) => { 41 | let header = 'Image #,' + _traitNames.join() + '\n' 42 | let csv = header 43 | let imageCounter = 1 44 | _nftAttributes.forEach(element => { 45 | csv += imageCounter + ',' + Object.values(element).join() + '\n' 46 | ++imageCounter 47 | }) 48 | csv = csv.trim() 49 | fs.writeFileSync('./imageTraits.csv', csv) 50 | } 51 | 52 | const generateRarityTable = (_traitNames, _nftAttributes, _traitsAndWeights) => { 53 | let header = 'Trait,Rarity' + '\n' 54 | let csv = header 55 | 56 | for (let i = 0; i < _traitNames.length; i++) { 57 | csv += _traitNames[i] + '\n' 58 | const traits = Object.keys(_traitsAndWeights[i][1]) 59 | 60 | traits.forEach(element => { 61 | let occurance = 0 62 | _nftAttributes.forEach(el => { 63 | let trait = _traitNames[i] 64 | if (el[trait] == element) { 65 | occurance = occurance + 1 66 | } 67 | }) 68 | const rarity = occurance / collectionNum 69 | csv += element + ',' + rarity.toFixed(5) + '\n' 70 | } 71 | ) 72 | } 73 | csv = csv.trim() 74 | fs.writeFileSync('./rarity.csv', csv) 75 | } 76 | 77 | const run = async () => { 78 | const hrstart = process.hrtime() 79 | const traitNames = getTraitNames() 80 | const weights = getWeights() 81 | const traitsPositions = [] 82 | 83 | let combinations 84 | 85 | fs.readdir(`./traits`, (err, traitGroups) => { 86 | if (err) console.log(err) 87 | comboArr = [] 88 | for (let i = 1; i <= traitGroups.length; i++) { 89 | comboArr.push(fs.readdirSync(`./traits/trait${i}`).length) 90 | } 91 | combinations = comboArr[0] 92 | for (let z = 1; z < comboArr.length; z++) { 93 | combinations = comboArr[z] * combinations 94 | } 95 | 96 | if (combinations < collectionNum) { 97 | console.log('NOT ENOUGH TRAITS TO FULFILL COLLECTION NUMBER') 98 | } else { 99 | 100 | for (let a = 0; a <= traitNames.length; a++) { 101 | for (let b = 0; b < weights.length; b++) { 102 | if (weights[b].match(`#Trait ${a}`)) { 103 | traitsPositions.push(b) 104 | } 105 | } 106 | } 107 | 108 | const traitsAndWeights = [] 109 | for (let c = 0; c < traitNames.length; c++) { 110 | traitsAndWeights.push([traitNames[c]]) 111 | const obj = {} 112 | traitsAndWeights[c].push(obj) 113 | const attributeFiles = fs.readdirSync(`./traits/trait${c + 1}`) 114 | 115 | for (let d = 0; d < attributeFiles.length; d++) { 116 | const attribute = attributeFiles[d].replace(/\.[^/.]+$/, "") 117 | const weight = weights[traitsPositions[c] + d + 1] 118 | obj[attribute] = parseFloat(weight) 119 | } 120 | } 121 | const nftAttributes = [] 122 | const nftHashes = [] 123 | let attempts = 0 124 | 125 | for (var e = collectionNum; e--;) { 126 | if (combinations < attempts) { 127 | console.log('NOT ENOUGH TRAITS TO FULFILL COLLECTION NUMBER') 128 | return 129 | } 130 | const nft = getAttributes(traitsAndWeights) 131 | const nftHash = sha256(JSON.stringify(nft)) 132 | if (nftHashes.includes(nftHash)) { e++; continue } 133 | const legal = attributeRules(nft) 134 | if (!legal) { 135 | attempts++ 136 | e++ 137 | continue 138 | } 139 | if (attempts > 0) attempts = 0 140 | nftHashes.push(nftHash) 141 | nftAttributes.push(nft) 142 | } 143 | 144 | generateTraitTable(traitNames, nftAttributes) 145 | generateRarityTable(traitNames, nftAttributes, traitsAndWeights) 146 | 147 | const hrend = process.hrtime(hrstart) 148 | console.info('Generated Image Trait Table (imageTraits.csv) and Rarity Table (rarity.csv). Execution time (hr): %ds %dms', hrend[0], hrend[1] / 1000000) 149 | } 150 | }) 151 | } 152 | 153 | run() 154 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nft-generative-art-js", 3 | "version": "1.0.1", 4 | "description": "Scripts to create everything needed for NFT generative art", 5 | "scripts": { 6 | "generate:traits": "node generate_traits.js", 7 | "generate:images": "node generate_images.js", 8 | "generate:hashes": "node generate_hashes.js", 9 | "generate:metadata": "node generate_metadata.js" 10 | }, 11 | "author": "Martin Sterlicchi", 12 | "license": "ISC", 13 | "dependencies": { 14 | "canvas": "^2.8.0", 15 | "csv-parse": "^5.0.4", 16 | "js-sha256": "^0.9.0", 17 | "sha256": "^0.2.0", 18 | "weighted": "^0.3.0" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tnames.dat: -------------------------------------------------------------------------------- 1 | Background 2 | Shape 3 | Emotion -------------------------------------------------------------------------------- /traits/trait1/brown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AboldUSER/nft_generative_art_js/72d2d63d12a04774e21630b05b24012718102c75/traits/trait1/brown.png -------------------------------------------------------------------------------- /traits/trait1/burgandy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AboldUSER/nft_generative_art_js/72d2d63d12a04774e21630b05b24012718102c75/traits/trait1/burgandy.png -------------------------------------------------------------------------------- /traits/trait1/green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AboldUSER/nft_generative_art_js/72d2d63d12a04774e21630b05b24012718102c75/traits/trait1/green.png -------------------------------------------------------------------------------- /traits/trait1/grey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AboldUSER/nft_generative_art_js/72d2d63d12a04774e21630b05b24012718102c75/traits/trait1/grey.png -------------------------------------------------------------------------------- /traits/trait1/lime.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AboldUSER/nft_generative_art_js/72d2d63d12a04774e21630b05b24012718102c75/traits/trait1/lime.png -------------------------------------------------------------------------------- /traits/trait1/orange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AboldUSER/nft_generative_art_js/72d2d63d12a04774e21630b05b24012718102c75/traits/trait1/orange.png -------------------------------------------------------------------------------- /traits/trait1/pink.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AboldUSER/nft_generative_art_js/72d2d63d12a04774e21630b05b24012718102c75/traits/trait1/pink.png -------------------------------------------------------------------------------- /traits/trait1/purple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AboldUSER/nft_generative_art_js/72d2d63d12a04774e21630b05b24012718102c75/traits/trait1/purple.png -------------------------------------------------------------------------------- /traits/trait1/steel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AboldUSER/nft_generative_art_js/72d2d63d12a04774e21630b05b24012718102c75/traits/trait1/steel.png -------------------------------------------------------------------------------- /traits/trait1/turquoise.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AboldUSER/nft_generative_art_js/72d2d63d12a04774e21630b05b24012718102c75/traits/trait1/turquoise.png -------------------------------------------------------------------------------- /traits/trait1/yellow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AboldUSER/nft_generative_art_js/72d2d63d12a04774e21630b05b24012718102c75/traits/trait1/yellow.png -------------------------------------------------------------------------------- /traits/trait2/circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AboldUSER/nft_generative_art_js/72d2d63d12a04774e21630b05b24012718102c75/traits/trait2/circle.png -------------------------------------------------------------------------------- /traits/trait2/decagon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AboldUSER/nft_generative_art_js/72d2d63d12a04774e21630b05b24012718102c75/traits/trait2/decagon.png -------------------------------------------------------------------------------- /traits/trait2/flag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AboldUSER/nft_generative_art_js/72d2d63d12a04774e21630b05b24012718102c75/traits/trait2/flag.png -------------------------------------------------------------------------------- /traits/trait2/heptagon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AboldUSER/nft_generative_art_js/72d2d63d12a04774e21630b05b24012718102c75/traits/trait2/heptagon.png -------------------------------------------------------------------------------- /traits/trait2/hexagon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AboldUSER/nft_generative_art_js/72d2d63d12a04774e21630b05b24012718102c75/traits/trait2/hexagon.png -------------------------------------------------------------------------------- /traits/trait2/nonagon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AboldUSER/nft_generative_art_js/72d2d63d12a04774e21630b05b24012718102c75/traits/trait2/nonagon.png -------------------------------------------------------------------------------- /traits/trait2/octagon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AboldUSER/nft_generative_art_js/72d2d63d12a04774e21630b05b24012718102c75/traits/trait2/octagon.png -------------------------------------------------------------------------------- /traits/trait2/square.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AboldUSER/nft_generative_art_js/72d2d63d12a04774e21630b05b24012718102c75/traits/trait2/square.png -------------------------------------------------------------------------------- /traits/trait2/triangle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AboldUSER/nft_generative_art_js/72d2d63d12a04774e21630b05b24012718102c75/traits/trait2/triangle.png -------------------------------------------------------------------------------- /traits/trait3/joy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AboldUSER/nft_generative_art_js/72d2d63d12a04774e21630b05b24012718102c75/traits/trait3/joy.png -------------------------------------------------------------------------------- /traits/trait3/mocking.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AboldUSER/nft_generative_art_js/72d2d63d12a04774e21630b05b24012718102c75/traits/trait3/mocking.png -------------------------------------------------------------------------------- /traits/trait3/sad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AboldUSER/nft_generative_art_js/72d2d63d12a04774e21630b05b24012718102c75/traits/trait3/sad.png -------------------------------------------------------------------------------- /traits/trait3/shrug.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AboldUSER/nft_generative_art_js/72d2d63d12a04774e21630b05b24012718102c75/traits/trait3/shrug.png -------------------------------------------------------------------------------- /traits/trait3/smile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AboldUSER/nft_generative_art_js/72d2d63d12a04774e21630b05b24012718102c75/traits/trait3/smile.png -------------------------------------------------------------------------------- /weights.dat: -------------------------------------------------------------------------------- 1 | #Weights for all of the traits 2 | #The trait files are sorted alphabetically 3 | #**** MAKE SURE ALL WEIGHTS ADD UP TO 1.0 FOR EACH TRAIT***** 4 | #Trait 1 5 | 0.10 6 | 0.05 7 | 0.10 8 | 0.02 9 | 0.30 10 | 0.15 11 | 0.03 12 | 0.15 13 | 0.01 14 | 0.07 15 | 0.02 16 | #Trait 2 17 | 0.10 18 | 0.02 19 | 0.20 20 | 0.10 21 | 0.05 22 | 0.03 23 | 0.25 24 | 0.10 25 | 0.15 26 | #Trait 3 27 | 0.20 28 | 0.20 29 | 0.10 30 | 0.30 31 | 0.20 --------------------------------------------------------------------------------