OMISC.cpp 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473
  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 : OMISC.CPP
  21. //Description : Object of Misc useful functions
  22. #include <windows.h>
  23. #include <windowsx.h>
  24. #include <mmsystem.h>
  25. #include <dos.h>
  26. #include <string.h>
  27. #include <stdlib.h>
  28. #include <time.h>
  29. #include <ALL.h>
  30. #include <OSTR.h>
  31. #include <OMISC.h>
  32. #define MOVE_AROUND_TABLE_SIZE 900
  33. static char move_around_table_x[MOVE_AROUND_TABLE_SIZE] = {0};
  34. static char move_around_table_y[MOVE_AROUND_TABLE_SIZE] = {0};
  35. static short move_around_table_size = 0;
  36. #if(defined(SPANISH))
  37. #define THOUSAND_SEPARATOR '.'
  38. #define DECIMAL_SEPARATOR ','
  39. #else
  40. #define THOUSAND_SEPARATOR ','
  41. #define DECIMAL_SEPARATOR '.'
  42. #endif
  43. //-------- Start of function Misc::delay -------------//
  44. //
  45. // Misc::delay for specified seconds
  46. //
  47. // float wait = the no. of second to wait
  48. //
  49. void Misc::delay(float wait)
  50. {
  51. clock_t stopTime;
  52. stopTime = (long) (clock() + (wait * CLOCKS_PER_SEC));
  53. while( clock() < stopTime );
  54. }
  55. //--------- End of function Misc::delay ---------------//
  56. //-------- BEGIN OF FUNCTION Misc::str_shorten --------//
  57. //
  58. // Shorten the string with words exceed the dest. length cut.
  59. //
  60. // <char *> = destination string
  61. // <char *> = source string (source should be longer than dest)
  62. // <int> = max. no. of characters in the dest. string.
  63. // ( destStr should be allocated as destStr[destLen+1] )
  64. //
  65. void Misc::str_shorten(char* destStr, char* srcStr, int destLen)
  66. {
  67. strncpy( destStr, srcStr, destLen );
  68. destStr[destLen]=NULL;
  69. //------ no need to cut characters if it fit preciously ----//
  70. //
  71. // e.g. "One Two Three" ---> "One Two"
  72. // (srcStr) (destStr, return it as the result)
  73. //----------------------------------------------------------//
  74. if( (int)strlen(srcStr) < destLen || srcStr[destLen] == ' ' )
  75. return;
  76. //--- if there is only one word in the string, don't cut it ----//
  77. //
  78. // e.g. "VeryLongWord" --> "VeryLongWo"
  79. //
  80. //--------------------------------------------------------------//
  81. if( !str_chr( destStr, ' ' ) )
  82. return;
  83. //------ if there is more than one word, cut it ------//
  84. //
  85. // e.g. "One Two Three" ----> "One Two Thr" ---> "One Two"
  86. // (srcStr) (destStr before) (destStr after)
  87. //
  88. //----------------------------------------------------//
  89. int i;
  90. for( i=destLen-1 ; i>0 && destStr[i] != ' ' ; i-- )
  91. destStr[i] = NULL;
  92. destStr[i] = NULL; // trim the space also
  93. }
  94. //------------ END OF FUNCTIN Misc::str_shorten -----------------//
  95. //-------- BEGIN OF FUNCTION Misc::str_cut --------//
  96. //
  97. // Syntax : Misc::str_cut( <char*>,<char*>,<int>,<int> )
  98. //
  99. // Description : cut up string1 and place the resuit in string 2
  100. //
  101. // <char *> = destination string
  102. // <char *> = source string
  103. // <int> = the start position of the new string
  104. // <int> = the no. of characters to copied. (default:to the end of the string)
  105. //
  106. int Misc::str_cut(char* dstr, char* sstr, int schar, int charnum )
  107. {
  108. int si,di,forever;
  109. forever = (charnum < 0);
  110. for (si=schar-1,di=0 ; ( di<charnum || forever ) && sstr[si] ; si++,di++)
  111. dstr[di] = sstr[si] ;
  112. dstr[di] = NULL; // terminating NULL sign
  113. return 1;
  114. }
  115. //------------ END OF FUNCTIN Misc::str_cut -----------------//
  116. //---------- BEGIN OF FUNCTION Misc::str_chr ----------------//
  117. //
  118. // Description : return the position of the first occurance of the character
  119. // in the string
  120. //
  121. // Syntax : Misc::str_chr( <char*>, <char), [int], [int] )
  122. //
  123. // <char*> = the string to the scanned.
  124. // <char> = the key character
  125. // [int] = the start position of the string to be scanned (1)
  126. // [int] = the end position of the string to be scanned (-1)
  127. //
  128. // return : a positive number indicating the position of the first occurance
  129. // FAIL / NULL if not found
  130. //
  131. int Misc::str_chr( char* str, char chr, int spos, int epos )
  132. {
  133. int i;
  134. epos--;
  135. for (i=spos-1 ; str[i] && ( i<=epos || epos==-2 ) ; i++)
  136. {
  137. if ( str[i] == chr )
  138. return(i+1);
  139. }
  140. return 0;
  141. }
  142. //----------- END OF FUNCTION Misc::str_chr -------------//
  143. //---------- BEGIN OF FUNCTION Misc::str_str ----------------//
  144. //
  145. // Description : return the position of the first occurance of the character
  146. // in the string
  147. //
  148. // Syntax : Misc::str_str( <char*>, <char*>, [int], [int] )
  149. //
  150. // <char*> = the string to the scanned.
  151. // <char*> = the key string
  152. // [int] = the start position of the string to be scanned (1)
  153. // [int] = the end position of the string to be scanned (-1)
  154. //
  155. // return : a positive number indicating the position of the first occurance
  156. // FAIL / NULL if not found
  157. //
  158. int Misc::str_str( char* str, char* fstr, int spos, int epos )
  159. {
  160. int i,j,flen;
  161. if (epos == -1)
  162. epos = strlen(str);
  163. flen = strlen(fstr);
  164. epos -= flen ;
  165. for (i=spos-1 ; str[i] && i<=epos ; i++)
  166. {
  167. for (j= 0; j < flen && str[i+j] ; j++ )
  168. {
  169. if ( str[i+j] != fstr[j] ) // exactly equal
  170. break;
  171. }
  172. if ( j==flen ) // all equal
  173. return (i+1) ;
  174. }
  175. return 0;
  176. }
  177. //----------- END OF FUNCTION Misc::str_str -------------//
  178. //------ BEGIN OF FUNCTION Misc::upper ---------//
  179. //
  180. // Description : Convert the character to upper case
  181. //
  182. // Syntax : Misc::upper(<char>)
  183. //
  184. // return : the converted character
  185. //
  186. //
  187. int Misc::upper(int inchar)
  188. {
  189. if ( inchar >= 'a' && inchar <= 'z' )
  190. inchar -= 32;
  191. return( inchar );
  192. }
  193. //----- END OF FUNCTION Misc::upper ------------//
  194. //------ BEGIN OF FUNCTION Misc::lower ---------//
  195. //
  196. // Description : Convert the character to lower case
  197. //
  198. // Syntax : Misc::lower(<char>)
  199. //
  200. // return : the converted character
  201. //
  202. //
  203. int Misc::lower(int inchar)
  204. {
  205. if ( inchar >= 'A' && inchar <= 'Z' )
  206. inchar += 32;
  207. return( inchar );
  208. }
  209. //----- END OF FUNCTION Misc::lower ------------//
  210. //--------- BEGIN OF FUNCTION Misc::ltrim_len ---------//
  211. //
  212. // Description : return the number of character in the string
  213. // with left space cut
  214. //
  215. int Misc::ltrim_len(char* inStr,int spos,int len)
  216. {
  217. int i,j;
  218. if ( len == -1 )
  219. len = strlen(inStr);
  220. for( i = spos-1,j=0 ; j<len && inStr[i]==' ' ; i++ )
  221. j++;
  222. return len-j;
  223. }
  224. //--------- END OF FUNCTION Misc::ltrim_len -------------//
  225. //--------- BEGIN OF FUNCTION Misc::rtrim_len ---------//
  226. //
  227. // Description : return the number of character in the string
  228. // with right space cut
  229. //
  230. // <char*> inStr = the pointer to the string
  231. // [int] spos = start position of the string from the pointer
  232. // (default : 1)
  233. // [int] len = length of the string
  234. // (default : until NULL)
  235. //
  236. int Misc::rtrim_len(char* inStr,int spos,int len)
  237. {
  238. int i,j;
  239. if ( len == -1 )
  240. len = strlen(inStr);
  241. for( i = spos+len-2,j=0 ; j<len && inStr[i]==' ' ; i-- )
  242. j++;
  243. return len-j;
  244. }
  245. //--------- END OF FUNCTION Misc::rtrim_len -------------//
  246. //------ BEGIN OF FUNCTION Misc::rtrim ---------//
  247. //
  248. // <char*> = the destination
  249. // <char*> = the source
  250. //
  251. // Note : the destination memory must be allocated
  252. //
  253. void Misc::rtrim( char* des, char* src )
  254. {
  255. int i;
  256. for ( i=strlen(src)-1 ; src[i]==' ' && i>=0 ; i-- )
  257. des[i] = src[i];
  258. des[i+1] = NULL;
  259. }
  260. //------- END OF FUNCTION Misc::rtrim --------//
  261. //------ BEGIN OF FUNCTION Misc::ltrim ---------//
  262. //
  263. // <char*> = the destination
  264. // <char*> = the source
  265. //
  266. // Note : the destination memory must be allocated
  267. //
  268. void Misc::ltrim( char* des, char* src )
  269. {
  270. int i,j;
  271. for ( i=0 ; src[i]==' ' && src[i] ; )
  272. i++ ;
  273. for ( j=0 ; src[i] ; i++,j++ )
  274. des[j] = src[i];
  275. des[j] = NULL;
  276. }
  277. //------- END OF FUNCTION Misc::ltrim --------//
  278. //------ BEGIN OF FUNCTION Misc::alltrim ---------//
  279. //
  280. // <char*> = the destination
  281. // <char*> = the source
  282. //
  283. // Note : the destination memory must be allocated
  284. //
  285. void Misc::alltrim( char* des, char* src)
  286. {
  287. int i,j;
  288. for ( i=0 ; src[i]==' ' && src[i] ; )
  289. i++ ;
  290. for ( j=0 ; src[i] && src[i]!=' ' ; i++,j++ )
  291. des[j] = src[i];
  292. des[j] = NULL;
  293. }
  294. //------- END OF FUNCTION Misc::alltrim --------//
  295. //------ BEGIN OF FUNCTION Misc::rtrim ---------//
  296. //
  297. // <char*> = the string, the result is put back into the original string pointer
  298. //
  299. char* Misc::rtrim( char* str )
  300. {
  301. int i;
  302. for ( i=strlen(str)-1 ; str[i]==' ' && i>=0 ; i-- );
  303. str[i+1] = NULL;
  304. return str;
  305. }
  306. //------- END OF FUNCTION Misc::rtrim --------//
  307. //------ BEGIN OF FUNCTION Misc::ltrim ---------//
  308. //
  309. // <char*> = the string
  310. //
  311. char* Misc::ltrim( char* str )
  312. {
  313. int i,j;
  314. for ( i=0 ; str[i]==' ' && str[i] ; i++ );
  315. for ( j=0 ; str[i] ; i++,j++ )
  316. str[j] = str[i];
  317. str[j] = NULL;
  318. return str;
  319. }
  320. //------- END OF FUNCTION Misc::ltrim --------//
  321. //------ BEGIN OF FUNCTION Misc::alltrim ---------//
  322. //
  323. // <char*> = the string
  324. //
  325. char* Misc::alltrim( char* str )
  326. {
  327. int i,j;
  328. for ( i=0 ; str[i]==' ' && str[i] ; i++ );
  329. for ( j=0 ; str[i] && str[i]!=' ' ; i++,j++ )
  330. str[j] = str[i];
  331. str[j] = NULL;
  332. return str;
  333. }
  334. //------- END OF FUNCTION Misc::alltrim --------//
  335. //------- BEGIN OF FUNCTION Misc::empty ------------//
  336. //
  337. // Description : empty a string
  338. //
  339. // Syntax : Misc::empty(<*char>,<int>)
  340. //
  341. // <*char> = the pointer of the string
  342. // <int> = the length of the string (not include the null string )
  343. //
  344. void Misc::empty(char *inStr, int strLen )
  345. {
  346. memset( inStr,' ',strLen);
  347. inStr[strLen] = NULL;
  348. }
  349. //-------- END OF FUNCTION Misc::empty ---------//
  350. //------- BEGIN OF FUNCTION Misc::is_empty ------------//
  351. //
  352. // Description : empty a string
  353. //
  354. // Syntax : Misc::is_empty(<*char>,[int],[int])
  355. //
  356. // <*char> = the pointer of the string
  357. // [int] = the length of the string (not include the null string )
  358. //
  359. int Misc::is_empty(char *inStr, int strLen)
  360. {
  361. int i;
  362. if( !strLen )
  363. strLen = strlen(inStr);
  364. for( i=0 ; i<strLen ; i++ )
  365. {
  366. if( inStr[i] != ' ' )
  367. return 0;
  368. }
  369. return 1;
  370. }
  371. //-------- END OF FUNCTION Misc::is_empty ---------//
  372. //------- BEGIN OF FUNCTION Misc::fix_str ------//
  373. //
  374. // format the word to the fixed length
  375. //
  376. // e.g. Misc::fix_str("ABC",10) -> "ABC "
  377. //
  378. // <char*> str = the string to be formated
  379. // <int> len = the deserved length after formatted
  380. // [char] endChar = the end character of the string ( default : NULL terminator )
  381. //
  382. void Misc::fix_str(char* str,int len,char endChar)
  383. {
  384. int oldLen;
  385. if ( endChar == NULL )
  386. oldLen = strlen(str);
  387. else
  388. {
  389. oldLen = Misc::str_chr(str,endChar)-1;
  390. err_if ( oldLen == -1 ) // the end character not found
  391. err_now("Misc::fix_str");
  392. }
  393. if ( len > oldLen )
  394. memset( str+oldLen, ' ', len-oldLen );
  395. str[len] = NULL;
  396. }
  397. //--------- END OF FUNCTION Misc::fix_str ---------//
  398. //------- BEGIN OF FUNCTION Misc::valid_char --------//
  399. //
  400. // Description : test if the character is valid for field and file name
  401. //
  402. // Syntax : Misc::valid_char(<char>)
  403. //
  404. // <char> = the character to be validify
  405. //
  406. // return : SUCCEED or FAIL
  407. //
  408. int Misc::valid_char( char ch )
  409. {
  410. return ( ch>='a' && ch<='z' ||
  411. ch>='A' && ch<='Z' ||
  412. ch>='0' && ch<='9' ||
  413. ch=='\\' || ch=='.' || ch=='_' || ch==':' ) ;
  414. }
  415. //--------- END OF FUNCTION Misc::valid_char ----------//
  416. //------- BEGIN OF FUNCTION Misc::str_cmp -----------//
  417. //
  418. // Description : compare string
  419. //
  420. // Return : SUCCEED if the same
  421. // FAIL if different
  422. //
  423. // e.g "ABCDE" <> "ABC"
  424. // "ABCDE " = "ABCDE"
  425. // "ABCDE" <> "ABCDEF"
  426. // "ABCDE" <> "ABCDE "
  427. int Misc::str_cmp( char* str1, char* str2 )
  428. {
  429. err_when( !str1 || !str2 );
  430. int i;
  431. for (i=0 ; str1[i] && str2[i] ; i++)
  432. if ( str1[i] != str2[i] )
  433. return 0;
  434. return ( str2[i] == NULL && (str1[i]==NULL || str1[i]==' ') );
  435. }
  436. //--------- END OF FUNCTION Misc::str_cmp -----------//
  437. //------- BEGIN OF FUNCTION Misc::str_cmpx -----------//
  438. //
  439. // Description : String Inexact comparsion
  440. //
  441. // Return : SUCCEED if the same
  442. // FAIL if different
  443. //
  444. // e.g "ABCDE" = "ABC"
  445. // "ABCDE " = "ABCDE"
  446. // "ABCDE" <> "ABCDEF"
  447. // "ABCDE" <> "ABCDE "
  448. //
  449. int Misc::str_cmpx( char* str1, char* str2 )
  450. {
  451. err_when( !str1 || !str2 );
  452. int i;
  453. for (i=0 ; str1[i] && str2[i] ; i++)
  454. if ( str1[i] != str2[i] )
  455. return 0;
  456. return ( str2[i] == NULL );
  457. }
  458. //--------- END OF FUNCTION Misc::str_cmpx -----------//
  459. //------- BEGIN OF FUNCTION Misc::str_icmpx -----------//
  460. //
  461. // Description : String Inexact comparsion without case sensitive
  462. //
  463. // Return : SUCCEED if the same
  464. // FAIL if different
  465. //
  466. // e.g "ABCDE" = "ABC"
  467. // "abcde " = "ABCDE"
  468. // "ABCDE" <> "ABCDEF"
  469. // "ABCDE" <> "ABCDE "
  470. int Misc::str_icmpx( char* str1, char* str2 )
  471. {
  472. err_when( !str1 || !str2 );
  473. int i;
  474. register int a,b;
  475. for (i=0 ; (a=str1[i]) != NULL && (b=str2[i]) != NULL ; i++)
  476. {
  477. if ( a >= 'a' && a <= 'z' )
  478. a -= 32;
  479. if ( b >= 'a' && b <= 'z' )
  480. b -= 32;
  481. if ( a != b )
  482. return 0;
  483. }
  484. return ( str2[i] == NULL );
  485. }
  486. //--------- END OF FUNCTION Misc::str_icmpx -----------//
  487. //-------- BEGIN OF FUNCTION Misc::check_sum ----------//
  488. //
  489. // Return the checksum of the string
  490. //
  491. // <char*> = the string
  492. // [int] = length of the string
  493. int Misc::check_sum(char* str, int len)
  494. {
  495. int i,checksum;
  496. if ( len == -1 )
  497. len = strlen( str );
  498. for( checksum=0,i=0 ; i<len ; i++,str++ )
  499. checksum += (*str) * (i+checksum+1) ;
  500. return checksum;
  501. }
  502. //--------- END OF FUNCTION Misc::check_sum -----------//
  503. //---------- Begin of function Misc::format --------//
  504. //
  505. // Format a number to a string with specified format
  506. // Note : the formated string is right justified
  507. //
  508. // int inNum = the number to be formated
  509. //
  510. // [int] formatType = 1 - 1,000,000 add thousand seperator
  511. // 2 - $1,000,000 add thousand seperator and dollar sign
  512. // 3 - 56% add percentage sign % at the end of the number
  513. // 4 - 1000000, no thousand seperator
  514. // (default : 1)
  515. //
  516. // return <char*> the pointer to the converted string, the string
  517. // is stored in static variable which will be overwritten
  518. // in next call.
  519. //
  520. char* Misc::format( int inNum, int formatType )
  521. {
  522. static char outBuf[35];
  523. static char longBuf[25];
  524. char *outPtr=outBuf;
  525. char *longStr;
  526. int i, intDigit, sign;
  527. if( inNum < 0 )
  528. {
  529. sign = -1;
  530. inNum = -inNum;
  531. }
  532. else
  533. sign = 0;
  534. longStr = ltoa( inNum, longBuf, 10 );
  535. intDigit = strlen(longStr); // no. of integer digits
  536. //--------- negetive bracket ------------//
  537. if( sign < 0 )
  538. *outPtr++ = '(';
  539. //--------- dollar sign ------------//
  540. if( formatType == 2 )
  541. *outPtr++ = '$';
  542. //-------- integer number -----------//
  543. for( i=intDigit ; i>0 ; i-- )
  544. {
  545. if( formatType != 4 ) // no thousand separators for format 4
  546. {
  547. if( i%3 == 0 && i < intDigit )
  548. *outPtr++ = THOUSAND_SEPARATOR;
  549. }
  550. *outPtr++ = *longStr++;
  551. }
  552. //--------- percent sign (%) ------------//
  553. if( formatType == 3 )
  554. *outPtr++ = '%';
  555. //--------- negetive bracket ----------//
  556. if( sign < 0 )
  557. *outPtr++ = ')';
  558. *outPtr++ = NULL;
  559. return outBuf;
  560. }
  561. //---------- End of function Misc::format ---------//
  562. //---------- Begin of function Misc::format --------//
  563. //
  564. // Format a number to a float number to format string
  565. // Note : the formated string is right justified
  566. //
  567. // <double> inNum = the number to be formated
  568. // use <double> instead of <float> because
  569. // fcvt() only accept <double>
  570. //
  571. // [int] formatType = 1 - 1,000,000 add thousand seperator
  572. // 2 - $1,000,000 add thousand seperator and dollar sign
  573. // 3 - 56% add percentage sign % at the end of the number
  574. //
  575. // return <char*> the pointer to the converted string, the string
  576. // is stored in static variable which will be overwritten
  577. // in next call.
  578. //
  579. char* Misc::format(double inNum, int formatType)
  580. {
  581. enum { MONEY_DEC_PLACE = 2 };
  582. static char outBuf[35];
  583. char *outPtr=outBuf;
  584. char *floatStr;
  585. int i, intDigit, sign; // intDigit = no. of integer digits
  586. floatStr = fcvt( inNum, MONEY_DEC_PLACE, &intDigit, &sign );
  587. #ifdef DEBUG
  588. if( intDigit > 29 ) // integer digits can't exceed 29
  589. err.run( "Misc::format(), inNum : %e, formatType : %d", inNum, formatType );
  590. #endif
  591. //--------- negetive bracket ------------//
  592. if( inNum < 0 )
  593. *outPtr++ = '(';
  594. //--------- dollar sign ($) ------------//
  595. if( formatType == 2 )
  596. *outPtr++ = '$';
  597. //------- integer number -----------//
  598. for( i=intDigit ; i>0 ; i-- )
  599. {
  600. if( i%3 == 0 && i < intDigit )
  601. *outPtr++ = THOUSAND_SEPARATOR;
  602. *outPtr++ = *floatStr++;
  603. }
  604. if( intDigit <= 0 )
  605. *outPtr++ = '0';
  606. //------- dec. place number -----------//
  607. if( inNum > -1000 && inNum < 1000 ) // if the number is less than 1000, add dec. places
  608. { // if the number is greater than 1000, truncate any dec. places
  609. *outPtr++ = DECIMAL_SEPARATOR;
  610. if( *floatStr && intDigit >= 0 ) // e.g. 0.03 --> str:"3", intDight:-1
  611. *outPtr++ = *floatStr++; // 1st dec. place
  612. else
  613. *outPtr++ = '0'; // add a '0' when intDigit < 0
  614. if( *floatStr ) // 2nd dec. place
  615. *outPtr++ = *floatStr++;
  616. else
  617. *outPtr++ = '0';
  618. }
  619. //--------- percent sign (%) ------------//
  620. if( formatType == 3 )
  621. *outPtr++ = '%';
  622. //--------- negetive bracket ------------//
  623. if( inNum < 0 )
  624. *outPtr++ = ')';
  625. *outPtr++ = NULL;
  626. return outBuf;
  627. }
  628. //---------- End of function Misc::format ---------//
  629. //---------- Begin of function Misc::num_to_str --------//
  630. //
  631. // Convert a number into string.
  632. //
  633. // int inNum = the number to be converted
  634. //
  635. // return : <char*> the converted string.
  636. //
  637. char* Misc::num_to_str(int inNum)
  638. {
  639. static char strBuf[25];
  640. return ltoa( inNum, strBuf, 10 );
  641. }
  642. //---------- End of function Misc::format ---------//
  643. //---------- Begin of function Misc::nullify -------//
  644. //
  645. // Nullify and right trim a string field in the record
  646. //
  647. // <char*> strPtr = string pointer
  648. // <int> strLen = string length
  649. //
  650. // Return : <char*> the nullied string which only stored in static
  651. // buffer temporary until next call to nullify()
  652. //
  653. // note : if the string is longer than the buffer space, the string
  654. // will be truncated
  655. //
  656. char* Misc::nullify(char* strPtr, int strLen)
  657. {
  658. int i;
  659. if( strLen > STR_BUF_LEN )
  660. strLen = STR_BUF_LEN;
  661. memcpy( str_buf, strPtr, strLen );
  662. for( i=strLen-1 ; i>=0 ; i-- ) // Right Trim
  663. {
  664. if( str_buf[i] != ' ' )
  665. {
  666. str_buf[i+1] = NULL;
  667. break;
  668. }
  669. }
  670. if( i<0 ) // Empty value
  671. str_buf[0] = NULL;
  672. return str_buf;
  673. }
  674. //----------- End of function Misc::nullify ----------//
  675. //-------- Begin of function Misc::rtrim_fld ---------//
  676. //
  677. // Rtrim a text field and copy it to variable
  678. //
  679. // <char*> varPtr = pointer to the variable
  680. // <char*> fldPtr = pointer to the field
  681. // <int> fldLen = length of the field
  682. //
  683. // Note <varPtr> must be pre-allocated with a len > fldLen+1
  684. //
  685. void Misc::rtrim_fld(char* varPtr, char* fldPtr, int fldLen)
  686. {
  687. int rtrimLen = rtrim_len( fldPtr, 1, fldLen );
  688. memcpy( varPtr, fldPtr, rtrimLen );
  689. varPtr[rtrimLen] = NULL;
  690. }
  691. //---------- End of function Misc::rtrim_fld ---------//
  692. //------- Begin of function Misc::atoi ---------//
  693. //
  694. // Same as atoi() in stdlib.h instead it allows you to specify the
  695. // length of the string
  696. //
  697. // <char*> str = the string to be converted to integer
  698. // <int> strLen = length of the string
  699. int Misc::atoi( char *str, int strLen )
  700. {
  701. if ( strLen >= sizeof( str_buf ) )
  702. strLen = sizeof( str_buf ) - 1 ;
  703. memcpy( str_buf, str, (size_t)strLen ) ;
  704. str_buf[strLen] = '\0' ;
  705. return ::atoi( str_buf ) ;
  706. }
  707. //---------- End of function Misc::atoi ---------//
  708. //------- Begin of function Misc::sqrt ---------//
  709. //
  710. // Find the square root of an long integer
  711. //
  712. // <int> x = the value for calculating its square root
  713. //
  714. int Misc::sqrt(long x)
  715. {
  716. err_when( x < 0 );
  717. long OddInt, OldArg, FirstSqrt;
  718. OddInt=1;
  719. OldArg=x;
  720. while(x>=0)
  721. {
  722. x-=OddInt;
  723. OddInt+=2;
  724. }
  725. FirstSqrt=OddInt >> 1;
  726. if( FirstSqrt*FirstSqrt - FirstSqrt + 1 > OldArg)
  727. return(FirstSqrt-1);
  728. else
  729. return(FirstSqrt);
  730. }
  731. //---------- End of function Misc::sqrt ---------//
  732. //------- Begin of function Misc::diagonal_distance ---------//
  733. //
  734. // Given two lengths in x and y coordination, then find the diagonal
  735. // distance between them
  736. // result = the square root of X*X + Y*Y
  737. //
  738. // <int> x1, y1 = the starting point of the diagonal line
  739. // <int> x2, y2 = the ending point of the diagonal line
  740. //
  741. int Misc::diagonal_distance(int x1, int y1, int x2, int y2)
  742. {
  743. int x = abs(x1-x2);
  744. int y = abs(y1-y2);
  745. return Misc::sqrt( x*x + y*y );
  746. }
  747. //---------- End of function Misc::diagonal_distance ---------//
  748. //------- Begin of function Misc::points_distance ---------//
  749. //
  750. // Given two lengths in x and y coordination, then find the
  751. // distance between two points, taking diagonal distance
  752. // the same as the horizontal and vertical distances.
  753. //
  754. // <int> x1, y1 = the starting point of the diagonal line
  755. // <int> x2, y2 = the ending point of the diagonal line
  756. //
  757. int Misc::points_distance(int x1, int y1, int x2, int y2)
  758. {
  759. int x = abs(x1-x2);
  760. int y = abs(y1-y2);
  761. return max(x, y);
  762. }
  763. //---------- End of function Misc::points_distance ---------//
  764. //------- Begin of function Misc::get_random_seed --------//
  765. //
  766. long Misc::get_random_seed()
  767. {
  768. return random_seed;
  769. }
  770. //---------- End of function Misc::get_random_seed ---------//
  771. //------- Begin of function Misc::randomize --------//
  772. //
  773. void Misc::randomize()
  774. {
  775. set_random_seed(time(NULL));
  776. }
  777. //---------- End of function Misc::randomize ---------//
  778. //------- Begin of function Misc::set_random_seed --------//
  779. //
  780. void Misc::set_random_seed(long randomSeed)
  781. {
  782. // ###### begin Gilbert 19/6 ######//
  783. err_when( is_seed_locked() );
  784. // ###### end Gilbert 19/6 ######//
  785. random_seed = randomSeed;
  786. }
  787. //---------- End of function Misc::set_random_seed ---------//
  788. //------- Begin of function Misc::random ---------//
  789. //
  790. // <int> maxNum = maximum random number, it must <= 0x7FFF
  791. // in 32 bit compiler <int> = <long>
  792. //
  793. // return : <int> the random number
  794. //
  795. int Misc::random(int maxNum)
  796. {
  797. err_if( maxNum < 0 || maxNum > 0x7FFF )
  798. err_now( "Misc::random()" );
  799. // ###### begin Gilbert 19/6 ######//
  800. err_when( is_seed_locked() );
  801. // ###### end Gilbert 19/6 ######//
  802. #define MULTIPLIER 0x015a4e35L
  803. #define INCREMENT 1
  804. #define RANDOM_MAX 0x7FFFU
  805. random_seed = MULTIPLIER * random_seed + INCREMENT;
  806. return maxNum * ((random_seed >> 16) & RANDOM_MAX) / (RANDOM_MAX+1);
  807. }
  808. //---------- End of function Misc::random ---------//
  809. //------- Begin of function Misc::rand ---------//
  810. //
  811. // Return a random number from 0 to 0x7FFF
  812. //
  813. // return : <int> a random number from from 0 to 0x7FFF
  814. //
  815. int Misc::rand()
  816. {
  817. #define MULTIPLIER 0x015a4e35L
  818. #define INCREMENT 1
  819. #define RANDOM_MAX 0x7FFFU
  820. // ###### begin Gilbert 19/6 ######//
  821. err_when( is_seed_locked() );
  822. // ###### end Gilbert 19/6 ######//
  823. random_seed = MULTIPLIER * random_seed + INCREMENT;
  824. return ((random_seed >> 16) & RANDOM_MAX);
  825. }
  826. //---------- End of function Misc::rand ---------//
  827. //------- Begin of function Misc::round ---------//
  828. //
  829. // Round the float no. to the 2 signicant values :
  830. //
  831. // Since this function is not called frequently, we can afford
  832. // to use a slower algorithm.
  833. //
  834. // <float> inValue = the number to be rounded.
  835. // <int> signPlace = round to no. of signicant places.
  836. // [int] roundDirection = 0-if <= 4, round to a smaller, if >=5 round to a bigger
  837. // 1-round to a smaller number
  838. // 2-round to a bigger number
  839. // (default : 0)
  840. //
  841. // return : <float> the rounded number
  842. //
  843. float Misc::round(float inValue, int signPlace, int roundDirection)
  844. {
  845. int i;
  846. float baseValue = (float) 1;
  847. float minValue = (float) 10;
  848. for( i=2 ; i<=signPlace ; i++ )
  849. minValue *= 10;
  850. while( inValue > minValue )
  851. {
  852. inValue /= 10;
  853. baseValue *= 10;
  854. }
  855. float outValue = (float)((int)inValue) * baseValue;
  856. //-----------------------------------------------//
  857. //
  858. // If the result number is smaller than the given number
  859. // and the roundDirection is rounding to a bigger number,
  860. // than increase result number.
  861. //
  862. //-----------------------------------------------//
  863. if( outValue!=inValue )
  864. {
  865. if( (roundDirection==0 && ((int)inValue)%10 >= 5) ||
  866. roundDirection==2 )
  867. {
  868. outValue = (float)((int)inValue+1) * baseValue;
  869. }
  870. }
  871. return outValue;
  872. }
  873. //---------- End of function Misc::round ---------//
  874. //------- Begin of function Misc::round_dec ---------//
  875. //
  876. // Round the number to its nearest 2 decimal places.
  877. //
  878. // <float> inNum - the input number.
  879. //
  880. // Return : <float> the output number
  881. //
  882. float Misc::round_dec(float inNum)
  883. {
  884. return (float)((int)(inNum * 100)) / 100;
  885. }
  886. //---------- End of function Misc::round_dec ---------//
  887. //------- Begin of function Misc::is_file_exist ---------//
  888. //
  889. // Check whether the given file exists in the current directory or not
  890. //
  891. // <char*> fileName = the name of the file
  892. //
  893. // return : <int> 1 - the file exists
  894. // 0 - doesn't exist
  895. //
  896. int Misc::is_file_exist(char* fileName)
  897. {
  898. WIN32_FIND_DATA findData;
  899. HANDLE findHandle = FindFirstFile( fileName, &findData );
  900. return findHandle!=INVALID_HANDLE_VALUE;
  901. }
  902. //---------- End of function Misc::is_file_exist ---------//
  903. //------- Begin of function Misc::change_file_ext ---------//
  904. //
  905. // Change file extension.
  906. //
  907. // <char*> desFileName = the destination file name to be written
  908. // <char*> srcFileName = the source file name
  909. // <char*> newExt = the new extension.
  910. //
  911. void Misc::change_file_ext(char* desFileName, char* srcFileName, char* newExt)
  912. {
  913. int nameLen = m.str_chr(srcFileName, '.'); // include the '.' in the nameLen
  914. err_when( nameLen<1 || nameLen>9 || strlen(newExt)>3 );
  915. memcpy( desFileName, srcFileName, nameLen );
  916. strcpy( desFileName+nameLen, newExt ); // extension for scenarion text file
  917. }
  918. //---------- End of function Misc::change_file_ext ---------//
  919. //------- Begin of function Misc::extract_file_name ---------//
  920. //
  921. // Extract the file name from a full file path.
  922. //
  923. // <char*> desFileName = the destination buffer to be written
  924. // <char*> srcFileName = the source file name
  925. //
  926. void Misc::extract_file_name(char* desFileName, char* srcFileName)
  927. {
  928. int i;
  929. for( i=strlen(srcFileName) ; i>=0 ; i-- )
  930. {
  931. if( srcFileName[i]=='\\' ) // get last '\' before the file name
  932. break;
  933. }
  934. strncpy(desFileName, srcFileName+i+1, MAX_PATH);
  935. desFileName[MAX_PATH]=NULL;
  936. }
  937. //---------- End of function Misc::extract_file_name ---------//
  938. //------- Begin of function Misc::num_th ---------//
  939. //
  940. // Convert the number into 99th format.
  941. //
  942. // <int> inNum = the input number
  943. //
  944. // return : <char*> the result string
  945. //
  946. char* Misc::num_th(int inNum)
  947. {
  948. static String str;
  949. str = format(inNum);
  950. if( inNum >=11 && inNum <= 13 )
  951. {
  952. str += "th";
  953. }
  954. else
  955. {
  956. switch( inNum%10 )
  957. {
  958. case 1:
  959. str += "st";
  960. break;
  961. case 2:
  962. str += "nd";
  963. break;
  964. case 3:
  965. str += "rd";
  966. break;
  967. default:
  968. str += "th";
  969. break;
  970. }
  971. }
  972. return str;
  973. }
  974. //---------- End of function Misc::num_th ---------//
  975. //------- Begin of function Misc::get_time ---------//
  976. //
  977. unsigned long Misc::get_time()
  978. {
  979. return timeGetTime();
  980. }
  981. //---------- End of function Misc::get_time ---------//
  982. //------- Begin of function Misc::del_array_rec ---------//
  983. //
  984. // Delete a record in an array.
  985. //
  986. // <void*> arrayBody - the array pointer
  987. // <int> arraySize - size of the array
  988. // <int> recSize - record size
  989. // <int> delRecno - recno to be deleted.
  990. //
  991. void Misc::del_array_rec(void* arrayBody, int arraySize, int recSize, int delRecno)
  992. {
  993. err_when( arraySize<1 );
  994. err_when( delRecno<1 || delRecno>arraySize);
  995. int t = delRecno-1;
  996. char* arrayPtr = (char*) arrayBody;
  997. memmove( arrayPtr+recSize*t, arrayPtr+recSize*(t+1),
  998. recSize * (arraySize-t-1) );
  999. }
  1000. //---------- End of function Misc::del_array_rec ---------//
  1001. //-------- Begin of function Misc::cal_move_around_a_point -------//
  1002. // This function is used to return the x_Offset and y_Offset from the
  1003. // center of the square. The detail is shown in the following figure.
  1004. //
  1005. //
  1006. // 21 20 19 18 17
  1007. // 22 7 6 5 16
  1008. // 23 8 1 4 15
  1009. // 24 9 2 3 14
  1010. // 25 10 11 12 13
  1011. //
  1012. // Assume the square is 5x5, 1 is the center of the square. The input
  1013. // value of num determine which point is processed. For instance, 9 is
  1014. // processed if num=9.
  1015. //
  1016. // using the center as the reference point, (xShift, yShift) = (-1, -1)
  1017. // for num=7, (xShift, yShift) = (0,2) for num=11.
  1018. //
  1019. // For num>25 in this case, multiply of 25 will be cut out until num<=25.
  1020. //
  1021. void Misc::cal_move_around_a_point(short num, short width, short height, int& xShift, int& yShift)
  1022. {
  1023. short maxSqtSize = (width>height) ? height+1 : width+1;
  1024. //short num2 = num%(maxSqtSize*maxSqtSize) + 1;
  1025. short num2 = (num-1)%(maxSqtSize*maxSqtSize) + 1;
  1026. if(num2<=MOVE_AROUND_TABLE_SIZE)
  1027. {
  1028. xShift = int(*(move_around_table_x+num2-1));
  1029. yShift = int(*(move_around_table_y+num2-1));
  1030. /*#ifdef DEBUG2
  1031. int xShift2, yShift2;
  1032. cal_move_around_a_point_v2(num, width, height, xShift2, yShift2);
  1033. err_when(xShift!=xShift2);
  1034. err_when(yShift!=yShift2);
  1035. #endif*/
  1036. return;
  1037. }
  1038. else
  1039. cal_move_around_a_point_v2(num, width, height, xShift, yShift);
  1040. }
  1041. //------ End of function Misc::cal_move_around_a_point ---------//
  1042. //-------- Begin of function Misc::cal_move_around_a_point_v2 -------//
  1043. void Misc::cal_move_around_a_point_v2(short num, short width, short height, int& xShift, int& yShift)
  1044. {
  1045. short maxSqtSize = (width>height) ? height+1 : width+1;
  1046. //short num2 = num%(maxSqtSize*maxSqtSize) + 1;
  1047. short num2 = (num-1)%(maxSqtSize*maxSqtSize) + 1;
  1048. if(num2<=1)
  1049. {
  1050. xShift = yShift = 0;
  1051. return;
  1052. }
  1053. int sqtCount = 1;
  1054. while(sqtCount<210) // the max. size of the map is 200x200
  1055. {
  1056. if(num2<=sqtCount*sqtCount)
  1057. break;
  1058. else
  1059. sqtCount += 2;
  1060. }
  1061. int filter = (sqtCount-1)/2; // is an integer
  1062. int refNum = num2 - (sqtCount-2)*(sqtCount-2);
  1063. //=====================================//
  1064. // some adjustment to the refNum can
  1065. // generate different mode of result
  1066. //=====================================//
  1067. // note: sqtCount>=3 for this mode
  1068. refNum = (refNum-1-(sqtCount-3)/2)%(4*(sqtCount-1)) + 1;
  1069. //-------------------------------------------------//
  1070. // determine xMag
  1071. //-------------------------------------------------//
  1072. int xMag;
  1073. if(refNum < sqtCount)
  1074. xMag = refNum - 1;
  1075. else
  1076. {
  1077. if(refNum>=sqtCount && refNum<=3*(sqtCount-1))
  1078. xMag = (sqtCount<<1) - 1 - refNum; //(sqtCount-1) - (refNum-sqtCount);
  1079. else if(refNum >= sqtCount+2*(sqtCount-1))
  1080. xMag = refNum + 3 - (sqtCount<<2); //(refNum-sqtCount-2*(sqtCount-1)) - (sqtCount-1);
  1081. else
  1082. err_here();
  1083. }
  1084. //-------------------------------------------------//
  1085. // calculate xShift
  1086. //-------------------------------------------------//
  1087. if(xMag>0) // +ve
  1088. xShift = (xMag>filter) ? filter : xMag;
  1089. else // -ve
  1090. xShift = (-xMag>filter) ? -filter : xMag;
  1091. //-------------------------------------------------//
  1092. // calculate yShift
  1093. //-------------------------------------------------//
  1094. //ySign = (refNum>sqtCount && refNum<=3*sqtCount-3) ? -1 : 1;
  1095. int yMag = (sqtCount-1) - abs(xMag); // abs(xMag) + abs(yMag) always = (sqtCount-1)
  1096. if(refNum>sqtCount && refNum<=3*sqtCount-3) // -ve
  1097. yShift = (yMag>filter) ? -filter : -yMag;
  1098. else // +ve
  1099. yShift = (yMag>filter) ? filter : yMag;
  1100. }
  1101. //------ End of function Misc::cal_move_around_a_point_v2 ---------//
  1102. //-------- Begin of function Misc::construct_move_around_table -------//
  1103. void Misc::construct_move_around_table()
  1104. {
  1105. if(move_around_table_size==MOVE_AROUND_TABLE_SIZE)
  1106. return; // table already created
  1107. int xShift, yShift;
  1108. char *xPtr = move_around_table_x;
  1109. char *yPtr = move_around_table_y;
  1110. for(int i=1; i<=MOVE_AROUND_TABLE_SIZE; ++i, xPtr++, yPtr++)
  1111. {
  1112. cal_move_around_a_point_v2(i, MOVE_AROUND_TABLE_SIZE, MOVE_AROUND_TABLE_SIZE, xShift, yShift);
  1113. *xPtr = char(xShift);
  1114. *yPtr = char(yShift);
  1115. }
  1116. move_around_table_size = MOVE_AROUND_TABLE_SIZE;
  1117. }
  1118. //------ End of function Misc::construct_move_around_table ---------//
  1119. //-------- Begin of function Misc::set_surround_bit -------//
  1120. void Misc::set_surround_bit(long int& flag, int bitNo)
  1121. {
  1122. static long int bitFlag[20] = {0x000001, 0x000002, 0x000004, 0x000008, 0x000010, 0x000020, 0x000040, 0x000080,
  1123. 0x000100, 0x000200, 0x000400, 0x000800, 0x001000, 0x002000, 0x004000, 0x008000,
  1124. 0x010000, 0x020000, 0x040000, 0x080000};
  1125. err_when(bitNo<0 || bitNo>=20);
  1126. flag |= bitFlag[bitNo];
  1127. }
  1128. //------ End of function Misc::set_surround_bit ---------//
  1129. //------- Begin of function Misc::roman_number -------//
  1130. char* Misc::roman_number(int inNum)
  1131. {
  1132. err_when( inNum<1 || inNum >= 1000 );
  1133. static char* roman_number_array[] =
  1134. { "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X" };
  1135. static String str;
  1136. str = "";
  1137. if( inNum > 100 )
  1138. {
  1139. str += roman_number_array[inNum/100-1];
  1140. inNum = inNum - inNum/100*100;
  1141. }
  1142. if( inNum > 10 )
  1143. {
  1144. str += roman_number_array[(inNum-1)/10-1];
  1145. inNum = inNum - (inNum-1)/10*10;
  1146. }
  1147. err_when( inNum<1 || inNum>10 );
  1148. str += roman_number_array[inNum-1];
  1149. return str;
  1150. }
  1151. //------ End of function Misc::roman_number ---------//
  1152. // ###### begin Gilbert 19/6 ########//
  1153. Misc::Misc()
  1154. {
  1155. freeze_seed = 0;
  1156. construct_move_around_table();
  1157. }
  1158. void Misc::lock_seed()
  1159. {
  1160. freeze_seed = 1;
  1161. }
  1162. void Misc::unlock_seed()
  1163. {
  1164. freeze_seed = 0;
  1165. }
  1166. int Misc::is_seed_locked()
  1167. {
  1168. return freeze_seed > 0;
  1169. }
  1170. // ###### end Gilbert 19/6 ########//