It sounds like your
Illusionary_Death method has a side effect of removing the passed
Object from the
LIST_Objects array. That wasn't immediately obvious to me when I first read through the code.
My first thought was, you have a known start and end point, so why not use a
for loop instead of a
while loop. That list modification done along the way would be why.
Tip: If you're removing elements from a list while iterating over it, it sometimes helps to iterate in reverse.
Assume for the sake of argument that you'd generated a list of all indexes into your array before walking the array. Instead, you walk the list of indexes, and use that to indirectly refer to the array. If at some point you remove an element from the array, which indexes are still valid and point to their original object? That would be all the indexes for slots before the object that was removed. All the indexes that point to slots at or after the removed object are invalidated (they either point to an element other than was originally intended, or point outside of the array).
That concept of invalidation is more general. It applies to pointers (more of a C/C++ thing) and iterators too. It doesn't matter if the positions in the list were generated up front, or on the fly. What matters is they are generated in a fixed manner, decided up front, which does not reflect later changes to the list.
You might say that indexes and pointers are just specific implementations of the more general concept of an iterator. When a container is modified, iterators that point into the container may be invalidated. Which iterators are invalidated may depend on both the type of container, and where the iterator currently points. The concept of invalidation of iterators is more conceptual, as there may not be any runtime error generated.
Example:
For arrays, removing an element may invalidate any iterators at or after the removed element.
Example:
For a linked list, removing an element may invalidate any iterators that point to the removed element (and only to that element).
By iterating the array in reverse, with a single iterator, the only positions that get invalidated are ones you've already processed, and so invalidation becomes a non-issue.
Note that I'm being a little sloppy about iterators pointing at the currently processed and removed item. Details here depend a bit on iterator implementation, which also depends on language and library implementation. In particular, some languages like C++ allow you to reference the same element as many times as you want through the iterator (
element = *iterator;), and have a separate operation for advancing the iterator (
iterator++;). Other language, which I believe include Python, only allow you to access the "
next" element (
element = next(iterator)), which immediately advances the iterator. In Python's case, once you capture the next element from an iterator moving in reverse, the iterator effectively already points to the element before the current element.
I'm also being a bit sloppy about iterator stop conditions. If a container changes, does the iterator know to update it's stopping condition? Or does it potentially run off the end of the container, or not iterator over newly added items. In many cases, iterators will refer back to the container in a live manner to check the size, so they don't run off the end of a container. In others, a shrinking container may invalidate the iterator, as it would otherwise eventually run off the end. That's a bit out of scope for this discussion though.
Applying this to your case, I think the code could look something like:
for object in reversed(LIST_Objects):
if object.fighter:
if object.fighter.Encounter_Type == 0:
Illusionary_Death(object)
Note that
reversed does not need to actually copy the list to iterate it in reverse. It accesses the elements in place, in reverse, on the fly.
Another suggestion I have, is to replace the
0 with a more meaningful named constant or enum value name.
And yes, that was also an interesting tidbit of code to look at.
Edit: Some references that might be worth reading:
https://stackoverflow.com/questions/529424/traverse-a-list-in-reverse-order-in-pythonhttps://realpython.com/python-range/