Colobot Forum - International Colobot Community
Finding Powercells that needs charging - Printable Version

+- Colobot Forum - International Colobot Community (https://colobot.info/forum)
+-- Forum: [Archive] New forum (2015-2019) (https://colobot.info/forum/forumdisplay.php?fid=76)
+--- Forum: Colobot: Gold Edition Basics (https://colobot.info/forum/forumdisplay.php?fid=58)
+---- Forum: General (https://colobot.info/forum/forumdisplay.php?fid=59)
+---- Thread: Finding Powercells that needs charging (/showthread.php?tid=591)



Finding Powercells that needs charging - Jono - 04-09-2015

How do I get a grabber to only collect Powercells that needs to be charged?

Code:
extern void object::Findandcharge()
{
object item;
while(true)
{

item=radar(PowerCell);

while ( item.energyLevel < 1 )
{
goto(item.position);
grab();
}
}
}



RE: Finding Powercells that needs charging - tomaszkax86 - 04-09-2015

Hello.

Problem of finding and recharging power cells can be divided in two parts. First one is to find all power cells that need to be recharged. Second, recharge all found power cells.

First part is to make a list for power cells. We can use empty list of objects to store them:

Code:
// list of power cells to recharge
object[] list;

To find all power cells we need to use retobject() function. We need to iterate over all objects in the world, see if given object is power cell, whether it is carried by something else and, finally, if it needs to be recharged. Then we add it to the list.

Code:
// find all power cells to recharge
for(int i=0, j=0; ; i++)
{
   // next object
   object item = retobject(i);

   // no more items
   if(item == null) break;

   // item is not power cell
   if(item.category != PowerCell) continue;

   // power cell was put in some other object
   if(item.position.x == nan) continue;

   // power cell has less than 100% energy
   if(item.energyLevel < 1.0)
   {
      // add to list
      list[j++] = item;
   }
}

Then we actually recharge all power cells. We iterate over our list, find each power cell and recharge it:

Code:
// recharge all power cells
for(int i=0; i<sizeof(list); i++)
{
   // take next power cell
   object item = list[i];
   goto(item.position);
   grab();

   // find and go to power station
   item = radar(PowerStation);
   goto(item.position);

   // recharge power cell
   while(this.load.energyLevel < 1.0)
   {
       wait(0.1);
   }

   // find free space and drop power cell
   goto(space());
   drop();
}

If you put together all the above code, you get complete solution to your problem. I hope that helped.


RE: Finding Powercells that needs charging - krakers - 12-04-2015

Hello,

Im quite new in programming (last time i was trying 10 years ago - in Colobot too) and i have problem with my program. I have no idea how to solve it.
I want it to:
1) find fully charged NuclearCell and grab it
2) find a robot with empty NuclearCell, go there
3) exchange him Cell to fresh one

So i wrote that code:
Code:
extern void object::Power_Rescue()
{
while (true)
{
if (this.load != null)
{
goto(space(position));
drop();
}

FindFullCell();
FindEmptyCell();  
ChangeCell();
wait(10);
}
}

void object::FindFullCell()
{
while (true)
{
object[] list;

for (int i=0, j=0;; i++)
{
object item = retobject(i);
if (item == null) break;
if (item.category != NuclearCell) continue;
if (item.position.x == nan) continue; // jesli ogniwo nie jest w robocie
if (item.energyLevel == 1)
{
list[j++] = item;
}
}

for (int i=0; i < sizeof(list); i++)
{
object item = list[i];
goto(item.position);
grab();
break;
}
break;
}

}

void object::FindEmptyCell()
{
object item;
int j;
object[] list;

for (int i=0, j=0;; i++)
{
object item = retobject(i);
if (item == null) break;
if (item.category != NuclearCell) continue;
if (item.position.x != nan) continue; // jesli ogniwo nie jest w robocie
if (item.energyLevel < 0.1)
{
list[j++] = item;
}
}

for (int i=0; i < sizeof(list); i++)
{
object item = list[i];
goto(item.position);
}
}

void object::ChangeCell()
{
turn(90);
drop();  
turn(-90);  
grab();
turn(-90);
drop();
turn(180);    
grab();
turn(-90);
drop();
}
So, FindFullCell works fine and the problem is with FindEmptyCell - it finds a cell with position.x == null, so that cell is installed in robot and that's good. But how the robot can goto robot's position, while the position (of cell) == null ? Big Grin How to get a position of the robot?

P.S. I know there may be a lot of bugs in program and maybe it's not well iptimized but its my third day, so I'm just a begginer.


RE: Finding Powercells that needs charging - melex750 - 12-04-2015

This seems like a good place to mention the new radarall() function, dev version only, for now.

object[] list;
list = radarall(PowerCell); // returns all PowerCells on the ground.


RE: Finding Powercells that needs charging - krakers - 12-04-2015

So for version Alpha 0.1.6 its impossible to make a program i want to make?


RE: Finding Powercells that needs charging - melex750 - 12-05-2015

It's not impossible.

I'm testing your program now.

Your program needs to be modified to search for a "robot" which has an empty PowerCell.

Wow that was tough. I re-wrote most of it. Tell me if you find any bugs. Smile

Code:
extern void object::Power_Rescue()
{
    while (true)
    {
        if (this.load != null)
        {
            goto(space(position));
            drop();
        }
        
        FindObjectReplaceCell();  
        if (this.load != null) continue;
        wait(10);
    }
}

void object::GrabNearestFullCell()
{
    object item, NearestItem = null;
    int i = 0;
    while (true)
    {
        item = retobject(i++);
        if (item == null) break;
        if (item.category != NuclearCell) continue;
        if (item.position.x == nan) continue;
        if (item.energyLevel == 1)
        {
            if (NearestItem == null)
            {
                NearestItem = item;
                continue;
            }
            if (distance(this.position, item.position) < distance(this.position, NearestItem.position) )
            {
                NearestItem = item;
            }
        }
    }
    if (NearestItem == null) return; // did not find an item
    goto(NearestItem.position);
    grab(InFront);
    return;
}

void object::ChangeCell()
{
    drop(Behind);  
    grab(InFront);
    
    turn(-90);  
    drop(InFront);
    turn(90);    
    
    grab(Behind);
    drop(InFront);
    
    turn(-90);
    grab(InFront);
}


void object::FindObjectReplaceCell()
{
    object item;
    int i = 0, t = 0;
    float speed;
    
    int types[];
    types[t++] = WheeledShooter;
    types[t++] = WheeledGrabber;
    types[t++] = TrackedGrabber;
    
    while (true)
    {
        item = retobject(i++);
        if (item == null) break;
        for (int k = 0; k < sizeof(types); k++)
        {
            if (item.category == types[k])      // must be in the list
            {
                if (item.id == this.id) break; // <--------- not this bot
                if (item.energyCell == null)
                {
                    message("INFO: "+item.category+" Has No energyCell");
                    break; //<--------------------------------------- must have an energyCell
                }
                if (item.energyCell.energyLevel < 0.1)
                {
                    if (item.velocity.x != nan)
                    {
                        speed =  abs(item.velocity.x);
                        speed += abs(item.velocity.y);
                        speed += abs(item.velocity.z);
                    } else speed = 0.0;
                    
                    if (speed != 0.0 and item.altitude > 0.0) break;// not moving or flying
                    GrabNearestFullCell();
                    if (this.load == null) return; // did not find a FuelCell
                    goto(item.position);
                    ChangeCell();
                    return;
                }
            }
        }
    }
    return;
}



RE: Finding Powercells that needs charging - krakers - 12-05-2015

Works perfect, thank You!
Now I can go to bed Big Grin


RE: Finding Powercells that needs charging - clop1000 - 05-03-2016

melex750 excellent job!

But - what is the meaning of this part of code? -
if (item.velocity.x != nan)
{
speed = abs(item.velocity.x);
speed += abs(item.velocity.y);
speed += abs(item.velocity.z);
} else speed = 0.0;



And for what purpose do you use line with - return; and nothing more? What is it doing?


RE: Finding Powercells that needs charging - tomaszkax86 - 05-03-2016

Quote:if (item.velocity.x != nan)
{
speed = abs(item.velocity.x);
speed += abs(item.velocity.y);
speed += abs(item.velocity.z);
} else speed = 0.0;

This code calculates linear speed of some object, although it's not a mathematically correct code. Properly, linear velocity is a square root of sum of squares of velocity components in all dimensions, so:

Code:
float vx = item.velocity.x;
float vy = item.velocity.y;
float vz = item.velocity.z;

float speed = sqrt(vx * vx + vy * vy + vz * vz);

Comparing a value for NaN is necessary because some objects have invalid velocity.

If you want linear velocity in horizontal plane, just skip third component Z.

return without value is used to return from void function, but it's not necessary to put it at the end of function because it doesn't do anything.


RE: Finding Powercells that needs charging - clop1000 - 05-05-2016

Thx! it's really good explanation!


RE: Finding Powercells that needs charging - clop1000 - 07-05-2016

Is there any way to get a reference on the holder of PowerCell?
For instance - i got a list of PowerCells, and i want tot know, which of them are installed in bots.
object.load - does not work properly .


RE: Finding Powercells that needs charging - krzys_h - 07-05-2016

I don't think there is a way to do that. You have to iterate through all objects and check therir .energyCell property.


RE: Finding Powercells that needs charging - radioactivity - 07-05-2016

There is a way, but you'd need identify to Power Cell as one that's being hold (By position.x == NaN (?)), then save it's id, and then sift though every object and check if it has load, and if yes then what's its id


RE: Finding Powercells that needs charging - melex750 - 07-05-2016

@clop1000 ,
This  program can get the holder of any object that can be carried.
Code:
extern void object::Example()
{
    // list of objects that can be carried
    object obj[];
    
    // ...fill the list...
    
    object holder = GetOwnerOf( obj[0] );
    
        // if this robot has obj[0]
    if (holder == this) /* do stuff */ ;
    
        // if obj[0] is on the ground   or obj[0] == null
    else if (holder == null) /* do stuff */ ;
    
        // if obj[0] is in battery slot of holder
    else if (obj[0] == holder.energyCell ) /* do stuff */ ;
    
        // if obj[0] is carried in claw of holder
    else if (obj[0] == holder.load ) /* do stuff */ ;
}

public object object::GetOwnerOf(object obj)
{
    if (obj == null) return null;
    if (obj.position.x != nan) return null; // obj is on the ground
    
    if (obj == this.energyCell) return this;
    if (obj == this.load) return this;
    
    int types[] = ObjectHolders();
    object objList[] = radarall(types); // find all object holders
    int numObjs = sizeof(objList);
    
    for (int i = 0; i < numObjs; i++)   // check if one holds obj
    {
        if (obj == objList[i].energyCell) return objList[i];
        if (obj == objList[i].load) return objList[i];
    }
    return null;
}

int[] ObjectHolders()
{
    int i=0;
    int list[];
    list[i++] = WingedGrabber;
    list[i++] = TrackedGrabber;
    list[i++] = WheeledGrabber;
    list[i++] = LeggedGrabber;
    list[i++] = WingedShooter;
    list[i++] = TrackedShooter;
    list[i++] = WheeledShooter;
    list[i++] = LeggedShooter;
    list[i++] = WingedOrgaShooter;
    list[i++] = TrackedOrgaShooter;
    list[i++] = WheeledOrgaShooter;
    list[i++] = LeggedOrgaShooter;
    list[i++] = WingedSniffer;
    list[i++] = TrackedSniffer;
    list[i++] = WheeledSniffer;
    list[i++] = LeggedSniffer;
    list[i++] = Thumper;
    list[i++] = PhazerShooter;
    list[i++] = Recycler;
    list[i++] = Shielder;
    list[i++] = Subber;
    list[i++] = DefenseTower;
    list[i++] = ResearchCenter;
    list[i++] = PowerPlant;
    list[i++] = NuclearPlant;
    list[i++] = AutoLab;
    //list[i++] = AlienWasp; // wasp can carry objects too
    return list;
}
This can also be done with a method called on the object, but that is slightly more complicated.