Bay 12 Games Forum

Please login or register.

Login with username, password and session length
Advanced search  
Pages: [1] 2

Author Topic: AutoFort  (Read 3796 times)

teatime

  • Bay Watcher
    • View Profile
AutoFort
« on: June 26, 2020, 02:35:50 pm »

Moving this here from General Discussion
Automatic Fort Generation

I am maximally lazy; as I perform a repetitive task I think of ways to automate it, and this has been the case when making fortresses. I don't want to do this for my own fortresses, because I am the program that bests makes new exciting forts, but it feels like there is a general enough structure to what I do, regardless of the goal of my fort, that I could abstract it into a program, and that program could then generate groovy NPC fortresses that evolve with the world.

First off, I'm virtually certain someone else must have posted about this, but being new here and not knowing the exact lingo, my search-fu is lacking. If someone can point me towards a thread, I'd be greatful. Other than that, I intend to just put some thoughts down here; I like thinking about creative problems, and I'm sure having more opinions on it would only make the end result better.


Automatic Fort Generation: A Problem Statement


So, in essence, what do we want from an automatically generated fort?
  • There must be enough variance that to all but the most non-casual observer it would look designed
  • There must be relics of its evolution
  • It must be appropriate to the culture
  • It must be appropraite to the history of the civilisation and site.

