src/town_cmd.cpp
changeset 8488 20a38b2c53f5
parent 8487 9d7e14b019fa
child 8580 b9ad9ca32df2
equal deleted inserted replaced
8487:9d7e14b019fa 8488:20a38b2c53f5
  1715  * @param tile where the house will be built
  1715  * @param tile where the house will be built
  1716  * @return false iff no house can be built at this tile
  1716  * @return false iff no house can be built at this tile
  1717  */
  1717  */
  1718 static bool BuildTownHouse(Town *t, TileIndex tile)
  1718 static bool BuildTownHouse(Town *t, TileIndex tile)
  1719 {
  1719 {
  1720 	int i;
       
  1721 	uint bitmask;
       
  1722 	HouseID house;
       
  1723 	Slope slope;
       
  1724 	uint z;
       
  1725 	uint oneof = 0;
       
  1726 	HouseSpec *hs;
       
  1727 
       
  1728 	/* no house allowed at all, bail out */
  1720 	/* no house allowed at all, bail out */
  1729 	if (!CanBuildHouseHere(tile, false)) return false;
  1721 	if (!CanBuildHouseHere(tile, false)) return false;
  1730 
  1722 
  1731 	/* Above snow? */
  1723 	uint z;
  1732 	slope = GetTileSlope(tile, &z);
  1724 	Slope slope = GetTileSlope(tile, &z);
  1733 
  1725 
  1734 	/* Get the town zone type of the current tile, as well as the climate.
  1726 	/* Get the town zone type of the current tile, as well as the climate.
  1735 	 * This will allow to easily compare with the specs of the new house to build */
  1727 	 * This will allow to easily compare with the specs of the new house to build */
  1736 	{
  1728 	HouseZonesBits rad = GetTownRadiusGroup(t, tile);
  1737 		HouseZonesBits rad = GetTownRadiusGroup(t, tile);
  1729 
  1738 
  1730 	/* Above snow? */
  1739 		int land = _opt.landscape;
  1731 	int land = _opt.landscape;
  1740 		if (land == LT_ARCTIC && z >= _opt.snow_line) land = -1;
  1732 	if (land == LT_ARCTIC && z >= _opt.snow_line) land = -1;
  1741 
  1733 
  1742 		bitmask = (1 << rad) + (1 << (land + 12));
  1734 	uint bitmask = (1 << rad) + (1 << (land + 12));
  1743 	}
       
  1744 
  1735 
  1745 	/* bits 0-4 are used
  1736 	/* bits 0-4 are used
  1746 	 * bits 11-15 are used
  1737 	 * bits 11-15 are used
  1747 	 * bits 5-10 are not used. */
  1738 	 * bits 5-10 are not used. */
  1748 	{
  1739 	HouseID houses[HOUSE_MAX];
  1749 		HouseID houses[HOUSE_MAX];
  1740 	uint num = 0;
  1750 		int num = 0;
  1741 	uint probs[HOUSE_MAX];
  1751 		uint probs[HOUSE_MAX];
  1742 	uint probability_max = 0;
  1752 		uint probability_max = 0;
  1743 
  1753 
  1744 	/* Generate a list of all possible houses that can be built. */
  1754 		/* Generate a list of all possible houses that can be built. */
  1745 	for (uint i = 0; i < HOUSE_MAX; i++) {
  1755 		for (i = 0; i < HOUSE_MAX; i++) {
  1746 		HouseSpec *hs = GetHouseSpecs(i);
  1756 			hs = GetHouseSpecs(i);
  1747 		/* Verify that the candidate house spec matches the current tile status */
  1757 			/* Verify that the candidate house spec matches the current tile status */
  1748 		if ((~hs->building_availability & bitmask) == 0 && hs->enabled) {
  1758 			if ((~hs->building_availability & bitmask) == 0 && hs->enabled) {
  1749 			/* Without NewHouses, all houses have probability '1' */
  1759 				/* Without NewHouses, all houses have probability '1' */
  1750 			uint cur_prob = (_loaded_newgrf_features.has_newhouses ? hs->probability : 1);
  1760 				uint cur_prob = (_loaded_newgrf_features.has_newhouses ? hs->probability : 1);
  1751 			probability_max += cur_prob;
  1761 				probability_max += cur_prob;
  1752 			probs[num] = cur_prob;
  1762 				probs[num] = cur_prob;
  1753 			houses[num++] = (HouseID)i;
  1763 				houses[num++] = (HouseID)i;
  1754 		}
       
  1755 	}
       
  1756 
       
  1757 	uint maxz = GetTileMaxZ(tile);
       
  1758 
       
  1759 	while (probability_max > 0) {
       
  1760 		uint r = RandomRange(probability_max);
       
  1761 		uint i;
       
  1762 		for (i = 0; i < num; i++) {
       
  1763 			if (probs[i] > r) break;
       
  1764 			r -= probs[i];
       
  1765 		}
       
  1766 
       
  1767 		HouseID house = houses[i];
       
  1768 		probability_max -= probs[i];
       
  1769 
       
  1770 		/* remove tested house from the set */
       
  1771 		num--;
       
  1772 		houses[i] = houses[num];
       
  1773 		probs[i] = probs[num];
       
  1774 
       
  1775 		HouseSpec *hs = GetHouseSpecs(house);
       
  1776 
       
  1777 		if (_loaded_newgrf_features.has_newhouses) {
       
  1778 			if (hs->override != 0) {
       
  1779 				house = hs->override;
       
  1780 				hs = GetHouseSpecs(house);
  1764 			}
  1781 			}
  1765 		}
  1782 
  1766 
  1783 			if ((hs->extra_flags & BUILDING_IS_HISTORICAL) && !_generating_world) continue;
  1767 		uint maxz = GetTileMaxZ(tile);
  1784 
  1768 
  1785 			if (HasBit(hs->callback_mask, CBM_HOUSE_ALLOW_CONSTRUCTION)) {
  1769 		while (probability_max > 0) {
  1786 				uint16 callback_res = GetHouseCallback(CBID_HOUSE_ALLOW_CONSTRUCTION, 0, 0, house, t, tile);
  1770 			uint r = RandomRange(probability_max);
  1787 				if (callback_res != CALLBACK_FAILED && callback_res == 0) continue;
  1771 			for (i = 0; i < num; i++) {
       
  1772 				if (probs[i] > r) break;
       
  1773 				r -= probs[i];
       
  1774 			}
  1788 			}
  1775 
  1789 		}
  1776 			house = houses[i];
  1790 
  1777 			probability_max -= probs[i];
  1791 		if (_cur_year < hs->min_date || _cur_year > hs->max_date) continue;
  1778 
  1792 
  1779 			/* remove tested house from the set */
  1793 		/* Special houses that there can be only one of. */
  1780 			num--;
  1794 		uint oneof = 0;
  1781 			houses[i] = houses[num];
  1795 
  1782 			probs[i] = probs[num];
  1796 		if (hs->building_flags & BUILDING_IS_CHURCH) {
  1783 
  1797 			SetBit(oneof, TOWN_HAS_CHURCH);
  1784 			hs = GetHouseSpecs(house);
  1798 		} else if (hs->building_flags & BUILDING_IS_STADIUM) {
  1785 
  1799 			SetBit(oneof, TOWN_HAS_STADIUM);
  1786 			if (_loaded_newgrf_features.has_newhouses) {
  1800 		}
  1787 				if (hs->override != 0) {
  1801 
  1788 					house = hs->override;
  1802 		if (HASBITS(t->flags12 , oneof)) continue;
  1789 					hs = GetHouseSpecs(house);
  1803 
  1790 				}
  1804 		/* Make sure there is no slope? */
  1791 
  1805 		bool noslope = (hs->building_flags & TILE_NOT_SLOPED) != 0;
  1792 				if ((hs->extra_flags & BUILDING_IS_HISTORICAL) && !_generating_world) continue;
  1806 		if (noslope && slope != SLOPE_FLAT) continue;
  1793 
  1807 
  1794 				if (HasBit(hs->callback_mask, CBM_HOUSE_ALLOW_CONSTRUCTION)) {
  1808 		if (hs->building_flags & TILE_SIZE_2x2) {
  1795 					uint16 callback_res = GetHouseCallback(CBID_HOUSE_ALLOW_CONSTRUCTION, 0, 0, house, t, tile);
  1809 			if (!CheckFree2x2Area(tile, maxz, noslope) &&
  1796 					if (callback_res != CALLBACK_FAILED && callback_res == 0) continue;
  1810 					!CheckFree2x2Area(tile += TileDiffXY(-1,  0), maxz, noslope) &&
  1797 				}
  1811 					!CheckFree2x2Area(tile += TileDiffXY( 0, -1), maxz, noslope) &&
       
  1812 					!CheckFree2x2Area(tile += TileDiffXY( 1,  0), maxz, noslope)) {
       
  1813 				/* return to the original tile */
       
  1814 				tile += TileDiffXY(0, 1);
       
  1815 				continue; /* continue the while() loop */
  1798 			}
  1816 			}
  1799 
  1817 		} else if (hs->building_flags & TILE_SIZE_2x1) {
  1800 			if (_cur_year < hs->min_date || _cur_year > hs->max_date) continue;
  1818 			/* 'tile' is already checked above - CanBuildHouseHere() and slope test */
  1801 
  1819 			if (!CheckBuildHouseSameZ(tile + TileDiffXY(1, 0), maxz, noslope)) {
  1802 			/* Special houses that there can be only one of. */
  1820 				if (!CheckBuildHouseSameZ(tile + TileDiffXY(-1, 0), maxz, noslope)) continue;
  1803 			if (hs->building_flags & BUILDING_IS_CHURCH) {
  1821 				tile += TileDiffXY(-1, 0);
  1804 				SetBit(oneof, TOWN_HAS_CHURCH);
  1822 			}
  1805 			} else if (hs->building_flags & BUILDING_IS_STADIUM) {
  1823 		} else if (hs->building_flags & TILE_SIZE_1x2) {
  1806 				SetBit(oneof, TOWN_HAS_STADIUM);
  1824 			if (!CheckBuildHouseSameZ(tile + TileDiffXY(0, 1), maxz, noslope)) {
       
  1825 				if (!CheckBuildHouseSameZ(tile + TileDiffXY(0, -1), maxz, noslope)) continue;
       
  1826 				tile += TileDiffXY(0, -1);
       
  1827 			}
       
  1828 		}
       
  1829 
       
  1830 		/* build the house */
       
  1831 		t->num_houses++;
       
  1832 		IncreaseBuildingCount(t, house);
       
  1833 
       
  1834 		/* Special houses that there can be only one of. */
       
  1835 		t->flags12 |= oneof;
       
  1836 
       
  1837 		byte construction_counter = 0;
       
  1838 		byte construction_stage = 0;
       
  1839 
       
  1840 		if (_generating_world) {
       
  1841 			uint32 r = Random();
       
  1842 
       
  1843 			construction_stage = TOWN_HOUSE_COMPLETED;
       
  1844 			if (Chance16(1, 7)) construction_stage = GB(r, 0, 2);
       
  1845 
       
  1846 			if (construction_stage == TOWN_HOUSE_COMPLETED) {
       
  1847 				ChangePopulation(t, hs->population);
  1807 			} else {
  1848 			} else {
  1808 				oneof = 0;
  1849 				construction_counter = GB(r, 2, 2);
  1809 			}
  1850 			}
  1810 
  1851 		}
  1811 			if (HASBITS(t->flags12 , oneof)) continue;
  1852 
  1812 
  1853 		MakeTownHouse(tile, t->index, construction_counter, construction_stage, house, Random());
  1813 			/* Make sure there is no slope? */
  1854 
  1814 			bool noslope = (hs->building_flags & TILE_NOT_SLOPED) != 0;
  1855 		return true;
  1815 			if (noslope && slope != SLOPE_FLAT) continue;
       
  1816 
       
  1817 			if (hs->building_flags & TILE_SIZE_2x2) {
       
  1818 				if (!CheckFree2x2Area(tile, maxz, noslope) &&
       
  1819 						!CheckFree2x2Area(tile += TileDiffXY(-1,  0), maxz, noslope) &&
       
  1820 						!CheckFree2x2Area(tile += TileDiffXY( 0, -1), maxz, noslope) &&
       
  1821 						!CheckFree2x2Area(tile += TileDiffXY( 1,  0), maxz, noslope)) {
       
  1822 					/* return to the original tile */
       
  1823 					tile += TileDiffXY(0, 1);
       
  1824 					continue; /* continue the while() loop */
       
  1825 				}
       
  1826 			} else if (hs->building_flags & TILE_SIZE_2x1) {
       
  1827 				/* 'tile' is already checked above - CanBuildHouseHere() and slope test */
       
  1828 				if (!CheckBuildHouseSameZ(tile + TileDiffXY(1, 0), maxz, noslope)) {
       
  1829 					if (!CheckBuildHouseSameZ(tile + TileDiffXY(-1, 0), maxz, noslope)) continue;
       
  1830 					tile += TileDiffXY(-1, 0);
       
  1831 				}
       
  1832 			} else if (hs->building_flags & TILE_SIZE_1x2) {
       
  1833 				if (!CheckBuildHouseSameZ(tile + TileDiffXY(0, 1), maxz, noslope)) {
       
  1834 					if (!CheckBuildHouseSameZ(tile + TileDiffXY(0, -1), maxz, noslope)) continue;
       
  1835 					tile += TileDiffXY(0, -1);
       
  1836 				}
       
  1837 			}
       
  1838 
       
  1839 			/* build the house */
       
  1840 			t->num_houses++;
       
  1841 			IncreaseBuildingCount(t, house);
       
  1842 
       
  1843 			/* Special houses that there can be only one of. */
       
  1844 			t->flags12 |= oneof;
       
  1845 
       
  1846 			{
       
  1847 				byte construction_counter = 0, construction_stage = 0;
       
  1848 
       
  1849 				if (_generating_world) {
       
  1850 					uint32 r = Random();
       
  1851 
       
  1852 					construction_stage = TOWN_HOUSE_COMPLETED;
       
  1853 					if (Chance16(1, 7)) construction_stage = GB(r, 0, 2);
       
  1854 
       
  1855 					if (construction_stage == TOWN_HOUSE_COMPLETED) {
       
  1856 						ChangePopulation(t, hs->population);
       
  1857 					} else {
       
  1858 						construction_counter = GB(r, 2, 2);
       
  1859 					}
       
  1860 				}
       
  1861 				MakeTownHouse(tile, t->index, construction_counter, construction_stage, house, Random());
       
  1862 			}
       
  1863 
       
  1864 			return true;
       
  1865 		}
       
  1866 	}
  1856 	}
  1867 
  1857 
  1868 	return false;
  1858 	return false;
  1869 }
  1859 }
  1870 
  1860