View Javadoc

1   package erland.game.tetris;
2   /*
3    * Copyright (C) 2003 Erland Isaksson (erland_i@hotmail.com)
4    *
5    * This program is free software; you can redistribute it and/or
6    * modify it under the terms of the GNU General Public License
7    * as published by the Free Software Foundation; either version 2
8    * of the License, or (at your option) any later version.
9    *
10   * This program is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   * GNU General Public License for more details.
14   *
15   * You should have received a copy of the GNU General Public License
16   * along with this program; if not, write to the Free Software
17   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18   *
19   */
20  
21  import erland.network.NetworkConnectionInterface;
22  import erland.game.GameServerEnvironmentInterface;
23  import erland.game.GamePlayerInterface;
24  
25  import java.awt.*;
26  
27  public class TetrisPlayer implements GamePlayerInterface {
28      private NetworkConnectionInterface connection;
29      /*** Current active block in the main game area */
30      protected Block block;
31      /*** Current active block in the preview block area */
32      protected Block blockNext;
33      /*** Counter that is increased every update, when it reaches the current game
34          speed the active block will be moved down one step */
35      protected int updateCounter;
36      /*** Number of levels */
37      protected final int MAX_LEVEL=9;
38      /*** Maximum block speed */
39      protected final int MAX_SPEED=20;
40      /*** Current score */
41      protected long score;
42      /*** Current level */
43      protected int level;
44      /*** Number of rows that has been removed in this level */
45      protected int rowsThisLevel;
46      /*** Container representing the main game area */
47      protected BlockContainerData mainContainer;
48      /*** Number of rows that has to be removed before level is increased */
49      protected final int ROWS_PER_LEVEL=10;
50      /*** true if game is completed or game over has occurred */
51      protected boolean bEnd=false;
52      /*** Indicates if the player has updated data */
53      private boolean bUpdated;
54      /*** Game environment */
55      protected GameServerEnvironmentInterface environment;
56  
57      public TetrisPlayer(GameServerEnvironmentInterface environment) {
58          this.environment = environment;
59          mainContainer = new BlockContainerData(10,30);
60          init();
61      }
62  
63      public void setConnection(NetworkConnectionInterface connection) {
64          this.connection = connection;
65      }
66  
67      public NetworkConnectionInterface getConnection() {
68          return connection;
69      }
70  
71      public void doCommand(String command) {
72          if(command.equals("RIGHT")) {
73              moveRight();
74          }else if(command.equals("LEFT")) {
75              moveLeft();
76          }else if(command.equals("ROTATE")) {
77              rotateRight();
78          }else if(command.equals("DOWN")) {
79              moveDownBottom();
80          }
81          bUpdated = true;
82      }
83  
84      public void init() {
85          mainContainer.clear();
86      }
87  
88      public void startNewGame() {
89          bEnd = false;
90          level = 1;
91          score = 0;
92          rowsThisLevel=0;
93          updateCounter=0;
94          mainContainer.clear();
95          block=null;
96          blockNext=null;
97      }
98      public boolean isGameOver() {
99          return bEnd;
100     }
101     public boolean isCompleted() {
102         return (bEnd && level>MAX_LEVEL);
103     }
104     public boolean update() {
105         updateCounter++;
106         if(updateCounter>(MAX_SPEED-level*2)) {
107             updateCounter=0;
108             if(!bEnd) {
109                 if(this.block==null) {
110                     if(this.blockNext==null) {
111                         blockNext = BlockFactory.getInstance().nextBlock(this);
112                     }
113                     block = blockNext;
114                     blockNext = BlockFactory.getInstance().nextBlock(this);
115                     blockNext.init(1,0,0);
116                     block.init(mainContainer.getWidth()/2,-1,0);
117                     if(!block.moveDown(mainContainer)) {
118                         removeCompletedRows();
119                         environment.getHighScore().save();
120                         bEnd = true;
121                     }
122                 }else {
123                     if(!block.moveDown(mainContainer)) {
124                         removeCompletedRows();
125                         block = null;
126                     }
127                 }
128                 if(rowsThisLevel>=ROWS_PER_LEVEL) {
129                     rowsThisLevel-=ROWS_PER_LEVEL;
130                     score+=200*level;
131                     environment.getHighScore().update(score);
132                     level++;
133                 }
134                 if(level>MAX_LEVEL) {
135                     bEnd=true;
136                     environment.getHighScore().save();
137                 }
138             }
139             return true;
140         }
141         return false;
142     }
143 
144     /***
145      * Removes all completed rows in the main game area and increases score
146      */
147     protected void removeCompletedRows()
148     {
149         for(int y=mainContainer.getHeight()-1;y>=0;y--) {
150             boolean bCompleted = true;
151             boolean bCompletedWithSameColor=true;
152             Color c=mainContainer.getColor(0,y);
153             for(int x=0;x<mainContainer.getWidth();x++) {
154                 if(!mainContainer.isUsed(x,y)) {
155                     bCompleted = false;
156                 }else {
157                     if(c==null || !c.equals(mainContainer.getColor(x,y))) {
158                         bCompletedWithSameColor=false;
159                     }
160                 }
161             }
162             if(bCompleted) {
163                 for(int i=y;i>0;i--) {
164                     for(int j=0;j<mainContainer.getWidth();j++) {
165                         if(mainContainer.isUsed(j,i-1)) {
166                             mainContainer.setUsed(j,i,mainContainer.getColor(j,i-1));
167                         }else {
168                             mainContainer.setUnused(j,i);
169                         }
170                     }
171                 }
172                 mainContainer.clearRow(0);
173                 y++;
174                 if(!bCompletedWithSameColor) {
175                     score+=(10*level);
176                 }else {
177                     score+=(100*level);
178                 }
179                 environment.getHighScore().update(score);
180                 rowsThisLevel++;
181             }
182         }
183     }
184 
185 
186     public String getBlockString(Block b) {
187         StringBuffer sb = new StringBuffer(2);
188         Color c = null;
189         if(b!=null) {
190             c = b.getColor();
191             if(c==Color.red) {
192                 sb.append('1');
193             }else if(c==Color.green) {
194                 sb.append('2');
195             }else if(c==Color.yellow) {
196                 sb.append('3');
197             }else if(c==Color.cyan) {
198                 sb.append('4');
199             }else if(c==Color.blue) {
200                 sb.append('5');
201             }else if(c==Color.pink) {
202                 sb.append('6');
203             }else if(c==Color.magenta) {
204                 sb.append('7');
205             }else {
206                 sb.append('7');
207             }
208 
209             int r = b.getRotation();
210             r=r/90;
211             sb.append(r);
212 
213             if(b.getX()<10) {
214                 sb.append(('0'));
215             }
216             if(b.getX()<0) {
217                 sb.append('0');
218             }else {
219                 sb.append(b.getX());
220             }
221             if(b.getY()<10) {
222                 sb.append(('0'));
223             }
224             if(b.getY()<0) {
225                 sb.append(('0'));
226             }else {
227                 sb.append(b.getY());
228             }
229         }else {
230             sb.append("000000");
231         }
232         return sb.toString();
233     }
234     public String getNumberString(int length, long number) {
235         StringBuffer sb = new StringBuffer(length);
236         int maxNumber=1;
237         for(int i=1;i<length;i++) {
238             maxNumber*=10;
239             if(number<maxNumber) {
240                 sb.append('0');
241             }
242         }
243         sb.append(number);
244         return sb.toString();
245     }
246     public String toString() {
247         bUpdated = false;
248         return getBlockString(block)+getBlockString(blockNext)+mainContainer.toString()+getNumberString(6,score)+getNumberString(6,environment.getHighScore().get())+getNumberString(2,level);
249         //System.out.println("s = " + s);
250         //connection.write(s);
251     }
252     /***
253      * Move the active block in the main game area one step left
254      * @return true/false (Success/Failure)
255      */
256     public boolean moveLeft()
257     {
258         if(block != null) {
259             return block.moveLeft(mainContainer);
260         }
261         return false;
262     }
263 
264     /***
265      * Move the active block in the main game area one step right
266      * @return true/false (Success/Failure)
267      */
268     public boolean moveRight()
269     {
270         if(block != null) {
271             return block.moveRight(mainContainer);
272         }
273         return false;
274     }
275 
276     /***
277      * Rotate the active block in the main game area 90 degrees clockwize
278      * @return true/false (Success/Failure)
279      */
280     public boolean rotateRight()
281     {
282         if(block != null) {
283             return block.rotateRight(mainContainer);
284         }
285         return false;
286     }
287 
288     /***
289      * Move the active block in the main game area one step down
290      * @return true/false (Success/Failure)
291      */
292     public boolean moveDown()
293     {
294         if(block != null) {
295             return block.moveDown(mainContainer);
296         }
297         return false;
298     }
299 
300     public boolean moveDownBottom()
301     {
302         while(moveDown()) {
303             ;
304         }
305         return false;
306     }
307 
308     public boolean needUpdate() {
309         return bUpdated;
310     }
311 
312     public BlockContainerData getMainContainer() {
313         return mainContainer;
314     }
315 
316     public Block getNextBlock() {
317         return blockNext;
318     }
319 
320     public long getScore() {
321         return score;
322     }
323 
324     public int getLevel() {
325         return level;
326     }
327 }