Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

be_ai_weap.c File Reference

#include "../game/q_shared.h"
#include "l_libvar.h"
#include "l_log.h"
#include "l_memory.h"
#include "l_utils.h"
#include "l_script.h"
#include "l_precomp.h"
#include "l_struct.h"
#include "aasfile.h"
#include "../game/botlib.h"
#include "../game/be_aas.h"
#include "be_aas_funcs.h"
#include "be_interface.h"
#include "be_ai_weight.h"
#include "../game/be_ai_weap.h"

Include dependency graph for be_ai_weap.c:

Include dependency graph

Go to the source code of this file.

Data Structures

struct  bot_weaponstate_s
struct  weaponconfig_s

Defines

#define PROJECTILE_OFS(x)   (int)&(((projectileinfo_t *)0)->x)
#define WEAPON_OFS(x)   (int)&(((weaponinfo_t *)0)->x)

Typedefs

typedef bot_weaponstate_s bot_weaponstate_t
typedef weaponconfig_s weaponconfig_t

Functions

int BotAllocWeaponState (void)
int BotChooseBestFightWeapon (int weaponstate, int *inventory)
void BotFreeWeaponState (int handle)
void BotFreeWeaponWeights (int weaponstate)
void BotGetWeaponInfo (int weaponstate, int weapon, weaponinfo_t *weaponinfo)
int BotLoadWeaponWeights (int weaponstate, char *filename)
void BotResetWeaponState (int weaponstate)
int BotSetupWeaponAI (void)
void BotShutdownWeaponAI (void)
int BotValidWeaponNumber (int weaponnum)
bot_weaponstate_tBotWeaponStateFromHandle (int handle)
weaponconfig_tLoadWeaponConfig (char *filename)
int * WeaponWeightIndex (weightconfig_t *wwc, weaponconfig_t *wc)

Variables

bot_weaponstate_tbotweaponstates [MAX_CLIENTS+1]
fielddef_t projectileinfo_fields []
structdef_t projectileinfo_struct
weaponconfig_tweaponconfig
fielddef_t weaponinfo_fields []
structdef_t weaponinfo_struct


Define Documentation

#define PROJECTILE_OFS  )     (int)&(((projectileinfo_t *)0)->x)
 

Definition at line 52 of file be_ai_weap.c.

#define WEAPON_OFS  )     (int)&(((weaponinfo_t *)0)->x)
 

Definition at line 51 of file be_ai_weap.c.


Typedef Documentation

typedef struct bot_weaponstate_s bot_weaponstate_t
 

Referenced by BotAllocWeaponState(), BotChooseBestFightWeapon(), BotFreeWeaponWeights(), BotGetWeaponInfo(), BotLoadWeaponWeights(), BotResetWeaponState(), and BotWeaponStateFromHandle().

typedef struct weaponconfig_s weaponconfig_t
 

Referenced by BotChooseBestFightWeapon(), LoadWeaponConfig(), and WeaponWeightIndex().


Function Documentation

int BotAllocWeaponState void   ) 
 

Definition at line 462 of file be_ai_weap.c.

References bot_weaponstate_t, botweaponstates, GetClearedMemory(), and i.

00463 {
00464     int i;
00465 
00466     for (i = 1; i <= MAX_CLIENTS; i++)
00467     {
00468         if (!botweaponstates[i])
00469         {
00470             botweaponstates[i] = GetClearedMemory(sizeof(bot_weaponstate_t));
00471             return i;
00472         } //end if
00473     } //end for
00474     return 0;
00475 } //end of the function BotAllocWeaponState

Here is the call graph for this function:

int BotChooseBestFightWeapon int  weaponstate,
int *  inventory
 

Definition at line 404 of file be_ai_weap.c.

References bot_weaponstate_t, BotWeaponStateFromHandle(), FuzzyWeight(), i, weaponconfig_s::numweapons, weaponinfo_s::valid, weaponconfig_t, weaponconfig_s::weaponinfo, bot_weaponstate_s::weaponweightconfig, and bot_weaponstate_s::weaponweightindex.

