On Sat, 1 Jan 2000, Warren Robbins wrote: > I suppose my question is: How else do people recommend trimming > memory usage for an overworld (approx. 300x200 rooms)? The area is > composed (ATM) of stock room_data structure types. Why allocate all of them when most of them aren't used? Since the wilderness is mostly arbitrary, allocate only space for rooms that have players and important items/mobiles in them (not the typical squirrels, branches, etc.). When a player enters a room, allocate the space for it, set a timer on it for it to expire (that starts counting when there are no players or important items/mobiles in it), and do a bit of a random check to drop some items in the room -- leaves, oversized magical acorns, squirrels, what have you. These items are mostly arbitrarily located within the wilderness, so the Mud need not actually keep track of their actual locations. The timer ensures that a player going 'w' and then 'e' doesn't wind up in a room with different objects in it. Of course, if he goes 'w', waits for 5 minutes, and goes 'e' the objects will be different, but 5 minutes in real life is quite a spell in Mud time, so that's fairly easy to explain away. For commands like 'scan' you can either allocate the rooms then and there, or report that they don't see much of anything and on room allocation have any mobiles dropped into the room report their arrival "from out of the bushes" or what have you. Links into (and out of) the wilderness will have to be done in a special manner. Even better, since the wilderness will be optimally kept separate from the world[] array, you can use a different type for them. forest_room_data or what have you. Since we're using a 300x200 map (which is really not that large a wilderness -- only 60000 rooms worth) and each room within that map is placed relative to another room, the traditional exits structure is superfluous. Instead, we might want something like, struct forest_room_data { ush_int x; ush_int y; ubyte exitFlags; struct room_data *outLink; }; #define FRD_EX_NO_NORTH 0x01 /* (1 << 0) */ #define FRD_EX_NO_EAST 0x02 #define FRD_EX_NO_SOUTH 0x04 #define FRD_EX_NO_WEST 0x08 #define FRD_EX_NORTH_OUT 0x10 #define FRD_EX_EAST_OUT 0x20 #define FRD_EX_SOUTH_OUT 0x40 #define FRD_EX_WEST_OUT 0x80 /* (1 << 7) */ The frd->outLink variable is used for any exit that has the _OUT flag set on it. Note that we don't keep separate bitvectors for each exit -- there's only two flags we can set for each one: NO_ or _OUT. If an exit has NO_ set on it, you can't exit in that direction. If an exit has _OUT set on it, then the exit, instead of taking you to the adjacent room, it takes you to the room specified by frd->outLink. It doesn't make sense for several exits within the same room to have _OUT set on them, since there's only one outLink. This is a bit of a restriction, but as you notice, the entire structure is only 9 bytes[1] (2 bytes for each of the 16 bit integers X/Y; 1 byte for exitFlags; 4 bytes for the pointer). We don't maintain pointers to descriptions or room names -- we figure we won't actually need them for the wilderness (especially if using an ASCII overhead map). Next we need to add the necessary 'people', 'contents', etc., lists to the forest_room_data structure, or provide a link to an instantiated room_data object. The latter method is easier, since you'll end up with being able to get by with char_from_room() and char_to_room() without change and minor modifications to the movement functions. The same will go for ANYTHING that uses ch->in_room. This is all fairly trivial, which isn't to say it's not time consuming. There might be better ways. After we go through and correct all of this stuff, we'll need to add the timer logic. This is just a single byte that is decremented each PULSE_WILDERNESS, which might occur every minute, and just involves quickly going through the wilderness_map, looking for instantiated rooms, and doing some stuff with those that are allocated. Our complete forest_room_data structure might look like, struct forest_room_data { ush_int x; ush_int y; ubyte exitFlags; struct room_data *outLink; struct room_data *roomInstance; ubyte timer; ubyte nonWildernessEntity; }; or, struct forest_room_data { ush_int x; ush_int y; ubyte exitFlags; struct room_data *outLink; struct char_data *people; struct obj_data *contents; ubyte timer; ubyte nonWildernessEntity; }; The 'nonWildernessEntity' byte is used to count how many entities (meaning objects or mobiles) that are not considered arbitrary (and, thus, may be entirely extracted when the room expires) are located in the room. When a non-wilderness entity is sent to the room (with, say, obj_to_wilderness() or char_to_wilderness()), the nonWildernessEntity counter is incremented. When one is removed (with [obj|char]_from_wilderness()), we decrement it. When it hits zero, the counter is set to, say, 5, and the wilderness update loop recognizes sees that it can decrement the timer. Shrug. There's lots more to it, most likely, but I'm too tired to think. -dak +------------------------------------------------------------+ | Ensure that you have read the CircleMUD Mailing List FAQ: | | http://qsilver.queensu.ca/~fletchra/Circle/list-faq.html | +------------------------------------------------------------+
This archive was generated by hypermail 2b30 : 04/10/01 PDT