Interesting ideas. We dreamed to make some agriculture and food in blackvoxel since a long time. But, be careful of animals that could be present in some other voxel games.
Maybe you could make it as some extra terrestrial animals. If you keep reference to some known animals, they could be very different of what we know. In blackvoxel, the idea is that one should be surprised from what he is expecting (when possible, of course).
I agree; was going to make some cyber-space names for them.. but fell back to my idea of foxes and rabbits .... predator/prey and make the foliage be like data nodes... but the concept of growth didn't apply so much... am open to ideas ... maybe 'bit scav'/'virus' and 'antivirus'... so a virus consumes data and anti-virus consumes viruses...
general properties of an 'animal'
health/data size
damage/data consumption
level/entities consumed (improve damage application effectiveness)
propagation_threshold - if health > threshold spawn new X
age maybe - builtin obsolescence
scent?
----------
Something I've been considering; making transparent voxels have a base voxel extension that can store other voxels... fish in water; animals in plants, animals sharing spots... 1) animals could attack horizontally and just require nearness... 2) animals could be 'on top of' plants... 3) could be a meta voxel type 'fish in water' that behaves like water... but...
Something I'd like to implement is 'smell' that is empty (air) voxels will be like a textureless voxel that's not zero; and contain information about aromas in the air...
We encourage you in your searching.
normally the player isn't a voxel; so voxels that are player-like should also respect 'can player pass through' ... but then they would be in the voxel.... and since there's only a current reprensentation of a single voxel type in any voxel, it could be an interface implemented on transparent voxels that allow being 'in' the voxel. Can do a multi-layered render of the voxel at some point to represent the contained voxels... thoughts? I will assert that from previous experience, I think you'd prefer to keep to a purist approach, and animals will just hop from ground to the top of foliage, and animals can attack animals nearby disregarding height differences.. and then I can't really populate air ... because eventually aroma voxels will exist above fertile land and prevent growth....
Yep, there is the paradigm to keep the rendering of all voxels the same and strictly cubic. That's a choice that will make sense in the future.
That's not something we consider we couldn’t change at all. There is pro and cons in the two ways.
But if we found there is better advantages to change, we'll do it.
In some ways, the "smells" are gas, so like the yellow gas.
Voxel Animals should'nt use the flag 'can player pass through'. When moving, they could either discard "gas" voxels or exchange their positions.
The water is doing that : When moving, a block of water exchange it's position with the gas located in the destination location.
For vegetation, they could simply delete gas voxels in growing over.
depends on your allocer; most malloc will return the same block as was last freed... so allocating short term storage doesn't fragment.. yes returning into a caller-owned struct solves it.... was more concerned with keeping the function signature the same for quickness; and when not deleted was what was causing my memory error ended up removing that.
well... memory deallocated is defragmented and allowed for reuse; so the things you throw away are collected, so there is garbage collection; just not automagic object reference increment/decrements... and garbage on the stack is collected...
And even so; you still have to intentionally throw away things like Datatables because of the circular references they won't auto implode.... so you should never count on things just going away.
free works kinda like ZMonoSizeMemoryPool::Free such that when released, it's immediately reused for new mallocs...
I find it's better to do a slight more work, and do 2 comparisons in the free list to order free blocks from least memory address to most; further reducing fragmentation... also if the allocer has a minimum memory block size there's less chance of having blocks that are not big enough laying around; my MUD terminal (dekware) improved greatly by setting minimum alloc at 60 bytes... at not that much increase in memory usage.
Also block types that are tiny like binary tree nodes come from a pool of structs so there's only a few allocs from physical memory.
so ya; I saw the techniques and recognized their purpose
In fact, the problem is like most optimisation problems : there is a limit to what a general approach can do.
As clever as memory manager could become on some systems, these algorithms remains tuned for general case.
That's why the best system memory manager would remain not optimal for all particular cases and particularly for some cases in video games.
There is also intrinsic limitation with C++ : a system memory manager can't defragment two blocs if you keep one in between. Because there is no reference tracking in C++, there is no way to move that memory.
Also, any defragmenting operation means system will take some CPU time to do it.
In fact, most system memory manager use complicated strategy. On the source code of the glibc, we can read that the strategy depends on the block size. The algorithm is explained in the source code. It doesn't fit well all the cases.
That's also mean something we want to avoid : heuristic approach in these algorithms could lead to unpredictable variability between systems and different memory manager.
Garbage collectors do more than simple memory management, they are tracking unused blocks in order to avoid the obligation of explicit memory freeing.
In Blackvoxel, we doesn't ban system memory manager : we use it for all is general, long term and non intensive memory use.
There is two custom allocators in Blackvoxel and there are used depending on the needs. There is one for specific size memory management and one other for more variable size.
Hmm... does the mem pool really help? Is new and delete not really based on malloc/free? Glibc usually collects garbage pretty well... I had my own memory allocator that was in the core of my library; still do, just hard to initialize a dynamic program without having initialized memory; and sometimes core debugging becomes impossible....
In my library I made a set allocator which is a linked list of nodes that have a bitmap mask of used mono-sized nodes... also keep a counter of used nodes so can just check if all used, otherwise scan the bits 32 at a time until it's not ~0 ... otherwise allocates a new block of nodes... so all nodes are continuous in memory ...
even if you're recycling previously allocated things, they're still jumbled all over memory....
Yep, the custom allocators in Blackvoxel helps a lot. For both fragmentation and speed.
These are really blazing fast and doesn't cause any fragmentation growing, even with the most intensive use.
As you guessed, it uses underlying system allocation. But the subtlety is that the memory is never returned to the system, but always recycled. So after a little startup time, no system allocation calls are made.
Of course, this approach have also drawbacks. It's not suited for everything, not even in Blackvoxel.
So, memory management is another case of the optimisation problem leading to the best compromise for each particular needs.
even if you're recycling previously allocated things, they're still jumbled all over memory....
Our goal with fragmentation isn't to avoid it completely or to make things perfect, but rather to avoid weird degenerative problems after some time of gaming.
The other goals are to get it the fastest as it is possible and limit variations between systems.
With our custom memory managers, even with billions of calls, the fragmentation doesn't grow over time and recycling is very fast. That's all what we need...
The Blackvoxel Team