Crossfire Server, Branches 1.12  R18729
build_map.c
Go to the documentation of this file.
1 /*
2  * static char *rcsid_build_map =
3  * "$Id: build_map.c 11578 2009-02-23 22:02:27Z lalo $";
4  */
5 /*
6  CrossFire, A Multiplayer game for X-windows
7 
8  Copyright (C) 2001-2006 Mark Wedel & Crossfire Development Team
9  Copyright (C) 1992 Frank Tore Johansen
10 
11  This program is free software; you can redistribute it and/or modify
12  it under the terms of the GNU General Public License as published by
13  the Free Software Foundation; either version 2 of the License, or
14  (at your option) any later version.
15 
16  This program is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU General Public License for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with this program; if not, write to the Free Software
23  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 
25  The authors can be reached via e-mail to crossfire-devel@real-time.com
26 */
27 
37 #include <global.h>
38 #include <living.h>
39 #include <spells.h>
40 #include <skills.h>
41 #include <tod.h>
42 #include <sproto.h>
43 
57 static int can_build_over(struct mapdef *map, object *new_item, short x, short y) {
58  object *ob;
59 
60  for (ob = GET_MAP_OB(map, x, y); ob; ob = ob->above) {
61  if (strcmp(ob->arch->name, "rune_mark") == 0)
62  /* you can always build on marking runes, used for connected building things. */
63  continue;
64 
65  if ((ob->head && QUERY_FLAG(ob->head, FLAG_IS_BUILDABLE)) || (!ob->head && QUERY_FLAG(ob, FLAG_IS_BUILDABLE)))
66  /* Check for the flag is required, as this function
67  * can be called recursively on different spots.
68  */
69  continue;
70 
71  switch (new_item->type) {
72  case SIGN:
73  case MAGIC_EAR:
74  /* Allow signs and magic ears to be built on books */
75  if (ob->type != BOOK)
76  return 0;
77  break;
78 
79  case BUTTON:
80  case DETECTOR:
81  case PEDESTAL:
82  case CF_HANDLE:
83  /* Allow buttons and levers to be built under gates */
84  if (ob->type != GATE && ob->type != DOOR)
85  return 0;
86  break;
87 
88  default:
89  return 0;
90  }
91  }
92 
93  /* If item being built is multi-tile, need to check other parts too. */
94  if (new_item->more)
95  return can_build_over(map, new_item->more, x+new_item->more->arch->clone.x-new_item->arch->clone.x, y+new_item->more->arch->clone.y-new_item->arch->clone.y);
96 
97  return 1;
98 }
99 
111 static object *get_connection_rune(object *pl, short x, short y) {
112  object *rune;
113 
114  rune = GET_MAP_OB(pl->map, x, y);
115  while (rune && ((rune->type != SIGN) || (strcmp(rune->arch->name, "rune_mark"))))
116  rune = rune->above;
117  return rune;
118 }
119 
131 static object *get_msg_book(object *pl, short x, short y) {
132  object *book;
133 
134  book = GET_MAP_OB(pl->map, x, y);
135  while (book && (book->type != BOOK))
136  book = book->above;
137  return book;
138 }
139 
152 static object *get_wall(struct mapdef *map, int x, int y) {
153  object *wall;
154 
155  wall = GET_MAP_OB(map, x, y);
156  while (wall && (wall->type != WALL))
157  wall = wall->above;
158 
159  return wall;
160 }
161 
170 static void remove_marking_runes(struct mapdef *map, short x, short y) {
171  object *rune;
172  object *next;
173 
174  rune = GET_MAP_OB(map, x, y);
175  while (rune) {
176  next = rune->above;
177  if ((rune->type == SIGN) && (!strcmp(rune->arch->name, "rune_mark"))) {
178  remove_ob(rune);
179  free_object(rune);
180  }
181  rune = next;
182  }
183 }
184 
202 static int adjust_sign_msg(object *pl, short x, short y, object *tmp) {
203  object *book;
204  char buf[MAX_BUF];
205  char buf2[MAX_BUF];
206 
207  book = get_msg_book(pl, x, y);
208  if (!book) {
210  "You need to put a book or scroll with the message.", NULL);
211  return -1;
212  }
213 
214  tmp->msg = book->msg;
215  add_refcount(tmp->msg);
216 
217  if (tmp->invisible) {
218  if (book->custom_name != NULL) {
219  snprintf(buf, sizeof(buf), "talking %s", book->custom_name);
220  } else {
221  snprintf(buf, sizeof(buf), "talking %s", book->name);
222  }
223  if (tmp->name)
224  free_string(tmp->name);
225  tmp->name = add_string(buf);
226 
227  if (book->name_pl != NULL) {
228  snprintf(buf2, sizeof(buf2), "talking %s", book->name_pl);
229  if (tmp->name_pl)
230  free_string(tmp->name_pl);
231  tmp->name_pl = add_string(buf2);
232  }
233 
234  tmp->face = book->face;
235  tmp->invisible = 0;
236  }
237  remove_ob(book);
238  free_object(book);
239  return 0;
240 }
241 
252 static int find_unused_connected_value(struct mapdef *map) {
253  int connected = 0;
254  int itest = 0;
255  oblinkpt *obp;
256 
257  while (itest++ < 1000) {
258  connected = 1+rand()%20000;
259  for (obp = map->buttons; obp && (obp->value != connected); obp = obp->next)
260  ;
261 
262  if (!obp)
263  return connected;
264  }
265 
266  return -1;
267 }
268 
269 
290 static int find_or_create_connection_for_map(object *pl, short x, short y, object *rune) {
291  object *force;
292  int connected;
293 
294  if (!rune)
295  rune = get_connection_rune(pl, x, y);
296 
297  if (!rune || !rune->msg) {
299  "You need to put a marking rune with the group name.", NULL);
300  return -1;
301  }
302 
303  /* Now, find force in player's inventory */
304  force = pl->inv;
305  while (force && ((force->type != FORCE) || (!force->slaying) || (strcmp(force->slaying, pl->map->path)) || (!force->msg) || (strcmp(force->msg, rune->msg))))
306  force = force->below;
307 
308  if (!force) {
309  /* No force, need to create & insert one */
310  /* Find unused value */
311  connected = find_unused_connected_value(pl->map);
312  if (connected == -1) {
314  "Could not create more groups.", NULL);
315  return -1;
316  }
317 
318  force = create_archetype(FORCE_NAME);
319  force->speed = 0;
320  update_ob_speed(force);
321  force->slaying = add_string(pl->map->path);
322  force->msg = add_string(rune->msg);
323  force->path_attuned = connected;
324  insert_ob_in_ob(force, pl);
325 
326  return connected;
327  }
328 
329  /* Found the force, everything's easy. */
330  return force->path_attuned;
331 }
332 
348 static void fix_walls(struct mapdef *map, int x, int y) {
349  int connect;
350  object *wall;
351  char archetype[MAX_BUF];
352  char *underscore;
353  uint32 old_flags[4];
354  struct archt *new_arch;
355  int flag;
356  int len;
357  int has_window;
358 
359  /* First, find the wall on that spot */
360  wall = get_wall(map, x, y);
361  if (!wall)
362  /* Nothing -> bail out */
363  return;
364 
365  /* Find base name */
366  strncpy(archetype, wall->arch->name, sizeof(archetype));
367  archetype[sizeof(archetype)-1] = '\0';
368  underscore = strchr(archetype, '_');
369  if (!underscore)
370  /* Not in a format we can change, bail out */
371  return;
372  has_window = 0;
373  if (!strcmp(underscore+1, "win1"))
374  has_window = 1;
375  else if (!strcmp(underscore+1, "win2"))
376  has_window = 1;
377  else if (!isdigit(*(underscore+1)))
378  return;
379 
380  underscore++;
381  *underscore = '\0';
382  len = sizeof(archetype)-strlen(archetype)-2;
383 
384  connect = 0;
385 
386  if ((x > 0) && get_wall(map, x-1, y))
387  connect |= 1;
388  if ((x < MAP_WIDTH(map)-1) && get_wall(map, x+1, y))
389  connect |= 2;
390  if ((y > 0) && get_wall(map, x, y-1))
391  connect |= 4;
392  if ((y < MAP_HEIGHT(map)-1) && get_wall(map, x, y+1))
393  connect |= 8;
394 
395  switch (connect) {
396  case 0:
397  strncat(archetype, "0", len);
398  break;
399 
400  case 1:
401  strncat(archetype, "1_3", len);
402  break;
403 
404  case 2:
405  strncat(archetype, "1_4", len);
406  break;
407 
408  case 3:
409  if (has_window) {
410  strncat(archetype, "win2", len);
411  } else {
412  strncat(archetype, "2_1_2", len);
413  }
414  break;
415 
416  case 4:
417  strncat(archetype, "1_2", len);
418  break;
419 
420  case 5:
421  strncat(archetype, "2_2_4", len);
422  break;
423 
424  case 6:
425  strncat(archetype, "2_2_1", len);
426  break;
427 
428  case 7:
429  strncat(archetype, "3_1", len);
430  break;
431 
432  case 8:
433  strncat(archetype, "1_1", len);
434  break;
435 
436  case 9:
437  strncat(archetype, "2_2_3", len);
438  break;
439 
440  case 10:
441  strncat(archetype, "2_2_2", len);
442  break;
443 
444  case 11:
445  strncat(archetype, "3_3", len);
446  break;
447 
448  case 12:
449  if (has_window) {
450  strncat(archetype, "win1", len);
451  } else {
452  strncat(archetype, "2_1_1", len);
453  }
454  break;
455 
456  case 13:
457  strncat(archetype, "3_4", len);
458  break;
459 
460  case 14:
461  strncat(archetype, "3_2", len);
462  break;
463 
464  case 15:
465  strncat(archetype, "4", len);
466  break;
467  }
468 
469  /*
470  * No need to change anything if the old and new names are identical.
471  */
472  if (!strncmp(archetype, wall->arch->name, sizeof(archetype)))
473  return;
474 
475  /*
476  * Before anything, make sure the archetype does exist...
477  * If not, prolly an error...
478  */
479  new_arch = find_archetype(archetype);
480  if (!new_arch)
481  return;
482 
483  /* Now delete current wall, and insert new one
484  * We save flags to avoid any trouble with buildable/non buildable, and so on
485  */
486  for (flag = 0; flag < 4; flag++)
487  old_flags[flag] = wall->flags[flag];
488  remove_ob(wall);
489  free_object(wall);
490 
491  wall = arch_to_object(new_arch);
492  wall->type = WALL;
493  insert_ob_in_map_at(wall, map, NULL, INS_ABOVE_FLOOR_ONLY, x, y);
494  for (flag = 0; flag < 4; flag++)
495  wall->flags[flag] = old_flags[flag];
496 }
497 
519 static int apply_builder_floor(object *pl, object *new_floor, short x, short y) {
520  object *tmp;
521  object *above_floor; /* Item above floor, if any */
522  object *floor; /* Floor which would be removed if required */
523  struct archt *new_wall;
524  int i, xt, yt, wall_removed;
525  char message[MAX_BUF];
526 
527  snprintf(message, sizeof(message), "You change the floor to better suit your tastes.");
528 
529  /*
530  * Now the building part...
531  * First, remove wall(s) and floor(s) at position x, y
532  */
533  above_floor = NULL;
534  floor = NULL;
535  new_wall = NULL;
536  wall_removed = 0;
537  tmp = GET_MAP_OB(pl->map, x, y);
538  while (tmp) {
539  object *above;
540 
541  above = tmp->above;
542  if (WALL == tmp->type) {
543  /* There was a wall, remove it & keep its archetype to make new walls */
544  new_wall = tmp->arch;
545  remove_ob(tmp);
546  free_object(tmp);
547  snprintf(message, sizeof(message), "You destroy the wall and redo the floor.");
548  wall_removed = 1;
549  if (floor != NULL) {
550  remove_ob(floor);
551  free_object(floor);
552  floor = NULL;
553  }
554  } else if ((FLOOR == tmp->type) || (QUERY_FLAG(tmp, FLAG_IS_FLOOR))) {
555  floor = tmp;
556  } else {
557  if (floor != NULL)
558  above_floor = tmp;
559  }
560 
561  tmp = above;
562  }
563 
564  if (wall_removed == 0 && floor != NULL) {
565  if (floor->arch == new_floor->arch) {
566  draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD, "You feel too lazy to redo the exact same floor.", NULL);
567  free_object(new_floor);
568  return 0;
569  }
570  }
571 
572  SET_FLAG(new_floor, FLAG_UNIQUE);
573  SET_FLAG(new_floor, FLAG_IS_FLOOR);
574  new_floor->type = FLOOR;
575  insert_ob_in_map_at(new_floor, pl->map, above_floor, above_floor ? INS_BELOW_ORIGINATOR : INS_ON_TOP, x, y);
576 
577  /* if there was a floor, remove it */
578  if (floor) {
579  remove_ob(floor);
580  free_object(floor);
581  floor = NULL;
582  }
583 
584  /*
585  * Next step: make sure there are either walls or floors around the new square
586  * Since building, you can have: blocking view / floor / wall / nothing
587  */
588  for (i = 1; i <= 8; i++) {
589  xt = x+freearr_x[i];
590  yt = y+freearr_y[i];
591  tmp = GET_MAP_OB(pl->map, xt, yt);
592  if (!tmp) {
593  /* Must insert floor & wall */
594 
595  tmp = arch_to_object(new_floor->arch);
596  /* Better make the floor unique */
597  SET_FLAG(tmp, FLAG_UNIQUE);
599  tmp->type = FLOOR;
600  insert_ob_in_map_at(tmp, pl->map, NULL, 0, xt, yt);
601  /* Insert wall if exists. Note: if it doesn't, the map is weird... */
602  if (new_wall) {
603  tmp = arch_to_object(new_wall);
605  tmp->type = WALL;
606  insert_ob_in_map_at(tmp, pl->map, NULL, 0, xt, yt);
607  }
608  }
609  }
610 
611  /* Finally fixing walls to ensure nice continuous walls
612  * Note: 2 squares around are checked, because potentially we added walls
613  * around the building spot, so need to check that those new walls connect
614  * correctly
615  */
616  for (xt = x-2; xt <= x+2; xt++)
617  for (yt = y-2; yt <= y+2; yt++) {
618  if (!OUT_OF_REAL_MAP(pl->map, xt, yt))
619  fix_walls(pl->map, xt, yt);
620  }
621 
622  /* Tell player about the fix */
624  return 1;
625 }
626 
644 static int apply_builder_wall(object *pl, object *new_wall, short x, short y) {
645  object *current_wall;
646  char message[MAX_BUF];
647 
648  remove_marking_runes(pl->map, x, y);
649 
650  current_wall = get_wall(pl->map, x, y);
651 
652  if (current_wall) {
653  char current_basename[MAX_BUF];
654  char new_basename[MAX_BUF];
655  char *underscore;
656 
657  /* Check if the old and new archetypes have the same prefix */
658  strncpy(current_basename, current_wall->arch->name, sizeof(current_basename));
659  current_basename[sizeof(current_basename)-1] = '\0';
660  underscore = strchr(current_basename, '_');
661  if (underscore && isdigit(*(underscore+1))) {
662  underscore++;
663  *underscore = '\0';
664  }
665  strncpy(new_basename, new_wall->arch->name, sizeof(new_basename));
666  new_basename[sizeof(new_basename)-1] = '\0';
667  underscore = strchr(new_basename, '_');
668  if (underscore && isdigit(*(underscore+1))) {
669  underscore++;
670  *underscore = '\0';
671  }
672  if (!strncmp(current_basename, new_basename, sizeof(new_basename))) {
673  draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD, "You feel too lazy to redo the exact same wall.", NULL);
674  free_object(new_wall);
675  return 0;
676  }
677  }
678 
679  snprintf(message, sizeof(message), "You build a wall.");
680  new_wall->type = WALL;
681 
682  if (current_wall) {
683  /* If existing wall, replace it, no need to fix other walls */
684  remove_ob(current_wall);
685  free_object(current_wall);
686  insert_ob_in_map_at(new_wall, pl->map, NULL, INS_ABOVE_FLOOR_ONLY, x, y);
687  fix_walls(pl->map, x, y);
688  snprintf(message, sizeof(message), "You redecorate the wall to better suit your tastes.");
689  } else {
690  int xt, yt;
691 
692  /* Else insert new wall and fix all walls around */
693  insert_ob_in_map_at(new_wall, pl->map, NULL, INS_ABOVE_FLOOR_ONLY, x, y);
694  for (xt = x-1; xt <= x+1; xt++)
695  for (yt = y-1; yt <= y+1; yt++) {
696  if (OUT_OF_REAL_MAP(pl->map, xt, yt))
697  continue;
698 
699  fix_walls(pl->map, xt, yt);
700  }
701  }
702 
703  /* Tell player what happened */
705  return 1;
706 }
707 
724 static int apply_builder_window(object *pl, object *new_wall_win, short x, short y) {
725  object *current_wall;
726  char archetype[MAX_BUF];
727  struct archt *new_arch;
728  object *window;
729  uint32 old_flags[4];
730  int flag;
731 
732  /* Too bad, we never use the window contained in the building material */
733  free_object(new_wall_win);
734 
735  current_wall = get_wall(pl->map, x, y);
736 
737  if (current_wall) {
738  char *underscore;
739 
740  strncpy(archetype, current_wall->arch->name, sizeof(archetype));
741  archetype[sizeof(archetype)-1] = '\0';
742  underscore = strchr(archetype, '_');
743  if (underscore) {
744  underscore++;
745  /* Check if the current wall has a window */
746  if (!strcmp(underscore, "win1")
747  || !strcmp(underscore, "win2")) {
748  draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD, "You feel too lazy to redo the window.", NULL);
749  return 0;
750  }
751  if (!strcmp(underscore, "2_1_1"))
752  strcpy(underscore, "win1");
753  else if (!strcmp(underscore, "2_1_2"))
754  strcpy(underscore, "win2");
755  else {
756  /* Wrong wall orientation */
757  draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD, "You cannot build a window in that wall.", NULL);
758  return 0;
759  }
760  }
761  } else {
763  "There is no wall there.", NULL);
764  return 0;
765  }
766 
767  new_arch = find_archetype(archetype);
768  if (!new_arch) {
769  /* That type of wall doesn't have corresponding window archetypes */
770  draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD, "You cannot build a window in that wall.", NULL);
771  return 0;
772  }
773 
774  /* Now delete current wall, and insert new one with a window
775  * We save flags to avoid any trouble with buildable/non buildable, and so on
776  */
777  for (flag = 0; flag < 4; flag++)
778  old_flags[flag] = current_wall->flags[flag];
779  remove_ob(current_wall);
780  free_object(current_wall);
781 
782  window = arch_to_object(new_arch);
783  window->type = WALL;
784  insert_ob_in_map_at(window, pl->map, NULL, INS_ABOVE_FLOOR_ONLY, x, y);
785  for (flag = 0; flag < 4; flag++)
786  window->flags[flag] = old_flags[flag];
787 
788  /* Tell player what happened */
789  draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD, "You build a window in the wall.", NULL);
790  return 1;
791 }
792 
814 static int apply_builder_item(object *pl, object *new_item, short x, short y) {
815  int insert_flag;
816  object *floor;
817  object *con_rune;
818  int connected;
819  char name[MAX_BUF];
820 
821  /* Find floor */
822  floor = GET_MAP_OB(pl->map, x, y);
823  if (!floor) {
824  draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD, "Invalid square.", NULL);
825  free_object(new_item);
826  return 0;
827  }
828 
829  while (floor && (floor->type != FLOOR) && (!QUERY_FLAG(floor, FLAG_IS_FLOOR)))
830  floor = floor->above;
831 
832  if (!floor) {
834  "This square has no floor, you can't build here.", NULL);
835  free_object(new_item);
836  return 0;
837  }
838 
839  SET_FLAG(new_item, FLAG_NO_PICK);
840 
841  /*
842  * This doesn't work on non unique maps. pedestals under floor will not be saved...
843  * insert_flag = (material->stats.Str == 1) ? INS_BELOW_ORIGINATOR : INS_ABOVE_FLOOR_ONLY;
844  */
845  insert_flag = INS_ABOVE_FLOOR_ONLY;
846 
847  connected = 0;
848  con_rune = NULL;
849  switch (new_item->type) {
850  case DOOR:
851  case GATE:
852  case BUTTON:
853  case DETECTOR:
854  case TIMED_GATE:
855  case PEDESTAL:
856  case CF_HANDLE:
857  case MAGIC_EAR:
858  case SIGN:
859  /* Signs don't need a connection, but but magic mouths do. */
860  if (new_item->type == SIGN && strcmp(new_item->arch->name, "magic_mouth"))
861  break;
862  con_rune = get_connection_rune(pl, x, y);
863  connected = find_or_create_connection_for_map(pl, x, y, con_rune);
864  if (connected == -1) {
865  /* Player already informed of failure by the previous function */
866  free_object(new_item);
867  return 0;
868  }
869  }
870 
871  /* For magic mouths/ears, and signs, take the msg from a book of scroll */
872  if ((new_item->type == SIGN) || (new_item->type == MAGIC_EAR)) {
873  if (adjust_sign_msg(pl, x, y, new_item) == -1) {
874  free_object(new_item);
875  return 0;
876  }
877  }
878 
879  if (con_rune != NULL) {
880  /* Remove marking rune */
881  remove_ob(con_rune);
882  free_object(con_rune);
883  }
884 
885  insert_ob_in_map_at(new_item, pl->map, floor, insert_flag, x, y);
886  if (connected != 0)
887  add_button_link(new_item, pl->map, connected);
888 
889  query_name(new_item, name, MAX_BUF);
891  "You build the %s",
892  "You build the %s",
893  name);
894  return 1;
895 }
896 
907 void apply_builder_remove(object *pl, int dir) {
908  object *item;
909  short x, y;
910  char name[MAX_BUF];
911 
912  x = pl->x+freearr_x[dir];
913  y = pl->y+freearr_y[dir];
914 
915  /* Check square */
916  item = GET_MAP_OB(pl->map, x, y);
917  if (!item) {
918  /* Should not happen with previous tests, but we never know */
920  "Invalid square.", NULL);
921  LOG(llevError, "apply_builder_remove: (null) square at (%d, %d, %s)\n", x, y, pl->map->path);
922  return;
923  }
924 
925  if (item->type == FLOOR || QUERY_FLAG(item, FLAG_IS_FLOOR))
926  item = item->above;
927 
928  if (!item) {
930  "Nothing to remove.", NULL);
931  return;
932  }
933 
934  /* Now remove object, with special cases (buttons & such) */
935  switch (item->type) {
936  case WALL:
938  "Can't remove a wall with that, build a floor.", NULL);
939  return;
940 
941  case DOOR:
942  case BUTTON:
943  case GATE:
944  case TIMED_GATE:
945  case DETECTOR:
946  case PEDESTAL:
947  case CF_HANDLE:
948  case MAGIC_EAR:
949  case SIGN:
950  /* Special case: must unconnect */
951  if (QUERY_FLAG(item, FLAG_IS_LINKED))
952  remove_button_link(item);
953 
954  /* Fall through */
955  default:
956  /* Remove generic item */
957  query_name(item, name, MAX_BUF);
959  "You remove the %s",
960  "You remove the %s",
961  name);
962  remove_ob(item);
963  free_object(item);
964  }
965 }
966 
978 void apply_map_builder(object *pl, int dir) {
979  object *builder;
980  object *tmp;
981  short x, y;
982 
983  if (!pl->type == PLAYER)
984  return;
985 
986  if (dir == 0) {
988  "You can't build or destroy under yourself.", NULL);
989  return;
990  }
991 
992  x = pl->x+freearr_x[dir];
993  y = pl->y+freearr_y[dir];
994 
995  if ((1 > x) || (1 > y)
996  || ((MAP_WIDTH(pl->map)-2) < x) || ((MAP_HEIGHT(pl->map)-2) < y)) {
998  "Can't build on map edge.", NULL);
999  return;
1000  }
1001 
1002  /*
1003  * Check specified square
1004  * The square must have only buildable items
1005  * Exception: marking runes are all right,
1006  * since they are used for special things like connecting doors / buttons
1007  */
1008 
1009  tmp = GET_MAP_OB(pl->map, x, y);
1010  if (!tmp) {
1011  /* Nothing, meaning player is standing next to an undefined square. */
1012  LOG(llevError, "apply_map_builder: undefined square at (%d, %d, %s)\n", x, y, pl->map->path);
1014  "You'd better not build here, it looks weird.", NULL);
1015  return;
1016  }
1017 
1018  builder = pl->contr->ranges[range_builder];
1019 
1020  if (builder->subtype != ST_BD_BUILD) {
1021  while (tmp) {
1022  if (!QUERY_FLAG(tmp, FLAG_IS_BUILDABLE)
1023  && ((tmp->type != SIGN) || (strcmp(tmp->arch->name, "rune_mark")))) {
1025  "You can't build here.", NULL);
1026  return;
1027  }
1028  tmp = tmp->above;
1029  }
1030  }
1031 
1032  /* Now we know the square is ok */
1033 
1034  if (builder->subtype == ST_BD_REMOVE) {
1035  /* Remover -> call specific function and bail out */
1036  apply_builder_remove(pl, dir);
1037  return;
1038  }
1039 
1040  if (builder->subtype == ST_BD_BUILD) {
1041  object *material;
1042  struct archt *new_arch;
1043  object *new_item;
1044  int built = 0;
1045 
1046  /* Builder -> find material, get new item, call specific function */
1047  /* find the marked item to buld */
1048  material = find_marked_object(pl);
1049  if (!material) {
1051  "You need to mark raw materials to use.", NULL);
1052  return;
1053  }
1054 
1055  if (material->type != MATERIAL) {
1057  "You can't use the marked item to build.", NULL);
1058  return;
1059  }
1060 
1061  /* create a new object from the raw materials */
1062  new_arch = find_archetype(material->slaying);
1063  if (!new_arch) {
1065  "You can't use this strange material.", NULL);
1066  LOG(llevError, "apply_map_builder: unable to find archetype %s\n", material->slaying);
1067  return;
1068  }
1069  new_item = object_create_arch(new_arch);
1070  SET_FLAG(new_item, FLAG_IS_BUILDABLE);
1071 
1072  if (!can_build_over(pl->map, new_item, x, y)) {
1074  "You can't build here.", NULL);
1075  return;
1076  }
1077 
1078  /* insert the new object in the map */
1079  switch (material->subtype) {
1080  case ST_MAT_FLOOR:
1081  built = apply_builder_floor(pl, new_item, x, y);
1082  break;
1083 
1084  case ST_MAT_WALL:
1085  built = apply_builder_wall(pl, new_item, x, y);
1086  break;
1087 
1088  case ST_MAT_ITEM:
1089  built = apply_builder_item(pl, new_item, x, y);
1090  break;
1091 
1092  case ST_MAT_WINDOW:
1093  built = apply_builder_window(pl, new_item, x, y);
1094  break;
1095 
1096  default:
1098  "Don't know how to apply this material, sorry.", NULL);
1099  LOG(llevError, "apply_map_builder: invalid material subtype %d\n", material->subtype);
1100  break;
1101  }
1102  if (built)
1103  decrease_ob(material);
1104  return;
1105  }
1106 
1107  /* Here, it means the builder has an invalid type */
1109  "Don't know how to apply this tool, sorry.", NULL);
1110  LOG(llevError, "apply_map_builder: invalid builder subtype %d\n", builder->subtype);
1111 }
char path[HUGE_BUF]
Definition: map.h:384
static int apply_builder_wall(object *pl, object *new_wall, short x, short y)
Definition: build_map.c:644
Definition: player.h:146
archetype * find_archetype(const char *name)
Definition: arch.c:700
#define FLAG_IS_FLOOR
Definition: define.h:599
#define FLAG_IS_LINKED
Definition: define.h:612
#define INS_BELOW_ORIGINATOR
Definition: object.h:398
#define BUTTON
Definition: define.h:274
#define SET_FLAG(xyz, p)
Definition: define.h:510
static object * get_connection_rune(object *pl, short x, short y)
Definition: build_map.c:111
sstring add_refcount(sstring str)
Definition: shstr.c:202
static void remove_marking_runes(struct mapdef *map, short x, short y)
Definition: build_map.c:170
static object * get_msg_book(object *pl, short x, short y)
Definition: build_map.c:131
object * insert_ob_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Definition: object.c:1761
#define DOOR
Definition: define.h:135
static int find_or_create_connection_for_map(object *pl, short x, short y, object *rune)
Definition: build_map.c:290
void free_string(sstring str)
Definition: shstr.c:272
#define MAP_HEIGHT(m)
Definition: map.h:99
object clone
Definition: object.h:326
sint16 invisible
Definition: object.h:211
short freearr_x[SIZEOFFREE]
Definition: object.c:75
void draw_ext_info(int flags, int pri, const object *pl, uint8 type, uint8 subtype, const char *message, const char *oldmessage)
Definition: standalone.c:171
const char * slaying
Definition: object.h:172
#define ST_MAT_ITEM
Definition: define.h:357
object * ranges[range_size]
Definition: player.h:157
uint8 subtype
Definition: object.h:190
struct obj * above
Definition: object.h:146
#define OUT_OF_REAL_MAP(M, X, Y)
Definition: map.h:238
static int adjust_sign_msg(object *pl, short x, short y, object *tmp)
Definition: build_map.c:202
sint16 x
Definition: object.h:179
uint32 path_attuned
Definition: object.h:194
static object * get_wall(struct mapdef *map, int x, int y)
Definition: build_map.c:152
void draw_ext_info_format(int flags, int pri, const object *pl, uint8 type, uint8 subtype, const char *new_format, const char *old_format,...)
Definition: standalone.c:175
#define ST_MAT_WALL
Definition: define.h:356
long value
Definition: object.h:309
Definition: object.h:321
#define ST_MAT_WINDOW
Definition: define.h:358
#define PLAYER
Definition: define.h:113
#define MAGIC_EAR
Definition: define.h:141
short freearr_y[SIZEOFFREE]
Definition: object.c:81
uint32 flags[4]
Definition: object.h:266
#define MSG_TYPE_APPLY_BUILD
Definition: newclient.h:524
static int apply_builder_window(object *pl, object *new_wall_win, short x, short y)
Definition: build_map.c:724
void remove_ob(object *op)
Definition: object.c:1515
struct oblinkpt * next
Definition: object.h:310
#define ST_BD_BUILD
Definition: define.h:347
const char * name_pl
Definition: object.h:168
object * create_archetype(const char *name)
Definition: arch.c:625
#define ST_MAT_FLOOR
Definition: define.h:355
#define INS_ON_TOP
Definition: object.h:397
#define WALL
Definition: define.h:244
struct mapdef * map
Definition: object.h:155
void remove_button_link(object *op)
Definition: button.c:700
const char * name
Definition: object.h:167
#define PEDESTAL
Definition: define.h:129
struct obj * below
Definition: object.h:145
static void fix_walls(struct mapdef *map, int x, int y)
Definition: build_map.c:348
void add_button_link(object *button, mapstruct *map, int connected)
Definition: button.c:663
sint16 y
Definition: object.h:179
struct pl * contr
Definition: object.h:134
object * find_marked_object(object *op)
Definition: c_object.c:1339
#define ST_BD_REMOVE
Definition: define.h:348
float speed
Definition: object.h:181
#define QUERY_FLAG(xyz, p)
Definition: define.h:514
#define MSG_TYPE_APPLY
Definition: newclient.h:330
#define INS_ABOVE_FLOOR_ONLY
Definition: object.h:395
object * insert_ob_in_ob(object *op, object *where)
Definition: object.c:2510
#define MAX_BUF
Definition: define.h:81
object * object_create_arch(archetype *at)
Definition: arch.c:741
oblinkpt * buttons
Definition: map.h:373
#define BOOK
Definition: define.h:120
#define SIGN
Definition: define.h:280
#define TIMED_GATE
Definition: define.h:138
#define FLOOR
Definition: define.h:233
static int apply_builder_floor(object *pl, object *new_floor, short x, short y)
Definition: build_map.c:519
int snprintf(char *dest, int max, const char *format,...)
Definition: porting.c:498
void apply_map_builder(object *pl, int dir)
Definition: build_map.c:978
#define decrease_ob(xyz)
Definition: global.h:276
#define FORCE
Definition: define.h:296
static int find_unused_connected_value(struct mapdef *map)
Definition: build_map.c:252
const char * custom_name
Definition: object.h:285
#define DETECTOR
Definition: define.h:174
struct archt * arch
Definition: object.h:263
#define MAP_WIDTH(m)
Definition: map.h:97
#define FLAG_IS_BUILDABLE
Definition: define.h:672
#define CF_HANDLE
Definition: define.h:275
static int can_build_over(struct mapdef *map, object *new_item, short x, short y)
Definition: build_map.c:57
const char * msg
Definition: object.h:175
#define FORCE_NAME
Definition: spells.h:196
void update_ob_speed(object *op)
Definition: object.c:1008
sstring add_string(const char *str)
Definition: shstr.c:116
static int apply_builder_item(object *pl, object *new_item, short x, short y)
Definition: build_map.c:814
#define GET_MAP_OB(M, X, Y)
Definition: map.h:193
struct obj * inv
Definition: object.h:148
#define NDI_UNIQUE
Definition: newclient.h:219
struct obj * head
Definition: object.h:154
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:63
unsigned int uint32
Definition: global.h:58
void query_name(const object *op, char *buf, size_t size)
Definition: item.c:628
void free_object(object *ob)
Definition: object.c:1238
Definition: map.h:346
New_Face * face
Definition: object.h:183
#define FLAG_UNIQUE
Definition: define.h:584
#define FLAG_NO_PICK
Definition: define.h:535
#define MATERIAL
Definition: define.h:337
#define GATE
Definition: define.h:273
struct obj * more
Definition: object.h:153
object * arch_to_object(archetype *at)
Definition: arch.c:576
const char * name
Definition: object.h:322
struct archt archetype
uint8 type
Definition: object.h:189
void apply_builder_remove(object *pl, int dir)
Definition: build_map.c:907