Background:
Genetics and inheritance (https://dwarffortresswiki.org/index.php/DF2014:Genetics) are supposed to be a thing. This is what Toady had to say in DF Talk #8 (2010) (https://www.bay12games.com/media/df_talk_8_transcript.html):
Currently what we've got are the attributes ... vaguely the attributes to an extent being passed down. It's not like if the parents have two specific numbers it doesn't pick one or the other, but there's a little bit going on there. Then all of the colours, like eye colours, hair colour, I think that uses a dominant/recessive thing now where you pass on two copies and then it picks probably the colour with the lowest index; maybe there's an alphabetic bias right now on which genes are dominant, or it might be the first you listed, it could be the first one you list in the raws that's the dominant gene. I think that's it right now, just attributes and colours, the idea this time around was just to get our feet wet and get something working, and after that really it's easy to add new genes, easy to add all kinds of effects for them. I mean, I have to code it up, it's not something you can just mod in, and of course we'd have to have discussions about this; what's the extent to which personality is passed on versus it being environmental factors and so on, I'm sure we can have all kinds of wonderful arguments on the forums and so on, but right now we're just doing simple things that are pretty cut and dried like colours. Attributes ... it's not quite cut and dried there what passes along and what doesn't and so on, but I think right now that all the attributes pass along, whether or not that's accurate is another question. Also stuff like the shape of the nose and the height modifiers, basically anything called a modifier in the raws - how curly is your hair, how long is your nose, how far apart are your eyes, what colour is your skin/eyes/hair - all those pass along right now, they have genes to pass them along. As far as curses and stuff or whatever ... whatever those end up being we can link it in, but there's nothing right now of course.
The best study of genetics I could find is this one by DeKaFu from 2016 (http://www.bay12forums.com/smf/index.php?topic=158692), however it only deals with fur colour.
I'm not aware of any recent experiments on attribute inheritance. There are a few threads from 2017 and earlier, but I haven't found any rigorous statistical analysis. Skullsploder got as far as posting results for his control group (http://www.bay12forums.com/smf/index.php?topic=148536.msg6106083#msg6106083), but he never followed up with results for the low-strength and high-strength groups.
If I've missed any other experiments, please let me know.
Setup:
This is all done in fortress mode in DF version 0.47.04 with no mods besides a small reduction in stress vulnerability. I don't have DFHack installed, but I'm using Dwarf Therapist to view attributes.
I chose cave crocodiles (https://dwarffortresswiki.org/index.php/DF2014:Cave_crocodile) as my breeding population because they lay a large number of eggs (20-60), giving a large sample size for statistical analysis. They also take 3 years to reach adulthood, which is a little on the long side but gives me plenty of time to move the hatchlings around without risk of any unwanted breeding. Their lifespan is 60-100 years, so particular breeding pairs can be kept around for a long time.
Given that all physical attributes are meant to be heritable, I picked Disease Resistance (DR) for my experiments. Other attributes like strength can change over the course of an animal's life as a result of physical activity, but as far as I know nothing can alter Disease Resistance. Therefore it should be entirely determined by genetics.
Dwarf Therapist actually gives two values for each attribute in the form "A/B". Presumably the first is the current value while the second represents some upper limit. The relationship between them seems to be: B=max(2*A,A+1000). CSV export only gives the first value, so that's what I'm using here.
Experiments:
From an initial batch of tame hatchlings I chose three breeding pairs with low, intermediate, and high values of Disease Resistance. These breeding pairs are labelled as generation 0. They were isolated in three separate breeding chambers before they reached adulthood. The doors were kept locked as much as possible to eliminate any risk of cross-contamination.
A nest box was added to each chamber and they were allowed to lay eggs. Any clutches of fewer than 50 eggs were collected for food, while larger clutches were allowed to hatch. In hindsight I should have probably let the smaller clutches hatch too, but I wanted to avoid having to process multiple batches of hatchlings from each breeding pair. These hatchlings are labelled as generation 1.
When each clutch hatched they were tagged using the nickname feature of Dwarf Therapist and the stats were exported as a CSV file. These were then parsed and analysed using a Python script.
Most of the hatchlings were slaughtered, but I once again selected breeding pairs with particular attributes. I used the same criteria as I used for generation 0, so the hatchlings with the lowest DR were selected from the low-DR group, the ones with intermediate (~1000) DR were selected from the med-DR group, and the ones with the highest DR were selected from the high-DR group. I haven't done anything with these breeding pairs from gen1 yet, but they could be used to test for more complex kinds of inheritance.
Results:
The raw Disease Resistance values for each group and generation are shown below:
Low Disease Resistance:
Generation 0: [263, 386]
Generation 1: [1221, 1009, 1427, 997, 1088, 1244, 1037, 1071, 810, 243, 1143, 1188, 1421, 966, 811, 1490, 554, 1381, 696, 911, 715, 1282, 1027, 1430, 1649, 854, 909, 1276, 965, 1048, 752, 1212, 480, 1145, 893, 1074, 838, 559, 542, 1212, 980, 420, 499, 1088, 1369, 1842, 1081, 820, 857, 1205, 278, 928, 1676, 1056, 1046, 812, 709, 316, 1205]
Medium Disease Resistance:
Generation 0: [1118, 1139]
Generation 1: [1206, 898, 755, 1017, 973, 414, 1257, 1074, 491, 1059, 1385, 1668, 1586, 1486, 1017, 1028, 262, 237, 888, 1339, 970, 1170, 944, 1740, 1141, 1572, 1188, 942, 962, 1057, 752, 1207, 677, 525, 708, 1845, 1067, 1139, 1717, 950, 937, 1801, 1902, 926, 1440, 838, 518, 1110, 1143, 1538, 363, 263, 1057]
High Disease Resistance:
Generation 0: [1957, 1950]
Generation 1: [1006, 1264, 738, 1972, 927, 1345, 1288, 1049, 991, 1273, 1234, 514, 1532, 1199, 1957, 468, 1835, 946, 1350, 320, 816, 760, 1095, 959, 1039, 1166, 543, 990, 1061, 299, 1373, 929, 675, 928, 913, 1085, 1092, 914, 1716, 895, 559, 1022, 895, 730, 1180, 916, 833, 1287, 794, 1061]
The aggregate statistics are as follows:
Low Disease Resistance:
Generation 0 (n=2): [263, 386]
Generation 1 (n=59):
Mean: 995.9 ± 44.6
Standard Deviation: 339.4
Medium Disease Resistance:
Generation 0 (n=2): [1118, 1139]
Generation 1 (n=53):
Mean: 1059.4 ± 57.0
Standard Deviation: 411.4
High Disease Resistance:
Generation 0 (n=2): [1957, 1950]
Generation 1 (n=50):
Mean: 1034.7 ± 51.6
Standard Deviation: 361.2
All Gen1 (n=162):
Mean: 1028.6 ± 29.3
Standard Deviation: 371.9
The plus-or-minus uncertainties on the means are calculated using the standard error on the mean.
I also plotted some histograms of the attribute distributions:
(https://i.ibb.co/n0Z2xzc/fig1.png)
These use a bin width of 100. The black markers show the attributes of the parents for each group.
Conclusions:
To put it simply, attributes don't seem to be heritable. All of the means are within roughly one standard error of 1000, which is what you'd expect if they were generated completely randomly. The medium group actually have a very slightly higher mean than the high group. The sample size isn't big enough to give really smooth histograms, but they look fairly normal.
Of course, this comes with a number of caveats. I only tested one attribute out of six, I only ran the experiment for one generation (so far), and I only tested it on egg-layers. It may behave differently for other attributes or for live births. I don't think it's likely that I'll see different results after another generation, but I might try anyway. I've also set aside some cave crocodiles with low and high strength values, so that's something I can easily experiment with.
Any suggestions/requests for further experiments are welcome.
I've finished collecting data for both the second generation of Disease Resistance and the first generation of Strength.
I switched over to using probability density rather than absolute number in the overlayed plots since there's more variation in sample sizes this time.
Disease Resistance Gen2
Low Disease Resistance:
Generation 1: [278, 243]
Generation 2: [752, 837, 752, 570, 987, 857, 612, 876, 822, 987, 571, 1060, 945, 1018, 1052, 1082, 1404, 1583, 802, 1217, 1015, 435, 1196, 761, 788, 790, 769, 380, 1647, 795, 1096, 1296, 1062, 622, 1547, 1253, 1161, 694, 1949, 1098, 1984, 583, 1100, 944, 1006, 1073, 1994, 709, 940, 1047]
Medium Disease Resistance:
Generation 1: [1139, 1110]
Generation 2: [1392, 1175, 939, 428, 828, 1014, 1201, 612, 1168, 1101, 1453, 1482, 775, 1557, 954, 1070, 267, 1254, 702, 627, 805, 946, 1286, 1290, 809, 343, 952, 1309, 379, 1379, 796, 1340, 1030, 1076, 1068, 285, 1068, 1202, 1079, 1191, 856, 1030, 919, 837, 1650, 984, 586, 940, 893, 929, 251, 1238]
High Disease Resistance:
Generation 1: [1972, 1835]
Generation 2: [771, 1288, 1259, 930, 974, 229, 740, 891, 942, 1416, 1084, 961, 787, 1168, 952, 1230, 1227, 873, 1146, 1938, 976, 353, 1041, 977, 1465, 779, 940, 616, 748, 1640, 987, 815, 1283, 747, 1853, 1176, 949, 737, 1275, 832, 898, 758, 988, 327, 714, 1717, 925, 989, 839, 856, 984, 1927, 1083]
Low Disease Resistance:
Generation 1 (n=2): [278, 243]
Generation 2 (n=50):
Mean: 1010.4 ± 52.0
Standard Deviation: 363.7
Medium Disease Resistance:
Generation 1 (n=2): [1139, 1110]
Generation 2 (n=52):
Mean: 975.9 ± 46.5
Standard Deviation: 332.1
High Disease Resistance:
Generation 1 (n=2): [1972, 1835]
Generation 2 (n=53):
Mean: 1018.9 ± 49.0
Standard Deviation: 353.0
All Gen2 (n=155):
Mean: 1001.7 ± 28.2
Standard Deviation: 350.2
(https://i.ibb.co/yBkrs4Y/fig3.png)
Strength Gen1
Low Strength:
Generation 0: [174, 124]
Generation 1: [869, 912, 975, 1807, 1168, 1484, 1529, 819, 1969, 749, 200, 1901, 1146, 715, 1280, 799, 947, 1244, 1862, 943, 993, 1722, 1025, 1619, 1248, 881, 801, 796, 1020, 1001, 1038, 1274, 1010, 1131, 1525, 1166, 1042, 1053, 916, 1176, 271, 1696, 281, 972, 931, 940, 453, 754, 946, 1088]
Medium Strength:
Generation 0: [1019, 1028]
Generation 1: [619, 1057, 1151, 1561, 1162, 1050, 790, 763, 1274, 547, 334, 773, 598, 1045, 1555, 1265, 430, 1921, 1071, 1120, 971, 1950, 1285, 651, 998, 879, 1806, 1187, 1254, 1726, 723, 1247, 975, 1462, 871, 1043, 923, 1469, 1019, 1039, 539, 1827, 733, 1316, 1093, 1037, 931, 982, 1675, 1290, 948, 1280, 459, 777, 1243]
High Strength:
Generation 0: [1790, 1808]
Generation 1: [1391, 1669, 1020, 1093, 1011, 1901, 1114, 897, 1057, 1001, 446, 924, 769, 979, 455, 1003, 1019, 1003, 737, 725, 1933, 805, 823, 965, 1065, 1174, 1969, 364, 1778, 1719, 1547, 1103, 915, 397, 1666, 770, 1816, 1113, 1053, 538, 1166, 517, 827, 491, 1237, 1263, 953, 1163, 1662, 1129, 463, 829, 1079, 271, 494, 213, 995, 751, 1019, 758, 329, 1585, 294, 983, 433, 1908, 773, 1051, 1042, 975, 465, 1590, 955, 1156, 1123, 531, 1213, 1571, 971, 694, 945, 1896, 890, 487, 1532, 1039, 710, 786, 1160, 606, 1067, 508, 639, 991, 979, 1135, 1829, 615]
Low Strength:
Generation 0 (n=2): [174, 124]
Generation 1 (n=50):
Mean: 1081.7 ± 56.5
Standard Deviation: 395.4
Medium Strength:
Generation 0 (n=2): [1019, 1028]
Generation 1 (n=55):
Mean: 1085.3 ± 51.3
Standard Deviation: 377.2
High Strength:
Generation 0 (n=2): [1790, 1808]
Generation 1 (n=98):
Mean: 1004.7 ± 43.0
Standard Deviation: 423.1
All Gen1 (n=203):
Mean: 1045.5 ± 28.6
Standard Deviation: 406.2
(https://i.ibb.co/s2TbH3x/fig2.png)
I still can't see any evidence of any kind of attribute inheritance. I suspect the problem might be that egg-laying was added to DF around 2011, after genetics had already been implemented. Toady may have simply forgotten to transfer the appropriate genetic information into the eggs.
The next step is to follow voliol's suggestion and mod in some kind of mammal with a large LITTERSIZE. I might not do that immediately though. My necromancers (and I) need a break from endless animal-hauling and butchery jobs.