Countdown Numbers Game Solver

The following source code is a countdown numbers game solver for PocketC:
Note: Daniel Silverstone ported it to "normal" C - here.

//countdown_game
//(c) T.Frogley
#include "sort.i"
#define NUMBERS 6
#define OPSIZE 3
#define ISIZE 18
#define WORST 65535
#define PLUS 0
#define MINUS 1
#define TIMES 2
#define DIVIDE 3
#define DISCARD 4
#define OPCOUNT 5
int source[NUMBERS];
int target;

int abs(int a)
{ if (a<0) return -a;
else return a;}

int Execute(
	pointer instructions, 
	int draw, int bail
)
{
  int scratch[NUMBERS];
  int size,ip,i;
  int a,b,best;
  for (ip=0;ip<NUMBERS;ip++)
    scratch[ip]=source[ip];
  ip = 0;
  size = NUMBERS;
  best = WORST;
  while(size>1){

    a=scratch[instructions[ip+1]];
    scratch[instructions[ip+1]]=
      scratch[--size];

    b=scratch[instructions[ip+2]];
    scratch[instructions[ip+2]]=
      scratch[--size];
    i=instructions[ip];
    if (i==PLUS){
      if (draw) puts(a+"+"+b);
      a=a+b;
    }
    else if (i==MINUS){
      if (draw) puts(a+"-"+b);
      a=a-b;
    }
    else if (i==TIMES){
      if (draw) puts(a+"*"+b);
      a=a*b;
    }
    else if (i==DIVIDE){
      if (draw) puts(a+"/"+b);
      if (b==0) return WORST;
      if (((a/b)*b)!=a) return WORST;
      a=a/b;
    }
    else if (i==DISCARD){
      if (draw) puts("discard "+b+"\n");
    }

    if (draw)
      if (i!=DISCARD)
        puts("="+a+"\n");

    scratch[size++]=a;
    a=abs(a-target);
    if (a==bail) return bail;
    if (a<best) best=a;
    ip=ip+3;
  }
  return best;
}

Randomize(pointer p)
{
  int i,ip;
  ip=0;
  for (i=0;i<NUMBERS;){
    p[ip++]=random(OPCOUNT);
    p[ip++]=random(NUMBERS-i++);
    p[ip++]= random(NUMBERS-i);
  }
}

RandomSearch()
{
  int instrucs[ISIZE];
  int b,r;
  b=WORST;
  do{
    Randomize(instrucs);
    r=Execute(instrucs,0,0);
    if (r<b){
      clear();
      b=r;
      Execute(instrucs,1,b);
    }
  }while(b);
}

CrossMutate(
  pointer a,
  pointer b,
  pointer c
)
{
  int i,ip;
  pointer r;
  ip=0;
  for (i=0;i<NUMBERS;i++){
    if (random(2)) r=a;
    else r=b;
    if (random(50))
      c[ip]=r[ip];
    else
      c[ip]=random(OPCOUNT);
    ip++;
    if (random(50) &&
      r[ip]<NUMBERS-(i+1)){
      c[ip]=r[ip+1];
      ip++;
      c[ip]=r[ip-1];
      ip++;
    }else{
      if (random(50))
        c[ip]=r[ip];
      else
        c[ip]=random(NUMBERS-i);
      ip++;
      if (random(50))
        c[ip]=r[ip];
      else
        c[ip]=random(NUMBERS-(i+1));
      ip++;
    }
  }
}

#define PSIZE 40
int score[PSIZE];
int derefcomp(pointer a, pointer b)
{
  return score[*a]-score[*b];
}

GASearch()
{
  pointer instructions[PSIZE];
  int index[PSIZE];
  int r,g,i,gen;

  //randomize population
  puts("Initialising...");
  for(g=0;g<PSIZE;g++){
    instructions[g]=malloc(ISIZE);
    Randomize(instructions[g]);
    index[g] = g;
  }

  gen = 0;
  do{
    //test population
    puts("Testing...");
    for(g=0;g<PSIZE;g++){
      score[g]=
        Execute(instructions[g],0,0);
      if (score[g]==0) break;
    }
    //sort results, best first
    if (g==PSIZE){
      puts("Sorting...");
      sort(index,PSIZE,1,derefcomp);
    }
    else index[0]=g;

    clear();
    puts("in generation "
      +(gen++)+":\n");
    Execute(
      instructions[index[0]],
      1, score[index[0]]
    );
    if (score[index[0]]==0) break;

    //cross & mutate population
    puts("Breeding...");
    for(g=0;g<PSIZE/2;g++){
      if (score[index[g]]==WORST)
        Randomize(
          instructions[index[g]]
        );
      CrossMutate(
          instructions[index[g]],
          instructions[index[random(g)]],
          instructions[index[PSIZE/2+g]]
        );
      }      
  }while(1);
  for(g=0;g<PSIZE;g++)
    free(instructions[g]);
}

main()
{
  int i;
  for (i=0;i<NUMBERS;i++){
    source[i]=gets(i);
  }
  target=gets("target");
  GASearch();
}