Complicating code in C#

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

Henk
Posts: 7216
Joined: Mon May 27, 2013 10:31 am

Re: Complicating code in C#

Post by Henk »

Result after rewrite. In reality class is about 190 lines of code. But methods fit on my screen.

Code: Select all

       ...
       public PawnSquareDirectionMovesBuilder(IMoveFactory mvFactory, ISquares<ISquareMoveGen> boardSquares)
        {
            MVFactory = mvFactory;
            BoardSquares = boardSquares;
        }

        public IImmutableList<IMoveBase> BuildPawnSquareDirectionMoves(
            ICoord coord, IPieceColor color,PawnDirection dir)
        {
            var lastRow = color == White() ? LASTROW : 0;
            var square = BoardSquares[coord];
            int rowNr = square.RowNr;
            if (rowNr == 0 || rowNr == lastRow)
                return null;                    
            switch (dir)
            {
                case LEFT:
                case RIGHT:
                        return BuildNonEPCaptures(color, square, dir);
                case EP_LEFT:
                case EP_RIGHT:
                        return BuildEPCaptures(color, square, dir);
                case FRONT:
                        return BuildPawnFrontMoves(color,  square);
                default:
                    return null;
            }
        }
        ...
  
Might as well have used ISquares<ISquare> BoardSquares. But strangely C# does not see that ISquares<ISquareMoveGen> is an ISquares<ISquare> while my code contains public interface ISquareMoveGen: ISquare
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: Complicating code in C#

Post by Sven »

Henk wrote: Tue Feb 16, 2021 12:44 pm Result after rewrite. In reality class is about 190 lines of code. But methods fit on my screen.

Code: Select all

       ...
       public PawnSquareDirectionMovesBuilder(IMoveFactory mvFactory, ISquares<ISquareMoveGen> boardSquares)
        {
            MVFactory = mvFactory;
            BoardSquares = boardSquares;
        }

        public IImmutableList<IMoveBase> BuildPawnSquareDirectionMoves(
            ICoord coord, IPieceColor color,PawnDirection dir)
        {
            var lastRow = color == White() ? LASTROW : 0;
            var square = BoardSquares[coord];
            int rowNr = square.RowNr;
            if (rowNr == 0 || rowNr == lastRow)
                return null;                    
            switch (dir)
            {
                case LEFT:
                case RIGHT:
                        return BuildNonEPCaptures(color, square, dir);
                case EP_LEFT:
                case EP_RIGHT:
                        return BuildEPCaptures(color, square, dir);
                case FRONT:
                        return BuildPawnFrontMoves(color,  square);
                default:
                    return null;
            }
        }
        ...
  
Might as well have used ISquares<ISquare> BoardSquares. But strangely C# does not see that ISquares<ISquareMoveGen> is an ISquares<ISquare> while my code contains public interface ISquareMoveGen: ISquare
C<Derived> is not automatically a derived class of C<Base>. That is not specific for C#.
Sven Schüle (engine author: Jumbo, KnockOut, Surprise)
Henk
Posts: 7216
Joined: Mon May 27, 2013 10:31 am

Re: Complicating code in C#

Post by Henk »

Sven wrote: Tue Feb 16, 2021 9:04 pm
Henk wrote: Tue Feb 16, 2021 12:44 pm Result after rewrite. In reality class is about 190 lines of code. But methods fit on my screen.

Code: Select all

       ...
       public PawnSquareDirectionMovesBuilder(IMoveFactory mvFactory, ISquares<ISquareMoveGen> boardSquares)
        {
            MVFactory = mvFactory;
            BoardSquares = boardSquares;
        }

        public IImmutableList<IMoveBase> BuildPawnSquareDirectionMoves(
            ICoord coord, IPieceColor color,PawnDirection dir)
        {
            var lastRow = color == White() ? LASTROW : 0;
            var square = BoardSquares[coord];
            int rowNr = square.RowNr;
            if (rowNr == 0 || rowNr == lastRow)
                return null;                    
            switch (dir)
            {
                case LEFT:
                case RIGHT:
                        return BuildNonEPCaptures(color, square, dir);
                case EP_LEFT:
                case EP_RIGHT:
                        return BuildEPCaptures(color, square, dir);
                case FRONT:
                        return BuildPawnFrontMoves(color,  square);
                default:
                    return null;
            }
        }
        ...
  
