Seznámení s Robocode

, Josef Krupička


1. Úvod
1.1. Instalace
1.2. Spuštění
1.3. Anatomie robůtka
1.4. Příkazy pro robůtka.
1.4.1. Pohyb tanku
1.4.2. Získávání informace o tanku
1.4.3. Příkazy pro střelbu
1.4.4. Události
1.4.5. První příklad
1.4.6. AdvancedRobot
1.5. Shrnutí
2. Taktiky pro boj jednoho tančíka
2.1. Pohyb
2.2. Střelba
2.3. Radar
2.4. Hospodaření s energiíí
2.5. Uchovávání důležitých informací o spoupeři
2.6. Můj zatím nejlepší tank...GruberuvTancik
2.6.1. Pohyb
2.6.2. Ostatní
3. Týmová práce
4. Budoucnost

1. Úvod

Robocode je bojový simulátor robotů, který je spustitelný na všech platformách, které podporují Javu 2. Lze v něm vytvářet vlastní roboty, které můžete posílat do boje s boty nacházející se v distribuci Robocode. Jakmile hravě porazíte tyto zkušební robůtky, je na čase vydat se do světa a účastnit se turnajů, kterých se účastní spousta hráču. Vaším sloganem bude Build the BEST. Destroy the REST.

1.1. Instalace

Robocode vytvořil Mathew Nelson, programátor z IBM. Zde je k dispozici distibuce Robocode(společně s příklady). Minimální požadavky na Váš systém jsou PentiumII -400 Mhz. Na slabších počítačích Robocode běží, ale není to příliš ke koukání. Dále 64 MB paměti a přibližne 10 MB na disku. Tu spustíte příkazem java -jar robocode-setup.jar.

1.2. Spuštění

Robocode spustíte buď přes robocode.sh, robocode.bat nebo kliknutím na ikonku. Robocode se skládá z bitevního pole a Robot editoru.

Figure 1. 

Bitevní pole, jak název vypovídá je místo, kde probíhá bitva robůtků. Obsahuje hlavní simulační engine. Dále umožňuje zakládat, ukládat a otevírat nové nebo již existující bitvy. Bitvu můžete pauznout, obnovit a zrušit. Můžete zníčit jednotlivé robůtky nebo si nechat zobrazit jejich statistiky. Odtud se také spouští Robot editor.

Robot editor je pravený Notepad, ve kterém můžete vytvářet vlastní tančík. Obsahuje Java kompilér a balíčkovač, který vytvoří z vašeho kódu jar archív, který obsahuje vašeho robota.Robot editor zvýrazňuje syntaxi, ale neumožňuje doplňování kódu, což je vzhledem k dlouhým názvům některých metod dosti nepříjemné. Proto k psaní doporučuji nějaké vyspělé IDE( IntelliJ Idea,Eclipse, JBuilder).

1.3. Anatomie robůtka

Tančík se skládá z otočné dělové věže. Na ní je umístěn otočný radar. Věž a radar se mohou pohybovat nezávisle. Defaultně jsou tyto části zarovnány a míří ve směru pohybu tanku.

1.4. Příkazy pro robůtka.

Všechny příkazy jsou zdokumentovány v Javadocu. Ukáži ty nejzákladnější.

1.4.1. Pohyb tanku

turnRight(double úhel) a turnLeft(double úhel) otočí tank o daný úhel.

ahead(double vzdálenost) a back(double vzdálenost) posunou tančík o danou vzdálenost;tyto metody jsou ukončeny pokud tank narazí do zdi nebo do jiného robota.

turnGunRight(double úhel) a turnGunLeft(double úhel) otočí dělovou věž nezávisle na pohybu na tanku

turnRadarRight(double úhel) a turnRadarLeft(double úhel) otočí radar nezávisle na věži a pohybu tanku. Ani jeden z těchto příkázů nevrátí kontrolu dokud není dokončen. Třída AdvancedRobot poskytuje sadu neblokujících metod, o kterých se zmíním později.

Pokud se tank otočí, otočí se věž i radar. Tomu lze zabránit zavoláním těchto metod.

setAdjustGunForRobotTurn(boolean flag): pokud je flag nastaven na true zůstane věž ve stejné pozici zatímco se tank otáčí.

setAdjustRadarForRobotTurn(boolean flag): pokud je flag nastaven na true zůstane radar ve stejné pozici zatímco se tank (a věž) otáčejí.

setAdjustRadarForGunTurn(boolean flag): to samé, ale pouze pokud se otáčí věž.

