11"""
22 Rogue-like map utilitys such as line-of-sight, field-of-view, and path-finding.
3-
3+
44"""
55
66import itertools as _itertools
@@ -26,42 +26,42 @@ def _get_fov_type(fov):
2626
2727class Map (object ):
2828 """Fast field-of-view and path-finding on stored data.
29-
29+
3030 Set map conditions with the walkable and transparency attributes, this
3131 object can be iterated and checked for containment similar to consoles.
32-
32+
3333 For example, you can set all tiles and transparent and walkable with the
3434 following code::
35-
35+
3636 map = tdl.map.Map(80, 60)
3737 for x,y in map:
3838 map.transparent[x,y] = true
3939 map.walkable[x,y] = true
40-
40+
4141 @ivar transparent: Map transparency, access this attribute with
4242 map.transparency[x,y]
43-
43+
4444 Set to True to allow field-of-view rays, False will
4545 block field-of-view.
46-
46+
4747 Transparent tiles only affect field-of-view.
4848
4949 @ivar walkable: Map accessibility, access this attribute with
5050 map.walkable[x,y]
51-
51+
5252 Set to True to allow path-finding through that tile,
5353 False will block passage to that tile.
54-
54+
5555 Walkable tiles only affect path-finding.
56-
56+
5757 @ivar fov: Map tiles touched by a field-of-view computation,
5858 access this attribute with map.fov[x,y]
59-
59+
6060 Is True if a the tile is if view, otherwise False.
61-
61+
6262 You can set to this attribute if you want, but you'll typically
6363 be using it to read the field-of-view of a L{compute_fov} call.
64-
64+
6565 @since: 1.5.0
6666 """
6767
@@ -71,19 +71,19 @@ def __init__(self, map, bit_index):
7171 self .bit_index = bit_index
7272 self .bit = 1 << bit_index
7373 self .bit_inverse = 0xFF ^ self .bit
74-
74+
7575 def __getitem__ (self , key ):
7676 return bool (self .map ._array_cdata [key [1 ]][key [0 ]] & self .bit )
77-
77+
7878 def __setitem__ (self , key , value ):
7979 self .map ._array_cdata [key [1 ]][key [0 ]] = (
8080 (self .map ._array_cdata [key [1 ]][key [0 ]] & self .bit_inverse ) |
8181 (self .bit * bool (value ))
8282 )
83-
83+
8484 def __init__ (self , width , height ):
8585 """Create a new Map with width and height.
86-
86+
8787 @type width: int
8888 @type height: int
8989 @param width: Width of the new Map instance, in tiles.
@@ -100,25 +100,25 @@ def __init__(self, width, height):
100100 self .transparent = self ._MapAttribute (self , 0 )
101101 self .walkable = self ._MapAttribute (self , 1 )
102102 self .fov = self ._MapAttribute (self , 2 )
103-
103+
104104 def __del__ (self ):
105105 if self ._map_cdata :
106106 _lib .TCOD_map_delete (self ._map_cdata )
107107 self ._map_cdata = None
108-
108+
109109 def compute_fov (self , x , y , fov = 'PERMISSIVE' , radius = None , light_walls = True ,
110110 sphere = True , cumulative = False ):
111111 """Compute the field-of-view of this Map and return an iterator of the
112112 points touched.
113-
113+
114114 @type x: int
115115 @type y: int
116-
116+
117117 @param x: x center of the field-of-view
118118 @param y: y center of the field-of-view
119119 @type fov: string
120120 @param fov: The type of field-of-view to be used. Available types are:
121-
121+
122122 'BASIC', 'DIAMOND', 'SHADOW', 'RESTRICTIVE', 'PERMISSIVE',
123123 'PERMISSIVE0', 'PERMISSIVE1', ..., 'PERMISSIVE8'
124124 @type radius: int
@@ -129,15 +129,15 @@ def compute_fov(self, x, y, fov='PERMISSIVE', radius=None, light_walls=True,
129129 @param sphere: True for a spherical field-of-view.
130130 False for a square one.
131131 @type cumulative: boolean
132- @param cumulative:
133-
132+ @param cumulative:
133+
134134 @rtype: iter((x, y), ...)
135135 @return: An iterator of (x, y) points of tiles touched by the
136136 field-of-view.
137-
137+
138138 Unexpected behaviour can happen if you modify the Map while
139139 using the iterator.
140-
140+
141141 You can use the Map's fov attribute as an alternative to this
142142 iterator.
143143 """
@@ -146,7 +146,7 @@ def compute_fov(self, x, y, fov='PERMISSIVE', radius=None, light_walls=True,
146146 self ._array_cdata_flat )
147147 if radius is None : # infinite radius
148148 radius = max (self .width , self .height )
149- _lib .TCOD_map_compute_fov (self .cdata , x , y , radius , light_walls ,
149+ _lib .TCOD_map_compute_fov (self ._map_cdata , x , y , radius , light_walls ,
150150 _get_fov_type (fov ))
151151 _lib .TDL_map_fov_to_buffer (self ._map_cdata ,
152152 self ._array_cdata_flat , cumulative )
@@ -157,18 +157,18 @@ def iterate_fov():
157157 if (_array_cdata [y ][x ] & 4 ):
158158 yield (x , y )
159159 return iterate_fov ()
160-
161-
162-
160+
161+
162+
163163 def compute_path (self , start_x , start_y , dest_x , dest_y ,
164164 diagonal_cost = _math .sqrt (2 )):
165165 """Get the shortest path between two points.
166-
166+
167167 The start position is not included in the list.
168-
168+
169169 @type diagnalCost: float
170170 @param diagnalCost: Multiplier for diagonal movement.
171-
171+
172172 Can be set to zero to disable diagonal movement
173173 entirely.
174174 @rtype: [(x, y), ...]
@@ -191,32 +191,32 @@ def compute_path(self, start_x, start_y, dest_x, dest_y,
191191 finally :
192192 _lib .TCOD_path_delete (path_cdata )
193193 return path
194-
194+
195195 def __iter__ (self ):
196196 return _itertools .product (range (self .width ), range (self .height ))
197-
197+
198198 def __contains__ (self , position ):
199199 x , y = position
200200 return (0 <= x < self .width ) and (0 <= y < self .height )
201-
202-
203-
201+
202+
203+
204204class AStar (object ):
205205 """A* pathfinder
206-
206+
207207 Using this class requires a callback detailed in L{AStar.__init__}
208-
208+
209209 @undocumented: getPath
210210 """
211-
211+
212212 __slots__ = ('_as_parameter_' , '_callback' , '__weakref__' )
213-
214-
213+
214+
215215
216216 def __init__ (self , width , height , callback ,
217217 diagnalCost = _math .sqrt (2 ), advanced = False ):
218218 """Create an A* pathfinder using a callback.
219-
219+
220220 Before crating this instance you should make one of two types of
221221 callbacks:
222222 - A function that returns the cost to move to (x, y)
@@ -225,34 +225,34 @@ def __init__(self, width, height, callback,
225225 (destX, destY, sourceX, sourceY)
226226 If path is blocked the function should return zero or None.
227227 When using the second type of callback be sure to set advanced=True
228-
228+
229229 @type width: int
230230 @param width: width of the pathfinding area in tiles
231231 @type height: int
232232 @param height: height of the pathfinding area in tiles
233-
233+
234234 @type callback: function
235235 @param callback: A callback taking parameters depending on the setting
236236 of 'advanced' and returning the cost of
237237 movement for an open tile or zero for a
238238 blocked tile.
239-
239+
240240 @type diagnalCost: float
241241 @param diagnalCost: Multiplier for diagonal movement.
242-
242+
243243 Can be set to zero to disable diagonal movement
244244 entirely.
245-
245+
246246 @type advanced: boolean
247247 @param advanced: A simple callback with 2 positional parameters may not
248248 provide enough information. Setting this to True will
249249 call the callback with 2 additional parameters giving
250250 you both the destination and the source of movement.
251-
251+
252252 When True the callback will need to accept
253253 (destX, destY, sourceX, sourceY) as parameters.
254254 Instead of just (destX, destY).
255-
255+
256256 """
257257 if not diagnalCost : # set None or False to zero
258258 diagnalCost = 0.0
@@ -270,23 +270,23 @@ def newCallback(sourceX, sourceY, destX, destY, null):
270270 return 0.0
271271 # float(int, int, int, int, void*)
272272 self ._callback = _ffi .callback ('TCOD_path_func_t' )(newCallback )
273-
273+
274274 self ._as_parameter_ = _lib .TCOD_path_new_using_function (width , height ,
275275 self ._callback , _ffi .NULL , diagnalCost )
276-
276+
277277 def __del__ (self ):
278278 if self ._as_parameter_ :
279279 _lib .TCOD_path_delete (self ._as_parameter_ )
280280 self ._as_parameter_ = None
281-
281+
282282 def get_path (self , origX , origY , destX , destY ):
283283 """
284284 Get the shortest path from origXY to destXY.
285-
285+
286286 @rtype: [(x, y), ...]
287287 @return: Returns a list walking the path from origXY to destXY.
288288 This excludes the starting point and includes the destination.
289-
289+
290290 If no path is found then an empty list is returned.
291291 """
292292 found = _lib .TCOD_path_compute (self ._as_parameter_ , origX , origY , destX , destY )
@@ -298,22 +298,22 @@ def get_path(self, origX, origY, destX, destY):
298298 while _lib .TCOD_path_walk (self ._as_parameter_ , x , y , recalculate ):
299299 path .append ((x [0 ], y [0 ]))
300300 return path
301-
301+
302302def quick_fov (x , y , callback , fov = 'PERMISSIVE' , radius = 7.5 , lightWalls = True , sphere = True ):
303303 """All field-of-view functionality in one call.
304-
304+
305305 Before using this call be sure to make a function, lambda, or method that takes 2
306306 positional parameters and returns True if light can pass through the tile or False
307307 for light-blocking tiles and for indexes that are out of bounds of the
308308 dungeon.
309-
309+
310310 This function is 'quick' as in no hassle but can quickly become a very slow
311311 function call if a large radius is used or the callback provided itself
312312 isn't optimized.
313-
313+
314314 Always check if the index is in bounds both in the callback and in the
315315 returned values. These values can go into the negatives as well.
316-
316+
317317 @type x: int
318318 @param x: x center of the field-of-view
319319 @type y: int
@@ -324,42 +324,42 @@ def quick_fov(x, y, callback, fov='PERMISSIVE', radius=7.5, lightWalls=True, sph
324324 or False if the tile blocks light or is out of bounds.
325325 @type fov: string
326326 @param fov: The type of field-of-view to be used. Available types are:
327-
327+
328328 'BASIC', 'DIAMOND', 'SHADOW', 'RESTRICTIVE', 'PERMISSIVE',
329329 'PERMISSIVE0', 'PERMISSIVE1', ..., 'PERMISSIVE8'
330330 @type radius: float
331331 @param radius: Raduis of the field-of-view.
332-
332+
333333 When sphere is True a floating point can be used to fine-tune
334334 the range. Otherwise the radius is just rounded up.
335-
335+
336336 Be careful as a large radius has an exponential affect on
337337 how long this function takes.
338338 @type lightWalls: boolean
339339 @param lightWalls: Include or exclude wall tiles in the field-of-view.
340340 @type sphere: boolean
341341 @param sphere: True for a spherical field-of-view. False for a square one.
342-
342+
343343 @rtype: set((x, y), ...)
344344 @return: Returns a set of (x, y) points that are within the field-of-view.
345345 """
346346 trueRadius = radius
347347 radius = int (_math .ceil (radius ))
348348 mapSize = radius * 2 + 1
349349 fov = _get_fov_type (fov )
350-
350+
351351 setProp = _lib .TCOD_map_set_properties # make local
352352 inFOV = _lib .TCOD_map_is_in_fov
353-
353+
354354 tcodMap = _lib .TCOD_map_new (mapSize , mapSize )
355355 try :
356356 # pass no.1, write callback data to the tcodMap
357357 for x_ , y_ in _itertools .product (range (mapSize ), range (mapSize )):
358- pos = (x_ + x - radius ,
358+ pos = (x_ + x - radius ,
359359 y_ + y - radius )
360360 transparent = bool (callback (* pos ))
361361 setProp (tcodMap , x_ , y_ , transparent , False )
362-
362+
363363 # pass no.2, compute fov and build a list of points
364364 _lib .TCOD_map_compute_fov (tcodMap , radius , radius , radius , lightWalls , fov )
365365 touched = set () # points touched by field of view
@@ -371,14 +371,14 @@ def quick_fov(x, y, callback, fov='PERMISSIVE', radius=7.5, lightWalls=True, sph
371371 finally :
372372 _lib .TCOD_map_delete (tcodMap )
373373 return touched
374-
374+
375375def bresenham (x1 , y1 , x2 , y2 ):
376376 """
377377 Return a list of points in a bresenham line.
378-
378+
379379 Implementation hastily copied from RogueBasin.
380-
381- @return: Returns a list of (x, y) points, including both the start and
380+
381+ @return: Returns a list of (x, y) points, including both the start and
382382 endpoints.
383383 """
384384 points = []
@@ -413,8 +413,8 @@ def bresenham(x1, y1, x2, y2):
413413 if rev :
414414 points .reverse ()
415415 return points
416-
417-
416+
417+
418418__all__ = [_var for _var in locals ().keys () if _var [0 ] != '_' ]
419419
420420quickFOV = _style .backport (quick_fov )
0 commit comments