/// <summary>
        /// Probes the transposition table for a entry that matches the position key.
        /// </summary>
        /// <param name="key">The position key</param>
        /// <returns>(true, entry) if one was found, (false, empty) if not found</returns>
        public (bool, TranspositionTableEntry) Probe(HashKey key)
        {
            var ttc = FindCluster(key);
            var g   = _generation;

            // Probing the Table will automatically update the generation of the entry in case the
            // probing retrieves an element.

            TranspositionTableEntry e = default;
            var set = false;

            for (var i = 0; i < ttc.Cluster.Length; ++i)
            {
                if (ttc.Cluster[i].Key32 != 0 && ttc.Cluster[i].Key32 != key.UpperKey)
                {
                    continue;
                }

                ttc.Cluster[i].Generation = g;
                e   = ttc.Cluster[i];
                set = true;
                Hits++;
                break;
            }

            return(set, !set ? TTCluster.DefaultEntry : e);
        }
 public void Save(TranspositionTableEntry tte)
 {
     Key32 = tte.Key32;
     if (!tte.Move.IsNullMove())
     {
         Move = tte.Move;
     }
     Depth       = tte.Depth;
     Generation  = tte.Generation;
     Value       = tte.Value;
     StaticValue = tte.StaticValue;
     Type        = tte.Type;
 }
        /// <summary>
        /// Stores a move in the transposition table. It will automatically detect the best cluster
        /// location to store it in. If a similar move already is present, a simple check if done to
        /// make sure it actually is an improvement of the previous move.
        /// </summary>
        /// <param name="key">The position key</param>
        /// <param name="value">The value of the move</param>
        /// <param name="type">The bound type, e.i. did it exceed alpha or beta</param>
        /// <param name="depth">The depth of the move</param>
        /// <param name="move">The move it self</param>
        /// <param name="statValue">The static value of the move</param>
        public void Store(HashKey key, int value, Bound type, sbyte depth, Move move, int statValue)
        {
            var ttc = FindCluster(key);

            var clusterIndex = 0;
            var found        = false;

            for (var i = 0; i < ttc.Cluster.Length; ++i)
            {
                if (ttc.Cluster[i].Key32 != 0 && ttc.Cluster[i].Key32 != key.UpperKey)
                {
                    continue;
                }

                clusterIndex = i;
                found        = true;
                break;
            }

            if (!found)
            {
                var index     = 0;
                var candidate = ttc.Cluster[index];
                var g         = _generation;
                var i         = 0;
                foreach (var ttEntry in ttc.Cluster)
                {
                    var(cc1, cc2, cc3, cc4) =
                        (candidate.Generation == g,
                         ttEntry.Generation == g,
                         ttEntry.Type == Bound.Exact,
                         ttEntry.Depth <= candidate.Depth);

                    if (cc1 && cc4 || !(cc2 || cc3) && (cc4 || cc1))
                    {
                        index     = i;
                        candidate = ttEntry;
                    }

                    i++;
                }

                clusterIndex = index;
            }

            var e = new TranspositionTableEntry(key.UpperKey, move, depth, _generation, value, statValue, type);

            ttc.Cluster[clusterIndex].Save(e);
        }
 public void Refresh(TranspositionTableEntry tte) => tte.Generation = _generation;
 public readonly bool Equals(TranspositionTableEntry other)
 => Key32 == other.Key32 && Generation == other.Generation;
 public TranspositionTableEntry(TranspositionTableEntry tte)
 {
     this = tte;
 }