Added public files
Roughly added all public files. Probably missed some, though.
diff --git a/items/bottle.c b/items/bottle.c
new file mode 100644
index 0000000..33935f4
--- /dev/null
+++ b/items/bottle.c
@@ -0,0 +1,321 @@
+/****************************************/
+/* BOTTLE.C -- a standard bottle object */
+/* or better a container for*/
+/* liquides */
+/* -- */
+/* (c) by Hate 1993 */
+/****************************************/
+
+inherit "/std/thing";
+
+/*****************************************************************************/
+#include <properties.h>
+#include <language.h>
+
+#define PL this_player()
+
+#define GULP 20 /* millilitre is one gulp ;) */
+
+#define NO ({"hundert", "neunzig", "achtzig", "siebzig",\
+ "sechzig", "fuenfzig", "vierzig", "dreissig",\
+ "zwanzig", "zehn"})
+
+#define FULL(what, amount) (what*_MaxCapacity/amount)
+#define PART(what, amount) (what*amount/_MaxCapacity)
+#define AVER(x,y, amount) ((FULL(x, amount)+y)/2)
+
+private string _Fname, _Fdescr;
+private int _Fprice, _Fheal, _Fstrength, _Fsoak;
+private int _MaxCapacity, _Capacity, _NoDrinking;
+private int _open, _NoClose;
+
+/**** ALL THE PUBLIC FUNCTIONS ***********************************************/
+public void LiquidContDescr(string Cname, string *Cids, string Cshort, string Clong,
+ int Cweight, int Capa, int NoClose, string Clabel)
+/* give a decription for the liquid container */
+/* Cname -- P_NAME of the container */
+/* Cid -- identity of the container */
+/* Cshort -- P_SHORT of the container */
+/* Clong -- P_LONG of the container */
+/* Cweight -- weight of the container */
+/* Ccapa -- capacity of the container */
+/* -- OPTIONAL -- */
+/* NoClose -- means if 1 the container can't be closed */
+/* Clabel -- optional readable label (for bottles) */
+{
+ SetProp(P_NAME, Cname);
+ SetProp(P_SHORT, Cshort);
+ SetProp(P_LONG, Clong);
+ SetProp(P_READ_MSG, Clabel);
+ SetProp(P_WEIGHT, Cweight);
+ SetProp(P_IDS, Cids);
+ _MaxCapacity = Capa;
+ _Capacity = Capa;
+ if(_NoClose = NoClose) _open = 1;
+}
+
+public int AddLiquid(int Famount, string Fname, string Fdescr, int Fprice,
+ int Fheal, int Fstrength, int Fsoak)
+/* add something in the container */
+/* Famount -- amount of liquid to be added to container, if more ignored */
+/* or better the container will run over */
+/* Fname -- name of the liquid, if there is still something inside the */
+/* container, it it will be mixed */
+/* Fdescr -- if somebody wants to look at the liquid he sees it if the */
+/* container is open */
+/* Fprice -- the price of the liquid for the given amount */
+/* Fheal -- the healing per for the given amount */
+/* Fstrength -- the strength of the liquid for the given amount */
+/* Fsoak -- the soak value for the given amount */
+{
+ if(_Capacity && Famount)
+ {
+ if(Famount<=_Capacity) _Capacity -= Famount;
+ else { Famount = _Capacity; _Capacity = 0; }
+ if(!_Fname || _Fname == Fname) { _Fname = Fname; _Fdescr = Fdescr; }
+ else { _Fdescr = "Eine Mixtur aus "+_Fname+" und "+Fname;
+ _Fname = _Fname+":"+Fname; }
+ if(_Fprice) _Fprice = AVER(Fprice, _Fprice, Famount);
+ else _Fprice = FULL(Fprice, Famount);
+ if(_Fheal) _Fheal = AVER(Fheal, _Fheal, Famount);
+ else _Fheal = FULL(Fheal, Famount);
+ if(_Fstrength) _Fstrength = AVER(Fstrength, Fstrength, Famount);
+ else _Fstrength = FULL(Fstrength, Famount);
+ if(_Fsoak) _Fsoak = AVER(Fsoak, _Fsoak, Famount);
+ else _Fsoak = FULL(Fsoak, Famount);
+ SetProp(P_VALUE, PART(_Fprice, (_MaxCapacity-_Capacity)));
+ }
+ return Famount;
+}
+
+/* to pour something out of the container */
+/* Famount -- amount of liquid to be poured */
+/* -- OPTIONAL -- */
+/* where -- if set the amount will be added to the container 'where' */
+public int PourLiquid(int Famount, object where)
+{
+ int pour, rest, oldc;
+
+ oldc = _Capacity;
+ if(objectp(where) && where->QueryContainer())
+ {
+ pour = Famount;
+ while(pour &&
+ (rest=where->AddLiquid(GULP, _Fname, _Fdescr,
+ PART(_Fprice, Famount),
+ PART(_Fheal, Famount),
+ PART(_Fstrength, Famount),
+ PART(_Fsoak, Famount)))==GULP)
+ pour -= GULP;
+ Famount -= rest;
+ }
+ else
+ if(objectp(where) && living(where))
+ {
+ if(Famount>_MaxCapacity-_Capacity) Famount = _MaxCapacity-_Capacity;
+ if(PART(_Fsoak, Famount) && !where->drink_soft(PART(_Fsoak, Famount)))
+ return 0;
+ if(!where->drink_alcohol(PART(_Fstrength, Famount)))
+ return 0;
+ where->heal_self(PART(_Fheal, Famount));
+ }
+ _Capacity += Famount;
+ SetProp(P_VALUE, PART(_Fprice, (_MaxCapacity-_Capacity)));
+ return oldc != _Capacity;
+}
+
+/* sometimes there is something poinsonous inside the container */
+/* no -- must be 1 if it is not allowed to drink (standard yes) */
+/* that means the liquid can be poured and filled, but nothing else */
+public int AllowDrinking(int no) { return _NoDrinking = no; }
+
+/* returns the amount and name of the contents as an array 0-contents 1-name */
+public <int|string>* QueryContents() { return ({ _MaxCapacity-_Capacity, _Fname }); }
+
+/* returns 1 if this is an liquid container */
+public int QueryContainer() { return 1; }
+
+/*****************************************************************************/
+protected void create()
+{
+ if (!clonep(this_object())) return;
+ ::create();
+
+ SetProp(P_NAME, "Flasche");
+ AddId("flasche");
+ SetProp(P_SHORT, "Eine Flasche");
+ SetProp(P_LONG, "Du siehst nichts besonderes an oder in der Flasche.\n");
+ SetProp(P_GENDER, FEMALE);
+ SetProp(P_WEIGHT,100);
+}
+
+void init()
+{
+ ::init();
+
+ add_action("DoDrink", "trinke");
+ add_action("DoDrink", "trink");
+ add_action("DoPour", "schuette");
+ add_action("DoPour", "schuett");
+ add_action("DoPour", "fuelle");
+ add_action("DoPour", "fuell");
+ add_action("DoOpen", "oeffne");
+ add_action("DoClose", "schliesse");
+ add_action("DoLookInside", "schaue");
+ add_action("DoLookInside", "schau");
+}
+
+int DoDrink(string arg)
+{
+ string howmuch, trash, str;
+ int all, cnt;
+
+ if(!_NoDrinking && arg && sscanf(arg, "%saus %s", str, trash)==2 && id(trash))
+ {
+ if(!_open) return write(capitalize(name(0,1))+" ist aber noch zu.\n") || 1;
+ if(_Capacity==_MaxCapacity)
+ {
+ write("Du setzt "+name(WEN, 1)+" an und merkst, dass nichts mehr darin "
+ +"ist.\n");
+ say(PL->name()+" setzt "+name(WEN)+" an und merkt, dass nichts mehr darin"
+ +" ist.\n");
+ return 1;
+ }
+ if(sscanf(str, "alles%s", trash) == 1)
+ {
+ all = _Capacity;
+ while(PourLiquid(GULP, PL));
+ if(_Capacity==all) return write("Du schaffst es nicht zu trinken.\n"),0;
+ if(_MaxCapacity>_Capacity)
+ write("Du hast nur einen Teil zu trinken geschafft.\n");
+ else
+ {
+ write("Du trinkst alles bis zum letzten Rest aus "+name(WEM, 1)+".\n");
+ say(PL->name()+" trinkt alles bis zum letzten Rest aus "
+ +name(WEM)+".\n");
+ }
+ return 1;
+ }
+ if(str==" " || (str=="schluck" || sscanf(str, "schluck%s", trash)) == 1)
+ if(PourLiquid(GULP, PL))
+ {
+ write("Du trinkst einen Schluck aus "+name(WEM, 1)+".\n");
+ say(PL->name()+" trinkt einen Schluck aus "+name(WEM)+".\n");
+ return 1;
+ }
+ else return write("Du schaffst es nicht zu trinken.\n") || 1;
+ else
+ {
+ if(sscanf(str, "%s schluck%s", howmuch, trash)>=1)
+ switch(howmuch)
+ {
+ case "1":
+ case "ein":
+ case "einen": { cnt = 1; howmuch = "einen"; break; }
+ case "2":
+ case "zwei" : { cnt = 2; break; }
+ case "3":
+ case "drei" : { cnt = 3; break; }
+ case "4":
+ case "vier" : { cnt = 4; break; }
+ case "5":
+ case "fuenf": { cnt = 5; break; }
+ case "6":
+ case "sechs": { cnt = 6; break; }
+ case "7":
+ case "sieben":{ cnt = 7; break; }
+ case "8":
+ case "acht" : { cnt = 8; break; }
+ case "9":
+ case "neun" : { cnt = 9; break; }
+ case "10":
+ case "zehn" : { cnt = 10; break; }
+ default: cnt = 0;
+ }
+ if(!cnt) { cnt = 1; howmuch = "einen"; }
+ while(cnt-- && all=PourLiquid(GULP, PL));
+ if(cnt>0 && all==_MaxCapacity)
+ write("Sooo viele Schluecke waren gar nicht in "+name(WEM, 1)+".\n");
+ else write("Du trinkst ein paar Schluck aus "+name(WEM, 1)+".\n");
+ say(PL->name()+" trinkt aus "+name(WEM)+".\n");
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int DoPour(string arg)
+{
+ object dest;
+ string where, str;
+
+ if(arg && sscanf(arg, "%saus %s", str, where)==2 && id(where))
+ {
+ if(!_open) return write(capitalize(name(0,1))+" ist aber noch zu.\n") || 1;
+ if(_Capacity==_MaxCapacity)
+ return write("Es ist nichts in "+name(WEM, 1)+".\n") || 1;
+ if(sscanf(str, "alles%s", where)==1)
+ {
+ PourLiquid(_MaxCapacity, environment(this_player()));
+ write("Du schuettest alles aus "+name(WEM, 1)+".\n");
+ say(PL->name()+" schuettet alles aus "+name(WEM)+".\n");
+ return _Capacity;
+ }
+ if(sscanf(str, "in %s", where)==1)
+ {
+ if(!dest = present(where)) dest = present(where, environment(PL));
+ if(dest && !query_once_interactive(dest) &&
+ PourLiquid(_MaxCapacity-_Capacity, dest))
+ {
+ write("Du fuellst "+dest->name(WEN, 1)+" mit "+_Fname+" ab.\n");
+ say(PL->name()+" fuellt "+dest->name(WEN)+" mit "+_Fname+" ab.\n");
+ return _Capacity;
+ }
+ }
+ }
+ return 0;
+}
+
+int DoOpen(string str)
+{
+ if(id(str) && !_NoClose)
+ {
+ if(_open) return write(capitalize(name(0,1))+" ist schon offen.\n") || 1;
+ write("Du oeffnest "+name(WEN, 1)+".\n");
+ say(PL->name()+" oeffnet "+name(WEN)+".\n");
+ _open = 1;
+ return 1;
+ }
+ return 0;
+}
+
+int DoClose(string str)
+{
+ if(id(str) && !_NoClose)
+ {
+ if(!_open) return write(capitalize(name(0,1))+" ist schon zu.\n") || 1;
+ write("Du machst "+name(WEN, 1)+" zu.\n");
+ say(PL->name()+" schliesst "+name(WEN)+".\n");
+ _open = 0;
+ return 1;
+ }
+ return 0;
+}
+
+int DoLookInside(string str)
+{
+ string trash;
+
+ if(str && sscanf(str, "in %s", trash)==1 && id(trash))
+ {
+ if(!_open) return write(capitalize(name(0,1))+" ist aber noch zu.\n") || 1;
+ if(_Capacity==_MaxCapacity)
+ return write("Es ist nichts in "+name(WEM, 1)+".\n") || 1;
+ write(capitalize(name(0,1))
+ +" ist zu "+NO[_Capacity*10/_MaxCapacity]+" Prozent voll mit "
+ +_Fdescr+".\n");
+ return 1;
+ }
+ return 0;
+}
+