Bay 12 Games Forum

Please login or register.

Login with username, password and session length
Advanced search  
Pages: [1] 2

Author Topic: What do I need to write this script:  (Read 5111 times)

Nagidal

  • Bay Watcher
    • View Profile
    • My gaming channel
What do I need to write this script:
« on: November 04, 2017, 09:52:11 am »

I am really interested in keeping detailed track of each dwarves' thoughts and preferences. (skills, body and soul attributespersonality traits, ...) I'd like to see which of them change over time, how often they change etc.

There is two things I want to achieve with this:

Goal 1. Sort of a personal file of each dwarf which would track the dwarves' development (take a daily record of his skills, attributes, traits). This would allow me to see how quickly do miners or pump operators grow muscles, how quickly each dwarf gains military skills, etc., use this data for a diachronic analysis. See how often things like worshipped deities, hair color, life ideals and behaviour, change - or if they are constant forever.

Goal 2. A Dwarf-Therapist-like spreadsheet overview of what kinds of pets, items, materials, food, drinks my dwarves like.
Example for pet preference: Obok and Tulon like dogs, Kib likes cows, Udib likes rabbits. Script would output a table like this:
Code: [Select]
PET NAME | NAME1           | NAME2            | NAME3
dog      | Obok Kűbukmamot | Tulon Orrunlikot |
cow      | Kib Tathtatled  |                  |
rabbit   | Udib Gutirurist |                  |


Here is a sketch of what I have in mind in a Python-like pseudo code (Python is currently the only language I can code in). Such script would probably have to run in the background parallel to the game:


Goal 1: A Dwarf's personal file recording his skill values
Code: [Select]
if calendarDateChanged():
    // dump the data about each dwarf into a file named like the dwarf
    for dwarf in fortressMembers:
        file = openFileInAppendMode(dwarf.name+".txt")
        print("Date:", calendar.currentDate(), file)
        print("Strength:", dwarf.strength.getValue(), file)
        print("Willpower:", dwarf.willpower.getValue(), file)
        // ... etc., dump all the info I want to keep track of piece by piece
        // it should probably be an XML dump instead, as I believe there are XML parsers ready to use.
        file.flush() // makes sure the print buffer is actually written into the file on the harddrive


And here is the sketch of the part which would serve to make a spreadsheet of the dwarves favourite pets, items, materials, food, etc.:

Goal 2: Spreadsheet of pets, items, materials, food, drinks which would list the names of dwarves who prefer it
Code: [Select]
// create a dictionary of pets, items, materials. In python a dictionary is an unordered list of (key,value) pairs, which can be evaluated: value = dictionary[key].
// example: pets[dog] would return a set of names of dwarves who like dogs
// initialize the dictionaries
pets = dict()
items = dict()
materials = dict()
for dwarf in fortressMembers:
    // if this dwarf's pet is already listed in the pet dictionary, just add the dwarf to the set of dwarves who like this pet
    try:
        pets[dwarf.favouritePet()].add(dwarf.name)
    // if this dwarf's pet is not yet in the pet dictionary, ...
    except keyError:
    // ... create a new dictionary entry for this pet
        // and assign this dictionary entry a set containing this dwarfs name (later more likeminded dwarves can be added to this set)
        pets[dwarf.favouritePet()] = set([dwarf.name])
    // same procedure for items
    try:
        items[dwarf.favouriteItem()].add(dwarf.name)
    except keyError:
        items[dwarf.favouriteItem()] = set([dwarf.name])
    // ... and materials
    try:
        materials[dwarf.favouriteMaterial()].add(dwarf.name)
    except keyError:
        materials[dwarf.favouriteMaterial()] = set([dwarf.name])

    // =====
    // obviously I would avoid copy-pasting the same procedure for pets, items and materials. I just wrote it down for easier readability.
    // I'd actually use something like this:
    // make tuples of dictionaries and dwarfs interests
    // dictionariesAndInterests = zip(list(pets, items, materials), list(dwarf.favouritePet(), dwarf.favouriteItem(), dwarf.favouriteMaterial())
    // for dictionayOfInterest, dwarfsFavourite in dictionariesAndInterests:
    //     try:
    //         dictionayOfInterest[dwarfsFavourite].add(dwarf.name)
    //     except keyError:
    //         dictionayOfInterest[dwarfsFavourite] = set([dwarf.name])
    // =====
