ORACERES.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  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 : ORACERES.CPP
  21. //Description : Race resource object
  22. #include <OSYS.h>
  23. #include <OGAMESET.h>
  24. #include <OSKILL.h>
  25. #include <OUNITRES.h>
  26. #include <ORACERES.h>
  27. #include <OTRANSL.h>
  28. //---------- #define constant ------------//
  29. #define RACE_DB "RACE"
  30. #define RACE_NAME_DB "RACENAME"
  31. //------- Begin of function RaceRes::RaceRes -----------//
  32. RaceRes::RaceRes()
  33. {
  34. init_flag=0;
  35. }
  36. //--------- End of function RaceRes::RaceRes -----------//
  37. //---------- Begin of function RaceRes::init -----------//
  38. //
  39. // This function must be called after a map is generated.
  40. //
  41. void RaceRes::init()
  42. {
  43. deinit();
  44. //----- open unit bitmap resource file -------//
  45. String str;
  46. str = DIR_RES;
  47. str += "I_RACE.RES";
  48. res_bitmap.init_imported(str, 1); // 1-don't read all into buffer
  49. //------- load database information --------//
  50. load_race_info();
  51. load_name();
  52. init_flag=1;
  53. }
  54. //---------- End of function RaceRes::init -----------//
  55. //---------- Begin of function RaceRes::deinit -----------//
  56. void RaceRes::deinit()
  57. {
  58. if( init_flag )
  59. {
  60. mem_del(race_info_array);
  61. mem_del(name_array);
  62. mem_del(name_used_array);
  63. init_flag=0;
  64. }
  65. }
  66. //---------- End of function RaceRes::deinit -----------//
  67. //------- Begin of function RaceRes::load_race_info -------//
  68. //
  69. // Read in information of RACE.DBF into memory array
  70. //
  71. void RaceRes::load_race_info()
  72. {
  73. RaceRec *raceRec;
  74. RaceInfo *raceInfo;
  75. int i, unitId;
  76. long bitmapOffset;
  77. Database *dbRace = game_set.open_db(RACE_DB);
  78. race_count = (short) dbRace->rec_count();
  79. race_info_array = (RaceInfo*) mem_add( sizeof(RaceInfo)*race_count );
  80. //------ read in race information array -------//
  81. memset( race_info_array, 0, sizeof(RaceInfo) * race_count );
  82. for( i=0 ; i<race_count ; i++ )
  83. {
  84. raceRec = (RaceRec*) dbRace->read(i+1);
  85. raceInfo = race_info_array+i;
  86. raceInfo->race_id = i+1;
  87. m.rtrim_fld( raceInfo->code, raceRec->code, raceRec->CODE_LEN );
  88. m.rtrim_fld( raceInfo->name, raceRec->name, raceRec->NAME_LEN );
  89. m.rtrim_fld( raceInfo->adjective, raceRec->adjective, raceRec->ADJECTIVE_LEN );
  90. #if(defined(GERMAN) || defined(FRENCH) || defined(SPANISH))
  91. translate.multi_to_win(raceInfo->name, raceInfo->NAME_LEN);
  92. translate.multi_to_win(raceInfo->adjective, raceInfo->ADJECTIVE_LEN);
  93. #endif
  94. memcpy( &bitmapOffset, raceRec->icon_bitmap_ptr, sizeof(long) );
  95. raceInfo->icon_bitmap_ptr = res_bitmap.read_imported(bitmapOffset);
  96. err_when( !raceInfo->icon_bitmap_ptr );
  97. for( unitId=1 ; unitId<=MAX_UNIT_TYPE ; unitId++ )
  98. {
  99. if( unit_res[unitId]->race_id == i+1 )
  100. {
  101. raceInfo->basic_unit_id = unitId;
  102. break;
  103. }
  104. }
  105. }
  106. }
  107. //--------- End of function RaceRes::load_race_info ---------//
  108. //------- Begin of function RaceRes::load_name -------//
  109. //
  110. // Read in information from RACENAME.DBF.
  111. //
  112. // Note: race_res must be initialized before calling this function.
  113. //
  114. void RaceRes::load_name()
  115. {
  116. #define MAX_SINGLE_RACE_NAME 255 // cannot be more than 255 in each name group, as Unit::name_id is an <int> and half of it is for the first name and another half of it is for the last name
  117. RaceNameRec *raceNameRec;
  118. RaceName *raceName;
  119. int i, j;
  120. Database *dbRaceName = game_set.open_db(RACE_NAME_DB);
  121. name_count = (short) dbRaceName->rec_count();
  122. name_array = (RaceName*) mem_add( sizeof(RaceName)*name_count );
  123. name_used_array = (char*) mem_add( sizeof(name_used_array[0])*name_count );
  124. memset( name_used_array, 0, sizeof(name_used_array[0])*name_count );
  125. //------ read in RaceName info array -------//
  126. int raceId=0, isFirstName;
  127. for( i=1 ; i<=name_count ; i++ )
  128. {
  129. raceNameRec = (RaceNameRec*) dbRaceName->read(i);
  130. raceName = name_array+i-1;
  131. m.rtrim_fld( raceName->name, raceNameRec->name, raceNameRec->NAME_LEN );
  132. // translate for all language
  133. translate.multi_to_win(raceName->name, raceName->NAME_LEN);
  134. if( raceName->name[0]=='@' )
  135. {
  136. if( raceId )
  137. {
  138. if( isFirstName )
  139. race_res[raceId]->first_name_count = i-race_res[raceId]->first_first_name_id;
  140. else
  141. race_res[raceId]->last_name_count = i-race_res[raceId]->first_last_name_id;
  142. err_when( race_res[raceId]->first_name_count > MAX_SINGLE_RACE_NAME );
  143. err_when( race_res[raceId]->last_name_count > MAX_SINGLE_RACE_NAME );
  144. }
  145. //----- get the race id. of the following names -----//
  146. for( j=1 ; j<=MAX_RACE ; j++ )
  147. {
  148. if( strcmp( race_res[j]->code, m.nullify(raceName->name+2, RaceInfo::CODE_LEN) )==0 )
  149. {
  150. raceId = j;
  151. break;
  152. }
  153. }
  154. err_when( j>MAX_RACE );
  155. //----------------------------------------------//
  156. isFirstName = raceName->name[1]=='1'; // whether the following names are first names
  157. if( isFirstName )
  158. race_res[raceId]->first_first_name_id = i+1; // next record following the "@RACECODE" is the first name record
  159. else
  160. race_res[raceId]->first_last_name_id = i+1; // next record following the "@RACECODE" is the first name record
  161. }
  162. }
  163. //------- finish up the last race in the list ------//
  164. if( raceId )
  165. {
  166. if( isFirstName )
  167. race_res[raceId]->first_name_count = i-race_res[raceId]->first_first_name_id;
  168. else
  169. race_res[raceId]->last_name_count = i-race_res[raceId]->first_last_name_id;
  170. err_when( race_res[raceId]->first_name_count > MAX_SINGLE_RACE_NAME );
  171. err_when( race_res[raceId]->last_name_count > MAX_SINGLE_RACE_NAME );
  172. }
  173. }
  174. //--------- End of function RaceRes::load_name ---------//
  175. //---------- Begin of function RaceRes::is_same_race -----------//
  176. //
  177. // Return whether the two given race ids are the same.
  178. //
  179. // This function is called instead of direct in-line comparsion
  180. // because it is easier to research all lines that compare races
  181. // by keyword searching is_same_race().
  182. //
  183. int RaceRes::is_same_race(int raceId1, int raceId2)
  184. {
  185. return raceId1 == raceId2;
  186. }
  187. //---------- End of function RaceRes::is_same_race -----------//
  188. //----- Start of function RaceInfo::get_new_name_id ------//
  189. //
  190. // Return an unused name id. and set the used_count of the
  191. // first and first name to 1.
  192. //
  193. WORD RaceInfo::get_new_name_id()
  194. {
  195. //---------- get the first name ----------//
  196. int i;
  197. int firstNameId = m.random(first_name_count)+1;
  198. for( i=1 ; i<=first_name_count ; i++ )
  199. {
  200. if( ++firstNameId > first_name_count )
  201. firstNameId = 1;
  202. //--- try to get an unused first name -----//
  203. //--- if all names have been used (when i>first_name_count), use the first selected random name id. --//
  204. if( !race_res.name_used_array[first_first_name_id+firstNameId-2] )
  205. break;
  206. }
  207. int nameRecno = first_first_name_id+firstNameId-1;
  208. err_when( nameRecno < 1 || nameRecno > race_res.name_count );
  209. race_res.name_used_array[nameRecno-1]++;
  210. //---------- get the last name ----------//
  211. int lastNameId;
  212. if( last_name_count==0 ) // if there is no last name for this race, add Roman letter as the last name
  213. {
  214. lastNameId = race_res.name_used_array[first_first_name_id+firstNameId-2];
  215. }
  216. else // this race has last names
  217. {
  218. lastNameId = m.random(last_name_count)+1;
  219. for( i=1 ; i<=last_name_count ; i++ )
  220. {
  221. if( ++lastNameId > last_name_count )
  222. lastNameId = 1;
  223. //--- try to get an unused last name -----//
  224. //--- if all names have been used, use the first selected random name id. --//
  225. if( !race_res.name_used_array[first_last_name_id+lastNameId-2] )
  226. break;
  227. }
  228. nameRecno = first_last_name_id+lastNameId-1;
  229. err_when( nameRecno < 1 || nameRecno > race_res.name_count );
  230. race_res.name_used_array[nameRecno-1]++;
  231. }
  232. //--- nameId is a combination of first & last name id. ----//
  233. err_when( firstNameId < 1 || firstNameId > first_name_count );
  234. err_when( last_name_count>0 && (lastNameId < 1 || lastNameId > last_name_count) );
  235. return (firstNameId<<8) + lastNameId;
  236. }
  237. //------ End of function RaceInfo::get_new_name_id -------//
  238. //----- Start of function RaceInfo::free_name_id ------//
  239. //
  240. // Free an used name id.
  241. //
  242. // Unit names are freed when they settle into a town.
  243. // But unit names are not freed when they are killed.
  244. //
  245. void RaceInfo::free_name_id(WORD nameId)
  246. {
  247. err_when( !nameId );
  248. int firstNameId = (nameId>>8);
  249. int nameRecno = first_first_name_id+firstNameId-1;
  250. err_when( firstNameId < 1 || firstNameId > first_name_count );
  251. err_when( nameRecno < 1 || nameRecno > race_res.name_count );
  252. race_res.name_used_array[nameRecno-1]--;
  253. err_when( race_res.name_used_array[nameRecno-1] < 0 );
  254. if( last_name_count > 0 ) // some races do not have last names
  255. {
  256. int lastNameId = (nameId&0xFF);
  257. int nameRecno = first_last_name_id+lastNameId-1;
  258. err_when( lastNameId < 1 || lastNameId > last_name_count );
  259. err_when( nameRecno < 1 || nameRecno > race_res.name_count );
  260. race_res.name_used_array[nameRecno-1]--;
  261. err_when( race_res.name_used_array[nameRecno-1] < 0 );
  262. }
  263. }
  264. //------ End of function RaceInfo::free_name_id -------//
  265. //----- Start of function RaceInfo::use_name_id ------//
  266. //
  267. // Claim the use a specific name id.
  268. //
  269. void RaceInfo::use_name_id(WORD nameId)
  270. {
  271. int firstNameId = (nameId>>8);
  272. int nameRecno = first_first_name_id+firstNameId-1;
  273. err_when( firstNameId < 1 || firstNameId > first_name_count );
  274. err_when( nameRecno < 1 || nameRecno > race_res.name_count );
  275. race_res.name_used_array[nameRecno-1]++;
  276. if( last_name_count > 0 ) // some races do not have last names
  277. {
  278. int lastNameId = (nameId&0xFF);
  279. int nameRecno = first_last_name_id+lastNameId-1;
  280. err_when( lastNameId < 1 || lastNameId > last_name_count );
  281. err_when( nameRecno < 1 || nameRecno > race_res.name_count );
  282. race_res.name_used_array[nameRecno-1]++;
  283. }
  284. }
  285. //------ End of function RaceInfo::use_name_id -------//
  286. //-------- Start of function RaceInfo::get_name -------------//
  287. //
  288. // <WORD> nameId - higher byte - first name id, lower byte - last name id.
  289. // [int] nameType - 0-full name, 1-first name only, 2-last name only
  290. //
  291. char* RaceInfo::get_name(WORD nameId, int nameType)
  292. {
  293. static String str;
  294. if( nameId==0 )
  295. {
  296. return "";
  297. }
  298. else
  299. {
  300. if( nameType != 2 ) // 2-is for last name only
  301. {
  302. int firstNameId = (nameId>>8);
  303. err_when( firstNameId > first_name_count );
  304. int nameRecno = first_first_name_id+firstNameId-1;
  305. err_when( nameRecno < 1 || nameRecno > race_res.name_count );
  306. str = race_res.name_array[nameRecno-1].name;
  307. if( nameType==1 ) // first name only
  308. return str;
  309. }
  310. else
  311. {
  312. if( last_name_count==0 ) // if this race does not have last name
  313. return "";
  314. str = "";
  315. }
  316. //--------- last name ----------//
  317. int lastNameId = (nameId&0xFF);
  318. if( last_name_count==0 ) // if there is no last name for this race
  319. {
  320. if( lastNameId > 1 ) // no need to display roman letter "I" for the first one
  321. {
  322. if( str.len() > 0 )
  323. str += " ";
  324. str += m.roman_number(lastNameId);
  325. }
  326. }
  327. else
  328. {
  329. err_when( lastNameId > last_name_count );
  330. int nameRecno = first_last_name_id+lastNameId-1;
  331. err_when( nameRecno < 1 || nameRecno > race_res.name_count );
  332. if( str.len() > 0 )
  333. str += " ";
  334. str += race_res.name_array[nameRecno-1].name;
  335. }
  336. return str;
  337. }
  338. }
  339. //--------- End of function RaceInfo::get_name ---------------//
  340. //-------- Start of function RaceInfo::get_single_name -------------//
  341. //
  342. // Return a single word name. If there are last names for this race,
  343. // return the last name, otherwise, return the first name.
  344. //
  345. // <WORD> nameId - higher byte - first name id, lower byte - last name id.
  346. //
  347. char* RaceInfo::get_single_name(WORD nameId)
  348. {
  349. switch( race_id )
  350. {
  351. case RACE_NORMAN:
  352. case RACE_VIKING:
  353. #if (MAX_RACE >= 10)
  354. case RACE_INDIAN:
  355. case RACE_ZULU:
  356. #endif
  357. return get_name(nameId, 1); // 1-first name only
  358. case RACE_CHINESE:
  359. case RACE_JAPANESE:
  360. return get_name(nameId, 2); // 2-last name only
  361. default:
  362. return get_name(nameId); // the whole name
  363. }
  364. }
  365. //--------- End of function RaceInfo::get_single_name ---------------//
  366. //---------- Begin of function RaceRes::operator[] -----------//
  367. RaceInfo* RaceRes::operator[](int raceId)
  368. {
  369. err_if( raceId<1 || raceId>race_count )
  370. err_now( "RaceRes::operator[]" );
  371. return race_info_array+raceId-1;
  372. }
  373. //------------ End of function RaceRes::operator[] -----------//