So... I'm trying to brainstorm ideas on code for a decent genetics system. I have a decent draft, but I have reservations. The basic idea was separating genes from appearance. With that, a character could have "tall" genes; there could be ways to influence the appearance to be short (if player wants), but offspring are still likely to be tall, depending on partner. So, a character file would be something like:
I like the flexibility of keeping genes separate from actual appearance, but it might be a bit much. Though regardless of complexity, I'd be interested in hearing any ideas.
This is the same as design a combat logic, it all depends on how much you want to complicate your life yourself .
I suppose that depending on the language things vary. but in theory when a character persists by itself in the save file you must already parameterize its characteristics like haircut color, skin color, complexity, stats, traits etc.
What do I mean by the above? A possible solution without the need to create specific fields for their genetics can be simply to use current parameters of the parents when generating the new child.
With this idea of simply a constructor to generate the child, it could be made more complex, as instead of simply using the color of one or the other, add the possibility of mixing both colors, or generating an intermediate color.
I like the flexibility of keeping genes separate from actual appearance, but it might be a bit much. Though regardless of complexity, I'd be interested in hearing any ideas.
Then just mimic DNA in a less complex way.
The character genes of each individual would be a string where each portion of X characters represent a characteristic. And for each characteristic, the letters define the gene by itself.
Therefore, your example would be a string like : FFFFFFFMMMSSSSSHHHHHSSSSSSSSTT
FFFFFFFMMM 70% female, 30% male
SSSSSHHHHH 50% Succubus, 50% human
SSSSSSSSTT 80% short, 20% tall.
Then this female have a baby with someone who have those genes: MMMMMMFFFFHHHHHHHHHHTTTTTSSSSS
60% male, 40% female
100% human
50% tall, 50% short
To determine the genes of the offspring, you pass each letter of the string and randomly decide which one will be kept (in pseudo language):
Code:
for i 1 to number letters:
if random 1 to 2 == 1
geneBaby += geneMother[i]
else
geneBaby += geneFather[i]
What can give you something like : FMFFMMFFMFSHSSSHHHHHSTTSTSSSTS
Then for each gene you count the number of letters to determine which characteristic will be the dominant one.
FMFFMMFFMF => 60% Female, 40% Male. It will be a female
SHSSSHHHHH => 40% succubus, 60% human. Mostly human, but with some succubus characteristics
STTSTSSSTS => 60% short, 40% tall. The size will be little bellow average for its race.
If you've an equality, you choose randomly which side won.
In my example the parent have ordered genes, because it's easier to write and understand for a human, but I recommend you to randomize the order before starting. Something like FMFFMFFMF Versus MMFMMFMFFM will give a better randomization for the baby.
Then, after many generation, you can see the apparition of recessive genes. By example you've two tall persons (TSSTTTSTTT and STTTSTTTST, both 70% tall) that lead to a baby with a size bellow the average (SSSTSTSTST 60% short)
Just be careful when you deal with genes that can have a large range of value, like the race or eyes color by example, a granularity of 10 can easily lead to a deadlock or a situation too complex for your initial algorithm. Lets say that for the eyes, you've (human) Grey, blUe, Brown, grE]en, (exotic races) gOld, Dark, Red. With a granularity of 10 like I used here, you can have a baby with GUBEODRGER, 20% Grey, 20% Green, 20% Red, 10% everything else. If will be difficult to effectively decide what will be the color.
It's better to have a granularity around 30, it should offer you more opportunities to have an effective dominant color, while keeping the possibility to have recessive genes.
You can also choose an odd number to limits the risk of equality, but it will just limits. If you choose 15 letters and have 3 possibilities for the characteristics, you can still have an equality with AAAAABBBBBCCCCC.
If you've a granularity high enough, you can also decide to cleanse the genes for each generation. If a letter appear only once, then it's replaced by the dominant letter. But you do this only once by characteristics. So if you've AAAAAAAABC, it's either B or C that become an A, not both. This should limit the problem presented above with the eyes color example.
Therefore, your example would be a string like : FFFFFFFMMMSSSSSHHHHHSSSSSSSSTT
FFFFFFFMMM 70% female, 30% male
SSSSSHHHHH 50% Succubus, 50% human
SSSSSSSSTT 80% short, 20% tall.
I'll chew on that example for traits; might be a good fit. My initial thought was to have base templates per race. E.g. "human" would have a normal height range between X and Y, but I'm not deep into it. I'll probably represent gender simply, though I won't let it control too much.
With this idea of simply a constructor to generate the child, it could be made more complex, as instead of simply using the color of one or the other, add the possibility of mixing both colors, or generating an intermediate color.
That's right up my alley. I already have something developed with e.g. { "colors": { "hair": [8,4,4], "skin": [128,64,0], ... } ; and a function that will pick a blend biased to one side or the other. E.g. white x red would result in slightly reddened white, or slightly whitened red, but not pink - this way two totally different colors wouldn't lead to a weird 50/50 blend.
For color stuff, I might limit it to simple appearance, and not genetics. Basically WYSIWYG: if you change your hair to red, that's what it is now. I'll say, anne O'nymous did provide some temptation - it would be interesting to see an unexpected eye color just pop up, though it might feel random unless the player was really studying the genes closely.
I'd also be interested in opinions on this, if I may impose: should a system be mostly predictable? Occasional surprises? Say you meet a blonde elf, one thing leads to another, and surprise: turns out there's some red hair in the lineage. I'd be fine either way. I'm not sure I care that much about breeding, strangely enough. It's more of an actions have consequences thing, and the consequences might as well be interesting (and I like playing with math).
With that, a character could have "tall" genes; there could be ways to influence the appearance to be short (if player wants), but offspring are still likely to be tall
That's right up my alley. I already have something developed with e.g. { "colors": { "hair": [8,4,4], "skin": [128,64,0], ... } ; and a function that will pick a blend biased to one side or the other. E.g. white x red would result in slightly reddened white, or slightly whitened red, but not pink
Yeah that sounds cool. With traits that are continuous in nature, like colors, height etc. you could do something like a weighted average of all genes. You can predetermine the weights of genes representing specific characteristics. Like in humans for example brown eyes will always be dominant over blue eyes (meaning brown eyes have a weight of 1 while blue 0 in this case). But two brown eyed people can have a blue eyed kid, if they had blue eye genes in them to begin with. Just an idea but I think it can have interesting possibilities. (Edit: a weight of 0 would mean it can never be picked lol, but you can program in exceptions for such cases like if the end average is 0 then it can only be that all genes are blue, or you can make it so that the weight is determined depending on the other gene in the pair instead of being fixed).
The way anne O'nymoussuggested is also really cool. But I think just having 2 genes for each trait (1 from dad 1 from mom) would be a bit more cleaner like in your original example, if you're going for continuous features especially. The random picking would've happened when picking which genes to pick from the parents (as each of them have pairs for genes as well), this is exactly how it happens irl too. The blending can happen by the weighted average method (this determines the phenotype and doesn't affect the genotype at all though, kinda like gene expression). For fixed traits that can't be blended, again you can use weights to determine which is the dominant one. Like race etc. (Though it would be cool if you can discretize racial features so they can blend as well).
This is tricky. I admit that if I wasn't paying too much attention to the genetics, and I randomly encountered red hair in an offspring, it would seem like a cheap trick as if the algo just picked a color randomly from a set. But on the other hand if I knew that some ancestors of this individual had red hair, and saw it pop up again unexpectedly, it would be really really cool.
The way anne O'nymoussuggested is also really cool. But I think just having 2 genes for each trait (1 from dad 1 from mom) would be a bit more cleaner like in your original example, if you're going for continuous features especially. The random picking would've happened when picking which genes to pick from the parents (as each of them have pairs for genes as well), this is exactly how it happens irl too.
While being cleaner, a pure 2 genes for each trait approach can only lead to more complex algorithm.
Take the specie by example. Did they really have to be half one specie and half the other ? It don't really make sense if the mother is the half human succubus in his example. The baby will be either human or succubus, but his genes being half/half feel odd.
What don't mean that you necessarily need to carry recessive genes in the character DNA. Instead of a cleanse method that remove one isolated gene, it can only keep the dominant gene of each parent.
Same for the hair color by example. Soon or later using a blended value, even a weighted one, will lead to a baby being the only purple haired person on this universe, or colors way more weird and/or unappealing. And here controlling the result will be a real pain in the ass.
This will a DNA approach offer you the possibility to limit the result into reasonable boundaries. If you've a baby with a dominant hair color as Blue, and a secondary color as Red, or what will be the most dangerous combination, Brown and Green, you'll randomize the value between two colors that you've already validated as being an acceptable range of color.
But the most important advantage is that the process will be consistent and limited to few simple lines of code that will works whatever the trait, with for sole variation the application of the result that will differ depending if it's a color or not. This while the pure 2 genes approach need to be proceeded differently for each trait if you want it to be effectively bug free.
While being cleaner, a pure 2 genes for each trait approach can only lead to more complex algorithm.
Take the specie by example. Did they really have to be half one specie and half the other ? It don't really make sense if the mother is the half human succubus in his example. The baby will be either human or succubus, but his genes being half/half feel odd.
What don't mean that you necessarily need to carry recessive genes in the character DNA. Instead of a cleanse method that remove one isolated gene, it can only keep the dominant gene of each parent.
Same for the hair color by example. Soon or later using a blended value, even a weighted one, will lead to a baby being the only purple haired person on this universe, or colors way more weird and/or unappealing. And here controlling the result will be a real pain in the ass.
This will a DNA approach offer you the possibility to limit the result into reasonable boundaries. If you've a baby with a dominant hair color as Blue, and a secondary color as Red, or what will be the most dangerous combination, Brown and Green, you'll randomize the value between two colors that you've already validated as being an acceptable range of color.
But the most important advantage is that the process will be consistent and limited to few simple lines of code that will works whatever the trait, with for sole variation the application of the result that will differ depending if it's a color or not. This while the pure 2 genes approach need to be proceeded differently for each trait if you want it to be effectively bug free.
Nope, you didn't read my post clearly enough. Both genes from each parent remain in the DNA. The weighted sum only determines the "phenotype", in other words, the expression. This is closer to how it actually happens irl as well. If you have a blue eye gene from your mum and a brown eyes gene from your dad, you will have brown eyes. But that doesn't mean that the blue gene disappears from your DNA, it remains there and can get passed on to your offsprings. So no, recessive genes don't get "removed", they're just never expressed if there's a dominant one.
With regards to you're critique on species, again I already addressed it. When it comes to "non-blendable" characteristics, the dominant one will be picked based on the weight. You're method is really cool but I think just using the simple 2 genes method you can achieve the same and is simpler overall. What essentially is happening in your case is, the "weight" is being encoded into how many of one letters you have, while in mine it is more explicitly defined for each trait. So basically in my technique if the weight value becomes mutable/inheritable, it will be the same as you. But personally I think its kinda sloppy to not have one trait explicitly dominant over the other, if they are not blendable.
Your critique about the limiting technique I agree with, but I think you can implicitly program that into my technique as well. If you want certain traits to remain discrete/non-blendable, a simple flag will suffice, only weights will be used to pick one. You can actually use a weighted die-roll as well if you don't want to keep one strictly dominant over the other. Possibilities are endless.
Wrong. In this case the baby have 50% chance to have blue eyes. In fact,
You must be registered to see the links
. Even if none have blue eyes, there's more than 10% chance that the baby eye will stay blue after birth. The only exception is when both are brown, because brown eyes "stole the chances" ; really basically speaking, blue and brown genes are complementary, while blue and green genes are opposed.
But that doesn't mean that the blue gene disappears from your DNA, it remains there and can get passed on to your offsprings. So no, recessive genes don't get "removed", they're just never expressed if there's a dominant one.
What is the reason why a DNA-like approach is easier to implement than any other one. The recession is implied by the format and automatically happen whatever the trait you're working on. While another approach need that you take count all the variation in your blending algorithm, and to take care of the rounding lost and possible overflow.
Let's say that the mother is a succubus with 0.5 succubus and 0.5 human, while the father is human with 0.3 martian, 0.1 succub, 0.6 human. How your computation is done in order to keep the recessive martian part, while ensuring that you'll never goes over or below 100% ?
By example, if you blend pair by pair, you'll have :
(0.0 + 0.1 ) / 2 = 0.05 martian
(0.5 + 0.1 ) / 2 = 0.3 succubus
(0.5 + 0.6 ) / 2 = 0.55 human
What lead to the baby being 0.1 nothing.
It's still possible to get ride of this missing part, by relying on the weight of each specie with specie weight * ( rest / number species in the trait)
martian += 0.5 * 0.03
succubus += 1.0 * 0.03
human += 1.5 * 0.03
And you resolve the lost due to the rounding (here 0.01) by adding to the dominant specie the difference between Sum( all specie ) and 100.
So yes, it's totally possible, but as I said it lead to an algorithm way more complex and open to bugs, than a simple "X genes DNA-like" approach.
In pseudo language it would be something near to :
Code:
babySpecies = array
for S each motherSpecies:
babySpecies += S
for S each fatherSpecies:
if S not in allSpecies:
babySpecies += S
for S each babySpecies:
if S in motherSpecies:
tmp = mother[S]
else:
tmp = 0
if S in fatherSpecies:
tmp += father[S]
baby[S] = round( 0.00 ) tmp / 2 # It' percent, keep it percent.
sum = 0
for S each babySpecies:
sum += baby[S]
rest = ( 1 - sum ) / size( babySpecies )
for S each babySpecies:
baby[S] += round( 0.00) weightSpecies[S] * rest
sum = 0
for S each babySpecies:
sum += baby[S]
dominant = ""
tmp = 0
for S each babySpecies:
if baby[S] > tmp:
tmp = baby[S]
dominant = S
baby[dominant] += 1 - sum
This opposed to:
Code:
for i = 0 to length DNA:
babyDNA[i] = random( 1 -> 2 ) == 1 ? motherDNA[i] : fatherDNA[i]
That will do the same thing that above, plus the algorithm for the eyes color, plus the algorithm for the size, plus the algorithm for...
Even if you define all the traits in the same way and then can have a generic version of the first code that will works for all of them, it will still be more complex than those two lines, for a result that will be the same in the end than then 30 lines of the first algorithm. If the traits are expressed by a 100 character string, you'll keep the percent approach, while having something nearer to how genetic transmission effectively works.
Even if you choose another approach than the ( mother + father ) / 2 I used as example here, by example applying weight to the specie, the algorithm will not be easier. In fact it will even be more complex since the blending itself will have to include the weight computation, while the rest of the algorithm, especially the catch-up part to stay with a value of 100% will be more complicated.
What essentially is happening in your case is, the "weight" is being encoded into how many of one letters you have, while in mine it is more explicitly defined for each trait.
The weight isn't encoded in the DNA-like string. In fact, the weight have absolutely no reason to be applied during the transmission. It have a meaning when you interpret the result, not when you compute it. The blue eyes gene don't have more or less chance to be transmitted, it have just more or less chance to be the one that will apply.
I choose a "keep the most frequent" approach for the interpretation in order to simplify the algorithm, because it's just a game after all, while keeping totally active the notion of recessive genes. But you can perfectly apply weight during the interpretation process. What will not make the algorithm really more complex. You count the number of occurrence for each genes in the trait, and apply the weight to it ; what you anyway have to do with your approach, just that you've already the "count".
But, once again, the weight have absolutely no reason to happen during the transmission. Imagine if it worked like that in real life. Instead of having more and more diversity, we would tend to uniformity, because the genes with the more weight would slowly thrown the others out of our DNA ; no more green eyes or redhead, an horror.
There's (relatively speaking) a notion of weight, but it don't apply to the genes themselves, who aren't a base unit. It apply to what compose them. What lead (globally speaking) to the blue eye gene to be more or less active, and therefore more or less likely to be triggered. And so what also lead to the weight having to be applied during the interpretation, not during the transmission.
Wrong. In this case the baby have 50% chance to have blue eyes. In fact,
You must be registered to see the links
. Even if none have blue eyes, there's more than 10% chance that the baby eye will stay blue after birth. The only exception is when both are brown, because brown eyes "stole the chances" ; really basically speaking, blue and brown genes are complementary, while blue and green genes are opposed.
What is the reason why a DNA-like approach is easier to implement than any other one. The recession is implied by the format and automatically happen whatever the trait you're working on. While another approach need that you take count all the variation in your blending algorithm, and to take care of the rounding lost and possible overflow.
Let's say that the mother is a succubus with 0.5 succubus and 0.5 human, while the father is human with 0.3 martian, 0.1 succub, 0.6 human. How your computation is done in order to keep the recessive martian part, while ensuring that you'll never goes over or below 100% ?
By example, if you blend pair by pair, you'll have :
(0.0 + 0.1 ) / 2 = 0.05 martian
(0.5 + 0.1 ) / 2 = 0.3 succubus
(0.5 + 0.6 ) / 2 = 0.55 human
What lead to the baby being 0.1 nothing.
It's still possible to get ride of this missing part, by relying on the weight of each specie with specie weight * ( rest / number species in the trait)
martian += 0.5 * 0.03
succubus += 1.0 * 0.03
human += 1.5 * 0.03
And you resolve the lost due to the rounding (here 0.01) by adding to the dominant specie the difference between Sum( all specie ) and 100.
So yes, it's totally possible, but as I said it lead to an algorithm way more complex and open to bugs, than a simple "X genes DNA-like" approach.
In pseudo language it would be something near to :
Code:
babySpecies = array
for S each motherSpecies:
babySpecies += S
for S each fatherSpecies:
if S not in allSpecies:
babySpecies += S
for S each babySpecies:
if S in motherSpecies:
tmp = mother[S]
else:
tmp = 0
if S in fatherSpecies:
tmp += father[S]
baby[S] = round( 0.00 ) tmp / 2 # It' percent, keep it percent.
sum = 0
for S each babySpecies:
sum += baby[S]
rest = ( 1 - sum ) / size( babySpecies )
for S each babySpecies:
baby[S] += round( 0.00) weightSpecies[S] * rest
sum = 0
for S each babySpecies:
sum += baby[S]
dominant = ""
tmp = 0
for S each babySpecies:
if baby[S] > tmp:
tmp = baby[S]
dominant = S
baby[dominant] += 1 - sum
This opposed to:
Code:
for i = 0 to length DNA:
babyDNA[i] = random( 1 -> 2 ) == 1 ? motherDNA[i] : fatherDNA[i]
That will do the same thing that above, plus the algorithm for the eyes color, plus the algorithm for the size, plus the algorithm for...
Even if you define all the traits in the same way and then can have a generic version of the first code that will works for all of them, it will still be more complex than those two lines, for a result that will be the same in the end than then 30 lines of the first algorithm. If the traits are expressed by a 100 character string, you'll keep the percent approach, while having something nearer to how genetic transmission effectively works.
Even if you choose another approach than the ( mother + father ) / 2 I used as example here, by example applying weight to the specie, the algorithm will not be easier. In fact it will even be more complex since the blending itself will have to include the weight computation, while the rest of the algorithm, especially the catch-up part to stay with a value of 100% will be more complicated.
The weight isn't encoded in the DNA-like string. In fact, the weight have absolutely no reason to be applied during the transmission. It have a meaning when you interpret the result, not when you compute it. The blue eyes gene don't have more or less chance to be transmitted, it have just more or less chance to be the one that will apply.
I choose a "keep the most frequent" approach for the interpretation in order to simplify the algorithm, because it's just a game after all, while keeping totally active the notion of recessive genes. But you can perfectly apply weight during the interpretation process. What will not make the algorithm really more complex. You count the number of occurrence for each genes in the trait, and apply the weight to it ; what you anyway have to do with your approach, just that you've already the "count".
But, once again, the weight have absolutely no reason to happen during the transmission. Imagine if it worked like that in real life. Instead of having more and more diversity, we would tend to uniformity, because the genes with the more weight would slowly thrown the others out of our DNA ; no more green eyes or redhead, an horror.
There's (relatively speaking) a notion of weight, but it don't apply to the genes themselves, who aren't a base unit. It apply to what compose them. What lead (globally speaking) to the blue eye gene to be more or less active, and therefore more or less likely to be triggered. And so what also lead to the weight having to be applied during the interpretation, not during the transmission.
Ok bro, so I'm not going to address each point cause clearly you don't understand what I'm proposing. The very first line you made a mistake. So I;m gonna give you a little genetics course. You misinterpreted my example, I didn't say you have one "parent" with blue eyes and one parent with brown eyes. I said you have two copies of the eye color "GENE", one blue "GENE" and one brown "GENE", YOU WILL HAVE BROWN EYES. As the blue gene simply tells the cell not to make pigment, brown one tells to make pigment. So brown is dominant.
This is how it works, all humans have 2 copies of each gene one from each parent. Eye color is complicated, but here is simplification in regards to only brown and blue. Following is the table of possible combinations:
BrownBlue = Brown
BrownBrown = Brown
BlueBlue = Blue
BlueBrown = Brown
So if two brown eyed parents have a kid (assuming the both have the BrownBlue combination), there is a 25% chance that they will produce a kid with blue eyes (if the kid will get BlueBlue combination).
The rest of the points you're making again come from a misunderstanding so not gonna address, all the answers are there, idk what's so difficult, this is a standard genetic algorithm that we learn in uni for NN and AI stuff.
One valid point that you brought up is the weights not adding up to 1, I completely forgot that one. In that case the weights are normalized. You can only have 2 genes my case also, so there's no x% orc, x% elf, x% some other etc. You can consider it a limitation as it might not suit your needs. (Also I just said race is not blendable, as only one will be expressed, why you using that example).
Btw, here's a link explaining the genetics of eye colors:
You must be registered to see the links
P.S.
In your calculator, if one parent has brown and one blue, the result is 50% which is consistent with what I am saying (though it is making the assumption that the brown parent has BrownBlue pair of genes, otherwise Blue eyed kid is almost impossible except a mutation happens), following combinations can happen:
Parent 1: BlueBlue = Blue
Parent 2 BlueBrown = Brown
Possibilities:
BlueBlue = Blue
BrownBlue = Brown
Thus 50% blue 50% brown. You simply didn't read what I said carefully enough. And bro I'm not attacking your life's work or anything lol, no need to viscously defend it, and please read more thoroughly everything is explained. This is the second time now.
Edit:
The irony is the calculator link you posted, if you scroll down, it explains homozygous and heterozygous genes I'm talking about, they're called alleles, each from each parent. You didn't even read that. The method I explained more closely resembles reality (not implying that necessarily makes it better). And also, again: THE WEIGHTS DON'T DETERMINE WHAT GETS PASSED IT ONLY DETERMINES WHAT IS EXPRESSED.
The idea is basically an implementation of Mendelian Genetics, read up on it, and the traits can be assumed to be Mendelian traits. Can't get much more biogically plausible than that bro. The weights determine dominant vs recessive alleles, or blend factor if you wanna do that.
I said you have two copies of the eye color "GENE", one blue "GENE" and one brown "GENE", YOU WILL HAVE BROWN EYES. [...] THE WEIGHTS DON'T DETERMINE WHAT GETS PASSED IT ONLY DETERMINES WHAT IS EXPRESSED. [...]
I’ve got a strong interest in genetics and this question really got me thinking of how I would implement a system involving genetics. I would want it to stay reasonably true to how real-life works but also provide some flexibility as this would be a game after all.
I’ve written down my idea below, and hopefully, it may give you some ideas.
Note: I started this independently from any of the previous comments as I had the idea of how I’d like it to work from the original question. ririmudev I didn't cover blending of colors specifically, but you could easily set a color to be three genes that represent the RGB value. You could increase the genes per color value to give you more distinction (like with the height example) anne O'nymous and bipedal_bastard Reading through your examples, I feel this is somewhere in between or a combination of both, depending on what type of trait it is. Hopefully, I've explained the idea clearly.
For a start, I would want to split the system into Distinct Values (like Eye Color) and Non-Distinct Values (like Height). However, using a simple concept, it’s possible to merge the two to form something like how it works in real life.
I’ll start with the simplest form:
Distinct Values:
Let’s take Eye Color as an example:
If say we have a trait pool of Brown, Blue, Green and Red. I would assign two of these to each person:
{Brown, Blue}
However, rather than assigning just this, I would also assign a strength value to each. These will be stored local to each person (but assigned a default at the start of the game):
{Brown:8, Blue:5}
Now, whichever has the strongest strength (or random if they are equal), that will be what the character shows (aka phenotype).
When the person (Person A) mates with one of these values will be selected at random (50/50) and then combined with another person’s gene of the same type and gone through the same splitting process.
If we say the other person (Person B) had {Blue:5, Green:4} genes, this will give us four options for the Persons genes:
Person A \ Person B
Blue:5
Green:3
Brown:8
{Brown:8, Blue:5}
{Brown:8, Green:4}
Blue:5
{Blue:5, Blue:5}
{Blue:5, Green:4}
This will represent the new persons genes, however, what the player sees will be:
Person A \ Person B
Blue:5
Blue:5
Brown:8
BROWN
BROWN
Blue:5
BLUE
BLUE
Or having a 50% chance of being Brown or Blue with this combination of people.
For me, using this type of approach should be fairly easy to program as you could easily create a generic function that does the comparison between two pairs of pairs of pairs and returns the result. This can be then be reused for all the distinct values (and even the non-distinct ones, which I’ll cover later) so then it’s just a case of assigned each person the set of traits and values and the same code can be re-used, making adding newer traits much simpler in the future.
However, before continuing, I should cover one key point from the above. Why should the strength value be unique to each person and not shared globally. The reason for this is to allow for a form of mutation between different people.
Mutations:
For me, adding mutations to this type of game would increase the playability as, I feel, adding some sort of randomness (albeit controlled) to the game increases the playability (100% up for debate I’m sure, so if you didn’t want any randomness, just use fixed global values for he strength in each value).
Now, after that detour, let’s cover non-distinct traits.
Non-Distinct Traits
I’m classifying non-distinct traits as traits that, taken as a whole, appear to merge together. Height and Skin colour are good examples in real life.
Before continuing however, I’d like to explain why I believe just taking the average of two values is not the best idea. This is because, by using the average of two values, you’ll always be at your maximum or minimum value based on the people you currently have available. In addition, there will be a tendency for the average to approach the mean value of the population. The player will have some control over this, but this trend will be difficult to override.
In real life, this is not how genetics work. An adult offspring that’s taller than his/her parents is proof of this. An adult child is rarely the average between the two and it’s common for the adult child to be significantly taller than his/her parents. This is because, things like height are not controlled by one gene, but multiple genes.
Therefore, for non-distinct values, I would use a multiple distinct values to determine the overall value.
Let’s use Height as an example and let’s say we want the people to vary from a height of 50 to a height of 150 with the ‘Normal’ height being 100(these don’t represent any actual units but could easily be converted).
We could do this using 5 genes for heights where each gene is either Tall(T) (+10 height), Normal(N) (+0 height) or Short(S)(-10 height).
Their genetic code would then be something like (I’m also including the strength of the gene):
{S:5, T:3}{T:7,S:2}{N:5,S:2}{T:6,T:5}{T:8,N:2}
Using the dominant gene method we gave earlier, this gives the trait of:
{S}{T}{N}{T}{T}
We can then add the values for each gene up (-10 + 10 + 0 +10 + 10) and add the ‘Normal’ height to give a height of 120.
However, the maximum height genes that person can pass on to their offspring would be {T}{T}{N}{T}{T} giving 140 while the shortest would be {S}{S}{S}{T}{N} giving 80. These chains will of course be combined with the partner to confirm the actual dominant genes and therefore, the overall height.
What I prefer about this method, is it re-uses the previous logic we had for distinct values and therefore, we can use the same generic function to determine the gene sequence of the offspring. This includes any of the mutations mentioned earlier.
One point of note, this will lead to a staggered height (there will only be 10 possible heights), but if you want the steps to be smaller, you can increase the number of genes or the have greater variance in the values assigned.
This pretty much covers the fundamentals of the system, however, I would like to add one more concept that could be entertaining in a game (or not):
For me, using this method should keep the code fairly simple but yet provide the freedom to allow for variances as the genes are combined. I’m sure there are simpler ways, but I tried to stay reasonably true to how genes work in real life. Hopefully, this might give you some ideas, but if not, I don’t mind. I enjoyed the process of thinking it through anyway.
I’ve got a strong interest in genetics and this question really got me thinking of how I would implement a system involving genetics. I would want it to stay reasonably true to how real-life works but also provide some flexibility as this would be a game after all.
I’ve written down my idea below, and hopefully, it may give you some ideas.
Note: I started this independently from any of the previous comments as I had the idea of how I’d like it to work from the original question. ririmudev I didn't cover blending of colors specifically, but you could easily set a color to be three genes that represent the RGB value. You could increase the genes per color value to give you more distinction (like with the height example) anne O'nymous and bipedal_bastard Reading through your examples, I feel this is somewhere in between or a combination of both, depending on what type of trait it is. Hopefully, I've explained the idea clearly.
For a start, I would want to split the system into Distinct Values (like Eye Color) and Non-Distinct Values (like Height). However, using a simple concept, it’s possible to merge the two to form something like how it works in real life.
I’ll start with the simplest form:
Distinct Values:
Let’s take Eye Color as an example:
If say we have a trait pool of Brown, Blue, Green and Red. I would assign two of these to each person:
{Brown, Blue}
However, rather than assigning just this, I would also assign a strength value to each. These will be stored local to each person (but assigned a default at the start of the game):
{Brown:8, Blue:5}
Now, whichever has the strongest strength (or random if they are equal), that will be what the character shows (aka phenotype).
When the person (Person A) mates with one of these values will be selected at random (50/50) and then combined with another person’s gene of the same type and gone through the same splitting process.
If we say the other person (Person B) had {Blue:5, Green:4} genes, this will give us four options for the Persons genes:
Person A \ Person B
Blue:5
Green:3
Brown:8
{Brown:8, Blue:5}
{Brown:8, Green:4}
Blue:5
{Blue:5, Blue:5}
{Blue:5, Green:4}
This will represent the new persons genes, however, what the player sees will be:
Person A \ Person B
Blue:5
Blue:5
Brown:8
BROWN
BROWN
Blue:5
BLUE
BLUE
Or having a 50% chance of being Brown or Blue with this combination of people.
For me, using this type of approach should be fairly easy to program as you could easily create a generic function that does the comparison between two pairs of pairs of pairs and returns the result. This can be then be reused for all the distinct values (and even the non-distinct ones, which I’ll cover later) so then it’s just a case of assigned each person the set of traits and values and the same code can be re-used, making adding newer traits much simpler in the future.
However, before continuing, I should cover one key point from the above. Why should the strength value be unique to each person and not shared globally. The reason for this is to allow for a form of mutation between different people.
Mutations:
For me, adding mutations to this type of game would increase the playability as, I feel, adding some sort of randomness (albeit controlled) to the game increases the playability (100% up for debate I’m sure, so if you didn’t want any randomness, just use fixed global values for he strength in each value).
Now, after that detour, let’s cover non-distinct traits.
Non-Distinct Traits
I’m classifying non-distinct traits as traits that, taken as a whole, appear to merge together. Height and Skin colour are good examples in real life.
Before continuing however, I’d like to explain why I believe just taking the average of two values is not the best idea. This is because, by using the average of two values, you’ll always be at your maximum or minimum value based on the people you currently have available. In addition, there will be a tendency for the average to approach the mean value of the population. The player will have some control over this, but this trend will be difficult to override.
In real life, this is not how genetics work. An adult offspring that’s taller than his/her parents is proof of this. An adult child is rarely the average between the two and it’s common for the adult child to be significantly taller than his/her parents. This is because, things like height are not controlled by one gene, but multiple genes.
Therefore, for non-distinct values, I would use a multiple distinct values to determine the overall value.
Let’s use Height as an example and let’s say we want the people to vary from a height of 50 to a height of 150 with the ‘Normal’ height being 100(these don’t represent any actual units but could easily be converted).
We could do this using 5 genes for heights where each gene is either Tall(T) (+10 height), Normal(N) (+0 height) or Short(S)(-10 height).
Their genetic code would then be something like (I’m also including the strength of the gene):
{S:5, T:3}{T:7,S:2}{N:5,S:2}{T:6,T:5}{T:8,N:2}
Using the dominant gene method we gave earlier, this gives the trait of:
{S}{T}{N}{T}{T}
We can then add the values for each gene up (-10 + 10 + 0 +10 + 10) and add the ‘Normal’ height to give a height of 120.
However, the maximum height genes that person can pass on to their offspring would be {T}{T}{N}{T}{T} giving 140 while the shortest would be {S}{S}{S}{T}{N} giving 80. These chains will of course be combined with the partner to confirm the actual dominant genes and therefore, the overall height.
What I prefer about this method, is it re-uses the previous logic we had for distinct values and therefore, we can use the same generic function to determine the gene sequence of the offspring. This includes any of the mutations mentioned earlier.
One point of note, this will lead to a staggered height (there will only be 10 possible heights), but if you want the steps to be smaller, you can increase the number of genes or the have greater variance in the values assigned.
This pretty much covers the fundamentals of the system, however, I would like to add one more concept that could be entertaining in a game (or not):
For me, using this method should keep the code fairly simple but yet provide the freedom to allow for variances as the genes are combined. I’m sure there are simpler ways, but I tried to stay reasonably true to how genes work in real life. Hopefully, this might give you some ideas, but if not, I don’t mind. I enjoyed the process of thinking it through anyway.
I especially like the idea of mutations and linked genes.
The correlated genes property I think can also emerge by just placing the genes that you want to correlate next to each other in the DNA sequence. And when inheritance happens, instead of happening on a gene by gene basis, it can happen on a splice by splice bases kinda like irl crossover. Naturally neighboring genes are likely to be inherited together instead of separately most of the time atleast.
Also making the Major Mutation rates themselves inheritable and mutable could be interesting like you said. Back in Darwin's days pigeon breeders knew that to get interesting breeds its better to breed mother to son, father to daughter etc. cause you see changes more often (though in reality this probably had more to do with recessive genes expressing more often rather than mutations). You could implement something similar so if you keep breeding among relatives, the mutation rates go up to the point where you even start seeing deformities.
I especially like the idea of mutations and linked genes.
The correlated genes property I think can also emerge by just placing the genes that you want to correlate next to each other in the DNA sequence. And when inheritance happens, instead of happening on a gene by gene basis, it can happen on a splice by splice bases kinda like irl crossover. Naturally neighboring genes are likely to be inherited together instead of separately most of the time atleast.
Also making the Major Mutation rates themselves inheritable and mutable could be interesting like you said. Back in Darwin's days pigeon breeders knew that to get interesting breeds its better to breed mother to son, father to daughter etc. cause you see changes more often (though in reality this probably had more to do with recessive genes expressing more often rather than mutations). You could implement something similar so if you keep breeding among relatives, the mutation rates go up to the point where you even start seeing deformities.
Yeah, I did consider taken the sequence of the genes into account. However, I imagined that would be painful to implement and if you wanted to make changes in the future, it would be painful (as with any specifically ordered list). That's why I thought it better to have Parent-Child relationships as it would give a similar behavior and should be a concept familiar to programmers without giving the pain of ensuring everything is kept in sequence.
On the Major Mutations, I think if this is a value, it could be fun from a gaming perspective. Something simple could be, if you place your people in a Nuclear Wasteland, it could increase this value while healthy living and diet could reduce to make your people more stable. This could be a nice way to add variety to the game, with different environments having an impact on how stable the population is.
As for breeding among relatives, I feel it would be better to implement the recessive gene methodology. However, this would involve deliberately implementing negative genes which I think would also be an extra challenge for the player. Things like, reduced lifespan, number of children capable of, tendency to headbutt things etc would add extra depth to the game.
A bit belated, but thanks for contributions. I've read everything and will hopefully do something sometime. Maybe before 2077. My main hangup now is the svg-based animation system, but from my whole collection I somehow don't have an ideal CP shot to trace over. It's always something: too zoomed in, breasts not the right shape, video quality not good enough, penis is curved too much... And then the white stuff has its own issues: too much spills out, too much stays in, too watery... I could go on.
(unrelated random comment, but why is Y**Tube on my other computer... with a different IP addr... showing people with baby announcements in my suggestions? Pretty sure I've never clicked on anything like that even once. I 100% don't care about preg outside of H-games)
tldr: thanks for the comments, and maybe I felt like ranting a bit on marginally related topics.
Necro...
Attached is a zip of an in-progress implementation (assuming the zip & attachment worked). I was initially hyped about my idea of generating traits based on a normal distribution derived from the parents, but not super happy with the result. E.g. for a human and succubus parent, genes will be a blend of the height distributions for each parent. But two tall parents can have short kids, and vice versa. A significantly tall race (e.g. a titan) would influence the equation, but the results still don't quite feel satisfying.
I guess to some degree it all depends on the game direction: if knocking up a bunch of randos once or twice, there probably shouldn't be a lot of surprises. If having a bunch of offspring with relatively fewer partners, then maybe the normal distribution stuff could be ok.
Either way, I'm at least happy with separating genes from expressions; just need to determine direction & settle on the appropriate algorithms.
Tech notes (for one who knows what npm & node is already, and can figure out the relevant working directory):
1. Build: npm run-script build
2. Run: node build/index.js
(known-working with node 16.18 and npm 8.19)
I was initially hyped about my idea of generating traits based on a normal distribution derived from the parents, but not super happy with the result. E.g. for a human and succubus parent, genes will be a blend of the height distributions for each parent. But two tall parents can have short kids, and vice versa. A significantly tall race (e.g. a titan) would influence the equation, but the results still don't quite feel satisfying.
Not sure; depends on what one is going for, and I haven't settled on a particular direction at this point.
But my current normal distro implementation seems unsatisfying, since the outcome is basically independent of the parents' expressions (though dependent on the parent's genes in a nonlinear way).
The algorithm I mentioned a year ago for eye color was more satisfying: pick one color, and move it in the direction of the other color. So if player has brown eyes, and demon has black eyes, result can be a darkened brown or reddened black. Could do the same for height, but wanted to explore other algorithms.
I think the overall quest is finding a good blend of predictability and variability. Which probably means working backwards: focusing on expressions, and resolving the underlying genes later.
The reason I asked that question was because I was hoping to maybe spur some thoughts or ideas. I honestly think it's a tricky problem and I don't have a good answer myself. I've dabbled with some character generation and randomization in my game and for my next game I would really like to do a breeder, so I've been thinking about these things a lot lately.
Here are a few thoughts I have, that may prove helpful:
When randomizing some physical measurement like, for instance, penis size, I got the best result when I did a Gaussian distribution over some range. I took the smallest cock I could think of as the minimum and the largest as the maximum and set the median to what I believed to be a good average. Then I took that whole range and shifted it up by 2 inches, because that reflects more what players expect. Don't be afraid to exaggerate.
For other things, like hair color, well... they say that when if you keep mixing colors you'll eventually end up with brown. Perhaps you could try a more guided approach. Choose one of the parents to have the more dominant gene and lean more towards their hair color, or trait, rather than go for something in the middle.
I believe it's important that when you look at someone's offspring, they should be reminiscent of their parents. At least one of them. That helps the player form that familiar link in their mind.
I wouldn't put too much weight on random mutations. You could sprinkle some in there for occasional surprises but I think it's better to be predictable rather than not.
Ah, with thanks for the discussion going - I see what my problem is.
The normal (or other distribution) idea is actually fine, but wasn't used at the right place.
The algorithm I mentioned for eye color is what I should generally use when determining traits from parents. At least for items that aren't true/false. Things like horns/no horns would get a different algorithm - maybe even a custom one. E.g. succubus horns x human no-horns = 90% chance of succubus horns; succubus horns x oni horn = 50/50, or maybe a small chance of triple horns? Just an example for now.
But parents ultimately come from 2 places: character creation (for player character), and NPC generation. The latter is where distributions can come into play: e.g. a town called elf valley would have most spawns get their attributes from an elf distribution.
Of note: the player and generated NPCs should get a duplicate of the same gene. That's to avoid having to backtrack to figure out grandparents, great-grandparents, etc.