blob: e44e4daa3ff33f6a646d85a058d69360492e559d [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001// MorgenGrauen MUDlib
2//
3// living/put_and_get.c -- taking and putting things
4//
5// $Id: put_and_get.c 8755 2014-04-26 13:13:40Z Zesstra $
6
7/*
8 Grundlegend neu strukturiert von Amynthor im April-Juni 2007
9
10Die eigentlichen Funktionen:
11
12 private string put_or_get(object o, object dest)
13 Bewegt ein einzelnes Objekt mit automatisch bestimmter Method. Gibt im
14 Erfolgsfall 0 zurueck, sonst die auszugebende Fehlermeldung.
15
16 varargs int drop(object o, mixed msg)
17 varargs int put(object o, object dest, mixed msg)
18 varargs int pick(object o, mixed msg)
19 varargs int give(object o, object dest, mixed msg)
20 varargs int show(object o, object dest, mixed msg)
21 Der Spieler nimmt/legt/gibt/zeigt/laesst ein Objekt fallen, wobei die
22 entsprechenden oder optional abweichende (im Format von P_XXX_MSG) oder
23 gar keine (msg == 1) Meldungen ausgegeben werden. Es liegt in der
24 Verantwortung des Rufenden, sinnvolle Werte zu uebergeben; insbesondere
25 wird nicht geprueft, ob sich die Objekte in der Reichweite des Spielers
26 befinden. Gibt 1 zurueck, wenn das Objekt bewegt wurde, sonst 0.
27
28Hilfsfunktionen:
29
30 private object *__find_objects(string *tokens, object env, int is_source)
31 object *find_objects(string what, object env, int is_source)
32 Sucht im Raum und im Spieler (oder alternativ in der angegebenen Umgebung)
33 nach den in tokens/what bezeichneten Objekten. is_source bestimmt die
34 erwartete grammatische Form (0 fuer "topf auf herd" und 1 fuer "topf von
35 herd", siehe Manpage).
36
37 varargs int drop_objects(string str, mixed msg)
38 varargs int put_objects(string str, int casus, string verb, mixed msg)
39 varargs int pick_objects(string str, mixed msg, int flag)
40 varargs int give_objects(string str, mixed msg)
41 varargs int show_objects(string str, mixed msg)
42 Ein Befehl wie "wirf waffen weg" resultiert in einem Aufruf von
43 drop_objects("waffen"). Diese Funktionen sind hauptsaechlich fuer die
44 Behandlung der jeweiligen Kommandos vorgesehen, koennen jedoch auch fuer
45 eigene Befehle verwendet werden. put_objects() erwartet ausserdem den
46 Kasus ("Du kannst nichts an DER Pinwand befestigen.") und das verwendete
47 Verb in der Gundform ("befestigen"). Das Flag fuer pick_objects() gibt
48 an, ob das Objekt auch einfach herumliegen darf ("nimm ...") oder nicht
49 ("hole ..."). Gibt bei Erfolg 1, sonst 0 zurueck.
50
51 object *moved_objects()
52 object moved_where()
53 Gibt die eben fallengelassenen/gesteckten/... Objekte zurueck und wohin
54 sie gesteckt/wem sie gegeben/gezeigt wurden. Fuer den Fall, dass man
55 anschliessend noch etwas mit ihnen machen moechte.
56
57Die einzelnen Kommandos:
58 static int fallenlassen(string str)
59 static int werfen(string str)
60 static int legen(string str)
61 static int stecken(string str)
62 static int holen(string str)
63 static int nehmen(string str)
64 static int geben(string str)
65 Minimale Wrapper fuer XXX_objects(), entfernen "fallen", "weg" bzw. "ab"
66 aus den Argumenten und setzen entsprechende Standard-Fehlermeldungen.
67
68 protected void add_put_and_get_commands()
69 Registriert obige Funktionen per add_action().
70
71Aus reinen Kompatibilitaetsgruenden weiterhin enthalten:
72
73 object* find_obs(string str, int meth)
74 int pick_obj(object ob)
75 int drop_obj(object ob)
76 int put_obj(object ob, object where)
77 int give_obj(object ob, object where)
78 siehe Manpages
79
80*/
81
82/*
83 21. Okt 1998 komplette neu programmierung von put_and_get.c (Padreic)
84- die Gruppenauswahlen alles, waffen und ruestungen sind jetzt immer moeglich
85 die Gruppen sind sehr leicht erweiterbar und man sollte sich nicht scheuen
86 davon gebrauch zu machen...
87- mit "in mir" und "im raum" kann man den abzusuchenden Raum selbst eingrenzen
88- mit "alle|jede|jeden|jedes <id>" kann man auch ganze objektgruppen auswaehlen
89*/
90
91#pragma strong_types
92#pragma save_types
93#pragma range_check
94#pragma no_clone
MG Mud User88f12472016-06-24 23:31:02 +020095
96#define NEED_PROTOTYPES
97#include <language.h>
98#include <thing/description.h>
99#include <thing/properties.h>
100#include <moving.h>
101#include <container.h>
102#undef NEED_PROTOTYPES
103
104#include <defines.h>
105#include <properties.h>
106#include <wizlevels.h>
107
108#define TME(str) tell_object(this_object(), \
109 break_string(str, 78, 0, BS_LEAVE_MY_LFS))
110#define TOB(ob,str) tell_object(ob, break_string(str, 78, 0, BS_LEAVE_MY_LFS))
111#define SAY(str) tell_room(environment(), \
112 break_string(str, 78, 0, BS_LEAVE_MY_LFS), ({this_object()}))
113#define SAY2(obs, str) tell_room(environment(), \
114 break_string(str, 78, 0, BS_LEAVE_MY_LFS), ({this_object()}) + obs)
115#define NF(str) _notify_fail(break_string(str, 78, 0, BS_LEAVE_MY_LFS))
116
117private nosave closure cl;
118private nosave string wen0, wen1, wer0;
119private nosave object *last_moved_objects;
120private nosave object last_moved_where;
121
122
123/*********************** Die eigentlichen Funktionen ************************/
124
125private string put_or_get(object o, object dest)
126
127/* Bewegt ein einzelnes Objekt <o> in das Zielobjekt <dest>. Verwendet dazu
128 * je nach Umstaenden (Ziel ist der Spieler, die Umgebung, ein Lebewesen) den
129 * entsprechenden Wert fuer <method>. Gibt im Erfolgsfall 0 zurueck, erstellt
130 * sonst die auszugebende Fehlermeldung und gibt diese zurueck.
131 */
132
133{
134 int method, ret;
Zesstra42495e72019-11-23 16:01:25 +0100135 <string|int> str;
MG Mud User88f12472016-06-24 23:31:02 +0200136
137 //if (living(o))
138 // raise_error(sprintf("Lebendes Argument fuer put_or_get: %O\n", o));
139
140 if (dest == this_object()) /* pick */
141 method = M_GET;
142 else if (dest == environment()) /* drop */
143 method = M_PUT;
144 else if (living(dest)) /* give */
145 method = M_GIVE;
146 else { /* put */
147 method = M_PUT | M_GET;
148 if (first_inventory(o))
149 return o->Name(WER, 1) + " ist nicht leer!";
150 }
151
152 if ((ret = o->move(dest, method)) > 0)
153 return 0;
154
155 switch (ret) {
156 case ME_TOO_HEAVY:
157 if (dest == this_object())
158 if (QueryProp(P_GHOST))
159 return "Als Geist kannst Du nichts mitnehmen.";
160 else
161 return "Du kannst " + wen1 + " nicht mehr tragen.";
162
163 if (stringp(str = dest->QueryProp(P_TOO_HEAVY_MSG)))
164 return capitalize(replace_personal(str, ({o, dest}), 1));
165
166 if (living(dest)) {
167 if (dest->QueryProp(P_GHOST))
168 return "Als Geist kann " + dest->name(WER, 1) +
169 " nichts mitnehmen.";
170 else
171 return dest->Name(WER, 1) + " kann " +
172 wen0 + " nicht mehr tragen.";
173 }
174
175 if (dest == environment())
176 return (stringp(str = dest->Name(WER, 1)) && sizeof(str) ?
177 str : "Der Raum") + " wuerde dann zu schwer werden.";
178
179 return capitalize(wer0 + " passt in " + dest->name(WEN, 1) +
180 " nicht mehr rein.");
181
182 case ME_CANT_BE_DROPPED:
Arathorn25568d42019-12-03 00:27:24 +0100183 str = o->QueryProp(P_NODROP);
184 if (o && stringp(str) && sizeof(str))
MG Mud User88f12472016-06-24 23:31:02 +0200185 return str;
186
187 if (dest == environment())
188 return "Du kannst " + wen1 + " nicht wegwerfen!";
189
190 if (living(dest))
191 return "Du kannst " + wen1 + " nicht weggeben.";
192
193 return "So wirst Du " + wen1 + " nicht los...";
194
195 case ME_CANT_BE_TAKEN:
Zesstraad154af2020-01-11 12:44:15 +0100196 str = o->QueryProp(P_NOGET);
Arathorn25568d42019-12-03 00:27:24 +0100197 if (o && stringp(str) && sizeof(str))
MG Mud User88f12472016-06-24 23:31:02 +0200198 return str;
199
Zesstrac2735d42020-01-15 17:14:47 +0100200 if (environment(o) &&
Zesstraad154af2020-01-11 12:44:15 +0100201 stringp(str = environment(o)->QueryProp(P_NOLEAVE_MSG)))
MG Mud User88f12472016-06-24 23:31:02 +0200202 return capitalize(
203 replace_personal(str, ({o, environment(o)}), 1));
204
205 //if (dest != environment())
206 // return "Du kannst " + wen1 + " nicht einmal nehmen.";
207
208 return "Du kannst " + wen1 + " nicht nehmen.";
209
210 case ME_CANT_BE_INSERTED:
211 if (stringp(str = dest->QueryProp(P_NOINSERT_MSG)))
212 return capitalize(replace_personal(str, ({o, dest}), 1));
213
214 if (dest == environment())
215 return "Das darfst Du hier nicht ablegen.";
216
217 if (dest == this_object())
218 return "Du kannst " + wen1 + " nicht nehmen.";
219
220 if (living(dest))
221 return "Das kannst Du " + dest->name(WEM, 1) + " nicht geben.";
222
223 return capitalize(wen0 + " kannst Du dort nicht hineinstecken.");
224
225 case ME_CANT_LEAVE_ENV:
Zesstrac2735d42020-01-15 17:14:47 +0100226 if (environment(o) &&
Zesstraad154af2020-01-11 12:44:15 +0100227 stringp(str = environment(o)->QueryProp(P_NOLEAVE_MSG)))
MG Mud User88f12472016-06-24 23:31:02 +0200228 return capitalize(
229 replace_personal(str, ({o, environment(o)}), 1));
230
231 if (environment(o) != this_object())
232 return "Du kannst " + wen1 + " nicht nehmen.";
233
234 if (dest == environment())
235 return "Du kannst " + wen1 + " nicht wegwerfen!";
236
237 if (living(dest))
238 return "Du kannst " + wen1 + " nicht weggeben.";
239
240 return "So wirst Du " + wen1 + " nicht los...";
241
242 case ME_TOO_HEAVY_FOR_ENV:
243 if (stringp(str = dest->QueryProp(P_ENV_TOO_HEAVY_MSG)))
244 return capitalize(replace_personal(str, ({o, dest}), 1));
245
246 if (environment(dest) == this_object())
247 return dest->Name(WER, 1) +
248 " wuerde Dir dann zu schwer werden.";
249
250 return (stringp(str = environment(dest)->Name(WER, 1))
251 && sizeof(str) ? str : "Der Raum") +
252 " wuerde dann zu schwer werden.";
253
254 case TOO_MANY_OBJECTS:
255 if (stringp(str = dest->QueryProp(P_TOO_MANY_MSG)))
256 return capitalize(replace_personal(str, ({o, dest}), 1));
257
258 if (dest == this_object())
259 return "Soviele Gegenstaende kannst Du unmoeglich tragen!";
260
261 if (dest == environment())
262 return "Dafuer ist hier nicht mehr genug Platz.";
263
264 if (living(dest))
265 return dest->Name(WER, 1) + " kann " + wen0 +
266 " nicht mehr tragen.";
267
268 return "Dafuer ist nicht mehr genug Platz in " +
269 dest->name(WEM, 1) + ".";
270
271 default:
272 if (dest == this_object())
273 return "Du kannst " + wen1 + " nicht nehmen.";
274
275 if (dest == environment())
276 return "Du kannst " + wen1 + " nicht wegwerfen!";
277
278 if (living(dest))
279 return "Du kannst " + wen1 + " nicht weggeben.";
280
281 return capitalize(wen0 + " kannst Du dort nicht hineinstecken.");
282 }
MG Mud User88f12472016-06-24 23:31:02 +0200283}
284
285
286/* varargs int drop(object o, mixed msg)
287 * varargs int put(object o, object dest, mixed msg)
288 * varargs int pick(object o, mixed msg)
289 * varargs int give(object o, object dest, mixed msg)
290 * varargs int show(object o, object dest, mixed msg)
291 *
292 * Der Spieler nimmt/legt/gibt/zeigt/laesst ein Objekt fallen, wobei die
293 * entsprechenden oder optional abweichende (im Format von P_XXX_MSG) oder
294 * gar keine (msg == 1) Meldungen ausgegeben werden. Es liegt in der
295 * Verantwortung des Rufenden, sinnvolle Werte zu uebergeben; insbesondere
296 * wird nicht geprueft, ob sich die Objekte in der Reichweite des Spielers
297 * befinden. Gibt 1 zurueck, wenn das Objekt bewegt wurde, sonst 0.
298 */
299
300varargs int drop(object o, mixed msg)
301{
302 string str;
303
304 // vorher speichern, falls das Objekt zerstoert wird
305 cl = symbol_function("name", o);
306 wen0 = funcall(cl, WEN, 0);
307 wen1 = funcall(cl, WEN, 1);
308 wer0 = 0;
309
310 if (!msg)
311 msg = o->QueryProp(P_DROP_MSG);
312
313 if (str = put_or_get(o, environment())) {
314 TME(str);
315 return 0;
316 }
317
318 if (!msg) {
319 TME("Du laesst " + wen1 + " fallen.");
320 SAY(Name(WER,1) + " laesst " + wen0 + " fallen.");
321 } else if (pointerp(msg))
322 switch (sizeof(msg)) {
323 // Wenn es zwei Strings gibt, geht die 2. ans Environment
324 case 2:
325 SAY(replace_personal(msg[1], ({this_object(), o||wen0}), 1));
326 case 1:
327 TME(replace_personal(msg[0], ({this_object(), o||wen1}), 1));
328 break;
329 default:
330 raise_error(sprintf(
331 "Falsches Format fuer P_DROP_MSG: %O\n", o||wen1));
332 }
333
334 return 1;
335}
336
337varargs int put(object o, object dest, mixed msg)
338{
339 string str;
340
341 // Falls das jemand von aussen ruft und Schrott uebergibt...
342 //if (living(dest))
343 // raise_error(sprintf("Lebendes Ziel fuer put(): %O\n", dest));
344 if (dest == environment())
345 raise_error("Ziel fuer put() ist Umgebung des Spielers\n");
346
347 // vorher speichern, falls das Objekt zerstoert wird
348 cl = symbol_function("name", o);
349 wen0 = funcall(cl, WEN, 0);
350 wen1 = funcall(cl, WEN, 1);
351 wer0 = funcall(cl, WER, 0);
352
353 if (!msg)
354 msg = o->QueryProp(P_PUT_MSG);
355
356 if (str = put_or_get(o, dest)) {
357 TME(str);
358 return 0;
359 }
360
361
362 if (!msg) {
Zesstrabc1e21c2016-07-24 14:43:54 +0200363 TME("Du steckst " + wen1 + " "
364 + dest->QueryProp(P_DEST_PREPOSITION) + " "
365 + dest->name(WEN, 1) + ".");
MG Mud User88f12472016-06-24 23:31:02 +0200366 if (environment())
Zesstrabc1e21c2016-07-24 14:43:54 +0200367 SAY(Name(WER, 1) + " steckt " + wen0 + " "
368 + dest->QueryProp(P_DEST_PREPOSITION) + " "
369 + dest->name(WEN, 0) + ".");
MG Mud User88f12472016-06-24 23:31:02 +0200370 }
371 else if (pointerp(msg)) {
372 switch (sizeof(msg)) {
373 case 2:
374 if (environment())
375 SAY(replace_personal(msg[1], ({this_object(), o||wen0, dest}), 1));
376 case 1:
377 TME(replace_personal(msg[0], ({this_object(), o||wen1, dest}), 1));
378 break;
379 default:
380 raise_error(sprintf(
381 "Falsches Format fuer P_PUT_MSG: %O\n",o||wen1));
382 }
383 }
384
385 return 1;
386}
387
388varargs int pick(object o, mixed msg)
389{
390 string str;
391
392 // vorher speichern, falls das Objekt zerstoert wird
393 cl = symbol_function("name", o);
394 wen0 = 0;
395 wen1 = funcall(cl, WEN, 1);
396 wer0 = 0;
397
398 if (!msg)
399 msg = o->QueryProp(P_PICK_MSG);
400
401 if (str = put_or_get(o, this_object())) {
402 TME(str);
403 return 0;
404 }
405
406 if (!msg) {
407 TME("Du nimmst " + wen1 + ".");
408 SAY(Name(WER, 1) + " nimmt " + wen1 + ".");
409 } else if (pointerp(msg))
410 switch (sizeof(msg)) {
411 case 2:
412 SAY(replace_personal(msg[1], ({this_object(), o||wen1}), 1));
413 case 1:
414 TME(replace_personal(msg[0], ({this_object(), o||wen1}), 1));
415 break;
416 default:
417 raise_error(sprintf(
418 "Falsches Format fuer P_PICK_MSG: %O\n", o||wen1));
419 }
420
421 return 1;
422}
423
424varargs int give(object o, object dest, mixed msg)
425{
426 string zname, gname;
427 string str;
428
429 // Falls das jemand von aussen ruft und Schrott uebergibt...
430 if (!living(dest))
431 raise_error(sprintf("Totes Ziel fuer give(): %O\n", dest));
432
433 zname = dest->name(WEM, 1);
434 gname = Name(WER, 1);
435
436 // vorher speichern, falls das Objekt zerstoert wird
437 cl = symbol_function("name", o);
438 wen0 = funcall(cl, WEN, 0);
439 wen1 = funcall(cl, WEN, 1);
440 wer0 = 0;
441
442 if (!msg)
443 msg = o->QueryProp(P_GIVE_MSG);
444
445 if (str = put_or_get(o, dest)) {
446 TME(str);
447 return 0;
448 }
449
450 if (!msg) {
451 TME("Du gibst " + zname + " " + wen1 + ".");
452 TOB(dest, gname + " gibt Dir " + wen0 + ".");
453 SAY2(({dest}), gname + " gibt " + zname + " " + wen0 + ".");
454 } else if (pointerp(msg))
455 switch (sizeof(msg)) {
456 case 3:
457 TOB(dest, replace_personal(
458 msg[2], ({this_object(), o||wen0, dest||zname}), 1));
459 case 2:
460 SAY2(({dest, this_object()}), replace_personal(
461 msg[1], ({this_object(), o||wen0, dest||zname}), 1));
462 case 1:
463 TME(replace_personal(
464 msg[0], ({this_object(), o||wen1, dest||zname}), 1));
465 break;
466 default:
467 raise_error(sprintf(
468 "Falsches Format fuer P_GIVE_MSG: %O\n", o||wen1));
469 }
470
471 if (!query_once_interactive(dest))
472 dest->give_notify(o);
473
474 return 1;
475}
476
477varargs int show(object o, object whom, mixed msg)
478{
479 string zname, gname;
480 string wen0, wen2, long;
481
482 zname = whom ? whom->name(WEM, 1) : "allen";
483 gname = Name(WER, 1);
484
485 if (!msg)
486 msg = o->QueryProp(P_SHOW_MSG);
487
488 if (environment(o) == this_object() ||
489 environment(environment(o)) == this_object()) {
490 wen0 = o->name(WEN, 0);
491
492 /* Der Akkusativ muss mit dem unbestimmten Artikel gebildet werden,
493 * damit eventuelle Adjektive die richtige Endung besitzen.
494 * (ein kleines Schwert -> kleines Schwert -> Dein kleines Schwert)
495 */
496
497 if (o->QueryProp(P_ARTICLE) && member(wen0, ' ') >= 0) {
498 int obgender = o->QueryProp(P_GENDER);
499 int obnum = o->QueryProp(P_AMOUNT) > 1 ? PLURAL : SINGULAR;
500
501 // Wichtig: P_AMOUNT ist 0 fuer Objekte, die nicht von unit erben.
502 // Da unit.c kein P_AMOUNT==0 zulaesst, nehmen wir diesen Fall als
503 // singular an. *Rumata
504
505 wen2 = wen0[member(wen0, ' ')..];
506 wen0 = QueryPossPronoun(o, WEN, obnum) + wen2;
507
508 if (obnum == PLURAL || obgender == FEMALE)
509 wen2 = "Deine" + wen2;
510 else if (obgender == MALE)
511 wen2 = "Deinen" + wen2;
512 else
513 wen2 = "Dein" + wen2;
514 } else
515 wen2 = wen0;
516 } else
517 wen2 = wen0 = o->name(WEN, 1);
518
519 // vorher speichern, falls das Objekt im catch_tell() zerstoert wird
520 long = o->long(4);
521
522 if (!msg) {
523 TME("Du zeigst " + zname + " " + wen2 + ".");
524 if (!whom)
525 SAY(gname + " zeigt Dir " + wen0 + ".");
526 else {
527 TOB(whom, gname + " zeigt Dir " + wen0 + ".");
528 SAY2(({whom}), gname + " zeigt " + zname + " " + wen0 + ".");
529 }
530 } else if (pointerp(msg))
531 switch (sizeof(msg)) {
532 case 3:
533 if (whom)
534 TOB(whom, replace_personal(
535 msg[2], ({this_object(), o||wen0, whom||zname}), 1));
536 else
537 SAY(replace_personal(
538 msg[2], ({this_object(), o||wen0, whom||zname}), 1));
539 case 2:
540 if (whom)
541 SAY2(({whom, this_object()}), replace_personal(
542 msg[1], ({this_object(), o||wen0, whom||zname}), 1));
543 case 1:
544 TME(replace_personal(
545 msg[0], ({this_object(), o||wen2, whom||zname}), 1));
546 break;
547 default:
548 raise_error(sprintf(
549 "Falsches Format fuer P_SHOW_MSG: %O\n", o||wen0));
550 }
551
552 if (!whom)
553 SAY(long);
554 else {
555 TOB(whom, long);
556 if (!query_once_interactive(whom))
557 whom->show_notify(o);
558 }
559
560 return 1;
561}
562
563
564/***************************** Hilfsfunktionen *****************************/
565
566/* private object *__find_objects(string *tokens, object env, int is_source);
567 * object *find_objects(string what, object env, int is_source);
568 *
569 * Sucht im Raum und im Spieler (oder alternativ in der angegebenen Umgebung)
570 * nach den in tokens/what bezeichneten Objekten. is_source bestimmt die
571 * erwartete grammatische Form (0 fuer "topf auf herd" und 1 fuer "topf von
572 * herd", siehe Manpage).
573 */
574
575private object *__find_objects(string *tokens, object env, int is_source)
576{
577 object ob, *obs;
578
579 // is_source == 0: Objekt soll nicht bewegt werden ("topf auf herd")
580 // 1: Objekt soll bewegt werden ("topf von herd")
Zesstra08e60732018-11-15 20:37:11 +0100581 // 2: Kennzeichnet rekursiven Aufruf, falls Objekt bewegt
582 // werden soll.
MG Mud User88f12472016-06-24 23:31:02 +0200583
Zesstrae8d5a0b2018-11-16 23:21:37 +0100584 // ganz am Ende von den tokens steht ggf. der vom User gewuenschte Anfang
585 // der Suche nache dem Objekt (z.B. "fackel aus truhe hier" oder "seil aus
586 // paket in mir".
MG Mud User88f12472016-06-24 23:31:02 +0200587 if (!env && sizeof(tokens) > 1 && tokens[<1] == "hier") {
588 tokens = tokens[..<2];
589 env = environment();
590 }
591 else if (!env && sizeof(tokens) > 2 && tokens[<2] == "in")
592 {
593 if (tokens[<1] == "mir" ||
594 tokens[<1] == "dir") {
595 tokens = tokens[..<3];
596 env = this_object();
597 }
598 else if (tokens[<1] == "raum") {
599 tokens = tokens[..<3];
600 env = environment();
601 }
602 }
603
604 for (int i = sizeof(tokens)-1; i > 1; i--) {
Zesstrae8d5a0b2018-11-16 23:21:37 +0100605 // wird fangen am Ende der Tokens an und arbeiten uns wortweise nach
606 // vorne, um ein Objekt zu finden. (z.B. "... in paket 12" wuerde 2
607 // Durchlaeufe brauchen)
MG Mud User88f12472016-06-24 23:31:02 +0200608 if (env)
609 ob = present(implode(tokens[i..], " "), env);
610 else
611 ob = present(implode(tokens[i..], " "), environment()) ||
612 present(implode(tokens[i..], " "), this_object());
613
614 if (!ob)
615 continue;
616
Zesstrae8d5a0b2018-11-16 23:21:37 +0100617 // aus Lebewesen darf man nix rausnehmen oder reingucken
MG Mud User88f12472016-06-24 23:31:02 +0200618 if (living(ob)) {
619 NF("Aber " + ob->name(WER, 1) + " lebt doch!");
620 continue;
621 }
622
Zesstrae8d5a0b2018-11-16 23:21:37 +0100623 // und aus geschlossenen Containern auch nicht.
MG Mud User88f12472016-06-24 23:31:02 +0200624 if (ob->QueryProp(P_CNT_STATUS)) {
625 NF("Aber " + ob->name(WER, 1) + " ist doch geschlossen!");
626 continue;
627 }
Zesstrae8d5a0b2018-11-16 23:21:37 +0100628 // Wenn was rausgenommen werden soll und jetzt vor dem gefundenen
629 // Container die passende Praeposition steht (z.B. "aus"), wird
630 // angenommen, dass der vordere Teil der Tokens zu aus diesem
631 // Container zu nehmende Objekt bezeichnet und in present_objects
632 // dieses Containers verzweigt.
MG Mud User88f12472016-06-24 23:31:02 +0200633 if (is_source != 0 &&
634 tokens[i-1] == ob->QueryProp(P_SOURCE_PREPOSITION))
635 return ob->present_objects(implode(tokens[..i-2], " "));
636
Zesstrae8d5a0b2018-11-16 23:21:37 +0100637 // Wenn vor dem gefundenen Objekt dessen normale Praeposition steht
638 // (z.B. "in", "auf"), wird rekursiv geschaut, ob der vordere Teil der
639 // Tokens erneut einen Container bezeichnet. is_source==2 wird
640 // uebergebeb, damit in der Rekursion nur Objekte vor der
641 // P_SOURCE_PREPOSITION geliefert werden, aber keine aus
642 // Environment/this_object() (s.u. nach der Schleife).
MG Mud User88f12472016-06-24 23:31:02 +0200643 if (tokens[i-1] == ob->QueryProp(P_PREPOSITION))
644 return __find_objects(tokens[..i-2], ob, is_source ? 2 : 0);
645
646 NF("Du kannst nichts " + tokens[i-1] + " " +
647 ob->name(WEM, 1) + " nehmen.");
648 }
649
650 if (is_source == 2)
651 return ({});
Zesstrae8d5a0b2018-11-16 23:21:37 +0100652 // wenn das for keine Container gefunden hat (auch: wenn tokens zu kurz
653 // fuers for), wird im uebergebenen env geguckt, ob der vorderste Rest von
654 // tokens nen Objekt bezeichnet.
655 // geguckt, ob nen pass
MG Mud User88f12472016-06-24 23:31:02 +0200656 if (env)
657 return env->present_objects(implode(tokens, " "));
658
Zesstrae8d5a0b2018-11-16 23:21:37 +0100659 // Und wenn kein env uebergeben und gefunden wurde, wird geguckt, ob unser
660 // Environment nen passendes Objekt fuer tokens hat...
MG Mud User88f12472016-06-24 23:31:02 +0200661 if (environment() &&
662 sizeof(obs = environment()->present_objects(implode(tokens, " "))))
663 return obs;
Zesstrae8d5a0b2018-11-16 23:21:37 +0100664 // oder eben wir selbst.
MG Mud User88f12472016-06-24 23:31:02 +0200665 return present_objects(implode(tokens, " "));
666}
667
668object *find_objects(string what, object env, int is_source)
669{
670 if (!stringp(what) || !sizeof(what))
671 return ({});
672 return __find_objects(explode(what, " "), env, is_source);
673}
674
675
676/* varargs int drop_objects(string str, mixed msg);
677 * varargs int put_objects(string str, int casus, string verb, mixed msg);
678 * varargs int pick_objects(string str, int flag, mixed msg);
679 * varargs int give_objects(string str, mixed msg);
680 * varargs int show_objects(string str, mixed msg);
681 *
682 * Ein Befehl wie "wirf waffen weg" resultiert in einem Aufruf von
683 * drop_objects("waffen"). Diese Funktionen sind hauptsaechlich fuer die
684 * Behandlung der jeweiligen Kommandos vorgesehen, koennen jedoch auch fuer
685 * eigene Befehle verwendet werden. put_objects() erwartet ausserdem den
686 * Kasus ("Du kannst nichts an DER Pinwand befestigen.") und das verwendete
687 * Verb in der Gundform ("befestigen"). Das Flag fuer pick_objects() gibt
688 * an, ob das Objekt auch einfach herumliegen darf ("nimm ...") oder nicht
689 * ("hole ..."). Gibt bei Erfolg 1, sonst 0 zurueck.
690 */
691
692varargs int drop_objects(string str, mixed msg)
693{
694 object *obs;
695
696 if (!sizeof(obs = find_objects(str, this_object(), 1)))
697 return 0;
698
Zesstra7dbdec52018-11-12 22:49:03 +0100699 last_moved_objects=({});
700 last_moved_where = 0;
MG Mud User88f12472016-06-24 23:31:02 +0200701 foreach (object o: obs) {
702 if (objectp(o))
Zesstra7dbdec52018-11-12 22:49:03 +0100703 if (drop(o, msg) == 1)
704 last_moved_objects+=({o});
MG Mud User88f12472016-06-24 23:31:02 +0200705
706 if (get_eval_cost() < 100000) {
707 TME("Den Rest behaeltst Du erst mal.");
MG Mud User88f12472016-06-24 23:31:02 +0200708 return 1;
709 }
710 }
MG Mud User88f12472016-06-24 23:31:02 +0200711 return 1;
712}
713
714varargs int put_objects(string str, int casus, string verb, mixed msg)
715{
716 object *obs, dest, *no_move;
717
718 if (!stringp(str) || !sizeof(str)) return 0;
719
720 string *tokens = explode(str, " ");
721 int allow_room = 1;
722 int allow_me = 1;
723
724 if (sizeof(tokens) > 1 && tokens[<1] == "hier") {
725 tokens = tokens[..<2];
726 allow_me = 0;
727 } else if (sizeof(tokens) > 2 && tokens[<2] == "in")
728 if (tokens[<1] == "mir" ||
729 tokens[<1] == "dir") {
730 tokens = tokens[..<3];
731 allow_room = 0;
732 } else if (tokens[<1] == "raum") {
733 tokens = tokens[..<3];
734 allow_me = 0;
735 }
736
737 for (int i = sizeof(tokens)-1; i > 1; i--) {
738 if (!(dest = allow_room && present(implode(tokens[i..], " "),
739 environment())) &&
740 !(dest = allow_me && present(implode(tokens[i..], " "),
741 this_object())))
742 continue;
743
744 if (living(dest)) {
745 NF("Aber " + dest->name(WER, 1) + " lebt doch!");
746 continue;
747 }
748/*
749 if (verb == "legen" && !dest->QueryProp(P_TRAY)) {
750 NF("Du kannst nichts auf " + dest->name(WEN, 1) + " legen.");
751 continue;
752 }
753*/
754 if (verb == "stecken" && !dest->QueryProp(P_CONTAINER)) {
755 NF("Du kannst in " + dest->name(WEN, 1) + " nichts reinstecken.");
756 continue;
757 }
758
759 if (dest->QueryProp(P_CNT_STATUS)) {
760 NF("Aber " + dest->name(WER, 1) + " ist doch geschlossen!");
761 continue;
762 }
763
764 if (tokens[i-1] != dest->QueryProp(P_DEST_PREPOSITION)) {
765 NF("Du kannst nichts " + tokens[i-1] + " " +
766 dest->name(casus, 1) + " " + verb + ".");
767 continue;
768 }
769
770 if (!sizeof(obs = __find_objects(tokens[..i-2], 0, 1) - ({ dest }))) {
771 NF("WAS moechtest Du " + tokens[i-1] + " " +
772 dest->name(casus, 1) + " " + verb + "?");
773 return 0;
774 }
775
776 if (sizeof(no_move = obs & all_inventory(dest))) {
777 TME(capitalize(CountUp(map_objects(no_move, "name", WER, 1))) +
778 (sizeof(no_move) == 1 ? " ist" : " sind") +
779 " doch bereits in " + dest->name(WEM,1) + ".");
780 if (!sizeof(obs -= no_move))
781 return 0;
782 }
783
Zesstra7dbdec52018-11-12 22:49:03 +0100784 last_moved_objects = ({});
785 last_moved_where = dest;
786
MG Mud User88f12472016-06-24 23:31:02 +0200787 foreach (object o: obs) {
788 if (objectp(o))
Zesstra7dbdec52018-11-12 22:49:03 +0100789 if (put(o, dest, msg) == 1)
790 last_moved_objects += ({o});
MG Mud User88f12472016-06-24 23:31:02 +0200791
792 if (get_eval_cost() < 100000) {
793 TME("Den Rest laesst Du erst mal, wo er ist.");
MG Mud User88f12472016-06-24 23:31:02 +0200794 return 1;
795 }
796 }
797
MG Mud User88f12472016-06-24 23:31:02 +0200798 return 1;
799 }
800
801 return 0;
802}
803
804varargs int pick_objects(string str, int flag, mixed msg)
805{
806 object *obs;
807
Arathorn9f22a9c2019-12-03 00:11:22 +0100808 if (QueryProp(P_MAX_HANDS) < 1){
MG Mud User88f12472016-06-24 23:31:02 +0200809 NF("Ohne Haende kannst Du nichts nehmen.");
810 return 0;
811 }
812
813 if (!sizeof(obs = find_objects(str, 0, 1) - all_inventory()
Zesstra7dbdec52018-11-12 22:49:03 +0100814 - (flag ? all_inventory(environment()) : ({}))))
MG Mud User88f12472016-06-24 23:31:02 +0200815 return 0;
816
Zesstra7dbdec52018-11-12 22:49:03 +0100817 last_moved_objects = ({});
818 last_moved_where = this_object();
MG Mud User88f12472016-06-24 23:31:02 +0200819 foreach (object o: obs) {
820 if (objectp(o))
Zesstra7dbdec52018-11-12 22:49:03 +0100821 if (pick(o, msg) == 1)
822 last_moved_objects += ({o});
MG Mud User88f12472016-06-24 23:31:02 +0200823
824 if (get_eval_cost() < 100000) {
825 TME("Den Rest laesst Du erst mal liegen.");
MG Mud User88f12472016-06-24 23:31:02 +0200826 return 1;
827 }
828 }
829
MG Mud User88f12472016-06-24 23:31:02 +0200830 return 1;
831}
832
833varargs int give_objects(string str, mixed msg)
834{
835 object *obs, dest;
Zesstra7dbdec52018-11-12 22:49:03 +0100836
MG Mud User88f12472016-06-24 23:31:02 +0200837 if (!stringp(str) || !sizeof(str)) return 0;
838
839 string *tokens = explode(str, " ");
840
Arathorn9f22a9c2019-12-03 00:11:22 +0100841 if (QueryProp(P_MAX_HANDS) < 1){
MG Mud User88f12472016-06-24 23:31:02 +0200842 NF("Ohne Haende kannst Du nichts weggeben.");
843 return 0;
844 }
845
846 for (int i = 0; i < sizeof(tokens)-1; i++) {
847 if (!(dest = present(implode(tokens[..i], " "), environment())))
848 continue;
849
850 if (!living(dest)) {
851 NF("Aber " + dest->name(WER, 1) + " lebt doch gar nicht!");
852 dest = 0;
853 continue;
854 }
855
856 if (!sizeof(obs = __find_objects(tokens[i+1..], 0, 1))) {
857 NF("WAS moechtest Du " + dest->name(WEM, 1)+" geben?");
858 dest = 0;
859 } else
860 break;
861 }
862
863 if (!dest) {
864 int pos;
865
866 if ((pos = strrstr(str, " an ")) >= 0) {
867 dest = present(str[pos+4..], environment());
868 // zu gebende Objekte in Env + Living suchen
869 obs = find_objects(str[..pos-1], 0, 1);
870 }
871 }
872
873 if (!dest || !living(dest) || !sizeof(obs))
874 return 0;
875
Zesstra7dbdec52018-11-12 22:49:03 +0100876 last_moved_objects = ({});
877 last_moved_where = dest;
MG Mud User88f12472016-06-24 23:31:02 +0200878 foreach (object o: obs) {
879 if (objectp(o))
Zesstra7dbdec52018-11-12 22:49:03 +0100880 if (give(o, dest, msg) == 1)
881 last_moved_objects += ({o});
MG Mud User88f12472016-06-24 23:31:02 +0200882
883 if (get_eval_cost() < 100000) {
884 TME("Den Rest behaeltst Du erst mal.");
MG Mud User88f12472016-06-24 23:31:02 +0200885 return 1;
886 }
887 }
MG Mud User88f12472016-06-24 23:31:02 +0200888 return 1;
889}
890
891varargs int show_objects(string str, mixed msg)
892{
893 object *obs, whom;
Zesstra7dbdec52018-11-12 22:49:03 +0100894
MG Mud User88f12472016-06-24 23:31:02 +0200895 if (!stringp(str) || !sizeof(str))
896 return 0;
897
898 string *tokens = explode(str, " ");
899
900 for (int i = 0; i < sizeof(tokens)-1; i++) {
901 if (whom = present(implode(tokens[..i], " "), environment())) {
902 if (!living(whom)) {
903 NF("Aber " + whom->name(WER, 1) + " lebt doch gar nicht!");
904 continue;
905 }
906 } else {
907 if (i != 0 || tokens[0] != "allen")
908 continue;
909
910 if (!sizeof(filter(all_inventory(environment()) -
911 ({ this_object() }), #'living))) {
912 NF("Hier ist niemand, dem Du etwas zeigen koenntest!");
913 continue;
914 }
915 }
916
917 if (whom == this_object()) {
918 NF("Dazu solltest Du dann besser 'schau' benutzen!\n");
919 continue;
920 }
921
922 if (!sizeof(obs = __find_objects(tokens[i+1..], this_object(), 0)) &&
923 !sizeof(obs = __find_objects(tokens[i+1..], 0, 0)
924 - ({ this_object(), whom }))) {
925 NF("WAS moechtest Du " + (whom ? whom->name(WEM, 1) : "allen") +
926 " zeigen?");
927 continue;
928 }
929
Zesstra7dbdec52018-11-12 22:49:03 +0100930 last_moved_objects = ({});
931 last_moved_where = whom;
MG Mud User88f12472016-06-24 23:31:02 +0200932 foreach (object o: obs) {
933 if (objectp(o))
Zesstra7dbdec52018-11-12 22:49:03 +0100934 if (show(o, whom, msg) == 1)
935 last_moved_objects += ({o});
MG Mud User88f12472016-06-24 23:31:02 +0200936
937 if (get_eval_cost() < 100000) {
938 TME("Das reicht erst mal.");
MG Mud User88f12472016-06-24 23:31:02 +0200939 return 1;
940 }
941 }
942
MG Mud User88f12472016-06-24 23:31:02 +0200943 return 1;
944 }
945
946 return 0;
947}
948
949object *moved_objects(void)
950{
951 return last_moved_objects;
952}
953
954object moved_where(void)
955{
956 return last_moved_where;
957}
958
959
960/************************* Die einzelnen Kommandos **************************/
961
962/* static int fallenlassen(string str)
963 * static int werfen(string str)
964 * static int legen(string str)
965 * static int stecken(string str)
966 * static int holen(string str)
967 * static int nehmen(string str)
968 * static int geben(string str)
969 * Minimale Wrapper fuer XXX_objects(), entfernen "fallen", "weg" bzw. "ab"
970 * aus den Argumenten und setzen entsprechende Standard-Fehlermeldungen.
971 *
972 * protected void add_put_and_get_commands()
973 * Registriert obige Funktionen per add_action().
974 */
975
976static int fallenlassen(string str)
977{
978 if (QueryProp(P_GHOST)) {
979 _notify_fail("Als Geist kannst Du nichts fallenlassen.\n");
980 return 0;
981 }
982
983 if (!str || str[<7..] != " fallen") {
984 _notify_fail("Lass etwas FALLEN, oder was meinst Du?\n");
985 return 0;
986 }
987
988 _notify_fail("WAS moechtest Du fallenlassen?\n");
989 return drop_objects(str[0..<8]);
990}
991
992static int werfen(string str)
993{
994 if (QueryProp(P_GHOST)) {
995 _notify_fail("Als Geist kannst Du nichts wegwerfen.\n");
996 return 0;
997 }
998
999 if (!str || str[<4..] != " weg") {
1000 _notify_fail("Wirf etwas WEG, oder was meinst Du?\n");
1001 return 0;
1002 }
1003
1004 _notify_fail("WAS moechtest Du loswerden?\n");
1005 return drop_objects(str[0..<5]);
1006}
1007
1008static int legen(string str)
1009{
1010 if (QueryProp(P_GHOST)) {
1011 _notify_fail("Als Geist kannst Du nichts weglegen.\n");
1012 return 0;
1013 }
1014
1015 if (!str) {
1016 _notify_fail("Lege etwas AB, oder was meinst Du?\n");
1017 return 0;
1018 }
1019
1020 if (str[<3..] == " ab") {
1021 _notify_fail("WAS moechtest Du ablegen?\n");
1022 return drop_objects(str[0..<4]);
1023 }
1024
1025 if (str[<4..] == " weg") {
1026 _notify_fail("WAS moechtest Du weglegen?\n");
1027 return drop_objects(str[0..<5]);
1028 }
1029
1030 _notify_fail("WAS moechtest Du WOHIN legen?\n");
1031 return put_objects(str, WEN, "legen");
1032}
1033
1034static int stecken(string str)
1035{
1036 if (QueryProp(P_GHOST)) {
1037 _notify_fail("Das kannst Du in Deinem immateriellen Zustand nicht.\n");
1038 return 0;
1039 }
1040
1041 _notify_fail("WAS moechtest Du WOHIN stecken?\n");
1042 return put_objects(str, WEN, "stecken");
1043}
1044
1045static int holen(string str)
1046{
1047 if (QueryProp(P_GHOST)) {
1048 _notify_fail("Als Geist kannst Du nichts nehmen.\n");
1049 return 0;
1050 }
1051
1052 _notify_fail("WAS moechtest Du aus WAS holen?\n");
1053 return pick_objects(str, 1);
1054}
1055
1056static int nehmen(string str)
1057{
1058 if (QueryProp(P_GHOST)) {
1059 _notify_fail("Als Geist kannst Du nichts nehmen.\n");
1060 return 0;
1061 }
1062
1063 _notify_fail("WAS moechtest Du nehmen?\n");
1064 return pick_objects(str, 0);
1065}
1066
1067static int geben(string str)
1068{
1069 if (QueryProp(P_GHOST)) {
1070 _notify_fail("Als Geist kannst Du nichts weggeben.\n");
1071 return 0;
1072 }
1073
1074 _notify_fail("WEM moechtest Du WAS geben?\n");
1075 return give_objects(str);
1076}
1077
1078static int zeigen(string str)
1079{
1080 if (QueryProp(P_GHOST)) {
1081 _notify_fail("Als Geist kannst Du niemandem etwas zeigen.\n");
1082 return 0;
1083 }
1084
1085 _notify_fail("WEM moechtest Du WAS zeigen?\n");
1086 return show_objects(str);
1087}
1088
1089protected void add_put_and_get_commands(void)
1090{
1091 add_action("fallenlassen", "lass");
1092 add_action("fallenlassen", "lasse");
1093 add_action("werfen", "wirf");
1094 add_action("werfen", "werf");
1095 add_action("werfen", "werfe");
1096 add_action("legen", "leg");
1097 add_action("legen", "lege");
1098 add_action("stecken", "steck");
1099 add_action("stecken", "stecke");
1100 add_action("holen", "hol");
1101 add_action("holen", "hole");
1102 add_action("nehmen", "nimm");
1103 add_action("nehmen", "nehm");
1104 add_action("nehmen", "nehme");
1105 add_action("geben", "gebe");
1106 add_action("geben", "gib");
1107 add_action("zeigen", "zeig");
1108 add_action("zeigen", "zeige");
1109}
1110
1111
1112/********** Aus reinen Kompatibilitaetsgruenden weiterhin enthalten *********/
1113
1114object* find_obs(string str, int meth)
1115// gibt ein array zurueck mit allen Objekten die mit str angesprochen werden
1116{
1117 object inv;
1118 if (!str) return 0;
1119 if (str[<7..]==" in mir") {
1120 inv=ME;
1121 str=str[0..<8];
1122 }
1123 else if (str[<8..]==" in raum") {
1124 if (meth & PUT_GET_DROP) { // man kann nichts aus dem Raum wegwerfen
1125 _notify_fail("Du kannst nichts wegwerfen, das Du gar nicht hast.\n");
1126 return 0;
1127 }
1128 inv=environment();
1129 str=str[0..<9];
1130 }
1131 else if (meth & PUT_GET_DROP) inv=ME; // Raum bei drop uninteressant
1132 // else kein besonderes inv ausgewaehlt also inv=0
1133 if (!sizeof(str))
1134 return 0; // hier passt die bereits gesetzte _notify_fail
1135 else {
1136 object *obs;
1137 string con;
1138 if (sscanf(str, "%s aus %s", str, con)==2 ||
1139 sscanf(str, "%s in %s", str, con)==2 ||
1140 sscanf(str, "%s von %s", str, con)==2 ||
1141 sscanf(str, "%s vom %s", str, con)==2) {
1142 if (!inv) {
1143 if (!environment() || !(inv=present(con, environment())))
1144 inv=present(con, ME); // sowohl im env als auch im inv suchen
1145 }
1146 else inv=present(con, inv); // nur in ausgewaehltem inv suchen
1147 if (inv==ME) inv=0;
1148 if (!inv || !(inv->short())) {
1149 _notify_fail(break_string("Du hast hier aber kein '"+capitalize(con)
1150 +"'.",78));
1151 return 0;
1152 }
1153 if (living(inv)) {
1154 _notify_fail(break_string("Aber "+inv->name(WER,1)+" lebt doch!",78));
1155 return 0;
1156 }
1157 // wieso man aus Objekten die von std/tray abgeleitet werden etwas
1158 // nehmen koennen soll, versteh ich zwar nicht so ganz...
1159 if (!(inv->QueryProp(P_CONTAINER)) && !(inv->QueryProp(P_TRAY))) {
1160 _notify_fail(break_string("Du kannst nichts aus "+inv->name(WEM,1)
1161 +" nehmen.",78));
1162 return 0;
1163 }
1164 if (inv->QueryProp(P_CNT_STATUS)) { // Container ist geschlossen
1165 _notify_fail(break_string("Aber "+inv->name(WER,1)
1166 +" ist doch geschlossen.", 78));
1167 return 0;
1168 }
1169 }
1170 else if (inv==ME && (meth & PUT_GET_TAKE)) { // nichts aus sich nehmen
1171 _notify_fail("Du kannst nichts nehmen, "
1172 "was Du schon bei Dir traegst.\n");
1173 return 0;
1174 }
1175 if (!inv && (meth & PUT_GET_TAKE))
1176 inv=environment(); // nichts nehmen was man schon hat
1177
1178 if (!inv) {
1179 if (environment()) {
1180 obs=(environment()->present_objects(str)||({}));
1181 if (!sizeof(obs)) obs+=(ME->present_objects(str)||({}));
1182 }
1183 else obs=(ME->present_objects(str) || ({}));
1184 }
1185 else obs=(inv->present_objects(str) || ({}));
1186 return obs-({ ME });
1187 }
MG Mud User88f12472016-06-24 23:31:02 +02001188}
1189
1190int pick_obj(object ob)
1191{
1192 object env;
1193
1194 if (!ob || ob == this_object() || environment(ob) == this_object()) return 0;
1195 if ((env=environment(ob)) != environment()) {
1196 if (!env->QueryProp(P_CONTAINER) && !env->QueryProp(P_TRAY)) {
1197 TME("Du kannst nichts aus " + env->name(WEM,1) + " nehmen.");
1198 return 1;
1199 }
1200 else if (env->QueryProp(P_CNT_STATUS)) { // Container ist geschlossen
1201 TME("Aber " + env->name(WER, 1) + " ist doch geschlossen.");
1202 return 1;
1203 }
1204 }
1205 if (ob->IsUnit() && ob->QueryProp(P_AMOUNT)<0) {
1206 TME("Du kannst nicht mehr nehmen als da ist.");
1207 return 1;
1208 }
1209 pick(ob);
1210 return 1;
1211}
1212
1213int drop_obj(object ob)
1214{
1215 if (!ob || ob==this_object() || environment(ob)!=this_object()) return 0;
1216 drop(ob);
1217 return 1;
1218}
1219
1220int put_obj(object ob, object where)
1221{
1222 object env;
1223
1224 if (ob == this_object() || ob == where || environment(ob) == where) return 0;
1225 env=environment(ob);
1226 if (!where->QueryProp(P_CONTAINER)) {
1227 TME("Du kannst in " + where->name(WEN,1) + " nix reinstecken.");
1228 return 1;
1229 }
1230 if (where->QueryProp(P_CNT_STATUS)) { // Container ist geschlossen
1231 TME("Aber " + where->name(WER, 1) + " ist doch geschlossen.");
1232 return 1;
1233 }
1234 if (env!=environment(this_object()) && env!=this_object()) {
1235 _notify_fail("Da kommst du so nicht ran.\n");
1236 return 0;
1237 }
1238 put(ob, where);
1239 return 1;
1240}
1241
1242int give_obj(object ob, object where)
1243{
MG Mud User88f12472016-06-24 23:31:02 +02001244 if (environment(ob)!=this_object()) {
1245 TME("Das solltest Du erstmal nehmen.");
1246 return 1;
1247 }
1248 if (!ob || ob == this_object() || ob == where ||
1249 environment(where)!=environment())
1250 return 0;
1251 if (environment(ob) == where) {
1252 _notify_fail("Das Ziel ist in dem zu gebenden Object enthalten!\n");
1253 return 0;
1254 }
1255 if (environment(ob)!=this_object()) {
1256 TME("Das hast Du nicht.");
1257 return 1;
1258 }
1259 give(ob, where);
1260 return 1;
1261}