📄 aipbase.cpp
字号:
//**********************************************************************
// aipBase.cpp - function bodies for aipBase.h
//
// Copyright (c) 1999, 2005, 2007, 2008 Brian Marshall
//
// See the license at end of this file.
//
// Developers/Contributers:
// [BRM] Brian Marshall - Calgary - bmarshal@agt.net
//
// 08/07/09 [BRM] new random_num(), logging, is_one_chance_in_x()
// multiple small changes
// 05/11/07 [BRM] random_num() now in class aipBase
// 05/11/01 [BRM] added aip_strncpy() that always terminates string
// 05/09/10 [BRM] development began
//
//----------------------------------------------------------------------
#include "aipBase.h"
#include <string.h>
#include <iostream>
using namespace std;
//======================================================================
// Definition of static members
aipRand aipBase::m_rand; // random number generator
aipLogger * aipBase::m_logger = 0; // optional logger
//======================================================================
// Global functions
//
//----------------------------------------------------------------------
// strncpy that terminates the string, returns length
int aip_strncpy (char *dest, const char *src, int max_len) {
strncpy (dest, src, max_len);
dest[max_len] = '\0';
return strlen(dest);
}
//----------------------------------------------------------------------
// Get a string from string x and write it to val.
//
// One or more sequential delimiters starting at x are ignored.
// The string ends just before the terminating delimiter, and a
// pointer to this delimiter is returned (or zero on failure).
//
// If the specified delimiter is '~', any character other than
// a letter or digit will be a delimiter.
//
// The string will not be longer than maxlen (up to 100).
const char * aip_get_str (const char *x, long maxlen,
char *str, char delim) {
if (maxlen < 1) return 0;
if (maxlen > 100) maxlen = 100;
*str = '\0';
int slen = 0;
if (!x) return 0;
while (1) {
if ( aip_is_delim(*x,delim) ) {
if (!slen) {
x++;
continue; // skip over leading delimiters
} else {
break; // found end of string
}
}
if (slen < maxlen) {
*str++ = *x;
slen++;
}
x++;
}
*str = '\0';
if (!slen) return 0; // string was not found
return x; // last character read from x
}
//----------------------------------------------------------------------
// Get an long value from string x and write it to val.
//
// One or more sequential delimiters starting at x are ignored.
// The string ends just before the terminating delimiter, and a
// pointer to this delimiter is returned (or zero on failure).
//
// If the specified delimiter is '~', any character other than
// a letter or digit will be a delimiter.
const char * aip_get_val (const char *x, long maxlen,
long *val, char delim) {
char buf[21];
const char *last_char = aip_get_str (x, 20, buf, delim);
if (!last_char) return 0;
if (maxlen < 10) buf[maxlen] = '\0';
*val = atol(buf);
return last_char;
}
//----------------------------------------------------------------------
// Return true if x is a delimiter character. If delim is '~',
// any char other than a letter or digit is a delimiter.
int aip_is_delim (char x, char delim) {
if (delim == '~') {
if ( !( (x >= '0' && x <= '9') ||
(x >= 'A' && x <= 'Z') ||
(x >= 'a' && x <= 'z') ) ) return 1;
} else {
if (x == delim || x == '\0' || x == '\n') return 1;
}
return 0;
}
//======================================================================
// aipRand
//
//----------------------------------------------------------------------
// sub-random-number-generator -
// Return a pseudo-random number from the set [0,1,2,3,...,9999].
//
// This function can be used to implement 11 different sub-rngs -
// for each parameter, there is an array with 11 values. At any
// time, there are two sub-rngs - rand_1() calls this function
// and uses the first set of parameters; rand_2() calls this
// function and uses one of the remaining 10 sets of parameters.
//
// rand_1() and rand_2() produce low-quality random numbers;
// combining them produces a better quality of random numbers.
long aipRand::sub_rng (long idx) {
if (idx < 0) idx = 0;
if (idx >= Num_Sub_RNG) idx = Num_Sub_RNG - 1;
long a = Rand_a[idx];
long c = Rand_c[idx];
long m = 10000;
long x;
if (idx == 0) { // for rand_1()
x = m_rand_seed_1 = (a * m_rand_seed_1 + c) % m;
} else { // for rand_2()
x = m_rand_seed_2 = (a * m_rand_seed_2 + c) % m;
}
return x;
}
//----------------------------------------------------------------------
// first sub-RNG (that does not change)
long aipRand::rand_1 () {
return sub_rng(0);
}
//----------------------------------------------------------------------
// second sub-RNG (that changes periodically)
long aipRand::rand_2 () {
if (m_rand_2_idx < 1) m_rand_2_idx = 1;
if (m_rand_2_idx >= Num_Sub_RNG) m_rand_2_idx = Num_Sub_RNG - 1;
return sub_rng(m_rand_2_idx);
}
//----------------------------------------------------------------------
// return a pseudo-random number in the range 0 to 9999 inclusive
//
// Two low-quality random number are generated, with sub-RNGs
// rand_1() and rand_2(), and combined to make a better-quality
// random number.
//
// After this function is called a certain number of times,
// the following static members are changed:
// - which set of parameters, including the starting seed,
// used by rand_2() is randomly changed
// - number of calls until we do this again is randomly set
long aipRand::random_num () {
if (m_rand_2_idx < Rand_Null_Test) { // initial setup
m_rand_2_idx = 1;
m_rand_count = 500;
m_rand_seed_1 = Rand_s[0];
m_rand_seed_2 = Rand_s[m_rand_2_idx];
for (int i=0; i<100; i++) {
m_deck[i] = rand_1();
}
m_deck_len = 100;
}
if ( --m_rand_count <= 0 ) { // use different sub-RNG in rand_2()
m_rand_2_idx = (rand_1() * (Num_Sub_RNG-1)) / 10000 + 1;
m_rand_count = 300 + ( (rand_1()*500) / 10000 );
m_rand_seed_2 = Rand_s[m_rand_2_idx];
}
long j = rand_2() / 100;
long x = m_deck[j];
m_deck[j] = rand_1();
return x;
}
//======================================================================
// aipBase - return a pseudo-random number in the range 0 to 9999
//
//----------------------------------------------------------------------
// return a pseudo-random number in the range 0 to 9999
long aipBase::random_num () {
return m_rand.random_num ();
}
//----------------------------------------------------------------------
// return a pseudo-random number in the specified range
long aipBase::random_num (long lo, long hi) {
if (lo == hi) return lo;
if (lo > hi) { long temp_flip = lo; lo = hi; hi = temp_flip; }
if ( (hi-lo) > 100000 ) hi = lo + 100000 + 1;
long x = ( random_num() * ((hi-lo)+1) ) / 10000 + lo;
return x;
}
//----------------------------------------------------------------------
// Return true 1 in x times, otherwise return false.
int aipBase::is_one_chance_in_x (long x) {
if (x < 2) return 1;
if (x > 100000) return 0;
return (random_num(1,x)==1) ? 1 : 0;
}
//----------------------------------------------------------------------
// Write a character string to the log (generally for debugging)
void aipBase::log (const char *x) const {
if (m_logger) {
m_logger->log(x);
} else {
cout << x;
}
}
//----------------------------------------------------------------------
// Write a double to the log (generally for debugging)
void aipBase::log (double x) const {
if (m_logger) {
m_logger->log(x);
} else {
cout << x;
}
}
//----------------------------------------------------------------------
// Write a long to the log (generally for debugging)
void aipBase::log (long x) const {
if (m_logger) {
m_logger->log(x);
} else {
cout << x;
}
}
//======================================================================
// aipMsg
//
//----------------------------------------------------------------------
// Constructor
aipMsg::aipMsg(short t, short st, aipG g) { set(t, st, g); }
//----------------------------------------------------------------------
// Destructor
aipMsg::~aipMsg () {}
//----------------------------------------------------------------------
// set the goodness
void aipMsg::set (aipG g) { m_g = g; }
//----------------------------------------------------------------------
// set the private variables
void aipMsg::set (short t, short st, aipG g) {
m_typ = t;
m_subtyp = st;
m_g = g;
}
//======================================================================
// aipFileLogger - not tested
//
//----------------------------------------------------------------------
// Constructor
aipFileLogger::aipFileLogger (const char *file_name) {
m_stream = fopen (file_name, "w");
}
//----------------------------------------------------------------------
// Destructor
aipFileLogger::~aipFileLogger () {
if (m_stream) fclose(m_stream);
}
//----------------------------------------------------------------------
// is_valid
int aipFileLogger::is_valid () {
return (m_stream ? 1 : 0);
}
//----------------------------------------------------------------------
// write a string
void aipFileLogger::log (const char *x) {
if (!is_valid() || !x) return;
fprintf (m_stream, "%s", x);
}
//----------------------------------------------------------------------
// write a double value
void aipFileLogger::log (double x) {
if (!is_valid()) return;
fprintf (m_stream, "%f", x);
}
//----------------------------------------------------------------------
// write a long value
void aipFileLogger::log (long x) {
if (!is_valid()) return;
fprintf (m_stream, "%ld", x);
}
//======================================================================
// aipStringLogger
//
//----------------------------------------------------------------------
// Constructor
aipStringLogger::aipStringLogger (long max_len) {
if (max_len < 1 || max_len > 10000) { m_max_len = 0; return; }
m_str = new char[max_len+1];
if (!m_str) { m_max_len = 0; return; }
m_str_len = 0;
m_max_len = max_len;
}
//----------------------------------------------------------------------
// Destructor
aipStringLogger::~aipStringLogger () {
if (m_str) delete m_str;
}
//----------------------------------------------------------------------
// is_valid
int aipStringLogger::is_valid () {
return (m_max_len>0 ? 1 : 0);
}
//----------------------------------------------------------------------
// write a string
void aipStringLogger::log (const char *x) {
if (!is_valid() || !x || *x=='\0') return;
long max_wrt = m_max_len - m_str_len;
if (max_wrt <= 0) return;
long xlen = strlen(x);
if (xlen > max_wrt) xlen = max_wrt;
aip_strncpy (m_str+m_str_len, x, xlen); // add to end
m_str_len += xlen;
}
//----------------------------------------------------------------------
// write a double value
void aipStringLogger::log (double x) {
if (!is_valid()) return;
char buf[31];
sprintf (buf, "%f", x);
log(buf);
}
//----------------------------------------------------------------------
// write a long value
void aipStringLogger::log (long x) {
if (!is_valid()) return;
char buf[31];
sprintf (buf, "%ld", x);
log(buf);
}
//======================================================================
// License
//
// Permission is hereby granted, free of charge, to any
// person obtaining a copy of this software and associated
// documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to
// whom the Software is furnished to do so, subject to the
// following conditions:
//
// The copyright notice and this license shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
//
//**********************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -