Tribe Design

From PSwiki
Jump to navigation Jump to search

Tribe Design

The tribe design is done using NPC Behaviors and Recipes. Tribe members are assigned tasks based on what the recipes dictates the tribe to achieve. This system uses a Recipe Manager which takes care of parsing recipes, breaking the initial recipe into subtasks and telling the npcs which action to take.

Classes

Adobe SVG Viewer plugin (for Internet Explorer) or use Firefox, Opera or Safari instead.

Members

Tribe members (both dead & alive) are kept in an array in the Tribe Class. They are all represented by the NPC class. The tribal class only has methods to attach a tribe member. For spawning new members the server (gemSupervisor & entityManager classes) and the npcclient class are responsable.

Tribe members can have different types. (Discussion needed about tribe types)

Tribe members are being kept in the 'tribe_members' mysql table.

Resources

A resource is kept in a data structure (Tribe::Resource) containing it's name, nick and quantity. The tribe class has methods for adding, modifying, storing and completely deleting resources.

Resources are being kept in the 'sc_tribe_resources' mysql table.

Memories

A memory is a location of some importance to the tribe. (E.g. a mine, a field, an enemy, etc)

A memory is kept in a data structure (Tribe::Memory) containing it's location (sector & coords), it's name and a link to an NPC (which is NULL if the memory is public to all tribe members, or != NULL if it's private to a tribe member). The tribe object has methods to add, store, modify and search memories.

Tribe members also have a memory slot for keeping it's current task location. (see bufferMemory attribute of NPC class).

Tribe memories are being kept in the 'sc_tribe_memories' mysql table.

Assets

Assets are belongings of the tribe. They can represent buildings, items or spots to be built in the future.

An asset is represented by a data structure (Tribe::Asset) containing it's location (sector & coords), it's name, it's quantity (relevant just for items) and it's type (Building Spot, Building or Item). The tribe class has methods for adding, editing and deleting assets. It also has methods for managing buildings. (e.g. Replace a building spot with the actual building after the workers built it)

Tribe assets are being kept in the 'sc_tribe_assets' mysql table.

Knowledge

Knowledge represents the information the tribe has gathered and the technologies they can use. (E.g. Ironworks, pottery, horseback riding, alphabet, math, etc)

Technically, they are just strings used as tokens to prove the tribe has acquired knowledge or not.

Knowledge is kept in an array of strings.

Tribe knowledge is being kept in the 'sc_tribe_knowledge' mysql table.

Recipe Tree Node

This class represents a node of the recipe tree describing the tribe current tasks. Each recipe tree node contains a link to it's recipe, waiting times, current requirement, current algorithm step and relationship information regarding other recipes. (just as a standard Tree, it may have parents and descendants).

RecipeTreeNodes are not being stored in any database. They are just used during runtime as an AI for tribes.

Recipe

A recipe is a set of requirements and algorithm steps regarding a task that needs to be done. Recipes can vary from simple (Gather a resource) to very complex (Build an entire civilization).

Recipes are being stored in the 'tribe_recipes' mysql table.

Sequences

Advance Sequence

Advance sequence is the heart of the Tribe system. The NPCClient will advance the brain 4 times a second. On each loop, this sequence takes care of special cases (e.g.: 0 npcs alive in tribe) and assigns tasks to idle members.

Adobe SVG Viewer plugin (for Internet Explorer) or use Firefox, Opera or Safari instead.

Setting up tribes

There are 3 main database tables that need to be populated.

  • tribes
    • Each row represents one tribe, which must have a home position/sector and a radius in which to resurrect dead members.
    • max_size sets the maximum number of members.
    • wealth_resource sets the different types of resource that a tribe can mine in order to grow and/or sustain itself. This needs more work however the most important one is wealth_resource_growth which is the default rate at which a resource will grow without any work per second.
    • reproduction_cost is the amount of resources required to reproduce.
    • tribal_recipe loads the initial recipe that sets tribe traits and loads tribe goals (recipes)
  • tribe_members
    • Each row is an association between a PID (on the server side) and a tribe.
  • tribe_recipes
    • Each row represents a recipe (name,requirements,algorithm). This table needs to be loaded in order to order tribe members what to do. Not having recipes, or requesting a recipe that does not exist will result in a termination of the npcclient.

Additionally, tables for extra tribe info need to be created:

  • sc_tribe_assets
  • sc_tribe_knowledge
  • sc_tribe_memories
  • sc_tribe_resources

Tribe day-to-day life

Tribe members are normal NPCs. They all expand a base NPCType called 'AbstractTribesman', on which each tribe adds it's own particularities (e.g. when to go to sleep, what to do when they meet a stranger, etc). Read more on NPC Scripting. The 'AbstractTribesman' contains behaviors that describe generic actions: breeding, gathering, mining, fighting, exploring and working. (trading to be added soon). These generic behaviors use some data buffers to read data from during runtime in order to execute the same behavior on different data. (different mines, different fields, different building places, etc)

Upon parsing recipes, different perceptions are fired on the tribesmen. This process simulates a working society on which a superior entity assigns tasks to the population.

Tribe death

When all the members die, then a member will be resurrected if there are 10*reproduction_cost resources available.

Runtime

Step #1 (Loading)

(executed only once, on NPCClient's startup. No further interrogation on the database should be done)

On NPCClient's startup everything is loaded into the classes.

1) The Recipe Manager loads all available recipes from mysql:'tribe_recipes' and add those in a flat array "recipes", one entry per recipe.

2) psNPCManager::LoadTribes() loads from the database all the tribes from mysql:'tribes'

