Full ANSIfication with prototypes.
[vms-empire.git] / attack.c
1 /*
2  *    Copyright (C) 1987, 1988 Chuck Simmons
3  * 
4  * See the file COPYING, distributed with empire, for restriction
5  * and warranty information.
6  */
7
8 /*
9 attack.c -- handle an attack between two pieces.  We do everything from
10 fighting it out between the pieces to notifying the user who won and
11 killing off the losing object.  Somewhere far above, our caller is
12 responsible for actually removing the object from its list and actually
13 updating the player's view of the world.
14
15 Find object being attacked.  If it is a city, attacker has 50% chance
16 of taking city.  If successful, give city to attacker.  Otherwise
17 kill attacking piece.  Tell user who won.
18
19 If attacking object is not a city, loop.  On each iteration, select one
20 piece to throw a blow.  Damage the opponent by the strength of the blow
21 thrower.  Stop looping when one object has 0 or fewer hits.  Kill off 
22 the dead object.  Tell user who won and how many hits her piece has left,
23 if any.
24 */
25
26 #include "empire.h"
27 #include "extern.h"
28
29 void
30 attack_city(piece_info_t *att_obj, loc_t loc)
31 {
32         city_info_t *cityp;
33         int att_owner, city_owner;
34
35         cityp = find_city (loc);
36         ASSERT (cityp);
37         
38         att_owner = att_obj->owner;
39         city_owner = cityp->owner;
40
41         if (irand (2) == 0) { /* attack fails? */
42                 if (att_owner == USER) {
43                         comment ("The scum defending the city crushed your attacking blitzkrieger.",0,0,0,0,0,0,0,0);
44                         ksend ("The scum defending the city crushed your attacking blitzkrieger.\n",0,0,0,0,0,0,0,0); //kermyt
45                 }
46                 else if (city_owner == USER) {
47                         ksend ("Your city at %d is under attack.\n",loc_disp(cityp->loc),0,0,0,0,0,0,0); //kermyt
48                         comment ("Your city at %d is under attack.",loc_disp(cityp->loc),0,0,0,0,0,0,0);
49                 }
50                 kill_obj (att_obj, loc);
51         }
52         else { /* attack succeeded */
53                 kill_city (cityp);
54                 cityp->owner = att_owner;
55                 kill_obj (att_obj, loc);
56
57                 if (att_owner == USER) {
58                         ksend ("City at %d has been subjugated!\n",loc_disp(cityp->loc),0,0,0,0,0,0,0); //kermyt
59                         error ("City at %d has been subjugated!",loc_disp(cityp->loc),0,0,0,0,0,0,0);
60
61                         extra ("Your army has been dispersed to enforce control.",0,0,0,0,0,0,0,0);
62                         ksend ("Your army has been dispersed to enforce control.\n",0,0,0,0,0,0,0,0);
63                         set_prod (cityp);
64                 }
65                 else if (city_owner == USER) {
66                         ksend("City at %d has been lost to the enemy!\n",loc_disp(cityp->loc),0,0,0,0,0,0,0); //kermyt
67                         comment ("City at %d has been lost to the enemy!",loc_disp(cityp->loc),0,0,0,0,0,0,0);
68                 }
69         }
70         /* let city owner see all results */
71         if (city_owner != UNOWNED) scan (MAP(city_owner), loc);
72 }
73
74 /*
75 Attack a piece other than a city.  The piece could be anyone's.
76 First we have to figure out what is being attacked.
77 */
78
79 void
80 attack_obj(piece_info_t *att_obj, loc_t loc)
81 {
82         void describe(), survive();
83         
84         piece_info_t *def_obj; /* defender */
85         int owner;
86
87         def_obj = find_obj_at_loc (loc);
88         ASSERT (def_obj != NULL); /* can't find object to attack? */
89         
90         if (def_obj->type == SATELLITE) return; /* can't attack a satellite */
91
92         while (att_obj->hits > 0 && def_obj->hits > 0) {
93                 if (irand (2) == 0) /* defender hits? */
94                      att_obj->hits -= piece_attr[def_obj->type].strength;
95                 else def_obj->hits -= piece_attr[att_obj->type].strength;
96         }
97
98         if (att_obj->hits > 0) { /* attacker won? */
99                 describe (att_obj, def_obj, loc);
100                 owner = def_obj->owner;
101                 kill_obj (def_obj, loc); /* kill loser */
102                 survive (att_obj, loc); /* move attacker */
103         }
104         else { /* defender won */
105                 describe (def_obj, att_obj, loc);
106                 owner = att_obj->owner;
107                 kill_obj (att_obj, loc);
108                 survive (def_obj, loc);
109         }
110         /* show results to first killed */
111         scan (MAP(owner), loc);
112 }
113
114 void
115 attack(piece_info_t *att_obj, loc_t loc)
116 {
117         if (map[loc].contents == '*') /* attacking a city? */
118                 attack_city (att_obj, loc);
119         else attack_obj (att_obj, loc); /* attacking a piece */
120 }
121
122 /*
123 Here we look to see if any cargo was killed in the attack.  If
124 a ships contents exceeds its capacity, some of the survivors
125 fall overboard and drown.  We also move the survivor to the given
126 location.
127 */
128
129 void
130 survive(piece_info_t *obj, loc_t loc)
131 {
132         while (obj_capacity (obj) < obj->count)
133                 kill_obj (obj->cargo, loc);
134                 
135         move_obj (obj, loc);
136 }
137
138 void
139 describe(piece_info_t *win_obj, piece_info_t *lose_obj, loc_t loc)
140 {
141         char buf[STRSIZE];
142         char buf2[STRSIZE];
143         int diff;
144         
145         *buf = '\0';
146         *buf2 = '\0';
147         
148         if (win_obj->owner != lose_obj->owner) {
149                 if (win_obj->owner == USER) {
150                         user_score += piece_attr[lose_obj->type].build_time; 
151                         ksend1 ("Enemy %s at %d destroyed.\n",piece_attr[lose_obj->type].name,loc_disp(loc),0,0,0,0,0,0); //kermyt
152                         topmsg1 (1, "Enemy %s at %d destroyed.",piece_attr[lose_obj->type].name,loc_disp(loc),0,0,0,0,0,0);
153                         ksend1 ("Your %s has %d hits left\n",piece_attr[win_obj->type].name,win_obj->hits,0,0,0,0,0,0); //kermyt
154                         topmsg1 (2, "Your %s has %d hits left.", piece_attr[win_obj->type].name, win_obj->hits,0,0,0,0,0,0);
155                                 
156                         diff = win_obj->count - obj_capacity (win_obj);
157                         if (diff > 0) switch (win_obj->cargo->type) {
158                         case ARMY:
159                                 ksend("%d armies fell overboard and drowned in the assault.\n",diff,0,0,0,0,0,0,0); //kermyt
160                              topmsg (3,"%d armies fell overboard and drowned in the assault.",diff,0,0,0,0,0,0,0);
161                              break;
162                         case FIGHTER:
163                                 ksend("%d fighters fell overboard and were lost in the assult.\n",diff,0,0,0,0,0,0,0); //kermyt
164                              topmsg (3,"%d fighters fell overboard and were lost in the assault.",diff,0,0,0,0,0,0,0);
165                              break;
166                         }
167                 }
168                 else {
169                         comp_score += piece_attr[lose_obj->type].build_time;
170                         ksend1 ("Your %s at %d destroyed.\n",piece_attr[lose_obj->type].name,loc_disp(loc),0,0,0,0,0,0); //kermyt
171                         topmsg1 (3, "Your %s at %d destroyed.",piece_attr[lose_obj->type].name,loc_disp(loc),0,0,0,0,0,0);
172                 }
173                 set_need_delay ();
174         }
175 }