Logo Search packages:      
Sourcecode: warzone2100 version File versions

aiexperience.c

/*
      This file is part of Warzone 2100.
      Copyright (C) 1999-2004  Eidos Interactive
      Copyright (C) 2005-2007  Warzone Resurrection Project

      Warzone 2100 is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published by
      the Free Software Foundation; either version 2 of the License, or
      (at your option) any later version.

      Warzone 2100 is distributed in the hope that it will be useful,
      but WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      GNU General Public License for more details.

      You should have received a copy of the GNU General Public License
      along with Warzone 2100; if not, write to the Free Software
      Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
//aiexperience.c
#include <physfs.h>
#include <string.h>

#include "objmem.h"
#include "objectdef.h"
#include "map.h"
#include "lib/framework/frame.h"
#include "lib/script/interp.h"
#include "lib/script/stack.h"
#include "lib/script/codeprint.h"
#include "lib/script/script.h"
#include "multiplay.h"

#include "console.h"          //for RIGHT_JUSTIFY
#include "geometry.h"

#include "aiexperience.h"

static PHYSFS_file* aiSaveFile[8];

SDWORD baseLocation[MAX_PLAYERS][MAX_PLAYERS][2];           //each player's visible enemy base x,y coords for each player (hence 3d)
static SDWORD oilLocation[MAX_PLAYERS][MAX_OIL_LOCATIONS][2];     //remembered oil locations

SDWORD baseDefendLocation[MAX_PLAYERS][MAX_BASE_DEFEND_LOCATIONS][2];
SDWORD baseDefendLocPrior[MAX_PLAYERS][MAX_BASE_DEFEND_LOCATIONS];            //Priority

SDWORD oilDefendLocation[MAX_PLAYERS][MAX_OIL_DEFEND_LOCATIONS][2];
SDWORD oilDefendLocPrior[MAX_PLAYERS][MAX_OIL_DEFEND_LOCATIONS];


void InitializeAIExperience(void)
{
      SDWORD i,j;

      for(i=0;i<MAX_PLAYERS;i++)
      {
            for(j=0;j<MAX_PLAYERS;j++)
            {
                  baseLocation[i][j][0] = -1;
                  baseLocation[i][j][1] = -1;
            }

            for(j=0; j < MAX_BASE_DEFEND_LOCATIONS; j++)
            {
                  baseDefendLocation[i][j][0] = -1;
                  baseDefendLocation[i][j][1] = -1;

                  baseDefendLocPrior[i][j] = -1;
            }

            for(j=0; j < MAX_OIL_DEFEND_LOCATIONS; j++)
            {
                  oilDefendLocation[i][j][0] = -1;
                  oilDefendLocation[i][j][1] = -1;

                  oilDefendLocPrior[i][j] = -1;
            }

            //oil locations
            for(j=0; j < MAX_OIL_LOCATIONS; j++)
            {
                  oilLocation[i][j][0] = -1;
                  oilLocation[i][j][1] = -1;
            }
      }
}

void LoadAIExperience(BOOL bNotify)
{
      SDWORD player,status;

      for(player=0; player<game.maxPlayers; player++)
      {
            status = LoadPlayerAIExperience(player);

            //notify if needed
            if(bNotify)
            {
                  if(status == EXPERIENCE_LOAD_NOSAVE)
                  {
                        console("No saved experience found for player %d", player);
                  }
                  else if(status == EXPERIENCE_LOAD_OK)
                  {
                        console("Successfully loaded experience for player %d", player);
                  }
                  else  //any error
                  {
                        console("Error while loading experience for player %d", player);
                  }
            }
      }
}

BOOL SaveAIExperience(BOOL bNotify)
{
      SDWORD i;
      for(i=0;i<game.maxPlayers;i++)
      {
            (void)SavePlayerAIExperience(i, bNotify);
      }

      return true;
}

SDWORD LoadPlayerAIExperience(SDWORD nPlayer)
{
      if((nPlayer > -1) && (nPlayer < MAX_PLAYERS))
      {
            return ReadAISaveData(nPlayer);
      }

      return EXPERIENCE_LOAD_ERROR;
}

BOOL SavePlayerAIExperience(SDWORD nPlayer, BOOL bNotify)
{
      if((nPlayer > -1) && (nPlayer < MAX_PLAYERS))
      {
            if(!WriteAISaveData(nPlayer))
            {
                  debug(LOG_ERROR,"SavePlayerAIExperience - failed to save exper");

                  //addConsoleMessage("Failed to save experience.",RIGHT_JUSTIFY,SYSTEM_MESSAGE);
                  console("Failed to save experience for player %d.", nPlayer);
                  return false;
            }
      }

      if(bNotify)
      {
            console("Experience for player %d saved successfully.", nPlayer);
      }

      return true;
}

BOOL SetUpOutputFile(SDWORD nPlayer)
{
      char              sPlayer[255] = "";
      char              SaveDir[PATH_MAX] = "multiplay/learndata/";
      char              FileName[255] = "";

      //debug(LOG_ERROR,"SetUpOutputFile");

      /* Assemble dir string */
      sprintf(sPlayer,"%d",nPlayer);

      sstrcat(SaveDir, "player");
      sstrcat(SaveDir, sPlayer);

      /* Create dir on disk */
      if ( !PHYSFS_mkdir(SaveDir))
      {
            debug( LOG_ERROR, "SetUpOutputFile: Error creating directory \"%s\": %s", SaveDir, PHYSFS_getLastError() );
            return false;
      }

      sstrcat(SaveDir, "/");

      /* Create filename */
      sstrcpy(FileName, SaveDir);

      sstrcat(FileName, game.map);        // Map name
      sstrcat(FileName, ".lrn");          // Like "multiplay/learndata/player0/Rush.lrn"

      /* Open file */
      aiSaveFile[nPlayer] = NULL;
      aiSaveFile[nPlayer] = PHYSFS_openWrite(FileName);
      if (!aiSaveFile[nPlayer])
      {
            debug(LOG_ERROR,"SetUpOutputFile(): Couldn't open debugging output file: '%s' for player %d", FileName,nPlayer);
            return false;
      }

      return true;
}

