Files
wagic/projects/mtg/src/utils.cpp
Xawotihs 3514476812 - Created a GamePhase type to ease debug.
- Modified the testsuite and gameobserver to be able to replay all the testcases based on the actions logged during the first pass. This allows to test the action logging and replay used during undo. It's only activated in multithreaded mode and it does not work on Momir tests.
-  Modified choice logging and replay to use menuId instead of ability index, as, for some obscur reasons related to Lord, those ability indexes may change.
- Fixed bug in nextphase logging wrongly generating click actions
- Added a "stack" zone to the click ability logging to be able to replay properly interrupt
- Fixed a wonderful bug mixing card names with zone names in the actions execution engine
- Added a "combatok" action logging/execution
- Added a "clone" virtual method to MTGCardInstance and Token to be able to clone correctly the right object type. Used that in MTGGameZones::removeCard
2011-11-29 21:50:16 +00:00

415 lines
8.6 KiB
C++

#include "PrecompiledHeader.h"
#include "utils.h"
#include "MTGDefinitions.h"
#include "Subtypes.h"
#include "WResourceManager.h"
#include "WFont.h"
#include <sys/stat.h>
#ifdef PSP
#include "pspsdk.h"
#endif
namespace wagic
{
#ifdef TRACK_FILE_USAGE_STATS
std::map<std::string, int> ifstream::sFileMap;
#endif
}
using std::vector;
using std::queue;
int RandomGenerator::random()
{
int result;
if (!loadedRandomValues.size() || !log)
{
result = rand();
}
else
{
result = loadedRandomValues.front();
loadedRandomValues.pop_front();
}
if(log)
usedRandomValues.push_back(result);
return result;
}
ostream& RandomGenerator::saveUsedRandValues(ostream& out) const
{
list<int>::const_iterator ite;
for(ite=usedRandomValues.begin(); ite != usedRandomValues.end(); ite++)
{
out << *ite << ",";
}
return out;
}
ostream& RandomGenerator::saveLoadedRandValues(ostream& out)
{
list<int>::iterator ite;
for(ite=loadedRandomValues.begin(); ite != loadedRandomValues.end(); ite++)
{
out << *ite << ",";
}
return out;
}
void RandomGenerator::loadRandValues(string s)
{
loadedRandomValues.clear();
usedRandomValues.clear();
while (s.size())
{
unsigned int value;
size_t limiter = s.find(",");
if (limiter != string::npos)
{
value = atoi(s.substr(0, limiter).c_str());
s = s.substr(limiter + 1);
}
else
{
value = atoi(s.c_str());
s = "";
}
if (value) loadedRandomValues.push_back(value);
}
}
int WRand(bool log)
{
return rand();
}
int filesize(const char * filename)
{
int file_size = 0;
#if defined (PSP)
int file = sceIoOpen(filename, PSP_O_RDONLY, 0777);
if (file > 0)
{
file_size = sceIoLseek(file, 0, PSP_SEEK_END);
sceIoClose(file);
}
#else
FILE * file = fopen(filename, "rb");
if (file != NULL)
{
fseek(file, 0, SEEK_END);
file_size = ftell(file);
fclose(file);
}
#endif
return file_size;
}
bool fileExists(const char * filename)
{
return JFileSystem::GetInstance()->FileExists(filename);
}
bool FileExists(const string & filename)
{
return JFileSystem::GetInstance()->FileExists(filename);
}
/*
#ifdef LINUX
#include <execinfo.h>
void dumpStack()
{
void* buffer[50];
int s = backtrace(buffer, 50);
char** tab = backtrace_symbols(buffer, s);
for (int i = 1; i < s; ++i) printf("%s\n", tab[i]);
printf("\n");
free(tab);
}
#endif
*/
/* RAM simple check functions source */
// *** FUNCTIONS ***
u32 ramAvailableLineareMax(void)
{
u32 size, sizeblock;
u8 *ram;
// Init variables
size = 0;
sizeblock = RAM_BLOCK;
#ifdef PSP
int disableInterrupts = pspSdkDisableInterrupts();
#endif
// Check loop
while (sizeblock)
{
// Increment size
size += sizeblock;
// Allocate ram
ram = (u8 *) malloc(size);
// Check allocate
if (!(ram))
{
// Restore old size
size -= sizeblock;
// Size block / 2
sizeblock >>= 1;
}
else
free(ram);
}
#ifdef PSP
pspSdkEnableInterrupts(disableInterrupts);
#endif
return size;
}
u32 ramAvailable(void)
{
u8 **ram, **temp;
u32 size, count, x;
// Init variables
ram = NULL;
size = 0;
count = 0;
#ifdef PSP
int disableInterrupts = pspSdkDisableInterrupts();
#endif
// Check loop
for (;;)
{
// Check size entries
if (!(count % 10))
{
// Allocate more entries if needed
temp = (u8**) realloc(ram, sizeof(u8 *) * (count + 10));
if (!(temp)) break;
// Update entries and size (size contains also size of entries)
ram = temp;
size += (sizeof(u8 *) * 10);
}
// Find max lineare size available
x = ramAvailableLineareMax();
if (!(x)) break;
// Allocate ram
ram[count] = (u8 *) malloc(x);
if (!(ram[count])) break;
// Update variables
size += x;
count++;
}
// Free ram
if (ram)
{
for (x = 0; x < count; x++)
free(ram[x]);
free(ram);
}
#ifdef PSP
pspSdkEnableInterrupts(disableInterrupts);
#endif
return size;
}
/* String manipulation functions */
string& trim(string& str)
{
str = ltrim(str);
str = rtrim(str);
return str;
}
string& ltrim(string& str)
{
str.erase(0, str.find_first_not_of(" \t"));
return str;
}
string& rtrim(string& str)
{
str.resize(str.find_last_not_of(" \t") + 1);
return str;
}
std::vector<std::string>& split(const std::string& s, char delim, std::vector<std::string>& elems)
{
std::stringstream ss(s);
std::string item;
while (std::getline(ss, item, delim))
{
elems.push_back(item);
}
return elems;
}
std::string join(vector<string>& v, string delim)
{
std::string retVal;
for ( vector<string>::iterator it = v.begin(); it != v.end(); ++it )
{
retVal.append( *it );
retVal.append( delim );
}
return retVal;
}
std::vector<std::string> split(const std::string& s, char delim)
{
std::vector<std::string> elems;
return split(s, delim, elems);
}
std::vector<std::string>& parseBetween(const std::string& s, string start, string stop, bool stopRequired, std::vector<std::string>& elems)
{
size_t found = s.find(start);
if (found == string::npos)
return elems;
size_t offset = found + start.size();
size_t end = s.find(stop, offset);
if (end == string::npos && stopRequired)
return elems;
elems.push_back(s.substr(0,found));
if (end != string::npos)
{
elems.push_back(s.substr(offset, end - offset));
elems.push_back(s.substr(end + 1));
}
else
{
elems.push_back(s.substr(offset));
elems.push_back("");
}
return elems;
}
std::vector<std::string> parseBetween(const std::string& s, string start, string stop, bool stopRequired)
{
std::vector<std::string> elems;
return parseBetween(s, start, stop, stopRequired, elems);
}
// This is a customized word wrap based on pixel width. It tries it's best
// to wrap strings using spaces as delimiters.
// Not sure how this translates into non-english fonts.
std::string wordWrap(const std::string& sentence, float width, int fontId)
{
WFont * mFont = WResourceManager::Instance()->GetWFont(fontId);
float lineWidth = mFont->GetStringWidth( sentence.c_str() );
string retVal = sentence;
if ( lineWidth < width ) return sentence;
int numLines = 1;
int breakIdx = 0;
for( size_t idx = 0; idx < sentence.length(); idx ++ )
{
if ( sentence[idx] == ' ' )
{
string currentSentence = sentence.substr(breakIdx, idx - breakIdx);
float stringLength = mFont->GetStringWidth( currentSentence.c_str() );
if (stringLength >= width)
{
if ( stringLength > width )
{
while ( sentence[idx-1] != ' ' )
idx--;
}
retVal[idx-1] = '\n';
breakIdx = idx;
numLines++;
}
}
else if ( sentence[idx] == '\n' )
{
string currentSentence = sentence.substr(breakIdx, idx - breakIdx);
float stringLength = mFont->GetStringWidth( currentSentence.c_str() );
if (stringLength >= width)
{
if ( stringLength > width )
{
while ( sentence[idx-1] != ' ' )
idx--;
retVal[idx-1] = '\n';
}
numLines++;
}
breakIdx = idx;
numLines++;
}
}
return retVal;
}
unsigned long hash_djb2(const char *str)
{
unsigned long hash = 5381;
int c;
while ((c = *str++))
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
return hash;
}
std::string buildFilePath(const vector<string> & folders, const string & filename)
{
string result = "";
for (size_t i = 0; i < folders.size(); ++i)
{
result.append(folders[i]);
if (result[result.length()-1] != '/')
{
result.append("/");
}
}
result.append(filename);
return result;
}
std::string ensureFolder(const std::string & folderName)
{
if (!folderName.size())
return "";
string result = folderName;
if (result[result.length()-1] != '/')
{
result.append("/");
}
return result;
}