source: abuse/trunk/src/chars.cpp @ 129

Last change on this file since 129 was 129, checked in by Sam Hocevar, 15 years ago
  • Get rid of jmalloc and replace it with standard malloc. Modern operating systems certainly perform a lot better than this custom implementation, and we have superior tools (eg. valgrind) to debug and profile memory usage without interfering with the code itself.
File size: 13.9 KB
Line 
1/*
2 *  Abuse - dark 2D side-scrolling platform game
3 *  Copyright (c) 1995 Crack dot Com
4 *
5 *  This software was released into the Public Domain. As with most public
6 *  domain software, no warranty is made or implied by Crack dot Com or
7 *  Jonathan Clark.
8 */
9
10#include "config.h"
11
12#include "chars.hpp"
13#include "game.hpp"
14#include "intsect.hpp"
15#include "lisp.hpp"
16#include "jwindow.hpp"
17#include "input.hpp"
18#include "id.hpp"
19#include "clisp.hpp"
20#include "dprint.hpp"
21#include "lisp_gc.hpp"
22
23#define FADING_FRAMES 26
24#define FADING_MAX 32
25
26character_type **figures;
27
28
29
30int total_weapons=0;
31int *weapon_types=NULL;    // maps 0..total_weapons into 'real' weapon type
32
33char const *state_names[MAX_STATE] =
34{
35    "dead",
36    "dieing",
37    "stopped",
38    "start_run_jump", "run_jump", "run_jump_fall", "end_run_jump",
39    "flinch_up", "flinch_down",
40    "morph_pose",
41    "running"
42};
43
44/*                   "start_still_jump","still_jump","still_jump_fall","end_still_jump",
45
46                   "morph_pose",
47           
48                   "walking",
49           
50
51                   "weapon_draw",
52                   "weapon_put_away",
53                   "weapon_fire",
54                   "weapon_end_fire",
55                   "weapon_fire_up",
56                   "weapon_end_fire_up",
57
58                   "blocking",
59                   "block_recoil",
60
61                   "turn_around",
62                   "flinch_up","flinch_down","flinch_back",
63                   "flinch_air","flinch_ground","flinch_getup","woze",
64                   "stance"
65                 } ; */
66
67
68char const *cflag_names[TOTAL_CFLAGS] =
69{
70    "hurt_all", "is_weapon", "stoppable", "can_block",
71    "hurtable", "pushable", "unlistable",
72    "add_front", "cached_in", "need_cache_in", "unactive_shield"
73};
74
75char const *ofun_names[TOTAL_OFUNS] =
76{
77    "ai_fun", "move_fun", "draw_fun", "map_draw_fun", "damage_fun",
78    "next_state_fun", "user_fun",
79    "constructor", "reload_fun", "get_cache_list_fun",
80    "type_change_fun"
81};
82
83int character_type::add_state(void *symbol)             // returns index into seq to use
84{
85  if (item_type(symbol)!=L_SYMBOL)
86  {
87    lprint(symbol);
88    lbreak("is not a symbol (in def_char)");
89    exit(0);
90  }
91
92  void *val=symbol_value(symbol);
93
94  int num;
95  if (DEFINEDP(val))
96  {
97    if (item_type(val)!=L_NUMBER)
98    {
99      lprint(symbol);
100      dprintf("expecting symbol value to be a number, instead got : ");
101      lprint(val);
102      lbreak("");
103      exit(0);
104    }
105    num=lnumber_value(val);
106  } else
107  {
108    num=ts;
109    if (num<MAX_STATE) num=MAX_STATE;
110    int sp=current_space;
111    current_space=PERM_SPACE;
112    set_symbol_number(symbol,num);
113    current_space=sp;
114  }
115
116  if (num<ts && seq[num])
117  {
118    lprint(symbol);
119    lbreak("symbol has been assigned value %d, but value already in use by state %s\n"
120       "use a different symbol for this state\n",
121       lstring_value(symbol_name(seq_syms[num])));
122    exit(0);
123  } else if (num>=ts)
124  {
125    seq=(sequence **)realloc(seq,sizeof(sequence *)*(num+1));
126    seq_syms=(void **)realloc(seq_syms,sizeof(void *)*(num+1));
127
128    memset(&seq[ts],0,sizeof(sequence *)*((num+1)-ts));
129    memset(&seq_syms[ts],0,sizeof(void *)*((num+1)-ts));
130
131    ts=num+1;
132  }
133
134  seq_syms[num]=symbol;
135  return num;
136}
137
138int flinch_state(character_state state)
139{
140  if (state==flinch_up || state==flinch_down)
141    return 1;
142  else return 0;
143}
144
145int character_type::cache_in()    // returns false if out of cache memory
146{
147  int i;
148  if (get_cflag(CFLAG_CACHED_IN))
149    return 1;
150  cflags|=1<<CFLAG_CACHED_IN;
151
152  for (i=0;i<ts;i++)
153  {
154    if (seq[i])
155      seq[i]->cache_in();
156  }
157  return 1;
158}
159
160void character_type::add_sequence(character_state which, sequence *new_seq)
161{
162  if (seq[which])
163    delete seq[which];
164  seq[which]=new_seq;
165}
166
167void *l_obj_get(long number) // exten lisp function switches on number
168{
169  character_type *t=figures[current_object->otype];
170  if (t->tiv<=number || !t->vars[number])
171  {
172    lbreak("access : variable does not exsist for this class\n");
173    return 0;
174  }
175  return new_lisp_number(current_object->lvars[t->var_index[number]]);
176}
177
178void l_obj_set(long number, void *arg)  // exten lisp function switches on number
179{
180  character_type *t=figures[current_object->otype];
181  if (t->tiv<=number || !t->vars[number])
182  {
183    lbreak("set : variable does not exsist for this class\n");
184    return;
185  }
186  current_object->lvars[t->var_index[number]]=lnumber_value(arg);
187}
188
189void l_obj_print(long number)  // exten lisp function switches on number
190{
191  character_type *t=figures[current_object->otype];
192  if (t->tiv<=number || !t->vars[number])
193  {
194    lbreak("access : variable does not exsist for this class\n");
195    return;
196  }
197  dprintf("%d",current_object->lvars[t->var_index[number]]);
198}
199
200void character_type::add_var(void *symbol, void *name)
201{
202  /* First see if the variable has been defined for another object
203     if so report a conflict if any occur */
204  lisp_symbol *s=(lisp_symbol *)symbol;
205  if (DEFINEDP(s->value) && (item_type(s->value)!=L_OBJECT_VAR))
206  {
207    lprint(symbol);
208    lbreak("symbol already has a value, cannot instantiate an object varible");
209    exit(0);
210  } else if (DEFINEDP(s->value))
211  {
212    int index=((lisp_object_var *)s->value)->number;
213    if (index<tiv)
214    {
215      if (vars[index])
216      {
217    lbreak("While defining object %s :\n"
218           "  var '%s' was previously defined by another\n"
219           "  with index %d, but %s has a var listed '%s' with same index\n"
220           "  try moving definition of %s before previously declared object",
221           lstring_value(symbol_name(name)),
222           lstring_value(symbol_name(symbol)),
223           index,
224           lstring_value(symbol_name(name)),
225           lstring_value(symbol_name(vars[index])),
226           lstring_value(symbol_name(name))
227           );
228    exit(0);
229      } else
230      {
231    var_index[index]=tv;
232    vars[index]=symbol;
233    tv++;
234      }
235    } else
236    {
237      int new_total=index+1;
238      vars=(void **)realloc(vars,sizeof(void *)*new_total);
239      var_index=(short *)realloc(var_index,sizeof(short)*new_total);
240      memset(&vars[tiv],0,(new_total-tiv)*sizeof(void *));
241      memset(&var_index[tiv],0,(new_total-tiv)*sizeof(short));
242      tiv=new_total;
243
244      var_index[index]=tv;
245      vars[index]=symbol;
246      tv++;
247    }
248  } else  /** Nope, looks like we have to add the variable ourself and define the assesor funs */
249  {
250    /* locate a free index in the index list */
251    int free_index=tiv;
252    for (int i=0;i<tiv;i++)
253      if (!vars[i] && i<tiv) free_index=i;
254    if (free_index==tiv)
255    {
256      int new_total=free_index+1;
257      vars=(void **)realloc(vars,sizeof(void *)*new_total);
258      var_index=(short *)realloc(var_index,sizeof(short)*new_total);
259      memset(&vars[tiv],0,(new_total-tiv)*sizeof(void *));
260      memset(&var_index[tiv],0,(new_total-tiv)*sizeof(short));
261      tiv=new_total;
262    }
263
264    /* create the var and add to var list */
265    int sp=current_space;
266    current_space=PERM_SPACE;
267
268    add_c_object(symbol,free_index);
269
270    vars[free_index]=symbol;
271    var_index[free_index]=tv;
272    tv++;
273    current_space=sp;
274  }
275}
276
277
278long character_type::isa_var_name(char *name)
279{
280  int i=0;
281  for (;i<TOTAL_OBJECT_VARS;i++)
282  {
283    if (!strcmp(object_descriptions[i].name,name))
284      return 1;
285  }
286  for (i=0;i<tiv;i++)
287    if (!strcmp(lstring_value(symbol_name(vars[i])),name))
288      return 1;
289  return 0;
290}
291
292character_type::character_type(void *args, void *name)
293{
294  p_ref r2(args);
295  int i;
296  ts=tv=0;
297  seq=NULL;
298  seq_syms=NULL;
299  vars=NULL;
300  var_index=NULL;
301  tiv=0;
302
303  void *l_abil=  make_find_symbol("abilities");
304  void *l_funs=  make_find_symbol("funs");
305  void *l_states=make_find_symbol("states");
306  void *l_flags= make_find_symbol("flags");
307  void *l_range= make_find_symbol("range");
308  void *l_draw_range= make_find_symbol("draw_range");
309  void *l_fields=make_find_symbol("fields");
310  void *l_logo=  make_find_symbol("logo");
311  void *l_vars=  make_find_symbol("vars");
312
313  memset(fun_table,0,sizeof(fun_table));     // destory all hopes of fun
314  fields=NULL;
315  cflags=0;
316  morph_mask=-1;
317  morph_power=0;
318  total_fields=0;
319  logo=-1;
320  rangex=rangey=0;
321  draw_rangex=draw_rangey=0;
322
323  for (i=0;i<TOTAL_ABILITIES;i++)
324    abil[i]=get_ability_default((ability)i);
325  void *field=args;
326  p_ref r7(field);
327  for (;field;field=CDR(field))
328  {
329    void *f=CAR(CAR(field));
330    p_ref r1(f);
331
332    if (f==l_abil)
333    {
334      void *l=CDR(CAR(field));
335      p_ref r4(l);
336      for (i=0;i<TOTAL_ABILITIES;i++)
337      {
338    Cell *ab=assoc(make_find_symbol(ability_names[i]),l);
339    p_ref r5(ab);
340    if (!NILP(ab))
341      abil[i]=lnumber_value(eval(lcar(lcdr(ab))));
342      }
343    } else if (f==l_funs)
344    {
345      void *l=CDR(CAR(field));
346      p_ref r4(l);
347      for (i=0;i<TOTAL_OFUNS;i++)
348      {
349    Cell *ab=assoc(make_find_symbol(ofun_names[i]),l);
350    p_ref r5(ab);
351    if (!NILP(ab) && lcar(lcdr(ab)))
352    fun_table[i]=lcar(lcdr(ab));
353      }
354    } else if (f==l_flags)
355    {
356      void *l=CDR(CAR(field));
357      p_ref r4(l);
358      for (i=0;i<TOTAL_CFLAGS;i++)
359      {
360    Cell *ab=assoc(make_find_symbol(cflag_names[i]),l);
361    p_ref r5(ab);
362    if (!NILP(ab) && eval(lcar(lcdr(ab))))
363    cflags|=(1<<i);
364      }
365
366      if (get_cflag(CFLAG_IS_WEAPON))  // if this is a weapon add to weapon array
367      {
368    total_weapons++;
369    weapon_types=(int *)realloc(weapon_types,sizeof(int)*total_weapons);
370    weapon_types[total_weapons-1]=total_objects;
371      }
372    } else if (f==l_range)
373    {
374      rangex=lnumber_value(eval(lcar(lcdr(lcar(field)))));
375      rangey=lnumber_value(eval(lcar(lcdr(lcdr(lcar(field))))));
376    } else if (f==l_draw_range)
377    {
378      draw_rangex=lnumber_value(eval(lcar(lcdr(lcar(field)))));
379      draw_rangey=lnumber_value(eval(lcar(lcdr(lcdr(lcar(field))))));
380    } else if (f==l_states)
381    {
382      void *l=CDR(CAR(field));
383      p_ref r4(l);
384      char fn[100];
385      strcpy(fn,lstring_value(eval(CAR(l)))); l=CDR(l);
386      while (l)
387      {
388      int index;
389      void *e;
390      sequence *mem;
391      index = add_state(CAR((CAR(l))));
392      e = eval(CAR(CDR(CAR(l))));
393      mem = new sequence(fn,e,NULL);
394    seq[index]=mem;
395    l=CDR(l);
396      }
397    } else if (f==l_fields)
398    {
399      void *mf=CDR(CAR(field));
400      p_ref r4(mf);
401      while (!NILP(mf))
402      {
403    char *real=lstring_value(eval(lcar(lcar(mf))));
404    char *fake=lstring_value(eval(lcar(lcdr(lcar(mf)))));
405    if (!isa_var_name(real))
406    {
407      lprint(field);
408      lbreak("fields : no such var name \"%s\"\n",name);
409      exit(0);
410    }
411    total_fields++;
412
413    fields=(named_field **)realloc(fields,sizeof(named_field *)*total_fields);
414    fields[total_fields-1]=new named_field(real,fake);
415    mf=lcdr(mf);
416      }
417    } else if (f==l_logo)
418    {
419      char *fn=lstring_value(eval(CAR(CDR(CAR(field)))));
420      char *o=lstring_value(eval(CAR(CDR(CDR(CAR(field))))));
421      logo=cache.reg(fn,o,SPEC_IMAGE,1);
422    } else if (f==l_vars)
423    {
424      void *l=CDR(CAR(field));
425      p_ref r8(l);
426      while (l)
427      {
428    add_var(CAR(l),name);
429    l=CDR(l);
430      }
431    }
432    else
433    {
434      lprint(lcar(field));
435      lbreak("Unknown field for character definition");
436      exit(0);
437    }
438  }
439
440  if (!seq[stopped])
441    lbreak("object (%s) has no stopped state, please define one!\n",
442       lstring_value(symbol_name(name)));
443
444/*  char *fn=lstring_value(lcar(desc));
445  if (!fn)
446  {
447    printf("No filename given for def-character (%s)\n",name);
448    exit(0);
449  }
450  desc=lcdr(desc);  //  skip filename
451
452
453  Cell *mrph=assoc(l_morph,desc);     // check for morph info
454  morph_power=0;
455  if (!NILP(mrph))
456  {
457    mrph=lcdr(mrph);
458    morph_mask=cache.reg_object(fn,lcar(mrph),SPEC_IMAGE,1);
459    morph_power=lnumber_value(lcar(lcdr(mrph)));
460  } else morph_mask=-1;
461
462  Cell *sa=assoc(l_state_art,desc);
463  if (NILP(sa))
464  {
465    printf("missing state state art in def-character (%s)\n",name);
466    exit(0);
467  }
468
469  sa=lcdr(sa);   // list of state sequences
470  while (!NILP(sa))
471  {
472    int num=lnumber_value(lcar(lcar(sa)));
473    if (seq[num])
474      printf("Warning : state '%s' defined multiply for object %s\n"
475         "          using first definition\n",state_names[num],name);
476    else
477      seq[lnumber_value(lcar(lcar(sa)))]=new sequence(fn,lcar(lcdr(lcar(sa))),lcar(lcdr(lcdr(lcar(sa)))));
478    sa=lcdr(sa);
479  }
480
481  Cell *range=assoc(l_range,desc);
482  if (!NILP(range))
483  {
484    rangex=lnumber_value(lcar(lcdr(range)));
485    rangey=lnumber_value(lcar(lcdr(lcdr(range))));
486  } else
487  {
488    rangex=100;
489    rangey=50;
490  }
491
492
493
494
495  Cell *mf=assoc(l_fields,desc);
496  if (!NILP(mf))
497  {
498    mf=lcdr(mf);
499    total_fields=0;
500    while (!NILP(mf))
501    {
502      char *name=lstring_value(lcar(lcar(mf)));
503      int t=default_simple.total_vars(),find=-1;
504      for (int i=0;find<0 && i<t;i++)
505        if (!strcmp(default_simple.var_name(i),name))
506      find=i;
507      if (find<0)
508      {
509    lprint(assoc(l_fields,desc));
510    printf("fields : no such var name \"%s\"\n",name);
511    printf("current possiblities are : \n");
512    for (int i=0;i<t;i++) printf("\"%s\" ",default_simple.var_name(i));
513    printf("\n");
514    exit(0);
515      }
516      char *new_name=lstring_value(lcar(lcdr(lcar(mf))));
517      total_fields++;
518
519      fields=(named_field **)realloc(fields,sizeof(named_field *)*total_fields);
520      fields[total_fields-1]=new named_field(find,new_name);
521      mf=lcdr(mf);
522    }
523  } else total_fields=0;
524
525
526  Cell *lg=assoc(l_logo,desc);
527  if (NILP(lg))
528  {
529    if (get_cflag(CFLAG_IS_WEAPON))
530    {
531      lprint(desc);
532      lbreak("object must have a logo defined if it is a weapon\n"
533         "example '(logo . (""art/misc.spe"" . ""big waepon""))\n");
534    }
535    logo=-1;
536  }
537  else
538    logo=cache.reg_object(fn,lcdr(lg),SPEC_IMAGE,1);
539    */
540}
541
542
543sequence *character_type::get_sequence(character_state s)
544{
545  if (seq[s])
546    return seq[s];
547  else return seq[stopped];
548}
549
550
551character_type::~character_type()
552{
553  for (int i=0;i<ts;i++)
554    if (seq[i])
555      delete seq[i];
556  if (ts) free(seq);
557
558  if (total_fields)
559  {
560    for (int i=0;i<total_fields;i++)
561      delete fields[i];
562    free(fields);
563  }
564
565  if (ts)
566    free(seq_syms);
567
568  if (tiv)
569  {
570    free(vars);
571    free(var_index);
572  }
573
574
575}
576
Note: See TracBrowser for help on using the repository browser.