// ===================================================================
// Author: Frank Stroebel
// WWW: http://www.chessgamble.de/
// ===================================================================

//
// Basisklasse für die Partieanalyse.
// Diese wird von "PartieUI.js" verwendet um das ziehen der Figuren zu berechnen.
// Wir verwenden hier wiederum functions aus "PartieAnzeige.js".
//
function PartieAnalyse()
{
}

//
// Initialisierung der Partieanalyse.
//
PartieAnalyse.prototype.Init = function()
{
}

//
// Wird von PartieAnzeige.js aufgerufen, wenn ein Zug angewählt wurde (vergangene Stellung).
// Spezielle Klassen können hier was bestimmtes machen.
// Z.B. werden bei Dark Chess die Restfiguren geschrieben
//
PartieAnalyse.prototype.ZugAngewaehlt = function(zugButtonId)
{
}

//
// Bereinigung der Zugliste.
//
// Parameter: Siehe PartieUI.js ganz oben.
// eigenFarbe = "w" oder "s".
//
PartieAnalyse.prototype.BereinigeZugmoeglichkeiten = function(feldNamenMitEigenenFiguren, zielFeldNamenDerEigenenFiguren, eigenFarbe)
{
  return zielFeldNamenDerEigenenFiguren;
}

//
// Gibt die Feldnamen zurück, auf denen eigene Figuren stehen.
// Ob sie ziehen dürfen, wird zunächst nicht berücksichtigt.
//
// Dazu nutzen wir functions aus "PartieAnzeige.js". Deswegen müssen vor Aufruf dieser Function
// folgende Methoden aufgerufen worden sein:
// - ErstelleAnalyseBrettAusFEN();
//
// Params:
// - amZugFarbe (= "W" oder "S")
//   Gibt an, welches die eigenen Figuren sind.
//
// Result:
// Ret[0] = "d3"
// Ret[1] = "f5"
// ...
//
PartieAnalyse.prototype.GetFeldNamenMitEigenenZiehbarenFiguren = function(amZugFarbe)
{
  var result = new Array();

  amZugFarbe = amZugFarbe.toLowerCase();
  for (var i = 0; i < 8; ++i) {
    for (var j = 0; j < 8; ++j) {
      var figur = brett[i][j];
      if ((figur != "") && (figur.substr(1, 1) == amZugFarbe)) {
        // Da steht eine eigene
        var feldName = this.GetFeldNameFromInizes(i, j);
        result.push(feldName);
      }
    }
  }
  
  return result;
}

//
// Ermittelt aus der eigenen Figur "PartieUI.js::feldNamenMitEigenenFiguren[figurIndex]"
// alle Zielfelder der Figur und schreibt diese in das array "PartieUI.js::zielFeldNamenDerEigenenFiguren[figurIndex]".
//
PartieAnalyse.prototype.ErmittleAlleZielFelderDerFigur = function(figurIndex)
{
  var eigeneFigurFeldName = feldNamenMitEigenenFiguren[figurIndex];
  // eigeneFigurFeldName ist jetzt "d4"
  var zielFelder = this.GetZielFeldNamenDerFigur(eigeneFigurFeldName);
  zielFeldNamenDerEigenenFiguren.push(zielFelder);
}

//
// Gibt die Feldnamen zurück, auf die die Figur ziehen darf.
//
// Params:
// - startFeldName:
//   Name des Feldes auf dem die Figur steht (z.B. "d4")
//
// Result:
// Ret[0] = "d3"
// Ret[1] = "f5"
// ...
//
PartieAnalyse.prototype.GetZielFeldNamenDerFigur = function(startFeldName)
{
  var result = new Array();
  
  var ziehendeFigur = this.GetFigur(startFeldName);
  // ziehendeFigur enthält jetzt "bw", "tw", ...
  if (ziehendeFigur.length > 0) {
    // Andernfalls ist da keine Figur
    var eigenFarbe = ziehendeFigur.substr(1, 1);
    switch (ziehendeFigur.substr(0, 1)) {
      case "b":
        result = this.GetZielFelderBauer(startFeldName, eigenFarbe);
        break;
      case "l":
        result = this.GetZielFelderLaeufer(startFeldName, eigenFarbe);
        break;
      case "s":
        result = this.GetZielFelderSpringer(startFeldName, eigenFarbe);
        break;
      case "t":
        result = this.GetZielFelderTurm(startFeldName, eigenFarbe);
        break;
      case "d":
        result = this.GetZielFelderTurm(startFeldName, eigenFarbe);
        result = result.concat(this.GetZielFelderLaeufer(startFeldName, eigenFarbe));
        break;
      case "k":
        result = this.GetZielFelderKoenig(startFeldName, eigenFarbe);
        break;
      default: break;
    }
  }
  
  // Zum Abschluss müssen wir noch auf "selbst ins Schach gestellt" prüfen
  result = this.CheckSelbstSchach(startFeldName, eigenFarbe, result);
  
  return result;
}

//
// Bereinigt die Liste der möglichen Züge um die, mit denen wir uns selbst ins Schach stellen würden.
//
// Result: Die bereinigte Liste
//
// Params:
// - startFeldName:
//   Name des Feldes auf dem die Figur steht (z.B. "d4")
// - zuegeListe:
//   Liste der Zielfelder, die von GetZielFeldNamenDerFigur() berechnet wurde: ["e3", "e4", ...]
// - eigenFarbe: "w" oder "s"
//
PartieAnalyse.prototype.CheckSelbstSchach = function(startFeldName, eigenFarbe, zuegeListe)
{
  // Vorgehen:
  // Wir müssen jeden Zug auf dem Analyse-Brett ausführen und prüfen ob der K bedroht ist
  var result = new Array();
  
  for (var zugIndex=0; zugIndex<zuegeListe.length; zugIndex++) {
    var zielFeldName = zuegeListe[zugIndex];
    AnalyseZugAusfuehren(startFeldName, zielFeldName);
    var eigenerKoenigFeldName = GetEigenerKoenigFeldName(eigenFarbe);
    if (!this.FeldIsBedroht(eigenerKoenigFeldName, eigenFarbe)) {
      // Der Zug ist OK
      result.push(zielFeldName);
    }
    AnalyseZugZurueckNehmen();
  }
  
  return result;
}

