#include "angband.h"

#ifdef AUTO_PLAY

#include "borg.h"


/*
 * Determine if an item can be sold in the current store
 */
EXTERN bool borg_good_sell(auto_item *item)
{
    int tval = item->tval;

#ifdef FRITSDEBUG
   borg_note("In routine borg_good_sell()");
#endif /* FRITSDEBUG */

    /* Switch on the store */
    switch (state_store) {

      /* General Store */
      case 1:

	/* Analyze the type */
	switch (tval) {
	  case TV_DIGGING:
	  case TV_CLOAK:
	  case TV_FOOD:
	  case TV_FLASK:
	  case TV_LITE:
	  case TV_SPIKE:
	    return (TRUE);
	  default:
	    return (FALSE);
	}

      /* Armoury */
      case 2:

	/* Analyze the type */
	switch (tval) {
	  case TV_BOOTS:
	  case TV_GLOVES:
	  case TV_HELM:
	  case TV_SHIELD:
	  case TV_SOFT_ARMOR:
	  case TV_HARD_ARMOR:
	  case TV_DRAG_ARMOR:
	    return (TRUE);
	  default:
	    return (FALSE);
	}

      /* Weapon Shop */
      case 3:

	/* Analyze the type */
	switch (tval) {
	  case TV_SHOT:
	  case TV_BOLT:
	  case TV_ARROW:
	  case TV_BOW:
#ifndef FRITS
	/* can sell these better at the Temple */
	  case TV_HAFTED:
#endif /* FRITS */
	  case TV_POLEARM:
	  case TV_SWORD:
	    return (TRUE);
	  default:
	    return (FALSE);
	}

      /* Temple */
      case 4:

	/* Analyze the type */
	switch (tval) {
	  case TV_HAFTED:
	  case TV_SCROLL:
	  case TV_POTION:
	  case TV_PRAYER_BOOK:
	    return (TRUE);
	  default:
	    return (FALSE);
	}

      /* Alchemist */
      case 5:

	/* Analyze the type */
	switch (tval) {
	  case TV_SCROLL:
	  case TV_POTION:
	    return (TRUE);
	  default:
	    return (FALSE);
	}

      /* Magic Shop */
      case 6:

	/* Analyze the type */
	switch (tval) {
	  case TV_MAGIC_BOOK:
	  case TV_AMULET:
	  case TV_RING:
	  case TV_STAFF:
	  case TV_WAND:
	  case TV_ROD:
	    return (TRUE);
	  default:
	    return (FALSE);
	}
    }

    /* XXX */
    return (FALSE);
}




/*
 * Determine the approximate "price" of a weapon/armour
 * Take into account item type, and known bonuses, if any
 * This routine is adapted from "item_value()" in "store.c"
 *
 * Armor is worth an extra 100 gold per bonus point to armor class.
 * Weapons are worth an extra 100 gold per bonus point (AC,TH,TD).
 * Missiles are only worth 5 gold per bonus point, as in "store.c"
 *
 * Allow "negative" weapon bonuses to be "offset" by positive ones.
 * This only happens for weapons with a non-negative "net effect".
 *
 * This function returns the "value" of ONE of the item's objects.
 */
