<commit_before>// The libMesh Finite Element Library.
// Copyright (C) 2002-2012 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

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

// This library 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
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ includes
#include <algorithm> // for std::fill
#include <cstdlib> // *must* precede <cmath> for proper std:abs() on PGI, Sun Studio CC
#include <cmath>    // for sqrt

// Local Includes
#include "libmesh/libmesh_common.h"
#include "libmesh/kelly_error_estimator.h"
#include "libmesh/error_vector.h"
#include "libmesh/fe_base.h"
#include "libmesh/libmesh_logging.h"
#include "libmesh/elem.h"
#include "libmesh/system.h"

#include "libmesh/dense_vector.h"
#include "libmesh/tensor_tools.h"

namespace libMesh
{

void
KellyErrorEstimator::initialize(const System& system,
                                ErrorVector&,
                                bool)
{
  // Hang onto the system - we may need it for variable names later.
  my_system = &system;

  // We'll need gradients and normal vectors for flux jump computation
  fe_fine->get_dphi();
  fe_fine->get_normals();
  fe_coarse->get_dphi();
}

void
KellyErrorEstimator::internal_side_integration ()
{
  Real error = 1.e-30;
  unsigned int n_qp = fe_fine->n_quadrature_points();
  unsigned int n_fine_dofs = Ufine.size();
  unsigned int n_coarse_dofs = Ucoarse.size();

  std::vector<std::vector<RealGradient> > dphi_coarse = fe_coarse->get_dphi();
  std::vector<std::vector<RealGradient> > dphi_fine = fe_fine->get_dphi();
  std::vector<Point> face_normals = fe_fine->get_normals();
  std::vector<Real> JxW_face = fe_fine->get_JxW();

  for (unsigned int qp=0; qp != n_qp; ++qp)
    {
      // Calculate solution gradients on fine and coarse elements
      // at this quadrature point
      Gradient grad_fine, grad_coarse;
      for (unsigned int i=0; i != n_coarse_dofs; ++i)
        grad_coarse.add_scaled (dphi_coarse[i][qp], Ucoarse(i));

      for (unsigned int i=0; i != n_fine_dofs; ++i)
        grad_fine.add_scaled (dphi_fine[i][qp], Ufine(i));

      // Find the jump in the normal derivative
      // at this quadrature point
      const Number jump = (grad_fine - grad_coarse)*face_normals[qp];
      const Real jump2 = TensorTools::norm_sq(jump);

      // Accumulate the jump integral
      error += JxW_face[qp] * jump2;
    }

  // Add the h-weighted jump integral to each error term
  fine_error =
    error * fine_elem->hmax() * error_norm.weight(var);
  coarse_error =
    error * coarse_elem->hmax() * error_norm.weight(var);
}

bool
KellyErrorEstimator::boundary_side_integration ()
{
  const std::string &var_name = my_system->variable_name(var);

  std::vector<std::vector<RealGradient> > dphi_fine = fe_fine->get_dphi();
  std::vector<Point> face_normals = fe_fine->get_normals();
  std::vector<Real> JxW_face = fe_fine->get_JxW();
  std::vector<Point> qface_point = fe_fine->get_xyz();

  // The reinitialization also recomputes the locations of
  // the quadrature points on the side.  By checking if the
  // first quadrature point on the side is on a flux boundary
  // for a particular variable, we will determine if the whole
  // element is on a flux boundary (assuming quadrature points
  // are strictly contained in the side).
  if (this->_bc_function(*my_system, qface_point[0], var_name).first)
    {
      const Real h = fine_elem->hmax();

      // The number of quadrature points
      const unsigned int n_qp = fe_fine->n_quadrature_points();

      // The error contribution from this face
      Real error = 1.e-30;

      // loop over the integration points on the face.
      for (unsigned int qp=0; qp<n_qp; qp++)
        {
          // Value of the imposed flux BC at this quadrature point.
          const std::pair<bool,Real> flux_bc =
            this->_bc_function(*my_system, qface_point[qp], var_name);

          // Be sure the BC function still thinks we're on the
          // flux boundary.
          libmesh_assert_equal_to (flux_bc.first, true);

          // The solution gradient from each element
          Gradient grad_fine;

          // Compute the solution gradient on element e
          for (unsigned int i=0; i != Ufine.size(); i++)
            grad_fine.add_scaled (dphi_fine[i][qp], Ufine(i));

          // The difference between the desired BC and the approximate solution.
          const Number jump = flux_bc.second - grad_fine*face_normals[qp];

          // The flux jump squared.  If using complex numbers,
          // TensorTools::norm_sq(z) returns |z|^2, where |z| is the modulus of z.
          const Real jump2 = TensorTools::norm_sq(jump);

          // Integrate the error on the face.  The error is
          // scaled by an additional power of h, where h is
          // the maximum side length for the element.  This
          // arises in the definition of the indicator.
          error += JxW_face[qp]*jump2;

        } // End quadrature point loop

      fine_error = error*h*error_norm.weight(var);

      return true;
    } // end if side on flux boundary
  return false;
}

void
KellyErrorEstimator::attach_flux_bc_function (std::pair<bool,Real> fptr(const System& system,
									const Point& p,
									const std::string& var_name))
{
  _bc_function = fptr;

// We may be turning boundary side integration on or off
  if (fptr)
    integrate_boundary_sides = true;
  else
    integrate_boundary_sides = false;
}

} // namespace libMesh
<commit_msg>Trivial change to save intel-12.0 from itself.<commit_after>// The libMesh Finite Element Library.
// Copyright (C) 2002-2012 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

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

// This library 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
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ includes
#include <algorithm> // for std::fill
#include <cstdlib> // *must* precede <cmath> for proper std:abs() on PGI, Sun Studio CC
#include <cmath>    // for sqrt

// Local Includes
#include "libmesh/libmesh_common.h"
#include "libmesh/kelly_error_estimator.h"
#include "libmesh/error_vector.h"
#include "libmesh/fe_base.h"
#include "libmesh/libmesh_logging.h"
#include "libmesh/elem.h"
#include "libmesh/system.h"

#include "libmesh/dense_vector.h"
#include "libmesh/tensor_tools.h"

namespace libMesh
{

void
KellyErrorEstimator::initialize(const System& system,
                                ErrorVector&,
                                bool)
{
  // Hang onto the system - we may need it for variable names later.
  my_system = &system;

  // We'll need gradients and normal vectors for flux jump computation
  fe_fine->get_dphi();
  fe_fine->get_normals();
  fe_coarse->get_dphi();
}

void
KellyErrorEstimator::internal_side_integration ()
{
  Real error = 1.e-30;
  unsigned int n_qp = fe_fine->n_quadrature_points();
  unsigned int n_fine_dofs = Ufine.size();
  unsigned int n_coarse_dofs = Ucoarse.size();

  std::vector<std::vector<RealGradient> > dphi_coarse = fe_coarse->get_dphi();
  std::vector<std::vector<RealGradient> > dphi_fine = fe_fine->get_dphi();
  std::vector<Point> face_normals = fe_fine->get_normals();
  std::vector<Real> JxW_face = fe_fine->get_JxW();

  for (unsigned int qp=0; qp != n_qp; ++qp)
    {
      // Calculate solution gradients on fine and coarse elements
      // at this quadrature point
      Gradient grad_fine, grad_coarse;
      for (unsigned int i=0; i != n_coarse_dofs; ++i)
        grad_coarse.add_scaled (dphi_coarse[i][qp], Ucoarse(i));

      for (unsigned int i=0; i != n_fine_dofs; ++i)
        grad_fine.add_scaled (dphi_fine[i][qp], Ufine(i));

      // Find the jump in the normal derivative
      // at this quadrature point
      const Number jump = (grad_fine - grad_coarse)*face_normals[qp];
      const Real jump2 = TensorTools::norm_sq(jump);

      // Accumulate the jump integral
      error += JxW_face[qp] * jump2;
    }

  // Add the h-weighted jump integral to each error term
  fine_error =
    error * fine_elem->hmax() * error_norm.weight(var);
  coarse_error =
    error * coarse_elem->hmax() * error_norm.weight(var);
}

bool
KellyErrorEstimator::boundary_side_integration ()
{
  const std::string &var_name = my_system->variable_name(var);
  const unsigned int n_fine_dofs = Ufine.size();

  std::vector<std::vector<RealGradient> > dphi_fine = fe_fine->get_dphi();
  std::vector<Point> face_normals = fe_fine->get_normals();
  std::vector<Real> JxW_face = fe_fine->get_JxW();
  std::vector<Point> qface_point = fe_fine->get_xyz();

  // The reinitialization also recomputes the locations of
  // the quadrature points on the side.  By checking if the
  // first quadrature point on the side is on a flux boundary
  // for a particular variable, we will determine if the whole
  // element is on a flux boundary (assuming quadrature points
  // are strictly contained in the side).
  if (this->_bc_function(*my_system, qface_point[0], var_name).first)
    {
      const Real h = fine_elem->hmax();

      // The number of quadrature points
      const unsigned int n_qp = fe_fine->n_quadrature_points();

      // The error contribution from this face
      Real error = 1.e-30;

      // loop over the integration points on the face.
      for (unsigned int qp=0; qp<n_qp; qp++)
        {
          // Value of the imposed flux BC at this quadrature point.
          const std::pair<bool,Real> flux_bc =
            this->_bc_function(*my_system, qface_point[qp], var_name);

          // Be sure the BC function still thinks we're on the
          // flux boundary.
          libmesh_assert_equal_to (flux_bc.first, true);

          // The solution gradient from each element
          Gradient grad_fine;

          // Compute the solution gradient on element e
          for (unsigned int i=0; i != n_fine_dofs; i++)
            grad_fine.add_scaled (dphi_fine[i][qp], Ufine(i));

          // The difference between the desired BC and the approximate solution.
          const Number jump = flux_bc.second - grad_fine*face_normals[qp];

          // The flux jump squared.  If using complex numbers,
          // TensorTools::norm_sq(z) returns |z|^2, where |z| is the modulus of z.
          const Real jump2 = TensorTools::norm_sq(jump);

          // Integrate the error on the face.  The error is
          // scaled by an additional power of h, where h is
          // the maximum side length for the element.  This
          // arises in the definition of the indicator.
          error += JxW_face[qp]*jump2;

        } // End quadrature point loop

      fine_error = error*h*error_norm.weight(var);

      return true;
    } // end if side on flux boundary
  return false;
}

void
KellyErrorEstimator::attach_flux_bc_function (std::pair<bool,Real> fptr(const System& system,
									const Point& p,
									const std::string& var_name))
{
  _bc_function = fptr;

// We may be turning boundary side integration on or off
  if (fptr)
    integrate_boundary_sides = true;
  else
    integrate_boundary_sides = false;
}

} // namespace libMesh
<|endoftext|>


<commit_before>#include "Engine.h"
#include "Game.h"
#include "ObjectDummy.h"
#include "BodyRigid.h"
#include "BodyDummy.h"

#include "Physics.h"
#include "ShapeCapsule.h"
#include "ActorBase.h"
#include "Visualizer.h"
#include "sys/SysControl.h"

#ifdef MEMORY_INFO
#define new new(__FILE__, __LINE__)
#endif // MEMORY_INFO

using namespace MathLib;

/*
*/
#define ACTOR_BASE_IFPS             (1.0f / 60.0f)
#define ACTOR_BASE_CLAMP            89.9f
#define ACTOR_BASE_COLLISIONS       4

/*
*/

CActorBase::CActorBase()
{
	m_vUp = vec3(0.0f, 0.0f, 1.0f);
	m_pObject = new CObjectDummy();
	m_pDummy = new CBodyDummy();
	m_pShape = new CShapeCapsule(1.0f, 1.0f);

	m_nFlush = 0;
	m_vPosition = Vec3_zero;
	m_vVelocity = Vec3_zero;
	m_fPhiAngle = 0.0f;			//б		άƽϵУֱYķX֮ļн
	m_fThetaAngle = 0.0f;			//λǣ뵱ǰ˳ʱ߹ĽǶ

	for (int i = 0; i < NUM_STATES; i++)
	{
		m_pStates[i] = 0;
		m_pTimes[i] = 0.0f;
	}

	m_pDummy->SetEnabled(1);
	m_pObject->SetBody(NULL);
	m_pObject->SetBody(m_pDummy);
	m_pShape->SetBody(NULL);
	m_pShape->SetBody(m_pDummy);

	m_pObject->SetWorldTransform(Get_Body_Transform());
	m_pShape->SetRestitution(0.0f);
	m_pShape->SetCollisionMask(2);

	SetEnabled(1);
	SetViewDirection(vec3(0.0f,1.0f,0.0f));
	SetCollision(1);
	SetCollisionRadius(0.3f);
	SetCollisionHeight(1.0f);
	SetFriction(2.0f);
	SetMinVelocity(2.0f);
	SetMaxVelocity(4.0f);
	SetAcceleration(8.0f);
	SetDamping(8.0f);
	SetJumping(1.5f);

	SetGround(0);
	SetCeiling(0);

}
CActorBase::~CActorBase()
{
	m_pDummy->SetObject(NULL);
	delete m_pObject;
	delete m_pDummy;
}

