#include <fstream>
#include "CPlayer.hpp"
#include "CMap.hpp"
#include "CDisplay.hpp"
#include "Interaction.hpp"
#include "CCine.hpp"
#include "Quests.hpp"


int level_table[MAX_LEVEL]; // max ten levels


CEventCheck::CEventCheck()
{
  name = "";
  x = 0;
  y = 0;
}


CPlayer player[2];

CPlayer::CPlayer()
{
    xoff = 0;
    yoff = 0;
    moving = 0;
	x = 64;
	y = 64;
	cam.x = 0;
	cam.y = 0; 
	facing = 0;
	frame = 0;
	
	name = "Javez";
	str=wis=intell=con=chr=hp=max_hp=mana=max_mana=0;
	exp = 0;
	level = 1;
	ac = 0;
	dam = 1;
	base_dam = 1;
	gold = 10;
	
    max_battles = 25;
   	fought_battles.resize(max_battles);
    for(int i = 0; i<max_battles; ++i)
       fought_battles[i] = "empty";

	movement_range = 5;
	fighting_range = 1;
	
	event_check.resize(1);

    level_table[0] = 0; // level 0 do nothing (padding)
    level_table[1] = 0; // level 1 you start at level 1
    level_table[2] = 6; // level 2
    level_table[3] = 25;
    level_table[4] = 100;
    level_table[5] = 300;
    level_table[6] = 500;
    level_table[7] = 800;
    level_table[8] = 1000;
    level_table[9] = 3000;
    level_table[10] = 6000;
//	portrait = load_bitmap("./data/portraits/maincharacter.bmp", NULL);
}

CPlayer::~CPlayer()
{
}
void CPlayer::Move(CMap map, int direction)
{
	switch(direction)
	{
	case NORTH:
		facing = NORTH;
		if( !map.Collision(x,y-1) && !map.Collision(x+16-1,y-1) && !map.CheckNpcs(x, y-1) ) y--;
		//if ( !CHECK_BIT(map.tile[0][y/map.sizeh][x/map.sizew].gfx, FLAG_WALKABLE) ) y--;
		if( y > screen->h/2 &&  y < map.GetHeight()*map.sizeh - screen->h/2) cam.y = y - screen->h/2;
		if( y < screen->h/2) cam.y = 0;
		if( y > map.GetHeight()*map.sizeh - screen->h/2) cam.y = map.GetHeight()*map.sizeh - screen->h-1;
		break;
	case SOUTH:
		facing = SOUTH;
		if( !map.Collision(x,y+16) && !map.Collision(x+16-1,y+16) && !map.CheckNpcs(x, y+1)  ) y++;
		if( y > screen->h/2 &&  y < map.GetHeight()*map.sizeh - screen->h/2) cam.y = y - screen->h/2;
		if( y < screen->h/2) cam.y = 0;        
		if( y > map.GetHeight()*map.sizeh - screen->h/2) cam.y = map.GetHeight()*map.sizeh - screen->h-1;
		break;
	case EAST:
		facing = EAST;
		if( !map.Collision(x+16, y) && !map.Collision(x+16, y+16-1) && !map.CheckNpcs(x+1, y) ) x++;
	    if( x > screen->w/2 && x < map.GetWidth()*map.sizew - screen->w/2) cam.x = x - screen->w/2;
		if( x < screen->w/2) cam.x = 0;
		if( x > map.GetWidth()*map.sizew - screen->w/2) cam.x = map.GetWidth()*map.sizew - screen->w;
		break;
	case WEST:
		facing = WEST;
		if( !map.Collision(x-1, y) && !map.Collision(x-1, y+16-1) && !map.CheckNpcs(x-1, y) ) x--;
		if( x > screen->w/2 && x < map.GetWidth()*map.sizew - screen->w/2) cam.x = x - screen->w/2;
		if( x < screen->w/2) cam.x = 0;
		if( x > map.GetWidth()*map.sizew - screen->w/2) cam.x = map.GetWidth()*map.sizew - screen->w;
		break;
	}
}

// TODO: Bug if the player is moving at the same time as an NPC it will get stuck! but it shouldn't matter in the
// battle system because everything move separately!
void CPlayer::MoveBlock(CMap map, int direction)
{
if(moving == 0)
 	switch(direction)
	{
	case NORTH:
		facing = NORTH;
		if( !map.Collision(x,y-1) && !map.Collision(x+16-1,y-1) && !map.CheckNpcs(x, y-1) && !map.CheckPlayer(x, y-16))
		{
      //   y--;
         yoff = 16;
        moving = 1;
        }
		//if ( !CHECK_BIT(map.tile[0][y/map.sizeh][x/map.sizew].gfx, FLAG_WALKABLE) ) y--;
	//	if( y+yoff > screen->h/2 &&  y < map.GetHeight()*map.sizeh - screen->h/2) cam.y = y - screen->h/2;
	//	if( y+yoff < screen->h/2) cam.y = 0;
//		if( y+yoff > map.GetHeight()*map.sizeh - screen->h/2) cam.y = map.GetHeight()*map.sizeh - screen->h;
		break;
	case SOUTH:
		facing = SOUTH;
		if( !map.Collision(x,y+16) && !map.Collision(x+16-1,y+16) && !map.CheckNpcs(x, y+1) && !map.CheckPlayer(x, y+16) )
		{
        // y++;
         yoff = -16;
        moving = 1;
        }
	//	if( y > screen->h/2 &&  y < map.GetHeight()*map.sizeh - screen->h/2) cam.y = y+yoff - screen->h/2;
	//	if( y < screen->h/2) cam.y = 0;
	//	if( y > map.GetHeight()*map.sizeh - screen->h/2) cam.y = map.GetHeight()*map.sizeh - screen->h;
		break;
	case EAST:
		facing = EAST;
		if( !map.Collision(x+16, y) && !map.Collision(x+16, y+16-1) && !map.CheckNpcs(x+1, y) && !map.CheckPlayer(x+16, y) )
		{
       // x++;
        xoff = -16;
        moving = 1;
        }
	   // if( x > screen->w/2 && x < map.GetWidth()*map.sizew - screen->w/2) cam.x = x - screen->w/2;
	//	if( x < screen->w/2) cam.x = 0;
	//	if( x > map.GetWidth()*map.sizew - screen->w/2) cam.x = map.GetWidth()*map.sizew - screen->w;
		break;
	case WEST:
		facing = WEST;
		if( !map.Collision(x-1, y) && !map.Collision(x-1, y+16-1) && !map.CheckNpcs(x-1, y) && !map.CheckPlayer(x-16, y) )
		{
       // x--;
        xoff = 16;
        moving = 1;
        }
		//if( x > screen->w/2 && x < map.GetWidth()*map.sizew - screen->w/2) cam.x = x - screen->w/2;
		//if( x < screen->w/2) cam.x = 0;
		//if( x > map.GetWidth()*map.sizew - screen->w/2) cam.x = map.GetWidth()*map.sizew - screen->w;
		break;
	}

}

// Removes collision for npcs... used for battle sys
void CPlayer::ViewBlock(CMap map, int direction)
{
if(moving == 0)
 	switch(direction)
	{
	case NORTH:
		facing = NORTH;
		if( !map.Collision(x,y-1) && !map.Collision(x+16-1,y-1))
		{
      //   y--;
         yoff = 16;
        moving = 1;
        }
		//if ( !CHECK_BIT(map.tile[0][y/map.sizeh][x/map.sizew].gfx, FLAG_WALKABLE) ) y--;
	//	if( y+yoff > screen->h/2 &&  y < map.GetHeight()*map.sizeh - screen->h/2) cam.y = y - screen->h/2;
	//	if( y+yoff < screen->h/2) cam.y = 0;
//		if( y+yoff > map.GetHeight()*map.sizeh - screen->h/2) cam.y = map.GetHeight()*map.sizeh - screen->h;
		break;
	case SOUTH:
		facing = SOUTH;
		if( !map.Collision(x,y+16) && !map.Collision(x+16-1,y+16) )
		{
        // y++;
         yoff = -16;
        moving = 1;
        }
	//	if( y > screen->h/2 &&  y < map.GetHeight()*map.sizeh - screen->h/2) cam.y = y+yoff - screen->h/2;
	//	if( y < screen->h/2) cam.y = 0;
	//	if( y > map.GetHeight()*map.sizeh - screen->h/2) cam.y = map.GetHeight()*map.sizeh - screen->h;
		break;
	case EAST:
		facing = EAST;
		if( !map.Collision(x+16, y) && !map.Collision(x+16, y+16-1)  )
		{
       // x++;
        xoff = -16;
        moving = 1;
        }
	   // if( x > screen->w/2 && x < map.GetWidth()*map.sizew - screen->w/2) cam.x = x - screen->w/2;
	//	if( x < screen->w/2) cam.x = 0;
	//	if( x > map.GetWidth()*map.sizew - screen->w/2) cam.x = map.GetWidth()*map.sizew - screen->w;
		break;
	case WEST:
		facing = WEST;
		if( !map.Collision(x-1, y) && !map.Collision(x-1, y+16-1) )
		{
       // x--;
        xoff = 16;
        moving = 1;
        }
		//if( x > screen->w/2 && x < map.GetWidth()*map.sizew - screen->w/2) cam.x = x - screen->w/2;
		//if( x < screen->w/2) cam.x = 0;
		//if( x > map.GetWidth()*map.sizew - screen->w/2) cam.x = map.GetWidth()*map.sizew - screen->w;
		break;
	}

}

void CPlayer::UpdateMovement()
{
     if(moving == 1)
     {

        if(xoff > 0)
        {
            x--;
            xoff--;
        }
		else if(xoff < 0)
		{
          x++;
          xoff++;
        }
       else if(yoff > 0)
        {
            y--;
            yoff--;
        }
        else if(yoff < 0)
        {
            y++;
            yoff++;
        }
        
		if( xoff == 0 && yoff == 0)
			moving = 0;
     }
     


		if( y > screen->h/2 &&  y < map.GetHeight()*map.sizeh - screen->h/2) cam.y = y - screen->h/2-1;
		if( y < screen->h/2) cam.y = 0;
		if( y > map.GetHeight()*map.sizeh - screen->h/2) cam.y = map.GetHeight()*map.sizeh - screen->h-1;
     	if( x > screen->w/2 && x <= map.GetWidth()*map.sizew - screen->w/2) cam.x = x - screen->w/2;
		if( x < screen->w/2) cam.x = 0;
		if( x > map.GetWidth()*map.sizew - screen->w/2) cam.x = map.GetWidth()*map.sizew - screen->w;
}

