diff --git a/2021-oop1/ku/A2_Angabe_M1/Makefile b/2021-oop1/ku/A2_Angabe_M1/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..65e1c2f4c768256e3a10efcdc784230f729796a8
--- /dev/null
+++ b/2021-oop1/ku/A2_Angabe_M1/Makefile
@@ -0,0 +1,53 @@
+CXX           := clang++
+CXXFLAGS      := -Wall -Wextra -pedantic -std=c++17 -g -c -o
+ASSIGNMENT    := oop1
+
+BUILDDIR      := build
+SOURCES       := $(wildcard *.cpp)
+OBJECTS       := $(patsubst %,$(BUILDDIR)/%,${SOURCES:.cpp=.o})
+
+TESTRUNNER_EXECUTABLE := ../testrunner
+
+.DEFAULT_GOAL := help
+.PHONY: reset clean bin lib all run test help
+
+prepare:
+	mkdir -p $(BUILDDIR)
+
+$(BUILDDIR)/%.o: %.cpp
+	@echo -e "[\033[36mINFO\033[0m] Compiling object:" $<
+	$(CXX) $(CXXFLAGS) $@ $< -MMD -MF ./$@.d
+
+$(ASSIGNMENT) : $(OBJECTS)
+	@echo -e "[\033[36mINFO\033[0m] Linking objects:" $@
+	$(CXX) -pthread -o $@ $^
+
+clean:						## cleans up project folder
+	@echo -e "[\033[36mINFO\033[0m] Cleaning up folder..."
+	rm -f $(ASSIGNMENT)
+	rm -rf ./$(BUILDDIR)
+	rm -rf testreport.html
+	rm -rf ./valgrind_logs
+
+bin: prepare $(ASSIGNMENT)	## compiles project to executable binary
+	@echo -e "[\033[36mINFO\033[0m] Compiling binary..."
+	chmod +x $(ASSIGNMENT)
+
+all: clean bin				## all of the above
+
+run: all					## runs the project
+	@echo -e "[\033[36mINFO\033[0m] Executing binary..."
+	./$(ASSIGNMENT)
+
+test: clean					## runs public testcases on the project
+	@echo -e "[\033[36mINFO\033[0m] Executing testrunner..."
+	chmod +x testrunner
+	./$(TESTRUNNER_EXECUTABLE) -c test.toml
+
+help:						## prints the help text
+	@echo -e "Usage: make \033[36m<TARGET>\033[0m"
+	@echo -e "Available targets:"
+	@awk -F':.*?##' '/^[a-zA-Z_-]+:.*?##.*$$/{printf "  \033[36m%-10s\033[0m%s\n", $$1, $$2}' $(MAKEFILE_LIST)
+
+-include $(wildcard *.d)
+
diff --git a/2021-oop1/ku/A2_Angabe_M1/README.md b/2021-oop1/ku/A2_Angabe_M1/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..5ae60e2213dbcd183265d6e572729058fc5335ce
--- /dev/null
+++ b/2021-oop1/ku/A2_Angabe_M1/README.md
@@ -0,0 +1,91 @@
+# Assignment 2
+
+## Einleitung
+
+In Assignment 2 (A2) der Konstruktionsübung (KU) wird ein Spiel programmiert, welches dem Brettspiel "Das verrückte Labyrinth" nachempfunden wurde.
+Das Spielprinzip wird auf dieser Seite allgemein beschrieben und sollte bei der Implementierung auch eingehalten werden. Die exakte Angabe zu einzelnen Assignments können Sie den folgenden Links entnehmen:
+
+- [Ass2](description/Ass2.md)
+
+Ganz unten auf dieser Seite finden Sie die Spezifikationen, die einzuhalten sind!
+
+## Spielaufbau
+
+Gespielt wird auf einem Spielfeld, welches 49 Felder umfasst (7x7 Felder). 16 dieser Felder sind mit jeweils einer Gangkarte belegt, welche nicht verschoben werden kann. Die anderen 33 Felder sind auch mit jeweils einer Gangkarte belegt, jedoch können diese Gangkarten verschoben werden, die Zuordnung einer Gangkarte zu einem Feld ist in diesem Fall also nicht fix.
+
+Es gibt insgesamt 50 Gangkarten: 16 fixe und 33 mobile (wie oben beschrieben) und eine zusätzliche Gangkarte, welche zum Verschieben verwendet wird.
+Außerdem gibt es in diesem Spiel 24 Schatzkarten und Schätze und 4 Spielfiguren.
+
+## Spielbeginn
+
+Am Anfang des Spiels werden die Gangkarten auf den freien Plätzen des Spielfelds verteilt. Dabei bleibt eine Gangkarte übrig.
+
+Als nächstes werden die Schatzkarten verdeckt und gleichmäßig an die Spielenden verteilt.
+
+Danach wählen alle Spielenden eine Spielfigur und jede Spielfigur wird auf die zugehörige Startposition auf dem Spielfeld gestellt.
+
+## Spielziel
+
+Ziel des Spiels ist es, alle Schätze zu sammeln, welche auf den eigenen Schatzkarten abgebildet sind und wieder an den Start zurückzukehren. Gewonnen hat also, wer zuerst alle Schätze eingesammelt hat und wieder an der eigenen Startposition steht.
+
+## Spielablauf
+
+Die Spielenden führen abwechselnd ihren Spielzug aus, bis das Spielende erreicht ist. Wie ein Zug im Detail aussieht, wird nun erklärt.
+
+Am Anfang eines Zuges benötigt man eine aktuelle Schatzkarte. Wenn man noch keine hat, so schaut man (geheim) die oberste Schatzkarte des eigenen Stapels an, diese wird zur aktuellen Schatzkarte, bis dieser Schatz aufgesammelt wurde.
+
+Ein Spielzug besteht immer aus zwei Schritten:
+1. Gänge verschieben
+2. Spielfigur ziehen
+
+### 1. Gänge verschieben
+
+Die freie (das heißt nicht am Spielfeld liegende) Gangkarte wird genommen und in beliebiger Orientierung von der Seite an einer der markierten Stellen eingeschoben. Dadurch wird eine andere Gangkarte herausgeschoben. Die Gangkarten dürfen aber nicht so verschoben werden, dass sich das Spielfeld wieder im Zustand des vorherigen Zuges befindet. (Das heißt, "Zurückschieben" ist nicht erlaubt.)
+
+Wird beim Verschieben eine Spielfigur aus dem Spiel herausgeschoben, so landet sie auf der anderen Seite – also auf der Gangkarte, welche gerade hineingeschoben wurde.
+
+Es muss immer eine Gangkarte eingeschoben werden; ein Überspringen dieses Schrittes ist nicht erlaubt.
+
+### 2. Spielfigur ziehen
+
+Nun darf die eigene Spielfigur an jeden Punkt im Labyrinth verschoben werden, welcher von der aktuellen Position mit einem durchgängigen Gang verbunden ist, auch wenn dort schon eine Spielfigur steht. Das Verschieben der Spielfigur ist optional, das heißt, dieser Schritt kann ausgelassen werden.
+
+Wenn die Spielfigur am Ende des Zuges auf der Gangkarte mit dem gesuchten Schatz steht, gilt dieser als gefunden (bzw. aufgesammelt). Beim Beginn des nächsten Zuges darf die oberste Schatzkarte des eigenen Stapels aufgedeckt werden, der darauf abgebildete Schatz ist dann der aktuelle Schatz, der gefunden werden muss.
+
+## Spielende
+
+Wer alle eigenen Schätze gefunden hat, muss wieder an die eigene Startposition zurück. Wer das als Erste*r schafft, hat das Spiel gewonnen und das Spiel ist zu Ende.
+
+## Spezifikation
+
+- nur geforderte Ausgaben
+- Die Random-Klasse (Random.cpp, Random.hpp) darf nicht verändert werden
+
+### Erlaubte Bibliotheken
+
+- alle Bibliotheken der C++ Standard Library
+
+### Abgabe und Bewertung
+
+- Push auf das Gitlab Repository des Teams **auf einen Branch namens `submission`**
+- **Abzugeben bis: 29.5.2021 um 23:59 Uhr**
+
+#### Ausbesserung
+
+Auch wenn Sie die benötigten 50 % der öffentlichen Test Cases am Ende der Abgabefrist noch nicht bestehen, bedeutet das noch nicht das Ausscheiden aus der KU für Sie. Es gibt die Möglichkeit einer **Ausbesserung**, welche anstelle von Assignment 3 gemacht werden kann. Diese Ausbesserung _ersetzt_ die bei A2 erreichten Punkte. Informationen dazu gab es im ersten Stream des Semesters am 3.3.2021.
+
+#### Teilnahmevoraussetzung für Assignment 3
+
+Da Assignment 3 auf A2 aufbauen wird, sind für eine Teilnahme an Assignment 3 zumindest zwei Drittel aller Test Cases in A2 zu bestehen.
+
+#### Bewertung
+
+- Bei Assignment 2 können 64 Punkte erreicht werden.
+- Die Kriterien, nach welchen Ihr Programm bewertet wird, können Sie folgenden Dokumenten entnehmen:
+  - [Beurteilungsschema](https://tc.tugraz.at/main/mod/page/view.php?id=157196)
+  - [Bewertung von Übungsbeispielen](https://tc.tugraz.at/main/mod/page/view.php?id=138898)
+  - [Style Guide](https://tc.tugraz.at/main/mod/page/view.php?id=138899)
+
+#### Updates
+
+Während das Assignment von Ihnen bearbeitet wird, wird es noch zu dem einen oder anderen Update kommen (z. B. etwaige Änderungen/Präzisierungen an der Angabe oder vielleicht sogar die Veröffentlichung einer Möglichkeit auf Bonuspunkte). An diese Updates gelangen Sie über einen Upstream-Pull mit Git.
diff --git a/2021-oop1/ku/A2_Angabe_M1/Random.cpp b/2021-oop1/ku/A2_Angabe_M1/Random.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ff437f5a1d80573c1b4ae9f70c3e5284467fd681
--- /dev/null
+++ b/2021-oop1/ku/A2_Angabe_M1/Random.cpp
@@ -0,0 +1,102 @@
+///---------------------------------------------------------------------------------------------------------------------
+/// Random.cpp
+///
+/// Authors: Tutors
+///---------------------------------------------------------------------------------------------------------------------
+
+#include "Random.hpp"
+
+#include <stdexcept>
+#include <iostream>
+#include <cstdlib>
+#include <sstream>
+#include <string>
+
+using Oop::Random;
+
+///---------------------------------------------------------------------------------------------------------------------
+std::string const Random::CARD_SEED{"RAND_SEED"};
+std::string const Random::ORIENTATION_SEED{"RAND_SEED"};
+size_t const Random::ORIENTATION_MIN{0};
+size_t const Random::ORIENTATION_MAX{3};
+
+///---------------------------------------------------------------------------------------------------------------------
+Random::Random() :
+  card_mersenne_twister_{getSeed(CARD_SEED)},
+  orientation_mersenne_twister_{getSeed(ORIENTATION_SEED)},
+  orientations_{ORIENTATION_MIN, ORIENTATION_MAX}
+{
+}
+
+///---------------------------------------------------------------------------------------------------------------------
+Random& Random::getInstance()
+{
+  static Random instance{};
+  return instance;
+}
+
+///---------------------------------------------------------------------------------------------------------------------
+size_t Random::getRandomCard(size_t const number_of_cards_left)
+{
+  std::uniform_int_distribution<size_t> normal_distribution{1, number_of_cards_left};
+  return normal_distribution(card_mersenne_twister_);
+}
+
+///---------------------------------------------------------------------------------------------------------------------
+size_t Random::getRandomOrientation()
+{
+  return orientations_(orientation_mersenne_twister_);
+}
+
+///---------------------------------------------------------------------------------------------------------------------
+size_t Random::getSeed(std::string const environment_variable)
+{
+  size_t seed{};
+
+  try
+  {
+    seed = getEnvironmentSeed(environment_variable);
+  }
+  catch (std::runtime_error& exception)
+  {
+    seed = getHardwareSeed();
+  }
+
+  return seed;
+}
+
+///---------------------------------------------------------------------------------------------------------------------
+size_t Random::getEnvironmentSeed(std::string const environment_variable)
+{
+  char* environment_seed{getenv(environment_variable.c_str())};
+
+  if (environment_seed)
+  {
+    return parseSeed(environment_seed);
+  }
+
+  throw  std::runtime_error{"Environment variable \"" + environment_variable + "\" does not exist."};
+}
+
+///---------------------------------------------------------------------------------------------------------------------
+size_t Random::getHardwareSeed()
+{
+  std::random_device seed_from_hardware{};
+  return seed_from_hardware();
+}
+
+///---------------------------------------------------------------------------------------------------------------------
+size_t Random::parseSeed(std::string const seed)
+{
+  std::stringstream seed_stream{seed};
+  size_t seed_value{};
+
+  seed_stream >> seed_value;
+
+  if (seed_stream.eof() && !seed_stream.bad())
+  {
+    return seed_value;
+  }
+
+  throw  std::runtime_error{"Could not parse the seed \"" + seed + "\"."};
+}
diff --git a/2021-oop1/ku/A2_Angabe_M1/Random.hpp b/2021-oop1/ku/A2_Angabe_M1/Random.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..d0e5b4c5c4bb43528cf864a0c01b8c273a821e9d
--- /dev/null
+++ b/2021-oop1/ku/A2_Angabe_M1/Random.hpp
@@ -0,0 +1,116 @@
+///---------------------------------------------------------------------------------------------------------------------
+/// Random.hpp
+///
+/// Authors: Tutors
+///---------------------------------------------------------------------------------------------------------------------
+
+#ifndef RANDOM_HPP
+#define RANDOM_HPP
+
+#include <random>
+#include <string>
+
+namespace Oop
+{
+  ///-------------------------------------------------------------------------------------------------------------------
+  /// Random class
+  /// Generates random values representing the card to distribute or the rotation of the card.
+  ///
+  class Random final
+  {
+    public:
+      ///---------------------------------------------------------------------------------------------------------------
+      /// Returns an instance of the Random class (Singleton pattern).
+      /// Example: Random::getInstance().getRandomOrientation()
+      ///
+      static Random& getInstance();
+
+      ///---------------------------------------------------------------------------------------------------------------
+      /// Deleted copy constructor.
+      ///
+      Random(Random const&) = delete;
+
+      ///-----------------------------------------------------------------------------------------------------------------
+      /// Deleted assignment operator.
+      ///
+      Random& operator=(Random const&) = delete;
+
+      ///-----------------------------------------------------------------------------------------------------------------
+      /// Get the number of the next card to be distributed.
+      ///
+      /// @param number_of_cards_left The total number of cards left to distribute.
+      /// @return A random number in range [1, number_of_cards_left].
+      ///
+      size_t getRandomCard(size_t const number_of_cards_left);
+
+      ///-----------------------------------------------------------------------------------------------------------------
+      /// Get the number of times the card should be rotated clock-wise.
+      ///
+      /// @return A random number in range [0, 3]
+      ///
+      size_t getRandomOrientation();
+
+    private:
+      ///---------------------------------------------------------------------------------------------------------------
+      /// Mersenne Twister pseudo-random generators
+      ///
+      std::mt19937 card_mersenne_twister_;
+      std::mt19937 orientation_mersenne_twister_;
+
+      ///---------------------------------------------------------------------------------------------------------------
+      /// Uniform distribution of all possible orientations
+      ///
+      std::uniform_int_distribution<size_t> orientations_;
+
+      ///---------------------------------------------------------------------------------------------------------------
+      /// Names of the environment seeds
+      ///
+      static std::string const CARD_SEED;
+      static std::string const ORIENTATION_SEED;
+
+      ///---------------------------------------------------------------------------------------------------------------
+      /// Orientation number range: [min, max]
+      ///
+      static size_t const ORIENTATION_MIN;
+      static size_t const ORIENTATION_MAX;
+
+      ///---------------------------------------------------------------------------------------------------------------
+      /// Private constructor. Access to class possible only through getInstance.
+      ///
+      Random();
+
+      ///---------------------------------------------------------------------------------------------------------------
+      /// Gets the seed from environment.
+      /// If the environment variable does not exist it falls back to generating the seed.
+      ///
+      /// @param environment_variable Name of the environment variable holding the seed.
+      /// @returns A number suitable to seed the random number generator.
+      ///
+      size_t getSeed(std::string const environment_variable = nullptr);
+
+      ///---------------------------------------------------------------------------------------------------------------
+      /// Gets the seed from environment.
+      ///
+      /// @param environment_variable Name of the environment variable holding the seed.
+      /// @return A number from the environment_variable suitable to seed the random number generator.
+      ///
+      size_t getEnvironmentSeed(std::string const environment_variable);
+
+      ///---------------------------------------------------------------------------------------------------------------
+      /// Generates a random seed.
+      ///
+      /// @return A hardware generated number suitable to seed the random number generator.
+      ///
+      size_t getHardwareSeed();
+
+      ///---------------------------------------------------------------------------------------------------------------
+      /// Parses the seed to a numerical value.
+      ///
+      /// @param environment_seed Seed to parse.
+      /// @return The numerical value of the seed parameter.
+      ///
+      size_t parseSeed(std::string const seed);
+  };
+}
+
+#endif
\ No newline at end of file
diff --git a/2021-oop1/ku/A2_Angabe_M1/description/Ass2.md b/2021-oop1/ku/A2_Angabe_M1/description/Ass2.md
new file mode 100644
index 0000000000000000000000000000000000000000..3302d1867e21c924f10ea4f9d243ced508589dc7
--- /dev/null
+++ b/2021-oop1/ku/A2_Angabe_M1/description/Ass2.md
@@ -0,0 +1,11 @@
+# A2 Angabe
+
+Assignment 2 ist in zwei Milestones unterteilt. Es wird empfohlen, zuerst Milestone 1 abzuschließen, bevor mit Milestone 2 begonnen wird, da Milestone 2 auf Milestone 1 aufbaut.
+
+Die genaue Beschreibung zu den einzelnen Milestones finden sich unter:
+
+- [Milestone 1](Milestone_1.md)
+
+## Milestone 1
+
+Hier wird die Grundstruktur des Spiels (welche zum Teil schon vorgegeben ist) und einige Basisfunktionen erstellt.
\ No newline at end of file
diff --git a/2021-oop1/ku/A2_Angabe_M1/description/Milestone_1.md b/2021-oop1/ku/A2_Angabe_M1/description/Milestone_1.md
new file mode 100644
index 0000000000000000000000000000000000000000..d1f741cc8ed8362463df4ac9c2a03475ca7ae74f
--- /dev/null
+++ b/2021-oop1/ku/A2_Angabe_M1/description/Milestone_1.md
@@ -0,0 +1,419 @@
+# Angabe Milestone 1
+
+Ziel des 1. Milestones ist es, eine Grundstruktur für das Spiel zu erstellen und das Spielfeld auszugeben. Im Rahmen von Milestone 1 werden demnach grundlegende Klassen erstellt.
+
+## Vorgegebene Klassen
+
+Mit dem Erstellen der Klassen sollte am besten begonnen werden, um schon eine Grundstruktur für das Spiel zu haben.
+
+Die hier angegebenen Klassen können so implementiert werden, wie sie hier beschrieben werden. Es ist erlaubt, diese auch zu erweitern wenn dies notwendig erscheint oder eine andere (objektorientierte) Programmstruktur zu wählen.
+
+Wenn in den folgenden Ausführungen kein Datentyp vorgegeben ist, soll eigenständig ein passender Datentyp gewählt werden. 
+
+Sofern nicht näher beschrieben, sind bei den Klassen Konstruktor(en) und Destruktor sowie Getter und Setter für alle Attribute zu implementieren.
+
+### Klasse `Treasure`
+Klasse, die einen Schatz repräsentiert. (Beim originalen Brettspiel wird zwischen Schatzkarten von Spielenden – sie geben die zu suchenden Schätze an – und Schätzen auf Gangkarten unterschieden. Im Gegensatz zum Brettspiel müssen wir hier nicht zwischen Schatzkarten und den tatsächlichen Schätzen unterscheiden – wir können aus dem Kontext erkennen, worum es sich handeln muss. Schätze im `card_stack_`s des `Player`s sind immer Schatzkarten, am Spielfeld sind es Schätze.)
+
+#### Attribute
+
+- `name_` (Name des Schatzes)
+- `treasure_id_` (Nummer des Schatzes)
+- `found_` (zeigt an, ob die Karte gefunden wurde)
+
+#### Methoden
+
+- Konstruktor mit den Parametern `(name, treasure_id)`
+- Getter für `name_`, `treasure_id_` und `found_`
+- Setter für `found_` (keine Setter für `name_` und `treasure_id_`)  
+
+
+### Klasse `Tile`
+Klasse, die eine Gangkarte repräsentiert.
+
+#### Enums
+Diese Enum Klassen dienen zur Beschreibung der Gangkarten und können vor der Definition von Tile definiert werden.
+
+```C++
+enum class TileType {T, L, I, O, U, X};
+```
+Die Buchstaben stehen für die verschiedenen möglichen Spielfeldkarten: 
+- T oben geschlossen, sonst überall offen
+- L oben und rechts offen, sonst geschlossen
+- I oben und unten offen, sonst geschlossen
+- U oben offen, sonst geschlossen
+- X überall offen
+- O überall geschlossen
+
+Die Rotation beschreibt, um wie viel eine Gangkarte gedreht wurde. Das heißt ein "L" mit einer Rotation von "DEG180" ist dann links und unten offen und ansonsten geschlossen. Die Rotation enspricht immer der Rotation in mathematisch positive Richtung, das heißt Drehung gegen den Urzeigersinn.
+```C++
+enum class Rotation {DEG0 = 0, DEG90 = 1, DEG180 = 2, DEG270 = 3};
+```
+
+
+#### Attribute
+
+- TileType `type_` (Richtung, wo offen)
+- Rotation `rotation_` (Gibt die Orientierung des Tiles an)
+- vector `players_` (enthält Zeiger zu `Player`n, welche sich auf der Gangkarte befinden)
+
+#### Methoden
+- pure virtual Methode `getTileString()` (gibt den String zurück, welcher das aktuelle Spielfeld auf der Map repräsentiert)
+- `getRotationValue()` Gibt die Orientierung (rotation_) in Grad zurück. 0 -> 0°, 1 -> 90°, 2 -> 180° und 3 -> 270°.
+- `string getTileTypeString()` (gibt den Kartentyp in Form eines Strings zurück. (entweder "T", "L", "I", "O", "U" oder "X").
+- Getter für `type_`, `rotation_` und `players_`
+- Setter für `rotation_` (kein Setter für `type_`)
+
+### Klasse `StartTile` (Subklasse von `Tile`)
+Klasse, die eine Gangkarte repräsentiert, welche auch als Startfeld für eine*n Spielende*n dienen kann.
+
+#### Attribute
+
+- `player_color_` (Zeigt an, für welchen `Player` die Gangkarte als Startfeld dient)
+
+#### Methoden
+- ein Getter für `player_color_`
+- `getTileString()` (gibt den String zurück, welcher das aktuelle Spielfeld für die Map repräsentiert).
+
+
+### Klasse `TreasureTile` (Subklasse von `Tile`)
+Klasse, die eine Gangkarte mit einem Schatz repräsentiert.
+
+#### Attribute
+
+- `treasure_` (verweist auf den `Treasure`)
+- `collected_` (zeigt an, ob der Schatz aufgesammelt wurde)
+
+#### Methoden
+- Setter, Getter
+- `collectTreasure()` (für das Aufsammeln des Schatzes)
+- `getTileString()` (gibt den String zurück, welcher das aktuelle Spielfeld für die Map repräsentiert).
+
+### Klasse `NormalTile` (Subklasse von `Tile`)
+Klasse, die eine Gangkarte repräsentiert, die kein Startfeld sein kann und auch keinen Gegenstand enthält.
+
+#### Methoden
+
+- `getTileString()` (gibt den String zurück, welcher das aktuelle Spielfeld für die Map repräsentiert).
+
+
+### Klasse `Player`
+Klasse, die eine Spielfigur bzw. eine*n Spielende*n repräsentiert.
+
+#### Attribute
+- `covered_stack_` Vektor mit dem (Treasure *) stack für die zu suchenden Schätze
+- `nr_found_treasures_` Anzahl der gefundenen Schätze
+
+### Klasse `Game`
+
+Die Spielklasse regelt das Spiel und hat die Daten, die es dazu braucht. Diese gibt es nur ein Mal, weshalb sie als Singleton realisiert werden sollte. ([Erklärung Singleton Klasse](Singleton.md))
+
+## Spielstart
+
+Das Spiel wird ohne Kommandozeilenparameter gestartet und gibt zunächst folgenden Text aus:
+
+```
+Welcome to the Wild OOP Labyrinth!!!\n
+```
+
+Dann wird abgefragt, mit wie vielen Personen das Spiel gespielt wird:
+```
+Player Count (2-4): 
+```
+
+Als Eingabe ist hier nur '2', '3' oder '4' erlaubt, also eine Zahl zwischen 2 und 4. Wird etwas anderes eingegeben, soll die folgende Meldung ausgegeben werden und wieder nach der Anzahl der Mitspielenden gefragt werden.
+
+```
+Wrong Input only a Number from 2 to 4 is allowed!\n
+```
+
+Nun muss eine Instanz der `Random` Klasse, welche zur Verfügung gestellt wird, erstellt werden, um eine zufällige Verteilung der Karten und des Spielfeldes zu erhalten. Es muss unbedingt die von der LV-Leitung bereitgestellte Klasse verwendet werden – ansonsten funktionieren die automatischen Tests nicht! 
+Die Instanz sollte solange das Spiel läuft verfügbar sein. Sie sollte also nur einmal erstellt werden und dann immer genutzt werden, wenn eine Zufallszahl benötigt wird.
+
+Danach werden die Schatzkarten verteilt (wie im Abschnitt "Verteilen der Schatzkarten" beschrieben).
+
+Nach dem Verteilen der Schatzkarten wird das Spielfeld belegt (wie unter "Belegen des Spielplans" beschrieben). 
+
+Anschließend wird das Spielfeld ein Mal ausgegeben. Danach wird ein Prompt mit dem aktiven `Player` ausgegeben und auf den Input des/der Spielenden gewartet.
+
+Die Reihenfolge der `Player` ist Red, Yellow, Green und dann Blue.
+
+Die Prompt sieht wie folgt aus:
+```
+PLAYERCOLOR > 
+```
+
+Dies wäre am Anfang also:
+```
+RED > 
+```
+
+Wird `EOF` eingegeben (End of File, nicht der String "EOF"), wird das Programm mit dem Returnwert 0 beendet.
+
+In Milestone 1 müssen noch keine weiteren Usereingaben für den Prompt behandelt werden. Für Milestone 1 reicht es also, nur auf `EOF` bei der Usereingabe zu achten.
+
+## Verteilen der Schatzkarten
+
+Die Schatzkarten haben eine feste ID.
+
+Die IDs der einzelnen Schätze können folgender Tabelle entnommen werden:
+| Schatznummer  | Schatzname    |
+| ------------- |:-------------:| 
+| 01            | Totenkopf     |
+| 02            | Schwert       |  
+| 03            | Goldsack      |
+| 04            | Schlüsselbund |
+| 05            | Sombrero      |
+| 06            | Ritterhelm    |
+| 07            | Buch          |
+| 08            | Krone         |
+| 09            | Schatztruhe   |
+| 10            | Kerzenleuchte |
+| 11            | Schatzkarte   |
+| 12            | Goldring      |
+| 13            | Eule          |
+| 14            | Hofnarr       |
+| 15            | Eidechse      |
+| 16            | Käfer         |
+| 17            | Flaschengeist |
+| 18            | Kobold        |
+| 19            | Schlange      |
+| 20            | Geist         |
+| 21            | Fledermaus    |
+| 22            | Spinne        |
+| 23            | Ratte         |
+| 24            | Motte         |
+
+Am Anfang jedes Spieles werden diese Karten genau in dieser Reihenfolge erstellt und dann folgendermaßen auf die Mitspielenden aufgeteilt.
+
+Es wird mit der bereitgestellten `Random`-Klasse eine Zahl von 1 bis zur Anzahl der noch nicht ausgeteilten Schatzkarten bestimmt (Aufruf der Funktion get `getRandomCard()`) und die Karte, welche am Stapel (Array/Vector) diese Position hat, an den nächsten Player ausgeteilt. Die Reihenfolge der Farben ist Rot, Gelb, Grün und Blau.
+
+Spielen weniger als 4 Personen das Spiel, so wird/werden die Farbe/Farben am Ende ausgelassen. Bei einem Spiel mit 3 Personen gibt es also nur die Farben Rot, Gelb und Grün, bei 2 Personen nur Rot und Gelb.
+
+Die Karten werden der Reihe nach ausgegeben, bis es keine Karte mehr zum Verteilen gibt, also alle Karten einem Player zugewiesen wurden.
+
+## Ausgabe des Spielfelds
+
+Das Spielfeld, auf dem die Karten liegen, soll als ASCII-Art im Terminal ausgegeben werden. Eine Karte besteht dabei aus 9*5 Zeichen (9 Spalten und 5 Zeilen). Sofern sich etwas/jemand auf der Karte befindet, soll dies mit einem Charakter angezeigt werden:  
+`P` für einen Player direkt gefolgt vom Anfangsbuchstaben der Farbe; für Player Blue also `PB`. Stehen mehrere Player auf einer Karte so wird P direkt gefolgt von den Buchstaben der Player ausgegeben. Wären also Player Red und Yellow auf der gleichen Karte, wäre die entsprechende Ausgabe `PRY`.
+Die Ausgabe erfolgt in der 4. Zeile der Karte mit einem Abstand von 3 Zeichen zum linken Rand außer bei 4 Playern, dort sind es nur 2 Zeichen Abstand.
+
+Ein Schatz auf einer Karte wird mit `T` und der zweistelligen Schatz-ID angezeigt; für Schatz 1 wäre dies z. B. `T01`.
+Befindet sich auf einer Karte ein Schatz, so wird dies in der 3. Zeile der Karte angezeigt mit einem Abstand von 3 Zeichen von links.
+Wichtig: Wurde ein Schatz schon gefunden, das heißt `collected_` ist `true`, so wird der Schatz nicht mehr angezeigt.
+
+Die ASCII-Karten bestehen aus den Zeichen ``'█'`` und ``' '``.
+
+Folgende ASCII-Karten existieren: (Die Buchstaben zeigen dabei an, wo sich die Zeichen für einen Schatz / Player befinden sollen.)
+
+
+Gerader Gang horizontal
+
+```
+█████████
+         
+   T01   
+   PY    
+█████████
+```
+
+Gerader Gang vertikal
+
+```
+██     ██
+██     ██
+██     ██
+██     ██
+██     ██
+```
+
+Verzweigung nach rechts
+
+```
+██     ██
+██       
+██       
+██       
+██     ██
+```
+
+Verzweigung nach oben
+
+```
+██     ██
+         
+         
+         
+█████████
+```
+
+Verzweigung nach links
+
+```
+██     ██
+       ██
+       ██
+       ██
+██     ██
+```
+
+Verzweigung nach unten
+
+```
+█████████
+         
+         
+         
+██     ██
+```
+
+Kurve oben-rechts
+
+```
+██     ██
+██       
+██       
+██       
+█████████
+```
+
+Kurve oben-links
+
+```
+██     ██
+       ██
+       ██
+       ██
+█████████
+```
+
+Kurve unten-links
+
+```
+█████████
+       ██
+       ██
+       ██
+██     ██
+```
+
+Kurve unten-rechts
+
+```
+█████████
+██       
+██       
+██       
+██     ██
+```
+
+## Spielfeld
+Beispiel:
+
+```
+Player Red(R)    |                 |                 |    Player Yellow(Y)
+Treasure: X/6    V                 V                 V    Treasure: X/6
+        1        2        3        4        5        6        7    
+    ███████████     █████████████     █████████████████████████████
+    ██ (R)   ██     ██         ██     ██                     (Y) ██
+   1██       ██     ██   T01   ██     ██   T02                   ██
+    ██       ██     ██         ██     ██                         ██
+    ██     ████     ████     ████     ████     █████████████     ██
+    ██     ████     ████     █████████████     ████     ████     ██
+           ████     ████                       ██         ██       
+-->2       ████     ████ T13               T14 ██   S15   ██        <--
+           ████     ████                       ██         ██       
+    ███████████     ████████████████████████████████████████     ██
+    ██     █████████████     ████     █████████████     ████     ██
+    ██                ██                                         ██
+   3██ T03            ██ T04               T05               T06 ██
+    ██                ██                                         ██
+    ██     █████████████     █████████████     █████████████     ██
+    ███████████     ████     ████     █████████████     ████     ██
+                    ████              ██         ██              ██
+-->4                ████        T16   ██         ██  T17         ██ <--
+                    ████              ██         ██              ██
+    ██████████████████████████████████████     ████████████████████
+    ██     ████     ████     █████████████     █████████████     ██
+    ██              ██                         ████              ██
+   5██ T07    T18   ██   T08              T09  ████  T19     T10 ██
+    ██              ██                         ████              ██ 
+    ██     ██████████████████████     ████     ████     ████     ██
+    ██     █████████████     ████     ████     ████     ███████████
+           ██                ████     ██       ██                  
+-->6   T20 ██            T21 ████     ██  T22  ██             T23   <--
+           ██                ████     ██       ██                  
+    ████████████████████     ████     █████████████████████████████
+    ██     ████     ████     ████     ████     █████████████     ██
+    ██ (G)   ██                       ██                     (B) ██
+   7██       ██          T11      T24 ██   T12                   ██
+    ██       ██                       ██                         ██
+    ███████████     ███████████████████████████████     ███████████
+Player Green(G)  Ʌ                 Ʌ                 Ʌ    Player Blue(B)
+Treasure: X/6    |                 |                 |    Treasure: X/6
+
+```
+
+Wie beim Brettspiel soll angezeigt werden, wo Karten verschoben werden können und wo nicht. Pfeile rund um das Spielfeld markieren bewegliche Reihen und Spalten.
+
+Für jede&ast;n Spielende&ast;n wird auch angezeit, wie viele Schätze schon eingesammelt wurden und wie viele noch zu finden sind. Dabei steht das X in dem obigen Beispiel für die Anzahl der von dem jeweiligen Spielenden bereits gefundenen Schätze und die 6 steht für die insgesamt zu findenden Schätze. Die Anzahl der zu findenden Schätze pro Person, hängt von der Anzahl der Spielenden ab. Bei zwei Speilenden müsste jede&ast;r Spielende nicht 6 Schätze einsammeln sondern 12 und bei 3 Spielenden müssen alle 8 Schätze finden. Es werden nur für mitspielende Player Informationen zu Farbe und Schätzen angezeigt. Player, die nicht im Spiel sind (dieser Fall tritt bei weniger als 4 Spielenden auf) würden in obiger Ausgabe keine Erwähnung finden. 
+## Belegen des Spielplans
+
+Es gibt auf dem Spielplan fix zugewiesene Karten. Diese sind:
+
+1:1, 1:3, 1:5, 1:7\
+3:1, 3:3, 3:5, 3:7\
+5:1, 5:3, 5:5, 5:7\
+7:1, 7:3, 7:5, 7:7
+
+Dadurch ergibt sich der folgende vorgegebene Spielplan:
+```
+█████████         █████████         █████████         █████████
+██                                                           ██
+██ (R)               T01               T02               (Y) ██
+██                                                           ██
+██     ██         ██     ██         ██     ██         ██     ██
+
+
+
+
+
+██     ██         ██     ██         █████████         ██     ██
+██                ██                                         ██
+██ T03            ██ T04               T05               T06 ██
+██                ██                                         ██
+██     ██         ██     ██         ██     ██         ██     ██
+
+
+
+
+
+██     ██         ██     ██         ██     ██         ██     ██
+██                                         ██                ██
+██ T07               T08               T09 ██            T10 ██
+██                                         ██                ██
+██     ██         █████████         ██     ██         ██     ██
+
+
+
+
+
+██     ██         ██     ██         ██     ██         ██     ██
+██                                                           ██
+██ (G)               T11               T12               (B) ██
+██                                                           ██
+█████████         █████████         █████████         █████████
+```
+
+Diese Karten des Spielplans können auch nicht verschoben werden und sind dadurch immer fix vorgegeben. 
+
+Die restlichen Karten werden am Anfang des Spieles immer neu verteilt. 
+
+Karten, welche nicht fix auf dem Spielfeld sind: 11 Karten mit Kurve, 11 Karten mit Durchgang und 12 Karten mit Verzweigung und Schatz.
+
+Zum Belegen des Spielplans werden diese Karten nun aneinander in einem Array/Vector gereiht, damit aus diesen zufällig eine Karte ausgesucht werden kann. So kommen zuerst alle Karten mit Kurve, dann alle Karten mit Durchgang und schlussendlich alle Karten mit Verzweigung.
+
+Nun soll mit der zur Verfügung gestellten Klasse "Random" und der Funktion "getRandomCard" eine Zahl von 1 bis zur Anzahl der noch nicht gelegten Karten auf dem Stapel gewählt werden. Dann wird die Karte, welche im Stapel an der zuvor bestimmten Zahl ist, genommen und auf die erste noch freie Stelle gelegt mit einer Orientierung welche ebenfalls durch die Random Klasse (Funktion: "getRandomOrientation") bestimmt wird. Hier ist die erste freie Stelle immer diejenige welche von oben links beginnend noch keine Karte auf dem Spielplan hat. "getRandomOrientation" gibt ein zufällige Zahl von der Menge {0, 1 , 2, 3} zurück, dabei steht diese Zahl für die Anzahl wie oft das jeweilige Feld um 90° nach links gedreht werden soll.
+Am Anfang wäre dies 1:2, dann 1:4, dann 1:6, dann 2:1 usw.
+
+Dies wird solange wiederholt, bis nur noch eine Karte übrig und das Spielfeld voll bedeckt ist. Die nicht gelegte Karte ist jene, welche als freie Karte zum Verschieben verwendet wird.
diff --git a/2021-oop1/ku/A2_Angabe_M1/description/Singleton.md b/2021-oop1/ku/A2_Angabe_M1/description/Singleton.md
new file mode 100644
index 0000000000000000000000000000000000000000..03f7fffa01057cdec3ab4932c1990f820f097281
--- /dev/null
+++ b/2021-oop1/ku/A2_Angabe_M1/description/Singleton.md
@@ -0,0 +1,48 @@
+# Singleton
+
+Ziel dieser Seite ist es, den Befriff Singleton für das Assignement so weit zu erklären, dass Singletons verstanden und für den gewünschten Zweck verwendet werden können. Genauere Infos über Singletons in C++, können selbständig in Büchern oder im Internet recherchiert werden.
+
+## Algemein
+
+Ein Singleton stellt sicher, dass es nur genau ein Objekt einer Klasse gibt. Wird eine Klasse also als Singleton implementiert, so kann es nicht mehr als eine Instanz der Klasse geben.
+
+## Beispiel ein Singleton Klasse
+
+```C++
+#ifndef TEST_SINGLETONCLASS_H
+#define TEST_SINGLETONCLASS_H
+
+class SingletonClass
+{
+  public:
+    static SingletonClass& instance()
+    {
+       static SingletonClass instance_;
+       return instance_;
+    }
+    ~ SingletonClass() {}
+    void function();
+  private:
+    SingletonClass() :variable(20) {}
+    SingletonClass( const SingletonClass& ); 
+    SingletonClass& operator = (const SingletonClass&); 
+
+    int variable;
+};
+#endif
+```
+
+Dadurch, dass Konstruktor, Copy-Konstruktor und Copy-Assignment-Operator`private` sind, kann eine Instanz von `SingletonClass` nur innerhalb dieser Klasse erstellt werden. Von außen kann ein `SingletonClass`-Objekt über die `static`-Methode `instance` angefordert werden. Auch bei wiederholten Aufrufen von `instance` wird immer die selbe Instanz zurückgegeben.
+
+## Verwendung der Klasse
+
+Um die Singleton Klasse zu verwenden kann entweder die Instanz als Referenz verwendet werdenoder direkt auf die Instanz verwendet werden.
+
+```C++
+SingletonClass &singleton = SingletonClass::instance();
+singleton.function();
+// oder dierekte Verwendung
+SingletonClass::instance().function();
+```
+
+Um die Singleton Klasse zu verwenden muss diese lediglich inkludiert werden. Sobald diese irgendwo inkludiert und verwendet wurde wird auch eine Instanz dafür angelegt.
diff --git a/2021-oop1/ku/assignments-fragenstunden/ku-vorstellungA1.pdf b/2021-oop1/ku/assignments-fragenstunden/ku-vorstellungA1.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..68caea3b5eb9d72524e72f7f10f09b918017f20a
Binary files /dev/null and b/2021-oop1/ku/assignments-fragenstunden/ku-vorstellungA1.pdf differ
diff --git a/2021-oop1/ku/stream-02/ku-stream-02-folien.pdf b/2021-oop1/ku/stream-02/ku-stream-02-folien.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..040a624a68e9cbbea0b5c008639e5f374c9f78d8
Binary files /dev/null and b/2021-oop1/ku/stream-02/ku-stream-02-folien.pdf differ
diff --git a/2021-oop1/ku/stream-03/ku-stream-03-folien.pdf b/2021-oop1/ku/stream-03/ku-stream-03-folien.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..a7de33c0ccb100bfc2b2c88d12c28f98eded8949
Binary files /dev/null and b/2021-oop1/ku/stream-03/ku-stream-03-folien.pdf differ
diff --git a/2021-oop1/ku/stream-04/ku-stream-04-folien.pdf b/2021-oop1/ku/stream-04/ku-stream-04-folien.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..cf6b427a362f4eb5fc4daa506a9e4307cc364b08
Binary files /dev/null and b/2021-oop1/ku/stream-04/ku-stream-04-folien.pdf differ
diff --git a/2021-oop1/vo/stream-04-vererbung/0_pets_wo_inheritance/main.cpp b/2021-oop1/vo/stream-04-vererbung/0_pets_wo_inheritance/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f1bb3898f044a574f189533bca90f8e902cb1732
--- /dev/null
+++ b/2021-oop1/vo/stream-04-vererbung/0_pets_wo_inheritance/main.cpp
@@ -0,0 +1,49 @@
+#include <cstdio>
+#include <cstring>
+
+// TODO: destructor (free memory allocated on the heap (for name_))
+// TODO: copy constructor (implement deep copy)
+
+class Pig {
+  char* name_; // longer names now supported (compared to `char name_[10];`)
+  unsigned age_;
+ 
+  public:
+    Pig(const char* name, unsigned age)
+      : name_{ new char[strlen(name) + 1] }, age_{age}
+    {
+      strcpy(name_, name);
+    }
+    void drink() { printf("%s drinks\n", name_); }
+    void bath() { printf("Bath! :D\n"); }
+    unsigned getAge() { return age_; }
+    void setAge(unsigned age) { age_ = age; }
+};
+
+class Cat { // not a pig
+  char* name_;
+  unsigned age_;
+
+  public:
+    Cat(const char* name, unsigned age)
+      : name_{ new char[strlen(name) + 1] }, age_{age}
+    {
+      strcpy(name_, name);
+    }
+    void drink() { printf("%s drinks\n", name_); }
+    void play() { printf("Play! :D\n"); } // cats play and don't take a bath
+    unsigned getAge() { return age_; }
+    void setAge(unsigned age) { age_ = age; }
+};
+
+int main()
+{
+  Pig pig{ "Babe", 0 };
+  pig.bath();
+  pig.drink();
+  Cat cat{ "Grumpy", 7 };
+  cat.play();
+  // cat.bath(); // <-- error: no member named 'bath' in 'Cat' (Cats don't enjoy taking a bath – only pigs do)
+  cat.drink();
+  return 0;
+}
diff --git a/2021-oop1/vo/stream-04-vererbung/1_pets_w_inheritance/cat.hpp b/2021-oop1/vo/stream-04-vererbung/1_pets_w_inheritance/cat.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..44f5d6b4ae335c08416dd285bb4cf1e6bcb8cd57
--- /dev/null
+++ b/2021-oop1/vo/stream-04-vererbung/1_pets_w_inheritance/cat.hpp
@@ -0,0 +1,12 @@
+# include "pet.hpp"
+
+// TODO: add include guards (see pet.hpp for an example)
+	
+class Cat : public Pet {
+  public:
+    Cat(const char* name, unsigned age)
+      : Pet{ name, age } {}
+    Cat(const Cat& other) = delete;
+    ~Cat() = default;
+    void play() { printf("%s plays!\n", name_); }
+};
\ No newline at end of file
diff --git a/2021-oop1/vo/stream-04-vererbung/1_pets_w_inheritance/main.cpp b/2021-oop1/vo/stream-04-vererbung/1_pets_w_inheritance/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d3d68014169018468861691b250d49d69fbf4957
--- /dev/null
+++ b/2021-oop1/vo/stream-04-vererbung/1_pets_w_inheritance/main.cpp
@@ -0,0 +1,15 @@
+#include <cstdio>
+
+#include "pig.hpp"
+#include "cat.hpp"
+
+int main()
+{
+  Pig pig{ "Babe", 0 };
+  pig.drink();
+  pig.bath();
+  Cat cat{ "Grumpy", 0 };
+  cat.drink();
+  cat.play();
+  return 0;
+}
\ No newline at end of file
diff --git a/2021-oop1/vo/stream-04-vererbung/1_pets_w_inheritance/pet.hpp b/2021-oop1/vo/stream-04-vererbung/1_pets_w_inheritance/pet.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..93a11912cff57073b382d8f4db9628050b636dd4
--- /dev/null
+++ b/2021-oop1/vo/stream-04-vererbung/1_pets_w_inheritance/pet.hpp
@@ -0,0 +1,24 @@
+#ifndef PET_H
+#define PET_H
+
+#include <cstring>
+#include <cstdio>
+
+class Pet {
+  unsigned age_;
+  protected:
+    char* name_;
+  public:
+    Pet(const char* name, unsigned age)
+      : age_{age}, name_{ new char[strlen(name) + 1] }
+    {
+      strcpy(name_, name);
+    }
+    Pet(const Pet& other) = delete;
+    ~Pet() { delete[] name_; }
+    unsigned getAge() { return age_; }
+    void setAge(unsigned age) { age_ = age; }
+    void drink() { printf("%s drinks\n", name_); }
+};
+
+#endif
\ No newline at end of file
diff --git a/2021-oop1/vo/stream-04-vererbung/1_pets_w_inheritance/pig.hpp b/2021-oop1/vo/stream-04-vererbung/1_pets_w_inheritance/pig.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..aca892f53914f31a40876d41142ce9f53e3bdedd
--- /dev/null
+++ b/2021-oop1/vo/stream-04-vererbung/1_pets_w_inheritance/pig.hpp
@@ -0,0 +1,13 @@
+# include "pet.hpp"
+
+// TODO: add include guards (see pet.hpp for an example)
+
+class Pig : public Pet {
+  public:
+    // using Pet::Pet; // possible instead of defining the constructor for Pig. Using this line, Pig inherits Pet's constructor.
+    Pig(const char* name, unsigned age)
+      : Pet{ name, age } {}
+    Pig(const Pig& other) = delete;
+    ~Pig() = default;
+    void bath() { printf("%s enjoys taking a bath!\n", name_); }
+};
\ No newline at end of file
diff --git a/2021-oop1/vo/stream-04-vererbung/2_pets_w_polymorphism/cat.hpp b/2021-oop1/vo/stream-04-vererbung/2_pets_w_polymorphism/cat.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..39036e26482ac2760843cb9ed0206eb8fdae4d69
--- /dev/null
+++ b/2021-oop1/vo/stream-04-vererbung/2_pets_w_polymorphism/cat.hpp
@@ -0,0 +1,12 @@
+# include "pet.hpp"
+
+// TODO: add include guards (see pet.hpp for an example)
+
+class Cat : public Pet {
+  public:
+    Cat(const char* name, unsigned age)
+      : Pet{ name, age } {}
+    Cat(const Cat& other) = delete;
+    ~Cat() = default;
+    void play() { printf("%s plays!\n", name_); }
+};
diff --git a/2021-oop1/vo/stream-04-vererbung/2_pets_w_polymorphism/main.cpp b/2021-oop1/vo/stream-04-vererbung/2_pets_w_polymorphism/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..096b0169f591d08557308388e6a5855df09bc5ea
--- /dev/null
+++ b/2021-oop1/vo/stream-04-vererbung/2_pets_w_polymorphism/main.cpp
@@ -0,0 +1,15 @@
+#include <cstdio>
+
+#include "pig.hpp"
+#include "cat.hpp"
+
+int main() {
+  Pet* pets[2]{
+    new Pig{ "Babe", 0 },
+    new Cat{ "Grumpy", 7}
+  };
+  for (auto pet : pets) {
+    pet->drink();
+  }
+  return 0;
+}
diff --git a/2021-oop1/vo/stream-04-vererbung/2_pets_w_polymorphism/pet.hpp b/2021-oop1/vo/stream-04-vererbung/2_pets_w_polymorphism/pet.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..f06cc054a9e1147c00d1306669c8873c7ddd118c
--- /dev/null
+++ b/2021-oop1/vo/stream-04-vererbung/2_pets_w_polymorphism/pet.hpp
@@ -0,0 +1,25 @@
+#ifndef PET_H
+#define PET_H
+
+#include <cstring>
+#include <cstdio>
+
+class Pet {
+  unsigned age_;
+  protected:
+    char* name_;
+  public:
+    Pet(const char* name, unsigned age)
+      : age_{age}, name_{ new char[strlen(name) + 1] }
+    {
+      strcpy(name_, name);
+    }
+    Pet(const Pet& other) = delete;
+    virtual ~Pet() { delete[] name_; }
+    unsigned getAge() { return age_; }
+    void setAge(unsigned age) { age_ = age; }
+    // virtual void drink() = 0; // if we use this line instead of the next, Pet becomes an abstract class.
+    virtual void drink() { printf("%s drinks.\n", name_); }
+};
+
+#endif
diff --git a/2021-oop1/vo/stream-04-vererbung/2_pets_w_polymorphism/pig.hpp b/2021-oop1/vo/stream-04-vererbung/2_pets_w_polymorphism/pig.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..fa67f7608dc5fd4b5a189ed3ab6b4926c8bd14ee
--- /dev/null
+++ b/2021-oop1/vo/stream-04-vererbung/2_pets_w_polymorphism/pig.hpp
@@ -0,0 +1,14 @@
+# include "pet.hpp"
+
+// TODO: add include guards (see pet.hpp for an example)
+
+class Pig : public Pet {
+  public:
+    // using Pet::Pet; // possible instead of defining the constructor for Pig. Using this line, Pig inherits Pet's constructor.
+    Pig(const char* name, unsigned age)
+      : Pet{ name, age } {}
+    Pig(const Pig& other) = delete;
+    ~Pig() = default;
+    void bath() { printf("%s enjoys taking a bath!\n", name_); }
+    void drink() override { printf("%s drinks water.\n", name_); }
+};