⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 squirmchemistry.h

📁 本程序模拟细胞的自我繁殖
💻 H
字号:
// SquirmChemistry.h

#ifndef SquirmChem
#define SquirmChem 1

#include "SquirmReaction.h"
#include "SquirmCell.h"
#include "SquirmError.h"

typedef CArray<SquirmReaction,SquirmReaction&> ReactionArray;

inline bool TestProb(unsigned long cases)
{
	return((rand()+(unsigned long)rand()*RAND_MAX)%cases==0);
}

class SquirmChemistry
{
private:
	ReactionArray reactions;
	int first_enzyme;

public:
	SquirmChemistry()
	{
		first_enzyme=7;
	}

	//---------------------------------interface functions---------------------------

	void SetFirstEnzymeState(int s) { this->first_enzyme=s; }

	int GetFirstEnzymeState() { return this->first_enzyme; }

	void removeAllReactions()
	{
		reactions.RemoveAll();
	}

	void addReaction(SquirmReaction r)
	{
		reactions.Add(r);
	}

	//--------------------------------------------------------------------------------

	int react(SquirmCell *cell,const SquirmCellList &unbonded_neighbours,float REACTION_RANGE2)
	{
		// try all the programmed reactions in turn
		// (only for cells with state <first_enzyme)
		if(cell->GetState()<first_enzyme)
		{
			for(int i=0;i<reactions.GetSize();i++)
			{
				if(tryReaction(cell,unbonded_neighbours,reactions[i],REACTION_RANGE2))
					return i;
				// only one reaction should apply per iteration
				// (also, unbonded_neighbours may now be wrong)
			}
		}
		else if(true) { // state>=first_enzyme
			// try the reactions that prime the enzymes
			if(tryProteinArithmeticReactions(cell))
				return reactions.GetSize();
			else if(tryEnzymeReactions(cell,unbonded_neighbours))
				return reactions.GetSize()+1;
		}
		
        if(true && cell->GetState()==-1 && unbonded_neighbours.GetCount()>0) {
            // try the special destructive reaction
			SquirmCell* first = unbonded_neighbours.GetHead();
            if(first->GetState()>0 && first->GetState()!=8 && 
                !(first->GetState()>=10 && first->GetState()<=13))
            {
                first->SetState(0);
                first->BreakAllBonds();
                return reactions.GetSize()+1;
            }
        }

		return -1; // no reaction could be applied
	}

private:

	bool tryProteinArithmeticReactions(SquirmCell *cell);

	bool tryEnzymeReactions(SquirmCell *cell,
		const SquirmCellList& unbonded_neighbours);

