예제 #1
0
TEST(SquareTest, testMake)
{
	ASSERT_EQ(make_square(File::FILE_9, Rank::RANK_9), Square::SQ_99);
	ASSERT_EQ(make_square(File::FILE_1, Rank::RANK_1), Square::SQ_11);

	ASSERT_EQ(make_square((File)0, (Rank)0), Square::SQ_91);
	ASSERT_EQ(make_square((File)8, (Rank)8), Square::SQ_19);
}
예제 #2
0
void	backtracking(struct s_list *list, size_t nb_jeton)
{
	char	**square;
	int		carre;

	carre = fake_sqrt(nb_jeton * 4);
	square = make_square(carre);
	while (brute_force(list, square) != 1)
		square = make_square(carre++);
	display(square);
}
예제 #3
0
파일: pawns.cpp 프로젝트: Jekaa/Stockfish
Value Entry::shelter_storm(const Position& pos, Square ksq) {

    const Color Them = (Us == WHITE ? BLACK : WHITE);
    const Bitboard Edges = (FileABB | FileHBB) & (Rank2BB | Rank3BB);

    Bitboard b = pos.pieces(PAWN) & (in_front_bb(Us, rank_of(ksq)) | rank_bb(ksq));
    Bitboard ourPawns = b & pos.pieces(Us);
    Bitboard theirPawns = b & pos.pieces(Them);
    Value safety = MaxSafetyBonus;
    File kf = std::max(FILE_B, std::min(FILE_G, file_of(ksq)));

    for (File f = kf - File(1); f <= kf + File(1); ++f)
    {
        b = ourPawns & file_bb(f);
        Rank rkUs = b ? relative_rank(Us, backmost_sq(Us, b)) : RANK_1;

        b  = theirPawns & file_bb(f);
        Rank rkThem = b ? relative_rank(Us, frontmost_sq(Them, b)) : RANK_1;

        if (   (Edges & make_square(f, rkThem))
                && file_of(ksq) == f
                && relative_rank(Us, ksq) == rkThem - 1)
            safety += 200;
        else
            safety -=  ShelterWeakness[rkUs]
                       + StormDanger[rkUs   == RANK_1   ? 0 :
                                     rkThem != rkUs + 1 ? 1 : 2][rkThem];
    }

    return safety;
}
예제 #4
0
파일: sys2.c 프로젝트: Macvol/OldBundle
int paint_square(int color,int num)
{
if(num==1)
{
make_square(color,x_p,y_p);
return 0;
}
if(num==2)
{
make_square(color,x_p,y_p+6);
return 0;
}
if(num==3)
{
make_square(color,x_p,y_p+12);
return 0;
}
if(num==4)
{
make_square(color,x_p+3,y_p);
return 0;
}
if(num==5)
{
make_square(color,x_p+3,y_p+6);
return 0;
}
if(num==6)
{
make_square(color,x_p+3,y_p+12);
return 0;
}
if(num==7)
{
make_square(color,x_p+6,y_p);
return 0;
}
if(num==8)
{
make_square(color,x_p+6,y_p+6);
return 0;
}
if(num==9)
{
make_square(color,x_p+6,y_p+12);
return 0;
}


}
예제 #5
0
void  backtracking(struct s_list *list)
{
  char **square;

  (void)*list;
  square = make_square(DEFAULT);
  display(square);
  brute_force(list, square);
}
/*^-----------------------------------------------------------------------------
| PF
| mod_image_gen_mksquare : command function for user command "mksquare"
|   struct lxrcmd *c: Command-control-block calling this command function.
|
|
|
| Returns : PASS/FAIL
+-----------------------------------------------------------------------------*/
PF mod_image_gen_mksquare ( struct lxrcmd *c ) 
{

    make_square ( c->args[1].v.s, c->args[2].v.ld, c->args[3].v.ld, c->args[4].v.f, c->args[5].v.f, c->args[6].v.f);   


    c->results = NULL;   // NULL results block. Change as appropriate


    return(PASS);
}
예제 #7
0
Value EvaluationFunction<KRKP>::apply(const Position& pos) const {

  assert(pos.non_pawn_material(strongerSide) == RookValueMidgame);
  assert(pos.piece_count(strongerSide, PAWN) == 0);
  assert(pos.non_pawn_material(weakerSide) == 0);
  assert(pos.piece_count(weakerSide, PAWN) == 1);

  Square wksq, wrsq, bksq, bpsq;
  int tempo = (pos.side_to_move() == strongerSide);

  wksq = pos.king_square(strongerSide);
  wrsq = pos.piece_list(strongerSide, ROOK, 0);
  bksq = pos.king_square(weakerSide);
  bpsq = pos.piece_list(weakerSide, PAWN, 0);

  if (strongerSide == BLACK)
  {
      wksq = flip_square(wksq);
      wrsq = flip_square(wrsq);
      bksq = flip_square(bksq);
      bpsq = flip_square(bpsq);
  }

  Square queeningSq = make_square(square_file(bpsq), RANK_1);
  Value result;

  // If the stronger side's king is in front of the pawn, it's a win
  if (wksq < bpsq && square_file(wksq) == square_file(bpsq))
      result = RookValueEndgame - Value(square_distance(wksq, bpsq));

  // If the weaker side's king is too far from the pawn and the rook,
  // it's a win
  else if (   square_distance(bksq, bpsq) - (tempo ^ 1) >= 3
           && square_distance(bksq, wrsq) >= 3)
      result = RookValueEndgame - Value(square_distance(wksq, bpsq));

  // If the pawn is far advanced and supported by the defending king,
  // the position is drawish
  else if (   square_rank(bksq) <= RANK_3
           && square_distance(bksq, bpsq) == 1
           && square_rank(wksq) >= RANK_4
           && square_distance(wksq, bpsq) - tempo > 2)
      result = Value(80 - square_distance(wksq, bpsq) * 8);

  else
      result =  Value(200)
              - Value(square_distance(wksq, bpsq + DELTA_S) * 8)
              + Value(square_distance(bksq, bpsq + DELTA_S) * 8)
              + Value(square_distance(bpsq, queeningSq) * 8);

  return strongerSide == pos.side_to_move() ? result : -result;
}
예제 #8
0
struct body * make_body(int x, int y)
{
    struct body *b = malloc(sizeof(struct body));
    if (b) {
        b->part = make_square(x, y, TILE, green);
        b->rest = NULL;
        if (!(b->part)) {
            free(b);
            b = NULL;
        }
    }
    return b;
}
예제 #9
0
ScaleFactor ScalingFunction<KBPsK>::apply(const Position& pos) const {

  assert(pos.non_pawn_material(strongerSide) == BishopValueMidgame);
  assert(pos.piece_count(strongerSide, BISHOP) == 1);
  assert(pos.piece_count(strongerSide, PAWN) >= 1);

  // No assertions about the material of weakerSide, because we want draws to
  // be detected even when the weaker side has some pawns.

  Bitboard pawns = pos.pieces(PAWN, strongerSide);
  File pawnFile = square_file(pos.piece_list(strongerSide, PAWN, 0));

  // All pawns are on a single rook file ?
  if (   (pawnFile == FILE_A || pawnFile == FILE_H)
      && (pawns & ~file_bb(pawnFile)) == EmptyBoardBB)
  {
      Square bishopSq = pos.piece_list(strongerSide, BISHOP, 0);
      Square queeningSq = relative_square(strongerSide, make_square(pawnFile, RANK_8));
      Square kingSq = pos.king_square(weakerSide);

      if (  !same_color_squares(queeningSq, bishopSq)
          && file_distance(square_file(kingSq), pawnFile) <= 1)
      {
          // The bishop has the wrong color, and the defending king is on the
          // file of the pawn(s) or the neighboring file. Find the rank of the
          // frontmost pawn.
          Rank rank;
          if (strongerSide == WHITE)
          {
              for (rank = RANK_7; (rank_bb(rank) & pawns) == EmptyBoardBB; rank--) {}
              assert(rank >= RANK_2 && rank <= RANK_7);
          }
          else
          {
              for (rank = RANK_2; (rank_bb(rank) & pawns) == EmptyBoardBB; rank++) {}
              rank = Rank(rank ^ 7);  // HACK to get the relative rank
              assert(rank >= RANK_2 && rank <= RANK_7);
          }
          // If the defending king has distance 1 to the promotion square or
          // is placed somewhere in front of the pawn, it's a draw.
          if (   square_distance(kingSq, queeningSq) <= 1
              || relative_rank(strongerSide, kingSq) >= rank)
              return SCALE_FACTOR_ZERO;
      }
  }
  return SCALE_FACTOR_NONE;
}
예제 #10
0
int main() {
	char buf[80];
	struct sockaddr_in s_addr;
	int i, sock;

	if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
		fprintf(stderr, "Failed to create socket\n");
		exit(1);
	}

	s_addr.sin_family = AF_INET;
	s_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
	s_addr.sin_port = htons(55443);

	if (connect(sock, (struct sockaddr *) &s_addr, sizeof(s_addr)) < 0) {
		fprintf(stderr, "Failed to connect socket\n");
		exit(1);
	}
	sleep(1);

	make_square(buf, sock);

	return 0;
}
Move move_from_san(Position &pos, const std::string &movestr) {
  assert(pos.is_ok());

  MovePicker mp = MovePicker(pos, false, MOVE_NONE, MOVE_NONE, MOVE_NONE,
                             MOVE_NONE, OnePly);

  // Castling moves
  if(movestr == "O-O-O") {
    Move m;
    while((m = mp.get_next_move()) != MOVE_NONE)
      if(move_is_long_castle(m) && pos.move_is_legal(m))
        return m;
    return MOVE_NONE;
  }
  else if(movestr == "O-O") {
    Move m;
    while((m = mp.get_next_move()) != MOVE_NONE)
      if(move_is_short_castle(m) && pos.move_is_legal(m))
        return m;
    return MOVE_NONE;
  }

  // Normal moves
  const char *cstr = movestr.c_str();
  const char *c;
  char *cc;
  char str[10];
  int i;

  // Initialize str[] by making a copy of movestr with the characters
  // 'x', '=', '+' and '#' removed.
  cc = str;
  for(i=0, c=cstr; i<10 && *c!='\0' && *c!='\n' && *c!=' '; i++, c++)
    if(!strchr("x=+#", *c)) {
      *cc = strchr("nrq", *c)? toupper(*c) : *c;
      cc++;
    }
  *cc = '\0';

  int left = 0, right = strlen(str) - 1;
  PieceType pt = NO_PIECE_TYPE, promotion;
  Square to;
  File fromFile = FILE_NONE;
  Rank fromRank = RANK_NONE;

  // Promotion?
  if(strchr("BNRQ", str[right])) {
    promotion = piece_type_from_char(str[right]);
    right--;
  }
  else
    promotion = NO_PIECE_TYPE;

  // Find the moving piece:
  if(left < right) {
    if(strchr("BNRQK", str[left])) {
      pt = piece_type_from_char(str[left]);
      left++;
    }
    else
      pt = PAWN;
  }

  // Find the to square:
  if(left < right) {
    if(str[right] < '1' || str[right] > '8' ||
       str[right-1] < 'a' || str[right-1] > 'h')
      return MOVE_NONE;
    to = make_square(file_from_char(str[right-1]), rank_from_char(str[right]));
    right -= 2;
  }
  else
    return MOVE_NONE;

  // Find the file and/or rank of the from square:
  if(left <= right) {
    if(strchr("abcdefgh", str[left])) {
      fromFile = file_from_char(str[left]);
      left++;
    }
    if(strchr("12345678", str[left]))
      fromRank = rank_from_char(str[left]);
  }

  // Look for a matching move:
  Move m, move = MOVE_NONE;
  int matches = 0;

  while((m = mp.get_next_move()) != MOVE_NONE) {
    bool match = true;
    if(pos.type_of_piece_on(move_from(m)) != pt)
      match = false;
    else if(move_to(m) != to)
      match = false;
    else if(move_promotion(m) != promotion)
      match = false;
    else if(fromFile != FILE_NONE && fromFile != square_file(move_from(m)))
      match = false;
    else if(fromRank != RANK_NONE && fromRank != square_rank(move_from(m)))
      match = false;
    if(match) {
      move = m;
      matches++;
    }
  }

  if(matches == 1)
    return move;
  else
    return MOVE_NONE;
}
예제 #12
0
int main(int argc, char *argv[])
{
    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0) {
        fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError());
        SDL_Quit();
        return -1;
    }
    SDL_Window *win = SDL_CreateWindow("snake", 50, 50, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_OPENGL);
    if (!win) {
        fprintf(stderr, "Unable to initialize window: %s\n", SDL_GetError());
        SDL_Quit();
        return -1;
    }
    SDL_GLContext gl_con = SDL_GL_CreateContext(win);
    struct square *head = make_square(0, 0, TILE, brown);
    struct square *fruit = make_square(0, 0, TILE, red);
    if (!head || !fruit) {
        fprintf(stderr, "Unable to allocate memory for square struct.");
        if (head) {
            free(head);
        }
    }
    struct body *snake_body = NULL;
    reposition_fruit(fruit);
    enum direction snake_d = LEFT;
    int previousx;
    int previousy;
    if (gl_con == NULL) {
        fprintf(stderr, "Unable to initialize gl context: %s\n", SDL_GetError());
        SDL_DestroyWindow(win);
        SDL_Quit();
        return -1;
    }
    SDL_Event event;
    while (1) {
        while (SDL_PollEvent(&event)) {
            if (event.type == SDL_QUIT) {
                goto end;
            }
            else if (event.type == SDL_KEYDOWN) {
                switch (event.key.keysym.sym) {
                case SDLK_ESCAPE:
                    goto end;
                    break;
                case SDLK_UP:
                    snake_d = UP;
                    break;
                case SDLK_DOWN:
                    snake_d = DOWN;
                    break;
                case SDLK_LEFT:
                    snake_d = LEFT;
                    break;
                case SDLK_RIGHT:
                    snake_d = RIGHT;
                    break;
                }
            }
        }
        previousx = head->x;
        previousy = head->y;
        switch (snake_d) {
        case UP:
            head->y += TILE;
            break;
        case DOWN:
            head->y -= TILE;
            break;
        case LEFT:
            head->x -= TILE;
            break;
        case RIGHT:
            head->x += TILE;
            break;
        }
        if (is_intersect_body(head, snake_body)) {
            goto end;
        }
        step_body(&snake_body, previousx, previousy);
        if (head->y > SCREEN_HEIGHT - TILE || head->y < -1 * SCREEN_HEIGHT || head->x > SCREEN_WIDTH - TILE || head->x < -1 * SCREEN_WIDTH) {
            goto end;
        }
        else if (is_intersect(head, fruit)) {
            add_body(&snake_body, previousx, previousy);
            do {
                reposition_fruit(fruit);
            } while (is_intersect(head, fruit) || is_intersect_body(fruit, snake_body));
        }
	cap_game_fps(display, win, head, snake_body, fruit);
    }
