import direct.directbase.DirectStart
from pandac.PandaModules import *
from direct.interval.IntervalGlobal import *
from direct.gui.DirectGUI import *
from random import randint, seed
import time

ROWS = 12
SEATS = 6 + 1
ISLE = 3
SEAT_WIDTH = .75

def loadObject(model, scale = None, pos = None, hpr = None,
			   texture = None, func = loader.loadModelCopy,
			   parent = render, wrt = False, transparency = True,
			   billboard = False, zbuffer = True, texClamp = False,
			   bin = None, binVal = 0, color = None, texSmooth = 1):
	
	obj = func(model)
	if pos: obj.setPos(pos)
	if hpr: obj.setHpr(hpr)
	if scale: obj.setScale(scale)
	if color: obj.setColor(color)
	if texture:
		obj.tex = loader.loadTexture('art/'+texture)
		obj.setTexture(obj.tex, 1)
		obj.tex.setMinfilter(texSmooth)
		obj.tex.setMagfilter(texSmooth)
		if texClamp:
			obj.tex.setWrapu(0)
			obj.tex.setWrapv(0)
	if transparency: obj.setTransparency(1)
	if wrt: obj.wrtReparentTo(parent)
	else: obj.reparentTo(parent)
	if billboard: obj.node().setEffect(BillboardEffect.makePointEye())
	if not zbuffer: obj.setDepthTest(False, 1)
	if bin: obj.setBin(bin, binVal)
	
	return obj


def PointAtZ(z, point, vec):
	return point + vec * ((z-point.getZ()) / vec.getZ())

def SeatPos(row, seat = None, z = 0):
	if not seat:
		return Point3(SEAT_WIDTH*((row%SEATS) - ISLE), int(row/SEATS) - ROWS/2, z)
	else: return seatPos(row * SEATS + seat, z = z)

def SeatCoord(i):
	return Point2(i%SEATS, int(i/SEATS))

def SeatLeft(i):
	seat = i % SEATS
	if seat != ISLE and seat != 0 and seat != ISLE+1: return i - 1
	return None

def SeatRight(i):
	seat = i % SEATS
	if seat != ISLE and seat != SEATS - 1 and seat != ISLE-1: return i + 1
	return None

def SeatSurround(i):
	seats = [None for j in range(8)]
	up = i - SEATS
	down = i + SEATS

	if (up >= 0):
		seats[0] = SeatLeft(up)
		if (up % SEATS) != ISLE: seats[1] = up
		seats[2] = SeatRight(up)
	seats[3] = SeatLeft(i)
	seats[4] = SeatRight(i)
	if down < (SEATS * ROWS):
		seats[5] = SeatLeft(down)
		if (up % SEATS) != ISLE: seats[7] = down
		seats[7] = SeatRight(down)

	return seats

def isMiddleSeat(i):
	return (i % SEATS) == 1 or (i % SEATS) == 5

def isIsleSeat(i):
	return (i % SEATS) == 2 or (i % SEATS) == 4

def isWindowSeat(i):
	return (i % SEATS) == 0 or (i % SEATS) == 6

def toggleStash(node):
	if node.isStashed(): node.unstash()
	else: node.stash()

def printCamera():
	print camera.getPos()
	print camera.getHpr()

