Using <Animal>List as the abstract data type, and Pool of different types containing <Animal>ListNode sets up a kind of static inheritance.
Pool and List are kind of generics controlled by the pre-processor, in the sense that you define something, and include something, and the code for that one case is written automatically. These are arguably preferable to turning off static type-checking by using pointers-to-void.
The inheritance, denoted by a clear arrow, is manifest in the code as nested structs. By doing it this way, for example, you cannot refer to bad_emu->name, but bad_emu->emu.animal.data.name.
Pool is a dynamic list, and may move elements around in memory; any dependencies must have a memory move function that updates the pointers. These are the dashed dependancy lines. One will notice that the dependancies flow out of each object which is a Pool or which descends therefrom. For example, wlg, the arrow between Emu and Animal labeled emu%(), says that in emu_migrate(), linked to struct Emu by, (#define POOL_TYPE struct Emu, #define POOL_MIGRATE_EACH &emu_migrate, #include "Pool.h",) there is a case handing <Animal>List, notably, AnimalListNodeMigrate(). If we wanted a static array of animals, this would not be needed, as in the case of Bear.
We have a static virtual table for all virtual functions, AnimalVt, one for each type of Animal. Note that the variables must be all private or all public, corresponding to putting the struct in the .c file or exporting it to the .h file.