// now dump the whole overview:
// heavily simplified
for dictionary in list(pets, items, materials):
    for key, value in dictionary:
        print(key, value)

If this can be done, can you introduce me to the structure of DF memory and the names of variables which bear the information I'd like to gather?
« Last Edit: November 04, 2017, 10:29:22 am by Nagidal »
Logged
I stream most of my DF sessions: gaming.youtube/nagidal146, they are archived on my youtube channel. (Dwarf Fortress Tutorials)

PatrikLundell

  • Bay Watcher
    • View Profile
Re: What do I need to write this script:
« Reply #1 on: November 04, 2017, 12:26:29 pm »

It can be done, at least mostly, but it's a fair bit of junk to sift through, and a lot of the data is encoded in rather messy ways.

You can either have a script running in the background (soaking up cycles), or use a file to store data between manual runs of a script (read data, update/and compare, write, exit, possibly producing some output in between). It's also possible to store data within DF itself, but I don't know if that is saved when the game is saved.

Your preferences spreadsheet is bound to be rather long, given that dorfs can have preferences for most everything in the game.

Here's a link to the script (it's too large to fit in a post)https://www.dropbox.com/s/igpki9r66o4mm10/thoughts.lua?dl=0.
Logged

Nagidal

  • Bay Watcher
    • View Profile
    • My gaming channel
Re: What do I need to write this script:
« Reply #2 on: November 04, 2017, 01:36:54 pm »

Your preferences spreadsheet is bound to be rather long, given that dorfs can have preferences for most everything in the game.

I know, that's why I would only list those preferred things which matter to the fortress members. If there is nobody in the fortress who likes donkeys, and the script only accumulates favourites of fortress members, donkeys would not appear in the list at all.

Now, reading the Lua script you linked: It looks like it is a script which would print out the things I see when I read the thoughts of a dwarf, right? I see how the values are found and the whole thoughts text is composed. At least the parts we know how they map to the values.

Could you explain the Locator function in more detail? I don't understand how does it limit its scope only to fortress members. How does it ignore invaders, visitors, merchants, animals, and all other historical figures of the world which are not even physically present on the embark map.

