/// <summary>
    /// Konstruktor
    /// </summary>
    /// <param name="spielFeld">Spielfeld als Textzeilen</param>
    public SokoWahn_5th(string spielFeld)
    {
      SokowahnStaticTools.SpielfeldEinlesen(spielFeld, out feldBreite, out feldHöhe, out feldSpielerStartPos, out feldData, out feldDataLeer);

      raumBasis = new SokowahnRaum(feldData, feldBreite);

      Directory.CreateDirectory(TempOrdner);

      // --- Vorwärtssuche initialisieren ---
      bekannteStellungen = new SokowahnHash_Index24Multi();
      bekannteStellungen.Add(raumBasis.Crc, 0);
      vorwärtsTiefe = 0;
      vorwärtsTiefeAktuell = 0;
      vorwärtsSucher = new SokowahnLinearList2[0];
      vorwärtsSucherPunkte = new Dictionary<int, int>[0];
      VorwärtsAdd(raumBasis.GetStellung(), new SokowahnPunkte());

      // --- Zielstellungen und Rückwärtssuche initialisieren ---
      zielStellungen = new SokowahnHash_Index24Multi();
      rückwärtsTiefe = 0;
      rückwärtsSucher = new SokowahnLinearList2[0];

      foreach (SokowahnStellung stellung in SokowahnStaticTools.SucheZielStellungen(raumBasis))
      {
        zielStellungen.Add(stellung.crc64, 60000);
        RückwärtsAdd(stellung);
      }

      ulong spielFeldCrc = Crc64.Start.Crc64Update(raumBasis.FeldBreite, raumBasis.FeldHöhe, raumBasis.FeldData);

      blocker = new SokowahnBlockerB2(Environment.CurrentDirectory + "\\temp\\blocker2_x" + spielFeldCrc.ToString("x").PadLeft(16, '0') + ".gz", raumBasis);
    }
Ejemplo n.º 2
0
    /// <summary>
    /// initialisiert die ersten Blocker-Kisten für den SammlerStart
    /// </summary>
    /// <param name="zielVariante">gibt an, ob nur Varianten ermittelt werden sollen, wo alle Kisten bereits auf dem Zielfeld stehen</param>
    void SammleKistenInit(bool zielVariante)
    {
      sammlerCheckKisten = Enumerable.Range(0, suchKistenAnzahl).Select(i => i).ToArray();
      sammlerCheckKisten[suchKistenAnzahl - 1]--; // letzte eins zurück setzen, damit beim ersten sammlerNext() auch die erste Variante gesetzt werden kann

      char[] feldData = basisRaum.FeldData;
      int feldBreite = basisRaum.FeldBreite;

      bool[] spielerRaum = SokowahnStaticTools.SpielfeldRaumScan(feldData, feldBreite);
      raumAnzahl = spielerRaum.Count(x => x);
      int[] raumZuFeld = Enumerable.Range(0, spielerRaum.Length).Where(i => spielerRaum[i]).ToArray();
      int[] feldZuRaum = Enumerable.Range(0, feldData.Length).Select(i => spielerRaum[i] ? raumZuFeld.ToList().IndexOf(i) : -1).ToArray();

      if (zielVariante)
      {
        sammlerCheckKistenRaum = raumZuFeld.Select(i => (feldData[i] == '.' || feldData[i] == '*' || feldData[i] == '+') ? feldZuRaum[i] : -1).Where(i => i >= 0).ToArray();
      }
      else
      {
        sammlerCheckKistenRaum = raumZuFeld.Select(i => (feldData[i] == '$' || feldData[i] == '*') ? feldZuRaum[i] : -1).Where(i => i >= 0).ToArray();
      }

      if (!zielVariante) // nur beim ersten mal Initialisieren
      {
        tmpRaum = new SokowahnRaum(feldData, feldBreite);
        tmpRaum.KistenAnzahl = suchKistenAnzahl;
        threadRäume = Enumerable.Range(0, 256).Select(i => new SokowahnRaum(tmpRaum)).ToArray();

        bekannteStellungen = new SokowahnHash_Index24Multi();

        prüfListe = new SokowahnLinearList2(suchKistenAnzahl + 1, Environment.CurrentDirectory + "\\temp\\", listeMax / 32768);
        prüfListeSammler = new SokowahnLinearList2(suchKistenAnzahl + 1, Environment.CurrentDirectory + "\\temp\\", listeMax / 32768);
        prüfListeGut = new SokowahnLinearList2(suchKistenAnzahl + 1, Environment.CurrentDirectory + "\\temp\\", listeMax / 32768);
        prüfListeBöse = new SokowahnLinearList2(suchKistenAnzahl + 1, Environment.CurrentDirectory + "\\temp\\", listeMax / 32768);
      }
    }
