\begin{matlab}
% Simulationsumgebung für den Wabenbau sozialer Insekten
global DX;
global DY;
global Wabengitter;
global Knotenzahl;
global zeit;
global Grenzen;
global MittelPunkte;
global MittelWabe;
global raumplot;
global bebautezellen;
global wespenanzahl;
global numberofruns;
global numberofgaruns;
global gadurchlauf;
global animation;
global ring;

% Parameter der Simulation
DX = 41; % Breite des Gitters
DY = 41; % Höhe des Gitters
wespenanzahl = uint8(1); % Zahl der aktiven Agenten pro einzelner Wabe
MaxSteps = uint16(200); % Zahl der Schritte pro Simulationslauf
MaxSteps2 = uint16(400); % Zahl der Schritte für zweite Hierarchie
numberofruns = uint8(200); % Größe der GA-Population
numberofgaruns = uint8(50); % Zahl der Durchläufe des GA
rulesetanzahl = uint8(1); % Zahl der unterschiedlichen Regelsätze
animation = true; % Parameter, um einzustellen, ob der Bauvorgang auch graphisch angezeigt wird

% Die äußerste Schleife wird pro hierarchischem Regelsatz einmal durchlaufen
for ring=uint8(1):rulesetanzahl

% Diese Schleife wird für jeden Durchlauf des GA einmal durchlaufen
 for gadurchlauf=uint8(1):numberofgaruns
  close all; % schließt alle vorherigen Fenster

  for run=uint8(1):numberofruns
   Wabengitter = hextop(DX,DY); 
% Erzeugen des hexagonalen Gitters
% Struktur der Matrix:
% Zeile 1: X-Koordinate des Knotenpunkts
% Zeile 2: Y-Koordinate des Knotenpunkts
% Zeile 3: Markierung, ob Knotenpunkt Wabenmittelpunkt ist (1/0)
% Zeile 4: Belegung des Feldes (0 = leer, 1 = Baustein Typ 1, ...)

Knotenzahl = size(Wabengitter,2);

% Algorithmus zur Markierung der Wabenmittelpunkte
% - legt eine dritte Zeile in der Matrix Wabengitter an und markiert jeden
% Knotenpunkt, der einem Wabenmittelpunkt entspricht, mit einer 1
Position = DX + 2; % Initialisierung - erster Wabenmittelpunkt
for Position=DX+2:3:2*DX-1
% die zweite Reihe vom zweiten bis zum vorletzten Element
% mit horizontalem Abstand 3
Position2 = Position;
while Position2 < (Knotenzahl - DX) % oberste Zeile ausschließen
Wabengitter(3,Position2) = 1; % Setze Markierung für Mittelpunkt
Position2 = Position2 + 2 * DX;
end
Position2 = Position + DX + 2;
if (mod(Position2,DX) > 1) && (mod(Position2,DX) < DX)
while Position2 < Knotenzahl - DX
Wabengitter(3,Position2) = 1;
Position2 = Position2 + 2*DX;
end
end
end

MittelPunkte = find(Wabengitter(3,:));
% erzeugt einen Vektor mit Indizes der Wabenmittelpunkte
Grenzen = max(Wabengitter,[],2);
% ereugt einen Vektor, der die Endkoordinaten des Gitters enthält
MittelWabe = MittelPunkte(ceil(length(MittelPunkte) / 2));
% Index der annähernd mittleren Wabe (Ausgangspunkt für die Simulation)
mittelnachbarn = nachbarn(MittelWabe);
Wabengitter(4,MittelWabe) = 1; % Baustein vom Typ 1 an Mittelpunkt gesetzt
% Wird als Anfangspunkt benötigt
for nachbarindex=1:6
Wabengitter(4,mittelnachbarn(nachbarindex)) = 1;
end 
% die sechs direkten Nachbarn des Mittelpunkts werden als bebaut markiert

if (gadurchlauf == numberofgaruns) 
 % nur beim letzten Durchlauf grafisch anzeigen
 scrsz = get(0,'ScreenSize');
 % erzeuge figure für die graphische Anzeige
 visual = figure('Name', ...
['GA ' num2str(gadurchlauf) ' RS ' num2str(run)], ...
'Position',[1 scrsz(4) scrsz(3) scrsz(4)], ...
'NumberTitle','off');
raumplot = gca;
% verhindern, dass gezeichnetes wieder gelöscht wird:
hold on; 

% Betrachtungswinkel einstellen
view(3); 
axis(raumplot,'manual');
set(raumplot, 'DataAspectRatio', [1 1 1] ); % , ...
axis(raumplot,[-2 (Grenzen(1)+2) -2 (Grenzen(2)+2)]);
camlight('right');
camproj('perspective');
lighting gouraud;

