Trying to understand Run/Disturb Code

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • wobbly
    Prophet
    • May 2012
    • 2629

    Trying to understand Run/Disturb Code

    Code:
    	/* Take time */
    
    	player->upkeep->energy_use = z_info->move_energy / player->state.num_moves;
    
    
    
    	/* Move the player; running straight into a trap == trying to disarm */
    
    	move_player(run_cur_dir, dir && disarm ? true : false);
    
    
    
    	/* Decrease counter if it hasn't been cancelled */
    
    	/* occurs after movement so that using p->u->running as flag works */
    
    	if (player->upkeep->running) {
    
    		player->upkeep->running--;
    
    	} else if (!player->upkeep->running_withpathfind)
    
    		return;
    
    
    
    	/* Prepare the next step */
    
    	if (player->upkeep->running) {
    
    		cmdq_push(CMD_RUN);
    
    		cmd_set_arg_direction(cmdq_peek(), "direction", 0);
    
    	}
    
    }
    So it takes energy, moves the player & then decreases the run counter (only here returning if the counter is =0 ? ) before queing CMD_RUN?

    Now when it disturbs:

    Code:
    void disturb(struct player *p, int stop_search)
    
    {
    
    	/* Cancel repeated commands */
    
    	cmd_cancel_repeat();
    
    
    
    	/* Cancel Resting */
    
    	if (player_is_resting(p)) {
    
    		player_resting_cancel(p, true);
    
    		p->upkeep->redraw |= PR_STATE;
    
    	}
    
    
    
    	/* Cancel running */
    
    	if (p->upkeep->running) {
    
    		p->upkeep->running = 0;
    
    
    
    		/* Check for new panel if appropriate */
    
    		event_signal(EVENT_PLAYERMOVED);
    
    		p->upkeep->update |= PU_TORCH;
    
    
    
    		/* Mark the whole map to be redrawn */
    
    		event_signal_point(EVENT_MAP, -1, -1);
    
    	}
    
    
    
    	/* Flush input */
    
    	event_signal(EVENT_INPUT_FLUSH);
    
    }
    It seems to set the run counter to 0 but I don't see anywhere where it removes the que-ed command? As far as I understand it that run command will still make a move if the run counter is 0? What am I missing here?
    Last edited by wobbly; March 23, 2019, 16:59.
  • wobbly
    Prophet
    • May 2012
    • 2629

    #2
    My understanding (which is limited & possibly wrong) of what happens here is it returns before movement (in run_test) for a visible monster but that doesn't help for off-screen breathers & invisible monsters. It doesn't que the next cmd_run if p->upkeep->running = 0 but it still actually moves if cmd_run is already qued.

    so in the following situation with the dragon fly just out of LOS:

    Code:
    ####
    @..F.
    ####
    if I run forward: I move, it ques cmd_run, the F become visible disturbing and setting p->upkeep->running = 0 (but cmd_run has already been qued? & is still qued?). Now if it moves backwards before cmd_run runs again it will not be visible when run_test actually checks & I'll still move another square forward before it hits return.

    While I'm not 100% sure that's how it works in the code, it's certainly what I'm seeing in-game.

    Edit: Hmm it doesn't interrupt properly for visible either. I can see this by running past a corridor full of sleeping 'p's, it moves 1 step too many.
    Last edited by wobbly; March 24, 2019, 07:55.

    Comment

    • wobbly
      Prophet
      • May 2012
      • 2629

      #3
      I'll have a go at fixing this in my own copy in the next couple of days. Just wanted to note that it runs the extra step if you recall while running.

      Comment

      • Nick
        Vanilla maintainer
        • Apr 2007
        • 9634

        #4
        If you work this out that would be great
        One for the Dark Lord on his dark throne
        In the Land of Mordor where the Shadows lie.

        Comment

        • wobbly
          Prophet
          • May 2012
          • 2629

          #5
          Had my plans messed up by the flu & only just got round to this, so apologises for the delay. Anyway I've got something that appears to be working on mine. Not sure whether it's the best solution but it is working when I test it.

          In player-path.c, run_step I've inserted a little check here:

          Code:
          /* Inserted a check here before movement - MC */
          	if ((!player->upkeep->running) && (!player->upkeep->running_withpathfind)) {
          		return;
          	}
          	
          	/* Take time */
          	player->upkeep->energy_use = z_info->move_energy / player->state.num_moves;
          
          	/* Move the player; running straight into a trap == trying to disarm */
          	move_player(run_cur_dir, dir && disarm ? true : false);
          
          	/* Decrease counter if it hasn't been cancelled */
          	/* occurs after movement so that using p->u->running as flag works */
          	if (player->upkeep->running) {
          		player->upkeep->running--;
          	} else if (!player->upkeep->running_withpathfind)
          		return;
          
          	/* Prepare the next step */
          	if (player->upkeep->running) {
          		cmdq_push(CMD_RUN);
          		cmd_set_arg_direction(cmdq_peek(), "direction", 0);
          	}
          }
          This next bit I'm less sure of as I don't exactly get running_withpathfind but it looked like it should be there.
          In player-util.c, disturb I added a bit:

          Code:
          void disturb(struct player *p, int stop_search)
          {
          	/* Cancel repeated commands */
          	cmd_cancel_repeat();
          
          	/* Cancel Resting */
          	if (player_is_resting(p)) {
          		player_resting_cancel(p, true);
          		p->upkeep->redraw |= PR_STATE;
          	}
          
          	/* Cancel running */
          	if (p->upkeep->running) {
          		p->upkeep->running = 0;
          
          		/* Check for new panel if appropriate */
          		event_signal(EVENT_PLAYERMOVED);
          		p->upkeep->update |= PU_TORCH;
          
          		/* Mark the whole map to be redrawn */
          		event_signal_point(EVENT_MAP, -1, -1);
          	}
          	/* Cancel running_withpathfind?? - MC */
          	if (p->upkeep->running_withpathfind) {
          player->upkeep->running_withpathfind = false;
          
          /* Check for new panel if appropriate */
          		event_signal(EVENT_PLAYERMOVED);
          		p->upkeep->update |= PU_TORCH;
          
          		/* Mark the whole map to be redrawn */
          		event_signal_point(EVENT_MAP, -1, -1);
          	}
          	/* Flush input */
          	event_signal(EVENT_INPUT_FLUSH);
          }
          There's also a disturb missing where ever the game IDs the call of the grave curse. Currently if it summons an invisible monster the curse will id, but not disturb which seems inconsistent.

          I was tempted to add message spam in to trace & output what was going on inside the code, though in the end I didn't. I assume there is a more technical way to do that then message spam? What's the usual way to get the game to output this information?
          Last edited by wobbly; April 4, 2019, 08:55.

          Comment

          • Nick
            Vanilla maintainer
            • Apr 2007
            • 9634

            #6
            So I think I've fixed this issue once and for all by more major surgery. Basically I put in a mechanism for the disturb function to cancel all commands in the queue. I don't think this will have any bad side-effects...
            One for the Dark Lord on his dark throne
            In the Land of Mordor where the Shadows lie.

            Comment

            Working...
            😀
            😂
            🥰
            😘
            🤢
            😎
            😞
            😡
            👍
            👎