Scripting help: Find me a woman!

Started by Nine Toes, Mon 25/05/2009 00:26:21

Previous topic - Next topic

Nine Toes

I'm looking for some help with how to script something - I've looked through the manual, but I'm not even sure AGS has a command for something like this.  I'm not even sure how to properly explain what I'm trying to do, but...

I've got a struct+array of variables.  Like this, for example:
Code: ags

struct Characteristics {
  bool gender; //"0" or "false" for female, "1" or "true" for male
  //etc... (the rest of the variables aren't important)
};

Characteristics people[100];


Then I use this struct+array in conjunction with all of the characters in the game:
Code: ags

function game start {
people[cJohn.ID].gender = true;
people[cMary.ID].gender = false;
people[cJennifer.ID].gender = false;
people[cMathew.ID].gender = true;
people[cDavid.ID].gender = true;
// etc...
}

You get the idea, right?

Now, I'm trying to script a function that will cycle through all of those variables, and pick out only one that meets a certain condition, something like this:
Code: ags

function pick_a_female (int random_character) {
  if (people[random_character].gender != false) {
    random_character = Random(99);
  }
}


Then I would use the function like this:
Code: ags

Character[pick_a_female(Random(99))].changeroom(2, 200, 200);

So, as you see, if the function doesn't at first pick a "female" character, then it will cycle through it again once more to try and find another character that is "female".

I'm pretty sure this script would work for the most part.  However, what if (by luck of the draw) the function picks a  "male"? (Lets say that out of the 100 characters in the game, only 25 of them are female.)  I could pop a few more "if" statements into the function to avoid that, but I'm looking for a way to keep the script to a minimum, in addition to looking for a definitive way to pick out the right variable.  I've had a quite long break from AGS, so my scripting skills have atrophied some - If anyone has a better idea how to do this, I'd like to hear it.

Any ideas?
Watch, I just killed this topic...

Khris

#1
This should work:

Code: ags
int pick_gender(bool male) {
  int ran;
  while(true) {
    ran = random(99);
    if (people[ran].gender == male) return ran;
  }
}


Now call
  character[pick_gender(false)].ChangeRoom(2, 200, 200);
Btw, it might be a good idea to change the struct member from ".gender" to ".male" so its value fits the name.

Snarky

The easiest thing is something like this:

Code: ags
function pick_a_female(int arraySize)
{
   int index = Random(arraySize-1)
   while(people[index].gender != false)
   {
      index = Random(arraySize-1);
   }
   return i;
}

...

Character[pick_a_female(100)].changeroom(2, 200, 200);



This works as long as you know for sure that there actually are any women in people[]. (Else it goes into an infinite loop.) But it can get pretty slow if there are few women in the array (it keeps trying people at random until it hits a woman). There are other things you can do, but I'd simply make another array for just the women, and pick a random person from there.

Nine Toes

Snarky; I plugged your script into mine, and it works fantastic.  Thank you very much.  I haven't experienced any slowdown at all (the array isn't actually that big... yet).  At first, I was going to make one array for the men, and one for the women to keep everything simple, however the reason why I didn't decide to go that route is because... well, there's a possibility that some of the men could turn into women. (Don't ask. :p)

KhrisMUC; I didn't try your script because I didn't understand it - in the first line, is "int pick_gender();" supposed to "function pick_gender();"?  Also, instead of changing the struct member from ".gender" to ".male", I just did this:
Code: ags

#define MALE 1
#define FEMALE 0

people[cJohn.ID].gender = MALE;
people[cMary.ID].gender = FEMALE;
Watch, I just killed this topic...

monkey0506

Regarding the int you were asking about Nine Toes, the function keyword is internally just defined as an int:

Code: ags
#define function int


The format of a function is:

Code: ags
return_type function_name([parameter1[, parameter2[, ...]]]) {
}


The return_type can be any of the basic data types, a pointer to one of the built-in complex types (Character*, GUI*, etc.), or an enum. What the return_type actually does is specify what type of data the function is going to return back to the user. So

Code: ags
int somefunc() {
}

Tells us that somefunc is going to return an int value which could then be assigned into a variable. Say for example you wanted to create a function that returned a String:

Code: ags
String GetIntroString() {
  return String.Format("Hello, my name is %s.", player.Name);
}


Then you could call:

Code: ags
player.Say(GetIntroString());


Which is a horrifically bad example but I couldn't think of anything ATM. The point is the function actually returns a value. That is, it gets replaced with that String value.

The only advantages to using the function keyword are:

1. It's easier for programming newbies.
2. It allows you to abort the function without returning anything.

The second point here could also be accomplished by using a return_type of void instead:

Code: ags
void returnNothing(int A, int B) {
  if (A == B) return; // abort the function
  // do some stuff here
}


Other than that you may also want to look into the manual entry on enums as your gender variable would be a good place to use one.

SMF spam blocked by CleanTalk