Sign in to follow this  

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

This topic is 3366 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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

This topic is 3366 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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