1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-24 08:32:34 +02:00

- hopefully better town development for AI

- fixed minimap blitting
- fixed crash on attacking town without moat
This commit is contained in:
Ivan Savenko 2012-05-19 16:22:34 +00:00
parent 6f6cd6814e
commit 665837d656
10 changed files with 154 additions and 64 deletions

View File

@ -1100,42 +1100,129 @@ void VCAI::recruitCreatures(const CGDwelling * d)
}
}
void VCAI::buildStructure(const CGTownInstance * t)
bool VCAI::tryBuildStructure(const CGTownInstance * t, int building, unsigned int maxDays)
{
//TODO make *real* town development system
const int buildings[] = {5, 11, 14, 16, 0, 12, 7, 8, 9, 13, 30, 31, 32, 33, 34, 35, 36, 37, 38,
39, 40, 41, 42, 43, 1, 2, 3, 4, 17, 18, 19, 21, 22, 23};
for(int i = 0; i < ARRAY_COUNT(buildings); i++)
if (t->hasBuilt(building)) //Already built? Shouldn't happen in general
return true;
std::set<int> toBuild = cb->getBuildingRequiments(t, building);
toBuild.insert(building);
if (maxDays && toBuild.size() > maxDays)
return false;
TResources currentRes = cb->getResourceAmount();
TResources income = estimateIncome();
//TODO: calculate if we have enough resources to build it in maxDays
BOOST_FOREACH(int buildID, toBuild)
{
if(t->hasBuilt(buildings[i]))
continue;
const CBuilding *b = VLC->buildh->buildings[t->subID][buildID];
const CBuilding *b = VLC->buildh->buildings[t->subID][buildings[i]];
int canBuild = cb->canBuildStructure(t, buildings[i]);
int canBuild = cb->canBuildStructure(t, buildID);
if(canBuild == EBuildingState::ALLOWED)
{
if(!containsSavedRes(b->resources))
{
BNLOG("Player %d will build %s in town of %s at %s", playerID % b->Name() % t->name % t->pos);
cb->buildBuilding(t, buildings[i]);
cb->buildBuilding(t, buildID);
return true;
}
break;
continue;
}
else if(canBuild == EBuildingState::NO_RESOURCES)
{
TResources mine = cb->getResourceAmount(), cost = VLC->buildh->buildings[t->subID][buildings[i]]->resources,
income = estimateIncome();
TResources cost = VLC->buildh->buildings[t->subID][buildID]->resources;
for (int i = 0; i < GameConstants::RESOURCE_QUANTITY; i++)
{
int diff = mine[i] - cost[i] + income[i];
int diff = currentRes[i] - cost[i] + income[i];
if(diff < 0)
saving[i] = 1;
}
continue;
}
}
return false;
}
bool VCAI::tryBuildAnyStructure(const CGTownInstance * t, std::vector<int> buildList, unsigned int maxDays)
{
BOOST_FOREACH(int building, buildList)
{
if(t->hasBuilt(building))
continue;
if (tryBuildStructure(t, building, maxDays))
return true;
}
return false; //Can't build anything
}
bool VCAI::tryBuildNextStructure(const CGTownInstance * t, std::vector<int> buildList, unsigned int maxDays)
{
BOOST_FOREACH(int building, buildList)
{
if(t->hasBuilt(building))
continue;
return tryBuildStructure(t, building, maxDays);
}
return false;//Nothing to build
}
void VCAI::buildStructure(const CGTownInstance * t)
{
using namespace EBuilding;
//TODO make *real* town development system
//TODO: faction-specific development
//TODO: build resource silo, defences when needed
//Set of buildings for different goals. Does not include any prerequisites.
const int essential[] = {TAVERN, TOWN_HALL};
const int goldSource[] = {TOWN_HALL, CITY_HALL, CAPITOL};
const int unitsSource[] = { 30, 31, 32, 33, 34, 35, 36};
const int unitsUpgrade[] = { 37, 38, 39, 40, 41, 42, 43};
const int unitGrowth[] = { FORT, CITADEL, CASTLE, HORDE_1, HORDE_1_UPGR, HORDE_2, HORDE_2_UPGR};
const int spells[] = {MAGES_GUILD_1, MAGES_GUILD_2, MAGES_GUILD_3, MAGES_GUILD_4, MAGES_GUILD_5};
const int extra[] = {RESOURCE_SILO, SPECIAL_1, SPECIAL_2, SPECIAL_3, SPECIAL_4, SHIPYARD}; // all remaining buildings
TResources currentRes = cb->getResourceAmount();
TResources income = estimateIncome();
if (tryBuildAnyStructure(t, std::vector<int>(essential, essential + ARRAY_COUNT(essential))))
return;
//we're running out of gold - try to build something gold-producing. Minimal amount can be tweaked
if (currentRes[Res::GOLD] + income[Res::GOLD] < 5000)
if (tryBuildNextStructure(t, std::vector<int>(goldSource, goldSource + ARRAY_COUNT(goldSource))))
return;
if (cb->getDate(1) > 6)// last 2 days of week - try to focus on growth
{
if (tryBuildNextStructure(t, std::vector<int>(unitGrowth, unitGrowth + ARRAY_COUNT(unitGrowth)), 2))
return;
}
// first in-game week or second half of any week: try build dwellings
if (cb->getDate(0) < 7 || cb->getDate(1) > 3)
if (tryBuildAnyStructure(t, std::vector<int>(unitsSource, unitsSource + ARRAY_COUNT(unitsSource)), 8 - cb->getDate(1)))
return;
//try to upgrade dwelling
for(int i = 0; i < ARRAY_COUNT(unitsUpgrade); i++)
{
if (t->hasBuilt(unitsSource[i]))
{
if (tryBuildStructure(t, unitsUpgrade[i]))
return;
}
}
//remaining tasks
if (tryBuildNextStructure(t, std::vector<int>(goldSource, goldSource + ARRAY_COUNT(goldSource))))
return;
if (tryBuildNextStructure(t, std::vector<int>(spells, spells + ARRAY_COUNT(spells))))
return;
if (tryBuildNextStructure(t, std::vector<int>(extra, extra + ARRAY_COUNT(extra))))
return;
}
bool isSafeToVisit(const CGHeroInstance *h, crint3 tile)

