// zeal - A portable Glk-based Z-code interpreter
// Copyright (C) 2000 Jeremy Condit <jcondit@eecs.harvard.edu>
// 
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

// =======================================================================
//  obj.h:
//
//  this module defines the object class, which is used as a higher-level
//  representation of objects within the z-machine's memory.  the object
//  basically contains the address of the associated object, providing an
//  interface that simplifies code in inst.cc a great deal.
// =======================================================================

#ifndef _obj_h_
#define _obj_h_

#include "zeal.h"
#include "machine.h"

extern machine* m;

const uint NUM_DEFAULTS1 = 31;
const uint NUM_DEFAULTS4 = 63;
const uint OBJECT_SIZE1 = 9;
const uint OBJECT_SIZE4 = 14;
const uint PARENT_OFFSET1 = 4;
const uint PARENT_OFFSET4 = 6;
const uint SIBLING_OFFSET1 = 5;
const uint SIBLING_OFFSET4 = 8;
const uint CHILD_OFFSET1 = 6;
const uint CHILD_OFFSET4 = 10;
const uint TABLE_OFFSET1 = 7;
const uint TABLE_OFFSET4 = 12;

class property;

class object {
    public:
        object(uword n_in);
        object(const object& obj);

        object& operator=(const object& obj);
        bool operator==(const object& obj);
        bool operator!=(const object& obj);

        bool valid();
        uword get_number();
        address get_name();

        bool get_attr(ubyte attr) const;
        void set_attr(ubyte attr, bool value);

        object get_parent() const;
        object get_sibling() const;
        object get_child() const;

        void set_parent(const object& parent);
        void set_sibling(const object& sibling);
        void set_child(const object& child);

        void insert(object& dest);
        void remove();

        property get_property(ubyte n);
        property get_first_property();

    private:
        uword n;
        address addr;

        ubyte get_attr_byte(ubyte attr) const;
        void set_attr_byte(ubyte attr, ubyte byte);

        uint get_num_defaults() const
             { return (m->version() <= 3) ? NUM_DEFAULTS1 : NUM_DEFAULTS4; }
        uint get_object_size() const
             { return (m->version() <= 3) ? OBJECT_SIZE1 : OBJECT_SIZE4; }
        uint get_parent_offset() const
             { return (m->version() <= 3) ? PARENT_OFFSET1 : PARENT_OFFSET4; }
        uint get_sibling_offset() const
             { return (m->version() <= 3) ? SIBLING_OFFSET1 : SIBLING_OFFSET4; }
        uint get_child_offset() const
             { return (m->version() <= 3) ? CHILD_OFFSET1 : CHILD_OFFSET4; }
        uint get_table_offset() const
             { return (m->version() <= 3) ? TABLE_OFFSET1 : TABLE_OFFSET4; }
};

#endif // _obj_h_
