Research is still ongoing, but I thought I'd share a useful lua script I wrote for dfhack based on the one by Nilsolm.
-- Prints out all the memories of the selected unit, along with some metadata.
local help = [====[
Select a unit in dwarf fortress, then run this script.
It will print out three blocks of information:
Short term memories, long term memories, and memories which have been
reflected upon.
The number in brackets after the thought is metadata used to store extra
details about the type of memory. It tracks things like who was talked to,
which book was read, etc.
The strength variable probably determines which memories get overwritten.
The severity variable seems to store metadata such as the value of a room
or the quality of an tem of clothing.
Memories in the "reflected memories" category don't seem to cause new
thoughts, but any personality changes which resulted from those memories
are displayed.
The date format is "YYY-MM-DD HH:TT", where TT runs from 0 to 50.
There are 50 ticks per hour so this seemed more elegant.
Options:
-help show this help screen
-all include overwritten and uninitialized memory slots in the output
]====]
utils = require('utils')
local validArgs = utils.invert({'help', 'all'})
local args = utils.processArgs({...}, validArgs)
if args.help then
print(help)
return
end
local color_A = 10
local color_B = 11
local color_uninit = 8
local color_overwritten = 13
function get_thought_type(agr)
return df.unit_thought_type[agr]
end
function get_emotion_type(agr)
return df.emotion_type[agr]
end
function get_facet_type(agr)
return df.personality_facet_type[agr]
end
function get_value_type(agr)
return df.value_type[agr]
end
function sort_emo(emo1, emo2)
return (emo1.year < emo2.year) or ((emo1.year == emo2.year) and (emo1.year_tick < emo2.year_tick))
end
function sort_reflection(ref1, ref2)
return sort_emo(ref1.memory, ref2.memory)
end
function pairs_sorted(t, f)
local a = {}
for key,value in pairs(t) do table.insert(a, value) end
table.sort(a, f)
return pairs(a)
end
function get_date_string(emo)
local year = emo.year
local tick = emo.year_tick
if year == -1 then return "None" end
if tick == -1 then
return string.format("Before year %d", year)
end
local month = math.floor(tick / 33600) + 1
local day = math.floor((tick % 33600) / 1200) + 1
local hour = math.floor((tick % 1200) / 50)
local minute = math.floor((tick % 50))
return string.format("%d-%02d-%02d %02d:%02d", year, month, day, hour, minute)
end
function print_emotion(emo)
local datestr = get_date_string(emo)
local feeling = get_emotion_type(emo.type)
local event = get_thought_type(emo.thought)
local subthought = emo.subthought
print(string.format("[%s]\t%s due to %s(%d)", datestr, feeling, event, subthought))
print(string.format("\tstrength = %d \tseverity = %d", emo.strength, emo.severity))
end
function display_emotions(emotions)
for ii, emo in pairs_sorted(emotions, sort_emo) do
local color = -1
if ii%2 == 0 then
color = color_A
else
color = color_B
end
if emo.thought == -1 then color = color_overwritten end
if emo.year == -1 then color = color_uninit end
dfhack.color(color)
if emo.thought > -1 or args.all then
print_emotion(emo)
end
end
dfhack.color(-1)
end
function display_reflections(refs)
for ii, ref in pairs_sorted(refs, sort_reflection) do
if ii%2 == 0 then
dfhack.color(color_A)
else
dfhack.color(color_B)
end
print_emotion(ref.memory)
if ref.changed_facet > -1 then
local facet = get_facet_type(ref.changed_facet)
local old = ref.anon_1
local new = ref.anon_2
print(string.format("\tChanged facet: %s [%d -> %d]", facet, old, new))
end
if ref.changed_value > -1 then
local value = get_value_type(ref.changed_value)
local old = ref.anon_3
local new = ref.anon_4
print(string.format("\tChanged value: %s [%d -> %d]", value, old, new))
end
end
dfhack.color(-1)
end
sel = dfhack.gui.getSelectedUnit()
if not sel then qerror("No unit selected.") end
if not sel.status.current_soul.personality.memories then
qerror("The selected unit doesn't have a memory struct.")
end
mem_short = sel.status.current_soul.personality.memories.shortterm
mem_long = sel.status.current_soul.personality.memories.longterm
mem_reflected = sel.status.current_soul.personality.memories.reflected_on
dfhack.color(-1)
print("\n-----------------------------------")
print("Short Term Memories:")
print("-----------------------------------")
display_emotions(mem_short)
print("\n-----------------------------------")
print("Long Term Memories:")
print("-----------------------------------")
display_emotions(mem_long)
print("\n-----------------------------------")
print("Reflected Memories:")
print("-----------------------------------")
display_reflections(mem_reflected)
print("-----------------------------------")
This should display all the memories of a dwarf, even ones which aren't present in their thoughts page. It also lists a non-zero strength value for every memory, although I'm still not 100% sure how those are calculated or how they relate to stress.
If the colours look weird in your terminal, try changing the color_A and color_B values.
Interestingly a lot of my dwarves seem to have very few long term memories and many even have empty slots in their short term memory. It explains why my strategy of trying to fill up their long term memories with positive thoughts wasn't working. Memories get removed from long term memory much faster than I had previously believed.
It shows a lot of "ANYTHING due to None" emotions. I don't know what those are about, but the rest seems to be accurate.
Those seem to be leftover data from memory slots which have been cleared. The game overwrites the emo.type and emo.thought fields with -1, but leaves all the other data in place.
I added a check to my script to filter them out since they don't provide much useful information and can be confusing.
EDIT: Added an -all option to the script which will display the contents of the cleared/uninitialised memory slots.