Knight's Tour

Take a chess knight around an empty board landing on every square once only. I wrote this while at Nescot studying for my HND. I had a friend run it on a 16 processor Sun machine overnight and it had done the job by the morning. Spot the goto.
// © Rob Geleit March 1998

#include <stdio.h>
#include <time.h>
#include <stdlib.h>

typedef enum {FALSE,TRUE} boolean;

struct position
{
    int x;
    int y;
};

struct position moves_rel[8];
struct position legal_moves_abs[8];

int board[8][8];

int max=0;

void randomise(void);
int random(int);
void init_arrays(void);
void display_board(void);
void move_to(struct position,int);

void main(void)
{
    struct position initial;
    
/* randomise(); */
    init_arrays();

    initial.x=random(8);
    initial.y=random(8);

    printf("Start at %d,%d\n\n",initial.x,initial.y);

    move_to(initial,1);

    display_board();
}

void init_arrays(void)
{
    int i,j;
    int x[8]={1,2,2,1,-1,-2,-2,-1};
    int y[8]={2,1,-1,-2,-2,-1,1,2};

    /* Set up relative moves array */

    for(i=0;i<8;i++)
    {
        moves_rel[i].x=x[i];
        moves_rel[i].y=y[i];
    }

    /* Clear board */

    for(i=0;i<8;i++)
        for(j=0;j<8;j++)
            board[i][j]=0;
}

void display_board(void)
{
    int i,j;

    for(i=0;i<8;i++)
    {
        for(j=0;j<8;j++)
            printf("%2d ",board[i][j]);
        printf("\n\n");
    }
}

void move_to(struct position current_pos_abs,int this_move_no)
{
    int i,j;
    static boolean complete=FALSE;
    boolean recurred;
    int no_legal_moves=0;
    struct position this_move_abs;

    board[current_pos_abs.x][current_pos_abs.y]=this_move_no;

    if(this_move_no==64) complete=TRUE;

    for(i=0;i<8;i++)
    {
        this_move_abs.x=current_pos_abs.x+moves_rel[i].x;
        this_move_abs.y=current_pos_abs.y+moves_rel[i].y;
        
        if(this_move_abs.x>=0 && this_move_abs.x<8 &&
           this_move_abs.y>=0 && this_move_abs.y<8 &&
           board[this_move_abs.x][this_move_abs.y]==0)
        {
            legal_moves_abs[no_legal_moves].x=this_move_abs.x;
            legal_moves_abs[no_legal_moves].y=this_move_abs.y;

            no_legal_moves++;
        }
    }
resume: recurred=FALSE;
    if(no_legal_moves>0)
    {
            recurred=TRUE;

        i=0;/*random(no_legal_moves);*/
        this_move_abs.x=legal_moves_abs[i].x;
        this_move_abs.y=legal_moves_abs[i].y;

if(board[this_move_abs.x][this_move_abs.y]!=0)printf("plop");
   
        /* remove from list */
        for(j=i;j<no_legal_moves;j++)
        {
            legal_moves_abs[j].x=legal_moves_abs[j+1].x;
            legal_moves_abs[j].y=legal_moves_abs[j+1].y;
        }
        no_legal_moves--;
        
        move_to(this_move_abs,this_move_no+1);
    }
    if(complete==TRUE) return; 
    
    if(recurred==FALSE) return;
    board[this_move_abs.x][this_move_abs.y]=0;
    
     if(no_legal_moves>0) goto resume;    
}

void randomise(void)
{
    time_t seed;
    srand((unsigned)time(&seed));
}

int random(int upper) {return(abs(rand()%upper));}