enigma-cvs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Enigma-cvs] enigma/src floors.cc,NONE,1.1 levels.hh,NONE,1.1


From: Daniel Heck <address@hidden>
Subject: [Enigma-cvs] enigma/src floors.cc,NONE,1.1 levels.hh,NONE,1.1
Date: Mon, 20 Oct 2003 08:10:12 +0000

Update of /cvsroot/enigma/enigma/src
In directory subversions:/tmp/cvs-serv11282

Added Files:
        floors.cc levels.hh 
Log Message:
New files

--- NEW FILE: floors.cc ---
/*
 * Copyright (C) 2002,2003 Daniel Heck
 *
 * 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.
 *
 * $Id: floors.cc,v 1.1 2003/10/20 08:10:09 dheck Exp $
 */

#include "game.hh"
#include "objects.hh"
#include "object_mixins.hh"

using namespace world;
using namespace std;

Floor::Floor(const char *kind, double friction_, double mfactor)
: TGridObject<GRID_FLOOR>(kind),
  traits (kind, friction_, mfactor, FLOOR_Normal)
{}

Floor::Floor (const FloorTraits &tr)
: TGridObject<GRID_FLOOR>(tr.name.c_str()), traits (tr)
{}

Floor *Floor::clone() {
    return this;
}

void Floor::dispose() {
    ; // do nothing
}

void Floor::message(const string& msg, const Value &/*val*/)
{
}

px::V2 Floor::process_mouseforce (Actor *a, px::V2 force)
{
    if (a->int_attrib("controllers") & (1+player::CurrentPlayer()))
        return mousefactor() * force;
    else
        return V2();
}


namespace
{

/* -------------------- Abyss -------------------- */

    class Abyss : public Floor {
        CLONEOBJ(Abyss);
    public:
        Abyss() : Floor("fl-abyss", 2.0, 1) {}
    private:
//         void actor_enter(Actor* a) {SendMessage(a, "fall");}
        void actor_contact (Actor* a) {SendMessage(a, "fall");}
        bool is_destroyable() const {return false;} 
    };

/* -------------------- Water -------------------- */

    class Water : public Floor {
        CLONEOBJ(Water);
    public:
        Water() : Floor("fl-water", 5, 1) {}
    private:
//         void actor_enter(Actor *a) {SendMessage(a, "drown");}
        void actor_contact(Actor *a) {SendMessage(a, "drown");}

        bool is_destroyable() const {return false;} 
    };

/* -------------------- Swamp -------------------- */

    class Swamp : public Floor {
        CLONEOBJ(Swamp);
    public:
        Swamp() : Floor("fl-swamp", 13, 1.0) {}
    private:
        void actor_contact(Actor *a) { SendMessage(a, "sink"); }
        void actor_leave(Actor *a) {
            Floor *new_floor = GetFloor(GridPos(a->get_pos()));

            if (!new_floor->is_kind("fl-swamp")) {
                SendMessage(a, "getout");
            }
        }
        bool is_destroyable() const {return false;} 
    };

/* -------------------- FallenBox -------------------- */

    class FallenBox : public Floor {
        CLONEOBJ(FallenBox);
    public:
        FallenBox(const char *kind)
        :  Floor(modify_kind(kind), 6.4, 2.0) // uses same traits as fl-wood
        {}

    private:
        const char *modify_kind(const char *kind) {
            if (0 == strcmp(kind, "fl-stwood")) {
                return enigma::IntegerRand(0, 1) ? "fl-stwood1" :  "fl-stwood2";
            }
            return kind;
        }
    };

/* -------------------- DummyFloor -------------------- */

    class DummyFloor : public Floor {
        CLONEOBJ(DummyFloor);
    public:
        DummyFloor() : Floor("fl-dummy", 4.0, 2.5) {}
    private:
        void actor_enter(Actor *) {
            static int lastCode = -1;
            int        code     = int_attrib("code");
            if (lastCode != code) {
                fprintf(stderr, "Entering floor 0x%x\n", code);
                lastCode = code;
            }
        }
    };
}

