source: golgotha/src/golg/global_id.cc @ 80

Last change on this file since 80 was 80, checked in by Sam Hocevar, 12 years ago
  • Adding the Golgotha source code. Not sure what's going to be interesting in there, but since it's all public domain, there's certainly stuff to pick up.
File size: 5.3 KB
Line 
1/********************************************************************** <BR>
2  This file is part of Crack dot Com's free source code release of
3  Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
4  information about compiling & licensing issues visit this URL</a>
5  <PRE> If that doesn't help, contact Jonathan Clark at
6  golgotha_source@usa.net (Subject should have "GOLG" in it)
7***********************************************************************/
8
9#include "global_id.hh"
10#include "error/error.hh"
11#include "memory/malloc.hh"
12#include "saver.hh"
13#include "g1_object.hh"
14
15#include <string.h>
16
17sw32 g1_cur_num_map_objects;
18#define PREASSIGN_SIG ((g1_object_class *)0xbadfeed)
19
20g1_global_id_manager_class::g1_global_id_manager_class()
21{
22  init();
23  claim_freespace();
24}
25
26i4_bool g1_global_id_manager_class::preassigned(w32 id) const
27{
28  return obj[id&ID_MASK]==PREASSIGN_SIG;
29}
30
31
32g1_global_id_reset_notifier *g1_global_id_reset_notifier::first=0;
33
34g1_global_id_reset_notifier::g1_global_id_reset_notifier()
35{
36  next=first;
37  first=this;
38}
39
40
41g1_global_id_reset_notifier::~g1_global_id_reset_notifier()
42{
43  if (first==this)
44    first=first->next;
45  else
46  {
47    g1_global_id_reset_notifier *p;
48    for (p=first; p->next!=this; p=p->next);
49    p->next=next;
50  }
51}
52
53
54void g1_global_id_manager_class::init()
55{
56  // initialize ids
57  for (w32 i=0; i<G1_MAX_OBJECTS; i++)
58    obj_id[i] = ID_INCREMENT+i;
59
60  memset(obj, 0, sizeof(obj));
61  first_free=G1_MAX_OBJECTS;
62
63  g1_cur_num_map_objects=0;
64
65  for (g1_global_id_reset_notifier *p=g1_global_id_reset_notifier::first;
66       p; p=p->next)
67    p->reset();
68}
69
70void g1_global_id_manager_class::free_objects()
71{
72  w32 i = first_free,j=0;
73
74  while (i<G1_MAX_OBJECTS)
75  {
76    j = *((w32*)(&obj[i]));                       // next one
77    obj[i] = 0;
78    i = j;
79  }
80
81  for (i=0; i<G1_MAX_OBJECTS; i++)
82    if (obj[i])
83    {
84      delete obj[i];
85      obj[i]=0;
86    }
87
88  first_free=G1_MAX_OBJECTS;
89}
90
91void g1_global_id_manager_class::claim_freespace()
92{
93  int i=G1_MAX_OBJECTS;
94  while (i>0)
95  {
96    i--;
97    if (!obj[i])
98    {
99      *((w32*)(&obj[i]))=first_free;
100      first_free=i;
101    }
102  }
103}
104
105void g1_global_id_manager_class::assign(w32 id, g1_object_class *for_who)
106{
107  w32 index = id&ID_MASK;
108
109  if (obj_id[index]!=id)
110    i4_warning("assigning a possibly invalid id!");
111
112  if (obj[index]!=PREASSIGN_SIG)
113    i4_warning("assigning a previously assigned id!");
114
115  obj[index] = for_who;
116  //return i4_T;
117}
118
119w32 g1_global_id_manager_class::alloc(g1_object_class *for_who)
120{
121  if (first_free>=G1_MAX_OBJECTS)
122  {
123    claim_freespace();
124    if (first_free>=G1_MAX_OBJECTS)
125      i4_error("alloc object id : too many objects");
126  }
127
128  w32 id=first_free;
129  first_free = *((w32*)(&obj[id]));
130 
131  obj[id] = (for_who) ? for_who : PREASSIGN_SIG;
132  g1_cur_num_map_objects++;
133
134  return obj_id[id];
135}
136
137void g1_global_id_manager_class::free(w32 id)
138{
139  if (!check_id(id))
140  {
141    i4_warning("free object id : bad id");
142    return;
143  }
144
145  id &= ID_MASK;
146
147#if 1
148  // forces use of all ids first
149  obj[id]=0;
150#else
151  *((w32*)(&obj[id]))=first_free;
152  first_free=id;
153#endif
154  obj_id[id] += ID_INCREMENT;
155  g1_cur_num_map_objects--;
156}
157
158g1_global_id_manager_class::remapper::remapper(g1_global_id_manager_class *gid) : gid(gid)
159{
160  map = (w32 *)i4_malloc(G1_MAX_OBJECTS*sizeof(*map), "global_id_remapping");
161}
162g1_global_id_manager_class::remapper::~remapper()
163{
164  i4_free(map);
165}
166
167g1_global_id_manager_class g1_global_id;
168
169
170
171void g1_id_ref::save(g1_saver_class *fp)
172{
173  fp->write_global_id(id);
174}
175
176void g1_id_ref::load(g1_loader_class *fp)
177{
178  id=fp->read_global_id();
179}
180
181g1_id_ref::g1_id_ref(g1_object_class *o)
182{
183  id=o->global_id;
184}
185
186g1_id_ref& g1_id_ref::operator=(g1_object_class *o)
187{
188  if (o)
189    id=o->global_id;
190  else
191    id=g1_global_id.invalid_id();
192
193  return *this;
194}
195
196void g1_global_id_manager_class::debug(w32 flag_pass)
197{
198  w32 invalid[(G1_MAX_OBJECTS+31)/32];
199  w32 num_free=0;
200
201  memset(invalid,0,sizeof(invalid));
202
203  w32 i = first_free;
204  while (i<G1_MAX_OBJECTS)
205  {
206    invalid[i>>5] |= (1<< (i&31));                // mark bit
207    i = *((w32*)(&obj[i]));                       // next one
208    num_free++;                                   // count
209  }
210
211
212  for (i=0; i<G1_MAX_OBJECTS; i++)
213    if ((invalid[i>>5] & (1<<(i&31)))==0)
214      if (!obj[i])
215      {
216        invalid[i>>5] |= (1<< (i&31));
217        num_free++;
218      }
219      else
220        if (obj[i]->get_flag(flag_pass))
221          i4_debug->printf("%d: [%s] team:%d [%c%c%c%c]\n",
222                           i,
223                           obj[i]->name(),
224                           obj[i]->player_num,
225                           obj[i]->get_flag(g1_object_class::MAP_OCCUPIED)?'M':'m',
226                           obj[i]->get_flag(g1_object_class::THINKING)?'T':'t',
227                           obj[i]->get_flag(g1_object_class::SCRATCH_BIT)?'S':'s',
228                           obj[i]->get_flag(g1_object_class::DELETED)?'D':'d'
229                           );
230
231  i4_debug->printf("Valid Objects: %d  Free Spaces: %d\n", G1_MAX_OBJECTS-num_free, num_free);
232
233}
234
235void g1_list_objects(w32 flag_pass=0xffffffff)
236{
237  g1_global_id.debug(flag_pass);
238}
Note: See TracBrowser for help on using the repository browser.