From 3440193a5a835b0cd695e3ee2bea31c240ba1028 Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Wed, 9 Jul 2025 18:30:54 +0300 Subject: [PATCH 1/7] Tutorial: spellcasting Add some basic spellcasting stuff to the tutorial: read a spellbook, cast a spell. If the hero doesn't have enough energy, just adds a note saying so. Remove/restore the known spells when entering/leaving the tutorial. --- dat/tut-1.lua | 21 ++++++++++++++++++--- include/decl.h | 1 + src/decl.c | 1 + src/nhlua.c | 3 +++ 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/dat/tut-1.lua b/dat/tut-1.lua index 22ae97c16..246dedefd 100644 --- a/dat/tut-1.lua +++ b/dat/tut-1.lua @@ -32,10 +32,10 @@ des.level_flags("mazelevel", "noflip", des.map([[ --------------------------------------------------------------------------- -|-.--|.......|......|..S....|.F.......|.............|.....................| +|-.--|.......|......|..S....|.F.......|.............|.......|.............| |.-..........|......|--|....|.F.....|.|S-------.....|.....................| -||.--|.......|..T......|....|.F.....|.|.......|.....|.....................| -||.|.|.......|......|-.|....|.F.....|.|.......|.....|.....................| +||.--|.......|..T......|....|.F.....|.|.......|.....|.......|.............| +||.|.|.......|......|-.|....|.F.....|.|.......|.....|--------.............| ||.|.|.......|......||.|-.-----------.-.......|-S----.....................| |-+-S---------..---.||........................|...|.......................| |......| |.-------------------.......|...|....--S----............| @@ -302,6 +302,21 @@ des.object({ id = "boulder", coord = {72,16} }); des.object({ id = "boulder", coord = {73,16} }); des.trap({ type = "trap door", coord = { 73,15 } }); +-- + +des.engraving({ coord = { 60,2 }, type = "engrave", text = "Spellcasting", degrade = false }); +if (u.uenmax < 5) then + -- TODO: make sure hero has enough Pw to cast the spell (5 pw) instead? + -- TODO: ensure the first cast of this spell succeeds? + des.engraving({ coord = { 59,2 }, type = "engrave", text = "Unfortunately you don't have enough energy to cast spells.", degrade = false }); +end +des.engraving({ coord = { 57,2 }, type = "engrave", text = "Pick up the spellbook with '" .. tut_key("pickup") .. "'", degrade = false }); +des.object({ coord = { 57,2 }, id = "spellbook of light", buc = "blessed" }); +des.engraving({ coord = { 55,2 }, type = "engrave", text = "Read the spellbook with '" .. tut_key("read") .. "'", degrade = false }); +des.engraving({ coord = { 53,2 }, type = "engrave", text = "Use '" .. tut_key("cast") .. "' to cast a spell", degrade = false }); +des.region(selection.area(53,01, 59, 3), "unlit"); + + ---------------- -- entering and leaving tutorial _branch_ now handled by core diff --git a/include/decl.h b/include/decl.h index 54cf2f390..d5186158b 100644 --- a/include/decl.h +++ b/include/decl.h @@ -423,6 +423,7 @@ struct instance_globals_g { long gmst_moves; struct obj *gmst_invent; genericptr_t *gmst_ubak, *gmst_disco, *gmst_mvitals; + struct spell gmst_spl_book[MAXSPELL + 1]; /* pline.c */ struct gamelog_line *gamelog; diff --git a/src/decl.c b/src/decl.c index 3430cd3a5..7d0a47cb4 100644 --- a/src/decl.c +++ b/src/decl.c @@ -372,6 +372,7 @@ static const struct instance_globals_g g_init_g = { 0L, /* gmst_moves */ NULL, /* gmst_invent */ NULL, NULL, NULL, /* gmst_ubak, gmst_disco, gmst_mvitals */ + { DUMMY }, /* gmst_spl_book */ /* pline.c */ UNDEFINED_PTR, /* gamelog */ /* region.c */ diff --git a/src/nhlua.c b/src/nhlua.c index 11cc8d537..b43e4c089 100644 --- a/src/nhlua.c +++ b/src/nhlua.c @@ -1695,6 +1695,7 @@ nhl_gamestate(lua_State *L) init_uhunger(); free_tutorial(); /* release gg.gmst_XYZ */ gg.gmst_stored = FALSE; + (void) memcpy(svs.spl_book, gg.gmst_spl_book, sizeof svs.spl_book); } else if (!reststate && !gg.gmst_stored) { /* store game state */ gg.gmst_moves = svm.moves; @@ -1715,6 +1716,8 @@ nhl_gamestate(lua_State *L) gg.gmst_mvitals = (genericptr_t) alloc(sizeof svm.mvitals); (void) memcpy(gg.gmst_mvitals, (genericptr_t) &svm.mvitals, sizeof svm.mvitals); + (void) memcpy(gg.gmst_spl_book, svs.spl_book, sizeof svs.spl_book); + (void) memset(svs.spl_book, 0, sizeof(svs.spl_book)); gg.gmst_stored = TRUE; } else { impossible("nhl_gamestate: inconsistent state (%s vs %s)", From 44b9ffe245036f80534bb0c2180bddc8be0bf5b4 Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Thu, 10 Jul 2025 11:01:30 +0300 Subject: [PATCH 2/7] Tutorial: tip containers --- dat/tut-1.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dat/tut-1.lua b/dat/tut-1.lua index 246dedefd..511090b79 100644 --- a/dat/tut-1.lua +++ b/dat/tut-1.lua @@ -222,10 +222,11 @@ des.door({ coord = { 38,6 }, state = "closed" }); des.engraving({ coord = { 39,6 }, type = "engrave", text = "You loot containers with '" .. tut_key("loot") .. "'", degrade = false }); -des.object({ coord = { 42,6 }, id = "large box", broken = true, trapped = false, +des.object({ coord = { 41,6 }, id = "large box", broken = true, trapped = false, contents = function(obj) des.object({ id = "secret door detection", class = "/", spe = 30 }); end }); +des.engraving({ coord = { 42,6 }, type = "engrave", text = "Containers can also be emptied with '" .. tut_key("tip") .. "'", degrade = false }); des.engraving({ coord = { 45,6 }, type = "engrave", text = "Magic wands are used with '" .. tut_key("zap") .. "'", degrade = false }); From 06ab2ce604cf492f8d650ca2a4d317c0a82c5bc5 Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Thu, 10 Jul 2025 11:07:45 +0300 Subject: [PATCH 3/7] Tutorial: Knight jumping --- dat/tut-1.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dat/tut-1.lua b/dat/tut-1.lua index 511090b79..f57f9119e 100644 --- a/dat/tut-1.lua +++ b/dat/tut-1.lua @@ -80,6 +80,10 @@ local diagmovekeys = tut_key("movesouthwest") .. " " .. des.engraving({ coord = { 9,3 }, type = "engrave", text = "Move around with " .. movekeys, degrade = false }); des.engraving({ coord = { 5,2 }, type = "engrave", text = "Move diagonally with " .. diagmovekeys, degrade = false }); +if (u.role == "Knight") then + des.engraving({ coord = { 12,1 }, type = "engrave", text = "Knights can jump with '" .. tut_key("jump") .. "'", degrade = false }); +end + -- des.engraving({ coord = { 2,4 }, type = "engrave", text = "Some actions may require multiple tries before succeeding", degrade = false }); From 588dc6b73f71c3e4abd5083480db046c8ec5c63a Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Thu, 10 Jul 2025 13:40:04 +0300 Subject: [PATCH 4/7] Tutorial: quaffing potions --- dat/tut-1.lua | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dat/tut-1.lua b/dat/tut-1.lua index f57f9119e..8640f3ad5 100644 --- a/dat/tut-1.lua +++ b/dat/tut-1.lua @@ -321,6 +321,11 @@ des.engraving({ coord = { 55,2 }, type = "engrave", text = "Read the spellbook w des.engraving({ coord = { 53,2 }, type = "engrave", text = "Use '" .. tut_key("cast") .. "' to cast a spell", degrade = false }); des.region(selection.area(53,01, 59, 3), "unlit"); +-- + +des.engraving({ coord = { 72,2 }, type = "engrave", text = "You \"quaff\" potions with '" .. tut_key("quaff") .. "'", degrade = false }); +des.object({ coord = { 72,2 }, id = "potion of object detection", buc = "blessed" }); + ---------------- From e5bd185ab5abac9dd3c9f7f2f43f20646612aa07 Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Thu, 10 Jul 2025 13:48:16 +0300 Subject: [PATCH 5/7] Tutorial: untrapping traps --- dat/tut-1.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dat/tut-1.lua b/dat/tut-1.lua index 8640f3ad5..b30e4edb2 100644 --- a/dat/tut-1.lua +++ b/dat/tut-1.lua @@ -133,6 +133,9 @@ for i = 1, 4 do coord = locs[i], victim = false }); end +des.engraving({ coord = { 15,15 }, type = "engrave", text = "Some traps can be disabled with '" .. tut_key("untrap") .. "'", degrade = false }); +des.trap({ coord = { 15,16 }, type = "web", spider_on_web = false }); + -- des.door({ coord = { 18,13 }, state = "closed" }); From 6c22e7af454c6c192f9f45bc4125336e87a7ec9b Mon Sep 17 00:00:00 2001 From: nhmall Date: Thu, 10 Jul 2025 22:44:56 -0400 Subject: [PATCH 6/7] attempt to ensure the correct curses.h is used on Linux OpenSUSE Tumbleweed ncurses 6.5 requires the one in /usr/include/ncursesw/curses.h, if ncursesw is being used. Otherwise, several needed function prototypes are not there. Fixes #1427 --- sys/unix/hints/linux.370 | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/sys/unix/hints/linux.370 b/sys/unix/hints/linux.370 index 2c4e460e8..3ce7d47d4 100755 --- a/sys/unix/hints/linux.370 +++ b/sys/unix/hints/linux.370 @@ -104,6 +104,7 @@ CURSESLIB = -lncurses -ltinfo ifdef MAKEFILE_SRC comma:=, NCURSES_LFLAGS = $(shell pkg-config ncursesw --libs) +NCURSES_CFLAGS = $(shell pkg-config ncursesw --cflags) ifeq (,$(findstring ncursesw, $(NCURSES_LFLAGS))) ifeq (,$(findstring ncurses, $(NCURSES_LFLAGS))) #this indicates that pkg-config itself was unavailable @@ -125,8 +126,33 @@ CURSESLIB = $(subst -Wl$(comma)-Bsymbolic-functions,,$(NCURSES_LFLAGS)) else CURSESLIB = $(NCURSES_LFLAGS) endif -#$(info $(CURSESLIB)) endif #HAVE_NCURSESW +#$(info $(CURSESLIB)) +ifeq (,$(findstring ncursesw, $(NCURSES_LFLAGS))) +ifeq (,$(findstring ncurses, $(NCURSES_LFLAGS))) +#this indicates that pkg-config itself was unavailable +NOPKGCONFIG = 1 +endif #ncurses not in NCURSES_LFLAGS? +endif #ncursesw not in NCURSES_LFLAGS? +# +ifeq "$(NOPKGCONFIG)" "1" +NCURSES_CFLAGS = -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 +ifeq "$(HAVE_NCURSESW)" "1" +ifeq (,$(wildcard /usr/include/ncursesw/curses.h)) +NCURSES_CFLAGS += -I/usr/include +else +NCURSES_CFLAGS += -I/usr/include/ncursesw +endif +NCURSES_LFLAGS = -lncursesw -ltinfo +else #HAVE_NCURSESW +ifeq (,$(wildcard /usr/include/ncurses/curses.h)) +NCURSES_CFLAGS += -I/usr/include +else +NCURSES_CFLAGS += -I/usr/include/ncurses +endif +NCURSES_LFLAGS = -lncurses -ltinfo +endif #HAVE_NCURSESW +endif #NOPKGCONFIG endif #MAKEFILE_SRC endif #USE_CURSESLIB @@ -152,6 +178,7 @@ NHCFLAGS+=-DCOMPRESS=\"/bin/gzip\" -DCOMPRESS_EXTENSION=\".gz\" #NHCFLAGS+=-DCHANGE_COLOR NHCFLAGS+=-DSELF_RECOVER ifdef WANT_WIN_CURSES +NHCFLAGS+=$(NCURSES_CFLAGS) ifeq "$(HAVE_NCURSESW)" "1" NHCFLAGS+=-DCURSES_UNICODE else From 8570421449c612bc28bf68cfc2286464c850460b Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Fri, 11 Jul 2025 13:04:25 +0300 Subject: [PATCH 7/7] Create familiar spell can create harder creatures --- doc/fixes3-7-0.txt | 1 + src/dog.c | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/fixes3-7-0.txt b/doc/fixes3-7-0.txt index 56d72fe80..8bb097002 100644 --- a/doc/fixes3-7-0.txt +++ b/doc/fixes3-7-0.txt @@ -1520,6 +1520,7 @@ the engraving pristine text field was not being appropriately populated during worn alchemy smock reduces chances of dipped potions exploding dwarves can sense buried items under their feet monsters trapped in pits cannot kick +create familiar spell can create harder creatures Fixes to 3.7.0-x General Problems Exposed Via git Repository diff --git a/src/dog.c b/src/dog.c index d0d4e7f3c..0682cf610 100644 --- a/src/dog.c +++ b/src/dog.c @@ -124,7 +124,10 @@ pick_familiar_pm(struct obj *otmp, boolean quietly) } else if (!rn2(3)) { pm = &mons[pet_type()]; } else { - pm = rndmonst(); + int skill = spell_skilltype(SPE_CREATE_FAMILIAR); + int max = 3 * P_SKILL(skill); + + pm = rndmonst_adj(0, max); if (!pm && !quietly) There("seems to be nothing available for a familiar."); }