//----------------------------------------
// Gradient
//----------------------------------------

/** \page fl-gradient Gradient Floor

This is a sloped floor that accelerates in a particular direction.

\subsection gradienta Attributes

- \b type: number between 0 and 15 (see below)

\subsection gradiente Examples

*/
namespace
{
    class Gradient : public Floor {
        CLONEOBJ(Gradient);
    public:
        Gradient(int type=MINTYPE);
    private:
        int get_type() const;
        enum { MINTYPE=1, MAXTYPE=24 };

        // GridObject interface.
        virtual void init_model();

        // Floor interface
        virtual px::V2 get_force(Actor *a);
    };
}

Gradient::Gradient(int type)
: Floor("fl-gradient", 4, 2)
{
    set_attrib ("type", Value(type));
//    set_attrib ("force", Value(1.0));
}

int Gradient::get_type() const
{
    int t=int_attrib("type");
    if (t < MINTYPE || t>MAXTYPE) {
        enigma::Log << "Gradient: Illegal type="<< int(t) << endl;
        t=MINTYPE;
    }
    return t;
}

void Gradient::init_model()
{
    char mname[20];
    sprintf(mname, "fl-gradient%d", get_type());
    set_model(mname);
}

px::V2 Gradient::get_force(Actor */*a*/)
{
    V2 force;
    int t = get_type();

    static int xforce[MAXTYPE-MINTYPE+1] = {
         0,  0,  1, -1,
         1, -1,  1, -1,
         1,  1, -1, -1,
        -1, -1,  1,  1,
         1, -1,  1, -1,
         0,  0,  1, -1
    };
    static int yforce[MAXTYPE-MINTYPE+1] = {
         1, -1,  0,  0,
         1,  1, -1, -1,
         1, -1,  1, -1,
         1, -1,  1, -1,
        -1, -1,  1,  1,
         1, -1,  0,  0
    };
    force = V2(xforce[t-MINTYPE], yforce[t-MINTYPE]);
    force.normalize();

    // use enigma::SlopeForce if no "force" attribute is set
    double factor = enigma::SlopeForce;
    double_attrib("force", &factor);
    return factor*force;
}


//----------------------------------------
// Bridge
//----------------------------------------

/** \page fl-bridge Bridge Floor

This Floor can be opened and closed much like a bridge.
The actor can move over this floor if the bridge is closed,
and will fall into abyss when the bridge is open.

\subsection bridgea Attributes

- \b type       The type of the bridge, currently only 'a' is possible

\subsection bridgem Messages
- \b open       open the bridge so actors cannot pass it
- \b close      close the bridge so actors can pass it
- \b openclose  toggle the state of the bridge
- \b signal     same as \b openclose

*/
namespace
{
    class Bridge : public Floor {
        CLONEOBJ(Bridge);
    public:
        Bridge(bool open=true);
    private:
        enum State {
            OPEN, CLOSED, OPENING, CLOSING, // normal states
            CLOSING_BYSTONE, CLOSED_BYSTONE // when stones are moved onto the 
bridge
        } state;
        // the BYSTONE-states look like closed, but act like open

        char get_type() const {
            string type = "a";
            string_attrib("type", &type);
            return type[0];
        }

//         void actor_enter(Actor *);
        void actor_contact (Actor* a) {if (state!=CLOSED) SendMessage(a, 
"fall");}
        void message(const string &m, const Value &);
        void init_model();
        void stone_change(Stone *st);

        void change_state( State newstate);
        void animcb();
    };
}

Bridge::Bridge(bool open) : Floor("fl-bridge", 5, 1)
{
    set_attrib("type", "a");
    state=open ? OPEN : CLOSED;
}

void Bridge::stone_change(Stone *st) {
    if (st && !st->is_floating()) {
        if (state == OPEN || state == OPENING) {
            change_state(CLOSING_BYSTONE);
        }
    }
    else {
        if (state == CLOSED_BYSTONE || state == CLOSING_BYSTONE) {
            change_state(OPENING);
        }
    }
}

