Affichage des résultats 1 à 3 sur 3

Discussion: [WeiDU] Comment fonctionne la commande RANDOM de WeiDU ?

  1. #1
    Date d'inscription
    April 2011
    Localisation
    Égaré dans un vortex entre Féérune et le Royaume de Diamant Éternel
    Messages 
    4 644

    Question [WeiDU] Comment fonctionne la commande RANDOM de WeiDU ?

    En phase de développement, j'ai créé plusieurs macros et fonctions pour automatiser la création de plusieurs fichiers spécifiques. Parmi elles, une procédure permet de générer des créatures sans me soucier de leurs caractéristiques, par exemple des PNJ non recrutables, mais nécessaires pour le scénar.

    Code:
    /*-----------------------------------------------------------------------------------*
     * MACRO GW_CRE_STATS_RANDOM : Création aléatoire des caractéristiques des créatures *
     *-----------------------------------------------------------------------------------*/
    
    DEFINE_PATCH_FUNCTION ~GW_CRE_STATS_RANDOM~ 
    	RET	GW_str_random
    		GW_str_ex_random
    		GW_dex_random
    		GW_int_random
    		GW_wis_random
    		GW_con_random
    		GW_chr_random
    BEGIN
    
    	SET GW_str_random = 0
    	SET GW_str_ex_random = RANDOM (1 100)
    	SET GW_dex_random = 0
    	SET GW_int_random = 0
    	SET GW_wis_random = 0
    	SET GW_con_random = 0
    	SET GW_chr_random = 0
    	
    	PATCH_FOR_EACH random_stat IN ~GW_str_random~ ~GW_dex_random~ ~GW_con_random~ ~GW_int_random~ ~GW_wis_random~ ~GW_chr_random~ BEGIN
    		FOR (i = 0; i < 3; i += 1) BEGIN
    			SET EVALUATE_BUFFER ~%random_stat%~ += RANDOM (1 6)	// 3 x 6 = 18 !
    		END
    	END
    // exceptional strength (only for warriors with 18 strength)
    	PATCH_IF (%GW_str_random% != 18) BEGIN
    		SET GW_str_ex_random = 0
    	END ELSE BEGIN
    		PATCH_IF  (("%GW_class_lib%" STRING_CONTAINS_REGEXP "FIGHTER" != 0) && ("%GW_class_lib%" STRING_CONTAINS_REGEXP "RANGER" != 0) 
    				&& ("%GW_class_lib%" STRING_CONTAINS_REGEXP "PALADIN" != 0)) BEGIN
    			SET GW_str_ex_random = 0
    		END
    	END
    	PATCH_PRINT ~CONTROLE RANDOM STATS : random_str = %GW_str_random% - random_str_ex = %GW_str_ex_random% - random_dex = %GW_dex_random% - random_con = %GW_con_random% - random_int = %GW_int_random% - random_wis = %GW_wis_random% - random_chr = %GW_chr_random%~
    //    LPF GW_CRE_STATS_ADJUST	INT_VAR GW_str_random GW_str_ex_random GW_dex_random GW_int_random GW_wis_random GW_con_random GW_chr RET GW_str_ajust GW_str_ex_ajust GW_dex_ajust GW_int_ajust GW_wis_ajust GW_con_ajust GW_chr_ajust END // adjust statistics to match class and racial minimums, maximums and modifiers
    
    END
    Cette fonction semblait fonctionner jusqu'à ce que je m'aperçoive qu'elle générait toujours les mêmes caractéristiques à chaque installation (les valeurs pouvaient varier d'une installation à l'autre, mais étaient identiques pour toutes les créatures créées).

    Par exemple :

    CONTROLE RANDOM : random_str = 10 - random_str_ex = 0 - random_dex = 14 - random_con = 11 - random_int = 11 - random_wis = 6 - random_chr = 12

    Après avoir trituré la doc WeiDU, j'ai fini par trouver une solution en ajoutant ces lignes jaunes dans la fonction :

    Code:
    DEFINE_PATCH_FUNCTION ~GW_CRE_STATS_RANDOM~ 
    	RET	GW_str_random
    		GW_str_ex_random
    		GW_dex_random
    		GW_int_random
    		GW_wis_random
    		GW_con_random
    		GW_chr_random
    BEGIN
    
    	INNER_ACTION BEGIN
    		RANDOM_SEED null // Initialize random numbers
    	END
    	SET GW_str_random = 0
    ...
    Problème : je ne comprends pas pourquoi ça fonctionne et quelle est l'utilité de la commande RANDOM_SEED, si ce n'est qu'elle semble solutionner mon problème. Et je déteste ne pas comprendre ce que je fais.

    Alors si quelqu'un a une explication, je suis preneur.
    Dernière modification par Freddy_Gwendo ; 19/07/2015 à 17h18.
    CARPE DIEM...
    Co-modérateur de La Forge et de La Chambre des Scribes
    Moddeur qui s'arrache les cheveux...

  2. #2
    Date d'inscription
    July 2003
    Localisation
    Plaisir
    Messages 
    6 826
    La graine d'un générateur aléatoire (en réalité pseudo-aléatoire) est l'initialisation permettant d'obtenir une séquence répétable entre deux utilisations. A défaut d'un forçage par le programmeur, cette initialisation est souvent faite avec un élément fonction de l'instant initial.

    Je ne sais pas à quoi correspond null pour WeiDU mais, d'après la documentation, si ce n'est pas considéré comme un nombre, WeiDU va l'initialiser en fonction de l'heure. De sorte qu'en deux appels de ta fonction, il y a des chances que cela force la génération de séries de valeurs différentes. Dans cette hypothèse, tu pourrais parfaitement te passer de réinitialiser à null dans chaque appel de fonction, le générateur devrait continuer tranquillement à dérouler sa séquence de valeurs aléatoires, qui normalement a un cycle long.

    Dans le cas où, comme dans certains languages, null est associé au nombre 0, cela devrait même te donner systématiquement toujours la même séquence à chaque appel de fonction, toutes tes créatures ayant exactement les mêmes caractéristiques.

    Le problème que tu décris est pourtant l'inverse en l'absence de l'initialisation dans la fonction. C'est à croire que tu aurais quelque part ailleurs un appel à RANDOM_SEED entre deux appels de fonctions.

    Il faut savoir qu'un générateur aléatoire est une entité complexe et que les langages ont longtemps intégré des fonctions assez mauvaises. A titre d'exemple, le générateur aléatoire de l'Infinity Engine vis à vis des RESPONSE #n des scripts est manifestement plutôt mauvais. J'ignore si WeiDU ou le langage sur lequel il s'appuie est meilleur.
    En tout état de cause, à moins d'un sérieux bug dans WeiDU ou d'un RANDOM_SEED mal placé ailleurs dans ton code, tu ne devrais que très rarement générer les mêmes 6 caractéristiques pour 2 appels de fonction à partir de la première mouture de la fonction. Selon comment WeiDU considère null, la deuxième est encore plus risquée.
    Peut-être que tu pourrais simplement te contenter d'ajouter une initialisation au tout début de ton programme d'installation. En principe, pour une valeur donnée, cela te donnerait les mêmes caractéristiques d'une installation sur l'autre, à moins de changer l'ordre d'utilisation des RANDOM ou d'introduire de nouveaux tirages aléatoires entre deux.

    A noter qu'il existe aussi PATCH_RANDOM_SEED, de sorte que tu pourrais te passer du INNER_ACTION_BEGIN. Mais manifestement le générateur aléatoire doit être unique et utiliser l'une ou l'autre des commandes devrait avoir le même effet.
    Peu disponible
    Guide d'installation (et FAQ) de Baldur's Gate, Baldur's Gate II, Baldur's Gate Trilogy (BGT), BG1Tutu, Widescreen, BGEE
    Pensez à utiliser à la fonction Recherche pour trouver une réponse à votre question !

  3. #3
    Date d'inscription
    April 2011
    Localisation
    Égaré dans un vortex entre Féérune et le Royaume de Diamant Éternel
    Messages 
    4 644
    Je n'ai pas trouvé d'autre RANDOM_SEED dans mes tp...

    Cependant, bonne nouvelle, je viens de refaire 6 installations de 10 créatures et ça a fonctionné : des caractéristiques différentes pour chaque créature et différentes à chaque installation.

    Va comprendre !

    Par ailleurs, j'ai hérité d'un code RANDOM_SEED de mike1072 auquel je ne comprends pas grand chose :

    Code:
    // initializes the random number generator for the creature using the resource name as the default seed
    // set quasi_random to a specific string if you want multiple creatures to share the same "random" results
    DEFINE_PATCH_FUNCTION ~CRE_INIT~
      STR_VAR
        quasi_random = EVALUATE_BUFFER ~%SOURCE_RES%~
    BEGIN
      SET q_r_length = STRING_LENGTH ~%quasi_random%~
      
      PATCH_IF (q_r_length == 0) BEGIN
        PATCH_PRINT ~CRE_INIT: Please specify a valid quasi_random string; exiting function.~
      END
      ELSE BEGIN
        // calculate sum* and xor of all bytes
        SET sum = 0
        SET xor = 0
        SET j = 0
        INNER_PATCH ~%quasi_random%~ BEGIN
          FOR (i = 0; i < q_r_length; i += 1) BEGIN
            READ_BYTE i temp
            SET sum += (temp * (i + 1))
            SET xor ^^= temp << (j * 8)
            SET j += 1
            SET j = j < 4 ? j : 0
          END
        END
        SET result = (xor + sum)
        
        PATCH_RANDOM_SEED result
      END
    END
    Si ce n'est qu'il est lancé à chaque création de créature et semble être calculé sur le nom du fichier de la créature pour être certain de générer des valeurs différentes. Mais ce n'est qu'un interprétation...
    CARPE DIEM...
    Co-modérateur de La Forge et de La Chambre des Scribes
    Moddeur qui s'arrache les cheveux...

Discussions similaires

  1. [WeiDU] Utiliser la fonction CREATE avant la prochaine mise-à-jour de WeiDU
    Par Freddy_Gwendo dans le forum Programmation WeiDU
    Réponses: 1
    Dernier message: 15/02/2016, 22h18
  2. [WeiDU] Comment ajouter un objet AU SOL sur une carte ?
    Par deratiseur dans le forum Programmation WeiDU
    Réponses: 6
    Dernier message: 13/03/2015, 19h13
  3. [WeiDU] Dialogue et commande EXTERN
    Par Cocrane dans le forum Dialogues
    Réponses: 5
    Dernier message: 27/10/2014, 21h01
  4. Réponses: 5
    Dernier message: 06/08/2014, 22h10
  5. [WeiDU] La commande STRING_SET
    Par zefklop dans le forum Programmation WeiDU
    Réponses: 3
    Dernier message: 28/12/2005, 08h50

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •  

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250