BOOL SetUpInputFile(SDWORD nPlayer)
{
      char              FileName[255] = "";
      char              sPlayer[255] = "";
      char              SaveDir[PATH_MAX] = "multiplay/learndata/";           // "multiplay/learndata/";

      /* Assemble dir */
      snprintf(sPlayer, sizeof(sPlayer), "%d", nPlayer);

      sstrcat(SaveDir, "player");
      sstrcat(SaveDir, sPlayer);
      sstrcat(SaveDir, "/");        // like "multiplay\learndata\player0\"

      /* Create filename */
      sstrcpy(FileName, SaveDir);

      sstrcat(FileName, game.map);        // map name
      sstrcat(FileName, ".lrn");          // Like "multiplay\learndata\player0\Rush.lrn"

      aiSaveFile[nPlayer] = NULL;
      aiSaveFile[nPlayer] = PHYSFS_openRead(FileName);

      if (!aiSaveFile[nPlayer])
      {
            debug(LOG_ERROR,"SetUpInputFile(): Couldn't open input file: '%s' for player %d: %s", FileName, nPlayer, PHYSFS_getLastError());
            return false;
      }

      return true;
}


BOOL ExperienceRecallOil(SDWORD nPlayer)
{
      FEATURE                             *psFeature;
return true;

      /* Make visible all oil derricks */
      for(psFeature = apsFeatureLists[0]; psFeature != NULL; psFeature = psFeature->psNext)
      {
            if(psFeature->psStats->subType == FEAT_OIL_RESOURCE)
            {
                  printf_console("Enabling feature at x: %d y: %d",psFeature->pos.x/128,psFeature->pos.y/128);

                  psFeature->visible[nPlayer] = true;
            }
      }
}

