March 19, 2026

Wissenschaftliche Texte schreiben mit typst

 Anstatt hier die technische Bedienung des Textsatzsystems typst zu erläutern, welche gut dokumentiert ist und große Ähnlichkeit mit LaTeX aufweist will ich ein wenig auf die sozialen Aspekte eingehen, wie genau der Switch vom altgedienten Kohledampfer LaTeX auf das neuartige Dieselschiff typst funktioniert. 

Zuerst einmal sollte man sich die Mühe machen, LaTeX lebewohl zu sagen was in Linux mit dem Befehl "apt remove textlive-*" funktioniert. Dieser Befehl löscht LaTeX von der Festplatte inkl. der zahlreichen ungenutzten Fonts, der Sprachpakete und der obsoleten Zusatzpakete. Wenn alles reibungslos funktioniert ist es danach nicht länger möglich über die Kommandozeile LaTeX Dokumente ins PDF Format zu kompilieren. Dadurch entsteht ein Bedarf nach einer Lösung die besser ist als gar keine Lösung.

Wenn man dringend eine Abschlussarbeit schreiben muss, aber es keine Software dafür gibt, ist jede Software besser als keine. Dadurch blickt man über eventuelle Schwächen großzügig hinweg. Z.B. gibt es in Typst keinen Knuth plass algorithmus wie bei LaTeX ... machts nichts hauptsache es wird überhaupt ein PDF gerendert. Es ist nur sehr umständlich möglich eine Titelzeile zu erzeugen .. .ist nicht weiter schlimm, hauptsache ist dass irgendwo auf der Seite eine Überschrift auftaucht.

Es macht wenig Sinn typst direkt mit Latex zu vergleichen, weil die Software anders funktioniert. Man wird immer irgendwelche Feinheiten finden in den typst Schwächen hat und die bei LaTeX besser gelöst wurden, nur darum geht es nicht. Entscheidend ist dass man überhaupt Text plus grafiken in eine PDF Datei rendern kann und solange die Schrift nicht kleiner ist als 5 pt und die Bilder irgendwie angezeigt werden ist die Aufgabe erfüllt.

Anstatt auf die Details der Typst Software einzugehen macht es mehr Sinn sich mit den Schwächen des LaTeX Ökosystems zu beschäftigen. Der Sourcecode der TeX engine gilt als Spaghetti code. Er wurde in den 1970er geschrieben und verwendet Rekursion als standardprogrammiertechnik. Die meisten Pakete wie Lamport Tex und Bibtex wurden in den 1990er Jahren erstellt und seitdem nicht mehr verbessert. Es gab mal ein Projekt namens latex3, was aber nie realisiert wurde. Von außen Betrawchtet erinnert LaTeX an einen Commodore 64 im Jahr 1994, wo also eine treue Fangemeinde neue Spiele in Assembler programmierte aber nicht einsehen wollte, dass die Welt eine andere ist. Mitte der 1980er Jahre war der 8bit Heimcomputer von Commodore mal state of the Art technologie, aber Mitte der 1990er Jahre war die selbe Technologie veraltet. Und genau das ist die Ist situation mit LaTeX. Die kompletten 8 GB welche eine texlive installation auf der Festplatte in Beschlag nimmt bestehen aus obsoleten Packages, ungewartetem Code, endlosen Makros und immer weiteren Softwareschichten die keinen Sinn machen.

Um eine wissenschaftliche Arbeit zu erstellen braucht es folgende Features: zweispaltensatz, Tabellen, Einbindung von Bildern, Fließtext, Fußnoten und ein Inhaltsverzeichnis. All das stellt typst bereit. Es gibt sogar noch weitere Extras wie Gleitumgebungen, Silbentrennung und dreispaltensatz. Man kann also sagen, dass typst die Anforderungen übererfüllt. Damit ist es gut geiegnet um damit Texte zu erstellen.

Die software ist schön klein, arbeitet sehr schnell, ist umfassend dokumentiert und es gibt online foren für weitere informationen. Also alles verfügbar was man so braucht. Die geringe Anzahl von Nutzer die typst derzeit nutzen ist kein Nachteil sondern ein Vorteil, damit ist sichergestellt dass jeder neue Nutzer der eine Anfängerfrage stellt begeistert empfangen wird und sofort Hilfestellung erhält.


