Forum

Entity List?

Discuss Artificial Intelligence and Bot programming.

Moderator: InsideQC Admins

Entity List?

Postby blubswillrule » Tue Jan 25, 2011 6:30 am

I know i've asked for help on here before, to no success, but this one I REALLY need help on.

basically, i've been working on a pathfinding system for the zombies of nzp (Nazi Zombies: Portable), and I must say, it works quite nicely, but there is one problem...
when finding a path, it sets each waypoint's .MARK value to TRUE, so the zombie doesn't check that waypoint again, but the problem is,
this is global, per say, if one zombie marks a waypoint, then another zombie can't see that waypoint.(yes, I have gotten' around this, but it still arouses more complex problems)

I need a better way to mark waypoints, specifically
I need a way to store a theoretical list of entities in qc.

with functions such as
add_to_list ( list, entity that is being added)
clear_list (list)
and
check_if_entity_is_on_list (list, entity being checked for)

but now the real problem is, is that I have no clue how to make such a list possible.

any ideas? PLEASE help, i've honestly been' working on this for over 2 weeks, everyday nonstop, and to think that i'm so close...
it's nerve racking.

I know some of you could also use this for a mod of your own as well, so please, help

(for those of you who don't know, this pathfinding system is a way for the zombies to ALWAYS find you, travel to you, (using waypoints) and attack you)

sincerely, Blubswillrule
A truly rewarding experience for an AI coder: watching your ai navigate the map... makes all the time invested in the code worth it :)
User avatar
blubswillrule
 
Posts: 68
Joined: Mon Oct 04, 2010 9:08 pm
Location: Lincoln, California

Postby silverjoel » Tue Jan 25, 2011 7:16 am

Have you tried something like .float MARKCHECK? That would make every true false value local to the entity.

Here's a little bit of code I made to do a tracker entity. I was sick of seeing a monster not go through a doorway and instead running along the wall on the oppisite side.

void() monster_chase =
{

if(enemy_vis)
{
self.tracker = self.enemy.origin;
self.goalentity = self.enemy;
self.trackcheck = 1;
remove(self.track);
}
else
{
if (self.trackcheck == 1)
{
self.track = spawn();
self.track.origin = self.tracker;
self.track.owner = self;
self.track.solid = SOLID_NOT;
self.track.movetype = MOVETYPE_NONE;
setmodel (self.track, "");
setsize(self.track, '0 0 0', '0 0 0');

self.goalentity = self.track;

self.trackcheck = 0;
}
}

if (vlen(self.track.origin - self.origin) < 50)
{
remove(self.track);
self.goalentity = self.enemy;
}
};

It created a entity at the last place it saw the enemy and went to that origin instead of the enemy origin. It worked alright.

Maybe this can help.
silverjoel
 
Posts: 46
Joined: Thu Sep 30, 2010 6:46 am

Postby blubswillrule » Tue Jan 25, 2011 7:25 am

hmm, nice code, i'll have to read that in-depth to extract it's juicyness :P

anyways,as for the .floats, well, I used .floats

but I believe (AND PLEASE CORRECT ME IF I'M WRONG)
that
self.way.MARK ============== self.mark
^^from zombies perspective______^^from waypoints perspective,

and since the waypoints must be global, then it won't nescessarily work :\ ... that is, if i'm right.

the example code that you showed me, (although as awesome as it is), isn't quite what i'm trying to achieve, you see, I need the zombie to be able to go to the player, regardless of whether it has seen the player or not, no matter where the player is on the map.
A truly rewarding experience for an AI coder: watching your ai navigate the map... makes all the time invested in the code worth it :)
User avatar
blubswillrule
 
Posts: 68
Joined: Mon Oct 04, 2010 9:08 pm
Location: Lincoln, California

Postby silverjoel » Tue Jan 25, 2011 7:27 am

It actually might be something you could use. You could spawn a temporary entity at the origin of the waypoint and use it as the place to go. When you reach it, just remove it and spawn the next one.

The enemy_vis stuff can be taken out.
silverjoel
 