View File

@ -174,6 +174,15 @@ private:
class VCAI : public CAdventureAI
{
//internal methods for town development
//try build an unbuilt structure in maxDays at most (0 = indefinite)
bool tryBuildStructure(const CGTownInstance * t, int building, unsigned int maxDays=0);
//try build ANY unbuilt structure
bool tryBuildAnyStructure(const CGTownInstance * t, std::vector<int> buildList, unsigned int maxDays=0);
//try build first unbuilt structure
bool tryBuildNextStructure(const CGTownInstance * t, std::vector<int> buildList, unsigned int maxDays=0);
public:
friend class FuzzyHelper;

View File

@ -65,7 +65,7 @@ CMinimap::CMinimap()
pos.h=ADVOPT.minimapW;
pos.w=ADVOPT.minimapH;
temps = newSurface(pos.w,pos.h);
temps = CSDL_Ext::createSurfaceWithBpp<3>(pos.w,pos.h);
aiShield = new CPicture("AISHIELD.bmp");
const JsonNode config(GameConstants::DATA_DIR + "/config/minimap.json");
@ -177,11 +177,6 @@ void CMinimapSurfacesRef::redraw(int level)
void CMinimapSurfacesRef::initMap(int level)
{
/*for(int g=0; g<map.size(); ++g)
{
SDL_FreeSurface(map[g]);
}
map.clear();*/
const Rect &minimap_pos = adventureInt->minimap.pos;
std::map<int,SDL_Color> &colors = adventureInt->minimap.colors;
std::map<int,SDL_Color> &colorsBlocked = adventureInt->minimap.colorsBlocked;
@ -205,7 +200,8 @@ void CMinimapSurfacesRef::initMap(int level)
{
if (tile->blocked && (!tile->visitable))
SDL_PutPixelWithoutRefresh(pom, x, y, colorsBlocked[tile->tertype].r, colorsBlocked[tile->tertype].g, colorsBlocked[tile->tertype].b);
else SDL_PutPixelWithoutRefresh(pom, x, y, colors[tile->tertype].r, colors[tile->tertype].g, colors[tile->tertype].b);
else
SDL_PutPixelWithoutRefresh(pom, x, y, colors[tile->tertype].r, colors[tile->tertype].g, colors[tile->tertype].b);
}
}
}
@ -232,7 +228,7 @@ void CMinimapSurfacesRef::initFoW(int level)
int3 pp( ((i*mapSizes.x)/mw), ((j*mapSizes.y)/mh), d );
if ( !LOCPLINT->cb->isVisible(pp) )
{
CSDL_Ext::SDL_PutPixelWithoutRefresh(pt,i,j,0,0,0);
CSDL_Ext::SDL_PutPixelWithoutRefresh(pt,i,j,0,0,0,0);
}
}
}
@ -242,14 +238,7 @@ void CMinimapSurfacesRef::initFoW(int level)
void CMinimapSurfacesRef::initFlaggableObjs(int level)
{
/*for(int g=0; g<flObjs.size(); ++g)
{
SDL_FreeSurface(flObjs[g]);
}
flObjs.clear();*/
const Rect &minimap_pos = adventureInt->minimap.pos;
int3 mapSizes = LOCPLINT->cb->getMapSize();
int mw = map_[0]->w, mh = map_[0]->h;
for(int d=0; d<CGI->mh->map->twoLevel+1; ++d)
{
@ -378,7 +367,8 @@ void CMinimap::showTile(const int3 &pos)
{
if (tile->blocked && (!tile->visitable))
SDL_PutPixelWithoutRefresh(surfs[player].map()[pos.z], pos.x*wo+ii, pos.y*ho+jj, colorsBlocked[tile->tertype].r, colorsBlocked[tile->tertype].g, colorsBlocked[tile->tertype].b);
else SDL_PutPixelWithoutRefresh(surfs[player].map()[pos.z], pos.x*wo+ii, pos.y*ho+jj, colors[tile->tertype].r, colors[tile->tertype].g, colors[tile->tertype].b);
else
SDL_PutPixelWithoutRefresh(surfs[player].map()[pos.z], pos.x*wo+ii, pos.y*ho+jj, colors[tile->tertype].r, colors[tile->tertype].g, colors[tile->tertype].b);
}
}
}
@ -421,11 +411,11 @@ void CMinimap::showTile(const int3 &pos)
for (int jj=0; jj<hoShifted; jj++)
{
if(oo[v]->tempOwner == 255)
SDL_PutPixelWithoutRefresh(flObjs[pos.z],maplgp.x+ii,maplgp.y+jj,graphics->neutralColor->b,
graphics->neutralColor->g,graphics->neutralColor->r);
SDL_PutPixelWithoutRefresh(flObjs[pos.z],maplgp.x+ii,maplgp.y+jj,graphics->neutralColor->r,
graphics->neutralColor->g,graphics->neutralColor->b);
else
SDL_PutPixelWithoutRefresh(flObjs[pos.z],maplgp.x+ii,maplgp.y+jj,graphics->playerColors[oo[v]->getOwner()].b,
graphics->playerColors[oo[v]->getOwner()].g,graphics->playerColors[oo[v]->getOwner()].r);
SDL_PutPixelWithoutRefresh(flObjs[pos.z],maplgp.x+ii,maplgp.y+jj,graphics->playerColors[oo[v]->getOwner()].r,
graphics->playerColors[oo[v]->getOwner()].g,graphics->playerColors[oo[v]->getOwner()].b);
}
}
}
@ -467,7 +457,7 @@ void CMinimap::hideTile(const int3 &pos)
for (int jj=0; jj<ho; jj++)
{
if ((pos.x*wo+ii<this->pos.w) && (pos.y*ho+jj<this->pos.h))
CSDL_Ext::SDL_PutPixelWithoutRefresh(FoW[pos.z],pos.x*wo+ii,pos.y*ho+jj,0,0,0,0);
CSDL_Ext::SDL_PutPixelWithoutRefresh(FoW[pos.z],pos.x*wo+ii,pos.y*ho+jj,0,0,0,255);
}
}
}

