# ai_sl.cpp

Go to the documentation of this file.

    00001 /* $Id$ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * OpenTTD 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, version 2.
    00006  * OpenTTD 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.
    00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
    00008  */
    00009
    00012 #include "../stdafx.h"
    00013 #include "../company_base.h"
    00014 #include "../debug.h"
    00015 #include "saveload.h"
    00016 #include "../string_func.h"
    00017
    00018 static char _ai_saveload_name[64];
    00019 static int  _ai_saveload_version;
    00020 static char _ai_saveload_settings[1024];
    00021 static bool _ai_saveload_is_random;
    00022
    00023 static const SaveLoad _ai_company[] = {
    00024       SLEG_STR(_ai_saveload_name,        SLE_STRB),
    00025       SLEG_STR(_ai_saveload_settings,    SLE_STRB),
    00026   SLEG_CONDVAR(_ai_saveload_version,   SLE_UINT32, 108, SL_MAX_VERSION),
    00027   SLEG_CONDVAR(_ai_saveload_is_random,   SLE_BOOL, 136, SL_MAX_VERSION),
    00028        SLE_END()
    00029 };
    00030
    00031 #ifdef ENABLE_AI
    00032 #include "../ai/ai.hpp"
    00033 #include "../ai/ai_config.hpp"
    00034 #include "../network/network.h"
    00035 #include "../ai/ai_instance.hpp"
    00036
    00037 static void SaveReal_AIPL(int *index_ptr)
    00038 {
    00039   CompanyID index = (CompanyID)*index_ptr;
    00040   AIConfig *config = AIConfig::GetConfig(index);
    00041
    00042   if (config->HasAI()) {
    00043     ttd_strlcpy(_ai_saveload_name, config->GetName(), lengthof(_ai_saveload_name));
    00044     _ai_saveload_version = config->GetVersion();
    00045   } else {
    00046     /* No AI is configured for this so store an empty string as name. */
    00047     _ai_saveload_name[0] = '\0';
    00048     _ai_saveload_version = -1;
    00049   }
    00050
    00051   _ai_saveload_is_random = config->IsRandomAI();
    00052   _ai_saveload_settings[0] = '\0';
    00053   config->SettingsToString(_ai_saveload_settings, lengthof(_ai_saveload_settings));
    00054
    00055   SlObject(NULL, _ai_company);
    00056   /* If the AI was active, store his data too */
    00057   if (Company::IsValidAiID(index)) AI::Save(index);
    00058 }
    00059
    00060 static void Load_AIPL()
    00061 {
    00062   /* Free all current data */
    00063   for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
    00064     AIConfig::GetConfig(c, AIConfig::AISS_FORCE_GAME)->ChangeAI(NULL);
    00065   }
    00066
    00067   CompanyID index;
    00068   while ((index = (CompanyID)SlIterateArray()) != (CompanyID)-1) {
    00069     _ai_saveload_version = -1;
    00070     SlObject(NULL, _ai_company);
    00071
    00072     if (_networking && !_network_server) {
    00073       if (Company::IsValidAiID(index)) AIInstance::LoadEmpty();
    00074       continue;
    00075     }
    00076
    00077     AIConfig *config = AIConfig::GetConfig(index, AIConfig::AISS_FORCE_GAME);
    00078     if (StrEmpty(_ai_saveload_name)) {
    00079       /* A random AI. */
    00080       config->ChangeAI(NULL, -1, false, true);
    00081     } else {
    00082       config->ChangeAI(_ai_saveload_name, _ai_saveload_version, false, _ai_saveload_is_random);
    00083       if (!config->HasAI()) {
    00084         /* No version of the AI available that can load the data. Try to load the
    00085          * latest version of the AI instead. */
    00086         config->ChangeAI(_ai_saveload_name, -1, false, _ai_saveload_is_random);
    00087         if (!config->HasAI()) {
    00088           if (strcmp(_ai_saveload_name, "%_dummy") != 0) {
    00089             DEBUG(ai, 0, "The savegame has an AI by the name '%s', version %d which is no longer available.", _ai_saveload_name, _ai_saveload_version);
    00090             DEBUG(ai, 0, "A random other AI will be loaded in its place.");
    00091           } else {
    00092             DEBUG(ai, 0, "The savegame had no AIs available at the time of saving.");
    00093             DEBUG(ai, 0, "A random available AI will be loaded now.");
    00094           }
    00095         } else {
    00096           DEBUG(ai, 0, "The savegame has an AI by the name '%s', version %d which is no longer available.", _ai_saveload_name, _ai_saveload_version);
    00097           DEBUG(ai, 0, "The latest version of that AI has been loaded instead, but it'll not get the savegame data as it's incompatible.");
    00098         }
    00099         /* Make sure the AI doesn't get the saveload data, as he was not the
    00100          *  writer of the saveload data in the first place */
    00101         _ai_saveload_version = -1;
    00102       }
    00103     }
    00104
    00105     config->StringToSettings(_ai_saveload_settings);
    00106
    00107     /* Start the AI directly if it was active in the savegame */
    00108     if (Company::IsValidAiID(index)) {
    00109       AI::StartNew(index, false);
    00110       AI::Load(index, _ai_saveload_version);
    00111     }
    00112   }
    00113 }
    00114
    00115 static void Save_AIPL()
    00116 {
    00117   for (int i = COMPANY_FIRST; i < MAX_COMPANIES; i++) {
    00118     SlSetArrayIndex(i);
    00119     SlAutolength((AutolengthProc *)SaveReal_AIPL, &i);
    00120   }
    00121 }
    00122
    00123 extern const ChunkHandler _ai_chunk_handlers[] = {
    00124   { 'AIPL', Save_AIPL, Load_AIPL, NULL, NULL, CH_ARRAY | CH_LAST},
    00125 };
    00126 #else
    00127
    00129 enum SQSaveLoadType {
    00130   SQSL_INT             = 0x00,
    00131   SQSL_STRING          = 0x01,
    00132   SQSL_ARRAY           = 0x02,
    00133   SQSL_TABLE           = 0x03,
    00134   SQSL_BOOL            = 0x04,
    00135   SQSL_NULL            = 0x05,
    00136   SQSL_ARRAY_TABLE_END = 0xFF,
    00137 };
    00138
    00139 static byte _ai_sl_byte;
    00140
    00141 static const SaveLoad _ai_byte[] = {
    00142   SLEG_VAR(_ai_sl_byte, SLE_UINT8),
    00143   SLE_END()
    00144 };
    00145
    00146 static bool LoadObjects()
    00147 {
    00148   SlObject(NULL, _ai_byte);
    00149   switch (_ai_sl_byte) {
    00150     case SQSL_INT: {
    00151       int value;
    00152       SlArray(&value, 1, SLE_INT32);
    00153       return true;
    00154     }
    00155
    00156     case SQSL_STRING: {
    00157       SlObject(NULL, _ai_byte);
    00158       static char buf[256];
    00159       SlArray(buf, _ai_sl_byte, SLE_CHAR);
    00160       return true;
    00161     }
    00162
    00163     case SQSL_ARRAY:
    00164       while (LoadObjects()) { }
    00165       return true;
    00166
    00167     case SQSL_TABLE:
    00168       while (LoadObjects()) { LoadObjects(); }
    00169       return true;
    00170
    00171     case SQSL_BOOL:
    00172       SlObject(NULL, _ai_byte);
    00173       return true;
    00174
    00175     case SQSL_NULL:
    00176       return true;
    00177
    00178     case SQSL_ARRAY_TABLE_END:
    00179       return false;
    00180
    00181     default: SlErrorCorrupt("Invalid AI data type");
    00182   }
    00183 }
    00184
    00185 static void Load_AIPL()
    00186 {
    00187   CompanyID index;
    00188   while ((index = (CompanyID)SlIterateArray()) != (CompanyID)-1) {
    00189     SlObject(NULL, _ai_company);
    00190
    00191     if (!Company::IsValidAiID(index)) continue;
    00192     SlObject(NULL, _ai_byte);
    00193     /* Check if there was anything saved at all. */
    00194     if (_ai_sl_byte == 0) continue;
    00195     LoadObjects();
    00196   }
    00197 }
    00198
    00199 extern const ChunkHandler _ai_chunk_handlers[] = {
    00200   { 'AIPL', NULL, Load_AIPL, NULL, NULL, CH_ARRAY | CH_LAST},
    00201 };
    00202 #endif /* ENABLE_AI */