Posts: 46
Joined: Thu Sep 30, 2010 6:46 am

Postby blubswillrule » Tue Jan 25, 2011 7:57 am

ahh, now see, the problem isn't going to the next waypoint, the problem comes in searching for the correct path of waypoints

basically what I have is...

Code: Select all
void(entity way) wayenqueB =
{
   bprint ("wayenque B! \n");
   setmodel(way, "progs/radio.mdl");
   if (way.owner1 != world)
   {   
      bprint("way.owner1 is not world! \n");
      if (way.owner1.MARK == FALSE)
      {
         if (way.owner1 == self.cway)// USED TO BE == SELF.GOALWAY, BUT WE ARE NOW GOING BACKWARDS WITH FINDING THE TREE, IT WILL BE OF HELP TO US LATER!
         {
            bprint ("we found the zombie's cway with enque B! \n");
            way.owner1.owner = way;
            foundgoalway(way.owner1);
            return;
         }
         if(way.owner1 != self.cway)
         {
         bprint("way.owner1 is not marked! \n");
         
         way.owner1.MARK = TRUE;
         way.owner1.owner = way;
         wayenqueA (way.owner1);
         return;
         }
      }
   }
   
   if (way.owner2 != world)
   {
      bprint("way.owner2 is not world! \n");
      if (way.owner2.MARK == FALSE)
      {
         if (way.owner2 == self.cway)// USED TO BE == SELF.GOALWAY, BUT WE ARE NOW GOING BACKWARDS WITH FINDING THE TREE, IT WILL BE OF HELP TO US LATER!
         {
            bprint ("we found the zombie's cway with enque B! \n");
            way.owner2.owner = way;
            foundgoalway(way.owner2);
            return;
         }
         
         if(way.owner2 != self.cway)
         {

         bprint("way.owner2 is not marked! \n");
         
         way.owner2.MARK = TRUE;
         way.owner2.owner = way;

         wayenqueA (way.owner2);
         return;
         }
      }
   }
   if (way.owner3 != world)
   {
      bprint("way.owner3 is not world! \n");
      if (way.owner3.MARK == FALSE)
      {
         if (way.owner3 == self.cway)// USED TO BE == SELF.GOALWAY, BUT WE ARE NOW GOING BACKWARDS WITH FINDING THE TREE, IT WILL BE OF HELP TO US LATER!
         {
            bprint ("we found the zombie's cway with enque B! \n");
            way.owner3.owner = way;
            foundgoalway(way.owner3);
            return;
         }
         if(way.owner3 != self.cway)
         {

         bprint("way.owner3 is not marked! \n");
         
         way.owner3.MARK = TRUE;
         way.owner3.owner = way;
         wayenqueA (way.owner3);
         return;
         }

      }
   }
   if (way.owner4 != world)
   {
      bprint("way.owner4 is not world! \n");
      if (way.owner4.MARK == FALSE)
      {
         if (way.owner4 == self.cway)// USED TO BE == SELF.GOALWAY, BUT WE ARE NOW GOING BACKWARDS WITH FINDING THE TREE, IT WILL BE OF HELP TO US LATER!
         {
            bprint ("we found the zombie's cway with enque B! \n");
            way.owner4.owner = way;
            foundgoalway(way.owner4);
            return;
         }
         if(way.owner4 != self.cway)
         {
         bprint("way.owner4 is not marked! \n");
         
         way.owner4.MARK = TRUE;
         way.owner4.owner = way;
         if (way.owner4 == self.cway)
         wayenqueA (way.owner4);
         return;
         }
      }
   }
   if (way.owner1 == world || way.owner1.MARK ==TRUE)
   {
      if (way.owner2 == world || way.owner2.MARK == TRUE)
      {
         if (way.owner3 == world || way.owner3.MARK == TRUE)
         {
            if (way.owner4 == world || way.owner4.MARK == TRUE)
            {
               bprint ("DEAD LINK!, RESTARTING! \n");
               if (way.owner != world)
                  wayenqueA(way.owner);
               return;
            }
         }
      }
   }
               

};



