Update programs/games/flood-it/flood-it.c
update game info Signed-off-by: Kiril Lipatov <lipatov.kiril@gmail.com>
This commit is contained in:
@@ -1,424 +1,426 @@
|
||||
//Leency 2011 - 2025, Flood-it! v3.0, GPL
|
||||
|
||||
#include "lib\kolibri.h"
|
||||
#include "lib\random.h"
|
||||
|
||||
system_colors sc;
|
||||
proc_info Form;
|
||||
dword help_window_stak[100];
|
||||
|
||||
#define DEFAULT_BLOCK_COUNT 14
|
||||
#define DEFAULT_MAX_CLICKS 25
|
||||
#define MAX_BLOCK_SIZE 28
|
||||
char board_size = -1;
|
||||
int BLOCK_SIZE; //cell size
|
||||
int BLOCKS_NUM; //number of cells by X and Y
|
||||
int MAX_CLICKS; //max clicks for win
|
||||
int CLICKS; //how many clicks user already did
|
||||
int game_end;
|
||||
|
||||
#define USER_PANEL_WIDTH 144
|
||||
|
||||
//six colors are used in a game for a cells
|
||||
//and seventh color is used to mark a cell during filling process
|
||||
dword FIELD_COLORS[] = {0xf18db6, 0x605ca8, 0xfddc80, 0xdc4a20, 0x46b1e2, 0x7e9d1e, 0x232323};
|
||||
char BOARD_SIZES[] = "S\0L";
|
||||
|
||||
|
||||
#ifdef LANG_RUS
|
||||
char *BUTTON_CAPTIONS[]={ " <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> [F2]", " <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> [F1]", " <20><>室 [Esc]", 0};
|
||||
char CLICKS_TEXT[]=" <20><><EFBFBD><EFBFBD><EFBFBD>: /";
|
||||
char LEVELS_TEXT[]=" <20><><EFBFBD><EFBFBD>:";
|
||||
|
||||
char HELP_WINDOW_CAPTION[]="<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>";
|
||||
char *HELP_TEXT[]={ "<EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> Flood-it?",
|
||||
"",
|
||||
"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> 梥⮬ <20><> <20><>࠭<EFBFBD>祭<EFBFBD><E7A5AD><EFBFBD> <20><> 室<><E5AEA4>.",
|
||||
"<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>稭<EFBFBD><E7A8AD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD>孥<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>⪨. <20>롥<EFBFBD><EBA1A5><EFBFBD><EFBFBD> 梥<>, <20><><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20><>",
|
||||
"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>⨪<EFBFBD><EFBFBD> <><E1ABA5>, <20> <20><><EFBFBD>⪨ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>⨬ 梥⮬ - ⠪ <20><> <20><><EFBFBD>ᮥ<EFBFBD><E1AEA5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",
|
||||
"<EFBFBD><EFBFBD>ᥤ<EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>⪨ ⮩ <20><> <20><><EFBFBD><EFBFBD>᪨. <20><>墠<EFBFBD><E5A2A0><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>㦭<EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>쭮<EFBFBD>",
|
||||
"<EFBFBD><EFBFBD> 室<><E5AEA4>. <20><>蠣<EFBFBD><E8A0A3><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>⥣<EFBFBD><E2A5A3> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ਭ樯<E0A8AD><E6A8AF> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,",
|
||||
"<EFBFBD>⮡<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!",
|
||||
"",
|
||||
"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ⠪<><E2A0AA> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>蠬<EFBFBD>:",
|
||||
"[Q] [W] [E]",
|
||||
"[A] [S] [D]",
|
||||
0};
|
||||
#elif LANG_EST
|
||||
char *BUTTON_CAPTIONS[]={ "Uus m<>ng [F2]", "Abi [F1]", "V<EFBFBD>lju [Esc]", 0};
|
||||
char CLICKS_TEXT[]="Klikki: /";
|
||||
char LEVELS_TEXT[]="V<EFBFBD>li:";
|
||||
|
||||
char HELP_WINDOW_CAPTION[]="Help";
|
||||
char *HELP_TEXT[]={ "Kuidas m<>ngida m<>ngu Flood-it?",
|
||||
"",
|
||||
"Ujuta kogu m<EFBFBD>nguv<EFBFBD>li <20>le <20>he v<>rviga lubatud k<>ikude arvuga.",
|
||||
"M<EFBFBD>ngu alustad <20>lemisest vasakust nurgast ja edened valides <20>he v<>rvi",
|
||||
"vajutades nuppudele vasakul. Kui sa muudad v<>rvi pragusel alal,",
|
||||
"siis iga kokkupuutuv sama v<>rv muutub samaks. Nii saad ujutada",
|
||||
"teised alad m<>nguv<75>ljal <20>le. Valida saad 2 m<>nguv<75>lja suuruse",
|
||||
"vahel. Proovi v<>li <20>le ujutada etteandtud k<>ikude arvuga!",
|
||||
"",
|
||||
"M<EFBFBD>ngida saab ka klaviatuuriga:",
|
||||
"[Q] [W] [E]",
|
||||
"[A] [S] [D]",
|
||||
0};
|
||||
#else
|
||||
char *BUTTON_CAPTIONS[]={ "Restart [F2]", " Help [F1]", " Exit [Esc]", 0};
|
||||
char CLICKS_TEXT[]="Clicks: /";
|
||||
char LEVELS_TEXT[]="Board:";
|
||||
|
||||
char HELP_WINDOW_CAPTION[]="Help";
|
||||
char *HELP_TEXT[]={ "How to play Flood-it?",
|
||||
"",
|
||||
"Flood the whole board with one color within the allowed steps.",
|
||||
"You start from the top left corner and progress by selecting one",
|
||||
"of the colored buttons on the left. When you change your current area",
|
||||
"color, every adjacent square with the same color also changes, that",
|
||||
"way you can flood other areas of the board. Select from 3 sizes of",
|
||||
"the board and try to flood-it in the least amount of steps!",
|
||||
"",
|
||||
"You can also play with keyboard:",
|
||||
"[Q] [W] [E]",
|
||||
"[A] [S] [D]",
|
||||
0};
|
||||
#endif
|
||||
|
||||
|
||||
unsigned char color_matrix[28*28]; //our field
|
||||
|
||||
unsigned char loss_matrix[14*14]={
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 2, 3, 2, 2,
|
||||
2, 3, 2, 2, 2, 3, 2, 3, 2, 2, 2, 3, 2, 2,
|
||||
2, 3, 2, 2, 2, 3, 2, 3, 2, 3, 2, 3, 2, 2,
|
||||
2, 3, 2, 2, 2, 3, 2, 3, 2, 3, 2, 3, 2, 2,
|
||||
2, 3, 2, 2, 2, 3, 2, 3, 2, 3, 2, 3, 2, 2,
|
||||
2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 2, 3, 2, 2,
|
||||
2, 3, 2, 2, 2, 3, 2, 3, 2, 3, 2, 3, 2, 2,
|
||||
2, 3, 2, 2, 2, 3, 2, 3, 2, 3, 2, 3, 2, 2,
|
||||
2, 3, 2, 2, 2, 3, 2, 3, 2, 3, 2, 3, 2, 2,
|
||||
2, 3, 2, 2, 2, 3, 2, 3, 2, 3, 2, 3, 3, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
|
||||
};
|
||||
|
||||
unsigned char win_matrix[14*14]={
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 4, 1, 4,
|
||||
4, 1, 4, 1, 4, 1, 4, 4, 4, 1, 4, 4, 1, 4,
|
||||
4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 1, 4, 1, 4,
|
||||
4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 1, 4,
|
||||
4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 4, 1, 4,
|
||||
4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 4, 1, 4,
|
||||
4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 4, 1, 4,
|
||||
4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 4, 1, 4,
|
||||
4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 4, 1, 4,
|
||||
4, 4, 1, 4, 1, 4, 4, 1, 4, 1, 4, 4, 1, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
};
|
||||
|
||||
void main()
|
||||
{
|
||||
int key, id;
|
||||
|
||||
set_board_size(0); //small board by default
|
||||
new_game();
|
||||
|
||||
loop() switch(WaitEvent())
|
||||
{
|
||||
case evButton:
|
||||
id = GetButtonID();
|
||||
IF (id==1) || (id==4) ExitProcess();
|
||||
IF (id==2) goto _NEW_GAME_MARK;
|
||||
IF (id==3) goto _HELP_MARK;
|
||||
IF (id>=100) {
|
||||
make_turn(id-100);
|
||||
}
|
||||
if (id==10) set_board_size(0);
|
||||
if (id==11) set_board_size(1);
|
||||
break;
|
||||
case evKey:
|
||||
key = GetKeyScancode();
|
||||
IF (key==01) //Escape
|
||||
ExitProcess();
|
||||
IF (key==59) //F1
|
||||
{
|
||||
_HELP_MARK:
|
||||
CreateThread(#help_thread,#help_window_stak);
|
||||
break;
|
||||
}
|
||||
IF (key==60) //F2
|
||||
{
|
||||
_NEW_GAME_MARK:
|
||||
new_game();
|
||||
draw_clicks_num();
|
||||
draw_field();
|
||||
break;
|
||||
}
|
||||
IF (key==16) make_turn(0); //Q
|
||||
IF (key==17) make_turn(1); //W
|
||||
IF (key==18) make_turn(2); //E
|
||||
IF (key==30) make_turn(3); //A
|
||||
IF (key==31) make_turn(4); //S
|
||||
IF (key==32) make_turn(5); //D
|
||||
break;
|
||||
case evReDraw:
|
||||
draw_window();
|
||||
}
|
||||
}
|
||||
|
||||
void set_board_size(char s)
|
||||
{
|
||||
if (board_size != s) {
|
||||
board_size = s;
|
||||
|
||||
BLOCKS_NUM = board_size + 1 * DEFAULT_BLOCK_COUNT;
|
||||
MAX_CLICKS = board_size + 1 * DEFAULT_MAX_CLICKS;
|
||||
|
||||
BLOCK_SIZE = GetScreenHeight() - 70 / BLOCKS_NUM;
|
||||
if (BLOCK_SIZE > MAX_BLOCK_SIZE) BLOCK_SIZE = MAX_BLOCK_SIZE;
|
||||
|
||||
new_game();
|
||||
|
||||
MoveSize(-1, -1, BLOCK_SIZE*BLOCKS_NUM +14+USER_PANEL_WIDTH,
|
||||
BLOCK_SIZE*BLOCKS_NUM +GetSkinHeight()+14);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void make_turn(int turn_id)
|
||||
{
|
||||
IF (color_matrix[0]==turn_id) return; //ignore no-sence click: first item color is equal to a new color
|
||||
IF (!game_is_ended()) {
|
||||
CLICKS++;
|
||||
draw_clicks_num();
|
||||
fill_field(turn_id);
|
||||
if (!game_is_ended()) draw_field();
|
||||
}
|
||||
}
|
||||
|
||||
void draw_window()
|
||||
{
|
||||
int i;
|
||||
#define BUTTON_SIZE 28
|
||||
|
||||
sc.get();
|
||||
|
||||
DefineAndDrawWindow(300,176, BLOCK_SIZE*BLOCKS_NUM +14+USER_PANEL_WIDTH,
|
||||
BLOCK_SIZE*BLOCKS_NUM +GetSkinHeight()+14, 0x74,0,"Flood-it!");
|
||||
|
||||
// Fix rolled-up bug
|
||||
GetProcessInfo(#Form, SelfInfo);
|
||||
IF (Form.status_window==4) return;
|
||||
|
||||
// Fill background to reduce window redraw
|
||||
for (i=0;i<=4;i++)
|
||||
{
|
||||
ESI = sc.work;
|
||||
IF (i==4) ESI = sc.work_graph;
|
||||
DrawRegion(USER_PANEL_WIDTH+i-5,i, BLOCK_SIZE*BLOCKS_NUM +9-i-i, ESI);
|
||||
}
|
||||
DrawBar(0,0, USER_PANEL_WIDTH-5, BLOCK_SIZE*BLOCKS_NUM+10, sc.work);
|
||||
|
||||
// Main buttons to fill the board
|
||||
#define FILL_BUTTON_SIZE BUTTON_SIZE+8
|
||||
for (i=0;i<6;i++)
|
||||
DefineButton(i%3*FILL_BUTTON_SIZE+17,i/3*FILL_BUTTON_SIZE+15,FILL_BUTTON_SIZE,FILL_BUTTON_SIZE, i+100,FIELD_COLORS[i]);
|
||||
|
||||
// Menu buttons
|
||||
for (i=0;i<3;i++)
|
||||
{
|
||||
DefineButton(17,i*31+140, 13*8+6, 25, i+2,sc.work_button);
|
||||
WriteText(17+4,i*31+146,0x90,sc.work_button_text,BUTTON_CAPTIONS[i],0);
|
||||
}
|
||||
|
||||
// Board size
|
||||
WriteText(17,BLOCKS_NUM*BLOCK_SIZE-25+7,0x90,sc.work_text,#LEVELS_TEXT,0);
|
||||
for (i=0;i<2;i++)
|
||||
{
|
||||
IF (board_size == i) {
|
||||
ESI=sc.work_button;
|
||||
EDI=sc.work_button_text;
|
||||
} ELSE {
|
||||
ESI = sc.work;
|
||||
EDI = sc.work_text;
|
||||
}
|
||||
|
||||
DefineButton(i*32+69,BLOCKS_NUM*BLOCK_SIZE-24, 26,25, i+10,ESI);
|
||||
WriteText(i*32+69+9,BLOCKS_NUM*BLOCK_SIZE-24+6,0x90,EDI,#BOARD_SIZES+i+i,0);
|
||||
$add ebx, 1<<16 //bold
|
||||
$int 0x40
|
||||
}
|
||||
|
||||
draw_clicks_num();
|
||||
draw_field();
|
||||
}
|
||||
|
||||
void randomly_fill_the_board()
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<BLOCKS_NUM*BLOCKS_NUM;i++) {
|
||||
color_matrix[i] = random(6);
|
||||
}
|
||||
}
|
||||
|
||||
void new_game()
|
||||
{
|
||||
CLICKS = 0;
|
||||
game_end = false;
|
||||
randomly_fill_the_board();
|
||||
}
|
||||
|
||||
void fill_field(int new_color_id)
|
||||
{
|
||||
int i, j,
|
||||
old_color_id=color_matrix[0],
|
||||
restart;
|
||||
int cur_cell;
|
||||
#define MARKED 6
|
||||
|
||||
color_matrix[0]=MARKED;
|
||||
|
||||
_RESTART_MARK:
|
||||
|
||||
restart=0;
|
||||
|
||||
for (i=0;i<BLOCKS_NUM;i++)
|
||||
for (j=0;j<BLOCKS_NUM;j++)
|
||||
{
|
||||
cur_cell = i*BLOCKS_NUM+j;
|
||||
IF (color_matrix[cur_cell]<>old_color_id) continue; //if not a needed color then continue
|
||||
IF (color_matrix[cur_cell]==MARKED) continue; //if already marked then continue
|
||||
|
||||
IF (j>0) && (color_matrix[i*BLOCKS_NUM+j-1]==MARKED) color_matrix[cur_cell]=MARKED; //left
|
||||
IF (i>0) && (color_matrix[i-1*BLOCKS_NUM+j]==MARKED) color_matrix[cur_cell]=MARKED; //top
|
||||
IF (j<BLOCKS_NUM-1) && (color_matrix[i*BLOCKS_NUM+j+1]==MARKED) color_matrix[cur_cell]=MARKED; //right
|
||||
IF (i<BLOCKS_NUM-1) && (color_matrix[i+1*BLOCKS_NUM+j]==MARKED) color_matrix[cur_cell]=MARKED; //bottom
|
||||
|
||||
IF (color_matrix[cur_cell]==MARKED) restart=1;
|
||||
}
|
||||
IF (restart) goto _RESTART_MARK;
|
||||
|
||||
for (i=0;i<BLOCKS_NUM*BLOCKS_NUM;i++)
|
||||
IF (color_matrix[i]==MARKED) color_matrix[i]=new_color_id;
|
||||
}
|
||||
|
||||
void draw_win_or_loose_animation(dword matrix)
|
||||
{
|
||||
int i, j, ii, jj;
|
||||
for (i=0;i<14;i++) {
|
||||
for (j=0;j<14;j++)
|
||||
{
|
||||
ii = board_size * 2 + i;
|
||||
jj = board_size * 2 + j;
|
||||
color_matrix[ii*BLOCKS_NUM+jj]=
|
||||
color_matrix[ii+1*BLOCKS_NUM+jj]=
|
||||
color_matrix[ii*BLOCKS_NUM+jj+1]=
|
||||
color_matrix[ii+1*BLOCKS_NUM+jj+1]=ESBYTE[i*14+j+matrix];
|
||||
draw_field();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int field_is_solid()
|
||||
{
|
||||
int i;
|
||||
if (game_end) return 1;
|
||||
game_end = 1;
|
||||
for (i=0;i<BLOCKS_NUM*BLOCKS_NUM;i++) {
|
||||
IF (color_matrix[i]<>color_matrix[0]) game_end = 0;
|
||||
}
|
||||
return game_end;
|
||||
}
|
||||
|
||||
int game_is_ended()
|
||||
{
|
||||
int i;
|
||||
|
||||
if (game_end) return 1;
|
||||
|
||||
if (CLICKS>=MAX_CLICKS) //check for game end via max_clicks
|
||||
{
|
||||
IF (CLICKS==MAX_CLICKS) //probably user won on the last step
|
||||
{
|
||||
if (field_is_solid()) goto _WIN_MARK;
|
||||
}
|
||||
draw_win_or_loose_animation(#loss_matrix);
|
||||
return 1;
|
||||
} else {
|
||||
if (!field_is_solid()) return 0;
|
||||
|
||||
//field is solid and CLICKS<MAX_CLICKS -> win
|
||||
|
||||
_WIN_MARK:
|
||||
|
||||
for (i=0;i<25;i++)
|
||||
{
|
||||
randomly_fill_the_board();
|
||||
draw_field();
|
||||
Pause(7);
|
||||
}
|
||||
|
||||
draw_win_or_loose_animation(#win_matrix);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void draw_clicks_num()
|
||||
{
|
||||
#define TEXT_X 19
|
||||
#define TEXT_Y 100
|
||||
|
||||
DrawBar(TEXT_X, TEXT_Y, USER_PANEL_WIDTH-TEXT_X-5,16, sc.work);
|
||||
|
||||
WriteText(TEXT_X,TEXT_Y,0x90,sc.work_text,#CLICKS_TEXT,0);
|
||||
|
||||
IF (CLICKS<10) EBX=9*8+TEXT_X;
|
||||
else EBX=8*8+TEXT_X;
|
||||
|
||||
WriteText(EBX,TEXT_Y,0x90,sc.work_text,itoa_nosign(CLICKS),0);
|
||||
|
||||
WriteText(11*8+TEXT_X,TEXT_Y,0x90,sc.work_text,itoa_nosign(MAX_CLICKS),0);
|
||||
}
|
||||
|
||||
|
||||
void draw_field()
|
||||
{
|
||||
int i, j;
|
||||
int color_id;
|
||||
|
||||
for (i=0;i<BLOCKS_NUM;i++)
|
||||
for (j=0;j<BLOCKS_NUM;j++)
|
||||
{
|
||||
color_id = color_matrix[i*BLOCKS_NUM+j];
|
||||
DrawBar(j*BLOCK_SIZE+USER_PANEL_WIDTH, i*BLOCK_SIZE+5, BLOCK_SIZE,BLOCK_SIZE, FIELD_COLORS[color_id]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void help_thread()
|
||||
{
|
||||
int i;
|
||||
|
||||
loop() switch (WaitEvent())
|
||||
{
|
||||
case evButton:
|
||||
ExitProcess();
|
||||
case evKey:
|
||||
IF (GetKeyScancode()==001) ExitProcess(); //Esc
|
||||
break;
|
||||
case evReDraw:
|
||||
//for (i=0; HELP_TEXT[i]<>0; i++;) {}; //calculate line numbers, predefined i=12 used to reduce size
|
||||
DefineAndDrawWindow(400,200,612,12*19+25+GetSkinHeight(),0x34,sc.work,#HELP_WINDOW_CAPTION);
|
||||
WriteText(6,12,0x90,sc.work_text,HELP_TEXT[0],0); //for a bold text
|
||||
for (i=0; HELP_TEXT[i]<>0; i++;) WriteText(7,i*19+12,0x90,sc.work_text,HELP_TEXT[i],0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
// Flood-it! - Strategy game: Flood the board with one color, within a step limit.
|
||||
// Copyright (C) 2011-2025 Leency
|
||||
|
||||
#include "lib\kolibri.h"
|
||||
#include "lib\random.h"
|
||||
|
||||
system_colors sc;
|
||||
proc_info Form;
|
||||
dword help_window_stak[100];
|
||||
|
||||
#define DEFAULT_BLOCK_COUNT 14
|
||||
#define DEFAULT_MAX_CLICKS 25
|
||||
#define MAX_BLOCK_SIZE 28
|
||||
char board_size = -1;
|
||||
int BLOCK_SIZE; //cell size
|
||||
int BLOCKS_NUM; //number of cells by X and Y
|
||||
int MAX_CLICKS; //max clicks for win
|
||||
int CLICKS; //how many clicks user already did
|
||||
int game_end;
|
||||
|
||||
#define USER_PANEL_WIDTH 144
|
||||
|
||||
//six colors are used in a game for a cells
|
||||
//and seventh color is used to mark a cell during filling process
|
||||
dword FIELD_COLORS[] = {0xf18db6, 0x605ca8, 0xfddc80, 0xdc4a20, 0x46b1e2, 0x7e9d1e, 0x232323};
|
||||
char BOARD_SIZES[] = "S\0L";
|
||||
|
||||
|
||||
#ifdef LANG_RUS
|
||||
char *BUTTON_CAPTIONS[]={ " ‡ ®¢® [F2]", " <20>®¬®éì [F1]", " ‚ë室 [Esc]", 0};
|
||||
char CLICKS_TEXT[]=" Š«¨ª¨: /";
|
||||
char LEVELS_TEXT[]=" <20>®«¥:";
|
||||
|
||||
char HELP_WINDOW_CAPTION[]="<EFBFBD>®¬®éì";
|
||||
char *HELP_TEXT[]={ "Š ª ¨£à âì ¢® Flood-it?",
|
||||
"",
|
||||
"‡ ¯®«¨â¥ ¯®«¥ ®¤¨¬ 梥⮬ § ®£à ¨ç¥®¥ ç¨á«® 室®¢.",
|
||||
"ˆ£à ç¨ ¥âáï á ¢¥à奩 «¥¢®© ª«¥âª¨. ‚ë¡¥à¨â¥ 梥â, ¦ ¢ ®¤¨ ¨§",
|
||||
"ª¢ ¤à ⨪®¢ á«¥¢ , ¨ ª«¥âª¨ ®ªà áïâáï í⨬ 梥⮬ - â ª ¢ë ¯à¨á®¥¤¨¨â¥",
|
||||
"á®á¥¤¨¥ ª«¥âª¨ ⮩ ¦¥ ®ªà ᪨. ‡ å¢ â¨âì ¯®«¥ 㦮 § ¬¨¨¬ «ì®¥",
|
||||
"ç¨á«® 室®¢. <20>®è £®¢ ï áâà ⥣¨ï á ¨â¥à¥áë¬ ¯à¨æ¨¯®¬ - ¨§¬¥¨áì,",
|
||||
"çâ®¡ë ¯®¡¥¤¨âì!",
|
||||
"",
|
||||
"ˆ£à âì â ª¦¥ ¬®¦® ª« ¢¨è ¬¨:",
|
||||
"[Q] [W] [E]",
|
||||
"[A] [S] [D]",
|
||||
0};
|
||||
#elif LANG_EST
|
||||
char *BUTTON_CAPTIONS[]={ "Uus mäng [F2]", "Abi [F1]", "Välju [Esc]", 0};
|
||||
char CLICKS_TEXT[]="Klikki: /";
|
||||
char LEVELS_TEXT[]="Väli:";
|
||||
|
||||
char HELP_WINDOW_CAPTION[]="Help";
|
||||
char *HELP_TEXT[]={ "Kuidas mängida mängu Flood-it?",
|
||||
"",
|
||||
"Ujuta kogu mänguväli üle ühe värviga lubatud käikude arvuga.",
|
||||
"Mängu alustad ülemisest vasakust nurgast ja edened valides ühe värvi",
|
||||
"vajutades nuppudele vasakul. Kui sa muudad värvi pragusel alal,",
|
||||
"siis iga kokkupuutuv sama värv muutub samaks. Nii saad ujutada",
|
||||
"teised alad mänguväljal üle. Valida saad 2 mänguvälja suuruse",
|
||||
"vahel. Proovi väli üle ujutada etteandtud käikude arvuga!",
|
||||
"",
|
||||
"Mängida saab ka klaviatuuriga:",
|
||||
"[Q] [W] [E]",
|
||||
"[A] [S] [D]",
|
||||
0};
|
||||
#else
|
||||
char *BUTTON_CAPTIONS[]={ "Restart [F2]", " Help [F1]", " Exit [Esc]", 0};
|
||||
char CLICKS_TEXT[]="Clicks: /";
|
||||
char LEVELS_TEXT[]="Board:";
|
||||
|
||||
char HELP_WINDOW_CAPTION[]="Help";
|
||||
char *HELP_TEXT[]={ "How to play Flood-it?",
|
||||
"",
|
||||
"Flood the whole board with one color within the allowed steps.",
|
||||
"You start from the top left corner and progress by selecting one",
|
||||
"of the colored buttons on the left. When you change your current area",
|
||||
"color, every adjacent square with the same color also changes, that",
|
||||
"way you can flood other areas of the board. Select from 3 sizes of",
|
||||
"the board and try to flood-it in the least amount of steps!",
|
||||
"",
|
||||
"You can also play with keyboard:",
|
||||
"[Q] [W] [E]",
|
||||
"[A] [S] [D]",
|
||||
0};
|
||||
#endif
|
||||
|
||||
|
||||
unsigned char color_matrix[28*28]; //our field
|
||||
|
||||
unsigned char loss_matrix[14*14]={
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 2, 3, 2, 2,
|
||||
2, 3, 2, 2, 2, 3, 2, 3, 2, 2, 2, 3, 2, 2,
|
||||
2, 3, 2, 2, 2, 3, 2, 3, 2, 3, 2, 3, 2, 2,
|
||||
2, 3, 2, 2, 2, 3, 2, 3, 2, 3, 2, 3, 2, 2,
|
||||
2, 3, 2, 2, 2, 3, 2, 3, 2, 3, 2, 3, 2, 2,
|
||||
2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 2, 3, 2, 2,
|
||||
2, 3, 2, 2, 2, 3, 2, 3, 2, 3, 2, 3, 2, 2,
|
||||
2, 3, 2, 2, 2, 3, 2, 3, 2, 3, 2, 3, 2, 2,
|
||||
2, 3, 2, 2, 2, 3, 2, 3, 2, 3, 2, 3, 2, 2,
|
||||
2, 3, 2, 2, 2, 3, 2, 3, 2, 3, 2, 3, 3, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
|
||||
};
|
||||
|
||||
unsigned char win_matrix[14*14]={
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 4, 1, 4,
|
||||
4, 1, 4, 1, 4, 1, 4, 4, 4, 1, 4, 4, 1, 4,
|
||||
4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 1, 4, 1, 4,
|
||||
4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 1, 4,
|
||||
4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 4, 1, 4,
|
||||
4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 4, 1, 4,
|
||||
4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 4, 1, 4,
|
||||
4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 4, 1, 4,
|
||||
4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 4, 1, 4,
|
||||
4, 4, 1, 4, 1, 4, 4, 1, 4, 1, 4, 4, 1, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
};
|
||||
|
||||
void main()
|
||||
{
|
||||
int key, id;
|
||||
|
||||
set_board_size(0); //small board by default
|
||||
new_game();
|
||||
|
||||
loop() switch(WaitEvent())
|
||||
{
|
||||
case evButton:
|
||||
id = GetButtonID();
|
||||
IF (id==1) || (id==4) ExitProcess();
|
||||
IF (id==2) goto _NEW_GAME_MARK;
|
||||
IF (id==3) goto _HELP_MARK;
|
||||
IF (id>=100) {
|
||||
make_turn(id-100);
|
||||
}
|
||||
if (id==10) set_board_size(0);
|
||||
if (id==11) set_board_size(1);
|
||||
break;
|
||||
case evKey:
|
||||
key = GetKeyScancode();
|
||||
IF (key==01) //Escape
|
||||
ExitProcess();
|
||||
IF (key==59) //F1
|
||||
{
|
||||
_HELP_MARK:
|
||||
CreateThread(#help_thread,#help_window_stak);
|
||||
break;
|
||||
}
|
||||
IF (key==60) //F2
|
||||
{
|
||||
_NEW_GAME_MARK:
|
||||
new_game();
|
||||
draw_clicks_num();
|
||||
draw_field();
|
||||
break;
|
||||
}
|
||||
IF (key==16) make_turn(0); //Q
|
||||
IF (key==17) make_turn(1); //W
|
||||
IF (key==18) make_turn(2); //E
|
||||
IF (key==30) make_turn(3); //A
|
||||
IF (key==31) make_turn(4); //S
|
||||
IF (key==32) make_turn(5); //D
|
||||
break;
|
||||
case evReDraw:
|
||||
draw_window();
|
||||
}
|
||||
}
|
||||
|
||||
void set_board_size(char s)
|
||||
{
|
||||
if (board_size != s) {
|
||||
board_size = s;
|
||||
|
||||
BLOCKS_NUM = board_size + 1 * DEFAULT_BLOCK_COUNT;
|
||||
MAX_CLICKS = board_size + 1 * DEFAULT_MAX_CLICKS;
|
||||
|
||||
BLOCK_SIZE = GetScreenHeight() - 70 / BLOCKS_NUM;
|
||||
if (BLOCK_SIZE > MAX_BLOCK_SIZE) BLOCK_SIZE = MAX_BLOCK_SIZE;
|
||||
|
||||
new_game();
|
||||
|
||||
MoveSize(-1, -1, BLOCK_SIZE*BLOCKS_NUM +14+USER_PANEL_WIDTH,
|
||||
BLOCK_SIZE*BLOCKS_NUM +GetSkinHeight()+14);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void make_turn(int turn_id)
|
||||
{
|
||||
IF (color_matrix[0]==turn_id) return; //ignore no-sence click: first item color is equal to a new color
|
||||
IF (!game_is_ended()) {
|
||||
CLICKS++;
|
||||
draw_clicks_num();
|
||||
fill_field(turn_id);
|
||||
if (!game_is_ended()) draw_field();
|
||||
}
|
||||
}
|
||||
|
||||
void draw_window()
|
||||
{
|
||||
int i;
|
||||
#define BUTTON_SIZE 28
|
||||
|
||||
sc.get();
|
||||
|
||||
DefineAndDrawWindow(300,176, BLOCK_SIZE*BLOCKS_NUM +14+USER_PANEL_WIDTH,
|
||||
BLOCK_SIZE*BLOCKS_NUM +GetSkinHeight()+14, 0x74,0,"Flood-it!");
|
||||
|
||||
// Fix rolled-up bug
|
||||
GetProcessInfo(#Form, SelfInfo);
|
||||
IF (Form.status_window==4) return;
|
||||
|
||||
// Fill background to reduce window redraw
|
||||
for (i=0;i<=4;i++)
|
||||
{
|
||||
ESI = sc.work;
|
||||
IF (i==4) ESI = sc.work_graph;
|
||||
DrawRegion(USER_PANEL_WIDTH+i-5,i, BLOCK_SIZE*BLOCKS_NUM +9-i-i, ESI);
|
||||
}
|
||||
DrawBar(0,0, USER_PANEL_WIDTH-5, BLOCK_SIZE*BLOCKS_NUM+10, sc.work);
|
||||
|
||||
// Main buttons to fill the board
|
||||
#define FILL_BUTTON_SIZE BUTTON_SIZE+8
|
||||
for (i=0;i<6;i++)
|
||||
DefineButton(i%3*FILL_BUTTON_SIZE+17,i/3*FILL_BUTTON_SIZE+15,FILL_BUTTON_SIZE,FILL_BUTTON_SIZE, i+100,FIELD_COLORS[i]);
|
||||
|
||||
// Menu buttons
|
||||
for (i=0;i<3;i++)
|
||||
{
|
||||
DefineButton(17,i*31+140, 13*8+6, 25, i+2,sc.work_button);
|
||||
WriteText(17+4,i*31+146,0x90,sc.work_button_text,BUTTON_CAPTIONS[i],0);
|
||||
}
|
||||
|
||||
// Board size
|
||||
WriteText(17,BLOCKS_NUM*BLOCK_SIZE-25+7,0x90,sc.work_text,#LEVELS_TEXT,0);
|
||||
for (i=0;i<2;i++)
|
||||
{
|
||||
IF (board_size == i) {
|
||||
ESI=sc.work_button;
|
||||
EDI=sc.work_button_text;
|
||||
} ELSE {
|
||||
ESI = sc.work;
|
||||
EDI = sc.work_text;
|
||||
}
|
||||
|
||||
DefineButton(i*32+69,BLOCKS_NUM*BLOCK_SIZE-24, 26,25, i+10,ESI);
|
||||
WriteText(i*32+69+9,BLOCKS_NUM*BLOCK_SIZE-24+6,0x90,EDI,#BOARD_SIZES+i+i,0);
|
||||
$add ebx, 1<<16 //bold
|
||||
$int 0x40
|
||||
}
|
||||
|
||||
draw_clicks_num();
|
||||
draw_field();
|
||||
}
|
||||
|
||||
void randomly_fill_the_board()
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<BLOCKS_NUM*BLOCKS_NUM;i++) {
|
||||
color_matrix[i] = random(6);
|
||||
}
|
||||
}
|
||||
|
||||
void new_game()
|
||||
{
|
||||
CLICKS = 0;
|
||||
game_end = false;
|
||||
randomly_fill_the_board();
|
||||
}
|
||||
|
||||
void fill_field(int new_color_id)
|
||||
{
|
||||
int i, j,
|
||||
old_color_id=color_matrix[0],
|
||||
restart;
|
||||
int cur_cell;
|
||||
#define MARKED 6
|
||||
|
||||
color_matrix[0]=MARKED;
|
||||
|
||||
_RESTART_MARK:
|
||||
|
||||
restart=0;
|
||||
|
||||
for (i=0;i<BLOCKS_NUM;i++)
|
||||
for (j=0;j<BLOCKS_NUM;j++)
|
||||
{
|
||||
cur_cell = i*BLOCKS_NUM+j;
|
||||
IF (color_matrix[cur_cell]<>old_color_id) continue; //if not a needed color then continue
|
||||
IF (color_matrix[cur_cell]==MARKED) continue; //if already marked then continue
|
||||
|
||||
IF (j>0) && (color_matrix[i*BLOCKS_NUM+j-1]==MARKED) color_matrix[cur_cell]=MARKED; //left
|
||||
IF (i>0) && (color_matrix[i-1*BLOCKS_NUM+j]==MARKED) color_matrix[cur_cell]=MARKED; //top
|
||||
IF (j<BLOCKS_NUM-1) && (color_matrix[i*BLOCKS_NUM+j+1]==MARKED) color_matrix[cur_cell]=MARKED; //right
|
||||
IF (i<BLOCKS_NUM-1) && (color_matrix[i+1*BLOCKS_NUM+j]==MARKED) color_matrix[cur_cell]=MARKED; //bottom
|
||||
|
||||
IF (color_matrix[cur_cell]==MARKED) restart=1;
|
||||
}
|
||||
IF (restart) goto _RESTART_MARK;
|
||||
|
||||
for (i=0;i<BLOCKS_NUM*BLOCKS_NUM;i++)
|
||||
IF (color_matrix[i]==MARKED) color_matrix[i]=new_color_id;
|
||||
}
|
||||
|
||||
void draw_win_or_loose_animation(dword matrix)
|
||||
{
|
||||
int i, j, ii, jj;
|
||||
for (i=0;i<14;i++) {
|
||||
for (j=0;j<14;j++)
|
||||
{
|
||||
ii = board_size * 2 + i;
|
||||
jj = board_size * 2 + j;
|
||||
color_matrix[ii*BLOCKS_NUM+jj]=
|
||||
color_matrix[ii+1*BLOCKS_NUM+jj]=
|
||||
color_matrix[ii*BLOCKS_NUM+jj+1]=
|
||||
color_matrix[ii+1*BLOCKS_NUM+jj+1]=ESBYTE[i*14+j+matrix];
|
||||
draw_field();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int field_is_solid()
|
||||
{
|
||||
int i;
|
||||
if (game_end) return 1;
|
||||
game_end = 1;
|
||||
for (i=0;i<BLOCKS_NUM*BLOCKS_NUM;i++) {
|
||||
IF (color_matrix[i]<>color_matrix[0]) game_end = 0;
|
||||
}
|
||||
return game_end;
|
||||
}
|
||||
|
||||
int game_is_ended()
|
||||
{
|
||||
int i;
|
||||
|
||||
if (game_end) return 1;
|
||||
|
||||
if (CLICKS>=MAX_CLICKS) //check for game end via max_clicks
|
||||
{
|
||||
IF (CLICKS==MAX_CLICKS) //probably user won on the last step
|
||||
{
|
||||
if (field_is_solid()) goto _WIN_MARK;
|
||||
}
|
||||
draw_win_or_loose_animation(#loss_matrix);
|
||||
return 1;
|
||||
} else {
|
||||
if (!field_is_solid()) return 0;
|
||||
|
||||
//field is solid and CLICKS<MAX_CLICKS -> win
|
||||
|
||||
_WIN_MARK:
|
||||
|
||||
for (i=0;i<25;i++)
|
||||
{
|
||||
randomly_fill_the_board();
|
||||
draw_field();
|
||||
Pause(7);
|
||||
}
|
||||
|
||||
draw_win_or_loose_animation(#win_matrix);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void draw_clicks_num()
|
||||
{
|
||||
#define TEXT_X 19
|
||||
#define TEXT_Y 100
|
||||
|
||||
DrawBar(TEXT_X, TEXT_Y, USER_PANEL_WIDTH-TEXT_X-5,16, sc.work);
|
||||
|
||||
WriteText(TEXT_X,TEXT_Y,0x90,sc.work_text,#CLICKS_TEXT,0);
|
||||
|
||||
IF (CLICKS<10) EBX=9*8+TEXT_X;
|
||||
else EBX=8*8+TEXT_X;
|
||||
|
||||
WriteText(EBX,TEXT_Y,0x90,sc.work_text,itoa_nosign(CLICKS),0);
|
||||
|
||||
WriteText(11*8+TEXT_X,TEXT_Y,0x90,sc.work_text,itoa_nosign(MAX_CLICKS),0);
|
||||
}
|
||||
|
||||
|
||||
void draw_field()
|
||||
{
|
||||
int i, j;
|
||||
int color_id;
|
||||
|
||||
for (i=0;i<BLOCKS_NUM;i++)
|
||||
for (j=0;j<BLOCKS_NUM;j++)
|
||||
{
|
||||
color_id = color_matrix[i*BLOCKS_NUM+j];
|
||||
DrawBar(j*BLOCK_SIZE+USER_PANEL_WIDTH, i*BLOCK_SIZE+5, BLOCK_SIZE,BLOCK_SIZE, FIELD_COLORS[color_id]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void help_thread()
|
||||
{
|
||||
int i;
|
||||
|
||||
loop() switch (WaitEvent())
|
||||
{
|
||||
case evButton:
|
||||
ExitProcess();
|
||||
case evKey:
|
||||
IF (GetKeyScancode()==001) ExitProcess(); //Esc
|
||||
break;
|
||||
case evReDraw:
|
||||
//for (i=0; HELP_TEXT[i]<>0; i++;) {}; //calculate line numbers, predefined i=12 used to reduce size
|
||||
DefineAndDrawWindow(400,200,612,12*19+25+GetSkinHeight(),0x34,sc.work,#HELP_WINDOW_CAPTION);
|
||||
WriteText(6,12,0x90,sc.work_text,HELP_TEXT[0],0); //for a bold text
|
||||
for (i=0; HELP_TEXT[i]<>0; i++;) WriteText(7,i*19+12,0x90,sc.work_text,HELP_TEXT[i],0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
stop:
|
Reference in New Issue
Block a user