]> git.pond.sub.org Git - empserver/blob - src/lib/commands/new.c
Factor common code out of add() and new() into nat_reset()
[empserver] / src / lib / commands / new.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2008, 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 files README, COPYING and CREDITS in the root of the source
23  *  tree for related information and legal notices.  It is expected
24  *  that future projects/authors will amend these files as needed.
25  *
26  *  ---
27  *
28  *  new.c: Create a new capital for a player
29  * 
30  *  Known contributors to this file:
31  *     Dave Pare, 1986
32  */
33
34 #include <config.h>
35
36 #include <fcntl.h>
37 #include <sys/stat.h>
38 #include <unistd.h>
39 #include "commands.h"
40 #include "land.h"
41 #include "optlist.h"
42 #include "path.h"
43 #include "prototypes.h"
44 #include "tel.h"
45
46 static int isok(int x, int y);
47 static void ok(signed char *map, int x, int y);
48 static void init_sanct(struct natstr *, coord, coord);
49
50 #define MAXAVAIL        300
51
52 int
53 new(void)
54 {
55     struct sctstr sect;
56     struct natstr *natp;
57     natid num;
58     coord x, y;
59     int i;
60     char *p;
61     char buf[1024];
62
63     natp = getnatp(player->cnum);
64     if (natp->nat_xorg != 0 || natp->nat_yorg != 0) {
65         pr("Must be at 0,0 to add a new country\n");
66         return RET_FAIL;
67     }
68     if (!(natp = natargp(player->argp[1], "Country? ")))
69         return RET_SYN;
70     num = natp->nat_cnum;
71     if (natp->nat_stat != STAT_NEW) {
72         pr("Country #%d (%s) isn't a new country!\n", num, cname(num));
73         return RET_SYN;
74     }
75     if (player->argp[2] != 0) {
76         if ((p = getstarg(player->argp[2], "sanctuary pair : ", buf)) == 0)
77             return RET_SYN;
78         if (!sarg_xy(p, &x, &y) || !getsect(x, y, &sect))
79             return RET_SYN;
80         if (sect.sct_type != SCT_RURAL) {
81             pr("%s is a %s; try again...\n",
82                xyas(x, y, player->cnum), dchr[sect.sct_type].d_name);
83             return RET_SYN;
84         }
85         getsect(x + 2, y, &sect);
86         if (sect.sct_type != SCT_RURAL) {
87             pr("%s is a %s; try again...\n",
88                xyas(x + 2, y, player->cnum), dchr[sect.sct_type].d_name);
89             return RET_SYN;
90         }
91     } else {
92         for (i = 0; i < 300 && !player->aborted; i++) {
93             /* Both x and y should be either odd or even */
94             x = (random() % WORLD_X) - (WORLD_X / 2);
95             y = (((random() % WORLD_Y) - (WORLD_Y / 2)) & ~1) | (x & 1);
96             /*
97              * If either of the two potential
98              * sanctuary sectors are already
99              * owned by someone else, pick
100              * another place on the map.
101              */
102             getsect(x, y, &sect);
103             if (sect.sct_type != SCT_RURAL || sect.sct_own != 0)
104                 continue;
105             getsect(x + 2, y, &sect);
106             if (sect.sct_type != SCT_RURAL || sect.sct_own != 0)
107                 continue;
108             if (isok(x, y))
109                 break;
110         }
111         if (i == 300) {
112             pr("couldn't find an empty slot!\n");
113             return RET_FAIL;
114         }
115     }
116
117     if (player->aborted)
118         return RET_FAIL;
119     pr("added country %d at %s\n", num, xyas(x, y, player->cnum));
120     nat_reset(natp, STAT_SANCT, x, y);
121     init_sanct(natp, x, y);
122     init_sanct(natp, x + 2, y);
123     putnat(natp);
124     return RET_OK;
125 }
126
127 static void
128 init_sanct(struct natstr *natp, coord x, coord y)
129 {
130     struct sctstr sect;
131
132     getsect(x, y, &sect);
133     sect.sct_own = natp->nat_cnum;
134     sect.sct_type = SCT_SANCT;
135     sect.sct_newtype = SCT_SANCT;
136     sect.sct_effic = 100;
137     sect.sct_road = 0;
138     sect.sct_rail = 0;
139     sect.sct_defense = 0;
140     sect.sct_mobil = startmob;
141     sect.sct_work = 100;
142     sect.sct_oldown = natp->nat_cnum;
143     if (at_least_one_100) {
144         sect.sct_oil = 100;
145         sect.sct_fertil = 100;
146         sect.sct_uran = 100;
147         sect.sct_min = 100;
148         sect.sct_gmin = 100;
149     }
150     sect.sct_item[I_CIVIL] = max_pop(start_research, &sect);
151     sect.sct_item[I_MILIT] = 55;
152     sect.sct_item[I_FOOD] = opt_NOFOOD ? 0 : 550;
153     sect.sct_item[I_UW] = 75;
154     putsect(&sect);
155 }
156
157 static int nmin, ngold, noil, nur;
158 static int nfree, navail, nowned;
159
160 static int
161 isok(int x, int y)
162 {
163     signed char *map;
164     char *p;
165     char buf[1024];
166
167     nmin = ngold = noil = nur = 0;
168     navail = nfree = nowned = 0;
169     if (!(map = malloc(WORLD_SZ()))) {
170         logerror("malloc failed in isok\n");
171         pr("Memory error.  Tell the deity.\n");
172         return 0;
173     }
174     memset(map, 0, WORLD_SZ());
175     ok(map, x, y);
176     free(map);
177     if (nfree < 5)
178         return 0;
179     pr("Cap at %s; owned sectors: %d, free sectors: %d, avail: %d\n",
180        xyas(x, y, player->cnum), nowned, nfree, navail);
181     pr("min: %d, oil: %d, gold: %d, uranium: %d\n",
182        nmin, noil, ngold, nur);
183     p = getstring("This setup ok? ", buf);
184     if (p == 0 || *p != 'y')
185         return 0;
186     return 1;
187 }
188
189 static void
190 ok(signed char *map, int x, int y)
191 {
192     struct sctstr sect;
193     int dir;
194     int id;
195
196     if (navail > MAXAVAIL)
197         return;
198     id = sctoff(x, y);
199     if (map[id])
200         return;
201     if (!ef_read(EF_SECTOR, id, &sect))
202         return;
203     if (sect.sct_type == SCT_WATER || sect.sct_type == SCT_BSPAN)
204         return;
205     navail++;
206     if (navail >= MAXAVAIL) {
207         pr("At least %d...\n", MAXAVAIL);
208         return;
209     }
210     if (sect.sct_type != SCT_MOUNT && sect.sct_type != SCT_PLAINS) {
211         if (sect.sct_own == 0)
212             nfree++;
213         else
214             nowned++;
215         if (sect.sct_min > 9)
216             nmin++;
217         if (sect.sct_gmin > 9)
218             ngold++;
219         if (sect.sct_uran > 9)
220             nur++;
221         if (sect.sct_oil > 9)
222             noil++;
223     }
224     map[id] = 1;
225     for (dir = DIR_FIRST; dir <= DIR_LAST; dir++)
226         ok(map, diroff[dir][0] + x, diroff[dir][1] + y);
227 }