When the fortress generation starts there will be initial conditions guiding its evolution based the motivations of the settlers (nomads, expanding the borders of a nearby settlement, an advance outpost for an invasion, a remote new settlement far from the homeland, a mining colony, etc).
The race influences the fortress structure (eg. dwarves are more likely to make underground fortresses, humans are more likely to channel out pits for stone and build buildings, but if the area doesn't allow it, anything is possible to survive). In the long run the fortress should evolve to suit the races preference*.
Relics of the fortresses evolution in this case refers to things like gradually replacing materials that become available over time, or having the goal of the settlement evolve, like an advance outpost that becomes a keep surrounded by farms after a war, or a small villiage that gradually grows to a city over a long period of time. Each of those scenarios would leave footprints depending of the nature of the changes at each step (like having wooden inner walls that used to be outer walls).

The goal here is then to find a framework to encapsulate all of this so a small working version can be written that, although intiially limited, could grow to accomodate all of these variables. To satisfy the requirement of "looking designed" will require some way to creatively mutate the base structure. Ideally if I could encapsulate this in a configureable way, so that I only leave a minimum of fingerprints on the fortress generator, then some kind of community sourcing action could generate parameter sets to finetune certain aspects of the final forts.

While I have a lot of pretty cool ideas for for this could generalise to other races and terrains, as a very bare minimum, the least this thing would have to do is create a fortress, for dwarves, underground.

A Simple Model For Fortress Evolution

For this to work properly, I can't just generate a fortress, I have to show my work. A good starting point is the same as Dwarf Fortress itself, the embark. I would need to know how many dwarves are coming, why they are coming and what they are bringing. A site may be built by royal decree, in which case the king could send a hundred laborours with several caravans of prepared materials and it would just pop into existence; or seven rugged, wild spirited dwarves could march into the mountain with two axes, two picks and a bag of seeds.

The motivation of the group and the materials they have will affect what happens when they reach the area to build their fortress, but this area will also affect what they can do**.
Ceremaic and clay industries can only exist if there is clay and sand.
Terrain that has large wobbles all over is not suitable for big surface structures (or rather, would be preferentially selected against in that environment, unless there was a motivation otherwise).

Realistically the first phase should involve shelter. Dwarves can either gather materials to build a building, or dig down/into the side of a mountain for shelter, leaving the food and wagon outside for too long isn't a good option. This is not necessarily housing yet, just somewhere to exist that isn't ouside and exposed - a meeting place, indoors. The cave is underground, safe, and eminently useful to your stone industry; but a lot of my forts have had some kind of keep-like structure, and it normally evolves from a little hut I built to protect my caravan.

Once there is somewhere to exist that isn't outside, the next priority is food. There are limited options on what to do here depending on the environment and the items you embarked with, but ignoring the complexity of what you brought along, in general you can get food by hunting, foraging, farming, owning animals and fishing. Owning animals yields continuous food in the form of milk and eggs, and discrete amounts of food in the form of meat, that if properly managed, doesn't reduce your flock size. Bees are counted as animals in that list, but cannot be eaten (yet?).

The food industries chosen by the group will related to what's most readily available in the area; but will also be affected by the motivation for creating the fort. You can't have 20 herbalists and fishermen roaming the country side when you're an advance outpost for an invasion; in such a case you either need a secure food supply behind your walls, or a reliable trade route to get supplies to sustain your war effort***. The size of this industry would be also affected by the groups motivation (plans for a big city needs plans for a lot of food, initial farm area might be small, but space is left for expansion because the city is planned to be large, a city that was planned small but grew large would bare the scars of inadequate spacing, and might necessitate creating a "second fortress" somewhere else that can accommodate the increased numbers comfortably).

Alcohol is a vital offshoot of the food industry, and all dwarven fortresses need a supply. All dwarven fortresses should employ a progressive strategy for acquiring alcohol.
Depending on the chosen food industry, dwarves may have the means to create alcohol.
  • If they are unable to create it, they must try import it.
  • If they are unable to import alcohol, they must seek seeds.
  • If no soil is available, seek water to create mud.
  • If no water is available, seek cavern↕ and bees.
  • If no seeds are available, seek cavern↕ and bees
  • If there are no caverns or bees, suffer↕↕.

From this point on though, things become less clearly defined, and depend more and more on the motivations of the group. City builders may want to focus on getting their stone-industry up and running, which may have gotten a kickstart from the initial digging of a cave. A dedicated mining operation might treat the initial fort as a starting point for going down to the magma, require shafts to dump ore down and a minecart system to transport it up. A military fort close to enemy lines might want to prioritise defences.

In summary, up to this point most fortresses would follow a similar path, but at this point they diverge. The problem involves capturing the trajectory of that transformation in a way that allows you to not only quickly and easily encode scenarios like the ones I've been dreaming up into the fortress builders "plan", but does so in a general enough way to be able to grow with the game. It may be possible that the embark is a single wizard, and he casts 50-level slade tower in the middle of the map, or that in the future you could embark with vampires only, and not need food, shelter or beds.

So, at the moment the model we are working with for the fort generator is looking something like this:
  • A fortress is an settlement that may have aboveground structures and or belowground structures.
  • Dwarves typically live in the belowground structures.
  • Fortress construction happens in phases over time.
  • As a first effort, the primary conern of any dwarves is to find shelter and food
  • Subsequent actions taken to develop the fortress should be a product of the motivations of the inhabitants and the events that take place there↕↕↕

The first version of this model was and could only be made from my experiences designing a fortress, but at this stage is still sufficiently vague to not constrain the end result much. Essentially, a fortress has a reason for being built, there are stages to its construction, and events affect how it grows. Mention was made of above and below ground structures, but nothing has been said about the sizes of areas, the spacing, the choices of materials, the relative layout of rooms, or other important factors, such as how the fortress survives economically¶ and whether they have requirements on who can migrate there (no children on the front lines...). These are important questions, and while it's very important to consider them so they are able to fit into the final generator, they are outside the scope of an initial implementation.

Some additional random thoughts on this topic: The population of a city affects the speed at which it is constructed. Food sources have a "rate" attached to them, and once the rate of consumption approaches the rate of generation, a need to expand the food industry is created. For simplicty this is checked on a yearly basis to accomodate the average # of animals roaming the country side, the average plant growth in the area, average fish available, etc. Food industries expand horizontally at first, if motivations allow it, and then vertically to increase capacity.

So, now that a basic model is in place, and we have a feel for the lay of the land, it's time to consider...

The Minimum Viable Fortress Generator

If someone came up to me and said, "Hey dude, I have an automatic fortress generator for Dwarf Fortress", what is the absolute least I would expect, given the title was technically accurate? I would imagine it would be something that spits out QuickFort blueprints; that doesn't care about what the map looks like, but tells you how to build. I would expect it to be either configurable or randomisable, else it's just a single blueprint, and I would expect it to generate structures compatible with a finished fortress of some size... bonus points if I can specify a number of dwarves. Double bonus points if I can specify casts and have the housing be dynamically created in zones near their industries with dining areas for individual groups (on top of a central meeting hall).

If I were dreaming a bit bigger I'd like it to have knowledge of different kinds of abstractions, and give me high level controls for determining how they are generated, eg. for a farming area I'd like to control the generation by specifying a capacity for how much food it should generate, a control for the varity of food sources (varity and capacity interact like civs in world gen with world size), perhaps some kind of seed, and a "wealth" control to determine the value of the chosen materials.. then some geometry of farm area should be generated with floors and plots and assigned to whatever vegetables were available for selection.

If it had knowledge of these abstractions, and a way to control how they interact, then we are in business. There are degrees of abstractions, and they can be deepened over time, given you plan their structure and interactions correctly. I think you can catagorise the motivations in the early game loosely as, in approximate order of priority:
  • Shelter: Cave or Keep (initially)
  • Security: Doors, Gates, Traps,
  • Food: Forage, Hunt, Farm, Animals, Fish
  • Building Materials: Wood, Stone, Ice, Ceramics, Glass
  • Sleeping Areas: Dormitories, bedrooms
  • Industry: Crafts, something plentiful in the area
  • Medical Facilities: Hospital, Water, Supplies
  • Self-Actualisation: Temples, Libraries, Taverns, Guild Halls
  • Beautification: Engraving, Smoothing, Gold Floors, Mist Generators (necessitating plumbing), fort "scale' grows over time

I would expect a fortress generator to lay out structures to fulfill these needs, in a logically connected fashion. The kitchen and still must be close to the area the plants are stored, but also to the place where the prepared meals and alcohol is stored. Space must be left for future expansion, but supply lines need to be short. Structures exist within a fort; a meeting hall, an entrance, a sleeping area - and these structures contain substructures; seating areas, decorations and bedrooms. A properly designed hierarchy of rooms and rules for their connectivity will give rise to various configurations of fortressses. Making these rules dynamic in response to a set of key parameters relating to their connectivity and parameters should then give the control needed to generate fortresses of a varity of scales and shapes. If this can then be adapted to suit an external terrain, with a random geometry and geology, the road from the minimum generator to implementing the above model becomes clearer.

The lynchpin in this whole thing is going to be figuring out how to effectively translate motivations into structures. Ideally I'd want to use things similar to what's already in Dwarf Fortress; I don't know if groups as a whole can have a motivation yet, but perhaps it could be adapted from the structure of the personal motivations, or reflect the desired of the king through the competancies of his underlines. Facinating as sourcing the real motivations from the game can doubtless prove to be, I'd have to pick a few general abstraction to work around, so this thing can comfortably slide into an external system, that way it can continue to grow outwards.

PAUSE
There's a bit more to develop here, there's still something to be thought about the minimum fortress generators minimum rooms; and the question of what method would be used to connect things hasn't been answered. I'm inclined to think what it wants to be connected to is a property of a room, and it satisfies it by the shortest route possible... but that is tomorrow me's problem. This has been a fascinating two and a half hours, but it's 4.30am and any additional planning will have to wait for a fresher me. I find it easiest to develop ideas by talking to myself, but I also find it useful to have an audience  ;D



* a splinter group of dwarves that fear the underground, a goblin-elf love cult that worship magma and enslave dwarves to get to it... 'preference' can be a broad term here.

**I'm not quite prepared to consider the complexities of multilevel heavy aquifers at this point, but I imagine you'd end up with a lot of unhappy dwarves in wooden structures on the surface, or shacked up in the dirt.

*** In a truly integrated fortress generator this would require the fortress sending the food in increase their food stores, either by building more food industries, or increasing imports, which, depending on the length of time it goes on for, may affect the industries in their neighboring cities. When the war ends, the price of food could fall and a city collapses economically. 

↕ "Seek Cavern" should involve digging vertical shafts to a certain depth, increasing in number until some critical stage when all shafts are made deeper. This is repeated until a cave is found. Shaft density should increase with depth. This might be hard to write, depending how caves are generated. There should be some math that helps dig exploratory tunnels.

↕↕ At this point blood wine would have made an interesting addition.

↕↕↕ eg. an unsuccessful invation that does some damage could be interpreted as "need for security" increased by "violent encounter", which could lead to "wall", "trap" or "moat" for a military fort, but possibly "abandon area" for a small family that came to build a hut in the mountains.

¶ Not strictly a problem, but I think the best way to approach this is from a worldbuilding / roleplaying perspective.

Logged

teatime

  • Bay Watcher
    • View Profile
2 Auty 2 Forty
« Reply #1 on: June 26, 2020, 02:36:48 pm »

Moving this here from General Discussion
How is a Fortress Constructed?
Dwarves arrive at an area. They have a reason for going there that will determine the overall structure of the fortress/settlement, and is seen as a property of the embark.
During their time constructing the fortress, they have certain general needs that need to be fulfilled. These were taken to be:
  • Shelter: Cave or Keep (initially)
  • Security: Doors, Gates, Traps,
  • Food: Forage, Hunt, Farm, Animals, Fish
  • Building Materials: Wood, Stone, Ice, Ceramics, Glass
  • Sleeping Areas: Dormitories, bedrooms
  • Industry: Crafts, something plentiful in the area
  • Medical Facilities: Hospital, Water, Supplies
  • Self-Actualisation: Temples, Libraries, Taverns, Guild Halls
  • Beautification: Engraving, Smoothing, Gold Floors, Mist Generators (necessitating plumbing), fort "scale' grows over time
Although this lists ordering is roughly true as a priorities list for all fortresses, it only holds for the first iteration of the fortress; once all the needs are satisfied the Reason-For-Going should primarily influence the future evolution of the fortress. Ideally the Reason should consist of a small number of attributes that can collectively describe a large number of scenarios. Catagorically I think these can be described as a collection of needs, each consisting of a statement relating to what there was too much of, and what there was too little of. The outcomes of such needs are simple to define in terms of material needs, like MORE LEATHER, but become more nuanced around something like MORE EXCITEMENT, or MORE SECURITY. The latter could mean moving to a safe area, or moving to a safer area and fortifying the everloving fuck out of it. The former could mean colonising a volcano, or moving somewhere otherwise inhospitable.

I imagine scenarios generated this way could look something like MORE WOOD 200, which would aim to set up a colony producing 200 wood a year. Multiple needs would require prioritisation; weighing each need against how fulfilled it is at every phase of fortress construction, coupled with priority gives a way to navigate fortress construction over time.

So - the Reason is a prioritised list of needs that shapes the phased construction of a fortress. There are catagories of types of things to build to fulfill needs, and using the priorities from the Reason coupled with the instantaneous needs of the dwarves (and means they already have to fulfill them) the next phase of fortress construction can be planned. As a fortress generator, we are blessed, for we do not actually need to do the work or wait for it to complete, but over time we would like to include available materials into the equation. It seems the most extreme, granular version of this is a program that plays dwarf fortress; but while that would definitely get the result we want it is a bit overkill.

The list of available Needs for the Reason should be modeled on the above list of.. er.. other needs? Local Needs. The Reason contains the Global Needs, which are modeled after and shape the Local Needs. The Global Needs can contain abstract concepts though, and these need to be translated to Local Needs changing over time*.

I have no interest in writing direct mappings, as these would need to be updated whenever I wanted to add a property. Instead, each phase of fortress construction can be modeled as having a certain capacity for work, and the prioritised Needs used to direct the effort. The current Global Needs and Local Needs combine to form a list of priorities for the phase. Changing the granularity of the time scale considered would affect the kinds of fortresses being generated, as this would affect the construction capacity available in that time frame. At this point I imagine something like a fortress having a construction capacity of say, 300 actions, or 50 actions per dwarf over the considered time period; this is treated as a form of currency which is to be spent improving the fortress. It might be decided to spend some capacity on increasing the forts ability to generate food. In most cases dwarves will tend to try and spend as little capacity as is needed to fulfill the need, while planning for the future. It doesn't make sense to build a food area that could only feed 30 dwarves if you know you're aiming for at least 200. Either room should be left from growth, or it should be "known" by the generator that fortress construction is sometimes a two step affair, with a tiny fort created initially to house everyone while building the big fort**.

How is a Room/Area Constructed?

So, at the moment, fortress construction looks like this:
  • Arrive with a Reason
  • Evaluate fortress capacities to generate list of Local Needs, priorities according to Needs catagories at the top
  • Evaluate Global Needs to generate a list of Local Needs
  • Interact these two lists in an as of yet unknown way
  • Determine the construction capacity of the fortress from the population
  • Build items off priorities list.***

Key problems that remain are figuring out how to interact these lists, and how to actually generate the rooms.

It feels like how these lists interact should be somehow dictated from the Global Needs.
The king ordering you to do something affects your decisions differently to you just wanting to do it on your own. The fact that your fort does not need to produce food because it expects it by caravan can only come from the Global Needs (as in a delivery of food, not a trade). Needing to prioritise a certain industry for export can be due to a local abundance, but the location of fortress could also have been chosen to exploit that, in which case the Global Need of "MORE MARBLE STATUES" could have dictated the location in an area with much marble, but also preferentially drives the fortress to have a marble industry that is larger that it might otherwise have been, earlier than other forts would. I can imagine the Reason not only a collection of Global Needs, but also containing certain flags that would constrain the development of the fortress somehow - some kind of limited selection of overarching themes to add flavour to the process.

As for actually generating the rooms... I think there is an exercise in graph theory waiting for me in the future to be able to plan it out properly, but in the general sense it will be generated from a hierarchy.
As an example, the fortress needs food. Currently, there are no facilities, and so the food priority is high. On this map, over the course of a year there is on average 100 meat available from hunting↕. There is no soil. There is water. There are 0.5 caravans a year from neighboring settlements. The need for Food requires some way to generate and store food. The Food Storage Area is a substructure of the Food Area↕↕. There are several factors influencing the size of the Food Storage Area; including the frequency of the food source, the number of dwarves in the fortress and the required stock to store. A military fortress might mandate a years worth of food be kept at all times, in case of a seige, where a peaceful villiage might just need stores to last the winter. The exact math for transforming "food generating capacity" and "storage needs" into a number of squares of stockpile feels like something that will be determined by fiddling around, but once that value is generated, it needs to be transformed into an actual area.

As a first effort, rectangles of a fixed ratio connected by straight corridors; at a later stage, a configureable architecture. The Reason and Global Needs can kind of arise naturally from the game at the moment - and caters for some specific contrived scenarios to be included - but the architecture should have a guiding hand in it. I forsee it as something like the world generator, exposing a lot of parameters to be tweaked and customised per civilisation, but (on some level) relying on fixed configurations as starting points for generating the complexity of a specific world. Things like:
  • preferred shape for a room (square? rectangular? round? prototype shapes defined by points and concavities?)
  • perferred type of material (initially single material, eventually linked with certain features, eg stone bases with wooden houses
  • preferred location of the main fortress (above ground/below ground; biome peference )
  • roof-height (as a function of fortress maturity, affecte by type of area and how many use it)
  • willingness to abide an odd-shaped wall to fit a room into a rocky outcropping vs. willingness to mine it out and build something outside to make the inside more shapely
  • overall fortress shape (high and narrow: an underground fort centered around a shaft, or a wizards tower; or flat: a series of houses, or single z-level underground fort)
  • general spaciousness (a number relating average corridor length between areas to expected fortress population)
These properties should be able to provide the flavour of how to build the fortress↕↕↕ once the decisions have been made as to what size each room should be.... but I get ahead of myself. We've only just decided how big the food area is going to be in this example. Depth first is fun but sometimes distracting and laborious way to explore a topic.

In our food area, we have now determined the size of stockpile that is needed. Based on the map we choose to initially hunt for food, but given there is water we can make a farm area somewhere, this will just require too many actions to be a first iteration of our forts food source... but nevertheless in the future, this farm will be a part of our food area.
We should thus look at the embarkation Reason to determine what the forts projected size is to get a rough estimate of the overall floor area a finished food area would need. There's going to be a lot of heuristics and tinkering here...or maybe just assigning a max size to each thing and summing them.. but based on the projected food needs of what the dwarves consider their "finished fortress", a number of blocks is chosen that will represent the area where food is made.
This Final Food Area will contain a Final Food Storage Area, of which we are making a small piece right now¶. We can thus say something like "In this phase, we saw we will need, in the final fortress, a food area of about 500 blocks. 200 blocks of this will be required for food storage. Of those 200 blocks, we need to construct 50 to fulfill our projected food storage needs until the next phase, which leaves 200 actions for subsequent projects this phase".

Likewise, areas can be partitioned into little pieces for farms, kitchens, stills and all the things you would expect to find in an area named the Food Area. There is still something to be said for how these areas connect externally, and internally.
This partially leans back to the architecture config idea, since some may have a preference for rooms connected by corridors, where others mights prefer large structures with internal walls... but overall, there needs to be a way to decide where things lay relative to each other and how the connect them, beyond the concerns of architecture. Functional concerns - the Mad Demon King didn't get to be the Mad Demon King by ordering his food production be placed on the magma level, and his fortress be built on the surface¶¶. All races are fundamentally lazy and won't do more than is needed to accomplish a task.. even Beautification requires excess capacity.

There are fundamental relationships between areas and industries. Food areas would want to be close to the food source. Dining areas need to be close to the food store or, if they are beyond a certain distance, have a local stockpile of food, drink and mugs. On some level, every room and area has other rooms and areas they want to be close to, and perhaps others they don't want to be close to (nobody likes walking past the corpse pit).
Placing a room near something it wants to be near makes that room happy, and a fortress full of happy rooms is a happy fortress. With some rooms that need to be central to everything, it may not be possible to make all other rooms happy; but there are degrees of internal conflict that a fortress can tolerate, provided it is trajecting in a direction to make the fortress as a whole happier. The happiness of a room is a function of the status of its relationship with all other rooms it has relationships with, and new constructions use the current and projected future happiness of all rooms in the forts to guide their placement.

This would lead to very predictable results in the absence of a world and geology to consider; as the current algorithm would tend to find the same optima each time. Even with the architecture changing path lengths, room shapes and sizes, and preferred verticality, it would still find fundamentally similar solutions. On the one hand, merely introducing a map will provide a lot, at least near the surface and around the caves, providing hard constraints on where you can build will squeeze and push the fort into different shapes.. but I feel there is another element needed.

As a fortress generator, we are doubly-blessed, for we can see the entire map at once. In the future, requiring the dwarves to dig exploratory tunnels to determine where they can build could add a lot of character to a fort, but for now having them know it as if the voice of God spoke to them, or they had a special Dwarven rock-sensing sense will suffice. The geology of a world isn't generated as a random individual squares of different materials¶¶¶, there are areas that consist of mostly the same material, and there are veins of ore. I know I like nestling my functional areas inside a certain type of stone, and will even preferentially lengthen a piece of corridor so I can cross the border into a new type of stone for homogeneity in the new area. Sometimes, I mine out a pocket of orthoclase for a big, almost elliptical room. This can maybe be encapsulated as a sense of aesthetics in the architecture config, or as a trait in the Reason - willingness to delay work for aesthetic purposes. Small villiage, sure. Outpost on the front lines, no.

Using the world geology will also help to make things look better, but this still doesn't solve the problem of the basic fort layout. On the one hand, I want to avoid hard coding my ideas of how a fort should look into this. I mean, sure, there is absolutely no way to get away from these fortresses bearing my mark, but I don't want to fundamentally limit what kinds of things can come out of this without reason... that being said, it feels like I might have to have some kind of set of basic values for different fortress connectivities that make sense to avoid every fortress (in the absence of a world) looking the same for a given number of dwarves with the same industry, etc. Randomisation feels like too blunt a tool, and a seed value for spicing up otherwise deterministic choices... well, maybe, but I feel there is a layer of abstraction I'm missing here that would be able to do what I want in a more controlled way. I suspect that reading up on graph theory, and actually coding it for that matter, would be most inspiring.

...for now, though, the above is a satisfactory model to generate a variety of fortresses. So, areas and rooms are generated by:
  • Select a type of construction from the priorities list.
  • Determine which components need to be created or upgraded
  • Determine if the current area has capacity, else designate a new maximally happy area (based on current and future for projections)▲
  • In the area, place the room for maximum happiness. Populate the room according to the architecture config, available materials and fort maturity
  • Evaluate fort
The last item on that list refers to any excess actions left over after optimally distributing the points among the prioritised Needs, and can be used on small beautification actions, or upgrading infrastructure - widening a corridor, smoothing a wall, looking if there is maybe a corridor that could be built to make all rooms happier at once without compromising fortress security, or violating the architecture config▲▲. There may also be value in doing half a thing with the left over points; nothing says "living fortress" like a half finished construction project.... and can you imagine how cool it would be if you wander onto the map and there's a stream of dwarves carrying stones to build something?


A Mental Test Run

Now that the tools and abstractions governing the generation process has been loosely defined it should be possible to see what kinds of scenarios we can generate using them. This generator can go outside the realm of things that can currently happen in Dwarf Fortress, but just to motivate its construction. Running through an actual scenario should help point out any cracks in the current system.

I can imagine a goblin fortress built on slave labour. The fortress was constructed to make weapons and armor for soldiers in other fortresses - this Reason for this fortress might look something like MORE ARMOR 100, MORE SWORDS 100, to bias their industry and indicate they need to generate exports. The embark information might indicate 100 goblins and 20 trolls. The style guide for this type of fortress might say that this type of socity typically has 5% upper class, 15% middle management (slavedrivers) and 80% slaves, and these groups do not mix when eating or sleeping. Furthermore, sleeping areas are separated by species. The slave cast sleeps in dormitories. There is a subsection on troll sleeping quarters to generate something appropriate for them. Trolls cannot be nobles.

As this group arrives in the new area, they first build shelter. The architecture config for this society highly prioritises shelter for the upperclass / nobles, and requires one set of quarters that is more lavish that all others. If the slave force is large enough, the main throne room is constructed first. Otherwise, a temporary house in the field must be built to house the nobles until a fortress interior exists. Priority is generally given to the comfort of the nobles. Secondarily, some way of acquiring food is needed. The Reason for this fort may include that this fort subsists on caravans of food stolen by raiding parties - I'm not sure what goblins and trolls eat, but the thought of them farming seems slightly silly... but at this point simultaneous priority is given to a massive smithing area and housing for the middle management. Later there will be housing for the slaves. Terrible, cramped housing, physically distant from the nobles... but close enough to protect them if something attacks.

The size of the smithing area is based on the amount of laborors present, and the desired exports of weapons and armor. This translates into a size of area, which consists of stockpiles, workshops, and paths. The workshops need wood and or magma, so if depending on whether those things exist on the map those 'industries' might spawn in a limited fashion....or on the other hand, goblins may be able to work metal by magic. It would certainly make planing this scenario easier. This generator, not a human like me, would have reaslied it was needed to spawn the logging and charcoal generation industry before the smiths one.

I'm speaking in terms of goblins and slaves here just to stretch my brain away from dwarves for a moment, but everything I'm saying should translate directly back to dwarves. This world now has a freestanding structure somewhere that was used to house nobles; some kind of structure to house the middle management, and it is now getting some kind of shitty dirt hole for the slaves, just connected to the surface. There must be a reason a colony was placed here for the purpose of making weapons and armor, I'm going to choose to believe because it is a densely forested area that has the wood required to stoke the furnaces. As part of the embark information it should be specified that this fotress intends to import weapons and armor that doesnt fit their forces, like dwarf/elf and human armor, and melt it down to create new weapons and armor for the vile forces of darkness. This simplifies things but not requiring me to dream up a goblin mine, and, for the moment, leaves me reasonably happy that the above abstractions can encapsulate everything from the vanilla ideas they were generated from to some outlandish scenarios of the future.

An even better test, however, would be to play dwarf fortress while pretending I am the generator. That's kinda what got me into this position in the first place, when I had to restart a fort because of some combination of gamebreaking bug and personal stupidity, and I found a young version of the above running in the back of my head.

Yet the best test would be to start writing this and encountering actual problems. I'm a big fan of building castles in the air (or perhaps more appropriately, a fortress in the sky), but as TS Elliot rightly said, "betwen the thought at the action, there falls the shadow". There are definitely still things that need to be planned, such as how to manage what could reasonably be imported vs what should be made locally (clothes, for example?). Whittling down all the fluff to a core idea that can be developed is it's own kind of feat, but a neccesary first step to what could easily try and become an automatic dwarf fortress player if I'm not careful.

teatime is taken by a fey mood!

teatime claims an IDE.

I must have enums!
I must have a hierarchical class structure!
I must have definitions for object interactions!

teatime has begun a mysterious construction.

teatime works furiously!

▲▲▲



* Integrating Local Needs over time gives Global Needs... the calculus of fortress construction? Maybe we can derive some way of interacting these things ::)

** An abandoned little fortress next-to-and-accidentally-linked-with the main fort would make for a neat little feature in adventure mode. 

*** This is an interesting optimisation problem, since sometimes it's better to do eg. all the food at once, and other times you're better off adding just a little capacity here and there. A military fort might need a little food generating capacity to keep it running when caravans can't get through, but would much rather have a chunk of wall constructed after the first phase. In this scenario we are not dreaming we are playing dwarf fortress, we are dreaming are are military dwarves setting up an advance outpost.

↕ I just discovered you can hunt things to extinction, so perhaps hunting should always be considered a transitionary food source.

↕↕ Note that a different incarnation of Food Storage Area is also a substructure of advanced Meeting Areas and Dining Areas.

↕↕↕ Which opens up GREAT possibilities for having fortresses being taken over and the new occupants expanding it using their sense of architecture....

¶ In advanced fortresses this area may undergo internal changes where the stockpiles are arranged better and specified on a more granular level.

¶¶ And yet, one might argue that is exactly how he became the Mad Demon King. Architecture config: "Hates citizens"; doesn't minimise path length for optimal industry.

¶¶¶ Side note, a civilisation having a geologist could enable them to make mining colonies that mine specific materials. Libraries teach people cool skills, it would be nice if they featured here somewhere - like a knowledge of hydraulics enabling certain advanced Dwarven Science to appear in its colonies.

▲ Ah, no, I think this is what was missing from my thoughts on connectivity. The initial plan might always be the same, because there are only so many way a small number of people will choose to live together, or set up a fixed size fort optimally. The food, dining and sleeping areas are linked in some way.... but as the fortress grows, as needs change, and requirements change, the planned areas and their locations may be insufficient, leading to new and interesting structures. No need to mess about with complex math to generate interesting structures, when events happening over time can do a lot of heavy lifting for you.

▲▲ Defining acceptable configurations of corridors numerically brings us back to graph theory.

▲▲▲ Alternatively, some years earlier:
teatime went stark raving mad!
teatime is running around babbling!
Logged

teatime

  • Bay Watcher
    • View Profile
AutoFort: A New Hope
« Reply #2 on: June 27, 2020, 05:37:17 pm »

So, I've not been idle - I opted to go for The Best Plan and start writing some code. Most of it has been abstracting away things I don't want to think about, but want in the final generator; like feeling your way through a foamy bath for the water. The easiest place to start is to create the capabilities of generating the final most ultimate fortress - once I can do that and have a mechanism for getting there incrementally, some of the wilder dreams in the first two posts can be realised.

AutoFort

I've been coding in a professional environment in Scala for about 5 years now, so I'm writing it in that. On the one hand this is a staggeringly horrible choice and no-one and nothing reated to dwarf fortress integrates that way, so it closes a lot of doors; but on the other hand there is value in thinking about this problem using immutable data structures and a language geared towards turning data crunching problems into natural language statements... so, that's where I am. More accurately, this is where I am:

https://github.com/treetime/AutoFort

Ach, treetime, named like an elf I know, but teatime was taken. As the vague idea from the first post solidified into the rough plan of the second post, so the third post aims to bring clarity to the problem. Thanks to my boatload of abstractions I can almost speak this generator as a sentence, and will attempt to do so, to make sense of things:

First off, let's try...
What is a Fortress?


A fortress is a thing that is generated from information relating to the embark, information about the world that generation is taking place in, how our model of a fortress is looking and what the StyleGuide is telling us to do. I'm not yet at the point of actually generating things, the problem is still being solved in principle; so for now Embark has no effect, and I completely ignore the GridMap...but the FortressModel tells us how to turn needs into buildings, and the StyleGuide tells us how those buildings should look. At the moment the overall model for types of things that could appear in this fortress looks like this:


The Fortress Model

I've added a few examples to each catagory to flesh out in my mind what they might contain (some of those are more feasible than others), and the idea is to have each of those classes controlling the logic of how that type of room is generated from a set of needs. At the moment the only need I am catering for is population, so by the time this gets to printing out fortresses I should be able to scale them by size. For example, you would tell SleepingArea you need rooms for 50 people, and it would, based on your StyleGuide decide on how they should look, how many should be rooms, what should be in the rooms, etc.

The StyleGuide is another key element to this, because this is not meant to generate functionally perfect fortresses; this must make beautiful fortresses - so styling it is part of the minimum generator. The StyleGuide is currently taking this form:


The Architechture for a civilization is specified as having PreferedShapes and PreferedGeometries. For now it's just one for the whole civilisation, but there could be ways to integrate it more finer grained (like having it depend on the Architect who built it...). PreferedShapes define the shape a room will be made in, and is defined as a sequence of points. Giving a scale factor then generates the GridBlocks needed for this room, which can ultimately be placed on the map.

This is still just a shaped room though, to actually fill it in in any meaningful way ther has be a logic to how a room is filled... and that is where I am now. Each building in the FortressModel will define they furniture and placement requirements as a function of population, and well as define the strategy for how it should be arranged. This is not an easy problem, I've been staring at the screen for a while, but, as previously determined, I think out loud, so it's time to take a moment to survey the land going forward.

Arranging Furniture

What I know at the moment is that a room is a Set[GridBlock], which each block defining it's own x and y position. This is encapsulated as an AreaDefinition, which gives us access to two aspects of the area, the perimeter and center. A center block is any block which touches 8 blocks around it; the perimeter consists of all other blocks.
Certain types of futurniture want to be placed on the perimeter, and other kinds prefer to be in the center; and it varies from room to room, and some rooms have both. I like having a single table and chair workdesk in my library, but also a little 4-table area for people to brainstorm in a small group. In the throne room there are many chairs, but not a great many tables, and I need to able to specify one throne at the focal point of the room.

All this tells me that each room needs to let me know the following: I need to know what furniture it wants, and how it likes arranging that furniture. Some of that information must come from the Style Guide, because that's what it's there for, but all dining rooms have some kind of group of tables and chairs... they're just grouped and spaced a bit differently. If these controls are too specific it will be a pain in the ass to program, and I want to avoid that at all costs; but make it too general and hands off and you won't be able to use this tool to execute a vision. It needs to be powerful, but natural and easy to use, like a poop-a-scoop; extending your natural abilities with minimal interference.

Tables and chairs are often grouped. When they are they are either come as a single row, or a double row. There is normally a passageway behind the thrones*. Dining room groups within a room are typically equal, I tend to do at most 2 different sized groups of tables and chairs, depending on the room shape... but then by what metric do you place the other things in the room? I'm thinking if the center is broken up into a grid of n x n squares, for all the n=sidelength of thing to be placed, and start out with a Best Effort trying to both fill and center according to the personality traits of Spaciousness and Offcenteredness... I'll get somewhere. On the other hand, I don't want to look for a solution, there must be exactly one solution, given the parameters fed to the system, so perhaps this is a good oppertunity to milk some seed value for some randomness. It feels like using a seed value represents the edge of the abstraction, where no rules exist to properly vary the system, so I just kinda wave my hand and go blaaaaaggggghhhhh; so if possible I'd prefer something neater and more predictable.

For me to confgure a room, it needs to be able to rell me it's furniture requirements in response to a population; it needs to know itself what kinds of functional groups those furniture should form (only the library can tell you what the library wants to look like). It needs to specify the positionings of those functional groups in terms of the perimeter, and the center, and in some way that can translate to the definition of the room, that is a Set[GridBlock]. I think the kinds of position specifications I could use could perhaps mean I don't have to calculate the amount of furniture right away. It could specify to fill the middle third of the room with tables and chairs in the dining arrangement, as densely as possible, in groups of no longer than 5, spaced as evenly from one side to the other as possible, vs spaced as symmetrically around the middle axis as possible. The room must tell me something about the direction that it prefers I arrange things in, since tables and chairs can go 4 ways** That prefererence can be expressed either as a preference in terms of the properties of the room shape, eg. perpendicular/parrallel to the nearest wall, or it can be expressed in terms of a weighted set of probabilities (20% chance to be along the one axis of the room, 80% on the other; respecting the rooms rotation, randomness from fixed seed).

So - now a space tells us what it needs in a graduated fashion, it has preferences on how to arrange those things which can be captured in config*** . This definition, being relative to the room size, should always fit given I put sane boundaries on the config. So, for now the room does not do that much arranging itself, but rather relies on config to tell it more or less what to expect. I can envision this system producing a throne room, and producing a dining room. Perhaps some of the dining room preferences, like the "big grid" used to place the tables, can be slightly wiggled to liven things up.. but it still feels a little static.

At the moment, I can generate a rooms AreaConfig from a population number. A RoomConfig / ComplexConfig will be used to generate the actual physical spaces, based on the population, some base size, and what the Room tells us it will need as contents. There should be a dedicated set of classes that specify ways of arranging tables, with some parameters to control it. Ah, yes, ok. Furniture arrangement will be a key factor in giving a fortress character. Civilisations have a preference for how many people eat together, that can come from their personality↕. This translates to whether they prefer tables facing each other or not, and how grouped tables are... and how filled those groups are.. and affects Workshop spacing, etc. I want to cater for weird interlocking L shaped table groups, room-long tables, tables arranged in a square with cutout sides, tables packed all along the wall, concentric sqiare tables, a round arrangement of tables... I think I can envision a structure that contains all those possibilities, but to do this I need to unlock a far greater slice of infinity than can be tamed with a few simple metrics; so it will require configuring... and at that stage I am going to use you. In the best case scenario once this thing is setup it should have some kind of live navigatable output so you can see how the fort morphs in real time in response to parameter changes, but more realistically it will generate images/quickfort blueprints on command. My gifts lie in unlocking the potential, but I'll need people to help harnass it... though I'm pretty sure a lot of people here have also generated a world, embarked, planned out a massive fort, and then saved and quit - so finding people with worldbuilding tendencies to play with a fortress generator should not be hard. The downside to generated content like that is that you lose some of the control you have with a model to finetune certain things. Hmmm.. I guess I'll start out with just blocks of tables and see where it goes.

While working on this I have pictures in my head of fortresses that I want to be able to generate, and I'm working towards being able to make them. One of them looks like this:
The map is plateau like region, still uneven, but straight enough for a town, and with sheer edges down the sides. The town itself consists of kidney bean shaped aboveground buildings, built on the side of a peak. The buildings are on dark stone foundations that stick out up to 1 z-levels high to try even out the town, with wooden paths on pilliars between some of the buildings where the terrain is uneven. Occasional staircases lead down to ground level. There are shear faces next to certain bits of the path where the mountain was channeled away to make space for it. The houses also have dark stone foundations, where they were built on soil, and the foundations are hollow. In the foundation is a staircase upwards into the house, and a stockpile of food and alcohol, barrels, and a chest with some jugs and cups. Several bags of plants are bunched up in the corner. The house itself has a dining room and a bedroom. The dining room leads to the cellar in the foundations. The dining room has two tables at the side flanking a bag. The houses walls are made of a white stone, it has green glass windows. Although all the buildings are kidney bean shaped, they are of various sizes and orientations, snaking along the pathway that leads through the center of town. With the internal layout of each being similar, but not same, and still making sense given it's orientation. Off to the side, a large hole has been dug into the side of the peak, and a wide passageway spirals gradually down into the mines↕↕. Nearby several neat 7x1 farm rows exist surrounded by a fence wooden fortification and a gate door. The top of the mountain peak is carved into the shape of an anvil (dream big, 7 z-levels, 7x15).

Another, is of a maze. A maze is a security structure. A maze is a structure that partitions a pathway. It can be a specified number of Z-levels tall, and a specified number of blocks wide and long. There is a way to control the complexity of the generated passageways, and length of the successful passage. The maze consists of stairs, ramps and passageway. There is a control for the density and intensity of traps. There is a control for the types of creatures found in the maze, and by default, the maze has a bypass path with a gate. Mazes can be 2D problems that advance in z-levels, or full multi-z level 3D twisty passageways.

What's Next?

Furniture arrangement is turning out to be a deep well of complexity that will be hard to do realistically. I have a vague incling that the solution will lie with finding the locus of points describing the middle of the area, and using that to partition and fill the center, and using a weighted system to choose arrangements in individual rooms... but keeping them constant across functional areas. There's just a bit too much too bite off and actually think all at once.. so I think using a simple grid for the center of the room is good for now. Space has been left for that to expand, and the function is so positioned that I can add functionality just there and everything will just work. There are definitely shorter roads to getting something that generates a fortress, but the problem being solved here ins't just drawing any old thing, so, to get somewhere special we are taking the long way around. Sometimes even the shortest road is pretty long. This still seems completely doable though.

Scala's way of working, intersecting functional programming and OOP lends itself to solving some of these problems with great ease, but some feel a bit clunky and unnatural. On some level I'd really want to place furniture by pointing them to the correct memory address of the map, and there's a small part of me that's consudering how a C-rewrite would look, but that is in the distant future.

Unrelated: I was digging around a fully revealed map, to try get a feel for how aquafers are positioned, and how the stone layers generally look, when I came across this thing (spoilers):
Spoiler (click to show/hide)

I am choosing to take that as Armok's Blessing on my quest.



* I want to consign decisions about things like this to Personality traits, which give general guidance to the fortress; things like strict cavedweller vs strict surface dweller; spaciousness vs crampedness; and opulance vs frugality. This is an infant-version of what should eventually become a RaceConfig / CivConfig

** Any strong opinions on what looks better, left to right or top to bottom? I've seen some people to do one kind religiously.

*** though this is "boring" config that needs to be tweaked; not exciting config that has one slider that changes the whole result in a massive way

↕ Personal Space: Italian to Finnish

↕↕ I would really dig to be able to generate running minecart systems.

Logged

teatime

  • Bay Watcher
    • View Profile
Space Invaders
« Reply #3 on: June 27, 2020, 06:11:42 pm »

Durr, room areas are a bit simpler than I thought. You start by taking away the largest rectangle you can, and then repeat the procedure until the room is used up. That then gives you a profile of that room, eg: 8x8  -- 1 ; 2x2 -- 4 ; 1x1 -- 12 could be an ellipitical room; and it works for rotated rooms too, and super weird shapes, since it priorities large spaces. You could have a room with thin arms leading to medium rooms, and the correct sized space will be chosen based on the needs of the objects to be placed, and you know what you have to work with. This excludes some types of irregular arrangements.. but I think that's ok, we have wiggle room inside the boxes.
Logged

Starver

  • Bay Watcher
    • View Profile
Re: AutoFort
« Reply #4 on: June 27, 2020, 06:16:54 pm »

Well, I still want to PTW. I'll do actual reading of new stuff later when I can wade through it and make sure I'm not missing non-obvious new bits.

(I think you, as the thread-starter, had Thread-Moving controls on your first post, BTW, but you've done it this way.)
Logged

teatime

  • Bay Watcher
    • View Profile
Re: AutoFort
« Reply #5 on: June 27, 2020, 06:48:42 pm »

Ah, I had the power, but not the knowledge of how to wield it. Classic. Well, the deed is done. PTW is Posting To Watch?

That last post was a lot of waffling trying to figure out furniture, but I have a plan now with describing a room as a set of rectangles. If you repeat the procedure with a smaller biggest rectangle each time you get a set of possible room configurations described as (useful) rectangular areas, so you can actually plan how to fill them. Whoo!
Logged

CarpFace

  • Escaped Lunatic
    • View Profile
Re: AutoFort
« Reply #6 on: June 29, 2020, 07:34:12 am »

I'm looking forward to seeing what comes of this... ideally, at some point you will need to integrate this with df, but even something like a plugin/script for quickfort would be cool.
Logged

teatime

  • Bay Watcher
    • View Profile
Captains Log: StarDate 40139.2
« Reply #7 on: July 01, 2020, 04:43:57 am »

Those are some cool ideas, but a bag of ideas is worth a bag. I don't want excuses, I want pictures of Spider Man!

Space Invaders

Part 1: Space

The Big Problem Preventing Us From Moving Forward was placing furniture. I needed to know what constitutes a room, and characterise it into certain recognisable features.


A room can be thought of as consisting of two areas: The dark grey is the perimeter, and the white is the center. The room is then broken up into areas to be filled by repeatedly removing the largest rectangle possible from it until the shape is used up. This is shown in the image on the left:


A species with a low tolerance for things that arent rotationally symmetrical might opt for the right side interpretation of the room though.
The perimeter also consists of recognisable features that can be extracted:

         

The dark grey blocks are the perimeter.
The orange blocks are detachable, because they can be removed without breaking connectivity.
The lime green block is an internal corner, because it has 7 neighbors in the shape.
The blue blocks are external corners, because they have two non-detachable neighbors in the perimeter.
The rest of the blocks are broken up into maximally large rectangular areas.

We now have a description of the room as a set of rectangular areas and key blocks, with hints of additional information we can use with respect to their orientation and connectivity. The following should both be seen as valid interpretations of the room by races with different ideas about what constitutes symmetry and its importance:



We still need to specify the contents of the room somehow though, so now we move from the lush green fields of actual imagary to the musty grey corner of verbal imagary for...

Part 2: Invaders

The contents of a room is specified as a function of the rectangular area it has to fill. A ╥╤ must know different ways to fill up a rectangle. Lines, Clusters, a Ring around the perimeter; and this must either be specified per room, or expressed as a preference for the overall fortress.
The actual values I want to specify in terms of a minimum and a maximum. I tend to think of a 7 dwarf fort vs a 200 dwarf fort for min and max values.
The items need to be prioritised, so it's clear which should be placed first.

I need to be able to describe the space filling function of a dining room as follows:

  • A dining room has a minimum area of 12 blocks (3 x 4) for a 7 dwarf fort, and grows to a max of 800 (40 x 20) for a 200 dwarf fort (not linearly I think)
  • A dining room contains ╥╤ in the center, up to a fill of (min = 1, max = 0.8 ) ; priority 1
  • A dining room contains alcohol stockpile in the center, up to a fill of (0, 0.1) ; priority 2
  • A dining room contains food stockpile in the center, up to a fill of (0, 0.05) ; priority 3
  • A dining room contains goblets stockpile in the center, up to a fill of (0, 0.05) ; priority 3
  • A dining room has (0, 16) statues in the perimeter, favouring internal corners starting at population 50; priority 1

The list is sorted by area, by priority, and then by size. For each area, eg. center or perimeter, the highest priority largest items specification is applied to all rectangular subareas, and it is placed according to it's associated placement strategy. This could be "fill grid centered", "tile starting at corner", etc. The PlacementStrategy aims to place the correct amount to satisfy the specifications given the properties of the fortress. The PlacementStrategy is the bit that is aware of the relative orientation and rankings of the areas; and can be told to fill only the largest rectangle with something, but fill all subareas with something else.

 Once all specifications have tried to satisfy themselves, the room exists, and we can start thinking about how to connect them together. I had a vague notion about room happiness being a function of which other rooms a room is friends with, how good friends they are and how spatially close to each other they are. This allows for some juicy control by giving the room placer a favourite room (eg. it just loves the stone industry, because this is a mining colony. The happiness of the stone industry is the primary guiding factor in our fortress)...

Although this sounds like someone talking to themself, and it looks like a coding project, this is, in fact, a magic trick... for you see, although I have written a ton of ideas down, and although I have written a sizable chunk of code.... I have yet to actually compile it. I am steaming forth with the fearless confidence of the ignorant, fully believing that at some point, with a minimum of fidgeting this will just magically work. I would not be so ballsy if I had to do this is a different language, and that's why this is happening in Scala.

I believe we are not far off from drawing our first rectangle.
Logged

Momiro

  • Escaped Lunatic
    • View Profile
Re: AutoFort
« Reply #8 on: July 02, 2020, 10:42:15 pm »

I love this concept!
It gets me thinking, maybe this is for a different mod, but the logic you use in the design of this utility makes a lot of sense when trying to envision a roadmap of what to do next when playing.
It would be interesting to see a mod that collects the 'goals' from the user like your script does, and then provides the user with suggestions on how to proceed to achieve those goals. Seasoned veterans and purists of the game probably wouldn't want to use it, but for those that have a hard time wrapping their heads around some of the mechanics or who, like you mentioned, might want to create a really whacky scenario, but don't have the focus to stay on task would really enjoy it as a tool.

I'm excited to see what comes of this project, though!
Logged

teatime

  • Bay Watcher
    • View Profile
Re: AutoFort
« Reply #9 on: July 03, 2020, 03:22:24 am »

Thanks Momiro! One of the stops on the way to completion will be having this program read the terrain, analyse it to extract features, and then designing the fort. That fort design must then be able to be put into the game somehow. My first thought was that there must exist dfhack commands to replace walls floor and items at various locations, so if my program could output those commands... then you could ask it to design you a 200-dwarf dining area centered on (42, 70, 112), without too much effort, and use this as a kind or robot butler to help build things.

Now that I've worked with it a bit more I'm getting a better picture of what would be configurable, and what would be fixed. Everything about the shape of a room can be captured in config, and rooms can be defined in plaintext as a preferred shape and a priotised list of items with config for the strategies for their placements. So, while I'm just implementing one room at the moment, and have these fixed ideas about fortress construction, I could expose sufficient parameters that someone could define a torture chamber, a music room, or whatever, in their own style, minimally needing to involve my ideas.



If someone can answer these questions it would be most useful:

  • Can DFHack read the terrain somehow, and give me the map as a csv or something?
  • Does DFHack have a command for altaring the wall, floor or item tile at a given x/y/z?
Logged

CarpFace

  • Escaped Lunatic
    • View Profile
Re: AutoFort
« Reply #10 on: July 08, 2020, 05:43:39 am »

For 2., I suggest having a look at https://docs.dfhack.org/en/stable/docs/Plugins.html#map-modification, and specifically the changeitem command. If that's not exactly what you want, scan the docs or ask in a the appropriate forum (i.e. fo modders/dfhack users) for advice.

I don't know about 1., but it feels like it should exist.
Logged

Starver

  • Bay Watcher
    • View Profile
Re: AutoFort
« Reply #11 on: July 08, 2020, 07:56:02 am »

Since the original request, I've been meaning to try to find my hacked-together stuff I made for converting some elements of a landscape into a POV-Ray rendering, in a project that I never finished. I tried a number of 'rip and convert' methods, some better than others (for my slightly different needs). I can't even remember which approach I used to get to the point I later mothballed it at, for different reasons of 'temporary' abandonment, but there will be a way. Though the one in which I took exported level images and 'parsed' them into features is probably worse for you than it was for me, given your likely need to be done 'in-plugin' and not suffer from tile-alike visual ambiguity.

I'm sure I also got a Lua thing together (learning on the run, and I'm not sure I used Lua much since, I'd need to refresh myself) to poll each {x,y,z} and get details (in my case, only properties useful for visuals).

So it's surely possible for your surveying requirements, and if I do discover the old USB stick or ripped-out HDD that contains that little bunch of experiments, I'll try to dig out the bits I think you'd benefit from. But it might be quicker just to try these things youself rather than rely on that. I don't think I did any particularly extraordinary fiddling[1] that various other plugins (e.g. 'floodfill' functionalities of various kinds) don't already employ in various ways.

I don't have access to it at the moment, but the "Reveal/Unreveal" mechanism includes, IIRC, a 'pathable-to' restriction option that must interrogate the nature of each cell and its {x,y,z}{±1} neighbours to establish inclusion/exclusion limits. The core interogation must demonstrate what you need to use (I don't think I knew/thought of that at the time, though; I probably hunted down other, drier, reference material in pursuit of my own goal).



[1] Except for using Perl to externally parse the level-export images, 'OCR' them and reconstruct things according to relation with neighbouring guesses, but I think that initial approach isn't how I left it and wouldn't be ideal for you anyway.
Logged

Nopenope

  • Bay Watcher
    • View Profile
Re: AutoFort
« Reply #12 on: July 08, 2020, 08:42:20 am »

You may want to take a look at https://github.com/BenLubar/df-ai
Logged

Su

  • Bay Watcher
    • View Profile
    • Angel Island Zone
Re: AutoFort
« Reply #13 on: July 09, 2020, 09:20:59 pm »

PTW. this is fascinating.
Logged

teatime

  • Bay Watcher
    • View Profile
nTagonal!
« Reply #14 on: July 12, 2020, 06:22:43 am »

Behold, what I do!

We can see in the above picture how the room has been broken up once generated:
Perimeter blocks are plusses, center blocks are the rectangular areas' size-rank.
In the perimeter the grey blocks are detechable, the teal ones are internal corners, and the red ones are external corners.
The center has been broken up into maximally sized rectangular areas, favouring horizontal areas, in the case of a tie.

These all represent spaces that can be configured in when defining a room. One might define a dining room as having all rectangles larger than 6 squares that isnt the smallest square packed tables and chairs, having the smallest area be a food stockpile and all internal corners goblet stockpiles. I'm still fiddling with the furniture placement, was doing dining room arrangement until I got stuck trying to draw arbitrary polygons. It's been a bit of a struggle. I could easily generate a rectangular room, but I want to generate n-tagonal rooms of any scale, and figuring out if points are inside a polygon took embarresingly long, despite being conceptually simple, "a point is inside a polygon if you extend it in a certain direction and it intersects the polygon once".
I was trying to just wing it, but it took sitting and drawing it out, and a very ugly manual decision tree to get things going. Ugly code that works is fine for now. It turned out I wasn't properly taking the directionality into account; every line segment needs to have one inclusive end, and one exclusive end, else you end up counting the wrong number of intersections... and the inclusive end is always the start of a vector, but that vector runs in a circle.

BUT ANYWAY, PITA aside, we can now draw some pretty cool pictures.


Triangles! Pentagons! Hexagons! and (on this scale very slightly different) Octagons!

      

Hept-, Oct- and Nonagon on a larger scale*. At the moment we only do regular polygons, and while the facilities exist to flip them horizontally, vertically and across the x=y line, it isn't currently plumbed in. In the future we would like to rotate them. The nonagon is unsymmetrical because it needs an evenxeven canvas to be symmetrical.

Well gee doc, what next?

I was trying to at least fill the room with tables before I was sidetracked with fixing the room generation, so that's where I'm going back to. I expect there is still a step missing from the room anaylsis; under a certain size of room it doesn't make sense to leave the perimeter blank, and I don't want to have to couple the room specification to the shape, else it's just manually drawing forts again....so I suspect once I start adding more than tables an additional step will appear in room generation, where the specification and the room definition interact. Mmm, maybe if the room specifications was in terms of fill percentages of the total room; then one could start dealing with rooms that are only rectangular by partitioning them somehow; and wonky shapes by picking the set of subspaces that would fulfill the space requirement... I imagine I may have to find ways both to merge small spaces into larger ones, and break large rectangles up in creative ways. I can kinda see it happening, but much like the polygon vector thing I'm going to actually have to see it happening to understand.

On a other side note the program is staggeringly unperformant at the moment. That's partly because of some poor choices I made, and partly because I focussed on writing code that was trivial to read without giving any though to how fast it runs...but since we have reached a stable state, so the program may sit and mutate internally a bit until it isnt what feels like O(n^n^n) aka O(fuck off). There are some easy wins to be had with the algorithm for finding the SubSpaces; since it's recursively calling a recursive function, and doesn't even have the decency to do it in parallel. I can probably write it as a much more efficient procedure, now that I have that thing to keep me true.

At the same time, I've begun to think about how to connect rooms. I have a vague notion of an overall desired fortress shape, like long and thin or short and flat. A maximally vertical fort would have one function per level, and possibly mutiple levels between functions; wheras a maximally horizontal fort would attempt to completely fill a level before moving on to the next. At the same time, I regularly do a string of beads, where I dig a little cave near the surface with a masons workshop, a dorm and a hospital; and this evolves into a small fort. Generally I space this fist fort for abooouuut, let's say 50. Then I dig down to the cavern layer, and treat it like a new outside, until I have made it a bit more secure for myself.. and down I go.

Perhaps I will need to know a bit more about connecting rooms and complexes, and planning our their spacing before this becomes relevant, or perhaps it could emerge naturally from those rules, with only the vaguest guiding principle needed to give things a bit of spice overall. It's a bit tricky though, because we're going at this at the moment to generate some final fort, as a pure abstraction that will always look the same given the initial rules, and at a later stage there well be mushing this into the landscape somehow. There will be rules for how it must be mushed in; whether above ground or below ground; fitting into the landscape or with no regard for geology, and preferentially deep or shalllow... and doing this incrementally by looking at the fortress needs is still on the table. So, we want to generate a final fort of any size now, but leave space for it to later be done in stages, and still remember what it did before. I don't want to have to, at any point, try and read the map and turn that _back_ into code somehow.  Heere be dragons; so every space will have to have to retain the knowledge of why it was built, for to expand it we might want to completely destry and rebuild (at first).. but it would be pretty cool if we could expand an existing space somehow.
 
It's the distant future, but if we don't peer there we might end up following a cold wind to some other icy region, and not end up at the north pole as we intend to.

As for the more distant future of this project, it's a good news bad news good news bad news situation. I'm once again gainfully employed (yay!) which means there's a smaller timeslice from which to dish out to this project (boo!), but one of my coworkers has a degree in applied math, and enjoys graph theory (yay!), but on the balance this project will slow down a bit (boo!).
I'll drop pictures here as they are created; I was sitting on these for a few days because, well, look at that pentagon... Regular, coloured, with walls... this post would have been very shamefur if I arrived here with some janky ass buggy room in black and white; but look at that thing. Aw yis. It's not perfect, but it's correct. I can move forward knowing that although it is ugly, it functions, and we can build around that. I think if I can make a dining room, and define a few ways of arranging tables in a rectangle, then see how well it scales when you add something else to the room... then I can get a feel for what lays beyond this***.



*a Nonagon is also called an Enneagon, which is pronounced "Any-a-gon". It almost looks like a contranym.

** That is, I make a large amount of houses. Seeing as there's a pop-cap, that's final enough. 

*** I am, however, suddenly getting the distinct impression that once the room layouts are done I'm going to need at least pretend maps to work with; since that greatly determines how things are laid out. You can bring water to any stone to make a farm, but if there's soil, you'd more likely start there.



Thanks @Carpface; that seems to be the right place to look, I quickly scanned and there's some promising things. I can definitely do a solid granite fortress in the inifinte sky.

@Staver; I can envision a tileset made of special tiles to make OCR easier, just to get the map out... though considering this should work on semi-arbitrary spaces, I can at lest just try and generate something plain as a first go, or a very contrived example to test it out.

@Nopenope thanks, it's useful seeing what scaling constants he uses and how he zoned things...  this has the potential to lead to something like that, though I can't imagine my interest being held beyond generating stellar looking forts. The smallest timeslice I imagine my program dealing with is 1 year.... though in that respect it may be like an AI assist. You manage the day to day operations, but once a year a fuckload of dig plans appear, and a shopping list of needed materials. Like a minigame :P

Edit: @Su thanks :) didn't see you there. I've been typing this message over a few days now, and there have been power outages. This absolute gem of a forum saves my partial message as I go though.
« Last Edit: July 12, 2020, 06:32:25 am by teatime »
Logged
Pages: [1] 2