<commit_before>#include <stdio.h>
#include <stdlib.h>
#include "console.h"
#include "gamestate.h"
#include "util.h"

#define COLOR_BOLDBLACK   "\033[1m\033[30m"      /* Bold Black */
#define COLOR_BLUE    "\033[34m"      /* Blue */
#define COLOR_RED     "\033[31m"      /* Red */
#define TEXT_RESET   "\033[0m"
#define COLOR_RESET   "\033[0m"
#define COLOR_BOLDWHITE   "\033[1m\033[37m"      /* Bold White */
#define COLOR_MAGENTA "\033[35m"      /* Magenta */
#define COLOR_GREEN   "\033[32m"      /* Green */

#define TEXT_BLINK    "\033[5m"      /* BLINK */
#define TEXT_BLINKOFF   "\033[25m"      /* NO BLINK */

#define COLOR_BACK_RED     "\033[41m"      /* Red background */
#define COLOR_BACK_RED_HIGH     "\033[101m"      /* Red background high intensity */

#define COLOR_BACK_RESET    "\033[40m"      /* reset background */

void GameState_Init(GameState* state)
{
  u32 i;
  state->currentTick = 0;
  state->paused = false;
  state->heading = 15 * (rand() % 24);
  state->ammunition = 0x010101;
  state->currentHealth = GAMESTATE_INITIAL_HEALTH;
  PQue_Init(&(state->eventQueue));

  state->currentTorpedo = 0;
  for(i = 0; i < TORPEDO_ARRAY_LENGTH; i++)
  {
    Torpedo_Init(state->torpedos + i);
  }

  for(i = 0; i < ENEMY_ARRAY_LENGTH; i++)
  {
    Enemy_Init(state->enemies + i);
  }

  for(i = 0; i < GAMESTATE_INITIAL_ENEMIES; i++)
  {
    GameState_SpawnEnemy(state);
  }
}

u32 HomingsLeft(GameState* state)
{
  return (state->ammunition >> 16) & 0xff;
}

void AddToHomings(GameState* state, u32 amt)
{
  s32 warheads = HomingsLeft(state);
  warheads += amt;
  if(warheads > 0xff)
  {
    warheads = 0xff;
  }
  if(warheads < 0)
  {
    warheads = 0;
  }
  warheads <<= 16;
  state->ammunition &= 0xff00ffff;
  state->ammunition |= warheads;
}

u32 BoostersLeft(GameState* state)
{
  return state->ammunition & 0xff;
}

void AddToBoosters(GameState* state, s32 amt)
{
  s32 boosters = BoostersLeft(state);
  boosters += amt;
  if(boosters > 0xff)
  {
    boosters = 0xff;
  }
  if(boosters < 0)
  {
    boosters = 0;
  }
  state->ammunition &= 0xffffff00;
  state->ammunition |= boosters;
}

u32 WarheadsLeft(GameState* state)
{
  return (state->ammunition >> 8) & 0xff;
}

void AddToWarheads(GameState* state, s32 amt)
{
  s32 warheads = WarheadsLeft(state);
  warheads += amt;
  if(warheads > 0xff)
  {
    warheads = 0xff;
  }
  if(warheads < 0)
  {
    warheads = 0;
  }
  warheads <<= 8;
  state->ammunition &= 0xffff00ff;
  state->ammunition |= warheads;
}

void GameState_Pause(GameState* state)
{
  state->paused = !state->paused;
  printf("Game %s.\n", state->paused ? "paused" : "unpaused");
}

void Command_Execute(Command* command, GameState* state)
{
  u32* a = command->commandArgs;
  switch(command->argLength)
  {
  case 0: command->commFunc.c0(state); break;
  case 1: command->commFunc.c1(state, a[0]); break;
  case 2: command->commFunc.c2(state, a[0], a[1]); break;
  case 3: command->commFunc.c3(state, a[0], a[1], a[2]); break;
  case 4: command->commFunc.c4(state, a[0], a[1], a[2], a[3]); break;
  default: perror("Command_Execute: Invalid argument length!"); 
  exit(3); 
  return;
  }
}

