Saturday, June 29, 2013

Radial Right-Click

With a RTS interface well known, the hope is that there is no need for any menu system at all for basic RTS commands. Move, harvest, attack, follow and drop-off are all just a matter of right click when you have a unit selected. Selection is through a left click. Scrolling is by holding your mouse to the edge of the screen or using WASD.
In keeping with the same theme the right-click menu will be just as minimal. It'll consist of icons that appear in the same manner as a context menu and will be designed radially. For the prototype version, it'll just be simply arranged box-shaped buttons but the idea is shown below:
Once the player has selected something to build then the UI shifts into building placement mode. Originally I had designed it to be a simple click and if you wanted to place multiple buildings then it was a shift click.
The shift in mentality is to have a more city-building friendly UI. In that light, placing just one building is more rare than placing multiple buildings. So shift is not required. After you place a building, the mode persists in order to allow you to place more buildings. Instead, you need to right-click in order to exit building placement mode.
Building structures in Cultura is a bit complicated versus most city-building games. Because my concept of "wood" is actually a category of goods you can collect (pine, oak etc) and I want the interface to be more friendly, I opted to follow something that is a combination of Sim City 2000 and Capitalism 2 interfaces. Basically, you go through the radial menu. First you select build. Then you select housing. Then you select tent. Now you are in building placement mode. A tent requires wood and fur/skins. In the bottom right corner a window would show up to show the various options and persists as you place buildings. Those settings are used per building placed. This allows for a quick way to build a lot of "common" structures using cheaper materials and then splurge on a select few "elite" structures in a quick and easy manner.
Sim City would have a large left panel with lots of building categories which would open into small sub-categories. Capitalism would let you place a building and then go into a settings menu. For Cultura, the large left panel is replaced by a radial context menu. The settings screen is replaced with a temporary settings panel at the bottom right of the screen. The real estate used in the UI is then temporary and once you are finished it immediately goes away.
I'll work on tweaks to make the UI experience faster/smoother once I have more of a game to play around with and see what is good and what needs to change.

Wednesday, June 12, 2013

Context Menu

Context Menu

Rather than have a full-on RTS style button grid at the bottom of the screen, Cultura will have a minimal menu presence. The game will rely on intuitive RTS control scheme (left click selection, right-click action) and a small tutorial to teach it. So it relies on established gamer knowledge and standard UI implementation. For everything else it will be done by a context menu. You right click anywhere and the context menu shows up.

In Cultura, it uses CEGUI and it uses Ogre3d and those two combined means they must communicate with each other. The actual context menu exists in CEGUI. The effects it has on the game and the RTS interface exists in Cultura code (which uses Ogre3d). That means I need the CEGUI component to communicate with the Cultura component. Now, since I have yet to implement an event system it entails a bit of tight coupling.

The Cultura component handles when to show the context menu and then "gives up" handling mouse events. The CEGUI component is informed that it should show the context menu and properly attaches listeners to various mouse events to buttons pressed. When a left click occurs that is outside the context menu, the menu is hidden and control is returned to the Cultura component. By control is returned, I mean the Cultura component now understands that the context menu is closed and therefore goes back to its original handling of mouse events. This means that on the first left click outside the context menu, the context menu is hidden, but no unit selection occurs. I think that is actually somewhat expected. The primary issue with making it any more complex is that because I cannot guarantee order, in a reasonable manner, of how an event is handled, the CEGUI component simply either handles the mouse click or it does not through all its possible listeners and the Cultura component can be blind as to what happened and simply waits for control to return.

The context menu currently only allows the construction of buildings, it will eventually include empire management options. Also it will probably become a radial menu and at the very least, use icons instead of text (but have text tooltips). If a build is selected, the menu then shifts into possible buildings that can be built (based on faction technology) and then if a building is selected, it then returns control to the Cultura component which then handles the placement of the new structure.

In the Cultura component, it will have a transparent version of the structure sitting at the mouse cursor locked to the closest game grid square. Left click means to place. Right click is to cancel everything. There is shift-click to place multiple buildings. Each placement of a building queues a faction-level action in the faction's action queue. In the faction class' updateTick() method, it will attempt to assign jobs to idle civilians (who work for the government directly). That can be more complex later in the game when there are more complex government options.

Eventually you will need a way to cancel actions and also to requeue actions if civilians are interrupted and stop doing a job, that job needs to be requeued.

I will finish "factionActions" in the next post!

Monday, June 10, 2013

SaveGood and LoadGood

SaveGood

Saving is the "easier" part in the Cultura project. What's being used is the simplest thing that can be done for now which is serialization into a bytestream and then writing this to a file. Difficult to debug and difficult to maintain but extremely fast. Essentially, each class that needs to have data save implements the serialize function, deriving from a class I called GameEntity (for you Java folks just pretend it's like Object). From here you can do whatever you please.

For primitives I simply cast their address to a char* and then save bytes into a byte buffer equal to their sizeof(). For objects that are not pointers, I call their serialize function. For objects that are pointers I can do the same. For arrays and other objects with size, I serialize their size and then serialize each individual object. The resultant byte stream is then directly written into a .sav file on disk.

Key notes here are that dependencies are not serialized (for instance, someone with a reference to AppStateManager will not serialize the AppStateManager and cause an infinite loop of serialization). Serialization is strictly "downstream" in the class hierarchy. Second, the graphics components are not serialized. I call createScene after I'm done deserializing when I load in order to recreate all the graphic entities.

LoadGood

Loading is the trickier part of deserialization although all of the problems are of course because you didn't serialize properly :). A file is loaded up, the contents are read and then put into a bytestream. This buffer is used for deserialization.

For primitives I can simply read a number of bytes and then assign the value I get to a primitive. For instance, read sizeof(int) bytes and put it into an int. Whatever value you get is what it is. Yay!

Objects are somewhat trickier. The constructor for all my classes that are serializable have a default constructor to make it easier to do this. In the default constructor, non-pointer member objects are constructed with their respective default constructors. When deserialization occurs, those objects can simply call .serialize(ByteBuffer) and for pointer objects then we create a new instance (using the default constructor) and then call ->serialize(ByteBuffer).

For arrays and the like we have to get the size, which we saved, and then resize arrays or unordered_maps and such and then begin to deserialize objects or primitives and then add them. For certain containers, we don't serialize the container, we merely serialize the contents. For instance, we can serialize the list of units in a faction and then create a new QuadTree and then add them to the QuadTree (so upon loading it is a fresh QuadTree with the saved units).

