% karol-doc.tex — Handbuch zum Paket karol
\documentclass[11pt]{article}
\usepackage[margin=2.4cm]{geometry}
\usepackage{fontspec}
\usepackage[provide=*, ngerman]{babel}
\usepackage{robotkarol}
\usepackage{parskip}
\usepackage{listings}
\usepackage{xcolor}
\usepackage{array}
\usepackage{hyperref}
\hypersetup{colorlinks, linkcolor=blue!50!black, urlcolor=blue!50!black}

\lstdefinestyle{tex}{
	language=[LaTeX]TeX, basicstyle=\ttfamily\small,
	keywordstyle=\color{blue!60!black}, commentstyle=\color{gray},
	columns=fullflexible, keepspaces=true, moretexcs={
		karolzeile,karolpaar,karolgitter,karollegende,karolsetup,
		karolzustandslegende,karolzustandslegendenitem,karollegendentrenner,
		karol,ziegel,marke,quader,wand,bbefehl,bwiederholemal,
		bwiederholesolange,bwiederholeimmer,bwenndann,bwenndannsonst,
		bluecke,bbedingung,bkommentar,baufruf,banweisung,bhauptprogramm,
		ibefehl,iaufruf,ianweisung,ikommentar,ihauptprogramm,
		iwiederholemal,iwiederholesolange,iwiederholeimmer,iwenndann,
		isonst,ibedingung,iluecke,bist,bnichtist,iist,inichtist,
		karolfigur,karolonline,karolweltaus,karoljsonlesen,karoljsontitel,
		karoljsonbeschreibung,karoljsonaufgabentitel,karoljsonanzahl,
		karoljsonzielart,karolquelltext,karolquelltextdatei,
		karoljsonschreiben}}
