-----
-- pacman.lua	-- by Robert Schmitz <Robert.Schmitz.Stolberg@googlemail.com> March 2006
--
-- This source code has been donated to the Public Domain.  Do whatever you 
-- want with it.
-- Der Code ist nicht in erster Linie für SDL ausgerichtet. Es sollte als Beispiel für ein
-- Buch "Lua - lernen für Anfänger" dienen und zwar für Mesnchen die bisher noch nicht mit  
-- Computersprachen in Berührung gekommen sind. (Aus dem Grund auch nicht der optimale Code)
-----
USES( 'lib.sdl', "global" )
USES( 'lib.bitlib', "global" )
USES 'lib.vec2d'
local SDL= ASSUME( lib.sdl )
local event= SDL.Init( SDL_INIT_VIDEO, SDL_INIT_AUDIO )
local screen=SDL.SetVideoMode(528,528,16,bmap{ SDL_HWSURFACE, SDL_ANYFORMAT })
myFrameRate=SDL_initFramerate(50)
background = SDL_MapRGB(screen.format, 0, 1, 0)
	SDL.EnableKeyRepeat()
	print("Screen is at ", 
	screen.format.BitsPerPixel, " bits per pixel\n")
	if btest( screen.flags, SDL_HWSURFACE ) then
		print "Screen is in video memory"
	else
		print "Screen is in system memory"
	end
	if btest( screen.flags, SDL_DOUBLEBUF ) then
		print "Screen has double-buffering enabled"
	end
	
	
function InitBitmaps()
	bitmap=SDL.LoadBMP("Pacmanleer528mit.bmp")
	bitmap=bitmap:DisplayFormat()
	geister={{},{},{},{}}
	geister.rot      = SDL.LoadBMP("GoastRot.bmp")
	geister.rosa     = SDL.LoadBMP("GoastRosa.bmp")
	geister.hellBlau = SDL.LoadBMP("GoastHellblau.bmp")
	geister.orange   = SDL.LoadBMP("GoastOrange.bmp")
	geister.blau     = SDL.LoadBMP("GoastBlau.bmp")
	geister.augen    = SDL.LoadBMP("Augen.bmp")
	geister.rot      = geister.rot:DisplayFormat()
	geister.rosa     = geister.rosa:DisplayFormat()
	geister.hellBlau = geister.hellBlau:DisplayFormat()
	geister.orange   = geister.orange:DisplayFormat()
	geister.blau     = geister.blau:DisplayFormat()
	geister.augen    = geister.augen:DisplayFormat()
	FaerbeGeister()
	zahlen={}
	for i = 1 , 9 do
		table.insert(zahlen,SDL.LoadBMP("d"..i..".bmp"))
		zahlen[i]=zahlen[i]:DisplayFormat()
	end
	table.insert(zahlen,SDL.LoadBMP("d0.bmp"))
	bitmapGameOver=SDL.LoadBMP("gameover.bmp")
	bitmapKirsche=SDL.LoadBMP("Kirsche.bmp")
	bitmapPkl=SDL.LoadBMP("punktKlein1.bmp")
	bitmapPkl=bitmapPkl:DisplayFormat()
	bitmapPgr=SDL.LoadBMP("punktGross1.bmp")
	bitmapPlayerLinks=SDL.LoadBMP("playerlinks.bmp")
	bitmapPlayerOben=SDL.LoadBMP("playeroben.bmp")
	bitmapPlayerRechts=SDL.LoadBMP("playerrechts.bmp")
	bitmapPlayerUnten=SDL.LoadBMP("playerunten.bmp")
	bitmapIch=bitmapPlayerLinks
	bitmapIchLeer=SDL.LoadBMP("playerleer.bmp")
	bitmapIchLeer=bitmapIchLeer:DisplayFormat()
	bitmapTor=SDL.LoadBMP("tor.bmp")
	bitmapIch:SetColorKey( bmap{SDL_SRCCOLORKEY,SDL_RLEACCEL}, 0 )
end

function FaerbeGeister()
	geister[1].bitmap = geister.rot
	geister[2].bitmap = geister.rosa
	geister[3].bitmap = geister.hellBlau
	geister[4].bitmap = geister.orange
	scharf = true
	geistGetroffen=0
	for i = 1,4 do
		geister[i].getroffen = false
	end
end

SperreInsel=function(_x1,_y1,_x2,_y2)
	for x = _x1,_x2 do
		for y = _y1, _y2 do
			punktTable[x][y].gesperrt = true
		end
	end
end

