Jump to content

  • Log In with Google      Sign In   
  • Create Account

FuzzyRhombus

Member Since 27 Feb 2005
Offline Last Active Oct 19 2014 09:01 AM

#5126127 Is HTML5 a legit language for developing game?

Posted by FuzzyRhombus on 24 January 2014 - 10:24 AM

I actually just wrote a blog post about this. Simply put, HTML5 is definitely legit, but write HTML5 games for that purpose. Intend them to run in browser. Don't try to replace an otherwise native app or try to make the next CoD in JS. I'm mainly a C++ guy, but I wanted to give it a shot, so I'm currently writing a small JS game with pixi.js. I'm impressed, but it's definitely different.

 

I saw some engine says it can port its game to html5 and even put it in Android/iOS wrapper. The boast seems quite questionable but also brought me some hope...

Don't do this. The performance of UIWebView is not the same as the browser. Chrome for Android is amazing though.

 

HTML5 for game development is something to stay well clear of, unless you're ready to waste a bunch of time and meet with frustration. I have developed many games in Flash and some in HTML5/JavaScript, some of them being direct ports of each other, so I've had lots of time to experience the broken promises of the HTML5 "standard".

 

If you're just looking to play around, HTML5 and JavaScript are probably the most accessible (you need a browser and a text editor), but I would highly recommend taking those skills and transferring them to something like ActionScript or even Java. C++ is a great language for sheer performance but it requires a learning curve.

It sounds like your attempts haven't been very recent. Even in just the past 6 months HTML5 support has grown. It is just as much capable, if not more, than Flash now, and it's going to continue to grow.

I reccomend playing around with all those languages regardless, though! biggrin.png

 

As to the original poster, HTML5 is OK for simple interfaces but once you get to "real" game development, it could be cumbersome. Keep in mind that a ton of people are stuck at IE9 which has problematic support for HTML5 and (as we found out) WebSockets. 

IE has always been a problem to web developers in general. I honestly wouldn't even worry about it. Anyone using IE9 (or IE at all) probably isn't looking to play web games, and if they are, they should upgrade. That is like supporting iOS1 when releasing iOS games.

 

HTML5 is okay for basic games with minimum animations for Desktop. Its mobile support is very poor and kills mobile battery as fast as Flash did. If you want something really performant, cross platform and as easy to develop as JS - you always have Flash here. Stage3D and ability to make as performant as native games on mobile due to underlying OpenGL-based rendering system is astounding. It won't go anywhere anytime soon, despite everything doomsayers have been telling us for 10 years.

 

The bottom line for me is that after a while, HTML5 Audio will be sorted out and HTML5 games will work fine on mobile, whereas native Flash is basically banished from mobile now that their last major hold-out, Android, dropped native Flash support a while back. HTML5 is going to continue to get better and better, but Flash isn't coming back to mobile outside of AIR packaging. Is Flash "dead" or "dying"? Of course not, and it likely won't be for decades. But the days of 95%+ installbase on all Internet-connected devices is long over. 

I forgot about AIR and Stage3D. I've always been an advocate of "Flash is here to stay," but I'm on the other side now. You bring up good points, but Flash in browser is definitely on the way to retirement. If you're new to either at this point, and trying to decide between HTML5 and Flash, I vote HTML5. wacko.png




#5109749 Coding horror experiment in C++

Posted by FuzzyRhombus on 16 November 2013 - 12:50 PM

Getting post too long for the resources...

 

So i uploaded the resources as a txt, and the whole file like slicer did.

Attached Files




#5109747 Coding horror experiment in C++

Posted by FuzzyRhombus on 16 November 2013 - 12:43 PM

yea....forgot to remove the good/bad counters, used them when i was figuring out scoring. msvc apparantly is cool with everything i did, Thanks fuzzy for fixing it.

All good :)

The sf::Text should be fine the way you had it, not sure why I had that problem; but now it works for everybody (I hope).

 

Anyway....

 

 

Finally got some more time to play around with this! Since no one else did anything yet, I just added my changes to this post.

I added a simple game over screen, and a little more conditions to satisfy for dieing, instead of just all of a sudden being back at the menu again lol.

Scoring and death could still use a little work. Seems too easy to me. And there's virtually no way to get a game over without a score of 0.

 

I improved on the particles, added a proper resource, aaaaand since it's ghost themed, added ghost trails! biggrin.png

I only added the effect for particles and background ghosts. Would probably be too much on everything.


#include <SFML/System.hpp>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <vector>
#include <cmath>
#include <stdint.h>
#include <iostream>
#include <cstring>
#include <sstream>

typedef unsigned int uint; // laziness
typedef unsigned char uchar; // more

union RGBA
{
	struct Channel
	{
		uint8_t red;
		uint8_t green;
		uint8_t blue;
		uint8_t alpha;
	};

	uint32_t rgba;
	Channel channel;
};

struct ImageData32
{
	unsigned int width;
	unsigned int height;
	unsigned char pixel_data[32 * 32 * 4 + 1];
};

struct ImageData64{
	unsigned int width;
	unsigned int height;
	unsigned char pixel_data[64*64*4+1];
};

struct Ghost
{
	sf::Vector2f position;
	sf::Vector2f oldPosition;
	sf::Vector2f forces;
	float scaleRate;
	float radius;
	float invmass;
	int m_GoodAmnt;
	sf::Sprite sprite;
};

struct ShadowGhost
{
	sf::Sprite sprite;
	float fadeDuration;
	float maxVisibility;
	float fadeState;
};

struct People{
	sf::Vector2f position;
	float radius;
	sf::Sprite sprite;
	unsigned char m_Flag;
};

struct Background
{
	sf::Color baseColor;
	sf::Image buffer;
	sf::Texture texture;
	float pulseState;

	std::vector<ShadowGhost> shadowGhosts;
};

// Simple "self-sufficient" particles
struct Particle
{
	sf::Vector2f position, velocity;
	float friction;
    float rotation, omega;
	sf::Color color;
    sf::Color endColor;
	uint lifetime;
    uint energy;
};

extern const uchar particleData[];
extern const ImageData32 imageData;
extern const ImageData64 Person_A;
extern const unsigned char InconcolataFont[58464];

#define PLAYER_GHOST 0
#define GHOST_GOOD 1
#define CONVERSION_DISTANCE 80.0f
#define CONVERSION_LARGE_DISTANCE 50.0f
#define GOOD_MINIMUM 100
#define GOOD_MAXIMUM 255
#define BAD_CONVERSION_RATE 6
#define GOOD_CONVERSION_RATE 2
#define GHOST_RADIUS 16.0f
#define GHOST_GROW_RATE 0.2
#define GHOST_SPAWN_MIN_TICKS 30 //0.5 seconds at 60 fps
#define GHOST_SPAWN_MAX_TICKS 120 //2 seconds at 60 fps
#define GHOST_MAX_SCALE 1.8
#define GHOST_MINIMUM_FOR_GOOD_SCALE 5
#define GHOST_SCALE_RATE 0.01f
#define INITIAL_SCORE 3000
#define GOOD_GHOST_SCORE_VALUE 1
#define BAD_GHOST_SCORE_VALUE 1
#define GAME_FASTER_SPAWN_AFTER_TICKS (45*60) //every 45 seconds(60 ticks per second), ghosts begin spawning slightly faster.

typedef enum {
    GameStateMenu = 0,
    GameStatePlaying,
    GameStateGameOver,
} GameState;

#define STATE_MENU GameStateMenu
#define STATE_PLAYING GameStatePlaying

#define PERSON_RADIUS 32.0f
#define PERSON_FACE_LEFT 1

#define GHOST_BUFFER_BLUR_X     16.0f
#define GHOST_BUFFER_BLUR_Y     16.0f
#define GHOST_BUFFER_FADE       240

#define PI                      3.1415926535897f

static sf::Vector2u mousePosition;
static float ghostGravityWellAttraction = 0;
static std::vector<Particle> *gParticles;    // yay global reference
static uint currentRenderTarget;

#define MASS 2 * 1e-2
#define GHOST_GRAVITY_WELL_DIEOFF_RATE (1.0f / 30.0f)

void addParticles(std::vector<Particle> *particles, const uint count, const sf::Vector2f &posMin, const sf::Vector2f &posMax, const sf::Vector2f &velMin, const sf::Vector2f &velMax, const float friction, const uint lifetime, const float energyScale, const sf::Color colorMin, const sf::Color colorMax, sf::Color *fadeColor=0);

float randomFloat()
{
	return std::rand()/(float)RAND_MAX; //get out of here swiftcoder!
	return 4.0f;//std::rand() / static_cast<float>(RAND_MAX);
}

inline float randomRange(const float min, const float max) {
    return min + (max-min)*randomFloat();
}

sf::Vector2f randomVector(sf::Vector2u bounds)
{
	return sf::Vector2f(randomFloat() * bounds.x, randomFloat() * bounds.y);
}

//return random vector between min/max....although since randomFloat returns 4, more like min+max*4....
sf::Vector2f randomVector(sf::Vector2f min, sf::Vector2f max){
	//sf::Vector2f Vec = min+(max-min);
	//return sf::Vector2f(Vec.x*randomFloat(), Vec.y*randomFloat());
	sf::Vector2f diff = max-min;
	return min + sf::Vector2f(diff.x*randomFloat(), diff.y*randomFloat());
}

sf::Color fadeColors(const sf::Color &start, const sf::Color &end, const float amount) {
    sf::Color color;
    color.r = start.r + amount*int(end.r - start.r);
    color.g = start.g + amount*int(end.g - start.g);
    color.b = start.b + amount*int(end.b - start.b);
    color.a = start.a + amount*int(end.a - start.a);
    return color;
}

//Copy-pasta w/ meatballs from one of my other projects
void drawTexture(sf::RenderTarget &destination, const sf::Vector2f &location, const sf::Texture &texture,
	sf::IntRect subRect = sf::IntRect(), const sf::Color &coloration = sf::Color::White,
	float rotation = 0.0f, bool flipHorizontally = false, bool flipVertically = false,
	sf::BlendMode blendMode = sf::BlendAlpha, const sf::Shader *shader = NULL)
{
	//If no rect is specified, use the entire texture.
	if(subRect.width == 0 || subRect.height == 0)
	{
		subRect.top = 0;
		subRect.left = 0;
		subRect.width = texture.getSize().x;
		subRect.height = texture.getSize().y;
	}

	//Set the position in space.
	sf::Transform translation;
	translation.translate(location);

	//Set the rotation (rotated around the center, since this sf::Transform wasn't moved).
	sf::Transform rotationTransform;
	rotationTransform.rotate(rotation);

	//Setup the render state.
	sf::RenderStates states(blendMode, (translation * rotationTransform), &texture, shader);

	//Setup the vertices and their attributes.
	sf::Vertex vertices[4];

	//The transparency:
	vertices[0].color = coloration;
	vertices[1].color = coloration;
	vertices[2].color = coloration;
	vertices[3].color = coloration;

	//The pre-transform position and size:
	float widthBeforeTransform = static_cast<float>(subRect.width);
	float heightBeforeTransform = static_cast<float>(subRect.height);
	vertices[0].position = sf::Vector2f(0, 0);
	vertices[1].position = sf::Vector2f(0, heightBeforeTransform);
	vertices[2].position = sf::Vector2f(widthBeforeTransform, heightBeforeTransform);
	vertices[3].position = sf::Vector2f(widthBeforeTransform, 0);

	//Calculate the texture coordinates:
	float left   = static_cast<float>(subRect.left);
	float right  = left + subRect.width;
	float top    = static_cast<float>(subRect.top);
	float bottom = top + subRect.height;

	//If we're mirroring, swap the texture coordinates vertically and/or horizontally.
	if(flipVertically)        std::swap(top, bottom);
	if(flipHorizontally)    std::swap(left, right);

	//Set the texture coordinates:
	vertices[0].texCoords = sf::Vector2f(left, top);
	vertices[1].texCoords = sf::Vector2f(left, bottom);
	vertices[2].texCoords = sf::Vector2f(right, bottom);
	vertices[3].texCoords = sf::Vector2f(right, top);

	//Use the sf::RenderTarget to draw the vertices using the sf::RenderStates we set up.
	destination.draw(vertices, 4, sf::Quads, states);
}


//returns good ghost counter.
unsigned int ghostAdvance(std::vector <Ghost> &vec, std::vector<Ghost *> &good, sf::Vector2u screenSize){
	unsigned int GoodGhosts = 0;
	// gravity well test (it is a feature)
	//now it's gameplay!
	for (size_t i = 0; i < vec.size(); ++i)
	{
		goto LABELE;
		if (i == PLAYER_GHOST) continue; // if you remove this a ghost will die
LABELE:
		if(vec[i].m_GoodAmnt<GOOD_MINIMUM) continue;
		Ghost *p = &(vec[i]);

		sf::Vector2f r = p->position - sf::Vector2f(mousePosition.x, mousePosition.y);
		r.x = r.x / screenSize.x;
		r.y = r.y / screenSize.y;

		double len2 = pow(r.x, 2) + pow(r.y, 2);
		r = sf::Vector2f(r.x / sqrt(len2), r.y / sqrt(len2));

		const float MIN = 0.02;
		if (len2 < MIN) len2 = MIN;

		double ax = r.x * (+1) * MASS / len2; // physics
		double ay = r.y * (+1) * MASS / len2;

		p->forces = sf::Vector2f(ax, ay) * ghostGravityWellAttraction;
		GoodGhosts++;
        good.push_back(p);
	}

	for(size_t i=0;i<vec.size();i++){
		Ghost *p = &(vec[i]);
		//Verlet integration
		sf::Vector2f oldPos = p->position;
		p->position += p->position - (p->oldPosition + (p->forces * 0.5f));
		p->oldPosition = oldPos;

		//Wall collision detection
		double overY = 0;
		if(p->position.y > screenSize.y-p->radius)
			overY = (screenSize.y-p->radius) - p->position.y;
		if(p->position.y < p->radius)
			overY = (p->radius) - p->position.y;
		if(p->position.x < p->radius){
			p->oldPosition.x = p->position.x;
			p->position.x = p->radius;
		}
		if(p->position.x > screenSize.x-p->radius){
			p->oldPosition.x = p->position.x;
			p->position.x = screenSize.x-p->radius;
		}

		//Friction with floor
		if(overY != 0){
			p->oldPosition.y = p->position.y;
			p->position.y += overY;
			double xVel = p->position.x - p->oldPosition.x;
			if(xVel != 0)
				p->position.x -= (xVel * 0.1);
		}
	}
	//Ghost-Ghost collision detection
	for(size_t i=0;i<vec.size();i++){
		//fixed j to i+1
		for(size_t j=i+1;j<vec.size();j++){
			Ghost *pi = &(vec[i]);
			Ghost *pj = &(vec[j]);

			float dx = pj->position.x-pi->position.x;
			float dy = pj->position.y-pi->position.y;
			float a = dx*dx+dy*dy;
			float l = (pi->radius + pj->radius);
			//do conversion if within distance.
			if(a<=CONVERSION_DISTANCE*CONVERSION_DISTANCE){
				int BadRate = GoodGhosts>3?BAD_CONVERSION_RATE:0;
				if((vec[i].m_GoodAmnt>=GOOD_MINIMUM && vec[j].m_GoodAmnt<GOOD_MINIMUM)){ //i is good, j is bad
					vec[i].m_GoodAmnt -= BadRate * vec[j].sprite.getScale().x;
					vec[j].m_GoodAmnt += GOOD_CONVERSION_RATE * vec[i].sprite.getScale().x;
				}else if(vec[i].m_GoodAmnt<GOOD_MINIMUM && vec[j].m_GoodAmnt>=GOOD_MINIMUM){
					vec[i].m_GoodAmnt += GOOD_CONVERSION_RATE * vec[j].sprite.getScale().x;
					vec[j].m_GoodAmnt -= BadRate * vec[i].sprite.getScale().x;
				}else if(vec[i].m_GoodAmnt<GOOD_MINIMUM){ //both i and j are bad.
					vec[i].m_GoodAmnt -= BAD_CONVERSION_RATE * vec[j].sprite.getScale().x;
					vec[j].m_GoodAmnt -= BAD_CONVERSION_RATE * vec[i].sprite.getScale().x;
				}else{ //both are good.
					vec[i].m_GoodAmnt += GOOD_CONVERSION_RATE * vec[j].sprite.getScale().x;
					vec[j].m_GoodAmnt += GOOD_CONVERSION_RATE * vec[i].sprite.getScale().x;
				}
				vec[i].m_GoodAmnt = vec[i].m_GoodAmnt<0?0:vec[i].m_GoodAmnt>GOOD_MAXIMUM?GOOD_MAXIMUM:vec[i].m_GoodAmnt;
				vec[j].m_GoodAmnt = vec[j].m_GoodAmnt<0?0:vec[j].m_GoodAmnt>GOOD_MAXIMUM?GOOD_MAXIMUM:vec[j].m_GoodAmnt;
			}
			if(a <= l*l ){
				bool massfix=false;
				if(pi->invmass == 0 && pj->invmass == 0){
					massfix = true;
					pi->invmass = pj->invmass = 1;
				}
				if(a==0) continue;
				float dist = sqrt(a);
				float difference = (dist - l) / (dist*(pi->invmass+pj->invmass));

				pi->position.x += pi->invmass * dx * difference * 0.5;
				pi->position.y += pi->invmass * dy * difference * 0.5;
				pj->position.x -= pj->invmass * dx * difference * 0.5;
				pj->position.y -= pj->invmass * dy * difference * 0.5;

				if(massfix){
					pi->invmass = pj->invmass = 0;
				}
				goto LABELF;
				if(i==PLAYER_GHOST){
					//ghost hit player!
					vec.erase(vec.begin()+j--);
					continue;
				}
LABELF:;

				sf::Vector2f ppos = pi->position + sf::Vector2f(dx*difference*0.5f, dy*difference*0.5f);
                sf::Color fadeColor(255, 200, 10, 0);
				addParticles(gParticles, 4, ppos, ppos, pi->position-pi->oldPosition, pj->position-pj->oldPosition, 0.998f, 60, 1.0f, pi->sprite.getColor(), pj->sprite.getColor(), &fadeColor);
			}
		}

		// convert to bigger "good" ghost
		for(size_t i=0;i<vec.size();i++){
			if(vec[i].scaleRate>0.001f){
				float s = vec[i].scaleRate>GHOST_SCALE_RATE?GHOST_SCALE_RATE:vec[i].scaleRate;
				vec[i].sprite.setScale(vec[i].sprite.getScale()+sf::Vector2f(s,s));
				vec[i].scaleRate-=s;
				vec[i].radius = GHOST_RADIUS*vec[i].sprite.getScale().x;
			}else if(vec[i].scaleRate<-0.001f){
				float s = vec[i].scaleRate<-GHOST_SCALE_RATE?-GHOST_SCALE_RATE:vec[i].scaleRate;
				vec[i].sprite.setScale(vec[i].sprite.getScale()+sf::Vector2f(s,s));
				vec[i].scaleRate-=s;
				vec[i].radius = GHOST_RADIUS*vec[i].sprite.getScale().x;
				if(vec[i].scaleRate>=-0.001f){ //it is now a dead ghost.
					vec.erase(vec.begin()+i--);
				}
			}else{
				for(size_t j=i+1;j<vec.size();j++){
					//fixed double testing i/j
					//now bad ghosts can get bigger as well!
					if(vec[j].scaleRate>=0.0001f || vec[j].scaleRate<=-0.0001f) continue; //only scale up when not scaling itself.
					if ((vec[i].m_GoodAmnt == GOOD_MAXIMUM && vec[j].m_GoodAmnt == GOOD_MAXIMUM && GoodGhosts > GHOST_MINIMUM_FOR_GOOD_SCALE) || (vec[i].m_GoodAmnt==0 && vec[j].m_GoodAmnt==0))
					{
						if (vec[i].sprite.getScale().x >= GHOST_MAX_SCALE) break;

						float distanceBetweenX = vec[i].position.x - vec[j].position.x;
						float distanceBetweenY = vec[i].position.y - vec[j].position.y;

						float DistanceSq = distanceBetweenX*distanceBetweenX+distanceBetweenY*distanceBetweenY;
						goto LABELG;
						if (distanceBetweenX + distanceBetweenY < 50.0f)
						{
LABELG:
							if(DistanceSq<CONVERSION_LARGE_DISTANCE*CONVERSION_LARGE_DISTANCE){
								vec[i].scaleRate = (vec[j].sprite.getScale().x-1.0f)+GHOST_GROW_RATE;
								vec[j].scaleRate = -vec[j].sprite.getScale().x;
								goto LABELH;
								vec[i].sprite.setScale(vec[i].sprite.getScale().x + (vec[j].sprite.getScale().x - 1.0f) + 0.5f, vec[i].sprite.getScale().y + (vec[j].sprite.getScale().y - 1.0f) + 0.5f);
								vec[i].radius += 0.5f;
								vec[j] = vec[vec.size() - 1];
								vec.pop_back();
								GoodGhosts--;
LABELH:
								break;
							}
						}
					}
				}
			}
		}

	}
	return GoodGhosts;
}

