/*
 * static char *rcsid_player_c =
 *   "$Id: player.c,v 1.31 1997/11/11 10:50:39 master Exp $";
 */

/*
    CrossFire, A Multiplayer game for X-windows

    Copyright (C) 1994 Mark Wedel
    Copyright (C) 1992 Frank Tore Johansen

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

    The author can be reached via e-mail to master@rahul.net
*/

#include <global.h>
#include <funcpoint.h>

/*
 * Returns a newly allocated and initialised and correctly
 * linked player structure.
 */

player *get_player_ob() {
  int i;
  player *new,*tmp;

  new = (player *) CALLOC(1,sizeof(player));
  if(new==NULL)
    fatal(OUT_OF_MEMORY);
  if(!editor) {
    tmp=first_player;
    while(tmp!=NULL&&tmp->next!=NULL)
      tmp=tmp->next;
    if(tmp!=NULL)
      tmp->next=new;
    else
      first_player=new;
  }
  new->next=NULL;
  new->menu_strings=NULL;
  new->sync = settings.synchronize;
  new->cur_sync = 1;
  new->known_spell = 0;
  new->removed=0;
#ifdef SIMPLE_PARTY_SYSTEM
  new->party_number=-1;
#endif
  new->last_known_spell = 0;
  new->infoline=0;
  new->infopos=0;
  new->infofull=0;
  new->keyboard_flush=0;
  new->show_inv_icon=0;
  new->sort_inventory=0;
  new->infolines=INFOLINES;
  new->infochars=INFOCHARS;
  new->gc_root=NULL;
  new->gc_xpm_floor=NULL;
  new->gc_xpm_object=NULL;
  new->info=(char **) malloc(sizeof(char *) * new->infolines);
  for(i=0;i<new->infolines;i++) {
    new->info[i]=(char *) malloc(sizeof(char) * (new->infochars + 1));
    strcpy(new->info[i]," ");
  }
  for(i=0;i<MAX_LOOK_SIZE;i++) {
    new->look_name[i]=NULL;
    new->look_face[i]=blank_face->number;
  }
  for(i=0;i<MAX_INV_SIZE;i++) {
    new->inv_name[i]=NULL;
    new->inv_face[i]=blank_face->number;
  }
  new->commandkey =(KeyCode)('\'');
  new->firekey[0] =0;
  new->firekey[1] =0;
  new->runkey[0] =0;
  new->runkey[1] =0;
  for(i=0;i<COMMAND_HASH_SIZE;i++)
    new->keys[i] =NULL;
  new->key_state=0;
  new->key_down=0;
  new->state=0;

  new->use_pixmaps = 0;
  new->pixmaps = NULL;
  new->masks = NULL;
  new->use_pixmaps=0;
  new->color_pixmaps=0;
  new->ob = get_object();
  new->ob->name = add_string("logon");
  new->ob->type = PLAYER;
  new->ob->contr = new;
  new->show_what = show_all;
  new->name = NULL;
  new->username = NULL;
  new->shoottype = range_none;
  new->last_shoot = range_size;
  new->no_echo =0;
  new->split_window =0;
  new->braced =0;
  new->search_str[0]=0;
#if 0
  memset(new->mapdelx, 0, 32);
  memset(new->mapdely, 0, 32);
#endif

#ifdef SAVE_WINDOW_POSITIONS
  new->valid_save_positions =0;
  memset(new->win_pos, 0, 6*sizeof(save_win_pos));
#endif
#ifdef USE_SWAP_STATS
  new->Swap_First = -1;
#endif
#ifdef SOUND_EFFECTS
  new->play_count=0;
  new->rplay_fd=0;
#endif

  for (i=0; i<NUM_OUTPUT_BUFS; i++) {
	new->outputs[i].buf=NULL;
	new->outputs[i].first_update=0;
	new->outputs[i].count=0;
  }
  new->outputs_sync=16;		/* Every 2 seconds */
  new->outputs_count=1;		/* Keeps present behaviour */
  new->mark=NULL;
  new->mark_count=0;
  new->draw_fire_on=0;
  new->draw_run_on=0;
  new->show_buttons=0;
  return new;
}

void free_player(player *pl) {
  int i;
  Key_s *key, *nextkey;

  if(first_player!=pl) {
    player *prev=first_player;
    while(prev!=NULL&&prev->next!=NULL&&prev->next!=pl)
      prev=prev->next;
    if(prev->next!=pl) {
      LOG(llevError,"Free_player: Can't find previous player.\n");
      exit(1);
    }
    prev->next=pl->next;
  } else first_player=pl->next;
  if(pl->ob != NULL)
    free_object(pl->ob);
  if(pl->name!=NULL)
    free_string(pl->name);
  if(pl->username != NULL)
    free(pl->username);
  if(pl->info) {	
    for(i=0;i<pl->infolines;i++)  {
	  free(pl->info[i]);
	  pl->info[i]=NULL;
    }
    free(pl->info);
  }
  /*
   * Binded keys
   */
  for(i=0;i<COMMAND_HASH_SIZE;i++) {
    for (key=pl->keys[i]; key; key=nextkey) {
	nextkey = key->next;
	free(key);
    }
    pl->keys[i] = NULL;
  }

  /* The XPM manual says that XFreePixmap and XFreeColors should be called
   * when those resources are no longer needed (this applies to the 
   * color pixmap (XPM) code.  Hopefully, the X11 server does so when 
   * the connection is closed.  However, the connection to close the display
   * is called before it gets here, so we can not do XFreePixmap or
   * XFreeColors here.   Mark Wedel (master@rahul.net)
   */
  if(pl->pixmaps != NULL) {
    free(pl->pixmaps);
  }
  if (pl->masks!=NULL)
	free(pl->masks);

  /* Free the menu strings and pointer as appropriate */
  if (pl->menu_strings) {  
    for (i=pl->menu_on_item; i<pl->menu_items_num; i++)
	free(pl->menu_strings[i]);
    free(pl->menu_strings);
  }

    for (i=0; i<MAX_INV_SIZE; i++)
	if (pl->inv_name[i]) free_string(pl->inv_name[i]);
    for (i=0; i<MAX_LOOK_SIZE; i++)
	if (pl->look_name[i]) free_string(pl->look_name[i]);

  CFREE(pl);
}
