NPBruce / valkyrie

Valkyrie GM for Fantasy Flight Board Games
Apache License 2.0
506 stars 105 forks source link

Quest Generator D2E v1.0 #637

Open PeterF-D2E opened 7 years ago

PeterF-D2E commented 7 years ago

Hi all,

I have been working on a software package for randomized quest generation for D2E (basically a set of MATLAB/octave routines). The s/w selects tiles at random and builds a dungeon with them; placing doors, spawning monsters, placing search tokens, and including a quest objective. The output can be used with Valkyrie to play a different quest each time. They are mainly intended for one-offs, or side quests, but anything is possible. They might also serve to start people of who want to create their own quests. Just generate a few dungeons until you get something you like, and start editing from there.

The plan now is to integrate it in Valkyrie itself with help from Bruce. Also, if anyone has ideas how to add more variety, let me know. Just keep in mind that it should be quite modular to easily fit in different dungeons.

Discussion at boardgamegeek: https://boardgamegeek.com/thread/1850261/random-dungeon-generator

and the files: QuestGeneratorD2E_v01.zip

NPBruce commented 7 years ago

Some random thoughts:

If leaving number of tiles to the random generator it can go down to 1 tile and up to all tiles used. Perhaps setting a minimum and maximum is useful?

I would like to change the tile definition arrays to characters, so that it is more visual and will line up using fixed width. This can be done with a find and replace, I am thinking something like this:

  ._  
##*&##
######
######
######
######
##&*##
  _.  

The problem is that a hazard square can't be on a puzzle edge, but I don't think this ever happens? One solution that may also help readability is to only mark the external puzzle spaces (1/2) and imply the others.

Going further still, only the extended bit (2) needs to be marked, as long as A/B type connections are known. This could mean using numbers 0 to 9 for here to mark inside, outside, city and blackrealm. I am also thinking ahead to Imperial Assualt which has even more types.

Traits in Valkyrie will need to be updated, this is not a big issue.

Currently this doesn't allow for excluding tiles sides where the other side of the same tile is already used. Valkyrie has this information already so it shouldn't be hard to add.

It doesn't look like you have a tile count to limit number of end peices or other duplicates. This will need to be added (Valkyrie doesn't have this either).

The traits you have are: 'Building','Cave','Cold','Corridor','Crossroads','Dark','Hot','Room','Tunnel','Water' Some of these are the standard D2E monster/quest traits are some are not. It is not immediately clear to me how these are used and mixed.

Random Names: This is both easier and harder in Valkyrie. You can self reference in dictionaries so you can have:

quest.name,{qst:PLACE_NAME2} {qst:OF} {qst:ADJECTIVE4} {qst:THEME1}
PLACE_NAME1,Crypt
PLACE_NAME2,Dungeon
PLACE_NAME3,Labyrinth
OF,of

This will allow for translations, however the quest.name will need to be generated, so any language that doesn't fit the X of Y Z template will break without special support.

These all look like things that should be exposed as controls for the generator: % probability that a doorway has a door ratedoor=.75; % probability that a tile has a spawn event ratespawn=.67; % probability that a tile has a search item ratesearch=.33;

On questtype, my concept is to have these still manually created. So the quest would have a manually written intro/outtro and the bit in the middle will be filled in. One implementation of this would then be to create a quest (not an internal Valkyrie feature) that has a whole bunch of questtypes as you have done and picks one at random, but I don't see that is something that should be built in.

The Long/Short weighting doesn't seem to do anything?

I think the first step is to get the extra TileSide data into Valkyrie, I will start on this.

NPBruce commented 7 years ago

Here is my current thinking:

[TileSide1B]
name="1B"
top=197
left=105
image="{import}/img/001B.dds"
traits=throne inside building
reverse=TileSide1A
zero=1,1
map00=    B    
map01= ##*#####
map02= ##*#####
map03= ########
map04=B########
map05= ##*#####
map06= ##*#####
map07=     B   

Where A is a join protrusion on an A side, B is for B side, C is for city and D is for blackrealm. * is obstacle, _ is pit, ! is hazard, ~ is water and = is sludge.

NPBruce commented 7 years ago

Tile definitions added here: https://github.com/NPBruce/valkyrie/blob/quest_generator/unity/Assets/StreamingAssets/content/D2E/base/tiles.ini

I will stick with the base tiles until I have something working.

PeterF-D2E commented 7 years ago

If leaving number of tiles to the random generator it can go down to 1 tile and up to all tiles used. Perhaps setting a minimum and maximum is useful?

Yes, that needs some improvement. I think the best solution would be if the user can choose between e.g. small, medium, large, vast, and the number of tiles then becomes 10,20,30,40 +/- 2 (random part) or something similar. That way the user can plan his evening, while not knowing the exact number of tiles.

I would like to change the tile definition arrays to characters, so that it is more visual and will line up using fixed width.

