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

be_aas_route.c

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 ===========================================================================
00021 */
00022 
00023 /*****************************************************************************
00024  * name:        be_aas_route.c
00025  *
00026  * desc:        AAS
00027  *
00028  * $Archive: /MissionPack/code/botlib/be_aas_route.c $
00029  *
00030  *****************************************************************************/
00031 
00032 #include "../game/q_shared.h"
00033 #include "l_utils.h"
00034 #include "l_memory.h"
00035 #include "l_log.h"
00036 #include "l_crc.h"
00037 #include "l_libvar.h"
00038 #include "l_script.h"
00039 #include "l_precomp.h"
00040 #include "l_struct.h"
00041 #include "aasfile.h"
00042 #include "../game/botlib.h"
00043 #include "../game/be_aas.h"
00044 #include "be_aas_funcs.h"
00045 #include "be_interface.h"
00046 #include "be_aas_def.h"
00047 
00048 #define ROUTING_DEBUG
00049 
00050 //travel time in hundreths of a second = distance * 100 / speed
00051 #define DISTANCEFACTOR_CROUCH       1.3f        //crouch speed = 100
00052 #define DISTANCEFACTOR_SWIM         1       //should be 0.66, swim speed = 150
00053 #define DISTANCEFACTOR_WALK         0.33f   //walk speed = 300
00054 
00055 //cache refresh time
00056 #define CACHE_REFRESHTIME       15.0f   //15 seconds refresh time
00057 
00058 //maximum number of routing updates each frame
00059 #define MAX_FRAMEROUTINGUPDATES     10
00060 
00061 
00062 /*
00063 
00064   area routing cache:
00065   stores the distances within one cluster to a specific goal area
00066   this goal area is in this same cluster and could be a cluster portal
00067   for every cluster there's a list with routing cache for every area
00068   in that cluster (including the portals of that cluster)
00069   area cache stores aasworld.clusters[?].numreachabilityareas travel times
00070 
00071   portal routing cache:
00072   stores the distances of all portals to a specific goal area
00073   this goal area could be in any cluster and could also be a cluster portal
00074   for every area (aasworld.numareas) the portal cache stores
00075   aasworld.numportals travel times
00076 
00077 */
00078 
00079 #ifdef ROUTING_DEBUG
00080 int numareacacheupdates;
00081 int numportalcacheupdates;
00082 #endif //ROUTING_DEBUG
00083 
00084 int routingcachesize;
00085 int max_routingcachesize;
00086 
00087 //===========================================================================
00088 //
00089 // Parameter:           -
00090 // Returns:             -
00091 // Changes Globals:     -
00092 //===========================================================================
00093 #ifdef ROUTING_DEBUG
00094 void AAS_RoutingInfo(void)
00095 {
00096     botimport.Print(PRT_MESSAGE, "%d area cache updates\n", numareacacheupdates);
00097     botimport.Print(PRT_MESSAGE, "%d portal cache updates\n", numportalcacheupdates);
00098     botimport.Print(PRT_MESSAGE, "%d bytes routing cache\n", routingcachesize);
00099 } //end of the function AAS_RoutingInfo
00100 #endif //ROUTING_DEBUG
00101 //===========================================================================
00102 // returns the number of the area in the cluster
00103 // assumes the given area is in the given cluster or a portal of the cluster
00104 //
00105 // Parameter:           -
00106 // Returns:             -
00107 // Changes Globals:     -
00108 //===========================================================================
00109 __inline int AAS_ClusterAreaNum(int cluster, int areanum)
00110 {
00111     int side, areacluster;
00112 
00113     areacluster = aasworld.areasettings[areanum].cluster;
00114     if (areacluster > 0) return aasworld.areasettings[areanum].clusterareanum;
00115     else
00116     {
00117 /*#ifdef ROUTING_DEBUG
00118         if (aasworld.portals[-areacluster].frontcluster != cluster &&
00119                 aasworld.portals[-areacluster].backcluster != cluster)
00120         {
00121             botimport.Print(PRT_ERROR, "portal %d: does not belong to cluster %d\n"
00122                                             , -areacluster, cluster);
00123         } //end if
00124 #endif //ROUTING_DEBUG*/
00125         side = aasworld.portals[-areacluster].frontcluster != cluster;
00126         return aasworld.portals[-areacluster].clusterareanum[side];
00127     } //end else
00128 } //end of the function AAS_ClusterAreaNum
00129 //===========================================================================
00130 //
00131 // Parameter:           -
00132 // Returns:             -
00133 // Changes Globals:     -
00134 //===========================================================================
00135 void AAS_InitTravelFlagFromType(void)
00136 {
00137     int i;
00138 
00139     for (i = 0; i < MAX_TRAVELTYPES; i++)
00140     {
00141         aasworld.travelflagfortype[i] = TFL_INVALID;
00142     } //end for
00143     aasworld.travelflagfortype[TRAVEL_INVALID] = TFL_INVALID;
00144     aasworld.travelflagfortype[TRAVEL_WALK] = TFL_WALK;
00145     aasworld.travelflagfortype[TRAVEL_CROUCH] = TFL_CROUCH;
00146     aasworld.travelflagfortype[TRAVEL_BARRIERJUMP] = TFL_BARRIERJUMP;
00147     aasworld.travelflagfortype[TRAVEL_JUMP] = TFL_JUMP;
00148     aasworld.travelflagfortype[TRAVEL_LADDER] = TFL_LADDER;
00149     aasworld.travelflagfortype[TRAVEL_WALKOFFLEDGE] = TFL_WALKOFFLEDGE;
00150     aasworld.travelflagfortype[TRAVEL_SWIM] = TFL_SWIM;
00151     aasworld.travelflagfortype[TRAVEL_WATERJUMP] = TFL_WATERJUMP;
00152     aasworld.travelflagfortype[TRAVEL_TELEPORT] = TFL_TELEPORT;
00153     aasworld.travelflagfortype[TRAVEL_ELEVATOR] = TFL_ELEVATOR;
00154     aasworld.travelflagfortype[TRAVEL_ROCKETJUMP] = TFL_ROCKETJUMP;
00155     aasworld.travelflagfortype[TRAVEL_BFGJUMP] = TFL_BFGJUMP;
00156     aasworld.travelflagfortype[TRAVEL_GRAPPLEHOOK] = TFL_GRAPPLEHOOK;
00157     aasworld.travelflagfortype[TRAVEL_DOUBLEJUMP] = TFL_DOUBLEJUMP;
00158     aasworld.travelflagfortype[TRAVEL_RAMPJUMP] = TFL_RAMPJUMP;
00159     aasworld.travelflagfortype[TRAVEL_STRAFEJUMP] = TFL_STRAFEJUMP;
00160     aasworld.travelflagfortype[TRAVEL_JUMPPAD] = TFL_JUMPPAD;
00161     aasworld.travelflagfortype[TRAVEL_FUNCBOB] = TFL_FUNCBOB;
00162 } //end of the function AAS_InitTravelFlagFromType
00163 //===========================================================================
00164 //
00165 // Parameter:           -
00166 // Returns:             -
00167 // Changes Globals:     -
00168 //===========================================================================
00169 __inline int AAS_TravelFlagForType_inline(int traveltype)
00170 {
00171     int tfl;
00172 
00173     tfl = 0;
00174     if (tfl & TRAVELFLAG_NOTTEAM1)
00175         tfl |= TFL_NOTTEAM1;
00176     if (tfl & TRAVELFLAG_NOTTEAM2)
00177         tfl |= TFL_NOTTEAM2;
00178     traveltype &= TRAVELTYPE_MASK;
00179     if (traveltype < 0 || traveltype >= MAX_TRAVELTYPES)
00180         return TFL_INVALID;
00181     tfl |= aasworld.travelflagfortype[traveltype];
00182     return tfl;
00183 } //end of the function AAS_TravelFlagForType_inline
00184 //===========================================================================
00185 //
00186 // Parameter:           -
00187 // Returns:             -
00188 // Changes Globals:     -
00189 //===========================================================================
00190 int AAS_TravelFlagForType(int traveltype)
00191 {
00192     return AAS_TravelFlagForType_inline(traveltype);
00193 } //end of the function AAS_TravelFlagForType_inline
00194 //===========================================================================
00195 //
00196 // Parameter:           -
00197 // Returns:             -
00198 // Changes Globals:     -
00199 //===========================================================================
00200 void AAS_UnlinkCache(aas_routingcache_t *cache)
00201 {
00202     if (cache->time_next) cache->time_next->time_prev = cache->time_prev;
00203     else aasworld.newestcache = cache->time_prev;
00204     if (cache->time_prev) cache->time_prev->time_next = cache->time_next;
00205     else aasworld.oldestcache = cache->time_next;
00206     cache->time_next = NULL;
00207     cache->time_prev = NULL;
00208 } //end of the function AAS_UnlinkCache
00209 //===========================================================================
00210 //
00211 // Parameter:           -
00212 // Returns:             -
00213 // Changes Globals:     -
00214 //===========================================================================
00215 void AAS_LinkCache(aas_routingcache_t *cache)
00216 {
00217     if (aasworld.newestcache)
00218     {
00219         aasworld.newestcache->time_next = cache;
00220         cache->time_prev = aasworld.newestcache;
00221     } //end if
00222     else
00223     {
00224         aasworld.oldestcache = cache;
00225         cache->time_prev = NULL;
00226     } //end else
00227     cache->time_next = NULL;
00228     aasworld.newestcache = cache;
00229 } //end of the function AAS_LinkCache
00230 //===========================================================================
00231 //
00232 // Parameter:           -
00233 // Returns:             -
00234 // Changes Globals:     -
00235 //===========================================================================
00236 void AAS_FreeRoutingCache(aas_routingcache_t *cache)
00237 {
00238     AAS_UnlinkCache(cache);
00239     routingcachesize -= cache->size;
00240     FreeMemory(cache);
00241 } //end of the function AAS_FreeRoutingCache
00242 //===========================================================================
00243 //
00244 // Parameter:           -
00245 // Returns:             -
00246 // Changes Globals:     -
00247 //===========================================================================
00248 void AAS_RemoveRoutingCacheInCluster( int clusternum )
00249 {
00250     int i;
00251     aas_routingcache_t *cache, *nextcache;
00252     aas_cluster_t *cluster;
00253 
00254     if (!aasworld.clusterareacache)
00255         return;
00256     cluster = &aasworld.clusters[clusternum];
00257     for (i = 0; i < cluster->numareas; i++)
00258     {
00259         for (cache = aasworld.clusterareacache[clusternum][i]; cache; cache = nextcache)
00260         {
00261             nextcache = cache->next;
00262             AAS_FreeRoutingCache(cache);
00263         } //end for
00264         aasworld.clusterareacache[clusternum][i] = NULL;
00265     } //end for
00266 } //end of the function AAS_RemoveRoutingCacheInCluster
00267 //===========================================================================
00268 //
00269 // Parameter:           -
00270 // Returns:             -
00271 // Changes Globals:     -
00272 //===========================================================================
00273 void AAS_RemoveRoutingCacheUsingArea( int areanum )
00274 {
00275     int i, clusternum;
00276     aas_routingcache_t *cache, *nextcache;
00277 
00278     clusternum = aasworld.areasettings[areanum].cluster;
00279     if (clusternum > 0)
00280     {
00281         //remove all the cache in the cluster the area is in
00282         AAS_RemoveRoutingCacheInCluster( clusternum );
00283     } //end if
00284     else
00285     {
00286         // if this is a portal remove all cache in both the front and back cluster
00287         AAS_RemoveRoutingCacheInCluster( aasworld.portals[-clusternum].frontcluster );
00288         AAS_RemoveRoutingCacheInCluster( aasworld.portals[-clusternum].backcluster );
00289     } //end else
00290     // remove all portal cache
00291     for (i = 0; i < aasworld.numareas; i++)
00292     {
00293         //refresh portal cache
00294         for (cache = aasworld.portalcache[i]; cache; cache = nextcache)
00295         {
00296             nextcache = cache->next;
00297             AAS_FreeRoutingCache(cache);
00298         } //end for
00299         aasworld.portalcache[i] = NULL;
00300     } //end for
00301 } //end of the function AAS_RemoveRoutingCacheUsingArea
00302 //===========================================================================
00303 //
00304 // Parameter:           -
00305 // Returns:             -
00306 // Changes Globals:     -
00307 //===========================================================================
00308 int AAS_EnableRoutingArea(int areanum, int enable)
00309 {
00310     int flags;
00311 
00312     if (areanum <= 0 || areanum >= aasworld.numareas)
00313     {
00314         if (bot_developer)
00315         {
00316             botimport.Print(PRT_ERROR, "AAS_EnableRoutingArea: areanum %d out of range\n", areanum);
00317         } //end if
00318         return 0;
00319     } //end if
00320     flags = aasworld.areasettings[areanum].areaflags & AREA_DISABLED;
00321     if (enable < 0)
00322         return !flags;
00323 
00324     if (enable)
00325         aasworld.areasettings[areanum].areaflags &= ~AREA_DISABLED;
00326     else
00327         aasworld.areasettings[areanum].areaflags |= AREA_DISABLED;
00328     // if the status of the area changed
00329     if ( (flags & AREA_DISABLED) != (aasworld.areasettings[areanum].areaflags & AREA_DISABLED) )
00330     {
00331         //remove all routing cache involving this area
00332         AAS_RemoveRoutingCacheUsingArea( areanum );
00333     } //end if
00334     return !flags;
00335 } //end of the function AAS_EnableRoutingArea
00336 //===========================================================================
00337 //
00338 // Parameter:           -
00339 // Returns:             -
00340 // Changes Globals:     -
00341 //===========================================================================
00342 __inline float AAS_RoutingTime(void)
00343 {
00344     return AAS_Time();
00345 } //end of the function AAS_RoutingTime
00346 //===========================================================================
00347 //
00348 // Parameter:               -
00349 // Returns:                 -
00350 // Changes Globals:     -
00351 //===========================================================================
00352 int AAS_GetAreaContentsTravelFlags(int areanum)
00353 {
00354     int contents, tfl;
00355 
00356     contents = aasworld.areasettings[areanum].contents;
00357     tfl = 0;
00358     if (contents & AREACONTENTS_WATER)
00359         tfl |= TFL_WATER;
00360     else if (contents & AREACONTENTS_SLIME)
00361         tfl |= TFL_SLIME;
00362     else if (contents & AREACONTENTS_LAVA)
00363         tfl |= TFL_LAVA;
00364     else
00365         tfl |= TFL_AIR;
00366     if (contents & AREACONTENTS_DONOTENTER)
00367         tfl |= TFL_DONOTENTER;
00368     if (contents & AREACONTENTS_NOTTEAM1)
00369         tfl |= TFL_NOTTEAM1;
00370     if (contents & AREACONTENTS_NOTTEAM2)
00371         tfl |= TFL_NOTTEAM2;
00372     if (aasworld.areasettings[areanum].areaflags & AREA_BRIDGE)
00373         tfl |= TFL_BRIDGE;
00374     return tfl;
00375 } //end of the function AAS_GetAreaContentsTravelFlags
00376 //===========================================================================
00377 //
00378 // Parameter:           -
00379 // Returns:             -
00380 // Changes Globals:     -
00381 //===========================================================================
00382 __inline int AAS_AreaContentsTravelFlags_inline(int areanum)
00383 {
00384     return aasworld.areacontentstravelflags[areanum];
00385 } //end of the function AAS_AreaContentsTravelFlags
00386 //===========================================================================
00387 //
00388 // Parameter:           -
00389 // Returns:             -
00390 // Changes Globals:     -
00391 //===========================================================================
00392 int AAS_AreaContentsTravelFlags(int areanum)
00393 {
00394     return aasworld.areacontentstravelflags[areanum];
00395 } //end of the function AAS_AreaContentsTravelFlags
00396 //===========================================================================
00397 //
00398 // Parameter:           -
00399 // Returns:             -
00400 // Changes Globals:     -
00401 //===========================================================================
00402 void AAS_InitAreaContentsTravelFlags(void)
00403 {
00404     int i;
00405 
00406     if (aasworld.areacontentstravelflags) FreeMemory(aasworld.areacontentstravelflags);
00407     aasworld.areacontentstravelflags = (int *) GetClearedMemory(aasworld.numareas * sizeof(int));
00408     //
00409     for (i = 0; i < aasworld.numareas; i++) {
00410         aasworld.areacontentstravelflags[i] = AAS_GetAreaContentsTravelFlags(i);
00411     }
00412 } //end of the function AAS_InitAreaContentsTravelFlags
00413 //===========================================================================
00414 //
00415 // Parameter:           -
00416 // Returns:             -
00417 // Changes Globals:     -
00418 //===========================================================================
00419 void AAS_CreateReversedReachability(void)
00420 {
00421     int i, n;
00422     aas_reversedlink_t *revlink;
00423     aas_reachability_t *reach;
00424     aas_areasettings_t *settings;
00425     char *ptr;
00426 #ifdef DEBUG
00427     int starttime;
00428 
00429     starttime = Sys_MilliSeconds();
00430 #endif
00431     //free reversed links that have already been created
00432     if (aasworld.reversedreachability) FreeMemory(aasworld.reversedreachability);
00433     //allocate memory for the reversed reachability links
00434     ptr = (char *) GetClearedMemory(aasworld.numareas * sizeof(aas_reversedreachability_t) +
00435                             aasworld.reachabilitysize * sizeof(aas_reversedlink_t));
00436     //
00437     aasworld.reversedreachability = (aas_reversedreachability_t *) ptr;
00438     //pointer to the memory for the reversed links
00439     ptr += aasworld.numareas * sizeof(aas_reversedreachability_t);
00440     //check all reachabilities of all areas
00441     for (i = 1; i < aasworld.numareas; i++)
00442     {
00443         //settings of the area
00444         settings = &aasworld.areasettings[i];
00445         //
00446         if (settings->numreachableareas >= 128)
00447             botimport.Print(PRT_WARNING, "area %d has more than 128 reachabilities\n", i);
00448         //create reversed links for the reachabilities
00449         for (n = 0; n < settings->numreachableareas && n < 128; n++)
00450         {
00451             //reachability link
00452             reach = &aasworld.reachability[settings->firstreachablearea + n];
00453             //
00454             revlink = (aas_reversedlink_t *) ptr;
00455             ptr += sizeof(aas_reversedlink_t);
00456             //
00457             revlink->areanum = i;
00458             revlink->linknum = settings->firstreachablearea + n;
00459             revlink->next = aasworld.reversedreachability[reach->areanum].first;
00460             aasworld.reversedreachability[reach->areanum].first = revlink;
00461             aasworld.reversedreachability[reach->areanum].numlinks++;
00462         } //end for
00463     } //end for
00464 #ifdef DEBUG
00465     botimport.Print(PRT_MESSAGE, "reversed reachability %d msec\n", Sys_MilliSeconds() - starttime);
00466 #endif
00467 } //end of the function AAS_CreateReversedReachability
00468 //===========================================================================
00469 //
00470 // Parameter:           -
00471 // Returns:             -
00472 // Changes Globals:     -
00473 //===========================================================================
00474 unsigned short int AAS_AreaTravelTime(int areanum, vec3_t start, vec3_t end)
00475 {
00476     int intdist;
00477     float dist;
00478     vec3_t dir;
00479 
00480     VectorSubtract(start, end, dir);
00481     dist = VectorLength(dir);
00482     //if crouch only area
00483     if (AAS_AreaCrouch(areanum)) dist *= DISTANCEFACTOR_CROUCH;
00484     //if swim area
00485     else if (AAS_AreaSwim(areanum)) dist *= DISTANCEFACTOR_SWIM;
00486     //normal walk area
00487     else dist *= DISTANCEFACTOR_WALK;
00488     //
00489     intdist = (int) dist;
00490     //make sure the distance isn't zero
00491     if (intdist <= 0) intdist = 1;
00492     return intdist;
00493 } //end of the function AAS_AreaTravelTime
00494 //===========================================================================
00495 //
00496 // Parameter:           -
00497 // Returns:             -
00498 // Changes Globals:     -
00499 //===========================================================================
00500 void AAS_CalculateAreaTravelTimes(void)
00501 {
00502     int i, l, n, size;
00503     char *ptr;
00504     vec3_t end;
00505     aas_reversedreachability_t *revreach;
00506     aas_reversedlink_t *revlink;
00507     aas_reachability_t *reach;
00508     aas_areasettings_t *settings;
00509     int starttime;
00510 
00511     starttime = Sys_MilliSeconds();
00512     //if there are still area travel times, free the memory
00513     if (aasworld.areatraveltimes) FreeMemory(aasworld.areatraveltimes);
00514     //get the total size of all the area travel times
00515     size = aasworld.numareas * sizeof(unsigned short **);
00516     for (i = 0; i < aasworld.numareas; i++)
00517     {
00518         revreach = &aasworld.reversedreachability[i];
00519         //settings of the area
00520         settings = &aasworld.areasettings[i];
00521         //
00522         size += settings->numreachableareas * sizeof(unsigned short *);
00523         //
00524         size += settings->numreachableareas * revreach->numlinks * sizeof(unsigned short);
00525     } //end for
00526     //allocate memory for the area travel times
00527     ptr = (char *) GetClearedMemory(size);
00528     aasworld.areatraveltimes = (unsigned short ***) ptr;
00529     ptr += aasworld.numareas * sizeof(unsigned short **);
00530     //calcluate the travel times for all the areas
00531     for (i = 0; i < aasworld.numareas; i++)
00532     {
00533         //reversed reachabilities of this area
00534         revreach = &aasworld.reversedreachability[i];
00535         //settings of the area
00536         settings = &aasworld.areasettings[i];
00537         //
00538         aasworld.areatraveltimes[i] = (unsigned short **) ptr;
00539         ptr += settings->numreachableareas * sizeof(unsigned short *);
00540         //
00541         for (l = 0; l < settings->numreachableareas; l++)
00542         {
00543             aasworld.areatraveltimes[i][l] = (unsigned short *) ptr;
00544             ptr += revreach->numlinks * sizeof(unsigned short);
00545             //reachability link
00546             reach = &aasworld.reachability[settings->firstreachablearea + l];
00547             //
00548             for (n = 0, revlink = revreach->first; revlink; revlink = revlink->next, n++)
00549             {
00550                 VectorCopy(aasworld.reachability[revlink->linknum].end, end);
00551                 //
00552                 aasworld.areatraveltimes[i][l][n] = AAS_AreaTravelTime(i, end, reach->start);
00553             } //end for
00554         } //end for
00555     } //end for
00556 #ifdef DEBUG
00557     botimport.Print(PRT_MESSAGE, "area travel times %d msec\n", Sys_MilliSeconds() - starttime);
00558 #endif
00559 } //end of the function AAS_CalculateAreaTravelTimes
00560 //===========================================================================
00561 //
00562 // Parameter:           -
00563 // Returns:             -
00564 // Changes Globals:     -
00565 //===========================================================================
00566 int AAS_PortalMaxTravelTime(int portalnum)
00567 {
00568     int l, n, t, maxt;
00569     aas_portal_t *portal;
00570     aas_reversedreachability_t *revreach;
00571     aas_reversedlink_t *revlink;
00572     aas_areasettings_t *settings;
00573 
00574     portal = &aasworld.portals[portalnum];
00575     //reversed reachabilities of this portal area
00576     revreach = &aasworld.reversedreachability[portal->areanum];
00577     //settings of the portal area
00578     settings = &aasworld.areasettings[portal->areanum];
00579     //
00580     maxt = 0;
00581     for (l = 0; l < settings->numreachableareas; l++)
00582     {
00583         for (n = 0, revlink = revreach->first; revlink; revlink = revlink->next, n++)
00584         {
00585             t = aasworld.areatraveltimes[portal->areanum][l][n];
00586             if (t > maxt)
00587             {
00588                 maxt = t;
00589             } //end if
00590         } //end for
00591     } //end for
00592     return maxt;
00593 } //end of the function AAS_PortalMaxTravelTime
00594 //===========================================================================
00595 //
00596 // Parameter:           -
00597 // Returns:             -
00598 // Changes Globals:     -
00599 //===========================================================================
00600 void AAS_InitPortalMaxTravelTimes(void)
00601 {
00602     int i;
00603 
00604     if (aasworld.portalmaxtraveltimes) FreeMemory(aasworld.portalmaxtraveltimes);
00605 
00606     aasworld.portalmaxtraveltimes = (int *) GetClearedMemory(aasworld.numportals * sizeof(int));
00607 
00608     for (i = 0; i < aasworld.numportals; i++)
00609     {
00610         aasworld.portalmaxtraveltimes[i] = AAS_PortalMaxTravelTime(i);
00611         //botimport.Print(PRT_MESSAGE, "portal %d max tt = %d\n", i, aasworld.portalmaxtraveltimes[i]);
00612     } //end for
00613 } //end of the function AAS_InitPortalMaxTravelTimes
00614 //===========================================================================
00615 //
00616 // Parameter:           -
00617 // Returns:             -
00618 // Changes Globals:     -
00619 //===========================================================================
00620 /*
00621 int AAS_FreeOldestCache(void)
00622 {
00623     int i, j, bestcluster, bestarea, freed;
00624     float besttime;
00625     aas_routingcache_t *cache, *bestcache;
00626 
00627     freed = qfalse;
00628     besttime = 999999999;
00629     bestcache = NULL;
00630     bestcluster = 0;
00631     bestarea = 0;
00632     //refresh cluster cache
00633     for (i = 0; i < aasworld.numclusters; i++)
00634     {
00635         for (j = 0; j < aasworld.clusters[i].numareas; j++)
00636         {
00637             for (cache = aasworld.clusterareacache[i][j]; cache; cache = cache->next)
00638             {
00639                 //never remove cache leading towards a portal
00640                 if (aasworld.areasettings[cache->areanum].cluster < 0) continue;
00641                 //if this cache is older than the cache we found so far
00642                 if (cache->time < besttime)
00643                 {
00644                     bestcache = cache;
00645                     bestcluster = i;
00646                     bestarea = j;
00647                     besttime = cache->time;
00648                 } //end if
00649             } //end for
00650         } //end for
00651     } //end for
00652     if (bestcache)
00653     {
00654         cache = bestcache;
00655         if (cache->prev) cache->prev->next = cache->next;
00656         else aasworld.clusterareacache[bestcluster][bestarea] = cache->next;
00657         if (cache->next) cache->next->prev = cache->prev;
00658         AAS_FreeRoutingCache(cache);
00659         freed = qtrue;
00660     } //end if
00661     besttime = 999999999;
00662     bestcache = NULL;
00663     bestarea = 0;
00664     for (i = 0; i < aasworld.numareas; i++)
00665     {
00666         //refresh portal cache
00667         for (cache = aasworld.portalcache[i]; cache; cache = cache->next)
00668         {
00669             if (cache->time < besttime)
00670             {
00671                 bestcache = cache;
00672                 bestarea = i;
00673                 besttime = cache->time;
00674             } //end if
00675         } //end for
00676     } //end for
00677     if (bestcache)
00678     {
00679         cache = bestcache;
00680         if (cache->prev) cache->prev->next = cache->next;
00681         else aasworld.portalcache[bestarea] = cache->next;
00682         if (cache->next) cache->next->prev = cache->prev;
00683         AAS_FreeRoutingCache(cache);
00684         freed = qtrue;
00685     } //end if
00686     return freed;
00687 } //end of the function AAS_FreeOldestCache
00688 */
00689 //===========================================================================
00690 //
00691 // Parameter:           -
00692 // Returns:             -
00693 // Changes Globals:     -
00694 //===========================================================================
00695 int AAS_FreeOldestCache(void)
00696 {
00697     int clusterareanum;
00698     aas_routingcache_t *cache;
00699 
00700     for (cache = aasworld.oldestcache; cache; cache = cache->time_next) {
00701         // never free area cache leading towards a portal
00702         if (cache->type == CACHETYPE_AREA && aasworld.areasettings[cache->areanum].cluster < 0) {
00703             continue;
00704         }
00705         break;
00706     }
00707     if (cache) {
00708         // unlink the cache
00709         if (cache->type == CACHETYPE_AREA) {
00710             //number of the area in the cluster
00711             clusterareanum = AAS_ClusterAreaNum(cache->cluster, cache->areanum);
00712             // unlink from cluster area cache
00713             if (cache->prev) cache->prev->next = cache->next;
00714             else aasworld.clusterareacache[cache->cluster][clusterareanum] = cache->next;
00715             if (cache->next) cache->next->prev = cache->prev;
00716         }
00717         else {
00718             // unlink from portal cache
00719             if (cache->prev) cache->prev->next = cache->next;
00720             else aasworld.portalcache[cache->areanum] = cache->next;
00721             if (cache->next) cache->next->prev = cache->prev;
00722         }
00723         AAS_FreeRoutingCache(cache);
00724         return qtrue;
00725     }
00726     return qfalse;
00727 } //end of the function AAS_FreeOldestCache
00728 //===========================================================================
00729 //
00730 // Parameter:           -
00731 // Returns:             -
00732 // Changes Globals:     -
00733 //===========================================================================
00734 aas_routingcache_t *AAS_AllocRoutingCache(int numtraveltimes)
00735 {
00736     aas_routingcache_t *cache;
00737     int size;
00738 
00739     //
00740     size = sizeof(aas_routingcache_t)
00741                         + numtraveltimes * sizeof(unsigned short int)
00742                         + numtraveltimes * sizeof(unsigned char);
00743     //
00744     routingcachesize += size;
00745     //
00746     cache = (aas_routingcache_t *) GetClearedMemory(size);
00747     cache->reachabilities = (unsigned char *) cache + sizeof(aas_routingcache_t)
00748                                 + numtraveltimes * sizeof(unsigned short int);
00749     cache->size = size;
00750     return cache;
00751 } //end of the function AAS_AllocRoutingCache
00752 //===========================================================================
00753 //
00754 // Parameter:           -
00755 // Returns:             -
00756 // Changes Globals:     -
00757 //===========================================================================
00758 void AAS_FreeAllClusterAreaCache(void)
00759 {
00760     int i, j;
00761     aas_routingcache_t *cache, *nextcache;
00762     aas_cluster_t *cluster;
00763 
00764     //free all cluster cache if existing
00765     if (!aasworld.clusterareacache) return;
00766     //free caches
00767     for (i = 0; i < aasworld.numclusters; i++)
00768     {
00769         cluster = &aasworld.clusters[i];
00770         for (j = 0; j < cluster->numareas; j++)
00771         {
00772             for (cache = aasworld.clusterareacache[i][j]; cache; cache = nextcache)
00773             {
00774                 nextcache = cache->next;
00775                 AAS_FreeRoutingCache(cache);
00776             } //end for
00777             aasworld.clusterareacache[i][j] = NULL;
00778         } //end for
00779     } //end for
00780     //free the cluster cache array
00781     FreeMemory(aasworld.clusterareacache);
00782     aasworld.clusterareacache = NULL;
00783 } //end of the function AAS_FreeAllClusterAreaCache
00784 //===========================================================================
00785 //
00786 // Parameter:           -
00787 // Returns:             -
00788 // Changes Globals:     -
00789 //===========================================================================
00790 void AAS_InitClusterAreaCache(void)
00791 {
00792     int i, size;
00793     char *ptr;
00794 
00795     //
00796     for (size = 0, i = 0; i < aasworld.numclusters; i++)
00797     {
00798         size += aasworld.clusters[i].numareas;
00799     } //end for
00800     //two dimensional array with pointers for every cluster to routing cache
00801     //for every area in that cluster
00802     ptr = (char *) GetClearedMemory(
00803                 aasworld.numclusters * sizeof(aas_routingcache_t **) +
00804                 size * sizeof(aas_routingcache_t *));
00805     aasworld.clusterareacache = (aas_routingcache_t ***) ptr;
00806     ptr += aasworld.numclusters * sizeof(aas_routingcache_t **);
00807     for (i = 0; i < aasworld.numclusters; i++)
00808     {
00809         aasworld.clusterareacache[i] = (aas_routingcache_t **) ptr;
00810         ptr += aasworld.clusters[i].numareas * sizeof(aas_routingcache_t *);
00811     } //end for
00812 } //end of the function AAS_InitClusterAreaCache
00813 //===========================================================================
00814 //
00815 // Parameter:           -
00816 // Returns:             -
00817 // Changes Globals:     -
00818 //===========================================================================
00819 void AAS_FreeAllPortalCache(void)
00820 {
00821     int i;
00822     aas_routingcache_t *cache, *nextcache;
00823 
00824     //free all portal cache if existing
00825     if (!aasworld.portalcache) return;
00826     //free portal caches
00827     for (i = 0; i < aasworld.numareas; i++)
00828     {
00829         for (cache = aasworld.portalcache[i]; cache; cache = nextcache)
00830         {
00831             nextcache = cache->next;
00832             AAS_FreeRoutingCache(cache);
00833         } //end for
00834         aasworld.portalcache[i] = NULL;
00835     } //end for
00836     FreeMemory(aasworld.portalcache);
00837     aasworld.portalcache = NULL;
00838 } //end of the function AAS_FreeAllPortalCache
00839 //===========================================================================
00840 //
00841 // Parameter:               -
00842 // Returns:                 -
00843 // Changes Globals:     -
00844 //===========================================================================
00845 void AAS_InitPortalCache(void)
00846 {
00847     //
00848     aasworld.portalcache = (aas_routingcache_t **) GetClearedMemory(
00849                                 aasworld.numareas * sizeof(aas_routingcache_t *));
00850 } //end of the function AAS_InitPortalCache
00851 //===========================================================================
00852 //
00853 // Parameter:               -
00854 // Returns:                 -
00855 // Changes Globals:     -
00856 //===========================================================================
00857 void AAS_InitRoutingUpdate(void)
00858 {
00859     int i, maxreachabilityareas;
00860 
00861     //free routing update fields if already existing
00862     if (aasworld.areaupdate) FreeMemory(aasworld.areaupdate);
00863     //
00864     maxreachabilityareas = 0;
00865     for (i = 0; i < aasworld.numclusters; i++)
00866     {
00867         if (aasworld.clusters[i].numreachabilityareas > maxreachabilityareas)
00868         {
00869             maxreachabilityareas = aasworld.clusters[i].numreachabilityareas;
00870         } //end if
00871     } //end for
00872     //allocate memory for the routing update fields
00873     aasworld.areaupdate = (aas_routingupdate_t *) GetClearedMemory(
00874                                     maxreachabilityareas * sizeof(aas_routingupdate_t));
00875     //
00876     if (aasworld.portalupdate) FreeMemory(aasworld.portalupdate);
00877     //allocate memory for the portal update fields
00878     aasworld.portalupdate = (aas_routingupdate_t *) GetClearedMemory(
00879                                     (aasworld.numportals+1) * sizeof(aas_routingupdate_t));
00880 } //end of the function AAS_InitRoutingUpdate
00881 //===========================================================================
00882 //
00883 // Parameter:           -
00884 // Returns:             -
00885 // Changes Globals:     -
00886 //===========================================================================
00887 void AAS_CreateAllRoutingCache(void)
00888 {
00889     int i, j, t;
00890 
00891     aasworld.initialized = qtrue;
00892     botimport.Print(PRT_MESSAGE, "AAS_CreateAllRoutingCache\n");
00893     for (i = 1; i < aasworld.numareas; i++)
00894     {
00895         if (!AAS_AreaReachability(i)) continue;
00896         for (j = 1; j < aasworld.numareas; j++)
00897         {
00898             if (i == j) continue;
00899             if (!AAS_AreaReachability(j)) continue;
00900             t = AAS_AreaTravelTimeToGoalArea(i, aasworld.areas[i].center, j, TFL_DEFAULT);
00901             //Log_Write("traveltime from %d to %d is %d", i, j, t);
00902         } //end for
00903     } //end for
00904     aasworld.initialized = qfalse;
00905 } //end of the function AAS_CreateAllRoutingCache
00906 //===========================================================================
00907 //
00908 // Parameter:           -
00909 // Returns:             -
00910 // Changes Globals:     -
00911 //===========================================================================
00912 
00913 //the route cache header
00914 //this header is followed by numportalcache + numareacache aas_routingcache_t
00915 //structures that store routing cache
00916 typedef struct routecacheheader_s
00917 {
00918     int ident;
00919     int version;
00920     int numareas;
00921     int numclusters;
00922     int areacrc;
00923     int clustercrc;
00924     int numportalcache;
00925     int numareacache;
00926 } routecacheheader_t;
00927 
00928 #define RCID                        (('C'<<24)+('R'<<16)+('E'<<8)+'M')
00929 #define RCVERSION                   2
00930 
00931 //void AAS_DecompressVis(byte *in, int numareas, byte *decompressed);
00932 //int AAS_CompressVis(byte *vis, int numareas, byte *dest);
00933 
00934 void AAS_WriteRouteCache(void)
00935 {
00936     int i, j, numportalcache, numareacache, totalsize;
00937     aas_routingcache_t *cache;
00938     aas_cluster_t *cluster;
00939     fileHandle_t fp;
00940     char filename[MAX_QPATH];
00941     routecacheheader_t routecacheheader;
00942 
00943     numportalcache = 0;
00944     for (i = 0; i < aasworld.numareas; i++)
00945     {
00946         for (cache = aasworld.portalcache[i]; cache; cache = cache->next)
00947         {
00948             numportalcache++;
00949         } //end for
00950     } //end for
00951     numareacache = 0;
00952     for (i = 0; i < aasworld.numclusters; i++)
00953     {
00954         cluster = &aasworld.clusters[i];
00955         for (j = 0; j < cluster->numareas; j++)
00956         {
00957             for (cache = aasworld.clusterareacache[i][j]; cache; cache = cache->next)
00958             {
00959                 numareacache++;
00960             } //end for
00961         } //end for
00962     } //end for
00963     // open the file for writing
00964     Com_sprintf(filename, MAX_QPATH, "maps/%s.rcd", aasworld.mapname);
00965     botimport.FS_FOpenFile( filename, &fp, FS_WRITE );
00966     if (!fp)
00967     {
00968         AAS_Error("Unable to open file: %s\n", filename);
00969         return;
00970     } //end if
00971     //create the header
00972     routecacheheader.ident = RCID;
00973     routecacheheader.version = RCVERSION;
00974     routecacheheader.numareas = aasworld.numareas;
00975     routecacheheader.numclusters = aasworld.numclusters;
00976     routecacheheader.areacrc = CRC_ProcessString( (unsigned char *)aasworld.areas, sizeof(aas_area_t) * aasworld.numareas );
00977     routecacheheader.clustercrc = CRC_ProcessString( (unsigned char *)aasworld.clusters, sizeof(aas_cluster_t) * aasworld.numclusters );
00978     routecacheheader.numportalcache = numportalcache;
00979     routecacheheader.numareacache = numareacache;
00980     //write the header
00981     botimport.FS_Write(&routecacheheader, sizeof(routecacheheader_t), fp);
00982     //
00983     totalsize = 0;
00984     //write all the cache
00985     for (i = 0; i < aasworld.numareas; i++)
00986     {
00987         for (cache = aasworld.portalcache[i]; cache; cache = cache->next)
00988         {
00989             botimport.FS_Write(cache, cache->size, fp);
00990             totalsize += cache->size;
00991         } //end for
00992     } //end for
00993     for (i = 0; i < aasworld.numclusters; i++)
00994     {
00995         cluster = &aasworld.clusters[i];
00996         for (j = 0; j < cluster->numareas; j++)
00997         {
00998             for (cache = aasworld.clusterareacache[i][j]; cache; cache = cache->next)
00999             {
01000                 botimport.FS_Write(cache, cache->size, fp);
01001                 totalsize += cache->size;
01002             } //end for
01003         } //end for
01004     } //end for
01005     // write the visareas
01006     /*
01007     for (i = 0; i < aasworld.numareas; i++)
01008     {
01009         if (!aasworld.areavisibility[i]) {
01010             size = 0;
01011             botimport.FS_Write(&size, sizeof(int), fp);
01012             continue;
01013         }
01014         AAS_DecompressVis( aasworld.areavisibility[i], aasworld.numareas, aasworld.decompressedvis );
01015         size = AAS_CompressVis( aasworld.decompressedvis, aasworld.numareas, aasworld.decompressedvis );
01016         botimport.FS_Write(&size, sizeof(int), fp);
01017         botimport.FS_Write(aasworld.decompressedvis, size, fp);
01018     }
01019     */
01020     //
01021     botimport.FS_FCloseFile(fp);
01022     botimport.Print(PRT_MESSAGE, "\nroute cache written to %s\n", filename);
01023     botimport.Print(PRT_MESSAGE, "written %d bytes of routing cache\n", totalsize);
01024 } //end of the function AAS_WriteRouteCache
01025 //===========================================================================
01026 //
01027 // Parameter:           -
01028 // Returns:             -
01029 // Changes Globals:     -
01030 //===========================================================================
01031 aas_routingcache_t *AAS_ReadCache(fileHandle_t fp)
01032 {
01033     int size;
01034     aas_routingcache_t *cache;
01035 
01036     botimport.FS_Read(&size, sizeof(size), fp);
01037     cache = (aas_routingcache_t *) GetMemory(size);
01038     cache->size = size;
01039     botimport.FS_Read((unsigned char *)cache + sizeof(size), size - sizeof(size), fp);
01040     cache->reachabilities = (unsigned char *) cache + sizeof(aas_routingcache_t) - sizeof(unsigned short) +
01041         (size - sizeof(aas_routingcache_t) + sizeof(unsigned short)) / 3 * 2;
01042     return cache;
01043 } //end of the function AAS_ReadCache
01044 //===========================================================================
01045 //
01046 // Parameter:           -
01047 // Returns:             -
01048 // Changes Globals:     -
01049 //===========================================================================
01050 int AAS_ReadRouteCache(void)
01051 {
01052     int i, clusterareanum;//, size;
01053     fileHandle_t fp;
01054     char filename[MAX_QPATH];
01055     routecacheheader_t routecacheheader;
01056     aas_routingcache_t *cache;
01057 
01058     Com_sprintf(filename, MAX_QPATH, "maps/%s.rcd", aasworld.mapname);
01059     botimport.FS_FOpenFile( filename, &fp, FS_READ );
01060     if (!fp)
01061     {
01062         return qfalse;
01063     } //end if
01064     botimport.FS_Read(&routecacheheader, sizeof(routecacheheader_t), fp );
01065     if (routecacheheader.ident != RCID)
01066     {
01067         AAS_Error("%s is not a route cache dump\n");
01068         return qfalse;
01069     } //end if
01070     if (routecacheheader.version != RCVERSION)
01071     {
01072         AAS_Error("route cache dump has wrong version %d, should be %d", routecacheheader.version, RCVERSION);
01073         return qfalse;
01074     } //end if
01075     if (routecacheheader.numareas != aasworld.numareas)
01076     {
01077         //AAS_Error("route cache dump has wrong number of areas\n");
01078         return qfalse;
01079     } //end if
01080     if (routecacheheader.numclusters != aasworld.numclusters)
01081     {
01082         //AAS_Error("route cache dump has wrong number of clusters\n");
01083         return qfalse;
01084     } //end if
01085     if (routecacheheader.areacrc !=
01086         CRC_ProcessString( (unsigned char *)aasworld.areas, sizeof(aas_area_t) * aasworld.numareas ))
01087     {
01088         //AAS_Error("route cache dump area CRC incorrect\n");
01089         return qfalse;
01090     } //end if
01091     if (routecacheheader.clustercrc !=
01092         CRC_ProcessString( (unsigned char *)aasworld.clusters, sizeof(aas_cluster_t) * aasworld.numclusters ))
01093     {
01094         //AAS_Error("route cache dump cluster CRC incorrect\n");
01095         return qfalse;
01096     } //end if
01097     //read all the portal cache
01098     for (i = 0; i < routecacheheader.numportalcache; i++)
01099     {
01100         cache = AAS_ReadCache(fp);
01101         cache->next = aasworld.portalcache[cache->areanum];
01102         cache->prev = NULL;
01103         if (aasworld.portalcache[cache->areanum])
01104             aasworld.portalcache[cache->areanum]->prev = cache;
01105         aasworld.portalcache[cache->areanum] = cache;
01106     } //end for
01107     //read all the cluster area cache
01108     for (i = 0; i < routecacheheader.numareacache; i++)
01109     {
01110         cache = AAS_ReadCache(fp);
01111         clusterareanum = AAS_ClusterAreaNum(cache->cluster, cache->areanum);
01112         cache->next = aasworld.clusterareacache[cache->cluster][clusterareanum];
01113         cache->prev = NULL;
01114         if (aasworld.clusterareacache[cache->cluster][clusterareanum])
01115             aasworld.clusterareacache[cache->cluster][clusterareanum]->prev = cache;
01116         aasworld.clusterareacache[cache->cluster][clusterareanum] = cache;
01117     } //end for
01118     // read the visareas
01119     /*
01120     aasworld.areavisibility = (byte **) GetClearedMemory(aasworld.numareas * sizeof(byte *));
01121     aasworld.decompressedvis = (byte *) GetClearedMemory(aasworld.numareas * sizeof(byte));
01122     for (i = 0; i < aasworld.numareas; i++)
01123     {
01124         botimport.FS_Read(&size, sizeof(size), fp );
01125         if (size) {
01126             aasworld.areavisibility[i] = (byte *) GetMemory(size);
01127             botimport.FS_Read(aasworld.areavisibility[i], size, fp );
01128         }
01129     }
01130     */
01131     //
01132     botimport.FS_FCloseFile(fp);
01133     return qtrue;
01134 } //end of the function AAS_ReadRouteCache
01135 //===========================================================================
01136 //
01137 // Parameter:           -
01138 // Returns:             -
01139 // Changes Globals:     -
01140 //===========================================================================
01141 #define MAX_REACHABILITYPASSAREAS       32
01142 
01143 void AAS_InitReachabilityAreas(void)
01144 {
01145     int i, j, numareas, areas[MAX_REACHABILITYPASSAREAS];
01146     int numreachareas;
01147     aas_reachability_t *reach;
01148     vec3_t start, end;
01149 
01150     if (aasworld.