class World(DirectObject):
	def __init__(self):
		self.anims = []
		self.animTask = taskMgr.add(self.playAnimations, 'animTask')
		self.animTask.last = 0
		self.titleAnim = Animation(titlecard, 6, "art/screens/title", 3)
		self.titleAnim.start()
		self.addAnim(self.titleAnim)
		Sequence(Wait(2),
				 Func(self.initialLoad)).start()

	def initialLoad(self):
		self.accept('f12', base.win.saveScreenshotDefault)
		self.accept('escape', sys.exit)
		base.disableMouse()
		self.accept('p', printCamera)

		#base.camLens.setFar(50)
		#base.camLens.setFov(Point2(30, 50))
		camera.setPosHpr(0, -13.95, 10.52, 0, -42.8, 0)

		self.bg = loadObject("passenger", pos = Point3(0,50,0),
							texture = "screens/background01.png",
							scale = 37.77, bin = "background", zbuffer = False,
							transparency = False, parent = camera)
		
		self.picker = CollisionTraverser()
		self.pq     = CollisionHandlerQueue()
		self.pickerNode = CollisionNode('mouseRay')
		self.pickerNP = camera.attachNewNode(self.pickerNode)
		#self.pickerNP.show()
		self.pickerNode.setFromCollideMask(BitMask32.bit(1))
		self.pickerRay = CollisionRay()
		self.pickerNode.addSolid(self.pickerRay)
		self.picker.addCollider(self.pickerNode, self.pq)
		#self.picker.showCollisions(render)

		self.seats = [None for i in range(ROWS * SEATS)]
		self.seatRoot = render.attachNewNode("seatRoot")
		for i in range(ROWS * SEATS):
			self.seats[i] = self.seatRoot.attachNewNode("seat" + str(i))
			self.seats[i].setPos(SeatPos(i))

			self.seats[i].seat = loadObject(
				"seat", texture = "seat/seat.png", parent = camera,
				scale = 1.263, color = Vec4(.8,.8,.8,1), wrt = True,
				texClamp = True, zbuffer = False, pos = SeatPos(i))
			self.seats[i].seat.setHpr(0,0,0)
			self.seats[i].seat.wrtReparentTo(self.seats[i])
			
			self.seats[i].col = self.seats[i].seat.find("**/pPlane1")
			self.seats[i].col.setScale(.59,1,.8)
			self.seats[i].col.node().setIntoCollideMask(BitMask32.bit(1))
			self.seats[i].col.node().setTag('seat', str(i))

			#self.seats[i].lock = loader.loadModelCopy("lock")
			#self.seats[i].lock.reparentTo(self.seats[i].seat)
			#self.seats[i].lock.setY(-.1)
			#self.seats[i].lock.setTransparency(1)
			#self.seats[i].lock.setTexture(loader.loadTexture("redx.png"),1)
			#self.seats[i].lock.hide()

			if (i%SEATS) == ISLE: self.seats[i].stash()

		self.flash = [loadObject("passenger", parent = camera, scale = .75,
								 pos = Point3(-1.47,5,-0.54), 
								 bin = "unsorted", zbuffer = False)
					  for i in range(4)]
		self.flash[1].setX(-1*self.flash[1].getX())
		self.flash[2].setX(-1*self.flash[2].getX())
		self.flash[2].setZ(.8); self.flash[3].setZ(.8)
		self.flash[2].setX(self.flash[2].getX()*.65)
		self.flash[3].setX(self.flash[3].getX()*.65)
		self.flash[2].setScale(.3); self.flash[3].setScale(.3)
		for np in self.flash:
			np.hide()
			np.setAlphaScale(.5)
			np.anim = Animation(np, 15, "art/feedback/light", 5, loop = 1,
								autoShow = True)
			self.addAnim(np.anim)

		self.passOrder = (
			[Passenger(self) for i in range(27)] +
			[Frequent(self) for i in range(15)] +
			[Baby(self) for i in range(1)] +
			[Fat(self) for i in range(4)] +
			[Talker(self) for i in range(10)] +
			[Sleeper(self) for i in range(15)])

		self.card = loadObject("passenger", bin = "unsorted", zbuffer = False,
							   pos = Point3(-1.04, 3.75, .3), parent = camera)
		self.card.hide()

		
		self.scoreTex = [loader.loadTexture("art/feedback/"+str(i)+".png")
						 for i in range(10)]
		self.scoreBoard = loadObject("passenger", parent = camera,
									 bin = "unsorted", zbuffer = False,
									 pos = Point3(.79, 3, .55),
									 texture = "feedback/infobox.png")
		self.scoreBoard.time = [
			loadObject("passenger", parent = self.scoreBoard, bin = "unsorted",
					   zbuffer = False, scale = .096,
					   pos = Point3(.074+.058*i, -.01, .152),
					   texture = "feedback/blank.png")
			for i in range(3)]
		self.scoreBoard.time[0].last = 0

		self.scoreBoard.score = [
			loadObject("passenger", parent = self.scoreBoard, bin = "unsorted",
					   zbuffer = False, scale = .096,
					   pos = Point3(-.179+.058*i, -.01, -.081),
					   texture = "feedback/blank.png")
			for i in range(3)]
		self.scoreBoard.score[0].last = 0

		self.scoreBoard.goal = [
			loadObject("passenger", parent = self.scoreBoard, bin = "unsorted",
					   zbuffer = False, scale = .096,
					   pos = Point3(.052+.058*i, -.01, -.081))
			for i in range(3)]
		self.scoreBoard.goal[0].setTexture(self.scoreTex[4], 1)
		self.scoreBoard.goal[1].setTexture(self.scoreTex[7], 1)
		self.scoreBoard.goal[2].setTexture(self.scoreTex[0], 1)

		self.accept('l', toggleStash, [self.card])
		self.accept("mouse1", self.grabSeat)
		self.accept("mouse1-up", self.releaseSeat)

		#Sounds
		self.bgm = loader.loadMusic("sound/Rain_of_though_cut.mp3")
		self.cheer = loader.loadSfx("sound/hooray.mp3")
		self.cheerInt = SoundInterval(self.cheer)
		self.boo = loader.loadSfx("sound/disappointed.mp3")
		self.booInt = SoundInterval(self.boo)
		self.warningSfx = loader.loadSfx("sound/beep.mp3")
		self.warningSfxInt = SoundInterval(self.warningSfx, duration = 10)
		

		self.titleAnim.pause()
		titlecard.setTexture(loader.loadTexture("art/screens/instructions.png"), 1)
		self.advButton = DirectButton(image = 'art/screens/continue.png',
									  scale = (.666*.732,0,.666*.242),
									  command=self.continueIntro,
									  pos = (.05, 0, -.7),
									  frameColor = (0,0,0,0),
									  clickSound = None, rolloverSound = None)
		self.advButton.setTransparency(1)

	def continueIntro(self):
		titlecard.setTexture(loader.loadTexture("art/screens/info.png"), 1)
		self.advButton.remove()
		self.advButton = DirectButton(image = 'art/screens/start.png',
									  scale = (.666*.506,0,.666*.242),
									  command=self.startGame,
									  pos = (.05, 0, -.7),
									  frameColor = (0,0,0,0),
									  clickSound = None, rolloverSound = None)
		self.advButton.setTransparency(1)
		

	def firstEmptySeat(self):
		for i in range(SEATS*ROWS):
			if i % SEATS == ISLE: continue
			if self.seats[i].passenger is None: return i
		return None

	def addAnim(self, anim):
		self.anims.append(anim)

	def addPassenger(self):
		s = self.firstEmptySeat()
		self.passOrder[self.pgrs].root.show()
		self.passOrder[self.pgrs].seat = s
		self.seats[s].passenger = self.passOrder[self.pgrs]
		self.refreshPassengers(feedback = False)
		self.pgrs += 1

	def swapPassengers(self, fr, to):
		temp = self.seats[fr].passenger
		self.seats[fr].passenger = self.seats[to].passenger
		self.seats[to].passenger = temp
		if self.seats[fr].passenger is not None:
			self.seats[fr].passenger.seat = fr
		if self.seats[to].passenger is not None:
			self.seats[to].passenger.seat = to

	def startGame(self):
		if not taskMgr.hasTaskNamed('timerTask'):
			self.timerTask = taskMgr.add(self.updateTimer, 'timerTask')
		else: return
		titlecard.stash()
		self.advButton.remove()

		self.hiSt = False
		self.dragging = False
		self.shufflePassengers()
		self.totHap = 0
		self.pgrs = 0
		for obj in self.seats: obj.passenger = None
		for obj in self.passOrder:
			obj.root.hide()
			obj.seat = None

		if not taskMgr.hasTaskNamed('mouseTask'):
			self.mouseTask = taskMgr.add(self.pickerTask, 'mouseTask')

		self.bgm.setVolume(1)
		self.bgm.setTime(0)
		self.bgm.play()
		self.card.hide()
		self.addBatch(12)


	def addBatch(self, size = 1, wait = 10):
		if self.pgrs >= (ROWS * (SEATS-1)): return
		self.addAction = Sequence()
		for i in range(size):
			self.addAction.append(Func(self.addPassenger))
			self.addAction.append(Wait(.1))
		self.addAction.append(Wait(wait))
		self.addAction.append(Func(self.addBatch, size, wait))
		self.addAction.start()

	def shufflePassengers(self):
		seed()
		for i in range(len(self.passOrder)):
			choice = randint(i, len(self.passOrder)-1)
			temp = self.passOrder[i]
			self.passOrder[i] = self.passOrder[choice]
			self.passOrder[choice] = temp

	def refreshPassengers(self, feedback = True):
		old = self.totHap
		self.totHap = 0
		for i in range(ROWS*SEATS):
			if self.seats[i].passenger is None:
				self.seats[i].seat.setColor(Vec4(.8,.8,.8,1))
			if i % SEATS == ISLE or self.seats[i].passenger is None : continue
			self.seats[i].passenger.root.setPos(SeatPos(i, z = .05))
			self.totHap += self.seats[i].passenger.calcHappiness(feedback)
			self.seats[i].seat.setColor(self.seats[i].passenger.seatColor())
		self.setNumber(self.scoreBoard.score, self.totHap)
		if feedback and self.totHap != old:
			if self.totHap > old:
				color = Vec4(0,1,0,1)
				self.cheerInt.start()
			else:
				color = Vec4(1,0,0,1)
				self.booInt.start()
			for np in self.flash:
				np.setColor(color)
				np.anim.start()
		if self.totHap >= 470:
			self.endGame("art/screens/win.png")

	def endGame(self, screen):
		taskMgr.remove('mouseTask')
		taskMgr.remove('timerTask')
		self.warningSfxInt.finish()
		self.addAction.pause()
		titlecard.setTexture(loader.loadTexture(screen), 1)
		titlecard.unstash()
		titlecard.setTransparency(1)
		self.advButton = DirectButton(image = 'art/screens/playagain.png',
									  scale = (.666*.894,0,.666*.242),
									  command=self.startGame,
									  pos = (.05, 0, -.7),
									  frameColor = (0,0,0,0),
									  clickSound = None, rolloverSound = None)
		self.advButton.setTransparency(1)

		Parallel(
			Sequence(
			LerpFunc(self.bgm.setVolume, fromData = 1, toData = 0, duration = 1.5),
			Func(self.bgm.stop)),
			LerpFunc(titlecard.setAlphaScale, duration = 1.5),
			LerpFunc(self.advButton.setAlphaScale, duration = 1.5)).start()

	def setNumber(self, group, number):
		if group[0].last != int(number):
			group[0].setTexture(self.scoreTex[int(number/100)%10])
			group[1].setTexture(self.scoreTex[int(number/10)%10])
			group[2].setTexture(self.scoreTex[int(number/1)%10])
			group[0].last = int(number)
			
	def pickerTask(self, task):
		if self.hiSt is not False:
			if self.seats[self.hiSt].passenger is not None:
				self.seats[self.hiSt].seat.setColor(
					self.seats[self.hiSt].passenger.seatColor())
			else: self.seats[self.hiSt].seat.setColor(Vec4(.8,.8,.8,1))
			self.hiSt = False
		if base.mouseWatcherNode.hasMouse():
			mpos = base.mouseWatcherNode.getMouse()
			self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY())
			if self.dragging is not False:
				nearR = render.getRelativePoint(camera,
												self.pickerRay.getOrigin())
				vecR = render.getRelativeVector(camera,
												self.pickerRay.getDirection())
				self.seats[self.dragging].passenger.root.setPos(
					PointAtZ(.5, nearR, vecR))

			self.picker.traverse(self.seatRoot)
			if self.pq.getNumEntries() > 0: 
				self.pq.sortEntries()
				i = int(self.pq.getEntry(0).getIntoNode().getTag('seat'))
				self.seats[i].seat.setColor(Vec4(0,1,1,1))
				self.hiSt=i
					
		return Task.cont

	def grabSeat(self):
		if (taskMgr.hasTaskNamed('mouseTask') and
			self.hiSt is not False and
			self.seats[self.hiSt].passenger is not None):
			self.dragging = self.hiSt
			self.hiSt = False
			self.card.setTexture(
				self.seats[self.dragging].passenger.cardTex, 1)
			self.card.show()
			self.seats[self.dragging].col.stash()
			self.seats[self.dragging].passenger.aoeobj.unstash()
			self.seats[self.dragging].passenger.aoeAnim.start()
			
	def releaseSeat(self):
		if (taskMgr.hasTaskNamed('mouseTask') and
			self.dragging is not False):
			self.card.hide()
			self.seats[self.dragging].passenger.aoeobj.stash()
			self.seats[self.dragging].passenger.aoeAnim.pause()
			if self.hiSt is False:
				self.seats[self.dragging].passenger.root.setPos(
					SeatPos(self.dragging, z = .05))
			else:
				self.swapPassengers(self.hiSt, self.dragging)
				
			self.refreshPassengers()
			self.seats[self.dragging].col.unstash()
			self.dragging = False
			
	def updateTimer(self, task):
		if task.time > 150:
			self.endGame("art/screens/lose.png")
			return Task.done
		if task.time > 140 and not self.warningSfxInt.isPlaying():
			self.warningSfxInt.start()
		self.setNumber(self.scoreBoard.time, 150-task.time)
		return Task.cont

	def playAnimations(self, task):
		dt = task.time - task.last
		task.last = task.time
		for anim in self.anims:
			anim.step(dt)
		return Task.cont

