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