Dependency injection is terribad. After creating new objects you must then inject dependencies again since you cannot save pointers in serialization (what would it point to?). This creates very strange and complicated deserialization call trees. The worst of it in Cultura were actions which require pointer to objects to allow it to manipulate the game world. Poop.

And here is the result of loading, the unit is still carrying out the action that was queued, a harvest node action.

Menu Upgrade

The menu automatically generates the file name. I'll leave it in automatic generation even to release to avoid problems with bad user input. Both the save/load menu refresh each time you go back, looking at the files that exist in the save directory. It is also capable of stripping the .sav from the file name to show the user a nicer looking name (although right now it's just numbered from 0 to whatever). There are no loading screens but in the work needed to perform loading, quitting the game, going back in, creating a new game, saving the game or loading the game all work as expected (game is cleared, there's no accidental double deletes, there may be a little bit of memory leakage but I haven't checked yet).

Now you can SaveGood and LoadGood

Thursday, June 6, 2013

Cultura

What is Cultura?

This is a game about empire building with a focus on city building and diplomacy. It takes place on a large map with a wide variety of resources to explore and discover. There are trees to cut for wood, ores to mine for iron, strawberries to pick and seals to hunt.

You start off on a large empty map. There's very few people and you control them directly but as population grows you begin to gain indirect control options in order to focus on higher level decisions. The world is not a vacuum. There are AI players that are in there doing the same thing, trying to struggle and survive as well. You eventually meet with these factions and work with or against them.

The game begins in the stone age, just at the discovery of fire and your first technologies include various stone age tools such as the hammerstone. Technologies represent new ways to interact with the world. At first you gather food and hunt animals. But as you develop ways to chop trees with axes, build huts, plant different plants you begin to shape the world and progress your way into a grand empire.

And new technology means doing more things faster. You can start to replace whole forests with different trees. Get rid of bushes that you don't want and begin to create large swathes of strawberry bushes. You can fill in empty land with wild wheat and harvest it next spring when your nomadic group comes back to the region. As you gain more technologies the options open up to do more.

How is it played?

Controls

The control scheme is a familiar RTS style. Left click to select and deselects. Control groups. Context-sensitive right click to issue orders. Then there is a right click context menu to build structures. As your society grows and you research more management options you can begin to issue indirect commands and manage a large number of labourers.

Resources

The game is heavily about city building and diplomacy and by extension this means a large economic and trade portion to the game. A large part of the game involves managing your population in collecting different resources. Then gather that into giant piles of stuff. Then roll around in those piles. Well I suppose you can't roll around in them. But like a game of Settlers, you collect resources, refine them or immediately use them for finished goods. Then you use the finished goods to improve your society or for the military.

Resources are grouped into categories. Raw categories would be (not the final list): wood, metal, precious metal, stone, precious stone, meat, grain, fruit, dairy, skins/furs/scales, bones. Then there are finished goods: pottery, chairs, tables, earthenware, crates. Some finished goods later become intermediate goods with increasing technology: gears, clockwork, rope.

Each category of resources has different material types. The idea is that you can have metal but it could be iron, copper, tin or viperore. Finished products can be made with ANY material, as long as it is the correct category. Swords require metal. You can make a sword from iron or from copper, both would work because those are both metals. However, having a higher variety of metals allows you to make higher level tools/weapons. A farming hoe that uses iron AND copper will have an extra item level, making it better than a farming hoe that only uses one or the other. This encourages trade or raiding.

The game is about exploration and discovery as much as it is about building your economy. So resources should be interesting. For each raw category there are 8 item types. They are split equally between "mundane" (real life) materials and "fantasy" materials. Furthermore, for goods where it makes sense they are also seasonally split, 1 mundane / 1 fantasy per season. For instance, "meat" can have "caribou" (spring)/"seal" (winter) / "gazelle" (summer) / "rabbit" (autumn). It's not entirely realistic (I mean do rabbits only breed in autumn? :P) but it's nicer for game purposes to push players to move around to discover the world and find new resource nodes being refreshed each season.

Additionally there may be extra special exotic resources that are rare and hard to find. These might be required for wonders or they might just be extra material types in an existing category (such as a "9th" metal type). This allows for the creation of extra special goods (goods using more types of materials are of higher quality) or wonders.

Industry

In Cultura you'll develop an extensive economy and later when you have indirect management technologies you can automate the collection process so that the focus shifts to ensuring the total industry is running smoothly. It's very much like a combination of Anno 1404 and Settlers where the player collects resources and then converts them into intermediate goods and then creates finished goods. Some goods can be made directly from raw materials (and with the game starting in the stone age, that is the case for almost all the first types of goods).

Goods have "levels" to indicate their quality. For tools it means how long they last before they break. For goods that convey health, they give better health bonuses. For goods that convey happiness, they give better happiness bonuses. For military weapons it improves their ability to do damage or block damage and decreases the chance they break if the unit dies. For consumable goods it means they last longer (for instance a bolt of cloth is used to repair clothing and a higher level bolt of cloth lasts longer).

These "levels" are determined by the skill and technology of the labourer as well as the types of materials used in the construction. More types of materials used the better the good becomes. This is mostly limited by technology (a higher level in metalworking technology allows you to use more types of metals). Exotic versions of an item category are exempt from the limit to make them more useful.

Some industries require tools. Before a tool or structure exists to give a production bonus, the work rate is zero. That would effectively mean you cannot make anything. Technologies would be locked in this manner such that goods that require tools to make cannot be researched until you have those tools first. However, you can always trade for things you cannot make.

City Building

At the start of the game in the stone age you do not city build. You find caves and you huddle in them. But the living space of a cave is limited and eventually you'll need to research basic housing technology to survive. This leads to temporary housing and while you are nomadic you will regularly abandon housing to move to a new land region to access new resources. You then have to, again, build housing there.

Ancient housing doesn't simply disappear. It may remain in later times to be salvaged or admired as an archaeological site. Either way, eventually you'll build a sedentary settlement. City planning and construction is very direct at the beginning. You decide everything. In later stages that decision making becomes more about zoning out areas for use and letting the people (modeled as rational economic actors) decide what needs to be built, when to expand industry and so on. You set the zoning and restrictions and then manage the industry. Better technologies allow finer control and higher level decision making.

Structure building is meant to be modular. You research "living space" and ways to make it more permanent (it might begin as a fur tent before becoming an adobe hut) and you build a "living space". However you might later research "eating space" and to design a house with a dining area and a bedroom, you place a "living space" and then connect a "eating space" to it. The same would be for industry. A blacksmith shop is likely to be a "metalworking space" and in there you can add different types of furniture that further improve that space and the bonus in construction speed it conveys to a worker.