March 18, 2026

Nähere Bekanntschaft mit dem Typst Textsatzsystem

Die Typst software könnte man als Latex clone bezeichnen. Es ist das wohl ambitionierste Projekt mit dieser Zielstellung. Es ist deutlich mächtiger als z.B. lout oder Sile welche ebenfalls angetreten sind um Latex Konkurrenz zu machen.

Selbstverständlich ist dort alles anders und deutlich moderner. Der größte Vorteil von typst ist, dass man nicht 7 GB für die texlive installation benötigt sondern es reichen 50 MB auf der Festplatte aus. Zusätzliche fonts oder packages sind unnötig, weil typst die Linux eigenen Schriften verwendet und mit den default parametern für alle wichtige Aufgaben gerüstet ist.

Im screenshot ist ein Beispieldokument zu sehen inkl. zweispaltensatz, Inhaltsverzeichnis, einer Überschrift die über die ganze Seite geht, eingebundenen Bildern und Blocksatz. Man kann also vereinfacht sagen, dass typst als Ersatz für latex gedacht ist. Im besten fall erfüllt es genau dieselbe Aufgabe.

Die Stärken werden vor allem beim Erstellen von wissenschaftlichen Arbeiten sichtbar die im Normalfall sehr umfangreich sind und viele Gleitabbildungen enthalten. Ferner ist das Prinzip eines Textsatzsystem nützlich bei der Datenbank-Ausgabe, wenn man also CSV Daten als PDF rendern möchte.

In der Summe ist typst das bessere Latex, wenn auch mit einer großen Einschränkung. Der verwendete linebreaking algorithmus ist nicht etwa die Knuth-plass globaloptimierung sondern es ist ein simpler greedy algorithmus der auch in Libreoffice oder in lout verwendet wird. Als Folge entstehen gerade beim Spaltensatz unschöne leerräume zwischen den Wörtern. Hier ist LaTeX deutlich fortschrittlicher auch wenn es Ende der 1970er Jahren entwickelt wurde.

Man wird bei genauer Betrachtung noch weitere Nachteile von typst entdecken. Das Hauptproblem dürfte sein dass es kein LaTeX ist und damit inkompatibel zum bewährten Ökosystem. Nur, das ist weniger eine technische Einschränkung als vielmehr eine soziale. Das also die typst community anders funktioniert und andere Ziele verfolgt als die Latex community.

Um typst würdigen zu können muss man zunächst einmal die Schwächen von TeX kennen. TeX war mal bis ca. Ende der 1990er Jahre das führende Textverarbeitungssystem in der Informatik. Es war schnell, überzeugte durch eine hohe Ausgabequalität, war gut dokumentiert und war offen für neue User. Das ist heute im Jahr 2026 leider nicht mehr so. LaTeX hat heute ähnlichkeit mit einem verrosteten Tanker der groß und schwerfällig an die Vergangenheit denkt und mit geänderten Anforderungen nicht mehr schritt hält. Die vielzahl an LateX implementierungen wie pdflatex, xelatex, Lualatex, context, plaintex, Lyx usw. zeugen davon dass die Community sich aufgespalten hat. Es gab innerhalb des TeX universums durchaus Versuche sich zu erneuern wie z.B. durch das Overleaf projekt, was eine webbasiertes Frontend ist oder durch die Luatex engine, welche das Erstellen von SCripten vereinfacht. Doch wegen der erforderlichen Rückwärtskompatiblität wirken diese Projekte eher wie zusätliche Layer in einem chaotischen Ökosystem was ähnlich wie initd in Linux als obsolet gilt.

Anstatt innerhalb des Latex Ökosystems nach Veränderung zu rufen ist es wohl besser sich auf eine neue technische Basis zu fokussieren wie z.B. das typst Projekt. Diese Software ist effizienter, kann alle wichtige Formatierungsaufgaben erfüllen, benötigt weniger Speicherplatz und ist gut dokumentiert, das einzige was fehlt sind noch die Nutzer.