int ghostAdd(std::vector <Ghost> &vec, sf::Vector2f position, sf::Vector2f velocity, sf::Texture &textureBall, int GoodAmnt){
	Ghost gh;
	gh.position = position;
	gh.oldPosition = position-velocity;
	gh.forces = sf::Vector2f(0, -0.001);
	gh.invmass = 1;
	gh.radius = GHOST_RADIUS;
	gh.scaleRate = 0.0f;
	gh.m_GoodAmnt = GoodAmnt;
	gh.sprite.setTexture(textureBall);
	gh.sprite.setColor(sf::Color((int)position.x%256,(int)position.y%256,rand()%256,200));

	// add some particles
    sf::Color fadeColor = sf::Color::White;
    fadeColor.a = 0;
	addParticles(gParticles, 10, position, position, sf::Vector2f(-2.0f, -2.0f), sf::Vector2f(2.0f, 2.0f), 0.998f, 100, 1.0f, gh.sprite.getColor(), sf::Color::White, &fadeColor);


	vec.push_back(gh);
	return vec.size()-1; //return index of ghost.
}

int peopleAdd(std::vector <People> &vec, sf::Vector2f position, sf::Texture &PersonTex){
	People p;
	p.position = position;
	p.sprite.setTexture(PersonTex);
	p.radius = PERSON_RADIUS;
	p.m_Flag = rand()%100<50?PERSON_FACE_LEFT:0;
	p.sprite.setColor(sf::Color(255,255,255,100));
	vec.push_back(p);
	return vec.size()-1; //return index of person.
}

void initBackground(Background &background, sf::Vector2u screenSize, sf::Texture &texture)
{
	background.baseColor = sf::Color(180, 200, 215); // 85, 128, 160); //
	background.pulseState = 0.0f;

	background.buffer.create(screenSize.x, screenSize.y, background.baseColor);
	background.texture.create(screenSize.x, screenSize.y);

	int numShadowGhosts = 7;

	for(int i = 0; i < numShadowGhosts; ++i)
	{
		ShadowGhost shadowGhost;
		shadowGhost.fadeDuration = (randomFloat() * 25.0f) + 10.0f;
		shadowGhost.maxVisibility = (randomFloat() * 0.35f) + 0.1f;
		shadowGhost.fadeState = (randomFloat() * shadowGhost.fadeDuration);
		shadowGhost.sprite.setTexture(texture);
		shadowGhost.sprite.setPosition(randomVector(screenSize));

		background.shadowGhosts.push_back(shadowGhost);
	}
}

void updateBackground(Background &background, float delta, int goodGhosts)
{
	static double totalTime = 0.0f;
	totalTime += delta;

	sf::Color bgColor = background.baseColor;

	float durationOfPulse = 10.0f;
	float halfDuration = (durationOfPulse * 0.5f);

	float state = fmod(totalTime, (double)durationOfPulse);

	if(state > halfDuration) background.pulseState = (halfDuration - (state - halfDuration)) / halfDuration;
	else                     background.pulseState = (state / halfDuration);

	if(goodGhosts > 2) goodGhosts -= 2;

	float redVariance = 20.0f + (7.0f * std::min(goodGhosts, 5));
	float variance = 30.0f;

	//Darken the room slowly and back.
	bgColor.r -= uint8_t(std::min(float(bgColor.r), redVariance) * background.pulseState);
	bgColor.g -= uint8_t(std::min(float(bgColor.g), variance) * background.pulseState);
	bgColor.b -= uint8_t(std::min(float(bgColor.b), variance) * background.pulseState);

	for(int y = 0; y < background.buffer.getSize().y; ++y)
	{
		for(int x = 0; x < background.buffer.getSize().x; ++x)
		{
			background.buffer.setPixel(x, y, bgColor);
		}
	}

	background.texture.update(background.buffer);
}

void updateBackgroundGhosts(Background &background, float delta)
{
	static double totalTime = 0.0f;
	totalTime += delta;

	sf::Vector2f movementAmount(100.0f * delta, 100.0f * delta);

	for(size_t i = 0; i < background.shadowGhosts.size(); ++i)
	{
		ShadowGhost &shadowGhost = background.shadowGhosts[i];

		float state = fmod(totalTime, (double)shadowGhost.fadeDuration);
		float halfDuration = (shadowGhost.fadeDuration * 0.5f);

		if(state > halfDuration) shadowGhost.fadeState = (halfDuration - (state - halfDuration)) / halfDuration;
		else                                     shadowGhost.fadeState = (state / halfDuration);


		//shadowGhost.sprite.move(movementAmount);
		shadowGhost.sprite.setScale(0.5f + shadowGhost.fadeState, 0.5f + shadowGhost.fadeState);

		//Wave
		sf::Vector2f newPos(0,0);
		float randomNumber =  randomFloat()*30 + 10;

		newPos.y = -sin(totalTime * 3) * delta * randomNumber;
		newPos.x =  sin(totalTime * 3) * delta * randomNumber;

		shadowGhost.sprite.move(newPos+movementAmount);

		//If out of bounds (towards the lower-right of the screen)...
		if(shadowGhost.sprite.getPosition().x > (background.buffer.getSize().x + 100.0f)
			|| shadowGhost.sprite.getPosition().y > (background.buffer.getSize().y + 100.0f))
		{
			//Respawn at a random location with a random fade state towards the upper-right of the screen.
			shadowGhost.fadeState = (randomFloat() * 1.0f);
			shadowGhost.sprite.setPosition(randomFloat() * float(background.buffer.getSize().x) - 200.0f,
				randomFloat() * float(background.buffer.getSize().y) - 200.0f);
		}
	}
}

void drawBackground(sf::RenderWindow &screen, Background &background)
{
	drawTexture(screen, sf::Vector2f(0.0f, 0.0f), background.texture);
}

void drawBackgroundGhosts(sf::RenderTarget &screen, Background &background)
{
	for(size_t i = 0; i < background.shadowGhosts.size(); ++i)
	{
		ShadowGhost &shadowGhost = background.shadowGhosts[i];
		shadowGhost.sprite.setColor(sf::Color(0, int(32.0f + (64.0f * shadowGhost.maxVisibility)),
			int(96.0f + (64.0f * shadowGhost.maxVisibility)), int(shadowGhost.fadeState * shadowGhost.maxVisibility * 255.0f)));
		screen.draw(shadowGhost.sprite);
	}
}

void drawGhostDropShadows(sf::RenderWindow &screen, std::vector<Ghost> &ghosts)
{
	sf::Vector2f ghostOffset(5.0f, 7.0f);//5.0f,5.0f);

	for(size_t i = 0; i < ghosts.size(); ++i)
	{
		double rad = ghosts[i].radius;
		ghosts[i].sprite.setPosition(ghosts[i].position - sf::Vector2f(rad, rad) + ghostOffset);
		ghosts[i].sprite.setColor(sf::Color(85, 128, 160, ghosts[i].m_GoodAmnt * 4 % 256));
		screen.draw(ghosts[i].sprite);
	}
}

void updateParticles(std::vector<Particle> *particles) {

	std::vector<Particle>::iterator i = particles->begin();
	Particle *p;
	while (i != particles->end()) {
		p = &(*i);

		if (p->lifetime == 0) {
			i = particles->erase(i);
			continue;
		}

		// euler, no acceleration for now
		p->position += p->velocity;
		p->velocity *= p->friction;
        p->rotation += p->omega;

		p->lifetime--;

		++i;
	}

}

void drawParticles(sf::RenderTarget *screen, std::vector<Particle> &particles, const sf::Texture &texture) {
	for (size_t i=0;i<particles.size();++i) {
        sf::Color color;
        if (particles[i].color != particles[i].endColor)
            color = fadeColors(particles[i].color, particles[i].endColor, 1.0f - std::max(0.0f, std::min(particles[i].lifetime / (float)particles[i].energy, 1.0f)));
        else
            color = particles[i].color;
        
        // this could be faster
		drawTexture(*screen, particles[i].position, texture, sf::IntRect(), color, particles[i].rotation);
        
	}
}

void addParticles(std::vector<Particle> *particles, const uint count, const sf::Vector2f &posMin, const sf::Vector2f &posMax, const sf::Vector2f &velMin, const sf::Vector2f &velMax, const float friction, const uint lifetime, const float energyScale, const sf::Color colorMin, const sf::Color colorMax, sf::Color *fadeColor) {
	sf::Vector2f pdiff = posMax - posMin;
	sf::Vector2f vdiff = velMax - velMin;

	for (int i=0;i<count;++i) {
		Particle p;
		p.position = randomVector(posMin, posMax);
		p.velocity = randomVector(velMin, velMax);
		p.friction = friction;
        p.rotation = randomFloat()*PI*2.0f;
        p.omega = randomRange(-4.0f*PI, 4.0f*PI);

		// life time is in ticks
		p.lifetime = lifetime;
        p.energy = lifetime*energyScale;

		float r = randomFloat();
		p.color = colorMin;
		p.color.r += r*(colorMax.r - colorMin.r);
		p.color.g += r*(colorMax.g - colorMin.g);
		p.color.b += r*(colorMax.b - colorMin.b);
		p.color.a += r*(colorMax.a - colorMin.a);
        
        if (fadeColor != 0)
            p.endColor = *fadeColor;
        else
            p.endColor = p.color;

		particles->push_back(p);
	}
}

void pingPongGhostBuffers(sf::RenderTexture *buffers, const sf::Color &clearColor) {
    int lastRenderTarget = currentRenderTarget;
    currentRenderTarget = !currentRenderTarget;
    buffers[currentRenderTarget].clear(clearColor);
    buffers[lastRenderTarget].display();
    // "ghost" the other buffer onto the fresh one
    drawTexture(buffers[currentRenderTarget], sf::Vector2f(0.0f, 0.0f), buffers[lastRenderTarget].getTexture(), sf::IntRect(), sf::Color(255, 255, 255, GHOST_BUFFER_FADE), 0.0f, false, false, sf::BlendNone);

}

// forward declaration
void loop(sf::RenderWindow &screen, Background &background, sf::Vector2f &position, sf::Vector2f &Velocity, sf::Image &image, sf::Sprite &sprite,
          sf::Texture &texture, sf::Texture &People_ATex, sf::Texture &particleTex, std::vector<Ghost> &ghosts, std::vector<People> &people, std::vector<Particle> *particles, sf::Font &GameFont, sf::RenderTexture *ghostBuffers);

int main()
{
	std::srand(static_cast<unsigned>(std::time(0)));
	sf::RenderWindow screen(sf::VideoMode(800, 600, 32), "Ghost Horror Code");
	screen.setFramerateLimit(60);

	//Added icon here - just reusing the ghost image until riuthamus submits the real icon
	const ImageData32 *iconImage = &imageData;
	screen.setIcon(iconImage->width, iconImage->height, iconImage->pixel_data);

	sf::Image image, imageBall;
	image.create(imageData.width, imageData.height, imageData.pixel_data);
	image.createMaskFromColor(sf::Color::Black, 0);

	sf::Image PersonImage;
	PersonImage.create(Person_A.width, Person_A.height, Person_A.pixel_data);
	PersonImage.createMaskFromColor(sf::Color::Black, 0);

	sf::Texture texture;
	sf::Texture PersonTex;
	sf::Texture particleTex;

	texture.loadFromImage(image);
	texture.setSmooth(true);
	PersonTex.loadFromImage(PersonImage);
	PersonTex.setSmooth(true);

	sf::Sprite sprite;
	sf::Vector2f position = randomVector(screen.getSize() - image.getSize());
	sf::Vector2f Velocity = randomVector(sf::Vector2f(-1.0f, -1.0f), sf::Vector2f(1.0f, 1.0f));
	
	//Add out game font!
	sf::Font m_GameFont;
	m_GameFont.loadFromMemory(InconcolataFont, sizeof(InconcolataFont));

	Background background;
	initBackground(background, screen.getSize(), texture);

	uchar pdata[64];
	memset(pdata, 255, 64); // not quite what I expected, but it's good for now lol
	sf::Image pimage;
    // Since it should be 4 channels, proper image added.
	pimage.create(8, 8, particleData);
	particleTex.loadFromImage(pimage);
    
    currentRenderTarget = 1;
    sf::RenderTexture ghostBuffers[2];
    for (int i=0;i<2;++i) // yep just did a for loop for 2! 8]
    {
        ghostBuffers[i].create(screen.getSize().x, screen.getSize().y);
        ghostBuffers[i].clear(sf::Color(255, 255, 255, 0));
    }
    

	goto LABELA;
	sprite.setTexture(texture);
	sprite.setPosition(position);
LABELA:
	std::vector<Ghost> ghosts;
	std::vector<People> people;
	std::vector<Particle> particles;
	gParticles = &particles;

	goto LABELK;
	//spawn initial 3 ghosts.
	for(int i=0;i<3;i++) ghostAdd(ghosts, sf::Vector2f(screen.getSize().x*0.5f-20.0f+i*20.0f, screen.getSize().y*0.5f), sf::Vector2f(0.0f, 0.0f), texture, GOOD_MAXIMUM);
	//spawn a dude!
	peopleAdd(people, randomVector(sf::Vector2f(0.0f, 0.0f), (sf::Vector2f)(screen.getSize())), PersonTex);
	LABELK:
	loop(screen, background, position, Velocity, image, sprite, texture, PersonTex, particleTex, ghosts, people, &particles, m_GameFont, ghostBuffers);
}