CEquip::CEquip()
{
    id = 0;
    name = "";
}

CInv::CInv()
{
      dam = 0;
      name = "";
      id = 0;
      type = 0;
      equipped = false;
}


/*
#define WEAR_HEAD       0
#define WEAR_ARM        1
#define WEAR_LEG        2
#define WEAR_RING       3
#define WEAR_WEAPON     4
*/
void CPlayer::GetInfo()
{

     std::string data;
     std::ifstream fin;
     fin.open("./data/equip.txt");
     
     fin >> data;
     list[0].name = data;     //inv.name[0];
     fin >> list[0].type;
     fin >> list[0].dam;
     fin >> list[0].ac;
     fin>>list[0].price;
     list[0].id = 1;
     
     int count = 1;
     while(!fin.eof())
     {
          fin>>list[count].name;
          fin>>list[count].type;
          fin>>list[count].dam;
          fin>>list[count].ac;
          fin>>list[count].price;
        //  list[count].id+=count+1;
          list[count].id = count+1;

          count++;
     }

     
   fin.close();
}

void CPlayer::UpdateEquip()
{
    for(int i = 0; i<MAX_EQUIP; ++i)
    {
            if(equip[i].id != 0)
            {
                 equip[i].name = list[equip[i].id-1].name;

            }
    }
}

void CPlayer::UpdateInventory()
{
    for(int i = 0; i<MAX_INV; ++i)
    {
            if(inv[i].id != 0)
            {
                inv[i].name = list[inv[i].id-1].name; /* The id is (-1) because it starts out as 1 instead of 0*/
                inv[i].type = list[inv[i].id-1].type;
                inv[i].ac = list[inv[i].id-1].ac;
                inv[i].dam = list[inv[i].id-1].dam;
            }
    }
}

/* TODO: Need to add modifying stats etc for each id** */
void CPlayer::WearObject(int id, int selected_item)
{
     if(list[id-1].type == WEAR_HEAD)
     {
          for(int i = 0; i<MAX_INV; ++i)
          {
              if(inv[i].equipped == true && inv[i].type == WEAR_HEAD)
                  RemoveObject(i);
          }
          equip[WEAR_HEAD].id = inv[selected_item].id;
          inv[selected_item].equipped = true;
     }
     
     else if(list[id-1].type == WEAR_ARM)
     {
          for(int i = 0; i<MAX_INV; ++i)
          {
              if(inv[i].equipped == true && inv[i].type == WEAR_ARM)
                  RemoveObject(i);
          }
          equip[WEAR_ARM].id = inv[selected_item].id;
          inv[selected_item].equipped = true;
     }
     
     else if(list[id-1].type == WEAR_LEG)
     {
          for(int i = 0; i<MAX_INV; ++i)
          {
              if(inv[i].equipped == true && inv[i].type == WEAR_LEG)
                  RemoveObject(i);
          }
          equip[WEAR_LEG].id = inv[selected_item].id;
          inv[selected_item].equipped = true;
     }
     
     else if(list[id-1].type == WEAR_RING)
     {
          for(int i = 0; i<MAX_INV; ++i)
          {
              if(inv[i].equipped == true && inv[i].type == WEAR_RING)
                  RemoveObject(i);
          }
          equip[WEAR_RING].id = inv[selected_item].id;
          inv[selected_item].equipped = true;
     }
      
     else if(list[id-1].type == WEAR_WEAPON)
     {
          for(int i = 0; i<MAX_INV; ++i)
          {
              if(inv[i].equipped == true && inv[i].type == WEAR_WEAPON)
                  RemoveObject(i);
          }
          equip[WEAR_WEAPON].id = inv[selected_item].id;
          inv[selected_item].equipped = true;
     }
     
   UpdateStats();
}

void CPlayer::RemoveObject(int item)
{
    equip[inv[item].type].id = 0;
    equip[inv[item].type].name = "";
    UpdateStats();
    inv[item].equipped = false;
    // TODO: Remove all effects the ITEM DOES!!!
}

void CPlayer::DropObject(int selected_item)
{
  if( inv[selected_item].equipped == true)
  {
       RemoveObject(selected_item);
/*     equip[inv[selected_item].type].id = 0;
     equip[inv[selected_item].type].name = "";
     inv[selected_item].equipped = false;
     */
  }
  

  CEvent event;
  event.x = x/16;
  event.y = y/16;
  event.name = "";
  event.text = "";

  SET_BIT(map.tile[1][y/16][x/16].flags, FLAG_EVENT);
  event.flags = EVENT_ITEM;
  event.id = inv[selected_item].id;

  map.event.push_back(event);
  map.max_event++;

  map.tile[1][y/16][x/16].gfx = TILE_ITEM;
  inv[selected_item].id = 0;
//allegro_message("%d", map.max_event);
  
  /*
  CEvent event;
  event.x = x/16;
  event.y = y/16;
  event.name = "";
  event.text = "";
  
  SET_BIT(map.tile[1][y/16][x/16].flags, FLAG_EVENT);
  event.flags = EVENT_ITEM;
  
//  for(int i = 0; i<MAX_ITEM_PER_TILE; ++i)
int counter = 0;
  while(counter < MAX_ITEM_PER_TILE)
  {
     if(map.event.id[counter] == 0)
     {
         event.id[counter] = inv[selected_item].id;
         counter = MAX_ITEM_PER_TILE; // exit while
         allegro_message("CHECK %d", counter);
     }
     else counter ++;
  }
  
  bool found = false;
  for(int i = 0; i<map.max_event; ++i)
  {
     if( map.event[i].x == event.x && map.event[i].y == event.y)
     {
         found = true;
     }
  }
  
  if(!found)
  {
     map.event.push_back(event);
     map.max_event++;
  }

  map.tile[1][y/16][x/16].gfx = TILE_ITEM;
  inv[selected_item].id = 0;
  allegro_message("%d %d", map.event[1].id[0], map.event[1].id[1]);
  */
     /*
  // First remove from equipment slots, if the obj is in one
  if( inv[selected_item].equipped == true)
  {
     equip[inv[selected_item].type].id = 0;
     inv[selected_item].equipped = false;
  }
  

  
  CEvent event;
  allegro_message("%d %d", x, y);
  event.x = x/16;
  event.y = y/16;
  event.name = "";
  event.text = "";
  SET_BIT(map.tile[1][y/16][x/16].flags, FLAG_EVENT);
  event.flags = EVENT_ITEM;
  for(int i = 0; i<MAX_ITEM_PER_TILE; ++i)
  {
          if(event.id[i] == 0)
          {
            event.id[i] = inv[selected_item].id;
            i = MAX_ITEM_PER_TILE+1; // exit for loop
          }
          //          todo:
          //     else if all tiles are filled do something

            
  }

  map.event.push_back(event);
  map.max_event++;
  map.tile[1][y/16][x/16].gfx = TILE_ITEM;
//allegro_message("%d %d", map.event[0].id[0], map.event[0].id[1]);
  inv[selected_item].id = 0;
  */
}

void CPlayer::PickupObject(int num)
{
     bool found = false;

     int stored_x = 0;
     int stored_y = 0;

//allegro_message("%d", map.event[num].id);
     if(map.event[num].id != 0)
     {
      for(int i = 0; i<MAX_INV; ++i)
      {
  //            allegro_message("%d", inv[i].id);
        if(inv[i].id == 0)
        {//              allegro_message("2nd %d", inv[i].id);
            inv[i].id = map.event[num].id;
            std::vector<CEvent>::iterator pos;
            pos = map.event.begin() + num;
            
            stored_x = map.event[num].x;
            stored_y = map.event[num].y;
   
            map.event.erase(pos);
            map.max_event--;
            found = true;

            i = MAX_INV+1; // exit for loop
        }
      }
     }
     
     if(!found) Talk("", "Not enough room!");



     for(int i = 0; i<map.max_event; ++i)
     {
     //   allegro_message(" num  %d ::: %d %d %d (Imax %d)", i,  map.event[i].x, map.event[i].y, map.event[i].flags, map.max_event);
     }
     
     

  // Only proceed if the PC picked up the obj
  if(found)
  {
     found = false;
     // Check if we should remove the graphic and event flag
     for(int v = 0; v<map.max_event; ++v)
     {
//             allegro_message("RGITH SLFDj %d %d", map.event[v].x, map.event[num].x);
        if( (map.event[v].flags == EVENT_ITEM &  map.event[v].x == stored_x
             && map.event[v].y == stored_y))
        {
//             allegro_message("FOUND AT SAME LOCAL x %d y%d %d", map.event[v].x, map.event[v].y, map.max_event);
         found = true;
        }

     }
     
     if(!found)
     {
       // allegro_message("num %d", num);
         REMOVE_BIT(map.tile[1][stored_y][stored_x].flags, FLAG_EVENT);
         map.tile[1][stored_y][stored_x].gfx = 0;
     }
  }

     /*
    if(map.event[num].id != 0)
    {
        for(int i = 0; i<MAX_INV; ++i)
        {
            if(inv[i].id == 0)
            {
             for(int j = 0; j<MAX_ITEM_PER_TILE; ++j)
             {
              if(map.event[num].id[j] != 0)
              {
               inv[i].id = map.event[num].id[j];
               
             
               std::vector<CEvent>::iterator pos;
 			   pos = map.event.begin() + i;
               map.event.erase(pos);
               map.max_event--;
               i = MAX_INV+1; // exit outer for loop
               j = MAX_ITEM_PER_TILE+1;

              }
              else if(map.event[num].id[j] == 0)
              {
                 REMOVE_BIT(map.tile[1][map.event[num].y][map.event[num].x].flags, FLAG_EVENT);
                 map.tile[1][map.event[num].y][map.event[num].x].gfx = 0;
              }
              }
             }
            }
        }
        
        */
}

bool CPlayer::AddObject(int id)
{
     bool added = false;
      for(int i = 0; i<MAX_INV; ++i)
      {
        if(inv[i].id == 0)
        {
//        allegro_message("%d", id);
            inv[i].id = id;
            i = MAX_INV+1;
            added = true;
        }
      }
     if(added == false)
     {
         Talk("", "You don't have any room in your inventory!");
     }
     
     return added;
}

CShop::CShop()
{
for(int max = 0; max<MAX_SHOP; ++max)
  for(int i = 0; i<MAX_ITEM_PER_SHOP; ++i)
    id[max][i] = 0;
}

void CShop::Init()
{
   shop_bmp = load_bitmap("./data/shop.bmp", NULL);
   shop_selector = load_bitmap("./data/shopselect.tga", NULL);
   selector = load_bitmap("./data/selector.bmp", NULL);
   item_type = load_bitmap("./data/items.bmp", NULL);
   choice_bmp = load_bitmap("./data/choice.bmp", NULL);
   


}

// reads the id's from a specific shop
// ***10 ITEMS PER SHOP
// TODO: Bug - Using player[0].gold shouldn't be there -- but it's required because both players SHARE the gold....
void CShop::Shop(int num, CPlayer &pc)
{

     std::string data;
     std::ifstream fin;
     fin.open("./data/shops.txt");

     int count = 0;
     while(!fin.eof())
     {
       for(int i = 0; i<MAX_ITEM_PER_SHOP; ++i)
       {
         fin >> id[count][i];
       }
         count++;
     }
     text_mode(-1);



     
     int key_up = 0;
     int key_down = 0;
     int key_space = 0;
     remove_keyboard();
     install_keyboard();
     
     bool done = false;
     int choice = 0;

     do{
      update_key(KEY_UP, &key_up);
      update_key(KEY_DOWN, &key_down);
      update_key(KEY_SPACE, &key_space);

      if(key_up == 1 && choice > 0) choice --;
      if(key_down == 1 && choice < MAX_ITEM_PER_SHOP) choice ++;
      map.DrawMap(0, pc.cam.x, pc.cam.y); // Walls
      blit(shop_bmp, Display.GetSurface(), 0,0, screen->w/2-shop_bmp->w/2, 0, shop_bmp->w, shop_bmp->h);
        masked_blit(choice_bmp, Display.GetSurface(), 0, 0, screen->w/2+shop_bmp->w/2-15, 125, choice_bmp->w, choice_bmp->h);
        pc.UpdateEquip();
        textprintf_ex(Display.GetSurface(), font, screen->w/2+shop_bmp->w/2+10, 135, makecol(0,0,0), -1, "Head: %s", pc.equip[WEAR_HEAD].name.c_str());
        textprintf_ex(Display.GetSurface(), font, screen->w/2+shop_bmp->w/2+10, 145, makecol(0,0,0), -1, "Arms: %s", pc.equip[WEAR_ARM].name.c_str());
        textprintf_ex(Display.GetSurface(), font, screen->w/2+shop_bmp->w/2+10, 155, makecol(0,0,0), -1, "Legs: %s", pc.equip[WEAR_LEG].name.c_str());
        textprintf_ex(Display.GetSurface(), font, screen->w/2+shop_bmp->w/2+10, 165, makecol(0,0,0), -1, "Ring: %s", pc.equip[WEAR_RING].name.c_str());
        textprintf_ex(Display.GetSurface(), font, screen->w/2+shop_bmp->w/2+10, 175, makecol(0,0,0), -1, "Weapon: %s", pc.equip[WEAR_WEAPON].name.c_str());
      textprintf(Display.GetSurface(), font, screen->w/2-75, 30, makecol(0,0,0), "Item Name Price(gp)");
      textprintf(Display.GetSurface(), font, screen->w/2-95,  50+(MAX_ITEM_PER_SHOP+1)*12, makecol(0,0,0), "Shopping for: %s", pc.name.c_str());
      textprintf(Display.GetSurface(), font, screen->w/2-95,  60+(MAX_ITEM_PER_SHOP+1)*12, makecol(0,0,0), "Your Gold: ");
      textprintf(Display.GetSurface(), font, screen->w/2-95+13*8, 60+(MAX_ITEM_PER_SHOP+1)*12, makecol(255,255,0), "%d", player[0].gold);


      for(int i = 0; i<MAX_ITEM_PER_SHOP; ++i)
      {
         // Display all the items that the shop has!
         masked_blit(item_type, Display.GetSurface(), 0,pc.list[id[num][i]-1].type*8, screen->w/2-75-8, 50+i*12, 8, 8);
         textprintf(Display.GetSurface(), font, screen->w/2-75+item_type->w+2, 50+i*12, makecol(255,0,0), "%s %d", pc.list[id[num][i]-1].name.c_str(), pc.list[id[num][i]-1].price);
      }

      if(key_space == 1 && choice == MAX_ITEM_PER_SHOP) done = true;
      else if(key_space == 1)
      {
         bool selection = false;
         int item_choice = choice;
         choice = 0;
         do{
            clear(Display.GetSurface());
            update_key(KEY_UP, &key_up);
            update_key(KEY_DOWN, &key_down);
            update_key(KEY_SPACE, &key_space);
            if(key_up == 1 && choice > 0) choice --;
            if(key_down == 1 && choice < 1) choice ++;
            // Buy
            if(choice == 0 && key_space == 1 && player[0].gold >= pc.list[id[num][item_choice]-1].price)
            {
                    //  allegro_message("%d %d %s %d %d %d", pc.list[id[num][item_choice]-1].id , pc.list[id[num][item_choice]-1].price, pc.list[id[num][item_choice]-1].name.c_str(), id[num][item_choice]-1, num, item_choice );
                     /* for(int count = 0; count < MAX_SHOP; count ++)
                      for(int counter = 0; counter <MAX_ITEM_PER_SHOP; counter++)
                      {
                     allegro_message("%d ", pc.list[id[count][counter]-1].id  );
                      }*/
                      if(pc.AddObject(pc.list[id[num][item_choice]-1].id))
                      {
                        SAMPLE *coin = load_wav("./data/music/coindropbynir.wav");
                        play_sample(coin, 255, 128, 1000, false);
                        player[0].gold -= pc.list[id[num][item_choice]-1].price;
                      }

                      selection = true;
            }
            else if(choice == 0 && key_space == 1 && player[0].gold < pc.list[id[num][item_choice]-1].price)
            {
               Talk("","Hey, you can't afford that!");
               selection = true;
            }
            
            
            // Exit
            if(choice == 1 && key_space == 1)
            {
                selection = true;
            }
               map.DrawMap(0, pc.cam.x, pc.cam.y); // Walls
               blit(shop_bmp, Display.GetSurface(), 0,0, screen->w/2-shop_bmp->w/2, 0, shop_bmp->w, shop_bmp->h);
                  masked_blit(choice_bmp, Display.GetSurface(), 0, 0, screen->w/2+shop_bmp->w/2-15, 125, choice_bmp->w, choice_bmp->h);
                  pc.UpdateEquip();
                  textprintf_ex(Display.GetSurface(), font, screen->w/2+shop_bmp->w/2+10, 135, makecol(0,0,0), -1, "Head: %s", pc.equip[WEAR_HEAD].name.c_str());
                  textprintf_ex(Display.GetSurface(), font, screen->w/2+shop_bmp->w/2+10, 145, makecol(0,0,0), -1, "Arms: %s", pc.equip[WEAR_ARM].name.c_str());
                  textprintf_ex(Display.GetSurface(), font, screen->w/2+shop_bmp->w/2+10, 155, makecol(0,0,0), -1, "Legs: %s", pc.equip[WEAR_LEG].name.c_str());
                  textprintf_ex(Display.GetSurface(), font, screen->w/2+shop_bmp->w/2+10, 165, makecol(0,0,0), -1, "Ring: %s", pc.equip[WEAR_RING].name.c_str());
                  textprintf_ex(Display.GetSurface(), font, screen->w/2+shop_bmp->w/2+10, 175, makecol(0,0,0), -1, "Weapon: %s", pc.equip[WEAR_WEAPON].name.c_str());
               textprintf(Display.GetSurface(), font, screen->w/2-75, 30, makecol(0,0,0), "Item Name Price(gp)");
               textprintf(Display.GetSurface(), font, screen->w/2-95,  50+(MAX_ITEM_PER_SHOP+1)*12, makecol(0,0,0), "Shopping for: %s", pc.name.c_str());
               textprintf(Display.GetSurface(), font, screen->w/2-95,  60+(MAX_ITEM_PER_SHOP+1)*12, makecol(0,0,0), "Your Gold: ");
               textprintf(Display.GetSurface(), font, screen->w/2-95+13*8, 60+(MAX_ITEM_PER_SHOP+1)*12, makecol(255,255,0), "%d", player[0].gold);
               for(int i = 0; i<MAX_ITEM_PER_SHOP; ++i)
               {
                   // Display the items sold!
                   masked_blit(item_type, Display.GetSurface(), 0,pc.list[id[num][i]-1].type*8, screen->w/2-75-8, 50+i*12, 8, 8);
                   textprintf(Display.GetSurface(), font, screen->w/2-75+item_type->w+2, 50+i*12, makecol(255,0,0), "%s %d", pc.list[id[num][i]-1].name.c_str(), pc.list[id[num][i]-1].price);
               }
            blit(shop_selector, Display.GetSurface(), 0,0, screen->w/2-shop_bmp->w, screen->h/2, shop_selector->w, shop_selector->h);//on purpose shop_bmp
            masked_stretch_blit( selector, Display.GetSurface(), 0, 0, selector->w, selector->h,  screen->w/2+10, screen->h/2+63+12*choice, 9,9);
            textprintf(Display.GetSurface(), font, screen->w/2-shop_bmp->w+10, screen->h/2+10, makecol(255,0,0), "Purchase %s for %dgp?", pc.list[id[num][item_choice]-1].name.c_str(),  pc.list[id[num][item_choice]-1].price);
            blit(Display.GetSurface(), screen, 0, 0, 0, 0, screen->w, screen->h);
            
          }while(selection == false);
          
          choice = item_choice; // put the choice back where it was
      }

      textprintf(Display.GetSurface(), font, screen->w/2-75, 50+MAX_ITEM_PER_SHOP*12, makecol(255,0,0), "Exit");


      masked_stretch_blit( selector, Display.GetSurface(), 0, 0, selector->w, selector->h,  screen->w/2-90, 50+choice*12, 9,9);
      
      blit(Display.GetSurface(), screen, 0, 0, 0, 0, screen->w, screen->h);
      clear(Display.GetSurface());
      }while(!done);
      text_mode(0);
      fin.close();

}


