/* LORD OF HOSTS - main.c --- Hauptprogramm */

#include "Lord.h"

int status,help[2];
BOOL joymouse_allowed;
struct IntuiMessage *msg;

extern BOOL joymouse_on;
extern struct Screen     *MyScreen;
extern struct Window     *MyWindow;
extern struct Move Moves[MAXUNDO];
extern struct Menu game_m;
extern struct Piece      ThePieces[16];
extern UBYTE whatsonboard[8][8];
extern int type_of_board,last_error,undopos;
extern char players[2][16];
extern UBYTE fval[16][8][8], kval[16][8][8];

void wait_events(void)
{
   while (TRUE)
   {
      Wait(1 << MyWindow->UserPort->mp_SigBit);
      while (msg = (struct IntuiMessage *)GetMsg(MyWindow->UserPort))
      {
         switch (msg->Class)
         {
            case MENUPICK:
               handle_menuevents();
               break;
            case MOUSEBUTTONS:
               if (msg->Code == SELECTDOWN) handle_mouseevents();
               break;
            default:
               break;
         }
         ReplyMsg((struct Message *)msg);
      }
   }
}

void handle_menuevents(void)
{
   USHORT MenuNumber,Menu,Item,SubItem;
   char msgstring[100];
   struct MenuItem *MyItem;
   int redohelp;
   MenuNumber = msg->Code;
   if (status & (WAITING_FOR_DEST|WAITING_FOR_CONF))
   {
      SimpleRequest("Bitte diesen Zug erst beenden!");
      return;
   }
   while (MenuNumber != MENUNULL)
   {
      MyItem = ItemAddress(&game_m,MenuNumber);
      Menu = MENUNUM(MenuNumber);
      Item = ITEMNUM(MenuNumber);
      SubItem = SUBNUM(MenuNumber);
      switch (Menu)
      {
         case 0:  /* Menü GAME */
            switch (Item)
            {
               case 0:  /* BEGIN GAME */
                  if (status & IN_GAME)
                     if (!TwoGadRequest("Spiel abbrechen ?"))
                        break;
                  if (!(status & BOARD_UNTOUCHED))
                     switch(type_of_board)
                     {
                        case STD_NORM:
                           drawboard();
                           setup_stdboard(FALSE);
                           break;
                        case STD_ROTD:
                           drawboard();
                           setup_stdboard(TRUE);
                           break;
                        case RND_BAL:
                           drawboard();
                           setup_rndboard(TRUE);
                           break;
                        case RND_UNB:
                           drawboard();
                           setup_rndboard(FALSE);
                           break;
                        default:
                           SimpleRequest("Brett-Typ unbekannt!");
                           break;
                     }
                  status &= (~IN_GAME);
                  NextPlayer(RED);
                  status |= IN_GAME;
                  status &= (~BOARD_UNTOUCHED);
                  EnterNames();
                  if (rand() % 2)
                  {
                     strcpy(msgstring,players[0]);
                     strcat(msgstring," fängt an!");
                     SimpleRequest(msgstring);
                     status |= PLAYER1_TO_MOVE;
                     NextPlayer(RED);
                  } else {
                     strcpy(msgstring,players[1]);
                     strcat(msgstring," fängt an!");
                     if (joymouse_allowed)
                        strcat(msgstring,"\n(Joystick benutzen)");
                     SimpleRequest(msgstring);
                     status &= (~PLAYER1_TO_MOVE);
                     NextPlayer(WHITE);
                  }
                  last_error=0; status |= WAITING_FOR_PICK;
                  break;
               case 1:  /* LOAD GAME */
                  if (status & IN_GAME)
                     if (!TwoGadRequest("Spiel abbrechen ?"))
                        break;
                  LoadGame();
                  break;
               case 2: /* SAVE GAME */
                  SaveGame();
                  break;
               case 3: /* RULES */
                  Rules();
                  break;
               case 4: /* ABOUT */
                  About();
                  break;
               case 5: /* QUIT */
                  if (status & IN_GAME)
                     if (!TwoGadRequest("Spiel abbrechen ?"))
                        break;
                  ReplyMsg((struct Message *)msg);
                  if (joymouse_on) swapjoymouse(FALSE);
                  close_all();
                  break;         /* eigentlich unnötig */
               default:
                  SimpleRequest("Item number unbekannt (Menu 0) !");
                  break;
            }
            break;
         case 1:     /* Menü BOARD */
            if (MyItem->Flags & CHECKED)  /* nur, wenn Wahl endgültig */
            {
               if (status & IN_GAME)
               {
                  SimpleRequest("Das Brett kann während des Spiels\n"
                                "nicht verändert werden. Ihre Wahl\n"
                                "wird aber beim nächsten  Spielbe-\n"
                                "ginn berücksichtigt.");
                  type_of_board = Item;      /* wird beim nächsten BEGIN */
                  break;                     /* gelesen */
               }
               switch (Item)
               {
                  case 0: /* STANDARD */
                     drawboard();
                     setup_stdboard(FALSE);
                     break;
                  case 1: /* STD rotated */
                     drawboard();
                     setup_stdboard(TRUE);
                     break;
                  case 2: /* Random balanced */
                     drawboard();
                     setup_rndboard(TRUE);
                     break;
                  case 3: /* Rnd unbalanced */
                     drawboard();
                     setup_rndboard(FALSE);
                     break;
                  default:
                     SimpleRequest("Item number unbekannt (Menu 1) !");
                     break;
               }
            }
            break;
         case 2: /* Menü SPECIAL */
            switch (Item)
            {
               case 0: /* UNDO */
                  if (!undo()) SimpleRequest("Nichts zurückzunehmen!");
                  else
                  {
                     status = Moves[undopos].status;
                     if (status & PLAYER1_TO_MOVE)
                        NextPlayer(RED);
                     else NextPlayer(WHITE);
                  }
                  break;
               case 1: /* REDO */
                  if (!redo())
                  {
                     SimpleRequest("Nichts nachzuspielen!");
                     if (Moves[undopos].GameOver)
                     {
                        status = IDLE;
                        NextPlayer(RED);
                     } else {
                        status = WAITING_FOR_PICK|IN_GAME;
                        redohelp = undopos-1;
                        if (redohelp<0) redohelp+=MAXUNDO;
                        if (!(Moves[redohelp].status & PLAYER1_TO_MOVE))
                        {
                           status |= PLAYER1_TO_MOVE;
                           NextPlayer(RED);
                        } else NextPlayer(WHITE);
                     }
                  }
                  else
                  {
                     if (Moves[undopos].GameOver)
                     {
                        status = IDLE;
                        NextPlayer(RED);
                     } else {
                        status = WAITING_FOR_PICK|IN_GAME;
                        redohelp = undopos-1;
                        if (redohelp<0) redohelp+=MAXUNDO;
                        if (!(Moves[redohelp].status & PLAYER1_TO_MOVE))
                        {
                           status |= PLAYER1_TO_MOVE;
                           NextPlayer(RED);
                        }
                        else NextPlayer(WHITE);
                     }
                  }
                  break;
               case 2: /* Player 1 Help Mode */
                  help[0] = SubItem;
                  break;
               case 3: /* Player 2 Help Mode */
                  help[1] = SubItem;
                  break;
               case 4: /* JoyMouse */
                  if (SubItem)
                  {
                     if (joymouse_on) swapjoymouse(FALSE);
                     joymouse_allowed = FALSE;
                  } else {
                     joymouse_allowed = TRUE;
                     if (!(status & PLAYER1_TO_MOVE) && !joymouse_on &&
                           (status & IN_GAME))
                        swapjoymouse(TRUE);
                  }
                  break;
               case 5: /* Set JoyMouse Speed */
                  SetJMSpeed();
                  break;
               case 6: /* Switch Sides */
                  SimpleRequest("Nicht implementiert!");
                  break;
               case 7: /* Explain Invalid Move */
                  ExplainError(last_error);
                  break;
               default:
                   SimpleRequest("Item number unbekannt (Menu 2) !");
                   break;
            }
            break;
         default:
            SimpleRequest("Menu number unbekannt !");
            break;
     }
     MenuNumber = MyItem->NextSelect;
  }
}

