/*MazeMouse*MazeMouse*MazeMouse*MazeMouse*MazeMouse*MazeMouse*MazeMouse*/
/*  actions.c                                                          */
/*    Hier stehen die Aktionen, die MazeMouse ausführen kann.          */
/*                                                                     */
/*     (c) 1991 Bob Malzan                                             */
/*MazeMouse*MazeMouse*MazeMouse*MazeMouse*MazeMouse*MazeMouse*MazeMouse*/
#include <exec/types.h>
#include <exec/memory.h>
#include <ctype.h>
#include <rexx/errors.h>
#include "maze.h"

/* gemeinsame Variablen (sind in MazeMouse.c beschrieben) */
extern int	MaxX,MaxY;
extern int	CatX,CatY;
extern int	CheeseX,CheeseY;
extern int	MouseX,MouseY;
extern int	MouseDir;
extern int	CatDir,CatSPos;
extern int	Dead;
extern int	Cheese;
extern long	seed;
extern char	*Maze;

/*       Ein paar (Vor-) Funktionsdeklarationen...        */
extern void	StepXY();
extern void	Do_Move();
extern void	*AllocMem();

/*--------------------------------------------------------*/
/*                Initialisierungsroutinen                */
/*--------------------------------------------------------*/
void	SetPositions()
{
  int	free=0,I;

  while (!free)
  {
    CatX=CheeseX = ((seed=FastRand(seed))&0x7FFF) % (MaxX-7) +5;
    CatY=CheeseY = ((seed=FastRand(seed))&0x7FFF) % (MaxY-7) +5;
    free = (*(Maze+CheeseX+CheeseY*MaxX) == ' ');
  }
  for (I=CatX-4;I<CatX+1;I++)
  {
    *(Maze+I+(CatY-4)*MaxX) = ' ';
    *(Maze+I+ CatY   *MaxX) = ' ';
  }
  for (I=CatY-4;I<CatY+1;I++)
  {
    *(Maze+CatX-4+I*MaxX) = ' ';
    *(Maze+CatX  +I*MaxX) = ' ';
  }
  MouseDir=3;
  CatDir = 3;
}

/*--------------------------------------------------------*/
void	NewMaze(str,arg,prim,sec)
char	*str,*arg;
long	*prim,*sec;
{
  char	num1[10],num2[10];
  int	p;

  arg+=8;
  p=0;
  while(*arg && isdigit(*arg))
  {
    num1[p] = *arg;
    p++;
    arg++;
  }
  num1[p]=0;
  arg++;
  p=0;
  while(*arg && isdigit(*arg))
  {
    num2[p] = *arg;
    p++;
    arg++;
  }
  num2[p]=0;

  if (Maze) FreeMem(Maze,MaxX*MaxY);
  Maze = NULL;
  MaxX = atoi(num1);
  MaxY = atoi(num2);
  if (MaxX<=0 || MaxY<=0)
  {
    *prim = RC_ERROR;
    *sec  = ERR10_018;	/* invalid parameters to function */
    Dead  = 1;
    return;
  }

  Maze = AllocMem(MaxX*MaxY,MEMF_PUBLIC);
  if (!Maze) CleanUp("can't allocate new maze!");
  CreateMaze(MaxX,MaxY,Maze);
  SetPositions();
  sprintf(str,"OK");
}

/*--------------------------------------------------------*/
/*                   Abfrage-Funktionen                   */
/*--------------------------------------------------------*/
void	MazeSize(str)
char	*str;
{
  sprintf(str,"%d %d",MaxX,MaxY);
}

void	DumpMaze(str)
char	*str;
{
  int I,J;
  
  for (I=0;I<MaxX;I++)
  {
    for (J=0;J<MaxY;J++)
    {
      *str=*(Maze+I+J*MaxX);
      str++;
    }
    *str=0x0A;
    str++;
  }
}

/*--------------------------------------------------------*/
void	CatPos(str)
char	*str;
{
  sprintf(str,"%d %d",CatX+1,CatY+1);
}

/*--------------------------------------------------------*/
void	MousePos(str)
char	*str;
{
  sprintf(str,"%d %d",MouseX+1,MouseY+1);
}

/*--------------------------------------------------------*/
void	WallAhead(str)
char	*str;
{
  int	count=0,X=MouseX,Y=MouseY;

  StepXY(&MouseDir,&X,&Y);

  while(*(Maze+X+Y*MaxX)==' ')
  {
    count++;
    StepXY(&MouseDir,&X,&Y);
  }
  sprintf(str,"%d",count);
}