void CActorBase::SetEnabled(int enable)
{
	m_nEnable = enable;
	m_pDummy->SetEnabled(m_nEnable);
}
int CActorBase::IsEnabled() const
{
	return m_nEnable;
}
<commit_msg>Signed-off-by: mrlitong <litongtongxue@gmail.com><commit_after>#include "Engine.h"
#include "Game.h"
#include "ObjectDummy.h"
#include "BodyRigid.h"
#include "BodyDummy.h"

#include "Physics.h"
#include "ShapeCapsule.h"
#include "ActorBase.h"
#include "Visualizer.h"
#include "sys/SysControl.h"

#ifdef MEMORY_INFO
#define new new(__FILE__, __LINE__)
#endif // MEMORY_INFO

using namespace MathLib;

/*
*/
#define ACTOR_BASE_IFPS             (1.0f / 60.0f)
#define ACTOR_BASE_CLAMP            89.9f
#define ACTOR_BASE_COLLISIONS       4

/*
*/

CActorBase::CActorBase()
{
	m_vUp = vec3(0.0f, 0.0f, 1.0f);
	m_pObject = new CObjectDummy();
	m_pDummy = new CBodyDummy();
	m_pShape = new CShapeCapsule(1.0f, 1.0f);

	m_nFlush = 0;
	m_vPosition = Vec3_zero;
	m_vVelocity = Vec3_zero;
	m_fPhiAngle = 0.0f;			//б		άƽϵУֱYķX֮ļн
	m_fThetaAngle = 0.0f;			//λǣ뵱ǰ˳ʱ߹ĽǶ

	for (int i = 0; i < NUM_STATES; i++)
	{
		m_pStates[i] = 0;
		m_pTimes[i] = 0.0f;
	}

	m_pDummy->SetEnabled(1);
	m_pObject->SetBody(NULL);
	m_pObject->SetBody(m_pDummy);
	m_pShape->SetBody(NULL);
	m_pShape->SetBody(m_pDummy);

	m_pObject->SetWorldTransform(Get_Body_Transform());
	m_pShape->SetRestitution(0.0f);
	m_pShape->SetCollisionMask(2);

	SetEnabled(1);
	SetViewDirection(vec3(0.0f,1.0f,0.0f));
	SetCollision(1);
	SetCollisionRadius(0.3f);
	SetCollisionHeight(1.0f);
	SetFriction(2.0f);
	SetMinVelocity(2.0f);
	SetMaxVelocity(4.0f);
	SetAcceleration(8.0f);
	SetDamping(8.0f);
	SetJumping(1.5f);

	SetGround(0);
	SetCeiling(0);

}
CActorBase::~CActorBase()
{
	m_pDummy->SetObject(NULL);
	delete m_pObject;
	delete m_pDummy;
}

void CActorBase::SetEnabled(int enable)
{
	m_nEnable = enable;
	m_pDummy->SetEnabled(m_nEnable);
}
int CActorBase::IsEnabled() const
{
	return m_nEnable;
}
void CActorBase::Update(float ifps)
{

}<|endoftext|>


<commit_before>//===-- Writer.cpp - Library for Printing VM assembly files ------*- C++ -*--=//
//
// This library implements the functionality defined in llvm/Assembly/Writer.h
//
// This library uses the Analysis library to figure out offsets for
// variables in the method tables...
//
// TODO: print out the type name instead of the full type if a particular type
//       is in the symbol table...
//
//===----------------------------------------------------------------------===//

#include "llvm/Assembly/Writer.h"
#include "llvm/Analysis/SlotCalculator.h"
#include "llvm/Module.h"
#include "llvm/Method.h"
#include "llvm/BasicBlock.h"
#include "llvm/ConstPoolVals.h"
#include "llvm/iOther.h"
#include "llvm/iMemory.h"

class AssemblyWriter : public ModuleAnalyzer {
  ostream &Out;
  SlotCalculator &Table;
public:
  inline AssemblyWriter(ostream &o, SlotCalculator &Tab) : Out(o), Table(Tab) {
  }

  inline void write(const Module *M)         { processModule(M);      }
  inline void write(const Method *M)         { processMethod(M);      }
  inline void write(const BasicBlock *BB)    { processBasicBlock(BB); }
  inline void write(const Instruction *I)    { processInstruction(I); }
  inline void write(const ConstPoolVal *CPV) { processConstant(CPV);  }

protected:
  virtual bool visitMethod(const Method *M);
  virtual bool processConstPool(const ConstantPool &CP, bool isMethod);
  virtual bool processConstant(const ConstPoolVal *CPV);
  virtual bool processMethod(const Method *M);
  virtual bool processMethodArgument(const MethodArgument *MA);
  virtual bool processBasicBlock(const BasicBlock *BB);
  virtual bool processInstruction(const Instruction *I);

private :
  void writeOperand(const Value *Op, bool PrintType, bool PrintName = true);
};

// visitMethod - This member is called after the above two steps, visting each
// method, because they are effectively values that go into the constant pool.
//
bool AssemblyWriter::visitMethod(const Method *M) {
  return false;
}

bool AssemblyWriter::processConstPool(const ConstantPool &CP, bool isMethod) {
  // Done printing arguments...
  if (isMethod) Out << ")\n";

  ModuleAnalyzer::processConstPool(CP, isMethod);

  if (isMethod)
    Out << "begin";
  else
    Out << "implementation\n";
  return false;
}

// processConstant - Print out a constant pool entry...
//
bool AssemblyWriter::processConstant(const ConstPoolVal *CPV) {
  Out << "\t";

  // Print out name if it exists...
  if (CPV->hasName())
    Out << "%" << CPV->getName() << " = ";

  // Print out the opcode...
  Out << CPV->getType();

  // Write the value out now...
  writeOperand(CPV, false, false);

  if (!CPV->hasName() && CPV->getType() != Type::VoidTy) {
    int Slot = Table.getValSlot(CPV); // Print out the def slot taken...
    Out << "\t\t; <" << CPV->getType() << ">:";
    if (Slot >= 0) Out << Slot;
    else Out << "<badref>";
  }

  Out << endl;
  return false;
}

// processMethod - Process all aspects of a method.
//
bool AssemblyWriter::processMethod(const Method *M) {
  // Print out the return type and name...
  Out << "\n" << M->getReturnType() << " \"" << M->getName() << "\"(";
  Table.incorporateMethod(M);
  ModuleAnalyzer::processMethod(M);
  Table.purgeMethod();
  Out << "end\n";
  return false;
}

// processMethodArgument - This member is called for every argument that
// is passed into the method.  Simply print it out
//
bool AssemblyWriter::processMethodArgument(const MethodArgument *Arg) {
  // Insert commas as we go... the first arg doesn't get a comma
  if (Arg != Arg->getParent()->getArgumentList().front()) Out << ", ";

  // Output type...
  Out << Arg->getType();

  // Output name, if available...
  if (Arg->hasName())
    Out << " %" << Arg->getName();
  else if (Table.getValSlot(Arg) < 0)
    Out << "<badref>";

  return false;
}

// processBasicBlock - This member is called for each basic block in a methd.
//
bool AssemblyWriter::processBasicBlock(const BasicBlock *BB) {
  if (BB->hasName()) {              // Print out the label if it exists...
    Out << "\n" << BB->getName() << ":";
  } else {
    int Slot = Table.getValSlot(BB);
    Out << "\n; <label>:";
    if (Slot >= 0)
      Out << Slot;         // Extra newline seperates out label's
    else
      Out << "<badref>";
  }
  Out << "\t\t\t\t\t;[#uses=" << BB->use_size() << "]\n";  // Output # uses

  ModuleAnalyzer::processBasicBlock(BB);
  return false;
}

// processInstruction - This member is called for each Instruction in a methd.
//
bool AssemblyWriter::processInstruction(const Instruction *I) {
  Out << "\t";

  // Print out name if it exists...
  if (I && I->hasName())
    Out << "%" << I->getName() << " = ";

  // Print out the opcode...
  Out << I->getOpcode();

  // Print out the type of the operands...
  const Value *Operand = I->getOperand(0);

  // Special case conditional branches to swizzle the condition out to the front
  if (I->getInstType() == Instruction::Br && I->getOperand(1)) {
    writeOperand(I->getOperand(2), true);
    Out << ",";
    writeOperand(Operand, true);
    Out << ",";
    writeOperand(I->getOperand(1), true);

  } else if (I->getInstType() == Instruction::Switch) {
    // Special case switch statement to get formatting nice and correct...
    writeOperand(Operand         , true); Out << ",";
    writeOperand(I->getOperand(1), true); Out << " [";

    for (unsigned op = 2; (Operand = I->getOperand(op)); op += 2) {
      Out << "\n\t\t";
      writeOperand(Operand, true); Out << ",";
      writeOperand(I->getOperand(op+1), true);
    }
    Out << "\n\t]";
  } else if (I->getInstType() == Instruction::PHINode) {
    Out << " " << Operand->getType();

    Out << " [";  writeOperand(Operand, false); Out << ",";
    writeOperand(I->getOperand(1), false); Out << "]";
    for (unsigned op = 2; (Operand = I->getOperand(op)); op += 2) {
      Out << ", [";  writeOperand(Operand, false); Out << ",";
      writeOperand(I->getOperand(op+1), false); Out << "]";
    }
  } else if (I->getInstType() == Instruction::Ret && !Operand) {
    Out << " void";
  } else if (I->getInstType() == Instruction::Call) {
    writeOperand(Operand, true);
    Out << "(";
    Operand = I->getOperand(1);
    if (Operand) writeOperand(Operand, true);
    for (unsigned op = 2; (Operand = I->getOperand(op)); ++op) {
      Out << ",";
      writeOperand(Operand, true);
    }

    Out << " )";
  } else if (I->getInstType() == Instruction::Malloc ||
	     I->getInstType() == Instruction::Alloca) {
    Out << " " << ((const PointerType*)((ConstPoolType*)Operand)
		   ->getValue())->getValueType();
    if ((Operand = I->getOperand(1))) {
      Out << ","; writeOperand(Operand, true);
    }

  } else if (Operand) {   // Print the normal way...

    // PrintAllTypes - Instructions who have operands of all the same type
    // omit the type from all but the first operand.  If the instruction has
    // different type operands (for example br), then they are all printed.
    bool PrintAllTypes = false;
    const Type *TheType = Operand->getType();
    unsigned i;

    for (i = 1; (Operand = I->getOperand(i)); i++) {
      if (Operand->getType() != TheType) {
	PrintAllTypes = true;       // We have differing types!  Print them all!
	break;
      }
    }

    if (!PrintAllTypes)
      Out << " " << I->getOperand(0)->getType();

    for (unsigned i = 0; (Operand = I->getOperand(i)); i++) {
      if (i) Out << ",";
      writeOperand(Operand, PrintAllTypes);
    }
  }

  // Print a little comment after the instruction indicating which slot it
  // occupies.
  //
  if (I->getType() != Type::VoidTy) {
    Out << "\t\t; <" << I->getType() << ">";

    if (!I->hasName()) {
      int Slot = Table.getValSlot(I); // Print out the def slot taken...
      if (Slot >= 0) Out << ":" << Slot;
      else Out << ":<badref>";
    }
    Out << "\t[#uses=" << I->use_size() << "]";  // Output # uses
  }
  Out << endl;

  return false;
}

