]> granicus.if.org Git - nethack/commitdiff
melting ice (trunk only)
authornethack.allison <nethack.allison>
Sun, 12 Oct 2003 04:21:27 +0000 (04:21 +0000)
committernethack.allison <nethack.allison>
Sun, 12 Oct 2003 04:21:27 +0000 (04:21 +0000)
add a new melt_ice_away timer for ice created via zapping
a wand/spell of cold.

Some follow-up adjustments to the length of time before
the ice melts may be necessary. Ideally, I'd like to
have it so that the shorter the length of time since
the ice was created, the lesser the chance that it will
melt out from under you.  Likewise, the longer it has
been, the more risky it will be to venture onto it.

At the moment, however, each spot of ice is just
getting a somewhat random time always greater
than 50, which is less than ideal.

doc/fixes35.0
include/extern.h
include/timeout.h
src/timeout.c
src/trap.c
src/zap.c

index 8931658e9dce53219923accd754a8621968da3e9..a5c65fa1c0a3fd80bac81c452ab890f5fed05ce4 100644 (file)
@@ -66,6 +66,7 @@ Izchak's lighting store is now able to stock oil for your lamp
 provide core support for saving of messsage history in save file
 the following actions can now be continued after save/restore: digging, 
        eating, studying, removing armor
+hero-created and monster-created ice will eventually melt away
 
 
 Platform- and/or Interface-Specific New Features
index 1eec667326e7461f603e0fcc535b410aecfa89cb..84f1834588632048bd100d678d379a3643a86488 100644 (file)
@@ -1982,6 +1982,7 @@ E void NDECL(run_timers);
 E void FDECL(obj_move_timers, (struct obj *, struct obj *));
 E void FDECL(obj_split_timers, (struct obj *, struct obj *));
 E void FDECL(obj_stop_timers, (struct obj *));
+E void FDECL(spot_stop_timers, (XCHAR_P,XCHAR_P,SHORT_P));
 E boolean FDECL(obj_is_local, (struct obj *));
 E void FDECL(save_timers, (int,int,int));
 E void FDECL(restore_timers, (int,int,BOOLEAN_P,long));
@@ -2379,7 +2380,9 @@ E struct monst *FDECL(bhit, (int,int,int,int,int (*)(MONST_P,OBJ_P),
 E struct monst *FDECL(boomhit, (int,int));
 E int FDECL(burn_floor_paper, (int,int,BOOLEAN_P,BOOLEAN_P));
 E void FDECL(buzz, (int,int,XCHAR_P,XCHAR_P,int,int));
-E void FDECL(melt_ice, (XCHAR_P,XCHAR_P));
+E void FDECL(melt_ice, (XCHAR_P,XCHAR_P,const char *));
+E void FDECL(start_melt_ice_timeout, (XCHAR_P,XCHAR_P));
+E void FDECL(melt_ice_away, (genericptr_t, long));
 E int FDECL(zap_over_floor, (XCHAR_P,XCHAR_P,int,boolean *));
 E void FDECL(fracture_rock, (struct obj *));
 E boolean FDECL(break_statue, (struct obj *));
index 481bf95bf9df4f116ce4fd73697140bca1993439..5c729ad996715acbf4fc2d41b047945d0342cb3f 100644 (file)
@@ -28,7 +28,8 @@ typedef void FDECL((*timeout_proc), (genericptr_t, long));
 #define BURN_OBJECT    3
 #define HATCH_EGG      4
 #define FIG_TRANSFORM  5
-#define NUM_TIME_FUNCS 6
+#define MELT_ICE_AWAY  6
+#define NUM_TIME_FUNCS 7
 
 /* used in timeout.c */
 typedef struct fe {
index 75f6ef86167ec902037bbf54f4425d05a54f3cac..12314da9eb31b4c0baac4001d3ec15783972dd9e 100644 (file)
@@ -1309,7 +1309,8 @@ static const ttable timeout_funcs[NUM_TIME_FUNCS] = {
     TTAB(revive_mon,   (timeout_proc)0,        "revive_mon"),
     TTAB(burn_object,  cleanup_burn,           "burn_object"),
     TTAB(hatch_egg,    (timeout_proc)0,        "hatch_egg"),
-    TTAB(fig_transform,        (timeout_proc)0,        "fig_transform")
+    TTAB(fig_transform,        (timeout_proc)0,        "fig_transform"),
+    TTAB(melt_ice_away,        (timeout_proc)0,        "melt_ice_away")
 };
 #undef TTAB
 
@@ -1554,6 +1555,36 @@ obj_stop_timers(obj)
     obj->timed = 0;
 }
 
+/*
+ * Stop all timers of index func_index at this spot.
+ * 
+ */
+void
+spot_stop_timers(x,y,func_index)
+xchar x,y;
+short func_index;
+{
+    timer_element *curr, *prev, *next_timer=0;
+    long where = (((long)x << 16) | ((long)y));
+
+    for (prev = 0, curr = timer_base; curr; curr = next_timer) {
+       next_timer = curr->next;
+       if (curr->kind == TIMER_LEVEL &&
+           curr->func_index == func_index && curr->arg == (genericptr_t)where) {
+           if (prev)
+               prev->next = curr->next;
+           else
+               timer_base = curr->next;
+           if (timeout_funcs[curr->func_index].cleanup)
+               (*timeout_funcs[curr->func_index].cleanup)(curr->arg,
+                       curr->timeout);
+           free((genericptr_t) curr);
+       } else {
+           prev = curr;
+       }
+    }
+}
+
 
 /* Insert timer into the global queue */
 STATIC_OVL void
index c5ac3ece052c3397bbb824b7b2204d1263b3be74..ffec6778cdf92905c4e18914de633687e81af7d8 100644 (file)
@@ -1904,7 +1904,7 @@ glovecheck:                   target = which_armor(mtmp, W_ARMG);
                                !see_it && distu(mtmp->mx, mtmp->my) <= 3*3)
                            You("smell smoke.");
                        if (is_ice(mtmp->mx,mtmp->my))
-                           melt_ice(mtmp->mx,mtmp->my);
+                           melt_ice(mtmp->mx,mtmp->my, (char *)0);
                        if (see_it) seetrap(trap);
                        break;
 
@@ -2440,7 +2440,7 @@ struct obj *box;  /* null for floor trap */
        if (!box && burn_floor_paper(u.ux, u.uy, see_it, TRUE) && !see_it)
            You("smell paper burning.");
        if (is_ice(u.ux, u.uy))
-           melt_ice(u.ux, u.uy);
+           melt_ice(u.ux, u.uy, (char *)0);
 }
 
 STATIC_OVL void
