/*
* Seven Kingdoms: Ancient Adversaries
*
* Copyright 1997,1998 Enlight Software Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
//Filename : OMISC.CPP
//Description : Object of Misc useful functions
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MOVE_AROUND_TABLE_SIZE 900
static char move_around_table_x[MOVE_AROUND_TABLE_SIZE] = {0};
static char move_around_table_y[MOVE_AROUND_TABLE_SIZE] = {0};
static short move_around_table_size = 0;
#if(defined(SPANISH))
#define THOUSAND_SEPARATOR '.'
#define DECIMAL_SEPARATOR ','
#else
#define THOUSAND_SEPARATOR ','
#define DECIMAL_SEPARATOR '.'
#endif
//-------- Start of function Misc::delay -------------//
//
// Misc::delay for specified seconds
//
// float wait = the no. of second to wait
//
void Misc::delay(float wait)
{
clock_t stopTime;
stopTime = (long) (clock() + (wait * CLOCKS_PER_SEC));
while( clock() < stopTime );
}
//--------- End of function Misc::delay ---------------//
//-------- BEGIN OF FUNCTION Misc::str_shorten --------//
//
// Shorten the string with words exceed the dest. length cut.
//
// = destination string
// = source string (source should be longer than dest)
// = max. no. of characters in the dest. string.
// ( destStr should be allocated as destStr[destLen+1] )
//
void Misc::str_shorten(char* destStr, char* srcStr, int destLen)
{
strncpy( destStr, srcStr, destLen );
destStr[destLen]=NULL;
//------ no need to cut characters if it fit preciously ----//
//
// e.g. "One Two Three" ---> "One Two"
// (srcStr) (destStr, return it as the result)
//----------------------------------------------------------//
if( (int)strlen(srcStr) < destLen || srcStr[destLen] == ' ' )
return;
//--- if there is only one word in the string, don't cut it ----//
//
// e.g. "VeryLongWord" --> "VeryLongWo"
//
//--------------------------------------------------------------//
if( !str_chr( destStr, ' ' ) )
return;
//------ if there is more than one word, cut it ------//
//
// e.g. "One Two Three" ----> "One Two Thr" ---> "One Two"
// (srcStr) (destStr before) (destStr after)
//
//----------------------------------------------------//
int i;
for( i=destLen-1 ; i>0 && destStr[i] != ' ' ; i-- )
destStr[i] = NULL;
destStr[i] = NULL; // trim the space also
}
//------------ END OF FUNCTIN Misc::str_shorten -----------------//
//-------- BEGIN OF FUNCTION Misc::str_cut --------//
//
// Syntax : Misc::str_cut( ,,, )
//
// Description : cut up string1 and place the resuit in string 2
//
// = destination string
// = source string
// = the start position of the new string
// = the no. of characters to copied. (default:to the end of the string)
//
int Misc::str_cut(char* dstr, char* sstr, int schar, int charnum )
{
int si,di,forever;
forever = (charnum < 0);
for (si=schar-1,di=0 ; ( di, = the string to the scanned.
// = the key character
// [int] = the start position of the string to be scanned (1)
// [int] = the end position of the string to be scanned (-1)
//
// return : a positive number indicating the position of the first occurance
// FAIL / NULL if not found
//
int Misc::str_chr( char* str, char chr, int spos, int epos )
{
int i;
epos--;
for (i=spos-1 ; str[i] && ( i<=epos || epos==-2 ) ; i++)
{
if ( str[i] == chr )
return(i+1);
}
return 0;
}
//----------- END OF FUNCTION Misc::str_chr -------------//
//---------- BEGIN OF FUNCTION Misc::str_str ----------------//
//
// Description : return the position of the first occurance of the character
// in the string
//
// Syntax : Misc::str_str( , , [int], [int] )
//
// = the string to the scanned.
// = the key string
// [int] = the start position of the string to be scanned (1)
// [int] = the end position of the string to be scanned (-1)
//
// return : a positive number indicating the position of the first occurance
// FAIL / NULL if not found
//
int Misc::str_str( char* str, char* fstr, int spos, int epos )
{
int i,j,flen;
if (epos == -1)
epos = strlen(str);
flen = strlen(fstr);
epos -= flen ;
for (i=spos-1 ; str[i] && i<=epos ; i++)
{
for (j= 0; j < flen && str[i+j] ; j++ )
{
if ( str[i+j] != fstr[j] ) // exactly equal
break;
}
if ( j==flen ) // all equal
return (i+1) ;
}
return 0;
}
//----------- END OF FUNCTION Misc::str_str -------------//
//------ BEGIN OF FUNCTION Misc::upper ---------//
//
// Description : Convert the character to upper case
//
// Syntax : Misc::upper()
//
// return : the converted character
//
//
int Misc::upper(int inchar)
{
if ( inchar >= 'a' && inchar <= 'z' )
inchar -= 32;
return( inchar );
}
//----- END OF FUNCTION Misc::upper ------------//
//------ BEGIN OF FUNCTION Misc::lower ---------//
//
// Description : Convert the character to lower case
//
// Syntax : Misc::lower()
//
// return : the converted character
//
//
int Misc::lower(int inchar)
{
if ( inchar >= 'A' && inchar <= 'Z' )
inchar += 32;
return( inchar );
}
//----- END OF FUNCTION Misc::lower ------------//
//--------- BEGIN OF FUNCTION Misc::ltrim_len ---------//
//
// Description : return the number of character in the string
// with left space cut
//
int Misc::ltrim_len(char* inStr,int spos,int len)
{
int i,j;
if ( len == -1 )
len = strlen(inStr);
for( i = spos-1,j=0 ; j inStr = the pointer to the string
// [int] spos = start position of the string from the pointer
// (default : 1)
// [int] len = length of the string
// (default : until NULL)
//
int Misc::rtrim_len(char* inStr,int spos,int len)
{
int i,j;
if ( len == -1 )
len = strlen(inStr);
for( i = spos+len-2,j=0 ; j = the destination
// = the source
//
// Note : the destination memory must be allocated
//
void Misc::rtrim( char* des, char* src )
{
int i;
for ( i=strlen(src)-1 ; src[i]==' ' && i>=0 ; i-- )
des[i] = src[i];
des[i+1] = NULL;
}
//------- END OF FUNCTION Misc::rtrim --------//
//------ BEGIN OF FUNCTION Misc::ltrim ---------//
//
// = the destination
// = the source
//
// Note : the destination memory must be allocated
//
void Misc::ltrim( char* des, char* src )
{
int i,j;
for ( i=0 ; src[i]==' ' && src[i] ; )
i++ ;
for ( j=0 ; src[i] ; i++,j++ )
des[j] = src[i];
des[j] = NULL;
}
//------- END OF FUNCTION Misc::ltrim --------//
//------ BEGIN OF FUNCTION Misc::alltrim ---------//
//
// = the destination
// = the source
//
// Note : the destination memory must be allocated
//
void Misc::alltrim( char* des, char* src)
{
int i,j;
for ( i=0 ; src[i]==' ' && src[i] ; )
i++ ;
for ( j=0 ; src[i] && src[i]!=' ' ; i++,j++ )
des[j] = src[i];
des[j] = NULL;
}
//------- END OF FUNCTION Misc::alltrim --------//
//------ BEGIN OF FUNCTION Misc::rtrim ---------//
//
// = the string, the result is put back into the original string pointer
//
char* Misc::rtrim( char* str )
{
int i;
for ( i=strlen(str)-1 ; str[i]==' ' && i>=0 ; i-- );
str[i+1] = NULL;
return str;
}
//------- END OF FUNCTION Misc::rtrim --------//
//------ BEGIN OF FUNCTION Misc::ltrim ---------//
//
// = the string
//
char* Misc::ltrim( char* str )
{
int i,j;
for ( i=0 ; str[i]==' ' && str[i] ; i++ );
for ( j=0 ; str[i] ; i++,j++ )
str[j] = str[i];
str[j] = NULL;
return str;
}
//------- END OF FUNCTION Misc::ltrim --------//
//------ BEGIN OF FUNCTION Misc::alltrim ---------//
//
// = the string
//
char* Misc::alltrim( char* str )
{
int i,j;
for ( i=0 ; str[i]==' ' && str[i] ; i++ );
for ( j=0 ; str[i] && str[i]!=' ' ; i++,j++ )
str[j] = str[i];
str[j] = NULL;
return str;
}
//------- END OF FUNCTION Misc::alltrim --------//
//------- BEGIN OF FUNCTION Misc::empty ------------//
//
// Description : empty a string
//
// Syntax : Misc::empty(<*char>,)
//
// <*char> = the pointer of the string
// = the length of the string (not include the null string )
//
void Misc::empty(char *inStr, int strLen )
{
memset( inStr,' ',strLen);
inStr[strLen] = NULL;
}
//-------- END OF FUNCTION Misc::empty ---------//
//------- BEGIN OF FUNCTION Misc::is_empty ------------//
//
// Description : empty a string
//
// Syntax : Misc::is_empty(<*char>,[int],[int])
//
// <*char> = the pointer of the string
// [int] = the length of the string (not include the null string )
//
int Misc::is_empty(char *inStr, int strLen)
{
int i;
if( !strLen )
strLen = strlen(inStr);
for( i=0 ; i "ABC "
//
// str = the string to be formated
// len = the deserved length after formatted
// [char] endChar = the end character of the string ( default : NULL terminator )
//
void Misc::fix_str(char* str,int len,char endChar)
{
int oldLen;
if ( endChar == NULL )
oldLen = strlen(str);
else
{
oldLen = Misc::str_chr(str,endChar)-1;
err_if ( oldLen == -1 ) // the end character not found
err_now("Misc::fix_str");
}
if ( len > oldLen )
memset( str+oldLen, ' ', len-oldLen );
str[len] = NULL;
}
//--------- END OF FUNCTION Misc::fix_str ---------//
//------- BEGIN OF FUNCTION Misc::valid_char --------//
//
// Description : test if the character is valid for field and file name
//
// Syntax : Misc::valid_char()
//
// = the character to be validify
//
// return : SUCCEED or FAIL
//
int Misc::valid_char( char ch )
{
return ( ch>='a' && ch<='z' ||
ch>='A' && ch<='Z' ||
ch>='0' && ch<='9' ||
ch=='\\' || ch=='.' || ch=='_' || ch==':' ) ;
}
//--------- END OF FUNCTION Misc::valid_char ----------//
//------- BEGIN OF FUNCTION Misc::str_cmp -----------//
//
// Description : compare string
//
// Return : SUCCEED if the same
// FAIL if different
//
// e.g "ABCDE" <> "ABC"
// "ABCDE " = "ABCDE"
// "ABCDE" <> "ABCDEF"
// "ABCDE" <> "ABCDE "
int Misc::str_cmp( char* str1, char* str2 )
{
err_when( !str1 || !str2 );
int i;
for (i=0 ; str1[i] && str2[i] ; i++)
if ( str1[i] != str2[i] )
return 0;
return ( str2[i] == NULL && (str1[i]==NULL || str1[i]==' ') );
}
//--------- END OF FUNCTION Misc::str_cmp -----------//
//------- BEGIN OF FUNCTION Misc::str_cmpx -----------//
//
// Description : String Inexact comparsion
//
// Return : SUCCEED if the same
// FAIL if different
//
// e.g "ABCDE" = "ABC"
// "ABCDE " = "ABCDE"
// "ABCDE" <> "ABCDEF"
// "ABCDE" <> "ABCDE "
//
int Misc::str_cmpx( char* str1, char* str2 )
{
err_when( !str1 || !str2 );
int i;
for (i=0 ; str1[i] && str2[i] ; i++)
if ( str1[i] != str2[i] )
return 0;
return ( str2[i] == NULL );
}
//--------- END OF FUNCTION Misc::str_cmpx -----------//
//------- BEGIN OF FUNCTION Misc::str_icmpx -----------//
//
// Description : String Inexact comparsion without case sensitive
//
// Return : SUCCEED if the same
// FAIL if different
//
// e.g "ABCDE" = "ABC"
// "abcde " = "ABCDE"
// "ABCDE" <> "ABCDEF"
// "ABCDE" <> "ABCDE "
int Misc::str_icmpx( char* str1, char* str2 )
{
err_when( !str1 || !str2 );
int i;
register int a,b;
for (i=0 ; (a=str1[i]) != NULL && (b=str2[i]) != NULL ; i++)
{
if ( a >= 'a' && a <= 'z' )
a -= 32;
if ( b >= 'a' && b <= 'z' )
b -= 32;
if ( a != b )
return 0;
}
return ( str2[i] == NULL );
}
//--------- END OF FUNCTION Misc::str_icmpx -----------//
//-------- BEGIN OF FUNCTION Misc::check_sum ----------//
//
// Return the checksum of the string
//
// = the string
// [int] = length of the string
int Misc::check_sum(char* str, int len)
{
int i,checksum;
if ( len == -1 )
len = strlen( str );
for( checksum=0,i=0 ; i the pointer to the converted string, the string
// is stored in static variable which will be overwritten
// in next call.
//
char* Misc::format( int inNum, int formatType )
{
static char outBuf[35];
static char longBuf[25];
char *outPtr=outBuf;
char *longStr;
int i, intDigit, sign;
if( inNum < 0 )
{
sign = -1;
inNum = -inNum;
}
else
sign = 0;
longStr = ltoa( inNum, longBuf, 10 );
intDigit = strlen(longStr); // no. of integer digits
//--------- negetive bracket ------------//
if( sign < 0 )
*outPtr++ = '(';
//--------- dollar sign ------------//
if( formatType == 2 )
*outPtr++ = '$';
//-------- integer number -----------//
for( i=intDigit ; i>0 ; i-- )
{
if( formatType != 4 ) // no thousand separators for format 4
{
if( i%3 == 0 && i < intDigit )
*outPtr++ = THOUSAND_SEPARATOR;
}
*outPtr++ = *longStr++;
}
//--------- percent sign (%) ------------//
if( formatType == 3 )
*outPtr++ = '%';
//--------- negetive bracket ----------//
if( sign < 0 )
*outPtr++ = ')';
*outPtr++ = NULL;
return outBuf;
}
//---------- End of function Misc::format ---------//
//---------- Begin of function Misc::format --------//
//
// Format a number to a float number to format string
// Note : the formated string is right justified
//
// inNum = the number to be formated
// use instead of because
// fcvt() only accept
//
// [int] formatType = 1 - 1,000,000 add thousand seperator
// 2 - $1,000,000 add thousand seperator and dollar sign
// 3 - 56% add percentage sign % at the end of the number
//
// return the pointer to the converted string, the string
// is stored in static variable which will be overwritten
// in next call.
//
char* Misc::format(double inNum, int formatType)
{
enum { MONEY_DEC_PLACE = 2 };
static char outBuf[35];
char *outPtr=outBuf;
char *floatStr;
int i, intDigit, sign; // intDigit = no. of integer digits
floatStr = fcvt( inNum, MONEY_DEC_PLACE, &intDigit, &sign );
#ifdef DEBUG
if( intDigit > 29 ) // integer digits can't exceed 29
err.run( "Misc::format(), inNum : %e, formatType : %d", inNum, formatType );
#endif
//--------- negetive bracket ------------//
if( inNum < 0 )
*outPtr++ = '(';
//--------- dollar sign ($) ------------//
if( formatType == 2 )
*outPtr++ = '$';
//------- integer number -----------//
for( i=intDigit ; i>0 ; i-- )
{
if( i%3 == 0 && i < intDigit )
*outPtr++ = THOUSAND_SEPARATOR;
*outPtr++ = *floatStr++;
}
if( intDigit <= 0 )
*outPtr++ = '0';
//------- dec. place number -----------//
if( inNum > -1000 && inNum < 1000 ) // if the number is less than 1000, add dec. places
{ // if the number is greater than 1000, truncate any dec. places
*outPtr++ = DECIMAL_SEPARATOR;
if( *floatStr && intDigit >= 0 ) // e.g. 0.03 --> str:"3", intDight:-1
*outPtr++ = *floatStr++; // 1st dec. place
else
*outPtr++ = '0'; // add a '0' when intDigit < 0
if( *floatStr ) // 2nd dec. place
*outPtr++ = *floatStr++;
else
*outPtr++ = '0';
}
//--------- percent sign (%) ------------//
if( formatType == 3 )
*outPtr++ = '%';
//--------- negetive bracket ------------//
if( inNum < 0 )
*outPtr++ = ')';
*outPtr++ = NULL;
return outBuf;
}
//---------- End of function Misc::format ---------//
//---------- Begin of function Misc::num_to_str --------//
//
// Convert a number into string.
//
// int inNum = the number to be converted
//
// return : the converted string.
//
char* Misc::num_to_str(int inNum)
{
static char strBuf[25];
return ltoa( inNum, strBuf, 10 );
}
//---------- End of function Misc::format ---------//
//---------- Begin of function Misc::nullify -------//
//
// Nullify and right trim a string field in the record
//
// strPtr = string pointer
// strLen = string length
//
// Return : the nullied string which only stored in static
// buffer temporary until next call to nullify()
//
// note : if the string is longer than the buffer space, the string
// will be truncated
//
char* Misc::nullify(char* strPtr, int strLen)
{
int i;
if( strLen > STR_BUF_LEN )
strLen = STR_BUF_LEN;
memcpy( str_buf, strPtr, strLen );
for( i=strLen-1 ; i>=0 ; i-- ) // Right Trim
{
if( str_buf[i] != ' ' )
{
str_buf[i+1] = NULL;
break;
}
}
if( i<0 ) // Empty value
str_buf[0] = NULL;
return str_buf;
}
//----------- End of function Misc::nullify ----------//
//-------- Begin of function Misc::rtrim_fld ---------//
//
// Rtrim a text field and copy it to variable
//
// varPtr = pointer to the variable
// fldPtr = pointer to the field
// fldLen = length of the field
//
// Note must be pre-allocated with a len > fldLen+1
//
void Misc::rtrim_fld(char* varPtr, char* fldPtr, int fldLen)
{
int rtrimLen = rtrim_len( fldPtr, 1, fldLen );
memcpy( varPtr, fldPtr, rtrimLen );
varPtr[rtrimLen] = NULL;
}
//---------- End of function Misc::rtrim_fld ---------//
//------- Begin of function Misc::atoi ---------//
//
// Same as atoi() in stdlib.h instead it allows you to specify the
// length of the string
//
// str = the string to be converted to integer
// strLen = length of the string
int Misc::atoi( char *str, int strLen )
{
if ( strLen >= sizeof( str_buf ) )
strLen = sizeof( str_buf ) - 1 ;
memcpy( str_buf, str, (size_t)strLen ) ;
str_buf[strLen] = '\0' ;
return ::atoi( str_buf ) ;
}
//---------- End of function Misc::atoi ---------//
//------- Begin of function Misc::sqrt ---------//
//
// Find the square root of an long integer
//
// x = the value for calculating its square root
//
int Misc::sqrt(long x)
{
err_when( x < 0 );
long OddInt, OldArg, FirstSqrt;
OddInt=1;
OldArg=x;
while(x>=0)
{
x-=OddInt;
OddInt+=2;
}
FirstSqrt=OddInt >> 1;
if( FirstSqrt*FirstSqrt - FirstSqrt + 1 > OldArg)
return(FirstSqrt-1);
else
return(FirstSqrt);
}
//---------- End of function Misc::sqrt ---------//
//------- Begin of function Misc::diagonal_distance ---------//
//
// Given two lengths in x and y coordination, then find the diagonal
// distance between them
// result = the square root of X*X + Y*Y
//
// x1, y1 = the starting point of the diagonal line
// x2, y2 = the ending point of the diagonal line
//
int Misc::diagonal_distance(int x1, int y1, int x2, int y2)
{
int x = abs(x1-x2);
int y = abs(y1-y2);
return Misc::sqrt( x*x + y*y );
}
//---------- End of function Misc::diagonal_distance ---------//
//------- Begin of function Misc::points_distance ---------//
//
// Given two lengths in x and y coordination, then find the
// distance between two points, taking diagonal distance
// the same as the horizontal and vertical distances.
//
// x1, y1 = the starting point of the diagonal line
// x2, y2 = the ending point of the diagonal line
//
int Misc::points_distance(int x1, int y1, int x2, int y2)
{
int x = abs(x1-x2);
int y = abs(y1-y2);
return max(x, y);
}
//---------- End of function Misc::points_distance ---------//
//------- Begin of function Misc::get_random_seed --------//
//
long Misc::get_random_seed()
{
return random_seed;
}
//---------- End of function Misc::get_random_seed ---------//
//------- Begin of function Misc::randomize --------//
//
void Misc::randomize()
{
set_random_seed(time(NULL));
}
//---------- End of function Misc::randomize ---------//
//------- Begin of function Misc::set_random_seed --------//
//
void Misc::set_random_seed(long randomSeed)
{
// ###### begin Gilbert 19/6 ######//
err_when( is_seed_locked() );
// ###### end Gilbert 19/6 ######//
random_seed = randomSeed;
}
//---------- End of function Misc::set_random_seed ---------//
//------- Begin of function Misc::random ---------//
//
// maxNum = maximum random number, it must <= 0x7FFF
// in 32 bit compiler =
//
// return : the random number
//
int Misc::random(int maxNum)
{
err_if( maxNum < 0 || maxNum > 0x7FFF )
err_now( "Misc::random()" );
// ###### begin Gilbert 19/6 ######//
err_when( is_seed_locked() );
// ###### end Gilbert 19/6 ######//
#define MULTIPLIER 0x015a4e35L
#define INCREMENT 1
#define RANDOM_MAX 0x7FFFU
random_seed = MULTIPLIER * random_seed + INCREMENT;
return maxNum * ((random_seed >> 16) & RANDOM_MAX) / (RANDOM_MAX+1);
}
//---------- End of function Misc::random ---------//
//------- Begin of function Misc::rand ---------//
//
// Return a random number from 0 to 0x7FFF
//
// return : a random number from from 0 to 0x7FFF
//
int Misc::rand()
{
#define MULTIPLIER 0x015a4e35L
#define INCREMENT 1
#define RANDOM_MAX 0x7FFFU
// ###### begin Gilbert 19/6 ######//
err_when( is_seed_locked() );
// ###### end Gilbert 19/6 ######//
random_seed = MULTIPLIER * random_seed + INCREMENT;
return ((random_seed >> 16) & RANDOM_MAX);
}
//---------- End of function Misc::rand ---------//
//------- Begin of function Misc::round ---------//
//
// Round the float no. to the 2 signicant values :
//
// Since this function is not called frequently, we can afford
// to use a slower algorithm.
//
// inValue = the number to be rounded.
// signPlace = round to no. of signicant places.
// [int] roundDirection = 0-if <= 4, round to a smaller, if >=5 round to a bigger
// 1-round to a smaller number
// 2-round to a bigger number
// (default : 0)
//
// return : the rounded number
//
float Misc::round(float inValue, int signPlace, int roundDirection)
{
int i;
float baseValue = (float) 1;
float minValue = (float) 10;
for( i=2 ; i<=signPlace ; i++ )
minValue *= 10;
while( inValue > minValue )
{
inValue /= 10;
baseValue *= 10;
}
float outValue = (float)((int)inValue) * baseValue;
//-----------------------------------------------//
//
// If the result number is smaller than the given number
// and the roundDirection is rounding to a bigger number,
// than increase result number.
//
//-----------------------------------------------//
if( outValue!=inValue )
{
if( (roundDirection==0 && ((int)inValue)%10 >= 5) ||
roundDirection==2 )
{
outValue = (float)((int)inValue+1) * baseValue;
}
}
return outValue;
}
//---------- End of function Misc::round ---------//
//------- Begin of function Misc::round_dec ---------//
//
// Round the number to its nearest 2 decimal places.
//
// inNum - the input number.
//
// Return : the output number
//
float Misc::round_dec(float inNum)
{
return (float)((int)(inNum * 100)) / 100;
}
//---------- End of function Misc::round_dec ---------//
//------- Begin of function Misc::is_file_exist ---------//
//
// Check whether the given file exists in the current directory or not
//
// fileName = the name of the file
//
// return : 1 - the file exists
// 0 - doesn't exist
//
int Misc::is_file_exist(char* fileName)
{
WIN32_FIND_DATA findData;
HANDLE findHandle = FindFirstFile( fileName, &findData );
return findHandle!=INVALID_HANDLE_VALUE;
}
//---------- End of function Misc::is_file_exist ---------//
//------- Begin of function Misc::change_file_ext ---------//
//
// Change file extension.
//
// desFileName = the destination file name to be written
// srcFileName = the source file name
// newExt = the new extension.
//
void Misc::change_file_ext(char* desFileName, char* srcFileName, char* newExt)
{
int nameLen = m.str_chr(srcFileName, '.'); // include the '.' in the nameLen
err_when( nameLen<1 || nameLen>9 || strlen(newExt)>3 );
memcpy( desFileName, srcFileName, nameLen );
strcpy( desFileName+nameLen, newExt ); // extension for scenarion text file
}
//---------- End of function Misc::change_file_ext ---------//
//------- Begin of function Misc::extract_file_name ---------//
//
// Extract the file name from a full file path.
//
// desFileName = the destination buffer to be written
// srcFileName = the source file name
//
void Misc::extract_file_name(char* desFileName, char* srcFileName)
{
int i;
for( i=strlen(srcFileName) ; i>=0 ; i-- )
{
if( srcFileName[i]=='\\' ) // get last '\' before the file name
break;
}
strncpy(desFileName, srcFileName+i+1, MAX_PATH);
desFileName[MAX_PATH]=NULL;
}
//---------- End of function Misc::extract_file_name ---------//
//------- Begin of function Misc::num_th ---------//
//
// Convert the number into 99th format.
//
// inNum = the input number
//
// return : the result string
//
char* Misc::num_th(int inNum)
{
static String str;
str = format(inNum);
if( inNum >=11 && inNum <= 13 )
{
str += "th";
}
else
{
switch( inNum%10 )
{
case 1:
str += "st";
break;
case 2:
str += "nd";
break;
case 3:
str += "rd";
break;
default:
str += "th";
break;
}
}
return str;
}
//---------- End of function Misc::num_th ---------//
//------- Begin of function Misc::get_time ---------//
//
unsigned long Misc::get_time()
{
return timeGetTime();
}
//---------- End of function Misc::get_time ---------//
//------- Begin of function Misc::del_array_rec ---------//
//
// Delete a record in an array.
//
// arrayBody - the array pointer
// arraySize - size of the array
// recSize - record size
// delRecno - recno to be deleted.
//
void Misc::del_array_rec(void* arrayBody, int arraySize, int recSize, int delRecno)
{
err_when( arraySize<1 );
err_when( delRecno<1 || delRecno>arraySize);
int t = delRecno-1;
char* arrayPtr = (char*) arrayBody;
memmove( arrayPtr+recSize*t, arrayPtr+recSize*(t+1),
recSize * (arraySize-t-1) );
}
//---------- End of function Misc::del_array_rec ---------//
//-------- Begin of function Misc::cal_move_around_a_point -------//
// This function is used to return the x_Offset and y_Offset from the
// center of the square. The detail is shown in the following figure.
//
//
// 21 20 19 18 17
// 22 7 6 5 16
// 23 8 1 4 15
// 24 9 2 3 14
// 25 10 11 12 13
//
// Assume the square is 5x5, 1 is the center of the square. The input
// value of num determine which point is processed. For instance, 9 is
// processed if num=9.
//
// using the center as the reference point, (xShift, yShift) = (-1, -1)
// for num=7, (xShift, yShift) = (0,2) for num=11.
//
// For num>25 in this case, multiply of 25 will be cut out until num<=25.
//
void Misc::cal_move_around_a_point(short num, short width, short height, int& xShift, int& yShift)
{
short maxSqtSize = (width>height) ? height+1 : width+1;
//short num2 = num%(maxSqtSize*maxSqtSize) + 1;
short num2 = (num-1)%(maxSqtSize*maxSqtSize) + 1;
if(num2<=MOVE_AROUND_TABLE_SIZE)
{
xShift = int(*(move_around_table_x+num2-1));
yShift = int(*(move_around_table_y+num2-1));
/*#ifdef DEBUG2
int xShift2, yShift2;
cal_move_around_a_point_v2(num, width, height, xShift2, yShift2);
err_when(xShift!=xShift2);
err_when(yShift!=yShift2);
#endif*/
return;
}
else
cal_move_around_a_point_v2(num, width, height, xShift, yShift);
}
//------ End of function Misc::cal_move_around_a_point ---------//
//-------- Begin of function Misc::cal_move_around_a_point_v2 -------//
void Misc::cal_move_around_a_point_v2(short num, short width, short height, int& xShift, int& yShift)
{
short maxSqtSize = (width>height) ? height+1 : width+1;
//short num2 = num%(maxSqtSize*maxSqtSize) + 1;
short num2 = (num-1)%(maxSqtSize*maxSqtSize) + 1;
if(num2<=1)
{
xShift = yShift = 0;
return;
}
int sqtCount = 1;
while(sqtCount<210) // the max. size of the map is 200x200
{
if(num2<=sqtCount*sqtCount)
break;
else
sqtCount += 2;
}
int filter = (sqtCount-1)/2; // is an integer
int refNum = num2 - (sqtCount-2)*(sqtCount-2);
//=====================================//
// some adjustment to the refNum can
// generate different mode of result
//=====================================//
// note: sqtCount>=3 for this mode
refNum = (refNum-1-(sqtCount-3)/2)%(4*(sqtCount-1)) + 1;
//-------------------------------------------------//
// determine xMag
//-------------------------------------------------//
int xMag;
if(refNum < sqtCount)
xMag = refNum - 1;
else
{
if(refNum>=sqtCount && refNum<=3*(sqtCount-1))
xMag = (sqtCount<<1) - 1 - refNum; //(sqtCount-1) - (refNum-sqtCount);
else if(refNum >= sqtCount+2*(sqtCount-1))
xMag = refNum + 3 - (sqtCount<<2); //(refNum-sqtCount-2*(sqtCount-1)) - (sqtCount-1);
else
err_here();
}
//-------------------------------------------------//
// calculate xShift
//-------------------------------------------------//
if(xMag>0) // +ve
xShift = (xMag>filter) ? filter : xMag;
else // -ve
xShift = (-xMag>filter) ? -filter : xMag;
//-------------------------------------------------//
// calculate yShift
//-------------------------------------------------//
//ySign = (refNum>sqtCount && refNum<=3*sqtCount-3) ? -1 : 1;
int yMag = (sqtCount-1) - abs(xMag); // abs(xMag) + abs(yMag) always = (sqtCount-1)
if(refNum>sqtCount && refNum<=3*sqtCount-3) // -ve
yShift = (yMag>filter) ? -filter : -yMag;
else // +ve
yShift = (yMag>filter) ? filter : yMag;
}
//------ End of function Misc::cal_move_around_a_point_v2 ---------//
//-------- Begin of function Misc::construct_move_around_table -------//
void Misc::construct_move_around_table()
{
if(move_around_table_size==MOVE_AROUND_TABLE_SIZE)
return; // table already created
int xShift, yShift;
char *xPtr = move_around_table_x;
char *yPtr = move_around_table_y;
for(int i=1; i<=MOVE_AROUND_TABLE_SIZE; ++i, xPtr++, yPtr++)
{
cal_move_around_a_point_v2(i, MOVE_AROUND_TABLE_SIZE, MOVE_AROUND_TABLE_SIZE, xShift, yShift);
*xPtr = char(xShift);
*yPtr = char(yShift);
}
move_around_table_size = MOVE_AROUND_TABLE_SIZE;
}
//------ End of function Misc::construct_move_around_table ---------//
//-------- Begin of function Misc::set_surround_bit -------//
void Misc::set_surround_bit(long int& flag, int bitNo)
{
static long int bitFlag[20] = {0x000001, 0x000002, 0x000004, 0x000008, 0x000010, 0x000020, 0x000040, 0x000080,
0x000100, 0x000200, 0x000400, 0x000800, 0x001000, 0x002000, 0x004000, 0x008000,
0x010000, 0x020000, 0x040000, 0x080000};
err_when(bitNo<0 || bitNo>=20);
flag |= bitFlag[bitNo];
}
//------ End of function Misc::set_surround_bit ---------//
//------- Begin of function Misc::roman_number -------//
char* Misc::roman_number(int inNum)
{
err_when( inNum<1 || inNum >= 1000 );
static char* roman_number_array[] =
{ "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X" };
static String str;
str = "";
if( inNum > 100 )
{
str += roman_number_array[inNum/100-1];
inNum = inNum - inNum/100*100;
}
if( inNum > 10 )
{
str += roman_number_array[(inNum-1)/10-1];
inNum = inNum - (inNum-1)/10*10;
}
err_when( inNum<1 || inNum>10 );
str += roman_number_array[inNum-1];
return str;
}
//------ End of function Misc::roman_number ---------//
// ###### begin Gilbert 19/6 ########//
Misc::Misc()
{
freeze_seed = 0;
construct_move_around_table();
}
void Misc::lock_seed()
{
freeze_seed = 1;
}
void Misc::unlock_seed()
{
freeze_seed = 0;
}
int Misc::is_seed_locked()
{
return freeze_seed > 0;
}
// ###### end Gilbert 19/6 ########//