Bay 12 Games Forum
Dwarf Fortress => DF Modding => Utilities and 3rd Party Applications => Topic started by: utunnels on April 16, 2015, 04:06:37 am
-
I want to run a fortress that only breeds using the starting seven. So I'm trying to write a script that prints all possible hetero couples(those who can marry and have children). It is still a WIP, but it can already print all necessary informations(age, orientation and valid mating candidates).
I'm still working on how to calculate the number of valid couples(I haven't do any math for ages so I'm a bit rusty).
For example there are two possible combinations: AB and AC, since A can only marry one from B and C, so there'll be only 1 possible couple.
local utils = require('utils')
local args = utils.processArgs({...})
if args.help then
print('Dwarven marriage test script.')
return
end
local function round(n, d)
local m= 10^(d or 0)
return math.floor(n*m+ 0.5) / m
end
local function getAgeString(unit)
return ''..round(dfhack.units.getAge(unit,true),2)
end
local function getInfoString(unit)
local infStr
if unit.sex==0 then
infStr='female, '
elseif unit.sex==1 then
infStr='male, '
else
infStr=""
end
infStr=infStr..getAgeString(unit)
return '('..infStr..')'
end
--this is from gaydar.lua
local function determineorientation(unit)
if unit.sex~=-1 then
local return_string=''
local orientation=unit.status.current_soul.orientation_flags
local male_interested,asexual=false,true
if orientation.romance_male then
return_string=return_string..' likes males'
male_interested=true
asexual=false
elseif orientation.marry_male then
return_string=return_string..' will marry males'
male_interested=true
asexual=false
end
if orientation.romance_female then
if male_interested then
return_string=return_string..' and likes females'
else
return_string=return_string..' likes females'
end
asexual=false
elseif orientation.marry_female then
if male_interested then
return_string=return_string..' and will marry females'
else
return_string=return_string..' will marry females'
end
asexual=false
end
if asexual then
return_string=' is asexual'
end
return return_string
else
return "is not biologically capable of sex"
end
end
local function nameOrSpeciesAndNumber(unit)
if unit.name.has_name then
return dfhack.TranslateName(dfhack.units.getVisibleName(unit))..' '..getInfoString(unit),true
else
return 'Unit #'..unit.id..' ('..df.creature_raw.find(unit.race).caste[unit.caste].caste_name[0]..getInfoString(unit)..')',false
end
end
local validcitizens={}
for k,v in ipairs(df.global.world.units.active) do
if dfhack.units.isCitizen(v)
and ((v.sex==0 and v.status.current_soul.orientation_flags.marry_male)
or (v.sex==1 and v.status.current_soul.orientation_flags.marry_female)) then
table.insert(validcitizens,{v,nameOrSpeciesAndNumber(v) .. determineorientation(v)})
end
end
local validpairs = {}
local validcount = {[0]=0,[1]=0}
local function checkAndAddValidPair(p)
--sort first
if p[1].sex==1 then
local t = p[1]
p[1] = p[2]
p[2] = t
end
for j,v in ipairs(validpairs) do
if p[1]==v[1] and p[2]==v[2] then
return false
end
end
table.insert(validpairs,p)
return true
end
-- only find valid couples
for k,v in ipairs(validcitizens) do
print(v[2])
if v[1].relations.spouse_id~=-1 then
print(' Already has a spouse')
end
if v[1].relations.lover_id~=-1 then
print(' Already has a lover')
end
local valid = false
for i,x in ipairs(validcitizens) do
if x[1]~=v[1] and x[1].sex~=v[1].sex then
if v[1].relations.spouse_id==x[1].id or v[1].relations.lover_id==x[1].id then
print(' '..dfhack.TranslateName(dfhack.units.getVisibleName(x[1]))..' (arranged)')
checkAndAddValidPair({v[1],x[1]})
valid = true
elseif v[1].relations.lover_id==-1 and v[1].relations.spouse_id==-1
and x[1].relations.lover_id==-1 and x[1].relations.spouse_id==-1
and math.abs(dfhack.units.getAge(x[1],true)-dfhack.units.getAge(v[1],true))<10 then
print(' '..dfhack.TranslateName(dfhack.units.getVisibleName(x[1])))
checkAndAddValidPair({v[1],x[1]})
valid = true
end
end
end
if valid then
validcount[v[1].sex] = validcount[v[1].sex]+1
end
end
print('')
print('There are ' ..math.min(validcount[1],validcount[0]).. ' possible valid couples')
for k,v in ipairs(validpairs) do
print(' '..dfhack.TranslateName(dfhack.units.getVisibleName(v[1]))..' x '..dfhack.TranslateName(dfhack.units.getVisibleName(v[2])))
end
-
Number of valid breeding couples = (n2 - n) / 2, where n is total number of eligible opposite-sex marry units.
Shipping science. (http://www.mspaintadventures.com/?s=6&p=006871)
-
Sorry maybe I didn't describe my goal clearly.
I figured out the result should be min(n_male, n_female), where n_male and n_female is corresponding total number of each gender among all valid pairs.
For example, there are 5 dorfs A,B,C,D & E, A & E are female, B,C & E are male, and there are 3 possible pairs, like this:
A--B
A--C
D--E
There are 2 possible couples, either (A--B and D--E), or (A--C and D--E).
1--4
A--B
A--C
A--E
A--F
result: 1
2--3
A--B
A--C
D--B
D--E
reulst:2
A--B, D--E
or
A--C, D--E
or
A--C, D--B
.....
-
Oh, total sets of couples as opposed to total sets of pairings, okay.
-
I tried your script and found it very useful.
I have three possible couples, one of which is already with child and another one is still on "lover" stage.
Would it be possible to extend it to check if the couple is formed or at least on lover status?
I don't know how to mod, but I suppose it requires only to check into relationships.
-
Even I do not know how to check relationships. (mainly because i haven't bothered to find out yet :P)
Checking if a couple is already formed, however, is as simple as checking if unit.relations.lover_id~=-1 or unit.relations.spouse_id~=-1.
-
Exactly what I was looking for. A way to check if said dwarf is a spouse or a lover.
I will toy with this once at home
-
I noticed when playing around with the relationship screen that you can find the types of relationships they have and even the "level" they are at, but I couldn't find where that information was actually stored (i.e. where the screen got the info).
-
I tried your script and found it very useful.
I have three possible couples, one of which is already with child and another one is still on "lover" stage.
Would it be possible to extend it to check if the couple is formed or at least on lover status?
I don't know how to mod, but I suppose it requires only to check into relationships.
The script already does. It will not print other candidates if said dwarf already has a spouse or lover.
However if you want to trace a family tree the relation screen is a better choice.
Also I don't know if children can have some sort of relationships. For example, two dwarven babies who grow up together. Will they become lovers when they both turn 12 years old?
edit*
Oh, maybe it should filter those children.
-
But it doesn't tell that there is only one candidate because already in a relationship, right?
-
Oh, it does. But the information was print before the list.
Something like this:
Mebzuth Avuzenkos (male, 70.58) will marry females
Already has a lover
Rakust Mosusnunok (arranged)
Rakust Mosusnunok (female, 66.25) will marry males and likes females
Already has a lover
Mebzuth Avuzenkos (arranged)
Bembul Oggezrimtar (female, 86.27) will marry males and will marry females
Tobul Egomdatan
Tobul Egomdatan (male, 87.05) will marry females
Bembul Oggezrimtar
Momuz Tosedfath (female, 67.2) will marry males
Urdim Thikutfotthor (male, 52.29) will marry females
There are 2 possible valid couples
Rakust Mosusnunok x Mebzuth Avuzenkos
Bembul Oggezrimtar x Tobul Egomdatan
-
Ops, sorry.
I was so concerned with my civ being dead that I overlooked the details