index 7b1879110f28b1200724e85ea9414bf87b37d33a..f4eaa9ea4da81f9de171011795c288a0ed2e15be 100644 (file)
--- a/src/zap.c
+++ b/src/zap.c
@@ -3479,12 +3479,14 @@ register int dx,dy;
 }
 
 void
-melt_ice(x, y)
+melt_ice(x, y, msg)
 xchar x, y;
+const char *msg;
 {
        struct rm *lev = &levl[x][y];
        struct obj *otmp;
 
+       if (!msg) msg = "The ice crackles and melts.";
        if (lev->typ == DRAWBRIDGE_UP)
            lev->drawbridgemask &= ~DB_ICE;     /* revert to DB_MOAT */
        else {  /* lev->typ == ICE */
@@ -3496,11 +3498,12 @@ xchar x, y;
 #endif
            lev->icedpool = 0;
        }
+       spot_stop_timers(x, y, MELT_ICE_AWAY);  /* no more ice to melt away */
        obj_ice_effects(x, y, FALSE);
        unearth_objs(x, y);
        if (Underwater) vision_recalc(1);
        newsym(x,y);
-       if (cansee(x,y)) Norep("The ice crackles and melts.");
+       if (cansee(x,y)) Norep(msg);
        if ((otmp = sobj_at(BOULDER, x, y)) != 0) {
            if (cansee(x,y)) pline("%s settles...", An(xname(otmp)));
            do {
@@ -3515,6 +3518,38 @@ xchar x, y;
                spoteffects(TRUE);      /* possibly drown, notice objects */
 }
 
+/*
+ * Start a melt_ice timer.
+ */
+void
+start_melt_ice_timeout(x,y)
+xchar x,y;
+{
+       long when, where;
+       short action = MELT_ICE_AWAY;
+       for (when = 50L; when < 2000L; when++)
+               if (!rn2(3)) break;
+       where = (((long)x << 16) | ((long)y));
+       (void) start_timer(when, TIMER_LEVEL, action, (genericptr_t)where);
+}
+
+/*
+ * Called when ice has melted completely away.
+ */
+void
+melt_ice_away(arg, timeout)
+genericptr_t arg;
+long timeout;  /* unused */
+{
+       xchar x,y;
+       long where = (long)arg;
+
+       y = (xchar)(where & 0xFFFF);
+       x = (xchar)((where >> 16) & 0xFFFF);
+       /* melt_ice does newsym when appropriate */
+       melt_ice(x,y,"Some ice melts away.");
+}
+
 /* Burn floor scrolls, evaporate pools, etc...  in a single square.  Used
  * both for normal bolts of fire, cold, etc... and for fireballs.
  * Sets shopdamage to TRUE if a shop door is destroyed, and returns the
@@ -3541,7 +3576,7 @@ boolean *shopdamage;
                if (cansee(x,y)) newsym(x,y);
            }
            if(is_ice(x, y)) {
-               melt_ice(x, y);
+               melt_ice(x, y, (char *)0);
            } else if(is_pool(x,y)) {
                const char *msgtxt = "You hear hissing gas.";
                if(lev->typ != POOL) {  /* MOAT or DRAWBRIDGE_UP */
@@ -3627,6 +3662,7 @@ boolean *shopdamage;
                        }
                    }
                }
+               start_melt_ice_timeout(x,y);
                obj_ice_effects(x,y,TRUE);
        }
        if(closed_door(x, y)) {