home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 7 Games / 07-Games.zip / mnswp14a.zip / MINE.C < prev    next >
C/C++ Source or Header  |  1999-12-03  |  15KB  |  547 lines

  1. //      ┌──────────────────────────────────────────────────────────────────┐
  2. //      │ OS/2 Mine Sweeper (C) Dmitry Zaharov, 1999. All Rights Reserved. │
  3. //      └──────────────────────────────────────────────────────────────────┘
  4.  
  5. #define INCL_WIN
  6. #define INCL_GPI
  7. #define INCL_DOS
  8.  
  9. #include <os2.h>            /* PM header file        */
  10. #include <string.h>
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <memory.h>
  14. #include <time.h>
  15. #include "mine.h"            /* Resource symbolic identifiers*/
  16.  
  17. // ┌─────────────────────┐
  18. // │ Function Prototypes │
  19. // └─────────────────────┘
  20.  
  21.  
  22. MRESULT EXPENTRY MyWindowProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 );
  23. VOID         LoadBitmaps(void);
  24.  
  25.  
  26. // ┌─────────────┐
  27. // │ Global vars │
  28. // └─────────────┘
  29.  
  30. HAB    hab;
  31. HWND    hwndClient,hwndFrame;
  32. HBITMAP    bitmaps[BM_LAST-BM_0+1];
  33. CHAR    pull[32][20];
  34. CHAR    mark[32][20];
  35. CHAR    fill[32][20];
  36. CHAR    show[32][20];
  37. INT    gameover=0,bombs,XS=16,YS=16,bomborigin,timer=1;
  38. ULONG    timer_count=0;
  39. LONG    lMenuHight;
  40.  
  41. // ┌──────┐
  42. // │ main │
  43. // └──────┘
  44.  
  45. INT main (VOID)
  46. {
  47.   HMQ  hmq;                /* Message queue handle        */
  48.   QMSG qmsg;                /* Message from message queue    */
  49.   ULONG flCreate;            /* Window creation control flags*/
  50.  
  51.   hab = WinInitialize(0);
  52.  
  53.   hmq = WinCreateMsgQueue( hab, 0 );
  54.  
  55.   WinRegisterClass(            /* Register window class    */
  56.      hab,                /* Anchor block handle        */
  57.      (PSZ)"MyWindow",            /* Window class name        */
  58.      (PFNWP)MyWindowProc,        /* Address of window procedure    */
  59.      CS_SIZEREDRAW,            /* Class style            */
  60.      0                    /* No extra window words    */
  61.      );
  62.  
  63.   flCreate =  FCF_TASKLIST  | FCF_SYSMENU   | FCF_ICON     | 
  64.               FCF_MINBUTTON | FCF_MENU      | FCF_TITLEBAR |
  65.               FCF_BORDER ;
  66.  
  67.   hwndFrame = WinCreateStdWindow(     
  68.            HWND_DESKTOP,        /* Desktop window is parent    */
  69.            0,            /* STD. window styles        */
  70.            &flCreate,        /* Frame control flag        */
  71.            "MyWindow",        /* Client window class name    */
  72.            "",            /* No window text        */
  73.            0,            /* No special class style    */
  74.            (HMODULE)0L,        /* Resource is in .EXE file     */
  75.            ID_WINDOW,        /* Frame window identifier    */
  76.            &hwndClient        /* Client window handle        */
  77.            );
  78.  
  79.   LoadBitmaps();
  80.  
  81.   WinSetWindowText(hwndFrame, "Mine Sweeper/2");
  82.  
  83.   lMenuHight = WinQuerySysValue(HWND_DESKTOP,SV_CYMENU) +
  84.                WinQuerySysValue(HWND_DESKTOP,SV_CYTITLEBAR);
  85.  
  86.   WinSetWindowPos( hwndFrame,        /* Shows and activates frame    */
  87.            HWND_TOP,
  88.            100, 60, XS*16+18,
  89.            YS*16+47+lMenuHight,
  90.            SWP_ACTIVATE | SWP_SHOW |
  91.            SWP_SIZE     | SWP_MOVE );
  92.  
  93.   while( WinGetMsg( hab, &qmsg, 0L, 0, 0 ) )
  94.     WinDispatchMsg( hab, &qmsg );
  95.  
  96.   WinDestroyWindow(hwndFrame);         /* Tidy up...             */
  97.   WinDestroyMsgQueue( hmq );         /* Tidy up...             */
  98.   WinTerminate( hab );             /* Terminate the application     */
  99.  
  100.   return( 1 );
  101. } /* End of main */
  102.  
  103. // ┌─────────────┐
  104. // │ Subroutines │
  105. // └─────────────┘
  106.  
  107. // initializing arrays & global vars
  108.  
  109. void  seet(int count)
  110. {
  111.    int x,y;
  112.  
  113.    srand((unsigned)clock());
  114.    memset(&pull[0][0],0,640);
  115.    memset(&mark[0][0],0,640);
  116.    memset(&show[0][0],0,640);
  117.    bombs=count;bomborigin=bombs;
  118.    while(count>0)
  119.       {
  120.          x=rand()%XS;
  121.          y=rand()%YS;
  122.          if(!pull[x][y]){
  123.             pull[x][y]=1;
  124.             count--;
  125.             }
  126.  
  127.     }
  128.    }
  129.  
  130. // mine counter near specificied cell
  131.  
  132. int counter(int x,int y)
  133. {
  134.    int c=0,i,j;
  135. for(i=0;i<3;i++)
  136.    for(j=0;j<3;j++)
  137.       {
  138.          if(((x+i-1)>=0) && ((x+i-1)<XS) && ((y+j-1)>=0) && ((y+j-1)<YS) &&
  139.             (pull[x+i-1][y+j-1]==1))c++;
  140.          }
  141. return c;
  142. }
  143.  
  144. // total mines conter
  145.  
  146. int calcbombs()
  147. {
  148. int i,j,a=0;
  149. for(i=0;i<XS;i++) for(j=0;j<YS;j++) if(mark[i][j])a++;
  150. return (bomborigin-a);
  151. }
  152.  
  153. // string writer
  154.  
  155. void  WriteString(HPS hps,int x,int y,char *s,int fg,int bg)
  156. {
  157. POINTL pt;
  158. FATTRS fat;
  159.       pt.x = x; pt.y = y;        /* Set the text coordinates,    */
  160.       GpiSetColor( hps, fg );           /* colour of the text,    */
  161.       GpiSetBackColor( hps, bg );  /* its background and    */
  162.       GpiSetBackMix( hps, BM_OVERPAINT );      /* how it mixes,        */
  163.                            /* and draw the string...*/
  164.       fat.usRecordLength = sizeof(FATTRS);
  165.       fat.fsSelection = 0;//FATTR_SEL_ITALIC;
  166.       fat.lMatch = 0L;
  167.       fat.idRegistry = 0;
  168.       fat.usCodePage = 866;
  169.       fat.lMaxBaselineExt = 18L;
  170.       fat.lAveCharWidth = 8L;
  171.       fat.fsType = 0;
  172.       fat.fsFontUse = 0;
  173.       strcpy(fat.szFacename,"System VIO");
  174.       GpiCreateLogFont(hps,NULL,1L,&fat);
  175.       GpiSetCharSet(hps,1L);
  176.       GpiCharStringAt( hps, &pt, (LONG)strlen( s ), s );
  177.       GpiDeleteSetId( hps, 1L);
  178. }
  179.  
  180. // clock
  181.  
  182. void showtimer(HPS hps)
  183. {
  184.    char buf[20];
  185.    sprintf(buf,"%ld:%02ld    ",timer_count/60,timer_count%60);
  186.    WriteString(hps,10,YS*16+22, buf,CLR_YELLOW,CLR_BLACK);
  187. }
  188.  
  189. // main paint procedure
  190.  
  191. void content(HWND hwnd,int p)
  192. {
  193. CHAR buf[10];
  194. HPS hps;
  195. INT i,j;
  196. POINTL pt;
  197. RECTL rc;
  198.  
  199. /* draw border */
  200. if(!p)hps=WinGetPS(hwnd);
  201.  else hps=WinBeginPaint( hwnd, 0L, &rc );
  202.  
  203. for(i=0;i<YS*2+4;i++)
  204.    {
  205.       pt.x=0;pt.y=8+i*8;
  206.    WinDrawBitmap(hps, bitmaps[BM_B2-BM_0], NULL, &pt, 0, 0, DBM_NORMAL);
  207.       pt.x=XS*16+8;
  208.    WinDrawBitmap(hps, bitmaps[BM_B2-BM_0], NULL, &pt, 0, 0, DBM_NORMAL);
  209.       }
  210. for(i=0;i<XS*2;i++)
  211.    {
  212.       pt.x=i*8+8;pt.y=0;
  213.    WinDrawBitmap(hps, bitmaps[BM_B6-BM_0], NULL, &pt, 0, 0, DBM_NORMAL);
  214.       pt.y=YS*16+8;
  215.    WinDrawBitmap(hps, bitmaps[BM_B6-BM_0], NULL, &pt, 0, 0, DBM_NORMAL);
  216.       pt.y=(YS+2)*16+8;
  217.    WinDrawBitmap(hps, bitmaps[BM_B6-BM_0], NULL, &pt, 0, 0, DBM_NORMAL);
  218.       }
  219. pt.x=0;pt.y=0;
  220. WinDrawBitmap(hps, bitmaps[BM_B5-BM_0], NULL, &pt, 0, 0, DBM_NORMAL);
  221. pt.x=XS*16+8;
  222. WinDrawBitmap(hps, bitmaps[BM_B4-BM_0], NULL, &pt, 0, 0, DBM_NORMAL);
  223. pt.y=(YS+2)*16+8;
  224. WinDrawBitmap(hps, bitmaps[BM_B3-BM_0], NULL, &pt, 0, 0, DBM_NORMAL);
  225. pt.x=0;
  226. WinDrawBitmap(hps, bitmaps[BM_B1-BM_0], NULL, &pt, 0, 0, DBM_NORMAL);
  227. pt.y=YS*16+8;
  228. WinDrawBitmap(hps, bitmaps[BM_B7-BM_0], NULL, &pt, 0, 0, DBM_NORMAL);
  229. pt.x=XS*16+8;
  230. WinDrawBitmap(hps, bitmaps[BM_B8-BM_0], NULL, &pt, 0, 0, DBM_NORMAL);
  231. pt.x=8;
  232. pt.y=YS*16+16;
  233. GpiSetCurrentPosition(hps,&pt);
  234. pt.x=7+XS*16;
  235. pt.y=YS*16+39;
  236. GpiSetColor(hps,CLR_BLACK);
  237. GpiSetBackColor(hps,CLR_BLACK);
  238. GpiBox(hps,DRO_FILL,&pt,0L,0L);
  239. if(!timer)
  240.    {
  241. if(XS==8)WriteString(hps,10,YS*16+22, "EASY  ",CLR_GREEN,CLR_BLACK);
  242. if(XS==16)WriteString(hps,10,YS*16+22,"NORMAL",CLR_GREEN,CLR_BLACK);
  243. if(XS==32)WriteString(hps,10,YS*16+22,"PROFY ",CLR_GREEN,CLR_BLACK);
  244.    }else showtimer(hps);
  245. sprintf(buf,"%03d",bombs);
  246. WriteString(hps,XS*16-24,YS*16+22,buf,CLR_RED,CLR_BLACK);
  247. for(i=0;i<XS;i++)
  248. for(j=0;j<YS;j++)
  249.    {
  250.       pt.x=8+i*16;pt.y=8+j*16;
  251. if(!show[i][j])
  252.    {
  253.       if(!mark[i][j])
  254. WinDrawBitmap(hps, bitmaps[BM_EMPTY-BM_0], NULL, &pt, 0, 0, DBM_NORMAL);
  255. else WinDrawBitmap(hps, bitmaps[BM_CHECK-BM_0], NULL, &pt, 0, 0, DBM_NORMAL);
  256.    }
  257.          else        WinDrawBitmap(hps, bitmaps[counter(i,j)], NULL, &pt, 0, 0, DBM_NORMAL);
  258. }
  259. if(!p)WinReleasePS(hps);
  260.  else WinEndPaint(hps);
  261.  
  262. }
  263.  
  264. // all safe checking
  265.  
  266. int checkdone()
  267. {
  268.    if(!memcmp(&pull[0][0],&mark[0][0],XS*YS))return 0;
  269.       else return 1;
  270. }
  271.  
  272. // gameover!
  273.  
  274. void failed(int x,int y,HWND hwnd)
  275. {
  276. HPS hps;
  277. int i,j;
  278. POINTL pt;
  279. hps=WinGetPS(hwnd);
  280. for(i=0;i<XS;i++)
  281. for(j=0;j<YS;j++)
  282.    {
  283. pt.x=8+i*16;
  284. pt.y=8+j*16;
  285. if((i==x) && (j==y))WinDrawBitmap(hps, bitmaps[BM_FAIL-BM_0], NULL, &pt, 0, 0, DBM_NORMAL);
  286.    else {
  287.       if((pull[i][j]==0)&& (mark[i][j]==1))
  288.      WinDrawBitmap(hps, bitmaps[BM_ILL-BM_0], NULL, &pt, 0, 0, DBM_NORMAL);
  289.       if(pull[i][j]==1)
  290.          WinDrawBitmap(hps, bitmaps[BM_BOMB-BM_0], NULL, &pt, 0, 0, DBM_NORMAL);
  291.       }
  292. }
  293. WinReleasePS(hps);
  294. }
  295.  
  296. // filler
  297.  
  298. void fills(int x,int y,HWND hwnd)
  299. {                                   
  300.    int i,j,o=0,a,b,c;
  301.    POINTL pt;
  302.    HPS hps;
  303.    memset(&fill[0][0],0,640);
  304.    fill[x][y]=1;
  305. if(counter(x,y)>0){
  306.    pt.x=8+x*16;pt.y=8+y*16;
  307.    show[x][y]=1;
  308.    hps=WinGetPS(hwnd);
  309.    WinDrawBitmap( hps, bitmaps[counter(x,y)], NULL, &pt, 0, 0, DBM_NORMAL );
  310.    WinReleasePS(hps);
  311.    return;
  312.    }
  313.    o=1;
  314.    hps=WinGetPS(hwnd);
  315.    pt.x=8+x*16;pt.y=8+y*16;  
  316.    WinDrawBitmap( hps, bitmaps[counter(x,y)], NULL, &pt, 0, 0, DBM_NORMAL );
  317.    mark[x][y]=0;
  318.    show[x][y]=1;
  319.    while(o>0)
  320.    {
  321.          o=0;
  322.       for(i=0;i<XS;i++)
  323.       for(j=0;j<YS;j++)
  324.       {
  325.           if(fill[i][j]==1)
  326.           {
  327.           for(a=0;a<3;a++)
  328.           for(b=0;b<3;b++)
  329.           {
  330.              if(((i+a-1)>=0)&&((i+a-1)<XS)&&((j+b-1)>=0)&&((j+b-1)<YS)&&
  331.                 !fill[i+a-1][j+b-1])
  332.         {
  333.                 c=counter(i+a-1,j+b-1);
  334.                 fill[i+a-1][j+b-1]=c+1;
  335.                 show[i+a-1][j+b-1]=1;
  336.              pt.x=8+(i+a-1)*16;pt.y=8+(j+b-1)*16;
  337.                 WinDrawBitmap( hps, bitmaps[c], NULL, &pt, 0, 0, DBM_NORMAL );
  338.                 mark[i+a-1][j+b-1]=0;
  339.                 if(!c)o++;
  340.         }
  341.           }
  342.           }
  343.       }
  344.    }
  345.    bombs=calcbombs();
  346.    WinReleasePS(hps);
  347. }
  348.  
  349. // load bitmap resources
  350.  
  351. void  LoadBitmaps(void)
  352. {
  353.    HPS stubHps;
  354.    int i;
  355.    stubHps = WinGetPS(hwndClient);
  356.    for( i=BM_0; i<=BM_LAST; i++)
  357.    bitmaps[i-BM_0] = GpiLoadBitmap( stubHps, NULLHANDLE,(ULONG) i , 0, 0 );
  358.    WinReleasePS(stubHps);
  359. }
  360.  
  361. // ┌─────────────┐
  362. // │ Window PROC │
  363. // └─────────────┘
  364.  
  365. MRESULT EXPENTRY MyWindowProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
  366. {
  367.       INT    x,y;
  368.       HPS    hps;            /* Presentation Space handle    */
  369.       POINTL pt;            /* String screen coordinates    */
  370.       CHAR   buf[80];
  371.       HWND   hwndMenu;
  372.   switch( msg )
  373.   {
  374.     case WM_TIMER:
  375.         if(timer&&(!gameover))
  376.         {
  377.     timer_count+=1L;
  378.         if(timer_count>=600L)
  379.         {
  380.            gameover=1;
  381.               WinMessageBox( HWND_DESKTOP,
  382.            hwndFrame,
  383.            "Time-delay bomb blow-up!",
  384.            "GAME OVER",
  385.            0,
  386.            MB_INFORMATION | MB_OK | MB_MOVEABLE | MB_SYSTEMMODAL);
  387.               WinSetWindowText(hwndFrame,"Mine Sweeper/2 - GAME OVER");
  388.               failed(-1,-1,hwndClient);
  389.         }
  390.         hps=WinGetPS(hwnd);
  391.         showtimer(hps);
  392.         WinReleasePS(hps);
  393.         }
  394.         break;
  395.     case WM_CREATE:
  396.         seet(40);
  397.         gameover=0;
  398.     WinStartTimer(hab,hwnd,99,1000L);
  399.         break;   
  400.      case WM_BUTTON1DBLCLK:
  401.         if(!gameover)break;
  402.            WinSetWindowText(hwndFrame, "Mine Sweeper/2");
  403.            gameover=0;timer_count=0L;
  404.            if(XS==8)seet(10);
  405.            if(XS==16)seet(40);
  406.            if(XS==32)seet(100);
  407.            content(hwndClient,0);
  408.         break;
  409.      case WM_BUTTON1DOWN:
  410.         if(gameover)break;
  411.     WinQueryPointerPos(HWND_DESKTOP, &pt);          
  412.     WinMapWindowPoints(HWND_DESKTOP,hwndClient,&pt,1);
  413.         if(pt.x<8 || pt.y<8 || pt.x>XS*16+7 || pt.y>YS*16+7) break;
  414.         x=(pt.x-8)/16;y=(pt.y-8)/16;
  415.         if(show[x][y])break;
  416.         if(mark[x][y])break;
  417.         /*pt.x=pt.x-pt.x%16;*/
  418.         /*pt.y=pt.y-pt.y%16;*/
  419.         if(pull[x][y]){
  420.         failed(x,y,hwndClient); 
  421.         gameover=1;WinSetWindowText(hwndFrame,"Mine Sweeper/2 - GAME OVER");
  422.         }else fills(x,y,hwndClient);
  423.         break;
  424.      case WM_BUTTON2DOWN:
  425.         if(gameover)break;
  426.     WinQueryPointerPos(HWND_DESKTOP, &pt);
  427.     WinMapWindowPoints(HWND_DESKTOP,hwndClient,&pt,1);
  428.         if(pt.x<8 || pt.y<8 || pt.x>XS*16+7 || pt.y>YS*16+7) break;
  429.         x=(pt.x-8)/16;y=(pt.y-8)/16;
  430.         if(show[x][y])break;
  431.         mark[x][y]=!mark[x][y];
  432.         pt.x=x*16+8;
  433.         pt.y=y*16+8;
  434.         hps=WinGetPS(hwndClient);
  435.         if(mark[x][y])
  436.            {
  437.            WinDrawBitmap(hps, bitmaps[BM_CHECK-BM_0], NULL, &pt, 0, 0, DBM_NORMAL );
  438.            bombs--;
  439.            sprintf(buf,"%03d",bombs);
  440.            WriteString(hps,XS*16-24,YS*16+22,buf,CLR_RED,CLR_BLACK);
  441.            WinSetWindowText(hwndFrame,"Mine Sweeper/2");
  442.            if(!bombs)
  443.            {
  444.            gameover=1;
  445.            if(!checkdone()){WinSetWindowText(hwndFrame,"Mine Sweeper/2 - SUCCESSFULL!");
  446.               WinMessageBox( HWND_DESKTOP,
  447.            hwndFrame,
  448.            "You safe all mines!",
  449.            "Information",
  450.            0,
  451.            MB_INFORMATION | MB_OK | MB_MOVEABLE | MB_SYSTEMMODAL);
  452.         }
  453.            else{
  454.               WinSetWindowText(hwndFrame,"Mine Sweeper/2 - GAME OVER");
  455.               failed(x,y,hwndClient);
  456.               }
  457.            }
  458.            }
  459.         else
  460.            {
  461.         WinDrawBitmap(hps, bitmaps[BM_EMPTY-BM_0], NULL, &pt, 0, 0, DBM_NORMAL );
  462.            bombs++;
  463.            sprintf(buf,"%03d",bombs);
  464.            WriteString(hps,XS*16-24,YS*16+22,buf,CLR_RED,CLR_BLACK);
  465.            WinSetWindowText(hwndFrame,"Mine Sweeper/2");
  466.            }
  467.         WinReleasePS(hps);
  468.         break;
  469.  
  470.     case WM_ERASEBACKGROUND:
  471.     return (MRESULT)( TRUE );
  472.  
  473.     case WM_COMMAND:
  474.           switch(SHORT1FROMMP(mp1))
  475.     {
  476.     case M_NEWEASY:
  477.         WinSetWindowText(hwndFrame, "Mine Sweeper/2");
  478.     gameover=0;XS=8;YS=8;
  479.  
  480.         WinSetWindowPos( hwndFrame,    /* Shows and activates frame    */
  481.            HWND_TOP,        /* window at position 100, 100, */
  482.            0, 0, XS*16+18, YS*16+47+lMenuHight,    /* and size 200, 200.        */
  483.            SWP_ACTIVATE | SWP_SHOW | SWP_SIZE);
  484.  
  485.         seet(10);
  486.         content(hwndClient,0);
  487.         timer_count=0L;
  488.         break;
  489.            case M_NEWMEDI:
  490.         WinSetWindowText(hwndFrame, "Mine Sweeper/2");
  491.     gameover=0;XS=16;YS=16;
  492.  
  493.         WinSetWindowPos( hwndFrame,    /* Shows and activates frame    */
  494.            HWND_TOP,        /* window at position 100, 100, */
  495.            0, 0, XS*16+18, YS*16+47+lMenuHight,    /* and size 200, 200.        */
  496.            SWP_ACTIVATE | SWP_SHOW | SWP_SIZE);
  497.  
  498.         seet(40);
  499.         content(hwndClient,0);
  500.         timer_count=0L;
  501.         break;
  502.           case M_NEWHARD:
  503.         WinSetWindowText(hwndFrame, "Mine Sweeper/2");
  504.     gameover=0;XS=32;YS=20;
  505.         WinSetWindowPos( hwndFrame,    /* Shows and activates frame    */
  506.            HWND_TOP,        /* window at position 100, 100, */
  507.            0, 0, XS*16+18, YS*16+47+lMenuHight,    /* and size 200, 200.        */
  508.            SWP_ACTIVATE | SWP_SHOW | SWP_SIZE);
  509.         seet(100);
  510.         content(hwndClient,0);
  511.         timer_count=0L;
  512.         break;
  513.      case M_TIMER:
  514.         timer=!timer;
  515.         hwndMenu=WinWindowFromID(hwndFrame,FID_MENU);
  516.         if(timer)WinCheckMenuItem(hwndMenu,M_TIMER,TRUE);
  517.         else     WinCheckMenuItem(hwndMenu,M_TIMER,FALSE);
  518.         content(hwndClient,0);
  519.         break;
  520.      case M_ABOUT:
  521.         WinDlgBox(HWND_DESKTOP,hwndFrame,NULL,NULLHANDLE,200,NULL);
  522.         break;
  523.      case M_EXIT:
  524.         WinPostMsg( hwnd, WM_QUIT, (MPARAM)0,(MPARAM)0 );/* Cause termination*/
  525.         break;
  526.     default:  
  527.     break;
  528.         }
  529.     break;
  530.     case WM_PAINT:
  531.     content(hwndClient,1);
  532.         if(gameover)failed(x,y,hwndClient);
  533.       break;
  534.     case WM_CLOSE:
  535.     WinPostMsg( hwnd, WM_QUIT, (MPARAM)0,(MPARAM)0 );/* Cause termination*/
  536.     break;
  537.     default: 
  538.     return WinDefWindowProc( hwnd, msg, mp1, mp2 );
  539. }
  540. return (MRESULT)FALSE;
  541. }
  542.  
  543. // ┌─────┐
  544. // │ END │
  545. // └─────┘
  546.  
  547.