class Animation:
	def __init__(self, np, fr, path = "", nFrames = 0, frames = None,
				 loop = 0, repeatDelay = 0, autoShow = False):
		self.playing = False
		self.np = np
		self.delay = 0
		self.frameLen = 1.0/fr
		self.frameTime = 0
		self.frame = 0
		self.loop = loop
		self.repeatDelay = repeatDelay
		self.autoShow = autoShow

		if frames: self.frames = frames
		else: self.loadAnim(nFrames, path)
		self.np.setTexture(self.frames[0], 1)

	def start(self):
		self.playing = True
		if self.autoShow: self.np.show()
	def pause(self):
		self.playing = False
		if self.autoShow: self.np.hide()
	def setDelay(self, t): self.delay = t

	def step(self, dt):
		if not self.playing: return
		if self.delay > 0:
			self.delay = max(self.delay - dt, 0)
			return
		self.frameTime += dt
		if self.frameTime > self.frameLen:
			frameAdv = int(self.frameTime / self.frameLen)
			self.frameTime = self.frameTime % self.frameLen
			self.frame = (self.frame + frameAdv)
			if self.frame >= len(self.frames):
				if self.loop == 1: self.pause()
				elif self.loop > 1: self.loop -= 1
				if self.repeatDelay: self.delay = randint(5,10)
			self.frame = self.frame % len(self.frames)
			self.np.setTexture(self.frames[self.frame], 1)

	def loadAnim(self, frs, path):
		self.frames = [loader.loadTexture((path+"%d.png") % i)
					   for i in range(frs)]
		for tex in self.frames:
			tex.setWrapu(0)
			tex.setWrapv(0)
			tex.setMinfilter(5)
			tex.setMagfilter(5)

