Initial commit of GNU Go v3.8.
[sgk-go] / engine / movelist.c
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
* This is GNU Go, a Go program. Contact gnugo@gnu.org, or see *
* http://www.gnu.org/software/gnugo/ for more information. *
* *
* Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008 and 2009 by the Free Software Foundation. *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation - version 3 or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License in file COPYING for more details. *
* *
* You should have received a copy of the GNU General Public *
* License along with this program; if not, write to the Free *
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
* Boston, MA 02111, USA. *
\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "gnugo.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "liberty.h"
static void movelist_sort_points(int max_points, int points[], int codes[]);
static void swap_points_and_codes(int points[], int codes[], int m, int n);
/* Return the code for the move if it is known.
*/
int
movelist_move_known(int move, int max_points, int points[], int codes[])
{
int k;
for (k = 0; k < max_points; k++) {
if (codes[k] == 0)
return 0;
if (points[k] == move)
return codes[k];
}
return 0;
}
/*
* This function does the real work for change_attack(),
* change_defense(), change_attack_threat(), and
* change_defense_threat().
*/
void
movelist_change_point(int move, int code, int max_points,
int points[], int codes[])
{
int k;
/* First see if we already know about this point. */
for (k = 0; k < max_points; k++)
if (points[k] == move)
break;
/* Yes, we do. */
if (k < max_points) {
if (codes[k] <= code)
return; /* Old news. */
codes[k] = code;
movelist_sort_points(max_points, points, codes);
return;
}
/* This tactical point is new to us. */
if (code > codes[max_points - 1]) {
points[max_points - 1] = move;
codes[max_points - 1] = code;
movelist_sort_points(max_points, points, codes);
}
}
/* Sort the tactical points so we have it sorted in falling order on
* the code values.
*
* We use shaker sort because we prefer a stable sort and in all use
* cases we can expect it to suffice with one turn through the outer
* loop.
*/
static void
movelist_sort_points(int max_points, int points[], int codes[])
{
int start = 0;
int end = max_points - 1;
int new_start;
int new_end;
int k;
while (start < end) {
new_start = end;
for (k = end; k > start; k--)
if (codes[k] > codes[k-1]) {
swap_points_and_codes(points, codes, k, k-1);
new_start = k;
}
start = new_start;
new_end = start;
for (k = start; k < end - 1; k++)
if (codes[k] < codes[k+1]) {
swap_points_and_codes(points, codes, k, k+1);
new_end = k;
}
end = new_end;
}
}
static void
swap_points_and_codes(int points[], int codes[], int m, int n)
{
int tmp = points[m];
points[m] = points[n];
points[n] = tmp;
tmp = codes[m];
codes[m] = codes[n];
codes[n] = tmp;
}
/*
* Local Variables:
* tab-width: 8
* c-basic-offset: 2
* End:
*/