diff --git a/dat/themerms.lua b/dat/themerms.lua index 4f4f59029..fa85a44df 100644 --- a/dat/themerms.lua +++ b/dat/themerms.lua @@ -545,6 +545,59 @@ xx|.....|xx end }); end, + -- Twin businesses + { + mindiff = 4; -- arbitrary + contents = function() + -- Due to the way room connections work in mklev.c, we must guarantee + -- that the "aisle" between the shops touches all four walls of the + -- larger room. Thus it has an extra width and height. + des.room({ type="themed", w=9, h=5, contents = function() + -- There are eight possible placements of the two shops, four of + -- which have the vertical aisle in the center. + southeast = function() return percent(50) and "south" or "east" end + northeast = function() return percent(50) and "north" or "east" end + northwest = function() return percent(50) and "north" or "west" end + southwest = function() return percent(50) and "south" or "west" end + placements = { + { lx = 1, ly = 1, rx = 4, ry = 1, lwall = "south", rwall = southeast() }, + { lx = 1, ly = 2, rx = 4, ry = 2, lwall = "north", rwall = northeast() }, + { lx = 1, ly = 1, rx = 5, ry = 1, lwall = southeast(), rwall = southwest() }, + { lx = 1, ly = 1, rx = 5, ry = 2, lwall = southeast(), rwall = northwest() }, + { lx = 1, ly = 2, rx = 5, ry = 1, lwall = northeast(), rwall = southwest() }, + { lx = 1, ly = 2, rx = 5, ry = 2, lwall = northeast(), rwall = northwest() }, + { lx = 2, ly = 1, rx = 5, ry = 1, lwall = southwest(), rwall = "south" }, + { lx = 2, ly = 2, rx = 5, ry = 2, lwall = northwest(), rwall = "north" } + } + ltype,rtype = "weapon shop","armor shop" + if percent(50) then + ltype,rtype = rtype,ltype + end + shopdoorstate = function() + if percent(1) then + return "locked" + elseif percent(50) then + return "closed" + else + return "open" + end + end + p = placements[d(#placements)] + des.room({ type=ltype, x=p["lx"], y=p["ly"], w=3, h=3, filled=1, joined=0, + contents = function() + des.door({ state=shopdoorstate(), wall=p["lwall"] }) + end + }); + des.room({ type=rtype, x=p["rx"], y=p["ry"], w=3, h=3, filled=1, joined=0, + contents = function() + des.door({ state=shopdoorstate(), wall=p["rwall"] }) + end + }); + end + }); + end + }, + }; function is_eligible(room) diff --git a/src/mklev.c b/src/mklev.c index bfb0c085c..51616aaf4 100644 --- a/src/mklev.c +++ b/src/mklev.c @@ -35,6 +35,7 @@ static void FDECL(do_room_or_subroom, (struct mkroom *, int, int, int, int, BOOLEAN_P, SCHAR_P, BOOLEAN_P, BOOLEAN_P)); static void NDECL(makerooms); +static boolean FDECL(door_into_nonjoined, (XCHAR_P, XCHAR_P)); static void FDECL(finddpos, (coord *, XCHAR_P, XCHAR_P, XCHAR_P, XCHAR_P)); static void FDECL(mkinvpos, (XCHAR_P, XCHAR_P, int)); @@ -68,6 +69,33 @@ const genericptr vy; #endif /* LINT */ } +/* Return TRUE if a door placed at (x, y) which otherwise passes okdoor() checks + * would be connecting into an area that was declared as joined = 0. + * Checking for this in finddpos() enables us to have rooms with sub-areas (such + * as shops) that will never randomly generate unwanted doors in order to + * connect them up to other areas. + */ +static boolean +door_into_nonjoined(x, y) +xchar x, y; +{ + xchar tx, ty, diridx; + + for (diridx = 0; diridx <= 6; diridx += 2) { + tx = x + xdir[diridx]; + ty = y + ydir[diridx]; + if (!isok(tx, ty) || IS_ROCK(levl[tx][ty].typ)) + continue; + + /* Is this connecting to a room that doesn't want joining? */ + if (levl[tx][ty].roomno >= ROOMOFFSET && + !g.rooms[levl[tx][ty].roomno - ROOMOFFSET].needjoining) { + return TRUE; + } + } + return FALSE; +} + static void finddpos(cc, xl, yl, xh, yh) coord *cc; @@ -77,12 +105,12 @@ xchar xl, yl, xh, yh; x = rn1(xh - xl + 1, xl); y = rn1(yh - yl + 1, yl); - if (okdoor(x, y)) + if (okdoor(x, y) && !door_into_nonjoined(x, y)) goto gotit; for (x = xl; x <= xh; x++) for (y = yl; y <= yh; y++) - if (okdoor(x, y)) + if (okdoor(x, y) && !door_into_nonjoined(x, y)) goto gotit; for (x = xl; x <= xh; x++) @@ -92,6 +120,8 @@ xchar xl, yl, xh, yh; /* cannot find something reasonable -- strange */ x = xl; y = yh; + impossible("finddpos: couldn't find door pos within (%d,%d,%d,%d)", + xl, yl, xh, yh); gotit: cc->x = x; cc->y = y; diff --git a/src/shknam.c b/src/shknam.c index 69b217ffb..b8a4386c4 100644 --- a/src/shknam.c +++ b/src/shknam.c @@ -495,7 +495,7 @@ const char *const *nlp; int i, trycnt, names_avail; const char *shname = 0; struct monst *mtmp; - int name_wanted; + int name_wanted = shk->m_id; s_level *sptr; if (nlp == shklight && In_mines(&u.uz) @@ -510,7 +510,7 @@ const char *const *nlp; use ledger_no rather than depth to keep minetown distinct. */ int nseed = (int) ((long) ubirthday / 257L); - name_wanted = ledger_no(&u.uz) + (nseed % 13) - (nseed % 5); + name_wanted += ledger_no(&u.uz) + (nseed % 13) - (nseed % 5); if (name_wanted < 0) name_wanted += (13 + 5); shk->female = name_wanted & 1; @@ -518,6 +518,8 @@ const char *const *nlp; for (names_avail = 0; nlp[names_avail]; names_avail++) continue; + name_wanted = name_wanted % names_avail; + for (trycnt = 0; trycnt < 50; trycnt++) { if (nlp == shktools) { shname = shktools[rn2(names_avail)]; @@ -545,6 +547,7 @@ const char *const *nlp; continue; if (strcmp(ESHK(mtmp)->shknam, shname)) continue; + name_wanted = names_avail; /* try a random name */ break; } if (!mtmp)