NORMAL  = 0
FAT     = 1
BABY    = 2
FFLYER  = 3
TALKER  = 4
SLEEPER = 5

seatColors = [
	Vec4(.594,    0,    0, 1),
	Vec4(.859,    0,    0, 1),
	Vec4(   1,  .73,    0, 1),
	Vec4(   1, .140,    0, 1),
	Vec4(   1, .769, .523, 1),
	Vec4(   1,    1,    0, 1),
	Vec4(.805,    1, .074, 1),
	Vec4(.632,    1, .094, 1),
	Vec4(.395,    1, .066, 1),
	Vec4(.152,    1, .027, 1),
	Vec4(   0,    1,    0, 1)]

#Attribs: [Window, Middle, Isle, NormalAdj, FatAdj, BabySurr,
#		   FFAdj, TalkAdj, SleepAdj, SleepFront]

class Passenger:
	ptype = NORMAL
	base = 5
	objscale = 1.35
	tex = "normalflier"
	frames = 4
	fps = 2
	attrib = [0,0,0,0,-1,-2,3,0,0,0]
	aoePath = "art/effect_radius/side_side/effect_radius_"
	minustex = loader.loadTexture("art/feedback/minus.png")
	plustex = loader.loadTexture("art/feedback/plus.png")
	
	def __init__(self, world):
		self.seat = None
		self.world = world
		self.root = render.attachNewNode("passenger")
		self.root.hide()

		self.obj = loadObject("passenger", parent = camera, zbuffer = False,
							  wrt = True, scale = self.objscale,
							  texture = self.tex + "/sitting/sitting0.png",
							  texClamp = True, texSmooth = 5)
		self.obj.setHpr(0,0,0)
		self.obj.wrtReparentTo(self.root)

		self.objAnim = Animation(self.obj, self.fps,
								 "art/" + self.tex + "/sitting/sitting",
								 self.frames, repeatDelay = True)
		self.objAnim.setDelay(randint(0,10))
		self.objAnim.start()
		self.world.addAnim(self.objAnim)

		self.changeobj = loadObject("passenger", parent = self.obj,
									scale = .25, bin = "unsorted")
		self.changeobj.stash()

		self.changeobj.int = Sequence(
			Func(self.changeobj.unstash),
			Func(self.changeobj.setAlphaScale, 1),
			Parallel(
			LerpFunc(self.changeobj.setZ, fromData = .45, toData = .7,
					 duration = 1),
			Sequence(
			Wait(.6),
			LerpFunc(self.changeobj.setAlphaScale, fromData = 1, toData = .6,
					 duration = .4))
			),
			Func(self.changeobj.stash))

		self.aoeobj = loadObject("aoe", parent = self.root, scale = 1.2,
								 pos = Point3(0,0,-.1), zbuffer = False)
		self.aoeobj.stash()

		self.aoeAnim = Animation(self.aoeobj, 15, self.aoePath, 35)
		self.world.addAnim(self.aoeAnim)

		self.cardTex = loader.loadTexture("art/" + self.tex + "/card.png")

		self.happiness = self.base

	def seatColor(self):
		return seatColors[min(int(self.happiness), 10)]

	def calcHappiness(self, feedback = True):
		newAttrib = [0 for i in range(10)]
		old = self.happiness
		self.happiness = self.base

		if self.seat is not None:
			if isWindowSeat(self.seat): newAttrib[0] = 1
			if isMiddleSeat(self.seat): newAttrib[1] = 1
			if isIsleSeat(self.seat): newAttrib[2] = 1
			sur = SeatSurround(self.seat)
			if (sur[3] is not None and
				self.world.seats[sur[3]].passenger is not None):
				newAttrib[self.world.seats[sur[3]].passenger.ptype + 3] += 1
			if (sur[4] is not None and
				self.world.seats[sur[4]].passenger is not None):
				newAttrib[self.world.seats[sur[4]].passenger.ptype + 3] += 1
			for i in sur[:3]+sur[5:]:
				if (i is not None and
					self.world.seats[i].passenger is not None and
					self.world.seats[i].passenger.ptype == BABY):
					newAttrib[3+BABY] += 1
			if (sur[1] is not None and
				self.world.seats[sur[1]].passenger is not None and
				self.world.seats[sur[1]].passenger.ptype == SLEEPER):
				newAttrib[9] = 1

		for i in range(10):
			self.happiness += (self.attrib[i] * newAttrib[i])

		if self.happiness < 0: self.happiness = 0

		if feedback and self.happiness != old:
			if self.happiness > old:
				self.changeobj.setTexture(self.plustex, 1)
			else: self.changeobj.setTexture(self.minustex, 1)
			self.changeobj.int.start()

		return self.happiness

