ODYNARRB.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  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 : ODYNARRB.CPP
  21. //Description : Object Dynamic Array Version B
  22. #include <OINFO.h>
  23. #include <ODYNARRB.h>
  24. //----------------------------------------------------------//
  25. //
  26. // Version B is different from Version A as :
  27. //
  28. // - when linkout() it doesn't not physically shift the memory
  29. // upwards.
  30. //
  31. // - when linkin() it will search for empty rooms in the array
  32. // before appending space at the end of the array.
  33. //
  34. //----------------------------------------------------------//
  35. #define EMPTY_ROOM_ALLOC_STEP 5
  36. //--------- BEGIN OF FUNCTION DynArrayB::DynArrayB -------//
  37. //
  38. // <int> eleSize = size of each element
  39. // [int] blockNum = number of entity of each block of element
  40. // increased ( default : 30 )
  41. // [int] reuseIntervalDays = no. of game days deleted records needed to be kept before reusing them.
  42. // (default: 0)
  43. //
  44. DynArrayB::DynArrayB(int eleSize,int blockNum,int reuseIntervalDays) : DynArray(eleSize, blockNum)
  45. {
  46. empty_room_array = NULL;
  47. empty_room_num = 0;
  48. empty_room_count = 0;
  49. reuse_interval_days = reuseIntervalDays;
  50. }
  51. //----------- END OF FUNCTION DynArrayB::DynArrayB -----//
  52. //--------- BEGIN OF FUNCTION DynArrayB::~DynArrayB -------//
  53. //
  54. DynArrayB::~DynArrayB()
  55. {
  56. if( empty_room_array )
  57. mem_del( empty_room_array );
  58. }
  59. //----------- END OF FUNCTION DynArrayB::DynArrayB -----//
  60. //---------- BEGIN OF FUNCTION DynArrayB::linkin -----------//
  61. //
  62. // <void*> ent
  63. // <int>
  64. //
  65. // - when linkin() it will search for empty rooms in the array
  66. // before appending space at the end of the array.
  67. //
  68. // - If found, then it will use that room
  69. //
  70. // - Otherwise, it will link a record at the END of the array
  71. //
  72. // WARNING : After calling linkin() all pointers to the linklist body
  73. // should be updated, because mem_resize() will move the body memory
  74. //
  75. void DynArrayB::linkin(void* ent)
  76. {
  77. //------- detect for empty rooms --------//
  78. int reusedFlag=0;
  79. if( empty_room_count > 0 )
  80. {
  81. if( reuse_interval_days )
  82. {
  83. //------ first in, first out approach -----//
  84. if( info.game_date >= empty_room_array[0].deleted_game_date + reuse_interval_days )
  85. {
  86. cur_pos = empty_room_array[0].recno;
  87. memmove( empty_room_array, empty_room_array+1, sizeof(empty_room_array[0]) * (empty_room_count-1) );
  88. empty_room_count--;
  89. reusedFlag = 1;
  90. }
  91. }
  92. else
  93. {
  94. //------ last in, first out approach -----//
  95. cur_pos = empty_room_array[empty_room_count-1].recno;
  96. empty_room_count--;
  97. reusedFlag = 1;
  98. }
  99. }
  100. if( !reusedFlag )
  101. {
  102. last_ele++;
  103. cur_pos=last_ele;
  104. }
  105. //---------- regular link in -----------//
  106. if ( last_ele > ele_num ) // not enough empty element left to hold the new entity
  107. resize( ele_num + block_num );
  108. if ( ent )
  109. memcpy(body_buf+(cur_pos-1)*ele_size, ent, ele_size );
  110. else
  111. *(body_buf+(cur_pos-1)*ele_size) = NULL;
  112. }
  113. //---------- END OF FUNCTION DynArrayB::linkin ------------//
  114. //----------- BEGIN OF FUNCTION DynArrayB::linkout ---------//
  115. //
  116. // - when linkout() it doesn't not physically shift the memory
  117. // upwards.
  118. //
  119. // - it record the address of this empty room at empty room list
  120. //
  121. // [int] delPos = the position (recno) of the item to be deleted
  122. // ( default : recno() current record no. )
  123. //
  124. void DynArrayB::linkout(int delPos)
  125. {
  126. if( delPos < 0 )
  127. delPos = cur_pos;
  128. if( delPos == 0 || delPos > last_ele )
  129. return;
  130. //-------- add to the empty room list ---------//
  131. if( ++empty_room_count > empty_room_num )
  132. {
  133. empty_room_array = (EmptyRoom*) mem_resize( empty_room_array,
  134. (empty_room_num+EMPTY_ROOM_ALLOC_STEP) * sizeof(*empty_room_array) );
  135. empty_room_num += EMPTY_ROOM_ALLOC_STEP;
  136. }
  137. empty_room_array[empty_room_count-1].recno = delPos;
  138. empty_room_array[empty_room_count-1].deleted_game_date = info.game_date;
  139. memset( body_buf+(delPos-1)*ele_size, 0, ele_size );
  140. }
  141. //------------ END OF FUNCTION DynArrayB::linkout ----------//
  142. //---------- Begin of function DynArrayB::write_file -------------//
  143. //
  144. // Write current dynamic array into file,
  145. // read_file() can be used to retrieve it.
  146. //
  147. // <File*> writeFile = the pointer to the writing file
  148. //
  149. // Return : 1 - write successfully
  150. // 0 - writing error
  151. //
  152. int DynArrayB::write_file(File* filePtr)
  153. {
  154. if( !filePtr->file_write( this, sizeof(DynArray) ) )
  155. return 0;
  156. //---------- write body_buf ---------//
  157. if( last_ele > 0 )
  158. {
  159. if( !filePtr->file_write( body_buf, ele_size*last_ele ) )
  160. return 0;
  161. }
  162. //---------- write empty_room_array ---------//
  163. write_empty_room(filePtr);
  164. return 1;
  165. }
  166. //------------- End of function DynArrayB::write_file --------------//
  167. //---------- Begin of function DynArrayB::read_file -------------//
  168. //
  169. // Read a saved dynamic array from file, it must be saved with write_file()
  170. //
  171. // <File*> readFile = the pointer to the writing file
  172. //
  173. // Return : 1 - read successfully
  174. // 0 - writing error
  175. //
  176. int DynArrayB::read_file(File* filePtr)
  177. {
  178. char* bodyBuf = body_buf; // preserve body_buf which has been allocated
  179. if( !filePtr->file_read( this, sizeof(DynArray) ) )
  180. return 0;
  181. //---------- read body_buf ---------//
  182. body_buf = mem_resize( bodyBuf, ele_size*ele_num );
  183. if( last_ele > 0 )
  184. {
  185. if( !filePtr->file_read( body_buf, ele_size*last_ele ) )
  186. return 0;
  187. }
  188. //---------- read empty_room_array ---------//
  189. read_empty_room(filePtr);
  190. //------------------------------------------//
  191. start(); // go top
  192. return 1;
  193. }
  194. //------------- End of function DynArrayB::read_file --------------//
  195. //---------- Begin of function DynArrayB::write_empty_room -------------//
  196. //
  197. // Write current dynamic array into file,
  198. // read_file() can be used to retrieve it.
  199. //
  200. // <File*> writeFile = the pointer to the writing file
  201. //
  202. // Return : 1 - write successfully
  203. // 0 - writing error
  204. //
  205. int DynArrayB::write_empty_room(File* filePtr)
  206. {
  207. filePtr->file_put_short( empty_room_count );
  208. //---------- write empty_room_array ---------//
  209. if( empty_room_count > 0 )
  210. {
  211. if( !filePtr->file_write( empty_room_array,
  212. sizeof(EmptyRoom) * empty_room_count ) )
  213. {
  214. return 0;
  215. }
  216. }
  217. return 1;
  218. }
  219. //------------- End of function DynArrayB::write_empty_room --------------//
  220. //---------- Begin of function DynArrayB::read_empty_room -------------//
  221. //
  222. // Read a saved dynamic array from file, it must be saved with write_file()
  223. //
  224. // <File*> readFile = the pointer to the writing file
  225. //
  226. // Return : 1 - read successfully
  227. // 0 - writing error
  228. //
  229. int DynArrayB::read_empty_room(File* filePtr)
  230. {
  231. empty_room_num = empty_room_count = filePtr->file_get_short(); // set both to the same
  232. //---------- read empty_room_array ---------//
  233. if( empty_room_count > 0 )
  234. {
  235. empty_room_array = (EmptyRoom*) mem_resize( empty_room_array,
  236. sizeof(EmptyRoom) * empty_room_count );
  237. if( !filePtr->file_read( empty_room_array,
  238. sizeof(*empty_room_array) * empty_room_count ) )
  239. {
  240. return 0;
  241. }
  242. }
  243. else // when empty_room_count == 0
  244. {
  245. if( empty_room_array )
  246. {
  247. mem_del( empty_room_array );
  248. empty_room_array = NULL;
  249. }
  250. }
  251. //------------------------------------------//
  252. return 1;
  253. }
  254. //------------- End of function DynArrayB::read_empty_room --------------//
  255. //---------- Begin of function DynArrayB::packed_recno -------------//
  256. //
  257. // Given the recno unpacked, it returns the recno packed.
  258. //
  259. // packed_recno() is the recno when the array is packed
  260. // (deleted record are actually removed)
  261. //
  262. // <int> recNo = given the recno unpacked
  263. //
  264. // return : <int> the recno when packed
  265. //
  266. int DynArrayB::packed_recno(int recNo)
  267. {
  268. int i, packedRecno = recNo;
  269. for( i=0 ; i<empty_room_count ; i++ )
  270. {
  271. if( empty_room_array[i].recno < recNo )
  272. packedRecno--;
  273. }
  274. return packedRecno;
  275. }
  276. //------------- End of function DynArrayB::packed_recno --------------//
  277. //---------- Begin of function DynArrayB::zap -------------//
  278. //
  279. // Zap the whole dynamic array, clear all elements
  280. //
  281. void DynArrayB::zap()
  282. {
  283. DynArray::zap();
  284. empty_room_count=0; // reset empty rooms
  285. }
  286. //------------- End of function DynArrayB::zap --------------//
  287. //-------- Start of function DynArrayB::write_ptr_array --------//
  288. //
  289. // Write a DynArrayB with pointer data elements.
  290. //
  291. // <File*> filePtr - pointer to the file object.
  292. // <int> objectSize - size of the objects pointed to by the pointers.
  293. //
  294. int DynArrayB::write_ptr_array(File* filePtr, int objectSize)
  295. {
  296. int i;
  297. char* elePtr;
  298. filePtr->file_put_short( size() );
  299. for( i=1; i<=size() ; i++ )
  300. {
  301. elePtr = (char*) get_ptr(i);
  302. //----- write 0 if the monster is deleted -----//
  303. if( !elePtr ) // the monster is deleted
  304. {
  305. filePtr->file_put_short(0);
  306. }
  307. else
  308. {
  309. filePtr->file_put_short(1); // the monster exists
  310. if( !filePtr->file_write(elePtr, objectSize) )
  311. return 0;
  312. }
  313. }
  314. //------- write empty room array --------//
  315. write_empty_room(filePtr);
  316. return 1;
  317. }
  318. //--------- End of function DynArrayB::write_ptr_array ---------------//
  319. //-------- Start of function DynArrayB::read_ptr_array -------------//
  320. //
  321. // Read a DynArrayB with pointer data elements previously saved by
  322. // write_ptr_array().
  323. //
  324. // <File*> filePtr - pointer to the file object.
  325. // <int> objectSize - size of the objects pointed to by the pointers.
  326. // <CreateEleFP> createEleFunc - function for creating a blank object.
  327. //
  328. int DynArrayB::read_ptr_array(File* filePtr, int objectSize, CreateEleFP createEleFunc)
  329. {
  330. int i;
  331. char* elePtr;
  332. int eleCount = filePtr->file_get_short(); // get no. of monsters from file
  333. for( i=1 ; i<=eleCount ; i++ )
  334. {
  335. if( filePtr->file_get_short()==0 ) // the monster has been deleted
  336. {
  337. add_blank(1); // it's a DynArrayB function
  338. }
  339. else
  340. {
  341. elePtr = (*createEleFunc)();
  342. if( !filePtr->file_read(elePtr, objectSize) )
  343. return 0;
  344. }
  345. }
  346. //-------- linkout() those record added by add_blank() ----------//
  347. //-- So they will be marked deleted in DynArrayB and can be -----//
  348. //-- undeleted and used when a new record is going to be added --//
  349. for( i=size() ; i>0 ; i-- )
  350. {
  351. DynArrayB::go(i); // since DynArrayB has its own go() which will call GroupArray::go()
  352. if( get_ptr() == NULL ) // add_blank() record
  353. linkout();
  354. }
  355. //------- read empty room array --------//
  356. read_empty_room(filePtr);
  357. return 1;
  358. }
  359. //--------- End of function DynArrayB::read_ptr_array ---------------//