239ad9ca1c7d7e42dabdda290978703f05003cdb
[experiments.git] / evolution / entities.py
1
2 import copy
3 import random
4
5 from utils import SceneLogger, Vector
6
7 class Scene:
8 class Types:
9 DRAWABLE = "Drawable"
10 PHYSICAL = "Physical"
11 ALIVE = "Alive"
12 GOODS = "Goods"
13
14 class GoodTypes:
15 FOOD = "Food"
16
17 def __init__(self, name, clock):
18 self.name = name
19 self.clock = clock
20 self.all = set()
21 self.byType = {}
22 self.byEntity = {}
23 self.logger = SceneLogger(self)
24
25 def add(self, entity):
26 self.logger.debug("Scene: add %s", entity)
27 self.all.add(entity)
28 for type in entity.TYPES:
29 self.byType.setdefault(type, []).append(entity)
30
31 def remove(self, entity):
32 self.logger.debug("Scene: remove %s", entity)
33 self.all.remove(entity)
34 for type in entity.TYPES:
35 entities = self.byType.get(type, [])
36 if entity in entities: entities.remove(entity)
37
38 def getByType(self, type):
39 return self.byType.get(type, [])
40
41 def getAt(self, entity, type):
42 return [e for e in self.getByType(type) if (e.pos[0] == entity.pos[0] and e.pos[1] == entity.pos[1])]
43
44 def getAround(self, entity, distance, type):
45 def isAround(e):
46 return (e.pos - entity.pos).magnitude() < distance
47 return [e for e in self.getByType(type) if isAround(e)]
48
49
50 _entityCounter = 0
51
52 class Entity(object):
53 TYPES = []
54 def __init__(self):
55 global _entityCounter
56 self.id = _entityCounter
57 _entityCounter += 1
58
59 def __repr__(self):
60 return "%s(%d)" % (self.__class__.__name__, self.id)
61
62
63 class Physical(Entity):
64 TYPES = Entity.TYPES + [Scene.Types.DRAWABLE, Scene.Types.PHYSICAL]
65 def __init__(self, pos, walkable=True):
66 super(Physical, self).__init__()
67 self.scene = None
68 self.pos = pos
69 self.walkable = walkable
70
71 def addToScene(self, scene):
72 self.scene = scene
73 self.scene.add(self)
74 return self
75
76 def removeFromScene(self):
77 self.scene.remove(self)
78 self.scene = None
79 return self
80
81 def move(self, dv):
82 self.pos += dv
83 return self
84
85 def at(self, newPos):
86 self.pos = newPos
87 return self
88
89
90 class Good(Physical):
91 TYPES = Physical.TYPES + [Scene.Types.GOODS]
92 def __init__(self, pos):
93 super(Good, self).__init__(pos, False)
94 self.type = Scene.GoodTypes.FOOD
95 self.value = 5
96
97 def getRenderColor(self):
98 return "blue"
99
100 def use(self, e):
101 e.stats["life"] += self.value
102 self.removeFromScene()
103
104
105 class Bot(Physical):
106 TYPES = Physical.TYPES + [Scene.Types.ALIVE]
107 def __init__(self, pos):
108 super(Bot, self).__init__(pos, True)
109 self.direction = Vector(0, 0)
110 self.genes = []
111 self.stats = {"life": 10, "speed": 1}
112 self.stamina = 10
113 self.behavior = None
114 self.behaviorData = {}
115
116 def addGene(self, gene):
117 self.genes.append(gene)
118 gene.apply(self)
119 return self
120
121 def getGenes(self):
122 return self.genes
123
124 def getRenderColor(self):
125 return "red"
126
127
128 class Gene(object):
129 def __init__(self):
130 self.name = self.__class__.__name__
131 self.attribute = ""
132 self.modifier = 0
133
134 def apply(self, entity):
135 stat = entity.stats.setdefault(self.attribute, 0)
136 if stat + self.modifier >= 0:
137 entity.stats[self.attribute] = stat + self.modifier
138 return self
139
140 def __repr__(self):
141 return "%s" % (self.name)
142
143
144 class LongLegs(Gene):
145 def __init__(self):
146 super(LongLegs, self).__init__()
147 self.attribute = "speed"
148 self.modifier = 1
149
150 class ShortLegs(Gene):
151 def __init__(self):
152 super(ShortLegs, self).__init__()
153 self.attribute = "speed"
154 self.modifier = -1
155
156 class ClassicBeauty(Gene):
157 def __init__(self):
158 super(ClassicBeauty, self).__init__()
159 self.attribute = "charisma"
160 self.modifier = 1
161
162 class ExoticBeauty(Gene):
163 def __init__(self):
164 super(ExoticBeauty, self).__init__()
165 self.attribute = "charisma"
166 self.modifier = 2
167
168 class Eyes(Gene):
169 def __init__(self):
170 super(Eyes, self).__init__()
171 self.attribute = "perception"
172 self.modifier = 2
173
174
175 import inspect, sys
176 GENES = dict(inspect.getmembers(sys.modules[__name__], lambda member: inspect.isclass(member) and member.__module__ == __name__ and issubclass(member, Gene)))
177 del GENES["Gene"]
178 GENE_NAMES = GENES.keys()
179 GENE_NAMES.sort()
180 print "Available genes: ", GENE_NAMES
181