'%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ' Puk Man! Programmed in Yabasic in September 2001 (C) ' Based on one of the all time classics!!! 'This program is public domain but remains the work and 'property of: Nick Simpson (Shockwave). 'Email me on: nicksimpson007@aol.com ' 'You may NOT distibute this unless all of the program 'comments in this listing and also the program remains 'the same in it's entirety. This may not be published for 'commercial gain or on any website or on any magazine 'cover disk without my consent. ' 'Enjoy the game!! ' ' Complete Version 1.0 finished on 21/09/01 '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ' This is an important variable! passed the direction=0 :rem move direction to maze update 1L 2R 3U 4D ghostnum=4 dim ghonblock(ghostnum) :rem set to 0 if on block. dim ghostmove(ghostnum) :rem movement direction of ghost dim usbx(5) : rem used for storing player and enemy dim usby(5) : rem regeneration points! dim gstx(ghostnum) :rem ghost x position dim gsty(ghostnum) :rem ghost y position dim grgx(ghostnum) :rem ghost regeneration point x dim grgy(ghostnum) :rem ghost regeneration point y dim mazes(20,30) : Rem This array stores All the levels dim maze(20,15) : Rem IS THE ARRAY THAT STORES THE MAZE open window 400,400 dw=0 high=2500 for y=1 to 30 for x=1 to 20 read mazes(x,y) next x next y label start gosub titlescreen level=1 score=0 lives=3 lp=0 repeat '%%%%%%%%%%%%%%%%%%%%% '%%% Refresh level:%%% '%%%%%%%%%%%%%%%%%%%%% for y=1+lp to 15+lp for x=1 to 20 maze(x,y-lp)= mazes(x,y) next x next y lp=lp+15 if lp>15 lp=0 for a=1 to 4 ghostmove(a)=int(1+ran(3)) ghonblock(a)=0 next a levelchecksum=0 :rem automatically set by program move=0 : rem player move variable 0=None 1=L 2=R 3=U 4=D om=0 setdrawbuf dw clear window gosub drawmazecomplete dw=1-dw setdrawbuf dw clear window gosub drawmazecomplete plxsc=(plyrx*32)-16:rem convert to screen positions plysc=(plyry*32)-16 powpil=0 repeat setdispbuf dw dw=1-dw setdrawbuf dw if death=1 gosub lossoflife 'prevent bits of ghost being left behind if gkf>0 then xwork=gx1 ywork=gy1 direction=1 gosub updatearoundsprites direction=3 gosub updatearoundsprites gkf=gkf-1 end if for gnum=1 to 4 if gmf=0 gosub ghostmve next gnum for a=1 to 4 direction=ghostmove(a) xwork=int(gstx(a)/32)+1:rem calculate ghost block x ywork=int(gsty(a)/32)+1:rem calculate ghost block y '>>>>>collision between player and ghost! gosub updatearoundsprites if xwork=plyrx and ywork=plyry and powpil=0 death=1 if xwork=plyrx and ywork=plyry and powpil>0 then gx1=xwork gy1=ywork gkf=2 score=score+100 gstx(a)=usbx(a) gsty(a)=usby(a) ghonblock(a)=0 fi next a gosub playermove xwork=plyrx:rem pass player x,y block to routine ywork=plyry direction=move gosub updatearoundsprites gosub drawpacman gosub drawghosts gosub scoretable if powpil>0 then powpil=powpil-.5 gmf=gmf+1 fi if gmf>1 gmf=0 if powpil=0 gmf=0 until ((lives=0) or (levelchecksum=0)) if lives>0 level=level+1 until (lives=0) goto start '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ' Take life and redraw the maze, reset ghosts and pacman '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% label lossoflife lives=lives-1 pause 1 clear window gosub drawmazecomplete dw=1-dw setdrawbuf dw gosub drawmazecomplete death=0 for a=1 to 4 ghonblock(a)=0 next a plxsc=(plyrx*32)-16:rem convert to screen positions plysc=(plyry*32)-16 move=0 plmove=0 return '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ' Move the ghosts around and see if they need to make any ' descisions! '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% label ghostmve if ghonblock(gnum)=0 gosub ghostmoveselect if ghostmove(gnum)=1 gstx(gnum)=gstx(gnum)-2 if ghostmove(gnum)=2 gstx(gnum)=gstx(gnum)+2 if ghostmove(gnum)=3 gsty(gnum)=gsty(gnum)-2 if ghostmove(gnum)=4 gsty(gnum)=gsty(gnum)+2 ghonblock(gnum)=ghonblock(gnum)-1 return '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ' Decide on ghost direction movement! 'These descisions are only made when in line with blocks! ' This subroutine is the enemy's AI. The enemy will make ' it's own descisions as to where to go, the enemy also ' actively tracks you through the maze and will work out ' the best way to get to you but can also give up!!!!!!! '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% label ghostmoveselect if ghostmove(gnum)=1 hate=2 if ghostmove(gnum)=2 hate=1 if ghostmove(gnum)=4 hate=3 if ghostmove(gnum)=3 hate=4 nmv=0 whwh=ran(100) xwork=int(gstx(gnum)/32)+1:rem calculate ghost block x ywork=int(gsty(gnum)/32)+1:rem calculate ghost block y ' Check for dead ends! if (ghostmove(gnum)=1) and (maze(xwork-1,ywork)=1) nmv=1 if (ghostmove(gnum)=2) and (maze(xwork+1,ywork)=1) nmv=1 if (ghostmove(gnum)=3) and (maze(xwork,ywork-1)=1) nmv=1 if (ghostmove(gnum)=4) and (maze(xwork,ywork+1)=1) nmv=1 ' 'Look for avenues above and below (if moving L or R)! ' if (nmv=0) and (ghostmove(gnum)<=2) then if maze(xwork,ywork-1)<>1 and (whwh<40) ghostmove(gnum)=3 if maze(xwork,ywork+1)<>1 and (whwh<40) ghostmove(gnum)=4 nmv=3 end if if (nmv=0) and (ghostmove(gnum)>=2) then if maze(xwork-1,ywork)<>1 and (whwh<40) ghostmove(gnum)=1 if maze(xwork+1,ywork)<>1 and (whwh<40) ghostmove(gnum)=2 end if '*************************************************** '**select new direction in the case of a dead end!** '*************************************************** if nmv=1 then mp1=0 mp2=0 mp3=0 mp4=0 if maze(xwork-1,ywork)<>1 then ghostmove(gnum)=1 mp1=1 fi if maze(xwork+1,ywork)<>1 then ghostmove(gnum)=2 mp2=1 fi if maze(xwork,ywork-1)<>1 then ghostmove(gnum)=3 mp3=1 fi if maze(xwork,ywork+1)<>1 then ghostmove(gnum)=4 mp4=1 fi prob1=0 prob2=0 prob3=0 prob4=0 if plyrxxwork prob2=60 if plyry>ywork prob4=60 if plyry4 and whwh<30+prob4 ghostmove(gnum)=4 if mp3=1 and hate <>3 and whwh<30+prob3 ghostmove(gnum)=3 if mp2=1 and hate <>2 and whwh<30+prob2 ghostmove(gnum)=2 if mp1=1 and hate <>1 and whwh<30+prob1 ghostmove(gnum)=1 end if ghonblock(gnum)=16 return '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ' Draw the ghost graphics on screen! '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% label drawghosts for a=1 to ghostnum setrgb 1,200+ran(20)-powpil,50+ran(20)+powpill*2,80+powpil fill rectangle gstx(a)-12,gsty(a)-12 to gstx(a)+12,gsty(a)+14 setrgb 1,255,255,255 fill rectangle gstx(a)-7,gsty(a)-7 to gstx(a)+7,gsty(a)+2 setrgb 1,0,0,0 fill rectangle gstx(a)-2,gsty(a) to gstx(a)-5,gsty(a)-5 fill rectangle gstx(a)+2,gsty(a) to gstx(a)+5,gsty(a)-5 next a return '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ' Update Score pannel '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% label scoretable if score>high high=score setrgb 1,155,80,90 fill rectangle 30,484 to 610,508 setrgb 1,255,255,255 text 50,500,"SCORE-"+str$(score)+" LEVEL-"+str$(level)+" HIGHEST SCORE-"+str$(high)+" LIVES-"+str$(lives) return '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ' Reads Joypad And moves player position accordingly!!!!!! ' Also pause function It only allows a change in the ' direction of movement when a corridor is perfectly ' lined up so that everything stays nice and accurate! ' also detects pill eating! '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% label playermove if and(peek("port1"),8)=8 gosub paus ' %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ' %%% Read pad!If there is no remainder! %%% ' %%% This makes things much easier!!!!! %%% ' %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% if (plyrx=plyrx2) and (plyry=plyry2) then '%%%%%%%%%%%%%%% '%% eat pill! %% '%%%%%%%%%%%%%%% if maze(plyrx,plyry)=2 then levelchecksum=levelchecksum-1 score=score+5 maze(plyrx,plyry)=0 end if '%%%%%%%%%%%%%%%%%%%%% '%% eat power pill! %% '%%%%%%%%%%%%%%%%%%%%% if maze(plyrx,plyry)=3 then levelchecksum=levelchecksum-1 score=score+50 maze(plyrx,plyry)=0 powpil=250 end if om=move if peek("port1")=0 goto jumpplcheck if and(peek("port1"),32)=32 move=2 if and(peek("port1"),16)=16 move=3 if and(peek("port1"),64)=64 move=4 if and(peek("port1"),128)=128 move=1 if peek("port1")<>0 then if (move=1) and (maze(plyrx-1,plyry)=1) move=om if (move=2) and (maze(plyrx+1,plyry)=1) move=om if (move=3) and (maze(plyrx,plyry-1)=1) move=om if (move=4) and (maze(plyrx,plyry+1)=1) move=om end if label jumpplcheck if (move=1) and (maze(plyrx-1,plyry)=1) move=0 if (move=2) and (maze(plyrx+1,plyry)=1) move=0 if (move=3) and (maze(plyrx,plyry-1)=1) move=0 if (move=4) and (maze(plyrx,plyry+1)=1) move=0 om=move end if '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% '%%% Check for collisions between walls and player 1 %%% '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% if move=1 plxsc=plxsc-2 if move=2 plxsc=plxsc+2 if move=3 plysc=plysc-2 if move=4 plysc=plysc+2 plyrx=int(plxsc/32)+1:rem calculate player block x plyry=int(plysc/32)+1:rem calculate player block y plyrx2=((plxsc+16)/32):rem calculate player block x plyry2=((plysc+16)/32):rem calculate player block y return '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ' Wait until a button is pressed!! '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% label paus pause .8 repeat until (peek("port1")<>0) return '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ' Draws the pacman graphic on the screen! '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% label drawpacman mouth=mouth+1 if mouth=16 mouth=1 '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% '%% call Maze Update routine! %% '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% setrgb 1,255,255,16 fill circle plxsc-1,plysc,14 if (move=2) and (mouth<8) then setrgb 1,0,0,0 fill triangle plxsc-4,plysc to plxsc+14,plysc-15 to plxsc+14 , plysc+15 end if if (move=1) and (mouth<8) then setrgb 1,0,0,0 fill triangle plxsc+4,plysc to plxsc-15,plysc-15 to plxsc-15 , plysc+15 end if if (move=3) and (mouth<8) then setrgb 1,0,0,0 fill triangle plxsc,plysc+4 to plxsc-15,plysc-15 to plxsc+15,plysc-15 end if if (move=4) and (mouth<8) then setrgb 1,0,0,0 fill triangle plxsc,plysc-4 to plxsc-15,plysc+15 to plxsc+15,plysc+15 end if return '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ' This routine updates the block that the sprite is on ' and also the four others around it.. This saves the ' whole maze being updated and still enables double ' buffering to take place. Clever eh?! This same code is ' used for the player sprite AND the ghosts. '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% label updatearoundsprites x=xwork y=ywork gosub partialmazeupdate if direction=1 or direction=2 then x=xwork-1 y=ywork gosub partialmazeupdate x=xwork+1 y=ywork gosub partialmazeupdate fi if (direction=3) or (direction=4) then x=xwork y=ywork+1 gosub partialmazeupdate x=xwork y=ywork-1 gosub partialmazeupdate fi return '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ' Take out five blocks and then replace them! '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% label partialmazeupdate xst=(x*32)-32 yst=(y*32)-32 setrgb 1,0,0,0 fill rectangle xst,yst to xst+32,yst+32 if maze(x,y)=1 then setrgb 1,140,140,250 fill rectangle xst,yst to xst+30,yst+30 setrgb 1,130,80,200 fill rectangle xst+2,yst+2 to xst+30,yst+30 fi if maze(x,y)=3 then setrgb 1,250,250,250 fill rectangle xst+6,yst+6 to xst+24,yst+24 end if if maze(x,y)=2 then setrgb 1,225,255,0 fill rectangle xst+10,yst+11 to xst+19,yst+19 end if return '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ' Complete screen update of the maze! ' This is only updated at the beginning of the level!!!!! ' Copies the screen display onto both the logical and ' physical screens!!! '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% label drawmazecomplete clear window levelchecksum=0 for z=1 to 2 xst=0 yst=0 for y=1 to 15 for x=1 to 20 if maze(x,y)=1 then setrgb 1,140,140,250 fill rectangle xst,yst to xst+30,yst+30 setrgb 1,130,80,200 fill rectangle xst+2,yst+2 to xst+30,yst+30 fi if maze(x,y)=3 then levelchecksum=levelchecksum+.5 setrgb 1,250,250,250 fill rectangle xst+6,yst+6 to xst+24,yst+24 end if if maze(x,y)=2 then levelchecksum=levelchecksum+.5 setrgb 1,225,255,0 fill rectangle xst+10,yst+11 to xst+19,yst+19 end if '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 'Look for ghost regeneration points and store if found! '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% if maze(x,y)=5 then gstx(1)=xst+15 gsty(1)=yst+15 usbx(1)=xst+15 usby(1)=yst+15 fi if maze(x,y)=6 then gstx(2)=xst+15 gsty(2)=yst+15 usbx(2)=xst+15 usby(2)=yst+15 fi if maze(x,y)=7 then gstx(3)=xst+15 gsty(3)=yst+15 usbx(3)=xst+15 usby(3)=yst+15 fi if maze(x,y)=8 then gstx(4)=xst+15 gsty(4)=yst+15 usbx(4)=xst+15 usby(4)=yst+15 fi if maze(x,y)=9 then plyrx=x plyry=y usbx(5)=x usby(5)=y fi xst=xst+32 next x xst=0 yst=yst+32 next y setdispbuf dw dw=1-dw setdrawbuf dw next z death=0 return ' The Mazes!! ' ~~~~~~~~~~ ' Re-define to make new levels! ' You must include the ghost and player start points and ' have at least one pill and also a maze bordered with ' blocks to prevent crashes! ' ' 0=empty block ' 1=wall ' 2=normal pill ' 3=power pill ' ' 5=ghost1 start point ' 6=ghost2 start point ' 7=ghost3 start point ' 8=ghost4 start point ' 9=player1 start point data 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 data 1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1 data 1,2,1,1,2,1,1,1,2,1,1,2,1,1,1,2,1,1,2,1 data 1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,1 data 1,2,2,2,1,1,1,1,1,2,1,1,1,1,1,1,2,2,2,1 data 1,2,1,2,1,2,2,3,1,2,2,2,2,2,3,1,2,1,2,1 data 1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,2,1 data 1,3,2,2,2,2,1,5,6,7,8,2,2,2,2,2,2,2,2,1 data 1,2,1,2,1,1,1,1,1,1,1,1,1,1,2,1,2,1,3,1 data 1,2,1,2,1,3,2,2,0,9,1,2,2,2,2,1,2,1,2,1 data 1,2,2,2,1,1,1,1,1,0,1,1,1,1,1,1,2,2,2,1 data 1,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,1 data 1,2,1,1,2,1,1,1,2,1,1,2,1,1,1,2,1,1,2,1 data 1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1 data 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 data 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 data 1,3,2,2,1,2,2,1,2,2,1,2,2,2,2,2,2,2,3,1 data 1,2,1,1,1,2,1,1,1,2,1,2,1,1,1,1,1,1,2,1 data 1,2,1,2,2,2,2,2,2,2,1,2,2,2,2,2,2,1,2,1 data 1,2,1,2,1,1,1,2,1,1,1,2,1,1,1,1,2,1,1,1 data 1,2,2,2,1,2,2,2,2,2,2,2,2,2,2,1,2,2,2,1 data 1,2,1,2,1,2,1,1,1,0,1,1,1,1,2,1,2,1,2,1 data 1,2,1,2,2,2,1,5,6,0,0,7,8,1,2,1,2,1,2,1 data 1,1,1,2,1,2,1,1,1,1,1,1,1,1,2,1,2,1,2,1 data 1,2,1,2,1,2,2,2,0,9,0,2,2,2,2,1,2,1,2,1 data 1,2,1,2,1,1,1,1,1,0,1,2,1,1,1,1,2,1,2,1 data 1,2,2,2,1,2,2,2,2,2,1,2,2,2,2,2,2,1,2,1 data 1,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,2,1,2,1 data 1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,1 data 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 gosub titlescreen '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 'A simple and badly coded title page for the game!!!!!!!!! '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% label titlescreen tnc=0 repeat tnc=tnc+1 setdrawbuf dw dw=1-dw setdispbuf dw setrgb 1,30+30*sin(tnc/17),10,10 setrgb 2,10,30+30*sin(tnc/15),10 setrgb 3,10,10,30+30*sin(tnc/13) 'clear screen with plasma gtriangle 0,0 to 640,512 to 0,512 gtriangle 0,0 to 640,512 to 640,0 setrgb 1,0,0,0 text 247,27,"P U K - M A N" setrgb 1,255,255,255 text 245,24,"P U K - M A N" setrgb 1,200,200,100 text 210,490,"TODAYS HIGH SCORE:"+str$(high) text 230,505,"LAST GAME SCORE:"+str$(score) setrgb 1,255,255,100+100*sin(tnc/8) text 115,105,"PROGRAMMED BY NICK SIMPSON AKA SHOCKWAVE" text 115,125,"========================================" text 115,145," INSTRUCTIONS:" text 115,165," =============" text 115,185,"USE THE JOYPAD TO CONTROL PUK MAN. EAT" text 115,205,"ALL THE DOTS TO COMPLETE A LEVEL! IF YOU" text 115,225,"EAT A POWER DOT YOU CAN TEMPORARILY EAT" text 115,245,"THE GHOSTS!! IF A GHOST CATCHES YOU WHEN" text 115,265," IT IS NOT VULNERABLE YOU LOSE A LIFE" text 115,285,"YOU CAN PAUSE THE GAME BY PRESSING THE" text 115,305," START BUTTON ON YOUR CONTROL PAD!!" text 115,325," ==================================" text 115,345,"IF YOU WANT TO SEE SOME MORE OF MY WORK" text 115,365,"OR IF YOU ARE JUST INTERESTED IN YABASIC" text 115,385,"PROGRAMMING, CONTACT ME VIA THE ACE SITE" text 115,405," WWW.YABASIC.CO.UK" text 115,425,"PRESS THE (X) BUTTON TO BEGIN A NEW GAME" until (peek("port1")=16384) return ======================================================= The above listing is 100% correct with NO errors....... ! !S H O C K W A V E ! ! =======================================================