void CPlayer::InitStats()
{
    //name="";
	str = rand()%(18-10+1)+10;
	wis = rand()%(18-10+1)+10;
    intell = rand()%(18-10+1)+10;
	con = rand()%(18-10+1)+10;
	chr = rand()%(18-10+1)+10;
	hp = rand()%(10-8+1)+8;
	max_hp=hp;
	max_mana = 0;
	mana = max_mana;
	
    exp = 0;
    ac = 0;
// TODO: modify gold value and load portrait!
// 	gold =
//	BITMAP *portrait;
}


// TODO: (delete) Obsolete Do not use
void CPlayer::GiveObject(int selected_item)
{
     for(int i = 0; i<MAX_INV; ++i)
     {
        if(inv[i].id == 0)
        {
          inv[i].id = selected_item;
        }
     }
}

void CPlayer::UpdateStats()
{
     int damage_counter = 0;
     int ac_counter = 0;
     for(int i = 0; i<MAX_INV; i++)
     {
//allegro_message("%d %s %d", i, inv[i].name.c_str(), inv[i].ac);
        if( inv[i].equipped == true)
        { //if(i != 4) allegro_message("%d %s", i, inv[i].name.c_str());

          damage_counter+=inv[i].dam;
          ac_counter+=inv[i].ac;
        }
     }
     dam = damage_counter + base_dam;
     ac =  ac_counter + base_ac;

}


