#include "allegro.h"

#ifdef _WIN32
#include "winalleg.h"

#include <winsock.h>
#else
#define SOCKET_ERROR -1
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netdb.h>
#endif

#include "defs.h"
#include "console.h"
#include "items.h"
#include "rules.h"

int gameType;
int teamplay;
int tactics;
int fragLimit;
int lifeLimit;

worm *predator;

worm *scores[GP_MAX_PLAYERS];

char gameNames[NUM_GAMES][20]= {"Kill 'em all", "Free for all", "Predator Deathmatch", "Capture the flag", "Game of Tag", "Domination"};
char teamplayNames[2][20]= {"Teamplay OFF", "Teamplay ON"};
char tacticalNames[2][20]= {"Tactics OFF", "Tactics ON"};

void giveScore(worm *player, int amount)
{
   int i;

   if (teamplay)
   {
      for (i=0; i < GP_NUM_PLAYERS; i++)
      {
         if (worms[i].team == player->team)
         {
            worms[i].kills += amount;
         }
      }
   }
   else
      player->kills += amount;
}

void playerDead(worm *attacker, worm *prey, weapon *weap)
{
   int i, distX, distY;
   interact *tmpItem;

   for (i=0; i < GP_NUM_PLAYERS; i++)
   {
      if (worms[i].flags[FL_GOT_ENEMY])
      if (worms[i].lineCatch == prey)
      {
         worms[i].flags[FL_GOT_ENEMY] = 0;
         worms[i].ropevel = prey->vel;
      }
   }

   tmpItem = itemList;
   while (tmpItem)
   {
      if (tmpItem->owner == prey)
         tmpItem->ownerDead(attacker);
      tmpItem = tmpItem->next;
   }

   distX = prey->coords.x - viewport[0].CurX;
   distY = prey->coords.y - viewport[0].CurY;
   if ((distX >= 0) && (distX<320) && (distY >= 0) && (distY<150))
      next_screenshot = gameTime + deathcam_delay;

   prey->flags[FL_ROPE_OUT] = 0;

   if (attacker != prey)
   {
      Console.WriteF("%s was killed by %s's %s.", prey->name, attacker->name, weap->name);
      if ((gameType != GAME_CTF) && (gameType != GAME_DOM))
      if (gameType == GAME_TAG) // a Game of Tag
      {
         if (predator->flags[FL_PREDATOR])
         {
            if (attacker->flags[FL_PREDATOR])
            {
               predator = prey;
               attacker->flags[FL_PREDATOR] = 0;
               prey->flags[FL_PREDATOR] = 1;
               prey->localTime = gameTime;
               Console.WriteCF("%s becomes the new IT.", predator->name);
            }
         }
         else // we don't have a pradator ATM
         {
            predator = prey;
            prey->flags[FL_PREDATOR] = 1;
            prey->localTime = gameTime;
            Console.WriteCF("%s becomes the IT.", predator->name);
         }
      }
      else if (gameType == GAME_PRD) // Predator DeathMatch
      {
         if (predator->flags[FL_PREDATOR])
         {
            if (attacker->flags[FL_PREDATOR])
            {
               giveScore(attacker, 1);
            }
            else
            if (prey->flags[FL_PREDATOR]) {
               predator = attacker;
               attacker->flags[FL_PREDATOR] = 1;
               prey->flags[FL_PREDATOR] = 0;
               Console.WriteCF("%s becomes the new predator.", predator->name);
            }
         }
         else // we don't have a pradator ATM
         {
            predator = attacker;
            attacker->flags[FL_PREDATOR] = 1;
            Console.WriteCF("%s becomes the predator.", predator->name);
         }
      }
      else
      {
         if ((teamplay) && (attacker->team == prey->team))
            giveScore(attacker, -1);
         else
            giveScore(attacker, 1);
      }
   }
   else
   {
      if (gameType == GAME_PRD)
      {
         prey->flags[FL_PREDATOR] = 0;
      }

      if (weap)
            Console.WriteF("%s commited suicide using his %s.", prey->name, weap->name);
      else
            Console.WriteF("%s fell to his death.", prey->name);

      if (gameType != GAME_KTA)
      if (gameType != GAME_CTF)
      if (gameType != GAME_DOM)
      if (gameType != GAME_TAG)
         giveScore(attacker, -1);
      if (gameType == GAME_TAG)
         giveScore(attacker, 1);
   }
   if (gameType == GAME_KTA)
      prey->lives--;
   if ((prey->lives>0) || (gameType != GAME_KTA))
   {
      prey->next_spawn = gameTime + GP_WORM_RESPAWN;
   }
   else
   {
      Console.WriteF("%s is no more.", prey->name);
   }
   prey->enemy = NULL;
   checkRules();
}

void sortScores()
{
   int i, j;
   worm *tmpWorm;

   for (i=0; i<GP_NUM_PLAYERS; i++)
      scores[i] = &worms[i];
   for (i=0; i<GP_NUM_PLAYERS-1; i++)
   for (j=i+1; j<GP_NUM_PLAYERS; j++)
   if (((gameType != GAME_TAG) && (((scores[j]->kills > scores[i]->kills) && (scores[j]->active)) || (!scores[i]->active))) ||
       ((gameType == GAME_TAG) && (((scores[j]->kills < scores[i]->kills) && (scores[j]->active)) || (!scores[i]->active))))
   {
      tmpWorm = scores[j];
      scores[j] = scores[i];
      scores[i] = tmpWorm;
   }
}

void checkRules()
{
   char isGameOver = 1;
   int i;
   worm *tmpWorm = NULL;
   
   if (gameType == GAME_KTA) // Kill 'em All
   {
      if (teamplay)
      {
         for (i=0; i<GP_NUM_PLAYERS; i++)
         if (worms[i].lives > 0)
         {
            if (!tmpWorm)
               tmpWorm = &worms[i];
            else 
               if (tmpWorm->team != worms[i].team) // other teams still alive
                  isGameOver = 0;
         }
      }
      else
      {
         for (i=0; i<GP_NUM_PLAYERS; i++)
         if (worms[i].lives > 0)
         {
            if (!tmpWorm)
               tmpWorm = &worms[i];
            else // more alive players
               isGameOver = 0;
         }
      }
   }
   else if (gameType == GAME_TAG) // a Game of Tag
   {
      isGameOver = 0;
      if (fragLimit)
      {
         isGameOver = 1;
         for (i=0; i<GP_NUM_PLAYERS; i++)
         if (worms[i].kills < fragLimit)
         {
            if (!tmpWorm)
               tmpWorm = &worms[i];
            else 
               if (tmpWorm->team != worms[i].team) // other teams still running
                  isGameOver = 0;
         }
      }
   }
   else // Free for All, Predator DM, Domination or CTF
   {
      isGameOver = 0;
      if (fragLimit)
      for (i=0; i<GP_NUM_PLAYERS; i++)
      if (worms[i].kills >= fragLimit)
      {
         isGameOver = 1;
      }
   }
   gameOver = isGameOver;
}