woah, that was long, lol

note: wayenqueB and wayenqueA are the same, they simply loop each other
what this does, is checks the current waypoint to make sure it's not the goal (if it is, end the function and tell the zombie to follow the goals owner)
and if it's not, AND IF IT'S NOT MARKED
it will simply do wayenque with the main way's corresponding link.

the problem comes with the
Code: Select all
if (way.MARK == FALSE)


I would like for each zombie to have it's own list of waypoints that it has checked instead,

actually, it's interesting

how this works, is it starts at the players waypoint (waypoint closest to the player),

and it basically builds a theoretical "tree", by searching the player's waypoint's links, then searching it's link's links, and so on, until it finds the zombies current waypoint, this method actually seems to work fairly well, but... as you may have noticed,

if checks owner1 first, then owner2, then owner3, then owner4

so fine, it will check 1 first, then when it reaches a dead end, it will backtrack through the tree one waypoint at a time, till it finds a linked waypoint THAT IS NOT MARKED (that it hasn't checked), and continues this...
now the problem with this, is marking the waypoints, like I said, I would like for the zombies to keep a list of the waypoints they have checked, but I have no clue on how to make a "entity list"

note: going to the next waypoint is no problem :)
another note: the setmodel part is so I can simply see which waypoints the zombie has checked, and sure enough, only the link 1's get checked because of m faulty marking system.
A truly rewarding experience for an AI coder: watching your ai navigate the map... makes all the time invested in the code worth it :)
User avatar
blubswillrule
 
Posts: 68
Joined: Mon Oct 04, 2010 9:08 pm
Location: Lincoln, California

Postby silverjoel » Tue Jan 25, 2011 3:11 pm

I haven't really messed with entity lists or waypoints. Have you looked at the tutor bot stuff?

Here's a link to adding waypoint
http://www.quakewiki.net/archives/aicaf ... ypoint.htm

Here's the page of tutorials
http://www.quakewiki.net/archives/aicaf ... l/main.htm
silverjoel
 
Posts: 46
Joined: Thu Sep 30, 2010 6:46 am

Postby blubswillrule » Tue Jan 25, 2011 3:26 pm

sweet, thanks, i'll look into it and see if theres anything on lists, or a better way to do what I want.

Although I think I remember that waypoint tutorial from a while back, that's not to say there isn't anything useful in the rest of it ;)
A truly rewarding experience for an AI coder: watching your ai navigate the map... makes all the time invested in the code worth it :)
User avatar
blubswillrule
 
Posts: 68
Joined: Mon Oct 04, 2010 9:08 pm
Location: Lincoln, California

Postby blubswillrule » Tue Jan 25, 2011 11:58 pm

repost, didn't find anything on there

anybody have any ideas on how to have a list of entities in quake?
without regards to AI, just in general.

like, one entity owns a list
you can add entities to that list
you can clear the list
you can check if an entity is on the list.

any ideas on how to make this? I REALLY need help, please :(
A truly rewarding experience for an AI coder: watching your ai navigate the map... makes all the time invested in the code worth it :)
User avatar
blubswillrule
 
Posts: 68
Joined: Mon Oct 04, 2010 9:08 pm
Location: Lincoln, California

Postby frag.machine » Wed Jan 26, 2011 1:13 am

blubswillrule wrote:repost, didn't find anything on there

anybody have any ideas on how to have a list of entities in quake?
without regards to AI, just in general.

like, one entity owns a list
you can add entities to that list
you can clear the list
you can check if an entity is on the list.

any ideas on how to make this? I REALLY need help, please :(



Pretty much the same way you would in C: using pointers.
Code: Select all
// WARNING: UNTESTED, MAY CONTAIN LOTS OF BUGS,
// USE AT YOUR OWN RISK!!!!!1ONE1.

// let's add some custom entity fields
.entity parent;
.entity link;

// adds a child to p
void (entity p, entity c) addChild =
{
  c.parent = p;
  if (p.link != world)
  {   
    c.link = p.link;
  }
  else
  {
    c.link = world;
  }

  p.link = c;
};

// clears all p children
void (entity p) clearChildren =
{
  local entity ptr = p.link;

  while (ptr != world)
  {   
    ptr.parent = world;
    ptr = ptr.link;
  }
};

// checks if c exists in p children list
float (entity p, entity c) containsChild =
{
    return (c.parent == p);
};
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC :) (LordHavoc)
User avatar
frag.machine
 