1.4.2. Získávání informace o tanku

getX() a getY() vrátí aktuální souřadnice robota

getHeading(), getGunHeading(), a getRadarHeading() vrací aktuální směr tanku, věže a radaru ve stupních.

getBattleFieldWidth() a getBattleFieldHeight() vrací rozměry bitevního pole aktuálního kola.

1.4.3. Příkazy pro střelbu

Každý robot začíná s defaultním množství energie. Pokud toto množství klesne pod nulu odebere se bot do kalkulačkového nebe. Robot může do jedné střely vložit až tři jednotky energie. Čím více energie střela má tím větší poškození způsobí svému soupeři. Dále platí, že čím silnější střela tím je pomalejší. O střelbu se stará metoda fire(double síla).

1.4.4. Události

Základní třída Robot obsahuje obsluhy pro velkou řadu události, které se objevují během. Můžete vytvářet i vlastní událost, což ukáži později. Zde jsou často používané události:

ScannedRobotEvent: tato událost se objeví, když objevíte jiného robota.

HitByBulletEvent: tato událost se objeví při zasažení robota střelou

HitRobotEvent: objeví se pokud trefíte jiného robota.

HitWallEvent: objeví se při nárazu do zdi.

1.4.5. První příklad

Tento kód vygeneruje editor pokud zvolíte volbu vytvořit nového robota. Tenhle robůtek jezdí do čtverce a jakmile spozoruje nepřítele tak po něm pálí. Neotáčí radarem ani věží.

package beast;
import robocode.*;
import java.awt.Color;
public class ISWExample1 extends Robot
{
	public void run() {
		setColors(Color.red,Color.blue,Color.green);
		while(true) {
			ahead(100);
			turnGunRight(360);
			back(100);
			turnGunRight(360);
		}
	}
	public void onScannedRobot(ScannedRobotEvent e) {
		fire(1);
	}
	public void onHitByBullet(HitByBulletEvent e) {
		turnLeft(90 - e.getBearing());
	}
}

Další příklad ukáže o něco lepšího bota odvozeného od třídy Robot, který do svých soupeřů naráží a střílí..

package beast;
import robocode.*;
//import java.awt.Color;
public class ISWexample2 extends Robot
{
	int turnDirection = 1;//po nebo proti smeru hodinovejch rucicek
	//otaci se okolo a hleda soupere
	public void run() {
		while (true)
		{
			turnRadarRight(360);
		}
	}
	public void onScannedRobot(ScannedRobotEvent e) {
				
		if (e.getBearing() >= 0)
			turnDirection = 1;
		else
			turnDirection = -1;
		turnRight(e.getBearing());
		ahead(e.getDistance() + 5);
		scan(); 
	}
	//po nepriteli streli a znovu do nej narazi
	public void onHitRobot(HitRobotEvent e) {
		if (e.getBearing() >= 0)
			turnDirection = 1;
		else
			turnDirection = -1;
		turnRight(e.getBearing());
		
		//zjisti energii soupere a podle ni urcuje silu strely...chci bonus za to
		//ze ho dorazim narazem
		if (e.getEnergy() > 16)
			fire(3);
		else if (e.getEnergy() > 10)
			fire(2);
		else if (e.getEnergy() > 4)
			fire(1);
		else if (e.getEnergy() > 2)
			fire(.5);
		else if (e.getEnergy() > .4)
			fire(.1);
		back(1);
		ahead(40); //bum do nej
	}
}

Boti odvozený od Robot jsou však naprosto nepoužitelní. Jejich možnosti pohybu jsou velmi malé a metody, které poskytují jsou neohrabané.

1.4.6. AdvancedRobot

Náš první tank byl odvozen od třídy Robot. Jak jsem uvedl dříve tato třída poskytuje pouze blokující metody. To se nám příliš nehodí a tudíž je k dispozici třída AdvancedRobot. Ta nám poskytuje sadu neblokujících metod jejichž název začínou předponou set.

Tyto nové metody vrátí kontrolu vašemu okamžitě bez provedení posunu nebo otocčení tanku. Nestane se nic dokude nepředáte kontrolu zpět Robocodu. To provedete voláním speciální metody execute(), která předá kontrolu přesně na jeden tik. Stejně jako v šachách dáváte najevo , že jste se již rozhodl a Robocode za vás provede váš plán.