Diplomacy

Diplomacy in the game is folded into trade. This revolves around the trade route. You directly control the core of your nation allowing you to shift resources around as needed within that region of control. But for any entities that fall outside of this you must develop a trade route on an agreed upon exchange (even with sub-entities in your own society). This leads to a control gradient. The level of actual control you exert on others and others on you is dependent on the sum total of the agreements.

So at first, in the stone age, you might have small groups of people carrying a package of goods move to another society, you perform trade deals and other political exchanges (such as gift giving). Then they return home and the agreements and trade deals are complete. It's important to note that they have to return for the deals to be complete (like bringing back or sending a peace treaty).

Later these deals could be more permanent or seasonal. For instance a trade festival every summer at a particular village. Or an extended trade agreement of meat (pork) for fur/skin/scales (dragonturtle shells) at an agreed upon exchange rate and scale, with a convoy that sends the goods back and forth automatically.

In all of this, diplomacy can only happen when envoys are in their proper spots. Your envoy at their court or their envoy at your court (well in the stone age, it's more like someone from their tribe visiting your tribe or vice versa).

In terms of empire building, exerting control on others is more gradual than in most games. One of the focuses of Cultura is that technology is tied with options in diplomacy. So rather than the only options being alliance, peace or war, the options are much more subtle. Perhaps you have a military agreement where you must protect them against invaders but instead of a strict agreement, the idea is this: They may "plea for protection" in exchange for "the right of two cartloads of goods to be traded in their society per day". It's complicated sure but this leads to a more gradual imperial domination. Someone might be a vassal because of how the agreements work (you're the military protector in exchange for trade rights) but perhaps someone else is "more" of a vassal (you have a standing military there, can conscript troops and they pay yearly taxes, in exchange for permanent military protection against all threats and this is a strict agreement with heavily political penalties for failing it).

Of course all this also means that the AI must recognise relationships and value them accordingly. They more appreciate a dominating power that offers good trade and real military protection against enemies than one that is more evil (threatens them, demands tribute and so on, they'd try to find someone else to aid them against such a power). As well there is a conflicting idea of whether they want to become more independent (develop their own military, pay less tribute) or more dependent (they might receive yearly gifts as an enticement to remain a vassal so why not?).

One aspect of imperialism in history was for example China's dealings with the Ryukyu kingdom (modern Okinawa and Diaoyou islands area). As an enticement for Ryukyu to remain a distant apparent vassal of China, the imperial leadership would ask for tribute from the Ryukyu but at the same time give many gifts as a show of power and beneficence. The main point? The gifts (goods such as expensive crossbows which required a large industrial base to produce) were far far greater in value than the tribute received (mostly luxury goods, very valuable in China, not as much in Ryukyu where it was more plentiful). So the Chinese Empire expended large resources to maintain its vassal relations (also why when various Dynasties went into decline and income levels dropped they could not afford to maintain these relations and vassals would drop out of the Chinese sphere of influence). The other point is that Ryukyu Kingdom may have been a disparate vassal of China but the control was fairly loose. Compare it with a much closer society to the central Chinese authority and the relationship would be much closer and the control much greater.

Other examples include the diplomacy of the Roman Empire. The relationship with Rome and its Italian allies involved allowing Italian villages to send representatives to the Roman Senate but in exchange the Italians sent taxes to the Roman state and even sent young men as soldiers for the Roman legions. That's a much closer relationship, one to a point where the Italian cities could be considered a part of Rome. In Cultura, the Italian cities would be a "sub-faction" in the game.

Technology

Cultura has three technological lines: Fantasy, Steampunk and Mundane. Those of one society cannot research any technology of the other two. This also means goods produced by one society may be impossible to build in another society. Hopefully that encourages cooperation (or war). But it does mean that interaction is typically quite meaningful for both parties.

Fantasy technology is themed around a strong military and a small society. Most of the fantasy technologies involve various spells, enchantments and magical artifacts that variously improve the military but also some of civil life. For instance health potions may be a good that improves the health of a population.

At the end of each game day a player earns tech points according to the amount of research conducted and their world ranking in scientific research. The idea is that poor research doesn't lead to an excessive gap. It also does mean diminishing returns for excessive research spending.

Tech points are used to unlock new technologies or improve existing ones. The technology tree is meant to be incredibly in-depth, involving many different upgrades for a single technology. For instance, pottery can be researched but then you could also research glazing (using up extra fuel to improve quality) or you can research leeching (using up whatever acid will be considered in the game in order to increase quality and make it look fancier). This leads to a more nuanced technology tree and a more progressive continuous shift into later ages. Instead of simply moving from one age to another you shift into it as you replace older technologies or acquire new technologies and make industries out of them.

Population Stages

Population growth leads to new stages in the game. Like a session of Anno 1404, as your population grows they gain new demands. In Cultura the model revolves around health and happiness. At higher population levels health is monitored and then happiness is monitored. The consequences of insufficient health/happiness becomes more severe at higher population levels.

At a later stage, for large empires, administration is the last of the three metrics by which your empire is scored. This represents the ability to manage the empire, low score leads to corruption and crime. Low health leads to sickness. Low happiness leads to emigration, civil unrest and even revolt.

Closing notes

Cultura is a large epic game. It's going to be released in phases with the first set just in stone age. Each subsequent release will include more technologies and more options to build a larger and larger empire. My hope is that it's a game where you have fun simply developing a great history for your culture; that you continue to play through the highs and lows. Explore a world. Find some walrus bear wyverns. Punch it to death. Make armour out of them. Conquer your nieghbours. Make your people happy with wine drunk from the skulls of your foes. Cultura.

Friday, May 31, 2013

Menus Everywhere

Saving and Loading

Menus! Right now there are no in-game menus or overlays and everything but new game and quit game do what they are supposed to do. The next task on the list is to fully implement saving/loading. Additionally, I wanted to fix up the menu transition in and out of game. There are two minor issues: you lose your selection of units and your mouse position is also reset.

Also I've been keeping a list of infrastructure debt but that list will be tackled on an as-needed basis to get a working game (also lets me have more time to figure out what I really need to do to solve those problems because I'm fairly unfamiliar with future issues that might arise in Cultura).

Saving/Loading

The saving and loading dialogs need you to be able to select save files or save to disk. I don't know if you really want a full file explorer or just a simplistic "save/load" console style. I'm leaning toward console style.

