backwardsgravity

#include <ncurses.h>
#include <vector>
#include <string>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
#define MAP_NUM 50
#define MOD_NUM 5

void Title();
void Init();

void Input();
void Edit(int l);

void Draw();
void Update();

void Exit();

void GenerateMaps();
void MT1(int i);
void MT2(int i);
void MT3(int i);

void PlaceEnemies(int i);
void DisplayText();

class CObject
{
    public:
        CObject(int x=0,int y=0,char t='?',string name="CObject",bool b=true,int a=0,int h=100):m_X(x),m_Y(y),m_Tile(t),m_Type("CObject"),m_Block(b),m_AI(a),m_Health(h),m_MaxHealth(h),m_Amount(1),m_Name(name),m_Delete(false),m_PickUp(false){};
        ~CObject(){};
       
        int Run();
        int Message(string m);
        bool Is(string s);
        void ChangeModifier(string old,string now,int n=-1);
       
        int m_X,m_Y,m_Health,m_MaxHealth,m_AI,m_Amount;
        int m_Attack,m_Defense,m_Damage,m_MaxDamage;
        char m_Tile;
        string m_Type,m_Name,m_WearType,m_Modifiers[MOD_NUM];
        bool m_Block,m_Delete,m_PickUp;
        vector<CObject *> m_Inventory[2];
};
CObject *GetObject(int x,int y,int n);
char GetMap(int x,int y);

char m_Maps[MAP_NUM][80][25];
vector<CObject *> m_Objects[MAP_NUM];
int m_Map;
CObject g_Player(1,1,'@');
bool m_Edit,m_On;
char m_Tile;
int m_Jump;
vector<string> m_Display[2];

