diff --git a/src/rect.c b/src/rect.c new file mode 100644 index 000000000..a967ca852 --- /dev/null +++ b/src/rect.c @@ -0,0 +1,194 @@ +/* SCCS Id: @(#)rect.c 3.3 90/02/22 */ +/* Copyright (c) 1990 by Jean-Christophe Collet */ +/* NetHack may be freely redistributed. See license for details. */ + +#include "hack.h" + +int FDECL(get_rect_ind, (NhRect *)); + +static boolean FDECL(intersect, (NhRect *,NhRect *,NhRect *)); + + /* + * In this file, we will handle the various rectangle functions we + * need for room generation. + */ + +#define MAXRECT 50 +#define XLIM 4 +#define YLIM 3 + +static NhRect rect[MAXRECT+1]; +static int rect_cnt; + +/* + * Initialisation of internal structures. Should be called for every + * new level to be build... + */ + +void +init_rect() +{ + rect_cnt = 1; + rect[0].lx = rect[0].ly = 0; + rect[0].hx = COLNO - 1; + rect[0].hy = ROWNO - 1; +} + +/* + * Search Index of one precise NhRect. + * + */ + +int +get_rect_ind(r) +NhRect *r; +{ + register NhRect *rectp; + register int lx, ly, hx, hy; + register int i; + + lx = r->lx; ly = r->ly; + hx = r->hx; hy = r->hy; + for (i=0,rectp = &rect[0];ilx && ly == rectp->ly && + hx == rectp->hx && hy == rectp->hy) + return i; + return -1; +} + +/* + * Search a free rectangle that include the one given in arg + */ + +NhRect * +get_rect(r) +NhRect *r; +{ + register NhRect *rectp; + register int lx, ly, hx, hy; + register int i; + + lx = r->lx; ly = r->ly; + hx = r->hx; hy = r->hy; + for (i=0,rectp = &rect[0];i= rectp->lx && ly >= rectp->ly && + hx <= rectp->hx && hy <= rectp->hy) + return rectp; + return 0; +} + +/* + * Get some random NhRect from the list. + */ + +NhRect * +rnd_rect() +{ + return rect_cnt > 0 ? &rect[rn2(rect_cnt)] : 0; +} + +/* + * Search intersection between two rectangles (r1 & r2). + * return TRUE if intersection exist and put it in r3. + * otherwise returns FALSE + */ + +static boolean +intersect(r1, r2, r3) +NhRect *r1, *r2, *r3; +{ + if (r2->lx > r1->hx || r2->ly > r1->hy || + r2->hx < r1->lx || r2->hy < r1->ly) + return FALSE; + + r3->lx = (r2->lx > r1->lx ? r2->lx : r1->lx); + r3->ly = (r2->ly > r1->ly ? r2->ly : r1->ly); + r3->hx = (r2->hx > r1->hx ? r1->hx : r2->hx); + r3->hy = (r2->hy > r1->hy ? r1->hy : r2->hy); + + if (r3->lx > r3->hx || r3->ly > r3->hy) + return FALSE; + return TRUE; +} + +/* + * Remove a rectangle from the list of free NhRect. + */ + +void +remove_rect(r) +NhRect *r; +{ + int ind; + + ind = get_rect_ind(r); + if ( ind >=0 ) + rect[ind] = rect[--rect_cnt]; +} + +/* + * Add a NhRect to the list. + */ + +void +add_rect(r) +NhRect *r; +{ + if (rect_cnt >= MAXRECT) { +#ifdef WIZARD + if (wizard) pline("MAXRECT may be too small."); +#endif + return; + } + /* Check that this NhRect is not included in another one */ + if (get_rect(r)) + return; + rect[rect_cnt] = *r; + rect_cnt++; +} + +/* + * Okay, here we have two rectangles (r1 & r2). + * r1 was already in the list and r2 is included in r1. + * What we want is to allocate r2, that is split r1 into smaller rectangles + * then remove it. + */ + +void +split_rects(r1, r2) +NhRect *r1, *r2; +{ + NhRect r, old_r; + int i; + + old_r = *r1; + remove_rect(r1); + + /* Walk down since rect_cnt & rect[] will change... */ + for (i=rect_cnt-1; i>=0; i--) + if (intersect(&rect[i], r2, &r)) + split_rects(&rect[i], &r); + + if (r2->ly - old_r.ly-1 > (old_r.hy < ROWNO - 1 ? 2*YLIM : YLIM+1)+4) { + r = old_r; + r.hy = r2->ly - 2; + add_rect(&r); + } + if (r2->lx - old_r.lx-1 > (old_r.hx < COLNO - 1 ? 2*XLIM : XLIM+1)+4) { + r = old_r; + r.hx = r2->lx - 2; + add_rect(&r); + } + if (old_r.hy - r2->hy-1 > (old_r.ly > 0 ? 2*YLIM : YLIM+1)+4) { + r = old_r; + r.ly = r2->hy + 2; + add_rect(&r); + } + if (old_r.hx - r2->hx-1 > (old_r.lx > 0 ? 2*XLIM : XLIM+1)+4) { + r = old_r; + r.lx = r2->hx + 2; + add_rect(&r); + } +} + +/*rect.c*/