Angband Forums

Angband Forums (http://angband.oook.cz/forum/index.php)
-   Development (http://angband.oook.cz/forum/forumdisplay.php?f=10)
-   -   Trying to understand Run/Disturb Code (http://angband.oook.cz/forum/showthread.php?t=9329)

wobbly March 23, 2019 16:53

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?

wobbly March 24, 2019 07:28

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.

wobbly March 25, 2019 05:16

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.

Nick March 25, 2019 10:49

If you work this out that would be great :D

wobbly April 4, 2019 07:55

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?

Nick July 6, 2019 07:54

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...


All times are GMT +1. The time now is 17:32.

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2019, vBulletin Solutions Inc.