AdvancedRobot dále poskytuje možnost vytářet si vlastní události. Nadefinujeme si podmínku a pokud je splněna Robocode nám to oznámí.Příklad ukáži na třídě MultiBot. Dodám, že AdvancedRobot je potomkem třídy Robot.

package beast;
import robocode.*;
import java.awt.Color;
public class ISWexampleMK3 extends AdvancedRobot
{
	final double veryFar = 9999.0;
        final double quarterTurn = 90.0;
        final double halfTurn = 180.0;
        final double threeQuarterTurn = 270.0;
        final double fullTurn = 360;
	public void run() {
        setColors(Color.red,Color.blue,Color.green);
        turnLeft(getHeading());
        turnRight(halfTurn);
          addCustomEvent(
			new Condition("LeftLimit") {
			  public boolean test() {
				  return (getHeading() <= quarterTurn);
				};
			}
		);
          addCustomEvent(
			new Condition("RightLimit") {
			  public boolean test() {
				  return (getHeading() >= threeQuarterTurn);
				};
			}
		);
                    setTurnRight(fullTurn);
                    setTurnGunLeft(fullTurn);
		while(true) {
			execute();
		}
	}


  public void onCustomEvent(CustomEvent ev) {
         Condition cd = ev.getCondition();
         System.out.println("udalost s " + cd.getName());
         if (cd.getName().equals("RightLimit")) {
            setTurnLeft(fullTurn);
            setTurnGunRight(fullTurn);
            }
            else {
             setTurnRight(fullTurn);
             setTurnGunLeft(fullTurn);
            }
        }
}

1.5. Shrnutí

Fungování jednoho bota jsem předvedl. V RoboLeague se bojům s jedním botem dává přednost. Existují soutěže s co nejmenšími boty, 1 vs 1 nebo normální death-match, kde bojuje každý s každým. Existuje spousta taktik, jak uspět v těchto soubojích. V úvahu musíte vzít váš způsob pohybu, zaměřování nepřítele, uhýbání se kulkám, zjišťování soupeřovy taktiky atd..

2. Taktiky pro boj jednoho tančíka

2.1. Pohyb

Tančík se může pohybovat lineárně. To není moc chytré, protože většina již udělaných botů používá predikci střelby na tento způsob pohybu. Může se pohybovat po kružnici. Tento způsob má stejnou nevýhodu jako předchozí. Dále můžete zvolit oscilační pohyb. Pro něj platí víceméně to samé, ale objevit nějakou pravidelnost je složitější. Velmi dobrým způsobem je tzv. Anti-gravity movement, kdy si váš robot zvolí několi bodů na hrací ploše, které mají vysokou "gravitaci" a snaží se jim vyhnout. Pozice těchto bodů je většinou totožná s pozicí nepřátel. Dále se lze pohybovat podél zdí. Používat kyvadlový pohyb. Dobrá taktika je kanibalský pohyb, kdy váš robot krade pohyby soupeře. Další taktikou je zvolit náhodný pohyb.

Další věcí, která značně ovlivňuje pohyb tanku je snaha uhýbat nepřátelským střelám. Sledováním robota může zjistit, zda-li vystřelil(podle úbytku energie) a podle toho patřične zareagovat. Bohužel nejde zjistit, směr výstřelu, takže uhýbáte naslepo:).

Při pohybu je také nutné si dát pozor před nárazy do zdí. Dále je vhodné se nenechat zahnat do kouta, o což se někteří boti snaží. Možnost pohybu v rozích je velmi omezená a pokud se soupeři podaří vás do rohu zahnat tak jste většinou skončil.

2.2. Střelba

Pokud zvládnete dobrý pohyb vašeho tanku je načase vytvořit vhodné metody na střílení po vašem soupeři. Kdykoliv můžete zjistit pozici vašeho soupeře, jeho rychlost a směr jeho pohybu. Střela má určitou rychlost(ta závisí na síle) a proto při výstřelu musíte mířit na předpokládanou pozici. Základem je predikce lineárního, kruhového a oscilačního pohybu. Další dobrou technikou je hledání vzoru v pohybu nepřítele. Tím se dají nahradit výše uvedené predikce a dokáže odhalit i složitější způsoby pohybu. Nejvychytanější metodu jsou asi virtuální zbraně. Princip je jednoduchý. Nepřítel nemůže zjistit kam míříte věží a tudíž podle toho nemůže reagovat. Vytvoří se střela pro každý ofset věže a sleduje se její dráha a zjišťuje se jestli je "zasáhne" nepřítele. Pokud kulka zasáhne zvedne se ohodnocení pro zaměřovací metodu, pokud ne tak se pro použité zaměřování sníží.