Typst ausprobiert

 Das Textsatzsystem LaTeX ist in der wissenschaftlichen Community zum Quasi Standard aufgestiegen. 98% aller Dokumente in der Informatik, Mathematik und Physik werden mit diesem Tool formatiert. Durch GUI Frontends wie Overleaf und Lyx findet LaTeX zunehmend auch in den Geisteswissenschaften Anklang. Leider hat LaTeX mehrere Nachteile, wie dass die Installation mehrere Gigabyte an Speicher benötigt, dass es historisch gesehen sehr viele Packages gibt und das die Kernsoftware, die TeX Engine, in einer heute unüblichen Programmiersprache erstellt wurde.

Eine mögliche Alternative ist Typst, welche in 2023 erstmals vorgestellt wurde. Die aktuelle Version ist noch etwas unausgereift, man kann damit aber bereits PDF Dokumente erzeugen. Nach dem Download der nur 16 Megabyte großen ausführbaren Datei von der Website des Projekts ist das erste was auffällt die hohe Geschwindigkeit. Anders als bei pdflatex und speziell bei lualatex wird nicht jede Seite des Dokuments einzeln formatiert, sondern das fertige PDF file steht quasi sofort bereit wenn man typst auf die Input Datei anwendet. Die Syntax ist ähnlich wie bei LaTex, es gibt also eine Trennung zwischen Inhalt und Layout. Defaultmäßig werden neue Dokumente im "Libertinus Serif" Font gesetzt, was man aber ändern kann auf „Nimbus Roman“ oder "New Computer Modern". Hier ist ein Beispieldokument für ein 2 spaltiges Dokument inkl. Float-Abbildung. Es wird in das PDF Format übersetzt mit ./typst compile hello.typ.

Ach ja, es gibt mehrere kleinere bugs in typst. zum einen ist die Überschrift nicht mittig und zweitens ist der optische Randausgleich im zweispalten Layout im unteren Bereich nicht verfügbar. Ob man diese Probleme durch andere Parameter lösen kann ist unklar. Im Zweifel muss man damit leben. Das heißt anders als LaTeX wurde typst eben nicht über Jahre hinweg verbessert sondern das Projekt befindet sich noch in einem frühen Stadium. Was aber zumindest funktioniert sind die Basics des Textsatzes wie Tabellen, Seitennummerierung, Blocksatz und Silbentrennung.

Vielleicht noch ein kleiner Hinweis wie der Umstieg von LaTeX auf Typst etwas gefälliger verläuft. Am besten beginnt man die Reise damit, dass man "apt remove texlive-*" eingibt, also das bisherige Textsatzsystem auf der Festplatte löscht. Dadurch gewinnt man Speicherplatz um etwas neues zu verwenden. 

#set page(
  paper: "a4",
  margin: (x: 2cm, y: 2cm,bottom: 3cm,),
  numbering: "1",
  columns: 2,
)

#set par(
  justify: true,
  spacing: 0.65em,
  first-line-indent: 1em,
)
#set text(
  // font: "New Computer Modern",
  font: "Nimbus Roman",
  size: 11pt
)
#title[
  Example typst document
]

= chapter1

This is a text.

- item
- item
- item

This is a longer text. This is a longer text. This is a longer text. This is a longer text. This is a longer text. This is a longer text. This is a longer text. This is a longer text. This is a longer text. This is a longer text. This is a longer text. This is a longer text. 

This is a longer text. This is a longer text. This is a longer text. This is a longer text. This is a longer text. This is a longer text. This is a longer text. This is a longer text. This is a longer text. This is a longer text. This is a longer text. This is a longer text. 

The equation $Q = rho A v + C$ defines the glacial flow rate.

$ v := vec(x_1, x_2, x_3) $

#figure(
  image("zk.webp", width: 80%),
  caption: [a picture with a Zettelkasten],
  placement: auto,
) <zk>

March 17, 2026

Automatic coding with Google Gemini

 

Since the advent of GPT-3 in 2020 lots of improvement are visible, especially the ability of large language models to code software programs is impressive. To check out the current capabilities a demanding example should be presented. Its a Tetris game written python with a built in feature vector. The feature vector is useful for creating an AI for Tetris.

The prompt consists of a multi-step pipeline. At first, the LLM was asked to create an elaborated prompt which gets executed in the second step.