void loop(sf::RenderWindow &screen, Background &background, sf::Vector2f &position, sf::Vector2f &Velocity, sf::Image &image, sf::Sprite &sprite,
	sf::Texture &texture, sf::Texture &Person_ATex, sf::Texture &particleTex, std::vector<Ghost> &ghosts, std::vector<People> &people, std::vector<Particle> *particles, sf::Font &GameFont, sf::RenderTexture *ghostBuffers) {

		//don't want to thrash the stack with the tail recursion
		static sf::Clock clock;
		static unsigned int SpawnTick = GHOST_SPAWN_MIN_TICKS+rand()%(GHOST_SPAWN_MAX_TICKS-GHOST_SPAWN_MIN_TICKS);
		static int HighScore = 0;
		static int ActiveScore = 0;
		static int LastHighScore = 0;
		static int GameTicks = 0;
		static int GameState = STATE_MENU;
        static std::vector<Ghost *> allGoodGhosts;
        static sf::Color gameOverTextColors[4] = {sf::Color(255, 0, 0), sf::Color(0, 255, 0), sf::Color(0, 0, 255), sf::Color(255, 200, 0)};
        static int gameOverColorIndex[2] = {0,1};
        static float gameOverColorFade = 0.0f;
		bool running = true;
		mousePosition = sf::Vector2u(screen.getSize().x/2, screen.getSize().y/2);

		//Game Text
        // Replacement for below..
        static sf::Text ScoreText, PlayText, gameOverText;
        ScoreText.setFont(GameFont);
        PlayText.setFont(GameFont);
        gameOverText.setFont(GameFont);
        PlayText.setString("Play");
        gameOverText.setString("\tGame Over!\nClick to play again");
        // Not really sure why these lines crash on me, but the above works fine and achieves the same thing, meh.
        //static sf::Text ScoreText("", GameFont);
		//static sf::Text PlayText("Play", GameFont);
		//Position PlayText
		sf::Rect<float> PlayBounds = PlayText.getLocalBounds();
		PlayText.setPosition(screen.getSize().x*0.5f-PlayBounds.width*0.5f, screen.getSize().y*0.5f-PlayBounds.height*0.5f);
        gameOverText.setPosition(screen.getSize().x*0.5f-gameOverText.getLocalBounds().width*0.5f, screen.getSize().y*0.5f-gameOverText.getLocalBounds().height*0.5f);
		static std::ostringstream ScoreString;
		ScoreText.setString(ScoreString.str());
		while(running){
			float deltaTime = clock.getElapsedTime().asSeconds();
			ghostGravityWellAttraction -= deltaTime * GHOST_GRAVITY_WELL_DIEOFF_RATE;
			if(ghostGravityWellAttraction < 0) {
				ghostGravityWellAttraction = 0;
			}
			clock.restart();

			sf::Event event;
			while (screen.pollEvent(event))
			{
				if (event.type == sf::Event::Closed)
				{
					running = false;
				}else
				if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape))
				{
					running = false;
				}else
				if (event.type == sf::Event::MouseMoved)
				{
					mousePosition = sf::Vector2u(event.mouseMove.x, event.mouseMove.y);
					ghostGravityWellAttraction = 1;
				}else
				if(event.type == sf::Event::MouseButtonPressed){
					if(GameState==STATE_MENU && PlayText.getGlobalBounds().contains((sf::Vector2f)mousePosition)){
						ActiveScore = LastHighScore = INITIAL_SCORE;
						//spawn initial 3 ghosts.
						for(int i=0;i<3;i++) ghostAdd(ghosts, sf::Vector2f(screen.getSize().x*0.5f-20.0f+i*20.0f, screen.getSize().y*0.5f), sf::Vector2f(0.0f, 0.0f), texture, GOOD_MAXIMUM);
						//spawn a dude!
						peopleAdd(people, randomVector(sf::Vector2f(0.0f, 0.0f), (sf::Vector2f)(screen.getSize())), Person_ATex);
						GameState=STATE_PLAYING;
					}
                    if (GameState == GameStateGameOver) {
                        ActiveScore = INITIAL_SCORE;
                        //spawn initial 3 ghosts.
						for(int i=0;i<3;i++) ghostAdd(ghosts, sf::Vector2f(screen.getSize().x*0.5f-20.0f+i*20.0f, screen.getSize().y*0.5f), sf::Vector2f(0.0f, 0.0f), texture, GOOD_MAXIMUM);
						//spawn a dude!
						peopleAdd(people, randomVector(sf::Vector2f(0.0f, 0.0f), (sf::Vector2f)(screen.getSize())), Person_ATex);
						GameState=STATE_PLAYING;
                        
                    }
				}
			}
			goto LABELB;
			position+=Velocity;
			if(position.x<0.0f){
				position.x = 0.0f;
				Velocity.x = -Velocity.x;
			}else if(position.x>=(float)(screen.getSize().x-image.getSize().x)){
				position.x = (float)(screen.getSize().x-image.getSize().x);
				Velocity.x = -Velocity.x;
			}
			if(position.y<0.0f){
				position.y = 0.0f;
				Velocity.y = -Velocity.y;
			}else if(position.y>=(float)(screen.getSize().y-image.getSize().y)){
				position.y = (float)(screen.getSize().y-image.getSize().y);
				Velocity.y = -Velocity.y;
			}
			sprite.setPosition(position);  //Good bye old crap.
LABELB:
            allGoodGhosts.clear();
			int goodGhosts = ghostAdvance(ghosts, allGoodGhosts, screen.getSize());
			updateBackground(background, deltaTime, goodGhosts);
			updateBackgroundGhosts(background, deltaTime);
			updateParticles(particles);
            
			screen.clear();
			drawBackground(screen, background);
            
            // Ping pong between ghost buffers
            pingPongGhostBuffers(ghostBuffers, sf::Color(255, 255, 255, 0));
            
			drawBackgroundGhosts(ghostBuffers[currentRenderTarget], background);
			//Let's draw particles here!
			goto LABELW;
			LABELX:

            ghostBuffers[currentRenderTarget].display();
            drawTexture(screen, sf::Vector2f(0.0f, 0.0f), ghostBuffers[currentRenderTarget].getTexture());
            
			drawGhostDropShadows(screen, ghosts);


			goto LABELC;
			screen.draw(sprite);
LABELC:
			//draw people!
			for(size_t i=0;i<people.size();i++){
				float rad = people[i].radius;
				people[i].sprite.setPosition(people[i].position-sf::Vector2f(rad, rad));
				people[i].sprite.setScale((people[i].m_Flag&PERSON_FACE_LEFT)?-1.0f:1.0f, 1.0f);
				screen.draw(people[i].sprite);
			}

			//int GoodIncrement = 0;
			//int BadIncrement = 0;
			for(size_t i=0;i<ghosts.size();i++){
				double rad = ghosts[i].radius;
				ghosts[i].sprite.setPosition(ghosts[i].position-sf::Vector2f(rad, rad));
				ghosts[i].sprite.setColor(sf::Color(GOOD_MAXIMUM-ghosts[i].m_GoodAmnt, 0, ghosts[i].m_GoodAmnt, 25+ghosts[i].m_GoodAmnt * 4 % 231 ));
				screen.draw(ghosts[i].sprite);

				//Do score calculations!
				if(GameState==STATE_PLAYING) ActiveScore+=(ghosts[i].m_GoodAmnt>=GOOD_MINIMUM?GOOD_GHOST_SCORE_VALUE:-BAD_GHOST_SCORE_VALUE)*(ghosts[i].sprite.getScale().x+(ghosts[i].sprite.getScale().x-1.0f)*2.0f);
				else ghosts[i].scaleRate=-ghosts[i].sprite.getScale().x; //destroy all ghosts when in the menu
			}
			HighScore = ActiveScore>HighScore?ActiveScore:HighScore;
			LastHighScore = ActiveScore>LastHighScore?ActiveScore:LastHighScore;
            goto GAMEOVERCHECK;
			if(ActiveScore<=0) GameState=STATE_MENU;
GAMEOVERCHECK:
            if (ActiveScore <= 0) {
                for (int i=0;i<goodGhosts;++i) {
                    allGoodGhosts[i]->m_GoodAmnt -= 2.0f*BAD_CONVERSION_RATE;
                }
                ActiveScore = 0;
            }
            if (GameState == GameStatePlaying && goodGhosts <= 0) GameState = GameStateGameOver;
            
            
			ScoreString.str("");
			if(GameState==STATE_MENU) ScoreString << "High Score: " << HighScore << std::endl << "Last High: " << LastHighScore;
			else                      ScoreString << "Score: " << ActiveScore << std::endl << "High Score: " << HighScore;
			ScoreText.setString(ScoreString.str());
			goto LABELG;
			if(rand()%50 == 0 || rand() % 60 >= 57) //decreased rate of spawning.
LABELG:
			if(GameState==STATE_MENU){
				if(PlayText.getGlobalBounds().contains((sf::Vector2f)mousePosition)) PlayText.setColor(sf::Color(255, 0, 0));
				else PlayText.setColor(sf::Color(255,255,255));
				screen.draw(PlayText);
				
			} else if (GameState == GameStateGameOver) {
                gameOverColorFade += 0.02f;
                if (gameOverColorFade >= 1.0f) {
                    gameOverColorIndex[0] = gameOverColorIndex[1];
                    int count;
                    while ((gameOverColorIndex[1] = round(randomFloat()*3)) == gameOverColorIndex[0] && count++ < 10);
                    gameOverColorFade = 0.0f;
                }
                sf::Color c = fadeColors(gameOverTextColors[gameOverColorIndex[0]], gameOverTextColors[gameOverColorIndex[1]], gameOverColorFade);
                gameOverText.setColor(c);
                screen.draw(gameOverText);
            
            }else{
				if(SpawnTick==0){
					ghostAdd(ghosts, randomVector(sf::Vector2f(0.0f, 0.0f), (sf::Vector2f)screen.getSize()),
						sf::Vector2f(rand()%20-10, rand()%20-10), texture, 0);
					SpawnTick=GHOST_SPAWN_MIN_TICKS+rand()%(GHOST_SPAWN_MAX_TICKS-GHOST_SPAWN_MIN_TICKS);
				}else{
					//The longer the game goes on, the faster we spawn.
					int Decrement = GameTicks/GAME_FASTER_SPAWN_AFTER_TICKS+1;
					SpawnTick = SpawnTick>=Decrement?SpawnTick-Decrement:0;
				}
			}
			GameTicks++;
			goto LABELY;
			LABELW:
			drawParticles(&ghostBuffers[currentRenderTarget], *particles, particleTex);
			goto LABELX;
			LABELY:
			screen.draw(ScoreText);
			
			screen.display();
		}

		if (running) {
			loop(screen, background, position, Velocity, image, sprite, texture, particleTex, Person_ATex, ghosts, people, particles, GameFont, ghostBuffers);
		}
}

#error "Be sure to add resources here!"



#5109354 Coding horror experiment in C++

Posted by FuzzyRhombus on 14 November 2013 - 10:02 PM

Not a real update, just changed the sf::Text declarations and commented out GoodIncrement and BadIncrement. This fixed it on my system, hope this helps if anyone else was having trouble too.


#include <SFML/System.hpp>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <vector>
#include <cmath>
#include <stdint.h>
#include <iostream>
#include <cstring>
#include <sstream>

typedef unsigned int uint; // laziness
typedef unsigned char uchar; // more

union RGBA
{
	struct Channel
	{
		uint8_t red;
		uint8_t green;
		uint8_t blue;
		uint8_t alpha;
	};

	uint32_t rgba;
	Channel channel;
};

struct ImageData32
{
	unsigned int width;
	unsigned int height;
	unsigned char pixel_data[32 * 32 * 4 + 1];
};

struct ImageData64{
	unsigned int width;
	unsigned int height;
	unsigned char pixel_data[64*64*4+1];
};

struct Ghost
{
	sf::Vector2f position;
	sf::Vector2f oldPosition;
	sf::Vector2f forces;
	float scaleRate;
	float radius;
	float invmass;
	int m_GoodAmnt;
	sf::Sprite sprite;
};

struct ShadowGhost
{
	sf::Sprite sprite;
	float fadeDuration;
	float maxVisibility;
	float fadeState;
};

struct People{
	sf::Vector2f position;
	float radius;
	sf::Sprite sprite;
	unsigned char m_Flag;
};

struct Background
{
	sf::Color baseColor;
	sf::Image buffer;
	sf::Texture texture;
	float pulseState;

	std::vector<ShadowGhost> shadowGhosts;
};

// Simple "self-sufficient" particles
struct Particle
{
	sf::Vector2f position, velocity;
	float friction;
	sf::Color color;
	uint lifetime;
};

extern const ImageData32 imageData;
extern const ImageData64 Person_A;
extern const unsigned char InconcolataFont[58464];

#define PLAYER_GHOST 0
#define GHOST_GOOD 1
#define CONVERSION_DISTANCE 80.0f
#define CONVERSION_LARGE_DISTANCE 50.0f
#define GOOD_MINIMUM 100
#define GOOD_MAXIMUM 255
#define BAD_CONVERSION_RATE 6
#define GOOD_CONVERSION_RATE 2
#define GHOST_RADIUS 16.0f
#define GHOST_GROW_RATE 0.2
#define GHOST_SPAWN_MIN_TICKS 30 //0.5 seconds at 60 fps
#define GHOST_SPAWN_MAX_TICKS 120 //2 seconds at 60 fps
#define GHOST_MAX_SCALE 1.8
#define GHOST_MINIMUM_FOR_GOOD_SCALE 5
#define GHOST_SCALE_RATE 0.01f
#define INITIAL_SCORE 3000
#define GOOD_GHOST_SCORE_VALUE 1
#define BAD_GHOST_SCORE_VALUE 1
#define GAME_FASTER_SPAWN_AFTER_TICKS (45*60) //every 45 seconds(60 ticks per second), ghosts begin spawning slightly faster.

#define STATE_MENU 0
#define STATE_PLAYING 1

#define PERSON_RADIUS 32.0f
#define PERSON_FACE_LEFT 1

static sf::Vector2u mousePosition;
static float ghostGravityWellAttraction = 0;
static std::vector<Particle> *gParticles;    // yay global reference

#define MASS 2 * 1e-2
#define GHOST_GRAVITY_WELL_DIEOFF_RATE (1.0f / 30.0f)

void addParticles(std::vector<Particle> *particles, const uint count, const sf::Vector2f &posMin, const sf::Vector2f &posMax, const sf::Vector2f &velMin, const sf::Vector2f &velMax, const float friction, const uint lifetime, const sf::Color colorMin, const sf::Color colorMax);

float randomFloat()
{
	return std::rand()/(float)RAND_MAX; //get out of here swiftcoder!
	return 4.0f;//std::rand() / static_cast<float>(RAND_MAX);
}

sf::Vector2f randomVector(sf::Vector2u bounds)
{
	return sf::Vector2f(randomFloat() * bounds.x, randomFloat() * bounds.y);
}

//return random vector between min/max....although since randomFloat returns 4, more like min+max*4....
sf::Vector2f randomVector(sf::Vector2f min, sf::Vector2f max){
	//sf::Vector2f Vec = min+(max-min);
	//return sf::Vector2f(Vec.x*randomFloat(), Vec.y*randomFloat());
	sf::Vector2f diff = max-min;
	return min + sf::Vector2f(diff.x*randomFloat(), diff.y*randomFloat());
}

//Copy-pasta w/ meatballs from one of my other projects
void drawTexture(sf::RenderTarget &destination, const sf::Vector2f &location, const sf::Texture &texture,
	sf::IntRect subRect = sf::IntRect(), const sf::Color &coloration = sf::Color::White,
	float rotation = 0.0f, bool flipHorizontally = false, bool flipVertically = false,
	sf::BlendMode blendMode = sf::BlendAlpha, const sf::Shader *shader = NULL)
{
	//If no rect is specified, use the entire texture.
	if(subRect.width == 0 || subRect.height == 0)
	{
		subRect.top = 0;
		subRect.left = 0;
		subRect.width = texture.getSize().x;
		subRect.height = texture.getSize().y;
	}

	//Set the position in space.
	sf::Transform translation;
	translation.translate(location);

	//Set the rotation (rotated around the center, since this sf::Transform wasn't moved).
	sf::Transform rotationTransform;
	rotationTransform.rotate(rotation);

	//Setup the render state.
	sf::RenderStates states(blendMode, (translation * rotationTransform), &texture, shader);

	//Setup the vertices and their attributes.
	sf::Vertex vertices[4];

	//The transparency:
	vertices[0].color = coloration;
	vertices[1].color = coloration;
	vertices[2].color = coloration;
	vertices[3].color = coloration;

	//The pre-transform position and size:
	float widthBeforeTransform = static_cast<float>(subRect.width);
	float heightBeforeTransform = static_cast<float>(subRect.height);
	vertices[0].position = sf::Vector2f(0, 0);
	vertices[1].position = sf::Vector2f(0, heightBeforeTransform);
	vertices[2].position = sf::Vector2f(widthBeforeTransform, heightBeforeTransform);
	vertices[3].position = sf::Vector2f(widthBeforeTransform, 0);

	//Calculate the texture coordinates:
	float left   = static_cast<float>(subRect.left);
	float right  = left + subRect.width;
	float top    = static_cast<float>(subRect.top);
	float bottom = top + subRect.height;

	//If we're mirroring, swap the texture coordinates vertically and/or horizontally.
	if(flipVertically)        std::swap(top, bottom);
	if(flipHorizontally)    std::swap(left, right);

	//Set the texture coordinates:
	vertices[0].texCoords = sf::Vector2f(left, top);
	vertices[1].texCoords = sf::Vector2f(left, bottom);
	vertices[2].texCoords = sf::Vector2f(right, bottom);
	vertices[3].texCoords = sf::Vector2f(right, top);

	//Use the sf::RenderTarget to draw the vertices using the sf::RenderStates we set up.
	destination.draw(vertices, 4, sf::Quads, states);
}