This is how I read it (I'm not at all familiar with Lua syntax):

Code: [Select]
function Locator:locate (id, count) // is "Locator" a class and "locate" a method of it?
// I figure its used like this:
// locatorInstance = Locator()
// locatorInstance.locate(23547, 13) would access unitID 23547 and ... what is count used for?
  // declaration of local variables:
  local bottom = 0
  local top = count - 1 // what is the value of count?, whatever, we'd start with 12 (top = 13 - 1)
  local step
  local index // this is the thing the locate() method returns after some math. But what does index represent?
 
  while true do
    step = top - bottom  // step = 12 - 0
    if step == 0 then
      return -1  --  Not found // allright if I call .locate(someID, 0) I'll get -1
    end

    // This rest of all this code is only executed if .locate() was called with a nonzero count, e.g. locatorInstance.locate(23547, 1)
    if step % 2 == 1 then  // this makes step even. Our step of 12 would be unaffected
      step = step + 1
    end
 
    step = math.floor (step / 2)   // ok, since step is always even, we can divide it by 2 (but WHY?), step is now 6
 
    index = bottom + step    // ok, 6. index = 0 + 6, whatever

    if self.id_of (index) < id then  // what does the method id_of do?
      // how can we call locatorInstance.id_of() is this method wasn't declared in Locator class?
      // whatever, self.id_of(6) < 23547 is either true or false
      bottom = index  // either bottom = 6 ...
     
    elseif self.id_of (index) > id then  // ... or  self.id_of(6) > 23547 , BUT ...
      if top == index then  // ... if top = 6, in this special case return -1 again
        return -1  --  Not found
      end
      // but actually
      top = index   // top = 6 , wait, wasn't this the case which is supposed to return -1?
    else
      // if neither (self.id_of (index) < id) nor (self.id_of (index) > id)
      // so actually only if self.id_of (index) == id ...
      return index    // ... return the index of the unitID in locatorInstance.locate(unitID, count) what the hell is count?
    end 
  end
end

// so, this method .locate() returns an index. Is this index the position of a particular unitID in a list of units?
e.g. listOfUnits = [unit35723, unit95473, unit23547, ...]
instanceOfLocator.locate(23547, someCountOfSomething) would return 1 because listOfUnits[2] = unit23547

Seriously, a handful of little comment lines of what is what in this function would save me hours of lifetime.  :'( :'(

Edit:
I now read the top lines which seem to be comments. They revealed to me that I only had a look at a part of the Locator class definition. Also, count is the number of units in a sorted (and indexed) list of units. Seriously? Why do we even use count? Why don't we use len(listOfUnits)? Instead we allow the programmer to call .locate with an invalid count argument and must handle errors resulting from it? Anyway... could count be the number of unit one sees in the Fortress (u)nits list?
« Last Edit: November 04, 2017, 02:11:56 pm by Nagidal »
Logged
I stream most of my DF sessions: gaming.youtube/nagidal146, they are archived on my youtube channel. (Dwarf Fortress Tutorials)

Nagidal

  • Bay Watcher
    • View Profile
    • My gaming channel
Re: What do I need to write this script:
« Reply #3 on: November 04, 2017, 06:34:40 pm »

I am now more acquainted with Lua syntax. I looked at the the Locator in broader context

there is a global table of historical figures which is indexed and assumed to be ordered by unitID in ascending order, e.g.:

Code: [Select]
index  | Historical Figure (as object)
0      | unit42
1      | unit56
2      | unit215
3      | unit418
...    | ...
354624 | unit678954

Each unit object in this table has an attribute .id, that's one of the game-internal attributes of the unit class, I presume.

Locator is a class (or table, in Lua terms) which serves two purposes:

1. Given an index in the table of historical figures, it can find access the corresponding historical figure and lookup its id. The method (or function) doing this is called id_of. This method is undefined by default, so every time the Locator class is instantiated, this method has to be defined like this:
Spoiler: id_of() (click to show/hide)

2. Given a game-internal unit id, it can find the unit with this unit id in the table of historical figures and return the index under which it can be found there. The method doing this is called index_of. Nah, that would make the code more readable, let's call it locate instead.

The locate method uses some sort of searching algorithm which I assume is pretty quick in searching in a list where the the historical figures are sorted by their ids in an ascending order. When I was trying to perform this method myself to see how its searching algorithm actually works, I think I have found a bug. It seems that it cannot handle the case where it is supposed to find and return the index of the very first historical figure in the list (index 0).

Let's shorten our list of global historical figures to only two members (count = 2):
Code: [Select]
index  | Historical Figure (as object)
0      | unit205
1      | unit408

I'll now run through the locate function:

Spoiler: locate(id, count) (click to show/hide)

When we call hf_locator:locate(205, 2), the initial values are:
id = 205
count = 2
bottom = 0
top = 1

the the loop starts:
step = 1 // (top - bottom)
step % 2 == 1 is true, that's why:
step = 2 (step + 1)
step = 1 (math.floor (step / 2))
index = 1 (bottom + step)
self.id_of(index) < id is false, skipping this if, executing elseif
elseif self.id_of(index) > id is true, executing the if body:
    if top == index is true (1 == 1), executing the if body:
        return -1, returning -1 index not found. (which is wrong, it should have found it and return 0)


Once the loop progresses to the point where top search limit is reduced to 1, the function only checks the unitID, and if it is not the unit we are looking for, it returns -1 forgetting to look at the one last remaining place in the list, index 0.

« Last Edit: November 04, 2017, 06:38:25 pm by Nagidal »
Logged
I stream most of my DF sessions: gaming.youtube/nagidal146, they are archived on my youtube channel. (Dwarf Fortress Tutorials)

Warmist

  • Bay Watcher
  • Master of unfinished jobs
    • View Profile
Re: What do I need to write this script:
« Reply #4 on: November 05, 2017, 02:05:09 am »

I'm very confused.... If I understood correctly that locator thing is for finding historical figure by it's id? Then you can just do 'df.historical_figure.find(id)' or if you need a (loaded) unit's historical figure, you just need to look up it's hf_id (or histfig_id or sth like that). Also many df lists (well std::vector things) are actually sorted, so you can binary-search them, that is why 'utils' file has functions for that and each type has ".find" function to make it easy.

PatrikLundell

  • Bay Watcher
    • View Profile
Re: What do I need to write this script:
« Reply #5 on: November 05, 2017, 04:07:23 am »

The locator thing is a binary search tool for sorted lists. I'm aware it probably duplicates something that's already present elsewhere, but since I wasn't sure I created it for my own use (I'd never intended to "export" the script. It was intended for my own usage, and thus wasn't commented for others, and isn't even finished.). I made the locator because linear search was taking far too long. I'll take a look at the .find function and try to make use of it in the future.

The count argument to the locator is intended to be #<list>, but since the locator itself doesn't have access to which list it's using, it needs to be told what the top index (+1) is to know the range of numbers to search. There are other ways to implement that, of course. All this is largely irrelevant if the find function already provides the functionality.

I wouldn't be surprised if the binary search implementation has a bug.

The locator functionality does not limit it searches to anything particular, which you've probably already found. It's a simple binary search to find (or fail to find) a match of an identifier in a sorted list.

There are two creature lists of interest for the script, and those are the units list containing units of direct interest to the fortress, and the hist fig list, which contains all hist figs (except culled ones, if that option is enabled). Whenever possible, it's better to use the units list than the hist fig list, as more info is available for units (including nick names, which seem not to propagate to the hist fig list).
The units list is probably the one you're most interested in, as most (or all) of the stuff you're looking for is in the units.

I assume you've found out by now that the usage if the script is to select a unit (with 'v' or in the unit table) and then invoke the script. Thus, it requires the same context as e.g. the teleport script.

I don't think snarky code review remarks about naming is an effective method of encouraging people to help you by providing script (snippets) that might help you find what you're looking for.
Logged

Nagidal

  • Bay Watcher
    • View Profile
    • My gaming channel
Re: What do I need to write this script:
« Reply #6 on: November 05, 2017, 07:28:08 am »

@Warmist: When I was searching the lua scripts in DF and DFHack directory, I found that utils.lua has a binary search function generalised to work with any list.

@Patrick:
I was puzzled why I can't find this script in DFHack or in the game already and I did not figure out how and when to run it. Thanks for telling me. It's only now that I realise that you did all this work for your private needs of getting an almost perfect duplicate of the text displayed under Thoughts and preferences. Hats off. You practically did 90% of the work I was afraid I'd had to do myself before I wrap it up with a routine gathering this periodically.

I am sorry if my snarky remark about the function naming. I thought I am looking at a publicly available DFHack script which is supposed to be properly commented and clear for all the DFHack devs. I didn't know that you did all this just to do your own DFHacking stuff and graciously share this.

Yet I have to say I truly struggled to understand all that code. A couple of comments of what this all or each of its functions are supposed to do would have saved me several hours of clueless staring at it and sort of reverse engineering it. I only learn programming as a pastime hobby and I never knew such algorithm as binary search. And I didn't know how hard—if not impossible—it is to implement it 100% bug-free.

Anyway, a thousand thanks for this script, it already gathers most of the information I am looking for. Back to the topic now: I have tried it on some of my dwarfves. Besides some of the information from thoughts missing (which I'm going to try to add to the script) I found that for some dwarves it writes the wrong feeling for inebriation. DF says "she didn't feel anything due to inebriation" thoughts.lua says "... felt euphoric due to inebriation" Although I'm currently not interested in keeping track of my dwarfs recent experiences, I wonder what can be causing this difference.
Logged
I stream most of my DF sessions: gaming.youtube/nagidal146, they are archived on my youtube channel. (Dwarf Fortress Tutorials)

PatrikLundell

  • Bay Watcher
    • View Profile
Re: What do I need to write this script:
« Reply #7 on: November 05, 2017, 09:19:25 am »

I would have thought the rather shoddy quality of the output should have given away that the script was neither official nor finished, but that requires it being run, of course, which you struggled with. If it had been a public DFHack script I would have just mentioned the location/name, rather than put it in my dropbox (again, that requires you to look at the link to see it's not to some "additional scripts" repo somewhere).

There are quite a few things improperly displayed because I've corrected the display of items only as I've found them in my fortress.
In addition to that, a lot of limits (such as "quality" are based on my observations and guesses (everything with the comment --### are things that I think needs further work due to missing observations: those comments are likely not complete, but are my way of indicating TODO points in a way that won't be matched by any actual script contents on searches. Sometimes I've added comments to observed boundary values for the corresponding feature [--### 33, 73 means I've observed the display for a low value of 33 and a high value of 73]).
The implementation of things are infuriatingly inconsistent with a need for case by case handling in a lot of cases (preferences is a total mess when it comes to which fields are relevant when, for instance, and I've failed to find a general way to distinguish when animal tissue means that tissue and when it means the animal as such).
When it comes to friendship values you should probably look at Fleeting Frames' relations-indicator script, as I think that is probably of a higher quality than my guesses.

The reason for the inebriation display discrepancy is a bug, of course ;)
The script assumes an emotion.type of EUPHORIA means euphoric. A discrepancy indicates there's a power level somewhere I haven't found that can moderate that feeling into nothing (and, by extension, that that can probably happen to other feelings as well, in a more or less inconsistent fashion). Without examining the case myself I can't dig up more details.

It can also be noted that the emotions can probably be printed in a lot more compact fashion by making use of knowledge I didn't get until today: It's quite probable the emotions can be matched to the df.global.world.raws.language.words [].forms.Adjective entries of the corresponding word.

Binary seach/interval halving is in itself a rather well known method of searching sorted material, and you actually use a more sophisticated version of it without thinking about it when looking for something in a dictionary (assuming you're old enough to not be fully Google dependent): you make a guess as to where in the volume the word you're looking for is, open up the volume at that page, look at the words, find that it's either earlier or later, make a new guess based on what you know, thus sub dividing the book into smaller and smaller segments until you find what you're looking for. Binary search does not make any sophisticated guesses, but rather looks halfway between the lowest point it can be and the highest one until there is only one possible location left.

Warmist's utils reference turned out to be rather handy for me as I could copy and adapt the script to search for words in the language structure (where the stuff I'm looking for is the combination of the data at the same index in two parallel lists, similar to how a lot of coordinates in DF is stored as {x [], y []} rather than []-{x, y} (if the pseudo Lua syntax is intelligible). Of course, there may be search functions available for these as well, but I don't know about them, and, even if I did, don't know the syntax for calling them.

I can try to answer specific questions, but don't be surprised if I don't have any good answers.
Logged

Nagidal

  • Bay Watcher
    • View Profile
    • My gaming channel
Re: What do I need to write this script:
« Reply #8 on: November 05, 2017, 11:53:00 am »

Thanks for the additional information.

If I want to start writing or modifying Lua scripts, I should learn some basics first. It is unclear to me how to know or guess that your thoughts.lua script has to be run when a unit is selected under the (v) cursor or under a cursor in the (u)nits screen. What gives it away?

Another thing I stumbled upon is how do you find out there is such thing as "T_type" e.g. this line from thoughts.lua
if preference.type == df.unit_preference.T_type.LikeMaterial then

I had a look at df data structures, I saw that there is a struct 'unit_preference' and that it has several enums, one of which is 'LikeMaterial'. If I had written that line, I'd assumed the right way to test whether a certain preference of a unit is of the 'LikeMaterial'-type would be to look at df.unit_preference.LikeMaterial. How did you find out that df.unit_preference has another object called T_type, which is parent to .LikeMaterial? Because I don't see the object T_type listed anywhere in df-structures or under <struct-type type-name='unit_preference'>. How do you know it's there?

Is there another place I don't know about where I could see or navigate the full structure of the df.global? When I used to debug my Python scripts, I used a debugger, and when I picked a complex object, I could expand or collapse any of its child objects and thus explore the complex structure. I wish I could do this with the df object.
Logged
I stream most of my DF sessions: gaming.youtube/nagidal146, they are archived on my youtube channel. (Dwarf Fortress Tutorials)

PatrikLundell

  • Bay Watcher
    • View Profile
Re: What do I need to write this script:
« Reply #9 on: November 05, 2017, 12:20:26 pm »

The start of the main function fetches the unit in focus:
"  local unit = dfhack.gui.getSelectedUnit (true)"

I don't remember the T_type thing, so it's likely it's something I've copied&pasted from somewhere else. I agree it definitely looks like it should work without the T_type thingie.

The go-to tool is gui/gm-editor.
"gui/gm-editor" on its own, without parameters, opens up the currently selected structure in DF, be it a unit, building, or whatever.
"gui/gm-editor df" will show the whole list of everything in df, i.e. every type (which is far to much to sift through to be useful), while "gui/gm-editor df.global" will do the same on the global level, showing all the structures there (which is a set small enough to actually be useful).
I use gui/gm-editor a lot, since it's typically the fastest way to find out what the names of fields in structures are. The only thing missing in gui/gm-editor is a display of what the type of the field is (that's displayed for some types, but not all), as it would save time going to the xml (or .h files if you've downloaded the DFHack source code) to find the name of enum types in particular.
gui/gm-editor doesn't allow you to expand/collapse, "only" traverse up/down, but that's good enough in my view.
Logged

Fleeting Frames

  • Bay Watcher
  • Spooky cart at distance
    • View Profile
Re: What do I need to write this script:
« Reply #10 on: November 05, 2017, 01:27:04 pm »

*echoes in*

I'm not sure where friendship values come in, skimming the thread, but relations-indicator is kind of long, so I'll note the possibly relevant structures.

a. Unit values. Stored in unit.status.current_soul.personality.values. To get friendship value you'd iterate over each entry, check if .type is 3, and if it is .strength is how high they value it. Ranges from -50 to +50. I think this is the one that can be changed by an argument or reading a fitting book.
 
b. Unit traits. Stored in unit.status.current_soul.personality.traits.FRIENDLINESS
    A space is replaced with _ in traits, otherwise works as normal. Ranges from 0 to 100.

c. unit relationships. While some things, like spouse, lover, etc. you can see locally, who they're friends - or holding grudge with - is listed in historical unit data.
    In particular, hf.histfig_links categorizes some broad relationship types such as df.histfig_hf_link_motherst and each entry of  hf.info.relationships.list contains .histfig_id (for who the relationship is targeted towards) and list of feelings in .anon_3.

1 is friend, 7 seems to be friendly terms, I think - has tendency to override bunch of other values (2 is grudge).

Can be multiple, as dwarf can have multiple, conflicting feelings with different strength towards another unit. (DF is awesome.)

Feeling strength is under .anon4 and corresponds to the matching value in exported xml. .anon5 is how many times they've met, iirc (not certain, it's been a while and I didn't take notes - also included in exported xml, btw), which is also something you might possibly want to track.


Things to look out to avoid crashes:
a) Some units like reanimated corpses lack a soul.
b) Some units like wild animals wandering onto map start out non-historical.
c) For historical figures, the relevant structure is not unit.status.current_soul.personality, but hf.info.personality
d) hf.info.personality is missing for units who have never updated their hfunit.
e) invaders may have hf.info.relationships absent
f) Relationships are updated dynamically in historical figure data, but most other fields seem to be updated only when unit is offloaded - A locally born dwarf will have hf.info.personality absent until retirement.
g) 43.05 dfhack and 43.03- store local unit relationship data differently - ex, first uses unit.relationship_ids.Spouse, second uses unit.relationships.spouse_id. This doesn't have any friends in it, though.