void handle_mouseevents()
{
   static UBYTE ConfirmX, ConfirmY, HighX, HighY;
   static int PNum,moveresult;
   UBYTE X,Y;
   int base,playernr,checkresult;
   if (Coords(msg->MouseX,msg->MouseY,&X,&Y))
   {
      switch (status & (WAITING_FOR_PICK|WAITING_FOR_DEST|WAITING_FOR_CONF))
      {
         case WAITING_FOR_PICK:  /* dieser Mausklick müßte einen Spielstein
                                    ausgewählt haben */
            PNum = whatsonboard[X][Y];
            base = (status & PLAYER1_TO_MOVE) ? 0 : 8;
            if (PNum >= base && PNum < base +8)
            {
               Highlight(X,Y); /* gültige Wahl */
               HighX=X; HighY=Y;
               status &= (~WAITING_FOR_PICK);
               status |= WAITING_FOR_DEST;
               OffMenu(MyWindow,SHIFTMENU(0)|SHIFTITEM(NOITEM));
               OffMenu(MyWindow,SHIFTMENU(1)|SHIFTITEM(NOITEM));
               OffMenu(MyWindow,SHIFTMENU(2)|SHIFTITEM(NOITEM));
            }
            break;
         case WAITING_FOR_DEST: /* dieser Mausklick müßte das Zielfeld
                                    ausgewählt haben */
            playernr = !(status & PLAYER1_TO_MOVE); /* Nummer des Spielers */
            checkresult = check_move(whatsonboard,ThePieces,PNum,X,Y);
            if (checkresult == MOVE_X_FIRST || checkresult == MOVE_Y_FIRST)
            {
               if (help[playernr]==SHOWKNOWN)
                  Exchange(&fval[PNum][X][Y],&kval[PNum][X][Y]);
               Highlight(HighX,HighY); /* Highlight löschen */
               moveresult = do_move(whatsonboard,ThePieces,PNum,X,Y,
                                    (checkresult==MOVE_X_FIRST));
               if (help[playernr]>NOHELP)
               {
                  status &= (~WAITING_FOR_DEST);
                  status |= WAITING_FOR_CONF;
                  ConfirmX=X;
                  ConfirmY=Y;
                  if (status & PLAYER1_TO_MOVE)
                     DrawText(10,JAM1,219,16,"Spieler 1");
                  else
                     DrawText(10,JAM1,219,49,"Spieler 2");
               } else {
                  kval[PNum][X][Y] = fval[PNum][X][Y];
                  Notify(playernr,moveresult);
                  if (status & IN_GAME)
                  {
                     if (status & PLAYER1_TO_MOVE)
                     {
                        status &= (~PLAYER1_TO_MOVE);
                        NextPlayer(WHITE);
                     } else {
                        status |= PLAYER1_TO_MOVE;
                        NextPlayer(RED);
                     }
                     status &= (~WAITING_FOR_DEST);
                     status |= WAITING_FOR_PICK;
                  }
                  OnMenu(MyWindow,SHIFTMENU(0)|SHIFTITEM(NOITEM));
                  OnMenu(MyWindow,SHIFTMENU(1)|SHIFTITEM(NOITEM));
                  OnMenu(MyWindow,SHIFTMENU(2)|SHIFTITEM(NOITEM));
                  OffMenu(MyWindow,SWITCHSIDENR);
               }
            } else if (checkresult & CANT_BEAT_BUDDY) /* anderer Stein */
            {
               Highlight(HighX,HighY);
               HighX=X; HighY=Y;
               PNum = whatsonboard[X][Y];
               Highlight(HighX,HighY);
            } else {    /* Zug ist ungültig */
               last_error = checkresult;
            }
            break;
         case WAITING_FOR_CONF:
            status &= (~WAITING_FOR_CONF);
            playernr = !(status & PLAYER1_TO_MOVE); /* Nummer des Spielers */
            if (X==ConfirmX && Y==ConfirmY)
            {
               status |= WAITING_FOR_PICK;
               if (help[playernr]==SHOWKNOWN)
               {
                  Exchange(&fval[PNum][X][Y],&kval[PNum][X][Y]);
                  ThePieces[PNum].Value = fval[PNum][X][Y];
                  SetPiece(ThePieces[PNum],FALSE,FALSE);
               }
               Notify(playernr,moveresult);
               kval[PNum][X][Y] = fval[PNum][X][Y];
               if (status & IN_GAME)
               {
                  if (status & PLAYER1_TO_MOVE)
                  {
                     status &= (~PLAYER1_TO_MOVE);
                     NextPlayer(WHITE);
                  } else {
                     status |= PLAYER1_TO_MOVE;
                     NextPlayer(RED);
                  }
               }
               OnMenu(MyWindow,SHIFTMENU(0)|SHIFTITEM(NOITEM));
               OnMenu(MyWindow,SHIFTMENU(1)|SHIFTITEM(NOITEM));
               OnMenu(MyWindow,SHIFTMENU(2)|SHIFTITEM(NOITEM));
               OffMenu(MyWindow,SWITCHSIDENR);
            } else {
               undo();
               Highlight(HighX,HighY); /* alte Startposition */
               status |= WAITING_FOR_DEST;
               if (status & PLAYER1_TO_MOVE)
                  DrawText(9,JAM1,219,16,"Spieler 1");
               else
                  DrawText(9,JAM1,219,49,"Spieler 2");
               if (help[playernr]==SHOWKNOWN)
                  Exchange(&fval[PNum][ConfirmX][ConfirmY],
                           &kval[PNum][ConfirmX][ConfirmY]);
               }
            break;
         default:
            break;
      }
   }
}

void main(void)
{
   open_all();
   drawboard();
   drawplayers(NULL,NULL);
   setup_stdboard(FALSE);  /* Standard, nicht gedreht */
   joymouse_allowed=TRUE;
   ScreenToFront(MyScreen);
   wait_events();
}
