1HedgewarsScriptLoad("/Scripts/Params.lua")
2local overrideFeatureSize = true
3local paramPadding = 0
4local ObjectList = {}
5
6-- Overall padding for roping freedom
7local Padding = 430
8-- If true, rope assumes team color
9local TeamRope = false
10
11function onParameters()
12    parseParams()
13    if params["teamrope"] ~= nil then
14        TeamRope = true
15    end
16    if params["scalemap"] ~= nil then
17        overrideFeatureSize = false
18    end
19    if params["padding"] ~= nil then
20        paramPadding = tonumber(params["padding"])
21    end
22end
23
24function onGearAdd(gear)
25    if GetGearType(gear) == gtRope and TeamRope then
26        SetTag(gear,1)
27        SetGearValues(gear,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,GetClanColor(GetHogClan(CurrentHedgehog)))
28    end
29end
30
31-- This could probably use less points and more precision
32-- 700x700 for object space
33function DrawStar(x, y, d, f)
34    -- default scale is 700x700 or so
35    local s = 700
36    local i = 0
37    local j = 0
38    if not(d == 1) then s = div(s,d) end
39    if NoOverlap(x,y,s,s) then
40        AddCollision(x,y,s,s)
41        if not(d == 1) then
42            i = 6-d
43            j = math.min(div(5,d),1)
44            -- centre
45            AddPoint(x,y,div(20,d))
46            -- arms
47            AddPoint(x-div(325,d),y-f*div(108,d),2)
48            AddPoint(x+div(325,d),y-f*div(108,d))
49            AddPoint(x-div(205,d),y+f*div(270,d))
50            AddPoint(x,y-f*div(345,d))
51            AddPoint(x+div(205,d),y+f*div(270,d))
52            AddPoint(x-div(325,d),y-f*div(108,d))
53            if d < 4 then
54            -- fill in arm 1
55            AddPoint(x-div(275,d),y-f*div(92,d),i)
56            AddPoint(x-div(50,d),y-f*div(92,d))
57            AddPoint(x-div(105,d),y+f*div(25,d))
58            AddPoint(x-div(250,d),y-f*div(80,d))
59            AddPoint(x-div(115,d),y-f*div(70,d))
60            AddPoint(x-div(130,d),y-f*div(25,d))
61            AddPoint(x-div(175,d),y-f*div(60,d))
62            -- fill in arm 2
63            AddPoint(x+div(275,d),y-f*div(92,d),i)
64            AddPoint(x+div(50,d),y-f*div(92,d))
65            AddPoint(x+div(105,d),y+f*div(25,d))
66            AddPoint(x+div(250,d),y-f*div(80,d))
67            AddPoint(x+div(115,d),y-f*div(70,d))
68            AddPoint(x+div(130,d),y-f*div(25,d))
69            AddPoint(x+div(175,d),y-f*div(60,d))
70            -- fill in arm 3
71            AddPoint(x-div(175,d),y+f*div(230,d),i)
72            AddPoint(x-div(110,d),y+f*div(60,d))
73            AddPoint(x,y+f*div(120,d))
74            AddPoint(x-div(155,d),y+f*div(215,d))
75            AddPoint(x-div(105,d),y+f*div(95,d))
76            AddPoint(x-div(60,d),y+f*div(130,d))
77            AddPoint(x-div(85,d),y+f*div(155,d),j)
78            -- fill in arm 4
79            AddPoint(x,y-f*div(300,d),3)
80            AddPoint(x+div(50,d),y-f*div(125,d))
81            AddPoint(x-div(50,d),y-f*div(125,d))
82            AddPoint(x,y-f*div(270,d))
83            AddPoint(x-div(40,d),y-f*div(160,d))
84            AddPoint(x+div(40,d),y-f*div(160,d))
85            AddPoint(x,y-f*div(195,d),j)
86            -- fill in arm 5
87            AddPoint(x+div(175,d),y+f*div(230,d),i)
88            AddPoint(x+div(110,d),y+f*div(60,d))
89            AddPoint(x,y+f*div(120,d))
90            AddPoint(x+div(155,d),y+f*div(215,d))
91            AddPoint(x+div(105,d),y+f*div(95,d))
92            AddPoint(x+div(60,d),y+f*div(130,d))
93            AddPoint(x+div(85,d),y+f*div(155,d),j)
94            end
95        else
96            -- centre
97            AddPoint(x,y,20)
98            -- arms
99            AddPoint(x-325,y-f*108,1)
100            AddPoint(x+325,y-f*108)
101            AddPoint(x-205,y+f*270)
102            AddPoint(x,y-f*345)
103            AddPoint(x+205,y+f*270)
104            AddPoint(x-325,y-f*108)
105            -- fill in arm 1
106            AddPoint(x-275,y-f*92,4)
107            AddPoint(x-50,y-f*92)
108            AddPoint(x-105,y+f*25)
109            AddPoint(x-250,y-f*80)
110            AddPoint(x-115,y-f*70)
111            AddPoint(x-130,y-f*25)
112            AddPoint(x-175,y-f*60)
113            -- fill in arm 2
114            AddPoint(x+275,y-f*92,4)
115            AddPoint(x+50,y-f*92)
116            AddPoint(x+105,y+f*25)
117            AddPoint(x+250,y-f*80)
118            AddPoint(x+115,y-f*70)
119            AddPoint(x+130,y-f*25)
120            AddPoint(x+175,y-f*60)
121            -- fill in arm 3
122            AddPoint(x-175,y+f*230,4)
123            AddPoint(x-110,y+f*60)
124            AddPoint(x-10,y+f*120)
125            AddPoint(x-155,y+f*215)
126            AddPoint(x-105,y+f*95)
127            AddPoint(x-60,y+f*130)
128            AddPoint(x-85,y+f*155,5)
129            -- fill in arm 4
130            AddPoint(x,y-f*300,3)
131            AddPoint(x+50,y-f*125)
132            AddPoint(x-50,y-f*125)
133            AddPoint(x,y-f*270)
134            AddPoint(x-40,y-f*160)
135            AddPoint(x+40,y-f*160)
136            AddPoint(x,y-f*195,5)
137            -- fill in arm 5
138            AddPoint(x+175,y+f*230,4)
139            AddPoint(x+110,y+f*60)
140            AddPoint(x+10,y+f*120)
141            AddPoint(x+155,y+f*215)
142            AddPoint(x+105,y+f*95)
143            AddPoint(x+60,y+f*130)
144            AddPoint(x+85,y+f*155,5)
145        end
146        return true
147    else
148        return false
149    end
150end
151
152-- well. this was easy
153function DrawCircle(x, y, w)
154    if NoOverlap(x,y,w*10+6,w*10+6) then
155        AddCollision(x,y,w*10+6,w*10+6)
156        AddPoint(x,y,w)
157        return true
158    else
159        return false
160    end
161end
162
163function DrawCrescent(x, y, w, s)
164    local b = div(w*(GetRandom(4)+1)*10+6,6)
165
166    if NoOverlap(x,y,w*10+6,w*10+6) then
167        AddCollision(x,y,w*10+6,w*10+6)
168        AddPoint(x,y,w)
169        if s then -- side
170            if GetRandom(1) == 0 then
171                b = b*-1
172            end
173            AddPoint(x-b,y,w,true)
174        else -- top
175            AddPoint(x,y-b,w,true)
176        end
177        return true
178    else
179        return false
180    end
181end
182
183function DrawCones(x,w,h,c)
184    local i = 0
185    local y = 2048-h
186    local hw = div(w,2)
187    if NoOverlap(x+div(w*c,2),y+div(h,2),w*c,h) then
188        AddCollision(x+div(w*c,2),y+div(h,2),w*c,h)
189        x = x + hw
190        for i = 1,c do -- I'm guessing outlining is slightly more efficient than fanning at 16px brush
191            AddPoint(x,y,1)
192            AddPoint(x-hw+8,2048)
193            AddPoint(x+hw-8,2048)
194            AddPoint(x,y)
195            for j = x-hw+25,x+hw,34 do
196                AddPoint(x,y+30,3)
197                AddPoint(j,2048)
198            end
199            if GetRandom(2)==0 then
200                AddPoint(x,y-20,8)
201            end
202            x = x + w
203        end
204    else
205        return false
206    end
207
208end
209
210function DrawPlateau(x,y,l,t,b)
211    local bo = 0
212    local to = 0
213    local bSucc = false
214    local tSucc = false
215    if NoOverlapXY(x-28,y-28,x+l+28,y+l+28) then
216        AddPoint(x,y,5)
217        AddPoint(x+l,y)
218
219        to = GetRandom(6)
220        if not(to==0) then
221            if GetRandom(2)==0 then
222                to = div(l,to)
223            else
224                to = l-div(l,to)
225            end
226        end
227        if t>0 and NoOverlapXY(x+to-28,y-t-28,x+to+28,y+28) then
228            AddPoint(x+to,y-t,5)
229            AddPoint(x+to,y)
230            if GetRandom(2)==0 then
231                AddPoint(x+to,y-t+75,20)
232            else -- square off
233                AddPoint(x+to-20,y-t,1)
234                AddPoint(x+to-20,y-t-20)
235                AddPoint(x+to+20,y-t-20)
236                AddPoint(x+to+20,y-t)
237            end
238            tSucc = true
239        end
240
241        if to > 120 and GetRandom(2)==0 then -- left bumper
242            AddPoint(x+15,y-20,9)
243        else -- square off
244            --AddPoint(x-50,y,2)
245            AddPoint(x,y+20,1)
246            AddPoint(x-20,y+20)
247            AddPoint(x-20,y-20)
248            AddPoint(x,y-20)
249        end
250        if to < (l-120) and GetRandom(2)==0 then -- right bumper
251            AddPoint(x+l-15,y-20,9)
252        else -- square off
253            --AddPoint(x+l+50,y,2)
254            AddPoint(x+l,y+20,1)
255            AddPoint(x+l+20,y+20)
256            AddPoint(x+l+20,y-20)
257            AddPoint(x+l,y-20)
258        end
259        bo = GetRandom(6)
260        if not(bo == 0) then
261            if GetRandom(2)==0 then
262                bo = div(l,bo)
263            else
264                bo = l-div(l,bo)
265            end
266        end
267        -- still consider a success even if we can't place this one.  Might need to return more than true/false
268        if b>0 and NoOverlapXY(x+bo-28,y-28,x+bo+28,y+b+28) then
269            AddPoint(x+bo,y,5)
270            AddPoint(x+bo,y+b)
271            if GetRandom(2)==0 then
272                AddPoint(x+bo,y+b-75,20)
273            else -- square off
274                AddPoint(x+bo-20,y+b,1)
275                AddPoint(x+bo-20,y+b+20)
276                AddPoint(x+bo+20,y+b+20)
277                AddPoint(x+bo+20,y+b)
278            end
279            bSucc = true
280        end
281        if bSucc then AddCollisionXY(x+bo-28,y-28,x+bo+28,y+b+28) end
282        if tSucc then AddCollisionXY(x+to-28,y-t-28,x+to+28,y+28) end
283        AddCollisionXY(x-28,y-28,x+l+28,y+28)
284        return true
285    else
286        return false
287    end
288end
289
290function AddCollision(x,y,w,h)
291    table.insert(ObjectList,{x-div(w+Padding,2),
292                             y-div(h+Padding,2),
293                             x+div(w+Padding,2),
294                             y+div(h+Padding,2)})
295end
296
297function AddCollisionXY(x,y,x2,y2)
298    table.insert(ObjectList,{x-div(Padding,2),
299                             y-div(Padding,2),
300                             x2+div(Padding,2),
301                             y2+div(Padding,2)})
302end
303
304-- bounding box check
305function NoOverlap(x,y,w,h)
306    w = w
307    h = h
308    x = x-div(w,2)
309    y = y-div(h,2)
310    return NoOverlapXY(x,y,x+w,y+h)
311end
312function NoOverlapXY(x,y,x2,y2)
313    local i = 1
314    local l = table.getn(ObjectList)
315    local ox = 0
316    local oy = 0
317    local ox2 = 0
318    local oy2 = 0
319    while i<=l do
320        ox = ObjectList[i][1]
321        oy = ObjectList[i][2]
322        ox2 = ObjectList[i][3]
323        oy2 = ObjectList[i][4]
324        if x < ox2 and ox < x2 and y < oy2 and oy < y2 then
325            return false
326        end
327        i=i+1
328    end
329    return true
330end
331
332function onPreviewInit()
333    onGameInit()
334end
335
336function onGameInit()
337    -- Calculate padding, determined  by map feature size
338	if paramPadding > 0 then
339		Padding = paramPadding
340	elseif MapFeatureSize <= 20 then
341        -- 10 .. 710. Step size=35
342        Padding = 10 + MapFeatureSize * 35
343    else
344        -- 780 .. 1060. Step size=70
345        Padding = 710 + (MapFeatureSize-20) * 70
346    end
347    -- reset feature size after use, to disable scaling
348    if overrideFeatureSize then MapFeatureSize = 12 end
349
350    MapGen = mgDrawn
351    TemplateFilter = 0
352    local TotGen = 0
353    local Tries = 0
354    local i = 0
355    local l = 0
356    local x = 0
357    local y = 0
358    local w = 0
359    local h = 0
360    if GetGameFlag(gfSolidLand) then EnableGameFlags(gfShoppaBorder) end
361    if not GetGameFlag(gfBottomBorder) and GetRandom(2) == 0 then
362        AddPoint(-50,2010,7)
363        AddPoint(4150,2010)
364        for i = 0,GetRandom(3) do
365            x = GetRandom(4096)
366            w = GetRandom(40)+10
367            AddPoint(x,2200,w,true)
368            AddPoint(x,1900)
369            table.insert(ObjectList,{x-div(w*9,2),
370                                     2010-div(100,2),
371                                     x+div(w*9,2),
372                                     2010+div(100,2)})
373        end
374    end
375
376    if GetRandom(2) == 0 then
377        l = GetRandom(3)+1
378        w = GetRandom(200)+200
379        h = GetRandom(350)+200
380        x = GetRandom(4096-w*l)
381        DrawCones(x,w,h,l)
382        --if DrawCones(x,w,h,l) then TotGen = TotGen+1
383    end
384    if GetRandom(2) == 0 then
385        for i = 1,GetRandom(5)+1 do
386            w = GetRandom(35)+15
387            x = GetRandom(4096-w*12)+w
388	    if GetRandom(2)==0 then
389		y = 2048-GetRandom(w*10+6)
390	    else
391	    	y = 2048
392	    end
393           -- if AddPoint(x,y,w) then TotGetn = TotGen+1
394           DrawCircle(x,y,w)
395        end
396    end
397    if GetRandom(2)==0 then
398        x = GetRandom(3300)+382
399        y = GetRandom(1300)+382
400        if DrawStar(x,y, 1, 1+GetRandom(2)*-2) then
401            TotGen = TotGen+1
402        end
403    end
404
405    while (TotGen < 6) and (Tries < 100) do
406        l = GetRandom(1000-Tries*10)+300
407        x = GetRandom(3900-l)+100
408        y = GetRandom(1900)+100
409        if GetRandom(2)==0 then b = GetRandom(800)+300
410        else b = 0 end
411        if GetRandom(2)==0 then t = GetRandom(800)+300
412        else t = 0 end
413        if y-t < 50 then t = y - 50 end
414        if t < 200 then t = 0 end
415        if DrawPlateau(x,y,l,t,b) then
416            TotGen = TotGen+1
417        end
418        Tries = Tries + 1
419    end
420    Tries = 0
421    while (TotGen < 17) and (Tries < 1000) do
422        if Tries < 500 and GetRandom(2)==0 then
423            x = GetRandom(3300)+350
424            y = GetRandom(1300)+350
425            if DrawStar(x,y, 1, 1+GetRandom(2)*-2) then
426                TotGen = TotGen+1
427            end
428        else
429            if Tries > 500 then d = GetRandom(2)+3
430            else d = GetRandom(3)+2 end
431            x = GetRandom(4000-div(764,d))+div(764,d*2)
432            y = GetRandom(1300-div(764,d))+div(764,d*2)
433            if DrawStar(x,y, d, 1+GetRandom(2)*-2) then
434                TotGen = TotGen+1
435            end
436        end
437        w = GetRandom(35-div(Tries,29))+15
438        x = GetRandom(4050-w*20)+w*10
439        y = GetRandom(2000-w*20)+w*10
440        if DrawCircle(x,y,w) then
441            TotGen = TotGen+1
442        end
443        w = GetRandom(35-div(Tries,29))+5
444        x = GetRandom(4050-w*20)+w*10
445        y = GetRandom(2000-w*20)+w*10
446        if DrawCrescent(x,y,w,GetRandom(2)==0) then
447            TotGen = TotGen+1
448        end
449        Tries = Tries + 1
450    end
451    FlushPoints()
452end
453