BOOL WriteAISaveData(SDWORD nPlayer)
{

      FEATURE                             *psFeature;
      STRUCTURE                     *psCurr;
      SDWORD                              x=0,y=0;
      SDWORD                              NumEntries=0;     //How many derricks/oil resources will be saved
      UDWORD                              PosXY[MAX_OIL_ENTRIES];       //Locations, 0=x,1=y,2=x etc
      UDWORD                              i,j;
      BOOL                          bTileVisible;

      /* prepare experience file for the current map */
      if(!SetUpOutputFile(nPlayer))
      {
            debug(LOG_ERROR,"Failed to prepare experience file for player %d",nPlayer);
            return false;
      }

      if (aiSaveFile[nPlayer])
      {
            //debug(LOG_ERROR,"WriteAISaveData - aiSaveFile ok");


            /* Version */
            NumEntries = SAVE_FORMAT_VERSION;         //Version
            if(PHYSFS_write(aiSaveFile[nPlayer], &NumEntries, sizeof(NumEntries), 1) != 1)
            {
                  debug(LOG_ERROR,"WriteAISaveData: failed to write version for player %d",nPlayer);
                  return false;
            }

            //fwrite(&NumEntries,sizeof(NumEntries),1,aiSaveFile[nPlayer]);   //Version

            //debug(LOG_ERROR,"WriteAISaveData - Version ok");

            /************************/
            /*          Enemy bases       */
            /************************/
            NumEntries = MAX_PLAYERS;

            /* max num of players to store */
            if(PHYSFS_write(aiSaveFile[nPlayer], &NumEntries, sizeof(NumEntries), 1) != 1)                  //num of players to store
            {
                  debug(LOG_ERROR,"WriteAISaveData: failed to write MAX_PLAYERS for player %d",nPlayer);
                  return false;
            }

            //debug(LOG_ERROR,"WriteAISaveData - MAX_PLAYERS ok");

            /* base locations of all players */
            if(PHYSFS_write(aiSaveFile[nPlayer], baseLocation[nPlayer], sizeof(SDWORD), MAX_PLAYERS * 2) != (MAX_PLAYERS * 2))                  //num of players to store
            {
                  debug(LOG_ERROR,"WriteAISaveData: failed to write base locations for player %d",nPlayer);
                  return false;
            }

            //debug(LOG_ERROR,"WriteAISaveData - Enemy bases ok");

            /************************************/
            /*          Base attack locations         */
            /************************************/
            NumEntries = MAX_BASE_DEFEND_LOCATIONS;

            /* write MAX_BASE_DEFEND_LOCATIONS */
            if(PHYSFS_write(aiSaveFile[nPlayer], &NumEntries, sizeof(SDWORD), 1) < 1)
            {
                  debug(LOG_ERROR,"WriteAISaveData: failed to write defence locations count for player %d",nPlayer);
                  return false;
            }

            /* base defence locations */
            if(PHYSFS_write(aiSaveFile[nPlayer], baseDefendLocation[nPlayer], sizeof(SDWORD), MAX_BASE_DEFEND_LOCATIONS * 2) < (MAX_BASE_DEFEND_LOCATIONS * 2))
            {
                  debug(LOG_ERROR,"WriteAISaveData: failed to write defence locations for player %d",nPlayer);
                  return false;
            }

            /* base defend priorities */
            if(PHYSFS_write(aiSaveFile[nPlayer], baseDefendLocPrior[nPlayer], sizeof(SDWORD), MAX_BASE_DEFEND_LOCATIONS * 2) < (MAX_BASE_DEFEND_LOCATIONS * 2))
            {
                  debug(LOG_ERROR,"WriteAISaveData: failed to write defence locations priority for player %d",nPlayer);
                  return false;
            }

            //debug(LOG_ERROR,"WriteAISaveData - Base attack locations ok");

            /************************************/
            /*          Oil attack locations          */
            /************************************/
            NumEntries = MAX_OIL_DEFEND_LOCATIONS;

            /* MAX_OIL_DEFEND_LOCATIONS */
            if(PHYSFS_write(aiSaveFile[nPlayer], &NumEntries, sizeof(SDWORD), 1) < 1)
            {
                  debug(LOG_ERROR,"WriteAISaveData: failed to write oil defence locations count for player %d",nPlayer);
                  return false;
            }

            /* oil locations */
            if(PHYSFS_write(aiSaveFile[nPlayer], oilDefendLocation[nPlayer], sizeof(SDWORD), MAX_OIL_DEFEND_LOCATIONS * 2) < (MAX_OIL_DEFEND_LOCATIONS * 2))
            {
                  debug(LOG_ERROR,"WriteAISaveData: failed to write oil defence locations for player %d",nPlayer);
                  return false;
            }

            /* oil location priority */
            if(PHYSFS_write(aiSaveFile[nPlayer], oilDefendLocPrior[nPlayer], sizeof(SDWORD), MAX_OIL_DEFEND_LOCATIONS * 2) < (MAX_OIL_DEFEND_LOCATIONS * 2))
            {
                  debug(LOG_ERROR,"WriteAISaveData: failed to write oil defence locations priority for player %d",nPlayer);
                  return false;
            }

            //debug(LOG_ERROR,"WriteAISaveData - Oil attack locations ok");


            /****************************/
            /*          Oil Resources           */
            /****************************/
            NumEntries = MAX_OIL_LOCATIONS;

            /* MAX_OIL_LOCATIONS */
            if(PHYSFS_write(aiSaveFile[nPlayer], &NumEntries, sizeof(NumEntries), 1) < 1)
            {
                  debug(LOG_ERROR,"WriteAISaveData: failed to write oil locations count for player %d",nPlayer);
                  return false;
            }

            NumEntries = 0;         //Num of oil resources

            /* first save everything what we recalled from last load */
            for(i=0; i<MAX_OIL_LOCATIONS; i++)
            {
                  if(oilLocation[nPlayer][i][0] <= 0 || oilLocation[nPlayer][i][1] <= 0)
                        continue;         //skip to next one, since nothing stored

                  PosXY[NumEntries * 2] = oilLocation[nPlayer][i][0];         //x
                  PosXY[NumEntries * 2 + 1] = oilLocation[nPlayer][i][1];     //y

                  NumEntries++;
            }

            /* now remember new ones that are not in memory yet (discovered this time) */
            for(psFeature = apsFeatureLists[0]; psFeature != NULL; psFeature = psFeature->psNext)
            {
                  if(psFeature->psStats->subType == FEAT_OIL_RESOURCE)
                  {
                        if (psFeature->visible[nPlayer])    //|| godMode)
                        {
                              if(!canRecallOilAt(nPlayer, psFeature->pos.x, psFeature->pos.y))  //already stored?
                              {
                                    /* Save X */
                                    PosXY[NumEntries * 2] = psFeature->pos.x;

                                    /* Save Y */
                                    PosXY[NumEntries * 2 + 1] = psFeature->pos.y;

                                    //printf_console("New oil visible x: %d y: %d. Storing.", PosXY[NumEntries * 2]/128,PosXY[NumEntries * 2 + 1]/128);

                                    NumEntries++;
                              }
                        }
                  }
            }

            //Save Derricks as oil resources, since most of them will be unoccupied when experiance will be loaded
            for(i=0;i<MAX_PLAYERS;i=i+1)
            {
                  for (psCurr = apsStructLists[i]; psCurr != NULL; psCurr = psCurr->psNext)
                  {
                        if (psCurr->pStructureType->type == REF_RESOURCE_EXTRACTOR)
                        {
                              if(psCurr->visible[nPlayer])  //if can see it
                              {
                                    if(!canRecallOilAt(nPlayer, psCurr->pos.x, psCurr->pos.y))  //already stored?
                                    {
                                          //psResExtractor = (RES_EXTRACTOR *)psCurr->pFunctionality;

                                          x = psCurr->pos.x;
                                          y = psCurr->pos.y;

                                          //printf_console("Found derrick at x: %d, y: %d,, width: %d",psCurr->pos.x/128,psCurr->pos.y/128,mapWidth);

                                          // Save X //
                                          PosXY[NumEntries * 2] = psCurr->pos.x;

                                          // Save Y //
                                          PosXY[NumEntries * 2 + 1] = psCurr->pos.y;

                                          //printf_console("New derrick visible x: %d y: %d. Storing.", PosXY[NumEntries * 2]/128,PosXY[NumEntries * 2 + 1]/128);

                                          NumEntries++;
                                    }
                              }
                        }
                  }
            }


            /* Write number of Oil Resources */
            if(PHYSFS_write(aiSaveFile[nPlayer], &NumEntries, sizeof(NumEntries), 1) < 1)
            {
                  debug(LOG_ERROR,"WriteAISaveData: failed to write stored oil locations count for player %d",nPlayer);
                  return false;
            }

            //printf_console("Num Oil Resources: %d ****",NumEntries);

            /* Write Oil Resources coords */
            if(NumEntries > 0)            //Anything to save
            {
                  if(PHYSFS_write(aiSaveFile[nPlayer], PosXY, sizeof(UDWORD), NumEntries * 2) < (NumEntries * 2))
                  {
                        debug(LOG_ERROR,"WriteAISaveData: failed to write oil locations fir player %d",nPlayer);
                        return false;
                  }
            }

            /************************/
            /*          Fog of War        */
            /************************/
            NumEntries = MAX_OIL_DEFEND_LOCATIONS;

            for(i=0;i<mapWidth;i++)
            {
                  for(j=0;j<mapHeight;j++)
                  {
                        /* Write tile visibility */
                        bTileVisible = TEST_TILE_VISIBLE(nPlayer, mapTile(i, j));
                        if(PHYSFS_write(aiSaveFile[nPlayer], &bTileVisible, sizeof(BOOL), 1) < 1)
                        {
                              debug(LOG_ERROR,"WriteAISaveData: failed to write fog of war at tile %d-%d for player %d", i, j, nPlayer);
                              return false;
                        }
                  }
            }
      }
      else
      {
            debug(LOG_ERROR,"WriteAISaveData(): no output file for player %d",nPlayer);
            return false;
      }

      //printf_console("AI settings file written for player %d",nPlayer);

      return PHYSFS_close(aiSaveFile[nPlayer]);
}