Nice idea here with goal 1; though I'll be honest - I've many times used DT for this purpose, so wouldn't have bothered to make it myself.

Goal 2 strongly reminds me of dwarfmonitor (prefs), part of dfhack default, which does give different in-game display of preferences amongst its many monitoring functions.  Maybe it's already what you want?

And yeah, lots of scripts are not part of core dfhack repo. I think the last originally non-git committed one that was added was fixes for stuck merchants and sieges?

Regarding gui/gm-editor, worth noting that many of the type values use not immediately obvious metatables - a lua inheritance structure where calls to the table, if not found present in table, try a different table. One example is .find(#) function, another example would be df.building_type - using ._first_item returns 1, using ._last_item returns the index value of last building, using .WELL returns 18 (I think it was 18), using [18] returns "WELL".
« Last Edit: November 05, 2017, 01:30:30 pm by Fleeting Frames »
Logged

Nagidal

  • Bay Watcher
    • View Profile
    • My gaming channel
Re: What do I need to write this script:
« Reply #11 on: November 05, 2017, 02:38:30 pm »

Wow, thanks, the GM-Editor is really good for browsing it. True, it could show more info about the object from the xml, but it's a good start.

I first wondered you left out the appearance section of Thoughts and preferences in thought.lua. e.g.: "He is short. His hair is wavy. His medium-length sideburns are neatly combed. ..." But now I can see that it is not easy to figure it out from what I see in gm-editor. If it is there, we don't know yet how these things are encoded. Maybe sometime we'll know

But I can see how I could add the dark green (or dark red) stuff, the Soul Attributes, e.g. "He has a gerat feel for social relationships, but he has little patience and poor spatial senses."

Thanks to FleetingFrames, I also see how I could add the cyan part (Beliefs), e.g. "He personally sees lying as an important means to an end and thinks friendship is important" (It's in unit.status.current_soul.personality.values) and several more information, like Facets.

Now we're getting somewhere.  ;D

@FleetingFrames:
Regarding Goal1: How did you use Dwarf Therapist for this? I suggested this feature to splinterminds a long time ago. He answered that it's not all that easy and pretty messy/finicky. I'm now starting to see what he meant. As far as I know DT has no such feature to list the favourite types of your citizens.

Back when I suggested this feature to splinterminds, I thought one could access the whole text written in thoughts and preferences as a multi-paragraph string and, with an intelligent parser, get the information from there. DT manages to gather these preferences of each dwarf, but only dumps it in the gigantic tooltip displayed when you hover the mouse cursor over a dwarf's name. It does not display them as systematic and structured as I'd like to see it. Now that I think about it, maybe I should change this goal to implement such a spreadsheet overview as yet another tab in Dwarf Therapist, because somehow DT has all this information gathered anyway, it just doesn't do much with it.
Logged
I stream most of my DF sessions: gaming.youtube/nagidal146, they are archived on my youtube channel. (Dwarf Fortress Tutorials)

Fleeting Frames

  • Bay Watcher
  • Spooky cart at distance
    • View Profile
Re: What do I need to write this script:
« Reply #12 on: November 05, 2017, 05:10:01 pm »

DT - right click on upper left - select preferences to get a sortable categorized list of who likes what. I use this to find out if I have anybody who likes exotic weapons or trap components for moods, for example.

But I meant more about changing military and attributes, which take the form of sticking a military dwarf in danger room, reading data, noting down the values I care about, running the game for few weeks, then reading again and comparing the values.

DT also uses preferences to determine the suitability of dwarves for a given role, and you can use custom filters for nobles without item preferences and such. But yeah, I'm not even aware of any attempts before this to confirm preferences being timeless and unchanging.
« Last Edit: November 05, 2017, 05:11:34 pm by Fleeting Frames »
Logged

Nagidal

  • Bay Watcher
    • View Profile
    • My gaming channel
Re: What do I need to write this script:
« Reply #13 on: November 05, 2017, 05:50:29 pm »

DT - right click on upper left - select preferences to get a sortable categorized list of who likes what. I use this to find out if I have anybody who likes exotic weapons or trap components for moods, for example.

What version of DT are you using? I have the one from Peridexis' Starter Pack, 43.5.1, there's no tab called preferences.  :-\

But I meant more about changing military and attributes, which take the form of sticking a military dwarf in danger room, reading data, noting down the values I care about, running the game for few weeks, then reading again and comparing the values.

Silly me, I didn't bother to look up what I called Goal 1 and what Goal 2. And I got it wrong. Yea, I thought some sort of a personal development record of a dwarf could become a nice source for all sorts of statistics. Things could be exported and graphed with R and so on.

DT also uses preferences to determine the suitability of dwarves for a given role, and you can use custom filters for nobles without item preferences and such. But yeah, I'm not even aware of any attempts before this to confirm preferences being timeless and unchanging.

I personally expect preferences to be unchanging, but I wouldn't be surprised if dwarves would get grey hair, white beards, or wrinkled skin when they grow old. And it would be interesting to see at what age that happens. Also, I thinks thoughts, ideals and values might change. I read the thoughts of one pubescent dwarf in my forterss which said: "She very easily falls in love and develops positive feelings. She often feels lustful. She can sometimes act without deliberation. ... " This all makes sense for a 12-15 years old dwarf. Also the thoughts of a just born baby, seemed more childish than of an adult dwarfs. Of course it can be an lucky accident. So I decided it'd be interesting to gather more data, see if these things change in the mid or long term or if they are set in stone forever the moment the dwarf is born.
Logged
I stream most of my DF sessions: gaming.youtube/nagidal146, they are archived on my youtube channel. (Dwarf Fortress Tutorials)

Fleeting Frames

  • Bay Watcher
  • Spooky cart at distance
    • View Profile
Re: What do I need to write this script:
« Reply #14 on: November 05, 2017, 06:25:18 pm »

Right click here: ||

I'd display the menu but menu overrides the screenshot hotkeys I use.

Values one can change indeed. Dream, though, not yet - it's a goal to have dwarves get new dreams when previous one is realized, but they currently don't do that.

Alcohol does permanently change dwarf traits, but I don't know any beyond that. Not on any evil weather that I've looked at.

How they speak maybe changes, as dwarf can improve their feel for social relationships attribute as well as social skills.
Pages: [1] 2