Skip to content

Conversation

@bwhmather
Copy link

I'm sorry for dumping such an ugly patch. It's for demonstration only.

Basic outline of what's going on (it's probably more clear from looking at the Ship class in turtlepower.asteroids):

  • The student script is just a string which gets evaluated once by the turtle at startup.
  • The turtle passes in a proxy to itself with overpowered methods (sort of) hidden and whatever utility functions might be needed.
  • Running the user script only once and forcing them to manually bind the update callback means that state can be saved in a closure. We could probably clear all callbacks when replacing the script.
  • Some things (like the turtle.distance method) don't really make sense without self and there needs to be a better way of deciding what methods to expose (@expose + @expose\n@staticmethod decorators?)

That's about it. What does everyone think?

@bloodearnest
Copy link
Member

Havn't had chance to look at this yet, but commenting to let you know there's a google group at https://groups.google.com/forum/#!forum/turtle-power-python if you wanna sign up for more discussion - most of the other sprinters have

@bwhmather
Copy link
Author

Excellent. Will move over there once I'm done with work

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, so the idea is to only expose limited apis?

Not sure I get this. The student is supposed to write the ship method. This example is just how I wrote it in an hour or so, there's other ways to do it. True, the teacher might choose to provide a rocket class or similar, but I'd want them to be able to build it all from scratch. E.g. first, an asteroid turtle, then a ship turtle, then a rocket turtle. We won't know in advance what methods they will write.

Also, the turn_towards, xcor, ycor, etc methods are part of the stdlib turtle interface, not specific to this game, and I would want them on every single turtle, not per world. It's up for the student to decide what they need to do.

Although, I do think update() is a bit better that callback() as a name.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a string just above called script which contains the students
code. The proxy object just limits the api so that you can keep things
competitive! There is no reason why the next level can't be making your
own game.
On 26 Sep 2013 20:35, "Simon Davy" notifications@github.com wrote:

In turtlepower/asteroids.py:

@@ -52,8 +93,23 @@ def setup(self):
self.setheading(90)
self.dead = False
self.rocket = None

  •    self.__range = 200
    
  •    self.state = "shooting"
    
  •    self.range = 200
    
  •    self._update_callback = None
    
  •    ship = Proxy(self, {
    
  •        'fire', 'range',
    
  •        'turn_towards', 'towards', 'forward',
    
  •        'xcor', 'ycor', 'distance',
    
  •        'on_update',
    
  •    })
    

Ok, so the idea is to only expose limited apis?

Not sure I get this. The student is supposed to write the ship method.
This example is just how I wrote it in an hour or so, there's other ways to
do it. True, the teacher might choose to provide a rocket class or similar,
but I'd want them to be able to build it all from scratch. E.g. first, an
asteroid turtle, then a ship turtle, then a rocket turtle. We won't know in
advance what methods they will write.

Also, the turn_towards, xcor, ycor, etc methods are part of the stdlib
turtle interface, not specific to this game, and I would want them on every
single turtle, not per world. It's up for the student to decide what they
need to do.

Although, I do think update() is a bit better that callback() as a name.


Reply to this email directly or view it on GitHubhttps://github.com//pull/19/files#r6611819
.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I saw the string - I was commenting ion the 'fire' method you provided.

Regards keeping it competitive, I think it may be confusing that the current implementation in turtlepower is incorrect. setposition/setx/sety do not teleport you in the stdlib module - they animate your path to that coord. That is TurtlePower will do too (very soon, once we start using NinjaTurtle as out turtle impl). So there is no way to teleport, at least - that's an artifact of current implementation that is incorrect.

Regards, other forms of cheating - that would be enforce by change the methods of the base turtle type for that world. e.g. for a grid world with only 90 deg changes allowed, it would coerce them to the nearest 90.

e.g.

class GridTurtle(PowerTurtle):
    def left(self, angle=90):
        angle = angle % 360
        if angle is None or angle <=90
            angle = 90
        elif angle <= 180:
            angle = 180
        elif angle <= 270:
            angle = 270
        else:
            return
        super(GridTurtle).left(angle)

@bloodearnest
Copy link
Member

So here's sort of what I'd imaging it'd look like in my head.

There'd be one file/script per turtle, a rough example of the asteroid

Asteroid script

# initialisation code
set_type('asteroid')
hideturtle()
setposition(...random...) # probably have helper for this.
setheading(...random...)
color('brown')
shape('circle')
speed(...random..)

radius = ...random...
shapesize(radius)

ship = world.get_first_turtle(type='ship')
alive = True

def explode(rocket):
    world.remove_turtle(rocket)
    alive = False
    exit()

def update():
    if distance(ship) < radius:  # more advanced api: if collided_with(ship):
        ship.die()
    rockets = world.get_turtles(type='rocket')
    for rocket in rockets:
        if distance(rocket) < radius:
            explode()
    if alive:
        forward()

In the above, all symbols save 'world' are just the bound methods of the appropriate PowerTurtle instance. The only new api's used that are not part of the stdlib turtle interface are 'exit' and 'set_type'

This script would be loaded as a function body with preloaded locals() (or func_closure/closure) to include the turtle's bare methods, pre-bound. The update and explode method definitions could be updated if changed, although the init code probably shouldn't be, perhaps.

If we assume a gui, we could even split these up into two separate windows/tabs - "Setup" for the init code and explode func, and "Update" for the update function code. That would give us more freedom about how we dynamically load/reload them.

@bwhmather
Copy link
Author

I think we are both arguing for the same thing here which is probably good.

I'm just using exec on line 109 to run the user script with the globals dict containing some utility functions and a reference to the turtle with game breaking methods hidden. This acheives basically the same thing as copying the script into a function body. The student code is currently loaded from the hard coded script string but could be loaded from a file or window.

I've left some of the initalisation code in Ship.setup as I don't think it makes sense for the ai code to be able to change the appearance of the ship.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants