Ms BlitzMan translated to PB

Advanced game related topics
User avatar
Psychophanta
Addict
Addict
Posts: 4968
Joined: Wed Jun 11, 2003 9:33 pm
Location: Lípetsk, Russian Federation
Contact:

Ms BlitzMan translated to PB

Post by Psychophanta »

Get the original Ms BlitzMan from:
http://www.incitti.com/Blitz/

Just put this code inside the same dir and run it.

To run windowed mode just create a direct access -W as program parameter (just the same as the blitz version).

Notice: not tested the joystick mode. Modify as your taste. Enjoy.

Code: Select all

;AppTitle "Ms BlitzMan"
; Ms BlitzMan  Version 1.31
; Mark Incitti,  September 2000/June 2001
; mark@incitti.com
; June 11, 2001 - updated sound commands
; June 24, 2001 - more sound tweaks
; Dec  16, 2002 - bouncing pause letters
; 				- line pause - L key to toggle
; Feb 23, 2004  - vwait and flip false added, windowed mode

;TRANSLATED TO PureBasic BY PSYCHOPHANTA (15 JANUARY 2018)

Enumeration
; you can change these
#invincible=0		; 0 normal, change to 1 for invincible *cheat*
#numprizes=3		; (1,2,3...) Usually 2 or 3
#prizeontime=511	; (127,255,511, or 1023) -power of 2 -1, Usually 511
#MAXEXSPEED=198	; (20-198) amount of zoom time
#PRIZEEXSPEED=75	; (0-200) extra zoom time from eating prize
#speedkey=#PB_Key_Space		; zoom key 57=SPACE
#speedkeyjoy=1		; zoom key Button 1 on joypad
#pausekey=#PB_Key_Pause;25		; pause key - 25=P
#skiplevkey=#PB_Key_F5		; 0,63 to skip levels with F5 *cheat* 
#eyespeed=32		; (1-32) 32 is 2 pixels per frame (eyes move 2X per frame)
#prizespeed=15		; (1-32)
#pointtime=110		; Length of time(# of frames) points are displayed
#dtime=12			; (8, 16, 32) 60 frames/second  = 1000/60  = ~16

; but don't change these
#gdsz=10		; block spacing
#numbrds=100	; number of boards/prizes
#mapwidth=23	; number of tiles wide
#mapheight=21	; number of tiles high
#cagex=11		; location of cage gate x
#cagey=8		; location of cage gate y
#screenw=320	; screen width
#screenh=240	; screen height
#M_XOFF=45		; center the board horizontally

;game states
#dyingmode		=0
#getreadymode	=1
#playingmode	=2
#gameovermode	=3
#creditsmode	=4
#startmode		=5
#donemode		=6
#nextboardmode	=7
#pausemode		=8

;ghost states
#edible=1
#deadly=2
#eyes=3

;ghost anim frame offsets
#frmgb = 48	; blue
#frmgw = 50	; white
#frmge = 52	; eyes
EndEnumeration
Global score.l,highscore.l,startinglevel.l
Global timer.l,board.l,gmode.l,keyorjoy.l,lastboard.l,sklevel.l=1
Global restorezoom.l    ;restore zoom after death, 1=true
Global freeman.l        ;every XXXXX points get a free pac

Structure ghost
	id.l       ; id number (0-5)
	act.l      ; activity - #edible, #deadly, or #eyes
	bx.l
	by.l       ; big x,y  32*screen pos
	sx.l
	sy.l       ; screen   bx/32, by/32
	x.l
	y.l        ; x,y map coords sx,sy/#gdsz
	vx.l
	vy.l       ; velocity  0-32?  
	gspeed.l   ; vel magnitude
	bluetimer.l; #edible time
	frm.l      ; anim frame
	frmcnt.l   ; anim frm counter
	cage.l     ; flag
	intunnel.l ; flag  0-not in, 1 = u/d, -1 = l/r
	cagetimer.l; time in cage
	changed.l  ; tics since last changed direction
EndStructure
Global NewList g.ghost()
Structure pacman
	bx.l
	by.l       ; big x,y  32*screen pos
	sx.l
	sy.l       ; screen   bx/32, by/32
	x.l
	y.l        ; x,y map coords sx,sy/#gdsz
	vx.l
	vy.l       ; velocity  0-32 ,0-32
	cx.l
	cy.l       ; character x y
	frm.l      ; anim frame
	frmcnt.l   ; frm counter
	intunnel.l ; flag 0,1,-1
EndStructure
Global NewList pac.pacman()
Structure prizetype
	bx.l
	by.l       ; big x,y  0-10230 ,0-6400
	sx.l
	sy.l       ; screen   bx/32, by/32
	x.l
	y.l        ; x,y map coords sx/16,sy/16
	vx.l
	vy.l       ; velocity  0-32 ,0-32
	cx.l
	cy.l       ; character x y
	cage.l     ; flag 0,1
	frm.l      ; anim frame - only 1 frame
	frmcnt.l   ; frm counter - not used
	intunnel.l ; flag 0,1,-1
	bouncedir.l; +/- 1
	bouncehgt.l; 0 to -8
	points.l   ; 100,200,...10000  
EndStructure
Global NewList prize.prizetype()
Structure pointstype
	v.l		; time on screen counter 
	x.l
	y.l
	frm.l
EndStructure
Global NewList pts.pointstype()
; color type for palette changes
Structure rgb
	col.l  	; color 0-7, 4-r, 2-g, 1-b
	x.l:y.l
EndStructure