Create a "Prompt Engineering" cheat sheet designed specifically for architecting software without writing manual code. Domain is: Tetris game including semantic annotation. The annotation is based on a numerical feature vector which determines important properties of the game so that an AI player can use the feature vector to automatically playing the game. The AI doesn't need to be implemented, its enough if the feature vector is shown on the screen and commented in the code.
Execute the Tetris prompt, so that the game is shown as python code.


The resulting game works fine. It can be executed without an error. There are falling tetris pieces which can be moved with cursor keys and there is also a feature vector visible on the screen at top right. The sourcecode for the entire app is 170 lines of code and is using numpy, pygame and random as libraries.

The most complex element of the software is "the get_feature_vector(self)" routine. Most Tetris implementation found at github have no such a routine because its not needed for a human player. But the feature vector is highly important for automating the game so that the computer decides at which position each pieces should be location. It seems, that current generation of LLMs are understanding what the purpose is and how to implement it in software.

It should be mentioned that some smaller bugs are available. For example the feature "height" is working wrong. Of course, the LLM can fix the issue but this would require a rewrite of the software. Another problem is, that the layout of the screen looks a bit messy. So the game needs to be interpreted as a prototype but not as a final version.

import pygame
import random
import numpy as np

# --- Konfiguration ---
SCREEN_WIDTH = 500
SCREEN_HEIGHT = 600
BLOCK_SIZE = 30
GRID_WIDTH = 10
GRID_HEIGHT = 20
SIDEBAR_X = 320

COLORS = [
    (0, 0, 0), (255, 0, 0), (0, 255, 0), (0, 0, 255), 
    (255, 255, 0), (255, 165, 0), (0, 255, 255), (128, 0, 128)
]

SHAPES = [
    [[1, 1, 1, 1]],
    [[0, 2, 2], [2, 2, 0]],
    [[3, 3, 0], [0, 3, 3]],
    [[4, 4], [4, 4]],
    [[5, 5, 5], [5, 0, 0]],
    [[6, 6, 6], [0, 0, 6]],
    [[7, 7, 7], [0, 7, 0]]
]

class TetrisEngine:
    def __init__(self):
        self.grid = np.zeros((GRID_HEIGHT, GRID_WIDTH), dtype=int)
        self.lines_cleared_total = 0
        self.game_over = False
        self.new_piece()

    def new_piece(self):
        self.current_shape = random.choice(SHAPES)
        self.piece_color = SHAPES.index(self.current_shape) + 1
        self.piece_x = GRID_WIDTH // 2 - len(self.current_shape[0]) // 2
        self.piece_y = 0
        if self.check_collision(self.piece_x, self.piece_y):
            self.game_over = True

    def rotate_shape(self):
        """
        Matrix-Rotation: Transponieren + Zeilen umkehren.
        Semantischer Hinweis: Ändert die Form-Struktur für den Feature-Vektor.
        """
        # List comprehension für 90-Grad Rotation
        new_shape = [list(row) for row in zip(*self.current_shape[::-1])]
        
        # Kollisionsprüfung: Nur rotieren, wenn Platz da ist
        if not self.check_collision(self.piece_x, self.piece_y, new_shape):
            self.current_shape = new_shape

    def check_collision(self, x, y, shape=None):
        if shape is None: shape = self.current_shape
        for r, row in enumerate(shape):
            for c, val in enumerate(row):
                if val:
                    if (x + c < 0 or x + c >= GRID_WIDTH or 
                        y + r >= GRID_HEIGHT or 
                        (y + r >= 0 and self.grid[y + r][x + c])):
                        return True
        return False

    def freeze_piece(self):
        for r, row in enumerate(self.current_shape):
            for c, val in enumerate(row):
                if val:
                    self.grid[self.piece_y + r][self.piece_x + c] = self.piece_color
        self.clear_lines()
        self.new_piece()

    def clear_lines(self):
        full_rows = [i for i, row in enumerate(self.grid) if all(row)]
        for i in full_rows:
            self.grid = np.delete(self.grid, i, axis=0)
            self.grid = np.insert(self.grid, 0, np.zeros(GRID_WIDTH), axis=0)
        self.lines_cleared_total += len(full_rows)

    def get_feature_vector(self):
        col_heights = []
        for c in range(GRID_WIDTH):
            h = 0
            for r in range(GRID_HEIGHT):
                if self.grid[r][c] != 0:
                    h = GRID_HEIGHT - r
                    break
            col_heights.append(h)
        
        agg_height = sum(col_heights)
        holes = 0
        for c in range(GRID_WIDTH):
            found_block = False
            for r in range(GRID_HEIGHT):
                if self.grid[r][c] != 0:
                    found_block = True
                elif found_block and self.grid[r][c] == 0:
                    holes += 1
        
        bumpiness = 0
        for i in range(GRID_WIDTH - 1):
            bumpiness += abs(col_heights[i] - col_heights[i+1])
            
        return [agg_height, holes, bumpiness, self.lines_cleared_total]