BOOL canRecallOilAt(SDWORD nPlayer, SDWORD x, SDWORD y)
{
      SDWORD i;

      /* go through all remembered oil and check */
      for(i=0; i<MAX_OIL_LOCATIONS; i++)
      {
            if(oilLocation[nPlayer][i][0] != x)
                  continue;

            if(oilLocation[nPlayer][i][1] != y)
                  continue;

            return true;            //yep, both matched
      }

      return false;                 //no
}

SDWORD ReadAISaveData(SDWORD nPlayer)
{
      FEATURE           *psFeature;
      SDWORD            NumEntries=0;           //How many derricks/oil resources will be saved
      UDWORD            PosXY[MAX_OIL_ENTRIES];       //Locations, 0=x,1=y,2=x etc
      UDWORD            i,j;
      BOOL        Found,bTileVisible;
      UDWORD            version;

      if(!SetUpInputFile(nPlayer))
      {
            //debug(LOG_ERROR,"No experience data loaded for %d",nPlayer);
            return EXPERIENCE_LOAD_NOSAVE;
      }
      else
      {
            /* Read data version */
            if (PHYSFS_read(aiSaveFile[nPlayer], &version, sizeof(NumEntries), 1 ) != 1 )
            {
                  debug(LOG_ERROR,"ReadAISaveData(): Failed to read version number for player '%d'",nPlayer);
                  return EXPERIENCE_LOAD_ERROR;
            }

            // Check version, assume backward compatibility
            if(version > SAVE_FORMAT_VERSION)
            {
                  debug(LOG_ERROR,"ReadAISaveData(): Incompatible version of the learn data (%d, expected %d) for player '%d'", version, SAVE_FORMAT_VERSION, nPlayer);
            }

            /************************/
            /*          Enemy bases       */
            /************************/

            /* read max number of players (usually 8) */
            if (PHYSFS_read(aiSaveFile[nPlayer], &NumEntries, sizeof(NumEntries), 1 ) != 1 )
            {
                  debug(LOG_ERROR,"ReadAISaveData(): Failed to read number of players for player '%d'",nPlayer);
                  return EXPERIENCE_LOAD_ERROR;
            }

            /* read base locations of all players */
            if (PHYSFS_read(aiSaveFile[nPlayer], baseLocation[nPlayer], sizeof(SDWORD), NumEntries * 2 ) != (NumEntries * 2) )
            {
                  debug(LOG_ERROR,"ReadAISaveData(): Failed to load baseLocation for player '%d'",nPlayer);
                  return EXPERIENCE_LOAD_ERROR;
            }

            /************************************/
            /*          Base attack locations         */
            /************************************/

            /* read MAX_BASE_DEFEND_LOCATIONS */
            if (PHYSFS_read(aiSaveFile[nPlayer], &NumEntries, sizeof(SDWORD), 1 ) != 1 )
            {
                  debug(LOG_ERROR,"ReadAISaveData(): Failed to read MAX_BASE_DEFEND_LOCATIONS for player '%d'",nPlayer);
                  return EXPERIENCE_LOAD_ERROR;
            }

            /* check it's the same as current MAX_BASE_DEFEND_LOCATIONS */
            if(NumEntries > MAX_BASE_DEFEND_LOCATIONS)
            {
                  debug(LOG_ERROR, "ReadAISaveData(): saved MAX_BASE_DEFEND_LOCATIONS and current one don't match (%d / %d)", NumEntries, MAX_BASE_DEFEND_LOCATIONS);
                  return EXPERIENCE_LOAD_ERROR;
            }

            //debug(LOG_ERROR,"num base attack loc: %d", NumEntries);

            /* read base defence locations */
            if (PHYSFS_read(aiSaveFile[nPlayer], baseDefendLocation[nPlayer], sizeof(SDWORD), NumEntries * 2 ) != (NumEntries * 2) )
            {
                  debug(LOG_ERROR,"ReadAISaveData(): Failed to load baseDefendLocation for player '%d'",nPlayer);
                  return EXPERIENCE_LOAD_ERROR;
            }

            /* read base defend priorities */
            if (PHYSFS_read(aiSaveFile[nPlayer], baseDefendLocPrior[nPlayer], sizeof(SDWORD), NumEntries * 2 ) != (NumEntries * 2) )
            {
                  debug(LOG_ERROR,"ReadAISaveData(): Failed to load baseDefendLocPrior for player '%d'",nPlayer);
                  return EXPERIENCE_LOAD_ERROR;
            }

            /************************************/
            /*          Oil attack locations          */
            /************************************/

            /* read MAX_OIL_DEFEND_LOCATIONS */
            if (PHYSFS_read(aiSaveFile[nPlayer], &NumEntries, sizeof(NumEntries), 1 ) != 1 )
            {
                  debug(LOG_ERROR,"ReadAISaveData(): Failed to read max number of oil attack locations for player '%d'",nPlayer);
                  return EXPERIENCE_LOAD_ERROR;
            }

            /* check it's the same as current MAX_OIL_DEFEND_LOCATIONS */
            if(NumEntries > MAX_OIL_DEFEND_LOCATIONS)
            {
                  debug(LOG_ERROR, "ReadAISaveData(): saved MAX_OIL_DEFEND_LOCATIONS and current one don't match (%d / %d)", NumEntries, MAX_OIL_DEFEND_LOCATIONS);
                  return EXPERIENCE_LOAD_ERROR;
            }

            //debug(LOG_ERROR,"num oil attack loc: %d", NumEntries);

            /* read oil locations */
            if (PHYSFS_read(aiSaveFile[nPlayer], oilDefendLocation[nPlayer], sizeof(SDWORD), NumEntries * 2 ) != (NumEntries * 2) )
            {
                  debug(LOG_ERROR,"ReadAISaveData(): Failed to load oilDefendLocation for player '%d'",nPlayer);
                  return EXPERIENCE_LOAD_ERROR;
            }

            /* read oil location priority */
            if (PHYSFS_read(aiSaveFile[nPlayer], oilDefendLocPrior[nPlayer], sizeof(SDWORD), NumEntries * 2 ) != (NumEntries * 2) )
            {
                  debug(LOG_ERROR,"ReadAISaveData(): Failed to load oilDefendLocPrior for player '%d'",nPlayer);
                  return EXPERIENCE_LOAD_ERROR;
            }

            /****************************/
            /*          Oil Resources           */
            /****************************/

            /* read MAX_OIL_LOCATIONS */
            if (PHYSFS_read(aiSaveFile[nPlayer], &NumEntries, sizeof(NumEntries), 1 ) != 1 )
            {
                  debug(LOG_ERROR,"ReadAISaveData(): Failed to load MAX_OIL_LOCATIONS for player '%d'",nPlayer);
                  return EXPERIENCE_LOAD_ERROR;
            }

            /* check it's the same as current MAX_OIL_LOCATIONS */
            if(NumEntries > MAX_OIL_LOCATIONS)
            {
                  debug(LOG_ERROR, "ReadAISaveData(): saved MAX_OIL_LOCATIONS and current one don't match (%d / %d)", NumEntries, MAX_OIL_LOCATIONS);
                  return EXPERIENCE_LOAD_ERROR;
            }


            /* Read number of Oil Resources */
            if (PHYSFS_read(aiSaveFile[nPlayer], &NumEntries, sizeof(NumEntries), 1 ) != 1 )
            {
                  debug(LOG_ERROR,"ReadAISaveData(): Failed to read Oil Resources count for player '%d'",nPlayer);
                  return EXPERIENCE_LOAD_ERROR;
            }

            //debug(LOG_ERROR,"Num oil: %d", NumEntries);

            if(NumEntries > 0)      //any oil resources were saved?
            {
                  /* Read Oil Resources coordinates */
                  if (PHYSFS_read(aiSaveFile[nPlayer], PosXY, sizeof(UDWORD), NumEntries * 2 ) != (NumEntries * 2) )
                  {
                        debug(LOG_ERROR,"ReadAISaveData(): Failed to read Oil Resources coordinates for player '%d'",nPlayer);
                        return EXPERIENCE_LOAD_ERROR;
                  }

                  for(i=0; i<NumEntries; i++)
                  {
                        Found = false;

                        //re-read into remory
                        if(i < MAX_OIL_LOCATIONS)     //didn't max out?
                        {
                              oilLocation[nPlayer][i][0] = PosXY[i * 2];            //x
                              oilLocation[nPlayer][i][1] = PosXY[i * 2 + 1];  //y
                        }

                        /* Iterate through all Oil Resources and try to match coordinates */
                        for(psFeature = apsFeatureLists[0]; psFeature != NULL; psFeature = psFeature->psNext)
                        {
                              if(psFeature->psStats->subType == FEAT_OIL_RESOURCE)  //Oil resource
                              {
                                    if (!(psFeature->visible[nPlayer]))       //Not visible yet
                                    {
                                          if((PosXY[i * 2] == psFeature->pos.x) && (PosXY[i * 2 + 1] == psFeature->pos.y))    /* Found it */
                                          {
                                                //printf_console("Matched oil resource at x: %d y: %d", PosXY[i * 2]/128,PosXY[i * 2 + 1]/128);

                                                psFeature->visible[nPlayer] = true;       //Make visible for AI
                                                Found = true;
                                                break;
                                          }
                                    }

                              }
                        }

                        //if(!Found)            //Couldn't find oil resource with this coords on the map
                        //    printf_console("!!Failed to match oil resource #%d at x: %d y: %d", i,PosXY[i * 2]/128,PosXY[i * 2 + 1]/128);
                  }

                  /************************/
                  /*          Fog of War        */
                  /************************/
                  if(version >= 2)
                  {
                        for(i=0;i<mapWidth;i++)
                        {
                              for(j=0;j<mapWidth;j++)
                              {
                                    if (PHYSFS_read(aiSaveFile[nPlayer], &bTileVisible, sizeof(BOOL), 1 ) != 1 )
                                    {
                                          debug(LOG_ERROR,"ReadAISaveData(): Failed to load tile visibility at tile %d-%d for player '%d'", i, j, nPlayer);
                                          return EXPERIENCE_LOAD_ERROR;
                                    }

                                    // Restore tile visibility
                                    if(bTileVisible)
                                    {
                                          SET_TILE_VISIBLE(selectedPlayer,mapTile(i,j));
                                    }
                              }
                        }
                  }
            }
      }

      return PHYSFS_close(aiSaveFile[nPlayer]) ? EXPERIENCE_LOAD_OK : EXPERIENCE_LOAD_ERROR;
}

