From 665837d6563849cd223d7ba23b3c4c343cefac53 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Sat, 19 May 2012 16:22:34 +0000 Subject: [PATCH] - hopefully better town development for AI - fixed minimap blitting - fixed crash on attacking town without moat --- AI/VCAI/VCAI.cpp | 119 ++++++++++++++++++++++---- AI/VCAI/VCAI.h | 9 ++ client/CAdvmapInterface.cpp | 32 +++---- client/CBitmapHandler.cpp | 2 +- client/CDefHandler.cpp | 2 +- client/Graphics.cpp | 7 +- client/UIFramework/SDL_Extensions.cpp | 13 ++- client/UIFramework/SDL_Extensions.h | 2 +- client/UIFramework/SDL_Pixels.h | 22 ++--- lib/IGameCallback.cpp | 10 +-- 10 files changed, 154 insertions(+), 64 deletions(-) diff --git a/AI/VCAI/VCAI.cpp b/AI/VCAI/VCAI.cpp index 23e1d5303..6ace5a004 100644 --- a/AI/VCAI/VCAI.cpp +++ b/AI/VCAI/VCAI.cpp @@ -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 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 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 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(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(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(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(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(goldSource, goldSource + ARRAY_COUNT(goldSource)))) + return; + if (tryBuildNextStructure(t, std::vector(spells, spells + ARRAY_COUNT(spells)))) + return; + if (tryBuildNextStructure(t, std::vector(extra, extra + ARRAY_COUNT(extra)))) + return; } bool isSafeToVisit(const CGHeroInstance *h, crint3 tile) diff --git a/AI/VCAI/VCAI.h b/AI/VCAI/VCAI.h index 22f3ff02b..740957330 100644 --- a/AI/VCAI/VCAI.h +++ b/AI/VCAI/VCAI.h @@ -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 buildList, unsigned int maxDays=0); + //try build first unbuilt structure + bool tryBuildNextStructure(const CGTownInstance * t, std::vector buildList, unsigned int maxDays=0); + public: friend class FuzzyHelper; diff --git a/client/CAdvmapInterface.cpp b/client/CAdvmapInterface.cpp index 4fce0824b..2b39616a8 100644 --- a/client/CAdvmapInterface.cpp +++ b/client/CAdvmapInterface.cpp @@ -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; gminimap.pos; std::map &colors = adventureInt->minimap.colors; std::map &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; gminimap.pos; - int3 mapSizes = LOCPLINT->cb->getMapSize(); int mw = map_[0]->w, mh = map_[0]->h; for(int d=0; dmh->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; jjtempOwner == 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; jjpos.w) && (pos.y*ho+jjpos.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); } } } diff --git a/client/CBitmapHandler.cpp b/client/CBitmapHandler.cpp index 4136a20e8..58be8b899 100644 --- a/client/CBitmapHandler.cpp +++ b/client/CBitmapHandler.cpp @@ -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; } } diff --git a/client/CDefHandler.cpp b/client/CDefHandler.cpp index 82b9e5631..055b3d547 100644 --- a/client/CDefHandler.cpp +++ b/client/CDefHandler.cpp @@ -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 diff --git a/client/Graphics.cpp b/client/Graphics.cpp index 9bcfd5f9a..37858e057 100644 --- a/client/Graphics.cpp +++ b/client/Graphics.cpp @@ -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()) { diff --git a/client/UIFramework/SDL_Extensions.cpp b/client/UIFramework/SDL_Extensions.cpp index aaef01906..f7fe27499 100644 --- a/client/UIFramework/SDL_Extensions.cpp +++ b/client/UIFramework/SDL_Extensions.cpp @@ -45,7 +45,7 @@ SDL_Surface * CSDL_Ext::createSurfaceWithBpp(int width, int height) Channels::px::b.set((Uint8*)&bMask, 255); Channels::px::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*/) diff --git a/client/UIFramework/SDL_Extensions.h b/client/UIFramework/SDL_Extensions.h index e02e717ad..f9b1103c5 100644 --- a/client/UIFramework/SDL_Extensions.h +++ b/client/UIFramework/SDL_Extensions.h @@ -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); diff --git a/client/UIFramework/SDL_Pixels.h b/client/UIFramework/SDL_Pixels.h index 1848f6125..28240163a 100644 --- a/client/UIFramework/SDL_Pixels.h +++ b/client/UIFramework/SDL_Pixels.h @@ -147,10 +147,10 @@ STRONG_INLINE void ColorPutter::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::PutColorAlphaSwitch(Uint8 *&p template STRONG_INLINE void ColorPutter::PutColor(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B, const Uint8 & A) { - PutColor(ptr, ((((Uint32)Channels::px::r.get(ptr)-(Uint32)R)*(Uint32)A) >> 8 ) + (Uint32)R, - ((((Uint32)Channels::px::g.get(ptr)-(Uint32)G)*(Uint32)A) >> 8 ) + (Uint32)G, - ((((Uint32)Channels::px::b.get(ptr)-(Uint32)B)*(Uint32)A) >> 8 ) + (Uint32)B); + PutColor(ptr, ((((Uint32)R - (Uint32)Channels::px::r.get(ptr))*(Uint32)A) >> 8 ) + (Uint32)Channels::px::r.get(ptr), + ((((Uint32)G - (Uint32)Channels::px::g.get(ptr))*(Uint32)A) >> 8 ) + (Uint32)Channels::px::g.get(ptr), + ((((Uint32)B - (Uint32)Channels::px::b.get(ptr))*(Uint32)A) >> 8 ) + (Uint32)Channels::px::b.get(ptr)); } @@ -185,7 +185,7 @@ STRONG_INLINE void ColorPutter::PutColor(Uint8 *&ptr, const U Channels::px::r.set(ptr, R); Channels::px::g.set(ptr, G); Channels::px::b.set(ptr, B); - Channels::px::a.set(ptr, 0); + Channels::px::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 diff --git a/lib/IGameCallback.cpp b/lib/IGameCallback.cpp index a91a7a3b1..e31f65deb 100644 --- a/lib/IGameCallback.cpp +++ b/lib/IGameCallback.cpp @@ -418,10 +418,9 @@ shared_ptr CBattleInfoCallback::battleGetObstacleOnPos( if(!gs->curB) return NULL; - - auto ptr = gs->curB->obstacles.front(); - shared_ptr nastala = ptr; - + //unused? causes crash in forts without moat + //auto ptr = gs->curB->obstacles.front(); + //shared_ptr nastala = ptr; BOOST_FOREACH(auto &obs, battleGetAllObstacles()) { @@ -431,9 +430,6 @@ shared_ptr CBattleInfoCallback::battleGetObstacleOnPos( return obs; } } - - - return NULL; }