def main():
    pygame.init()
    screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
    clock = pygame.time.Clock()
    font = pygame.font.SysFont("monospace", 16)
    engine = TetrisEngine()

    drop_time = 0
    while not engine.game_over:
        screen.fill((240, 240, 240))
        dt = clock.get_rawtime()
        drop_time += dt
        clock.tick()

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT and not engine.check_collision(engine.piece_x - 1, engine.piece_y):
                    engine.piece_x -= 1
                if event.key == pygame.K_RIGHT and not engine.check_collision(engine.piece_x + 1, engine.piece_y):
                    engine.piece_x += 1
                if event.key == pygame.K_DOWN and not engine.check_collision(engine.piece_x, engine.piece_y + 1):
                    engine.piece_y += 1
                if event.key == pygame.K_UP:
                    engine.rotate_shape() # ROTATION TRIGGER

        if drop_time > 400:
            if not engine.check_collision(engine.piece_x, engine.piece_y + 1):
                engine.piece_y += 1
            else:
                engine.freeze_piece()
            drop_time = 0

        # Draw Grid & Piece
        for r in range(GRID_HEIGHT):
            for c in range(GRID_WIDTH):
                if engine.grid[r][c]:
                    pygame.draw.rect(screen, COLORS[engine.grid[r][c]], (c*BLOCK_SIZE, r*BLOCK_SIZE, BLOCK_SIZE-1, BLOCK_SIZE-1))
        
        for r, row in enumerate(engine.current_shape):
            for c, val in enumerate(row):
                if val:
                    pygame.draw.rect(screen, COLORS[engine.piece_color], 
                                     ((engine.piece_x + c)*BLOCK_SIZE, (engine.piece_y + r)*BLOCK_SIZE, BLOCK_SIZE-1, BLOCK_SIZE-1))

        # AI Interface Update
        features = engine.get_feature_vector()
        labels = ["Height", "Holes", "Bumpy", "Lines"]
        title = font.render("AI INPUT VECTOR:", True, (0, 0, 0))
        screen.blit(title, (SIDEBAR_X, 20))
        for i, val in enumerate(features):
            txt = font.render(f"{labels[i]}: {val}", True, (0, 0, 0))
            screen.blit(txt, (SIDEBAR_X, 50 + i*30))

        pygame.display.flip()
    pygame.quit()

if __name__ == "__main__":
    main()
 

How to scale up artificial intelligence

 In the past it was mostly unknown how to create Artificial intelligence, even restricted problems like the game of chess or robot control in a warehouse were recognized as hard to realize in software. The cause was a missing understanding of the domain and missing tools to implement AI domains on a computer.

What is available today is a pathway how to realize Artificial intelligence in a step by step fashion. It has to do with splitting the task between human and computer. In case of computer chess the situation can be described. Automating the entire process of playing the game is difficult, but the computer can be used to only count the pieces on the board and print out the number to the screen. This information helps the human player to decide what for the best move. So the human sees the chessboard itself and a dashboard with important information generated by a computer.

The next task is to improve the dashboard, in a sense that more information are recognized by the computer software like the value for each piece, similar board situation found in the database, and the allowed possible moves. All the information are shown on the same dashboard and reduce the workload for the human operator. The resulting AI system can't be called a true AI but its only a semi-autonomous system.

Instead of answering the question how to play chess with a computer the modified task is to communicate between a human and a computer program about the domain of chess. This communication is realized with an algorithm. The human enters high level actions like "move pawn forward" or "protect queen" and the AI software is in charge to realize this command on the board.

March 16, 2026

Die Erfindung der Teleoperation / Fernsteuerung

