175 lines
5.2 KiB
C
175 lines
5.2 KiB
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 "liberty.h"
|
||
|
#include "dfa.h"
|
||
|
|
||
|
#include <memory.h>
|
||
|
|
||
|
/* Array for use by TRANSFORM() macro. */
|
||
|
int transformation[MAX_OFFSET][8];
|
||
|
|
||
|
/* Matrix array for use by TRANSFORM2() macro. */
|
||
|
const int transformation2[8][2][2] = {
|
||
|
{ { 1, 0},
|
||
|
{ 0, 1}}, /* a - identity transformation matrix */
|
||
|
|
||
|
{ { 0, 1},
|
||
|
{-1, 0}}, /* g - rotate 90 clockwise */
|
||
|
|
||
|
{ {-1, 0},
|
||
|
{ 0, -1}}, /* d - rotate 180 */
|
||
|
|
||
|
{ { 0, -1},
|
||
|
{ 1, 0}}, /* f - rotate 90 counter-clockwise */
|
||
|
|
||
|
{ { 0, -1},
|
||
|
{-1, 0}}, /* h - rotate 90 clockwise and flip on x axis */
|
||
|
|
||
|
{ {-1, 0},
|
||
|
{ 0, 1}}, /* b - flip on x axis */
|
||
|
|
||
|
{ { 0, 1},
|
||
|
{ 1, 0}}, /* e - rotate 90 counter-clockwise and flip on x axis */
|
||
|
|
||
|
{ { 1, 0},
|
||
|
{ 0, -1}} /* c - flip on y axis */
|
||
|
};
|
||
|
|
||
|
|
||
|
/* Initialize transformation[][] array. */
|
||
|
void
|
||
|
transformation_init(void)
|
||
|
{
|
||
|
int k;
|
||
|
int dx;
|
||
|
int dy;
|
||
|
|
||
|
for (k = 0; k < 8; k++) {
|
||
|
for (dy = -MAX_BOARD+1; dy <= MAX_BOARD-1; dy++) {
|
||
|
for (dx = -MAX_BOARD+1; dx <= MAX_BOARD-1; dx++) {
|
||
|
int tx;
|
||
|
int ty;
|
||
|
|
||
|
TRANSFORM2(dx, dy, &tx, &ty, k);
|
||
|
transformation[OFFSET(dx, dy)][k] = DELTA(tx, ty);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
/* Spiral orders for DFA matching and building. */
|
||
|
int spiral[DFA_MAX_ORDER][8];
|
||
|
|
||
|
/* The spiral order is the way we scan the board, we begin on the
|
||
|
* anchor and we progressively scan all its neigbouring intersections,
|
||
|
* collecting all the known patterns we meet on our way:
|
||
|
*
|
||
|
* 4 4 4
|
||
|
* 1 1 13 13 513 513 ... and so on until we reach a
|
||
|
* 2 2 2 2 827 stopping state in the DFA.
|
||
|
* 6
|
||
|
*
|
||
|
* Build the spiral order for each transformation: instead of changing
|
||
|
* the board or changing the patterns, we only change the order. For
|
||
|
* e.g. the same DFA can perform the pattern matching
|
||
|
*
|
||
|
* That way for identity:
|
||
|
*
|
||
|
* 40 04
|
||
|
* 5139 and this way for mirror symetry: 9315
|
||
|
* 827 728
|
||
|
* 6 6
|
||
|
*
|
||
|
* Anther possibility is to generate one string by pattern and by
|
||
|
* transformation in `mkpat' to avoid any runtime transformation but
|
||
|
* it drastically increases the size of DFAs.
|
||
|
*/
|
||
|
void
|
||
|
build_spiral_order(void)
|
||
|
{
|
||
|
int i;
|
||
|
int j;
|
||
|
int k;
|
||
|
char mark[2 * DFA_MAX_BOARD + 1][2 * DFA_MAX_BOARD + 1];
|
||
|
int queue_i[DFA_MAX_ORDER];
|
||
|
int queue_j[DFA_MAX_ORDER];
|
||
|
int queue_start = 0;
|
||
|
int queue_end = 1;
|
||
|
|
||
|
static const int delta_i[4] = { 1, 0, -1, 0};
|
||
|
static const int delta_j[4] = { 0, 1, 0, -1};
|
||
|
|
||
|
/* Initialization. */
|
||
|
memset(mark, 1, sizeof(mark));
|
||
|
for (i = 1; i < 2 * DFA_MAX_BOARD; i++) {
|
||
|
for (j = 1; j < 2 * DFA_MAX_BOARD; j++)
|
||
|
mark[i][j] = 0;
|
||
|
}
|
||
|
|
||
|
queue_i[0] = DFA_MAX_BOARD;
|
||
|
queue_j[0] = DFA_MAX_BOARD;
|
||
|
mark[DFA_MAX_BOARD][DFA_MAX_BOARD] = 1;
|
||
|
|
||
|
do {
|
||
|
int transformation;
|
||
|
|
||
|
/* Transform queued coordinates and store DFA offsets in spiral[][]. */
|
||
|
for (transformation = 0; transformation < 8; transformation++) {
|
||
|
TRANSFORM2(queue_i[queue_start] - DFA_MAX_BOARD,
|
||
|
queue_j[queue_start] - DFA_MAX_BOARD,
|
||
|
&i, &j, transformation);
|
||
|
spiral[queue_start][transformation] = DFA_BASE * i + j;
|
||
|
}
|
||
|
|
||
|
for (k = 0; k < 4; k++) {
|
||
|
i = queue_i[queue_start] + delta_i[k];
|
||
|
j = queue_j[queue_start] + delta_j[k];
|
||
|
|
||
|
if (!mark[i][j]) {
|
||
|
queue_i[queue_end] = i;
|
||
|
queue_j[queue_end++] = j;
|
||
|
mark[i][j] = 1;
|
||
|
}
|
||
|
}
|
||
|
} while (++queue_start < queue_end);
|
||
|
|
||
|
if (0) {
|
||
|
int transformation;
|
||
|
for (transformation = 0; transformation < 8; transformation++) {
|
||
|
fprintf(stderr, "Transformation %d:\n", transformation);
|
||
|
for (k = 0; k < 16; k++) {
|
||
|
fprintf(stderr, "\t%d(%c); %d\n", k, 'A' + k,
|
||
|
spiral[k][transformation]);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Local Variables:
|
||
|
* tab-width: 8
|
||
|
* c-basic-offset: 2
|
||
|
* End:
|
||
|
*/
|