1 /*
2  *  CVS: $Id: Inventory.java,v 1.12 2004/07/26 10:09:12 marcus Exp $
3  * 
4  *  This file is part of JZuul.
5  *
6  *  JZuul is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10 *
11 *  JZuul is distributed in the hope that it will be useful,
12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 *  GNU General Public License for more details.
15 *
16 *  You should have received a copy of the GNU General Public License
17 *  along with Zuul; if not, write to the Free Software
18 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 * 
20 *  Copyrigth 2004 by marcus, leh
21 * 
22 */
23
24package org.jzuul.engine;
25import java.text.MessageFormat;
26import java.util.HashMap;
27import java.util.List;
28import java.util.Map;
29import java.util.Stack;
30import java.util.Iterator;
31import java.util.Vector;
32
33import org.jdom.Element;
34
35/**
36 * Das Inventar eines Spielers oder eines Raums.
37 * Hier werden die aufgenommen GameObjects gehalten.
38 * Das Inventar hat eine Grösse. Jedes aufgenomme GameObject belegt Platz im Inventar,
39 * so dass nur eine gewisse Anzahl an GameObjects aufgenommen werden kann.
40 * 
41 * 
42 * @version $Revision: 1.12 $
43  */
44
45public class Inventory {
46    /**
47     * Interner Datentyp zum halten der GameObjects
48     * HashMap of Stacks
49     */
50    protected Map gameObjectMap;
51    
52    /**
53     * Größe des Inventars in Einheiten
54     */
55    int size = 10;
56    
57    /**
58     * Füllstatus des Inventars
59     */
60    int fillStat = 0;
61    
62    /**
63     * Bildet size == UNLIMITED_INVENTORY ab
64     */
65    boolean isUnlimited;
66    
67    /**
68     * Größenwert für ein unendlich großes Inventar
69     */
70    public static int UNLIMITED_INVENTORY = -1;
71
72    //----------------------------------------------------------------------------
73
74    /**
75     * Konstruktor
76     * @param size - Die größe des Inventar
77     */
78    public Inventory(int size) {
79        this.gameObjectMap = new HashMap();
80        this.size = size;
81        this.isUnlimited = (size == Inventory.UNLIMITED_INVENTORY);
82    }
83
84    /**
85     * Fügt ein neues Item in das Inventar ein
86     * @param item das Aufgenommen werden soll
87     * @return Erfolgsmeldung... konnte das Item aufgenommen werden true, bei Fehlern wie z.B. volles Inventar false
88     */
89    public boolean addGameObject(GameObject item) {
90        if ((!this.isUnlimited) && ((fillStat + item.getSize()) > this.size)) {
91            return false;
92        }
93        if (gameObjectMap.containsKey(item.getName())) {
94            ((Stack) gameObjectMap.get(item.getName())).push(item);
95        } else {
96            Stack s = new Stack();
97            s.push(item);
98            gameObjectMap.put(item.getName(), s);
99        }
00
01        fillStat += item.getSize();
02        return true;
03    }
04
05    /**
06     * @param item das Item das hinzugefügt werden soll
07     * @return  true wenn das Item aufgenommen wurde, false sonst
08     * @see #addGameObject 
09     */
10    public boolean pushGameObject(GameObject item) {
11        return this.addGameObject(item);
12    }
13
14    /**
15     * Get a GameObject by name
16     * @param name  Name des GameObjects das geholt werden soll
17     * @return              Das korespondierende GameObject, null wenn es nicht existiert
18     */
19    public GameObject getGameObject(String name) {
20        if (gameObjectMap.containsKey(name)) {
21            Stack itemStack = (Stack) gameObjectMap.get(name);
22            return (GameObject) itemStack.peek();
23        }
24        return null;
25    }
26
27    /**
28     * Liefert Iterator über die Namen der Objekt in dem Inventars 
29     * 
30     * @return Iterator über die GameObject Namen
31     */
32    public Iterator gameObjectNamesIterator() {
33        return this.gameObjectMap.keySet().iterator();
34    }
35
36    /**
37     * Fragt ob das Iventory das GameObject mit dem Namen name enthält
38     * 
39     * @param name  der Name des GameObject
40     * @return              true falls das Inventar mindest ein GameObject mit dem Namen enthält, false otherwise
41     */
42    public boolean containsGameObject(String name) {
43        return this.gameObjectMap.containsKey(name);
44    }
45
46    /**
47     * Löscht das Item mit dem Namen name
48     * @param name  der Name des zu löschenden Objektes
49     * @return always true ?
50     */
51    public boolean deleteGameObject(String name) {
52        Stack objStack = (Stack) gameObjectMap.get(name);
53        fillStat -= ((GameObject) objStack.peek()).getSize();
54        objStack.pop();
55        if (objStack.isEmpty()) {
56            gameObjectMap.remove(name);
57        }
58        return true;
59    }
60
61    /**
62     * popItem gibt das GameObject mit dem Namen name zurück und entfernt dieses aus dem Inventar
63     *
64     * @param name
65     * @return GameObject on success and null on failure
66     */
67    public GameObject popGameObject(String name) {
68        Stack objStack = (Stack) gameObjectMap.get(name);
69        if (objStack == null) {
70            return null;
71        }
72        GameObject obj = (GameObject) objStack.pop();
73        fillStat -= obj.getSize();
74        if (objStack.isEmpty()) {
75            gameObjectMap.remove(name);
76        }
77        return obj;
78    }
79
80    /**
81     * Gibt eine textuelle Beschreibung des Inventars zurück
82     * 
83     * @return  einen multiline String der den Inhalt des Inventars beschreibt
84     */
85    public String toString() {
86        if (this.gameObjectMap.isEmpty()) {
87            Object[] formatArgs = { new Integer(size) };
88            return MessageFormat.format(Messages.getString("INVENTORY_EMPTY"),formatArgs); //$NON-NLS-1$
89        }
90        String inhalt = new String(Messages.getString("INVENTORY_CONTAINS")); //$NON-NLS-1$
91        for (Iterator i = gameObjectMap.keySet().iterator(); i.hasNext();) {
92            String objName = (String) i.next();
93            inhalt += Helpers.firstToUpper(objName);
94            // tell how many:
95            if (getNumberOfObject(objName) > 1) {
96                inhalt += " (" + getNumberOfObject(objName) + ")\n"; //$NON-NLS-1$ //$NON-NLS-2$
97            } else {
98                inhalt += "\n"; //$NON-NLS-1$
99            }
00        }
01        inhalt += "\n"; //$NON-NLS-1$
02        Object[] formatArgs = {  new Integer(size - fillStat) };
03        inhalt += MessageFormat.format(Messages.getString("INVENTORY_SPACE_LEFT"),formatArgs); //$NON-NLS-1$
04        return inhalt;
05    }
06
07    /**
08     * Sucht alle Character im Inventar
09     * 
10     * @return  Eine Liste aller Character Objekte im Inventar
11     */
12    public List getCharacterObjects() {
13        Vector v = new Vector();
14        for (Iterator i = gameObjectMap.values().iterator(); i.hasNext();) {
15            Stack s = (Stack) i.next();
16            if (!s.isEmpty() && (s.peek() instanceof Character)) {
17                for (Iterator stackIter = s.iterator(); stackIter.hasNext();) {
18                    Character o = (Character) stackIter.next();
19                    v.add(o);
20                }
21            }
22        }
23        return v;
24    }
25
26    /**
27     * Gibt alle GameObjects im Inventar zurück
28     * 
29     * @return  Iterator über die GameObjects Objekte
30     */
31    public Iterator getGameObjects() {
32        Vector v = new Vector();
33        for (Iterator i = gameObjectMap.values().iterator(); i.hasNext();) {
34            Stack s = (Stack) i.next();
35            for (Iterator stackIter = s.iterator(); stackIter.hasNext();) {
36                GameObject o = (GameObject) stackIter.next();
37                v.add(o);
38            }
39        }
40        return v.iterator();
41    }
42
43    /**
44     * Wandelt das Inventar in ein JDOM XML Element um.
45     * 
46     * @return  ein JDOM Element Objekt das den Inhalt des Inventars beschreibt
47     */
48    public Element toElement() {
49        Element contentE = new Element("contents"); //$NON-NLS-1$
50        for (Iterator i = this.getGameObjects(); i.hasNext();) {
51            contentE.addContent(((GameObject) i.next()).toElement());
52        }
53        return contentE;
54    }
55
56    /**
57     * Fragt nach ob das Inventar die GameObjects mit den gegebenen Namen enthält
58     * 
59     * @param objects   Die Namen der zu überprüfenden GameObjects
60     * @return                  true wenn das Inventar für jeden Namen mindestens ein Objekt enthält, false otherwise
61     */
62    public boolean contains(String[] objects) {
63        Vector v = new Vector(objects.length);
64        for (int i = 0; i < objects.length; i++) {
65            v.add(objects[i]);
66        }
67        return contains(v);
68    }
69
70
71    /**
72     * Fragt nach der Anzahl der Objekte mit dem gegebenen Namen
73     * 
74     * @param name  ein Name eines GameObjects
75     * @return              die Anzahl der GameObjects in dem Inventar mit diesem Namen
76     */
77    public int getNumberOfObject(String name) {
78        if (gameObjectMap.containsKey(name)) {
79            Stack s = (Stack) gameObjectMap.get(name);
80            return s.size();
81        } else {
82            return 0;
83        }
84    }
85
86    /**
87     * @param objects eine Liste von Objekten die überprüft werden sollen
88     * @return True wenn die Objekte in dem Invetar sind, false sonst
89     * @see #contains(String[] objects)
90     */
91     public boolean contains(List objects) {
92        Inventory tmp = this.copy();
93        for (Iterator objIter = objects.iterator(); objIter.hasNext();) {
94            String objName = (String) objIter.next();
95            if (tmp.containsGameObject(objName)) {
96                tmp.deleteGameObject(objName);
97            } else {
98                return false;
99            }
00
01        }
02        return true;
03    }
04
05    /**
06     * Erstellt eine depp copy des aktuellen Inventars
07     * 
08     * @return  ein neues Inventar objekt mit dem gleichen Inhalt wie das aktuelle Inventar
09     */
10    public Inventory copy() {
11        Map copy = new HashMap();
12        
13        for (Iterator mapIter = gameObjectMap.keySet().iterator(); mapIter.hasNext();) {
14            String element = (String) mapIter.next();
15            Stack oldStack = (Stack) gameObjectMap.get(element);
16            Stack newStack = new Stack();
17            newStack.addAll(oldStack);
18            copy.put(element, newStack);
19        }
20
21        Inventory newInv =  new Inventory(this.size);
22        newInv.gameObjectMap = copy;
23        newInv.fillStat = this.fillStat;
24        return newInv;
25    }
26
27}
28