00405 {
00406     int i, index, bestweapon;
00407     float weight, bestweight;
00408     weaponconfig_t *wc;
00409     bot_weaponstate_t *ws;
00410 
00411     ws = BotWeaponStateFromHandle(weaponstate);
00412     if (!ws) return 0;
00413     wc = weaponconfig;
00414     if (!weaponconfig) return 0;
00415 
00416     //if the bot has no weapon weight configuration
00417     if (!ws->weaponweightconfig) return 0;
00418 
00419     bestweight = 0;
00420     bestweapon = 0;
00421     for (i = 0; i < wc->numweapons; i++)
00422     {
00423         if (!wc->weaponinfo[i].valid) continue;
00424         index = ws->weaponweightindex[i];
00425         if (index < 0) continue;
00426         weight = FuzzyWeight(inventory, ws->weaponweightconfig, index);
00427         if (weight > bestweight)
00428         {
00429             bestweight = weight;
00430             bestweapon = i;
00431         } //end if
00432     } //end for
00433     return bestweapon;
00434 } //end of the function BotChooseBestFightWeapon

Here is the call graph for this function:

void BotFreeWeaponState int  handle  ) 
 

Definition at line 482 of file be_ai_weap.c.

References BotFreeWeaponWeights(), botimport, botweaponstates, FreeMemory(), and PRT_FATAL.

Referenced by BotShutdownWeaponAI().

00483 {
00484     if (handle <= 0 || handle > MAX_CLIENTS)
00485     {
00486         botimport.Print(PRT_FATAL, "move state handle %d out of range\n", handle);
00487         return;
00488     } //end if
00489     if (!botweaponstates[handle])
00490     {
00491         botimport.Print(PRT_FATAL, "invalid move state %d\n", handle);
00492         return;
00493     } //end if
00494     BotFreeWeaponWeights(handle);
00495     FreeMemory(botweaponstates[handle]);
00496     botweaponstates[handle] = NULL;
00497 } //end of the function BotFreeWeaponState

Here is the call graph for this function:

void BotFreeWeaponWeights int  weaponstate  ) 
 

Definition at line 349 of file be_ai_weap.c.

References bot_weaponstate_t, BotWeaponStateFromHandle(), FreeMemory(), FreeWeightConfig(), bot_weaponstate_s::weaponweightconfig, and bot_weaponstate_s::weaponweightindex.

Referenced by BotFreeWeaponState(), and BotLoadWeaponWeights().

00350 {
00351     bot_weaponstate_t *ws;
00352 
00353     ws = BotWeaponStateFromHandle(weaponstate);
00354     if (!ws) return;
00355     if (ws->weaponweightconfig) FreeWeightConfig(ws->weaponweightconfig);
00356     if (ws->weaponweightindex) FreeMemory(ws->weaponweightindex);
00357 } //end of the function BotFreeWeaponWeights

Here is the call graph for this function:

void BotGetWeaponInfo int  weaponstate,
int  weapon,
weaponinfo_t weaponinfo
 

Definition at line 388 of file be_ai_weap.c.

References bot_weaponstate_t, BotValidWeaponNumber(), BotWeaponStateFromHandle(), Com_Memcpy(), weaponconfig, weaponconfig_s::weaponinfo, and weaponinfo_t.

00389 {
00390     bot_weaponstate_t *ws;
00391 
00392     if (!BotValidWeaponNumber(weapon)) return;
00393     ws = BotWeaponStateFromHandle(weaponstate);
00394     if (!ws) return;
00395     if (!weaponconfig) return;
00396     Com_Memcpy(weaponinfo, &weaponconfig->weaponinfo[weapon], sizeof(weaponinfo_t));
00397 } //end of the function BotGetWeaponInfo

Here is the call graph for this function:

int BotLoadWeaponWeights int  weaponstate,
char *  filename
 

Definition at line 364 of file be_ai_weap.c.

References bot_weaponstate_t, BotFreeWeaponWeights(), botimport, BotWeaponStateFromHandle(), PRT_FATAL, ReadWeightConfig(), weaponconfig, bot_weaponstate_s::weaponweightconfig, bot_weaponstate_s::weaponweightindex, and WeaponWeightIndex().