function SperreAlleInseln()
	SperreInsel(2,2,5,4)
	SperreInsel(2,6,5,7)
	SperreInsel(1,9,5,13)
	SperreInsel(1,15,5,19)
	SperreInsel(2,21,5,22)
	SperreInsel(4,22,5,25)
	SperreInsel(2,27,11,28)
	SperreInsel(1,24,2,25)
	SperreInsel(7,2,11,4)
	SperreInsel(16,2,20,4)
	SperreInsel(22,2,25,4)
	SperreInsel(7,6,8,13)
	SperreInsel(7,15,8,19)
	SperreInsel(7,21,11,22)
	SperreInsel(10,6,17,7)
	SperreInsel(13,6,16,7)
	SperreInsel(19,6,20,13)
	SperreInsel(22,6,25,7)
	SperreInsel(13,8,14,10)
	SperreInsel(9,9,11,10)
	SperreInsel(10,18,17,19)
	SperreInsel(16,9,18,10)
	SperreInsel(10,12,17,16)
	SperreInsel(10,24,17,25)
	SperreInsel(13,20,14,22)
	SperreInsel(13,26,14,28)
	SperreInsel(22,9,26,13)
	SperreInsel(7,24,8,26)
	SperreInsel(13,1,14,4)
	SperreInsel(22,15,26,19)
	SperreInsel(19,15,20,19)
	SperreInsel(16,2,20,3)
	SperreInsel(19,24,20,28)
	SperreInsel(16,27,25,28)
	SperreInsel(16,21,20,22)
	SperreInsel(22,21,25,22)
	SperreInsel(22,23,23,25)
	SperreInsel(25,24,26,25)
	punktTable[1][3].bitMap = bitmapPgr
	punktTable[1][3].w = 23
	punktTable[1][3].h = 23
	punktTable[26][3].bitMap = bitmapPgr
	punktTable[26][3].w = 23
	punktTable[26][3].h = 23
	punktTable[1][23].bitMap = bitmapPgr
	punktTable[1][23].w = 23
	punktTable[1][23].h = 23
	punktTable[26][23].bitMap = bitmapPgr
	punktTable[26][23].w = 23
	punktTable[26][23].h = 23
end

ZeichneBildschirm = function()
	bitmapIch = bitmapPlayerLinks
	myPos = {X = 13, Y = 29}
	ka = SDL.Rect( 0, 0 )
	SDL.BlitSurface( bitmap, nil, screen, ka ) 
	for x = 1 , table.getn(punktTable) do
		for y = 1 , table.getn(punktTable[x]) do
			if not punktTable[x][y].gesperrt and punktTable[x][y].sichtBar then
				local pX = punktTable[x][y].X - punktTable[x][y].w/2
				local pY = punktTable[x][y].Y - punktTable[x][y].h/2
				ka = SDL.Rect( pX, pY ,23,23)
				SDL.BlitSurface( punktTable[x][y].bitMap, nil, screen, ka )
			elseif not punktTable[x][y].gesperrt and not punktTable[x][y].sichtBar then
				local pX = punktTable[x][y].X - punktTable[x][y].w/2
				local pY = punktTable[x][y].Y - punktTable[x][y].h/2
				ka = SDL.Rect( pX, pY ,23,23)
				SDL.BlitSurface( bitmapIchLeer, nil, screen, ka )
			end
		end
	end
	ka = SDL.Rect( punktTable[myPos.X][myPos.Y].X-11,punktTable[myPos.X][myPos.Y].Y -10 , 23, 23)
	SDL.BlitSurface( bitmapIch, nil, screen, ka ) 
	ka = SDL.Rect( 450,495 )
	SDL.BlitSurface( bitmapKirsche, nil, screen, ka ) 
	ka = SDL.Rect( 245,205 )
	SDL.BlitSurface( bitmapTor, nil, screen, ka ) 
	ka = SDL.Rect( punktTable[13][11].X-11,punktTable[13][11].Y-10, 23, 23 )
	SDL.BlitSurface( geister[1].bitmap, nil, screen, ka ) 
	SDL_Flip(screen)
end

function ZeichnePunkte()
	local zahl={}
	zahl[1]=math.floor(punkteStand/1000)
	zahl[2]=math.floor((punkteStand-zahl[1]*1000)/100)
	zahl[3]=math.floor((punkteStand-zahl[1]*1000-zahl[2]*100)/10)
	zahl[4]=math.floor(punkteStand-zahl[1]*1000-zahl[2]*100-zahl[3]*10)
	for i = 1,4 do
		if zahl[i] == 0 then
			zahl[i] = 10
		end
	end
	ka = SDL.Rect( 136, 500, 12, 19 )
	SDL.BlitSurface( zahlen[zahl[1]], nil, screen, ka ) 
	ka = SDL.Rect( 148, 500, 12, 19 )
	SDL.BlitSurface( zahlen[zahl[2]], nil, screen, ka ) 
	ka = SDL.Rect( 160, 500, 12, 19 )
	SDL.BlitSurface( zahlen[zahl[3]], nil, screen, ka ) 
	ka = SDL.Rect( 172, 500, 12, 19 )
	SDL.BlitSurface( zahlen[zahl[4]], nil, screen, ka ) 
end

function InitGeister()
	geister[1].posX = 13
	geister[1].posY = 11
	geister[2].posX = 13
	geister[2].posY = 11
	geister[3].posX = 13
	geister[3].posY = 11
	geister[4].posX = 13
	geister[4].posY = 11
	for i = 1,4 do 
		geister[i].bitmap = geister[i].bitmap:DisplayFormat()
		if i ~= 1 then
			geister[i].frei = false
		else
			geister[1].frei = true
		end
		geister[i].getroffen = false
		geister[i].neuX, geister[i].neuY = NeuePos(i)
		geister[i].haengtFest = false
	end
end

function StartSimpleJob(_Job)
	for i = 1, table.getn(simpleJobs) do
		if simpleJobs[i][1] == _Job then -- läuft schon
			assert(false,_Job .. ": ein Job kann nicht zwei mal laufen")
		end
	end
	local myJobID = GetNextID()
	table.insert(simpleJobsAnwaerter,{_Job, myJobID})
	return myJobID
