changeset 34:2d976c526ad4

a little smarter monsters
author Radomir Dopieralski <sheep-devel@sheep.art.pl>
date Tue, 23 Aug 2011 19:03:59 +0200
parents deb53da4ef98
children 258867e11432
files main.py monster.py
diffstat 2 files changed, 52 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/main.py	Tue Aug 23 18:31:39 2011 +0200
+++ b/main.py	Tue Aug 23 19:03:59 2011 +0200
@@ -51,7 +51,8 @@
                 if m.dead:
                     del self.level.monsters[(m.x, m.y)]
             for m in monsters:
-                m.act(self.level)
+                if not m.dead:
+                    m.act(self.level)
             for m in monsters:
                 for d, effect in enumerate(m.effects):
                     effect.render(self.display, delay=d * 12)
--- a/monster.py	Tue Aug 23 18:31:39 2011 +0200
+++ b/monster.py	Tue Aug 23 19:03:59 2011 +0200
@@ -8,6 +8,13 @@
 import display
 
 
+dirs = [(0, 1), (0, -1), (1, 0), (-1, 0)]
+
+
+def distance(x1, y1, x2, y2):
+    return abs(x1 - x2) + abs(y1 - y2)
+
+
 class MonsterSprite(display.Sprite):
     def __init__(self, x, y, tx):
         self.tx = tx
@@ -71,10 +78,12 @@
             self.rect.move_ip(0, frame - 1)
         self.kill()
 
+
 class Monster(thing.Thing):
     tx = 0
     max_hp = 4
     name = "monster"
+    alpha = None
 
     def __init__(self, x, y):
         self.x, self.y = x, y
@@ -84,6 +93,9 @@
 
     def render(self, to_display):
         self.sprite = MonsterSprite(self.x, self.y, self.tx)
+        if self.alpha:
+            for frame in self.sprite.frames[self.tx]:
+                frame.set_alpha(self.alpha)
         to_display.sprites.add(self.sprite)
         to_display.sprites.add(thing.ShadowSprite(self.sprite))
 
@@ -102,14 +114,20 @@
         self.sprite.animation.next()
 
     def act(self, level):
-        if self.dead:
+        # Attack if standing next to the hero
+        if distance(level.hero.x, level.hero.y, self.x, self.y) == 1:
+            self.walk(level, level.hero.x - self.x, level.hero.y - self.y)
             return
-        try:
-            dx, dy = random.choice([(dx, dy) for (dx, dy) in
-                (0, 1), (0, -1), (1, 0), (-1, 0)
-                if not level.is_blocked(self.x+dx, self.y+dy)])
-        except IndexError:
+
+        # Walk towards the hero
+        possible = [(dx, dy) for (dx, dy) in dirs if
+                    not level.is_blocked(self.x+dx, self.y+dy)]
+        if not possible:
             return
+        random.shuffle(possible)
+        dx, dy = min(possible,
+            key=lambda d: distance(level.hero.x, level.hero.y,
+                                        self.x+d[0], self.y+d[1]))
         self.walk(level, dx, dy)
 
     def walk(self, level, dx, dy):
@@ -131,37 +149,57 @@
 class Skeleton(Monster):
     tx = 0
     name = "skeleton"
+    max_hp = 4
 
 
 class Zombie(Monster):
     tx = 1
     name = "zombie"
+    max_hp = 7
 
 
 class Jack(Monster):
     tx = 2
     name = "jack"
+    max_hp = 8
+
 
 class Bat(Monster):
     tx = 3
     name = "bat"
+    max_hp = 2
+
+    def act(self, level):
+        # Attack if we feel like it
+        if random.choice([True, False]):
+            if distance(level.hero.x, level.hero.y, self.x, self.y) == 1:
+                self.walk(level, level.hero.x - self.x, level.hero.y - self.y)
+                return
+
+        # Move randomly (very annoying)
+        possible = [(dx, dy) for (dx, dy) in dirs if
+                    not level.is_blocked(self.x+dx, self.y+dy)]
+        if not possible:
+            return
+        dx, dy = random.choice(possible)
+        self.walk(level, dx, dy)
 
 
 class Ghost(Monster):
     tx = 4
     name = "ghost"
-
-    def render(self, *args, **kwargs):
-        super(Ghost, self).render(*args, **kwargs)
-        for frame in self.sprite.frames[self.tx]:
-            frame.set_alpha(192)
+    max_hp = 5
+    alpha = 192
 
 
 class Eye(Monster):
     tx = 5
     name = "eye"
+    max_hp = 7
 
 
-class Jelly(Ghost):
+class Jelly(Monster):
     tx = 6
     name = "jelly"
+    max_hp = 6
+    alpha = 192