Důležité je také vhodně volit sílu střelby. Každá střela ubere určitou část vaší energie. Pokud vám dojde energie váš tank ztratí možnost pohybu a proto jste na 99% prohrál. Když se vám podaří soupeře znehybnit, můžete ho dorazit banzaii útokem, za který dostanete body navíc:)).

Většina vyspělých botů si ukládá informace o soupeři během jednotlivých kol. Používají je k vylepšování svých zaměřovacích algoritmů.

Našli se již tvůrci botů, kteří k vývoji používají neuronové sítě a genetické algoritmy. Tito boti zatím nejsou příliš úspěšní a prohrávají v soubojích s ručně udělanými. Faktem, ale je, že bot, který dlouhou dobu vede RoboLeague ve 1 vs 1 je doladěn pomocí genetických algoritmů, které upravovali parametry zaměřovacích a pohybujících metod napsaných člověkem.

2.3. Radar

Další důležitou složkou vaší hry by mělo bůt kvalitní zjišťování informací o vaších soupeřích. K tomu, jak jsem uváděl dříve, slouží radar. Pokud hrajete 1 vs 1 tak je vhodné mít radar neustále zaměřený na vašeho soupeře a o nic jiného se není nutné starat. Při boji mezi více hráči musíte skenovat okolí neustále. Důvodem je nedostat se do špatné pozice mezi více bojujících soupeřů. Zbytečně do nich nenarážet atd..

2.4. Hospodaření s energiíí

Na velkou vzdálenost střílet střelama s menší energií. Nestřílet po soupeři zbytečně silné střely pokud už má málo energie. Snížit sílu střely(nebo přestat střílet) pokud je vaše energie už hodně nízko. Není dobré zůstat nepojízdný.

2.5. Uchovávání důležitých informací o spoupeři

Je dobré si během hry(mezi jednotlivými hrami) ukládat nějaké info o vašem protivníkovi. Takovými daty jsou např. jeho rychlost, změna směru atd.

2.6. Můj zatím nejlepší tank...GruberuvTancik

2.6.1. Pohyb

Snaží se zůstat v pevné vzdálenosti od svého soupeře. Na rozdíl od většíny botů na netu se snaží být hodně blízko ke svému soupeři. Kopíruje sopeřovu Y souřadnici a přidává k ní offset. Nemusí se tudíž vymýšlet žádná složitá funkce na generování pohybu. Tento způsob má jednu chybu. Pokud soupeř má metodu na predikci takového způsobu boje...tak jsem nahranej:)). Řešení spočívá ve vytvoření dalších strategických manažerů, které by se aktivovali v případě jasných porážek a pokud by se tanku povedlo zjistit jakou jeho nepřítel používá taktiku.

2.6.2. Ostatní

Tento bot si ukládá mezi tahy informace o zaměřovacích faktorech, které používám k úpravě střelby.

Pokud soupeř vystřelí vybere se nový offset pro Y souřadnici.

Tento bot je pouze 1 vs 1. Taktiku proti více soupeřům nemá. Porazí všechny sample boty a poradí si s velkým počtem botů, kteří jsou k dispozici ke stažení z inetu.

3. Týmová práce

V Robocode se dají vytvářet i týmy, které pak proti sobě bojují. Dá se použít jakýkoliv robot v neomezeném počtu. První robot ve skupině získá 200 bodu energie a získává postavení vůdce. Po jeho zníčení se všem ostatním tankům sníží energie o 30 bodů. Dále je zde třída TeamRobot, která je odvozena od AdvancedRobot. Roboti odvození od této třídy si mohou vyměnovat zprávy(serializované objekty). Zpráva můžete poslat všem soudruhům nebo jednomu určitému. Příjetí zprávy se projeví událostí MessageEvent. Další možností je interface Droid, který vašemu robotu přidá 20 životů, ale za cenu ztráty radaru. Je tudíž zcela odkázaný na zprávy od svých kolegů.

4. Budoucnost

Nyní je ve vývoji RobocodeGL, který k vykreslování hrací plochy používá OpenGL a přidává možnost ladění vašeho robota. Chystá se i nová verze Robocode2, která by měla být 3D a mělo by dojít ke zvětšení realističnosti. Parta nadšenců dokonce vytváří aplikaci, se kterou se budete schopni napojit na Robocode a hrát proti vámi udělanému botu.