#include "geki4.h"
#include "extern.h"

/****************************
  自分データ削除
 ****************************/
int DeleteMyData(Uint16 m)
{
  if (Root->My[m]->Chr.Active == True) {
    Root->My[m]->Chr.Active = False;
    Root->MyNo --;
    return True;
  }
  return False;
}

/****************************
  敵データ削除
 ****************************/
int DeleteYourData(Uint16 y)
{
  if (Root->Your[y]->Chr.Active == True) {
    Root->Your[y]->Chr.Active = False;
    Root->YourNo --;
    return True;
  }
  return False;
}

/****************************
 敵データ作成
 ****************************/
Sint16 CopyYourNew(RcHitEnum (*act)(CharacterData *my),
		   RcHitEnum (*hit)(CharacterData *my, CharacterData *your),
		   void (*re)(CharacterData *my))
{
  Uint16 i;
  
  if (Root->YourNo >= MAX_YOUR)
    return -1;
  for (i = 0; i < MAX_YOUR; i ++) {
    if (Root->Your[i]->Chr.Active == False) {
      Root->Your[i]->Chr         = Cchr;
      Root->Your[i]->Move        = act;
      Root->Your[i]->Hit         = hit;
      Root->Your[i]->Draw        = re;
      Root->Your[i]->Chr.Active  = True;
      Root->Your[i]->Chr.Cnt1    = 0;
      Root->YourNo ++;
      return i;
    }
  }
}

/****************************
 自分データ作成
 ****************************/
Sint16 CopyMyNew(RcHitEnum (*act)(CharacterData *my),
		 RcHitEnum (*hit)(CharacterData *my, CharacterData *your),
		 void (*re)(CharacterData *my))
{
  Uint16 i;
  
  if (Root->MyNo >= MAX_MY)
    return -1;
  for (i = 1; i < MAX_MY; i ++) {
    if (Root->My[i]->Chr.Active == False) {
      Root->My[i]->Chr         = Cchr;
      Root->My[i]->Move        = act;
      Root->My[i]->Hit         = hit;
      Root->My[i]->Draw        = re;
      Root->My[i]->Chr.Active  = True;
      Root->MyNo ++;
      return i;
    }
  }
}

/****************************
  当り判定
 ****************************/
Bool Check(CharacterData *my, CharacterData *your)
{
  Uint16 i;
  Sint16 z = BASE_Z + my->Z;
  Sint16 ax = my->X * BASE_Z / z + my->Spr[my->Z]->AddX;
  Sint16 ay = my->Y * BASE_Z / z + my->Spr[my->Z]->AddY; 
  Sint16 bx = your->X * BASE_Z / z + your->Spr[your->Z]->AddX;
  Sint16 by = your->Y * BASE_Z / z + your->Spr[your->Z]->AddY;
  
  for (i = 0; i < 4; i ++)
    if (ax + my->Spr[my->Z]->x[i] >= bx + your->Spr[your->Z]->x[0] &&
	ax + my->Spr[my->Z]->x[i] <= bx + your->Spr[your->Z]->x[1] &&
	ay + my->Spr[my->Z]->y[i] >= by + your->Spr[your->Z]->y[0] &&
	ay + my->Spr[my->Z]->y[i] <= by + your->Spr[your->Z]->y[2])
      return True;
  for (i = 0; i < 4; i ++)
    if (bx + your->Spr[your->Z]->x[i] >= ax + my->Spr[my->Z]->x[0] &&
	bx + your->Spr[your->Z]->x[i] <= ax + my->Spr[my->Z]->x[1] &&
	by + your->Spr[your->Z]->y[i] >= ay + my->Spr[my->Z]->y[0] &&
	by + your->Spr[your->Z]->y[i] <= ay + my->Spr[my->Z]->y[2])
      return True;
  return False;
}

/****************************
  ゲームメイン
 ****************************/
