|
Forum - Polski Portal COLOBOTa |
|
|
Przesunięty przez: Abadon 20-02-2010, 14:23 |
Rozbudowany program bota obsługującego hutę |
Autor |
Wiadomość |
pipok
Dołączył: 24 Cze 2009 Posty: 53
|
Wysłany: 25-06-2009, 16:55 Rozbudowany program bota obsługującego hutę
|
|
|
Rozbudowany program dla bota transportowego obsługującego hutę. Jak każdy inny tego rodzaju, działa w cyklu: zanieś rudę do huty, wyjmij kostkę tytanu i odłóż na wolne miejsce, idź po następną bryłę rudy.
Założenia:* drobne ułatwienia: można uruchomić nawet jeśli bot trzyma coś w chwytaku; kiedy dotrze z surowcem do huty, a zastanie w niej gotową kostkę tytanu, prawidłowo się zachowa itp.
* dba o odpowiedni zapas energii, przewidując zużycie na trasie
* optymalnie wykorzystuje elektrownie, także jeśli jest więcej niż jedna
* podjeżdża blisko elektrowni i jeśli nie może zająć w niej miejsca, to czeka w pobliżu aż będzie dostępna
* sam planuje lądowania techniczne dla ostudzenia silników (jeśli latający)
* wybiera bezpieczne miejsca do lądowania: suche i w miarę możliwości płaskie (dla uniknięcia ryzyka ześlizgnięcia się do wody lub w przepaść). W zasadzie program można uruchomić na więcej niż jednym bocie. Nie pamiętam, czy testowałem taką sytuację, bo ostatnie poprawki robiłem w 2005 roku.
Tytan.txt
|
Pobierz Plik ściągnięto 137 raz(y) 10,67 KB |
|
|
|
|
|
pipok
Gość
|
Wysłany: 26-06-2009, 07:59 Re: Rozbudowany program bota obsługującego hutę
|
|
|
Sam skomentuję, skoro nikogo nie korci
Ułatwiajmy sobie życie
Główny program wygląda tak: Kod: | extern void object::ZbierajTytan()
{
int surowiec = TitaniumOre;
int przetwornia = Converter;
int produkt = Titanium;
object rzecz, budynek;
point tutaj;
float odl;
// co trzymasz w łapie, robocie?
WyrzucInne(surowiec);
while (true) { // powtarzaj w nieskończoność
WezSurowiec(surowiec);
// znajdź przetwórnię i idź tam
budynek = radar(przetwornia);
// opróznij przetwórnię, jeśli jest w niej produkt
OproznijPrzetwornie(surowiec, produkt, przetwornia);
// upewnij się, że masz w łapce surowiec, zostaw go w przetwórni
WezSurowiec(surowiec);
Idz(budynek.position); drop();
// poczekaj na produkt i odłóż go
ObsluzProdukt(surowiec, produkt, przetwornia);
}
} | Pierwsze trzy linijki ciała programu (deklaracje i inicjowanie zmiennych typu int) mają za zadanie ułatwić przemianę zbieracza tytanu w zbieracza uranu.
Dalsza część to trzy inne deklaracje, i... do roboty... jednokrotne wywołanie funkcji WyrzucInne oraz pętla zasadniczej pracy. Trzy z czterech użytych funkcji własnych występują w kodzie jednokrotnie, więc dlaczego ich treść nie jest po prostu wpisana w główny program, po co zrobiłem funkcje z kawałków kodu? Program jest dość obszerny (ponad 10KB) -- podzielenie go na części ułatwia zrozumienie jego działania, testowanie i modyfikowanie. Wyobraźmy sobie zagnieżdżenie sześciu dlugaśnych pętli, jedna w drugiej... Dla początkujących programistów: jeśli kod jest dłuższy niż dwa-trzy ekrany, podziel go na kawałki.
Innego rodzaju ułatwienie występuje w pierwszej własnej funkcji. Pierwszym działaniem bota w cyklu pracy jest znalezienie, dojazd i wzięcie rudy tytanu. Bardzo irytowało mnie, że przed uruchomieniem programu zbieracza musiałem upewnić się, że na pusty chwytak. W przeciwnym razie jechał sobie do najbliższej bryły i próbował ją podnieść mając zajęte "ręce". Na dodatek błąd pojawia się dopiero przy próbie podniesienia! Czy powinien mieć wolne łapki? Odpowiedni fragment programu Kempiora wygląda tak: Kod: | while( load == null )
{
item = radar(TitaniumOre);
[ ... ]
goto(item.position);
grab();
}
item = radar(Converter);
while ( item == null );
while(goto(item.position) != 0 )
| Jeśli bot nic nie niesie, to ma iść i zabrać rudę tytanu. Następnie udaje się do huty. Co się stanie, jeśli przed uruchomieniem programu bot już trzyma rudę? Wtedy nie pójdzie po rudę, tylko od razu do huty. W porządku. Ale zrobi to samo, jeśli w chwytaku ma coś innego: kostkę tytanu, ogniwo, uran... Nie uda się po rudę, ale z tym, co trzyma, od razu pójdzie do huty. I tam zostawi, czekając aż huta przerobi to na kostkę
Warto upewnić się przed rozpoczęciem pracy, czy coś trzyma. Ale... Jeśli tak, to powinna to być ruda. Inne przedmioty powinien odłożyć na bok. Kod: | void object::WyrzucInne(int surowiec)
{
if (load != null) {
if (load.category != surowiec) {
// trzyma coś, ale nie surowiec!
// zostaw to gdzieś w pobliżu
goto(space()); drop();
}
}
} |
|
|
|
|
|
pipok
Gość
|
Wysłany: 26-06-2009, 09:50 Re: Rozbudowany program bota obsługującego hutę
|
|
|
Kolejny klocek to funkcja nakazująca botowi udanie się w miejsce, gdzie leży najbliższa bryła tytanu i zabranie jej:
Kod: | void object::WezSurowiec(int surowiec)
{
int err;
object rzecz;
if (load == null) { // puste łapki - weź surowiec
// idź do surowca i podnieś go
do {
rzecz = radar(surowiec); // znajdź
Idz(rzecz.position); // idź do surowca
// podnieś go
errmode(0); err=grab(); errmode(1);
} while (err != 0);
}
} | Co tutaj robi instrukcja warunkowa? Kod: | if (load == null) { // puste łapki - weź surowiec | Upraszcza kod. Mamy jedną funkcję do znajdowania i zabierania surowca, a na samym początku być może bot trzyma już w chwytaku rudę - wówczas nie musi nigdzie chodzić i niczego brać. Poza sprawdzeniem bot nic wówczas nie robi. Z kolei Kod: | ierrmode(0); err=grab(); errmode(1); | obsługuje sytuację, kiedy z jakiegoś powodu podniesienie surowca się nie powiodło. Szukanie, ewentualna podróż i próba zabrania są powtarzanie póki nie uda się pomyślnie pochwycić surowca. W szczególności błąd chwytania pojawi się, kiedy ktoś już zabrał surowiec podczas gdy nasz bot do niego podróżował. Dzięki umieszczeniu "szukania" surowca wewnątrz pętli, bot spróbuje wtedy dotrzeć do innej, położonej najbliżej niego bryły.
Użyta do przemieszczenia bota funkcja Idz(), przyjmująca parametr typu point, odpowiada wbudowanej funkcji goto() użytej z jednym parametrem. Dodatkowo zapewnia obsługę podładowywania ogniwa i studzenia silników w razie potrzeby. |
|
|
|
|
Kempior
Twoja ulubiona misja: Krystalia: Ziemska Strategia
Wiek: 23 Dołączył: 19 Cze 2009 Posty: 15 Skąd: Bielsko-Biała
|
Wysłany: 26-06-2009, 15:21
|
|
|
Kod: | while( load == null )
{
item = radar(TitaniumOre);
[ ... ]
goto(item.position);
grab();
} |
Ten kod miał sprawić że robot nie pojedzie bez rudy do huty. |
|
|
|
|
pipok
Gość
|
Wysłany: 26-06-2009, 16:31
|
|
|
Kempior napisał/a: | Ten kod miał sprawić że robot nie pojedzie bez rudy do huty. | Ale jeśli nie uda mu się chwycić rudy, to nie powtórzy zawartości pętli, tylko przerwie działanie z powodu błędu, prawda? |
|
|
|
|
pipok
Gość
|
Wysłany: 26-06-2009, 16:53
|
|
|
Kiedy bot ma już w chwytaku bryłę rudy tytanu (surowiec), powinien udać się z nią do huty (przetwórni), żeby ją tam umieścić. Co jednak, jeśli w przetwórni leży już wyprodukowana kostka tytanu?
Jak sprawdzić, czy w hucie leży tytan? Wystarczy sprawdzić, czy w promieniu 3 metrów od centrum tego budynku znajduje się kostka tytanu. Współrzędne budynku odnalezionego funkcją radar są współrzędnymi środka budowli. Niestety, funkcja radar daje możliwość przeszukania zadanego wycinka koła, z ograniczeniem odległości, ale centrum poszukiwań stanowi nasz bot. Dlatego poszukamy kostki tytanu znajdującej się w stosunku do bota w odległości takiej jak budynek huty, plus minus 3 metry. Ponadto, ta kostka musi być z pozycji bota widoczna w tym samym kierunku, co budynek, z dokładnością do powiedzmy 5 stopni.
Stąd wziął się występujący w funkcji fragment:
Kod: | budynek = radar(przetwornia);
odl=distance(position, budynek.position);
rzecz=radar(produkt,direction(budynek.position),5, odl-3,odl+3); | Alternatywną metoda sprawdzenia jest szukanie w pętli kolejnych kostek tytanu i sprawdzanie, czy odległość miedzy kostką a hutą jest mniejsza od 3 metry.
Jeżeli w hucie (przetwórni) jest kostka tytanu, to bot powinien pojechać na jakieś wolne miejsce w pobliżu huty, odłożyć trzymaną rudę, a następnie wyciągnąć z huty kostkę tytanu i położyć ją w miejscu składowania kostek (produktów). Po to, żeby w kolejnym kroku móc swoją rude umieścić w opróżnionym budynku huty. Całość wygląda więc tak: Kod: | void object::OproznijPrzetwornie(int surowiec, int produkt, int przetwornia)
{
object rzecz, budynek;
float odl;
int err;
// czy w przetwórni nie ma aby gotowego produktu? - wyjmij go
budynek = radar(przetwornia);
odl=distance(position, budynek.position);
rzecz=radar(produkt,direction(budynek.position),5, odl-3,odl+3);
if (rzecz != null) {
// przetwórnia zajęta, leży w niej gotowy produkt
if (load != null) {
// trzyma coś, trzeba to odłożyć, żeby wyjąć produkt
// odłóz w poblizu przetwórni
Idz(space(budynek.position,5,20,2)); drop();
}
Idz(budynek.position);
errmode(0); err=grab(); errmode(1); // wyjmij produkt
if (err == 0) { OdlozProdukt(produkt); }
}
} | Warto zauważyć, że próba podniesienia kostki z huty nie jest zamknięta w pętli. Dlaczego? Ponieważ sprawdzenia zajętości huty dokonaliśmy zanim do niej bot wyruszył. Kiedy już dotarł w pobliże huty, być może kostki już nie ma w środku (astronauta ją zabrał?).
Z drugiej strony, jak zauważył Kempior, powstaje problem, gdy równocześnie z naszym obsługuje inny bot. Kiedy huta jest pusta w chwili, gdy bot sprawdza (ma rudę, ale jeszcze nie ruszył z nią w drogę), może się zdarzyć, że zanim dotrze na miejsce, drugi bot włoży do huty rudę. A ponownego sprawdzenia już nie ma... |
|
|
|
|
pipok
Gość
|
Wysłany: 26-06-2009, 16:59
|
|
|
Kempior napisał/a: | Ten kod miał sprawić że robot nie pojedzie bez rudy do huty. | Dopiero teraz zwróciłem uwagę, że wyłączyłeś globalnie, na samym początku programu, zatrzymywanie działania w przypadku błędu. |
|
|
|
|
colobotwymiiata
Zjem cię
Twoja ulubiona misja: Swobodna na Krystalii
Pomógł: 6 razy Wiek: 20 Dołączył: 02 Lut 2009 Posty: 329 Skąd: Oleśnica
|
Wysłany: 17-08-2009, 16:04
|
|
|
Istnieje też funkcja "search", która nie jest opisana w oficjalnym podręczniku. Szuka obiektu jak "radar", ale można ustalić pozycję. |
|
|
|
|
pipok
Dołączył: 24 Cze 2009 Posty: 53
|
Wysłany: 25-08-2009, 15:30
|
|
|
colobotwymiiata napisał/a: | Istnieje też funkcja "search", która nie jest opisana w oficjalnym podręczniku. Szuka obiektu jak "radar", ale można ustalić pozycję. | Słusznie. Zupełnie o niej zapomniałem, a jest bardzo przydatna w podobnych sytuacjach Cytat: | search ( kategoria, pozycja );
Znajduje obiekt o określonej kategorii, będący najbliżej podanej pozycji. |
|
|
|
|
|
|
Nie możesz pisać nowych tematów Możesz odpowiadać w tematach Nie możesz zmieniać swoich postów Nie możesz usuwać swoich postów Nie możesz głosować w ankietach Nie możesz załączać plików na tym forum Możesz ściągać załączniki na tym forum
|
Wersja do druku
|
|
| |
|
|
|
|
Polski Portal COLOBOTa © 2008 - 2012 |
|
|