On 11/17/23 13:31, Leo Wandersleb wrote:
Anyway, who wants to fix a reproducible crash bug so I can finally defeat 3
nicowars without building a single warrior?

    Hi,

    Haven't touched glob2 in ages, and I don't know if it's related to your crash, but I have this patch fixing a nicowar deadlock that's been gathering dust on my HDD since forever…

        Jérôme

--
mailto:[email protected]
http://jeberger.free.fr
Diaspora*: https://framasphere.org/u/jeberger

# HG changeset patch
# User Jerome M. BERGER <[email protected]>
# Date 1285494999 -7200
# Node ID a1a58411a086d70d99cde32798d8d7c08fc37670
# Parent  8f8b9354ad8782530032dc3e89dbcf1bd6f4e979
Fix a deadlock in Nicowar AI.

diff -r 8f8b9354ad87 -r a1a58411a086 src/AINicowar.cpp
--- a/src/AINicowar.cpp	Sat Sep 25 17:54:50 2010 +0200
+++ b/src/AINicowar.cpp	Sun Sep 26 11:56:39 2010 +0200
@@ -2095,9 +2095,10 @@
 	//when a defense flag position is chosen, all units or buildings within range of the flag
 	//have all squares within their range -1, effectivly doing the same as recalculating all
 	//squares excluding those units now covered by a defense flag
-	MapInfo mi(echo);
-	const int w = mi.get_width();
-	const int h = mi.get_height();
+	MapInfo     mi(echo);
+	const int   w      = mi.get_width();
+	const int   h      = mi.get_height();
+	const int   RADIUS = 4;
 	
 	Uint16* counts = new Uint16[w * h];
 	Uint16* buildingGID = new Uint16[w * h];
@@ -2115,7 +2116,7 @@
 		if(unit && unit->underAttackTimer && unit->movement != Unit::MOV_ATTACKING_TARGET && unit->typeNum != EXPLORER && unitGID[(unit->posX+w)%w * h + (unit->posY+h)%h] == NOGUID)
 		{
 			unitGID[(unit->posX+w)%w * h + (unit->posY+h)%h] = unit->gid;
-			modify_points(counts, w, h, (unit->posX+w)%w, (unit->posY+h)%h, 4, 1, locations);
+			modify_points(counts, w, h, (unit->posX+w)%w, (unit->posY+h)%h, RADIUS, 1, locations);
 		}
 	}
 	for(int i=0; i<Building::MAX_COUNT; ++i)
@@ -2126,7 +2127,7 @@
 			int nx = (building->posX - building->type->decLeft + w) %w;
 			int ny = (building->posY - building->type->decTop + h) %h;
 			buildingGID[building->posX * h + building->posY] = building->gid;
-			modify_points(counts, w, h, nx, ny, 4, 1, locations);
+			modify_points(counts, w, h, nx, ny, RADIUS, 1, locations);
 		}
 	}
 	
@@ -2149,7 +2150,14 @@
 				max = n;
 			}
 		}
-		
+
+		// Inserting twice the same flag is a bug and may lead to an
+		// infinite loop. The most probable cause if an insufficient
+		// margin in the loop on all units and buildings below.
+		for (std::vector<int>::const_iterator i = flagLocations.begin();
+		     i != flagLocations.end();
+		     ++i)
+			assert (*i != maxPos);
 		flagLocations.push_back(maxPos);
 		
 		int max_x = maxPos / h;
@@ -2161,16 +2169,19 @@
 		//decrement the values surrounding them. At the same time, count the number of enemy
 		//warriors in this zone
 		int enemy_count = 0;
-		for(int px = -3; px <= 3; ++px)
+		// We need to loop over an area slightly bigger than RADIUS
+		// because buildings are taken into account in an offset
+		// location
+		for(int px = -RADIUS-3; px <= RADIUS+3; ++px)
 		{
 			int nx = (max_x + px + w)%w;
-			for(int py = -3; py<=3; ++py)
+			for(int py = -RADIUS-3; py<=RADIUS+3; ++py)
 			{
 				int ny = (max_y + py + h)%h;
 				if(unitGID[nx * h + ny] != NOGUID)
 				{
 					Unit* unit = echo.player->team->myUnits[Unit::GIDtoID(unitGID[nx * h + ny])];
-					modify_points(counts, w, h, (unit->posX+w)%w, (unit->posY+h)%h, 4, -1, locations);
+					modify_points(counts, w, h, (unit->posX+w)%w, (unit->posY+h)%h, RADIUS, -1, locations);
 					unitGID[nx * h + ny] = NOGUID;
 				}
 				if(buildingGID[nx * h + ny] != NOGBID)
@@ -2178,17 +2189,22 @@
 					Building* building = echo.player->team->myBuildings[Building::GIDtoID(buildingGID[nx * h + ny])];
 					int nx2 = (building->posX - building->type->decLeft + w) %w;
 					int ny2 = (building->posY - building->type->decTop + h) %h;
-					modify_points(counts, w, h, nx2, ny2, 4, -1, locations);
+					modify_points(counts, w, h, nx2, ny2, RADIUS, -1, locations);
 					buildingGID[nx * h + ny] = NOGBID;
 				}
-				
-				Uint16 guid = echo.player->map->getGroundUnit(nx, ny);
-				if(guid != NOGUID && (1<<Unit::GIDtoTeam(guid)) & echo.player->team->enemies)
-				{
-					Unit* unit = echo.player->game->teams[Unit::GIDtoTeam(guid)]->myUnits[Unit::GIDtoID(guid)];
-					if(unit->typeNum == WARRIOR)
+
+				// Take enemy units into account only if they are
+				// within RADIUS of the flag (remember that we loop
+				// over a bigger area).
+				if ((px >= -RADIUS) && (px <= RADIUS) && (py >= -RADIUS) && (py <= RADIUS)) {
+					Uint16 guid = echo.player->map->getGroundUnit(nx, ny);
+					if(guid != NOGUID && (1<<Unit::GIDtoTeam(guid)) & echo.player->team->enemies)
 					{
-						enemy_count += 1;
+						Unit* unit = echo.player->game->teams[Unit::GIDtoTeam(guid)]->myUnits[Unit::GIDtoID(guid)];
+						if(unit->typeNum == WARRIOR)
+						{
+							enemy_count += 1;
+						}
 					}
 				}
 			}
@@ -2348,21 +2364,17 @@
 			int ny = (y + py + h)%h;
 			if(px * px + py * py <= dist * dist)
 			{
-				Uint8 d = (dist-std::max(std::abs(px), std::abs(py)));
-				if(d != 0)
+				if(value>0)
 				{
-					if(value>0)
-					{
-						if(counts[nx * h + ny] == 0)
-							locations.push_back(nx * h + ny);
-						counts[nx * h + ny] += d;
-					}
-					else if(value<0)
-					{
-						counts[nx * h + ny] -= d;
-						if(counts[nx * h + ny] == 0)
-							locations.remove(nx * h + ny);
-					}
+					if(counts[nx * h + ny] == 0)
+						locations.push_back(nx * h + ny);
+					counts[nx * h + ny] += value;
+				}
+				else if(value<0)
+				{
+					counts[nx * h + ny] += value;
+					if(counts[nx * h + ny] == 0)
+						locations.remove(nx * h + ny);
 				}
 			}
 		}

Attachment: OpenPGP_signature.asc
Description: OpenPGP digital signature

_______________________________________________
glob2-devel mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/glob2-devel

Reply via email to