home *** CD-ROM | disk | FTP | other *** search
/ C++ Games Programming / CPPGAMES.ISO / thx / demos / shootout / build / shootout.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-06  |  8.4 KB  |  318 lines

  1. // ------------ shootout.cpp
  2.  
  3. #include <stdlib.h>
  4. #include "shootout.h"
  5. #include "options.h"
  6.  
  7. Portal Shootout::portals[] = {
  8.     { nobldg,   0,   0,   0,   0, 1},    // nowhere
  9.     { house,   27,  63,  41,  77, 0},    // window1
  10.     { house,   52,  63,  66,  77, 0},    // window2
  11.     { house,   78,  63,  91,  77, 0},    // window3
  12.     { house,   27, 117,  41, 131, 0},    // window4
  13.     { house,   78, 117,  91, 131, 0},    // window5
  14.     { house,   61,   0, 319, 239, 0},    // housedoor
  15.     { nobldg, 102,   0, 118, 239, 0},    // alley1
  16.     { jail,   183,   0, 319, 239, 0},    // jaildoor
  17.     { nobldg, 216,   0, 233, 239, 0},    // alley2
  18.     { saloon, 260,   0, 319, 239, 0},    // saloondoor
  19.     { saloon, 244,  56, 258,  69, 0},     // window6
  20.     { saloon, 268,  56, 282,  69, 0},     // window7
  21.     { saloon, 291,  56, 305,  69, 0}     // window8
  22. };
  23.  
  24. static Location houseentr[] = {
  25.     window1, window2, window3, window4, window5, housedoor, alley2
  26. };
  27. static Location jailentr[] = { alley2, jaildoor, alley3 };
  28. static Location saloonentr[] = {
  29.     alley3, saloondoor, window6, window7, window8
  30. };
  31. Location *Shootout::entrances[] = { 0, houseentr, jailentr, saloonentr };
  32. int Shootout::entrcounts[] = { 0, 7, 3, 5 };
  33.  
  34. Building nextbldg[][2] = {
  35.     { nobldg, nobldg }, // nowhere
  36.     {  house,  house },    // window1
  37.     {  house,  house },    // window2
  38.     {  house,  house },    // window3
  39.     {  house,  house },    // window4
  40.     {  house,  house },    // window5
  41.     {  house,  house },    // housedoor
  42.     {   jail,  house }, // alley2
  43.     {   jail,   jail }, // jaildoor
  44.     { saloon,   jail }, // alley3
  45.     { saloon, saloon }, // saloondoor
  46.     { saloon, saloon }, // window6
  47.     { saloon, saloon }, // window7
  48.     { saloon, saloon }  // window8
  49. };
  50.  
  51. Shootout::Shootout() : SceneDirector("town.pcx", fade)
  52. {
  53.     bullets = new Digit;
  54.     citizens = new Digit;
  55.     badguys = new Digit;
  56.     actorctr = 0;
  57.     conductor = new MusicHand("shootout.xmi");
  58.     door3 = new Door(3);
  59.     door2 = new Door(2);
  60.     door1 = new Door(1);
  61.     actors[actorctr++] = new Sadie;
  62.     actors[actorctr++] = new Deputy;
  63.     actors[actorctr++] = new Parson;
  64.     actors[actorctr++] = new BadSadie;
  65.     actors[actorctr++] = new BadDeputy;
  66.     actors[actorctr++] = new BadParson;
  67.     sheriff = new Sheriff;
  68.     finalscreen = new Player("finalscr.gfx", "sounds.sfx");
  69. }
  70.  
  71. Shootout::~Shootout()
  72. {
  73.     for (int i = 0; i < actorctr; i++)    {
  74.         delete actors[i];
  75.         actors[i] = 0;
  76.         actorctr = 0;
  77.     }
  78.     delete conductor;
  79. }
  80. void Shootout::display()
  81. {
  82.     sheriff->initialize_sheriff();
  83.     SceneDirector::display();
  84.     for (int i = 1; i < 14; i++)
  85.         portals[i].occupied = 0;
  86.     randomize();
  87.     rinterval = random(maxticks);
  88.     rticks = 0;
  89.     screenshattered = 0;
  90.     certificate = 0;
  91.     badguysintown = 0;
  92.     door1->initialize_door();
  93.     door2->initialize_door();
  94.     door3->initialize_door();
  95.     sheriff->appear();
  96.     distribute_players();
  97.     conductor->play_music_clip(1);
  98.     bullets->setxy(59,215);
  99.     bullets->appear();
  100.     citizens->setxy(176,215);
  101.     citizens->setnum(0);
  102.     citizens->appear();
  103.     badguys->setxy(300,215);
  104.     badguys->setnum(0);
  105.     badguys->appear();
  106. }
  107. void Shootout::hide()
  108. {
  109.     conductor->stop_music_clip();
  110.     sheriff->disappear();
  111.     finalscreen->disappear();
  112.     SceneDirector::hide();
  113. }
  114. // ---- initially distribute the players evenly among the buildings
  115. void Shootout::distribute_players()
  116. {
  117.     short int *ply = new short int[actorctr];
  118.     for (int i = 0; i < actorctr; i++)
  119.         *(ply+i) = 0;
  120.     Building bldg = nobldg;
  121.     for (short int acs = 0; acs < actorctr; acs++)    {
  122.         actors[acs]->initialize_bitpart();
  123.         if ((acs&1) == 0)
  124.             bldg++;
  125.         short int ac;
  126.         do
  127.             ac = random(actorctr);
  128.         while (ply[ac] != 0);
  129.         ply[ac] = 1;
  130.         actors[ac]->clipper.building = bldg;
  131.     }
  132.     delete ply;
  133. }
  134.  
  135. BitPart *Shootout::select_actor()
  136. {
  137.     int maxbadguys = options->fletchers->getnum();
  138.     // --- first see if there are any invisible actors
  139.     //     (they might all be on stage)
  140.     for (int pl = 0; pl < actorctr; pl++)    {
  141.         if ((actors[pl]->isvisible()))
  142.             continue;
  143.         if (!actors[pl]->iscitizen())
  144.             // --- a bad guy
  145.             if (badguysintown == maxbadguys)
  146.                 continue;
  147.         break;
  148.     }
  149.     if (pl == actorctr)
  150.         return 0;
  151.     // --- choose an available (invisible) player at random
  152.     for (;;)    {
  153.         pl = random(actorctr);
  154.         if ((actors[pl]->isvisible()))
  155.             continue;
  156.         if (!actors[pl]->iscitizen())
  157.             // --- a bad guy
  158.             if (badguysintown == maxbadguys)
  159.                 continue;
  160.         break;
  161.     }
  162.     return actors[pl];
  163. }
  164.  
  165. int Shootout::entrance_available(Location loc)
  166. {
  167.     return (
  168.         portals[loc].occupied == 0 &&
  169.                 (!sheriff->isdead() || on_the_street(loc)) );
  170. }
  171.  
  172. Location Shootout::select_location(BitPart *bp)
  173. {
  174.     Building currbldg = bp->clipper.building;
  175.     int ecnt = entrcounts[currbldg];
  176.     Location *locp = entrances[currbldg];
  177.     Location loc;
  178.  
  179.     // --- first see if there are any unoccupied, eliglible entrances
  180.     for (int locoffset = 0; locoffset < ecnt; locoffset++)    {
  181.         loc = locp[locoffset];
  182.         if (entrance_available(loc))
  183.             break;
  184.     }
  185.     if (locoffset == ecnt)
  186.         return nowhere;
  187.     // --- there is at least one entrance available, pick one at random
  188.     do
  189.         loc = locp[random(ecnt)];
  190.     while (!entrance_available(loc));
  191.     return loc;
  192. }
  193.  
  194. void Shootout::on_timer()
  195. {
  196.     if (!conductor->music_clip_is_playing())
  197.         conductor->play_music_clip(1);
  198.     if (screenshattered)    {
  199.         if (screenshattered == 1)    {
  200.             while (finalscreen->sound_clip_is_playing())
  201.                 ;
  202.             screenshattered = 2;
  203.             finalscreen->set_imageno(3);
  204.             finalscreen->setxy(60,65);
  205.             finalscreen->appear();
  206.             finalscreen->play_sound_clip(9);
  207.         }
  208.         SceneDirector::on_timer();
  209.         return;
  210.     }
  211.     if (certificate)    {
  212.         if (certificate != 3)    {
  213.             // ---- display a death certificate
  214.             finalscreen->set_imageno(certificate);
  215.             finalscreen->setxy(60,65);
  216.             finalscreen->appear();
  217.             certificate = 3;
  218.             SceneDirector::on_timer();
  219.         }
  220.         return;
  221.     }
  222.     SceneDirector::on_timer();
  223.     int sheriffdead = sheriff->isdead();
  224.     int badguysdead = badguys->getnum() == 3;
  225.     if (sheriffdead || badguysdead || rticks++ == rinterval)    {
  226.         rticks = 0;
  227.         // ---- time to send in a bit player
  228.         BitPart *bp = select_actor();
  229.         if (bp != 0)    {
  230.             // --- found an off-stage player, pick an entrance
  231.             //     based on the building where the player is now
  232.             Location loc = select_location(bp);
  233.             if (loc != nowhere)
  234.                 enteractor(bp, loc);
  235.         }
  236.         rinterval = random(maxticks);
  237.     }
  238. }
  239.  
  240. void Shootout::enteractor(BitPart *bp, Location loc)
  241. {
  242.     int sheriffdead = sheriff->isdead();
  243.     short int badguysdead = badguys->getnum() == 3;
  244.     short int citizendead = citizens->getnum();
  245.     // ---- if 1 sheriff or 3 badguys are dead, go to the street only
  246.     if ((sheriffdead || badguysdead) && !on_the_street(loc))
  247.         return;
  248.     // ---- if 3 badguys are dead and any citizens, don't enter
  249.     if (badguysdead && citizendead)
  250.         return;
  251.     // ---- bad guys stay off the street after the sheriff is dead
  252.     if (!bp->iscitizen() && sheriffdead)
  253.         return;
  254.     Door *dor = 0;
  255.     switch (loc)    {
  256.         case housedoor:
  257.             dor = door1;
  258.             break;
  259.         case jaildoor:
  260.             dor = door2;
  261.             break;
  262.         case saloondoor:
  263.             dor = door3;
  264.             break;
  265.         default:
  266.             break;
  267.     }
  268.     // --- clip the actor's display to the entranceway
  269.     bp->clip(portals[loc].x1, portals[loc].y1,
  270.         portals[loc].x2, portals[loc].y2);
  271.     // --- mark the door/alley as occupied
  272.     portals[loc].occupied = 1;
  273.     // --- count the number of bad guys on the street
  274.     if (!bp->iscitizen())
  275.         badguysintown++;
  276.     // --- tell the actor to make an entrance
  277.     bp->enter(portals[loc], dor, loc);
  278. }
  279. // --- find the actors in zone
  280. short int Shootout::findactors(BitPart *actrs[], short int zone)
  281. {
  282.     short int ct = 0;
  283.     for (int pl = 0; pl < actorctr; pl++)
  284.         if (actors[pl]->zone() == zone)
  285.             actrs[ct++] = actors[pl];
  286.     return ct;
  287. }
  288. // --- find the actors in zone1 and zone2
  289. short int Shootout::findactors(BitPart *actrs[],
  290.                             short int zone1, short int zone2)
  291. {
  292.     short int ct = findactors(actrs, zone1);
  293.     if (zone1 != zone2 && zone2 != 0)
  294.         ct += findactors(actrs+ct, zone2);
  295.     return ct;
  296. }
  297. // ---- test if anyone other than caller is drawing down on sheriff
  298. short int Shootout::isbadguy_shooting(BitPart *bp)
  299. {
  300.     for (int pl = 0; pl < actorctr; pl++)
  301.         if (actors[pl] != bp)
  302.             if (actors[pl]->isshooting())
  303.                 return 1;
  304.     return 0;
  305. }
  306. // ---- an actor is leaving the stage
  307. void Shootout::exitstage(BitPart *bp)
  308. {
  309.     // ---- free the entrance position for another actor to use
  310.     portals[bp->location].occupied = 0;
  311.     // ---- update actor's position based on
  312.     //      current location and direction of exit
  313.     bp->clipper.building = nextbldg[bp->location][bp->exitright];
  314.     if (!bp->iscitizen())
  315.         --badguysintown;
  316. }
  317.  
  318.