(norganizer) web status filter
[experiments.git] / evolution / systems.py
1
2 import pygame
3 import random
4
5 from scene import Scene
6 from utils import Vector
7
8
9 class PygameRenderer:
10 def __init__(self, width, height, name):
11 self.width = width
12 self.height = height
13 self.clock = pygame.time.Clock()
14 self.bg_color = pygame.Color("black")
15 self.screen = pygame.display.set_mode((width, height))
16 pygame.display.set_caption(name)
17 self.pygame = pygame
18
19 def toScreen(self, scene, point):
20 return (int(point[0] * self.width / scene.w), int(point[1] * self.height / scene.h))
21
22 def toWorld(self, scene, point):
23 return (float(point[0]) / self.width * scene.w, float(point[1]) / self.height * scene.h)
24
25 def update(self, scene):
26 self.screen.fill(self.bg_color)
27 toRender = scene.getByType(Scene.Types.DRAWABLE)
28 for e in toRender:
29 if (e.RENDER == Scene.Render.Good):
30 color = self.pygame.Color(e.color)
31 self.pygame.draw.rect(self.screen, color, pygame.Rect(self.toScreen(scene, e.pos), (4, 4)), 0)
32 elif (e.RENDER == Scene.Render.Bot):
33 color = self.pygame.Color(
34 min(255 - e.stats.get("color_red", 255), 255),
35 min(255 - e.stats.get("color_green", 255), 255),
36 min(255 - e.stats.get("color_blue", 255), 255)
37 )
38 self.pygame.draw.circle(self.screen, color, self.toScreen(scene, e.pos), 4, 0)
39
40 self.pygame.display.flip()
41
42 def close(self):
43 pass
44
45
46 class Movement:
47 def __init__(self):
48 pass
49
50 def update(self, scene):
51 def isValid(e, dv):
52 newPos = e.pos + dv
53 return (newPos[0] < scene.w and newPos[0] >= 0 and
54 newPos[1] < scene.h and newPos[1] >= 0)
55
56 entities = scene.getByType(Scene.Types.ALIVE)
57 for e in entities:
58 speed = e.stats.get("speed", 1)
59 e.velocity = (e.velocity + e.forces).truncate(speed)
60 if isValid(e, e.velocity):
61 e.move(e.velocity)
62 e.forces = Vector(0, 0)
63 # everybody has moved, let's rebuild the perf stuff
64 scene.spatialHash()
65
66 def close(self):
67 pass
68
69 class Behavior:
70 def __init__(self):
71 pass
72
73 def update(self, scene):
74 entities = scene.getByType(Scene.Types.ALIVE)
75 actions = [self.checkForFood, self.lookForFood, self.wander]
76 for entity in entities:
77 for action in actions:
78 if action(scene, entity): break
79
80 entity.stats["life"] = entity.stats["life"] - 1
81 if entity.stats["life"] == 0:
82 scene.logger.info("[%s] died by exhaustion. Was %s", entity, entity.getGenes())
83 entity.removeFromScene()
84 return
85
86 def checkForFood(self, scene, entity):
87 # Check if we can eat food
88 entities = scene.getAround(entity, 4, Scene.Types.GOODS)
89 for e in entities:
90 if e.type == Scene.GoodTypes.FOOD:
91 e.use(entity)
92 entity.behaviorData["target"] = None
93 return True
94 return False
95
96 def lookForFood(self, scene, entity):
97 target = entity.behaviorData.get("target", None)
98 if target is None:
99 # Check for surrounding food
100 perceptionDistance = entity.stats.get("perception", 1) * 4
101 entities = scene.getAround(entity, perceptionDistance, Scene.Types.GOODS)
102 for e in entities:
103 if e.type == Scene.GoodTypes.FOOD:
104 scene.logger.info("lookForFood: [%s] Found target %s", entity, e)
105 target = e
106 break
107 if target:
108 # And apply behavior
109 vector = (target.pos - entity.pos)
110 entity.forces += vector.normalize()
111 entity.behaviorData["target"] = target
112 return True
113 return False
114
115 def wander(self, scene, entity):
116 target = entity.behaviorData.get("wander", None)
117 count = entity.behaviorData.get("count", 10)
118 count -= 1
119 entity.behaviorData["count"] = count
120 if target is None or count == 0:
121 target = Vector(random.randint(0, scene.w), random.randint(0, scene.h))
122 entity.forces += (target - entity.pos).normalize()
123 entity.behaviorData["wander"] = target
124 entity.behaviorData["count"] = 10
125 return True
126
127 def close(self):
128 pass
129
130