int main()
{
    Init();
    Title();
    while(m_On)
    {
        Input();
        Update();
        Draw();
    };
    Exit();
};
void Init()
{
    int i,j,k;
    CObject *o;
    srand(time(0));
    m_Map = m_Jump = 0;
    m_Edit = false;
    m_Tile = '#';
    initscr();
    keypad(stdscr,true);
    clear();
    m_On=true;
    GenerateMaps();
};
void Title()
{
    mvprintw(0,0,"Backwards Gravity\nthe 7DRL.\n\nMath and physics has collapsed! As a brilliant mathematician, you are \nthe only one who can restore math and physics and save all life.\n\n[press space to continue.]");
    refresh();
    while(getch()!=' ');
};
void Input()
{
    int m_XMove,m_YMove;
    int i,l,nx,ny;
    nx = g_Player.m_X;
    ny = g_Player.m_Y;
    switch(l=getch())
    {
        case 'E':
            m_Edit=!m_Edit;
            break;
        case 'q':
            mvprintw(0,0,"Really quit? [Y/n]");
            refresh();
            if(getch()=='Y')
                m_On = false;
        case KEY_UP:
            if(m_Jump==0&&GetMap(g_Player.m_X,g_Player.m_Y)=='.')
                ny--;
            break;
        case KEY_DOWN:
            if(m_Jump==0&&GetMap(g_Player.m_X,g_Player.m_Y)=='.')
                ny++;
            break;
        case KEY_LEFT:
            nx--;
            if(m_Jump==0&&GetMap(g_Player.m_X-1,g_Player.m_Y)==' ')
                m_Jump = -1;
            break;
        case KEY_RIGHT:
            nx++;
            if(m_Jump==0&&GetMap(g_Player.m_X+1,g_Player.m_Y)==' ')
                m_Jump = -1;
            break;
        case '?':
            mvprintw(0,0,"Keys:\n");
            printw("E - Edit mode.\n");
            printw("q - Quit.\n");
            printw("Arrow Keys - Move.\n");
            printw("j - Jump.\n");
            printw("> - Go down.\n");
            printw("< - Go up.\n");
            getch();
            break;
        case 'j':
            if(GetMap(g_Player.m_X,g_Player.m_Y)=='.')
                if(GetMap(g_Player.m_X,g_Player.m_Y-1)=='#'&&GetMap(g_Player.m_X,g_Player.m_Y+1)!='#')
                    m_Jump = -1;
                else
                    m_Jump = 4;
            break;
        case '<':
            if(GetObject(g_Player.m_X,g_Player.m_Y,0)!=NULL&&GetObject(g_Player.m_X,g_Player.m_Y,0)->Is("stairs")&&GetObject(g_Player.m_X,g_Player.m_Y,0)->Is("up"))
            {
                m_Map--;
                if(m_Map<0)
                    m_Map=0;
                g_Player.m_X=g_Player.m_Y=0;
                while(m_Maps[m_Map][g_Player.m_X][g_Player.m_Y]!='.')
                {
                    g_Player.m_X = rand()%79;
                    g_Player.m_Y = rand()%23;
                };
            };
            break;
        case '>':
            if(GetObject(g_Player.m_X,g_Player.m_Y,0)!=NULL&&GetObject(g_Player.m_X,g_Player.m_Y,0)->Is("stairs")&&GetObject(g_Player.m_X,g_Player.m_Y,0)->Is("down"))
            {
                m_Map++;
                if(m_Map>27)
                {
                    mvprintw(0,0,"You win!!!\n");
                    m_On = false;
                    getch();
                    refresh();
                    getch();
                    getch();
                    getch();
                    getch();
                    getch();
                    getch();
                    refresh();
                    getch();
                };
                g_Player.m_X=g_Player.m_Y=0;
                while(m_Maps[m_Map][g_Player.m_X][g_Player.m_Y]!='.')
                {
                    g_Player.m_X = rand()%79;
                    g_Player.m_Y = rand()%23;
                };
            };
            break;
    };
    if(m_Edit)
        Edit(l);
    if(m_Jump>0)
    {
        ny--;
        m_Jump--;
        if(GetMap(nx,ny)!=' '&&GetMap(nx,ny)!='.'&&GetMap(nx,ny+2)!='#')
            m_Jump = 0;
    };
    if(m_Jump==0&&GetMap(g_Player.m_X,g_Player.m_Y)==' ')
        ny++;
    if(m_Jump==-1)
        ny++;
    if(m_Jump==-1&&GetMap(nx,ny)!=' ')
        m_Jump = 0;
    if((GetObject(nx,ny,0)==NULL||GetObject(nx,ny,0)->m_Block==false)&&(GetMap(nx,ny)=='.'||((GetMap(g_Player.m_X,g_Player.m_Y)==' '||m_Jump!=0)&&GetMap(nx,ny)==' ')))
    {
        g_Player.m_X = nx;
        g_Player.m_Y = ny;
    };
    if(GetMap(nx,ny)==' '&&GetMap(g_Player.m_X,g_Player.m_Y)!=' ')
    {
        string s = "Press 'j' to jump.";
        m_Display[0].push_back(s);
    };
    i=0;
    while(GetObject(nx,ny,i)!=NULL)
        GetObject(nx,ny,i++)->Message("touch");
};
void Edit(int l)
{
    switch(l)
    {
        case ' ':
            m_Maps[m_Map][g_Player.m_X][g_Player.m_Y]=m_Tile;
            break;
        case 'g':
            m_Tile=m_Maps[m_Map][g_Player.m_X][g_Player.m_Y];
            break;
        case ']':
            while(isgraph(++m_Tile)==0);
            break;
        case '[':
            while(isgraph(--m_Tile)==0);
            break;
        case 't':
            mvprintw(0,0,"Tile? ");
            while(isgraph(m_Tile=getch())==0);
            break;
    };
};
void Draw()
{
    int i,j;
    string s;
    char b[255];
    clear();
    for(i=0;i<80;i++)for(j=0;j<24;j++)
        mvaddch(j,i,m_Maps[m_Map][i][j]);
    for(i=0;i<m_Objects[m_Map].size();i++)
        mvaddch(m_Objects[m_Map][i]->m_Y,m_Objects[m_Map][i]->m_X,m_Objects[m_Map][i]->m_Tile);
    mvaddch(g_Player.m_Y,g_Player.m_X,m_Edit?m_Tile:g_Player.m_Tile);
    sprintf(b,"HP: %d/%d ",g_Player.m_Health,g_Player.m_MaxHealth);
    s = b;
    m_Display[1].push_back(s);
    if(m_Jump>0)
    {
        sprintf(b,"Jump left: %d ",m_Jump);
        s = b;
        m_Display[1].push_back(s);
    };
    DisplayText();
    move(0,0);
    refresh();
};
void Update()
{
    int i;
    for(i=0;i<m_Objects[m_Map].size();i++)
        !m_Edit?m_Objects[m_Map][i]->Run():0;
    for(i=0;i<m_Objects[m_Map].size();i++)
        if(m_Objects[m_Map][i]->m_Delete)
        {
            delete(m_Objects[m_Map][i]);
            m_Objects[m_Map].erase(m_Objects[m_Map].begin()+i);
            i--;
        };
};
void Exit()
{
    int i;
    for(i=0;i<MAP_NUM;i++)while(m_Objects[i].size()>0)
    {
        delete(m_Objects[i][0]);
        m_Objects[i].erase(m_Objects[i].begin());
    };
    endwin();
};
int CObject::Run()
{
    int m_XMove,m_YMove,i;
    switch(m_AI)
    {
        case 0:
            break;
        case 1:
            if(abs(m_X-g_Player.m_X)>8||abs(m_Y-g_Player.m_Y)>8)
            {
                break;
            };
            m_XMove=m_YMove=0;
            if(g_Player.m_X<m_X&&rand()%4==0)
                m_XMove=-1;
            if(g_Player.m_Y<m_Y&&rand()%3==0&&m_XMove==0)
                m_YMove=-1;
            if(g_Player.m_X>m_X&&rand()%4==0&&m_YMove==0)
                m_XMove=1;
            if(g_Player.m_Y>m_Y&&rand()%3==0&&m_XMove==0)
                m_YMove=1;
            if(m_XMove==0&&m_YMove==0)
            {
                if(g_Player.m_X<m_X)
                    m_XMove=-1;
                if(g_Player.m_Y<m_Y&&m_XMove==0)
                    m_YMove=-1;
                if(g_Player.m_X>m_X&&m_YMove==0)
                    m_XMove=1;
                if(g_Player.m_Y>m_Y&&m_XMove==0)
                    m_YMove=1;
            };
            if(m_Health<m_MaxHealth/5)
            {
                m_XMove = -m_XMove;
                m_YMove = -m_YMove;
            };
            if(m_X+m_XMove==g_Player.m_X&&m_Y+m_YMove==g_Player.m_Y)
                m_XMove = m_YMove = 0;
            if(m_Maps[m_Map][m_X+m_XMove][m_Y+m_YMove]!='.'&&m_Maps[m_Map][m_X+m_XMove][m_Y+m_YMove]!=' ')
                m_XMove = m_YMove = 0;
            for(i=0;i<m_Objects[m_Map].size();i++)
                if(m_Objects[m_Map][i]->m_X==m_X+m_XMove&&m_Objects[m_Map][i]->m_Y==m_Y+m_YMove)
                    m_XMove = m_YMove = 0;
            m_X+=m_XMove;
            m_Y+=m_YMove;
            if(m_X<0)
                m_X=0;
            if(m_Y<0)
                m_Y=0;
            if(m_X>78)
                m_X=78;
            if(m_Y>23)
                m_Y=23;
            break;
        case 2:
            break;
    };
    return 0;
};
int CObject::Message(string m)
{
    if((m=="touch"&&Is("door"))||(m=="open"&&Is("openable")))
    {
        if(Is("open"))
            mvprintw(0,0,"The %s is already open.",m_Name.c_str());
        if(Is("closed")&&!Is("on fire"))
        {
            mvprintw(0,0,"You open the %s.",m_Name.c_str());
            ChangeModifier("closed","open");
        };
        if(Is("locked"))
            mvprintw(0,0,"The %s is locked.",m_Name.c_str());
        if(Is("stuck")&&rand()%4!=0)
            mvprintw(0,0,"The %s resists.",m_Name.c_str());
        else if(Is("stuck")&&!Is("on fire"))
        {
            mvprintw(0,0,"You open the %s.",m_Name.c_str());
            ChangeModifier("stuck","open");
        };
        if(Is("on fire"))
            mvprintw(0,0,"The %s is on fire and is too hot to open.",m_Name.c_str());
        if(Is("broken"))
            mvprintw(0,0,"The %s is broken and can't be opened.",m_Name.c_str());
       
        if((Is("open")||Is("broken"))&&Is("door"))
        {
            m_Tile = '`';
            m_Block = false;
        }
        else if(Is("door")&&(Is("closed")||Is("locked")||Is("stuck")))
        {
            m_Tile = '+';
            m_Block = true;
        };
        getch();
        refresh();
    };
    if(m_AI==1&&m=="touch")
    {
        m_Display[0].push_back("You hit the enemy!");
        m_Health-=30;
        if(m_Health<0)
            m_Delete = true;
    };
};
bool CObject::Is(string s)
{
    int i;
    for(i=0;i<MOD_NUM;i++)
        if(m_Modifiers[i]==s)
            return true;
    return false;
};
void CObject::ChangeModifier(string old,string now,int n)
{
    int i;
    if(old==now&&n==-1)return;
    if(n!=-1)
    {
        m_Modifiers[n] = now;
        return;
    };
    for(i=0;i<MOD_NUM;i++)
        if(m_Modifiers[i]==old)
            m_Modifiers[i]=now;
};
CObject *GetObject(int x,int y,int n)
{
    int i,j;
    j = 0;
    for(i=0;i<m_Objects[m_Map].size();i++)
        if(m_Objects[m_Map][i]->m_X==x&&m_Objects[m_Map][i]->m_Y==y&&j==n)
            return m_Objects[m_Map][i];
        else if(m_Objects[m_Map][i]->m_X==x&&m_Objects[m_Map][i]->m_Y==y)
            j++;
    return NULL;
};
char GetMap(int x,int y)
{
    if(x<0||y<0||x>80||y>25)
        return '#';
    return m_Maps[m_Map][x][y];
};
void DisplayText()
{
    int i;
    mvprintw(0,0,"");
    for(i=0;i<m_Display[0].size();i++)
        printw(m_Display[0][i].c_str());
    mvprintw(24,0,"");
    for(i=0;i<m_Display[1].size();i++)
        printw(m_Display[1][i].c_str());
    m_Display[0].clear();
    m_Display[1].clear();
};

