PDA

View Full Version : Familicide Simulation



Halaku
2013-04-13, 09:53 AM
Hi guys!

I've been reading the comic for several years and lurking the forums for a few months but it's the first time I post.

After reading the last argument about the Familicide (if it's posible, if it would wipe the whole OoTS world, etc...), I got the idea yesterday to try to help, by creating a small program to simulate the casting of the spell. First I'll explain how it works and second the results I got.

I did it with Python and I will try to post the code in a spoiler box at the end of the post. Of course anybody who wants to run it himself or check the code to find all the enourmous mistakes I made, can ask me and I will happily send it :smallbiggrin:

I say it in advance: I did it mainly for fun and to practice my programming and in second place to see what would happend and to try to clarify (also to myself) how it works.. I did not do it to prove anyone right or wrong. Also, it feels wierd, to spend time creating your own little world full of dragons, and then try to kill them all!! Just for the fun of it It's like being your own merciless god! :smallbiggrin:

How it works:
It creates the first generation of dragons (the number of initial dragons can be modified), each one with its own unique Blood Line (BL), represented by a number. Then it matches them randomly, creating 2 offsprings, both with all the BLs of the parents. For example: if the dragon with the BL "5" mates with the dragon with the BL "18", the offspring has the BL "5,18". It does that for every dragon, so now we have the second generation, each with 2 BLs. Then it repeats the process, to create a third generation, in which every dragon has 4 BLs. This goes as long as we want, creating new generations. To avoid an infinite number of dragons, each generation dies when their grand-grandchildren are born, so there is only 3 generations of dragons on the field at any time.

Now that we had fun giving birth to a new race, its time to slaughter them all!! :smallamused:. When Familide is cast over a dragon, the program checks every living dragon and, if it shares at least one BL with the "objective" it kills it, and stores all his BLs for the second step. In the second step, it checks again every living dragon, and kills it if it has any of the BLs stored during the first step. Finally, it returns the percentage of slain dragons.

The results:
I run several simulations, varying the initial population and the number of passed generations, and V's prediction turned to be more accurate than I thought. Some examples:
(The result vary slightly from run to run, but are generally accurate and largely depending of the target's generation. To make it easier, I made it targe the equivalent to the ABD)

- 4 Generations, 500 Dragons: Around 10% dead
- 4 Generations, 100 Dragons: Around 40% dead
- 5 Generations, 500 Dragons: Around 70% dead
- 5 Geberations, 1000 Dragons: Around 50% dead
- 6 Generations, 1000 Dragons: Around 99.9% dead
- 6 Generations, 10000 Dragons: Around 60% dead

I think the trends are easy to get. I have no idea about the dragon's live cicle in D&D, but 200-300 years for generations doesn't sound crazy for me, so with 4 or 5 generations and a few hundreds of dragons, V's 25% is quite posible. :smallbiggrin:

I thought about runing it with human parameters, but when I tried with several thausand people and 30 or 40 generation, my computer gave me the finger and told me to do it myself :smallwink: Anyway, at this point the answer would be "everybody is dead"

Actually, at this point the genetic pool is so mixed (after 40 generations everybody should have 2^40 BLs (1000000000000 :smalleek:)) that any human targeted by the first step should probably wipe the whole humanity.
Anyway, and quoting V him/herself: "And once again, Probability proves itself willing to sneak into a back alley and service Drama as would a copper-piece harlot" And I'm fine with it!!! :smallwink:


I hope this helps in the endless discussion about Familicide!! :smallsmile:

The code:



import random

class Dragon (object):
"""
Represents a dragon"
"""
def __init__(self, BloodLines):
"""
BloodLines must be a List
"""
self.BloodLines = BloodLines
self.Alive = True

def Kill (self):
self.Alive = False


def Mate (Mate1, Mate2):
"""
Dragon1 and Dragon2 are instances of class Dragon
Returns a list with 2 equal Dragons, both with all the blood lines of th parents
"""
NewBloodLines = Mate1.BloodLines + Mate2.BloodLines
Offspring1 = Dragon(NewBloodLines)
Offspring2 = Dragon(NewBloodLines)
return [Offspring1, Offspring2]

def CreateGeneration (OldGeneration):
"""
Imput: A Generation of Dragons (a list of instances Dragon, all with the same number of BloodLines
Output: A new generation of Dragons after the old mated with random partners. Every Dragon has double number of blood lines as the previos one
"""

if (len(OldGeneration) % 2) != 0:
return ("Can't create a new Generation from ",OldGeneration, "The number of parents must be even")
ClonGeneration = OldGeneration[:]
random.shuffle(ClonGeneration)
NewGeneration = []

while len(ClonGeneration) > 0:
Mate1 = ClonGeneration.pop()
Mate2 = ClonGeneration.pop()
Offspring = Mate(Mate1, Mate2)
NewGeneration += Offspring
return NewGeneration

def Familicide (Dragon, DragonPopulation):
"""
Imput: An instance of the class Dragon (the objective of the spell) and the whole population of dragons (all the living generations, as a whole list
Output: a new list with the surviving Dragons"
"""
BloodLinesFirstStep = []
BloodLinesSecondStep = []
DeadDragons = 0
"First the blood lines used in the first step are added"
for BloodLine in Dragon.BloodLines:
if BloodLine not in BloodLinesFirstStep:
BloodLinesFirstStep.append(BloodLine)


"searchs every dragon and every blood line for the first step"
for Victim in DragonPopulation:
for BloodLine in BloodLinesFirstStep:

"checkst that the victim is an objective and is not already dead"
if BloodLine in Victim.BloodLines and Victim.Alive == True:
"adds the new blood lines of the victim for the second step, and kills it"
for BL in Victim.BloodLines:
if BL not in BloodLinesSecondStep:
BloodLinesSecondStep.append(BL)
Victim.Kill()
break

"starts the second step"
for Victim in DragonPopulation:
for BloodLine in BloodLinesSecondStep:
"checkst that the victim is an objective and is not already dead"
if BloodLine in Victim.BloodLines and Victim.Alive == True:
Victim.Kill()
break
## print "the blood lines cursed in the first step are", BloodLinesFirstStep
## print "the blood lines cursed in the second step are", BloodLinesSecondStep
for dragon in DragonPopulation:
if dragon.Alive == False:
DeadDragons +=1
## print "the number of dead dragons is", DeadDragons
## print "the total number of dragons is", len(DragonPopulation)
## print "the percentage of dead dragons is", (100.0*DeadDragons/len(DragonPopulation))
return (100.0*DeadDragons/len(DragonPopulation))


def BuildPopulation (NumGen, DragonsPerGen):
FirstGeneration = []
ListGenerations = []
GlobalPopulation = []
for dragon in range (DragonsPerGen):
NewDragon = Dragon([dragon])
FirstGeneration.append(NewDragon)
ListGenerations.append(FirstGeneration)
for Generation in range (NumGen - 1):
ListGenerations.append(CreateGeneration(ListGenera tions[-1]))
if len(ListGenerations) > 3:
ListGenerations.remove(ListGenerations[0])
"""
this line represents that the older generation dies of old age when their grand-grandchildren are born, thus keeping the population constant
"""
for Generation in (ListGenerations):
GlobalPopulation += Generation
return(GlobalPopulation)

def RunSimulation (numTrials, NumGen, DragonsPerGen):
ListResults = []
total = 0
for n in range (numTrials):
Population = BuildPopulation(NumGen,DragonsPerGen)
## Objective = random.choice(Population)
"""With this line of code, the spell targets a random dragon"""
Objective = Population[-(DragonsPerGen+1)]
"""With this line of code, the spell targets the equivalent to the ABD"""
Result = Familicide(Objective,Population)
print Result
ListResults.append(Result)
for a in ListResults:
total +=a
return (total/len(ListResults))


How to impove it:

I made some assumptions to make it easier that could of course be improved:
- It allows incest bewteen siblings or cousing (grose :smalleek:) which diminisses the efectivity of the spell but decreasing the mixing of the BLs
- It considers a unique population with perfect mixing, which highly enhances the efectivity. It would be interesting to model it with isolated populations, onlly allowed for a small percentage of mixing at each generation
- It could be done with a random amount of offspring, allowing for example between 0 and 4 children, but I think it would just make it more complicated without providing anything new.

I am of course open to new ideas and suggestions. :smalltongue:

Kaulguard
2013-04-13, 10:11 AM
I know exactly nothing about programming, but I thought this was cool as hell. Kudos to you!

EmperorSarda
2013-04-13, 10:50 AM
Something to take into consideration is what The Giant said (http://www.giantitp.com/forums/showpost.php?p=12856280&postcount=1034),
"If a person can only trace their blood through (say) Penelope's already-dead great-great-great-grandfather, then they're safe. Thus cousins and second-cousins and the like are all dead, but more distant genetic relations are not."

So, it wouldn't completely wipe out the human race.

VanaGalen
2013-04-13, 10:52 AM
The dragon simulation is very impressive. However, for human simulation, I think the method of selecting familicide target should be modified. If we have, let's say, 30 generations, picking for the spell somebody from the first generations should probably wipe out every living human. That even is unlikely, why would anyone want to cast such spell on somebody who has been dead for centuries (not to mention the trouble of finding a corpse from 500 years ago). Therefore we can assume eligible familicide targets are only from living or recently deceased generations. As the first, unconditional step of familicide kills only ancestors and descendants of the target, majority of the ancestors is dead anyway (it might kill the target's grandpappy, but not many more), and any target can have 3 generation of descendants at most, each carrying minimum of 12,5% of target's genes, the affliction isn't really widespread in the population.
Now, for the second step, it stops at the first person who had already been dead when the spell was cast. So even if the target's grand-grandfather is alive, the furthest it goes is 2nd cousins. It's true that if these cousins have offspring, the spell will jump to their spouses' families, but it would require very specific (and rare) family structure to really wipe out whole human population.

ellindsey
2013-04-13, 10:56 AM
Code's kind of useless as presented, unfortunately. The forum software stripped out all the leading spaces on the lines, which in Python completely wrecks the flow control of the code. You'll need to post it using the CODE tag to preserve the program structure.

NerdyKris
2013-04-13, 11:19 AM
Actually, at this point the genetic pool is so mixed (after 40 generations everybody should have 2^40 BLs (1000000000000 :smalleek:)) that any human targeted by the first step should probably wipe the whole humanity.

Keep in mind that the OOTS universe was created at a set point in time, with dragons, a large human population, etc, already in existence. You can't trace all life back to a single organism, and there's no real bottleneck, as the world has only been in existence for 1180-ish years.

Halaku
2013-04-13, 11:21 AM
Code's kind of useless as presented, unfortunately. The forum software stripped out all the leading spaces on the lines, which in Python completely wrecks the flow control of the code. You'll need to post it using the CODE tag to preserve the program structure.


Thanks! I fixed it (Sorry, first time I use the forum) :smallredface:


Therefore we can assume eligible familicide targets are only from living or recently deceased generations.

I took that into acount. Older generations are erased during the "building population" stage, and can't be the objective of the spell, or the target of any of the spell's steps.


If we have, let's say, 30 generations, picking for the spell somebody from the first generations should probably wipe out every living human.

What I realized while writing the program is that (against intuition), if you target a "younger" target, the spell is deadlier. If you target a member of the first generation, the first step only wipes people who shares this unique blood line. But, if you target a member of the fourth generation, the first step kills anyone who shares at least 1 part of EIGHT blood lines, thefore making the second step a complete nightmare. And it gets worse with every generation passing. (at least that's how I understood and wrote it, of course I could be wrong).

Halaku
2013-04-13, 11:24 AM
Keep in mind that the OOTS universe was created at a set point in time, with dragons, a large human population, etc, already in existence. You can't trace all life back to a single organism, and there's no real bottleneck, as the world has only been in existence for 1180-ish years.

Yeah but 1000 years, if we assume one generation every 25 years, means 40 generations.

(again, I did this for the fun. I do not care what the numbers say, if the giant says that only a few hundred humans are killed, then a few hundred humans will be killed, and I will love it!!!) (ok, that sounds pretty creepy :smalleek:)

VanaGalen
2013-04-13, 11:47 AM
What I realized while writing the program is that (against intuition), if you target a "younger" target, the spell is deadlier. If you target a member of the first generation, the first step only wipes people who shares this unique blood line. But, if you target a member of the fourth generation, the first step kills anyone who shares at least 1 part of EIGHT blood lines, thefore making the second step a complete nightmare. And it gets worse with every generation passing. (at least that's how I understood and wrote it, of course I could be wrong).

Ah yes, I interpreted the Giant's familicide description wrong. The detailed spell description is here (http://www.giantitp.com/forums/showpost.php?p=12856280&postcount=1061) (if anyone wants to read it again). I thought the 1st step only targets direct descendants and ancestors, but now I see it goes over every branch of the family tree. And the 2nd step is applicable to spouses' families only.
In that case indeed, the younger the target is, the more ancestors he has in the first generation, so as a result the spell covers bigger part of the population. So assuming that incest isn't really popular among humans, the spell is very likely to wipe out whole human population, and possibly also elven and orc.

Douglas
2013-04-13, 11:48 AM
Your algorithm matches what The Giant described for the first step, but not for the second. The second step is a much more limited "can you trace a blood relationship solely through still-living relatives". Sharing a bloodline is not sufficient for the second step if the closest link is already dead. To do that part properly you need to keep track of parents, children, and siblings, and trace the relationships step by step.

King of Nowhere
2013-04-13, 11:57 AM
nice simulation.
So, if we knew how long a dragon generation lasts, we could know how many dragons were there at the beginning of the ootsworld.

Amphiox
2013-04-13, 12:06 PM
Keep in mind that the OOTS universe was created at a set point in time, with dragons, a large human population, etc, already in existence. You can't trace all life back to a single organism, and there's no real bottleneck, as the world has only been in existence for 1180-ish years.

It should not be difficult to alter the code to start with any arbitrary number of unique BL's instead of 1.

But I HIGHLY suspect the results will, after a very few number of generations, end up the same. It is not easy to intuitively grasp just how extensive blood-line mixing becomes after a surprisingly short period of time.

Amphiox
2013-04-13, 12:09 PM
Great simulation, Halaku!

Interestingly your program closely duplicates the kinds of programs evolutionary scientists use to determine universal common ancestors and to trace gene trees.

It is how, for example, they calculated that "Y-chromosome Adam" lived approximately 70000 years ago, or that "mitochondrial Eve" lived about 150000 years ago.

Halaku
2013-04-13, 12:20 PM
Your algorithm matches what The Giant described for the first step, but not for the second. The second step is a much more limited "can you trace a blood relationship solely through still-living relatives". Sharing a bloodline is not sufficient for the second step if the closest link is already dead. To do that part properly you need to keep track of parents, children, and siblings, and trace the relationships step by step.

Hmm.. I think you may be right about that! I'll try to think a way to solve this, but I am afraid that even if I manage, it will be too time-consuming to be viable. (at least implemented in my crapy, amateur way :smallredface:)

Fshy94
2013-04-13, 02:35 PM
No, you've done good. You should model a few additional things, IMO -- make a class for each creature type, and make a "death" effect at random stages of each individuals life, dependent on creature type.

Then we can accurately model step 2, and for bonus points, we can regionalize populations based on locations in a simple map, and account for cross-regional travel and localization. If you want me to give you some help, I'd be happy to try -- Python is not my primary language, but its a rather fun language to play with.

King of Nowhere
2013-04-13, 02:56 PM
right, regionalization. THe simulation consider that any dragon has an equal chance of mating any other dragon, while in truth they are more likeloy to hang up woth someone living close.
That should reduce the impact of the familicide in a real population.

VanaGalen
2013-04-13, 03:09 PM
Hmm.. I think you may be right about that! I'll try to think a way to solve this, but I am afraid that even if I manage, it will be too time-consuming to be viable. (at least implemented in my crapy, amateur way :smallredface:)

Actually, if life expectancy and number of children are fixed, step 2 should be pretty simple, as every member of the population affected by step 2 has exactly the same family structure - 1 sibling, 2 parents, 2 uncles/aunts, 4 cousins and so on. Anyway, with relatively short lifespan and many generations, I suppose the number of deaths during step 2 is negligible compared to step 1.

Of course for more realistic simulation these numbers shouldn't be fixed, but that would require random variables for the time of death and another one for reproduction. But I think your approximation is really good - it's fast and gives the general idea how the number of generations influence the number of deaths.

F.Harr
2013-04-13, 03:43 PM
"I did it with Python and I will try to post the code in a spoiler box at the end of the post. Of course anybody who wants to run it himself or check the code to find all the enourmous mistakes I made, can ask me and I will happily send it"

Cool!

RunicLGB
2013-04-13, 07:52 PM
That sir(or madame as the case may be) is awesome.

I'm not sure How much Dnd you want to inject into this but one of the complications with dragons is their unusual mortality rate, and reproductive leniency.

Ignoring their non dragon mates definitely simplifies things. But even then a dragon can live through far more than just two generations, since they can live essentially indefinitely unless killed by treasure hunting adventurers. In an unintuitive bit of logic from a real world perspective, the Dragon mortality rate actually decreases with age since they grow in power as they grow older, meaning they are less likely to die.

I'm not sure if it was ever officially stated by the Giant, but some sources describe the Dragon that V hit with Familicide as being "Ancient". In Dnd terms that makes the Dragon somewhere between 800 and 1000 years old. So she could have quite a few living descendants, and even seniors.

Dragon Reproduction according to the Draconomicon: Dragons are fertile between the young aldult and and very old phase, or up to wyrm for Males. Using just females, that means the fertile period is between the ages of 50, and 800. so 750 years of potential breeding. Further Draconomicon states that a dragon lays eggs and fertilizes them i clutches of 2-5, as often as once a year.

Assuming a slower breeding rate to fit V's comment: Lets assume the dragons in oots breed only every ten years or so, with 1-4 eggs in a clutch. 75 chances to breed with 2.5 average eggs, the purely average Dragon that survives to Ancient status will have about 187 children in its lifespan.

Now I don't know what kind of mortality rate should be applied to dragons of any age, nor do I believe for a sec the giant took this must consideration in calculating the actual birth rate of dragons, I just thought this was some interesting math.

:smallsmile:

Edit: In fact I liked the math so much I continued!

If any of you crazy awesome programmers do decide to account for dragon age and mortality, you could use a flat % to account. Essentially check with a random chance, each dragon at each age change and each 50 year mark according to its current age with a survival as such:

wyrmling: <5 years, 8% survival.
Very Young: 5<15 16% Suvival
Young: 16<25 24% survival
Juvenile: 26<50 32% Survival
Young Adult: 51<100, 40% Survival, Breeding starts here. Spawns 2.5 Wyrmlings every 10 years.
Adult: 101<200, 48% Survival
Mature Adult: 201<400, 56% Survival
Old: 401<600, 64 % Survival
Very Old: 601<800, 72% Survival
Ancient: 801<1000, 80% Survival, NO MOre Breeding.
Wyrm: 1001<1200, 88% Survival
Great Wyrm: 1201+, 96% Survival.

Halaku
2013-04-14, 05:58 AM
No, you've done good. You should model a few additional things, IMO -- make a class for each creature type, and make a "death" effect at random stages of each individuals life, dependent on creature type.

It could be interesting to spread it to cover different species. You could create a class "individual" with subclases "dragon", "human" and so on.. But I just can't imagine how to make it work.. too many variables to take into account. But if you have any ideas, I'm listening! :smalltongue:

I thought already about adding a death effect. But then you should increase the birth rate as well to balance the population and you risk both extinction and overpopulation.
I see the way it is done as: "every family has 2 or more children, but only 2 of them are alive and capable of mate." If you think about it, any children who is born but dies without passing its blood lines is not important in our calculations.
Something that could be done to produce the same "random" effect to mess the family trees, and I think it would be easier to implement is to create a "random" number of children (maybe from 0 to 4, with balanced probabilities). If a couple produces no children, it may represent that they had 3 children but all of them died. What do you think?


Actually, if life expectancy and number of children are fixed, step 2 should be pretty simple, as every member of the population affected by step 2 has exactly the same family structure - 1 sibling, 2 parents, 2 uncles/aunts, 4 cousins and so on. Anyway, with relatively short lifespan and many generations, I suppose the number of deaths during step 2 is negligible compared to step 1

It is not so easy. You need to find them, since all the dragons are "mixed" together in one big list. And these little bastards don't have surnames :smallfurious: just a string of numbers with their BLs. Anyway, I think I got how to do it. It's a little tricky but I will try to explain it.


If any of you crazy awesome programmers do decide to account for dragon age and mortality, you could use a flat % to account. Essentially check with a random chance, each dragon at each age change and each 50 year mark according to its current age with a survival as such:

wyrmling: <5 years, 8% survival.
Very Young: 5<15 16% Suvival
Young: 16<25 24% survival
Juvenile: 26<50 32% Survival
Young Adult: 51<100, 40% Survival, Breeding starts here. Spawns 2.5 Wyrmlings every 10 years.
Adult: 101<200, 48% Survival
Mature Adult: 201<400, 56% Survival
Old: 401<600, 64 % Survival
Very Old: 601<800, 72% Survival
Ancient: 801<1000, 80% Survival, NO MOre Breeding.
Wyrm: 1001<1200, 88% Survival
Great Wyrm: 1201+, 96% Survival.

I think I don't understand your numbers. Each percentage is the probability to survive to see the next age category? In this case, a newborn dragon has a probability to reach the young adult age of 0,1%. Even with 2.5 Spawns every 10 years the race would dissapear :smallconfused:
Also, the ABD said that it was "her only child" so I don't think the dragons in the OOtS universe work like that. I imagine them more like the big mammals: just one (or maybe 2) children at a time, and slow reproductive cicles.
But I like the idea that some members of the older generations may life past the "three generations barrier". I will try that as well!


right, regionalization. THe simulation consider that any dragon has an equal chance of mating any other dragon, while in truth they are more likeloy to hang up woth someone living close.
That should reduce the impact of the familicide in a real population.

That is interesting. Different population with scarce mixing (maybe 1 or 2% of the population per generation) should affect the numbers. It could be done with 3 populations, representing the northern, southern and western continent.

Anyway, I think I managed to implement the step 2 in the right way. It's hard to explain but I will try :smallsmile:
The way I've done it requires that 3 generations are alive at the moment the spell is cast. Later I think I will try to generalize it to the case where several generations are on the field at the same time.
It works like that: Every dragon has a unique sequence of Blood Lines that represents him (and his brother/sister). This sequence can be treated as some sort of "adn" to track the family relationships. The number of digits of this "adn" is always a power of 2: "1" for Gen.1, "2" for Gen.2, "4" for Gen.3 and so on.
We can divide the "adn" of a given dragon to get their parents': the first half is actually what defines "dad" and the second half what defines "mum". If we divide again, the first quarter is "granpa1", the second "granma1", the third "granpa1" and the forth "grandma2". (the length of these strings depends on the number of generations passed, but it's not really important). Every of these divisions is a "gene" and can be used to track the effect of the second step (instead of share a blood line, the victim has to share the whole "gene")
I hope it is clear!! :smallsmile:


The results (with the new 2º step):

- 4 Generations, 500 Dragons: Around 9% dead
- 4 Generations, 100 Dragons: Around 40% dead
- 5 Generations, 500 Dragons: Around 29% dead
- 5 Generations, 1000 Dragons: Around 16% dead
- 6 Generations, 1000 Dragons: Around 49% dead
- 6 Generations, 5000 Dragons: Around 13% dead
- 7 Generations, 5000 Dragons: Around 41% dead

As you can see, the numbers are quite lower with the new method, specially at higher generations. I could go on and try to

I also tried a couple of simulations with bigger number, to see what would happend if Haerta casted the spell on human populations (not much bigger, since they already take a few minutes to complete a single try)
- 8 Generations, 50000 Humans: Around 19% dead
- 10 Generations, 50000 Humans: Around 94% dead

I think the initial Human populations should be at least a million (for the whole world, I think it sounds reasonable). If Haerta lived during the first couple centuries, she should feel safe casting it without destroying the whole humanity (not that she cares, anyway) :smallwink:


The new code: (I also added some helping functions, to describe populations and so on.

import random

class Dragon (object):
"""
Represents a dragon"
"""
def __init__(self, BloodLines, Generation):
"""
BloodLines must be a List
Generation must be an integer
"""
self.BloodLines = BloodLines
self.Alive = True
self.Generation = Generation

def Kill (self):
self.Alive = False


def Mate (Mate1, Mate2):
"""
Dragon1 and Dragon2 are instances of class Dragon
Returns a list with 2 equal Dragons, both with all the blood lines of th parents
"""
NewBloodLines = Mate1.BloodLines + Mate2.BloodLines
Generation = Mate1.Generation+1
Offspring1 = Dragon(NewBloodLines, Generation)
Offspring2 = Dragon(NewBloodLines, Generation)
return [Offspring1, Offspring2]

def CreateGeneration (OldGeneration):
"""
Imput: A Generation of Dragons (a list of instances Dragon, all with the same number of BloodLines
Output: A new generation of Dragons after the old mated with random partners. Every Dragon has double number of blood lines as the previos one
"""

if (len(OldGeneration) % 2) != 0:
return ("Can't create a new Generation from ",OldGeneration, "The number of parents must be even")
ClonGeneration = OldGeneration[:]
random.shuffle(ClonGeneration)
NewGeneration = []

while len(ClonGeneration) > 0:
Mate1 = ClonGeneration.pop()
Mate2 = ClonGeneration.pop()
Offspring = Mate(Mate1, Mate2)
NewGeneration += Offspring
return NewGeneration

def AddGeneCodes(Victim, LastGeneration, GeneCodesSecondStep):
if Victim.Generation == (LastGeneration-2):
Gene = Victim.BloodLines
if Gene not in GeneCodesSecondStep:
GeneCodesSecondStep.append(Gene)
if Victim.Generation == (LastGeneration-1):
Gene = Victim.BloodLines[:(len(Victim.BloodLines)/2)]
if Gene not in GeneCodesSecondStep:
GeneCodesSecondStep.append(Gene)
Gene = Victim.BloodLines[(len(Victim.BloodLines)/2):]
if Gene not in GeneCodesSecondStep:
GeneCodesSecondStep.append(Gene)
if Victim.Generation == (LastGeneration):
Gene = Victim.BloodLines[:(len(Victim.BloodLines)/4)]
if Gene not in GeneCodesSecondStep:
GeneCodesSecondStep.append(Gene)
Gene = Victim.BloodLines[(len(Victim.BloodLines)/4):(len(Victim.BloodLines)/2)]
if Gene not in GeneCodesSecondStep:
GeneCodesSecondStep.append(Gene)
Gene = Victim.BloodLines[(len(Victim.BloodLines)/2):(3*len(Victim.BloodLines)/4)]
if Gene not in GeneCodesSecondStep:
GeneCodesSecondStep.append(Gene)
Gene = Victim.BloodLines[(3*len(Victim.BloodLines)/4):]
if Gene not in GeneCodesSecondStep:
GeneCodesSecondStep.append(Gene)
def Familicide (Dragon, DragonPopulation, LastGeneration):
"""
Imput: An instance of the class Dragon (the objective of the spell) and the whole population of dragons (all the living generations, as a whole list
Output: a new list with the surviving Dragons"
"""

BloodLinesFirstStep = []
GeneCodesSecondStep = []
DeadDragons = 0
DeadDragonsFirstStep = 0

"First the blood lines used in the first step are added"
for BloodLine in Dragon.BloodLines:
if BloodLine not in BloodLinesFirstStep:
BloodLinesFirstStep.append(BloodLine)


"searchs every dragon and every blood line for the first step"
for Victim in DragonPopulation:
for BloodLine in BloodLinesFirstStep:

"checkst that the victim is an objective and is not already dead"
if BloodLine in Victim.BloodLines and Victim.Alive == True:
"adds the new *GeneCodes* of the victim for the second step, and kills it"
AddGeneCodes(Victim, LastGeneration, GeneCodesSecondStep)
Victim.Kill()

"""
this lines show how many are killed during the first step
"""
## for dragon in DragonPopulation:
## if dragon.Alive == False:
## DeadDragonsFirstStep +=1
## print "the dragons killed in the first step are", DeadDragonsFirstStep, "the percentage is ",(100.0*DeadDragonsFirstStep/len(DragonPopulation))

"starts the second step"
for Victim in DragonPopulation:
if Victim.Alive == True:
GenesVictim = []
if Victim.Generation == (LastGeneration -2):
Gene = Victim.BloodLines
GenesVictim.append(Gene)
if Victim.Generation == (LastGeneration-1):
Gene = Victim.BloodLines[:(len(Victim.BloodLines)/2)]
GenesVictim.append(Gene)
Gene = Victim.BloodLines[:(len(Victim.BloodLines)/2)]
GenesVictim.append(Gene)
if Victim.Generation == (LastGeneration):
Gene = Victim.BloodLines[:(len(Victim.BloodLines)/4)]
GenesVictim.append(Gene)
Gene = Victim.BloodLines[(len(Victim.BloodLines)/4):(len(Victim.BloodLines)/2)]
GenesVictim.append(Gene)
Gene = Victim.BloodLines[(len(Victim.BloodLines)/2):(3*len(Victim.BloodLines)/4)]
GenesVictim.append(Gene)
Gene = Victim.BloodLines[(3*len(Victim.BloodLines)/4):]
GenesVictim.append(Gene)
"checkst that the victim is an objective and is not already dead"
for Gene in GenesVictim:
if Gene in GeneCodesSecondStep:
Victim.Kill()
break
## print "the Gene Pool for the second step is", GeneCodesSecondStep

"""
Counts and returns the count of dead dragons
"""

for dragon in DragonPopulation:
if dragon.Alive == False:
DeadDragons +=1
return (100.0*DeadDragons/len(DragonPopulation))


def BuildPopulation (NumGen, DragonsPerGen):
FirstGeneration = []
ListGenerations = []
GlobalPopulation = []
"""
These lines create the first generation
"""
for dragon in range (DragonsPerGen):
NewDragon = Dragon([dragon],1)
FirstGeneration.append(NewDragon)
ListGenerations.append(FirstGeneration)
for Generation in range (NumGen - 1):
ListGenerations.append(CreateGeneration(ListGenera tions[-1]))
if len(ListGenerations) > 3:
ListGenerations.remove(ListGenerations[0])
"""
this line represents that the older generation dies of old age when their grand-grandchildren are born, thus keeping the population constant
"""
for Generation in (ListGenerations):
GlobalPopulation += Generation
return(GlobalPopulation)

def DescribePopulation (Population):
for dragon in Population:
print "BloodLines=",dragon.BloodLines, "///","Generation=", dragon.Generation, "///", "Alive=", dragon.Alive


def RunSimulation (numTrials, NumGen, DragonsPerGen):
ListResults = []
total = 0
for n in range (numTrials):
Population = BuildPopulation(NumGen,DragonsPerGen)
## Objective = random.choice(Population)
"""With this line of code, the spell targets a random dragon"""
Objective = Population[-(DragonsPerGen+1)]
"""With this line of code, the spell targets the equivalent to the ABD"""
Result = Familicide(Objective,Population,NumGen)
print Result
ListResults.append(Result)
for a in ListResults:
total +=a
return (total/len(ListResults))

RunicLGB
2013-04-14, 08:25 AM
The numbers could easily be tweaked into the Draconomicons normal rate then: 3.5 eggs every 1 year. More than 10 times as many dragons born. With the very low survival rate at young years it makes quite a bit of sense for the ABD to only have one child, one child who survived at any rate.

However I do agree that they most likely don't work that way in oots, since as stated the giant prob don't go that deep into the rules for details.

137beth
2013-04-14, 11:41 AM
Something to take into consideration is what The Giant said (http://www.giantitp.com/forums/showpost.php?p=12856280&postcount=1034),

So, it wouldn't completely wipe out the human race.

This only applies to protecting people in step 2 of familicide. For human-like conditions, all humans would be killed from step one, and step 2 would do nothing.

Anyways, nice job:smallbiggrin:

Dr.Epic
2013-04-14, 11:52 AM
After reading the last argument about the Familicide (if it's posible, if it would wipe the whole OoTS world, etc...)

Then it'd be called the genocide spell.

Halaku
2013-04-17, 03:14 PM
Then it'd be called the genocide spell.

I read this argument at the main thread and I don't really see the point. If Haerta lived and developed the spell during the first couple hundred years (6-7 generations) it would have killed from a few dozens to a few thousand people and maybe she just didn't consider (or care) what would happend if her spell was casted a thousand yeras later. ( I know we don't know that for sure, but it looks like the more logical explanation for me)

I also worked again on the program to allow the modification of the different variables (isolated populations, death rate, birth rate and so on) and playing with them is easy to get almost any result.
Therefore, the estimation given by V is quite in the range of the posible (which was the point of this whole thread) :smallsmile:

Out of curiosity, I modified the program to calculate the amount of humans killed by V's spell (counting only the effect of the draketooth family, not other interbreeding) and the number ranges between a couple of hundreds and a couple of thousends, depending on the birth rate and how many generations away from the dragon are we (5 are shonw in the diagram at the wall, but I also did it with 6). Quite an impresive number!!

I write the final code, in case anybody is curious :smalltongue:



"""
Features of this update:
- The new "step 2" is implemented
- The may be individuals from 4 or more generations together
- A generation with odd number of members can reproduce
- The Familicide Functinon no longer requires the LastGeneration as an Imput (it calculates itself)
- Allows several isolated populations
- The number of children is random allowing some family branches to take over the others
"""

import random

class Creature (object):
"""
Represents a dragon"
"""
def __init__(self, BloodLines, Generation):
"""
BloodLines must be a List
Generation must be an integer
"""
self.BloodLines = BloodLines
self.Alive = True
self.Generation = Generation

def Kill (self):
self.Alive = False

class Dragon (Creature):
def __init__(self, BloodLines, Generation):
Creature.__init__(self, BloodLines, Generation)

class Human (Creature):
def __init__(self, BloodLines, Generation):
Creature.__init__(self, BloodLines, Generation)

def Mate (Mate1, Mate2, BirthRate):
"""
Dragon1 and Dragon2 are instances of class Dragon
Returns a list with 2 equal Dragons, both with all the blood lines of th parents
"""
NewBloodLines = Mate1.BloodLines + Mate2.BloodLines
Generation = Mate1.Generation+1
NumberOfChildren = random.random()

if BirthRate == 1:
Offspring1 = Dragon(NewBloodLines, Generation)
Offspring2 = Dragon(NewBloodLines, Generation)
return [Offspring1, Offspring2]

if BirthRate == 2:
Prob1 = 0.2
Prob2 = 0.4
Prob3 = 0.6
Prob4 = 0.8
Prob5 = 1

if BirthRate == 3:
Prob1 = 0.1
Prob2 = 0.3
Prob3 = 0.7
Prob4 = 0.9
Prob5 = 1

if NumberOfChildren <= Prob1:
return []
if Prob1 < NumberOfChildren <= Prob2:
Offspring = Dragon(NewBloodLines, Generation)
return [Offspring]
elif Prob2 < NumberOfChildren <= Prob3:
Offspring1 = Dragon(NewBloodLines, Generation)
Offspring2 = Dragon(NewBloodLines, Generation)
return [Offspring1, Offspring2]
elif Prob3 < NumberOfChildren <= Prob4:
Offspring1 = Dragon(NewBloodLines, Generation)
Offspring2 = Dragon(NewBloodLines, Generation)
Offspring3 = Dragon(NewBloodLines, Generation)
return [Offspring1, Offspring2, Offspring3]
elif Prob4 < NumberOfChildren <= Prob5:
Offspring1 = Dragon(NewBloodLines, Generation)
Offspring2 = Dragon(NewBloodLines, Generation)
Offspring3 = Dragon(NewBloodLines, Generation)
Offspring4 = Dragon(NewBloodLines, Generation)
return [Offspring1, Offspring2, Offspring3, Offspring4]


def CreateGeneration (OldGeneration, BirthRate):
"""
Imput: A Generation of Dragons (a list of instances Dragon, all with the same number of BloodLines
Output: A new generation of Dragons after the old mated with random partners. Every Dragon has double number of blood lines as the previos one
"""

ClonGeneration = OldGeneration[:]
random.shuffle(ClonGeneration)
NewGeneration = []
if (len(OldGeneration) % 2) != 0:
ClonGeneration.remove(ClonGeneration[0])
while len(ClonGeneration) > 0:
Mate1 = ClonGeneration.pop()
Mate2 = ClonGeneration.pop()
Offspring = Mate(Mate1, Mate2, BirthRate)
NewGeneration += Offspring
return NewGeneration


def MixPopulations (pop1, pop2):
"""
enters 2 list, of dragons and exchanges one random member of each one
"""
inmigranta = pop1.pop(random.randrange(len(pop1)))
inmigrantb = pop2.pop(random.randrange(len(pop2)))
pop1.append(inmigrantb)
pop2.append(inmigranta)


def DescribePopulation (Population):
for dragon in Population:
print "BloodLines=",dragon.BloodLines, "///","Generation=", dragon.Generation, "///", "Alive=", dragon.Alive

def BriefDescribePopulation (Population):
LowerGeneration = Population[0].Generation
LastGeneration = Population[0].Generation
SortedPopulation = {}
for dragon in Population:
if dragon.Generation in SortedPopulation:
SortedPopulation[dragon.Generation] += 1
else:
SortedPopulation[dragon.Generation] = 1

## for n in SortedPopulation:
## if n>LastGeneration:
## LastGeneration = n
## if n<LowerGeneration:
## LowerGeneration = n
## for dragon in Population:
## if dragon.Generation > LastGeneration:
## LastGeneration = dragon.Generation
## if dragon.Generation < LowerGeneration:
## LowerGeneration = dragon.Generation

print "this population contains:", len(Population), "individuals, sorted as follows"
for n in SortedPopulation:
print SortedPopulation[n], "individuals of the", n, "generation"

def PassOfTime(ListGenerations, DeadRate):
"""
Input: a Population with several generations
Output: the same Population after some of the old dragons die of old age
"""

## if len(ListGenerations) > 3:
## ListGenerations.remove(ListGenerations[0])
if DeadRate == 3:
if len(ListGenerations) > 3:
ListGenerations.remove(ListGenerations[0])
for dragon in ListGenerations[1]:
if random.random() > 0.75:
ListGenerations[1].remove(dragon)
for dragon in ListGenerations[0]:
if random.random() > 0.5:
ListGenerations[0].remove(dragon)

else:
if DeadRate == 1:
Prob1 = 0.90
Prob2 = 0.7
Prob3 = 0.3
Prob4 = 0.2

if DeadRate == 2:
Prob1 = 0.75
Prob2 = 0.5
Prob3 = 0.2
Prob4 = 0.1


for generation in ListGenerations:
if len(generation) == 0:
ListGenerations.remove(generation)
else:
if (len(ListGenerations)- ListGenerations.index(generation)) == 2:
for dragon in generation:
if random.random() > Prob1:
generation.remove(dragon)
if (len(ListGenerations)- ListGenerations.index(generation)) == 3:
for dragon in generation:
if random.random() > Prob2:
generation.remove(dragon)
if (len(ListGenerations)- ListGenerations.index(generation)) == 4:
for dragon in generation:
if random.random() > Prob3:
generation.remove(dragon)
if (len(ListGenerations)- ListGenerations.index(generation)) > 4:
for dragon in generation:
if random.random() > Prob4:
generation.remove(dragon)


def BuildPopulation (NumGen, DragonsPerPop, NumPopulations, BirthRate, MixPercentage, DeadRate):

DragonsPerGen = DragonsPerPop * NumPopulations

FirstGeneration = []
ListGenerations = []
ListPopulations = []
GlobalPopulation = []
MixTotal = int(round(MixPercentage*DragonsPerPop))



"""
Creates the fist generations
"""
for dragon in range (DragonsPerGen):
NewDragon = Dragon([dragon],1)
FirstGeneration.append(NewDragon)

"""
Separates the generation into different populations"
"""
for n in range (NumPopulations):
Population = [FirstGeneration[0:DragonsPerPop]]
for aux in range (DragonsPerPop):
FirstGeneration.remove(FirstGeneration[0])
ListPopulations.append(Population)

for Generation in range (NumGen - 1):
"""
mixing a bit the differentn populations. One dragon/per population is exchanged with one dragon of a random population
"""
if NumPopulations > 1:
for Population in ListPopulations:
for n in range(MixTotal):
Pop2 = random.choice(ListPopulations)
## print "the Population number", ListPopulations.index(Population), "exchanges the following individuals with the population number", ListPopulations.index(Pop2)
MixPopulations(Population[-1],Pop2[-1])

for Population in ListPopulations:
"""
This line creates the new generations for each population
"""
Population.append(CreateGeneration(Population[-1],BirthRate))
"""
this function represents that the older generation dies of old age when their grand-grandchildren are born, thus keeping the population constant
"""
PassOfTime(Population, DeadRate)

for Population in ListPopulations:
for Generation in Population:
GlobalPopulation += Generation
return(GlobalPopulation)

def AddGeneCodes(Victim, GeneLength, GeneCodesSecondStep):
"""
adds the gene codes of the victim of the first step to the gene pool used in the second step
"""
ClonBL = Victim.BloodLines[:]
while len(ClonBL) > 0:
Gene = ClonBL[:GeneLength]
del ClonBL[:GeneLength]
if Gene not in GeneCodesSecondStep:
GeneCodesSecondStep.append(Gene)

def Familicide (Dragon, DragonPopulation):
"""
Imput: An instance of the class Dragon (the objective of the spell) and the whole population of dragons (all the living generations, as a whole list
Output: a new list with the surviving Dragons"
"""

BloodLinesFirstStep = []
GeneCodesSecondStep = []
DeadDragons = 0
LowerGeneration = Dragon.Generation
LastGeneration = Dragon.Generation
"""
calculates the generation of the older dragon alive and the lenght of the "gene", to use it in the second step of the spell and the last generation born
"""
for dragon in DragonPopulation:
if dragon.Generation < LowerGeneration:
LowerGeneration = dragon.Generation
GeneLength = 2**(LowerGeneration-1)
for dragon in DragonPopulation:
if dragon.Generation > LastGeneration:
LastGeneration = dragon.Generation


"First the blood lines used in the first step are added"
for BloodLine in Dragon.BloodLines:
if BloodLine not in BloodLinesFirstStep:
BloodLinesFirstStep.append(BloodLine)


"searchs every dragon and every blood line for the first step"
for Victim in DragonPopulation:
for BloodLine in BloodLinesFirstStep:

"checkst that the victim is an objective and is not already dead"
if BloodLine in Victim.BloodLines and Victim.Alive == True:
"adds the new *GeneCodes* of the victim for the second step, and kills it"
AddGeneCodes(Victim, GeneLength, GeneCodesSecondStep)
Victim.Kill()

"""
this lines show how many are killed during the first step
"""
## DeadDragonsFirstStep = 0
## for dragon in DragonPopulation:
## if dragon.Alive == False:
## DeadDragonsFirstStep +=1
## print "the dragons killed in the first step are", DeadDragonsFirstStep, "the percentage is ",(100.0*DeadDragonsFirstStep/len(DragonPopulation))

"starts the second step"
for Victim in DragonPopulation:
if Victim.Alive == True:
GenesVictim = []
ClonBL = Victim.BloodLines[:]
while len(ClonBL) > 0:
Gene = ClonBL[:GeneLength]
GenesVictim.append(Gene)
del ClonBL[:GeneLength]
"checkst that the victim is an objective and is not already dead"
for Gene in GenesVictim:
if Gene in GeneCodesSecondStep:
Victim.Kill()
break
## print "the Gene Pool for the second step is", GeneCodesSecondStep

"""
Counts and returns the count of dead dragons
"""

for dragon in DragonPopulation:
if dragon.Alive == False:
DeadDragons +=1
return (100.0*DeadDragons/len(DragonPopulation))

def RunSimulation (numTrials, NumGen, DragonsPerPop, NumPop, GenCasted, Customized = False):
ListResults = []
LowestResult = 100
HighestResult = 0
total = 0
DragonsPerGen = DragonsPerPop*NumPop

if Customized == True:
MixPercentage = int(raw_input("Itroduce the number of individuals exchanged by a population each generation, as a percentage over the number of individuals"))/100.0
BirthRate = int(raw_input("Introduce the desired Birth Rate: *1* for constant, *2* for low variation, *3* for high variation"))
DeadRate = int(raw_input("Introduce the desired Dead Rate among older generations: *1* for low, *2* for high, *3* for extreme"))

else:
BirthRate = 2
DeadRate = 2
MixPercentage = 0.05



for n in range (numTrials):
Population = BuildPopulation(NumGen,DragonsPerPop, NumPop, BirthRate, MixPercentage, DeadRate)
## """With this line of code, the spell targets a random dragon"""
## Objective = random.choice(Population)
"""
with this line of code, the spell targets an objective of the generation provided by the user
"""
for dragon in Population:
if dragon.Generation == GenCasted:
Objective = dragon
break

Result = Familicide(Objective,Population)
if Result > HighestResult:
HighestResult = Result
if Result < LowestResult:
LowestResult = Result
ListResults.append(Result)
for a in ListResults:
total +=a
print "Lowest Mortality Rate is:", LowestResult
print "Highest Mortality Rate is:", HighestResult
print "Average Mortality Rate is:", (total/len(ListResults))

Olinser
2013-04-17, 04:37 PM
Then it'd be called the genocide spell.

Remember, V estimated he wiped out 1/4 of the entire Black Dragon population.

I'm not sure you can call something that involves the extermination of 1/4 of a race anything BUT genocide.

Snails
2013-04-17, 05:00 PM
It is perfectly possible that Haerta created a spell that, if she herself were to cast it on a random human, might kill her and possibly the entire human race. Or it is possible that during her own lifespan, the intermixing of the original human specimens were much less progressed, so that some degree of precision was possible. Either extreme or anything in between is plausible.

There is no logical reason to assume something so evil would be practical. Very smart people put great efforts into goals that eventually prove impractical all the time.

Once deceased, it is easy to see why she would like to give it a try.

Dire Lemming
2013-04-17, 07:11 PM
Well, it is "familicide" rather than, say, "genocide" or "vivicide."

Great simulation, incidentally!

Olinser
2013-04-17, 08:47 PM
It is perfectly possible that Haerta created a spell that, if she herself were to cast it on a random human, might kill her and possibly the entire human race. Or it is possible that during her own lifespan, the intermixing of the original human specimens were much less progressed, so that some degree of precision was possible. Either extreme or anything in between is plausible.

There is no logical reason to assume something so evil would be practical. Very smart people put great efforts into goals that eventually prove impractical all the time.

Once deceased, it is easy to see why she would like to give it a try.

It is also possible that, while alive, she crafted it as essentially the 'nuclear deterrent' of the day.

Somewhere along the lines of, "Any do-gooders try to break into my throne room and kill me, the first spell that goes off will wipe half the human race off the planet!"

No reason she had to actually use it while she was alive.

After she was dead... hell yeah, let's try it out!

Souju
2013-04-18, 01:27 AM
i was always of the assumption that Haerta developed the spell but couldn't cast it because her CL wouldn't have been high enough on her own...
then again the ridiculous specificity of the spell makes it seem like it's something she came up with while bored or as a theory.

pendell
2013-04-18, 08:11 AM
Kudos to Halaku for the work. Nicely done!

Respectfully,

Brian P.

Snails
2013-04-18, 10:21 AM
It is also possible that, while alive, she crafted it as essentially the 'nuclear deterrent' of the day.

Somewhere along the lines of, "Any do-gooders try to break into my throne room and kill me, the first spell that goes off will wipe half the human race off the planet!"

No reason she had to actually use it while she was alive.

After she was dead... hell yeah, let's try it out!

Exactly. There is no reason to assume it was a practical spell -- by "practical" I mean a spell she actually did or expected to a cast once or more during her lifetime to her own personal betterment. Just because a spell is not practical does not mean it has no value -- deterrence can be very valuable.

SincroFashad
2013-04-18, 11:28 AM
Has anyone considered that the reason Haerta is dead is because she had cast it at least once, and wiped herself out in the process?

I mean, why isn't an epic-level necro like her running around as a lich? Logically, it means something unexpected happened to her. It's not a huge stretch to go from something unexpected to something self-inflicted. By accident (or insufficient math skillz) of course.

-Sinc

Olinser
2013-04-18, 11:36 AM
Has anyone considered that the reason Haerta is dead is because she had cast it at least once, and wiped herself out in the process?

I mean, why isn't an epic-level necro like her running around as a lich? Logically, it means something unexpected happened to her. It's not a huge stretch to go from something unexpected to something self-inflicted. By accident (or insufficient math skillz) of course.

-Sinc

Why weren't the other two Epic casters liches?

They all seemed at least relatively young. They may simply have been killed before they thought about it too much.

After all, even though Redcloak obviously had the capability, even with Xykon getting EXTREMELY aged, he didn't even consider making the jump until they had no way out.

SincroFashad
2013-04-18, 11:55 AM
I would guess they look young because that's how they see themselves, much like Roy's mom is a young looker with a rack, not an old woman with her hair in a bun.

Also, the 'something unexpected' which got in the way of the epic-level necro being a lich could certainly have occurred at a young age. My only reason for wondering why she's dead and not a lich comes from my own opinion that the ratio of epic-level necromancers which exist that want to become a lich to epic-level necromancers which exist is pretty close to 1:1.

Yes, I know that wanting to be a lich and being able to pull it off aren't the same thing, but we *are* talking about an epic-level caster. Smart money says she would've had the capability.

-Sinc

Snails
2013-04-18, 12:13 PM
Has anyone considered that the reason Haerta is dead is because she had cast it at least once, and wiped herself out in the process?


It is a cute suggestion, but we might as well guess that all three were killed by Haerta accidentally. Presuming that every epic evil spellcaster "should" choose to eventually become undead is pretty dodgy.

Kish
2013-04-18, 12:49 PM
I see no reason to take for granted that Haerta didn't spend some time as a lich, actually.

There's no indication that she died of old age.

Souju
2013-04-18, 09:27 PM
or some other form of undead...vampire maybe?
Oooo new epileptic tree! Haerta was Malack's sire!

skim172
2013-04-19, 01:29 AM
Excellent work on the simulation. Sounds like it was a lot of fun to code, too.

Out of curiosity, because I'm not sure from your original description - did you eliminate all dead people from the calculations? I believe that's how the Giant described the spell.

Presumably, 40 generations wouldn't be enough intermixing to kill all humans if you started off with about a million or so, even if an inordinate amount of dragons seem to be attracted to "soft-skins." But I would say that V's responsible for killing a LOT of people regardless. Elves, dwarves, humans, gnomes - huge numbers of dead. The black dragons probably took the brunt of it, yeah, but still - the other races are probably at the moment experiencing one of the worst mass deaths in any point in history.

Other than if and when Haerta cast it before, of course. I guess I kind of assume she must have - otherwise, how would she know if it worked? Wouldn't it have been just so embarrassing if V cast the spell in that dramatic moment and nothing at all happened?

Perhaps Haerta is what killed off all the flumphs. That's why there's only two left.

Or maybe she's the reason why there are only two lawyers. They're an endangered species. Haerta Familicide'd the Brood Mother inside the Genesis Pit and all the lawyers that had once oozed out of the egg sacs perished. Jones and Rodriguez are the very last of their kind - spawnlings saved by a freak genetic mutation that occurred within their larval cocoons.

Halaku
2013-04-19, 10:55 AM
Excellent work on the simulation. Sounds like it was a lot of fun to code, too.

Out of curiosity, because I'm not sure from your original description - did you eliminate all dead people from the calculations? I believe that's how the Giant described the spell.

Presumably, 40 generations wouldn't be enough intermixing to kill all humans if you started off with about a million or so, even if an inordinate amount of dragons seem to be attracted to "soft-skins." But I would say that V's responsible for killing a LOT of people regardless. Elves, dwarves, humans, gnomes - huge numbers of dead. The black dragons probably took the brunt of it, yeah, but still - the other races are probably at the moment experiencing one of the worst mass deaths in any point in history.

.

The program has 2 main stages. First it "builds" the populations, breeding new generations from the old ones and killing the older individuals. At first I did it the simplest way: every generation was completely eresed when their grand-grandchildren were born, so that only 3 generations were on the field at the same time. This was done before casting the the spell, so for the spell is like they never existed. Then I refined it a little bit, so every individual has a certein probability to die after each generation passes (the probability of dying increases as the individual gets older), and allowed the used to choose between low and high mortality rate.

I also modified the code to try to calculate how many humans were killed by the spell. Of course the number varies a lot depending on how many generations passed, but I got a number between a couple of hundreds and a couple of thousand just from the Draketooth family. (which is quite a big number to be just collateral effect). An interbreeding just a few generations before (somethig like 10 or so) would have done much more damage. Not sure how much because my computer died trying to calculate these numbers.. :smalleek:

SincroFashad
2013-04-19, 02:02 PM
It is a cute suggestion, but we might as well guess that all three were killed by Haerta accidentally. Presuming that every epic evil spellcaster "should" choose to eventually become undead is pretty dodgy.

Agreed, which is why I specified necromancer, as opposed to evil spellcaster. Not every necromancer is necessarily evil (although I suspect many would be) and certainly not every evil spellcaster is a necromancer. I only make that assumption about necromancers because of their inordinate amounts of contact with, and presumably as a result of that amount of contact, familiarity with the workings of undead, both mundane and extraordinary. It's still an assumption, which may or not be right, of course. :)

-Sinc

Olinser
2013-04-19, 04:04 PM
Agreed, which is why I specified necromancer, as opposed to evil spellcaster. Not every necromancer is necessarily evil (although I suspect many would be) and certainly not every evil spellcaster is a necromancer. I only make that assumption about necromancers because of their inordinate amounts of contact with, and presumably as a result of that amount of contact, familiarity with the workings of undead, both mundane and extraordinary. It's still an assumption, which may or not be right, of course. :)

-Sinc

Yes, but by and large, most mortals do not seek to become undead until the later stages of their life, when mortality starts bearing down on them.

Being a lich isn't a goal in itself - it is a means to avoid dying. Most epic wizards don't seriously consider their own mortality until extremely aged, or severely threatened.

For instance, Tsukiko, despite her LOVE for the undead, did not seek to become one herself. I'm guessing when she got on in years she'd start thinking about it, though, but certainly not in the prime of her life.

Amphiox
2013-04-21, 12:20 AM
Why weren't the other two Epic casters liches?

They all seemed at least relatively young. They may simply have been killed before they thought about it too much.

After all, even though Redcloak obviously had the capability, even with Xykon getting EXTREMELY aged, he didn't even consider making the jump until they had no way out.

Why were all three of them not liches (or some other undead)?

Well, it is because, to paraphrase Xykon, they were just schmutzes who didn't have the cojones to stay in the game!

Amphiox
2013-04-21, 12:23 AM
It is certainly not beyond conception that Haerta might have cast familicide and accidentally killed herself in the process.

Or that she crafted the spell that she knew she could never use, just for kicks.

We already have one illustration of "stupid-good" in the story, why not an example of "chaotic-stupid/stupid-evil"?

petersohn
2013-04-21, 01:34 AM
Very nice, I never thought of simulating it. I have one comment on your program. You said that the number of bloodlines each individual has grows exponentially with generations. But if you think about it, the total number of bloodlines in a simulation is fixed. The solution is that instead of an array, you should store the bloodlines in a set (or whatever it's called in Python, I'm not very familiar with that language). Then, when two dragons mate, take the union of the two bloodlines instead of simply appending them.

But anyway, if you choose a large enough number of generations, a familicide would probably kill everyone anyway. Mathematically speaking, as the number of generations approaches infinity, the probability of every individual sharing all of the bloodlines approaches 1. I'll try to figure out the exact formula later. :smallbiggrin:

AgentPaper
2013-04-21, 02:05 AM
An idea to more accurately model things:

Rather than storing arbitrary "bloodlines", instead have each person store only their parents, and their children. From there, you can easily follow the rules of Familicide more accurately:

For step one, simply have the program go through a simple loop, starting with the original target of the spell. First, go to her children, in turn, adding them each to the list of targets, as well as their children, and their children, and so on, until all of her descendants are on the list. After that, add her parents to the list, and do the same thing for their children (the targets brothers and sisters), and their children, et cetera, skipping anyone already on the list. After that's done, go to the original target's grandparents, and repeat it again, then again for the great-grandparents, and so on.

For the second step, you do the same thing for each of the targets, except in addition to skipping anyone who's already on the list, if you run into someone who's dead, you go through that person's children, but don't go to their parents. That way, you get brothers and sisters, and aunts and uncles if the mother/father is still alive, but you don't kill anyone related through non-living ancestors.

This should both more accurately reflect the specifics of the spell, and also allow for much larger simulations, since the amount of information stored for each person is much smaller, and more importantly, doesn't grow as time goes on. I'm not sure, but I think the time it takes to process all the information should go down considerably as well, since you're not going through the entire population, just the affected parties. Just make sure that it skips over anyone already targeted, otherwise you'll waste a lot of time killing the same people multiple times if they're related to the target in more than one way.

Halaku
2013-04-21, 08:09 AM
Very nice, I never thought of simulating it. I have one comment on your program. You said that the number of bloodlines each individual has grows exponentially with generations. But if you think about it, the total number of bloodlines in a simulation is fixed. The solution is that instead of an array, you should store the bloodlines in a set (or whatever it's called in Python, I'm not very familiar with that language). Then, when two dragons mate, take the union of the two bloodlines instead of simply appending them.

But anyway, if you choose a large enough number of generations, a familicide would probably kill everyone anyway. Mathematically speaking, as the number of generations approaches infinity, the probability of every individual sharing all of the bloodlines approaches 1. I'll try to figure out the exact formula later. :smallbiggrin:

I though about doing that (I even did a version who did it). I thought it would reduce the computing time, but I found that it didn't, at least enough for me to notice, so I dropped it. I guess it's because the time you save not storing every bloodline, you lose it searching the list every time for every BL.
It also has another problem: the order of the BLs in each individuals also gives you information about who their ancestors are, which is used on the second step. If you compress the info about the BLs, only storing each of them once, you can't track who their cousins and uncles and so on...


An idea to more accurately model things:

Rather than storing arbitrary "bloodlines", instead have each person store only their parents, and their children. From there, you can easily follow the rules of Familicide more accurately:

For step one, simply have the program go through a simple loop, starting with the original target of the spell. First, go to her children, in turn, adding them each to the list of targets, as well as their children, and their children, and so on, until all of her descendants are on the list. After that, add her parents to the list, and do the same thing for their children (the targets brothers and sisters), and their children, et cetera, skipping anyone already on the list. After that's done, go to the original target's grandparents, and repeat it again, then again for the great-grandparents, and so on.


For the second step, you do the same thing for each of the targets, except in addition to skipping anyone who's already on the list, if you run into someone who's dead, you go through that person's children, but don't go to their parents. That way, you get brothers and sisters, and aunts and uncles if the mother/father is still alive, but you don't kill anyone related through non-living ancestors.

This should both more accurately reflect the specifics of the spell, and also allow for much larger simulations, since the amount of information stored for each person is much smaller, and more importantly, doesn't grow as time goes on. I'm not sure, but I think the time it takes to process all the information should go down considerably as well, since you're not going through the entire population, just the affected parties. Just make sure that it skips over anyone already targeted, otherwise you'll waste a lot of time killing the same people multiple times if they're related to the target in


That is a good idea! I didn't thought about doing that. The main drawback is that you have to store every individual who ever lived, but anyways I think it would make everything faster, specially for a large number of generations.
I'll try it as soon as I can

petersohn
2013-04-21, 12:05 PM
I think that this is a good idea, but maybe you should introduce a generation limit for this one too, otherwise you not only will eat up memory processing time as the number of generations grow, but you will also have most of the dragons killed anyway if the generation number is large enough. So for example you use the last 3 generations for mating, but store the last, say 10 generations for determining relations. So if two dragon doesn't have a common ancestor or child within 10 generations, they are so far away in bloodline that the spell fails to target the other one. Of course, to "realistically" model the OOTS world, you should use larger numbers than that, but it wouldn't be feasible to simulate 50 generations of 100 000 dragons or so.

Anyway, did you think about the fact that should Tarquin and Penelope had had a child, Elan would be dead by now (as well as Tarquin and Nale, of course)? :smalleek:

JustWantedToSay
2013-04-21, 02:05 PM
Perhaps a limit based on human chromosomes.

using the formula:
1 - ( 2^n -1 / 2^n )^46
46 being the number of chromosomes people have. 'n' being the number of generations back or down. So parents are generation n=1.

n=3 Statistically all your eight great-grandparents are related to you by chromosomes (99.79% chance for each one sharing a chromosome)

n=4 sixteen great-great-grandparents: on average, only 15 of them passed chromosomes to you. (94.86%)

n=5 thirty-two great*3-grandparents: on average 24 or 25 will share a chromosome.
(76.79% chance average chance, last generation that it's possible for all to be related.)

n=6 sixty-four great*4-grandparents. 33 on average share a chromosome
(51.54%, at least 18 must not share a chromosome.)

n=7 one-hundred-twenty-eight g*5 grandparents. ~39 sharing.
(30.29%-- outside of the sigma-1 value.)

So perhaps it should only go to 6 generations either way, since odds are that any one random 7th gen ancestor/descendant is not actually related to you by chromosomes.

Now unfortunately this doesn't account for the fact that your ancestors might share chromosomes (so you could have one in common even though it didn't come from them).