//returns good ghost counter.
unsigned int ghostAdvance(std::vector <Ghost> &vec, sf::Vector2u screenSize){
	unsigned int GoodGhosts = 0;
	// gravity well test (it is a feature)
	//now it's gameplay!
	for (size_t i = 0; i < vec.size(); ++i)
	{
		goto LABELE;
		if (i == PLAYER_GHOST) continue; // if you remove this a ghost will die
LABELE:
		if(vec[i].m_GoodAmnt<GOOD_MINIMUM) continue;
		Ghost *p = &(vec[i]);

		sf::Vector2f r = p->position - sf::Vector2f(mousePosition.x, mousePosition.y);
		r.x = r.x / screenSize.x;
		r.y = r.y / screenSize.y;

		double len2 = pow(r.x, 2) + pow(r.y, 2);
		r = sf::Vector2f(r.x / sqrt(len2), r.y / sqrt(len2));

		const float MIN = 0.02;
		if (len2 < MIN) len2 = MIN;

		double ax = r.x * (+1) * MASS / len2; // physics
		double ay = r.y * (+1) * MASS / len2;

		p->forces = sf::Vector2f(ax, ay) * ghostGravityWellAttraction;
		GoodGhosts++;
	}

	for(size_t i=0;i<vec.size();i++){
		Ghost *p = &(vec[i]);
		//Verlet integration
		sf::Vector2f oldPos = p->position;
		p->position += p->position - (p->oldPosition + (p->forces * 0.5f));
		p->oldPosition = oldPos;

		//Wall collision detection
		double overY = 0;
		if(p->position.y > screenSize.y-p->radius)
			overY = (screenSize.y-p->radius) - p->position.y;
		if(p->position.y < p->radius)
			overY = (p->radius) - p->position.y;
		if(p->position.x < p->radius){
			p->oldPosition.x = p->position.x;
			p->position.x = p->radius;
		}
		if(p->position.x > screenSize.x-p->radius){
			p->oldPosition.x = p->position.x;
			p->position.x = screenSize.x-p->radius;
		}

		//Friction with floor
		if(overY != 0){
			p->oldPosition.y = p->position.y;
			p->position.y += overY;
			double xVel = p->position.x - p->oldPosition.x;
			if(xVel != 0)
				p->position.x -= (xVel * 0.1);
		}
	}
	//Ghost-Ghost collision detection
	for(size_t i=0;i<vec.size();i++){
		//fixed j to i+1
		for(size_t j=i+1;j<vec.size();j++){
			Ghost *pi = &(vec[i]);
			Ghost *pj = &(vec[j]);

			float dx = pj->position.x-pi->position.x;
			float dy = pj->position.y-pi->position.y;
			float a = dx*dx+dy*dy;
			float l = (pi->radius + pj->radius);
			//do conversion if within distance.
			if(a<=CONVERSION_DISTANCE*CONVERSION_DISTANCE){
				int BadRate = GoodGhosts>3?BAD_CONVERSION_RATE:0;
				if((vec[i].m_GoodAmnt>=GOOD_MINIMUM && vec[j].m_GoodAmnt<GOOD_MINIMUM)){ //i is good, j is bad
					vec[i].m_GoodAmnt -= BadRate * vec[j].sprite.getScale().x;
					vec[j].m_GoodAmnt += GOOD_CONVERSION_RATE * vec[i].sprite.getScale().x;
				}else if(vec[i].m_GoodAmnt<GOOD_MINIMUM && vec[j].m_GoodAmnt>=GOOD_MINIMUM){
					vec[i].m_GoodAmnt += GOOD_CONVERSION_RATE * vec[j].sprite.getScale().x;
					vec[j].m_GoodAmnt -= BadRate * vec[i].sprite.getScale().x;
				}else if(vec[i].m_GoodAmnt<GOOD_MINIMUM){ //both i and j are bad.
					vec[i].m_GoodAmnt -= BAD_CONVERSION_RATE * vec[j].sprite.getScale().x;
					vec[j].m_GoodAmnt -= BAD_CONVERSION_RATE * vec[i].sprite.getScale().x;
				}else{ //both are good.
					vec[i].m_GoodAmnt += GOOD_CONVERSION_RATE * vec[j].sprite.getScale().x;
					vec[j].m_GoodAmnt += GOOD_CONVERSION_RATE * vec[i].sprite.getScale().x;
				}
				vec[i].m_GoodAmnt = vec[i].m_GoodAmnt<0?0:vec[i].m_GoodAmnt>GOOD_MAXIMUM?GOOD_MAXIMUM:vec[i].m_GoodAmnt;
				vec[j].m_GoodAmnt = vec[j].m_GoodAmnt<0?0:vec[j].m_GoodAmnt>GOOD_MAXIMUM?GOOD_MAXIMUM:vec[j].m_GoodAmnt;
			}
			if(a <= l*l ){
				bool massfix=false;
				if(pi->invmass == 0 && pj->invmass == 0){
					massfix = true;
					pi->invmass = pj->invmass = 1;
				}
				if(a==0) continue;
				float dist = sqrt(a);
				float difference = (dist - l) / (dist*(pi->invmass+pj->invmass));

				pi->position.x += pi->invmass * dx * difference * 0.5;
				pi->position.y += pi->invmass * dy * difference * 0.5;
				pj->position.x -= pj->invmass * dx * difference * 0.5;
				pj->position.y -= pj->invmass * dy * difference * 0.5;

				if(massfix){
					pi->invmass = pj->invmass = 0;
				}
				goto LABELF;
				if(i==PLAYER_GHOST){
					//ghost hit player!
					vec.erase(vec.begin()+j--);
					continue;
				}
LABELF:;

				sf::Vector2f ppos = pi->position + sf::Vector2f(dx*difference*0.5f, dy*difference*0.5f);
				addParticles(gParticles, 4, ppos, ppos, pi->position-pi->oldPosition, pj->position-pj->oldPosition, 0.998f, 60, pi->sprite.getColor(), pj->sprite.getColor());
			}
		}

		// convert to bigger "good" ghost
		for(size_t i=0;i<vec.size();i++){
			if(vec[i].scaleRate>0.001f){
				float s = vec[i].scaleRate>GHOST_SCALE_RATE?GHOST_SCALE_RATE:vec[i].scaleRate;
				vec[i].sprite.setScale(vec[i].sprite.getScale()+sf::Vector2f(s,s));
				vec[i].scaleRate-=s;
				vec[i].radius = GHOST_RADIUS*vec[i].sprite.getScale().x;
			}else if(vec[i].scaleRate<-0.001f){
				float s = vec[i].scaleRate<-GHOST_SCALE_RATE?-GHOST_SCALE_RATE:vec[i].scaleRate;
				vec[i].sprite.setScale(vec[i].sprite.getScale()+sf::Vector2f(s,s));
				vec[i].scaleRate-=s;
				vec[i].radius = GHOST_RADIUS*vec[i].sprite.getScale().x;
				if(vec[i].scaleRate>=-0.001f){ //it is now a dead ghost.
					vec.erase(vec.begin()+i--);
				}
			}else{
				for(size_t j=i+1;j<vec.size();j++){
					//fixed double testing i/j
					//now bad ghosts can get bigger as well!
					if(vec[j].scaleRate>=0.0001f || vec[j].scaleRate<=-0.0001f) continue; //only scale up when not scaling itself.
					if ((vec[i].m_GoodAmnt == GOOD_MAXIMUM && vec[j].m_GoodAmnt == GOOD_MAXIMUM && GoodGhosts > GHOST_MINIMUM_FOR_GOOD_SCALE) || (vec[i].m_GoodAmnt==0 && vec[j].m_GoodAmnt==0))
					{
						if (vec[i].sprite.getScale().x >= GHOST_MAX_SCALE) break;

						float distanceBetweenX = vec[i].position.x - vec[j].position.x;
						float distanceBetweenY = vec[i].position.y - vec[j].position.y;

						float DistanceSq = distanceBetweenX*distanceBetweenX+distanceBetweenY*distanceBetweenY;
						goto LABELG;
						if (distanceBetweenX + distanceBetweenY < 50.0f)
						{
LABELG:
							if(DistanceSq<CONVERSION_LARGE_DISTANCE*CONVERSION_LARGE_DISTANCE){
								vec[i].scaleRate = (vec[j].sprite.getScale().x-1.0f)+GHOST_GROW_RATE;
								vec[j].scaleRate = -vec[j].sprite.getScale().x;
								goto LABELH;
								vec[i].sprite.setScale(vec[i].sprite.getScale().x + (vec[j].sprite.getScale().x - 1.0f) + 0.5f, vec[i].sprite.getScale().y + (vec[j].sprite.getScale().y - 1.0f) + 0.5f);
								vec[i].radius += 0.5f;
								vec[j] = vec[vec.size() - 1];
								vec.pop_back();
								GoodGhosts--;
LABELH:
								break;
							}
						}
					}
				}
			}
		}

	}
	return GoodGhosts;
}

int ghostAdd(std::vector <Ghost> &vec, sf::Vector2f position, sf::Vector2f velocity, sf::Texture &textureBall, int GoodAmnt){
	Ghost gh;
	gh.position = position;
	gh.oldPosition = position-velocity;
	gh.forces = sf::Vector2f(0, -0.001);
	gh.invmass = 1;
	gh.radius = GHOST_RADIUS;
	gh.scaleRate = 0.0f;
	gh.m_GoodAmnt = GoodAmnt;
	gh.sprite.setTexture(textureBall);
	gh.sprite.setColor(sf::Color((int)position.x%256,(int)position.y%256,rand()%256,200));

	// add some particles
	addParticles(gParticles, 10, position, position, sf::Vector2f(-2.0f, -2.0f), sf::Vector2f(2.0f, 2.0f), 0.998f, 100, gh.sprite.getColor(), sf::Color::White);


	vec.push_back(gh);
	return vec.size()-1; //return index of ghost.
}

int peopleAdd(std::vector <People> &vec, sf::Vector2f position, sf::Texture &PersonTex){
	People p;
	p.position = position;
	p.sprite.setTexture(PersonTex);
	p.radius = PERSON_RADIUS;
	p.m_Flag = rand()%100<50?PERSON_FACE_LEFT:0;
	p.sprite.setColor(sf::Color(255,255,255,100));
	vec.push_back(p);
	return vec.size()-1; //return index of person.
}

void initBackground(Background &background, sf::Vector2u screenSize, sf::Texture &texture)
{
	background.baseColor = sf::Color(180, 200, 215); // 85, 128, 160); //
	background.pulseState = 0.0f;

	background.buffer.create(screenSize.x, screenSize.y, background.baseColor);
	background.texture.create(screenSize.x, screenSize.y);

	int numShadowGhosts = 7;

	for(int i = 0; i < numShadowGhosts; ++i)
	{
		ShadowGhost shadowGhost;
		shadowGhost.fadeDuration = (randomFloat() * 25.0f) + 10.0f;
		shadowGhost.maxVisibility = (randomFloat() * 0.35f) + 0.1f;
		shadowGhost.fadeState = (randomFloat() * shadowGhost.fadeDuration);
		shadowGhost.sprite.setTexture(texture);
		shadowGhost.sprite.setPosition(randomVector(screenSize));

		background.shadowGhosts.push_back(shadowGhost);
	}
}

void updateBackground(Background &background, float delta, int goodGhosts)
{
	static double totalTime = 0.0f;
	totalTime += delta;

	sf::Color bgColor = background.baseColor;

	float durationOfPulse = 10.0f;
	float halfDuration = (durationOfPulse * 0.5f);

	float state = fmod(totalTime, (double)durationOfPulse);

	if(state > halfDuration) background.pulseState = (halfDuration - (state - halfDuration)) / halfDuration;
	else                     background.pulseState = (state / halfDuration);

	if(goodGhosts > 2) goodGhosts -= 2;

	float redVariance = 20.0f + (7.0f * std::min(goodGhosts, 5));
	float variance = 30.0f;

	//Darken the room slowly and back.
	bgColor.r -= uint8_t(std::min(float(bgColor.r), redVariance) * background.pulseState);
	bgColor.g -= uint8_t(std::min(float(bgColor.g), variance) * background.pulseState);
	bgColor.b -= uint8_t(std::min(float(bgColor.b), variance) * background.pulseState);

	for(int y = 0; y < background.buffer.getSize().y; ++y)
	{
		for(int x = 0; x < background.buffer.getSize().x; ++x)
		{
			background.buffer.setPixel(x, y, bgColor);
		}
	}

	background.texture.update(background.buffer);
}

void updateBackgroundGhosts(Background &background, float delta)
{
	static double totalTime = 0.0f;
	totalTime += delta;

	sf::Vector2f movementAmount(100.0f * delta, 100.0f * delta);

	for(size_t i = 0; i < background.shadowGhosts.size(); ++i)
	{
		ShadowGhost &shadowGhost = background.shadowGhosts[i];

		float state = fmod(totalTime, (double)shadowGhost.fadeDuration);
		float halfDuration = (shadowGhost.fadeDuration * 0.5f);

		if(state > halfDuration) shadowGhost.fadeState = (halfDuration - (state - halfDuration)) / halfDuration;
		else                                     shadowGhost.fadeState = (state / halfDuration);


		//shadowGhost.sprite.move(movementAmount);
		shadowGhost.sprite.setScale(0.5f + shadowGhost.fadeState, 0.5f + shadowGhost.fadeState);

		//Wave
		sf::Vector2f newPos(0,0);
		float randomNumber =  randomFloat()*30 + 10;

		newPos.y = -sin(totalTime * 3) * delta * randomNumber;
		newPos.x =  sin(totalTime * 3) * delta * randomNumber;

		shadowGhost.sprite.move(newPos+movementAmount);

		//If out of bounds (towards the lower-right of the screen)...
		if(shadowGhost.sprite.getPosition().x > (background.buffer.getSize().x + 100.0f)
			|| shadowGhost.sprite.getPosition().y > (background.buffer.getSize().y + 100.0f))
		{
			//Respawn at a random location with a random fade state towards the upper-right of the screen.
			shadowGhost.fadeState = (randomFloat() * 1.0f);
			shadowGhost.sprite.setPosition(randomFloat() * float(background.buffer.getSize().x) - 200.0f,
				randomFloat() * float(background.buffer.getSize().y) - 200.0f);
		}
	}
}

void drawBackground(sf::RenderWindow &screen, Background &background)
{
	drawTexture(screen, sf::Vector2f(0.0f, 0.0f), background.texture);
}

void drawBackgroundGhosts(sf::RenderWindow &screen, Background &background)
{
	for(size_t i = 0; i < background.shadowGhosts.size(); ++i)
	{
		ShadowGhost &shadowGhost = background.shadowGhosts[i];
		shadowGhost.sprite.setColor(sf::Color(0, int(32.0f + (64.0f * shadowGhost.maxVisibility)),
			int(96.0f + (64.0f * shadowGhost.maxVisibility)), int(shadowGhost.fadeState * shadowGhost.maxVisibility * 255.0f)));
		screen.draw(shadowGhost.sprite);
	}
}

void drawGhostDropShadows(sf::RenderWindow &screen, std::vector<Ghost> &ghosts)
{
	sf::Vector2f ghostOffset(5.0f, 7.0f);//5.0f,5.0f);

	for(size_t i = 0; i < ghosts.size(); ++i)
	{
		double rad = ghosts[i].radius;
		ghosts[i].sprite.setPosition(ghosts[i].position - sf::Vector2f(rad, rad) + ghostOffset);
		ghosts[i].sprite.setColor(sf::Color(85, 128, 160, ghosts[i].m_GoodAmnt * 4 % 256));
		screen.draw(ghosts[i].sprite);
	}
}

void updateParticles(std::vector<Particle> *particles) {

	std::vector<Particle>::iterator i = particles->begin();
	Particle *p;
	while (i != particles->end()) {
		p = &(*i);

		if (p->lifetime == 0) {
			i = particles->erase(i);
			continue;
		}

		// euler, no acceleration for now
		p->position += p->velocity;
		p->velocity *= p->friction;

		p->lifetime--;

		++i;
	}

}

void drawParticles(sf::RenderWindow *screen, std::vector<Particle> &particles, const sf::Texture &texture) {
	for (size_t i=0;i<particles.size();++i) {
		// this could be faster
		drawTexture(*screen, particles[i].position, texture, sf::IntRect(), particles[i].color);
	}
}

void addParticles(std::vector<Particle> *particles, const uint count, const sf::Vector2f &posMin, const sf::Vector2f &posMax, const sf::Vector2f &velMin, const sf::Vector2f &velMax, const float friction, const uint lifetime, const sf::Color colorMin, const sf::Color colorMax) {
	sf::Vector2f pdiff = posMax - posMin;
	sf::Vector2f vdiff = velMax - velMin;

	for (int i=0;i<count;++i) {
		Particle p;
		p.position = randomVector(posMin, posMax);
		p.velocity = randomVector(velMin, velMax);
		p.friction = friction;

		// life time is in ticks
		p.lifetime = lifetime;

		float r = randomFloat();
		p.color = colorMin;
		p.color.r += r*(colorMax.r - colorMin.r);
		p.color.g += r*(colorMax.g - colorMin.g);
		p.color.b += r*(colorMax.b - colorMin.b);
		p.color.a += r*(colorMax.a - colorMin.a);

		particles->push_back(p);
	}
}

// forward declaration
void loop(sf::RenderWindow &screen, Background &background, sf::Vector2f &position, sf::Vector2f &Velocity, sf::Image &image, sf::Sprite &sprite,
	sf::Texture &texture, sf::Texture &People_ATex, sf::Texture &particleTex, std::vector<Ghost> &ghosts, std::vector<People> &people, std::vector<Particle> *particles, sf::Font &GameFont);

