Dwarf Fortress Bug Tracker - Dwarf Fortress
View Issue Details
0006334Dwarf FortressCreaturespublic2013-05-31 09:242014-11-25 22:59
Toady One 
0006334: Creatures, including dwarves, born in the fortress do not grow to full adult size.
Two separate forum threads discovered significant differences in body size between creatures born in the fort vs. those who migrated or were purchased. Butchering results for animals born in the fort are less than the expected adult size result. Dwarf soldiers born in the fort are much less effective with blunt weapons compared to their migrant peers.
Observe butchering or combat results for creatures and dwarves born in the fortress.
Thread on butchering discrepency:
http://www.bay12forums.com/smf/index.php?topic=91166.msg4284557#msg4284557 [^]

Thread on weapon performance discrepency:
http://www.bay12forums.com/smf/index.php?topic=126558.msg4283868#msg4283868 [^]
binary patch
has duplicate 0001047resolved Footkerchief Butchered cats only produce skulls, possibly related to aging while caged 
related to 0007067resolved Footkerchief Animals do not age or mature 
Issue History
2013-05-31 09:24verdantsfNew Issue
2013-05-31 09:37verdantsfNote Added: 0023987
2013-06-01 17:08verdantsfNote Edited: 0023987bug_revision_view_page.php?bugnote_id=0023987#r8935
2013-06-01 17:09verdantsfNote Edited: 0023987bug_revision_view_page.php?bugnote_id=0023987#r8936
2013-06-01 17:10verdantsfNote Edited: 0023987bug_revision_view_page.php?bugnote_id=0023987#r8937
2013-06-01 17:11verdantsfNote Edited: 0023987bug_revision_view_page.php?bugnote_id=0023987#r8938
2013-06-01 17:12verdantsfNote Edited: 0023987bug_revision_view_page.php?bugnote_id=0023987#r8939
2013-06-03 23:22InsanityPreludeIssue Monitored: InsanityPrelude
2013-06-07 03:52StebIssue Monitored: Steb
2013-06-08 18:37jfw25Issue Monitored: jfw25
2013-06-11 09:13verdantsfNote Added: 0023997
2013-06-11 09:19QuietustNote Added: 0023998
2013-06-13 09:16verdantsfNote Added: 0024002
2013-06-16 21:42krenshalaIssue Monitored: krenshala
2013-08-26 15:35Cobbler89Note Added: 0024100
2013-11-04 10:49FootkerchiefTag Attached: binary patch
2014-01-15 14:48Kirig Stonebeard IIIssue Monitored: Kirig Stonebeard II
2014-01-15 20:38BenLubarNote Added: 0024276
2014-01-17 10:03Kirig StonebeardIssue Monitored: Kirig Stonebeard
2014-03-25 13:11DwarfuAssigned To => Dwarfu
2014-03-25 13:11DwarfuStatusnew => acknowledged
2014-07-10 12:37Toady OneNote Added: 0025572
2014-07-10 12:37Toady OneStatusacknowledged => resolved
2014-07-10 12:37Toady OneResolutionopen => fixed
2014-07-10 12:37Toady OneAssigned ToDwarfu => Toady One
2014-07-10 12:39Toady OneStatusresolved => assigned
2014-07-10 12:39Toady OneAssigned ToToady One => Logical2u
2014-07-10 12:39Toady OneStatusassigned => resolved
2014-07-10 12:39Toady OneFixed in Version => Next Version
2014-07-10 12:39Toady OneAssigned ToLogical2u => Toady One
2014-07-12 09:33FootkerchiefRelationship addedrelated to 0007067
2014-07-14 02:57StebIssue End Monitor: Steb
2014-07-23 10:06FootkerchiefRelationship addedhas duplicate 0001047
2014-07-23 10:06FootkerchiefIssue Monitored: thvaz
2014-07-23 12:28thvazIssue End Monitor: thvaz
2014-08-11 18:11krenshalaIssue End Monitor: krenshala
2014-11-25 22:59InsanityPreludeIssue End Monitor: InsanityPrelude