//
// Gibt die möglichen Zielfelder eines Königs zurück.
//
// Params:
// - startFeldName = "d4"
// - eigenFarbe    = "w" oder "s"
//
PartieAnalyse.prototype.GetZielFelderKoenig = function(startFeldName, eigenFarbe)
{
  var result = new Array();
  
  // Aktuelle Inizes des Königs
  var reiheBrettIndex = this.GetBrettIndexReihe(startFeldName);
  var linieBrettIndex = this.GetBrettIndexLinie(startFeldName);
  
  // Prüfe normales ziehen
  var zielFeld;
  var zielFeldStatus;
  
  var i = reiheBrettIndex + 1;
  var j = linieBrettIndex;
  if ((i>=0) && (i<=7) && (j>=0) && (j<=7)) {
    zielFeld = brett[i][j];
    zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if ((zielFeldStatus == "frei") || (zielFeldStatus == "gegner")) {
      // Das Feld kommt dazu
      result.push(this.GetFeldNameFromInizes(i, j));
    }
  }
  
  i = reiheBrettIndex - 1;
  j = linieBrettIndex;
  if ((i>=0) && (i<=7) && (j>=0) && (j<=7)) {
    zielFeld = brett[i][j];
    zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if ((zielFeldStatus == "frei") || (zielFeldStatus == "gegner")) {
      // Das Feld kommt dazu
      result.push(this.GetFeldNameFromInizes(i, j));
    }
  }
  
  i = reiheBrettIndex;
  j = linieBrettIndex + 1;
  if ((i>=0) && (i<=7) && (j>=0) && (j<=7)) {
    zielFeld = brett[i][j];
    zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if ((zielFeldStatus == "frei") || (zielFeldStatus == "gegner")) {
      // Das Feld kommt dazu
      result.push(this.GetFeldNameFromInizes(i, j));
    }
  }
  
  i = reiheBrettIndex;
  j = linieBrettIndex - 1;
  if ((i>=0) && (i<=7) && (j>=0) && (j<=7)) {
    zielFeld = brett[i][j];
    zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if ((zielFeldStatus == "frei") || (zielFeldStatus == "gegner")) {
      // Das Feld kommt dazu
      result.push(this.GetFeldNameFromInizes(i, j));
    }
  }
  
  i = reiheBrettIndex + 1;
  j = linieBrettIndex + 1;
  if ((i>=0) && (i<=7) && (j>=0) && (j<=7)) {
    zielFeld = brett[i][j];
    zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if ((zielFeldStatus == "frei") || (zielFeldStatus == "gegner")) {
      // Das Feld kommt dazu
      result.push(this.GetFeldNameFromInizes(i, j));
    }
  }
  
  i = reiheBrettIndex + 1;
  j = linieBrettIndex - 1;
  if ((i>=0) && (i<=7) && (j>=0) && (j<=7)) {
    zielFeld = brett[i][j];
    zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if ((zielFeldStatus == "frei") || (zielFeldStatus == "gegner")) {
      // Das Feld kommt dazu
      result.push(this.GetFeldNameFromInizes(i, j));
    }
  }
  
  i = reiheBrettIndex - 1;
  j = linieBrettIndex + 1;
  if ((i>=0) && (i<=7) && (j>=0) && (j<=7)) {
    zielFeld = brett[i][j];
    zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if ((zielFeldStatus == "frei") || (zielFeldStatus == "gegner")) {
      // Das Feld kommt dazu
      result.push(this.GetFeldNameFromInizes(i, j));
    }
  }
  
  i = reiheBrettIndex - 1;
  j = linieBrettIndex - 1;
  if ((i>=0) && (i<=7) && (j>=0) && (j<=7)) {
    zielFeld = brett[i][j];
    zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if ((zielFeldStatus == "frei") || (zielFeldStatus == "gegner")) {
      // Das Feld kommt dazu
      result.push(this.GetFeldNameFromInizes(i, j));
    }
  }
  
  //
  // Jetzt noch Rochade prüfen
  //
  if (eigenFarbe == "w") {
    // Rochade von W
    if (rochadeWKurzMoeglich) {
      // Kurze W prüfen
      if ((this.GetFigur("f1") == "") &&
          (this.GetFigur("g1") == "") &&
          (this.GetFigur("h1") == "tw")) {
        // Felder dazwischen sind frei
        if (!this.FeldIsBedroht("e1", eigenFarbe) &&
            !this.FeldIsBedroht("f1", eigenFarbe) &&
            !this.FeldIsBedroht("g1", eigenFarbe)) {
          // König steht nicht im Schach, Zielfeld und die dazwischen sind nicht bedroht: Rochade geht
          result.push("g1");
        }
      }
    }
    if (rochadeWLangMoeglich) {
      // Lange W prüfen
      if ((this.GetFigur("d1") == "") &&
          (this.GetFigur("c1") == "") &&
          (this.GetFigur("b1") == "") &&
          (this.GetFigur("a1") == "tw")) {
        // Felder dazwischen sind frei
        if (!this.FeldIsBedroht("e1", eigenFarbe) &&
            !this.FeldIsBedroht("d1", eigenFarbe) &&
            !this.FeldIsBedroht("c1", eigenFarbe)) {
          // König steht nicht im Schach, Zielfeld und die dazwischen sind nicht bedroht: Rochade geht
          result.push("c1");
        }
      }
    }
  }
  else {
    // Rochade von S
    if (rochadeSKurzMoeglich) {
      // Kurze S prüfen
      if ((this.GetFigur("f8") == "") &&
          (this.GetFigur("g8") == "") &&
          (this.GetFigur("h8") == "ts")) {
        // Felder dazwischen sind frei
        if (!this.FeldIsBedroht("e8", eigenFarbe) &&
            !this.FeldIsBedroht("f8", eigenFarbe) &&
            !this.FeldIsBedroht("g8", eigenFarbe)) {
          // König steht nicht im Schach, Zielfeld und die dazwischen sind nicht bedroht: Rochade geht
          result.push("g8");
        }
      }
    }
    if (rochadeSLangMoeglich) {
      // Lange S prüfen
      if ((this.GetFigur("d8") == "") &&
          (this.GetFigur("c8") == "") &&
          (this.GetFigur("b8") == "") &&
          (this.GetFigur("a8") == "ts")) {
        // Felder dazwischen sind frei
        if (!this.FeldIsBedroht("e8", eigenFarbe) &&
            !this.FeldIsBedroht("d8", eigenFarbe) &&
            !this.FeldIsBedroht("c8", eigenFarbe)) {
          // König steht nicht im Schach, Zielfeld und die dazwischen sind nicht bedroht: Rochade geht
          result.push("c8");
        }
      }
    }
  }
  
  return result;
}

//
// Gibt die möglichen Zielfelder eines Bauern zurück.
//
// Params:
// - startFeldName = "d4"
// - eigenFarbe    = "w" oder "s"
//
PartieAnalyse.prototype.GetZielFelderBauer = function(startFeldName, eigenFarbe)
{
  var result = new Array();
  
  // Aktuelle Inizes des Bauers
  var reiheBrettIndex = this.GetBrettIndexReihe(startFeldName);
  var linieBrettIndex = this.GetBrettIndexLinie(startFeldName);
  
  // Prüfe normales ziehen
  var i, j;
  if (eigenFarbe == "w") {
    i = reiheBrettIndex + 1;
    j = linieBrettIndex;
  }
  else {
    i = reiheBrettIndex - 1;
    j = linieBrettIndex;
  }
  var zielFeld = brett[i][j];
  var zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
  if (zielFeldStatus == "frei") {
    // Das Feld kommt dazu
    result.push(this.GetFeldNameFromInizes(i, j));
    
    // Prüfe jetzt noch auf Doppelschritt
    var pruefeWeiter = false;
    if (eigenFarbe == "w") {
      if (reiheBrettIndex == 1) {
        i = reiheBrettIndex + 2;
        pruefeWeiter = true;
      }
    }
    else {
      if (reiheBrettIndex == 6) {
        i = reiheBrettIndex - 2;
        pruefeWeiter = true;
      }
    }
    if (pruefeWeiter) {
      var zielFeld = brett[i][j];
      var zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
      if (zielFeldStatus == "frei") {
        // Das Feld kommt dazu
        result.push(this.GetFeldNameFromInizes(i, j));
      }
    }
  }
  
  // Prüfe schlagen nach links
  var i, j;
  if (eigenFarbe == "w") {
    i = reiheBrettIndex + 1;
    j = linieBrettIndex + 1;
  }
  else {
    i = reiheBrettIndex - 1;
    j = linieBrettIndex + 1;
  }
  if ((i>=0) && (i<=7) && (j>=0) && (j<=7)) {
    var zielFeld = brett[i][j];
    var zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if (zielFeldStatus == "gegner") {
      // Normales Schlagen: Das Feld kommt dazu
      result.push(this.GetFeldNameFromInizes(i, j));
    }
    else if ((bauerDoppelschritt != "") &&
             (zielFeldStatus == "frei") &&
             (j == this.GetBrettIndexLinie(bauerDoppelschritt)) &&
             this.IsNachbarFeld(startFeldName, bauerDoppelschritt)) {
      // E.P. möglich: Das Feld kommt dazu
      result.push(this.GetFeldNameFromInizes(i, j));
    }
    else {
      // Kein weiterer Sonderfall
    }
  }
  
  // Prüfe schlagen nach rechts
  if (eigenFarbe == "w") {
    i = reiheBrettIndex + 1;
    j = linieBrettIndex - 1;
  }
  else {
    i = reiheBrettIndex - 1;
    j = linieBrettIndex - 1;
  }
  if ((i>=0) && (i<=7) && (j>=0) && (j<=7)) {
    var zielFeld = brett[i][j];
    var zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if (zielFeldStatus == "gegner") {
      // Normales Schlagen: Das Feld kommt dazu
      result.push(this.GetFeldNameFromInizes(i, j));
    }
    else if ((bauerDoppelschritt != "") &&
             (zielFeldStatus == "frei") &&
             (j == this.GetBrettIndexLinie(bauerDoppelschritt)) &&
             this.IsNachbarFeld(startFeldName, bauerDoppelschritt)) {
      // E.P. möglich: Das Feld kommt dazu
      result.push(this.GetFeldNameFromInizes(i, j));
    }
    else {
      // Kein weiterer Sonderfall
    }
  }
  
  return result;
}

//
// True, falls die Felder seitlich nebeneinander liegen (z.B. "e5" und "f5")
//
// Params:
// - feld1 = "d4"
// - feld2 = "e4" oder ""
//
PartieAnalyse.prototype.IsNachbarFeld = function(feld1, feld2)
{
  var result = false;
  
  if ((feld1.length == 2) && (feld2.length == 2)) {
    if (this.GetBrettIndexReihe(feld1) == this.GetBrettIndexReihe(feld2)) {
      // Selbe Reihe
      var linienDiff = this.GetBrettIndexLinie(feld1) - this.GetBrettIndexLinie(feld2);
      if (Math.abs(linienDiff) == 1) {
        // Linien differieren um 1
        result = true;
      }
    }
  }
  
  return result;
}

//
// Gibt die möglichen Zielfelder eines Turms zurück.
//
// Params:
// - startFeldName = "d4"
// - eigenFarbe    = "w" oder "s"
//
PartieAnalyse.prototype.GetZielFelderTurm = function(startFeldName, eigenFarbe)
{
  var result = new Array();
  
  // Aktuelle Inizes des Turms
  var reiheBrettIndex = this.GetBrettIndexReihe(startFeldName);
  var linieBrettIndex = this.GetBrettIndexLinie(startFeldName);
  
  // Prüfe alle Felder nach oben
  for (var i=reiheBrettIndex+1; i<=7; i++) {
    var zielFeld = brett[i][linieBrettIndex];
    var zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if (zielFeldStatus == "eigen") {
      // Eigene Figur: Geht nicht und Abbruch
      break;
    }
    else {
      // Das Feld kommt dazu
      result.push(this.GetFeldNameFromInizes(i, linieBrettIndex));
      if (zielFeldStatus == "gegner") {
        // Aber es ist eine gegnerische Figur, also nicht weiter
        break;
      }
    }
  }
  
  // Prüfe alle Felder nach unten
  for (var i=reiheBrettIndex-1; i>=0; i--) {
    var zielFeld = brett[i][linieBrettIndex];
    var zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if (zielFeldStatus == "eigen") {
      // Eigene Figur: Geht nicht und Abbruch
      break;
    }
    else {
      // Das Feld kommt dazu
      result.push(this.GetFeldNameFromInizes(i, linieBrettIndex));
      if (zielFeldStatus == "gegner") {
        // Aber es ist eine gegnerische Figur, also nicht weiter
        break;
      }
    }
  }
  
  // Prüfe alle Felder nach rechts
  for (var i=linieBrettIndex+1; i<=7; i++) {
    var zielFeld = brett[reiheBrettIndex][i];
    var zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if (zielFeldStatus == "eigen") {
      // Eigene Figur: Geht nicht und Abbruch
      break;
    }
    else {
      // Das Feld kommt dazu
      result.push(this.GetFeldNameFromInizes(reiheBrettIndex, i));
      if (zielFeldStatus == "gegner") {
        // Aber es ist eine gegnerische Figur, also nicht weiter
        break;
      }
    }
  }
  
  // Prüfe alle Felder nach rechts
  for (var i=linieBrettIndex-1; i>=0; i--) {
    var zielFeld = brett[reiheBrettIndex][i];
    var zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if (zielFeldStatus == "eigen") {
      // Eigene Figur: Geht nicht und Abbruch
      break;
    }
    else {
      // Das Feld kommt dazu
      result.push(this.GetFeldNameFromInizes(reiheBrettIndex, i));
      if (zielFeldStatus == "gegner") {
        // Aber es ist eine gegnerische Figur, also nicht weiter
        break;
      }
    }
  }
  
  return result;
}

//
// Gibt die möglichen Zielfelder eines Läufers zurück.
//
// Params:
// - startFeldName = "d4"
// - eigenFarbe    = "w" oder "s"
//
PartieAnalyse.prototype.GetZielFelderLaeufer = function(startFeldName, eigenFarbe)
{
  var result = new Array();
  
  // Aktuelle Inizes des Läufers
  var reiheBrettIndex = this.GetBrettIndexReihe(startFeldName);
  var linieBrettIndex = this.GetBrettIndexLinie(startFeldName);
  
  // Prüfe alle Felder nach rechts oben
  var i = reiheBrettIndex;
  var j = linieBrettIndex;
  i++;
  j++;
  while ((i<8) && (j<8)) {
    var zielFeld = brett[i][j];
    var zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if (zielFeldStatus == "eigen") {
      // Eigene Figur: Geht nicht und Abbruch
      break;
    }
    else {
      // Das Feld kommt dazu
      result.push(this.GetFeldNameFromInizes(i, j));
      if (zielFeldStatus == "gegner") {
        // Aber es ist eine gegnerische Figur, also nicht weiter
        break;
      }
    }
    i++;
    j++;
  }
  
  // Prüfe alle Felder nach rechts unten
  i = reiheBrettIndex;
  j = linieBrettIndex;
  i--;
  j++;
  while ((i>=0) && (j<8)) {
    var zielFeld = brett[i][j];
    var zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if (zielFeldStatus == "eigen") {
      // Eigene Figur: Geht nicht und Abbruch
      break;
    }
    else {
      // Das Feld kommt dazu
      result.push(this.GetFeldNameFromInizes(i, j));
      if (zielFeldStatus == "gegner") {
        // Aber es ist eine gegnerische Figur, also nicht weiter
        break;
      }
    }
    i--;
    j++;
  }
  
  // Prüfe alle Felder nach links oben
  i = reiheBrettIndex;
  j = linieBrettIndex;
  i++;
  j--;
  while ((i<=7) && (j>=0)) {
    var zielFeld = brett[i][j];
    var zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if (zielFeldStatus == "eigen") {
      // Eigene Figur: Geht nicht und Abbruch
      break;
    }
    else {
      // Das Feld kommt dazu
      result.push(this.GetFeldNameFromInizes(i, j));
      if (zielFeldStatus == "gegner") {
        // Aber es ist eine gegnerische Figur, also nicht weiter
        break;
      }
    }
    i++;
    j--;
  }
  
  // Prüfe alle Felder nach links unten
  i = reiheBrettIndex;
  j = linieBrettIndex;
  i--;
  j--;
  while ((i>=0) && (j>=0)) {
    var zielFeld = brett[i][j];
    var zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if (zielFeldStatus == "eigen") {
      // Eigene Figur: Geht nicht und Abbruch
      break;
    }
    else {
      // Das Feld kommt dazu
      result.push(this.GetFeldNameFromInizes(i, j));
      if (zielFeldStatus == "gegner") {
        // Aber es ist eine gegnerische Figur, also nicht weiter
        break;
      }
    }
    i--;
    j--;
  }
  
  return result;
}

//
// Gibt die möglichen Zielfelder eines Springers zurück.
//
// Params:
// - startFeldName = "d4"
// - eigenFarbe    = "w" oder "s"
//
PartieAnalyse.prototype.GetZielFelderSpringer = function(startFeldName, eigenFarbe)
{
  var result = new Array();
  
  // Aktuelle Inizes des Springers
  var reiheBrettIndex = this.GetBrettIndexReihe(startFeldName);
  var linieBrettIndex = this.GetBrettIndexLinie(startFeldName);
  
  // Prüfe das ganze Springer-Rad
  var i = reiheBrettIndex + 2;
  var j = linieBrettIndex + 1;
  if ((i>=0) && (i<=7) && (j>=0) && (j<=7)) {
    var zielFeld = brett[i][j];
    var zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if ((zielFeldStatus == "frei") || (zielFeldStatus == "gegner")) {
      // Das Feld kommt dazu
      result.push(this.GetFeldNameFromInizes(i, j));
    }
  }

  i = reiheBrettIndex + 2;
  j = linieBrettIndex - 1;
  if ((i>=0) && (i<=7) && (j>=0) && (j<=7)) {
    zielFeld = brett[i][j];
    zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if ((zielFeldStatus == "frei") || (zielFeldStatus == "gegner")) {
      // Das Feld kommt dazu
      result.push(this.GetFeldNameFromInizes(i, j));
    }
  }

  i = reiheBrettIndex + 1;
  j = linieBrettIndex + 2;
  if ((i>=0) && (i<=7) && (j>=0) && (j<=7)) {
    zielFeld = brett[i][j];
    zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if ((zielFeldStatus == "frei") || (zielFeldStatus == "gegner")) {
      // Das Feld kommt dazu
      result.push(this.GetFeldNameFromInizes(i, j));
    }
  }

  i = reiheBrettIndex - 1;
  j = linieBrettIndex + 2;
  if ((i>=0) && (i<=7) && (j>=0) && (j<=7)) {
    zielFeld = brett[i][j];
    zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if ((zielFeldStatus == "frei") || (zielFeldStatus == "gegner")) {
      // Das Feld kommt dazu
      result.push(this.GetFeldNameFromInizes(i, j));
    }
  }

  i = reiheBrettIndex - 2;
  j = linieBrettIndex + 1;
  if ((i>=0) && (i<=7) && (j>=0) && (j<=7)) {
    zielFeld = brett[i][j];
    zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if ((zielFeldStatus == "frei") || (zielFeldStatus == "gegner")) {
      // Das Feld kommt dazu
      result.push(this.GetFeldNameFromInizes(i, j));
    }
  }

  i = reiheBrettIndex - 2;
  j = linieBrettIndex - 1;
  if ((i>=0) && (i<=7) && (j>=0) && (j<=7)) {
    zielFeld = brett[i][j];
    zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if ((zielFeldStatus == "frei") || (zielFeldStatus == "gegner")) {
      // Das Feld kommt dazu
      result.push(this.GetFeldNameFromInizes(i, j));
    }
  }

  i = reiheBrettIndex + 1;
  j = linieBrettIndex - 2;
  if ((i>=0) && (i<=7) && (j>=0) && (j<=7)) {
    zielFeld = brett[i][j];
    zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if ((zielFeldStatus == "frei") || (zielFeldStatus == "gegner")) {
      // Das Feld kommt dazu
      result.push(this.GetFeldNameFromInizes(i, j));
    }
  }

  i = reiheBrettIndex - 1;
  j = linieBrettIndex - 2;
  if ((i>=0) && (i<=7) && (j>=0) && (j<=7)) {
    zielFeld = brett[i][j];
    zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if ((zielFeldStatus == "frei") || (zielFeldStatus == "gegner")) {
      // Das Feld kommt dazu
      result.push(this.GetFeldNameFromInizes(i, j));
    }
  }
  
  return result;
}

//
// Bestimmt den Status des Zielfeldes.
//
// Params:
// - zielFeld   = Das brett an der Stelle: "", "kw", "ts", ...
// - eigenFarbe = "w" oder "s"
//
// Result:
// - "frei"   = Das Feld ist frei
// - "eigen"  = Das Feld ist von einer eigenen Figur belegt
// - "gegner" = Das Feld ist von einer gegnerischen Figur belegt
//
PartieAnalyse.prototype.GetZielFeldStatus = function(zielFeld, eigenFarbe)
{
  var result = "eigen";
  if (zielFeld == "") {
    // Da steht nix, OK
    result = "frei";
  }
  else if (zielFeld.substr(1, 1) != eigenFarbe) {
    // Da steht eine gegnerische Figur
    result = "gegner";
  }
  else {
    // Da steht eine eigene Figur
    result = "eigen";
  }
  return result;
}

//
// True, falls das Feld von einer gegnerischen Figur bedroht ist.
//
// Params:
// - feld       = "e8", das zu prüfende Feld
// - eigenFarbe = "w" oder "s"
//
PartieAnalyse.prototype.FeldIsBedroht = function(feld, eigenFarbe)
{
  // Wir prüfen "rückwärts" alle Felder von uns aus
  
  // Aktuelle Inizes unseres Feldes
  var zielFeld;
  var zielFeldStatus;
  var i, j;
  
  var reiheBrettIndex = this.GetBrettIndexReihe(feld);
  var linieBrettIndex = this.GetBrettIndexLinie(feld);
  
  
  //
  // Die "geraden" prüfen
  //
  
  // Prüfe alle Felder nach oben
  for (i=reiheBrettIndex+1; i<=7; i++) {
    zielFeld = brett[i][linieBrettIndex];
    zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if (zielFeldStatus == "eigen") {
      // Eigene Figur: Keine Gefahr und Abbruch
      break;
    }
    else if (zielFeldStatus == "gegner") {
      // Da steht ein Gegner
      if (((zielFeld.substr(0, 1) == "k") && (i-reiheBrettIndex == 1)) || (zielFeld.substr(0, 1) == "d") || (zielFeld.substr(0, 1) == "t")) {
        // Der bedroht uns, Ende!
        return true;
      }
      // Abbruch, da Angriffslinie besetzt
      break;
    }
  }
  
  // Prüfe alle Felder nach unten
  for (i=reiheBrettIndex-1; i>=0; i--) {
    zielFeld = brett[i][linieBrettIndex];
    zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if (zielFeldStatus == "eigen") {
      // Eigene Figur: Keine Gefahr und Abbruch
      break;
    }
    else if (zielFeldStatus == "gegner") {
      // Da steht ein Gegner
      if (((zielFeld.substr(0, 1) == "k") && (reiheBrettIndex-i == 1)) || (zielFeld.substr(0, 1) == "d") || (zielFeld.substr(0, 1) == "t")) {
        // Der bedroht uns, Ende!
        return true;
      }
      // Abbruch, da Angriffslinie besetzt
      break;
    }
  }
  
  // Prüfe alle Felder nach rechts
  for (j=linieBrettIndex+1; j<=7; j++) {
    zielFeld = brett[reiheBrettIndex][j];
    zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if (zielFeldStatus == "eigen") {
      // Eigene Figur: Keine Gefahr und Abbruch
      break;
    }
    else if (zielFeldStatus == "gegner") {
      // Da steht ein Gegner
      if (((zielFeld.substr(0, 1) == "k") && (j-linieBrettIndex == 1)) || (zielFeld.substr(0, 1) == "d") || (zielFeld.substr(0, 1) == "t")) {
        // Der bedroht uns, Ende!
        return true;
      }
      // Abbruch, da Angriffslinie besetzt
      break;
    }
  }
  
  // Prüfe alle Felder nach links
  for (j=linieBrettIndex-1; j>=0; j--) {
    zielFeld = brett[reiheBrettIndex][j];
    zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if (zielFeldStatus == "eigen") {
      // Eigene Figur: Keine Gefahr und Abbruch
      break;
    }
    else if (zielFeldStatus == "gegner") {
      // Da steht ein Gegner
      if (((zielFeld.substr(0, 1) == "k") && (linieBrettIndex-j == 1)) || (zielFeld.substr(0, 1) == "d") || (zielFeld.substr(0, 1) == "t")) {
        // Der bedroht uns, Ende!
        return true;
      }
      // Abbruch, da Angriffslinie besetzt
      break;
    }
  }
  
  
  //
  // Die "schrägen" prüfen
  //
  
  // Prüfe alle Felder nach oben rechts
  i = reiheBrettIndex;
  j = linieBrettIndex;
  i++;
  j++;
  while ((i>=0) && (i<=7) && (j>=0) && (j<=7)) {
    zielFeld = brett[i][j];
    zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if (zielFeldStatus == "eigen") {
      // Eigene Figur: Keine Gefahr und Abbruch
      break;
    }
    else if (zielFeldStatus == "gegner") {
      // Da steht ein Gegner
      if (((zielFeld.substr(0, 1) == "k") && (Math.abs(reiheBrettIndex-i) == 1) && (Math.abs(linieBrettIndex-j) == 1)) || (zielFeld.substr(0, 1) == "d") || (zielFeld.substr(0, 1) == "l")) {
        // Der bedroht uns, Ende!
        return true;
      }
      // Abbruch, da Angriffslinie besetzt
      break;
    }
    i++;
    j++;
  }
  
  // Prüfe alle Felder nach
  i = reiheBrettIndex;
  j = linieBrettIndex;
  i--;
  j++;
  while ((i>=0) && (i<=7) && (j>=0) && (j<=7)) {
    zielFeld = brett[i][j];
    zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if (zielFeldStatus == "eigen") {
      // Eigene Figur: Keine Gefahr und Abbruch
      break;
    }
    else if (zielFeldStatus == "gegner") {
      // Da steht ein Gegner
      if (((zielFeld.substr(0, 1) == "k") && (Math.abs(reiheBrettIndex-i) == 1) && (Math.abs(linieBrettIndex-j) == 1)) || (zielFeld.substr(0, 1) == "d") || (zielFeld.substr(0, 1) == "l")) {
        // Der bedroht uns, Ende!
        return true;
      }
      // Abbruch, da Angriffslinie besetzt
      break;
    }
    i--;
    j++;
  }
  
  // Prüfe alle Felder nach
  i = reiheBrettIndex;
  j = linieBrettIndex;
  i++;
  j--;
  while ((i>=0) && (i<=7) && (j>=0) && (j<=7)) {
    zielFeld = brett[i][j];
    zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if (zielFeldStatus == "eigen") {
      // Eigene Figur: Keine Gefahr und Abbruch
      break;
    }
    else if (zielFeldStatus == "gegner") {
      // Da steht ein Gegner
      if (((zielFeld.substr(0, 1) == "k") && (Math.abs(reiheBrettIndex-i) == 1) && (Math.abs(linieBrettIndex-j) == 1)) || (zielFeld.substr(0, 1) == "d") || (zielFeld.substr(0, 1) == "l")) {
        // Der bedroht uns, Ende!
        return true;
      }
      // Abbruch, da Angriffslinie besetzt
      break;
    }
    i++;
    j--;
  }
  
  // Prüfe alle Felder nach
  i = reiheBrettIndex;
  j = linieBrettIndex;
  i--;
  j--;
  while ((i>=0) && (i<=7) && (j>=0) && (j<=7)) {
    zielFeld = brett[i][j];
    zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if (zielFeldStatus == "eigen") {
      // Eigene Figur: Keine Gefahr und Abbruch
      break;
    }
    else if (zielFeldStatus == "gegner") {
      // Da steht ein Gegner
      if (((zielFeld.substr(0, 1) == "k") && (Math.abs(reiheBrettIndex-i) == 1) && (Math.abs(linieBrettIndex-j) == 1)) || (zielFeld.substr(0, 1) == "d") || (zielFeld.substr(0, 1) == "l")) {
        // Der bedroht uns, Ende!
        return true;
      }
      // Abbruch, da Angriffslinie besetzt
      break;
    }
    i--;
    j--;
  }
  
  
  //
  // Bedrohungen von Springern
  //
  
  i = reiheBrettIndex + 2;
  j = linieBrettIndex + 1;
  if ((i>=0) && (i<=7) && (j>=0) && (j<=7)) {
    zielFeld = brett[i][j];
    zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if ((zielFeldStatus == "gegner") && (zielFeld.substr(0, 1) == "s")) {
      // Der bedroht uns, Ende!
      return true;
    }
  }
  
  i = reiheBrettIndex + 2;
  j = linieBrettIndex - 1;
  if ((i>=0) && (i<=7) && (j>=0) && (j<=7)) {
    zielFeld = brett[i][j];
    zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if ((zielFeldStatus == "gegner") && (zielFeld.substr(0, 1) == "s")) {
      // Der bedroht uns, Ende!
      return true;
    }
  }
  
  i = reiheBrettIndex - 2;
  j = linieBrettIndex + 1;
  if ((i>=0) && (i<=7) && (j>=0) && (j<=7)) {
    zielFeld = brett[i][j];
    zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if ((zielFeldStatus == "gegner") && (zielFeld.substr(0, 1) == "s")) {
      // Der bedroht uns, Ende!
      return true;
    }
  }
  
  i = reiheBrettIndex - 2;
  j = linieBrettIndex - 1;
  if ((i>=0) && (i<=7) && (j>=0) && (j<=7)) {
    zielFeld = brett[i][j];
    zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if ((zielFeldStatus == "gegner") && (zielFeld.substr(0, 1) == "s")) {
      // Der bedroht uns, Ende!
      return true;
    }
  }
  
  i = reiheBrettIndex + 1;
  j = linieBrettIndex + 2;
  if ((i>=0) && (i<=7) && (j>=0) && (j<=7)) {
    zielFeld = brett[i][j];
    zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if ((zielFeldStatus == "gegner") && (zielFeld.substr(0, 1) == "s")) {
      // Der bedroht uns, Ende!
      return true;
    }
  }
  
  i = reiheBrettIndex + 1;
  j = linieBrettIndex - 2;
  if ((i>=0) && (i<=7) && (j>=0) && (j<=7)) {
    zielFeld = brett[i][j];
    zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if ((zielFeldStatus == "gegner") && (zielFeld.substr(0, 1) == "s")) {
      // Der bedroht uns, Ende!
      return true;
    }
  }
  
  i = reiheBrettIndex - 1;
  j = linieBrettIndex + 2;
  if ((i>=0) && (i<=7) && (j>=0) && (j<=7)) {
    zielFeld = brett[i][j];
    zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if ((zielFeldStatus == "gegner") && (zielFeld.substr(0, 1) == "s")) {
      // Der bedroht uns, Ende!
      return true;
    }
  }
  
  i = reiheBrettIndex - 1;
  j = linieBrettIndex - 2;
  if ((i>=0) && (i<=7) && (j>=0) && (j<=7)) {
    zielFeld = brett[i][j];
    zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if ((zielFeldStatus == "gegner") && (zielFeld.substr(0, 1) == "s")) {
      // Der bedroht uns, Ende!
      return true;
    }
  }
  
  
  //
  // Bedrohungen von Bauern
  //
  // Prüfe schlagen von links
  if (eigenFarbe == "w") {  // wir: b1 (01), Teste c2 (12)
    i = reiheBrettIndex + 1;
    j = linieBrettIndex + 1;
  }
  else {                    // wir: b8 (71), Teste c7 (62)
    i = reiheBrettIndex - 1;
    j = linieBrettIndex + 1;
  }
  if ((i>=0) && (i<=7) && (j>=0) && (j<=7)) {
    zielFeld = brett[i][j];
    zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if ((zielFeldStatus == "gegner") && (zielFeld.substr(0, 1) == "b")) {
      // Der bedroht uns, Ende!
      return true;
    }
  }
  
  // Prüfe schlagen von rechts
  if (eigenFarbe == "w") {  // wir: b1 (01), Teste a2 (10)
    i = reiheBrettIndex + 1;
    j = linieBrettIndex - 1;
  }
  else {                    // wir: b8 (71), Teste a7 (60)
    i = reiheBrettIndex - 1;
    j = linieBrettIndex - 1;
  }
  if ((i>=0) && (i<=7) && (j>=0) && (j<=7)) {
    zielFeld = brett[i][j];
    zielFeldStatus = this.GetZielFeldStatus(zielFeld, eigenFarbe);
    if ((zielFeldStatus == "gegner") && (zielFeld.substr(0, 1) == "b")) {
      // Der bedroht uns, Ende!
      return true;
    }
  }
  
  return false;
}

//
// Gibt die Figur zurück: "", "bw", "sw", "lw", "ts", "ds", "ks".
//
// Param: "d4"
//
PartieAnalyse.prototype.GetFigur = function(feldName)
{
  var result = "";
  
  var reiheBrettIndex = this.GetBrettIndexReihe(feldName);
  var linieBrettIndex = this.GetBrettIndexLinie(feldName);
  result = brett[reiheBrettIndex][linieBrettIndex];
  
  return result;
}

//
// Gibt den Reihen-Index (0-7) des Feldes auf dem Brett zurück.
//
// Param: "g4" -> Erg = 3.
//
PartieAnalyse.prototype.GetBrettIndexReihe = function(feldName)
{
  var reihe = feldName.substr(1, 1);
  var reiheBrettIndex = 0;
  switch (reihe) {
    case "1": reiheBrettIndex = 0; break;
    case "2": reiheBrettIndex = 1; break;
    case "3": reiheBrettIndex = 2; break;
    case "4": reiheBrettIndex = 3; break;
    case "5": reiheBrettIndex = 4; break;
    case "6": reiheBrettIndex = 5; break;
    case "7": reiheBrettIndex = 6; break;
    case "8": reiheBrettIndex = 7; break;
    default: break;
  }
  return reiheBrettIndex;
}


//
// Gibt den Linien-Index (0-7) des Feldes auf dem Brett zurück.
//
// Param: "g4" -> Erg = 6.
//
PartieAnalyse.prototype.GetBrettIndexLinie = function(feldName)
{
  var linie = feldName.substr(0, 1);
  var linieBrettIndex = 0;
  switch (linie) {
    case "a": linieBrettIndex = 0; break;
    case "b": linieBrettIndex = 1; break;
    case "c": linieBrettIndex = 2; break;
    case "d": linieBrettIndex = 3; break;
    case "e": linieBrettIndex = 4; break;
    case "f": linieBrettIndex = 5; break;
    case "g": linieBrettIndex = 6; break;
    case "h": linieBrettIndex = 7; break;
    default: break;
  }
  return linieBrettIndex;
}

