/*--------------------------------------------------------*/
/*                      MazeMouse.c                       */
/*                                                        */
/*     Ein nettes kleines ARexx-Spielchen, das zeigt,     */
/*         wie ein ARexx-Host aufgebaut sein muß          */
/*                                                        */
/*                  (c) Bob Malzan 1991                   */
/*--------------------------------------------------------*/

#include <exec/types.h>
#include <exec/ports.h>
#include <exec/memory.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include "rexx.h"
#include "maze.h"

/*--------------------------------------------------------*/
/*                meine globalen Variablen                */
/*--------------------------------------------------------*/
int		RexxCount = 0;

APTR		RexxSysBase = NULL;
struct MsgPort	*RexxPort = NULL;
struct MsgPort	*MousePort = NULL;
struct RexxMsg	*RxMsg;

int		MaxX,MaxY;		/* Labyrinthgröße	*/
int		CatX,CatY;		/* Position Katze	*/
int		CheeseX,CheeseY;	/* Position Käse	*/
int		MouseX,MouseY;		/* Maus (Deine) Position*/
int		MouseDir;		/* Laufrichtung		*/
int		CatDir,CatSPos;		/* Katzenrichtung	*/
int		Dead;			/* Schon tot?		*/
int		Cheese;			/* Käse gefunden?	*/
char		*Maze=NULL;		/* Das Labyrinth	*/
char		Result[2000];		/* Puffer für RESULT	*/

/*--------------------------------------------------------*/
/*                   externe Functionen                   */
/*--------------------------------------------------------*/
extern void	SetPositions();	/* Positionen initialisieren	*/
extern void	WallAhead();	/* Abstand zur nächsten Wand?	*/
extern void	WallLeft();	/* Ist Links eine Wand?		*/
extern void	WallRight();	/* Ist Rechts eine Wand?	*/
extern void	StepAhead();	/* Ein Schritt nach vorne!	*/
extern void 	Stay();		/* Einen Zug lang abwarten!	*/
extern void	MazeSize();	/* Labyrinthgröße?		*/
extern void	DumpMaze();	/* Labyrinth nach RESULT	*/
extern void	CatPos();	/* Wo steckt die #$! Katze?	*/
extern void	MousePos();	/* Wo bin ich?			*/
extern void	CreateMaze();	/* Erzeugt das Labyrinth	*/


/*--------------------------------------------------------*/
/*                 Funktionsdeklarationen                 */
/*--------------------------------------------------------*/
extern	struct MsgPort	*SetupMyPort();
extern	int		RX();
extern	void		FreeRexxCommand();
extern	void		ReplyRexxCommand();

extern	void		InterpretCommand();
extern	void		OpenUp();
extern	void		CleanUp();

extern struct Message	*GetMsg();
extern struct MsgPort	*FindPort();
extern void		*OpenLibrary(),*AllocMem();
extern struct MsgPort	*SetupMyPort();

/*--------------------------------------------------------*/
/*       OpenUp() und CleanUp() zum Initialisieren        */
/*                     und Schließen                      */
/*--------------------------------------------------------*/
void	OpenUp()
{
  int	I,J;

  RexxSysBase = OpenLibrary("rexxsyslib.library",0L);
  if (!RexxSysBase)
    CleanUp("Wieso kann ich die rexxsyslib.library nicht öffnen?");

  MousePort = SetupMyPort(MOUSEPORT_NAME);
  if (!MousePort)
    CleanUp("Pardon, entweder Rexxmast läuft nicht, oder\nMazeMouse läuft bereits!");

/*              Jetzt das Labyrinth erzeugen              */
  Maze = AllocMem(MaxX*MaxY,MEMF_PUBLIC);
  if (!Maze)
    CleanUp("Pech! Nicht genug Speicher für das Labyrinth!");

  CreateMaze(MaxX,MaxY,Maze);
}

/*--------------------------------------------------------*/

void	CleanUp(str)
char	*str;
{
   if (Maze)		FreeMem(Maze,MaxX*MaxY);
   if (MousePort)	DeletePort(MousePort);
   if (RexxSysBase)	CloseLibrary(RexxSysBase);
   if (str)		puts(str);

   exit(0);
}

