/* level.c --- level information
 *
 * This file is gift-ware.  This file is given to you freely
 * as a gift.  You may use, modify, redistribute, and generally hack
 * it about in any way you like, and you do not have to give anyone
 * anything in return.
 *
 * I do not accept any responsibility for any effects, adverse or
 * otherwise, that this code may have on just about anything that
 * you can think of.  Use it at your own risk.
 *
 * Copyright (C) 1999  Michael Bukin
 */

#include <ctype.h>
#include <stdlib.h>
#include <allegro.h>

#include "data.h"
#include "level.h"

/* Level info.  */
int eater_speed;
int ghost_speed;
int ghost_count;
int bonus_count;
int coin_count;
struct actor_t eater;
struct actor_t prize;
struct actor_t ghost[MAX_GHOST];
struct actor_t bonus[MAX_BONUS];
int map_info[MAP_HEIGHT][MAP_WIDTH];

/* Map descriptions.  */
#define MAX_MAP	1
static char map_text[MAX_MAP][MAP_HEIGHT][MAP_WIDTH + 1] =
{
  {
    "+-------------+-------------+",
    "|             |             |",
    "| +--+ +----+ | +----+ +--+ |",
    "|b+--+ +----+ + +----+ +--+b|",
    "|                           |",
    "| +--+ ++ +-------+ ++ +--+ |",
    "|      ||     +     ||      |",
    "+----+ |+---+x+x+---+| +----+",
    "xxxxx| ||xxxxxxxxxxx|| |xxxxx",
    "+----+ ++x+--+d+--+x++ +----+",
    "xxxxxx xxx|xxxgggg|xxx xxxxxx",
    "+----+ ++x+-------+x++ +----+",
    "xxxxx| ||xxxxxpxxxxx|| |xxxxx",
    "+----+ ++x+---+---+x++ +----+",
    "|             |             |",
    "| +--+ +----+ + +----+ +--+ |",
    "|b   |        s        |   b|",
    "+--+ + ++ +---+---+ ++ + +--+",
    "|      ||     |     ||      |",
    "| +----++---+ + +---++----+ |",
    "|                           |",
    "+---------------------------+"
  }
};

/*
 * Initialize map for new level.
 */
void
game_map_init (int level)
{
  int x, y;

  if (level > MAX_MAP)
    level = MAX_MAP - 1;

  /* TODO: Get speeds from table.  */
  eater_speed = 2 << SPEED_SHIFT;
  ghost_speed = 2 << SPEED_SHIFT;

  bonus_count = 0;
  ghost_count = 0;
  coin_count = 0;

  eater.x0 = -1;
  eater.y0 = -1;
  prize.x0 = -1;
  prize.y0 = -1;

  for (y = 0; y < MAP_HEIGHT; y++)
    {
      char *line = map_text[level][y];

      for (x = 0; x < MAP_WIDTH; x++)
	{
	  switch (tolower (line[x]))
	    {
	    case ' ':
	      /* Coin.  */
	      map_info[y][x] = CELL_COIN;
	      coin_count++;
	      break;
	    case 'x':
	    case '.':
	      /* Empty.  */
	      map_info[y][x] = CELL_VOID;
	      break;
	    case 'b':
	      /* Bonus.  */
	      if (bonus_count < MAX_BONUS)
		{
		  bonus[bonus_count].x0 = x * (20 << SPEED_SHIFT);
		  bonus[bonus_count].y0 = y * (20 << SPEED_SHIFT);
		  bonus_count++;
		}
	      map_info[y][x] = CELL_VOID;
	      break;
	    case 'd':
	      /* Door.  */
	      map_info[y][x] = CELL_DOOR;
	      break;
	    case 's':
	      /* Start.  */
	      eater.x0 = x * (20 << SPEED_SHIFT);
	      eater.y0 = y * (20 << SPEED_SHIFT);
	      map_info[y][x] = CELL_VOID;
	      break;
	    case 'g':
	      /* Ghost.  */
	      if (ghost_count < MAX_GHOST)
		{
		  ghost[ghost_count].x0 = x * (20 << SPEED_SHIFT);
		  ghost[ghost_count].y0 = y * (20 << SPEED_SHIFT);
		  ghost_count++;
		}
	      map_info[y][x] = CELL_VOID;
	      break;
	    case 'p':
	      /* Prize (and text position).  */
	      prize.x0 = x * (20 << SPEED_SHIFT);
	      prize.y0 = y * (20 << SPEED_SHIFT);
	      map_info[y][x] = CELL_VOID;
	      break;
	    default:
	      /* Wall.  */
	      map_info[y][x] = CELL_WALL;
	      break;
	    }
	}
    }

  /* Any essential info missing?  */
  if (eater.x0 == -1)
    {
      allegro_exit ();
      allegro_message ("Eater position was not defined!");
      exit (EXIT_FAILURE);
    }
  else if (prize.x0 == -1)
    {
      allegro_exit ();
      allegro_message ("Prize position was not defined!");
      exit (EXIT_FAILURE);
    }

  /* Test that walls are placed correctly.  */
  for (x = 0; x < MAP_WIDTH; x++)
    {
      if (((map_info[0][x] == CELL_WALL) && (map_info[MAP_HEIGHT - 1][x] != CELL_WALL))
	  || ((map_info[0][x] != CELL_WALL) && (map_info[MAP_HEIGHT - 1][x] == CELL_WALL)))
	{
	  allegro_exit ();
	  allegro_message ("Misplaced horizontal walls!");
	  exit (EXIT_FAILURE);
	}
    }
  for (y = 0; y < MAP_HEIGHT; y++)
    {
      if (((map_info[y][0] == CELL_WALL) && (map_info[y][MAP_WIDTH - 1] != CELL_WALL))
	  || ((map_info[y][0] != CELL_WALL) && (map_info[y][MAP_WIDTH - 1] == CELL_WALL)))
	{
	  allegro_exit ();
	  allegro_message ("Misplaced vertical walls!");
	  exit (EXIT_FAILURE);
	}
    }
}

