Coding Adventure with Kaggle and Lux AI

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome everybody to a kaggle coding adventure with lux ai lux ai is a currently running kaggle competition where players face off in a 1v1 challenge to collect resources and end the game with the largest cities there are lots of details to the game and knowing them will certainly help you to win the competition but i do find with competitions like this that i've done in the past it's usually best to just try to make something basic and then build from there rather than attempting to be the best right out of the gate there are tiers of workers tiers of resources those resources have varying requirements to obtain there's a day-night cycle where in the night you need enough resources to produce light or those city tiles die and so on coding all this can represent a decent challenge alone much less competing against other people and strategies so i'll be starting off simple then slowly building out from there i don't expect anything that i come up with at least initially or even within a few hours to be competitive in any way but i do enjoy this style of competition [Music] to begin we need to acquire lux locally this is going to vary based on your operating system so check the github page and follow the instructions if you want to follow along essentially it is just merely installing node.js then installing the challenge from there we can check out the kits directory and then in here we can see there's some examples in various programming languages for coding your ai i'm interested in python so i'll click that and then in here we have this simple directory if we check out the simple directory this is a complete submission ready example that you could zip up and upload to kaggle for competition that said the bot here is way too primitive to actually compete with you just embarrass yourself so we'll start by running things locally and then tinkering from there so for me i've copied the simple directory inside here we have of main interest to us we've got the lux package in python but then mainly agent.pi and main.pi so i'll pull those over here we have main.pi essentially just runs your agent you don't really need to mess with this at all and you really shouldn't other than maybe if you change agent here or this pi file to something else and so on so then we check out agent.pie this is what contains your actual logic and strategy and all that so we'll be digging more into this very soon but first let's go ahead and run this and see what things look like so now to actually run this we're going to go back one directory since we're in the simple ai directory and in theory this is our actual agent so i'll go back one directory and just run a game of simple versus simple so i'll open up a terminal here drag that over make that slightly bigger and then run the following command and in this case it's npx run lux ai and then this is ai number one that's going to compete versus ai number two in this case it just happens to be the exact same ai and then this is the game size so we're going to do a 24 by 24 game map and we'll go ahead and run that and we should see that we wind up with a replays directory so if we double click on that we see there's some sort of json file that is the replay and if we want to look at this we can either come over to the lux viewer and view this like offline so if we want to just use it locally we could do that so we can essentially just host the viewer locally or we can use the following uh it's at 2021viz.lux-ai.org and we can upload the replay so we can run that real quick and in general so over here we have like the stats and stuff like that and then down here you can press play and you can like speed it up by pressing play but it's really annoying to like do that every single time and as time goes on you'll probably run many iterations and this is like super slow even this is slower than i would want it to be so i've personally found that when i look at replays i just click this and just kind of drag it around and if i see anything that looks interesting i'll kind of go back and watch it maybe a little slower but in general i just kind of drag this around and then you can look over here you can see city fuel you can even click on like specific units so you can click on like your worker you can click on your city tiles you can click on these resource tiles and so on [Music] the objective of this competition is to simply end the game with more city tiles than the opponent that's all there is to it of the slightly over 400 teams currently participating in the competition the bottom 125 or so at the time of my recording are all just keeping a mere single city tile like the simple bot does here so the tiny change of merely building one more city tile would put us above about 25 percent of the competition so let's go ahead and do that also while we're doing that one issue that creeps up a lot especially with coding a strategy bot like this is that code can explode and get really messy really fast because you're gonna try a strategy try another strategy you're gonna have a bunch of logic that corresponds maybe just to one strategy and and so on and things just get really messy now i'm no pillar of organization but i'm going to do some housekeeping with the bot even just the simple bot right here as i run through the existing code and we make some changes to build one more city to start the first 32 lines are probably good enough to keep as they are after this though we come across the first block of code that could easily be a function which is the creation of this list that contains the resource tile objects we're not going to save total line count in the file here by turning this into a function but instead we're looking to abstract away our code logic from the strategy logic as much as possible so as to make the strategy logic as clear as possible so for this we'll define resource tiles as get resource tiles and pass the game state width and height this function doesn't exist yet so i'll copy the code block that defined these in the first place go and make a new function called get resource tiles and then paste in this code at the end i'll return the resource tiles and there's our first bit of cleaned up logic the next chunk of code that i'll address here is the code that simply finds a resource i'll use a similar method here to just say the closest resource tile is equal to the return of a function called get close resource and pass the unit resource tiles and player object then i cut the code go to the top to find a new function called get close resource paste in the code and add the parameters continuing along in the code same thing here where there's a block of code that simply finds the closest city tile to return to with our resources i'll establish the variable to be equal to the return of a function called get close city paste in the code and realize that i never actually returned the closest resource tile in the above and previous function so add that in and then of course also a return closest city tile for that get close city function and now we've considerably simplified our actual agent function again we didn't remove code in the total file we actually added more lines here but the idea is to keep the agent function our logic or strategy as simple and easy to understand as possible for ourselves especially as we begin to add much much more logic the next thing to do is run the code make sure there are no errors and check the replay to make sure everything is acting as expected looks good to me now to beat those hundred or so competitors we really just need to build one more city tile checking the documentation to do this requires a unit with 100 units of resources and then we just call unit.build city we really just want to do this once so just build one more city tile for now and to do this we need to know how many do we actually have scrolling up in the documentation we can see that we can find this out possibly through player.cities but it's kind of unclear to me what this is to help us here i'll be bringing in logging due to how the game itself is using terminal outputs to actually play the game we can't really use prints here plus the game moves so fast that an actual log file i think would be more useful anyway i'll specify my log file and start things off by just simply logging this player.cities value then i'll run the code check the log file and it appears what we have here is indeed some sort of id for the key and then the city object as the value one thing to note immediately here is that we have both cities and city tiles adjacent city tiles are part of the same city so cities are comprised of city tiles coming back to my code i'll specify then that the cities are now player.cities.values and the city tiles which we want two of for now will be an empty list to start and then i'll iterate through all cities and then all city tiles in those cities city tiles and add those to my city tiles list finally i'll log the cities and city tiles just to make sure my logic and things are working how i expect running this i'm initially confused because log files are appended and i'm not seeing the new information because i'm scrolled up to the top thinking it'll help i add some text to differentiate these and upon seeing it doesn't help i realize my mistake and i find that um i find what i was expecting by simply scrolling down clearing the log file and running again much better that's what i wanted and everything is indeed looking as i expected one city tile and one city and now it's time to crush my opponents before iterating over units i'll set a new variable called build city to false and then i'll check to see if the list of city tiles is less than two if it is then i want to build another city tile so then we begin iterating through the workers we know we need a hundred units of resources to build a city and each worker unit holds 100 resources so if the unit's cargo space left is more than zero we need to just keep gathering else if build city is true then we'll log that we do wish to build a city but where deciding where to build is all by itself another part of the strategy so for now let's just try to build adjacent so that it stays a part of one single city i'll set a global variable called build location at the top of the script come down to the agent function and add it as a global and then begin to build the logic what we really want to do here is find an empty tile next to our current city tile so first i grab that close city tile then build a list of directional changes we're working in xy coordinates so adding 1 to the x position of the city tile checks the tile to the east of that tile and one to the y would check the tile to the south and so on for the negatives there may be times where these spots are all filled this is something we'll handle for another time so we'll iterate through those directions and check for emptiness allowing for errors and sometimes your city tile might actually be on the edge of the map so we'll check for a tile that doesn't even exist but we'd also like to see any other errors that we didn't even think about too for each tile we'll see if it has any resources any road or any existing city tile already on it if it doesn't great that's our build location and let's break out of the loop then we'll check if the unit is already at the build location if it is build the city note that you need to define the action then append it to the list of actions this full list of actions is what the game reads and acts on after building we'll set build city to false and build location back to none and continue if we don't need to find the build location and we're not yet at the build location but we have a build location then we wish to navigate to that location so we'll append that action with a unit.move to the direction of the build location unit moves are actually in north south east west or center and basically denoted as n s e w and c not in coordinates so keep that in mind so when you do a unit dot move it's actually an n s e w or c eventually we'll need to probably create our own pathing function rather than using this one since it doesn't handle for things like avoiding unit collisions and other problems so we'll need to get more into these movements later probably now i want to run everything and make sure it works and there's some error with logging this error makes no sense to me it still makes no sense to me it seems to be logging related despite using logging earlier just fine it appears to be caused somehow by it but i just i have no idea why but commenting out the logs and running appears to work as expected so rather than using logging i'll just try out a typical file i'll define its name and then go ahead and open it with a write intention purely to clear the file every time next everywhere i was logging and still want to log some info i'll instead add an open file to append option and write what i want i could also encase the whole agent function in this open so i don't need to keep calling the with open but i don't intend to be doing a ton of logging i'll probably regret this later running things again i get an error i forget the quotes in step i do a find and replace run again and of course my replace causes a new error we're using double quotes inside of double quotes run again and i see i'm not getting a second city tile checking the logs i see we're indeed hitting that error exception and logging it after some poking around i realized that after all of this in the condition where we have the build location that we wish to navigate to after we hit that else we're going to actually continue this block and hit that final if statement which then instead instructs the exact same unit to go find the closest city tile to remedy this i'll add a continue after the units move to the build location trying again things run no errors but i don't see a second city tile with either agent in the replay looking at the log file i see we wanted to build a second city we really did but then we don't what's up running it again and checking the replay we can see things actually worked this time for both agents so what actually happened here well like i said the default navigation is kind of silly anytime an agent runs over a city tile all of the resources are deposited there so what was happening was our agent tried to move to a tile that was across a city tile deposited everything then had cargo space so it went back to collect and repeated this over and over now actually if we want to build adjacent to a city tile i believe we can do that with zero resources on the worker i think the worker actually subtracts or the resources get subtracted from the adjacent city tile but that's not the logic i was intending here so we really we want something to fix this and at this point i'm starting to realize i might not be very good at this competition and how much time will be required to actually make a decent bot [Music] so the first thing i've done is copied the simple directory and called it intermediate and in here this is the agent that i'm going to continue working on to begin expanding the city we can just build another city tile but then our upkeep is higher so we want more workers too i think i want to have one worker per city tile but we cannot build another worker first since in order to build workers you need to have less workers than city tiles to start building city tiles i think we also want to start tracking workers the resources those workers are using and the city tiles that those workers deposit to initially if we're just building one big city we don't need to associate workers to that city tile but if we want to start expanding we need to at least probably associate workers to the overall city that they're depositing to but for now i'll just map to this specific city tile along with mapping workers to resources using a couple of global dictionaries next when looking for a resource we'll skip a resource if it's already a resource for a different worker later we might elect to allow for two or three or any number of workers to share a resource tile but this is something worthy of trial and error later for now i'll just assign one one per in the agent function i'll add the two global dictionaries i'll add a list that contains all workers that i can reference and iterate through and then i am checking to see if those workers exist in the unit to city dictionary if not i'll just assign them to a closed city and then i do the exact same thing for workers and resources then i already know that i'm going to want more than two city tiles so i'm going to change the build city boolean criteria to instead be a measure of the ratio of workers to city tiles again the specific number that i'm going to go with here is something that could easily be tuned fuel burn rates per city tile varies based on the city's size so it's possible that one worker unit could theoretically serve two or more city tiles or maybe 20 workers could serve 30 city tiles and so on or maybe it's better to have a worker per city tile next when iterating over units and filling cargo we'll grab the resource tile to head for from the unit resource dictionary now instead it's probably wise to confirm this cell has a resource still and if not get a new one and assign that unit to the new one if we do want to build i still am okay with the logic for the build location so i'm ready to go ahead and extract this out into its own function so now the build location will be the return of a new function called find empty tile near i'm also going to go ahead and add in checking for the diagonal tiles for response 2. this is mostly a copy and paste and could definitely be made quite a bit better with i don't know something like a for loop over the two types of directions or something like that but this will do for now i'm also going to change this alif to an if because we might as well issue a unit's navigation even if we need to define the build location first and then i'll change the final if to an l if the continues i think should stop us from landing here anyways but i'm just throwing it in just in case then rather than returning to the closest city we'll return to this unit's specified city tile if the unit doesn't have one we'll get a new one running things i see that we just need to move our resource tiles definition a bit up since we're referencing it earlier in some of the new logic another run another issue a typo fix that run again we do get another city so that is indeed what we expected checking the logs however i see that we're constantly finding a worker without a city or a resource and that's not expected i also note here that each unit object here is a new or different object in memory so that's kind of a problem because we're using the object itself as the key checking the docs though i see that units also have unique ids maybe we can use that value instead so i'm going to go ahead and change all the references of the worker to instead be worker dot id essentially and running again things look much better the next order of business for me is to address the running over of city tiles and depositing all of our cargo when we do it if we want to avoid doing this we need to navigate around the city there may be times where we also want to navigate around an enemy city or something like this and this logic could be used for that under the build city if statement we want to address the final else where we actually navigate to that build location the logic here is first to determine what is the x and y coordinate difference between our current position and the one that we want to be at then take note that movement commands for units are not actually coordinates but instead are n s e w or c for north south east west or center so i'll make note of what coordinates would translate to what directions then whichever absolute value is greater in the coordinate differences we'll just assume that's the direction that we want to start off going so then i'll check the tile one step in that direction to see if it is empty if it is great we'll go that way if not we'll go in the other direction that we need to go instead this logic could probably be improved pretty significantly and a small wall of city tiles would be enough i think to actually thwart this completely but running this i forgot to import numpy so i'll do that run again and i see that we still tied but that's because both teams built a second city there wasn't really a city tile in the way trying again i see an instance where the intermediate bot won so let's check that replay i see indeed that my unit went around the other city tile finally just to make things a bit more clear in the logs i'll add a log when the city is actually built running one more time and checking the logs things are looking pretty good here now that i've got the logic for workers to build more city tiles i need the logic to build more workers to do this i'll continue building workers until i have as many workers as city tiles i'll iterate over all city tiles and if that city tile can build a worker i'll go ahead and do that while i'm here since we need to do research to eventually get coal and uranium i'll also do research if i cannot build another worker running this i can see that i've hit a div by zero error which can really only mean that i had zero city tiles checking the replay i can see that i indeed expanded too quickly and the city did not survive the night there are kind of two issues here one obviously ideally this just wouldn't happen and two we could have easily just rebuilt new city tiles during this game if we wanted to and we wouldn't have necessarily ended with zero city tiles and we would have beat the other bot so first we'll determine if we really should build more city tiles to do this i'll figure out which city we're going to build on to and then get the fuel for that city then we can divide the total city fuel by the size of that city giving us a about average number of fuel per city tile and really we're just looking for a way to have enough fuel per city tile to make it through the night so now i can pick some number like 300 units of fuel per city and if we have more than that we can allow ourselves to build another city tile i'll log some of the information and then add an if statement to handle for if we have the fuel to build or not if we don't have the fuel i'll just sloppily copy and paste the code to go find a city to dump the resources into running things i see i've got an error about the resource assignment variable it looks like somehow in a copy and paste frenzy i left in old names or something fixing that and things are getting closer to what i want though now units are running into each other a lot and getting stuck running again i get another div by zero issue when all of my city tiles have died so what i'll do here is encase the build city boolean and try and accept and set it to true in the exception case truly expert coding and running this things are looking better but still having problems with collisions [Music] to handle for these collisions my first idea is to create another global dictionary that tracks unit positions over steps if that unit has stayed at the same coordinates for some number of steps it's stuck and we want to move it for now i propose that movement is random for each step i'll iterate through the workers and if they're already in this like worker positions dictionary i'll append the new position if not then i'll create a new key where the value is a deck with a maximum length of three essentially we'll just store the last three positions of each worker i'm going to go ahead and log this dictionary and run things to see if things are looking as i expect they sure do and i can already see workers that are definitely stuck to hopefully remedy this we'll check the last positions so long as we have two or more in this deck then we're going to check how many unique values using a set of the list of the deck if there's only one unique coordinate pair this unit must be stuck so i'll log that and then move a random choice between north south east or west running this i get a list index out of range error checking the replay i see this makes sense since the entire city died to solve for this some more expert coding with a try and accept if we hit an exception i'll just continue next i get a build location that is none as the city grows there will be many times where there's no directly surrounding tiles that we could build on i think here we could actually like loop and use some sort of range to keep checking more and more distant tiles and a further away radius instead of just one out but for now how about another try and accept i'll sort the exceptions to the logs so we can handle those later running this a few times i can see that things are looking up for me and my empire is forming at this point i'd say we're pretty close to something good enough as a first submission and a decent starting point to leave everyone on without raising the bar probably at all this will probably be a pretty average bot the last thing i'll share is a way to test hyper parameter changes to your agent we have lots of values like city fuel how many units could share a resource and even more nebulous things like maybe a new navigation or avoidance logic you probably have many ideas of how to improve things already from what you've seen here or maybe a curiosity about what might change if you tweak certain things so one option is to just simply log how many city tiles you have ended the game with so i'll just create a name and then at the very end if the observation step is 359 the very last step of the game write out how many city tiles we have we can use this to compare two agents and count wins and games or even just the average number of city tiles in general that this agent is capable of creating so here for example i'm comparing the agent code that we've built up to this point and then agent r d is with one change which is to find an empty tire radius that can be greater than one that one change made a pretty considerable impact in the average city tiles created you should also be probably paying attention to any scenarios where you ended with zero city tiles these are often just throwaway games that you could have made a tiny change to to save it there are many improvements that we could make here we could definitely clean up this code a ton like we did in the beginning just to make it easier to read and i'm sure there are even bugs in my logic we could also eke out more performance by doing things like paying attention to how close is the night so cycles are in 40 steps 30 of those are days and then 10 are nights well we could be far more expansive maybe in the first 15 days and then settle down and adhere more strictly to fuel requirements as we approach nighttime stuff like that there's so many things that we can do but i still think this is a pretty good stopping point uh and a place for people to build on if they want when you're ready to submit you just compress to a tar.gz and then you can submit your bot within about five minutes you should start seeing matches against other people after about a day my score with this agent was 656 which leaves a lot of room for improvement i also see there are over 500 teams now so there's even more competition to play with so definitely check it out if you are interested i'll also put a link to my ending code up to this point in the description so if you want to take it and start cleaning it up and adding your own logic go ahead this video is sponsored by udacity which is currently offering 75 off of all of their nano degrees if you use code centex 21. they've just recently redone the self-driving car nanodegree which i've spent some time checking out and would definitely recommend if you're interested but the discount code works on any of the nanodegrees so feel free to pick something else that piques your interest i'll put links in the description that you can use for the 75 off and thank you to udacity for supporting the content you
Info
Channel: sentdex
Views: 83,741
Rating: undefined out of 5
Keywords: python, programming
Id: 6_GXTbTL9Uc
Channel Id: undefined
Length: 27min 45sec (1665 seconds)
Published: Sun Sep 26 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.