end

function StartSimpleHiResJob(_Job)
	for i = 1, table.getn(simpleHiResJobs) do
		if simpleHiResJobs[i][1] == _Job then -- läuft schon
			assert(false,_Job .. ": ein Job kann nicht zwei mal laufen")
		end
	end
	local myJobID = GetNextID()
	table.insert(simpleHiResJobsAnwaerter,{_Job, myJobID})
	return myJobID
end

function StartSimpleHiHiResJob(_Job) -- ist begrenzt durch die Größe des Spiels
	for i = 1, table.getn(StartSimpleHiHiResJob) do
		if StartSimpleHiHiResJob[i][1] == _Job then -- läuft schon
			assert(false,_Job .. ": ein Job kann nicht zwei mal laufen")
		end
	end
	local myJobID = GetNextID()
	table.insert(simpleHiHiResJobsAnwaerter,{_Job, myJobID})
	return myJobID
end

function IsJobRunning(_Job)
	local erLaeuft = false
	if type(_Job) == "number" then
		for i = table.getn(simpleJobs), 1, -1 do
			if simpleJobs[i][2] == _Job then
				erLaeuft = true
			end
		end
		for i = table.getn(simpleHiResJobs), 1, -1 do
			if simpleHiResJobs[i][2] == _Job then
				erLaeuft = true
			end
		end
		for i = table.getn(simpleHiHiResJobs), 1, -1 do
			if simpleHiHiResJobs[i][2] == _Job then
				erLaeuft = true
			end
		end
	elseif type(_Job) == "string" then
		for i = table.getn(simpleJobs), 1, -1 do
			if simpleJobs[i][1] == _Job then
				erLaeuft = true
			end
		end
		for i = table.getn(simpleHiResJobs), 1, -1 do
			if simpleHiResJobs[i][1] == _Job then
				erLaeuft = true
			end
		end
		for i = table.getn(simpleHiHiResJobs), 1, -1 do
			if simpleHiHiResJobs[i][1] == _Job then
				erLaeuft = true
			end
		end
	else
		assert(false, "Job ist nicht richtig angegeben. Er ist: ".. type(_Job))
	end
	return erLaeuft
end

function UeberwacheJobs()
	if deleteAllJobs then
		deleteAllJobs = false
		simpleJobs = {}
		simpleHiResJobs = {}
		simpleHiHiResJobs = {}
	end
	for i = table.getn(simpleJobsAnwaerter), 1, -1 do
		table.insert(simpleJobs,{simpleJobsAnwaerter[i][1],simpleJobsAnwaerter[i][2]})
		table.remove(simpleJobsAnwaerter,i)
	end
	for i = table.getn(simpleHiResJobsAnwaerter), 1, -1 do
		table.insert(simpleHiResJobs,{simpleHiResJobsAnwaerter[i][1],simpleHiResJobsAnwaerter[i][2]})
		table.remove(simpleHiResJobsAnwaerter,i)
	end
	for i = table.getn(simpleHiHiResJobsAnwaerter), 1, -1 do
		table.insert(simpleHiHiResJobs,{simpleHiHiResJobsAnwaerter[i][1],simpleHiHiResJobsAnwaerter[i][2]})
		table.remove(simpleHiHiResJobsAnwaerter,i)
	end
	local pruefZeit = SDL_GetTicks()
	if pruefZeit >= myTime.JobZeit + 1000 then
		if gcinfo() > 1000 then
			collectgarbage ()
		end
		for i = table.getn(simpleJobs),1, -1 do
			if  _G[simpleJobs[i][1]]() then
				table.remove(simpleJobs,i)
			end
		end
		myTime.JobZeit = SDL_GetTicks()
	end
	if pruefZeit >= myTime.HiResJobZeit + 100 then
		for i = table.getn(simpleHiResJobs), 1, -1 do
			if _G[simpleHiResJobs[i][1]]() then
				table.remove(simpleHiResJobs,i)
			end
		end
		myTime.HiResJobZeit = SDL_GetTicks()
	end
	if pruefZeit >= myTime.HiHiResJobZeit + 20 then
		for i = table.getn(simpleHiHiResJobs), 1, -1 do
			if _G[simpleHiHiResJobs[i][1]]() then
				table.remove(simpleHiHiResJobs,i)
			end
		end
		myTime.HiHiResJobZeit = SDL_GetTicks()
	end
end

function EndJob(_Job) -- geht auch anders : if type(_Job) == "number" then i2 = 2 
	if type(_Job) == "number" then
		for i = table.getn(simpleJobs), 1, -1 do
			if simpleJobs[i][2] == _Job then
				table.remove(simpleJobs,i)
				return
			end
		end
		for i = table.getn(simpleHiResJobs), 1, -1 do
			if simpleHiResJobs[i][2] == _Job then
				table.remove(simpleHiResJobs,i)
				return
			end
		end
		for i = table.getn(simpleHiHiResJobs), 1, -1 do
			if simpleHiHiResJobs[i][2] == _Job then
				table.remove(simpleHiHiResJobs,i)
				return
			end
		end
	elseif type(_Job) == "string" then
		for i = table.getn(simpleJobs), 1, -1 do
			if simpleJobs[i][1] == _Job then
				table.remove(simpleJobs,i)
				return
			end
		end
		for i = table.getn(simpleHiResJobs), 1, -1 do
			if simpleHiResJobs[i][1] == _Job then
				table.remove(simpleHiResJobs,i)
				return
			end
		end
		for i = table.getn(simpleHiHiResJobs), 1, -1 do
			if simpleHiHiResJobs[i][1] == _Job then
				table.remove(simpleHiHiResJobs,i)
				return
			end
		end
	end
