I'd like to point out something else: You can have monsters that walk through other monsters, through players, certain walls, etc while still acting solid to other objects. Create wrapper functions for movetogoal and walkmove, and have those same wrappers call the same code as player pre think and post think are calling.
pseudo-code:
void movetogoal(float dist)
{
desolidify_targets();
movetogoal_real(dist);
solidify_targets();
}
You could make a ghost monster that moves through certain walls of the level that are solid to the player and other monsters. It also moves through players and other monsters. The other monsters won't get stuck as long as they are making the ghost non-solid with their movetogoal, as it does to them.
Summoning monsters is problematic when you don't want that monster blocking player movement. Setting .owner is a good way to let the summoner move through as though the monster wasn't solid, while still allowing enemy bullets to hit the monster. However, teammates cannot travel through it in this way. If you marked them as non-solid to each other though, they could pass through the monster and the monster could pass through them.
Making a swarm of monsters non-solid to each other but not anything else also helps with swarm mechanics so that they don't get stuck trying to go around each other.
One problem though is natural movement, like falling, jumping, etc. The monsters will still interact with the world during such movement. At that point you may prefer SOLID_CORPSE for some of these features.