void Bridge::message(const string &m, const Value &)
{
    if (m == "open" && (state==CLOSED || state==CLOSING))
        change_state(OPENING);
    else if (m=="close")
        switch (state) {
        case OPEN:
        case OPENING:
        case CLOSING_BYSTONE:
            change_state(CLOSING);
            break;
        case CLOSED_BYSTONE:
            change_state(CLOSED);
            break;
        case CLOSED:
        case CLOSING:
            break; // already closed

        }
    else if (m=="openclose" || m=="signal")
        switch (state) {
        case OPEN:
        case OPENING:
        case CLOSING_BYSTONE:
            change_state(CLOSING);
            break;
        case CLOSED_BYSTONE:
            change_state(CLOSED);
            break;
        case CLOSED:
        case CLOSING:
            change_state(OPENING);
            break;
        }
}

// void Bridge::actor_enter(Actor *a)
// {
//     if (state != CLOSED)
//         SendMessage(a, "fall");
// }


void Bridge::init_model()
{
    char mname[25];
    sprintf(mname, "fl-bridge%c-%s", get_type(),
            (state==OPEN) ? "open" : "closed");
    set_model(mname);
}

void Bridge::change_state( State newstate)
{
    if (state != newstate) {
        string mname = string("fl-bridge")+get_type();

        switch( newstate) {
            case OPENING: {
                Stone *st = GetStone(get_pos());
                if (st && !st->is_floating()) {
                    if (state == CLOSED || state == CLOSED_BYSTONE)
                        newstate = CLOSED_BYSTONE;
                    else if (state == CLOSING || state == CLOSING_BYSTONE)
                        newstate = CLOSING_BYSTONE;
                    // here the model is already correct!
                }
                else { // no stone or floating stone :
                    if( state == CLOSING || state == CLOSING_BYSTONE)
                        get_model()->reverse();
                    else
                        set_anim(mname+"-opening");
                }
                break;
            }
            case CLOSING:
            case CLOSING_BYSTONE:
                if( state == OPENING)
                    get_model()->reverse();
                else if (state != CLOSING && state != CLOSING_BYSTONE)
                    set_anim(mname+"-closing");
                break;
            case OPEN:
            case CLOSED:
            case CLOSED_BYSTONE:
                state = newstate;
                init_model();
                break;
        }
        state = newstate;
    }
}

void Bridge::animcb()
{
    switch (state) {
        case OPENING: change_state(OPEN); break;
        case CLOSING: change_state(CLOSED); break;
        case CLOSING_BYSTONE: change_state(CLOSED_BYSTONE); break;
        default : assert(0); break;
    }
}


//----------------------------------------
// Black and white tiles
//----------------------------------------
namespace
{
    class BlackTile : public Floor {
    public:
        BlackTile() : Floor ("fl-acblack", 5.0, 2.0) {}

        px::V2 process_mouseforce (Actor *a, px::V2 force)
        {
            if (player::CurrentPlayer() == 0) // && player::IsCurrentPlayer(a))
                return mousefactor() * force;
            else
                return V2();
        }
    };

    class WhiteTile : public Floor {
    public:
        WhiteTile() : Floor ("fl-acwhite", 5.0, 2.0) {}

        px::V2 process_mouseforce (Actor *a, px::V2 force)
        {
            if (player::CurrentPlayer() == 1) // && player::IsCurrentPlayer(a))
                return mousefactor() * force;
            else
                return V2();
        }
    };
}


