Wow. SCCS cookies! There's a blast from the past.
[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 (att_obj, loc)
31 piece_info_t *att_obj;
32 long loc;
33 {
34         city_info_t *cityp;
35         int att_owner, city_owner;
36
37         cityp = find_city (loc);
38         ASSERT (cityp);
39         
40         att_owner = att_obj->owner;
41         city_owner = cityp->owner;
42
43         if (irand (2) == 0) { /* attack fails? */
44                 if (att_owner == USER) {
45                         comment ("The scum defending the city crushed your attacking blitzkrieger.",0,0,0,0,0,0,0,0);
46                         ksend ("The scum defending the city crushed your attacking blitzkrieger.\n",0,0,0,0,0,0,0,0); //kermyt
47                 }
48                 else if (city_owner == USER) {
49                         ksend ("Your city at %d is under attack.\n",loc_disp(cityp->loc),0,0,0,0,0,0,0); //kermyt
50                         comment ("Your city at %d is under attack.",loc_disp(cityp->loc),0,0,0,0,0,0,0);
51                 }
52                 kill_obj (att_obj, loc);
53         }
54         else { /* attack succeeded */
55                 kill_city (cityp);
56                 cityp->owner = att_owner;
57                 kill_obj (att_obj, loc);
58
59                 if (att_owner == USER) {
60                         ksend ("City at %d has been subjugated!\n",loc_disp(cityp->loc),0,0,0,0,0,0,0); //kermyt
61                         error ("City at %d has been subjugated!",loc_disp(cityp->loc),0,0,0,0,0,0,0);
62
63                         extra ("Your army has been dispersed to enforce control.",0,0,0,0,0,0,0,0);
64                         ksend ("Your army has been dispersed to enforce control.\n",0,0,0,0,0,0,0,0);
65                         set_prod (cityp);
66                 }
67                 else if (city_owner == USER) {
68                         ksend("City at %d has been lost to the enemy!\n",loc_disp(cityp->loc),0,0,0,0,0,0,0); //kermyt
69                         comment ("City at %d has been lost to the enemy!",loc_disp(cityp->loc),0,0,0,0,0,0,0);
70                 }
71         }
72         /* let city owner see all results */
73         if (city_owner != UNOWNED) scan (MAP(city_owner), loc);
74 }
75
76 /*
77 Attack a piece other than a city.  The piece could be anyone's.
78 First we have to figure out what is being attacked.
79 */
80
81 void
82 attack_obj (att_obj, loc)
83 piece_info_t *att_obj;
84 long loc;
85 {
86         void describe(), survive();
87         
88         piece_info_t *def_obj; /* defender */
89         int owner;
90
91         def_obj = find_obj_at_loc (loc);
92         ASSERT (def_obj != NULL); /* can't find object to attack? */
93         
94         if (def_obj->type == SATELLITE) return; /* can't attack a satellite */
95
96         while (att_obj->hits > 0 && def_obj->hits > 0) {
97                 if (irand (2) == 0) /* defender hits? */
98                      att_obj->hits -= piece_attr[def_obj->type].strength;
99                 else def_obj->hits -= piece_attr[att_obj->type].strength;
100         }
101
102         if (att_obj->hits > 0) { /* attacker won? */
103                 describe (att_obj, def_obj, loc);
104                 owner = def_obj->owner;
105                 kill_obj (def_obj, loc); /* kill loser */
106                 survive (att_obj, loc); /* move attacker */
107         }
108         else { /* defender won */
109                 describe (def_obj, att_obj, loc);
110                 owner = att_obj->owner;
111                 kill_obj (att_obj, loc);
112                 survive (def_obj, loc);
113         }
114         /* show results to first killed */
115         scan (MAP(owner), loc);
116 }
117
118 void
119 attack (att_obj, loc)
120 piece_info_t *att_obj;
121 long loc;
122 {
123         if (map[loc].contents == '*') /* attacking a city? */
124                 attack_city (att_obj, loc);
125         else attack_obj (att_obj, loc); /* attacking a piece */
126 }
127
128 /*
129 Here we look to see if any cargo was killed in the attack.  If
130 a ships contents exceeds its capacity, some of the survivors
131 fall overboard and drown.  We also move the survivor to the given
132 location.
133 */
134
135 void
136 survive (obj, loc)
137 piece_info_t *obj;
138 long loc;
139 {
140         while (obj_capacity (obj) < obj->count)
141                 kill_obj (obj->cargo, loc);
142                 
143         move_obj (obj, loc);
144 }
145
146 void
147 describe (win_obj, lose_obj, loc)
148 piece_info_t *win_obj, *lose_obj;
149 long loc;
150 {
151         char buf[STRSIZE];
152         char buf2[STRSIZE];
153         int diff;
154         
155         *buf = '\0';
156         *buf2 = '\0';
157         
158         if (win_obj->owner != lose_obj->owner) {
159                 if (win_obj->owner == USER) {
160                         user_score += piece_attr[lose_obj->type].build_time; 
161                         ksend1 ("Enemy %s at %d destroyed.\n",piece_attr[lose_obj->type].name,loc_disp(loc),0,0,0,0,0,0); //kermyt
162                         topmsg1 (1, "Enemy %s at %d destroyed.",piece_attr[lose_obj->type].name,loc_disp(loc),0,0,0,0,0,0);
163                         ksend1 ("Your %s has %d hits left\n",piece_attr[win_obj->type].name,win_obj->hits,0,0,0,0,0,0); //kermyt
164                         topmsg1 (2, "Your %s has %d hits left.", piece_attr[win_obj->type].name, win_obj->hits,0,0,0,0,0,0);
165                                 
166                         diff = win_obj->count - obj_capacity (win_obj);
167                         if (diff > 0) switch (win_obj->cargo->type) {
168                         case ARMY:
169                                 ksend("%d armies fell overboard and drowned in the assault.\n",diff,0,0,0,0,0,0,0); //kermyt
170                              topmsg (3,"%d armies fell overboard and drowned in the assault.",diff,0,0,0,0,0,0,0);
171                              break;
172                         case FIGHTER:
173                                 ksend("%d fighters fell overboard and were lost in the assult.\n",diff,0,0,0,0,0,0,0); //kermyt
174                              topmsg (3,"%d fighters fell overboard and were lost in the assault.",diff,0,0,0,0,0,0,0);
175                              break;
176                         }
177                 }
178                 else {
179                         comp_score += piece_attr[lose_obj->type].build_time;
180                         ksend1 ("Your %s at %d destroyed.\n",piece_attr[lose_obj->type].name,loc_disp(loc),0,0,0,0,0,0); //kermyt
181                         topmsg1 (3, "Your %s at %d destroyed.",piece_attr[lose_obj->type].name,loc_disp(loc),0,0,0,0,0,0);
182                 }
183                 set_need_delay ();
184         }
185 }