src/lib/subs/move.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  *  move.c: Move something somewhere.
00029  * 
00030  *  Known contributors to this file:
00031  *     
00032  */
00033 
00034 #include <config.h>
00035 
00036 #include <ctype.h>
00037 #include "damage.h"
00038 #include "file.h"
00039 #include "map.h"
00040 #include "path.h"
00041 #include "player.h"
00042 #include "prototypes.h"
00043 #include "sect.h"
00044 
00045 static int move_map(coord curx, coord cury, char *arg);
00046 
00047 int
00048 move_ground(struct sctstr *start, struct sctstr *end,
00049             double weight, char *path,
00050             int (*map)(coord, coord, char *), int exploring,
00051             int *dam)
00052 {
00053     struct sctstr sect, ending_sect;
00054     struct sctstr next, dsect;
00055     coord curx, cury, oldx, oldy;
00056     coord tmpx, tmpy;
00057     coord dx, dy;
00058     char *movstr;
00059     double sect_mcost;
00060     double total_mcost;
00061     double mv_cost;
00062     double mobility = start->sct_mobil;
00063     int dir;
00064     int intcost;
00065     int takedam = *dam;
00066     int out = 0;
00067     char bpath[512];
00068     char buf2[512];
00069     char prompt[128];
00070     char buf[1024];
00071 
00072     *end = *start;
00073     if (mobility <= 0.0)
00074         return -1;
00075     *dam = 0;
00076     if (path && sarg_xy(path, &dx, &dy) && getsect(dx, dy, &ending_sect)) {
00077         if ((ending_sect.sct_x == start->sct_x) &&
00078             (ending_sect.sct_y == start->sct_y)) {
00079             pr("Start sector is ending sector!\n");
00080             return -1;
00081         }
00082         pr("Looking for best path to %s\n", path);
00083         path = BestLandPath(buf2, start, &ending_sect, &total_mcost,
00084                             MOB_MOVE);
00085         if (exploring && path)  /* take off the 'h' */
00086             path[strlen(path) - 1] = '\0';
00087         if (!path)
00088             pr("No owned path exists!\n");
00089         else {
00090             pr("Using best path '%s', movement cost %1.3f\n",
00091                path, total_mcost);
00092             strncpy(bpath, path, sizeof(bpath));
00093             path = bpath;
00094         }
00095         if ((total_mcost * weight) > mobility) {
00096             pr("Not enough mobility to go all the way. Nothing moved.\n");
00097             return -1;
00098         }
00099     }
00100     movstr = path;
00101     curx = start->sct_x;
00102     cury = start->sct_y;
00103     total_mcost = 0.0;
00104     if (getsect(curx, cury, &sect) < 0) {
00105         logerror("move_path: getsect %d,%d", curx, cury);
00106         return -1;
00107     }
00108     for (;;) {
00109         oldx = curx;
00110         oldy = cury;
00111         if (!movstr || *movstr == 0) {
00112             if (exploring) {
00113                 map(curx, cury, NULL);
00114             } else {
00115                 move_map(curx, cury, NULL);
00116             }
00117             sprintf(prompt, "<%.1f: %c %s> ", mobility,
00118                     dchr[sect.sct_type].d_mnem,
00119                     xyas(sect.sct_x, sect.sct_y, player->cnum));
00120             movstr = getstring(prompt, buf);
00121         }
00122         if (movstr && sarg_xy(movstr, &dx, &dy)) {
00123             if (getsect(dx, dy, &dsect)) {
00124                 movstr = BestLandPath(buf2, &sect, &dsect, &mv_cost,
00125                                       MOB_MOVE);
00126             } else {
00127                 pr("Invalid destination sector!\n");
00128                 movstr = NULL;
00129             }
00130 
00131             if (movstr == NULL) {
00132                 pr("Can't get to %s from here!\n",
00133                    xyas(dx, dy, player->cnum));
00134             } else {
00135                 if ((mv_cost * weight) > mobility) {
00136                     pr("Not enough mobility to go all the way. Nothing moved.\n");
00137                     movstr = NULL;
00138                 } else {
00139                     pr("Using best path '%s', movement cost %1.3f\n",
00140                        movstr, mv_cost);
00141                     strncpy(bpath, movstr, sizeof(bpath));
00142                     movstr = bpath;
00143                 }
00144             }
00145         }
00146         if (!movstr || *movstr == 0) {
00147             buf2[0] = dirch[DIR_STOP];
00148             buf2[1] = 0;
00149             movstr = buf2;
00150         }
00151         if ((dir = chkdir(*movstr, DIR_STOP, DIR_MAP)) < 0) {
00152             pr("\"%c\" is not legal...", *movstr);
00153             direrr("'%c' to stop ", "'%c' to view ", "& '%c' to map\n");
00154             *movstr = 0;
00155             continue;
00156         }
00157         do  movstr++; while (isspace(*movstr));
00158         if (dir == DIR_MAP) {
00159             if (!exploring)
00160                 map(curx, cury, movstr);
00161             *movstr = 0;
00162             continue;
00163         } else if (dir == DIR_STOP)
00164             break;
00165         else if (dir == DIR_VIEW) {
00166             pr("%d%% %s with %d civilians.\n", sect.sct_effic,
00167                dchr[sect.sct_type].d_name, sect.sct_item[I_CIVIL]);
00168             continue;
00169         }
00170         /*
00171          * now see if we can move into the
00172          * next sector.  Mobility, terrain,
00173          * or ownership may prevent us.
00174          */
00175         tmpx = curx + diroff[dir][0];
00176         tmpy = cury + diroff[dir][1];
00177         if (getsect(tmpx, tmpy, &next) < 0) {
00178             pr("You can't go there...\n");
00179             *movstr = 0;
00180             continue;
00181         }
00182         if (!player->god) {
00183             if ((next.sct_type == SCT_SANCT) &&
00184                 (next.sct_own != player->cnum)) {
00185                 pr("Converts, huh?\n");
00186                 *movstr = 0;
00187                 continue;
00188             }
00189             sect_mcost = sector_mcost(&next, MOB_MOVE);
00190             if ((!player->owner && (!exploring
00191                                     || next.sct_item[I_MILIT]
00192                                     || next.sct_item[I_CIVIL]))
00193                 || sect_mcost == -1.0) {
00194                 /* already-owned, or prohibited terrain */
00195                 pr("You can't go there...\n");
00196                 *movstr = 0;
00197                 continue;
00198             }
00199             sect_mcost *= weight;
00200             if (sect_mcost > mobility) {
00201                 pr("Not enough mobility.  ");
00202                 pr("You can't go there...\n");
00203                 *movstr = 0;
00204                 continue;
00205             }
00206             mobility -= sect_mcost;
00207             total_mcost += sect_mcost;
00208         }
00209         curx = tmpx;
00210         cury = tmpy;
00211         if (cury != start->sct_y)
00212             out = 1;
00213         if (curx != start->sct_x)
00214             out = 1;
00215 
00216         sect = next;
00217 
00218         if (takedam)
00219             *dam += check_lmines(sect.sct_x, sect.sct_y, weight);
00220         if (*dam >= 100)
00221             break;
00222         /*
00223          * Check and see if anyone will interdict us
00224          */
00225         if (takedam && chance(weight / 100.0) &&
00226             ((curx != oldx) || (cury != oldy)))
00227             *dam += ground_interdict(curx, cury, player->cnum,
00228                                      "commodities");
00229         if (*dam >= 100)
00230             break;
00231     }
00232     *end = sect;
00233     intcost = (int)total_mcost;
00234     if (intcost < 0)
00235         return -1;
00236     if ((start->sct_x == end->sct_x) && (start->sct_y == end->sct_y)
00237         && !out)
00238         return -1;
00239 
00240     if (chance(total_mcost - intcost))
00241         intcost++;
00242     return intcost;
00243 }
00244 
00245 
00246 /*ARGSUSED*/
00247 static int
00248 move_map(coord curx, coord cury, char *arg)
00249 {
00250     struct nstr_sect ns;
00251     struct sctstr sect;
00252     char view[7];
00253     int i;
00254     int changed = 0;
00255 
00256     snxtsct_dist(&ns, curx, cury, 1);
00257     i = 0;
00258     while (i < 7 && nxtsct(&ns, &sect)) {
00259         /* Nasty: this relies on the iteration order */
00260         view[i] = dchr[sect.sct_type].d_mnem;
00261         switch (sect.sct_type) {
00262         case SCT_WATER:
00263         case SCT_RURAL:
00264         case SCT_MOUNT:
00265         case SCT_WASTE:
00266         case SCT_PLAINS:
00267             break;
00268         default:
00269             if (sect.sct_own != player->cnum && !player->god)
00270                 view[i] = '?';
00271             break;
00272         }
00273         changed += map_set(player->cnum, ns.x, ns.y, view[i], 0);
00274         i++;
00275     }
00276     if (changed)
00277         writemap(player->cnum);
00278     if (!getsect(curx, cury, &sect))
00279         return RET_FAIL;
00280     pr("    %c %c      eff   mob   civ  mil   uw food  work  avail\n",
00281        view[0], view[1]);
00282     pr("   %c %c %c     %3d   %3d  %4d %4d %4d %4d   %3d   %3d\n",
00283        view[2], view[3], view[4],
00284        sect.sct_effic, sect.sct_mobil,
00285        sect.sct_item[I_CIVIL], sect.sct_item[I_MILIT], sect.sct_item[I_UW],
00286        sect.sct_item[I_FOOD], sect.sct_work, sect.sct_avail);
00287     pr("    %c %c\n", view[5], view[6]);
00288     return RET_OK;
00289 }
00290 
00291 int
00292 fly_map(coord curx, coord cury)
00293 {
00294     struct nstr_sect ns;
00295     struct sctstr sect;
00296     char view[7];
00297     int i;
00298 
00299     snxtsct_dist(&ns, curx, cury, 1);
00300     i = 0;
00301     while (i < 7 && nxtsct(&ns, &sect)) {
00302         /* Nasty: this relies on the iteration order */
00303         if (!(view[i] = player->bmap[sctoff(ns.x, ns.y)]))
00304             view[i] = ' ';
00305         i++;
00306     }
00307 
00308     pr("    %c %c\n", view[0], view[1]);
00309     pr("   %c %c %c\n", view[2], view[3], view[4]);
00310     pr("    %c %c\n", view[5], view[6]);
00311     return RET_OK;
00312 }
00313 
00314 int
00315 check_lmines(coord x, coord y, double weight)
00316 {
00317     struct sctstr sect;
00318     int dam = 0;
00319 
00320     getsect(x, y, &sect);
00321     if (sect.sct_mines > 0 &&
00322         sect.sct_oldown != player->cnum &&
00323         chance(DMINE_LHITCHANCE(sect.sct_mines)) && chance(weight / 100.0)) {
00324         pr_beep();
00325         pr("Blammo! Landmines detected! in %s  ",
00326            xyas(sect.sct_x, sect.sct_y, player->cnum));
00327         dam = roll(20);
00328         --sect.sct_mines;
00329         putsect(&sect);
00330         pr("%d damage sustained.\n", dam);
00331     }
00332     return dam;
00333 }

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