⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dungeongenerator.cpp

📁 S.C.O.U.R.G.E.是一款类似Rogue的游戏
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/***************************************************************************                          dungeongenerator.cpp  -  description                             -------------------    begin                : Thu May 15 2003    copyright            : (C) 2003 by Gabor Torok    email                : cctorok@yahoo.com ***************************************************************************//*************************************************************************** *                                                                         * *   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.                                   * *                                                                         * ***************************************************************************/#include "dungeongenerator.h"/*width - max 31height - max 31curvyness - in %, the lower the more twisty mazesparseness - (1-5) the higher the more sparse (more empty space)loopyness - in %, the higher the more loops in the mazeroomcountrooom max widthroom max heightobject count*/const int DungeonGenerator::levels[][9] = {  { 10, 20,  90, 5,  1,    2,  4,  4,      5 },    { 15, 15,  70, 5, 10,    3,  6,  4,     10 },  { 15, 15,  50, 4, 20,    4,  5,  5,     15 },  { 20, 20,  50, 6, 20,    5,  6,  5,     20 },  { 25, 25,  40, 6, 20,    5,  6,  5,     25 },  { 30, 25,   5, 6, 25,    6,  6,  6,     30 },          { 31, 31,   3, 5, 25,    6,  7,  7,     35 }};/**   Pre-generated maps:   x,y,w,h,   starting coord   roomCount,   roomDimensions: x,y,w,h,furnish(0,1)   map: #-room, +-floor, nsew-doors (by facing) */const MapLocation DungeonGenerator::location[] = {  { 	0,0,5,12,	{ 		{2*unitSide+16, unitSide+6}, 	  {2*unitSide+13, unitSide+9}, 		{2*unitSide+19, unitSide+9}, 		{2*unitSide+16, unitSide+12} 	},	false,	5,	{	  {0,0,5,4,0},	  {0,5,2,3,1}, 	  {3,5,2,3,1}, 	  {0,9,2,3,1}, 	  {3,9,2,3,1}	},	{ 	  "  ## ",	  "  ## ",	  "  ## ",	  "  s# ",	  "  +  ",	  "##+##",	  "#e+w#",	  "s# #s",	  "+   +",	  "n# #n",	  "#e+w#",	  "## ##" 	},	25, 	{	  { "BOARD", 2*unitSide+11, unitSide + 1, 0 },		{ "COLUMN", 2*unitSide+3, unitSide, 0 },		{ "COLUMN", 2*unitSide+26, unitSide, 0 },		{ "COLUMN", 2*unitSide+3, unitSide+8, 0 },		{ "COLUMN", 2*unitSide+26, unitSide+8, 0 },		{ "COLUMN", 2*unitSide+3, unitSide+16, 0 },		{ "COLUMN", 2*unitSide+26, unitSide+16, 0 },		{ "COLUMN", 2*unitSide+3, unitSide+24, 0 },		{ "COLUMN", 2*unitSide+26, unitSide+24, 0 },		{ "COLUMN", 2*unitSide+3, unitSide+32, 0 },		{ "COLUMN", 2*unitSide+26, unitSide+32, 0 },		{ "COLUMN", 2*unitSide+3, unitSide+40, 0 },		{ "COLUMN", 2*unitSide+26, unitSide+40, 0 },	  { "BRAZIER", 2*unitSide+7, unitSide+8, 2 },	  { "BRAZIER_BASE", 2*unitSide+7, unitSide+8, 0 },			  { "BRAZIER", 2*unitSide+22, unitSide+8, 2 },	  { "BRAZIER_BASE", 2*unitSide+22, unitSide+8, 0 },	  { "BRAZIER", 2*unitSide+7, unitSide+16, 2 },	  { "BRAZIER_BASE", 2*unitSide+7, unitSide+16, 0 },	  { "BRAZIER", 2*unitSide+22, unitSide+16, 2 },	  { "BRAZIER_BASE", 2*unitSide+22, unitSide+16, 0 },	  { "BRAZIER", 2*unitSide+7, unitSide+24, 2 },	  { "BRAZIER_BASE", 2*unitSide+7, unitSide+24, 0 },	  { "BRAZIER", 2*unitSide+22, unitSide+24, 2 },	  { "BRAZIER_BASE", 2*unitSide+22, unitSide+24, 0 }	}  }};DungeonGenerator::DungeonGenerator(Scourge *scourge, int level, bool stairsDown, 								   bool stairsUp, Mission *mission){  this->scourge = scourge;  this->level = level;  this->stairsUp = stairsUp;  this->stairsDown = stairsDown;  this->mission = mission;  this->status = 0;  initByLevel();      this->nodes = (Uint16**)malloc(sizeof(void*) * width);  for(int i = 0; i < width; i++) {    nodes[i] = (Uint16*)malloc(sizeof(void*) * height);  }  for(int x = 0; x < width; x++) {    for(int y = 0; y < height; y++) {      nodes[x][y] = UNVISITED;    }  }    notVisitedCount = width * height;  notVisited = (int*)new int[notVisitedCount];    for(int i = 0; i < notVisitedCount; i++) {    notVisited[i] = i;  }  visitedCount = 0;  visited = (int*)new int[notVisitedCount];}DungeonGenerator::~DungeonGenerator(){  for(int i = 0; i < width; i++) {    free(nodes[i]);  }  free(nodes);  delete[] notVisited;  delete[] visited;}void DungeonGenerator::initByLevel() {  if(level < 1) level = 1;    this->width = levels[level - 1][dgWIDTH];  this->height = levels[level - 1][dgHEIGHT];  this->curvyness = levels[level - 1][dgCURVYNESS];  this->sparseness = levels[level - 1][dgSPARSENESS];  this->loopyness = levels[level - 1][dgLOOPYNESS];  this->roomCount = levels[level - 1][dgROOMCOUNT];  this->roomMaxWidth = levels[level - 1][dgROOMMAXWIDTH];  this->roomMaxHeight = levels[level - 1][dgROOMMAXHEIGHT];  this->objectCount = levels[level - 1][dgOBJECTCOUNT];  this->monsters = true;}void DungeonGenerator::makeRooms() {  int rw, rh, px, py;  int best, score;  for(int i = 0; i < roomCount; i++) {    // create a room    rw = (int) ((double)(roomMaxWidth / 2) * rand()/RAND_MAX) + (roomMaxWidth / 2);    rh = (int) ((double)(roomMaxHeight / 2) * rand()/RAND_MAX) + (roomMaxHeight / 2);    best = -1;    px = py = -1;    // find best place for this room    if(i % 2) {      for(int x = 0; x < width - rw; x++) {        for(int y = 0; y < height - rh; y++) {          score = getScore(x, y, rw, rh);          if(score > 0 && (best == -1 || score < best)) {            best = score;            px = x;            py = y;          }        }      }    } else {      for(int x = width - rw - 1; x >= 0; x--) {        for(int y = height - rh - 1; y >= 0; y--) {          score = getScore(x, y, rw, rh);          if(score > 0 && (best == -1 || score < best)) {            best = score;            px = x;            py = y;          }        }              }    }    // set the room    if(px > -1 && py > -1) {	  // save the room info	  room[i].x = px;	  room[i].y = py;	  room[i].w = rw;	  room[i].h = rh;      for(int x = px; x < px + rw; x++) {        for(int y = py; y < py + rh; y++) {          nodes[x][y] = ROOM + N_PASS + S_PASS + E_PASS + W_PASS;          // 1. connect the room to the passage          // 2. put in some doors: after each door, the chance of there being          //    another door decreases.          // 3. put in the walls          if(x == px) {            if(x > 0 && nodes[x - 1][y] != UNVISITED) {              nodes[x - 1][y] |= E_PASS;            } else {              nodes[x][y] -= W_PASS;            }          }          if(x == px + rw - 1) {            if(x < width - 1 && nodes[x + 1][y] != UNVISITED) {              nodes[x + 1][y] |= W_PASS;            } else {              nodes[x][y] -= E_PASS;            }          }          if(y == py) {            if(y > 0 && nodes[x][y - 1] != UNVISITED) {              nodes[x][y - 1] |= S_PASS;            } else {              nodes[x][y] -= N_PASS;            }          }          if(y == py + rh - 1) {            if(y < height - 1 && nodes[x][y + 1] != UNVISITED) {              nodes[x][y + 1] |= N_PASS;            } else {              nodes[x][y] -= S_PASS;            }          }        }      }      // add doors      for(int x = px; x < px + rw; x++) {        for(int y = py; y < py + rh; y++) {          if(x == px) {            if(x > 0 && nodes[x - 1][y] != UNVISITED && nodes[x - 1][y] < ROOM) {							nodes[x][y] |= W_DOOR;            }          }          if(x == px + rw - 1) {            if(x < width - 1 && nodes[x + 1][y] != UNVISITED && nodes[x + 1][y] < ROOM) {							nodes[x][y] |= E_DOOR;            }          }          if(y == py) {            if(y > 0 && nodes[x][y - 1] != UNVISITED && nodes[x][y - 1] < ROOM) {							nodes[x][y] |= N_DOOR;            }          }          if(y == py + rh - 1) {            if(y < height - 1 && nodes[x][y + 1] != UNVISITED && nodes[x][y + 1] < ROOM) {							nodes[x][y] |= S_DOOR;            }          }                  }      }    }      }}int DungeonGenerator::getScore(int px, int py, int rw, int rh) {  int score = 0;  for(int x = px; x < px + rw; x++) {    for(int y = py; y < py + rh; y++) {      if(nodes[x][y] == UNVISITED) {        if(x < width - 1 && nodes[x + 1][y] != UNVISITED) score++;        if(x > 0 && nodes[x - 1][y] != UNVISITED) score++;        if(y < height - 1 && nodes[x][y + 1] != UNVISITED) score++;        if(y > 0 && nodes[x][y - 1] != UNVISITED) score++;        if(x < width - 1 && nodes[x + 1][y] >= ROOM) score+=100;        if(x > 0 && nodes[x - 1][y] >= ROOM) score+=100;        if(y < height - 1 && nodes[x][y + 1] >= ROOM) score+=100;        if(y > 0 && nodes[x][y - 1] >= ROOM) score+=100;              } else if(nodes[x][y] >= ROOM) {          score += 100;      } else {          score += 3;      }    }  }  return score;}void DungeonGenerator::makeLoops() {  for(int i = 0; i < sparseness; i++) {    for(int x = 0; x < width; x++) {      for(int y = 0; y < height; y++) {                switch(nodes[x][y]) {          case N_PASS:          case S_PASS:          case E_PASS:          case W_PASS:            if((int) (100.0 * rand()/RAND_MAX) <= loopyness)            generatePassage(x, y, false);            break;          default:            break;        }      }    }  } }void DungeonGenerator::makeSparse() {  for(int i = 0; i < sparseness; i++) {    for(int x = 0; x < width; x++) {      for(int y = 0; y < height; y++) {        switch(nodes[x][y]) {          case N_PASS:            nodes[x][y] = UNVISITED;            if(y > 0) {			  nodes[x][y - 1] -= S_PASS;			}            break;          case S_PASS:            nodes[x][y] = UNVISITED;            if(y < height - 1) {			  nodes[x][y + 1] -= N_PASS;			}            break;          case E_PASS:            nodes[x][y] = UNVISITED;            if(x < width - 1) {			  nodes[x + 1][y] -= W_PASS;			}            break;          case W_PASS:            nodes[x][y] = UNVISITED;            if(x > 0) {			  nodes[x - 1][y] -= E_PASS;			}            break;          default:            break;        }      }    }  }}void DungeonGenerator::generateMaze() {  int x, y;  //fprintf(stderr, "Starting maze w=%d h=%d\n", width, height);  nextNotVisited(&x, &y);  while(notVisitedCount > 0) {    // draw the passage    generatePassage(x, y, true);    // select a starting point    nextVisited(&x, &y);    if(x == -1) break;  }}void DungeonGenerator::generatePassage(const int sx, const int sy, const bool stopAtVisited) {  //char line[80];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -