Search Results
Searched for posts by SquashMonster in all forums

Showing results 1 - 8 out of 8 total
Modify your search
Posted by SquashMonster, Nov 6, 2011 at 3:47 pm
Okay, this post got a little technical so here's the tl;dr version. I think I can make the whole worldmap generation thing a whole lot simpler, and way easier to add new locations to. Maybe I could even port it to a script file instead of people having to touch code to add dungeons. But the catch is that the New Attnam continent will average slightly bigger (4 to 10 cells instead of 2 to 4) and that it might not always be as close to the Attnam continent as before (the underwater tunnel could be improbably long). Is that acceptable?


Great tutorial, Warheck!

So, to clarify a little, the way things are working in the code there are that wterras.h contains a bunch of class definitions for classes that extend owterrain and gwterrain. owterrain is towns and dungeons and the like, gwterrain is forests and tundras and the like - I have no clue what the two names are supposed to mean, they're both overworld terrain. OWTERRAIN(namehere, owterrain) is a macro that does part of the class definition for you. What you are filling in at wterras.cpp are the actual methods of the class, which contain the class data. Nothing is actually being added to the game at this point though, just the code. Down in worldmap.cpp when you call ChangeOWTerrain(namehere::Spawn()) you are calling a method in the class namehere (which you unwittingly made with that OWTERRAIN macro) which creates an instance of that class and puts it into that square of the map.

