/*>>> sanmnd.c: SAN project move notation decode routines */

/* Revised: 1993.04.10 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#include "sandef.h"
#include "sanvar.h"

#include "sanmnd.h"
#include "sanmne.h"

/*--> SANDecodeBump: increment a style vector and return overflow */
static
  siT
SANDecodeBump (ssavT ssav, ssavT bssav)
{
  siT flag;
  ssaT ssa;

  flag = 1;
  ssa = 0;
  while (flag && (ssa < ssaL))
    {
      flag = 0;
      ssav[ssa]++;
      if (ssav[ssa] == bssav[ssa])
	{
	  flag = 1;
	  ssav[ssa] = 0;
	};
      ssa++;
    };

  return (flag);
}

/*--> SANDecodeFlex: locate a move from SAN (flexible interpretation) */
static
  mptrT
SANDecodeFlex (sanT san)
{
  mptrT mptr;
  ssavT ssav, bssav;
  siT i, flag;
  mptrT rmptr;
  sanT lcsan, rsan;

/* set default return value */

  mptr = NULL;

/* set minimal upper bounds */

  for (i = 0; i < ssaL; i++)
    bssav[i] = 1;

/* scan for upper bound conditions */

  rmptr = curr_g.g_base;
  for (i = 0; i < curr_g.g_gmvc; i++)
    {
      /* letter case */

      bssav[ssa_case] = 2;

      /* capturing */

      if ((rmptr->m_tocp != cp_v0) || (rmptr->m_scmv == scmv_epc))
	bssav[ssa_capt] = 5;

      /* checking */

      if (rmptr->m_flag & mf_chec)
	bssav[ssa_chec] = 3;

      /* castling */

      if ((rmptr->m_scmv == scmv_cks) || (rmptr->m_scmv == scmv_cqs))
	bssav[ssa_cast] = 5;

      /* promoting */

      if ((rmptr->m_scmv == scmv_ppn) || (rmptr->m_scmv == scmv_ppb) ||
	  (rmptr->m_scmv == scmv_ppr) || (rmptr->m_scmv == scmv_ppq))
	bssav[ssa_prom] = 4;

      /* pawn destination target */

      if (cv_p_cpv[rmptr->m_frcp] == p_p)
	bssav[ssa_ptar] = 2;

      /* checkmating */

      if (rmptr->m_flag & mf_chmt)
	bssav[ssa_chmt] = 4;

      /* en passant capturing */

      if (rmptr->m_scmv == scmv_epc)
	bssav[ssa_epct] = 2;

      /* drawing */

      if (rmptr->m_flag & mf_draw)
	bssav[ssa_draw] = 2;

      /* moving (non-capturing) */

      if (optnv[optn_emde] && (rmptr->m_tocp == cp_v0) &&
	  (rmptr->m_scmv != scmv_epc))
	bssav[ssa_move] = 2;

      /* extra disambiguation: file */

      if (optnv[optn_emde] && !(rmptr->m_flag & mf_sanf))
	bssav[ssa_edcf] = 2;

      /* extra disambiguation: rank */

      if (optnv[optn_emde] && !(rmptr->m_flag & mf_sanr))
	bssav[ssa_edcr] = 2;

      rmptr++;
    };

/* make a lower case copy of the input */

  for (i = 0; i < sanL; i++)
    lcsan[i] = map_lower (san[i]);

/* initialize the index style vector */

  for (i = 0; i < ssaL; i++)
    ssav[i] = 0;

/* search */

  flag = 0;
  while (!flag && (mptr == NULL))
    {
      rmptr = curr_g.g_base;
      i = 0;

      /* scan candidate moves */

      while ((mptr == NULL) && (i < curr_g.g_gmvc))
	{
	  /* encode the current style version of a candidate */

	  SANEncodeAux (rmptr, rsan, ssav);

	  /* select either original or lower case comparison */

	  if (ssav[ssa_case] == 0)
	    {
	      if (strcmp (san, rsan) == 0)
		mptr = rmptr;
	    }
	  else
	    {
	      if (strcmp (lcsan, rsan) == 0)
		mptr = rmptr;
	    };

	  /* next candidate */

	  rmptr++;
	  i++;
	};

      /* update the overflow termination flag */

      flag = SANDecodeBump (ssav, bssav);
    };

  return (mptr);
}

/*--> SANDecode: locate a move from SAN (strict interpretation) */
static
  mptrT
SANDecode (sanT san)
{
  mptrT mptr;
  mptrT rmptr;
  sanT rsan;
  siT i;

/* set default return value */

  mptr = NULL;

/* assume current moveset properly generated */

  rmptr = curr_g.g_base;
  i = 0;

/* search */

  while ((mptr == NULL) && (i < curr_g.g_gmvc))
    {
      SANEncode (rmptr, rsan);
      if (strcmp (san, rsan) == 0)
	mptr = rmptr;
      else
	{
	  rmptr++;
	  i++;
	};
    };

  return (mptr);
}

/*--> SANDecodeAux: locate a move from SAN */
nonstatic
mptrT
SANDecodeAux (sanT san)
{
  mptrT mptr;

  if (optnv[optn_nmde])
    mptr = SANDecode (san);
  else
    mptr = SANDecodeFlex (san);

  return (mptr);
}

/*<<< sanmnd.c: EOF */