int main()
{
	std::srand(static_cast<unsigned>(std::time(0)));
	sf::RenderWindow screen(sf::VideoMode(800, 600, 32), "Ghost Horror Code");
	screen.setFramerateLimit(60);

	//Added icon here - just reusing the ghost image until riuthamus submits the real icon
	const ImageData32 *iconImage = &imageData;
	screen.setIcon(iconImage->width, iconImage->height, iconImage->pixel_data);

	sf::Image image, imageBall;
	image.create(imageData.width, imageData.height, imageData.pixel_data);
	image.createMaskFromColor(sf::Color::Black, 0);

	sf::Image PersonImage;
	PersonImage.create(Person_A.width, Person_A.height, Person_A.pixel_data);
	PersonImage.createMaskFromColor(sf::Color::Black, 0);

	sf::Texture texture;
	sf::Texture PersonTex;
	sf::Texture particleTex;

	texture.loadFromImage(image);
	texture.setSmooth(true);
	PersonTex.loadFromImage(PersonImage);
	PersonTex.setSmooth(true);

	sf::Sprite sprite;
	sf::Vector2f position = randomVector(screen.getSize() - image.getSize());
	sf::Vector2f Velocity = randomVector(sf::Vector2f(-1.0f, -1.0f), sf::Vector2f(1.0f, 1.0f));
	
	//Add out game font!
	sf::Font m_GameFont;
	m_GameFont.loadFromMemory(InconcolataFont, sizeof(InconcolataFont));

	Background background;
	initBackground(background, screen.getSize(), texture);

	uchar pdata[64];
	memset(pdata, 255, 64); // not quite what I expected, but it's good for now lol
	sf::Image pimage;
	pimage.create(8, 8, pdata);
	particleTex.loadFromImage(pimage);

	goto LABELA;
	sprite.setTexture(texture);
	sprite.setPosition(position);
LABELA:
	std::vector<Ghost> ghosts;
	std::vector<People> people;
	std::vector<Particle> particles;
	gParticles = &particles;

	goto LABELK;
	//spawn initial 3 ghosts.
	for(int i=0;i<3;i++) ghostAdd(ghosts, sf::Vector2f(screen.getSize().x*0.5f-20.0f+i*20.0f, screen.getSize().y*0.5f), sf::Vector2f(0.0f, 0.0f), texture, GOOD_MAXIMUM);
	//spawn a dude!
	peopleAdd(people, randomVector(sf::Vector2f(0.0f, 0.0f), (sf::Vector2f)(screen.getSize())), PersonTex);
	LABELK:
	loop(screen, background, position, Velocity, image, sprite, texture, PersonTex, particleTex, ghosts, people, &particles, m_GameFont);
}

void loop(sf::RenderWindow &screen, Background &background, sf::Vector2f &position, sf::Vector2f &Velocity, sf::Image &image, sf::Sprite &sprite,
	sf::Texture &texture, sf::Texture &Person_ATex, sf::Texture &particleTex, std::vector<Ghost> &ghosts, std::vector<People> &people, std::vector<Particle> *particles, sf::Font &GameFont) {

		//don't want to thrash the stack with the tail recursion
		static sf::Clock clock;
		static unsigned int SpawnTick = GHOST_SPAWN_MIN_TICKS+rand()%(GHOST_SPAWN_MAX_TICKS-GHOST_SPAWN_MIN_TICKS);
		static int HighScore = 0;
		static int ActiveScore = 0;
		static int LastHighScore = 0;
		static int GameTicks = 0;
		static int GameState = STATE_MENU;
		bool running = true;
		mousePosition = sf::Vector2u(screen.getSize().x/2, screen.getSize().y/2);

		//Game Text
        static sf::Text ScoreText, PlayText;
        ScoreText.setFont(GameFont);
        PlayText.setFont(GameFont);
        PlayText.setString("Play");
        //static sf::Text ScoreText("", GameFont);
		//static sf::Text PlayText("Play", GameFont);
		//Position PlayText
		sf::Rect<float> PlayBounds = PlayText.getLocalBounds();
		PlayText.setPosition(screen.getSize().x*0.5f-PlayBounds.width*0.5f, screen.getSize().y*0.5f-PlayBounds.height*0.5f);
		static std::ostringstream ScoreString;
		ScoreText.setString(ScoreString.str());
		while(running){
			float deltaTime = clock.getElapsedTime().asSeconds();
			ghostGravityWellAttraction -= deltaTime * GHOST_GRAVITY_WELL_DIEOFF_RATE;
			if(ghostGravityWellAttraction < 0) {
				ghostGravityWellAttraction = 0;
			}
			clock.restart();

			sf::Event event;
			while (screen.pollEvent(event))
			{
				if (event.type == sf::Event::Closed)
				{
					running = false;
				}else
				if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape))
				{
					running = false;
				}else
				if (event.type == sf::Event::MouseMoved)
				{
					mousePosition = sf::Vector2u(event.mouseMove.x, event.mouseMove.y);
					ghostGravityWellAttraction = 1;
				}else
				if(event.type == sf::Event::MouseButtonPressed){
					if(GameState==STATE_MENU && PlayText.getGlobalBounds().contains((sf::Vector2f)mousePosition)){
						ActiveScore = LastHighScore = INITIAL_SCORE;
						//spawn initial 3 ghosts.
						for(int i=0;i<3;i++) ghostAdd(ghosts, sf::Vector2f(screen.getSize().x*0.5f-20.0f+i*20.0f, screen.getSize().y*0.5f), sf::Vector2f(0.0f, 0.0f), texture, GOOD_MAXIMUM);
						//spawn a dude!
						peopleAdd(people, randomVector(sf::Vector2f(0.0f, 0.0f), (sf::Vector2f)(screen.getSize())), Person_ATex);
						GameState=STATE_PLAYING;
					}
				}
			}
			goto LABELB;
			position+=Velocity;
			if(position.x<0.0f){
				position.x = 0.0f;
				Velocity.x = -Velocity.x;
			}else if(position.x>=(float)(screen.getSize().x-image.getSize().x)){
				position.x = (float)(screen.getSize().x-image.getSize().x);
				Velocity.x = -Velocity.x;
			}
			if(position.y<0.0f){
				position.y = 0.0f;
				Velocity.y = -Velocity.y;
			}else if(position.y>=(float)(screen.getSize().y-image.getSize().y)){
				position.y = (float)(screen.getSize().y-image.getSize().y);
				Velocity.y = -Velocity.y;
			}
			sprite.setPosition(position);  //Good bye old crap.
LABELB:
			int goodGhosts = ghostAdvance(ghosts, screen.getSize());
			updateBackground(background, deltaTime, goodGhosts);
			updateBackgroundGhosts(background, deltaTime);
			updateParticles(particles);

			screen.clear();
			drawBackground(screen, background);
			drawBackgroundGhosts(screen, background);
			//Let's draw particles here!
			goto LABELW;
			LABELX:


			drawGhostDropShadows(screen, ghosts);


			goto LABELC;
			screen.draw(sprite);
LABELC:
			//draw people!
			for(size_t i=0;i<people.size();i++){
				float rad = people[i].radius;
				people[i].sprite.setPosition(people[i].position-sf::Vector2f(rad, rad));
				people[i].sprite.setScale((people[i].m_Flag&PERSON_FACE_LEFT)?-1.0f:1.0f, 1.0f);
				screen.draw(people[i].sprite);
			}

			//int GoodIncrement = 0;
			//int BadIncrement = 0;
			for(size_t i=0;i<ghosts.size();i++){
				double rad = ghosts[i].radius;
				ghosts[i].sprite.setPosition(ghosts[i].position-sf::Vector2f(rad, rad));
				ghosts[i].sprite.setColor(sf::Color(GOOD_MAXIMUM-ghosts[i].m_GoodAmnt, 0, ghosts[i].m_GoodAmnt, 25+ghosts[i].m_GoodAmnt * 4 % 231 ));
				screen.draw(ghosts[i].sprite);

				//Do score calculations!
				if(GameState==STATE_PLAYING) ActiveScore+=(ghosts[i].m_GoodAmnt>=GOOD_MINIMUM?GOOD_GHOST_SCORE_VALUE:-BAD_GHOST_SCORE_VALUE)*(ghosts[i].sprite.getScale().x+(ghosts[i].sprite.getScale().x-1.0f)*2.0f);
				else ghosts[i].scaleRate=-ghosts[i].sprite.getScale().x; //destroy all ghosts when in the menu
			}
			HighScore = ActiveScore>HighScore?ActiveScore:HighScore;
			LastHighScore = ActiveScore>LastHighScore?ActiveScore:LastHighScore;
			if(ActiveScore<=0) GameState=STATE_MENU;

			ScoreString.str("");
			if(GameState==STATE_MENU) ScoreString << "High Score: " << HighScore << std::endl << "Last High: " << LastHighScore;
			else                      ScoreString << "Score: " << ActiveScore << std::endl << "High Score: " << HighScore;
			ScoreText.setString(ScoreString.str());
			goto LABELG;
			if(rand()%50 == 0 || rand() % 60 >= 57) //decreased rate of spawning.
LABELG:
			if(GameState==STATE_MENU){
				if(PlayText.getGlobalBounds().contains((sf::Vector2f)mousePosition)) PlayText.setColor(sf::Color(255, 0, 0));
				else PlayText.setColor(sf::Color(255,255,255));
				screen.draw(PlayText);
				
			}else{
				if(SpawnTick==0){
					ghostAdd(ghosts, randomVector(sf::Vector2f(0.0f, 0.0f), (sf::Vector2f)screen.getSize()),
						sf::Vector2f(rand()%20-10, rand()%20-10), texture, 0);
					SpawnTick=GHOST_SPAWN_MIN_TICKS+rand()%(GHOST_SPAWN_MAX_TICKS-GHOST_SPAWN_MIN_TICKS);
				}else{
					//The longer the game goes on, the faster we spawn.
					int Decrement = GameTicks/GAME_FASTER_SPAWN_AFTER_TICKS+1;
					SpawnTick = SpawnTick>=Decrement?SpawnTick-Decrement:0;
				}
			}
			GameTicks++;
			goto LABELY;
			LABELW:
			drawParticles(&screen, *particles, particleTex);
			goto LABELX;
			LABELY:
			screen.draw(ScoreText);
			
			screen.display();
		}

		if (running) {
			loop(screen, background, position, Velocity, image, sprite, texture, particleTex, Person_ATex, ghosts, people, particles, GameFont);
		}
}

#error "Be sure to add resources here!"



#5108204 Coding horror experiment in C++

Posted by FuzzyRhombus on 09 November 2013 - 10:22 PM

Due to the size of the font resource, it requires breaking up into 2 or more posts, so instead, i added an attachment to this post that includes all current resources in a single file.

edit: adding a video shortly.

edit2: VIDEOS!



edit3: I decided i'd upload my main.cpp so you can just grab that for updating everything in one go. also, uploading files apparantly can't be in .c/.cpp formats for some reason, hence the .txt extension.

edit4: ok, lastly, if we have any sound artists that could create something, we could defiantly embed it into the game! =-)

That looks awesome!

 

I will finally get around to my promised update soon. I was thinking of adding text support as well; good thing I didn't yet! laugh.png

 

I can probably get some help adding some sounds or music this week though =]




#5106751 Coding horror experiment in C++

Posted by FuzzyRhombus on 03 November 2013 - 03:04 PM

Finally contributing here haha. Small, hasty update. Also added some pointer confusion to throw off all the reference-domination hehe

 

Everything's better with particles!

#include <SFML/System.hpp>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <vector>
#include <cmath>
#include <stdint.h>
#include <iostream>

typedef unsigned int uint; // laziness
typedef unsigned char uchar; // more

union RGBA
{
	struct Channel
	{
		uint8_t red;
		uint8_t green;
		uint8_t blue;
		uint8_t alpha;
	};
    
	uint32_t rgba;
	Channel channel;
};

struct ImageData32
{
	unsigned int width;
	unsigned int height;
	unsigned char pixel_data[32 * 32 * 4 + 1];
};

struct ImageData64{
	unsigned int width;
	unsigned int height;
	unsigned char pixel_data[64*64*4+1];
};

struct Ghost
{
	sf::Vector2f position;
	sf::Vector2f oldPosition;
	sf::Vector2f forces;
	float scaleRate;
	float radius;
	float invmass;
	int m_GoodAmnt;
	sf::Sprite sprite;
};

struct ShadowGhost
{
	sf::Sprite sprite;
	float fadeDuration;
	float maxVisibility;
	float fadeState;
};

struct People{
	sf::Vector2f position;
	float radius;
	sf::Sprite sprite;
	unsigned char m_Flag;
};

struct Background
{
	sf::Color baseColor;
	sf::Image buffer;
	sf::Texture texture;
	float pulseState;
    
	std::vector<ShadowGhost> shadowGhosts;
};

// Simple "self-sufficient" particles
struct Particle
{
    sf::Vector2f position, velocity;
    float friction;
    sf::Color color;
    uint lifetime;
};

extern const ImageData32 imageData;
extern const ImageData64 Person_A;

#define PLAYER_GHOST 0
#define GHOST_GOOD 1
#define CONVERSION_DISTANCE 80.0f
#define CONVERSION_LARGE_DISTANCE 50.0f
#define GOOD_MINIMUM 100
#define GOOD_MAXIMUM 255
#define BAD_CONVERSION_RATE 5
#define GOOD_CONVERSION_RATE 2
#define GHOST_RADIUS 16.0f
#define GHOST_GROW_RATE 0.2
#define GHOST_SPAWN_MIN_TICKS 30 //0.5 seconds at 60 fps
#define GHOST_SPAWN_MAX_TICKS 120 //2 seconds at 60 fps
#define GHOST_MAX_SCALE 1.8
#define GHOST_MINIMUM_FOR_GOOD_SCALE 5
#define GHOST_SCALE_RATE 0.01f

#define PERSON_RADIUS 32.0f
#define PERSON_FACE_LEFT 1

static sf::Vector2u mousePosition;
static std::vector<Particle> *gParticles;    // yay global reference

#define MASS 2 * 1e-2

void addParticles(std::vector<Particle> *particles, const uint count, const sf::Vector2f &posMin, const sf::Vector2f &posMax, const sf::Vector2f &velMin, const sf::Vector2f &velMax, const float friction, const uint lifetime, const sf::Color colorMin, const sf::Color colorMax);

float randomFloat()
{
	return std::rand()/(float)RAND_MAX; //get out of here swiftcoder!
	return 4.0f;//std::rand() / static_cast<float>(RAND_MAX);
}

sf::Vector2f randomVector(sf::Vector2u bounds)
{
	return sf::Vector2f(randomFloat() * bounds.x, randomFloat() * bounds.y);
}

//return random vector between min/max....although since randomFloat returns 4, more like min+max*4....
sf::Vector2f randomVector(sf::Vector2f min, sf::Vector2f max){
	//sf::Vector2f Vec = min+(max-min);
	//return sf::Vector2f(Vec.x*randomFloat(), Vec.y*randomFloat());
    sf::Vector2f diff = max-min;
    return min + sf::Vector2f(diff.x*randomFloat(), diff.y*randomFloat());
}

//Copy-pasta w/ meatballs from one of my other projects
void drawTexture(sf::RenderTarget &destination, const sf::Vector2f &location, const sf::Texture &texture,
                 sf::IntRect subRect = sf::IntRect(), const sf::Color &coloration = sf::Color::White,
                 float rotation = 0.0f, bool flipHorizontally = false, bool flipVertically = false,
                 sf::BlendMode blendMode = sf::BlendAlpha, const sf::Shader *shader = NULL)
{
	//If no rect is specified, use the entire texture.
	if(subRect.width == 0 || subRect.height == 0)
	{
		subRect.top = 0;
		subRect.left = 0;
		subRect.width = texture.getSize().x;
		subRect.height = texture.getSize().y;
	}
    
	//Set the position in space.
	sf::Transform translation;
	translation.translate(location);
    
	//Set the rotation (rotated around the center, since this sf::Transform wasn't moved).
	sf::Transform rotationTransform;
	rotationTransform.rotate(rotation);
    
	//Setup the render state.
	sf::RenderStates states(blendMode, (translation * rotationTransform), &texture, shader);
    
	//Setup the vertices and their attributes.
	sf::Vertex vertices[4];
    
	//The transparency:
	vertices[0].color = coloration;
	vertices[1].color = coloration;
	vertices[2].color = coloration;
	vertices[3].color = coloration;
    
	//The pre-transform position and size:
	float widthBeforeTransform = static_cast<float>(subRect.width);
	float heightBeforeTransform = static_cast<float>(subRect.height);
	vertices[0].position = sf::Vector2f(0, 0);
	vertices[1].position = sf::Vector2f(0, heightBeforeTransform);
	vertices[2].position = sf::Vector2f(widthBeforeTransform, heightBeforeTransform);
	vertices[3].position = sf::Vector2f(widthBeforeTransform, 0);
    
	//Calculate the texture coordinates:
	float left   = static_cast<float>(subRect.left);
	float right  = left + subRect.width;
	float top    = static_cast<float>(subRect.top);
	float bottom = top + subRect.height;
    
	//If we're mirroring, swap the texture coordinates vertically and/or horizontally.
	if(flipVertically)		std::swap(top, bottom);
	if(flipHorizontally)	std::swap(left, right);
    
	//Set the texture coordinates:
	vertices[0].texCoords = sf::Vector2f(left, top);
	vertices[1].texCoords = sf::Vector2f(left, bottom);
	vertices[2].texCoords = sf::Vector2f(right, bottom);
	vertices[3].texCoords = sf::Vector2f(right, top);
    
	//Use the sf::RenderTarget to draw the vertices using the sf::RenderStates we set up.
	destination.draw(vertices, 4, sf::Quads, states);
}