void SaveGame()
{
   FILE *fout = fopen("player.sav", "wb");
   char *temp = new char[1024];

  // Save the Players!
  for(int i = 0; i<2; ++i)
  {
      fwrite(&player[i].x, sizeof(dword), 1, fout);
      fwrite(&player[i].y, sizeof(dword), 1, fout);
      fwrite(&player[i].facing, sizeof(dword), 1, fout);
                // TODO: Load GFX?
      fwrite(&player[i].facing, sizeof(dword), 1, fout);
      
      for(int j = 0; j<MAX_EQUIP; ++j)
      {
         fwrite(&player[i].equip[j].id, sizeof(int), 1, fout);
         fwrite(&player[i].equip[j].price, sizeof(int), 1, fout);

         for(int v = 0; v<255; ++v) temp[v] = ' ';
            strcpy( temp, player[i].equip[j].name.c_str());
         fwrite(temp, 1, 255, fout);
      }
      
      for(int j = 0; j<MAX_INV; ++j)
      {
         fwrite(&player[i].inv[j].equipped, sizeof(bool), 1, fout);
         fwrite(&player[i].inv[j].ac, sizeof(int), 1, fout);
         fwrite(&player[i].inv[j].dam, sizeof(int), 1, fout);
         fwrite(&player[i].inv[j].id, sizeof(int), 1, fout);
         fwrite(&player[i].inv[j].price, sizeof(int), 1, fout);
         fwrite(&player[i].inv[j].type, sizeof(int), 1, fout);
         for(int v = 0; v<255; ++v) temp[v] = ' ';
            strcpy( temp, player[i].inv[j].name.c_str());
         fwrite(temp, 1, 255, fout);
      }

    // I don't think we need to save this
    //	CInv list[MAX_ITEMS];
    
    for(int v = 0; v<255; ++v) temp[v] = ' ';
      strcpy( temp, player[i].name.c_str());
    fwrite(temp, 1, 255, fout);
    
    fwrite(&player[i].str, sizeof(int), 1, fout);
    fwrite(&player[i].wis, sizeof(int), 1, fout);
    fwrite(&player[i].intell, sizeof(int), 1, fout);
    fwrite(&player[i].con, sizeof(int), 1, fout);
    fwrite(&player[i].chr, sizeof(int), 1, fout);
    fwrite(&player[i].hp, sizeof(int), 1, fout);
    fwrite(&player[i].max_hp, sizeof(int), 1, fout);
    fwrite(&player[i].max_mana, sizeof(int), 1, fout);
    fwrite(&player[i].mana, sizeof(int), 1, fout);

    fwrite(&player[i].exp, sizeof(int), 1, fout);
    fwrite(&player[i].level, sizeof(int), 1, fout);
    fwrite(&player[i].ac, sizeof(int), 1, fout);
    fwrite(&player[i].base_ac, sizeof(int), 1, fout);
    fwrite(&player[i].dam, sizeof(int), 1, fout);
    fwrite(&player[i].base_dam, sizeof(int), 1, fout);
    fwrite(&player[i].gold, sizeof(int), 1, fout);
    
    // need a portrait
    
    fwrite(&player[i].max_battles, sizeof(int), 1, fout);
    fwrite(&player[i].movement_range, sizeof(int), 1, fout);
    fwrite(&player[i].fighting_range, sizeof(int), 1, fout);
    
    for(int j = 0; j<player[i].max_battles; ++j)
    {
      for(int v = 0; v<255; ++v) temp[v] = ' ';
         strcpy( temp, player[i].fought_battles[j].c_str());
      fwrite(temp, 1, 255, fout);
    }

  }

//friend CCine; //cine;
int size = cine.seen.size();
fwrite(&size, sizeof(dword), 1, fout);
for(int j = 0; j<size; ++j)
{
    bool seen = cine.seen[j];
    fwrite(&seen, sizeof(bool), 1, fout);
}

for(int v = 0; v<1024; ++v) temp[v] = ' ';
         strcpy( temp,map.name.c_str());
fwrite(temp, 1, 1024, fout);

fwrite(&quest.quest_bit, sizeof(long long unsigned int), 1, fout);


size = player[0].event_check.size();
fwrite(&size, sizeof(dword), 1, fout);
for(int j = 0; j<player[0].event_check.size(); ++j)
{
    for(int v = 0; v<1024; ++v) temp[v] = ' ';
             strcpy( temp,player[0].event_check[j].name.c_str());
    fwrite(temp, 1, 1024, fout);
    fwrite(&player[0].event_check[j].x, sizeof(dword), 1, fout);
    fwrite(&player[0].event_check[j].y, sizeof(dword), 1, fout);
}
   delete[] temp;
   fclose(fout);
}


