home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / ABUSESRC.ZIP / AbuseSrc / macabuse / src / level.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-20  |  76.8 KB  |  3,346 lines

  1. #include "system.h"
  2. #include "light.hpp"
  3. #include "level.hpp"
  4. #include "game.hpp"
  5. #include "intsect.hpp"
  6. #include "lisp.hpp"
  7. #include "dprint.hpp"
  8. #include "objects.hpp"
  9. #include "jrand.hpp"
  10. #include "macs.hpp"
  11. #include "clisp.hpp"
  12. #include "status.hpp"
  13. #include "dev.hpp"
  14. #include "demo.hpp"
  15. #include "pcxread.hpp"
  16. #include "profile.hpp"
  17. #include "sbar.hpp"
  18. #include "cop.hpp"
  19. #include "nfserver.hpp"
  20. #include "lisp_gc.hpp"
  21.  
  22. #ifndef __MAC__
  23. #include <sys/stat.h>
  24. #endif
  25.  
  26. #include <time.h>
  27.  
  28. level *current_level;
  29.  
  30. game_object *level::attacker(game_object *who)
  31.   long d=0x7fffffff;
  32.   game_object *c=NULL;
  33.   view *f=the_game->first_view;
  34.   for (;f;f=f->next)
  35.   {
  36.     if (f->focus)
  37.     {
  38.       long tmp_d=abs(f->focus->x-who->x)+abs(f->focus->y-who->y);
  39.       if (tmp_d<d)
  40.       {
  41.     d=tmp_d;
  42.     c=f->focus;
  43.       }
  44.     }
  45.   }
  46.   return c; 
  47.  
  48. double level::time_taken()
  49. {
  50.   if (am_timing)
  51.   {
  52.     stop_timing();
  53.     start_timing();
  54.   }
  55.   return previous_time;
  56. }
  57.  
  58. void level::start_timing()         // reset's start_time
  59. {
  60.   start_time.get_time();
  61.   am_timing=1;
  62. }
  63.  
  64. void level::stop_timing()          // transfers all time from start_time till now to previous time
  65. {
  66.   time_marker now;
  67.   previous_time+=now.diff_time(&start_time);
  68.   am_timing=0;  
  69. }
  70.  
  71.  
  72. int level::is_attacker(game_object *who)
  73.   return who->controller()!=NULL;
  74. }
  75.  
  76.  
  77. game_object *level::main_character()
  78. {
  79.   return the_game->first_view->focus;
  80. }
  81.  
  82. void level::load_fail()
  83. {
  84.   if (map_fg)    jfree(map_fg);   map_fg=NULL;
  85.   if (map_bg)    jfree(map_bg);   map_bg=NULL;
  86.   if (Name)      jfree(Name);     Name=NULL;
  87.  
  88.   first_active=NULL;
  89.   view *f=player_list;
  90.   for (;f;f=f->next)
  91.     if (f->focus)
  92.       current_level->remove_object(f->focus);
  93.  
  94.   while (first)
  95.   {
  96.     first_active=first;
  97.     first=first->next;
  98.     if (dev_cont)
  99.       dev_cont->notify_deleted_object(first_active);
  100.     delete first_active;
  101.   }
  102.  
  103.   while (area_list)
  104.   {
  105.     area_controller *l=area_list;
  106.     area_list=area_list->next;
  107.     delete l;
  108.   }
  109.  
  110.   last=NULL;
  111.   delete_all_lights();
  112.  
  113. }
  114.  
  115. level::~level() 
  116.   load_fail();
  117.   if (attack_list) jfree(attack_list);
  118.   if (target_list) jfree(target_list);
  119.   if (block_list) jfree(block_list);
  120.   if (all_block_list) jfree(all_block_list);
  121.   if (first_name) jfree(first_name);
  122. }
  123.  
  124. void level::restart()
  125. {
  126.   view *f;
  127.   game_object *found=NULL,*o;
  128.   f=the_game->first_view;
  129.   for (o=first;f && o;o=o->next)
  130.   {
  131.     while (f && !f->focus) f=f->next;
  132.     if (f)
  133.     {
  134.       if (!strcmp(object_names[o->otype],"START"))
  135.       {
  136.     if (!found) found=o;
  137.     f->focus->x=o->x;
  138.     f->focus->y=o->y;          
  139.     f->focus->set_hp(get_ability(f->focus->otype,start_hp));
  140.     f->focus->set_state(stopped);
  141.     f=f->next;
  142.       }
  143.     }
  144.   }
  145.   while (f)
  146.   {
  147.     if (f->focus)
  148.     {
  149.       f->focus->x=found->x;
  150.       f->focus->y=found->y;          
  151.       f->focus->set_hp(get_ability(f->focus->otype,start_hp));
  152.       f->focus->set_state(stopped);      
  153.     }
  154.     f=f->next;
  155.   }
  156. }
  157.  
  158.  
  159. void level::next_focus()
  160. {
  161. /*  int i;
  162.   for (i=0;i<total_objs;i++)
  163.     if (obj[i]==the_game->first_view->focus)
  164.     {      
  165.       int tries=total_objs;
  166.       do
  167.       {
  168.     i++;
  169.     if (i==total_objs)
  170.       i=0;
  171.     the_game->first_view->focus=obj[i];
  172.       }  while ((!the_game->first_view->focus->is_playable() || 
  173.          the_game->first_view->focus->hp<=0) && tries--);
  174.       return ;
  175.     }            */  
  176. }
  177.  
  178. void level::unactivate_all()
  179. {
  180.   first_active=NULL;
  181.   game_object *o=first;
  182.   attack_total=0;  // reset the attack list
  183.   target_total=0;
  184.   block_total=0;
  185.   all_block_total=0;
  186.  
  187.   for (;o;o=o->next)
  188.     o->active=0;
  189. }
  190.  
  191.  
  192. void level::pull_actives(game_object *o, game_object *&last_active, int &t)
  193. {
  194.   int i=o->total_objects();
  195.   for (;i;i--)        // pull any linked object into active list
  196.   {
  197.     game_object *other=o->get_object(i-1);
  198.     if (!other->active)
  199.     {
  200.       other->active=1;
  201.       if (other->can_block())              // if object can block other player, keep a list for fast testing
  202.       {
  203.     add_block(other);
  204.     add_all_block(other);
  205.       } else if (other->hurtable())
  206.         add_all_block(other);
  207.  
  208.       t++;
  209.       last_active->next_active=other;
  210.       last_active=other;    
  211.       pull_actives(o,last_active,t);
  212.     }
  213.   }
  214. }
  215.  
  216. int level::add_actives(long x1, long y1, long x2, long y2)
  217. {
  218.   int t=0;
  219.   game_object *last_active=NULL;
  220.   if (first_active)
  221.     for (last_active=first_active;last_active->next_active;last_active=last_active->next_active);
  222.  
  223.   game_object *o=first;
  224.   for (;o;o=o->next)
  225.   {    
  226.     if (!o->active)
  227.     {
  228.       long xr=figures[o->otype]->rangex,
  229.            yr=figures[o->otype]->rangey;
  230.  
  231.       if (o->x+xr>=x1 && o->x-xr<=x2 && o->y+yr>=y1 && o->y-yr<=y2)
  232.       {
  233.     
  234.     if (o->can_block())              // if object can block other player, keep a list for fast testing
  235.     {
  236.       add_block(o);
  237.       add_all_block(o);
  238.     } else if (o->hurtable())
  239.           add_all_block(o);
  240.       
  241.  
  242.     o->active=1;
  243.     t++;
  244.     if (!first_active)      
  245.       first_active=o;    
  246.     else
  247.           last_active->next_active=o;
  248.     last_active=o;
  249.  
  250.     pull_actives(o,last_active,t);    
  251.       }  
  252.     }  
  253.   }
  254.   if (last_active)
  255.     last_active->next_active=NULL;
  256.   return t;
  257. }
  258.  
  259.  
  260. int level::add_drawables(long x1, long y1, long x2, long y2)
  261. {
  262.   int t=0,ft=0;
  263.   game_object *last_active=NULL;
  264.   if (first_active)
  265.   {
  266.     for (last_active=first_active;last_active->next_active;last_active=last_active->next_active);
  267.   } else ft=1;
  268.  
  269.   game_object *o=first;
  270.   for (;o;o=o->next)
  271.   {    
  272.     if (ft || !o->active)
  273.     {
  274.       long xr=figures[o->otype]->draw_rangex,
  275.       yr=figures[o->otype]->draw_rangey;
  276.  
  277.       if (o->x+xr>=x1 && o->x-xr<=x2 && o->y+yr>=y1 && o->y-yr<=y2)
  278.       {
  279.     t++;
  280.     if (!first_active)      
  281.     first_active=o;    
  282.     else
  283.     last_active->next_active=o;
  284.     last_active=o;
  285.     o->active=1;
  286.       } else if (ft) o->active=0;  // if this is the first pass, then mark objects not in this ranges as not active
  287.     }
  288.   }
  289.   if (last_active)
  290.     last_active->next_active=NULL;
  291.   return t;
  292. }
  293.  
  294.  
  295. view *level::make_view_list(int nplayers)
  296. {
  297.   int startable;
  298.   CONDITION(nplayers>0,"make_view_list with <=0 players!\n");
  299.   view *f=NULL;
  300.   int j,use_type=current_start_type;
  301.   figures[use_type]->cache_in();
  302.   game_object *o,*last_start=NULL;
  303.   int num=0;
  304.   
  305.   for (j=0,o=first;o && j<nplayers;o=o->next)
  306.   {
  307.     if (!strcmp(object_names[o->otype],"START"))
  308.     {
  309.       f=new view(create(use_type,o->x,o->y),f,num); num++;
  310.       f->focus->set_controller(f);
  311.       add_object_after(f->focus,o);
  312.       j++;
  313.       last_start=o;
  314.     }
  315.   }
  316.  
  317.   // if we couldn't find enough starts then create the rest of the players at the original start
  318.   startable=j;  // if we haven't created anyone yet, it's because we can't
  319.  
  320.   for (;j<nplayers;j++)
  321.   {
  322.     if (startable)
  323.     {
  324.       game_object *o=create(use_type,f->focus->x,f->focus->y);
  325.       f=new view(o,f,num); num++;
  326.       f->focus->set_controller(f);
  327.       add_object_after(o,last_start);
  328.     }
  329.     else 
  330.     {
  331.       f=new view(NULL,f,num); 
  332.       num++;
  333.     }
  334.   }
  335.   return f;
  336. }
  337.  
  338. void level::wall_push()
  339. {
  340.   long sx1,sy1,sx2,sy2,xv,yv;
  341.   game_object *o=first_active;
  342.   for (;o;o=o->next_active)
  343.   {
  344.     if (o->pushable())
  345.     {
  346.       o->picture_space(sx1,sy1,sx2,sy2);
  347.       xv=sx1-o->x;
  348.       yv=0;
  349.       o->try_move(o->x,o->y-1,xv,yv,1);         // check for wall pushes on the left using feet
  350.       if (xv!=sx1-o->x)                         // is the character in the wall?
  351.       {
  352.     xv=-xv;
  353.     o->try_move(o->x,o->y-1,xv,yv,1);       // see how far to the right we can push the character
  354.     o->x+=xv;
  355.       } else
  356.       {
  357.     xv=sx2-o->x;
  358.     o->try_move(o->x,o->y-1,xv,yv,1);      // now check the right of the character for a wall
  359.     if (xv!=sx2-o->x)
  360.     {
  361.       xv=-xv;
  362.       o->try_move(o->x,o->y-1,xv,yv,1);
  363.       o->x+=xv;
  364.     }
  365.       }           
  366.     }
  367.   }
  368. }
  369.  
  370.  
  371. void level::try_pushback(game_object *subject,game_object *target)
  372. {
  373.   if (subject->pushable() && target->pushable() && 
  374.       subject->state!=dead && target->state!=dead &&
  375.       subject->state!=dieing && target->state!=dieing)
  376.   {
  377.     int b1=subject->push_range(),b2=target->push_range();
  378.     if (abs(subject->x-target->x)<b1+b2)
  379.     {
  380.       long tmove=b1+b2-abs(subject->x-target->x),xv,yv=0,xv2;
  381.       if (subject->x>target->x)
  382.         xv=tmove/2;
  383.       else xv=-tmove/2;
  384.       xv2=-xv;
  385.  
  386.       subject->try_move(subject->x,subject->y,xv,yv,3);
  387.       subject->x+=xv;
  388.  
  389.       yv=0;
  390.       target->try_move(target->x,target->y,xv2,yv,3);
  391.       target->x+=xv2;     
  392.     }
  393.   }
  394. }
  395.  
  396. /*
  397. void level::check_collisions()
  398. {
  399.   game_object *target,*reciever=NULL;
  400.   long sx1,sy1,sx2,sy2,tx1,ty1,tx2,ty2,hitx,hity,
  401.       s_centerx,t_centerx;
  402.  
  403.   for (game_object *subject=first_active;subject;subject=subject->next_active)
  404.   {
  405.     subject->picture_space(sx1,sy1,sx2,sy2);   
  406.     s_centerx=subject->x_center();
  407.  
  408.     int hit=0;
  409.     reciever=NULL;
  410.     for (target=first_active;target;target=target->next_active)
  411.     {
  412.       if (target!=subject)
  413.       {
  414.     target->picture_space(tx1,ty1,tx2,ty2);
  415.  
  416.         if (!(sx2<tx1 || sx1>tx2 || sy1>ty2 || sy2<ty1))  // are they semi/overlapping?
  417.         {    
  418.       try_pushback(subject,target);
  419.       if (subject->can_hurt(target))    // see if we can hurt him before calculating
  420.       {        
  421.         t_centerx=target->x_center();
  422.         point_list *s_hit,*t_damage;
  423.                     
  424.         s_hit=subject->current_figure()->hit;      
  425.         t_damage=target->current_figure()->damage;
  426.  
  427.         unsigned char *s_dat=s_hit->data,
  428.         *t_dat;
  429.         int i,j;
  430.         for (i=(int)s_hit->tot-1;i>0 && !hit;i--)
  431.         {
  432.           for (t_dat=t_damage->data,j=(int)t_damage->tot-1;j>0 && !hit;j--)
  433.           {
  434.         long x1,y1,x2,y2,          // define the two line segments to check
  435.         xp1,yp1,xp2,yp2;
  436.  
  437.         xp1=target->x+target->tx(*t_dat);  t_dat++;          
  438.         yp1=target->y+target->ty(*t_dat);  t_dat++;
  439.         xp2=target->x+target->tx(*t_dat); 
  440.         yp2=target->y+target->ty(t_dat[1]); 
  441.  
  442.         x1=subject->x+subject->tx(s_dat[0]);  
  443.         y1=subject->y+subject->ty(s_dat[1]); 
  444.         x2=subject->x+subject->tx(s_dat[2]); 
  445.         y2=subject->y+subject->ty(s_dat[3]); 
  446.           
  447.  
  448.         // ok, now we know which line segemnts to check for intersection
  449.         // now check to see if (x1,y1-x2,y2) intercest with (xp1,yp1-xp2,yp2)
  450.         int _x2=x2,_y2=y2;          
  451.         setback_intersect(x1, y1, x2, y2, xp1, yp1, xp2, yp2,0);
  452.  
  453.  
  454.         if (x2!=_x2 || _y2!=y2)
  455.         {
  456.           reciever=target;
  457.           hitx=((x1+x2)/2+(xp1+xp2)/2)/2;
  458.           hity=((y1+y1)/2+(yp1+yp2)/2)/2;
  459.         }
  460.           } 
  461.           s_dat+=2;
  462.         }        
  463.       }
  464.     }
  465.       }  
  466.     }    
  467.     if (reciever)
  468.     {
  469.       reciever->do_damage((int)subject->current_figure()->hit_damage,subject,hitx,hity,0,0);
  470.       subject->note_attack(reciever);
  471.       hit=1;
  472.     }
  473.   }
  474. }
  475. */
  476.  
  477. game_object *level::boundary_setback(game_object *subject, long x1, long y1, long &x2, long &y2)
  478. {
  479.   game_object *l=NULL;
  480.   long tx1,ty1,tx2,ty2,t_centerx;
  481.   game_object *target=first_active;
  482.   game_object **blist=block_list;
  483.   int t=block_total;
  484.   for (;t;t--,blist++)
  485.   { 
  486.     target=*blist;
  487.     if (target!=subject && (target->total_objects()==0 || target->get_object(0)!=subject))
  488.     {
  489.       target->picture_space(tx1,ty1,tx2,ty2);
  490.       if (!((x2<tx1 && x1<tx1) || (x1>tx2 && x2>tx2) ||
  491.         (y1>ty2 && y2>ty2) || (y1<ty1 && y2<ty1)))  // are they semi/overlapping?
  492.       {         
  493.     t_centerx=target->x_center();
  494.     boundary *t_damage;
  495.     if (target->direction>0)
  496.     t_damage=target->current_figure()->f_damage;
  497.     else
  498.     t_damage=target->current_figure()->b_damage;
  499.     unsigned char *t_dat=t_damage->data,*ins=t_damage->inside;
  500.     int iter=t_damage->tot-1;
  501.     while(iter-->0)
  502.     {
  503.       long xp1=target->x+target->tx(*t_dat);  t_dat++;          
  504.       long yp1=target->y+target->ty(*t_dat);  t_dat++;
  505.       long xp2=target->x+target->tx(*t_dat); 
  506.       long yp2=target->y+target->ty(t_dat[1]); 
  507.  
  508.       // now check to see if (x1,y1-x2,y2) intercest with (xp1,yp1-xp2,yp2)
  509.       if (*ins)
  510.       {                
  511.         if (setback_intersect(x1,y1,x2,y2,xp1,yp1,xp2,yp2,1))
  512.         l=target;
  513.       }        
  514.       else
  515.       {
  516.         if (setback_intersect(x1,y1,x2,y2,xp1,yp1,xp2,yp2,-1))
  517.         l=target;
  518.       }        
  519.       ins++;
  520.       
  521.     }      
  522.       }      
  523.     }   
  524.   }
  525.   return l;       // return the last person we intersected  
  526. }
  527.  
  528.  
  529. game_object *level::all_boundary_setback(game_object *subject, long x1, long y1, long &x2, long &y2)
  530. {
  531.   game_object *l=NULL;
  532.   long tx1,ty1,tx2,ty2,t_centerx;
  533.   game_object *target=first_active;
  534.   game_object **blist=all_block_list;
  535.   int t=all_block_total;
  536.   for (;t;t--,blist++)
  537.   { 
  538.     target=*blist;
  539.     if (target!=subject && (target->total_objects()==0 || target->get_object(0)!=subject))
  540.     {
  541.       target->picture_space(tx1,ty1,tx2,ty2);
  542.       if (!((x2<tx1 && x1<tx1) || (x1>tx2 && x2>tx2) ||
  543.         (y1>ty2 && y2>ty2) || (y1<ty1 && y2<ty1)))  // are they semi/overlapping?
  544.       {         
  545.     t_centerx=target->x_center();
  546.     boundary *t_damage;
  547.     if (target->direction>0)
  548.     t_damage=target->current_figure()->f_damage;
  549.     else
  550.     t_damage=target->current_figure()->b_damage;
  551.     unsigned char *t_dat=t_damage->data,*ins=t_damage->inside;
  552.     int iter=t_damage->tot-1;
  553.     while(iter-->0)
  554.     {
  555.       long xp1=target->x+target->tx(*t_dat);  t_dat++;          
  556.       long yp1=target->y+target->ty(*t_dat);  t_dat++;
  557.       long xp2=target->x+target->tx(*t_dat); 
  558.       long yp2=target->y+target->ty(t_dat[1]); 
  559.  
  560.       // now check to see if (x1,y1-x2,y2) intercest with (xp1,yp1-xp2,yp2)
  561.       if (*ins)
  562.       {                
  563.         if (setback_intersect(x1,y1,x2,y2,xp1,yp1,xp2,yp2,1))
  564.         l=target;
  565.       }        
  566.       else
  567.       {
  568.         if (setback_intersect(x1,y1,x2,y2,xp1,yp1,xp2,yp2,-1))
  569.         l=target;
  570.       }        
  571.       ins++;      
  572.     }      
  573.       }      
  574.     }   
  575.   }
  576.   return l;       // return the last person we intersected  
  577. }
  578.  
  579.  
  580. //bFILE *rcheck=NULL,*rcheck_lp=NULL;
  581.  
  582. void level::interpolate_draw_objects(view *v)
  583. {
  584.   long old_x,old_y;
  585.   current_view=v;
  586.   
  587.   game_object *o=first_active;
  588.   for (;o;o=o->next_active)
  589.   {
  590.     old_x=o->x;
  591.     old_y=o->y;
  592.     o->x=(o->last_x+o->x)/2;
  593.     o->y=(o->last_y+o->y)/2;
  594.     o->last_x=old_x;
  595.     o->last_y=old_y;
  596.   }
  597.  
  598.   for (o=first_active;o;o=o->next_active)
  599.     o->draw();
  600.  
  601.   for (o=first_active;o;o=o->next_active)
  602.   {
  603.     o->x=o->last_x;
  604.     o->y=o->last_y;
  605.   }
  606. }
  607.  
  608. bFILE *rcheck=NULL,*rcheck_lp=NULL;
  609.  
  610. extern int sshot_fcount,screen_shot_on;
  611.  
  612. //extern long StartTime(int cnt);         //kill me
  613. //extern long DiffTime(char *name, int cnt);   //kill me
  614.  
  615. int level::tick()
  616. {
  617.  
  618.   game_object *o,*l=NULL,  // l is last, used for delete
  619.               *cur;        // cur is current object, NULL if object deletes it's self
  620.   int ret=1;
  621.  
  622.   if (profiling())
  623.     profile_reset();
  624.  
  625. /*  // test to see if demo is in sync
  626.   if (current_demo_mode()==DEMO_PLAY)
  627.   {
  628.     if (!rcheck) rcheck=open_file("rcheck","rb");
  629.     long x=rcheck->read_long();
  630.     if (x!=rand_on)
  631.       dprintf("off!\n");
  632.   } else if (current_demo_mode()==DEMO_RECORD)
  633.   {
  634.     if (!rcheck) 
  635.     {
  636.       rcheck=open_file("rcheck","wb");
  637.       rcheck_lp=open_file("rcheck.lp","wb");
  638.     }
  639.     rcheck->write_long(rand_on);
  640.   } else
  641.   {
  642.     if (rcheck)
  643.     {
  644.       delete rcheck;
  645.       rcheck=NULL;
  646.     }
  647.     if (rcheck_lp)
  648.     {
  649.       delete rcheck_lp;
  650.       rcheck_lp=NULL;
  651.     }
  652.   }*/
  653.  
  654.   if (!am_timing)
  655.     start_timing();
  656.   
  657.   for (o=first_active;o;)
  658.   {       
  659.     o->last_x=o->x;
  660.     o->last_y=o->y;
  661.     cur=o;
  662.     view *c=o->controller();
  663.     if (!(dev&SUSPEND_MODE) || c)
  664.     {
  665.       o->set_flags(o->flags()&(0xff-FLAG_JUST_HIT-FLAG_JUST_BLOCKED));
  666.  
  667.       if (c)
  668.       {      
  669.                 area_controller *a,*smallest=NULL;
  670.                 long smallest_size=0xfffffff;
  671.                 for (a=area_list;a;a=a->next)
  672.                   if (o->x>=a->x && o->y>=a->y && o->x<=a->x+a->w && o->y<=a->y+a->h)
  673.                   {
  674.                     long size=a->w*a->h;
  675.                     if (size<smallest_size)
  676.                     {
  677.                       smallest=a;
  678.                       smallest_size=size;
  679.                     }
  680.                   }
  681.  
  682.                 if (c->local_player())
  683.                 {
  684.                   if (!shutdown_lighting)       // should we initiate a lighting shutdown?
  685.                   {
  686. //                    if (massive_frame_panic>30)
  687. //                    {
  688. //                      shutdown_lighting=100;
  689. //                      shutdown_lighting_value=c->ambient;
  690. //                    }
  691.                   } else if (massive_frame_panic)  // do we need brighten towards 63?
  692.                   {
  693.                     if (shutdown_lighting_value<63)
  694.                       shutdown_lighting_value++;
  695.                   } else if (shutdown_lighting>1)        // delay for some time before turning back on
  696.                     shutdown_lighting--;
  697.                   else if (shutdown_lighting_value!=c->ambient) // do we need to lower light toward real ambient?
  698.                   {
  699.                     if (abs(shutdown_lighting_value-c->ambient)<4)
  700.                       shutdown_lighting_value=c->ambient;
  701.                     else
  702.                       if (shutdown_lighting_value<c->ambient)
  703.                           shutdown_lighting_value+=4;
  704.                     else if (shutdown_lighting_value>c->ambient)
  705.                       shutdown_lighting_value-=4;
  706.                   } else shutdown_lighting=0;                    // back to normal
  707.                 }
  708.             
  709.                 if (smallest)
  710.                   c->configure_for_area(smallest);
  711.             
  712.                 o->move(c->x_suggestion,c->y_suggestion,c->b1_suggestion|(c->b2_suggestion<<1)|
  713.                     (c->b3_suggestion<<2));
  714.             
  715.                 if (o->otype!=current_start_type)
  716.                 {
  717.                   long fmp=o->fmp();      
  718.                   int reduce=figures[o->otype]->morph_power;
  719.                   if (reduce)
  720.                   {
  721.                     fmp-=reduce;
  722.                     o->add_power(fmp>>16);
  723.                     o->set_fmp(fmp&0xffff);
  724.                     if (o->mp()<=0)
  725.                     o->morph_into(current_start_type,NULL,-1,9);
  726.                   }
  727.                 }
  728.             
  729.                 l=o;
  730.                 o=o->next_active;       
  731.       }
  732.       else if (!o->decide())      // if object returns 0, delete it... I don't like 0's :)
  733.       {
  734.                 game_object *p=o;
  735.                 o=o->next_active;
  736.                 delete_object(p);
  737.                 cur=NULL;
  738.       } else 
  739.       {
  740.                 o=o->next_active;
  741.                 l=o;
  742.       }
  743.     } else
  744.     {
  745.       o=o->next_active;
  746.       l=o;      
  747.     }
  748.  
  749.     clear_tmp();
  750.  
  751.     if (cur)
  752.     {
  753.       point_list *p=cur->current_figure()->hit;  // see if this character is on an attack frame
  754.       if (p && p->tot)
  755.         add_attacker(cur);               // if so add him to attack list for later collision detect
  756.       
  757.       if (cur->hurtable())                    // add to target list if is hurtable
  758.         add_target(cur);
  759.       
  760.     }
  761.  
  762.   }
  763.  
  764.   check_collisions();
  765. //  wall_push();
  766.  
  767.   set_tick_counter(tick_counter()+1);
  768.  
  769.   if (sshot_fcount!=-1)
  770.   {
  771.     sshot_fcount++;
  772.     if ((sshot_fcount%70)==0)
  773.     {    
  774.       char name[100];
  775.       sprintf(name,"shot%04d.pcx",screen_shot_on++);
  776.       write_PCX(screen,pal,name);
  777.     }
  778.   }
  779.  
  780.   return ret;
  781. }
  782.  
  783. void level::set_tick_counter(ulong x) 
  784.   ctick=x; 
  785. }
  786.  
  787. void level::draw_areas(view *v)
  788. {
  789.   long sx1,sy1,sx2,sy2;
  790.   area_controller *a=area_list;
  791.   for (;a;a=a->next)
  792.   {
  793.     int c1,c2;
  794.     if (a->active)
  795.     {
  796.       c1=morph_sel_frame_color;
  797.       c2=eh->bright_color();
  798.     } else 
  799.     {
  800.       c2=morph_sel_frame_color;
  801.       c1=eh->bright_color();
  802.     }
  803.     
  804.     the_game->game_to_mouse(a->x,a->y,v,sx1,sy1);
  805.     the_game->game_to_mouse(a->x+a->w,a->y+a->h,v,sx2,sy2);
  806.     screen->rectangle(sx1,sy1,sx2,sy2,c1);
  807.     screen->bar(sx1-1,sy1-1,sx1+1,sy1+1,c2);
  808.     screen->bar(sx2-1,sy2-1,sx2+1,sy2+1,c2);
  809.   }
  810. }
  811.  
  812. void level::draw_objects(view *v)
  813. {
  814.   current_view=v;
  815.   game_object *o=first_active;
  816.   if (dev&MAP_MODE)
  817.   {
  818.     for (;o;o=o->next_active)
  819.       o->map_draw();
  820.   } else
  821.   {
  822.     for (;o;o=o->next_active)
  823.       o->draw();
  824.   }
  825.  
  826.   clear_tmp();
  827. }  
  828.  
  829. void calc_bgsize(unsigned short fgw, unsigned short  fgh, unsigned short  &bgw, unsigned short  &bgh)
  830. {
  831.   bgw=fgw/ASPECT+8;
  832.   bgh=fgh/ASPECT+8;  
  833. }
  834.  
  835.  
  836. void level::set_size(int w, int h) 
  837. {
  838.   if (w*h>200000)
  839.   {
  840.     the_game->show_help(symbol_str("too_big"));
  841.     return ; 
  842.   }
  843.  
  844.   unsigned short *new_fg,*new_bg;
  845.   new_fg=(unsigned short *)jmalloc(w*h*sizeof(short),"Map fg : resized");
  846.   memset(new_fg,0,w*h*sizeof(short));
  847.  
  848.   int x,y,miny=(h<fg_height)? h : fg_height,minx=(w<fg_width)? w : fg_width;
  849.   
  850.   unsigned short nbw,nbh;
  851.   calc_bgsize(w,h,nbw,nbh);
  852.   
  853.   new_bg=(unsigned short *)jmalloc((int)nbw*(int)nbh*sizeof(short),"map bg : resized");
  854.   memset(new_bg,0,(int)nbw*(int)nbh*sizeof(short));
  855.  
  856.   for (y=0;y<miny;y++)
  857.     for (x=0;x<minx;x++)
  858.       new_fg[x+y*w]=get_fg(x,y);
  859.  
  860.   miny=(nbh<bg_height) ? nbh : bg_height;
  861.   minx=(nbw<bg_width) ? nbw : bg_width;
  862.  
  863.   for (y=0;y<miny;y++)
  864.     for (x=0;x<minx;x++)
  865.       new_bg[x+y*nbw]=get_bg(x,y);
  866.  
  867.   jfree(map_fg);
  868.   jfree(map_bg);
  869.   map_fg=new_fg;
  870.   map_bg=new_bg;
  871.   fg_width=w;
  872.   fg_height=h;
  873.   bg_height=nbh;
  874.   bg_width=nbw; 
  875.  
  876.   char msg[80];
  877.   sprintf(msg,"Level %s size now %d %d\n",name(),foreground_width(),foreground_height());
  878.   the_game->show_help(msg);
  879. }
  880.  
  881.  
  882. int locate_var(bFILE *fp, spec_directory *sd, char *str, int size)
  883. {
  884.   spec_entry *se=sd->find(str);
  885.   if (se)
  886.   {
  887.     fp->seek(se->offset,0);
  888.     if (RC_type_size(fp->read_byte())!=size)
  889.       return 0;
  890.     else return 1;
  891.   } 
  892.   return 0;
  893. }
  894.  
  895.  
  896. // load objects assumes current objects have already been disposed of
  897. void level::old_load_objects(spec_directory *sd, bFILE *fp)
  898. {
  899.   spec_entry *se=sd->find("objects");
  900.   total_objs=0;
  901.   first=last=first_active=NULL;
  902.   int i,j;
  903.   if (se)
  904.   {
  905.     fp->seek(se->offset,0);
  906.     /******************************* Read debug info ******************************/
  907.     short old_tot=fp->read_short();  
  908.     unsigned short *o_remap=(unsigned short *)jmalloc(old_tot*2,"obj remap array");    
  909.     char old_name[150];      
  910.     for (i=0;i<old_tot;i++)
  911.     {
  912.       fp->read(old_name,fp->read_byte());    // read the name
  913.       for (o_remap[i]=0xffff,j=0;j<total_objects;j++)  // check for matching current name
  914.       {
  915.     if (!strcmp(old_name,object_names[j]))
  916.           o_remap[i]=j;
  917.       }
  918.     }
  919.  
  920.  
  921.     /***************************** Read state names *********************************/
  922.     int old_stot=fp->read_short();
  923.     unsigned char *s_remap=(unsigned char *)jmalloc(old_stot,"state remap array");
  924.     for (i=0;i<old_stot;i++)
  925.     {
  926.       fp->read(old_name,fp->read_byte());
  927.       s_remap[i]=stopped;           // non exsitant states get mapped into stopped state
  928.       for (j=0;j<MAX_STATE;j++)                  // see if old state exist now
  929.     if (!strcmp(state_names[j],old_name))
  930.          s_remap[i]=j;
  931.     }
  932.     total_objs=fp->read_long();    
  933.  
  934.     se=sd->find("type");
  935.     if (se)
  936.     {
  937.       fp->seek(se->offset,0);
  938.       last=NULL;
  939.       if (fp->read_byte()==RC_S)    //  read type array, this should be type RC_S
  940.       {
  941.     for (i=0;i<total_objs;i++)
  942.     {
  943.       ushort t=fp->read_short();
  944.       game_object *p=new game_object(o_remap[t],1);
  945.       clear_tmp();
  946.       if (!first) first=p; else last->next=p;
  947.       last=p; p->next=NULL;          
  948.     }
  949.  
  950.        
  951.     se=sd->find("state");
  952.     if (se)
  953.     {
  954.       fp->seek(se->offset,0);
  955.       if (fp->read_byte()==RC_S)    //  read state array, this should be type RC_S
  956.       {
  957.         game_object *l=first;
  958.         for (i=0;i<total_objs;i++,l=l->next)
  959.         {
  960.           character_state s=(character_state)s_remap[fp->read_short()];
  961.           if (l->otype!=0xffff)
  962.           {
  963.         if (l->has_sequence((character_state)s))
  964.           l->state=s;
  965.         else l->state=stopped;
  966.         l->current_frame=0;
  967.           }
  968.         }
  969.       }
  970.     }
  971.  
  972.     int frame_var=0;
  973.     int i=0;
  974.     for (;i<TOTAL_OBJECT_VARS;i++)
  975.       if (!strcmp(object_descriptions[i].name,"cur_frame"))
  976.         frame_var=i;
  977.         
  978.     int j=0;
  979.     for (;j<default_simple.total_vars();j++)
  980.     {
  981.       spec_entry *se=sd->find(object_descriptions[j].name);
  982.       if (se)
  983.       {
  984.         fp->seek(se->offset,0);
  985.         int t=object_descriptions[j].type;
  986.         if (fp->read_byte()!=t)
  987.           dprintf("Warning : load level -> var '%s' size changed\n");
  988.         else
  989.         {
  990.           game_object *f=first;
  991.           for (;f;f=f->next)
  992.           {           
  993.         switch (t)
  994.         {
  995.           case RC_C : f->set_var(j,fp->read_byte()); break;
  996.           case RC_S : f->set_var(j,fp->read_short()); break;
  997.           case RC_L : f->set_var(j,fp->read_long()); break;
  998.         }
  999.  
  1000.         // check to make sure the frame number is not out of bounds from the time
  1001.         // it was last saved
  1002.         if (j==frame_var) 
  1003.         {
  1004.           if (f->otype!=0xffff && f->current_frame>=
  1005.               figures[f->otype]->get_sequence(f->state)->length())
  1006.             f->current_frame=0;
  1007.         }
  1008.           } 
  1009.         }        
  1010.       } else dprintf("Warning : load level -> no previous var %s\n",default_simple.var_name(j));
  1011.     }
  1012.       }
  1013.     }
  1014.     
  1015.     
  1016.  
  1017.     jfree(o_remap);
  1018.     jfree(s_remap);
  1019.   }  
  1020.   
  1021. }
  1022.  
  1023.  
  1024. // load objects assumes current objects have already been disposed of
  1025. void level::load_objects(spec_directory *sd, bFILE *fp)
  1026. {
  1027.   spec_entry *se=sd->find("object_descripitions"); 
  1028.   total_objs=0;
  1029.   first=last=first_active=NULL;
  1030.   int i,j;
  1031.   if (!se)
  1032.   {
  1033.     old_load_objects(sd,fp);
  1034.     return ;
  1035.   }
  1036.   else if (se)
  1037.   {
  1038.     fp->seek(se->offset,0);
  1039.     short old_tot=fp->read_short();
  1040.     se=sd->find("describe_names");
  1041.     if (!se || !old_tot)
  1042.       return ;
  1043.  
  1044.     unsigned short *o_remap=(unsigned short *)jmalloc(old_tot*2,"obj remap array");    
  1045.     unsigned short *o_backmap=(unsigned short *)jmalloc(total_objects*2,"obj remap array");    
  1046.     memset(o_backmap,0xff,total_objects*2);
  1047.     char old_name[150];      
  1048.     for (i=0;i<old_tot;i++)
  1049.     {
  1050.       fp->read(old_name,fp->read_byte());    // read the name
  1051.       for (o_remap[i]=0xffff,j=0;j<total_objects;j++)  // check for matching current name
  1052.       {
  1053.     if (!strcmp(old_name,object_names[j]))
  1054.     {
  1055.           o_remap[i]=j;
  1056.       o_backmap[j]=i;
  1057.     }
  1058.       }
  1059.     }    
  1060.  
  1061.     se=sd->find("describe_states");
  1062.     if (!se) { jfree(o_remap); jfree(o_backmap); return ; }
  1063.     short **s_remap=(short **)jmalloc(old_tot*sizeof(short *),"big state remap array");
  1064.     short *s_remap_totals=(short *)jmalloc(old_tot*sizeof(short),"big state rmp totals");
  1065.     fp->seek(se->offset,0);
  1066.     int i=0;
  1067.     for (;i<old_tot;i++)
  1068.     {
  1069.       short t=fp->read_short();
  1070.       s_remap_totals[i]=t;
  1071.       if (t)
  1072.       {
  1073.         s_remap[i]=(short *)jmalloc(t*sizeof(short),"state remap");
  1074.     int j=0;
  1075.     for (;j<t;j++)
  1076.       *(s_remap[i]+j)=stopped;    // if no remap found, then go to stopped state
  1077.       }
  1078.       else s_remap[i]=0;
  1079.  
  1080.       int j=0;
  1081.       for (;j<t;j++)
  1082.       {
  1083.     fp->read(old_name,fp->read_byte());
  1084.     int new_type=o_remap[i];    
  1085.     if (new_type<total_objects)     // make sure old object still exsist
  1086.     {
  1087.       int k=0;
  1088.       for (;k<figures[new_type]->ts;k++)
  1089.       {
  1090.         if (figures[new_type]->seq[k] &&
  1091.            !strcmp(lstring_value(symbol_name(figures[new_type]->seq_syms[k])),old_name))
  1092.         *(s_remap[i]+j)=k;
  1093.       }
  1094.     }
  1095.       }
  1096.     }
  1097.  
  1098.     short **v_remap=NULL;
  1099.     short *v_remap_totals=NULL;
  1100.     int load_vars=1;
  1101.     se=sd->find("describe_lvars");
  1102.     if (se)
  1103.     {
  1104.       v_remap=(short **)jmalloc(old_tot*sizeof(short *),"big var remap array");
  1105.       v_remap_totals=(short *)jmalloc(old_tot*sizeof(short),"big var rmp totals");
  1106.  
  1107.       fp->seek(se->offset,0);
  1108.       int i=0;
  1109.       for (;i<old_tot;i++)
  1110.       {
  1111.     short t=fp->read_short();
  1112.     v_remap_totals[i]=t;
  1113.     if (t)
  1114.     {
  1115.       v_remap[i]=(short *)jmalloc(t*sizeof(short),"var remap");
  1116.       memset(v_remap[i],0xff,t*sizeof(short));
  1117.     } else { v_remap[i]=NULL; }
  1118.     int j=0;
  1119.     for (;j<t;j++)
  1120.     {
  1121.       fp->read(old_name,fp->read_byte());
  1122.       int new_type=o_remap[i];
  1123.       if (new_type!=0xffff)        // make sure old object still exsist
  1124.       {
  1125.         int k=0;
  1126.         for (;k<figures[new_type]->tiv;k++)
  1127.         {
  1128.           if (figures[new_type]->vars[k])
  1129.           {
  1130.         if (!strcmp(lstring_value(symbol_name(figures[new_type]->vars[k])),old_name))
  1131.           *(v_remap[i]+j)=figures[new_type]->var_index[k];
  1132.           }
  1133.         }
  1134.       }
  1135.     }
  1136.       }
  1137.       load_vars=1;
  1138.     }
  1139.     
  1140.     se=sd->find("object_list");
  1141.     if (se)
  1142.     {
  1143.       total_objs=fp->read_long();    
  1144.  
  1145.       se=sd->find("type");
  1146.       if (se)
  1147.       {
  1148.     fp->seek(se->offset,0);
  1149.     last=NULL;
  1150.     if (fp->read_byte()==RC_S)    //  read type array, this should be type RC_S
  1151.     {
  1152.       int i=0;
  1153.       for (;i<total_objs;i++)
  1154.       {
  1155.         ushort t=fp->read_short();
  1156.         game_object *p=new game_object(o_remap[t],1);
  1157.         clear_tmp();
  1158.         if (!first) first=p; else last->next=p;
  1159.         last=p; p->next=NULL;          
  1160.       }
  1161.        
  1162.       se=sd->find("state");
  1163.       if (se)
  1164.       {
  1165.         fp->seek(se->offset,0);
  1166.         if (fp->read_byte()==RC_S)    //  read state array, this should be type RC_S
  1167.         {
  1168.           game_object *l=first;
  1169.           for (i=0;i<total_objs;i++,l=l->next)
  1170.           {
  1171.         int st=fp->read_short();
  1172.         if (l->otype==0xffff)
  1173.           l->state=stopped;
  1174.         else
  1175.         {
  1176.           character_state s=(character_state)(*(s_remap[o_backmap[l->otype]]+st));
  1177.           if (l->has_sequence((character_state)s))
  1178.                 l->state=s;
  1179.           else l->state=stopped;
  1180.           l->current_frame=0;
  1181.         }
  1182.           }
  1183.         }
  1184.       }
  1185.     
  1186.       se=sd->find("lvars");
  1187.       if (se && load_vars)
  1188.       {
  1189.         fp->seek(se->offset,0);
  1190.         int abort=0;
  1191.         game_object *o=first;
  1192.         for (;o && !abort;o=o->next)
  1193.         {
  1194.           short ot=fp->read_short();
  1195.           int k=0;
  1196.           for (;k<ot;k++)
  1197.           {
  1198.         if (fp->read_byte()!=RC_L) abort=1;
  1199.         else
  1200.         {
  1201.           long v=fp->read_long();
  1202.           if (o->otype!=0xffff)     // non-exstant object
  1203.           {
  1204.             int remap=*(v_remap[o_backmap[o->otype]]+k);
  1205.             if (remap!=-1 && figures[o->otype]->tiv>=k)
  1206.             {
  1207.               o->lvars[remap]=v;       
  1208.             }
  1209.           }
  1210.         }
  1211.           }
  1212.         }
  1213.       }
  1214.  
  1215.       int frame_var=0;
  1216.       for (i=0;i<TOTAL_OBJECT_VARS;i++)
  1217.         if (!strcmp(object_descriptions[i].name,"cur_frame"))
  1218.           frame_var=i;
  1219.         
  1220.  
  1221.       int j=0;
  1222.       for (;j<default_simple.total_vars();j++)
  1223.       {
  1224.         spec_entry *se=sd->find(object_descriptions[j].name);
  1225.         if (se)
  1226.         {
  1227.           fp->seek(se->offset,0);
  1228.           int t=object_descriptions[j].type;
  1229.           if (fp->read_byte()!=t)
  1230.             dprintf("Warning : load level -> var '%s' size changed\n");
  1231.           else
  1232.           {
  1233.         game_object *f=first;
  1234.         for (;f;f=f->next)
  1235.         {           
  1236.           switch (t)
  1237.           {
  1238.             case RC_C : 
  1239.             { f->set_var(j,fp->read_byte()); } break;
  1240.             case RC_S : 
  1241.             { f->set_var(j,fp->read_short()); } break;
  1242.             case RC_L : 
  1243.             { f->set_var(j,fp->read_long()); } break;
  1244.           }
  1245.           
  1246.           // check to make sure the frame number is not out of bounds from the time
  1247.           // it was last saved
  1248.           if (j==frame_var) 
  1249.           {
  1250.             if (f->otype!=0xffff && f->current_frame>=
  1251.             figures[f->otype]->get_sequence(f->state)->length())
  1252.             f->current_frame=0;
  1253.           }
  1254.         } 
  1255.           }        
  1256.         } else dprintf("Warning : load level -> no previous var %s\n",default_simple.var_name(j));
  1257.       }
  1258.     }
  1259.       }
  1260.     }
  1261.     
  1262.     int k=0;
  1263.     for (;k<old_tot;k++)
  1264.     {
  1265.       if (s_remap_totals[k])
  1266.         jfree(s_remap[k]);
  1267.     }
  1268.  
  1269.     int l=0;
  1270.     for (;l<old_tot;l++)
  1271.     {
  1272.       if (v_remap_totals[l])
  1273.         jfree(v_remap[l]);
  1274.     }
  1275.     jfree(v_remap_totals);
  1276.     jfree(s_remap_totals);
  1277.     jfree(o_remap);
  1278.     jfree(o_backmap);
  1279.     jfree(s_remap);
  1280.     jfree(v_remap);
  1281.   }  
  1282.   
  1283. }
  1284.  
  1285. level::level(spec_directory *sd, bFILE *fp, char *lev_name)
  1286. {
  1287.   am_timing=0;
  1288.   previous_time=0;
  1289.  
  1290.   spec_entry *e;
  1291.   area_list=NULL;
  1292.  
  1293.   attack_list=NULL;
  1294.   attack_list_size=attack_total=0;
  1295.  
  1296.   target_list=NULL;
  1297.   target_list_size=target_total=0;
  1298.  
  1299.   block_list=NULL;
  1300.   block_list_size=block_total=0;
  1301.  
  1302.   all_block_list=NULL;
  1303.   all_block_list_size=all_block_total=0;
  1304.   first_name=NULL;
  1305.  
  1306.   the_game->need_refresh();
  1307.  
  1308.   char cmd[100];
  1309.   sprintf(cmd,symbol_str("loading"),lev_name);
  1310.   stack_stat stat(cmd);
  1311.   Name=strcpy((char *)jmalloc(strlen(lev_name)+1,"lev name"),lev_name);
  1312.  
  1313.   e=sd->find("first name");
  1314.   if (e)
  1315.   {
  1316.     fp->seek(e->offset,0);
  1317.     int len=fp->read_byte();   // read the length of the string
  1318.     first_name=(char *)jmalloc(len,"level first name");
  1319.     fp->read(first_name,len);    // read the string
  1320.   } else
  1321.   {
  1322.     first_name=(char *)jmalloc(strlen(Name)+1,"level first name");    
  1323.     strcpy(first_name,Name);
  1324.   }
  1325.  
  1326.   e=sd->find("fgmap");
  1327.   int no_fg=0,no_bg=0;
  1328.  
  1329.   if (e)
  1330.   {    
  1331.     fp->seek(e->offset,0);
  1332.     fg_width=fp->read_long();
  1333.     fg_height=fp->read_long();
  1334.     map_fg=(unsigned short *)jmalloc(2*fg_width*fg_height,"Map fg : loaded");
  1335.     fp->read((char *)map_fg,2*fg_width*fg_height);
  1336.     int t=fg_width*fg_height;
  1337.     unsigned short *map=map_fg;
  1338.     while (t) { *map=lstl(*map); map++; t--; }
  1339.   } else
  1340.   {
  1341.     the_game->show_help("Warning foreground map missing");
  1342.     no_fg=1;
  1343.   }
  1344.   stat_man->update(5);
  1345.  
  1346.   e=sd->find("bgmap");
  1347.   if (e)
  1348.   {
  1349.     fp->seek(e->offset,0);
  1350.     bg_width=fp->read_long();
  1351.     bg_height=fp->read_long();
  1352.     map_bg=(unsigned short *)jmalloc(2*bg_width*bg_height,"Map bg : loaded");
  1353.     fp->read((char *)map_bg,2*bg_width*bg_height);
  1354.     int t=bg_width*bg_height;
  1355.     unsigned short *map=map_bg;
  1356.     while (t) { *map=lstl(*map); map++; t--; } 
  1357.   } else
  1358.   {
  1359.     the_game->show_help("Warning background map missing");
  1360.     no_bg=1;
  1361.   }
  1362.  
  1363.   if (no_fg && !no_bg)
  1364.   {
  1365.     fg_width=bg_width;
  1366.     fg_height=bg_height;
  1367.     map_fg=(unsigned short *)jmalloc(2*fg_width*fg_height,"Map fg : loaded");
  1368.     memset(map_fg,0,2*fg_width*fg_height);
  1369.   }
  1370.  
  1371.   if (no_bg)
  1372.   {
  1373.     bg_width=fg_width/8+8;
  1374.     bg_height=fg_height/8+8;
  1375.     map_bg=(unsigned short *)jmalloc(2*bg_width*bg_height,"Map bg : loaded");
  1376.     memset(map_bg,0,2*bg_width*bg_height);
  1377.   }
  1378.   stat_man->update(10);
  1379.  
  1380.   /***************** Check map for non exsistant tiles **************************/
  1381.   long i,j,w;
  1382.   unsigned short *m;  
  1383.   spec_entry *load_all=sd->find("player_info");
  1384.   for (i=0,w=fg_width*fg_height,m=map_fg;i<w;i++,m++)
  1385.   {
  1386.     if (!load_all)
  1387.       (*m)=(*m)&(~0x8000);    // clear the has-seen bit on the tile
  1388.  
  1389.     if (fgvalue(*m)>=nforetiles || foretiles[fgvalue(*m)]<0) 
  1390.       *m=0;  
  1391.   }
  1392.  
  1393.   for (i=0,w=bg_width*bg_height,m=map_bg;i<w;i++,m++)
  1394.   {
  1395.     if ( (bgvalue(*m)>=nbacktiles) || backtiles[bgvalue(*m)]<0) 
  1396.        *m=0;  
  1397.   }
  1398.  
  1399.   load_options(sd,fp);
  1400.   stat_man->update(15);
  1401.  
  1402. //  first=first_active=last=NULL;
  1403.   load_objects(sd,fp);
  1404.   stat_man->update(25);
  1405.  
  1406.   object_node *players,*objs;
  1407.   players=make_player_onodes();
  1408.   objs=make_not_list(players); 
  1409.  
  1410.  
  1411.  
  1412.   read_lights(sd,fp,lev_name);
  1413.   load_links(fp,sd,objs,players);
  1414.   int players_got_loaded=load_player_info(fp,sd,objs);
  1415.  
  1416.  
  1417.   game_object *l=first;
  1418.   for (;l;)
  1419.   {
  1420.     game_object *p=l;
  1421.     l=l->next;
  1422.     if (p->otype==0xffff || p->x<0 || p->y<0)
  1423.       delete_object(p);
  1424.   }
  1425.  
  1426.   load_cache_info(sd,fp);
  1427.  
  1428.   if (!players_got_loaded)
  1429.   {
  1430.     level *old=current_level;
  1431.     current_level=this;
  1432.    
  1433.     object_node *list=NULL;
  1434.     list=make_not_list(list);     // create a list of the object list in case objects change positions
  1435.  
  1436.     object_node *ln=list;
  1437.     for (;ln;ln=ln->next)
  1438.       ln->me->reload_notify();
  1439.     delete_object_list(list);
  1440.  
  1441.     current_level=old;
  1442.  
  1443.     insert_players();
  1444.   }
  1445.  
  1446.   delete_object_list(players);
  1447.   delete_object_list(objs);
  1448.  
  1449. }
  1450.  
  1451.  
  1452. /*
  1453.    [object_descriptions] 2 total_type
  1454.    for(1..total_types)
  1455.    {
  1456.      ["object_names"]  1,(name)
  1457.  
  1458.      ["object_states"]  2(total),<2=number,1,name>
  1459.  
  1460.      ["object_lvars"]   2(total),<1(type),1,name>   
  1461.    }
  1462.  
  1463.   [object_list]
  1464.    4 total_objects    
  1465.    for(1..total_objects)
  1466.    {
  1467.      ["type"]
  1468.      ["state"]
  1469.      ["lvars"]
  1470.      ...
  1471.    }
  1472.  
  1473. */
  1474.  
  1475.  
  1476. void get_prof_assoc_filename(char *filename, char *prof_filename)
  1477. {
  1478.   char *s1,*s2,*dot=NULL;
  1479.   for (s1=filename,s2=prof_filename,dot=NULL;*s1;s1++,s2++)
  1480.   {
  1481.     *s2=*s1;
  1482.     if (*s1=='.') dot=s2;    
  1483.   }
  1484.   if (dot) s2=dot+1;
  1485.  
  1486.   *(s2++)='c'; 
  1487.   *(s2++)='p'; 
  1488.   *(s2++)='f'; 
  1489.   *s2=0;
  1490. }
  1491.  
  1492. void level::level_loaded_notify()
  1493. {
  1494.   char *n;
  1495.   if (first_name)
  1496.     n=first_name;
  1497.   else
  1498.     n=name();
  1499.   if (strstr(n,"levels/level"))
  1500.   {
  1501.     char nm[100];
  1502.     sprintf(nm,"music/abuse%c%c.hmi",n[12],n[13]);
  1503.     bFILE *fp=open_file(nm,"rb");
  1504.     if (fp->open_failure())
  1505.     {
  1506.       delete fp;
  1507.     }
  1508.     else
  1509.     {
  1510.       if (current_song) { current_song->stop(); delete current_song; }
  1511.  
  1512.       delete fp;
  1513.       current_song=new song(nm);
  1514.       current_song->play(music_volume);
  1515.     }
  1516.   }
  1517.   
  1518. /*  if (DEFINEDP(symbol_function(l_level_loaded)))
  1519.   {
  1520.     int sp=current_space;
  1521.     current_space=PERM_SPACE;
  1522.  
  1523.     void *arg_list=NULL;
  1524.     p_ref r1(arg_list);
  1525.     push_onto_list(new_lisp_string(n),arg_list);
  1526.     eval_function((lisp_symbol *)l_level_loaded,arg_list);
  1527.  
  1528.     current_space=sp;
  1529.   } */
  1530. }
  1531.  
  1532.  
  1533. bFILE *level::create_dir(char *filename, int save_all,
  1534.              object_node *save_list, object_node *exclude_list)
  1535. {
  1536.   spec_directory sd;
  1537.   sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"Copyright 1995 Crack dot Com, All Rights reserved",NULL,0,0));
  1538.   if (first_name)
  1539.     sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"first name",NULL,strlen(first_name)+2,0));
  1540.     
  1541.  
  1542.  
  1543.   sd.add_by_hand(new spec_entry(SPEC_GRUE_FGMAP,"fgmap",NULL,4+4+fg_width*fg_height*2,0));
  1544.   sd.add_by_hand(new spec_entry(SPEC_GRUE_BGMAP,"bgmap",NULL,4+4+bg_width*bg_height*2,0));
  1545.   sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"bg_scroll_rate",NULL,1+4*4,0));
  1546.  
  1547.   int ta=0;
  1548.   area_controller *a=area_list;
  1549.   for (;a;a=a->next) ta++;
  1550.  
  1551.   sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"area_list.v1",NULL,1+ta*(4*11)+4,0));
  1552.  
  1553.   sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"tick_counter",NULL,1+4,0));
  1554.  
  1555.  
  1556.  
  1557.   // how many object types are we goint to save, use a short to specify how many
  1558.   sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"object_descripitions",NULL,2,0));
  1559.  
  1560.  
  1561.   int size=0;
  1562.   int i=0;
  1563.   for (;i<total_objects;i++)       // now save the names of the objects so if ordering
  1564.     size+=1+strlen(object_names[i])+1;    // changes in future versions we can adjust in load
  1565.   sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"describe_names",NULL,size,0));
  1566.  
  1567.  
  1568.   size=0;                                
  1569.   for (i=0;i<total_objects;i++) 
  1570.   {
  1571.     size+=2;  // total number of states
  1572.     int j=0;
  1573.     for (;j<figures[i]->ts;j++)
  1574.       if (figures[i]->seq[j])
  1575.         size+=1+strlen(lstring_value(symbol_name(figures[i]->seq_syms[j])))+1;
  1576.   }
  1577.   sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"describe_states",NULL,size,0));
  1578.  
  1579.  
  1580.  
  1581.   size=0;
  1582.   for (i=0;i<total_objects;i++) 
  1583.   {
  1584.     size+=2;  // total number of variables
  1585.     int j=0;
  1586.     for (;j<figures[i]->tiv;j++)
  1587.       if (figures[i]->vars[j])
  1588.         size+=1+strlen(lstring_value(symbol_name(figures[i]->vars[j])))+1;
  1589.   }
  1590.   sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"describe_lvars",NULL,size,0));
  1591.  
  1592.  
  1593.  
  1594.   // how many objects are we goint to save, use a long to specify how many
  1595.   sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"object_list",NULL,4,0)); 
  1596.   
  1597.   long t=0;
  1598.   object_node *o=save_list;
  1599.   for (;o;o=o->next)
  1600.     t++;
  1601.  
  1602.   // type and state aren't normal records because they will be remapped on loading
  1603.   sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"type",NULL,1+2*t,0));
  1604.   sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"state",NULL,1+2*t,0));
  1605.  
  1606.  
  1607.   // now save all the lvars for each object
  1608.   for (size=0,o=save_list;o;o=o->next)
  1609.     size+=figures[o->me->otype]->tv*5+2;
  1610.   sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"lvars",NULL,size,0));
  1611.  
  1612.  
  1613.   for (i=0;i<TOTAL_OBJECT_VARS;i++)
  1614.     sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,object_descriptions[i].name,NULL,1+
  1615.               RC_type_size(object_descriptions[i].type)*t,0));
  1616.  
  1617.   add_light_spec(&sd,Name);
  1618.  
  1619.  
  1620.   sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"object_links",NULL,1+4+total_object_links(save_list)*8,0));
  1621.   sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"light_links",NULL,1+4+total_light_links(save_list)*8,0));
  1622.  
  1623.   if (save_all)
  1624.   {
  1625.     t=0;
  1626.     view *v=player_list;
  1627.     for (;v;v=v->next) t++; 
  1628.     sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"player_info",NULL,t*4+4,0));
  1629.  
  1630.     int tv=total_view_vars();
  1631.     int i=0;
  1632.     for (;i<tv;i++)
  1633.       sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,get_view_var_name(i),NULL,1+4*t,0));
  1634.     sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"random_start",NULL,5,0));
  1635.  
  1636.     sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"weapon_array",NULL,1+4+total_weapons*4*t,0));
  1637.  
  1638.     int name_len=0;
  1639.     for (v=player_list;v;v=v->next)
  1640.       name_len+=strlen(v->name)+2;
  1641.     sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"player_names",NULL,name_len,0));
  1642.     sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"play_time",NULL,8,0));
  1643.  
  1644.     sd.add_by_hand(new spec_entry(SPEC_IMAGE,"thumb nail",NULL,4+160*(100+eh->font()->height()*2),0));
  1645.  
  1646.  
  1647.   }
  1648.  
  1649.   sd.calc_offsets();
  1650.   bFILE *fp=sd.write(filename);
  1651.   sd.delete_entries();   // if the directory was created by hand instead of by file
  1652.   return fp;
  1653. }
  1654.  
  1655. void scale_put(image *im, image *screen, int x, int y, short new_width, short new_height);
  1656.  
  1657. void level::write_thumb_nail(bFILE *fp, image *im)
  1658. {
  1659.   image *i=new image(160,100+eh->font()->height()*2);
  1660.   i->clear();
  1661.   scale_put(im,i,0,0,160,100);
  1662.   char *name_start=first_name,*n=first_name;
  1663.   for (;*n;n++)
  1664.     if (*n=='/' || *n=='\\')
  1665.       name_start=n+1;
  1666.   
  1667.  
  1668. #ifdef __MAC__
  1669.   if (Name)
  1670.     eh->font()->put_string(i,80-strlen(name_start)*eh->font()->width()/2,100,name_start);
  1671.  
  1672. #else
  1673.   if (first_name)
  1674.     eh->font()->put_string(i,80-strlen(name_start)*eh->font()->width()/2,100,name_start);
  1675.  
  1676.   time_t t;
  1677.   t=time(NULL);
  1678.   char buf[80];
  1679.  
  1680.   strftime(buf,80,"%T %A %B %d",localtime(&t));  
  1681.   eh->font()->put_string(i,80-strlen(buf)*eh->font()->width()/2,100+eh->font()->height(),buf);
  1682. #endif
  1683.  
  1684.   fp->write_short(i->width());
  1685.   fp->write_short(i->height());
  1686.   int y=0;
  1687.   for (;y<i->height();y++)
  1688.     fp->write(i->scan_line(y),i->width());
  1689.  
  1690.   delete i;
  1691. }
  1692.  
  1693. void level::write_player_info(bFILE *fp, object_node *save_list)
  1694. {
  1695.   long t=0;
  1696.   view *v=player_list;
  1697.   for (;v;v=v->next) t++; 
  1698.   fp->write_long(t);
  1699.  
  1700.   for (v=player_list;v;v=v->next)
  1701.     fp->write_long(object_to_number_in_list(v->focus,save_list));
  1702.  
  1703.   int tv=total_view_vars();
  1704.   int i=0;
  1705.   for (;i<tv;i++)
  1706.   {
  1707.     fp->write_byte(RC_L);
  1708.     for (v=player_list;v;v=v->next)
  1709.       fp->write_long(v->get_view_var_value(i));
  1710.   }
  1711.  
  1712.   fp->write_byte(RC_L);
  1713.   fp->write_long(rand_on);
  1714.  
  1715.   fp->write_byte(RC_L);
  1716.   fp->write_long(total_weapons);
  1717.   for (v=player_list;v;v=v->next)
  1718.     for (i=0;i<total_weapons;i++)
  1719.       fp->write_long(v->weapons[i]);
  1720.  
  1721.   for (v=player_list;v;v=v->next)
  1722.   {
  1723.     int len=strlen(v->name)+1;
  1724.     fp->write_byte(len);
  1725.     fp->write(v->name,len);
  1726.   }
  1727.  
  1728.  
  1729.   if (am_timing)
  1730.   {
  1731.     stop_timing();
  1732.     start_timing();
  1733.   }
  1734.  
  1735.   fp->write_double(previous_time);
  1736. }
  1737.  
  1738.  
  1739. int level::load_player_info(bFILE *fp, spec_directory *sd, object_node *save_list)
  1740. {
  1741.   int ret;
  1742.   spec_entry *se=sd->find("player_info");
  1743.   if (se)
  1744.   {
  1745.     fp->seek(se->offset,0);
  1746.  
  1747.     int set_first_view=0;
  1748.     if (the_game->first_view==player_list) set_first_view=1;
  1749.     int my_player_number=-1;
  1750.  
  1751.     view *v=player_list;
  1752.     for (;v;v=v->next)
  1753.     { v->suggest.send_view=0;
  1754.       v->suggest.send_weapon_change=0;
  1755.     }
  1756.  
  1757.     for (v=player_list;v;v=v->next)
  1758.       if (v->local_player()) 
  1759.          my_player_number=v->player_number;
  1760.  
  1761.     while (player_list)    // delete all of the views (they will get recreated)
  1762.     {
  1763.       v=player_list;
  1764.       if (v->focus)
  1765.       {
  1766.         if (v->focus->controller())
  1767.          v->focus->set_controller(NULL);
  1768.                 delete v->focus;
  1769.       }
  1770.  
  1771.       player_list=player_list->next;
  1772.       delete v;
  1773.     }
  1774.  
  1775.     long total_players=fp->read_long();
  1776.     view *last;
  1777.     int i=0;
  1778.     for (;i<total_players;i++)    
  1779.     {
  1780.       game_object *o=number_to_object_in_list(fp->read_long(),save_list);
  1781.       v=new view(o,NULL,0);
  1782.       if (o) o->set_controller(v);
  1783.       if (player_list)
  1784.         last->next=v;
  1785.       else player_list=v;
  1786.       last=v;
  1787.     }
  1788.     if (set_first_view)
  1789.       the_game->first_view=player_list;
  1790.     
  1791.     for (i=0;i<total_view_vars();i++)
  1792.     {
  1793.       char *find_name=get_view_var_name(i);
  1794.       se=sd->find(find_name);
  1795.  
  1796.       if (se)
  1797.       {
  1798.                 fp->seek(se->offset,0);
  1799.                 if (fp->read_byte()==RC_L)
  1800.                 {
  1801.                   for (v=player_list;v;v=v->next)
  1802.                         v->set_view_var_value(i,fp->read_long());
  1803.                 }
  1804.       } else 
  1805.       {
  1806.                 for (v=player_list;v;v=v->next)
  1807.                 v->set_view_var_value(i,0);
  1808.       }
  1809.     }
  1810.  
  1811.     se=sd->find("random_start");      // start of index into random table
  1812.     if (se)
  1813.     {
  1814.       fp->seek(se->offset,0);
  1815.       if (fp->read_byte()==RC_L)
  1816.         rand_on=fp->read_long();
  1817.     } else rand_on=0;
  1818.  
  1819.     se=sd->find("weapon_array");
  1820.     if (se)
  1821.     {
  1822.       fp->seek(se->offset,0);
  1823.       if (fp->read_byte()==RC_L)
  1824.       {
  1825.                 long m=fp->read_long();  // read how many weapons exsisted when last saved
  1826.                 int i;
  1827.                 for (v=player_list;v;v=v->next)      
  1828.                 {
  1829.                   for (i=0;i<m;i++)
  1830.                   {
  1831.                     long x=fp->read_long();
  1832.                     if (i<total_weapons)
  1833.                     {
  1834.                       v->weapons[i]=x;
  1835.                       v->last_weapons[i]=x;
  1836.                     }
  1837.                   }
  1838.                 }
  1839.       }
  1840.     }  else 
  1841.     { 
  1842.       for (v=player_list;v;v=v->next)      
  1843.       {
  1844.                 memset(v->last_weapons,0xff,total_weapons*sizeof(long));
  1845.                 memset(v->weapons,0xff,total_weapons*sizeof(long));
  1846.       }
  1847.     }
  1848.  
  1849.     se=sd->find("player_names");
  1850.     if (se)
  1851.     {
  1852.       fp->seek(se->offset,0);
  1853.       for (v=player_list;v;v=v->next)      
  1854.       {
  1855.     uchar len=fp->read_byte();
  1856.     fp->read(v->name,len);
  1857.       }
  1858.     }
  1859.  
  1860.  
  1861.     se=sd->find("play_time");
  1862.     if (se)
  1863.     {
  1864.       fp->seek(se->offset,0);
  1865.       previous_time=fp->read_double();    
  1866.     } else
  1867.       previous_time=0;
  1868.  
  1869.  
  1870.     start_timing();
  1871.  
  1872.     ret=1;
  1873.     recalc_local_view_space();
  1874.     
  1875.   } else 
  1876.   {
  1877.     void *fun=make_find_symbol("set_player_defaults");
  1878.     if (DEFINEDP(symbol_function(fun)))
  1879.     {      
  1880.       view *f;
  1881.       game_object *o=current_object;
  1882.       for (f=player_list;f;f=f->next)
  1883.       {
  1884.     if (f->focus)
  1885.     {
  1886.       current_object=f->focus;
  1887.       void *m=mark_heap(TMP_SPACE);
  1888.       eval_function((lisp_symbol *)fun,NULL);
  1889.       restore_heap(m,TMP_SPACE);
  1890.     }
  1891.       }    
  1892.       current_object=o;
  1893.     }
  1894.     ret=0;
  1895.   }
  1896.  
  1897.   view *vw;
  1898.   for (vw=player_list;vw;vw=vw->next)
  1899.   {
  1900.     if (total_weapons && !vw->has_weapon(vw->current_weapon))
  1901.     {
  1902.       vw->suggest.send_weapon_change=1;
  1903.       vw->suggest.new_weapon=0;      
  1904.     }
  1905.   }
  1906.  
  1907.   return ret;
  1908. }
  1909.  
  1910.  
  1911. void level::write_objects(bFILE *fp, object_node *save_list)
  1912. {
  1913.   // record information in the file about what the data structures look like
  1914.   // right now, so if they change later, they don't get get screwed up
  1915.   fp->write_short(total_objects);   // mark how many objects we know about right now  
  1916.  
  1917.   int i=0;
  1918.   for (;i<total_objects;i++)   // loop through all the object types we know of
  1919.   {    
  1920.     fp->write_byte(strlen(object_names[i])+1);                    // sizeof name    
  1921.     fp->write(object_names[i],strlen(object_names[i])+1);      // write object name
  1922.   }
  1923.     
  1924.  
  1925.   // write state numbers and names for each object
  1926.   for (i=0;i<total_objects;i++)
  1927.   {
  1928.     int total=0;
  1929.     int j=0;
  1930.     for (;j<figures[i]->ts;j++)
  1931.       if (figures[i]->seq[j]) total++;
  1932.     fp->write_short(total);
  1933.  
  1934.     for (j=0;j<figures[i]->ts;j++)
  1935.       if (figures[i]->seq[j])
  1936.       {
  1937.     char *state_name=lstring_value(symbol_name(figures[i]->seq_syms[j]));
  1938.     fp->write_byte(strlen(state_name)+1);
  1939.     fp->write(state_name,strlen(state_name)+1);
  1940.       }
  1941.   }
  1942.  
  1943.   
  1944.   // write object lvar names
  1945.   for (i=0;i<total_objects;i++)
  1946.   {
  1947.     fp->write_short(figures[i]->tv);
  1948.     int j,x;
  1949.     
  1950.     for (x=0;x<figures[i]->tv;x++)
  1951.     {
  1952.       for (j=0;j<figures[i]->tiv;j++)
  1953.       {
  1954.         if (figures[i]->vars[j] && figures[i]->var_index[j]==x)
  1955.     {
  1956.       char *var_name=lstring_value(symbol_name(figures[i]->vars[j]));
  1957.       fp->write_byte(strlen(var_name)+1);
  1958.       fp->write(var_name,strlen(var_name)+1);
  1959.     }
  1960.       }
  1961.     }
  1962.   }
  1963.   
  1964.   long t=0;
  1965.   object_node *o=save_list;
  1966.   for (;o;o=o->next) t++;
  1967.   fp->write_long(t);
  1968.  
  1969.  
  1970.   fp->write_byte(RC_S);                                    // save type info for each record
  1971.   for (o=save_list;o;o=o->next) fp->write_short(o->me->type());    
  1972.  
  1973.   fp->write_byte(RC_S);                                    // save state info for each record
  1974.   for (o=save_list;o;o=o->next) fp->write_short(o->me->reduced_state());
  1975.  
  1976.   for (o=save_list;o;o=o->next)                            // save lvars
  1977.   {
  1978.     fp->write_short(figures[o->me->otype]->tv);
  1979.     for (i=0;i<figures[o->me->otype]->tv;i++) 
  1980.     {
  1981.       fp->write_byte(RC_L);                           // for now the only type allowed is long
  1982.       fp->write_long(o->me->lvars[i]);
  1983.     }
  1984.   }
  1985.  
  1986.   for (i=0;i<default_simple.total_vars();i++)
  1987.   {
  1988.     int t=object_descriptions[i].type;
  1989.     fp->write_byte(t);
  1990.     for (o=save_list;o;o=o->next)
  1991.     {
  1992.       switch (t)
  1993.       {     
  1994.     case RC_C :
  1995.     { fp->write_byte(o->me->get_var(i)); } break;
  1996.     case RC_S :
  1997.     { fp->write_short(o->me->get_var(i)); } break;
  1998.     case RC_L :
  1999.     { fp->write_long(o->me->get_var(i)); } break;
  2000.       }
  2001.     }
  2002.   }
  2003. }
  2004.  
  2005.  
  2006. long level::total_object_links(object_node *list)
  2007. {
  2008.   long tl=0;
  2009.   for (object_node *o=list;o;o=o->next)
  2010.     tl+=o->me->total_objects();
  2011.   return tl;
  2012. }
  2013.  
  2014. long level::total_light_links(object_node *list)
  2015. {
  2016.   long tl=0;
  2017.   for (object_node *o=list;o;o=o->next)
  2018.     tl+=o->me->total_lights();
  2019.   return tl;
  2020. }
  2021.  
  2022. void level::write_links(bFILE *fp, object_node *save_list, object_node *exclude_list)
  2023. {
  2024.   fp->write_byte(RC_L);  
  2025.   fp->write_long(total_object_links(save_list));
  2026.  
  2027.   int x=1;
  2028.   object_node *o=save_list;
  2029.  
  2030.   for (;o;o=o->next,x++)
  2031.   {
  2032.     int i=0;
  2033.     for (;i<o->me->total_objects();i++)
  2034.     {
  2035.       fp->write_long(x);
  2036.       long x=object_to_number_in_list(o->me->get_object(i),save_list); 
  2037.       if (x)
  2038.         fp->write_long(x);
  2039.       else                            // save links to excluded items as negative
  2040.         fp->write_long((long)(-(object_to_number_in_list(o->me,exclude_list))));
  2041.     }
  2042.   }
  2043.  
  2044.   fp->write_byte(RC_L);  
  2045.   fp->write_long(total_light_links(save_list));
  2046.  
  2047.   x=1;
  2048.   for (o=save_list;o;o=o->next,x++)
  2049.   {
  2050.     int i=0;
  2051.     for (;i<o->me->total_lights();i++)
  2052.     {
  2053.       fp->write_long(x);
  2054.       fp->write_long(light_to_number(o->me->get_light(i)));
  2055.     }
  2056.   }
  2057.  
  2058. }
  2059.  
  2060.  
  2061. void level::load_links(bFILE *fp, spec_directory *sd, 
  2062.                object_node *save_list, object_node *exclude_list)
  2063. {
  2064.   spec_entry *se=sd->find("object_links");
  2065.   if (se)
  2066.   {
  2067.     fp->seek(se->offset,0);
  2068.     if (fp->read_byte()==RC_L)
  2069.     {
  2070.       long t=fp->read_long();
  2071.       while (t)
  2072.       {
  2073.     long x1=fp->read_long();
  2074.     CONDITION(x1>=0,"expected x1 for object link to be > 0\n");
  2075.     long x2=fp->read_long();
  2076.     game_object *p,*q=number_to_object_in_list(x1,save_list);
  2077.     if (x2>0)
  2078.       p=number_to_object_in_list(x2,save_list);
  2079.     else p=number_to_object_in_list(-x2,exclude_list);
  2080.     if (q)
  2081.       q->add_object(p);
  2082.     else dprintf("bad object link\n");
  2083.  
  2084.     t--;
  2085.       } 
  2086.     }
  2087.   }
  2088.  
  2089.   se=sd->find("light_links");
  2090.   if (se)
  2091.   {
  2092.     fp->seek(se->offset,0);
  2093.     if (fp->read_byte()==RC_L)
  2094.     {
  2095.       long t=fp->read_long();
  2096.       while (t)
  2097.       {
  2098.     long x1=fp->read_long();
  2099.     long x2=fp->read_long();
  2100.     game_object *p=number_to_object_in_list(x1,save_list);
  2101.     if (p)
  2102.       p->add_light(number_to_light(x2));
  2103.     else dprintf("bad object/light link\n");
  2104.     t--;
  2105.       } 
  2106.     }
  2107.   }
  2108.  
  2109. }
  2110.  
  2111.  
  2112. void level::write_options(bFILE *fp)
  2113. {
  2114.   // save background scroll rate
  2115.   fp->write_byte(RC_L);
  2116.   fp->write_long(bg_xmul);
  2117.   fp->write_long(bg_xdiv);
  2118.   fp->write_long(bg_ymul);
  2119.   fp->write_long(bg_ydiv);
  2120.  
  2121.   fp->write_byte(RC_L);
  2122.   int ta=0;
  2123.   area_controller *a=area_list;
  2124.   for (;a;a=a->next) ta++;
  2125.   fp->write_long(ta);
  2126.   for (a=area_list;a;a=a->next)
  2127.   {
  2128.     fp->write_long(a->x);
  2129.     fp->write_long(a->y);
  2130.     fp->write_long(a->w);
  2131.     fp->write_long(a->h);
  2132.     fp->write_long(a->active);
  2133.  
  2134.     fp->write_long(a->ambient);
  2135.     fp->write_long(a->view_xoff);
  2136.     fp->write_long(a->view_yoff);
  2137.     fp->write_long(a->ambient_speed);
  2138.     fp->write_long(a->view_xoff_speed);
  2139.     fp->write_long(a->view_yoff_speed);
  2140.   }
  2141.   fp->write_byte(RC_L);
  2142.   fp->write_long(tick_counter());
  2143. }
  2144.  
  2145. void level::load_options(spec_directory *sd, bFILE *fp)
  2146. {
  2147.   spec_entry *se=sd->find("bg_scroll_rate");
  2148.   if (se)
  2149.   {
  2150.     fp->seek(se->offset,0);
  2151.     if (fp->read_byte()!=RC_L)
  2152.     { bg_xmul=bg_ymul=1; bg_xdiv=bg_ydiv=8; }
  2153.     else
  2154.     {
  2155.       bg_xmul=fp->read_long();
  2156.       bg_xdiv=fp->read_long();
  2157.       bg_ymul=fp->read_long();
  2158.       bg_ydiv=fp->read_long();
  2159.     }
  2160.   } else { bg_xmul=bg_ymul=1; bg_xdiv=bg_ydiv=8; }
  2161.  
  2162.   se=sd->find("area_list.v1");
  2163.   if (se)
  2164.   {
  2165.     fp->seek(se->offset,0);
  2166.     if (fp->read_byte()==RC_L)
  2167.     {
  2168.       area_controller *l=NULL,*p;
  2169.       long ta=fp->read_long();
  2170.       int i=0;
  2171.       for (;i<ta;i++)
  2172.       {
  2173.     long x,y,w,h;
  2174.     x=fp->read_long();
  2175.     y=fp->read_long();
  2176.     w=fp->read_long();
  2177.     h=fp->read_long();    
  2178.     p=new area_controller(x,y,w,h,NULL);
  2179.     if (l) l->next=p;
  2180.     else area_list=p;
  2181.     l=p;
  2182.     p->active=fp->read_long();
  2183.     p->ambient=fp->read_long();
  2184.     p->view_xoff=fp->read_long();
  2185.     p->view_yoff=fp->read_long();
  2186.     p->ambient_speed=fp->read_long();
  2187.     p->view_xoff_speed=fp->read_long();
  2188.     p->view_yoff_speed=fp->read_long();
  2189.       }
  2190.     }
  2191.   }
  2192.  
  2193.   se=sd->find("tick_counter");
  2194.   if (se)
  2195.   {
  2196.     fp->seek(se->offset,0);
  2197.     if (fp->read_byte()==RC_L)    
  2198.       set_tick_counter(fp->read_long());
  2199.     else set_tick_counter(0);
  2200.   } else set_tick_counter(0);
  2201. }
  2202.  
  2203.  
  2204. void level::write_cache_prof_info()
  2205. {
  2206.   if (cash.prof_is_on())
  2207.   {
  2208.     char pf_name[100];
  2209.     if (first_name)
  2210.       get_prof_assoc_filename(first_name,pf_name);
  2211.     else
  2212.       get_prof_assoc_filename(Name,pf_name);
  2213.  
  2214.  
  2215.     spec_directory sd;
  2216.     sd.add_by_hand(new spec_entry(SPEC_DATA_ARRAY,"cache profile info",NULL,cash.prof_size(),0));
  2217.     sd.calc_offsets();
  2218.     jFILE *fp2=sd.write(pf_name);
  2219.     if (!fp2)
  2220.       the_game->show_help("Unable to open cache profile output file");
  2221.     else
  2222.     {
  2223.       cash.prof_write(fp2);
  2224.       delete fp2;
  2225.     }
  2226.     sd.delete_entries();
  2227.   }
  2228.  
  2229. }
  2230.  
  2231. void level::load_cache_info(spec_directory *sd, bFILE *fp)
  2232. {
  2233.   if (!DEFINEDP(symbol_value(l_empty_cache)) || !symbol_value(l_empty_cache))
  2234.   {
  2235.     char pf_name[100];
  2236.     if (first_name)
  2237.       get_prof_assoc_filename(first_name,pf_name);  // get cache info from orignal filename if this is a savegame
  2238.     else
  2239.       get_prof_assoc_filename(Name,pf_name);
  2240.  
  2241.  
  2242.     cash.load_cache_prof_info(pf_name,this);
  2243.   }
  2244. }
  2245.  
  2246.  
  2247. int level::save(char *filename, int save_all)
  2248. {  
  2249.   if (!save_all && DEFINEDP(symbol_value(l_keep_backup)) &&
  2250.       symbol_value(l_keep_backup))                        // make a backup 
  2251.   {
  2252.     bFILE *fp=open_file(filename,"rb");                   // do file already exsist?
  2253.     if (!fp->open_failure())
  2254.     {
  2255.       unlink("levsave.bak");
  2256.       bFILE *bk=open_file("levsave.bak","wb");
  2257.       if (bk->open_failure())
  2258.         dprintf("unable to open backup file levsave.bak");
  2259.       else
  2260.       {     
  2261.                 long size=fp->file_size();
  2262.                 uchar *buf=(uchar *)jmalloc(0x1000,"copy buf");
  2263.                 int tr=1;
  2264.                 while (size && tr)
  2265.                 {
  2266.                   int tr=fp->read(buf,0x1000);
  2267.                   if (tr)
  2268.                   tr=bk->write(buf,tr);      
  2269.                   size-=tr;
  2270.                 }
  2271.                 jfree(buf);
  2272.       }
  2273.       delete bk;
  2274. #ifndef __MAC__
  2275.       chmod("levsave.bak",S_IRWXU | S_IRWXG | S_IRWXO);
  2276. #endif
  2277.     }
  2278.     delete fp;
  2279.   }
  2280.  
  2281.   
  2282.   // if we are not doing a savegame then change the first_name to this name
  2283.   if (!save_all)
  2284.   {
  2285.     if (first_name) jfree(first_name);
  2286.     first_name=(char *)jmalloc(strlen(filename)+1,"level first name");
  2287.     strcpy(first_name,filename);
  2288.   }
  2289.   
  2290.  
  2291.   
  2292.   object_node *players,*objs;
  2293.   if (save_all)
  2294.     players=NULL;
  2295.   else
  2296.     players=make_player_onodes();
  2297.  
  2298.   objs=make_not_list(players);     // negate the above list
  2299.  
  2300.   bFILE *fp=create_dir(filename,save_all,objs,players);
  2301.   if (!fp->open_failure())
  2302.   {
  2303.     if (first_name)
  2304.     {
  2305.       fp->write_byte(strlen(first_name)+1);
  2306.       fp->write(first_name,strlen(first_name)+1);
  2307.     } else 
  2308.     {
  2309.       fp->write_byte(1);
  2310.       fp->write_byte(0);
  2311.     }
  2312.  
  2313.     fp->write_long(fg_width);
  2314.     fp->write_long(fg_height);
  2315.  
  2316.     int t=fg_width*fg_height;
  2317.     ushort *rm=map_fg;    
  2318.     for (;t;t--,rm++) 
  2319.     {
  2320.       ushort x=*rm;
  2321.       x=lstl(x);            // convert to intel endianess
  2322.       *rm=x;
  2323.     }
  2324.  
  2325.     fp->write((char *)map_fg,2*fg_width*fg_height);
  2326.     t=fg_width*fg_height;
  2327.     rm=map_fg;
  2328.     for (;t;t--,rm++) 
  2329.     {
  2330.       ushort x=*rm;
  2331.       x=lstl(x);            // convert to intel endianess
  2332.       *rm=x;
  2333.     }
  2334.  
  2335.  
  2336.     fp->write_long(bg_width);
  2337.     fp->write_long(bg_height);
  2338.     t=bg_width*bg_height;
  2339.     rm=map_bg;
  2340.     
  2341.     for (;t;t--,rm++) 
  2342.     {
  2343.       ushort x=*rm;
  2344.       x=lstl(x);            // convert to intel endianess
  2345.       *rm=x;
  2346.     }
  2347.  
  2348.     fp->write((char *)map_bg,2*bg_width*bg_height); 
  2349.     rm=map_bg;
  2350.     t=bg_width*bg_height;
  2351.  
  2352.     for (;t;t--,rm++) 
  2353.     {
  2354.       ushort x=*rm;
  2355.       x=lstl(x);            // convert to intel endianess
  2356.       *rm=x;
  2357.     }
  2358.  
  2359.  
  2360.     write_options(fp);
  2361.  
  2362.  
  2363.  
  2364.     write_objects(fp,objs);
  2365.     write_lights(fp);
  2366.     write_links(fp,objs,players);
  2367.     if (save_all)
  2368.     {
  2369.       write_player_info(fp,objs);
  2370.       write_thumb_nail(fp,screen);
  2371.     }
  2372.    
  2373.  
  2374.     delete fp;
  2375. #ifndef __MAC__
  2376.     chmod(filename,S_IRWXU | S_IRWXG | S_IRWXO);
  2377. #endif
  2378.     write_cache_prof_info();
  2379.   } else 
  2380.   {
  2381.     the_game->show_help("Unable to open file for saving\n");
  2382.     delete fp;
  2383.     return 0;
  2384.   }
  2385.  
  2386.   delete_object_list(players);
  2387.   delete_object_list(objs);
  2388.  
  2389.   return 1;
  2390. }
  2391.  
  2392. level::level(int width, int height, char *name)
  2393. {
  2394.   am_timing=0;
  2395.   previous_time=0;
  2396.  
  2397.  
  2398.   the_game->need_refresh();
  2399.   area_list=NULL;
  2400.   set_tick_counter(0);
  2401.  
  2402.   attack_list=NULL;
  2403.   attack_list_size=attack_total=0;
  2404.  
  2405.   target_list=NULL;
  2406.   target_list_size=target_total=0;
  2407.  
  2408.   block_list=NULL;
  2409.   block_list_size=block_total=0;
  2410.  
  2411.   all_block_list=NULL;
  2412.   all_block_list_size=all_block_total=0;
  2413.  
  2414.   Name=NULL;
  2415.   first_name=NULL;
  2416.  
  2417.   set_name(name);
  2418.   first=first_active=NULL;
  2419.   
  2420.   fg_width=width;
  2421.   fg_height=height;
  2422.   calc_bgsize(fg_width,fg_height,bg_width,bg_height);
  2423.   
  2424.   map_bg=(unsigned short *)jmalloc(sizeof(short)*bg_width*bg_height,"map bg");
  2425.   map_fg=(unsigned short *)jmalloc(sizeof(short)*fg_width*fg_height,"map fg");
  2426.  
  2427.  
  2428.  
  2429.   memset(map_bg,0,sizeof(short)*bg_width*bg_height);
  2430.   memset(map_fg,0,sizeof(short)*fg_width*fg_height);
  2431.  
  2432.   int i;  
  2433.   for (i=0;i<fg_width;i++)
  2434.   {    
  2435.     map_fg[i]=1;
  2436.     map_fg[fg_width*(fg_height-1)+i]=1;
  2437.   }
  2438.   for (i=0;i<fg_height;i++)
  2439.   {    
  2440.     map_fg[fg_width*i]=1;
  2441.     map_fg[fg_width*i+fg_width-1]=1;
  2442.   }
  2443.   
  2444.   total_objs=0;  
  2445.   insert_players();
  2446. }
  2447.  
  2448.  
  2449. void level::add_object(game_object *new_guy)
  2450. {
  2451.   total_objs++;
  2452.   new_guy->next=NULL;
  2453.   if (figures[new_guy->otype]->get_cflag(CFLAG_ADD_FRONT))
  2454.   {
  2455.     if (!first)
  2456.       first=new_guy;
  2457.     else
  2458.       last->next=new_guy;
  2459.     last=new_guy;
  2460.   } else
  2461.   {
  2462.     if (!first)
  2463.       last=first=new_guy;
  2464.     else
  2465.     {
  2466.       new_guy->next=first;
  2467.       first=new_guy;
  2468.     }
  2469.   }
  2470. }
  2471.  
  2472. void level::add_object_after(game_object *new_guy,game_object *who)
  2473. {
  2474.   if (!who) add_object(new_guy);
  2475.   else
  2476.   {
  2477.     total_objs++;
  2478.     if (who==last) last=new_guy;
  2479.     new_guy->next=who->next;
  2480.     who->next=new_guy;
  2481.   }
  2482. }
  2483.  
  2484. void level::delete_object(game_object *who)
  2485. {
  2486.   remove_object(who);
  2487.   delete who;
  2488. }
  2489.  
  2490. void level::remove_block(game_object *who)
  2491. {
  2492.   int i=0,j;
  2493.   game_object **o=block_list;
  2494.   for (;i<block_total;i++)
  2495.   {
  2496.     if (*o==who)        // is this object in the block list?
  2497.     {
  2498.       block_total--;    // squish the block list in
  2499.       o++;
  2500.       for (j=i;j<block_total;j++)
  2501.         block_list[j]=block_list[j+1];
  2502.     } else o++;    
  2503.   }
  2504. }
  2505.  
  2506.  
  2507. // searches through the all_block list for who and if it finds it deletes it
  2508. void level::remove_all_block(game_object *who)
  2509. {
  2510.   int i=0,j;
  2511.   game_object **o=all_block_list;
  2512.   for (;i<all_block_total;i++)
  2513.   {
  2514.     if (*o==who)        // is this object in the block list?
  2515.     {
  2516.       all_block_total--;    // squish the block list in
  2517.       o++;
  2518.       for (j=i;j<all_block_total;j++)
  2519.         all_block_list[j]=all_block_list[j+1];
  2520.     } else o++;    
  2521.   }
  2522. }
  2523.  
  2524. void level::remove_object(game_object *who)
  2525. {
  2526.   if (dev_cont)
  2527.     dev_cont->notify_deleted_object(who);
  2528.  
  2529.   if (who==first)
  2530.   {
  2531.     if (who==last) last=NULL;
  2532.     first=first->next;
  2533.   }
  2534.   else
  2535.   {
  2536.     game_object *o=first;
  2537.     for (;o && o->next!=who;o=o->next);
  2538.     if (o)
  2539.     {
  2540.       o->next=who->next;
  2541.       if (!o->next) last=o;
  2542.     }
  2543.     else return ;     // if object is not in level, don't try to do anything else
  2544.   }
  2545.   total_objs--;
  2546.  
  2547.  
  2548.   if (first_active==who) 
  2549.     first_active=who->next_active;
  2550.   else
  2551.   {
  2552.     game_object *o=first_active;
  2553.     for (;o && o->next_active!=who;o=o->next_active);
  2554.     if (o)
  2555.       o->next_active=who->next_active;
  2556.   }
  2557.  
  2558.   if (who->flags()&KNOWN_FLAG)
  2559.   {
  2560.     game_object *o=first;
  2561.     for (;o;o=o->next)
  2562.     {
  2563.       int t=o->total_objects();
  2564.       int i=0;
  2565.       for (;i<t;i++)
  2566.         if (o->get_object(i)==who)
  2567.     {
  2568.       o->remove_object(who);
  2569.       t=o->total_objects();
  2570.     }
  2571.     }
  2572.   }
  2573.  
  2574.   if (who->otype<0xffff)
  2575.   {
  2576.     if (who->can_block())  // remove object from block list and all_block if nessasary
  2577.     {
  2578.       remove_block(who);
  2579.       remove_all_block(who);
  2580.     } else if (who->hurtable()) 
  2581.       remove_all_block(who);
  2582.   }
  2583.  
  2584.  
  2585.   int t=who->total_objects();
  2586.   while (t) { who->remove_object(who->get_object(0)); t--; }
  2587.  
  2588.   t=who->total_lights();
  2589.   while (t) { who->remove_light(who->get_light(0)); t--; }
  2590. }
  2591.  
  2592. void level::to_front(game_object *o)  // move to end of list, so we are drawn last, therefore top 
  2593. {
  2594.   if (o==last) return ;
  2595.   first_active=NULL;     // make sure nothing goes screwy with the active list
  2596.  
  2597.   if (o==first)  
  2598.     first=first->next;  
  2599.   else
  2600.   {
  2601.     game_object *w=first;
  2602.     for (;w && w->next!=o;w=w->next);
  2603.     if (!w) return ;
  2604.     w->next=o->next;
  2605.   }
  2606.  
  2607.   last->next=o;
  2608.   o->next=NULL;
  2609.   last=o;
  2610. }
  2611.  
  2612. void level::to_back(game_object *o)   // to make the character drawn in back, put at front of list
  2613. {  
  2614.   if (o==first) return;
  2615.   first_active=NULL;     // make sure nothing goes screwy with the active list  
  2616.   
  2617.   game_object *w=first;
  2618.   for (;w && w->next!=o;w=w->next);
  2619.   if (!w) return;
  2620.   if (last==o)
  2621.     last=w;
  2622.   w->next=o->next;
  2623.   o->next=first;
  2624.   first=o;
  2625. }
  2626.  
  2627.  
  2628. game_object *level::find_self(game_object *me)
  2629. {
  2630.   return me;
  2631. }
  2632.  
  2633. game_object *level::find_object(long x, long y)
  2634. {
  2635.   long x1,y1,x2,y2;  
  2636.   game_object *o=first;
  2637.   for (;o;o=o->next)
  2638.   {
  2639.     o->picture_space(x1,y1,x2,y2);    
  2640.     if (x<x2 && x>=x1 && y<y2 && y>=y1)
  2641.       return o;
  2642.   }
  2643.   return NULL; 
  2644. }
  2645.  
  2646. long last_tile_hit_x,last_tile_hit_y;
  2647.  
  2648. #define remapx(x) (x==0 ? -1 : x==tl-1 ? tl+1 : x)
  2649. #define remapy(y) (y==0 ? -1 : y==th-1 ? th+1 : y)
  2650.  
  2651. void level::vforeground_intersect(long x1, long y1, long &y2)
  2652. {
  2653.   //  foreground_intersect(x1,y1,x1,y2);
  2654.   //  return ;
  2655.  
  2656.   long tl=the_game->ftile_width(),th=the_game->ftile_height();
  2657.  
  2658.   long blocky1,blocky2,bx,by,block,realy;
  2659.   foretile *f;
  2660.  
  2661.   bx=x1/tl;
  2662.  
  2663.   blocky1=y1/th;
  2664.   blocky2=y2/th;  
  2665.  
  2666.   if (y2>y1)
  2667.   {
  2668.     realy=blocky1*th;
  2669.  
  2670.     for (by=blocky1;by<=blocky2;by++,realy+=th)
  2671.     {
  2672.       block=the_game->get_map_fg(bx,by);      
  2673.       if (block>BLACK)        // don't check BLACK, should be no points in it
  2674.       {   
  2675.         f=the_game->get_fg(block);
  2676.         if (f->ylevel!=255)
  2677.         {
  2678.           if (y2-realy>=f->ylevel-1)
  2679.           {            
  2680.             y2=realy+f->ylevel-1;
  2681.             if (y2<y1)
  2682.               y2=y1;
  2683.             return ;
  2684.           }          
  2685.         } else if (f->points->tot)
  2686.         {
  2687.           foreground_intersect(x1,y1,x1,y2);
  2688.           return ;
  2689.         }
  2690.       }
  2691.     }
  2692.  
  2693.   } else
  2694.   {
  2695.     realy=blocky1*th;
  2696.  
  2697.     for (by=blocky1;by>=blocky2;by--,realy-=th)
  2698.     {
  2699.       block=the_game->get_map_fg(bx,by);      
  2700.       if (block>BLACK)        // don't check BLACK, should be no points in it
  2701.       {   
  2702.         f=the_game->get_fg(block);
  2703.         if (f->ylevel!=255)
  2704.         {
  2705.           if (y1>=realy+th-1 && y2<realy+th+2)
  2706.           {           
  2707.             y2=realy+th+2;
  2708.             return ;
  2709.           }          
  2710.         } else if (f->points->tot)
  2711.         {
  2712.           foreground_intersect(x1,y1,x1,y2);
  2713.           return ;
  2714.         }
  2715.       }
  2716.     }
  2717.   }
  2718. }
  2719.  
  2720. signed char remap_x[30]= {-1,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,30};
  2721. signed char remap_y[15]= {-1,1,2,3,4,5,6,7,8,9,10,11,12,13,15};
  2722.  
  2723. void level::foreground_intersect(long x1, long y1, long &x2, long &y2)
  2724. {
  2725.   long tl=the_game->ftile_width(),th=the_game->ftile_height(),
  2726.     j,
  2727.     xp1,yp1,xp2,yp2,    // starting and ending points of block line segment 
  2728.     swap;               // temp var
  2729.   long blockx1,blocky1,blockx2,blocky2,block,bx,by;
  2730.   point_list *block_list;
  2731.   unsigned char *bdat;
  2732.  
  2733.   blockx1=x1;
  2734.   blocky1=y1;
  2735.   blockx2=x2;
  2736.   blocky2=y2;
  2737.   if (blockx1>blockx2) { swap=blockx1; blockx1=blockx2; blockx2=swap; }
  2738.   if (blocky1>blocky2) { swap=blocky1; blocky1=blocky2; blocky2=swap; }
  2739.   blockx1=(blockx1-2)/tl;
  2740.   blockx2=(blockx2+tl+2)/tl;
  2741.   blocky1=(blocky1-2)/th;
  2742.   blocky2=(blocky2+th+2)/th;
  2743.  
  2744.  
  2745.   if (blockx2>=foreground_width()) { x2=tl*foreground_width()-1; }
  2746.   if (blocky2>=foreground_height()) { y2=th*foreground_height()-1; }  
  2747.   blockx1=max(blockx1,0);
  2748.   blocky1=max(blocky1,0);  
  2749.  
  2750.   //  printf("%4d %4d  -> %4d %4d %4d %4d\n",x2-x1,y2-y1,blockx1,blocky1,blockx2,blocky2);
  2751.  
  2752.   // now check all the map positions this line could intersect
  2753.   for (bx=blockx1;bx<=blockx2;bx++)
  2754.   {
  2755.     for (by=blocky1;by<=blocky2;by++)
  2756.     {
  2757.       block=the_game->get_map_fg(bx,by);
  2758.       if (block>BLACK)        // don't check BLACK, should be no points in it
  2759.       {
  2760.         // now check the all the line segments in the block
  2761.         foretile *f=the_game->get_fg(block);
  2762.         block_list=f->points;
  2763.         unsigned char total=block_list->tot;
  2764.         bdat=block_list->data;
  2765.         unsigned char *ins=f->points->inside;
  2766.     long xo=bx*tl,yo=by*th;
  2767.         for (j=0;j<total-1;j++,ins++)
  2768.         {
  2769.           // find the starting and ending points for this segment
  2770.       xp1=xo+remap_x[*bdat];
  2771.       bdat++;
  2772.  
  2773.       yp1=yo+remap_y[*bdat];
  2774.       bdat++;
  2775.  
  2776.       xp2=xo+remap_x[*bdat];
  2777.       yp2=yo+remap_y[bdat[1]];
  2778.  
  2779.  
  2780.       long ox2=x2,oy2=y2;
  2781.           if (*ins)      
  2782.             setback_intersect(x1,y1,x2,y2,xp1,yp1,xp2,yp2,1); 
  2783.           else
  2784.             setback_intersect(x1,y1,x2,y2,xp1,yp1,xp2,yp2,-1); 
  2785.       if (ox2!=x2 || oy2!=y2)
  2786.       {
  2787.         last_tile_hit_x=bx;
  2788.         last_tile_hit_y=by;
  2789.       }
  2790.  
  2791.         }       
  2792.       }
  2793.     }
  2794.   }  
  2795. }
  2796.  
  2797.  
  2798. void level::send_signal(long signal)
  2799. {
  2800.   if (signal)   // signal 0 is never sent!
  2801.   {
  2802.     game_object *o=first_active;
  2803.     for (;o;o=o->next_active)
  2804.       o->recieve_signal(signal);  
  2805.   }
  2806. }
  2807.  
  2808.  
  2809. int level::crush(game_object *by_who, int xamount, int yamount)
  2810. {
  2811.   long xv,yv,crushed=0;  
  2812.   game_object *o=first_active;
  2813.   for (;o;o=o->next_active)
  2814.   {
  2815.     if (o->hurtable() && o!=by_who)
  2816.     {      
  2817.       xv=-xamount;
  2818.       yv=-yamount;    
  2819.       if (o->try_move(o->x,o->y,xv,yv,3)==by_who)
  2820.       {      
  2821.     xv=xamount;
  2822.     yv=yamount;
  2823.     o->try_move(o->x,o->y,xv,yv,3);
  2824.     if (xv==0 && yv==0)
  2825.     {
  2826.       if (o->state!=dead && o->state!=dieing)
  2827.         o->do_damage(by_who->current_figure()->hit_damage,by_who,o->x,o->y,0,0);
  2828.  
  2829. /*      {          
  2830.         if (o->has_sequence(dieing))
  2831.           o->set_state(dieing);
  2832.         else o->set_state(dead);
  2833.           o->hp=0;        
  2834.       }        */
  2835.       crushed=1;      
  2836.     }
  2837.       }    
  2838.     }    
  2839.   }
  2840.  
  2841.   return crushed;  
  2842. }
  2843.  
  2844.  
  2845. int level::platform_push(game_object *by_who, int xamount, int yamount)
  2846. {
  2847.   int failed=0;
  2848.   long xv,yv;
  2849.   game_object *o=first_active;
  2850.   for (;o;o=o->next_active)  
  2851.   {
  2852.     if (o->is_playable() && o->state!=dieing && o->state!=dead)  
  2853.     {      
  2854.       // check to see if the platform is going up and will run into us.      
  2855.       long tvx,tvy;
  2856.       if (yamount<0)
  2857.       {
  2858.     tvx=-xamount;
  2859.     tvy=-yamount;
  2860.     if (o->try_move(o->x,o->y,tvx,tvy,1)==by_who)
  2861.     {
  2862.       o->x+=tvx;
  2863.       o->y+=tvy;       
  2864.     }
  2865.       }
  2866.  
  2867. /*      xv=xamount;    
  2868.       yv=yamount;
  2869.       tvx,tvy;
  2870.       if (xv>0) tvx=xv+1; else if (xv<0) tvx=xv-1; else tvx=0;
  2871.       if (yv>0) tvy=yv+1; else if (yv<0) tvx=yv-1; else tvy=0;
  2872.       if (o->try_move(o->x,o->y,tvx,tvy,1)==by_who)  // we the platform hit us?
  2873.       {
  2874.     o->x+=tvx;
  2875.     o->y+=tvy;       
  2876.       }*/
  2877.  
  2878.       xv=0;   
  2879.       yv=2;
  2880.       if (o->try_move(o->x,o->y,xv,yv,1)==by_who)  // are we standing on the platform?
  2881.       {      
  2882.     by_who->x=-by_who->x;
  2883.     xv=xamount;
  2884.     yv=yamount;
  2885.     o->try_move(o->x,o->y,xv,yv,3); 
  2886.     if (xv!=xamount || yv!=yamount) failed=1;
  2887.     o->x+=xv;
  2888.     o->y+=yv;
  2889.     by_who->x=-by_who->x;
  2890.       }    
  2891.     }    
  2892.   }
  2893.   return !failed;
  2894. }
  2895.  
  2896. int level::push_characters(game_object *by_who, int xamount, int yamount)
  2897. {
  2898.   long xv,yv;
  2899.   int failed=0;
  2900.   game_object *o=first_active;
  2901.   for (;o;o=o->next_active)  
  2902.   {
  2903.     if ((o->is_playable() || o->pushable()) && o->state!=dieing && o->state!=dead)  
  2904.     {      
  2905.       xv=-xamount;    
  2906.       yv=-yamount;
  2907.       long tvx,tvy;
  2908.       if (xv>0) tvx=xv+1; else if (xv<0) tvx=xv-1; else tvx=0;
  2909.       if (yv>0) tvy=yv+1; else if (yv<0) tvx=yv-1; else tvy=0;
  2910.       if (o->try_move(o->x+xamount,o->y+yamount,tvx,tvy,3)==by_who)
  2911.       {      
  2912.     xv=(xamount-tvx);
  2913.     yv=(yamount-tvy);
  2914.     o->try_move(o->x,o->y,xv,yv,3);       
  2915.     o->x+=xv;
  2916.     o->y+=yv;
  2917.     if (xv!=xamount-tvx || yv!=yamount-tvy)
  2918.       failed=1;
  2919.       }    
  2920.     }    
  2921.   }
  2922.   return !failed;
  2923. }
  2924.  
  2925. game_object *level::find_xrange(int x, int y, int type, int xd)
  2926. {
  2927.   long find_ydist=100000;
  2928.   game_object *find=NULL;
  2929.   game_object *o=first_active;
  2930.   for (;o;o=o->next_active)  
  2931.   {
  2932.     if (o->otype==type)
  2933.     {
  2934.       int x_dist=abs(x-o->x);
  2935.       int y_dist=abs(y-o->y);
  2936.  
  2937.       if (x_dist<xd  && y_dist<find_ydist)
  2938.       {   
  2939.     find_ydist=y_dist;
  2940.     find=o;
  2941.       }
  2942.     }
  2943.   }
  2944.   return find;
  2945. }
  2946.  
  2947.  
  2948. game_object *level::find_xclosest(int x, int y, int type, game_object *who)
  2949. {
  2950.   long find_ydist=100000,find_xdist=0xffffff;
  2951.   game_object *find=NULL;
  2952.   game_object *o=first_active;
  2953.   for (;o;o=o->next_active)  
  2954.   {
  2955.     if (o->otype==type && o!=who)
  2956.     {
  2957.       int x_dist=abs(x-o->x);
  2958.       if (x_dist<find_xdist)
  2959.       {
  2960.     find_xdist=x_dist;
  2961.     find_ydist=abs(y-o->y);
  2962.     find=o;
  2963.       }
  2964.       else if (x_dist==find_xdist)
  2965.       {
  2966.     int y_dist=abs(y-o->y);
  2967.     if (y_dist<find_ydist)
  2968.     {
  2969.       find_ydist=y_dist;
  2970.       find=o;
  2971.     }
  2972.       }
  2973.     }
  2974.   }
  2975.   return find;
  2976. }
  2977.  
  2978. game_object *level::find_closest(int x, int y, int type, game_object *who)
  2979. {
  2980.   long find_dist=100000;
  2981.   game_object *find=NULL;
  2982.   game_object *o=first_active;
  2983.   for (;o;o=o->next_active)  
  2984.   {
  2985.     if (o->otype==type && o!=who)
  2986.     {
  2987.       int d=(x-o->x)*(x-o->x)+(y-o->y)*(y-o->y);
  2988.       if (d<find_dist)
  2989.       {
  2990.     find=o;
  2991.     find_dist=d;
  2992.       }
  2993.     }
  2994.   }
  2995.   return find;
  2996. }
  2997.  
  2998.  
  2999.  
  3000. void level::remove_light(light_source *which)
  3001. {
  3002.   if (which->known)
  3003.   {
  3004.     game_object *o=first;
  3005.     for (;o;o=o->next)
  3006.     {
  3007.       int t=o->total_lights();
  3008.       int i=0;
  3009.       for (;i<t;i++)
  3010.         if (o->get_light(i)==which)
  3011.       o->remove_light(o->get_light(i));
  3012.     }
  3013.   }
  3014.   delete_light(which);
  3015. }
  3016.  
  3017.  
  3018. game_object *level::find_type(int type, int skip)
  3019. {
  3020.   game_object *l=NULL;
  3021.   game_object *o=first;
  3022.   for (;o;o=o->next)
  3023.   {
  3024.     if (o->otype==type)
  3025.     {
  3026.       if (!skip)
  3027.         return o;      
  3028.       skip--;
  3029.       l=o;
  3030.     }
  3031.   }
  3032.   return l;
  3033. }
  3034.  
  3035. void level::hurt_radius(long x, long y,long r, long m, game_object *from, game_object *exclude, 
  3036.             int max_push)
  3037. {
  3038.   if (r<1) return ;   // avoid dev vy zero
  3039.   game_object *o=first_active;
  3040.   for (;o;o=o->next_active)
  3041.   {
  3042.     if (o!=exclude && o->hurtable())
  3043.     {
  3044.       long y1=o->y,y2=o->y-o->picture()->height();
  3045.       long cx=abs(o->x-x),cy1=abs(y1-y),d1,d2,cy2=abs(y2-y);
  3046.       if (cx<cy1)
  3047.         d1=cx+cy1-(cx>>1);
  3048.       else d1=cx+cy1-(cy1>>1);
  3049.  
  3050.       if (cx<cy2)
  3051.         d2=cx+cy2-(cx>>1);
  3052.       else d2=cx+cy2-(cy2>>1);
  3053.       if (d2<d1)
  3054.         d1=d2;
  3055.  
  3056.  
  3057.  
  3058.       if (d1<r)
  3059.       {
  3060.  
  3061.     int px=(r-cx)*max_push/r,py=(r-cy1)*max_push/r;
  3062.     if (o->x<x)
  3063.           px=-px;
  3064.     if (o->y<y)
  3065.           py=-py;
  3066.     o->do_damage((r-d1)*m/r,from,x,y1,px,py);
  3067.       }
  3068.  
  3069.  
  3070.     }
  3071.   }
  3072.  
  3073. }
  3074.  
  3075.  
  3076.  
  3077. game_object *level::get_random_start(int min_player_dist, view *exclude)
  3078. {
  3079.   int t=0;
  3080.   game_object *o=first;
  3081.   for (;o;o=o->next)
  3082.     if (o->otype==start_position_type) t++;    // count how many starts there are in the level
  3083.  
  3084.   if (t==0) return NULL;                       // there aren't any starts in level!
  3085.  
  3086.   int retries=t;
  3087.   do
  3088.   {
  3089.     int ctry=jrandom(t)+1;
  3090.     game_object *n=first;
  3091.     for (n=first;ctry && n;n=n->next)
  3092.     {
  3093.       if (n->otype==start_position_type) 
  3094.       {
  3095.     o=n;
  3096.         ctry--;
  3097.       }
  3098.     }
  3099.  
  3100.     int too_close=0;
  3101.     view *v=player_list;
  3102.     for (;v;v=v->next)
  3103.     { 
  3104.       if (v!=exclude)
  3105.       {
  3106.     long cx=abs(v->x_center()-o->x),cy=abs(v->y_center()-o->y),d;
  3107.     if (cx<cy)
  3108.           d=cx+cy-(cx>>1);
  3109.     else d=cx+cy-(cy>>1);
  3110.     if (d<min_player_dist) too_close=1;
  3111.       }
  3112.     }
  3113.     if (too_close) retries--;
  3114.     else retries=0;
  3115.   } while (retries);
  3116.  
  3117.   return o;
  3118. }
  3119.  
  3120.  
  3121.  
  3122.  
  3123.  
  3124. void level::insert_players()
  3125. {
  3126.  
  3127.   int start=0;
  3128.   int i=0;
  3129.   for (;i<total_objects;i++)
  3130.     if (!strcmp(object_names[i],"START"))
  3131.       start=i;
  3132.  
  3133.   view *f=player_list;
  3134.   for (;f;f=f->next)  
  3135.   {
  3136.     long x=50,y=50;
  3137.     game_object *st=find_type(start,f->player_number);    
  3138.     if (st)
  3139.     {
  3140.       f->focus->x=st->x;
  3141.       f->focus->y=st->y;
  3142.     }
  3143.     add_object_after(f->focus,st);
  3144.   }
  3145.  
  3146. }
  3147.  
  3148.  
  3149. void level::add_attacker(game_object *who)
  3150. {
  3151.   if (attack_total>=attack_list_size)  // see if we need to grow the list size..
  3152.   {
  3153.     attack_list_size++;
  3154.     attack_list=(game_object **)jrealloc(attack_list,sizeof(game_object *)*attack_list_size,
  3155.                               "attack_list");    
  3156.   }
  3157.   attack_list[attack_total]=who;
  3158.   attack_total++;
  3159. }
  3160.  
  3161.  
  3162.  
  3163. void level::add_target(game_object *who)
  3164. {
  3165.   if (target_total>=target_list_size)  // see if we need to grow the list size..
  3166.   {
  3167.     target_list_size++;
  3168.     target_list=(game_object **)jrealloc(target_list,sizeof(game_object *)*target_list_size,
  3169.                               "target_list");    
  3170.   }
  3171.   target_list[target_total]=who;
  3172.   target_total++;
  3173. }
  3174.  
  3175.  
  3176.  
  3177. void level::add_block(game_object *who)
  3178. {
  3179.   if (block_total>=block_list_size)  // see if we need to grow the list size..
  3180.   {
  3181.     block_list_size++;
  3182.     block_list=(game_object **)jrealloc(block_list,sizeof(game_object *)*block_list_size,
  3183.                               "block_list");    
  3184.   }
  3185.   block_list[block_total]=who;
  3186.   block_total++;
  3187. }
  3188.  
  3189.  
  3190. void level::add_all_block(game_object *who)
  3191. {
  3192.   if (all_block_total>=all_block_list_size)  // see if we need to grow the list size..
  3193.   {
  3194.     all_block_list_size++;
  3195.     all_block_list=(game_object **)jrealloc(all_block_list,sizeof(game_object *)*all_block_list_size,
  3196.                               "all_block_list");    
  3197.   }
  3198.   all_block_list[all_block_total]=who;
  3199.   all_block_total++;
  3200. }
  3201.  
  3202.  
  3203. game_object *level::find_object_in_area(long x, long y, long x1, long y1, long x2, long y2,
  3204.                      Cell *list, game_object *exclude)
  3205. {
  3206.   game_object *closest=NULL;
  3207.   long closest_distance=0xfffffff,distance,xo,yo;
  3208.   game_object *o=first_active;
  3209.   for (;o;o=o->next_active)
  3210.   {
  3211.     long xp1,yp1,xp2,yp2;
  3212.     o->picture_space(xp1,yp1,xp2,yp2);
  3213.  
  3214.  
  3215.     if (!(xp1>x2 || xp2<x1 || yp1>y2 || yp2<y1) && o!=exclude)
  3216.     {
  3217.       // check to see if the type is in the list
  3218.       Cell *v=list;
  3219.       for (;!NILP(v) && lnumber_value(CAR(v))!=o->otype;v=CDR(v));
  3220.       if (!NILP(v))
  3221.       {
  3222.     xo=abs(o->x-x);
  3223.     yo=abs(o->y-y);
  3224.     distance=xo*xo+yo*yo;
  3225.     if (distance<closest_distance)
  3226.     {
  3227.       closest_distance=distance;
  3228.       closest=o;
  3229.     }
  3230.       }
  3231.     }
  3232.   }
  3233.   return closest;
  3234. }
  3235.  
  3236.  
  3237.  
  3238.  
  3239. game_object *level::find_object_in_angle(long x, long y, long start_angle, long end_angle,
  3240.                     void *list, game_object *exclude)
  3241. {
  3242.   game_object *closest=NULL;
  3243.   long closest_distance=0xfffffff,distance,xo,yo;
  3244.   game_object *o=first_active;
  3245.   for (;o;o=o->next_active)
  3246.   {
  3247.     long angle=lisp_atan2(o->y-y,o->x-x);
  3248.     if (((start_angle<=end_angle && (angle>=start_angle && angle<=end_angle))
  3249.     || (start_angle>end_angle && (angle>=start_angle || angle<=end_angle)))
  3250.     && o!=exclude)
  3251.     {
  3252.       // check to see if the type is in the list
  3253.       Cell *v=(Cell *)list;
  3254.       for (;!NILP(v) && lnumber_value(CAR(v))!=o->otype;v=CDR(v));
  3255.       if (!NILP(v))
  3256.       {
  3257.     xo=abs(o->x-x);
  3258.     yo=abs(o->y-y);
  3259.     distance=xo*xo+yo*yo;
  3260.     if (distance<closest_distance)
  3261.     {
  3262.       closest_distance=distance;
  3263.       closest=o;
  3264.     }
  3265.       }
  3266.     }
  3267.   }
  3268.   return closest;
  3269. }
  3270.  
  3271.  
  3272. object_node *level::make_not_list(object_node *list)
  3273. {
  3274.   object_node *f=NULL,*l;
  3275.   game_object *o=first;
  3276.   for (;o;o=o->next)
  3277.   {
  3278.     if (!object_to_number_in_list(o,list))
  3279.     {
  3280.       object_node *q=new object_node(o,NULL);
  3281.       if (f)
  3282.         l->next=q;
  3283.       else f=q;
  3284.       l=q;
  3285.     }
  3286.   }
  3287.   return f;
  3288. }
  3289.  
  3290. FILE *open_FILE(char *filename, char *mode);
  3291.  
  3292. void level::write_object_info(char *filename)
  3293. {
  3294.   FILE *fp=open_FILE(filename,"wb");
  3295.   if (fp)
  3296.   {
  3297.     int i=0;
  3298.     game_object *o=first;
  3299.     for (;o;o=o->next)
  3300.     {
  3301.       fprintf(fp,"%3d %s %4d %4d %4d %4d %04d\n",i++,object_names[o->otype],o->x,o->y,
  3302.           o->xvel(),o->yvel(),o->current_frame);
  3303.     }
  3304.     fclose(fp);
  3305.   }
  3306. }
  3307.  
  3308.  
  3309. area_controller::area_controller(long X, long Y, long W, long H, area_controller *Next)
  3310.   x=X; y=Y; w=W; h=H; 
  3311.   next=Next; active=0; 
  3312.  
  3313.   ambient=-1;
  3314.   view_xoff=-1;
  3315.   view_yoff=-1;
  3316.   ambient_speed=2; 
  3317.   view_xoff_speed=4;
  3318.   view_yoff_speed=4;
  3319. }
  3320.  
  3321.  
  3322.  
  3323.  
  3324.  
  3325.  
  3326.  
  3327.  
  3328.  
  3329.  
  3330.  
  3331.  
  3332.  
  3333.  
  3334.  
  3335.  
  3336.  
  3337.  
  3338.  
  3339.  
  3340.