/*
   File:        whis.c
   Author:      Andrew W. Moore
   Created:     Mon Sep 21 15:17:33 EDT 1992
   Description: History of worsts

   Copyright (C) 1992, Andrew W. Moore
*/

#include <stdio.h>
#include <math.h>
#include "ambs.h"      /* Very basic operations */
#include "amma.h"      /* Fast, non-fragmenting, memory management */
#include "amar.h"      /* Obvious operations on 1-d arrays */
#include "maxdim.h"    /* The MAX_DIM declaration */
#include "gpro.h"      /* Graphics projections kd->2d space */
#include "hype.h"      /* Hyper-rectangles from ../kdtr */
#include "region.h"    /* K-d region Data Structure */
#include "wrld.h"      /* Spec. of the World Control problem */
#include "whis.h"      /* History of worsts */

void empty_worst_hist(wh)
worst_hist *wh;
{
  worst_list *wl = wh -> recent;

  while ( wl != NULL )
  {
    worst_list *before = wl -> before;
    free_worst(wl->worst);
    am_free((char *)wl,sizeof(worst_list));
    wl = before;
  }

  wh -> recent = NULL;
  wh -> start = NULL;
  wh -> length = 0;
  wh -> modes_all_same = TRUE;
}

void init_worst_hist(wh)
worst_hist *wh;
{
  wh -> recent = NULL;
  wh -> start = NULL;
  empty_worst_hist(wh);
}

void add_to_worst_hist(wh,w,w_size)
worst_hist *wh;
worst *w;
int w_size;
/*
  Adds a COPY of worst 'w'

  PRE: modes_all_same field is valid before. As is length.
*/
{
  worst *wcop = create_worst(w->mode,w_size);
  worst_list *node = AM_MALLOC(worst_list);
  copy_worst(w,wcop,w_size);

  wh -> modes_all_same = ( wh -> modes_all_same &&
                           ( wh -> recent == NULL ||
                             wh -> recent -> worst -> mode == w -> mode
                           )
                         );
  node -> worst = wcop;

  if ( wh -> recent == NULL )  
  {
    wh -> recent = node;
    wh -> start = node;
    node -> before = NULL;
    node -> after = NULL;
  }
  else
  {
    node -> before = wh -> recent;
    node -> after = NULL;
    wh -> recent -> after = node;
    wh -> recent = node;
  }

  wh -> length++;
}

void fprint_worst_hist(s,m,wh,wld)
FILE *s;
char *m;
worst_hist *wh;
world *wld;
{
  char buff[100];
  int i = 1;
  worst_list *wl;
  for ( wl = wh->start ; wl != NULL ; wl = wl -> after )
  {
    sprintf(buff,"%s[%d] = ",m,i);
    fprintf_worst(s,buff,wl->worst,wld,"\n");
    i += 1;
  }
  fprintf(s,"%s -> length = %d\n",m,wh->length);
}

int worst_hist_age(wh)
worst_hist *wh;
{
  return(wh->length);
}

bool whist_is_stuck(wld,wh)
world *wld;
worst_hist *wh;
{
  bool result = FALSE;
  if ( !wh->modes_all_same )
  {
    fprint_worst_hist(stderr,"offending-wh",wh,wld);
    my_error("whist_is_stuck(): modes aren't all the same");
  }
  else if ( wh -> recent == NULL )
    result = FALSE;
  else
  {
    mode_spec *msp;

    if ( Verbosity > 30.0 )
      printf("whist_is_stuck(): wh->recent->worst->mode = %d\n",
             wh->recent->worst->mode
            );

    msp = mode_ref(wld,wh->recent->worst->mode);
    if ( msp->is_stuck == NULL )
      result = TRUE;
    else
      result = msp->is_stuck(wld,wh);
  }
  return(result);
}


      
  
