home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / x / xconq55.zip / xc5.5 / order.c < prev    next >
C/C++ Source or Header  |  1992-03-08  |  10KB  |  441 lines

  1. /* Copyright (c) 1987, 1988  Stanley T. Shebs. */
  2. /* This program may be used, copied, modified, and redistributed freely */
  3. /* for noncommercial purposes, so long as this notice remains intact. */
  4.  
  5. /* Handling of unit orders. */
  6.  
  7. #include "config.h"
  8. #include "misc.h"
  9. #include "dir.h"
  10. #include "period.h"
  11. #include "side.h"
  12. #include "unit.h"
  13.  
  14. char *ordernames[] = ORDERNAMES;   /* full names of orders */
  15. char *dirnames[] = DIRNAMES;       /* short names of directions */
  16. char orderbuf[BUFSIZE];            /* buffer for printed form of an order */
  17. char oargbuf[BUFSIZE];             /* buffer for order's arguments */
  18.  
  19. int orderargs[] = ORDERARGS;       /* types of parameters for each order */
  20.  
  21. /* General routine to wake a unit up (and maybe all its cargo). */
  22.  
  23. wake_unit(unit, wakeocc, reason, other)
  24. Unit *unit, *other;
  25. int reason;
  26. bool wakeocc;
  27. {
  28.     Unit *occ;
  29.  
  30. /* make sure that a side always gets to move a unit that is woken up
  31. late in the turn */
  32.  
  33.     if (unit->side != NULL && unit->movesleft > 0 &&
  34.     alive(unit) && !unit->side->more_units) {
  35.       unit->side->more_units = TRUE;
  36.       update_sides(unit->side);
  37.       move_mode(unit->side);
  38.       unit->side->movunit = unit;
  39.       cancel_request(unit->side);
  40.     }
  41.  
  42.     unit->orders.type = AWAKE;
  43.     unit->orders.rept = 0;
  44.     unit->orders.flags = NORMAL;
  45.     unit->wakeup_reason = reason;
  46.     if (reason == WAKEFULL) {
  47.       unit->orders.morder = FALSE;
  48.     }
  49.     if (reason == WAKEOWNER)
  50.       unit->area = area_index(unit->x, unit->y);
  51.     if (reason == WAKEENEMY && other!=NULL) {
  52.       unit->waking_side = other->side;
  53.       unit->waking_type = other-> type;
  54.       unit->area = area_index(unit->x, unit->y);
  55.     }
  56.     if (wakeocc) {
  57.     for_all_occupants(unit, occ) wake_unit(occ, wakeocc, reason, other);
  58.     }
  59. }
  60.  
  61. /* Stash a "wakeup call" - will only be for main unit, not occupants. */
  62.  
  63. cache_awake(side)
  64. Side *side;
  65. {
  66.     side->tmporder->type = AWAKE;
  67.     side->tmporder->rept = 0;
  68.     side->tmporder->morder = FALSE;
  69.     finish_teach(side);
  70. }
  71.  
  72. /* Give a unit sentry orders. */
  73.  
  74. order_sentry(unit, n)
  75. Unit *unit;
  76. int n;
  77. {
  78.     unit->orders.type = SENTRY;
  79.     unit->orders.rept = n;
  80. }
  81.  
  82. /* Stash sentry orders. */
  83.  
  84. cache_sentry(side, n)
  85. Side *side;
  86. int n;
  87. {
  88.     side->tmporder->type = SENTRY;
  89.     side->tmporder->rept = n;
  90.     finish_teach(side);
  91. }
  92.  
  93. /* Fill in the given unit with direction-moving orders. */
  94.  
  95. order_movedir(unit, dir, n)
  96. Unit *unit;
  97. int dir, n;
  98. {
  99.     unit->orders.type = MOVEDIR;
  100.     unit->orders.p.dir = dir;
  101.     unit->orders.rept = n;
  102. }
  103.  
  104. cache_movedir(side, dir, n)
  105. Side *side;
  106. int dir, n;
  107. {
  108.     side->tmporder->type = MOVEDIR;
  109.     side->tmporder->p.dir = dir;
  110.     side->tmporder->rept = n;
  111.     finish_teach(side);
  112. }
  113.  
  114. /* Give the unit orders to move to a given place - it only needs to do this */
  115. /* once, repetition is nonsensical. */
  116.  
  117. order_moveto(unit, x, y)
  118. Unit *unit;
  119. int x, y;
  120. {
  121.     unit->orders.type = MOVETO;
  122.     unit->orders.rept = 1;
  123.     unit->orders.p.pt[0].x = x;
  124.     unit->orders.p.pt[0].y = y;
  125. }
  126.  
  127. cache_moveto(side, x, y)
  128. Side *side;
  129. int x, y;
  130. {
  131.     side->tmporder->type = MOVETO;
  132.     side->tmporder->rept = 1;
  133.     side->tmporder->p.pt[0].x = x;
  134.     side->tmporder->p.pt[0].y = y;
  135.     finish_teach(side);
  136. }
  137.  
  138. /* order a unit to move toward another unit */
  139.  
  140. order_movetounit(unit, dest, n)
  141. Unit    *unit, *dest;
  142. int    n;
  143. {
  144.   unit->orders.type = MOVETOUNIT;
  145.   unit->orders.rept = n;
  146.   unit->orders.p.leader_id = dest->id;
  147. }
  148.  
  149. cache_movetounit(side, dest, n)
  150. Side    *side;
  151. Unit    *dest;
  152. int    n;
  153. {
  154.   side->tmporder->type = MOVETOUNIT;
  155.   side->tmporder->rept = n;
  156.   side->tmporder->p.leader_id = dest->id;
  157.   finish_teach(side);
  158. }
  159.  
  160. /* order a unit to return to base */
  161.  
  162. order_return(unit, n)
  163. Unit *unit;
  164. int n;
  165. {
  166.   unit->orders.type = RETURN;
  167.   unit->orders.rept = n;
  168. }
  169.  
  170. cache_return(side, n)
  171. Side *side;
  172. int n;
  173. {
  174.   side->tmporder->type = RETURN;
  175.   side->tmporder->rept = n;
  176.   finish_teach(side);
  177. }
  178.  
  179. /* Order to follow an edge needs to know the direction and which side the
  180.    obstacle is on. */
  181.  
  182. order_edge(unit, d, ccw, n)
  183. Unit *unit;
  184. int d, ccw, n;
  185. {
  186.     unit->orders.type = EDGE;
  187.     unit->orders.rept = n;
  188.     unit->orders.p.edge.forward = d;
  189.     unit->orders.p.edge.ccw = ccw;
  190. }
  191.  
  192. cache_edge(side, d, ccw, n)
  193. Side *side;
  194. int d, ccw, n;
  195. {
  196.     side->tmporder->type = EDGE;
  197.     side->tmporder->rept = n;
  198.     side->tmporder->p.edge.forward = d;
  199.     side->tmporder->p.edge.ccw = ccw;
  200.     finish_teach(side);
  201. }
  202.  
  203. /* Order to move to the nearest filling transport */
  204.  
  205. order_movetotransport(unit, n)
  206.      Unit    *unit;
  207.      int    n;
  208. {
  209.   unit->orders.type = MOVETOTRANSPORT;
  210.   unit->orders.rept = n;
  211. }
  212.  
  213. cache_movetotransport(side, n)
  214.      Side    *side;
  215.      int    n;
  216. {
  217.   side->tmporder->type = MOVETOTRANSPORT;
  218.   side->tmporder->rept = n;
  219.   finish_teach(side);
  220. }
  221.  
  222. /* Order to follow a unit just needs the unit to follow. */
  223.  
  224. order_follow(unit, leader, n)
  225. Unit *unit, *leader;
  226. int n;
  227. {
  228.     unit->orders.type = FOLLOW;
  229.     unit->orders.rept = n;
  230.     unit->orders.p.leader_id = leader->id;;
  231. }
  232.  
  233. cache_follow(side, leader, n)
  234. Side *side;
  235. Unit *leader;
  236. int n;
  237. {
  238.     side->tmporder->type = FOLLOW;
  239.     side->tmporder->rept = n;
  240.     side->tmporder->p.leader_id = leader->id;
  241.     finish_teach(side);
  242. }
  243.  
  244. /* A two-waypoint patrol suffices for many purposes. */
  245. /* Should have a more general patrol routine eventually (> 2 waypoints). */
  246.  
  247. order_patrol(unit, x0, y0, x1, y1, n)
  248. Unit *unit;
  249. int x0, y0, x1, y1, n;
  250. {
  251.     unit->orders.type = PATROL;
  252.     unit->orders.rept = n;
  253.     unit->orders.p.pt[0].x = x0;
  254.     unit->orders.p.pt[0].y = y0;
  255.     unit->orders.p.pt[1].x = x1;
  256.     unit->orders.p.pt[1].y = y1;
  257. }
  258.  
  259. cache_patrol(side, x0, y0, x1, y1, n)
  260. Side *side;
  261. int x0, y0, x1, y1, n;
  262. {
  263.     side->tmporder->type = PATROL;
  264.     side->tmporder->rept = n;
  265.     side->tmporder->p.pt[0].x = x0;
  266.     side->tmporder->p.pt[0].y = y0;
  267.     side->tmporder->p.pt[1].x = x1;
  268.     side->tmporder->p.pt[1].y = y1;
  269.     finish_teach(side);
  270. }
  271.  
  272.  
  273. /* Wait around to embark on some unit when it comes to our location. */
  274.  
  275. order_embark(unit, n)
  276. Unit *unit;
  277. int n;
  278. {
  279.     unit->orders.type = EMBARK;
  280.     unit->orders.rept = n;
  281. }
  282.  
  283. cache_embark(side, n)
  284. Side *side;
  285. int n;
  286. {
  287.     side->tmporder->type = EMBARK;
  288.     side->tmporder->rept = n;
  289.     finish_teach(side);
  290. }
  291.  
  292. order_fill(unit, n)
  293. Unit *unit;
  294. int n;
  295. {
  296.     unit->orders.type = FILL;
  297.     unit->orders.rept = n;
  298. }
  299.  
  300. cache_fill(side, n)
  301. Side *side;
  302. int n;
  303. {
  304.     side->tmporder->type = FILL;
  305.     side->tmporder->rept = n;
  306.     finish_teach(side);
  307. }
  308.  
  309. /* Note that this leaves all other orders the same. */
  310.  
  311. cache_auto(side)
  312. Side *side;
  313. {
  314.   Order *oldorder;
  315.  
  316.   if ((oldorder = side->sounit->standing->orders[side->soutype]) != NULL) 
  317.     copy_orders(side->tmporder, oldorder);
  318.   else {
  319.     side->tmporder->type = AWAKE;
  320.     side->tmporder->rept = 0;
  321.   }
  322.   side->tmporder->morder = TRUE;
  323.   finish_teach(side);
  324. }
  325.  
  326. /* Switch from standing order teaching mode back to normal, and confirm */
  327. /* that the standing order has been set. */
  328.  
  329. finish_teach(side)
  330. Side *side;
  331. {
  332.     Unit *occ, *next;
  333.  
  334.     side->teach = FALSE;
  335.     if (side->sounit->standing->orders[side->soutype] != NULL)
  336.       free(side->sounit->standing->orders[side->soutype]);
  337.     side->sounit->standing->orders[side->soutype] = side->tmporder;
  338.     if (side->tmporder==NULL) {
  339.       notify(side, "standing orders for %s deleted",
  340.          utypes[side->soutype].name);
  341.     } else {
  342.       notify(side, "%s has orders for %s to %s%0s.",
  343.          unit_handle(side, side->sounit), utypes[side->soutype].name,
  344.          order_desig(side->tmporder),
  345.          ((side->tmporder->morder) ? " and auto" : ""));
  346.       for_all_occupants(side->sounit, occ) {
  347.     if (occ->type == side->soutype) {
  348.       get_standing_orders(occ, side->sounit);
  349.     }
  350.       }
  351.     }
  352.     show_timemode(side,TRUE);
  353. }
  354.  
  355. /* Display orders in some coherent fashion.  Use the information about the */
  356. /* types of order parameters to decide how to display them. */
  357.  
  358. char *
  359. order_desig(orders)
  360. Order *orders;
  361. {
  362.     switch (orderargs[orders->type]) {
  363.     case NOARG:
  364.     sprintf(oargbuf, "");
  365.     break;
  366.     case DIR:
  367.     sprintf(oargbuf, "%s ", dirnames[orders->p.dir]);
  368.     break;
  369.     case POS:
  370.     sprintf(oargbuf, "%d,%d ", orders->p.pt[0].x, orders->p.pt[0].y);
  371.     break;
  372.     case EDGE_A:
  373.     sprintf(oargbuf, "%d/%d ", orders->p.edge.forward, orders->p.edge.ccw);
  374.     break;
  375.     case LEADER:
  376.     sprintf(oargbuf, "%s ", unit_handle((Side *) NULL,
  377.                         find_unit(orders->p.leader_id)));
  378.     break;
  379.     case WAYPOINTS:
  380.     sprintf(oargbuf, "%d,%d %d,%d ",
  381.         orders->p.pt[0].x, orders->p.pt[0].y,
  382.         orders->p.pt[1].x, orders->p.pt[1].y);
  383.     break;
  384.     default:
  385.     case_panic("order arg type", orderargs[orders->type]);
  386.     }
  387.     if (orders->rept > 1)
  388.     sprintf(orderbuf, "%s %s(%d)",
  389.         ordernames[orders->type], oargbuf, orders->rept);
  390.     else
  391.     sprintf(orderbuf, "%s %s",
  392.         ordernames[orders->type], oargbuf);
  393.     return orderbuf;
  394. }
  395.  
  396. /* Yeah yeah, assignment statements supposedly copy structures. */
  397.  
  398. copy_orders(dst, src)
  399. Order *dst, *src;
  400. {
  401.   /* the first two options should work fine since the Order
  402.      is (theoretically) contiguous with no pointers. */
  403. #ifdef BCOPY
  404.   bcopy(src, dst, sizeof(*dst));
  405. #else
  406.   memcpy(dst, src, sizeof(*dst));
  407. #endif
  408. #if 0  /* fallback code */
  409.     dst->type = src->type;
  410.     dst->rept = src->rept;
  411.     dst->flags = src->flags;
  412.     switch (orderargs[src->type]) {
  413.     case NOARG:
  414.     break;
  415.     case DIR:
  416.     dst->p.dir = src->p.dir;
  417.     break;
  418.     case POS:
  419.     dst->p.pt[0].x = src->p.pt[0].x;
  420.     dst->p.pt[0].y = src->p.pt[0].y;
  421.     break;
  422.     case EDGE_A:
  423.     dst->p.edge.forward = src->p.edge.forward;
  424.     dst->p.edge.ccw     = src->p.edge.ccw;
  425.     break;
  426.     case LEADER:
  427.     dst->p.leader_id = src->p.leader_id;
  428.     break;
  429.     case WAYPOINTS:    
  430.     dst->p.pt[0].x = src->p.pt[0].x;
  431.     dst->p.pt[0].y = src->p.pt[0].y;
  432.     dst->p.pt[1].x = src->p.pt[1].x;
  433.     dst->p.pt[1].y = src->p.pt[1].y;
  434.     break;
  435.     default:
  436.     case_panic("order arg type", orderargs[src->type]);
  437.     }
  438.     dst->morder = src->morder;
  439. #endif /* 0 */
  440. }
  441.