X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame.c;h=6b920a51ca2d40b9ca2f097e6d3fa865ff0f2c81;hb=4abc7d07404767933918e25220cab6c2eae683e5;hp=a52780cbc7e63762ac4fc04c86c170a9984224cf;hpb=90e16791f1e0e84a76cbe631629749f43f2ad725;p=rocksndiamonds.git diff --git a/src/game.c b/src/game.c index a52780cb..6b920a51 100644 --- a/src/game.c +++ b/src/game.c @@ -134,6 +134,458 @@ #define DX_TIME (DX + XX_TIME) #define DY_TIME (DY + YY_TIME) +#if 0 +/* game panel display and control definitions */ + +#define GAME_CONTROL_LEVEL 0 +#define GAME_CONTROL_GEMS 1 +#define GAME_CONTROL_INVENTORY 2 +#define GAME_CONTROL_KEYS 3 +#define GAME_CONTROL_SCORE 4 +#define GAME_CONTROL_TIME 5 +#define GAME_CONTROL_TIME_HH 6 +#define GAME_CONTROL_TIME_MM 7 +#define GAME_CONTROL_TIME_SS 8 +#define GAME_CONTROL_DROP_NEXT_1 9 +#define GAME_CONTROL_DROP_NEXT_2 10 +#define GAME_CONTROL_DROP_NEXT_3 11 +#define GAME_CONTROL_DROP_NEXT_4 12 +#define GAME_CONTROL_DROP_NEXT_5 13 +#define GAME_CONTROL_DROP_NEXT_6 14 +#define GAME_CONTROL_DROP_NEXT_7 15 +#define GAME_CONTROL_DROP_NEXT_8 16 +#define GAME_CONTROL_EMC_KEYS 17 +#define GAME_CONTROL_KEY_1 18 +#define GAME_CONTROL_KEY_2 19 +#define GAME_CONTROL_KEY_3 20 +#define GAME_CONTROL_KEY_4 21 +#define GAME_CONTROL_KEY_5 22 +#define GAME_CONTROL_KEY_6 23 +#define GAME_CONTROL_KEY_7 24 +#define GAME_CONTROL_KEY_8 25 +#define GAME_CONTROL_KEY_WHITE 26 +#define GAME_CONTROL_KEY_WHITE_COUNT 27 +#define GAME_CONTROL_SHIELD_NORMAL 28 +#define GAME_CONTROL_SHIELD_NORMAL_TIME 29 +#define GAME_CONTROL_SHIELD_DEADLY 30 +#define GAME_CONTROL_SHIELD_DEADLY_TIME 31 +#define GAME_CONTROL_EXIT 32 +#define GAME_CONTROL_EM_EXIT 33 +#define GAME_CONTROL_SP_EXIT 34 +#define GAME_CONTROL_STEEL_EXIT 35 +#define GAME_CONTROL_EM_STEEL_EXIT 36 +#define GAME_CONTROL_EMC_MAGIC_BALL 37 +#define GAME_CONTROL_EMC_MAGIC_BALL_TIME 38 +#define GAME_CONTROL_LIGHT_SWITCH 39 +#define GAME_CONTROL_LIGHT_SWITCH_TIME 40 +#define GAME_CONTROL_TIMEGATE_SWITCH 41 +#define GAME_CONTROL_TIMEGATE_SWITCH_TIME 42 +#define GAME_CONTROL_SWITCHGATE_SWITCH 43 +#define GAME_CONTROL_EMC_LENSES 44 +#define GAME_CONTROL_EMC_LENSES_TIME 45 +#define GAME_CONTROL_EMC_MAGNIFIER 46 +#define GAME_CONTROL_EMC_MAGNIFIER_TIME 47 +#define GAME_CONTROL_BALLOON_SWITCH 48 +#define GAME_CONTROL_DYNABOMB_NUMBER 49 +#define GAME_CONTROL_DYNABOMB_SIZE 50 +#define GAME_CONTROL_DYNABOMB_POWER 51 +#define GAME_CONTROL_PENGUINS 52 +#define GAME_CONTROL_SOKOBAN_OBJECTS 53 +#define GAME_CONTROL_SOKOBAN_FIELDS 54 +#define GAME_CONTROL_ROBOT_WHEEL 55 +#define GAME_CONTROL_CONVEYOR_BELT_1 56 +#define GAME_CONTROL_CONVEYOR_BELT_1_SWITCH 57 +#define GAME_CONTROL_CONVEYOR_BELT_2 58 +#define GAME_CONTROL_CONVEYOR_BELT_2_SWITCH 59 +#define GAME_CONTROL_CONVEYOR_BELT_3 60 +#define GAME_CONTROL_CONVEYOR_BELT_3_SWITCH 61 +#define GAME_CONTROL_CONVEYOR_BELT_4 62 +#define GAME_CONTROL_CONVEYOR_BELT_4_SWITCH 63 +#define GAME_CONTROL_MAGIC_WALL 64 +#define GAME_CONTROL_MAGIC_WALL_TIME 65 +#define GAME_CONTROL_BD_MAGIC_WALL 66 +#define GAME_CONTROL_DC_MAGIC_WALL 67 +#define GAME_CONTROL_PLAYER_NAME 68 +#define GAME_CONTROL_LEVEL_NAME 69 +#define GAME_CONTROL_LEVEL_AUTHOR 70 + +struct GameControlInfo +{ + int nr; + + struct TextPosInfo *pos_text; + int type; + void *ptr; +}; + +static struct GameControlInfo game_controls[] = +{ + { + GAME_CONTROL_LEVEL, + &game.panel.level, + TYPE_INTEGER, + }, + { + GAME_CONTROL_GEMS, + &game.panel.gems, + TYPE_INTEGER, + }, + { + GAME_CONTROL_INVENTORY, + &game.panel.inventory, + TYPE_INTEGER, + }, + { + GAME_CONTROL_KEYS, + &game.panel.keys, + TYPE_INTEGER, + }, + { + GAME_CONTROL_SCORE, + &game.panel.score, + TYPE_INTEGER, + }, + { + GAME_CONTROL_TIME, + &game.panel.time, + TYPE_INTEGER, + }, + { + GAME_CONTROL_TIME_HH, + &game.panel.time_hh, + TYPE_INTEGER, + }, + { + GAME_CONTROL_TIME_MM, + &game.panel.time_mm, + TYPE_INTEGER, + }, + { + GAME_CONTROL_TIME_SS, + &game.panel.time_ss, + TYPE_INTEGER, + }, + { + GAME_CONTROL_DROP_NEXT_1, + &game.panel.drop_next_1, + TYPE_INTEGER, + }, + { + GAME_CONTROL_DROP_NEXT_2, + &game.panel.drop_next_2, + TYPE_INTEGER, + }, + { + GAME_CONTROL_DROP_NEXT_3, + &game.panel.drop_next_3, + TYPE_INTEGER, + }, + { + GAME_CONTROL_DROP_NEXT_4, + &game.panel.drop_next_4, + TYPE_INTEGER, + }, + { + GAME_CONTROL_DROP_NEXT_5, + &game.panel.drop_next_5, + TYPE_INTEGER, + }, + { + GAME_CONTROL_DROP_NEXT_6, + &game.panel.drop_next_6, + TYPE_INTEGER, + }, + { + GAME_CONTROL_DROP_NEXT_7, + &game.panel.drop_next_7, + TYPE_INTEGER, + }, + { + GAME_CONTROL_DROP_NEXT_8, + &game.panel.drop_next_8, + TYPE_INTEGER, + }, + { + GAME_CONTROL_EMC_KEYS, + &game.panel.emc_keys, + TYPE_INTEGER, + }, + { + GAME_CONTROL_KEY_1, + &game.panel.key_1, + TYPE_INTEGER, + }, + { + GAME_CONTROL_KEY_2, + &game.panel.key_2, + TYPE_INTEGER, + }, + { + GAME_CONTROL_KEY_3, + &game.panel.key_3, + TYPE_INTEGER, + }, + { + GAME_CONTROL_KEY_4, + &game.panel.key_4, + TYPE_INTEGER, + }, + { + GAME_CONTROL_KEY_5, + &game.panel.key_5, + TYPE_INTEGER, + }, + { + GAME_CONTROL_KEY_6, + &game.panel.key_6, + TYPE_INTEGER, + }, + { + GAME_CONTROL_KEY_7, + &game.panel.key_7, + TYPE_INTEGER, + }, + { + GAME_CONTROL_KEY_8, + &game.panel.key_8, + TYPE_INTEGER, + }, + { + GAME_CONTROL_KEY_WHITE, + &game.panel.key_white, + TYPE_INTEGER, + }, + { + GAME_CONTROL_KEY_WHITE_COUNT, + &game.panel.key_white_count, + TYPE_INTEGER, + }, + { + GAME_CONTROL_SHIELD_NORMAL, + &game.panel.shield_normal, + TYPE_INTEGER, + }, + { + GAME_CONTROL_SHIELD_NORMAL_TIME, + &game.panel.shield_normal_time, + TYPE_INTEGER, + }, + { + GAME_CONTROL_SHIELD_DEADLY, + &game.panel.shield_deadly, + TYPE_INTEGER, + }, + { + GAME_CONTROL_SHIELD_DEADLY_TIME, + &game.panel.shield_deadly_time, + TYPE_INTEGER, + }, + { + GAME_CONTROL_EXIT, + &game.panel.exit, + TYPE_INTEGER, + }, + { + GAME_CONTROL_EM_EXIT, + &game.panel.em_exit, + TYPE_INTEGER, + }, + { + GAME_CONTROL_SP_EXIT, + &game.panel.sp_exit, + TYPE_INTEGER, + }, + { + GAME_CONTROL_STEEL_EXIT, + &game.panel.steel_exit, + TYPE_INTEGER, + }, + { + GAME_CONTROL_EM_STEEL_EXIT, + &game.panel.em_steel_exit, + TYPE_INTEGER, + }, + { + GAME_CONTROL_EMC_MAGIC_BALL, + &game.panel.emc_magic_ball, + TYPE_INTEGER, + }, + { + GAME_CONTROL_EMC_MAGIC_BALL_TIME, + &game.panel.emc_magic_ball_time, + TYPE_INTEGER, + }, + { + GAME_CONTROL_LIGHT_SWITCH, + &game.panel.light_switch, + TYPE_INTEGER, + }, + { + GAME_CONTROL_LIGHT_SWITCH_TIME, + &game.panel.light_switch_time, + TYPE_INTEGER, + }, + { + GAME_CONTROL_TIMEGATE_SWITCH, + &game.panel.timegate_switch, + TYPE_INTEGER, + }, + { + GAME_CONTROL_TIMEGATE_SWITCH_TIME, + &game.panel.timegate_switch_time, + TYPE_INTEGER, + }, + { + GAME_CONTROL_SWITCHGATE_SWITCH, + &game.panel.switchgate_switch, + TYPE_INTEGER, + }, + { + GAME_CONTROL_EMC_LENSES, + &game.panel.emc_lenses, + TYPE_INTEGER, + }, + { + GAME_CONTROL_EMC_LENSES_TIME, + &game.panel.emc_lenses_time, + TYPE_INTEGER, + }, + { + GAME_CONTROL_EMC_MAGNIFIER, + &game.panel.emc_magnifier, + TYPE_INTEGER, + }, + { + GAME_CONTROL_EMC_MAGNIFIER_TIME, + &game.panel.emc_magnifier_time, + TYPE_INTEGER, + }, + { + GAME_CONTROL_BALLOON_SWITCH, + &game.panel.balloon_switch, + TYPE_INTEGER, + }, + { + GAME_CONTROL_DYNABOMB_NUMBER, + &game.panel.dynabomb_number, + TYPE_INTEGER, + }, + { + GAME_CONTROL_DYNABOMB_SIZE, + &game.panel.dynabomb_size, + TYPE_INTEGER, + }, + { + GAME_CONTROL_DYNABOMB_POWER, + &game.panel.dynabomb_power, + TYPE_INTEGER, + }, + { + GAME_CONTROL_PENGUINS, + &game.panel.penguins, + TYPE_INTEGER, + }, + { + GAME_CONTROL_SOKOBAN_OBJECTS, + &game.panel.sokoban_objects, + TYPE_INTEGER, + }, + { + GAME_CONTROL_SOKOBAN_FIELDS, + &game.panel.sokoban_fields, + TYPE_INTEGER, + }, + { + GAME_CONTROL_ROBOT_WHEEL, + &game.panel.robot_wheel, + TYPE_INTEGER, + }, + { + GAME_CONTROL_CONVEYOR_BELT_1, + &game.panel.conveyor_belt_1, + TYPE_INTEGER, + }, + { + GAME_CONTROL_CONVEYOR_BELT_1_SWITCH, + &game.panel.conveyor_belt_1_switch, + TYPE_INTEGER, + }, + { + GAME_CONTROL_CONVEYOR_BELT_2, + &game.panel.conveyor_belt_2, + TYPE_INTEGER, + }, + { + GAME_CONTROL_CONVEYOR_BELT_2_SWITCH, + &game.panel.conveyor_belt_2_switch, + TYPE_INTEGER, + }, + { + GAME_CONTROL_CONVEYOR_BELT_3, + &game.panel.conveyor_belt_3, + TYPE_INTEGER, + }, + { + GAME_CONTROL_CONVEYOR_BELT_3_SWITCH, + &game.panel.conveyor_belt_3_switch, + TYPE_INTEGER, + }, + { + GAME_CONTROL_CONVEYOR_BELT_4, + &game.panel.conveyor_belt_4, + TYPE_INTEGER, + }, + { + GAME_CONTROL_CONVEYOR_BELT_4_SWITCH, + &game.panel.conveyor_belt_4_switch, + TYPE_INTEGER, + }, + { + GAME_CONTROL_MAGIC_WALL, + &game.panel.magic_wall, + TYPE_INTEGER, + }, + { + GAME_CONTROL_MAGIC_WALL_TIME, + &game.panel.magic_wall_time, + TYPE_INTEGER, + }, + { + GAME_CONTROL_BD_MAGIC_WALL, + &game.panel.bd_magic_wall, + TYPE_INTEGER, + }, + { + GAME_CONTROL_DC_MAGIC_WALL, + &game.panel.dc_magic_wall, + TYPE_INTEGER, + }, + { + GAME_CONTROL_PLAYER_NAME, + &game.panel.player_name, + TYPE_INTEGER, + }, + { + GAME_CONTROL_LEVEL_NAME, + &game.panel.level_name, + TYPE_INTEGER, + }, + { + GAME_CONTROL_LEVEL_AUTHOR, + &game.panel.level_author, + TYPE_INTEGER, + }, + + { + -1, + NULL, + -1, + NULL + } +}; +#endif + + /* values for delayed check of falling and moving elements and for collision */ #define CHECK_DELAY_MOVING 3 #define CHECK_DELAY_FALLING CHECK_DELAY_MOVING @@ -843,7 +1295,7 @@ static int playfield_scan_delta_y = 1; (y) += playfield_scan_delta_y) \ for ((x) = playfield_scan_start_x; \ (x) >= 0 && (x) <= lev_fieldx - 1; \ - (x) += playfield_scan_delta_x) \ + (x) += playfield_scan_delta_x) #ifdef DEBUG void DEBUG_SetMaximumDynamite() @@ -942,7 +1394,7 @@ void GetPlayerConfig() InitJoysticks(); } -static int get_element_from_group_element(int element) +int GetElementFromGroupElement(int element) { if (IS_GROUP_ELEMENT(element)) { @@ -1240,7 +1692,7 @@ static void InitField(int x, int y, boolean init_game) } else if (IS_GROUP_ELEMENT(element)) { - Feld[x][y] = get_element_from_group_element(element); + Feld[x][y] = GetElementFromGroupElement(element); InitField(x, y, init_game); } @@ -1288,74 +1740,91 @@ static inline void InitField_WithBug2(int x, int y, boolean init_game) void DrawGameValue_Emeralds(int value) { struct TextPosInfo *pos = &game.panel.gems; +#if 1 + int font_nr = pos->font; +#else int font_nr = FONT_TEXT_2; +#endif int font_width = getFontWidth(font_nr); - int digits = pos->chars; + int chars = pos->chars; if (PANEL_DEACTIVATED(pos)) return; - pos->width = digits * font_width; + pos->width = chars * font_width; - DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), int2str(value, digits), font_nr); + DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), int2str(value, chars), font_nr); } void DrawGameValue_Dynamite(int value) { struct TextPosInfo *pos = &game.panel.inventory; +#if 1 + int font_nr = pos->font; +#else int font_nr = FONT_TEXT_2; +#endif int font_width = getFontWidth(font_nr); - int digits = pos->chars; + int chars = pos->chars; if (PANEL_DEACTIVATED(pos)) return; - pos->width = digits * font_width; + pos->width = chars * font_width; - DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), int2str(value, digits), font_nr); + DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), int2str(value, chars), font_nr); } void DrawGameValue_Score(int value) { struct TextPosInfo *pos = &game.panel.score; +#if 1 + int font_nr = pos->font; +#else int font_nr = FONT_TEXT_2; +#endif int font_width = getFontWidth(font_nr); - int digits = pos->chars; + int chars = pos->chars; if (PANEL_DEACTIVATED(pos)) return; - pos->width = digits * font_width; + pos->width = chars * font_width; - DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), int2str(value, digits), font_nr); + DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), int2str(value, chars), font_nr); } void DrawGameValue_Time(int value) { struct TextPosInfo *pos = &game.panel.time; static int last_value = -1; - int digits1 = 3; - int digits2 = 4; - int digits = pos->chars; + int chars1 = 3; + int chars2 = 4; + int chars = pos->chars; +#if 1 + int font1_nr = pos->font; + int font2_nr = pos->font_alt; +#else int font1_nr = FONT_TEXT_2; int font2_nr = FONT_TEXT_1; +#endif int font_nr = font1_nr; - boolean use_dynamic_digits = (digits == -1 ? TRUE : FALSE); + boolean use_dynamic_chars = (chars == -1 ? TRUE : FALSE); if (PANEL_DEACTIVATED(pos)) return; - if (use_dynamic_digits) /* use dynamic number of digits */ + if (use_dynamic_chars) /* use dynamic number of chars */ { - digits = (value < 1000 ? digits1 : digits2); + chars = (value < 1000 ? chars1 : chars2); font_nr = (value < 1000 ? font1_nr : font2_nr); } - /* clear background if value just changed its size (dynamic digits only) */ - if (use_dynamic_digits && (last_value < 1000) != (value < 1000)) + /* clear background if value just changed its size (dynamic chars only) */ + if (use_dynamic_chars && (last_value < 1000) != (value < 1000)) { - int width1 = digits1 * getFontWidth(font1_nr); - int width2 = digits2 * getFontWidth(font2_nr); + int width1 = chars1 * getFontWidth(font1_nr); + int width2 = chars2 * getFontWidth(font2_nr); int max_width = MAX(width1, width2); int max_height = MAX(getFontHeight(font1_nr), getFontHeight(font2_nr)); @@ -1365,9 +1834,9 @@ void DrawGameValue_Time(int value) max_width, max_height); } - pos->width = digits * getFontWidth(font_nr); + pos->width = chars * getFontWidth(font_nr); - DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), int2str(value, digits), font_nr); + DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), int2str(value, chars), font_nr); last_value = value; } @@ -1375,26 +1844,31 @@ void DrawGameValue_Time(int value) void DrawGameValue_Level(int value) { struct TextPosInfo *pos = &game.panel.level; - int digits1 = 2; - int digits2 = 3; - int digits = pos->chars; + int chars1 = 2; + int chars2 = 3; + int chars = pos->chars; +#if 1 + int font1_nr = pos->font; + int font2_nr = pos->font_alt; +#else int font1_nr = FONT_TEXT_2; int font2_nr = FONT_TEXT_1; +#endif int font_nr = font1_nr; - boolean use_dynamic_digits = (digits == -1 ? TRUE : FALSE); + boolean use_dynamic_chars = (chars == -1 ? TRUE : FALSE); if (PANEL_DEACTIVATED(pos)) return; - if (use_dynamic_digits) /* use dynamic number of digits */ + if (use_dynamic_chars) /* use dynamic number of chars */ { - digits = (level_nr < 100 ? digits1 : digits2); + chars = (level_nr < 100 ? chars1 : chars2); font_nr = (level_nr < 100 ? font1_nr : font2_nr); } - pos->width = digits * getFontWidth(font_nr); + pos->width = chars * getFontWidth(font_nr); - DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), int2str(value, digits), font_nr); + DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), int2str(value, chars), font_nr); } void DrawGameValue_Keys(int key[MAX_NUM_KEYS]) @@ -1419,11 +1893,34 @@ void DrawGameValue_Keys(int key[MAX_NUM_KEYS]) int dst_x = PANEL_XPOS(pos) + i * MINI_TILEX; int dst_y = PANEL_YPOS(pos); +#if 0 + /* masked blit with tiles from half-size scaled bitmap does not work yet + (no mask bitmap created for these sizes after loading and scaling) -- + solution: load without creating mask, scale, then create final mask */ + + BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto, src_x, src_y, + MINI_TILEX, MINI_TILEY, dst_x, dst_y); + + if (key[i]) + { + int graphic = el2edimg(base_key_graphic + i); + Bitmap *src_bitmap; + int src_x, src_y; + + getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y); + + SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc, + dst_x - src_x, dst_y - src_y); + BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, MINI_TILEX, MINI_TILEY, + dst_x, dst_y); + } +#else if (key[i]) DrawMiniGraphicExt(drawto, dst_x, dst_y, el2edimg(base_key_graphic + i)); else BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto, src_x, src_y, MINI_TILEX, MINI_TILEY, dst_x, dst_y); +#endif } } @@ -8732,7 +9229,7 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) static void CreateFieldExt(int x, int y, int element, boolean is_change) { int old_element = Feld[x][y]; - int new_element = get_element_from_group_element(element); + int new_element = GetElementFromGroupElement(element); int previous_move_direction = MovDir[x][y]; #if USE_NEW_CUSTOM_VALUE int last_ce_value = CustomValue[x][y]; @@ -9064,12 +9561,13 @@ static void HandleElementChange(int x, int y, int page) if (change->can_change) { -#if 0 +#if 1 /* !!! not clear why graphic animation should be reset at all here !!! */ + /* !!! UPDATE: but is needed for correct Snake Bite tail animation !!! */ #if USE_GFX_RESET_WHEN_NOT_MOVING /* when a custom element is about to change (for example by change delay), do not reset graphic animation when the custom element is moving */ - if (IS_MOVING(x, y)) + if (!IS_MOVING(x, y)) #endif { ResetGfxAnimation(x, y); @@ -10782,14 +11280,19 @@ void ScrollLevel(int dx, int dy) int i, x, y; #endif +#if 0 + /* !!! THIS IS APPARENTLY WRONG FOR PLAYER RELOCATION !!! */ /* only horizontal XOR vertical scroll direction allowed */ if ((dx == 0 && dy == 0) || (dx != 0 && dy != 0)) return; +#endif #if 1 if (bitmap_db_field2 == NULL) bitmap_db_field2 = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH); + /* needed when blitting directly to same bitmap -- should not be needed with + recent SDL libraries, but apparently does not work in 1.2.11 directly */ BlitBitmap(drawto_field, bitmap_db_field2, FX + TILEX * (dx == -1) - softscroll_offset, FY + TILEY * (dy == -1) - softscroll_offset, @@ -10808,6 +11311,7 @@ void ScrollLevel(int dx, int dy) #else #if 1 + /* !!! DOES NOT WORK FOR DIAGONAL PLAYER RELOCATION !!! */ int xsize = (BX2 - BX1 + 1); int ysize = (BY2 - BY1 + 1); int start = (dx != 0 ? (dx == -1 ? BX1 : BX2) : (dy == -1 ? BY1 : BY2));