void AssemblyWriter::writeOperand(const Value *Operand, bool PrintType,
				  bool PrintName) {
  if (PrintType)
    Out << " " << Operand->getType();

  if (Operand->hasName() && PrintName) {
    Out << " %" << Operand->getName();
  } else {
    int Slot = Table.getValSlot(Operand);

    if (Operand->getValueType() == Value::ConstantVal) {
      Out << " " << ((ConstPoolVal*)Operand)->getStrValue();
    } else {
      if (Slot >= 0)  Out << " %" << Slot;
      else if (PrintName)
        Out << "<badref>";     // Not embeded into a location?
    }
  }
}

//===----------------------------------------------------------------------===//
//                       External Interface declarations
//===----------------------------------------------------------------------===//

void WriteToAssembly(const Module *M, ostream &o) {
  if (M == 0) { o << "<null> module\n"; return; }
  SlotCalculator SlotTable(M, true);
  AssemblyWriter W(o, SlotTable);

  W.write(M);
}

void WriteToAssembly(const Method *M, ostream &o) {
  if (M == 0) { o << "<null> method\n"; return; }
  SlotCalculator SlotTable(M->getParent(), true);
  AssemblyWriter W(o, SlotTable);

  W.write(M);
}

void WriteToAssembly(const BasicBlock *BB, ostream &o) {
  if (BB == 0) { o << "<null> basic block\n"; return; }

  SlotCalculator SlotTable(BB->getParent(), true);
  AssemblyWriter W(o, SlotTable);

  W.write(BB);
}

void WriteToAssembly(const ConstPoolVal *CPV, ostream &o) {
  if (CPV == 0) { o << "<null> constant pool value\n"; return; }

  SlotCalculator *SlotTable;

  // A Constant pool value may have a parent that is either a method or a
  // module.  Untangle this now...
  //
  if (CPV->getParent() == 0 ||
      CPV->getParent()->getValueType() == Value::MethodVal) {
    SlotTable = new SlotCalculator((Method*)CPV->getParent(), true);
  } else {
    assert(CPV->getParent()->getValueType() == Value::ModuleVal);
    SlotTable = new SlotCalculator((Module*)CPV->getParent(), true);
  }

  AssemblyWriter W(o, *SlotTable);
  W.write(CPV);

  delete SlotTable;
}

void WriteToAssembly(const Instruction *I, ostream &o) {
  if (I == 0) { o << "<null> instruction\n"; return; }

  SlotCalculator SlotTable(I->getParent() ? I->getParent()->getParent() : 0,
			   true);
  AssemblyWriter W(o, SlotTable);

  W.write(I);
}
<commit_msg>Add a space to the PHI node output code to make it look nicer<commit_after>//===-- Writer.cpp - Library for Printing VM assembly files ------*- C++ -*--=//
//
// This library implements the functionality defined in llvm/Assembly/Writer.h
//
// This library uses the Analysis library to figure out offsets for
// variables in the method tables...
//
// TODO: print out the type name instead of the full type if a particular type
//       is in the symbol table...
//
//===----------------------------------------------------------------------===//

#include "llvm/Assembly/Writer.h"
#include "llvm/Analysis/SlotCalculator.h"
#include "llvm/Module.h"
#include "llvm/Method.h"
#include "llvm/BasicBlock.h"
#include "llvm/ConstPoolVals.h"
#include "llvm/iOther.h"
#include "llvm/iMemory.h"

class AssemblyWriter : public ModuleAnalyzer {
  ostream &Out;
  SlotCalculator &Table;
public:
  inline AssemblyWriter(ostream &o, SlotCalculator &Tab) : Out(o), Table(Tab) {
  }

  inline void write(const Module *M)         { processModule(M);      }
  inline void write(const Method *M)         { processMethod(M);      }
  inline void write(const BasicBlock *BB)    { processBasicBlock(BB); }
  inline void write(const Instruction *I)    { processInstruction(I); }
  inline void write(const ConstPoolVal *CPV) { processConstant(CPV);  }

protected:
  virtual bool visitMethod(const Method *M);
  virtual bool processConstPool(const ConstantPool &CP, bool isMethod);
  virtual bool processConstant(const ConstPoolVal *CPV);
  virtual bool processMethod(const Method *M);
  virtual bool processMethodArgument(const MethodArgument *MA);
  virtual bool processBasicBlock(const BasicBlock *BB);
  virtual bool processInstruction(const Instruction *I);

private :
  void writeOperand(const Value *Op, bool PrintType, bool PrintName = true);
};

// visitMethod - This member is called after the above two steps, visting each
// method, because they are effectively values that go into the constant pool.
//
bool AssemblyWriter::visitMethod(const Method *M) {
  return false;
}

bool AssemblyWriter::processConstPool(const ConstantPool &CP, bool isMethod) {
  // Done printing arguments...
  if (isMethod) Out << ")\n";

  ModuleAnalyzer::processConstPool(CP, isMethod);

  if (isMethod)
    Out << "begin";
  else
    Out << "implementation\n";
  return false;
}

// processConstant - Print out a constant pool entry...
//
bool AssemblyWriter::processConstant(const ConstPoolVal *CPV) {
  Out << "\t";

  // Print out name if it exists...
  if (CPV->hasName())
    Out << "%" << CPV->getName() << " = ";

  // Print out the opcode...
  Out << CPV->getType();

  // Write the value out now...
  writeOperand(CPV, false, false);

  if (!CPV->hasName() && CPV->getType() != Type::VoidTy) {
    int Slot = Table.getValSlot(CPV); // Print out the def slot taken...
    Out << "\t\t; <" << CPV->getType() << ">:";
    if (Slot >= 0) Out << Slot;
    else Out << "<badref>";
  }

  Out << endl;
  return false;
}

// processMethod - Process all aspects of a method.
//
bool AssemblyWriter::processMethod(const Method *M) {
  // Print out the return type and name...
  Out << "\n" << M->getReturnType() << " \"" << M->getName() << "\"(";
  Table.incorporateMethod(M);
  ModuleAnalyzer::processMethod(M);
  Table.purgeMethod();
  Out << "end\n";
  return false;
}

// processMethodArgument - This member is called for every argument that
// is passed into the method.  Simply print it out
//
bool AssemblyWriter::processMethodArgument(const MethodArgument *Arg) {
  // Insert commas as we go... the first arg doesn't get a comma
  if (Arg != Arg->getParent()->getArgumentList().front()) Out << ", ";

  // Output type...
  Out << Arg->getType();

  // Output name, if available...
  if (Arg->hasName())
    Out << " %" << Arg->getName();
  else if (Table.getValSlot(Arg) < 0)
    Out << "<badref>";

  return false;
}

// processBasicBlock - This member is called for each basic block in a methd.
//
bool AssemblyWriter::processBasicBlock(const BasicBlock *BB) {
  if (BB->hasName()) {              // Print out the label if it exists...
    Out << "\n" << BB->getName() << ":";
  } else {
    int Slot = Table.getValSlot(BB);
    Out << "\n; <label>:";
    if (Slot >= 0)
      Out << Slot;         // Extra newline seperates out label's
    else
      Out << "<badref>";
  }
  Out << "\t\t\t\t\t;[#uses=" << BB->use_size() << "]\n";  // Output # uses

  ModuleAnalyzer::processBasicBlock(BB);
  return false;
}

// processInstruction - This member is called for each Instruction in a methd.
//
bool AssemblyWriter::processInstruction(const Instruction *I) {
  Out << "\t";

  // Print out name if it exists...
  if (I && I->hasName())
    Out << "%" << I->getName() << " = ";

  // Print out the opcode...
  Out << I->getOpcode();

  // Print out the type of the operands...
  const Value *Operand = I->getOperand(0);

  // Special case conditional branches to swizzle the condition out to the front
  if (I->getInstType() == Instruction::Br && I->getOperand(1)) {
    writeOperand(I->getOperand(2), true);
    Out << ",";
    writeOperand(Operand, true);
    Out << ",";
    writeOperand(I->getOperand(1), true);

  } else if (I->getInstType() == Instruction::Switch) {
    // Special case switch statement to get formatting nice and correct...
    writeOperand(Operand         , true); Out << ",";
    writeOperand(I->getOperand(1), true); Out << " [";

    for (unsigned op = 2; (Operand = I->getOperand(op)); op += 2) {
      Out << "\n\t\t";
      writeOperand(Operand, true); Out << ",";
      writeOperand(I->getOperand(op+1), true);
    }
    Out << "\n\t]";
  } else if (I->getInstType() == Instruction::PHINode) {
    Out << " " << Operand->getType();

    Out << " [";  writeOperand(Operand, false); Out << ",";
    writeOperand(I->getOperand(1), false); Out << " ]";
    for (unsigned op = 2; (Operand = I->getOperand(op)); op += 2) {
      Out << ", [";  writeOperand(Operand, false); Out << ",";
      writeOperand(I->getOperand(op+1), false); Out << " ]";
    }
  } else if (I->getInstType() == Instruction::Ret && !Operand) {
    Out << " void";
  } else if (I->getInstType() == Instruction::Call) {
    writeOperand(Operand, true);
    Out << "(";
    Operand = I->getOperand(1);
    if (Operand) writeOperand(Operand, true);
    for (unsigned op = 2; (Operand = I->getOperand(op)); ++op) {
      Out << ",";
      writeOperand(Operand, true);
    }

    Out << " )";
  } else if (I->getInstType() == Instruction::Malloc ||
	     I->getInstType() == Instruction::Alloca) {
    Out << " " << ((const PointerType*)((ConstPoolType*)Operand)
		   ->getValue())->getValueType();
    if ((Operand = I->getOperand(1))) {
      Out << ","; writeOperand(Operand, true);
    }

  } else if (Operand) {   // Print the normal way...

    // PrintAllTypes - Instructions who have operands of all the same type
    // omit the type from all but the first operand.  If the instruction has
    // different type operands (for example br), then they are all printed.
    bool PrintAllTypes = false;
    const Type *TheType = Operand->getType();
    unsigned i;

    for (i = 1; (Operand = I->getOperand(i)); i++) {
      if (Operand->getType() != TheType) {
	PrintAllTypes = true;       // We have differing types!  Print them all!
	break;
      }
    }

    if (!PrintAllTypes)
      Out << " " << I->getOperand(0)->getType();

    for (unsigned i = 0; (Operand = I->getOperand(i)); i++) {
      if (i) Out << ",";
      writeOperand(Operand, PrintAllTypes);
    }
  }

  // Print a little comment after the instruction indicating which slot it
  // occupies.
  //
  if (I->getType() != Type::VoidTy) {
    Out << "\t\t; <" << I->getType() << ">";

    if (!I->hasName()) {
      int Slot = Table.getValSlot(I); // Print out the def slot taken...
      if (Slot >= 0) Out << ":" << Slot;
      else Out << ":<badref>";
    }
    Out << "\t[#uses=" << I->use_size() << "]";  // Output # uses
  }
  Out << endl;

  return false;
}

void AssemblyWriter::writeOperand(const Value *Operand, bool PrintType,
				  bool PrintName) {
  if (PrintType)
    Out << " " << Operand->getType();

  if (Operand->hasName() && PrintName) {
    Out << " %" << Operand->getName();
  } else {
    int Slot = Table.getValSlot(Operand);

    if (Operand->getValueType() == Value::ConstantVal) {
      Out << " " << ((ConstPoolVal*)Operand)->getStrValue();
    } else {
      if (Slot >= 0)  Out << " %" << Slot;
      else if (PrintName)
        Out << "<badref>";     // Not embeded into a location?
    }
  }
}

//===----------------------------------------------------------------------===//
//                       External Interface declarations
//===----------------------------------------------------------------------===//

void WriteToAssembly(const Module *M, ostream &o) {
  if (M == 0) { o << "<null> module\n"; return; }
  SlotCalculator SlotTable(M, true);
  AssemblyWriter W(o, SlotTable);

  W.write(M);
}

void WriteToAssembly(const Method *M, ostream &o) {
  if (M == 0) { o << "<null> method\n"; return; }
  SlotCalculator SlotTable(M->getParent(), true);
  AssemblyWriter W(o, SlotTable);

  W.write(M);
}

void WriteToAssembly(const BasicBlock *BB, ostream &o) {
  if (BB == 0) { o << "<null> basic block\n"; return; }

  SlotCalculator SlotTable(BB->getParent(), true);
  AssemblyWriter W(o, SlotTable);

  W.write(BB);
}

