#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); }; |