Oryginalna strona colobot.cba.pl umarła, gdy cba.pl przestało oferować darmowy hosting. To jest statyczny mirror, pobrany w 2018. ~krzys_h
 
Polski Portal COLOBOTa
COLOBOT Polish Portal

Eliminacja obcych - AlienKiller2

Bartek c++ - 22-12-2009, 11:49
Temat postu: AlienKiller2
To drugi program z serii AlienKiller
Sam idzie do naprawy i do ładowania gdy to potrzebne i jeszcze załatwiajaja obcych.
Kod:
extern void object::AlienKiller2()
{

while ( true )
{
object wrog,repair,power;
float A,B,alfa;
int alien[];
alien[0] = AlienAnt;
alien[1] = AlienSpider;
alien[2] = AlienWasp;
alien[3] = AlienWorm;
alien[4] = AlienEgg;
wrog = radar(alien);
repair = radar(RepairCenter);
power = radar(PowerStation);
while ( shieldLevel < 0.4 )
{
goto(repair.position);
wait(10);
}
while ( energyCell.energyLevel < 0.4 )
{
goto(power.position);
wait(10);
}
turn(direction(wrog.position));
motor(1,1);
if(position.z > wrog.position.z +35)
{
jet(-0.9);
}

if(position.z < wrog.position.z - 1)
{
jet(0.8);
}
wait(1);
A = wrog.position.z-position.z;
B = distance2d(position,wrog.position)-1.5;
alfa = atan(A/B);
if (distance(position, wrog.position) < 42)
{
aim(alfa-2);
turn(direction(wrog.position));
motor(0.6,0.6);
fire(0.5);
wait(4); 
if ( wrog == null)
{
message("wszystkie szkodniki zestrelone",3);
goto(repair.position);
break;
}
}






}
}

Berserker - 22-12-2009, 17:56

Bez sensu, bez sensu i kompletny brak sensu.
Najpierw sprawa z naprawa i ladowaniem sie. Pomine milczeniem czekanie 10s, to bylo juz duzo razy walkowane. Ale to pochopnie wstawione errmode(0) bedzie zguba robota, jesli stacja naprawcza badz energetyczna bedzie zajeta. Robot pewnie po prostu stanie w miejscu i bedzie czekal. Prawdopodobnie az go mrowki zalatwia.
Po co definiujesz zmienne dopiero w petli? Zmienne i stale lepiej sie definiuje przed petla, wtedy nie ma takiego balaganu.
Zamiast bezsensownie porownywac swoja wysokosc z wysokoscia mrowki lepiej skorzystac ze swojej wysokosci nad poziomem gruntu.
Polecam rowniez zastanowic sie nad tym co ma robic robot kiedy juz moze strzelic oraz zdefiniowac kiedy moze strzelic :)

FE4R - 22-12-2009, 20:59

Tak tak Bartek. Wciąż jest kilka problemów do rozwiązania.

Kod:
errmode(0);

Niepotrzebne kompletnie. Robot to nie owad, a błędy pomogą Ci udoskonalić program.

Kod:
object wrog;
wrog = radar(alien);
turn(direction(wrog.position));

A co, jeśli wroga nie ma? Można odpalić program, a robot sam poczeka, aż coś wykryje.
Dodatkowo ten turn(direction(wrog.position));. Nauczcie się ludzie dawać zmianę kierunków w funkcji motor();. To jest nawet opisane w Ćwiczeniach, lecz postaram się dać pewien rysunek. Może pomóc. ;)



Jeśli użyjesz kodu:

Kod:
float dir = direction(Cel1.position);
turn(dir);

Robot najpierw zwróci się w stronę przeciwnika, a potem dopiero ustawi silniki na pełną moc.
Można jednak zrobić to trochę inaczej, aby robot obrócił się płynnie oraz natychmiastowo zareagował na zmianę kierunku:

Kod:
float dir = direction(Cel1.position);

if( dir > 0) motor(1-dir/90, 1);
if( dir < 0) motor(1, 1+dir/90);

Już wyjaśniam. Jak pewnie wiesz, w Colobocie są kąty tylko do 180 stopni. Kąt +180 stopni to kąt w lewo, a kąt -180 stopni to kąt w prawo. Dlatego używając warunku if() sprawdzamy, czy obiekt jest po lewo(dir > 0) czy po prawo (dir < 0). Jeśli jest w jednym z tych kierunków, robot ustawi moc silników w zależności od kąta. Biorąc z rysunku:

Jeśli dir = 120, to dir/90 = 1.3. A więc, jeśli cel jest po lewo, sterowanie silnikiem będzie wyglądało tak: motor(-0.3, 1); i robot będzie zwracał się w lewo, póki cel nie znajdzie się na środku celownika. Oczywiście cały czas jedzie na pełnych obrotach. Zajmijmy się teraz prawą stroną.

Jeśli dir = -120, to dir/90 = -1.3. Wtedy motor() będzie wyglądał tak: motor(1, -0.3); i robot skręci w prawo. Zależnie, jak duży jest kąt, robot będzie skręcał powoli / szybko. Można również dostosować to zamieniając dir/90 na dir/40. Nie polecam schodzić poniżej dir/20, gdyż potem robot zaczął latać do tyłu. :lol:
Dla uproszczenia powiem, że:

Kod:
if( dir > 0) motor(1-dir/90, 1);
if( dir < 0) motor(1, 1+dir/90);


to jest to samo co:
Kod:
motor(1-dir/90, 1+dir/90);


Kolejny problem to rozróżnienie, czy obiekt to osa czy obiekt naziemny. Podpatrz sobie rozwiązanie z mojego programu na dole. Wnioskuję, że
Kod:
if(position.z > wrog.position.z +35)
to właśnie nieudana próba dostosowania się do tego.




Sam daję swój program, który niedawno lekko udoskonaliłem. Być może uda Ci się coś z niego podpatrzeć, Bartek. Tym razem dodałem komentarze do wszystkiego, co robot robi. Poczytaj je, żeby zrozumieć rzeczy, których nie wiesz, ewentualnie napisz tutaj. Mam nadzieję, że będzie pomocne.

Kod:
extern void object::ActiveKiller2()
{
    while(true)
    {
        ShieldCheck(); // sprawdz czy uszkodzony
        EnergyCheck(); // sprawdz baterie
       
        int i, list [];
       
        i = 0;
        list[i++] = AlienAnt;
        list[i++] = AlienSpider;
        list[i++] = AlienWorm;
        list[i++] = AlienWasp;
       
        while(radar(list) != null) // jesli wykryto wroga
        {
            ShieldCheck(); // sprawdzaj stan oslony za kazdym podejsciem do wroga
            EnergyCheck(); // sprawdzaj stan baterii za kazdym podejsciem do wroga
           
            object enemy = radar(list);
           
            if(enemy.category == list[3]) // jesli wrog to osa
            {
                ActiveWaspKiller(); // zastosuj funkcje do zabijania os
            }
            else // jesli naziemny
            {
                ActiveLandKiller(); // zastosuj funkcje do zabijania mrowek
            }
        }
       
        motor(0,0); // jesli nie wykryto zatrzymaj sie
        jet(0);
        wait(1); // i czekaj...
    }
}

void object::ActiveWaspKiller() // funkcja do zabijania os
{
    object wasp = radar(AlienWasp); // zmienne...
    float h, d, dir;
   
    if(altitude < wasp.altitude) // jesli osa jest wyzej...
    {
        jet(0.5); // wznies sie...
    }
   
    if(altitude > wasp.altitude) // jesli nizej...
    {
        jet(-0.5); // opadnij...
    }
   
    h = wasp.position.z - position.z; // zmienne...
    d = distance2d(position, wasp.position);
   
    aim(atan(h/d)); // celuj w ose
   
    dir = direction(wasp.position);
   
    motor(1-dir/40, 1+dir/40); // ustaw silniki
   
    if(distance(position, wasp.position) < 40) // jesli osa jest w zasiegu
    {
        if(dir < 5 && dir > -5) // jesli jest na celowniku
        {
            fire(0.1); // strzelaj
            wait(0.4);
        }
    }
   
    if(temperature == 1) // jesli silnik sie przegrzal
    {
        do
        {
            jet(-1); // zatrzymaj sie
            motor(0,0);
        }
        while(temperature != 0); // az ostygnie
    }
}

void object::ActiveLandKiller() // funkcja do zabijania mrowek
{
    int list[], i = 0;
   
    list[i++] = AlienAnt;
    list[i++] = AlienSpider;
    list[i++] = AlienWorm;
   
    object enemy = radar(list);  // zmienne...
    float h, d, dir, posZ, pitchK;
   
    posZ = position.z - topo(position);
   
    if(posZ < 8) // jesli wysokosc lotu jest mniejsza niz 8
    {
        jet(0.5); // wznies sie
    }
   
    posZ = position.z - topo(position);
   
    if(posZ > 12) // jesli wysokosc lotu jest wieksza niz 12
    {
        jet(-0.5); // opadnij
    }
   
    h = enemy.position.z - position.z; // zmienne...
    d = distance2d(position, enemy.position);
   
    dir = direction(enemy.position); // poprawka na celowanie
    pitchK = pitch*cos(dir) - roll*sin(dir);
   
    aim(atan(h/d) - pitchK); // celuj w mrowke
   
    motor(1-dir/40, 1+dir/40); // ustaw silniki
   
    if(distance(position, enemy.position) < 40) // jesli jest w zasiegu
    {
        if(dir < 5 && dir > -5) // jesli jest na celowniku
        {
            fire(0.1); // strzelaj
        }
       
        if((atan(h/d) - pitchK) < -25) // jesli jest za blisko - nie trafi
        {
            jet(0);
            motor(1,1);
           
            do wait(0.1); while((atan(h/d) - pitchK) >= -25); // poczekaj az sie oddali
           
        }
    }
   
    if(temperature == 1) // jesli silnik sie przegrzal
    {
        jet(0); // zatrzymaj sie
        motor(0,0);
       
        do wait(0.1); while(temperature != 0); // poczekaj az ostygnie
    }
}