void WriteToAssembly(const ConstPoolVal *CPV, ostream &o) {
  if (CPV == 0) { o << "<null> constant pool value\n"; return; }

  SlotCalculator *SlotTable;

  // A Constant pool value may have a parent that is either a method or a
  // module.  Untangle this now...
  //
  if (CPV->getParent() == 0 ||
      CPV->getParent()->getValueType() == Value::MethodVal) {
    SlotTable = new SlotCalculator((Method*)CPV->getParent(), true);
  } else {
    assert(CPV->getParent()->getValueType() == Value::ModuleVal);
    SlotTable = new SlotCalculator((Module*)CPV->getParent(), true);
  }

  AssemblyWriter W(o, *SlotTable);
  W.write(CPV);

  delete SlotTable;
}

void WriteToAssembly(const Instruction *I, ostream &o) {
  if (I == 0) { o << "<null> instruction\n"; return; }

  SlotCalculator SlotTable(I->getParent() ? I->getParent()->getParent() : 0,
			   true);
  AssemblyWriter W(o, SlotTable);

  W.write(I);
}
<|endoftext|>


<commit_before>/**************************************************************************

 The MIT License (MIT)

 Copyright (c) 2015 Dmitry Sovetov

 https://github.com/dmsovetov

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:
 The above copyright notice and this permission notice shall be included in all
 copies or substantial portions of the Software.
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 SOFTWARE.

 **************************************************************************/

// Include a Platform module header.
#include <platform/Platform.h>

// Open a root engine namespace
DC_USE_DREEMCHEST

// Open a platform namespace to use shorter types.
using namespace platform;

// This class is a key for handling events raised by Window.
// Yes, this is a window delegate class, and it works in the
// same way as an application delegate.
class WindowHandler : public WindowDelegate {

    // This method is called when mouse/touch is pressed.
    virtual void handleMouseDown( Window* window, u32 x, u32 y, int touchId ) {
        platform::log::msg( "handleMouseDown : %d %d\n", x, y );
    }

    // This method is called when mouse/touch is released.
    virtual void handleMouseUp( Window* window, u32 x, u32 y, int touchId ) {
        platform::log::msg( "handleMouseUp : %d %d\n", x, y );
    }

    // This method is called when mouse/touch is moved.
    virtual void handleMouseMove( Window* window, u32 sx, u32 sy, u32 ex, u32 ey, int touchId ) {
        platform::log::msg( "handleMouseMove : %d %d\n", ex, ey );
    }

    // This method is called when key is pressed.
    virtual void handleKeyDown( Window* window, Key key ) {
        platform::log::msg( "handleKeyDown : %d\n", key );
    }

    // This method is called when key is released.
    virtual void handleKeyUp( Window* window, Key key ) {
        platform::log::msg( "handleKeyUp : %d\n", key );
    }

    // This method is called each frame
    virtual void handleUpdate( Window* window ) {

    }
};

// Application delegate is used to handle an events raised by application instance.
class WindowEvents : public ApplicationDelegate {

    // This method will be called once an application is launched.
    virtual void handleLaunched( Application* application ) {

        platform::log::setStandardHandler();

        // Create a 800x600 window like we did in previous example.
        Window* window = Window::create( 800, 600 );

        // Now set a window delegate.
        window->setDelegate( new WindowHandler );
    }
};

// Now declare an application entry point with WindowEvents application delegate.
dcDeclareApplication( new WindowEvents )<commit_msg>Fixed compilation issue<commit_after>/**************************************************************************

 The MIT License (MIT)

 Copyright (c) 2015 Dmitry Sovetov

 https://github.com/dmsovetov

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:
 The above copyright notice and this permission notice shall be included in all
 copies or substantial portions of the Software.
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 SOFTWARE.

 **************************************************************************/

// Include a Platform module header.
#include <platform/Platform.h>

// Open a root engine namespace
DC_USE_DREEMCHEST

// Open a platform namespace to use shorter types.
using namespace platform;

// This class is a key for handling events raised by Window.
// Yes, this is a window delegate class, and it works in the
// same way as an application delegate.
class WindowHandler : public WindowDelegate {

    // This method is called when mouse/touch is pressed.
    virtual void handleMouseDown( Window* window, u32 x, u32 y, int touchId ) {
        platform::log::msg( "handleMouseDown : %d %d\n", x, y );
    }

    // This method is called when mouse/touch is released.
    virtual void handleMouseUp( Window* window, u32 x, u32 y, int touchId ) {
        platform::log::msg( "handleMouseUp : %d %d\n", x, y );
    }

    // This method is called when mouse/touch is moved.
    virtual void handleMouseMove( Window* window, u32 sx, u32 sy, u32 ex, u32 ey, int touchId ) {
        platform::log::msg( "handleMouseMove : %d %d\n", ex, ey );
    }

    // This method is called when key is pressed.
    virtual void handleKeyDown( Window* window, Key key ) {
        platform::log::msg( "handleKeyDown : %d\n", (int)key );
    }

    // This method is called when key is released.
    virtual void handleKeyUp( Window* window, Key key ) {
        platform::log::msg( "handleKeyUp : %d\n", (int)key );
    }

    // This method is called each frame
    virtual void handleUpdate( Window* window ) {

    }
};

// Application delegate is used to handle an events raised by application instance.
class WindowEvents : public ApplicationDelegate {

    // This method will be called once an application is launched.
    virtual void handleLaunched( Application* application ) {

        platform::log::setStandardHandler();

        // Create a 800x600 window like we did in previous example.
        Window* window = Window::create( 800, 600 );

        // Now set a window delegate.
        window->setDelegate( new WindowHandler );
    }
};

// Now declare an application entry point with WindowEvents application delegate.
dcDeclareApplication( new WindowEvents )<|endoftext|>


<commit_before>#include "Engine.h"
#include "Game.h"
#include "ObjectDummy.h"

#ifdef MEMORY_INFO
#define new new(__FILE__, __LINE__)
#endif // MEMORY_INFO

CActorBase::CActorBase()
{
	m_vUp = vec3(0.0f, 0.0f, 1.0f);
	m_pObject = new CObjectDummy();
	m_pDummy = new CBodyDummy();
	m_pShape = new CShapeCapsule(1.0f, 1.0f);

	m_nFlush = 0;
	m_vPosition = Vec3_zero;
	m_vVelocity = Vec3_zero;
	m_fPhiAngle = 0.0f;			//б		άƽϵУֱYķX֮ļн
	m_fThetaAngle = 0.0f;			//λǣ뵱ǰ˳ʱ߹ĽǶ

	for (int i = 0; i < NUM_STATES; i++)
	{
		m_pStates[i] = 0;
		m_pTimes[i] = 0.0f;
	}
}<commit_msg>Signed-off-by: mrlitong <litongtongxue@gmail.com><commit_after>#include "Engine.h"
#include "Game.h"
#include "ObjectDummy.h"
#include "BodyRigid.h"
#include "BodyDummy.h"

#ifdef MEMORY_INFO
#define new new(__FILE__, __LINE__)
#endif // MEMORY_INFO

CActorBase::CActorBase()
{
	m_vUp = vec3(0.0f, 0.0f, 1.0f);
	m_pObject = new CObjectDummy();
	m_pDummy = new CBodyDummy();
	m_pShape = new CShapeCapsule(1.0f, 1.0f);

	m_nFlush = 0;
	m_vPosition = Vec3_zero;
	m_vVelocity = Vec3_zero;
	m_fPhiAngle = 0.0f;			//б		άƽϵУֱYķX֮ļн
	m_fThetaAngle = 0.0f;			//λǣ뵱ǰ˳ʱ߹ĽǶ

	for (int i = 0; i < NUM_STATES; i++)
	{
		m_pStates[i] = 0;
		m_pTimes[i] = 0.0f;
	}

}<|endoftext|>


<commit_before>/*
Copyright (c) 2012 Carsten Burstedde, Donna Calhoun
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "amr_includes.H"
#include "fc2d_clawpack46.H"
#include "swirl_user.H"

#ifdef __cplusplus
extern "C"
{
#if 0
}
#endif
#endif

void swirl_link_solvers(fclaw2d_domain_t *domain)
{
    fclaw2d_solver_functions_t* sf = get_solver_functions(domain);

    sf->use_single_step_update = fclaw_true;
    sf->use_mol_update = fclaw_false;

    sf->f_patch_setup              = &swirl_patch_setup;
    sf->f_patch_initialize         = &swirl_patch_initialize;
    sf->f_patch_physical_bc        = &swirl_patch_physical_bc;
    sf->f_patch_single_step_update = &swirl_patch_single_step_update;

    fclaw2d_output_functions_t* of = get_output_functions(domain);
    of->f_patch_write_header = &swirl_parallel_write_header;
    of->f_patch_write_output = &swirl_parallel_write_output;

    fc2d_clawpack46_link_to_clawpatch();
}

void swirl_problem_setup(fclaw2d_domain_t* domain)
{
    fc2d_clawpack46_setprob(domain);
}

void swirl_patch_setup(fclaw2d_domain_t *domain,
                          fclaw2d_patch_t *this_patch,
                          int this_block_idx,
                          int this_patch_idx)
{
    fc2d_clawpack46_setaux(domain,this_patch,this_block_idx,this_patch_idx);
}

void swirl_patch_initialize(fclaw2d_domain_t *domain,
                            fclaw2d_patch_t *this_patch,
                            int this_block_idx,
                            int this_patch_idx)
{
    fc2d_clawpack46_qinit(domain,this_patch,this_block_idx,this_patch_idx);
}

void swirl_patch_physical_bc(fclaw2d_domain *domain,
                             fclaw2d_patch_t *this_patch,
                             int this_block_idx,
                             int this_patch_idx,
                             double t,
                             double dt,
                             fclaw_bool intersects_bc[],
                             fclaw_bool time_interp)
{
    fc2d_clawpack46_bc2(domain,this_patch,this_block_idx,this_patch_idx,
                     t,dt,intersects_bc,time_interp);
}

double swirl_patch_single_step_update(fclaw2d_domain_t *domain,
                                      fclaw2d_patch_t *this_patch,
                                      int this_block_idx,
                                      int this_patch_idx,
                                      double t,
                                      double dt)
{
    fc2d_clawpack46_b4step2(domain,this_patch,this_block_idx,this_patch_idx,t,dt);

    double maxcfl = fc2d_clawpack46_step2(domain,this_patch,this_block_idx,
                                       this_patch_idx,t,dt);
    return maxcfl;
}

/* -----------------------------------------------------------------
   Default routine for tagging patches for refinement and coarsening
   ----------------------------------------------------------------- */
fclaw_bool swirl_patch_tag4refinement(fclaw2d_domain_t *domain,
                                      fclaw2d_patch_t *this_patch,
                                      int this_block_idx, int this_patch_idx,
                                      int initflag)
{
    /* ----------------------------------------------------------- */
    // Global parameters
    const amr_options_t *gparms = get_domain_parms(domain);
    int mx = gparms->mx;
    int my = gparms->my;
    int mbc = gparms->mbc;
    int meqn = gparms->meqn;

    /* ----------------------------------------------------------- */
    // Patch specific parameters
    ClawPatch *cp = get_clawpatch(this_patch);
    double xlower = cp->xlower();
    double ylower = cp->ylower();
    double dx = cp->dx();
    double dy = cp->dy();

    /* ------------------------------------------------------------ */
    // Pointers needed to pass to Fortran
    double* q = cp->q();

    int tag_patch = 0;
    swirl_tag4refinement_(mx,my,mbc,meqn,xlower,ylower,dx,dy,q,initflag,tag_patch);
    return tag_patch == 1;
}

fclaw_bool swirl_patch_tag4coarsening(fclaw2d_domain_t *domain,
                                      fclaw2d_patch_t *this_patch,
                                      int blockno,
                                      int patchno)
{
    /* ----------------------------------------------------------- */
    // Global parameters
    const amr_options_t *gparms = get_domain_parms(domain);
    int mx = gparms->mx;
    int my = gparms->my;
    int mbc = gparms->mbc;
    int meqn = gparms->meqn;

    /* ----------------------------------------------------------- */
    // Patch specific parameters
    ClawPatch *cp = get_clawpatch(this_patch);
    double xlower = cp->xlower();
    double ylower = cp->ylower();
    double dx = cp->dx();
    double dy = cp->dy();

    /* ------------------------------------------------------------ */
    // Pointers needed to pass to Fortran
    double* qcoarse = cp->q();

    int tag_patch = 1;  // == 0 or 1
    swirl_tag4coarsening_(mx,my,mbc,meqn,xlower,ylower,dx,dy,qcoarse,tag_patch);
    return tag_patch == 0;
}