void GenerateMaps()
{
    int i,j,k;
    for(i=0;i<MAP_NUM;i++)
    {
        m_Map = i;
        for(j=0;j<80;j++)for(k=0;k<25;k++)
                m_Maps[i][j][k] = ' ';
        if(i==0)
            MT3(i);
        else
        switch(rand()%2)
        {
            default:
            case 0:
                MT1(i);
                break;
            case 1:
                MT2(i);
                break;
        };
        PlaceEnemies(i);
    };
    m_Map=0;
    while(GetMap(g_Player.m_X,g_Player.m_Y)!='.')
    {
        g_Player.m_X = rand()%80;
        g_Player.m_Y = rand()%25;
    };
};
void Link(int x,int y,int x2,int y2)
{
    int i,j;
    bool o;
    if(y2<y)
    {
        i = x;
        j = y;
        x = x2;
        y = y2;
        x2 = i;
        y2 = j;
    };
    if(y==0)
        y=1;
    if(x<x2)
    {
        for(i=x;i<x2;i+=2+(rand()%3))
        {
            //if(GetMap(i,y)==' ')
            m_Maps[m_Map][i][y]='.';
            if(GetMap(i,y+1)==' ')
            m_Maps[m_Map][i][y+1]='#';
        };
    }
    else
    {
        for(i=x;i>x2;i-=2+(rand()%3))
        {
            //if(GetMap(i,y)==' ')
            m_Maps[m_Map][i][y]='.';
            if(GetMap(i,y+1)==' ')
            m_Maps[m_Map][i][y+1]='#';
        };
    };
    o = false;
    for(i=y;i<y2;i+=3)
    {
        //if(GetMap(x2,i)==' ')
        if(o)x2++;
        else x2--;
        m_Maps[m_Map][x2][i]='.';
        if(GetMap(x2,i+1)==' ')
        m_Maps[m_Map][x2][i+1]='#';
        o=!o;
    };
};

void MT1(int i)
{
    int j,k,l,j2,k2;
    int x,y,x2,y2;
    x2 = 0;
    y2 = 23;
    for(l=0;l<6+(rand()%4);l++)
    {
        x=rand()%70;
        y=rand()%15;
        j2 = 5+(rand()%5);
        k2 = 5+(rand()%5);
        if(GetMap(x,y)==' ')
        {
            if(l>0)
                Link(x,y,x2,y2);
            for(j=0;j<j2;j++)for(k=0;k<k2;k++)
                    if(k==0||j==0||k==k2-1||j==j2-1)
                        m_Maps[i][j+x][k+y] = '.';
                    else
                        m_Maps[i][j+x][k+y] = '#';
            x2 = x;
            y2 = y;
        }
        else
            l--;
    };
    for(l=0;l<80;l++)
        m_Maps[i][l][23]='^';
};
void MT2(int i)
{
    int m_Rooms[10][2];
    int j,k,l,j2,k2;
    int x,y,x2,y2;
    bool good,up,down,left,right;
    for(j=0;j<10;j++)
    {
        good=true;
        m_Rooms[j][0] = rand()%63;
        m_Rooms[j][1] = rand()%23;
        x =8+(rand()%10);
        y =2;
        for(k=0;k<x;k++)
            for(l=0;l<y;l++)
                if(m_Maps[i][k+m_Rooms[j][0]][l+m_Rooms[j][1]]!=' ')
                    good = false;
        if(good)
        for(k=0;k<x;k++)
            for(l=0;l<y;l++)
                if(l==y-2)
                    m_Maps[i][k+m_Rooms[j][0]][l+m_Rooms[j][1]] = '.';
                else if(l==y-1)
                    m_Maps[i][k+m_Rooms[j][0]][l+m_Rooms[j][1]] = '#';
        if(!good)
            j--;
        if(good&&j>0)
            Link(m_Rooms[j][0],m_Rooms[j][1],m_Rooms[j-1][0],m_Rooms[j-1][1]);
    };
    up=down=left=right=false;
    if(rand()%3==0)
        up=true;
    if(rand()%3==0)
        down=true;
    if(rand()%3==0)
        left=true;
    if(rand()%3==0)
        right=true;
    for(j=0;j<80;j++)
        for(k=0;k<25;k++)
        {
            if(j==0&&left)
                m_Maps[i][j][k] = '#';
            if(j==1&&left)
                m_Maps[i][j][k] = '.';
            if(j==79&&right)
                m_Maps[i][j][k] = '#';
            if(j==78&&right)
                m_Maps[i][j][k] = '.';
            if(k==0&&up)
                m_Maps[i][j][k] = '#';
            if(k==1&&up)
                m_Maps[i][j][k] = '.';
            if(k==23&&down)
                m_Maps[i][j][k] = '#';
            if(k==22&&down)
                m_Maps[i][j][k] = '.';
        };
    j2 = 2+rand()%4;
    for(l=0;l<j2;l++)
    {
        x=rand()%74;
        y=rand()%19;
        j2 = 3+(rand()%4);
        k2 = 3+(rand()%4);
        if(GetMap(x,y)==' ')
            for(j=0;j<j2;j++)for(k=0;k<k2;k++)
                    if(k==0||j==0||k==k2-1||j==j2-1)
                        m_Maps[i][j+x][k+y] = '.';
        else
            m_Maps[i][j+x][k+y] = '#';
        else
            l--;
    };
};

