I need help on Hunting Party

Whenever I command my soldiers to move forward, half of them get stuck and go backwards, the other half go through the wrong lane, then stop working. Here is my code:

friends = self.findFriends()


loop:
    for friend in friends:
        enemy = friend.findNearest(self.findEnemies())
        if not enemy:
            self.command(friend, "move", {'x':friend.pos.x + 35, 'y':friend.pos.y})
        if enemy:
             self.command(friend, "attack", enemy)

What is it that I am doing wrong?

enemy = friend.findNearest(self.findEnemies())

They are finding the Nearest enemy that you can see . . . if you can only see enemies in the middle section…

Doesn’t friend.findNearest(self.findEnemies()) return the nearest enemy that my friend sees?

self.enemies is supplying the list of enemies.

friend.findNearest(friend.findEnemies())

would give the nearest enemy to the friend, that the friend can see.

I am now using friend.findNearest(friend.findEnemies()), but my top and bottom row are still getting stuck.

ok, I just ran your code and believe it or not the problem, now, is the “x+35”

For some reason when that target “x” gets into the inaccessible parts of the map they go wonky. (If I had to guess, I’d say they are trying to figure out a path to a place they can’t get to.)

Since they never get to walk more than a couple of meters, there is really no point in telling them to go so far.

x + 24, wins but does not get the bonus, try a lower number… :smile:
(well, it did for me, but may run slightly differently for different random seeds…)

Ok, now that we have that figured out, we can “pick on” :wink: your code.

You have “if not enemy” then “if enemy” those are two if statements that are complete opposites and cover all possibilities… in other words, you only need one “if”:

if not enemy:
    # move command
else:
    # attack command

– or –

if enemy:
    # attack command
else:
    # move command

with either of the if/else sets your code will do the exact same thing but will only ask one “if” whereas the current code ask both ifs everytime.

(now that they are moving correctly, if you were to switch back to “self.findEnemies()” they would just keep walking and get slaughtered, unless you have the Twilight Glasses and can see through the trees.)

1 Like

Hello there,

I can’t code in Python (I should redo the campain in Python, soon but not now !), so here is my piece of advices from JavaScript. I’m using the best glasses, so I’m seeing through walls, and your code didn’t work well at all with the RedGlasses. I’ve been struggling a bit more than usual with this level, until I understood I needed to use :

this.isPathClear( friend.pos , enemy.pos )

in order to determine wether or not every single friend was in sight of a an enemy.

I use two for loops to do so (friends and enemies). If no enemies are in sight, my troops are moving forward as a unit (as mentionned in the tips, I use a very low step (0.3) so my archer don’t run forward to their doom and they let soldier stay in front of them)

var fwPos={ "x" : friend.pos.x+0.3  ,  "y" : friend.pos.y } ;

If one enemy is in sight, then the current friend in the loop attacks it :

this.command( friend , "attack" , enemy ) ;

and if ever the life of my units drops too low (half of their maximum life), I make them run backward to safety :

var bkPos={ "x" : friend.pos.x - 4  ,  "y" : friend.pos.y } ;

Worked like a charm, with bonus.
If you still have trouble defeating this level, let me know I’ll give you a more “copy-pastable” piece of code in your inbox.

Cool, ideas. More work than necessary for this level but a nice solution.
(psst, iow: Good stuff to remember for tougher levels.)

The simple code works fine (bonus) with the right seed/“x+#” combos. My code is a lot like it, I was going for as simple as possible and still do the trick. At one point I added retreat code but, I like this one better with out it. :smile:

Oh, and a note about the “seed”, if the one you have is giving you fits . . . “submit” to get a new one. :wink:

I started translating a bit. I submit changes to this particular level, in which I took the liberty to add a warning sign in the translation (one added sentence)

Instead of

Use for-loops and findFriends.

I translated this sentence into (the french version of the following) :

Use for-loops and findFriends. Beware of Twilight Glasses as seeing through walls might confuse your troups.

Useful tip ? Should I remove it ? Modify it ? Should the english version be modified to warn about Twilight glasses ? In my experience, I think it was the problem I didn’t understand when I thought I needed isPathClear function to complete this level.

In my cluncky way of writing I wrote (badly) this code that allowed me to complete this level. Maybe there are much better ways to do it (much faster), but that’s the one I came to after 30min of thinking “what the hell” is wrong with findFriend ?

I didn’t think at the time seeing through walls was my problem. Anyway, here is my (badly written, but copy-pastable) code. Just as an example of unecessary complexity my mind went to because I couldn’t find an elegant way to make it work with my twilight glasses.

loop {
    var friends=this.findFriends();
    var enemies=this.findEnemies();

    for(iFriend=0;iFriend<friends.length;iFriend++){
        var booAttacking=0;
        var friend=friends[iFriend];
        var fwPos={"x":friend.pos.x+0.3,"y":friend.pos.y};
        var bkPos={"x":friend.pos.x-4,"y":friend.pos.y};
        var fLife=friend.health;
        var fMaxLife=0;
        if (friend.type=="archer") {
            fMaxLife=30;
        }
        else if(friend.type=="soldier"){
            fMaxLife=200;
        }
        
        for(iEnemy=0;iEnemy<enemies.length;iEnemy++){
            var enemy=enemies[iEnemy];
            if(this.isPathClear(friend.pos, enemy.pos)&&fLife>fMaxLife/2){
                this.command(friend, "attack", enemy); 
                booAttacking=1;
            }
        }
        if(!booAttacking&&fLife>fMaxLife/2){
            this.command(friend, "move", fwPos);    
        }
        if(fLife<fMaxLife/2){
            this.command(friend, "move", bkPos);   
        }
           
    }
}
loop:
    friends = self.findFriends()
    for i in range(len(friends)):
        friend = friends[i]
        enemy = friend.findNearest(friend.findEnemies())
        if enemy:
            if friend.health > friend.maxHealth/1.5:
                self.command(friend, "attack", enemy)
            else:
                self.command(friend, "move", {'x':friend.pos.x - 15, 'y':friend.pos.y})
        else:
            self.command(friend, "move", {'x':friend.pos.x + 5, 'y':friend.pos.y})

It works before submit
but when I clicked the submit button, one archer died so that I couldn`t get the bonus score.

That’s okay. Just resubmit. Every submission gives you a random seed, so what works in one might not work in another.

DITTO! IT IS SO ANNOYING!
Also, can’t people think for themselves? Why wouldn’t the troops keep marching if there’s no target? Are these troops not actually people? Hmmm…

I attempted to use your code at first, but all that happens is a pop-up that says: “Infinite Loop Detected”. What am I doing wrong?

@VincentMaths You really shouldn’t post solutions

can somebody help me whit my code

while True:
    friends = hero.findFriends()
    # Use for-loop and for each friend:
    for-loop:
        # If they see an enemy then command to attack.
        if enemy:
            self.command(friend, "attack", enemy)
        # Command to move east by small steps.
        self.command(friend, "move", enemy)

Hi stefan_grecu,

You’re using self in the code, which hasn’t been taught in CoCo for several years, hmmm?

From your code, it looks as though you haven’t quite got for-loops. Can I suggest you go back a couple of levels to Timber Guard and go over how they work. If it doesn’t make sense the first time you do it, then writing your code out a few times will help it become clear. For-loops are really useful, so it’s worth understanding them properly now!

Good luck,

Jenny

1 Like