Computer Chess Club Archives


Search

Terms

Messages

Subject: Re: Warning! Long demystified chess program (explosion of Eugene's posting)

Author: Eugene Nalimov

Date: 11:31:48 06/29/99

Go up one level in this thread


I looked at the program for 2 minutes, and here are my findings:

Macro a(x) in the original program is abs(x).
Macro m(x) in the original program is sign(x).

I'd recommend to revert back to macro calls. sign(v) is much more readable than
(v < 0 ? -1 : !!v).

Eugene

On June 29, 1999 at 11:41:16, Gareth McCaughan wrote:

>That's not very demystified. Try this. I've
>  - renamed all the functions
>  - reordered them a little
>  - renamed most of the variables
>  - added comments.
>
>There are some amusing points. I particularly like the initialisation
>of the constant variables formerly known as M,N,K and now called
>sixtyfour, seven and three, and the board representation.
>
>#include <stdio.h>
>#include <stdlib.h>
>static int v, w, to_move = -1, from, to, p, depth, o = 9999,
>           sixtyfour, seven, three, node_count, YY, ZZ,
>           pcolour[9999], in_check();
>
>/* The type |pore| is a Piece OR Evaluator. All will become clear soon. */
>typedef int (*pore) (); /* define type for function returning int */
>static pore ptype[9999];
>
>int try_move (int from, int to, pore D);
>
>/* Find the first piece on the line starting at |from| and going
> * in direction (v,w).
> */
>int scan_line (void) {
>  int S = (v < 0 ? -1 : !!v) + ((w < 0 ? -1 : !!w) << three);
>  if (!S)
>    return to;
>  for (v = from + S; v != to && !ptype[v]; v += S);
>  return v;
>}
>
>/* Pieces. A piece is a function void -> int. It does two things:
> * (1) sets ZZ to a value related to the piece's name
> * (2) return 0 if and only if it's legal to move that kind of
> *     piece from square |from| by (v,w). [CHECK DETAILS]
> * When one of these is called to determine legality,
> * to_move is +1/-1 according to whose move it is, and J is the
> * square we're hoping to move to. Some aspects of legality (e.g.,
> * can't capture your own pieces) are handled elsewhere.
> */
>int pawn (void) {
>  ZZ = three;
>  return
>    /* if |v!=0| we're not moving straight forward. */
>    v ? (v<0 ? -v : v) > 1 || w-to_move || !ptype[to]
>    /* otherwise, we are. */
>      : (w - to_move && (w - to_move * 2
>                   || ptype[from + to_move * (seven + 1)]
>                   || (to >> three) - three + (to_move - 1) / 2))
>        || ptype[to];
>}
>int rook (void) {
>  ZZ = 5;
>  return v * w || scan_line () - to;
>}
>int king (void) {
>  ZZ = -2;
>  return (v*v*v - v || w*w*w - w)
>         && (to-from - 2
>             || (from & seven) - 4
>             || (from >> three != (to_move - 1 ? seven : 0))
>             || ptype[from + 1]
>             || ptype[from + 2]
>             || ptype[from + three] != rook
>             || pcolour[from + three] * to_move < 0);
>}
>int queen (void) {
>  ZZ = three + 1;
>  return (v * w && (v < 0 ? -v : v) - (w < 0 ? -w : w)) || scan_line () - to;
>}
>int bishop (void) {
>  ZZ = -11;
>  return (v < 0 ? -v : v) - (w < 0 ? -w : w) || scan_line () - to;
>}
>int knight (void) {
>  ZZ = 1;
>  return (v * w < 0 ? -v * w : v * w) - 2;
>}
>
>/* |rand_real| exists only for |biased_rand|. The latter returns
> * a random variable that happens to have a mean of about 0.64.
> * (Maybe *exactly* 0.64. I'm too lazy to check.)
> */
>double rand_real (void) {
>  int max = 0x7fff;
>  return (double) (rand () & max) / (double) max;
>}
>double biased_rand (void) {
>  double i = 0, d;
>  while ((i += d = rand_real ()) < 1.0);
>  return d;
>}
>
>int illegal (int ur, int n, int x)
>{
>  from = ur;
>  to = n;
>  if (pcolour[from] != to_move || pcolour[to] == to_move)
>    return to + 1; /* never zero, that's all */
>  v = (to & seven) - (from & seven);
>  w = (to >> three) - (from >> three);
>  return
>    ptype[from] () || (x && try_move (from, to, in_check));
>}
>/* Call a piece function and return something non-0. Used to set ZZ.
> */
>int call_piece (int from) {
>  v = w = 0;
>  return ptype[from] () + three;
>}
>
>/* Return non-0 if -to_move is in check, else 0.
> */
>int in_check (void)
>{
>  int j = -1, i;
>  to_move = -to_move;
>  for (i = 0; i < sixtyfour; ++i) {
>    if (j < 0 && pcolour[i] == -to_move && call_piece (i) && ZZ == -2) {
>      /* Found -to_move's king. Start scanning the board again. */
>      j = i;
>      i = -1;
>    }
>    else if (j >= 0 && !illegal (i, j, 0))
>      return to_move = -to_move;
>  }
>  return !(to_move = -to_move);
>}
>
>int init_board (void)
>{
>  /* This really only needs to go up to 63. */
>  for (v = 0; v < 9999; ++v)
>    {
>      /* v>>three is rank number of square. Are we on either back rank? */
>      if (((v >> three) <= three ? v >> three
>                                 : seven - (v >> three)) == 0)
>        {
>          /* S is 0,1,2,3 for R,N,B,K/Q. */
>          int S = ((v & seven) <= three ? v & seven
>                                        : seven - (v & seven));
>          ptype[v] = !S ? rook :
>                 (S == 1 ? knight :
>                 (S == 2 ? bishop :
>                 (v & seven > three ? queen : king)));
>        }
>      /* Are we on next-to-back rank? */
>      else if (((v >> three) <= three ? v >> three
>                                      : seven - (v >> three)) == 1)
>        ptype[v] = pawn;
>      else
>        ptype[v] = 0;
>      pcolour[v] = !!ptype[v] * (28 - v);
>    }
>  return 0;
>}
>int print_board (void)
>{
>  int G = to_move, i;
>  to = 0;
>  for (i = 0; i < sixtyfour; ++i)
>    {
>      i % 8 || printf ("\n%4o ", i);
>      if ((to_move = pcolour[i] = (pcolour[i] < 0 ? -1 : !!pcolour[i])) &&
>call_piece (i))
>        printf ("%c ", ZZ + 93 + to_move * 16);
>      else
>        printf ("- ");
>    }
>  printf ("\n    ");
>  do
>    printf ("%2d", i++ & seven);
>  while (i & seven);
>  to_move = G;
>  printf ("\n");
>  return 0;
>}
>int make_move (int from, int to)
>{
>  /* Promotion: */
>  if ((ptype[to] = ptype[from]) == pawn
>       && ((to >> three) <= three ? to >> three
>                                 : seven - (to >> three)) == 0)
>    ptype[to] = queen;
>  /* Castling (forward or backward!): */
>  if (ptype[from] == king)
>    if (to - from == 2)
>      make_move (to + 1, to - 1);
>    else if (from - to == 2)
>      make_move (from - 1, from + 1);
>  pcolour[to] = pcolour[from];
>  ptype[from] = 0;
>  pcolour[from] = 0;
>  return 0;
>}
>int try_move (int from, int to, pore eval)
>{
>  int pcolour_to = pcolour[to], result;
>  pore ptype_to = ptype[to], ptype_from = ptype[from];
>  make_move (from, to);
>  result = eval ();
>  make_move (to, from);
>  ptype[to] = ptype_to; ptype[from] = ptype_from; pcolour[to] = pcolour_to;
>  return result;
>}
>int leaf_eval (void) {
>  int i, j, BZ = 0;
>  for (i = 0; i < sixtyfour; ++i) {
>    pore Z = ptype[i];
>    if (Z) {
>      /* |r| is a centrality term. |S| is a simple piece-square
>       * eval for piece |Z|.
>       */
>      int r = ((i >> three) <= three ? i >> three
>                                     : seven - (i >> three))
>              + ((i & seven) <= three ? i & seven
>                                        : seven - (i & seven)),
>          G = to_move,
>          S = Z == rook ? 88 :
>              (Z == pawn ? 11 + r + (pcolour[i] < 0 ? seven - (i >> three)
>                                              : (i >> three)) :
>              (Z == queen ? 124 - ((YY < 8
>                                    && ((i & seven) != three
>                                        || (i >> three) != (pcolour[i]>0 ? 0
>                                                                   : seven)))
>                                   ? sixtyfour : 0) :
>              (Z == bishop ? 41 + r :
>              (Z == king ? 9999 - r - r : 36 + r + r))));
>      /* mobility/capture term */
>      to_move = pcolour[i];
>      for (j = 0; j < sixtyfour; ++j)
>        if (!illegal (i, j, 0))
>          S += (pcolour[j] ? 5 : 1);
>      BZ += G == to_move ? S : -S;
>      to_move = G;
>    }
>  }
>  if (!(++node_count & sixtyfour - 1)) write (1, ".", 1);
>  return BZ;
>}
>int search (void)
>{
>  int i, Q = 0, XP = 0, c4096 = sixtyfour * sixtyfour, E = -9999, t, S = o;
>  if (!depth--)
>    return ++depth + leaf_eval ();
>  for (i = 0; i < c4096; ++i)
>    if (!illegal (i >> three + three, i & sixtyfour - 1, 1)) {
>      to_move = -to_move;
>      o = -E;
>      t = -try_move (i >> three + three, i & sixtyfour - 1, search);
>      to_move = -to_move;
>      if (t > E) {
>        ++XP; /* there was a legal move */
>        Q = i;
>        E = t;
>        if (E >= S) return ++depth, E;
>      }
>    }
>  if (!XP)
>    E = in_check ()? -9999 + 1 : 0;
>  p = Q;
>  return ++depth, E;
>}
>int play_game (void)
>{
>  int i, j, T = 0;
>  for (;;)
>    {
>      print_board ();
>      o = 9999;
>      do
>        {
>          printf ("\n%d %d %d %s ", node_count, T, leaf_eval (), in_check ()?
>"!" : ">");
>          fflush(stdout);
>        }
>      while (scanf ("%o%o", &i, &j) != 2 || illegal (i, j, 1));
>      make_move (i, j);
>      print_board ();
>      node_count = 0;
>      ++YY;
>      to_move = -to_move;
>      T = search ();
>      i = p >> (three << 1);
>      j = p & (sixtyfour - 1);
>      if (illegal (i, j, 1))
>        {
>          puts("Rats!");
>          return 0;
>        }
>      make_move (i, j);
>      to_move = -to_move;
>      if (T > sixtyfour * sixtyfour)
>        puts("\nHar har.");
>    }
>  return 0;
>}
>#include <time.h>
>main (int ac, char **av)
>{
>  long time (), j = time (&j);
>  double i = 0;
>  srand ((int) j);
>  /* The following 4 lines are almost certain to set sixtyfour=64. */
>  for (sixtyfour = 0; sixtyfour <= 9999; ++sixtyfour) i += biased_rand ();
>  sixtyfour = i / 100;
>  if (sixtyfour & 3) ++sixtyfour;
>  if (sixtyfour & 1) --sixtyfour;
>  /* So the following 2 lines will set seven=8, then seven=7, then three=3. */
>  for (seven = 1; seven * seven < sixtyfour; ++seven);
>  three = --seven / 2;
>  depth = ac > 1 ? atoi (av[1]) : 2;
>  init_board ();
>  play_game ();
>  return 0;
>}



This page took 0 seconds to execute

Last modified: Thu, 15 Apr 21 08:11:13 -0700

Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.