BOOL OilResourceAt(UDWORD OilX,UDWORD OilY, SDWORD VisibleToPlayer)
{
      FEATURE                             *psFeature;
      BOOL                          Found;


      /* Iterate through all Oil Resources and try to match coordinates */
      for(psFeature = apsFeatureLists[0]; psFeature != NULL; psFeature = psFeature->psNext)
      {
            if(psFeature->psStats->subType == FEAT_OIL_RESOURCE)  //Oil resource
            {
                  if ((VisibleToPlayer < 0) || (!(psFeature->visible[VisibleToPlayer])))        //Not visible yet
                  {
                        if((OilX == psFeature->pos.x) && (OilY == psFeature->pos.y))      /* Found it */
                        {
                              printf_console("Matched oil resource at x: %d y: %d", OilX/128,OilY/128);

                              psFeature->visible[VisibleToPlayer] = true;           //Make visible for AI
                              Found = true;
                              break;
                        }
                  }

            }
      }

      return true;
}


//x and y are passed by script, find out if this loc is close to
//an already stored loc, if yes then increase its priority
BOOL StoreBaseDefendLoc(SDWORD x, SDWORD y, SDWORD nPlayer)
{
      SDWORD      i, index;
      BOOL  found;

      index = GetBaseDefendLocIndex(x, y, nPlayer);
      if(index < 0)                 //this one is new
      {
            //find an empty element
            found = false;
            for(i=0; i < MAX_BASE_DEFEND_LOCATIONS; i++)
            {
                  if(baseDefendLocation[nPlayer][i][0] < 0) //not initialized yet
                  {
                        //addConsoleMessage("Base defense location - NEW LOCATION.", RIGHT_JUSTIFY,SYSTEM_MESSAGE);

                        baseDefendLocation[nPlayer][i][0] = x;
                        baseDefendLocation[nPlayer][i][1] = y;

                        baseDefendLocPrior[nPlayer][i] = 1;

                        found = true;

                        return true;
                  }
            }

            addConsoleMessage("Base defense location - NO SPACE LEFT.",RIGHT_JUSTIFY,SYSTEM_MESSAGE);
            return false;           //not enough space to store
      }
      else        //this one already stored
      {
            //addConsoleMessage("Base defense location - INCREASED PRIORITY.",SYSTEM_MESSAGE);

            baseDefendLocPrior[nPlayer][index]++;     //higher the priority

            if(baseDefendLocPrior[nPlayer][index] == SDWORD_MAX)
                  baseDefendLocPrior[nPlayer][index] = 1;               //start all over

            SortBaseDefendLoc(nPlayer);                     //now sort everything
      }

      return true;
}

