X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Feditor.c;h=009297ae66122de238e2126ce7312d66015739e3;hb=590e9a86daa2b0d3923673bfe02525766224808e;hp=632d7155b53d80f12607688d91f896a1cb357de6;hpb=5c51379382ab3d349e17ae6988eb80b3c2f9da3f;p=rocksndiamonds.git diff --git a/src/editor.c b/src/editor.c index 632d7155..009297ae 100644 --- a/src/editor.c +++ b/src/editor.c @@ -916,11 +916,11 @@ /* values for elements with score for certain actions */ #define MIN_SCORE 0 -#define MAX_SCORE 255 +#define MAX_SCORE 999 /* values for elements with count for collecting */ #define MIN_COLLECT_COUNT 0 -#define MAX_COLLECT_COUNT 255 +#define MAX_COLLECT_COUNT 999 /* values for random placement */ #define RANDOM_USE_PERCENTAGE 0 @@ -1047,7 +1047,7 @@ static struct }, { ED_LEVEL_SETTINGS_XPOS(0), ED_LEVEL_SETTINGS_YPOS(9), - 0, 255, + 0, 999, GADGET_ID_LEVEL_TIMESCORE_DOWN, GADGET_ID_LEVEL_TIMESCORE_UP, GADGET_ID_LEVEL_TIMESCORE_TEXT, GADGET_ID_NONE, &level.score[SC_TIME_BONUS], @@ -1173,7 +1173,7 @@ static struct }, { ED_ELEMENT_SETTINGS_XPOS(1), ED_ELEMENT_SETTINGS_YPOS(7), - 0, 255, + 0, 999, GADGET_ID_PUSH_DELAY_FIX_DOWN, GADGET_ID_PUSH_DELAY_FIX_UP, GADGET_ID_PUSH_DELAY_FIX_TEXT, GADGET_ID_NONE, &custom_element.push_delay_fixed, @@ -1181,7 +1181,7 @@ static struct }, { -1, ED_ELEMENT_SETTINGS_YPOS(7), - 0, 255, + 0, 999, GADGET_ID_PUSH_DELAY_RND_DOWN, GADGET_ID_PUSH_DELAY_RND_UP, GADGET_ID_PUSH_DELAY_RND_TEXT, GADGET_ID_PUSH_DELAY_FIX_UP, &custom_element.push_delay_random, @@ -1189,7 +1189,7 @@ static struct }, { ED_ELEMENT_SETTINGS_XPOS(1), ED_ELEMENT_SETTINGS_YPOS(8), - 0, 255, + 0, 999, GADGET_ID_DROP_DELAY_FIX_DOWN, GADGET_ID_DROP_DELAY_FIX_UP, GADGET_ID_DROP_DELAY_FIX_TEXT, GADGET_ID_NONE, &custom_element.drop_delay_fixed, @@ -1197,7 +1197,7 @@ static struct }, { -1, ED_ELEMENT_SETTINGS_YPOS(8), - 0, 255, + 0, 999, GADGET_ID_DROP_DELAY_RND_DOWN, GADGET_ID_DROP_DELAY_RND_UP, GADGET_ID_DROP_DELAY_RND_TEXT, GADGET_ID_DROP_DELAY_FIX_UP, &custom_element.drop_delay_random, @@ -1224,7 +1224,7 @@ static struct }, { ED_ELEMENT_SETTINGS_XPOS(1), ED_ELEMENT_SETTINGS_YPOS(12), - 0, 255, + 0, 999, GADGET_ID_EXPLOSION_DELAY_DOWN, GADGET_ID_EXPLOSION_DELAY_UP, GADGET_ID_EXPLOSION_DELAY_TEXT, GADGET_ID_NONE, &custom_element.explosion_delay, @@ -1232,7 +1232,7 @@ static struct }, { ED_ELEMENT_SETTINGS_XPOS(1), ED_ELEMENT_SETTINGS_YPOS(13), - 0, 255, + 0, 999, GADGET_ID_IGNITION_DELAY_DOWN, GADGET_ID_IGNITION_DELAY_UP, GADGET_ID_IGNITION_DELAY_TEXT, GADGET_ID_NONE, &custom_element.ignition_delay, @@ -8418,9 +8418,20 @@ static int getBeltFromNrAndOpenDirection(int nr, int direction) direction == MV_RIGHT ? MV_LEFT : direction == MV_HORIZONTAL ? MV_NONE : direction); + if (direction == MV_NONE) + return EL_EMPTY; + return getBeltElementFromBeltNrAndBeltDir(nr, belt_dir); } +static int getBeltFromNrAndOpenDirectionNotEmpty(int nr, int direction, + int element_old) +{ + int element_new = getBeltFromNrAndOpenDirection(nr, direction); + + return (element_new != EL_EMPTY ? element_new : element_old); +} + static int getOpenDirectionFromPool(int element) { switch (element) @@ -8451,7 +8462,7 @@ static int getPoolFromOpenDirection(int direction) return EL_EMPTY; } -static int getPoolFromOpenDirection2(int direction, int help_element) +static int getPoolFromOpenDirectionExt(int direction, int help_element) { int element = getPoolFromOpenDirection(direction); int help_direction = getOpenDirectionFromPool(help_element); @@ -8475,7 +8486,114 @@ static int getPoolFromOpenDirection2(int direction, int help_element) static int getPoolFromOpenDirectionNotEmpty(int direction, int element_old) { - int element_new = getPoolFromOpenDirection2(direction, element_old); + int element_new = getPoolFromOpenDirectionExt(direction, element_old); + + return (element_new != EL_EMPTY ? element_new : element_old); +} + +static int getOpenDirectionFromPillar(int element) +{ + switch (element) + { + case EL_EMC_WALL_1: return (MV_DOWN); + case EL_EMC_WALL_2: return (MV_VERTICAL); + case EL_EMC_WALL_3: return (MV_UP); + } + + return MV_NONE; +} + +static int getPillarFromOpenDirection(int direction) +{ + switch (direction) + { + case (MV_DOWN): return EL_EMC_WALL_1; + case (MV_VERTICAL): return EL_EMC_WALL_2; + case (MV_UP): return EL_EMC_WALL_3; + } + + return EL_EMPTY; +} + +static int getPillarFromOpenDirectionNotEmpty(int direction, int element_old) +{ + int element_new = getPillarFromOpenDirection(direction); + + return (element_new != EL_EMPTY ? element_new : element_old); +} + +static int getOpenDirectionFromSteel2(int element) +{ + switch (element) + { + case EL_DC_STEELWALL_2_LEFT: return (MV_RIGHT); + case EL_DC_STEELWALL_2_RIGHT: return (MV_LEFT); + case EL_DC_STEELWALL_2_TOP: return (MV_DOWN); + case EL_DC_STEELWALL_2_BOTTOM: return (MV_UP); + case EL_DC_STEELWALL_2_HORIZONTAL: return (MV_HORIZONTAL); + case EL_DC_STEELWALL_2_VERTICAL: return (MV_VERTICAL); + case EL_DC_STEELWALL_2_MIDDLE: return (MV_ANY_DIRECTION); + case EL_DC_STEELWALL_2_SINGLE: return (MV_NONE); + } + + return MV_NONE; +} + +static int getSteel2FromOpenDirection(int direction) +{ + switch (direction) + { + case (MV_RIGHT): return EL_DC_STEELWALL_2_LEFT; + case (MV_LEFT): return EL_DC_STEELWALL_2_RIGHT; + case (MV_DOWN): return EL_DC_STEELWALL_2_TOP; + case (MV_UP): return EL_DC_STEELWALL_2_BOTTOM; + case (MV_HORIZONTAL): return EL_DC_STEELWALL_2_HORIZONTAL; + case (MV_VERTICAL): return EL_DC_STEELWALL_2_VERTICAL; + case (MV_ANY_DIRECTION): return EL_DC_STEELWALL_2_MIDDLE; + case (MV_NONE): return EL_DC_STEELWALL_2_SINGLE; + } + + return EL_EMPTY; +} + +static int getSteel2FromOpenDirectionNotEmpty(int direction, int element_old) +{ + int element_new = getSteel2FromOpenDirection(direction); + + return (element_new != EL_EMPTY ? element_new : element_old); +} + +static int getOpenDirectionFromChip(int element) +{ + switch (element) + { + case EL_SP_CHIP_SINGLE: return (MV_NONE); + case EL_SP_CHIP_LEFT: return (MV_RIGHT); + case EL_SP_CHIP_RIGHT: return (MV_LEFT); + case EL_SP_CHIP_TOP: return (MV_DOWN); + case EL_SP_CHIP_BOTTOM: return (MV_UP); + } + + return MV_NONE; +} + +static int getChipFromOpenDirection(int direction) +{ + switch (direction) + { + case (MV_NONE): return EL_SP_CHIP_SINGLE; + case (MV_LEFT): return EL_SP_CHIP_RIGHT; + case (MV_RIGHT): return EL_SP_CHIP_LEFT; + case (MV_UP): return EL_SP_CHIP_BOTTOM; + case (MV_DOWN): return EL_SP_CHIP_TOP; + } + + return EL_EMPTY; +} + +static int getChipFromOpenDirectionNotEmpty(int direction, int element_old) +{ + int element_new = getChipFromOpenDirection(direction); return (element_new != EL_EMPTY ? element_new : element_old); } @@ -8490,8 +8608,8 @@ static int getClosedTube(int x, int y) { 0, +1 } }; int element_old = IntelliDrawBuffer[x][y]; - int tube_direction_old = getOpenDirectionFromTube(element_old); - int tube_direction_new = MV_NONE; + int direction_old = getOpenDirectionFromTube(element_old); + int direction_new = MV_NONE; int i; for (i = 0; i < NUM_DIRECTIONS; i++) @@ -8502,28 +8620,30 @@ static int getClosedTube(int x, int y) int dir_opposite = MV_DIR_OPPOSITE(dir); if (IN_LEV_FIELD(xx, yy) && IS_TUBE(IntelliDrawBuffer[xx][yy]) && - (tube_direction_old & dir) && + (direction_old & dir) && (getOpenDirectionFromTube(IntelliDrawBuffer[xx][yy]) & dir_opposite)) - tube_direction_new |= dir; + direction_new |= dir; } - return getTubeFromOpenDirectionNotEmpty(tube_direction_new, element_old); + return getTubeFromOpenDirectionNotEmpty(direction_new, element_old); } static int getClosedBelt(int x, int y) { - static int xy[2][2] = + static int xy[4][2] = { { -1, 0 }, { +1, 0 }, + { 0, -1 }, + { 0, +1 } }; int element_old = IntelliDrawBuffer[x][y]; - int belt_nr = getBeltNrFromBeltElement(element_old); - int belt_direction_old = getOpenDirectionFromBelt(element_old); - int belt_direction_new = MV_NONE; + int nr = getBeltNrFromBeltElement(element_old); + int direction_old = getOpenDirectionFromBelt(element_old); + int direction_new = MV_NONE; int i; - for (i = 0; i < 2; i++) + for (i = MV_BIT_LEFT; i <= MV_BIT_RIGHT; i++) { int xx = x + xy[i][0]; int yy = y + xy[i][1]; @@ -8531,12 +8651,12 @@ static int getClosedBelt(int x, int y) int dir_opposite = MV_DIR_OPPOSITE(dir); if (IN_LEV_FIELD(xx, yy) && IS_BELT(IntelliDrawBuffer[xx][yy]) && - (belt_direction_old & dir) && + (direction_old & dir) && (getOpenDirectionFromBelt(IntelliDrawBuffer[xx][yy]) & dir_opposite)) - belt_direction_new |= dir; + direction_new |= dir; } - return getBeltFromNrAndOpenDirection(belt_nr, belt_direction_new); + return getBeltFromNrAndOpenDirection(nr, direction_new); } static int getClosedPool(int x, int y) @@ -8549,8 +8669,8 @@ static int getClosedPool(int x, int y) { 0, +1 } }; int element_old = IntelliDrawBuffer[x][y]; - int pool_direction_old = getOpenDirectionFromPool(element_old); - int pool_direction_new = MV_NONE; + int direction_old = getOpenDirectionFromPool(element_old); + int direction_new = MV_NONE; int i; for (i = 0; i < NUM_DIRECTIONS; i++) @@ -8562,28 +8682,146 @@ static int getClosedPool(int x, int y) if (IN_LEV_FIELD(xx, yy) && IS_ACID_POOL_OR_ACID(IntelliDrawBuffer[xx][yy]) && - (pool_direction_old & dir) && + (direction_old & dir) && (getOpenDirectionFromPool(IntelliDrawBuffer[xx][yy]) & dir_opposite)) - pool_direction_new |= dir; + direction_new |= dir; + } + + return getPoolFromOpenDirectionNotEmpty(direction_new, element_old); +} + +static int getClosedPillar(int x, int y) +{ + static int xy[4][2] = + { + { -1, 0 }, + { +1, 0 }, + { 0, -1 }, + { 0, +1 } + }; + int element_old = IntelliDrawBuffer[x][y]; + int direction_old = getOpenDirectionFromPillar(element_old); + int direction_new = MV_NONE; + int i; + + for (i = MV_BIT_UP; i <= MV_BIT_DOWN; i++) + { + int xx = x + xy[i][0]; + int yy = y + xy[i][1]; + int dir = MV_DIR_FROM_BIT(i); + int dir_opposite = MV_DIR_OPPOSITE(dir); + + if (IN_LEV_FIELD(xx, yy) && IS_EMC_PILLAR(IntelliDrawBuffer[xx][yy]) && + (direction_old & dir) && + (getOpenDirectionFromPillar(IntelliDrawBuffer[xx][yy]) & dir_opposite)) + direction_new |= dir; + } + + return getPillarFromOpenDirectionNotEmpty(direction_new, element_old); +} + +static int getClosedSteel2(int x, int y) +{ + static int xy[4][2] = + { + { -1, 0 }, + { +1, 0 }, + { 0, -1 }, + { 0, +1 } + }; + int element_old = IntelliDrawBuffer[x][y]; + int direction_old = getOpenDirectionFromSteel2(element_old); + int direction_new = MV_NONE; + int i; + + for (i = 0; i < NUM_DIRECTIONS; i++) + { + int xx = x + xy[i][0]; + int yy = y + xy[i][1]; + int dir = MV_DIR_FROM_BIT(i); + int dir_opposite = MV_DIR_OPPOSITE(dir); + + if (IN_LEV_FIELD(xx, yy) && IS_DC_STEELWALL_2(IntelliDrawBuffer[xx][yy]) && + (direction_old & dir) && + (getOpenDirectionFromSteel2(IntelliDrawBuffer[xx][yy]) & dir_opposite)) + direction_new |= dir; } - return getPoolFromOpenDirectionNotEmpty(pool_direction_new, element_old); + return getSteel2FromOpenDirectionNotEmpty(direction_new, element_old); +} + +static int getClosedChip(int x, int y) +{ + static int xy[4][2] = + { + { -1, 0 }, + { +1, 0 }, + { 0, -1 }, + { 0, +1 } + }; + int element_old = IntelliDrawBuffer[x][y]; + int direction_old = getOpenDirectionFromChip(element_old); + int direction_new = MV_NONE; + int i; + + for (i = 0; i < NUM_DIRECTIONS; i++) + { + int xx = x + xy[i][0]; + int yy = y + xy[i][1]; + int dir = MV_DIR_FROM_BIT(i); + int dir_opposite = MV_DIR_OPPOSITE(dir); + + if (IN_LEV_FIELD(xx, yy) && IS_SP_CHIP(IntelliDrawBuffer[xx][yy]) && + (direction_old & dir) && + (getOpenDirectionFromChip(IntelliDrawBuffer[xx][yy]) & dir_opposite)) + direction_new |= dir; + } + + return getChipFromOpenDirectionNotEmpty(direction_new, element_old); } static void SetElementSimple(int x, int y, int element, boolean change_level) { + int sx = x - level_xpos; + int sy = y - level_ypos; + + IntelliDrawBuffer[x][y] = element; + if (change_level) Feld[x][y] = element; - IntelliDrawBuffer[x][y] = element; + if (IN_ED_FIELD(sx, sy)) + DrawMiniElement(sx, sy, element); +} - if (IN_ED_FIELD(x - level_xpos, y - level_ypos)) - DrawMiniElement(x - level_xpos, y - level_ypos, element); +static void MergeAndCloseNeighbourElements(int x1, int y1, int *element1, + int x2, int y2, int *element2, + int (*close_function)(int, int), + boolean change_level) +{ + /* set neighbour elements to newly determined connections */ + SetElementSimple(x1, y1, *element1, change_level); + SetElementSimple(x2, y2, *element2, change_level); + + /* remove all open connections of neighbour elements */ + *element1 = close_function(x1, y1); + *element2 = close_function(x2, y2); + + /* set neighbour elements to new, minimized connections */ + SetElementSimple(x1, y1, *element1, change_level); + SetElementSimple(x2, y2, *element2, change_level); } static void SetElementIntelliDraw(int x, int y, int new_element, - boolean change_level) + boolean change_level, int button) { + static int xy[4][2] = + { + { -1, 0 }, + { +1, 0 }, + { 0, -1 }, + { 0, +1 } + }; static int last_x = -1; static int last_y = -1; int old_element = IntelliDrawBuffer[x][y]; @@ -8598,18 +8836,11 @@ static void SetElementIntelliDraw(int x, int y, int new_element, if (IS_TUBE(new_element)) { - static int xy[4][2] = - { - { -1, 0 }, - { +1, 0 }, - { 0, -1 }, - { 0, +1 } - }; int last_element_new = EL_UNDEFINED; int direction = MV_NONE; int i; - /* if existing element is tube, keep all existing tube directions */ + /* if old element is of same kind, keep all existing directions */ if (IS_TUBE(old_element)) direction |= getOpenDirectionFromTube(old_element); @@ -8635,37 +8866,57 @@ static void SetElementIntelliDraw(int x, int y, int new_element, new_element = getTubeFromOpenDirectionNotEmpty(direction, new_element); - /* reduce connections of neighbour tube elements to minimal connections */ if (last_element_new != EL_UNDEFINED) + MergeAndCloseNeighbourElements(x, y, &new_element, + last_x, last_y, &last_element_new, + getClosedTube, change_level); + } + else if (IS_BELT(new_element)) + { + int belt_nr = getBeltNrFromBeltElement(new_element); + int last_element_new = EL_UNDEFINED; + int direction = MV_NONE; + int i; + + /* if old element is of same kind, keep all existing directions */ + if (IS_BELT(old_element)) + direction |= getOpenDirectionFromBelt(old_element); + + for (i = MV_BIT_LEFT; i <= MV_BIT_RIGHT; i++) { - /* set neighbour tube elements to newly determined tube connections */ - SetElementSimple(x, y, new_element, change_level); - SetElementSimple(last_x, last_y, last_element_new, change_level); + int xx = x + xy[i][0]; + int yy = y + xy[i][1]; - /* remove all open tube connections of neighbour tube elements */ - new_element = getClosedTube(x, y); - last_element_new = getClosedTube(last_x, last_y); + if (last_x == xx && last_y == yy && IN_LEV_FIELD(last_x, last_y) && + IS_BELT(IntelliDrawBuffer[last_x][last_y])) + { + int dir = MV_DIR_FROM_BIT(i); + int dir_opposite = MV_DIR_OPPOSITE(dir); + int last_element_old = IntelliDrawBuffer[last_x][last_y]; + int last_belt_nr = getBeltNrFromBeltElement(last_element_old); + int last_direction_old = getOpenDirectionFromBelt(last_element_old); + int last_direction_new = last_direction_old | dir_opposite; - /* set neighbour tube elements to new, minimized tube connections */ - SetElementSimple(x, y, new_element, change_level); - SetElementSimple(last_x, last_y, last_element_new, change_level); + last_element_new = getBeltFromNrAndOpenDirection(last_belt_nr, + last_direction_new); + direction |= dir; + } } + + new_element = getBeltFromNrAndOpenDirectionNotEmpty(belt_nr, direction, + new_element); + if (last_element_new != EL_UNDEFINED) + MergeAndCloseNeighbourElements(x, y, &new_element, + last_x, last_y, &last_element_new, + getClosedBelt, change_level); } else if (IS_ACID_POOL_OR_ACID(new_element)) { -#if 1 - static int xy[4][2] = - { - { -1, 0 }, - { +1, 0 }, - { 0, -1 }, - { 0, +1 } - }; int last_element_new = EL_UNDEFINED; int direction = MV_NONE; int i; - /* if existing element is pool, keep all existing pool directions */ + /* if old element is of same kind, keep all existing directions */ if (IS_ACID_POOL_OR_ACID(old_element)) direction |= getOpenDirectionFromPool(old_element); @@ -8689,219 +8940,176 @@ static void SetElementIntelliDraw(int x, int y, int new_element, } } -#if 1 + /* special corrections needed for intuitively correct acid pool drawing */ if (last_element_new == EL_EMPTY) - last_element_new = EL_ACID; -#endif + last_element_new = new_element; + else if (last_element_new != EL_UNDEFINED) + new_element = last_element_new; -#if 1 - if (last_element_new != EL_UNDEFINED) - new_element = getPoolFromOpenDirectionNotEmpty(direction, - last_element_new); - else - new_element = getPoolFromOpenDirectionNotEmpty(direction, new_element); -#else new_element = getPoolFromOpenDirectionNotEmpty(direction, new_element); -#endif - /* reduce connections of neighbour pool elements to minimal connections */ if (last_element_new != EL_UNDEFINED) + MergeAndCloseNeighbourElements(x, y, &new_element, + last_x, last_y, &last_element_new, + getClosedPool, change_level); + } + else if (IS_EMC_PILLAR(new_element)) + { + int last_element_new = EL_UNDEFINED; + int direction = MV_NONE; + int i; + + /* if old element is of same kind, keep all existing directions */ + if (IS_EMC_PILLAR(old_element)) + direction |= getOpenDirectionFromPillar(old_element); + + for (i = MV_BIT_UP; i <= MV_BIT_DOWN; i++) { - /* set neighbour pool elements to newly determined pool connections */ - SetElementSimple(x, y, new_element, change_level); - SetElementSimple(last_x, last_y, last_element_new, change_level); + int xx = x + xy[i][0]; + int yy = y + xy[i][1]; - /* remove all open pool connections of neighbour pool elements */ - new_element = getClosedPool(x, y); - last_element_new = getClosedPool(last_x, last_y); + if (last_x == xx && last_y == yy && IN_LEV_FIELD(last_x, last_y) && + IS_EMC_PILLAR(IntelliDrawBuffer[last_x][last_y])) + { + int dir = MV_DIR_FROM_BIT(i); + int dir_opposite = MV_DIR_OPPOSITE(dir); + int last_element_old = IntelliDrawBuffer[last_x][last_y]; + int last_direction_old = getOpenDirectionFromPillar(last_element_old); + int last_direction_new = last_direction_old | dir_opposite; - /* set neighbour pool elements to new, minimized pool connections */ - SetElementSimple(x, y, new_element, change_level); - SetElementSimple(last_x, last_y, last_element_new, change_level); + last_element_new = getPillarFromOpenDirection(last_direction_new); + + direction |= dir; + } } -#else + new_element = getPillarFromOpenDirectionNotEmpty(direction, new_element); + if (last_element_new != EL_UNDEFINED) + MergeAndCloseNeighbourElements(x, y, &new_element, + last_x, last_y, &last_element_new, + getClosedPillar, change_level); + } + else if (IS_DC_STEELWALL_2(new_element)) + { int last_element_new = EL_UNDEFINED; + int direction = MV_NONE; + int i; - if (IS_ACID_POOL(old_element)) - new_element = old_element; + /* if old element is of same kind, keep all existing directions */ + if (IS_DC_STEELWALL_2(old_element)) + direction |= getOpenDirectionFromSteel2(old_element); - if (last_x == x - 1 && last_y == y && IN_LEV_FIELD(last_x, last_y) && - IS_ACID_POOL(IntelliDrawBuffer[last_x][last_y])) - { - if (IntelliDrawBuffer[last_x][last_y] == EL_ACID_POOL_TOPLEFT) - { - new_element = EL_ACID_POOL_TOPRIGHT; - } - else if (IntelliDrawBuffer[last_x][last_y] == EL_ACID_POOL_TOPRIGHT) - { - last_element_new = EL_ACID; - new_element = EL_ACID_POOL_TOPRIGHT; - } - else if (IntelliDrawBuffer[last_x][last_y] == EL_ACID_POOL_BOTTOMLEFT) - { - new_element = EL_ACID_POOL_BOTTOMRIGHT; - } - else if (IntelliDrawBuffer[last_x][last_y] == EL_ACID_POOL_BOTTOMRIGHT) - { - last_element_new = EL_ACID_POOL_BOTTOM; - new_element = EL_ACID_POOL_BOTTOMRIGHT; - } - } - else if (last_x == x + 1 && last_y == y && IN_LEV_FIELD(last_x, last_y) && - IS_ACID_POOL(IntelliDrawBuffer[last_x][last_y])) - { - if (IntelliDrawBuffer[last_x][last_y] == EL_ACID_POOL_TOPLEFT) - { - last_element_new = EL_ACID; - new_element = EL_ACID_POOL_TOPLEFT; - } - else if (IntelliDrawBuffer[last_x][last_y] == EL_ACID_POOL_TOPRIGHT) - { - new_element = EL_ACID_POOL_TOPLEFT; - } - else if (IntelliDrawBuffer[last_x][last_y] == EL_ACID_POOL_BOTTOMLEFT) - { - last_element_new = EL_ACID_POOL_BOTTOM; - new_element = EL_ACID_POOL_BOTTOMLEFT; - } - else if (IntelliDrawBuffer[last_x][last_y] == EL_ACID_POOL_BOTTOMRIGHT) - { - new_element = EL_ACID_POOL_BOTTOMLEFT; - } - } - else if (last_x == x && last_y == y - 1 && IN_LEV_FIELD(last_x, last_y) && - IS_ACID_POOL(IntelliDrawBuffer[last_x][last_y])) - { - if (IntelliDrawBuffer[last_x][last_y] == EL_ACID_POOL_TOPLEFT) - { - new_element = EL_ACID_POOL_BOTTOMLEFT; - } - else if (IntelliDrawBuffer[last_x][last_y] == EL_ACID_POOL_TOPRIGHT) - { - new_element = EL_ACID_POOL_BOTTOMRIGHT; - } - else if (IntelliDrawBuffer[last_x][last_y] == EL_ACID_POOL_BOTTOMLEFT) - { - last_element_new = EL_ACID_POOL_TOPLEFT; - new_element = EL_ACID_POOL_BOTTOMLEFT; - } - else if (IntelliDrawBuffer[last_x][last_y] == EL_ACID_POOL_BOTTOMRIGHT) - { - last_element_new = EL_ACID_POOL_TOPRIGHT; - new_element = EL_ACID_POOL_BOTTOMRIGHT; - } - else - { - last_element_new = EL_ACID; - new_element = EL_ACID_POOL_BOTTOM; - } - } - else if (last_x == x && last_y == y + 1 && IN_LEV_FIELD(last_x, last_y) && - IS_ACID_POOL(IntelliDrawBuffer[last_x][last_y])) + for (i = 0; i < NUM_DIRECTIONS; i++) { - if (IntelliDrawBuffer[last_x][last_y] == EL_ACID_POOL_TOPLEFT) - { - new_element = EL_ACID_POOL_TOPLEFT; - } - else if (IntelliDrawBuffer[last_x][last_y] == EL_ACID_POOL_TOPRIGHT) - { - new_element = EL_ACID_POOL_TOPRIGHT; - } - else if (IntelliDrawBuffer[last_x][last_y] == EL_ACID_POOL_BOTTOMLEFT) - { - new_element = EL_ACID_POOL_TOPLEFT; - } - else if (IntelliDrawBuffer[last_x][last_y] == EL_ACID_POOL_BOTTOMRIGHT) - { - new_element = EL_ACID_POOL_TOPRIGHT; - } - else + int xx = x + xy[i][0]; + int yy = y + xy[i][1]; + + if (last_x == xx && last_y == yy && IN_LEV_FIELD(last_x, last_y) && + IS_DC_STEELWALL_2(IntelliDrawBuffer[last_x][last_y])) { - last_element_new = EL_ACID; - new_element = EL_ACID; + int dir = MV_DIR_FROM_BIT(i); + int dir_opposite = MV_DIR_OPPOSITE(dir); + int last_element_old = IntelliDrawBuffer[last_x][last_y]; + int last_direction_old = getOpenDirectionFromSteel2(last_element_old); + int last_direction_new = last_direction_old | dir_opposite; + + last_element_new = getSteel2FromOpenDirection(last_direction_new); + + direction |= dir; } } + new_element = getSteel2FromOpenDirectionNotEmpty(direction, new_element); + if (last_element_new != EL_UNDEFINED) - SetElementSimple(last_x, last_y, last_element_new, change_level); -#endif + MergeAndCloseNeighbourElements(x, y, &new_element, + last_x, last_y, &last_element_new, + getClosedSteel2, change_level); } - else if (IS_BELT(new_element)) + else if (IS_SP_CHIP(new_element)) { int last_element_new = EL_UNDEFINED; + int direction = MV_NONE; + int i; - if (((last_x == x - 1 && last_y == y) || - (last_x == x + 1 && last_y == y)) && IN_LEV_FIELD(last_x, last_y) && - IS_BELT(IntelliDrawBuffer[last_x][last_y])) + /* (do not keep existing directions, regardless of kind of old element) */ + + for (i = 0; i < NUM_DIRECTIONS; i++) { - int belt_nr = getBeltNrFromBeltElement(new_element); - int belt_middle = getBeltElementFromBeltNrAndBeltDir(belt_nr, MV_NONE); + int xx = x + xy[i][0]; + int yy = y + xy[i][1]; - new_element = belt_middle; - last_element_new = belt_middle; + if (last_x == xx && last_y == yy && IN_LEV_FIELD(last_x, last_y) && + IS_SP_CHIP(IntelliDrawBuffer[last_x][last_y])) + { + int dir = MV_DIR_FROM_BIT(i); + int dir_opposite = MV_DIR_OPPOSITE(dir); + int last_element_old = IntelliDrawBuffer[last_x][last_y]; + int last_direction_old = getOpenDirectionFromChip(last_element_old); + int last_direction_new = last_direction_old | dir_opposite; + + if (last_direction_old == MV_NONE) + { + last_element_new = getChipFromOpenDirection(last_direction_new); + direction |= dir; + } + else if (last_direction_old & (dir | dir_opposite)) + { + direction |= MV_DIR_OPPOSITE(last_direction_old); + } + else + { + direction |= MV_DIR_OPPOSITE(dir); + } + } } - /* reduce connections of neighbour belt elements to minimal connections */ + new_element = getChipFromOpenDirectionNotEmpty(direction, new_element); + if (last_element_new != EL_UNDEFINED) - { - /* set neighbour belt elements to newly determined belt connections */ - SetElementSimple(x, y, new_element, change_level); - SetElementSimple(last_x, last_y, last_element_new, change_level); + MergeAndCloseNeighbourElements(x, y, &new_element, + last_x, last_y, &last_element_new, + getClosedChip, change_level); + } + else if (IS_SP_HARDWARE_BASE(new_element)) + { + int nr = GetSimpleRandom(6); - /* remove all open belt connections of neighbour belt elements */ - new_element = getClosedBelt(x, y); - last_element_new = getClosedBelt(last_x, last_y); + new_element = (nr == 0 ? EL_SP_HARDWARE_BASE_1 : + nr == 1 ? EL_SP_HARDWARE_BASE_2 : + nr == 2 ? EL_SP_HARDWARE_BASE_3 : + nr == 3 ? EL_SP_HARDWARE_BASE_4 : + nr == 4 ? EL_SP_HARDWARE_BASE_5 : EL_SP_HARDWARE_BASE_6); + } + else if (new_element == EL_SP_HARDWARE_GREEN || + new_element == EL_SP_HARDWARE_BLUE || + new_element == EL_SP_HARDWARE_RED) + { + int nr = GetSimpleRandom(3); - /* set neighbour belt elements to new, minimized belt connections */ - SetElementSimple(x, y, new_element, change_level); - SetElementSimple(last_x, last_y, last_element_new, change_level); - } + new_element = (nr == 0 ? EL_SP_HARDWARE_GREEN : + nr == 1 ? EL_SP_HARDWARE_BLUE : EL_SP_HARDWARE_RED); } - else if (new_element == EL_EMC_WALL_1 || - new_element == EL_EMC_WALL_2 || - new_element == EL_EMC_WALL_3) + else if (IS_GROUP_ELEMENT(new_element)) { - int last_element_new = EL_UNDEFINED; + boolean connected_drawing = FALSE; + int i; - if (last_x == x && last_y == y - 1 && IN_LEV_FIELD(last_x, last_y) && - (IntelliDrawBuffer[last_x][last_y] == EL_EMC_WALL_1 || - IntelliDrawBuffer[last_x][last_y] == EL_EMC_WALL_2 || - IntelliDrawBuffer[last_x][last_y] == EL_EMC_WALL_3)) + for (i = 0; i < NUM_DIRECTIONS; i++) { - if (IN_LEV_FIELD(last_x, last_y - 1)) - { - if (IntelliDrawBuffer[last_x][last_y - 1] != EL_EMC_WALL_1 && - IntelliDrawBuffer[last_x][last_y - 1] != EL_EMC_WALL_2) - last_element_new = EL_EMC_WALL_1; - else if (IntelliDrawBuffer[last_x][last_y - 1] == EL_EMC_WALL_1 || - IntelliDrawBuffer[last_x][last_y - 1] == EL_EMC_WALL_2) - last_element_new = EL_EMC_WALL_2; - } + int xx = x + xy[i][0]; + int yy = y + xy[i][1]; - new_element = EL_EMC_WALL_3; + if (last_x == xx && last_y == yy && IN_LEV_FIELD(last_x, last_y) && + IS_IN_GROUP_EL(IntelliDrawBuffer[last_x][last_y], new_element)) + connected_drawing = TRUE; } - else if (last_x == x && last_y == y + 1 && IN_LEV_FIELD(last_x, last_y) && - (IntelliDrawBuffer[last_x][last_y] == EL_EMC_WALL_1 || - IntelliDrawBuffer[last_x][last_y] == EL_EMC_WALL_2 || - IntelliDrawBuffer[last_x][last_y] == EL_EMC_WALL_3)) - { - if (IN_LEV_FIELD(last_x, last_y + 1)) - { - if (IntelliDrawBuffer[last_x][last_y + 1] != EL_EMC_WALL_2 && - IntelliDrawBuffer[last_x][last_y + 1] != EL_EMC_WALL_3) - last_element_new = EL_EMC_WALL_3; - else if (IntelliDrawBuffer[last_x][last_y + 1] == EL_EMC_WALL_2 || - IntelliDrawBuffer[last_x][last_y + 1] == EL_EMC_WALL_3) - last_element_new = EL_EMC_WALL_2; - } - new_element = EL_EMC_WALL_1; - } + if (!connected_drawing) + ResolveGroupElement(new_element); - if (last_element_new != EL_UNDEFINED) - SetElementSimple(last_x, last_y, last_element_new, change_level); + new_element = GetElementFromGroupElement(new_element); } else if (IS_BELT_SWITCH(old_element)) { @@ -8960,7 +9168,107 @@ static void SetElementIntelliDraw(int x, int y, int new_element, { -1, -1 }, }; - int i; + static int rotatable_elements[][4] = + { + { + EL_BUG_UP, + EL_BUG_RIGHT, + EL_BUG_DOWN, + EL_BUG_LEFT + }, + + { + EL_SPACESHIP_UP, + EL_SPACESHIP_RIGHT, + EL_SPACESHIP_DOWN, + EL_SPACESHIP_LEFT + }, + + { + EL_BD_BUTTERFLY_UP, + EL_BD_BUTTERFLY_RIGHT, + EL_BD_BUTTERFLY_DOWN, + EL_BD_BUTTERFLY_LEFT + }, + + { + EL_BD_FIREFLY_UP, + EL_BD_FIREFLY_RIGHT, + EL_BD_FIREFLY_DOWN, + EL_BD_FIREFLY_LEFT + }, + + { + EL_PACMAN_UP, + EL_PACMAN_RIGHT, + EL_PACMAN_DOWN, + EL_PACMAN_LEFT + }, + + { + EL_YAMYAM_UP, + EL_YAMYAM_RIGHT, + EL_YAMYAM_DOWN, + EL_YAMYAM_LEFT + }, + + { + EL_ARROW_UP, + EL_ARROW_RIGHT, + EL_ARROW_DOWN, + EL_ARROW_LEFT + }, + + { + EL_SP_PORT_UP, + EL_SP_PORT_RIGHT, + EL_SP_PORT_DOWN, + EL_SP_PORT_LEFT + }, + + { + EL_SP_GRAVITY_PORT_UP, + EL_SP_GRAVITY_PORT_RIGHT, + EL_SP_GRAVITY_PORT_DOWN, + EL_SP_GRAVITY_PORT_LEFT + }, + + { + EL_MOLE_UP, + EL_MOLE_RIGHT, + EL_MOLE_DOWN, + EL_MOLE_LEFT + }, + + { + EL_BALLOON_SWITCH_UP, + EL_BALLOON_SWITCH_RIGHT, + EL_BALLOON_SWITCH_DOWN, + EL_BALLOON_SWITCH_LEFT + }, + + { + EL_SP_GRAVITY_ON_PORT_UP, + EL_SP_GRAVITY_ON_PORT_RIGHT, + EL_SP_GRAVITY_ON_PORT_DOWN, + EL_SP_GRAVITY_ON_PORT_LEFT + }, + + { + EL_SP_GRAVITY_OFF_PORT_UP, + EL_SP_GRAVITY_OFF_PORT_RIGHT, + EL_SP_GRAVITY_OFF_PORT_DOWN, + EL_SP_GRAVITY_OFF_PORT_LEFT + }, + + { + -1, + -1, + -1, + -1, + }, + }; + int i, j; for (i = 0; swappable_elements[i][0] != -1; i++) { @@ -8970,6 +9278,20 @@ static void SetElementIntelliDraw(int x, int y, int new_element, if (old_element == element1 || old_element == element2) new_element = (old_element == element1 ? element2 : element1); } + + for (i = 0; rotatable_elements[i][0] != -1; i++) + { + for (j = 0; j < 4; j++) + { + int element = rotatable_elements[i][j]; + + if (old_element == element) + new_element = (button == 1 ? rotatable_elements[i][(j + 3) % 4] : + button == 2 ? rotatable_elements[i][0] : + button == 3 ? rotatable_elements[i][(j + 1) % 4] : + old_element); + } + } } SetElementSimple(x, y, new_element, change_level); @@ -8986,53 +9308,38 @@ static void ResetIntelliDraw() for (y = 0; y < lev_fieldy; y++) IntelliDrawBuffer[x][y] = Feld[x][y]; - SetElementIntelliDraw(-1, -1, EL_UNDEFINED, FALSE); + SetElementIntelliDraw(-1, -1, EL_UNDEFINED, FALSE, -1); } -static void SetElementExt(int x, int y, int element, boolean change_level) +static void SetElementExt(int x, int y, int element, boolean change_level, + int button) { if (element < 0) - { - element = IntelliDrawBuffer[x][y] = Feld[x][y]; - SetElementSimple(x, y, element, change_level); - - return; - } - - if (GetKeyModState() & KMOD_Shift) - SetElementIntelliDraw(x, y, element, change_level); + SetElementSimple(x, y, Feld[x][y], change_level); + else if (GetKeyModState() & KMOD_Shift) + SetElementIntelliDraw(x, y, element, change_level, button); else SetElementSimple(x, y, element, change_level); } static void SetElement(int x, int y, int element) { - SetElementExt(x, y, element, TRUE); + SetElementExt(x, y, element, TRUE, -1); } -static void DrawLineElement(int sx, int sy, int element, boolean change_level) +static void SetElementButton(int x, int y, int element, int button) { -#if 1 - int lx = sx + level_xpos; - int ly = sy + level_ypos; - - SetElementExt(lx, ly, element, change_level); - -#else + SetElementExt(x, y, element, TRUE, button); +} +static void DrawLineElement(int sx, int sy, int element, boolean change_level) +{ int lx = sx + level_xpos; int ly = sy + level_ypos; - int element_new = (element < 0 ? Feld[lx][ly] : element); - - DrawMiniElement(sx, sy, element_new); - if (change_level) - Feld[lx][ly] = element; -#endif + SetElementExt(lx, ly, element, change_level, -1); } -#if 1 - static void DrawLine(int from_x, int from_y, int to_x, int to_y, int element, boolean change_level) { @@ -9054,16 +9361,16 @@ static void DrawLine(int from_x, int from_y, int to_x, int to_y, } else /* diagonal line */ { - int x, y; - if (ysize < xsize) /* a < 1 */ { float a = (float)ysize / (float)xsize; for (i = 0; i <= xsize; i++) { - y = (int)(a * i + 0.5) * dy; - DrawLineElement(from_x + i * dx, from_y + y, element, change_level); + int x = dx * i; + int y = dy * (int)(a * i + 0.5); + + DrawLineElement(from_x + x, from_y + y, element, change_level); } } else /* a >= 1 */ @@ -9072,77 +9379,15 @@ static void DrawLine(int from_x, int from_y, int to_x, int to_y, for (i = 0; i <= ysize; i++) { - x = (int)(a * i + 0.5) * dx; - DrawLineElement(from_x + x, from_y + i * dy, element, change_level); - } - } - } -} - -#else - -static void DrawLine(int from_x, int from_y, int to_x, int to_y, - int element, boolean change_level) -{ - if (from_y == to_y) /* horizontal line */ - { - int x; - int y = from_y; - - if (from_x > to_x) - swap_numbers(&from_x, &to_x); - - for (x = from_x; x <= to_x; x++) - DrawLineElement(x, y, element, change_level); - } - else if (from_x == to_x) /* vertical line */ - { - int x = from_x; - int y; - - if (from_y > to_y) - swap_numbers(&from_y, &to_y); - - for (y = from_y; y <= to_y; y++) - DrawLineElement(x, y, element, change_level); - } - else /* diagonal line */ - { - int len_x = ABS(to_x - from_x); - int len_y = ABS(to_y - from_y); - int x, y; - - if (len_y < len_x) /* a < 1 */ - { - float a = (float)len_y / (float)len_x; - - if (from_x > to_x) - swap_number_pairs(&from_x, &from_y, &to_x, &to_y); - - for (x = 0; x <= len_x; x++) - { - y = (int)(a * x + 0.5) * (to_y < from_y ? -1 : +1); - DrawLineElement(from_x + x, from_y + y, element, change_level); - } - } - else /* a >= 1 */ - { - float a = (float)len_x / (float)len_y; + int x = dx * (int)(a * i + 0.5); + int y = dy * i; - if (from_y > to_y) - swap_number_pairs(&from_x, &from_y, &to_x, &to_y); - - for (y = 0; y <= len_y; y++) - { - x = (int)(a * y + 0.5) * (to_x < from_x ? -1 : +1); DrawLineElement(from_x + x, from_y + y, element, change_level); } } } } -#endif - static void DrawBox(int from_x, int from_y, int to_x, int to_y, int element, boolean change_level) { @@ -9637,6 +9882,10 @@ static void RandomPlacement(int new_element) int num_percentage, num_elements; int x, y; +#if 1 + ResetIntelliDraw(); +#endif + /* determine number of free positions for randomly placing the new element */ for (x = 0; x < lev_fieldx; x++) for (y = 0; y < lev_fieldy; y++) { @@ -9660,20 +9909,28 @@ static void RandomPlacement(int new_element) for (x = 0; x < lev_fieldx; x++) for (y = 0; y < lev_fieldy; y++) if (free_position[x][y]) +#if 1 + SetElement(x, y, new_element); +#else Feld[x][y] = new_element; +#endif } else { while (num_elements > 0) { - x = RND(lev_fieldx); - y = RND(lev_fieldy); + x = GetSimpleRandom(lev_fieldx); + y = GetSimpleRandom(lev_fieldy); /* don't place element at the same position twice */ if (free_position[x][y]) { free_position[x][y] = FALSE; +#if 1 + SetElement(x, y, new_element); +#else Feld[x][y] = new_element; +#endif num_elements--; } } @@ -9842,7 +10099,7 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) } #if 1 - SetElement(lx, ly, new_element); + SetElementButton(lx, ly, new_element, button); #else Feld[lx][ly] = new_element; DrawMiniElement(sx, sy, new_element);