Bay 12 Games Forum

Please login or register.

Login with username, password and session length
Advanced search  

Author Topic: [WIP] Dwarven marriage test (dmt.lua)  (Read 2900 times)

utunnels

  • Bay Watcher
  • Axedwarf
    • View Profile
[WIP] Dwarven marriage test (dmt.lua)
« 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.

Code: [Select]
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
« Last Edit: April 16, 2015, 09:58:21 am by utunnels »
Logged
The troglodyte head shakes The Troglodyte around by the head, tearing apart the head's muscle!

Risen Asteshdakas, Ghostly Recruit has risen and is haunting the fortress!

Putnam

  • Bay Watcher
  • DAT WIZARD
    • View Profile
Re: [WIP] Dwarven marriage test (dmt.lua)
« Reply #1 on: April 16, 2015, 09:51:40 pm »

Number of valid breeding couples = (n2 - n) / 2, where n is total number of eligible opposite-sex marry units.

Shipping science.
« Last Edit: April 16, 2015, 09:53:26 pm by Putnam »
Logged

utunnels

  • Bay Watcher
  • Axedwarf
    • View Profile
Re: [WIP] Dwarven marriage test (dmt.lua)
« Reply #2 on: April 16, 2015, 10:30:29 pm »

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


.....



« Last Edit: April 16, 2015, 10:37:36 pm by utunnels »
Logged
The troglodyte head shakes The Troglodyte around by the head, tearing apart the head's muscle!

Risen Asteshdakas, Ghostly Recruit has risen and is haunting the fortress!

Putnam

  • Bay Watcher
  • DAT WIZARD
    • View Profile
Re: [WIP] Dwarven marriage test (dmt.lua)
« Reply #3 on: April 16, 2015, 10:37:40 pm »

Oh, total sets of couples as opposed to total sets of pairings, okay.

TheKaspa

  • Bay Watcher
    • View Profile
Re: [WIP] Dwarven marriage test (dmt.lua)
« Reply #4 on: April 22, 2015, 03:02:06 am »

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.
Logged
Tai'shar DwarfFortress

I've heard Minecart Airlines Express offers nice trips to nobility. Alternative trips include a voyage over the volcano. Call 1-800-I-THE-GUINEAPIG-VOLUNTEER and book now!
My fucking armok, you broke the game.

Putnam

  • Bay Watcher
  • DAT WIZARD
    • View Profile
Re: [WIP] Dwarven marriage test (dmt.lua)
« Reply #5 on: April 22, 2015, 03:05:55 am »

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.
« Last Edit: April 22, 2015, 03:13:51 am by Putnam »
Logged

TheKaspa

  • Bay Watcher
    • View Profile
Re: [WIP] Dwarven marriage test (dmt.lua)
« Reply #6 on: April 22, 2015, 03:11:29 am »

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
Logged
Tai'shar DwarfFortress

I've heard Minecart Airlines Express offers nice trips to nobility. Alternative trips include a voyage over the volcano. Call 1-800-I-THE-GUINEAPIG-VOLUNTEER and book now!
My fucking armok, you broke the game.

Roses

  • Bay Watcher
    • View Profile
Re: [WIP] Dwarven marriage test (dmt.lua)
« Reply #7 on: April 22, 2015, 08:40:59 am »

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).
Logged

utunnels

  • Bay Watcher
  • Axedwarf
    • View Profile
Re: [WIP] Dwarven marriage test (dmt.lua)
« Reply #8 on: April 23, 2015, 03:51:04 am »

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.
« Last Edit: April 23, 2015, 04:04:10 am by utunnels »
Logged
The troglodyte head shakes The Troglodyte around by the head, tearing apart the head's muscle!

Risen Asteshdakas, Ghostly Recruit has risen and is haunting the fortress!

TheKaspa

  • Bay Watcher
    • View Profile
Re: [WIP] Dwarven marriage test (dmt.lua)
« Reply #9 on: April 23, 2015, 08:53:14 am »

But it doesn't tell that there is only one candidate because already in a relationship, right?
Logged
Tai'shar DwarfFortress

I've heard Minecart Airlines Express offers nice trips to nobility. Alternative trips include a voyage over the volcano. Call 1-800-I-THE-GUINEAPIG-VOLUNTEER and book now!
My fucking armok, you broke the game.

utunnels

  • Bay Watcher
  • Axedwarf
    • View Profile
Re: [WIP] Dwarven marriage test (dmt.lua)
« Reply #10 on: April 23, 2015, 09:56:13 am »

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
Logged
The troglodyte head shakes The Troglodyte around by the head, tearing apart the head's muscle!

Risen Asteshdakas, Ghostly Recruit has risen and is haunting the fortress!

TheKaspa

  • Bay Watcher
    • View Profile
Re: [WIP] Dwarven marriage test (dmt.lua)
« Reply #11 on: April 23, 2015, 10:28:10 am »

Ops, sorry.
I was so concerned with my civ being dead that I overlooked the details
Logged
Tai'shar DwarfFortress

I've heard Minecart Airlines Express offers nice trips to nobility. Alternative trips include a voyage over the volcano. Call 1-800-I-THE-GUINEAPIG-VOLUNTEER and book now!
My fucking armok, you broke the game.