SDWORD GetBaseDefendLocIndex(SDWORD x, SDWORD y, SDWORD nPlayer)
{
      UDWORD      i,range;

      range  = world_coord(SAME_LOC_RANGE);           //in world units

      for(i=0; i < MAX_BASE_DEFEND_LOCATIONS; i++)
      {
            if((baseDefendLocation[nPlayer][i][0] > 0) && (baseDefendLocation[nPlayer][i][1] > 0))          //if this one initialized
            {
                  //check if very close to an already stored location
                  if(dirtySqrt(x,y,baseDefendLocation[nPlayer][i][0],baseDefendLocation[nPlayer][i][1]) < range)
                  {
                        return i;                                             //end here
                  }
            }
      }

      return -1;
}

//sort the priorities, placing the higher ones at the top
BOOL SortBaseDefendLoc(SDWORD nPlayer)
{
      SDWORD i, prior, temp,LowestPrior,LowestIndex,SortBound;



      SortBound = MAX_BASE_DEFEND_LOCATIONS-1;  //nothing sorted yet, point at last elem

      while(SortBound >= 0)         //while didn't reach the top
      {
            LowestPrior = (SDWORD_MAX - 1);

            LowestIndex = -1;

            //find lowest element
            for(i=0; i <= SortBound; i++)
            {
                  prior = baseDefendLocPrior[nPlayer][i];
                  if(prior < LowestPrior) //lower and isn't a flag meaning this one wasn't initialized with anything
                  {
                        LowestPrior = prior;
                        LowestIndex = i;
                  }
            }

            //huh, nothing found? (probably nothing set yet, no experience)
            if(LowestIndex < 0)
            {
                  //debug(LOG_ERROR,"sortBaseDefendLoc() - No lowest elem found");
                  return true;
            }

            //swap
            if(LowestPrior < baseDefendLocPrior[nPlayer][SortBound])    //need to swap? (might be the same elem)
            {
                  //priority
                  temp = baseDefendLocPrior[nPlayer][SortBound];
                  baseDefendLocPrior[nPlayer][SortBound] = baseDefendLocPrior[nPlayer][LowestIndex];
                  baseDefendLocPrior[nPlayer][LowestIndex] = temp;

                  //x
                  temp = baseDefendLocation[nPlayer][SortBound][0];
                  baseDefendLocation[nPlayer][SortBound][0] = baseDefendLocation[nPlayer][LowestIndex][0];
                  baseDefendLocation[nPlayer][LowestIndex][0] = temp;

                  //y
                  temp = baseDefendLocation[nPlayer][SortBound][1];
                  baseDefendLocation[nPlayer][SortBound][1] = baseDefendLocation[nPlayer][LowestIndex][1];
                  baseDefendLocation[nPlayer][LowestIndex][1] = temp;
            }

            SortBound--;            //in any case lower the boundry, even if didn't swap
      }

      return true;
}