end

function EndAllJobs()
	deleteAllJobs = true
end

function GetNextID()
	myJobIDs = myJobIDs +1
	return myJobIDs
end

function Gehe(_oldPosX,_oldPosY,_posX,_posY,_bitMap)
	ka = SDL.Rect( _oldPosX-11,_oldPosY-10 )
	SDL.BlitSurface( bitmapIchLeer, nil, screen, ka ) 
	ka = SDL.Rect( _posX-11,_posY-10 )
	SDL.BlitSurface( bitmapIch, nil, screen, ka ) 
	SDL_Flip(screen)
end

function AddierePunkte()
	if punktTable[myPos.X][myPos.Y].sichtBar then
		if (myPos.X == 1 and myPos.Y == 3 ) or (myPos.X == 26 and myPos.Y == 3 ) 
		    or (myPos.X == 1 and myPos.Y == 23 ) or (myPos.X == 26 and myPos.Y == 23 ) then
			for i = 1,4 do
				geister[i].bitmap = geister.blau
				scharf = false
			end
			StartCountDown(15,FaerbeGeister)
		else
			punkteStand = punkteStand + 1
		end
		punktTable[myPos.X][myPos.Y].sichtBar = false
	end
end

function GeheLinks()
	if myPos.X > 1 and not punktTable[myPos.X-1][myPos.Y].gesperrt then
		bitmapIch=bitmapPlayerLinks
		Gehe(punktTable[myPos.X][myPos.Y].X,punktTable[myPos.X][myPos.Y].Y,punktTable[myPos.X-1][myPos.Y].X,punktTable[myPos.X][myPos.Y].Y)
		myPos.X = myPos.X - 1
		AddierePunkte()
	elseif myPos.X == 1 and myPos.Y == 14 then
		Gehe(punktTable[1][14].X,punktTable[1][14].Y,punktTable[26][14].X,punktTable[26][14].Y) -- ist in der Sackgasse
		myPos.X = 26
		AddierePunkte()
	end
end

function GeheRechts()
	if myPos.X < 26 and not punktTable[myPos.X+1][myPos.Y].gesperrt then
		bitmapIch=bitmapPlayerRechts
		Gehe(punktTable[myPos.X][myPos.Y].X,punktTable[myPos.X][myPos.Y].Y,punktTable[myPos.X+1][myPos.Y].X,punktTable[myPos.X][myPos.Y].Y)
		myPos.X = myPos.X + 1
		AddierePunkte()
	elseif myPos.X == 26 and myPos.Y == 14 then
		Gehe(punktTable[26][14].X,punktTable[26][14].Y,punktTable[1][14].X,punktTable[1][14].Y) -- ist in der Sackgasse
		myPos.X = 1
		AddierePunkte()
	end
end

function GeheRunter()
	if myPos.Y < 29 and not punktTable[myPos.X][myPos.Y+1].gesperrt then
		bitmapIch=bitmapPlayerUnten
		Gehe(punktTable[myPos.X][myPos.Y].X,punktTable[myPos.X][myPos.Y].Y,punktTable[myPos.X][myPos.Y].X,punktTable[myPos.X][myPos.Y+1].Y)
		myPos.Y = myPos.Y + 1
		AddierePunkte()
	end
end

function GeheHoch()
	if myPos.Y > 1 and not punktTable[myPos.X][myPos.Y-1].gesperrt then
		bitmapIch=bitmapPlayerOben
		Gehe(punktTable[myPos.X][myPos.Y].X,punktTable[myPos.X][myPos.Y].Y,punktTable[myPos.X][myPos.Y].X,punktTable[myPos.X][myPos.Y-1].Y)
		myPos.Y = myPos.Y - 1
		AddierePunkte()
	end
end

function NichtMoeglich(_posX,_posY)
	return punktTable[_posX][_posY].gesperrt
end