void EvalCurrentEvents(GameState* state)
{
  Command* cmd;
  while(PQue_Size(&state->eventQueue) > 0 &&
	PQue_Peek(&state->eventQueue)->executionTick <= state->currentTick)
  {
    cmd = PQue_Remove(&state->eventQueue);
    Command_Execute(cmd, state);
    FreeCommand(cmd);
  }
}

bool EnemiesLeft(GameState* state)
{
  u32 i;
  for(i = 0; i < ENEMY_ARRAY_LENGTH; i++)
  {
    if(state->enemies[i].alive)
    {
      return true;
    }
  }
  return false;
}

void Torpedo_Advance(GameState* state, Torpedo* t)
{
  u32 speed = t->booster ? TORPEDO_BOOST_SPEED : TORPEDO_NORMAL_SPEED;
  u32 i;
  t->distance += speed;

  if(t->distance > TORPEDO_MAX_DISTANCE)
  {
    t->state = TORPEDOSTATE_STORAGE;
    printf("[WEAPONS]: Torpedo missed.\n");
    Torpedo_Init(t);
  }

  for(i = 0; i < ENEMY_ARRAY_LENGTH; i++)
  {
    Enemy* e = state->enemies + i;
    if(e->alive)
    {
      Torpedo* et = &e->torpedo;
      if(et->state == TORPEDOSTATE_FIRE)
      {
	if(et->heading == t->heading ||
	   (t->homing && (ABS(t->heading - et->heading) < ENEMY_DIFFUSE_LATERAL)))
	{
	  if(t->distance - speed <= et->distance &&
	     t->distance >= et->distance)
	  {
	    /* Hit another torpedo! */
	    printf(COLOR_MAGENTA 
		   "[SONAR]: Enemy Torpedo destroyed, heading %d degrees.\n"
		   COLOR_RESET, et->heading);
	    Torpedo_Init(t);
	    Torpedo_Init(et);
	    break;
	  }
	}
      }

      if(e->heading == t->heading ||
	 (t->homing && (ABS(t->heading - e->heading) < ENEMY_DIFFUSE_LATERAL)))
      {
	if(t->distance - speed <= e->distance &&
	   t->distance >= e->distance)
	{
	  /* HIT! */
	  if(!t->warhead && RANDONEIN(5))
	  {
	    /* Didn't do enough damage. */
	    printf(COLOR_GREEN "[WEAPONS]: Enemy hit, but remains at %d degrees.\n",
		   e->heading);
	    Torpedo_Init(t);
	    break;
	  }
	  else
	  {
	    u32 upgrades = 1 + (rand() % 3);
	    printf(COLOR_GREEN "[WEAPONS]: Enemy neutralized.\n" COLOR_RESET);

	    switch(rand() % 3)
	    {
	    case 0: printf("[HELM]: Upgrade received: %d booster%s.", upgrades,
			   upgrades > 1 ? "s" : "");
	      AddToBoosters(state, upgrades); break;
	    case 1: printf("[HELM]: Upgrade received: %d warhead%s.", upgrades,
			   upgrades > 1 ? "s" : "");
	      AddToWarheads(state, upgrades); break;
	    case 2: printf("[HELM]: Upgrade received: %d homing%s.", upgrades,
			   upgrades > 1 ? "s" : "");
	      AddToHomings(state, upgrades); break;
	    }
	    Torpedo_Init(t);
	    Enemy_Init(e);

	    if(!EnemiesLeft(state))
	    {
	      printf("[SONAR]: All enemies neutralized. Moving to deeper waters...");
	      Console_IncreaseTickSpeed();
	      GameState_Init(state);
	    }
	    break;
	  }
	}
      }
    }
  }
}


