blob: 936fad0c9c39645e0d25fc465fb44a0e03a04683 [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 }
283 return 0; // NOT REACHED
284}
285
286
287/* varargs int drop(object o, mixed msg)
288 * varargs int put(object o, object dest, mixed msg)
289 * varargs int pick(object o, mixed msg)
290 * varargs int give(object o, object dest, mixed msg)
291 * varargs int show(object o, object dest, mixed msg)
292 *
293 * Der Spieler nimmt/legt/gibt/zeigt/laesst ein Objekt fallen, wobei die
294 * entsprechenden oder optional abweichende (im Format von P_XXX_MSG) oder
295 * gar keine (msg == 1) Meldungen ausgegeben werden. Es liegt in der
296 * Verantwortung des Rufenden, sinnvolle Werte zu uebergeben; insbesondere
297 * wird nicht geprueft, ob sich die Objekte in der Reichweite des Spielers
298 * befinden. Gibt 1 zurueck, wenn das Objekt bewegt wurde, sonst 0.
299 */
300
301varargs int drop(object o, mixed msg)
302{
303 string str;
304
305 // vorher speichern, falls das Objekt zerstoert wird
306 cl = symbol_function("name", o);
307 wen0 = funcall(cl, WEN, 0);
308 wen1 = funcall(cl, WEN, 1);
309 wer0 = 0;
310
311 if (!msg)
312 msg = o->QueryProp(P_DROP_MSG);
313
314 if (str = put_or_get(o, environment())) {
315 TME(str);
316 return 0;
317 }
318
319 if (!msg) {
320 TME("Du laesst " + wen1 + " fallen.");
321 SAY(Name(WER,1) + " laesst " + wen0 + " fallen.");
322 } else if (pointerp(msg))
323 switch (sizeof(msg)) {
324 // Wenn es zwei Strings gibt, geht die 2. ans Environment
325 case 2:
326 SAY(replace_personal(msg[1], ({this_object(), o||wen0}), 1));
327 case 1:
328 TME(replace_personal(msg[0], ({this_object(), o||wen1}), 1));
329 break;
330 default:
331 raise_error(sprintf(
332 "Falsches Format fuer P_DROP_MSG: %O\n", o||wen1));
333 }
334
335 return 1;
336}
337
338varargs int put(object o, object dest, mixed msg)
339{
340 string str;
341
342 // Falls das jemand von aussen ruft und Schrott uebergibt...
343 //if (living(dest))
344 // raise_error(sprintf("Lebendes Ziel fuer put(): %O\n", dest));
345 if (dest == environment())
346 raise_error("Ziel fuer put() ist Umgebung des Spielers\n");
347
348 // vorher speichern, falls das Objekt zerstoert wird
349 cl = symbol_function("name", o);
350 wen0 = funcall(cl, WEN, 0);
351 wen1 = funcall(cl, WEN, 1);
352 wer0 = funcall(cl, WER, 0);
353
354 if (!msg)
355 msg = o->QueryProp(P_PUT_MSG);
356
357 if (str = put_or_get(o, dest)) {
358 TME(str);
359 return 0;
360 }
361
362
363 if (!msg) {
Zesstrabc1e21c2016-07-24 14:43:54 +0200364 TME("Du steckst " + wen1 + " "
365 + dest->QueryProp(P_DEST_PREPOSITION) + " "
366 + dest->name(WEN, 1) + ".");
MG Mud User88f12472016-06-24 23:31:02 +0200367 if (environment())
Zesstrabc1e21c2016-07-24 14:43:54 +0200368 SAY(Name(WER, 1) + " steckt " + wen0 + " "
369 + dest->QueryProp(P_DEST_PREPOSITION) + " "
370 + dest->name(WEN, 0) + ".");
MG Mud User88f12472016-06-24 23:31:02 +0200371 }
372 else if (pointerp(msg)) {
373 switch (sizeof(msg)) {
374 case 2:
375 if (environment())
376 SAY(replace_personal(msg[1], ({this_object(), o||wen0, dest}), 1));
377 case 1:
378 TME(replace_personal(msg[0], ({this_object(), o||wen1, dest}), 1));
379 break;
380 default:
381 raise_error(sprintf(
382 "Falsches Format fuer P_PUT_MSG: %O\n",o||wen1));
383 }
384 }
385
386 return 1;
387}
388
389varargs int pick(object o, mixed msg)
390{
391 string str;
392
393 // vorher speichern, falls das Objekt zerstoert wird
394 cl = symbol_function("name", o);
395 wen0 = 0;
396 wen1 = funcall(cl, WEN, 1);
397 wer0 = 0;
398
399 if (!msg)
400 msg = o->QueryProp(P_PICK_MSG);
401
402 if (str = put_or_get(o, this_object())) {
403 TME(str);
404 return 0;
405 }
406
407 if (!msg) {
408 TME("Du nimmst " + wen1 + ".");
409 SAY(Name(WER, 1) + " nimmt " + wen1 + ".");
410 } else if (pointerp(msg))
411 switch (sizeof(msg)) {
412 case 2:
413 SAY(replace_personal(msg[1], ({this_object(), o||wen1}), 1));
414 case 1:
415 TME(replace_personal(msg[0], ({this_object(), o||wen1}), 1));
416 break;
417 default:
418 raise_error(sprintf(
419 "Falsches Format fuer P_PICK_MSG: %O\n", o||wen1));
420 }
421
422 return 1;
423}
424
425varargs int give(object o, object dest, mixed msg)
426{
427 string zname, gname;
428 string str;
429
430 // Falls das jemand von aussen ruft und Schrott uebergibt...
431 if (!living(dest))
432 raise_error(sprintf("Totes Ziel fuer give(): %O\n", dest));
433
434 zname = dest->name(WEM, 1);
435 gname = Name(WER, 1);
436
437 // vorher speichern, falls das Objekt zerstoert wird
438 cl = symbol_function("name", o);
439 wen0 = funcall(cl, WEN, 0);
440 wen1 = funcall(cl, WEN, 1);
441 wer0 = 0;
442
443 if (!msg)
444 msg = o->QueryProp(P_GIVE_MSG);
445
446 if (str = put_or_get(o, dest)) {
447 TME(str);
448 return 0;
449 }
450
451 if (!msg) {
452 TME("Du gibst " + zname + " " + wen1 + ".");
453 TOB(dest, gname + " gibt Dir " + wen0 + ".");
454 SAY2(({dest}), gname + " gibt " + zname + " " + wen0 + ".");
455 } else if (pointerp(msg))
456 switch (sizeof(msg)) {
457 case 3:
458 TOB(dest, replace_personal(
459 msg[2], ({this_object(), o||wen0, dest||zname}), 1));
460 case 2:
461 SAY2(({dest, this_object()}), replace_personal(
462 msg[1], ({this_object(), o||wen0, dest||zname}), 1));
463 case 1:
464 TME(replace_personal(
465 msg[0], ({this_object(), o||wen1, dest||zname}), 1));
466 break;
467 default:
468 raise_error(sprintf(
469 "Falsches Format fuer P_GIVE_MSG: %O\n", o||wen1));
470 }
471
472 if (!query_once_interactive(dest))
473 dest->give_notify(o);
474
475 return 1;
476}
477
478varargs int show(object o, object whom, mixed msg)
479{
480 string zname, gname;
481 string wen0, wen2, long;
482
483 zname = whom ? whom->name(WEM, 1) : "allen";
484 gname = Name(WER, 1);
485
486 if (!msg)
487 msg = o->QueryProp(P_SHOW_MSG);
488
489 if (environment(o) == this_object() ||
490 environment(environment(o)) == this_object()) {
491 wen0 = o->name(WEN, 0);
492
493 /* Der Akkusativ muss mit dem unbestimmten Artikel gebildet werden,
494 * damit eventuelle Adjektive die richtige Endung besitzen.
495 * (ein kleines Schwert -> kleines Schwert -> Dein kleines Schwert)
496 */
497
498 if (o->QueryProp(P_ARTICLE) && member(wen0, ' ') >= 0) {
499 int obgender = o->QueryProp(P_GENDER);
500 int obnum = o->QueryProp(P_AMOUNT) > 1 ? PLURAL : SINGULAR;
501
502 // Wichtig: P_AMOUNT ist 0 fuer Objekte, die nicht von unit erben.
503 // Da unit.c kein P_AMOUNT==0 zulaesst, nehmen wir diesen Fall als
504 // singular an. *Rumata
505
506 wen2 = wen0[member(wen0, ' ')..];
507 wen0 = QueryPossPronoun(o, WEN, obnum) + wen2;
508
509 if (obnum == PLURAL || obgender == FEMALE)
510 wen2 = "Deine" + wen2;
511 else if (obgender == MALE)
512 wen2 = "Deinen" + wen2;
513 else
514 wen2 = "Dein" + wen2;
515 } else
516 wen2 = wen0;
517 } else
518 wen2 = wen0 = o->name(WEN, 1);
519
520 // vorher speichern, falls das Objekt im catch_tell() zerstoert wird
521 long = o->long(4);
522
523 if (!msg) {
524 TME("Du zeigst " + zname + " " + wen2 + ".");
525 if (!whom)
526 SAY(gname + " zeigt Dir " + wen0 + ".");
527 else {
528 TOB(whom, gname + " zeigt Dir " + wen0 + ".");
529 SAY2(({whom}), gname + " zeigt " + zname + " " + wen0 + ".");
530 }
531 } else if (pointerp(msg))
532 switch (sizeof(msg)) {
533 case 3:
534 if (whom)
535 TOB(whom, replace_personal(
536 msg[2], ({this_object(), o||wen0, whom||zname}), 1));
537 else
538 SAY(replace_personal(
539 msg[2], ({this_object(), o||wen0, whom||zname}), 1));
540 case 2:
541 if (whom)
542 SAY2(({whom, this_object()}), replace_personal(
543 msg[1], ({this_object(), o||wen0, whom||zname}), 1));
544 case 1:
545 TME(replace_personal(
546 msg[0], ({this_object(), o||wen2, whom||zname}), 1));
547 break;
548 default:
549 raise_error(sprintf(
550 "Falsches Format fuer P_SHOW_MSG: %O\n", o||wen0));
551 }
552
553 if (!whom)
554 SAY(long);
555 else {
556 TOB(whom, long);
557 if (!query_once_interactive(whom))
558 whom->show_notify(o);
559 }
560
561 return 1;
562}
563
564
565/***************************** Hilfsfunktionen *****************************/
566
567/* private object *__find_objects(string *tokens, object env, int is_source);
568 * object *find_objects(string what, object env, int is_source);
569 *
570 * Sucht im Raum und im Spieler (oder alternativ in der angegebenen Umgebung)
571 * nach den in tokens/what bezeichneten Objekten. is_source bestimmt die
572 * erwartete grammatische Form (0 fuer "topf auf herd" und 1 fuer "topf von
573 * herd", siehe Manpage).
574 */
575
576private object *__find_objects(string *tokens, object env, int is_source)
577{
578 object ob, *obs;
579
580 // is_source == 0: Objekt soll nicht bewegt werden ("topf auf herd")
581 // 1: Objekt soll bewegt werden ("topf von herd")
Zesstra08e60732018-11-15 20:37:11 +0100582 // 2: Kennzeichnet rekursiven Aufruf, falls Objekt bewegt
583 // werden soll.
MG Mud User88f12472016-06-24 23:31:02 +0200584
Zesstrae8d5a0b2018-11-16 23:21:37 +0100585 // ganz am Ende von den tokens steht ggf. der vom User gewuenschte Anfang
586 // der Suche nache dem Objekt (z.B. "fackel aus truhe hier" oder "seil aus
587 // paket in mir".
MG Mud User88f12472016-06-24 23:31:02 +0200588 if (!env && sizeof(tokens) > 1 && tokens[<1] == "hier") {
589 tokens = tokens[..<2];
590 env = environment();
591 }
592 else if (!env && sizeof(tokens) > 2 && tokens[<2] == "in")
593 {
594 if (tokens[<1] == "mir" ||
595 tokens[<1] == "dir") {
596 tokens = tokens[..<3];
597 env = this_object();
598 }
599 else if (tokens[<1] == "raum") {
600 tokens = tokens[..<3];
601 env = environment();
602 }
603 }
604
605 for (int i = sizeof(tokens)-1; i > 1; i--) {
Zesstrae8d5a0b2018-11-16 23:21:37 +0100606 // wird fangen am Ende der Tokens an und arbeiten uns wortweise nach
607 // vorne, um ein Objekt zu finden. (z.B. "... in paket 12" wuerde 2
608 // Durchlaeufe brauchen)
MG Mud User88f12472016-06-24 23:31:02 +0200609 if (env)
610 ob = present(implode(tokens[i..], " "), env);
611 else
612 ob = present(implode(tokens[i..], " "), environment()) ||
613 present(implode(tokens[i..], " "), this_object());
614
615 if (!ob)
616 continue;
617
Zesstrae8d5a0b2018-11-16 23:21:37 +0100618 // aus Lebewesen darf man nix rausnehmen oder reingucken
MG Mud User88f12472016-06-24 23:31:02 +0200619 if (living(ob)) {
620 NF("Aber " + ob->name(WER, 1) + " lebt doch!");
621 continue;
622 }
623
Zesstrae8d5a0b2018-11-16 23:21:37 +0100624 // und aus geschlossenen Containern auch nicht.
MG Mud User88f12472016-06-24 23:31:02 +0200625 if (ob->QueryProp(P_CNT_STATUS)) {
626 NF("Aber " + ob->name(WER, 1) + " ist doch geschlossen!");
627 continue;
628 }
Zesstrae8d5a0b2018-11-16 23:21:37 +0100629 // Wenn was rausgenommen werden soll und jetzt vor dem gefundenen
630 // Container die passende Praeposition steht (z.B. "aus"), wird
631 // angenommen, dass der vordere Teil der Tokens zu aus diesem
632 // Container zu nehmende Objekt bezeichnet und in present_objects
633 // dieses Containers verzweigt.
MG Mud User88f12472016-06-24 23:31:02 +0200634 if (is_source != 0 &&
635 tokens[i-1] == ob->QueryProp(P_SOURCE_PREPOSITION))
636 return ob->present_objects(implode(tokens[..i-2], " "));
637
Zesstrae8d5a0b2018-11-16 23:21:37 +0100638 // Wenn vor dem gefundenen Objekt dessen normale Praeposition steht
639 // (z.B. "in", "auf"), wird rekursiv geschaut, ob der vordere Teil der
640 // Tokens erneut einen Container bezeichnet. is_source==2 wird
641 // uebergebeb, damit in der Rekursion nur Objekte vor der
642 // P_SOURCE_PREPOSITION geliefert werden, aber keine aus
643 // Environment/this_object() (s.u. nach der Schleife).
MG Mud User88f12472016-06-24 23:31:02 +0200644 if (tokens[i-1] == ob->QueryProp(P_PREPOSITION))
645 return __find_objects(tokens[..i-2], ob, is_source ? 2 : 0);
646
647 NF("Du kannst nichts " + tokens[i-1] + " " +
648 ob->name(WEM, 1) + " nehmen.");
649 }
650
651 if (is_source == 2)
652 return ({});
Zesstrae8d5a0b2018-11-16 23:21:37 +0100653 // wenn das for keine Container gefunden hat (auch: wenn tokens zu kurz
654 // fuers for), wird im uebergebenen env geguckt, ob der vorderste Rest von
655 // tokens nen Objekt bezeichnet.
656 // geguckt, ob nen pass
MG Mud User88f12472016-06-24 23:31:02 +0200657 if (env)
658 return env->present_objects(implode(tokens, " "));
659
Zesstrae8d5a0b2018-11-16 23:21:37 +0100660 // Und wenn kein env uebergeben und gefunden wurde, wird geguckt, ob unser
661 // Environment nen passendes Objekt fuer tokens hat...
MG Mud User88f12472016-06-24 23:31:02 +0200662 if (environment() &&
663 sizeof(obs = environment()->present_objects(implode(tokens, " "))))
664 return obs;
Zesstrae8d5a0b2018-11-16 23:21:37 +0100665 // oder eben wir selbst.
MG Mud User88f12472016-06-24 23:31:02 +0200666 return present_objects(implode(tokens, " "));
667}
668
669object *find_objects(string what, object env, int is_source)
670{
671 if (!stringp(what) || !sizeof(what))
672 return ({});
673 return __find_objects(explode(what, " "), env, is_source);
674}
675
676
677/* varargs int drop_objects(string str, mixed msg);
678 * varargs int put_objects(string str, int casus, string verb, mixed msg);
679 * varargs int pick_objects(string str, int flag, mixed msg);
680 * varargs int give_objects(string str, mixed msg);
681 * varargs int show_objects(string str, mixed msg);
682 *
683 * Ein Befehl wie "wirf waffen weg" resultiert in einem Aufruf von
684 * drop_objects("waffen"). Diese Funktionen sind hauptsaechlich fuer die
685 * Behandlung der jeweiligen Kommandos vorgesehen, koennen jedoch auch fuer
686 * eigene Befehle verwendet werden. put_objects() erwartet ausserdem den
687 * Kasus ("Du kannst nichts an DER Pinwand befestigen.") und das verwendete
688 * Verb in der Gundform ("befestigen"). Das Flag fuer pick_objects() gibt
689 * an, ob das Objekt auch einfach herumliegen darf ("nimm ...") oder nicht
690 * ("hole ..."). Gibt bei Erfolg 1, sonst 0 zurueck.
691 */
692
693varargs int drop_objects(string str, mixed msg)
694{
695 object *obs;
696
697 if (!sizeof(obs = find_objects(str, this_object(), 1)))
698 return 0;
699
Zesstra7dbdec52018-11-12 22:49:03 +0100700 last_moved_objects=({});
701 last_moved_where = 0;
MG Mud User88f12472016-06-24 23:31:02 +0200702 foreach (object o: obs) {
703 if (objectp(o))
Zesstra7dbdec52018-11-12 22:49:03 +0100704 if (drop(o, msg) == 1)
705 last_moved_objects+=({o});
MG Mud User88f12472016-06-24 23:31:02 +0200706
707 if (get_eval_cost() < 100000) {
708 TME("Den Rest behaeltst Du erst mal.");
MG Mud User88f12472016-06-24 23:31:02 +0200709 return 1;
710 }
711 }
MG Mud User88f12472016-06-24 23:31:02 +0200712 return 1;
713}
714
715varargs int put_objects(string str, int casus, string verb, mixed msg)
716{
717 object *obs, dest, *no_move;
718
719 if (!stringp(str) || !sizeof(str)) return 0;
720
721 string *tokens = explode(str, " ");
722 int allow_room = 1;
723 int allow_me = 1;
724
725 if (sizeof(tokens) > 1 && tokens[<1] == "hier") {
726 tokens = tokens[..<2];
727 allow_me = 0;
728 } else if (sizeof(tokens) > 2 && tokens[<2] == "in")
729 if (tokens[<1] == "mir" ||
730 tokens[<1] == "dir") {
731 tokens = tokens[..<3];
732 allow_room = 0;
733 } else if (tokens[<1] == "raum") {
734 tokens = tokens[..<3];
735 allow_me = 0;
736 }
737
738 for (int i = sizeof(tokens)-1; i > 1; i--) {
739 if (!(dest = allow_room && present(implode(tokens[i..], " "),
740 environment())) &&
741 !(dest = allow_me && present(implode(tokens[i..], " "),
742 this_object())))
743 continue;
744
745 if (living(dest)) {
746 NF("Aber " + dest->name(WER, 1) + " lebt doch!");
747 continue;
748 }
749/*
750 if (verb == "legen" && !dest->QueryProp(P_TRAY)) {
751 NF("Du kannst nichts auf " + dest->name(WEN, 1) + " legen.");
752 continue;
753 }
754*/
755 if (verb == "stecken" && !dest->QueryProp(P_CONTAINER)) {
756 NF("Du kannst in " + dest->name(WEN, 1) + " nichts reinstecken.");
757 continue;
758 }
759
760 if (dest->QueryProp(P_CNT_STATUS)) {
761 NF("Aber " + dest->name(WER, 1) + " ist doch geschlossen!");
762 continue;
763 }
764
765 if (tokens[i-1] != dest->QueryProp(P_DEST_PREPOSITION)) {
766 NF("Du kannst nichts " + tokens[i-1] + " " +
767 dest->name(casus, 1) + " " + verb + ".");
768 continue;
769 }
770
771 if (!sizeof(obs = __find_objects(tokens[..i-2], 0, 1) - ({ dest }))) {
772 NF("WAS moechtest Du " + tokens[i-1] + " " +
773 dest->name(casus, 1) + " " + verb + "?");
774 return 0;
775 }
776
777 if (sizeof(no_move = obs & all_inventory(dest))) {
778 TME(capitalize(CountUp(map_objects(no_move, "name", WER, 1))) +
779 (sizeof(no_move) == 1 ? " ist" : " sind") +
780 " doch bereits in " + dest->name(WEM,1) + ".");
781 if (!sizeof(obs -= no_move))
782 return 0;
783 }
784
Zesstra7dbdec52018-11-12 22:49:03 +0100785 last_moved_objects = ({});
786 last_moved_where = dest;
787
MG Mud User88f12472016-06-24 23:31:02 +0200788 foreach (object o: obs) {
789 if (objectp(o))
Zesstra7dbdec52018-11-12 22:49:03 +0100790 if (put(o, dest, msg) == 1)
791 last_moved_objects += ({o});
MG Mud User88f12472016-06-24 23:31:02 +0200792
793 if (get_eval_cost() < 100000) {
794 TME("Den Rest laesst Du erst mal, wo er ist.");
MG Mud User88f12472016-06-24 23:31:02 +0200795 return 1;
796 }
797 }
798
MG Mud User88f12472016-06-24 23:31:02 +0200799 return 1;
800 }
801
802 return 0;
803}
804
805varargs int pick_objects(string str, int flag, mixed msg)
806{
807 object *obs;
808
Arathorn9f22a9c2019-12-03 00:11:22 +0100809 if (QueryProp(P_MAX_HANDS) < 1){
MG Mud User88f12472016-06-24 23:31:02 +0200810 NF("Ohne Haende kannst Du nichts nehmen.");
811 return 0;
812 }
813
814 if (!sizeof(obs = find_objects(str, 0, 1) - all_inventory()
Zesstra7dbdec52018-11-12 22:49:03 +0100815 - (flag ? all_inventory(environment()) : ({}))))
MG Mud User88f12472016-06-24 23:31:02 +0200816 return 0;
817
Zesstra7dbdec52018-11-12 22:49:03 +0100818 last_moved_objects = ({});
819 last_moved_where = this_object();
MG Mud User88f12472016-06-24 23:31:02 +0200820 foreach (object o: obs) {
821 if (objectp(o))
Zesstra7dbdec52018-11-12 22:49:03 +0100822 if (pick(o, msg) == 1)
823 last_moved_objects += ({o});
MG Mud User88f12472016-06-24 23:31:02 +0200824
825 if (get_eval_cost() < 100000) {
826 TME("Den Rest laesst Du erst mal liegen.");
MG Mud User88f12472016-06-24 23:31:02 +0200827 return 1;
828 }
829 }
830
MG Mud User88f12472016-06-24 23:31:02 +0200831 return 1;
832}
833
834varargs int give_objects(string str, mixed msg)
835{
836 object *obs, dest;
Zesstra7dbdec52018-11-12 22:49:03 +0100837
MG Mud User88f12472016-06-24 23:31:02 +0200838 if (!stringp(str) || !sizeof(str)) return 0;
839
840 string *tokens = explode(str, " ");
841
Arathorn9f22a9c2019-12-03 00:11:22 +0100842 if (QueryProp(P_MAX_HANDS) < 1){
MG Mud User88f12472016-06-24 23:31:02 +0200843 NF("Ohne Haende kannst Du nichts weggeben.");
844 return 0;
845 }
846
847 for (int i = 0; i < sizeof(tokens)-1; i++) {
848 if (!(dest = present(implode(tokens[..i], " "), environment())))
849 continue;
850
851 if (!living(dest)) {
852 NF("Aber " + dest->name(WER, 1) + " lebt doch gar nicht!");
853 dest = 0;
854 continue;
855 }
856
857 if (!sizeof(obs = __find_objects(tokens[i+1..], 0, 1))) {
858 NF("WAS moechtest Du " + dest->name(WEM, 1)+" geben?");
859 dest = 0;
860 } else
861 break;
862 }
863
864 if (!dest) {
865 int pos;
866
867 if ((pos = strrstr(str, " an ")) >= 0) {
868 dest = present(str[pos+4..], environment());
869 // zu gebende Objekte in Env + Living suchen
870 obs = find_objects(str[..pos-1], 0, 1);
871 }
872 }
873
874 if (!dest || !living(dest) || !sizeof(obs))
875 return 0;
876
Zesstra7dbdec52018-11-12 22:49:03 +0100877 last_moved_objects = ({});
878 last_moved_where = dest;
MG Mud User88f12472016-06-24 23:31:02 +0200879 foreach (object o: obs) {
880 if (objectp(o))
Zesstra7dbdec52018-11-12 22:49:03 +0100881 if (give(o, dest, msg) == 1)
882 last_moved_objects += ({o});
MG Mud User88f12472016-06-24 23:31:02 +0200883
884 if (get_eval_cost() < 100000) {
885 TME("Den Rest behaeltst Du erst mal.");
MG Mud User88f12472016-06-24 23:31:02 +0200886 return 1;
887 }
888 }
MG Mud User88f12472016-06-24 23:31:02 +0200889 return 1;
890}
891
892varargs int show_objects(string str, mixed msg)
893{
894 object *obs, whom;
Zesstra7dbdec52018-11-12 22:49:03 +0100895
MG Mud User88f12472016-06-24 23:31:02 +0200896 if (!stringp(str) || !sizeof(str))
897 return 0;
898
899 string *tokens = explode(str, " ");
900
901 for (int i = 0; i < sizeof(tokens)-1; i++) {
902 if (whom = present(implode(tokens[..i], " "), environment())) {
903 if (!living(whom)) {
904 NF("Aber " + whom->name(WER, 1) + " lebt doch gar nicht!");
905 continue;
906 }
907 } else {
908 if (i != 0 || tokens[0] != "allen")
909 continue;
910
911 if (!sizeof(filter(all_inventory(environment()) -
912 ({ this_object() }), #'living))) {
913 NF("Hier ist niemand, dem Du etwas zeigen koenntest!");
914 continue;
915 }
916 }
917
918 if (whom == this_object()) {
919 NF("Dazu solltest Du dann besser 'schau' benutzen!\n");
920 continue;
921 }
922
923 if (!sizeof(obs = __find_objects(tokens[i+1..], this_object(), 0)) &&
924 !sizeof(obs = __find_objects(tokens[i+1..], 0, 0)
925 - ({ this_object(), whom }))) {
926 NF("WAS moechtest Du " + (whom ? whom->name(WEM, 1) : "allen") +
927 " zeigen?");
928 continue;
929 }
930
Zesstra7dbdec52018-11-12 22:49:03 +0100931 last_moved_objects = ({});
932 last_moved_where = whom;
MG Mud User88f12472016-06-24 23:31:02 +0200933 foreach (object o: obs) {
934 if (objectp(o))
Zesstra7dbdec52018-11-12 22:49:03 +0100935 if (show(o, whom, msg) == 1)
936 last_moved_objects += ({o});
MG Mud User88f12472016-06-24 23:31:02 +0200937
938 if (get_eval_cost() < 100000) {
939 TME("Das reicht erst mal.");
MG Mud User88f12472016-06-24 23:31:02 +0200940 return 1;
941 }
942 }
943
MG Mud User88f12472016-06-24 23:31:02 +0200944 return 1;
945 }
946
947 return 0;
948}
949
950object *moved_objects(void)
951{
952 return last_moved_objects;
953}
954
955object moved_where(void)
956{
957 return last_moved_where;
958}
959
960
961/************************* Die einzelnen Kommandos **************************/
962
963/* static int fallenlassen(string str)
964 * static int werfen(string str)
965 * static int legen(string str)
966 * static int stecken(string str)
967 * static int holen(string str)
968 * static int nehmen(string str)
969 * static int geben(string str)
970 * Minimale Wrapper fuer XXX_objects(), entfernen "fallen", "weg" bzw. "ab"
971 * aus den Argumenten und setzen entsprechende Standard-Fehlermeldungen.
972 *
973 * protected void add_put_and_get_commands()
974 * Registriert obige Funktionen per add_action().
975 */
976
977static int fallenlassen(string str)
978{
979 if (QueryProp(P_GHOST)) {
980 _notify_fail("Als Geist kannst Du nichts fallenlassen.\n");
981 return 0;
982 }
983
984 if (!str || str[<7..] != " fallen") {
985 _notify_fail("Lass etwas FALLEN, oder was meinst Du?\n");
986 return 0;
987 }
988
989 _notify_fail("WAS moechtest Du fallenlassen?\n");
990 return drop_objects(str[0..<8]);
991}
992
993static int werfen(string str)
994{
995 if (QueryProp(P_GHOST)) {
996 _notify_fail("Als Geist kannst Du nichts wegwerfen.\n");
997 return 0;
998 }
999
1000 if (!str || str[<4..] != " weg") {
1001 _notify_fail("Wirf etwas WEG, oder was meinst Du?\n");
1002 return 0;
1003 }
1004
1005 _notify_fail("WAS moechtest Du loswerden?\n");
1006 return drop_objects(str[0..<5]);
1007}
1008
1009static int legen(string str)
1010{
1011 if (QueryProp(P_GHOST)) {
1012 _notify_fail("Als Geist kannst Du nichts weglegen.\n");
1013 return 0;
1014 }
1015
1016 if (!str) {
1017 _notify_fail("Lege etwas AB, oder was meinst Du?\n");
1018 return 0;
1019 }
1020
1021 if (str[<3..] == " ab") {
1022 _notify_fail("WAS moechtest Du ablegen?\n");
1023 return drop_objects(str[0..<4]);
1024 }
1025
1026 if (str[<4..] == " weg") {
1027 _notify_fail("WAS moechtest Du weglegen?\n");
1028 return drop_objects(str[0..<5]);
1029 }
1030
1031 _notify_fail("WAS moechtest Du WOHIN legen?\n");
1032 return put_objects(str, WEN, "legen");
1033}
1034
1035static int stecken(string str)
1036{
1037 if (QueryProp(P_GHOST)) {
1038 _notify_fail("Das kannst Du in Deinem immateriellen Zustand nicht.\n");
1039 return 0;
1040 }
1041
1042 _notify_fail("WAS moechtest Du WOHIN stecken?\n");
1043 return put_objects(str, WEN, "stecken");
1044}
1045
1046static int holen(string str)
1047{
1048 if (QueryProp(P_GHOST)) {
1049 _notify_fail("Als Geist kannst Du nichts nehmen.\n");
1050 return 0;
1051 }
1052
1053 _notify_fail("WAS moechtest Du aus WAS holen?\n");
1054 return pick_objects(str, 1);
1055}
1056
1057static int nehmen(string str)
1058{
1059 if (QueryProp(P_GHOST)) {
1060 _notify_fail("Als Geist kannst Du nichts nehmen.\n");
1061 return 0;
1062 }
1063
1064 _notify_fail("WAS moechtest Du nehmen?\n");
1065 return pick_objects(str, 0);
1066}
1067
1068static int geben(string str)
1069{
1070 if (QueryProp(P_GHOST)) {
1071 _notify_fail("Als Geist kannst Du nichts weggeben.\n");
1072 return 0;
1073 }
1074
1075 _notify_fail("WEM moechtest Du WAS geben?\n");
1076 return give_objects(str);
1077}
1078
1079static int zeigen(string str)
1080{
1081 if (QueryProp(P_GHOST)) {
1082 _notify_fail("Als Geist kannst Du niemandem etwas zeigen.\n");
1083 return 0;
1084 }
1085
1086 _notify_fail("WEM moechtest Du WAS zeigen?\n");
1087 return show_objects(str);
1088}
1089
1090protected void add_put_and_get_commands(void)
1091{
1092 add_action("fallenlassen", "lass");
1093 add_action("fallenlassen", "lasse");
1094 add_action("werfen", "wirf");
1095 add_action("werfen", "werf");
1096 add_action("werfen", "werfe");
1097 add_action("legen", "leg");
1098 add_action("legen", "lege");
1099 add_action("stecken", "steck");
1100 add_action("stecken", "stecke");
1101 add_action("holen", "hol");
1102 add_action("holen", "hole");
1103 add_action("nehmen", "nimm");
1104 add_action("nehmen", "nehm");
1105 add_action("nehmen", "nehme");
1106 add_action("geben", "gebe");
1107 add_action("geben", "gib");
1108 add_action("zeigen", "zeig");
1109 add_action("zeigen", "zeige");
1110}
1111
1112
1113/********** Aus reinen Kompatibilitaetsgruenden weiterhin enthalten *********/
1114
1115object* find_obs(string str, int meth)
1116// gibt ein array zurueck mit allen Objekten die mit str angesprochen werden
1117{
1118 object inv;
1119 if (!str) return 0;
1120 if (str[<7..]==" in mir") {
1121 inv=ME;
1122 str=str[0..<8];
1123 }
1124 else if (str[<8..]==" in raum") {
1125 if (meth & PUT_GET_DROP) { // man kann nichts aus dem Raum wegwerfen
1126 _notify_fail("Du kannst nichts wegwerfen, das Du gar nicht hast.\n");
1127 return 0;
1128 }
1129 inv=environment();
1130 str=str[0..<9];
1131 }
1132 else if (meth & PUT_GET_DROP) inv=ME; // Raum bei drop uninteressant
1133 // else kein besonderes inv ausgewaehlt also inv=0
1134 if (!sizeof(str))
1135 return 0; // hier passt die bereits gesetzte _notify_fail
1136 else {
1137 object *obs;
1138 string con;
1139 if (sscanf(str, "%s aus %s", str, con)==2 ||
1140 sscanf(str, "%s in %s", str, con)==2 ||
1141 sscanf(str, "%s von %s", str, con)==2 ||
1142 sscanf(str, "%s vom %s", str, con)==2) {
1143 if (!inv) {
1144 if (!environment() || !(inv=present(con, environment())))
1145 inv=present(con, ME); // sowohl im env als auch im inv suchen
1146 }
1147 else inv=present(con, inv); // nur in ausgewaehltem inv suchen
1148 if (inv==ME) inv=0;
1149 if (!inv || !(inv->short())) {
1150 _notify_fail(break_string("Du hast hier aber kein '"+capitalize(con)
1151 +"'.",78));
1152 return 0;
1153 }
1154 if (living(inv)) {
1155 _notify_fail(break_string("Aber "+inv->name(WER,1)+" lebt doch!",78));
1156 return 0;
1157 }
1158 // wieso man aus Objekten die von std/tray abgeleitet werden etwas
1159 // nehmen koennen soll, versteh ich zwar nicht so ganz...
1160 if (!(inv->QueryProp(P_CONTAINER)) && !(inv->QueryProp(P_TRAY))) {
1161 _notify_fail(break_string("Du kannst nichts aus "+inv->name(WEM,1)
1162 +" nehmen.",78));
1163 return 0;
1164 }
1165 if (inv->QueryProp(P_CNT_STATUS)) { // Container ist geschlossen
1166 _notify_fail(break_string("Aber "+inv->name(WER,1)
1167 +" ist doch geschlossen.", 78));
1168 return 0;
1169 }
1170 }
1171 else if (inv==ME && (meth & PUT_GET_TAKE)) { // nichts aus sich nehmen
1172 _notify_fail("Du kannst nichts nehmen, "
1173 "was Du schon bei Dir traegst.\n");
1174 return 0;
1175 }
1176 if (!inv && (meth & PUT_GET_TAKE))
1177 inv=environment(); // nichts nehmen was man schon hat
1178
1179 if (!inv) {
1180 if (environment()) {
1181 obs=(environment()->present_objects(str)||({}));
1182 if (!sizeof(obs)) obs+=(ME->present_objects(str)||({}));
1183 }
1184 else obs=(ME->present_objects(str) || ({}));
1185 }
1186 else obs=(inv->present_objects(str) || ({}));
1187 return obs-({ ME });
1188 }
1189 return(0);
1190}
1191
1192int pick_obj(object ob)
1193{
1194 object env;
1195
1196 if (!ob || ob == this_object() || environment(ob) == this_object()) return 0;
1197 if ((env=environment(ob)) != environment()) {
1198 if (!env->QueryProp(P_CONTAINER) && !env->QueryProp(P_TRAY)) {
1199 TME("Du kannst nichts aus " + env->name(WEM,1) + " nehmen.");
1200 return 1;
1201 }
1202 else if (env->QueryProp(P_CNT_STATUS)) { // Container ist geschlossen
1203 TME("Aber " + env->name(WER, 1) + " ist doch geschlossen.");
1204 return 1;
1205 }
1206 }
1207 if (ob->IsUnit() && ob->QueryProp(P_AMOUNT)<0) {
1208 TME("Du kannst nicht mehr nehmen als da ist.");
1209 return 1;
1210 }
1211 pick(ob);
1212 return 1;
1213}
1214
1215int drop_obj(object ob)
1216{
1217 if (!ob || ob==this_object() || environment(ob)!=this_object()) return 0;
1218 drop(ob);
1219 return 1;
1220}
1221
1222int put_obj(object ob, object where)
1223{
1224 object env;
1225
1226 if (ob == this_object() || ob == where || environment(ob) == where) return 0;
1227 env=environment(ob);
1228 if (!where->QueryProp(P_CONTAINER)) {
1229 TME("Du kannst in " + where->name(WEN,1) + " nix reinstecken.");
1230 return 1;
1231 }
1232 if (where->QueryProp(P_CNT_STATUS)) { // Container ist geschlossen
1233 TME("Aber " + where->name(WER, 1) + " ist doch geschlossen.");
1234 return 1;
1235 }
1236 if (env!=environment(this_object()) && env!=this_object()) {
1237 _notify_fail("Da kommst du so nicht ran.\n");
1238 return 0;
1239 }
1240 put(ob, where);
1241 return 1;
1242}
1243
1244int give_obj(object ob, object where)
1245{
1246 object env;
1247
1248 if (environment(ob)!=this_object()) {
1249 TME("Das solltest Du erstmal nehmen.");
1250 return 1;
1251 }
1252 if (!ob || ob == this_object() || ob == where ||
1253 environment(where)!=environment())
1254 return 0;
1255 if (environment(ob) == where) {
1256 _notify_fail("Das Ziel ist in dem zu gebenden Object enthalten!\n");
1257 return 0;
1258 }
1259 if (environment(ob)!=this_object()) {
1260 TME("Das hast Du nicht.");
1261 return 1;
1262 }
1263 give(ob, where);
1264 return 1;
1265}