3.2. RG – klocki 1

Wskazówka

  • Każdy “klocek” można testować osobno, a później w połączeniu z innymi. Warto i trzeba zmieniać kolejność stosowanych reguł!

3.2.1. Idź do środka

To będzie nasza domyślna reguła. Umieszczamy ją w pliku robot01.py zawierającym niezbędne minimum działającego bota:

Kod nr
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#! /usr/bin/env python
# -*- coding: utf-8 -*-

import rg


class Robot:

    def act(self, game):

        # idź do środka planszy, ruch domyślny
        return ['move', rg.toward(self.location, rg.CENTER_POINT)]

Metody i właściwości biblioteki rg:

  • rg.toward(poz_wyj, poz_cel) – zwraca następne położenie na drodze z bieżącego miejsca do podanego.
  • self.location – pozycja robota, który podejmuje działanie (self).
  • rg.CENTER_POINT – środek areny.

3.2.2. W środku broń się lub giń

Co powinien robić robot, kiedy dojdzie do środka? Może się bronić lub popełnić samobójstwo:

Kod nr
1
2
3
4
5
6
7
8
9
# jeżeli jesteś w środku, broń się
if self.location == rg.CENTER_POINT:
    return ['guard']

# LUB

# jeżeli jesteś w środku, popełnij samobójstwo
if self.location == rg.CENTER_POINT:
    return ['suicide']

3.2.3. Atakuj wrogów obok

Wersja wykorzystująca pętlę.

Kod nr
1
2
3
4
5
6
# jeżeli obok są przeciwnicy, atakuj
# wersja z pętlą przeglądającą wszystkie pola zajęte przez roboty
for poz, robot in game.robots.iteritems():
    if robot.player_id != self.player_id:
        if rg.dist(poz, self.location) <= 1:
            return ['attack', poz]

Metody i właściwości biblioteki rg:

  • Słownik game.robots zawiera dane wszystkich robotów na planszy. Metoda .iteritems() zwraca indeks poz, czyli położenie (x,y) robota, oraz słownik robot opisujący jego właściwości, czyli:

    • player_id – identyfikator gracza, do którego należy robot;
    • hp – ilość punktów HP robota;
    • location – tupla (x, y) oznaczająca położenie robota na planszy;
    • robot_id – identyfikator robota w Twojej drużynie.
  • rg.dist(poz1, poz1) – zwraca matematyczną odległość między dwoma położeniami.

3.2.4. Robot podstawowy

Łącząc omówione wyżej trzy podstawowe reguły, otrzymujemy robota podstawowego:

Plik robot04a.py. Kod nr
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#! /usr/bin/env python
# -*- coding: utf-8 -*-

import rg


class Robot:

    def act(self, game):
        # jeżeli jesteś w środku, broń się
        if self.location == rg.CENTER_POINT:
            return ['guard']

        # jeżeli wokół są przeciwnicy, atakuj
        for poz, robot in game.robots.iteritems():
            if robot.player_id != self.player_id:
                if rg.dist(poz, self.location) <= 1:
                    return ['attack', poz]

        # idź do środka planszy
        return ['move', rg.toward(self.location, rg.CENTER_POINT)]

Wybrane działanie robota zwracamy za pomocą instrukcji return. Zwróć uwagę, jak ważna jest w tej wersji kodu kolejność umieszczenia reguł, pierwszy spełniony warunek powoduje wyjście z funkcji, więc pozostałe możliwości nie są już sprawdzane!


Powyższy kod można przekształcić wykorzystując zmienną pomocniczą ruch, inicjowaną działaniem domyślnym, które może zostać zmienione przez kolejne reguły. Dopiero na końcu zwracamy ustaloną akcję:

Plik robot04b.py. Kod nr
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#! /usr/bin/env python
# -*- coding: utf-8 -*-

import rg


class Robot:

    def act(self, game):
        # działanie domyślne:
        ruch = ['move', rg.toward(self.location, rg.CENTER_POINT)]

        if self.location == rg.CENTER_POINT:
            ruch = ['guard']

        for poz, robot in game.robots.iteritems():
            if robot.player_id != self.player_id:
                if rg.dist(poz, self.location) <= 1:
                    ruch = ['attack', poz]

        return ruch

3.2.4.1. Ćwiczenie 1

Przetestuj działanie robota podstawowego wystawiając go do gry z samym sobą w symulatorze. Zaobserwuj zachowanie się robotów tworząc różne układy początkowe:

(env)~/robot$ python ./symuluj robot04a.py robot04b.py

3.2.5. Możliwe ulepszenia

Robota podstawowego można rozbudowywać na różne sposoby przy użyciu różnych technik kodowania. Proponujemy więc wersję **A** opartą na funkcjach i listach oraz wersję **B** opartą na zbiorach. Obie wersje implementują te same reguły, jednak efekt końcowy wcale nie musi być identyczny. Przetestuj i przekonaj się sam.

Wskazówka

Przydatną rzeczą byłaby możliwość dokładniejszego śledzenia decyzji podejmowanych przez robota. Najprościej można to osiągnąć używając polecenia print w kluczowych miejscach algorytmu. Podany niżej Kod nr 6 wyświetla w terminalu pozycję aktualnego i atakowanego robota. Kod nr 7, który nadaje się zwłaszcza do wersji robota wykorzystującej pomocniczą zmienną ruch, umieszczony przed instrukcją return pozwoli zobaczyć w terminalu kolejne ruchy naszego robota.

Kod nr
1
2
3
4
5
for poz, robot in game.robots.iteritems():
    if robot.player_id != self.player_id:
        if rg.dist(poz, self.location) <= 1:
            print "Atak", self.location, "=>", poz
            return ['attack', poz]
Kod nr
print ruch[0], self.location, "=>",
if (len(ruch) > 1):
    print ruch[1]
else:
    print

Licencja Creative Commons Materiały Python 101 udostępniane przez Centrum Edukacji Obywatelskiej na licencji Creative Commons Uznanie autorstwa-Na tych samych warunkach 4.0 Międzynarodowa.

Utworzony:2017-09-08 o 18:17 w Sphinx 1.5.3
Autorzy:Patrz plik “Autorzy”