void GameState_AdvanceTorpedos(GameState* state)
{<commit_msg>Tested endgame, seems to work<commit_after>#include <stdio.h>
#include <stdlib.h>
#include "console.h"
#include "gamestate.h"
#include "util.h"

#define COLOR_BOLDBLACK   "\033[1m\033[30m"      /* Bold Black */
#define COLOR_BLUE    "\033[34m"      /* Blue */
#define COLOR_RED     "\033[31m"      /* Red */
#define TEXT_RESET   "\033[0m"
#define COLOR_RESET   "\033[0m"
#define COLOR_BOLDWHITE   "\033[1m\033[37m"      /* Bold White */
#define COLOR_MAGENTA "\033[35m"      /* Magenta */
#define COLOR_GREEN   "\033[32m"      /* Green */

#define TEXT_BLINK    "\033[5m"      /* BLINK */
#define TEXT_BLINKOFF   "\033[25m"      /* NO BLINK */

#define COLOR_BACK_RED     "\033[41m"      /* Red background */
#define COLOR_BACK_RED_HIGH     "\033[101m"      /* Red background high intensity */

#define COLOR_BACK_RESET    "\033[40m"      /* reset background */

void GameState_Init(GameState* state)
{
  u32 i;
  state->currentTick = 0;
  state->paused = false;
  state->heading = 15 * (rand() % 24);
  state->ammunition = 0x010101;
  state->currentHealth = GAMESTATE_INITIAL_HEALTH;
  PQue_Init(&(state->eventQueue));

  state->currentTorpedo = 0;
  for(i = 0; i < TORPEDO_ARRAY_LENGTH; i++)
  {
    Torpedo_Init(state->torpedos + i);
  }

  for(i = 0; i < ENEMY_ARRAY_LENGTH; i++)
  {
    Enemy_Init(state->enemies + i);
  }

  for(i = 0; i < GAMESTATE_INITIAL_ENEMIES; i++)
  {
    GameState_SpawnEnemy(state);
  }
}

u32 HomingsLeft(GameState* state)
{
  return (state->ammunition >> 16) & 0xff;
}

void AddToHomings(GameState* state, u32 amt)
{
  s32 warheads = HomingsLeft(state);
  warheads += amt;
  if(warheads > 0xff)
  {
    warheads = 0xff;
  }
  if(warheads < 0)
  {
    warheads = 0;
  }
  warheads <<= 16;
  state->ammunition &= 0xff00ffff;
  state->ammunition |= warheads;
}

u32 BoostersLeft(GameState* state)
{
  return state->ammunition & 0xff;
}

void AddToBoosters(GameState* state, s32 amt)
{
  s32 boosters = BoostersLeft(state);
  boosters += amt;
  if(boosters > 0xff)
  {
    boosters = 0xff;
  }
  if(boosters < 0)
  {
    boosters = 0;
  }
  state->ammunition &= 0xffffff00;
  state->ammunition |= boosters;
}

u32 WarheadsLeft(GameState* state)
{
  return (state->ammunition >> 8) & 0xff;
}

void AddToWarheads(GameState* state, s32 amt)
{
  s32 warheads = WarheadsLeft(state);
  warheads += amt;
  if(warheads > 0xff)
  {
    warheads = 0xff;
  }
  if(warheads < 0)
  {
    warheads = 0;
  }
  warheads <<= 8;
  state->ammunition &= 0xffff00ff;
  state->ammunition |= warheads;
}

void GameState_Pause(GameState* state)
{
  state->paused = !state->paused;
  printf("Game %s.\n", state->paused ? "paused" : "unpaused");
}

void Command_Execute(Command* command, GameState* state)
{
  u32* a = command->commandArgs;
  switch(command->argLength)
  {
  case 0: command->commFunc.c0(state); break;
  case 1: command->commFunc.c1(state, a[0]); break;
  case 2: command->commFunc.c2(state, a[0], a[1]); break;
  case 3: command->commFunc.c3(state, a[0], a[1], a[2]); break;
  case 4: command->commFunc.c4(state, a[0], a[1], a[2], a[3]); break;
  default: perror("Command_Execute: Invalid argument length!"); 
  exit(3); 
  return;
  }
}

void EvalCurrentEvents(GameState* state)
{
  Command* cmd;
  while(PQue_Size(&state->eventQueue) > 0 &&
	PQue_Peek(&state->eventQueue)->executionTick <= state->currentTick)
  {
    cmd = PQue_Remove(&state->eventQueue);
    Command_Execute(cmd, state);
    FreeCommand(cmd);
  }
}

bool EnemiesLeft(GameState* state)
{
  u32 i;
  for(i = 0; i < ENEMY_ARRAY_LENGTH; i++)
  {
    if(state->enemies[i].alive)
    {
      return true;
    }
  }
  return false;
}

void Torpedo_Advance(GameState* state, Torpedo* t)
{
  u32 speed = t->booster ? TORPEDO_BOOST_SPEED : TORPEDO_NORMAL_SPEED;
  u32 i;
  t->distance += speed;

  if(t->distance > TORPEDO_MAX_DISTANCE)
  {
    t->state = TORPEDOSTATE_STORAGE;
    printf("[WEAPONS]: Torpedo missed.\n");
    Torpedo_Init(t);
  }

  for(i = 0; i < ENEMY_ARRAY_LENGTH; i++)
  {
    Enemy* e = state->enemies + i;
    if(e->alive)
    {
      Torpedo* et = &e->torpedo;
      if(et->state == TORPEDOSTATE_FIRE)
      {
	if(et->heading == t->heading ||
	   (t->homing && (ABS(t->heading - et->heading) < ENEMY_DIFFUSE_LATERAL)))
	{
	  if(t->distance - speed <= et->distance &&
	     t->distance >= et->distance)
	  {
	    /* Hit another torpedo! */
	    printf(COLOR_MAGENTA 
		   "[SONAR]: Enemy Torpedo destroyed, heading %d degrees.\n"
		   COLOR_RESET, et->heading);
	    Torpedo_Init(t);
	    Torpedo_Init(et);
	    break;
	  }
	}
      }

      if(e->heading == t->heading ||
	 (t->homing && (ABS(t->heading - e->heading) < ENEMY_DIFFUSE_LATERAL)))
      {
	if(t->distance - speed <= e->distance &&
	   t->distance >= e->distance)
	{
	  /* HIT! */
	  if(!t->warhead && RANDONEIN(5))
	  {
	    /* Didn't do enough damage. */
	    printf(COLOR_GREEN "[WEAPONS]: Enemy hit, but remains at %d degrees.\n",
		   e->heading);
	    Torpedo_Init(t);
	    break;
	  }
	  else
	  {
	    u32 upgrades = 1 + (rand() % 3);
	    printf(COLOR_GREEN "[WEAPONS]: Enemy neutralized.\n" COLOR_RESET);

	    switch(rand() % 3)
	    {
	    case 0: printf("[HELM]: Upgrade received: %d booster%s.", upgrades,
			   upgrades > 1 ? "s" : "");
	      AddToBoosters(state, upgrades); break;
	    case 1: printf("[HELM]: Upgrade received: %d warhead%s.", upgrades,
			   upgrades > 1 ? "s" : "");
	      AddToWarheads(state, upgrades); break;
	    case 2: printf("[HELM]: Upgrade received: %d homing%s.", upgrades,
			   upgrades > 1 ? "s" : "");
	      AddToHomings(state, upgrades); break;
	    }
	    Torpedo_Init(t);
	    Enemy_Init(e);

	    if(!EnemiesLeft(state))
	    {
	      printf("[SONAR]: All enemies neutralized. Moving to deeper waters...\n");
	      Console_IncreaseTickSpeed();
	      GameState_Init(state);
	    }
	    break;
	  }
	}
      }
    }
  }
}


void GameState_AdvanceTorpedos(GameState* state)
{
{'fraction_non_alphanumeric': 0.16378139850644943, 'fraction_numerical': 0.030719619823489478, 'mean_word_length': 3.0331964407939767, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 161, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1496228', 'n_tokens_mistral': 5014, 'n_tokens_neox': 4570, 'n_words': 902}