X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Feditor.c;h=d85d56655fa9f09967f10022b9dbad8fd6264f40;hb=097cb899f2c98e2f300e081dd09d7db8b0f636a5;hp=632d7155b53d80f12607688d91f896a1cb357de6;hpb=5c51379382ab3d349e17ae6988eb80b3c2f9da3f;p=rocksndiamonds.git diff --git a/src/editor.c b/src/editor.c index 632d7155..d85d5665 100644 --- a/src/editor.c +++ b/src/editor.c @@ -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,38 @@ 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); } @@ -8512,10 +8554,12 @@ static int getClosedTube(int x, int y) 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); @@ -8523,7 +8567,7 @@ static int getClosedBelt(int x, int y) int belt_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]; @@ -8570,20 +8614,78 @@ static int getClosedPool(int x, int y) return getPoolFromOpenDirectionNotEmpty(pool_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 pillar_direction_old = getOpenDirectionFromPillar(element_old); + int pillar_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]) && + (pillar_direction_old & dir) && + (getOpenDirectionFromPillar(IntelliDrawBuffer[xx][yy]) & dir_opposite)) + pillar_direction_new |= dir; + } + + return getPillarFromOpenDirectionNotEmpty(pillar_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); +} + +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); - if (IN_ED_FIELD(x - level_xpos, y - level_ypos)) - DrawMiniElement(x - level_xpos, y - level_ypos, element); + /* 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) { + 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,13 +8700,6 @@ 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; @@ -8635,6 +8730,12 @@ static void SetElementIntelliDraw(int x, int y, int new_element, new_element = getTubeFromOpenDirectionNotEmpty(direction, new_element); +#if 1 + if (last_element_new != EL_UNDEFINED) + MergeAndCloseNeighbourElements(x, y, &new_element, + last_x, last_y, &last_element_new, + getClosedTube, change_level); +#else /* reduce connections of neighbour tube elements to minimal connections */ if (last_element_new != EL_UNDEFINED) { @@ -8650,17 +8751,69 @@ static void SetElementIntelliDraw(int x, int y, int new_element, SetElementSimple(x, y, new_element, change_level); SetElementSimple(last_x, last_y, last_element_new, change_level); } +#endif } - else if (IS_ACID_POOL_OR_ACID(new_element)) + 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 existing element is belt, keep all existing belt directions */ + if (IS_BELT(old_element)) + direction |= getOpenDirectionFromBelt(old_element); + + for (i = MV_BIT_LEFT; i <= MV_BIT_RIGHT; i++) + { + 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_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; + + last_element_new = getBeltFromNrAndOpenDirection(last_belt_nr, + last_direction_new); + + direction |= dir; + } + } + + new_element = getBeltFromNrAndOpenDirectionNotEmpty(belt_nr, direction, + new_element); + #if 1 - static int xy[4][2] = + if (last_element_new != EL_UNDEFINED) + MergeAndCloseNeighbourElements(x, y, &new_element, + last_x, last_y, &last_element_new, + getClosedBelt, change_level); +#else + /* reduce connections of neighbour belt elements to minimal connections */ + if (last_element_new != EL_UNDEFINED) { - { -1, 0 }, - { +1, 0 }, - { 0, -1 }, - { 0, +1 } - }; + /* 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); + + /* remove all open belt connections of neighbour belt elements */ + new_element = getClosedBelt(x, y); + last_element_new = getClosedBelt(last_x, last_y); + + /* 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); + } +#endif + } + else if (IS_ACID_POOL_OR_ACID(new_element)) + { int last_element_new = EL_UNDEFINED; int direction = MV_NONE; int i; @@ -8704,6 +8857,12 @@ static void SetElementIntelliDraw(int x, int y, int new_element, new_element = getPoolFromOpenDirectionNotEmpty(direction, new_element); #endif +#if 1 + if (last_element_new != EL_UNDEFINED) + MergeAndCloseNeighbourElements(x, y, &new_element, + last_x, last_y, &last_element_new, + getClosedPool, change_level); +#else /* reduce connections of neighbour pool elements to minimal connections */ if (last_element_new != EL_UNDEFINED) { @@ -8719,189 +8878,62 @@ static void SetElementIntelliDraw(int x, int y, int new_element, SetElementSimple(x, y, new_element, change_level); SetElementSimple(last_x, last_y, last_element_new, change_level); } - -#else - - int last_element_new = EL_UNDEFINED; - - if (IS_ACID_POOL(old_element)) - new_element = 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])) - { - 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 - { - last_element_new = EL_ACID; - new_element = EL_ACID; - } - } - - if (last_element_new != EL_UNDEFINED) - SetElementSimple(last_x, last_y, last_element_new, change_level); #endif } - else if (IS_BELT(new_element)) + else if (IS_EMC_PILLAR(new_element)) { int last_element_new = EL_UNDEFINED; + int direction = MV_NONE; + int i; + + /* if existing element is pillar, keep all existing pillar directions */ + if (IS_EMC_PILLAR(old_element)) + direction |= getOpenDirectionFromPillar(old_element); - 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])) + for (i = MV_BIT_UP; i <= MV_BIT_DOWN; 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]; + + 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; - new_element = belt_middle; - last_element_new = belt_middle; + last_element_new = getPillarFromOpenDirection(last_direction_new); + + direction |= dir; + } } - /* reduce connections of neighbour belt elements to minimal connections */ + new_element = getPillarFromOpenDirectionNotEmpty(direction, new_element); + +#if 1 + if (last_element_new != EL_UNDEFINED) + MergeAndCloseNeighbourElements(x, y, &new_element, + last_x, last_y, &last_element_new, + getClosedPillar, change_level); +#else + /* reduce connections of neighbour pillar elements to minimal connections */ if (last_element_new != EL_UNDEFINED) { - /* set neighbour belt elements to newly determined belt connections */ + /* set neighbour pillar elements to newly determined pillar connections */ SetElementSimple(x, y, new_element, change_level); SetElementSimple(last_x, last_y, last_element_new, change_level); - /* remove all open belt connections of neighbour belt elements */ - new_element = getClosedBelt(x, y); - last_element_new = getClosedBelt(last_x, last_y); + /* remove all open pillar connections of neighbour pillar elements */ + new_element = getClosedPillar(x, y); + last_element_new = getClosedPillar(last_x, last_y); - /* set neighbour belt elements to new, minimized belt connections */ + /* set neighbour pillar elements to new, minimized pillar connections */ SetElementSimple(x, y, new_element, change_level); SetElementSimple(last_x, last_y, last_element_new, change_level); } - } - else if (new_element == EL_EMC_WALL_1 || - new_element == EL_EMC_WALL_2 || - new_element == EL_EMC_WALL_3) - { - int last_element_new = EL_UNDEFINED; - - 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_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; - } - - new_element = EL_EMC_WALL_3; - } - 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 (last_element_new != EL_UNDEFINED) - SetElementSimple(last_x, last_y, last_element_new, change_level); +#endif } else if (IS_BELT_SWITCH(old_element)) { @@ -8992,14 +9024,8 @@ static void ResetIntelliDraw() static void SetElementExt(int x, int y, int element, boolean change_level) { if (element < 0) - { - element = IntelliDrawBuffer[x][y] = Feld[x][y]; - SetElementSimple(x, y, element, change_level); - - return; - } - - if (GetKeyModState() & KMOD_Shift) + SetElementSimple(x, y, Feld[x][y], change_level); + else if (GetKeyModState() & KMOD_Shift) SetElementIntelliDraw(x, y, element, change_level); else SetElementSimple(x, y, element, change_level); @@ -9012,27 +9038,12 @@ static void SetElement(int x, int y, int element) static void DrawLineElement(int sx, int sy, int element, boolean change_level) { -#if 1 int lx = sx + level_xpos; int ly = sy + level_ypos; SetElementExt(lx, ly, element, change_level); - -#else - - 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 } -#if 1 - static void DrawLine(int from_x, int from_y, int to_x, int to_y, int element, boolean change_level) { @@ -9054,16 +9065,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 +9083,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) {