% leeres Gitter anzeigen
plotgitter(Wabengitter, raumplot);
plotwabe(MittelWabe, raumplot, 8); % die Anfangswabe wird markiert
for nachbarindex=1:6
 plotwabe(mittelnachbarn(nachbarindex), raumplot, 8);
 end % die sechs unmittelbaren Nachbarzellen der Mittelwabe werden auch gesetzt
 % verhindert die Notwendigkeit einer Einserregel
end

if (ring == 1) % nur für den ersten Regelsatz

if (gadurchlauf == 1) % Nur im ersten Durchlauf des GA...
% ...wird die durch \texttt{wespenanzahl} festgelegte Menge von Objekten der
% Klasse \texttt{agent} angelegt. 
 for nummer=uint8(1):wespenanzahl
  wespe(run,nummer) = ...
   bauagent(Wabengitter(1:2, MittelWabe)',nummer);
% erzeugt ein Objekt der Klasse Bauagent auf den Koordinaten
% der mittleren Wabe
end
global wespe; % 'workaround', um das Array, das die Agenten beinhaltet,
% nachträglich als \texttt{global} zu definieren. Gilt als \texttt{deprecated},
% funktioniert aber in der verwendeten Version von MATLAB.
% Eine Vorabdeklaration als \texttt{global} funktioniert nicht, weil das Array
% dann automatisch als numerisch deklariert wird.
else
% dieser else-block wird nur in späteren Durchläufen des GA erreicht.
% \texttt{wespe} ist dann schon als global deklariert und kann benutzt werden.
 for nummer=uint8(1):wespenanzahl
 wespe(run,nummer).BuildCounter = 0;
 wespe(run,nummer).Position = Wabengitter(1:2, MittelWabe)';
end
end
else
% für den zweiten Durchlauf in der Hierarchie mit zwei
% hintereinander zu benutzenden Regelsätzen
for nummer=uint8(1):wespenanzahl
 wespe(run,nummer).classifierset = ...
  bestclassifierset1;
 wespe(run,nummer).numberofclassifiers = ...
  length(wespe(run,nummer).classifierset);
 wespe(run,nummer).classifierfitnessstring = ...
  strcat(wespe(run,nummer).classifierset.fitnessstring);
 wespe(run,nummer).BuildCounter = 0;
 wespe(run,nummer).Position = Wabengitter(1:2, MittelWabe)';
end
end



 % Simulationsstart
 %
 % Update der Liste der Indizes aller bebauten Zellen
 bebautezellen = find(Wabengitter(4,:));
 grafik = gcf;

 % Simulationsschleife zur äußeren Steuerung der Simulation
 % - hier werden die Agenten aktivert und bewegt
 for zeit=uint16(1):MaxSteps
  for wespennummer=uint8(1):wespenanzahl
   wespe(run,wespennummer).movebuild();
  end
 end

 % Zweiter hierarchischer Regelsatz
 if ( ring == 2 )
  for wespennummer=uint8(1):wespenanzahl
wespe(run,wespennummer) ...
 .updateclassifierset(wespe(run,wespennummer).RuleSet2);
   % Zweites regelwerk wird hier aktiviert
  end
  % zweite Zeitschleife für zweite Hierarchieebene
  for zeit=MaxSteps+1:MaxSteps2 
   for wespennummer=uint8(1):wespenanzahl
    wespe(run,wespennummer).movebuild();
   end
  end
 end

 % Berechnung des globalen Fitnesswerts der gebauten Wabe
[fitnesswert,idealwert,aussenlaenge,wabenanzahl,quotient] ...
 = fitness(Wabengitter);

 % Legt einen Vektor overallfitness an, in dem für den Phänotyp
 % jedes Regelsatzes seine Overall-Fitness abgespeichert wird.
 % Dient als Basis für den GA.
 overallfitness(run) = quotient;
end

strengthga(overallfitness); 
% Aufruf des GA zur Erzeugung neuer Regelsätze mit anderen Fitnesswerten

numberofruns = size(wespe,1);
% Update der Anzahl der Durchläufe
% - wenn neue Individuen (Regelsätze) dazukommen,
%   müssen diese auch berücksichtigt werden

[maxwert, maxindex] = max(overallfitness);
[minwert, minindex] = min(overallfitness);
% ermittelt den Regelsatz mit bester bzw. niedrigster Fitness

maxvektor(gadurchlauf,1) = maxwert;
maxvektor(gadurchlauf,2) = maxindex;
maxvektor(gadurchlauf,3) = minwert;
maxvektor(gadurchlauf,4) = minindex;
maxvektor(gadurchlauf,5) = mean(overallfitness);
end

if (ring == 1)

 bestclassifierset1 = ...
  wespe(uint16(maxvektor(gadurchlauf,2))).classifierset;
 % besten Regelsatz zur Wiederverwendung kopieren

 bestwespe1 = wespe(uint16(maxvektor(gadurchlauf,2)));
 bestwespe1.BuildCounter = 0;
 bestwespe1.Position = Wabengitter(1:2, MittelWabe)';
end
end
\end{matlab}
