Slots to the rescue!
I didn't really have much time to work on this, but I did a bit of refactoring: removed all inheritance, and added __slots__ to all the classes. The result? It now runs on the hardware without memory errors!I still want to do level loading directly from the file, because then I can have large levels not limited by memory, but I'm already happy with this outcome.
Slowly thinking about the AI for the monsters, I think I will have a couple of different behaviors, randomly assigned to them, so that they don't just lump into one group in a corner somewhere.