Posts: 2031
Joined: Sat Nov 25, 2006 1:49 pm

Postby blubswillrule » Wed Jan 26, 2011 3:49 am

dude!, oh my god, thank you!
my pathfinding now works now :D
although it is a little bit slow (mainly because I added delays for things, because I don't want to have a runaway loop counter :P)

one thing, although not sure if this matters.

I changed this...
Code: Select all
void (entity p) clearChildren =
{
  local entity ptr = p.link;

  while (ptr != world)
  {
    ptr.parent = world;
    ptr = ptr.link;
  }
};

to...

Code: Select all

void (entity p) clearChildren =
{
  local entity ptr = p.link;

  while (ptr != world)
  {
    ptr.parent.link = ptr.link;//*******
    ptr.parent = world;
    ptr = ptr.link;
  }
};


the ptr.parent.link line
so it actually kinda' takes off the current ptr, then ptr's parent is linked to ptr's link

otherwise, it would give me a runaway loop counter

well, now, off to fix my one crash-causing bug...
of stack overflows lol

but again, thanks so much :)
A truly rewarding experience for an AI coder: watching your ai navigate the map... makes all the time invested in the code worth it :)
User avatar
blubswillrule
 
Posts: 68
Joined: Mon Oct 04, 2010 9:08 pm
Location: Lincoln, California

Postby blubswillrule » Mon May 02, 2011 8:47 pm

Sorry for reviving the topic, but looking back at the code you gratefully gave me, made me wonder, do the entities.linklist affect the ACTUAL entities linklist, or the OWNER OF THE LISTS linklist?

I need to have different lists of the same entities. (If they affect the actual objects' linklist, then the different lists would interfere with each other and make this not useable :\ )
A truly rewarding experience for an AI coder: watching your ai navigate the map... makes all the time invested in the code worth it :)
User avatar
blubswillrule
 
Posts: 68
Joined: Mon Oct 04, 2010 9:08 pm
Location: Lincoln, California

Postby frag.machine » Tue May 03, 2011 12:48 am

As long the different lists have different parents, I don't see any problems.
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC :) (LordHavoc)
User avatar
frag.machine
 
Posts: 2031
Joined: Sat Nov 25, 2006 1:49 pm

Postby Spike » Tue May 03, 2011 4:11 am

if you modify the objects to create the list, you can only add that object to one list.

you can have multiple things refering to the same list, you can have additional lists which lead on to the aforementioned list, but if you have a single 'next' pointer, you only have a single next pointer.

so a list of simple node objects that purely refer to the real object and the next node will work. will take a lot of memory, one per ent, but it'll work.

If you're okay with maximum list sizes, you may wish to consider using some sort of field array in a qcc that supports it.
Spike
 
Posts: 2853
Joined: Fri Nov 05, 2004 3:12 am
Location: UK

Postby blubswillrule » Wed May 04, 2011 6:13 am

Yeah, I guess I could just go with maximum entity list sizes, because I'm using this for storing waypoint paths, and I'm pretty sure either a) by the time the ai reaches the end of the list, it will have recalculated it's path, and b) if it just reaches the end, it can just calculate again.

(having the ai check if it's goal is in same relative place, if not, then recalculate path)

thanks for the help!
A truly rewarding experience for an AI coder: watching your ai navigate the map... makes all the time invested in the code worth it :)
User avatar
blubswillrule
 
Posts: 68
Joined: Mon Oct 04, 2010 9:08 pm
Location: Lincoln, California


Return to Artificial Intelligence

Who is online

Users browsing this forum: No registered users and 1 guest