Might as well have used ISquares<ISquare> BoardSquares. But strangely C# does not see that ISquares<ISquareMoveGen> is an ISquares<ISquare> while my code contains public interface ISquareMoveGen: ISquare
C<Derived> is not automatically a derived class of C<Base>. That is not specific for C#.
https://docs.microsoft.com/en-us/dotnet ... ravariance
Probably have to implement covariance interface yourself unless it is a system type like list or so. I don't know yet.
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: Complicating code in C#

Post by Sven »

Did you make ISquares covariant on its type parameter?
Sven Schüle (engine author: Jumbo, KnockOut, Surprise)
Henk
Posts: 7216
Joined: Mon May 27, 2013 10:31 am

Re: Complicating code in C#

Post by Henk »

No I had never heard of covariant. I changed it, Only had to add 'out'. That's all to make it work.
Don't understand why compiler or intellisense does not give a hint.

Code: Select all

  
public interface ISquares<out T> 
 
Henk
Posts: 7216
Joined: Mon May 27, 2013 10:31 am

Re: Complicating code in C#

Post by Henk »

By the way in essence a square is an int or ulong. Depends on how much squares you need.
For standard chess no more than 64.
Henk
Posts: 7216
Joined: Mon May 27, 2013 10:31 am

Re: Complicating code in C#

Post by Henk »

Again I have trouble with C#.

I want to write

Code: Select all

enum Angle { 0, 45, 90, 135, 180}
etc.
But that does not compile. So I have to use this workaround which I don't like.

Code: Select all

enum Angle { Right, RightUp, Up, LeftUp, Left, LeftDown, Down, RightDown }
Alternative is to define a class Angle. But that's too much.

O wait I can use this:

Code: Select all

enum Angle { A_0, A_45, A_90, A_135, A_180}
Not very readable

Or maybe

Code: Select all

enum Angle { _0, _45, _90, _135, _180}
Have not tried but still looks silly/ugly
Henk
Posts: 7216
Joined: Mon May 27, 2013 10:31 am

Re: Complicating code in C#

Post by Henk »

Hmm bit communistic code. Maybe better have used operator overloading.

Code: Select all

 
      public ICoordSet QueenMoves(ICoordSet occupiers)
        =>
            StraightMoves(occupiers)
            .Union(DiagonalMoves(occupiers));
 
Henk
Posts: 7216
Joined: Mon May 27, 2013 10:31 am

Re: Complicating code in C#

Post by Henk »

Trying to understand bitboard movegen. I get:

Square64MoveGen:
Should have two magic numbers + keyLengths (that is number of bits). One for diagonal and one for straight moves.
Has two hastables: one for diagonal and one for straight moves
Number of buckets of each hash table = Pow(2, keyLength)

Code: Select all

hashKey = (int)((occupancy * magic) >> (64 - nBitsKeyLength));
hastable returns the coords of the diagonal/vertical moves for a given occupancy for a bishop/rook/queen on this square.

By the way I don't understand that code or formula for computing the hashkey.

But I am trying to rewrite it and implement it this way and see if it still works.

I forgot how the magic numbers were created. So If I would change the number of squares I first have to implement code to generate magic numbers or not use magic bitboard movegeneration at all.
Henk
Posts: 7216
Joined: Mon May 27, 2013 10:31 am

Re: Complicating code in C#

Post by Henk »

A similar formula I used earlier to map a bitboard into an index of a table with 64 entries.
So looks like magic numbers are just debruijn constants.

Code: Select all

 
 const UInt64 debruijn64 = 157587932685088877;
 
 public int Index(ulong bb)
 {
            unchecked
            {
                return index[((bb * debruijn64) >> 58)];
            }
 }