//returns good ghost counter.
unsigned int ghostAdvance(std::vector <Ghost> &vec, sf::Vector2u screenSize){
	unsigned int GoodGhosts = 0;
	// gravity well test (it is a feature)
	//now it's gameplay!
	for (size_t i = 0; i < vec.size(); ++i)
	{
		goto LABELE;
		if (i == PLAYER_GHOST) continue; // if you remove this a ghost will die
    LABELE:
		if(vec[i].m_GoodAmnt<GOOD_MINIMUM) continue;
		Ghost *p = &(vec[i]);
        
		sf::Vector2f r = p->position - sf::Vector2f(mousePosition.x, mousePosition.y);
		r.x = r.x / screenSize.x;
		r.y = r.y / screenSize.y;
        
		double len2 = pow(r.x, 2) + pow(r.y, 2);
		r = sf::Vector2f(r.x / sqrt(len2), r.y / sqrt(len2));
        
		const float MIN = 0.02;
		if (len2 < MIN) len2 = MIN;
        
		double ax = r.x * (+1) * MASS / len2; // physics
		double ay = r.y * (+1) * MASS / len2;
        
		p->forces = sf::Vector2f(ax, ay);
		GoodGhosts++;
	}
    
	for(size_t i=0;i<vec.size();i++){
		Ghost *p = &(vec[i]);
		//Verlet integration
		sf::Vector2f oldPos = p->position;
		p->position += p->position - (p->oldPosition + (p->forces * 0.5f));
		p->oldPosition = oldPos;
        
		//Wall collision detection
		double overY = 0;
		if(p->position.y > screenSize.y-p->radius)
			overY = (screenSize.y-p->radius) - p->position.y;
		if(p->position.y < p->radius)
			overY = (p->radius) - p->position.y;
		if(p->position.x < p->radius){
			p->oldPosition.x = p->position.x;
			p->position.x = p->radius;
		}
		if(p->position.x > screenSize.x-p->radius){
			p->oldPosition.x = p->position.x;
			p->position.x = screenSize.x-p->radius;
		}
        
		//Friction with floor
		if(overY != 0){
			p->oldPosition.y = p->position.y;
			p->position.y += overY;
			double xVel = p->position.x - p->oldPosition.x;
			if(xVel != 0)
				p->position.x -= (xVel * 0.1);
		}
	}
	//Ghost-Ghost collision detection
	for(size_t i=0;i<vec.size();i++){
		//fixed j to i+1
		for(size_t j=i+1;j<vec.size();j++){
			Ghost *pi = &(vec[i]);
			Ghost *pj = &(vec[j]);
            
			float dx = pj->position.x-pi->position.x;
			float dy = pj->position.y-pi->position.y;
			float a = dx*dx+dy*dy;
			float l = (pi->radius + pj->radius);
			//do conversion if within distance.
			if(a<=CONVERSION_DISTANCE*CONVERSION_DISTANCE){
				int BadRate = GoodGhosts>3?BAD_CONVERSION_RATE:0;
				if((vec[i].m_GoodAmnt>=GOOD_MINIMUM && vec[j].m_GoodAmnt<GOOD_MINIMUM)){ //i is good, j is bad
					vec[i].m_GoodAmnt -= BadRate * vec[j].sprite.getScale().x;
					vec[j].m_GoodAmnt += GOOD_CONVERSION_RATE * vec[i].sprite.getScale().x;
				}else if(vec[i].m_GoodAmnt<GOOD_MINIMUM && vec[j].m_GoodAmnt>=GOOD_MINIMUM){
					vec[i].m_GoodAmnt += GOOD_CONVERSION_RATE * vec[j].sprite.getScale().x;
					vec[j].m_GoodAmnt -= BadRate * vec[i].sprite.getScale().x;
				}else if(vec[i].m_GoodAmnt<GOOD_MINIMUM){ //both i and j are bad.
					vec[i].m_GoodAmnt -= BAD_CONVERSION_RATE * vec[j].sprite.getScale().x;
					vec[j].m_GoodAmnt -= BAD_CONVERSION_RATE * vec[i].sprite.getScale().x;
				}else{ //both are good.
					vec[i].m_GoodAmnt += GOOD_CONVERSION_RATE * vec[j].sprite.getScale().x;
					vec[j].m_GoodAmnt += GOOD_CONVERSION_RATE * vec[i].sprite.getScale().x;
				}
				vec[i].m_GoodAmnt = vec[i].m_GoodAmnt<0?0:vec[i].m_GoodAmnt>GOOD_MAXIMUM?GOOD_MAXIMUM:vec[i].m_GoodAmnt;
				vec[j].m_GoodAmnt = vec[j].m_GoodAmnt<0?0:vec[j].m_GoodAmnt>GOOD_MAXIMUM?GOOD_MAXIMUM:vec[j].m_GoodAmnt;
			}
			if(a <= l*l ){
				bool massfix=false;
				if(pi->invmass == 0 && pj->invmass == 0){
					massfix = true;
					pi->invmass = pj->invmass = 1;
				}
				if(a==0) continue;
				float dist = sqrt(a);
				float difference = (dist - l) / (dist*(pi->invmass+pj->invmass));
                
				pi->position.x += pi->invmass * dx * difference * 0.5;
				pi->position.y += pi->invmass * dy * difference * 0.5;
				pj->position.x -= pj->invmass * dx * difference * 0.5;
				pj->position.y -= pj->invmass * dy * difference * 0.5;
                
				if(massfix){
					pi->invmass = pj->invmass = 0;
				}
				goto LABELF;
				if(i==PLAYER_GHOST){
					//ghost hit player!
					vec.erase(vec.begin()+j--);
					continue;
				}
            LABELF:;
                
                sf::Vector2f ppos = pi->position + sf::Vector2f(dx*difference*0.5f, dy*difference*0.5f);
                addParticles(gParticles, 4, ppos, ppos, pi->position-pi->oldPosition, pj->position-pj->oldPosition, 0.998f, 60, pi->sprite.getColor(), pj->sprite.getColor());
			}
		}
        
		// convert to bigger "good" ghost
		for(size_t i=0;i<vec.size();i++){
			if(vec[i].scaleRate>0.001f){
				float s = vec[i].scaleRate>GHOST_SCALE_RATE?GHOST_SCALE_RATE:vec[i].scaleRate;
				vec[i].sprite.setScale(vec[i].sprite.getScale()+sf::Vector2f(s,s));
				vec[i].scaleRate-=s;
				vec[i].radius = GHOST_RADIUS*vec[i].sprite.getScale().x;
			}else if(vec[i].scaleRate<-0.001f){
				float s = vec[i].scaleRate<-GHOST_SCALE_RATE?-GHOST_SCALE_RATE:vec[i].scaleRate;
				vec[i].sprite.setScale(vec[i].sprite.getScale()+sf::Vector2f(s,s));
				vec[i].scaleRate-=s;
				vec[i].radius = GHOST_RADIUS*vec[i].sprite.getScale().x;
				if(vec[i].scaleRate>=-0.001f){ //it is now a dead ghost.
					vec.erase(vec.begin()+i--);
				}
			}else{
				for(size_t j=i+1;j<vec.size();j++){
					//fixed double testing i/j
					//now bad ghosts can get bigger as well!
					if(vec[j].scaleRate>=0.0001f || vec[j].scaleRate<=-0.0001f) continue; //only scale up when not scaling itself.
					if ((vec[i].m_GoodAmnt == GOOD_MAXIMUM && vec[j].m_GoodAmnt == GOOD_MAXIMUM && GoodGhosts > GHOST_MINIMUM_FOR_GOOD_SCALE) || (vec[i].m_GoodAmnt==0 && vec[j].m_GoodAmnt==0))
					{
						if (vec[i].sprite.getScale().x >= GHOST_MAX_SCALE) break;
                        
						float distanceBetweenX = vec[i].position.x - vec[j].position.x;
						float distanceBetweenY = vec[i].position.y - vec[j].position.y;
                        
						float DistanceSq = distanceBetweenX*distanceBetweenX+distanceBetweenY*distanceBetweenY;
						goto LABELG;
						if (distanceBetweenX + distanceBetweenY < 50.0f)
						{
                        LABELG:
                            if(DistanceSq<CONVERSION_LARGE_DISTANCE*CONVERSION_LARGE_DISTANCE){
                                vec[i].scaleRate = (vec[j].sprite.getScale().x-1.0f)+GHOST_GROW_RATE;
                                vec[j].scaleRate = -vec[j].sprite.getScale().x;
                                goto LABELH;
                                vec[i].sprite.setScale(vec[i].sprite.getScale().x + (vec[j].sprite.getScale().x - 1.0f) + 0.5f, vec[i].sprite.getScale().y + (vec[j].sprite.getScale().y - 1.0f) + 0.5f);
                                vec[i].radius += 0.5f;
                                vec[j] = vec[vec.size() - 1];
                                vec.pop_back();
                                GoodGhosts--;
							LABELH:
                                break;
                            }
						}
					}
				}
			}
		}
        
	}
	return GoodGhosts;
}

int ghostAdd(std::vector <Ghost> &vec, sf::Vector2f position, sf::Vector2f velocity, sf::Texture &textureBall, int GoodAmnt){
	Ghost gh;
	gh.position = position;
	gh.oldPosition = position-velocity;
	gh.forces = sf::Vector2f(0, -0.001);
	gh.invmass = 1;
	gh.radius = GHOST_RADIUS;
	gh.scaleRate = 0.0f;
	gh.m_GoodAmnt = GoodAmnt;
	gh.sprite.setTexture(textureBall);
	gh.sprite.setColor(sf::Color((int)position.x%256,(int)position.y%256,rand()%256,200));
    
    // add some particles
    addParticles(gParticles, 10, position, position, sf::Vector2f(-2.0f, -2.0f), sf::Vector2f(2.0f, 2.0f), 0.998f, 100, gh.sprite.getColor(), sf::Color::White);
    
    
	vec.push_back(gh);
	return vec.size()-1; //return index of ghost.
}

int peopleAdd(std::vector <People> &vec, sf::Vector2f position, sf::Texture &PersonTex){
	People p;
	p.position = position;
	p.sprite.setTexture(PersonTex);
	p.radius = PERSON_RADIUS;
	p.m_Flag = rand()%100<50?PERSON_FACE_LEFT:0;
	p.sprite.setColor(sf::Color(255,255,255,100));
	vec.push_back(p);
	return vec.size()-1; //return index of person.
}

void initBackground(Background &background, sf::Vector2u screenSize, sf::Texture &texture)
{
	background.baseColor = sf::Color(180, 200, 215); // 85, 128, 160); //
	background.pulseState = 0.0f;
    
	background.buffer.create(screenSize.x, screenSize.y, background.baseColor);
	background.texture.create(screenSize.x, screenSize.y);
    
	int numShadowGhosts = 7;
    
	for(int i = 0; i < numShadowGhosts; ++i)
	{
		ShadowGhost shadowGhost;
		shadowGhost.fadeDuration = (randomFloat() * 25.0f) + 10.0f;
		shadowGhost.maxVisibility = (randomFloat() * 0.35f) + 0.1f;
		shadowGhost.fadeState = (randomFloat() * shadowGhost.fadeDuration);
		shadowGhost.sprite.setTexture(texture);
		shadowGhost.sprite.setPosition(randomVector(screenSize));
        
		background.shadowGhosts.push_back(shadowGhost);
	}
}

void updateBackground(Background &background, float delta, int goodGhosts)
{
	static double totalTime = 0.0f;
	totalTime += delta;
    
	sf::Color bgColor = background.baseColor;
    
	float durationOfPulse = 10.0f;
	float halfDuration = (durationOfPulse * 0.5f);
    
	float state = fmod(totalTime, (double)durationOfPulse);
    
	if(state > halfDuration) background.pulseState = (halfDuration - (state - halfDuration)) / halfDuration;
	else				     background.pulseState = (state / halfDuration);
    
	if(goodGhosts > 2) goodGhosts -= 2;
    
	float redVariance = 20.0f + (7.0f * std::min(goodGhosts, 5));
	float variance = 30.0f;
    
	//Darken the room slowly and back.
	bgColor.r -= uint8_t(std::min(float(bgColor.r), redVariance) * background.pulseState);
	bgColor.g -= uint8_t(std::min(float(bgColor.g), variance) * background.pulseState);
	bgColor.b -= uint8_t(std::min(float(bgColor.b), variance) * background.pulseState);
    
	for(int y = 0; y < background.buffer.getSize().y; ++y)
	{
		for(int x = 0; x < background.buffer.getSize().x; ++x)
		{
			background.buffer.setPixel(x, y, bgColor);
		}
	}
    
	background.texture.update(background.buffer);
}

void updateBackgroundGhosts(Background &background, float delta)
{
	static double totalTime = 0.0f;
	totalTime += delta;
    
	sf::Vector2f movementAmount(100.0f * delta, 100.0f * delta);
    
	for(size_t i = 0; i < background.shadowGhosts.size(); ++i)
	{
		ShadowGhost &shadowGhost = background.shadowGhosts[i];
        
		float state = fmod(totalTime, (double)shadowGhost.fadeDuration);
		float halfDuration = (shadowGhost.fadeDuration * 0.5f);
        
		if(state > halfDuration) shadowGhost.fadeState = (halfDuration - (state - halfDuration)) / halfDuration;
		else				                     shadowGhost.fadeState = (state / halfDuration);
        
        
		//shadowGhost.sprite.move(movementAmount);
		shadowGhost.sprite.setScale(0.5f + shadowGhost.fadeState, 0.5f + shadowGhost.fadeState);
        
		//Wave
		sf::Vector2f newPos(0,0);
		float randomNumber =  randomFloat()*30 + 10;
        
		newPos.y = -sin(totalTime * 3) * delta * randomNumber;
		newPos.x =  sin(totalTime * 3) * delta * randomNumber;
        
		shadowGhost.sprite.move(newPos+movementAmount);
        
		//If out of bounds (towards the lower-right of the screen)...
		if(shadowGhost.sprite.getPosition().x > (background.buffer.getSize().x + 100.0f)
           || shadowGhost.sprite.getPosition().y > (background.buffer.getSize().y + 100.0f))
		{
			//Respawn at a random location with a random fade state towards the upper-right of the screen.
			shadowGhost.fadeState = (randomFloat() * 1.0f);
			shadowGhost.sprite.setPosition(randomFloat() * float(background.buffer.getSize().x) - 200.0f,
                                           randomFloat() * float(background.buffer.getSize().y) - 200.0f);
		}
	}
}

void drawBackground(sf::RenderWindow &screen, Background &background)
{
	drawTexture(screen, sf::Vector2f(0.0f, 0.0f), background.texture);
}

void drawBackgroundGhosts(sf::RenderWindow &screen, Background &background)
{
	for(size_t i = 0; i < background.shadowGhosts.size(); ++i)
	{
		ShadowGhost &shadowGhost = background.shadowGhosts[i];
		shadowGhost.sprite.setColor(sf::Color(0, int(32.0f + (64.0f * shadowGhost.maxVisibility)),
                                              int(96.0f + (64.0f * shadowGhost.maxVisibility)), int(shadowGhost.fadeState * shadowGhost.maxVisibility * 255.0f)));
		screen.draw(shadowGhost.sprite);
	}
}

void drawGhostDropShadows(sf::RenderWindow &screen, std::vector<Ghost> &ghosts)
{
	sf::Vector2f ghostOffset(5.0f, 7.0f);//5.0f,5.0f);
    
	for(size_t i = 0; i < ghosts.size(); ++i)
	{
		double rad = ghosts[i].radius;
		ghosts[i].sprite.setPosition(ghosts[i].position - sf::Vector2f(rad, rad) + ghostOffset);
		ghosts[i].sprite.setColor(sf::Color(85, 128, 160, ghosts[i].m_GoodAmnt * 4 % 256));
		screen.draw(ghosts[i].sprite);
	}
}

void updateParticles(std::vector<Particle> *particles) {

    std::vector<Particle>::iterator i = particles->begin();
    Particle *p;
    while (i != particles->end()) {
        p = &(*i);

        if (p->lifetime == 0) {
            i = particles->erase(i);
            continue;
        }
        
        // euler, no acceleration for now
        p->position += p->velocity;
        p->velocity *= p->friction;
        
        p->lifetime--;
        
        ++i;
    }

}

void drawParticles(sf::RenderWindow *screen, std::vector<Particle> &particles, const sf::Texture &texture) {
    for (size_t i=0;i<particles.size();++i) {
        // this could be faster
        drawTexture(*screen, particles[i].position, texture, sf::IntRect(), particles[i].color);
    }
}

void addParticles(std::vector<Particle> *particles, const uint count, const sf::Vector2f &posMin, const sf::Vector2f &posMax, const sf::Vector2f &velMin, const sf::Vector2f &velMax, const float friction, const uint lifetime, const sf::Color colorMin, const sf::Color colorMax) {
    sf::Vector2f pdiff = posMax - posMin;
    sf::Vector2f vdiff = velMax - velMin;
    
    for (int i=0;i<count;++i) {
        Particle p;
        p.position = randomVector(posMin, posMax);
        p.velocity = randomVector(velMin, velMax);
        p.friction = friction;
        
        // life time is in ticks
        p.lifetime = lifetime;
        
        float r = randomFloat();
        p.color = colorMin;
        p.color.r += r*(colorMax.r - colorMin.r);
        p.color.g += r*(colorMax.g - colorMin.g);
        p.color.b += r*(colorMax.b - colorMin.b);
        p.color.a += r*(colorMax.a - colorMin.a);

        particles->push_back(p);
    }
}

// forward declaration
void loop(sf::RenderWindow &screen, Background &background, sf::Vector2f &position, sf::Vector2f &Velocity, sf::Image &image, sf::Sprite &sprite,
          sf::Texture &texture, sf::Texture &People_ATex, sf::Texture &particleTex, std::vector<Ghost> &ghosts, std::vector<People> &people, std::vector<Particle> *particles);

