One classic way to handle it is to load the binary into IDA Pro (a graphical disassembly suite). That starts from the entry point of the binary and traces through as much of it as possible, noting the locations of strings, function calls, the state of the stack when functions are called, different segments in the binary, etc. It'll allow you to view the code in blocks connected by lines, which indicate branches and loops. As a dev, you can go through the code then and start working things out. With some investigation and the context of where you are in the program, things slowly start falling into place, and you can start putting names to different functions. Although...Dwarf Fortress looks like it was compiled with GCC 4.5, so I'd expect things to be pretty difficult to read, just because of non-obvious optimizations made by the compiler.
I've always thought it would be useful to have a debugger that logs all the locations that data is read from or written to during execution, and which addresses were executed as instructions. Just play the game for a while to try to get some good code coverage, and import the data as extra input into IDA (probably you'd have to write your own plugin for that too).
I've always thought it would be useful to have a debugger that logs all the locations that data is read from or written to during execution, and which addresses were executed as instructions. Just play the game for a while to try to get some good code coverage, and import the data as extra input into IDA (probably you'd have to write your own plugin for that too).