]> git.pond.sub.org Git - empserver/blob - src/lib/update/finish.c
Remove a bunch of redundant casts.
[empserver] / src / lib / update / finish.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2005, Dave Pare, Jeff Bailey, Thomas Ruschak,
4  *                           Ken Stevens, Steve McClure
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  *  ---
21  *
22  *  See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
23  *  related information and legal notices. It is expected that any future
24  *  projects/authors will amend these files as needed.
25  *
26  *  ---
27  *
28  *  finish.c: Finish the update
29  * 
30  *  Known contributors to this file:
31  *     Dave Pare, 1986
32  *     Thomas Ruschak, 1993
33  *     Steve McClure, 1998
34  */
35
36 #include "misc.h"
37 #include "sect.h"
38 #include "nat.h"
39 #include "file.h"
40 #include "xy.h"
41 #include "path.h"
42 #include "distribute.h"
43 #include "update.h"
44 #include "common.h"
45 #include "optlist.h"
46
47 /* Used for building up distribution info */
48 struct distinfo {
49     s_char *path;               /* path to take */
50     double imcost;              /* import cost */
51     double excost;              /* export cost */
52 };
53
54 /* This is our global buffer of distribution pointers.  Note that
55  * We only malloc this once, and never again (until reboot time
56  * of course :) ) We do clear it each and every time. */
57 struct distinfo *g_distptrs = (struct distinfo *)0;
58
59 /* Note that even though we malloc and save the path, it is never
60  * used.  Thus, this option.  If you want to malloc and save every
61  * path and then free when done, just enable this.  Or, if the
62  * dodistribute ever uses the path for something other than checking
63  * to see that a path exists, enable this */
64 /* #define SAVE_FINISH_PATHS */
65
66 #ifndef SAVE_FINISH_PATHS
67 static s_char *finish_path = "h";       /* Placeholder indicating path exists */
68 #endif /* SAVE_FINISH_PATHS */
69
70 static void assemble_dist_paths(struct distinfo *distptrs);
71 static s_char *ReversePath(s_char *path);
72
73 void
74 finish_sects(int etu)
75 {
76     struct sctstr *sp;
77     struct natstr *np;
78     int n;
79     struct distinfo *infptr;
80
81     if (g_distptrs == (struct distinfo *)0) {
82         logerror("First update since reboot, allocating buffer\n");
83         /* Allocate the information buffer */
84         g_distptrs = (struct distinfo *)(malloc((WORLD_X * WORLD_Y) *
85                                                 sizeof(struct distinfo)));
86         if (g_distptrs == (struct distinfo *)0) {
87             logerror("malloc failed in finish_sects.\n");
88             return;
89         }
90
91         logerror("Allocated '%lu' bytes '%d' indices\n",
92                  (unsigned long)(WORLD_X * WORLD_Y * sizeof(struct distinfo)),
93                  WORLD_X * WORLD_Y);
94     }
95
96     /* Wipe it clean */
97     memset(g_distptrs, 0, ((WORLD_X * WORLD_Y) * sizeof(struct distinfo)));
98
99     logerror("delivering...\n");
100     /* Do deliveries */
101     for (n = 0; NULL != (sp = getsectid(n)); n++) {
102         if (sp->sct_type == SCT_WATER)
103             continue;
104         if (sp->sct_own == 0)
105             continue;
106         np = getnatp(sp->sct_own);
107         if (np->nat_money < 0)
108             continue;
109         dodeliver(sp);
110     }
111     logerror("done delivering\n");
112
113     logerror("assembling paths...\n");
114
115     /* First, enable the best_path cacheing */
116     bp_enable_cachepath();
117
118     /* Now assemble the paths */
119     assemble_dist_paths(g_distptrs);
120
121     /* Now disable the best_path cacheing */
122     bp_disable_cachepath();
123
124     /* Now, clear the best_path cache that may have been created */
125     bp_clear_cachepath();
126
127     logerror("done assembling paths\n");
128
129     logerror("exporting...");
130     for (n = 0; NULL != (sp = getsectid(n)); n++) {
131         if (sp->sct_type == SCT_WATER || sp->sct_own == 0)
132             continue;
133         np = getnatp(sp->sct_own);
134         if (np->nat_money < 0)
135             continue;
136         /* Get the pointer */
137         infptr = &g_distptrs[XYOFFSET(sp->sct_x, sp->sct_y)];
138         dodistribute(sp, EXPORT,
139                      infptr->path, infptr->imcost, infptr->excost);
140     }
141     logerror("done exporting\n");
142
143     /* Note that we free the paths (if allocated) as we loop here */
144     logerror("importing...");
145     for (n = 0; NULL != (sp = getsectid(n)); n++) {
146         /* Get the pointer (we do it first so we can free if needed) */
147         infptr = &g_distptrs[XYOFFSET(sp->sct_x, sp->sct_y)];
148         if (sp->sct_type == SCT_WATER || sp->sct_own == 0) {
149 #ifdef SAVE_FINISH_PATHS
150             if (infptr->path)
151                 free(infptr->path);
152 #endif /* SAVE_FINISH_PATHS */
153             continue;
154         }
155         np = getnatp(sp->sct_own);
156         if (np->nat_money < 0) {
157 #ifdef SAVE_FINISH_PATHS
158             if (infptr->path)
159                 free(infptr->path);
160 #endif /* SAVE_FINISH_PATHS */
161             continue;
162         }
163         dodistribute(sp, IMPORT,
164                      infptr->path, infptr->imcost, infptr->excost);
165 #ifdef SAVE_FINISH_PATHS
166         if (infptr->path)
167             free(infptr->path);
168 #endif /* SAVE_FINISH_PATHS */
169     }
170     logerror("done importing\n");
171
172 }
173
174 static void
175 assemble_dist_paths(struct distinfo *distptrs)
176 {
177     s_char *path, *p;
178     double d;
179     struct sctstr *sp;
180     struct sctstr *dist;
181     struct distinfo *infptr;
182     int n;
183     s_char buf[512];
184
185     for (n = 0; NULL != (sp = getsectid(n)); n++) {
186         if ((sp->sct_dist_x == sp->sct_x) && (sp->sct_dist_y == sp->sct_y))
187             continue;
188         /* Set the pointer */
189         infptr = &distptrs[XYOFFSET(sp->sct_x, sp->sct_y)];
190         /* now, get the dist sector */
191         dist = getsectp(sp->sct_dist_x, sp->sct_dist_y);
192         if (dist == (struct sctstr *)0) {
193             logerror("Bad dist sect %d,%d for %d,%d !\n", sp->sct_dist_x,
194                      sp->sct_dist_y, sp->sct_x, sp->sct_y);
195             continue;
196         }
197         /* Now, get the best distribution path over roads */
198         /* Note we go from the dist center to the sector.  This gives
199            us the import path for that sector. */
200         path = BestDistPath(buf, dist, sp, &d, MOB_ROAD);
201
202         /* Now, we have a path */
203         if (path != (s_char *)0) {
204 #ifdef SAVE_FINISH_PATHS
205             int len;
206             /* Here we malloc a buffer and save it */
207             len = strlen(path);
208             infptr->path = malloc(len);
209             if (infptr->path == (s_char *)0) {
210                 logerror("malloc failed in assemble_dist_path!\n");
211                 return;
212             }
213 #endif /* SAVE_FINISH_PATHS */
214             /* Save the import cost */
215             infptr->imcost = d;
216             /* Now, reverse the path */
217             p = ReversePath(path);
218             /* And walk the path back to the dist center to get the export
219                cost */
220             infptr->excost = pathcost(sp, p, MOB_ROAD);
221 #ifdef SAVE_FINISH_PATHS
222             memcpy(infptr->path, p, len);
223 #else
224             infptr->path = finish_path;
225 #endif /* SAVE_FINISH_PATHS */
226         }
227     }
228 }
229
230 static s_char *
231 ReversePath(s_char *path)
232 {
233     s_char *patharray = "aucdefjhigklmyopqrstbvwxnz";
234     static s_char new_path[512];
235     int ind;
236
237     if (path == (s_char *)0)
238         return (s_char *)0;
239
240     ind = strlen(path);
241     if (ind == 0)
242         return (s_char *)0;
243
244     if (path[ind - 1] == 'h')
245         ind--;
246
247     new_path[ind--] = '\0';
248     new_path[ind] = '\0';
249
250     while (ind >= 0) {
251         new_path[ind--] = patharray[*(path++) - 'a'];
252     }
253
254     return new_path;
255 }