/*--------------------------------------------------------*/
void	WallLeft(str)
char	*str;
{
  char	dc;

  switch (MouseDir)
  {
    case 0 : dc = *(Maze+MouseX+(MouseY+1)*MaxX);
    break;
    case 1 : dc = *(Maze+MouseX+1+MouseY*MaxX);
    break;
    case 2 : dc = *(Maze+MouseX+(MouseY-1)*MaxX);
    break;
    case 3 : dc = *(Maze+MouseX-1+MouseY*MaxX);
    break;
  }
  sprintf(str,"%d",dc == ' ' ? 0 : 1);
}

/*--------------------------------------------------------*/
void	WallRight(str)
char	*str;
{
  char	dc;

  switch (MouseDir)
  {
    case 0 : dc = *(Maze+MouseX+(MouseY-1)*MaxX);
    break;
    case 1 : dc = *(Maze+MouseX-1+MouseY*MaxX);
    break;
    case 2 : dc = *(Maze+MouseX+(MouseY+1)*MaxX);
    break;
    case 3 : dc = *(Maze+MouseX+1+MouseY*MaxX);
    break;
  }
  sprintf(str,"%d",dc == ' ' ? 0 : 1);
}

/*--------------------------------------------------------*/
/*                        Aktionen                        */
/*--------------------------------------------------------*/
void	StepAhead(str)
char	*str;
{
  int X,Y;

  X=MouseX;
  Y=MouseY;

  StepXY(&MouseDir,&X,&Y);
  if (*(Maze+X+Y*MaxX)=='*')	/* 	bumped into a wall	*/
  {
    strcpy(str,"BUMPED");
  }
  else	/*	otherwise assume all's OK		*/
  {
    MouseX=X;
    MouseY=Y;
    strcpy(str,"OK");
  }
  Do_Move(str);	/*	now, let the cat move...	*/
}

/*--------------------------------------------------------*/
void 	Stay(str)
char	*str;
{
  strcpy(str,"OK");	/*	mouse stays (suicide?)	*/
  Do_Move(str);		/*	the cat NEVER sleeps...	*/
}

/*--------------------------------------------------------*/
/*                   Interne Funktionen                   */
/*--------------------------------------------------------*/
void	Do_Move(str)
char	*str;
{
  int	TestDir,TestX,TestY;

  if (CatX==MouseX && CatY==MouseY)
  {
    strcpy(str,"DEAD");
    Dead=-1;
    return;
  }
  else if (CheeseX==MouseX && CheeseY==MouseY)
  {
    strcpy(str,"CHEESE");
    Cheese=-1;
    return;
  }

  /* now, let's move the cat */
  TestX=CatX;
  TestY=CatY;
  TestDir = (CatDir+3)%4;
  StepXY(&TestDir,&TestX,&TestY);
  if (*(Maze+TestX+TestY*MaxX)==' ')	/* test left */
  {
    CatDir = TestDir;
    CatX   = TestX;
    CatY   = TestY;
  }
  else		/* test straight ahead */
  {
    TestX=CatX;
    TestY=CatY;
    StepXY(&CatDir,&TestX,&TestY);
    if (*(Maze+TestX+TestY*MaxX)==' ')
    {
      CatX   = TestX;
      CatY   = TestY;
    }
    else	/* test right */
    {
      TestX=CatX;
      TestY=CatY;
      TestDir = (CatDir+1)%4;
      StepXY(&TestDir,&TestX,&TestY);
      if (*(Maze+TestX+TestY*MaxX)==' ')
      {
        CatX   = TestX;
        CatY   = TestY;
        CatDir = TestDir;
      }
      else	/* about face */
      {
        CatDir = (CatDir+2)%4;
        StepXY(&CatDir,&CatX,&CatY);
      }
    }
  }

  /* maybe the cat is onto something NOW? */
  if (CatX==MouseX && CatY==MouseY)
  {
    strcpy(str,"DEAD");
    Dead=-1;
    return;
  }
}

/*--------------------------------------------------------*/
/*   Die Bewegungsrichtung ist folgendermaßen codiert:    */
/*                    0: X=  1;  Y=  0                    */
/*                    1: X=  0;  Y= -1                    */
/*                    2: X= -1;  Y=  0                    */
/*                    3: X=  0;  Y=  1                    */
/*--------------------------------------------------------*/
void	StepXY(d,i,j)	
int	*d,*i,*j;
{
  switch(*d)
  {
    case 0:
      *i= *i+1;
    break;
    case 1:
      *j= *j-1;
    break;
    case 2:
      *i= *i-1;
    break;
    case 3:
      *j= *j+1;
    break;
  }
}