void swirl_parallel_write_header(fclaw2d_domain_t* domain, int iframe, int ngrids)
{
    const amr_options_t *gparms = get_domain_parms(domain);
    double time = get_domain_time(domain);

    printf("Matlab output Frame %d  at time %16.8e\n\n",iframe,time);

    // Write out header file containing global information for 'iframe'
    int mfields = gparms->meqn;
    int maux = 0;
    swirl_write_tfile_(iframe,time,mfields,ngrids,maux);

    // This opens file 'fort.qXXXX' for replace (where XXXX = <zero padding><iframe>, e.g. 0001,
    // 0010, 0114), and closes the file.
    new_qfile_(iframe);
}

void swirl_parallel_write_output(fclaw2d_domain_t *domain, fclaw2d_patch_t *this_patch,
                                  int this_block_idx, int this_patch_idx,
                                  int iframe,int num,int level)
{
    /* ----------------------------------------------------------- */
    // Global parameters
    const amr_options_t *gparms = get_domain_parms(domain);
    int mx = gparms->mx;
    int my = gparms->my;
    int mbc = gparms->mbc;
    int meqn = gparms->meqn;

    /* ----------------------------------------------------------- */
    // Patch specific parameters
    ClawPatch *cp = get_clawpatch(this_patch);
    double xlower = cp->xlower();
    double ylower = cp->ylower();
    double dx = cp->dx();
    double dy = cp->dy();

    /* ------------------------------------------------------------ */
    // Pointers needed to pass to Fortran
    double* q = cp->q();

    /* ------------------------------------------------------------- */
    // This opens a file for append.  Now, the style is in the 'clawout' style.
    int matlab_level = level;

    int mpirank = domain->mpirank;
    swirl_write_qfile_(meqn,mbc,mx,my,xlower,ylower,dx,dy,q,
                       iframe,num,matlab_level,this_block_idx,
                       mpirank);
}

#ifdef __cplusplus
#if 0
{
#endif
}
#endif
<commit_msg>(swirl) Add clawpack vtable<commit_after>/*
Copyright (c) 2012 Carsten Burstedde, Donna Calhoun
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "amr_includes.H"
#include "fc2d_clawpack46.H"
#include "swirl_user.H"

#ifdef __cplusplus
extern "C"
{
#if 0
}
#endif
#endif

static const fc2d_clawpack46_vtable_t classic_user =
{
    setprob_,
    NULL,  /* bc2 */
    qinit_,
    setaux_,
    b4step2_,
    NULL  /* src2 */
};

void swirl_link_solvers(fclaw2d_domain_t *domain)
{
    fclaw2d_solver_functions_t* sf = get_solver_functions(domain);

    sf->use_single_step_update = fclaw_true;
    sf->use_mol_update = fclaw_false;

    sf->f_patch_setup              = &swirl_patch_setup;
    sf->f_patch_initialize         = &swirl_patch_initialize;
    sf->f_patch_physical_bc        = &swirl_patch_physical_bc;
    sf->f_patch_single_step_update = &swirl_patch_single_step_update;

    fclaw2d_output_functions_t* of = get_output_functions(domain);
    of->f_patch_write_header = &swirl_parallel_write_header;
    of->f_patch_write_output = &swirl_parallel_write_output;

    fc2d_clawpack46_set_vtable(&classic_user);

    fc2d_clawpack46_link_to_clawpatch();
}

void swirl_problem_setup(fclaw2d_domain_t* domain)
{
    fc2d_clawpack46_setprob();
}

void swirl_patch_setup(fclaw2d_domain_t *domain,
                          fclaw2d_patch_t *this_patch,
                          int this_block_idx,
                          int this_patch_idx)
{
    fc2d_clawpack46_setaux(domain,this_patch,this_block_idx,this_patch_idx);
}

void swirl_patch_initialize(fclaw2d_domain_t *domain,
                            fclaw2d_patch_t *this_patch,
                            int this_block_idx,
                            int this_patch_idx)
{
    fc2d_clawpack46_qinit(domain,this_patch,this_block_idx,this_patch_idx);
}

void swirl_patch_physical_bc(fclaw2d_domain *domain,
                             fclaw2d_patch_t *this_patch,
                             int this_block_idx,
                             int this_patch_idx,
                             double t,
                             double dt,
                             fclaw_bool intersects_bc[],
                             fclaw_bool time_interp)
{
    fc2d_clawpack46_bc2(domain,this_patch,this_block_idx,this_patch_idx,
                     t,dt,intersects_bc,time_interp);
}

double swirl_patch_single_step_update(fclaw2d_domain_t *domain,
                                      fclaw2d_patch_t *this_patch,
                                      int this_block_idx,
                                      int this_patch_idx,
                                      double t,
                                      double dt)
{
    fc2d_clawpack46_b4step2(domain,this_patch,this_block_idx,this_patch_idx,t,dt);

    double maxcfl = fc2d_clawpack46_step2(domain,this_patch,this_block_idx,
                                       this_patch_idx,t,dt);
    return maxcfl;
}

/* -----------------------------------------------------------------
   Default routine for tagging patches for refinement and coarsening
   ----------------------------------------------------------------- */
fclaw_bool swirl_patch_tag4refinement(fclaw2d_domain_t *domain,
                                      fclaw2d_patch_t *this_patch,
                                      int this_block_idx, int this_patch_idx,
                                      int initflag)
{
    /* ----------------------------------------------------------- */
    // Global parameters
    const amr_options_t *gparms = get_domain_parms(domain);
    int mx = gparms->mx;
    int my = gparms->my;
    int mbc = gparms->mbc;
    int meqn = gparms->meqn;

    /* ----------------------------------------------------------- */
    // Patch specific parameters
    ClawPatch *cp = get_clawpatch(this_patch);
    double xlower = cp->xlower();
    double ylower = cp->ylower();
    double dx = cp->dx();
    double dy = cp->dy();

    /* ------------------------------------------------------------ */
    // Pointers needed to pass to Fortran
    double* q = cp->q();

    int tag_patch = 0;
    swirl_tag4refinement_(mx,my,mbc,meqn,xlower,ylower,dx,dy,q,initflag,tag_patch);
    return tag_patch == 1;
}

fclaw_bool swirl_patch_tag4coarsening(fclaw2d_domain_t *domain,
                                      fclaw2d_patch_t *this_patch,
                                      int blockno,
                                      int patchno)
{
    /* ----------------------------------------------------------- */
    // Global parameters
    const amr_options_t *gparms = get_domain_parms(domain);
    int mx = gparms->mx;
    int my = gparms->my;
    int mbc = gparms->mbc;
    int meqn = gparms->meqn;

    /* ----------------------------------------------------------- */
    // Patch specific parameters
    ClawPatch *cp = get_clawpatch(this_patch);
    double xlower = cp->xlower();
    double ylower = cp->ylower();
    double dx = cp->dx();
    double dy = cp->dy();

    /* ------------------------------------------------------------ */
    // Pointers needed to pass to Fortran
    double* qcoarse = cp->q();

    int tag_patch = 1;  // == 0 or 1
    swirl_tag4coarsening_(mx,my,mbc,meqn,xlower,ylower,dx,dy,qcoarse,tag_patch);
    return tag_patch == 0;
}

void swirl_parallel_write_header(fclaw2d_domain_t* domain, int iframe, int ngrids)
{
    const amr_options_t *gparms = get_domain_parms(domain);
    double time = get_domain_time(domain);

    printf("Matlab output Frame %d  at time %16.8e\n\n",iframe,time);

    // Write out header file containing global information for 'iframe'
    int mfields = gparms->meqn;
    int maux = 0;
    swirl_write_tfile_(iframe,time,mfields,ngrids,maux);

    // This opens file 'fort.qXXXX' for replace (where XXXX = <zero padding><iframe>, e.g. 0001,
    // 0010, 0114), and closes the file.
    new_qfile_(iframe);
}

void swirl_parallel_write_output(fclaw2d_domain_t *domain, fclaw2d_patch_t *this_patch,
                                  int this_block_idx, int this_patch_idx,
                                  int iframe,int num,int level)
{
    /* ----------------------------------------------------------- */
    // Global parameters
    const amr_options_t *gparms = get_domain_parms(domain);
    int mx = gparms->mx;
    int my = gparms->my;
    int mbc = gparms->mbc;
    int meqn = gparms->meqn;

    /* ----------------------------------------------------------- */
    // Patch specific parameters
    ClawPatch *cp = get_clawpatch(this_patch);
    double xlower = cp->xlower();
    double ylower = cp->ylower();
    double dx = cp->dx();
    double dy = cp->dy();

    /* ------------------------------------------------------------ */
    // Pointers needed to pass to Fortran
    double* q = cp->q();

    /* ------------------------------------------------------------- */
    // This opens a file for append.  Now, the style is in the 'clawout' style.
    int matlab_level = level;

    int mpirank = domain->mpirank;
    swirl_write_qfile_(meqn,mbc,mx,my,xlower,ylower,dx,dy,q,
                       iframe,num,matlab_level,this_block_idx,
                       mpirank);
}

#ifdef __cplusplus
#if 0
{
#endif
}
#endif
<|endoftext|>


<commit_before>#ifndef CAN_EMULATOR

#include "usbutil.h"
#include "canread.h"
#include "serialutil.h"
#include "signals.h"
#include "log.h"
#include "cJSON.h"
#include "listener.h"
#include <stdint.h>

extern SerialDevice SERIAL_DEVICE;
extern UsbDevice USB_DEVICE;
extern Listener listener;

/* Forward declarations */

void receiveCan(CanBus*);
void initializeAllCan();
bool receiveWriteRequest(uint8_t*);
bool receiveCANWriteRequest(uint8_t*);

void setup() {
    initializeLogging();
    initializeSerial(&SERIAL_DEVICE);
    initializeUsb(&USB_DEVICE);
    initializeAllCan();
}

void loop() {
    for(int i = 0; i < getCanBusCount(); i++) {
        receiveCan(&getCanBuses()[i]);
    }
    processListenerQueues(&listener);
#ifdef TRANSMITTER
    readFromHost(&USB_DEVICE, &receiveCANWriteRequest);
    readFromSerial(&SERIAL_DEVICE, &receiveCANWriteRequest);
#else
    readFromHost(&USB_DEVICE, &receiveWriteRequest);
    readFromSerial(&SERIAL_DEVICE, &receiveWriteRequest);
    for(int i = 0; i < getCanBusCount(); i++) {
        processCanWriteQueue(&getCanBuses()[i]);
    }
#endif
}

void initializeAllCan() {
    for(int i = 0; i < getCanBusCount(); i++) {
        initializeCan(&(getCanBuses()[i]));
    }
}
#ifdef TRANSMITTER
bool receiveCANWriteRequest(uint8_t* message) {
    int index=0;
    int packetLength = 15;

    while(true) {
      if(message[index] == '!') {
        return true;
      }

      if (index + packetLength >= 64) {
          debug("!");
      }

      if(message[index] != '{' || message[index+5] != '|'
              || message[index+14] != '}') {
          debug("Received a corrupted CAN message.\r\n");
          for(int i = 0; i < 16; i++) {
              debug("%02x ", message[index+i] );
          }
          debug("\r\n");
          return false;
      }

      CanMessage outGoing = {0, 0};

      memcpy((uint8_t*)&outGoing.id, &message[index+1], 4);

      for(int i = 0; i < 8; i++) {
          ((uint8_t*)&(outGoing.data))[i] = message[index+i+6];
      }

      //    debug("Sending CAN message id = 0x%02x, data = 0x", outGoing.id);
      //for(int i = 0; i < 8; i++) {
      //    debug("%02x ", ((uint8_t*)&(outGoing.data))[i] );
      //}
      //debug("\r\n");

      sendCanMessage(&(getCanBuses()[0]), outGoing);
      index += packetLength;
    }

    return true;
}

#else    //ifdef TRANSMITTER

bool receiveRawWriteRequest(cJSON* idObject, cJSON* root) {
    int id = idObject->valueint;
    cJSON* dataObject = cJSON_GetObjectItem(root, "data");
    if(dataObject == NULL) {
        debug("Raw write request missing data\r\n", id);
        return true;
    }
    int data = dataObject->valueint;
    CanMessage message = {id, data};
    QUEUE_PUSH(CanMessage, &getCanBuses()[0].sendQueue, message);
    return true;
}

