[C++] Tracking Game "Affinities/Allegiences"

Started by
4 comments, last by Zahlman 15 years, 6 months ago
In the god-game I'm currently working on, each player starts as a vague elemental force, and works their way up to become a Deity of a specific Realm(War, Storms, Time, etc), gaining power by attaining worshippers through the use of miracles. Miracles are performed by gaining Elements(one for each possible Realm). Using a single Storm Element might cause a gust of wind, while using four at the same time might allow you to send a bolt of lightning at a target mortal. I want Players to gain access to Elements through a weighted-chance mechanic. Once enough prayer-power has built up, they gain a new Element...at the start of the game, the Element could be anything, but once the player has defined themselves as a God of Forests for example(by casting a majority of Forest miracles) they should be increasingly likely to attain Forest Elements. Only caveat is that there should always be at least SOME chance of gaining an Element of a neglected Realm. I'm looking for a nice, efficient technique to keep track of 21 different affinities, allowing for random selection between them as they grow/shrink. ... Current Stop-Gap method -> The only method I can think of for now is by utilizing a string for each player than contains characters representing each affinity. I.e. "abcdefghijklmnopqrstuaaaabbbbccccdddd...etc" Here, each letter pertains to a different realm, and each letter occurs five times. The first 21 characters cannot be changed(allowing the above caveat), but performing a single Winter miracle causes a random character beyond that point to be changed to "o" (where "o" represents the Winter Realm). Larger miracles can replace more characters. Then each time a new Element is gained, a random character is selected from the string to determine the Element's Realm. It works, but it doesn't seem very pretty, and I was wondering if there was a more efficient method that I might have overlooked. Any thoughts?
Advertisement
Well i don't know of a better way but you don't specifically have to use letters you know. To make it easier to read, you could define different char values:
enum Realm {    WINTER = 0x4F,  // ASCII value for 'O'    ...};

Of course, you don't have to use the same char value as 'O'.
[Window Detective] - Windows UI spy utility for programmers
You could have a vector<int> which has the same number of elements as factions. You then increment the appropriate faction when ever you cast a spell from it, while keeping track of the total number of increments, B. Then when you are to get a new ability you generate a random number from 0-B and count off through the vector to see the faction you get a spell from.

small example if I wasn't clear:

vec[0] = 13
vec[1] = 30
vec[2] = 29
vec[3] = 2
total = 74
rand(74) = 45;

45 > vec[0]....45 > vec[0]+vec[1]... 45 < vec[0]+vec[1]+vec[2].

so you would get a spell from the faction represented by vec[2].
The formal name for vs322's approach is fitness proportionate selection, also known as 'roulette' wheel selection.
Quote:Original post by Kylotan
The formal name for vs322's approach is fitness proportionate selection, also known as 'roulette' wheel selection.


Yeah I should have known. It was too simple and useful for it not to have been implemented, and named, already. Well thanks for the info.

[Edited by - vs322 on September 23, 2008 6:25:47 AM]
To make the binary chop work, store a vector of partial sums, and then use a binary search to figure out which option to select.

Something vaguely like:

class ElementSelector {  std::vector<int> affinity_fitness;  public:  ElementSelector(): affinity_fitness(21, 0) {    for (int i = 0; i < 21; ++i) {      adjust_affinity(i, 5);    }  }  void adjust_affinity(int which, int howMuch) {    for (int i = which; i < 21; ++i) {      affinity_fitness += howMuch;    }  }  int operator()() {    return std::distance(      affinity_fitness.begin(),      std::lower_bound(affinity_fitness.begin(), affinity_fitness.end(),                       (rand() % affinity_fitness.back()) + 1)    );  }};

This topic is closed to new replies.

Advertisement