function TanzeGeister()
	if 	zG < geistTanzOffset + 2 then
		ka = SDL.Rect( 250, 230 - geistOffSet, 23, 23)
		SDL.BlitSurface( bitmapIchLeer, nil, screen, ka ) 
	end
	if 	zG < geistTanzOffset + 23 then
		ka = SDL.Rect( 225, 215 + geistOffSet, 23, 23 )
		SDL.BlitSurface( bitmapIchLeer, nil, screen, ka )
	end
	if 	zG < geistTanzOffset + 42 then
		ka = SDL.Rect( 275, 215 + geistOffSet, 23, 23 )
		SDL.BlitSurface( bitmapIchLeer, nil, screen, ka ) 
	end
	if geistOffSet == 15 then
		geistOffSet=0
	else
		geistOffSet=15
	end
	if zG < geistTanzOffset + 1 then
		ka = SDL.Rect( 250, 230 - geistOffSet, 23, 23)
		SDL.BlitSurface( geister[2].bitmap, nil, screen, ka )
	elseif zG == geistTanzOffset + 2 then
		ka = SDL.Rect( 250, 200, 23, 23)
		SDL.BlitSurface( bitmapIchLeer, nil, screen, ka )
		ka = SDL.Rect( 250, 200, 23, 23)
		SDL.BlitSurface( geister[2].bitmap, nil, screen, ka )
	elseif zG == geistTanzOffset + 3 then
		ka = SDL.Rect( 250, 200, 23, 23)
		SDL.BlitSurface( bitmapIchLeer, nil, screen, ka )
		ka = SDL.Rect( 250, 190, 23, 23)
		SDL.BlitSurface( geister[2].bitmap, nil, screen, ka )
	elseif zG == geistTanzOffset + 4 then
		ka = SDL.Rect( 250, 190, 23, 23)
		SDL.BlitSurface( bitmapIchLeer, nil, screen, ka )
		ka = SDL.Rect( 250, 180, 23, 23)
		SDL.BlitSurface( geister[2].bitmap, nil, screen, ka )
		-- Tor schließen
		ka = SDL.Rect( 245,205 )
		SDL.BlitSurface( bitmapTor, nil, screen, ka ) 
		--jetzt rausschicken
	elseif zG == geistTanzOffset + 5 then
		ka = SDL.Rect( 250, 180, 23, 23)
		SDL.BlitSurface( bitmapIchLeer, nil, screen, ka )
		geister[2].frei = true
	end	
	if 	zG < geistTanzOffset +22 then
		ka = SDL.Rect( 225, 215 + geistOffSet, 23, 23 )
		SDL.BlitSurface( geister[3].bitmap, nil, screen, ka ) 
	elseif zG == geistTanzOffset + 23 then
		ka = SDL.Rect( 250, 200, 23, 23)
		SDL.BlitSurface( bitmapIchLeer, nil, screen, ka )
		ka = SDL.Rect( 250, 200, 23, 23)
		SDL.BlitSurface( geister[3].bitmap, nil, screen, ka )
	elseif zG == geistTanzOffset + 24 then
		ka = SDL.Rect( 250, 200, 23, 23)
		SDL.BlitSurface( bitmapIchLeer, nil, screen, ka )
		ka = SDL.Rect( 250, 190, 23, 23)
		SDL.BlitSurface( geister[3].bitmap, nil, screen, ka )
	elseif zG == geistTanzOffset + 25 then
		ka = SDL.Rect( 250, 190, 23, 23)
		SDL.BlitSurface( bitmapIchLeer, nil, screen, ka )
		ka = SDL.Rect( 250, 180, 23, 23)
		SDL.BlitSurface( geister[3].bitmap, nil, screen, ka )
		-- Tor schließen
		ka = SDL.Rect( 245,205 )
		SDL.BlitSurface( bitmapTor, nil, screen, ka ) 
		--jetzt rausschicken
	elseif zG == geistTanzOffset + 26 then
		ka = SDL.Rect( 250, 180, 23, 23)
		SDL.BlitSurface( bitmapIchLeer, nil, screen, ka )
		geister[3].frei = true
	end
	if 	zG < geistTanzOffset +41 then
		ka = SDL.Rect( 275, 215 + geistOffSet, 23, 23 )
		SDL.BlitSurface( geister[4].bitmap, nil, screen, ka ) 
	elseif zG == geistTanzOffset + 42 then
		ka = SDL.Rect( 250, 200, 23, 23)
		SDL.BlitSurface( bitmapIchLeer, nil, screen, ka )
		ka = SDL.Rect( 250, 200, 23, 23)
		SDL.BlitSurface( geister[4].bitmap, nil, screen, ka )
	elseif zG == geistTanzOffset + 43 then
		ka = SDL.Rect( 250, 200, 23, 23)
		SDL.BlitSurface( bitmapIchLeer, nil, screen, ka )
		ka = SDL.Rect( 250, 190, 23, 23)
		SDL.BlitSurface( geister[4].bitmap, nil, screen, ka )
	elseif zG == geistTanzOffset + 44 then
		ka = SDL.Rect( 250, 190, 23, 23)
		SDL.BlitSurface( bitmapIchLeer, nil, screen, ka )
		ka = SDL.Rect( 250, 180, 23, 43)
		SDL.BlitSurface( geister[4].bitmap, nil, screen, ka )
		-- Tor schließen
		ka = SDL.Rect( 245,205 )
		SDL.BlitSurface( bitmapTor, nil, screen, ka ) 
		--jetzt rausschicken
	elseif zG == geistTanzOffset + 45 then
		ka = SDL.Rect( 250, 180, 23, 23)
		SDL.BlitSurface( bitmapIchLeer, nil, screen, ka )
		geister[4].frei = true
		-- alle raus, also funktion beenden
		zG = 0 -- fürs nächste mal
		return true
	end
	zG=zG+1
	SDL_Flip(screen)
end