bool receiveWriteRequest(uint8_t* message) {

    cJSON *root = cJSON_Parse((char*)message);
    if(root != NULL) {
        cJSON* nameObject = cJSON_GetObjectItem(root, "name");
        if(nameObject == NULL) {
            cJSON* idObject = cJSON_GetObjectItem(root, "id");
            if(idObject == NULL) {
                debug("Write request is malformed, "
                        "missing name or id: %s\r\n", message);
                return true;
            } else {
                return receiveRawWriteRequest(idObject, root);
            }
        }

        char* name = nameObject->valuestring;
        cJSON* value = cJSON_GetObjectItem(root, "value");
        if(value == NULL) {
            debug("Write request for %s missing value\r\n", name);
            return true;
        }

        CanSignal* signal = lookupSignal(name, getSignals(),
                getSignalCount(), true);
        CanCommand* command = lookupCommand(name, getCommands(),
                getCommandCount());
        if(signal != NULL) {
            sendCanSignal(signal, value, getSignals(), getSignalCount());
        } else if(command != NULL) {
            command->handler(name, value, getSignals(), getSignalCount());
        } else {
            debug("Writing not allowed for signal with name %s\r\n", name);
        }
        cJSON_Delete(root);
        return true;
    }
    return false;
}
#endif
/*
 * Check to see if a packet has been received. If so, read the packet and print
 * the packet payload to the serial monitor.
 */
void receiveCan(CanBus* bus) {
    // TODO what happens if we process until the queue is empty?
    if(!QUEUE_EMPTY(CanMessage, &bus->receiveQueue)) {
        CanMessage message = QUEUE_POP(CanMessage, &bus->receiveQueue);
        decodeCanMessage(message.id, message.data);
    }
}

void reset() {
    initializeAllCan();
}

#endif // CAN_EMULATOR
<commit_msg>Use CAN write queue when acting as a transmitter.<commit_after>#ifndef CAN_EMULATOR

#include "usbutil.h"
#include "canread.h"
#include "serialutil.h"
#include "signals.h"
#include "log.h"
#include "cJSON.h"
#include "listener.h"
#include <stdint.h>

extern SerialDevice SERIAL_DEVICE;
extern UsbDevice USB_DEVICE;
extern Listener listener;

/* Forward declarations */

void receiveCan(CanBus*);
void initializeAllCan();
bool receiveWriteRequest(uint8_t*);

void setup() {
    initializeLogging();
    initializeSerial(&SERIAL_DEVICE);
    initializeUsb(&USB_DEVICE);
    initializeAllCan();
}

void loop() {
    for(int i = 0; i < getCanBusCount(); i++) {
        receiveCan(&getCanBuses()[i]);
    }
    processListenerQueues(&listener);
    readFromHost(&USB_DEVICE, &receiveWriteRequest);
    readFromSerial(&SERIAL_DEVICE, &receiveWriteRequest);
    for(int i = 0; i < getCanBusCount(); i++) {
        processCanWriteQueue(&getCanBuses()[i]);
    }
}

void initializeAllCan() {
    for(int i = 0; i < getCanBusCount(); i++) {
        initializeCan(&(getCanBuses()[i]));
    }
}

bool receiveRawWriteRequest(cJSON* idObject, cJSON* root) {
    int id = idObject->valueint;
    cJSON* dataObject = cJSON_GetObjectItem(root, "data");
    if(dataObject == NULL) {
        debug("Raw write request missing data\r\n", id);
        return true;
    }
    int data = dataObject->valueint;
    CanMessage message = {id, data};
    QUEUE_PUSH(CanMessage, &getCanBuses()[0].sendQueue, message);
    return true;
}

bool receiveWriteRequest(uint8_t* message) {
#ifdef TRANSMITTER
    int index = 0;
    const int BINARY_CAN_WRITE_PACKET_LENGTH = 15;

    while(message[index] != '!') {
        if (index + BINARY_CAN_WRITE_PACKET_LENGTH >= 64) {
            debug("!");
        }

        if(message[index] != '{' || message[index+5] != '|'
                || message[index+14] != '}') {
            debug("Received a corrupted CAN message.\r\n");
            for(int i = 0; i < 16; i++) {
                debug("%02x ", message[index+i] );
            }
            debug("\r\n");
            return false;
        }

        CanMessage outgoing = {0, 0};
        memcpy((uint8_t*)&outgoing.id, &message[index+1], 4);
        for(int i = 0; i < 8; i++) {
            ((uint8_t*)&(outgoing.data))[i] = message[index+i+6];
        }
        QUEUE_PUSH(CanMessage, &getCanBuses()[0].sendQueue, outgoing);
    }
    return true;
#else
    cJSON *root = cJSON_Parse((char*)message);
    if(root != NULL) {
        cJSON* nameObject = cJSON_GetObjectItem(root, "name");
        if(nameObject == NULL) {
            cJSON* idObject = cJSON_GetObjectItem(root, "id");
            if(idObject == NULL) {
                debug("Write request is malformed, "
                        "missing name or id: %s\r\n", message);
                return true;
            } else {
                return receiveRawWriteRequest(idObject, root);
            }
        }

        char* name = nameObject->valuestring;
        cJSON* value = cJSON_GetObjectItem(root, "value");
        if(value == NULL) {
            debug("Write request for %s missing value\r\n", name);
            return true;
        }

        CanSignal* signal = lookupSignal(name, getSignals(),
                getSignalCount(), true);
        CanCommand* command = lookupCommand(name, getCommands(),
                getCommandCount());
        if(signal != NULL) {
            sendCanSignal(signal, value, getSignals(), getSignalCount());
        } else if(command != NULL) {
            command->handler(name, value, getSignals(), getSignalCount());
        } else {
            debug("Writing not allowed for signal with name %s\r\n", name);
        }
        cJSON_Delete(root);
        return true;
    }
    return false;
#endif
}

/*
 * Check to see if a packet has been received. If so, read the packet and print
 * the packet payload to the serial monitor.
 */
void receiveCan(CanBus* bus) {
    // TODO what happens if we process until the queue is empty?
    if(!QUEUE_EMPTY(CanMessage, &bus->receiveQueue)) {
        CanMessage message = QUEUE_POP(CanMessage, &bus->receiveQueue);
        decodeCanMessage(message.id, message.data);
    }
}

void reset() {
    initializeAllCan();
}

#endif // CAN_EMULATOR
<|endoftext|>


<commit_before>
#include "world.hpp"

namespace hacky_internals {

  // When a worldblock is inited, it DOESN'T call insert_water for all the water in it - the water is 'already there'.
  // Water that starts out in a worldblock starts out inactive (observing the rule "the landscape takes zero time to process").
  //
  // We would have to make special rules for worldblocks that start out with
  // active water in them, because it could invalidate iterators into the
  // active_tiles map, because worldblocks can be created essentially any time in the processing.
  // TODO: "init_if_needed" is because we don't know how to make unordered_map's mapped_types be constructed in place in a non-default way.
  worldblock& worldblock::init_if_needed(world *w_, vector3<location_coordinate> global_position_) {
    if (!inited) {
      inited = true;
      w = w_;
      global_position = global_position_;
      axis_aligned_bounding_box bounds{global_position, vector3<location_coordinate>(worldblock_dimension,worldblock_dimension,worldblock_dimension)};
      w->worldgen_function(world_building_gun(w, bounds), bounds);
      std::cerr << "A worldblock has been created!\n";
    }
    return (*this);
  }

  tile& worldblock::get_tile(vector3<location_coordinate> global_coords) {
    vector3<location_coordinate> local_coords = global_coords - global_position;
    return tiles[local_coords.x][local_coords.y][local_coords.z];
  }

  location worldblock::get_neighboring_loc(vector3<location_coordinate> const& old_coords, cardinal_direction dir) {
    // this could be made more effecient, but I'm not sure how
    vector3<location_coordinate> new_coords = old_coords + dir.v;
    if (new_coords.x < global_position.x) return location(new_coords, neighbors[cdir_xminus]);
    if (new_coords.y < global_position.y) return location(new_coords, neighbors[cdir_yminus]);
    if (new_coords.z < global_position.z) return location(new_coords, neighbors[cdir_zminus]);
    if (new_coords.x >= global_position.x + worldblock_dimension) return location(new_coords, neighbors[cdir_xplus]);
    if (new_coords.y >= global_position.y + worldblock_dimension) return location(new_coords, neighbors[cdir_yplus]);
    if (new_coords.z >= global_position.z + worldblock_dimension) return location(new_coords, neighbors[cdir_zplus]);
    return location(new_coords, this);
  }

  location worldblock::get_loc_across_boundary(vector3<location_coordinate> const& new_coords, cardinal_direction dir) {
    if (worldblock* neighbor = neighbors[dir]) return location(new_coords, neighbor);
    return location(new_coords, (neighbors[dir] = w->create_if_necessary_and_get_worldblock(global_position +    vector3<worldblock_dimension_type>(dir.v) * worldblock_dimension)));
  }

  location worldblock::get_loc_guaranteed_to_be_in_this_block(vector3<location_coordinate> coords) {
    return location(coords, this);
  }

}

location location::operator+(cardinal_direction dir)const {
  return wb->get_neighboring_loc(v, dir);
}
tile const& location::stuff_at()const { return wb->get_tile(v); }

location world::make_location(vector3<location_coordinate> const& coords) {
  return create_if_necessary_and_get_worldblock(vector3<location_coordinate>(
      coords.x & ~(hacky_internals::worldblock_dimension-1),
      coords.y & ~(hacky_internals::worldblock_dimension-1),
      coords.z & ~(hacky_internals::worldblock_dimension-1)
    ))->get_loc_guaranteed_to_be_in_this_block(coords);
}

hacky_internals::worldblock* world::create_if_necessary_and_get_worldblock(vector3<location_coordinate> position) {
  return &(blocks[position].init_if_needed(this, position));
}

void world::ensure_space_exists(axis_aligned_bounding_box space) {
  const hacky_internals::worldblock_dimension_type wd = hacky_internals::worldblock_dimension;
  for (location_coordinate
       x =  space.min.x                            / wd;
       x < (space.min.x + space.size.x + (wd - 1)) / wd;
       ++x) {
    for (location_coordinate
         y =  space.min.y                            / wd;
         y < (space.min.y + space.size.y + (wd - 1)) / wd;
         ++y) {
      for (location_coordinate
           z =  space.min.z                            / wd;
           z < (space.min.z + space.size.z + (wd - 1)) / wd;
           ++z) {
        const vector3<location_coordinate> worldblock_position(x*wd, y*wd, z*wd);
        create_if_necessary_and_get_worldblock(worldblock_position);
      }
    }
  }
}

<commit_msg>Fixed the segfault. Water now exists and simulates in real time, but the physics are wrong.<commit_after>
#include "world.hpp"

namespace hacky_internals {

  // When a worldblock is inited, it DOESN'T call insert_water for all the water in it - the water is 'already there'.
  // Water that starts out in a worldblock starts out inactive (observing the rule "the landscape takes zero time to process").
  //
  // We would have to make special rules for worldblocks that start out with
  // active water in them, because it could invalidate iterators into the
  // active_tiles map, because worldblocks can be created essentially any time in the processing.
  // TODO: "init_if_needed" is because we don't know how to make unordered_map's mapped_types be constructed in place in a non-default way.
  worldblock& worldblock::init_if_needed(world *w_, vector3<location_coordinate> global_position_) {
    if (!inited) {
      inited = true;
      w = w_;
      global_position = global_position_;
      axis_aligned_bounding_box bounds{global_position, vector3<location_coordinate>(worldblock_dimension,worldblock_dimension,worldblock_dimension)};
      w->worldgen_function(world_building_gun(w, bounds), bounds);
      std::cerr << "A worldblock has been created!\n";
    }
    return (*this);
  }

  tile& worldblock::get_tile(vector3<location_coordinate> global_coords) {
    vector3<location_coordinate> local_coords = global_coords - global_position;
    return tiles[local_coords.x][local_coords.y][local_coords.z];
  }