void BaseExperienceDebug(SDWORD nPlayer)
{
      SDWORD i;

      printf_console("-------------");
      for(i=0; i< MAX_BASE_DEFEND_LOCATIONS; i++)
      {
            printf_console("%d) %d - %d (%d)", i, map_coord(baseDefendLocation[nPlayer][i][0]), map_coord(baseDefendLocation[nPlayer][i][1]), baseDefendLocPrior[nPlayer][i]);
      }
      printf_console("-------------");
}

void OilExperienceDebug(SDWORD nPlayer)
{
      SDWORD i;

      printf_console("-------------");
      for(i=0; i< MAX_OIL_DEFEND_LOCATIONS; i++)
      {
            printf_console("%d) %d - %d (%d)", i, map_coord(oilDefendLocation[nPlayer][i][0]), map_coord(oilDefendLocation[nPlayer][i][1]), oilDefendLocPrior[nPlayer][i]);
      }
      printf_console("-------------");
}


//x and y are passed by script, find out if this loc is close to
//an already stored loc, if yes then increase its priority
BOOL StoreOilDefendLoc(SDWORD x, SDWORD y, SDWORD nPlayer)
{
      SDWORD      i, index;
      BOOL  found;

      index = GetOilDefendLocIndex(x, y, nPlayer);
      if(index < 0)                 //this one is new
      {
            //find an empty element
            found = false;
            for(i=0; i < MAX_OIL_DEFEND_LOCATIONS; i++)
            {
                  if(oilDefendLocation[nPlayer][i][0] < 0)  //not initialized yet
                  {
                        //addConsoleMessage("Oil defense location - NEW LOCATION.", SYSTEM_MESSAGE);

                        oilDefendLocation[nPlayer][i][0] = x;
                        oilDefendLocation[nPlayer][i][1] = y;

                        oilDefendLocPrior[nPlayer][i] = 1;

                        found = true;

                        return true;
                  }
            }

            addConsoleMessage("Oil defense location - NO SPACE LEFT.",RIGHT_JUSTIFY,SYSTEM_MESSAGE);
            return false;           //not enough space to store
      }
      else        //this one already stored
      {
            //addConsoleMessage("Oil defense location - INCREASED PRIORITY.",SYSTEM_MESSAGE);

            oilDefendLocPrior[nPlayer][index]++;      //higher the priority

            if(oilDefendLocPrior[nPlayer][index] == SDWORD_MAX)
                  oilDefendLocPrior[nPlayer][index] = 1;                //start all over

            SortOilDefendLoc(nPlayer);                      //now sort everything
      }

      return true;
}