EXTERN s32b item_worth(auto_item *item)
{
    s32b value;
#ifdef FRITS
    cptr spdesc;
    int speed;
#endif /* FRITS */

#ifdef FRITSDEBUG
   borg_note("In routine borg_item_worth()");
#endif /* FRITSDEBUG */

    /* Extract the base value */
    value = k_list[item->kind].cost;
    
    /* Hack -- assume 200 for non-aware */
#ifndef FRITS
    if (!item->kind) value = 200;
#else
    /* that way, it will NEVER find gain stat potions! */
    if (!item->kind) value = 20*auto_depth*auto_depth;
#endif /* FRITS */
    
    /* Known worthless items are worthless */
    if (value <= 0L) return (0L);
        
    /* Armour -- pay extra for armor bonuses */
    if ((item->tval == TV_BOOTS) ||
	(item->tval == TV_GLOVES) ||
	(item->tval == TV_CLOAK) ||
	(item->tval == TV_HELM) ||
	(item->tval == TV_SHIELD) ||
	(item->tval == TV_SOFT_ARMOR) ||
	(item->tval == TV_HARD_ARMOR) ||
	(item->tval == TV_DRAG_ARMOR)) {

	/* Hack -- negative armor bonus */
	if (item->to_a < 0) return (0L);

#ifdef FRITS
	if (item->name1 != 0) value +=20000; /* artifact, just an average */
	if ( (item->name2 > 0) && (item->name2 < 96) ) /* > 96 = bad */
            value +=1000; /* ego-item */

        /* speed bonus  ( */
        spdesc=strstr(item->desc," to speed)");
        if (spdesc!=NULL) {
           spdesc=strrchr(item->desc,'(');
           if (sscanf(spdesc,"(%d to speed)",&speed) != 0 ) {
              borg_note(format("itemdesc[%s] speedbonus %d",item->desc,speed));
              value += 2000L * speed;
              if (value < 0) return(0L);
           } 
        }
        
#endif /* FRITS */

	/* Give credit for bonuses */
	return (value + (item->to_a * 100));
    }

    /* Weapons -- pay extra for all three bonuses */
    if ((item->tval == TV_DIGGING) || (item->tval == TV_HAFTED) ||
	(item->tval == TV_SWORD) || (item->tval == TV_POLEARM)) {

	/* Allow negatives to be overcome */
	if (item->to_h + item->to_d + item->to_a < 0) return (0L);

#ifdef FRITS
	if (item->name1 != 0) value +=20000; /* artifact, just an average */
        if ((item->name2 > 0) && (item->name2 < 96)) {
        switch(item->name2) {
           case 0:
             /* no ego item */
           break;
           case EGO_FIRE:
             value+=2000L;
           break;
           case EGO_HA:
             value+=10000L;
           break;
           case EGO_DF:
             value+=7500L;
           break;
           case EGO_FT:
             value+=3000L;
           break;
           case EGO_FB:
             value+=2200L;
           break;
           case EGO_SLAY_A:
             value+=2000L;
           break;
           case EGO_SLAY_D:
             value+=4000L;
           break;
           case EGO_SLAY_E:
             value+=4000L;
           break;
           case EGO_SLAY_U:
             value+=3500L;
           break;
           case EGO_WEST:
             value+=10000L;
           break;
           case EGO_BLESS_BLADE:
             value+=4000L;
           break;
           case EGO_EXTRA_MIGHT:
           case EGO_EXTRA_SHOTS:
             value+=10000L;
           break;
           case EGO_MIGHT:
           case EGO_ACCURACY:
             value+=1000L;
           break;
           case EGO_WONDER:
             value+=2000L;
           default:
             value+=1000L;
           break;
        }
        }

        /* speed bonus   */
        spdesc=strstr(item->desc," to speed)");
        if (spdesc!=NULL) {
           spdesc=strrchr(item->desc,'(');
           if (sscanf(spdesc,"(%d to speed)",&speed) != 0 ) {
              borg_note(format("itemdesc[%s] speedbonus %d",item->desc,speed));
              value += 2000L * speed;
              if (value < 0) return(0L);
	      /* ) please vi editor */
           } 
        }
#endif /* FRITS */

	/* Give credit for the plusses, take away for minuses */
	return (value + (item->to_h + item->to_d + item->to_a) * 100L);
    }

    /* Bows -- pay extra for all three bonuses */
    if (item->tval == TV_BOW) {

	/* Allow negatives to be overcome */
	if (item->to_h + item->to_d + item->to_a < 0) return (0L);

	/* Give credit for the plusses, take away for minuses */
	return (value + (item->to_h + item->to_d + item->to_a) * 100L);
    }

    /* Ammo -- pay extra for all three bonuses.  Hack -- 1/20 normal weapons */
    if ((item->tval == TV_SHOT) ||
	(item->tval == TV_ARROW) ||
	(item->tval == TV_BOLT)) {

	/* Allow negatives to be overcome */
	if (item->to_h + item->to_d + item->to_a < 0) return (0L);

	/* Give credit for the plusses, take away for minuses */
	return (value + (item->to_h + item->to_d + item->to_a) * 5);
    }

    /* Return the base value */
    return (value);
}


/*
 * Determine if an item should be bought from a store
 */