function NeuePos(_geist)
	local currPosX, currPosY = geister[_geist].posX ,geister[_geist].posY
	local richtung -- 1 = links, 2= oben ,  3 = rechts, 4 = unten
	repeat
		if not scharf then
			richtung = math.random(4)
		else
			istGut = false
			repeat
				richtung = math.random(4)
				if geister[_geist].haengtFest then
					istGut = true
				else
					if (myPos.X >= currPosX) and (richtung == 3) then
						istGut = true
					elseif (myPos.X <= currPosX) and (richtung == 1) then
						istGut = true
					elseif (myPos.Y >= currPosY) and (richtung == 4) then
						istGut = true
					elseif (myPos.Y <= currPosY) and (richtung == 2) then
						istGut = true
					end
				end	
			until istGut == true
		end
		if richtung == 1 then
			if currPosX > 1 then
				if NichtMoeglich(currPosX - 1,currPosY) then
								geister[_geist].haengtFest = true
					richtung = 0 -- versuche noch mal
				else
					-- nächste Kreuzung suchen
					for i = currPosX - 1, 1,-1 do
						if currPosY > 1 then
							if currPosY < 29 then
								if (not NichtMoeglich(i,currPosY + 1)) or (not NichtMoeglich(i,currPosY - 1)) then
									geister[_geist].haengtFest = false
									return i, currPosY
								end
							else
								if not NichtMoeglich(i,currPosY - 1) then
									geister[_geist].haengtFest = false
									return i, currPosY
								end
							end
						else
							if not NichtMoeglich(i,currPosY + 1) then
								geister[_geist].haengtFest = false
								return i, currPosY
							end
						end
					end
				end
			else
				richtung = 0
				geister[_geist].haengtFest = true
			end
		elseif richtung == 2 then
			if currPosY > 1 then
				if NichtMoeglich(currPosX,currPosY - 1) then
								geister[_geist].haengtFest = true
					richtung = 0 -- versuche noch mal
				else
					-- nächste Kreuzung suchen
					for i = currPosY - 1, 1, -1 do
						if currPosX > 1 then
							if currPosX < 26 then
								if (not NichtMoeglich(currPosX + 1, i)) or (not NichtMoeglich(currPosX - 1, i)) then
									geister[_geist].haengtFest = false
									return  currPosX, i
								end
							else
								if not NichtMoeglich(currPosX - 1, i) then
									geister[_geist].haengtFest = false
									return  currPosX, i
								end
							end
						else
							if (not NichtMoeglich(currPosX + 1, i))  then
								geister[_geist].haengtFest = false
								return  currPosX, i
							end
						end
					end
				end
			else
				richtung = 0
				geister[_geist].haengtFest = true
			end
		elseif richtung == 3 then
			if currPosX < 26 then
				if NichtMoeglich(currPosX + 1, currPosY) then
								geister[_geist].haengtFest = true
					richtung = 0 -- versuche noch mal
				else
					-- nächste Kreuzung suchen
					for i = currPosX + 1, 26 do
						if currPosY > 1 then
							if currPosY < 29 then
								if (not NichtMoeglich(i, currPosY + 1)) or (not NichtMoeglich(i,currPosY - 1)) then
									geister[_geist].haengtFest = false
									return i, currPosY
								end
							else
								if not NichtMoeglich(i, currPosY - 1) then
									geister[_geist].haengtFest = false
									return i, currPosY
								end
							end
						else
							if  not NichtMoeglich(i, currPosY + 1) then
								geister[_geist].haengtFest = false
								return i, currPosY
							end
						end
					end
				end
			else
				richtung = 0
				geister[_geist].haengtFest = true
			end
		elseif richtung == 4 then
			if currPosY < 29 then
				if NichtMoeglich(currPosX,currPosY + 1) then
								geister[_geist].haengtFest = true
					richtung = 0 -- versuche noch mal
				else
					-- nächste Kreuzung suchen
					for i = currPosY + 1, 29 do
						if currPosX > 1 then
							if currPosX < 26 then
								if (not NichtMoeglich(currPosX + 1, i)) or (not NichtMoeglich(currPosX - 1,i)) then
									geister[_geist].haengtFest = false
									return  currPosX, i
								end
							else
								if not NichtMoeglich(currPosX - 1, i) then
									geister[_geist].haengtFest = false
									return  currPosX, i
								end
							end
						else
							if (not NichtMoeglich(currPosX + 1, i)) then
								geister[_geist].haengtFest = false
								return  currPosX, i
							end
						end
					end
				end
			else
				richtung = 0
				geister[_geist].haengtFest = true
			end
		end
	until richtung ~= 0
	-- kommt er nach hier, dann ist er rechts oder links vom Durchgang und hat den Auftrag da zu suchen
	if currPosX == 6 then  -- schicken wir ihn hinein
	geister[_geist].haengtFest = false
		return 1, currPosY 
	else
	geister[_geist].haengtFest = false
		return 26, currPosY 
	end
end

