comparison src/town_cmd.cpp @ 6571:6777295c2328 draft

(svn r9779) -Feature: Add the possiblity to choose different road patterns for towns to use. Possible patterns are : No Road (not available in scenario editor) Original (for the nostalgics) Better Roads (same as original, but based on distance of 2 tiles instead of one) 2x2 grids 3x3 grids Patch by skiddl13
author belugas <belugas@openttd.org>
date Fri, 04 May 2007 16:27:13 +0000
parents 838badc858d3
children c3aef1e6e3e1
comparison
equal deleted inserted replaced
6570:eacaf5f73afd 6571:6777295c2328
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