src/town_cmd.cpp
changeset 6571 6a8a1d0835d9
parent 6560 24106d85dcf5
child 6605 d92f454a00a6
equal deleted inserted replaced
6570:0db336a1b931 6571:6a8a1d0835d9
   553 	{ 0, -1},
   553 	{ 0, -1},
   554 	{ 1,  0},
   554 	{ 1,  0},
   555 	{ 0,  1}
   555 	{ 0,  1}
   556 };
   556 };
   557 
   557 
       
   558 /**
       
   559  * Distance multiplyer
       
   560  * Defines the possible distances between 2 road tiles
       
   561  */
       
   562 enum RoadBlockTitleDistance {
       
   563 	RB_TILE_DIST1 = 1, ///< 1 tile between
       
   564 	RB_TILE_DIST2,     ///< 2 tiles between
       
   565 };
   558 
   566 
   559 static bool GrowTown(Town *t);
   567 static bool GrowTown(Town *t);
   560 
   568 
   561 static void TownTickHandler(Town *t)
   569 static void TownTickHandler(Town *t)
   562 {
   570 {
   603 	if (b & TRACK_BIT_UPPER) r |= ROAD_NE | ROAD_NW;
   611 	if (b & TRACK_BIT_UPPER) r |= ROAD_NE | ROAD_NW;
   604 	if (b & TRACK_BIT_LOWER) r |= ROAD_SE | ROAD_SW;
   612 	if (b & TRACK_BIT_LOWER) r |= ROAD_SE | ROAD_SW;
   605 	if (b & TRACK_BIT_LEFT)  r |= ROAD_NW | ROAD_SW;
   613 	if (b & TRACK_BIT_LEFT)  r |= ROAD_NW | ROAD_SW;
   606 	if (b & TRACK_BIT_RIGHT) r |= ROAD_NE | ROAD_SE;
   614 	if (b & TRACK_BIT_RIGHT) r |= ROAD_NE | ROAD_SE;
   607 	return r;
   615 	return r;
       
   616 }
       
   617 
       
   618 /**
       
   619  * Check if a neighboring tile has a road
       
   620  *
       
   621  * @param tile curent tile
       
   622  * @param dir target direction
       
   623  * @param dist_multi distance multiplyer
       
   624  * @return true if one of the neighboring tiles at the
       
   625  *  given distance is a road tile else
       
   626  */
       
   627 static bool NeighborIsRoadTile(TileIndex tile, int dir, RoadBlockTitleDistance dist_multi)
       
   628 {
       
   629 	return (HASBIT(GetTownRoadMask(TILE_ADD(tile, dist_multi * ToTileIndexDiff(_roadblock_tileadd[dir + 1]))), dir ^ 2) ||
       
   630 			HASBIT(GetTownRoadMask(TILE_ADD(tile, dist_multi * ToTileIndexDiff(_roadblock_tileadd[dir + 3]))), dir ^ 2) ||
       
   631 			HASBIT(GetTownRoadMask(TILE_ADD(tile, dist_multi * (ToTileIndexDiff(_roadblock_tileadd[dir + 1]) + ToTileIndexDiff(_roadblock_tileadd[dir + 2])))), dir) ||
       
   632 			HASBIT(GetTownRoadMask(TILE_ADD(tile, dist_multi * (ToTileIndexDiff(_roadblock_tileadd[dir + 3]) + ToTileIndexDiff(_roadblock_tileadd[dir + 2])))), dir));
   608 }
   633 }
   609 
   634 
   610 static bool IsRoadAllowedHere(TileIndex tile, int dir)
   635 static bool IsRoadAllowedHere(TileIndex tile, int dir)
   611 {
   636 {
   612 	Slope k;
   637 	Slope k;
   628 		}
   653 		}
   629 
   654 
   630 		slope = GetTileSlope(tile, NULL);
   655 		slope = GetTileSlope(tile, NULL);
   631 		if (slope == SLOPE_FLAT) {
   656 		if (slope == SLOPE_FLAT) {
   632 no_slope:
   657 no_slope:
   633 			/* Tile has no slope
   658 			/* Tile has no slope */
   634 			 * Disallow the road if any neighboring tile has a road. */
   659 			switch (_patches.town_layout) {
   635 			if (HASBIT(GetTownRoadMask(TILE_ADD(tile, ToTileIndexDiff(_roadblock_tileadd[dir + 1]))), dir ^ 2) ||
   660 				default: NOT_REACHED();
   636 					HASBIT(GetTownRoadMask(TILE_ADD(tile, ToTileIndexDiff(_roadblock_tileadd[dir + 3]))), dir ^ 2) ||
   661 
   637 					HASBIT(GetTownRoadMask(TILE_ADD(tile, ToTileIndexDiff(_roadblock_tileadd[dir + 1]) + ToTileIndexDiff(_roadblock_tileadd[dir + 2]))), dir) ||
   662 				case TL_ORIGINAL: /* Disallow the road if any neighboring tile has a road (distance: 1) */
   638 					HASBIT(GetTownRoadMask(TILE_ADD(tile, ToTileIndexDiff(_roadblock_tileadd[dir + 3]) + ToTileIndexDiff(_roadblock_tileadd[dir + 2]))), dir))
   663 					return !NeighborIsRoadTile(tile, dir, RB_TILE_DIST1);
   639 				return false;
   664 
   640 
   665 				case TL_BETTER_ROADS: /* Disallow the road if any neighboring tile has a road (distance: 1 and 2). */
   641 			/* Otherwise allow */
   666 					return !(NeighborIsRoadTile(tile, dir, RB_TILE_DIST1) ||
   642 			return true;
   667 							NeighborIsRoadTile(tile, dir, RB_TILE_DIST2));
       
   668 			}
   643 		}
   669 		}
   644 
   670 
   645 		/* If the tile is not a slope in the right direction, then
   671 		/* If the tile is not a slope in the right direction, then
   646 		 * maybe terraform some. */
   672 		 * maybe terraform some. */
   647 		k = (dir & 1) ? SLOPE_NE : SLOPE_NW;
   673 		k = (dir & 1) ? SLOPE_NE : SLOPE_NW;
   696 	if (!TerraformTownTile(tile, ~tileh & 0xF, 1)) {
   722 	if (!TerraformTownTile(tile, ~tileh & 0xF, 1)) {
   697 		TerraformTownTile(tile, tileh & 0xF, 0);
   723 		TerraformTownTile(tile, tileh & 0xF, 0);
   698 	}
   724 	}
   699 }
   725 }
   700 
   726 
       
   727 /**
       
   728  * Generate the RoadBits of a grid tile
       
   729  *
       
   730  * @param t current town
       
   731  * @param tile tile in reference to the town
       
   732  * @return the RoadBit of the current tile regarding
       
   733  *  the selected town layout
       
   734  */
       
   735 static RoadBits GetTownRoadGridElement(Town* t, TileIndex tile)
       
   736 {
       
   737 	/* align the grid to the downtown */
       
   738 	TileIndexDiffC grid_pos = TileIndexToTileIndexDiffC(t->xy, tile); ///< Vector from downtown to the tile
       
   739 
       
   740 	/* lx, ly description:
       
   741 	 * @li lx and ly are true  if the tile is a crossing tile.
       
   742 	 * @li lx xor ly are true  if the tile is a straight road tile.
       
   743 	 * @li lx and ly are false if the tile is a house tile.
       
   744 	 */
       
   745 	bool lx, ly;
       
   746 
       
   747 	switch (_patches.town_layout) {
       
   748 		default: NOT_REACHED();
       
   749 
       
   750 		case TL_2X2_GRID:
       
   751 			lx = ((grid_pos.x % 3) == 0);
       
   752 			ly = ((grid_pos.y % 3) == 0);
       
   753 			break;
       
   754 
       
   755 		case TL_3X3_GRID:
       
   756 			lx = ((grid_pos.x % 4) == 0);
       
   757 			ly = ((grid_pos.y % 4) == 0);
       
   758 			break;
       
   759 	}
       
   760 
       
   761 	/* generate the basic grid structure */
       
   762 	if (!lx && !ly) {         ///< It is a house tile
       
   763 		return ROAD_NONE;
       
   764 	} else if (lx && !ly) {   ///< It is a Y-dir road tile
       
   765 		return ROAD_Y;
       
   766 	} else if (!lx && ly) {   ///< It is a X-dir road tile
       
   767 		return ROAD_X;
       
   768 	} else {                  ///< It is a crossing tile
       
   769 		/* Presets for junctions on slopes
       
   770 		 * not nice :( */
       
   771 		switch (GetTileSlope(tile, NULL)) {
       
   772 			case SLOPE_W:
       
   773 				return ROAD_NW | ROAD_SW;
       
   774 			case SLOPE_S:
       
   775 				return ROAD_SE | ROAD_SW;
       
   776 			case SLOPE_SW:
       
   777 				return ROAD_Y | ROAD_SW;
       
   778 			case SLOPE_E:
       
   779 				return ROAD_NE | ROAD_SE;
       
   780 			case SLOPE_SE:
       
   781 				return ROAD_X | ROAD_SE;
       
   782 			case SLOPE_N:
       
   783 				return ROAD_NW | ROAD_NE;
       
   784 			case SLOPE_NW:
       
   785 				return ROAD_X | ROAD_NW;
       
   786 			case SLOPE_NE:
       
   787 				return ROAD_Y | ROAD_NE;
       
   788 			case SLOPE_STEEP_W:
       
   789 			case SLOPE_STEEP_N:
       
   790 				return ROAD_X;
       
   791 			case SLOPE_STEEP_S:
       
   792 			case SLOPE_STEEP_E:
       
   793 				return ROAD_Y;
       
   794 			default:
       
   795 				return ROAD_ALL;
       
   796 		}
       
   797 	}
       
   798 }
       
   799 
       
   800 /**
       
   801  * Check there are enougth neighbor house tiles next to the current tile
       
   802  *
       
   803  * @param tile current tile
       
   804  * @return true if there are more than 2 house tiles next
       
   805  *  to the current one
       
   806  */
       
   807 static bool NeighborsAreHouseTiles(TileIndex tile)
       
   808 {
       
   809 	uint counter = 0; ///< counts the house neighbor tiles
       
   810 
       
   811 	/* We can't look further than that. */
       
   812 	if (TileX(tile) < 1 || TileY(tile) < 1) {
       
   813 		return false;
       
   814 	}
       
   815 
       
   816 	/* Check the tiles E,N,W and S of the current tile. */
       
   817 	for (uint i = 0; i < 4; i++) {
       
   818 		if (IsTileType(TILE_ADD(tile, ToTileIndexDiff(_roadblock_tileadd[i])), MP_HOUSE)) {
       
   819 			counter++;
       
   820 		}
       
   821 
       
   822 		/* If there are enougth neighbor's stop it here */
       
   823 		if (counter >= 3) {
       
   824 			return true;
       
   825 		}
       
   826 	}
       
   827 	return false;
       
   828 }
       
   829 
       
   830 /**
       
   831  * Grows the given town.
       
   832  * There are at the moment 3 possible way's for
       
   833  * the town expansion:
       
   834  * @li Generate a random tile and check if there is a road allowed
       
   835  * 	@li TL_ORIGINAL
       
   836  * 	@li TL_BETTER_ROADS
       
   837  * @li Check if the town geometry allows a road and which one
       
   838  * 	@li TL_2X2_GRID
       
   839  * 	@li TL_3X3_GRID
       
   840  * @li Forbid roads, only build houses
       
   841  * 	@li TL_NO_ROADS
       
   842  *
       
   843  * @param tile_ptr current tile
       
   844  * @param mask current tiles RoadBits
       
   845  * @param block road block
       
   846  * @param t1 current town
       
   847  */
   701 static void GrowTownInTile(TileIndex* tile_ptr, RoadBits mask, int block, Town* t1)
   848 static void GrowTownInTile(TileIndex* tile_ptr, RoadBits mask, int block, Town* t1)
   702 {
   849 {
   703 	RoadBits rcmd;
   850 	RoadBits rcmd;
   704 	TileIndex tmptile;
   851 	TileIndex tmptile;
   705 	DiagDirection i;
   852 	DiagDirection i;
   718 
   865 
   719 		/* Remove hills etc */
   866 		/* Remove hills etc */
   720 		LevelTownLand(tile);
   867 		LevelTownLand(tile);
   721 
   868 
   722 		/* Is a road allowed here? */
   869 		/* Is a road allowed here? */
   723 		if (!IsRoadAllowedHere(tile, block)) return;
   870 		switch (_patches.town_layout) {
   724 
   871 			default: NOT_REACHED();
   725 		/* Randomize new road block numbers */
   872 
   726 		a = block;
   873 			case TL_NO_ROADS: /* Disallow Roads */
   727 		b = block ^ 2;
       
   728 		if (CHANCE16(1, 4)) {
       
   729 			do {
       
   730 				a = GB(Random(), 0, 2);
       
   731 			} while (a == b);
       
   732 		}
       
   733 
       
   734 		if (!IsRoadAllowedHere(TILE_ADD(tile, ToTileIndexDiff(_roadblock_tileadd[a])), a)) {
       
   735 			/* A road is not allowed to continue the randomized road,
       
   736 			 *   return if the road we're trying to build is curved. */
       
   737 			if (a != (b ^ 2)) return;
       
   738 
       
   739 			/* Return if neither side of the new road is a house */
       
   740 			if (!IsTileType(TILE_ADD(tile, ToTileIndexDiff(_roadblock_tileadd[a + 1])), MP_HOUSE) &&
       
   741 					!IsTileType(TILE_ADD(tile, ToTileIndexDiff(_roadblock_tileadd[a + 3])), MP_HOUSE))
       
   742 				return;
   874 				return;
   743 
   875 
   744 			/* That means that the road is only allowed if there is a house
   876 			case TL_3X3_GRID:
   745 			 *  at any side of the new road. */
   877 			case TL_2X2_GRID:
   746 		}
   878 				rcmd = GetTownRoadGridElement(t1, tile);
   747 		rcmd = (RoadBits)((1 << a) + (1 << b));
   879 				if (rcmd == ROAD_NONE) {
       
   880 					return;
       
   881 				}
       
   882 				break;
       
   883 
       
   884 			case TL_BETTER_ROADS:
       
   885 			case TL_ORIGINAL:
       
   886 				if (!IsRoadAllowedHere(tile, block)) {
       
   887 					return;
       
   888 				}
       
   889 
       
   890 				/* Randomize new road block numbers */
       
   891 				a = block;
       
   892 				b = block ^ 2;
       
   893 				if (CHANCE16(1, 4)) {
       
   894 					do {
       
   895 						a = GB(Random(), 0, 2);
       
   896 					} while (a == b);
       
   897 				}
       
   898 
       
   899 				if (!IsRoadAllowedHere(TILE_ADD(tile, ToTileIndexDiff(_roadblock_tileadd[a])), a)) {
       
   900 					/* A road is not allowed to continue the randomized road,
       
   901 					 *   return if the road we're trying to build is curved. */
       
   902 					if (a != (b ^ 2)) {
       
   903 						return;
       
   904 					}
       
   905 
       
   906 					/* Return if neither side of the new road is a house */
       
   907 					if (!IsTileType(TILE_ADD(tile, ToTileIndexDiff(_roadblock_tileadd[a + 1])), MP_HOUSE) &&
       
   908 							!IsTileType(TILE_ADD(tile, ToTileIndexDiff(_roadblock_tileadd[a + 3])), MP_HOUSE)) {
       
   909 						return;
       
   910 					}
       
   911 
       
   912 					/* That means that the road is only allowed if there is a house
       
   913 					 *  at any side of the new road. */
       
   914 				}
       
   915 
       
   916 				rcmd = (RoadBits)((1 << a) + (1 << b));
       
   917 				break;
       
   918 		}
   748 
   919 
   749 	} else if (block < 5 && !HASBIT(mask, block ^ 2)) {
   920 	} else if (block < 5 && !HASBIT(mask, block ^ 2)) {
   750 		/* Continue building on a partial road.
   921 		/* Continue building on a partial road.
   751 		 * Always OK. */
   922 		 * Always OK. */
   752 		_grow_town_result = 0;
   923 		_grow_town_result = 0;
   753 		rcmd = (RoadBits)(1 << (block ^ 2));
   924 
       
   925 		switch (_patches.town_layout) {
       
   926 			default: NOT_REACHED();
       
   927 
       
   928 			case TL_NO_ROADS: /* Disallow Roads */
       
   929 				return;
       
   930 
       
   931 			case TL_3X3_GRID:
       
   932 			case TL_2X2_GRID:
       
   933 			 	rcmd = GetTownRoadGridElement(t1, tile);
       
   934 				break;
       
   935 
       
   936 			case TL_BETTER_ROADS:
       
   937 			case TL_ORIGINAL:
       
   938 				rcmd = (RoadBits)(1 << (block ^ 2));
       
   939 				break;
       
   940 		}
   754 	} else {
   941 	} else {
   755 		int i;
   942 		int i;
       
   943 		bool allow_house = false;
       
   944 		TileIndex tmptile2;
   756 
   945 
   757 		/* Reached a tunnel/bridge? Then continue at the other side of it. */
   946 		/* Reached a tunnel/bridge? Then continue at the other side of it. */
   758 		if (IsTileType(tile, MP_TUNNELBRIDGE)) {
   947 		if (IsTileType(tile, MP_TUNNELBRIDGE)) {
   759 			if (IsTunnel(tile) && GetTunnelTransportType(tile) == TRANSPORT_ROAD) {
   948 			if (IsTunnel(tile) && GetTunnelTransportType(tile) == TRANSPORT_ROAD) {
   760 				*tile_ptr = GetOtherTunnelEnd(tile);
   949 				*tile_ptr = GetOtherTunnelEnd(tile);
   773 		tmptile = TILE_ADD(tile, ToTileIndexDiff(_roadblock_tileadd[i]));
   962 		tmptile = TILE_ADD(tile, ToTileIndexDiff(_roadblock_tileadd[i]));
   774 
   963 
   775 		/* Don't do it if it reaches to water. */
   964 		/* Don't do it if it reaches to water. */
   776 		if (IsClearWaterTile(tmptile)) return;
   965 		if (IsClearWaterTile(tmptile)) return;
   777 
   966 
   778 		/* Build a house at the edge. 60% chance or
   967 		switch (_patches.town_layout) {
   779 		 *  always ok if no road allowed. */
   968 			default: NOT_REACHED();
   780 		if (!IsRoadAllowedHere(tmptile, i) || CHANCE16(6, 10)) {
   969 
   781 			/* But not if there already is a house there. */
   970 			case TL_NO_ROADS:
       
   971 				allow_house = true;
       
   972 				break;
       
   973 
       
   974 			case TL_3X3_GRID: /* Use 2x2 grid afterwards! */
       
   975 				/* Fill gap if house has enougth neighbors */
       
   976 				tmptile2 = TILE_ADD(tmptile, ToTileIndexDiff(_roadblock_tileadd[i]));
       
   977 				if (NeighborsAreHouseTiles(tmptile2) && BuildTownHouse(t1, tmptile2)) {
       
   978 					_grow_town_result = -1;
       
   979 				}
       
   980 
       
   981 			case TL_2X2_GRID:
       
   982 				rcmd = GetTownRoadGridElement(t1, tmptile);
       
   983 				allow_house = (rcmd == ROAD_NONE);
       
   984 				break;
       
   985 
       
   986 			case TL_BETTER_ROADS: /* Use original afterwards! */
       
   987 				/* Fill gap if house has enougth neighbors */
       
   988 				tmptile2 = TILE_ADD(tmptile, ToTileIndexDiff(_roadblock_tileadd[i]));
       
   989 				if (NeighborsAreHouseTiles(tmptile2) && BuildTownHouse(t1, tmptile2)) {
       
   990 					_grow_town_result = -1;
       
   991 				}
       
   992 
       
   993 			case TL_ORIGINAL:
       
   994 				 /* Allow a house at the edge. 60% chance or
       
   995 				  * always ok if no road allowed. */
       
   996 				allow_house = (!IsRoadAllowedHere(tmptile, i) || CHANCE16(6, 10));
       
   997 				break;
       
   998 		}
       
   999 
       
  1000 
       
  1001 		if (allow_house) {
       
  1002 			/* Build a house, but not if there already is a house there. */
   782 			if (!IsTileType(tmptile, MP_HOUSE)) {
  1003 			if (!IsTileType(tmptile, MP_HOUSE)) {
   783 				/* Level the land if possible */
  1004 				/* Level the land if possible */
   784 				LevelTownLand(tmptile);
  1005 				LevelTownLand(tmptile);
   785 
  1006 
   786 				/* And build a house.
  1007 				/* And build a house.
   787 				 * Set result to -1 if we managed to build it. */
  1008 				 * Set result to -1 if we managed to build it. */
   788 				if (BuildTownHouse(t1, tmptile)) _grow_town_result = -1;
  1009 				if (BuildTownHouse(t1, tmptile)) {
       
  1010 					_grow_town_result = -1;
       
  1011 				}
   789 			}
  1012 			}
   790 			return;
  1013 			return;
   791 		}
  1014 		}
   792 
  1015 
   793 		_grow_town_result = 0;
  1016 		_grow_town_result = 0;
   809 build_road_and_exit:
  1032 build_road_and_exit:
   810 			if (!CmdFailed(DoCommand(tile, rcmd, t1->index, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD))) {
  1033 			if (!CmdFailed(DoCommand(tile, rcmd, t1->index, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD))) {
   811 				_grow_town_result = -1;
  1034 				_grow_town_result = -1;
   812 			}
  1035 			}
   813 			return;
  1036 			return;
       
  1037 	}
       
  1038 
       
  1039 	/* Check if the bridge is in the right direction */
       
  1040 	if ((rcmd == ROAD_X && (i == DIAGDIR_NW || i == DIAGDIR_SE)) ||
       
  1041 			(rcmd == ROAD_Y && (i == DIAGDIR_NE || i == DIAGDIR_SW))) {
       
  1042 		goto build_road_and_exit;
   814 	}
  1043 	}
   815 
  1044 
   816 	tmptile = tile;
  1045 	tmptile = tile;
   817 
  1046 
   818 	/* Now it contains the direction of the slope */
  1047 	/* Now it contains the direction of the slope */
   853 {
  1082 {
   854 	int block = 5; // special case
  1083 	int block = 5; // special case
   855 
  1084 
   856 	TILE_ASSERT(tile);
  1085 	TILE_ASSERT(tile);
   857 
  1086 
   858 	/* Number of times to search. */
  1087 	/* Number of times to search.
   859 	_grow_town_result = 10 + t->num_houses * 4 / 9;
  1088 	 * Better roads, 2X2 and 3X3 grid grow quite fast so we give
       
  1089 	 * them a little handicap. */
       
  1090 	switch (_patches.town_layout) {
       
  1091 		case TL_BETTER_ROADS:
       
  1092 			_grow_town_result = 10 + t->num_houses * 2 / 9;
       
  1093 			break;
       
  1094 
       
  1095 		case TL_3X3_GRID:
       
  1096 		case TL_2X2_GRID:
       
  1097 			_grow_town_result = 10 + t->num_houses * 1 / 9;
       
  1098 			break;
       
  1099 
       
  1100 		default:
       
  1101 			_grow_town_result = 10 + t->num_houses * 4 / 9;
       
  1102 			break;
       
  1103 	}
   860 
  1104 
   861 	do {
  1105 	do {
   862 		/* Get a bitmask of the road blocks on a tile */
  1106 		/* Get a bitmask of the road blocks on a tile */
   863 		RoadBits mask = GetTownRoadMask(tile);
  1107 		RoadBits mask = GetTownRoadMask(tile);
   864 
  1108 
   927 		{-2,  2},
  1171 		{-2,  2},
   928 		{ 2,  2},
  1172 		{ 2,  2},
   929 		{ 2, -2},
  1173 		{ 2, -2},
   930 		{ 0,  0}
  1174 		{ 0,  0}
   931 	};
  1175 	};
       
  1176 
       
  1177 	/* Let the town be a ghost town
       
  1178 	 * The player wanted it in such a way. Thus there he has it. ;)
       
  1179 	 * Never reached in editor mode. */
       
  1180 	if (_patches.town_layout == TL_NO_ROADS) {
       
  1181 		return false;
       
  1182 	}
   932 
  1183 
   933 	/* Current player is a town */
  1184 	/* Current player is a town */
   934 	old_player = _current_player;
  1185 	old_player = _current_player;
   935 	_current_player = OWNER_TOWN;
  1186 	_current_player = OWNER_TOWN;
   936 
  1187