def _place_random_creatures(new_map, player): start_region = new_map.region[player.pos.x][player.pos.y] terrain_chances = { 'lake' : { None : 10 }, 'marsh' : { None : 10, bestiary.swamp_goblin : 10 }, 'desert' : { None : 20, bestiary.hyena_pair : 5, bestiary.gazelle : 10 }, 'scrub' : { None : 20, bestiary.hyena : 2, bestiary.gazelle : 4, bestiary.deer : 4, bestiary.wolf : 2 }, 'forest' : { None : 20, bestiary.deer : 10, bestiary.wolf_pair : 5, bestiary.bear : 3 }, 'rock' : { None : 10, bestiary.snow_leopard : 1 }, 'ice' : { None : 10, bestiary.snow_leopard : 1 } } for r in range(len(new_map.region_seeds)): if (r == start_region or (new_map.quarry_regions and r in new_map.quarry_regions)): continue fn = _random_choice(terrain_chances[new_map.region_terrain[r]]) if fn is not None: pos = algebra.Location(new_map.region_seeds[r][0], new_map.region_seeds[r][1]) while new_map.is_blocked_at(pos): pos += actions.random_direction() pos.bound(algebra.Rect(0, 0, new_map.width-1, new_map.height-1)) if new_map.caravanserai and new_map.caravanserai.bounds.contains(pos): continue # print('Creature in region ' + str(r) + ' at ' + str(pos.x) + ' ' + str(pos.y)) fn(new_map, pos, player)
def ignoring_monster(monster, player, metadata): """ A creature that moves randomly (q.v. confused_monster) and ignores the player unless hurt, in which case it becomes hostile or scared. """ _spotting(monster, metadata) if metadata.active_turns > 0: metadata.active_turns -= 1 if monster.fighter.last_attacker: if monster.fighter.unarmed_damage > 2: monster.ai = AI( hostile_monster, hostile_monster_metadata(monster.fighter.last_attacker)) else: monster.old_ai = monster.ai monster.ai = AI( fleeing_monster, hostile_monster_metadata(monster.fighter.last_attacker)) monster.ai.set_owner(monster) return monster.ai.take_turn(player) # TODO: this movement may fail, so the monster will appear to # move less when in constricted quarters. if metadata.on_idle and not metadata.on_idle(player): actions.move(monster, actions.random_direction())
def territorial_monster(monster, player, metadata): """ Move randomly but near home until approached or hurt """ _spotting(monster, metadata) if metadata.active_turns > 0: metadata.active_turns -= 1 # In the grander scheme of things this should reset to territorial # after killing its prey, but that doesn't matter so long as we only # go hostile on the player. if monster.fighter.last_attacker: monster.ai = AI( hostile_monster, hostile_monster_metadata(monster.fighter.last_attacker)) monster.ai.set_owner(monster) return monster.ai.take_turn(player) if monster.distance_to_obj(player) < metadata.radius: log.message( monster.name.capitalize() + ' decides ' + player.name + ' is too close!', libtcod.red) monster.ai = AI(hostile_monster, hostile_monster_metadata(player)) monster.ai.set_owner(monster) return monster.ai.take_turn(player) while True: trial_dir = actions.random_direction() candidate = monster.pos + trial_dir cand_dist = candidate.distance(metadata.home) if ((cand_dist < metadata.radius or cand_dist < monster.pos.distance(metadata.home)) and not monster.current_map.is_blocked_at(candidate)): actions.move(monster, trial_dir) return
def hyena_pair(new_map, pos, player): return (_hostile_monster(new_map, pos, player, 'C', 'hyena', libtcod.amber, hp=12, unarmed_damage=3, skills={'grappling':20}), _hostile_monster(new_map, pos + actions.random_direction(), player, 'C', 'hyena', libtcod.amber, hp=12, unarmed_damage=3, skills={'grappling':20}))
def territorial_monster(monster, player, metadata): """ Move randomly but near home until approached or hurt """ _spotting(monster, metadata) if metadata.active_turns > 0: metadata.active_turns -= 1 # In the grander scheme of things this should reset to territorial # after killing its prey, but that doesn't matter so long as we only # go hostile on the player. if monster.fighter.last_attacker: monster.ai = AI(hostile_monster, hostile_monster_metadata(monster.fighter.last_attacker)) monster.ai.set_owner(monster) return monster.ai.take_turn(player) if monster.distance_to_obj(player) < metadata.radius: log.message(monster.name.capitalize() + ' decides ' + player.name + ' is too close!', libtcod.red) monster.ai = AI(hostile_monster, hostile_monster_metadata(player)) monster.ai.set_owner(monster) return monster.ai.take_turn(player) while True: trial_dir = actions.random_direction() candidate = monster.pos + trial_dir cand_dist = candidate.distance(metadata.home) if ((cand_dist < metadata.radius or cand_dist < monster.pos.distance(metadata.home)) and not monster.current_map.is_blocked_at(candidate)): actions.move(monster, trial_dir) return
def wolf_pair(new_map, pos, player): return (_hostile_monster(new_map, pos, player, 'C', 'wolf', libtcod.darker_orange, hp=16, unarmed_damage=4, skills={'grappling':30}), _hostile_monster(new_map, pos + actions.random_direction(), player, 'C', 'wolf', libtcod.darker_orange, hp=16, unarmed_damage=4, skills={'grappling':30}))
def confused_monster(monster, player, metadata): if metadata.num_turns > 0: actions.move(monster, actions.random_direction()) metadata.num_turns -= 1 else: # Restore the previous AI (this one will be deleted # because it's not referenced anymore) monster.ai = metadata.old_ai log.message(monster.name.capitalize() + ' is no longer confused!', libtcod.red)
def _place_random_creatures(new_map, player): start_region = new_map.region[player.pos.x][player.pos.y] terrain_chances = { 'lake': { None: 10 }, 'marsh': { None: 10, bestiary.swamp_goblin: 10 }, 'desert': { None: 20, bestiary.hyena_pair: 5, bestiary.gazelle: 10 }, 'scrub': { None: 20, bestiary.hyena: 2, bestiary.gazelle: 4, bestiary.deer: 4, bestiary.wolf: 2 }, 'forest': { None: 20, bestiary.deer: 10, bestiary.wolf_pair: 5, bestiary.bear: 3 }, 'rock': { None: 10, bestiary.snow_leopard: 1 }, 'ice': { None: 10, bestiary.snow_leopard: 1 } } for r in range(len(new_map.region_seeds)): if (r == start_region or (new_map.quarry_regions and r in new_map.quarry_regions)): continue fn = _random_choice(terrain_chances[new_map.region_terrain[r]]) if fn is not None: pos = algebra.Location(new_map.region_seeds[r][0], new_map.region_seeds[r][1]) while new_map.is_blocked_at(pos): pos += actions.random_direction() pos.bound( algebra.Rect(0, 0, new_map.width - 1, new_map.height - 1)) if new_map.caravanserai and new_map.caravanserai.bounds.contains( pos): continue # print('Creature in region ' + str(r) + ' at ' + str(pos.x) + ' ' + str(pos.y)) fn(new_map, pos, player)
def hyena_pair(new_map, pos, player): return (_hostile_monster(new_map, pos, player, 'C', 'hyena', libtcod.amber, hp=12, unarmed_damage=3, skills={'grappling': 20}), _hostile_monster(new_map, pos + actions.random_direction(), player, 'C', 'hyena', libtcod.amber, hp=12, unarmed_damage=3, skills={'grappling': 20}))
def wolf_pair(new_map, pos, player): return (_hostile_monster(new_map, pos, player, 'C', 'wolf', libtcod.darker_orange, hp=16, unarmed_damage=4, skills={'grappling': 30}), _hostile_monster(new_map, pos + actions.random_direction(), player, 'C', 'wolf', libtcod.darker_orange, hp=16, unarmed_damage=4, skills={'grappling': 30}))
def make_map(player, dungeon_level): """ Creates a new simple map at the given dungeon level. Sets player.current_map to the new map, and adds the player as the first object. """ new_map = map.OutdoorMap(config.OUTDOOR_MAP_WIDTH, config.OUTDOOR_MAP_HEIGHT, dungeon_level) new_map.objects.append(player) player.current_map = new_map player.camera_position = algebra.Location(0, 0) new_map.random_seed = libtcod.random_save(0) _build_map(new_map) # Might want to change this later, but this is required in creature placement # routines so we know what region the player starts in so there isn't a # wandering monster jumping down their throat. Unless, of course, this # start point is on a *region border* and there's a monster in the next # region over... player.pos = algebra.Location(config.OUTDOOR_MAP_WIDTH - 8, 12) _place_random_creatures(new_map, player) _inhabit_rotunda(new_map, new_map.peak) if new_map.caravanserai: compound_cartographer.inhabit_caravanserai(new_map, player) if new_map.quarry_regions: _inhabit_quarry(new_map, player) # make sure we're not starting on top of an object or terrain feature while (new_map.terrain_at(player.pos).name != 'ground'): # subtle bug? doesn't use the map-building random number generator player.pos = player.pos + actions.random_direction() player.pos.bound( algebra.Rect(0, 0, new_map.width - 1, new_map.height - 1)) new_map.initialize_fov() # setting an instancemethod breaks shelve save games # new_map.xp_visit = type(map.BaseMap.xp_visit)(_mountain_exploration, new_map, map.BaseMap) new_map.xp_visit = _mountain_exploration return True
def make_map(player, dungeon_level): """ Creates a new simple map at the given dungeon level. Sets player.current_map to the new map, and adds the player as the first object. """ new_map = map.OutdoorMap(config.OUTDOOR_MAP_WIDTH, config.OUTDOOR_MAP_HEIGHT, dungeon_level) new_map.objects.append(player) player.current_map = new_map player.camera_position = algebra.Location(0, 0) new_map.random_seed = libtcod.random_save(0) _build_map(new_map) # Might want to change this later, but this is required in creature placement # routines so we know what region the player starts in so there isn't a # wandering monster jumping down their throat. Unless, of course, this # start point is on a *region border* and there's a monster in the next # region over... player.pos = algebra.Location(config.OUTDOOR_MAP_WIDTH - 8, 12) _place_random_creatures(new_map, player) _inhabit_rotunda(new_map, new_map.peak) if new_map.caravanserai: compound_cartographer.inhabit_caravanserai(new_map, player) if new_map.quarry_regions: _inhabit_quarry(new_map, player) # make sure we're not starting on top of an object or terrain feature while (new_map.terrain_at(player.pos).name != 'ground'): # subtle bug? doesn't use the map-building random number generator player.pos = player.pos + actions.random_direction() player.pos.bound(algebra.Rect(0, 0, new_map.width - 1, new_map.height - 1)) new_map.initialize_fov() # setting an instancemethod breaks shelve save games # new_map.xp_visit = type(map.BaseMap.xp_visit)(_mountain_exploration, new_map, map.BaseMap) new_map.xp_visit = _mountain_exploration return True
def ignoring_monster(monster, player, metadata): """ A creature that moves randomly (q.v. confused_monster) and ignores the player unless hurt, in which case it becomes hostile or scared. """ _spotting(monster, metadata) if metadata.active_turns > 0: metadata.active_turns -= 1 if monster.fighter.last_attacker: if monster.fighter.unarmed_damage > 2: monster.ai = AI(hostile_monster, hostile_monster_metadata(monster.fighter.last_attacker)) else: monster.old_ai = monster.ai monster.ai = AI(fleeing_monster, hostile_monster_metadata(monster.fighter.last_attacker)) monster.ai.set_owner(monster) return monster.ai.take_turn(player) # TODO: this movement may fail, so the monster will appear to # move less when in constricted quarters. if metadata.on_idle and not metadata.on_idle(player): actions.move(monster, actions.random_direction())
def make_map(player, dungeon_level): """ """ old_map = player.current_map new_map = map.DungeonMap(MINE_SIZE, MINE_SIZE, dungeon_level) new_map.objects.append(player) player.current_map = new_map player.camera_position = algebra.Location(0, 0) new_map.random_seed = libtcod.random_save(0) new_map.rng = libtcod.random_new_from_seed(new_map.random_seed) old_quarry_stairs = old_map.quarry_stairs _link_up_stairs(new_map, old_map, old_quarry_stairs) _create_entries(new_map, old_quarry_stairs) _descend_stairs(new_map, player, old_quarry_stairs) _dig_some_caves(new_map, old_quarry_stairs) _dig_mine_tunnels(new_map) map_bounds = algebra.Rect(1, 1, new_map.width - 1, new_map.height - 1) for x in range(1, new_map.width - 1): for y in range(1, new_map.height - 1): if libtcod.random_get_float(new_map.rng, 0., 1.) < 0.2: new_map.terrain[x][y] = map.TERRAIN_GROUND ca_cartographer._generation(new_map, map_bounds, 7, 1) ca_cartographer._generation(new_map, map_bounds, 5, 1) # Redig the initial rooms because the CA can fill in the stairs for i in range(3): _create_room(new_map, new_map.rooms[i]) for i in range(3): stair_pos = old_quarry_stairs[i].dest_position ca_cartographer._floodfill(new_map, stair_pos.x, stair_pos.y, map.TERRAIN_GROUND, map.TERRAIN_FLOOR) for x in range(1, new_map.width - 1): for y in range(1, new_map.height - 1): if new_map.terrain[x][y] == map.TERRAIN_GROUND: new_map.terrain[x][y] = map.TERRAIN_WALL #for x in range(0, new_map.width): # new_map.terrain[x][0] = map.TERRAIN_WALL # new_map.terrain[x][new_map.height-1] = map.TERRAIN_WALL #for y in range(0, new_map.height): # new_map.terrain[0][y] = map.TERRAIN_WALL # new_map.terrain[new_map.width-1][y] = map.TERRAIN_WALL zone_divisor = MINE_SIZE / 3 slime_zone = new_map.rnd(0, 2) while True: undead_zone = new_map.rnd(0, 2) if undead_zone != slime_zone: break for r in range(3, len(new_map.rooms)): if new_map.rnd(1, 4) < 3: room = new_map.rooms[r] zone = room.center().x / zone_divisor if zone == slime_zone: if new_map.rnd(1, 2) == 1: bestiary.slime(new_map, _find_floor_near_room(new_map, room), player) bestiary.slime(new_map, _find_floor_near_room(new_map, room), player) else: bestiary.jelly(new_map, _find_floor_near_room(new_map, room), player) elif zone == undead_zone: bestiary.ghul(new_map, _find_floor_near_room(new_map, room), player) else: bestiary.worm(new_map, _find_floor_near_room(new_map, room), player) r = new_map.rnd(3, len(new_map.rooms) - 1) pos = new_map.rooms[r].center() while new_map.is_blocked_at(pos): pos += actions.random_direction() new_map.objects.insert(0, Object(pos, '%', "hero's corpse", libtcod.dark_red)) sword = miscellany.the_black_sword() sword.pos = pos new_map.objects.insert(0, sword) new_map.initialize_fov() new_map.xp_visit = _dungeon_exploration return False # Don't need to generate stairs in caller thanks to _link_up_stairs()
def make_map(player, dungeon_level): """ """ old_map = player.current_map new_map = map.DungeonMap(MINE_SIZE, MINE_SIZE, dungeon_level) new_map.objects.append(player) player.current_map = new_map player.camera_position = algebra.Location(0, 0) new_map.random_seed = libtcod.random_save(0) new_map.rng = libtcod.random_new_from_seed(new_map.random_seed) old_quarry_stairs = old_map.quarry_stairs _link_up_stairs(new_map, old_map, old_quarry_stairs) _create_entries(new_map, old_quarry_stairs) _descend_stairs(new_map, player, old_quarry_stairs) _dig_some_caves(new_map, old_quarry_stairs) _dig_mine_tunnels(new_map) map_bounds = algebra.Rect(1, 1, new_map.width-1, new_map.height-1) for x in range(1, new_map.width-1): for y in range(1, new_map.height-1): if libtcod.random_get_float(new_map.rng, 0., 1.) < 0.2: new_map.terrain[x][y] = map.TERRAIN_GROUND ca_cartographer._generation(new_map, map_bounds, 7, 1) ca_cartographer._generation(new_map, map_bounds, 5, 1) # Redig the initial rooms because the CA can fill in the stairs for i in range(3): _create_room(new_map, new_map.rooms[i]) for i in range(3): stair_pos = old_quarry_stairs[i].dest_position ca_cartographer._floodfill(new_map, stair_pos.x, stair_pos.y, map.TERRAIN_GROUND, map.TERRAIN_FLOOR) for x in range(1, new_map.width-1): for y in range(1, new_map.height-1): if new_map.terrain[x][y] == map.TERRAIN_GROUND: new_map.terrain[x][y] = map.TERRAIN_WALL #for x in range(0, new_map.width): # new_map.terrain[x][0] = map.TERRAIN_WALL # new_map.terrain[x][new_map.height-1] = map.TERRAIN_WALL #for y in range(0, new_map.height): # new_map.terrain[0][y] = map.TERRAIN_WALL # new_map.terrain[new_map.width-1][y] = map.TERRAIN_WALL zone_divisor = MINE_SIZE / 3 slime_zone = new_map.rnd(0, 2) while True: undead_zone = new_map.rnd(0, 2) if undead_zone != slime_zone: break for r in range(3, len(new_map.rooms)): if new_map.rnd(1, 4) < 3: room = new_map.rooms[r] zone = room.center().x / zone_divisor if zone == slime_zone: if new_map.rnd(1, 2) == 1: bestiary.slime(new_map, _find_floor_near_room(new_map, room), player) bestiary.slime(new_map, _find_floor_near_room(new_map, room), player) else: bestiary.jelly(new_map, _find_floor_near_room(new_map, room), player) elif zone == undead_zone: bestiary.ghul(new_map, _find_floor_near_room(new_map, room), player) else: bestiary.worm(new_map, _find_floor_near_room(new_map, room), player) r = new_map.rnd(3, len(new_map.rooms) - 1) pos = new_map.rooms[r].center() while new_map.is_blocked_at(pos): pos += actions.random_direction() new_map.objects.insert(0, Object(pos, '%', "hero's corpse", libtcod.dark_red)) sword = miscellany.the_black_sword() sword.pos = pos new_map.objects.insert(0, sword) new_map.initialize_fov() new_map.xp_visit = _dungeon_exploration return False # Don't need to generate stairs in caller thanks to _link_up_stairs()