function StarteNeu()
	keyBoardFrei = false
	EndAllJobs()
	EndAllCounter()
	StartCountDown(2,StarteNeu2)
	InitGeister()
	ZeichneBildschirm()
	if leben == 3 then
		ka = SDL.Rect( 355,498, 23, 23 )
		SDL.BlitSurface( bitmapIch, nil, screen, ka ) 
		ka = SDL.Rect( 330,498 , 23, 23)
		SDL.BlitSurface( bitmapIch, nil, screen, ka ) 
	elseif leben == 2 then
		ka = SDL.Rect( 330,498 , 23, 23)
		SDL.BlitSurface( bitmapIch, nil, screen, ka ) 
		ka = SDL.Rect( 355,498, 23, 23 )
		SDL.BlitSurface( bitmapIchLeer, nil, screen, ka ) 
	elseif leben == 1 then
		ka = SDL.Rect( 355,498, 23, 23 )
		SDL.BlitSurface( bitmapIchLeer, nil, screen, ka ) 
		ka = SDL.Rect( 330,498 , 23, 23)
		SDL.BlitSurface( bitmapIchLeer, nil, screen, ka ) 
	else
		gameOver = true
		EndAllCounter()
		EndAllJobs()
		ka = SDL.Rect( 148,138 )
		SDL.BlitSurface( bitmapGameOver, nil, screen, ka ) 
		SDL_Flip(screen)
		return
	end
	ZeichnePunkte()
	SDL_Flip(screen)
	leben = leben - 1
	zG = 0
	if IsJobRunning("TanzeGeister") then
		EndJob("TanzeGeister")
	end
	StartSimpleHiResJob("TanzeGeister")
end

function StarteNeu2()
	keyBoardFrei = true
	geisterJobID = StartSimpleHiResJob("UeberwacheGeister")
end

function StartCountDown( _Limit, _Callback, _Show )
	local entry = {}
	entry.limit = _Limit
	entry.beginn = SDL_GetTicks()
	entry.show = _Show
	entry.ID = GetNextID()
	if type(_Callback) == "function" then
		entry.callBack = _Callback
	elseif type(_G[_Callback]) == "function" then
		entry.callBack = _G[_Callback]
	else
		-- unsinn daher Error
		assert (false, "Callback vom Counter ist keine Funktion")
	end
	table.insert (CounterTableAnwaerter,entry)
	return entry.ID
end

function EndAllCounter()
	deleteAllCounter = true
end

function UeberWacheCounter()
	if deleteAllCounter then
		deleteAllCounter = false
		CounterTable={}
	end
	for i =  table.getn(CounterTableAnwaerter) , 1, -1 do
		table.insert(CounterTable,CounterTableAnwaerter[i])
		table.remove(CounterTableAnwaerter,i)
	end
	local istZeit = SDL_GetTicks()
	for i =  table.getn(CounterTable) , 1, -1 do
		if CounterTable[i].beginn + CounterTable[i].limit * 1000 <= istZeit then -- Zeit ist erreicht
			CounterTable[i].callBack() -- funktion ausführen
			table.remove(CounterTable,i) -- aus dem Table streichen
		end
	end
end

function BewegeGeist(_geist)
	local oldPosX, oldPosY = geister[_geist].posX, geister[_geist].posY
	if (myPos.X >= oldPosX-1 and myPos.X <= oldPosX + 1) and (myPos.Y >= oldPosY - 1 and myPos.Y <= oldPosY + 1) then
		if scharf then
			EndAllCounter()
			EndAllJobs()
			StarteNeu()
			return
		else
			geister[_geist].bitmap = geister.augen
			if not geister[_geist].getroffen then
				if geistGetroffen == 0 then
					geistGetroffen = 1
					punkteStand = punkteStand + 200
				elseif geistGetroffen == 1 then
					punkteStand = punkteStand + 400
					geistGetroffen = 2
				elseif geistGetroffen == 2 then
					punkteStand = punkteStand + 800
					geistGetroffen = 3
				elseif geistGetroffen == 3 then
					punkteStand = punkteStand + 1600
				end
			geister[_geist].getroffen = true
			end
		end
		-- getroffen
	end
	if geister[_geist].posX == geister[_geist].neuX and geister[_geist].posY == geister[_geist].neuY then
		-- am Ziel angekommen
		geister[_geist].neuX,geister[_geist].neuY = NeuePos(_geist)
	end
	if geister[_geist].posX > geister[_geist].neuX then
		GeistGeheLinks(_geist)
	elseif geister[_geist].posX < geister[_geist].neuX then
		GeistGeheRechts(_geist)
	elseif geister[_geist].posY > geister[_geist].neuY then
		GeistGeheHoch(_geist)
	elseif geister[_geist].posY < geister[_geist].neuY then
		GeistGeheRunter(_geist)
	end
	ZeichneGeist(_geist, oldPosX, oldPosY)
end

function GeistGeheLinks(_geist)
	geister[_geist].posX = geister[_geist].posX - 1
end

function GeistGeheRechts(_geist)
	geister[_geist].posX = geister[_geist].posX + 1
end

function GeistGeheHoch(_geist)
	geister[_geist].posY = geister[_geist].posY - 1
end

function GeistGeheRunter(_geist)
	geister[_geist].posY = geister[_geist].posY + 1
end