3) For each tribe psNPCManager::LoadTribes() loads all the information regarding the tribe:

  • resources from mysql:'sc_tribe_resources'
  • memories from mysql:'sc_tribe_memories'
  • knowledge from mysql:'sc_tribe_knowledge'
  • assets from mysql:'sc_tribe_assets'
  • basic tribe information from mysql:'tribes' (including the ID of the tribal recipe, more details below)
  • npc's are loaded by the psNPCClient and assigned to the tribe

4) For each tribe it calls RecipeManager::AddTribe() , which parses the requirements and keeps them in the Recipe Class. (Recipe::requirements<Recipe::Requirement>)

5) Further on, each Tribal Object is linked to the Recipe Manager. (a pointer is sent and loaded into a csArray) For each tribe loaded, the Recipe Manager does the following:

  • assembles a data structure named 'TribeData'
  • links the tribal recipe belonging to this tribe to 'TribeData'
  • parses the information in the tribal recipe and assign the stats to csStrings in 'TribeData'
  • computes a tribal npctype having as parent the 'AbstractTribesman' npctype. The difference is done by adding reactions to whatever the tribe reacts to. (attacking any player nearby or simply greeting them, sleeping at day or at night, etc)

Step #2 (RunTime)

(executed once on startup and each time a recipe is completed)

1) NPCManager is ticking all the tribes with frequency TRIBE_TICK (tribe.h) and calling Advance() on each tribe

2) Each tribe searches for idle members, to assign tasks in Tribe::Advance()

3) updates the waiting time of all the TOP level recipe (the ones listed in mysql:'tribes_recipe.algorithm' as loadRecipe())

4) select the best recipe based on lowest wait time and high priority (where priority is defined level in the recipe tree, the lowest the better)

The Tribal Object selects the top-priority recipe which needs execution and sends it to the Recipe Manager.

The Recipe Manager parses the contents of the recipe: It checks for requirements. If requirements are met it proceeds with parsing the algorithm (see step #3). If requirements are not met, it pushes the Recipes which achieves the requirement on top of the tribe's recipe list. Requirement parsing can be done two ways:

  • Distributed Parsing : The parser takes the first requirement and checks it + tries to achieve it. When the same recipe gets parsed again, the parser takes the second requirement (even if the first is still not met) and tries to achieve it. This way, the parser loops through requirements and tries to achieve all in parallel.
  • Concentrated Parsing : The parser tries to achieve the first requirement on each recipe parse until it is met. After that it picks the second requirement and applies the same principle.

5) A new child of the RecipeTree is added as soon as the tribe decides that something can be executed (all requirements met). This is added to 'tribalRecipe' variable. Then the algorithm of this recipe is executed (for example percect NPC to go work), and the child is immediately removed from the tree. This mean that while the NPC is working, the tree does not contain that child anymore, so if another NPC becomes available, it will pick the NEXT requirement in line.


Example of Distributed vs Concentracted Parsing:

E.G.: We want our tribe to gain 150 of Coal, Silver, Gold and Platinum.

Using Distributed Parsing:

  • Step 1: Assign miner to Coal.
  • Step 2: Assign miner to Silver.
  • Step 3: Assign miner to Gold.
  • Step 4: Assign miner to Platinum.
  • Step 5: Assign miner to Coal.

...

Using Concentrated Parsing: (in this example we consider each step gets the tribe 1 quantity of resource)

  • Step 1: Assign miner to Coal.

...

  • Step 150: Assign miner to Coal.
  • Step 151: Assign miner to Silver.

...

Step #3 (Recipe's Algorithm)

(executed for each step the algorithm has, each time a recipe needs execution)

The Recipe has an algorithm stored as a csArray<csString>. When an algorithm needs an execution, the Recipe Manager takes each string and parses it. Depending on the rules we set, the Recipe Manager will tell the tribal object which perceptions to fire on their npcs. A complete set of algorithm and requirements functions can be found here.

(E.g.: If the recipe's algorithm require us to send 10 workers to build a town hall, the tribal object will be told to fire a "go to work" perception on 10 worker tribesman)


Mining tribe

The mining tribe is defined in tribes table with:

  • a tribal_recipe value pointing to tribe_recipe table which is defining the brain, aggressivity, growth, ...
  • a set of members inside tribe_members table, each member is flagged with a tag, example "Miner" which then be used in the selection of workers for a specific task

The Brain definition above will point to sc_npctypes table, which will most likely derive from AbstractTribesman

AbstractTribesman will define the reactions/behaviors for example

 <react event="tribe:explore"            behavior="Explore" />
 <react event="tribe:mine"               behavior="MineResource" />

During the 'Explore' behavior, tribe members will move around the map. psNPCManager::PerceptProximityLocations() is called every second, triggering a LocationPerception with "location sensed" to all NPC in range. This perception will make the NPC find the mine.

After mining from an unknown deposit, the npcclient will receive a psWorkDoneMessage telling it what his npc just mined. This function renames the former 'mine' Memory with it's real deposit name.

Two things need to happen:

1) The tribe sends a member to explore for mining locations, this happens with

 <react event="tribe:explore"            behavior="Explore" />

2) The tribe sends a members to mine for a KNOWN resource location, this happens with

 <react event="tribe:mine"               behavior="MineResource" />


Important methods:

  • psNPCManager::PerceptProximityLocations() is called every second, triggering a LocationPerception with "location sensed" to all NPC in range
  • NPCType::FirePerception() is checking if this NPC should automemorize the new locations sensed
  • Tribe::Memorize() where we add the location found to the NPC memory

The mining tribe will send his members to explore in search of resources. This is done with the Behavior "Explore" in the AbstractTribsmen NPC Type stored in sc_npctypes.