Sign in to follow this  
ChaosFollowing

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

Recommended Posts

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?

Share this post


Link to post
Share on other sites
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'.

Share this post


Link to post
Share on other sites
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].

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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[i] += howMuch;
}
}

int operator()() {
return std::distance(
affinity_fitness.begin(),
std::lower_bound(affinity_fitness.begin(), affinity_fitness.end(),
(rand() % affinity_fitness.back()) + 1)
);
}
};

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this