void MT3(int i)
{
    int x,y,j,k,l;
    int h;
    x = 30;
    y = 12;
    for(k=0;k<8;k++)
    {
        for(l=0;l<8;l++)
            if(k==0||l==0||k==7||l>4)
                m_Maps[i][x+k][y+l]='#';
            else
                m_Maps[i][x+k][y+l]='.';
        m_Maps[i][x+k][(y+(abs((k/2)-2)))-3]='#';
        m_Maps[i][x+k][(y+(abs((k/2)-2)-1))-3]='.';
    };
   
    x+=8;
    y+=6;
    m_Maps[i][x][y-7]='#';
    m_Maps[i][x][y-8]='.';
    m_Maps[i][x+1][y-7]='#';
    m_Maps[i][x+1][y-8]='.';
   
    m_Maps[i][x][y-1]='#';
    m_Maps[i][x][y-2]='.';
    m_Maps[i][x-1][y-4]='.';
    m_Maps[i][x+29][y+3]='#';
    m_Maps[i][x-8][y-2]='.';
    h = 3;
    x=0;
    for(j=0;j<60;j++)
    {
        if(h<0)
            h=0;
        if(h>2)
            h=2;
        if(m_Maps[i][x+j][(y-1)+(2-h)]==' ')
            m_Maps[i][x+j][(y-1)+(2-h)]='.';
        if(h==2)
        m_Maps[i][x+j][y]='#';
        if(h>0)
        m_Maps[i][x+j][y+1]='#';
        m_Maps[i][x+j][y+2]='#';
        if(rand()%4==0)
            h--;
        if(rand()%4==0)
            h++;
    };
    x=60;
    y+=1;
    h=0;
    for(j=0;j<10;j++)
    {
        if(h<0)
            h=0;
        if(h>2)
            h=2;
        m_Maps[i][x+j][(y-1)+(2-h)]='.';
        if(h==2)
            m_Maps[i][x+j][y]='#';
        if(h>0)
            m_Maps[i][x+j][y+1]='#';
        m_Maps[i][x+j][y+2]='#';
        if(rand()%4==0)
            h--;
        if(rand()%4==0)
            h++;
    };
   
    h=0;
    x=0;
    y=0;
    for(j=0;j<80;j++)
    {
        if(h<0)
            h=0;
        if(h>3)
            h=3;
        m_Maps[i][x+j][y+1]='.';
        m_Maps[i][x+j][y+h+1]='.';
        m_Maps[i][x+j][y]='#';
        m_Maps[i][x+j][y-1]='#';
        if(rand()%4==0)
            h--;
        if(rand()%4==0)
            h++;
    };
    h=0;
    x=76;
    y=0;
    for(j=0;j<25;j++)
    {
        if(h<0)
            h=0;
        if(h>2)
            h=2;
        m_Maps[i][x+h-1][y+j]='.';
        m_Maps[i][x+h-2][y+j]=' ';
        m_Maps[i][x+h][y+j]='#';
        m_Maps[i][x+h+1][y+j]='#';
        if(rand()%4==0)
            h--;
        if(rand()%4==0)
            h++;
    };
    h=0;
    x=0;
    y=22;
    for(j=0;j<80;j++)
    {
        m_Maps[i][x+j][y]='.';
        m_Maps[i][x+j][y+1]='#';
    };
};

void PlaceEnemies(int i)
{
    int j,x,y;
    CObject *o;
    for(j=0;j<30;j++)
    {
        o = new CObject(rand()%80,rand()%23,'E',"Math",true,1);
        m_Objects[i].push_back(o);
    };
    while(m_Maps[i][x][y]!='.')
    {
        x = rand()%80;
        y = rand()%23;
    };
    o = new CObject(x,y,'>',"stairs",false,2);
    o->ChangeModifier("","stairs",0);
    o->ChangeModifier("","down",1);
    m_Objects[i].push_back(o);
    x = y = 0;
    while(m_Maps[i][x][y]!='.')
    {
        x = rand()%80;
        y = rand()%23;
    };
    o = new CObject(x,y,'<',"stairs",false,2);
    o->ChangeModifier("","stairs",0);
    o->ChangeModifier("","up",1);
    m_Objects[i].push_back(o);
};
Comments