View Issue Details

IDProjectCategoryView StatusLast Update
0006334Dwarf FortressCreaturespublic2014-11-25 22:59
Reporterverdantsf Assigned ToToady One  
PriorityhighSeveritymajorReproducibilityalways
Status resolvedResolutionfixed 
Product Version0.34.11 
Fixed in Version0.40.02 
Summary0006334: Creatures, including dwarves, born in the fortress do not grow to full adult size.
DescriptionTwo 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.
Steps To ReproduceObserve butchering or combat results for creatures and dwarves born in the fortress.
Additional InformationThread 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
Tagsbinary patch

Relationships

has duplicate 0001047 resolveduser6 Butchered cats only produce skulls, possibly related to aging while caged 
related to 0007067 resolveduser6 Animals do not age or mature 

Activities

verdantsf

2013-05-31 09:37

reporter   ~0023987

Last edited: 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

verdantsf

2013-06-11 09:13

reporter   ~0023997

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.

Quietust

2013-06-11 09:19

reporter   ~0023998

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

verdantsf

2013-06-13 09:16

reporter   ~0024002

The latest version of the LazyNewbPack has the fix pre-installed.

http://dffd.wimbli.com/file.php?id=7622

Cobbler89

2013-08-26 15:35

reporter   ~0024100

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"?

BenLubar

2014-01-15 20:38

reporter   ~0024276

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

administrator   ~0025572

Thanks to everybody that helped figure this one out. Hopefully it is all sorted out for next time.

Issue History

Date Modified Username Field Change
2013-05-31 09:24 verdantsf New Issue
2013-05-31 09:37 verdantsf Note Added: 0023987
2013-06-01 17:08 verdantsf Note Edited: 0023987
2013-06-01 17:09 verdantsf Note Edited: 0023987
2013-06-01 17:10 verdantsf Note Edited: 0023987
2013-06-01 17:11 verdantsf Note Edited: 0023987
2013-06-01 17:12 verdantsf Note Edited: 0023987
2013-06-11 09:13 verdantsf Note Added: 0023997
2013-06-11 09:19 Quietust Note Added: 0023998
2013-06-13 09:16 verdantsf Note Added: 0024002
2013-08-26 15:35 Cobbler89 Note Added: 0024100
2013-11-04 10:49 user6 Tag Attached: binary patch
2014-01-15 20:38 BenLubar Note Added: 0024276
2014-03-25 13:11 user11 Assigned To => user11
2014-03-25 13:11 user11 Status new => acknowledged
2014-07-10 12:37 Toady One Note Added: 0025572
2014-07-10 12:37 Toady One Status acknowledged => resolved
2014-07-10 12:37 Toady One Resolution open => fixed
2014-07-10 12:37 Toady One Assigned To user11 => Toady One
2014-07-10 12:39 Toady One Status resolved => assigned
2014-07-10 12:39 Toady One Assigned To Toady One => Logical2u
2014-07-10 12:39 Toady One Status assigned => resolved
2014-07-10 12:39 Toady One Fixed in Version => Next Version
2014-07-10 12:39 Toady One Assigned To Logical2u => Toady One
2014-07-12 09:33 user6 Relationship added related to 0007067
2014-07-23 10:06 user6 Relationship added has duplicate 0001047