00365 {
00366     bot_weaponstate_t *ws;
00367 
00368     ws = BotWeaponStateFromHandle(weaponstate);
00369     if (!ws) return BLERR_CANNOTLOADWEAPONWEIGHTS;
00370     BotFreeWeaponWeights(weaponstate);
00371     //
00372     ws->weaponweightconfig = ReadWeightConfig(filename);
00373     if (!ws->weaponweightconfig)
00374     {
00375         botimport.Print(PRT_FATAL, "couldn't load weapon config %s\n", filename);
00376         return BLERR_CANNOTLOADWEAPONWEIGHTS;
00377     } //end if
00378     if (!weaponconfig) return BLERR_CANNOTLOADWEAPONCONFIG;
00379     ws->weaponweightindex = WeaponWeightIndex(ws->weaponweightconfig, weaponconfig);
00380     return BLERR_NOERROR;
00381 } //end of the function BotLoadWeaponWeights

Here is the call graph for this function:

void BotResetWeaponState int  weaponstate  ) 
 

Definition at line 441 of file be_ai_weap.c.

References bot_weaponstate_t, BotWeaponStateFromHandle(), bot_weaponstate_s::weaponweightconfig, and bot_weaponstate_s::weaponweightindex.

00442 {
00443     struct weightconfig_s *weaponweightconfig;
00444     int *weaponweightindex;
00445     bot_weaponstate_t *ws;
00446 
00447     ws = BotWeaponStateFromHandle(weaponstate);
00448     if (!ws) return;
00449     weaponweightconfig = ws->weaponweightconfig;
00450     weaponweightindex = ws->weaponweightindex;
00451 
00452     //Com_Memset(ws, 0, sizeof(bot_weaponstate_t));
00453     ws->weaponweightconfig = weaponweightconfig;
00454     ws->weaponweightindex = weaponweightindex;
00455 } //end of the function BotResetWeaponState

Here is the call graph for this function:

int BotSetupWeaponAI void   ) 
 

Definition at line 504 of file be_ai_weap.c.

References botimport, file, LibVarString(), LoadWeaponConfig(), PRT_FATAL, and weaponconfig.

Referenced by Export_BotLibSetup().

00505 {
00506     char *file;
00507 
00508     file = LibVarString("weaponconfig", "weapons.c");
00509     weaponconfig = LoadWeaponConfig(file);
00510     if (!weaponconfig)
00511     {
00512         botimport.Print(PRT_FATAL, "couldn't load the weapon config\n");
00513         return BLERR_CANNOTLOADWEAPONCONFIG;
00514     } //end if
00515 
00516 #ifdef DEBUG_AI_WEAP
00517     DumpWeaponConfig(weaponconfig);
00518 #endif //DEBUG_AI_WEAP
00519     //
00520     return BLERR_NOERROR;
00521 } //end of the function BotSetupWeaponAI

Here is the call graph for this function:

void BotShutdownWeaponAI void   ) 
 

Definition at line 528 of file be_ai_weap.c.

References BotFreeWeaponState(), botweaponstates, FreeMemory(), i, and weaponconfig.

Referenced by Export_BotLibShutdown().

00529 {
00530     int i;
00531 
00532     if (weaponconfig) FreeMemory(weaponconfig);
00533     weaponconfig = NULL;
00534 
00535     for (i = 1; i <= MAX_CLIENTS; i++)
00536     {
00537         if (botweaponstates[i])
00538         {
00539             BotFreeWeaponState(i);
00540         } //end if
00541     } //end for
00542 } //end of the function BotShutdownWeaponAI

Here is the call graph for this function:

int BotValidWeaponNumber int  weaponnum  ) 
 

Definition at line 137 of file be_ai_weap.c.

References botimport, weaponconfig_s::numweapons, PRT_ERROR, and weaponconfig.

Referenced by BotGetWeaponInfo().

00138 {
00139     if (weaponnum <= 0 || weaponnum > weaponconfig->numweapons)
00140     {
00141         botimport.Print(PRT_ERROR, "weapon number out of range\n");
00142         return qfalse;
00143     } //end if
00144     return qtrue;
00145 } //end of the function BotValidWeaponNumber

bot_weaponstate_t* BotWeaponStateFromHandle int  handle  ) 
 

Definition at line 152 of file be_ai_weap.c.

References bot_weaponstate_t, botimport, botweaponstates, and PRT_FATAL.

Referenced by BotChooseBestFightWeapon(), BotFreeWeaponWeights(), BotGetWeaponInfo(), BotLoadWeaponWeights(), and BotResetWeaponState().

