1 /* 2 * Draw the connecting passages 3 * 4 * passages.c 1.4 (A.I. Design) 12/14/84 5 */ 6 7 #include "rogue.h" 8 #include "curses.h" 9 10 /* 11 * conn: 12 * Draw a corridor from a room in a certain direction. 13 */ 14 conn(r1, r2) 15 int r1, r2; 16 { 17 struct room *rpf, *rpt; 18 register int rmt, rm; 19 int distance, turn_spot, turn_distance, index; 20 int direc; 21 coord del, curr, turn_delta, spos, epos; 22 23 if (r1 < r2) { 24 rm = r1; 25 if (r1 + 1 == r2) 26 direc = 'r'; 27 else 28 direc = 'd'; 29 } else { 30 rm = r2; 31 if (r2 + 1 == r1) 32 direc = 'r'; 33 else 34 direc = 'd'; 35 } 36 rpf = &rooms[rm]; 37 /* 38 * Set up the movement variables, in two cases: 39 * first drawing one down. 40 */ 41 if (direc == 'd') { 42 rmt = rm + 3; /* room # of dest */ 43 rpt = &rooms[rmt]; /* room pointer of dest */ 44 del.x = 0; /* direction of move */ 45 del.y = 1; 46 /* 47 * If we are drawing from/to regular or maze rooms, we have 48 * to pick the spot we draw from/to 49 */ 50 if ((rpf->r_flags & ISGONE) == 0 || (rpf->r_flags & ISMAZE)) { 51 spos.y = rpf->r_pos.y + rpf->r_max.y - 1; 52 do { 53 spos.x = rpf->r_pos.x + rnd(rpf->r_max.x - 2) + 1; 54 } while (chat(spos.y,spos.x) == ' '); 55 } else { 56 spos.x = rpf->r_pos.x; 57 spos.y = rpf->r_pos.y; 58 } 59 epos.y = rpt->r_pos.y; 60 if ((rpt->r_flags & ISGONE) == 0 || (rpt->r_flags & ISMAZE)) { 61 do { 62 epos.x = rpt->r_pos.x + rnd(rpt->r_max.x - 2) + 1; 63 } while (chat(epos.y,epos.x) == ' '); 64 } else 65 epos.x = rpt->r_pos.x; 66 distance = abs(spos.y - epos.y) - 1; /* distance to move */ 67 turn_delta.y = 0; /* direction to turn */ 68 turn_delta.x = (spos.x < epos.x ? 1 : -1); 69 turn_distance = abs(spos.x - epos.x); /* how far to turn */ 70 } else if (direc == 'r') { /* setup for moving right */ 71 rmt = rm + 1; 72 rpt = &rooms[rmt]; 73 del.x = 1; 74 del.y = 0; 75 if ((rpf->r_flags & ISGONE) == 0 || (rpf->r_flags & ISMAZE)) { 76 spos.x = rpf->r_pos.x + rpf->r_max.x-1; 77 do { 78 spos.y = rpf->r_pos.y + rnd(rpf->r_max.y-2)+1; 79 } while (chat(spos.y,spos.x) == ' '); 80 } else { 81 spos.x = rpf->r_pos.x; 82 spos.y = rpf->r_pos.y; 83 } 84 epos.x = rpt->r_pos.x; 85 if ((rpt->r_flags & ISGONE) == 0 || (rpt->r_flags & ISMAZE)) { 86 do { 87 epos.y = rpt->r_pos.y + rnd(rpt->r_max.y-2)+1; 88 } while (chat(epos.y, epos.x) == ' '); 89 } else 90 epos.y = rpt->r_pos.y; 91 distance = abs(spos.x - epos.x) - 1; 92 turn_delta.y = (spos.y < epos.y ? 1 : -1); 93 turn_delta.x = 0; 94 turn_distance = abs(spos.y - epos.y); 95 } 96 #ifdef DEBUG 97 else 98 debug("error in connection tables"); 99 #endif 100 turn_spot = rnd(distance-1) + 1; 101 /* 102 * Draw in the doors on either side of the passage or just put #'s 103 * if the rooms are gone. 104 */ 105 if (!(rpf->r_flags & ISGONE)) 106 door(rpf, &spos); 107 else 108 psplat(spos.y, spos.x); 109 if (!(rpt->r_flags & ISGONE)) 110 door(rpt, &epos); 111 else 112 psplat(epos.y, epos.x); 113 /* 114 * Get ready to move... 115 */ 116 curr.x = spos.x; 117 curr.y = spos.y; 118 while (distance) 119 { 120 /* 121 * Move to new position 122 */ 123 curr.x += del.x; 124 curr.y += del.y; 125 /* 126 * Check if we are at the turn place, if so do the turn 127 */ 128 if (distance == turn_spot) 129 { 130 while (turn_distance--) 131 { 132 psplat(curr.y, curr.x); 133 curr.x += turn_delta.x; 134 curr.y += turn_delta.y; 135 } 136 } 137 /* 138 * Continue digging along 139 */ 140 psplat(curr.y, curr.x); 141 distance--; 142 } 143 curr.x += del.x; 144 curr.y += del.y; 145 if (!ce(curr, epos)) { 146 epos.x -= del.x; 147 epos.y -= del.y; 148 psplat(epos.y, epos.x); 149 } 150 } 151 152 /* 153 * do_passages: 154 * Draw all the passages on a level. 155 */ 156 do_passages() 157 { 158 register int i, j; 159 int roomcount; 160 static struct rdes 161 { 162 char conn[MAXROOMS]; /* possible to connect to room i? */ 163 char isconn[MAXROOMS]; /* connection been made to room i? */ 164 char ingraph; /* this room in graph already? */ 165 } rdes[MAXROOMS] = { 166 { { 0, 1, 0, 1, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 }, 167 { { 1, 0, 1, 0, 1, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 }, 168 { { 0, 1, 0, 0, 0, 1, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 }, 169 { { 1, 0, 0, 0, 1, 0, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 }, 170 { { 0, 1, 0, 1, 0, 1, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 }, 171 { { 0, 0, 1, 0, 1, 0, 0, 0, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 }, 172 { { 0, 0, 0, 1, 0, 0, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 }, 173 { { 0, 0, 0, 0, 1, 0, 1, 0, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 }, 174 { { 0, 0, 0, 0, 0, 1, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 } 175 }; 176 struct rdes *r1, *r2; 177 178 /* 179 * reinitialize room graph description 180 */ 181 for (r1 = rdes; r1 < &rdes[MAXROOMS]; r1++) 182 { 183 for (j = 0; j < MAXROOMS; j++) 184 r1->isconn[j] = FALSE; 185 r1->ingraph = FALSE; 186 } 187 188 /* 189 * starting with one room, connect it to a random adjacent room and 190 * then pick a new room to start with. 191 */ 192 roomcount = 1; 193 r1 = &rdes[rnd(MAXROOMS)]; 194 r1->ingraph = TRUE; 195 do 196 { 197 /* 198 * find a room to connect with 199 */ 200 j = 0; 201 for (i = 0; i < MAXROOMS; i++) 202 if (r1->conn[i] && !rdes[i].ingraph && rnd(++j) == 0) 203 r2 = &rdes[i]; 204 /* 205 * if no adjacent rooms are outside the graph, pick a new room 206 * to look from 207 */ 208 if (j == 0) 209 { 210 do 211 r1 = &rdes[rnd(MAXROOMS)]; 212 while (!r1->ingraph); 213 } 214 /* 215 * otherwise, connect new room to the graph, and draw a tunnel 216 * to it 217 */ 218 else 219 { 220 r2->ingraph = TRUE; 221 i = r1 - rdes; 222 j = r2 - rdes; 223 conn(i, j); 224 r1->isconn[j] = TRUE; 225 r2->isconn[i] = TRUE; 226 roomcount++; 227 } 228 } while (roomcount < MAXROOMS); 229 230 /* 231 * attempt to add passages to the graph a random number of times so 232 * that there isn't always just one unique passage through it. 233 */ 234 for (roomcount = rnd(5); roomcount > 0; roomcount--) 235 { 236 r1 = &rdes[rnd(MAXROOMS)]; /* a random room to look from */ 237 /* 238 * find an adjacent room not already connected 239 */ 240 j = 0; 241 for (i = 0; i < MAXROOMS; i++) 242 if (r1->conn[i] && !r1->isconn[i] && rnd(++j) == 0) 243 r2 = &rdes[i]; 244 /* 245 * if there is one, connect it and look for the next added 246 * passage 247 */ 248 if (j != 0) 249 { 250 i = r1 - rdes; 251 j = r2 - rdes; 252 conn(i, j); 253 r1->isconn[j] = TRUE; 254 r2->isconn[i] = TRUE; 255 } 256 } 257 passnum(); 258 } 259 260 261 /* 262 * door: 263 * Add a door or possibly a secret door. Also enters the door in 264 * the exits array of the room. 265 */ 266 door(rm, cp) 267 struct room *rm; 268 coord *cp; 269 { 270 register int index, xit; 271 272 index = INDEX(cp->y, cp->x); 273 if (rnd(10) + 1 < level && rnd(5) == 0) 274 { 275 _level[index] = (cp->y == rm->r_pos.y || cp->y == rm->r_pos.y + rm->r_max.y - 1) ? HWALL : VWALL; 276 _flags[index] &= ~F_REAL; 277 } 278 else 279 _level[index] = DOOR; 280 xit = rm->r_nexits++; 281 rm->r_exit[xit].y = cp->y; 282 rm->r_exit[xit].x = cp->x; 283 } 284 285 #ifdef WIZARD 286 /* 287 * add_pass: 288 * Add the passages to the current window (wizard command) 289 */ 290 add_pass() 291 { 292 register int y, x, ch; 293 294 for (y = 1; y < maxrow; y++) 295 for (x = 0; x < COLS; x++) 296 if ((ch = chat(y, x)) == DOOR || ch == PASSAGE) 297 mvaddch(y, x, ch); 298 } 299 #endif 300 301 /* 302 * passnum: 303 * Assign a number to each passageway 304 */ 305 static int pnum; 306 static byte newpnum; 307 308 passnum() 309 { 310 register struct room *rp; 311 register int i; 312 313 pnum = 0; 314 newpnum = FALSE; 315 for (rp = passages; rp < &passages[MAXPASS]; rp++) 316 rp->r_nexits = 0; 317 for (rp = rooms; rp < &rooms[MAXROOMS]; rp++) 318 for (i = 0; i < rp->r_nexits; i++) 319 { 320 newpnum++; 321 numpass(rp->r_exit[i].y, rp->r_exit[i].x); 322 } 323 } 324 /* 325 * numpass: 326 * Number a passageway square and its brethren 327 */ 328 numpass(y, x) 329 int y, x; 330 { 331 register byte *fp; 332 register struct room *rp; 333 register byte ch; 334 335 if (offmap(y,x)) 336 return; 337 fp = &flat(y, x); 338 if (*fp & F_PNUM) 339 return; 340 if (newpnum) { 341 pnum++; 342 newpnum = FALSE; 343 } 344 /* 345 * check to see if it is a door or secret door, i.e., a new exit, 346 * or a numerable type of place 347 */ 348 if ((ch = chat(y, x)) == DOOR || (!(*fp & F_REAL) && ch != FLOOR)) { 349 rp = &passages[pnum]; 350 rp->r_exit[rp->r_nexits].y = y; 351 rp->r_exit[rp->r_nexits++].x = x; 352 } else if (!(*fp & F_PASS)) 353 return; 354 *fp |= pnum; 355 /* 356 * recurse on the surrounding places 357 */ 358 numpass(y + 1, x); 359 numpass(y - 1, x); 360 numpass(y, x + 1); 361 numpass(y, x - 1); 362 } 363 364 psplat(y, x) 365 shint y, x; 366 { 367 register int idx; 368 369 _level[idx = INDEX(y, x)] = PASSAGE; 370 _flags[idx] |= F_PASS; 371 } 372 ÿ