  location worldblock::get_neighboring_loc(vector3<location_coordinate> const& old_coords, cardinal_direction dir) {
    // this could be made more effecient, but I'm not sure how
    vector3<location_coordinate> new_coords = old_coords + dir.v;
    if (new_coords.x < global_position.x) return get_loc_across_boundary(new_coords, cdir_xminus);
    if (new_coords.y < global_position.y) return get_loc_across_boundary(new_coords, cdir_yminus);
    if (new_coords.z < global_position.z) return get_loc_across_boundary(new_coords, cdir_zminus);
    if (new_coords.x >= global_position.x + worldblock_dimension) return get_loc_across_boundary(new_coords, cdir_xplus);
    if (new_coords.y >= global_position.y + worldblock_dimension) return get_loc_across_boundary(new_coords, cdir_yplus);
    if (new_coords.z >= global_position.z + worldblock_dimension) return get_loc_across_boundary(new_coords, cdir_zplus);
    return location(new_coords, this);
  }

  location worldblock::get_loc_across_boundary(vector3<location_coordinate> const& new_coords, cardinal_direction dir) {
    if (worldblock* neighbor = neighbors[dir]) return location(new_coords, neighbor);
    return location(new_coords, (neighbors[dir] = w->create_if_necessary_and_get_worldblock(global_position +    vector3<worldblock_dimension_type>(dir.v) * worldblock_dimension)));
  }

  location worldblock::get_loc_guaranteed_to_be_in_this_block(vector3<location_coordinate> coords) {
    return location(coords, this);
  }

}

location location::operator+(cardinal_direction dir)const {
  return wb->get_neighboring_loc(v, dir);
}
tile const& location::stuff_at()const { return wb->get_tile(v); }

location world::make_location(vector3<location_coordinate> const& coords) {
  return create_if_necessary_and_get_worldblock(vector3<location_coordinate>(
      coords.x & ~(hacky_internals::worldblock_dimension-1),
      coords.y & ~(hacky_internals::worldblock_dimension-1),
      coords.z & ~(hacky_internals::worldblock_dimension-1)
    ))->get_loc_guaranteed_to_be_in_this_block(coords);
}

hacky_internals::worldblock* world::create_if_necessary_and_get_worldblock(vector3<location_coordinate> position) {
  return &(blocks[position].init_if_needed(this, position));
}

void world::ensure_space_exists(axis_aligned_bounding_box space) {
  const hacky_internals::worldblock_dimension_type wd = hacky_internals::worldblock_dimension;
  for (location_coordinate
       x =  space.min.x                            / wd;
       x < (space.min.x + space.size.x + (wd - 1)) / wd;
       ++x) {
    for (location_coordinate
         y =  space.min.y                            / wd;
         y < (space.min.y + space.size.y + (wd - 1)) / wd;
         ++y) {
      for (location_coordinate
           z =  space.min.z                            / wd;
           z < (space.min.z + space.size.z + (wd - 1)) / wd;
           ++z) {
        const vector3<location_coordinate> worldblock_position(x*wd, y*wd, z*wd);
        create_if_necessary_and_get_worldblock(worldblock_position);
      }
    }
  }
}

<|endoftext|>


<commit_before>/*
Copyright (c) 2015 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.

Author: Leonardo de Moura
*/
#include "library/tactic/location.h"
#include "frontends/lean/parser.h"
#include "frontends/lean/tokens.h"
#include "frontends/lean/parse_tactic_location.h"

namespace lean {
static occurrence parse_occurrence(parser & p) {
    if (p.curr_is_token(get_lcurly_tk())) {
        p.next();
        bool has_pos = false;
        bool has_neg = false;
        buffer<unsigned> occs;
        while (true) {
            if (p.curr_is_token(get_sub_tk())) {
                if (has_pos)
                    throw parser_error("invalid tactic location, cannot mix positive and negative occurrences", p.pos());
                has_neg = true;
                p.next();
                occs.push_back(p.parse_small_nat());
            } else {
                auto pos = p.pos();
                occs.push_back(p.parse_small_nat());
                if (has_neg)
                    throw parser_error("invalid tactic location, cannot mix positive and negative occurrences", pos);
                has_pos = true;
            }
            if (p.curr_is_token(get_rcurly_tk()))
                break;
        }
        p.next();
        if (has_pos)
            return occurrence::mk_occurrences(occs);
        else
            return occurrence::mk_except_occurrences(occs);
    } else {
        return occurrence();
    }
}

location parse_tactic_location(parser & p) {
    if (p.curr_is_token(get_at_tk())) {
        p.next();
        if (p.curr_is_token(get_star_tk())) {
            p.next();
            if (p.curr_is_token(get_turnstile_tk())) {
                p.next();
                if (p.curr_is_token(get_star_tk())) {
                    // at * |- *
                    return location::mk_everywhere();
                } else {
                    // at * |-
                    return location::mk_all_hypotheses();
                }
            } else {
                // at *
                return location::mk_everywhere();
            }
        } else if (p.curr_is_token(get_lparen_tk())) {
            p.next();
            buffer<name>       hyps;
            buffer<occurrence> hyp_occs;
            while (true) {
                hyps.push_back(p.get_name_val());
                p.next();
                hyp_occs.push_back(parse_occurrence(p));
                if (!p.curr_is_token(get_comma_tk()))
                    break;
                p.next();
            }
            p.check_token_next(get_rparen_tk(), "invalid tactic location, ')' expected");
            if (p.curr_is_token(get_turnstile_tk())) {
                p.next();
                occurrence goal_occ = parse_occurrence(p);
                return location::mk_at(goal_occ, hyps, hyp_occs);
            } else {
                return location::mk_hypotheses_at(hyps, hyp_occs);
            }
        } else if (p.curr_is_token(get_lcurly_tk())) {
            occurrence o = parse_occurrence(p);
            return location::mk_goal_at(o);
        } else {
            buffer<name>       hyps;
            buffer<occurrence> hyp_occs;
            hyps.push_back(p.check_id_next("invalid tactic location, identifier expected"));
            hyp_occs.push_back(parse_occurrence(p));
            return location::mk_hypotheses_at(hyps, hyp_occs);
        }
    } else {
        return location::mk_goal_only();
    }
}
}
<commit_msg>feat(frontends/lean/parse_tactic_location): validate occurrence index<commit_after>/*
Copyright (c) 2015 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.

Author: Leonardo de Moura
*/
#include "library/tactic/location.h"
#include "frontends/lean/parser.h"
#include "frontends/lean/tokens.h"
#include "frontends/lean/parse_tactic_location.h"

namespace lean {
static occurrence parse_occurrence(parser & p) {
    if (p.curr_is_token(get_lcurly_tk())) {
        p.next();
        bool has_pos = false;
        bool has_neg = false;
        buffer<unsigned> occs;
        while (true) {
            if (p.curr_is_token(get_sub_tk())) {
                if (has_pos)
                    throw parser_error("invalid tactic location, cannot mix positive and negative occurrences", p.pos());
                has_neg = true;
                p.next();
                auto pos   = p.pos();
                unsigned i = p.parse_small_nat();
                if (i == 0)
                    throw parser_error("invalid tactic location, first occurrence is 1", pos);
                occs.push_back(i);
            } else {
                auto pos   = p.pos();
                unsigned i = p.parse_small_nat();
                if (i == 0)
                    throw parser_error("invalid tactic location, first occurrence is 1", pos);
                occs.push_back(i);
                if (has_neg)
                    throw parser_error("invalid tactic location, cannot mix positive and negative occurrences", pos);
                has_pos = true;
            }
            if (p.curr_is_token(get_rcurly_tk()))
                break;
        }
        p.next();
        if (has_pos)
            return occurrence::mk_occurrences(occs);
        else
            return occurrence::mk_except_occurrences(occs);
    } else {
        return occurrence();
    }
}

location parse_tactic_location(parser & p) {
    if (p.curr_is_token(get_at_tk())) {
        p.next();
        if (p.curr_is_token(get_star_tk())) {
            p.next();
            if (p.curr_is_token(get_turnstile_tk())) {
                p.next();
                if (p.curr_is_token(get_star_tk())) {
                    // at * |- *
                    return location::mk_everywhere();
                } else {
                    // at * |-
                    return location::mk_all_hypotheses();
                }
            } else {
                // at *
                return location::mk_everywhere();
            }
        } else if (p.curr_is_token(get_lparen_tk())) {
            p.next();
            buffer<name>       hyps;
            buffer<occurrence> hyp_occs;
            while (true) {
                hyps.push_back(p.get_name_val());
                p.next();
                hyp_occs.push_back(parse_occurrence(p));
                if (!p.curr_is_token(get_comma_tk()))
                    break;
                p.next();
            }
            p.check_token_next(get_rparen_tk(), "invalid tactic location, ')' expected");
            if (p.curr_is_token(get_turnstile_tk())) {
                p.next();
                occurrence goal_occ = parse_occurrence(p);
                return location::mk_at(goal_occ, hyps, hyp_occs);
            } else {
                return location::mk_hypotheses_at(hyps, hyp_occs);
            }
        } else if (p.curr_is_token(get_lcurly_tk())) {
            occurrence o = parse_occurrence(p);
            return location::mk_goal_at(o);
        } else {
            buffer<name>       hyps;
            buffer<occurrence> hyp_occs;
            hyps.push_back(p.check_id_next("invalid tactic location, identifier expected"));
            hyp_occs.push_back(parse_occurrence(p));
            return location::mk_hypotheses_at(hyps, hyp_occs);
        }
    } else {
        return location::mk_goal_only();
    }
}
}
<|endoftext|>


<commit_before>#include "cbase.h"
#include "asw_door_area.h"
#include "func_movelinear.h"
#include "asw_button_area.h"
#include "asw_base_spawner.h"
#include "asw_marine_hint.h"
#include "ai_network.h"
#include "ai_link.h"

// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"

ConVar asw_follow_ignore_hints("asw_follow_ignore_hints", "0.1", FCVAR_CHEAT, "If less than (by default) 10% of nodes are marine hints, use all nodes as marine hints.");

// BenLubar: I really wish I didn't have to do this, but there are popular campaigns that have huge problems in them.
class CASW_Campaign_Fixes : public CAutoGameSystem
{
public:

	CASW_Campaign_Fixes() : CAutoGameSystem("CASW_Campaign_Fixes") {}

