Mercurial > rinkhals
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 |