Wandering Creatures
This is an experiment with using a FSM Table. An FSM Table is a table of states, their transitions, and the conditions for those transitions. It's a way to represent a Finite State Machine. I used it to simulate a lot of creatures wandering around looking for food.
For visualization, I just use different colors for each different state. Red is food. Blue is Idle. Green is searching. Grey is dead/stash.
The AI is pretty simple. Each AI has a health meter which also doubles as a hunger meter. This meter degrades over time. When the AI is full, it will wander around aimlessly (the blue state). When the AI is hungry, it will start searching for food (the green state). If the AI fails to find food for a period of time, it will go back to the idle state (e.g. the AI is in the middle of nowhere). If the AI's hunger meter depletes fully, then it will die, leaving behind a stash.
Food sources include the red food and grey stashes. The stash degrades in value over time until it disappears entirely. Stashes are less valuable, so the AI will only search for a stash if it is really hungry.
Originally, the AI wouldn't move in the Search state if there wasn't a nearby food source. This was problematic since there may be plenty of food near the AI but it was just outside the AI's search range. I added in code which would switch the AI out of the Search state if it failed to find enough food by the end of so many frames, that way it would start wandering around aimlessly to get near food. To prevent AI from constantly flipping between Idle and Search states, the AI must remain in the Idle state for a minimum number of frames before switching. This gives a delay so that the AI remains in the Idle state for a specific period of time. I later changed the search state to also wander around aimlessly if no target was found, but to switch directions more often. I kept in the "switch to Idle after *n* frames" code since I liked having a "failure" fallback in my AI system.
Each entity does respawn after so many frames. I don't add or remove entities from my array, I only mark them as "dead" and ignore them in a lot of processing steps. I also don't do any sort of quad maps for my searches. Instead, I just iterate over my entire array of entities anytime I need to do a search (this includes collision detection with the food). For something as simple as my simulation, this gives plenty of performance. I was able to hit 120fps in my browser with 3,000 entities and hit 500-600fps in a native executable with 3,000 entities. The simulation running here is just 300 entities, and it works really well.
I do keep all the entities in the same array, whether it's a creature, food, or stash. I don't know if that's a good idea or a bad one, but it was an idea. Mostly I just didn't want to introduce a second array and have to try to manage that. It does make things a bit simpler since I can just change a flag field to convert creatures to stashes and back again. And I only ever have to search a single array for what I want. I also can quickly process adjusting the positions and velocities of the entities by doing a single iteration with lots of additions (food and stashes just have a velocity of zero, so no need to filter them out).