//Note from Blake: //Iustus wrote this function, it ensures that a new river actually //creates fresh water on the passed plot. Quite useful really //Altouh I veto'd it's use since I like that you don't always //get fresh water starts. // pFreshWaterPlot = the plot we want to give a fresh water river // bool CvMapGenerator::addRiver(CvPlot* pFreshWaterPlot) { FAssertMsg(pFreshWaterPlot != NULL, "NULL plot parameter"); // cannot have a river flow next to water if (pFreshWaterPlot->isWater()) { return false; } // if it already has a fresh water river, then success! we done if (pFreshWaterPlot->isRiver()) { return true; } bool bSuccess = false; // randomize the order of directions std::vector<int> aiShuffle(NUM_CARDINALDIRECTION_TYPES); GC.getGameINLINE().getMapRand().shuffleSequence(aiShuffle, NULL); // make two passes, once for each flow direction of the river int iNWFlowPass = GC.getGameINLINE().getMapRandNum(2, "addRiver"); for (int iPass = 0; !bSuccess && iPass <= 1; iPass++) { // try placing a river edge in each direction, in random order for (int iI = 0; !bSuccess && iI < NUM_CARDINALDIRECTION_TYPES; iI++) { CardinalDirectionTypes eRiverDirection = NO_CARDINALDIRECTION; CvPlot *pRiverPlot = NULL; switch (aiShuffle[iI]) { case CARDINALDIRECTION_NORTH: if (iPass == iNWFlowPass) { pRiverPlot = plotDirection(pFreshWaterPlot->getX_INLINE(), pFreshWaterPlot->getY_INLINE(), DIRECTION_NORTH); eRiverDirection = CARDINALDIRECTION_WEST; } else { pRiverPlot = plotDirection(pFreshWaterPlot->getX_INLINE(), pFreshWaterPlot->getY_INLINE(), DIRECTION_NORTHWEST); eRiverDirection = CARDINALDIRECTION_EAST; } break; case CARDINALDIRECTION_EAST: if (iPass == iNWFlowPass) { pRiverPlot = pFreshWaterPlot; eRiverDirection = CARDINALDIRECTION_NORTH; } else { pRiverPlot = plotDirection(pFreshWaterPlot->getX_INLINE(), pFreshWaterPlot->getY_INLINE(), DIRECTION_NORTH); eRiverDirection = CARDINALDIRECTION_SOUTH; } break; case CARDINALDIRECTION_SOUTH: if (iPass == iNWFlowPass) { pRiverPlot = pFreshWaterPlot; eRiverDirection = CARDINALDIRECTION_WEST; } else { pRiverPlot = plotDirection(pFreshWaterPlot->getX_INLINE(), pFreshWaterPlot->getY_INLINE(), DIRECTION_WEST); eRiverDirection = CARDINALDIRECTION_EAST; } break; case CARDINALDIRECTION_WEST: if (iPass == iNWFlowPass) { pRiverPlot = plotDirection(pFreshWaterPlot->getX_INLINE(), pFreshWaterPlot->getY_INLINE(), DIRECTION_WEST); eRiverDirection = CARDINALDIRECTION_NORTH; } else { pRiverPlot = plotDirection(pFreshWaterPlot->getX_INLINE(), pFreshWaterPlot->getY_INLINE(), DIRECTION_NORTHWEST); eRiverDirection = CARDINALDIRECTION_SOUTH; } break; default: FAssertMsg(false, "invalid cardinal direction"); } if (pRiverPlot != NULL && !pRiverPlot->hasCoastAtSECorner()) { // try to make the river doRiver(pRiverPlot, eRiverDirection, eRiverDirection, -1); // if it succeeded, then we will be a river now! if (pFreshWaterPlot->isRiver()) { bSuccess = true; } } } } return bSuccess; }
// pStartPlot = the plot at whose SE corner the river is starting // void CvMapGenerator::doRiver(CvPlot *pStartPlot, CardinalDirectionTypes eLastCardinalDirection, CardinalDirectionTypes eOriginalCardinalDirection, int iThisRiverID) { if (iThisRiverID == -1) { iThisRiverID = GC.getMapINLINE().getNextRiverID(); GC.getMapINLINE().incrementNextRiverID(); } int iOtherRiverID = pStartPlot->getRiverID(); if (iOtherRiverID != -1 && iOtherRiverID != iThisRiverID) { return; // Another river already exists here; can't branch off of an existing river! } CvPlot *pRiverPlot = NULL; CvPlot *pAdjacentPlot = NULL; CardinalDirectionTypes eBestCardinalDirection = NO_CARDINALDIRECTION; if (eLastCardinalDirection==CARDINALDIRECTION_NORTH) { pRiverPlot = pStartPlot; if (pRiverPlot == NULL) { return; } pAdjacentPlot = plotCardinalDirection(pRiverPlot->getX_INLINE(), pRiverPlot->getY_INLINE(), CARDINALDIRECTION_EAST); if ((pAdjacentPlot == NULL) || pRiverPlot->isWOfRiver() || pRiverPlot->isWater() || pAdjacentPlot->isWater()) { return; } pStartPlot->setRiverID(iThisRiverID); pRiverPlot->setWOfRiver(true, eLastCardinalDirection); pRiverPlot = plotCardinalDirection(pRiverPlot->getX_INLINE(), pRiverPlot->getY_INLINE(), CARDINALDIRECTION_NORTH); } else if (eLastCardinalDirection==CARDINALDIRECTION_EAST) { pRiverPlot = plotCardinalDirection(pStartPlot->getX_INLINE(), pStartPlot->getY_INLINE(), CARDINALDIRECTION_EAST); if (pRiverPlot == NULL) { return; } pAdjacentPlot = plotCardinalDirection(pRiverPlot->getX_INLINE(), pRiverPlot->getY_INLINE(), CARDINALDIRECTION_SOUTH); if ((pAdjacentPlot == NULL) || pRiverPlot->isNOfRiver() || pRiverPlot->isWater() || pAdjacentPlot->isWater()) { return; } pStartPlot->setRiverID(iThisRiverID); pRiverPlot->setNOfRiver(true, eLastCardinalDirection); } else if (eLastCardinalDirection==CARDINALDIRECTION_SOUTH) { pRiverPlot = plotCardinalDirection(pStartPlot->getX_INLINE(), pStartPlot->getY_INLINE(), CARDINALDIRECTION_SOUTH); if (pRiverPlot == NULL) { return; } pAdjacentPlot = plotCardinalDirection(pRiverPlot->getX_INLINE(), pRiverPlot->getY_INLINE(), CARDINALDIRECTION_EAST); if ((pAdjacentPlot == NULL) || pRiverPlot->isWOfRiver() || pRiverPlot->isWater() || pAdjacentPlot->isWater()) { return; } pStartPlot->setRiverID(iThisRiverID); pRiverPlot->setWOfRiver(true, eLastCardinalDirection); } else if (eLastCardinalDirection==CARDINALDIRECTION_WEST) { pRiverPlot = pStartPlot; if (pRiverPlot == NULL) { return; } pAdjacentPlot = plotCardinalDirection(pRiverPlot->getX_INLINE(), pRiverPlot->getY_INLINE(), CARDINALDIRECTION_SOUTH); if ((pAdjacentPlot == NULL) || pRiverPlot->isNOfRiver() || pRiverPlot->isWater() || pAdjacentPlot->isWater()) { return; } pStartPlot->setRiverID(iThisRiverID); pRiverPlot->setNOfRiver(true, eLastCardinalDirection); pRiverPlot = plotCardinalDirection(pRiverPlot->getX_INLINE(), pRiverPlot->getY_INLINE(), CARDINALDIRECTION_WEST); } else { //FAssertMsg(false, "Illegal direction type"); // River is starting here, set the direction in the next step pRiverPlot = pStartPlot; long result = 0; if (gDLL->getPythonIFace()->pythonGetRiverStartCardinalDirection(pRiverPlot, &result) && !gDLL->getPythonIFace()->pythonUsingDefaultImpl()) // Python override { if (result >= 0) { eBestCardinalDirection = ((CardinalDirectionTypes)result); } else { FAssertMsg(false, "python pythonGetRiverStartCardinalDirection() must return >= 0"); } } } if (pRiverPlot == NULL) { return; // The river has flowed off the edge of the map. All is well. } else if (pRiverPlot->hasCoastAtSECorner()) { return; // The river has flowed into the ocean. All is well. } if (eBestCardinalDirection == NO_CARDINALDIRECTION) { int iBestValue = MAX_INT; for (int iI = 0; iI < NUM_CARDINALDIRECTION_TYPES; iI++) { if (getOppositeCardinalDirection((CardinalDirectionTypes)iI) != eOriginalCardinalDirection) { if (getOppositeCardinalDirection((CardinalDirectionTypes)iI) != eLastCardinalDirection) { CvPlot* pAdjacentPlot; pAdjacentPlot = plotCardinalDirection(pRiverPlot->getX_INLINE(), pRiverPlot->getY_INLINE(), ((CardinalDirectionTypes)iI)); if (pAdjacentPlot != NULL) { int iValue = getRiverValueAtPlot(pAdjacentPlot); if (iValue < iBestValue) { iBestValue = iValue; eBestCardinalDirection = (CardinalDirectionTypes)iI; } } } } } } if (eBestCardinalDirection != NO_CARDINALDIRECTION) { if (eOriginalCardinalDirection == NO_CARDINALDIRECTION) { eOriginalCardinalDirection = eBestCardinalDirection; } doRiver(pRiverPlot, eBestCardinalDirection, eOriginalCardinalDirection, iThisRiverID); } }