Broken Circle: need feedback (and cheats)


#1

Hi, adventurers!

Here is the new level for the experienced heroes: Broken Circles I made this level a few weeks ago, but I wasn’t sure how to solve it. Now I know how to do it. So the level will be on the Glacier map soon.

I would like to ask your opinion about this level. Also, I’ll be grateful if you share about cheats for this level.

I tried several solutions for this level. As the result, my final solution isn’t so complex as I thought (and much simpler than first ones).


#2

I found one problem. isPathClear method return true ignoring 3 step radius of mine exsplosion.

trapAttackRange = 3;
radiusStep = 10;
center = {"x": 68, "y": 68};
# Бегоооом, марш!
while True:
    direction = Vector.subtract(Vector(center.x, center.y), hero.pos)
    direction = Vector.multiply(Vector.normalize(direction), (radiusStep-trapAttackRange)/2)
    move = Vector.add(hero.pos, direction)    
    if(hero.isPathClear(hero.pos, move)):        
        hero.move(move)
    else:
        direction = Vector.rotate(direction, Math.PI/2)
        move = Vector.add(hero.pos, direction) 
        hero.move(move)

#3

Nope. It’s normal behaviour. isPathClear checks only obstacles. attackRange of an unit (the trap is an unit) is not an obstacle.


#4

I think better to use wall, not mines.


#5

That’s why I used traps :wink:


#6

Ok. For me its meens that I need to write additional function, to check this. I’ll write when finish.


#7

Ok. I just try to walk by the circle, but it seems, that circle not perfect.
http://clip2net.com/s/3B5bC3M

hero.moveXY(122, 66)
way = Vector.subtract(center, hero.pos)
normal = Vector.normalize(way)
direction = Vector.multiply(normal, trapAttackRange+1)
direction = Vector.rotate(direction, Math.PI/2)
move = Vector.add(hero.pos, direction)    
hero.move(move)

#8

Second try

center = Vector(center.x, center.y)
angle = 0
while True:     
    way = Vector.subtract(hero.pos, center)        
    normal = Vector.normalize(way)   
    normal = Vector.rotate(normal, angle)
    direction = Vector.multiply(normal, radiusStep*5 + trapAttackRange+2) 
    move = Vector.add(center, direction)   
    hero.move(move)
    angle -= 0.002

http://clip2net.com/s/3B5yUni


#9

i jumped using okar stompfoot to trigger the traps, but he doesn’t launch him enough to cause the fangriders to attack him. Easy win :grinning:


#10

It’s because {122,68} is not ‘angle == 0’ . Use 122, 68. I use sin and cos to form circles.


#11

Thanks, Tom. I’ll fix that cheat.


#12

@Tom_H: Okar’s stomp doesn’t change pos.z so it doesn’t count as a jump. But I increased the power of traps, so now they have 20 metres blow radius and stomp has 15 metres.


#13

My circles. Math.sin and Math.cos:


#14

Hey, here’s one exploit.

Pender equipped with Boots of Leaping, Elemental Codex V and The Precious.

center = {"x": 68, "y": 68};

# Go, Go, GO!
hero.cast("haste", hero)
hero.moveXY(123, 67)
hero.jumpTo({ 'x': 0, 'y': 67 })
hero.cast("invisibility", hero)
hero.moveXY(center.x, center.y)

You can watch my game session here.


I just found yet another exploit.

This time using Pender with Vine Staff, Elemental Codex V and The Precious.

hero.cast("haste", hero)

# call moveXY twice to disable inertia effect
for i in range(2):
    hero.moveXY(128, 61)

# Summoning burl will lure the fangriders.
# The Burl will step on a trap and explode itself together with all the fangriders.
hero.cast("summon-burl")

# Hide from the explosions and enemy fire
hero.moveXY(154, 64)
hero.cast("invisibility", hero)

# All the traps have exploded by now, collect the treasure :D
hero.moveXY(center.x, center.y)

#15

I solved the cheats. The new rule - No magic.


#16

Oh noes! Does this mean I should solve the level for real now? Or maybe I could just find another exploit…

Well, turns out it was easy enough to patch the first exploit—a single jump is enough to cheat this level even without any magic.

Here’s my game session again.

hero.moveXY(122.2, 67)
hero.jumpTo({ 'x': 0, 'y': 67 })
hero.wait(2.2)
for direction in (1, -1):
    for i in range(5):
        hero.moveXY(hero.pos.x + .4 * direction, hero.pos.y)
        hero.wait(.1)

#17

Thanks! I know how to fix it. Will do it today.


#18

I added the power engine for jumps. Now each jump will be really high :wink:

Thanks for the exploits. I’m grateful for your help.


#19

No problem. Nice work fixing these so quickly! :smile:

Not sure if I understand. The jumps seem smaller now, but the jump exploit is still doable.

Game session.

center = Vector(68, 68)

#
# Exploit #1.2
#
hero.moveXY(125, 65)
hero.moveXY(116, 40)
hero.moveXY(100, 22)
hero.moveXY(76, 12)

hero.jumpTo(center.copy().subtract(hero.pos).multiply(.5).add(hero.pos)) # Why didn't I just hardcode the value?
for i in range(2): # Move twice to disable inertia
    hero.moveXY(73.5, 34)

while not hero.isReady("jump"):
    hero.wait(.1)

nextJump = Vector(69, 53)
hero.jumpTo(nextJump.copy().subtract(hero.pos).multiply(1.3).add(hero.pos))
for i in range(2): # Disable inertia
    hero.moveXY(nextJump.x, nextJump.y)

while not hero.isReady("jump"):
    hero.wait(.1)

hero.jumpTo(center)

#20

I added the trap exploding when a hero jumps instead the attack of the guards.

Looks like small jumps don’t trigger the alarm. it’s because I use something like this:

# first frame
@startPosZ = @hero.pos.z + diff # about 0.5
...
if @hero.pos.z > @startPosZ
    @blown()

Without diff can be an occasional exploding.

Thanks. I have one idea how to close that cheat.

You are really good in the cheat/bug search.