OTOWNRES.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  1. /*
  2. * Seven Kingdoms: Ancient Adversaries
  3. *
  4. * Copyright 1997,1998 Enlight Software Ltd.
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. *
  19. */
  20. //Filename : OTOWNRES.CPP
  21. //Description : Town resource object
  22. #include <OSYS.h>
  23. #include <OGAMESET.h>
  24. #include <OWORLD.h>
  25. #include <OIMGRES.h>
  26. #include <ORACERES.h>
  27. #include <OTOWNRES.h>
  28. //---------- define constant ------------//
  29. #define TOWN_LAYOUT_DB "TOWNLAY"
  30. #define TOWN_SLOT_DB "TOWNSLOT"
  31. #define TOWN_BUILD_TYPE_DB "TOWNBTYP"
  32. #define TOWN_BUILD_DB "TOWNBULD"
  33. #define TOWN_NAME_DB "TOWNNAME"
  34. //------- Begin of function TownRes::TownRes -----------//
  35. TownRes::TownRes()
  36. {
  37. init_flag=0;
  38. }
  39. //--------- End of function TownRes::TownRes -----------//
  40. //---------- Begin of function TownRes::init -----------//
  41. //
  42. // This function must be called after a map is generated.
  43. //
  44. void TownRes::init()
  45. {
  46. deinit();
  47. //----- open town material bitmap resource file -------//
  48. String str;
  49. str = DIR_RES;
  50. str += "I_TOWN.RES";
  51. res_bitmap.init_imported(str,1); // 1-read all into buffer
  52. //------- load database information --------//
  53. load_town_slot(); // load_town_slot() must be called first before load_town_layout(), as load_town_layout() accesses town_slot_array
  54. load_town_layout();
  55. load_town_build_type();
  56. load_town_build();
  57. load_town_name();
  58. init_flag=1;
  59. }
  60. //---------- End of function TownRes::init -----------//
  61. //---------- Begin of function TownRes::deinit -----------//
  62. void TownRes::deinit()
  63. {
  64. if( init_flag )
  65. {
  66. mem_del(town_layout_array);
  67. mem_del(town_slot_array);
  68. mem_del(town_build_array);
  69. mem_del(town_build_type_array);
  70. mem_del(town_name_array);
  71. mem_del(town_name_used_array);
  72. res_bitmap.deinit();
  73. init_flag=0;
  74. }
  75. }
  76. //---------- End of function TownRes::deinit -----------//
  77. //------- Begin of function TownRes::load_town_layout -------//
  78. //
  79. // Read in information from TOWNLAY.DBF.
  80. //
  81. void TownRes::load_town_layout()
  82. {
  83. TownLayoutRec *townLayoutRec;
  84. TownLayout *townLayout;
  85. TownSlot *townSlot;
  86. int i, j;
  87. Database *dbTownLayout = game_set.open_db(TOWN_LAYOUT_DB);
  88. town_layout_count = (short) dbTownLayout->rec_count();
  89. town_layout_array = (TownLayout*) mem_add( sizeof(TownLayout)*town_layout_count );
  90. //------ read in town layout info array -------//
  91. memset( town_layout_array, 0, sizeof(TownLayout) * town_layout_count );
  92. for( i=0 ; i<town_layout_count ; i++ )
  93. {
  94. townLayoutRec = (TownLayoutRec*) dbTownLayout->read(i+1);
  95. townLayout = town_layout_array+i;
  96. townLayout->first_slot_recno = m.atoi(townLayoutRec->first_slot, TownLayoutRec::FIRST_SLOT_LEN);
  97. townLayout->slot_count = m.atoi(townLayoutRec->slot_count, TownLayoutRec::SLOT_COUNT_LEN);
  98. // ###### begin Gilbert 9/9 ########//
  99. // townLayout->ground_bitmap_ptr = image_spict.get_ptr( m.nullify(townLayoutRec->ground_name, TownLayoutRec::GROUND_NAME_LEN) );
  100. townLayout->ground_bitmap_ptr = image_tpict.get_ptr( m.nullify(townLayoutRec->ground_name, TownLayoutRec::GROUND_NAME_LEN) );
  101. // ###### end Gilbert 9/9 ########//
  102. err_if( townLayout->slot_count > MAX_TOWN_LAYOUT_SLOT )
  103. err_now( "Error: MAX_TOWN_LAYOUT_SLOT limit exceeded." );
  104. //----- calculate min_population & max_population -----//
  105. townSlot = town_slot_array+townLayout->first_slot_recno-1;
  106. for( j=0 ; j<townLayout->slot_count ; j++, townSlot++ )
  107. {
  108. if( townSlot->build_type==TOWN_OBJECT_HOUSE ) // if there is a building in this slot
  109. townLayout->build_count++;
  110. }
  111. }
  112. }
  113. //--------- End of function TownRes::load_town_layout ---------//
  114. //------- Begin of function TownRes::load_town_slot -------//
  115. //
  116. // Read in information from TOWNSLOT.DBF.
  117. //
  118. void TownRes::load_town_slot()
  119. {
  120. TownSlotRec *townSlotRec;
  121. TownSlot *townSlot;
  122. int i;
  123. Database *dbTownSlot = game_set.open_db(TOWN_SLOT_DB);
  124. town_slot_count = (short) dbTownSlot->rec_count();
  125. town_slot_array = (TownSlot*) mem_add( sizeof(TownSlot)*town_slot_count );
  126. //------ read in town slot info array -------//
  127. memset( town_slot_array, 0, sizeof(TownSlot) * town_slot_count );
  128. for( i=0 ; i<town_slot_count ; i++ )
  129. {
  130. townSlotRec = (TownSlotRec*) dbTownSlot->read(i+1);
  131. townSlot = town_slot_array+i;
  132. townSlot->base_x = m.atoi(townSlotRec->base_x, TownSlotRec::POS_LEN);
  133. townSlot->base_y = m.atoi(townSlotRec->base_y, TownSlotRec::POS_LEN);
  134. townSlot->build_type = m.atoi(townSlotRec->type_id, TownSlotRec::TYPE_ID_LEN);
  135. townSlot->build_code = m.atoi(townSlotRec->build_code, TownSlotRec::BUILD_CODE_LEN);
  136. err_when( townSlot->build_type == TOWN_OBJECT_FARM &&
  137. (townSlot->build_code < 1 || townSlot->build_code > 9) );
  138. }
  139. }
  140. //--------- End of function TownRes::load_town_slot ---------//
  141. //------- Begin of function TownRes::load_town_build_type -------//
  142. //
  143. // Read in information from TOWNBTYP.DBF.
  144. //
  145. void TownRes::load_town_build_type()
  146. {
  147. TownBuildTypeRec *buildTypeRec;
  148. TownBuildType *buildType;
  149. int i;
  150. Database *dbTownBuildType = game_set.open_db(TOWN_BUILD_TYPE_DB);
  151. town_build_type_count = (short) dbTownBuildType->rec_count();
  152. town_build_type_array = (TownBuildType*) mem_add( sizeof(TownBuildType)*town_build_type_count );
  153. //------ read in TownBuildType info array -------//
  154. memset( town_build_type_array, 0, sizeof(TownBuildType) * town_build_type_count );
  155. for( i=0 ; i<town_build_type_count ; i++ )
  156. {
  157. buildTypeRec = (TownBuildTypeRec*) dbTownBuildType->read(i+1);
  158. buildType = town_build_type_array+i;
  159. buildType->first_build_recno = m.atoi(buildTypeRec->first_build, TownBuildTypeRec::FIRST_BUILD_LEN);
  160. buildType->build_count = m.atoi(buildTypeRec->build_count, TownBuildTypeRec::BUILD_COUNT_LEN);
  161. }
  162. }
  163. //--------- End of function TownRes::load_town_build_type ---------//
  164. //------- Begin of function TownRes::load_town_build -------//
  165. //
  166. // Read in information from TOWNBULD.DBF.
  167. //
  168. void TownRes::load_town_build()
  169. {
  170. TownBuildRec *townBuildRec;
  171. TownBuild *townBuild;
  172. int i;
  173. long bitmapOffset;
  174. Database *dbTownBuild = game_set.open_db(TOWN_BUILD_DB);
  175. town_build_count = (short) dbTownBuild->rec_count();
  176. town_build_array = (TownBuild*) mem_add( sizeof(TownBuild)*town_build_count );
  177. err_when( town_build_count > 255 ); // BYTE is used in TownZone::slot_array[]
  178. //------ read in town build info array -------//
  179. memset( town_build_array, 0, sizeof(TownBuild) * town_build_count );
  180. for( i=0 ; i<town_build_count ; i++ )
  181. {
  182. townBuildRec = (TownBuildRec*) dbTownBuild->read(i+1);
  183. townBuild = town_build_array+i;
  184. townBuild->build_type = m.atoi(townBuildRec->type_id, TownBuildRec::TYPE_ID_LEN);
  185. townBuild->build_code = m.atoi(townBuildRec->build_code, TownBuildRec::BUILD_CODE_LEN);
  186. townBuild->race_id = m.atoi(townBuildRec->race_id, TownBuildRec::RACE_ID_LEN);
  187. memcpy( &bitmapOffset, townBuildRec->bitmap_ptr, sizeof(long) );
  188. townBuild->bitmap_ptr = res_bitmap.read_imported(bitmapOffset);
  189. townBuild->bitmap_width = *((short*)townBuild->bitmap_ptr);
  190. townBuild->bitmap_height = *(((short*)townBuild->bitmap_ptr)+1);
  191. }
  192. }
  193. //--------- End of function TownRes::load_town_build ---------//
  194. //------- Begin of function TownRes::load_town_name -------//
  195. //
  196. // Read in information from TOWNNAME.DBF.
  197. //
  198. // Note: race_res must be initialized before calling this function.
  199. //
  200. void TownRes::load_town_name()
  201. {
  202. TownNameRec *townNameRec;
  203. TownName *townName;
  204. int i;
  205. Database *dbTownName = game_set.open_db(TOWN_NAME_DB);
  206. town_name_count = dbTownName->rec_count();
  207. town_name_array = (TownName*) mem_add( sizeof(TownName)*town_name_count );
  208. town_name_used_array = (char*) mem_add( sizeof(town_name_used_array[0]) * town_name_count ); // store the used_count separately from town_name_array to faciliate file saving
  209. memset( town_name_used_array, 0, sizeof(town_name_used_array[0]) * town_name_count );
  210. //------ read in TownName info array -------//
  211. int raceId=0;
  212. for( i=1 ; i<=town_name_count ; i++ )
  213. {
  214. townNameRec = (TownNameRec*) dbTownName->read(i);
  215. townName = town_name_array+i-1;
  216. m.rtrim_fld( townName->name, townNameRec->name, townNameRec->NAME_LEN );
  217. if( townName->name[0]=='@' ) // next race
  218. {
  219. int j;
  220. for( j=1 ; j<=MAX_RACE ; j++ )
  221. {
  222. if( strcmp( race_res[j]->code, townName->name+1 ) == 0 )
  223. break;
  224. }
  225. err_when( j > MAX_RACE );
  226. if( raceId )
  227. race_res[raceId]->town_name_count = i-race_res[raceId]->first_town_name_recno;
  228. raceId = j;
  229. race_res[raceId]->first_town_name_recno = i+1;
  230. }
  231. }
  232. //-- set the town_name_count of the last town in TOWNNAME.DBF --//
  233. race_res[raceId]->town_name_count = i-race_res[raceId]->first_town_name_recno;
  234. }
  235. //--------- End of function TownRes::load_town_name ---------//
  236. //---------- Begin of function TownRes::scan_build -----------//
  237. //
  238. // Set the given slot with a building that fits the given criteria
  239. //
  240. // <int> slotId - the slot id. of the current town section to be set.
  241. // <int> raceId - one of the building selection criteria
  242. // (0-any race)
  243. //
  244. // return : <int> townBuildId - the id. of the town building
  245. //
  246. int TownRes::scan_build(int slotId, int raceId)
  247. {
  248. enum { MAX_SCAN_ID = 100 };
  249. TownSlot* townSlot = town_res.get_slot(slotId);
  250. TownBuildType* buildType;
  251. TownBuild* townBuild;
  252. int i, buildRecno, matchCount=0;
  253. int scanIdArray[MAX_SCAN_ID];
  254. //---- get the building type of the slot ------//
  255. buildType = town_res.get_build_type(townSlot->build_type);
  256. err_if( buildType->build_count==0 )
  257. err_here();
  258. //------ scan_build buildings of the specified type ------//
  259. buildRecno = buildType->first_build_recno;
  260. townBuild = town_res.get_build(buildRecno); // the pointer to the first building of the specified type
  261. for( i=buildType->build_count ; i>0 ; i--, townBuild++, buildRecno++ )
  262. {
  263. if( townBuild->build_code == townSlot->build_code )
  264. {
  265. if( !raceId || townBuild->race_id == raceId )
  266. {
  267. scanIdArray[matchCount] = buildRecno;
  268. if( ++matchCount >= MAX_SCAN_ID )
  269. break;
  270. }
  271. }
  272. }
  273. //--- pick one from those plants that match the criteria ---//
  274. if( matchCount > 0 )
  275. {
  276. int buildId = scanIdArray[m.random(matchCount)];
  277. #ifdef DEBUG
  278. town_res.get_build( buildId ); // get_build() will error if buildId is not valid
  279. #endif
  280. return buildId;
  281. }
  282. else
  283. return 0;
  284. }
  285. //---------- End of function TownRes::scan_build -----------//
  286. #ifdef DEBUG
  287. //---------- Begin of function TownRes::get_layout -----------//
  288. TownLayout* TownRes::get_layout(int recNo)
  289. {
  290. err_if( recNo<1 || recNo>town_layout_count )
  291. err_now( "TownRes::get_layout()" );
  292. return town_layout_array+recNo-1;
  293. }
  294. //------------ End of function TownRes::get_layout -----------//
  295. //---------- Begin of function TownRes::get_slot -----------//
  296. TownSlot* TownRes::get_slot(int recNo)
  297. {
  298. err_if( recNo<1 || recNo>town_slot_count )
  299. err_now( "TownRes::get_slot()" );
  300. return town_slot_array+recNo-1;
  301. }
  302. //------------ End of function TownRes::get_slot -----------//
  303. //---------- Begin of function TownRes::get_build_type -----------//
  304. TownBuildType* TownRes::get_build_type(int recNo)
  305. {
  306. err_if( recNo<1 || recNo>town_build_type_count )
  307. err_now( "TownRes::get_build_type()" );
  308. return town_build_type_array+recNo-1;
  309. }
  310. //------------ End of function TownRes::get_build_type -----------//
  311. //---------- Begin of function TownRes::get_build -----------//
  312. TownBuild* TownRes::get_build(int recNo)
  313. {
  314. err_if( recNo<1 || recNo>town_build_count )
  315. err_now( "TownRes::get_build()" );
  316. return town_build_array+recNo-1;
  317. }
  318. //------------ End of function TownRes::get_build -----------//
  319. #endif
  320. //---------- Begin of function TownRes::get_name -----------//
  321. char* TownRes::get_name(int recNo)
  322. {
  323. err_if( recNo<1 || recNo>town_name_count )
  324. err_now( "TownRes::get_name()" );
  325. return town_name_array[recNo-1].name;
  326. }
  327. //------------ End of function TownRes::get_name -----------//
  328. //--------- Begin of function TownRes::get_new_name_id ----------//
  329. //
  330. int TownRes::get_new_name_id(int raceId)
  331. {
  332. RaceInfo* raceInfo = race_res[raceId];
  333. err_when( raceInfo->town_name_used_count > raceInfo->town_name_count );
  334. int townNameId;
  335. //----- if all town names have been used already -----//
  336. //--- scan the town name one by one and pick an unused one ---//
  337. if( raceInfo->town_name_used_count == raceInfo->town_name_count )
  338. {
  339. int nameId = m.random(raceInfo->town_name_count)+1; // this is the id. of one race only
  340. for( int i=raceInfo->town_name_count ; i>0 ; i-- )
  341. {
  342. if( ++nameId > raceInfo->town_name_count )
  343. nameId = 1;
  344. if( town_name_used_array[raceInfo->first_town_name_recno+nameId-2]==0 ) // -2 is the total of two -1, (one with first_town_name_recno, another with town_name_used_array[]
  345. break;
  346. }
  347. townNameId = raceInfo->first_town_name_recno + nameId - 1;
  348. }
  349. else
  350. {
  351. raceInfo->town_name_used_count++;
  352. townNameId = raceInfo->first_town_name_recno + raceInfo->town_name_used_count - 1;
  353. }
  354. err_when( townNameId < 1 || townNameId > town_name_count );
  355. town_name_used_array[townNameId-1]++;
  356. return townNameId;
  357. }
  358. //--------- End of function TownRes::get_new_name_id ----------//
  359. //--------- Begin of function TownRes::free_name_id ----------//
  360. //
  361. // Free an used name id.
  362. //
  363. void TownRes::free_name_id(int townNameId)
  364. {
  365. town_name_used_array[townNameId-1]--;
  366. err_when( town_name_used_array[townNameId-1] < 0 );
  367. }
  368. //--------- End of function TownRes::free_name_id ----------//