fonctions : aléatoire avec boucle

Répondre
Partager Rechercher
Bonsoir

Voilà quelques petites fonctions de rien du tout qui m'ont bien aidées, donc je me suis dit que ça pourrait aider quelqu'un d'autre.

Elle ont été faites à la base pour prendre aléatoirement un objet sur une zone, sans pour autant refaire le script à chaque changement de zone, sans se soucier du nombre d'objets de même type sur la zone, et sans mettre de variable sur un objet

Exemple : je veux prendre aléatoirement un Waypoint, mais ce waypoint doit avoir une variable X à 4 (pour faire apparaître un créature, un effet spécial, etc).

Problème N°1
: l'utilisation des fonctions GetFirstObjectInArea et GetNextObjectInArea fera que l'on tombera toujours sur le même waypoint, ce qui rend l'aléatoire inopérant . Donc il faut compter le nombre de Waypoint dans la zone et appliquer Random () ensuite avec une boucle on prend aléatoirement le waypoint (boucle de type while )

Problème N°2 : si l'on a beaucoup de WP sur la zone, et que seul un petit nombre de ces WP n'ont pas la propriété voulue, la recherche aléatoire peut durer une éternité (d'ailleurs rien qu'avec un seul WP qui n'a pas la propriété voulue il y a une chance, même infime, que la fonction renvoie toujours celui si et donc que la boucle continue indéfiniement). Du coup j'ai fait une autre fonction qui crée une boucle décalée dont le décalage sera lui aléatoire. (en gros on a une suite avec des numéros qui se suivent 1,2,3,4,5,6,7,8,9,10, et la boucle décalée scannera les objets N° 4,5,6,7,8,9,10,1,2,3 si elle est décalée de 3)..
Donc on regardera tous les objets, quel qu'ils soient. Et s'il n'existe qu'un seul qui corresponde, on le trouvera parmi une multitude.


Code PHP:

// choisi le 1er objet de la zone en excluant un type d'objet
 // fait pour compter le nombre d'objet de même type
 
object ChoiseFirstObject (object oAreaChoiseObjectint iTypeExclude)
 {
 
object oFirstObjectChoise GetFirstObjectInArea (oAreaChoiseObject);
 while (
GetObjectType (oFirstObjectChoise) == iTypeExclude)
     {
     
oFirstObjectChoise GetNextObjectInArea (oAreaChoiseObject);
     }
 return 
oFirstObjectChoise;
 } 

Code PHP:

// Compte et renvoie le nombre d'objets de type nType
  // nType : OBJECT_TYPE_CREATURE, OBJECT_TYPE_DOOR,
  // OBJECT_TYPE_WAYPOINT, OBJECT_TYPE_PLACEABLE, etc..
 
int ObjectCompteur (object oAreaint nType)
 {
 
object oFirstObject ChoiseFirstObject(oAreanType);
 
int iCompt 0;
 
object oObject GetNearestObject (nTypeoFirstObject iCompt );
 while (
oObject != OBJECT_INVALID)
     {
    
iCompt ++;
    
oObject GetNearestObject (nTypeoFirstObject ,iCompt );
     }
 
// je sais pas pourquoi mais il y en a toujours 1 de plus... 
 // peut etre que le n°0 et le n°1 sont les mêmes
 
iCompt --;
 return 
iCompt ;
 } 
Code PHP:

// prend une boucle et donne le résultat sur une boucle décalée
 // Rajoute iRandomBoucle tout en restant en dessous du max
 // sert à se servir d'une fonction aléatoire avec condition
 // sans risquer de toujours tomber toujours sur un mauvais objet
 
int GetBoucle (int iNbBoucleint iRandomBoucleint iBoucleMax)
 {
 
int iResult iRandomBoucle iNbBoucle ;
 if (
iResult iBoucleMaxiResult iResult iBoucleMax;
 return 
iResult;
 } 

donc voilà avec ces fonctions on peut prendre aléatoirement mon Waypoint qui aura une variable int X égale à 4 avec ces lignes, parmi quelques WP qui possèdent cette propriété, même s'il y a 200 WP sur la zone et seulement 2 WP qui ont une variable X à 4.

Code PHP:

 //oArea est la zone acquise avec GetArea()
 
object oFirstObject ChoiseFirstObject (oAreaOBJECT_TYPE_WAYPOINT );
 
int nRandomBcle Random (ObjectCompteur (oAreaOBJECT_TYPE_WAYPOINT)+1); // le décalage de la boucle est aléatoire
 
int nRandomBclCompt 1;
 
object oWPSpawn OBJECT_INVALID;
 
int iVar;
 while ((
oWPSpawn == OBJECT_INVALID)||(iVar != 4)
      {
      
oWPSpawn GetNearestObject (OBJECT_TYPE_WAYPOINToFirstObject,GetBoucle (nRandomBclComptnRandomBcleiDoorAleat));
      
iVarGetLocalInt (oWPSpawn"X");
      
nRandomBclCompt ++;
      } 
__________________
http://img91.imageshack.us/img91/9666/yingyangwm8jt3.gif
http://simaon.free.fr/
<font color="black"><font color="#000000"><font color="#ff8000">Gaffe à la boucle infinie, dans ta première boucle.

Code PHP:

// Choisit le 1er objet d'un type voulu dans une zone
object GetFirstObjectByTypeInArea(object oAreaint nType=OBJECT_TYPE_CREATURE)
{
    
object oLoop GetFirstObjectInArea(oArea);
    while((
GetObjectType(oLoop)!=nType) || (oLoop != OBJECT_INVALID))
    {
        
oLoop GetNextObjectInArea (oAreaChoiseObject);
    }
    return 
oLoop;
}

// Suite de la boucle, à utiliser dans le même script.
// Au cas où ça peut servir.

object GetNextObjectByTypeInArea(object oAreaint nType=OBJECT_TYPE_CREATURE)
{
    
object oLoop GetNextObjectInArea(oArea);
    while((
GetObjectType(oLoop)!=nType) || (oLoop != OBJECT_INVALID))
    {
        
oLoop GetNextObjectInArea(oArea);
    }
    return 
oLoop;

Pour ta deuxième boucle, tu peux faire plus simple en reprenant le principe de ta première boucle. Ca t'évitera de faire appel à deux boucles dans la même fonction. Par contre, c'est normal que tu comptes un objet en plus, vu que le compteur démarre à 0. Donc "GetNearestObject" compte l'objet repère aussi. Après tout il fait partie des objets recherchés... Mais ta fonction est très lourde à gérer. Il y a ta boucle personnalisée, "GetNearestObject" qui compte comme une énorme boucle avec une comparaison de distance... Mieux vaut faire au plus simple, pour rendre au final le même résultat :
Code PHP:

object GetNumObjectByTypeInArea(oAreanType=OBJECT_TYPE_CREATURE)
{
    
int nReturn 0;
    
object oLoop GetFirstObjectInArea(oArea);
    while(
oLoop != OBJECT_INVALID)
    {
        if(
GetObjectType(oLoop)==nType);
            
nReturn ++;
        
oLoop GetNextObjectInArea(oArea);
    }
    return 
nReturn;

Ta fonction finale risque également la boucle infinie. Tant que l'objet est invalide ou que la variable est différente de 4 ça tourne... C'est donc un très gros risque à prendre.

La j'ai rajouté une sécurité dans le cas où le plus proche objet du même type n'existe pas (donc la boucle ne sert à rien de continuer. En théorie ça devrait faire quasiment ce que tu cherches à faire, avec quelques boucles en moins pour alléger la sauce.
Code PHP:

//oArea est la zone acquise avec GetArea()
int nType OBJECT_TYPE_WAYPOINT;
object oBase GetFirstObjectByTypeInArea(oArea,nType);

// Là je prends le nombre d'objet du même type
// dans la même zone,
// puis je prends un nouveau repère aléatoirement;
int nMax GetNumObjectByTypeInArea(oArea,nType);
if(
nMax>1);
{
    
oBase GetNearestObject(nType,oFirstObject,Random(nMax));

    
int nNth,nVar;
    
object oLoop;
    while((
nNth <= nMax) && (nVar != 4))
    {
        
oLoop GetNearestObject(nType,oBase,nNth);
        if(
oLoop==OBJECT_INVALID)
            break;
        
nVar GetLocalInt(oLoop,"X");
        
nNth ++;
    }

Je n'ai pas testé, mais l'idée y est.
Répondre

Connectés sur ce fil

 
1 connecté (0 membre et 1 invité) Afficher la liste détaillée des connectés