> I tried adding my saved game to Savannah bug 19542, but Savannah
> wouldn't allow this because the file size is 689 K which exceeds
> Savannah's limit of 512 K.  I'm happy to e-mail it to anyone who wants
> to look at it.

Try to compress it.

I now have an save game where only AIs play which crashes in cvs.
A similar game does not crash AIs in the version from last month.
I'm now very confident that this bug was introduced by the patch
that I talked about yesterday.  Fixing it should be as simple as
reverting every part of that new "forbiddenzone around buildings"
feature in recent cvs and checking that no other patches rely on
it.

I attach the complete diff:

diff -r e5dccad7dfcb -r 3abde68dab1a src/AIEcho.cpp
--- a/src/AIEcho.cpp    Sat Mar 24 00:26:38 2007 +0000
+++ b/src/AIEcho.cpp    Sat Mar 24 01:37:03 2007 +0000
@@ -1428,7 +1428,7 @@ position BuildingOrder::find_location(Ec
                                        for(int y2=0; y2<type->height && 
passes; ++y2)
                                                if((x2==0 || y2==0 || 
x2==type->width-1 || y2==type->height-1))
                                                {
-                                                       
if(!(*i)->passes_constraint(echo, x+x2, y+y2))
+                                                       
if(!(*i)->passes_constraint(echo, map->normalizeX(x+x2), map->normalizeY(y+y2)))
                                                        {
                                                                        
passes=false;
                                                        }
@@ -1445,10 +1445,10 @@ position BuildingOrder::find_location(Ec
                                        passes=false;
                                        break;
                                }
-                               score+=(*i)->calculate_constraint(echo, x, y);
-                               score+=(*i)->calculate_constraint(echo, 
x+type->width-1, y+type->height-1);
-                               score+=(*i)->calculate_constraint(echo, x, 
y+type->height-1);
-                               score+=(*i)->calculate_constraint(echo, 
x+type->width-1, y);
+                               score+=(*i)->calculate_constraint(echo, 
map->normalizeX(x), map->normalizeY(y));
+                               score+=(*i)->calculate_constraint(echo, 
map->normalizeX(x+type->width-1), map->normalizeY(y+type->height-1));
+                               score+=(*i)->calculate_constraint(echo, 
map->normalizeX(x), map->normalizeY(y+type->height-1));
+                               score+=(*i)->calculate_constraint(echo, 
map->normalizeX(x+type->width-1), map->normalizeY(y));
                        }
                        if(!passes)
                                continue;
diff -r e5dccad7dfcb -r 3abde68dab1a src/AIEcho.h
--- a/src/AIEcho.h      Sat Mar 24 00:26:38 2007 +0000
+++ b/src/AIEcho.h      Sat Mar 24 01:37:03 2007 +0000
@@ -136,7 +136,7 @@ namespace AIEcho
                position(int x, int y) : x(x), y(y) {}
                int x;
                int y;
-               bool operator<(const position& rhs)
+               bool operator<(const position& rhs) const
                {
                        if(x!=rhs.x)
                                return x<rhs.x;
diff -r e5dccad7dfcb -r 3abde68dab1a src/AINicowar.cpp
--- a/src/AINicowar.cpp Sat Mar 24 00:26:38 2007 +0000
+++ b/src/AINicowar.cpp Sat Mar 24 01:37:03 2007 +0000
@@ -22,6 +22,7 @@
 #include "boost/lexical_cast.hpp"
 #include "Utilities.h"
 #include "Game.h"
+#include "Unit.h"
 
 using namespace AIEcho;
 using namespace AIEcho::Gradients;
@@ -802,12 +803,12 @@ void NewNicowar::manage_inn(Echo& echo, 
        }
        if(level==2 && assigned!=3)
        {
-               ManagementOrder* mo_assign=new AssignWorkers(2, id);
+               ManagementOrder* mo_assign=new AssignWorkers(3, id);
                echo.add_management_order(mo_assign);
        }
        if(level==3 && assigned!=5)
        {
-               ManagementOrder* mo_assign=new AssignWorkers(3, id);
+               ManagementOrder* mo_assign=new AssignWorkers(5, id);
                echo.add_management_order(mo_assign);
        }
 }
@@ -1037,7 +1038,6 @@ void NewNicowar::upgrade_buildings(Echo&
        ///Level one upgrades
        if(num_upgrading_level1 < num_to_upgrade_level1)
        {
-               std::cout<<"starting upgrade "<<num_upgrading_level1<<std::endl;
                int building_type=choose_building_upgrade_type_level1(echo);
                if(building_type!=-1)
                {
@@ -1162,7 +1162,6 @@ void NewNicowar::choose_enemy_target(Ech
 {
        if(target==-1 || !echo.player->game->teams[target]->isAlive)
        {
-               std::cout<<"changing targets"<<std::endl;
                std::vector<int> available_targets;             
                for(enemy_team_iterator i(echo); i!=enemy_team_iterator(); ++i)
                {
@@ -1213,7 +1212,7 @@ void NewNicowar::dig_out_enemy(Echo& ech
        gi_pathfind.add_obstacle(new Entities::Ressource(STONE));
        Gradient& 
gradient_pathfind=echo.get_gradient_manager().get_gradient(gi_pathfind);
 
-       ///Next, find the closest point manhattan distance wise, to that 
building that is accessible
+       ///Next, find the closest point manhattan distance wise, to the 
building that is accessible
        MapInfo mi(echo);
        int closest_x=0;
        int closest_y=0;
@@ -1236,7 +1235,7 @@ void NewNicowar::dig_out_enemy(Echo& ech
        }
 
        ///Next, follow a path arround stone between the closest point and the 
buildings position, 
-       ///placing Clearing flags nas you go
+       ///placing Clearing flags as you go
 
        int xpos=closest_x;
        int ypos=closest_y;
@@ -1260,53 +1259,52 @@ void NewNicowar::dig_out_enemy(Echo& ech
                int cur_dist=gradient_pathfind.get_height(xpos, ypos);
                int lowest_entity=cur_dist+1;
 
-
                //Test diagnols first, then the horizontals and verticals.
-               if(gradient_pathfind.get_height(lx, uy) < lowest_entity)
+               if(gradient_pathfind.get_height(lx, uy) < lowest_entity && 
gradient_pathfind.get_height(lx, uy)>=0)
                {
                        lowest_entity=gradient_pathfind.get_height(lx, uy);
                        xpos=lx;
                        ypos=uy;
                }
-               if(gradient_pathfind.get_height(rx, uy) < lowest_entity)
+               if(gradient_pathfind.get_height(rx, uy) < lowest_entity && 
gradient_pathfind.get_height(rx, uy)>=0)
                {
                        lowest_entity=gradient_pathfind.get_height(rx, uy);
                        xpos=rx;
                        ypos=uy;
                }
-               if(gradient_pathfind.get_height(lx, dy) < lowest_entity)
+               if(gradient_pathfind.get_height(lx, dy) < lowest_entity && 
gradient_pathfind.get_height(lx, dy)>=0)
                {
                        lowest_entity=gradient_pathfind.get_height(lx, dy);
                        xpos=lx;
                        ypos=dy;
                }
-               if(gradient_pathfind.get_height(rx, dy) < lowest_entity)
+               if(gradient_pathfind.get_height(rx, dy) < lowest_entity && 
gradient_pathfind.get_height(rx, dy)>=0)
                {
                        lowest_entity=gradient_pathfind.get_height(rx, dy);
                        xpos=rx;
                        ypos=dy;
                }
 
-               if(gradient_pathfind.get_height(xpos, uy) < lowest_entity)
+               if(gradient_pathfind.get_height(xpos, uy) < lowest_entity && 
gradient_pathfind.get_height(xpos, uy)>=0)
                {
                        lowest_entity=gradient_pathfind.get_height(xpos, uy);
                        xpos=xpos;
                        ypos=uy;
                }
 
-               if(gradient_pathfind.get_height(lx, ypos) < lowest_entity)
+               if(gradient_pathfind.get_height(lx, ypos) < lowest_entity && 
gradient_pathfind.get_height(lx, ypos)>=0)
                {
                        lowest_entity=gradient_pathfind.get_height(lx, ypos);
                        xpos=lx;
                        ypos=ypos;
                }
-               if(gradient_pathfind.get_height(rx, ypos) < lowest_entity)
+               if(gradient_pathfind.get_height(rx, ypos) < lowest_entity && 
gradient_pathfind.get_height(rx, ypos)>=0)
                {
                        lowest_entity=gradient_pathfind.get_height(rx, ypos);
                        xpos=rx;
                        ypos=ypos;
                }
-               if(gradient_pathfind.get_height(xpos, dy) < lowest_entity)
+               if(gradient_pathfind.get_height(xpos, dy) < lowest_entity && 
gradient_pathfind.get_height(xpos, dy)>=0)
                {
                        lowest_entity=gradient_pathfind.get_height(xpos, dy);
                        xpos=xpos;
@@ -1321,7 +1319,7 @@ void NewNicowar::dig_out_enemy(Echo& ech
                {
                        flag_dist_count=0;
                        //The main order for the clearing flag
-                       BuildingOrder* bo_flag = new 
BuildingOrder(IntBuildingType::CLEARING_FLAG, 5);
+                       BuildingOrder* bo_flag = new 
BuildingOrder(IntBuildingType::CLEARING_FLAG, 10);
                        //Place it on the current point
                        bo_flag->add_constraint(new 
Construction::SinglePosition(xpos, ypos));
                        //Add the building order to the list of orders
@@ -1424,9 +1422,6 @@ void NewNicowar::update_fruit_flags(AIEc
                ManagementOrder* mo_completion_orange=new ChangeFlagSize(4, 
id_orange);
                echo.add_management_order(mo_completion_orange);
 
-
-
-
                //The main order for the exploration flag on prunes
                BuildingOrder* bo_prune = new 
BuildingOrder(IntBuildingType::EXPLORATION_FLAG, 2);
                //You want the closest fruit to your settlement possible
@@ -1440,6 +1435,8 @@ void NewNicowar::update_fruit_flags(AIEc
                ManagementOrder* mo_completion_prune=new ChangeFlagSize(4, 
id_prune);
                echo.add_management_order(mo_completion_prune);
 
+
+
                exploration_on_fruit=true;
        }
        update_fruit_alliances(echo);
diff -r e5dccad7dfcb -r 3abde68dab1a src/AINicowar.h
--- a/src/AINicowar.h   Sat Mar 24 00:26:38 2007 +0000
+++ b/src/AINicowar.h   Sat Mar 24 01:37:03 2007 +0000
@@ -47,6 +47,7 @@ private:
                PlacementSize,
        };
 
+
        ///This function is called at the very begginning of the game,
        ///to initialize the existing buildings with the right amount of units
        void initialize(AIEcho::Echo& echo);
@@ -168,7 +169,6 @@ private:
        ///This integer stores whether a building is being dug out at the 
current moment
        bool is_digging_out;
 
-
        ///This function updates the restricted areas for farming
        void update_farming(AIEcho::Echo& echo);
 
diff -r e5dccad7dfcb -r 3abde68dab1a src/Building.cpp
--- a/src/Building.cpp  Sat Mar 24 00:26:38 2007 +0000
+++ b/src/Building.cpp  Sat Mar 24 01:37:03 2007 +0000
@@ -656,13 +656,15 @@ void Building::cancelConstruction(void)
                // when the building upgrade" was already canceled.
                return;
        }
+       
+       removeForbiddenZoneFromUpgradeArea();
+
        constructionResultState=NO_CONSTRUCTION;
        
        if (!type->isVirtual)
                owner->map->setBuilding(posX, posY, type->width, type->height, 
NOGBID);
        int midPosX=posX-type->decLeft;
        int midPosY=posY-type->decTop;
-       
        owner->removeFromAbilitiesLists(this);
        owner->prestige-=type->prestige;
        typeNum=recoverTypeNum;
@@ -752,6 +754,7 @@ void Building::updateCallLists(void)
 {
        if (buildingState==DEAD)
                return;
+       desiredMaxUnitWorking = desiredNumberOfWorkers();
        bool ressourceFull=isRessourceFull();
        if (ressourceFull && !(type->canExchange && owner->openMarket()))
        {
@@ -861,6 +864,7 @@ void Building::updateConstructionState(v
                        {
                                buildingState=WAITING_FOR_CONSTRUCTION_ROOM;
                                
owner->buildingsTryToBuildingSiteRoom.push_front(this);
+                               addForbiddenZoneToUpgradeArea();
                                if (verbose)
                                        printf("bgid=%d, inserted in 
buildingsTryToBuildingSiteRoom\n", gid);
                        }
@@ -880,6 +884,8 @@ void Building::updateBuildingSite(void)
                for(int i=0; i<MAX_RESSOURCES; i++)
                        ressources[i]-=type->maxRessource[i];
 
+               if(constructionResultState!=NEW_BUILDING)
+                       removeForbiddenZoneFromUpgradeArea();
                owner->prestige-=type->prestige;
                typeNum=type->nextLevel;
                type=globalContainer->buildingsTypes.get(type->nextLevel);
@@ -1178,6 +1184,66 @@ bool Building::tryToBuildingSiteRoom(voi
        }
        return isRoom;
 }
+
+
+
+void Building::addForbiddenZoneToUpgradeArea(void)
+{
+       int midPosX=posX-type->decLeft;
+       int midPosY=posY-type->decTop;
+
+       int targetLevelTypeNum=-1;
+       if (constructionResultState==UPGRADE)
+               targetLevelTypeNum=type->nextLevel;
+       else if (constructionResultState==REPAIR)
+               targetLevelTypeNum=type->prevLevel;
+       else
+               assert(false);
+
+       BuildingType 
*targetBt=globalContainer->buildingsTypes.get(targetLevelTypeNum);
+       int newPosX=midPosX+targetBt->decLeft;
+       int newPosY=midPosY+targetBt->decTop;
+       int newWidth=targetBt->width;
+       int newHeight=targetBt->height;
+       for(int nx=0; nx<newWidth; ++nx)
+       {
+               for(int ny=0; ny<newHeight; ++ny)
+               {
+                       
owner->map->addHiddenForbidden(owner->map->normalizeX(newPosX+nx), 
owner->map->normalizeY(newPosY+ny), owner->teamNumber); 
+               }
+       }
+}
+
+
+
+void Building::removeForbiddenZoneFromUpgradeArea(void)
+{
+       int midPosX=posX-type->decLeft;
+       int midPosY=posY-type->decTop;
+
+       int targetLevelTypeNum=-1;
+       if (constructionResultState==UPGRADE)
+               targetLevelTypeNum=type->nextLevel;
+       else if (constructionResultState==REPAIR)
+               targetLevelTypeNum=type->prevLevel;
+       else
+               assert(false);
+
+       BuildingType 
*targetBt=globalContainer->buildingsTypes.get(targetLevelTypeNum);
+       int newPosX=midPosX+targetBt->decLeft;
+       int newPosY=midPosY+targetBt->decTop;
+       int newWidth=targetBt->width;
+       int newHeight=targetBt->height;
+       for(int nx=0; nx<newWidth; ++nx)
+       {
+               for(int ny=0; ny<newHeight; ++ny)
+               {
+                       
owner->map->removeHiddenForbidden(owner->map->normalizeX(newPosX+nx), 
owner->map->normalizeY(newPosY+ny), owner->teamNumber); 
+               }
+       }
+}
+
+
 
 bool Building::isHardSpaceForBuildingSite(void)
 {
@@ -2096,8 +2162,7 @@ void Building::addRessourceIntoBuilding(
                default:
                        assert(false);
        }
-       updateCallLists();
-       updateUnitsWorking();
+       update();
 }
 
 
diff -r e5dccad7dfcb -r 3abde68dab1a src/Building.h
--- a/src/Building.h    Sat Mar 24 00:26:38 2007 +0000
+++ b/src/Building.h    Sat Mar 24 01:37:03 2007 +0000
@@ -120,6 +120,14 @@ public:
        ///Attempts to find room for a building site. If room is found, the 
building site is established,
        ///and it returns true.
        bool tryToBuildingSiteRoom(void);
+
+       ///This function puts hidden forbidden area arround a new building 
site. This dispereses units so that
+       ///the building isn't waiting for space when there are lots of units.
+       void addForbiddenZoneToUpgradeArea(void);
+       ///This function removes the hidden forbidden area placed by 
addForbiddenToUpgradeArea
+       ///It must be done before any type or position state is changed.
+       void removeForbiddenZoneFromUpgradeArea(void);
+       
        ///Checks if there is hard space for a building. Non hard space is any 
space occupied by something that
        ///won't move. Units will move, so they are ignored. If there is space 
for the building site, then this
        ///returns true.
@@ -173,9 +181,9 @@ public:
        
        /// This function is called when a Unit places a ressource into the 
building.
        void addRessourceIntoBuilding(int ressourceType);
-       
        /// This function is called when a Unit takes a ressource from a 
building, such as a market
        void removeRessourceFromBuilding(int ressourceType);
+
        ///Gets the middle x cordinate relative to posX
        int getMidX(void);
        ///Gets the middle y cordinate relative to posY
@@ -240,6 +248,7 @@ public:
        Sint32 subscriptionWorkingTimer;
        Sint32 maxUnitInside;
        std::list<Unit *> unitsInside;
+       Sint32 clearingFlagUpdateTimer;
        
        // optimisation and consistency
        Sint32 canFeedUnit; // Included in {0: unknow, 1:allready in 
owner->canFeedUnit, 2:not in owner->canFeedUnit}
diff -r e5dccad7dfcb -r 3abde68dab1a src/Engine.cpp
--- a/src/Engine.cpp    Sat Mar 24 00:26:38 2007 +0000
+++ b/src/Engine.cpp    Sat Mar 24 01:37:03 2007 +0000
@@ -394,7 +394,7 @@ int Engine::run(void)
        
        while (doRunOnceAgain)
        {
-               const int speed=40;
+               const int speed=15;
                Uint32 startTick, endTick;
                bool networkReadyToExecute = true;
                Sint32 ticksSpentInComputation = speed;
diff -r e5dccad7dfcb -r 3abde68dab1a src/Game.cpp
--- a/src/Game.cpp      Sat Mar 24 00:26:38 2007 +0000
+++ b/src/Game.cpp      Sat Mar 24 01:37:03 2007 +0000
@@ -1508,6 +1508,17 @@ bool Game::checkHardRoomForBuilding(int 
        assert(!bt->isVirtual); // This method is not for flags!
        return map.isHardSpaceForBuilding(x, y, w, h);
 }
+
+
+
+Unit* Game::getUnit(int guid)
+{
+       if(guid == NOGUID)
+               return NULL;
+       return teams[Unit::GIDtoTeam(guid)]->myUnits[Unit::GIDtoID(guid)];
+}
+
+
 
 void Game::drawPointBar(int x, int y, BarOrientation orientation, int 
maxLength, int actLength, Uint8 r, Uint8 g, Uint8 b, int barWidth)
 {
diff -r e5dccad7dfcb -r 3abde68dab1a src/Game.h
--- a/src/Game.h        Sat Mar 24 00:26:38 2007 +0000
+++ b/src/Game.h        Sat Mar 24 01:37:03 2007 +0000
@@ -135,6 +135,8 @@ public:
        //! This remove anything at case(x, y), and return a rect which include 
every removed things.
        bool removeUnitAndBuildingAndFlags(int x, int y, unsigned 
flags=DEL_UNIT|DEL_BUILDING|DEL_FLAG);
        bool removeUnitAndBuildingAndFlags(int x, int y, int size, unsigned 
flags=DEL_UNIT|DEL_BUILDING|DEL_FLAG);
+       ///A convenience function, returns a pointer to the unit with the guid, 
or NULL otherwise
+       Unit* getUnit(int guid);
 
        bool checkRoomForBuilding(int mousePosX, int mousePosY, const 
BuildingType *bt, int *buildingPosX, int *buildingPosY, int teamNumber, bool 
checkFow=true);
        bool checkRoomForBuilding(int x, int y, const BuildingType *bt, int 
teamNumber, bool checkFow=true);
diff -r e5dccad7dfcb -r 3abde68dab1a src/Makefile.am
--- a/src/Makefile.am   Sat Mar 24 00:26:38 2007 +0000
+++ b/src/Makefile.am   Sat Mar 24 01:37:03 2007 +0000
@@ -25,188 +25,189 @@ endif
 endif
 
 glob2_SOURCES=\
-IntBuildingType.h\
-IntBuildingType.cpp\
-AI.cpp \
-AI.h\
-AIOldNicowar.cpp \
-AIOldNicowar.h \
-AINicowar.cpp \
-AINicowar.h \
-AIImplementation.h\
-AIEcho.h\
-AIEcho.cpp\
-AINull.h\
-AINull.cpp\
-AINumbi.h\
-AINumbi.cpp\
-AICastor.h\
-AICastor.cpp\
-AIToubib.h\
-AIToubib.cpp\
-AIWarrush.h\
-AIWarrush.cpp\
-Building.cpp\
-Building.h\
-BuildingType.cpp\
-BuildingType.h\
-Bullet.h\
-Bullet.cpp\
-Campaign.h\
-Campaign.cpp\
-CampaignSelectorScreen.h\
-CampaignSelectorScreen.cpp\
-CampaignEditor.h\
-CampaignEditor.cpp\
-CampaignMenuScreen.h\
-CampaignMenuScreen.cpp\
-CVS\
-Engine.cpp\
-Engine.h\
-EntityType.cpp\
-EntityType.h\
-Fatal.cpp\
-Fatal.h\
-GUIGlob2FileList.h \
-GUIGlob2FileList.cpp \
-GUIMapPreview.h \
-GUIMapPreview.cpp \
-Game.cpp\
-Game.h\
-GameGUI.cpp\
-GameGUI.h\
-GameGUIDialog.cpp\
-GameGUIDialog.h\
-GameGUILoadSave.cpp\
-GameGUILoadSave.h\
-Glob2.cpp\
-Glob2.h\
-GlobalContainer.cpp\
-GlobalContainer.h\
-Settings.cpp\
-Settings.h\
-Header.h\
-Makefile.am\
-Map.cpp\
-Map.h\
-MapGenerator.cpp\
-MapEdit.cpp\
-MapEdit.h\
-NetConsts.h\
-NetGame.cpp\
-NetGame.h\
-Order.cpp\
-Order.h\
-Player.cpp\
-Player.h\
-SessionConnection.cpp\
-SessionConnection.h\
-Race.cpp\
-Race.h\
-Ressource.h\
-Ressource.cpp\
-Sector.h\
-Sector.cpp\
-Session.cpp\
-Session.h\
-SGSL.cpp \
-SGSL.h \
-SoundMixer.cpp \
-SoundMixer.h \
-Team.cpp\
-Team.h\
-TeamStat.h\
-TeamStat.cpp\
-Unit.cpp\
-Unit.h\
-UnitType.cpp\
-UnitType.h\
-Utilities.cpp\
-Utilities.h \
-ChooseMapScreen.h \
-ChooseMapScreen.cpp \
-CustomGameScreen.h \
-CustomGameScreen.cpp \
-MainMenuScreen.h \
-MainMenuScreen.cpp \
-CreditScreen.h \
-CreditScreen.cpp \
-CampaignScreen.h \
-CampaignScreen.cpp \
-MultiplayersOfferScreen.h\
-MultiplayersOfferScreen.cpp \
-YOGScreen.h \
-YOGScreen.cpp \
-SettingsScreen.h \
-SettingsScreen.cpp \
-MultiplayersHostScreen.h \
-MultiplayersHostScreen.cpp \
-MultiplayersHost.h \
-MultiplayersHost.cpp \
-MultiplayersJoinScreen.h \
-MultiplayersJoinScreen.cpp \
-MultiplayersJoin.h \
-MultiplayersJoin.cpp \
-MultiplayersConnectedScreen.h \
-MultiplayersConnectedScreen.cpp \
-MultiplayersChooseMapScreen.h \
-MultiplayersChooseMapScreen.cpp \
-MultiplayersCrossConnectable.h \
-MultiplayersCrossConnectable.cpp \
-NonANSICStdWrapper.h \
-NewMapScreen.h \
-NewMapScreen.cpp \
-YOG.h \
-YOG.cpp  \
-MapGenerationDescriptor.h \
-MapGenerationDescriptor.cpp \
-LogFileManager.h \
-LogFileManager.cpp \
-YOGPreScreen.h \
-YOGPreScreen.cpp \
-ScriptEditorScreen.h \
-ScriptEditorScreen.cpp \
-EndGameScreen.h \
-EndGameScreen.cpp \
-Marshaling.h \
-YOGConsts.h \
-NetDefine.h \
-Version.h \
-RessourceType.h \
-TerrainType.h \
-UnitConsts.h \
-ConfigFiles.h \
-EntitiesTypes.h \
-BuildingsTypes.h \
-BuildingsTypes.cpp \
-RessourcesTypes.h \
-RessourcesTypes.cpp \
-GameUtilities.h \
-GameUtilities.cpp \
-BitArray.h \
-BitArray.cpp \
-Brush.h \
-Brush.cpp \
-IRC.h \
-IRC.cpp \
-VoiceRecorder.h \
-VoiceRecorder.cpp \
-PerlinNoise.h \
-PerlinNoise.cpp\
-Glob2Screen.h \
-Glob2Screen.cpp \
-Glob2Style.h \
-Glob2Style.cpp\
-UnitSkin.h\
-UnitSkin.cpp\
-UnitsSkins.h\
-UnitsSkins.cpp\
-UnitEditorScreen.h\
-UnitEditorScreen.cpp\
-HeightMapGenerator.h\
-HeightMapGenerator.cpp\
-DynamicClouds.h\
-DynamicClouds.cpp
+AI.cpp  \
+AI.h \
+AICastor.cpp \
+AICastor.h \
+AIEcho.cpp \
+AIEcho.h \
+AIImplementation.h \
+AINicowar.cpp  \
+AINicowar.h  \
+AINull.cpp \
+AINull.h \
+AINumbi.cpp \
+AINumbi.h \
+AIOldNicowar.cpp  \
+AIOldNicowar.h  \
+AIToubib.cpp \
+AIToubib.h \
+AIWarrush.cpp \
+AIWarrush.h \
+BitArray.cpp  \
+BitArray.h  \
+Brush.cpp  \
+Brush.h  \
+Building.cpp \
+Building.h \
+BuildingType.cpp \
+BuildingType.h \
+BuildingsTypes.cpp  \
+BuildingsTypes.h  \
+Bullet.cpp \
+Bullet.h \
+CVS \
+Campaign.cpp \
+Campaign.h \
+CampaignEditor.cpp \
+CampaignEditor.h \
+CampaignMenuScreen.cpp \
+CampaignMenuScreen.h \
+CampaignScreen.cpp  \
+CampaignScreen.h  \
+CampaignSelectorScreen.cpp \
+CampaignSelectorScreen.h \
+ChooseMapScreen.cpp  \
+ChooseMapScreen.h  \
+ConfigFiles.h  \
+CreditScreen.cpp  \
+CreditScreen.h  \
+CustomGameScreen.cpp  \
+CustomGameScreen.h  \
+DynamicClouds.cpp \
+DynamicClouds.h \
+EndGameScreen.cpp  \
+EndGameScreen.h  \
+Engine.cpp \
+Engine.h \
+EntitiesTypes.h  \
+EntityType.cpp \
+EntityType.h \
+Fatal.cpp \
+Fatal.h \
+GUIGlob2FileList.cpp  \
+GUIGlob2FileList.h  \
+GUIMapPreview.cpp  \
+GUIMapPreview.h  \
+Game.cpp \
+Game.h \
+GameGUI.cpp \
+GameGUI.h \
+GameGUIDialog.cpp \
+GameGUIDialog.h \
+GameGUILoadSave.cpp \
+GameGUILoadSave.h \
+GameUtilities.cpp  \
+GameUtilities.h  \
+Glob2.cpp \
+Glob2.h \
+Glob2Screen.cpp  \
+Glob2Screen.h  \
+Glob2Style.cpp \
+Glob2Style.h  \
+GlobalContainer.cpp \
+GlobalContainer.h \
+Header.h \
+HeightMapGenerator.cpp \
+HeightMapGenerator.h \
+IRC.cpp  \
+IRC.h  \
+IntBuildingType.cpp \
+IntBuildingType.h \
+LogFileManager.cpp  \
+LogFileManager.h  \
+MainMenuScreen.cpp  \
+MainMenuScreen.h  \
+Makefile.am \
+Map.cpp \
+Map.h \
+MapEdit.cpp \
+MapEdit.h \
+MapGenerationDescriptor.cpp  \
+MapGenerationDescriptor.h  \
+MapGenerator.cpp \
+Marshaling.h  \
+MultiplayersChooseMapScreen.cpp  \
+MultiplayersChooseMapScreen.h  \
+MultiplayersConnectedScreen.cpp  \
+MultiplayersConnectedScreen.h  \
+MultiplayersCrossConnectable.cpp  \
+MultiplayersCrossConnectable.h  \
+MultiplayersHost.cpp  \
+MultiplayersHost.h  \
+MultiplayersHostScreen.cpp  \
+MultiplayersHostScreen.h  \
+MultiplayersJoin.cpp  \
+MultiplayersJoin.h  \
+MultiplayersJoinScreen.cpp  \
+MultiplayersJoinScreen.h  \
+MultiplayersOfferScreen.cpp  \
+MultiplayersOfferScreen.h \
+NetConsts.h \
+NetDefine.h  \
+NetGame.cpp \
+NetGame.h \
+NewMapScreen.cpp  \
+NewMapScreen.h  \
+NonANSICStdWrapper.h  \
+Order.cpp \
+Order.h \
+PerlinNoise.cpp \
+PerlinNoise.h  \
+Player.cpp \
+Player.h \
+Race.cpp \
+Race.h \
+Ressource.cpp \
+Ressource.h \
+RessourceType.h  \
+RessourcesTypes.cpp  \
+RessourcesTypes.h  \
+SGSL.cpp  \
+SGSL.h  \
+ScriptEditorScreen.cpp  \
+ScriptEditorScreen.h  \
+Sector.cpp \
+Sector.h \
+Session.cpp \
+Session.h \
+SessionConnection.cpp \
+SessionConnection.h \
+Settings.cpp \
+Settings.h \
+SettingsScreen.cpp  \
+SettingsScreen.h  \
+SoundMixer.cpp  \
+SoundMixer.h  \
+Team.cpp \
+Team.h \
+TeamStat.cpp \
+TeamStat.h \
+TerrainType.h  \
+Unit.cpp \
+Unit.h \
+UnitConsts.h  \
+UnitEditorScreen.cpp \
+UnitEditorScreen.h \
+UnitSkin.cpp \
+UnitSkin.h \
+UnitType.cpp \
+UnitType.h \
+UnitsSkins.cpp \
+UnitsSkins.h \
+Utilities.cpp \
+Utilities.h  \
+Version.h  \
+VoiceRecorder.cpp  \
+VoiceRecorder.h  \
+YOG.cpp   \
+YOG.h  \
+YOGConsts.h  \
+YOGPreScreen.cpp  \
+YOGPreScreen.h  \
+YOGScreen.cpp  \
+YOGScreen.h 
+
 
 if LINKSTATIC
 glob2_LDADD = ../libgag/src/libgag.a -lGL -lGLU -lpthread $(glob2_static_lib)
diff -r e5dccad7dfcb -r 3abde68dab1a src/Map.cpp
--- a/src/Map.cpp       Sat Mar 24 00:26:38 2007 +0000
+++ b/src/Map.cpp       Sat Mar 24 01:37:03 2007 +0000
@@ -937,6 +937,7 @@ void Map::setSize(int wDec, int hDec, Te
        initCase.groundUnit = NOGUID;
        initCase.airUnit = NOGUID;
        initCase.forbidden = 0;
+       initCase.hiddenForbidden = 0;
        initCase.guardArea = 0;
        initCase.clearArea = 0;
        initCase.scriptAreas = 0;
@@ -1073,6 +1074,10 @@ bool Map::load(GAGCore::InputStream *str
                cases[i].airUnit = stream->readUint16("airUnit");
 
                cases[i].forbidden = stream->readUint32("forbidden");
+               if(sessionGame->versionMinor >= 56)
+                       cases[i].hiddenForbidden = 
stream->readUint32("hiddenForbidden");
+               else
+                       cases[i].hiddenForbidden = 0;
                
                if (sessionGame->versionMinor >= 36)
                        cases[i].guardArea = stream->readUint32("guardArea");
@@ -1202,6 +1207,7 @@ void Map::save(GAGCore::OutputStream *st
                stream->writeUint16(cases[i].groundUnit, "groundUnit");
                stream->writeUint16(cases[i].airUnit, "airUnit");
                stream->writeUint32(cases[i].forbidden, "forbidden");
+               stream->writeUint32(cases[i].hiddenForbidden, 
"hiddenForbidden");
                stream->writeUint32(cases[i].guardArea, "guardArea");
                stream->writeUint32(cases[i].clearArea, "clearArea");
                stream->writeUint16(cases[i].scriptAreas, "scriptAreas");
@@ -2870,7 +2876,7 @@ template<typename Tint> void Map::update
        for (size_t i=0; i<size; i++)
        {
                Case c=cases[i];
-               if (c.forbidden&teamMask)
+               if ((c.forbidden|c.hiddenForbidden)&teamMask)
                        gradient[i]=0;
                else if (c.ressource.type==NO_RES_TYPE)
                {
@@ -3229,7 +3235,7 @@ void Map::pathfindRandom(Unit *unit, boo
                printf("pathfindRandom()\n");
        int x=unit->posX;
        int y=unit->posY;
-       if (cases[x+(y<<wDec)].forbidden&unit->owner->me)
+       if 
((cases[x+(y<<wDec)].forbidden|cases[x+(y<<wDec)].hiddenForbidden)&unit->owner->me)
        {
                if (verbose)
                        printf(" forbidden\n");
@@ -3372,7 +3378,7 @@ void Map::updateLocalGradient(Building *
                                        gradient[addrl]=0;
                                else if (c.building!=NOGBID && c.building!=bgid)
                                        gradient[addrl]=0;
-                               else if (c.forbidden&teamMask)
+                               else if (c.forbidden&teamMask || 
c.hiddenForbidden&teamMask)
                                        gradient[addrl]=0;
                                else if (!canSwim && isWater(xg, yg))
                                        gradient[addrl]=0;
@@ -3655,7 +3661,7 @@ template<typename Tint> void Map::update
                        {
                                if (c.ressource.type!=NO_RES_TYPE)
                                        gradient[wyx] = 0;
-                               else if (c.forbidden&teamMask)
+                               else if (c.forbidden&teamMask || 
c.hiddenForbidden&teamMask)
                                        gradient[wyx] = 0;
                                else if (!canSwim && isWater(x, y))
                                        gradient[wyx] = 0;
@@ -3801,7 +3807,7 @@ bool Map::updateLocalRessources(Building
                                }
                                else if (c.building!=NOGBID)
                                        gradient[addrl]=0;
-                               else if (c.forbidden&teamMask)
+                               else if (c.forbidden&teamMask || 
c.hiddenForbidden&teamMask)
                                        gradient[addrl]=0;
                                else if (!canSwim && isWater(xg, yg))
                                        gradient[addrl]=0;
@@ -4168,7 +4174,7 @@ bool Map::pathfindBuilding(Building *bui
        assert(x>=0);
        assert(y>=0);
        Uint32 teamMask=building->owner->me;
-       if (((cases[x+y*w].forbidden) & teamMask)!=0)
+       if (((cases[x+y*w].forbidden | cases[x+y*w].hiddenForbidden) & 
teamMask)!=0)
        {
                int teamNumber=building->owner->teamNumber;
                if (verbose)
@@ -4660,7 +4666,7 @@ template<typename Tint> void Map::update
                {
                        gradient[i] = 0;
                }
-               else if (c.forbidden & teamMask)
+               else if ((c.forbidden | c.hiddenForbidden) & teamMask)
                {
                        // we compute the 8 addresses around i:
                        // (a stands for address, u for up, d for down, l for 
left, r for right, m for middle)
@@ -4673,21 +4679,21 @@ template<typename Tint> void Map::update
                        size_t adl = (i - 1 + w) & (size - 1);
                        size_t aml = (i - 1    ) & (size - 1);
                        
-                       if( ((cases[aul].ressource.type != NO_RES_TYPE) || 
(cases[aul].forbidden&teamMask)
+                       if( ((cases[aul].ressource.type != NO_RES_TYPE) || 
((cases[aul].forbidden | cases[aul].hiddenForbidden) &teamMask)
                                || (cases[aul].building!=NOGBID) || (!canSwim 
&& isWater(aul))) &&
-                           ((cases[aul].ressource.type != NO_RES_TYPE) || 
(cases[aum].forbidden&teamMask)
+                           ((cases[aul].ressource.type != NO_RES_TYPE) || 
((cases[aum].forbidden | cases[aum].hiddenForbidden) &teamMask)
                            || (cases[aum].building!=NOGBID) || (!canSwim && 
isWater(aum))) &&
-                           ((cases[aul].ressource.type != NO_RES_TYPE) || 
(cases[aur].forbidden&teamMask)
+                           ((cases[aul].ressource.type != NO_RES_TYPE) || 
((cases[aur].forbidden | cases[aur].hiddenForbidden) &teamMask)
                            || (cases[aur].building!=NOGBID) || (!canSwim && 
isWater(aur))) &&
-                           ((cases[aul].ressource.type != NO_RES_TYPE) || 
(cases[amr].forbidden&teamMask)
+                           ((cases[aul].ressource.type != NO_RES_TYPE) || 
((cases[amr].forbidden | cases[amr].hiddenForbidden) &teamMask)
                            || (cases[amr].building!=NOGBID) || (!canSwim && 
isWater(amr))) &&
-                           ((cases[aul].ressource.type != NO_RES_TYPE) || 
(cases[adr].forbidden&teamMask)
+                           ((cases[aul].ressource.type != NO_RES_TYPE) || 
((cases[adr].forbidden | cases[adr].hiddenForbidden) &teamMask)
                            || (cases[adr].building!=NOGBID) || (!canSwim && 
isWater(adr))) &&
-                           ((cases[aul].ressource.type != NO_RES_TYPE) || 
(cases[adm].forbidden&teamMask)
+                           ((cases[aul].ressource.type != NO_RES_TYPE) || 
((cases[adm].forbidden | cases[adm].hiddenForbidden) &teamMask)
                            || (cases[adm].building!=NOGBID) || (!canSwim && 
isWater(adm))) &&
-                           ((cases[aul].ressource.type != NO_RES_TYPE) || 
(cases[adl].forbidden&teamMask)
+                           ((cases[aul].ressource.type != NO_RES_TYPE) || 
((cases[adl].forbidden | cases[adl].hiddenForbidden) &teamMask)
                            || (cases[adl].building!=NOGBID) || (!canSwim && 
isWater(adl))) &&
-                           ((cases[aul].ressource.type != NO_RES_TYPE) || 
(cases[aml].forbidden&teamMask)
+                           ((cases[aul].ressource.type != NO_RES_TYPE) || 
((cases[aml].forbidden | cases[aml].hiddenForbidden) &teamMask)
                            || (cases[aml].building!=NOGBID) || (!canSwim && 
isWater(aml))) )
                        {
                                gradient[i]= 1;
@@ -4722,7 +4728,7 @@ template<typename Tint> void Map::update
                        testgradient[i] = 0;
                else if (!canSwim && isWater(i))
                        testgradient[i] = 0;
-               else if (c.forbidden&teamMask)
+               else if (c.forbidden&teamMask || c.hiddenForbidden&teamMask)
                {
                        testgradient[i]= 1;  // Later: check if we can set it 
to 254.
                        listedAddr[listCountWriteInit++] = i;  // Remember this 
field.
@@ -4787,7 +4793,7 @@ template<typename Tint> void Map::update
                        gradient[i] = 0;
                else if (!canSwim && isWater(i))
                        gradient[i] = 0;
-               else if (c.forbidden&teamMask)
+               else if (c.forbidden&teamMask || c.hiddenForbidden&teamMask)
                        gradient[i]= 1;
                else
                {
@@ -4836,7 +4842,7 @@ template<typename Tint> void Map::update
        for (size_t i=0; i<size; i++)
        {
                Case c=cases[i];
-               if (c.forbidden & teamMask)
+               if (c.forbidden & teamMask || c.hiddenForbidden & teamMask)
                        gradient[i] = 0;
                else if (c.ressource.type != NO_RES_TYPE)
                        gradient[i] = 0;
@@ -5018,6 +5024,7 @@ Uint32 Map::checkSum(bool heavy)
                                c->groundUnit +
                                c->airUnit +
                                c->forbidden +
+                               c->hiddenForbidden +
                                c->scriptAreas;
                        cs=(cs<<1)|(cs>>31);
                }
diff -r e5dccad7dfcb -r 3abde68dab1a src/Map.h
--- a/src/Map.h Sat Mar 24 00:26:38 2007 +0000
+++ b/src/Map.h Sat Mar 24 01:37:03 2007 +0000
@@ -57,6 +57,9 @@ struct Case
        Uint16 airUnit;
 
        Uint32 forbidden; // This is a mask, one bit by team, 1=forbidden, 
0=allowed
+       ///The difference between forbidden zone and hidden forbidden zone is 
that hidden forbidden zone
+       ///is put there by the game engine and is not draw to the screen.
+       Uint32 hiddenForbidden; // This is a mask, one bit by team, 
1=forbidden, 0=allowed
        Uint32 guardArea; // This is a mask, one bit by team, 1=guard area, 
0=normal
        Uint32 clearArea; // This is a mask, one bit by team, 1=clear area, 
0=normal
 
@@ -123,6 +126,26 @@ public:
        //! Return the number of sectors on y, which corresponds to the sector 
map height
        int getSectorH(void) const { return hSector; }
 
+       ///Returns a normalized version of the x cordinate, taking into account 
that x cordinates wrap arround
+       int normalizeX(int x)
+       {
+               if(x>=getW())
+                       return x-getW();
+               if(x<0)
+                       return x+getW();
+               return x;
+       }
+       
+       ///Returns a normalized version of the y cordinate, taking into account 
that y cordinates wrap arround
+       int normalizeY(int y)
+       {
+               if(y>=getH())
+                       return y-getH();
+               if(y<0)
+                       return y+getH();
+               return y;
+       }
+
        //! Set map to discovered state at position (x, y) for all teams in 
sharedVision (mask).
        void setMapDiscovered(int x, int y, Uint32 sharedVision)
        {
@@ -291,9 +314,10 @@ public:
                return (cases+pos)->ressource;
        }
        
+       //Returns the combined forbidden and hidden foribidden masks
        Uint32 getForbidden(int x, int y)
        {
-               return cases[((y&hMask)<<wDec)+(x&wMask)].forbidden;
+               return cases[((y&hMask)<<wDec)+(x&wMask)].forbidden | 
cases[((y&hMask)<<wDec)+(x&wMask)].hiddenForbidden;
        }
        
        Uint8 getExplored(int x, int y, int team)
@@ -314,6 +338,16 @@ public:
        void setForbidden(int x, int y, Uint32 forbidden)
        {
                cases[((y&hMask)<<wDec)+(x&wMask)].forbidden = forbidden;
+       }
+       
+       void addHiddenForbidden(int x, int y, Uint32 teamNum)
+       {
+               cases[((y&hMask)<<wDec)+(x&wMask)].hiddenForbidden |= 
(1<<teamNum);
+       }
+       void removeHiddenForbidden(int x, int y, Uint32 teamNum)
+       {
+               Case& c=cases[((y&hMask)<<wDec)+(x&wMask)];
+               c.hiddenForbidden ^= c.hiddenForbidden & (1<<teamNum);
        }
        
        bool isWater(int x, int y)
diff -r e5dccad7dfcb -r 3abde68dab1a src/Team.cpp
--- a/src/Team.cpp      Sat Mar 24 00:26:38 2007 +0000
+++ b/src/Team.cpp      Sat Mar 24 01:37:03 2007 +0000
@@ -926,6 +926,8 @@ bool Team::prioritize_building(Building*
                int ratio_rhs_unit = (rhs->maxUnitWorking  - 
rhs->unitsWorking.size()) * lhs->unitsWorking.size();
                if(ratio_lhs_unit == ratio_rhs_unit)
                {
+                       lhs->computeWishedRessources();
+                       rhs->computeWishedRessources();
                        int ratio_lhs_ressource = lhs->totalWishedRessource();
                        int ratio_rhs_ressource = rhs->totalWishedRessource();
                        return ratio_lhs_ressource > ratio_rhs_ressource;
diff -r e5dccad7dfcb -r 3abde68dab1a src/Unit.cpp
--- a/src/Unit.cpp      Sat Mar 24 00:26:38 2007 +0000
+++ b/src/Unit.cpp      Sat Mar 24 01:37:03 2007 +0000
@@ -1051,7 +1051,6 @@ void Unit::handleDisplacement(void)
                                
                                if (!loopMove && !exchangeReady)
                                {
-                                       attachedBuilding->update();
                                        //NOTE: if attachedBuilding has become 
NULL; it's beacause the building doesn't need me anymore.
                                        if (!attachedBuilding)
                                        {
@@ -1067,6 +1066,7 @@ void Unit::handleDisplacement(void)
                                                ///Find a ressource that the 
building wants and a location to get it from
                                                ///The location may be a 
market, or the harvesting the ressource from the
                                                ///map.
+                                               attachedBuilding->update();
                                                int needs[MAX_NB_RESSOURCES];
                                                
attachedBuilding->wishedRessources(needs);
                                                int 
teamNumber=owner->teamNumber;
@@ -1892,6 +1892,10 @@ void Unit::handleAction(void)
                        assert(!performance[FLY]);
                        owner->map->setGroundUnit(posX, posY, NOGUID);
                        gotoGroundTarget();
+                       if(dx==0 && dy==0)
+                       owner->map->addHiddenForbidden(posX, posY, 
owner->teamNumber);
+                       else
+                               owner->map->removeHiddenForbidden(posX, posY, 
owner->teamNumber);
                        posX=(posX+dx)&(owner->map->getMaskW());
                        posY=(posY+dy)&(owner->map->getMaskH());
                        selectPreferedGroundMovement();
@@ -1926,6 +1930,12 @@ void Unit::handleAction(void)
                                owner->map->setGroundUnit(posX, posY, NOGUID);
                        
                        directionFromDxDy();
+                       
+                       if(dx==0 && dy==0)
+                               owner->map->addHiddenForbidden(posX, posY, 
owner->teamNumber);
+                       else
+                               owner->map->removeHiddenForbidden(posX, posY, 
owner->teamNumber);
+                               
                        posX=(posX+dx)&(owner->map->getMaskW());
                        posY=(posY+dy)&(owner->map->getMaskH());
                        
diff -r e5dccad7dfcb -r 3abde68dab1a src/Version.h
--- a/src/Version.h     Sat Mar 24 00:26:38 2007 +0000
+++ b/src/Version.h     Sat Mar 24 01:37:03 2007 +0000
@@ -69,6 +69,6 @@
 // version 53 added no-growth areas, to limit ressources growth
 // version 54 removed campaign map linking for the new campaign system
 // version 55 froze current Nicowar to OldNicowar in preperation of new 
nicowar system
-// version 56 rewrote the unit allocation system
+// version 56 rewrote the unit allocation system, and added "hidden" forbidden 
zone to Map
 
 #endif

-- 
Kai Antweiler
_______________________________________________
glob2-devel mailing list
[EMAIL PROTECTED]
http://lists.nongnu.org/mailman/listinfo/glob2-devel

Reply via email to