void LoadGame()
{
   FILE *fin = fopen("player.sav", "rb");
   char *temp = new char[1024];

  // Save the Players!
  for(int i = 0; i<2; ++i)
  {
      fread(&player[i].x, sizeof(dword), 1, fin);
      fread(&player[i].y, sizeof(dword), 1, fin);
      fread(&player[i].facing, sizeof(dword), 1, fin);
                // TODO: Load GFX?
      fread(&player[i].facing, sizeof(dword), 1, fin);

      for(int j = 0; j<MAX_EQUIP; ++j)
      {
         fread(&player[i].equip[j].id, sizeof(int), 1, fin);
         fread(&player[i].equip[j].price, sizeof(int), 1, fin);
         
         for(int v = 0; v<255; ++v) temp[v] = ' ';
         
         fread(temp, 1, 255, fin);
         player[i].equip[j].name = temp;
      }

      for(int j = 0; j<MAX_INV; ++j)
      {
         fread(&player[i].inv[j].equipped, sizeof(bool), 1, fin);
         fread(&player[i].inv[j].ac, sizeof(int), 1, fin);
         fread(&player[i].inv[j].dam, sizeof(int), 1, fin);
         fread(&player[i].inv[j].id, sizeof(int), 1, fin);
         fread(&player[i].inv[j].price, sizeof(int), 1, fin);
         fread(&player[i].inv[j].type, sizeof(int), 1, fin);
         
         for(int v = 0; v<255; ++v) temp[v] = ' ';
         fread(temp, 1, 255, fin);
         player[i].inv[j].name = temp;
      }

    // I don't think we need to save this
    //	CInv list[MAX_ITEMS];

    for(int v = 0; v<255; ++v) temp[v] = ' ';
    fread(temp, 1, 255, fin);
    player[i].name = temp;

    fread(&player[i].str, sizeof(int), 1, fin);
    fread(&player[i].wis, sizeof(int), 1, fin);
    fread(&player[i].intell, sizeof(int), 1, fin);
    fread(&player[i].con, sizeof(int), 1, fin);
    fread(&player[i].chr, sizeof(int), 1, fin);
    fread(&player[i].hp, sizeof(int), 1, fin);
    fread(&player[i].max_hp, sizeof(int), 1, fin);
    fread(&player[i].max_mana, sizeof(int), 1, fin);
    fread(&player[i].mana, sizeof(int), 1, fin);

    fread(&player[i].exp, sizeof(int), 1, fin);
    fread(&player[i].level, sizeof(int), 1, fin);
    fread(&player[i].ac, sizeof(int), 1, fin);
    fread(&player[i].base_ac, sizeof(int), 1, fin);
    fread(&player[i].dam, sizeof(int), 1, fin);
    fread(&player[i].base_dam, sizeof(int), 1, fin);
    fread(&player[i].gold, sizeof(int), 1, fin);

    // need a portrait

    fread(&player[i].max_battles, sizeof(int), 1, fin);
    fread(&player[i].movement_range, sizeof(int), 1, fin);
    fread(&player[i].fighting_range, sizeof(int), 1, fin);

    player[i].fought_battles.resize(player[i].max_battles);
    for(int j = 0; j<player[i].max_battles; ++j)
    {
      for(int v = 0; v<255; ++v) temp[v] = ' ';
      fread(temp, 1, 255, fin);
      player[i].fought_battles[j] = temp;
    }


  player[0].GetInfo();
  player[1].GetInfo();
  }
  
int size;
fread(&size, sizeof(dword), 1, fin);
//size = cine.seen.size();
cine.seen.resize(size);
for(int j = 0; j<size; ++j)
{
    bool seen = false;
    fread(&seen, sizeof(bool), 1, fin);
    cine.seen[j] = seen;
}

for(int v = 0; v<1024; ++v) temp[v] = ' ';
fread(temp,  1, 1024, fin);
std::string temp_string = temp;

fread(&quest.quest_bit, sizeof(long long unsigned int), 1, fin);

fread(&size, sizeof(dword), 1, fin);
player[0].event_check.resize(size);
for(int j = 0; j<size; ++j)
{
    for(int v = 0; v<1024; ++v) temp[v] = ' ';
    fread(temp,  1, 1024, fin);
    player[0].event_check[j].name = temp;
    
    fread(&player[0].event_check[j].x, sizeof(dword), 1, fin);
    fread(&player[0].event_check[j].y, sizeof(dword), 1, fin);
}



fclose(fin);
//allegro_message("%s", temp_string.c_str());
map.LoadMap("./data/"+temp_string);
player[0].UpdateMovement();
map.LoadNpcs();
player[0].GetInfo();
player[0].shop.Init();
player[1].GetInfo();
player[1].shop.Init();
   delete[] temp;

}











