1 | |
|
|
2 | /* |
|
|
3 | * static char *rcsid_build_map = |
|
|
4 | * "$Id: build_map.C,v 1.5 2006/09/10 15:59:57 root Exp $"; |
|
|
5 | */ |
|
|
6 | |
|
|
7 | /* |
1 | /* |
8 | CrossFire, A Multiplayer game for X-windows |
2 | CrossFire, A Multiplayer game for X-windows |
9 | |
3 | |
10 | Copyright (C) 2001 Mark Wedel & Crossfire Development Team |
4 | Copyright (C) 2001 Mark Wedel & Crossfire Development Team |
11 | Copyright (C) 1992 Frank Tore Johansen |
5 | Copyright (C) 1992 Frank Tore Johansen |
… | |
… | |
22 | |
16 | |
23 | You should have received a copy of the GNU General Public License |
17 | You should have received a copy of the GNU General Public License |
24 | along with this program; if not, write to the Free Software |
18 | along with this program; if not, write to the Free Software |
25 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
26 | |
20 | |
27 | The authors can be reached via e-mail to crossfire-devel@real-time.com |
21 | The authors can be reached via e-mail to <crossfire@schmorp.de> |
28 | */ |
22 | */ |
29 | |
23 | |
30 | #include <global.h> |
24 | #include <global.h> |
31 | #include <living.h> |
25 | #include <living.h> |
32 | #include <spells.h> |
26 | #include <spells.h> |
… | |
… | |
36 | |
30 | |
37 | /** |
31 | /** |
38 | * Check if objects on a square interfere with building |
32 | * Check if objects on a square interfere with building |
39 | */ |
33 | */ |
40 | int |
34 | int |
41 | can_build_over (mapstruct *map, object *tmp, short x, short y) |
35 | can_build_over (maptile *map, object *tmp, short x, short y) |
42 | { |
36 | { |
43 | object *ob; |
37 | object *ob; |
44 | |
38 | |
45 | ob = GET_MAP_OB (map, x, y); |
39 | ob = GET_MAP_OB (map, x, y); |
46 | while (ob) |
40 | while (ob) |
… | |
… | |
79 | |
73 | |
80 | /** |
74 | /** |
81 | * Erases marking runes at specified location |
75 | * Erases marking runes at specified location |
82 | */ |
76 | */ |
83 | void |
77 | void |
84 | remove_marking_runes (mapstruct *map, short x, short y) |
78 | remove_marking_runes (maptile *map, short x, short y) |
85 | { |
79 | { |
86 | object *rune; |
80 | object *rune; |
87 | object *next; |
81 | object *next; |
88 | |
82 | |
89 | rune = GET_MAP_OB (map, x, y); |
83 | rune = GET_MAP_OB (map, x, y); |
90 | while (rune) |
84 | while (rune) |
91 | { |
85 | { |
92 | next = rune->above; |
86 | next = rune->above; |
93 | if ((rune->type == SIGN) && (!strcmp (rune->arch->name, "rune_mark"))) |
87 | if ((rune->type == SIGN) && (!strcmp (rune->arch->name, "rune_mark"))) |
94 | { |
88 | { |
95 | remove_ob (rune); |
89 | rune->remove (); |
96 | free_object (rune); |
90 | rune->destroy (0); |
97 | } |
91 | } |
98 | rune = next; |
92 | rune = next; |
99 | } |
93 | } |
100 | } |
94 | } |
101 | |
95 | |
… | |
… | |
105 | * \return 'connected' value with no item, or -1 if failure. |
99 | * \return 'connected' value with no item, or -1 if failure. |
106 | * |
100 | * |
107 | * Tries 1000 random values, then returns -1. |
101 | * Tries 1000 random values, then returns -1. |
108 | */ |
102 | */ |
109 | int |
103 | int |
110 | find_unused_connected_value (mapstruct *map) |
104 | find_unused_connected_value (maptile *map) |
111 | { |
105 | { |
112 | int connected = 0; |
106 | int connected = 0; |
113 | int itest = 0; |
107 | int itest = 0; |
114 | oblinkpt *obp; |
108 | oblinkpt *obp; |
115 | |
109 | |
… | |
… | |
214 | |
208 | |
215 | /** |
209 | /** |
216 | * Returns first item of type WALL. |
210 | * Returns first item of type WALL. |
217 | */ |
211 | */ |
218 | object * |
212 | object * |
219 | get_wall (mapstruct *map, int x, int y) |
213 | get_wall (maptile *map, int x, int y) |
220 | { |
214 | { |
221 | object *wall; |
215 | object *wall; |
222 | |
216 | |
223 | wall = GET_MAP_OB (map, x, y); |
217 | wall = GET_MAP_OB (map, x, y); |
224 | while (wall && (WALL != wall->type)) |
218 | while (wall && (WALL != wall->type)) |
… | |
… | |
237 | * Basically it ensures the correct wall is put where needed. |
231 | * Basically it ensures the correct wall is put where needed. |
238 | * |
232 | * |
239 | * Note: x & y must be valid map coordinates. |
233 | * Note: x & y must be valid map coordinates. |
240 | */ |
234 | */ |
241 | void |
235 | void |
242 | fix_walls (mapstruct *map, int x, int y) |
236 | fix_walls (maptile *map, int x, int y) |
243 | { |
237 | { |
244 | int connect; |
238 | int connect; |
245 | object *wall; |
239 | object *wall; |
246 | char archetype[MAX_BUF]; |
240 | char archetype[MAX_BUF]; |
247 | char *underscore; |
241 | char *underscore; |
248 | uint32 old_flags[4]; |
242 | uint32 old_flags[4]; |
249 | struct archetype *new_arch; |
243 | struct archetype *new_arch; |
250 | int flag; |
244 | int flag; |
251 | |
245 | |
|
|
246 | |
252 | /* First, find the wall on that spot */ |
247 | /* First, find the wall on that spot */ |
253 | wall = get_wall (map, x, y); |
248 | wall = get_wall (map, x, y); |
254 | if (!wall) |
249 | if (!wall) |
255 | /* Nothing -> bail out */ |
250 | /* Nothing -> bail out */ |
256 | return; |
251 | return; |
257 | |
252 | |
258 | /* Find base name */ |
253 | /* Find base name */ |
259 | strcpy (archetype, wall->arch->name); |
254 | strcpy (archetype, wall->arch->name); |
260 | underscore = strchr (archetype, '_'); |
255 | underscore = strchr (archetype, '_'); |
261 | |
256 | |
|
|
257 | /* search for the first _ before a number */ |
|
|
258 | while (underscore && !isdigit (*(underscore + 1))) |
|
|
259 | underscore = strchr (underscore + 1, '_'); |
|
|
260 | |
262 | if (!underscore || (!isdigit (*(underscore + 1)))) |
261 | if (!underscore || !isdigit (*(underscore + 1))) |
263 | /* Not in a format we can change, bail out */ |
262 | /* Not in a format we can change, bail out */ |
264 | return; |
263 | return; |
265 | |
264 | |
266 | underscore++; |
265 | underscore++; |
267 | *underscore = '\0'; |
266 | *underscore = '\0'; |
… | |
… | |
349 | |
348 | |
350 | /* |
349 | /* |
351 | * Before anything, make sure the archetype does exist... |
350 | * Before anything, make sure the archetype does exist... |
352 | * If not, prolly an error... |
351 | * If not, prolly an error... |
353 | */ |
352 | */ |
354 | new_arch = find_archetype (archetype); |
353 | new_arch = archetype::find (archetype); |
355 | |
354 | |
356 | if (!new_arch) |
355 | if (!new_arch) |
357 | return; |
356 | return; |
358 | |
357 | |
359 | /* Now delete current wall, and insert new one |
358 | /* Now delete current wall, and insert new one |
360 | * We save flags to avoid any trouble with buildable/non buildable, and so on |
359 | * We save flags to avoid any trouble with buildable/non buildable, and so on |
361 | */ |
360 | */ |
362 | for (flag = 0; flag < 4; flag++) |
361 | for (flag = 0; flag < 4; flag++) |
363 | old_flags[flag] = wall->flags[flag]; |
362 | old_flags[flag] = wall->flags[flag]; |
364 | remove_ob (wall); |
363 | wall->remove (); |
365 | free_object (wall); |
364 | wall->destroy (0); |
366 | |
365 | |
367 | wall = arch_to_object (new_arch); |
366 | wall = arch_to_object (new_arch); |
368 | wall->type = WALL; |
367 | wall->type = WALL; |
369 | insert_ob_in_map_at (wall, map, NULL, INS_ABOVE_FLOOR_ONLY, x, y); |
368 | insert_ob_in_map_at (wall, map, NULL, INS_ABOVE_FLOOR_ONLY, x, y); |
370 | for (flag = 0; flag < 4; flag++) |
369 | for (flag = 0; flag < 4; flag++) |
… | |
… | |
408 | above = tmp->above; |
407 | above = tmp->above; |
409 | if (WALL == tmp->type) |
408 | if (WALL == tmp->type) |
410 | { |
409 | { |
411 | /* There was a wall, remove it & keep its archetype to make new walls */ |
410 | /* There was a wall, remove it & keep its archetype to make new walls */ |
412 | new_wall = tmp->arch; |
411 | new_wall = tmp->arch; |
413 | remove_ob (tmp); |
412 | tmp->remove (); |
414 | free_object (tmp); |
413 | tmp->destroy (0); |
415 | sprintf (message, "You destroy the wall and redo the floor."); |
414 | sprintf (message, "You destroy the wall and redo the floor."); |
416 | } |
415 | } |
417 | else if ((FLOOR == tmp->type) || (QUERY_FLAG (tmp, FLAG_IS_FLOOR))) |
416 | else if ((FLOOR == tmp->type) || (QUERY_FLAG (tmp, FLAG_IS_FLOOR))) |
418 | { |
417 | { |
419 | remove_ob (tmp); |
418 | tmp->remove (); |
420 | free_object (tmp); |
419 | tmp->destroy (0); |
421 | floor_removed = 1; |
420 | floor_removed = 1; |
422 | } |
421 | } |
423 | else |
422 | else |
424 | { |
423 | { |
425 | if (floor_removed) |
424 | if (floor_removed) |
… | |
… | |
429 | tmp = above; |
428 | tmp = above; |
430 | } |
429 | } |
431 | } |
430 | } |
432 | |
431 | |
433 | /* Now insert our floor */ |
432 | /* Now insert our floor */ |
434 | new_floor = find_archetype (material->slaying); |
433 | new_floor = archetype::find (material->slaying); |
435 | if (!new_floor) |
434 | if (!new_floor) |
436 | { |
435 | { |
437 | /* Not found, log & bail out */ |
436 | /* Not found, log & bail out */ |
438 | LOG (llevError, "apply_builder_floor: unable to find archetype %s.\n", &material->slaying); |
437 | LOG (llevError, "apply_builder_floor: unable to find archetype %s.\n", &material->slaying); |
439 | return; |
438 | return; |
… | |
… | |
492 | /* And tell player about the fix */ |
491 | /* And tell player about the fix */ |
493 | new_draw_info (NDI_UNIQUE, 0, pl, message); |
492 | new_draw_info (NDI_UNIQUE, 0, pl, message); |
494 | } |
493 | } |
495 | |
494 | |
496 | /** |
495 | /** |
|
|
496 | * Wall radius fix function |
|
|
497 | */ |
|
|
498 | void fix_walls_around (maptile *map, int x, int y) |
|
|
499 | { |
|
|
500 | for (int xt = x - 1; xt <= x + 1; xt++) |
|
|
501 | for (int yt = y - 1; yt <= y + 1; yt++) |
|
|
502 | { |
|
|
503 | if (OUT_OF_REAL_MAP (map, xt, yt)) |
|
|
504 | continue; |
|
|
505 | |
|
|
506 | fix_walls (map, xt, yt); |
|
|
507 | } |
|
|
508 | } |
|
|
509 | |
|
|
510 | /** |
497 | * Wall building function |
511 | * Wall building function |
498 | * |
512 | * |
499 | * Walls can be build: |
513 | * Walls can be build: |
500 | * - on a floor without anything else |
514 | * - on a floor without anything else |
501 | * - on an existing wall, with or without a floor |
515 | * - on an existing wall, with or without a floor |
… | |
… | |
524 | |
538 | |
525 | /* Find the raw wall in inventory */ |
539 | /* Find the raw wall in inventory */ |
526 | sprintf (message, "You build a wall."); |
540 | sprintf (message, "You build a wall."); |
527 | |
541 | |
528 | /* Now we can actually insert the wall */ |
542 | /* Now we can actually insert the wall */ |
529 | new_wall = find_archetype (material->slaying); |
543 | new_wall = archetype::find (material->slaying); |
530 | if (!new_wall) |
544 | if (!new_wall) |
531 | { |
545 | { |
532 | LOG (llevError, "apply_builder_wall: unable to find archetype %s\n", &material->slaying); |
546 | LOG (llevError, "apply_builder_wall: unable to find archetype %s\n", &material->slaying); |
533 | return; |
547 | return; |
534 | } |
548 | } |
… | |
… | |
539 | insert_ob_in_map_at (tmp, pl->map, 0, INS_ABOVE_FLOOR_ONLY, x, y); |
553 | insert_ob_in_map_at (tmp, pl->map, 0, INS_ABOVE_FLOOR_ONLY, x, y); |
540 | |
554 | |
541 | /* If existing wall, remove it, no need to fix other walls */ |
555 | /* If existing wall, remove it, no need to fix other walls */ |
542 | if (current_wall) |
556 | if (current_wall) |
543 | { |
557 | { |
544 | remove_ob (current_wall); |
558 | current_wall->remove (); |
545 | free_object (current_wall); |
559 | current_wall->destroy (0); |
546 | fix_walls (pl->map, x, y); |
560 | fix_walls (pl->map, x, y); |
547 | sprintf (message, "You redecorate the wall to better suit your tastes."); |
561 | sprintf (message, "You redecorate the wall to better suit your tastes."); |
548 | } |
562 | } |
549 | else |
563 | else |
550 | { |
564 | { |
… | |
… | |
599 | { |
613 | { |
600 | new_draw_info (NDI_UNIQUE, 0, pl, "This square has no floor, you can't build here."); |
614 | new_draw_info (NDI_UNIQUE, 0, pl, "This square has no floor, you can't build here."); |
601 | return; |
615 | return; |
602 | } |
616 | } |
603 | /* Create item, set flag, insert in map */ |
617 | /* Create item, set flag, insert in map */ |
604 | arch = find_archetype (item->slaying); |
618 | arch = archetype::find (item->slaying); |
605 | if (!arch) |
619 | if (!arch) |
606 | return; |
620 | return; |
607 | |
621 | |
608 | tmp = arch_to_object (arch); |
622 | tmp = arch_to_object (arch); |
609 | |
623 | |
… | |
… | |
641 | con_rune = get_connection_rune (pl, x, y); |
655 | con_rune = get_connection_rune (pl, x, y); |
642 | connected = find_or_create_connection_for_map (pl, x, y, con_rune); |
656 | connected = find_or_create_connection_for_map (pl, x, y, con_rune); |
643 | if (connected == -1) |
657 | if (connected == -1) |
644 | { |
658 | { |
645 | /* Player already informed of failure by the previous function */ |
659 | /* Player already informed of failure by the previous function */ |
646 | free_object (tmp); |
660 | tmp->destroy (0); |
647 | return; |
661 | return; |
648 | } |
662 | } |
649 | /* Remove marking rune */ |
663 | /* Remove marking rune */ |
650 | remove_ob (con_rune); |
664 | con_rune->remove (); |
651 | free_object (con_rune); |
665 | con_rune->destroy (0); |
652 | } |
666 | } |
653 | |
667 | |
654 | /* For magic mouths/ears, and signs, take the msg from a book of scroll */ |
668 | /* For magic mouths/ears, and signs, take the msg from a book of scroll */ |
655 | if ((tmp->type == SIGN) || (tmp->type == MAGIC_EAR)) |
669 | if ((tmp->type == SIGN) || (tmp->type == MAGIC_EAR)) |
656 | { |
670 | { |
657 | if (adjust_sign_msg (pl, x, y, tmp) == -1) |
671 | if (adjust_sign_msg (pl, x, y, tmp) == -1) |
658 | { |
672 | { |
659 | free_object (tmp); |
673 | tmp->destroy (0); |
660 | return; |
674 | return; |
661 | } |
675 | } |
662 | } |
676 | } |
663 | |
677 | |
664 | insert_ob_in_map_at (tmp, pl->map, floor, insert_flag, x, y); |
678 | insert_ob_in_map_at (tmp, pl->map, floor, insert_flag, x, y); |
… | |
… | |
725 | /* Fall through */ |
739 | /* Fall through */ |
726 | |
740 | |
727 | default: |
741 | default: |
728 | /* Remove generic item */ |
742 | /* Remove generic item */ |
729 | new_draw_info_format (NDI_UNIQUE, 0, pl, "You remove the %s", query_name (item)); |
743 | new_draw_info_format (NDI_UNIQUE, 0, pl, "You remove the %s", query_name (item)); |
730 | remove_ob (item); |
744 | item->remove (); |
731 | free_object (item); |
745 | item->destroy (0); |
732 | } |
746 | } |
733 | } |
747 | } |
734 | |
748 | |
735 | /** |
749 | /** |
736 | * Global building function |
750 | * Global building function |
… | |
… | |
897 | } |
911 | } |
898 | |
912 | |
899 | tmp->face = book->face; |
913 | tmp->face = book->face; |
900 | tmp->invisible = 0; |
914 | tmp->invisible = 0; |
901 | } |
915 | } |
902 | remove_ob (book); |
916 | book->remove (); |
903 | free_object (book); |
917 | book->destroy (0); |
904 | return 0; |
918 | return 0; |
905 | } |
919 | } |