00153 {
00154     if (handle <= 0 || handle > MAX_CLIENTS)
00155     {
00156         botimport.Print(PRT_FATAL, "move state handle %d out of range\n", handle);
00157         return NULL;
00158     } //end if
00159     if (!botweaponstates[handle])
00160     {
00161         botimport.Print(PRT_FATAL, "invalid move state %d\n", handle);
00162         return NULL;
00163     } //end if
00164     return botweaponstates[handle];
00165 } //end of the function BotWeaponStateFromHandle

weaponconfig_t* LoadWeaponConfig char *  filename  ) 
 

Definition at line 198 of file be_ai_weap.c.

References BOTFILESBASEFOLDER, botimport, Com_Memcpy(), Com_Memset(), FreeMemory(), FreeSource(), GetClearedHunkMemory(), i, j, LibVarSet(), LibVarValue(), LoadSourceFile(), MAX_PATH, projectileinfo_s::name, weaponinfo_s::name, weaponinfo_s::number, weaponconfig_s::numprojectiles, weaponconfig_s::numweapons, PC_ReadToken(), PC_SetBaseFolder(), weaponinfo_s::proj, weaponinfo_s::projectile, weaponconfig_s::projectileinfo, projectileinfo_struct, projectileinfo_t, PRT_ERROR, PRT_MESSAGE, PRT_WARNING, ReadStructure(), source, source_t, strcmp(), token_s::string, strncpy(), token, token_t, weaponinfo_s::valid, weaponconfig_t, weaponconfig_s::weaponinfo, weaponinfo_struct, and weaponinfo_t.

Referenced by BotSetupWeaponAI().