Global Dim currentmap.a(#mapwidth,#mapheight)		; the current map
Global Dim mapopen(#mapwidth,#mapheight)		; bitsum of the u/d/l/r bits of the current map
Global Dim maps.a(#mapwidth,#mapheight,#numbrds)	; all the maps
Global Dim prizepoints(#numbrds)		; points awarded for each prize
Global Dim coltable(7,3,#numbrds)		; 7 colors, r,g,orb, 100 palettes
Global Dim gkol(6,3)				; 6 ghosts * rgb for each
Global NewList c.rgb	()			; for ploting the map blocks in new colors
Declare FlushKeys()
Declare GetPalettes()
Declare PaletteSwitch()
Declare Createghosts(num.l)
Restore points
For t = 0 To #numbrds-1
  Read.l p:prizepoints(t)=p*10
Next
DataSection
points:
Data.l 10  ,20  ,50  ,70  ,100
Data.l 200 ,500 ,300 ,200 ,100
Data.l 110 ,120 ,130 ,140 ,150
Data.l 160 ,170 ,180 ,190 ,200
Data.l 210 ,220 ,230 ,240 ,250
Data.l 260 ,270 ,280 ,290 ,300
Data.l 310 ,320 ,330 ,340 ,350
Data.l 360 ,370 ,380 ,390 ,400
Data.l 410 ,420 ,430 ,440 ,450
Data.l 460 ,470 ,480 ,490 ,500
Data.l 510 ,520 ,530 ,540 ,550
Data.l 560 ,570 ,580 ,590 ,600
Data.l 610 ,620 ,630 ,640 ,650
Data.l 660 ,670 ,680 ,690 ,700
Data.l 710 ,720 ,730 ,740 ,750
Data.l 760 ,770 ,780 ,790 ,800
Data.l 810 ,820 ,830 ,840 ,850
Data.l 860 ,870 ,880 ,890 ,900
Data.l 910 ,920 ,930 ,940 ,950
Data.l 960 ,970 ,980 ,990 ,1000
EndDataSection

RandomSeed(ElapsedMilliseconds())	; reset the random number generator to random start

AddElement(pac())
AddElement(prize())

; set up the screen
Global windowed.b=0
InitSprite():InitKeyboard():InitSound()
If LCase(ProgramParameter())="-w"
  windowed.b=1:OpenWindowedScreen(OpenWindow(0,240,180,#screenw,#screenh,"Ms BlitzMan",#PB_Window_ScreenCentered|#PB_Window_MinimizeGadget|#PB_Window_SystemMenu|#PB_Window_TitleBar),0,0,#screenw,#screenh,1,0,0)
Else
  OpenScreen(#screenw,#screenh,32,"Ms BlitzMan")
EndIf

; display booting up message
LoadFont (0, "Courier",8)            ; Load Courrier Font, Size 15
StartDrawing(ScreenOutput())
FrontColor(RGB(255,200,200))
DrawingFont(FontID(0))
DrawText(40,100,"MsBlitzMan Version 1.31")
DrawText(40,115,"Programmed in BlitzBasicPC")
DrawText(40,130,"By Mark incitti (2001)")
StopDrawing()
FlipBuffers()
If windowed:For tt.i=1 To 100:If WindowEvent()=#PB_Event_CloseWindow:End:EndIf:Delay(20):Next
Else:Delay(2000)
EndIf
Macro LoadAnimImage(name,imagen,w,h,first,amount)
  Dim name#(amount#-1)
  preservescreen.i=GrabSprite(#PB_Any,0,0,#screenw,#screenh)
  ii.i=LoadSprite(#PB_Any,imagen#)
  DisplaySprite(ii,0,0)
  i.l=SpriteWidth(ii.i)/w#
  For tt=0 To amount#-1
    name#(tt)=GrabSprite(#PB_Any,(first#+tt)%i*w#,(first#+tt)/i*h#,w#,h#)
  Next
  DisplaySprite(preservescreen,0,0)
  FreeSprite(preservescreen)
  FreeSprite(ii.i)
EndMacro
Procedure.i miGrabimage(ima.i,x.u,y.u,w.u,h.u)
  Protected res.i,preservescreen.i=GrabSprite(#PB_Any,0,0,#screenw,#screenh)
  DisplaySprite(ima,0,0)
  res=GrabSprite(#PB_Any,x,y,w,h)
  DisplaySprite(preservescreen,0,0)
  FreeSprite(preservescreen)
  ProcedureReturn res
EndProcedure
; load in the graphics
Global LoadAnimImage(ghostimages,"images/ghosts.bmp",16,16,0,56)	; rrlluudd*6, bbwwee
Global LoadAnimImage(pacimages,"images/pac.bmp",16,16,0,16)			; rrrllluuudddxxxx
Global LoadAnimImage(prizeimages,"images/prizes.bmp",16,16,0,100)	; cherries, strawberry,...
Global LoadAnimImage(blockimages,"images/blocks.bmp",16,16,0,5*13)	; rgb version of blocks
Global LoadAnimImage(pointimages,"images/points.bmp",16,16,0,106)	; 100,200,...9900,10000, 200,400,800,1600,3200,6400
Global miscimages=LoadSprite(#PB_Any,"images/misc.bmp")						; misc - game over, get ready, Ms.Blitzman, paused, zoom
Global LoadAnimImage(numberimages,"images/numbers.bmp",16,16,0,40)	; 0,1,2..8,9 in 4 different colors
Global paletteimg=LoadSprite(#PB_Any,"images/palette.bmp")					; 7 pixels(bg,dot,centre,,trim,,, )

; grab the individual images from the miscimage

Global gameoverimage=miGrabimage(miscimages,0,0,32,16)
Global getreadyimage=miGrabimage(miscimages,32,0,32,16)
Global mspacimage=miGrabimage(miscimages,0,64,96,48)
Global Dim pauseimage(5)
For tt=0 To 5
  pauseimage(tt)=miGrabimage(miscimages,2+tt*5,16,4,16)
Next
Global zoomimage=miGrabimage(miscimages,0,48,22,6)
Global bonusimage=miGrabimage(miscimages,32,16,32,16)
Global nobonusimage=miGrabimage(miscimages,64,0,32,16)
Global nopowerimage=miGrabimage(miscimages,0,32,32,16)
Global zoompowerimage=miGrabimage(miscimages,64,16,32,16)

; load in the sounds
Global sounddot = LoadSound(#PB_Any,"sounds/dot.wav" )
Global soundpower = LoadSound(#PB_Any,"sounds/pill.wav" )
Global soundprize = LoadSound(#PB_Any,"sounds/prize.wav" )
Global soundbounce = LoadSound(#PB_Any,"sounds/bounce.wav" )
Global sounddeath = LoadSound(#PB_Any,"sounds/death.wav" )
Global soundghost = LoadSound(#PB_Any,"sounds/ghost.wav" )
Global soundbonus = LoadSound(#PB_Any,"sounds/clap.wav" )
Global soundboarddone = LoadSound(#PB_Any,"sounds/clap.wav" )
Global soundgameover = LoadSound(#PB_Any,"sounds/over.wav" )
Global soundstartmusic = LoadSound(#PB_Any,"sounds/start.wav" )
Global sounddeadly = LoadSound(#PB_Any,"sounds/lp-hum.wav" )
Global soundeyes = LoadSound(#PB_Any,"sounds/lp-eyes.wav" )
Global soundblue = LoadSound(#PB_Any,"sounds/lp-blue.wav" )

Global chsounddeadly=PlaySound(sounddeadly,#PB_Sound_Loop|#PB_Sound_MultiChannel)
Global chsoundeyes=PlaySound(soundeyes,#PB_Sound_Loop|#PB_Sound_MultiChannel)
Global chsoundblue=PlaySound(soundblue,#PB_Sound_Loop|#PB_Sound_MultiChannel)

; load all the maps
Gosub loadmaps

; grab all the colored pixels from the block images
Gosub GetImageRGB

; fill coltable(7,3,100) with the color values from the palette image
GetPalettes()

bluesleft = 0
gmode = #creditsmode
keyorjoy = 0 	; keyboard=0, joystick=1 
highscore = 0 
lastboard = 24	; start from level 1 to 25
timer=0
Global Dim pausex.f(10),Dim pausey.f(10),Dim driftx.f(10),Dim drifty.f(10)

innerloop:
  ExamineKeyboard()
  If KeyboardReleased(#PB_Key_Escape) Or (windowed And WindowEvent()=#PB_Event_CloseWindow):gmode=#creditsmode:EndIf	; end with esc
  timer=timer+1
  If timer&16384=16384:timer = 0:EndIf
  If timer&2047=2047:Gosub reverse:EndIf
  If timer&15=15:flashpill=flashpill+1:If flashpill>1:flashpill=0:EndIf:EndIf
  If timer&#prizeontime=#prizeontime:Gosub prizeon:EndIf
  Select gmode
  	Case #pausemode
  	  If SoundStatus(soundeyes,chsoundeyes)=#PB_Sound_Playing:PauseSound(soundeyes,chsoundeyes):psnde = 1:Else:psnde = 0:EndIf
  		If SoundStatus(sounddeadly,chsounddeadly)=#PB_Sound_Playing:PauseSound(sounddeadly,chsounddeadly):psndd = 1:Else:psndd = 0:EndIf
  		If SoundStatus(soundblue,chsoundblue)=#PB_Sound_Playing:PauseSound(soundblue,chsoundblue):psndb = 1:Else:psndb = 0:EndIf
  		While KeyboardPushed(#pausekey)=0
  		  ExamineKeyboard()
  		  If linepause.b=0
  				Gosub drawmap
  				Gosub drawprize
  				Gosub drawghosts
  				Gosub drawpac
  				Gosub drawpoints
  				Gosub drawzoom
  				Gosub drawscore
  				Gosub drawpacsleft
  				If nozoomflag > 0
  				  DisplayTransparentSprite(nopowerimage,#gdsz*#cagex-8+#M_XOFF,#gdsz*(#cagey+3))
  				EndIf
  				If zoompowerflag > 0
  					DisplayTransparentSprite(zoompowerimage,#gdsz*#cagex-8+#M_XOFF,#gdsz*(#cagey+3))
  				EndIf
  			Else
  				ClearScreen(0)	
  			EndIf
  			Gosub drawpause
  			FlipBuffers()
  			Delay(30)
  			ExamineKeyboard()
  			If KeyboardPushed(#PB_Key_L):linepause!1:EndIf
  		Wend
  		If psnde = 1:ResumeSound(soundeyes,chsoundeyes):EndIf
  		If psndd = 1:ResumeSound(sounddeadly,chsounddeadly):EndIf
  		If psndb = 1:ResumeSound(soundblue,chsoundblue):EndIf
  		gmode = oldmode
  	Case #creditsmode
  		Gosub soundoff
  		Gosub credits
  		gmode = #startmode
  	Case #startmode
  		;new game
  		Gosub setupgame
  		gmode = #nextboardmode
  	Case #nextboardmode
  		; get new map and reset variables each level
  		Gosub setuplevel
  		Gosub setpositions
  		gmode = #getreadymode
  	Case #getreadymode
  		;every level and every life
  		zoompowerflag = 0
  		nozoomflag = 0
  		Gosub drawall
  		Gosub drawgetready
  		FlipBuffers()
  		ExamineKeyboard()
  		If KeyboardPushed(#skiplevkey)=0
  			If board=0 And looped=0 And played=0
  				PlaySound(soundstartmusic)
  				Delay(3500)
  			Else
  				Delay(1500)
  			EndIf
  		EndIf
  		played=1
  		gmode = #playingmode
  	Case #playingmode
  	  stime = ElapsedMilliseconds()
  	  ExamineKeyboard()
  		Gosub moveall
  		Gosub drawall
  		FlipBuffers() 
  		;Flip False
  		etime = ElapsedMilliseconds() - stime
  		;delay if needed
  		If etime < #dtime
  			Delay(#dtime-etime)
  		EndIf
  		ExamineKeyboard()
  		If KeyboardPushed(#skiplevkey):gmode = #nextboardmode:EndIf   ; skip boards with skipkey
  		If KeyboardPushed(#pausekey)
  			oldmode = gmode: gmode = #pausemode	; pause, remember current mode
  			For tt = 0 To 5
  				pausex(tt) = #cagex*#gdsz-8+tt*5
  				pausey(tt) = (#cagey+3)*#gdsz
  				driftx(tt) = Random(1,-1)
  				drifty(tt) = Random(1,-1)
  			Next
  			; the P needs a boost
  			driftx(0) = Random(3,-3)
  			drifty(0) = Random(3,-3)
  			For tt = 0 To 3
  				If board+t-3 >= 0
  					If board < 4:xoff = board:Else:xoff = 3:EndIf
  					pausex(tt+6) = 264-(xoff+tt)*17
  					pausey(tt+6) = #gdsz*#mapheight
  					driftx(tt) = Random(1,-1)
  					drifty(tt) = Random(1,-1)
  				EndIf
  			Next
  		EndIf			
  	Case #donemode
  	  ; all the dots are eaten
  		Gosub drawmap
  		Gosub drawpac
  		Gosub drawzoom
  		Gosub drawscore
  		Gosub drawpacsleft
  		Gosub drawlevel
  		Gosub boardclear
  		boarddone=0
  		gmode = #nextboardmode
  	Case #dyingmode
  		Gosub death
  		Gosub setpositions
  		If pacmen > 0:gmode = #getreadymode:EndIf
  		If pacmen = 0:gmode = #gameovermode:EndIf
  	Case #gameovermode
  	  Gosub soundoff
  		Gosub drawmap
  		Gosub drawpacsleft
  		Gosub drawlevel
  		Gosub drawscore
  		Gosub drawzoom
  		Gosub drawgameover
  		FlipBuffers()
  		PlaySound(soundgameover)
  		Delay(3500)
  		If score > highscore:highscore = score:EndIf
  		If board > lastboard:lastboard = board:startinglevel=lastboard:EndIf
  		gmode = #creditsmode
  EndSelect
  ExamineKeyboard()
  If KeyboardPushed(#PB_Key_L):linepause!1:EndIf
  ;If KeyboardPushed(#PB_Key_F12) SaveBuffer(FrontBuffer(),"SNAPHOT"+timer+".bmp")
  Goto innerloop
End  ;  mainloop

drawall:
  Gosub drawmap
  Gosub drawprize
  Gosub drawghosts
  Gosub drawpac
  Gosub drawpoints
  Gosub drawzoom
  Gosub drawscore
  Gosub drawlevel
  Gosub drawpacsleft
  If nozoomflag > 0
  	DisplayTransparentSprite(nopowerimage,#gdsz*#cagex-8+#M_XOFF,#gdsz*(#cagey+3))
  EndIf
  If zoompowerflag > 0
  	DisplayTransparentSprite(zoompowerimage,#gdsz*#cagex-8+#M_XOFF,#gdsz*(#cagey+3))
  EndIf
Return

moveall:
  slowdown = slowdown - 1: If slowdown <0:slowdown = 0:EndIf
  Select keyorjoy
	Case 0
		If KeyboardPushed(#speedkey)
			If exspeed>0
				Gosub movepac:Gosub gobble
				Gosub movepac:Gosub gobble
				exspeed=exspeed-1
			Else
				nozoomflag = 20
			EndIf
		EndIf
	Case 1
    ExamineJoystick(0)
		If JoystickButton(0,#speedkeyjoy)
			If exspeed>0
				Gosub movepac:Gosub gobble
				Gosub movepac:Gosub gobble
				exspeed=exspeed-1
			Else
				nozoomflag = 20
			EndIf
		EndIf
  EndSelect
  Gosub movepac
  Gosub gobble
  Gosub movepac
  Gosub gobble
  pass = 0 ; for regular ghosts
  Gosub moveghosts
  pass = 0 ; for regular ghosts
  Gosub moveghosts
  pass = 1 ; for eyes to give 50% more speed
  Gosub moveghosts
  Gosub moveprize
  Gosub checkcollisions
  If nozoomflag> 0:nozoomflag = nozoomflag - 1:EndIf
  If zoompowerflag> 0:zoompowerflag = zoompowerflag - 1:EndIf
Return

setupgame:
  ;set game variables
  played=0	;played start music?
  board=startinglevel-1
  looped=0	;looped through 100 boards?
  score=0
  bonuscount=1
  Select sklevel
	Case 0
		pacmen=5
		freeman=20000
		restorezoom=1
		numghosts = 4
	Case 1
		pacmen=3
		freeman=30000
		restorezoom=1
		numghosts = 4
	Case 2
		pacmen=3
		freeman=50000
		restorezoom=1
		numghosts = 5
	Case 3
		pacmen=2
		freeman=80000
		restorezoom=0
		numghosts = 6
	Case 4
		pacmen=1
		freeman=100000
		restorezoom=0
		numghosts = 6
  EndSelect
  Createghosts(numghosts-1)
Return

Procedure Createghosts(num.l)
  ;delete the current ghosts
  ClearList(g.ghost()) 
  ;create new ghosts
  For t.l=0 To num.l
  	AddElement(g.ghost())
  	g()\id = t
  Next
EndProcedure

setuplevel:
  Gosub soundoff
  ForEach pts.pointstype()
  	pts()\v = 0
  Next
  munched=0:pillstotal=0:prizeseaten=0:bluesleft=0
  exspeed=#MAXEXSPEED:flashpill=0
  board+1:If board>#numbrds-1:board=0:looped+1:EndIf
  If looped=0 ; go to max and stay there
  	; ghost speed
  	ForEach g.ghost()
  		t = g()\id
  		ts = Int(10-t/2+board/10)
  		If ts < 8:ts = 8:EndIf
  		If ts > 30:ts = 30:EndIf
  		g()\gspeed = ts
  	Next
  
  	; ghost #edible speed
  	ts = Int(8+board/10)
  	If ts < 8:ts = 8:EndIf
  	If ts > 30:ts = 30:EndIf
  	edspeed = ts
  	
  	;ghost tunnel speed
  	ts = Int(4+board/10)
  	If ts < 4:ts = 4:EndIf
  	If ts > 32:ts = 32:EndIf
  	gtspeed = ts
  	
  	;pac speed
  	ts = Int(12+board/10)
  	If ts < 12:ts = 12:EndIf
  	If ts > 32:ts = 32:EndIf
  	pspeed = ts
  	
  	;pac tunnel speed
  	ts = Int(12+board/10)
  	If ts < 12:ts = 12:EndIf
  	If ts > 32:ts = 32:EndIf
  	ptspeed = ts
  EndIf
  PaletteSwitch()
  Gosub setupmap
Return
  
setpositions:
  timer=0:prizedir=0:gobble=0:bluesleft=0
  ForEach g.ghost()
    g()\x=#cagex
    g()\y=#cagey+1
    g()\sx=#gdsz*g()\x
    g()\sy=#gdsz*g()\y
    g()\vx=g()\gspeed
    g()\vy=0
    g()\bluetimer=0
    g()\bx=g()\sx*32:g()\by=g()\sy*32
    g()\frm=20:g()\intunnel=0
    g()\cage=0:g()\act=#deadly
    g()\cagetimer = 80+g()\id*100-board*2
    If g()\cagetimer < 0:g()\cagetimer=2:EndIf
    If g()\cagetimer > 500:g()\cagetimer=500:EndIf
  Next
  
  pac()\x=#cagex
  pac()\y=#cagey+7
  pac()\sx=#gdsz*pac()\x
  pac()\sy=#gdsz*pac()\y
  pac()\bx=pac()\sx*32
  pac()\by=pac()\sy*32
  pac()\frm=4
  pac()\intunnel=0
  pac()\vx = -pspeed
  pac()\vy = 0
  
  prize()\cage = 1
  prize()\x=#cagex
  prize()\y=#cagey+1
  prize()\sx=#gdsz*prize()\x
  prize()\sy=#gdsz*prize()\y
  prize()\frm=board
  
  FlushKeys()
Return

Procedure FlushKeys()
	ExamineKeyboard():While KeyboardPushed(#PB_Key_All):ExamineKeyboard():Wend
	ExamineKeyboard():For k=1 To 255:KeyboardPushed(k):ExamineKeyboard():Next
EndProcedure

Procedure GetPalettes()
  ClearScreen(0)
	DisplayTransparentSprite(paletteimg,0,0)
	; grab the 7 colors from the 100 rows 
	StartDrawing(ScreenOutput())
	For y = 0 To #numbrds-1
		For x = 0 To 6
			getcolor.l=Point(x,y)
			coltable(x,0,y) = Red(getcolor)
			coltable(x,1,y) = Green(getcolor)
			coltable(x,2,y) = Blue(getcolor)
		Next
		coltable(7,0,y) = coltable(4,0,y)
		coltable(7,1,y) = coltable(4,1,y)
		coltable(7,2,y) = coltable(4,2,y)
	Next
	StopDrawing()
EndProcedure

Procedure PaletteSwitch()
	ClearScreen(0)
	; plot the red, green, blue, yellow, purple, white, cyan
  ; to the screen in their new colors
	imag.i=CreateSprite(#PB_Any,#screenw,#screenh)
	StartDrawing(SpriteOutput(imag))
	ForEach c.rgb()
		Plot(c()\x,c()\y,RGB(coltable(c()\col,0,board),coltable(c()\col,1,board),coltable(c()\col,2,board)))
	Next
	StopDrawing()
	; grab the newly colored images
	For row=0 To 4 
		For frm=0 To 12
			blockimages(frm+row*13)=miGrabimage(imag,16*frm,row*16,16,16)
		Next
	Next
	FreeSprite(imag)
EndProcedure

GetImageRGB:
	; draw the block images
	; check each pixel, if it is r,g,b,y,p,c, or w 
	;   then create an rgb object
	; later used to plot the image in new colors
  ClearScreen(0)
  For row = 0 To 4
		For frm = 0 To 12
			DisplayTransparentSprite(blockimages(frm+row*13),16*frm,row*16)
		Next
	Next
	StartDrawing(ScreenOutput())
	For y = 1 To 16*5
		For x = 1 To 16*13
		  col=Point(x,y)
			cr = Red(col)
			cg = Green(col)
			cb = Blue(col)
			col = 0
			If cr > 128:col|4:EndIf
			If cg > 128:col|2:EndIf
			If cb > 128:col|1:EndIf
			If col > 0
				AddElement(c.rgb())
				c()\col = col 
				c()\x = x
				c()\y = y
			EndIf
		Next
	Next
	StopDrawing()
Return

soundoff:
  ;shut off looping sounds
  If SoundStatus(soundeyes,chsoundeyes)=#PB_Sound_Playing:StopSound(soundeyes,chsoundeyes):chsoundeyes=0:EndIf
  If SoundStatus(sounddeadly,chsounddeadly)=#PB_Sound_Playing:StopSound(sounddeadly,chsounddeadly):chsounddeadly=0:EndIf
  If SoundStatus(soundblue,chsoundblue)=#PB_Sound_Playing:StopSound(soundblue,chsoundblue):chsoundblue=0:EndIf
Return

prizeon:
  If prizeseaten < #numprizes 
  	prizedir = prizedir + 1
  	If prizedir > 8:prizedir = 0:EndIf
  	If prizedir = 1 And prize()\x=#cagex And prize()\y=#cagey+1
  		; pop out of the cage
  		prize()\vx = #prizespeed:If Random(10)>4:prize()\vx=-prize()\vx:EndIf
  		prize()\vy = 0
  		prize()\sx = #cagex * #gdsz
  		prize()\sy = (#cagey-1) * #gdsz
  		prize()\bx = prize()\sx * 32
  		prize()\by = prize()\sy * 32
  		prize()\frm = board ; 0-100
  		prize()\points = prizepoints(board)
  		prize()\cage=0 
  		prize()\bouncedir = 1
  		prize()\bouncehgt = 0
  	EndIf
  EndIf
Return

moveprize:
  If prize()\cage = 0
  	; not in the cage
  	If prize()\x<1 Or prize()\x>(#mapwidth-2):prize()\intunnel=-1:EndIf
  	If prize()\y<1 Or prize()\y>(#mapheight-2):prize()\intunnel=1:EndIf
  	If prize()\intunnel=0
  		If prize()\vx<0 Or prize()\vy<0
  			prize()\bx=prize()\bx+prize()\vx
  			prize()\by=prize()\by+prize()\vy
  			prize()\sx=(prize()\bx / 32)
  			prize()\sy=(prize()\by / 32)
  			prize()\x=prize()\sx/#gdsz
  			prize()\y=prize()\sy/#gdsz
  			If currentmap(prize()\x,prize()\y) < 52 ; crash ,change dir
  				prize()\bx=prize()\bx-prize()\vx
  				prize()\by=prize()\by-prize()\vy
  				prize()\x=prize()\bx/(#gdsz*32)
  				prize()\y=prize()\by/(#gdsz*32)
  				pcngflg=10
  			EndIf
  		Else
  			If prize()\vy>0 ; moving down
  				y=((prize()\by/32)+#gdsz)/#gdsz
  				x=prize()\x
  				If currentmap(x,y) < 52
  					pcngflg=10
  				Else
  					prize()\by=prize()\by+prize()\vy
  				EndIf
  			Else ; prize()\vx>0 moving right
  				x =	((prize()\bx/32)+#gdsz)/#gdsz
  				y=prize()\y
  				If currentmap(x,y) < 52
  					pcngflg=10
  				Else
  					prize()\bx=prize()\bx+prize()\vx
  				EndIf
  			EndIf
  		EndIf
  	Else
  		; in tunnel
  		If prize()\intunnel=-1 
  			; left right tunnel
  			prize()\bx=prize()\bx+Sign(prize()\vx)*#prizespeed 
  			If prize()\bx < 0 
  				prize()\bx = 32*(#mapwidth-1)*#gdsz
  			ElseIf prize()\bx > 32*(#mapwidth-1)*#gdsz
  				prize()\bx=0
  			EndIf
  			prize()\sx=prize()\bx/32
  			prize()\x=prize()\sx/#gdsz
  			If prize()\x>0 Or prize()\x<=(#mapwidth-2):prize()\intunnel=0:EndIf
  		EndIf
  		If prize()\intunnel=1
  			; up down tunnel
  			prize()\by=prize()\by+Sign(prize()\vy)*#prizespeed
  			If prize()\by < 0 
  				prize()\by = 32*(#mapheight-1)*#gdsz
  			ElseIf prize()\by > 32*(#mapheight-1)*#gdsz
  				prize()\by=0
  			EndIf
  			prize()\sy=prize()\by/32
  			prize()\y=prize()\sy/#gdsz
  			If prize()\y > 0 Or prize()\y<=(#mapheight-2):prize()\intunnel=0:EndIf
  		EndIf
  	EndIf
  	prize()\sx=prize()\bx/32
  	prize()\sy=prize()\by/32
  	prize()\x=prize()\sx/#gdsz
  	prize()\y=prize()\sy/#gdsz
  
  	If prize()\bx%(32*#gdsz)<33 And prize()\by%(32*#gdsz)<33:square=1:Else:square=0:EndIf
  
  	If square And Random(10)>6 And pcngflg=0:pcngflg = 10:EndIf
  	If pcngflg>0:pcngflg=pcngflg-1:EndIf
  	If pcngflg=9
  		prize()\sx=prize()\x*#gdsz
  		prize()\sy=prize()\y*#gdsz
  		prize()\bx=prize()\sx*32
  		prize()\by=prize()\sy*32
  		Gosub changedirprize
  	EndIf
  
  	If square And prize()\x=#cagex And prize()\y = #cagey-1 And prizedir >1
  		; go back in cage and wait
  		prizedir = 8
  		prize()\cage=1
  		prize()\y=#cagey+1
  		prize()\sy=prize()\y*#gdsz
  	EndIf
  	;\bouncehgt goes from 0 To -8 back to 0
  	If prize()\bouncehgt <= -16 Or prize()\bouncehgt >=0:prize()\bouncedir = -prize()\bouncedir:EndIf
  	prize()\bouncehgt = prize()\bouncehgt + prize()\bouncedir
  	If prize()\bouncehgt = 0
  		PlaySound(soundbounce)
  	EndIf
  EndIf
Return

changedirprize:
  pick2=-1:If Random(10)>4:pick2=1:EndIf
  ; select the destination according to the prizedir
  Select (prizedir)
  	Case 0
  		; randon dir
  		xdiff=1:ydiff=1
  		If Random(10)>4:xdiff=-1:EndIf
  		If Random(10)>4:ydiff=-1:EndIf
  	Case 1
  		; towards bottom right corner
  		xdiff=1:ydiff=1
  	Case 2
  		; towards bottom left corner
  		xdiff=-1:ydiff=1
  	Case 3
  		; towards top left corner
  		xdiff=-1:ydiff=-1
  	Case 4
  		; towards top right corner
  		xdiff=1:ydiff=-1
  	Default ; 5,6,7,8
  		; towards cage center
  		xdiff=Sign(#cagex-prize()\x):ydiff=Sign((#cagey+1)-prize()\y)
  EndSelect
  Select mapopen(prize()\x,prize()\y)
  	Case 0
  		; how? you shouldn't be on this tile!
  	Case 1;up
  		prize()\vy=-#prizespeed:prize()\vx=0
  	Case 2;right
  		prize()\vx=#prizespeed:prize()\vy=0
  	Case 4;down
  		prize()\vy=#prizespeed:prize()\vx=0
  	Case 8;left
  		prize()\vx=-#prizespeed:prize()\vy=0
  	Case 3
  		If prize()\vy>0:prize()\vx=#prizespeed:prize()\vy=0:Else:prize()\vx=0:prize()\vy=-#prizespeed:EndIf
  	Case 5;u d
  	Case 6;r d
  		If prize()\vy<0:prize()\vx=#prizespeed:prize()\vy=0 :Else:prize()\vx=0:prize()\vy=#prizespeed:EndIf
  	Case 10;l r
  	Case 12;d l
  		If prize()\vy<0:prize()\vx=-#prizespeed:prize()\vy=0:Else:prize()\vx=0:prize()\vy=#prizespeed:EndIf
  	Case 9;l u
  		If prize()\vy>0:prize()\vx=-#prizespeed:prize()\vy=0:Else:prize()\vx=0:prize()\vy=-#prizespeed:EndIf
  	Case 7;urd
  		If prize()\vx<0;going r , turn u or d
  			prize()\vx=0:prize()\vy=ydiff*#prizespeed; up or d
  			If prize()\vy = 0:prize()\vy=pick2*#prizespeed:EndIf
  		Else
  			If xdiff = 1:prize()\vx=#prizespeed:prize()\vy=0:EndIf; right
  		EndIf
  	Case 11
  		If prize()\vy>0
  			prize()\vy=0:prize()\vx=xdiff*#prizespeed; l or r
  			If prize()\vx = 0:prize()\vx=pick2*#prizespeed:EndIf
  		Else
  			If ydiff = -1 :prize()\vy=-#prizespeed:prize()\vx=0:EndIf; u
  		EndIf
  	Case 13
  		If prize()\vx>0
  			prize()\vx=0:prize()\vy=ydiff*#prizespeed  ;  up or down
  			If prize()\vy = 0:prize()\vy=pick2*#prizespeed:EndIf
  		Else
  			If xdiff = -1:prize()\vx=-#prizespeed:prize()\vy=0:EndIf; l
  		EndIf
  	Case 14
  		If prize()\vy<0
  			prize()\vy=0:prize()\vx=xdiff*#prizespeed    ; l or r
  			If prize()\vx = 0:prize()\vx=pick2*#prizespeed:EndIf
  		Else
  			If ydiff = 1:prize()\vy=#prizespeed:prize()\vx=0:EndIf; d
  		EndIf
  	Case 15
  		If Random(10) > 4; keep going 40% of time
  			If prize()\vx = 0 ; going up or down
  				If Random(10)>4 Or xdiff=0:xdiff = pick2:EndIf
  				prize()\vx = xdiff*#prizespeed:prize()\vy=0
  			Else ; going l or r
  				If Random(10)>4 Or ydiff=0:ydiff = pick2:EndIf
  				prize()\vy = ydiff*#prizespeed:prize()\vx=0
  			EndIf
  		EndIf
  EndSelect
Return

movepac:
  If slowdown > 0:slowmo=2:Else:slowmo = 1:EndIf ;go half speed when digesting
  wdirx=0:wdiry=0
  If keyorjoy=0
		If KeyboardPushed(#PB_Key_Left):wdirx = -1:EndIf
		If KeyboardPushed(#PB_Key_Right):wdirx = 1:EndIf
		If KeyboardPushed(#PB_Key_Up):wdiry = -1:EndIf
		If KeyboardPushed(#PB_Key_Down):wdiry = 1:EndIf
	Else
	  ExamineJoystick(0)
    wdirx=JoystickAxisX(0):wdiry=JoystickAxisY(0)
  EndIf
  If pac()\sx%#gdsz=0 And pac()\sy%#gdsz=0:square=1:Else:square=0:EndIf
  If square Or (pac()\vx=0 And pac()\vy=0)
  	If wdirx=-1 And mapopen(pac()\x,pac()\y)&8=8
  		pac()\vx=-pspeed
  		pac()\vy=0
  	EndIf
  	If wdirx=1 And mapopen(pac()\x,pac()\y)&2=2
  		pac()\vx=pspeed
  		pac()\vy=0
  	EndIf
  	If wdiry=-1 And mapopen(pac()\x,pac()\y)&1=1
  		pac()\vy=-pspeed
  		pac()\vx=0
  	EndIf
  	If wdiry=1 And mapopen(pac()\x,pac()\y)&4=4
  		pac()\vy=pspeed
  		pac()\vx=0
  	EndIf
  Else 
  	If wdirx=-1 And pac()\vx
  		pac()\vx=-pspeed
  		pac()\vy=0
  	EndIf
  	If wdirx=1 And pac()\vx
  		pac()\vx=pspeed
  		pac()\vy=0
  	EndIf
  	If wdiry=-1 And pac()\vy
  		pac()\vy=-pspeed
  		pac()\vx=0
  	EndIf
  	If wdiry=1 And pac()\vy
  		pac()\vy=pspeed
  		pac()\vx=0
  	EndIf
  EndIf
  
  If pac()\intunnel=0
  	If pac()\x<1 Or pac()\x>#mapwidth-2:pac()\intunnel=-1:EndIf
  	If pac()\y<1 Or pac()\y>#mapheight-2:pac()\intunnel=1:EndIf
  	If pac()\vx<0 Or pac()\vy<0
  		pac()\bx=pac()\bx+(pac()\vx/slowmo)
  		pac()\by=pac()\by+(pac()\vy/slowmo)
  		pac()\sx=pac()\bx/32
  		pac()\sy=pac()\by/32
  		pac()\x=pac()\sx/#gdsz
  		pac()\y=pac()\sy/#gdsz
  		If currentmap(pac()\x,pac()\y)<52 ; crash ,change dir
  			pac()\bx=pac()\bx-pac()\vx/slowmo
  			pac()\by=pac()\by-pac()\vy/slowmo
  			pac()\x=pac()\bx/(#gdsz*32)
  			pac()\y=pac()\by/(#gdsz*32)
  			If pac()\vy<0:pac()\frm=8:Else:pac()\frm=5:EndIf
  			pac()\vx=0:pac()\vy=0
  		EndIf
  	Else
  		;down or right
  		If pac()\vy>0
  			;moving down
  			y=((pac()\by/32)+#gdsz)/#gdsz
  			x=pac()\x
  			If currentmap(x,y)<52  
  				pac()\vy=0:pac()\vx=0
  				pac()\frm=11
  			Else
  				;pac()\bx=pac()\bx+(pac()\vx/slowmo)
  				pac()\by=pac()\by+(pac()\vy/slowmo)
  				;pac()\sx=pac()\bx/32
  				pac()\sy=pac()\by/32
  				;pac()\x=pac()\sx/#gdsz
  				pac()\y=pac()\sy/#gdsz
  			EndIf
  		ElseIf pac()\vx>0
  			; vx > 0 - moving right
  			x = ((pac()\bx/32)+#gdsz)/#gdsz
  			y=pac()\y
  			If currentmap(x,y)<52
  				pac()\vy=0:pac()\vx=0
  				pac()\frm=2
  			Else
  				pac()\bx=pac()\bx+(pac()\vx/slowmo)
  				;pac()\by=pac()\by+(pac()\vy/slowmo)
  				pac()\sx=pac()\bx/32
  				;pac()\sy=pac()\by/32
  				pac()\x=pac()\sx/#gdsz
  				;pac()\y=pac()\sy/#gdsz
  			EndIf
  		EndIf
  	EndIf
  Else 
  	; in tunnel
  	If pac()\intunnel=-1
  		;left right tunnel
  		pac()\bx=pac()\bx+Sign(pac()\vx)*ptspeed
  		If pac()\bx < 0 
  			pac()\bx = 32*(#mapwidth-1)*#gdsz
  		Else 
  			If pac()\bx > 32*(#mapwidth-1)*#gdsz:pac()\bx = 0:EndIf
  		EndIf
  		pac()\sx=pac()\bx/32
  		pac()\x=pac()\sx/#gdsz
  		If pac()\bx>0 And pac()\x<=(#mapwidth-2):pac()\intunnel=0:EndIf
  	EndIf
  	If pac()\intunnel=1
  		; up down tunnel
  		pac()\by=pac()\by+Sign(pac()\vy)*ptspeed
  		If pac()\by < 0 
  			pac()\by = 32*(#mapheight-1)*#gdsz
  		Else 
  			If pac()\by > 32*(#mapheight-1)*#gdsz:pac()\by = 0:EndIf
  		EndIf
  		pac()\sy=pac()\by/32
  		pac()\y=pac()\sy/#gdsz
  		If pac()\by>0 And pac()\y<=#mapheight-2:pac()\intunnel=0:EndIf
  	EndIf
  EndIf
  
  pac()\sx=pac()\bx/32
  pac()\cx=Int((((pac()\bx+(pac()\vx*2))/32)+4)/#gdsz)
  pac()\sy=pac()\by/32
  pac()\cy=Int((((pac()\by+(pac()\vy*2))/32)+4)/#gdsz)
  pac()\x=pac()\sx/#gdsz
  pac()\y=pac()\sy/#gdsz
  
  char.a=currentmap(pac()\cx,pac()\cy)
  gobble = 0
  If char<>255 And char>51:gobble = 1:EndIf
  
  If pac()\vx>0:pac()\frm=0+2:EndIf
  If pac()\vx<0:pac()\frm=3+2:EndIf
  If pac()\vy<0:pac()\frm=6+2:EndIf
  If pac()\vy>0:pac()\frm=9+2:EndIf
  
  If pac()\vx <>0 Or pac()\vy <>0
  	;images are rrrllluuuddd
  	pac()\frmcnt=pac()\frmcnt+2:If pac()\frmcnt > 63:pac()\frmcnt=0:EndIf
  	sc=Int(pac()\frmcnt/16)
  	Select sc
  		Case 0
  			pac()\frm=pac()\frm-1
  		Case 1
  			pac()\frm=pac()\frm-2
  		Case 2
  			pac()\frm=pac()\frm-1
  		Case 3
  			pac()\frm=pac()\frm
  	EndSelect
  EndIf
Return

moveghosts:
ForEach g.ghost()
	If g()\act=#eyes Or pass=0
		;enter the cage?
		If g()\act=#eyes And g()\y=#cagey-1 And g()\x=#cagex
		  If g()\sx%#gdsz=0 And g()\cage=0
				If SoundStatus(soundeyes,chsoundeyes)=#PB_Sound_Playing:StopSound(soundeyes,chsoundeyes):chsoundeyes=0:EndIf
				If SoundStatus(sounddeadly,chsounddeadly)<>#PB_Sound_Playing
					chsounddeadly=PlaySound(sounddeadly,#PB_Sound_MultiChannel)
				EndIf
				g()\vx=0:g()\vy=10   ;gspeed
				g()\cage=1
			EndIf
		EndIf
		;exit cage ?
		If g()\act<>#eyes And g()\y-1=#cagey And g()\x=#cagex
			g()\cagetimer = g()\cagetimer-1
			If g()\sx%#gdsz=0 And g()\cagetimer<0
				g()\vx=0:g()\vy=-g()\gspeed
				g()\cage=-1
				If SoundStatus(sounddeadly,chsounddeadly)<>#PB_Sound_Playing
					chsounddeadly=PlaySound(sounddeadly,#PB_Sound_MultiChannel)
				EndIf
			EndIf
		EndIf
		;if not in cage - move
		If g()\cage=0
			If g()\x<1 Or g()\x>(#mapwidth-2):g()\intunnel=-1:EndIf
			If g()\y<1 Or g()\y>(#mapheight-2):g()\intunnel=1:EndIf
			; not in tunnel
			If g()\intunnel=0
				If g()\vx<0 Or g()\vy<0
					; moving up or left
					If g()\act=#eyes
						If g()\vx<0:g()\vx=-#eyespeed:Else:g()\vy=-#eyespeed:EndIf
					ElseIf g()\act=#edible
						If g()\vx<0:g()\vx=-edspeed:Else:g()\vy=-edspeed:EndIf
					EndIf
					g()\bx=g()\bx + g()\vx  ; 0 - 32*#mapwidth*#gdsz
					g()\by=g()\by + g()\vy  ; 0 - 32*#mapheight*#gdsz
					g()\sx=g()\bx/32
					g()\sy=g()\by/32
					g()\x=g()\sx/#gdsz
					g()\y=g()\sy/#gdsz
					If currentmap(g()\x,g()\y)<52 ; crash ,change dir
						g()\bx=g()\bx - g()\vx  ; 0 - 32*#mapwidth*#gdsz
						g()\by=g()\by - g()\vy  ; 0 - 32*#mapheight*#gdsz
						g()\x=g()\bx/(#gdsz*32)
						g()\y=g()\by/(#gdsz*32)
						Gosub changedirg
						g()\changed=10
						g()\bx=g()\bx + g()\vx  ;0-32*#mapwidth*#gdsz
						g()\by=g()\by + g()\vy  ;0-32*#mapheight*#gdsz
					EndIf
				Else
					If g()\vy>0
						; moving down
						If g()\act=#eyes:g()\vy=#eyespeed:ElseIf g()\act=#edible:g()\vy=edspeed:EndIf
						tsy=g()\sy+#gdsz
						y=tsy/#gdsz
						x=g()\x
						If currentmap(x,y)<52
							Gosub changedirg  ; crash ,change dir
							g()\changed=10
						EndIf
						g()\bx=g()\bx + g()\vx  ;0-32*#mapwidth*#gdsz
						g()\by=g()\by + g()\vy  ;0-32*#mapheight*#gdsz
					Else 
						; \vx>0 - moving right
						If g()\act=#eyes:g()\vx=#eyespeed:ElseIf g()\act=#edible:g()\vx=edspeed:EndIf
						tsx=g()\sx + #gdsz
						x=tsx/#gdsz
						y=g()\y
						If currentmap(x,y)<52
							Gosub changedirg ; crash ,change dir
							g()\changed=10
						EndIf
						g()\bx=g()\bx + g()\vx ;0-32*#mapwidth*#gdsz
						g()\by=g()\by + g()\vy ;0-32*#mapheight*#gdsz
					EndIf
				EndIf
				g()\sx=g()\bx/32
				g()\sy=g()\by/32
				g()\x=g()\sx/#gdsz
				g()\y=g()\sy/#gdsz
		
				g()\changed=g()\changed-1
				If g()\changed<=0
					If g()\sx%#gdsz=0 And g()\sy%#gdsz=0
						Select g()\act
							Case #deadly  ; 2
								If Random(10)  > 4 ; 50% of time change dir
									Gosub changedirg
									g()\changed=5; don't change again until 10 steps away
				    		EndIf
							Case #edible  ; 1
								If Random(10)  > 7 ; blue is dumb, don't change as much
									Gosub changedirg
									g()\changed=5; don't change again until 10 steps away
				    	  EndIf
							Case #eyes    ; 3
								If Random(10)  > 2 ; #eyes head home quickly
									Gosub changedirg
									g()\changed=5; don't change again until 10 steps away
				    		EndIf
						EndSelect
					EndIf
				EndIf
			Else 
				; intunnel<>0
				If  g()\intunnel=-1
					; left right
					g()\bx=g()\bx + Sign(g()\vx)*gtspeed 
					If g()\bx < 0 
						g()\bx = 32*(#mapwidth-1)*#gdsz
					ElseIf g()\bx > 32*(#mapwidth-1)*#gdsz
						g()\bx = 0
					EndIf
					g()\sx=g()\bx/32
					g()\x=g()\sx/#gdsz
					If g()\x>0 And g()\x<=#mapwidth-2:g()\intunnel=0:EndIf
				EndIf
				If g()\intunnel=1
					; up down
					g()\by=g()\by + Sign(g()\vy)*gtspeed 
					If g()\by < 0 
						g()\by = 32*(#mapheight-1)*#gdsz
					ElseIf g()\by > 32*(#mapheight-1)*#gdsz 
						g()\by = 0
					EndIf
					g()\sy=g()\by/32
					g()\y=g()\sy/#gdsz
					If g()\y>0 And g()\y<=#mapheight-2:g()\intunnel=0:EndIf
				EndIf
			EndIf
		Else
			; inside cage stuff
			g()\by=g()\by + Sign(g()\vy)*8 ; move slowly in/out
			g()\sy=g()\by/32
			g()\y=g()\sy/#gdsz
			If g()\y<(#cagey-1) Or g()\y>#cagey
				If g()\cage=1
					g()\act=#deadly
					g()\cagetimer = 20+g()\id*(20-board/5)
					g()\by=(#cagey+1)*#gdsz*32
					g()\vy=0
					g()\vx=g()\gspeed
				Else
					g()\by=(#cagey-1)*#gdsz*32
				EndIf
		  		g()\cage=0
			EndIf
		EndIf
		
		; select anim frame
		;images are:	rrlluudd - red   
		;then		rrlluudd - pink  
		;then		rrlluudd - cyan 
		;then		rrlluudd - orange
		;then		rrlluudd - green
		;then		rrlluudd - yellow		
		;then		bbwwee
						
		g()\frmcnt=g()\frmcnt+1:If g()\frmcnt>63:g()\frmcnt=0:EndIf

		If g()\vy>0:g()\frm=6+g()\id*8:EndIf
		If g()\vy<0:g()\frm=4+g()\id*8:EndIf
		If g()\vx>0:g()\frm=0+g()\id*8:EndIf
		If g()\vx<0:g()\frm=2+g()\id*8:EndIf
		
		If g()\bluetimer > 0
			g()\bluetimer = g()\bluetimer-1
		EndIf
		If g()\act=#edible
			If g()\bluetimer = 0
				g()\act = #deadly
				bluesleft = bluesleft - 1
				g()\vx = Sign(g()\vx) * g()\gspeed
				g()\vy = Sign(g()\vy) * g()\gspeed
				If SoundStatus(soundblue,chsoundblue)=#PB_Sound_Playing:StopSound(soundblue,chsoundblue):chsoundblue=0:EndIf
				If SoundStatus(sounddeadly,chsounddeadly)<>#PB_Sound_Playing
					chsounddeadly = PlaySound(sounddeadly,#PB_Sound_MultiChannel)
				EndIf
			Else
				g()\frm = #frmgb   ; blue  32,33
				;                                                               setsoundPitch(chsoundblue,35000-g()\bluetimer*20)
				If g()\bluetimer<160
					If g()\frmcnt&4=4:g()\frm = #frmgw:EndIf ; white 34,35
				Else
					If g()\bluetimer<360
						If g()\frmcnt&32=32:g()\frm = #frmgw:EndIf ; white 34,35
					EndIf
				EndIf
			EndIf
		EndIf
		
		If g()\frmcnt > 30:g()\frm = g()\frm+1:EndIf
		
		If g()\act=#eyes
			g()\frm= #frmge ; #eyes 36,37
			If g()\frmcnt&16=16:g()\frm = g()\frm + 1:EndIf ; blink
		EndIf
	EndIf
Next
Return

changedirg:
  xdiff=Sign(pac()\x-g()\x)
  ydiff=Sign(pac()\y-g()\y)
  t=g()\id
  ;if pink,ink, or sue head towards prize 20% of time
  If t > 3 And Random(15) > 11
  	xdiff=Sign(prize()\x-g()\x):ydiff=Sign(prize()\y-g()\y)
  EndIf
  
  ; if #eyes, head towards cage
  If g()\act=#eyes
  	xdiff=Sign(#cagex-g()\x):ydiff=Sign((#cagey-1)-g()\y)
  EndIf
  
  ; if blue then head away from pac
  If g()\act=#edible:xdiff=-xdiff:ydiff=-ydiff:EndIf
  
  pick2=-1:If Random(10)>4:pick2=1:EndIf

  Select mapopen(g()\x,g()\y)
  	Case 0
  		; how? you shouldn't be on this tile!
  	Case 1
  		; up
  		g()\vy=-g()\gspeed:g()\vx=0
  	Case 2
  		; right
  		g()\vx=g()\gspeed:g()\vy=0
  	Case 4
  		; down
  		g()\vy=g()\gspeed:g()\vx=0
  	Case 8
  		; left
  		g()\vx=-g()\gspeed:g()\vy=0
  	Case 3
  		; up or right
  		If g()\vy>0:g()\vx=g()\gspeed:g()\vy=0:Else:g()\vx=0:g()\vy=-g()\gspeed:EndIf
  	Case 5
  		; ghosts don't reverse on their own
  		; up OR down
  		; If Rnd > .95
  		;  \vx=0:\vy=ydiff*\gspeed
  		; EndIf
  	Case 6
  		; right or down
  		If g()\vy<0:g()\vx=g()\gspeed:g()\vy=0:Else:g()\vx=0:g()\vy=g()\gspeed:EndIf
  	Case 10
  		; right or left
   		If g()\vy < 0  ; getting out of cage only
  			g()\vx=xdiff*g()\gspeed:g()\vy=0
  			If g()\vx=0:g()\vx = g()\gspeed:EndIf
  		EndIf
  	Case 12
  		; down or left
  		If g()\vy<0:g()\vx=-g()\gspeed:g()\vy=0:Else:g()\vx=0:g()\vy=g()\gspeed:EndIf
  	Case 9
  		; up or left
  		If g()\vy>0:g()\vx=-g()\gspeed:g()\vy=0:Else:g()\vx=0:g()\vy=-g()\gspeed:EndIf
  	Case 7
  		; up right down
  		If g()\vx<0
  			; moving left hit wall, go u or d
  			g()\vx=0:g()\vy=ydiff*g()\gspeed; up or d
  			If g()\vy = 0:g()\vy=pick2*g()\gspeed:EndIf
  		Else
  			; else cont up or down, or turn right
  			If xdiff = 1:g()\vx=g()\gspeed:g()\vy=0:EndIf; right
  		EndIf
  	Case 11
  		; up left right
  		If g()\vy>0
  			; moving d hit wall, go l or r
  			g()\vy=0:g()\vx=xdiff*g()\gspeed; l or r
  			If g()\vx = 0:g()\vx=pick2*g()\gspeed:EndIf
  		Else
  			; else moving l or r, cont or turn u
  			If ydiff = -1:g()\vy=-g()\gspeed:g()\vx=0:EndIf; u
  		EndIf
  	Case 13
  		; up left down
  		If g()\vx>0
  			; moving r hit wall, go u or d
  			g()\vx=0:g()\vy=ydiff*g()\gspeed  ;  up or down
  			If g()\vy = 0:g()\vy=pick2*g()\gspeed:EndIf
  		Else
  			; else moving up or down, cont or turn l
  			If xdiff = -1:g()\vx=-g()\gspeed:g()\vy=0:EndIf; l
  		EndIf
  	Case 14
  		; down left right
  		If g()\vy<0
  			; moving u hit wall, go l or r
  			g()\vy=0:g()\vx=xdiff*g()\gspeed    ; l or r
  			If g()\vx = 0:g()\vx=pick2*g()\gspeed:EndIf
  		Else
  			; else moving l or r, cont or turn d
  			If ydiff = 1:g()\vy=g()\gspeed:g()\vx=0:EndIf; d
  		EndIf
  	Case 15
  		; up right down or left open
  		If g()\vx = 0 ; going up or down
  			If Random(10)>4 Or xdiff=0:xdiff = pick2:EndIf
  			g()\vx = xdiff*g()\gspeed:g()\vy=0
  		Else ; going l or r
  			If Random(10)>4 Or ydiff=0:ydiff = pick2:EndIf
  			g()\vy = ydiff*g()\gspeed:g()\vx=0
  		EndIf
  EndSelect
Return

reverse:
  ForEach g.ghost()
  	If g()\act = #deadly
  		If g()\vy And g()\cage=0:g()\vy=-g()\vy:EndIf
  		If g()\vx:g()\vx=-g()\vx:EndIf
  	EndIf
  Next
Return

turnblue:
  ForEach g.ghost()
  	If g()\act<>#eyes
  		;change direction if not blue
  		If g()\act<>#edible
   			If g()\vy And g()\cage=0:g()\vy=-g()\vy:EndIf
  			If g()\vx:g()\vx=-g()\vx:EndIf
  			bluesleft = bluesleft + 1
  		EndIf
  		g()\bluetimer = 1000-board*10
  		g()\frm=36
  		g()\act=#edible
  		If SoundStatus(sounddeadly,chsounddeadly)=#PB_Sound_Playing:StopSound(sounddeadly,chsounddeadly):chsounddeadly=0:EndIf
  		;If SoundStatus(soundeyes,chsoundeyes)=#PB_Sound_Playing:StopSound(soundeyes,chsoundeyes):chsoundeyes=0:endif
  		If SoundStatus(soundblue,chsoundblue)<>#PB_Sound_Playing
  			chsoundblue = PlaySound(soundblue)
  			;                                                   ChannelPitch chsoundblue,25000-360*10
  		EndIf
  	EndIf
  Next
  killed=0
Return

drawghosts:
  ForEach g.ghost()
  	DisplayTransparentSprite(ghostimages(g()\frm),g()\sx+#M_XOFF,g()\sy)
  Next
Return

drawpac:
  If pac()\sx > 4 And pac()\sx < (#mapwidth-1)*#gdsz-4
  	DisplayTransparentSprite(pacimages(pac()\frm),pac()\sx+#M_XOFF,pac()\sy)
  EndIf
Return

drawpoints:
  ForEach pts.pointstype()
  	If pts()\v > 0
  		pts()\v=pts()\v-1
  		DisplayTransparentSprite(pointimages(pts()\frm),pts()\x+#M_XOFF,pts()\y)
  		If pts()\v = 0:DeleteElement(pts(),1):EndIf
  	EndIf
  Next
Return

drawprize:
  If prize()\cage = 0
  	prizey=prize()\sy+prize()\bouncehgt/2+2:If prizey<0:prizey = 0:EndIf
  	DisplayTransparentSprite(prizeimages(prize()\frm),prize()\sx+#M_XOFF,prizey)
  Else
  	;draw it in the cage
  	DisplayTransparentSprite(prizeimages(prize()\frm),prize()\sx+#M_XOFF,prize()\sy)
  EndIf
Return

drawpacsleft:
  t = 1
  While t<6 And t<pacmen
   DisplayTransparentSprite(pacimages(0),t*14+#M_XOFF,#gdsz*#mapheight)
   t = t + 1
  Wend
Return

drawlevel:
  ;draw prize/board number
  For t = 0 To 3
  	If board+t-3 >= 0
  		If board < 4:xoff = board:Else:xoff = 3:EndIf
  		DisplayTransparentSprite(prizeimages(t+board-3),264-(xoff+t)*17+#M_XOFF,#gdsz*#mapheight)
  	EndIf
  Next
Return

drawscore:
  If score>=freeman*bonuscount
    PlaySound(soundbonus)
    bonuscount=bonuscount+1
    pacmen=pacmen+1
  EndIf
  If score>999999:score-999999:bonuscount=1:EndIf
  sc=score
  For t=0 To 5
  	DisplayTransparentSprite(numberimages(30+sc%10),#gdsz*(13-t)+(5-t)*2+#M_XOFF,#gdsz*#mapheight)
  	sc/10
  Next
Return

drawzoom:
  DisplayTransparentSprite(zoomimage,7+#M_XOFF,0)
  StartDrawing(ScreenOutput())
  FrontColor(RGB(255,255,0))
  Box(4+26+#M_XOFF,1,exspeed,4)
  FrontColor(RGB(255,0,0))
  DrawingMode(#PB_2DDrawing_Outlined)
  Box(4+25+#M_XOFF,0,#MAXEXSPEED+2,6)
  StopDrawing()
Return

;.drawzoom
;DrawImage zoomimage,#M_XOFF-4,0
;Color 255,255,0
;Rect #M_XOFF+1-4,26,4,exspeed
;Color 255,0,0
;Rect #M_XOFF-4,25,6,#MAXEXSPEED+2,0
;Return

drawgetready:
  DisplayTransparentSprite(getreadyimage,#gdsz*#cagex-8+#M_XOFF,#gdsz*(#cagey+3))
Return

drawgameover:
  DisplayTransparentSprite(gameoverimage,#gdsz*#cagex-8+#M_XOFF,#gdsz*(#cagey+3))
Return

drawpause:
  For tt = 9 To 0 Step -1
  	pausex(tt) = pausex(tt) + driftx(tt)
  	pausey(tt) = pausey(tt) + drifty(tt)
  	If tt > 0
  		diffx.f = pausex(tt-1) - pausex(tt)
  		diffy.f = pausey(tt-1) - pausey(tt)
  		mag.f = Sqr(diffx*diffx + diffy*diffy)
  		If mag > 10
  			driftx(tt) = driftx(tt) + diffx/mag*2
  			drifty(tt) = drifty(tt) + diffy/mag*2
  		EndIf
  	Else
  		If Random(100) > 80
  			diffx.f = pausex(9) - pausex(tt)
  			diffy.f = pausey(9) - pausey(tt)
  			mag.f = Sqr(diffx*diffx + diffy*diffy)
  			If mag > 10
  				driftx(tt) = driftx(tt) + diffx/mag
  				drifty(tt) = drifty(tt) + diffy/mag
  			EndIf
  		EndIf
  	EndIf
  	If pausex(tt) < 0:driftx(tt) = -driftx(tt):pausex(tt) = 2:EndIf
  	If pausex(tt) > #gdsz*#mapwidth:driftx(tt) = -driftx(tt):pausex(tt) = #gdsz*#mapwidth-2:EndIf
  	If pausey(tt) < #gdsz:drifty(tt) = -drifty(tt):pausey(tt) = #gdsz+2:EndIf
  	If pausey(tt) > #gdsz*#mapheight:drifty(tt) = -drifty(tt):pausey(tt) = #gdsz*#mapheight-2:EndIf
  
  	If linepause.b
  		If tt > 0:Line(pausex(tt)+#M_XOFF,pausey(tt),pausex(tt-1)+#M_XOFF,pausey(tt-1)):EndIf
  	Else
  		If tt < 6 
  			DrawImage(pauseimage(tt),pausex(tt)+#M_XOFF,pausey(tt))
  		Else	
  			fr=tt-6+board-3
  			If fr>=0:DisplayTransparentSprite(prizeimages(fr),pausex(tt)+#M_XOFF,pausey(tt)):EndIf
  		EndIf
  	EndIf
  	If Random(100) > 95:driftx(tt) = driftx(tt) + Random(1,-1):EndIf
  	If Random(100) > 95:drifty(tt) = drifty(tt) + Random(1,-1):EndIf
  	If Abs(driftx(tt)) > 4:driftx(tt) = Sign(driftx(tt))*4:EndIf
  	If Abs(drifty(tt)) > 4:drifty(tt) = Sign(drifty(tt))*4:EndIf
  Next
Return

checkcollisions:
  ;check collisons with ghosts
  sx=pac()\sx
  sy=pac()\sy
  ForEach g.ghost()
  	Select g()\act
  		Case #eyes
  			; do nothing
  		Case #edible
  			If Abs(sx-g()\sx)<7 And Abs(sy-g()\sy)<7
  				;collision between pac and ghost t
  				PlaySound(soundghost)
  				If SoundStatus(soundeyes,chsoundeyes)<>#PB_Sound_Playing:StopSound(soundblue,chsoundblue):chsoundeyes=PlaySound(soundeyes):EndIf
  				g()\act=#eyes
  				killed=killed+1
  				bluesleft = bluesleft-1
  				If bluesleft = 0:If SoundStatus(soundblue,chsoundblue)=#PB_Sound_Playing:StopSound(soundblue,chsoundblue):chsoundblue=0:EndIf:EndIf
  				score=score+200*Pow(2,killed-1)
  				AddElement(pts.pointstype())
  				pts()\v=#pointtime
  				pts()\x=g()\x*#gdsz
  				pts()\y=g()\y*#gdsz
  				pts()\frm=killed+99
  			EndIf
  		Case #deadly 
  			If Abs(sx-g()\sx)<4 And Abs(sy-g()\sy)<4
  				;collision between pac and ghost t
  				If #invincible = 0:gmode = #dyingmode:EndIf
  			EndIf
  	EndSelect
  Next
  ;check collision with prize
  If prize()\cage = 0
  	; check if pac and prize overlap
  	; if so eat prize
  	If Abs(sx-prize()\sx)<6 And Abs(sy-prize()\sy)<6
  		PlaySound(soundprize)
  		score+prizepoints(board)
  		prizeseaten = prizeseaten+1
  		AddElement(pts.pointstype())
  		pts()\v=#pointtime
  		pts()\x=prize()\sx
  		pts()\y=prize()\sy
  		pts()\frm=prizepoints(board)/100-1
  		; move back to cage
  		prize()\cage = 1
  		prizedir = 8
  		prize()\y=#cagey+1
  		prize()\x=#cagex
  		prize()\sy=prize()\y*#gdsz
  		prize()\sx=prize()\x*#gdsz
  		exspeed = exspeed + #PRIZEEXSPEED
  		If #PRIZEEXSPEED> 0:zoompowerflag = 60:EndIf
  		If exspeed > #MAXEXSPEED:exspeed = #MAXEXSPEED:EndIf
  	EndIf
  EndIf
Return

gobble:
  x=pac()\cx
  y=pac()\cy
  If gobble=1
  	munched=munched+1
  	slowdown = 3
  	If currentmap(x,y)=53
  		; power pellet
  		PlaySound(soundpower)
  		score+50
  		Gosub turnblue
  	ElseIf currentmap(x,y)=52
  		; dot
  		PlaySound(sounddot)
  		score+10
  	EndIf
  	currentmap(x,y)=255
  EndIf
  If munched=pillstotal
  	gmode = #donemode
  EndIf
Return

boardclear:
  Gosub soundoff
  Delay(300)
  PlaySound(soundboarddone)
  Delay(100)
  spbns=exspeed*10
  score+spbns*10
  For ft=0 To 8
  	If Int(ft/2)*2 = ft
  		Gosub drawmap
  		If spbns > 0 
  			DisplayTransparentSprite(bonusimage,#gdsz*#cagex-8+#M_XOFF,#gdsz*(#cagey+3))
  		Else
  			DisplayTransparentSprite(nobonusimage,#gdsz*#cagex-8+#M_XOFF,#gdsz*(#cagey+3))
  		EndIf
  	Else
  		ClearScreen(0)
  	EndIf
  	Gosub drawpacsleft
  	Gosub drawlevel
  	Gosub drawzoom
  	Gosub drawscore
  	FlipBuffers()
  	Delay(150)
  Next
Return

death:
  Gosub soundoff
  PlaySound(sounddeath)
  ForEach pts.pointstype()
  	DeleteElement(pts(),1)
  Next
  ;animate the death
  For ft = 0 To 3
    pac()\frm = 12+ft
  	Gosub drawmap
  	Gosub drawpac
  	Gosub drawscore
  	Gosub drawzoom
  	Gosub drawpacsleft
  	Gosub drawlevel
  	FlipBuffers()
  	Delay(300)
  Next
  ;one less pacman
  pacmen-1
  If restorezoom = 1
    exspeed = #MAXEXSPEED
  EndIf
  Gosub drawmap
  Gosub drawscore
  Gosub drawzoom
  Gosub drawpacsleft
  Gosub drawlevel
  FlipBuffers()
  Delay(300)
Return

loadmaps:
  fh.i=OpenFile(#PB_Any,"maps/allmaps.bin")
  For m=0 To #numbrds-1
  	For y=0 To #mapheight
  		chars$=ReadString(fh,#PB_Ascii)
  		For x=0 To #mapwidth
  			ch.a=Asc(Mid(chars$,x+1,1))-32
        maps(x,y,m)=ch ; read in all the chars
  		Next
  	Next
  Next
  CloseFile(fh)
Return

setupmap:
  ; put 255s in the far right and bottom 
  ; array pos for the openmap() array
  For x=0 To #mapwidth
  	currentmap(x,#mapheight)=255
  Next
  For y=0 To #mapheight
  	currentmap(#mapwidth,y)=255
  Next
  ; copy map from the maps()
  For x=0 To #mapwidth-1
  	For y=0 To #mapheight-1
  		character.a = maps(x,y,board)
  		If character.a=52 Or character.a=53
  			pillstotal+1
  		EndIf
  		If character.a=0:character.a=255:EndIf
  		currentmap(x,y) = character.a
  	Next
  Next
  ;create the mapopen array
  For x=1 To #mapwidth-2
  	For y=1 To #mapheight-2
  		opu = 0:If currentmap(x,y-1)>51:opu=1:EndIf ; above open
  		opd = 0:If currentmap(x,y+1)>51:opd=4:EndIf ; below open
  		opl = 0:If currentmap(x-1,y)>51:opl=8:EndIf ; left open
  		opr = 0:If currentmap(x+1,y)>51:opr=2:EndIf ; right open
  		mapopen(x,y)=opu+opd+opl+opr ; 0,1,2,3,4...15
  	Next
  Next
Return

drawmap:
  ClearScreen(0)
  If Random(30)>25:shinv = 1:Else:shinv = 0:EndIf
  ;DrawingMode(#PB_2DDrawing_Outlined)
  ;Box(0,0,320,240)
  ;DrawingMode(#PB_2DDrawing_Default)
  For y = 0 To #mapheight-1
  	For x = 0 To #mapwidth-1
  		character.a = currentmap(x,y)
  		Select character.a
  		Case 51
  			If shinv = 1:DisplayTransparentSprite(blockimages(2),x*#gdsz+#M_XOFF,y*#gdsz):EndIf
  		Case 53
  			; powerpill flashes on/off
  			If flashpill = 1
  				DisplayTransparentSprite(blockimages(character.a),x*#gdsz+#M_XOFF,y*#gdsz)
  			Else
  				DisplayTransparentSprite(blockimages(character.a+1),x*#gdsz+#M_XOFF,y*#gdsz)
  			EndIf
  		Case 255
  			; do nothing
  		Default
  			DisplayTransparentSprite(blockimages(character.a),x*#gdsz+#M_XOFF,y*#gdsz)
     	EndSelect
  	Next
  Next
Return

colorcycle:
  col+1
  If col = 9
  	col = 0
  	Colo=$FFFFFF
  EndIf
  If col = 1
  	Colo=RGB(255,0,0)
  EndIf
Return

credits:
  pac()\sx=320:pac()\sy=200
  Createghosts(5)
  ForEach g.ghost()
  	g()\sx=320:g()\sy=200:g()\frm=39
  Next
  ClearScreen(0)
  ; grab the ghost colors for printing their names
  For t=0 To 5
    DisplayTransparentSprite(ghostimages(t*8),0,t*16)
    StartDrawing(ScreenOutput())
    getcolor.l=Point(7,t*16+1)
  	gkol(t,0)=Red(getcolor)
  	gkol(t,1)=Green(getcolor)
  	gkol(t,2)=Blue(getcolor)
    StopDrawing()
  Next
  ctmr = 850:If highscore>0:ctmr=600:EndIf
  timer = 0
  resetcmtr=1200
  ExamineKeyboard()
  While KeyboardPushed(#PB_Key_F4)=0 And KeyboardPushed(#PB_Key_Escape)=0  ; f4 (62) to start, ESC (1) to quit
    If windowed And WindowEvent()=#PB_Event_CloseWindow:End:EndIf
    ExamineKeyboard()
    ClearScreen(0)
    DisplayTransparentSprite(mspacimage,106,28)
    StartDrawing(ScreenOutput())
    DrawingFont(FontID(0))
    
    col = timer
    FrontColor(RGB(255,0,0))
    For t = 0 To 18
    	Gosub colorcycle
    ;	DrawText(90+t*7,9,".",colo)
    	Box(90+t*7,12+9,2,2,colo)
    Next
    For t = 1 To 8
    	Gosub colorcycle
    ;	DrawText(216,t*7+8,".",colo)
    	Box(216,12+t*7+8,2,2,colo)
    Next
    For t = 18 To 0 Step -1
    	Gosub colorcycle
    ;	DrawText(90+t*7,70,".",colo)
    	Box(90+t*7,12+70,2,2,colo)
    Next 
    For t = 8 To 1 Step -1
    	Gosub colorcycle
    ;	DrawText(90,t*7+8,".",colo)
    	Box(90,12+t*7+8,2,2,colo)
    Next
    timer=timer+1:If timer > 8:timer = 0:EndIf
  
    ; move g onto screen
    If ctmr < 6
    	ForEach g.ghost()
    		If g()\id = ctmr
    			g()\sx = g()\sx - 2
    			g()\frmcnt = g()\frmcnt + 4:If g()\frmcnt >63:g()\frmcnt = 0:EndIf
    			g()\frm = g()\id*8 + 2 + g()\frmcnt/32 ; left
    			If g()\sx < 90
    				g()\sx = 90
    				g()\sy = g()\sy - 2
    	 			g()\frm =  g()\id*8 + 4 + g()\frmcnt/32 ; up
    				If g()\sy < 90 + ctmr*16
    		    	    g()\sy = 90+ctmr*16
    					g()\frm =  g()\id*8 + 6 ; down
    					ctmr = ctmr+1
    			 	EndIf
    			EndIf
    		EndIf
    	Next
    EndIf
    
    If ctmr > 5:ctmr=ctmr+1:EndIf
    
    colo=RGB(240,50,50)
    If ctmr >= 0 And ctmr <600
    	DrawText(130,90, "Blinky",RGB(gkol(0,0),gkol(0,1),gkol(0,2)))
    EndIf
    If ctmr >= 1 And ctmr <600
    	DrawText(130,106, "Pinky",RGB(gkol(1,0),gkol(1,1),gkol(1,2)))
    EndIf
    If ctmr >= 2 And ctmr <600
    	DrawText(130,122, "Inky",RGB(gkol(2,0),gkol(2,1),gkol(2,2)))
    EndIf
    If ctmr >= 3 And ctmr <600
    	DrawText(130,138, "Sue",RGB(gkol(3,0),gkol(3,1),gkol(3,2)))
    EndIf
    If ctmr >= 4 And ctmr <600
    	DrawText(130,154, "Winky",RGB(gkol(4,0),gkol(4,1),gkol(4,2)))
    EndIf
    If ctmr >= 5 And ctmr <600
    	DrawText(130,170, "Clyde",RGB(gkol(5,0),gkol(5,1),gkol(5,2)))
    EndIf
    If ctmr > 198 + 205 And ctmr <600
    	DrawText(130,200,"Ms BlitzMan",RGB(255,255,0))
    EndIf
    If ctmr = 198 + 15
    	ForEach g.ghost()
    		g()\frm = g()\id*8 + 0 ;gstrchar
      Next
    EndIf
    If ctmr = 198 + 100
    	ForEach g.ghost()
    		g()\frm = g()\id*8 + 6 ;gstdchar
      Next
    EndIf
    If ctmr = 198 + 120
    	ForEach g.ghost()
    		g()\frm = g()\id*8 + 2 ;gstlchar
      Next
    EndIf
    If ctmr = 198 + 196
    	ForEach g.ghost()
    		g()\frm = g()\id*8 + 6 ;gstdchar
      Next
    EndIf
      
    If ctmr > 198 And ctmr < 198 + 204
    	If ctmr < 198 + 160
    		pac()\sx=pac()\sx-2
    		pac()\frm=5
    	Else
    		pac()\sx = pac()\sx+2
    		pac()\frm=2
    	EndIf
    	pac()\frmcnt=pac()\frmcnt+4:If pac()\frmcnt > 63:pac()\frmcnt=0:EndIf
    	sc=Int(pac()\frmcnt/16)
    	Select sc
    		Case 0
    			pac()\frm=pac()\frm-1
    		Case 1
    			pac()\frm=pac()\frm-2
    		Case 2
    			pac()\frm=pac()\frm-1
    		Case 3
    			pac()\frm=pac()\frm
    	EndSelect
    EndIf
    StopDrawing()
    If ctmr < 600
    	ForEach g.ghost()
    		If ctmr >= g()\id 
    			DisplayTransparentSprite(ghostimages(g()\frm),g()\sx,g()\sy)
    		EndIf
    	Next
    EndIf
    If ctmr < 600 And ctmr > 198:DisplayTransparentSprite(pacimages(pac()\frm),pac()\sx,pac()\sy):EndIf
     
    If ctmr > 600 And ctmr < 850
      If highscore>0
        StartDrawing(ScreenOutput())
        DrawingFont(FontID(0))
        DrawText(85,120,"    High Score     ",RGB(200,200,200))
        StopDrawing()
    		skol = Int(Random(3,0))*10 ; random digit color
    		score = highscore
    		DisplayTransparentSprite(numberimages(skol),180,140) ; 0 
    		score/10
    		DisplayTransparentSprite(numberimages(skol+score1-Int(score1/10)*10),168,140) ; 10s
    		score1/10
    		DisplayTransparentSprite(numberimages(skol+score1-Int(score1/10)*10),156,140) ; 100s
    		score1/10
    		DisplayTransparentSprite(numberimages(skol+score1-Int(score1/10)*10),144,140) ; 1 000s
    		score1/10
    		DisplayTransparentSprite(numberimages(skol+score1-Int(score1/10)*10),132,140) ; 10 000s
    		score1/10
    		DisplayTransparentSprite(numberimages(skol+score1-Int(score1/10)*10),120,140) ; 100 000s
    	Else
    		ctmr = 850
    	EndIf
    EndIf
    If ctmr < 850
    	For key = #PB_Key_F1 To #PB_Key_F5
    	  ExamineKeyboard()
    	  If KeyboardPushed(key):ctmr = 850:EndIf
    	Next
    EndIf
    If ctmr > 849
      StartDrawing(ScreenOutput())
      DrawingFont(FontID(0))
      DrawText(50,120,"F1: Starting Level - ",RGB(180,240,180))
      StopDrawing()
      DisplayTransparentSprite(prizeimages(startinglevel),238,120)
    	StartDrawing(ScreenOutput())
      DrawingFont(FontID(0))
      control$ = "F2: Control Type - "
    	If keyorjoy = 0 
    		control$ = control$ + "Keyboard"
    	Else
    		control$ = control$ + "Joystick"
    	EndIf
    	DrawText(50,140, control$,RGB(180,240,180))
    	difficulty$ = "F3: Skill Level - "
    	Select sklevel
    		Case 0
    			difficulty$ = difficulty$ + "Easy"
    		Case 1
    			difficulty$ = difficulty$ + "Normal"
    		Case 2
    			difficulty$ = difficulty$ + "Medium"
    		Case 3
    			difficulty$ = difficulty$ + "Hard"
    		Case 4
    			difficulty$ = difficulty$ + "Hard++"
    	EndSelect
    	DrawText(50,160, difficulty$,RGB(180,240,180))
    	DrawText(50,180, "F4: Start Game",RGB(180,240,180))
    	DrawText(50,210, "F5: Help",RGB(180,240,180))
    	If KeyboardReleased(#PB_Key_F1):ctmr=850:startinglevel+1:If startinglevel>lastboard:startinglevel=0:EndIf:EndIf
    	If KeyboardReleased(#PB_Key_F2):ctmr=850:keyorjoy+1:If keyorjoy>1:keyorjoy=0:EndIf:EndIf
    	If KeyboardReleased(#PB_Key_F3)
    		ctmr=850
    		sklevel = sklevel + 1
    		If sklevel > 4:sklevel = 0:EndIf
    	EndIf
    	If KeyboardReleased(#PB_Key_F5)
    	  ctmr = 850
    		Gosub helpscreen
    	EndIf
      StopDrawing()
    EndIf
    If ctmr > resetcmtr
    	ctmr = 0
    	pac()\sx=320:pac()\sy=200
    	ForEach g.ghost()
    		g()\sx=320:g()\sy=200:g()\frm=39
    	Next
    EndIf
    FlipBuffers()
    ;If KeyboardReleased(#PB_Key_F12) SaveBuffer(FrontBuffer(),"SNAPHOT"+timer+".bmp")
  Wend
  If KeyboardPushed(#PB_Key_Escape):End:EndIf
Return

helpscreen:
  StopDrawing()
  ClearScreen(0)
  FlipBuffers()
  ClearScreen(0)
	StartDrawing(ScreenOutput())
  DrawingFont(FontID(0))
  DrawText(50,5,"     Ms Blitzman Help",RGB(250,20,0))
  DrawText(50,30,  "  Keyboard Controls:",RGB(250,100,0))
  DrawText(50,50, "    Cursor Keys L/R/U/D",RGB(250,200,0))
  DrawText(50,70, "    SPACEBAR for Zoom",RGB(200,250,0))
  DrawText(50,100, "  Joystick Controls:",RGB(100,250,0))
  DrawText(50,120, "        L/R/U/D",RGB(20,250,0))
  DrawText(50,140, "   Fire Button for Zoom",RGB(20,250,100))
  DrawText(50,160, "   ESC to Quit Playing",RGB(20,250,200))
  DrawText(50,180, "Eat Prizes For Zoom Power",RGB(20,200,250))
  DrawText(50,200, "    Hit F5 to Return",RGB(20,100,250))
  StopDrawing()
  FlipBuffers()
  ExamineKeyboard()
  While KeyboardReleased(#PB_Key_F5)=0
    Delay(10):ExamineKeyboard()
  Wend
Return
Last edited by Psychophanta on Sun Jan 21, 2018 10:38 pm, edited 1 time in total.
http://www.zeitgeistmovie.com

While world=business:world+mafia:Wend
Will never leave this forum until the absolute bugfree PB :mrgreen:
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5342
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: Ms BlitzMan translated to PB

Post by Kwai chang caine »

Waooouuuh very nice !!! :shock:
Works fine here with W10 X64 8)
I'm not really a fan of games, but i surprising me several time, to play with your translate of PACMAN old game :lol:
That remember the good time of the first games when i have young and found that a miracle of electronic :shock:
Thanks for sharing this great code 8)
ImageThe happiness is a road...
Not a destination
User avatar
Psychophanta
Addict
Addict
Posts: 4968
Joined: Wed Jun 11, 2003 9:33 pm
Location: Lípetsk, Russian Federation
Contact:

Re: Ms BlitzMan translated to PB

Post by Psychophanta »

Thank you Kwai chang :)
http://www.zeitgeistmovie.com

While world=business:world+mafia:Wend
Will never leave this forum until the absolute bugfree PB :mrgreen:
User avatar
Andre
PureBasic Team
PureBasic Team
Posts: 2056
Joined: Fri Apr 25, 2003 6:14 pm
Location: Germany (Saxony, Deutscheinsiedel)
Contact:

Re: Ms BlitzMan translated to PB

Post by Andre »

Very nice old-skool game, thank you :mrgreen:

More conversions of old (BlitzBasic) game packages are welcome! 8)
Bye,
...André
(PureBasicTeam::Docs & Support - PureArea.net | Order:: PureBasic | PureVisionXP)
User avatar
Psychophanta
Addict
Addict
Posts: 4968
Joined: Wed Jun 11, 2003 9:33 pm
Location: Lípetsk, Russian Federation
Contact:

Re: Ms BlitzMan translated to PB

Post by Psychophanta »

Andre wrote:Very nice old-skool game, thank you :mrgreen:

More conversions of old (BlitzBasic) game packages are welcome! 8)
Thanks Mr. Andre.
Indeed, to the PB is wellcome the conversions from BlitzBasic, and there are lots of nice works waiting to be converted.
The bad part is there seem not possible to make a software to convert it, not even to make the task easy, I mean, finally, the conversion implicates to get more or less deeply in the code.

Salud!
http://www.zeitgeistmovie.com

While world=business:world+mafia:Wend
Will never leave this forum until the absolute bugfree PB :mrgreen:
User avatar
Bisonte
Addict
Addict
Posts: 1226
Joined: Tue Oct 09, 2007 2:15 am

Re: Ms BlitzMan translated to PB

Post by Bisonte »

Sorry, but it will give me an IMA at line 191 "StartDrawing(ScreenOutput())" and I don't know why.....

I try to compile it with pb5.46 x86,x64 and pb 5.61 x86 and x64... on Win10 Pro x64....
PureBasic 6.04 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom​​
English is not my native language... (I often use DeepL to translate my texts.)
User avatar
VB6_to_PBx
Enthusiast
Enthusiast
Posts: 617
Joined: Mon May 09, 2011 9:36 am

Re: Ms BlitzMan translated to PB

Post by VB6_to_PBx »

Bisonte wrote:Sorry, but it will give me an IMA at line 191 "StartDrawing(ScreenOutput())" and I don't know why.....

I try to compile it with pb5.46 x86,x64 and pb 5.61 x86 and x64... on Win10 Pro x64....
i get the very same ERROR
using those same PB versions
but on Win-7 64-bit Computer using PB x86 versions
 
PureBasic .... making tiny electrons do what you want !

"With every mistake we must surely be learning" - George Harrison
User avatar
mk-soft
Always Here
Always Here
Posts: 5335
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Ms BlitzMan translated to PB

Post by mk-soft »

320x240 not supported ?

How to find sounds and images?
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
Bisonte
Addict
Addict
Posts: 1226
Joined: Tue Oct 09, 2007 2:15 am

Re: Ms BlitzMan translated to PB

Post by Bisonte »

Not supported ScreenSize ;) You are right. The next Problem are the loaded images... and now I see I have to download the original ;)
PureBasic 6.04 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom​​
English is not my native language... (I often use DeepL to translate my texts.)
User avatar
Psychophanta
Addict
Addict
Posts: 4968
Joined: Wed Jun 11, 2003 9:33 pm
Location: Lípetsk, Russian Federation
Contact:

Re: Ms BlitzMan translated to PB

Post by Psychophanta »

Yes, the problem is modern VGAs, with lacks about some resolutions, and 16 bit depth (which is the screen depth in the original Blitz code).

Edited the first post to fix code for pause the game pushing "P" key.
http://www.zeitgeistmovie.com

While world=business:world+mafia:Wend
Will never leave this forum until the absolute bugfree PB :mrgreen:
Bitblazer
Enthusiast
Enthusiast
Posts: 733
Joined: Mon Apr 10, 2017 6:17 pm
Location: Germany
Contact:

Re: Ms BlitzMan translated to PB

Post by Bitblazer »

I just checked on my system with an nvidia card on windows. The nvidia sytemcontrol lists the gfx modes and allows to change them. The lowest resolution is 800x600, but i have the option to create and enable custom resolutions including 16bit ones and lowresolutions. I guess you could create a custom setting but then the monitor support will be the next big problem. Its also rather impractical to ask users to do all this themselves just to execute some game which otherwise simply fails with "cant switch to 320x240 16-bit videomode".

But luckily todays computers are fast enough to upscale video graphics in realtime, so i suggest three solutions.
a) find the best supported video resolution with the same aspect ratio, switch to the resolution and scale a virtual 320x240 buffer up to display it
b) show it in a window in original resolution (beware, this will be laughable tiny, so you better offer the option to show x2, x4, x8 versions
c) do B) but with a window where the border and top line is hidden and its displayed at a negative offset covering the full screen, basically it will act like a fullscreen to the user (i think some other games call this a fullscreen window mode)

All three solutions will make the game appear like the original 320x240 arcade screen without giving the user trouble with video mode hacking or resolution/monitor problems. So it will be super easy to run the game which means you have more fans/users and basically you need such a solution for ancient resolutions anyway :)

Also you better convert the 16-bit colormode display to a 32bit RGBA - but this can be done during the postprocessing/upscaling of the 320x240 framebuffer.
webpage - discord chat links -> purebasic GPT4All
User avatar
Psychophanta
Addict
Addict
Posts: 4968
Joined: Wed Jun 11, 2003 9:33 pm
Location: Lípetsk, Russian Federation
Contact:

Re: Ms BlitzMan translated to PB

Post by Psychophanta »

Thank you for your advise Bitblazer.
I really want to translate more BlitzBasic programs to PureBasic, and I am making some tools to make easier these tasks. Not enough time is the omnipresent obstacle, but I will try.
So, thanks again for your careful observation.
http://www.zeitgeistmovie.com

While world=business:world+mafia:Wend
Will never leave this forum until the absolute bugfree PB :mrgreen:
User avatar
bfernhout
Enthusiast
Enthusiast
Posts: 123
Joined: Mon Feb 26, 2018 10:41 pm
Location: Netherlands
Contact:

Re: Ms BlitzMan translated to PB

Post by bfernhout »

Hey.

Its nicly done. I like it.
I am a former PBlitz3D user. Did do a lot in blitz. An d currently buzu is a big project of reprogramming a old AMIGA game to PC. Using the Blitz3D for it. This project takes alreadt up 3 years. A lot of graphics and sound ripping.
The sound has to cleaned up to be for good use. The graphics is on a very low pixel mode. All the graphics i had to upsized time 2. And that was a lot of hand working. Cause Blitz3D did do the job not correctly.
Anyway beside the poind. The screen resolution is on my computer no problem i use a MSI win 10 16GB mem and 4 TB SSD (Got it in china). The whole program is working like a charm. The 16 bits mode is a problem on the newer computers. Itys not that the screen can't handle. Its the drivers that not willing. When upgrade to 32 bits its ok. Today computers can handle this. I had a computer that works on win 8.1 64 bits. And it hase the same problem, could not handle 16 bits. Then i search the internet and found some pretty old drivers for that computer. Removed the new drivers and install the old drivers. And what you think. The 16 bits mode was no problem anymore.
Testing in game speed using the 16 and the 32 mode. I could not find any differend is speed, but in Blitz3D there was a frame lost of 2 FPS from 35 to 33. This is stil good there a frame rate or 30 is the bare minimum to get good animation on screen.

Keep working and do please recode a lot of Blitz3D files to PD.

N.B. I am starting from today a new PB user.
From my first self made computer till now I stil like computers.
Post Reply