Ferngesteuerte Roboter und technische Anlagen sind ein sehr altes Prinzip. Das Telekino war ein ferngesteuertes Boot welche um 1905 von Leonardo Torres Quevedo vorgestellt wurde, seit den 1950er gibt es ferngesteuerte Spielzeugautos die meist über Kabel funktionierten. Und seit den 1980er sind funkferngesteuerte Spielzeugautos im Mainstream bekannt.

Allerdings wurde das Konzept von der Informatik und speziell der Robotikforschung ignoriert. Stattdessen fokussierte man sich über jahrzehnte auf autonome algorithmen gesteuerte Roboter, was man als Dogma bezeichnen könnte.

Es gab in der Geschichte der Robotik zumindest früher keinen Grund "remote control" näher zu untersuchen, zumal technisch gesehen das Problem gelöst ist also dort nichts neues mehr entwickelt werden kann. Um die Vorteile von fenrgesteuerten Robotern in Bezug zur künstlichen Intelligenz näher zu untersuchen muss man die Transformaion von einem geschlossenen in ein offenes System beschreiben. Klassicherweise wurden Roboter als geschlossene Systeme betrachtet. Die Frage war immer wie sieht die Maschinen innen aus, also welche Hardware, welche Programmiersprache und welcher Algorithmus steuert den Roboter. Sobald der Roboter jedoch von einem operator ferngesteuert wird, wird ein wichtiges Modul ausgelagert und zwar das Modul der Entscheidungsfindung.

Laut Definition gibt bei einem ferngesteuerten Roboter der Bediener am Joystick vor, was der Roboter als nächtes tut. Der Bediener ist nicht länger Teil des Roboters sondern befindet sich außerhalb. Dadurch steigt die Komplexität massiv an, und es bedarf eines Kommunikationsprotokoll. Also einer Sprache die definiert wie Signale vom joystick zum Roboter gelangen. Dieses Kommunikationsprotokoll ist der Schlüssel zum Verständnis von künstlicher Intelligenz als signalverarbeitende Zwischenschicht.

Ein offenes System wie es mittels Fernsteuerung erzielt wird, folgt nicht länger den bekannten Gesetzen einer Turing Maschine. Der Roboter wird also nicht per algorithmus gesteuert sondern über Input außerhalb des Roboters. Man kann den Roboter länger programmieren sondern man kann lediglich einen Parser programmieren der die äußeren Kommandos in Aktionen übersetzt.

Ferngesteuerte Roboter sind automatisch offene Systeme während algorithmengesteurte Roboter geschlossene Systeme sind. Ein Algorithmus benötigt keine Kommunikation mit der außenwelt weil die Entscheidungen intern getroffen werden.



March 15, 2026

Line following roboter

 

Üblicherweise ist die Programmierung eines Line following roboters auf den Sourcecode fokussiert der in Java, Python oder C++ erstellt wird. Im folgende wird der Fokus auf die Mensch Maschine Kommunikation gelegt. Es wird ein semantischer Tagging space verwendet um die Linie auf dem Boden zu klassifizieren. Der Software für diesen Liniengenerator findet sich weiter unten und wurde in der Sprache python erstellt.

Die Hauptaufgabe der Software besteht darin, die dargestellte visuelle Szene innerhalb der 200x200 Pixel Karte in eine semantische Tagging beschreibung zu überführen. Diese Tagging beschreibung dient der Mensch Maschine interaktion. Der Roboter meldet die Tags zurück an den Menschen und dieser entscheidet was in der jeweiligen Situation zu tun ist. 

import pygame
import random

# --- Konfiguration ---
WIDTH, HEIGHT = 800, 600
BOX_SIZE = 200
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (200, 0, 0)  # Hindernis
GRAY = (200, 200, 200) # Box-Rahmen

# --- Moegliche Parameter ---
paths = ["vorwärts", "links", "rechts", "sackgasse", "Kreuzung"]
thicknesses = {"normal": 10, "dick": 20}
breaks = [False, True]
obstacles = [False, True]

# --- Pygame Setup ---
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Roboter Linien-Generator (Space für neue Karte)")
font_small = pygame.font.Font(None, 24)
font_large = pygame.font.Font(None, 36)