void InitFloors()
{
    // Floors (most floors are defined in init.lua)
    Register(new Abyss);
    Register(new Water);
    Register(new Swamp);
    Register(new DummyFloor);
    Register(new FallenBox("fl-stwood"));
    Register(new FallenBox("fl-stwood1"));
    Register(new FallenBox("fl-stwood2"));
    Register(new Bridge);
    Register("fl-bridge-open", new Bridge(true));
    Register("fl-bridge-closed", new Bridge(false));
    Register(new WhiteTile);
    Register(new BlackTile);

    Register(new Gradient);
    Register("fl-gradient1", new Gradient(1));
    Register("fl-gradient2", new Gradient(2));
    Register("fl-gradient3", new Gradient(3));
    Register("fl-gradient4", new Gradient(4));
    Register("fl-gradient5", new Gradient(5));
    Register("fl-gradient6", new Gradient(6));
    Register("fl-gradient7", new Gradient(7));
    Register("fl-gradient8", new Gradient(8));
    Register("fl-gradient9", new Gradient(9));
    Register("fl-gradient10", new Gradient(10));
    Register("fl-gradient11", new Gradient(11));
    Register("fl-gradient12", new Gradient(12));
    Register("fl-gradient13", new Gradient(22));
    Register("fl-gradient14", new Gradient(21));
    Register("fl-gradient15", new Gradient(24));
    Register("fl-gradient16", new Gradient(23));
}

--- NEW FILE: levels.hh ---
/*
 * Copyright (C) 2002,2003 Daniel Heck
 *
 * 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.
 *
 * $Id: levels.hh,v 1.1 2003/10/20 08:10:09 dheck Exp $
 */
#ifndef LEVELS_HH
#define LEVELS_HH

namespace levels
{
    /* Enigma can run its own levels but also emulate various versions
       of Oxyd.  All these games behave similarly, but there are also
       quite a few differences in object behaviour, visual appearance,
       etc.  The game type is set at program startup and cannot be
       changed during the game. */
    enum GameType {
        GAMET_FIRST,

        GAMET_ENIGMA = GAMET_FIRST,
        GAMET_OXYD1,
        GAMET_PEROXYD,
        GAMET_OXYDEXTRA,
        GAMET_OXYDMAGNUM,

        GAMET_LAST = GAMET_OXYDMAGNUM,
        GAMET_COUNT,
        GAMET_UNKNOWN
    };

    /* This datastructure contains information about individual
       levels. */
    struct LevelInfo
    {
        // Variables.
        string filename;        // Filename of the level _without_ extension
        string name;            // Complete name of the level
        string author;          // Author of the level
        GameType type;
        int best_time;          // Best time in seconds
        int revision;           // Revision # of this level
        string hint1, hint2;    // Hints for solving this level

        // Methods
        enum { DEFAULT_TIME = 99*60+59 };

        LevelInfo(const string &fn,
                  const string &n,
                  const string &a,
                  GameType gt,
                  int par_time = DEFAULT_TIME
                  )
            : filename(fn), name(n), author(a), type(gt), best_time(par_time)
        {}

        LevelInfo() {
            best_time = DEFAULT_TIME;
            type = GAMET_ENIGMA;
        }
    };

    struct LevelStatus {
        LevelStatus(int easy=-1, int hard=-1, int fin=0, std::time_t solv = 0);
        bool operator != (const LevelStatus& other) const;

        // Variables.
        int  time_easy, time_hard; // Best time in seconds (-1: use level 
default)
        int  finished;          // Level solved? 0 = 
no,1=easy,2=hard,3=easy&hard
        std::time_t solved_at; // date when level was solved last time
        int solved_revision;    // Revision #  that was solved
    };


    class LevelPack {
    public:
        virtual ~LevelPack() {}

        //! Return level pack's name
        virtual string get_name() const = 0;

        //! Return number of levels
        virtual size_t size() const = 0;

        /* Load a level into the game engine */
        virtual bool load_level (size_t index) = 0;

        virtual const LevelInfo *get_info (size_t index) = 0;

        virtual px::Surface *load_preview (size_t /*index*/) { return 0; }

        //! Return file modification time of level(pack)
        virtual std::time_t get_modtime(size_t index) = 0;

        //! Return the default SoundSet (see options::SoundSet for meaning)
        virtual int get_default_SoundSet() const = 0;

        //! returns true if it's a twoplayer levelpack, but has no it-yinyang
        // (needed to add it-yinyang to inventory if oxyd-linkgame is played as 
single-player)
        virtual bool needs_twoplayers() const = 0;

        // returns true if LevelPack may have previews
        virtual bool may_have_previews() const = 0;
    };

}
#endif





reply via email to

[Prev in Thread] Current Thread [Next in Thread]