Mercurial > hg > early-roguelike
comparison urogue/passages.c @ 256:c495a4f288c6
Import UltraRogue from the Roguelike Restoration Project (r1490)
| author | John "Elwin" Edwards |
|---|---|
| date | Tue, 31 Jan 2017 19:56:04 -0500 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 253:d9badb9c0179 | 256:c495a4f288c6 |
|---|---|
| 1 /* | |
| 2 passages.c - Draw the connecting passages | |
| 3 | |
| 4 UltraRogue: The Ultimate Adventure in the Dungeons of Doom | |
| 5 Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong | |
| 6 All rights reserved. | |
| 7 | |
| 8 Based on "Advanced Rogue" | |
| 9 Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka | |
| 10 All rights reserved. | |
| 11 | |
| 12 Based on "Rogue: Exploring the Dungeons of Doom" | |
| 13 Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman | |
| 14 All rights reserved. | |
| 15 | |
| 16 See the file LICENSE.TXT for full copyright and licensing information. | |
| 17 */ | |
| 18 | |
| 19 #include <stdlib.h> | |
| 20 #include "rogue.h" | |
| 21 | |
| 22 #define cmov(xy) move((xy).y, (xy).x) | |
| 23 | |
| 24 /* | |
| 25 do_passages() | |
| 26 Draw all the passages on a level. | |
| 27 */ | |
| 28 | |
| 29 void | |
| 30 do_passages(void) | |
| 31 { | |
| 32 struct rdes *r1, *r2 = NULL; | |
| 33 int i, j; | |
| 34 int roomcount; | |
| 35 | |
| 36 static struct rdes rdes[MAXROOMS] = | |
| 37 { | |
| 38 {{ 0, 1, 0, 1, 0, 0, 0, 0, 0}, | |
| 39 { 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0}, | |
| 40 {{ 1, 0, 1, 0, 1, 0, 0, 0, 0}, | |
| 41 { 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0}, | |
| 42 {{ 0, 1, 0, 0, 0, 1, 0, 0, 0}, | |
| 43 { 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0}, | |
| 44 {{ 1, 0, 0, 0, 1, 0, 1, 0, 0}, | |
| 45 { 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0}, | |
| 46 {{ 0, 1, 0, 1, 0, 1, 0, 1, 0}, | |
| 47 { 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0}, | |
| 48 {{ 0, 0, 1, 0, 1, 0, 0, 0, 1}, | |
| 49 { 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0}, | |
| 50 {{ 0, 0, 0, 1, 0, 0, 0, 1, 0}, | |
| 51 { 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0}, | |
| 52 {{ 0, 0, 0, 0, 1, 0, 1, 0, 1}, | |
| 53 { 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0}, | |
| 54 {{ 0, 0, 0, 0, 0, 1, 0, 1, 0}, | |
| 55 { 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0} | |
| 56 }; | |
| 57 | |
| 58 /* reinitialize room graph description */ | |
| 59 | |
| 60 for (r1 = rdes; r1 < &rdes[MAXROOMS]; r1++) | |
| 61 { | |
| 62 for (j = 0; j < MAXROOMS; j++) | |
| 63 r1->isconn[j] = FALSE; | |
| 64 | |
| 65 r1->ingraph = FALSE; | |
| 66 } | |
| 67 | |
| 68 /* | |
| 69 * starting with one room, connect it to a random adjacent room and | |
| 70 * then pick a new room to start with. | |
| 71 */ | |
| 72 | |
| 73 roomcount = 1; | |
| 74 r1 = &rdes[rnd(MAXROOMS)]; | |
| 75 r1->ingraph = TRUE; | |
| 76 | |
| 77 do | |
| 78 { | |
| 79 j = 0; | |
| 80 | |
| 81 for (i = 0; i < MAXROOMS; i++) | |
| 82 if (r1->conn[i] && !rdes[i].ingraph && rnd(++j) == 0) | |
| 83 r2 = &rdes[i]; | |
| 84 | |
| 85 /* | |
| 86 * if no adjacent rooms are outside the graph, pick a new | |
| 87 * room to look from | |
| 88 */ | |
| 89 | |
| 90 if (j == 0) | |
| 91 do | |
| 92 { | |
| 93 r1 = &rdes[rnd(MAXROOMS)]; | |
| 94 } | |
| 95 while (!r1->ingraph); | |
| 96 | |
| 97 /* | |
| 98 * otherwise, connect new room to the graph, and draw a | |
| 99 * tunnel to it | |
| 100 */ | |
| 101 else | |
| 102 { | |
| 103 r2->ingraph = TRUE; | |
| 104 i = (int)(r1 - rdes); | |
| 105 j = (int)(r2 - rdes); | |
| 106 conn(i, j); | |
| 107 r1->isconn[j] = TRUE; | |
| 108 r2->isconn[i] = TRUE; | |
| 109 roomcount++; | |
| 110 } | |
| 111 } | |
| 112 while (roomcount < MAXROOMS); | |
| 113 | |
| 114 /* | |
| 115 * attempt to add passages to the graph a random number of times so | |
| 116 * that there isn't just one unique passage through it. | |
| 117 */ | |
| 118 | |
| 119 for (roomcount = rnd(5); roomcount > 0; roomcount--) | |
| 120 { | |
| 121 r1 = &rdes[rnd(MAXROOMS)]; /* a random room to look from */ | |
| 122 | |
| 123 /* | |
| 124 * find an adjacent room not already connected | |
| 125 */ | |
| 126 | |
| 127 j = 0; | |
| 128 for (i = 0; i < MAXROOMS; i++) | |
| 129 if (r1->conn[i] && !r1->isconn[i] && rnd(++j) == 0) | |
| 130 r2 = &rdes[i]; | |
| 131 | |
| 132 /* | |
| 133 * if there is one, connect it and look for the next added | |
| 134 * passage | |
| 135 */ | |
| 136 | |
| 137 if (j != 0) | |
| 138 { | |
| 139 i = (int)(r1 - rdes); | |
| 140 j = (int)(r2 - rdes); | |
| 141 conn(i, j); | |
| 142 r1->isconn[j] = TRUE; | |
| 143 r2->isconn[i] = TRUE; | |
| 144 } | |
| 145 } | |
| 146 } | |
| 147 | |
| 148 /* | |
| 149 conn() | |
| 150 Draw a corridor from a room in a certain direction. | |
| 151 */ | |
| 152 | |
| 153 void | |
| 154 conn(int r1, int r2) | |
| 155 { | |
| 156 struct room *rpf, *rpt = NULL; | |
| 157 int rmt; | |
| 158 int distance = 0, turn_spot = 0, turn_distance = 0; | |
| 159 int rm; | |
| 160 char direc; | |
| 161 coord delt = {0,0}, curr, turn_delta = {0,0}, spos = {0,0}, epos = {0,0}; | |
| 162 | |
| 163 if (r1 < r2) | |
| 164 { | |
| 165 rm = r1; | |
| 166 | |
| 167 if (r1 + 1 == r2) | |
| 168 direc = 'r'; | |
| 169 else | |
| 170 direc = 'd'; | |
| 171 } | |
| 172 else | |
| 173 { | |
| 174 rm = r2; | |
| 175 | |
| 176 if (r2 + 1 == r1) | |
| 177 direc = 'r'; | |
| 178 else | |
| 179 direc = 'd'; | |
| 180 } | |
| 181 | |
| 182 rpf = &rooms[rm]; | |
| 183 | |
| 184 /* | |
| 185 * Set up the movement variables, in two cases: first drawing one | |
| 186 * down. | |
| 187 */ | |
| 188 | |
| 189 if (direc == 'd') | |
| 190 { | |
| 191 rmt = rm + 3; /* room # of dest */ | |
| 192 rpt = &rooms[rmt]; /* room pointer of dest */ | |
| 193 delt.x = 0; /* direction of move */ | |
| 194 delt.y = 1; | |
| 195 spos.x = rpf->r_pos.x; /* start of move */ | |
| 196 spos.y = rpf->r_pos.y; | |
| 197 epos.x = rpt->r_pos.x; /* end of move */ | |
| 198 epos.y = rpt->r_pos.y; | |
| 199 | |
| 200 if (!(rpf->r_flags & ISGONE)) /* if not gone pick door pos */ | |
| 201 { | |
| 202 spos.x += rnd(rpf->r_max.x - 2) + 1; | |
| 203 spos.y += rpf->r_max.y - 1; | |
| 204 } | |
| 205 | |
| 206 if (!(rpt->r_flags & ISGONE)) | |
| 207 epos.x += rnd(rpt->r_max.x - 2) + 1; | |
| 208 | |
| 209 distance = abs(spos.y - epos.y) - 1; /* distance to move */ | |
| 210 turn_delta.y = 0; /* direction to turn */ | |
| 211 turn_delta.x = (spos.x < epos.x ? 1 : -1); | |
| 212 turn_distance = abs(spos.x - epos.x); /* how far to turn */ | |
| 213 turn_spot = rnd(distance - 1) + 1; /* where turn starts */ | |
| 214 } | |
| 215 else if (direc == 'r') /* setup for moving right */ | |
| 216 { | |
| 217 rmt = rm + 1; | |
| 218 rpt = &rooms[rmt]; | |
| 219 delt.x = 1; | |
| 220 delt.y = 0; | |
| 221 spos.x = rpf->r_pos.x; | |
| 222 spos.y = rpf->r_pos.y; | |
| 223 epos.x = rpt->r_pos.x; | |
| 224 epos.y = rpt->r_pos.y; | |
| 225 | |
| 226 if (!(rpf->r_flags & ISGONE)) | |
| 227 { | |
| 228 spos.x += rpf->r_max.x - 1; | |
| 229 spos.y += rnd(rpf->r_max.y - 2) + 1; | |
| 230 } | |
| 231 | |
| 232 if (!(rpt->r_flags & ISGONE)) | |
| 233 epos.y += rnd(rpt->r_max.y - 2) + 1; | |
| 234 | |
| 235 distance = abs(spos.x - epos.x) - 1; | |
| 236 turn_delta.y = (spos.y < epos.y ? 1 : -1); | |
| 237 turn_delta.x = 0; | |
| 238 turn_distance = abs(spos.y - epos.y); | |
| 239 turn_spot = rnd(distance - 1) + 1; | |
| 240 } | |
| 241 else | |
| 242 debug("Error in connection tables."); | |
| 243 | |
| 244 /* | |
| 245 * Draw in the doors on either side of the passage or just put #'s if | |
| 246 * the rooms are gone. | |
| 247 */ | |
| 248 | |
| 249 if (!(rpf->r_flags & ISGONE)) | |
| 250 door(rpf, &spos); | |
| 251 else | |
| 252 { | |
| 253 cmov(spos); | |
| 254 addch('#'); | |
| 255 } | |
| 256 | |
| 257 if (!(rpt->r_flags & ISGONE)) | |
| 258 door(rpt, &epos); | |
| 259 else | |
| 260 { | |
| 261 cmov(epos); | |
| 262 addch('#'); | |
| 263 } | |
| 264 | |
| 265 /* Get ready to move... */ | |
| 266 | |
| 267 curr.x = spos.x; | |
| 268 curr.y = spos.y; | |
| 269 | |
| 270 while (distance) | |
| 271 { | |
| 272 /* Move to new position */ | |
| 273 | |
| 274 curr.x += delt.x; | |
| 275 curr.y += delt.y; | |
| 276 | |
| 277 /* Check if we are at the turn place, if so do the turn */ | |
| 278 | |
| 279 if (distance == turn_spot && turn_distance > 0) | |
| 280 while (turn_distance--) | |
| 281 { | |
| 282 cmov(curr); | |
| 283 addch(PASSAGE); | |
| 284 curr.x += turn_delta.x; | |
| 285 curr.y += turn_delta.y; | |
| 286 } | |
| 287 | |
| 288 /* Continue digging along */ | |
| 289 | |
| 290 cmov(curr); | |
| 291 addch(PASSAGE); | |
| 292 distance--; | |
| 293 } | |
| 294 | |
| 295 curr.x += delt.x; | |
| 296 curr.y += delt.y; | |
| 297 | |
| 298 if (!ce(curr, epos)) | |
| 299 msg("Warning, connectivity problem on this level."); | |
| 300 } | |
| 301 | |
| 302 /* | |
| 303 door() | |
| 304 Add a door or possibly a secret door also enters the door in the exits | |
| 305 array of the room. | |
| 306 */ | |
| 307 | |
| 308 void | |
| 309 door(struct room *rm, coord *cp) | |
| 310 { | |
| 311 char a_door; | |
| 312 | |
| 313 cmov(*cp); | |
| 314 | |
| 315 a_door = (rnd(10)<level - 1 && rnd(100) < 20) ? SECRETDOOR : DOOR; | |
| 316 | |
| 317 addch(a_door); | |
| 318 | |
| 319 rm->r_exit[rm->r_nexits++] = *cp; | |
| 320 } |