Ejemplo n.º 3
0
    /// <summary>
    /// berechnet die nächsten Blocker
    /// </summary>
    /// <param name="limit">maximale Anzahl der Berechnungen, oder 0, wenn die Berechnung beendet werden soll</param>
    /// <returns>true, wenn noch weitere Berechnungen anstehen</returns>
    public bool Next(int limit)
    {
      int maxKisten = basisRaum.FeldData.Where(c => c == '$' || c == '*').Count();

      if (limit <= 0) // Marker für Abbruch
      {
        return false;
      }

      switch (status)
      {
        #region # case BlockerStatus.Init: // Start einer Blocker-Sucher (eine neue Kistenanzahl wird ausprobiert)
        case BlockerStatus.Init:
        {
          if (suchKistenAnzahl + 1 >= maxKisten)
          {
            Abbruch();
            return false; // Kisten-Limit erreicht
          }

          suchKistenAnzahl++;

          SammleKistenInit(false);

          status = BlockerStatus.SammleStartStellungen;
          return true;
        }
        #endregion
        #region # case BlockerStatus.SammleStartStellungen: // sammelt alle Start-Stellungen mit der entsprechenden Kistenanzahl (sind automatisch auch gleichzeitig Stellungen, mit denen das Ziel erreichbar ist)
        case BlockerStatus.SammleStartStellungen:
        {
          limit--;
          while (limit > 0 && SammleKistenNext()) limit--;

          if (SammleKistenNext())
          {
            return true;
          }
          else
          {
            SammleKistenInit(true);

            status = BlockerStatus.SammleZielStellungen;
            return true;
          }
        }
        #endregion
        #region # case BlockerStatus.SammleZielStellungen: // sammelt alle Ziel-Stellungen, wo jede Kiste auf ein Zielfeld steht
        case BlockerStatus.SammleZielStellungen:
        {
          limit--;
          while (limit > 0 && SammleKistenNext()) limit--;

          if (!SammleKistenNext()) status = BlockerStatus.SucheVarianten;

          return true;
        }
        #endregion
        #region # case BlockerStatus.SucheVarianten: // sucht vorwärts alle möglichen Varianten (eventuell bereits vorhandene Blocker werden beachten)
        case BlockerStatus.SucheVarianten:
        {
          if (prüfListe.SatzAnzahl == 0)
          {
            prüfListe.Dispose();
            prüfListe = prüfListeSammler;
            prüfListeSammler = new SokowahnLinearList2(suchKistenAnzahl + 1, Environment.CurrentDirectory + "\\temp\\", listeMax / 32768);
            if (prüfListe.SatzAnzahl == 0)
            {
              prüfListeSammler.Dispose();
              status = BlockerStatus.VerschmelzeZielStellungen;
              verschmelzenRest = prüfListeBöse.SatzAnzahl;
              return true;
            }
          }

          limit = (int)Math.Min((long)limit, prüfListe.SatzAnzahl);

          var ergebnisse = Enumerable.Range(0, limit).Select(i => prüfListe.Pop()).AsParallel().SelectMany(stellung =>
          {
            SokowahnRaum raum = threadRäume[Thread.CurrentThread.ManagedThreadId];
            raum.LadeStellung(stellung, 0, 0);
            return raum.GetVarianten(this);
          }).Where(x => bekannteStellungen.Get(x.crc64) == 65535).ToArray();

          foreach (var stellung in ergebnisse)
          {
            int find = bekannteStellungen.Get(stellung.crc64);
            if (find == 65535)
            {
              bekannteStellungen.Add(stellung.crc64, 12345);
              prüfListeSammler.Add(stellung.raumSpielerPos, stellung.kistenZuRaum);
              prüfListeBöse.Add(stellung.raumSpielerPos, stellung.kistenZuRaum);
            }
          }

          return true;
        }
        #endregion
        #region # case BlockerStatus.VerschmelzeZielStellungen: // ermittelt (anhand der Rückwärts-Suche) welche der ermittelten Stellungen zum Ziel führen können und markiert diese
        case BlockerStatus.VerschmelzeZielStellungen:
        {
          if (prüfListe.SatzAnzahl == 0)
          {
            prüfListe.Dispose();
            prüfListe = prüfListeGut;
            prüfListeGut = new SokowahnLinearList2(suchKistenAnzahl + 1, Environment.CurrentDirectory + "\\temp\\", listeMax / 32768);
            if (prüfListe.SatzAnzahl == 0)
            {
              prüfListe.Dispose();
              prüfListeGut.Dispose();
              prüfListe = null;
              prüfListeGut = null;
              status = BlockerStatus.ErstelleBlocker;
              tempBlocker = new BlockerFeld[raumAnzahl];
              for (int i = 0; i < tempBlocker.Length; i++)
              {
                tempBlocker[i].geprüfteStellungen = bekannteStellungen.HashAnzahl;
                tempBlocker[i].kistenNummerLeer = suchKistenAnzahl;
              }
              return true;
            }
          }

          limit = (int)Math.Min((long)limit, prüfListe.SatzAnzahl);
          verschmelzenRest -= (long)limit;

          var ergebnisse = Enumerable.Range(0, limit).Select(i => prüfListe.Pop()).AsParallel().SelectMany(stellung =>
          {
            SokowahnRaum raum = threadRäume[Thread.CurrentThread.ManagedThreadId];
            raum.LadeStellung(stellung, 0, 0);
            return raum.GetVariantenRückwärts();
          }).Where(x => bekannteStellungen.Get(x.crc64) < 65535).ToArray();

          foreach (var stellung in ergebnisse)
          {
            int find = bekannteStellungen.Get(stellung.crc64);
            if (find == 60000)
            {
              continue;
            }
            else
            {
              prüfListeGut.Add(stellung.raumSpielerPos, stellung.kistenZuRaum);
              bekannteStellungen.Update(stellung.crc64, 60000);
            }
          }

          return true;
        }
        #endregion
        #region # case BlockerStatus.ErstelleBlocker: // erstellt die Blocker anhand der restlichen Stellungen, welche nicht zum Ziel führten
        case BlockerStatus.ErstelleBlocker:
        {
          limit = (int)Math.Min((long)limit, prüfListeBöse.SatzAnzahl);

          var ergebnisse = Enumerable.Range(0, limit).Select(i => prüfListeBöse.Pop()).Select(x =>
          {
            tmpRaum.LadeStellung(x, 0, 0);
            return tmpRaum.GetStellung();
          }).Where(stellung => bekannteStellungen.Get(stellung.crc64) == 12345).ToArray();

          foreach (var stellung in ergebnisse)
          {
            tempBlocker[stellung.raumSpielerPos].Add(stellung.kistenZuRaum, suchKistenAnzahl);
          }

          if (prüfListeBöse.SatzAnzahl == 0)
          {
            int startPos = bekannteBlocker.Length;
            Array.Resize(ref bekannteBlocker, startPos + raumAnzahl);
            for (int i = 0; i < raumAnzahl; i++) bekannteBlocker[startPos + i] = tempBlocker[i];

            for (int i = 0; i < bekannteBlocker.Length; i++) bekannteBlocker[i].kistenNummerLeer = suchKistenAnzahl + 1;

            long geprüfteStellungenGesamt = 0;
            for (int i = 0; i < bekannteBlocker.Length; i += raumAnzahl) geprüfteStellungenGesamt += bekannteBlocker[i].geprüfteStellungen;
            if (geprüfteStellungenGesamt > 100000) SpeichereAlleBlocker();

            status = BlockerStatus.Init;
            bekannteStellungen = null;
          }

          return true;
        }
        #endregion
        #region # case BlockerStatus.Fertig: // Blockersuche wurde beendet, (nur noch der Check-Methode steht bereit)
        case BlockerStatus.Fertig: return false;
        #endregion

        default: throw new Exception("Status unbekant: " + status);
      }
    }
