550 * @param flags of operation to conduct |
564 * @param flags of operation to conduct |
551 * @param p2 unused |
565 * @param p2 unused |
552 */ |
566 */ |
553 CommandCost CmdClearArea(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
567 CommandCost CmdClearArea(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
554 { |
568 { |
555 CommandCost ret, money; |
|
556 CommandCost cost(EXPENSES_CONSTRUCTION); |
|
557 int ex; |
|
558 int ey; |
|
559 int sx, sy; |
|
560 int x, y; |
|
561 bool success = false; |
|
562 |
|
563 if (p1 >= MapSize()) return CMD_ERROR; |
569 if (p1 >= MapSize()) return CMD_ERROR; |
564 |
570 |
565 /* make sure sx,sy are smaller than ex,ey */ |
571 /* make sure sx,sy are smaller than ex,ey */ |
566 ex = TileX(tile); |
572 int ex = TileX(tile); |
567 ey = TileY(tile); |
573 int ey = TileY(tile); |
568 sx = TileX(p1); |
574 int sx = TileX(p1); |
569 sy = TileY(p1); |
575 int sy = TileY(p1); |
570 if (ex < sx) Swap(ex, sx); |
576 if (ex < sx) Swap(ex, sx); |
571 if (ey < sy) Swap(ey, sy); |
577 if (ey < sy) Swap(ey, sy); |
572 |
578 |
573 money.AddCost(GetAvailableMoneyForCommand()); |
579 Money money = GetAvailableMoneyForCommand(); |
574 |
580 CommandCost cost(EXPENSES_CONSTRUCTION); |
575 for (x = sx; x <= ex; ++x) { |
581 bool success = false; |
576 for (y = sy; y <= ey; ++y) { |
582 |
577 ret = DoCommand(TileXY(x, y), 0, 0, flags & ~DC_EXEC, CMD_LANDSCAPE_CLEAR); |
583 for (int x = sx; x <= ex; ++x) { |
|
584 for (int y = sy; y <= ey; ++y) { |
|
585 CommandCost ret = DoCommand(TileXY(x, y), 0, 0, flags & ~DC_EXEC, CMD_LANDSCAPE_CLEAR); |
578 if (CmdFailed(ret)) continue; |
586 if (CmdFailed(ret)) continue; |
579 success = true; |
587 success = true; |
580 |
588 |
581 if (flags & DC_EXEC) { |
589 if (flags & DC_EXEC) { |
582 money.AddCost(-ret.GetCost()); |
590 money -= ret.GetCost(); |
583 if (ret.GetCost() > 0 && money.GetCost() < 0) { |
591 if (ret.GetCost() > 0 && money < 0) { |
584 _additional_cash_required = ret.GetCost(); |
592 _additional_cash_required = ret.GetCost(); |
585 return cost; |
593 return cost; |
586 } |
594 } |
587 DoCommand(TileXY(x, y), 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
595 DoCommand(TileXY(x, y), 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
588 |
596 |
607 #define TILELOOP_ASSERTMASK ((TILELOOP_SIZE - 1) + ((TILELOOP_SIZE - 1) << MapLogX())) |
615 #define TILELOOP_ASSERTMASK ((TILELOOP_SIZE - 1) + ((TILELOOP_SIZE - 1) << MapLogX())) |
608 #define TILELOOP_CHKMASK (((1 << (MapLogX() - TILELOOP_BITS))-1) << TILELOOP_BITS) |
616 #define TILELOOP_CHKMASK (((1 << (MapLogX() - TILELOOP_BITS))-1) << TILELOOP_BITS) |
609 |
617 |
610 void RunTileLoop() |
618 void RunTileLoop() |
611 { |
619 { |
612 TileIndex tile; |
620 TileIndex tile = _cur_tileloop_tile; |
613 uint count; |
621 |
614 |
622 assert((tile & ~TILELOOP_ASSERTMASK) == 0); |
615 tile = _cur_tileloop_tile; |
623 uint count = (MapSizeX() / TILELOOP_SIZE) * (MapSizeY() / TILELOOP_SIZE); |
616 |
|
617 assert( (tile & ~TILELOOP_ASSERTMASK) == 0); |
|
618 count = (MapSizeX() / TILELOOP_SIZE) * (MapSizeY() / TILELOOP_SIZE); |
|
619 do { |
624 do { |
620 _tile_type_procs[GetTileType(tile)]->tile_loop_proc(tile); |
625 _tile_type_procs[GetTileType(tile)]->tile_loop_proc(tile); |
621 |
626 |
622 if (TileX(tile) < MapSizeX() - TILELOOP_SIZE) { |
627 if (TileX(tile) < MapSizeX() - TILELOOP_SIZE) { |
623 tile += TILELOOP_SIZE; // no overflow |
628 tile += TILELOOP_SIZE; // no overflow |
624 } else { |
629 } else { |
625 tile = TILE_MASK(tile - TILELOOP_SIZE * (MapSizeX() / TILELOOP_SIZE - 1) + TileDiffXY(0, TILELOOP_SIZE)); /* x would overflow, also increase y */ |
630 tile = TILE_MASK(tile - TILELOOP_SIZE * (MapSizeX() / TILELOOP_SIZE - 1) + TileDiffXY(0, TILELOOP_SIZE)); /* x would overflow, also increase y */ |
626 } |
631 } |
627 } while (--count); |
632 } while (--count != 0); |
628 assert( (tile & ~TILELOOP_ASSERTMASK) == 0); |
633 assert((tile & ~TILELOOP_ASSERTMASK) == 0); |
629 |
634 |
630 tile += 9; |
635 tile += 9; |
631 if (tile & TILELOOP_CHKMASK) |
636 if (tile & TILELOOP_CHKMASK) { |
632 tile = (tile + MapSizeX()) & TILELOOP_ASSERTMASK; |
637 tile = (tile + MapSizeX()) & TILELOOP_ASSERTMASK; |
|
638 } |
633 _cur_tileloop_tile = tile; |
639 _cur_tileloop_tile = tile; |
634 } |
640 } |
635 |
641 |
636 void InitializeLandscape() |
642 void InitializeLandscape() |
637 { |
643 { |
638 uint maxx = MapMaxX(); |
644 uint maxx = MapMaxX(); |
639 uint maxy = MapMaxY(); |
645 uint maxy = MapMaxY(); |
640 uint sizex = MapSizeX(); |
646 uint sizex = MapSizeX(); |
641 uint x; |
647 |
642 uint y; |
648 uint y; |
643 |
|
644 for (y = 0; y < maxy; y++) { |
649 for (y = 0; y < maxy; y++) { |
|
650 uint x; |
645 for (x = 0; x < maxx; x++) { |
651 for (x = 0; x < maxx; x++) { |
646 MakeClear(sizex * y + x, CLEAR_GRASS, 3); |
652 MakeClear(sizex * y + x, CLEAR_GRASS, 3); |
647 SetTileHeight(sizex * y + x, 0); |
653 SetTileHeight(sizex * y + x, 0); |
648 SetTropicZone(sizex * y + x, TROPICZONE_NORMAL); |
654 SetTropicZone(sizex * y + x, TROPICZONE_NORMAL); |
649 ClearBridgeMiddle(sizex * y + x); |
655 ClearBridgeMiddle(sizex * y + x); |
650 } |
656 } |
651 MakeVoid(sizex * y + x); |
657 MakeVoid(sizex * y + x); |
652 } |
658 } |
653 for (x = 0; x < sizex; x++) MakeVoid(sizex * y + x); |
659 for (uint x = 0; x < sizex; x++) MakeVoid(sizex * y + x); |
654 } |
660 } |
655 |
661 |
656 static const byte _genterrain_tbl_1[5] = { 10, 22, 33, 37, 4 }; |
662 static const byte _genterrain_tbl_1[5] = { 10, 22, 33, 37, 4 }; |
657 static const byte _genterrain_tbl_2[5] = { 0, 0, 0, 0, 33 }; |
663 static const byte _genterrain_tbl_2[5] = { 0, 0, 0, 0, 33 }; |
658 |
664 |
659 static void GenerateTerrain(int type, int flag) |
665 static void GenerateTerrain(int type, uint flag) |
660 { |
666 { |
661 uint32 r; |
667 uint32 r = Random(); |
662 uint x; |
668 |
663 uint y; |
669 const Sprite *templ = GetSprite((((r >> 24) * _genterrain_tbl_1[type]) >> 8) + _genterrain_tbl_2[type] + 4845); |
664 uint w; |
670 |
665 uint h; |
671 uint x = r & MapMaxX(); |
666 const Sprite* templ; |
672 uint y = (r >> MapLogX()) & MapMaxY(); |
667 const byte *p; |
|
668 Tile* tile; |
|
669 byte direction; |
|
670 |
|
671 r = Random(); |
|
672 templ = GetSprite((((r >> 24) * _genterrain_tbl_1[type]) >> 8) + _genterrain_tbl_2[type] + 4845); |
|
673 |
|
674 x = r & MapMaxX(); |
|
675 y = (r >> MapLogX()) & MapMaxY(); |
|
676 |
|
677 |
673 |
678 if (x < 2 || y < 2) return; |
674 if (x < 2 || y < 2) return; |
679 |
675 |
680 direction = GB(r, 22, 2); |
676 DiagDirection direction = (DiagDirection)GB(r, 22, 2); |
681 if (direction & 1) { |
677 uint w = templ->width; |
682 w = templ->height; |
678 uint h = templ->height; |
683 h = templ->width; |
679 |
684 } else { |
680 if (DiagDirToAxis(direction) == AXIS_Y) Swap(w, h); |
685 w = templ->width; |
681 |
686 h = templ->height; |
682 const byte *p = templ->data; |
687 } |
683 |
688 p = templ->data; |
684 if ((flag & 4) != 0) { |
689 |
|
690 if (flag & 4) { |
|
691 uint xw = x * MapSizeY(); |
685 uint xw = x * MapSizeY(); |
692 uint yw = y * MapSizeX(); |
686 uint yw = y * MapSizeX(); |
693 uint bias = (MapSizeX() + MapSizeY()) * 16; |
687 uint bias = (MapSizeX() + MapSizeY()) * 16; |
694 |
688 |
695 switch (flag & 3) { |
689 switch (flag & 3) { |
|
690 default: NOT_REACHED(); |
696 case 0: |
691 case 0: |
697 if (xw + yw > MapSize() - bias) return; |
692 if (xw + yw > MapSize() - bias) return; |
698 break; |
693 break; |
699 |
694 |
700 case 1: |
695 case 1: |
712 } |
707 } |
713 |
708 |
714 if (x + w >= MapMaxX() - 1) return; |
709 if (x + w >= MapMaxX() - 1) return; |
715 if (y + h >= MapMaxY() - 1) return; |
710 if (y + h >= MapMaxY() - 1) return; |
716 |
711 |
717 tile = &_m[TileXY(x, y)]; |
712 Tile *tile = &_m[TileXY(x, y)]; |
718 |
713 |
719 switch (direction) { |
714 switch (direction) { |
720 case 0: |
715 default: NOT_REACHED(); |
|
716 case DIAGDIR_NE: |
721 do { |
717 do { |
722 Tile* tile_cur = tile; |
718 Tile *tile_cur = tile; |
723 uint w_cur; |
719 |
724 |
720 for (uint w_cur = w; w_cur != 0; --w_cur) { |
725 for (w_cur = w; w_cur != 0; --w_cur) { |
|
726 if (*p >= tile_cur->type_height) tile_cur->type_height = *p; |
721 if (*p >= tile_cur->type_height) tile_cur->type_height = *p; |
727 p++; |
722 p++; |
728 tile_cur++; |
723 tile_cur++; |
729 } |
724 } |
730 tile += TileDiffXY(0, 1); |
725 tile += TileDiffXY(0, 1); |
731 } while (--h != 0); |
726 } while (--h != 0); |
732 break; |
727 break; |
733 |
728 |
734 case 1: |
729 case DIAGDIR_SE: |
735 do { |
730 do { |
736 Tile* tile_cur = tile; |
731 Tile *tile_cur = tile; |
737 uint h_cur; |
732 |
738 |
733 for (uint h_cur = h; h_cur != 0; --h_cur) { |
739 for (h_cur = h; h_cur != 0; --h_cur) { |
|
740 if (*p >= tile_cur->type_height) tile_cur->type_height = *p; |
734 if (*p >= tile_cur->type_height) tile_cur->type_height = *p; |
741 p++; |
735 p++; |
742 tile_cur += TileDiffXY(0, 1); |
736 tile_cur += TileDiffXY(0, 1); |
743 } |
737 } |
744 tile++; |
738 tile += TileDiffXY(1, 0); |
745 } while (--w != 0); |
739 } while (--w != 0); |
746 break; |
740 break; |
747 |
741 |
748 case 2: |
742 case DIAGDIR_SW: |
749 tile += TileDiffXY(w - 1, 0); |
743 tile += TileDiffXY(w - 1, 0); |
750 do { |
744 do { |
751 Tile* tile_cur = tile; |
745 Tile *tile_cur = tile; |
752 uint w_cur; |
746 |
753 |
747 for (uint w_cur = w; w_cur != 0; --w_cur) { |
754 for (w_cur = w; w_cur != 0; --w_cur) { |
|
755 if (*p >= tile_cur->type_height) tile_cur->type_height = *p; |
748 if (*p >= tile_cur->type_height) tile_cur->type_height = *p; |
756 p++; |
749 p++; |
757 tile_cur--; |
750 tile_cur--; |
758 } |
751 } |
759 tile += TileDiffXY(0, 1); |
752 tile += TileDiffXY(0, 1); |
760 } while (--h != 0); |
753 } while (--h != 0); |
761 break; |
754 break; |
762 |
755 |
763 case 3: |
756 case DIAGDIR_NW: |
764 tile += TileDiffXY(0, h - 1); |
757 tile += TileDiffXY(0, h - 1); |
765 do { |
758 do { |
766 Tile* tile_cur = tile; |
759 Tile *tile_cur = tile; |
767 uint h_cur; |
760 |
768 |
761 for (uint h_cur = h; h_cur != 0; --h_cur) { |
769 for (h_cur = h; h_cur != 0; --h_cur) { |
|
770 if (*p >= tile_cur->type_height) tile_cur->type_height = *p; |
762 if (*p >= tile_cur->type_height) tile_cur->type_height = *p; |
771 p++; |
763 p++; |
772 tile_cur -= TileDiffXY(0, 1); |
764 tile_cur -= TileDiffXY(0, 1); |
773 } |
765 } |
774 tile++; |
766 tile += TileDiffXY(1, 0); |
775 } while (--w != 0); |
767 } while (--w != 0); |
776 break; |
768 break; |
777 } |
769 } |
778 } |
770 } |
779 |
771 |
780 |
772 |
781 #include "table/genland.h" |
773 #include "table/genland.h" |
782 |
774 |
783 static void CreateDesertOrRainForest() |
775 static void CreateDesertOrRainForest() |
784 { |
776 { |
785 TileIndex tile; |
|
786 TileIndex update_freq = MapSize() / 4; |
777 TileIndex update_freq = MapSize() / 4; |
787 const TileIndexDiffC *data; |
778 const TileIndexDiffC *data; |
788 uint i; |
779 |
789 |
780 for (TileIndex tile = 0; tile != MapSize(); ++tile) { |
790 for (tile = 0; tile != MapSize(); ++tile) { |
|
791 if ((tile % update_freq) == 0) IncreaseGeneratingWorldProgress(GWP_LANDSCAPE); |
781 if ((tile % update_freq) == 0) IncreaseGeneratingWorldProgress(GWP_LANDSCAPE); |
792 |
782 |
793 for (data = _make_desert_or_rainforest_data; |
783 for (data = _make_desert_or_rainforest_data; |
794 data != endof(_make_desert_or_rainforest_data); ++data) { |
784 data != endof(_make_desert_or_rainforest_data); ++data) { |
795 TileIndex t = TILE_MASK(tile + ToTileIndexDiff(*data)); |
785 TileIndex t = TILE_MASK(tile + ToTileIndexDiff(*data)); |
797 } |
787 } |
798 if (data == endof(_make_desert_or_rainforest_data)) |
788 if (data == endof(_make_desert_or_rainforest_data)) |
799 SetTropicZone(tile, TROPICZONE_DESERT); |
789 SetTropicZone(tile, TROPICZONE_DESERT); |
800 } |
790 } |
801 |
791 |
802 for (i = 0; i != 256; i++) { |
792 for (uint i = 0; i != 256; i++) { |
803 if ((i % 64) == 0) IncreaseGeneratingWorldProgress(GWP_LANDSCAPE); |
793 if ((i % 64) == 0) IncreaseGeneratingWorldProgress(GWP_LANDSCAPE); |
804 |
794 |
805 RunTileLoop(); |
795 RunTileLoop(); |
806 } |
796 } |
807 |
797 |
808 for (tile = 0; tile != MapSize(); ++tile) { |
798 for (TileIndex tile = 0; tile != MapSize(); ++tile) { |
809 if ((tile % update_freq) == 0) IncreaseGeneratingWorldProgress(GWP_LANDSCAPE); |
799 if ((tile % update_freq) == 0) IncreaseGeneratingWorldProgress(GWP_LANDSCAPE); |
810 |
800 |
811 for (data = _make_desert_or_rainforest_data; |
801 for (data = _make_desert_or_rainforest_data; |
812 data != endof(_make_desert_or_rainforest_data); ++data) { |
802 data != endof(_make_desert_or_rainforest_data); ++data) { |
813 TileIndex t = TILE_MASK(tile + ToTileIndexDiff(*data)); |
803 TileIndex t = TILE_MASK(tile + ToTileIndexDiff(*data)); |
818 } |
808 } |
819 } |
809 } |
820 |
810 |
821 void GenerateLandscape(byte mode) |
811 void GenerateLandscape(byte mode) |
822 { |
812 { |
823 const int gwp_desert_amount = 4 + 8; |
813 static const int gwp_desert_amount = 4 + 8; |
824 uint i; |
|
825 uint flag; |
|
826 uint32 r; |
|
827 |
814 |
828 if (mode == GW_HEIGHTMAP) { |
815 if (mode == GW_HEIGHTMAP) { |
829 SetGeneratingWorldProgress(GWP_LANDSCAPE, (_opt.landscape == LT_TROPIC) ? 1 + gwp_desert_amount : 1); |
816 SetGeneratingWorldProgress(GWP_LANDSCAPE, (_opt.landscape == LT_TROPIC) ? 1 + gwp_desert_amount : 1); |
830 LoadHeightmap(_file_to_saveload.name); |
817 LoadHeightmap(_file_to_saveload.name); |
831 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE); |
818 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE); |
832 } else if (_patches.land_generator == LG_TERRAGENESIS) { |
819 } else if (_patches.land_generator == LG_TERRAGENESIS) { |
833 SetGeneratingWorldProgress(GWP_LANDSCAPE, (_opt.landscape == LT_TROPIC) ? 3 + gwp_desert_amount : 3); |
820 SetGeneratingWorldProgress(GWP_LANDSCAPE, (_opt.landscape == LT_TROPIC) ? 3 + gwp_desert_amount : 3); |
834 GenerateTerrainPerlin(); |
821 GenerateTerrainPerlin(); |
835 } else { |
822 } else { |
836 switch (_opt.landscape) { |
823 switch (_opt.landscape) { |
837 case LT_ARCTIC: |
824 case LT_ARCTIC: { |
838 SetGeneratingWorldProgress(GWP_LANDSCAPE, 2); |
825 SetGeneratingWorldProgress(GWP_LANDSCAPE, 2); |
839 |
826 |
840 for (i = ScaleByMapSize((Random() & 0x7F) + 950); i != 0; --i) { |
827 uint32 r = Random(); |
|
828 |
|
829 for (uint i = ScaleByMapSize(GB(r, 0, 7) + 950); i != 0; --i) { |
841 GenerateTerrain(2, 0); |
830 GenerateTerrain(2, 0); |
842 } |
831 } |
843 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE); |
832 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE); |
844 |
833 |
845 r = Random(); |
834 uint flag = GB(r, 7, 2) | 4; |
846 flag = GB(r, 0, 2) | 4; |
835 for (uint i = ScaleByMapSize(GB(r, 9, 7) + 450); i != 0; --i) { |
847 for (i = ScaleByMapSize(GB(r, 16, 7) + 450); i != 0; --i) { |
|
848 GenerateTerrain(4, flag); |
836 GenerateTerrain(4, flag); |
849 } |
837 } |
850 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE); |
838 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE); |
851 break; |
839 } break; |
852 |
840 |
853 case LT_TROPIC: |
841 case LT_TROPIC: { |
854 SetGeneratingWorldProgress(GWP_LANDSCAPE, 3 + gwp_desert_amount); |
842 SetGeneratingWorldProgress(GWP_LANDSCAPE, 3 + gwp_desert_amount); |
855 |
843 |
856 for (i = ScaleByMapSize((Random() & 0x7F) + 170); i != 0; --i) { |
844 uint32 r = Random(); |
|
845 |
|
846 for (uint i = ScaleByMapSize(GB(r, 0, 7) + 170); i != 0; --i) { |
857 GenerateTerrain(0, 0); |
847 GenerateTerrain(0, 0); |
858 } |
848 } |
859 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE); |
849 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE); |
860 |
850 |
861 r = Random(); |
851 uint flag = GB(r, 7, 2) | 4; |
862 flag = GB(r, 0, 2) | 4; |
852 for (uint i = ScaleByMapSize(GB(r, 9, 8) + 1700); i != 0; --i) { |
863 for (i = ScaleByMapSize(GB(r, 16, 8) + 1700); i != 0; --i) { |
|
864 GenerateTerrain(0, flag); |
853 GenerateTerrain(0, flag); |
865 } |
854 } |
866 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE); |
855 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE); |
867 |
856 |
868 flag ^= 2; |
857 flag ^= 2; |
869 |
858 |
870 for (i = ScaleByMapSize((Random() & 0x7F) + 410); i != 0; --i) { |
859 for (uint i = ScaleByMapSize(GB(r, 17, 7) + 410); i != 0; --i) { |
871 GenerateTerrain(3, flag); |
860 GenerateTerrain(3, flag); |
872 } |
861 } |
873 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE); |
862 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE); |
874 break; |
863 } break; |
875 |
864 |
876 default: |
865 default: { |
877 SetGeneratingWorldProgress(GWP_LANDSCAPE, 1); |
866 SetGeneratingWorldProgress(GWP_LANDSCAPE, 1); |
878 |
867 |
879 i = ScaleByMapSize((Random() & 0x7F) + (3 - _opt.diff.quantity_sea_lakes) * 256 + 100); |
868 uint32 r = Random(); |
|
869 |
|
870 uint i = ScaleByMapSize(GB(r, 0, 7) + (3 - _opt.diff.quantity_sea_lakes) * 256 + 100); |
880 for (; i != 0; --i) { |
871 for (; i != 0; --i) { |
881 GenerateTerrain(_opt.diff.terrain_type, 0); |
872 GenerateTerrain(_opt.diff.terrain_type, 0); |
882 } |
873 } |
883 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE); |
874 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE); |
884 break; |
875 } break; |
885 } |
876 } |
886 } |
877 } |
887 |
878 |
888 ConvertGroundTilesIntoWaterTiles(); |
879 ConvertGroundTilesIntoWaterTiles(); |
889 |
880 |