function ZeichneGeist(_geist, _oldPosX, _oldPosY)
	local newPosX, newPosY = geister[_geist].posX, geister[_geist].posY
	local newPunktPosX = punktTable[newPosX][newPosY].X
	local newPunktPosY = punktTable[newPosX][newPosY].Y
	local oldPunktPosX = punktTable[_oldPosX][_oldPosY].X
	local oldPunktPosY = punktTable[_oldPosX][_oldPosY].Y
	ka = SDL.Rect( oldPunktPosX-11,oldPunktPosY-10,23,23 )
	if punktTable[_oldPosX][_oldPosY].sichtBar then
		SDL.BlitSurface( punktTable[_oldPosX][_oldPosY].bitMap, nil, screen, ka ) 
	else
		SDL.BlitSurface( bitmapIchLeer, nil, screen, ka ) 
	end
	ka = SDL.Rect( newPunktPosX-11,newPunktPosY-10, 23, 23 )
	SDL.BlitSurface( geister[_geist].bitmap, nil, screen, ka ) 
	if punktTable[1][3].sichtBar then
		ka = SDL.Rect( punktTable[1][3].X-11,punktTable[1][3].Y-10, 23, 23 )
		SDL.BlitSurface( punktTable[1][3].bitMap, nil, screen, ka ) 
	end
	if punktTable[26][3].sichtBar then
		ka = SDL.Rect( punktTable[26][3].X-11,punktTable[1][3].Y-10, 23, 23 )
		SDL.BlitSurface( punktTable[26][3].bitMap, nil, screen, ka ) 
	end
	if punktTable[1][23].sichtBar then
		ka = SDL.Rect( punktTable[1][23].X-11,punktTable[1][3].Y-10, 23, 23 )
		SDL.BlitSurface( punktTable[1][23].bitMap, nil, screen, ka ) 
	end
	if punktTable[26][23].sichtBar then
		ka = SDL.Rect( punktTable[26][23].X-11,punktTable[1][3].Y-10, 23, 23 )
		SDL.BlitSurface( punktTable[26][23].bitMap, nil, screen, ka ) 
	end
	ZeichnePunkte()
	SDL_Flip(screen)
end

function InitVariables()
	math.randomseed(os.time()) -- damit es auch wirklich zufällig ist
	stopUeberwachung = false
	beginn=os.time()
	neu = false	
	scharf = true
	gameOver = false
	offestX=75
	offsetY=39
	CounterTable = {}
	punktTable={}
	haengtFest = false
	for x = 1,26 do
		punktTable[x]={}
		for y = 1, 29 do
			punktTable[x][y]={X=offestX+(x-1)*15, Y=offsetY+(y-1)*15,gesperrt=false,bitMap=bitmapPkl
							,w=23,h=23,sichtBar=true}
		end
	end
	zG = 0
	deleteAllJobs = false
	deleteAllCounter = false
	geistTanzOffset=30
	zaehler=0
	myTime={}
	myTime.beginnZeit = SDL_GetTicks()
	myTime.JobZeit = SDL_GetTicks()
	myTime.HiResJobZeit = SDL_GetTicks()
	myTime.HiHiResJobZeit = SDL_GetTicks()
	myPos = {X = 13, Y = 29}
	leben = 3
	punkteStand=0
	geistGetroffen=0
	geistOffSet=0
	simpleJobs = {}
	simpleHiResJobs = {}
	simpleHiHiResJobs = {}
	simpleJobsAnwaerter = {}
	simpleHiResJobsAnwaerter = {}
	simpleHiHiResJobsAnwaerter = {}
	CounterTableAnwaerter ={}
	Stop=true
	myJobIDs= 0
	m={}
end	

function UeberwacheGeister()
	for i = 1,4 do
		if geister[i].frei then
			BewegeGeist(i)
		end
	end
end

function StarteSpiel()
	InitBitmaps()
	InitVariables()
	SperreAlleInseln()
	StarteNeu()
	Manager()
	if neu then
		neu = false
		return StarteSpiel()
	end
end

function Manager()
	Stop=true
	while Stop do
		if not gameOver then
			UeberwacheJobs()
			UeberWacheCounter()
		end
		SDL_framerateDelay(myFrameRate)
		while SDL.PollEvent(event) do 
			if event.type == SDL_KEYDOWN then
				local sym = event.key.keysym.sym
				if sym == SDLK_q or sym == SDLK_ESCAPE then
					Stop = false
					break;
				elseif sym == SDLK_LEFT and keyBoardFrei then 
					GeheLinks()
				elseif sym == SDLK_RIGHT and keyBoardFrei then 
					GeheRechts()
				elseif sym == SDLK_DOWN and keyBoardFrei then 
					GeheRunter()
				elseif sym == SDLK_UP and keyBoardFrei then 
					GeheHoch()
				elseif sym == SDLK_n and gameOver then   
					neu = true
					Stop = false
					break;
				elseif sym == SDLK_s then   -- take a screenshot...
					screen:SaveBMP( "SCREENSHOT.bmp" )
				end
			elseif event.type == SDL_MOUSEBUTTONDOWN then
				m.buttons, m.x, m.y = SDL_GetMouseState(0, 0)
				if gameOver then
					if m.x > 207 and m.x < 326 and m.y > 264 and m.y < 278 then -- Spieler hat auf neu gedrückt
						neu = true
						Stop = false
						break;
					elseif m.x > 197 and m.x < 281 and m.y > 299 and m.y < 312 then -- Spieler hat auf Escape
						Stop = false
			            break;	
					end
				end
				print(m.x.."Down"..m.y)  -- um die Bildschirmposition zu wissen beim testen.
			elseif event.type == SDL_QUIT then
				Stop = false
	            break;	
			end
		end	
	end
end

StarteSpiel()