Momoka wrote:
I've been working on a way to make monsters and items be different at various floors (ultimate goal: at least one new thing every floor).
Right now, though, it's causing nothing to spawn at all, and I don't know why
Right now, though, it's causing nothing to spawn at all, and I don't know why

Okay, fixed that. There was an indentation error. I loathe when I have the wrong indentation on a Python script and it doesn't throw an error. That's so hard to catch.
Anyway, Imps are now currently the only monster you see on the first floor, doing exactly 1 damage. Current damage formula is (Attack - Defense) + 1, to make a floor of 1 damage if your defense is better than my attack. As you go further down, Ogres, which are more powerful, start appearing more and more, with imps fading out of the spotlight. There are also more items and monsters on deeper floors, while the earlier ones are more sparse.
I want to apply this same concept to my random dungeon generator, with earlier floors having a few rooms, and successive floors getting wider and more complicated.
Thus, my current goals are, in order
1. Change the map logic so that maps get bigger as you go down, making the dungeon levels more and more open
2. Make an enemy with a ranged attack. I'm thinking that it will use AOE fire spells it it's too far away to get caught in the blast (with no concern to any other monsters that might get blasted), and run away if it's too close. I think this is a sufficiently complex monster to be interesting.
3. Give the witch an ability to cast spells, making her not a strictly inferior choice to the knight
4. HP/MP regeneration
5. Reason to keep going down, like a need to eat (this will probably coincide with monster drops and monster corpses)
Regarding point 1, before I revamp the Map Generator to be more complex and interesting, I have a problem I can't figure out. There seems to be nearly a 50% chance that any given floor will just be one room, and I can't figure out why.
The code is as follows. The ALL_CAPS variables are global variables I intend to replace with procedures, so I can do things like have the fifth floor be a single giant room, etc. (Make more tile types than "wall" and "not wall" comes later)
I can't figure out why this seems to make single-room floors so often, though. It shouldn't.
Anyone have any ideas what I might be doing wrong?
Code:
#Map-making!
def make_map():
global map, objects, stairs
#The list of objects with just the player
objects = [player]
#fill map with "blocked" tiles
map = [[ Tile(True)
for y in range(MAP_HEIGHT) ]
for x in range(MAP_WIDTH) ]
rooms = []
num_rooms = 0
for r in range(MAX_ROOMS):
#random width and height
w = libtcod.random_get_int(0, ROOM_MIN_SIZE, ROOM_MAX_SIZE)
h = libtcod.random_get_int(0, ROOM_MIN_SIZE, ROOM_MAX_SIZE)
#random position within the map
x = libtcod.random_get_int(0, 0, MAP_WIDTH - w -1)
y = libtcod.random_get_int(0, 0, MAP_HEIGHT - h - 1)
#"Rect" class makes Rectangles easier to work with
new_room = Rect(x, y, w, h)
#Check list of rooms for overlap
failed = False
for other_room in rooms:
if new_room.intersect(other_room):
failed = True
break
if not failed:
#No intersections, so room is valid
#"Paint" Rect to tiles
create_room(new_room)
#Fill room with objects, such as monsters!
place_objects(new_room)
#center co-ordinates of the new room will be useful later
(new_x, new_y) = new_room.center()
if num_rooms == 0:
#The player starts in the first room made
player.x = new_x
player.y = new_y
else:
#all rooms after the first:
#Connect to previous room with a tunnel
#center co-ordinates of previous room
(prev_x, prev_y) = rooms[num_rooms-1].center()
#Coinflip! Either 0 or 1!
if libtcod.random_get_int(0, 0, 1) == 1:
#Make a horizontal tunnel, then a vertical one
create_h_tunnel(prev_x, new_x, prev_y)
create_v_tunnel(prev_y, new_y, new_x)
else:
#Vert than horizontal.
create_v_tunnel(prev_y, new_y, new_x)
create_h_tunnel(prev_x, new_x, new_y)
#finally, add the room to the list
rooms.append(new_room)
num_rooms += 1
#Make stairs at the center of the last room
stairs = Object(new_x,new_y,'<','stairs',libtcod.white, always_visible = True)
objects.append(stairs)
#Map-making!
def make_map():
global map, objects, stairs
#The list of objects with just the player
objects = [player]
#fill map with "blocked" tiles
map = [[ Tile(True)
for y in range(MAP_HEIGHT) ]
for x in range(MAP_WIDTH) ]
rooms = []
num_rooms = 0
for r in range(MAX_ROOMS):
#random width and height
w = libtcod.random_get_int(0, ROOM_MIN_SIZE, ROOM_MAX_SIZE)
h = libtcod.random_get_int(0, ROOM_MIN_SIZE, ROOM_MAX_SIZE)
#random position within the map
x = libtcod.random_get_int(0, 0, MAP_WIDTH - w -1)
y = libtcod.random_get_int(0, 0, MAP_HEIGHT - h - 1)
#"Rect" class makes Rectangles easier to work with
new_room = Rect(x, y, w, h)
#Check list of rooms for overlap
failed = False
for other_room in rooms:
if new_room.intersect(other_room):
failed = True
break
if not failed:
#No intersections, so room is valid
#"Paint" Rect to tiles
create_room(new_room)
#Fill room with objects, such as monsters!
place_objects(new_room)
#center co-ordinates of the new room will be useful later
(new_x, new_y) = new_room.center()
if num_rooms == 0:
#The player starts in the first room made
player.x = new_x
player.y = new_y
else:
#all rooms after the first:
#Connect to previous room with a tunnel
#center co-ordinates of previous room
(prev_x, prev_y) = rooms[num_rooms-1].center()
#Coinflip! Either 0 or 1!
if libtcod.random_get_int(0, 0, 1) == 1:
#Make a horizontal tunnel, then a vertical one
create_h_tunnel(prev_x, new_x, prev_y)
create_v_tunnel(prev_y, new_y, new_x)
else:
#Vert than horizontal.
create_v_tunnel(prev_y, new_y, new_x)
create_h_tunnel(prev_x, new_x, new_y)
#finally, add the room to the list
rooms.append(new_room)
num_rooms += 1
#Make stairs at the center of the last room
stairs = Object(new_x,new_y,'<','stairs',libtcod.white, always_visible = True)
objects.append(stairs)
I think that your problem will be mostly solved by replacing
with
After that if too few rooms are still being placed, it's probably because your max room size is too big relative to the map size: fiddle with the constants, or place rooms differently.
BTW, Python has a for-else flow construct you can use here, though I wouldn't blame anyone for not using it; I don't like it too much myself.
Code:
num_rooms = 0
for r in range(MAX_ROOMS):
#...
#Check list of rooms for overlap
failed = False
for other_room in rooms:
if new_room.intersect(other_room):
failed = True
break
if not failed:
#...
num_rooms += 1
num_rooms = 0
for r in range(MAX_ROOMS):
#...
#Check list of rooms for overlap
failed = False
for other_room in rooms:
if new_room.intersect(other_room):
failed = True
break
if not failed:
#...
num_rooms += 1
with
Code:
num_rooms = 0
loop_count = 0
while num_rooms < MAX_ROOMS and loop_count < 100:
loop_count += 1
#...
#Check list of rooms for overlap
failed = False
for other_room in rooms:
if new_room.intersect(other_room):
failed = True
break
if not failed:
#...
num_rooms += 1
num_rooms = 0
loop_count = 0
while num_rooms < MAX_ROOMS and loop_count < 100:
loop_count += 1
#...
#Check list of rooms for overlap
failed = False
for other_room in rooms:
if new_room.intersect(other_room):
failed = True
break
if not failed:
#...
num_rooms += 1
After that if too few rooms are still being placed, it's probably because your max room size is too big relative to the map size: fiddle with the constants, or place rooms differently.
BTW, Python has a for-else flow construct you can use here, though I wouldn't blame anyone for not using it; I don't like it too much myself.
Code:
#Check list of rooms for overlap
for other_room in rooms:
if new_room.intersect(other_room):
break
else:
#...
num_rooms += 1
#Check list of rooms for overlap
for other_room in rooms:
if new_room.intersect(other_room):
break
else:
#...
num_rooms += 1
I actually was generating the right number of rooms, I just wasn't making hallways connecting them properly. When dealing with issues related to maps, I will turn fog of war off
I've developed a new monster that shoots explosive fireballs at you, not caring about any other monsters that get hit, but running away if it's close enough to be hit by it's own blast. You can confuse or scare it to keep it from casting, but I'll put an MP limit on him later.
I was trying to make a monster that swarms, but my AI is stupid and gets stuck on corners. But, right now, monsters can attack around corners and players can't, so getting stuck on a corner is actually smart (since the monster gets a free hit). I kind of like the "ambush 'im at the door" mechanic this makes, so I'm thinking about just leaving them stupid and not adding in diagonal attacks.
I've developed a new monster that shoots explosive fireballs at you, not caring about any other monsters that get hit, but running away if it's close enough to be hit by it's own blast. You can confuse or scare it to keep it from casting, but I'll put an MP limit on him later.
I was trying to make a monster that swarms, but my AI is stupid and gets stuck on corners. But, right now, monsters can attack around corners and players can't, so getting stuck on a corner is actually smart (since the monster gets a free hit). I kind of like the "ambush 'im at the door" mechanic this makes, so I'm thinking about just leaving them stupid and not adding in diagonal attacks.



