original 1.0.1 release
[xwelltris.git] / src / wellclass.cxx
blob7f92ce9364e1dbd8c8b2f440387a09fdb1dcea6c
1 // docm_prefix(///)
2 /****************************************************************************
3 * Copyright (C) 2002 by Leo Khramov
4 * email: leo@xnc.dubna.su
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 ****************************************************************************/
17 # Original algorithm with polyominoes by
19 # David A. Bagley, bagleyd@bigfoot.com
21 # Q. Alex Zhao, azhao@cc.gatech.edu
23 $Id: wellclass.cxx,v 1.3 2003/02/21 11:40:33 leo Exp $
27 /// module description
28 /// Main class that is the game itself - contains game board, generate figures
29 /// drop it to the field, and interacts with the user.
31 #include "wellclass.h"
32 #include "wellengine.h"
33 #include "welldrawing.h"
34 #include "commonfuncs.h"
36 static int speeds[NUM_LEVELS] = {
37 100, 92, 84, 76, 68, 60, 53, 46, 39, 32, 26, 20, 15, 11, 8, 5, 3, 1, 0};
39 //===========================================================================
40 /// global WellBase()
41 /// Constructor of base class - loads polyominoes and init structs
42 /// tags WellBase
43 WellBase::WellBase() : WellObject()
45 int turn_style, number_polyominoes;
47 dre=0;
49 level=0;
50 rows=score=0;
51 pause=steps_to_rotate=0;
52 player_name[0]=0;
54 set_default_options();
56 SRAND(time(NULL));
57 read_polyominoes();
59 turn_style = tris[squares - MIN_SQUARES].mode[diagonal].turn_style;
60 if (turn_style < 0 || turn_style >= MAX_TYPES)
62 fprintf(stderr, "Welltris: corrupted input file %s\n",
63 POLYOMINOFILE);
64 fprintf(stderr, "\tturn_style = %d.\n", turn_style);
65 exit(1);
67 number_polyominoes =
68 tris[squares - MIN_SQUARES].mode[diagonal].number[mixed][turn_style];
69 if (number_polyominoes <= 0 || number_polyominoes > MAX_START_POLYOMINOES)
71 fprintf(stderr, "Welltris: corrupted input file %s\n",
72 POLYOMINOFILE);
73 fprintf(stderr, "\tnumber_polyominoes = %d.\n",
74 number_polyominoes);
75 exit(1);
77 geo=get_geo_by_name("the_game");
80 //===========================================================================
81 /// global new_game()
82 /// set params for new game
83 /// tags WellBase
84 void WellBase::new_game()
86 int i,j;
87 for (j = 0; j < MAX_DEPTH; j++)
88 for (i = 0; i < MAX_PERIMETER; i++)
90 wall[j][i].pmid = EMPTY;
91 wall[j][i].cid = 0;
93 for (j = 0; j < MAX_WIDTH; j++)
94 for (i = 0; i < MAX_WIDTH; i++)
96 base[j][i].pmid = EMPTY;
97 base[j][i].cid = 0;
99 for (i = 0; i < MAX_SIDES; i++)
100 frozen_wall[i] = 0;
102 dre->set_inner_alpha(30);
103 dre->set_outer_alpha(0);
104 dre->set_field_sizes(20,20,14,18);
105 dre->calc_grid_points();
106 dre->set_field_id(0);
108 rows=score=0;
110 if(rotation)
111 steps_to_rotate=level;
112 else
113 steps_to_rotate=0;
115 new_level_calc();
117 new_thing();
118 check_freeze();
119 new_thing();
121 player_score=new Score;
122 player_score->set_player(player_name);
123 player_score->squares=squares;
124 player_score->set_params(score,rows,level);
125 player_score->next_piece=showNext;
126 player_score->rotation=rotation;
127 player_score->mixed=mixed;
130 //===========================================================================
131 /// global init(WellEngine*)
132 /// init class and other related stuff
133 /// tags WellBase
134 void WellBase::init(WellEngine* we)
136 //Additional init's such as read defaults....
137 dbgprintf(("WellBase: game board size: %dx%d\n",VIEW_L,VIEW_H));
138 //And Draw Engine inits
139 if(dre==0)
140 dre=we->new_well_drawing_engine();
141 dre->init(NUM_ROT_STEPS,VIEW_X,VIEW_Y,VIEW_L,VIEW_H);
143 txt_score=we->new_well_image_font(imFont1,FONT2_L,FONT2_H,FONT2_DX,FONT2_DY);
144 txt_score->set_screen_region(SCORE_REG_X,SCORE_REG_Y,
145 SCORE_REG_L,SCORE_REG_H);
147 txt_lines=we->new_well_image_font(imFont1,FONT1_L,FONT1_H,FONT1_DX,FONT1_DY);
148 txt_lines->set_screen_region(LINES_REG_X,LINES_REG_Y,
149 LINES_REG_L,LINES_REG_H);
151 txt_levelup=we->new_well_image_font(imFont1,FONT1_L,FONT1_H,FONT1_DX,FONT1_DY);
152 txt_levelup->set_screen_region(LEVUP_REG_X,LEVUP_REG_Y,
153 LEVUP_REG_L,LEVUP_REG_H);
155 txt_level=we->new_well_image_font(imFont1,FONT1_L,FONT1_H,FONT1_DX,FONT1_DY);
156 txt_level->set_screen_region(LEVEL_REG_X,LEVEL_REG_Y,
157 LEVEL_REG_L,LEVEL_REG_H);
159 txt_first=we->new_well_image_font(imFont1,FONT1_L,FONT1_H,FONT1_DX,FONT1_DY);
160 txt_first->set_screen_region(CHAL1_REG_X,CHAL1_REG_Y,
161 CHAL_REG_L,CHAL_REG_H);
163 txt_second=we->new_well_image_font(imFont1,FONT1_L,FONT1_H,FONT1_DX,FONT1_DY);
164 txt_second->set_screen_region(CHAL2_REG_X,CHAL2_REG_Y,
165 CHAL_REG_L,CHAL_REG_H);
167 txt_third=we->new_well_image_font(imFont1,FONT1_L,FONT1_H,FONT1_DX,FONT1_DY);
168 txt_third->set_screen_region(CHAL3_REG_X,CHAL3_REG_Y,
169 CHAL_REG_L,CHAL_REG_H);
174 //===========================================================================
175 /// global new_level_calc()
176 /// calculate params for new level
177 /// tags WellBase
178 void WellBase::new_level_calc()
180 rows_levelup=THRESHOLD(level);
181 if(shown)
183 if(rotation)
184 make_rotation();
185 default_well_engine->del_timer(this);
186 default_well_engine->add_timer(this,speeds[level]);
190 //==========================================================================
191 /// global set_default_option()
192 /// set options needed by the game to its default values
193 /// tags WellBase
194 void WellBase::set_default_options()
196 bonusNow=false;
197 showNext=true;
198 beep=false;
199 diagonal=false;
200 mixed=true;
201 bonus=true;
202 grid=true;
203 cw=true;
204 gradualAppear=false;
205 squares=4;
206 rotation=true;
209 //===========================================================================
210 /// global read_polyominoes()
211 /// reading polyominoes (our game figures) info from file
212 /// tags WellBase
213 void WellBase::read_polyominoes()
215 char fname[L_MAXPATH];
216 int c, i, j, k, sq, polyomino, sum, start, n, size, height, diag,
217 game, toss = 0;
218 int counter[MAX_SQUARES - MIN_SQUARES + 1];
219 int start_counter[MAX_SQUARES - MIN_SQUARES + 1][MAX_MODES][MAX_TYPES];
220 FILE *fp;
222 find_full_path_for_file(POLYOMINOFILE,fname,ReadOnly);
224 for (sq = 0; sq <= MAX_SQUARES - MIN_SQUARES; sq++)
226 counter[sq] = 0;
227 for (polyomino = 0; polyomino < MAX_POLYOMINOES; polyomino++)
228 for (j = 0; j < MAX_SQUARES; j++)
229 for (i = 0; i < MAX_SQUARES; i++)
230 tris[sq].polyomino[polyomino].shape[j][i] = 0;
231 for (j = 0; j < MAX_TYPES; j++)
233 for (polyomino = 0; polyomino < MAX_START_POLYOMINOES; polyomino++)
235 tris[sq].mode[NODIAG].start[polyomino][j] = 0;
236 tris[sq].mode[DIAGONAL].start[polyomino][j] = 0;
238 start_counter[sq][NODIAG][j] = 0;
239 start_counter[sq][DIAGONAL][j] = 0;
240 tris[sq].mode[NODIAG].number[NOMIX][j] = 0;
241 tris[sq].mode[DIAGONAL].number[NOMIX][j] = 0;
242 tris[sq].mode[NODIAG].number[MIXED][j] = 0;
243 tris[sq].mode[DIAGONAL].number[MIXED][j] = 0;
245 tris[sq].mode[NODIAG].turn_style = NONE;
246 tris[sq].mode[DIAGONAL].turn_style = NONE;
248 if ((fp = fopen(fname, "r")) == (FILE *)NULL)
250 (void) fprintf(stderr, "Can not open input file, %s\n.", POLYOMINOFILE);
251 exit(1);
253 else
255 while ((c = getc(fp)) != EOF)
257 if (c == '/')
259 while ((c = getc(fp)) != '/') {}
260 c = getc(fp);
262 if (c == '+')
264 (void) fscanf(fp, "%d", &k);
265 sq = k - MIN_SQUARES;
266 for (i = 0; i < MAX_TYPES; i++)
268 (void) fscanf(fp, "%d", &k);
269 tris[sq].mode[NODIAG].number[NOMIX][i] = k;
271 (void) fscanf(fp, "%d", &k);
272 tris[sq].mode[NODIAG].turn_style = k;
273 (void) fscanf(fp, "%d", &k);
274 tris[sq].diagonal_switch = k;
275 if (tris[sq].diagonal_switch == true)
277 for (i = 0; i < MAX_TYPES; i++)
279 (void) fscanf(fp, "%d", &k);
280 tris[sq].mode[DIAGONAL].number[NOMIX][i] = k;
282 (void) fscanf(fp, "%d", &k);
283 tris[sq].mode[DIAGONAL].turn_style = k;
285 c = getc(fp);
287 if (c == '*')
289 (void) fscanf (fp, "%d", &size);
290 c = getc(fp);
292 if (c == '~') /* Useful for debugging Things */
294 (void) fscanf (fp, "%d", &toss);
295 c = getc(fp);
297 if (c == '#')
299 (void) fscanf(fp, "%d", &k);
300 sq = k - MIN_SQUARES;
301 (void) fscanf(fp, "%d", &n);
302 if (tris[sq].diagonal_switch == true)
303 (void) fscanf(fp, "%d", &n);
304 for (polyomino = 0; polyomino <= toss; polyomino++)
305 while ((c = getc(fp)) != EOF && c != '\n');
306 for (polyomino = 0; polyomino < n - toss; polyomino++)
308 sum = polyomino + counter[sq];
309 /* This is only there to "read" input file */
310 (void) fscanf(fp, "%d", &k);
311 (void) fscanf(fp, "%d", &k);
312 tris[sq].polyomino[sum].rotation =
313 k + counter[sq] - toss;
314 (void) fscanf(fp, "%d", &k);
315 tris[sq].polyomino[sum].reflection =
316 k + counter[sq] - toss;
317 for (game = JUMPIN; game <= GRADUAL; game++)
319 (void) fscanf(fp, "%d", &height);
320 if (!gradualAppear && game == JUMPIN)
321 tris[sq].polyomino[sum].start_height = height;
322 else if (gradualAppear && game == GRADUAL)
323 tris[sq].polyomino[sum].start_height = height;
324 for (diag = NODIAG; diag <= tris[sq].diagonal_switch; diag++)
326 (void) fscanf(fp, "%d", &start);
327 if (game == JUMPIN)
329 if (sq == 0 ||
330 tris[sq - 1].mode[diag].turn_style == NONE)
332 i = start_counter[sq][diag][NONE];
333 tris[sq].mode[diag].start[i][NONE] = sum;
334 start_counter[sq][diag][NONE]++;
336 if ((sq == 0 ||
337 tris[sq - 1].mode[diag].turn_style < ALL) &&
338 start != NONE)
340 i = start_counter[sq][diag][NOREFL];
341 tris[sq].mode[diag].start[i][NOREFL] = sum;
342 start_counter[sq][diag][NOREFL]++;
344 if (start == ALL)
346 i= start_counter[sq][diag][ALL];
347 tris[sq].mode[diag].start[i][ALL] = sum;
348 start_counter[sq][diag][ALL]++;
353 tris[sq].polyomino[sum].size = size;
354 for (j = 0; j < size; j++)
355 for (i = 0; i < size; i++)
357 (void) fscanf(fp, "%d", &k);
358 tris[sq].polyomino[sum].shape[j][i] = k;
361 counter[sq] += n - toss;
362 toss = 0;
365 (void) fclose(fp);
366 for (i = 0; i <= MAX_SQUARES - MIN_SQUARES; i++)
367 for (j = 0; j < MAX_TYPES; j++)
368 for (k = 0; k <= i; k++)
370 tris[i].mode[NODIAG].number[MIXED][j] +=
371 tris[k].mode[NODIAG].number[NOMIX][j];
372 if (tris[i].diagonal_switch == true)
373 /*since k & i are not independent*/
374 tris[i].mode[DIAGONAL].number[MIXED][j] +=
375 tris[k].mode[DIAGONAL].number[NOMIX][j];
381 //===========================================================================
382 /// global show()
383 /// install itself in lists for proper processing events, draw itself.
384 /// tags WellBase
385 void WellBase::show()
387 default_well_engine->set_main_background_image(imBoardBG);
388 dbgprintf(("WellBase registering event handlers\n"));
389 shown=true;
390 default_well_engine->add_timer(this,speeds[level]);
391 default_well_engine->add_object(this);
392 dre->clear_field(0);
393 draw_field();
394 draw_thing();
396 redraw_all();
399 //===========================================================================
400 /// global hide()
401 /// unregister itself from any events
402 /// tags WellBase
403 void WellBase::hide()
405 shown=false;
406 dbgprintf(("WellBase unregistering from engine\n"));
407 default_well_engine->del_timer(this);
408 default_well_engine->del_object(this);
411 //===========================================================================
412 /// global new_thing()
413 /// Generate new figure random gen for field
414 /// tags WellBase
415 void WellBase::new_thing()
417 curThing = nextThing;
418 nextThing.random_number = LRAND();
419 nextThing.random_rotation = NRAND(MAX_SIDES);
420 nextThing.random_reflection = NRAND(2);
421 nextThing.bonus = bonusNow;
422 bonusNow = false;
423 redo_next();
426 //===========================================================================
427 /// global redo_next()
428 /// fill nextThing vars with data from polyomino
429 /// tags WellBase
430 void WellBase::redo_next()
432 int turn_style = tris[squares - MIN_SQUARES].mode[diagonal].turn_style;
433 int next_start, i;
435 nextThing.squares = squares - MIN_SQUARES + nextThing.bonus;
436 nextThing.squares = nextThing.squares > MAX_SQUARES - MIN_SQUARES ?
437 MAX_SQUARES - MIN_SQUARES: nextThing.squares;
438 next_start = nextThing.random_number % tris[nextThing.squares].
439 mode[diagonal].number[(nextThing.bonus) ? NOMIX : mixed][turn_style];
440 nextThing.color_number = next_start;
441 dbgprintf(("NEXT COLOR number is %d\n",next_start));
442 if (mixed && !nextThing.bonus)
444 nextThing.squares = 0;
445 while (next_start >=
446 tris[nextThing.squares].mode[diagonal].number[NOMIX][turn_style])
448 next_start -=
449 tris[nextThing.squares].mode[diagonal].number[NOMIX][turn_style];
450 nextThing.squares++;
453 nextThing.polyomino_number =
454 tris[nextThing.squares].mode[diagonal].start[next_start][turn_style];
455 if (tris[nextThing.squares].mode[diagonal].turn_style > NONE)
456 for (i = 0; i < nextThing.random_rotation; i++)
457 nextThing.polyomino_number = tris[nextThing.squares].polyomino
458 [nextThing.polyomino_number].rotation;
459 if (tris[nextThing.squares].mode[diagonal].turn_style == ALL)
460 for (i = 0; i < nextThing.random_reflection; i++)
461 nextThing.polyomino_number = tris[nextThing.squares].polyomino
462 [nextThing.polyomino_number].reflection;
463 nextThing.size =
464 tris[nextThing.squares].polyomino[nextThing.polyomino_number].size;
465 nextThing.ypos = -tris[nextThing.squares].polyomino
466 [nextThing.polyomino_number].start_height;
470 //===========================================================================
471 /// global put_box()
472 /// Putting figure into game field
473 /// tags WellBase
474 void WellBase::put_box()
476 int i, j, xi, yj;
477 int x = curThing.xpos, y = curThing.ypos;
479 for (i = 0; i < curThing.size; i++)
480 for (j = 0; j < curThing.size; j++)
481 if ((y + j >= 0) && tris[curThing.squares].polyomino
482 [curThing.polyomino_number].shape[j][i]) {
483 xi = (x + i) % MAX_PERIMETER;
484 yj = y + j;
485 if (yj < MAX_DEPTH) { // Draw on the wall of glass
486 wall[yj][xi].pmid = tris[curThing.squares].polyomino
487 [curThing.polyomino_number].shape[j][i];
488 wall[yj][xi].cid = curThing.color_number;
489 frozen_wall[xi / MAX_WIDTH] = MAX_SIDES;
490 } else { // Draw on the floor (base)
491 int base_i, base_j;
492 wall_to_base(&base_i, &base_j, xi, yj);
493 base[base_j][base_i].pmid = tris[curThing.squares].polyomino
494 [curThing.polyomino_number].shape[j][i];
495 base[base_j][base_i].cid = curThing.color_number;
501 //===========================================================================
502 /// global overlapping()
503 /// check overlapping our figure in current position with another ones
504 /// on game field
505 /// tags WellBase
506 bool WellBase::overlapping()
508 int i, j, xi, yj;
509 int x = curThing.xpos, y = curThing.ypos;
511 for (i = 0; i < curThing.size; i++)
512 for (j = 0; j < curThing.size; j++)
513 if (tris[curThing.squares].polyomino
514 [curThing.polyomino_number].shape[j][i]) {
515 xi = (x + i) % MAX_PERIMETER;
516 yj = y + j;
517 if (yj < MAX_DEPTH) {
518 if (frozen_wall[xi / MAX_WIDTH])
519 return true;
520 if (gradualAppear) {
521 /* This method one can turn polyomino to an area above of screen, also
522 part of the polyomino may not be visible initially */
523 if ((yj >= 0) && (wall[yj][xi].pmid >= 0))
524 return true;
525 } else {
526 /* This method does not allow turning polyomino to an area above screen */
527 if ((yj < 0) || (wall[yj][xi].pmid >= 0))
528 return true;
531 else if (yj < MAX_DEPTH + MAX_WIDTH) {
532 int base_i, base_j;
533 wall_to_base(&base_i, &base_j, xi, yj);
534 if (base[base_j][base_i].pmid >= 0)
535 return true;
537 else
538 return true;
541 return false;
544 //===========================================================================
545 /// global wall_to_base(int* base_x,int* base_y,int wall_x,int wall_y)
546 /// Translate wall coordinates to floor (base) one.
547 /// tags WellBase
548 void WellBase::wall_to_base(int* base_x,int* base_y,int wall_x,int wall_y)
550 switch (wall_x / MAX_WIDTH)
552 case 0:
553 *base_x = wall_x;
554 *base_y = wall_y - MAX_DEPTH;
555 break;
556 case 1:
557 *base_x = MAX_WIDTH - 1 + MAX_DEPTH - wall_y;
558 *base_y = wall_x - MAX_WIDTH;
559 break;
560 case 2:
561 *base_x = MAX_PERIMETER - 1 - MAX_WIDTH - wall_x;
562 *base_y = MAX_WIDTH - 1 + MAX_DEPTH - wall_y;
563 break;
564 case 3:
565 *base_x = wall_y - MAX_DEPTH;
566 *base_y = MAX_PERIMETER - 1 - wall_x;
567 break;
568 default:
569 (void) fprintf (stderr, "wall_to_base kinds range 0-3, got %d.\n",
570 wall_x / MAX_WIDTH);
571 exit(-1);
575 //===========================================================================
576 /// global at_bottom()
577 /// Do we at bottom of the glass? (any piece of our figure)
578 /// tags WellBase
579 bool WellBase::at_bottom()
581 int i, j, xi, yj;
582 int x = curThing.xpos, y = curThing.ypos;
584 for (i = 0; i < curThing.size; i++)
585 for (j = 0; j < curThing.size; j++)
586 if (tris[curThing.squares].polyomino
587 [curThing.polyomino_number].shape[j][i]) {
588 xi = (x + i) % MAX_PERIMETER;
589 yj = y + j;
590 if (yj < -1)
591 return false;
592 if (yj < MAX_DEPTH - 1) {
593 if (frozen_wall[xi / MAX_WIDTH])
594 return true;
595 if (wall[yj + 1][xi].pmid >= 0)
596 return true;
598 else if (yj < MAX_DEPTH + MAX_WIDTH - 1) {
599 int base_i, base_j;
600 wall_to_base(&base_i, &base_j, xi, yj + 1);
601 if (base[base_j][base_i].pmid >= 0)
602 return true;
604 else
605 return true;
608 return false;
611 //===========================================================================
612 /// global at_base_fully()
613 /// Do we fully on the floor? (all pieces of our figure)
614 /// tags WellBase
615 bool WellBase::at_base_fully()
617 int i, j;
619 for (i = 0; i < curThing.size; i++)
620 for (j = 0; j < curThing.size; j++)
621 if (curThing.ypos + j < MAX_DEPTH && tris[curThing.squares].polyomino
622 [curThing.polyomino_number].shape[j][i])
623 return false;
624 return true;
627 //===========================================================================
628 /// global at_base_partially()
629 /// Do we on the floor? (at least one of our piece)
630 /// tags WellBase
631 bool WellBase::at_base_partially()
633 int i, j;
635 for (i = 0; i < curThing.size; i++)
636 for (j = 0; j < curThing.size; j++)
637 if (curThing.ypos + j >= MAX_DEPTH && tris[curThing.squares].polyomino
638 [curThing.polyomino_number].shape[j][i])
639 return true;
640 return false;
643 //===========================================================================
644 /// global wall_change(thing_t old,thing_t new_t)
645 /// Do we change the wall from last position?
646 /// tags WellBase
647 bool WellBase::wall_change(thing_t old,thing_t new_t)
649 int w = -1, i, j;
650 int x = curThing.xpos;
652 for (i = 0; i < old.size; i++)
653 for (j = 0; j < old.size; j++)
654 if (tris[old.squares].polyomino[old.polyomino_number].shape[j][i]) {
655 if (w == -1)
656 w = ((x + i) % MAX_PERIMETER) / MAX_WIDTH;
657 else if (w != ((x + i) % MAX_PERIMETER) / MAX_WIDTH)
658 return true;
660 for (i = 0; i < new_t.size; i++)
661 for (j = 0; j < new_t.size; j++)
662 if (tris[new_t.squares].polyomino[new_t.polyomino_number].shape[j][i])
663 if (w != ((x + i) % MAX_PERIMETER) / MAX_WIDTH)
664 return true;
665 return false;
669 //===========================================================================
670 /// global try_move(Actions move)
671 /// Trying to move/rotate/fall our figure according to the given move action
672 /// tags WellBase
673 void WellBase::try_move(Actions move)
675 thing_t old;
676 int i;
677 bool skip = false;
679 old = curThing;
681 switch (move) {
682 case FALL:
683 curThing.ypos ++;
684 break;
686 case DROP:
687 do {
688 curThing.ypos ++;
689 score += level;
690 } while (!overlapping());
691 curThing.ypos --;
692 break;
694 case LEFT:
695 curThing.xpos = (curThing.xpos + MAX_PERIMETER - 1) % MAX_PERIMETER;
696 if (at_base_fully() || (at_base_partially() && wall_change(old, curThing)))
697 skip = true;
698 break;
700 case RIGHT:
701 curThing.xpos = (curThing.xpos + 1) % MAX_PERIMETER;
702 if (at_base_fully() || (at_base_partially() && wall_change(old, curThing)))
703 skip = true;
704 break;
706 case ROTATE:
707 if (tris[squares - MIN_SQUARES].mode[diagonal].turn_style > NONE)
709 if (cw)
710 for (i = 0; i < MAX_SIDES - 1; i++)
711 curThing.polyomino_number = tris[curThing.squares].polyomino
712 [curThing.polyomino_number].rotation;
713 else /* ccw */
714 curThing.polyomino_number = tris[curThing.squares].polyomino
715 [curThing.polyomino_number].rotation;
716 curThing.xpos = old.xpos;
717 curThing.ypos = old.ypos;
718 if (at_base_partially() && wall_change(old, curThing))
719 skip = true;
721 break;
723 case REFLECT: /* reflect on y axis */
724 if (tris[squares - MIN_SQUARES].mode[diagonal].turn_style == ALL)
726 curThing.polyomino_number = tris[curThing.squares].polyomino
727 [curThing.polyomino_number].reflection;
728 curThing.xpos = old.xpos;
729 curThing.ypos = old.ypos;
730 if (at_base_partially() && wall_change(old, curThing))
731 skip = true;
733 break;
734 default:
735 skip=true;
736 break;
739 if (!skip && !overlapping())
740 draw_thing_diff(&old);
741 else
742 curThing = old;
745 //===========================================================================
746 /// global draw_box(int color,int i,int j)
747 /// Draw our box (piece of figure) on our virtual square (walls + floor)
748 /// tags WellBase
749 void WellBase::draw_box(int color,int i,int j)
751 if (j < MAX_DEPTH) { //Draw trapazoid on the wall
752 dre->draw_trapazoid(color, i, j);
754 else { // Draw square on the floor
755 int base_i, base_j;
756 wall_to_base(&base_i, &base_j, i, j);
757 dre->draw_square(color, base_i, base_j);
761 //===========================================================================
762 /// global draw_thing()
763 /// for all squares in figure do draw_box -> draw whole figure on the field
764 /// tags WellBase
765 void WellBase::draw_thing()
767 int i, j, xi;
769 for (i = 0; i < curThing.size; i++)
770 for (j = 0; j < curThing.size; j++)
771 if (tris[curThing.squares].polyomino
772 [curThing.polyomino_number].shape[j][i]) {
773 xi = (curThing.xpos + i) % MAX_PERIMETER;
774 draw_box(curThing.color_number,xi, curThing.ypos + j);
778 //===========================================================================
779 /// global draw_thing_diff(thing_t* old)
780 /// Make diff between old and new position on figure and Draw its
781 /// actually Draw new one and clear empty old pieces :)
782 /// tags WellBase
783 void WellBase::draw_thing_diff(thing_t* old)
785 int i, j, ox, oy;
787 for (i = 0; i < curThing.size; i++)
788 for (j = 0; j < curThing.size; j++)
789 if ((curThing.ypos + j >= 0) && tris[curThing.squares].polyomino
790 [curThing.polyomino_number].shape[j][i])
792 draw_box(curThing.color_number,
793 (curThing.xpos + i) % MAX_PERIMETER, curThing.ypos + j);
796 for (i = 0; i < curThing.size; i++)
797 for (j = 0; j < curThing.size; j++)
799 ox = (old->xpos + i - curThing.xpos + MAX_PERIMETER) % MAX_PERIMETER;
800 oy = old->ypos + j - curThing.ypos;
801 if (tris[old->squares].polyomino[old->polyomino_number].shape[j][i] &&
802 ((ox >= curThing.size) || (oy < 0) || (oy >= curThing.size) ||
803 !tris[curThing.squares].polyomino
804 [curThing.polyomino_number].shape[oy][ox]))
806 draw_box(BackColor,(old->xpos + i) % MAX_PERIMETER, old->ypos + j);
811 //===========================================================================
812 /// global fill_lines()
813 /// Fill all glass with random squares. Just for test only
814 /// tags WellBase
815 void WellBase::fill_lines()
817 int i, j;
818 int turn_style = tris[squares - MIN_SQUARES].mode[diagonal].turn_style;
820 for (j = 0; j < MAX_DEPTH + MAX_WIDTH; j++)
821 for (i = 0; i < MAX_PERIMETER; i++)
823 draw_box(NRAND(tris[squares - MIN_SQUARES].mode
824 [diagonal].number[mixed][turn_style]),
825 i, j);
829 //===========================================================================
830 /// global freeze_wall(int w)
831 /// Freeze wall - make some blinks while freezing :)
832 /// tags WellBase
833 void WellBase::freeze_wall(int w)
835 int i, j;
837 for (j = 0; j < MAX_DEPTH; j++)
838 for (i = 0; i < MAX_WIDTH; i++)
840 if (wall[j][i+w*MAX_WIDTH].pmid < 0)
841 dre->draw_trapazoid(FreezeColor, w * MAX_WIDTH + i, j);
843 dre->sync();
844 udelay(FLUSH_DELAY);
845 for (j = 0; j < MAX_DEPTH; j++)
846 for (i = 0; i < MAX_WIDTH; i++)
848 if (wall[j][i+w*MAX_WIDTH].pmid < 0)
849 dre->draw_trapazoid (BackColor, w * MAX_WIDTH + i, j);
851 dre->sync();
852 udelay(FLUSH_DELAY);
853 for (j = 0; j < MAX_DEPTH; j++)
854 for (i = 0; i < MAX_WIDTH; i++)
856 if (wall[j][i+w*MAX_WIDTH].pmid < 0)
857 dre->draw_trapazoid (FreezeColor, w * MAX_WIDTH + i, j);
859 if (beep)
860 dre->bell(BVOLUME);
861 dre->sync();
864 //===========================================================================
865 /// global defreeze_wall(int w)
866 /// Return wall to normal state
867 /// tags WellBase
868 void WellBase::defreeze_wall(int w)
870 int i, j;
872 for (j = 0; j < MAX_DEPTH; j++)
873 for (i = 0; i < MAX_WIDTH; i++)
875 if (wall[j][i+w*MAX_WIDTH].pmid < 0)
876 dre->draw_trapazoid (BackColor, w * MAX_WIDTH + i, j);
878 if (beep)
879 dre->bell(BVOLUME);
880 dre->sync();
883 void WellBase::udelay(int msec)
885 default_well_engine->udelay(msec);
888 //===========================================================================
889 /// global draw_field()
890 /// Draw field with squares and frozen walls
891 /// tags WellBase
892 void WellBase::draw_field()
894 int i, j;
896 for (i = 0; i < MAX_PERIMETER; i++)
897 for (j = 0; j < MAX_DEPTH; j++)
899 if (wall[j][i].pmid >= 0)
900 dre->draw_trapazoid(wall[j][i].cid, i, j);
901 else
903 if (frozen_wall[i / MAX_WIDTH])
904 dre->draw_trapazoid(FreezeColor, i, j);
905 else
906 dre->draw_trapazoid(BackColor, i, j);
909 for (i = 0; i < MAX_WIDTH; i++)
910 for (j = 0; j < MAX_WIDTH; j++)
911 if (base[j][i].pmid >= 0)
912 dre->draw_square(base[j][i].cid, i, j);
913 else
914 dre->draw_square(BackColor, i, j);
915 dre->clear_dirty_list();
916 dre->field_sync();
919 //===========================================================================
920 /// global draw_next()
921 /// Draw next figure (cheating?)
922 /// Currently not implemented
923 /// tags WellBase
924 void WellBase::draw_next()
926 int x, y;
927 int i, j;
929 Colors color= nextThing.bonus ? BonusColor : GridColor;
930 Colors color2= nextThing.bonus ? BonusColor2 : GridColor2;
932 dbgprintf(("Next color: %d, size: %d\n",nextThing.color_number,
933 nextThing.size));
934 x=NEXT_CENTER_X - nextThing.size*(NEXT_BOX_SIZE+2)/2;
935 y=NEXT_CENTER_Y - nextThing.size*(NEXT_BOX_SIZE+2)/2;
937 for (i = 0; i < nextThing.size; i++)
938 for (j = 0; j < nextThing.size; j++)
939 if (tris[nextThing.squares].polyomino
940 [nextThing.polyomino_number].shape[j][i])
942 dre->draw_rect(x+ (NEXT_BOX_SIZE+2)*i, y+ (NEXT_BOX_SIZE+2)*j,
943 NEXT_BOX_SIZE, NEXT_BOX_SIZE, color);
944 dre->draw_rect(x+ (NEXT_BOX_SIZE+2)*i +1, y+ (NEXT_BOX_SIZE+2)*j +1,
945 NEXT_BOX_SIZE-2, NEXT_BOX_SIZE-2, color2);
947 dre->sync();
950 //===========================================================================
951 /// global clear_next()
952 /// Clear next figure
953 /// Currently not implemented
954 /// tags WellBase
955 void WellBase::clear_next()
957 dre->fill_rect(NEXT_CENTER_X-NEXT_X_SIZE/2+1,NEXT_CENTER_Y-NEXT_Y_SIZE/2+1,
958 NEXT_X_SIZE-1,NEXT_Y_SIZE-1,BackColor);
961 //===========================================================================
962 /// global draw_status()
963 /// draw status of the game, i.e. scores, lines...
964 /// Currently not implemented
965 /// tags WellBase
966 void WellBase::draw_status()
968 int delta_score;
969 Score *pscore2=0,*pscore1=0;
970 char buf[L_MAXPATH];
971 char buf2[PLAYER_NAME_LEN];
973 if(!shown)
974 return;
976 dbgprintf(("score: %d, lines: %d, level %d, levelup at: +%d\n",
977 score, rows, level, rows_levelup - rows));
978 sprintf(buf,"%d",score);
979 txt_score->set_text(buf);
980 txt_score->draw_text(RightJust);
981 sprintf(buf,"%d",rows);
982 txt_lines->set_text(buf);
983 txt_lines->draw_text(RightJust);
984 sprintf(buf,"+%d",rows_levelup - rows + 1);
985 txt_levelup->set_text(buf);
986 txt_levelup->draw_text(RightJust);
987 sprintf(buf,"%d",level);
988 txt_level->set_text(buf);
989 txt_level->draw_text(RightJust);
990 dbgprintf(("score done\n"));
991 pscore2=default_top_nine->find_challenger(player_score);
992 if(pscore2)
993 pscore1=default_top_nine->find_challenger(pscore2);
995 do {
996 if(pscore1)
998 delta_score=pscore1->score - player_score->score;
999 delta_score= delta_score>=100000 ? 99999 : delta_score;
1000 strncpy(buf2,pscore1->player,CHAL_NAME_LEN);
1001 buf2[CHAL_NAME_LEN]=0;
1002 sprintf(buf,"%d.%-9s+%05d",pscore1->place,buf2,
1003 delta_score);
1004 dbgprintf(("draw_status: %s\n",buf));
1005 txt_first->set_text(buf);
1006 txt_first->draw_text();
1008 strncpy(buf2,pscore2->player,CHAL_NAME_LEN);
1009 buf2[CHAL_NAME_LEN]=0;
1010 delta_score=pscore2->score - player_score->score;
1011 delta_score= delta_score>=100000 ? 99999 : delta_score;
1012 sprintf(buf,"%d.%-9s+%05d",pscore2->place,buf2,
1013 delta_score);
1014 txt_second->set_text(buf);
1015 txt_second->draw_text();
1017 sprintf(buf,"%d.You are here",pscore2->place+1);
1018 txt_third->set_text(buf);
1019 txt_third->draw_text();
1020 break;
1022 if(pscore2)
1024 strncpy(buf2,pscore2->player,CHAL_NAME_LEN);
1025 buf2[CHAL_NAME_LEN]=0;
1026 delta_score=pscore2->score - player_score->score;
1027 delta_score= delta_score>=100000 ? 99999 : delta_score;
1028 sprintf(buf,"%d.%-9s+%05d",pscore2->place,buf2,
1029 delta_score);
1030 txt_first->set_text(buf);
1031 txt_first->draw_text();
1033 sprintf(buf,"%d.You are here",pscore2->place+1);
1034 txt_second->set_text(buf);
1035 txt_second->draw_text();
1037 txt_third->clear_region();
1038 break;
1040 sprintf(buf,"%d.You are here",1);
1041 txt_first->set_text(buf);
1042 txt_first->draw_text();
1044 txt_second->clear_region();
1046 txt_third->clear_region();
1047 } while(0);
1049 if(rotation)
1050 default_well_engine->screen_copy(&geo[GEO_ROT_IDX]);
1051 if(showNext)
1052 default_well_engine->screen_copy(&geo[GEO_NEXT_IDX]);
1053 if(mixed)
1054 default_well_engine->screen_copy(&geo[GEO_MIXED_IDX]);
1055 dre->sync();
1058 //===========================================================================
1059 /// global draw_grid()
1060 /// draw grid of the field
1061 /// tags WellBase
1062 void WellBase::draw_grid()
1064 dre->draw_grid();
1067 //===========================================================================
1068 /// global drop_wall(int wall_num)
1069 /// Drop all squres on the wall to the floor after row is cleared
1070 /// tags WellBase
1071 void WellBase::drop_wall(int w)
1073 int i, j, k, l, fits, lines, base_x, base_y;
1074 lines = 0;
1075 for (j = MAX_DEPTH - 1; j >= 0 && lines == 0; j--)
1076 for (i = 0; i < MAX_WIDTH; i++)
1077 if (wall[j][w * MAX_WIDTH + i].pmid != EMPTY)
1078 lines = MAX_DEPTH - j;
1079 if (lines > 0) {
1080 fits = true;
1081 j = 0;
1082 while (j < (MAX_WIDTH / 2 + lines - 1) && fits) {
1083 j++;
1084 for (l = MAX_DEPTH - j; l < MAX_DEPTH; l++)
1085 for (i = 0; i < MAX_WIDTH; i++)
1086 if (wall[l][w * MAX_WIDTH + i].pmid != EMPTY) {
1087 wall_to_base(&base_x, &base_y,
1088 w * MAX_WIDTH + i, l + j);
1089 if (base[base_y][base_x].pmid != EMPTY)
1090 fits = false;
1093 if (!fits)
1094 j--;
1095 if (j > 0)
1097 for (l = MAX_DEPTH - 1; l >= 0; l--)
1098 for (i = 0; i < MAX_WIDTH; i++)
1099 if (wall[l][w * MAX_WIDTH + i].pmid != EMPTY) {
1100 k = w * MAX_WIDTH + i;
1101 if (l + j >= MAX_DEPTH) {
1102 wall_to_base(&base_x, &base_y, k, l + j);
1103 base[base_y][base_x] = wall[l][k];
1104 wall[l][k].pmid = EMPTY;
1105 dre->draw_trapazoid(BackColor, k, l);
1106 dre->draw_square(wall[l][k].cid, base_x, base_y);
1107 } else {
1108 wall[l + j][k] = wall[l][k];
1109 wall[l][k].pmid = EMPTY;
1110 dre->draw_trapazoid(BackColor, k, l);
1111 dre->draw_trapazoid(wall[l][k].cid, k, l + j);
1113 dre->sync();
1115 if (beep)
1116 dre->bell(BVOLUME);
1117 dre->sync();
1122 //===========================================================================
1123 /// global all_frozen()
1124 /// True if all walls are frozen -> end of the game
1125 /// tags WellBase
1126 bool WellBase::all_frozen()
1128 int w;
1130 for (w = 0; w < MAX_SIDES; w++)
1131 if (frozen_wall[w] == MAX_SIDES) {
1132 freeze_wall(w);
1134 for (w = 0; w < MAX_SIDES; w++)
1135 if (frozen_wall[w] == 0)
1136 return false;
1137 return true;
1140 //===========================================================================
1141 /// global check_freeze()
1142 /// Check frozen walls - decrease frozen counter and do defreeze
1143 // and dropwall
1144 /// tags WellBase
1145 void WellBase::check_freeze()
1147 int w;
1148 bool all_frozen=true;
1150 for (w = 0; w < MAX_SIDES; w++) {
1151 if (frozen_wall[w] == 0)
1153 all_frozen=false;
1154 drop_wall(w);
1156 else
1158 frozen_wall[w]--;
1159 if (frozen_wall[w] == 0)
1161 defreeze_wall(w);
1162 drop_wall(w);
1163 all_frozen=false;
1168 if(all_frozen)
1170 dbgprintf(("check_freeze - all frozen - doing game_over\n"));
1171 throw aGameOver;
1174 /* not all frozen else this is an infinite loop */
1175 /* curThing.xpos = (MAX_WIDTH - curThing.size) / 2; */
1176 curThing.xpos = NRAND(MAX_WIDTH - curThing.size + 1);
1177 do {
1178 w = NRAND(MAX_SIDES);
1179 } while (frozen_wall[w]); //Hmm, very strange method of choosing the wall???
1180 curThing.xpos += w * MAX_WIDTH;
1183 //===========================================================================
1184 /// global check_lines()
1185 /// Checking for full lines on the floor and deleting it - make free space
1186 /// tags WellBase
1187 int WellBase::check_lines()
1189 int lSet[2][MAX_WIDTH], nset[2];
1190 int i, j, k;
1192 nset[0] = nset[1] = 0;
1194 //First check horizontal lines, increase nset[0] and lSet[0][line]
1195 for (j = 0; j < MAX_WIDTH; j++)
1197 lSet[0][j] = 0;
1198 for (i = 0; i < MAX_WIDTH; i++)
1199 if (base[j][i].pmid >= 0)
1200 lSet[0][j] ++;
1201 if (lSet[0][j] == MAX_WIDTH)
1202 nset[0] ++;
1204 //Then the same for vertical ones
1205 for (i = 0; i < MAX_WIDTH; i++)
1207 lSet[1][i] = 0;
1208 for (j = 0; j < MAX_WIDTH; j++)
1209 if (base[j][i].pmid >= 0)
1210 lSet[1][i] ++;
1211 if (lSet[1][i] == MAX_WIDTH)
1212 nset[1] ++;
1214 if (nset[0] || nset[1]) //If we have full lines
1216 // Now flashing full lines awhile
1217 for (k = 0; k < NUM_FLASHES; k++)
1219 int color;
1220 color=(k%2) ? BackColor : FlashColor;
1221 for (j = 0; j < MAX_WIDTH; j++)
1223 if (lSet[0][j] == MAX_WIDTH)
1225 for (i = 0; i < MAX_WIDTH; i++)
1226 dre->draw_square(color, i, j);
1228 if (lSet[1][j] == MAX_WIDTH)
1230 for (i = 0; i < MAX_WIDTH; i++)
1231 dre->draw_square(color, j, i);
1234 dre->flush_dirty();
1235 dre->sync();
1236 udelay(FLUSH_DELAY/2);
1239 if (nset[0] > 0) //Now delete full horizontal lines
1240 for (j = 0; j < MAX_WIDTH; j++)
1241 if (lSet[0][j] == MAX_WIDTH)
1243 if (j < MAX_WIDTH / 2)
1244 //If upper part of field then move other lines down to center
1245 for (i = 0; i < MAX_WIDTH; i++)
1247 for (k = j; k > 0; k--)
1248 base[k][i] = base[k - 1][i];
1249 base[0][i].pmid = EMPTY;
1251 else //else move them up
1253 for (i = 0; i < MAX_WIDTH; i++)
1255 for (k = j; k < MAX_WIDTH - 1; k++)
1256 base[k][i] = base[k + 1][i];
1257 base[MAX_WIDTH - 1][i].pmid = EMPTY;
1259 for (k = j; k < MAX_WIDTH - 1; k++)
1260 //Fixing lSet position of moved lines
1261 lSet[0][k]=lSet[0][k+1];
1262 lSet[0][MAX_WIDTH-1]=0;
1263 j--; //Fixing index
1266 if (nset[1] > 0) //Do the same for vertical lines
1267 for (i = 0; i < MAX_WIDTH; i++)
1268 if (lSet[1][i] == MAX_WIDTH)
1270 if (i < MAX_WIDTH / 2)
1271 for (j = 0; j < MAX_WIDTH; j++)
1273 for (k = i; k > 0; k--)
1274 base[j][k] = base[j][k - 1];
1275 base[j][0].pmid = EMPTY;
1277 else
1279 for (j = 0; j < MAX_WIDTH; j++)
1281 for (k = i; k < MAX_WIDTH - 1; k++)
1282 base[j][k] = base[j][k + 1];
1283 base[j][MAX_WIDTH - 1].pmid = EMPTY;
1285 for (k = i; k < MAX_WIDTH - 1; k++)
1286 lSet[1][k]=lSet[1][k+1];
1287 lSet[1][MAX_WIDTH-1]=0;
1288 i--;
1292 //Now reDraw new field
1293 for (j = 0; j < MAX_WIDTH; j++)
1294 for (i = 0; i < MAX_WIDTH; i++)
1296 if (base[j][i].pmid >= 0)
1297 dre->draw_square(base[j][i].cid, i, j);
1298 else
1299 dre->draw_square(BackColor, i, j);
1301 //All done, beeping...
1302 if (beep)
1303 dre->bell(BVOLUME);
1304 dre->flush_dirty();
1305 dre->sync();
1308 return (nset[0] + nset[1]);
1312 //===========================================================================
1313 /// global check_update_lines()
1314 /// Calculating statistics ans SCORES! :) And redraw status
1315 /// tags WellBase
1316 void WellBase::check_update_lines()
1318 int lines,mult;
1319 int oldrows=rows;
1320 lines = check_lines();
1321 score += lines + !gradualAppear + !grid;
1322 mult= showNext ? 5 : 7;
1323 mult += (rotation ? 1 : 0);
1324 score += mult * level * level * lines * lines * lines *
1325 squares * squares * (bonus + diagonal + 1) / (16 * (1 + mixed));
1326 rows += lines;
1327 player_score->set_params(score,rows,level);
1328 if (rows > rows_levelup)
1330 level++;
1331 new_level_calc();
1332 if (bonus)
1333 bonusNow = true;
1334 player_score->set_params(score,rows,level);
1335 draw_status();
1336 } else
1337 if(oldrows!=rows)
1338 draw_status();
1341 //===========================================================================
1342 /// global move_one_step(Actions move)
1343 /// Move figure one step down/left/right
1344 /// tags WellBase
1345 bool WellBase::move_one_step(Actions move)
1347 if ((move == DROP) || ((move == FALL) && at_bottom())) {
1348 try_move(move);
1349 put_box();
1350 check_update_lines();
1351 new_thing();
1352 if (showNext) {
1353 clear_next();
1354 draw_next();
1356 dre->sync(); /* discard all events */
1357 if (all_frozen())
1358 throw aGameOver;
1359 check_freeze();
1360 if (overlapping())
1361 throw aGameOver;
1362 check_update_lines();
1363 draw_thing();
1364 return true;
1365 } else {
1366 try_move(move);
1367 if (rows > THRESHOLD(level)) {
1368 level++;
1369 draw_status();
1370 if (bonus)
1371 bonusNow = true;
1374 return false;
1377 //===========================================================================
1378 /// global game_over()
1379 /// game is over :( you are looser
1380 /// tags WellBase
1381 void WellBase::game_over()
1383 dbgprintf(("WellBase::game_over() called\n"));
1384 hide();
1385 player_score->calc_play_time();
1386 player_score=default_top_nine->try_add_to_table(player_score);
1387 delete player_score;
1388 game_over_object.call(wEvent(aGameOver,this));
1391 //===========================================================================
1392 /// global redraw_all()
1393 /// redraw all game
1394 /// tags WellBase
1395 void WellBase::redraw_all()
1397 if(!shown)
1398 return;
1400 draw_status();
1401 dre->flush_all();
1402 clear_next();
1403 if(showNext)
1404 draw_next();
1405 dre->flush_all();
1407 while(steps_to_rotate>0)
1409 make_rotation();
1410 steps_to_rotate--;
1411 udelay(FLUSH_DELAY/10);
1414 dre->sync();
1417 //===========================================================================
1418 /// global make_pause()
1419 /// set/uset game pause
1420 /// tags WellBase
1421 void WellBase::make_pause()
1423 pause^=1;
1424 if(pause)
1426 default_well_engine->del_timer(this);
1427 dre->clear_field(0);
1428 dre->pixmap_copy(&geo[GEO_PAUSE_IDX]);
1429 dre->flush_all();
1430 dre->sync();
1431 } else
1433 default_well_engine->add_timer(this,speeds[level]);
1434 dre->clear_field(0);
1435 draw_field();
1436 draw_thing();
1437 redraw_all();
1441 //===========================================================================
1442 /// global make_rotation()
1443 /// rotate field step by step
1444 /// tags WellBase
1445 void WellBase::make_rotation()
1447 dre->outer_rotation();
1448 dre->clear_field(0);
1449 draw_field();
1450 draw_thing();
1451 dre->flush_all();
1452 dre->sync();
1455 //===========================================================================
1456 /// global process_event()
1457 /// process all events for this game object
1458 /// return false if we don't want to process this event for other objects
1459 /// tags WellBase
1460 bool WellBase::process_event(wEvent ev)
1462 Actions action;
1464 switch(ev.type)
1466 case eTimeOut:
1467 dbgprintf(("WellBase got time out event\n"));
1470 move_one_step(FALL);
1471 dre->flush_dirty();
1473 catch(EvType)
1475 game_over();
1476 return false;
1478 break;
1480 case eExpose:
1481 dbgprintf(("WellBase got expose event\n"));
1482 redraw_all();
1483 break;
1485 case eFocusOut:
1486 if(!pause)
1487 make_pause();
1488 return false;
1490 case eKeyPress:
1491 action=dre->key_to_action(ev.data);
1492 try
1494 return process_action(action);
1496 catch(EvType)
1498 game_over();
1499 return false;
1502 case eDelete:
1503 hide();
1504 break;
1506 case aIntroExit:
1507 new_game();
1508 show();
1509 break;
1511 return true;
1514 //===========================================================================
1515 /// global process_action(Actions)
1516 /// process actions - moves/drops/other
1517 /// tags WellBase
1518 bool WellBase::process_action(Actions action)
1520 switch(action)
1522 case LEFT:
1523 case RIGHT:
1524 case ROTATE:
1525 case FALL:
1526 case DROP:
1527 if(pause)
1528 return false;
1529 move_one_step(action);
1530 dre->flush_dirty();
1531 return false;
1533 case PAUSE_GAME:
1534 make_pause();
1535 return false;
1537 case OUTER_ROTATION:
1538 if(pause)
1539 return false;
1540 make_rotation();
1541 return false;
1543 case END_GAME:
1544 game_over();
1545 return false;
1547 case LEVEL_UP:
1548 if(pause)
1549 return false;
1550 if(level+1<NUM_LEVELS)
1552 level++;
1553 new_level_calc();
1554 draw_status();
1556 return false;
1557 case LEVEL_DOWN:
1558 if(pause)
1559 return false;
1560 if(level-1>0)
1562 level--;
1563 new_level_calc();
1564 draw_status();
1566 return false;
1568 return true;