end:
    free(head);
    clean_body(snake_body);
    free(fruit);
    SDL_GL_DeleteContext(gl_con);
    SDL_Quit();
    return 0;
}
예제 #13
0
int
main(int argc, char ** argv)
{
	SWFMovie mo;
	SWFDisplayItem it1, it2, it3;
	SWFShape sh1, sh2, sh3;
	int framenum;

	argc=argc; argv=argv; /* unused... */

	/*********************************************
	 *
	 * Initialization
	 *
	 *********************************************/

	puts("Setting things up");

	Ming_init();
        Ming_useSWFVersion (OUTPUT_VERSION);
	Ming_setScale(20.0); 
 
	mo = newSWFMovie();

	/*****************************************************
	 *
	 * Add the square named 
	 *
	 *****************************************************/

	SWFMovie_setDimension(mo, 100, 100);

#define FRAMESGAP 5

	sh1 = make_square(10, 10, 20, 20, 255, 0, 0);
	it1 = SWFMovie_add(mo, (SWFBlock)sh1);
	SWFDisplayItem_setDepth(it1, 1);
	SWFDisplayItem_setName(it1, "Name1");

	for (framenum=0; framenum<FRAMESGAP; framenum++) {
		SWFMovie_nextFrame(mo); 
	}

	sh2 = make_square(35, 10, 20, 20, 0, 255, 0);
	it2 = SWFMovie_add(mo, (SWFBlock)sh2);
	SWFDisplayItem_setDepth(it2, 2);
	SWFDisplayItem_setName(it2, "Name2");

	for (framenum=0; framenum<FRAMESGAP; framenum++) {
		SWFMovie_nextFrame(mo); 
	}

	sh3 = make_square(10, 35, 45, 20, 0, 0, 255);
	it3 = SWFMovie_add(mo, (SWFBlock)sh3);
	SWFDisplayItem_setDepth(it3, 3);
	SWFDisplayItem_setName(it3, "Name3");

	for (framenum=0; framenum<FRAMESGAP; framenum++) {
		SWFMovie_nextFrame(mo); 
	}

	SWFMovie_remove(mo, it1);

	for (framenum=0; framenum<FRAMESGAP; framenum++) {
		SWFMovie_nextFrame(mo); 
	}

	SWFMovie_remove(mo, it2);

	for (framenum=0; framenum<FRAMESGAP; framenum++) {
		SWFMovie_nextFrame(mo); 
	}

	SWFMovie_remove(mo, it3);

	puts("Saving " OUTPUT_FILENAME );

	SWFMovie_nextFrame(mo); /* showFrame */

	SWFMovie_save(mo, OUTPUT_FILENAME);

	return 0;
}
예제 #14
0
ScaleFactor ScalingFunction<KBPPKB>::apply(const Position& pos) const {

  assert(pos.non_pawn_material(strongerSide) == BishopValueMidgame);
  assert(pos.piece_count(strongerSide, BISHOP) == 1);
  assert(pos.piece_count(strongerSide, PAWN) == 2);
  assert(pos.non_pawn_material(weakerSide) == BishopValueMidgame);
  assert(pos.piece_count(weakerSide, BISHOP) == 1);
  assert(pos.piece_count(weakerSide, PAWN) == 0);

  Square wbsq = pos.piece_list(strongerSide, BISHOP, 0);
  Square bbsq = pos.piece_list(weakerSide, BISHOP, 0);

  if (same_color_squares(wbsq, bbsq))
      // Not opposite-colored bishops, no scaling
      return SCALE_FACTOR_NONE;

  Square ksq = pos.king_square(weakerSide);
  Square psq1 = pos.piece_list(strongerSide, PAWN, 0);
  Square psq2 = pos.piece_list(strongerSide, PAWN, 1);
  Rank r1 = square_rank(psq1);
  Rank r2 = square_rank(psq2);
  Square blockSq1, blockSq2;

  if (relative_rank(strongerSide, psq1) > relative_rank(strongerSide, psq2))
  {
      blockSq1 = psq1 + pawn_push(strongerSide);
      blockSq2 = make_square(square_file(psq2), square_rank(psq1));
  }
  else
  {
      blockSq1 = psq2 + pawn_push(strongerSide);
      blockSq2 = make_square(square_file(psq1), square_rank(psq2));
  }

  switch (file_distance(psq1, psq2))
  {
  case 0:
    // Both pawns are on the same file. Easy draw if defender firmly controls
    // some square in the frontmost pawn's path.
    if (   square_file(ksq) == square_file(blockSq1)
        && relative_rank(strongerSide, ksq) >= relative_rank(strongerSide, blockSq1)
        && !same_color_squares(ksq, wbsq))
        return SCALE_FACTOR_ZERO;
    else
        return SCALE_FACTOR_NONE;

  case 1:
    // Pawns on neighboring files. Draw if defender firmly controls the square
    // in front of the frontmost pawn's path, and the square diagonally behind
    // this square on the file of the other pawn.
    if (   ksq == blockSq1
        && !same_color_squares(ksq, wbsq)
        && (   bbsq == blockSq2
            || (pos.attacks_from<BISHOP>(blockSq2) & pos.pieces(BISHOP, weakerSide))
            || rank_distance(r1, r2) >= 2))
        return SCALE_FACTOR_ZERO;

    else if (   ksq == blockSq2
             && !same_color_squares(ksq, wbsq)
             && (   bbsq == blockSq1
                 || (pos.attacks_from<BISHOP>(blockSq1) & pos.pieces(BISHOP, weakerSide))))
        return SCALE_FACTOR_ZERO;
    else
        return SCALE_FACTOR_NONE;

  default:
    // The pawns are not on the same file or adjacent files. No scaling.
    return SCALE_FACTOR_NONE;
  }
}
예제 #15
0
ScaleFactor ScalingFunction<KRPKR>::apply(const Position& pos) const {

  assert(pos.non_pawn_material(strongerSide) == RookValueMidgame);
  assert(pos.piece_count(strongerSide, PAWN) == 1);
  assert(pos.non_pawn_material(weakerSide) == RookValueMidgame);
  assert(pos.piece_count(weakerSide, PAWN) == 0);

  Square wksq = pos.king_square(strongerSide);
  Square wrsq = pos.piece_list(strongerSide, ROOK, 0);
  Square wpsq = pos.piece_list(strongerSide, PAWN, 0);
  Square bksq = pos.king_square(weakerSide);
  Square brsq = pos.piece_list(weakerSide, ROOK, 0);

  // Orient the board in such a way that the stronger side is white, and the
  // pawn is on the left half of the board.
  if (strongerSide == BLACK)
  {
      wksq = flip_square(wksq);
      wrsq = flip_square(wrsq);
      wpsq = flip_square(wpsq);
      bksq = flip_square(bksq);
      brsq = flip_square(brsq);
  }
  if (square_file(wpsq) > FILE_D)
  {
      wksq = flop_square(wksq);
      wrsq = flop_square(wrsq);
      wpsq = flop_square(wpsq);
      bksq = flop_square(bksq);
      brsq = flop_square(brsq);
  }

  File f = square_file(wpsq);
  Rank r = square_rank(wpsq);
  Square queeningSq = make_square(f, RANK_8);
  int tempo = (pos.side_to_move() == strongerSide);

  // If the pawn is not too far advanced and the defending king defends the
  // queening square, use the third-rank defence.
  if (   r <= RANK_5
      && square_distance(bksq, queeningSq) <= 1
      && wksq <= SQ_H5
      && (square_rank(brsq) == RANK_6 || (r <= RANK_3 && square_rank(wrsq) != RANK_6)))
      return SCALE_FACTOR_ZERO;

  // The defending side saves a draw by checking from behind in case the pawn
  // has advanced to the 6th rank with the king behind.
  if (   r == RANK_6
      && square_distance(bksq, queeningSq) <= 1
      && square_rank(wksq) + tempo <= RANK_6
      && (square_rank(brsq) == RANK_1 || (!tempo && abs(square_file(brsq) - f) >= 3)))
      return SCALE_FACTOR_ZERO;

  if (   r >= RANK_6
      && bksq == queeningSq
      && square_rank(brsq) == RANK_1
      && (!tempo || square_distance(wksq, wpsq) >= 2))
      return SCALE_FACTOR_ZERO;

  // White pawn on a7 and rook on a8 is a draw if black's king is on g7 or h7
  // and the black rook is behind the pawn.
  if (   wpsq == SQ_A7
      && wrsq == SQ_A8
      && (bksq == SQ_H7 || bksq == SQ_G7)
      && square_file(brsq) == FILE_A
      && (square_rank(brsq) <= RANK_3 || square_file(wksq) >= FILE_D || square_rank(wksq) <= RANK_5))
      return SCALE_FACTOR_ZERO;

  // If the defending king blocks the pawn and the attacking king is too far
  // away, it's a draw.
  if (   r <= RANK_5
      && bksq == wpsq + DELTA_N
      && square_distance(wksq, wpsq) - tempo >= 2
      && square_distance(wksq, brsq) - tempo >= 2)
      return SCALE_FACTOR_ZERO;

  // Pawn on the 7th rank supported by the rook from behind usually wins if the
  // attacking king is closer to the queening square than the defending king,
  // and the defending king cannot gain tempi by threatening the attacking rook.
  if (   r == RANK_7
      && f != FILE_A
      && square_file(wrsq) == f
      && wrsq != queeningSq
      && (square_distance(wksq, queeningSq) < square_distance(bksq, queeningSq) - 2 + tempo)
      && (square_distance(wksq, queeningSq) < square_distance(bksq, wrsq) + tempo))
      return ScaleFactor(SCALE_FACTOR_MAX - 2 * square_distance(wksq, queeningSq));

  // Similar to the above, but with the pawn further back
  if (   f != FILE_A
      && square_file(wrsq) == f
      && wrsq < wpsq
      && (square_distance(wksq, queeningSq) < square_distance(bksq, queeningSq) - 2 + tempo)
      && (square_distance(wksq, wpsq + DELTA_N) < square_distance(bksq, wpsq + DELTA_N) - 2 + tempo)
      && (  square_distance(bksq, wrsq) + tempo >= 3
          || (    square_distance(wksq, queeningSq) < square_distance(bksq, wrsq) + tempo
              && (square_distance(wksq, wpsq + DELTA_N) < square_distance(bksq, wrsq) + tempo))))
      return ScaleFactor(  SCALE_FACTOR_MAX
                         - 8 * square_distance(wpsq, queeningSq)
                         - 2 * square_distance(wksq, queeningSq));

  // If the pawn is not far advanced, and the defending king is somewhere in
  // the pawn's path, it's probably a draw.
  if (r <= RANK_4 && bksq > wpsq)
  {
      if (square_file(bksq) == square_file(wpsq))
          return ScaleFactor(10);
      if (   abs(square_file(bksq) - square_file(wpsq)) == 1
          && square_distance(wksq, bksq) > 2)
          return ScaleFactor(24 - 2 * square_distance(wksq, bksq));
  }
  return SCALE_FACTOR_NONE;
}