EXTERN bool borg_good_buy(auto_item *ware)
{
    int slot;

    auto_item *worn = NULL;

#ifdef FRITSDEBUG
   borg_note("In routine borg_good_buy()");
#endif /* FRITSDEBUG */

    /* Determine where the item would be worn */
    slot = wield_slot(ware->tval);

    /* Extract the item currently in that slot */
    if (slot >= 0) worn = &auto_items[slot];


    /* Food */
    if (ware->tval == TV_FOOD) {

#ifdef FRITS
        /* don't buy if can cast create food spell */
           /* _sometimes_ buy food; prevent deadlock on town */
        if ( ((sclass==SCLASS_PRIEST)&&(borg_can_cast(sclass,'b','f'))) ||
             ((sclass==SCLASS_MAGE)&&(borg_can_cast(sclass,'c','a'))) )
        {
           if(borg_count_items(TV_FOOD,-1) >= 5) return(FALSE); 
	/* doesn't need to buy much food; prevent deadlock on town */
        }
#endif /* FRITS */

	/* Only buy "normal" food */
	if (ware->sval < SV_FOOD_MIN_FOOD) return (FALSE);
	
	/* Always have at least 50 food */
	if (borg_count_items(TV_FOOD, -1) >= 20) return (FALSE);

	/* Hack -- always buy food */
	return (TRUE);
    }
    
    /* Flasks */
    else if (ware->tval == TV_FLASK) {

	/* Never buy more than 50 flasks */
	if (borg_count_items(TV_FLASK, -1) >= 30) return (FALSE);
	
	/* Hack -- examine the lite */
	worn = &auto_items[INVEN_LITE];

	/* Hack -- buy flasks for lanterns */
	if (worn->sval == SV_LITE_LANTERN) return (TRUE);
	
	/* Never buy random flasks */
	return (FALSE);
    }


#ifdef FRITS
    /* spellbooks */
    else if ((sclass==SCLASS_PRIEST)&&(ware->tval == TV_PRAYER_BOOK))
            {
            if (borg_count_items(TV_PRAYER_BOOK,ware->sval) < 6) 
	    { /* don't buy discount: we want stacking! */
               if (!strchr(ware->desc,'{')) return(TRUE); 
               /* } keep vi happy */
            }
	    else return (FALSE);
            }

    else if ((sclass==SCLASS_MAGE)&&(ware->tval == TV_MAGIC_BOOK))
            {
            if (borg_count_items(TV_MAGIC_BOOK,ware->sval) < 6) 
	    { /* don't buy discount: we want stacking! */
               if (!strchr(ware->desc,'{')) return(TRUE); 
               /* } keep vi happy */
            }
	    else return (FALSE);
            }

#endif /* FRITS */

    /* Scrolls */
    else if (ware->tval == TV_SCROLL) {

	/* Buy scrolls of identify */
	if (ware->kind == OBJ_SCROLL_IDENTIFY) {
	
	    /* Buy up to 30 scrolls */
	    if (borg_count_items(ware->tval, ware->sval) < 30) return (TRUE);
	}

	/* Buy scrolls of word of recall */
	if (ware->kind == OBJ_SCROLL_RECALL) {
	
	    /* Buy up to 5 scrolls */
	    if (borg_count_items(ware->tval, ware->sval) < 5) return (TRUE);
	}

#ifdef FRITS
	/* scrolls of *enchantment* */
        if ((ware->kind == OBJ_SCROLL_ENCHANT__WE) ||
            (ware->kind == OBJ_SCROLL_ENCHANT__WE) )
           return(TRUE);
#endif /* FRITS */

	/* Do not buy it */
	return (FALSE);
    }

    /* Potions */
    else if (ware->tval == TV_POTION) {

	/* Buy potions of cure critical */
	if (ware->kind == OBJ_POTION_CRITICAL) {
	
	    /* Buy up to 20 potions */
	    if (borg_count_items(ware->tval, ware->sval) < 20) return (TRUE);
	}

#ifdef FRITS
        switch(ware->kind) {
           case OBJ_POTION_STR:
           case OBJ_POTION_INT:
           case OBJ_POTION_WIS:
           case OBJ_POTION_DEX:
           case OBJ_POTION_CON:
           case OBJ_POTION_CHR:
           case OBJ_POTION_EXP:
           case OBJ_POTION_AUGMENT:
           case OBJ_POTION__ENLIGHT:
              return(TRUE);
           break;

           case OBJ_POTION_REST_STR:
              if ((drained_stat & (1<<0))!=0) return(TRUE);
           break;
           case OBJ_POTION_REST_INT:
              if ((drained_stat & (1<<1))!=0) return(TRUE);
           break;
           case OBJ_POTION_REST_WIS:
              if ((drained_stat & (1<<2))!=0) return(TRUE);
           break;
           case OBJ_POTION_REST_DEX:
              if ((drained_stat & (1<<3))!=0) return(TRUE);
           break;
           case OBJ_POTION_REST_CON:
              if ((drained_stat & (1<<4))!=0) return(TRUE);
           break;
           case OBJ_POTION_REST_CHR:
              if ((drained_stat & (1<<5))!=0) return(TRUE);
           break;
           case OBJ_POTION_REST_LIFE:
              if ((drained_stat & (1<<6))!=0) return(TRUE);
           break;

           default:
           break;
        }
#endif /* FRITS */

	/* Do not buy it */
	return (FALSE);
    }

    else if (ware->tval == TV_RING) {
#ifdef FRITS
        borg_note(format("Buying ring %s",ware->desc));
        if (worn->kind == OBJ_RING_SEE_INVIS) /* don't need nothing else.. */
           return(FALSE);
        if (ware->kind == OBJ_RING_SEE_INVIS)
        {
           borg_note("BUYING SEE INVIS!");
           return(TRUE);
        }
        /* don't buy */
#endif /* FRITS */
        return(FALSE);
    }

    else if (ware->tval == TV_AMULET) {
#ifdef FRITS
    /* amulet of the Magi; charisma? TE DOEN */
#endif /* FRITS */
        return(FALSE);
    }
    
	    
    /* Process Torches */
    else if ((ware->tval == TV_LITE) && (ware->sval == SV_LITE_TORCH)) {

	/* Hack -- Artifact lites are the best */
	if (worn->name1) return (FALSE);
	
	/* Hack -- Torches are defeated by (fueled) lanterns */
	if (worn->sval == SV_LITE_LANTERN) {
	    if (borg_count_items(TV_FLASK, -1) >= 10) return (FALSE);
	}
	
	/* Never buy more than 20 torches */
	if (borg_count_items(TV_LITE, SV_LITE_TORCH) >= 20) return (FALSE);

	/* Hack -- always buy torches */
	return (TRUE);
    }

    /* Process Lanterns */
    else if ((ware->tval == TV_LITE) && (ware->sval == SV_LITE_LANTERN)) {

	/* Hack -- Artifact lites are the best */
	if (worn->name1) return (FALSE);
	
	/* Never buy a lantern when wielding one already */
	if (worn->sval == SV_LITE_LANTERN) return (FALSE);

	/* Never buy more than 1 lantern */
	if (borg_count_items(TV_LITE, SV_LITE_LANTERN) >= 1) return (FALSE);

	/* Hack -- always buy a lantern */
	return (TRUE);
    }


    /* Process equipment */
    else if (slot >= 0) {

	/* Prefer some equipment to none */
	if (!worn->iqty) return (TRUE);
	
	/* XXX XXX XXX Hack -- Prefer "expensive" equipment */
        if (item_worth(ware) > item_worth(worn)) {

	    /* Hack -- Buy it */
	    return (TRUE);	
	}
    }


    /* Assume useless */
    return (FALSE);
}


