tfe-1.0/area/
tfe-1.0/files/
tfe-1.0/logs/
tfe-1.0/logs/immortal/
tfe-1.0/logs/mob/
tfe-1.0/logs/object/
tfe-1.0/logs/player/
tfe-1.0/logs/room/
tfe-1.0/notes/clans/
tfe-1.0/player/
tfe-1.0/prev/
tfe-1.0/prev/area/
tfe-1.0/prev/player/
tfe-1.0/prev/rooms/
tfe-1.0/rooms/
tfe-1.0/src-gc/
tfe-1.0/src-msvc/
tfe-1.0/src-unix/
tfe-1.0/www/
tfe-1.0/www/html/
#include <ctype.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include "define.h"
#include "struct.h"


/*
 *   DRINK ROUTINES
 */


void do_drink( char_data* ch, char* argument )
{
  obj_data* obj;

  if( !strncasecmp( argument, "from ", 5 ) )
    argument += 5;

  if( *argument == '\0' ) {
    if( ( obj = find_type( *ch->array,
      ITEM_FOUNTAIN ) ) == NULL ) {
      send( ch, "Drink what?\n\r" );
      return;
      }
    obj->selected = 1;
    }
  else {
    if( ( obj = one_object( ch, argument,
      "drink", &ch->contents, ch->array ) ) == NULL )
      return;
    }

  include_empty  = FALSE;
  include_liquid = FALSE;

  drink( ch, obj );

  include_empty  = TRUE;
  include_liquid = TRUE;
}


bool drink( char_data* ch, obj_data* obj )
{
  content_array*   where;
  int             amount;
  int             liquid;
  int            alcohol;
  int              spell;

  if( obj->pIndexData->item_type != ITEM_FOUNTAIN
    && obj->pIndexData->item_type != ITEM_DRINK_CON ) {
    send( ch, "You can't drink from %s.\n\r", obj );
    return FALSE;
    }

  if( obj->value[1] == 0 ) {
    send( ch, "%s is already empty.\n\r", obj );
    return FALSE;
    }

  if( ch->species == NULL && ch->pcdata->condition[ COND_THIRST ] > 40 ) {
    send( ch, "You do not feel thirsty.\n\r" );
    return FALSE;
    }
 
  if( ( liquid = obj->value[2] ) >= table_max[ TABLE_LIQUID ]
    || liquid < 0 ) {
    bug( "Do_drink: bad liquid number. (Obj# %d, Liq# %d)",
      obj->pIndexData->vnum, liquid );
    liquid = obj->value[2] = 0;
    }

  amount  = min( number_range( 20, 40 ),
    ( obj->value[1] == -1 ? 70 : obj->value[1] ) );
  alcohol = amount*liquid_table[liquid].alcohol/10;

  send( ch, "You drink %s%s from %s.\n\r",
    obj->value[1] == amount ? "the last drops of " : "",
    liquid_name( obj ), obj );

  send_seen( ch, "%s drinks %s from %s.\n\r",
    ch, liquid_name( obj ), obj );

  if( ch->pcdata != NULL ) {
    ch->pcdata->condition[ COND_ALCOHOL ] += (alcohol+1)/2;
    gain_drunk( ch, alcohol/2 );
    }

  gain_condition( ch, COND_FULL,   amount*liquid_table[liquid].hunger/10 );
  gain_condition( ch, COND_THIRST, amount*liquid_table[liquid].thirst/10 );

  if( obj->value[1] != -1 ) {
    where = obj->array;
    obj   = (obj_data*) obj->From( 1 );
    if( ( obj->value[1] -= amount ) == 0 )
      remove_bit( obj->extra_flags, OFLAG_KNOWN_LIQUID );
    obj->To( where );
    }

  if( ( spell = liquid_table[liquid].spell ) == -1 ) 
    return FALSE;

  if( spell < SPELL_FIRST || spell >= WEAPON_FIRST ) {
    bug( "Do_drink: Liquid with non-spell skill." );
    return FALSE;
    }

  ( *spell_table[spell-SPELL_FIRST].function )( NULL, ch, NULL, 10, -1 ); 

  return TRUE;
}


/*
 *   FILL 
 */


thing_data* cant_fill( thing_data* thing, char_data*, thing_data* )
{
  obj_data* obj  = object( thing );

  return( obj == NULL || obj->pIndexData->item_type != ITEM_DRINK_CON
    ? NULL : obj );
}


thing_data* already_full( thing_data* thing, char_data*, thing_data* )
{
  obj_data* obj  = (obj_data*) thing;

  return( obj->value[1] >= obj->value[0] ? NULL : obj );
}


thing_data* fill( thing_data* t1, char_data*, thing_data* t2 )
{
  obj_data*          obj  = (obj_data*) t1;
  obj_data*     fountain  = (obj_data*) t2;
  content_array*   where  = obj->array;

  obj = (obj_data*) obj->From( obj->selected );

  if( obj->value[1] == 0 || obj->value[2] == fountain->value[2] ) 
    obj->value[2] = fountain->value[2];
  else
    obj->value[2] = 9;

  if( fountain->pIndexData->item_type == ITEM_FOUNTAIN
    || fountain->value[1] == -1 ) {
    obj->value[1] = obj->value[0];
    }
  else if( fountain->value[1]
    < obj->selected*( obj->value[0]-obj->value[1] ) ) {
    obj->value[1]     += fountain->value[1]/obj->selected;
    fountain->value[1] = 0;
    } 
  else {
    fountain->value[1] -= obj->selected*(obj->value[0]-obj->value[1]);
    obj->value[1]       = obj->value[0];
    }
  
  obj->To( where );

  return obj;
}