View File

@ -84,7 +84,7 @@ SDL_Surface * CPCXConv::getSurface() const
tp.r = pcx[it++];
tp.g = pcx[it++];
tp.b = pcx[it++];
tp.unused = 0;
tp.unused = 255;
ret->format->palette->colors[i] = tp;
}
}

View File

@ -68,7 +68,7 @@ void CDefHandler::openFromMemory(ui8 *table, const std::string & name)
palette[it].R = de.palette[it].R;
palette[it].G = de.palette[it].G;
palette[it].B = de.palette[it].B;
palette[it].F = 0;
palette[it].F = 255;
}
// The SDefEntryBlock starts just after the SDefEntry

View File

@ -171,7 +171,7 @@ void Graphics::loadPaletteAndColors()
col.r = pals[startPoint++];
col.g = pals[startPoint++];
col.b = pals[startPoint++];
col.unused = pals[startPoint++];
col.unused = !pals[startPoint++];
playerColorPalette[i] = col;
}
@ -185,6 +185,7 @@ void Graphics::loadPaletteAndColors()
ncp.read((char*)&neutralColorPalette[i].g,1);
ncp.read((char*)&neutralColorPalette[i].b,1);
ncp.read((char*)&neutralColorPalette[i].unused,1);
neutralColorPalette[i].unused = !neutralColorPalette[i].unused;
}
@ -196,9 +197,9 @@ void Graphics::loadPaletteAndColors()
playerColors[i].r = kolory[i].x;
playerColors[i].g = kolory[i].y;
playerColors[i].b = kolory[i].z;
playerColors[i].unused = 0;
playerColors[i].unused = 255;
}
neutralColor->r = 0x84; neutralColor->g = 0x84; neutralColor->b = 0x84; neutralColor->unused = 0x0;//gray
neutralColor->r = 0x84; neutralColor->g = 0x84; neutralColor->b = 0x84; neutralColor->unused = 255;//gray
const JsonNode config(GameConstants::DATA_DIR + "/config/town_pictures.json");
BOOST_FOREACH(const JsonNode &p, config["town_pictures"].Vector()) {

View File

@ -45,7 +45,7 @@ SDL_Surface * CSDL_Ext::createSurfaceWithBpp(int width, int height)
Channels::px<bpp>::b.set((Uint8*)&bMask, 255);
Channels::px<bpp>::a.set((Uint8*)&aMask, 255);
return SDL_CreateRGBSurface( SDL_SWSURFACE | SDL_SRCALPHA, width, height, bpp * 8, rMask, gMask, bMask, aMask);
return SDL_CreateRGBSurface( SDL_SWSURFACE, width, height, bpp * 8, rMask, gMask, bMask, aMask);
}
bool isItIn(const SDL_Rect * rect, int x, int y)
@ -504,7 +504,7 @@ void CSDL_Ext::alphaTransform(SDL_Surface *src)
{
//NOTE: colors #7 & #8 used in some of WoG objects. Don't know how they're handled by H3
assert(src->format->BitsPerPixel == 8);
SDL_Color colors[] = {{0,0,0,255}, {0,0,0,214}, {0,0,0,164}, {0,0,0,82}, {0,0,0,128},
SDL_Color colors[] = {{0,0,0,0}, {0,0,0,32}, {0,0,0,64}, {0,0,0,128}, {0,0,0,128},
{255,255,255,0}, {255,255,255,0}, {255,255,255,0}, {0,0,0,192}, {0,0,0,192}};
SDL_SetColors(src, colors, 0, ARRAY_COUNT(colors));
@ -934,7 +934,7 @@ const TColorPutterAlpha CSDL_Ext::getPutterAlphaFor(SDL_Surface * const &dest, i
#undef CASE_BPP
}
Uint8 * CSDL_Ext::getPxPtr(const SDL_Surface * const &srf, const int & x, const int & y)
Uint8 * CSDL_Ext::getPxPtr(const SDL_Surface * const &srf, const int x, const int y)
{
return (Uint8 *)srf->pixels + y * srf->pitch + x * srf->format->BytesPerPixel;
}
@ -984,6 +984,13 @@ void CSDL_Ext::SDL_PutPixelWithoutRefresh(SDL_Surface *ekran, const int & x, con
{
Uint8 *p = getPxPtr(ekran, x, y);
getPutterFor(ekran, false)(p, R, G, B);
switch(ekran->format->BytesPerPixel)
{
case 2: Channels::px<2>::a.set(p, A); break;
case 3: Channels::px<3>::a.set(p, A); break;
case 4: Channels::px<4>::a.set(p, A); break;
}
}
void CSDL_Ext::SDL_PutPixelWithoutRefreshIfInSurf(SDL_Surface *ekran, const int & x, const int & y, const Uint8 & R, const Uint8 & G, const Uint8 & B, Uint8 A /*= 255*/)

View File

@ -132,7 +132,7 @@ namespace CSDL_Ext
bool isTransparent(SDL_Surface * srf, int x, int y); //checks if surface is transparent at given position
Uint8 *getPxPtr(const SDL_Surface * const &srf, const int & x, const int & y);
Uint8 *getPxPtr(const SDL_Surface * const &srf, const int x, const int y);
const TColorPutter getPutterFor(SDL_Surface * const &dest, int incrementing); //incrementing: -1, 0, 1
const TColorPutterAlpha getPutterAlphaFor(SDL_Surface * const &dest, int incrementing); //incrementing: -1, 0, 1
BlitterWithRotationVal getBlitterWithRotation(SDL_Surface *dest);

View File

@ -147,10 +147,10 @@ STRONG_INLINE void ColorPutter<bpp, incrementPtr>::PutColorAlphaSwitch(Uint8 *&p
{
switch (A)
{
case 255:
case 0:
ptr += bpp * incrementPtr;
return;
case 0:
case 255:
PutColor(ptr, R, G, B);
return;
case 128: // optimized
@ -168,9 +168,9 @@ STRONG_INLINE void ColorPutter<bpp, incrementPtr>::PutColorAlphaSwitch(Uint8 *&p
template<int bpp, int incrementPtr>
STRONG_INLINE void ColorPutter<bpp, incrementPtr>::PutColor(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B, const Uint8 & A)
{
PutColor(ptr, ((((Uint32)Channels::px<bpp>::r.get(ptr)-(Uint32)R)*(Uint32)A) >> 8 ) + (Uint32)R,
((((Uint32)Channels::px<bpp>::g.get(ptr)-(Uint32)G)*(Uint32)A) >> 8 ) + (Uint32)G,
((((Uint32)Channels::px<bpp>::b.get(ptr)-(Uint32)B)*(Uint32)A) >> 8 ) + (Uint32)B);
PutColor(ptr, ((((Uint32)R - (Uint32)Channels::px<bpp>::r.get(ptr))*(Uint32)A) >> 8 ) + (Uint32)Channels::px<bpp>::r.get(ptr),
((((Uint32)G - (Uint32)Channels::px<bpp>::g.get(ptr))*(Uint32)A) >> 8 ) + (Uint32)Channels::px<bpp>::g.get(ptr),
((((Uint32)B - (Uint32)Channels::px<bpp>::b.get(ptr))*(Uint32)A) >> 8 ) + (Uint32)Channels::px<bpp>::b.get(ptr));
}
@ -185,7 +185,7 @@ STRONG_INLINE void ColorPutter<bpp, incrementPtr>::PutColor(Uint8 *&ptr, const U
Channels::px<bpp>::r.set(ptr, R);
Channels::px<bpp>::g.set(ptr, G);
Channels::px<bpp>::b.set(ptr, B);
Channels::px<bpp>::a.set(ptr, 0);
Channels::px<bpp>::a.set(ptr, 255);
if (incrementPtr > 0)
ptr += bpp;
@ -226,10 +226,10 @@ STRONG_INLINE void ColorPutter<2, incrementPtr>::PutColorAlphaSwitch(Uint8 *&ptr
{
switch (A)
{
case 255:
case 0:
ptr += 2 * incrementPtr;
return;
case 0:
case 255:
PutColor(ptr, R, G, B);
return;
default:
@ -254,9 +254,9 @@ STRONG_INLINE void ColorPutter<2, incrementPtr>::PutColor(Uint8 *&ptr, const Uin
b8 = (b5 << (8 - bbit)) | (b5 >> (2*bbit - 8));
PutColor(ptr,
(((r8-R)*A) >> 8) + R,
(((g8-G)*A) >> 8) + G,
(((b8-B)*A) >> 8) + B);
(((R-r8)*A) >> 8) + r8,
(((G-g8)*A) >> 8) + g8,
(((B-b8)*A) >> 8) + b8);
}
template <int incrementPtr>

View File

@ -418,10 +418,9 @@ shared_ptr<const CObstacleInstance> CBattleInfoCallback::battleGetObstacleOnPos(
if(!gs->curB)
return NULL;
auto ptr = gs->curB->obstacles.front();
shared_ptr<const CObstacleInstance> nastala = ptr;
//unused? causes crash in forts without moat
//auto ptr = gs->curB->obstacles.front();
//shared_ptr<const CObstacleInstance> nastala = ptr;
BOOST_FOREACH(auto &obs, battleGetAllObstacles())
{
@ -431,9 +430,6 @@ shared_ptr<const CObstacleInstance> CBattleInfoCallback::battleGetObstacleOnPos(
return obs;
}
}
return NULL;
}