This Week In Veloren 61
This week, @Zesterer gives us an in-depth look into the mentality behind the design, development, and goals of worldsim. @xMAC94x gives us another look into the new networking prototype. Lots of progress was made in combat as well.
- AngelOnFira, TWiV Editor
Contributor Work
Thanks to this week's contributors, @Capucho, @Songtronix, @Imbris, @Zesterer, @AngelOnFira, @jackrubino, @Slipped, and @Shandley!
This week, @Zesterer has been putting a lot of work into worldsim. This includes sites, settlements, trade routes, and basic economic simulation. @Capucho finished free look and some other fixes. @yusdacra is working on a Turkish translation. @Juli199696 is working on a test server as well as finding bugs.
@Timo has quite a list this week. He worked on many bugs from the combat branch. He's done lots of playtesting and has worked on issues that have come up. Some fixes include attacking animations, better combat movement, and glider physics. @Pfau has been working on adding new armour and weapons. He has also worked on improving some icons, as well as a new map background.
World Simulation Process by @Zesterer
One of the goals of Veloren is to have interesting and complex world simulation. We don't have any illusions of grandeur - world simulation on the same level of Dwarf Fortress is unlikely - but we do want to create a world that fulfills the following criteria:
1. It encourages the player to ask questions when encountering new things by providing answers to those questions
World simulation should be internally consistent and driven by cause and effect. When a player encounters a peculiar feature of the world, deciding to investigate further should warrant actual answers rather than "because it just is like this".
This means placing aspects of the world in a historical context such that the ripples of past events can be explored by the player. If the player comes across ruins, they should have a name and an event in history that led to their abandonment. What happened at this place? Why did it happen? How has this had an impact on the surrounding settlements? All of these questions should have answers that can be discovered by interacting with NPCs or observing aspects of the world.
2. It provides unexpected and unique situations
Existing procedural games tend to suffer from two key problems. The first, a lack of depth, I have already mentioned. When there exists no depth to features of an environment it becomes meaningless to investigate them. Players don't feel like they have a stake in the world around them and don't bother trying to satisfy their curiosity. They become conditioned to accept that things 'just are' without question.
The second problem is homogeneity. Random variations in existing content do not lead to meaningful gameplay and players quickly become accustomed to the scope of the variation that the game permits. By combining elements of variation in a way that interact with one another, it's possible to create an environment that throws up a far greater number of combinations of mechanics than would otherwise be possible.
3. It is dynamic and reacts to decisions made by the player in a way that feels meaningful
Many procedural games suffer from either a lack of interactivity (No Man's Sky) or a lack of interactivity that produces a meaningful effect on the world (Minecraft). Players want to explore a world where their actions have far-reaching ramifications. To do this, the game world must be complex and interconnected such that those effects may propagate through the world in interesting and unexpected ways. Changing the world should change the behaviour of agents within the game world. Too often we see wooden-headed NPCs that blissfully ignore the player's actions in games. We will do our best to avoid this.
How do we achieve all this? Sadly, there is no silver bullet. Procedural systems are difficult to get right, but I've come up with a few basic principles that I've found to be useful.
First, to create content, don't create more variations of existing content. Instead, create new ways in which existing may interact. Minecraft often provides good examples of this: the addition of a single extra block to the game often has a multiplicative effect where players find thousands of ways in which it may interact with existing mechanics to create new things.
Next, randomization is not good procedural generation. In fact, the very opposite: games such as No Man's Sky suffer badly from this misnomer and it created environments without depth or meaning. Instead, variation should be a product of the interaction of a small number of existing elements. Just take a look at how Conway's Game of Life produces incredible emergent behaviour from an absurdly simple set of rules.
Players should be able to reason about the circumstances that led up to a particular situation and use that information to change the way they play in the future. If your game is informed by randomization, there is no common thread that players can use to reason about the game. Instead, they become a 'back-seat driver', beholden to the disorganized chaos of the random rules you've created.
Finally, create 'meta' rules. Games that stick to a strict set of rules tend to be rather dull. Instead of trying to spice things up by making the rules more complex (which just leads to confusion and frustration for players), it's better instead to come up with consistent rules about when other rules might change. You can build up a hierarchy of rules that is both simple to understand but permits a vast amount of variation.
With this in mind, I've begun work on simulating civilizations in Veloren. I've not got a huge amount to show yet, but I envisage something that looks like this:
A world full of 'sites': these are places of interest in the world that may take on particular characteristics. Examples include villages, towns, ruins, farms, hideouts, towers, caves, dungeons, or magical places. The world simulation code will be aware of these sites and will influence them throughout the course of world generation and gameplay. Sites may get invaded, develop an economy, play host to various creatures, or otherwise play a part in the world's story-telling.
A dynamic simulated economy where prices are determined by regional supply and demand. This feature will permit a lot of gameplay, allowing players to become merchants and trade goods across the world. The economy should react to various economic stimuli, with prices rising and falling according to the availability of goods. If a dragon decides to lay siege to a town, demand for weapons should spike!
Simulation of social and material conditions: Ethnic and political groups within the world should interact with one another. Wars, battles, uprisings, plagues, and famines should occur and inform the behaviour of groups within the world.
To facilitate these things, I've made the decision to split world generation into 4 distinct stages, each of them adding more 'colour' to the world:
World generation. We already have this stage: it takes place over the course of millennia simulating erosion, river formation, ecology, etc.
Antiquity. This stage will involve the founding of civilizations and the simulation of basic economic relationships between them. This stage will take place over thousands of years.
History. In this stage, we'll be creating and simulating actual characters in the world. Legends and myths will be created, significant figures will live and die, wars and battles will occur between settlements and civilization. Diplomacy will be simulated too. This stage will take place over a number of generations and probably a few hundred years.
In-game world simulation. This stage will occur throughout the duration of gameplay. It will be an extension of the third stage, with small details added that players can interact with. Characters will persist and can be interacted with by players, changing their behaviour accordingly. Diplomacy will include events triggered by players and will permit a certain level of player interaction.
These stages will be run one after the other for each world. In theory, the results of each stage should be layered on top of one another in a manner that produces a rich, interesting world with a meaningful history.
Of course, all of this is going to take a lot of time to develop. Do not expect this content to suddenly appear in the next update: however, I do want to get a basic skeleton of this architecture working for 0.6 such that it can be fleshed out in subsequent updates.
Networking with @xMAC94x
Networking is currently in a transit stage between the implementation I had, and a newer async-std based variant. I noticed the implementation had a few difficulties, which are not trivial and didn't come up in the beginning.
My initial plan was to have multiple worker-threads. Each worker thread could get multiple channels, like TCP or UDP, and handle their requests simultaneously. This would allow a single participant to have an opened TCP and UDP connection and both are handled by different threads.
This requires a lot of locking and careful synchronising. Also, the old coding had some limitations. A packet could only ever be sent over a single channel, TCP or UDP. But mixed mode, like HEADERS via TCP, or UDP for Data (which isn't that big of a deal). But prioritisation of outgoing messages was only possible inside a single worker thread which could use up all the network capacities. Additionally, these workers would need to be balanced if one has a high load while one a low load.
Those all are not simple tasks, which lead me to the idea of a redesign. Instead of multiple worker threads, we could use a single thread and then use async_std. This has the potential of stopping the synchronisation problems as I include everything in the state machine of async.
For example, the code that handles TCP gets reduced to a small amount, as most of it was manually building a state machine that async already provides. Unfortunately, I don't have any numbers yet to compare those both approaches yet, nor is the new one really usable yet.