I like that idea. Using numbers makes it easy to literally add the tiles, but that can also be solved in a different manner. Or do you want to translate back before fitting?

The problem is that a hazard square can't be on a puzzle edge, but I don't think this ever happens?

I think that's a safe bet, because ffg wouldn't be able to complete the colored lines otherwise.

One solution that may also help readability is to only mark the external puzzle spaces (1/2) and imply the others. Going further still, only the extended bit (2) needs to be marked, as long as A/B type connections are known. This could mean using numbers 0 to 9 for here to mark inside, outside, city and blackrealm. I am also thinking ahead to Imperial Assualt which has even more types.

Yes, the tile shapes would be completely defined by using A or B. You will need to make the fitting algorithm a bit smarter though. Just make sure the 1 in my tile definition is still an occupied square, and can only be used for a connection. That way it can almost always be closed of with an end cap.

Again, I don't know if you want to translate back before fitting, but otherwise you could get the following. Suppose you have two tiles. To which tile does the middle B belong?

. B . ## ## . ##B##B . ## ##

Having said that, my method might also have some problematic corner cases, E.g. when combining A and B tiles.

Currently this doesn't allow for excluding tiles sides where the other side of the same tile is already used. Valkyrie has this information already so it shouldn't be hard to add.

That would be a nice addition. I only considered B sides so far.

It doesn't look like you have a tile count to limit number of end peices or other duplicates. This will need to be added (Valkyrie doesn't have this either).

True.

The traits you have are: 'Building','Cave','Cold','Corridor','Crossroads','Dark','Hot','Room','Tunnel','Water' Some of these are the standard D2E monster/quest traits are some are not. It is not immediately clear to me how these are used and mixed.

I used the following traits:

  1. D2E monster/quest traits
  2. 'Corridor' vs 'Room' tile traits determined manually by looking at the tile.
  3. 'Tunnel' vs 'Crossroads' tile traits determined automatically from the number of possible connections
  4. 'Long' vs 'Short' for weighting

A generated quest can have any type of trait. 1-3 are used to select tiles to include in the dungeon (simply ignoring 4). 4 is used to select the connection where to place the next tile (1-3 are ignored) 1 is used to spawn monsters (2-4 are ignored)

Random Names: This is both easier and harder in Valkyrie. You can self reference in dictionaries so you can have: quest.name,{qst:PLACE_NAME2} {qst:OF} {qst:ADJECTIVE4} {qst:THEME1} PLACE_NAME1,Crypt PLACE_NAME2,Dungeon PLACE_NAME3,Labyrinth OF,of This will allow for translations, however the quest.name will need to be generated, so any language that doesn't fit the X of Y Z template will break without special support.

I did not consider this yet. English might actually be the easiest language for something like this. Having a 4 word combination and 4 word lists simplifies it a bit (a list can also be a single word). That way the adjective can e.g. be placed at the back. But that still might give problems with male vs female words etc. Maybe it would be better to just provide a long list of complete names?

These all look like things that should be exposed as controls for the generator: % probability that a doorway has a door ratedoor=.75; % probability that a tile has a spawn event ratespawn=.67; % probability that a tile has a search item ratesearch=.33;

Do you mean controlled by the user? I'm not sure. Maybe better to set them according to difficulty level.

On questtype, my concept is to have these still manually created. So the quest would have a manually written intro/outtro and the bit in the middle will be filled in. One implementation of this would then be to create a quest (not an internal Valkyrie feature) that has a whole bunch of questtypes as you have done and picks one at random, but I don't see that is something that should be built in.

I see what you mean, and I agree about the 'fluff'. But there still should be some kind of archetypes I guess, Because it also determines whether there should e.g. be an exit, unique monster etc.

The Long/Short weighting doesn't seem to do anything?

It should influence where the next tile is placed. Far from the entrance, or close to the entrance. The idea is that this makes the dungeon more stretched out or more densely packed.

Where A is a join protrusion on an A side, B is for B side, C is for city and D is for blackrealm. * is obstacle, _ is pit, ! is hazard, ~ is water and = is sludge.

Nice selection of symbols! I planned to distinguish between B and D through tile traits. They can be mixed quite easily, but this also works.

NPBruce commented 7 years ago

Nice selection of symbols! I planned to distinguish between B and D through tile traits. They can be mixed quite easily, but this also works.

You can't use tile traits because of tiles that cover multiple types, it has to be on the connection.

I'm working on implementing the basics of this now.

PeterF-D2E commented 7 years ago

I got Mists of Bilehall in the post today, and going through the tiles I noticed the following tile:

83B

  B    
!!!#!#B
*!!!!# 
!!##!! 
   B   

The hazard square under the top B would not have fit in my system, because the yellow square around the tile is not complete. But for your proposed system it should not be a problem. I'll also go over the tiles from the other expansions one of these days.

NPBruce commented 7 years ago

I haven't forgotten this, but I've had a lot going on and a new MoM expansion just dropped, so I'll be adding support for that first.