def generate_random_config():
    return {
        "path": random.choice(paths),
        "thickness_name": random.choice(list(thicknesses.keys())),
        "break": random.choice(breaks),
        "obstacle": random.choice(obstacles)
    }

def draw_text(screen, text, font, color, x, y, align_center=False):
    text_obj = font.render(text, True, color)
    text_rect = text_obj.get_rect()
    if align_center:
        text_rect.center = (x, y)
    else:
        text_rect.topleft = (x, y)
    screen.blit(text_obj, text_rect)

def draw_card(config):
    screen.fill(WHITE)
    
    # 1. Box berechnen (Zentrum des Bildschirms)
    box_rect = pygame.Rect((WIDTH//2 - BOX_SIZE//2, HEIGHT//2 - BOX_SIZE//2), (BOX_SIZE, BOX_SIZE))
    pygame.draw.rect(screen, GRAY, box_rect, 1) # Rahmen der Box
    
    center_x, center_y = box_rect.center
    half = BOX_SIZE // 2
    
    # Parameter
    path = config["path"]
    thickness_val = thicknesses[config["thickness_name"]]
    has_break = config["break"]
    has_obstacle = config["obstacle"]

    # 2. Pfade definieren (Relativ zur Box)
    # Startpunkt ist immer unten in der Mitte der Box
    start_p = (center_x, center_y + half)
    mid_p = (center_x, center_y)
    
    lines = [] # Liste von (Start, Ende) Paaren
    
    if path == "vorwärts":
        lines.append((start_p, (center_x, center_y - half)))
    elif path == "links":
        lines.append((start_p, mid_p))
        lines.append((mid_p, (center_x - half, center_y)))
    elif path == "rechts":
        lines.append((start_p, mid_p))
        lines.append((mid_p, (center_x + half, center_y)))
    elif path == "sackgasse":
        lines.append((start_p, (center_x, center_y + 10))) # Kurzes Stück
    elif path == "Kreuzung":
        lines.append((start_p, (center_x, center_y - half)))
        lines.append(((center_x - half, center_y), (center_x + half, center_y)))

    # 3. Zeichnen mit optionaler Unterbrechung
    for s, e in lines:
        if has_break:
            # Zeichne nur das erste und letzte Drittel der Teil-Linie
            m1 = (s[0] + (e[0]-s[0])//3, s[1] + (e[1]-s[1])//3)
            m2 = (s[0] + 2*(e[0]-s[0])//3, s[1] + 2*(e[1]-s[1])//3)
            pygame.draw.line(screen, BLACK, s, m1, thickness_val)
            pygame.draw.line(screen, BLACK, m2, e, thickness_val)
        else:
            pygame.draw.line(screen, BLACK, s, e, thickness_val)

    # 4. Hindernis (Falls ja, immer am Mittelpunkt der Box)
    if has_obstacle:
        pygame.draw.rect(screen, RED, (center_x - 15, center_y - 15, 30, 30))

    # 5. Semantische Beschreibung
    desc_str = f"Linienweg: {path} | Liniendicke: {config['thickness_name']}"
    extra_str = f"Unterbrechung: {'ja' if has_break else 'nein'} | Hindernis: {'ja' if has_obstacle else 'nein'}"
    
    draw_text(screen, desc_str, font_small, BLACK, WIDTH//2, HEIGHT//2 + half + 40, True)
    draw_text(screen, extra_str, font_small, BLACK, WIDTH//2, HEIGHT//2 + half + 65, True)
    draw_text(screen, "Drücke LEERTASTE für neue Karte", font_large, BLACK, WIDTH//2, 50, True)

# --- Hauptschleife ---
current_config = generate_random_config()
draw_card(current_config)

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE:
                current_config = generate_random_config()
                draw_card(current_config)

    pygame.display.flip()

pygame.quit()
 

March 14, 2026

Line following robot with grounded language

 

Mögliche Worte sind nach Kategorien sortiert. Darüber erfolgt die Kommunikation zwischen Mensch und Maschine. Die Software hat lediglich die Aufgabe die Kommunikation sicherzustellen:

- navigation (folgen, suchen, andocken, ignorieren, u_turn)
- line (junction, curve, end)
- attribute_speed (slow, fast)
- attribute_color (black, white)
- attribute_thick (thin, thick)
- feedback (lost_line, multiple_paths, pathblocked)