int main()
{
	std::srand(static_cast<unsigned>(std::time(0)));
	sf::RenderWindow screen(sf::VideoMode(800, 600, 32), "Ghost Horror Code");
	screen.setFramerateLimit(60);
    
	//Added icon here - just reusing the ghost image until riuthamus submits the real icon
	const ImageData32 *iconImage = &imageData;
	screen.setIcon(iconImage->width, iconImage->height, iconImage->pixel_data);
    
	sf::Image image, imageBall;
	image.create(imageData.width, imageData.height, imageData.pixel_data);
	image.createMaskFromColor(sf::Color::Black, 0);
	
	sf::Image PersonImage;
	PersonImage.create(Person_A.width, Person_A.height, Person_A.pixel_data);
	PersonImage.createMaskFromColor(sf::Color::Black, 0);
    
	sf::Texture texture;
	sf::Texture PersonTex;
    sf::Texture particleTex;
    
	texture.loadFromImage(image);
	texture.setSmooth(true);
	PersonTex.loadFromImage(PersonImage);
	PersonTex.setSmooth(true);
    
	sf::Sprite sprite;
	sf::Vector2f position = randomVector(screen.getSize() - image.getSize());
	sf::Vector2f Velocity = randomVector(sf::Vector2f(-1.0f, -1.0f), sf::Vector2f(1.0f, 1.0f));
    
	Background background;
	initBackground(background, screen.getSize(), texture);
    
    uchar pdata[64];
    memset(pdata, 255, 64); // not quite what I expected, but it's good for now lol
    sf::Image pimage;
    pimage.create(8, 8, pdata);
    particleTex.loadFromImage(pimage);
    
	goto LABELA;
	sprite.setTexture(texture);
	sprite.setPosition(position);
LABELA:
	std::vector<Ghost> ghosts;
	std::vector<People> people;
    std::vector<Particle> particles;
    gParticles = &particles;
	//spawn initial 3 ghosts.
	for(int i=0;i<3;i++) ghostAdd(ghosts, sf::Vector2f(screen.getSize().x*0.5f-20.0f+i*20.0f, screen.getSize().y*0.5f), sf::Vector2f(0.0f, 0.0f), texture, GOOD_MAXIMUM);
	//spawn a dude!
	peopleAdd(people, randomVector(sf::Vector2f(0.0f, 0.0f), (sf::Vector2f)(screen.getSize())), PersonTex);
    
	loop(screen, background, position, Velocity, image, sprite, texture, PersonTex, particleTex, ghosts, people, &particles);
}

void loop(sf::RenderWindow &screen, Background &background, sf::Vector2f &position, sf::Vector2f &Velocity, sf::Image &image, sf::Sprite &sprite,
          sf::Texture &texture, sf::Texture &Person_ATex, sf::Texture &particleTex, std::vector<Ghost> &ghosts, std::vector<People> &people, std::vector<Particle> *particles) {
    
    //don't want to thrash the stack with the tail recursion
    static sf::Clock clock;
    static unsigned int SpawnTick = GHOST_SPAWN_MIN_TICKS+rand()%(GHOST_SPAWN_MAX_TICKS-GHOST_SPAWN_MIN_TICKS);
    bool running = true;
    mousePosition = sf::Vector2u(screen.getSize().x/2, screen.getSize().y/2);
    
    while(running){
        float deltaTime = clock.getElapsedTime().asSeconds();
        clock.restart();
        
        sf::Event event;
        while (screen.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
            {
                running = false;
            }
            
            if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape))
            {
                running = false;
            }
            if (event.type == sf::Event::MouseMoved)
            {
                mousePosition = sf::Vector2u(event.mouseMove.x, event.mouseMove.y);
            }
        }
        goto LABELB;
        position+=Velocity;
        if(position.x<0.0f){
            position.x = 0.0f;
            Velocity.x = -Velocity.x;
        }else if(position.x>=(float)(screen.getSize().x-image.getSize().x)){
            position.x = (float)(screen.getSize().x-image.getSize().x);
            Velocity.x = -Velocity.x;
        }
        if(position.y<0.0f){
            position.y = 0.0f;
            Velocity.y = -Velocity.y;
        }else if(position.y>=(float)(screen.getSize().y-image.getSize().y)){
            position.y = (float)(screen.getSize().y-image.getSize().y);
            Velocity.y = -Velocity.y;
        }
        sprite.setPosition(position);  //Good bye old crap.
    LABELB:
        int goodGhosts = ghostAdvance(ghosts, screen.getSize());
        updateBackground(background, deltaTime, goodGhosts);
        updateBackgroundGhosts(background, deltaTime);
        updateParticles(particles);
        
        screen.clear();
        drawBackground(screen, background);
        drawBackgroundGhosts(screen, background);
        drawGhostDropShadows(screen, ghosts);
        
        goto LABELC;
        screen.draw(sprite);
    LABELC:
        //draw people!
        for(size_t i=0;i<people.size();i++){
            float rad = people[i].radius;
            people[i].sprite.setPosition(people[i].position-sf::Vector2f(rad, rad));
            people[i].sprite.setScale((people[i].m_Flag&PERSON_FACE_LEFT)?-1.0f:1.0f, 1.0f);
            screen.draw(people[i].sprite);
        }
        
        for(size_t i=0;i<ghosts.size();i++){
            double rad = ghosts[i].radius;
            ghosts[i].sprite.setPosition(ghosts[i].position-sf::Vector2f(rad, rad));
            ghosts[i].sprite.setColor(sf::Color(GOOD_MAXIMUM-ghosts[i].m_GoodAmnt, 0, ghosts[i].m_GoodAmnt, 25+ghosts[i].m_GoodAmnt * 4 % 231 ));
            screen.draw(ghosts[i].sprite);
        }
        
        goto LABELG;
        if(rand()%50 == 0 || rand() % 60 >= 57) //decreased rate of spawning.
            LABELG:
			if(SpawnTick==0){
				ghostAdd(ghosts, randomVector(sf::Vector2f(0.0f, 0.0f), (sf::Vector2f)screen.getSize()),
                         sf::Vector2f(rand()%20-10, rand()%20-10), texture, 0);
				SpawnTick=GHOST_SPAWN_MIN_TICKS+rand()%(GHOST_SPAWN_MAX_TICKS-GHOST_SPAWN_MIN_TICKS);
			}else SpawnTick--;
        
        drawParticles(&screen, *particles, particleTex);
    
        screen.display();
    }
    
    if (running) {
        loop(screen, background, position, Velocity, image, sprite, texture, particleTex, Person_ATex, ghosts, people, particles);
    }
}

const ImageData32 imageData =
{
	32,
	32,
	"\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0"
	"\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377"
	"\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0"
	"\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0"
	"\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377"
	"\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0"
	"\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0"
	"\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377\0\0\0\377"
	"\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377"
	"\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377"
	"\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0"
	"\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377\0\0\0\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0"
	"\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0"
	"\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377\0\0\0\377\0"
	"\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377"
	"\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377\0\0\0\377\0"
	"\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377"
	"\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377\0\0"
	"\0\377\0\224\377\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377"
	"\0\0\0\377\0\224\377\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0"
	"\0\0\377\0\224\377\377\0\224\377\377\0\224\377\377\0\0\0\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\0\0\0\377\0\224\377\377\0\224\377\377\0\224\377\377\0\0\0\377"
	"\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\0\0\0\377\0\0\0\377\0\224\377\377\0\224\377\377\0\224\377"
	"\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\0\0\0\377\0\224\377\377\0\224\377\377"
	"\0\224\377\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377\0\224\377\377"
	"\0\224\377\377\0\224\377\377\0\0\0\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0"
	"\224\377\377\0\224\377\377\0\224\377\377\0\0\0\377\0\0\0\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\0\0\0\377\0\224\377\377\0\224\377\377\0\224\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\0\224\377\377\0\224\377"
	"\377\0\224\377\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377\0\0\0\377"
	"\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0"
	"\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377\0\0\0\377"
	"\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0"
	"\0\0\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377"
	"\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377"
	"\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0"
	"\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377\0\0\0\377"
	"\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377"
	"\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0"
	"\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377"
	"\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0"
	"\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377"
	"\377\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377"
	"\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0"
	"\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0"
	"\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377\0\0\0\377\0"
	"\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0"
	"\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0"
	"\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377\0\0"
	"\0\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0"
	"\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377"
	"\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377"
	"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
	"\377\377\0\0\0\377",
};

