Merge pull request #150 from timgame/DDRace64

tons of automapper feautures
This commit is contained in:
Dennis Felsing 2015-02-20 07:02:28 +01:00
commit ed73b733e6
4 changed files with 310 additions and 155 deletions

View file

@ -1856,6 +1856,19 @@ int str_format(char *buffer, int buffer_size, const char *format, ...)
return ret; return ret;
} }
char *str_trim_words(char *str, int words)
{
while (words && *str)
{
if (isspace(*str) && !isspace(*(str + 1)))
{
words--;
}
str++;
}
return str;
}
/* makes sure that the string only contains the characters between 32 and 127 */ /* makes sure that the string only contains the characters between 32 and 127 */

View file

@ -784,6 +784,22 @@ int str_length(const char *str);
*/ */
int str_format(char *buffer, int buffer_size, const char *format, ...); int str_format(char *buffer, int buffer_size, const char *format, ...);
/*
Function: str_trim_words
Trims specific number of words at the start of a string.
Parameters:
str - String to trim the words from.
words - Count of words to trim.
Returns:
Trimmed string
Remarks:
- The strings are treated as zero-termineted strings.
*/
char *str_trim_words(char *str, int words);
/* /*
Function: str_sanitize_strong Function: str_sanitize_strong
Replaces all characters below 32 and above 127 with whitespace. Replaces all characters below 32 and above 127 with whitespace.

View file

@ -25,6 +25,7 @@ void CAutoMapper::Load(const char* pTileName)
LineReader.Init(RulesFile); LineReader.Init(RulesFile);
CConfiguration *pCurrentConf = 0; CConfiguration *pCurrentConf = 0;
CRun *pCurrentRun = 0;
CIndexRule *pCurrentIndex = 0; CIndexRule *pCurrentIndex = 0;
char aBuf[256]; char aBuf[256];
@ -40,116 +41,208 @@ void CAutoMapper::Load(const char* pTileName)
{ {
// new configuration, get the name // new configuration, get the name
pLine++; pLine++;
CConfiguration NewConf; CConfiguration NewConf;
int ID = m_lConfigs.add(NewConf); int ConfigurationID = m_lConfigs.add(NewConf);
pCurrentConf = &m_lConfigs[ID]; pCurrentConf = &m_lConfigs[ConfigurationID];
str_copy(pCurrentConf->m_aName, pLine, str_length(pLine)); str_copy(pCurrentConf->m_aName, pLine, str_length(pLine));
// add start run
CRun NewRun;
int RunID = pCurrentConf->m_aRuns.add(NewRun);
pCurrentRun = &pCurrentConf->m_aRuns[RunID];
} }
else else if(!str_comp_num(pLine, "NewRun", 6))
{ {
if(!str_comp_num(pLine, "Index", 5)) // add new run
CRun NewRun;
int RunID = pCurrentConf->m_aRuns.add(NewRun);
pCurrentRun = &pCurrentConf->m_aRuns[RunID];
}
else if(!str_comp_num(pLine, "Index", 5))
{
// new index
int ID = 0;
char aOrientation1[128] = "";
char aOrientation2[128] = "";
char aOrientation3[128] = "";
sscanf(pLine, "Index %d %127s %127s %127s", &ID, aOrientation1, aOrientation2, aOrientation3);
CIndexRule NewIndexRule;
NewIndexRule.m_ID = ID;
NewIndexRule.m_Flag = 0;
NewIndexRule.m_RandomValue = 0;
NewIndexRule.m_DefaultRule = true;
if(str_length(aOrientation1) > 0)
{ {
// new index if(!str_comp(aOrientation1, "XFLIP"))
int ID = 0; NewIndexRule.m_Flag |= TILEFLAG_VFLIP;
char aOrientation1[128] = ""; else if(!str_comp(aOrientation1, "YFLIP"))
char aOrientation2[128] = ""; NewIndexRule.m_Flag |= TILEFLAG_HFLIP;
char aOrientation3[128] = ""; else if(!str_comp(aOrientation1, "ROTATE"))
NewIndexRule.m_Flag |= TILEFLAG_ROTATE;
sscanf(pLine, "Index %d %127s %127s %127s", &ID, aOrientation1, aOrientation2, aOrientation3);
CIndexRule NewIndexRule;
NewIndexRule.m_ID = ID;
NewIndexRule.m_Flag = 0;
NewIndexRule.m_RandomValue = 0;
NewIndexRule.m_DefaultRule = true;
if(str_length(aOrientation1) > 0)
{
if(!str_comp(aOrientation1, "XFLIP"))
NewIndexRule.m_Flag |= TILEFLAG_VFLIP;
else if(!str_comp(aOrientation1, "YFLIP"))
NewIndexRule.m_Flag |= TILEFLAG_HFLIP;
else if(!str_comp(aOrientation1, "ROTATE"))
NewIndexRule.m_Flag |= TILEFLAG_ROTATE;
}
if(str_length(aOrientation2) > 0)
{
if(!str_comp(aOrientation2, "XFLIP"))
NewIndexRule.m_Flag |= TILEFLAG_VFLIP;
else if(!str_comp(aOrientation2, "YFLIP"))
NewIndexRule.m_Flag |= TILEFLAG_HFLIP;
else if(!str_comp(aOrientation2, "ROTATE"))
NewIndexRule.m_Flag |= TILEFLAG_ROTATE;
}
if(str_length(aOrientation3) > 0)
{
if(!str_comp(aOrientation3, "XFLIP"))
NewIndexRule.m_Flag |= TILEFLAG_VFLIP;
else if(!str_comp(aOrientation3, "YFLIP"))
NewIndexRule.m_Flag |= TILEFLAG_HFLIP;
else if(!str_comp(aOrientation3, "ROTATE"))
NewIndexRule.m_Flag |= TILEFLAG_ROTATE;
}
// add the index rule object and make it current
int ArrayID = pCurrentConf->m_aIndexRules.add(NewIndexRule);
pCurrentIndex = &pCurrentConf->m_aIndexRules[ArrayID];
} }
else if(!str_comp_num(pLine, "Pos", 3) && pCurrentIndex)
if(str_length(aOrientation2) > 0)
{ {
int x = 0, y = 0; if(!str_comp(aOrientation2, "XFLIP"))
char aValue[128]; NewIndexRule.m_Flag |= TILEFLAG_VFLIP;
int Value = CPosRule::EMPTY; else if(!str_comp(aOrientation2, "YFLIP"))
bool IndexValue = false; NewIndexRule.m_Flag |= TILEFLAG_HFLIP;
else if(!str_comp(aOrientation2, "ROTATE"))
NewIndexRule.m_Flag |= TILEFLAG_ROTATE;
}
sscanf(pLine, "Pos %d %d %127s", &x, &y, aValue); if(str_length(aOrientation3) > 0)
{
if(!str_comp(aOrientation3, "XFLIP"))
NewIndexRule.m_Flag |= TILEFLAG_VFLIP;
else if(!str_comp(aOrientation3, "YFLIP"))
NewIndexRule.m_Flag |= TILEFLAG_HFLIP;
else if(!str_comp(aOrientation3, "ROTATE"))
NewIndexRule.m_Flag |= TILEFLAG_ROTATE;
}
if(!str_comp(aValue, "FULL")) // add the index rule object and make it current
Value = CPosRule::FULL; int IndexRuleID = pCurrentRun->m_aIndexRules.add(NewIndexRule);
else if(!str_comp_num(aValue, "INDEX", 5)) pCurrentIndex = &pCurrentRun->m_aIndexRules[IndexRuleID];
{ }
sscanf(pLine, "Pos %*d %*d INDEX %d", &Value); else if(!str_comp_num(pLine, "Pos", 3) && pCurrentIndex)
IndexValue = true; {
int x = 0, y = 0;
char aValue[128];
int Value = CPosRule::NORULE;
array<CIndexInfo> NewIndexList;
sscanf(pLine, "Pos %d %d %127s", &x, &y, aValue);
if(!str_comp(aValue, "EMPTY"))
{
Value = CPosRule::EMPTY;
}
else if(!str_comp(aValue, "FULL"))
{
Value = CPosRule::FULL;
}
else if(!str_comp(aValue, "INDEX") || !str_comp(aValue, "NOTINDEX"))
{
if(!str_comp(aValue, "INDEX"))
Value = CPosRule::INDEX;
else
Value = CPosRule::NOTINDEX;
int pWord = 4;
while(true) {
int ID = 0;
char aOrientation1[128] = "";
char aOrientation2[128] = "";
char aOrientation3[128] = "";
char aOrientation4[128] = "";
sscanf(str_trim_words(pLine, pWord), "%d %127s %127s %127s %127s", &ID, aOrientation1, aOrientation2, aOrientation3, aOrientation4);
CIndexInfo NewIndexInfo;
NewIndexInfo.m_ID = ID;
NewIndexInfo.m_Flag = 0;
if(!str_comp(aOrientation1, "OR")) {
NewIndexList.add(NewIndexInfo);
pWord += 2;
continue;
} else if(str_length(aOrientation1) > 0) {
if(!str_comp(aOrientation1, "XFLIP"))
NewIndexInfo.m_Flag |= TILEFLAG_VFLIP;
else if(!str_comp(aOrientation1, "YFLIP"))
NewIndexInfo.m_Flag |= TILEFLAG_HFLIP;
else if(!str_comp(aOrientation1, "ROTATE"))
NewIndexInfo.m_Flag |= TILEFLAG_ROTATE;
} else {
NewIndexList.add(NewIndexInfo);
break;
}
if(!str_comp(aOrientation2, "OR")) {
NewIndexList.add(NewIndexInfo);
pWord += 3;
continue;
} else if(str_length(aOrientation2) > 0) {
if(!str_comp(aOrientation2, "XFLIP"))
NewIndexInfo.m_Flag |= TILEFLAG_VFLIP;
else if(!str_comp(aOrientation2, "YFLIP"))
NewIndexInfo.m_Flag |= TILEFLAG_HFLIP;
else if(!str_comp(aOrientation2, "ROTATE"))
NewIndexInfo.m_Flag |= TILEFLAG_ROTATE;
} else {
NewIndexList.add(NewIndexInfo);
break;
}
if(!str_comp(aOrientation3, "OR")) {
NewIndexList.add(NewIndexInfo);
pWord += 4;
continue;
} else if(str_length(aOrientation3) > 0) {
if(!str_comp(aOrientation3, "XFLIP"))
NewIndexInfo.m_Flag |= TILEFLAG_VFLIP;
else if(!str_comp(aOrientation3, "YFLIP"))
NewIndexInfo.m_Flag |= TILEFLAG_HFLIP;
else if(!str_comp(aOrientation3, "ROTATE"))
NewIndexInfo.m_Flag |= TILEFLAG_ROTATE;
} else {
NewIndexList.add(NewIndexInfo);
break;
}
if(!str_comp(aOrientation4, "OR")) {
NewIndexList.add(NewIndexInfo);
pWord += 5;
continue;
} else {
NewIndexList.add(NewIndexInfo);
break;
}
} }
}
CPosRule NewPosRule = {x, y, Value, IndexValue}; if(Value != CPosRule::NORULE) {
CPosRule NewPosRule = {x, y, Value, NewIndexList};
pCurrentIndex->m_aRules.add(NewPosRule); pCurrentIndex->m_aRules.add(NewPosRule);
} }
else if(!str_comp_num(pLine, "Random", 6) && pCurrentIndex) }
{ else if(!str_comp_num(pLine, "Random", 6) && pCurrentIndex)
sscanf(pLine, "Random %d", &pCurrentIndex->m_RandomValue); {
} sscanf(pLine, "Random %d", &pCurrentIndex->m_RandomValue);
else if(!str_comp_num(pLine, "NoDefaultRule", 13) && pCurrentIndex) }
{ else if(!str_comp_num(pLine, "NoDefaultRule", 13) && pCurrentIndex)
pCurrentIndex->m_DefaultRule = false; {
} pCurrentIndex->m_DefaultRule = false;
} }
} }
} }
// add default rule for Pos 0 0 if there is none // add default rule for Pos 0 0 if there is none
for (int h = 0; h < m_lConfigs.size(); ++h) for (int g = 0; g < m_lConfigs.size(); ++g)
{ {
for(int i = 0; i < m_lConfigs[h].m_aIndexRules.size(); ++i) for (int h = 0; h < m_lConfigs[g].m_aRuns.size(); ++h)
{ {
bool Found = false; for(int i = 0; i < m_lConfigs[g].m_aRuns[h].m_aIndexRules.size(); ++i)
for(int j = 0; j < m_lConfigs[h].m_aIndexRules[i].m_aRules.size(); ++j)
{ {
CPosRule *pRule = &m_lConfigs[h].m_aIndexRules[i].m_aRules[j]; bool Found = false;
if(pRule && pRule->m_X == 0 && pRule->m_Y == 0) for(int j = 0; j < m_lConfigs[g].m_aRuns[h].m_aIndexRules[i].m_aRules.size(); ++j)
{ {
Found = true; CPosRule *pRule = &m_lConfigs[g].m_aRuns[h].m_aIndexRules[i].m_aRules[j];
break; if(pRule && pRule->m_X == 0 && pRule->m_Y == 0)
{
Found = true;
break;
}
}
if(!Found && m_lConfigs[g].m_aRuns[h].m_aIndexRules[i].m_DefaultRule)
{
array<CIndexInfo> NewIndexList;
CPosRule NewPosRule = {0, 0, CPosRule::FULL, NewIndexList};
m_lConfigs[g].m_aRuns[h].m_aIndexRules[i].m_aRules.add(NewPosRule);
} }
}
if(!Found && m_lConfigs[h].m_aIndexRules[i].m_DefaultRule)
{
CPosRule NewPosRule = {0, 0, CPosRule::FULL, false};
m_lConfigs[h].m_aIndexRules[i].m_aRules.add(NewPosRule);
} }
} }
} }
@ -177,74 +270,93 @@ void CAutoMapper::Proceed(CLayerTiles *pLayer, int ConfigID)
CConfiguration *pConf = &m_lConfigs[ConfigID]; CConfiguration *pConf = &m_lConfigs[ConfigID];
if(!pConf->m_aIndexRules.size()) // for every run: copy tiles, automap, overwrite tiles
return; for(int h = 0; h < pConf->m_aRuns.size(); ++h) {
CRun *pRun = &pConf->m_aRuns[h];
CLayerTiles newLayer(pLayer->m_Width, pLayer->m_Height);
CLayerTiles newLayer(pLayer->m_Width, pLayer->m_Height); // copy tiles
for(int y = 0; y < pLayer->m_Height; y++) {
for(int y = 0; y < pLayer->m_Height; y++) for(int x = 0; x < pLayer->m_Width; x++)
for(int x = 0; x < pLayer->m_Width; x++)
{
CTile *in = &pLayer->m_pTiles[y*pLayer->m_Width+x];
CTile *out = &newLayer.m_pTiles[y*pLayer->m_Width+x];
out->m_Index = in->m_Index;
out->m_Flags = in->m_Flags;
}
// auto map !
int MaxIndex = pLayer->m_Width*pLayer->m_Height;
for(int y = 0; y < pLayer->m_Height; y++)
for(int x = 0; x < pLayer->m_Width; x++)
{
CTile *pTile = &(newLayer.m_pTiles[y*pLayer->m_Width+x]);
m_pEditor->m_Map.m_Modified = true;
if(y == 0 || y == pLayer->m_Height-1 || x == 0 || x == pLayer->m_Width-1)
continue;
for(int i = 0; i < pConf->m_aIndexRules.size(); ++i)
{ {
bool RespectRules = true; CTile *in = &pLayer->m_pTiles[y*pLayer->m_Width+x];
for(int j = 0; j < pConf->m_aIndexRules[i].m_aRules.size() && RespectRules; ++j) CTile *out = &newLayer.m_pTiles[y*pLayer->m_Width+x];
{ out->m_Index = in->m_Index;
CPosRule *pRule = &pConf->m_aIndexRules[i].m_aRules[j]; out->m_Flags = in->m_Flags;
int CheckIndex = (y+pRule->m_Y)*pLayer->m_Width+(x+pRule->m_X);
if(CheckIndex < 0 || CheckIndex >= MaxIndex)
RespectRules = false;
else
{
if(pRule->m_IndexValue)
{
if(pLayer->m_pTiles[CheckIndex].m_Index != pRule->m_Value)
RespectRules = false;
}
else
{
if(pLayer->m_pTiles[CheckIndex].m_Index > 0 && pRule->m_Value == CPosRule::EMPTY)
RespectRules = false;
if(pLayer->m_pTiles[CheckIndex].m_Index == 0 && pRule->m_Value == CPosRule::FULL)
RespectRules = false;
}
}
}
if(RespectRules &&
(pConf->m_aIndexRules[i].m_RandomValue <= 1 || (int)((float)rand() / ((float)RAND_MAX + 1) * pConf->m_aIndexRules[i].m_RandomValue) == 1))
{
pTile->m_Index = pConf->m_aIndexRules[i].m_ID;
pTile->m_Flags = pConf->m_aIndexRules[i].m_Flag;
}
} }
} }
for(int y = 0; y < pLayer->m_Height; y++) // auto map
for(int x = 0; x < pLayer->m_Width; x++) int MaxIndex = pLayer->m_Width*pLayer->m_Height;
{ for(int y = 0; y < pLayer->m_Height; y++)
CTile *in = &newLayer.m_pTiles[y*pLayer->m_Width+x]; for(int x = 0; x < pLayer->m_Width; x++)
CTile *out = &pLayer->m_pTiles[y*pLayer->m_Width+x]; {
out->m_Index = in->m_Index; CTile *pTile = &(newLayer.m_pTiles[y*pLayer->m_Width+x]);
out->m_Flags = in->m_Flags; m_pEditor->m_Map.m_Modified = true;
for(int i = 0; i < pRun->m_aIndexRules.size(); ++i)
{
bool RespectRules = true;
for(int j = 0; j < pRun->m_aIndexRules[i].m_aRules.size() && RespectRules; ++j)
{
CPosRule *pRule = &pRun->m_aIndexRules[i].m_aRules[j];
int CheckIndex = (y+pRule->m_Y)*pLayer->m_Width+(x+pRule->m_X);
if(CheckIndex < 0 || CheckIndex >= MaxIndex)
RespectRules = false;
else
{
if(pRule->m_Value == CPosRule::EMPTY)
{
if(pLayer->m_pTiles[CheckIndex].m_Index > 0)
RespectRules = false;
}
else if(pRule->m_Value == CPosRule::FULL)
{
if(pLayer->m_pTiles[CheckIndex].m_Index == 0)
RespectRules = false;
}
else if(pRule->m_Value == CPosRule::INDEX)
{
bool PosRuleTest = false;
for(int i = 0; i < pRule->m_aIndexList.size(); ++i) {
if(pLayer->m_pTiles[CheckIndex].m_Index == pRule->m_aIndexList[i].m_ID && (!pRule->m_aIndexList[i].m_Flag || pLayer->m_pTiles[CheckIndex].m_Flags == pRule->m_aIndexList[i].m_Flag))
PosRuleTest = true;
}
if(!PosRuleTest)
RespectRules = false;
}
else if(pRule->m_Value == CPosRule::NOTINDEX)
{
bool PosRuleTest = true;
for(int i = 0; i < pRule->m_aIndexList.size(); ++i) {
if(pLayer->m_pTiles[CheckIndex].m_Index == pRule->m_aIndexList[i].m_ID && (!pRule->m_aIndexList[i].m_Flag || pLayer->m_pTiles[CheckIndex].m_Flags == pRule->m_aIndexList[i].m_Flag))
PosRuleTest = false;
}
if(!PosRuleTest)
RespectRules = false;
}
}
}
if(RespectRules &&
(pRun->m_aIndexRules[i].m_RandomValue <= 1 || (int)((float)rand() / ((float)RAND_MAX + 1) * pRun->m_aIndexRules[i].m_RandomValue) == 1))
{
pTile->m_Index = pRun->m_aIndexRules[i].m_ID;
pTile->m_Flags = pRun->m_aIndexRules[i].m_Flag;
}
}
}
// overwrite tiles
for(int y = 0; y < pLayer->m_Height; y++) {
for(int x = 0; x < pLayer->m_Width; x++)
{
CTile *in = &newLayer.m_pTiles[y*pLayer->m_Width+x];
CTile *out = &pLayer->m_pTiles[y*pLayer->m_Width+x];
out->m_Index = in->m_Index;
out->m_Flags = in->m_Flags;
}
} }
}
} }

View file

@ -5,17 +5,26 @@
class CAutoMapper class CAutoMapper
{ {
struct CIndexInfo
{
int m_ID;
int m_Flag;
};
struct CPosRule struct CPosRule
{ {
int m_X; int m_X;
int m_Y; int m_Y;
int m_Value; int m_Value;
bool m_IndexValue; array<CIndexInfo> m_aIndexList;
enum enum
{ {
EMPTY=0, NORULE=0,
FULL EMPTY,
FULL,
INDEX,
NOTINDEX
}; };
}; };
@ -28,9 +37,14 @@ class CAutoMapper
bool m_DefaultRule; bool m_DefaultRule;
}; };
struct CConfiguration struct CRun
{ {
array<CIndexRule> m_aIndexRules; array<CIndexRule> m_aIndexRules;
};
struct CConfiguration
{
array<CRun> m_aRuns;
char m_aName[128]; char m_aName[128];
}; };