]> git.pond.sub.org Git - empserver/blob - src/lib/commands/mfir.c
fire: Change "Sector X,Y firing" to "Sector X,Y ready to fire"
[empserver] / src / lib / commands / mfir.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2014, Dave Pare, Jeff Bailey, Thomas Ruschak,
4  *                Ken Stevens, Steve McClure, Markus Armbruster
5  *
6  *  Empire 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 3 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, see <http://www.gnu.org/licenses/>.
18  *
19  *  ---
20  *
21  *  See files README, COPYING and CREDITS in the root of the source
22  *  tree for related information and legal notices.  It is expected
23  *  that future projects/authors will amend these files as needed.
24  *
25  *  ---
26  *
27  *  multifire.c: Fire at other sectors/ships
28  *
29  *  Known contributors to this file:
30  *     Steve McClure, 2000
31  *     Markus Armbruster, 2004-2014
32  */
33
34 #include <config.h>
35
36 #include "chance.h"
37 #include "commands.h"
38 #include "empobj.h"
39 #include "news.h"
40 #include "optlist.h"
41 #include "retreat.h"
42
43 enum targ_type {
44     targ_land, targ_ship, targ_sub, targ_bogus
45 };
46
47 struct flist {
48     struct emp_qelem queue;     /* list of fired things */
49     short type;                 /* EF_SECTOR, EF_SHIP or EF_LAND */
50     int uid;
51     coord x, y;
52     int defdam;                 /* damage defenders did */
53     natid victim;
54 };
55
56 static int defend(struct emp_qelem *, struct emp_qelem *,
57                   struct empobj *, natid, int *);
58 static void do_defdam(struct emp_qelem *, double);
59 static int quiet_bigdef(int, struct emp_qelem *, natid, natid, coord,
60                         coord, int *);
61 static void add_to_flist(struct emp_qelem *, struct empobj *, int, natid);
62 static void free_flist(struct emp_qelem *);
63 static struct flist *search_flist(struct emp_qelem *, struct empobj *);
64
65 int
66 multifire(void)
67 {
68     static int ef_with_guns[] = { EF_SECTOR, EF_SHIP, EF_LAND, EF_BAD };
69     char *ptr;
70     double range;
71     int trange, range2;
72     coord fx;
73     coord fy;
74     coord x;
75     coord y;
76     int dam;
77     int totaldefdam = 0;
78     int vshipno;
79     natid vict;
80     struct shpstr fship;
81     struct lndstr fland;
82     struct sctstr fsect;
83     char *sep = "";
84     struct shpstr vship;
85     struct sctstr vsect;
86     enum targ_type target;
87     struct nstr_item nbst;
88     int type;
89     struct empobj *attgp;
90     char *p;
91     int nfiring = 0;
92     int ndefending = 0;
93     union empobj_storage item;
94     struct emp_qelem fired, defended;
95     double odds;
96     char buf[1024];
97
98     emp_initque(&fired);
99     emp_initque(&defended);
100     p = getstarg(player->argp[1],
101                  "Firing from ship(s), sect(s), or land unit(s)? ", buf);
102     if (!p)
103         return RET_SYN;
104     type = ef_byname_from(p, ef_with_guns);
105     if (opt_NO_FORT_FIRE && type == EF_SECTOR) {
106         pr("Fort firing is disabled.\n");
107         return RET_FAIL;
108     }
109     if (type < 0) {
110         pr("Ships, land units or sectors only!\n");
111         return RET_SYN;
112     }
113     if (!snxtitem(&nbst, type, player->argp[2], "Firing from? "))
114         return RET_SYN;
115
116     while (nxtitem(&nbst, &item)) {
117         if (type == EF_LAND) {
118             if (!getland(item.land.lnd_uid, &fland))
119                 continue;
120             if (!getsect(item.land.lnd_x, item.land.lnd_y, &fsect))
121                 continue;
122             if (item.land.lnd_own != player->cnum)
123                 continue;
124
125             if (lchr[fland.lnd_type].l_dam == 0) {
126                 pr("Unit %d cannot fire!\n", fland.lnd_uid);
127                 continue;
128             }
129             if (fland.lnd_item[I_MILIT] < 1) {
130                 pr("Unit %d cannot fire because it has no military!\n",
131                    fland.lnd_uid);
132                 continue;
133             }
134             if (fland.lnd_ship >= 0) {
135                 pr("Unit %d cannot fire because it is on a ship!\n",
136                    fland.lnd_uid);
137                 continue;
138             }
139             if (fland.lnd_land >= 0) {
140                 pr("Unit %d cannot fire because it is on a land unit!\n",
141                    fland.lnd_uid);
142                 continue;
143             }
144             if (fland.lnd_effic < LAND_MINFIREEFF) {
145                 pr("Unit %d cannot fire because it is less than %d%% efficient\n",
146                    fland.lnd_uid, LAND_MINFIREEFF);
147                 continue;
148             }
149             if (fland.lnd_item[I_GUN] == 0) {
150                 pr("%s -- not enough guns\n", prland(&fland));
151                 continue;
152             }
153
154             if (fland.lnd_item[I_SHELL] == 0) {
155                 pr("%s -- not enough shells\n", prland(&fland));
156                 continue;
157             }
158             fx = fland.lnd_x;
159             fy = fland.lnd_y;
160         } else if (type == EF_SHIP) {
161             if (!getship(item.ship.shp_uid, &fship))
162                 continue;
163             if (item.ship.shp_own != player->cnum)
164                 continue;
165             if (item.ship.shp_item[I_MILIT] < 1) {
166                 pr("Not enough mil on ship #%d\n", item.ship.shp_uid);
167                 continue;
168             }
169             if (mchr[item.ship.shp_type].m_glim == 0
170                 && !(mchr[fship.shp_type].m_flags & M_DCH)) {
171                 pr("Ships %d cannot fire guns!\n", item.ship.shp_uid);
172                 continue;
173             }
174             if (item.ship.shp_item[I_GUN] == 0) {
175                 pr("Not enough guns on ship #%d\n", item.ship.shp_uid);
176                 continue;
177             }
178             if (item.ship.shp_item[I_SHELL] == 0) {
179                 pr("Not enough shells on ship #%d\n", item.ship.shp_uid);
180                 continue;
181             }
182             if (item.ship.shp_effic < 60) {
183                 pr("Ship #%d is crippled!\n", item.ship.shp_uid);
184                 continue;
185             }
186             fx = fship.shp_x;
187             fy = fship.shp_y;
188         } else {
189             if (!getsect(item.sect.sct_x, item.sect.sct_y, &fsect))
190                 continue;
191             if (item.sect.sct_own != player->cnum)
192                 continue;
193             if (item.sect.sct_type != SCT_FORTR)
194                 continue;
195             if (item.sect.sct_effic < FORTEFF) {
196                 pr("Fort not efficient enough to fire!\n");
197                 continue;
198             }
199             if (item.sect.sct_item[I_GUN] == 0) {
200                 pr("Not enough guns in sector %s!\n",
201                    xyas(item.sect.sct_x, item.sect.sct_y, player->cnum));
202                 continue;
203             }
204             if (item.sect.sct_item[I_SHELL] == 0) {
205                 pr("Not enough shells in sector %s!\n",
206                    xyas(item.sect.sct_x, item.sect.sct_y, player->cnum));
207                 continue;
208             }
209             if (item.sect.sct_item[I_MILIT] < 5) {
210                 pr("Not enough military in sector %s!\n",
211                    xyas(item.sect.sct_x, item.sect.sct_y, player->cnum));
212                 continue;
213             }
214             pr("%sSector %s ready to fire\n", sep,
215                xyas(item.sect.sct_x, item.sect.sct_y, player->cnum));
216             fx = fsect.sct_x;
217             fy = fsect.sct_y;
218         }
219         sep = "\n";
220
221         ptr = getstarg(player->argp[3], "Firing at? ", buf);
222         if (!ptr)
223             return RET_FAIL;
224         if (!*ptr)
225             continue;
226         if (!issector(ptr)) {
227             vshipno = atoi(ptr);
228             if (vshipno < 0 || !getship(vshipno, &vship) ||
229                 (!vship.shp_own)) {
230                 pr("No such ship exists!\n");
231                 continue;
232             }
233             target = (mchr[(int)vship.shp_type].m_flags & M_SUB) ?
234                 targ_sub : targ_ship;
235             vict = vship.shp_own;
236             x = vship.shp_x;
237             y = vship.shp_y;
238             if (!getsect(x, y, &vsect)) {
239                 pr("No such sector exists!\n");
240                 continue;
241             }
242         } else {
243             if (!sarg_xy(ptr, &x, &y) || !getsect(x, y, &vsect)) {
244                 pr("No such sector exists!\n");
245                 continue;
246             }
247             /* We check the sector type, but we only use it for damage, not
248                reporting.  That way, you don't get extra information you wouldn't
249                normally get.  Besides, what if they want to slam water? :)  */
250             if (vsect.sct_type == SCT_SANCT || vsect.sct_type == SCT_WATER)
251                 target = targ_bogus;
252             else
253                 target = targ_land;
254             vict = vsect.sct_own;
255             x = vsect.sct_x;
256             y = vsect.sct_y;
257         }
258
259         trange = mapdist(x, y, fx, fy);
260
261         if (type == EF_SHIP) {
262             if (!check_ship_ok(&fship))
263                 return RET_FAIL;
264             if (target == targ_sub || target == targ_ship) {
265                 if (fship.shp_uid == vship.shp_uid) {
266                     pr("You can't fire upon yourself!\n");
267                     continue;
268                 }
269             }
270             range = shp_fire_range(&fship);
271             range2 = roundrange(range);
272             pr("range is %d.00 (%.2f)\n", range2, range);
273             if (target == targ_sub
274                 && trange <= range2
275                 && (mchr[(int)fship.shp_type].m_flags & M_DCH)) {
276                 dam = shp_dchrg(&fship);
277             } else {
278                 if (target == targ_sub)
279                     /* Don't tell it's a sub */
280                     range2 = -1;
281                 if (fship.shp_item[I_GUN] == 0) {
282                     pr("Insufficient arms.\n");
283                     continue;
284                 }
285                 dam = shp_fire(&fship);
286             }
287             putship(fship.shp_uid, &fship);
288             if (CANT_HAPPEN(dam < 0)) {
289                 pr("Klick!     ...\n");
290                 continue;
291             }
292             if (opt_NOMOBCOST == 0) {
293                 fship.shp_mobil = MAX(fship.shp_mobil - 15, -100);
294                 putship(fship.shp_uid, &fship);
295             }
296         } else if (type == EF_LAND) {
297             if (!check_land_ok(&fland))
298                 return RET_FAIL;
299             if (target == targ_land) {
300                 if (fland.lnd_x == vsect.sct_x
301                     && fland.lnd_y == vsect.sct_y) {
302                     pr("You can't fire upon yourself!\n");
303                     continue;
304                 }
305             }
306
307             range = lnd_fire_range(&fland);
308             range2 = roundrange(range);
309             pr("range is %d.00 (%.2f)\n", range2, range);
310             if (target == targ_sub) {
311                 /* Don't tell it's a sub */
312                 range2 = -1;
313             }
314
315             dam = lnd_fire(&fland);
316             putland(fland.lnd_uid, &fland);
317             if (CANT_HAPPEN(dam < 0)) {
318                 pr("Klick!     ...\n");
319                 continue;
320             }
321             if (target == targ_ship) {
322                 if (chance(lnd_acc(&fland) / 100.0))
323                     dam = ldround(dam / 2.0, 1);
324             }
325         } else {
326             if (!check_sect_ok(&fsect))
327                 return RET_FAIL;
328             if (target == targ_land) {
329                 if (fsect.sct_x == vsect.sct_x
330                     && fsect.sct_y == vsect.sct_y) {
331                     pr("You can't fire upon yourself!\n");
332                     continue;
333                 }
334             }
335             dam = fort_fire(&fsect);
336             putsect(&fsect);
337             if (CANT_HAPPEN(dam < 0)) {
338                 pr("Klick!     ...\n");
339                 continue;
340             }
341             range = fortrange(&fsect);
342             range2 = roundrange(range);
343             pr("range is %d.00 (%.2f)\n", range2, range);
344             if (target == targ_sub) {
345                 /* Don't tell it's a sub */
346                 range2 = -1;
347             }
348         }
349         if (trange > range2) {
350             pr("Target out of range.\n");
351             switch (type) {
352             case EF_SECTOR:
353                 putsect(&fsect);
354                 break;
355             case EF_LAND:
356                 fland.lnd_mission = 0;
357                 putland(fland.lnd_uid, &fland);
358                 break;
359             case EF_SHIP:
360                 fship.shp_mission = 0;
361                 putship(fship.shp_uid, &fship);
362                 break;
363             default:
364                 CANT_REACH();
365             }
366             continue;
367         }
368         switch (target) {
369         case targ_ship:
370             if (!trechk(player->cnum, vict, SEAFIR))
371                 continue;
372             break;
373         case targ_sub:
374             if (!trechk(player->cnum, vict, SUBFIR))
375                 continue;
376             break;
377         case targ_land:
378             if (!trechk(player->cnum, vict, LANFIR))
379                 continue;
380             break;
381         default:
382             break;
383         }
384
385         nfiring++;
386         switch (target) {
387         case targ_sub:
388             pr_beep();
389             pr("Kawhomp!!!\n");
390             break;
391         default:
392             pr_beep();
393             pr("Kaboom!!!\n");
394             break;
395         }
396         switch (target) {
397         case targ_bogus:
398         case targ_land:
399             nreport(player->cnum, N_SCT_SHELL, vict, 1);
400             if (vict && vict != player->cnum)
401                 wu(0, vict,
402                    "Country #%d shelled sector %s for %d damage.\n",
403                    player->cnum, xyas(x, y, vict), dam);
404             pr("Shells hit sector %s for %d damage.\n",
405                xyas(x, y, player->cnum), dam);
406             break;
407         case targ_ship:
408             nreport(player->cnum, N_SHP_SHELL, vict, 1);
409             /* fall through */
410         default:
411             if (vict && vict != player->cnum) {
412                 wu(0, vict,
413                    "Country #%d shelled %s in %s for %d damage.\n",
414                    player->cnum, prship(&vship),
415                    xyas(vship.shp_x, vship.shp_y, vict), dam);
416             }
417             pr("Shells hit %s in %s for %d damage.\n",
418                prsub(&vship),
419                xyas(vship.shp_x, vship.shp_y, player->cnum), dam);
420             break;
421         }
422         /*  Ok, now, check if we had a bogus target.  If so,
423            just continue on, since there is no defender. */
424         if (target == targ_bogus)
425             continue;
426         attgp = &item.gen;
427         if (type == EF_LAND) {
428             getsect(fland.lnd_x, fland.lnd_y, &fsect);
429             attgp = (struct empobj *)&fsect;
430         }
431         totaldefdam = defend(&fired, &defended, attgp, vict, &ndefending);
432         switch (target) {
433         case targ_land:
434             getsect(x, y, &vsect);
435             sectdamage(&vsect, dam);
436             putsect(&vsect);
437             break;
438         default:
439             getship(vshipno, &vship);
440             check_retreat_and_do_shipdamage(&vship, dam);
441             if (vship.shp_effic < SHIP_MINEFF)
442                 pr("%s sunk!\n", prsub(&vship));
443             else if (target == targ_sub
444                 && (vship.shp_rflags & RET_DCHRGED)
445                 && !(vship.shp_rflags & RET_INJURED))
446                 retreat_ship(&vship, 'd');
447             putship(vship.shp_uid, &vship);
448             break;
449         }
450         if (totaldefdam == 0 && target == targ_ship
451             && (vship.shp_rflags & RET_HELPLESS)
452             && !(vship.shp_rflags & RET_INJURED))
453             retreat_ship(&vship, 'h');
454         switch (attgp->ef_type) {
455         case EF_SECTOR:
456             putsect(&fsect);
457             break;
458         case EF_SHIP:
459             if ((target == targ_ship) || (target == targ_sub)) {
460                 if (fship.shp_effic > SHIP_MINEFF) {
461                     shp_missdef(&fship, vict);
462                 };
463             };
464             putship(fship.shp_uid, &fship);
465             break;
466         default:
467             CANT_REACH();
468         }
469     }
470
471     free_flist(&defended);
472     if (nfiring)
473         odds = ((double)ndefending) / ((double)nfiring);
474     else
475         odds = 1.0;
476     do_defdam(&fired, odds);
477     return RET_OK;
478 }
479
480 static int
481 defend(struct emp_qelem *al, struct emp_qelem *dl,
482        struct empobj *attgp, natid vict, int *nd)
483 {
484     int dam;
485     int nfiring = 0;
486
487     dam = quiet_bigdef(attgp->ef_type, dl, vict,
488                        attgp->own, attgp->x, attgp->y, &nfiring);
489     if (dam) {
490         if (nfiring > *nd)
491             *nd = nfiring;
492         add_to_flist(al, attgp, dam, vict);
493     }
494
495     return dam;
496 }
497
498 static void
499 do_defdam(struct emp_qelem *list, double odds)
500 {
501
502     int dam, first = 1;
503     natid vict;
504     struct flist *fp;
505     struct shpstr ship;
506     struct sctstr sect;
507     struct emp_qelem *qp, *next;
508
509     for (qp = list->q_forw; qp != list; qp = next) {
510         next = qp->q_forw;
511         fp = (struct flist *)qp;
512         if (fp->type == EF_SHIP) {
513             if (!getship(fp->uid, &ship) || !ship.shp_own)
514                 continue;
515         }
516         if (first) {
517             pr_beep();
518             pr("\nDefenders fire back!\n");
519             first = 0;
520         }
521         dam = odds * fp->defdam;
522
523         if (fp->type == EF_SHIP) {
524             vict = fp->victim;
525             pr("Return fire hit %s in %s for %d damage.\n",
526                prship(&ship),
527                xyas(ship.shp_x, ship.shp_y, player->cnum), dam);
528             if (vict)
529                 wu(0, vict,
530                    "Return fire hit %s in %s for %d damage.\n",
531                    prsub(&ship), xyas(ship.shp_x, ship.shp_y, vict), dam);
532             shipdamage(&ship, dam);
533             putship(ship.shp_uid, &ship);
534         } else {
535             CANT_HAPPEN(fp->type != EF_SECTOR);
536             getsect(fp->x, fp->y, &sect);
537             vict = fp->victim;
538             pr("Return fire hit sector %s for %d damage.\n",
539                xyas(fp->x, fp->y, player->cnum), dam);
540             sectdamage(&sect, dam);
541             putsect(&sect);
542             if (vict)
543                 wu(0, vict, "Return fire hit sector %s for %d damage.\n",
544                    xyas(fp->x, fp->y, vict), dam);
545         }
546         emp_remque(&fp->queue);
547         free(fp);
548     }
549 }
550
551 static int
552 quiet_bigdef(int type, struct emp_qelem *list, natid own, natid aown,
553              coord ax, coord ay, int *nfiring)
554 {
555     double erange;
556     struct shpstr ship;
557     struct lndstr land;
558     struct nstr_item ni;
559     int dam, dam2;
560     struct sctstr firing;
561     struct nstr_sect ns;
562     struct flist *fp;
563
564     if (own == 0)
565         return 0;
566     dam = 0;
567     snxtitem_dist(&ni, EF_SHIP, ax, ay, 8);
568     while (nxtitem(&ni, &ship)) {
569         if (!feels_like_helping(ship.shp_own, own, aown))
570             continue;
571
572         if ((mchr[ship.shp_type].m_flags & M_SUB) && type != EF_SHIP)
573             continue;
574
575         if (mchr[(int)ship.shp_type].m_flags & M_SUB) {
576             erange = torprange(&ship);
577             if (roundrange(erange) < ni.curdist)
578                 continue;
579             if (!line_of_sight(NULL, ship.shp_x, ship.shp_y, ax, ay))
580                 continue;
581             fp = search_flist(list, (struct empobj *)&ship);
582             if (fp)
583                 dam2 = fp->defdam;
584             else {
585                 dam2 = shp_torp(&ship, 0);
586                 putship(ship.shp_uid, &ship);
587             }
588             if (dam2 < 0)
589                 continue;
590             if (!chance(shp_torp_hitchance(&ship, ni.curdist)))
591                 dam2 = 0;
592         } else {
593             erange = shp_fire_range(&ship);
594             if (roundrange(erange) < ni.curdist)
595                 continue;
596             fp = search_flist(list, (struct empobj *)&ship);
597             if (fp)
598                 dam2 = fp->defdam;
599             else {
600                 dam2 = shp_fire(&ship);
601                 putship(ship.shp_uid, &ship);
602             }
603             if (dam2 < 0)
604                 continue;
605             nreport(ship.shp_own, N_FIRE_BACK, player->cnum, 1);
606         }
607         (*nfiring)++;
608         if (!fp)
609             add_to_flist(list, (struct empobj *)&ship, dam2, 0);
610         dam += dam2;
611     }
612     snxtitem_dist(&ni, EF_LAND, ax, ay, 8);
613     while (nxtitem(&ni, &land)) {
614         if (!feels_like_helping(land.lnd_own, own, aown))
615             continue;
616
617         erange = lnd_fire_range(&land);
618         if (roundrange(erange) < ni.curdist)
619             continue;
620
621         fp = search_flist(list, (struct empobj *)&land);
622         if (fp)
623             dam2 = fp->defdam;
624         else {
625             dam2 = lnd_fire(&land);
626             putland(land.lnd_uid, &land);
627         }
628         if (dam2 < 0)
629             continue;
630
631         (*nfiring)++;
632         if (!fp)
633             add_to_flist(list, (struct empobj *)&land, dam2, 0);
634         nreport(land.lnd_own, N_FIRE_BACK, player->cnum, 1);
635         if (type == EF_SHIP) {
636             if (chance(lnd_acc(&land) / 100.0))
637                 dam2 = ldround(dam2 / 2.0, 1);
638         }
639         dam += dam2;
640     }
641
642     /*
643      * Determine if any nearby gun-equipped sectors are within
644      * range and able to fire at an attacker.  Firing sectors
645      * need to have guns, shells, and military.  Sector being
646      * attacked is x,y -- attacker is at ax,ay.
647      */
648
649     if (!opt_NO_FORT_FIRE) {
650         snxtsct_dist(&ns, ax, ay, 8);
651         while (nxtsct(&ns, &firing)) {
652             if (!feels_like_helping(firing.sct_own, own, aown))
653                 continue;
654
655             erange = fortrange(&firing);
656             if (roundrange(erange) < ns.curdist)
657                 continue;
658
659             fp = search_flist(list, (struct empobj *)&firing);
660             if (fp)
661                 dam2 = fp->defdam;
662             else {
663                 dam2 = fort_fire(&firing);
664                 putsect(&firing);
665             }
666             if (dam2 < 0)
667                 continue;
668             (*nfiring)++;
669             if (!fp)
670                 add_to_flist(list, (struct empobj *)&firing, dam2, 0);
671             nreport(firing.sct_own, N_FIRE_BACK, player->cnum, 1);
672             dam += dam2;
673         }
674     }
675
676     return *nfiring == 0 ? 0 : dam / *nfiring;
677 }
678
679 static void
680 add_to_flist(struct emp_qelem *list,
681              struct empobj *gp, int dam, natid victim)
682 {
683     struct flist *fp;
684
685     fp = malloc(sizeof(struct flist));
686     fp->type = gp->ef_type;
687     fp->uid = gp->uid;
688     fp->x = gp->x;
689     fp->y = gp->y;
690     fp->defdam = dam;
691     fp->victim = victim;
692     emp_insque(&fp->queue, list);
693 }
694
695 static void
696 free_flist(struct emp_qelem *list)
697 {
698     struct emp_qelem *qp, *next;
699     struct flist *fp;
700
701     for (qp = list->q_forw; qp != list; qp = next) {
702         next = qp->q_forw;
703         fp = (struct flist *)qp;
704         emp_remque(&fp->queue);
705         free(fp);
706     }
707 }
708
709 static int
710 uid_eq(struct emp_qelem *elem, void *key)
711 {
712     return ((struct flist *)elem)->uid == ((struct empobj *)key)->uid;
713 }
714
715 static struct flist *
716 search_flist(struct emp_qelem *list, struct empobj *gp)
717 {
718     return (struct flist *)emp_searchque(list, gp, uid_eq);
719 }