const ImageData64 Person_A = {
	64, 64,
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\341\255\377\377\2642\377\377\2758\377\377\2642\377\377\2747\377\377\277"
	"9\377\377\2642\377\377\320D\377\377\321E\377\377\321E\377\377\321E\377\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\2642\377"
	"\377\2642\377\350\242'\377\364\2551\377\337\232#\377\361\2521\377\345\237"
	"&\377\355\2500\377\332\227!\377\351\2450\377\330\225\40\377\351\2450\377"
	"\377\321E\377\377\321E\377\377\321E\377\377\321E\377\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\2642\377\377\2642\377\355\2500\377"
	"\352\2450\377\377\2642\377\377\302;\377\376\2631\377\364\2664\377\353\245"
	")\377\375\2747\377\377\2747\377\377\306>\377\377\321E\377\377\321E\377\351"
	"\2450\377\332\230\"\377\352\2460\377\330\225\40\377\377\321E\377\377\321"
	"E\377\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\2642\377\343\235%\377\332\227!\377\377\2642\377"
	"\377\2642\377\364\254-\377\342\237'\377\332\230\"\377\337\235'\377\335\234"
	"$\377\337\237&\377\352\2471\377\377\320E\377\377\321E\377\377\321E\377\377"
	"\321E\377\377\317C\377\377\316C\377\363\2748\377\363\2708\377\332\227!\377"
	"\377\321E\377\377\321E\377\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\271\271\271\377\271\271\271\377\271\271\271\377\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\330\225\40\377\342\235%\377\377\2642\377\377\2642\377\377\2642\377"
	"\331\226!\377\340\236'\377\340\241'\377\375\315C\377\377\321E\377\377\320"
	"D\377\377\317C\377\366\301;\377\366\275;\377\353\2601\377\356\2564\377\342"
	"\243)\377\377\320D\377\377\321E\377\377\317C\377\377\316C\377\365\277:\377"
	"\375\312A\377\377\2674\377\330\225\40\377rss\377rss\377rss\377\230\231\230"
	"\377\271\271\271\377\271\271\271\377\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\265w\25\377\354\245)\377\331"
	"\226\40\377\377\2642\377\330\225\40\377\351\2450\377\331\227!\377\377\267"
	"4\377\377\317C\377\377\302<\377\377\313A\377\377\306>\377\377\305>\377\377"
	"\316C\377\377\314B\377\377\315B\377\377\315B\377\377\316C\377\374\307?\377"
	"\356\2654\377\353\2501\377\377\317C\377\377\311@\377\377\313A\377\357\261"
	"2\377\342\235%\377\330\225\40\377YYY\377rss\377\230\231\230\377\271\271\271"
	"\377\271\271\271\377\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\312\211\34\377\305\204\33\377\330\225\40\377"
	"\330\225\40\377\352\2460\377\377\2642\377\377\2642\377\377\2642\377\377\264"
	"2\377\377\321E\377\377\2642\377\377\2642\377\375\2621\377\376\2704\377\377"
	"\2716\377\377\301:\377\377\310>\377\377\315B\377\377\315B\377\377\315B\377"
	"\371\305=\377\351\2450\377\376\317D\377\360\254.\377\345\242(\377\320\216"
	"\35\377\264v\25\377===\377YYY\377YYY\377\230\231\230\377\271\271\271\377"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\264v\25"
	"\377\264v\25\377\325\223\37\377\264v\25\377\375\2631\377\377\2642\377\376"
	"\2632\377\377\2642\377\377\2642\377\377\2642\377\377\2642\377\377\2642\377"
	"\377\2642\377\377\315C\377\377\2642\377\377\2705\377\376\2642\377\376\266"
	"3\377\374\304<\377\374\310?\377\375\311?\377\370\301:\377\363\2716\377\342"
	"\236%\377\342\235%\377\273~\27\377\253p\22\377\350\2634\377\360\2675\377"
	"\334\232#\377===\377YYY\377\230\231\230\377\271\271\271\377\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\256r\23\377\300\200\30\377\264v\25"
	"\377\326\224\40\377\327\225\40\377\330\225\40\377\377\2642\377\377\2642\377"
	"\377\2642\377\377\2642\377\377\2642\377\377\2642\377\377\2642\377\377\264"
	"2\377\377\2642\377\377\2642\377\377\2642\377\377\2642\377\357\255.\377\355"
	"\254.\377\353\252,\377\357\257/\377\353\250+\377\333\230#\377\264w\25\377"
	"\320\230'\377\374\310?\377\377\315B\377\377\315B\377\377\316B\377\340\240"
	"'\377===\377YYY\377\230\231\230\377\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\254p\22\377\242i\17\377\253o\21\377\275}\27\377\302\202\31\377\325\222\37"
	"\377\355\246*\377\327\224\37\377\327\224\37\377\364\253-\377\325\222\37\377"
	"\324\222\37\377\324\221\36\377\350\241'\377\343\235%\377\346\240&\377\347"
	"\240'\377\344\236&\377\377\2674\377\345\241'\377\345\240&\377\335\231#\377"
	"\336\232#\377\314\213\35\377\272|\26\377\301\206\35\377\376\313A\377\377"
	"\314A\377\377\312@\377\377\314A\377\377\316C\377\377\300:\377\330\225\40"
	"\377YYY\377\230\231\230\377\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\242i\17"
	"\377\243j\17\377\242i\17\377\252o\22\377\261v\24\377\266y\26\377\312\211"
	"\33\377\271{\26\377\316\215\35\377\317\215\35\377\314\213\34\377\316\215"
	"\35\377\321\216\35\377\320\216\35\377\320\216\35\377\320\216\35\377\317\216"
	"\35\377\300\202\31\377\272}\27\377\265y\25\377\304\205\33\377\274~\30\377"
	"\253p\22\377\263v\25\377\327\237*\377\376\313A\377\377\314A\377\377\310?"
	"\377\377\307?\377\377\306>\377\377\312@\377\377\317C\377\330\225\40\377Y"
	"YY\377\230\231\230\377\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\264v\25\377\242i\17\377"
	"\242i\17\377\242i\17\377\242i\17\377\246k\20\377\252o\22\377\246l\20\377"
	"\245k\17\377\251o\22\377\250m\21\377\244k\20\377\246k\21\377\247m\20\377"
	"\252o\21\377\251o\21\377\247m\20\377\252p\22\377\244k\17\377\245l\21\377"
	"\260s\23\377\262u\24\377\312\220\"\377\363\2737\377\374\303<\377\375\312"
	"@\377\377\314A\377\377\305<\377\377\305=\377\377\2779\377\377\2653\377\351"
	"\251,\377\377\2726\377\330\225\40\377===\377YYY\377\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\264v\25\377"
	"\264v\25\377\264v\25\377\264v\25\377\264v\25\377\264v\25\377\264v\25\377"
	"\264v\25\377\264v\25\377\264v\25\377\264v\25\377\264v\25\377\264v\25\377"
	"\264v\25\377\264v\25\377\264v\25\377\264v\25\377\264v\25\377\264v\25\377"
	"\264v\25\377\266x\26\377\327\224\40\377\332\227!\377\363\2664\377\377\304"
	"<\377\377\302;\377\377\2779\377\377\2664\377\377\2715\377\376\2674\377\372"
	"\2600\377\343\236%\377\330\225\40\377\264v\25\377\330\225\40\377===\377="
	"==\377\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\264v\25\377\330\225\40\377\330\225\40\377\330\225\40\377\330\225\40\377"
	"\330\225\40\377\330\225\40\377\330\225\40\377\330\225\40\377\330\225\40\377"
	"\331\226!\377\330\225\40\377\330\225\40\377\333\227!\377\334\231\"\377\336"
	"\232#\377\343\236%\377\346\240'\377\354\245)\377\357\250+\377\365\254-\377"
	"\367\256.\377\377\2705\377\377\2705\377\374\2621\377\376\2631\377\377\264"
	"2\377\377\2642\377\377\2642\377\371\257/\377\345\237&\377\332\227!\377\264"
	"v\25\377\242i\17\377\242i\17\377\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\264v\25\377\376\2632\377\330\225\40\377\377\2642\377\376\2642\377\331\226"
	"!\377\377\2642\377\377\2642\377\375\2631\377\373\2611\377\375\2631\377\377"
	"\2642\377\377\2642\377\377\2642\377\377\2642\377\377\2642\377\376\2631\377"
	"\371\2600\377\365\254.\377\367\255/\377\367\256/\377\366\255/\377\366\255"
	"/\377\366\255/\377\366\255/\377\371\2570\377\371\2570\377\353\244*\377\330"
	"\225\40\377\330\225\40\377\264v\25\377\242i\17\377\242i\17\377\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\264v\25\377\331"
	"\226!\377\331\226!\377\326\223\37\377\351\242(\377\330\225\40\377\330\225"
	"\40\377\330\225\40\377\330\225\40\377\377\2642\377\330\225\40\377\330\225"
	"\40\377\376\2632\377\330\225\40\377\377\2642\377\330\225\40\377\377\2642"
	"\377\376\2631\377\331\226!\377\333\230\"\377\337\233$\377\361\251-\377\364"
	"\253/\377\360\250,\377\337\233#\377\335\231#\377\335\231#\377\334\230\"\377"
	"\264v\25\377\242i\17\377\242i\17\377\271tN\377\271tN\377\322\221m\377\335"
	"\237}\377\350\255\214\377\364\274\235\377\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\242i\17\377\265w\25"
	"\377\272|\27\377\266x\26\377\266x\26\377\277\177\30\377\277\200\31\377\276"
	"~\30\377\267y\26\377\267y\26\377\266x\26\377\267y\26\377\272{\27\377\274"
	"~\30\377\275~\30\377\276\177\30\377\302\202\32\377\305\205\32\377\313\212"
	"\34\377\306\206\33\377\334\230$\377\333\227#\377\302\202\32\377\264v\25\377"
	"\264v\25\377\330\225\40\377\264v\25\377\242i\17\377\242i\17\377\271tN\377"
	"\277{V\377\322\221m\377\322\221m\377\322\221m\377\352\257\217\377\362\271"
	"\232\377\364\274\235\377\364\274\235\377\364\274\235\377\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\242i\17\377\264v\25\377\264v\25\377"
	"\264v\25\377\264v\25\377\264v\25\377\264v\25\377\264v\25\377\264v\25\377"
	"\264v\25\377\264v\25\377\264v\25\377\264v\25\377\264v\25\377\264v\25\377"
	"\267x\26\377\272{\27\377\273|\30\377\270y\26\377\265v\25\377\264v\25\377"
	"\264v\25\377\242i\17\377\242i\17\377\242i\17\377\242i\17\377\242i\17\377"
	"\377\377\377\377\271tN\377\322\221m\377\322\221m\377\322\221m\377\362\271"
	"\232\377\364\274\235\377\355\307\262\377\355\307\262\377\355\307\262\377"
	"\364\274\235\377\364\274\235\377\322\221m\377\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\242i\17\377\242i\17\377\242i\17\377\242i\17"
	"\377\242i\17\377\242i\17\377\242i\17\377\242i\17\377\242i\17\377\242i\17"
	"\377\242i\17\377\242i\17\377\242i\17\377\242i\17\377\242i\17\377\242i\17"
	"\377\242i\17\377\242i\17\377\242i\17\377\242i\17\377\242i\17\377\271tN\377"
	"\271tN\377\271tN\377\271tN\377\377\377\377\377===\377\322\221m\377\322\221"
	"m\377\341\244\202\377\363\272\233\377\364\274\235\377\364\274\235\377\355"
	"\307\262\377\355\307\262\377\355\307\262\377\355\307\262\377\364\274\235"
	"\377\322\221m\377\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\322\221m\377\271tN\377\271tN\377"
	"\271tN\377\271tN\377\271tN\377\271tN\377\271tN\377\271tN\377\271tN\377\271"
	"tN\377\271tN\377\271tN\377\271tN\377\271tN\377\271tN\377\271tN\377\271tN"
	"\377\322\221m\377\322\221m\377\322\221m\377\271tN\377===\377===\377\322\221"
	"m\377\334\235{\377\364\274\235\377\364\274\235\377\364\274\235\377\360\302"
	"\251\377\355\307\262\377\355\307\262\377\355\307\262\377\355\307\262\377"
	"\364\274\235\377\322\221m\377\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\322\221m\377\322\221"
	"m\377\322\221m\377\322\221m\377\316\214h\377\271tN\377\322\221m\377\322\221"
	"m\377\322\221m\377\271tN\377\272uO\377\324\223o\377\322\221m\377\322\221"
	"m\377\322\221m\377\326\226s\377\333\235z\377\337\242\177\377\342\246\204"
	"\377\342\246\204\377\322\221m\377\271tN\377===\377===\377\322\221m\377\356"
	"\265\225\377\364\274\235\377\364\274\235\377\364\274\235\377\363\275\237"
	"\377\362\277\243\377\357\304\255\377\355\307\262\377\364\274\235\377\364"
	"\274\235\377\322\221m\377\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\322\221m\377\342\246\204"
	"\377\342\246\204\377\342\246\204\377\321\221n\377\271tN\377\322\221m\377"
	"\343\247\205\377\317\217l\377\342\246\204\377\300|W\377\342\246\204\377\346"
	"\253\212\377\342\246\204\377\342\247\205\377\342\246\204\377\350\255\214"
	"\377\342\246\204\377\364\274\235\377\364\274\235\377\364\274\235\377\322"
	"\221m\377\271tN\377===\377\322\221m\377\347\254\213\377\364\274\235\377\364"
	"\274\235\377\364\274\235\377\364\274\235\377\364\274\235\377\364\274\235"
	"\377\364\274\235\377\364\274\235\377\364\274\235\377\322\221m\377\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\322\221m\377\342\246\204\377\342\246\204\377\347\255\213"
	"\377\332\234z\377\271tN\377\322\221m\377\317\217k\377\351\256\216\377\364"
	"\274\235\377\355\263\223\377\364\274\235\377\362\271\232\377\357\266\226"
	"\377\355\264\224\377\354\263\222\377\360\267\230\377\364\274\235\377\364"
	"\274\235\377\364\274\235\377\364\274\235\377\364\274\235\377\322\221m\377"
	"\322\221m\377\342\245\204\377\347\254\213\377\364\274\235\377\364\274\235"
	"\377\355\307\262\377\364\274\235\377\364\274\235\377\364\274\235\377\364"
	"\274\235\377\364\274\235\377\364\274\235\377\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\322\221m\377\342\246\204\377\342\246\204\377\354\263\222\377\345"
	"\251\211\377\271tN\377\311\206b\377\344\250\207\377\360\303\252\377\364\274"
	"\235\377\364\274\235\377\364\274\235\377\364\274\235\377\364\274\235\377"
	"\364\274\235\377\364\274\235\377\364\274\235\377\364\274\235\377\364\274"
	"\235\377\364\274\235\377\364\274\235\377\364\274\235\377\354\263\222\377"
	"\347\254\213\377\335\237|\377\334\236{\377\357\265\225\377\364\274\235\377"
	"\364\274\235\377\364\274\235\377\364\274\235\377\364\274\235\377\364\274"
	"\235\377\342\246\204\377\322\221m\377\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\322\221m\377\342\246\204\377\342\246\204\377\354\262\222\377\353\261\221"
	"\377\303\200[\377\271tN\377\303\177Z\377\320\217k\377\357\304\254\377\357"
	"\304\255\377\356\305\257\377\322\222n\377\356\264\225\377\364\274\235\377"
	"\364\274\235\377\364\274\235\377\363\275\237\377\362\277\243\377\360\303"
	"\252\377\364\274\235\377\364\274\235\377\353\261\221\377\342\246\204\377"
	"\327\227t\377\325\225q\377\326\226s\377\353\261\221\377\356\264\224\377\351"
	"\256\215\377\342\245\204\377\342\246\204\377\342\246\204\377\322\221m\377"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\327\230"
	"u\377\342\246\204\377\351\255\215\377\364\274\235\377\323\224q\377\311\210"
	"d\377\271tN\377\271tN\377\317\215i\377\321\220l\377\310\206a\377\303\200"
	"[\377\307\205a\377\364\274\235\377\364\274\235\377\361\300\245\377\356\305"
	"\256\377\355\307\262\377\355\307\262\377\364\274\235\377\364\274\235\377"
	"\364\273\234\377\342\246\204\377\333\235{\377\315\213g\377\320\216j\377\323"
	"\222n\377\322\221m\377\323\222n\377\333\235z\377\322\221m\377\322\221m\377"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\322\221m\377\342\246\204\377\343\247\205\377\363\271\232\377\362\271"
	"\232\377\337\243\201\377\307\205`\377\303\200[\377\271tN\377\274xR\377\310"
	"\206a\377\331\233x\377\364\274\235\377\364\274\235\377\355\307\262\377\355"
	"\307\262\377\355\307\262\377\355\307\262\377\355\307\262\377\364\274\235"
	"\377\364\274\235\377\364\274\235\377\342\246\204\377\342\246\204\377\311"
	"\210c\377\300|W\377\276zT\377\276zU\377\300|W\377\304\201\\\377\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\324\224q\377\342\246\204\377\347\254"
	"\212\377\357\266\226\377\361\271\231\377\360\267\227\377\343\247\206\377"
	"\327\230u\377\362\272\233\377\364\274\235\377\364\274\235\377\364\274\235"
	"\377\364\274\235\377\364\274\235\377\355\307\262\377\364\274\235\377\364"
	"\274\235\377\364\274\235\377\364\274\235\377\364\274\235\377\364\274\235"
	"\377\351\256\215\377\342\246\204\377\336\240~\377\316\215i\377\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\322\221m\377\342\246\204\377\342\246\204\377\343\250"
	"\206\377\360\267\227\377\364\274\235\377\364\274\235\377\364\274\235\377"
	"\364\274\235\377\364\274\235\377\364\274\235\377\364\274\235\377\364\274"
	"\235\377\364\274\235\377\364\274\235\377\364\274\235\377\364\274\235\377"
	"\364\274\235\377\364\274\235\377\364\274\235\377\352\260\217\377\343\247"
	"\205\377\342\246\204\377\326\226s\377\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\324\223o\377\342\246\204\377\342\246\204\377\342"
	"\246\204\377\347\254\212\377\356\264\224\377\361\270\230\377\360\270\231"
	"\377\363\273\234\377\364\274\235\377\364\274\235\377\364\274\235\377\364"
	"\274\235\377\364\274\235\377\364\274\235\377\364\274\235\377\363\273\234"
	"\377\351\256\215\377\345\251\210\377\342\246\204\377\342\246\204\377\342"
	"\246\204\377\322\221m\377\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\324\223p\377\337\242\177\377\342\246\204\377\342"
	"\246\204\377\342\246\204\377\342\246\204\377\342\246\204\377\342\246\204"
	"\377\342\246\204\377\342\246\204\377\346\253\211\377\345\252\210\377\345"
	"\251\210\377\345\251\210\377\345\252\210\377\343\247\205\377\343\247\205"
	"\377\342\246\204\377\342\246\204\377\330\230u\377\322\221m\377\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\322\221n\377\331\233x\377\340\243\201\377"
	"\340\244\202\377\341\245\203\377\341\245\203\377\337\242\200\377\342\246"
	"\204\377\342\246\204\377\342\246\204\377\342\246\204\377\342\246\204\377"
	"\342\246\204\377\337\241\177\377\333\235z\377\330\231v\377\323\222o\377\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\271tN\377\277{V\377\303\201\\\377\276"
	"zT\377\276zU\377\326\226s\377\325\225q\377\326\226r\377\325\225r\377\322"
	"\222n\377\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\202\236-\377\202\236-\377\202\236-\377\271tN\377\271tN\377\271tN\377\322"
	"\221m\377\271tN\377\364\274\235\377\364\274\235\377_v\30\377\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\202\236-\377\202\236-\377\222"
	"\264,\377\202\236-\377\202\236-\377_v\30\377_v\30\377_v\30\377_v\30\377\322"
	"\221m\377\322\221m\377\255\322=\377_v\30\377\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\202\236-\377\255\322=\377\255\322=\377\255\322=\377\222\264,\377"
	"\222\264,\377\202\236-\377\202\236-\377\202\236-\377_v\30\377\24.F\377\35"
	"Be\377\255\322=\377\255\322=\377_v\30\377\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\202\236-\377\255\322"
	"=\377\255\322=\377\255\322=\377\255\322=\377\255\322=\377\202\236-\377\222"
	"\264,\377\202\236-\377\202\236-\377_v\30\377\24.F\377\35Be\377\202\236-\377"
	"\255\322=\377_v\30\377\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\202\236-\377\255\322=\377\255\322=\377\255\322=\377"
	"\255\322=\377\222\264,\377\255\322=\377\222\264,\377\222\264,\377\202\236"
	"-\377\202\236-\377\202\236-\377_v\30\377\24.F\377\35Be\377\255\322=\377_"
	"v\30\377\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\202\236-\377\255\322=\377\255\322=\377\255\322=\377\255\322=\377\255"
	"\322=\377\222\264,\377\202\236-\377\202\236-\377\202\236-\377\202\236-\377"
	"\202\236-\377_v\30\377_v\30\377\35Be\377\202\236-\377\222\264,\377_v\30\377"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\202\236-\377\255\322=\377\255"
	"\322=\377\255\322=\377\255\322=\377\222\264,\377\222\264,\377\202\236-\377"
	"\222\264,\377\202\236-\377\222\264,\377\202\236-\377\202\236-\377\202\236"
	"-\377_v\30\377\24.F\377\35Be\377\222\264,\377_v\30\377\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\202\236-\377\255\322=\377\255\322=\377\255\322=\377\222\264,\377"
	"\255\322=\377\222\264,\377\222\264,\377\222\264,\377\202\236-\377\202\236"
	"-\377\202\236-\377\202\236-\377_v\30\377\202\236-\377_v\30\377\24.F\377\35"
	"Be\377\202\236-\377_v\30\377\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\202\236-\377\255"
	"\322=\377\255\322=\377\255\322=\377\255\322=\377\222\264,\377\222\264,\377"
	"\202\236-\377\222\264,\377\202\236-\377\202\236-\377\202\236-\377\202\236"
	"-\377_v\30\377\202\236-\377_v\30\377\24.F\377\24.F\377\202\236-\3770=\11"
	"\377_v\30\377\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\202\236-\377\255\322=\377\255\322=\377\222\264"
	",\377\255\322=\377\222\264,\377\222\264,\377\222\264,\377\202\236-\377\222"
	"\264,\377\202\236-\377\202\236-\377\202\236-\3770=\11\377_v\30\377_v\30\377"
	"\24.F\377\35Be\377\202\236-\3770=\11\377_v\30\377\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\202\236-\377"
	"\222\264,\377\222\264,\377\222\264,\377\222\264,\377\202\236-\377\202\236"
	"-\377\202\236-\377\222\264,\377\202\236-\377\202\236-\377\202\236-\377\202"
	"\236-\3770=\11\377_v\30\377_v\30\377\24.F\377\24.F\377\202\236-\3770=\11"
	"\377_v\30\377\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\202\236-\377\222\264,\377\222"
	"\264,\377\222\264,\377\222\264,\377\202\236-\377\222\264,\377\202\236-\377"
	"\202\236-\377\202\236-\377\202\236-\377\202\236-\3770=\11\377_v\30\377_v"
	"\30\377\24.F\377\35Be\377\202\236-\377\322\221m\377\322\221m\377\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\202\236-\377\202\236-\377\202\236-\377\202\236-\377"
	"\202\236-\377\202\236-\377\202\236-\377\202\236-\377\202\236-\377\202\236"
	"-\377\202\236-\377\202\236-\3770=\11\3770=\11\377_v\30\377\24.F\377\24.F"
	"\377\202\236-\377\364\274\235\377\342\246\204\377\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\271tN\377\271tN\377\271tN\377\271tN\377\271tN\377\271tN\377\271tN\377"
	"\271tN\377\271tN\377\271tN\377\271tN\377\271tN\377\326\226s\3770=\11\377"
	"0=\11\377\24.F\377\35Be\377_v\30\377\364\274\235\377\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\322\221m\377\322\221m\377\322\221m\377\322\221m\377"
	"\322\221m\377\322\221m\377\322\221m\377\322\221m\377\322\221m\377\364\274"
	"\235\377\364\274\235\377\342\246\204\377\322\221m\377\12\35/\377\12\35/\377"
	"\24.F\377\24.F\377\12\35/\377\342\246\204\377\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\322\221m\377\322\221m\377\326\226s\377\342\246\204\377\342"
	"\246\204\377\353\261\221\377\364\274\235\377\364\274\235\377\364\274\235"
	"\377\364\274\235\377\342\246\204\377\322\221m\377\322\221m\377\12\35/\377"
	"\12\35/\377\367\332\31\377\315\267#\377\12\35/\377\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\322\221m\377\322\221m\377"
	"\322\221m\377\271tN\377\353\261\221\377\353\261\221\377\364\274\235\377\364"
	"\274\235\377\355\307\262\377\342\246\204\377\271tN\377\322\221m\377\12\35"
	"/\377\12\35/\377\315\267#\377\266\241\21\377\12\35/\377\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\322\221"
	"m\377\322\221m\377\271tN\377\342\246\204\377\342\246\204\377\353\261\221"
	"\377\364\274\235\377\355\307\262\377\355\307\262\377\342\246\204\377\12\35"
	"/\377\12\35/\377\12\35/\377\12\35/\377\12\35/\377\12\35/\377\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\326\226s\377\322\221m\377\271tN\377\353\261\221\377\342\246"
	"\204\377\353\261\221\377\364\274\235\377\364\274\235\377\342\246\204\377"
	"\12\35/\377\12\35/\377\35Be\377\35Be\377\24.F\377\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\12\35/\377\322\221m\377\353\261"
	"\221\377\326\226s\377\326\226s\377\342\246\204\377\24.F\377\35Be\377\35B"
	"e\377\35Be\377\35Be\377\24.F\377\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\12\35/\377\12\35/\377\12\35/\377\24.F\377\35"
	"Be\377\24.F\377\35Be\377\24.F\377\35Be\377\24.F\377\24.F\377B*\16\377}Y0"
	"\377\265\207R\377\265\207R\377\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\24.F\377\35Be\377\24.F\377\35"
	"Be\377\24.F\377\24.F\377\35Be\377\35Be\377\24.F\377\24.F\377B*\16\377Y;\30"
	"\377}Y0\377\241r=\377\241r=\377\265\207R\377\265\207R\377\265\207R\377\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\24.F\377\35Be\377\24"
	".F\377\35Be\377\35Be\377\35Be\377\24.F\377\24.F\377B*\16\377B*\16\377}Y0"
	"\377\241r=\377\241r=\377\241r=\377\241r=\377\241r=\377\241r=\377\265\207"
	"R\377\265\207R\377\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\24.F\377\24"
	".F\377\24.F\377\35Be\377\24.F\377B*\16\377B*\16\377B*\16\377}Y0\377}Y0\377"
	"\241r=\377}Y0\377\241r=\377}Y0\377\241r=\377}Y0\377}Y0\377\241r=\377}Y0\377"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\24.F\377\24.F\377B*\16\377B*\16"
	"\377B*\16\377Y;\30\377Y;\30\377Y;\30\377iG\37\377Y;\30\377iG\37\377Y;\30"
	"\377iG\37\377Y;\30\377iG\37\377Y;\30\377iG\37\377iG\37\377iG\37\377iG\37"
	"\377\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0B*\16\377B*\16\377Y;\30\377iG\37\377iG"
	"\37\377}Y0\377iG\37\377iG\37\377iG\37\377iG\37\377iG\37\377}Y0\377}Y0\377"
	"iG\37\377}Y0\377}Y0\377iG\37\377}Y0\377}Y0\377iG\37\377\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0Y;\30\377Y;\30\377Y;\30\377Y;\30\377Y;\30\377Y;\30\377Y;\30\377"
	"Y;\30\377Y;\30\377Y;\30\377iG\37\377Y;\30\377Y;\30\377iG\37\377iG\37\377"
	"Y;\30\377Y;\30\377iG\37\377Y;\30\377Y;\30\377\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377"
	"\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377"
	"\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377"
	"\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0"
	"\377\377\377\0",
};

Just added a simple emitter-less particle system. Plan on expanding it a bit later. Unless someone else does first tongue.png




PARTNERS