# Colobot Forum - International Colobot Community

Full Version: Finding Powercells that needs charging
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
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(); } } }```
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.
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 ? 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.
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.
So for version Alpha 0.1.6 its impossible to make a program i want to make?
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.

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; }```
Works perfect, thank You!
Now I can go to bed
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?
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.
Thx! it's really good explanation!
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 .
I don't think there is a way to do that. You have to iterate through all objects and check therir .energyCell property.
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
@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.