comparison gamelib/animal.py @ 395:2d0ff46118e2

Basic support for z coordinate
author Neil Muller <drnlmuller@gmail.com>
date Thu, 12 Nov 2009 21:14:21 +0000
parents ad77b3b71b08
children 19e583e5cdc0
comparison
equal deleted inserted replaced
394:ad77b3b71b08 395:2d0ff46118e2
24 Sprite.__init__(self, image_left, (-1000, -1000)) 24 Sprite.__init__(self, image_left, (-1000, -1000))
25 self._image_left = image_left 25 self._image_left = image_left
26 self.image_left = image_left.copy() 26 self.image_left = image_left.copy()
27 self._image_right = image_right 27 self._image_right = image_right
28 self.image_right = image_right.copy() 28 self.image_right = image_right.copy()
29 if hasattr(tile_pos, 'to_tuple'): 29 if hasattr(tile_pos, 'to_tile_tuple'):
30 self.pos = tile_pos 30 self.pos = tile_pos
31 else: 31 else:
32 self.pos = Position(tile_pos[0], tile_pos[1]) 32 self.pos = Position(tile_pos[0], tile_pos[1], 0)
33 self.equipment = [] 33 self.equipment = []
34 self.accoutrements = [] 34 self.accoutrements = []
35 self.abode = None 35 self.abode = None
36 self.facing = 'left' 36 self.facing = 'left'
37 37
38 def loop(self, tv, _sprite): 38 def loop(self, tv, _sprite):
39 ppos = tv.tile_to_view(self.pos.to_tuple()) 39 ppos = tv.tile_to_view(self.pos.to_tile_tuple())
40 self.rect.x = ppos[0] 40 self.rect.x = ppos[0]
41 self.rect.y = ppos[1] 41 self.rect.y = ppos[1]
42 42
43 def die(self, gameboard): 43 def die(self, gameboard):
44 """Play death animation, noises, whatever.""" 44 """Play death animation, noises, whatever."""
45 if hasattr(self, 'DEATH_SOUND'): 45 if hasattr(self, 'DEATH_SOUND'):
46 sound.play_sound(self.DEATH_SOUND) 46 sound.play_sound(self.DEATH_SOUND)
47 if hasattr(self, 'DEATH_ANIMATION'): 47 if hasattr(self, 'DEATH_ANIMATION'):
48 self.DEATH_ANIMATION(gameboard.tv, self.pos.to_tuple()) 48 self.DEATH_ANIMATION(gameboard.tv, self.pos.to_tile_tuple())
49 self._game_death(gameboard) 49 self._game_death(gameboard)
50 50
51 def _game_death(self, gameboard): 51 def _game_death(self, gameboard):
52 # Call appropriate gameboard cleanup here. 52 # Call appropriate gameboard cleanup here.
53 pass 53 pass
272 def _game_death(self, gameboard): 272 def _game_death(self, gameboard):
273 gameboard.kill_fox(self) 273 gameboard.kill_fox(self)
274 274
275 def _cost_tile(self, pos, gameboard): 275 def _cost_tile(self, pos, gameboard):
276 if gameboard.in_bounds(pos): 276 if gameboard.in_bounds(pos):
277 this_tile = gameboard.tv.get(pos.to_tuple()) 277 this_tile = gameboard.tv.get(pos.to_tile_tuple())
278 cost = self.costs.get(tiles.TILE_MAP[this_tile], 100) 278 cost = self.costs.get(tiles.TILE_MAP[this_tile], 100)
279 else: 279 else:
280 cost = 100 # Out of bounds is expensive 280 cost = 100 # Out of bounds is expensive
281 return cost 281 return cost
282 282
292 excluding start_pos""" 292 excluding start_pos"""
293 if abs(start_pos.x - final_pos.x) < 2 and \ 293 if abs(start_pos.x - final_pos.x) < 2 and \
294 abs(start_pos.y - final_pos.y) < 2: 294 abs(start_pos.y - final_pos.y) < 2:
295 # pgu gets this case wrong on occasion. 295 # pgu gets this case wrong on occasion.
296 return [final_pos] 296 return [final_pos]
297 start = start_pos.to_tuple() 297 start = start_pos.to_tile_tuple()
298 end = final_pos.to_tuple() 298 end = final_pos.to_tile_tuple()
299 points = getline(start, end) 299 points = getline(start, end)
300 points.remove(start) # exclude start_pos 300 points.remove(start) # exclude start_pos
301 if end not in points: 301 if end not in points:
302 # Rounding errors in getline cause this 302 # Rounding errors in getline cause this
303 points.append(end) 303 points.append(end)
305 305
306 def _find_best_path_step(self, final_pos, gameboard): 306 def _find_best_path_step(self, final_pos, gameboard):
307 """Find the cheapest path to final_pos, and return the next step 307 """Find the cheapest path to final_pos, and return the next step
308 along the path.""" 308 along the path."""
309 # We calculate the cost of the direct path 309 # We calculate the cost of the direct path
310 if final_pos.z < self.pos.z:
311 # We need to try heading down.
312 return Position(self.pos.x, self.pos.y, self.pos.z - 1)
310 direct_path = self._gen_path(self.pos, final_pos) 313 direct_path = self._gen_path(self.pos, final_pos)
311 min_cost = self._cost_path(direct_path, gameboard) 314 min_cost = self._cost_path(direct_path, gameboard)
312 min_path = direct_path 315 min_path = direct_path
313 # is there a point nearby that gives us a cheaper direct path? 316 # is there a point nearby that gives us a cheaper direct path?
314 # This is delibrately not finding the optimal path, as I don't 317 # This is delibrately not finding the optimal path, as I don't
362 return self.pos 365 return self.pos
363 if self.closest.pos == self.pos: 366 if self.closest.pos == self.pos:
364 # Caught a chicken 367 # Caught a chicken
365 self._catch_chicken(self.closest, gameboard) 368 self._catch_chicken(self.closest, gameboard)
366 return self.pos 369 return self.pos
370 if self.closest.pos.to_tile_tuple() == self.pos.to_tile_tuple():
371 # Only differ in z, so next step is in z
372 if self.closest.pos.z < self.pos.z:
373 new_z = self.pos.z - 1
374 else:
375 new_z = self.pos.z + 1
376 return Position(self.pos.x, self.pos.y, new_z)
367 return self._find_best_path_step(self.closest.pos, gameboard) 377 return self._find_best_path_step(self.closest.pos, gameboard)
368 378
369 def _catch_chicken(self, chicken, gameboard): 379 def _catch_chicken(self, chicken, gameboard):
370 """Catch a chicken""" 380 """Catch a chicken"""
371 chicken.damage(gameboard) 381 chicken.damage(gameboard)
377 """Update the position, making sure we don't step on other foxes""" 387 """Update the position, making sure we don't step on other foxes"""
378 if new_pos == self.pos: 388 if new_pos == self.pos:
379 # We're not moving, so we can skip all the checks 389 # We're not moving, so we can skip all the checks
380 return new_pos 390 return new_pos
381 final_pos = new_pos 391 final_pos = new_pos
382 blocked = final_pos in self.last_steps 392 blocked = False # We don't worry about loops on ladders
383 moves = [Position(x, y) for x in range(self.pos.x-1, self.pos.x + 2) 393 if new_pos.z != self.pos.z:
384 for y in range(self.pos.y-1, self.pos.y + 2) 394 # We can only move up and down a ladder
385 if Position(x,y) != self.pos and \ 395 moves = [Position(self.pos.x, self.pos.y, z) for z
386 Position(x, y) not in self.last_steps] 396 in range(self.pos.z-1, self.pos.z + 2) if z >= 0]
397 else:
398 blocked = final_pos in self.last_steps
399 moves = [Position(x, y) for x in range(self.pos.x-1, self.pos.x + 2)
400 for y in range(self.pos.y-1, self.pos.y + 2)
401 if Position(x,y) != self.pos and
402 Position(x, y) not in self.last_steps and self.pos.z == 0]
387 for fox in gameboard.foxes: 403 for fox in gameboard.foxes:
388 if fox is not self and fox.pos == final_pos: 404 if fox is not self and fox.pos == final_pos:
389 blocked = True 405 blocked = True
390 if fox.pos in moves: 406 if fox.pos in moves:
391 moves.remove(fox.pos) 407 moves.remove(fox.pos)
403 final_pos = poss 419 final_pos = poss
404 if not final_pos: 420 if not final_pos:
405 # No good choice, so stay put 421 # No good choice, so stay put
406 return self.pos 422 return self.pos
407 if gameboard.in_bounds(final_pos): 423 if gameboard.in_bounds(final_pos):
408 this_tile = gameboard.tv.get(final_pos.to_tuple()) 424 this_tile = gameboard.tv.get(final_pos.to_tile_tuple())
409 else: 425 else:
410 this_tile = tiles.REVERSE_TILE_MAP['woodland'] 426 this_tile = tiles.REVERSE_TILE_MAP['woodland']
411 if tiles.TILE_MAP[this_tile] == 'broken fence' and self.hunting: 427 if tiles.TILE_MAP[this_tile] == 'broken fence' and self.hunting:
412 # We'll head back towards the holes we make/find 428 # We'll head back towards the holes we make/find
413 self.landmarks.append(final_pos) 429 self.landmarks.append(final_pos)
424 self.tick = 5 440 self.tick = 5
425 self.dig_pos = dig_pos 441 self.dig_pos = dig_pos
426 442
427 def _make_hole(self, gameboard): 443 def _make_hole(self, gameboard):
428 """Make a hole in the fence""" 444 """Make a hole in the fence"""
429 fence = gameboard.get_building(self.dig_pos.to_tuple()) 445 fence = gameboard.get_building(self.dig_pos.to_tile_tuple())
430 # Another fox could have made the same hole this turn 446 # Another fox could have made the same hole this turn
431 if fence: 447 if fence:
432 fence.damage(gameboard.tv) 448 fence.damage(gameboard.tv)
433 self.dig_pos = None 449 self.dig_pos = None
434 450
440 self.tick -= 1 456 self.tick -= 1
441 # We're still digging through the fence 457 # We're still digging through the fence
442 # Check the another fox hasn't dug a hole for us 458 # Check the another fox hasn't dug a hole for us
443 # We're too busy digging to notice if a hole appears nearby, 459 # We're too busy digging to notice if a hole appears nearby,
444 # but we'll notice if the fence we're digging vanishes 460 # but we'll notice if the fence we're digging vanishes
445 this_tile = gameboard.tv.get(self.dig_pos.to_tuple()) 461 this_tile = gameboard.tv.get(self.dig_pos.to_tile_tuple())
446 if tiles.TILE_MAP[this_tile] == 'broken fence': 462 if tiles.TILE_MAP[this_tile] == 'broken fence':
447 self.tick = 0 463 self.tick = 0
448 return 464 return
449 else: 465 else:
450 # We've dug through the fence, so make a hole 466 # We've dug through the fence, so make a hole
478 494
479 def _dig(self, gameboard, dig_pos): 495 def _dig(self, gameboard, dig_pos):
480 """Setup dig parameters, to be overridden if needed""" 496 """Setup dig parameters, to be overridden if needed"""
481 self.tick = 0 # Costs us nothing to go through a fence. 497 self.tick = 0 # Costs us nothing to go through a fence.
482 self.dig_pos = dig_pos 498 self.dig_pos = dig_pos
483 self.DIG_ANIMATION(gameboard.tv, dig_pos.to_tuple()) 499 self.DIG_ANIMATION(gameboard.tv, dig_pos.to_tile_tuple())
484 self._make_hole(gameboard) 500 self._make_hole(gameboard)
485 501
486 class GreedyFox(Fox): 502 class GreedyFox(Fox):
487 """Greedy foxes eat more chickens""" 503 """Greedy foxes eat more chickens"""
488 CONFIG_NAME = 'greedy fox' 504 CONFIG_NAME = 'greedy fox'
511 self.hunting = False 527 self.hunting = False
512 self.last_steps = [] 528 self.last_steps = []
513 529
514 def _make_hole(self, gameboard): 530 def _make_hole(self, gameboard):
515 """The Rinkhals eats fences""" 531 """The Rinkhals eats fences"""
516 fence = gameboard.get_building(self.dig_pos.to_tuple()) 532 fence = gameboard.get_building(self.dig_pos.to_tile_tuple())
517 if fence: 533 if fence:
518 fence.remove(gameboard.tv) 534 fence.remove(gameboard.tv)
519 gameboard.remove_building(fence) 535 gameboard.remove_building(fence)
520 self.dig_pos = None 536 self.dig_pos = None
521 537