\lstset{style=tex}
\newcommand*{\pkg}[1]{\textsf{#1}}
\newcommand*{\key}[1]{\texttt{#1}}

\title{Das Paket \pkg{robotkarol}\\[2pt]
	\large Robot-Karol-Welten und Blockprogramme für Unterrichtsmaterial}
\author{Anselm Wagner\thanks{\texttt{anselm.wagner@posteo.de}}}
\date{31. Oktober 2026 \quad Version 4.0}

% Beispielaufgabe für den Abschnitt über JSON -- Inhalt, wie Karol Online
% ihn herunterlädt (Format v1), eingerückt wie die Dateien, die
% \karoljsonschreiben erzeugt.
\begin{filecontents*}[overwrite]{robotkarol-doc-treppen.json}
{
  "version": "v1",
  "title": "Treppen",
  "description": "Zwei Aufträge rund um Treppen.",
  "tasks": [
    {
      "title": "Baue eine Treppe aus drei Stufen.",
      "start": {
        "dimX": 5,
        "dimY": 3,
        "height": 6,
        "karol": {
          "x": 0,
          "y": 1,
          "dir": "east"
        },
        "bricks": {
          "offsetX": -1,
          "offsetY": -1,
          "dimX": 0,
          "dimY": 0,
          "data": [

          ]
        },
        "marks": {
          "dimX": 1,
          "dimY": 1,
          "offsetX": 4,
          "offsetY": 1,
          "data": [
            [
              true
            ]
          ]
        },
        "blocks": {
          "dimX": 1,
          "dimY": 1,
          "offsetX": 2,
          "offsetY": 0,
          "data": [
            [
              true
            ]
          ]
        }
      },
      "target": {
        "dimX": 5,
        "dimY": 3,
        "height": 6,
        "karol": {
          "x": 0,
          "y": 1,
          "dir": "east"
        },
        "bricks": {
          "dimX": 3,
          "dimY": 1,
          "offsetX": 1,
          "offsetY": 1,
          "data": [
            [
              1,
              2,
              3
            ]
          ]
        },
        "marks": {
          "dimX": 1,
          "dimY": 1,
          "offsetX": 4,
          "offsetY": 1,
          "data": [
            [
              true
            ]
          ]
        },
        "blocks": {
          "dimX": 1,
          "dimY": 1,
          "offsetX": 2,
          "offsetY": 0,
          "data": [
            [
              true
            ]
          ]
        }
      }
    },
    {
      "title": "Probiere aus, wie Karol über Stufen läuft.",
      "start": {
        "dimX": 5,
        "dimY": 2,
        "height": 6,
        "karol": {
          "x": 0,
          "y": 0,
          "dir": "east"
        },
        "bricks": {
          "dimX": 3,
          "dimY": 1,
          "offsetX": 1,
          "offsetY": 0,
          "data": [
            [
              1,
              2,
              1
            ]
          ]
        },
        "marks": {
          "offsetX": -1,
          "offsetY": -1,
          "dimX": 0,
          "dimY": 0,
          "data": [

          ]
        },
        "blocks": {
          "offsetX": -1,
          "offsetY": -1,
          "dimX": 0,
          "dimY": 0,
          "data": [

          ]
        }
      },
      "target": {
        "dimX": 5,
        "dimY": 2,
        "height": 6,
        "karol": {
          "x": 0,
          "y": 0,
          "dir": "east"
        },
        "bricks": {
          "dimX": 3,
          "dimY": 1,
          "offsetX": 1,
          "offsetY": 0,
          "data": [
            [
              1,
              2,
              1
            ]
          ]
        },
        "marks": {
          "offsetX": -1,
          "offsetY": -1,
          "dimX": 0,
          "dimY": 0,
          "data": [

          ]
        },
        "blocks": {
          "offsetX": -1,
          "offsetY": -1,
          "dimX": 0,
          "dimY": 0,
          "data": [

          ]
        }
      }
    }
  ],
  "lng": "de",
  "questScript": ""
}
\end{filecontents*}

\IfFileExists{hologo.sty}{\usepackage{hologo}}{\newcommand{\hologo}[1]{#1}}

\begin{document}
\maketitle

\begin{abstract}\noindent
Das Paket \pkg{robotkarol} zeichnet Welten und Blockprogramme im Stil von
\emph{Robot Karol Online} (\url{https://karol.arrrg.de/}) für
Arbeitsblätter, Präsentationen und Prüfungen. Welten können als
3D-Schrägbild oder als 2D-Draufsicht ausgegeben werden; Farben und
Formen sind der Weboberfläche nachempfunden. Einzelne Blöcke lassen
sich als Inline-Blöcke in den Fließtext setzen, Aufgaben der
Online-Umgebung mit \verb|\karolonline| verlinken. Aufgaben aus Robot
Karol Online lassen sich als JSON-Datei einlesen und Welten dorthin
exportieren. Ein Druckmodus stellt
alle Ansichten auf tonersparende Graustufen um. Das Paket benötigt
\hologo{LuaLaTeX}\footnote{Genauer: eine Engine mit
	\texttt{\textbackslash directlua}; getestet mit LuaLaTeX.}
und expl3. \emph{English:} draws worlds and Blockly-style block
programs of the German teaching environment Robot Karol for worksheets;
3D oblique or 2D top view; single blocks can be set inline in running
text, aligned to the surrounding baseline; tasks are imported from and
exported to Robot Karol Online's JSON format; a toner-saving greyscale
print mode; requires LuaLaTeX.
\end{abstract}

\tableofcontents

\section{Schnellstart}

\begin{lstlisting}
\usepackage{robotkarol}   % Kompilierung mit LuaLaTeX
\end{lstlisting}

\begin{minipage}[c]{0.52\textwidth}
\begin{lstlisting}
\begin{karolwelt}[breite=5, laenge=3]
  \karol[x=1, y=2, richtung=osten]
  \ziegel[x=2, y=2, bisx=4]
  \marke[x=5, y=2]
\end{karolwelt}
\end{lstlisting}
\end{minipage}\hfill
\begin{minipage}[c]{0.44\textwidth}
\begin{karolwelt}[breite=5, laenge=3, skalierung=0.85]
	\karol[x=1, y=2, richtung=osten]
	\ziegel[x=2, y=2, bisx=4]
	\marke[x=5, y=2]
\end{karolwelt}
\end{minipage}

\medskip\noindent
Eine in Robot Karol Online gebaute Aufgabe (\emph{Aufgabe freigeben}
$\rightarrow$ \emph{Als JSON herunterladen}) kann direkt in \LaTeX{}
gesetzt werden -- hier der erste Auftrag der Datei, Start und Ziel in einem Bild:

\begin{minipage}[c]{0.52\textwidth}
\begin{lstlisting}
\karoljsonlesen[name=treppen]{treppen.json}
\karolweltaus[aufgabe=1]{treppen}
\end{lstlisting}
\end{minipage}\hfill
\begin{minipage}[c]{0.44\textwidth}
\karoljsonlesen[name=treppen]{robotkarol-doc-treppen.json}%
\karolweltaus[aufgabe=1, skalierung=0.85]{treppen}
\end{minipage}

\medskip\noindent
Umgekehrt wird jede Welt mit dem Schlüssel \key{export=blatt/1},
\key{export=blatt/2}, \dots{} zu einem Auftrag der Sammlung
\texttt{blatt}, und
\begin{lstlisting}
\karoljsonschreiben{blatt}{blatt.json}
\end{lstlisting}
schreibt sie am Dokumentende als JSON-Datei, die Karol Online auf der
Startseite mit \emph{Aufgabe aus Datei laden} öffnet. Für die vollstänidge Beschreibung
siehe Abschnitt~\ref{sec:json}.

\section{Die Umgebung \texttt{karolwelt}}

\begin{lstlisting}
\begin{karolwelt}[<Schlüssel>]
  <Objekte>
\end{karolwelt}
\end{lstlisting}

\subsection{Koordinatensystem}

Die Koordinaten folgen Robot Karol Online: \key{x} zählt die
\emph{Spalten} von links (1 bis \key{breite}), \key{y} die
\emph{Zeilen von hinten} (1 bis \key{laenge}). In der 2D-Draufsicht
ist die Zeile $y=1$ folglich die \emph{oberste} Zeile; in der
3D-Ansicht liegt sie am weitesten hinten. \key{hoehe} bezeichnet wie
in Karol Online die \emph{Raumhöhe} (Anzahl Ziegellagen bis zum
oberen Rahmen) und wirkt nur auf den 3D-Rahmen.

Mit \key{nummern} schreibt die Umgebung die Koordinaten an den Rand:
die Spaltennummern vor die vorderste Gitterkante, die Zeilennummern in
der Draufsicht links daneben. Im Schrägbild stehen die Zeilennummern
\emph{rechts} -- links lägen sie hinter den Stapeln der ersten Spalte
und würden verdeckt werden. Gezählt wird ab 1, es stehen also genau
die Zahlen am Rand, die man in \key{x} und \key{y} einträgt. Eine
hervorgehobene Zelle färbt ihre beiden Nummern mit.

\begin{center}
\begin{karolwelt}[breite=4, laenge=3, nummern, hervorheben={3/2},
		skalierung=0.7]
	\karol[x=1, y=3, richtung=osten]
	\ziegel[x=3, y=2, anzahl=2]
	\marke[x=4, y=1]
\end{karolwelt}
\qquad
\begin{karolwelt}[breite=4, laenge=3, nummern, hervorheben={3/2},
		ansicht=2d, skalierung=0.7]
	\karol[x=1, y=3, richtung=osten]
	\ziegel[x=3, y=2, anzahl=2]
	\marke[x=4, y=1]
\end{karolwelt}
\end{center}

\subsection{Schlüssel der Umgebung}

\begin{tabular}{@{}llp{7.6cm}@{}}
\key{breite} & 5 & Anzahl Spalten \\
\key{laenge} & 5 & Anzahl Zeilen \\
\key{hoehe} & 6 & Raumhöhe des 3D-Rahmens in Ziegellagen \\
\key{ansicht} & \key{3d} & \key{3d} (Schrägbild) oder \key{2d}
	(Draufsicht) \\
\key{zustand} & \key{beides} & \key{start}, \key{ziel} oder
	\key{beides} (Abschnitt~\ref{sec:zustand}) \\
\key{auftrag} & \key{keiner} & \key{aufbauen} oder \key{aufraeumen}:
	die Start- bzw.\ Zielwelt ist leer (Abschnitt~\ref{sec:zustand}) \\
\key{nummern} & \key{false} & Koordinaten an den Rand schreiben \\
\key{rahmen} & \key{true} & Raumrahmen zeichnen (nur 3D) \\
\key{hervorheben} & & Liste hervorzuhebender Zellen, etwa
	\key{\{2/2, 4/1\}} \\
\key{skalierung} & 1 & Skalierungsfaktor des Bildes \\
\key{titel} & & Beschriftung über dem Bild \\
\key{hinweis} & & kursiver Hinweis unter dem Bild \\
\end{tabular}

\subsection{Objekte}

Alle Objekte werden über Schlüssel platziert. \key{bisx}/\key{bisy}
(auch \key{bisX}/\key{bisY}) füllen rechteckige Bereiche.

\begin{lstlisting}
\karol[x=1, y=1, richtung=osten]  % genau einmal je Welt
\ziegel[x=2, y=3, anzahl=4]       % Stapel aus 4 Ziegeln
\ziegel[x=1, y=5, bisx=5]         % Reihe einzelner Ziegel
\marke[x=3, y=3]                  % gelbe Marke
\marke[x=5, y=1, farbe=cyan!60]   % Marke in eigener Farbe
\quader[x=4, y=1, bisy=5]         % Quaderwand; \wand = Synonym
\end{lstlisting}

\key{richtung} akzeptiert \key{osten}, \key{westen}, \key{norden} und
\key{sueden} sowie die Synonyme \key{rechts}, \key{links},
\key{hinten} bzw.\ \key{oben} und \key{vorn}, \key{vorne} bzw.\
\key{unten} (Vorgabe: \key{sueden}). Marken liegen stets \emph{oben auf} dem
Ziegelstapel ihrer Zelle; Karol steht auf Stapel und Marke.

\subsection{Beispiel in beiden Ansichten}

\begin{center}
\begin{karolwelt}[breite=4, laenge=4, skalierung=0.8,
		titel={3D-Ansicht}]
	\karol[x=1, y=4, richtung=osten]
	\ziegel[x=2, y=4]\ziegel[x=3, y=4, anzahl=2]
	\ziegel[x=4, y=4, anzahl=3]\ziegel[x=4, y=3, anzahl=4]
	\ziegel[x=4, y=2, anzahl=5]\ziegel[x=4, y=1, anzahl=6]
	\ziegel[x=3, y=1, anzahl=7]\ziegel[x=2, y=1, anzahl=8]
	\ziegel[x=1, y=1, anzahl=9]
	\marke[x=1, y=1]
\end{karolwelt}
\qquad
\begin{karolwelt}[breite=4, laenge=4, ansicht=2d,
		titel={2D-Ansicht}]
	\karol[x=1, y=4, richtung=osten]
	\ziegel[x=2, y=4]\ziegel[x=3, y=4, anzahl=2]
	\ziegel[x=4, y=4, anzahl=3]\ziegel[x=4, y=3, anzahl=4]
	\ziegel[x=4, y=2, anzahl=5]\ziegel[x=4, y=1, anzahl=6]
	\ziegel[x=3, y=1, anzahl=7]\ziegel[x=2, y=1, anzahl=8]
	\ziegel[x=1, y=1, anzahl=9]
	\marke[x=1, y=1]
\end{karolwelt}
\end{center}

In der 2D-Ansicht zeigen Zahlen die Stapelhöhe; Ziegelzellen sind
rosa, Marken eine einfarbige Fläche, die kleiner als das Feld ist —
so bleibt der Ziegel ringsum sichtbar und „Marke auf Ziegel“
erkennbar. Quader sind grau, Karol ist der schwarze Richtungskeil.

\subsection{Start- und Zielzustände}\label{sec:zustand}

Aufgaben in Robot Karol Online zeigen oft in \emph{einem} Bild, was
sich ändern soll: Ziegel und Marken, die bleiben, sehen aus wie immer;
was verschwinden soll, ist durchgekreuzt; was entstehen soll, erscheint
blass mit einem Pfeil bzw.\ als X-Fläche. Dasselbe leisten die
Schlüssel \key{start} und \key{ziel} an den Objekten.

\begin{tabular}{@{}llp{8.2cm}@{}}
\key{start} & \key{weg} & nur im Startzustand: soll verschwinden \\
\key{ziel} & \key{neu} & nur im Zielzustand: soll entstehen \\
\key{startanzahl} & & Ziegel im Startzustand \\
\key{zielanzahl} & & Ziegel im Zielzustand \\
\end{tabular}

\medskip
Wer beides oder keines von beiden nennt, bekommt ein Objekt, das in
beiden Zuständen vorkommt --- unverändert also. Statt \key{start} und
\key{ziel} darf man die Befehlsnamen von Robot Karol schreiben:
\key{hinlegen} und \key{aufheben} für Ziegel, \key{setzen} und
\key{loeschen} für Marken. \key{startanzahl} und \key{zielanzahl}
gibt es auch mit Bindestrich (\key{start-anzahl}, \key{ziel-anzahl}). Die Reihenfolge der
Schlüssel spielt keine Rolle: \verb|[anzahl=3, ziel]| und
\verb|[ziel, anzahl=3]| bedeuten dasselbe.

\begin{lstlisting}
\begin{karolwelt}[breite=4, laenge=3]
  \karol[x=1, y=3, richtung=osten]
  \ziegel[x=2, y=2]                              % bleibt liegen
  \ziegel[x=4, y=1, start]                       % nur im Start: verschwindet
  \ziegel[x=3, y=3, ziel]                        % nur im Ziel: entsteht
  \ziegel[x=3, y=1, aufheben]                    % dasselbe wie start
  \ziegel[x=4, y=2, hinlegen]                    % dasselbe wie ziel
  \ziegel[x=2, y=1, startanzahl=1, zielanzahl=3] % zwei kommen dazu
  \marke[x=1, y=1]                               % bleibt liegen
  \marke[x=2, y=2, loeschen]                     % soll geloescht werden
  \marke[x=4, y=2, setzen]                       % soll gesetzt werden
\end{karolwelt}
\end{lstlisting}

\begin{center}
\begin{karolwelt}[breite=4, laenge=3, skalierung=0.85]
	\karol[x=1, y=3, richtung=osten]
	\ziegel[x=2, y=2]
	\ziegel[x=4, y=1, start]
	\ziegel[x=3, y=3, ziel]
	\ziegel[x=3, y=1, aufheben]
	\ziegel[x=4, y=2, hinlegen]
	\ziegel[x=2, y=1, startanzahl=1, zielanzahl=3]
	\marke[x=1, y=1]
	\marke[x=2, y=2, loeschen]
	\marke[x=4, y=2, setzen]
\end{karolwelt}
\qquad
\begin{karolwelt}[breite=4, laenge=3, ansicht=2d, skalierung=0.85]
	\karol[x=1, y=3, richtung=osten]
	\ziegel[x=2, y=2]
	\ziegel[x=4, y=1, start]
	\ziegel[x=3, y=3, ziel]
	\ziegel[x=3, y=1, aufheben]
	\ziegel[x=4, y=2, hinlegen]
	\ziegel[x=2, y=1, startanzahl=1, zielanzahl=3]
	\marke[x=1, y=1]
	\marke[x=2, y=2, loeschen]
	\marke[x=4, y=2, setzen]
\end{karolwelt}
\end{center}

\begin{center}
	\karolzustandslegende
\end{center}

\medskip
In der 2D-Draufsicht gibt es keine Kreuze und keine Pfeile: dort steht
die Stapelzahl des Startzustands mittig und die Veränderung als rote
Zahl in der Ecke.

\verb|\karolzustandslegende| erklärt nur die vier Zustandszeichen; die
gewöhnlichen Symbole erklärt weiterhin \verb|\karollegende|
(Abschnitt~\ref{sec:zeile}). Eine eigene Legende setzt man aus
Einträgen der Form
\begin{center}
\verb|\karolzustandslegendenitem{Objekt}{Text}|
\end{center}
zusammen: das erste Argument ist der Rumpf einer Welt aus einem
einzigen Feld (Koordinaten
\texttt{x=1, y=1}), das zweite die Beschriftung. Zwischen die Einträge
gehört \verb|\karollegendentrenner|:

\begin{lstlisting}
\karolzustandslegendenitem{\ziegel[x=1, y=1, anzahl=2, hinlegen]}
  {zwei Ziegel hinlegen}\karollegendentrenner
\karolzustandslegendenitem{\marke[x=1, y=1, setzen]}
  {Marke setzen}
\end{lstlisting}

\begin{center}
\karolzustandslegendenitem{\ziegel[x=1, y=1, anzahl=2, hinlegen]}
  {zwei Ziegel hinlegen}\karollegendentrenner
\karolzustandslegendenitem{\marke[x=1, y=1, setzen]}
  {Marke setzen}
\end{center}

Der Schlüssel \key{zustand} wählt, was gezeigt wird. \key{beides} ist
wie in Karol Online und liefert das Bild oben; \key{start} und \key{ziel}
zeigen je \emph{eine} Welt in der gewohnten Optik --- eine Welt ohne
\key{start}- und \key{ziel}-Angaben sieht in allen drei Fällen gleich
aus.

Für „vorher / nachher“ nebeneinander gibt es die Umgebung
\texttt{karolweltpaar}. Ihr Rumpf wird zweimal gezeichnet, links im
Zustand \key{links} (Vorgabe \key{start}), rechts im Zustand
\key{rechts} (Vorgabe \key{ziel}); dazu \key{trenner},
\key{titellinks} und \key{titelrechts} (Vorgaben: ein Pfeil sowie
\textbf{Start} und \textbf{Ziel}). Alle übrigen Schlüssel
reicht sie an beide Welten durch.

\begin{lstlisting}
\begin{karolweltpaar}[breite=4, laenge=2]
  \karol[x=1, y=2, richtung=osten]
  \ziegel[x=3, y=1, anzahl=2, aufheben]
  \ziegel[x=4, y=2, anzahl=3, hinlegen]
  \marke[x=2, y=1, setzen]
\end{karolweltpaar}
\end{lstlisting}

\begin{karolweltpaar}[breite=4, laenge=2, skalierung=0.72]
	\karol[x=1, y=2, richtung=osten]
	\ziegel[x=3, y=1, anzahl=2, aufheben]
	\ziegel[x=4, y=2, anzahl=3, hinlegen]
	\marke[x=2, y=1, setzen]
\end{karolweltpaar}

Soll am Ende \emph{alles} weggeräumt sein, wäre an jedem Objekt ein
\key{weg} oder \key{start} nötig. Umgekehrt
bräuchte beim Bau einer Mauer jeder Ziegel ein \key{neu} oder \key{ziel}. 
Dafür gibt es den Schlüssel \key{auftrag}. Er legt fest, wozu ein Objekt
\emph{ohne} eigene Angabe gehört:

\begin{tabular}{@{}lp{9cm}@{}}
\key{keiner} & zu Start und Ziel (Vorgabe) \\
\key{aufraeumen} & nur zum Start -- die Zielwelt ist leer
	(auch \key{aufräumen}) \\
\key{aufbauen} & nur zum Ziel -- die Startwelt ist leer \\
\end{tabular}

\medskip
Wer an einem Objekt \key{start}, \key{ziel} oder eine Anzahl angibt,
behält seine Angabe. Quader und Karol betrifft \key{auftrag} nicht:
Wände stehen in beiden Zuständen.

\begin{lstlisting}
\begin{karolwelt}[breite=6, laenge=3, auftrag=aufraeumen]
  \ziegel[x=2, y=2, bisx=5, anzahl=2]  % alles ohne Angabe = nur Start
  \marke[x=3, y=3, start, ziel]        % Ausnahme: diese Marke bleibt
\end{karolwelt}
\end{lstlisting}

\noindent\begin{minipage}{\linewidth}
\begin{lstlisting}
\begin{karolwelt}[breite=6, laenge=2, auftrag=aufbauen]
  \karol[x=1, y=2, richtung=osten]
  \ziegel[x=2, y=1, bisx=5, anzahl=2]  % die Mauer entsteht erst
  \quader[x=6, y=1]                    % Wand: steht schon
\end{karolwelt}
\end{lstlisting}

\begin{center}
\begin{karolwelt}[breite=6, laenge=2, auftrag=aufbauen, skalierung=0.72]
	\karol[x=1, y=2, richtung=osten]
	\ziegel[x=2, y=1, bisx=5, anzahl=2]
	\quader[x=6, y=1]
\end{karolwelt}
\end{center}
\end{minipage}

Nicht ausdrückbar sind eine Zielposition für Karol und ein
Farbwechsel einer Marke: \key{farbe} gilt für beide Zustände, und
Robot Karol Online vergleicht die Figur beim Prüfen ohnehin nicht.
Quader kennen keinen Zielzustand --- Karol kann sie weder setzen noch
räumen.

\section{Einzeilige Welten: \texttt{\textbackslash karolzeile}}\label{sec:zeile}

Für schnelle eindimensionale Welten gibt es die kompakte
Zeichenketten-Notation (bis Version 2.x hieß das Kommando
\texttt{\textbackslash karolwelt}). Gezeichnet wird mit denselben
Bausteinen wie in der Umgebung \texttt{karolwelt}: gleiche Projektion,
gleiches Bodengitter, gleiche Ziegel, Marken, Quader und derselbe
Avatar. Eine Zeilen-Welt ist damit optisch nichts anderes als eine
\texttt{karolwelt} mit \key{laenge}\,=\,1 -- nur die Eingabe ist kürzer.

\begin{center}
\begin{tabular}{@{}c@{\qquad}l@{}}
\karolzeile[skalierung=0.8]{> Z 2 {2M} {3>} M Q} &
\begin{minipage}[c]{6.6cm}
\begin{lstlisting}
\karolzeile{> Z 2 {2M} {3>} M Q}
\end{lstlisting}
\end{minipage}
\end{tabular}
\end{center}

\begin{tabular}{@{}ll@{}}
\verb|> < ^ v| & Karol mit Blickrichtung \\
\verb|.| & leeres Feld \\
\verb|Z|, \verb|2|\,…\,\verb|9| & Ziegel bzw.\ Stapel \\
\verb|M|, \verb|Q| & Marke, Quader \\
\verb|{...}| & mehrere Objekte auf einem Feld, von unten nach
	oben: \verb|{M>}|, \verb|{2M}|, \verb|{3>}| \\
\end{tabular}

\subsection{Schlüssel}

\begin{tabular}{@{}lll@{}}
\key{skalierung} & 1 & Skalierungsfaktor des Bildes \\
\key{nummern} & \texttt{true} & Feldnummern anzeigen (ab 1) \\
\key{titel} & --- & Zeile über dem Bild \\
\key{hinweis} & --- & kursive Zeile unter dem Bild \\
\key{hervorheben} & --- & Komma-Liste von Feldnummern \\
\key{rahmen} & \texttt{false} & Raumrahmen wie in \texttt{karolwelt} \\
\key{hoehe} & 3 & Raumhöhe des Rahmens in Ziegellagen \\
\end{tabular}

Die \textbf{Feldnummern} stehen vor der vordersten Gitterkante und nicht
auf dem Feld: im Schrägbild würde sie sonst jeder Ziegelstapel verdecken.
Sie zählen wie \key{x} in \texttt{karolwelt} ab 1; \key{hervorheben}
nimmt dieselben Nummern.
\key{hervorheben} zeichnet einen magentafarbenen Rahmen knapp außerhalb
des Feldes und färbt dessen Nummer mit -- ein roter Rahmen wäre neben den
reinroten Ziegelkanten nicht zu erkennen (Farbe: \key{hervorfarbe}).
Den Raumrahmen zeichnet \verb|\karolzeile| nur auf Wunsch; für eine
einzelne Reihe ist er meist nicht nötig.

\begin{center}
\karolzeile[skalierung=0.8, hervorheben={2,5}]{> Z 2 {2M} M Q .}
\qquad
\karolzeile[skalierung=0.8, rahmen, hoehe=3]{> Z 2 {2M} M Q .}
\end{center}

Dazu gibt es

\begin{tabular}{@{}lp{7.4cm}@{}}
\verb|\karolpaar[keys][keys2]{vorher}{nachher}| & Vorher-nachher-Paar;
	\texttt{keys} gilt für beide Bilder, \texttt{keys2} nur für
	„nachher" \\
\verb|\karolgitter[keys]{n}| & leeres Gitter aus $n$ Feldern \\
\verb|\karollegende| & Standardlegende der Weltsymbole \\
\verb|\karollegendenitem{Welt}{Text}| & einzelner Legendeneintrag \\
\verb|\karollegendentrenner| & Abstand zwischen zwei Einträgen; dehnbar,
	die Legende darf dort umbrechen \\
\end{tabular}

\section{Blockprogramme}

Die Umgebung \texttt{karolbloecke} stapelt Blockly-Blöcke; Farben und
Formen entsprechen der Karol-Online-Oberfläche.

\begin{center}
\begin{minipage}[c]{0.56\textwidth}
\begin{lstlisting}
\begin{karolbloecke}
  \bwiederholesolange{NichtIstWand}{%
    \bwenndann{IstZiegel}{%
      \bbefehl[1]{Aufheben}}
    \bbefehl[1]{Schritt}}
\end{karolbloecke}
\end{lstlisting}
\end{minipage}\hfill
\begin{minipage}[c]{0.40\textwidth}
\begin{karolbloecke}[skalierung=0.9]
	\bwiederholesolange{NichtIstWand}{%
		\bwenndann{IstZiegel}{%
			\bbefehl[1]{Aufheben}}
		\bbefehl[1]{Schritt}}
\end{karolbloecke}
\end{minipage}
\end{center}

\begin{tabular}{@{}lp{8.2cm}@{}}
\verb|\bbefehl[n]{Name}| & Anweisung (violett); optionale Zahl als
	Pille \\
\verb|\bwiederholemal{n}{...}| & Zählschleife \\
\verb|\bwiederholesolange{Bed}{...}| & kopfgesteuerte Schleife \\
\verb|\bwiederholeimmer{...}| & Endlosschleife \\
\verb|\bwenndann{Bed}{...}| & einseitige Verzweigung \\
\verb|\bwenndannsonst{Bed}{...}{...}| & zweiseitige Verzweigung \\
\verb|\bbedingung[n]{IstZiegel}| & Bedingung mit linkem Stecker; auch
	im Fließtext; optionale Anzahl als Pille; leeres Argument =
	weißer Leersockel \\
\verb|\bist{Norden}| & Himmelsrichtung als Auswahlmenü \\
\verb|\bnichtist{Norden}| & dasselbe verneint \\
\verb|\bluecke[Breite]| & gestrichelter Geisterblock \\
\verb|\bkommentar{Text}| & Kommentar (khaki, \texttt{//}) \\
\verb|\baufruf[n]{Name}| & Aufruf einer eigenen Anweisung (rot) \\
\verb|\banweisung{Name}{...}| & Definition einer eigenen Anweisung \\
\verb|\bhauptprogramm| & Hauptprogramm-Hut \\
\end{tabular}

\subsection{Bedingungen mit Anzahl}

In Robot Karol Online nehmen \verb|IstZiegel| und \verb|NichtIstZiegel|
eine Anzahl entgegen -- im Blockeditor ein Zahlenfeld, im Programmtext
\verb|IstZiegel(2)|. Im Paket steht sie als optionales Argument vor der
Bedingung; die Pille trägt kein Auswahldreieck, denn im Original ist es
ein Zahlenfeld und kein Menü.

\begin{center}
\begin{karolbloecke}[skalierung=0.9]\bbedingung[2]{IstZiegel}\end{karolbloecke}\quad
\begin{karolbloecke}[skalierung=0.9]\bbedingung[2]{NichtIstZiegel}\end{karolbloecke}
\end{center}

Die Zahl gehört der Bedingung, nicht dem Block. Die Kontrollblöcke
reichen sie als erstes, optionales Argument an ihre Bedingung durch --
die Pille bleibt darum auch im grünen \verb|\bwenndann| stahlblau.

\begin{center}
\begin{minipage}[c]{0.52\textwidth}
\begin{lstlisting}
\bwiederholesolange[2]{IstZiegel}{%
  \bbefehl{Schritt}}
\end{lstlisting}
\end{minipage}\hfill
\begin{minipage}[c]{0.44\textwidth}
\begin{karolbloecke}[skalierung=0.9]
	\bwiederholesolange[2]{IstZiegel}{%
		\bbefehl{Schritt}}
\end{karolbloecke}
\end{minipage}
\end{center}

\subsection{Himmelsrichtungen}

Die acht Blöcke \verb|Ist|\,/\,\verb|NichtIst| zeigen die Richtung in
Robot Karol Online nicht als Text, sondern als Auswahlmenü: eine helle
Pille mit Auswahldreieck. \verb|\bist{...}| und \verb|\bnichtist{...}|
bilden das nach und nehmen die Richtung als Argument.

\begin{center}
\begin{karolbloecke}[skalierung=0.9]\bist{Norden}\end{karolbloecke}\quad
\begin{karolbloecke}[skalierung=0.9]\bnichtist{Westen}\end{karolbloecke}
\end{center}

Für sich allein ergeben sie ein vollständiges Bedingungsplättchen. Als
Argument eines Kontrollblocks steuern sie nur dessen Beschriftung bei --
das Plättchen baut dort wie gewohnt \verb|\bbedingung|:

\begin{center}
\begin{minipage}[c]{0.52\textwidth}
\begin{lstlisting}
\bwenndann{\bist{Norden}}{%
  \bbefehl{Schritt}}
\end{lstlisting}
\end{minipage}\hfill
\begin{minipage}[c]{0.44\textwidth}
\begin{karolbloecke}[skalierung=0.9]
	\bwenndann{\bist{Norden}}{%
		\bbefehl{Schritt}}
\end{karolbloecke}
\end{minipage}
\end{center}

Dasselbe Auswahldreieck trägt der Aufrufblock \verb|\baufruf|: dort
wählt man in der Oberfläche die aufzurufende Anweisung aus. Die
Definition \verb|\banweisung| zeigt den Namen dagegen in einer Pille
ohne Dreieck.

\begin{center}
\begin{karolbloecke}[skalierung=0.9]
	\banweisung{TueEtwas}{\bbefehl[1]{Schritt}}
\end{karolbloecke}\qquad
\begin{karolbloecke}[skalierung=0.9]\baufruf{TueEtwas}\end{karolbloecke}
\end{center}

Beispiel Lückenaufgabe mit Leersockel und Geisterblock:

\begin{center}
\begin{karolbloecke}[skalierung=0.9]
	\bwiederholesolange{}{%
		\bluecke
		\bbefehl[1]{Schritt}}
\end{karolbloecke}
\end{center}

\section{Inline-Blöcke im Fließtext}

Die \verb|\i...|-Kommandos setzen genau \emph{einen} Block in die
laufende Zeile. Die Textgrundlinie des Blocks liegt dabei exakt auf der
Grundlinie des umgebenden Textes, und die Beschriftung übernimmt dessen
Schriftgröße; Kerbe, Nase und Innenabstände sind flacher als im Stapel,
damit die Blockhöhe der Zeilenhöhe nahekommt.

\begin{lstlisting}
Mit \iwenndann{IstZiegel} prüft Karol, ob ein Ziegel vor ihm liegt;
\iwiederholemal{5} wiederholt fünfmal, \ibefehl{Schritt} geht weiter.
\end{lstlisting}

\noindent
Mit \iwenndann{IstZiegel} prüft Karol, ob ein Ziegel vor ihm liegt;
\iwiederholemal{5} wiederholt fünfmal, \ibefehl{Schritt} geht weiter.

\medskip\noindent
{\sloppy
Blöcke, die im Stapel mehrzeilig wären -- Schleifen, Verzweigungen und
eigene Anweisungen --, erscheinen inline \textbf{nur mit ihrem Kopf}.
\verb|\iwenndann{IstZiegel}| ergibt also den Block \iwenndann{IstZiegel}
ohne Rumpf. Für echte Rümpfe bleibt die Umgebung \texttt{karolbloecke}
zuständig.\par}

% Inline-Blöcke sind höher als eine normale Textzeile: Zeilen strecken.
\begingroup\renewcommand{\arraystretch}{1.45}
\begin{tabular}{@{}lp{8.2cm}@{}}
\verb|\ibefehl[n]{Name}| & Anweisung \ibefehl[3]{Schritt} \\
\verb|\iaufruf[n]{Name}| & Aufruf einer eigenen Anweisung \\
\verb|\ianweisung{Name}| & Kopf einer eigenen Anweisung \\
\verb|\ikommentar{Text}| & Kommentar \\
\verb|\ihauptprogramm| & Hauptprogramm-Hut \\
\verb|\iwiederholemal{n}| & Kopf der Zählschleife \iwiederholemal{5} \\
\verb|\iwiederholesolange[n]{Bed}| & Kopf der kopfgesteuerten Schleife \\
\verb|\iwiederholeimmer| & Kopf der Endlosschleife \\
\verb|\iwenndann[n]{Bed}| & Kopf der Verzweigung \\
\verb|\isonst| & sonst-Balken \isonst{} \\
\verb|\ibedingung[n]{Bed}| & Bedingung \ibedingung{IstMarke},
	mit Anzahl \ibedingung[2]{IstZiegel} \\
\verb|\iist{Norden}| & Himmelsrichtung \iist{Norden} \\
\verb|\inichtist{Norden}| & verneint \inichtist{Osten} \\
\verb|\iluecke[Breite]| & Geisterblock \iluecke{} \\
\end{tabular}
\endgroup

\medskip\noindent
Die \verb|\b...|-Kommandos erkennen den Fließtext selbst und setzen dort
ebenfalls inline; die \verb|\i...|-Fassungen ersparen nur die leeren
Rumpf-Argumente und erzwingen den Modus auch im Stapel.

Inline-Blöcke sind breite, unzerbrechliche Kästen. In schmalen Spalten
kann \hologo{TeX} sie nicht immer umbrechen -- dann hilft
\verb|\sloppy| oder eine höhere \verb|\tolerance| für den Absatz.

\section{Text-Programme und Struktogramme}

Die Umgebung \texttt{karolcode} setzt Karol-Quelltext mit
Syntaxhervorhebung (\pkg{listings}); \verb|\kb{...}| und
\verb|\kw{...}| formatieren Bezeichner und Schlüsselwörter im
Fließtext. Für Struktogramme lädt das Paket \pkg{struktex} und
ergänzt \verb|\leeranweisung| sowie \verb|\stklucke[Breite]|.

\section{Globale Einstellungen: \texttt{\textbackslash karolsetup}}

\begin{lstlisting}
\karolsetup{feldbreite=8.4mm, befehlfarbe={RGB}{116,91,165}, ...}
\end{lstlisting}

\subsection{Schriften}\label{sec:schriften}

Die Oberfläche von Robot Karol Online setzt ihre Beschriftungen in
\emph{Noto Sans} und den Programmtext des Editors in \emph{Hack}. Das
Paket tut das seit v3.6 ebenso: Beschriftungen der Blöcke, Feldnummern
und Stapelzahlen erscheinen in Noto Sans, \texttt{karolcode} sowie
\verb|\kb| und \verb|\kw| in Hack. Dafür lädt das Paket
\pkg{fontspec}. Noto Sans liegt in \TeX\ Live; Hack nicht -- ist es im
System installiert, wird es benutzt, sonst DejaVu Sans Mono, aus dessen
Vorläufer Hack hervorgegangen ist. Welche der beiden es geworden ist,
steht in der \texttt{.log}-Datei.

Wer die Schriften des eigenen Dokuments übernehmen will -- oder
\pkg{fontspec} nicht geladen haben möchte --, lädt das Paket mit

\begin{lstlisting}
\usepackage[schrift=dokument]{robotkarol}
\end{lstlisting}

\noindent
Dann benutzt das Paket \verb|\sffamily| und \verb|\ttfamily| des
Dokuments; die Ausgabe ist Zeichen für Zeichen dieselbe wie bis v3.5.
Umschalten geht auch mitten im Dokument, in einer Gruppe nur dort:

\begin{tabular}{@{}ll@{}}
\key{schrift=karol} & Noto Sans und Hack (Vorgabe) \\
\key{schrift=dokument} & \verb|\sffamily| und \verb|\ttfamily| des Dokuments \\
\key{textschrift=\{...\}} & eigene Schrift für Beschriftungen \\
\key{codeschrift=\{...\}} & eigene Schrift für Programmtext \\
\end{tabular}

\noindent
Die beiden letzten Schlüssel nehmen den Umschaltbefehl selbst:

\begin{lstlisting}
\karolsetup{textschrift={\fontspec{Fira Sans}}}
\end{lstlisting}

\noindent
Ein \verb|\karolsetup{schrift=karol}| in einem Dokument, das mit
\key{schrift=dokument} geladen wurde, ist wirkungslos (mit Warnung) --
die Schriften sind dann gar nicht geladen.

Titel und Hinweis einer Welt bleiben absichtlich in der Schrift des
Dokuments: sie sind Text des Dokuments, keine Beschriftung der
Zeichnung. Für eigenen Text in der Paketschrift gibt es die Umschalter
\verb|\karolschrift| und \verb|\karolcodeschrift|.

\subsection{Weltfarben}

Sie wirken auf \verb|\karolzeile| \emph{und} die Umgebung
\texttt{karolwelt}, die dieselben Bausteine zeichnen.

\begin{tabular}{@{}lll@{}}
\key{feldbreite} & 8.4\,mm & Zell-/Feldbreite aller Welten \\
\key{ziegelfarbe} & reines Rot & Lagenkante; Körper daraus abgeleitet
	(\texttt{!59!black}) \\
\key{ziegelkoerperfarbe} & 150,8,8 & nur die Ziegelflächen \\
\key{ziegelkantenfarbe} & 255,0,0 & nur die Lagenkanten \\
\key{markenfarbe} & 250,205,60 & Markenplatte \\
\key{quaderfarbe} & 128,128,128 & Quader\,/\,Wand \\
\key{bodenfarbe}, \key{gitterfarbe} & 45,45,215 & Bodengitter \\
\key{hervorfarbe} & 226,0,122 & \key{hervorheben} \\
\end{tabular}

\subsection{Figur der Welten}

Das Paket bringt zwei Figuren mit: \key{karol} (Vorgabe) und
\key{emma} mit langem Haar und einer Blume in der Hand. Umgeschaltet
wird mit

\begin{lstlisting}
\karolfigur{emma}           % gleichwertig: \karolsetup{figur=emma}
\end{lstlisting}

\noindent
Die Einstellung wirkt auf \verb|\karolzeile| \emph{und} die Umgebung
\texttt{karolwelt}; in einer Gruppe gesetzt gilt sie nur dort.

\begin{center}
\begin{tabular}{@{}c@{\qquad}c@{}}
\karolzeile[nummern=false, skalierung=1.1]{> ^ < v} &
{\karolfigur{emma}\karolzeile[nummern=false, skalierung=1.1]{> ^ < v}} \\[2pt]
\texttt{karol} & \texttt{emma} \\
\end{tabular}
\end{center}

{\sloppy
Emma ist aus derselben Figur gebaut wie Karol. Ihre Farben heißen
\key{karolEmmaShirt}, \key{karolEmmaHaar}, \key{karolEmmaBluete} und
\key{karolEmmaStiel} und lassen sich mit \verb|\colorlet| ändern.\par}

\subsection{Blockfarben}

\begin{tabular}{@{}lll@{}}
\key{befehlfarbe} & 116,91,165 & Anweisungsblöcke \\
\key{schleifenfarbe}, \key{verzweigungfarbe} & 91,165,91 &
	grüne Kontrollblöcke \\
\key{bedingungfarbe} & 91,128,165 & Bedingungen \\
\key{anweisungfarbe} & 165,91,98 & eigene Anweisungen \\
\key{kommentarfarbe} & 165,150,91 & Kommentare \\
\key{hutfarbe} & 130,123,117 & Hauptprogramm-Hut \\
\end{tabular}

Die Blockfarben sind aus der Karol-Online-Oberfläche übernommen.

\subsection{Druckmodus}\label{sec:druck}

Arbeitsblätter werden selten in Farbe vervielfältigt. Der Druckmodus
zeichnet deshalb alle Ansichten -- Welten, Zeilen-Welten und
Blockprogramme -- in Graustufen:

\begin{lstlisting}
\usepackage[druck]{robotkarol}   % das ganze Dokument
\karolsetup{druck=true}          % ab hier; in einer Gruppe nur dort
\karolsetup{druck=false}         % zurueck zur Farbdarstellung
\end{lstlisting}

\noindent
Der Leitgedanke ist \emph{nicht} das absolute Minimum an Toner zu verwenden,
sondern: so wenig wie möglich, so viel wie nötig. Deshalb tragen die Konturen
die Information, und die Flächen bleiben so hell wie möglich:

\begin{itemize}
\item Ziegel sind \emph{weiß} mit schwarzen Kanten -- der
	Stapel bleibt seitlich abzählbar, kostet aber praktisch keine Farbe.
\item Der Quader ist die einzige große graue Fläche der Welt: er teilt
	seine Form mit dem Ziegel und muss sich von ihm abheben.
\item Die Marke ist mittelgrau. Sie ist klein, und sie liegt oft auf
	einem Ziegel, von dem sie sich absetzen muss.
\item Bei den Blöcken bekommt der häufigste -- \verb|\bbefehl| -- die
	weiße Fläche; die formgleichen \verb|\baufruf| und
	\verb|\banweisung| bekommen eine \textbf{45-Grad-Schraffur} auf
	weißem Grund. Ein bloß dunkleres Grau trug diesen Unterschied
	nicht -- beide Blöcke haben dieselbe Form, im Original
	unterscheidet sie allein die Farbe (violett gegen rot).
	Beschriftung und Namenspille stehen dabei auf weißem Grund;
	schraffiert ist nur der Hintergrund. Nebenbei braucht die
	Schraffur weniger Farbe als eine graue Fläche.
	Alles übrige unterscheidet sich ohnehin schon durch die Form
	(C-Maul, Hut, Bedingungsplättchen).
\item An die Stelle des 3D-Anschliffs tritt eine schwarze Kontur, und
	die Eingabepillen bekommen einen Rand: auf einem weißen Block wären
	sie sonst nicht zu sehen.
\end{itemize}

\begin{center}
\begin{tabular}{@{}c@{\qquad}c@{}}
\karolzeile[skalierung=0.85]{> Z 2 {2M} M Q} &
{\karolsetup{druck=true}\karolzeile[skalierung=0.85]{> Z 2 {2M} M Q}} \\[4pt]
\begin{karolbloecke}[skalierung=0.85]
	\bwiederholemal{4}{%
		\bbefehl{Schritt}
		\baufruf{Drehen}}
\end{karolbloecke} &
{\karolsetup{druck=true}
\begin{karolbloecke}[skalierung=0.85]
	\bwiederholemal{4}{%
		\bbefehl{Schritt}
		\baufruf{Drehen}}
\end{karolbloecke}} \\[2pt]
\texttt{druck=false} (Vorgabe) & \texttt{druck=true} \\
\end{tabular}
\end{center}

\noindent
Die Farbschlüssel aus den vorigen Abschnitten bleiben dabei
unangetastet: sie wirken wieder, sobald der Druckmodus aus ist -- im
Druckmodus selbst haben sie keine Wirkung, denn eigene Farben würden das
Graustufenschema gerade aufheben. Eigene \emph{Markenfarben}
(\verb|\marke[x=2, y=1, farbe=cyan]|) werden in ihren Grauwert
umgesetzt, bleiben also als verschiedene Grautöne unterscheidbar. Die
beiden Farben, die es nur im Druck gibt, heißen
\key{karolDruckKontur} (Blockkonturen und Pillenränder) und
\key{karolDruckAkzent} (Auswahldreieck der Pillen); sie lassen sich mit
\verb|\definecolor| ändern.

\section{Aufgaben verlinken: \texttt{\textbackslash karolonline}}
\label{sec:online}

Eine Aufgabe in Robot Karol Online steckt vollständig in ihrer Adresse:
auf \url{https://karol.arrrg.de/} folgt eine Raute und der
Aufgabencode. \verb|\karolonline| macht daraus einen Verweis und setzt
dabei nur, was man tatsächlich eintippen muss:

\begin{lstlisting}
Die Aufgabe steht unter \karolonline{2t7t}.
\end{lstlisting}

\noindent
Das ergibt: Die Aufgabe steht unter \karolonline{2t7t}. Der Verweis
führt auf \url{https://karol.arrrg.de/#2t7t}. Der Code wird dabei
unverändert übernommen -- auf Groß- und Kleinschreibung kommt es bei
den Aufgabencodes nicht an.

\subsection{Mit oder ohne \pkg{hyperref}}\label{sec:hyperref}

Der Verweis braucht \pkg{hyperref}. Ob \pkg{robotkarol} es lädt,
entscheidet eine Paketoption:

\begin{tabular}{@{}ll@{}}
\key{hyperref=true} & \pkg{hyperref} wird geladen (Vorgabe) \\
\key{hyperref=false} & \pkg{hyperref} wird nicht geladen \\
\end{tabular}

\noindent
Ohne \pkg{hyperref} setzt \verb|\karolonline| denselben Text, nur ohne
Verweis; das Dokument übersetzt in beiden Fällen unverändert.

Geladen wird erst am Ende der Präambel (im Haken
\texttt{begindocument/before}) -- \pkg{hyperref} möchte als letztes
Paket geladen werden. Ein Dokument darf es deshalb auch selbst laden,
mit eigenen Optionen und an beliebiger Stelle, ohne Optionskonflikt:

\begin{lstlisting}
\usepackage{robotkarol}
\usepackage[colorlinks]{hyperref}
\end{lstlisting}

\noindent
Geladen wird dabei ohne Optionen: wie Verweise aussehen -- farbig,
umrahmt oder unsichtbar --, stellt das Dokument selbst ein, etwa mit
\verb|\usepackage[hidelinks]{hyperref}| oder \verb|\hypersetup{...}|.

Und weil \verb|\karolonline| nicht die Paketoption abfragt, sondern ob
es \verb|\href| beim Setzen wirklich gibt, verlinkt es auch in einem
Dokument, das \pkg{hyperref} trotz \key{hyperref=false} selbst geladen
hat.

Ein Verweis ist ein unteilbarer Block. Steht er in einer schmalen
Spalte, braucht der Absatz unter Umständen ein \verb|\sloppy| (wie die
Inline-Blöcke auch).

\section{Aufgaben aus Robot Karol Online: JSON}\label{sec:json}

Robot Karol Online speichert eine Aufgabe als JSON-Datei: im Editor
\emph{Aufgabe freigeben} $\rightarrow$ \emph{Als JSON herunterladen}.
\pkg{robotkarol} liest solche Dateien und kann sie auch schreiben: eine in
Karol Online gebaute Aufgabe kann also fast direkt in \LaTeX{} gesetzt
werden, und eine in \LaTeX{} gesetzte Welt lässt sich in Karol Online hochladen.
Gelesen und geschrieben wird mit \hologo{LuaLaTeX} selbst ohne
Shell-Escape. Die Datei \texttt{robotkarol.lua} gehört dazu und muss neben
\texttt{robotkarol.sty} liegen.

Eine Aufgabe enthält eine oder mehrere Teilaufgaben (in Karol Online
\emph{Aufträge}), jede mit einer Start- und einer Zielwelt. Eine
Teilaufgabe entspricht genau einer Umgebung \texttt{karolwelt}: Start
und Ziel stehen darin wie in Abschnitt~\ref{sec:zustand}. Die
Koordinaten sind dieselben wie in Karol Online -- \key{x} von links,
\key{y} von hinten, beide ab~1.

\subsection{Einlesen und abfragen}

\begin{lstlisting}
\karoljsonlesen[name=treppen]{robotkarol-doc-treppen.json}
\end{lstlisting}
\karoljsonlesen[name=treppen]{robotkarol-doc-treppen.json}%
\noindent
liest die Datei unter dem Namen \texttt{treppen} ein; ohne
\key{name} heißt sie wie die Datei ohne Endung. Gesucht wird im
Arbeitsverzeichnis, neben der \texttt{.tex}-Datei und wie jede andere
Eingabedatei. Jede Datei wird je Lauf nur einmal gelesen. Statt des
Namens darf überall auch der Dateiname stehen (\texttt{treppen.json});
die Datei wird dann bei Bedarf geladen.

\begin{tabular}{@{}ll@{}}
\verb|\karoljsontitel{treppen}| & \karoljsontitel{treppen} \\
\verb|\karoljsonbeschreibung{treppen}| & \karoljsonbeschreibung{treppen} \\
\verb|\karoljsonanzahl{treppen}| & \karoljsonanzahl{treppen} \\
\verb|\karoljsonaufgabentitel{treppen}{1}| & \karoljsonaufgabentitel{treppen}{1} \\
\verb|\karoljsonzielart{treppen}{1}| & \karoljsonzielart{treppen}{1} \\
\verb|\karoljsonzielart{treppen}{2}| & \karoljsonzielart{treppen}{2} \\
\end{tabular}

Texte kommen unverändert an: \verb|& % # _ $ ~ ^| im Titel werden
gesetzt, nicht ausgeführt. Markdown in der Beschreibung wertet das
Paket nicht aus; eine Leerzeile beginnt einen neuen Absatz.
\verb|\karoljsonanzahl| und \verb|\karoljsonzielart| sind expandierbar,
man kann mit ihnen rechnen und vergleichen.

\subsection{Eine Welt aus der Datei}

\begin{lstlisting}
\karolweltaus{treppen}
\karolweltaus[zustand=start, ansicht=2d]{treppen}
\karolweltaus[zustand=ziel, ansicht=2d]{treppen}
\end{lstlisting}

\begin{center}
\karolweltaus[skalierung=0.8]{treppen}\quad
\karolweltaus[zustand=start, ansicht=2d, skalierung=0.8]{treppen}\quad
\karolweltaus[zustand=ziel, ansicht=2d, skalierung=0.8]{treppen}
\end{center}

\verb|\karolweltaus[|\textit{Schlüssel}\verb|]{|\textit{Quelle}\verb|}|
ist eine Kurzform für eine Umgebung mit dem Schlüssel \key{quelle}.
Welche Teilaufgabe gemeint ist, sagt \key{aufgabe} (Vorgabe~1).
\key{breite}, \key{laenge} und \key{hoehe} kommen aus der Datei; alle
anderen Schlüssel der Umgebung wirken wie gewohnt, auch in
\texttt{karolweltpaar}:

\begin{lstlisting}
\begin{karolweltpaar}[quelle=treppen]\end{karolweltpaar}
\end{lstlisting}

Mit der Umgebung lässt sich die eingelesene Welt ergänzen. Erst wird
die Datei eingetragen, dann der Rumpf; der Rumpf gewinnt je Zelle:

\begin{lstlisting}
\begin{karolwelt}[quelle=treppen, hervorheben={5/2}]
  \ziegel[x=4, y=2, zielanzahl=0]   % Stufe 3 entfällt
  \marke[x=1, y=3]                  % neue Marke, Start und Ziel
\end{karolwelt}
\end{lstlisting}

\begin{center}
\begin{karolwelt}[quelle=treppen, hervorheben={5/2}, skalierung=0.8]
  \ziegel[x=4, y=2, zielanzahl=0]
  \marke[x=1, y=3]
\end{karolwelt}
\end{center}

Ein Objekt ohne Seitenangabe ersetzt die Zelle in Start und Ziel, eins
mit Seitenangabe nur die genannte Seite, und \key{startanzahl=0} bzw.
\key{zielanzahl=0} löscht den Eintrag aus der Datei. \key{auftrag} wirkt
nur auf die Objekte des Rumpfs.

\subsection{Drei Arten von Aufgaben}

Karol Online kennt keine eigene Angabe \glqq Aufgabe mit Ziel\grqq{} --
es vergleicht Start- und Zielwelt. \verb|\karoljsonzielart| liefert das
Ergebnis:

\begin{tabular}{@{}lp{0.68\linewidth}@{}}
\texttt{welt} & Start und Ziel sind verschieden. Karol Online prüft,
	ob das Programm die Zielwelt herstellt. Auch ein Aufräumauftrag
	(Ziel ohne Ziegel und Marken) gehört dazu. \\
\texttt{frei} & Start und Ziel sind gleich: eine Welt zum
	Ausprobieren, ohne Prüfung (\glqq Ausführung beendet\grqq). Karols
	Position zählt dabei nicht mit. \\
\texttt{skript} & Die Aufgabe hat ein Prüfskript (\emph{QuestScript});
	was es prüft, steht nicht in der Welt. \\
\end{tabular}

So kann ein Arbeitsblatt bei einer freien Aufgabe statt eines
Zielbildes einen Hinweis setzen:

\begin{lstlisting}
\ExplSyntaxOn
\str_if_eq:eeTF { \karoljsonzielart{treppen}{2} } { frei }
  { Probiere~aus! } { \karolweltaus[aufgabe=2, zustand=ziel]{treppen} }
\ExplSyntaxOff
\end{lstlisting}

\textbf{Achtung beim Bauen in Karol Online:} Ein neuer Auftrag hat dort
eine \emph{leere} Zielwelt, keine Kopie der Startwelt. Wenn man nur die
Startwelt baut, erhält man einen Aufräumauftrag. Für eine freie Aufgabe
muss im Welteditor \emph{Start in Ziel kopieren} angeklickt werden.

\subsection{Den Quelltext erzeugen}

Oft soll die Datei nur der Ausgangspunkt sein. \verb|\karolquelltext|
setzt den Quelltext, den man sonst abtippen würde,
\verb|\karolquelltextdatei| schreibt ihn in eine Datei:

\begin{lstlisting}
\karolquelltext{treppen}
\karolquelltextdatei[aufgabe=2]{treppen}{treppe-2.tex}
\end{lstlisting}

\karolquelltext{treppen}

\noindent
Mit \key{kompakt} werden gleiche Zellen zu Rechtecken zusammengefasst
(\key{bisx}, \key{bisy}), und eine freie Aufgabe mit nur einer Reihe
erscheint als \verb|\karolzeile|. Ist die Ziel- bzw. die Startwelt
leer, steht \key{auftrag=aufraeumen} bzw. \key{auftrag=aufbauen} im
Kopf, und die Objekte brauchen keine Seitenangaben.

\subsection{Welten exportieren}

Jede Welt mit dem Schlüssel \key{export} wird zu einer Teilaufgabe. Die
Adresse \texttt{sammlung/nummer} sagt, in welche Datei und an welche
Stelle; \verb|\karoljsonschreiben| schreibt die Sammlung:

\begin{lstlisting}
\begin{karolwelt}[breite=5, laenge=3, export=blatt/1,
                  aufgabentitel={Baue die Treppe fertig.}]
  \karol[x=1, y=2, richtung=osten]
  \ziegel[x=2, y=2]
  \ziegel[x=3, y=2, startanzahl=1, zielanzahl=2]
  \ziegel[x=4, y=2, ziel, anzahl=3]
\end{karolwelt}
\karolzeile[export=blatt/2]{> Z 2 Z .}

\karoljsonschreiben[titel={Treppen}, beschreibung={Arbeitsblatt 3}]
  {blatt}{blatt.json}
\end{lstlisting}

\begin{itemize}
\item Eine Welt ohne \key{start}/\key{ziel}-Angaben wird eine freie
	Aufgabe, \key{auftrag=aufraeumen} ein geprüfter Aufräumauftrag. Sind
	Start und Ziel trotz solcher Angaben gleich, gibt es eine Warnung
	-- Karol Online würde nicht prüfen. Eine \verb|\karolzeile| ist immer
	frei.
\item Geschrieben wird am Ende des Dokuments; \verb|\karoljsonschreiben|
	darf also vor den Welten stehen, die Nummern in beliebiger
	Reihenfolge. Lücken sind ein Fehler. Eine geschriebene Datei lässt
	sich erst im nächsten Lauf wieder einlesen.
\item Die Datei muss im Ordner des Dokuments oder in einem
	\emph{vorhandenen} Unterordner liegen: \TeX{} schreibt nicht nach
	\texttt{../} und legt keine Ordner an. Andernfalls meldet das Paket
	einen Fehler und schreibt die Datei nicht; das PDF entsteht trotzdem.
\item Die Datei wird eingerückt geschrieben, ein Wert je Zeile -- gut
	lesbar und für die Versionsverwaltung geeignet. Karol Online liest
	sie wie seine eigenen, einzeiligen Exporte.
\item Fehlt \verb|\karol|, steht Karol auf (1,1) mit Blick nach Süden
	(mit Warnung); \key{exportkarol=\{x=…, y=…, richtung=…\}} setzt ihn
	nur für die Datei, ohne ihn zu zeichnen.
\item \key{erbt=blatt/1} beginnt mit dem Inhalt eines weiter vorn
	belegten Slots, etwa für eine Variante. \key{quelle=blatt/1} geht
	ebenso.
\item \texttt{karolweltpaar} darf \key{export} tragen: beide Hälften
	belegen denselben Slot mit demselben Inhalt.
\item Heißt die Sammlung wie eine eingelesene Datei, bleibt alles
	erhalten, was nicht aus \LaTeX{} kommt -- Programm, Prüfskript,
	Aufträge ohne \key{export}. So lässt sich eine Aufgabe einlesen, in
	\LaTeX{} ändern und zurückschreiben:
\end{itemize}

\begin{lstlisting}
\karoljsonlesen[name=treppen]{treppen.json}
\begin{karolwelt}[quelle=treppen, aufgabe=2, export=treppen/2]
  \ziegel[x=5, y=1]
\end{karolwelt}
\karoljsonschreiben{treppen}{treppen-neu.json}
\end{lstlisting}

\noindent
Den Share-Code, den Karol Online nach dem Hochladen vergibt, setzt
\verb|\karolonline| (Abschnitt~\ref{sec:online}).

\subsection{Ein Startprogramm mitgeben}

Eine Aufgabe kann ein Programm mitbringen, das beim Öffnen schon im
Editor steht -- ein Gerüst, eine angefangene Schleife, ein Kommentar
mit dem Auftrag. Es steht in einer eigenen Textdatei, geschrieben in
der Textsprache von Robot Karol, und \key{programm} nennt sie:

\begin{lstlisting}
\karoljsonschreiben[titel={Treppen}, programm=treppe-start.karol]
  {blatt}{blatt.json}
\end{lstlisting}

\noindent
mit \texttt{treppe-start.karol} etwa

\begin{lstlisting}[language={}]
// Baue die Treppe fertig.
wiederhole 3 mal
  Hinlegen
endewiederhole
\end{lstlisting}

\noindent
Die Datei wird bei jedem Lauf gelesen und wie die Welten gesucht.
\key{sprache} wählt den Editor: \key{blocks} (Vorgabe) öffnet die
Aufgabe im Blockeditor, der den Text selbst in Blöcke umsetzt,
\key{karol} im Texteditor. Ob das Programm übersetzbar ist, prüft das
Paket nicht -- Karol Online meldet einen Fehler erst beim Öffnen. Ohne
\key{programm} wird ein durchgereichtes Programm einer eingelesenen
Datei beibehalten. Alles in der Datei ist öffentlich lesbar; die Lösung
gehört nicht hinein.

\subsection{Was nicht übertragen wird}

\begin{tabular}{@{}>{\raggedright}p{0.3\linewidth}
                >{\raggedright\arraybackslash}p{0.64\linewidth}@{}}
\verb|\marke[farbe=…]| & Marken haben in Karol Online keine Farbe; sie
	geht beim Export verloren. \\
Darstellung & \key{ansicht}, \key{zustand}, \key{skalierung},
	\key{nummern}, \key{rahmen}, \key{hervorheben}, \key{titel},
	\key{hinweis} und die Figur gibt es nur in \LaTeX. \\
Quader im Ziel & \pkg{robotkarol} kennt für Quader keinen Zielzustand
	und zeigt die der Startwelt (Warnung). Eine Datei mit verschiedenen
	Quadern in Start und Ziel ist in Karol Online ohnehin unlösbar. \\
Karol im Ziel & wird nicht gezeichnet, beim Zurückschreiben einer
	unveränderten Teilaufgabe aber erhalten. \\
\glqq Nichts ändern\grqq{} prüfen & lässt sich nicht ausdrücken: gleiche
	Start- und Zielwelt heißt in Karol Online \emph{frei}. \\
\end{tabular}

\subsection{Große Welten}

Karol Online erlaubt bis zu $100\times100$ Felder und Stapel bis~10;
\pkg{robotkarol} liest jede solche Datei. Eine dicht gefüllte Welt
dieser Größe braucht aber Zeit: gemessen etwa eine halbe Minute in
\key{ansicht=2d} und gut sieben Minuten im Schrägbild. Ab rund tausend
belegten Feldern im Schrägbild warnt das Paket mit einer Zeitschätzung.

\section{Hinweise und Migration}

\begin{itemize}
\item Das Paket benötigt \textbf{LuaLaTeX}.
\item Neu in v4.0 ist die JSON-Schnittstelle zu Robot Karol Online
	(Abschnitt~\ref{sec:json}). Dazu gehört die Datei
	\texttt{robotkarol.lua}; sie muss neben \texttt{robotkarol.sty}
	liegen, sonst lässt sich das Paket nicht laden. Bestehende
	Dokumente setzen unverändert.
\item Bis v2.x hieß das Zeichenketten-Kommando
	\texttt{\textbackslash karolwelt}; ab v3.0 heißt es
	\texttt{\textbackslash karolzeile}, der Name \texttt{karolwelt}
	bezeichnet die neue Umgebung. Bestehende Dokumente: einfaches
	Suchen/Ersetzen.
\item Die kurzen Objektnamen \verb|\karol|, \verb|\ziegel|,
	\verb|\marke|, \verb|\quader| und \verb|\wand| sind nur
	\emph{innerhalb} der Umgebung \texttt{karolwelt} belegt. Ein
	Dokument darf sie also selbst verwenden -- außerhalb der Umgebung
	behalten sie ihre eigene Bedeutung.
\item In v3.10 hat sich dreierlei geändert, ohne Rücksicht auf ältere
	Dokumente. Der Schlüssel \key{aufraeumen} heißt jetzt
	\key{auftrag=aufraeumen}, neu dazu kam \key{auftrag=aufbauen}. Die
	Feldnummern von \verb|\karolzeile| zählen ab 1 statt ab 0 --
	wie die Koordinaten der Umgebung. Damit gilt auch
	\key{hervorheben} ab 1: aus \verb|hervorheben={2,4}| wird
	\verb|hervorheben={3,5}|. Und \texttt{karolwelt} beginnt keinen
	neuen Absatz mehr: zwei Welten mit \verb|\qquad| dazwischen stehen
	jetzt nebeneinander statt untereinander. Wer sie untereinander
	will, trennt sie durch eine Leerzeile.
\item Vorgegeben ist die Figur \key{karol}. In v3.5 war für kurze Zeit
	\key{emma} die Vorgabe; wer sie behalten will, schreibt in die
	Präambel ein \verb|\karolfigur{emma}|.
\item Neu in v3.7 ist außerdem \verb|\karolonline| für Verweise auf
	Aufgaben der Online-Umgebung (Abschnitt~\ref{sec:online}).
	\textbf{Dafür lädt das Paket jetzt \pkg{hyperref}} -- wer das nicht
	will, lädt es mit \key{hyperref=false}
	(Abschnitt~\ref{sec:hyperref}).
\item Neu in v3.7 ist der Druckmodus
	(\verb|\usepackage[druck]{robotkarol}|,
	Abschnitt~\ref{sec:druck}). Ohne ihn ist die Ausgabe dieselbe wie
	in v3.6 -- mit einer Ausnahme: die \emph{Marke} sitzt jetzt in
	beiden Modi mittig auf ihrem Feld. Bis v3.6 fehlte in ihren
	Bildkoordinaten der Tiefenanteil, sie saß rund 0,3\,mm zu weit
	links und berührte auf einem Ziegel dessen linke Kante.
\item Seit v3.6 setzt das Paket seine Beschriftungen in den Schriften
	von Robot Karol Online und lädt dafür \pkg{fontspec}. Wer die
	bisherige Ausgabe will, lädt es mit der Paketoption
	\key{schrift=dokument} -- siehe Abschnitt~\ref{sec:schriften}.
\end{itemize}

\section*{Lizenz}

\pkg{robotkarol} steht unter der \LaTeX{} Project Public License,
Version 1.3c oder später (\url{https://www.latex-project.org/lppl.txt}),
mit dem Wartungsstatus \emph{maintained}. Copyright \copyright{} 2026
Anselm Wagner.

Farben und Proportionen sind aus der Oberfläche von \emph{Robot Karol
Online} gemessen und mit \pkg{TikZ} nachgebaut; es wurden keine Grafiken
übernommen.

\end{document}
