Complicating code in C#

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

User avatar
mvanthoor
Posts: 1784
Joined: Wed Jul 03, 2019 4:42 pm
Location: Netherlands
Full name: Marcel Vanthoor

Re: Complicating code in C#

Post by mvanthoor »

A board (or squares) in its simplest form is just an array of 64 bytes holding a number that represents the piece that is in there.
Author of Rustic, an engine written in Rust.
Releases | Code | Docs | Progress | CCRL
Henk
Posts: 7216
Joined: Mon May 27, 2013 10:31 am

Re: Complicating code in C#

Post by Henk »

Need not be an array. Might be a set when array is sparse. May be useful in irregular chess variations.
Henk
Posts: 7216
Joined: Mon May 27, 2013 10:31 am

Re: Complicating code in C#

Post by Henk »

mvanthoor wrote: Fri Feb 05, 2021 12:05 pm A board (or squares) in its simplest form is just an array of 64 bytes holding a number that represents the piece that is in there.
Don't know if you are going to implement bitboards by the way. Bitboards start of all misery. Means much more code to maintain.
Henk
Posts: 7216
Joined: Mon May 27, 2013 10:31 am

Re: Complicating code in C#

Post by Henk »

Maybe better say that coordinate and square are the same thing.

So all properties I assigned to square might have been assigned to coordinate as well.

In case you don't use bitboards you don't need perfect hash key data per coordinate for move generation.

And what about a PieceCoordinateTable.

In plain movegeneration I don't need access to eval properties per coord.
In evaluation I don't need acces to move generation properties per coord.
Henk
Posts: 7216
Joined: Mon May 27, 2013 10:31 am

Re: Complicating code in C#

Post by Henk »

Really terrible to make it work/compile

