One thing you may wanna try that I never did (I envisioned it right when I decided to give up clicking) is giving enemies a bit more learning capacity. Perhaps assign each monster an ID number, and use a 2d array to act as the contents of their brains. Eg:

0 1 2 3 4 5 6 7 8 9 >Dimension X
Dimension Y

Dimension X is the ID number of the monster. Dimension Y is all his thoughts and memories. Imagine it like a clothes line (x dimension) - for each monster, you stick a piece of thread onto the clothes line and let it flop down (y dimension). Every time a monster has an experience, you write down the details on a post-it-note and pin them one after the other onto that monster's thread.

The kind of details you could potentially log, and how exactly you would do it, is up to you. Potentially you could let them form friendships, even group into packs, assigning an ID to each pack (so every monster would have a little post-it-note stuck on his thread saying 'Note to self: I am in pack number 3' or whatever). You could also add other behavioural details in another post-it-note, like 'I am married to monster #5'. That way if a monster is killed, you can check for any other monsters who 'cared' about that monster, and then make their AI go insane (mimicking vengeance or anger). Perhaps the degree of their reaction can be guaged by whether they were just an aquaintence, a friend, a close friend, or family. Alternately, if you really wanted to play around, how about monsters forming dislikes too? A post-it-note saying 'i despise #3 and wish he was dead'. That may motivate the enemy to run away rather than come to #3's aid in a firefight.

Obviously you can't go around having armies of hundreds of monsters all appearing to bond with their peers. The more threads you have and the more stuff you pin on those threads, the slower your game will be. What's more, you need to be able to code the AI responses to this data. This method will only tell you data (what monsters think what about which and why), it won't actually do the responses. You gotta code them yourself.

If you were to try this method, it'd be recommended to use smaller groups of monsters per level (between 10 and 20 would be a reasonable number if you've got a very elaborate AI in there).

Another trick that should theoretically also be possible with threaded memories is learning. Let's assume the monster has a number of basic reactions:
1. Do nothing
2. Dodge
3. Jump attack
4. Run and bite

Let's assume that the monster also categorises the outcomes of an attack as:
1. Successful Attack (whatever the monster did to the player, it did damage to the player)
2. Unsuccessful Attack (the player is immune to whatever attack this was)
3. Did nothing (the player did not respond to the attack. Maybe it was too quick for him?)
4. Close attack (the player had to use a close attack, such as the butt of his weapon)
5. Range attack (the player shot at the monster)
6. Pain (the player injured the monster)
7. Dodge (player dodged the attack, or the attack missed)

Suppose monster #4 attacks the player and just escapes with her life. She can now add a little post-it-note basically saying the following:
"I performed 'Run and Bite' (attack 4):
-Player Dodged (result 7)
-Player shot range attack(result 5)
-I got pwned (result 6)"

She now knows next time that if she does 'Run and Bite', the player may dodge. It certainly ended painfully, so our monster knows not to do this attack again. Instead she may try attack 3 (Jump attack). If she suffered greatly, she may choose to dodge or run from the player if she sees him rather than risk a fatal confrontation.

And hey, what the heck? Let's take stuff further.

She's injured, and a bit annoyed, so off she goes to get better, and there she meets another monster (we'll call him Bob). It turns out that Bob has met the player and also fought him. But Bob had more success! Bob managed to nearly kill the player.

Now they can exchange and compare post-it-notes. She can warn Bob not to try the RunAndBite attack, and he can tell her that the JumpAttack should work. As far as coding is concerned, they basically just copy each other's 'post-it-note' and add it to their own list of experiences.

So now BOTH monsters are better equiped to attack the player.

Depending on how much memory you're happy to use, you could also log data based on encounters rather than attacks. So instead of thinking 'what happened when I did my 'blah' attack', they can think 'well I've spotted the player 6 times today. What happened on each time?'

The monster may think 'well I saw him at a distance of 160px and he didn't attack me. The other time I saw him at a closer distance of 100px and he shot me. I had time to dodge. The third time I was at a distance of 160px again and he didn't attack...'

Just from this data the monster can conclude that 160px or greater is a safe distance to approach the player. 100 is definitely not. Anything between those may be, but is best avoided.

Lol, I have to stress I never bothered to test and see just how far you could push this - like I said, making the threading part is easy, it's actually building the AI responses that's the tricky part. I didn't have the motivation. But it'd sure be nice to see someone have a crack at it...

This is a bit of an abstract concept, so lemme show you how I would possibly make it work. Let us use as an example the memory thread of one monster. The data is divided into sections. Bold stuff shows groups of data (these wouldn't really exist in the array, they're just here to make it easier to understand), and the italics explain what each string in the array does.

5 (I have 5 aquaintances. Their details are as follows)
2,friend (Monster #2 is my friend)
3,friend (Monster #3 is my friend)
12,child (Monster #12 is my child)
8,mate (Monster #8 is my wife)[/i]
5,enemy (Monster #5 is my enemy)
3 (I've had 3 encounters with the player. See below for details)
me,4,1,30;him,4,1,6,10 (I used attack #4 and injured player by 30pts. Player did close attack and injured me by only 10 pts)
him,5,1,80;me,1 (Player attacked me from a distance (attack 5). I could do nothing, and took a massive 80pt hit. I fled (response 1, to do nothing or to flee))
me,3,1,60;me,1 (I attacked player (attack 3) and he took 60 damage. Player died, so I did not need to do anything else)