dungeonmaker-develop Mailing List for DungeonMaker (Page 6)
Brought to you by:
acdalton,
henningsen
You can subscribe to this list here.
2001 |
Jan
|
Feb
|
Mar
(1) |
Apr
(54) |
May
(22) |
Jun
(16) |
Jul
(4) |
Aug
(25) |
Sep
(3) |
Oct
(3) |
Nov
(2) |
Dec
(8) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2002 |
Jan
|
Feb
(9) |
Mar
|
Apr
(1) |
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2003 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(1) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2004 |
Jan
|
Feb
(16) |
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2005 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(5) |
Dec
(11) |
From: Stephan B. <ste...@ei...> - 2001-05-02 08:57:42
|
On Tuesday 01 May 2001 00:45, Henningsen wrote: > >> Remember to give doors the number 7;-) like in floor=3D0, wall=3D1, > >> high wall=3D2,... door=3D7! > > > >Ah, yes, I forgot about that. I'll fix that tonight. > > That's just for the internal parameters - when the map is printed, it > can of course be anything... "D" would probably be best i think. When > you talk about "rendering", I presume you mean rendering to the "Map" > object inside the DungeonMaker? You're not putting some kind of > "rendering-to-screen" function in the program, right? That should all > be left to the users IMO. Okay, here's the current state: I've got the Door class basically done, but I've got a bug or two I=20 need to work out. The problem is, it works okay as long as you don't=20 change the orientation of your wall after the Door is placed. Let's say=20 you have a wall which looks like: xxxDxxx (D =3D=3D Door) If you call setOrientation( Vertical ), the wall will look like: x x x x x x x But the Door will be here: x[--D----] x x x x x x and won't be rendered (or rendered incorrectly). I want to fix this=20 before I commit the Door stuff. I know it's not an important fix, but I=20 think it will be handy later for other types of objects, and allows=20 programmers to change their walls after building them without having to=20 move the doors manually. The problem is that I know if I don't fix this=20 now, I'll be scratching my head in 2 months saying, "why does it do=20 that?" because I will have forgotten what the problem was (aus dem=20 Augen, aus den Sinn). The current implementation of setting a wall's orientation is kind of=20 lame, but it works for our simple case: it simply resizes the wall.=20 Each wall has a Length field. If orientation =3D=3D Horiz, then it's=20 resized to length,1. If it's vertical, then it's resized to 1,length.=20 The 1 is currently hardcoded, but can be gotten around by calling=20 resize() or setGeometry() on the wall after setOrientation() is called.=20 I will work around this inconsistency one of these days, and get away=20 from the hard-coded width/height of 1. I spent much of yesterday working on adding convenience functions to=20 the DungeonElement API and getting the Doors done. I've added the=20 following to the DE API: get/setSquareSubType(): by default this returns -1. Subclasses may use=20 this to set a "sub type" for their square. A Wall square could specify,=20 for example, if it's a corner wall, a "high wall", etc. A door could be=20 open, closed, gold-inlaid, etc. This function is used by Door to hold=20 it's type. The subtype can be collected for the object as a whole (the=20 case with most objects, plus the default implementation) or objects may=20 supply a subtype for a square at at a given x/y coordinate. Currently=20 only Door uses these at all, but it's there for future use if we want=20 it. I think client apps will get the most out of it, as it lets them do=20 things with their rooms which DungeonMaker can't do (doesn't specify=20 corner wall joins, for example). I've also added several other convenience functions, like: - removeAllOfType( DungeonElement *de ) removes all child objects which are of the same class as the given=20 DungeonElement *. A Room can use this, for example, to remove all walls while keeping=20 other data (like the chest of gold in the middle):=20 Wall *w =3D new Wall(); removeAllOfType( w ); delete( wall ); Actually, that function is completely untested, but "should work" ;). Load/save is still on the back burner. I spent about 4 hours yesterday=20 completely rewiring the class hierarchy and moving functions around=20 into a hierarchy which made more sense to my brain. We should now have=20 forward-compatible save support so we can drop in binary, XML,=20 GridSlammer, etc. save support with very little pain later on (the pain=20 is only in the parser). We'll simply have to implement new Serializer=20 objects for the new file types. I've still got plenty of work to do on=20 the text-saving version, I think a few more days. See ya! ----- Stephan Beal Generic Universal Computer Guy ste...@ei... - http://www.einsurance.de Office: +49 (89) 552 92 862 Handy: +49 (179) 211 97 67 "Go away or I shall replace you with a very small shell script." |
From: Stephan B. <st...@wa...> - 2001-05-01 02:39:28
|
On Tuesday 01 May 2001 00:45, you wrote: > >> Remember to give doors the number 7;-) like in floor=0, wall=1, high > >> wall=2,... door=7! > > > >Ah, yes, I forgot about that. I'll fix that tonight. > > That's just for the internal parameters - when the map is printed, it can > of course be anything... "D" would probably be best i think. When you talk > about "rendering", I presume you mean rendering to the "Map" object inside > the DungeonMaker? You're not putting some kind of "rendering-to-screen" > function in the program, right? That should all be left to the users IMO. Nonono... I mean "rendering to some object using X/Y coordinates and int values, using the DMGrid interface." :) -- ----- Stephan Beal - st...@wa... http://qub.sourceforge.net - http://stephan.rootonfire.org http://dungeonmaker.sourceforge.net "Now I'm not normally the kind of person who likes to trespass, but sometimes you just find yourself over the line." -- Bob Dylan |
From: Henningsen <al...@gl...> - 2001-04-30 22:36:50
|
>> Remember to give doors the number 7;-) like in floor=0, wall=1, high >> wall=2,... door=7! > >Ah, yes, I forgot about that. I'll fix that tonight. That's just for the internal parameters - when the map is printed, it can of course be anything... "D" would probably be best i think. When you talk about "rendering", I presume you mean rendering to the "Map" object inside the DungeonMaker? You're not putting some kind of "rendering-to-screen" function in the program, right? That should all be left to the users IMO. Peter |
From: Stephan B. <ste...@ei...> - 2001-04-30 08:40:44
|
On Monday 30 April 2001 00:33, you wrote: > I would just design a file format that is easy to parse, (can be > edited by humans ???), and still can hold all the data we need. But I > get the feeling you are a perfectionist;-)=20 Only when I know others may see my code ;) > Still, with the > classloading stuff, I think you don't have to go that far.=20 Me, too. > Just > assume all the subclasses that people are going to use are all > compiled into the program. I mean, if someone writes a new subclass, > they are probably smart enough to be able to recompile the program > including their class? And anyway, we can include a nice set of > precompiled classes. That's also the conclusion I came to. > Remember to give doors the number 7;-) like in floor=3D0, wall=3D1, hig= h > wall=3D2,... door=3D7! Ah, yes, I forgot about that. I'll fix that tonight. > ???: If we have an interactive design program, the file does not even > have to be editable by humans as far as I'm concerned. And if it's > not edited by humans, you can let the file reading function fail for > any missing space or added comma or whatever (like I do anyway). Then > things shouldn't be so hard. I would, but it frustrates me to a) have a data file which I can't=20 hand-edit if I need to and b) one which may not work with the next=20 software version (and I can't hand-edit it to bring it up to spec). I'm=20 still deciding on the data format, but that part can wait a little=20 while while I clean up the rendering and such. I can currently save the=20 data, but the format isn't really one I can use to read back easily.=20 I've got to to simplify significantly before I can read it back. ----- Stephan Beal Generic Universal Computer Guy ste...@ei... - http://www.einsurance.de Office: +49 (89) 552 92 862 Handy: +49 (179) 211 97 67 "Belief makes a hollow place. Something has to roll in to fill it." -- Terry Pratchet |
From: Henningsen <al...@gl...> - 2001-04-29 22:25:28
|
>Pretty simple, I think. Now once I can load my serialized data, we can store >and user-created load dungeons. > >It wouldn't be hard to implement a small scripting language, like: >room( x, y, w, h ) >wall( x, y, orientation, length ) > >Should probably just use that for the config files, I guess. It's just that >parsing that stuff is such a pain in the butt in C. I can be done, however, >and I wouldn't mind doing it, if it makes sense to use a "script" instead of >a "config file". The objects would simply save themselves in "source code" >format: >room( 12, 47, 7, 7 ) I would just design a file format that is easy to parse, (can be edited by humans ???), and still can hold all the data we need. But I get the feeling you are a perfectionist;-) Still, with the classloading stuff, I think you don't have to go that far. Just assume all the subclasses that people are going to use are all compiled into the program. I mean, if someone writes a new subclass, they are probably smart enough to be able to recompile the program including their class? And anyway, we can include a nice set of precompiled classes. If you want to write the perfect app, OK, but otherwise let's just write an app that is good enough to make the perfect dungeons;-) People here in Nova Scotia are usually trying to do things "good enough", and that is very wise i think. Saves a lot of trouble, anyway. Remember to give doors the number 7;-) like in floor=0, wall=1, high wall=2,... door=7! C'ya, Peter ???: If we have an interactive design program, the file does not even have to be editable by humans as far as I'm concerned. And if it's not edited by humans, you can let the file reading function fail for any missing space or added comma or whatever (like I do anyway). Then things shouldn't be so hard. |
From: Stephan B. <st...@wa...> - 2001-04-29 00:39:15
|
Okay, Now I've made some progress in the dungeon rendering. The whole thing is done in about 12 lines of code. So far the default rendering code is working for Rooms and Walls for all subclasses (no subclass-specific rendering has been needed so far!!!) This is literally all of the rendering code: void DungeonElement::renderTo( DMGrid &grid, int relativeX, int relativeY ) { //CERR << "rendering..."; IntCoordinate pos = getPosition(); int rx = getPosition().x()+relativeX; int ry = getPosition().y()+relativeY; int sq = getSquareType(); //CERR << " width="<<getWidth()<<", height="<<getHeight()<<", xoff="<<rx<<", yoff="<<ry<<endl; for( int x = 0; x < getWidth(); x++ ) { for( int y = 0; y < getHeight(); y++ ) { sq = getSquareType( x, y ); grid.set( rx+x,ry+y, sq ); } } for( iter = childs.begin(); iter != childs.end(); ++iter ) { //CERR << "asking child "<<(*iter)->getName()<<endl; (*iter)->renderTo( grid, this ); } } That code turns this: DungeonElement top( "dungeon" ); DungeonElement *de = 0; top.add( de = new Room( "roomX" ) ); de->move( 3, 5 ); top.add( de = new Room( 7,3, "wide room" ) ); de->move( 17,4 ); top.add( de = new Room( 5,8, "tall room" ) ); de->move( 10,2 ); top.add( de = new Wall( 1,1, 3 ) ); de->setSquareType( DM::sq_Open ); de->setGeometry( 10, 15, 7, 3 ); top.toCerr(); DMGrid grid( 40, 20 ); top.renderTo( grid ); into: 0111111111111111111111111111111111111111 1000000000000000000000000000000000000001 1000000000111110000000000000000000000001 1000000000100010000000000000000000000001 1000000000100010011111111111100000000001 1001111100100010010000000000100000000001 1001000100100010010000000000100000000001 1001000100100010010000000000100000000001 1001000100100010011111111111100000000001 1001111100111110000000000000000000000001 1000000000000000000000000000000000000001 1000000000000000000000000000000000000001 1000000000000000000000000000000000000001 1000000000000000000000000000000000000001 1000000000000000000000000000000000000001 1000000000333333300000000000000000000001 1000000000333333300000000000000000000001 1000000000333333300000000000000000000001 1000000000000000000000000000000000000001 1111111111111111111111111111111111111111 I don't know what's up with that 0 in the corner. It shouldn't be there. Anyway... Note that walls are only 1 unit wide by default, but they may be resized, to make filled-in areas, as I've done near the bottom. A user can dynamically change these, too. Note how I've set one wall to be a large area with SquareType "open" (int id 3). And you want to lay down tunnel through that? Just make a new DungeonElement and setSquareType( DM::sq_Floor ), then lay it down so that it goes over the desired area. They will be rendered in the order they are added, so the last-added will show up "over" the first-added. Still no doors, but they're coming. Here's a trick which I thought was particularly clever for reusing the same pointer variable: DungeonElement top( "dungeon" ); DungeonElement *de = top.add( new Room( "roomX" ) ); de->move( 3, 5 ); de = top.add( new Room( 12,5, "wide room" ) ); de->move( 17,4 ); de = de->add( new DungeonElement("blank strip" ) ); de->setGeometry( 5,0, 2, 5 ); // relative to "wide room"!!! de->setSquareType( DM::sq_Floor ); // we want to paint double-doors. add() returns the child it adds, so we can keep using 'de' over and over. :) This draws double-doors in the wide room, by the way: 1000000000100010000000000000000000000001 1000000000100010011111001111100000000001 1001111100100010010000000000100000000001 1001000100100010010000000000100000000001 1001000100100010010000000000100000000001 1001000100100010011111001111100000000001 1001111100111110000000000000000000000001 --------------------^here^ (if you're using a monospaced font, anyway ;) Pretty simple, I think. Now once I can load my serialized data, we can store and user-created load dungeons. It wouldn't be hard to implement a small scripting language, like: room( x, y, w, h ) wall( x, y, orientation, length ) Should probably just use that for the config files, I guess. It's just that parsing that stuff is such a pain in the butt in C. I can be done, however, and I wouldn't mind doing it, if it makes sense to use a "script" instead of a "config file". The objects would simply save themselves in "source code" format: room( 12, 47, 7, 7 ) I could build hierarchies that way, with something like: room( 12, 47, 7, 7 ) { .... list of children... } But it'd be a bitch to write the parser. Or we just add each line's output object to some top-level object, then render that object. Good night! ----- Stephan Beal - st...@wa... http://qub.sourceforge.net - http://stephan.rootonfire.org http://dungeonmaker.sourceforge.net "Now I'm not normally the kind of person who likes to trespass, but sometimes you just find yourself over the line." -- Bob Dylan |
From: Stephan B. <st...@wa...> - 2001-04-28 21:52:01
|
Morning, y'all, This is just some rambling. Nothing terribly important, as I sort out my own thoughts on the subject... I think I've basically got most of the hierarchical stuff down. Here's a sample usage of the current API: RandomDungeon top( 60, 60, "dungeon" ); // init's a random dungeon. DungeonElement *de = new Room(); de->setName( "roomX" ); de->move( 27, 17 ); de->add( new Wall( 0,0,6 ) ); de->add( new Wall( 0,0,4, DungeonElement::Vertical, "wall2" ) ); top.add( de ); top.toCerr(); // prints to cerr. class 'RandomDungeon' does not yet exist, but is a hypothetical DungeonElement subclass which initializes some random dungeon parameters at instantiation. I'm not at all happy with what I've done with save/load, so I'm going back to the drawing board on that. It's gotten too complex to be manageable, so I'm gonna rewrite that from scratch. The problem lies not so much in the conversion from hierarchical data to a flat board or data format (like the ini-style file approach), but in the reversing of that. If we can't read back our own output format, I see that as a problem. If we restricted outselves to a flat data structure the load/save would be simpler, but the whole thing would not be nearly as extendable or easy to use. Right now the runtime flexibility is really good, but the method of loading and saving those states sucks, largely because the data format has to be flat, while the structure is not. I can envision and approach like this, but back-parsing it'd be a real bitch: dungeon{ name=My Favorite Dungeon; randomSeed = 42; room { name=Dwarvish Beer Hall; width=5; height=7; x=17; y=19; wall { name=1; x=0; y=1; length=7; orientation=1; // vertical door { name=1; point=3; // where on the wall it is. }; // wall }; // room }; // room }; // dungeon Writing into that format is no problem. Reading that format back is the problem. The parser wouldn't be much fun to write, mainly because it'd have to do so much syntax checking. Plus it'd be limited to a hard-coded set of class types (the tops of the classname{} blocks - the properties within them would still be _completely_ dynamic). We could use a classloader to completely get around that problem, but the only classloader code I know of is GPL (Peter doesn't want GPL in code), and I don't think it'll work under Windows. Actually, in Perl I could parse it with little problem, I think, but in C... gimme a week, maybe. I wonder how much work it would be to port the Perl-Compatible Regular Expressions support from the PHP code... THAT would be useful. I don't know if PHP's license allows stealing code from it. I'll have to look into that. Anyway... Note that in the above sample hierarchy, all children use parent-relative X/Y values. These are converted at render-time to the rendering object (the DMGrid, which I have not yet built, but is on my list). This is MUCH simpler to maintain, and allows moving of whole branches of objects without having to deal with child positions relative to the new target. For example, we could copy the wall{} block from above into another room, or the top-level dungeon, and it'd still be a valid object at the same position, relative to the new parent. Imagine having to move all your walls every time you wanted to move a room! I think I'm going to skip the load/save for tonight and move on to the rendering. That sounds like more fun right now. I imagine this of consisting of a DMGrid object, with a very simple API: DMGrid( int w, int h ) void set( int x, int y, int val ) int get( int x, int y ) and other such stuff. Most of this will simply be swiped from the current DM object. The special one will be: void render( DungeonElement &de ) This will call de.renderTo( *this ), which is defined in DungeonElement, as: void renderTo( DMGrid &gr, int xoffset=0, int yoffset=0 ); This gets recursively called on all children of this DungeonElement object, adjusting the x/y offset as we climb down the tree. That x/y is where the children consider to be their 0/0 starting point for all rendering operations. The DMGrid will allow these rendering operations to go outside it's bounds - it will simply ignore such requests. This allows us to have elements which "run off" the DMGrid, like a lake (hey, how about a RiverCrawler object, to make underground lakes and streams?). Thus the above C++ code could simply add this code to render the whole dungeon to the console, for example: DMGrid gr( top ); // will get his size from top's size. top.renderTo( gr ); cerr << gr; // dump output to the console And adding new terrain types will not affect this code at all, like: de = new LavaPit( 2,2 ); // DungeonElement subclass room->add( de, 3, 4 ); // 3,4 == position But, see, theres' the catch: this flexibility dies when we can't load these new classes dynamically from our saved data. Our parser would have to know about type "lavapit". We could get around that 100% with XML and a classloader, but I don't know of any XML libs which are widely available on Windows and Unix, either. This is exactly the approach QUB uses to dynamically determine data types from XML data and instantiating the correct classes, searching for them as DLLs if needed. We don't NEED XML to do it, but we need some format which we can parse. Of course, we can write our own parser, aber das dauert eine Menge Zeit. And we'd still need a classloader to make it extenable without having to update the parser with each class. Oh, Hey, Pete! I just realized: with this rendering approach, QUB can offer view-as-the-crawlers-create rendering simply by subclassing GMGrid() and catching all the set()'s so I can update the pixmaps. Cool. Anyway... See y'all! ----- Stephan Beal - st...@wa... http://qub.sourceforge.net - http://stephan.rootonfire.org http://dungeonmaker.sourceforge.net "Now I'm not normally the kind of person who likes to trespass, but sometimes you just find yourself over the line." -- Bob Dylan |
From: Stephan B. <st...@wa...> - 2001-04-28 21:50:40
|
Here's a sample: DungeonElement top( "dungeon" ); DungeonElement *de = new Room(); de->setName( "roomX" ); de->move( 3, 5 ); top.add( room ); de = new Room( 7,3, "wide room" ); de->move( 17,4 ); top.add( de ); de = new Room( 5,8, "tall room" ); de->move( 10,1 ); top.add( de ); DMGrid grid( 20, 20 ); CERR << "after rendering:" << endl; top.renderTo( grid ); grid.dump(); (Doors will be added later.) Note how all of that is done through the generic DungeonElement API, and not Room's specific API. Basically, anything which goes in a Dungeon in a DungeonElement, and has lots of behaviour in common (moving, resizing, etc.), though each may implement that completely differently. This code draws us with the following map: 00000000000000000000 00000000001111100000 00000000001000100000 00000000001000100000 00000000001000100111 00011111001000100100 00010001001000100111 00010001001000100000 00010001001111100000 00011111000000000000 00000000000000000000 00000000000000000000 00000000000000000000 00000000000000000000 00000000000000000000 00000000000000000000 00000000000000000000 00000000000000000000 00000000000000000000 00000000000000000000 (Sorry for the ugly output - I haven't yet got the char/int mapping support done.) DMGrid provides a resizable grid. If it's resized, though, all renderings are nuked. Any attempts to write outside it's boundaries are ignored. You'll see that in the above map, the "wide room" overflows off the side. The rendering code is spread out: the recursive functionality is in DungeonElement. The actual drawing of data is left to the subclasses. Room draws nothing, but it's 4 children each draw themselves. See ya! ----- Stephan Beal - st...@wa... http://qub.sourceforge.net - http://stephan.rootonfire.org http://dungeonmaker.sourceforge.net "Now I'm not normally the kind of person who likes to trespass, but sometimes you just find yourself over the line." -- Bob Dylan |
From: Henningsen <al...@gl...> - 2001-04-27 14:57:58
|
>How about something like: > >Door( Wall *, position ) [: public DungeonElement] > >Then, when Wall gets render()ed, it will first draw itself to the grid, then >will ask all of it's Door children to draw themselves, which they will >gleefully do. >Also add: > >Wall::addDoor( Door *, int offset ) >Wall::addDoor( int offset ); // shortcut for addDoor( new Door( this, offset Good idea! Peter |
From: Stephan B. <st...@wa...> - 2001-04-27 14:31:18
|
On Friday 27 April 2001 15:30, you wrote: > I think you do. We'll have to see where Stephan takes it, but I think this > is about it. I think we all understand it the same. > In reply to Stephan latest postings: > I think specifying the start point, the length, and the direction for a > wall is an improvement, because it makes the check for "parallel to outer > walls" redundant. But you forgot the doors so far. Putting doors in the > walls will be one of the best improvements to actual usefulness of the code > we can make. People want ominously creaking doors with deviously hidden > keys in their dungeons! How about something like: Door( Wall *, position ) [: public DungeonElement] Then, when Wall gets render()ed, it will first draw itself to the grid, then will ask all of it's Door children to draw themselves, which they will gleefully do. Also add: Wall::addDoor( Door *, int offset ) Wall::addDoor( int offset ); // shortcut for addDoor( new Door( this, offset ) ); > Will you put a parameter "closedProb" in there with "openAtStartProb" and > the others? If you do, I can implement its use in the core DM classes. > That'll give me a chance to see whether I still recognize the code;-) No > hurry though... We can use whichever names you want. I haven't coded much since yesterday because my arm is aching, but I'll certainly try to finish the DMPr... DungeonDataKeep by Sunday night, with load/save support and all. See ya! ----- Stephan Beal - st...@wa... http://qub.sourceforge.net - http://stephan.rootonfire.org http://dungeonmaker.sourceforge.net "Now I'm not normally the kind of person who likes to trespass, but sometimes you just find yourself over the line." -- Bob Dylan |
From: Stephan B. <st...@wa...> - 2001-04-27 13:46:25
|
> In order for the things that Peter wants to do with > the DungeonMaker in the future to be possible, Stephan > will have to supply interface functions like this: > DesignParams* GetDesignParams(); //returns a pointer to a > struct or class containing the design params; > WriteDesignParams( filename ); > GeneticParams* GetGeneticParams( generation ); > WriteGeneticParams( filename ); No problem. We're a ways from doing that, though. I've been off the PC today because my RSI is acting up, but I hope to be back to coding tomorrow. > design and genetic data to two different files. Stephan, > when the user works from one of these file structures to > update dungeon data, will the DMProperties object be able > to update the other file structure also? Or maybe you will > need a function > GenerateDesignAndGeneticParamFiles( fromUnitaryFile )and > the other way round? You're getting way ahead of me. I haven't considering the genetic data just yet. I'd rather rewrite once I get to that point - I'm pretty scatterbrained, so I don't like to try to go too many directions at once. > Oh, yes, the naming, DMProperties... how about DungeonDataKeeper? > That is very descriptive, and also funny. That is a GREAT name. I'll do that. > So do I understand this right, you'll have the main classes: > DungeonDesigner - manipulates DesignParams (and possibly > GeneticParams), contains all kinds of high level constructs > such as Rooms, Palaces, CrawlerPairs, ... hands them to the > DungeonMaker as elementary simple data for Walls, Crawlers, etc... It's something like that. I haven't been concentrating at all on the Designer - just a really generic interface into the lower-level components so far. Once that API is complete the designer will know what it has to do. > DungeonMaker - more or less as is, constructs the dungeon > from elementary data Exactly. > DungeonDataKeeper - keeps all the data, both design data and > map data, and can present data to be rendered, and save and > load, and change between formats. Yup. > Ahh, you're sure working hard. Hope you're having fun, I wouldn't be doing it if I didn't enjoy it! ----- Stephan Beal - st...@wa... http://qub.sourceforge.net - http://stephan.rootonfire.org http://dungeonmaker.sourceforge.net "Now I'm not normally the kind of person who likes to trespass, but sometimes you just find yourself over the line." -- Bob Dylan |
From: Henningsen <al...@gl...> - 2001-04-27 13:21:52
|
The illustrious Selena wrote: > I come into town and what do I find: A big whopping pile of email. >Your DungeonMaker traffic has really taken off, Peter. Please be a bit more >selective in what you forward to me in the future. If my inbox is too full, >I'll simply have to ignore it altogether. Will do. Guess we should concentrate on the essentials, and write less;-( >I would say both maxCrawlers and joinDist could be GeneticParams. Why did >you put them into DesignParams? You are quite right, they make excellent GENETICparams. >Oh, yes, the naming, DMProperties... how about DungeonDataKeeper? That is >very descriptive, and also funny. I like it. >So do I understand this right, you'll have the main classes: >DungeonDesigner - manipulates DesignParams (and possibly GeneticParams), >contains all kinds of high level constructs such as Rooms, Palaces, >CrawlerPairs, ... hands them to the DungeonMaker as elementary simple data >for Walls, Crawlers, etc... > >DungeonMaker - more or less as is, constructs the dungeon from elementary data > >DungeonDataKeeper - keeps all the data, both design data and map data, and >can present data to be rendered, and save and load, and change between formats. I think you do. We'll have to see where Stephan takes it, but I think this is about it. In reply to Stephan latest postings: I think specifying the start point, the length, and the direction for a wall is an improvement, because it makes the check for "parallel to outer walls" redundant. But you forgot the doors so far. Putting doors in the walls will be one of the best improvements to actual usefulness of the code we can make. People want ominously creaking doors with deviously hidden keys in their dungeons! I don't want to put the older branch of the DungeonMaker on CVS. It's easier to get as a file download, and I'm not actively developing it anyway. Will you put a parameter "closedProb" in there with "openAtStartProb" and the others? If you do, I can implement its use in the core DM classes. That'll give me a chance to see whether I still recognize the code;-) No hurry though... Peter |
From: Selena W. <se...@al...> - 2001-04-26 22:40:10
|
Hey guys! I come into town and what do I find: A big whopping pile of email. Your DungeonMaker traffic has really taken off, Peter. Please be a bit more selective in what you forward to me in the future. If my inbox is too full, I'll simply have to ignore it altogether. >2. DESIGNparams - formerly called the rooms-file > >contains these params formerly formerly from the constants-file: >maxCrawlers >chDirOnStraight >joinDist I would say both maxCrawlers and joinDist could be GeneticParams. Why did you put them into DesignParams? >For version 2, I will write an "evolutionary-engine" object that will manage >the GENETICparams-file, accept user-ratings, and return fresh >GENETICparams-sets upon request. In order for the things that Peter wants to do with the DungeonMaker in the future to be possible, Stephan will have to supply interface functions like this: DesignParams* GetDesignParams(); //returns a pointer to a struct or class containing the design params; WriteDesignParams( filename ); GeneticParams* GetGeneticParams( generation ); WriteGeneticParams( filename ); The last two functions could then later be replaced by the genetic engine, working with its own binary file. I think storing single Crawlers will not be useful - as I understand them, one Crawler is pretty much as good as another, they get their quality from the interaction of an entire set (right, Peter?). The two save/restore types that I perceive to be of real benefit will be saving the entire dungeon data in one file, and saving design and genetic data to two different files. Stephan, when the user works from one of these file structures to update dungeon data, will the DMProperties object be able to update the other file structure also? Or maybe you will need a function GenerateDesignAndGeneticParamFiles( fromUnitaryFile )and the other way round? Oh, yes, the naming, DMProperties... how about DungeonDataKeeper? That is very descriptive, and also funny. So do I understand this right, you'll have the main classes: DungeonDesigner - manipulates DesignParams (and possibly GeneticParams), contains all kinds of high level constructs such as Rooms, Palaces, CrawlerPairs, ... hands them to the DungeonMaker as elementary simple data for Walls, Crawlers, etc... DungeonMaker - more or less as is, constructs the dungeon from elementary data DungeonDataKeeper - keeps all the data, both design data and map data, and can present data to be rendered, and save and load, and change between formats. Ahh, you're sure working hard. Hope you're having fun, Selena ________________________________________________ The void liberates you from all conceptual views ...but if you conceptualize the void... |
From: Stephan B. <ste...@ei...> - 2001-04-26 13:45:01
|
On Thursday 26 April 2001 15:05, you wrote: > In the DungeonMaker we should have a flat hierarchy, with just the > Map coordinates used for everything. In the DungeonDesigner you can > use nested hierarchies and build veritable palaces from walls if you > want. I'm sorry i didn't write earlier, but if (as i hope you do) you > go with my "no rooms in the DungeonMaker"-policy, this becomes all > very simple. And simple is the way we want it. Otherwise i might > never understand your code, and then what? Yes, following your earlier suggestion I will go with the all-walls=20 approach. Rooms are only wrappers which ease the work of using more=20 than one wall at a time. > >If you'll tell me that the crawlers simply analyze the grid after > > the rooms have been rendered to it, I'll continue with this more > > heirarchical approach. > > The crawlers do not interact with rooms objects in any way, they just > "see" with GetMap(i , j). But put all that complex stuff in the > DungeonDesigner. Please? Ah, good. Will do. ----- Stephan Beal Generic Universal Computer Guy ste...@ei... - http://www.einsurance.de Office: +49 (89) 552 92 862 Handy: +49 (179) 211 97 67 "Belief makes a hollow place. Something has to roll in to fill it." -- Terry Pratchet |
From: Stephan B. <ste...@ei...> - 2001-04-26 13:43:02
|
On Thursday 26 April 2001 15:05, you wrote: > >lets the room "draw" it's contents onto the target grid. Returns > > false if there is some error (out of bounds, etc., though the item > > would still be rendered as much as it could. > > That sounds good to me, go ahead. But make sure the bounds checking > is solid;-) We are not concerned with running fast, so definitely > check the bounds in the DungeonMaker, even if the DungeonDesigner > checks them also. That'll be the "hard" part (but not really hard). > >Even better would be to make a Renderable interface and have Room > > and Wall subclass that, then we have: > > > >DMGrid::render( Renderable * ); > > > >But I'm not sure what the Renderable API would have to look like (it > > would have to be generic enough to allow the DMGrid to handle > > drawing for all types of objects, and this seems a bit complex). > > I'd appreciate any ideas on a Renderable API which would allow > > DMGrid to handle all the rendering. > > Very simple - if you accept my idea of keeping anything above Walls > out of the DungeonMaker, there will only be (I think) four different > objects that will ever have to use this interface, and they are all > known to you right now.=20 Hmmmm. HHHMmmmmm. Yes. I will definately look more closely at this. > needed;-) Elegant code is not neccessarily easier to understand and > maintain. True, but I often forget that. :) > Yeah, keep it simple, man;-) Use the Renderable interface only if it > actually simplifies things, which i doubt it does. Avoid code bloat!! I'm attempting to make the framework use it's own API, so I can get=20 "maximum feel" for the usability. I try to limit myself to two API=20 calls per operation, to keep it as simple as user as possible. When I=20 find that I often have to make the same two-function call sequence, I=20 almost wrap that into another function. The current API has a very high=20 degree of granularity. Using the "suggested" API gives a very=20 high-level usage of the stuff, with very minimal coding. Then there are=20 a wide variety of lower-level functions. ----- Stephan Beal Generic Universal Computer Guy ste...@ei... - http://www.einsurance.de Office: +49 (89) 552 92 862 Handy: +49 (179) 211 97 67 "Belief makes a hollow place. Something has to roll in to fill it." -- Terry Pratchet |
From: Stephan B. <ste...@ei...> - 2001-04-26 13:39:07
|
On Thursday 26 April 2001 15:05, you wrote: > >You can have multiple CVS trees in the DungeonMaker project on > >SourceForge. We could use this to keep DM1 and DM2 in separate > > trees, if you like (this would be ideal, I think). If you'll send > > me a tar/gz of what you want for the DM1 tree, I'll do that for > > you. > > You mean, DM1 the 1.0 release I'm planning, and DM2 the stuff you're > working on now? If so, I kind of hope that DM1 will not be developed > any further because when the time cometh, i will enthusiastically > work on DM2;-) Let's stick a dungeonmaker1 tree in there, then. If you'll pack up the=20 tree you want to use as dm1 I'll get that into it's own tree. That also=20 allows us to easily make fixes to that code without doing any special=20 magic with CVS (branching, forking, merging, etc...). > PS: I'm a bit confused with terminology, because I use "DM2" for the > new class that will place doors in closed rooms and thus roomify our > dungeons - plus, it will find and store shortest paths to specified > locations.=20 Good point. I'm using DM2 to mean the generic rewrite. Let me know=20 which terminology you want for which work and I'll stick with those=20 terms. > I wonder how many target locations I should allow? These Why limit it? Using STL classes you can ignore any arbitrary limits. > are locations of special interest such that if a certain condition is > triggered, the AI for all monsters is switched around so that the > shortest path to location X is then known to the monsters... for my > purposes, 2 locations would be enough: the exit (catch the player > before he makes it, ahh, the excitement), and the quest location (uh, > oh, I'm approaching the Gryfniborg! All hell will break loose any > time now...). Any opinions? My mind is crammed with the reorg stuff right now. If I think about=20 this stuff right now it'll explode. ;) ----- Stephan Beal Generic Universal Computer Guy ste...@ei... - http://www.einsurance.de Office: +49 (89) 552 92 862 Handy: +49 (179) 211 97 67 "Belief makes a hollow place. Something has to roll in to fill it." -- Terry Pratchet |
From: Stephan B. <ste...@ei...> - 2001-04-26 13:36:31
|
On Thursday 26 April 2001 15:05, you wrote: > My only concern is whether it will also be possible to save/load > DESIGNparams and GENETICparams to/from two different files? We will > need that to implement planned future developments. Any DungeonElement object (see previous mail) can save itself to a=20 file, and it will contain only it's data and that of it's children. So=20 we'll be able to easily support multiple files for apps which need it: DungeonElement *dungeon =3D new DMProperties( "my.dungeondata" ); dungeon->load(); DungeonElement *crawler =3D new Crawler( "fred.crawlerdata" ); crawler->load(); dungeon->add( crawler ); =2E =2E =2E crawler->save(); dungeon->save(); // but crawler data is also saved here, because it's a=20 child of dungeon All done! ----- Stephan Beal Generic Universal Computer Guy ste...@ei... - http://www.einsurance.de Office: +49 (89) 552 92 862 Handy: +49 (179) 211 97 67 "Belief makes a hollow place. Something has to roll in to fill it." -- Terry Pratchet |
From: Stephan B. <ste...@ei...> - 2001-04-26 13:33:23
|
I've made some heavy changes to the heirarchy in DM, and I'm sure I'm=20 not done tweaking it yet. The heirarchy currently looks like this: DMProperties -> DungeonElement -> (Room,Wall...) DMProperties provides the basic properties storage and load/save=20 support. This can be replaced or added to later to write binary data,=20 for example. DungeonElement is a base class for... dungeon elements. Each can=20 contain an arbitrary number of other DungeonElements, and recursively=20 saves them when it's asked to save. You can remove elements, etc., as=20 well. Loading is broken right now because of these changes. I will make=20 several changes to saving to support this heirarchy, and hopefully will=20 be able to support arbitrarily-deeply-nested saving/loading. This=20 feature is a limitation of the data format, and not the objects, which=20 already can have any number of children going any number of levels dee. I expect that it'll be Saturday or Sunday before I'm happy with the=20 class heirarchy, but it's getting there. Of this heirarchy, the typical user would normally only use Room, Wall,=20 etc. The others provide all of the common functionality and to provide=20 a common framework for the data storage and internal representation. ----- Stephan Beal Generic Universal Computer Guy ste...@ei... - http://www.einsurance.de Office: +49 (89) 552 92 862 Handy: +49 (179) 211 97 67 "Belief makes a hollow place. Something has to roll in to fill it." -- Terry Pratchet |
From: Stephan B. <ste...@ei...> - 2001-04-26 13:28:14
|
On Thursday 26 April 2001 13:49, you wrote: =2E.. > My opinion is that if we get Walls into the DungeonMaker, Rooms > become redundant, and are just a source of unneeded complexity and The do become redundant, but they offer a MUCH simpler interface for=20 adding 4 walls at a time. I've got the room object about 1/2 done, and=20 it's got several convenience methods for creating sets of walls. This=20 saves the user the hassle of lining up x/y, etc. I'll have to think=20 about the doors implementation a big, given your notes from above. > possible bugs. Rooms would only be useful to simplify design, so > their proper place is in a design program - either a simple wrapper > program around the DungeonMaker (replacement for the current > main()-program) or a graphical program using QUB for interactive > design. Such a program should offer Rooms for initial placement of > several Walls + Crawlers which could then be modified. But there is > no reason to pass the Room data into the Dungeonmaker. Pass it all as > Walls, and *keep things simple*. Yup. We can have: Room::addToDungeon() which asks the Room to place all of it's walls in the Dungeon for us. --=20 ----- Stephan Beal Generic Universal Computer Guy ste...@ei... - http://www.einsurance.de Office: +49 (89) 552 92 862 Handy: +49 (179) 211 97 67 "Belief makes a hollow place. Something has to roll in to fill it." -- Terry Pratchet |
From: Henningsen <al...@gl...> - 2001-04-26 12:57:19
|
>Saving the object's state to the config file is now as simple as: > DMConfigFile c( "myfile.config" ); > SimpleConfigable sc; > sc.saveToConfig( c ); > bool okay = c.save(); > >If you have a completely populated DM object, you could save the whole >thing to a config file with: > DMConfigFile c( "myfile.dungeonconfig" ); > dm->saveToConfig( c ); > bool okay = c.save(); >..... >So, I'm trudging on ahead with that. If someone doesn't like it, please >let me know - I'm always open for discussion on these things. My only concern is whether it will also be possible to save/load DESIGNparams and GENETICparams to/from two different files? We will need that to implement planned future developments. Peter |
From: Henningsen <al...@gl...> - 2001-04-26 12:57:19
|
>I started on the Walls last night and came up with the following >parameters for each wall: x, y, length and orientation (horiz or >vertical). This keeps the user (and us) from having to check for >(x1==x2 || y1==y2, i.e., for enforcing non-diagonal walls), and >simplifies the API further. > >The question, though, is about the x/y: should they be relative to the >dungeon or to the containing room? It could be done either way. >Room-relative _seems_ to make more sense to me, but I'm not sure if >that's the best approach for this project. In the DungeonMaker we should have a flat hierarchy, with just the Map coordinates used for everything. In the DungeonDesigner you can use nested hierarchies and build veritable palaces from walls if you want. I'm sorry i didn't write earlier, but if (as i hope you do) you go with my "no rooms in the DungeonMaker"-policy, this becomes all very simple. And simple is the way we want it. Otherwise i might never understand your code, and then what? >If you'll tell me that the crawlers simply analyze the grid after the >rooms have been rendered to it, I'll continue with this more >heirarchical approach. The crawlers do not interact with rooms objects in any way, they just "see" with GetMap(i , j). But put all that complex stuff in the DungeonDesigner. Please? Peter |
From: Henningsen <al...@gl...> - 2001-04-26 12:57:19
|
>You can have multiple CVS trees in the DungeonMaker project on >SourceForge. We could use this to keep DM1 and DM2 in separate trees, >if you like (this would be ideal, I think). If you'll send me a tar/gz >of what you want for the DM1 tree, I'll do that for you. You mean, DM1 the 1.0 release I'm planning, and DM2 the stuff you're working on now? If so, I kind of hope that DM1 will not be developed any further because when the time cometh, i will enthusiastically work on DM2;-) Peter PS: I'm a bit confused with terminology, because I use "DM2" for the new class that will place doors in closed rooms and thus roomify our dungeons - plus, it will find and store shortest paths to specified locations. I wonder how many target locations I should allow? These are locations of special interest such that if a certain condition is triggered, the AI for all monsters is switched around so that the shortest path to location X is then known to the monsters... for my purposes, 2 locations would be enough: the exit (catch the player before he makes it, ahh, the excitement), and the quest location (uh, oh, I'm approaching the Gryfniborg! All hell will break loose any time now...). Any opinions? |
From: Henningsen <al...@gl...> - 2001-04-26 12:57:19
|
>I just started working on the Rooms/Walls combos and came up with some ideas >I'd like to throw by you and see if they sound as useful to you as they do to >me: > >Current DM holds it's own array of ints for the map. I'd like to split that >into a DMGrid object, which does the same thing but in it's own object. The >reason is simple: > >bool Room::render( DMGrid & ); > >lets the room "draw" it's contents onto the target grid. Returns false if >there is some error (out of bounds, etc., though the item would still be >rendered as much as it could. That sounds good to me, go ahead. But make sure the bounds checking is solid;-) We are not concerned with running fast, so definitely check the bounds in the DungeonMaker, even if the DungeonDesigner checks them also. >Even better would be to make a Renderable interface and have Room and Wall >subclass that, then we have: > >DMGrid::render( Renderable * ); > >But I'm not sure what the Renderable API would have to look like (it would >have to be generic enough to allow the DMGrid to handle drawing for all types >of objects, and this seems a bit complex). I'd appreciate any ideas on a >Renderable API which would allow DMGrid to handle all the rendering. Very simple - if you accept my idea of keeping anything above Walls out of the DungeonMaker, there will only be (I think) four different objects that will ever have to use this interface, and they are all known to you right now. The complicated object hoierarchy will be in the DungeonDesigner. However, don't make things more complicated than needed;-) Elegant code is not neccessarily easier to understand and maintain. >Does this sound okay? It would also mean simplification of the DungeonMaker >class internals and API (plus adding Set/GetGrid() methods). Yeah, keep it simple, man;-) Use the Renderable interface only if it actually simplifies things, which i doubt it does. Avoid code bloat!! Peter |
From: Henningsen <al...@gl...> - 2001-04-26 11:41:08
|
>For the upcoming changes we'll need to define some lines of >communication between the various objects. I mean, we'll need to decide >which objects know about each other, and how they interact. If we can >abstract this a bit (like by subclassing Rooms and Crawlers from a more >generic DungeonElement) they we will get the most extendability out of >it. These are my initial thoughts about who has to know about who >(denoted by arrows pointing to/from the classes): > >For example: >Rooms <--- Walls >This means that Rooms need to know about walls, but walls don't need to >know about rooms. I would prefer the DungeonMaker to be simply a random dungeon generator, and all the design elements it needs are Walls, Crawlers, OpenSquares, and Columns. Single wall tiles are degenerate Walls with start=end. Any other objects, like Rooms, SpecialRooms, SuperSpecialRooms, etc. should be handled in a design program that is an extra layer above the DungeonMaker. The Dungeonmaker should be kept as simple as possible, with no unneeded design objects in it. If we go that way, the hierarchy is flat, with no design object needing to know about another. >All <---- Config (config is a bad word for this, because it implies ini >file, when it's really more generic than that - suggestions for a >better name?) How about DungeonData? As I understand it, the config object will manage the DungeonMaker data, like in read it, serialize it, store it, allow modifications to it during interactive design... then we'd have the DungeonMaker, the DungeonData, and, if you want to bring all kings of extra objects like fancy rooms into the fray, the DungeonDesigner. Or if we adopt the style of ..Maker, ..Designer, and we want to make a little joke, we could instead of DungeonData call it DungeonKeeper. How about that? >The way I envision the basic Room API is something like this (of >course, completely up for change, though): > >Remove/AddWall( Wall ); >AddWall( int x1, int y1, int x2, int y2 ) >// creates a Wall and calls AddWall( wall ) >// must assert that x1==x2 OR y1==y2 (no diagonal walls), but this will >be done in Wall, and Wall will have a bool IsStraight() method which >returns false if the wall is not "straight". > >typdef list<Wall *> WallList; >WallList GetWalls(); // DM can use this to actually lay out the room. > >Various other STL-like iterator methods will also be supplied, for >looping through the walls. I hope you see the wisdom of keeping this out of the DungeonMaker class, and starting a DungeonDesigner class. (Of course, only after the DungeonMaker runs smoothly on Walls alone.) In the DungeonDesigner, i think you should start with functions for moving Walls, either in total, or by stretching them. Then from that you can build functions for morphing Rooms. With the Rooms, remember that they should have Crawlers attached to them, which will build unbroken walls between the room and an outside wall or another structural wall, and thus define the basic dungeon architecture. That is the whole idea of these pre-defined rooms. Their purpose is to be used together with the OpenSquares to implement story elements. If they are not structural in this sense, we may as well wait for DM2 and use random rooms. For structural rooms, I think it would be best to start with just a few types, the most basic being "2 doors, 2 Crawlers, player is forced to pass through". I actually think it would be quite sufficient for design if one placed a few of these, and then had the capability of morphing them. Peter |
From: Henningsen <al...@gl...> - 2001-04-26 11:41:07
|
>I was thinking about this this morning: what exactly is a wall, in our >context? Nothing but a set of two points, both of which must have the >same x or the same y. Actually no, because the only way we will get doors is through walls. I think we need in the Wall-object: startX , startY , endX , endY , doorType , doorSize , doorOffset doorType: 0 <==> no door 1 <==> opening that is always open (like we have now in all doors) 1 1 1 1 0 0 0 1 1 1 1 2 <==> opening that is always open with accentuated doorframe, like in 1 1 1 2 0 0 0 2 1 1 1 ... 0=open, 2=high wall 3 <==> actual door that can be open or closed, different graphics from open space 1 1 1 1 7 7 7 1 1 1 1 ... use new value 7 for "door" 4 <==> actual door with accentuated doorframe 1 1 1 2 7 7 7 2 1 1 1 doorSize: the above examples have doorsize 3 - this is doorsize 4: 1 1 1 0 0 0 0 1 1 1 ... with doorOffset 3; the examples above all have doorOffset 4. doorOffset: number of tiles from start until door begins Comment: In the current rooms-based version, all walls and doors must have an odd number of tiles, so that it is unproblematic to center the door. If we go to walls, we can do away with this altogether, and give the use total freedom to place the door where she wants. However, we should check that there is actually a wall tile at the end of the wall, and reject a wall if its end falls in the middle of a door. >I think it would be simpler for users if we keep the rooms, for ease of >use, AND offer walls (for fine-tuning). Rooms, after all, are just >wrappers around N walls. My opinion is that if we get Walls into the DungeonMaker, Rooms become redundant, and are just a source of unneeded complexity and possible bugs. Rooms would only be useful to simplify design, so their proper place is in a design program - either a simple wrapper program around the DungeonMaker (replacement for the current main()-program) or a graphical program using QUB for interactive design. Such a program should offer Rooms for initial placement of several Walls + Crawlers which could then be modified. But there is no reason to pass the Room data into the Dungeonmaker. Pass it all as Walls, and *keep things simple*. Peter |