void Game(void)
{
  RcHitEnum rc;
  Sint16 m, y;
  Uint16 i;
  Uint8 text[81];

  /** 背景 **/
  KXL_PutImage(PixSky[0]->Image, AREA_LX, AREA_LY);
  for (i = 0; i < 10; i ++)
    KXL_PutImage(PixBack[Root->Cnt % 3]->Image, AREA_LX + i * 50, AREA_RY - 120);
  /** 敵等発生 **/
  for (i = 0; i < Root->StageMax; i ++) {
    if (Root->EnemyCnt == StageDatas[i]->Time &&
        StageDatas[i]->Flag == False) {
      StageDatas[i]->Flag = True;
    }
  }
  for (i = 0; i < Root->StageMax; i ++) {
    if (StageDatas[i]->Flag == True) {
      if (StageDatas[i]->Max) {
        if (!StageDatas[i]->StepTime) {
          StageDatas[i]->Max --;
          StageDatas[i]->StepTime = StageDatas[i]->Step;
          switch (StageDatas[i]->CreateNo) {
	  case 0: /** 障害物 **/
	    CreateWall((rand() % 500) - 250);
	    break;
          case 1: /**  顔 **/
	    CreateEnemy1((rand() % 500) - 250, (rand() % 300) - 150);
            break;
          case 2: /**  飛行機 **/
	    CreateEnemy2((rand() % 500) - 250, (rand() % 300) - 150);
            break;
	  case 99: /** ボス **/
	    KXL_PlaySound(0, KXL_SOUND_STOP_ALL);
	    KXL_PlaySound(SE_BOSS, KXL_SOUND_PLAY_LOOP);
	    CreateBoss1();
	    break;
          }
        } else
          StageDatas[i]->StepTime --;
      } else
        StageDatas[i]->Flag = False;
    }
  }
  if (Root->EnemyCnt < 10000)
    Root->EnemyCnt ++;

  /** 敵移動 **/
  for (y = 0; y < MAX_YOUR; y ++) {
    if (Root->Your[y]->Chr.Active == True) {
      rc = Root->Your[y]->Move(&(Root->Your[y]->Chr));
      switch (rc) {
      case RcHitBoss:
	Root->MainFlag = MainClear;
	Root->Cnt = -1;
	Root->Score += Root->Your[y]->Chr.Score;
	if (Root->HiScore < Root->Score)
	  Root->HiScore = Root->Score;
      case RcHitDel:
	DeleteYourData(y);
	break;
      default:
	break;
      }
    }
  }
  /** 自分移動 **/
  for (m = 0; m < MAX_MY; m ++)
    if (Root->My[m]->Chr.Active == True)
      if ((rc = Root->My[m]->Move(&(Root->My[m]->Chr))) == RcHitDel)
        DeleteMyData(m);
  /** 当り判定 **/
  for (m = MAX_MY - 1; m >= 0; m --) {
    if (Root->My[m]->Chr.Active == False)
      continue;
    for (y = 0; y < MAX_YOUR; y ++) {
      if (Root->Your[y]->Chr.Active == False)
        continue;
      if (Root->My[m]->Chr.Z != Root->Your[y]->Chr.Z &&
	  Root->My[m]->Chr.Z != Root->Your[y]->Chr.Z - 1)
	continue;
      if (Root->My[m]->Chr.Target & Root->Your[y]->Chr.Attr) {
        if (Check(&(Root->My[m]->Chr), &(Root->Your[y]->Chr)) == False)
          continue;
        if (Root->My[m]->Hit(&(Root->My[m]->Chr), &(Root->Your[y]->Chr)) == RcHitDel)
          DeleteMyData(m);
        rc = Root->Your[y]->Hit(&(Root->Your[y]->Chr), &(Root->My[m]->Chr));
        switch (rc) {
        case RcHitBomb:
	  Root->Score += Root->Your[y]->Chr.Score;
	  if (Root->HiScore < Root->Score)
	    Root->HiScore = Root->Score;
        case RcHitDel:
          DeleteYourData(y);
          break;
        default:
          break;
        }
      }
    }
  }
  /** 敵描画 **/
  for (m = MAX_Z - 1; m >= 0; m --) {
    for (y = MAX_YOUR - 1; y >= 0; y --) {
      if (Root->Your[y]->Chr.Active == False || Root->Your[y]->Chr.Z != m)
	continue;
      Root->Your[y]->Draw(&(Root->Your[y]->Chr));
    }
  }
  /** 自分描画 **/
  for (y = MAX_Z - 1; y >= 0; y --) {
    for (m = MAX_MY - 1; m >= 0; m --) {
      if (Root->My[m]->Chr.Active == False || Root->My[m]->Chr.Z != y)
	continue;
      Root->My[m]->Draw(&(Root->My[m]->Chr));
    }
  }
  /** スコア等描画 **/
  KXL_Font(NULL, 0xff, 0xff, 0xff);
  sprintf(text, "Score %06d   Hi-Score %06d   Stage %d   Man %d",
	  Root->Score, Root->HiScore, Root->Stage + 1, Root->Left);
  KXL_PutText(AREA_LX + 28, AREA_LY + 12, text);
}
