]> git.pond.sub.org Git - empserver/blob - src/lib/commands/assa.c
9fbd30e2f8ab43600379ec193e9cab797220f7f7
[empserver] / src / lib / commands / assa.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2010, 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  *  assa.c: Hit the beaches!
29  *
30  *  Known contributors to this file:
31  *     Ken Stevens, 1995
32  *     Steve McClure, 1997
33  */
34
35 #include <config.h>
36
37 #include "combat.h"
38 #include "commands.h"
39 #include "mission.h"
40 #include "path.h"
41 #include "empobj.h"
42 #include "unit.h"
43
44 int
45 assa(void)
46 {
47     struct combat off[1];       /* assaulting ship */
48     struct combat def[1];       /* defending sector */
49     int fort_sup, ship_sup, land_sup, plane_sup;
50     struct emp_qelem olist;     /* assaulting units */
51     struct emp_qelem dlist;     /* defending units */
52     int ototal;                 /* total assaulting strength */
53     int a_engineer = 0;         /* assaulter engineers are present */
54     int a_spy = 0;              /* the best assaulter scout */
55     double osupport = 1.0;      /* assault support */
56     double dsupport = 1.0;      /* defense support */
57     char *p;
58     char buf[1024];
59     int n;
60     int ourtotal;
61     struct emp_qelem *qp, *next;
62     struct ulist *llp;
63     int rel;
64
65     att_combat_init(off, EF_SHIP);
66     att_combat_init(def, EF_SECTOR);
67     /*
68      * Collect input from the assaulter
69      */
70
71     /* What are we assaulting? */
72
73     if (!(p = getstarg(player->argp[1], "Sector :  ", buf)))
74         return RET_SYN;
75     if (!sarg_xy(p, &def->x, &def->y))
76         return RET_SYN;
77     if (att_abort(A_ASSAULT, NULL, def))
78         return RET_FAIL;
79
80     /*
81      * Ask the assaulter what he wants to assault with
82      */
83
84     if ((off->shp_uid =
85          onearg(player->argp[2], "Assault from ship # ")) < 0) {
86         pr("You may only assault from one ship!\n");
87         return RET_FAIL;
88     }
89     if (att_abort(A_ASSAULT, off, def)) {
90         pr("Assault aborted\n");
91         return RET_OK;
92     }
93
94     /* Show what we're assaulting, and check treaties */
95
96     if (att_show(def))
97         return RET_FAIL;
98
99     /* Ask about offensive support */
100
101     att_ask_support(3, &fort_sup, &ship_sup, &land_sup, &plane_sup);
102     if (att_abort(A_ASSAULT, off, def)) {
103         att_empty_attack(A_ASSAULT, 0, def);
104         return RET_OK;
105     }
106
107     /* Ask the player what he wants to assault with */
108
109     att_ask_offense(A_ASSAULT, off, def, &olist, &a_spy, &a_engineer);
110     if (att_abort(A_ASSAULT, off, def)) {
111         pr("Assault aborted\n");
112         att_empty_attack(A_ASSAULT, 0, def);
113         return att_free_lists(&olist, NULL);
114     }
115
116     /* If we're assaulting our own sector, end here */
117     if (def->own == player->cnum) {
118         if (off->troops)
119             pr("You reinforce %s with %d troops\n",
120                xyas(def->x, def->y, player->cnum), off->troops);
121         if (off->troops || !QEMPTY(&olist))
122             att_move_in_off(A_ASSAULT, off, &olist, def);
123         return RET_OK;
124     }
125
126     ototal = att_get_offense(A_ASSAULT, off, &olist, def);
127     if (att_abort(A_ASSAULT, off, def)) {
128         pr("Assault aborted\n");
129         att_empty_attack(A_ASSAULT, 0, def);
130         return att_free_lists(&olist, NULL);
131     }
132
133     /*
134      * We have now got all the answers from the assaulter.  From this point
135      * forward, we can assume that this battle is the _only_ thing
136      * happening in the game.
137      */
138
139     /* First, we check to see if the only thing we have are spies
140      * assaulting.  If so, we try to sneak them on land.  If they
141      * make it, the defenders don't see a thing.  If they fail, well,
142      * the spies die, and the defenders see them. */
143
144     ourtotal = 0;
145     for (n = 0; n <= off->last; n++) {
146         if (off[n].type == EF_BAD)
147             continue;
148         ourtotal += off[n].troops * att_combat_eff(off + n);
149     }
150     for (qp = olist.q_forw; qp != &olist; qp = next) {
151         next = qp->q_forw;
152         llp = (struct ulist *)qp;
153         if (lchr[(int)llp->unit.land.lnd_type].l_flags & L_SPY)
154             continue;
155         ourtotal++;
156     }
157
158     /* If no attacking forces (i.e. we got here with only spies)
159      * then try to sneak on-land. */
160
161     if (!ourtotal) {
162         pr("Trying to sneak on shore...\n");
163
164         for (qp = olist.q_forw; qp != &olist; qp = next) {
165             next = qp->q_forw;
166             llp = (struct ulist *)qp;
167             rel = getrel(getnatp(def->own), player->cnum);
168             if (chance(0.10) || rel == ALLIED || !def->own) {
169                 pr("%s made it on shore safely.\n", prland(&llp->unit.land));
170                 llp->unit.land.lnd_x = def->x;
171                 llp->unit.land.lnd_y = def->y;
172                 llp->unit.land.lnd_ship = -1;
173                 putland(llp->unit.land.lnd_uid, &llp->unit.land);
174             } else {
175                 pr("%s was spotted", prland(&llp->unit.land));
176                 if (rel <= HOSTILE) {
177                     wu(0, def->own, "%s spy shot and killed in %s.\n",
178                        cname(player->cnum), xyas(def->x, def->y,
179                                                  def->own));
180                     pr(" and was killed in the attempt.\n");
181                     llp->unit.land.lnd_effic = 0;
182                     putland(llp->unit.land.lnd_uid, &llp->unit.land);
183                     lnd_delete(llp);
184                 } else {
185                     wu(0, def->own, "%s spy spotted in %s.\n",
186                        cname(player->cnum), xyas(def->x, def->y,
187                                                  def->own));
188                     pr(" but made it ok.\n");
189                     llp->unit.land.lnd_x = def->x;
190                     llp->unit.land.lnd_y = def->y;
191                     llp->unit.land.lnd_ship = -1;
192                     putland(llp->unit.land.lnd_uid, &llp->unit.land);
193                 }
194             }
195         }
196         return RET_OK;
197     }
198
199     /* Get the real defense */
200
201     att_get_defense(&olist, def, &dlist, a_spy, ototal);
202
203     /* Get assaulter and defender support */
204
205     att_get_support(A_ASSAULT, fort_sup, ship_sup, land_sup, plane_sup,
206                     &olist, off, &dlist, def, &osupport, &dsupport,
207                     a_engineer);
208     if (att_abort(A_ASSAULT, off, def)) {
209         pr("Assault aborted\n");
210         att_empty_attack(A_ASSAULT, 0, def);
211         return att_free_lists(&olist, &dlist);
212     }
213
214     /*
215      * Death, carnage, and destruction.
216      */
217
218     att_fight(A_ASSAULT, off, &olist, osupport, def, &dlist, dsupport);
219
220     return RET_OK;
221 }