CEGUI provides something called the layout container which I plan to use to create the list of files to save/load. When the dialog is loaded it scans the save/load director for files following the *.sav format. This creates a cross-platform issue which will be ignored for now (we'll just use the windows directory system to load up the list of files). For each file we create a window and add it to the layout container. Then we will have the same functor used as the subscriber to the onClick event of each. We will set userData on each window so that when the user later clicks on it, in the listener function we can then determine what was clicked and set the correct file as the one to be saved/loaded (also do fancy UI stuff like highlight that box and unhighlight all other boxes).

Here are some CEGUI references that are relevant:

The user then clicks on save/load to perform the actual save or load. For now, I will not allow user defined file names. Instead they will be automatically generated.

Currently, the serialisation works on creating a byte array that is then saved to disk. The serialisation is a bit manual. All objects that need to be serialised essentially derive from CGameEntity. The serialisation uses a custom class known as a CByteBuffer. Objects write to a byte buffer when serialisation or reads from the byte buffer when deserialising. Each class must know how to read/write its member variables inside its serialisation function. Each class calls the super class's serialisation function. That way you get a chain serialisation occurring. It's somewhat tricky to choose which variables inside a class to serialise but there are special considerations (which can be cleaned up with refactoring later): not serialising temporary member variables such as graphic entity pointers.

Also, to simplify serialisation, units/structures and many other entities are being compacted. Originally, I had subclasses for units and structures for different types of units/structures. However, when you get to serialisation that becomes a problem (I have a CUnit pointer but is it really a CAnimal?). Instead of something fancy, the different levels will be compacted into one with a few classes added to record large blobs of data (a new StorageStates class for structures).

I will have to serialise actions as well and in that case, I will have to serialise what action was just serialised (so I can perform proper desserialisation). This means adding a few constants to the UnitAction class and a variable for UnitActionType.

Compacting the Classes

In an effort to simplify serialization, I am compacting my unit and structure classes into a single class with several "container" classes hanging off of them.

Unit:

  • CombatStats
  • EquipmentStats
  • CounterStats
  • Carried items
  • Location

Structure:

  • CombatStats
  • CounterStats
  • StorageStats
  • Location

CombatStats:

  • Hitpoints
  • Damage

EquipmentStats:

  • Item* HeadSlot
  • Torso
  • LeftArm
  • RightArm
  • LeftHand (for weapons or equipment)
  • RightHand (two handed weapons will have both slots point to the same item
  • LeftLeg
  • RightLeg
  • LeftFoot
  • RightFoot

CounterStats:

  • int MoveCounter
  • AttackCounter
  • bool incrementMoveCounter //returns true when move counter gets reset and the unit should move, false otherwise

StorageStats:

  • std::vector Capacity //-1 means unlimited, uses constants for item categories, checks narrowest category first before moving upward, for alpha, just have all/food/non-food categories
  • std::vector StoredAmount //list that mirrors capacity, must update all categories when giving or taking items
  • std::vector StoredItems
  • int GiveItem(Item* item) //returns amount not stored
  • void TakeItem(Item* item)

Carried items can just be a StorageStats object that is not using most of the functionality and only has a single storage limit for all items.

Location is a std::pair to indicate a map location

Tuesday, May 14, 2013

Alpha Design

Designing Cultura

I'd like to pause for a second to develop a clear goal for the alpha and just blab a bit about the game I want to create.

Checklist

  • RTS Interface
  • Management Interfaces
  • Diplomacy and AI Factions
  • Menu Basics

RTS Interface

The core of the game is very much an RTS, the ability to scroll around and watch your empire do work in real time. But, the ultimate intention is not for you to individually control units. As you progress you spend more time managing your empire than you do individual people. There are three main RTS interfaces that will happen: Direct, Partial and Indirect. Direct control means units that do nothing unless you tell them to do things. This will remain true of military units in battle and of only some civilians units (all units at the beginning of stone age will be directly controlled). As you automate more of your labour through the various management interfaces they begin to act automatically. The intention is that as your society gets large and you try to maintain direct control, then you will likely lack enough focus to keep everything running smoothly. Partial control means individuals who are tasked to certain tasks but you can still give them one-time orders. Those one time orders will cause them to deviated from their automated behaviour but once completed they will return to their original task. For indirect control, units will not listen to your orders at all. Instead the only way to manage them is through the management interfaces. At much later stages of the game, such as well into the classical age, portions of the population act completely autonomously and you only affect their behaviour like any government of today: incentives, tax policies, tariffs and so on.

Management Interfaces

The management interfaces are a slew of UI dialogs that you can access in game (which will pause the game) that let you handle different aspects of your society. These interfaces are likely to have to morph through the times (depending on technology). The goal of these interfaces is to lower the amount of direct individual interaction with units in order to manage your society. It is also through this interface to do some special actions such as claiming or abandoning areas.

Wealth Management: An interface that looks at the total stocks, the stocks owned by regions, by individual people and allows you to distribute wealth to individuals. The accuracy, or the ability to have these numbers, will likely depend on technology and bureaucratic size. In addition to that, I am intending to add administrative cost (someone has to count, keep track of records and then physically hand out goods) to distributing goods as an incentive to streamline good distribution without direct government (you) intervention.

Region/Empire Management: This allows you to look at population level and owned structures. It also allows you to claim or abandon regions. Abandoning regions is more common early on when you might leave to find new food sources. As well you can see happiness/health score and perhaps secondary information such as change of disease, revolt or natural disaster. A tab or transition to another screen should allow you to set various social policy. Right now, I'm only thinking of taxation but whether I wanted a "rule" base engine or something less fancy I'll have to contemplate. I don't want it too complex to play but this is already a fairly niche game so whatever.

In addition to the Empire Management it should probably feature a second for population and animal growth (for directly owned animal herds). Since population growth is dependent on food it should be affected here. I figure all new births are in the spring. Because what the hey.

Industry Management: This allows you to assign labour to particular tasks, for all seasons, for particular seasons. Also allows you to set production minimums, maximums, quotas, rate limits and so on.

Technology/Culture: Here you can see the tech tree, culture trait leanings and of course spend tech/culture points to acquire new techs or cultural traits. This should also show you the cumulative effect of your various cultural traits

Diplomacy and AI Factions

The other meat of the game is about diplomacy and so I need at least the existence of AI factions in the alpha. Maybe the AI will be really bad or whatever, but I just need them to exist to allow diplomacy to be conducted (albeit not very useful with a player that does nothing). Of course later on AI factions will play a major role in making the game "fun" because they will be a dynamic part of the world.

Menu Basics

For the alpha, at the very least, we need new game functionality (with world generation) and saving/loading. Other than that, I don't think I'll spend any effort into graphics/audio settings (well in fact I have no audio as of right now :) ). I just need a fully functional menu.

Inspiration

There are a number of games inspiring me to make Cultura, the two most important are Civilization and Dwarf Fortress. Unlike Civilization, this is an RTS (so I suppose more like Rise of Nations). Unlike Dwarf Fortress this is about managing a society rather than individual dwarves.

But because I focus less on individual needs and more on social needs, the focus of the player changes to bigger management decisions with industry, diplomacy, trade and war. Those reflect ideas I pulled from other games. An industry-chain for each finished good; this is like Settlers. Diplomacy based on trade-routes but also intelligently reacting AI: trade is like Anno series and diplomacy is more like Galactic Civilization where they don't simply have a flat point-score in making decisions, they take in the context of the socio-economic condition of the game. But the world is vibrant, with a mixture of mundane, fantasy and steampunk. The exploration of the world is more like Master of Magic where you always wonder what strange new resources exist "over there", or what creatures you might encounter and must deal with.

Ultimately, I'd like to eventually see a game where some Mundane society is sending a trade ship across the ocean carrying ivory carvings when it runs into a kraken just off the coast of a fantasy nation under blockade. Then... BROADSIDE!

Look and Feel

I'd like to capitalize on the 2dness of the graphics that I am implementing and what would be a good fit is a "painterly" look. I think that'd be the most bang for the buck. It'd look really slick but not require any extra special graphics tricks compared to what I am already doing.

For the game itself I'd want it to be a mixture of direct control and indirect management. The entire goal is for you to be building a history with the society you are shaping from the very first days of the discovery of fire all the way on forward. It should be personal, it should be your tribe and you should feel like its leader. But, it's not meant to be about controlling individual people, it's about the whole society. So as you progress you should feel like you are capable of doing more grand things while the society takes care of itself.

You'd start off with a bunch of cave people, the first races being human/elf/ogre, and you need to go out and explore the world. You must find natural caves at first until later you can begin to construct buildings. Before sedentary life you might abandon places seasonally to go on the hunt for more food in different regions. The environment is vibrant, lively with an ecosystem you have to follow. But it's a living environment. Perhaps you want more cherry trees instead of pine trees, so you slowly over time shift the eco system of regions. Then as the land becomes more productive, you can support more people and so you go on from there to build a greater and greater society.

The tech tree is meant to be slow and more about differentiating your society from others. So it's more about very specific technologies with a small section devoted to cultural technologies where you define culture specific luxuries and cuisine. You develop specific good-preferences, value systems and so on which will affect how you manage your society (preference for specific goods will push you to develop those industries) and how you might interact with others (a preference for peace versus war).

Another aspect of the tech tree I hope to differentiate from Civilization is the elimination of the "1000 year war" problem. Where, in the time span of a single war, you can move through 2-3 ages worth of weapons. I think that breaks a lot of the suspension of disbelief. By the time you send your archers and warriors to the frontline, there are axemen and chariots following up behind and finally swordsmen and catapults. I want Cultura to be a game where you don't just "feel" technological progress but there IS technological progress throughout the game yet at the same time you play out whole scenarios in the same tech age.

I accomplish that through being very specific with technology. You develop the burin before a chisel and needle. You have to research scrapers before you can do leatherworking. It's very in-depth and involves a lot of small improvements to society. There will be no clear line between stone age and copper age. You will just slowly shift your industries into the latter. But, I like having a player be able to invest their time into something, have it last and mean something and for them to be able to sit there and formulate grand plans for world domination, to have to worry about this faction and that, while still using stone axes and after all those plans have finished... new technologies and factions come about to upset the balance. I want a player to fight 2-3 major wars just in one age, have convincing stories and history about it and then move into the copper age.

The ultimate goal is for a player to find archaeological ruins of their own making in Cultura. Why, these caves? These were the ones you lived in back in the early stone age but now that you've built Rome in a neighbouring region, they are merely a curiosity.

Less talking. More Raiding.

Saturday, May 11, 2013

Attacking

Attacking

Now available in Cultura, punching other people. To the death.

And after punching the ogre into poop... WE DINE!

Actually, I will make it a cultural trait choice if you want to perform cannibalism or not. Otherwise the resource node that is created will contain the stuff the unit had equipped and/or carried.

The attack action itself is actually fairly simple. It's similar to the move action. It does a distance check to target, moves closer if necessary and when in range it then calls the combatResolver to do damage. In the future when events are implemented it will throw up an attack event rather than call the function directly.

Secondary Action List:

  • Unit Creator
  • Action Architecture
  • Faction redesign

In order to cope with the growing needs of Cultura there are a few items that I'm going to address before my mind melts at the bad code.

Unit Creator

The unit creator is a class with a lot of static functions used primarily to create game entity objects. You call its various functions like createUnit or createAnimal, pass in an integer for an id and it spits back out a pointer to the new object. This is useful for several reasons: it can have an internal counter to use as a unit id (or resource node id etc.) which will be useful for decoupling some classes from direct usage of units/structures. It will know what numbers to assign to what for basic versions of units (I may add in more parameters later to make the entityCreator do more stuff but we'll keep it simple for now). These numbers include hp, damage, mesh names (although this might be changed later, at least it'll be fixed in one place) and so on. One place to make everything, one place to change how anything is made.

There is a little bit of design decision with how the type identifier ids work. Basically, there are around 10-20 raw good categories (I still have to hash out the exact design later) and in each there are several different material types. It would be nice to map those different materials to the item type that they are. For example: oak, pine, silverwood, ironwood would all map to wood for item type. There are all sorts of crazy complex stuff you can think of but rather than do anything special there'll just be a min and max constant for each set of materials and any value that falls between them inclusively will be mapped to a particular item type.

Doing that is useful for a situation such as a deer carcass. You kill a deer it drops an item of type carcass, and the material of the carcass is like deer antler (bone), deer meat (meat), deer bone (bone) and deer skin (skin). When you process the carcass it would be an easy conversion to know that the carcass (deer antler) converts into bone (deer antler).

Action Architecture

As mentioned, I'm switching CUnit* references and other such direct references to objects in actions into knowledge only of integer-based ids. The reason is to decouple actions from those classes. Right now, the flow is GameState->Faction->Unit->Action. But then action has knowledge of the gameState and units. That's just poop. It also makes memory management a nightmare. For instance, say an action is referencing a resource node and then it is deleted. No way to know and you'll get an access violation error. If instead you only know of the node by its id, then you must call gameState->getResourceNodeById(int id) and then if it returns null, then you know it's been destroyed and thus you should stop trying to harvest it.

I can remove the gameState coupling when I introduce an event system but for now, we'll go with the id-based system. We are going to "decouple" through coupling only through the gameState object. When there is an event system we blow away those references make them into events instead.

Faction

Factions, which contain the units and structures, will now need to keep knowledge of units by id and structures by id. The cost of an id is an integer per unit/structure and also a pointer to each unit/structure within a hash set (probably going to use an std::unordered_map). I think that's a reasonable cost for O(1) access time from actions to units when they only know about the id.

As an aside, I had some offline feedback about the fact that the cavemen in the game were carrying about balls of water and punching gazelles. Thus here is potential cover art for Cultura to reflect just that:

                                   `                                                                                       
                                                                                                                           
                                                                                                                           
                                                                                                                           
                                                                                                                           
                                                                           ,       `                    `                  
                                           @                                           `                   `.              
                                           @@              ,@@@@@@`              #.    :@@@@@              @@@ @@+         
        ,@'+##+#@@@@@@:           @@@;    @@@       `   @@@@@@@@@@+       @@@'   @@    @@@@@@#   @@@@@@@  @@@@:@@@@        
         @@@@@@@@@@@@@:          @@@@+    @@@   #@# @@@,@@@@@@@@@@+     ,@@@@@  '@@`   @@@@@@#   @@@@@@@: .@@@@@@@         
        `@@@@@@@@@@@@@:         @@@@@,   +@@@@  @@@:@@@  @#  @@@@@'     @@@@@#  @@@@   @@@@@@    @@@@@@@:   @@@@@.         
        .@@@@@@@@@@@@@.        @@@@@     @@@@@  @@@@@@@  @@  @@@        @@@ #   @@@@   @@@@@@    @@@@@@@     @@@@          
         +@@@@@@@@@@@#         @@@@      @@@@#  @@@@@@@      @@@       ,@@      @@@@`  #@@@@     @@@@@@`     @@@           
         ;+ .+@@@@@            @@@      @@@@@@+ @@@@@@@      @@@       :@@     #@@@@@  @@@@@#    @@@@@       @@@           
              @@@@@            @@@      @@@@@@@ @@@@@@@     #@@@       ;@@@@@  @@@@@@  @@@@@@@  .@@@@@       @@@           
              @@@@@           ;@@@+  @  @#@@@@@ @@@@@@@     @@@@        @@@@@# @@@.+@  @@@@@@@; ;@@@@@`     #@@@           
           @@@@@@@@@@         :@@@@@;@ @@'@@#@@ @@@@@@@     @@@@        @@@@@+:@@@ @@@ @@@,@@@@  ;  @'@     @@@@           
          @@@@@@@@@@@@        .@@@@#@@ @@@@+@@@`@@@# :.   ;              @@@   @@      :@   ,                ':            
           @@@@@@@@@@          @@@@@@` '@,                      ;@:           :                :#                          
           @@@@@@@@@@           :;'                `        @@@@@@@                         @@,;#''@@                      
           @@@@@@+  :.           ,             `           `@@@@@@@                     +.@#       @'#@                    
                :                                           '@@@@                     :  @+ :,  ` :` #'@;                  
             @  `            +      #    '     ;:    @@@@@' `@@@@@                  ` +@@ `         '  #,@                 
            @@@       `  .@ @@@  : ;@@:@#@:  .@@@@,  @@@@ @  @@@#@                 ;@'@@          ;     :#.                
           @@@@  +@@@+@ @@@@@@#  ;@@@@@@#@   @@@@@@  @#@@ @  @@@@#                 @@@    `      :@@      @                
           @@@@  @@@@@@  @@@@@   :@@@@@@#@`  @@@@@@@ +@@#@   @@@@                '@@@@@@        .@  #@ .   @               
           @@@@` #@@@@@  #@@@@    @@@@#@#@: :@@@.@@@ :+#@@   @@@@@@@            #@@@#.#          @@@.'@`   @               
           @@@@@  @@@@@,  @@@@  # @@@@@@#@'  @@@:@@@  @@#@   @@@@@#@`           @@@:@@@#          @@@@+@' . @              
           @@@@@  @@@@@@  @@@@    @@@@@@#@@  @@@ @@@  @@@@@  @@@@@@@@          :@@@@.' ;@            `@@@ + @              
           @@@@@  @@@@@@  +@@     @@@ @ @+@  @@@@@@   @@@#@  +@@++             ;@@,@#@#.,@@            @@ ' @              
          ,@@#@@' @@:@@@  '@@     @@@   @@@  @@@@@#   @@#@                     ,@@@@',#@: .            '. ' @              
          @@@@@@@@@@ @@@  @@@+   .@@@   @@@  @@+@@                             :@@@@@',,#@                ' @              
          @@@@@@@#@  .'    @`      :`         #::              ##@             @@@@:###..#                :+@              
         ,@@ ;                                       @@#@@@@@@@@@@@@           #@@#@@# ##                ' @@              
                                                +#@  '@+`;+'@@@#@@#@@          #@@.;@@',@@ @           @ @:@.              
                                                 :@@@@; @`##@#@@##+:@@         #@@@@'.@;`'.. :,   +  +,@#@@@               
                                               .+ @#@##+@@#@@@@;@++@@@'@,      :@+#@@;.@@ # @'   @  @ @ ;+@'               
                                                 ;@@## #@.#+'@@`@@@@@@#@@       @@@ .@ ;, ':.@ @;@ ##,@@@#@                
                                                @@`#@#.@@+#@#+#@@@;#@,##@@      ;#@@##@@.@ @+:#'+ ;+ ::'@@@                
                                               @@@@;@@:@#@@@@@#@#@#@#,@@@@       @@@@ :# ;,'@+@@@: @#@@ @@                 
                                               @+@':@+#@,#.+## ++@@@@@@@@@        #@@@@@@#@.;@@@@@@@@@@@,@                 
                                               +.@@#@.+@'###:@#`+#@@@@@@@@:`      '@@@@@@ @@+@@@@@@@@@@@@@                 
                                              @@@@@#@;#:@#@`@#@ @@@@@@@@@ #        @#@@@@@###@@@@@@@@@@@,@                 
                                                . @#+#@ @@@@.@#@#@@#@@'+@#        @@ `@@@@@@@@@@@@@@@@@# @.                
                                                 @@@. @@@@@  @@@@@@` @@@+         @  .,.@@@@@@@@@@@@##@: @                 
                                                ;@@+#@ @@    @ .@@ ` @@@@         @``@ :.     ;@@@@@@:@  @'                
                       @                        #@@#+@;@       @#  `  ' .         @@@. . '     ;  :@@,'  @+                
                     :@@@+                    +@@:@@'#@@      ;@   `  ' @         `@@        `:.,     `  @                 
                     @@  #@@ @+               @@@@#@@ #;'#  ` @      @@#+         ,;@@                   @                 
                     @     @@@@@@.   ., :     #@@@@@@#` @@@@@@;@@ ` @@#             @@                  @:                 
                    @#       `@@@#;   .@     ;@@@@@#@#       .+@: '@@@.             :@           #@;';@@@@  ,              
                    @            @@@@@       @ @@@@@ `   @@@@@@@  @@@#:             `@@          @@@@@@+@   @  `           
                   +@              @@@@@@@' # #@@@@@ ``,@,@@@@.`  @@@.         #  ; '@@    @.   @,          @@             
                   @                @@, @@@@@+@@@@@@@ :+  ;@#+'@ # .:@        @@    '@@   :@@' #@           @@+            
                  @@                ,@@;    @@ `@@@@@,@  @@@@@@@: `@@         @@    @`@        @            @@@            
                 @@.                  @@@    @@#@@@@@#@#@@@@@'@@@@;@@'       +@@    #;@.      #@            @ @'           
                '@@ .                  @@` ;  @#@@#@:#@@@@;@@@@,#@@@@@       @@@     ,@        @           ,@;#:           
                .@                      @@  , @@@@#@#@@@@@@@@@@@@@' @@       @@@     `@        @            @@'            
                @@;                     @@  . @@@'@@@@@@@@@: @@@@@@@;@;      @@@     +@        @:                          
                @@@                      @`    +@@#@@@@+@@:.;@ ,  @+#@       @#@@    '@   .    @@                          
                @+                       @@     #@@@@#@##@  .@ @ `@'@         @@     #@   :    @@                          
                @+                  `    @@    #'@@ @@@@#@  `@ #@@`@@@@#      @'     @#        @@                          
                @+                      '@@    @ @@# @@#@@'# @@@, @@#@@@@#           @;        #@                          
                @#                      `+@    @+@@  @@'@@@#@@@:@@+@    @@@          @         @@                          
                @@                     ` @@     @@    @+@@@@@@@@@@ @      @@         @         @@                          
                @@                      .@@@          @@@@@@@@@##@@@   :.  @,        @         '@+                         
                @@                       @@#@         @@@@@@@@@,@@@    @@+ @@        @          @@                         
               .@@                       #@'          @@@@@@;#@@@        @ @@:       @         .@@                         
                @@                       :@'   `      ,##@@@##@       ;@ +  @#       @          @@   #.                    
                .@@                       @@#: @@     ##@@@@@@       @@     @+      :@          @@   '@                    
                 @@@                      @@+#  @@    #'@@@@@@:   ` @@      @#      @@          @@   #@@                   
                 +@@@                     '@+,   @@' , `#@@@,@`   @@@    `  +@, `   @#          @@   @ @                   
                 :@@@#                     @@     +@@,,' @@@     #@@    .    '@:    @:          @@  .@ @+                  
                  ,@@@#                    @@+      ,@@` @@.   .@@           #@@   ,@           @@  #@ #@                  
                   @@@@                `   @@      '     ;@     :       ,    `@@@  :@           @@, +;@@                   
                    ##@@                   @@#   .@@@#   #@           @.       @@: +@           #@# #.                     
                    ;@@@@                  ,@@`@@@   @@: :@           #@;.      @@ @@           #@@.@'                     
                     ##@@;                  +@@@ `    #@ @;            #@:       @@@@           #@# .                      
                     `@:@@         .@#    ;@@@.        +#@              @@       `@@+           ;@@                        
                      +@#.@       @@'`@@@@ @@ `         @`     ;         @`      . @@       , . `@@                        
                       #'#@@    ;@  `   @@+@.``         ,@`    @         @+        @@     ` `  `;@@,      `                
                        #+@@,  @@ `   `@@@@+ ;     ';   @@. `  @@        @@   ,   ,@`          .;@@`                       
                         @'@# +@#    ;@@@@@@+           ;@'+.  +@        #@       @@             @@+                       
                         `@,@@@     '@@#@@@@@          #:@#@@# :@     .  :@.      @, .           @@                        
                            `@+      @@+@@@@@#        ' '@@@@#,,@         @+    ` @#  ,         +@@;                       
                        `,@@@@ ,     @ +@@@@@#`        ..@@:@@@ @        :@.     # @`          ';@   .                     
                      @@@@@. @  ,    @ #@@@@@@#     `  .`@@   @@@        @@    '   #          ; @   #                      
                      @@    '@`     @@ @@@@@@@,        . @@ .  @@   `  . @@@  .  . .,        .#@@  #@'                     
                      @     '@'  ;  @@ '@@@@@@#`       ` @@    #@     ,`##@@@  ;  `.    @@@+  @#@  @@'                     
                     @@      #@   . @@ #@@@@@@@'         #@     @,    ,'#@@#@@';               @@; @@                      
                     @. ,    #@ . `#@: +@@@@@@@@         #@     #@   `; +@@ @@@  `          `  @@@#@@                      
                     @;.      @, . @@  :@@@@@@@@         #@      @'` .,@`@  '@@@+           +#@@@;                         
                    @@        ;@  `#@   @@@@@@@@# .`     .@ ,     @..@  @;.   @@@@@+ ;#`@#'@';@ ,`                         
                    @@        `@`  @@   @@@@@@@@@ `..  `,@        @@.  @@      @@@@@@@@ .@. @;  :+                         
                    @###       +@ :@@ : @@@,@@@@@ ,..   +@        @@  @@        @@@@ +@@  @@@  #:#  `                      
                    `@@,       .@`#@@   +@@@@@@@@  .`,   @         @;@@        #@#; @@  .@.@   +@@ `                       
                     @@ #@      `@#@@@  ,#@@@`@@@  .,`   @        @@@+#     +#. :@@   `@@: @   ;@@                         
                    .;@  @@`@.   @@;@@@  @@@@'@@@@ :  ,  @  ` `   @@+@ `,@#  ;@@:`   @@ @@@    @#@                         
                     :@@ @@@@@# ` +,#@@@  #@@@'@ ;@: ` .@@ ::    ,@@,@:+;'@@+ '#   @@          @@@.                        
                     ` @. @  '@@++@@@#@@ ., #@@@@. @` ..@@      ,@@@@@@@#   :'   @@,          #@;@                         
                    .  .@ @'    @@@@@#+@   ` @'. :::@@@#@@@ `;+@@@@.,    `'    @@;            :@+@                         
                        @@+@  '@@@@;@',     .   #    #@@+@#  ,@#,@     ,+    +@:             , @@@                         
                        ,@@@ ,@@@@`  :+;    :        ,:@@@;'@#+@@#    +@@  .@#               ; @ @                         
                      :#`@#@@ @@@   .  @@##;          . +@@@@@@@@#:   #@ :@#                 ,;@ @                         
             #@@@@@@@@@::++  ,@@     , '`  :@       `    .@#; ,'`. , @,+@'           ,'.:;  :#@@@@,                        
              @@  `'+ ,;+@ ` @@      ::                   #@  `,.  , '@@;.'.:. ,;';,    `@@@#@@  @                         
                @@#. #   ;.  @@         +           `,+    @@+   ` `  ###@@@@#+.    :@@'  '@@ @ #;                         
              + @@@#     ,, :@@                     '     +:@ '#       @@@@@@@@@'@@'    #@@+  @ @                          
             @@@@,  `    #` @@@                       `   +@@@@@@+      @@@'`@@@.     @@; :;@@  ,@             `           
            @@@ .`       ; .@@.                           +@@@@@@@#    #            @@    ;@ @@.,@                         
          @@@,      ,+@@@# :@@                    '        @@@@@@@@#        .    #@'      @`@, @@#                         
       +@@@+     #@@@@#@@@@@.@   .,                         @@@@@@@',   '@`   .@@:        @,@   @@                         
      +@@@@@#+, @@@@   @#,@@@@                              @@@@@@@@'    @.;@@#           @ @   @@                         
          @@@@@@@#  `    #@@@@@`                  .          @@@@@@@@:    + +,@           @@@   +,                         
           +@@@@@@@@; :,   +@@@@@        `                   ,#@@@@@@    ,  @@@;          @@`   @:                         
          @@@@@@@@@@@@@@@@@@@@@@@@ `                            @@@@@       ,@:::         @@,   @                          
         :' @@@@; @        :@@@     `  .            .    `          @@.       #@ `, `    @@  '  @                          
        @.# @@@@@@+@@       # +@+     `              ,                @;   '  +#@        @   #  @                          
          #+.@@@@@@@@@@ @   @  ,     :                `               :@#        `.    ,@   @#  @                          
           @`@@@@@@#@@:@@.@;@@  +                          `           @@@         '  @@`   @  @                 `         
            @#@@@@@@+@@,@@@@@@@  ,.                   .                 @@@   .`     @@    :@  @                           
             #@@@@@@@@@@@@@@@@@;                          `              @@@,,      @@ :   @@ .@                `          
              '@@@@@@@@@+@@@@@@@                .:                   .     @@+  ; @@;   +;#@  @                            
               #@@@@@@@@@.@@@@@@@.            `@@@@@@                       @@#:@@`      +@  .@                            
               @ @@@@@@@@@@@@@@@@            @@@@@@@@@                       @@  ;`      @ `@@.                            
              `+  @#@@@@@@@@@@#. +          #@@ @@@@@@@               .        @# ..   +@   @@ @                           
              @     '@@@@@@  #             `@;@@@@@:@@@@           +           @@`.`,,#@   @@ +,  +                        
              `    +     .@+                #@@@@@@@@@@@                 .  .  @@   : @   '@#  #,,                         
             @     #      @@       .        .@@@@@@@@@@@                ;  ':'+@@@#  #    @@                               
            @   , #       @@    ;',          .@@@@@@@@@   :, ..:          ###+@@@@@; ` @#@@                                
           ;# '   '      + @+     .            .@@@@@@       ` :      @@@@@@@@.@@ @@@@ .@@`                                
          +@'#+@ @      @` @@                     ``   .:           : `@,#@#@@ ;   #@@#@@                           `      
         ;@+;@ @@@     ,@  :@                                          .@@@@@@.;  `'@@@@:@                                 
       #+#@ @  @@      @@   @+                                  '#@@.  `:'#  .;'  ;#@@@                                    
      ''@@''  '#@     @ #   @@     @                      @# #@@@@@@#,  ''.    @, @@@:                                     
      ,`      : @    @ @    #@    #@@                    @@@@@@@@@@@@@@#.+ `    @@@@                                       
                @'  @  @:   `@:    @@@                   :@@@   @@@@@@@@@@#:.:'@@@:`'                                      
               , ` @  ,@@   @@@    '@@@                   @@#  :  `    .#@@@@@@@@+@+                       `               
               @+ #;  @@@  @ ;@.    @@@@@@            ,' .+@@#'+#,.       .'@@@,@@@,   ;                                   
               @`:@     + @  @@@     @;@@@#@@@@@@@@@.`+#@@@#@@@@@@@@@@@@@'  ,`.@@@#                                        
               # @     # :.,##@@      #;++#@@@#@@+ @#    #@@@@@@@@@@@@@@@@@@@@@;'@'                                        
              @ @      @ @ .@@@`       `@@#@@@@@@@:    ,    +@@@@@@@@@` @@@@@#'+@,                                         
              @,+      @@  #@@@          #`   #               @@@@@@@@@@@@#`.@@@@#`                                        
             # @      '.' :#@@                               @@,@ ;;#@@@@@@@@@@@;                                          
            .@@       @@ `+@@#                              @@+#     # '+@@@'@                                             
            +@@       @; .@@@                             :@@.#       # `                                                  
           `;@          ;@@@`                             @@, ,        @  ;   :`                                           
           `@`         ;,@@@                             +@;            @    '          `                                  
           #@         . @@@                             @@#@     +    @@ ;   @                                             
          :@.          +@@@                            .@# @     @'   ' @@@:+@                                             
          @@          :@@@                            .@#  `@    @@`   + @ @@'@                                            
                      @@@@            '               @@    @    @,@   @    @`@.                                           
`                    #@@@                            @@     ',   @ ,@  @     @@                                            
`                   `#@@'                           @@.      @   @  @@;      :@                                            
                    '@@@                           @@'       @@: @   @#       +                                            
                    #@@:                         `@@#        :@@ @    @:                                                   
                   ` @@                          #@@          @@ @     ,                                                   
                    @@                         ':@@             @@                                                         
                    @@                        :,@@              @'                                                         
                   @@                       .` @@.              @;                                                         
                   @'                    .    @@                 @,                                                        
                   @                          @.                 @+                                                        
`                 @:                         @@                  @'                                                        
                  @           `             @@                   +@                                                        
                               `           @@'                    @                                                        
                                           @ ;                    @                                                        
                                                        `         @