Gruppe 3 Idee: Eine Burg mit Türmchen; siehe Bild in Teamschat Ziel: Den versteckten Schatz finden, welcher in der Burg versteckt ist. - Verwinkelte Räume (Labyrinth) **Code** # ------------------------------------------------------------------------------ # Nutzung # In der Burg ist ein Schatz versteckt, den es zu finden gilt! # # Befehle # • "Sesam, öffne dich!" # • "Sesam, schliesse dich!" # ------------------------------------------------------------------------------ MIN_PADDING = 3 # Mindestabstand zwischen Räumen und Aussenwand SIMPLIFY = 0 # Burg vereinfachen um sie schneller zu generieren TOWERS = True # Türme generieren T_RADIUS = 3 # Radius der Türme seed = 54321 # Startwert für Pseudozufallszahlen # ------------------------------------------------------------------------------ # Die Koordinaten im Code folgen der Einteilung von Minecraft, nach der y die # Höhe ist. # Bei blocks.fill wurde FillOperation.REPLACE zwecks Leserlichkeit weggelassen, # da es sich um den Standartwert handelt. # ------------------------------------------------------------------------------ CHUNK_HEIGHT = 6 # Festgelegt durch Höhe der Burgsegmente L = 0 materials = [STONE_BRICKS, MOSSY_STONE_BRICKS, STONE_BRICK_STAIRS, STONE_BRICKS_SLAB, OXIDIZED_COPPER, CRACKED_STONE_BRICKS] start_pos = player.position() #----------------- # Hilfsfunktionen #----------------- # Relative Koordinaten unabhängig von der Bewegung des Spielers während der Ausführung def position(x, y, z): return start_pos.add(positions.create(x, y, z)) # Funktion um Wert eine Position zu erhalten (da die Funktion position() mit .get_value() sonst nur Weltkoordinaten ausgibt) def get(pos: Position, axis): return pos.to_world().get_value(axis) - start_pos.get_value(axis) # Pseudozufallszahlengenerator https://de.wikipedia.org/wiki/Kongruenzgenerator#Linearer_Kongruenzgenerator def lcg(value=0): global seed a, c, m = 1664525, 1013904223, 2**32 # Werte aus https://www.columbia.edu/~ks20/4106-18-Fall/Simulation-LCG.pdf if value == 0: seed = (seed * a + c) % m return seed / m else: return ((value * a + c ) % m) / m #----------------- # Burg #----------------- # Funktion zum bauen der Segmente def chunk_builder(): blocks.saveStructure("save", world(0, 200, 0), world(16, 250, 16), True) blocks.fill(AIR, world(0, 200, 0), world(16, 250, 16)) # Bereich leeren for i in range(2): blocks.fill(materials[0], world(0, 200 + 5 * i, 0), world(16, 200 + 5 * i, 16)) blocks.fill(materials[0], world(0, 201, 16 * i), world(5 + i, 204, 16 * i)) blocks.fill(materials[0], world(10 - i, 200, 16 * i), world(16, 204, 16 * i)) blocks.fill(materials[0], world(16 * i, 200, 0), world(16 * i, 204, 16)) blocks.fill(materials[0], world(5 + 5 * i, 200, 0), world(5 + 5 * i, 204, 4)) blocks.fill(materials[0], world(6 + 3 * i, 200, 5), world(6 + 3 * i, 204, 5)) blocks.fill(materials[0], world(5 + 5 * i, 200, 16), world(5 + 5 * i, 204, 12)) blocks.fill(materials[0], world(6 + 3 * i, 200, 11), world(6 + 3 * i, 204, 11)) blocks.fill(materials[0], world(6 + 3 * i, 200, 6), world(6 + 3 * i, 203, 11)) blocks.fill(materials[0], world(0 + 11 * i, 200, 4), world(4 + 11 * i, 204, 4)) blocks.fill(materials[0], world(13 - i, 200 + 3 * i, 11), world(13 - i, 202 + 2 * i, 5)) blocks.fill(materials[0], world(11, 200, 12), world(15, 204, 12)) blocks.fill(materials[0], world(6, 204, 6), world(9, 204, 10)) blocks.fill(materials[0], world(6, 200, 11), world(6, 204, 11)) blocks.fill(materials[0], world(4, 200, 12), world(4, 204, 12)) blocks.fill(materials[0], world(3, 200, 11), world(3, 204, 5)) # Öffnungen für Durchgänge blocks.fill(AIR, world(0, 201, 7), world(0, 203, 8)) blocks.fill(AIR, world(4, 201, 4), world(4, 202, 4)) blocks.fill(AIR, world(14, 201, 1), world(14, 202, 4)) blocks.fill(AIR, world(10, 201, 2), world(10, 202, 2)) blocks.fill(AIR, world(3, 201, 5), world(3, 202, 5)) blocks.fill(AIR, world(15, 201, 12), world(15, 202, 12)) blocks.fill(AIR, world(11, 201, 12), world(11, 202, 12)) blocks.fill(AIR, world(5, 201, 14), world(5, 202, 14)) blocks.fill(AIR, world(2, 201, 16), world(3, 203, 16)) blocks.fill(AIR, world(16, 201, 7), world(16, 203, 9)) blocks.fill(AIR, world(5, 205, 10), world(10, 205, 6)) blocks.fill(AIR, world(9, 205, 11), world(9, 205, 5)) blocks.fill(AIR, world(6, 205, 11), world(6, 205, 5)) blocks.fill(AIR, world(5, 205, 0), world(5, 205, 13)) blocks.fill(AIR, world(10, 205, 3), world(10, 205, 16)) # Stufen zur Verschönerung der Durchgänge blocks.place(blocks.block_with_data(materials[2], 7), world(0, 203, 7)) blocks.place(blocks.block_with_data(materials[2], 6), world(0, 203, 8)) blocks.place(blocks.block_with_data(materials[2], 5), world(2, 203, 16)) blocks.place(blocks.block_with_data(materials[2], 4), world(3, 203, 16)) blocks.place(blocks.block_with_data(materials[2], 7), world(16, 203, 7)) blocks.place(blocks.block_with_data(materials[2], 6), world(16, 203, 9)) blocks.fill(blocks.block_with_data(materials[2], 5), world(10, 204, 5), world(10, 204, 11)) blocks.fill(blocks.block_with_data(materials[2], 4), world(5, 204, 5), world(5, 204, 11)) for x in range(16): if x % 3 == 0: for z in range(16): if z % 3 == 0: player.execute("/setblock " + x + " 205 " + z + " ochre_froglight") # Treppen-Segment blocks.fill(materials[1], world(0, 220, 0), world(16, 220, 16)) blocks.fill(AIR, world(3, 220, 3), world(13, 220, 13)) for step in range(2, 14): # Treppenstufen erstellen material = materials[3] if step % 2 == 0 else materials[0] blocks.fill(material, world(step + 1, 220 + (step // 2), 5), world(step + 1, 220 + (step // 2), 8)) # Speichern der Strukturen blocks.saveStructure("chunk_default", world(0, 200, 0), world(16, 205, 16), True) blocks.loadStructure("chunk_default", world(0, 210, 0)) blocks.saveStructure("chunk_staircase", world(0, 220, 0), world(16, 225, 16), True) blocks.place(IRON_BLOCK, world(1, 211, 1)) blocks.place(GOLD_BLOCK, world(2, 211, 1)) blocks.place(GOLD_BLOCK, world(3, 211, 1)) blocks.place(EMERALD_BLOCK, world(1, 211, 2)) blocks.place(EMERALD_BLOCK, world(2, 211, 2)) blocks.place(DIAMOND_BLOCK, world(1, 212, 1)) blocks.place(DIAMOND_BLOCK, world(2, 212, 1)) blocks.place(DIAMOND_BLOCK, world(1, 211, 3)) blocks.place(DIAMOND_BLOCK, world(1, 212, 3)) # Schatz-Segment speichern blocks.saveStructure("chunk_treasure", world(0, 210, 0), world(16, 215, 16), True) blocks.loadStructure("save", world(0, 200, 0)) return 1 # Funktion zum Zusammensetzen der Segmente def build_core(length, height, width, start_pos: Position): treasure = Math.round(lcg() * length * width * height) for x in range(length): for y in range(height): for z in range(width): x_now = x * 16 + get(start_pos, Axis.X) y_now = y * 6 + get(start_pos, Axis.Y) z_now = z * 16 + get(start_pos, Axis.Z) if x != Math.floor(length / 2) or z != Math.floor(width / 2): if treasure == x + y + z: blocks.loadStructure("chunk_treasure", position(x_now, y_now, z_now), Math.round(lcg()*4), Math.round(lcg())) else: blocks.loadStructure("chunk_default", position(x_now, y_now, z_now), Math.round(lcg()*4), Math.round(lcg())) else: if treasure == x + y + z: treasure += 1 blocks.loadStructure("chunk_staircase", position(x * 16 + get(start_pos, Axis.X), y * 6 + get(start_pos, Axis.Y), z * 16 + get(start_pos, Axis.Z))) if y == 0: blocks.fill(materials[0], position(x_now, y_now, z_now), position(x_now + 16, y_now, z_now + 16)) # Öffnung zum Boden schliessen # Burgmauern def wall(start_pos: Position, end_pos: Position, mirror): sx, sy, sz = get(start_pos, Axis.X), get(start_pos, Axis.Y), get(start_pos, Axis.Z) ex, ey, ez = get(end_pos, Axis.X), get(end_pos, Axis.Y), get(end_pos, Axis.Z) dir_x = 0 dir_z = 0 outside = 1 if mirror == False else -1 # Bestimmen auf welcher Seite (+ oder -) der Mauer sich die Aussenseite befindet. 1 wenn mirror == False, sonst -1. height = abs(sy - ey) # Überprüfen welche Koordinaten identisch sind um Richtung zu bestimmen if sx == ex: dir_x = outside length = abs(sz - ez) else: dir_z = outside length = abs(sx - ex) blocks.fill(materials[0], start_pos, end_pos) # Deko blocks.fill(materials[0], start_pos.add(pos(dir_x, 1 + ey - min(sy, ey) , dir_z)), end_pos.add(pos(dir_x, 1 + sy - min(sy, ey), dir_z))) for i in range(length + 1): if i % (2 + SIMPLIFY) == 1: # Jeder 2. Block, falls SIMPLIFY verwendet wird mit entsprechend grösseren Abständen stair_data = 0 if dir_x != 0: stair_data = 4 if mirror else 5 # EAST oder WEST blocks.place(blocks.block_with_data(materials[2], stair_data), start_pos.add(pos(dir_x, max(sy, ey), i - sz))) blocks.place(materials[3], start_pos.add(pos(dir_x, max(sy, ey) + 2, i - sz))) # Zinnen # Fenster for j in range(height): if j % CHUNK_HEIGHT == 3: blocks.place(blocks.block_with_data(materials[2], 6), start_pos.add(pos(0, j, i - sz))) blocks.place(blocks.block_with_data(materials[2], 2), start_pos.add(pos(0, j-1, i - sz))) else: stair_data = 6 if mirror else 7 # SOUTH oder NORTH blocks.place(blocks.block_with_data(materials[2], stair_data), start_pos.add(pos(i - sx, max(sy, ey), dir_z))) blocks.place(materials[3], start_pos.add(pos(i - sx, max(sy, ey) + 2, dir_z))) # Zinnen # Fenster for j in range(height): if j % CHUNK_HEIGHT == 3: blocks.place(blocks.block_with_data(materials[2], 4), start_pos.add(pos(i - sx, j, 0))) blocks.place(blocks.block_with_data(materials[2], 0), start_pos.add(pos(i - sx, j-1, 0))) # Türme def tower(location: Position, radius, height): base_materials = [materials[0], materials[1], materials[5]] for i in range(height): mat = base_materials[randint(0, len(base_materials) - 1)] shapes.circle(mat, location.add(pos(0, i, 0)), radius, Axis.Y, ShapeOperation.REPLACE if i % CHUNK_HEIGHT == 0 else ShapeOperation.HOLLOW) # Auf der Höhe jedes Stockwerks einen Boden erstellen for j in range(radius + 2): if j % 2 == 0: r = radius - j / 2 shapes.circle(materials[4], location.add(pos(0, height + j, 0)), r, Axis.Y, ShapeOperation.REPLACE) def outside(length, height, width): if height > CHUNK_HEIGHT * 1: for i in range(4): # 4 Wände # Festlegen Start- und Endpositionen der aktuellen Wand (1 oder 0) # (1/0)--(1/1) # ¦ ¦ # (0/0)--(0/1) x1 = length if i in(1,2) else 0 # Wenn i == 1 oder i == 3: x1 = length, sonst x1 = 0 y1 = 0 z1 = width if i in(2,3) else 0 x2 = length if i in(0,1) else 0 y2 = height // CHUNK_HEIGHT * CHUNK_HEIGHT z2 = width if i in(1,2) else 0 invert = i in(0,3) # True oder False, abhängig davon ob i 1 oder 2 ist wall(position(x1, y1, z1), position(x2, y2, z2), invert) # Wand if TOWERS == True: tower(position(x1, 0, z1), T_RADIUS, height + 2) # Eingangstor blocks.fill(AIR, position(length // 2 - 1, 0, 0), position(length // 2 + 1, 4, 0)) blocks.fill(DARK_OAK_FENCE, position(length // 2 - 2, 1, 1), position(length // 2 + 2, 5, 1)) blocks.place(blocks.block_with_data(materials[2], 5), position(length // 2 - 1, 4, 0)) blocks.place(blocks.block_with_data(materials[2], 4), position(length // 2 + 1, 4, 0)) # Böden for i in range(height + 1): if i % CHUNK_HEIGHT == 0: blocks.fill(materials[0], position(0, i, 0), position(length, i, width)) def tor_auf(a, b): blocks.fill(AIR, position(L // 2 - 2, 1, 1), position(L // 2 + 2, 5, 1)) def tor_zu(a, b): blocks.fill(DARK_OAK_FENCE, position(L // 2 - 2, 1, 1), position(L // 2 + 2, 5, 1)) def main(length, height, width, start_pos: Position): global L # Global, da sonst die auf() und zu() Funktionen des Eingangstors nicht verwendet weden können. L = length if length < 16 + 2 * MIN_PADDING + 4 or width < 16 + 2 * MIN_PADDING + 4 or height < CHUNK_HEIGHT: player.execute("""/tellraw @a {"rawtext":[{"text":"§c§lError: values to small"}]}""") return 0 player.execute("""/tellraw @a {"rawtext":[{"text":"§a§lErstellung gestartet..."}]}""") # Chatbefehle player.on_chat("Sesam, schliesse dich!", tor_zu) player.on_chat("Sesam, öffne dich!", tor_auf) # Burg bauen chunk_builder() outside(length, height, width) core_chunks_x = (length - 2 * MIN_PADDING) // 16 core_chunks_z = (width - 2 * MIN_PADDING) // 16 core_start_x = (length - core_chunks_x * 16) // 2 core_start_z = (width - core_chunks_z * 16) // 2 build_core(core_chunks_x, height // CHUNK_HEIGHT, core_chunks_z, position(core_start_x, 0, core_start_z)) player.execute("""/tellraw @a {"rawtext":[{"text":"§a§lDone!"}]}""") return 1 main(54, 18, 38, position(0, 0, 0))