00199 {
00200     int max_weaponinfo, max_projectileinfo;
00201     token_t token;
00202     char path[MAX_PATH];
00203     int i, j;
00204     source_t *source;
00205     weaponconfig_t *wc;
00206     weaponinfo_t weaponinfo;
00207 
00208     max_weaponinfo = (int) LibVarValue("max_weaponinfo", "32");
00209     if (max_weaponinfo < 0)
00210     {
00211         botimport.Print(PRT_ERROR, "max_weaponinfo = %d\n", max_weaponinfo);
00212         max_weaponinfo = 32;
00213         LibVarSet("max_weaponinfo", "32");
00214     } //end if
00215     max_projectileinfo = (int) LibVarValue("max_projectileinfo", "32");
00216     if (max_projectileinfo < 0)
00217     {
00218         botimport.Print(PRT_ERROR, "max_projectileinfo = %d\n", max_projectileinfo);
00219         max_projectileinfo = 32;
00220         LibVarSet("max_projectileinfo", "32");
00221     } //end if
00222     strncpy(path, filename, MAX_PATH);
00223     PC_SetBaseFolder(BOTFILESBASEFOLDER);
00224     source = LoadSourceFile(path);
00225     if (!source)
00226     {
00227         botimport.Print(PRT_ERROR, "counldn't load %s\n", path);
00228         return NULL;
00229     } //end if
00230     //initialize weapon config
00231     wc = (weaponconfig_t *) GetClearedHunkMemory(sizeof(weaponconfig_t) +
00232                                         max_weaponinfo * sizeof(weaponinfo_t) +
00233                                         max_projectileinfo * sizeof(projectileinfo_t));
00234     wc->weaponinfo = (weaponinfo_t *) ((char *) wc + sizeof(weaponconfig_t));
00235     wc->projectileinfo = (projectileinfo_t *) ((char *) wc->weaponinfo +
00236                                         max_weaponinfo * sizeof(weaponinfo_t));
00237     wc->numweapons = max_weaponinfo;
00238     wc->numprojectiles = 0;
00239     //parse the source file
00240     while(PC_ReadToken(source, &token))
00241     {
00242         if (!strcmp(token.string, "weaponinfo"))
00243         {
00244             Com_Memset(&weaponinfo, 0, sizeof(weaponinfo_t));
00245             if (!ReadStructure(source, &weaponinfo_struct, (char *) &weaponinfo))
00246             {
00247                 FreeMemory(wc);
00248                 FreeSource(source);
00249                 return NULL;
00250             } //end if
00251             if (weaponinfo.number < 0 || weaponinfo.number >= max_weaponinfo)
00252             {
00253                 botimport.Print(PRT_ERROR, "weapon info number %d out of range in %s\n", weaponinfo.number, path);
00254                 FreeMemory(wc);
00255                 FreeSource(source);
00256                 return NULL;
00257             } //end if
00258             Com_Memcpy(&wc->weaponinfo[weaponinfo.number], &weaponinfo, sizeof(weaponinfo_t));
00259             wc->weaponinfo[weaponinfo.number].valid = qtrue;
00260         } //end if
00261         else if (!strcmp(token.string, "projectileinfo"))
00262         {
00263             if (wc->numprojectiles >= max_projectileinfo)
00264             {
00265                 botimport.Print(PRT_ERROR, "more than %d projectiles defined in %s\n", max_projectileinfo, path);
00266                 FreeMemory(wc);
00267                 FreeSource(source);
00268                 return NULL;
00269             } //end if
00270             Com_Memset(&wc->projectileinfo[wc->numprojectiles], 0, sizeof(projectileinfo_t));
00271             if (!ReadStructure(source, &projectileinfo_struct, (char *) &wc->projectileinfo[wc->numprojectiles]))
00272             {
00273                 FreeMemory(wc);
00274                 FreeSource(source);
00275                 return NULL;
00276             } //end if
00277             wc->numprojectiles++;
00278         } //end if
00279         else
00280         {
00281             botimport.Print(PRT_ERROR, "unknown definition %s in %s\n", token.string, path);
00282             FreeMemory(wc);
00283             FreeSource(source);
00284             return NULL;
00285         } //end else
00286     } //end while
00287     FreeSource(source);
00288     //fix up weapons
00289     for (i = 0; i < wc->numweapons; i++)
00290     {
00291         if (!wc->weaponinfo[i].valid) continue;
00292         if (!wc->weaponinfo[i].name[0])
00293         {
00294             botimport.Print(PRT_ERROR, "weapon %d has no name in %s\n", i, path);
00295             FreeMemory(wc);
00296             return NULL;
00297         } //end if
00298         if (!wc->weaponinfo[i].projectile[0])
00299         {
00300             botimport.Print(PRT_ERROR, "weapon %s has no projectile in %s\n", wc->weaponinfo[i].name, path);
00301             FreeMemory(wc);
00302             return NULL;
00303         } //end if
00304         //find the projectile info and copy it to the weapon info
00305         for (j = 0; j < wc->numprojectiles; j++)
00306         {
00307             if (!strcmp(wc->projectileinfo[j].name, wc->weaponinfo[i].projectile))
00308             {
00309                 Com_Memcpy(&wc->weaponinfo[i].proj, &wc->projectileinfo[j], sizeof(projectileinfo_t));
00310                 break;
00311             } //end if
00312         } //end for
00313         if (j == wc->numprojectiles)
00314         {
00315             botimport.Print(PRT_ERROR, "weapon %s uses undefined projectile in %s\n", wc->weaponinfo[i].name, path);
00316             FreeMemory(wc);
00317             return NULL;
00318         } //end if
00319     } //end for
00320     if (!wc->numweapons) botimport.Print(PRT_WARNING, "no weapon info loaded\n");
00321     botimport.Print(PRT_MESSAGE, "loaded %s\n", path);
00322     return wc;
00323 } //end of the function LoadWeaponConfig

Here is the call graph for this function:

int* WeaponWeightIndex weightconfig_t wwc,
weaponconfig_t wc
 

Definition at line 330 of file be_ai_weap.c.

References FindFuzzyWeight(), GetClearedMemory(), i, weaponinfo_s::name, weaponconfig_s::numweapons, weaponconfig_t, weaponconfig_s::weaponinfo, and weightconfig_t.

Referenced by BotLoadWeaponWeights().

00331 {
00332     int *index, i;
00333 
00334     //initialize item weight index
00335     index = (int *) GetClearedMemory(sizeof(int) * wc->numweapons);
00336 
00337     for (i = 0; i < wc->numweapons; i++)
00338     {
00339         index[i] = FindFuzzyWeight(wwc, wc->weaponinfo[i].name);
00340     } //end for
00341     return index;
00342 } //end of the function WeaponWeightIndex

Here is the call graph for this function:


Variable Documentation

bot_weaponstate_t* botweaponstates[MAX_CLIENTS+1] [static]
 