//
// Gibt den Feldnamen des Feldes mit den Indizes zurück (siehe "PartieAnzeige.js::brett").
//
PartieAnalyse.prototype.GetFeldNameFromInizes = function(i, j)
{
  var result = '';
  switch (j) {
    case 0: result = 'a'; break;
    case 1: result = 'b'; break;
    case 2: result = 'c'; break;
    case 3: result = 'd'; break;
    case 4: result = 'e'; break;
    case 5: result = 'f'; break;
    case 6: result = 'g'; break;
    case 7: result = 'h'; break;
    default: break;
  }
  switch (i) {
    case 0: result += '1'; break;
    case 1: result += '2'; break;
    case 2: result += '3'; break;
    case 3: result += '4'; break;
    case 4: result += '5'; break;
    case 5: result += '6'; break;
    case 6: result += '7'; break;
    case 7: result += '8'; break;
    default: break;
  }
  return result;
}

//
// True, falls das Feld weiss ist.
//
// Params:
// - feldName: "d4"
//
PartieAnalyse.prototype.IsFeldWeiss = function(feldName)
{
  var result = false;
  
  if ((feldName == "b1") ||
      (feldName == "d1") ||
      (feldName == "f1") ||
      (feldName == "h1") ||
      (feldName == "a2") ||
      (feldName == "c2") ||
      (feldName == "e2") ||
      (feldName == "g2") ||
      (feldName == "b3") ||
      (feldName == "d3") ||
      (feldName == "f3") ||
      (feldName == "h3") ||
      (feldName == "a4") ||
      (feldName == "c4") ||
      (feldName == "e4") ||
      (feldName == "g4") ||
      (feldName == "b5") ||
      (feldName == "d5") ||
      (feldName == "f5") ||
      (feldName == "h5") ||
      (feldName == "a6") ||
      (feldName == "c6") ||
      (feldName == "e6") ||
      (feldName == "g6") ||
      (feldName == "b7") ||
      (feldName == "d7") ||
      (feldName == "f7") ||
      (feldName == "h7") ||
      (feldName == "a8") ||
      (feldName == "c8") ||
      (feldName == "e8") ||
      (feldName == "g8")) {
    result = true;
  }
  
  return result;
}

//
// Gibt die Namen aller Felder zurück
//
// Result:
// Ret[0]  = "a1"
// Ret[1]  = "a2"
// ...
// Ret[63] = "h8"
//
PartieAnalyse.prototype.GetAlleFelder = function()
{
  var result = new Array();
  
  result.push("a1");
  result.push("a2");
  result.push("a3");
  result.push("a4");
  result.push("a5");
  result.push("a6");
  result.push("a7");
  result.push("a8");
  
  result.push("b1");
  result.push("b2");
  result.push("b3");
  result.push("b4");
  result.push("b5");
  result.push("b6");
  result.push("b7");
  result.push("b8");
  
  result.push("c1");
  result.push("c2");
  result.push("c3");
  result.push("c4");
  result.push("c5");
  result.push("c6");
  result.push("c7");
  result.push("c8");
  
  result.push("d1");
  result.push("d2");
  result.push("d3");
  result.push("d4");
  result.push("d5");
  result.push("d6");
  result.push("d7");
  result.push("d8");
  
  result.push("e1");
  result.push("e2");
  result.push("e3");
  result.push("e4");
  result.push("e5");
  result.push("e6");
  result.push("e7");
  result.push("e8");
  
  result.push("f1");
  result.push("f2");
  result.push("f3");
  result.push("f4");
  result.push("f5");
  result.push("f6");
  result.push("f7");
  result.push("f8");
  
  result.push("g1");
  result.push("g2");
  result.push("g3");
  result.push("g4");
  result.push("g5");
  result.push("g6");
  result.push("g7");
  result.push("g8");
  
  result.push("h1");
  result.push("h2");
  result.push("h3");
  result.push("h4");
  result.push("h5");
  result.push("h6");
  result.push("h7");
  result.push("h8");
  
  return result;
}

//
// Ob es sich um einen Spezial-Zug handelt.
// Hier wird nicht auf ausführbarkeit des Zuges geprüft.
//
// Result:
// - "keiner"     Nein, es ist ein normaler Zug
// - "RochadeWk"  Rochade (Weiss, kurz) oder entsprechend
// - "Umwandlung" Bauerumwandlung
// - "EP"         Schlagen en passant
//
PartieAnalyse.prototype.IsSpezialZug = function(startFeldName, zielFeldName)
{
  var startFeldFigur = this.GetFigur(startFeldName);
  
  //
  // Auf Rochaden prüfen
  //
  if ((startFeldName == "e1") && (zielFeldName == "g1") && (startFeldFigur == "kw")) {
    return "RochadeWk";
  }
  if ((startFeldName == "e1") && (zielFeldName == "c1") && (startFeldFigur == "kw")) {
    return "RochadeWl";
  }
  if ((startFeldName == "e8") && (zielFeldName == "g8") && (startFeldFigur == "ks")) {
    return "RochadeSk";
  }
  if ((startFeldName == "e8") && (zielFeldName == "c8") && (startFeldFigur == "ks")) {
    return "RochadeSl";
  }
  
  //
  // Auf Bauerumwandlung prüfen
  //
  if ((startFeldFigur == "bw") || (startFeldFigur == "bs")) {
    // Es ist ein Bauer
    var zielReiheBrettIndex  = this.GetBrettIndexReihe(zielFeldName);
    if ((zielReiheBrettIndex == 0) || (zielReiheBrettIndex == 7)) {
      return "Umwandlung";
    }
  }
  
  //
  // Auf Schlagen e.p. prüfen
  //
  if ((startFeldFigur == "bw") || (startFeldFigur == "bs")) {
    // Es ist ein Bauer
    if (this.GetBrettIndexLinie(startFeldName) != this.GetBrettIndexLinie(zielFeldName)) {
      // Er hat geschlagen
      if (this.GetFigur(zielFeldName) == "") {
        // Zielfeld war leer: e.p.
        return "EP";
      }
    }
  }
  
  return "keiner";
}

