Code
1571/// Put Natural Wonders on the map - this could be a LUA script1572void CvMap::DoPlaceNaturalWonders()1573{1574 FeatureTypes eNWFeature = NO_FEATURE;1575 FeatureTypes eFeature;15761577 FeatureTypes featureFuji = NO_FEATURE;1578 FeatureTypes featureEverest = NO_FEATURE;1579 FeatureTypes featureReef = NO_FEATURE;1580 FeatureTypes featureCrater = NO_FEATURE;1581 FeatureTypes featureLake = NO_FEATURE;1582 FeatureTypes featureMesa = NO_FEATURE;1583 FeatureTypes featureVolcano = NO_FEATURE;15841585 int iNumFeatureInfos = GC.getNumFeatureInfos();1586 int nwCount = 0;1587 for(int iFeatureLoop = 0; iFeatureLoop < iNumFeatureInfos; iFeatureLoop++)1588 {1589 eFeature = (FeatureTypes) iFeatureLoop;1590 CvFeatureInfo* feature = GC.getFeatureInfo(eFeature);1591 if(feature && feature->IsNaturalWonder())1592 {1593 eNWFeature = eFeature;15941595 // hackery - this should be more data driven but the engine side isn't15961597 if(strcmp(feature->GetType(), "FEATURE_EVEREST") == 0)1598 {1599 featureEverest = eFeature;1600 }1601 else if(strcmp(feature->GetType(), "FEATURE_CRATER") == 0)1602 {1603 featureCrater = eFeature;1604 }1605 else if(strcmp(feature->GetType(), "FEATURE_TITICACA") == 0)1606 {1607 featureLake = eFeature;1608 }1609 else if(strcmp(feature->GetType(), "FEATURE_FUJI") == 0)1610 {1611 featureFuji = eFeature;1612 }1613 else if(strcmp(feature->GetType(), "FEATURE_MESA") == 0)1614 {1615 featureMesa = eFeature;1616 }1617 else if(strcmp(feature->GetType(), "FEATURE_REEF") == 0)1618 {1619 featureReef = eFeature;1620 }1621 else if(strcmp(feature->GetType(), "FEATURE_VOLCANO") == 0)1622 {1623 featureVolcano = eFeature;1624 }16251626 nwCount++;1627 }1628 }16291630 // No Natural Wonder Feature, abort!1631 if(eNWFeature == NO_FEATURE)1632 {1633 return;1634 }16351636 int iNumNaturalWondersToAdd = getWorldInfo().getNumNaturalWonders();16371638 int iCoastDistance = -1; // Should be in XML1639 int iAnotherNWDistance = 5; // Should be in XML16401641 int iCount = 0;16421643 int iPlotRand;1644 CvPlot* pRandPlot;16451646 int iPlotLoopX;1647 int iPlotLoopY;1648 CvPlot* pLoopPlot;16491650 int iNumMapPlots = numPlots();16511652 // Determine the max number of NWs we can have in a single Area1653 CvArea* pLoopArea;1654 int iLoop;1655 int iNumValidAreas = 0;16561657 int iMaxLatitudeForNW = 65;16581659 int iBottomLatitude;16601661 for(pLoopArea = firstArea(&iLoop); pLoopArea != NULL; pLoopArea = nextArea(&iLoop))1662 {1663 if(!pLoopArea->isWater())1664 {1665 if(!pLoopArea->IsMountains())1666 {1667 iBottomLatitude = pLoopArea->GetAreaMinLatitude();16681669 if(iBottomLatitude <= iMaxLatitudeForNW)1670 {1671 iNumValidAreas++;1672 }1673 }1674 }1675 }16761677 int iMaxNWsOneArea = 2;16781679 // If we have more Natural Wonders than we have Areas then we have to handle things differently - more can be placed in one Area than normal1680 if(iNumNaturalWondersToAdd > iNumValidAreas)1681 {1682 iMaxNWsOneArea = iNumNaturalWondersToAdd - iNumValidAreas + 1;1683 }16841685 while(iNumNaturalWondersToAdd > 0 && iCount < 10000)1686 {1687 iCount++;16881689 iPlotRand = GC.getGame().getJonRandNum(iNumMapPlots, "Randomly Placing Natural Wonders");16901691 pRandPlot = plotByIndex(iPlotRand);16921693 // No Water Tiles1694 if(pRandPlot->isWater())1695 {1696 continue;1697 }16981699 // No River Tiles either (don't want them carved up)1700 if(pRandPlot->isRiver())1701 {1702 continue;1703 }17041705 // No Tiles with Resources1706 if(pRandPlot->getResourceType() != NO_RESOURCE)1707 {1708 continue;1709 }17101711 // No Tiles with Improvements (Goody Huts)1712 if(pRandPlot->getImprovementType() != NO_IMPROVEMENT)1713 {1714 continue;1715 }17161717 // Can't have too many NWs in one Area1718 if(getArea(pRandPlot->getArea())->GetNumNaturalWonders() >= iMaxNWsOneArea)1719 {1720 continue;1721 }17221723 // Has to be in the central band of the map. If the latitude is too extreme we might end up on a islelet surrounded by Ice or something1724 if(pRandPlot->getLatitude() > /*65*/ iMaxLatitudeForNW)1725 {1726 continue;1727 }17281729 // Can't be a starting Plot for ANY player (including Minors)1730 if(pRandPlot->isStartingPlot())1731 {1732 continue;1733 }17341735 bool bValid;17361737 // Does it have to be close to the coast?1738 if(iCoastDistance != -1)1739 {1740 bValid = false;17411742 for(iPlotLoopX = -iCoastDistance; iPlotLoopX <= iCoastDistance; iPlotLoopX++)1743 {1744 for(iPlotLoopY = -iCoastDistance; iPlotLoopY <= iCoastDistance; iPlotLoopY++)1745 {1746 pLoopPlot = plotXYWithRangeCheck(pRandPlot->getX(), pRandPlot->getY(), iPlotLoopX, iPlotLoopY, iCoastDistance);17471748 if(pLoopPlot != NULL)1749 {1750 if(pLoopPlot->isWater())1751 {1752 if(!pLoopPlot->isLake())1753 {1754 // Found a Plot within 2 plots of "the Ocean"1755 bValid = true;1756 break;1757 }1758 }1759 }1760 }17611762 if(bValid)1763 {1764 break;1765 }1766 }17671768 // Plot not within 2 of Ocean1769 if(!bValid)1770 {1771 continue;1772 }1773 }17741775 bValid = true;17761777 // Can't be too close to another Natural Wonder1778 for(iPlotLoopX = -iAnotherNWDistance; iPlotLoopX <= iAnotherNWDistance; iPlotLoopX++)1779 {1780 for(iPlotLoopY = -iAnotherNWDistance; iPlotLoopY <= iAnotherNWDistance; iPlotLoopY++)1781 {1782 pLoopPlot = plotXYWithRangeCheck(pRandPlot->getX(), pRandPlot->getY(), iPlotLoopX, iPlotLoopY, iAnotherNWDistance);17831784 if(pLoopPlot != NULL)1785 {1786 if(pLoopPlot->IsNaturalWonder())1787 {1788 // Found a NW too close1789 bValid = false;1790 break;1791 }1792 }1793 }17941795 if(!bValid)1796 {1797 break;1798 }1799 }18001801 // Natural Wonder too close1802 if(!bValid)1803 {1804 continue;1805 }18061807 // see if we can add the volcano1808 if(featureVolcano != NO_FEATURE)1809 {1810 if(!pRandPlot->isAdjacentToLand())1811 {1812 pRandPlot->setPlotType(PLOT_MOUNTAIN);1813 pRandPlot->setFeatureType(featureVolcano);1814 iNumNaturalWondersToAdd--;1815 featureVolcano = NO_FEATURE; // Prevent this one from being placed again1816 continue;1817 }1818 }18191820 // see if we can add the reef1821 if(featureReef != NO_FEATURE)1822 {1823 if(!pRandPlot->isMountain() && pRandPlot->isAdjacentToShallowWater())1824 {1825 if(pRandPlot->area()->getNumTiles() == 2)1826 {1827 pRandPlot->setPlotType(PLOT_MOUNTAIN);1828 pRandPlot->setFeatureType(featureReef);1829 for(int iI = 0; iI < NUM_DIRECTION_TYPES; ++iI)1830 {1831 CvPlot* pAdjacentPlot = plotDirection(pRandPlot->getX(), pRandPlot->getY(), ((DirectionTypes)iI));1832 if(pAdjacentPlot != NULL)1833 {1834 if(!(pAdjacentPlot->isWater()))1835 {1836 pAdjacentPlot->setPlotType(PLOT_MOUNTAIN);1837 pAdjacentPlot->setFeatureType(featureReef);1838 break;1839 }1840 }1841 }1842 iNumNaturalWondersToAdd--;1843 featureReef = NO_FEATURE; // Prevent this one from being placed again1844 continue;1845 }1846 }1847 }18481849 // see if we can add the lake1850 if(featureLake != NO_FEATURE)1851 {1852 if(pRandPlot->isHills())1853 {1854 int iHillCount = 0;1855 // if we have a couple of hills nearby already1856 for(int iI = 0; iI < NUM_DIRECTION_TYPES; ++iI)1857 {1858 CvPlot* pAdjacentPlot = plotDirection(pRandPlot->getX(), pRandPlot->getY(), ((DirectionTypes)iI));1859 if(pAdjacentPlot != NULL)1860 {1861 if((pAdjacentPlot->isHills()))1862 {1863 iHillCount++;1864 }1865 }1866 }1867 if(iHillCount > 2)1868 {1869 // we are stamping the terrain1870 for(int iI = 0; iI < NUM_DIRECTION_TYPES; ++iI)1871 {1872 CvPlot* pAdjacentPlot = plotDirection(pRandPlot->getX(), pRandPlot->getY(), ((DirectionTypes)iI));1873 if(pAdjacentPlot != NULL)1874 {1875 pAdjacentPlot->setPlotType(PLOT_HILLS);1876 pAdjacentPlot->setTerrainType((TerrainTypes)(GC.getLAND_TERRAIN()));1877 }1878 }1879 pRandPlot->setPlotType(PLOT_MOUNTAIN);1880 pRandPlot->setFeatureType(featureLake);1881 iNumNaturalWondersToAdd--;1882 featureLake = NO_FEATURE; // Prevent this one from being placed again1883 continue;1884 }1885 }1886 }18871888 // see if we can add Everest1889 if(featureEverest != NO_FEATURE)1890 {1891 if(pRandPlot->isMountain() && GC.getGame().getMapRandNum(100, "Natural Wonder") > 75)1892 {1893 // we are stamping the terrain1894 for(int iI = 0; iI < NUM_DIRECTION_TYPES; ++iI)1895 {1896 CvPlot* pAdjacentPlot = plotDirection(pRandPlot->getX(), pRandPlot->getY(), ((DirectionTypes)iI));1897 if(pAdjacentPlot != NULL)1898 {1899 if(iI & 1)1900 {1901 pAdjacentPlot->setPlotType(PLOT_MOUNTAIN);1902 }1903 else1904 {1905 pAdjacentPlot->setPlotType(PLOT_HILLS);1906 pAdjacentPlot->setTerrainType((TerrainTypes)(GC.getLAND_TERRAIN()));1907 }1908 }1909 }1910 pRandPlot->setPlotType(PLOT_MOUNTAIN);1911 pRandPlot->setFeatureType(featureEverest);1912 iNumNaturalWondersToAdd--;1913 featureEverest = NO_FEATURE; // Prevent this one from being placed again1914 continue;1915 }1916 }19171918 // randomly pick one of the other three - but not if this is a coastal plot, because they look terrible there1919 if(pRandPlot->isCoastalLand())1920 {1921 continue;1922 }19231924 int iDice = GC.getGame().getMapRandNum(100, "Natural Wonder");1925 if(iDice > 66)1926 {1927 if(featureCrater != NO_FEATURE)1928 {1929 pRandPlot->setPlotType(PLOT_MOUNTAIN);1930 pRandPlot->setFeatureType(featureCrater);1931 iNumNaturalWondersToAdd--;1932 featureCrater = NO_FEATURE; // Prevent this one from being placed again1933 continue;1934 }1935 }1936 else if(iDice > 25)1937 {1938 if(featureFuji != NO_FEATURE)1939 {1940 pRandPlot->setPlotType(PLOT_MOUNTAIN);1941 pRandPlot->setFeatureType(featureFuji);1942 iNumNaturalWondersToAdd--;1943 featureFuji = NO_FEATURE; // Prevent this one from being placed again1944 continue;1945 }1946 }1947 else1948 {1949 if(featureMesa != NO_FEATURE)1950 {1951 pRandPlot->setPlotType(PLOT_MOUNTAIN);1952 pRandPlot->setFeatureType(featureMesa);1953 iNumNaturalWondersToAdd--;1954 featureMesa = NO_FEATURE; // Prevent this one from being placed again1955 continue;1956 }1957 }1958 }1959}