Code: Select all

 
 public class Squares<T> : ISquares<T> where T : ISquare
  {
    ..
      public IList<T> BuildSquares(ISquareBuilder<T> squareBuilder)
        {
            var board = new List<T>();
            for (int i = 0; i <= NSQUARES -1; i++)
            {
                var square = squareBuilder.BuildSquare();
                board.Add(square);
                square.Init((coord)i);
            }
            return board;
        }
        
  

Before this I used new T() instead of a squarebuilder and added a new constraint to the class signature.
But then I could not create a ISquares<ISquareEval> but only a ISquares<SquareEval>. And if I only could create ISquares<SquareEval> I had to repair another zillion of compile errors.


That is the advantage from re-starting from scratch: you don't need to repair zillions compile errors when you make a mistake. Although when restarting from scratch you have to re-type, re-copy, re-invent the wheel.
Henk
Posts: 7216
Joined: Mon May 27, 2013 10:31 am

Re: Complicating code in C#

Post by Henk »

Did not work. Still need extra class to assign movegeneration data per square.
Ugly! Something went wrong.

Code: Select all

    public class BoardSquaresMoveGen : Squares<ISquareMoveGen>
    {
        public BoardSquaresMoveGen(): base(new SquareMoveGenBuilder(), 8, 8)
        {
            InitAllMoves();
        }

        /// <summary>
        /// Assumes all squares are initialized 
        /// </summary>
        public void InitAllMoves()
        {
          for (int i = 0; i <= NSQUARES - 1; i++)
            {
                var field = this[i];
                field.InitMoves(this);
            }
        }
   }
User avatar
mvanthoor
Posts: 1784
Joined: Wed Jul 03, 2019 4:42 pm
Location: Netherlands
Full name: Marcel Vanthoor

Re: Complicating code in C#

Post by mvanthoor »

To some extend, this topic is becoming hilarious. What engine is this by the way? Is it private, open source, can it be found in the CCRL-list, and/or is the code somewhere online?
Author of Rustic, an engine written in Rust.
Releases | Code | Docs | Progress | CCRL
Henk
Posts: 7216
Joined: Mon May 27, 2013 10:31 am

Re: Complicating code in C#

Post by Henk »

It's about Skipper. Private engine. Only used for testing some software development ideas.
Maybe best not to recommend writing generic code. For there are always exceptions that don't fit in.
Perhaps generic code only possible for lowest level.

For movegeneration you need to know the bordersquares of the board. So it looks like can't do it per square.
Henk
Posts: 7216
Joined: Mon May 27, 2013 10:31 am

Re: Complicating code in C#

Post by Henk »

Maybe only argument to use properties is to reduce length of paramerlist.
But I don't like it that a class/structure/record contains methods that do not use all its properties.

Properties behaving as bad as semi global variables. At least they should be all immutable.

So maybe make a method static unless number of parameters greater than three and some methods share the same parameter. In that case create a class with that parameter as a property.

By the way biggest problem is methods being too long. So I should repair that first.
Henk
Posts: 7216
Joined: Mon May 27, 2013 10:31 am

Re: Complicating code in C#

Post by Henk »

Here an example of bad code to be rewritten. Man you can spend weeks/months/years on rewriting source code.

Code: Select all

  
 public static IImmutableList<IMoveBase> ComputePawnDirectionMoves(ICoord coord, IPieceColor color,
            IMoveFactory mvFactory, ISquares<ISquareMoveGen> boardSquares, PawnDirection dir)
        {
            var nColumns = boardSquares.nColumns;
            var pieceSort = ConvertToPieceSort(Kind.Pawn_Kind, color);
      
            var firstRow = color == White() ? 0 : LASTROW;
            var lastRow = color == White() ? LASTROW : 0;
            var epRow = color == White() ? 4 : 3;

            var square = boardSquares[coord];
            int rowNr2 = square.RowNr;
            if (rowNr2 == 0 || rowNr2 == lastRow)
                return null;
            var dirMoves = CreateBuilder<IMoveBase>();
            var colorValue = ABSearch.Eval(color);
            if (dir == LEFT || dir == EP_LEFT)
            {
                if (square.ColNr > 0 &&
                    Less(color, square.RowNr, lastRow)
                    )
                {
                    int newPos = (int)square.Coord + colorValue * nColumns - 1;
                    if (dir == LEFT)
                    {
                        if (Less(color, square.RowNr, lastRow - ABSearch.Eval(color)))
                        {
                            var mv = mvFactory.BuildMove(square.Coord2, boardSquares[(int)newPos].Coord2, pieceSort);
                            dirMoves.Add(mv);
                        }
                        else
                        {
                            AddPromotionMoves(square, mvFactory, pieceSort, boardSquares, dirMoves, newPos);
                        }
                    }
                    else
                    {
                        Debug.Assert(dir == EP_LEFT);
                        if (square.RowNr == epRow)
                        {
                            var mv = mvFactory.BuildEPMove(square.Coord2, boardSquares[(int)newPos].Coord2, pieceSort);
                            dirMoves.Add(mv);
                        }
                    }
                }
            }
            else if (dir == FRONT)
            {
                int rowNr = square.RowNr;
                if (rowNr == lastRow - colorValue
                   )
                {
                    int newPos = (int)square.Coord + colorValue * nColumns;
                    AddPromotionMoves(square, mvFactory, pieceSort, boardSquares, dirMoves, newPos);
                }
                else
                {
                    int nSteps = 1;
                    if (rowNr == firstRow + colorValue)
                    {
                        nSteps = 2;
                    }

                    for (int i = 1; i <= nSteps; i++)
                    {
                        int newPos = (int)square.Coord + i * colorValue * nColumns;
                        var field = boardSquares[newPos];
                        dirMoves.Add(PawnFrontMove(boardSquares, mvFactory, pieceSort, square.Coord2, field.Coord2));
                    }
                }
            }
            else if (dir == RIGHT || dir == EP_RIGHT)
            {
                if (square.ColNr < LASTCOLUMN
                    && Less(color, square.RowNr, lastRow))
                {
                    int newPos = (int)square.Coord + colorValue * nColumns + 1;
                    if (dir == RIGHT)
                    {
                        if (Less(color, square.RowNr, lastRow - colorValue))
                            dirMoves.Add(mvFactory.BuildMove(square.Coord2, boardSquares[(int)newPos].Coord2, pieceSort));
                        else
                        {
                            AddPromotionMoves(square, mvFactory, pieceSort, boardSquares, dirMoves, newPos);
                        }
                    }
                    else if (square.RowNr == epRow)
                    {
                        var mv = mvFactory.BuildEPMove(square.Coord2, boardSquares[(int)newPos].Coord2, pieceSort);
                        dirMoves.Add(mv);
                    }
                }
            }
            return dirMoves.ToImmutableList();

            bool Less(IPieceColor color2, int x, int y)
            =>
                color2 == White() ? x < y : x > y;

        }