2013-05-31 09:37   
(edited on: 2013-06-01 17:12)
Here's the save file with Edem II, a legendary hammerdwarf born in the fortress.

https://docs.google.com/file/d/0B9DOgh4L-pqaVzNkdHJqRWZRTkU/edit?usp=sharing [^]

Community members compared him to the other legendary hammerdwarves, as well as the legendary macedwarf Dishmab, using a maxblood script like the one below:

http://www.bay12forums.com/smf/index.php?topic=126558.msg4285632#msg4285632 [^]

Dishmab is actually weaker than he is, and yet when they've exchanged weapons, she has outperformed him in combat by a wide margin:

http://www.bay12forums.com/smf/index.php?topic=126558.msg4281876#msg4281876 [^]

2013-06-11 09:13   
A solution has been discovered, thanks to Urist Da Vinci!

http://www.bay12forums.com/smf/index.php?topic=126558.msg4310469#msg4310469 [^]

Crowdsourced tweaking & testing currently underway.
2013-06-11 09:19   
In summary, it appears that unit growth is intended to be recalculated once per day (and offset by the time of day the creature was born), but there's a further restriction that it only does that check once every 10 ticks, so if the creature's birth time is not a multiple of 10 ticks, its size does not properly get updated.

if (((cur_year_tick % 10) == 0) && (((cur_year_tick - birth_time) % 1200) == 0)) { update stuff }

http://www.bay12forums.com/smf/index.php?topic=91166.msg4311166#msg4311166 [^]
2013-06-13 09:16   
The latest version of the LazyNewbPack has the fix pre-installed.

http://dffd.wimbli.com/file.php?id=7622 [^]
2013-08-26 15:35   
Working off the assumption that the (probably simplified) example code above is essentially accurate, and just thinking out loud here... This could be fixed by making the birth times only be multiples of ten (which is currently done after the fact in the DFHack fix), but that could introduce other bugs in the game code if not done perfectly (for instance, if it only allowed births every ten ticks, you wouldn't want there only to be 1/10th the offspring on average; if it simply rounded the birth time instead of using the real birth time, it would need to always round down to prevent creating a birth time in the future and whatever problems that could potentially cause for all of <9 ticks -- obscure things like that). It could also be fixed by checking for updates on every tick, but then the check portion of the code would use up ten times as much processing since it's firing ten times as often (then again, the portion that restricts it to every tenth tick would be using up none, so I guess it depends on the relative complexity of the two spots in the actual code -- I would imagine the "once every ten ticks" part of the code is an if block inside of which is a loop through the units to check their ages, so the one check only fires once per tick and the other fires, on the relevant ticks, once per unit per relevant tick). Finally, assuming the code above is something like how it's done, it could be fixed by changing that last "== 0" to "< 10" (or, conceivably, instead of literal 10 have a constant that's used there and where the number of ticks to skip over is set, so that if its value is ever changed in the one place it's changed in the other).

Of course, Toady probably doesn't need my coding advice... but here's where it gets interesting: I wonder if we could find where this operation is occuring in the binary and patch it to be a "< 10" comparison instead of "== 0"? Not that it would be easy to find; but I am curious whether it could theoretically be fixed if somebody found it -- whether, in short, the binary code for "< 10" would take up the same space as the binary code for "== 0"?
2014-01-15 20:38   
Well, the check requires:
- a subtraction
- a division
- a jump-when-zero (or jump-when-not-zero, depending on where the compiler put the body of the if statement)

The code that makes the check only run once every ten ticks requires:
- a division
- a jump-when(-not)?-zero

So really all we're saving is a single subtraction nine out of ten ticks in exchange for an extra division and an extra conditional jump one out of ten ticks. Even if we did that a million times per tick, that's still less than a millisecond saved or lost by the optimization. Subtraction is cheap.
Toady One   
2014-07-10 12:37   
Thanks to everybody that helped figure this one out. Hopefully it is all sorted out for next time.