src/lib/update/finish.c

Go to the documentation of this file.
00001 /*
00002  *  Empire - A multi-player, client/server Internet based war game.
00003  *  Copyright (C) 1986-2007, Dave Pare, Jeff Bailey, Thomas Ruschak,
00004  *                           Ken Stevens, Steve McClure
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  *  ---
00021  *
00022  *  See files README, COPYING and CREDITS in the root of the source
00023  *  tree for related information and legal notices.  It is expected
00024  *  that future projects/authors will amend these files as needed.
00025  *
00026  *  ---
00027  *
00028  *  finish.c: Finish the update
00029  * 
00030  *  Known contributors to this file:
00031  *     Dave Pare, 1986
00032  *     Thomas Ruschak, 1993
00033  *     Steve McClure, 1998
00034  */
00035 
00036 #include <config.h>
00037 
00038 #include "distribute.h"
00039 #include "path.h"
00040 #include "update.h"
00041 #include <stdlib.h>
00042 
00043 /* Used for building up distribution info */
00044 struct distinfo {
00045     char *path;                 /* path to take */
00046     double imcost;              /* import cost */
00047     double excost;              /* export cost */
00048 };
00049 
00050 /* This is our global buffer of distribution pointers.  Note that
00051  * We only malloc this once, and never again (until reboot time
00052  * of course :) ) We do clear it each and every time. */
00053 static struct distinfo *g_distptrs;
00054 
00055 /* Note that even though we malloc and save the path, it is never
00056  * used.  Thus, this option.  If you want to malloc and save every
00057  * path and then free when done, just enable this.  Or, if the
00058  * dodistribute ever uses the path for something other than checking
00059  * to see that a path exists, enable this */
00060 /* #define SAVE_FINISH_PATHS */
00061 
00062 #ifndef SAVE_FINISH_PATHS
00063 static char *finish_path = "h"; /* Placeholder indicating path exists */
00064 #endif /* SAVE_FINISH_PATHS */
00065 
00066 static void assemble_dist_paths(struct distinfo *distptrs);
00067 static char *ReversePath(char *path);
00068 
00069 void
00070 finish_sects(int etu)
00071 {
00072     struct sctstr *sp;
00073     struct natstr *np;
00074     int n;
00075     struct distinfo *infptr;
00076 
00077     if (g_distptrs == NULL) {
00078         logerror("First update since reboot, allocating buffer\n");
00079         /* Allocate the information buffer */
00080         g_distptrs = malloc(WORLD_SZ() * sizeof(*g_distptrs));
00081         if (g_distptrs == NULL) {
00082             logerror("malloc failed in finish_sects.\n");
00083             return;
00084         }
00085     }
00086 
00087     /* Wipe it clean */
00088     memset(g_distptrs, 0, WORLD_SZ() * sizeof(*g_distptrs));
00089 
00090     logerror("delivering...\n");
00091     /* Do deliveries */
00092     for (n = 0; NULL != (sp = getsectid(n)); n++) {
00093         if (sp->sct_type == SCT_WATER)
00094             continue;
00095         if (sp->sct_own == 0)
00096             continue;
00097         np = getnatp(sp->sct_own);
00098         if (np->nat_money < 0)
00099             continue;
00100         dodeliver(sp);
00101     }
00102     logerror("done delivering\n");
00103 
00104     logerror("assembling paths...\n");
00105 
00106     /* First, enable the best_path cacheing */
00107     bp_enable_cachepath();
00108 
00109     /* Now assemble the paths */
00110     assemble_dist_paths(g_distptrs);
00111 
00112     /* Now disable the best_path cacheing */
00113     bp_disable_cachepath();
00114 
00115     /* Now, clear the best_path cache that may have been created */
00116     bp_clear_cachepath();
00117 
00118     logerror("done assembling paths\n");
00119 
00120     logerror("exporting...");
00121     for (n = 0; NULL != (sp = getsectid(n)); n++) {
00122         if (sp->sct_type == SCT_WATER || sp->sct_own == 0)
00123             continue;
00124         np = getnatp(sp->sct_own);
00125         if (np->nat_money < 0)
00126             continue;
00127         /* Get the pointer */
00128         infptr = &g_distptrs[XYOFFSET(sp->sct_x, sp->sct_y)];
00129         dodistribute(sp, EXPORT,
00130                      infptr->path, infptr->imcost, infptr->excost);
00131     }
00132     logerror("done exporting\n");
00133 
00134     /* Note that we free the paths (if allocated) as we loop here */
00135     logerror("importing...");
00136     for (n = 0; NULL != (sp = getsectid(n)); n++) {
00137         /* Get the pointer (we do it first so we can free if needed) */
00138         infptr = &g_distptrs[XYOFFSET(sp->sct_x, sp->sct_y)];
00139         if (sp->sct_type == SCT_WATER || sp->sct_own == 0) {
00140 #ifdef SAVE_FINISH_PATHS
00141             if (infptr->path)
00142                 free(infptr->path);
00143 #endif /* SAVE_FINISH_PATHS */
00144             continue;
00145         }
00146         np = getnatp(sp->sct_own);
00147         if (np->nat_money < 0) {
00148 #ifdef SAVE_FINISH_PATHS
00149             if (infptr->path)
00150                 free(infptr->path);
00151 #endif /* SAVE_FINISH_PATHS */
00152             continue;
00153         }
00154         dodistribute(sp, IMPORT,
00155                      infptr->path, infptr->imcost, infptr->excost);
00156 #ifdef SAVE_FINISH_PATHS
00157         if (infptr->path)
00158             free(infptr->path);
00159 #endif /* SAVE_FINISH_PATHS */
00160 
00161         sp->sct_off = 0;
00162     }
00163     logerror("done importing\n");
00164 
00165 }
00166 
00167 static void
00168 assemble_dist_paths(struct distinfo *distptrs)
00169 {
00170     char *path, *p;
00171     double d;
00172     struct sctstr *sp;
00173     struct sctstr *dist;
00174     struct distinfo *infptr;
00175     int n;
00176     char buf[512];
00177 
00178     for (n = 0; NULL != (sp = getsectid(n)); n++) {
00179         if ((sp->sct_dist_x == sp->sct_x) && (sp->sct_dist_y == sp->sct_y))
00180             continue;
00181         /* Set the pointer */
00182         infptr = &distptrs[XYOFFSET(sp->sct_x, sp->sct_y)];
00183         /* now, get the dist sector */
00184         dist = getsectp(sp->sct_dist_x, sp->sct_dist_y);
00185         if (dist == NULL) {
00186             logerror("Bad dist sect %d,%d for %d,%d !\n",
00187                      sp->sct_dist_x, sp->sct_dist_y,
00188                      sp->sct_x, sp->sct_y);
00189             continue;
00190         }
00191         /* Now, get the best distribution path over roads */
00192         /* Note we go from the dist center to the sector.  This gives
00193            us the import path for that sector. */
00194         path = BestDistPath(buf, dist, sp, &d);
00195 
00196         /* Now, we have a path */
00197         if (path != NULL) {
00198 #ifdef SAVE_FINISH_PATHS
00199             int len;
00200             /* Here we malloc a buffer and save it */
00201             len = strlen(path);
00202             infptr->path = malloc(len);
00203             if (infptr->path == NULL) {
00204                 logerror("malloc failed in assemble_dist_path!\n");
00205                 return;
00206             }
00207 #endif /* SAVE_FINISH_PATHS */
00208             /* Save the import cost */
00209             infptr->imcost = d;
00210             /* Now, reverse the path */
00211             p = ReversePath(path);
00212             /* And walk the path back to the dist center to get the export
00213                cost */
00214             infptr->excost = pathcost(sp, p, MOB_MOVE);
00215 #ifdef SAVE_FINISH_PATHS
00216             memcpy(infptr->path, p, len);
00217 #else
00218             infptr->path = finish_path;
00219 #endif /* SAVE_FINISH_PATHS */
00220         }
00221     }
00222 }
00223 
00224 static char *
00225 ReversePath(char *path)
00226 {
00227     char *patharray = "aucdefjhigklmyopqrstbvwxnz";
00228     static char new_path[512];
00229     int ind;
00230 
00231     if (path == NULL)
00232         return NULL;
00233 
00234     ind = strlen(path);
00235     if (ind == 0)
00236         return NULL;
00237 
00238     if (path[ind - 1] == 'h')
00239         ind--;
00240 
00241     new_path[ind--] = '\0';
00242     new_path[ind] = '\0';
00243 
00244     while (ind >= 0) {
00245         new_path[ind--] = patharray[*(path++) - 'a'];
00246     }
00247 
00248     return new_path;
00249 }

Generated on Fri Mar 28 11:01:16 2008 for empserver by  doxygen 1.5.2