// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;

library GenesisTraitFactory {
  uint constant public NUM_TRAITS = 9;
  uint constant public MAX_LENGTH = 40;

  function roll(uint seed, uint nonce) external view returns(uint[NUM_TRAITS] memory){
    uint[NUM_TRAITS] memory traits;
    uint[MAX_LENGTH][4][NUM_TRAITS] memory genes;
    
    uint[2][2] memory races;
    races[0] = [uint(1), 2];
    races[1] = [uint(50), 100];

    genes[1][0] = [uint(0), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23];
    genes[1][1] = [uint(0), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23];
    genes[1][2] = [uint(0), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 240, 360, 480, 600, 680, 790, 870, 950, 1026, 1136, 1240, 1350, 1460, 1570, 1680, 1720, 1760, 1840, 1870, 1925, 1980, 2000];
    genes[1][3] = [uint(0), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 240, 360, 480, 600, 680, 790, 870, 950, 1026, 1136, 1240, 1350, 1460, 1570, 1680, 1720, 1760, 1840, 1870, 1925, 1980, 2000];

    genes[2][0] = [uint(0), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
    genes[2][1] = [uint(0), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; 
    genes[2][2] = [uint(0), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 62, 72, 76, 90, 104, 118, 132, 146, 158, 172, 181, 189, 197, 198, 200];
    genes[2][3] = [uint(0), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 62, 72, 76, 90, 104, 118, 132, 146, 158, 172, 181, 189, 197, 198, 200];

    genes[3][0] = [uint(0), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 5, 6, 9, 11];
    genes[3][1] = [uint(0), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 7, 8, 10];
    genes[3][2] = [uint(0), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 50, 57, 81, 88, 90];
    genes[3][3] = [uint(0), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 35, 45, 50, 55];

    genes[4][0] = [uint(0), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 5, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 21, 22, 23, 24];
    genes[4][1] = [uint(0), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 17, 19, 20, 21, 22, 23, 24, 25];
    genes[4][2] = [uint(0), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 30, 45, 55, 61, 67, 74, 80, 86, 94, 98, 102, 104, 108, 114, 120, 124, 125];
    genes[4][3] = [uint(0), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 45, 55, 65, 75, 81, 87, 94, 100, 106, 110, 116, 118, 122, 128, 134, 138, 139, 141];

    genes[5][0] = [uint(0), 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37];
    genes[5][1] = [uint(0), 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37];
    genes[5][2] = [uint(0), 0, 30, 55, 73, 113, 153, 193, 238, 268, 288, 318, 333, 373, 418, 458, 488, 533, 563, 603, 643, 688, 708, 753, 768, 793, 818, 843, 873, 890, 910, 935, 955, 980, 982, 984, 986, 988, 990, 1000];
    genes[5][3] = [uint(0), 0, 30, 55, 73, 113, 153, 193, 238, 268, 288, 318, 333, 373, 418, 458, 488, 533, 563, 603, 643, 688, 708, 753, 768, 793, 818, 843, 873, 890, 910, 935, 955, 980, 982, 984, 986, 988, 990, 1000];

    genes[6][0] = [uint(0), 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33];
    genes[6][1] = [uint(0), 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33];
    genes[6][2] = [uint(0), 0, 0, 0, 0, 0, 0, 8, 16, 19, 23, 31, 39, 47, 52, 54, 60, 62, 70, 76, 84, 92, 98, 104, 110, 116, 123, 129, 135, 143, 148, 153, 160, 168, 174, 179, 185, 187, 192, 200];
    genes[6][3] = [uint(0), 0, 0, 0, 0, 0, 0, 8, 16, 19, 23, 31, 39, 47, 52, 54, 60, 62, 70, 76, 84, 92, 98, 104, 110, 116, 123, 129, 135, 143, 148, 153, 160, 168, 174, 179, 185, 187, 192, 200];

    genes[7][0] = [uint(0), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40];
    genes[7][1] = [uint(0), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 24, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40];
    genes[7][2] = [uint(290), 310, 316, 436, 556, 676, 756, 796, 876, 1036, 1066, 1096, 1176, 1276, 1316, 1356, 1396, 1456, 1536, 1576, 1616, 1696, 1726, 1766, 1796, 1826, 1856, 1876, 1882, 1892, 1898, 1905, 1921, 1930, 1934, 1938, 1942, 1946, 1950, 1970];
    genes[7][3] = [uint(0), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 290, 296, 376, 406, 506, 546, 586, 626, 686, 766, 806, 846, 926, 956, 986, 1006, 1012, 1022, 1028, 1035, 1051, 1060, 1064, 1068, 1072, 1076, 1080, 1100];

    genes[8][0] = [uint(0), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22];
    genes[8][1] = [uint(0), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22];
    genes[8][2] = [uint(0), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 690, 710, 730, 750, 770, 790, 810, 815, 835, 855, 875, 890, 905, 925, 945, 965, 967, 969, 971, 973, 975, 985, 1000];
    genes[8][3] = [uint(0), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 690, 710, 730, 750, 770, 790, 810, 815, 835, 855, 875, 890, 905, 925, 945, 965, 967, 969, 971, 973, 975, 985, 1000];

    uint randomSeed = uint(keccak256(abi.encodePacked(block.difficulty, seed, block.timestamp, nonce++)));
    uint r;
    for (uint i = 0; i < races[1].length; i++) {
      if (randomSeed % races[1][1] < races[1][i]) {
        r = i;
        traits[0] = races[0][i];
        break;
      }
    }
    
    for (uint i = 1; i < NUM_TRAITS; i++) {
      randomSeed = uint(keccak256(abi.encodePacked(block.difficulty, randomSeed, block.timestamp, nonce++)));
      uint traitSeed = randomSeed % genes[i][2+r][MAX_LENGTH-1];
      for (uint j = 0; j < MAX_LENGTH; j++) {
        if (traitSeed < genes[i][2+r][j]) {
          traits[i] = genes[i][r][j];
          break;
        }
      }
    }

    if (traits[6] == 3 || traits[6] == 21 || traits[6] == 22 || traits[6] == 28) {
      traits[4] = 0;
    }
    
    if (traits[7] == 28 || traits[7] == 29 || traits[7] == 31 || traits[7] == 33) {
      traits[5] = 0;
    }

    if (traits[7] == 32 || traits[7] == 36 || traits[7] == 37) {
      traits[4] = 0;
      traits[6] = 0;
    }

    if (traits[7] == 40) {
      traits[4] = 0;
      traits[5] = 0;
      traits[6] = 0;
    }

    return traits;
  }
  
}
{"success": true, "error": null, "results": {"detectors": [{"check": "weak-prng", "impact": "High", "confidence": "Medium"}, {"check": "uninitialized-local", "impact": "Medium", "confidence": "Medium"}]}}