1
0
Fork 0

(svn r12062) -Fix: possible deadlock when there are no houses available to build at given tile

-Fix: houses with zero probability could be built
release/0.6
smatz 2008-02-04 23:24:22 +00:00
parent 23c669fe50
commit 146779b158
1 changed files with 57 additions and 55 deletions

View File

@ -1748,7 +1748,7 @@ static bool BuildTownHouse(Town *t, TileIndex tile)
{ {
HouseID houses[HOUSE_MAX]; HouseID houses[HOUSE_MAX];
int num = 0; int num = 0;
uint cumulative_probs[HOUSE_MAX]; uint probs[HOUSE_MAX];
uint probability_max = 0; uint probability_max = 0;
/* Generate a list of all possible houses that can be built. */ /* Generate a list of all possible houses that can be built. */
@ -1756,25 +1756,30 @@ static bool BuildTownHouse(Town *t, TileIndex tile)
hs = GetHouseSpecs(i); hs = GetHouseSpecs(i);
/* Verify that the candidate house spec matches the current tile status */ /* Verify that the candidate house spec matches the current tile status */
if ((~hs->building_availability & bitmask) == 0 && hs->enabled) { if ((~hs->building_availability & bitmask) == 0 && hs->enabled) {
if (_loaded_newgrf_features.has_newhouses) { /* Without NewHouses, all houses have probability '1' */
probability_max += hs->probability; uint cur_prob = (_loaded_newgrf_features.has_newhouses ? hs->probability : 1);
cumulative_probs[num] = probability_max; probability_max += cur_prob;
} probs[num] = cur_prob;
houses[num++] = (HouseID)i; houses[num++] = (HouseID)i;
} }
} }
uint maxz = GetTileMaxZ(tile); uint maxz = GetTileMaxZ(tile);
for (;;) { while (probability_max > 0) {
if (_loaded_newgrf_features.has_newhouses) {
uint r = RandomRange(probability_max); uint r = RandomRange(probability_max);
for (i = 0; i < num; i++) if (cumulative_probs[i] >= r) break; for (i = 0; i < num; i++) {
if (probs[i] > r) break;
r -= probs[i];
}
house = houses[i]; house = houses[i];
} else { probability_max -= probs[i];
house = houses[RandomRange(num)];
} /* remove tested house from the set */
num--;
houses[i] = houses[num];
probs[i] = probs[num];
hs = GetHouseSpecs(house); hs = GetHouseSpecs(house);
@ -1810,35 +1815,28 @@ static bool BuildTownHouse(Town *t, TileIndex tile)
if (noslope && slope != SLOPE_FLAT) continue; if (noslope && slope != SLOPE_FLAT) continue;
if (hs->building_flags & TILE_SIZE_2x2) { if (hs->building_flags & TILE_SIZE_2x2) {
if (CheckFree2x2Area(tile, maxz, noslope) || if (!CheckFree2x2Area(tile, maxz, noslope) &&
CheckFree2x2Area(tile += TileDiffXY(-1, 0), maxz, noslope) || !CheckFree2x2Area(tile += TileDiffXY(-1, 0), maxz, noslope) &&
CheckFree2x2Area(tile += TileDiffXY( 0, -1), maxz, noslope) || !CheckFree2x2Area(tile += TileDiffXY( 0, -1), maxz, noslope) &&
CheckFree2x2Area(tile += TileDiffXY( 1, 0), maxz, noslope)) { !CheckFree2x2Area(tile += TileDiffXY( 1, 0), maxz, noslope)) {
break; /* return to the original tile */
}
/* return to original tile */
tile += TileDiffXY(0, 1); tile += TileDiffXY(0, 1);
continue; /* continue the while() loop */
}
} else if (hs->building_flags & TILE_SIZE_2x1) { } else if (hs->building_flags & TILE_SIZE_2x1) {
/* 'tile' is already checked above - CanBuildHouseHere() and slope test */ /* 'tile' is already checked above - CanBuildHouseHere() and slope test */
if (CheckBuildHouseSameZ(tile + TileDiffXY(1, 0), maxz, noslope)) break; if (!CheckBuildHouseSameZ(tile + TileDiffXY(1, 0), maxz, noslope)) {
if (!CheckBuildHouseSameZ(tile + TileDiffXY(-1, 0), maxz, noslope)) continue;
if (CheckBuildHouseSameZ(tile + TileDiffXY(-1, 0), maxz, noslope)) {
tile += TileDiffXY(-1, 0); tile += TileDiffXY(-1, 0);
break;
} }
} else if (hs->building_flags & TILE_SIZE_1x2) { } else if (hs->building_flags & TILE_SIZE_1x2) {
if (CheckBuildHouseSameZ(tile + TileDiffXY(0, 1), maxz, noslope)) break; if (!CheckBuildHouseSameZ(tile + TileDiffXY(0, 1), maxz, noslope)) {
if (!CheckBuildHouseSameZ(tile + TileDiffXY(0, -1), maxz, noslope)) continue;
if (CheckBuildHouseSameZ(tile + TileDiffXY(0, -1), maxz, noslope)) {
tile += TileDiffXY(0, -1); tile += TileDiffXY(0, -1);
break;
}
} else {
break;
}
} }
} }
/* build the house */
t->num_houses++; t->num_houses++;
IncreaseBuildingCount(t, house); IncreaseBuildingCount(t, house);
@ -1864,6 +1862,10 @@ static bool BuildTownHouse(Town *t, TileIndex tile)
} }
return true; return true;
}
}
return false;
} }