	bool tryReaction(SquirmCell *cell,
		const SquirmCellList& unbonded_neighbours,
		SquirmReaction r,float REACTION_RANGE2)
	{
		// can this reaction apply to this cell based on the cells it is 
		// bonded to and its unbonded neighbours?
		
		// the 3-nhood reaction can apply in any orientation, so this is
		// much more difficult to work out than for the 2-nhood reactions
	
		// we are checking this for every atom, therefore it suffices here to
		// check whether this reaction applies to this atom as the 'a' atom

		if( (r.a_type=='x' || r.a_type==cell->GetType()) && r.a_state==cell->GetState() )
		{	
			// collect the possible candidates for b
			SquirmCellList b_candidates;
			{
				SquirmCellList& possibles = r.current_ab_bond?(cell->GetBondedCells()):unbonded_neighbours;
				// look for matches in the bonded_cells list
				if( r.b_type=='y' || (r.b_type=='x' && r.a_type!='x') )
				{
					// b can be of any type
					getThoseOfState(possibles,r.b_state,b_candidates);
				}
				else if(r.b_type=='x' && r.a_type=='x')
				{
					// b must be of a's type
					getThoseOfTypeAndState(possibles,
						cell->GetType(),r.b_state,
						b_candidates);
				}
				else
				{
					// b must be of specified type and state
					getThoseOfTypeAndState(possibles,
						r.b_type,r.b_state,
						b_candidates);
				}
			}

			// for each b candidate (if any) can we find a suitable c?
			// apply the reaction and return if we find one
			POSITION pos = b_candidates.GetHeadPosition();
			while(pos)
			{
			    SquirmCell *b_candidate = b_candidates.GetNext(pos);

			    if(r.n_inputs==3)
			    {
				SquirmCellList& possibles = r.current_ac_bond?cell->GetBondedCells():unbonded_neighbours;
				SquirmCellList c_candidates;
				if(r.c_type=='z' || (r.c_type=='x' && r.a_type!='x' && r.b_type!='x') ||
					(r.c_type=='y' && r.a_type!='y' && r.b_type!='y'))
				{
					// c can be of any type
					getThoseOfState(possibles,r.c_state,c_candidates);
				}
				else if(r.c_type=='x' && r.a_type=='x')
				{
					// c must be of a's type
					getThoseOfTypeAndState(possibles,
						cell->GetType(),r.c_state,c_candidates);
				}
				else if( (r.c_type=='x' && r.b_type=='x') ||
					(r.c_type=='y' && r.b_type=='y') )
				{
					// c must be of b's type
					getThoseOfTypeAndState(possibles,
						b_candidate->GetType(),r.c_state,c_candidates);
				}
				else
				{
					// c must be of type and state specified
					getThoseOfTypeAndState(possibles,
						r.c_type,r.c_state,c_candidates);
				}

				// consider each candidate c in turn (if any)
				POSITION pos2 = c_candidates.GetHeadPosition();
				while(pos2)
				{
					SquirmCell *c_candidate = c_candidates.GetNext(pos2);
					// cannot be the same candidate cell as b!
					if(c_candidate!=b_candidate)
					{
						// also the bond/not between b and c must be correct, and all the players must be within range
						if( r.current_bc_bond == b_candidate->HasBondWith(c_candidate) && 
                            Length2(c_candidate->location-b_candidate->location)<REACTION_RANGE2 )
						{
							if(TestProb(r.cases))
							{
							    // apply the reaction and return
								cell->SetState(r.future_a_state);
								b_candidate->SetState(r.future_b_state);
								c_candidate->SetState(r.future_c_state);
								if(cell->HasBondWith(b_candidate) && !r.future_ab_bond)
									cell->Debond(b_candidate);
								else if(!cell->HasBondWith(b_candidate) && r.future_ab_bond)
									cell->BondTo(b_candidate);
								if(b_candidate->HasBondWith(c_candidate) && !r.future_bc_bond)
									b_candidate->Debond(c_candidate);
								else if(!b_candidate->HasBondWith(c_candidate) && r.future_bc_bond)
									b_candidate->BondTo(c_candidate);
								if(cell->HasBondWith(c_candidate) && !r.future_ac_bond)
									cell->Debond(c_candidate);
								else if(!cell->HasBondWith(c_candidate) && r.future_ac_bond)
									cell->BondTo(c_candidate);
	
								return true;
							}
						}
					}
				}
			    }
			    else // n_inputs==2
			    {
					if(TestProb(r.cases))
					{
						// apply the reaction and return
	 					cell->SetState(r.future_a_state);
						b_candidate->SetState(r.future_b_state);
						if(cell->HasBondWith(b_candidate) && !r.future_ab_bond)
							cell->Debond(b_candidate);
						else if(!cell->HasBondWith(b_candidate) && r.future_ab_bond)
							cell->BondTo(b_candidate);
						return true;
					}
				}
			}
		}
		return false; // this reaction was not possible
	}

	// ----------------------------------------------------------------------------------------
public:

	static void getThoseOfTypeAndState(const SquirmCellList& cells,
		char type,int state,SquirmCellList &dest)
	{
		if(type=='x' || type=='y' || type=='z')
		{
			SquirmError("getThoseOfTypeAndState : cannot pass a type variable to this function!");
			return;
		}

		// do any of these cells match the type and state specified?
		// if so return all that match (empty list if none)
		
		dest.RemoveAll();
		SquirmCell *c;
		POSITION pos = cells.GetHeadPosition();
		while(pos)
		{
	        c = cells.GetNext(pos);
  			if(c->GetType()==type && c->GetState()==state)
				dest.AddTail(c);
		}
	}

	// ----------------------------------------------------------------------------------------

	static void getThoseOfState(const SquirmCellList& cells,int state,
		SquirmCellList& dest)
	{
		// do any of these cells match the state specified? (any type)
		// if so return all that match (empty list if none)
		
		dest.RemoveAll();
		SquirmCell *c;
		POSITION pos = cells.GetHeadPosition();
		while(pos)
		{
	        c = cells.GetNext(pos);
			if(c->GetState()==state)
				dest.AddTail(c);
		}
	}
};

#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -