NotebookPut[Notebook[{Cell[BoxData@ToBoxes@DynamicModule[{maze,rows,cols,player,dir,nextDir,phase,score,dotsList,ghost,ghostDir,ghostTimer,gameState="Start",staticBackground,lastKeySerial=0,cellCenter,canMoveQ,resetGame,setDirection,movePlayer,moveGhost,checkCollisions,readNotebookInput,tick,handleClick,drawGraphics},maze={{1,1,1,1,1,1,1,1,1,1,1,1,1},{1,0,0,0,0,0,1,0,0,0,0,0,1},{1,0,1,1,0,1,1,1,0,1,1,0,1},{1,0,0,0,0,0,0,0,0,0,0,0,1},{1,1,0,1,1,0,2,0,1,1,0,1,1},{1,0,0,0,0,0,0,0,0,0,0,0,1},{1,1,1,1,1,1,1,1,1,1,1,1,1}};
rows=Length[maze];
cols=Length[First[maze]];
player={2,2};
dir={0,0};
nextDir={0,0};
phase=0;
score=0;
ghost={12,5};
ghostDir={-1,0};
ghostTimer=0;
dotsList={};
cellCenter[pos_]:={pos[[1]]-0.5,rows-pos[[2]]+0.5};
canMoveQ[pos_,d_]:=Module[{p=pos+d},1<=p[[1]]<=cols&&1<=p[[2]]<=rows&&maze[[p[[2]],p[[1]]]]!=1];
staticBackground={Black,Rectangle[{0,0},{cols,rows}],Table[If[maze[[r,c]]==1,{RGBColor[0.05,0.18,0.95],EdgeForm[RGBColor[0.12,0.35,1]],Rectangle[{c-1,rows-r},{c,rows-r+1}]},Nothing],{r,rows},{c,cols}]};
resetGame[]:=(player={2,2};
dir={0,0};
nextDir={0,0};
phase=0;
score=0;
ghost={12,5};
ghostDir={-1,0};
ghostTimer=0;
dotsList=Flatten[Table[If[maze[[r,c]]==0&&{c,r}!=player,{{c,r}},{}],{r,rows},{c,cols}],2];
gameState="Playing";);
setDirection[d_]:=(If[MemberQ[{"Start","GameOver","Clear"},gameState],resetGame[]];
nextDir=d;
If[canMoveQ[player,d],dir=d];);
readNotebookInput[]:=Module[{serial,d},serial=Replace[CurrentValue[EvaluationNotebook[],{TaggingRules,"PacManKeySerial"}],Except[_Integer]->0];
If[serial=!=lastKeySerial,lastKeySerial=serial;
d=CurrentValue[EvaluationNotebook[],{TaggingRules,"PacManDirection"}];
If[MemberQ[{{-1,0},{1,0},{0,-1},{0,1}},d],setDirection[d]];];];
movePlayer[]:=(If[nextDir!={0,0}&&canMoveQ[player,nextDir],dir=nextDir];
If[dir!={0,0}&&canMoveQ[player,dir],player=player+dir;
phase++;
If[MemberQ[dotsList,player],dotsList=DeleteCases[dotsList,player];
score+=10;
If[dotsList=={},gameState="Clear"];];];);
moveGhost[]:=Module[{dirs,validMoves,forward},ghostTimer++;
If[OddQ[ghostTimer],Return[]];
dirs={{1,0},{-1,0},{0,1},{0,-1}};
validMoves=Select[dirs,canMoveQ[ghost,#]&&#!=-ghostDir&];
If[validMoves=={},validMoves=Select[dirs,canMoveQ[ghost,#]&]];
forward=canMoveQ[ghost,ghostDir];
If[validMoves!={}&&(!forward||RandomReal[]<0.25),ghostDir=RandomChoice[validMoves]];
If[canMoveQ[ghost,ghostDir],ghost=ghost+ghostDir];];
checkCollisions[]:=(If[player==ghost,gameState="GameOver"];);
tick[]:=(readNotebookInput[];
If[gameState=="Playing",movePlayer[];
checkCollisions[];
If[gameState=="Playing",moveGhost[];
checkCollisions[];];];);
handleClick[]:=(If[MemberQ[{"Start","GameOver","Clear"},gameState],resetGame[]];);
drawGraphics[]:=Graphics[{staticBackground,If[gameState!="Start",{White,PointSize[0.016],Point[cellCenter/@dotsList],Yellow,With[{center=cellCenter[player],angle=If[dir=={0,0},0,ArcTan[dir[[1]],-dir[[2]]]],mouth=If[dir=={0,0},0.2,0.25 Abs[Sin[phase Pi/2]]]},Disk[center,0.4,{angle+mouth,angle+2 Pi-mouth}]],Red,Disk[cellCenter[ghost],0.4],White,Disk[cellCenter[ghost]+{-0.15,0.1},0.1],Disk[cellCenter[ghost]+{0.15,0.1},0.1],Black,Disk[cellCenter[ghost]+{-0.15,0.1}+0.04 {ghostDir[[1]],-ghostDir[[2]]},0.05],Disk[cellCenter[ghost]+{0.15,0.1}+0.04 {ghostDir[[1]],-ghostDir[[2]]},0.05],White,Text[Style["SCORE: "<>ToString[score],FontSize->14,Bold,FontFamily->"Courier"],{2.5,rows+0.4}]},Nothing],Switch[gameState,"Start",{Black,Rectangle[{0,0},{cols,rows}],Yellow,Disk[{6.5,4.5},1.0,{0.5,5.8}],Text[Style["PAC-MAN",FontSize->36,Bold,Yellow,FontFamily->"Arial"],{6.5,2.5}],White,Text[Style["CLICK OR PRESS ARROW",FontSize->16,Bold],{6.5,1.0}]},"GameOver",{Black,Opacity[0.8],Rectangle[{0,0},{cols,rows}],Opacity[1],Red,Text[Style["GAME OVER",FontSize->32,Bold],{6.5,3.9}],White,Text[Style["Click or Press Arrow to Retry",FontSize->15],{6.5,2.9}]},"Clear",{Black,Opacity[0.8],Rectangle[{0,0},{cols,rows}],Opacity[1],Green,Text[Style["STAGE CLEAR!!",FontSize->32,Bold],{6.5,3.9}],White,Text[Style["Click or Press Arrow to Play Again",FontSize->15],{6.5,2.9}]},_,Nothing]},PlotRange->{{0,cols},{-0.2,rows+0.8}},ImageSize->450,Background->Black];
ClickPane[Dynamic[Refresh[tick[];
drawGraphics[],UpdateInterval->0.12],TrackedSymbols:>{}],Function[{pos},handleClick[]]]],"Output",Editable->False,Selectable->False]},WindowTitle->"Pac-Man Mini",Saveable->False,Editable->False,Selectable->False,WindowElements->{"StatusArea"},Background->Black,TaggingRules->{"PacManDirection"->{0,0},"PacManKeySerial"->0},NotebookEventActions->{"LeftArrowKeyDown":>(CurrentValue[EvaluationNotebook[],{TaggingRules,"PacManDirection"}]={-1,0};
CurrentValue[EvaluationNotebook[],{TaggingRules,"PacManKeySerial"}]=CurrentValue[EvaluationNotebook[],{TaggingRules,"PacManKeySerial"}]+1;
Null),"RightArrowKeyDown":>(CurrentValue[EvaluationNotebook[],{TaggingRules,"PacManDirection"}]={1,0};
CurrentValue[EvaluationNotebook[],{TaggingRules,"PacManKeySerial"}]=CurrentValue[EvaluationNotebook[],{TaggingRules,"PacManKeySerial"}]+1;
Null),"UpArrowKeyDown":>(CurrentValue[EvaluationNotebook[],{TaggingRules,"PacManDirection"}]={0,-1};
CurrentValue[EvaluationNotebook[],{TaggingRules,"PacManKeySerial"}]=CurrentValue[EvaluationNotebook[],{TaggingRules,"PacManKeySerial"}]+1;
Null),"DownArrowKeyDown":>(CurrentValue[EvaluationNotebook[],{TaggingRules,"PacManDirection"}]={0,1};
CurrentValue[EvaluationNotebook[],{TaggingRules,"PacManKeySerial"}]=CurrentValue[EvaluationNotebook[],{TaggingRules,"PacManKeySerial"}]+1;
Null)}]]