ainslec / adventuron-issue-tracker

Adventuron Issues Tracker
4 stars 0 forks source link

Make it easy to track NPC movements without a lot of boilerplate code #280

Open ainslec opened 3 years ago

ainslec commented 3 years ago

(different to the racetrack issue)

Here is some long-winded NPC implementation code for NPC movement. It doesn't currently let you know the direction that the NPC entered a room in.

start_at = room_1

integers {
   my_counter : integer "0" ;
}

locations {
   room_1 : location "room 1" ;
   room_2 : location "room 2" ;
   room_3 : location "room 3" ;
   room_4 : location "room 4" ;
   room_5 : location "room 5";
}

connections {
   from, direction, to = [
      room_1, east, room_2
      room_2, east, room_3
      room_3, east, room_4
      room_4, east, room_5
   ]
}

objects {
   NPC : scenery "the NPC" ;
}

strings {
   last_npc_location : string "" ;
}

on_tick {
   : print {("counter: "+my_counter)} ;

   : set_string var = "last_npc_location" { expression -> (parent_of("NPC")) }

   : if      (my_counter==1) { : create "NPC" target = "room_4" ; }
   : else_if (my_counter==2) { : create "NPC" target = "room_3" ; }
   : else_if (my_counter==3) { : create "NPC" target = "room_2" ; }
   : else_if (my_counter==4) { : create "NPC" target = "room_1" ; }
   : else_if (my_counter==6) { : create "NPC" target = "room_2" ; }

   : if (is_beside "NPC") {
      : if (current_location() != previous_location()) {
         : if (last_npc_location != current_location()) {
            : if (last_npc_location == previous_location()) {
               : print "You follow the NPC ?????." ;
            }
            : else {
               : print "The NPC enters from the ?????." ;
            }
         }
         : else {
            : print "NPC is here (3)." ;
         }
      }
      : else {
         : if (last_npc_location != current_location()) {
            : print "The NPC enters from the ?????." ;
         }
      }
   }
   : else_if (parent_of("NPC") == previous_location() && current_location() == last_npc_location) {
      : print "The NPC passes you on the way ?????." ;
   }
   : increment "my_counter" ;
}
ainslec commented 3 years ago

Added ": gosub "print_npc_movements" ;" command.

start_at    = room_1
redescribe  = auto_beta
start_theme = chris
protagonist = chris

locations {
   room_1 : location "room 1" ;
   room_2 : location "room 2" ;
   room_3 : location "room 3" ;
   room_4 : location "room 4" ;
   room_5 : location "room 5";
}

connections {
   from, direction, to = [
      room_1, east, room_2
      room_2, east, room_3
      room_3, east, room_4
      room_4, east, room_5
   ]
}

objects {
   lamp  : object    "a lamp" at = "room_3" ;
   barry : character "Barry" ;
   sally : character "Sally" ;
   chris : character "Chris" at = "room_1" ;
   mark  : character "Mark"  at = "room_4" ;
}

integers {
   my_counter : integer "0" ;
}

strings {
   protagonist_text : dynamic_string {( "Playing As: " + protagonist() )}
}

on_command {

   : match "become _"  {
      : if (noun1_is "mark") {
         : become "mark";
         : set_theme "mark" ;

      } 
      : else_if (noun1_is "chris") {
         : become "chris";
         : set_theme "chris" ;

      }
   }

}

on_tick {
   : gosub "npc_movements" ;
}

subroutines {

   npc_movements : subroutine {
      : if  (my_counter==1) {
         : create "barry" target = "room_4" ;
         : create "sally" target = "room_2" ;
      }
      : else_if (my_counter==2) {
         : create "barry" target = "room_3" ;
         : create "sally" target = "room_1" ;
      }
      : else_if (my_counter==3) {
         : create "barry" target = "room_2" ;
         : create "sally" target = "room_2" ;
      }
      : else_if (my_counter==4) {
         : create "barry" target = "room_1" ;
         : create "sally" target = "room_3" ;
      }
      : else_if (my_counter==6) {
         : create "barry" target = "room_2" ;
         : create "sally" target = "room_4" ;
         : set_integer var = "my_counter"  value = "0" ;
      }

      : increment "my_counter" ;

      // PRINTS NPC ROAMING MOVEMENTS FOR ALL NPCS
      : print_npc_movements ;
   }

}
themes {
   chris : theme {
      lister_objects {
         include_characters = true
      }
      status_bar {
         : fixed_text "" ;
         : dynamic_text "protagonist_text" ;
      }
      colors {
         status_bar_paper = 1
         status_bar_pen   = 14
         incidental_pen   = 12
      }
   }

   mark : theme {
      extends = chris
      colors {
         status_bar_paper = 2
      }
   }

}
nww02 commented 3 years ago

What would be very useful would be to be able to enumerate the exits to do things with. I don't know if it's possible. But one thing you could do is have randomly moving NPC.....

on_tick
{
    // Allow NPCs to linger in their current location for some turns.
    // have a timer that ticks down. When it hits zero, they move if you're not standing next to them.

    :decrement "npc_move_timer";
    :if (npc_move_timer > 0 ) { :return;}

    // where is the NPC now?
    :set_string var = "last_npc_location" { expression -> (parent_of("NPC")) }

    // Where can it move to?  this would be a map, I assume.
    :collection_create {       source -> (exits_of(last_npc_location))     list="possible_exits"        };

   // Pick one at random
    :set_integer var="random_direction" {(     random( collection_count "possible_exits")     )};

   // Get the name of the location in that direction.
    :set_string var="new_location" {( collection_get {
                                                   collection = "possible_exits"
                                                   index -> (random_direction)
                                                   }    )};

    // move the NPC to the new location if you're not standing next to it.
     if ( !is_beside "NPC" )
     {
        :create {entity -> ("NPC") target->(new_location)};
     }

    // reset the NPC's linger timer.
    :set_integer "npc_move_timer"   {(20)};

}

The alternative, using a beefed-up version of "is_can_go" would also work, I guess, if we could sent objects in a numerical direction, or (once again) find the target location of a connection in a numerical direction.