Ejemplo n.º 4
0
    /// <summary>
    /// berechnet die nächsten Blocker
    /// </summary>
    /// <param name="limit">maximale Anzahl der Berechnungen, oder 0, wenn die Berechnung beendet werden soll</param>
    /// <returns>true, wenn noch weitere Berechnungen anstehen</returns>
    public bool Next(int limit)
    {
      switch (blockerStatus)
      {
        #region # case BlockerStatus.init:
        case BlockerStatus.init:
        {
          sammlerKistenAnzahl++;
          if (sammlerKistenAnzahl == basisRaum.KistenAnzahl)
          {
            Abbruch();
            return false;
          }

          sammlerAbfrage = SammlerBerechneZielStellungen().GetEnumerator();
          sammlerHash = new SokowahnHash_Index16Multi();
          sammlerStats = new long[60001];
          rückwärtsSucher = Enumerable.Range(0, maxVorschau).Select(x => new SokowahnLinearList2(sammlerKistenAnzahl + 1, Environment.CurrentDirectory + "\\temp\\", multi32k)).ToArray();
          rückwärtsTiefe = 0;

          alleStellungen = new SokowahnLinearList2(sammlerKistenAnzahl + 1, Environment.CurrentDirectory + "\\temp\\", multi32k * 4);
          alleBlockerHash = new HashSet<ulong>();

          char[] feldData = basisRaum.FeldData;
          int feldBreite = basisRaum.FeldBreite;

          bool[] spielerRaum = SokowahnStaticTools.SpielfeldRaumScan(feldData, feldBreite);
          raumAnzahl = spielerRaum.Count(x => x);

          tempBlocker = new SokowahnBlockerB.BlockerFeld[raumAnzahl];
          for (int i = 0; i < tempBlocker.Length; i++) tempBlocker[i].kistenNummerLeer = sammlerKistenAnzahl;

          blockerStatus = BlockerStatus.sammleZiele;
          return true;
        }
        #endregion

        #region # case BlockerStatus.sammleZiele:
        case BlockerStatus.sammleZiele:
        {
          while (limit-- > 0 && sammlerAbfrage.MoveNext())
          {
            var satz = sammlerAbfrage.Current;
            if (sammlerHash.Get(satz.crc64) == 65535)
            {
              sammlerHash.Add(satz.crc64, 60000);
              sammlerStats[60000]++;
              rückwärtsSucher[0].Add(satz.raumSpielerPos, satz.kistenZuRaum);
              alleStellungen.Add(satz.raumSpielerPos, satz.kistenZuRaum);
            }
          }

          if (limit >= 0)
          {
            tempRaum = new SokowahnRaum(basisRaum);
            tempRaum.KistenAnzahl = sammlerKistenAnzahl;
            threadRäume = Enumerable.Range(0, 256).Select(i => new SokowahnRaum(tempRaum)).ToArray();
            blockerStatus = BlockerStatus.suchModus;
          }

          return true;
        }
        #endregion

        #region # case BlockerStatus.suchModus:
        case BlockerStatus.suchModus:
        {
          if (SucheRückwärts(limit)) return true;

          Array.Resize(ref bekannteBlockerHashes, sammlerKistenAnzahl);
          bekannteBlockerHashes[sammlerKistenAnzahl - 1] = sammlerHash;
          Array.Resize(ref bekannteSammlerStats, sammlerKistenAnzahl);
          var tmp = sammlerStats.Reverse().ToList();
          while (tmp[tmp.Count - 1] == 0) tmp.RemoveAt(tmp.Count - 1);
          bekannteSammlerStats[sammlerKistenAnzahl - 1] = tmp.ToArray();
          for (int i = 0; i < rückwärtsSucher.Length; i++) rückwärtsSucher[i].Dispose();
          blockerStatus = BlockerStatus.blockerSuche;

          return true;
        }
        #endregion

        #region # case BlockerStatus.blockerSuche:
        case BlockerStatus.blockerSuche:
        {
          limit = (int)Math.Min((long)limit, alleStellungen.SatzAnzahl);

          if (limit == 0)
          {
            int startPos = bekannteBlocker.Length;
            Array.Resize(ref bekannteBlocker, startPos + raumAnzahl);
            for (int i = 0; i < raumAnzahl; i++) bekannteBlocker[startPos + i] = tempBlocker[i];

            for (int i = 0; i < bekannteBlocker.Length; i++)
            {
              bekannteBlocker[i].geprüfteStellungen = sammlerHash.HashAnzahl;
              bekannteBlocker[i].kistenNummerLeer = sammlerKistenAnzahl + 1;
            }

            long geprüfteStellungenGesamt = 0;
            for (int i = 0; i < bekannteBlocker.Length; i += raumAnzahl) geprüfteStellungenGesamt += bekannteBlocker[i].geprüfteStellungen;
            for (int i = 0; i < bekannteBlocker.Length; i++) bekannteBlocker[i].Sortieren();

            blockerStatus = BlockerStatus.init;
            return true;
          }

          var stellungen = alleStellungen.Pop(limit);
          int satzGröße = alleStellungen.SatzGröße;

          var ergebnisse = Enumerable.Range(0, limit)
#if !parallelDeaktivieren
.AsParallel()
#if parallelGeordnet
.AsOrdered()
#endif
#endif
.SelectMany(stellung =>
          {
            SokowahnRaum raum = threadRäume[Thread.CurrentThread.ManagedThreadId];
            raum.LadeStellung(stellungen, stellung * satzGröße, 0);
            //            return raum.GetVarianten(this).Where(x => sammlerHash.Get(x.crc64) == 65535);
            var ausgabe = raum.GetVarianten(this).Where(x =>
              {
                if (sammlerHash.Get(x.crc64) == 65535) return true;
                x.zugTiefe = 60000 - sammlerHash.Get(x.crc64);
                //string dbg = x.Debug(basisRaum);
                return false;
              }
              );
            return ausgabe;
          }).ToArray();

          foreach (var stellung in ergebnisse)
          {
            if (alleBlockerHash.Contains(stellung.crc64)) continue;
            alleBlockerHash.Add(stellung.crc64);
            tempBlocker[stellung.raumSpielerPos].Add(stellung.kistenZuRaum, sammlerKistenAnzahl);
          }

          return true;
        }
        #endregion

        #region # case BlockerStatus.bereit:
        case BlockerStatus.bereit:
        {
          return false;
        }
        #endregion

        default: throw new NotImplementedException();
      }
    }
    /// <summary>
    /// entfernt unnötige Einträge aus der Hashtabelle (sofern möglich)
    /// </summary>
    /// <returns>Anzahl der Einträge, welche entfernt werden konnten</returns>
    public long Refresh()
    {
      // --- hash aufräumen ---
      var old = hashStellungen;
      hashStellungen = new SokowahnHash_Index24Multi();
      var übertrag = new List<StellungsSatz>();

      foreach (var satz in old.GetAll())
      {
        if (satz.Value <= suchTiefe)
        {
          übertrag.Add(new StellungsSatz { stellung = satz.Key, tiefe = satz.Value });
        }
        else
        {
          hashStellungen.Add(satz.Key, satz.Value);
        }
      }

      übertrag.Sort((x, y) => x.stellung.CompareTo(y.stellung));

      ArchivEintrag(übertrag);

      return archivGro + (long)48000000;
    }
    /// <summary>
    /// berechnet den nächsten Schritt
    /// </summary>
    /// <param name="limit">Anzahl der zu berechnenden (kleinen) Arbeitsschritte, negativer Wert = optionale Vorbereitungsschritte)</param>
    /// <returns>gibt an, ob noch weitere Berechnungen anstehen</returns>
    public bool Next(int limit)
    {
      if (limit == 0) return false;
      switch (modus)
      {
        #region # case Modus.unbekannt:
        case Modus.Unbekannt:
        {
          if (limit > 0)
          {
            modus = Modus.SucheInit; // Initialisierung für die Suche direkt starten
          }
          else
          {
            modus = Modus.SteinerInit; // Initialisierung der Vorbereitung starten
          }
          return true;
        }
        #endregion
        #region # case Modus.steinerInit:
        case Modus.SteinerInit:
        {
          if (limit > 0)
          {
            modus = Modus.SucheInit; // Vorbereitung abbrechen und Suche direkt starten
            return true;
          }

          int maxKisten = feldData.Where(c => c == '$' || c == '*').Count();

          kistenAnzahl++;

          if (kistenAnzahl >= maxKisten)
          {
            return false; // Maximale Kistenanzahl erreicht, weitere Berechnungen sind nicht mehr möglich
          }

          modus = Modus.SteinerVarianten; // neue Aufgabe: alle Varianten ermitteln

          KistenSteinerInit();
          steinerPrüfStellungen = new List<Variante>();
          steinerPrüfstellungenPos = 0;

          return true;
        }
        #endregion
        #region # case Modus.steinerVarianten:
        case Modus.SteinerVarianten:
        {
          if (limit > 0)
          {
            modus = Modus.SucheInit; // Vorbereitung abbrechen und Suche direkt starten
            return true;
          }

          limit = -limit;

          while (limit > 0)
          {
            if (steinerPrüfstellungenPos == steinerPrüfStellungen.Count)
            {
              limit--;
              if (!KistenSteinerNext())
              {
                modus = Modus.SteinerLösen;
                steinerBöseStellungen = steinerPrüfStellungen.Where(x => hashStellungen.Get(x.stellungCrc) == 1).ToArray();
                steinerPrüfStellungen = steinerPrüfStellungen.Where(x => hashStellungen.Get(x.stellungCrc) == 2).ToList();
                var old = hashStellungen;
                hashStellungen = new SokowahnHash_Index24Multi();
                foreach (var satz in old.GetAll().Where(x => x.Value == 1))
                {
                  hashStellungen.Add(satz.Key, satz.Value);
                }
                steinerPrüfstellungenPos = 0;
                return true;
              }
            }
            else
            {
              var prüf = steinerPrüfStellungen[steinerPrüfstellungenPos++];
              LadeStellung(prüf.stellung); limit--;
              if (kistenMitZiel == kistenAnzahl)
              {
                if (hashStellungen.Get(prüf.stellungCrc) == 65535) hashStellungen.Add(prüf.stellungCrc, 2); else hashStellungen.Update(prüf.stellungCrc, 2);
              }
              foreach (var neuPrüf in SucheVariantenSteiner())
              {
                steinerPrüfStellungen.Add(neuPrüf);
                hashStellungen.Add(neuPrüf.stellungCrc, 1);
              }
            }
          }

          return true;
        }
        #endregion
        #region # case Modus.steinerLösen:
        case Modus.SteinerLösen:
        {
          if (limit > 0)
          {
            modus = Modus.SucheInit; // Vorbereitung abbrechen und Suche direkt starten
            return true;
          }

          limit = -limit;

          while (limit > 0)
          {
            if (steinerPrüfstellungenPos == steinerPrüfStellungen.Count)
            {
              // var dummy = steinerBöseStellungen.Where(x => bekannteStellungen.ContainsKey(x.stellungCrc)).ToArray();

              foreach (var satz in steinerBöseStellungen.Where(x => hashStellungen.Get(x.stellungCrc) < 65535))
              {
                SteinerBlockerDazu(satz.stellung);
              }

              modus = Modus.SteinerInit;

              return true;
            }

            var prüf = steinerPrüfStellungen[steinerPrüfstellungenPos++];
            LadeStellung(prüf.stellung); limit--;
            suchTiefe = 99999;

            var vorgänger = SucheVariantenVorgänger().ToArray();

            if (vorgänger.Length > 0)
            {
              foreach (var check in vorgänger)
              {
                if (hashStellungen.Get(check.stellungCrc) < 65535)
                {
                  steinerPrüfStellungen.Add(new Variante { stellung = check.stellung, stellungCrc = check.stellungCrc, tiefe = 1 });
                  hashStellungen.Remove(check.stellungCrc);
                }
              }
            }
            else // gute Stellung, da keine Vorgänger möglich sind
            {
              if (hashStellungen.Get(prüf.stellungCrc) < 65535)
              {
                hashStellungen.Remove(prüf.stellungCrc);
              }
            }

          }

          return true;
        }
        #endregion
        #region # case Modus.sucheInit:
        case Modus.SucheInit:
        {
          raumSpielerPos = feldZuRaum[startSpielerPos];

          KistenStandardInit();

          suchListenSatz = kistenAnzahl + 1;

          suchTiefe = 0;
          SuchListeInsert(GetStellung(), suchTiefe);

          hashStellungen = new SokowahnHash_Index24Multi();
          hashStellungen.Add(StellungCrc(GetStellung()), 0);

          modus = Modus.SucheRechne;
          return true;
        }
        #endregion
        #region # case Modus.sucheRechne:
        case Modus.SucheRechne:
        {
          var listeAuswahl = suchListe[suchTiefe];
          limit = (int)Math.Min(limit, listeAuswahl.SatzAnzahl);
          for (int listenPos = 0; listenPos < limit; listenPos++)
          {
            LadeStellung(listeAuswahl.Pop());
            if (kistenMitZiel == kistenAnzahl)
            {
              modus = Modus.SucheGefunden;
              return false;
            }

            if (StellungBekannt(StellungCrc(GetStellung())) < suchTiefe) continue; // zu prüfende Stellung wurde schon früher (mit weniger Tiefe) berechnet

            foreach (var variante in SucheVariantenHashcheck())
            {
              var tmpTiefe = StellungBekannt(variante.stellungCrc);
              if (tmpTiefe >= 0)
              {
                if (tmpTiefe <= variante.tiefe) continue; // Vorschlag ignorieren
                hashStellungen.Update(variante.stellungCrc, variante.tiefe);
                SuchListeInsert(variante.stellung, variante.tiefe);
              }
              else
              {
                hashStellungen.Add(variante.stellungCrc, variante.tiefe);
                SuchListeInsert(variante.stellung, variante.tiefe);
              }
            }
          }
          if (listeAuswahl.SatzAnzahl == 0) suchTiefe++; // keine weiteren Stellungen bei dieser Zugtiefe vorhanden, dann zur nächsten Zugtiefe springen
          return true;
        }
        #endregion
        case Modus.SucheGefunden: return false; // Ergebnis gefunden, keine weiteren Berechnungen notwendig
        default: throw new Exception("? " + modus);
      }

    }
    /// <summary>
    /// initialisiert die ersten Steiner-Kisten
    /// </summary>
    void KistenSteinerInit()
    {
      raumZuKiste = raumZuFeld.Select(i => -1).ToArray();
      kistenZuRaum = new int[kistenAnzahl];

      steinerCheckKisten = Enumerable.Range(0, kistenAnzahl).Select(i => i).ToArray();
      steinerCheckKisten[kistenAnzahl - 1]--; // letzte eins zurück setzen, damit beim ersten steinerNext() auch die erste Variante gesetzt werden kann

      steinerCheckKistenRaum = raumZuFeld.Select(i => (feldData[i] == '$' || feldData[i] == '*') ? feldZuRaum[i] : -1).Where(i => i >= 0).ToArray();

      hashStellungen = new SokowahnHash_Index24();
    }
Ejemplo n.º 8
0
    /// <summary>
    /// Konstruktor
    /// </summary>
    /// <param name="raum">Basisdaten anhand eines vorhanden Raumes nutzen</param>
    /// <param name="blocker">bekannte Blocker</param>
    /// <param name="startHash">bekannte Einträge in der Start-Hashtable</param>
    /// <param name="zielHash">bekannte Einträge in der Ziel-Hashtable</param>
    public SokowahnRaum(SokowahnRaum raum, ISokowahnBlocker blocker, ISokowahnHash startHash, ISokowahnHash zielHash)
    {
      this.feldData = raum.feldData;
      this.feldBreite = raum.feldBreite;
      this.raumAnzahl = raum.raumAnzahl;
      this.raumLinks = raum.raumLinks;
      this.raumRechts = raum.raumRechts;
      this.raumOben = raum.raumOben;
      this.raumUnten = raum.raumUnten;

      this.raumSpielerPos = raum.raumSpielerPos;
      this.spielerZugTiefe = raum.spielerZugTiefe;
      this.raumZuKisten = raum.raumZuKisten.ToArray(); // Kopie erstellen
      this.kistenAnzahl = raum.kistenAnzahl;
      this.kistenZuRaum = raum.kistenZuRaum.ToArray(); // Kopie erstellen

      this.tmpCheckRaumPosis = new int[raumAnzahl];
      this.tmpCheckRaumTiefe = new int[raumAnzahl];
      this.tmpRaumCheckFertig = new bool[raumAnzahl + 1];
      this.tmpRaumCheckFertig[raumAnzahl] = true; // Ende-Feld schon auf fertig setzen

      this.merkBlocker = blocker;
      this.merkStartHash = startHash;
      this.merkZielHash = zielHash;
    }