class Fat(Passenger):
	ptype = FAT
	#objscale = Point3(2.64, 1.73, 1.73)
	tex = "fattie"
	frames = 5
	fps = 4
	attrib = [0,-1,2,0,-2,-1,0,2,2,-1]

class Frequent(Passenger):
	ptype = FFLYER
	tex = "frequentflier"
	frames = 4
	fps = 2
	base = 7
	attrib = [0,-2,0,0,-2,-3,0,3,3,-2]
		
class Baby(Passenger):
	aoePath = "art/effect_radius/circle/effect_radius_"
	ptype = BABY
	tex = "mother"
	frames = 8
	fps = 4
	attrib = [0,0,0,2,-1,-2,0,2,2,-1]

class Talker(Passenger):
	tex = "talker"
	ptype = TALKER
	frames = 16
	fps = 3
	attrib = [0,2,0,0,-1,-1,0,2,0,-1]

class Sleeper(Passenger):
	aoePath = "art/effect_radius/T/effect_radius_"
	tex = "leaner"
	frames = 12
	fps = 5
	ptype = SLEEPER
	attrib = [3,-1,0,0,-1,-2,0,-2,2,0]

#Initial Image
titlecard = OnscreenImage(image = 'art/screens/title0.png',
						  scale = (1.33,0,1.33))
	
w = World()
run()
