Logo Search packages:      
Sourcecode: xblast version File versions  Download package

demo.c

/*
 * Program XBLAST V2.5.7 or higher
 * (C) by Oliver Vogel (e-mail: vogel@ikp.uni-koeln.de)
 * April 19th, 1997
 * started August 1993
 *
 * File: demo.c 
 * demo recording and playback
 *
 *
 * 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; or (at your option)
 * any later version
 *
 * This program is distributed in the hope that it will be entertaining,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILTY 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.
 *
 * $Id: demo.c,v 1.2 1999/10/03 09:44:32 xblast Exp $
 * $Log: demo.c,v $
 * Revision 1.2  1999/10/03 09:44:32  xblast
 * missing int inserted
 *
 * Revision 1.1  1998/01/03 14:11:22  xblast
 * Initial revision
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#define _DEMO_C
#include "include.h"
#include "mytypes.h"
#include "const.h"
#include "maze.h"
#include "mystring.h"
#include "demo.h"
#include "util.h"

/*
 * local typedefs
 */
typedef struct {
  char num_player;
  char team_mode;
  char max_lives;
  char random_spos;
  unsigned random_seed;
  unsigned length;
} XBDemoData;

/*
 * local variables
 */

static unsigned char *buffer = NULL;
static unsigned char *current = NULL;
static unsigned char *last;
static XBDemoData data;
static FILE *demo_fp;
static char demo_string[] = "XBlast 2.5 Demo";
static int num_player;
static int demo_level;
static char *player_name[MAX_PLAYER] = {
  "Player 1", "Player 2", "Player 3", "Player 4", "Player 5", "Player 6"
};


/*
 * public function: open_demo
 */
#ifdef __STDC__
int
open_demo (XBConfig *config, 
         XBSettings *setup,
         int level)
#else
int
open_demo (config, setup, level) 
  XBConfig *config;
  XBSettings *setup;
  int level;
#endif
{
  static int demo_count = 0;
  struct stat stat_buf;
  char fname[1024];
  

  /* number opf players */
  num_player = config->num_player;

  /* alloc data buffer */
  if (buffer == NULL) {
    buffer = malloc(GAME_TIME * config->num_player * sizeof(unsigned char) );
    if (buffer == NULL) {
      fprintf(stderr, "failed to alloc demo buffer\n");
      return -1;
    }
  }
  current = buffer;

  
  /* open demo file for output */
  do {
    sprintf(fname,"xblast%04d.dem", demo_count++);
  } while (stat(fname, &stat_buf) != -1);
  if (NULL == (demo_fp = fopen(fname, "w") ) ) {
    fprintf(stderr, "Failed to open demo-file \"%s\".\n", fname);
    return -1;
  }
  
  /* write header line */
  fprintf(demo_fp, "%s\n", demo_string);
  
  /* write level name */
  fprintf(demo_fp, "%s\n", get_level_name(level));

  /* set game information block */
  data.num_player  = config->num_player;
  data.team_mode   = config->team_mode;
  data.max_lives   = setup->max_lives;
  data.random_spos = setup->random_spos;
  data.random_seed = get_random_seed();

  return 0;
}

/*
 * public function: record_void
 */
#ifdef __STDC__
void
record_void (PlayerAction *pa)
#else
void
record_void (pa)
  PlayerAction *pa;
#endif
{
  /* just a dummy */
}

/*
 * public function: record_keys
 */
#ifdef __STDC__
void
record_keys (PlayerAction *pa)
#else
void
record_keys (pa)
  PlayerAction *pa;
#endif
{
  int i;

  for (i=0; i<num_player; i++) {
    /* bits #0-2 are used for the direction */
    *current =   (unsigned char)pa[i].dir;
    /* bit #3 is used for the bomb key */
    *current |= ((unsigned char)pa[i].bomb << 3);
    /* bit #4 is used for the special key */
    *current |= ((unsigned char)pa[i].special << 4);
    /* bits #5-6 are used for the abort keys */
    *current |= ((unsigned char)pa[i].abort << 5);
    /* go to next data element */
    current++;
  }
}

#ifdef __STDC__
int
close_demo (void)
#else
int
close_demo ()
#endif
{
  /* write length of demo data */
  data.length = current-buffer;

  /* write data block */
  if (1 != fwrite (&data, sizeof(XBDemoData), 1, demo_fp) ) {
    fprintf(stderr,"failed to write demo header to file\n");
    fclose (demo_fp);
    return -1;
  }

  /* write demo data */
  if ((current - buffer) != 
      fwrite (buffer, sizeof(unsigned char), current - buffer, demo_fp) ) {
    fprintf(stderr,"failed to write demo data to file\n");
    fclose (demo_fp);
    return -1;
  }
  
  /* close demo file */
  fclose (demo_fp);

  return 0;
}

/*
 * loading demos
 */

#ifdef __STDC__
int
load_demo (char *fname)
#else
int
load_demo (fname)
  char *fname;