/*--------------------------------------------------------*/
/*                     Hauptprogramm                      */
/*--------------------------------------------------------*/
int	main(argc,argv)
int	argc;
char	*argv[];
{

/*                      argc testen                       */
  if (argc!=2) CleanUp("Verwendung: MazeMouse <rexx-Makro>");

/*                    Initialisierung                     */
  Dead = Cheese = 0;
  MaxX=MAZE_X;	MaxY=MAZE_Y;
  OpenUp();
  SetPositions();

/*                   Rexx-Makro starten                   */
/*      und merken, wieviel Makros unterwegs sind...      */
  if (RX(argv[1],MousePort,MAZE_EXTENSION) != OK)
    CleanUp("Makro konnte nicht gestartet werden!");
  else RexxCount++;


/*            Solange Rexx-Makro nicht fertig             */
  while (RexxCount)
  {

/*          Warte, bis etwas am Mausport ankommt          */
    WaitPort(MousePort);

/*                    Da war doch was?                    */
    while(RxMsg = GetMsg(MousePort))
    {
/*    Ist dies eine Antwort auf eine meiner Messages?     */
      if (RxMsg->rm_Node.mn_Node.ln_Type == NT_REPLYMSG)
      {
         if (RxMsg->rm_Result1!=0 &&  RxMsg->rm_Result2!=0)
         {
           printf("rexx-Fehler: %d, severity %d\n",
             RxMsg->rm_Result2, RxMsg->rm_Result1
           );
         }
         FreeRexxCommand(RxMsg);
         /* jetzt fliegt ein Makro weniger herum...  */
         RexxCount--;

         if (Dead) CleanUp("Hab' ich dich, Knopfauge!!");
         else if (Cheese) CleanUp("Nächstes mal krieg' ich dich, Kleiner!");
         else CleanUp("Gibst du schon auf?!");
      }
      else
      {
/*       Rexx-Befehl erhalten, jetzt interpretieren       */
        InterpretCommand(RxMsg);
      }
    }
  }

/*                 Sauberkeit muß sein...                 */
  CleanUp("Done.");
}

/*--------------------------------------------------------*/
/*                 Befehls-Interpretation                 */
/*--------------------------------------------------------*/
void InterpretCommand(RxMsg)
struct RexxMsg *RxMsg;
{
  long Primary=0,Secondary=0;

/*                Neues Spiel, neues Glück                */
  if (strncmp(RxMsg->rm_Args[0],"NEWMAZE",7) == 0L)
  {
    NewMaze(Result,RxMsg->rm_Args[0],&Primary,&Secondary);
  }
/*  Wenn das Spiel zu Ende ist, ist nur NEWMAZE erlaubt   */
  else if (Dead || Cheese)
  {
    strcpy(Result,(Dead ? "DEAD" : "CHEESE" ));
  }
/*           Abfragen. Sie gelten nicht als Zug           */
  else if (strcmp(RxMsg->rm_Args[0],"MAZESIZE") == 0L)
  {
    MazeSize(Result);
  }
  else if (strcmp(RxMsg->rm_Args[0],"DUMPMAZE") == 0L)
  {
    DumpMaze(Result);
  }
  else if (strcmp(RxMsg->rm_Args[0],"POSITION OF CAT") == 0L)
  {
    CatPos(Result);
  }
  else if (strcmp(RxMsg->rm_Args[0],"POSITION OF MOUSE") == 0L)
  {
    MousePos(Result);
  }
  else if (strcmp(RxMsg->rm_Args[0],"WALL AHEAD") == 0L)
  {
    WallAhead(Result);
  }
  else if (strcmp(RxMsg->rm_Args[0],"WALL LEFT") == 0L)
  {
    WallLeft(Result);
  }
  else if (strcmp(RxMsg->rm_Args[0],"WALL RIGHT") == 0L)
  {
    WallRight(Result);
  }
/*           Aktionen, die nicht als Zug gelten           */
  else if (strcmp(RxMsg->rm_Args[0],"TURN LEFT") == 0L)
  {
    MouseDir = (MouseDir+3)%4;
  }
  else if (strcmp(RxMsg->rm_Args[0],"TURN RIGHT") == 0L)
  {
    MouseDir = (MouseDir+1)%4;
  }
/*   Aktionen, die als Zug gelten, d.h. die Katze macht   */
/*                     auch einen Zug                     */
  else if (strcmp(RxMsg->rm_Args[0],"STEP AHEAD") == 0L)
  {
    StepAhead(Result);
  }
  else if (strcmp(RxMsg->rm_Args[0],"STAY") == 0L)
  {
    Stay(Result);
  }
/*           sonst: Befehl unbekannt => Fehler            */
  else
  {
    Primary   = RC_ERROR;
    Secondary = ERR10_008;	/* unrecognized token */
  }
  ReplyRexxCommand(RxMsg,Primary,Secondary,Result);
}