/*
 * Restart level.
 */
void
game_level_restart (int level)
{
  int i;

  /* Initial eater state.  */
  eater.x = eater.x0;
  eater.y = eater.y0;
  eater.cdx = DIR_LEFT;
  eater.cdy = DIR_NONE;
  eater.ndx = DIR_LEFT;
  eater.ndy = DIR_NONE;
  eater.state = EATER_ENTER;
  eater.state_count = 0;
  eater.frame = 0;
  eater.frame_count = 0;

  /* Initial prize state.  */
  prize.x = prize.x0;
  prize.y = prize.y0;
  prize.state = PRIZE_ABSENT;
  prize.state_count = 0;
  prize.frame = 0;
  prize.frame_count = 0;

  /* Initial ghost states.  */
  for (i = 0; i < ghost_count; i++)
    {
      ghost[i].x = ghost[i].x0;
      ghost[i].y = ghost[i].y0;
      ghost[i].cdx = DIR_LEFT;
      ghost[i].cdy = DIR_NONE;
      ghost[i].state = GHOST_ENTER;
      ghost[i].state_count = 0;
      ghost[i].frame = 0;
      ghost[i].frame_count = 0;
    }

  /* Initial bonus states.  */
  for (i = 0; i < bonus_count; i++)
    {
      bonus[i].x = bonus[i].x0;
      bonus[i].y = bonus[i].y0;
      bonus[i].state = BONUS_VISIBLE;
      bonus[i].state_count = 0;
      bonus[i].frame = 0;
      bonus[i].frame_count = 0;
    }
}

/*
 * Draw current map.
 */
void
game_draw_map (BITMAP *buffer)
{
  int x, y;

  clear (buffer);
  for (y = 0; y < MAP_HEIGHT; y++)
    {
      for (x = 0; x < MAP_WIDTH; x++)
	{
	  int left = 0, up = 0, right = 0, down = 0;
	  int type = map_info[y][x];

	  if (type == CELL_COIN)
	    {
	      draw_sprite (buffer, coin_sprite, x * 20, y * 20);
	    }
	  else if (type == CELL_DOOR)
	    {
	      draw_sprite (buffer, door_sprite, x * 20, y * 20);
	    }
	  else if (type == CELL_WALL)
	    {
	      draw_sprite (buffer, wall_sprite, x * 20, y * 20);
	      if ((x != 0) && (map_info[y][x - 1] == CELL_WALL))
		{
		  left = 1;
		  draw_sprite (buffer, wall_left_sprite, x * 20, y * 20);
		}
	      if ((x != (MAP_WIDTH - 1)) && (map_info[y][x + 1] == CELL_WALL))
		{
		  right = 1;
		  draw_sprite (buffer, wall_right_sprite, x * 20, y * 20);
		}
	      if ((y != 0) && (map_info[y - 1][x] == CELL_WALL))
		{
		  up = 1;
		  draw_sprite (buffer, wall_up_sprite, x * 20, y * 20);
		}
	      if ((y != (MAP_HEIGHT - 1)) && (map_info[y + 1][x] == CELL_WALL))
		{
		  down = 1;
		  draw_sprite (buffer, wall_down_sprite, x * 20, y * 20);
		}

	      if (up && left && (map_info[y - 1][x - 1] == CELL_WALL))
		draw_sprite (buffer, wall_top_left_sprite, x * 20, y * 20);
	      if (up && right && (map_info[y - 1][x + 1] == CELL_WALL))
		draw_sprite (buffer, wall_top_right_sprite, x * 20, y * 20);
	      if (down && left && (map_info[y + 1][x - 1] == CELL_WALL))
		draw_sprite (buffer, wall_bottom_left_sprite, x * 20, y * 20);
	      if (down && right && (map_info[y + 1][x + 1] == CELL_WALL))
		draw_sprite (buffer, wall_bottom_right_sprite, x * 20, y * 20);
	    }
	}
    }
}

/*
 * level.c ends here
 */