#endif
{
  static char zeile[1024];
  char *newline;

  if (NULL == (demo_fp = fopen(fname,"r") ) ) {
    fprintf(stderr, "Failed to open demo file \"%s\".\n", fname);
    return -1;
  }

  /* get header line */
  fgets (zeile, 1024, demo_fp);
  if (NULL != (newline = rindex(zeile, '\n') ) ) {
    *newline = '\0';
  }
#ifdef DEBUG
  fprintf(stderr, "Demo type is \"%s\".\n", zeile);
#endif
  if (0 != strcmp(zeile,demo_string)) {
    fprintf(stderr, "Unsupported demo type \"%s\".\n", zeile);
    return -1;
  }
  
  /* get level name */
  fgets (zeile, 1024, demo_fp);
  if (NULL != (newline = rindex(zeile, '\n') ) ) {
    *newline = '\0';
  }
  if (-1 == (demo_level = get_level_by_name(zeile) ) ) {
    fprintf(stderr, "Unknown level \"%s\".\n", zeile);
    return -1;
  }
#ifdef DEBUG
  fprintf(stderr, "Level name is %d \"%s\".\n",demo_level,zeile);
#endif

  /* get demo data struct */
  if (1 != fread(&data, sizeof(XBDemoData), 1, demo_fp)) {
    fprintf(stderr, "Read failed in demo file \"%s\".\n", fname);
    return -1;
  }

  num_player = data.num_player;

  /* alloc buffer for demo data */
  if (buffer != NULL) {
    free(buffer);
  } 
  buffer = malloc(data.length * sizeof(unsigned char) );
  if (buffer == NULL) {
    fprintf(stderr, "failed to alloc demo buffer\n");
    return -1;
  }

  current = buffer;
  /* now read it */
  if (data.length != fread (buffer, sizeof(unsigned char), data.length, 
                      demo_fp) ) {
    fprintf(stderr, "Read failed in demo file \"%s\".\n", fname);
    return -1;
  }
  last = buffer + data.length;

  /* close file */
  fclose(demo_fp);
  return 0;
}

/*
 * public function config_from_demo
 */
#ifdef __STDC__
void
config_from_demo (XBConfig *config)
#else
void
config_from_demo (config)
  XBConfig *config;
#endif
{
  int p;
  config->num_player = data.num_player;
  config->num_disp = 1;
  config->team_mode = data.team_mode;
  for (p=0; p<data.num_player; p++) {
    config->pl_at_disp[p] = 0;
  }
}

/*
 * public function setup_from_demo
 */
#ifdef __STDC__
void
setup_from_demo (XBSettings *setup)
#else
void
setup_from_demo (setup)
  XBSettings *setup;
#endif
{
  int i;

  setup->max_victories = 9;
  setup->max_lives = data.max_lives;
  setup->start_level = demo_level;
  setup->random_mode = FALSE;
  setup->random_spos = data.random_spos;
  setup->print_stat = FALSE;
  for (i=0; i<levelMax; i++) {
    setup->use_level[i] = FALSE;
  }
  setup->use_level[demo_level] = TRUE;
}



/*
 * public player_strings_from_demo
 */
#ifdef __STDC__
void
player_strings_from_demo (PlayerStrings *st, 
                        XBConfig *config)
#else
void
player_strings_from_demo (st, config)
     PlayerStrings *st;
     XBConfig *config;
#endif
{
  int player;
  char line[1024];

  /* first get names for all players */
  for (player=0; player<MAX_PLAYER; player++) {
    st[player].tag = player_name[player];
  }
  /* if in team mode combine names */
  switch (config->team_mode) {
  case TM_Single:
    for (player=0; player<MAX_PLAYER; player ++) {
      st[player].name = st[player].tag;
    }
    break;
  case TM_Team:
    for (player=0; player<MAX_PLAYER; player += 2) {
      sprintf(line, "%s & %s", st[player].tag, st[player+1].tag);
      st[player].name = st[player+1].name = dup_string(line, strlen(line)); 
    }
    break;
  case TM_Double:
    for (player=0; player<MAX_PLAYER; player ++) {
      st[player + config->num_player/2].name 
      = st[player + config->num_player/2].tag 
      = st[player].name = st[player].tag;
    }
    break;
  } 

  /* set player string */
  for (player=0; player<MAX_PLAYER; player++) {
    /* pause string */
    sprintf(line, "Game paused by %s", st[player].tag);
    st[player].pause = dup_string(line, strlen(line));
    /* win level */
    if (config->team_mode == TM_Single) {
      sprintf(line, "%s wins", st[player].name);
    } else {
      sprintf(line, "%s win", st[player].name);
    }
    st[player].winlevel = dup_string(line, strlen(line));
    /* abort level */
    sprintf(line, "Abort requested by %s", st[player].tag);
    st[player].abort = dup_string(line, strlen(line));
    /* cancel level abort */
    sprintf(line, "%s cancels abort", st[player].tag);
    st[player].abortcancel = dup_string(line, strlen(line));
    /* the rest is NULL */
    st[player].wingame = NULL;
    st[player].loselevel = NULL;
    st[player].loselife = NULL;
    st[player].gloat = NULL;
    st[player].welcome = NULL;
  }

}



/*
 * public function reset_demo
 */
#ifdef __STDC__
void
reset_demo (void)
#else
void
reset_demo ()
#endif
{
  seed_random (data.random_seed);
  current = buffer;
}

/*
 * public function: record_keys
 */
#ifdef __STDC__
void
playback_keys (PlayerAction *pa)
#else
void
playback_keys (pa)
  PlayerAction *pa;
#endif
{
  int i;

  if (current < last) {
    for (i=0; i<num_player; i++) {
      /* bits #0-2 are used for the direction */
      pa[i].dir = (int) (*current & 0x7);
      /* bit #3 is used for the bomb key */
      pa[i].bomb = ( (*current & (1<<3)) != 0 );
      /* bit #4 is used for the special key */
      pa[i].special = ( (*current & (1<<4)) != 0 );
      /* bits #5-6 are used for the abort keys */
      pa[i].abort = (int) ((*current>>5) & 0x3);
      /* go to next data element */
      current++;
    }
  } else {
    for (i=0; i<num_player; i++) {
      pa[i].dir = GoDefault;
      pa[i].bomb = TRUE;
      pa[i].special = FALSE;
      pa[i].abort = ABORT_NONE;
    }
  }
}

/*
 * end of file demo.c
 */




Generated by  Doxygen 1.6.0   Back to index