Minor fix for internal help.
[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.");
44             ksend ("The scum defending the city crushed your attacking blitzkrieger.\n"); //kermyt
45         }
46         else if (city_owner == USER) {
47             ksend ("Your city at %d is under attack.\n",loc_disp(cityp->loc)); //kermyt
48             comment ("Your city at %d is under attack.",loc_disp(cityp->loc));
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)); //kermyt
59             error ("City at %d has been subjugated!",loc_disp(cityp->loc));
60
61             extra ("Your army has been dispersed to enforce control.");
62             ksend ("Your army has been dispersed to enforce control.\n");
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)); //kermyt
67             comment ("City at %d has been lost to the enemy!",loc_disp(cityp->loc));
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 == MAP_CITY) /* 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         
144     *buf = '\0';
145     *buf2 = '\0';
146         
147     if (win_obj->owner != lose_obj->owner) {
148         if (win_obj->owner == USER) {
149             int diff;
150             user_score += piece_attr[lose_obj->type].build_time; 
151             ksend ("Enemy %s at %d destroyed.\n",piece_attr[lose_obj->type].name,loc_disp(loc)); //kermyt
152             topmsg (1, "Enemy %s at %d destroyed.",piece_attr[lose_obj->type].name,loc_disp(loc));
153             ksend ("Your %s has %d hits left\n",piece_attr[win_obj->type].name,win_obj->hits); //kermyt
154             topmsg (2, "Your %s has %d hits left.", piece_attr[win_obj->type].name, win_obj->hits);
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); //kermyt
160                     topmsg (3,"%d armies fell overboard and drowned in the assault.",diff);
161                     break;
162                 case FIGHTER:
163                     ksend("%d fighters fell overboard and were lost in the assult.\n",diff); //kermyt
164                     topmsg (3,"%d fighters fell overboard and were lost in the assault.",diff);
165                     break;
166                 }
167         }
168         else {
169             comp_score += piece_attr[lose_obj->type].build_time;
170             ksend ("Your %s at %d destroyed.\n",piece_attr[lose_obj->type].name,loc_disp(loc)); //kermyt
171             topmsg (3, "Your %s at %d destroyed.",piece_attr[lose_obj->type].name,loc_disp(loc));
172         }
173         set_need_delay ();
174     }
175 }
176
177 /* end */