635 |
647 |
636 if SDL_MustLock(Surface) then |
648 if SDL_MustLock(Surface) then |
637 SDL_UnlockSurface(Surface); |
649 SDL_UnlockSurface(Surface); |
638 end; |
650 end; |
639 |
651 |
|
652 procedure GenMaze; |
|
653 const small_cell_size = 128; |
|
654 medium_cell_size = 192; |
|
655 large_cell_size = 256; |
|
656 braidness = 25; |
|
657 maze_inverted = false; //false makes more sense for now |
|
658 |
|
659 var x, y: Longint; |
|
660 bg_color, fg_color: Longint; |
|
661 cellsize: LongInt; //selected by the user in the gui |
|
662 seen_cells_x, seen_cells_y: Longint; //number of cells that can be visited by the generator, that is every second cell in x and y direction. the cells between there are walls that will be removed when we move from one cell to another |
|
663 start_x, start_y: Longint; //first visited cell, must be between 0 and seen_cells_x/y - 1 inclusive |
|
664 num_edges_x, num_edges_y: Longint; //number of resulting edges that need to be vertexificated |
|
665 num_cells_x, num_cells_y: Longint; //actual number of cells, depending on cell size |
|
666 seen_list: array of array of Boolean; |
|
667 xwalls: array of array of Boolean; |
|
668 ywalls: array of array of Boolean; |
|
669 x_edge_list: array of array of Boolean; |
|
670 y_edge_list: array of array of Boolean; |
|
671 maze: array of array of Boolean; |
|
672 pa: TPixAr; |
|
673 num_vertices: Longint; |
|
674 off_y: LongInt; |
|
675 |
|
676 function is_cell_seen(x: Longint; y: Longint): Boolean; |
|
677 begin |
|
678 if (x < 0) or (x >= seen_cells_x) or (y < 0) or (y >= seen_cells_y) then |
|
679 is_cell_seen := true |
|
680 else |
|
681 is_cell_seen := seen_list[x, y]; |
|
682 end; |
|
683 |
|
684 function is_x_edge(x, y: Longint): Boolean; |
|
685 begin |
|
686 if (x < 0) or (x > num_edges_x) or (y < 0) or (y > num_cells_y) then |
|
687 is_x_edge := false |
|
688 else |
|
689 is_x_edge := x_edge_list[x, y]; |
|
690 end; |
|
691 |
|
692 function is_y_edge(x, y: Longint): Boolean; |
|
693 begin |
|
694 if (x < 0) or (x > num_cells_x) or (y < 0) or (y > num_edges_y) then |
|
695 is_y_edge := false |
|
696 else |
|
697 is_y_edge := y_edge_list[x, y]; |
|
698 end; |
|
699 |
|
700 procedure see_cell(x: Longint; y: Longint); |
|
701 var dir: direction; |
|
702 tries: Longint; |
|
703 begin |
|
704 seen_list[x, y] := true; |
|
705 case GetRandom(4) of |
|
706 0: dir := DIR_N; |
|
707 1: dir := DIR_E; |
|
708 2: dir := DIR_S; |
|
709 3: dir := DIR_W; |
|
710 end; |
|
711 tries := 0; |
|
712 while (tries < 5) do |
|
713 begin |
|
714 if is_cell_seen(x + dir.x, y + dir.y) then |
|
715 begin |
|
716 //we have already seen the target cell, decide if we should remove the wall anyway |
|
717 //(or put a wall there if maze_inverted, but we're not doing that right now) |
|
718 if not maze_inverted and (GetRandom(braidness) = 0) then |
|
719 //or just warn that inverted+braid+indestructable terrain != good idea |
|
720 begin |
|
721 case dir.x of |
|
722 -1: if x > 0 then ywalls[x-1, y] := false; |
|
723 1: if x < seen_cells_x - 1 then ywalls[x, y] := false; |
|
724 end; |
|
725 case dir.y of |
|
726 -1: if y > 0 then xwalls[x, y-1] := false; |
|
727 1: if y < seen_cells_y - 1 then xwalls[x, y] := false; |
|
728 end; |
|
729 end; |
|
730 if dir = DIR_N then //TODO might want to randomize that |
|
731 dir := DIR_E |
|
732 else if dir = DIR_E then |
|
733 dir := DIR_S |
|
734 else if dir = DIR_S then |
|
735 dir := DIR_W |
|
736 else |
|
737 dir := DIR_N; |
|
738 end |
|
739 else //cell wasn't seen yet, go there |
|
740 begin |
|
741 case dir.y of |
|
742 -1: xwalls[x, y-1] := false; |
|
743 1: xwalls[x, y] := false; |
|
744 end; |
|
745 case dir.x of |
|
746 -1: ywalls[x-1, y] := false; |
|
747 1: ywalls[x, y] := false; |
|
748 end; |
|
749 see_cell(x + dir.x, y + dir.y); |
|
750 end; |
|
751 |
|
752 tries := tries + 1; |
|
753 end; |
|
754 |
|
755 end; |
|
756 procedure add_vertex(x, y: Longint); |
|
757 begin |
|
758 writelntoconsole('add_vertex('+inttostr(x)+', '+inttostr(y)+')'); |
|
759 if x = NTPX then |
|
760 begin |
|
761 pa.ar[num_vertices].x := NTPX; |
|
762 pa.ar[num_vertices].y := 0; |
|
763 end |
|
764 else |
|
765 begin |
|
766 pa.ar[num_vertices].x := x*cellsize; |
|
767 pa.ar[num_vertices].y := y*cellsize + off_y; |
|
768 end; |
|
769 num_vertices := num_vertices + 1; |
|
770 end; |
|
771 |
|
772 procedure add_edge(x, y: Longint; dir: direction); |
|
773 var i: integer; |
|
774 begin |
|
775 if dir = DIR_N then |
|
776 begin |
|
777 dir := DIR_W |
|
778 end |
|
779 else if dir = DIR_E then |
|
780 begin |
|
781 dir := DIR_N |
|
782 end |
|
783 else if dir = DIR_S then |
|
784 begin |
|
785 dir := DIR_E |
|
786 end |
|
787 else |
|
788 begin |
|
789 dir := DIR_S; |
|
790 end; |
|
791 |
|
792 for i := 0 to 3 do |
|
793 begin |
|
794 if dir = DIR_N then |
|
795 dir := DIR_E |
|
796 else if dir = DIR_E then |
|
797 dir := DIR_S |
|
798 else if dir = DIR_S then |
|
799 dir := DIR_W |
|
800 else |
|
801 dir := DIR_N; |
|
802 |
|
803 if (dir = DIR_N) and is_x_edge(x, y) then |
|
804 begin |
|
805 x_edge_list[x, y] := false; |
|
806 add_vertex(x+1, y); |
|
807 add_edge(x, y-1, DIR_N); |
|
808 break; |
|
809 end; |
|
810 |
|
811 if (dir = DIR_E) and is_y_edge(x+1, y) then |
|
812 begin |
|
813 y_edge_list[x+1, y] := false; |
|
814 add_vertex(x+2, y+1); |
|
815 add_edge(x+1, y, DIR_E); |
|
816 break; |
|
817 end; |
|
818 |
|
819 if (dir = DIR_S) and is_x_edge(x, y+1) then |
|
820 begin |
|
821 x_edge_list[x, y+1] := false; |
|
822 add_vertex(x+1, y+2); |
|
823 add_edge(x, y+1, DIR_S); |
|
824 break; |
|
825 end; |
|
826 |
|
827 if (dir = DIR_W) and is_y_edge(x, y) then |
|
828 begin |
|
829 y_edge_list[x, y] := false; |
|
830 add_vertex(x, y+1); |
|
831 add_edge(x-1, y, DIR_W); |
|
832 break; |
|
833 end; |
|
834 end; |
|
835 |
|
836 end; |
|
837 |
|
838 begin |
|
839 case cMazeSize of |
|
840 0: cellsize := small_cell_size; |
|
841 1: cellsize := medium_cell_size; |
|
842 2: cellsize := large_cell_size; |
|
843 end; |
|
844 |
|
845 num_cells_x := LAND_WIDTH div cellsize; |
|
846 if num_cells_x mod 2 = 0 then num_cells_x := num_cells_x - 1; //needs to be odd |
|
847 num_cells_y := LAND_HEIGHT div cellsize; |
|
848 if num_cells_y mod 2 = 0 then num_cells_y := num_cells_y - 1; |
|
849 num_edges_x := num_cells_x - 1; |
|
850 num_edges_y := num_cells_y - 1; |
|
851 seen_cells_x := num_cells_x div 2; |
|
852 seen_cells_y := num_cells_y div 2; |
|
853 |
|
854 SetLength(seen_list, seen_cells_x, seen_cells_y); |
|
855 SetLength(xwalls, seen_cells_x, seen_cells_y - 1); |
|
856 SetLength(ywalls, seen_cells_x - 1, seen_cells_y); |
|
857 SetLength(x_edge_list, num_edges_x, num_cells_y); |
|
858 SetLength(y_edge_list, num_cells_x, num_edges_y); |
|
859 SetLength(maze, num_cells_x, num_cells_y); |
|
860 |
|
861 num_vertices := 0; |
|
862 |
|
863 (* |
|
864 TODO - Inverted maze |
|
865 if maze_inverted then |
|
866 begin |
|
867 bg_color := 0; |
|
868 fg_color := COLOR_LAND; |
|
869 end |
|
870 else |
|
871 begin*) |
|
872 bg_color := COLOR_LAND; |
|
873 fg_color := 0; |
|
874 //end; |
|
875 |
|
876 playHeight := num_cells_y * cellsize; |
|
877 playWidth := num_cells_x * cellsize; |
|
878 off_y := LAND_HEIGHT - playHeight; |
|
879 |
|
880 for x := 0 to playWidth do |
|
881 for y := 0 to off_y - 1 do |
|
882 Land[y, x] := fg_color; |
|
883 |
|
884 for x := 0 to playWidth do |
|
885 for y := off_y to LAND_HEIGHT - 1 do |
|
886 Land[y, x] := bg_color; |
|
887 |
|
888 for y := 0 to num_cells_y - 1 do |
|
889 for x := 0 to num_cells_x - 1 do |
|
890 maze[x, y] := false; |
|
891 |
|
892 start_x := GetRandom(seen_cells_x); |
|
893 start_y := GetRandom(seen_cells_y); |
|
894 |
|
895 for x := 0 to seen_cells_x - 1 do |
|
896 for y := 0 to seen_cells_y - 2 do |
|
897 xwalls[x, y] := true; |
|
898 |
|
899 for x := 0 to seen_cells_x - 2 do |
|
900 for y := 0 to seen_cells_y - 1 do |
|
901 ywalls[x, y] := true; |
|
902 |
|
903 for x := 0 to seen_cells_x - 1 do |
|
904 for y := 0 to seen_cells_y - 1 do |
|
905 seen_list[x, y] := false; |
|
906 |
|
907 for x := 0 to num_edges_x - 1 do |
|
908 for y := 0 to num_cells_y - 1 do |
|
909 x_edge_list[x, y] := false; |
|
910 |
|
911 for x := 0 to num_cells_x - 1 do |
|
912 for y := 0 to num_edges_y - 1 do |
|
913 y_edge_list[x, y] := false; |
|
914 |
|
915 see_cell(start_x, start_y); |
|
916 |
|
917 for x := 0 to seen_cells_x - 1 do |
|
918 for y := 0 to seen_cells_y - 1 do |
|
919 if seen_list[x, y] then |
|
920 maze[(x+1)*2-1, (y+1)*2-1] := true; |
|
921 |
|
922 for x := 0 to seen_cells_x - 1 do |
|
923 for y := 0 to seen_cells_y - 2 do |
|
924 if not xwalls[x, y] then |
|
925 maze[x*2 + 1, y*2 + 2] := true; |
|
926 |
|
927 |
|
928 for x := 0 to seen_cells_x - 2 do |
|
929 for y := 0 to seen_cells_y - 1 do |
|
930 if not ywalls[x, y] then |
|
931 maze[x*2 + 2, y*2 + 1] := true; |
|
932 |
|
933 for x := 0 to num_edges_x - 1 do |
|
934 for y := 0 to num_cells_y - 1 do |
|
935 if maze[x, y] xor maze[x+1, y] then |
|
936 x_edge_list[x, y] := true |
|
937 else |
|
938 x_edge_list[x, y] := false; |
|
939 |
|
940 for x := 0 to num_cells_x - 1 do |
|
941 for y := 0 to num_edges_y - 1 do |
|
942 if maze[x, y] xor maze[x, y+1] then |
|
943 y_edge_list[x, y] := true |
|
944 else |
|
945 y_edge_list[x, y] := false; |
|
946 |
|
947 for x := 0 to num_edges_x - 1 do |
|
948 for y := 0 to num_cells_y - 1 do |
|
949 if x_edge_list[x, y] then |
|
950 begin |
|
951 x_edge_list[x, y] := false; |
|
952 add_vertex(x+1, y+1); |
|
953 add_vertex(x+1, y); |
|
954 add_edge(x, y-1, DIR_N); |
|
955 add_vertex(NTPX, 0); |
|
956 end; |
|
957 |
|
958 pa.count := num_vertices; |
|
959 |
|
960 RandomizePoints(pa); |
|
961 BezierizeEdge(pa, _0_25); |
|
962 RandomizePoints(pa); |
|
963 BezierizeEdge(pa, _0_5); |
|
964 |
|
965 DrawEdge(pa, 0); |
|
966 |
|
967 for x := 0 to num_cells_x - 1 do |
|
968 for y := 0 to num_cells_y - 1 do |
|
969 if maze[x, y] then begin |
|
970 FillLand(cellsize div 2 + cellsize * x, cellsize div 2 + cellsize * y + off_y); |
|
971 break; |
|
972 end; |
|
973 |
|
974 MaxHedgehogs:= 32; |
|
975 hasGirders:= false; |
|
976 leftX:= 0; |
|
977 rightX:= playWidth; |
|
978 topY:= off_y; |
|
979 hasBorder := true; |
|
980 end; |
|
981 |
640 procedure GenLandSurface; |
982 procedure GenLandSurface; |
641 var tmpsurf: PSDL_Surface; |
983 var tmpsurf: PSDL_Surface; |
642 begin |
984 begin |
643 WriteLnToConsole('Generating land...'); |
985 WriteLnToConsole('Generating land...'); |
644 GenBlank(EdgeTemplates[SelectTemplate]); |
986 case cMapGen of |
|
987 0: GenBlank(EdgeTemplates[SelectTemplate]); |
|
988 1: GenMaze; |
|
989 end; |
645 AddProgress(); |
990 AddProgress(); |
646 |
991 |
647 tmpsurf:= SDL_CreateRGBSurface(SDL_SWSURFACE, LAND_WIDTH, LAND_HEIGHT, 32, RMask, GMask, BMask, 0); |
992 tmpsurf:= SDL_CreateRGBSurface(SDL_SWSURFACE, LAND_WIDTH, LAND_HEIGHT, 32, RMask, GMask, BMask, 0); |
648 |
993 |
649 TryDo(tmpsurf <> nil, 'Error creating pre-land surface', true); |
994 TryDo(tmpsurf <> nil, 'Error creating pre-land surface', true); |