My Python-Automated Pumpkins are Now Efficient...

Поділитися
Вставка
  • Опубліковано 3 січ 2025
  • Program and optimize a drone to automate a farm and watch it do the work for you. Collect resources to unlock better technology and become the most efficient farmer in the world. Improve your problem solving and coding skills.
    Check out The Farmer was Replaced here:
    -- store.steampow...
    Check out my Python tutorials:
    • VARIABLES, TYPES, AND ...
    #games #olexa #strategy #farming #automation #programming
    Thanks for watching!
    -- Extra Olexa Content - / @olexa2
    -- Discord: / discord
    -- Twitch: / olexastream
    -- Twitter: / olexayt
    -- Reddit: / olexa
    -- My Nexus Gamestore: www.nexus.gg/o...
    -- UA-cam: / olexayt
    -- Business Email: olexakid@gmail.com
    -- Join this channel to get access to perks:
    / @olexayt
    Music I Use:
    -- www.bensound.c...
    -- Spring by Ikson
    -- Harris Heller Streambeats Lofi Spring by Ikson | ikson.com/tell...
    Music promoted by www.free-stock...

КОМЕНТАРІ • 342

  • @Flancisco__
    @Flancisco__ 7 місяців тому +224

    Liking just to keep olenky dreaming about his pythonscoded farm

  • @sefaku3783
    @sefaku3783 7 місяців тому +143

    29:36 The fact that you were, in fact, pressing the right button before too, and didn't change anything in the code, but this time it worked (as it should've before) is PEAK coding experience. Change nothing, different results.
    This is now probably one my favorite certifefied Olexa Moments™

    • @befana666_vods
      @befana666_vods 6 місяців тому +5

      ^feel that too well me after 4h trying to figure out how to solve the easy Maze (i am a programmer but never worked with this kind of things) ok lets check the hints. implements it drone just spins in circels. continues the next 4h or so to try to figure out the problem creating a more and more complex code to end up with the same code as in the beginning but now it works. best wasted 8h of my life(it was 4am when i finally solved it sob)

    • @adrianocs4
      @adrianocs4 6 місяців тому +1

      ​@@befana666_vods Sometimes there is an explanation for this. Every once in a while the eletromagnetic efect of the sun impacting the earth can change a few bits from your HD from 1 to 0 or vice-versa. So you can tell to yourself that god is mocking your code and changing thing around.

    • @befana666_vods
      @befana666_vods 6 місяців тому +1

      @@adrianocs4 ok will do tomorrow when i have to earn my food trying to understand why one time it works and the other time it doesnt

    • @morosov4595
      @morosov4595 5 місяців тому +1

      You think nothing changed, but in this video, the drone was in a different starting position.
      As to why it didn't work, the problem was, that there was greater, or less than, but not equal zero in his code, that he fixed with else, later on. So when the drone was equally far away to the left or right, there was no case for that.

    • @hamzamotara4304
      @hamzamotara4304 4 місяці тому +1

      ​@@adrianocs4 gonna use this as my reason for failing CS.

  • @abandonment
    @abandonment 7 місяців тому +47

    can only speak for myself, but watching you explain this stuff (most of which isn't new to me so far, but is still a bit tricky) is surprisingly entertaining. and especially with it being a bit broken when you first run it and having to scramble and figure out what's wrong was probably even more fun to watch than if it had worked perfectly the first time

  • @cubondemais
    @cubondemais 7 місяців тому +69

    Refactor your code to only use a queue of coordinates and in the initialization you add every possible coordinate into the queue (also, you can use tuples and destructuring syntax for the coordinates if you prefer) and you can make the algorithm work this way:
    1. pop first item of the queue
    2. go to the coordinates of the item
    3. if it cannot be harvested, plant a pumpkin then add current coordinates to queue
    4. repeat until the queue is empty (goto line 1)
    5. harvest the giga pumpkin
    this might not be the most efficient as the first pass will use your goto function instead of simple moves, but it will be a generalized, more readable and easily modifiable algorithm. If you wish to do an efficient first pass, I suggest you extract the first pass into its own function as it has no interaction with the extra passes and will help you not mess up your code. The second pass with the efficient goto may also be a separate function.
    also, I'll add that the mazes unlock is quite interesting, they involve graph search algorithms (like bfs and dfs) and if you'd like you can also eventually use path finding algorithms (Djikstra or A*)

    • @OlexaYT
      @OlexaYT  7 місяців тому +82

      This is definitely cool and the correct approach but I’m not gonna do it haha

    • @doubledigitIQ
      @doubledigitIQ 7 місяців тому +16

      I wrote a "hold left-hand to wall" algorithm to solve the mazes, super simple algorithm, solves really fast.
      the first solution I made was to move in a random direction until it found the treasure... while inefficient, it would eventually solve any maze

    • @robcop2play
      @robcop2play 7 місяців тому

      @@doubledigitIQ Random direction go was my first attempt too... Until I saw the power consumption of sunflowers.

    • @PatientEscape38
      @PatientEscape38 7 місяців тому

      ⁠@@doubledigitIQ I downloaded this game yesterday and my first solution was a random maze “solver” too 😂

    • @AJ-ws5vy
      @AJ-ws5vy 7 місяців тому

      @@OlexaYT might be easiest to just make it check in order of closest if you're planning to optimize pumpkins further, otherwise it's about as good as you can get on a 6x6 farm

  • @williambao8272
    @williambao8272 7 місяців тому +30

    44:10 you can highlight multiple lines and shift+tab to unindent them all by 1.

    • @sirusmaj
      @sirusmaj 7 місяців тому +21

      If playing on Steam the overlay normally comes up with shift+tab. This annoyed me so much I had to change it to crtl+shift+tab.

    • @jamesfitzpatrick9607
      @jamesfitzpatrick9607 6 місяців тому +1

      ​@@sirusmajwhy did I not think of changing the key bindings

  • @travis1347
    @travis1347 7 місяців тому +54

    Can't wait for the final episode (based on the tech tree) is something like "5k likes and I mod the game to add content"

    • @satibel
      @satibel 7 місяців тому +10

      [spoilers]
      there's a fully automated option, where you can make a program that goes from the start of the game to buying all the upgrades.

    • @travis1347
      @travis1347 7 місяців тому +2

      @@satibel so maybe like... 15-20k likes? Yeah we can do that

    • @Plystire
      @Plystire 6 місяців тому

      @@travis1347 Just to automate the game, not even 1k. If you want to get competitive on leaderboard (top 30), you're likely going to be hardcoding approaches for each "section" of the game which will bloat the amount of code needed... maybe reach 1-2k.

  • @StarcraftOakley
    @StarcraftOakley 5 місяців тому +2

    Thank you so much for the "goto" code. While I now understand how it works after you explaining it, and see what the code is doing, it was far far above my rookie coding's head to even conceive of. I had ideas for something like it but it would have been really jank, so I'm glad I didn't try that.
    I did realize one could just combine some lines with an OR operator so it looks cleaner.
    I also didn't know you could call functions from other windows and keep codeblocks seperate, that's really nice!

  • @iconica9516
    @iconica9516 7 місяців тому +37

    this video is probably fueling the teacher olexa fanart (unless that already exists)

  • @mihver1
    @mihver1 7 місяців тому +63

    Was going to comment, that goto function is pretty inefficient, but realised, that the gamefield is basically a toroid which really would need thouse four clauses. :)
    As for strange behavior, i think you are trying to harvest not mature crop in some cases, which breaks it, and your code resets.
    e.g. You have only one item in temp_coords, drone goes to this one spot, plants pumpkin, then iterates once again on the same spot, checks that it is a pumpkin, but not that it is mature, harvests it, which breaks not mature pumpkin, leaving all other fields populated. Then breaks from the loop and iterates from the very begining.

    • @zeiram666
      @zeiram666 7 місяців тому +2

      That is indeed the case. There should be a wait after planting the last pumpkin to let it mature and fuse with all the other pumpkins.

    • @bekfaststealer2660
      @bekfaststealer2660 7 місяців тому

      It could be solved with just two if/else's if he used xor

    • @sirusmaj
      @sirusmaj 7 місяців тому +4

      I think he can add in "if canharvest()" the line above "harvest()" - else: do a flip() for a wait moment.

    • @SolDizZo
      @SolDizZo 7 місяців тому +2

      @@sirusmaj that's whether you want to waste time or waste loop processing - then again, I have no idea what the equivalent (total actions per second) will be

  • @terryholtzmann
    @terryholtzmann 7 місяців тому +6

    This is by far the only series of this game that explains it like you do. And you do so in a way that keeps it interesting. You gotta keep these coming!

  • @starwheels8648
    @starwheels8648 7 місяців тому +89

    Your not waiting for the last pumpkin to grow before you harvest. The pumpkins dont combine if they are not fully grown

    • @spazisspaz6074
      @spazisspaz6074 7 місяців тому +2

      I'm 9 hours late, but still proud of myself for figuring it out, lol

    • @codesymphony
      @codesymphony 7 місяців тому +12

      yeah I think he just needs can_harvest() instead of is_entity == pumpkin

  • @FranWin
    @FranWin 7 місяців тому +3

    You implemented it as promised, awesome! Loved your explanation of the goto.
    Also another fun tip, if you want nice docstrings that appear when you hover over one of your own functions, you can get that!
    Just add a comment line immediately above your def statement with whatever your docstring will be :)

  • @einsford9894
    @einsford9894 7 місяців тому +7

    These episodes have taught me more about coding than a course at uni did

  • @daniel12294
    @daniel12294 7 місяців тому +4

    Your problem with the code is that by the end of the code there might be only one or two empty spots in the grid, but you evaluate it again before they finished growing, then it says there is a pumpkin there when it had not matured yet. It harvests and tries to plant again on a filled grid. If you add the check about not 'can harvest' to also be added to the list (Or temp list) it should solve the issue. If it is not mature it will consider it as empty for the cycle and try again until it is either dead and can plant again or is mature and the whole grid is fully fused for your harvest.
    Also, thank you very much for the video. I love your content!

  • @docrun3516
    @docrun3516 7 місяців тому +3

    Just wanted to let you know, that you can use breakpoints in your code here. On the left side of a window where there is a vertical like, press on the line you want a break at. Now if you run the code normally, it will stop there and you can step through with the second button.

    • @OlexaYT
      @OlexaYT  7 місяців тому +3

      Totally forgot we had the built in debugger here hahahaha

  • @Adalast
    @Adalast 7 місяців тому +7

    To answer your question at the end, if there are only one or spots in coord_list it is too fast checking them to account for their growth time. Your if statement checking to append to the list should use the `get_entity() == None` as its check instead of checking if a pumpkin is there because a partially grown pumpkin will still resolve as true. Maybe add a `while get_entity() == Entities.Pumpkin and not can_harvest(): do_a_flip()` above the check to give the partially grown ones to either complete or die.

    • @decivex
      @decivex 7 місяців тому

      You can also do 'while not can_harvest(): pass' to wait.

  • @wesleycoder
    @wesleycoder 7 місяців тому +9

    It is more effective to plant other crops in the gaps when planting trees (also more complex)
    Depending on the needs we can always be planting trees with other crops keeping the spacing

    • @OlexaYT
      @OlexaYT  7 місяців тому +14

      I’d rather just plant bushes so we can treat it as a wood function.

    • @wesleycoder
      @wesleycoder 7 місяців тому

      ​@@OlexaYT
      Yes, totally valid, I understand the urge to modularize and isolate the functionality, I just let the urge to be fully efficient speak for a moment.
      Definitely worth to just isolate it.
      I've been watchin your vids for more than a month now.
      Just today I found out that I'm not subscribed, this should be a crime and I should go to jail for that lol
      Thanks for the content, as a software developer, this game hits just right for me :)

    • @apophys1110
      @apophys1110 7 місяців тому

      @@OlexaYT I do trees + carrots for standard use; these work well together, and it's more time-efficient overall to get all wood from trees than from a mix of trees & bushes, since trees have higher output. Eventually, the primary use for wood is upgrading carrot output anyway.

  • @DamnitDutch
    @DamnitDutch 7 місяців тому +6

    You can select your code and tab to indent the selection and shift+tab to remove the indent. massive time saver :)

    • @OlexaYT
      @OlexaYT  7 місяців тому +8

      That’s a godsend, thanks. You’ll see me not do that tomorrow, it’s because I already recorded haha

    • @DamnitDutch
      @DamnitDutch 7 місяців тому +2

      Also i think my farm is so dang fast with the sunflower power-ups it's literally not getting enough time to find missing pumpkins now with this algorithm and movement... i end up with empty lists with pumpkins missing

    • @OlexaYT
      @OlexaYT  7 місяців тому +2

      The sunflowers are crazy lol

    • @sirusmaj
      @sirusmaj 7 місяців тому

      @@OlexaYT If playing on Steam the overlay normally comes up with shift+tab. This annoyed me so much I had to change it to crtl+shift+tab in the Steam options.

  • @williamwolfe962
    @williamwolfe962 7 місяців тому +28

    "Aaaaand we're in hell" bahaha cracking me up!!

  • @pr0duct1v1ty7
    @pr0duct1v1ty7 6 місяців тому

    I loved that you left the currx/y debacle in the video I caught it immediately and it gave me flashbacks to college because me an my friends always made stupid mistakes like that and just couldn't figure it out for the life of us. But as soon as a another of us saw the code fresh they'd figure it out immediately. "Damn, I'm stupid" was the catchphrase for the group

  • @acters124
    @acters124 7 місяців тому

    Thank you for posting this video, I just bought this game and made my pumpkin farm and much more(trade management with stock refilling by switching farms before returning to the previous farm, capable of recursively switching farms, and starting from any farm such as pumpkin, sunflower or any I create separately).
    Instead of scanning for failed pumpkins(empty spots), I just make a first pass to plant, and then, on a second pass, I plant and force grow with fertilizer every empty non-harvestable spot. It will also fertilize if my drone is too fast and reaches a pumpkin before it grew, I just spam fertilizer until it is mature, then check if it is harvestable(empty spots are not harvestable!)
    This strikes a balance of speed and fertilizer usage when creating the big pumpkin. making only one pass and using fertilizer for every spot and checking for harvestable pumpkin is takes longer than the two passes I make with the second pass utilizing the fertilizer. This also means I do not use watering mechanics as it does not offer time benefits since I need to make a second pass either way.

  • @brandonmack111
    @brandonmack111 6 місяців тому

    Interesting. I did this:
    wdist = abs(y - ytarget - size) % size
    edist = abs(y - ytarget - size) % size
    if (wdist < edist):
    return West
    else:
    return East
    And the same for North/South. I got there by thinking of the spaces on the other sides like they were on extra squares off the edges (with coordinates = coords + size one one side, and coords - size on the other) and simplifying from there.
    Also, the modulus operator (%) is so that it also works for distances that *don't* wrap

  • @samuelgage3598
    @samuelgage3598 7 місяців тому +1

    Brilliant. I love it. I love trying to catch the problem before you do (I never have)

  • @BasslineBeat
    @BasslineBeat 7 місяців тому +5

    After 4 videos about this game, i learned more than in my entire school time 😂 good job

  • @apophys1110
    @apophys1110 7 місяців тому

    It's very helpful to have a custom upgraded harvest function, which waits over its square until the object can be harvested before actually harvesting (and checking first that something actually exists, so it can't get stuck). I call that on every crop, from grass to sunflowers.
    For pumpkins, my solution doesn't require a temp list. Instead, I store the length of the "holes" list in a variable in the outer loop, and in the inner loop iterate through from the back end of the list to the beginning, popping out entries as needed.
    I like doing all trades at the start of the program in bulk, to simplify and to account for the later multi-trade unlock. In this case, I buy until I have size * size * 2 seeds, to have a buffer for those that will need redoing.

  • @Alexander.Kravchenko
    @Alexander.Kravchenko 7 місяців тому

    You can significantly reduce the number of conditions needed to calculate a direction for your goto() function. Notice that you have opposite signs (like > and ) when the direction is East.
    This means we can use multiplication property to unify pairs of conditions for each direction. And you will get something like this:
    currx = get_pos_x()
    size = get_world_size()
    dir = East
    if (abs(x - currx) - size / 2) * (currx - x) < 0:
    dir = West
    while get_pos_x() != x:
    move(dir)

  • @SchPal
    @SchPal 7 місяців тому +3

    LESSGOOO I Love this game. Helping with the 1000 again!

  • @TUC12341
    @TUC12341 3 місяці тому

    So I’m kinda happy with myself, as I was watching and finally understood the code for “goto “ I realized I did something a lot like it except I had it set to always go to 0,0 so I didn’t need to mess with absolutes but I did the same operations where taking half the world size and go east or west to be efficient. Makes me happy that I ended up somewhat like you

  • @OhioStateOfficialsOffice
    @OhioStateOfficialsOffice 7 місяців тому

    Not only did I get the game after watching your videos but you sir have earned my like, comment, and subscription. Great content man!

  • @jrpower12
    @jrpower12 7 місяців тому

    Got the game to give this a shot here is what I came up with, I first divide the movement function into a "linear_movement" function, this allows me to isolate the movement into one direction and then evaluate them as it was just a row, removing some duplicated logic there. Now the next part is the hard part, determining which direction to move, for that I isolated it to just getting the direction using similar logic you had then broken out in a function to make it so I was able to debug when needed easier. and then finally just having the movement while loop checking if we are there yet.
    I am sure there is an easier way with some more time, but in my testing, I didn't have any weird movement.
    def move_to(x, y):
    wrap_linear_move(get_pos_x, x, East, West)
    wrap_linear_move(get_pos_y, y, North, South)
    return
    def wrap_linear_move(position_func, destination, PositiveDirection, NegativeDirection):
    direction = get_direction(position_func, destination, PositiveDirection, NegativeDirection)
    while position_func() != destination:
    move(direction)
    def get_direction(position_func, destination, PositiveDirection, NegativeDirection):
    halfDist = (get_world_size()/2)
    DeltaMovement = (position_func() - destination)
    if halfDist < DeltaMovement:
    if DeltaMovement < 0:
    direction = NegativeDirection
    else:
    direction = PositiveDirection
    else:
    if DeltaMovement > 0:
    direction = PositiveDirection
    else:
    direction = NegativeDirection
    return direction

  • @Kunteki
    @Kunteki 7 місяців тому +1

    ok i like how you think, but here are a fix and an optimization path for you, for the pumpkins
    1. move the "coord_list = []" above the first set of for loops
    2. remove the if/else structure in the first set of for loops keeping the while loop for seeds intact (remember to correct the indentation),
    and of course keeping the "water_me()" and "plant()" functions as well ^^
    3. before the move(south) in the first set of for loops, add the "coord_list.append()" from the second loop
    4. remove the entire second set of for loops
    5. the fix: i beleve the "break" at the end only exits the if statement and not the while loop like it's supposed to, but simply indenting it back one would break the while loop before it is done looping through the missing pumpkin patches. so i would change the while loop, so that a variable set to true is used, and insted of a break the ending if statement ends with setting that variable to false
    hope this helps ^^, and have a nice day :)

  • @paul-is-me
    @paul-is-me 7 місяців тому +7

    Okay the problems you had:
    You at the end of the big pumpkin check you dont check if the last pumkin is fully grown
    That means that you harverst it befor it is an adult and can form the mega pumpkin, out of the view of the code compliting your harvest what means that the code trys to replant the field

    • @paul-is-me
      @paul-is-me 7 місяців тому +3

      I also think that you could improve your goto() by having one statement be =< so that you don't need the last else

    • @paul-is-me
      @paul-is-me 7 місяців тому +3

      But ❤ the videos and ty for showing me the came
      For years, I had a 12h python tutorial in my "watch later" folder on UA-cam and did never had the willpower to get into it, but thanks to you and the game I finally have no reason to procrastinate getting into coding❤

    • @paul-is-me
      @paul-is-me 7 місяців тому

      I am sorry incase you can't read sth or want me to clarify. English is not my first language so if you need any clarification hit me up and I will gladly try my best to explain myself better 😅

  • @khaledahmed9136
    @khaledahmed9136 7 місяців тому +1

    An easier way to remember coordinates is to have all your farm in a list where index 0 is 0,0, index 1 is 0,1 etc.
    From there, you can find the x and y using: x = index // world_size and y = index%world size. this is what I did for sunflowers
    You can have the list be 0 for non pumpkins and 1 for pumpkins.

    • @OlexaYT
      @OlexaYT  7 місяців тому +2

      I think I’m… not a fan of that lol. I’ll show y’all how I do sunflowers tomorrow

    • @khaledahmed9136
      @khaledahmed9136 7 місяців тому

      ​@@OlexaYT Fair enough. I'm excited to see a different approach from the one I did.

  • @ElectricalInsanity
    @ElectricalInsanity 7 місяців тому +9

    Can't wait to see your solution for sunflowers, it should be fun!

    • @OlexaYT
      @OlexaYT  7 місяців тому +20

      Not wanting to toot my own horn, but sunflowers is our best and most successful one yet. Can’t wait to show yall

    • @Mikrowelliger
      @Mikrowelliger 7 місяців тому +7

      ​@@OlexaYTSo you already recorded the next episode without this one reaching 1k likes? You spoil us!

    • @OlexaYT
      @OlexaYT  7 місяців тому +14

      You guys are animals, you’ll reach it

    • @jakeoshay
      @jakeoshay 7 місяців тому +5

      @@OlexaYT turns out this was a series after all 😈

    • @OlexaYT
      @OlexaYT  7 місяців тому +6

      I’m really just Python automated farming likes at this point. It’d be really cool to just have y’all like all my videos :) it helps me out a lot, so this is a good incentive

  • @KarateDuckFull
    @KarateDuckFull 7 місяців тому +3

    I really hope everyone keeps liking these videos, i love this series (not series) so much

  • @youenntrehorel9808
    @youenntrehorel9808 7 місяців тому

    When you have your list of coords you only take the first coord in the list, but you take them in the order of where you plant them, when you use your goto(x,y) it takes the next spot in the order of plots but not the closer to the spot you are in wich is not using your goto as efficiently as you made it. It will only go to the next plot wich could be just under the plot that you are on but it could be on the other side of the whole field and you could have an empty plot just before the plot you are on wich will be the closest but with the list of coords it will goto the plot on the other side of the field and not to the closest wich is not the most efficient. Don’t know if i’m explaining it good but i think you can check the coord list and goto the empty plot wich will be the closest and not just the next in the list

  • @roidrole882
    @roidrole882 7 місяців тому

    56:27 it goes back once the pumpkin is fully grown because the drone doesn’t know that it has been grown. It has to scan that there is a pumpkin at least once, and that is the once

  • @yohflyer173
    @yohflyer173 7 місяців тому +1

    Juuuust finished the last video, hell yeah keep making these plzzzz

  • @jayglenn837
    @jayglenn837 7 місяців тому

    Always happy to see more of this series!!

  • @andrewsanders17
    @andrewsanders17 7 місяців тому +9

    With all this automation and power we have lost something great. We lost the backflips.

  • @erictrinque6513
    @erictrinque6513 7 місяців тому +1

    liking and commenting for the inevitable mental breakdown over digital pumpkins and optimization nightmares.

  • @unrealraven
    @unrealraven 7 місяців тому +1

    I don’t even know why I find this so fascinating. I have no clue how to code and no desire to learn how.
    But take my like and make the next one

  • @sttiter
    @sttiter 7 місяців тому

    My first liked video on this platform from a creator, really good content, love your stuff

  • @JustBIue
    @JustBIue 7 місяців тому +1

    You could refactor your goto by re-ordering the if statement order and then collapsing two of the if else into the else statement as it runs identical while statements.

  • @mb-ost
    @mb-ost 7 місяців тому

    Maaan, I found this game yesterday, right before going to bed, woke up this morning, and began playing it throughout the day (mostly cuz I was getting a bit tilted from work), ended up spending like 30 mins to make something similar to the motion system U did, similar idea, looking completely different, bit shorter, not that it made it easier to read haha.
    Then after that, I just leaned into the motion system and made a self-balancing system that harvests everything by using the companion bonuses and does a full set of pumpkins occasionally.
    Currently, the balancing is 1:1 for everything, but tomorrow 100% gonna add a balancer based on proportions between a set of variables I can adjust, proportions are great to just leave the app running while doing something else.
    Btw, I work with data integration, so 99% SQL automation, but Python is soooo great to work with, it even had me staying late tonight to mess around with it a bit more, a breath of fresh air coming from cursed 15+ years old procedures that no one knows how they still work.

  • @roidrole882
    @roidrole882 7 місяців тому +8

    For the goto function, have you considered modular arthmetic? That seems to be how moving x and y works. With a world size of 6, your distance is (current x - target x) mod worldsize - worldsize/2 is how much you move left/right

    • @nuggetoftruth865
      @nuggetoftruth865 7 місяців тому +1

      That’s almost correct, but that means a distance of 4 would become moving 1 instead of moving -2. To counterbalance, you’ll want to add worldsize/2 before the modulus. It’s like moving 3 to the right, then not moving (cause moving 6 is the same as 0), and then moving 3 back to the left. Position doesn’t change.

    • @roidrole882
      @roidrole882 7 місяців тому +1

      @@nuggetoftruth865 ah, circled back to the video, I see. Thank you, stranger!

    • @apophys1110
      @apophys1110 7 місяців тому +2

      I tried it out, and modular arithmetic does dramatically simplify the code:
      a = (currx - x) % size
      b = (x - currx) % size
      if a

  • @Dyanosis
    @Dyanosis 6 місяців тому +1

    Your goto(...) could be way more efficient. Something like so:
    def goto(x, y):
    # We're left of the target location
    while get_pos_x() < x:
    move(East)
    # We're right of the target location
    while get_pos_x() > x:
    move(West)
    # We're below the target location
    while get_pos_y() < y:
    move(North)
    # We're above the target location
    while get_pos_y() > y:
    move(South)
    No need to be checking world side and doing weird abs(...) checks just to figure out which direction to move. The difficult part of this is that we don't have a confirm for what the directions mean (North/South/East/West). So it's not like we can say "move((-1, 0))" and that'll move us West 1 tile. If we could somehow correlate the different in position with directions, it'd be even easier to write since we could just calculate the different and then tell the drone to follow that path.

  • @philipp9633
    @philipp9633 7 місяців тому

    If you want to move an indentation back, you can mark what you want to move and press shift tab.
    Took me wayy to long to figure out when i started programming

  • @adamrowell1588
    @adamrowell1588 7 місяців тому

    You can cut the number of if's in half by testing (abs(currx - x) > (size / 2)) == (currx > x), rather than having and. When they are the same you move east, when they are different you move west, and because you only have one if, you tie-break being equidistant, rather than fail to move or have the final else

  • @dranyth
    @dranyth 7 місяців тому +7

    So for my GoTo function, I went with calculating how many moves in each direction need to be made, then just plugged the positive or negative resulting value into a helper function that runs a loop to move that many times depending on if the original value was positive or negative to determine direction. I ended up with this:
    def move_drone(amount, negative_dir, positive_dir):
    if amount == 0:
    return
    for i in range(abs(amount)):
    if amount < 0:
    move(negative_dir)
    else:
    move(positive_dir)
    def move_x(amount):
    move_drone(amount, West, East)
    def move_y(amount):
    move_drone(amount, South, North)
    def calc_move_amount(half_size, delta, abs_delta, sign):
    if abs_delta > half_size:
    return (get_world_size() - abs_delta) * sign
    else:
    return delta
    def goto(dest_x, dest_y):
    delta_x = dest_x - get_pos_x()
    delta_y = dest_y - get_pos_y()
    abs_delta_x = abs(delta_x)
    abs_delta_y = abs(delta_y)
    flipped_sign_x = (delta_x / abs_delta_x) * -1
    flipped_sign_y = (delta_y / abs_delta_y) * -1
    half_world_size = get_world_size() // 2
    move_x(calc_move_amount(half_world_size, delta_x, abs_delta_x, flipped_sign_x))
    move_y(calc_move_amount(half_world_size, delta_y, abs_delta_y, flipped_sign_y))
    I think it turned out fairly compact, though there might be some Python specific tricks that could combine a few things. This is my first time writing Python code, I'm usually more familiar with C style languages, C#, Javascript, etc.

    • @decivex
      @decivex 7 місяців тому

      You could calculate delta x and y using '(dest_x - get_pos_x() + half_world_size) % get_world_size() - half_world_size' I used that in a function that calculates the wrapping offset between two coordinate tuples for my goto.

    • @poendie835
      @poendie835 6 місяців тому

      I don't own the game, so my code won't work directly, however I saw that many of the different starting conditions result in the same outcome.
      def goto(coord: list[int]):
      directionList = [["North", "South"], ["East", "West"]]
      for coordId, dest in enumerate(coord):
      curr = currCoords[coordId]
      direction = directionList[coordId][((dest-curr >= 0) ^ (abs(dest-curr) >= mapSize[coordId]/2))]
      while currCoords[coordId] != dest: move(direction)
      This uses an xor to filter out those extra steps and make it more compact.
      This doesn't automatically update the new positions, so replacing "currCoords[coordId]" with "[get_pos_y, get_pos_x][coordId]()" might be usefull.
      This code was made for an asymmetrical n-dimensional map, so "mapSize[coordId]" can be replaced with "get_world_size()".
      edit: The ingame version would look something like this.
      def goto(coord):
      directionList = [["South", "North"], ["East", "West"]]
      for coordId, dest in enumerate(coord):
      curr = [get_pos_y, get_pos_x][coordId]()
      direction = directionList[coordId][((dest-curr >= 0) ^ (abs(dest-curr) >= get_world_size()/2))]
      while [get_pos_y, get_pos_x][coordId]() != dest: move(direction)
      edit2: switched "South" and "North" to compensate for flipped board in game.

  • @NoonKnite
    @NoonKnite 7 місяців тому

    i like watching the your debugging process. i think it's helpful to see how to debug code. it's a large part of programming. remember "code does what it's told to do, seldom what you want it to do".
    have you thought about debugging with breakpoints? also when the code is paused, just hover the mouse over a variable to see it's value.
    great videos, keep 'em coming.

    • @OlexaYT
      @OlexaYT  7 місяців тому +2

      I kinda forgot there was a built in debugger in this haha

  • @Klero6869
    @Klero6869 7 місяців тому

    I started to learn coding (mainly in C++). And I am not that far into it, but seeing a list with different types of data was deeply unsettling to me. Love the videos!

    • @russianyoutube
      @russianyoutube 6 місяців тому +1

      In most oop langs you can cast to object and store an object list, but please just don't

    • @davez5201
      @davez5201 4 місяці тому

      @@russianyoutube Is it generally not good to use objects that way?

    • @russianyoutube
      @russianyoutube 4 місяці тому

      @@davez5201 depends on your usecase

  • @rokonacdc
    @rokonacdc 7 місяців тому

    I was waiting until I played the game first to come look at your videos of it and I'm so pleased that I've never touched Python before this game and I'm much happier with my pumpkin harvesting than you seem to be lol
    This is my code for pumpkins:
    def pumpkin_cycle():
    pumpkin_size = 0
    reset_position()
    while True:
    for i in range(get_world_size()):
    for j in range(get_world_size()):
    if get_entity_type() != None:
    pumpkin_size += 1
    else:
    plant(harvest_crop)
    move(direction)
    move(East)
    if pumpkin_size == get_world_size() ** 2:
    do_a_flip()
    harvest()
    else:
    reset_position()
    pumpkin_size = 0

  • @MindCaged
    @MindCaged 7 місяців тому

    Wow, you came up with pretty much the same solution I did, which I guess makes sense since it seems somewhat obvious that moving over and checking pumpkins that have already fully grown is wasting time when you only need to check the pumpkins you've planted recently.

  • @trrt0048
    @trrt0048 7 місяців тому +3

    There'a a quality of life to organize the various functions (files I guess), If u drag one on top of the name of another one they get stacked.

  • @aawnu
    @aawnu 4 місяці тому

    The way I solved "goto" is basically just calculating if I need to go further than half the map, then go the opposide way.
    I also added safe offsets, because going outside the map goes to the opposide side, so negative values calculates from opposide border, eg -1 is either max X or Y cord. Useful if you plant something and just want to go to last tile and wait for it to be fully grown like sunflowers.
    Just for comparison, my "goto(x,y)" function is this:
    ```
    def XY():
    return get_pos_x(), get_pos_y()
    def goto(x=None,y=None):
    size = get_world_size()
    if x < 0:
    x = size + (x % -size)
    x = x % size
    if y < 0:
    y = size + (y % -size)
    y = y % size
    atX, atY = XY()
    goX, goY = East, North
    if x != None and x != atX:
    if x < atX and atX - x < size / 2 or x > atX and x - atX > size / 2:
    goX = West
    while get_pos_x() != x:
    move(goX)
    if y != None and y != atY:
    if y < atY and atY - y < size / 2 or y > atY and y - atY > size / 2:
    goY = South
    while get_pos_y() != y:
    move(goY)
    ```

  • @brandonmack111
    @brandonmack111 6 місяців тому

    Watching you try to figure out why your drone keeps going when you didn't update your current x variable was great.

  • @hamzamotara4304
    @hamzamotara4304 4 місяці тому

    Saying "is about to work perfectly", then it failing, failing some more, and failing a bit extra, then working is such a programming moment.

  • @frisbe3803
    @frisbe3803 7 місяців тому

    This game is so fun
    Love your vids They always give me new ideas

  • @novice_gamer809
    @novice_gamer809 7 місяців тому

    I really want to see how you will handle the sunflowers. I'm just glad I came up with a working solution for them.

  • @charonwave
    @charonwave 7 місяців тому

    Culture shock cause we learnt and used absolute value since 5th grade. Love this series

  • @Noelwiz
    @Noelwiz 7 місяців тому +1

    Love this series

  • @MrNizam1
    @MrNizam1 5 місяців тому

    26:13 I was yelling to my screen "You are not updating the value!!" I've been there too 😢😂

  • @davidkilmer
    @davidkilmer 7 місяців тому

    I thought of a simple algorithm for goto with fewer "if" conditions that I thought you might enjoy (apologize if it already appears in the comments - I didn't see it). I'll just do the X movement.
    You have ww (the world width, 6), sx (starting x position) and ex (ending x position). You'd calculate (ex - sx) and (ex - sx) - ww and take the one where the absolute value is smaller. If that answer was negative, move that many spaces West, and if it was positive, move that many spaces East. So for ww=6, sx=1, ex=5 you'd get (ex -sx) = 4 and (ex-sx)-ww = -2. |-2| is the smaller, so you'd move 2 spaces West. For ww=6, sx=5, ex=1 you'd get (ex-sx) = -4 and (ex-sx)-ww = 2. |2| is the smaller, so you'd move two spaces East.

  • @samuelgage3598
    @samuelgage3598 7 місяців тому

    The final pumpkin harvest reveal was so incredible

  • @ruudcools2866
    @ruudcools2866 7 місяців тому

    amazing coverage!

  • @FlashTheMusik
    @FlashTheMusik 6 місяців тому

    Here is an algorithm that does this in linear time (O(n)) if you want. (Don't read this if you want to try that yourself first).
    If someone has a more efficient algorithm for that I'd love to hear it!
    You can separate the problem into two stages.
    First during the initial planting stage you plant on every tile that needs planting and build up a stack of positions that don't have harvestable pumpkins.
    Next is the filling stage where you pop an item from the stack and check the position for a harvestable pumpkin, if there is no pumpkin, plant one and add the position to the bottom of your stack. If there is a pumpkin that is harvestable continue.
    Once your stack is empty it means that all positions have a harvestable pumpkin and you can harvest, and restart.

  • @DuchessEvie
    @DuchessEvie 7 місяців тому +2

    I’m doing my part!

  • @MegaKnoedl
    @MegaKnoedl 6 місяців тому

    Have you considered just doing incremental steps in the goto function?
    The drone just moves while its not at the target, und just does one step to the target each iteration, it looks if its, above, below, left or right of the target, and then moves in the corresponding direction.
    def goto(t_x,t_y):
    x = get_pos_x()
    y = get_pos_y()
    while x != t_x and y != t_y:
    x = get_pos_x()
    y = get_pos_y()
    if x < t_x: #drone left of target
    move(East)
    elif x > t_x: #drone right of target
    move(West)
    elif y < t_y: #drone below target
    move(North)
    elif y > t_y: #droen above
    move(South)
    To further increase efficiency you could calculate dx, and dy and then move multiple times in one direction instead of repeating the process.

  • @lonking1990
    @lonking1990 3 місяці тому

    a bit too late for commenting, but I think the goto function could get way easier if you work using the vector from origin to destiny to choose direction, and if modulus is greater than half the diagonal of the total field, reverse the direction based on the angle of the vector is facing: towards north or south, only Y axis, and towards east or west, only X axis. If facing a diagonal (NE, SE, NW or SW) both of them

  • @Repsack2
    @Repsack2 7 місяців тому

    Me seeing olexa pull up paint and drawing a data table: Leans forward and pays Extra attention

  • @fightheader
    @fightheader 7 місяців тому

    concerning the goto function.
    I'd make variables for both cases.
    wrap_around = abs(curry-y) < size/2
    move_up = ((curry-y) < 0
    If they are both equal move(North) else move(South)
    Same for x but different.

  • @Kasperbjerby
    @Kasperbjerby 7 місяців тому

    Gotta say, with the codeing shown in the first videos, i am impressed with the go to function :p Guess you are better at it when you get to have some time to plan and not on the spot xD

    • @OlexaYT
      @OlexaYT  7 місяців тому

      Crazy that somebody who does something for a living is pretty okay it

  • @roarkesponhaltz4811
    @roarkesponhaltz4811 7 місяців тому

    Can’t watch yet, but popped in to drop a like. Gotta get that next episode out asap ❤

  • @echirdo
    @echirdo 7 місяців тому

    I got this to work with the position thing you got me inspired to try it myself and it looks awesome:
    def goto(x,y):
    start_x = get_pos_x()
    start_y = get_pos_y()
    world_size = get_world_size()
    if abs(start_x-x) < world_size/2:
    for i in range(abs(start_x-x)):
    if start_x-x < 0:
    move(East)
    else:
    move(West)
    else:
    while (x != get_pos_x()):
    if start_x-x < 0:
    move(West)
    else:
    move(East)

    if abs(start_y-y) < world_size/2:
    for j in range(abs(start_y-y)):
    if start_y-y < 0:
    move(North)
    else:
    move(South)
    else:
    while (y != get_pos_y()):
    if start_y-y < 0:
    move(South)
    else:
    move(North)

  • @Lobituki
    @Lobituki 3 місяці тому

    i never thought i'd get programming lessons on an automation game
    i require more

  • @MrGedem
    @MrGedem 7 місяців тому

    There is another way to solve problem of "way" == "half of world size". You should use >= and and < and get rid of "else". Than you can tune it so drone will prefer to stay inside farm. This looks more beautiful in situations like you have to go from 0,0 to 3,3 and back to 0,0 (on farm size 6).
    Also, I believe, ((currx - x) < 0) is slower than (currx < x) and it is doing same thing.

  • @hazir7618
    @hazir7618 7 місяців тому

    my approach for goto function was entirely different.
    i based mine on the understanding that every point on the board is equal that same point + world_size.
    for a world size 6: (0,0) === (6,6) === (0,6) === (6,0)
    using this assumption we can calculate a simple diff from point A to B, from point A to B+world_size and from point A+world_size to B
    the absolute min between those three is the shortest path and the positivity of the difference determines if we must invert our direction laterally\horizontally
    code:
    def short_direction(target, position):
    direction = position - target
    inverted_p = position + get_world_size() - target
    inverted_t = position - (target + get_world_size())
    min = direction
    if abs(min) > abs(inverted_p):
    min = inverted_p
    if abs(min) > abs(inverted_t):
    min = inverted_t
    return min
    def move_or_invert_move(direction, inverted):
    if direction == East:
    if inverted:
    direction = West
    elif direction == West:
    if inverted:
    direction = East
    if direction == North:
    if inverted:
    direction = South
    elif direction == South:
    if inverted:
    direction = North
    move(direction)
    def goto(target_x, target_y):
    short_x = short_direction(target_x, get_pos_x())
    short_y = short_direction(target_y, get_pos_y())
    for i in range(0, abs(short_x)):
    move_or_invert_move(West, short_x < 0)
    for i in range(0, abs(short_y)):
    move_or_invert_move(South, short_y < 0)

  • @SeigneurDMorts
    @SeigneurDMorts 7 місяців тому +1

    @45:40 selection then tab or shift + tab is a life changer

  • @steveheffner
    @steveheffner 7 місяців тому +2

    Thanks for your video. I yoinked your goto code.. still going to write my own nightmare fuel code for pumpkins using the updated goto and a list. Probably will play with tuples also. Funny thing is after I saw the code for goto I went AAAH yea I understand now. Funny thing is it is 200 cycles (whatever that means in real world time) per move of the drone. So saving a few moves saves time, but really would we even notice?
    Oh and thank you for doing these videos. Been fun game to practice/relearn what I forgot over the years for coding.
    Peace

  • @whyme6742
    @whyme6742 7 місяців тому +1

    it does a full scan because you are too fast. you only check for pumpkin, but not if its fully grown -> the drone tries to harvest the last pumpkin that is still growing. The scanning is planting for the next round

  • @valseedian
    @valseedian 7 місяців тому

    27:00
    I'm dying inside.
    bright side. I'm now going to buy this. been programming for 20 years. kinda hated python when I gave it a whirl more than a decade ago. this has maybe changed my mind

  • @billy65bob
    @billy65bob 7 місяців тому +2

    I think I would've approached the move something like:
    while x != curr_x:
    if abs(curr_x - x) > (curr_x+world_size) - x:
    move(West)
    else:
    move(East)
    No idea if that's correct though... Wrapping math hurts my head...

    • @andreabiaggi8643
      @andreabiaggi8643 7 місяців тому

      I've just tried and it only moves east

    • @billy65bob
      @billy65bob 7 місяців тому +1

      @@andreabiaggi8643 I had a proper go at solving it, this was my final solution:
      def MoveTo(x, y):
      def domove(c, posFun, posMove, negMove):
      cur = posFun()
      if c == cur:
      return
      d2 = c - cur # no wrap
      d1 = d2 - get_world_size() #left/lower wrap
      d3 = d2 + get_world_size() #right/upper wrap
      moves = 0
      if abs(d1) < abs(d2):
      moves = d1
      elif abs(d2) < abs(d3):
      moves = d2
      else:
      moves = d3
      dir = posMove
      if moves < 0:
      dir = negMove
      moves = -moves
      while moves:
      moves -= 1
      if not move(dir):
      return
      domove(x % get_world_size(), get_pos_x, East, West)
      domove(y % get_world_size(), get_pos_y, North, South)

  • @Adalast
    @Adalast 7 місяців тому +4

    Whenever I have to do these sorts of cases I use something binary addition with the boolean statements:
    while currx != x:
    switch_x = (abs(currx - x) > size/2) + 2*((currx - x) > 0)
    if switch_x in [0,3]:
    move(East)
    elif switch_x in [1,2]:
    move(West)
    currx = get_pos_x()

    • @nuggetoftruth865
      @nuggetoftruth865 7 місяців тому +2

      That’s one of the places I tend to go as well. Personally though, I’m a big math guy, so I first try to see if I can transform the input space into the output space via pure math. Removing if statements is satisfying haha
      dir = [East, West, South, North]
      dist_x = (target_x - current_x + gridsize/2) % gridsize - gridsize/2
      dist_y = (target_y - current_y + gridsize/2) % gridsize - gridsize/2
      for i in range(abs(dist_x):
      move(dir[min(max(dist_x, 0), 1)])
      for i in range(abs(dist_y):
      move(dir[min(max(dist_y, 0), 1) + 2])

  • @eriqthompson757
    @eriqthompson757 7 місяців тому +1

    Do be enjoying these

  • @Galapagon191
    @Galapagon191 7 місяців тому +1

    25:42 It's pretty good
    26:05 it immediately Implodes

  • @mean4276
    @mean4276 7 місяців тому

    if you have xor, you could do this use one of the statements in the video, if it is true with xor, move the opposite way as the statement said in the video and if the xor is false, move the same way.

  • @josephmellen7052
    @josephmellen7052 7 місяців тому

    Just finished implementing this in my game yesterday

  • @blismatic
    @blismatic 7 місяців тому +1

    Your goto() function can take advantage of the min() function you unlocked to cut down on all the if-elif statements.
    def goto(x, y):
    CURRX = get_pos_x()
    CURRY = get_pos_y()
    SIZE = get_world_size()
    delta_x = abs(CURRX - x)
    x_steps = min(delta_x, SIZE - delta_x)
    x_direction = "EAST" # Assume you will move to the right
    if (delta_x >= SIZE / 2):
    x_direction = "WEST" # Move to the left instead
    delta_y = abs(CURRY - y)
    y_steps = min(delta_y, SIZE - delta_y)
    y_direction = "NORTH" # Assume you will move up
    if (delta_y >= SIZE / 2):
    y_direction = "SOUTH" # Move down instead

    # Actually move the drone
    for x in range(x_steps):
    if x_direction = "EAST":
    move(East)
    else:
    move(West)
    for y in range(y_steps):
    if y_direction = "NORTH":
    move(North)
    else:
    move(South)
    Love this series btw, just wanted to give a slight suggestion ❤

  • @squarebie
    @squarebie 7 місяців тому +2

    I look forward to mazes. :)

  • @khaledahmed9136
    @khaledahmed9136 7 місяців тому +1

    took me over an hour to do something similar, ended up just using 2 while loops for east and north and call it a day.

    • @OlexaYT
      @OlexaYT  7 місяців тому +1

      Totally fair!

  • @jayjchapman
    @jayjchapman 7 місяців тому

    This is where I start to get confused.
    Edit: the live debugging helped me understand it

  • @oliveguardian7757
    @oliveguardian7757 7 місяців тому

    Really liking this little game

  • @ARENVS
    @ARENVS 7 місяців тому

    I know this is terrible programming, but you don't really need temp_coord. If you append to coord_list directly, the for loop continues, since you keep adding stuff to it, until you don't add it anymore.
    For the move function, you can calculate how many times you have to move east or west, and use that instead of the while condition.
    Loving the series

    • @OlexaYT
      @OlexaYT  7 місяців тому +2

      I’ve been burned mannnnnny times in the past by removing data from a list while iterating through it so as a safe measure I like to make sure I create a temp list that I can use

  • @TheTymolc
    @TheTymolc 7 місяців тому +1

    Classic Heisenbug that cannot be observed when debugging, because of timings :D

  • @lukamiler5824
    @lukamiler5824 4 місяці тому

    Man refuses to unlock Fertilizer and makes spaghetti code as a result: The Movie

  • @cassandrakimmel9600
    @cassandrakimmel9600 7 місяців тому

    this feels like one of my teachers classes and i love it lol

  • @linux_steely
    @linux_steely 7 місяців тому +3

    I wanted to try making the wrapping goto function myself. Had fun and made it so abs() wasn't needed.
    # # don't have dict yet
    # swap_dir = {
    # West: East,
    # East: West,
    # North: South,
    # South: North
    # }
    # # are the directions just numbers? 0-3
    # swap_dir = [0,0,0,0]
    # swap_dir[West] = East
    # swap_dir[East] = West
    # swap_dir[North] = South
    # swap_dir[South] = North
    def swap_dir(direction):
    if direction == West:
    return(East)
    elif direction == East:
    return(West)
    elif direction == North:
    return(South)
    elif direction == South:
    return(North)
    def move_dir(direction, amount=1):
    # check for negative amount
    if amount < 0:
    d = swap_dir(direction)
    a = amount * -1
    else:
    d = direction
    a = amount
    # if faster to loop around
    if a > get_world_size()/2:
    d = swap_dir(d)
    a -= get_world_size()/2
    else:
    d = direction
    a = amount
    # actualy move now
    for x in range(a):
    move(d)
    def goto(x, y):
    move_dir(West, get_pos_x() - x)
    move_dir(South, get_pos_y() - y) # y=0 is at the bottom

  • @Kraus-
    @Kraus- 7 місяців тому +4

    Olexa keeping at 1000 because he wants to continue just as much as we do lmao. The issue is your drone is too fast and detects a growing pumpkin which triggers the harvest and reset.

  • @3DPDK
    @3DPDK 6 місяців тому

    Instead of rescanning the entire field over and over:
    1. plant the entire field once
    2. move on to next code block or call a function to fill in the missing pumpkins
    3 to fill in, scan until you encounter a blank square
    4. add water, plant new pumpkin, and do a flip (1 second delay) or print something (1 second delay) or both (2 second delay); pumpkin will grow in 1 second if square is watered.
    5. rescan the immediate square. If still empty, repeat step 4
    The drone, because of the delay, will not move on until the square has a fully grown pumpkin. This will fill in all the empty squares, one at a time, and returns (or ends the loop) when the last square of the grid scans as occupied or harvestable. This procedure only navigates the grid once, bypassing the final redundant full grid scan.
    6 when the function returns or the fill code ends, perform a harvest and loop back to step 1
    You could fertilize the square to grow the pumpkin immediately so you don't need to delay, but fertilizing does not affect the odds of death. If the grid has many missing pumpkins, the cost of fertilizer may not justify using it on pumpkins.