/* BattleView.h -- implementation for main view
   Copyright (C) 1992, 1993 David A. Strout

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */

/* Written by David Strout <dstrout@isi.edu>. */


#import "BattleView.h"
#import "Ship.h"
#import "Misc.h"
#import "Weapon.h"
#import "Thinker.h"

@implementation BattleView

- initFrame:(const NXRect *)frm
{
  int i;
  id theSpaceThing;
  
  
  INITRAND;
  
/* Nothing majic about 12, just a nice number to start */
  theFedList=[[List alloc] initCount:12];
  theKliList=[[List alloc] initCount:12];
  theWeaponList=[[List alloc] initCount:12];
  
  for(i=0;i<NUMSHIPS;i++){
    theSpaceThing=[[Ship alloc] initOnSide:FED];
    [theFedList addObject:theSpaceThing];
  };
  
  for(i=0;i<NUMSHIPS;i++){
    theSpaceThing=[[Ship alloc] initOnSide:KLI];
    [theKliList addObject:theSpaceThing];
  };
  
  [self display];
  
  return self;
}

- drawSelf:(NXRect *)rects :(int)rectCount 
{
  if (!rects || !rectCount) return self;
  PSsetgray(0);
  NXRectFill(rects);
  return self;
}

- (float)xSize
{
  return bounds.size.width;
}

- (float)ySize
{
  return bounds.size.height;
}


- drawPhaser
/* Walks through the WeaponList drawing everything.  Doesn't belong here, never got around to moving it. */
{
  int i;
  NXPoint *from, *to;
  

  for(i=0;i<[theWeaponList count];i++) {
    
    from=[[theWeaponList objectAt:i] from];
    to=[[theWeaponList objectAt:i] to];
    
    PSsetrgbcolor((float)(RANDINT(10)*.1), (float)(RANDINT(10)*.1), (float)(RANDINT(10)*.1));

    PSmoveto(from->x+8, from->y+8);
    PSlineto(to->x+8, to->y+8);
  };
  
  PSstroke();
  PSflushgraphics();

  return self;
}

- erasePhaser
/* Same as drawPhaser, only draws them in black */
{
  int i;
  NXPoint *from, *to;
  

  for(i=0;i<[theWeaponList count];i++) {
    
    from=[[theWeaponList objectAt:i] from];
    to=[[theWeaponList objectAt:i] to];
    
    PSsetgray(0);
    PSmoveto(from->x+8, from->y+8);
    PSlineto(to->x+8, to->y+8);
    [[theWeaponList removeObjectAt:i] free];
  };
  
  PSstroke();
  PSflushgraphics();

  return self;
}

- shootPhaser
/* Picks a ship at random (the "shooter") then finds the closest enemy. Then we create an instance of Weapon, add it to theWeaponList, and tell that ship to take some damage */
{
  int i,j, target, shooter;
  double distance, minDist;
  id theShot;
  NXPoint from, to;

  /* Do the Federation */
  minDist=10000.0;
  for(i=0;i<SHOTS_PER_FRAME;i++) {
    theShot=[[Weapon alloc] init];
    shooter=RANDINT(NUMSHIPS-1);
    from.x=[[theFedList objectAt:shooter] xLoc];
    from.y=[[theFedList objectAt:shooter] yLoc];
    
    target=0; minDist=10000.0; 
    for(j=0;j<NUMSHIPS;j++) {
      to.x=[[theKliList objectAt:j] xLoc];
      to.y=[[theKliList objectAt:j] yLoc];
      
      distance=sqrt(pow(fabs((double)to.x-(double)from.x), 2)+pow(fabs((double)to.y-(double)from.y), 2));
      if( distance <= minDist ){
	target=j;
	minDist=distance;
      };
    };
    to.x=[[theKliList objectAt:target] xLoc];
    to.y=[[theKliList objectAt:target] yLoc];
    
    [[theShot setTo:&to] setFrom:&from];
    [theWeaponList addObject:theShot];
    
    [[theKliList objectAt:target] takeHitForPoints:FED_DAM];
  };
  
  /* Do the Klingons */
  minDist=10000.0;
  for(i=0;i<SHOTS_PER_FRAME;i++) {
    theShot=[[Weapon alloc] init];
    shooter=RANDINT(NUMSHIPS-1);
    from.x=[[theKliList objectAt:shooter] xLoc];
    from.y=[[theKliList objectAt:shooter] yLoc];
    
    target=0; minDist=10000.0; 
    for(j=0;j<NUMSHIPS;j++) {
      to.x=[[theFedList objectAt:j] xLoc];
      to.y=[[theFedList objectAt:j] yLoc];
      
      distance=sqrt(pow(fabs((double)to.x-(double)from.x), 2)+pow(fabs((double)to.y-(double)from.y), 2));
      if( distance <= minDist ){
	target=j;
	minDist=distance;
      };
    };
    to.x=[[theFedList objectAt:target] xLoc];
    to.y=[[theFedList objectAt:target] yLoc];
    
    [[theShot setTo:&to] setFrom:&from];
    [theWeaponList addObject:theShot];
    
    [[theFedList objectAt:target] takeHitForPoints:KLI_DAM];
    
  };
  return self;
}

- oneStep
/* This is called by BackSpace as fast as possible */
{
  [self shootPhaser];
  [self drawPhaser];
  [theFedList makeObjectsPerform:@selector(oneStep)];
  [theKliList makeObjectsPerform:@selector(oneStep)];
  [self erasePhaser];
  
  return self;
}

- inspector:sender
{
  char buf[MAXPATHLEN];
  
  if (!sharedInspectorPanel)
  {
    sprintf(buf,"%s/Battle.nib",[sender moduleDirectory:"Battle"]);
    [NXApp loadNibFile:buf owner:self withNames:NO];
  }
  return sharedInspectorPanel;
}


- sizeTo:(NXCoord)width :(NXCoord)height
{
  int i;
  
  [super sizeTo:width :height];
  for(i=0;i<NUMSHIPS;i++) {
    [[theFedList objectAt:i] setViewXSize:width YSize:height];
    [[theKliList objectAt:i] setViewXSize:width YSize:height];
  };
  return self;
}

@end