/*
 * Analyze a "store" screen
 */
EXTERN bool borg_prepare_store(void)
{
    int i;

    byte t_a;

    char what[32];

    char desc[80];
    char cost[10];
    
    char buf[256];

    /* Multiple pages? */
    int more = 0;

    /* Current page */
    int page = 0;

    /* Hack -- make sure both pages are seen */
    static int browse = TRUE;
    
    /* What store did I *think* I was in */
    static int old_store = 0;

    /* How many pages did I *think* there were */
    static int old_more = 0;

#ifdef FRITSDEBUG
   borg_note("In routine borg_prepare_store()");
#endif /* FRITSDEBUG */

    /* Extract the "store" name (or "Home") */
    if (Term_what_text(50, 3, -20, &t_a, what)) what[0] = '\0';
    if (!what[0] || (what[0] == ' ')) strcpy(what, "Home");

    /* React to new stores */
    if (old_store != state_store) {

	/* Clear all the items */
	for (i = 0; i < 24; i++) {

	    /* XXX Wipe the ware */
	    WIPE(&auto_wares[i], auto_item);
	}
	
	/* Save the store */
	old_store = state_store;
    }
        
    
    /* Extract the "page", if any */
    if ((0 == Term_what_text(20, 5, 8, &t_a, buf)) &&
	(prefix(buf, "(Page "))) /* --)-- */ {

	/* Take note of the page */
	more = 1; page = (buf[6] - '0') - 1;
    }

    /* React to disappearing pages */
    if (old_more != more) {

	/* Clear the second page */
	for (i = 12; i < 24; i++) {

	    /* XXX Wipe the ware */
	    WIPE(&auto_wares[i], auto_item);
	}
	
	/* Save the new one */
	old_more = more;
    }
    

    /* Extract the current gold (unless in home) */
    if (0 == Term_what_text(68, 19, -9, &t_a, buf)) {

	/* Ignore this "field" in the home */
	if (state_store != 8) auto_gold = atol(buf);
    }


    /* Note */
    borg_note(format("In store %s (%d), page %d/%d, with %ld gold",
		     what, state_store, page+1, more+1, (long)auto_gold));


    /* Parse the store (or home) inventory */
    for (i = 0; i < 12; i++) {

	char /* p1 = '(', */ p2 = ')';

	/* Default to "empty" */
	desc[0] = '\0';
	cost[0] = '\0';
	
	/* Verify "intro" to the item */
	if ((0 == Term_what_text(0, i + 6, 3, &t_a, buf)) &&
	    (buf[0] == 'a' + i) && (buf[1] == p2) && (buf[2] == ' ')) {

	    /* Extract the item description */
	    if (Term_what_text(3, i + 6, -65, &t_a, desc)) desc[0] = '\0';

	    /* XXX Make sure trailing spaces get stripped (?) */
	    	
	    /* Extract the item cost */
	    if (Term_what_text(68, i + 6, -9, &t_a, cost)) cost[0] = '\0';

	    /* Hack -- forget the cost in the home */
	    if (state_store == 8) cost[0] = '\0';
	}

	/* Ignore "unchanged" descriptions */
	if (streq(desc, auto_wares[page*12+i].desc)) continue;

	/* Analyze it (including the cost) */
	borg_item_analyze(&auto_wares[page*12+i], desc, cost);
    }


    /* Hack -- browse as needed */
    if (more && browse) {
	borg_keypress(' ');
	browse = FALSE;
	return (TRUE);
    }

    /* Hack -- must browse later */
    browse = TRUE;
    

    /* Examine the inventory */
    borg_notice();
    
    /* Wear things */
    if (borg_wear_stuff()) {

	/* Send the "inventory" command */
	if (!cheat_inven) borg_keypress('i');

	/* Prepare to parse */
	state = STATE_INVEN;

	/* Success */
	return (TRUE);
    }

    
    /* Sell stuff */
    for (i = 0; i < INVEN_PACK; i++) {

	auto_item *item = &auto_items[i];

	/* XXX Hack -- notice "full" store */
	if (auto_wares[23].iqty) break;
	
	/* Item must be marked as sellable */
	if (!item->iqty) continue;
	if (!item->cash) continue;

	/* Do not try to make "bad" sales */
	if (!borg_good_sell(item)) continue;

	/* Note */
	borg_note(format("Selling %s to the %s", item->desc, what));

	/* Hack -- sell it */
	borg_keypress('s');
	
	/* Sell that item */
	borg_keypress('a' + i);

	/* Hack -- Sell a single item */
	if (item->iqty > 1) borg_keypress('\n');

	/* Accept the price, skip the messages */
	borg_keypress('\n');
	borg_keypress('\n');
	borg_keypress('\n');
	borg_keypress('\n');
	borg_keypress('\n');
	borg_keypress('\n');
	borg_keypress('\n');

	/* Send the "inventory" command */
	if (!cheat_inven) borg_keypress('i');

	/* Prepare to parse */
	state = STATE_INVEN;

	/* Success */
	return (TRUE);
    }

    /* Buy stuff */
    for (i = 0; i < 24; i++) {

	auto_item *ware = &auto_wares[i];

	/* Notice end of shop inventory */
	if (!ware->iqty) break;
	
	/* XXX Hack -- notice "full" inventory */
	if (auto_items[INVEN_PACK-1].iqty) break;

	/* We must have "enough" cash */
	if (auto_gold < ware->cost) continue;

	/* Only buy useful stuff */
	if (!borg_good_buy(ware)) continue;

	/* Note */
	borg_note(format("Buying %s from the %s", ware->desc, what));

        /* Hack -- wrong page */
        if ((i / 12) != page) borg_keypress(' ');
        
	/* Buy an item */
	borg_keypress('p');

	/* Buy the desired item */
	borg_keypress('a' + (i % 12));

	/* Buy a single item */
	if (ware->iqty > 1) borg_keypress('\n');

	/* Skip the messages */
	borg_keypress('\n');
	borg_keypress('\n');
	borg_keypress('\n');
	borg_keypress('\n');
	borg_keypress('\n');
	borg_keypress('\n');
	borg_keypress('\n');

	/* Send the "inventory" command */
	if (!cheat_inven) borg_keypress('i');
	
	/* Prepare to parse */
	state = STATE_INVEN;

	/* Success */
	return (TRUE);
    }
    
    

    /* Leave the store */
    borg_keypress(ESCAPE);

    /* Forget that we are in a store */
    state_store = 0;
    
    /* Prepare to start over */
#ifdef FRITS
    state = STATE_BOOKCHECK;
#else
    state = STATE_START;
#endif /* FRITS */

    /* Done */
    return (TRUE);
}

#endif /* AUTO_PLAY */