Definition at line 128 of file be_ai_weap.c.

Referenced by BotAllocWeaponState(), BotFreeWeaponState(), BotShutdownWeaponAI(), and BotWeaponStateFromHandle().

fielddef_t projectileinfo_fields[] [static]
 

Initial value:

{
{"name", PROJECTILE_OFS(name), FT_STRING},                  
{"model", WEAPON_OFS(model), FT_STRING},                        
{"flags", PROJECTILE_OFS(flags), FT_INT},                       
{"gravity", PROJECTILE_OFS(gravity), FT_FLOAT},             
{"damage", PROJECTILE_OFS(damage), FT_INT},                 
{"radius", PROJECTILE_OFS(radius), FT_FLOAT},               
{"visdamage", PROJECTILE_OFS(visdamage), FT_INT},           
{"damagetype", PROJECTILE_OFS(damagetype), FT_INT},     
{"healthinc", PROJECTILE_OFS(healthinc), FT_INT},           
{"push", PROJECTILE_OFS(push), FT_FLOAT},                       
{"detonation", PROJECTILE_OFS(detonation), FT_FLOAT},       
{"bounce", PROJECTILE_OFS(bounce), FT_FLOAT},               
{"bouncefric", PROJECTILE_OFS(bouncefric), FT_FLOAT},   
{"bouncestop", PROJECTILE_OFS(bouncestop), FT_FLOAT},       

{NULL, 0, 0, 0}
}

Definition at line 83 of file be_ai_weap.c.

structdef_t projectileinfo_struct [static]
 

Initial value:

{
    sizeof(projectileinfo_t), projectileinfo_fields
}

Definition at line 107 of file be_ai_weap.c.

Referenced by LoadWeaponConfig().

weaponconfig_t* weaponconfig [static]
 

Definition at line 129 of file be_ai_weap.c.

Referenced by BotGetWeaponInfo(), BotLoadWeaponWeights(), BotSetupWeaponAI(), BotShutdownWeaponAI(), and BotValidWeaponNumber().

fielddef_t weaponinfo_fields[] [static]
 

Initial value:

{
{"number", WEAPON_OFS(number), FT_INT},                     
{"name", WEAPON_OFS(name), FT_STRING},                          
{"level", WEAPON_OFS(level), FT_INT},
{"model", WEAPON_OFS(model), FT_STRING},                        
{"weaponindex", WEAPON_OFS(weaponindex), FT_INT},           
{"flags", WEAPON_OFS(flags), FT_INT},                           
{"projectile", WEAPON_OFS(projectile), FT_STRING},          
{"numprojectiles", WEAPON_OFS(numprojectiles), FT_INT}, 
{"hspread", WEAPON_OFS(hspread), FT_FLOAT},                 
{"vspread", WEAPON_OFS(vspread), FT_FLOAT},                 
{"speed", WEAPON_OFS(speed), FT_FLOAT},                     
{"acceleration", WEAPON_OFS(acceleration), FT_FLOAT},       
{"recoil", WEAPON_OFS(recoil), FT_FLOAT|FT_ARRAY, 3},       
{"offset", WEAPON_OFS(offset), FT_FLOAT|FT_ARRAY, 3},       
{"angleoffset", WEAPON_OFS(angleoffset), FT_FLOAT|FT_ARRAY, 3},
{"extrazvelocity", WEAPON_OFS(extrazvelocity), FT_FLOAT},
{"ammoamount", WEAPON_OFS(ammoamount), FT_INT},             
{"ammoindex", WEAPON_OFS(ammoindex), FT_INT},               
{"activate", WEAPON_OFS(activate), FT_FLOAT},               
{"reload", WEAPON_OFS(reload), FT_FLOAT},                       
{"spinup", WEAPON_OFS(spinup), FT_FLOAT},                       
{"spindown", WEAPON_OFS(spindown), FT_FLOAT},               
{NULL, 0, 0, 0}
}

Definition at line 55 of file be_ai_weap.c.

structdef_t weaponinfo_struct [static]
 

Initial value:

{
    sizeof(weaponinfo_t), weaponinfo_fields
}

Definition at line 103 of file be_ai_weap.c.

Referenced by LoadWeaponConfig().


Generated on Thu Aug 25 12:42:05 2005 for Quake III Arena by  doxygen 1.3.9.1