home *** CD-ROM | disk | FTP | other *** search
/ com!online 2002 April / comcd0402.iso / homepage / javaspecial / 07_01 / Siji.java < prev    next >
Encoding:
Java Source  |  2000-08-10  |  14.7 KB  |  503 lines

  1. /*********************************************************
  2.    Applet  : Siji.java - My 4th Java Applet Game
  3.    Version : 1.30
  4.    Author  : Riza Purwo Nugroho <rizapn@ratelindo.co.id>
  5.    Date    : August 9, 2000
  6.    Update  : August 9, 2000
  7. **********************************************************/
  8.  
  9. import java.applet.*;
  10. import java.awt.*;
  11. import java.awt.image.*;
  12. import java.net.*;
  13. import java.util.*;
  14.  
  15. public class Siji extends Applet implements Runnable
  16. {
  17.   static int MAX_X=12, MAX_Y=10, MAX_LVL=100, MAX_IMG=5;
  18.   static int xRect = 24, yRect = 24;
  19.   static int X_0 = 5, Y_0 = 5, BALL_CODE = 4;
  20.   static int maxHist = 200;
  21.  
  22.   Thread game0 = null;
  23.  
  24.   private Image[] xImg = new Image[MAX_IMG+1];
  25.   private int gLevel, mvPos, maxMove, dlyBall, num, xPos, yPos;
  26.   private byte[][] currCanvas = new byte[MAX_Y+1][MAX_X+1];
  27.   private byte firstTime;
  28.   private int[] hst = new int[maxHist+1];
  29.  
  30.   private Button btn1  = new Button("X");
  31.   private Button btnN2 = new Button(">>");
  32.   private Button btnN  = new Button(">");
  33.   private Button btnP  = new Button("<");
  34.   private Button btnP2 = new Button("<<");
  35.   private Button btnU  = new Button("U");
  36.  
  37.   private static String stGameEnd = " [GAME END]";
  38.   private static String stYouLose = " [YOU LOSE]";
  39.  
  40.   private static String mCode = " =#.xo,123456789ABCDEFGHIJKLMN";
  41.   private static int xCoord[][] =
  42.     {{      0,     0,xRect,yRect},
  43.      {  xRect,     0,xRect,yRect},
  44.      {2*xRect,     0,xRect,yRect},
  45.      {      0, yRect,xRect,yRect},
  46.      {  xRect, yRect,xRect,yRect},
  47.      {2*xRect, yRect,xRect,yRect},
  48.     };
  49.  
  50.   private static String biDat[] = {
  51.     ", 3#4, 2#1.x.#, 2#.x.1#, 2#x#x.#, 2#x.x.#, 2#.1#2, 2#.#1, 2#2,,",
  52.     ",, 2#3, 2#.1#2, 2#.x1.#, 2#x3#1, 1#1.1x.1#, 1#.2#3, 1#1.#1, 2#2,,",
  53.     ", 1#2, 1#.#5, 1#.#.x#.#, 1#.x.x.1#, 1#.x3.#, 1#1.1x1.#, 2#4.#, 6#2,,",
  54.     ", 2#5, 2#x1.1#1, 1#1x1.2#, 1#.x1.2#, 1#1x2.#1, 2#1.x.1#, 3#.1#2, 3#3,,",
  55.     ",, 4#4, 3#1.2#, 2#1.3#, 1#1x1.2#, 1#x3.#1, 1#1.x#2, 2#3,",
  56.     ",, 1#4, 1#.2#1, 1#.x1.#, 1#1.2#2, 2#1.x.1#, 3#1x2#, 4#4,",
  57.     ", 3#3, 3#.1#1, 2#1x1.#1, 2#.x.x1#, 2#.1x.1#, 2#1x1#2, 1#1.x.#, 1#.2#1, 1#4,",
  58.     ",, 3#4, 2#1.x.#, 2#.2x#, 2#1.x1#1, 2#x1.1x#, 2#.3#1, 2#5,",
  59.     ", 1#8, 1#x.x1.x.#, 1#1x#2x1#, 1#1.# #x1#, 1#.x#3.#, 1#.#2.2#, 1#.#2.#.#, 1#3.1#2, 4#3,,",
  60.     ", 2#5, 2#.1x.#, 2#.x1#1, 2#.x1#1, 2#x.x.#1, 2#.1x1.#, 2#.#.1#1, 2#.#3, 2#2,,",
  61.     ",,, 1#4, 1#.2#2, 1#.1x1.#, 1#.1x1#3, 1#.2x.x1#, 1#8,,",
  62.     ", 2#3, 1#1.1#3, 1#.2x1.#, 1#1.x.x#1, 2#1x1#1, 3#.x#1, 3#.2#, 3#4,,",
  63.     ", 5#2, 4#1x#1, 3#1x1.#, 3#.x2#1, 3#.2x1#, 3#.#.2#, 3#.3#1, 3#5,,",
  64.     ", 7#3, 2#5x.#, 2#.x.#1x.#,#3x3.x.#,#.2#.#5,#.1x1.#,#.1#3,#3,,",
  65.     ", 2#6, 1#1.1#x.#, 1#x1.3#, 1#.1#x1.#, 1#3x1#1, 4#1.1#, 5#3,,",
  66.     ", 6#2, 3#3.#, 2#1.x.1#, 2#.1x.1#, 2#.x2#1, 2#x.x1#, 2#2.1#, 4#1.#, 5#2,,",
  67.     ",, 6#2, 1#5.#, #1.1x1.1#, #.2x1.1#1, #2.x1.x1#, 2#1x1.1#1, 3#1.#2, 4#2,,",
  68.     ", 4#2, 2#2.#3, 1#1x.4#, #1.x#5, #.x.#1, #x2.#, #2.#1, 2#2,,",
  69.     ",, 6#2, 2#4.#, 2#.1x1.#, 2#x.x1.#, 2#x.x1.#, 2#.4#, 2#6,,",
  70.     ",, 2#4, 1#1.2#3, 1#x1.1#1.#, 1#.x2#1.#, 1#1x.x1.1#, 2#1x.1#.#, 3#6,,,",
  71.     ",, 1#6, 1#.1x.1#, 1#.x2.#, 1#2.x.#1, 3#x#.1#, 3#.#3, 3#2,,",
  72.     ",, 1#3, #1.x#2, #.x1.x#2, #2.x1.1#, 2#x#1.#2, 2#1.4#, 3#6,,",
  73.     ",, 2#7, 1#1.1#.x.#, 1#.3x1.#, 1#.x1.x.x#, 1#1.#.x1#1, 2#6,,",
  74.     ",, 2#4, 2#.2#1, 2#.1x1#2, 2#.1x1.1#, 2#x1.1#2, 2#5,,",
  75.     ",, 2#7, 2#.x#.2#, 2#x1.1x1#, 2#.x.2#1, 2#.x#3, 2#.#1, 2#2,,",
  76.     ",, 1#4, 1#x2#1, 1#x1.x#, 1#2.1#2, 1#1.x2.#2, 1#.2x.3#, 1#.1#2.#2, 1#3 #2,,",
  77.     ",,, 2#6, 2#.#x.1#1, 2#.1x#.1#, 2#.x1.x.#, 2#4x.#, 6#3,,",
  78.     ",, 2#7, 2#.1x1.1#, 2#1x1.#.#, 3#2.x1#, 5#.1#1, 5#.1#, 5#3,,",
  79.     ", 5#2, 1#4.#, 1#.4#, 1#.1x.1#1, 1#2.x2#, 3#1x2#, 4#1.#1, 5#2,,",
  80.     ",, 2#3, 2#.x# #2, 2#.x#2.#, 2#x.#.2#, 1#1x3.#1, 1#x.1#1.1#, 1#6.#, 7#2,,",
  81.     ", 3#4, 3#.2#, 1#2.x.#2, 1#.2x.2#, 1#.x4.#, 1#.2x.2#, 1#2.x.#2, 3#.2#, 3#4,,",
  82.     ", 3#4, 3#x2#, 1#2x2#2, 1#.1x2.1#, 1#.1x.x.1#, 1#.6#, 1#2.2#2, 3#.2#, 3#4,,",
  83.     ", 3#4, 3#.2#, 1#2.x.#2, 1#.1x2.1#, 1#.x4.#, 1#x6#, 1#2.2#2, 3#.2#, 3#4,,",
  84.     ", 3#4, 3#.x.#, 1#2x2#2, 1#.x4.#, 1#.2x.2#, 1#.2x.2#, 1#2x2#2, 3#x2#, 3#4,,",
  85.     ", 3#4, 3#.x.#, 1#2x2#2, 1#.x4.#, 1#.1x2.1#, 1#.x4.#, 1#2x2#2, 3#.x.#, 3#4,,",
  86.     ", 3#4, 3#.x.#, 1#2x2#2, 1#.x4.#, 1#x2.x2#, 1#.x4.#, 1#2x2#2, 3#.x.#, 3#4,,",
  87.     ", 3#4, 3#x2#, 1#2x2#2, 1#x6#, 1#x2.x2#, 1#x6#, 1#2x2#2, 3#x2#, 3#4,,",
  88.     " 3#4, 3#x2#, 3#x2#, #3x2#3, #x8#, #x3.x3#, #x8#, #3x2#3, 3#x2#, 3#x2#, 3#4,,",
  89.     " 2#9, 2#.1#.x1.1#, 2#.x#x2.1#,#3.x.x.1x.#,#.#1x2.x2.#,#.4x2.1x#,#.1#.#x5#,#.1#.1#x.x1.#,#4.x2.x1#, 3#2.3#1, 5#5,,",
  90.     " 1#8, 1#.#.2#.#1, 1#.x.#.#.1#, 1#1x.5#, 1#.3x1.1#, 1#.1x2.x1#, 1#.x2.3#, #2x2#.x1#,#1x3.x3#,#x1.x1.x.#2,#9,,",
  91.     "#3 #6,#.x#2.4#,#.x.x1.4#,#x2#x1.3#,#.x4.3#,#1.x3.#.1#,#x5.#3,#.x1#.2#,#.#6,#2,,",
  92.     " 2#2, #2x#2,#1x.x2#2,#.x5.#,#.x1.x1.1#3,#x1.x1.2#1.#,#.x.1x2.3#,#.x5.3#,#.x3.5#,#.1x1.6#,#C,,",
  93.     " 5#2, 5#.#,#6.#3,#.1#1.x1.2#1,#.4x.x3#,#.4x3.x#,#.2x4.x1#,#.3x6#,#.5x2.x#,#C,,",
  94.     "#8,#.#1.x1.#2,#.1#x4.#,#x1.x4.#,#.#1.x4#1,#.x1.x2.2#,#.2x.x#.1#1,#1.2x.#3, #.2x.#, #.#.2#, #6,,",
  95.     ", #B,#1.x#.1x1.2#,#.2x2.x.x1#,#2x2.1x1.1#, 1#x3.#.2#, 1#x3#.2#1, 1#x.x.x1.2#, 1#1.1#1.1#2, 2#7,,",
  96.     " 5#2, 5#.#3,#6x.2#,#.6x1#1,#.x.x4.1#,#1x4.2#1,#x4.#.2#,#x1.x1.x1.#1,#.x2#.4#,#1.x1.2#3, #7,,",
  97.   };
  98.  
  99.   private static int aMove[] = {
  100.      0,0,0,0,0,0,0,0,0,0,
  101.      0,0,0,0,0,0,0,0,0,0,
  102.      0,0,0,0,0,0,0,0,0,0,
  103.      0,0,0,0,0,0,0,0,0,0,
  104.      0,0,0,0,0,0,0,0,0,0,
  105.      0,0,0,0,0,0,0,0,0,0,
  106.      0,0,0,0,0,0,0,0,0,0,
  107.      0,0,0,0,0,0,0,0,0,0,
  108.     };
  109.  
  110.   private Image mainImg;
  111.   private Graphics g;
  112.   private TextField txt1;
  113.  
  114.   public void init()
  115.   {
  116.     String param;
  117.     int i;
  118.  
  119.     if (g==null) g = getGraphics();
  120.  
  121.     URL url = getCodeBase();
  122.  
  123.     String str = "";
  124.     int b = 0;
  125.  
  126.     MediaTracker tracker = new MediaTracker(this);
  127.     mainImg = getImage(url, "Images.gif");
  128.     tracker.addImage(mainImg,0);
  129.  
  130.     for (i=0; i<=MAX_IMG; i++)
  131.       {
  132.         xImg[i] = extractImage(xCoord[i]);
  133.         tracker.addImage(xImg[i], i+1);
  134.       }
  135.  
  136.     try { tracker.waitForAll(); }
  137.     catch (InterruptedException e) {}
  138.  
  139.     setLayout(new BorderLayout());
  140.  
  141.     txt1 = new TextField(17);
  142.     txt1.setForeground(new Color(255,255,204));
  143.     txt1.setBackground(new Color(102,51,51));
  144.     txt1.setEditable(false);
  145.  
  146.     Panel p = new Panel();
  147.  
  148.     p.add(txt1);
  149.     p.add(btnP2);
  150.     p.add(btnP);
  151.     p.add(btnN);
  152.     p.add(btnN2);
  153.     p.add(btnU);
  154.     p.add(btn1);
  155.  
  156.     add("South", p);
  157.  
  158.     gLevel = 0;
  159.     dat2Canvas(0);
  160.     firstTime = 1;
  161.     dlyBall = 30;
  162.   }
  163.  
  164.   public void start()
  165.   {
  166.     if (game0==null) 
  167.      {
  168.        game0 = new Thread(this);
  169.        game0.start();
  170.      }
  171.   }
  172.  
  173.   public void stop()
  174.   {
  175.     if (game0 != null)
  176.      {
  177.        game0.stop();
  178.        game0 = null;
  179.      }
  180.   }
  181.  
  182.   public void run()
  183.   {
  184.   }
  185.  
  186.   public boolean dat2Canvas(int dlvl)
  187.   {
  188.     int i,x,y,tmp0;
  189.     byte z = 0, oz = 0;
  190.     String param;
  191.  
  192.     try
  193.      {
  194.        gLevel += dlvl;
  195.        if (gLevel<0) gLevel = 0;
  196.  
  197.        try { i = Integer.parseInt(getParameter("maxmove"+gLevel)); }
  198.        catch (NumberFormatException e) { i = 0; }
  199.  
  200.        param = getParameter("data"+gLevel);
  201.        if (i>0) maxMove = i;
  202.  
  203.        if (param==null || i<=0)
  204.         { 
  205.           param = biDat[gLevel];
  206.           maxMove = aMove[gLevel];
  207.         }
  208.      }
  209.     catch (ArrayIndexOutOfBoundsException exc)
  210.      { 
  211.        gLevel -= dlvl; 
  212.        param = biDat[gLevel];
  213.        maxMove = aMove[gLevel];
  214.      }
  215.  
  216.     for (y=0; y<=MAX_Y; y++)
  217.       { for (x=0; x<=MAX_X; x++)
  218.           { currCanvas[y][x] = 0; }
  219.       }
  220.  
  221.     x = y = 0;
  222.     for (i=0; i<param.length(); i++)
  223.       {
  224.         z = (byte)(mCode.indexOf(param.charAt(i)));
  225.         if (z>MAX_IMG)
  226.          {
  227.            if ((tmp0 = (z-MAX_IMG-1))>0)
  228.             {
  229.               for (int j=0; j<tmp0; j++)
  230.                 {
  231.                   try { currCanvas[y][x++] = oz; }
  232.                   catch (ArrayIndexOutOfBoundsException exc) { j = tmp0; }
  233.                 }
  234.             }
  235.            else
  236.             {
  237.               x = 0; y++;
  238.               if (y>MAX_Y) break;
  239.             }
  240.          }
  241.         else if (x<=MAX_X)
  242.          {
  243.            if (z<0) z = 0;
  244.            currCanvas[y][x++] = z;
  245.            oz = z;
  246.          }
  247.       }
  248.     xPos = yPos = -1;
  249.     mvPos = 0;
  250.  
  251.     for (x=0; x<=maxHist; x++) hst[x] = 0;
  252.  
  253.     if (maxMove>0) { txt1.setText(" Level "+gLevel+" ("+maxMove+" step max.)"); }
  254.        else { txt1.setText(" Level "+gLevel); }
  255.     if (firstTime==1) firstTime = 0;
  256.  
  257.     return true;
  258.   }
  259.  
  260.   public int checkStep(int x, int y)
  261.   {
  262.     int  h = 0;
  263.     byte z0 = (byte)(BALL_CODE-1);
  264.     byte z1 = (byte)BALL_CODE;
  265.  
  266.     if (currCanvas[y][x]==z1)
  267.      {
  268.        if ((currCanvas[y-1][x]==z1 && currCanvas[y-2][x]==z0) ||
  269.            (currCanvas[y+1][x]==z1 && currCanvas[y+2][x]==z0) ||
  270.            (currCanvas[y][x-1]==z1 && currCanvas[y][x-2]==z0) ||
  271.            (currCanvas[y][x+1]==z1 && currCanvas[y][x+2]==z0)) h = 1;
  272.      }
  273.     else h = -1;
  274.  
  275.     return h;
  276.   }
  277.  
  278.   public int gameEnd()
  279.   {
  280.     byte z0 = (byte)(BALL_CODE-1);
  281.     byte z1 = (byte)(BALL_CODE);
  282.     byte z2 = (byte)(BALL_CODE+1);
  283.     int h = 0, ch = 0;
  284.     int x,y,i;
  285.  
  286.     y = 2;
  287.     while (y<MAX_Y-1 && h==0)
  288.     {
  289.       x = 2;
  290.       while (x<MAX_X-1 && h==0)
  291.       {
  292.         i = checkStep(x,y);
  293.         if (i>=0) { ch++; if (i>0) h = 1; }
  294.         x++;
  295.       }
  296.       y++;
  297.     }
  298.  
  299.     if (ch>1 && h==0) h = -1;
  300.     
  301.     return h;
  302.   }
  303.  
  304.   public boolean mouseDown(Event e, int x, int y)
  305.   {
  306.     int  dx,dy;
  307.     byte z0;
  308.     int  h = 0;
  309.     byte old = 0;
  310.     int  x2,y2,x1,y1;
  311.  
  312.     x2 = (x-X_0)/xRect;
  313.     y2 = (y-Y_0)/yRect;
  314.     if (x2<0 || x2>MAX_X || y2<0 || y2>MAX_Y) return true;
  315.  
  316.     if (xPos>=0 && yPos>=0 && xPos<=MAX_X && yPos<=MAX_Y) old = currCanvas[yPos][xPos];
  317.  
  318.     z0 = currCanvas[y2][x2];
  319.     h = checkStep(x2,y2);
  320.     if (z0==BALL_CODE+1) { z0 -= 1; h = 1; }
  321.     else if (h>0) { z0 += 1; h = 1; }
  322.     else
  323.      {
  324.        dx = (x2-xPos)/2; x1 = x2-dx;
  325.        dy = (y2-yPos)/2; y1 = y2-dy;
  326.        if (old==BALL_CODE+1 &&
  327.            (((dx==1 || dx==-1) && dy==0) || ((dy==1 || dy==-1) && dx==0)) &&
  328.            currCanvas[y1][x1]==BALL_CODE
  329.           )
  330.         {
  331.           changeCanvas(xPos,yPos,BALL_CODE-1);
  332.           changeCanvas(x1,y1,BALL_CODE-1);
  333.           z0 = (byte)BALL_CODE;
  334.  
  335.           hst[mvPos % maxHist] = 16*y2 + x2 + 256*((1+dx)+4*(1+dy));
  336.  
  337.           old = 0; mvPos++;
  338.           h = 2;
  339.         }
  340.      }
  341.  
  342.     if (h>0)
  343.      {
  344.        if (old>=BALL_CODE)
  345.         {
  346.           changeCanvas(xPos,yPos,BALL_CODE);
  347.         }
  348.        xPos = x2;
  349.        yPos = y2;
  350.        changeCanvas(x2,y2,z0);
  351.        if (h==2)
  352.         {
  353.           h = gameEnd();
  354.           if (h==0) { txt1.setText(stGameEnd); h = -99; }
  355.           else if (h==-1) { txt1.setText(stYouLose); h = -100; }
  356.           else { txt1.setText("Level "+gLevel+" step "+mvPos); }
  357.         }
  358.      }
  359.  
  360.     if (h<=-99)
  361.      {
  362.        try { game0.sleep(400); }
  363.        catch (InterruptedException exp) {}
  364.        if (dat2Canvas(h+100)) paint(null);
  365.      }
  366.  
  367.     return true;
  368.   }
  369.  
  370.   public void changeCanvas(int x, int y, int z0)
  371.   {
  372.     currCanvas[y][x] = (byte)z0;
  373.     g.drawImage(xImg[z0],X_0+xRect*x,Y_0+yRect*y,this);
  374.   }
  375.  
  376.   public boolean action(Event e, Object arg)
  377.   {
  378.     int h = 0;
  379.  
  380.     if      (e.target==btnP)  h = 106;
  381.     else if (e.target==btnN)  h = 107;
  382.     else if (e.target==btn1)  h = 27;
  383.     else if (e.target==btnP2) h = 104;
  384.     else if (e.target==btnN2) h = 108;
  385.  
  386.     if (h>0) keyDown(e, h);
  387.  
  388.     return true;
  389.   }
  390.  
  391.   public boolean keyDown(Event e, int c)
  392.   {
  393.     int h = 0;
  394.  
  395.     switch (c)
  396.     {
  397.       case  8:  if (mvPos>0) doUndo(); break;
  398.       case 27:  if (mvPos==0 && firstTime==0) { firstTime = 1; paint(null); return true; }
  399.                 h = 100; break;
  400.       case 104: h =  89; break;
  401.       case 106: h =  99; break;
  402.       case 107: h = 101; break;
  403.       case 108: h = 111; break;
  404.       default: txt1.setText("Key "+c+" is not defined"); return true;
  405.     }
  406.  
  407.     if (h>0) { if (dat2Canvas(h-100)) paint(null); }
  408.  
  409.     return true;
  410.   }
  411.  
  412.   private void doUndo()
  413.   {
  414.     int ch,h,x,y,dx,dy;
  415.  
  416.     mvPos--;
  417.     h = hst[mvPos % maxHist];
  418.     hst[mvPos] = 0;
  419.  
  420.     ch = h/256;
  421.     dx = (ch % 4) - 1;
  422.     dy = ((ch / 4) % 4) - 1;
  423.  
  424.     x  = h % 16;
  425.     y  = (h / 16) % 16;
  426.  
  427.     txt1.setText("Back to step "+mvPos);
  428.  
  429.     ch = BALL_CODE-1;
  430.     for (h=0; h<3; h++)
  431.       {
  432.         changeCanvas(x,y,ch);
  433.         ch = BALL_CODE;
  434.         x -= dx; y -= dy;
  435.       }
  436.  
  437.   }
  438.  
  439.   private Image extractImage(int[] xyCoord)
  440.   {
  441.     Image newImage;
  442.     ImageFilter filter;
  443.     ImageProducer producer;
  444.  
  445.     filter = new CropImageFilter(xyCoord[0],xyCoord[1],xyCoord[2],xyCoord[3]);
  446.     producer = new FilteredImageSource(mainImg.getSource(), filter);
  447.     newImage = createImage(producer);
  448.     return newImage;
  449.    }
  450.  
  451.   public void paint(Graphics g)
  452.   {
  453.     byte z;
  454.     int  x2,y2,xe,x,y;
  455.  
  456.     if (g==null) g = getGraphics();
  457.     y2 = Y_0;
  458.     xe = X_0+xRect*(MAX_X+1);
  459.     for (y=0; y<=MAX_Y; y++)
  460.       {
  461.         //g.drawImage(xImg[1],X_0-20,y2,this);
  462.         //g.drawImage(xImg[1],xe,y2,this);
  463.         x2 = X_0;
  464.         for (x=0; x<=MAX_X; x++)
  465.           {
  466.             z = currCanvas[y][x];
  467.             if (firstTime==1 || z>MAX_IMG) z = 0;
  468.             g.drawImage(xImg[z],x2,y2,this);
  469.             x2 += xRect;
  470.           }
  471.         y2 += yRect;
  472.       }
  473.     if (firstTime==1) doFirstTime();
  474.   }
  475.  
  476.   public void doFirstTime()
  477.   {
  478.     int y,x;
  479.     int c;
  480.  
  481.     y = 20;
  482.     x = X_0 + 15;
  483.     g.setColor(new Color(255,255,204));
  484.     String str = "* Siji v0.9 *";
  485.     g.drawString(str,x,y);
  486.     txt1.setText(str);
  487.     y += 20; g.drawString("(Java Applet version) 2000 by Riza PN",x,y);
  488.     y += 20; g.drawString("Siji is a word of 'One' in Javanesse language.",x,y);
  489.     y += 20; g.drawString("The goal is to take all object until the last one by jump over",x,y);
  490.     y += 15; g.drawString("another object. Click one object, jump over another object,",x,y);
  491.     y += 15; g.drawString("move it to the blank place, and it will clear the middle object.",x,y);
  492.     y += 15; g.drawString("Repeat it until there is only one object in the screen.",x,y);
  493.     y += 15; g.drawString("Press U button or use Backspace to undo the last move (it",x,y);
  494.     y += 15; g.drawString("can do until 200 last steps). Press X button or Esc key to",x,y);
  495.     y += 15; g.drawString("restart the game. Use h,j,k,l to change the level.",x,y);
  496.     y += 15; g.drawString("Almost all level is based on its similar game from internet.",x,y);
  497.     y += 20; g.drawString("Hope you enjoy it...",x,y);
  498.     y += 20; g.drawString("Salam",x,y);
  499.     y += 15; g.drawString("Riza Purwo Nugroho, Jakarta-Indonesia",x,y);
  500.   }
  501.  
  502. }
  503.