- Joined
- Aug 7, 2013
- Messages
- 1,338
Hi,
I have a function/algorithm in vJASS which essentially does the following:
1. Takes a rect as input, and divides it up into a random number of predetermined sub rects, from 2 to 5 (2 would be splitting it in half vertically or horizontally, and 5 would be adding a "square" in the middle, which results in five new rects total: the middle piece, the two vertical bars, and the two horizontal bars).
2. Further, if it is passed an integer value iterations, it will perform the algorithm on each of the new rects. Note that while it will always succeed for values 0-2, it can crash (hit OP limit) with increasingly higher probability for n >= 3. I think at 5 it is guaranteed to crash. Did the math awhile back. But I'm not worried about the OP limit.
So now I've sort of described the function, how could I make it smaller? You'll note its a top down solution--it handles every single possible case, which is why it's so "long." But a very simply algorithm. However, the size makes it very annoying to read through and also modify. Too long. Would like to make it smaller if possible.
I have a function/algorithm in vJASS which essentially does the following:
1. Takes a rect as input, and divides it up into a random number of predetermined sub rects, from 2 to 5 (2 would be splitting it in half vertically or horizontally, and 5 would be adding a "square" in the middle, which results in five new rects total: the middle piece, the two vertical bars, and the two horizontal bars).
2. Further, if it is passed an integer value iterations, it will perform the algorithm on each of the new rects. Note that while it will always succeed for values 0-2, it can crash (hit OP limit) with increasingly higher probability for n >= 3. I think at 5 it is guaranteed to crash. Did the math awhile back. But I'm not worried about the OP limit.
So now I've sort of described the function, how could I make it smaller? You'll note its a top down solution--it handles every single possible case, which is why it's so "long." But a very simply algorithm. However, the size makes it very annoying to read through and also modify. Too long. Would like to make it smaller if possible.
JASS:
method partitionAlg takes integer iterations returns nothing
local real subMinX
local real subMaxX
local real subMinY
local real subMaxY
local real subArea
local real x
local real y
local rect r
local real midPoint
local integer i = 0
local integer j = 0
local integer side = 0
//determine where the first rectangle goes
local integer firstPos = GetRandomInt(ZERO_SIDES, THREE_SIDES)
if firstPos == ZERO_SIDES then
set r = Rect(minX + DIST_FROM_EDGE, minY + DIST_FROM_EDGE, maxX - DIST_FROM_EDGE, maxY - DIST_FROM_EDGE)
set subQuads[i] = Quad.create(rectInsideRect((rectArea(r) * 0.25), r))
call subQuads[i].highlight()
call RemoveRect(r)
set r = null
set i = i + 1
//now we need to add 4 rectangles to cover up the remaining area
//two solutions
//1) horizontal bars on top/bottom, and vertical bars left/right
//2) vertical bars on top/bottom, and horiztonal bars top/bottom
if GetRandomInt(0, 1) == 0 then //horizontal bars
//top bar
set subMinX = minX
set subMaxX = maxX
set subMinY = subQuads[FIRST].maxY
set subMaxY = maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
//bottom bar
set subMinX = minX
set subMaxX = maxX
set subMinY = minY
set subMaxY = subQuads[FIRST].minY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
//left bar
set subMinX = minX
set subMaxX = subQuads[FIRST].minX
set subMinY = subQuads[FIRST].minY
set subMaxY = subQuads[FIRST].maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
//right bar
set subMinX = subQuads[FIRST].maxX
set subMaxX = maxX
set subMinY = subQuads[FIRST].minY
set subMaxY = subQuads[FIRST].maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
else
//left bar
set subMinX = minX
set subMaxX = subQuads[FIRST].minX
set subMinY = minY
set subMaxY = maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
//right bar
set subMinX = subQuads[FIRST].maxX
set subMaxX = maxX
set subMinY = minY
set subMaxY = maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
//top bar
set subMinX = subQuads[FIRST].minX
set subMaxX = subQuads[FIRST].maxX
set subMinY = subQuads[FIRST].maxY
set subMaxY = maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
//bottom bar
set subMinX = subQuads[FIRST].minX
set subMaxX = subQuads[FIRST].maxX
set subMinY = minY
set subMaxY = subQuads[FIRST].minY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
endif
elseif firstPos == ONE_SIDE then
set subArea = GetRandomReal(area * 0.125, area * 0.20)
set side = GetRandomInt(LEFT, BOTTOM)
if side == LEFT then
set subMinX = minX
set subMaxX = minX + SquareRoot(subArea)
set midPoint = minY + ((maxY - minY) / 2)
set subMaxY = midPoint + 0.5 * SquareRoot(subArea)
set subMinY = midPoint - 0.5 * SquareRoot(subArea)
elseif side == RIGHT then
set subMaxX = maxX
set subMinX = maxX - SquareRoot(subArea)
set midPoint = minY + ((maxY - minY) / 2)
set subMaxY = midPoint + 0.5 * SquareRoot(subArea)
set subMinY = midPoint - 0.5 * SquareRoot(subArea)
elseif side == TOP then
set subMaxY = maxY
set subMinY = maxY - SquareRoot(subArea)
set midPoint = minX + ((maxX - minX) / 2)
set subMaxX = midPoint + 0.5 * SquareRoot(subArea)
set subMinX = midPoint - 0.5 * SquareRoot(subArea)
else
set subMinY = minY
set subMaxY = minY + SquareRoot(subArea)
set midPoint = minX + ((maxX - minX) / 2)
set subMaxX = midPoint + 0.5 * SquareRoot(subArea)
set subMinX = midPoint - 0.5 * SquareRoot(subArea)
endif
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
if side == LEFT then
if GetRandomInt(0, 1) == 0 then
//top square
set subMinX = minX
set subMaxX = subQuads[FIRST].maxX
set subMinY = subQuads[FIRST].maxY
set subMaxY = maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
//bottom square
set subMinX = minX
set subMaxX = subQuads[FIRST].maxX
set subMinY = minY
set subMaxY = subQuads[FIRST].minY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
//right rectangle
set subMinX = subQuads[FIRST].maxX
set subMaxX = maxX
set subMinY = minY
set subMaxY = maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
else
//top rectangle
set subMinX = minX
set subMaxX = maxX
set subMinY = subQuads[FIRST].maxY
set subMaxY = maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
//bottom rectangle
set subMinX = minX
set subMaxX = maxX
set subMinY = minY
set subMaxY = subQuads[FIRST].minY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
//middle rectangle
set subMinX = subQuads[FIRST].maxX
set subMaxX = maxX
set subMinY = subQuads[FIRST].minY
set subMaxY = subQuads[FIRST].maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
endif
elseif side == RIGHT then
if GetRandomInt(0, 1) == 0 then
//top square
set subMinX = subQuads[FIRST].minX
set subMaxX = maxX
set subMinY = subQuads[FIRST].maxY
set subMaxY = maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
//bottom square
set subMinX = subQuads[FIRST].minX
set subMaxX = maxX
set subMinY = minY
set subMaxY = subQuads[FIRST].minY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
//left rectangle
set subMinX = minX
set subMaxX = subQuads[FIRST].minX
set subMinY = minY
set subMaxY = maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
else
//top rectangle
set subMinX = minX
set subMaxX = maxX
set subMinY = subQuads[FIRST].maxY
set subMaxY = maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
//bottom rectangle
set subMinX = minX
set subMaxX = maxX
set subMinY = minY
set subMaxY = subQuads[FIRST].minY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
//middle rectangle
set subMinX = minX
set subMaxX = subQuads[FIRST].minX
set subMinY = subQuads[FIRST].minY
set subMaxY = subQuads[FIRST].maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
endif
elseif side == TOP then
if GetRandomInt(0, 1) == 0 then
//left rectangle
set subMinX = minX
set subMaxX = subQuads[FIRST].minX
set subMinY = minY
set subMaxY = maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
//right rectangle
set subMinX = subQuads[FIRST].maxX
set subMaxX = maxX
set subMinY = minY
set subMaxY = maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
//middle rectangle
set subMinX = subQuads[FIRST].minX
set subMaxX = subQuads[FIRST].maxX
set subMinY = minY
set subMaxY = subQuads[FIRST].minY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
else
//left square
set subMinX = minX
set subMaxX = subQuads[FIRST].minX
set subMinY = subQuads[FIRST].minY
set subMaxY = maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
//right square
set subMinX = subQuads[FIRST].maxX
set subMaxX = maxX
set subMinY = subQuads[FIRST].minY
set subMaxY = maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
//middle rectangle
set subMinX = minX
set subMaxX = maxX
set subMinY = minY
set subMaxY = subQuads[FIRST].minY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
endif
elseif side == BOTTOM then
if GetRandomInt(0, 1) == 0 then
//left rectangle
set subMinX = minX
set subMaxX = subQuads[FIRST].minX
set subMinY = minY
set subMaxY = maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
//right rectangle
set subMinX = subQuads[FIRST].maxX
set subMaxX = maxX
set subMinY = minY
set subMaxY = maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
//middle rectangle
set subMinX = subQuads[FIRST].minX
set subMaxX = subQuads[FIRST].maxX
set subMinY = subQuads[FIRST].maxY
set subMaxY = maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
else
//left square
set subMinX = minX
set subMaxX = subQuads[FIRST].minX
set subMinY = subQuads[FIRST].minY
set subMaxY = subQuads[FIRST].maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
//right square
set subMinX = subQuads[FIRST].maxX
set subMaxX = maxX
set subMinY = subQuads[FIRST].minY
set subMaxY = subQuads[FIRST].maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
//middle rectangle
set subMinX = minX
set subMaxX = maxX
set subMinY = subQuads[FIRST].maxY
set subMaxY = maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
endif
endif
elseif firstPos == TWO_SIDES then
set subArea = GetRandomReal(area * 0.125, area * 0.20)
set side = GetRandomInt(LEFT, VERTICAL)
if side == LEFT then //bottom left corner
set subMinY = minY
set subMinX = minX
set subMaxY = minY + SquareRoot(subArea)
set subMaxX = minX + SquareRoot(subArea)
elseif side == RIGHT then //top right corner
set subMaxY = maxY
set subMaxX = maxX
set subMinY = maxY - SquareRoot(subArea)
set subMinX = maxX - SquareRoot(subArea)
elseif side == TOP then //top left corner
set subMaxY = maxY
set subMinX = minX
set subMinY = maxY - SquareRoot(subArea)
set subMaxX = minX + SquareRoot(subArea)
elseif side == BOTTOM then //bottom right corner
set subMaxX = maxX
set subMinY = minY
set subMinX = maxX - SquareRoot(subArea)
set subMaxY = minY + SquareRoot(subArea)
elseif side == HORIZONTAL then
set subMinX = minX
set subMaxX = maxX
set midPoint = minY + ((maxY - minY) / 2)
set subMaxY = midPoint + 0.5 * (subArea / (maxX - minX))
set subMinY = midPoint - 0.5 * (subArea / (maxX - minX))
else //side == VERTICAL
set subMinY = minY
set subMaxY = maxY
set midPoint = minX + ((maxX - minX) / 2)
set subMaxX = midPoint + 0.5 * (subArea / (maxY - minY))
set subMinX = midPoint - 0.5 * (subArea / (maxY - minY))
endif
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
if side == LEFT then
if GetRandomInt(0, 1) == 0 then
//top rectangle
set subMinX = minX
set subMaxX = maxX
set subMinY = subQuads[FIRST].maxY
set subMaxY = maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
//bottom rectangle
set subMinX = subQuads[FIRST].maxX
set subMaxX = maxX
set subMinY = minY
set subMaxY = subQuads[FIRST].maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
else
//left bar
set subMinX = minX
set subMaxX = subQuads[FIRST].maxX
set subMinY = subQuads[FIRST].maxY
set subMaxY = maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
//right bar
set subMinX = subQuads[FIRST].maxX
set subMaxX = maxX
set subMinY = minY
set subMaxY = maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
endif
elseif side == RIGHT then
if GetRandomInt(0, 1) == 0 then
//top rectangle
set subMinX = minX
set subMaxX = subQuads[FIRST].minX
set subMinY = subQuads[FIRST].minY
set subMaxY = maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
//bottom rectangle
set subMinX = minX
set subMaxX = maxX
set subMinY = minY
set subMaxY = subQuads[FIRST].minY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
else
//left bar
set subMinX = minX
set subMaxX = subQuads[FIRST].minX
set subMinY = minY
set subMaxY = maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
//right bar
set subMinX = subQuads[FIRST].minX
set subMaxX = maxX
set subMinY = minY
set subMaxY = subQuads[FIRST].minY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
endif
elseif side == TOP then
if GetRandomInt(0, 1) == 0 then
//top rectangle
set subMinX = subQuads[FIRST].maxX
set subMaxX = maxX
set subMinY = subQuads[FIRST].minY
set subMaxY = maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
//bottom rectangle
set subMinX = minX
set subMaxX = maxX
set subMinY = minY
set subMaxY = subQuads[FIRST].minY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
else
//left bar
set subMinX = minX
set subMaxX = subQuads[FIRST].maxX
set subMinY = minY
set subMaxY = subQuads[FIRST].minY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
//right bar
set subMinX = subQuads[FIRST].maxX
set subMaxX = maxX
set subMinY = minY
set subMaxY = maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
endif
elseif side == BOTTOM then
if GetRandomInt(0, 1) == 0 then
//top rectangle
set subMinX = minX
set subMaxX = maxX
set subMinY = subQuads[FIRST].maxY
set subMaxY = maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
//bottom rectangle
set subMinX = minX
set subMaxX = subQuads[FIRST].minX
set subMinY = minY
set subMaxY = subQuads[FIRST].maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
else
//left bar
set subMinX = minX
set subMaxX = subQuads[FIRST].minX
set subMinY = minY
set subMaxY = maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
//right bar
set subMinX = subQuads[FIRST].minX
set subMaxX = maxX
set subMinY = subQuads[FIRST].maxY
set subMaxY = maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
endif
elseif side == HORIZONTAL then
//top rectangle
set subMinX = minX
set subMaxX = maxX
set subMinY = subQuads[FIRST].maxY
set subMaxY = maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
//bottom rectangle
set subMinX = minX
set subMaxX = maxX
set subMinY = minY
set subMaxY = subQuads[FIRST].minY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
elseif side == VERTICAL then
//left bar
set subMinX = minX
set subMaxX = subQuads[FIRST].minX
set subMinY = minY
set maxY = maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
//right bar
set subMinX = subQuads[FIRST].maxX
set subMaxX = maxX
set subMinY = minY
set maxY = maxY
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
endif
elseif firstPos == THREE_SIDES then
set subArea = GetRandomReal(area * 0.125, area * 0.20)
set side = GetRandomInt(HORIZONTAL, VERTICAL)
if side == HORIZONTAL then
set subMinX = minX
set subMaxX = maxX
if GetRandomInt(0, 1) == 0 then
set subMinY = minY
set subMaxY = (((subArea + (subMaxX * subMinY)) - (subMinX * subMinY)) / (subMaxX - subMinX))
else
set subMaxY = maxY
set subMinY = (((subArea - (subMaxX * subMaxY)) + (subMaxY * subMinX)) / (subMinX - subMaxX))
endif
elseif side == VERTICAL then
set subMinY = minY
set subMaxY = maxY
if GetRandomInt(0, 1) == 0 then
set subMinX = minX
set subMaxX = (((subArea + (subMaxY * subMinX)) - (subMinX * subMinY)) / (subMaxY - subMinY))
else
set subMaxX = maxX
set subMinX = maxX - (subArea / (maxY - minY))
endif
endif
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
if side == HORIZONTAL then
if subQuads[FIRST].maxY == maxY then
set subMinX = minX
set subMaxX = maxX
set subMinY = minY
set subMaxY = subQuads[FIRST].minY
else
set subMinX = minX
set subMaxX = maxX
set subMinY = subQuads[FIRST].maxY
set subMaxY = maxY
endif
else
if subQuads[FIRST].minX == minX then
set subMinX = subQuads[FIRST].maxX
set subMaxX = maxX
set subMinY = minY
set subMaxY = maxY
else
set subMinX = minX
set subMaxX = subQuads[FIRST].minX
set subMinY = minY
set subMaxY = maxY
endif
endif
set subQuads[i] = Quad.create(Rect(subMinX, subMinY, subMaxX, subMaxY))
call subQuads[i].highlight()
set i = i + 1
endif
if iterations > 0 then
loop
exitwhen j == i
call subQuads[j].partitionAlg(iterations - 1)
set j = j + 1
endloop
endif
endmethod