void do_fill( char_data* ch, char* argument )
{
  char               arg  [ MAX_INPUT_LENGTH ];
  thing_array*     array;
  obj_data*     fountain;
  content_array*   where;

  if( count( argument ) == 1 ) {
    if( ( fountain = find_type( *ch->array, ITEM_FOUNTAIN ) ) == NULL ) {
      send( ch, "You see nothing obvious to fill from.\n\r" );
      return;
      }
    }
  else {  
    if( !two_argument( argument, "from", arg ) ) {
      send( ch, "Syntax: Fill <object> [from] <container>.\n\r" );
      return;
      }
    if( ( fountain = one_object( ch, argument,
      "fill", &ch->contents, &ch->wearing, ch->array ) ) == NULL ) 
      return;
    if( fountain->pIndexData->item_type != ITEM_DRINK_CON
      && fountain->pIndexData->item_type != ITEM_FOUNTAIN ) {
      send( ch, "%s isn't something you can fill from.\n\r", fountain );
      return;
      }
    if( fountain->pIndexData->item_type == ITEM_DRINK_CON
      && fountain->value[1] == 0 ) {
      include_empty = FALSE; 
      send( ch, "%s is empty.\n\r", fountain );
      include_empty = TRUE; 
      return;
      }
    argument = arg;
    }

  where    = fountain->array;
  fountain = (obj_data*) fountain->From( 1 );
  fountain->To( where ); 

  if( ( array = several_things( ch, argument, 
    "fill", &ch->contents ) ) == NULL ) 
    return;

  if( fountain->pIndexData->item_type == ITEM_DRINK_CON
    && fountain->value[0] != -1 
    && ( array->size != 1 || array->list[0]->selected != 1 ) ) {
    send( ch, "Due to the rabid complexity of limited liquid and multiple\
 containers you may\n\ronly fill one container at a time from non-infinite\
 sources.\n\r" );
    return;
    }

  thing_array   subset  [ 4 ];
  thing_func*     func  [ 4 ]  = { cant_fill, same, already_full,
                                   fill };

  sort_objects( ch, *array, fountain, 4, subset, func );

  page_priv( ch, NULL, empty_string );
  page_priv( ch, &subset[0], "can't fill" );
  page_priv( ch, &subset[1], "Filling", NULL, "from itself is impossible" );
  page_priv( ch, &subset[2], NULL, NULL, "is already full",
    "are already full" );
  page_publ( ch, &subset[3], "fill", fountain, "from" );

  delete array;
}


bool react_filled( char_data* ch, obj_data* obj, int liquid )
{
  int spell;

  if( ( spell = liquid_table[liquid].spell ) == -1 )
    return FALSE;

  if( spell < SPELL_FIRST || spell >= WEAPON_FIRST ) {
    bug( "Do_fill: Liquid with non-spell skill." );
    return FALSE;
    }

  return( *spell_table[spell-SPELL_FIRST].function )( NULL, ch, obj, 10, -4 );
}


/*
 *   EMPTY ROUTINES
 */


thing_data* not_container( thing_data* thing, char_data*, thing_data* )
{
  obj_data* obj = object( thing );

  return( obj->pIndexData->item_type == ITEM_DRINK_CON
    ? obj : NULL );
}


thing_data* already_empty( thing_data* thing, char_data*, thing_data* )
{
  obj_data* obj = object( thing );

  return( obj->value[1] != 0 ? thing : NULL );
}


thing_data* fountain( thing_data* thing, char_data*, thing_data* )
{
  obj_data* obj = object( thing );

  return( obj->value[0] != -1 ? thing : NULL );
}


thing_data* empty_con( thing_data* thing, char_data*, thing_data* )
{
  obj_data* obj         = object( thing );
  content_array* where  = obj->array;

  obj = (obj_data*) obj->From( obj->selected );
  obj->value[1] = 0;
  obj->To( where );

  return obj;
}


void do_empty( char_data* ch, char* argument )
{
  thing_array*  array;
  thing_array   subset  [ 4 ];
  thing_func*     func  [ 4 ]  = { not_container, already_empty,
                                 fountain, empty_con };

  if( ( array = several_things( ch, argument,
    "empty", &ch->contents ) ) == NULL ) 
    return;
 
  sort_objects( ch, *array, NULL, 4, subset, func );

  include_empty = FALSE;

  page_priv( ch, NULL, empty_string );
  page_priv( ch, &subset[0], "emptying", NULL, "doesn't make sense" );
  page_priv( ch, &subset[1], NULL, NULL,
    "is already empty", "are already empty" );
  page_priv( ch, &subset[2], "can't empty" );
  page_publ( ch, &subset[3], "empty" );

  include_empty = TRUE;
  
  consolidate( subset[3] );

  delete array;
}