void object::ShieldCheck() // sprawdzaj oslone
{
    if(shieldLevel < 0.5) // jesli jest naruszona
    {
        object spot = radar(RepairCenter);
       
        if(spot != null) // jesli warsztat istnieje
        {
            errmode(0);
            int err = goto(spot.position); // jesli warsztat jest wolny
            errmode(1);
           
            if(err != 0) // jesli jest zajety, zatrzymaj sie 4 metry od warsztatu i czekaj
            {
                turn(direction(spot.position));
               
                errmode(0);
                move(distance(position, spot.position) -4);
                errmode(1);
               
                do
                {
                    wait(1);
                   
                    errmode(0);
                    goto(spot.position);
                    errmode(1);
                }
                while(err != 0);
            }
           
            do
            {
                wait(2);
            }
            while(shieldLevel != 1); // czekaj az naladuje oslone
        }
    }
}

void object::EnergyCheck() // sprawdzaj baterie
{
    if(energyCell.category == NuclearCell) // jesli atomowka
    {
        if(energyCell.energyLevel < 0.1) // jesli wyczerpana
        {
            motor(0,0); // zatrzymaj
            jet(0);
           
            message("Potrzebuje ogniwa! Pozycja: x: "+position.x+" y: "+position.y); // wezwij pomoc
           
            do wait(1); while(energyCell == null || energyCell.energyLevel != 1); // czekaj
        }
    }
    else // jesli normalne ogniwo
    {
        if(energyCell.energyLevel < 0.3) // jesli wyczerpane
        {
            object px = radar(PowerStation);
           
            if(px != null) // jesli stacja istnieje
            {
                errmode(0);
                int err = goto(px.position); // jesli nie jest zajeta
                errmode(1);
               
                if(err != 0) // jesli jest zajeta, zatrzymaj sie 4 metry przed i poczekaj
                {
                    turn(direction(px.position));
                   
                    errmode(0);
                    move(distance(position, px.position) -4);
                    errmode(1);
                   
                    do
                    {
                        wait(1);
                       
                        errmode(0);
                        goto(px.position);
                        errmode(1);
                    }
                    while(err != 0);
                }
               
                do
                {
                    wait(2);
                }
                while(energyCell.energyLevel != 1); // poczekaj az sie naladuje
               
            }
            else // jesli stacja nie istnieje
            {
                motor(0,0); // zatrzymaj
                jet(0);
               
                message("Potrzebuje ogniwa! Pozycja: x: "+position.x+" y: "+position.y); // wezwij pomoc
               
                do wait(1); while(energyCell == null || energyCell.energyLevel != 1); // czekaj
            }
        }
    }
}

Berserker - 22-12-2009, 23:22

Cytat:
motor(0,0); // jesli nie wykryto zatrzymaj sie
jet(0);
wait(1); // i czekaj...

Jak czesto robot z takimi instrukcjami laduje w wodzie? :>

FE4R - 22-12-2009, 23:44

Berserker napisał/a:
Cytat:
motor(0,0); // jesli nie wykryto zatrzymaj sie
jet(0);
wait(1); // i czekaj...

Jak czesto robot z takimi instrukcjami laduje w wodzie? :>

Jaką masz wersję Colobota, że Twój robot ma dostęp do mapy terenu w postaci siatki. Nie ma skutecznego sposóbu, aby robot szybko znalazł bezpieczne miejsce do lądowania.

Berserker - 23-12-2009, 09:02

Jak to nie ma? Sa przynajmniej 2, wystarczy troche pomyslec...
FE4R - 23-12-2009, 12:49

A jakiś szybki? Ja wymyśliłem, że robot sprawdzi 9 punktów wokół siebie w zasięgu mocy reaktora, ale zanim to zrobił, chlup do wody.
W ogóle uderzyłeś w najczulszy punkt tego programu. Czuję się zgwałcony. D:

adiblol - 23-12-2009, 12:56

FE4R napisał/a:
Ja wymyśliłem, że robot sprawdzi 9 punktów wokół siebie w zasięgu mocy reaktora, ale zanim to zrobił, chlup do wody.

Jest taka funkcji ipf ...

Berserker - 23-12-2009, 13:44

Pierwszy sposob: sprawdzasz punkty po kolei w 4 kierunkach: do przodu, do tylu, na lewo i prawo.
Drugi: co kilka sekund sprawdzasz, czy pozycja w jakiej sie znajdujesz ma grunt nad poziomem morza i jesli tak to ja zapisujesz. Pozniej do niej wracasz.

Zreszta wydaje mi sie, ze space() powinno znalezc takie miejsce.

Bartek c++ - 01-01-2010, 13:20

FE4R napisał/a:
Tak tak Bartek. Wciąż jest kilka problemów do rozwiązania.
Kod:
errmode(0);


Niepotrzebne kompletnie. Robot to nie owad, a błędy pomogą Ci udoskonalić program.

Dzięki za zauwarznie zapomniałem tego usunąć.


Powered by phpBB modified by Przemo & WRIM © 2003 phpBB Group