This is actually rather inside-out. All the dungeons and towns could share a class, and different objects of that class would have their different name strings, graphics positions, etc. This would also be convenient because it'd allow you to make an actual list of places in the game, which then allows you to replace that whole mess at the start of worldmap::Generate() with something that looks like:

 for(uint c = 1; c < Continent.size(); ++c)
{
    if(Continent[c]->GetSize() > 25 && Continent[c]->GetSize() < 1000)
    {
        truth aPlaceForEveryone = true;
        for(uint i = 0; i < ImportantPlaces.size(); i++)
        {
            if(Continent[c]->GetGTerrainAmount(ImportantPlaces[i]->GetLocalEnvironment())
            {
                aPlaceForEveryone = false;
                break;
            }
        }
        if(aPlaceForEveryone)
        {
            PerfectForAttnam.push_back(Continent[c]);
        }
    }
}

Which doesn't need to be changed when you add places, you just need to make sure ImportantPlaces gets your new location added to it at some point if it needs to be in the Attnam continent. And the AttnamPos, ElpuriCavePos stuff can be done easily with a list, as can the end spawning.

This can be extended to work for multiple continents pretty easily too. ImportantPlaces becomes a list of lists, things that need to go in the first continent go into the first list, next continent the second list, and so on. I can write code if that makes it more clear, but what I really want to get at is that there is a big messy hitch to all of this.

New Attnam is not actually on a continent. The game doesn't even look for a tiny island for it. Wherever the exit to the underwater tunnel goes, the game looks a certain radius outwards for some ocean and builds a tiny island on the spot, midway through the part where the other locations are looking for a place in the already-existing world. It's really hacky and I don't know how to generalize that.

So what I was thinking is maybe I make it so the game can check for different required sizes for the different continents (see above, it's looking for 25 to 1000 for the Attnam continent). Then the multi-continent thing above would let it put New Attnam on a small real continent, instead of a small continent it summoned out of the aether. The problem is that by default those continents wouldn't be anywhere near eachother. I could pretty easily add a generic thing that says two overworld locations try to be close to eachother (by repeatedly sampling possible locations and taking the best of N samples) which increases generation time slightly and improves the tunnel situation so far as at least making the two ends be as close as they can be on their continents (which is to say, if the continents are on opposite sides of the world, at least the tunnels are facing eachother). I could also put in a hard limit (discard the world if two locations are not within X of eachother), which fixes the problem entirely but that would probably increase generation time a fair deal, especially as people add more locations that use this requirement.

Anything that reduces special locations to objects instead of classes has another benefit. It's the prerequisite to being able to port that off to a script file. But learning how to make new script files is a big challenge in and of itself, I'd say this is something that should be done in two steps.

So... go for it, or use your tutorial as the official way to add new things to the world?
Posted by SquashMonster, Nov 5, 2011 at 11:38 pm
How much would be in the game development fund? I do contract game development now, that's part of why I don't have much time to do proper work helping out IVAN. I would be willing to give a significant discount from my usual rates for such a cool project.

Don't let it sound like I'm pushing for that though. I'm happy to do what I can for free.
Posted by SquashMonster, Nov 5, 2011 at 7:00 pm
There aren't enough people to justify spreading discussion around. Putting everyone in the same spot makes sure ideas draw a crowd and maximizes the chances that someone sees something where their skills or ideas are useful.

Phase 1 has some good non-programming questions that need answering.

  • What things from existing variants fill an otherwise empty spot and should be added to the game?
  • What existing monsters are Gloomy Cave only? What about the Underwater Tunnel, or that crystal cavern, or Oree's realm?
  • Should we add some more stuff to pad out the Gloomy Cave only list?
  • What do we name the damned thing?

Also, we can talk about the black fortress, coral tower, etc.
Posted by SquashMonster, Nov 5, 2011 at 4:14 am
The approach I give above will let you limit monsters to certain dungeons, but it only supports "any dungeon," "specific dungeon," and I suppose "no dungeon," by degenerate-case (do specific dungeon, never make that dungeon). It does not do sets of dungeons.

I went with making the dungeon tag a string instead of a series of integer flags because it makes things easier for developers who don't know coding (the string approach doesn't need defines). So you cannot or things together like in your example. However, now that you mention it there's a really simple way to get the best of both. Replace DataBase->DungeonSet==game::GetDungeonSet()
with game::GetDungeonSet.Find(DataBase->DungeonSet)!=[failedvalue]

I'm not sure what the return value of a failed find is with festring. Too much uncommented template-laden code for me. So actual return value of a failed find where I wrote [failedvalue] but otherwise just like written above. This makes it so if you say DungeonSet="HorsesSkeletons" or DungeonSet="Horses|Skeletons" or however you want to write it, it will find Horses and Skeletons as substrings and allow those creatures in the set. The downsides are that it's slightly slow (but who cares, it's 2011 and this is a turn based game) and that sometimes you will occasionally run into hilarious misunderstandings where one name is a substring of another (if you defined Petrus' wives as "Ho" then they'll show up with horses).


I just saw what vasilly did with the dungeon dat and it's really great. We absolutely should have that feature. Is his code available and in a working state? I saw that he was working on replacing all scripts with some fancy thing and we don't need that (especially since it doesn't seem to have happened) but everything else from his version sounds like a fantastic base.


Bursting out the other data types would be super handy as well. Actually, what I've done for similar projects works even better, but I think it's scope creep in this case. For reference I'll explain anyway.

Say each type of data has a specific type name that shows up in the declaration of an element. IVAN already does this nicely in dungeon.dat, where every new dungeon starts with the DUNGEON declaration, but does not do this for the other data files. All types of data can show up in all files. So, I could declare an Ommel creature in a file, then decide it needs Ommel_Flesh and declare that in the same file. Instead of bothering to have specific data files at all, the game just reads every data file out of the script folder, and yells at you if you define the same thing twice. For things that need to refer to eachother you need to do some clever stuff though (simplest version of clever stuff - set all references to placeholders then pass through after everything is loaded and resolve placeholders).


And I would say CVS or Vasilly would be the best places to start. Also, if I understand correctly (I often don't) you added a number of extra dungeons in CLIVAN, yeah? Do you have a general system for that, or in general an idea how we'd do Phase 1 point 2?
Posted by SquashMonster, Nov 5, 2011 at 1:19 am
I thought dungeon-tags seemed a fair deal harder than the rest of what phase 1 asked, so I went through and found all the places that need changing for it. I haven't actually tested this yet, and probably won't have time to get IVAN compiling any time soon, but it will work .

Phase 1 - "Add dungeon-tags to script files."

In char.h -
- add DATA_BASE_VALUE(const festring&, DungeonSet) to big list of DATA_BASE_WHATEVER calls
- add festring DungeonSet to struct characterdatabase

In script.h -
- add SCRIPT_MEMBER_WITH_BASE(festring, DungeonSet) to levelscript

In script.cpp -
- add INIT_ENTRY(DungeonSet) to levelscript::InitDataMap()

In level.h -
- add festring DungeonSet to level's protected members
- add festring GetDungeonSet() const { return DungeonSet; } to level near GetDifficulty

In level.cpp -
- add DungeonSet to list of things saved by level::Save
- add DungeonSet to list of things loaded by level::Load (must be same spot in list, natch)
- add DungeonSet = *LevelScript->GetDungeonSet() to level:generateDungeon

In game.h -
- add static festring GetDungeonSet() { return CurrentLevel->GetDungeonSet();} near GetMinDifficulty

In proto.cpp -
- at start of protosystem::BalancedCreateMonster() add festring anyDungeon = festring("any" );
- in protosystem::BalancedCreateMonster(), after it checks Database->IsAbstract and Database->CanBeGenerated but before it checks DataBase->IsUnique, add if(!(DataBase->DungeonSet==game::GetDungeonSet() || DataBase->DungeonSet== anyDungeon)) continue;
- (note that constructing and comparing festrings is most likely place for me to have made error)

In char.dat
- add DungeonSet = "any"; to character (the default)
- add DungeonSet = [set you want to restrict to] to [entry you want to restrict to a specific dungeon]

In dungeon.dat
- in each level 0 or LevelDefault block, add DungeonSet = "nothingspecial"
- in each floor block where you want to ignore that, or in dungeons where you want to enable a special dungeonset, (instead) put DungeonSet = [what you named that set]
Posted by SquashMonster, Nov 4, 2011 at 12:00 am
The key to making it so people don't always choose the same dungeon is differentiation in the capabilities of characters. Making sure Underwater Tunnel gives a varied spread of loot and stats is important to this - your example of weapon skill is a good example of somewhere the game already does this.

So an in-depth proposal:

Phase 1:
  • Make a fork with its own SourceForge project page
  • Look through existing variants and see what has the most extensible way to add new dungeons. Try to make adding a dungeon to the game as easy as possible. Dungeon-system should have a global "chosen dungeon" that can be set when the player chooses a dungeon.
  • Look through existing variants and see what new content has been made that fills a specific niche missing in the base game.
  • Add dungeon-tags to the script files. Monsters/items/etc need to be able to be tagged with "blackfortress" or "towerofcoral" or "gloomycave" and only be chosen by the random generator in floors that have the matching tag.

Phase 2:
  • Everyone who wants to contribute gets their own dungeon. You own your dungeon project but are not required to do it by yourself - you can open yourself up to submitting new creatures and whatnot from the community. Note that things will go a LOT faster if most creatures and items are all-dungeons, we define a handful as being iconic Gloomy Cave features, and only try to get that many new ones.
  • People can add new towns as well, especially after we have a few dungeons. Towns should continue to be full of very difficult to kill people, so leveling all the towns you don't need for your quest is not an easy way to gain extra experience and items.
  • Begin adding new subsystems. When a new subsystem is complete, put high priority getting someone to make a dungeon designed to emphasize that subsystem. There's a list of example systems at the bottom of the post.

Phase 3:
  • The game will become somewhat non-cohesive after a lot of new towns and dungeons are added. I think it'll be a good idea to add some inter-town multi-part fetchquest type deals that need to be completed before unlocking the actual quests that send you off to dungeons. And some side challenges to get food while doing this. But this is seriously like two years down the line, don't worry about Phase 3 stuff.
  • Start adding higher-level-monster content (monsters) to the dungeons. Add higher-level variants of fixed monsters like Elpuri and the Enner Beast. Once there's enough we can do "ultra" endings for completing multiple plots in a row. Note that the game's existing dynamic difficulty system is important to making this work. Again, Phase 3 is like two years down the line at minimum, don't worry about it any time soon.

And since a lot of people may want to work on subsystems, here is a non-exhaustive list of a bunch I think could fit into the game well. Nobody has to do all of these. Nobody has to do any of these. And I want to hear things I haven't listed.
Subsystems:
  • Magic. I highly recommend doing this after other subsystems to give spells ways to do interesting things, instead of fireball things.
  • Complex enchantments / curses. IVAN tracks what kind of wood your sword's hilt is made of separately from what kind of metal the blade is made of, yet "enchantments" are raw numbers. Weapons should be able to pick up all sorts of odd quirks, without being artifacts. Armor and other items too. (Emits a constant droning noise that lures in monsters, you teleport five squares when you use it, weapons with knockback, it makes rats follow you, weapons that really hate orcs...)
  • Mutations. Crawl and several other roguelikes have these. IVAN, with its limb and materials systems, would be an even better place for these. You definitely need to be able to grow a giant crab claw out of your head, then change material that to steel.
  • Vermin. With all that blood and guts and gibs and extraneous detail in the game's dungeons, they probably should be crawling with rats and maggots and beetles. These are separate from monsters in that they do not attack you and you can just walk over them. Normally it's just flavor, but then in one dungeon it's all plague rats, and a spell makes them attack your enemies, and so forth.
  • Random artifacts. If you have complex enchantments in, this is super easy. Just give a random item a name and an unusually large number of enchantments and curses.

So there you have it. Re-read phase 1 to see we really don't need to do much to get things into a shape where people can contribute all these awesome things more easily.

Also, someone tell me why the list syntax is broken.
Posted by SquashMonster, Nov 3, 2011 at 6:44 pm
Ischaldirh wrote
Wow, it HAS been 5 years. Hi, Squash. Long time no see.
Atomic, you spelled your name wrong. It's spelled "Izzy."

capristo wrote
I don't know you from jconserv, but welcome. Has it really been 5 years? Wow.

"I think I actually know how to fix that"

Please tell more
Okay. Everyone wants there to be more IVAN. But there are three problems with that.

IVAN is already a complete game-length. There is enough stuff to do in a normal run from Underground Tunnel to the ends of Gloomy Caves, and adding any more would mean either fucking up the difficulty curve or adding a whole lot of new content for more powerful characters (since you get more powerful the more stuff you do, natch). The game is also so hard that many people who've been here five years haven't beaten it, which is great, but making it longer means even fewer people will get through.

Everything that is already in the game, there is enough of. The game has enough monsters, items, materials, and gods. Well, it could use a handful more in certain key places but over-all you cannot pad up the game with a bunch more of this sort of content.

The existing ways to contribute do not give developers ownership. People are more motivated to work on things if they feel like their contribution is a solid thing. If Tim adds something to the game, people should be able to say "Oh, Tim? Yeah, he did the tower of coral." not "Oh, Tim? He added like... four monsters, I think one of them was that bee golem, and then a couple types of armor and a prayer effect for... Silva? It was either Silva or Nefas." It also helps to have a defined place that the game needs new content, which are really what the other two points are about.

Watch now as I majestically fix all of these problems in a single stroke.

The game needs a slight restructuring. The start of the game is brilliant, everything up through the end of Underground Tunnel can stay as-is. Afterwards, the game needs to branch out. You choose a quest somewhere; maybe it's heading to Gloomy Cave like always. Or maybe you decide to conquer some other dungeon like Tim's tower of coral. Whichever you pick, that locks you out of the others for the rest of the game. It's okay; you'll get to see the rest of the dungeons, because you'll die, because it's still IVAN.

How does this fix things? It lets you add to the game while keeping the game length the same. As long as new dungeons are roughly the same size as GC (and they don't need to start that way, they can grow to fit), the length is the same. It allows you to add more content to the game without cluttering it - new dungeons need new thematic monsters instead of GC's communism and radiation theme. A developer can "own" their dungeon and feel good about the contribution. New developers know where to start without stepping on toes. And, all the more importantly, it answers the question for everyone of "what am I actually accomplishing by adding to this game?"

Now, from a game design perspective, there is something slightly off about this plan. Why does the player pick dungeon B, instead of dungeon C? The answer in that is simple - during the course of Underground Tunnel, different characters tend to pick up different capabilities. New dungeons need to emphasize this - if I end up with completely rigged armor and health and no offensive capabilities to speak of, I should be able to figure out which dungeon best capitalizes on that, and pick that quest. We can emphasize that with something else IVAN needs.

New subsystems. IVAN is a game where baroque subsystems are the name of the game. Limbs, materials, gods? All go into a great deal of depth. More can be added, and doing so means being able to add more interesting monsters and items. More monsters and items means more interesting dungeons. I can think of a lot of great places to add this sort of thing, but I think I've said enough for now. If you don't think I'm crazy I'll go into more depth.
Posted by SquashMonster, Nov 3, 2011 at 5:08 am
Somagu insisted that I should stop by and say hi because apparently I'm a legend.

I won't have free time worth shit for the next month at least, so don't expect to see much of me. But hi. I'll try to at least keep up with this thread.

Also, I hear you have a lot of problems with fork/variant devs showing up and disappearing without a trace before they make all that much. I think I actually know how to fix that, but is anyone who's still around a programmer?

(I don't count - didn't you hear that I don't have free time worth shit?)