	virtual void LevelInitPostEntity()
	{
		const char *pszMap = STRING(gpGlobals->mapname);

		// Fixes cargo elevator leaving without all the marines if at least 4 marines are already on the elevator.
		if (!V_stricmp(pszMap, "asi-jac1-landingbay_02"))
		{
			CASW_Door_Area *pMarinesPast = dynamic_cast<CASW_Door_Area *>(gEntList.FindEntityByName(NULL, "trigger_lift_marine_check"));
			Assert(pMarinesPast);
			if (pMarinesPast)
				pMarinesPast->m_nPlayersRequired = ASW_MAX_MARINE_RESOURCES;
		}

		// Fixes the last segment of a bridge on deima being extended before the marines get there.
		if (!V_stricmp(pszMap, "asi-jac2-deima"))
		{
			CFuncMoveLinear *pBridgeGate = dynamic_cast<CFuncMoveLinear *>(gEntList.FindEntityByName(NULL, "move_door_bridge"));
			Assert(pBridgeGate);
			if (pBridgeGate)
			{
				CBaseEntityOutput *pOutput = pBridgeGate->FindNamedOutput("OnFullyOpen");
				Assert(pOutput);
				if (pOutput)
				{
					Assert(pOutput->NumberOfElements() == 2);
					pOutput->DeleteAllElements();
				}
			}
		}

		// Fixes the tech marine requirement never being turned off after the last hack.
		if (!V_stricmp(pszMap, "dc1-omega_city"))
		{
			CASW_Button_Area *pEndButton = dynamic_cast<CASW_Button_Area *>(gEntList.FindEntityByName(NULL, "end_button"));
			Assert(pEndButton);
			if (pEndButton)
			{
				CBaseEntityOutput *pOutput = pEndButton->FindNamedOutput("OnButtonHackCompleted");
				Assert(pOutput);
				if (pOutput)
				{
					pOutput->ParseEventAction("asw_tech_marine_req,DisableTechMarineReq,,0,1");
				}
			}
		}

		// Fixes the tech marine requirement never being turned off after the last hack.
		if (!V_stricmp(pszMap, "dc2-breaking_an_entry"))
		{
			CASW_Button_Area *pEndButton = NULL;
			while ((pEndButton = dynamic_cast<CASW_Button_Area *>(gEntList.FindEntityByClassname(pEndButton, "trigger_asw_button_area"))))
			{
				if (!V_stricmp(STRING(pEndButton->m_szPanelPropName), "elevator_pc"))
				{
					CBaseEntityOutput *pOutput = pEndButton->FindNamedOutput("OnButtonHackCompleted");
					Assert(pOutput);
					if (pOutput)
					{
						pOutput->ParseEventAction("asw_tech_marine_req,DisableTechMarineReq,,0,1");
					}
					break;
				}
			}
		}

		// Fixes the tech marine requirement never being turned off after the last hack.
		if (!V_stricmp(pszMap, "dc3-search_and_rescue"))
		{
			CASW_Button_Area *pC4PlantedButton = dynamic_cast<CASW_Button_Area *>(gEntList.FindEntityByName(NULL, "c4_planted_button"));
			Assert(pC4PlantedButton);
			if (pC4PlantedButton)
			{
				CBaseEntityOutput *pOutput = pC4PlantedButton->FindNamedOutput("OnButtonHackCompleted");
				Assert(pOutput);
				if (pOutput)
				{
					pOutput->ParseEventAction("asw_tech_marine_req,DisableTechMarineReq,,0,1");
				}
			}
		}

		// Fixes maps before the brutal update assuming there would always be exactly 4 difficulty levels.
		bool bShouldFixSkillLevels = true;
		CASW_Base_Spawner *pSpawner = NULL;
		while ((pSpawner = dynamic_cast<CASW_Base_Spawner *>(gEntList.FindEntityByClassname(pSpawner, "asw_spawner"))) != NULL)
		{
			bShouldFixSkillLevels = bShouldFixSkillLevels && pSpawner->m_iMaxSkillLevel < 5;
		}
		while ((pSpawner = dynamic_cast<CASW_Base_Spawner *>(gEntList.FindEntityByClassname(pSpawner, "asw_holdout_spawner"))) != NULL)
		{
			bShouldFixSkillLevels = bShouldFixSkillLevels && pSpawner->m_iMaxSkillLevel < 5;
		}
		if (bShouldFixSkillLevels)
		{
			while ((pSpawner = dynamic_cast<CASW_Base_Spawner *>(gEntList.FindEntityByClassname(pSpawner, "asw_spawner"))) != NULL)
			{
				if (pSpawner->m_iMaxSkillLevel == 4)
					pSpawner->m_iMaxSkillLevel = 5;
			}
			while ((pSpawner = dynamic_cast<CASW_Base_Spawner *>(gEntList.FindEntityByClassname(pSpawner, "asw_holdout_spawner"))) != NULL)
			{
				if (pSpawner->m_iMaxSkillLevel == 4)
					pSpawner->m_iMaxSkillLevel = 5;
			}
		}

		// Fixes maps without marine hints being confusing for marines. The hints are added in ai_initutils.cpp.
		Assert( MarineHintManager() );
		if ( MarineHintManager() && MarineHintManager()->m_LastResortHints.Count() )
		{
			CUtlVector<HintData_t *> &hints = MarineHintManager()->m_LastResortHints;
			FOR_EACH_VEC_BACK( hints, i )
			{
				HintData_t *pHint = hints[i];
				Assert( pHint );
				Assert( g_pBigAINet );
				int nNode = g_pBigAINet->NearestNodeToPoint( pHint->m_vecPosition, false );
				CAI_Node *pNode = g_pBigAINet->GetNode( nNode );
				Assert( pNode );

				bool bAccessible = false;

				if ( pNode )
				{
					// We consider nodes "accessible" if a marine can walk from there to any other node.
					FOR_EACH_VEC( pNode->m_Links, j )
					{
						if ( pNode->m_Links[j]->m_iAcceptedMoveTypes[HULL_HUMAN] & bits_CAP_MOVE_GROUND )
						{
							bAccessible = true;
							break;
						}
					}
				}

				if ( !bAccessible )
				{
					hints.FastRemove( i );
					delete pHint;
				}
			}

			if ( hints.Count() * asw_follow_ignore_hints.GetFloat() > MarineHintManager()->m_Hints.Count() )
			{
				// We have less than 10% marine hints. The mapper either forgot to add hints or added a few and forgot about it. Use the nodes instead.
				MarineHintManager()->m_Hints.AddVectorToTail( hints );
				hints.Purge();

				// Reset the indices because we may have removed some from the middle.
				FOR_EACH_VEC( MarineHintManager()->m_Hints, i )
				{
					MarineHintManager()->m_Hints[i]->m_nHintIndex = i;
				}
			}
			else
			{
				hints.PurgeAndDeleteElements();
			}
		}
	}
};

static CASW_Campaign_Fixes g_CampaignFixes;<commit_msg>MAPPING: fix the practice map as well<commit_after>#include "cbase.h"
#include "asw_door_area.h"
#include "func_movelinear.h"
#include "asw_button_area.h"
#include "asw_base_spawner.h"
#include "asw_marine_hint.h"
#include "ai_network.h"
#include "ai_link.h"

// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"

ConVar asw_follow_ignore_hints("asw_follow_ignore_hints", "0.1", FCVAR_CHEAT, "If less than (by default) 10% of nodes are marine hints, use all nodes as marine hints.");

// BenLubar: I really wish I didn't have to do this, but there are popular campaigns that have huge problems in them.
class CASW_Campaign_Fixes : public CAutoGameSystem
{
public:

	CASW_Campaign_Fixes() : CAutoGameSystem("CASW_Campaign_Fixes") {}

	virtual void LevelInitPostEntity()
	{
		const char *pszMap = STRING(gpGlobals->mapname);

		// Fixes cargo elevator leaving without all the marines if at least 4 marines are already on the elevator.
		if (!V_stricmp(pszMap, "asi-jac1-landingbay_02") || !V_stricmp(pszMap, "asi-jac1-landingbay_pract"))
		{
			CASW_Door_Area *pMarinesPast = dynamic_cast<CASW_Door_Area *>(gEntList.FindEntityByName(NULL, "trigger_lift_marine_check"));
			Assert(pMarinesPast);
			if (pMarinesPast)
			{
				pMarinesPast->m_nPlayersRequired = ASW_MAX_MARINE_RESOURCES;
			}
		}

		// Fixes the last segment of a bridge on deima being extended before the marines get there.
		if (!V_stricmp(pszMap, "asi-jac2-deima"))
		{
			CFuncMoveLinear *pBridgeGate = dynamic_cast<CFuncMoveLinear *>(gEntList.FindEntityByName(NULL, "move_door_bridge"));
			Assert(pBridgeGate);
			if (pBridgeGate)
			{
				CBaseEntityOutput *pOutput = pBridgeGate->FindNamedOutput("OnFullyOpen");
				Assert(pOutput);
				if (pOutput)
				{
					Assert(pOutput->NumberOfElements() == 2);
					pOutput->DeleteAllElements();
				}
			}
		}

		// Fixes the tech marine requirement never being turned off after the last hack.
		if (!V_stricmp(pszMap, "dc1-omega_city"))
		{
			CASW_Button_Area *pEndButton = dynamic_cast<CASW_Button_Area *>(gEntList.FindEntityByName(NULL, "end_button"));
			Assert(pEndButton);
			if (pEndButton)
			{
				CBaseEntityOutput *pOutput = pEndButton->FindNamedOutput("OnButtonHackCompleted");
				Assert(pOutput);
				if (pOutput)
				{
					pOutput->ParseEventAction("asw_tech_marine_req,DisableTechMarineReq,,0,1");
				}
			}
		}

		// Fixes the tech marine requirement never being turned off after the last hack.
		if (!V_stricmp(pszMap, "dc2-breaking_an_entry"))
		{
			CASW_Button_Area *pEndButton = NULL;
			while ((pEndButton = dynamic_cast<CASW_Button_Area *>(gEntList.FindEntityByClassname(pEndButton, "trigger_asw_button_area"))))
			{
				if (!V_stricmp(STRING(pEndButton->m_szPanelPropName), "elevator_pc"))
				{
					CBaseEntityOutput *pOutput = pEndButton->FindNamedOutput("OnButtonHackCompleted");
					Assert(pOutput);
					if (pOutput)
					{
						pOutput->ParseEventAction("asw_tech_marine_req,DisableTechMarineReq,,0,1");
					}
					break;
				}
			}
		}

		// Fixes the tech marine requirement never being turned off after the last hack.
		if (!V_stricmp(pszMap, "dc3-search_and_rescue"))
		{
			CASW_Button_Area *pC4PlantedButton = dynamic_cast<CASW_Button_Area *>(gEntList.FindEntityByName(NULL, "c4_planted_button"));
			Assert(pC4PlantedButton);
			if (pC4PlantedButton)
			{
				CBaseEntityOutput *pOutput = pC4PlantedButton->FindNamedOutput("OnButtonHackCompleted");
				Assert(pOutput);
				if (pOutput)
				{
					pOutput->ParseEventAction("asw_tech_marine_req,DisableTechMarineReq,,0,1");
				}
			}
		}

		// Fixes maps before the brutal update assuming there would always be exactly 4 difficulty levels.
		bool bShouldFixSkillLevels = true;
		CASW_Base_Spawner *pSpawner = NULL;
		while ((pSpawner = dynamic_cast<CASW_Base_Spawner *>(gEntList.FindEntityByClassname(pSpawner, "asw_spawner"))) != NULL)
		{
			bShouldFixSkillLevels = bShouldFixSkillLevels && pSpawner->m_iMaxSkillLevel < 5;
		}
		while ((pSpawner = dynamic_cast<CASW_Base_Spawner *>(gEntList.FindEntityByClassname(pSpawner, "asw_holdout_spawner"))) != NULL)
		{
			bShouldFixSkillLevels = bShouldFixSkillLevels && pSpawner->m_iMaxSkillLevel < 5;
		}
		if (bShouldFixSkillLevels)
		{
			while ((pSpawner = dynamic_cast<CASW_Base_Spawner *>(gEntList.FindEntityByClassname(pSpawner, "asw_spawner"))) != NULL)
			{
				if (pSpawner->m_iMaxSkillLevel == 4)
					pSpawner->m_iMaxSkillLevel = 5;
			}
			while ((pSpawner = dynamic_cast<CASW_Base_Spawner *>(gEntList.FindEntityByClassname(pSpawner, "asw_holdout_spawner"))) != NULL)
			{
				if (pSpawner->m_iMaxSkillLevel == 4)
					pSpawner->m_iMaxSkillLevel = 5;
			}
		}

		// Fixes maps without marine hints being confusing for marines. The hints are added in ai_initutils.cpp.
		Assert( MarineHintManager() );
		if ( MarineHintManager() && MarineHintManager()->m_LastResortHints.Count() )
		{
			CUtlVector<HintData_t *> &hints = MarineHintManager()->m_LastResortHints;
			FOR_EACH_VEC_BACK( hints, i )
			{
				HintData_t *pHint = hints[i];
				Assert( pHint );
				Assert( g_pBigAINet );
				int nNode = g_pBigAINet->NearestNodeToPoint( pHint->m_vecPosition, false );
				CAI_Node *pNode = g_pBigAINet->GetNode( nNode );
				Assert( pNode );

				bool bAccessible = false;

				if ( pNode )
				{
					// We consider nodes "accessible" if a marine can walk from there to any other node.
					FOR_EACH_VEC( pNode->m_Links, j )
					{
						if ( pNode->m_Links[j]->m_iAcceptedMoveTypes[HULL_HUMAN] & bits_CAP_MOVE_GROUND )
						{
							bAccessible = true;
							break;
						}
					}
				}

				if ( !bAccessible )
				{
					hints.FastRemove( i );
					delete pHint;
				}
			}

			if ( hints.Count() * asw_follow_ignore_hints.GetFloat() > MarineHintManager()->m_Hints.Count() )
			{
				// We have less than 10% marine hints. The mapper either forgot to add hints or added a few and forgot about it. Use the nodes instead.
				MarineHintManager()->m_Hints.AddVectorToTail( hints );
				hints.Purge();

				// Reset the indices because we may have removed some from the middle.
				FOR_EACH_VEC( MarineHintManager()->m_Hints, i )
				{
					MarineHintManager()->m_Hints[i]->m_nHintIndex = i;
				}
			}
			else
			{
				hints.PurgeAndDeleteElements();
			}
		}
	}
};

static CASW_Campaign_Fixes g_CampaignFixes;<|endoftext|>