SDWORD GetOilDefendLocIndex(SDWORD x, SDWORD y, SDWORD nPlayer)
{
      UDWORD      i,range;

      range  = world_coord(SAME_LOC_RANGE);           //in world units

      for(i=0; i < MAX_OIL_DEFEND_LOCATIONS; i++)
      {
            if((oilDefendLocation[nPlayer][i][0] > 0) && (oilDefendLocation[nPlayer][i][1] > 0))            //if this one initialized
            {
                  //check if very close to an already stored location
                  if(dirtySqrt(x,y,oilDefendLocation[nPlayer][i][0],oilDefendLocation[nPlayer][i][1]) < range)
                  {
                        return i;                                             //end here
                  }
            }
      }

      return -1;
}

//sort the priorities, placing the higher ones at the top
BOOL SortOilDefendLoc(SDWORD nPlayer)
{
      SDWORD i, prior, temp,LowestPrior,LowestIndex,SortBound;

      SortBound = MAX_OIL_DEFEND_LOCATIONS-1;   //nothing sorted yet, point at last elem

      while(SortBound >= 0)         //while didn't reach the top
      {
            LowestPrior = (SDWORD_MAX - 1);

            LowestIndex = -1;

            //find lowest element
            for(i=0; i <= SortBound; i++)
            {
                  prior = oilDefendLocPrior[nPlayer][i];
                  if(prior < LowestPrior) //lower and isn't a flag meaning this one wasn't initialized with anything
                  {
                        LowestPrior = prior;
                        LowestIndex = i;
                  }
            }

            //huh, nothing found? (probably nothing set yet, no experience)
            if(LowestIndex < 0)
            {
                  //debug(LOG_ERROR,"sortBaseDefendLoc() - No lowest elem found");
                  return true;
            }

            //swap
            if(LowestPrior < oilDefendLocPrior[nPlayer][SortBound])     //need to swap? (might be the same elem)
            {
                  //priority
                  temp = oilDefendLocPrior[nPlayer][SortBound];
                  oilDefendLocPrior[nPlayer][SortBound] = oilDefendLocPrior[nPlayer][LowestIndex];
                  oilDefendLocPrior[nPlayer][LowestIndex] = temp;

                  //x
                  temp = oilDefendLocation[nPlayer][SortBound][0];
                  oilDefendLocation[nPlayer][SortBound][0] = oilDefendLocation[nPlayer][LowestIndex][0];
                  oilDefendLocation[nPlayer][LowestIndex][0] = temp;

                  //y
                  temp = oilDefendLocation[nPlayer][SortBound][1];
                  oilDefendLocation[nPlayer][SortBound][1] = oilDefendLocation[nPlayer][LowestIndex][1];
                  oilDefendLocation[nPlayer][LowestIndex][1] = temp;
            }

            SortBound--;            //in any case lower the boundry, even if didn't swap
      }

      return true;
}

BOOL CanRememberPlayerBaseLoc(SDWORD lookingPlayer, SDWORD enemyPlayer)
{
      if(lookingPlayer < 0 || enemyPlayer < 0)
            return false;

      if(lookingPlayer >= MAX_PLAYERS || enemyPlayer >= MAX_PLAYERS)
            return false;

      if(baseLocation[lookingPlayer][enemyPlayer][0] <= 0)
            return false;
      if(baseLocation[lookingPlayer][enemyPlayer][1] <= 0)
            return false;

      return true;
}

BOOL CanRememberPlayerBaseDefenseLoc(SDWORD player, SDWORD index)
{
      if(player < 0)
            return false;
      if(player >= MAX_PLAYERS)
            return false;
      if(index < 0 || index >= MAX_BASE_DEFEND_LOCATIONS)
            return false;
      if(baseDefendLocation[player][index][0] <= 0)
            return false;
      if(baseDefendLocation[player][index][1] <= 0)
            return false;

      return true;
}

BOOL CanRememberPlayerOilDefenseLoc(SDWORD player, SDWORD index)
{
      if(player < 0)
            return false;
      if(player >= MAX_PLAYERS)
            return false;
      if(index < 0 || index >= MAX_BASE_DEFEND_LOCATIONS)
            return false;
      if(oilDefendLocation[player][index][0] <= 0)
            return false;
      if(oilDefendLocation[player][index][1] <= 0)
            return false;

      return true;
}

Generated by  Doxygen 1.6.0   Back to index