1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-98 Artsoft Entertainment *
8 * phone: ++49 +521 290471 *
9 * email: aeglos@valinor.owl.de *
10 *----------------------------------------------------------*
12 ***********************************************************/
22 /* positions in the level editor */
23 #define ED_WIN_MB_LEFT_XPOS 7
24 #define ED_WIN_MB_LEFT_YPOS 6
25 #define ED_WIN_LEVELNR_XPOS 77
26 #define ED_WIN_LEVELNR_YPOS 7
27 #define ED_WIN_MB_MIDDLE_XPOS 7
28 #define ED_WIN_MB_MIDDLE_YPOS 258
29 #define ED_WIN_MB_RIGHT_XPOS 77
30 #define ED_WIN_MB_RIGHT_YPOS 258
32 /* other constants for the editor */
33 #define ED_SCROLL_NO 0
34 #define ED_SCROLL_LEFT 1
35 #define ED_SCROLL_RIGHT 2
36 #define ED_SCROLL_UP 4
37 #define ED_SCROLL_DOWN 8
39 /* screens in the level editor */
40 #define ED_MODE_DRAWING 0
41 #define ED_MODE_INFO 1
42 #define ED_MODE_PROPERTIES 2
44 /* how many steps can be cancelled */
45 #define NUM_UNDO_STEPS (10 + 1)
47 /* values for random placement */
48 #define RANDOM_USE_PERCENTAGE 0
49 #define RANDOM_USE_NUM_OBJECTS 1
51 /* values for the control window */
52 #define ED_CTRL_BUTTONS_GFX_YPOS 236
53 #define ED_CTRL_BUTTONS_ALT_GFX_YPOS 142
55 #define ED_CTRL1_BUTTONS_HORIZ 4
56 #define ED_CTRL1_BUTTONS_VERT 4
57 #define ED_CTRL1_BUTTON_XSIZE 22
58 #define ED_CTRL1_BUTTON_YSIZE 22
59 #define ED_CTRL1_BUTTONS_XPOS 6
60 #define ED_CTRL1_BUTTONS_YPOS 6
61 #define ED_CTRL2_BUTTONS_HORIZ 3
62 #define ED_CTRL2_BUTTONS_VERT 2
63 #define ED_CTRL2_BUTTON_XSIZE 30
64 #define ED_CTRL2_BUTTON_YSIZE 20
65 #define ED_CTRL2_BUTTONS_XPOS 5
66 #define ED_CTRL2_BUTTONS_YPOS 100
67 #define ED_NUM_CTRL1_BUTTONS (ED_CTRL1_BUTTONS_HORIZ * ED_CTRL1_BUTTONS_VERT)
68 #define ED_NUM_CTRL2_BUTTONS (ED_CTRL2_BUTTONS_HORIZ * ED_CTRL2_BUTTONS_VERT)
69 #define ED_NUM_CTRL_BUTTONS (ED_NUM_CTRL1_BUTTONS + ED_NUM_CTRL2_BUTTONS)
71 /* values for other gadgets */
72 #define ED_SCORE_XPOS TILEX
73 #define ED_SCORE_YPOS (7 * TILEY)
74 #define ED_COUNT_VALUE_XOFFSET 5
75 #define ED_COUNT_VALUE_YOFFSET 3
77 /* control button identifiers */
78 #define ED_CTRL_ID_SINGLE_ITEMS 0
79 #define ED_CTRL_ID_CONNECTED_ITEMS 1
80 #define ED_CTRL_ID_LINE 2
81 #define ED_CTRL_ID_TEXT 3
82 #define ED_CTRL_ID_RECTANGLE 4
83 #define ED_CTRL_ID_FILLED_BOX 5
84 #define ED_CTRL_ID_WRAP_UP 6
85 #define ED_CTRL_ID_PROPERTIES 7
86 #define ED_CTRL_ID_FLOOD_FILL 8
87 #define ED_CTRL_ID_WRAP_LEFT 9
88 #define ED_CTRL_ID_UNUSED1 10
89 #define ED_CTRL_ID_WRAP_RIGHT 11
90 #define ED_CTRL_ID_RANDOM_PLACEMENT 12
91 #define ED_CTRL_ID_BRUSH 13
92 #define ED_CTRL_ID_WRAP_DOWN 14
93 #define ED_CTRL_ID_UNUSED2 15
94 #define ED_CTRL_ID_UNDO 16
95 #define ED_CTRL_ID_INFO 17
96 #define ED_CTRL_ID_SAVE 18
97 #define ED_CTRL_ID_CLEAR 19
98 #define ED_CTRL_ID_TEST 20
99 #define ED_CTRL_ID_EXIT 21
101 /* counter button identifiers */
102 #define ED_CTRL_ID_SCORE_DOWN 22
103 #define ED_CTRL_ID_SCORE_UP 23
105 /* drawing area identifiers */
106 #define ED_CTRL_ID_DRAWING_LEVEL 24
108 #define ED_NUM_GADGETS 25
110 /* values for counter gadgets */
111 #define ED_COUNTER_SCORE 0
113 #define ED_NUM_COUNTERS 1
119 } counter_info[ED_NUM_COUNTERS] =
121 { ED_SCORE_XPOS, ED_SCORE_YPOS, ED_CTRL_ID_SCORE_DOWN }
124 /* forward declaration for internal use */
125 static void DrawDrawingWindow();
126 static void DrawPropertiesWindow(int);
127 static void CopyLevelToUndoBuffer();
128 static void HandleDrawingAreas(struct GadgetInfo *);
129 static void HandleCounterButtons(struct GadgetInfo *);
130 static void HandleControlButtons(struct GadgetInfo *);
132 static struct GadgetInfo *level_editor_gadget[ED_NUM_GADGETS];
133 static boolean level_editor_gadgets_created = FALSE;
135 static int drawing_function = ED_CTRL_ID_SINGLE_ITEMS;
137 static short OrigBackup[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
138 static short UndoBuffer[NUM_UNDO_STEPS][MAX_LEV_FIELDX][MAX_LEV_FIELDY];
139 static int undo_buffer_position = 0;
140 static int undo_buffer_steps = 0;
142 static int random_placement_percentage = 10;
143 static int random_placement_num_objects = 10;
145 static int random_placement_method = RANDOM_USE_PERCENTAGE;
147 static int random_placement_method = RANDOM_USE_NUM_OBJECTS;
150 /* pointer to score value */
151 static int *gadget_score_value;
153 static int level_xpos,level_ypos;
154 static int edit_mode;
155 static boolean name_typing;
156 static int new_element1 = EL_MAUERWERK;
157 static int new_element2 = EL_LEERRAUM;
158 static int new_element3 = EL_ERDREICH;
161 int editor_element[] =
163 EL_CHAR_A + ('B' - 'A'),
164 EL_CHAR_A + ('O' - 'A'),
165 EL_CHAR_A + ('U' - 'A'),
166 EL_CHAR_A + ('L' - 'A'),
169 EL_CHAR_A + ('D' - 'A'),
170 EL_CHAR_A + ('E' - 'A'),
171 EL_CHAR_A + ('R' - 'A'),
173 EL_CHAR_A + ('D' - 'A'),
174 EL_CHAR_A + ('A' - 'A'),
175 EL_CHAR_A + ('S' - 'A'),
176 EL_CHAR_A + ('H' - 'A'),
203 EL_CHAR_A + ('E' - 'A'),
204 EL_CHAR_A + ('M' - 'A'),
205 EL_CHAR_A + ('E' - 'A'),
208 EL_CHAR_A + ('R' - 'A'),
209 EL_CHAR_A + ('A' - 'A'),
210 EL_CHAR_A + ('L' - 'A'),
211 EL_CHAR_A + ('D' - 'A'),
213 EL_CHAR_A + ('M' - 'A'),
214 EL_CHAR_A + ('I' - 'A'),
215 EL_CHAR_A + ('N' - 'A'),
216 EL_CHAR_A + ('E' - 'A'),
293 EL_CHAR_A + ('M' - 'A'),
294 EL_CHAR_A + ('O' - 'A'),
295 EL_CHAR_A + ('R' - 'A'),
296 EL_CHAR_A + ('E' - 'A'),
343 EL_CHAR_A + ('S' - 'A'),
344 EL_CHAR_A + ('O' - 'A'),
345 EL_CHAR_A + ('K' - 'A'),
346 EL_CHAR_A + ('O' - 'A'),
349 EL_CHAR_A + ('B' - 'A'),
350 EL_CHAR_A + ('A' - 'A'),
351 EL_CHAR_A + ('N' - 'A'),
354 EL_SOKOBAN_FELD_LEER,
355 EL_SOKOBAN_FELD_VOLL,
359 EL_CHAR_A + ('D' - 'A'),
360 EL_CHAR_A + ('Y' - 'A'),
361 EL_CHAR_A + ('N' - 'A'),
362 EL_CHAR_A + ('A' - 'A'),
364 EL_CHAR_A + ('B' - 'A'),
365 EL_CHAR_A + ('L' - 'A'),
366 EL_CHAR_A + ('A' - 'A'),
367 EL_CHAR_A + ('S' - 'A'),
370 EL_CHAR_A + ('T' - 'A'),
371 EL_CHAR_A + ('E' - 'A'),
372 EL_CHAR_A + ('R' - 'A'),
454 int elements_in_list = sizeof(editor_element)/sizeof(int);
456 static void ScrollMiniLevel(int from_x, int from_y, int scroll)
459 int dx = (scroll==ED_SCROLL_LEFT ? -1 : scroll==ED_SCROLL_RIGHT ? 1 : 0);
460 int dy = (scroll==ED_SCROLL_UP ? -1 : scroll==ED_SCROLL_DOWN ? 1 : 0);
462 XCopyArea(display,drawto,drawto,gc,
463 SX+MINI_TILEX*(dx==-1),SY+MINI_TILEY*(dy==-1),
464 SXSIZE-MINI_TILEX*ABS(dx),SYSIZE-MINI_TILEY*ABS(dy),
465 SX+MINI_TILEX*(dx==+1),SY+MINI_TILEY*(dy==+1));
468 x = (dx==1 ? 0 : 2*SCR_FIELDX-1);
469 for(y=0;y<2*SCR_FIELDY;y++)
470 DrawMiniElementOrWall(x,y,from_x,from_y);
474 y = (dy==1 ? 0 : 2*SCR_FIELDY-1);
475 for(x=0;x<2*SCR_FIELDX;x++)
476 DrawMiniElementOrWall(x,y,from_x,from_y);
479 redraw_mask |= REDRAW_FIELD;
483 void InitLevelEditorGadgets()
487 for (i=0; i<ED_NUM_GADGETS; i++)
488 level_editor_gadget[i] = NULL;
491 static void CreateControlButtons()
495 for (i=0; i<ED_NUM_CTRL_BUTTONS; i++)
497 Pixmap gd_pixmap = pix[PIX_DOOR];
498 struct GadgetInfo *gi;
499 int gd_xoffset, gd_yoffset;
500 int gd_x1, gd_x2, gd_y1, gd_y2;
504 boolean radio_button_pressed;
505 unsigned long event_mask;
508 if (id == ED_CTRL_ID_SINGLE_ITEMS ||
509 id == ED_CTRL_ID_CONNECTED_ITEMS ||
510 id == ED_CTRL_ID_LINE ||
511 id == ED_CTRL_ID_TEXT ||
512 id == ED_CTRL_ID_RECTANGLE ||
513 id == ED_CTRL_ID_FILLED_BOX ||
514 id == ED_CTRL_ID_FLOOD_FILL ||
515 id == ED_CTRL_ID_BRUSH)
517 button_type = GD_TYPE_RADIO_BUTTON;
519 radio_button_pressed = (id == drawing_function ? TRUE : FALSE);
520 event_mask = GD_EVENT_PRESSED;
524 button_type = GD_TYPE_NORMAL_BUTTON;
526 radio_button_pressed = FALSE;
528 if (id == ED_CTRL_ID_WRAP_LEFT ||
529 id == ED_CTRL_ID_WRAP_RIGHT ||
530 id == ED_CTRL_ID_WRAP_UP ||
531 id == ED_CTRL_ID_WRAP_DOWN)
532 event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
534 event_mask = GD_EVENT_RELEASED;
537 if (id < ED_NUM_CTRL1_BUTTONS)
539 int x = i % ED_CTRL1_BUTTONS_HORIZ;
540 int y = i / ED_CTRL1_BUTTONS_HORIZ;
542 gd_xoffset = ED_CTRL1_BUTTONS_XPOS + x * ED_CTRL1_BUTTON_XSIZE;
543 gd_yoffset = ED_CTRL1_BUTTONS_YPOS + y * ED_CTRL1_BUTTON_YSIZE;
544 width = ED_CTRL1_BUTTON_XSIZE;
545 height = ED_CTRL1_BUTTON_YSIZE;
549 int x = (i - ED_NUM_CTRL1_BUTTONS) % ED_CTRL2_BUTTONS_HORIZ;
550 int y = (i - ED_NUM_CTRL1_BUTTONS) / ED_CTRL2_BUTTONS_HORIZ;
552 gd_xoffset = ED_CTRL2_BUTTONS_XPOS + x * ED_CTRL2_BUTTON_XSIZE;
553 gd_yoffset = ED_CTRL2_BUTTONS_YPOS + y * ED_CTRL2_BUTTON_YSIZE;
554 width = ED_CTRL2_BUTTON_XSIZE;
555 height = ED_CTRL2_BUTTON_YSIZE;
558 gd_x1 = DOOR_GFX_PAGEX8 + gd_xoffset;
559 gd_x2 = DOOR_GFX_PAGEX7 + gd_xoffset;
560 gd_y1 = DOOR_GFX_PAGEY1 + ED_CTRL_BUTTONS_GFX_YPOS + gd_yoffset;
561 gd_y2 = DOOR_GFX_PAGEY1 + ED_CTRL_BUTTONS_ALT_GFX_YPOS + gd_yoffset;
563 gi = CreateGadget(GDI_CUSTOM_ID, id,
564 GDI_X, EX + gd_xoffset,
565 GDI_Y, EY + gd_yoffset,
568 GDI_TYPE, button_type,
569 GDI_STATE, GD_BUTTON_UNPRESSED,
570 GDI_RADIO_NR, radio_button_nr,
571 GDI_RADIO_PRESSED, radio_button_pressed,
572 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y1,
573 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y1,
574 GDI_ALT_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y2,
575 GDI_ALT_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y2,
576 GDI_EVENT_MASK, event_mask,
577 GDI_CALLBACK, HandleControlButtons,
581 Error(ERR_EXIT, "cannot create gadget");
583 level_editor_gadget[id] = gi;
587 static void CreateCounterButtons(int counter_id)
593 Pixmap gd_pixmap = pix[PIX_DOOR];
594 struct GadgetInfo *gi;
596 int gd_x1, gd_x2, gd_y;
597 int id = counter_info[counter_id].gadget_id + i;
598 unsigned long event_mask;
600 event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
602 gd_xoffset = (i == 0 ? ED_BUTTON_MINUS_XPOS : ED_BUTTON_PLUS_XPOS);
603 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
604 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
605 gd_y = DOOR_GFX_PAGEY1 + ED_BUTTON_COUNT_YPOS;
607 gi = CreateGadget(GDI_CUSTOM_ID, id,
608 GDI_X, SX + counter_info[counter_id].x + gd_xoffset,
609 GDI_Y, SY + counter_info[counter_id].y,
610 GDI_WIDTH, ED_BUTTON_COUNT_XSIZE,
611 GDI_HEIGHT, ED_BUTTON_COUNT_YSIZE,
612 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
613 GDI_STATE, GD_BUTTON_UNPRESSED,
614 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
615 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
616 GDI_EVENT_MASK, event_mask,
617 GDI_CALLBACK, HandleCounterButtons,
621 Error(ERR_EXIT, "cannot create gadget");
623 level_editor_gadget[id] = gi;
627 static void CreateDrawingAreas()
629 struct GadgetInfo *gi;
630 unsigned long event_mask;
633 GD_EVENT_PRESSED | GD_EVENT_RELEASED | GD_EVENT_MOVING |
634 GD_EVENT_OFF_BORDERS;
636 gi = CreateGadget(GDI_CUSTOM_ID, ED_CTRL_ID_DRAWING_LEVEL,
641 GDI_TYPE, GD_TYPE_DRAWING_AREA,
642 GDI_ITEM_SIZE, MINI_TILEX, MINI_TILEY,
643 GDI_EVENT_MASK, event_mask,
644 GDI_CALLBACK, HandleDrawingAreas,
648 Error(ERR_EXIT, "cannot create gadget");
650 level_editor_gadget[ED_CTRL_ID_DRAWING_LEVEL] = gi;
653 static void CreateLevelEditorGadgets()
655 if (level_editor_gadgets_created)
658 CreateControlButtons();
659 CreateCounterButtons(ED_COUNTER_SCORE);
660 CreateDrawingAreas();
662 level_editor_gadgets_created = TRUE;
665 static void MapControlButtons()
669 for (i=0; i<ED_NUM_CTRL_BUTTONS; i++)
670 MapGadget(level_editor_gadget[i]);
673 static void MapCounterButtons(int counter_id)
678 MapGadget(level_editor_gadget[counter_info[counter_id].gadget_id + i]);
681 static void MapMainDrawingArea()
683 MapGadget(level_editor_gadget[ED_CTRL_ID_DRAWING_LEVEL]);
686 void UnmapLevelEditorWindowGadgets()
690 for (i=ED_NUM_CTRL_BUTTONS; i<ED_NUM_GADGETS; i++)
691 UnmapGadget(level_editor_gadget[i]);
694 void UnmapLevelEditorGadgets()
698 for (i=0; i<ED_NUM_GADGETS; i++)
699 UnmapGadget(level_editor_gadget[i]);
704 int i, x, y, graphic;
708 edit_mode = ED_MODE_DRAWING;
712 CloseDoor(DOOR_CLOSE_ALL);
714 if (level_editor_test_game)
716 for(x=0; x<lev_fieldx; x++)
717 for(y=0; y<lev_fieldy; y++)
718 Feld[x][y] = Ur[x][y];
720 for(x=0; x<lev_fieldx; x++)
721 for(y=0; y<lev_fieldy; y++)
722 Ur[x][y] = OrigBackup[x][y];
724 level_editor_test_game = FALSE;
728 undo_buffer_position = -1;
729 undo_buffer_steps = -1;
730 CopyLevelToUndoBuffer();
733 DrawMiniLevel(level_xpos,level_ypos);
736 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
737 DOOR_GFX_PAGEX6,DOOR_GFX_PAGEY1,
739 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
740 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
741 DOOR_GFX_PAGEX6+ED_BUTTON_ELEM_XPOS,
742 DOOR_GFX_PAGEY1+ED_BUTTON_ELEM_YPOS,
743 4*ED_BUTTON_ELEM_XSIZE,5*ED_BUTTON_ELEM_YSIZE,
744 DOOR_GFX_PAGEX1+ED_BUTTON_ELEM_XPOS,
745 DOOR_GFX_PAGEY1+ED_BUTTON_EUP_Y2POS);
747 for(i=0;i<MAX_ELEM_X*MAX_ELEM_Y;i++)
749 if (i < elements_in_list)
750 graphic = el2gfx(editor_element[i]);
752 graphic = GFX_LEERRAUM;
754 DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
755 DOOR_GFX_PAGEX1+ED_BUTTON_ELEM_XPOS+3 +
756 (i%MAX_ELEM_X)*ED_BUTTON_ELEM_XSIZE,
757 DOOR_GFX_PAGEY1+ED_BUTTON_ELEM_YPOS+3 +
758 (i/MAX_ELEM_X)*ED_BUTTON_ELEM_YSIZE,
762 DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
763 DOOR_GFX_PAGEX1+ED_WIN_MB_LEFT_XPOS,
764 DOOR_GFX_PAGEY1+ED_WIN_MB_LEFT_YPOS,
765 el2gfx(new_element1));
766 DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
767 DOOR_GFX_PAGEX1+ED_WIN_MB_MIDDLE_XPOS,
768 DOOR_GFX_PAGEY1+ED_WIN_MB_MIDDLE_YPOS,
769 el2gfx(new_element2));
770 DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
771 DOOR_GFX_PAGEX1+ED_WIN_MB_RIGHT_XPOS,
772 DOOR_GFX_PAGEY1+ED_WIN_MB_RIGHT_YPOS,
773 el2gfx(new_element3));
774 DrawTextExt(pix[PIX_DB_DOOR],gc,
775 DOOR_GFX_PAGEX2+ED_WIN_LEVELNR_XPOS,
776 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS,
777 int2str(level_nr,2),FS_SMALL,FC_SPECIAL1);
778 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
779 DOOR_GFX_PAGEX2+ED_WIN_LEVELNR_XPOS+3,
780 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS,
782 DOOR_GFX_PAGEX1+ED_WIN_LEVELNR_XPOS,
783 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS);
784 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
785 DOOR_GFX_PAGEX2+ED_WIN_LEVELNR_XPOS+14,
786 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS,
788 DOOR_GFX_PAGEX1+ED_WIN_LEVELNR_XPOS+9,
789 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS);
791 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
792 DOOR_GFX_PAGEX6,DOOR_GFX_PAGEY2,
794 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
796 /* draw bigger door */
797 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
802 /* draw new control window */
803 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
804 DOOR_GFX_PAGEX8, 236,
808 redraw_mask |= REDRAW_ALL;
810 OpenDoor(DOOR_OPEN_1);
812 if (!level_editor_gadgets_created)
813 CreateLevelEditorGadgets();
816 MapMainDrawingArea();
819 OpenDoor(DOOR_OPEN_1 | DOOR_OPEN_2);
823 void DrawControlWindow()
828 UnmapLevelEditorWindowGadgets();
830 /* Inhalt der Mampfer */
831 DrawText(ED_COUNT_GADGET_XPOS+1,SY+6,
832 "Contents of a smashed cruncher:",FS_SMALL,FC_YELLOW);
833 for(i=0;i<4;i++) for(y=0;y<4;y++) for(x=0;x<4;x++)
835 DrawMiniElement(1+5*i+x,2+y,EL_ERDREICH);
836 XFillRectangle(display,drawto,gc,
837 SX+(1+5*i)*MINI_TILEX+MINI_TILEX/2-1,
838 SY+(2)*MINI_TILEY+MINI_TILEY/2-1,
839 3*MINI_TILEX+2,3*MINI_TILEY+2);
841 XCopyArea(display,drawto,drawto,gc,
842 SX+1*MINI_TILEX,SY+2*MINI_TILEY,
843 4*5*MINI_TILEX,5*MINI_TILEY,
844 SX+1*MINI_TILEX-MINI_TILEX/2,SY+2*MINI_TILEY-MINI_TILEY/2);
847 for(y=0;y<3;y++) for(x=0;x<3;x++)
848 DrawMiniElement(1+5*i+x,2+y,level.mampfer_inhalt[i][x][y]);
850 DrawText(SX+MINI_TILEX+(5*i+1)*MINI_TILEX+1,
851 SY+2*MINI_TILEY+(4)*MINI_TILEY-4,
852 int2str(i+1,1),FS_SMALL,FC_YELLOW);
855 /* Inhalt der Amöbe */
856 for(y=0;y<2;y++) for(x=0;x<2;x++)
858 DrawMiniElement(29+x,26+y,EL_ERDREICH);
859 XFillRectangle(display,drawto,gc,
860 SX+29*MINI_TILEX+MINI_TILEX/2-1,
861 SY+26*MINI_TILEY+MINI_TILEY/2-1,
862 MINI_TILEX+2,MINI_TILEY+2);
864 XCopyArea(display,drawto,drawto,gc,
865 SX+29*MINI_TILEX,SY+26*MINI_TILEY,
866 3*MINI_TILEX,3*MINI_TILEY,
867 SX+29*MINI_TILEX-MINI_TILEX/2,SY+26*MINI_TILEY-MINI_TILEY/2);
868 DrawMiniElement(29,26,level.amoebe_inhalt);
870 for(i=0;i<11+3+2;i++)
872 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
873 DOOR_GFX_PAGEX4+ED_BUTTON_MINUS_XPOS,
874 DOOR_GFX_PAGEY1+ED_BUTTON_MINUS_YPOS,
875 DXSIZE-4,ED_BUTTON_MINUS_YSIZE,
876 ED_COUNT_GADGET_XPOS,
877 ED_COUNT_GADGET_YPOS+i*ED_COUNT_GADGET_YSIZE);
880 DrawText(ED_COUNT_VALUE_XPOS,
881 ED_COUNT_VALUE_YPOS+i*ED_COUNT_GADGET_YSIZE,
882 int2str(level.score[i],3),FS_SMALL,FC_YELLOW);
884 DrawText(ED_COUNT_VALUE_XPOS,
885 ED_COUNT_VALUE_YPOS+11*ED_COUNT_GADGET_YSIZE,
886 int2str(level.tempo_amoebe,3),FS_SMALL,FC_YELLOW);
888 DrawText(ED_COUNT_VALUE_XPOS,
889 ED_COUNT_VALUE_YPOS+12*ED_COUNT_GADGET_YSIZE,
890 int2str(level.dauer_sieb,3),FS_SMALL,FC_YELLOW);
892 DrawText(ED_COUNT_VALUE_XPOS,
893 ED_COUNT_VALUE_YPOS+13*ED_COUNT_GADGET_YSIZE,
894 int2str(level.dauer_ablenk,3),FS_SMALL,FC_YELLOW);
896 DrawText(ED_COUNT_VALUE_XPOS,
897 ED_COUNT_VALUE_YPOS+14*ED_COUNT_GADGET_YSIZE,
898 int2str(level.edelsteine,3),FS_SMALL,FC_YELLOW);
900 DrawText(ED_COUNT_VALUE_XPOS,
901 ED_COUNT_VALUE_YPOS+15*ED_COUNT_GADGET_YSIZE,
902 int2str(level.time,3),FS_SMALL,FC_YELLOW);
905 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+0*ED_COUNT_TEXT_YSIZE,
906 "Score for Emerald",FS_SMALL,FC_YELLOW);
907 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+1*ED_COUNT_TEXT_YSIZE,
908 "Score for Diamond",FS_SMALL,FC_YELLOW);
909 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+2*ED_COUNT_TEXT_YSIZE,
910 "Score for smashing a Bug",FS_SMALL,FC_YELLOW);
911 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+3*ED_COUNT_TEXT_YSIZE,
912 "Score for smashing a Spaceship",FS_SMALL,FC_YELLOW);
913 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+4*ED_COUNT_TEXT_YSIZE,
914 "Score for smashing a Cruncher",FS_SMALL,FC_YELLOW);
915 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+5*ED_COUNT_TEXT_YSIZE,
916 "Score for smashing an Alien",FS_SMALL,FC_YELLOW);
917 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+6*ED_COUNT_TEXT_YSIZE,
918 "Score for smashing a Pacman",FS_SMALL,FC_YELLOW);
919 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+7*ED_COUNT_TEXT_YSIZE,
920 "Score for cracking a nut",FS_SMALL,FC_YELLOW);
921 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+8*ED_COUNT_TEXT_YSIZE,
922 "Score for dynamite",FS_SMALL,FC_YELLOW);
923 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+9*ED_COUNT_TEXT_YSIZE,
924 "Score for key",FS_SMALL,FC_YELLOW);
925 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+10*ED_COUNT_TEXT_YSIZE,
926 "Score for each 10 seconds left",FS_SMALL,FC_YELLOW);
927 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+11*ED_COUNT_TEXT_YSIZE,
928 "Speed of the amoeba / Content",FS_SMALL,FC_YELLOW);
929 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+12*ED_COUNT_TEXT_YSIZE,
930 "Time for magic wall",FS_SMALL,FC_YELLOW);
931 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+13*ED_COUNT_TEXT_YSIZE,
932 "Time for wheel",FS_SMALL,FC_YELLOW);
933 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+14*ED_COUNT_TEXT_YSIZE,
934 "Emeralds needed in this level",FS_SMALL,FC_YELLOW);
935 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+15*ED_COUNT_TEXT_YSIZE,
936 "Time available for this level",FS_SMALL,FC_YELLOW);
938 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
939 DOOR_GFX_PAGEX4+ED_WIN_COUNT_XPOS,
940 DOOR_GFX_PAGEY1+ED_WIN_COUNT_YPOS,
941 ED_WIN_COUNT_XSIZE,ED_WIN_COUNT_YSIZE,
942 ED_COUNT_GADGET_XPOS,
943 ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE);
945 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
946 DOOR_GFX_PAGEX4+ED_WIN_COUNT_XPOS+3+2*FONT2_XSIZE,
947 DOOR_GFX_PAGEY1+ED_WIN_COUNT_YPOS,
948 ED_WIN_COUNT_XSIZE-3-2*FONT2_XSIZE,ED_WIN_COUNT_YSIZE,
949 ED_COUNT_GADGET_XPOS+3+i*FONT2_XSIZE,
950 ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE);
951 DrawText(ED_COUNT_GADGET_XPOS+5,
952 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
953 level.name,FS_SMALL,FC_YELLOW);
954 DrawText(ED_COUNT_GADGET_XPOS+(30+3)*FONT2_XSIZE-5,
955 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
956 "Title",FS_SMALL,FC_YELLOW);
958 DrawText(ED_SIZE_GADGET_XPOS,ED_SIZE_GADGET_YPOS-18,
959 "Playfield size:",FS_SMALL,FC_YELLOW);
960 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
961 DOOR_GFX_PAGEX4+ED_BUTTON_MINUS_XPOS,
962 DOOR_GFX_PAGEY1+ED_BUTTON_MINUS_YPOS,
963 DXSIZE-4,ED_BUTTON_MINUS_YSIZE,
965 ED_SIZE_GADGET_YPOS+0*ED_COUNT_GADGET_YSIZE);
966 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
967 DOOR_GFX_PAGEX4+ED_BUTTON_MINUS_XPOS,
968 DOOR_GFX_PAGEY1+ED_BUTTON_MINUS_YPOS,
969 DXSIZE-4,ED_BUTTON_MINUS_YSIZE,
971 ED_SIZE_GADGET_YPOS+1*ED_COUNT_GADGET_YSIZE);
972 DrawText(ED_SIZE_TEXT_XPOS,ED_SIZE_TEXT_YPOS+0*ED_SIZE_TEXT_YSIZE,
973 "Width",FS_SMALL,FC_YELLOW);
974 DrawText(ED_SIZE_TEXT_XPOS,ED_SIZE_TEXT_YPOS+1*ED_SIZE_TEXT_YSIZE,
975 "Height",FS_SMALL,FC_YELLOW);
976 DrawText(ED_SIZE_VALUE_XPOS,ED_SIZE_VALUE_YPOS+0*ED_SIZE_GADGET_YSIZE,
977 int2str(level.fieldx,3),FS_SMALL,FC_YELLOW);
978 DrawText(ED_SIZE_VALUE_XPOS,ED_SIZE_VALUE_YPOS+1*ED_SIZE_GADGET_YSIZE,
979 int2str(level.fieldy,3),FS_SMALL,FC_YELLOW);
982 void AdjustLevelScrollPosition()
986 if (level_xpos > lev_fieldx - 2*SCR_FIELDX + 1)
987 level_xpos = lev_fieldx - 2*SCR_FIELDX + 1;
988 if (lev_fieldx < 2*SCR_FIELDX - 2)
993 if (level_ypos > lev_fieldy - 2*SCR_FIELDY + 1)
994 level_ypos = lev_fieldy - 2*SCR_FIELDY + 1;
995 if (lev_fieldy < 2*SCR_FIELDY - 2)
999 void LevelEd(int mx, int my, int button)
1001 static int last_button = 0;
1002 static int in_field_pressed = FALSE;
1003 static boolean use_floodfill = FALSE;
1007 int x = (mx-SX)/MINI_TILEX;
1008 int y = (my-SY)/MINI_TILEY;
1012 HandlePressedControlButtons();
1013 HandleDrawingFunctions(mx, my, button);
1016 if (use_floodfill) /********** FLOOD FILL **********/
1024 if (mx>=SX && mx<SX+SXSIZE && my>=SY && my<SY+SYSIZE)
1029 if (x>lev_fieldx || y>lev_fieldy ||
1030 (x==0 && level_xpos<0) ||
1031 (x==2*SCR_FIELDX-1 && level_xpos>lev_fieldx-2*SCR_FIELDX) ||
1032 (y==0 && level_ypos<0) ||
1033 (y==2*SCR_FIELDY-1 && level_ypos>lev_fieldy-2*SCR_FIELDY))
1036 from_x = x+level_xpos;
1037 from_y = y+level_ypos;
1038 fill_element = (button==1 ? new_element1 :
1039 button==2 ? new_element2 :
1040 button==3 ? new_element3 : 0);
1042 FloodFill(from_x,from_y,fill_element);
1043 DrawMiniLevel(level_xpos,level_ypos);
1046 use_floodfill = FALSE;
1047 CloseDoor(DOOR_CLOSE_1);
1048 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
1057 else /********** EDIT/CTRL-FENSTER **********/
1059 static unsigned long choice_delay = 0;
1060 int choice = CheckElemButtons(mx,my,button);
1061 int elem_pos = choice-ED_BUTTON_ELEM;
1063 if (((choice == ED_BUTTON_EUP && element_shift>0) ||
1064 (choice == ED_BUTTON_EDOWN &&
1065 element_shift<elements_in_list-MAX_ELEM_X*MAX_ELEM_Y)) &&
1066 DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1068 int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
1072 step = (button==1 ? MAX_ELEM_X : button==2 ? 5*MAX_ELEM_X :
1074 element_shift += (choice==ED_BUTTON_EUP ? -step : step);
1076 step = step * MAX_ELEM_X * (choice == ED_BUTTON_EUP ? -1 : +1);
1077 element_shift += step;
1080 if (element_shift<0)
1082 if (element_shift>elements_in_list-MAX_ELEM_X*MAX_ELEM_Y)
1083 element_shift = elements_in_list-MAX_ELEM_X*MAX_ELEM_Y;
1084 if (element_shift % MAX_ELEM_X)
1085 element_shift += MAX_ELEM_X-(element_shift % MAX_ELEM_X);
1087 for(i=0;i<MAX_ELEM_X*MAX_ELEM_Y;i++)
1088 DrawElemButton(i+2,ED_BUTTON_RELEASED);
1090 else if (elem_pos>=0 && elem_pos<MAX_ELEM_X*MAX_ELEM_Y)
1094 if (elem_pos+element_shift < elements_in_list)
1095 new_element = editor_element[elem_pos+element_shift];
1097 new_element = EL_LEERRAUM;
1100 new_element1 = new_element;
1101 else if (last_button==2)
1102 new_element2 = new_element;
1103 else if (last_button==3)
1104 new_element3 = new_element;
1106 DrawMiniGraphicExt(drawto,gc,
1107 DX+ED_WIN_MB_LEFT_XPOS,
1108 DY+ED_WIN_MB_LEFT_YPOS,
1109 el2gfx(new_element1));
1110 DrawMiniGraphicExt(drawto,gc,
1111 DX+ED_WIN_MB_MIDDLE_XPOS,
1112 DY+ED_WIN_MB_MIDDLE_YPOS,
1113 el2gfx(new_element2));
1114 DrawMiniGraphicExt(drawto,gc,
1115 DX+ED_WIN_MB_RIGHT_XPOS,
1116 DY+ED_WIN_MB_RIGHT_YPOS,
1117 el2gfx(new_element3));
1118 redraw_mask |= REDRAW_DOOR_1;
1120 if (edit_mode == ED_MODE_PROPERTIES)
1121 DrawPropertiesWindow(new_element);
1124 if (edit_mode == ED_MODE_DRAWING) /********** EDIT-FENSTER **********/
1131 switch(CheckEditButtons(mx,my,button))
1133 case ED_BUTTON_CTRL:
1134 CloseDoor(DOOR_CLOSE_2);
1135 DrawControlWindow();
1136 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1137 DOOR_GFX_PAGEX4,DOOR_GFX_PAGEY1+80,
1139 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
1140 OpenDoor(DOOR_OPEN_2);
1141 edit_mode = ED_MODE_INFO;
1143 case ED_BUTTON_FILL:
1144 Request("Caution ! Flood fill mode ! Choose area !",REQ_OPEN);
1145 use_floodfill = TRUE;
1148 case ED_BUTTON_LEFT:
1151 if (!DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1153 if (lev_fieldx<2*SCR_FIELDX-2)
1156 level_xpos -= (button==1 ? 1 : button==2 ? 5 : lev_fieldx);
1160 ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_RIGHT);
1162 DrawMiniLevel(level_xpos,level_ypos);
1165 case ED_BUTTON_RIGHT:
1166 if (level_xpos<=lev_fieldx-2*SCR_FIELDX)
1168 if (!DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1170 if (lev_fieldx<2*SCR_FIELDX-2)
1173 level_xpos += (button==1 ? 1 : button==2 ? 5 : lev_fieldx);
1174 if (level_xpos>lev_fieldx-2*SCR_FIELDX+1)
1175 level_xpos = lev_fieldx-2*SCR_FIELDX+1;
1177 ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_LEFT);
1179 DrawMiniLevel(level_xpos,level_ypos);
1185 if (!DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1187 if (lev_fieldy<2*SCR_FIELDY-2)
1190 level_ypos -= (button==1 ? 1 : button==2 ? 5 : lev_fieldy);
1194 ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_DOWN);
1196 DrawMiniLevel(level_xpos,level_ypos);
1199 case ED_BUTTON_DOWN:
1200 if (level_ypos<=lev_fieldy-2*SCR_FIELDY)
1202 if (!DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1204 if (lev_fieldy<2*SCR_FIELDY-2)
1207 level_ypos += (button==1 ? 1 : button==2 ? 5 : lev_fieldy);
1208 if (level_ypos>lev_fieldy-2*SCR_FIELDY+1)
1209 level_ypos = lev_fieldy-2*SCR_FIELDY+1;
1211 ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_UP);
1213 DrawMiniLevel(level_xpos,level_ypos);
1226 if (mx>=SX && mx<SX+SXSIZE && my>=SY && my<SY+SYSIZE)
1230 if (button && !motion_status)
1231 in_field_pressed = TRUE;
1233 if (!button || !in_field_pressed || button<1 || button>3 ||
1234 (y==0 && level_ypos<0) ||
1235 (y==2*SCR_FIELDY-1 && level_ypos>lev_fieldy-2*SCR_FIELDY) ||
1236 (x==0 && level_xpos<0) ||
1237 (x==2*SCR_FIELDX-1 && level_xpos>lev_fieldx-2*SCR_FIELDX) ||
1238 x>lev_fieldx || y>lev_fieldy)
1241 new_element = (button==1 ? new_element1 :
1242 button==2 ? new_element2 :
1243 button==3 ? new_element3 : 0);
1245 if (new_element != Feld[x+level_xpos][y+level_ypos])
1247 if (new_element==EL_SPIELFIGUR) /* Jeder nur EINE Figur bitte... */
1251 for(x=0;x<lev_fieldx;x++) for(y=0;y<lev_fieldy;y++)
1253 if (Feld[x][y]==EL_SPIELFIGUR || Feld[x][y]==EL_SPIELER1)
1255 Feld[x][y] = EL_LEERRAUM;
1256 if (x-level_xpos>=0 && x-level_xpos<2*SCR_FIELDX &&
1257 y-level_ypos>=0 && y-level_ypos<2*SCR_FIELDY)
1258 DrawMiniElement(x-level_xpos,y-level_ypos,EL_LEERRAUM);
1263 Feld[x+level_xpos][y+level_ypos] = new_element;
1264 DrawMiniElement(x,y,new_element);
1267 else if (!motion_status) /* Mauszeiger nicht im Level-Feld */
1268 in_field_pressed = FALSE;
1275 else if (edit_mode == ED_MODE_INFO)/********** KONTROLL-FENSTER **********/
1277 int choice = CheckCountButtons(mx,my,button);
1278 int step = (button==1 ? 1 : button==2 ? 5 : button==3 ? 10 : 0);
1280 if (choice >= 0 && choice < 36 &&
1281 DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1290 level.score[choice] += step;
1291 if (level.score[choice]<0)
1292 level.score[choice] = 0;
1293 else if (level.score[choice]>255)
1294 level.score[choice] = 255;
1296 else if (choice==11)
1298 level.tempo_amoebe += step;
1299 if (level.tempo_amoebe<0)
1300 level.tempo_amoebe = 0;
1301 else if (level.tempo_amoebe>255)
1302 level.tempo_amoebe = 255;
1304 else if (choice==12)
1306 level.dauer_sieb += step;
1307 if (level.dauer_sieb<0)
1308 level.dauer_sieb = 0;
1309 else if (level.dauer_sieb>255)
1310 level.dauer_sieb = 255;
1312 else if (choice==13)
1314 level.dauer_ablenk += step;
1315 if (level.dauer_ablenk<0)
1316 level.dauer_ablenk = 0;
1317 else if (level.dauer_ablenk>255)
1318 level.dauer_ablenk = 255;
1320 else if (choice==14)
1322 level.edelsteine += step;
1323 if (level.edelsteine<0)
1324 level.edelsteine = 0;
1325 else if (level.edelsteine>999)
1326 level.edelsteine = 999;
1328 else if (choice==15)
1333 else if (level.time>999)
1336 else if (choice==16)
1339 if (lev_fieldx<MIN_LEV_FIELDX)
1340 lev_fieldx = MIN_LEV_FIELDX;
1341 else if (lev_fieldx>MAX_LEV_FIELDX)
1342 lev_fieldx = MAX_LEV_FIELDX;
1343 level.fieldx = lev_fieldx;
1345 else if (choice==17)
1348 if (lev_fieldy<MIN_LEV_FIELDY)
1349 lev_fieldy = MIN_LEV_FIELDY;
1350 else if (lev_fieldy>MAX_LEV_FIELDY)
1351 lev_fieldy = MAX_LEV_FIELDY;
1352 level.fieldy = lev_fieldy;
1356 DrawText(ED_COUNT_VALUE_XPOS,
1357 ED_COUNT_VALUE_YPOS+choice*ED_COUNT_GADGET_YSIZE,
1358 int2str(level.score[choice],3),FS_SMALL,FC_YELLOW);
1359 else if (choice==11)
1360 DrawText(ED_COUNT_VALUE_XPOS,
1361 ED_COUNT_VALUE_YPOS+11*ED_COUNT_GADGET_YSIZE,
1362 int2str(level.tempo_amoebe,3),FS_SMALL,FC_YELLOW);
1363 else if (choice==12)
1364 DrawText(ED_COUNT_VALUE_XPOS,
1365 ED_COUNT_VALUE_YPOS+12*ED_COUNT_GADGET_YSIZE,
1366 int2str(level.dauer_sieb,3),FS_SMALL,FC_YELLOW);
1367 else if (choice==13)
1368 DrawText(ED_COUNT_VALUE_XPOS,
1369 ED_COUNT_VALUE_YPOS+13*ED_COUNT_GADGET_YSIZE,
1370 int2str(level.dauer_ablenk,3),FS_SMALL,FC_YELLOW);
1371 else if (choice==14)
1372 DrawText(ED_COUNT_VALUE_XPOS,
1373 ED_COUNT_VALUE_YPOS+14*ED_COUNT_GADGET_YSIZE,
1374 int2str(level.edelsteine,3),FS_SMALL,FC_YELLOW);
1375 else if (choice==15)
1376 DrawText(ED_COUNT_VALUE_XPOS,
1377 ED_COUNT_VALUE_YPOS+15*ED_COUNT_GADGET_YSIZE,
1378 int2str(level.time,3),FS_SMALL,FC_YELLOW);
1379 else if (choice==16)
1380 DrawText(ED_SIZE_VALUE_XPOS,
1381 ED_SIZE_VALUE_YPOS+0*ED_SIZE_GADGET_YSIZE,
1382 int2str(level.fieldx,3),FS_SMALL,FC_YELLOW);
1383 else if (choice==17)
1384 DrawText(ED_SIZE_VALUE_XPOS,
1385 ED_SIZE_VALUE_YPOS+1*ED_SIZE_GADGET_YSIZE,
1386 int2str(level.fieldy,3),FS_SMALL,FC_YELLOW);
1388 redraw_mask &= ~REDRAW_FIELD;
1390 XCopyArea(display,drawto,window,gc,
1391 ED_COUNT_VALUE_XPOS,
1392 ED_COUNT_VALUE_YPOS+choice*ED_COUNT_GADGET_YSIZE,
1393 3*FONT2_XSIZE,FONT2_YSIZE,
1394 ED_COUNT_VALUE_XPOS,
1395 ED_COUNT_VALUE_YPOS+choice*ED_COUNT_GADGET_YSIZE);
1397 XCopyArea(display,drawto,window,gc,
1399 ED_SIZE_VALUE_YPOS+(choice-16)*ED_SIZE_GADGET_YSIZE,
1400 3*FONT2_XSIZE,FONT2_YSIZE,
1402 ED_SIZE_VALUE_YPOS+(choice-16)*ED_SIZE_GADGET_YSIZE);
1410 switch(CheckCtrlButtons(mx,my,button))
1412 case ED_BUTTON_EDIT:
1413 CloseDoor(DOOR_CLOSE_2);
1414 AdjustLevelScrollPosition();
1415 DrawMiniLevel(level_xpos,level_ypos);
1416 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1417 DOOR_GFX_PAGEX6,DOOR_GFX_PAGEY2,
1419 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
1420 OpenDoor(DOOR_OPEN_2);
1421 edit_mode = ED_MODE_DRAWING;
1423 case ED_BUTTON_CLEAR:
1424 if (Request("Are you sure to clear this level ?",REQ_ASK))
1426 for(x=0;x<MAX_LEV_FIELDX;x++)
1427 for(y=0;y<MAX_LEV_FIELDY;y++)
1428 Feld[x][y] = EL_ERDREICH;
1429 DrawMiniLevel(level_xpos,level_ypos);
1432 case ED_BUTTON_UNDO:
1433 if (leveldir[leveldir_nr].readonly ||
1434 Request("Exit without saving ?",REQ_ASK | REQ_STAY_OPEN))
1436 CloseDoor(DOOR_CLOSE_ALL);
1437 game_status=MAINMENU;
1442 CloseDoor(DOOR_CLOSE_1);
1443 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
1446 case ED_BUTTON_EXIT:
1448 int figur_vorhanden = FALSE;
1450 if (leveldir[leveldir_nr].readonly)
1452 Request("This level is read only !",REQ_CONFIRM);
1456 for(y=0;y<lev_fieldy;y++)
1457 for(x=0;x<lev_fieldx;x++)
1458 if (Feld[x][y]==EL_SPIELFIGUR || Feld[x][y]==EL_SPIELER1)
1459 figur_vorhanden = TRUE;
1461 if (!figur_vorhanden)
1462 Request("No Level without Gregor Mc Duffin please !",
1466 if (Request("Save this level and kill the old ?",
1467 REQ_ASK | REQ_STAY_OPEN))
1469 for(x=0;x<lev_fieldx;x++)
1470 for(y=0;y<lev_fieldy;y++)
1471 Ur[x][y]=Feld[x][y];
1472 SaveLevel(level_nr);
1474 CloseDoor(DOOR_CLOSE_ALL);
1475 game_status=MAINMENU;
1488 if (mx>=ED_COUNT_GADGET_XPOS &&
1489 mx<ED_COUNT_GADGET_XPOS+31*FONT2_XSIZE+10 &&
1490 my>=ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE &&
1491 my<ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE+ED_WIN_COUNT_YSIZE)
1496 DrawText(ED_COUNT_GADGET_XPOS+5,
1497 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1498 level.name,FS_SMALL,FC_GREEN);
1499 DrawText(ED_COUNT_GADGET_XPOS+5+strlen(level.name)*FONT2_XSIZE,
1500 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1501 "<",FS_SMALL,FC_RED);
1508 name_typing = FALSE;
1509 DrawText(ED_COUNT_GADGET_XPOS+5,
1510 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1511 level.name,FS_SMALL,FC_YELLOW);
1512 DrawText(ED_COUNT_GADGET_XPOS+5+strlen(level.name)*FONT2_XSIZE,
1513 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1514 " ",FS_SMALL,FC_RED);
1518 if (mx>=SX+29*MINI_TILEX && mx<SX+30*MINI_TILEX &&
1519 my>=SY+26*MINI_TILEY && my<SY+27*MINI_TILEY)
1523 if (!button || button<1 || button>3)
1526 new_element = (button==1 ? new_element1 :
1527 button==2 ? new_element2 :
1528 button==3 ? new_element3 : 0);
1530 if (new_element != level.amoebe_inhalt)
1532 level.amoebe_inhalt = new_element;
1533 DrawMiniElement(29,26,new_element);
1537 if (mx>=SX+1*MINI_TILEX && mx<SX+(1+4*5)*MINI_TILEX &&
1538 my>=SY+2*MINI_TILEY && my<SY+(2+3)*MINI_TILEY)
1540 int x = (mx-SX-1*MINI_TILEX)/MINI_TILEX;
1541 int y = (my-SY-2*MINI_TILEY)/MINI_TILEY;
1546 if (i>=0 && i<43 && x>=0 && x<3 && y>=0 && y<3)
1548 if (button && !motion_status)
1549 in_field_pressed = TRUE;
1551 if (!button || !in_field_pressed || button<1 || button>3)
1554 new_element = (button==1 ? new_element1 :
1555 button==2 ? new_element2 :
1556 button==3 ? new_element3 : 0);
1558 if (new_element != level.mampfer_inhalt[i][x][y])
1560 level.mampfer_inhalt[i][x][y] = new_element;
1561 DrawMiniElement(1+5*i+x,2+y,new_element);
1564 else if (!motion_status)/* Mauszeiger nicht im Cruncher-Feld */
1565 in_field_pressed = FALSE;
1567 else if (!motion_status) /* Mauszeiger nicht im Cruncher-Feld */
1568 in_field_pressed = FALSE;
1572 last_button = button;
1577 void LevelNameTyping(KeySym key)
1579 unsigned char ascii = 0;
1580 int len = strlen(level.name);
1585 if (key>=XK_A && key<=XK_Z)
1586 ascii = 'A'+(char)(key-XK_A);
1587 else if (key>=XK_a && key<=XK_z)
1588 ascii = 'a'+(char)(key-XK_a);
1589 else if (key>=XK_0 && key<=XK_9)
1590 ascii = '0'+(char)(key-XK_0);
1592 else if (key>=XK_space && key<=XK_at)
1593 ascii = ' '+(char)(key-XK_space);
1594 else if (key==XK_Adiaeresis)
1596 else if (key==XK_Odiaeresis)
1598 else if (key==XK_Udiaeresis)
1600 else if (key==XK_adiaeresis)
1602 else if (key==XK_odiaeresis)
1604 else if (key==XK_udiaeresis)
1606 else if (key==XK_underscore)
1610 if (ascii && len<MAX_LEVNAMLEN-2)
1612 level.name[len] = ascii;
1613 level.name[len+1] = 0;
1616 DrawTextExt(drawto,gc,
1617 ED_COUNT_GADGET_XPOS+5,
1618 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1619 level.name,FS_SMALL,FC_GREEN);
1620 DrawTextExt(window,gc,
1621 ED_COUNT_GADGET_XPOS+5,
1622 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1623 level.name,FS_SMALL,FC_GREEN);
1624 DrawTextExt(drawto,gc,
1625 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
1626 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1627 "<",FS_SMALL,FC_RED);
1628 DrawTextExt(window,gc,
1629 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
1630 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1631 "<",FS_SMALL,FC_RED);
1633 else if ((key==XK_Delete || key==XK_BackSpace) && len>0)
1635 level.name[len-1] = 0;
1638 DrawTextExt(drawto,gc,
1639 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
1640 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1641 "< ",FS_SMALL,FC_GREEN);
1642 DrawTextExt(window,gc,
1643 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
1644 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1645 "< ",FS_SMALL,FC_GREEN);
1647 else if (key==XK_Return)
1649 DrawTextExt(drawto,gc,
1650 ED_COUNT_GADGET_XPOS+5,
1651 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1652 level.name,FS_SMALL,FC_YELLOW);
1653 DrawTextExt(window,gc,
1654 ED_COUNT_GADGET_XPOS+5,
1655 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1656 level.name,FS_SMALL,FC_YELLOW);
1657 DrawTextExt(drawto,gc,
1658 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
1659 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1660 " ",FS_SMALL,FC_YELLOW);
1661 DrawTextExt(window,gc,
1662 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
1663 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1664 " ",FS_SMALL,FC_YELLOW);
1666 name_typing = FALSE;
1670 static void DrawCounterValueField(int counter_id, int value)
1672 int x = SX + counter_info[counter_id].x + ED_WIN_COUNT_XPOS;
1673 int y = SY + counter_info[counter_id].y;
1675 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
1676 DOOR_GFX_PAGEX4 + ED_WIN_COUNT_XPOS,
1677 DOOR_GFX_PAGEY1 + ED_WIN_COUNT_YPOS,
1678 ED_WIN_COUNT_XSIZE, ED_WIN_COUNT_YSIZE,
1681 DrawText(x + ED_COUNT_VALUE_XOFFSET, y + ED_COUNT_VALUE_YOFFSET,
1682 int2str(value, 3), FS_SMALL, FC_YELLOW);
1685 #define TEXT_COLLECTING "Score for collecting"
1686 #define TEXT_SMASHING "Score for smashing"
1687 #define TEXT_CRACKING "Score for cracking"
1688 #define TEXT_SPEED "Speed of growth"
1689 #define TEXT_DURATION "Duration when activated"
1691 static void DrawDrawingWindow()
1694 UnmapLevelEditorWindowGadgets();
1695 MapMainDrawingArea();
1696 AdjustLevelScrollPosition();
1697 DrawMiniLevel(level_xpos, level_ypos);
1700 static void DrawPropertiesWindow(int element)
1703 int num_elements_in_level;
1709 } elements_with_counter[] =
1711 { EL_EDELSTEIN, &level.score[0], TEXT_COLLECTING },
1712 { EL_EDELSTEIN_BD, &level.score[0], TEXT_COLLECTING },
1713 { EL_EDELSTEIN_GELB,&level.score[0], TEXT_COLLECTING },
1714 { EL_EDELSTEIN_ROT, &level.score[0], TEXT_COLLECTING },
1715 { EL_EDELSTEIN_LILA,&level.score[0], TEXT_COLLECTING },
1716 { EL_DIAMANT, &level.score[1], TEXT_COLLECTING },
1717 { EL_KAEFER_R, &level.score[2], TEXT_SMASHING },
1718 { EL_KAEFER_O, &level.score[2], TEXT_SMASHING },
1719 { EL_KAEFER_L, &level.score[2], TEXT_SMASHING },
1720 { EL_KAEFER_U, &level.score[2], TEXT_SMASHING },
1721 { EL_BUTTERFLY_R, &level.score[2], TEXT_SMASHING },
1722 { EL_BUTTERFLY_O, &level.score[2], TEXT_SMASHING },
1723 { EL_BUTTERFLY_L, &level.score[2], TEXT_SMASHING },
1724 { EL_BUTTERFLY_U, &level.score[2], TEXT_SMASHING },
1725 { EL_FLIEGER_R, &level.score[3], TEXT_SMASHING },
1726 { EL_FLIEGER_O, &level.score[3], TEXT_SMASHING },
1727 { EL_FLIEGER_L, &level.score[3], TEXT_SMASHING },
1728 { EL_FLIEGER_U, &level.score[3], TEXT_SMASHING },
1729 { EL_FIREFLY_R, &level.score[3], TEXT_SMASHING },
1730 { EL_FIREFLY_O, &level.score[3], TEXT_SMASHING },
1731 { EL_FIREFLY_L, &level.score[3], TEXT_SMASHING },
1732 { EL_FIREFLY_U, &level.score[3], TEXT_SMASHING },
1733 { EL_MAMPFER, &level.score[4], TEXT_SMASHING },
1734 { EL_MAMPFER2, &level.score[4], TEXT_SMASHING },
1735 { EL_ROBOT, &level.score[5], TEXT_SMASHING },
1736 { EL_PACMAN_R, &level.score[6], TEXT_SMASHING },
1737 { EL_PACMAN_O, &level.score[6], TEXT_SMASHING },
1738 { EL_PACMAN_L, &level.score[6], TEXT_SMASHING },
1739 { EL_PACMAN_U, &level.score[6], TEXT_SMASHING },
1740 { EL_KOKOSNUSS, &level.score[7], TEXT_CRACKING },
1741 { EL_DYNAMIT_AUS, &level.score[8], TEXT_COLLECTING },
1742 { EL_SCHLUESSEL1, &level.score[9], TEXT_COLLECTING },
1743 { EL_SCHLUESSEL2, &level.score[9], TEXT_COLLECTING },
1744 { EL_SCHLUESSEL3, &level.score[9], TEXT_COLLECTING },
1745 { EL_SCHLUESSEL4, &level.score[9], TEXT_COLLECTING },
1746 { EL_AMOEBE_NASS, &level.tempo_amoebe, TEXT_SPEED },
1747 { EL_AMOEBE_NORM, &level.tempo_amoebe, TEXT_SPEED },
1748 { EL_AMOEBE_VOLL, &level.tempo_amoebe, TEXT_SPEED },
1749 { EL_AMOEBE_BD, &level.tempo_amoebe, TEXT_SPEED },
1750 { EL_SIEB_LEER, &level.dauer_sieb, TEXT_DURATION },
1751 { EL_ABLENK_AUS, &level.dauer_ablenk, TEXT_DURATION },
1756 UnmapLevelEditorWindowGadgets();
1758 DrawGraphic(1, 1, el2gfx(element));
1759 DrawText(SX + 3*TILEX, SY + 5*TILEY/4, "Element Properties",
1760 FS_SMALL, FC_YELLOW);
1762 num_elements_in_level = 0;
1763 for(y=0; y<lev_fieldy; y++)
1764 for(x=0; x<lev_fieldx; x++)
1765 if (Feld[x][y] == element)
1766 num_elements_in_level++;
1768 DrawTextF(TILEX, 5*TILEY, FC_YELLOW, "%d x contained in level",
1769 num_elements_in_level);
1771 for (i=0; elements_with_counter[i].element != -1; i++)
1773 if (elements_with_counter[i].element == element)
1775 int x = SX + counter_info[ED_COUNTER_SCORE].x + DXSIZE;
1776 int y = SY + counter_info[ED_COUNTER_SCORE].y;
1778 gadget_score_value = elements_with_counter[i].counter_value;
1779 DrawCounterValueField(ED_COUNTER_SCORE, *gadget_score_value);
1780 DrawText(x + ED_COUNT_VALUE_XOFFSET, y + ED_COUNT_VALUE_YOFFSET,
1781 elements_with_counter[i].text, FS_SMALL, FC_YELLOW);
1782 MapCounterButtons(ED_COUNTER_SCORE);
1788 static void swap_numbers(int *i1, int *i2)
1796 static void swap_number_pairs(int *x1, int *y1, int *x2, int *y2)
1808 static void DrawLineElement(int sx, int sy, int element, boolean change_level)
1810 int lx = sx + level_xpos;
1811 int ly = sy + level_ypos;
1813 DrawMiniElement(sx, sy, (element < 0 ? Feld[lx][ly] : element));
1816 Feld[lx][ly] = element;
1819 static void DrawLine(int from_x, int from_y, int to_x, int to_y,
1820 int element, boolean change_level)
1822 if (from_y == to_y) /* horizontal line */
1828 swap_numbers(&from_x, &to_x);
1830 for (x=from_x; x<=to_x; x++)
1831 DrawLineElement(x, y, element, change_level);
1833 else if (from_x == to_x) /* vertical line */
1839 swap_numbers(&from_y, &to_y);
1841 for (y=from_y; y<=to_y; y++)
1842 DrawLineElement(x, y, element, change_level);
1844 else /* diagonal line */
1846 int len_x = ABS(to_x - from_x);
1847 int len_y = ABS(to_y - from_y);
1850 if (len_y < len_x) /* a < 1 */
1852 float a = (float)len_y / (float)len_x;
1855 swap_number_pairs(&from_x, &from_y, &to_x, &to_y);
1857 for (x=0; x<=len_x; x++)
1859 int y = (int)(a * x + 0.5) * (to_y < from_y ? -1 : +1);
1861 DrawLineElement(from_x + x, from_y + y, element, change_level);
1866 float a = (float)len_x / (float)len_y;
1869 swap_number_pairs(&from_x, &from_y, &to_x, &to_y);
1871 for (y=0; y<=len_y; y++)
1873 int x = (int)(a * y + 0.5) * (to_x < from_x ? -1 : +1);
1875 DrawLineElement(from_x + x, from_y + y, element, change_level);
1881 static void DrawRectangle(int from_x, int from_y, int to_x, int to_y,
1882 int element, boolean change_level)
1884 DrawLine(from_x, from_y, from_x, to_y, element, change_level);
1885 DrawLine(from_x, to_y, to_x, to_y, element, change_level);
1886 DrawLine(to_x, to_y, to_x, from_y, element, change_level);
1887 DrawLine(to_x, from_y, from_x, from_y, element, change_level);
1890 static void DrawFilledBox(int from_x, int from_y, int to_x, int to_y,
1891 int element, boolean change_level)
1896 swap_number_pairs(&from_x, &from_y, &to_x, &to_y);
1898 for (y=from_y; y<=to_y; y++)
1899 DrawLine(from_x, y, to_x, y, element, change_level);
1902 static void DrawAreaBorder(int from_x, int from_y, int to_x, int to_y)
1904 unsigned long border_color = ReadPixel(pix[PIX_SMALLFONT], 2, 16);
1905 int from_sx, from_sy;
1909 swap_numbers(&from_x, &to_x);
1912 swap_numbers(&from_y, &to_y);
1914 from_sx = SX + from_x * MINI_TILEX;
1915 from_sy = SY + from_y * MINI_TILEX;
1916 to_sx = SX + to_x * MINI_TILEX + MINI_TILEX - 1;
1917 to_sy = SY + to_y * MINI_TILEX + MINI_TILEY - 1;
1919 XSetForeground(display, gc, border_color);
1921 XDrawLine(display, drawto, gc, from_sx, from_sy, to_sx, from_sy);
1922 XDrawLine(display, drawto, gc, to_sx, from_sy, to_sx, to_sy);
1923 XDrawLine(display, drawto, gc, to_sx, to_sy, from_sx, to_sy);
1924 XDrawLine(display, drawto, gc, from_sx, to_sy, from_sx, from_sy);
1926 XSetForeground(display, gc, BlackPixel(display,screen));
1928 if (from_x == to_x && from_y == to_y)
1929 MarkTileDirty(from_x/2, from_y/2);
1931 redraw_mask |= REDRAW_FIELD;
1934 static void SelectArea(int from_x, int from_y, int to_x, int to_y,
1935 int element, boolean change_level)
1937 if (element == -1 || change_level)
1938 DrawRectangle(from_x, from_y, to_x, to_y, -1, FALSE);
1940 DrawAreaBorder(from_x, from_y, to_x, to_y);
1943 static void FloodFill(int from_x, int from_y, int fill_element)
1947 static int check[4][2] = { {-1,0}, {0,-1}, {1,0}, {0,1} };
1948 static int safety = 0;
1950 /* check if starting field still has the desired content */
1951 if (Feld[from_x][from_y] == fill_element)
1956 if (safety > lev_fieldx*lev_fieldy)
1957 Error(ERR_EXIT, "Something went wrong in 'FloodFill()'. Please debug.");
1959 old_element = Feld[from_x][from_y];
1960 Feld[from_x][from_y] = fill_element;
1964 x = from_x + check[i][0];
1965 y = from_y + check[i][1];
1967 if (IN_LEV_FIELD(x,y) && Feld[x][y] == old_element)
1968 FloodFill(x, y, fill_element);
1974 /* values for DrawLevelText() modes */
1976 #define TEXT_SETCURSOR 1
1977 #define TEXT_WRITECHAR 2
1978 #define TEXT_BACKSPACE 3
1979 #define TEXT_NEWLINE 4
1982 static void DrawLevelText(int sx, int sy, char letter, int mode)
1984 static short delete_buffer[MAX_LEV_FIELDX];
1985 static int start_sx, start_sy;
1986 static int last_sx, last_sy;
1987 static boolean typing = FALSE;
1988 int letter_element = EL_CHAR_ASCII0 + letter;
1991 if (mode != TEXT_INIT)
1996 if (mode != TEXT_SETCURSOR)
2002 lx = last_sx + level_xpos;
2003 ly = last_sy + level_ypos;
2010 DrawLevelText(0, 0, 0, TEXT_END);
2013 start_sx = last_sx = sx;
2014 start_sy = last_sy = sy;
2015 DrawLevelText(sx, sy, 0, TEXT_SETCURSOR);
2018 case TEXT_SETCURSOR:
2019 DrawMiniElement(last_sx, last_sy, Feld[lx][ly]);
2020 DrawAreaBorder(sx, sy, sx, sy);
2025 case TEXT_WRITECHAR:
2026 if (letter_element >= EL_CHAR_START && letter_element <= EL_CHAR_END)
2028 delete_buffer[sx - start_sx] = Feld[lx][ly];
2029 Feld[lx][ly] = letter_element;
2031 if (sx + 1 < 2*SCR_FIELDX && lx + 1 < lev_fieldx)
2032 DrawLevelText(sx + 1, sy, 0, TEXT_SETCURSOR);
2033 else if (sy + 1 < 2*SCR_FIELDY && ly + 1 < lev_fieldy)
2034 DrawLevelText(start_sx, sy + 1, 0, TEXT_SETCURSOR);
2036 DrawLevelText(0, 0, 0, TEXT_END);
2040 case TEXT_BACKSPACE:
2043 Feld[lx - 1][ly] = delete_buffer[sx - start_sx - 1];
2044 DrawMiniElement(sx - 1, sy, new_element3);
2045 DrawLevelText(sx - 1, sy, 0, TEXT_SETCURSOR);
2050 if (sy + 1 < 2*SCR_FIELDY - 1 && ly + 1 < lev_fieldy - 1)
2051 DrawLevelText(start_sx, sy + 1, 0, TEXT_SETCURSOR);
2053 DrawLevelText(0, 0, 0, TEXT_END);
2057 CopyLevelToUndoBuffer();
2058 DrawMiniElement(sx, sy, Feld[lx][ly]);
2067 static void CopyLevelToUndoBuffer()
2071 undo_buffer_position = (undo_buffer_position + 1) % NUM_UNDO_STEPS;
2073 if (undo_buffer_steps < NUM_UNDO_STEPS - 1)
2074 undo_buffer_steps++;
2076 for(x=0; x<lev_fieldx; x++)
2077 for(y=0; y<lev_fieldy; y++)
2078 UndoBuffer[undo_buffer_position][x][y] = Feld[x][y];
2081 static void RandomPlacement(int button)
2086 new_element = (button == 1 ? new_element1 :
2087 button == 2 ? new_element2 :
2088 button == 3 ? new_element3 : 0);
2090 if (random_placement_method == RANDOM_USE_PERCENTAGE)
2092 for(x=0; x<lev_fieldx; x++)
2093 for(y=0; y<lev_fieldy; y++)
2094 if (RND(100) < random_placement_percentage)
2095 Feld[x][y] = new_element;
2099 int elements_left = random_placement_num_objects;
2101 while (elements_left > 0)
2103 x = RND(lev_fieldx);
2104 y = RND(lev_fieldy);
2106 if (Feld[x][y] != new_element)
2108 Feld[x][y] = new_element;
2114 DrawMiniLevel(level_xpos, level_ypos);
2117 static void HandleDrawingAreas(struct GadgetInfo *gi)
2119 static boolean started_inside_drawing_area = FALSE;
2120 boolean inside_drawing_area = !gi->event.off_borders;
2121 boolean button_press_event;
2122 boolean button_release_event;
2124 int button = gi->event.button;
2125 int sx = gi->event.x, sy = gi->event.y;
2129 if (edit_mode != ED_MODE_DRAWING)
2132 button_press_event = (gi->event.type == GD_EVENT_PRESSED);
2133 button_release_event = (gi->event.type == GD_EVENT_RELEASED);
2135 sx = (sx < 0 ? 0 : sx > 2*SCR_FIELDX - 1 ? 2*SCR_FIELDX - 1 : sx);
2136 sy = (sy < 0 ? 0 : sy > 2*SCR_FIELDY - 1 ? 2*SCR_FIELDY - 1 : sy);
2137 lx = sx + level_xpos;
2138 ly = sy + level_ypos;
2140 lx = (lx < 0 ? 0 : lx > lev_fieldx - 1 ? lev_fieldx - 1 : lx);
2141 ly = (ly < 0 ? 0 : ly > lev_fieldy - 1 ? lev_fieldy - 1 : ly);
2142 sx = lx - level_xpos;
2143 sy = ly - level_ypos;
2145 if (button_press_event)
2146 started_inside_drawing_area = inside_drawing_area;
2148 if (!started_inside_drawing_area)
2151 if ((!button && !button_release_event) ||
2152 sx > lev_fieldx || sy > lev_fieldy ||
2153 (sx == 0 && level_xpos<0) ||
2154 (sx == 2*SCR_FIELDX - 1 && level_xpos > lev_fieldx - 2*SCR_FIELDX) ||
2155 (sy == 0 && level_ypos < 0) ||
2156 (sy == 2*SCR_FIELDY - 1 && level_ypos > lev_fieldy - 2*SCR_FIELDY))
2159 new_element = (button == 1 ? new_element1 :
2160 button == 2 ? new_element2 :
2161 button == 3 ? new_element3 : 0);
2163 switch (drawing_function)
2165 case ED_CTRL_ID_SINGLE_ITEMS:
2166 if (button_release_event)
2167 CopyLevelToUndoBuffer();
2172 if (new_element != Feld[lx][ly])
2174 if (new_element == EL_SPIELFIGUR)
2176 /* remove player at old position */
2177 for(y=0; y<lev_fieldy; y++)
2179 for(x=0; x<lev_fieldx; x++)
2181 if (Feld[x][y] == EL_SPIELFIGUR || Feld[x][y] == EL_SPIELER1)
2183 Feld[x][y] = EL_LEERRAUM;
2184 if (x - level_xpos >= 0 && x - level_xpos < 2*SCR_FIELDX &&
2185 y - level_ypos >= 0 && y - level_ypos < 2*SCR_FIELDY)
2186 DrawMiniElement(x - level_xpos, y - level_ypos, EL_LEERRAUM);
2192 Feld[lx][ly] = new_element;
2193 DrawMiniElement(sx, sy, new_element);
2197 case ED_CTRL_ID_CONNECTED_ITEMS:
2199 static int last_sx = -1;
2200 static int last_sy = -1;
2202 if (button_release_event)
2203 CopyLevelToUndoBuffer();
2207 if (!button_press_event)
2208 DrawLine(last_sx, last_sy, sx, sy, new_element, TRUE);
2216 case ED_CTRL_ID_LINE:
2217 case ED_CTRL_ID_RECTANGLE:
2218 case ED_CTRL_ID_FILLED_BOX:
2219 case ED_CTRL_ID_BRUSH:
2221 static int last_sx = -1;
2222 static int last_sy = -1;
2223 static int start_sx = -1;
2224 static int start_sy = -1;
2225 void (*draw_func)(int, int, int, int, int, boolean);
2227 if (drawing_function == ED_CTRL_ID_LINE)
2228 draw_func = DrawLine;
2229 else if (drawing_function == ED_CTRL_ID_RECTANGLE)
2230 draw_func = DrawRectangle;
2231 else if (drawing_function == ED_CTRL_ID_FILLED_BOX)
2232 draw_func = DrawFilledBox;
2234 draw_func = SelectArea;
2236 if (button_press_event)
2238 draw_func(sx, sy, sx, sy, new_element, FALSE);
2239 start_sx = last_sx = sx;
2240 start_sy = last_sy = sy;
2242 else if (button_release_event)
2244 draw_func(start_sx, start_sy, sx, sy, new_element, TRUE);
2245 CopyLevelToUndoBuffer();
2247 else if (last_sx != sx || last_sy != sy)
2249 draw_func(start_sx, start_sy, last_sx, last_sy, -1, FALSE);
2250 draw_func(start_sx, start_sy, sx, sy, new_element, FALSE);
2257 case ED_CTRL_ID_TEXT:
2258 if (button_press_event)
2259 DrawLevelText(sx, sy, 0, TEXT_INIT);
2262 case ED_CTRL_ID_FLOOD_FILL:
2263 if (button_press_event && Feld[lx][ly] != new_element)
2265 FloodFill(lx, ly, new_element);
2266 DrawMiniLevel(level_xpos, level_ypos);
2267 CopyLevelToUndoBuffer();
2276 static void HandleCounterButtons(struct GadgetInfo *gi)
2278 int id = gi->custom_id;
2279 int button = gi->event.button;
2280 int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
2284 case ED_CTRL_ID_SCORE_DOWN:
2285 case ED_CTRL_ID_SCORE_UP:
2286 *gadget_score_value += (id == ED_CTRL_ID_SCORE_DOWN ? -step : step);
2287 if (*gadget_score_value < 0)
2288 *gadget_score_value = 0;
2289 else if (*gadget_score_value > 255)
2290 *gadget_score_value = 255;
2292 DrawCounterValueField(ED_COUNTER_SCORE, *gadget_score_value);
2300 static void HandleControlButtons(struct GadgetInfo *gi)
2302 int id = gi->custom_id;
2303 int button = gi->event.button;
2304 int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
2306 int player_present = FALSE;
2307 int level_changed = FALSE;
2310 new_element = (button == 1 ? new_element1 :
2311 button == 2 ? new_element2 :
2312 button == 3 ? new_element3 : 0);
2314 if (edit_mode == ED_MODE_DRAWING && drawing_function == ED_CTRL_ID_TEXT)
2315 DrawLevelText(0, 0, 0, TEXT_END);
2317 if (id < ED_NUM_CTRL1_BUTTONS && edit_mode != ED_MODE_DRAWING)
2319 DrawDrawingWindow();
2320 edit_mode = ED_MODE_DRAWING;
2325 case ED_CTRL_ID_SINGLE_ITEMS:
2326 case ED_CTRL_ID_CONNECTED_ITEMS:
2327 case ED_CTRL_ID_LINE:
2328 case ED_CTRL_ID_TEXT:
2329 case ED_CTRL_ID_RECTANGLE:
2330 case ED_CTRL_ID_FILLED_BOX:
2331 case ED_CTRL_ID_FLOOD_FILL:
2332 case ED_CTRL_ID_BRUSH:
2333 drawing_function = id;
2336 case ED_CTRL_ID_WRAP_LEFT:
2337 if (level_xpos >= 0)
2339 if (lev_fieldx < 2*SCR_FIELDX - 2)
2343 if (level_xpos <- 1)
2346 ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_RIGHT);
2348 DrawMiniLevel(level_xpos, level_ypos);
2352 case ED_CTRL_ID_WRAP_RIGHT:
2353 if (level_xpos <= lev_fieldx - 2*SCR_FIELDX)
2355 if (lev_fieldx < 2*SCR_FIELDX - 2)
2359 if (level_xpos > lev_fieldx - 2*SCR_FIELDX + 1)
2360 level_xpos = lev_fieldx - 2*SCR_FIELDX + 1;
2362 ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_LEFT);
2364 DrawMiniLevel(level_xpos, level_ypos);
2368 case ED_CTRL_ID_WRAP_UP:
2369 if (level_ypos >= 0)
2371 if (lev_fieldy < 2*SCR_FIELDY - 2)
2375 if (level_ypos < -1)
2378 ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_DOWN);
2380 DrawMiniLevel(level_xpos, level_ypos);
2384 case ED_CTRL_ID_WRAP_DOWN:
2385 if (level_ypos <= lev_fieldy - 2*SCR_FIELDY)
2387 if (lev_fieldy < 2*SCR_FIELDY - 2)
2391 if (level_ypos > lev_fieldy - 2*SCR_FIELDY + 1)
2392 level_ypos = lev_fieldy - 2*SCR_FIELDY + 1;
2394 ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_UP);
2396 DrawMiniLevel(level_xpos, level_ypos);
2400 case ED_CTRL_ID_PROPERTIES:
2401 DrawPropertiesWindow(new_element);
2402 edit_mode = ED_MODE_PROPERTIES;
2405 case ED_CTRL_ID_RANDOM_PLACEMENT:
2406 RandomPlacement(button);
2407 CopyLevelToUndoBuffer();
2410 case ED_CTRL_ID_UNDO:
2411 if (undo_buffer_steps == 0)
2413 Request("Undo buffer empty !", REQ_CONFIRM);
2417 undo_buffer_position =
2418 (undo_buffer_position - 1 + NUM_UNDO_STEPS) % NUM_UNDO_STEPS;
2419 undo_buffer_steps--;
2421 for(x=0; x<lev_fieldx; x++)
2422 for(y=0; y<lev_fieldy; y++)
2423 Feld[x][y] = UndoBuffer[undo_buffer_position][x][y];
2424 DrawMiniLevel(level_xpos,level_ypos);
2427 case ED_CTRL_ID_INFO:
2428 if (edit_mode != ED_MODE_INFO)
2430 DrawControlWindow();
2431 edit_mode = ED_MODE_INFO;
2435 AdjustLevelScrollPosition();
2436 DrawMiniLevel(level_xpos, level_ypos);
2437 edit_mode = ED_MODE_DRAWING;
2441 case ED_CTRL_ID_CLEAR:
2442 for(x=0; x<MAX_LEV_FIELDX; x++)
2443 for(y=0; y<MAX_LEV_FIELDY; y++)
2444 Feld[x][y] = new_element3;
2445 CopyLevelToUndoBuffer();
2447 DrawMiniLevel(level_xpos, level_ypos);
2450 case ED_CTRL_ID_SAVE:
2451 if (leveldir[leveldir_nr].readonly)
2453 Request("This level is read only !", REQ_CONFIRM);
2457 for(y=0; y<lev_fieldy; y++)
2458 for(x=0; x<lev_fieldx; x++)
2459 if (Feld[x][y] != Ur[x][y])
2460 level_changed = TRUE;
2464 Request("Level has not changed !", REQ_CONFIRM);
2468 for(y=0; y<lev_fieldy; y++)
2469 for(x=0; x<lev_fieldx; x++)
2470 if (Feld[x][y] == EL_SPIELFIGUR || Feld[x][y] == EL_SPIELER1)
2471 player_present = TRUE;
2473 if (!player_present)
2474 Request("No Level without Gregor Mc Duffin please !", REQ_CONFIRM);
2477 if (Request("Save this level and kill the old ?", REQ_ASK))
2479 for(x=0; x<lev_fieldx; x++)
2480 for(y=0; y<lev_fieldy; y++)
2481 Ur[x][y] = Feld[x][y];
2482 SaveLevel(level_nr);
2487 case ED_CTRL_ID_TEST:
2488 for(y=0; y<lev_fieldy; y++)
2489 for(x=0; x<lev_fieldx; x++)
2490 if (Feld[x][y] == EL_SPIELFIGUR || Feld[x][y] == EL_SPIELER1)
2491 player_present = TRUE;
2493 if (!player_present)
2494 Request("No Level without Gregor Mc Duffin please !", REQ_CONFIRM);
2497 for(x=0; x<lev_fieldx; x++)
2498 for(y=0; y<lev_fieldy; y++)
2499 OrigBackup[x][y] = Ur[x][y];
2501 for(x=0; x<lev_fieldx; x++)
2502 for(y=0; y<lev_fieldy; y++)
2503 Ur[x][y] = Feld[x][y];
2505 level_editor_test_game = TRUE;
2506 game_status = PLAYING;
2511 case ED_CTRL_ID_EXIT:
2512 for(y=0; y<lev_fieldy; y++)
2513 for(x=0; x<lev_fieldx; x++)
2514 if (Feld[x][y] != Ur[x][y])
2515 level_changed = TRUE;
2517 if (!level_changed ||
2518 Request("Level has changed! Exit without saving ?",
2519 REQ_ASK | REQ_STAY_OPEN))
2521 CloseDoor(DOOR_CLOSE_1);
2524 CloseDoor(DOOR_CLOSE_ALL);
2527 /* draw smaller door */
2528 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
2529 DOOR_GFX_PAGEX7, 64,
2532 redraw_mask |= REDRAW_ALL;
2534 game_status = MAINMENU;
2539 CloseDoor(DOOR_CLOSE_1);
2540 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
2541 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2542 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2543 OpenDoor(DOOR_OPEN_1);
2548 if (gi->event.type == GD_EVENT_PRESSED)
2549 printf("default: HandleControlButtons: GD_EVENT_PRESSED\n");
2550 else if (gi->event.type == GD_EVENT_RELEASED)
2551 printf("default: HandleControlButtons: GD_EVENT_RELEASED\n");
2552 else if (gi->event.type == GD_EVENT_MOVING)
2553 printf("default: HandleControlButtons: GD_EVENT_MOVING\n");
2555 printf("default: HandleControlButtons: ?\n");
2560 void HandleLevelEditorKeyInput(KeySym key)
2562 if (edit_mode == ED_MODE_DRAWING && drawing_function == ED_CTRL_ID_TEXT)
2564 char *keyname = getKeyNameFromKeySym(key);
2567 if (strlen(keyname) == 1)
2568 letter = keyname[0];
2569 else if (strcmp(keyname, "space") == 0)
2571 else if (strcmp(keyname, "less") == 0)
2573 else if (strcmp(keyname, "equal") == 0)
2575 else if (strcmp(keyname, "greater") == 0)
2578 /* map lower case letters to upper case */
2579 if (letter >= 'a' && letter <= 'z')
2580 letter += (int)('A' - 'a');
2581 else if (letter == 'ä')
2583 else if (letter == 'ä')
2585 else if (letter == 'ä')
2589 DrawLevelText(0, 0, letter, TEXT_WRITECHAR);
2590 else if (key == XK_Delete || key == XK_BackSpace)
2591 DrawLevelText(0, 0, 0, TEXT_BACKSPACE);
2592 else if (key == XK_Return)
2593 DrawLevelText(0, 0, 0, TEXT_NEWLINE);