@@ -354,8 +354,8 @@ void runner_impl::jump(ip_t dest, bool record_visits, bool track_knot_visit, boo
354354 const container_data_t & dest_container = _story->container_data (dest_id);
355355 if (dest_offset == dest_container._start_offset ) {
356356 // Record direct jump to non-knot if requested. (Knots handled below.)
357- if (record_visits && ! dest_container.knot ()) {
358- _globals->visit (dest_id, preserve_turns );
357+ if (! preserve_turns && record_visits && ! dest_container.knot ()) {
358+ _globals->visit (dest_id);
359359 }
360360
361361 // Consume instruction so we don't process it again during normal flow. (We need to do this here
@@ -387,8 +387,8 @@ void runner_impl::jump(ip_t dest, bool record_visits, bool track_knot_visit, boo
387387 //
388388 // Ink has a rule about incrementing visit counts when you jump to the top of a knot, which
389389 // seems to need to override inkcpp's knot_visit flag.
390- if (track_knot_visit || container._start_offset == dest_offset) {
391- _globals->visit (id, preserve_turns );
390+ if (! preserve_turns && ( track_knot_visit || container._start_offset == dest_offset) ) {
391+ _globals->visit (id);
392392 }
393393
394394 // If tracking, update with the first knot we encounter, which is the one closest to the top
@@ -425,9 +425,15 @@ void runner_impl::start_frame(uint32_t target)
425425 }
426426 _evaluation_mode = false ; // unset eval mode when enter function or tunnel
427427
428+ // Always record visits
429+ const bool record_visits = true ;
430+
431+ // Do we visit the knot? We need to visit anything that can have knot tags.
432+ const bool track_knot_visit = type != frame_type::function;
433+
428434 // Do the jump
429435 inkAssert (_story->instructions () + target < _story->end (), " Diverting past end of story data!" );
430- jump (_story->instructions () + target, true , false );
436+ jump (_story->instructions () + target, record_visits, track_knot_visit );
431437}
432438
433439frame_type runner_impl::execute_return ()
@@ -461,13 +467,21 @@ frame_type runner_impl::execute_return()
461467 }
462468 }
463469
470+ // Never record visits
471+ const bool record_visits = false ;
472+
473+ // Do we visit the knot? This needs to match what we tracked in start_frame.
474+ const bool track_knot_visit = type != frame_type::function;
475+
476+ // Returns should never update visit counts.
477+ const bool preserve_turns = true ;
464478
465479 // Jump to the old offset
466480 inkAssert (
467481 _story->instructions () + offset < _story->end (),
468482 " Callstack return is outside bounds of story!"
469483 );
470- jump (_story->instructions () + offset, false , false );
484+ jump (_story->instructions () + offset, record_visits, track_knot_visit, preserve_turns );
471485
472486 // Return frame type
473487 return type;
@@ -625,7 +639,11 @@ void runner_impl::choose(size_t index)
625639 inkAssert (prev != nullptr , " No 'done' point recorded before finishing choice output" );
626640
627641 // Move to the previous pointer so we track our movements correctly
628- jump (prev, false , false );
642+ {
643+ const bool record_visits = false ;
644+ const bool track_knot_visit = false ;
645+ jump (prev, record_visits, track_knot_visit);
646+ }
629647 _done = nullptr ;
630648
631649 // Collapse callstacks to the correct thread
@@ -635,7 +653,9 @@ void runner_impl::choose(size_t index)
635653 _eval.clear ();
636654
637655 // Jump to destination and clear choice list
638- jump (_story->instructions () + c.path (), true , false );
656+ const bool record_visits = true ;
657+ const bool track_knot_visit = false ;
658+ jump (_story->instructions () + c.path (), record_visits, track_knot_visit);
639659 clear_choices ();
640660 _entered_knot = false ;
641661}
@@ -815,7 +835,9 @@ bool runner_impl::move_to(hash_t path)
815835 // Clear state and move to destination
816836 reset ();
817837 _ptr = _story->instructions ();
818- jump (destination, false , false );
838+ const bool record_visits = false ;
839+ const bool track_knot_visit = false ;
840+ jump (destination, record_visits, track_knot_visit);
819841
820842 return true ;
821843}
@@ -833,7 +855,8 @@ bool runner_impl::migrate_to(const loader& loader, hash_t path)
833855 ip_t start_of_knot = _story->find_offset_for (_story->container_data (_current_knot_id)._hash );
834856 fetch_tags (start_of_knot);
835857 assign_tags ({tags_level::KNOT });
836- if (start_of_knot != destination) {
858+ // If the destination is in the recorded current knot
859+ if (start_of_knot < destination) {
837860 for (ip_t iter = start_of_knot; iter != destination; iter += 6 ) {
838861 if (read<Command>(iter) == Command::DEFINE_TEMP ) {
839862 hash_t temp_name = read<hash_t >(iter + 2 );
@@ -846,7 +869,9 @@ bool runner_impl::migrate_to(const loader& loader, hash_t path)
846869 while (read<Command>(eval_start) != Command::START_EVAL ) {
847870 eval_start -= 6 ;
848871 }
849- jump (eval_start, false , false );
872+ const bool record_visits = false ;
873+ const bool track_knot_visit = false ;
874+ jump (eval_start, record_visits, track_knot_visit);
850875 while (_ptr != iter + 6 ) {
851876 step ();
852877 }
@@ -860,7 +885,10 @@ bool runner_impl::migrate_to(const loader& loader, hash_t path)
860885 // without this the visit() call inside jump() would reset them to 0.
861886 _container.clear ();
862887 _ptr = nullptr ;
863- jump (destination, false , true , true );
888+ const bool record_visits = false ;
889+ const bool track_knot_visit = false ;
890+ const bool preserve_turns = true ;
891+ jump (destination, record_visits, track_knot_visit, preserve_turns);
864892
865893 if (loader.old_ref_table
866894 && ! _globals->lists ().migrate_variables (
@@ -1202,7 +1230,9 @@ void runner_impl::step()
12021230 inkAssert (
12031231 _story->instructions () + target < _story->end (), " Diverting past end of story data!"
12041232 );
1205- jump (_story->instructions () + target, true , ! (flag & CommandFlag::DIVERT_HAS_CONDITION ));
1233+ const bool record_visits = true ;
1234+ const bool track_knot_visit = ! (flag & CommandFlag::DIVERT_HAS_CONDITION );
1235+ jump (_story->instructions () + target, record_visits, track_knot_visit);
12061236 } break ;
12071237 case Command::DIVERT_TO_VARIABLE : {
12081238 // Get variable value
@@ -1224,9 +1254,11 @@ void runner_impl::step()
12241254 inkAssert (val, " Jump destiniation needs to be defined!" );
12251255
12261256 // Move to location
1257+ const bool record_visits = true ;
1258+ const bool track_knot_visit = ! (flag & CommandFlag::DIVERT_HAS_CONDITION );
12271259 jump (
1228- _story->instructions () + val->get <value_type::divert>(), true ,
1229- ! (flag & CommandFlag:: DIVERT_HAS_CONDITION )
1260+ _story->instructions () + val->get <value_type::divert>(), record_visits ,
1261+ track_knot_visit
12301262 );
12311263 inkAssert (_ptr < _story->end (), " Diverted past end of story data!" );
12321264 } break ;
0 commit comments