5 Simple class for position information. Implements 'comparable
6 interface' by implementing __cmp__ -method. Comparing is based purely
7 on distances between two Position-instances.
9 def __init__(self
, x
, y
):
15 >>> pos = Position(3,4)
23 >>> pos = Position(5,6)
29 def __add__(self
, other
):
30 return Position(self
.x() + other
.x(), self
.y() + other
.y())
32 def __sub__(self
, other
):
33 return Position(self
.x() - other
.x(), self
.y() - other
.y())
35 def distance(self
, other
):
37 Counts the distance between self and other.
40 >>> origin = Position(0,0)
41 >>> origin.distance(Position(0,0))
43 >>> origin.distance(Position(5,7))
45 >>> origin.distance(origin)
47 >>> pos = Position(2,4)
48 >>> pos.distance(Position(6,7))
51 delta_x
= self
.x() - other
.x()
52 delta_y
= self
.y() - other
.y()
53 return math
.sqrt(math
.pow(delta_x
, 2) + math
.pow(delta_y
, 2))
55 def __cmp__(self
, other
):
57 >>> origin = Position(0,0)
60 >>> origin == Position(0,0)
62 >>> origin <= (origin)
64 >>> origin >= (origin)
66 >>> origin != (origin)
68 >>> origin < Position(3,4)
70 >>> Position(5,5) > Position(4,1)
73 origin
= Position(0,0)
74 return self
.distance(origin
) - other
.distance(origin
)
78 Symbolic representation for the use of different objects. Every symbol
79 contains char+color -combination the be represented in the maps of the
80 game. Every symbol can be also referenced by an unique_char. At the
81 moment, it's up to the developer to take care of uniqueness of these
82 unique_chars. It's also up to the developer to take care of the
83 relationship between unique_char and char+color -combination.
86 def __init__(self
, char
, color
, unique_char
):
88 self
.__color
__ = color
89 self
.__unique
_char
__ = unique_char
97 def unique_char(self
):
98 return self
.__unique
_char
__
100 def __eq__(self
, other
):
102 >>> Symbol('^', 7, 'a') == Symbol('!', 3, 'a')
104 >>> Symbol('=', 1, 'b') == Symbol('=', 2, 'c')
106 >>> Symbol('=', 1, 'b') == Symbol('=', 1, 'c')
109 return self
.unique_char() == other
.unique_char()
116 Abstract baseclass for every object in the game. At minimum, every
117 object has a position information, a symbolic (color + char)
118 representation and a description which reveals it's deepest essence to
121 def __init__(self
, position
, symbol
, description
):
122 self
.__pos
__ = position
123 self
.__sym
__ = symbol
124 self
.__desc
__ = description
126 def move(self
, direction
):
128 Parameter direction is a kind of direction vector, still being
129 instance of Position-class. It represents the new relative
130 position of this object.
133 >>> o = Object(Position(4,5),None, None)
134 >>> o.move(Position(0,1)) # North
135 >>> Position(4,6) == o.position() # Assume 'speed' == 1
138 self
.__pos
__ = self
.position() + direction
146 def description(self
):
150 return self
.symbol().__str
__()
154 def __init__(self
, position
, symbol
, description
=""):
155 Object
.__init
__(self
, position
, symbol
, description
)
158 class WorldException(Exception):
160 Baseclass for every exception that Map-class may throw.
166 def __init__(self
, width
, height
):
167 self
.__height
__ = height
168 self
.__width
__ = width
170 def surfacearea(self
):
172 >>> Map(4,5,None).surfacearea()
175 return self
.width() * self
.height()
177 def has_position(self
, pos
):
179 >>> m = Map(5,5, None)
180 >>> m.has_position(Position(3,3))
182 >>> m.has_position(Position(6,1))
184 >>> m.has_position(Position(5,5))
187 return pos
.x() < self
.width() and pos
.y() < self
.height()
190 return self
.__height
__
193 return self
.__width
__
195 def __position__(self
, i
):
200 def __index__(self
, pos
):
201 return pos
.y() * self
.width() + pos
.x()
203 class StoringRectangleArea(RectangleArea
):
204 def __init__(self
, width
, height
, empty_symbol
):
205 RectangleArea
.__init
__(self
, width
, height
)
206 self
.__empty
_symbol
__ = empty_symbol
208 self
.__init
_items
__()
210 def __init_items__(self
):
211 for i
in range(self
.surfacearea()):
212 pos
= self
.__position
__(i
)
213 t
= Tile(pos
, self
.empty_symbol(), "Space. Cold.")
214 self
.__items
__.append(t
)
217 def is_complete(self
):
219 Returns a boolean value that indicates whether every position
220 in the area is populated by a item. If there is even one
221 empty_symbol, this method returns false.
226 >>> WATER = world.Symbol('=', 1, 'a')
227 >>> DESERT = world.Symbol('.', 3, 'b')
228 >>> area = Map(2,2,None)
232 if item
.symbol() == self
.empty_symbol():
236 def reserved(self
, pos
):
238 if item
.symbol() != self
.empty_symbol():
242 def empty_symbol(self
):
243 return self
.__empty
_symbol
__
246 i
= self
.__index
__(pos
)
247 return self
.__items
__[i
]
250 return self
.__items
__.__iter
__()
252 # def fromlist(self, tiles, replace=False):
254 # Inserts tiles from the given list.
256 # if len(tiles) != self.surfacearea():
257 # raise WorldException("Data does not fit into the map.")
258 # raise WorldException("Not yet implemented.")
260 def insert(self
, tile
, replace
=False):
262 Public interface for inserting tiles into the map.
263 Overrides Map's __insert-method and adds handling for replacing
264 inserts. Throws WorldException if there is already a tile in
265 position (x,y) and replacing is not allowed. By default,
266 replacing is forbidden.
268 pos
= tile
.position()
269 if self
.reserved(pos
) and not replace
:
270 raise WorldException("Position %s is reserved." % pos
)
271 i
= self
.__index
__(pos
)
272 self
.__items
__[i
] = tile
279 def __init__(self
, type, object):
281 self
.__object
__ = object
287 return self
.__object
__
290 class Map(StoringRectangleArea
):
292 Class to represent rectangle-shaped areas populated by different kinds
293 of tiles. Tiles are accessed using coordinate-like attributes.
295 def __init__(self
, width
, height
, empty_symbol
):
296 StoringRectangleArea
.__init
__(self
, width
, height
, empty_symbol
)
297 self
.__observers
__ = set()
299 def add_observer(self
, observer
):
300 self
.__observers
__.add(observer
)
302 def remove_observer(self
, observer
):
303 self
.__observers
__.discard(observer
)
305 def notify_observers(self
, event
):
306 for observer
in self
.__observers
__:
307 observer
.map_event(event
)
309 def insert(self
, tile
, replace
=False):
311 Public interface for inserting tiles into the map.
312 Overrides Map's __insert-method and adds handling for replacing
313 inserts. Throws WorldException if there is already a tile in
314 position (x,y) and replacing is not allowed. By default,
315 replacing is forbidden.
317 self
.notify_observers(MapEvent(MapEvent
.BEFORE_INSERT
, tile
))
318 StoringRectangleArea
.insert(self
, tile
, replace
)
319 self
.notify_observers(MapEvent(MapEvent
.AFTER_INSERT
, tile
))
325 if __name__
== "__main__":