Wir haben gesehen, dass man den Agenten verwenden kann, um Objekte zu bauen. Dies ist jedoch recht kompliziert, da der Agent die Blocks nicht an seiner eigenen Position hinlegt, sondern vor oder hinter oder neben sich stellt. Dies macht die Programmierung nicht sehr einfach.
Will man Blöcke automatisch erstellen lassen, kann man dies auch direkt machen, d.h. ohne den Agenten. Dazu verwendet man hauptsächlich die Befehle: blocks.place und blocks.fill. Damit kann man einen Block an einer bestimmten Position setzen, oder einen ganzen Quader von Blöcken auf einmal erstellen.
Eine Linie von Blocks erstellen, wobei jeder zweite Block aus Gold bzw. aus blauer Wolle besteht: (das %-Zeichen ist die Modulo-Rechnung vgl. Stunde)
for i in range(3,20,1):
if (i%2)==0:
blocks.place(GOLD_BLOCK, pos(i, 0, 0))
else:
blocks.place(BLUE_WOOL, pos(i,0,0))
Einen Grossen Goldblock erstellen und mit Luft aushöhlen:
blocks.fill(GOLD_BLOCK, pos(1, 1, 1), pos(10, 10, 10)) blocks.fill(AIR, pos(2,2,2), pos(9, 9, 9))
Eine Variable ist ein Behälter für eine Grösse. Diese wird durch einen Namen repräsentiert und zeigt auf eine bestimmte Adresse im Speicher des Computers. Variablen können beliebig wieder überschrieben werden.
In Variablen kann man ganz unterschiedliche Dinge speichern. Z.B.
In vielen Programmiersprachen muss man sich bei einer bestimmten Variable entscheiden, von welchem Typ sie ist und kann dann nur diesen Typ verwenden. Nicht so in Python. In Python herrscht dynamische Typisierung vor, d.h. ich kann in einer Variablen a zunächst eine Zeichenkette speichern und dann diese durch eine ganze Zahl überschreiben und danach eine Kommazahl daraus machen.
a = 4 # In der Variablen a wird der Wert 4 gespeichert name = 'Rene Lehmann' # In der Variablen name wird 'Rene Lehmann' gespeichert strasse = "Lärchenweg" # doppelte Anführungszeichen gehen auch pi = 3.141592 # Eine Fliesskommazahl a = "Hallo" #die Variable a wird wieder überschrieben
if agent.get_item_count(2)>=2:
agent.set_slot(2)
agent.place(BACK)
agent.move(FORWARD, 1)
agent.place(BACK)
elif agent.get_item_count(2)==1:
agent.set_slot(2)
agent.place(BACK)
else:
player.say("Nix mehr in Slot 2")
while agent.get_item_count(1)>0:
agent.place(BACK)
agent.move(FORWARD,1)
l1 = [GRASS, STONE, OAK_DOOR] # Liste erstellen
agent.set_slot(1)
for item_type in l1: # Liste durchgehen
agent.set_item(item_type, 1, 1)
agent.place(BACK)
agent.move(FORWARD, 1)
Eine Liste kann man auch sehr elegant mit dem range-Befehl erstellen:
range(10) # => [0,1,2,3,4,5,6,7,8,9] range(9,18,3) # => [9, 12,15]
# Eine Funktion definieren, welche zwei Parameter (n, type) nimmt
def build_line(n, type):
agent.set_item(type,1,1)
agent.set_slot(1)
for i in range(n):
agent.place(BACK)
agent.move(FORWARD,1)
# Nun kann die Funktion aufgerufen werden
build_line(5,GRASS)
build_line(8,STONE)
Der Modulo-Operator % kann praktisch sein, um bei einer Schleife, nur gewisse Schritte anzusteuern, z.B. nur bei jeder zweiten Position einen Block setzen:
for i in range(20):
if (i % 2) == 0:
blocks.place(GOLD_BLOCK, world(i, 4, 0))
Was ändert sich, wenn man statt %2, %3, %4 etc. schreibt?
for i in range(40):
if (i%3) == 0:
blocks.place(GOLD_BLOCK,world(i,5,0))
if (i%3) == 1:
blocks.place(BLUE_WOOL,world(i,5,0))
if (i%3) == 2:
blocks.place(GREEN_WOOL,world(i,5,0))
for i in range(20):
for j in range(20):
if (i+j) % 2 == 0:
blocks.place(GOLD_BLOCK,pos(i,5,j))
else:
blocks.place(BLUE_WOOL,pos(i,5,j))
Damit die Funktion möglichst flexibel eingesetzt werden kann, sollte man sie parametrisieren, d.h. man kann der Funktion als Argumente übergeben, an welcher Position das Haus gebaut wird, bzw. welche Grösse es hat.
def simple_house(xpos,ypos,zpos,breite, hoehe):
blocks.fill(STONE_BRICKS,world(xpos,ypos,zpos),world(xpos+breite,ypos+hoehe, zpos+breite))
blocks.fill(AIR, world(xpos+1,ypos,zpos+1),world(xpos+breite-1,ypos+hoehe-1, zpos+breite-1))
#Tuere
blocks.fill(AIR,world(xpos+4,ypos,zpos),world(xpos+4,ypos+1,zpos))
blocks.place(ACACIA_DOOR,world(xpos+4,ypos,zpos))
simple_house(100,4,-18,7,10)
simple_house(140,4,-18,10,5)
Statt z.B. blocks.place(OAK_DOOR,world(0,0,0)) kann man den Block mit zugehörigem Datenwert platzieren:
blocks.place(blocks.block_with_data(OAK_DOOR, 0),world(0,0,0))
Der Daten-Wert gibt an, ob die Türe (oder Treppe) etc. geöffnet ist, nach links aufgeht etc.
def strasse(xpos,ypos,zpos,laenge):
blocks.fill(LIGHT_GRAY_CONCRETE,world(xpos,ypos,zpos),world(xpos+laenge,ypos,zpos+4))
for i in range(xpos,xpos+laenge,2):
blocks.place(CONCRETE,world(i,ypos,zpos+2))
strasse(700,3,700,40)